mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-04 15:11:05 +01:00 
			
		
		
		
	ImFontAtlas: reduced number of temporary allocation when building lots of input ranges
This commit is contained in:
		
							
								
								
									
										37
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								imgui.cpp
									
									
									
									
									
								
							@@ -6484,7 +6484,7 @@ bool    ImFontAtlas::Build()
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Start packing
 | 
					    // Start packing
 | 
				
			||||||
    TexWidth = (total_glyph_count > 3000) ? 2048 : (total_glyph_count > 1000) ? 1024 : 512;  // Width doesn't actually matters.
 | 
					    TexWidth = (total_glyph_count > 1000) ? 1024 : 512;  // Width doesn't actually matters.
 | 
				
			||||||
    TexHeight = 0;
 | 
					    TexHeight = 0;
 | 
				
			||||||
    const int max_tex_height = 1024*32;
 | 
					    const int max_tex_height = 1024*32;
 | 
				
			||||||
    stbtt_pack_context spc;
 | 
					    stbtt_pack_context spc;
 | 
				
			||||||
@@ -6499,6 +6499,14 @@ bool    ImFontAtlas::Build()
 | 
				
			|||||||
    stbrp_pack_rects((stbrp_context*)spc.pack_info, &extra_rect, 1);
 | 
					    stbrp_pack_rects((stbrp_context*)spc.pack_info, &extra_rect, 1);
 | 
				
			||||||
    TexExtraDataPos = ImVec2(extra_rect.x, extra_rect.y);
 | 
					    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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // First pass: pack all glyphs (no rendering at this point, we are working with glyph sizes only)
 | 
					    // 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;
 | 
					    int tex_height = extra_rect.y + extra_rect.h;
 | 
				
			||||||
    for (size_t input_i = 0; input_i < InputData.size(); input_i++)
 | 
					    for (size_t input_i = 0; input_i < InputData.size(); input_i++)
 | 
				
			||||||
