Browse Source

Font: fix for fallback character width.

ocornut 10 years ago
parent
commit
0ffd99d319
2 changed files with 25 additions and 10 deletions
  1. 21 8
      imgui.cpp
  2. 4 2
      imgui.h

+ 21 - 8
imgui.cpp

@@ -3194,8 +3194,6 @@ static void SetFont(ImFont* font)
     g.Font = font;
     g.Font = font;
     g.FontSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;
     g.FontSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale;
     g.FontTexUvWhitePixel = g.Font->ContainerAtlas->TexUvWhitePixel;
     g.FontTexUvWhitePixel = g.Font->ContainerAtlas->TexUvWhitePixel;
-    g.Font->FallbackGlyph = NULL;
-    g.Font->FallbackGlyph = g.Font->FindGlyph(g.Font->FallbackChar);
 }
 }
 
 
 void ImGui::PushFont(ImFont* font)
 void ImGui::PushFont(ImFont* font)
@@ -7459,9 +7457,10 @@ void    ImFont::Clear()
     DisplayOffset = ImVec2(-0.5f, 0.5f);
     DisplayOffset = ImVec2(-0.5f, 0.5f);
     ContainerAtlas = NULL;
     ContainerAtlas = NULL;
     Glyphs.clear();
     Glyphs.clear();
+    FallbackGlyph = NULL;
+    FallbackXAdvance = 0.0f;
     IndexXAdvance.clear();
     IndexXAdvance.clear();
     IndexLookup.clear();
     IndexLookup.clear();
-    FallbackGlyph = NULL;
 }
 }
 
 
 // Retrieve list of range (2 int per range, values are inclusive)
 // Retrieve list of range (2 int per range, values are inclusive)
@@ -7563,7 +7562,7 @@ void ImFont::BuildLookupTable()
     IndexLookup.resize((size_t)max_codepoint + 1);
     IndexLookup.resize((size_t)max_codepoint + 1);
     for (size_t i = 0; i < (size_t)max_codepoint + 1; i++)
     for (size_t i = 0; i < (size_t)max_codepoint + 1; i++)
     {
     {
-        IndexXAdvance[i] = 0.0f;
+        IndexXAdvance[i] = -1.0f;
         IndexLookup[i] = -1;
         IndexLookup[i] = -1;
     }
     }
     for (size_t i = 0; i < Glyphs.size(); i++)
     for (size_t i = 0; i < Glyphs.size(); i++)
@@ -7577,7 +7576,8 @@ void ImFont::BuildLookupTable()
     // FIXME: Needs proper TAB handling but it needs to be contextualized (can arbitrary say that each string starts at "column 0"
     // FIXME: Needs proper TAB handling but it needs to be contextualized (can arbitrary say that each string starts at "column 0"
     if (FindGlyph((unsigned short)' '))
     if (FindGlyph((unsigned short)' '))
     {
     {
-        Glyphs.resize(Glyphs.size() + 1);
+        if (Glyphs.back().Codepoint != '\t')   // So we can call this function multiple times
+            Glyphs.resize(Glyphs.size() + 1);
         ImFont::Glyph& tab_glyph = Glyphs.back();
         ImFont::Glyph& tab_glyph = Glyphs.back();
         tab_glyph = *FindGlyph((unsigned short)' ');
         tab_glyph = *FindGlyph((unsigned short)' ');
         tab_glyph.Codepoint = '\t';
         tab_glyph.Codepoint = '\t';
@@ -7585,6 +7585,19 @@ void ImFont::BuildLookupTable()
         IndexXAdvance[(size_t)tab_glyph.Codepoint] = (float)tab_glyph.XAdvance;
         IndexXAdvance[(size_t)tab_glyph.Codepoint] = (float)tab_glyph.XAdvance;
         IndexLookup[(size_t)tab_glyph.Codepoint] = (int)(Glyphs.size()-1);
         IndexLookup[(size_t)tab_glyph.Codepoint] = (int)(Glyphs.size()-1);
     }
     }
