Bladeren bron

Fonts: reinstated ImFontAtlasBuildSetupFontCreateEllipsisFromDot() compatible with baked system, lazily baked.

ocornut 7 maanden geleden
bovenliggende
commit
d59f10d7f5
2 gewijzigde bestanden met toevoegingen van 50 en 23 verwijderingen
  1. 1 0
      imgui.h
  2. 49 23
      imgui_draw.cpp

+ 1 - 0
imgui.h

@@ -3697,6 +3697,7 @@ struct ImFont
     ImWchar                     FallbackChar;       // 2-4   // out // Character used if a glyph isn't found (U+FFFD, '?')
     float                       Scale;              // 4     // in  // Base font scale (~1.0f), multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
     ImU8                        Used8kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/8192/8]; // 1 bytes if ImWchar=ImWchar16, 16 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints.
+    bool                        EllipsisAutoBake;   // 1     //     // Mark when the "..." glyph needs to be generated.
     short                       LockSingleSrcConfigIdx;
 
     // Methods

+ 49 - 23
imgui_draw.cpp

@@ -2497,7 +2497,8 @@ void ImTextureData::DestroyPixels()
 // - ImFontAtlasBuildUpdateBasicTexData()
 // - ImFontAtlasBuildUpdateLinesTexData()
 // - ImFontAtlasBuildAddFont()
-// - ImFontAtlasBuildSetupFontCreateEllipsisFromDot()
+// - ImFontAtlasBuildSetupFontBakedEllipsis()
+// - ImFontAtlasBuildSetupFontBakedBlanks()
 // - ImFontAtlasBuildSetupFontSpecialGlyphs()
 // - ImFontAtlasBuildDiscardBakes()
 // - ImFontAtlasBuildDiscardFontBakedGlyph()
@@ -3528,37 +3529,50 @@ bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src)
     return true;
 }
 
-// Rasterize our own ellipsis character from a dot.
+// Create a compact, baked "..." if it doesn't exist, by using the ".".
 // This may seem overly complicated right now but the point is to exercise and improve a technique which should be increasingly used.
