Imgui: Change the default font

Created on 16 Apr 2017  路  18Comments  路  Source: ocornut/imgui

Hello, it is not really an issue. I am just trying the change the default font. But I dont know how to do it. Here is my code:

/* I am using sfml */
sf::RenderWindow window(sf::VideoMode(640, 480), "");
window.setVerticalSyncEnabled(true);
ImGui::SFML::Init(window);

ImGuiIO& io = ImGui::GetIO();
ImFont* pFont = io.Fonts->AddFontFromFileTTF("sansation.ttf", 10.0f);

unsigned char * pixels; 
int width, height, bytes_per_pixels;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixels);
GLuint id = loadTexture(pixels, width, height, 4);
io.Fonts->SetTexID((void*)id);

ImGui::PushFont(pFont);

The problem is just at PushFont...

void ImGui::PushFont(ImFont* font)
{
ImGuiContext& g = *GImGui;
if (!font)
font = g.IO.Fonts->Fonts[0];
SetCurrentFont(font);
g.FontStack.push_back(font);
g.CurrentWindow->DrawList->PushTextureID(font->ContainerAtlas->TexID);
}

And this is the error:

Exception thrown: read access violation.
g.CurrentWindow was nullptr.

I guess I am doing something wrong... do you know what is my error? Or do you have
a sample code that works?

Thanks in advance.
Rixthor

fontext

Most helpful comment

Hello I had this issue as well the solution when using ImGui/SFML is to call ImGui::SFML::UpdateFontTexture(); so to load a font you would do something like the fallowing

ImGuiIO io = ImGui::GetIO();
ImFont* font1 = io.Fonts->AddFontFromFileTTF("../res/FFF_Tusj.ttf", 13);
ImGui::SFML::UpdateFontTexture();

Hopefully this helps someone.

All 18 comments

Hello,

PushFont() currently needs to be called after ImGui::NewFrame(). I realize it may be practical or common to try to call it at initialization time, will look if I can change it but it will probably create issue if the user try to symmetrically call PopFont() on application shutdown.

A) Call PushFont() after NewFrame()
or
B) if you are loading only that font and no default font, you don't really need to call PushFont because the first font will be used.

Thanks for your response...

I have commented pushFont... this is the new code at initialization (before main loop)

/* I am using sfml */
sf::RenderWindow window(sf::VideoMode(640, 480), "");
window.setVerticalSyncEnabled(true);
ImGui::SFML::Init(window);

ImGuiIO& io = ImGui::GetIO();
ImFont* pFont = io.Fonts->AddFontFromFileTTF("sansation.ttf", 10.0f);

unsigned char * pixels;
int width, height, bytes_per_pixels;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixels);
GLuint id = loadTexture(pixels, width, height, 4);
io.Fonts->SetTexID((void*)id);

...

Now the error is here:
ImGui::Render();

This error does not occur if I dont load the font...so, it is a side effect...
I should be doing something wrong...

The error is inside void RenderDrawLists(ImDrawData* draw_data) ... specifically
sf::Texture::bind(texture);

So, it seems I am doing something wrong with the texture...
Any idea?

Thanks for your help!

-- just in case, this is the code for loadTexture
GLuint loadTexture(unsigned char *pixels, int w, int h, int components)
{
GLuint textureID;
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, components, w, h, 0, (components==3)?GL_RGB:GL_RGBA, GL_UNSIGNED_BYTE, pixels);
return textureID;
}

Did your call to AddFontFromFileTTF() succeed, is the return value not NULL?
You should look into the existing SFML bindings/examples see what you are doing wrong.