+
+    FallbackGlyph = NULL;
+    FallbackGlyph = FindGlyph(FallbackChar);
+    FallbackXAdvance = FallbackGlyph ? FallbackGlyph->XAdvance : 0.0f;
+    for (size_t i = 0; i < (size_t)max_codepoint + 1; i++)
+        if (IndexXAdvance[i] < 0.0f)
+            IndexXAdvance[i] = FallbackXAdvance;
+}
+
+void ImFont::SetFallbackChar(ImWchar c)
+{
+    FallbackChar = c;
+    BuildLookupTable();
 }
 }
 
 
 const ImFont::Glyph* ImFont::FindGlyph(unsigned short c) const
 const ImFont::Glyph* ImFont::FindGlyph(unsigned short c) const
@@ -7796,7 +7809,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
             continue;
             continue;
         }
         }
 
 
-        const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : 0.0f;
+        const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : FallbackXAdvance;
         if (ImCharIsSpace(c))
         if (ImCharIsSpace(c))
         {
         {
             if (inside_word)
             if (inside_word)
@@ -7900,7 +7913,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
             continue;
             continue;
         }
         }
         
         
-        const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : 0.0f;
+        const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : FallbackXAdvance;
         if (line_width + char_width >= max_width)
         if (line_width + char_width >= max_width)
             break;
             break;
 
 
@@ -7944,7 +7957,7 @@ ImVec2 ImFont::CalcTextSizeW(float size, float max_width, const ImWchar* text_be
             continue;
             continue;
         }
         }
         
         
-        const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : 0.0f;
+        const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : FallbackXAdvance;
         if (line_width + char_width >= max_width)
         if (line_width + char_width >= max_width)
             break;
             break;
 
 

+ 4 - 2
imgui.h

@@ -921,7 +921,7 @@ struct ImFont
     float               FontSize;           // <user set>      // Height of characters, set during loading (don't change after loading)
     float               FontSize;           // <user set>      // Height of characters, set during loading (don't change after loading)
     float               Scale;              // = 1.0f          // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale()
     float               Scale;              // = 1.0f          // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale()
     ImVec2              DisplayOffset;      // = (0.0f,0.0f)   // Offset font rendering by xx pixels
     ImVec2              DisplayOffset;      // = (0.0f,0.0f)   // Offset font rendering by xx pixels
-    ImWchar             FallbackChar;       // = '?'           // Replacement glyph if one isn't found.
+    ImWchar             FallbackChar;       // = '?'           // Replacement glyph if one isn't found. Only set via SetFallbackChar()
 
 
     // Members: Runtime data
     // Members: Runtime data
     struct Glyph
     struct Glyph
@@ -934,9 +934,10 @@ struct ImFont
     };
     };
     ImFontAtlas*        ContainerAtlas;     // What we has been loaded into
     ImFontAtlas*        ContainerAtlas;     // What we has been loaded into
     ImVector<Glyph>     Glyphs;
     ImVector<Glyph>     Glyphs;
+    const Glyph*        FallbackGlyph;      // == FindGlyph(FontFallbackChar)
+    float               FallbackXAdvance;   //
     ImVector<float>     IndexXAdvance;      // Glyphs->XAdvance directly indexable (for CalcTextSize functions which are often bottleneck in large UI)
     ImVector<float>     IndexXAdvance;      // Glyphs->XAdvance directly indexable (for CalcTextSize functions which are often bottleneck in large UI)
     ImVector<int>       IndexLookup;        // Index glyphs by Unicode code-point
     ImVector<int>       IndexLookup;        // Index glyphs by Unicode code-point
-    const Glyph*        FallbackGlyph;      // == FindGlyph(FontFallbackChar)
 
 
     // Methods
     // Methods
     IMGUI_API ImFont();
     IMGUI_API ImFont();
@@ -944,6 +945,7 @@ struct ImFont
     IMGUI_API void                  Clear();
     IMGUI_API void                  Clear();
     IMGUI_API void                  BuildLookupTable();
     IMGUI_API void                  BuildLookupTable();
     IMGUI_API const Glyph*          FindGlyph(unsigned short c) const;
     IMGUI_API const Glyph*          FindGlyph(unsigned short c) const;
+    IMGUI_API void                  SetFallbackChar(ImWchar c);
     IMGUI_API bool                  IsLoaded() const        { return ContainerAtlas != NULL; }
     IMGUI_API bool                  IsLoaded() const        { return ContainerAtlas != NULL; }
 
 
     // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable.
     // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable.