Appending a pre-baked Font texture to the FontAtlas

I’ve integrated imgui into my project at commit: 56c3aaf6bd06bbde95138b9dad61e1fa33ccfde8

I’ve a couple of questions related to Fonts and texture atlases.

As another note I am compiling on VS2010 so don’t have access to the modern C++ stuff like string literals u8"some unicode string". I have to setup my unicode strings the legacy way.

Now the preamble is done I’m trying to add a texture directly into the Font Atlas Imgui will use. Bypassing the font ttf loading and building.

  1. I’ve grabbed the atlas from ImGui::GetIO().Fonts

  2. Called the CreateDeviceObjects for the renderer I’m using (either opengl2 or dx9 ) to get the g_FontTexture setup.

  3. I have setup an array of ImWchar’s for the glyph ranges that get passed into the ImFontConfig structure for my pre-baked font texture. like so:
    static const ImWchar fsfranges[] =
    {
    0x0024, 0x0024, // $ sign
    0x002C, 0x002E, // comma, hyphen-minus, full stop
    0x0030, 0x0039, // 0-9
    0x0058, 0x0058, // X
    0xC2A3, 0xC2A3, // £ sign
    0xC8BC, 0xC8BC, // small c with stroke
    0xC2A9, 0xC2A9, // overwritten copyright with emoji type graphic
    0xC2AE, 0xC2AE, // overwritten registration mark with emoji type graphic
    0,
    };

  4. As I am bypassing the font loading/building I am creating an ImFont manually and pushing it to the atlas.Like so:
    imageFont = IM_NEW(ImFont);
    atlas->Fonts.push_back(imageFont);

  5. After setting the font up with the size etc. I set the glyph positions manually for the new font:
    int glyphpos = imageFont->Glyphs.Size; // don’t stamp over glyphs already in the container
    imageFont->Glyphs.resize( glyphpos + glyphCount );

for( int i = 0; i < glyphCount; ++i )
{
GlyphInfo &glyph = fsfglyphs[i];
ImFontGlyph &fontglyph = imageFont->Glyphs[glyphpos + i];
fontglyph.Codepoint = glyph.character;
fontglyph.X0 = glyph.x0; fontglyph.Y0 = glyph.y0; fontglyph.X1 = glyph.x1; fontglyph.Y1 = glyph.y1;
fontglyph.U0 = glyph.u0; fontglyph.V0 = glyph.v0; fontglyph.U1 = glyph.u1; fontglyph.V1 = glyph.v1;
fontglyph.AdvanceX = glyph.xAdvance;

// Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round)
imageFont->DirtyLookupTables = true;
imageFont->MetricsTotalSurface += (int)((fontglyph.U1 - fontglyph.U0) * imageFont->ContainerAtlas->TexWidth + 1.99f) * (int)((fontglyph.V1 - fontglyph.V0) * imageFont->ContainerAtlas->TexHeight + 1.99f);

float xadvance    = 0.0f;
ImVec2 offset     = ImVec2(0,0);
int width  = (int)floor(glyph.x1 - glyph.x0);
int height = (int)floor(glyph.y1 - glyph.y0);
atlas->AddCustomRectFontGlyph(imageFont, glyph.character, width, height, xadvance, offset );

}

Running with the style editor open, it shows on the Font tab the newly added font and I’m not expecting the demo text “quick brown fox” to appear as I haven’t supplied those glyphs for this new font.

I am expecting the atlas itself to have changed and the glyphs dropdown to contain a list of my ranges displaying the grid with my glyphs mapped in. Neither of these things seem to have occurred. I get no sub list like U0020…U00FF and no grid of glyph mappings.

If anyone can point me in the right direction on this it would be very helpful.

Notice that the call to AddCustomRectFontGlyph() doesn’t specify an uv/position in the texture, this is meant to register a rectange for packing into the atlas, and then to get filled with pixels after calling Build, with positions obtained from GetCustomRect() cals.

I think you can either use AddCustomRectFontGlyph+GetCustomRect() and copy pixel data in the position decided by the atlas packer, OR create the glyphs yourself as you started doing, but maybe just add font->AddGlyph() and then BuildLookupTable().
I think the later will be more natural here if you already have a texture and known coordinates.

See https://github.com/ocornut/imgui/issues/2127
You probably need to call BuildLookupTable(), but otherwise I suggest just stepping through code trying to use that font and you’ll find what the problem is.

Thanks a lot for your help!

Following your advice I changed tack and followed the example from issue 2127. This meant implementing the custom texture as a new atlas (rather than copying my custom data into the default atlas), that gets me 90% of the way to a system working as I had initially envisaged.

The main issue now seems to be only some of the glyphs are drawn in the correct place!

For string “PcSF,$XXX-.0123456789” — Where ‘P’ == £, ‘c’ == c slashed, ‘S’=SPINS ‘F’=FREE-SPINS

test
As you can see the regular latin characters seem ok, I have issues with the overwritten latin characters ‘P’ ‘c’ ‘S’ and ‘F’. I have set xAdvance to 20.0f for all glyphs, except ‘X’ which I have set to 40.0f for some reason they wanted to all be bunched together???. All in all very odd.

The other more minor but related issue is the glyph mappings for extended character sets 0xC2A3 for the ‘£’ sign and the like, don’t seem to get picked up but if I map those glyphs to basic latin characters my font doesn’t use, it works, so this workaround will be fine for me for the time being. I suspect I have setup the u8 strings badly somewhere along the lines, but I should be able to sort that out at a later time.

I’ll update this thread If I manage to improve things in the hopes it’ll help someone else.

Thanks once again for steering me in the right direction.