sf::Texture::bind(texture);`

It this taking a Gluint OpenGL texture identiers?

Because earlier you have set the value to :

GLuint id = loadTexture(pixels, width, height, 4);
io.Fonts->SetTexID((void*)id);

Does your loadTexture() functions returns a value that fits in GLuint and can be used to call sf::Texture::bind() ?

PS: Please surround your code block with triple-backquote to have them appear as code.

Hello, yes pFont is not NULL after this
\\ ImFont* pFont = io.Fonts->AddFontFromFileTTF("sansation.ttf", 10.0f);

and yeah,

\\ GLuint loadTexture(unsigned char *pixels, int w, int h, int components)

returns a good texture ID (GLuint) ... tracing the code, it returns 2 ...

By the way, what should be the steps that I should follow to replace
the default font by any other ttf font? ... may be I am missing something.

Thanks again

So what's the error when you call sf::Texture:bind(2) ?

The step is just to add ->AddFontXX as you are doing.

ok... look .... if I do
ImGuiIO& io = ImGui::GetIO();
ImFont* pFont = io.Fonts->AddFontFromFileTTF("sansation.ttf", 10.0f);

then nothing happens... I still see the old font after I use

\\ ImGui::Button or ImGui::Text

Should we write something else?
Thx

Did you function success and return a non-NULL pointer?
Try to provide a repro with all the code..

no null...

well, here the simplified full code:

include "imgui.h"

include "imgui-sfml.h"

include

include

include

include

int main()
{
sf::RenderWindow window(sf::VideoMode(640, 480), "");
window.setVerticalSyncEnabled(true);
ImGui::SFML::Init(window);
ImGuiIO& io = ImGui::GetIO();
ImFont* pFont = io.Fonts->AddFontFromFileTTF("sansation.ttf", 10.0f);
window.setTitle("test new font");
window.resetGLStates(); // call it if you only draw ImGui. Otherwise not needed.
sf::Clock deltaClock;

while (window.isOpen())
{
    sf::Event event;
    while (window.pollEvent(event))
    {
        ImGui::SFML::ProcessEvent(event);
        if (event.type == sf::Event::Closed)
            window.close();
    }

    ImGui::SFML::Update(deltaClock.restart());

    ImGui::Begin("Sample window", 0, ImGuiWindowFlags_NoTitleBar); // begin window
      ImGui::Button("Open Dataset", ImVec2(160, 20));
    ImGui::End();
    sf::Color bgColor( 0.f, 0.0f, 0.0f );
    window.clear(bgColor);
    ImGui::Render();
    window.display();
}
ImGui::SFML::Shutdown();

}

( Please surround your code block with triple-backquote to have them appear as code. )

The problem is perhaps related to the code in ImGui::SFML::.
Do the PushFont after ImGui::SFML::Update() which I assume calls ImGui::NewFrame

ok...I did it... and I get

///
Assertion failed: font && font->IsLoaded(), file imgui.cpp, line 4583
///

thx again for any help or suggestion

You are doing something wrong and probably one of your answer in the thread below was incorrect and misleading the discussion.

Please use a debugger to figure out what you are doing, if not doing that already.

Or ask the people who are maintaining the SFML functions.

so... I added a line after update

麓麓麓 ImGui::SFML::Update(deltaClock.restart());
麓麓麓 ImGui::PushFont(pFont);

But anyway, it is rare to push a font inside the main loop... should we call "pop" ?

Yes you should call PopFont at the end.

ok... the problem is in pushFont...

static void SetCurrentFont(ImFont* font)
{
    ImGuiContext& g = *GImGui;
    IM_ASSERT(font && font->IsLoaded());

here: font->IsLoaded() ...

so, the font has not been loaded...

so...it seems like ImFont* pFont = io.Fonts->AddFontFromFileTTF("sansation.ttf", 10.0f); is not enough to load a font...

so...if I load the font into GPU memory (texture), the problem is move to ImGui::Render()

int main()
{

    sf::RenderWindow window(sf::VideoMode(640, 480), "");
    window.setVerticalSyncEnabled(true);
    ImGui::SFML::Init(window);
    ImGuiIO& io = ImGui::GetIO();
    ImFont* pFont = io.Fonts->AddFontFromFileTTF("sansation.ttf", 10.0f);


    unsigned char * pixels;
    int width, height, bytes_per_pixels;
    io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height, &bytes_per_pixels);
    GLuint id = loadTexture(pixels, width, height, 4);
    io.Fonts->SetTexID((void*)id);

    window.setTitle("test new font");
    window.resetGLStates(); // call it if you only draw ImGui. Otherwise not needed.
    sf::Clock deltaClock;


    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            ImGui::SFML::ProcessEvent(event);

            if (event.type == sf::Event::Closed)
            {
                window.close();
            }
        }

        ImGui::SFML::Update(deltaClock.restart());
        ImGui::PushFont(pFont);

        ImGui::Begin("Sample window", 0, ImGuiWindowFlags_NoTitleBar); // begin window
            if (ImGui::Button("Open Dataset", ImVec2(160, 20)))
            {
            }
        ImGui::End(); // end window


        sf::Color bgColor( 0.f, 0.0f, 0.0f );
        window.clear(bgColor);
        ImGui::Render();
        window.display();
        ImGui::PopFont();
    }

    ImGui::SFML::Shutdown();
}

look... here...
static void CheckStacksSize(ImGuiWindow* window, bool write)

    { int current = g.FontStack.Size;           if (write) *p_backup = current; else IM_ASSERT(*p_backup == current && "PushFont/PopFont Mismatch!");               p_backup++; }    // User forgot PopFont()

So...Push is ok ... but ... the problem is now Pop ... I have moved POP before and after window.display() with same result...

Another SFML/IMGUI user here, seem to be having the same issues as the user above me.

Did you ever come across an effective solution, @rixthor?

Hello....I was not using the template (the sample code you have for each case, sfml, freeglut, sdl and so on). And that's why it did not work. I realized it when I moved my code to freeglut and I saw things like "ImGui::NewFrame". So, the solution is just to start from a sample code which works, and then include the new stuff. It should work in this way Best regards!

Hello I had this issue as well the solution when using ImGui/SFML is to call ImGui::SFML::UpdateFontTexture(); so to load a font you would do something like the fallowing

ImGuiIO io = ImGui::GetIO();
ImFont* font1 = io.Fonts->AddFontFromFileTTF("../res/FFF_Tusj.ttf", 13);
ImGui::SFML::UpdateFontTexture();

Hopefully this helps someone.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  3Comments

KaungZawHtet picture KaungZawHtet  路  3Comments

Folling picture Folling  路  3Comments

spaderthomas picture spaderthomas  路  3Comments

bizehao picture bizehao  路  3Comments