-// FIXME-NEWATLAS: This borrows too much from FontBackend_FontAddGlyph() and suggest that we should add further helpers.
-// FIXME-BAKED: prebaked ellipsis
-/*static void ImFontAtlasBuildSetupFontCreateEllipsisFromDot(ImFontAtlas* atlas, ImFont* font, const ImFontGlyph* dot_glyph)
+// FIXME-NEWATLAS: This borrows too much from FontLoader's FontLoaderGlyph() handlers and suggest that we should add further helpers.
+static ImFontGlyph* ImFontAtlasBuildSetupFontBakedEllipsis(ImFontAtlas* atlas, ImFontBaked* baked)
 {
-    ImFontAtlasRect* dot_r = ImFontAtlasPackGetRect(atlas, dot_glyph->PackId);
+    ImFont* font = baked->ContainerFont;
+    IM_ASSERT(font->EllipsisChar != 0);
+
+    const ImFontGlyph* dot_glyph = baked->FindGlyphNoFallback((ImWchar)'.');
+    if (dot_glyph == NULL)
+        dot_glyph = baked->FindGlyphNoFallback((ImWchar)0xFF0E);
+    if (dot_glyph == NULL)
+        return NULL;
+    ImFontAtlasRectId dot_r_id = dot_glyph->PackId; // Deep copy to avoid invalidation of glyphs and rect pointers
+    ImFontAtlasRect* dot_r = ImFontAtlasPackGetRect(atlas, dot_r_id);
     const int dot_spacing = 1;
     const float dot_step = (dot_glyph->X1 - dot_glyph->X0) + dot_spacing;
+
     ImFontAtlasRectId pack_id = ImFontAtlasPackAddRect(atlas, (dot_r->w * 3 + dot_spacing * 2), dot_r->h);
     ImFontAtlasRect* r = ImFontAtlasPackGetRect(atlas, pack_id);
 
-    ImFontGlyph glyph;
-    glyph.Codepoint = (ImWchar)0x0085; // FIXME: Using arbitrary codepoint.
-    glyph.AdvanceX = ImMax(dot_glyph->AdvanceX, dot_glyph->X0 + dot_step * 3.0f - dot_spacing); // FIXME: Slightly odd for normally mono-space fonts but since this is used for trailing contents.
-    glyph.X0 = dot_glyph->X0;
-    glyph.Y0 = dot_glyph->Y0;
-    glyph.X1 = dot_glyph->X0 + dot_step * 3 - dot_spacing;
-    glyph.Y1 = dot_glyph->Y1;
-    glyph.Visible = true;
-    glyph.PackId = pack_id;
-    ImFontAtlasBuildAddFontGlyph(atlas, font, NULL, &glyph);
-    font->EllipsisChar = (ImWchar)glyph.Codepoint;
+    ImFontGlyph glyph_in = {};
+    ImFontGlyph* glyph = &glyph_in;
+    glyph->Codepoint = font->EllipsisChar;
+    glyph->AdvanceX = ImMax(dot_glyph->AdvanceX, dot_glyph->X0 + dot_step * 3.0f - dot_spacing); // FIXME: Slightly odd for normally mono-space fonts but since this is used for trailing contents.
+    glyph->X0 = dot_glyph->X0;
+    glyph->Y0 = dot_glyph->Y0;
+    glyph->X1 = dot_glyph->X0 + dot_step * 3 - dot_spacing;
+    glyph->Y1 = dot_glyph->Y1;
+    glyph->Visible = true;
+    glyph->PackId = pack_id;
+    glyph = ImFontAtlasBakedAddFontGlyph(atlas, baked, NULL, glyph);
+    dot_glyph = NULL; // Invalidated
 
     // Copy to texture, post-process and queue update for backend
     // FIXME-NEWATLAS-V2: Dot glyph is already post-processed as this point, so this would damage it.
+    dot_r = ImFontAtlasPackGetRect(atlas, dot_r_id);
     ImTextureData* tex = atlas->TexData;
     for (int n = 0; n < 3; n++)
         ImFontAtlasTextureBlockCopy(tex, dot_r->x, dot_r->y, tex, r->x + (dot_r->w + dot_spacing) * n, r->y, dot_r->w, dot_r->h);
     ImFontAtlasTextureBlockQueueUpload(atlas, tex, r->x, r->y, r->w, r->h);
-}*/
+
+    return glyph;
+}
 
 static void ImFontAtlasBuildSetupFontBakedSpecialGlyphs(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked)
 {
@@ -3582,6 +3596,14 @@ static void ImFontAtlasBuildSetupFontBakedSpecialGlyphs(ImFontAtlas* atlas, ImFo
     }
     baked->FallbackGlyphIndex = baked->Glyphs.index_from_ptr(fallback_glyph); // Storing index avoid need to update pointer on growth and simplify inner loop code
     baked->FallbackAdvanceX = fallback_glyph->AdvanceX;
+}
+
+static void ImFontAtlasBuildSetupFontBakedBlanks(ImFontAtlas* atlas, ImFontBaked* baked)
+{
+    // Mark space as always hidden (not strictly correct/necessary. but some e.g. icons fonts don't have a space. it tends to look neater in previews)
+    ImFontGlyph* space_glyph = baked->FindGlyphNoFallback((ImWchar)' ');
+    if (space_glyph != NULL)
+        space_glyph->Visible = false;
 
     // Setup Tab character.
     // FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at "column 0" ?)
@@ -3628,11 +3650,8 @@ void ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFont* font, Im
             }
     if (font->EllipsisChar == 0)
     {
-        /*const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E };
-        if (const ImFontGlyph* dot_glyph = LoadFirstExistingGlyph(font, dots_chars, IM_ARRAYSIZE(dots_chars)))
-            ImFontAtlasBuildSetupFontCreateEllipsisFromDot(atlas, font, dot_glyph);
-        else*/
-            font->EllipsisChar = (ImWchar)' ';
+        font->EllipsisChar = 0x0085;
+        font->EllipsisAutoBake = true;
     }
     font->LockSingleSrcConfigIdx = -1;
 }
@@ -4162,6 +4181,7 @@ ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h, ImFon
     }
 }
 
+// Important: don'return pointer valid until next call to AddRect(), e.g. FindGlyph(), CalcTextSize() can all potentially invalidate previous pointers.
 ImFontAtlasRect* ImFontAtlasPackGetRect(ImFontAtlas* atlas, ImFontAtlasRectId id)
 {
     IM_ASSERT(id >= 0);
@@ -4182,6 +4202,12 @@ ImFontGlyph* ImFontBaked::BuildLoadGlyph(ImWchar codepoint)
     //char utf8_buf[5];
     //IMGUI_DEBUG_LOG("[font] BuildLoadGlyph U+%04X (%s)\n", (unsigned int)codepoint, ImTextCharToUtf8(utf8_buf, (unsigned int)codepoint));
 
+    // Special hook
+    // FIXME-NEWATLAS: it would be nicer if this used a more standardized way of hooking
+    if (codepoint == font->EllipsisChar && font->EllipsisAutoBake)
+        if (ImFontGlyph* glyph = ImFontAtlasBuildSetupFontBakedEllipsis(atlas, baked))
+            return glyph;
+
     // Load from single source or all sources?
     int srcs_count = (font->LockSingleSrcConfigIdx != -1) ? 1 : font->SourcesCount;
     ImFontConfig* srcs = (font->LockSingleSrcConfigIdx != -1) ? &font->Sources[font->LockSingleSrcConfigIdx] : font->Sources;