From bfe894406d449625cf1c27391628ea3ebf05914f Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 18 Jan 2015 12:12:16 +0000 Subject: [PATCH] ImFontAtlas: some more optimisations / cleanup. --- imgui.cpp | 78 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e76abfa8..9c394a4c 100644 --- a/imgui.cpp +++ b/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 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;