Browse Source

ImFontAtlas: some more optimisations / cleanup.

ocornut 10 years ago
parent
commit
bfe894406d
1 changed files with 43 additions and 35 deletions
  1. 43 35
      imgui.cpp

+ 43 - 35
imgui.cpp

@@ -6297,17 +6297,18 @@ void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const Im
 struct ImFontAtlas::ImFontAtlasData
 {
     // Input
-    ImFont*         OutFont;        // Load into this font
-    void*           TTFData;        // TTF data, we own the memory
-    size_t          TTFDataSize;    // TTF data size, in bytes
-    float           SizePixels;     // Desired output size, in pixels
-    const ImWchar*  GlyphRanges;    // List of Unicode range (2 value per range, values are inclusive, zero-terminated list)
-    int             FontNo;         // Index of font within .TTF file (0)
+    ImFont*             OutFont;        // Load into this font
+    void*               TTFData;        // TTF data, we own the memory
+    size_t              TTFDataSize;    // TTF data size, in bytes
+    float               SizePixels;     // Desired output size, in pixels
+    const ImWchar*      GlyphRanges;    // List of Unicode range (2 value per range, values are inclusive, zero-terminated list)
+    int                 FontNo;         // Index of font within .TTF file (0)
 
     // Temporary Build Data
-    stbtt_fontinfo              FontInfo;
-    stbrp_rect*                 Rects;
-    ImVector<stbtt_pack_range>  Ranges;
+    stbtt_fontinfo      FontInfo;
+    stbrp_rect*         Rects;
+    stbtt_pack_range*   Ranges;
+    int                 RangesCount;
 };
 
 ImFontAtlas::ImFontAtlas()
@@ -6468,6 +6469,7 @@ bool    ImFontAtlas::Build()
 
     // Initialize font information early (so we can error without any cleanup) + count glyphs
     int total_glyph_count = 0;
+    int total_glyph_range_count = 0;
     for (size_t input_i = 0; input_i < InputData.size(); input_i++)
     {
         ImFontAtlasData& data = *InputData[input_i];
@@ -6480,7 +6482,10 @@ bool    ImFontAtlas::Build()
         if (!data.GlyphRanges)
             data.GlyphRanges = GetGlyphRangesDefault();
         for (const ImWchar* in_range = data.GlyphRanges; in_range[0] && in_range[1]; in_range += 2)
+        {
             total_glyph_count += (in_range[1] - in_range[0]) + 1;
+            total_glyph_range_count++;
+        }
     }
 
     // Start packing
@@ -6499,13 +6504,13 @@ bool    ImFontAtlas::Build()
     stbrp_pack_rects((stbrp_context*)spc.pack_info, &extra_rect, 1);
     TexExtraDataPos = ImVec2(extra_rect.x, extra_rect.y);
 
-    // Allocate packing character data and flag as non-packed (x0=y0=x1=y1=0)
-    stbtt_packedchar* packed_chardata = (stbtt_packedchar*)ImGui::MemAlloc(total_glyph_count * sizeof(stbtt_packedchar));
-    int packed_chardata_n = 0;
-    memset(packed_chardata, 0, total_glyph_count * sizeof(stbtt_packedchar));
-
-    stbrp_rect* rectdata = (stbrp_rect*)ImGui::MemAlloc(total_glyph_count * sizeof(stbrp_rect));
-    int rectdata_n = 0;
+    // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0)
+    int buf_packedchars_n = 0, buf_rects_n = 0, buf_ranges_n = 0;
+    stbtt_packedchar* buf_packedchars = (stbtt_packedchar*)ImGui::MemAlloc(total_glyph_count * sizeof(stbtt_packedchar));
+    stbrp_rect* buf_rects = (stbrp_rect*)ImGui::MemAlloc(total_glyph_count * sizeof(stbrp_rect));
+    stbtt_pack_range* buf_ranges = (stbtt_pack_range*)ImGui::MemAlloc(total_glyph_range_count * sizeof(stbtt_pack_range));
+    memset(buf_packedchars, 0, total_glyph_count * sizeof(stbtt_packedchar));
+    memset(buf_ranges, 0, total_glyph_range_count * sizeof(stbtt_pack_range));
 
     // First pass: pack all glyphs (no rendering at this point, we are working with glyph sizes only)
     int tex_height = extra_rect.y + extra_rect.h;
@@ -6521,22 +6526,24 @@ bool    ImFontAtlas::Build()
             glyph_count += (in_range[1] - in_range[0]) + 1;
             glyph_ranges_count++;
         }
