mirror of
https://github.com/ocornut/imgui.git
synced 2026-01-03 12:02:33 +00:00
Fonts: encode additional data in ImFontAtlasRectId to detect invalid id + added Rects debug browser.
This commit is contained in:
@@ -3238,7 +3238,8 @@ ImFontAtlasRectId ImFontAtlas::AddCustomRect(int width, int height, ImFontAtlasR
|
||||
|
||||
void ImFontAtlas::RemoveCustomRect(ImFontAtlasRectId id)
|
||||
{
|
||||
IM_ASSERT(id != ImFontAtlasRectId_Invalid);
|
||||
if (ImFontAtlasPackGetRectSafe(this, id) == NULL)
|
||||
return;
|
||||
ImFontAtlasPackDiscardRect(this, id);
|
||||
}
|
||||
|
||||
@@ -3294,10 +3295,12 @@ int ImFontAtlas::AddCustomRectFontGlyphForSize(ImFont* font, float font_size, Im
|
||||
|
||||
bool ImFontAtlas::GetCustomRect(ImFontAtlasRectId id, ImFontAtlasRect* out_r) const
|
||||
{
|
||||
ImTextureRect* r = ImFontAtlasPackGetRect((ImFontAtlas*)this, id);
|
||||
ImTextureRect* r = ImFontAtlasPackGetRectSafe((ImFontAtlas*)this, id);
|
||||
if (r == NULL)
|
||||
return false;
|
||||
IM_ASSERT(TexData->Width > 0 && TexData->Height > 0); // Font atlas needs to be built before we can calculate UV coordinates
|
||||
if (out_r == NULL)
|
||||
return true;
|
||||
out_r->x = r->x;
|
||||
out_r->y = r->y;
|
||||
out_r->w = r->w;
|
||||
@@ -4001,7 +4004,7 @@ void ImFontAtlasBuildRepackTexture(ImFontAtlas* atlas, int w, int h)
|
||||
ImFontAtlasBuildGrowTexture(atlas, w, h); // Recurse
|
||||
return;
|
||||
}
|
||||
IM_ASSERT(new_r_id == builder->RectsIndex.index_from_ptr(&index_entry));
|
||||
IM_ASSERT(ImFontAtlasRectId_GetIndex(new_r_id) == builder->RectsIndex.index_from_ptr(&index_entry));
|
||||
ImTextureRect* 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);
|
||||
}
|
||||
@@ -4230,17 +4233,18 @@ static ImFontAtlasRectId ImFontAtlasPackAllocRectEntry(ImFontAtlas* atlas, int r
|
||||
builder->RectsIndex.resize(builder->RectsIndex.Size + 1);
|
||||
index_idx = builder->RectsIndex.Size - 1;
|
||||
index_entry = &builder->RectsIndex[index_idx];
|
||||
memset(index_entry, 0, sizeof(*index_entry));
|
||||
}
|
||||
else
|
||||
{
|
||||
index_idx = builder->RectsIndexFreeListStart;
|
||||
index_entry = &builder->RectsIndex[index_idx];
|
||||
IM_ASSERT(index_entry->IsUsed == false);
|
||||
IM_ASSERT(index_entry->IsUsed == false && index_entry->Generation > 0); // Generation is incremented during DiscardRect
|
||||
builder->RectsIndexFreeListStart = index_entry->TargetIndex;
|
||||
}
|
||||
index_entry->TargetIndex = rect_idx;
|
||||
index_entry->IsUsed = 1;
|
||||
return (ImFontAtlasRectId)index_idx;
|
||||
return ImFontAtlasRectId_Make(index_idx, index_entry->Generation);
|
||||
}
|
||||
|
||||
// Overwrite existing entry
|
||||
@@ -4248,23 +4252,29 @@ static ImFontAtlasRectId ImFontAtlasPackReuseRectEntry(ImFontAtlas* atlas, ImFon
|
||||
{
|
||||
IM_ASSERT(index_entry->IsUsed);
|
||||
index_entry->TargetIndex = atlas->Builder->Rects.Size - 1;
|
||||
return atlas->Builder->RectsIndex.index_from_ptr(index_entry);
|
||||
int index_idx = atlas->Builder->RectsIndex.index_from_ptr(index_entry);
|
||||
return ImFontAtlasRectId_Make(index_idx, index_entry->Generation);
|
||||
}
|
||||
|
||||
// This is expected to be called in batches and followed by a repack
|
||||
void ImFontAtlasPackDiscardRect(ImFontAtlas* atlas, ImFontAtlasRectId id)
|
||||
{
|
||||
IM_ASSERT(id != ImFontAtlasRectId_Invalid);
|
||||
ImFontAtlasBuilder* builder = (ImFontAtlasBuilder*)atlas->Builder;
|
||||
ImFontAtlasRectEntry* index_entry = &builder->RectsIndex[id];
|
||||
IM_ASSERT(index_entry->IsUsed && index_entry->TargetIndex >= 0);
|
||||
|
||||
ImTextureRect* rect = ImFontAtlasPackGetRect(atlas, id);
|
||||
if (rect == NULL)
|
||||
return;
|
||||
|
||||
ImFontAtlasBuilder* builder = atlas->Builder;
|
||||
int index_idx = ImFontAtlasRectId_GetIndex(id);
|
||||
ImFontAtlasRectEntry* index_entry = &builder->RectsIndex[index_idx];
|
||||
IM_ASSERT(index_entry->IsUsed && index_entry->TargetIndex >= 0);
|
||||
index_entry->IsUsed = false;
|
||||
index_entry->TargetIndex = builder->RectsIndexFreeListStart;
|
||||
index_entry->Generation++;
|
||||
|
||||
const int pack_padding = atlas->TexGlyphPadding;
|
||||
builder->RectsIndexFreeListStart = id;
|
||||
builder->RectsIndexFreeListStart = index_idx;
|
||||
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
|
||||
@@ -4319,16 +4329,36 @@ ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h, ImFon
|
||||
return ImFontAtlasPackAllocRectEntry(atlas, builder->Rects.Size - 1);
|
||||
}
|
||||
|
||||
// Important: return pointer is valid until next call to AddRect(), e.g. FindGlyph(), CalcTextSize() can all potentially invalidate previous pointers.
|
||||
// Generally for non-user facing functions: assert on invalid ID.
|
||||
ImTextureRect* ImFontAtlasPackGetRect(ImFontAtlas* atlas, ImFontAtlasRectId id)
|
||||
{
|
||||
IM_ASSERT(id != ImFontAtlasRectId_Invalid);
|
||||
int index_idx = ImFontAtlasRectId_GetIndex(id);
|
||||
int generation = ImFontAtlasRectId_GetGeneration(id);
|
||||
ImFontAtlasBuilder* builder = (ImFontAtlasBuilder*)atlas->Builder;
|
||||
ImFontAtlasRectEntry* index_entry = &builder->RectsIndex[id];
|
||||
ImFontAtlasRectEntry* index_entry = &builder->RectsIndex[index_idx];
|
||||
IM_ASSERT(index_entry->Generation == generation);
|
||||
IM_ASSERT(index_entry->IsUsed);
|
||||
return &builder->Rects[index_entry->TargetIndex];
|
||||
}
|
||||
|
||||
// For user-facing functions: return NULL on invalid ID.
|
||||
// Important: return pointer is valid until next call to AddRect(), e.g. FindGlyph(), CalcTextSize() can all potentially invalidate previous pointers.
|
||||
ImTextureRect* ImFontAtlasPackGetRectSafe(ImFontAtlas* atlas, ImFontAtlasRectId id)
|
||||
{
|
||||
if (id == ImFontAtlasRectId_Invalid)
|
||||
return NULL;
|
||||
int index_idx = ImFontAtlasRectId_GetIndex(id);
|
||||
int generation = ImFontAtlasRectId_GetGeneration(id);
|
||||
ImFontAtlasBuilder* builder = (ImFontAtlasBuilder*)atlas->Builder;
|
||||
if (index_idx >= builder->RectsIndex.Size)
|
||||
return NULL;
|
||||
ImFontAtlasRectEntry* index_entry = &builder->RectsIndex[index_idx];
|
||||
if (index_entry->Generation != generation || !index_entry->IsUsed)
|
||||
return NULL;
|
||||
return &builder->Rects[index_entry->TargetIndex];
|
||||
}
|
||||
|
||||
// Important! This assume by ImFontConfig::GlyphFilter is a SMALL ARRAY (e.g. <10 entries)
|
||||
static bool ImFontAtlasBuildAcceptCodepointForSource(ImFontConfig* src, ImWchar codepoint)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user