@@ -6521,17 +6529,13 @@ bool    ImFontAtlas::Build()
 | 
				
			|||||||
            const ImWchar* in_range = &data.GlyphRanges[i * 2];
 | 
					            const ImWchar* in_range = &data.GlyphRanges[i * 2];
 | 
				
			||||||
            range.first_unicode_char_in_range = in_range[0];
 | 
					            range.first_unicode_char_in_range = in_range[0];
 | 
				
			||||||
            range.num_chars_in_range = (in_range[1] - in_range[0]) + 1;
 | 
					            range.num_chars_in_range = (in_range[1] - in_range[0]) + 1;
 | 
				
			||||||
 | 
					            range.chardata_for_range = packed_chardata + packed_chardata_n;
 | 
				
			||||||
            // Allocate characters and flag as not packed
 | 
					            packed_chardata_n += range.num_chars_in_range;
 | 
				
			||||||
            // FIXME-OPT: Loose ranges will incur lots of allocations. Allocate all contiguous in loop above.
 | 
					 | 
				
			||||||
            range.chardata_for_range = (stbtt_packedchar*)ImGui::MemAlloc(range.num_chars_in_range * sizeof(stbtt_packedchar));
 | 
					 | 
				
			||||||
            for (int j = 0; j < range.num_chars_in_range; ++j)
 | 
					 | 
				
			||||||
                range.chardata_for_range[j].x0 = range.chardata_for_range[j].y0 = range.chardata_for_range[j].x1 = range.chardata_for_range[j].y1 = 0;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Pack
 | 
					        // Pack
 | 
				
			||||||
        data.Rects = (stbrp_rect*)ImGui::MemAlloc(sizeof(stbrp_rect) * glyph_count);
 | 
					        data.Rects = rectdata + rectdata_n;
 | 
				
			||||||
        IM_ASSERT(data.Rects);
 | 
					        rectdata_n += glyph_count;
 | 
				
			||||||
        const int n = stbtt_PackFontRangesGatherRects(&spc, &data.FontInfo, data.Ranges.begin(), data.Ranges.size(), data.Rects);
 | 
					        const int n = stbtt_PackFontRangesGatherRects(&spc, &data.FontInfo, data.Ranges.begin(), data.Ranges.size(), data.Rects);
 | 
				
			||||||
        stbrp_pack_rects((stbrp_context*)spc.pack_info, data.Rects, n);
 | 
					        stbrp_pack_rects((stbrp_context*)spc.pack_info, data.Rects, n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -6540,6 +6544,7 @@ bool    ImFontAtlas::Build()
 | 
				
			|||||||
            if (data.Rects[i].was_packed)
 | 
					            if (data.Rects[i].was_packed)
 | 
				
			||||||
                tex_height = ImMax(tex_height, data.Rects[i].y + data.Rects[i].h);
 | 
					                tex_height = ImMax(tex_height, data.Rects[i].y + data.Rects[i].h);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    IM_ASSERT(packed_chardata_n == total_glyph_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Create texture
 | 
					    // Create texture
 | 
				
			||||||
    TexHeight = ImUpperPowerOfTwo(tex_height);
 | 
					    TexHeight = ImUpperPowerOfTwo(tex_height);
 | 
				
			||||||
@@ -6553,12 +6558,13 @@ bool    ImFontAtlas::Build()
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        ImFontAtlasData& data = *InputData[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.begin(), data.Ranges.size(), data.Rects);
 | 
				
			||||||
        ImGui::MemFree(data.Rects);
 | 
					 | 
				
			||||||
        data.Rects = NULL;
 | 
					        data.Rects = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // End packing
 | 
					    // End packing
 | 
				
			||||||
    stbtt_PackEnd(&spc);
 | 
					    stbtt_PackEnd(&spc);
 | 
				
			||||||
 | 
					    ImGui::MemFree(rectdata);
 | 
				
			||||||
 | 
					    rectdata = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Third pass: setup ImFont and glyphs for runtime
 | 
					    // Third pass: setup ImFont and glyphs for runtime
 | 
				
			||||||
    for (size_t input_i = 0; input_i < InputData.size(); input_i++)
 | 
					    for (size_t input_i = 0; input_i < InputData.size(); input_i++)
 | 
				
			||||||
@@ -6601,18 +6607,19 @@ bool    ImFontAtlas::Build()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        data.OutFont->BuildLookupTable();
 | 
					        data.OutFont->BuildLookupTable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Cleanup temporary
 | 
					        // Cleanup temporaries
 | 
				
			||||||
        for (size_t i = 0; i < data.Ranges.size(); i++)
 | 
					 | 
				
			||||||
            ImGui::MemFree(data.Ranges[i].chardata_for_range);
 | 
					 | 
				
			||||||
        data.Ranges.clear();
 | 
					        data.Ranges.clear();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Cleanup temporaries
 | 
				
			||||||
 | 
					    ClearInputData();
 | 
				
			||||||
 | 
					    ImGui::MemFree(packed_chardata);
 | 
				
			||||||
 | 
					    packed_chardata = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Draw white pixel into texture and make UV points to it
 | 
					    // Draw white pixel into texture and make UV points to it
 | 
				
			||||||
    TexPixelsAlpha8[0] = TexPixelsAlpha8[1] = TexPixelsAlpha8[TexWidth+0] = TexPixelsAlpha8[TexWidth+1] = 0xFF;
 | 
					    TexPixelsAlpha8[0] = TexPixelsAlpha8[1] = TexPixelsAlpha8[TexWidth+0] = TexPixelsAlpha8[TexWidth+1] = 0xFF;
 | 
				
			||||||
    TexUvWhitePixel = ImVec2((TexExtraDataPos.x + 0.5f) / TexWidth, (TexExtraDataPos.y + 0.5f) / TexHeight);
 | 
					    TexUvWhitePixel = ImVec2((TexExtraDataPos.x + 0.5f) / TexWidth, (TexExtraDataPos.y + 0.5f) / TexHeight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ClearInputData();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user