mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-11-03 17:24:24 +00:00 
			
		
		
		
	Fonts: repack without full reload, discard rectangle, fixed CustomRect api with stable id, remove public BuildInit().
This commit is contained in:
		
							
								
								
									
										5
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								imgui.h
									
									
									
									
									
								
							@@ -3529,7 +3529,6 @@ struct ImFontAtlas
 | 
			
		||||
    IMGUI_API void              Clear();                    // Clear all input and output.
 | 
			
		||||
 | 
			
		||||
    IMGUI_API void              ClearCache();               // Clear cached glyphs
 | 
			
		||||
    IMGUI_API void              BuildInit();
 | 
			
		||||
 | 
			
		||||
    // Build atlas, retrieve pixel data.
 | 
			
		||||
    // User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID().
 | 
			
		||||
@@ -3583,7 +3582,7 @@ struct ImFontAtlas
 | 
			
		||||
    // - Note: this API may be redesigned later in order to support multi-monitor varying DPI settings.
 | 
			
		||||
    IMGUI_API int               AddCustomRectRegular(int width, int height);
 | 
			
		||||
    IMGUI_API int               AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0, 0));
 | 
			
		||||
    ImFontAtlasCustomRect*      GetCustomRectByIndex(int index) { IM_ASSERT(index >= 0); return &CustomRects[index]; }
 | 
			
		||||
    IMGUI_API ImFontAtlasCustomRect* GetCustomRectByIndex(int index);
 | 
			
		||||
 | 
			
		||||
    // [Internal]
 | 
			
		||||
    IMGUI_API void              CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const;
 | 
			
		||||
@@ -3608,8 +3607,8 @@ struct ImFontAtlas
 | 
			
		||||
    ImVec2                      TexUvScale;         // = (1.0f/TexData->TexWidth, 1.0f/TexData->TexHeight)
 | 
			
		||||
    ImVec2                      TexUvWhitePixel;    // Texture coordinates to a white pixel
 | 
			
		||||
    ImVector<ImFont*>           Fonts;              // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font.
 | 
			
		||||
    ImVector<ImFontAtlasCustomRect> CustomRects;    // Rectangles for packing custom texture data into the atlas.
 | 
			
		||||
    ImVector<ImFontConfig>      Sources;            // Source/configuration data
 | 
			
		||||
    //ImVector<ImFontAtlasCustomRect> CustomRects;  // Rectangles for packing custom texture data into the atlas.
 | 
			
		||||
    ImVec4                      TexUvLines[IM_DRAWLIST_TEX_LINES_WIDTH_MAX + 1];  // UVs for baked anti-aliased lines
 | 
			
		||||
    int                         TexNextUniqueID;    // Next value to be stored in TexData->UniqueID
 | 
			
		||||
    ImDrawListSharedData*       DrawListSharedData; // In principle this could become an array (e.g. multiple contexts using same atlas)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										207
									
								
								imgui_draw.cpp
									
									
									
									
									
								
							
							
						
						
									
										207
									
								
								imgui_draw.cpp
									
									
									
									
									
								
							@@ -2606,7 +2606,7 @@ void ImFontAtlas::ClearInputData()
 | 
			
		||||
            font->SourcesCount = 0;
 | 
			
		||||
        }
 | 
			
		||||
    Sources.clear();
 | 
			
		||||
    CustomRects.clear();
 | 
			
		||||
    //CustomRects.clear();
 | 
			
		||||
    // Important: we leave TexReady untouched
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2646,6 +2646,7 @@ void ImFontAtlas::Clear()
 | 
			
		||||
    ImFontAtlasBuildSetupFontLoader(this, font_loader);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME-NEWATLAS: Too widespread purpose. Clarify each call site in current WIP demo.
 | 
			
		||||