-        data.Ranges.resize(glyph_ranges_count);
-        for (size_t i = 0; i < data.Ranges.size(); i++)
+        data.Ranges = buf_ranges + buf_ranges_n;
+        data.RangesCount = glyph_ranges_count;
+        buf_ranges_n += glyph_ranges_count;
+        for (size_t i = 0; i < glyph_ranges_count; i++)
         {
+            const ImWchar* in_range = &data.GlyphRanges[i * 2];
             stbtt_pack_range& range = data.Ranges[i];
             range.font_size = data.SizePixels;
-            const ImWchar* in_range = &data.GlyphRanges[i * 2];
             range.first_unicode_char_in_range = in_range[0];
             range.num_chars_in_range = (in_range[1] - in_range[0]) + 1;
-            range.chardata_for_range = packed_chardata + packed_chardata_n;
-            packed_chardata_n += range.num_chars_in_range;
+            range.chardata_for_range = buf_packedchars + buf_packedchars_n;
+            buf_packedchars_n += range.num_chars_in_range;
         }
 
         // Pack
-        data.Rects = rectdata + rectdata_n;
-        rectdata_n += glyph_count;
-        const int n = stbtt_PackFontRangesGatherRects(&spc, &data.FontInfo, data.Ranges.begin(), data.Ranges.size(), data.Rects);
+        data.Rects = buf_rects + buf_rects_n;
+        buf_rects_n += glyph_count;
+        const int n = stbtt_PackFontRangesGatherRects(&spc, &data.FontInfo, data.Ranges, data.RangesCount, data.Rects);
         stbrp_pack_rects((stbrp_context*)spc.pack_info, data.Rects, n);
 
         // Extend texture height
@@ -6544,11 +6551,13 @@ bool    ImFontAtlas::Build()
             if (data.Rects[i].was_packed)
                 tex_height = ImMax(tex_height, data.Rects[i].y + data.Rects[i].h);
     }
-    IM_ASSERT(packed_chardata_n == total_glyph_count);
+    IM_ASSERT(buf_rects_n == total_glyph_count);
+    IM_ASSERT(buf_packedchars_n == total_glyph_count);
+    IM_ASSERT(buf_ranges_n == total_glyph_range_count);
 
     // Create texture
     TexHeight = ImUpperPowerOfTwo(tex_height);
-    TexPixelsAlpha8 = (unsigned char*)ImGui::MemRealloc(TexPixelsAlpha8, TexWidth * TexHeight);
+    TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(TexWidth * TexHeight);
     memset(TexPixelsAlpha8, 0, TexWidth * TexHeight);
     spc.pixels = TexPixelsAlpha8;
     spc.height = TexHeight;
@@ -6557,14 +6566,14 @@ bool    ImFontAtlas::Build()
     for (size_t input_i = 0; input_i < InputData.size(); input_i++)
     {
         ImFontAtlasData& data = *InputData[input_i];
-        ret = stbtt_PackFontRangesRenderIntoRects(&spc, &data.FontInfo, data.Ranges.begin(), data.Ranges.size(), data.Rects);
+        ret = stbtt_PackFontRangesRenderIntoRects(&spc, &data.FontInfo, data.Ranges, data.RangesCount, data.Rects);
         data.Rects = NULL;
     }
 
     // End packing
     stbtt_PackEnd(&spc);
-    ImGui::MemFree(rectdata);
-    rectdata = NULL;
+    ImGui::MemFree(buf_rects);
+    buf_rects = NULL;
 
     // Third pass: setup ImFont and glyphs for runtime
     for (size_t input_i = 0; input_i < InputData.size(); input_i++)
@@ -6580,7 +6589,7 @@ bool    ImFontAtlas::Build()
         const float uv_scale_x = 1.0f / TexWidth;
         const float uv_scale_y = 1.0f / TexHeight;
         const int character_spacing_x = 1;
-        for (size_t i = 0; i < data.Ranges.size(); i++)
+        for (int i = 0; i < data.RangesCount; i++)
         {
             stbtt_pack_range& range = data.Ranges[i];
             for (int char_idx = 0; char_idx < range.num_chars_in_range; char_idx += 1)
@@ -6606,15 +6615,14 @@ bool    ImFontAtlas::Build()
         }
 
         data.OutFont->BuildLookupTable();
-
-        // Cleanup temporaries
-        data.Ranges.clear();
     }
 
     // Cleanup temporaries
+    ImGui::MemFree(buf_packedchars);
+    ImGui::MemFree(buf_ranges);
+    buf_packedchars = NULL;
+    buf_ranges = NULL;
     ClearInputData();
-    ImGui::MemFree(packed_chardata);
-    packed_chardata = NULL;
 
     // Draw white pixel into texture and make UV points to it
     TexPixelsAlpha8[0] = TexPixelsAlpha8[1] = TexPixelsAlpha8[TexWidth+0] = TexPixelsAlpha8[TexWidth+1] = 0xFF;