Bladeren bron

Fonts: Baked system, v12: support GlyphOffset / GlyphMinAdvanceX / GlyphMaxAdvanceX by scaling from ref value.

Overwriting cfg->PixelSnapH = true; in imgui_freetype is weird.
ocornut 7 maanden geleden
bovenliggende
commit
99f6b305c1
4 gewijzigde bestanden met toevoegingen van 27 en 10 verwijderingen
  1. 1 1
      imgui.cpp
  2. 5 4
      imgui.h
  3. 11 3
      imgui_draw.cpp
  4. 10 2
      misc/freetype/imgui_freetype.cpp

+ 1 - 1
imgui.cpp

@@ -8602,7 +8602,7 @@ void ImGui::SetCurrentFont(ImFont* font, float font_size)
 {
     ImGuiContext& g = *GImGui;
     g.Font = font;
-    //g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.FontBaked->FontSize * g.Font->Scale);
+    //g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.FontBaked->Size * g.Font->Scale);
     g.FontSize = font_size;// g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
     if (font != NULL)
     {

+ 5 - 4
imgui.h

@@ -3424,15 +3424,16 @@ struct ImFontConfig
     bool            FontDataOwnedByAtlas;   // true     // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself).
     bool            MergeMode;              // false    // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
     bool            PixelSnapH;             // false    // Align every glyph AdvanceX to pixel boundaries. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1.
+    bool            PixelSnapV;             // true     // Align Scaled GlyphOffset.y to pixel boundaries.
     int             FontNo;                 // 0        // Index of font within TTF/OTF file
     int             OversampleH;            // 0 (2)    // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1 or 2 depending on size. Note the difference between 2 and 3 is minimal. You can reduce this to 1 for large glyphs save memory. Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details.
     int             OversampleV;            // 0 (1)    // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1. This is not really useful as we don't use sub-pixel positions on the Y axis.
     float           SizePixels;             //          // Size in pixels for rasterizer (more or less maps to the resulting font height).
-    //ImVec2        GlyphExtraSpacing;      // 0, 0     // (REMOVED IN 1.91.9: use GlyphExtraAdvanceX)
-    ImVec2          GlyphOffset;            // 0, 0     // [FIXME-BAKED] Offset all glyphs from this font input.
+    //ImVec2        GlyphExtraSpacing;      // 0, 0     // (REMOVED AT IT SEEMS LARGELY OBSOLETE. PLEASE REPORT IF YOU WERE USING THIS). Extra spacing (in pixels) between glyphs when rendered: essentially add to glyph->AdvanceX. Only X axis is supported for now.
+    ImVec2          GlyphOffset;            // 0, 0     // Offset (in pixels) all glyphs from this font input. Absolute value for default size, other sizes will scale this value.
     const ImWchar*  GlyphRanges;            // NULL     // THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list).
-    float           GlyphMinAdvanceX;       // 0        // [FIXME-BAKED] Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
-    float           GlyphMaxAdvanceX;       // FLT_MAX  // [FIXME-BAKED] Maximum AdvanceX for glyphs
+    float           GlyphMinAdvanceX;       // 0        // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font. Absolute value for default size, other sizes will scale this value.
+    float           GlyphMaxAdvanceX;       // FLT_MAX  // Maximum AdvanceX for glyphs
     float           GlyphExtraAdvanceX;     // 0        // Extra spacing (in pixels) between glyphs. Please contact us if you are using this.
     unsigned int    FontBuilderFlags;       // 0        // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure.
     float           RasterizerMultiply;     // 1.0f     // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future.

+ 11 - 3
imgui_draw.cpp

@@ -4351,8 +4351,15 @@ static bool ImGui_ImplStbTrueType_FontBakedAddGlyph(ImFontAtlas* atlas, ImFontBa
         if (oversample_v > 1)
             stbtt__v_prefilter(bitmap_pixels, r->w, r->h, r->w, oversample_v);
 
-        float font_off_x = src->GlyphOffset.x + stbtt__oversample_shift(oversample_h);
-        float font_off_y = src->GlyphOffset.y + stbtt__oversample_shift(oversample_v) + IM_ROUND(baked->Ascent);
+        const float offsets_scale = baked->Size / baked->ContainerFont->Sources[0].SizePixels;
+        float font_off_x = (src->GlyphOffset.x * offsets_scale);
+        float font_off_y = (src->GlyphOffset.y * offsets_scale);
+        if (src->PixelSnapH) // Snap scaled offset. This is to mitigate backward compatibility issues for GlyphOffset, but a better design would be welcome.
+            font_off_x = IM_ROUND(font_off_x);
+        if (src->PixelSnapV)
+            font_off_y = IM_ROUND(font_off_y);
+        font_off_x += stbtt__oversample_shift(oversample_h);
+        font_off_y += stbtt__oversample_shift(oversample_v) + IM_ROUND(baked->Ascent);
         float recip_h = 1.0f / (oversample_h * src->RasterizerDensity);
         float recip_v = 1.0f / (oversample_v * src->RasterizerDensity);
 
@@ -4800,7 +4807,8 @@ ImFontGlyph* ImFontAtlasBakedAddFontGlyph(ImFontAtlas* atlas, ImFontBaked* baked
     if (src != NULL)
     {
         // Clamp & recenter if needed
-        float advance_x = ImClamp(glyph.AdvanceX, src->GlyphMinAdvanceX, src->GlyphMaxAdvanceX);
+        const float offsets_scale = baked->Size / baked->ContainerFont->Sources[0].SizePixels;
+        float advance_x = ImClamp(glyph.AdvanceX, src->GlyphMinAdvanceX * offsets_scale, src->GlyphMaxAdvanceX * offsets_scale);
         if (advance_x != glyph.AdvanceX)
         {
             float char_off_x = src->PixelSnapH ? ImTrunc((advance_x - glyph.AdvanceX) * 0.5f) : (advance_x - glyph.AdvanceX) * 0.5f;

+ 10 - 2
misc/freetype/imgui_freetype.cpp

@@ -204,6 +204,9 @@ namespace
 
         if (UserFlags & ImGuiFreeTypeBuilderFlags_NoHinting)
             LoadFlags |= FT_LOAD_NO_HINTING;
+        else
+            src->PixelSnapH = true; // FIXME: A bit weird to do this this way.
+
         if (UserFlags & ImGuiFreeTypeBuilderFlags_NoAutoHint)
             LoadFlags |= FT_LOAD_NO_AUTOHINT;
         if (UserFlags & ImGuiFreeTypeBuilderFlags_ForceAutoHint)
@@ -559,8 +562,13 @@ bool ImGui_ImplFreeType_FontBakedAddGlyph(ImFontAtlas* atlas, ImFontBaked* baked
         uint32_t* temp_buffer = (uint32_t*)atlas->Builder->TempBuffer.Data;
         bd_font_data->BlitGlyph(ft_bitmap, temp_buffer, w);
 
-        float font_off_x = src->GlyphOffset.x;
-        float font_off_y = src->GlyphOffset.y + IM_ROUND(baked->Ascent);
+        const float offsets_scale = baked->Size / baked->ContainerFont->Sources[0].SizePixels;
+        float font_off_x = (src->GlyphOffset.x * offsets_scale);
+        float font_off_y = (src->GlyphOffset.y * offsets_scale) + baked->Ascent;
+        if (src->PixelSnapH) // Snap scaled offset. This is to mitigate backward compatibility issues for GlyphOffset, but a better design would be welcome.
+            font_off_x = IM_ROUND(font_off_x);
+        if (src->PixelSnapV)
+            font_off_y = IM_ROUND(font_off_y);
         float recip_h = 1.0f / src->RasterizerDensity;
         float recip_v = 1.0f / src->RasterizerDensity;