void ImFontAtlas::ClearCache()
 | 
			
		||||
{
 | 
			
		||||
    int tex_w = (TexData && TexData->Status != ImTextureStatus_WantDestroy) ? TexData->Width : 0;
 | 
			
		||||
@@ -2891,7 +2892,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
 | 
			
		||||
 | 
			
		||||
    // Lazily create builder on the first call to AddFont
 | 
			
		||||
    if (Builder == NULL)
 | 
			
		||||
        BuildInit();
 | 
			
		||||
        ImFontAtlasBuildInit(this);
 | 
			
		||||
 | 
			
		||||
    // Create new font
 | 
			
		||||
    if (!font_cfg->MergeMode)
 | 
			
		||||
@@ -3066,11 +3067,24 @@ int ImFontAtlas::AddCustomRectRegular(int width, int height)
 | 
			
		||||
{
 | 
			
		||||
    IM_ASSERT(width > 0 && width <= 0xFFFF);
 | 
			
		||||
    IM_ASSERT(height > 0 && height <= 0xFFFF);
 | 
			
		||||
    ImFontAtlasCustomRect r;
 | 
			
		||||
    r.Width = (unsigned short)width;
 | 
			
		||||
    r.Height = (unsigned short)height;
 | 
			
		||||
    CustomRects.push_back(r);
 | 
			
		||||
    return CustomRects.Size - 1; // Return index
 | 
			
		||||
 | 
			
		||||
    if (DrawListSharedData && DrawListSharedData->RendererHasTextures)
 | 
			
		||||
    {
 | 
			
		||||
        ImFontAtlasRectId r_id = ImFontAtlasPackAddRect(this, width, height);
 | 
			
		||||
        ImFontAtlasRect* r = ImFontAtlasPackGetRect(this, r_id);
 | 
			
		||||
        ImFontAtlasTextureBlockQueueUpload(this, TexData, r->x, r->y, r->w, r->h);
 | 
			
		||||
        return r_id;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        // FIXME-NEWATLAS-V1: Unfinished
 | 
			
		||||
        ImFontAtlasCustomRect r;
 | 
			
		||||
        r.Width = (unsigned short)width;
 | 
			
		||||
        r.Height = (unsigned short)height;
 | 
			
		||||
        //CustomRects.push_back(r);
 | 
			
		||||
        //return CustomRects.Size - 1; // Return index
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset)
 | 
			
		||||
@@ -3089,8 +3103,18 @@ int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int
 | 
			
		||||
    r.GlyphAdvanceX = advance_x;
 | 
			
		||||
    r.GlyphOffset = offset;
 | 
			
		||||
    r.Font = font;
 | 
			
		||||
    CustomRects.push_back(r);
 | 
			
		||||
    return CustomRects.Size - 1; // Return index
 | 
			
		||||
    //CustomRects.push_back(r);
 | 
			
		||||
    //return CustomRects.Size - 1; // Return index
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ImFontAtlasCustomRect* ImFontAtlas::GetCustomRectByIndex(int idx)
 | 
			
		||||
{
 | 
			
		||||
    IM_STATIC_ASSERT(offsetof(ImFontAtlasCustomRect, X) == offsetof(ImFontAtlasRect, x));
 | 
			
		||||
    IM_STATIC_ASSERT(offsetof(ImFontAtlasCustomRect, Y) == offsetof(ImFontAtlasRect, y));
 | 
			
		||||
    IM_STATIC_ASSERT(offsetof(ImFontAtlasCustomRect, Width) == offsetof(ImFontAtlasRect, w));
 | 
			
		||||
    IM_STATIC_ASSERT(offsetof(ImFontAtlasCustomRect, Height) == offsetof(ImFontAtlasRect, h));
 | 
			
		||||
    return (ImFontAtlasCustomRect*)(void*)ImFontAtlasPackGetRect(this, idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImFontAtlas::CalcCustomRectUV(const ImFontAtlasCustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max) const
 | 
			
		||||
@@ -3121,35 +3145,12 @@ bool ImFontAtlasGetMouseCursorTexData(ImFontAtlas* atlas, ImGuiMouseCursor curso
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImFontAtlas::BuildInit()
 | 
			
		||||
{
 | 
			
		||||
    // Select builder
 | 
			
		||||
    // - Note that we do not reassign to atlas->FontLoader, since it is likely to point to static data which
 | 
			
		||||
    //   may mess with some hot-reloading schemes. If you need to assign to this (for dynamic selection) AND are
 | 
			
		||||
    //   using a hot-reloading scheme that messes up static data, store your own instance of ImFontLoader somewhere
 | 
			
		||||
    //   and point to it instead of pointing directly to return value of the GetBackendIOXXX functions.
 | 
			
		||||
    if (FontLoader == NULL)
 | 
			
		||||
    {
 | 
			
		||||
#ifdef IMGUI_ENABLE_FREETYPE
 | 
			
		||||
        ImFontAtlasBuildSetupFontLoader(this, ImGuiFreeType::GetBackendIOForFreeType());
 | 
			
		||||
#elif defined(IMGUI_ENABLE_STB_TRUETYPE)
 | 
			
		||||
        ImFontAtlasBuildSetupFontLoader(this, ImFontAtlasGetFontLoaderForStbTruetype());
 | 
			
		||||
#else
 | 
			
		||||
        IM_ASSERT(0); // Invalid Build function
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Create initial texture size
 | 
			
		||||
    ImFontAtlasBuildAddTexture(this, 512, 128);
 | 
			
		||||
    ImFontAtlasBuildInit(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ImFontAtlas::Build()
 | 
			
		||||
{
 | 
			
		||||
    IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
 | 
			
		||||
 | 
			
		||||
    if (Builder == NULL)
 | 
			
		||||
        BuildInit();
 | 
			
		||||
        ImFontAtlasBuildInit(this);
 | 
			
		||||
 | 
			
		||||
    // Default font is none are specified
 | 
			
		||||
    if (Sources.Size == 0)
 | 
			
		||||
@@ -3222,6 +3223,8 @@ void ImFontAtlasBuildUpdatePointers(ImFontAtlas* atlas)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME-NEWATLAS: Unused
 | 
			
		||||
#if 0
 | 
			
		||||
void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opaque)
 | 
			
		||||
{
 | 
			
		||||
    ImTextureData* tex = atlas->TexData;
 | 
			
		||||
@@ -3253,6 +3256,7 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa
 | 
			
		||||
            tex->Height = ImMax(tex->Height, pack_rects[i].y + pack_rects[i].h);
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Render a white-colored bitmap encoded in a string
 | 
			
		||||
void ImFontAtlasBuildRenderBitmapFromString(ImFontAtlas* atlas, int x, int y, int w, int h, const char* in_str, char in_marker_char)
 | 
			
		||||
@@ -3476,6 +3480,28 @@ void ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFontConfig* sr
 | 
			
		||||
    font->LockSingleSrcConfigIdx = -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImFontAtlasBuildReloadFont(ImFontAtlas* atlas, ImFont* font)
 | 
			
		||||
{
 | 
			
		||||
    for (ImFontGlyph& glyph : font->Glyphs)
 | 
			
		||||
        if (glyph.PackId >= 0)
 | 
			
		||||
            ImFontAtlasPackDiscardRect(atlas, glyph.PackId);
 | 
			
		||||
    font->BuildClearGlyphs();
 | 
			
		||||
 | 
			
		||||
    for (int src_n = 0; src_n < font->SourcesCount; src_n++)
 | 
			
		||||
    {
 | 
			
		||||
        ImFontConfig* src = (ImFontConfig*)(void*)&font->Sources[src_n];
 | 
			
		||||
        IM_ASSERT(src->SizePixels > 0.0f);
 | 
			
		||||
 | 
			
		||||
        // Reload font in backend
 | 
			
		||||
        if (atlas->FontLoader && atlas->FontLoader->FontSrcDestroy != NULL)
 | 
			
		||||
            atlas->FontLoader->FontSrcDestroy(atlas, src);
 | 
			
		||||
        if (atlas->FontLoader && atlas->FontLoader->FontSrcInit != NULL)
 | 
			
		||||
            atlas->FontLoader->FontSrcInit(atlas, src);
 | 
			
		||||
 | 
			
		||||
        ImFontAtlasBuildSetupFontSpecialGlyphs(atlas, src); // Technically this is called for each source sub-font, tho 99.9% of the time the first one fills everything.
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Those functions are designed to facilitate changing the underlying structures for ImFontAtlas to store an array of ImDrawListSharedData*
 | 
			
		||||
void ImFontAtlasAddDrawListSharedData(ImFontAtlas* atlas, ImDrawListSharedData* data)
 | 
			
		||||
{
 | 
			
		||||
@@ -3588,29 +3614,40 @@ void ImFontAtlasBuildRepackTexture(ImFontAtlas* atlas, int w, int h)
 | 
			
		||||
 | 
			
		||||
    // FIXME-NEWATLAS-TESTS: Test calling RepackTexture with size too small to fits existing rects.
 | 
			
		||||
 | 
			
		||||
    // Repack + copy pixels
 | 
			
		||||
    // Repack, lose discarded rectangle, copy pixels
 | 
			
		||||
    // FIXME-NEWATLAS-V2: Repacking in batch would be beneficial to packing heuristic.
 | 
			
		||||
    ImFontAtlasPackInit(atlas);
 | 
			
		||||
    ImVector<ImFontAtlasRect> old_rects;
 | 
			
		||||
    ImVector<ImFontAtlasRectEntry> old_index = builder->RectsIndex;
 | 
			
		||||
    old_rects.swap(builder->Rects);
 | 
			
		||||
    for (ImFontAtlasRect& old_r : old_rects)
 | 
			
		||||
 | 
			
		||||
    for (ImFontAtlasRectEntry& index_entry : builder->RectsIndex)
 | 
			
		||||
    {
 | 
			
		||||
        ImFontAtlasRectId new_r_id = ImFontAtlasPackAddRect(atlas, old_r.w, old_r.h);
 | 
			
		||||
        if (index_entry.Used == false)
 | 
			
		||||
            continue;
 | 
			
		||||
        ImFontAtlasRect& old_r = old_rects[index_entry.TargetIndex];
 | 
			
		||||
        if (old_r.w == 0 && old_r.h == 0)
 | 
			
		||||
            continue;
 | 
			
		||||
        ImFontAtlasRectId new_r_id = ImFontAtlasPackAddRect(atlas, old_r.w, old_r.h, &index_entry);
 | 
			
		||||
        if (new_r_id == -1)
 | 
			
		||||
        {
 | 
			
		||||
            // Undo, grow texture and try repacking again.
 | 
			
		||||
            // FIXME-NEWATLAS-TESTS: This is a very rarely exercised path! It needs to be automatically tested properly.
 | 
			
		||||
            IMGUI_DEBUG_LOG_FONT("[font] Texture #%03d: resize failed. Will grow.\n", new_tex->UniqueID);
 | 
			
		||||
            new_tex->WantDestroyNextFrame = true;
 | 
			
		||||
            old_rects.swap(builder->Rects);
 | 
			
		||||
            builder->Rects.swap(old_rects);
 | 
			
		||||
            builder->RectsIndex = old_index;
 | 
			
		||||
            ImFontAtlasBuildSetTexture(atlas, old_tex);
 | 
			
		||||
            ImFontAtlasBuildGrowTexture(atlas, w, h);
 | 
			
		||||
            ImFontAtlasBuildGrowTexture(atlas, w, h); // Recurse
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        IM_ASSERT(new_r_id == builder->RectsIndex.index_from_ptr(&index_entry));
 | 
			
		||||
        ImFontAtlasRect* new_r = ImFontAtlasPackGetRect(atlas, new_r_id);
 | 
			
		||||
        ImFontAtlasTextureBlockCopy(old_tex, old_r.x, old_r.y, new_tex, new_r->x, new_r->y, new_r->w, new_r->h);
 | 
			
		||||
    }
 | 
			
		||||
    IM_ASSERT(old_rects.Size == builder->Rects.Size);
 | 
			
		||||
    IM_ASSERT(old_rects.Size == builder->Rects.Size + builder->RectsDiscardedCount);
 | 
			
		||||
    builder->RectsDiscardedCount = 0;
 | 
			
		||||
    builder->RectsDiscardedSurface = 0;
 | 
			
		||||
 | 
			
		||||
    // Patch glyphs UV
 | 
			
		||||
    for (ImFont* font : atlas->Fonts)
 | 
			
		||||
@@ -3645,6 +3682,7 @@ void ImFontAtlasBuildGrowTexture(ImFontAtlas* atlas, int old_tex_w, int old_tex_
 | 
			
		||||
    IM_ASSERT(ImIsPowerOfTwo(old_tex_w) && ImIsPowerOfTwo(old_tex_h));
 | 
			
		||||
 | 
			
		||||
    // Grow texture so it follows roughly a square.
 | 
			
		||||
    // FIXME-NEWATLAS-V1: Take account of RectsDiscardedSurface: may not need to grow.
 | 
			
		||||
    int new_tex_w = (old_tex_h < old_tex_w) ? old_tex_w : old_tex_w * 2;
 | 
			
		||||
    int new_tex_h = (old_tex_h < old_tex_w) ? old_tex_h * 2 : old_tex_h;
 | 
			
		||||
 | 
			
		||||
@@ -3669,14 +3707,15 @@ void ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas)
 | 
			
		||||
    // FIXME-NEWATLAS: Expose atlas->TexMinWidth etc.
 | 
			
		||||
    const int min_w = ImMax(builder->MaxRectSize.x, 512);
 | 
			
		||||
    const int min_h = builder->MaxRectSize.y;
 | 
			
		||||
    const int surface_sqrt = (int)sqrtf((float)atlas->_PackedSurface);
 | 
			
		||||
    const int surface_approx = atlas->_PackedSurface - builder->RectsDiscardedSurface; // Expected surface after repack
 | 
			
		||||
    const int surface_sqrt = (int)sqrtf((float)surface_approx);
 | 
			
		||||
 | 
			
		||||
    int new_tex_w;
 | 
			
		||||
    int new_tex_h;
 | 
			
		||||
    if (min_w >= min_h)
 | 
			
		||||
    {
 | 
			
		||||
        new_tex_w = ImMax(min_w, ImUpperPowerOfTwo(surface_sqrt));
 | 
			
		||||
        new_tex_h = ImMax(min_h, (int)(atlas->_PackedSurface / new_tex_w));
 | 
			
		||||
        new_tex_h = ImMax(min_h, (int)((surface_approx + new_tex_w - 1) / new_tex_w));
 | 
			
		||||
        if ((atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) == 0)
 | 
			
		||||
            new_tex_h = ImUpperPowerOfTwo(new_tex_h);
 | 
			
		||||
    }
 | 
			
		||||
@@ -3685,10 +3724,10 @@ void ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas)
 | 
			
		||||
        new_tex_h = ImMax(min_h, ImUpperPowerOfTwo(surface_sqrt));
 | 
			
		||||
        if ((atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) == 0)
 | 
			
		||||
            new_tex_h = ImUpperPowerOfTwo(new_tex_h);
 | 
			
		||||
        new_tex_w = ImMax(min_w, (int)(atlas->_PackedSurface / new_tex_h));
 | 
			
		||||
        new_tex_w = ImMax(min_w, (int)((surface_approx + new_tex_h - 1) / new_tex_h));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (new_tex_w == old_tex_w && new_tex_h == old_tex_h)
 | 
			
		||||
    if (builder->RectsDiscardedCount == 0 && new_tex_w == old_tex_w && new_tex_h == old_tex_h)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    ImFontAtlasBuildRepackTexture(atlas, new_tex_w, new_tex_h);
 | 
			
		||||
@@ -3699,6 +3738,25 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas)
 | 
			
		||||
{
 | 
			
		||||
    ImFontAtlasBuilder* builder = atlas->Builder;
 | 
			
		||||
 | 
			
		||||
    // Select Backend
 | 
			
		||||
    // - Note that we do not reassign to atlas->FontBackendIO, since it is likely to point to static data which
 | 
			
		||||
    //   may mess with some hot-reloading schemes. If you need to assign to this (for dynamic selection) AND are
 | 
			
		||||
    //   using a hot-reloading scheme that messes up static data, store your own instance of ImFontBackendIO somewhere
 | 
			
		||||
    //   and point to it instead of pointing directly to return value of the GetBackendIOXXX functions.
 | 
			
		||||
    if (atlas->FontLoader == NULL)
 | 
			
		||||
    {
 | 
			
		||||
#ifdef IMGUI_ENABLE_FREETYPE
 | 
			
		||||
        ImFontAtlasBuildSetupFontLoader(atlas, ImGuiFreeType::GetFontLoader());
 | 
			
		||||
#elif defined(IMGUI_ENABLE_STB_TRUETYPE)
 | 
			
		||||
        ImFontAtlasBuildSetupFontLoader(atlas, ImFontAtlasGetFontLoaderForStbTruetype());
 | 
			
		||||
#else
 | 
			
		||||
        IM_ASSERT(0); // Invalid Build function
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    // Create initial texture size
 | 
			
		||||
    if (atlas->TexData == NULL)
 | 
			
		||||
        ImFontAtlasBuildAddTexture(atlas, 512, 128);
 | 
			
		||||
 | 
			
		||||
    const bool builder_is_new = (builder == NULL);
 | 
			
		||||
    if (builder_is_new)
 | 
			
		||||
        builder = atlas->Builder = IM_NEW(ImFontAtlasBuilder)();
 | 
			
		||||
@@ -3736,7 +3794,7 @@ void ImFontAtlasBuildDestroy(ImFontAtlas* atlas)
 | 
			
		||||
    atlas->Builder = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ImFontAtlasPackInit(ImFontAtlas* atlas)
 | 
			
		||||
void ImFontAtlasPackInit(ImFontAtlas * atlas)
 | 
			
		||||
{
 | 
			
		||||
    ImTextureData* tex = atlas->TexData;
 | 
			
		||||
    ImFontAtlasBuilder* builder = atlas->Builder;
 | 
			
		||||
@@ -3751,9 +3809,52 @@ void ImFontAtlasPackInit(ImFontAtlas* atlas)
 | 
			
		||||
    builder->MaxRectBounds = ImVec2i(0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This is essentially a free-list pattern, it may be nice to wrap it into a dedicated type.
 | 
			
		||||
static ImFontAtlasRectId ImFontAtlasPackAllocRectEntry(ImFontAtlas* atlas, int rect_idx)
 | 
			
		||||
{
 | 
			
		||||
    ImFontAtlasBuilder* builder = (ImFontAtlasBuilder*)atlas->Builder;
 | 
			
		||||
    int index_idx;
 | 
			
		||||
    ImFontAtlasRectEntry* index_entry;
 | 
			
		||||
    if (builder->RectsIndexFreeListStart < 0)
 | 
			
		||||
    {
 | 
			
		||||
        builder->RectsIndex.resize(builder->RectsIndex.Size + 1);
 | 
			
		||||
        index_idx = builder->RectsIndex.Size - 1;
 | 
			
		||||
        index_entry = &builder->RectsIndex[index_idx];
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        index_idx = builder->RectsIndexFreeListStart;
 | 
			
		||||
        index_entry = &builder->RectsIndex[index_idx];
 | 
			
		||||
        IM_ASSERT(index_entry->Used == false);
 | 
			
		||||
        builder->RectsIndexFreeListStart = index_entry->TargetIndex;
 | 
			
		||||
    }
 | 
			
		||||
    index_entry->TargetIndex = rect_idx;
 | 
			
		||||
    index_entry->Used = 1;
 | 
			
		||||
    return (ImFontAtlasRectId)index_idx;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This is expected to be called in batches and followed by a repack
 | 
			
		||||
void ImFontAtlasPackDiscardRect(ImFontAtlas* atlas, ImFontAtlasRectId id)
 | 
			
		||||
{
 | 
			
		||||
    IM_ASSERT(id >= 0);
 | 
			
		||||
    ImFontAtlasBuilder* builder = (ImFontAtlasBuilder*)atlas->Builder;
 | 
			
		||||
    ImFontAtlasRectEntry* index_entry = &builder->RectsIndex[id];
 | 
			
		||||
    IM_ASSERT(index_entry->Used && index_entry->TargetIndex >= 0);
 | 
			
		||||
 | 
			
		||||
    ImFontAtlasRect* rect = ImFontAtlasPackGetRect(atlas, id);
 | 
			
		||||
    index_entry->Used = false;
 | 
			
		||||
    index_entry->TargetIndex = builder->RectsIndexFreeListStart;
 | 
			
		||||
 | 
			
		||||
    const int pack_padding = atlas->TexGlyphPadding;
 | 
			
		||||
    builder->RectsIndexFreeListStart = id;
 | 
			
		||||
    builder->RectsDiscardedCount++;
 | 
			
		||||
    builder->RectsDiscardedSurface += (rect->w + pack_padding) * (rect->h + pack_padding);
 | 
			
		||||
    rect->w = rect->h = 0; // Clear rectangle so it won't be packed again
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Important: Calling this may recreate a new texture and therefore change atlas->TexData
 | 
			
		||||
// FIXME-NEWATLAS-V2: Expose other glyph padding settings for custom alteration (e.g. drop shadows). See #7962
 | 
			
		||||
ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h)
 | 
			
		||||
ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h, ImFontAtlasRectEntry* overwrite_entry)
 | 
			
		||||
{
 | 
			
		||||
    IM_ASSERT(w > 0 && w <= 0xFFFF);
 | 
			
		||||
    IM_ASSERT(h > 0 && h <= 0xFFFF);
 | 
			
		||||
@@ -3796,13 +3897,25 @@ ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h)
 | 
			
		||||
    atlas->_PackedRects++;
 | 
			
		||||
 | 
			
		||||
    builder->Rects.push_back(r);
 | 
			
		||||
    return builder->Rects.Size - 1;
 | 
			
		||||
    if (overwrite_entry != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        // Write into an existing entry instead of adding one (used during repack)
 | 
			
		||||
        IM_ASSERT(overwrite_entry->Used);
 | 
			
		||||
        overwrite_entry->TargetIndex = builder->Rects.Size - 1;
 | 
			
		||||
        return builder->RectsIndex.index_from_ptr(overwrite_entry);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        return ImFontAtlasPackAllocRectEntry(atlas, builder->Rects.Size - 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ImFontAtlasRect* ImFontAtlasPackGetRect(ImFontAtlas* atlas, ImFontAtlasRectId id)
 | 
			
		||||
{
 | 
			
		||||
    ImFontAtlasBuilder* builder = (ImFontAtlasBuilder*)atlas->Builder;
 | 
			
		||||
    return &builder->Rects[id];
 | 
			
		||||
    ImFontAtlasRectEntry* index_entry = &builder->RectsIndex[id];
 | 
			
		||||
    IM_ASSERT(index_entry->Used);
 | 
			
		||||
    return &builder->Rects[index_entry->TargetIndex];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ImFontGlyph* ImFont::BuildLoadGlyph(ImWchar codepoint)
 | 
			
		||||
 
 | 
			
		||||
@@ -142,6 +142,7 @@ struct ImGuiTextIndex;              // Maintain a line index for a text buffer.
 | 
			
		||||
struct ImDrawDataBuilder;           // Helper to build a ImDrawData instance
 | 
			
		||||
struct ImDrawListSharedData;        // Data shared between all ImDrawList instances
 | 
			
		||||
struct ImFontAtlasRect;             // Packed rectangle (same as ImTextureRect)
 | 
			
		||||
struct ImFontAtlasRectEntry;        // Packed rectangle lookup entry
 | 
			
		||||
struct ImFontAtlasBuilder;          // Internal storage for incrementally packing and building a ImFontAtlas
 | 
			
		||||
 | 
			
		||||
// ImGui
 | 
			
		||||
@@ -3639,7 +3640,6 @@ IMGUI_API const ImFontLoader* ImFontAtlasGetFontLoaderForStbTruetype();
 | 
			
		||||
// [SECTION] ImFontAtlas internal API
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
// Packed rectangle (same as ImTextureRect)
 | 
			
		||||
struct ImFontAtlasRect
 | 
			
		||||
{
 | 
			
		||||
    unsigned short  x, y;
 | 
			
		||||
@@ -3647,6 +3647,17 @@ struct ImFontAtlasRect
 | 
			
		||||
};
 | 
			
		||||
typedef int ImFontAtlasRectId;          // <0 when invalid
 | 
			
		||||
 | 
			
		||||
// Packed rectangle lookup entry (we need an indirection to allow removing/reordering rectangles)
 | 
			
		||||
// User are returned ImFontAtlasRectId values which are meant to be persistent.
 | 
			
		||||
// We handle this with an indirection. While Rects[] may be in theory shuffled, compacted etc., RectsIndex[] cannot it is keyed by ImFontAtlasRectId.
 | 
			
		||||
// RectsIndex[] is used both as an index into Rects[] and an index into itself. This is basically a free-list. See ImFontAtlasBuildAllocRectIndexEntry() code.
 | 
			
		||||
// Having this also makes it easier to e.g. sort rectangles during repack.
 | 
			
		||||
struct ImFontAtlasRectEntry
 | 
			
		||||
{
 | 
			
		||||
    int             TargetIndex : 31; // When Used: ImFontAtlasRectId -> into Rects[]. When unused: index to next unused RectsIndex[] slot to consume free-list.
 | 
			
		||||
    unsigned int    Used : 1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Internal storage for incrementally packing and building a ImFontAtlas
 | 
			
		||||
struct stbrp_context_opaque { char data[80]; };
 | 
			
		||||
struct stbrp_node;
 | 
			
		||||
@@ -3655,7 +3666,11 @@ struct ImFontAtlasBuilder
 | 
			
		||||
    stbrp_context_opaque        PackContext;            // Actually 'stbrp_context' but we don't want to define this in the header file.
 | 
			
		||||
    ImVector<stbrp_node>        PackNodes;
 | 
			
		||||
    ImVector<ImFontAtlasRect>   Rects;
 | 
			
		||||
    ImVector<ImFontAtlasRectEntry> RectsIndex;          // ImFontAtlasRectId -> index into Rects[]
 | 
			
		||||
    ImVector<unsigned char>     TempBuffer;             // Misc scratch buffer
 | 
			
		||||
    int                         RectsIndexFreeListStart;// First unused entry
 | 
			
		||||
    int                         RectsDiscardedCount;
 | 
			
		||||
    int                         RectsDiscardedSurface;
 | 
			
		||||
    ImVec2i                     MaxRectSize;            // Largest rectangle to pack (de-facto used as a "minimum texture size")
 | 
			
		||||
    ImVec2i                     MaxRectBounds;          // Bottom-right most used pixels
 | 
			
		||||
    bool                        LockDisableResize;      // Disable resizing texture
 | 
			
		||||
@@ -3665,7 +3680,7 @@ struct ImFontAtlasBuilder
 | 
			
		||||
    ImFontAtlasRectId           PackIdMouseCursors;     // White pixel + mouse cursors. Also happen to be fallback in case of packing failure.
 | 
			
		||||
    ImFontAtlasRectId           PackIdLinesTexData;
 | 
			
		||||
 | 
			
		||||
    ImFontAtlasBuilder()        { memset(this, 0, sizeof(*this)); }
 | 
			
		||||
    ImFontAtlasBuilder()        { memset(this, 0, sizeof(*this)); RectsIndexFreeListStart = -1; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// FIXME-NEWATLAS: Cleanup
 | 
			
		||||
@@ -3683,11 +3698,13 @@ IMGUI_API void              ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas);
 | 
			
		||||
 | 
			
		||||
IMGUI_API bool              ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src);
 | 
			
		||||
IMGUI_API void              ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFontConfig* src);
 | 
			
		||||
IMGUI_API void              ImFontAtlasBuildReloadFont(ImFontAtlas* atlas, ImFont* font);
 | 
			
		||||
IMGUI_API void              ImFontAtlasBuildPreloadAllGlyphRanges(ImFontAtlas* atlas); // Legacy
 | 
			
		||||
IMGUI_API void              ImFontAtlasBuildGetOversampleFactors(ImFontConfig* src, int* out_oversample_h, int* out_oversample_v);
 | 
			
		||||
 | 
			
		||||
IMGUI_API void              ImFontAtlasPackInit(ImFontAtlas* atlas);
 | 
			
		||||
IMGUI_API ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h);
 | 
			
		||||
IMGUI_API ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h, ImFontAtlasRectEntry* overwrite_entry = NULL);
 | 
			
		||||
IMGUI_API void              ImFontAtlasPackDiscardRect(ImFontAtlas* atlas, ImFontAtlasRectId id);
 | 
			
		||||
IMGUI_API ImFontAtlasRect*  ImFontAtlasPackGetRect(ImFontAtlas* atlas, ImFontAtlasRectId id);
 | 
			
		||||
 | 
			
		||||
IMGUI_API void              ImFontAtlasAddDrawListSharedData(ImFontAtlas* atlas, ImDrawListSharedData* data);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user