Fonts: Baked system, with auto-bind, v10.

# Conflicts:
#	imgui_internal.h
This commit is contained in:
ocornut
2025-01-23 15:46:22 +01:00
parent 7aba8da551
commit 093d01269a
7 changed files with 545 additions and 296 deletions
+60 -34
View File
@@ -3738,7 +3738,8 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
const float font_size = draw_list->_Data->FontSize;
const float font_scale = draw_list->_Data->FontScale;
const char* text_end_ellipsis = NULL;
const float ellipsis_width = font->GetCharAdvance(font->EllipsisChar) * font_scale;
ImFontBaked* baked = font->GetFontBaked(font_size);
const float ellipsis_width = baked->GetCharAdvance(font->EllipsisChar) * font_scale;
// We can now claim the space between pos_max.x and ellipsis_max.x
const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_width) - pos_min.x, 1.0f);
@@ -3939,7 +3940,8 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
Initialized = false;
FontAtlasOwnedByContext = shared_font_atlas ? false : true;
Font = NULL;
FontSize = FontBaseSize = FontScale = CurrentDpiScale = 0.0f;
FontBaked = NULL;
FontSize = /*FontBaseSize = */FontScale = CurrentDpiScale = 0.0f;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
IO.Fonts->RefCount++;
Time = 0.0f;
@@ -4275,6 +4277,7 @@ void ImGui::Shutdown()
g.MenusIdSubmittedThisFrame.clear();
g.InputTextState.ClearFreeMemory();
g.InputTextDeactivatedState.ClearFreeMemory();
g.InputTextPasswordFont.ContainerAtlas = NULL;
g.SettingsWindows.clear();
g.SettingsHandlers.clear();
@@ -4371,8 +4374,9 @@ static void SetCurrentWindow(ImGuiWindow* window)
g.CurrentDpiScale = 1.0f; // FIXME-DPI: WIP this is modified in docking
if (window)
{
g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
g.FontScale = g.DrawListSharedData.FontScale = g.FontSize / g.Font->FontSize;
// FIXME-BAKED
//g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
//g.FontScale = g.DrawListSharedData.FontScale = g.FontSize / g.Font->FontSize;
ImGui::NavUpdateCurrentWindowIsScrollPushableX();
}
}
@@ -5186,7 +5190,7 @@ static void ImGui::UpdateTexturesNewFrame()
if (g.FontAtlasOwnedByContext)
{
atlas->RendererHasTextures = (g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) != 0;
ImFontAtlasUpdateNewFrame(atlas);
ImFontAtlasUpdateNewFrame(atlas, g.FrameCount);
}
}
@@ -8399,11 +8403,14 @@ ImVec2 ImGui::GetFontTexUvWhitePixel()
void ImGui::SetWindowFontScale(float scale)
{
IM_ASSERT(scale > 0.0f);
// FIXME-BAKED
/*
ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
window->FontWindowScale = scale;
g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
g.FontScale = g.DrawListSharedData.FontScale = g.FontSize / g.Font->FontSize;
*/
}
void ImGui::PushFocusScope(ImGuiID id)
@@ -8570,20 +8577,21 @@ void ImGui::UpdateFontsNewFrame()
ImGuiContext& g = *GImGui;
if ((g.IO.BackendFlags & ImGuiBackendFlags_RendererHasTextures) == 0)
g.IO.Fonts->Locked = true;
SetCurrentFont(GetDefaultFont());
SetCurrentFont(GetDefaultFont(), GetDefaultFont()->Sources[0].SizePixels);
IM_ASSERT(g.Font->IsLoaded());
}
// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only.
void ImGui::SetCurrentFont(ImFont* font)
void ImGui::SetCurrentFont(ImFont* font, float font_size)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
IM_ASSERT(font->Scale > 0.0f);
g.Font = font;
g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale);
g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
g.FontScale = g.FontSize / g.Font->FontSize;
//g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.FontBaked->Size * g.Font->Scale);
g.FontSize = font_size;// g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f;
g.FontBaked = g.Font->GetFontBaked(g.FontSize);
g.FontScale = g.FontSize / g.FontBaked->Size;
g.DrawListSharedData.Font = g.Font;
g.DrawListSharedData.FontSize = g.FontSize;
g.DrawListSharedData.FontScale = g.FontScale;
@@ -8606,7 +8614,7 @@ void ImGui::PushFont(ImFont* font)
if (font == NULL)
font = GetDefaultFont();
g.FontStack.push_back(font);
SetCurrentFont(font);
SetCurrentFont(font, g.FontSize);
}
void ImGui::PopFont()
@@ -8619,7 +8627,14 @@ void ImGui::PopFont()
}
g.FontStack.pop_back();
ImFont* font = g.FontStack.Size == 0 ? GetDefaultFont() : g.FontStack.back();
SetCurrentFont(font);
SetCurrentFont(font, g.FontSize); // FIXME-BAKED: size in stack
}
void ImGui::SetFontSize(float size)
{
// FIXME-BAKED
ImGuiContext& g = *GImGui;
SetCurrentFont(g.Font, size);
}
//-----------------------------------------------------------------------------
@@ -15512,7 +15527,7 @@ void ImGui::DebugTextEncoding(const char* str)
}
TableNextColumn();
TextUnformatted(p, p + c_utf8_len);
if (GetFont()->FindGlyphNoFallback((ImWchar)c) == NULL)
if (!GetFont()->IsGlyphInFont((ImWchar)c))
{
SameLine();
TextUnformatted("[missing]");
@@ -16478,8 +16493,8 @@ void ImGui::DebugNodeFont(ImFont* font)
{
ImGuiContext& g = *GImGui;
ImGuiMetricsConfig* cfg = &g.DebugMetricsConfig;
bool opened = TreeNode(font, "Font: \"%s\": %.2f px, %d glyphs, %d sources(s)",
font->Sources ? font->Sources[0].Name : "", font->FontSize, font->Glyphs.Size, font->SourcesCount);
ImFontAtlas* atlas = font->ContainerAtlas;
bool opened = TreeNode(font, "Font: \"%s\": %d sources(s)", font->Sources ? font->Sources[0].Name : "", font->SourcesCount);
// Display preview text
if (!opened)
@@ -16499,11 +16514,11 @@ void ImGui::DebugNodeFont(ImFont* font)
}
if (SmallButton("Set as default"))
GetIO().FontDefault = font;
if (font->ContainerAtlas->Fonts.Size > 1 && !font->ContainerAtlas->Locked)
if (atlas->Fonts.Size > 1 && !atlas->Locked)
{
SameLine();
if (SmallButton("Remove"))
font->ContainerAtlas->RemoveFont(font);
atlas->RemoveFont(font);
}
// Display details
@@ -16515,33 +16530,43 @@ void ImGui::DebugNodeFont(ImFont* font)
"You may oversample them to get some flexibility with scaling. "
"You can also render at multiple sizes and select which one to use at runtime.\n\n"
"(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");
Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
char c_str[5];
Text("Fallback character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar);
Text("Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar);
const int surface_sqrt = (int)ImSqrt((float)font->MetricsTotalSurface);
Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);
for (int config_i = 0; config_i < font->SourcesCount; config_i++)
if (font->Sources)
{
ImFontConfig* src = &font->Sources[config_i];
int oversample_h, oversample_v;
ImFontAtlasBuildGetOversampleFactors(src, &oversample_h, &oversample_v);
BulletText("Input %d: \'%s\', Oversample: (%d=>%d,%d=>%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",
config_i, src->Name, src->OversampleH, oversample_h, src->OversampleV, oversample_v, src->PixelSnapH, src->GlyphOffset.x, src->GlyphOffset.y);
}
for (int src_n = 0; src_n < font->SourcesCount; src_n++)
if (ImFontConfig* src = &font->Sources[src_n])
BulletText("Input %d: \'%s\', Oversample: %d,%d, PixelSnapH: %d, Offset: (%.1f,%.1f)",
src_n, src->Name, src->OversampleH, src->OversampleV, src->PixelSnapH, src->GlyphOffset.x, src->GlyphOffset.y);
// Display all glyphs of the fonts in separate pages of 256 characters
for (int baked_n = 0; baked_n < atlas->Builder->BakedPool.Size; baked_n++)
{
if (TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
ImFontBaked* baked = &atlas->Builder->BakedPool[baked_n];
if (baked->ContainerFont != font)
continue;
PushID(baked_n);
if (TreeNode("Glyphs", "Baked at %.2fpx: %d glyphs%s", baked->Size, baked->Glyphs.Size, (baked->LastUsedFrame < atlas->Builder->FrameCount - 1) ? " *Unused*" : ""))
{
if (SmallButton("Load all"))
for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base++)
font->FindGlyph((ImWchar)base);
baked->FindGlyph((ImWchar)base);
const int surface_sqrt = (int)ImSqrt((float)baked->MetricsTotalSurface);
Text("Ascent: %f, Descent: %f, Ascent-Descent: %f", baked->Ascent, baked->Descent, baked->Ascent - baked->Descent);
Text("Texture Area: about %d px ~%dx%d px", baked->MetricsTotalSurface, surface_sqrt, surface_sqrt);
for (int src_n = 0; src_n < font->SourcesCount; src_n++)
{
ImFontConfig* src = &font->Sources[src_n];
int oversample_h, oversample_v;
ImFontAtlasBuildGetOversampleFactors(src, baked->Size, &oversample_h, &oversample_v);
BulletText("Input %d: \'%s\', Oversample: (%d=>%d,%d=>%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",
src_n, src->Name, src->OversampleH, oversample_h, src->OversampleV, oversample_v, src->PixelSnapH, src->GlyphOffset.x, src->GlyphOffset.y);
}
ImDrawList* draw_list = GetWindowDrawList();
const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);
const float cell_size = font->FontSize * 1;
const float cell_size = baked->Size * 1;
const float cell_spacing = GetStyle().ItemSpacing.y;
for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
{
@@ -16556,7 +16581,7 @@ void ImGui::DebugNodeFont(ImFont* font)
int count = 0;
for (unsigned int n = 0; n < 256; n++)
if (font->IsGlyphLoaded((ImWchar)(base + n)))
if (baked->IsGlyphLoaded((ImWchar)(base + n)))
count++;
if (count <= 0)
continue;
@@ -16571,7 +16596,7 @@ void ImGui::DebugNodeFont(ImFont* font)
// available here and thus cannot easily generate a zero-terminated UTF-8 encoded string.
ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
const ImFontGlyph* glyph = font->IsGlyphLoaded((ImWchar)(base + n)) ? font->FindGlyph((ImWchar)(base + n)) : NULL;
const ImFontGlyph* glyph = baked->IsGlyphLoaded((ImWchar)(base + n)) ? baked->FindGlyph((ImWchar)(base + n)) : NULL;
draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
if (!glyph)
continue;
@@ -16587,6 +16612,7 @@ void ImGui::DebugNodeFont(ImFont* font)
}
TreePop();
}
PopID();
}
TreePop();
Unindent();
+44 -18
View File
@@ -50,7 +50,7 @@ Index of this file:
// [SECTION] Multi-Select API flags and structures (ImGuiMultiSelectFlags, ImGuiMultiSelectIO, ImGuiSelectionRequest, ImGuiSelectionBasicStorage, ImGuiSelectionExternalStorage)
// [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData)
// [SECTION] Texture API (ImTextureFormat, ImTextureStatus, ImTextureRect, ImTextureData)
// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont)
// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFontBaked, ImFont)
// [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport)
// [SECTION] ImGuiPlatformIO + other Platform Dependent Interfaces (ImGuiPlatformImeData)
// [SECTION] Obsolete functions and types
@@ -172,6 +172,7 @@ struct ImDrawVert; // A single vertex (pos + uv + col = 20 byte
struct ImFont; // Runtime data for a single font within a parent ImFontAtlas
struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader
struct ImFontAtlasBuilder; // Opaque storage for building a ImFontAtlas
struct ImFontBaked; // Baked data for a ImFont at a given size.
struct ImFontConfig; // Configuration data when adding a font or merging fonts
struct ImFontGlyph; // A single font glyph (code point + coordinates within in ImFontAtlas + offset)
struct ImFontGlyphRangesBuilder; // Helper to build glyph ranges from text/string data
@@ -471,6 +472,8 @@ namespace ImGui
// Parameters stacks (shared)
IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font
IMGUI_API void PopFont();
IMGUI_API void SetFontSize(float size);
//IMGUI_API void PopFontSize();
IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col); // modify a style color. always use this if you modify the style after NewFrame().
IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col);
IMGUI_API void PopStyleColor(int count = 1);
@@ -3419,10 +3422,10 @@ struct ImFontConfig
int OversampleV; // 0 (1) // Rasterize at higher quality for sub-pixel positioning. 0 == auto == 1. This is not really useful as we don't use sub-pixel positions on the Y axis.
float SizePixels; // // Size in pixels for rasterizer (more or less maps to the resulting font height).
//ImVec2 GlyphExtraSpacing; // 0, 0 // (REMOVED IN 1.91.9: use GlyphExtraAdvanceX)
ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input.
ImVec2 GlyphOffset; // 0, 0 // [FIXME-BAKED] Offset all glyphs from this font input.
const ImWchar* GlyphRanges; // NULL // THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list).
float GlyphMinAdvanceX; // 0 // Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
float GlyphMaxAdvanceX; // FLT_MAX // Maximum AdvanceX for glyphs
float GlyphMinAdvanceX; // 0 // [FIXME-BAKED] Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
float GlyphMaxAdvanceX; // FLT_MAX // [FIXME-BAKED] Maximum AdvanceX for glyphs
float GlyphExtraAdvanceX; // 0 // Extra spacing (in pixels) between glyphs. Please contact us if you are using this.
unsigned int FontBuilderFlags; // 0 // Settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure.
float RasterizerMultiply; // 1.0f // Linearly brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. This is a silly thing we may remove in the future.
@@ -3599,6 +3602,7 @@ struct ImFontAtlas
ImVector<ImFontConfig> Sources; // Source/configuration data
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
int FontNextUniqueID; // Next value to be stored in ImFont->SourceID
ImVector<ImDrawListSharedData*> DrawListSharedDatas;
// [Internal] Font builder
@@ -3616,30 +3620,57 @@ struct ImFontAtlas
//typedef ImFontGlyphRangesBuilder GlyphRangesBuilder; // OBSOLETED in 1.67+
};
// Font runtime data and rendering
// ImFontAtlas automatically loads a default embedded font for you when you call GetTexDataAsAlpha8() or GetTexDataAsRGBA32().
struct ImFont
// Font runtime data for a given size
// Important: pointers to ImFontBaked are only valid for the current frame.
struct ImFontBaked
{
// [Internal] Members: Hot ~20/24 bytes (for CalcTextSize)
ImVector<float> IndexAdvanceX; // 12-16 // out // Sparse. Glyphs->AdvanceX in a directly indexable way (cache-friendly for CalcTextSize functions which only this info, and are often bottleneck in large UI).
float FallbackAdvanceX; // 4 // out // FindGlyph(FallbackChar)->AdvanceX
float FontSize; // 4 // in // Height of characters/line, set during loading (don't change after loading)
float Size; // 4 // in // Height of characters/line, set during loading (doesn't change after loading)
// [Internal] Members: Hot ~28/36 bytes (for RenderText loop)
ImVector<ImU16> IndexLookup; // 12-16 // out // Sparse. Index glyphs by Unicode code-point.
ImVector<ImFontGlyph> Glyphs; // 12-16 // out // All glyphs.
int FallbackGlyphIndex; // 4 // out // Index of FontFallbackChar
// [Internal] Members: Cold ~32/40/60 bytes
// [Internal] Members: Cold
float Ascent, Descent; // 4+4 // out // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] (unscaled)
unsigned int MetricsTotalSurface:26;// 3 // out // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs)
unsigned int WantDestroy:1; // 1 // // Queued for destroy
int LastUsedFrame; // 4 // // Record of that time this was bounds
ImGuiID BakedId; // 4 //
ImFont* ContainerFont; // 4-8 // in // Parent font
void* FontBackendData; // 4-8 // // Font backend opaque storage (per baked font)
// Functions
IMGUI_API ImFontBaked();
IMGUI_API void ClearOutputData();
IMGUI_API ImFontGlyph* FindGlyph(ImWchar c); // Return U+FFFD glyph if requested glyph doesn't exists.
IMGUI_API ImFontGlyph* FindGlyphNoFallback(ImWchar c); // Return NULL if glyph doesn't exist
IMGUI_API float GetCharAdvance(ImWchar c);
IMGUI_API bool IsGlyphLoaded(ImWchar c);
IMGUI_API ImFontGlyph* BuildLoadGlyph(ImWchar c);
IMGUI_API void BuildGrowIndex(int new_size);
};
// Font runtime data and rendering
// - ImFontAtlas automatically loads a default embedded font for you if you didn't load one manually.
// - Since 1.92.X a font may be rendered as any size! Therefore a font doesn't have one specific size.
// - Use 'font->GetBakedForSize(size)' to retrieve the ImFontBaked* corresponding to a given size.
// - If you used g.Font + g.FontSize (which is frequent from the ImGui layer), you can use g.FontBaked as a shortcut, as g.FontBaked == g.Font->GetBakedForSize(g.FontSize).
struct ImFont
{
// [Internal] Members: Cold ~32/40/80 bytes
// Conceptually Sources[] is the list of font sources merged to create this font.
ImFontBaked* LastBaked; // Cache last bound baked. DO NOT USE. Use GetFontBaked().
ImGuiID FontId; // Unique identifier for the font
short SourcesCount; // 2 // in // Number of ImFontConfig involved in creating this font. Usually 1, or >1 when merging multiple font sources into one ImFont.
ImFontConfig* Sources; // 4-8 // in // Pointer within ContainerAtlas->Sources[], to SourcesCount instances
ImFontAtlas* ContainerAtlas; // 4-8 // out // What we has been loaded into
ImWchar EllipsisChar; // 2-4 // out // Character used for ellipsis rendering ('...').
ImWchar FallbackChar; // 2-4 // out // Character used if a glyph isn't found (U+FFFD, '?')
float Scale; // 4 // in // Base font scale (~1.0f), multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
float Ascent, Descent; // 4+4 // out // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] (unscaled)
int MetricsTotalSurface;// 4 // out // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs)
ImU8 Used8kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/8192/8]; // 1 bytes if ImWchar=ImWchar16, 16 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints.
bool LockDisableLoading;
short LockSingleSrcConfigIdx;
@@ -3647,10 +3678,7 @@ struct ImFont
// Methods
IMGUI_API ImFont();
IMGUI_API ~ImFont();
IMGUI_API ImFontGlyph* FindGlyph(ImWchar c); // Return fallback glyph if requested glyph doesn't exists.
IMGUI_API ImFontGlyph* FindGlyphNoFallback(ImWchar c); // Return NULL if glyph doesn't exist
IMGUI_API float GetCharAdvance(ImWchar c);
IMGUI_API bool IsGlyphLoaded(ImWchar c);
IMGUI_API ImFontBaked* GetFontBaked(float font_size); // Get or create baked data for given size
IMGUI_API bool IsGlyphInFont(ImWchar c);
bool IsLoaded() const { return ContainerAtlas != NULL; }
const char* GetDebugName() const { return Sources ? Sources->Name : "<unknown>"; }
@@ -3664,15 +3692,13 @@ struct ImFont
IMGUI_API void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(FontSize * scale, text, text_end, wrap_width); }
inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(Sources[0].SizePixels * scale, text, text_end, wrap_width); }
#endif
// [Internal] Don't use!
IMGUI_API void ClearOutputData();
IMGUI_API void AddRemapChar(ImWchar from_codepoint, ImWchar to_codepoint, bool overwrite_dst);// , bool overwrite_dst = true); // Makes 'dst' character/glyph points to 'src' character/glyph. Currently needs to be called AFTER fonts have been built.
IMGUI_API bool IsGlyphRangeUnused(unsigned int c_begin, unsigned int c_last);
IMGUI_API ImFontGlyph* BuildLoadGlyph(ImWchar c);
IMGUI_API void BuildGrowIndex(int new_size);
};
// Added indirection to avoid patching ImDrawCmd after texture updates.
+310 -166
View File
File diff suppressed because it is too large Load Diff
+26 -13
View File
@@ -2130,11 +2130,12 @@ struct ImGuiContext
ImGuiIO IO;
ImGuiPlatformIO PlatformIO;
ImGuiStyle Style;
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
float FontScale; // == FontSize / Font->FontSize
float CurrentDpiScale; // Current window/viewport DpiScale
ImFont* Font; // == FontStack.back().Font
ImFontBaked* FontBaked; // == Font->GetFontBaked(FontSize)
float FontSize; // == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window.
//float FontBaseSize; // == io.FontGlobalScale * Font->Scale * Font->FontSize. Base text height.
float FontScale; // == FontBaked->Size / Font->FontSize. Scale factor over baked size.
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
ImDrawListSharedData DrawListSharedData;
ImVector<ImTextureData*>Textures;
double Time;
@@ -2673,7 +2674,7 @@ public:
// We don't use g.FontSize because the window may be != g.CurrentWindow.
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
float CalcFontSize() const { ImGuiContext& g = *Ctx; return g.FontBaseSize * FontWindowScale * FontWindowScaleParents; }
//float CalcFontSize() const { ImGuiContext& g = *Ctx; return g.FontBaseSize * FontWindowScale * FontWindowScaleParents; }
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight)); }
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight; return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight); }
};
@@ -3098,7 +3099,7 @@ namespace ImGui
IMGUI_API void SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
// Fonts, drawing
IMGUI_API void SetCurrentFont(ImFont* font);
IMGUI_API void SetCurrentFont(ImFont* font, float font_size);
inline ImFont* GetDefaultFont() { ImGuiContext& g = *GImGui; return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; }
IMGUI_API void PushPasswordFont();
inline ImDrawList* GetForegroundDrawList(ImGuiWindow* window) { IM_UNUSED(window); return GetForegroundDrawList(); } // This seemingly unnecessary wrapper simplifies compatibility between the 'master' and 'docking' branches.
@@ -3661,7 +3662,9 @@ struct ImFontLoader
bool (*FontSrcInit)(ImFontAtlas* atlas, ImFontConfig* src);
void (*FontSrcDestroy)(ImFontAtlas* atlas, ImFontConfig* src);
bool (*FontSrcContainsGlyph)(ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint);
bool (*FontAddGlyph)(ImFontAtlas* atlas, ImFont* font, ImFontConfig* srcs, int srcs_count, ImWchar codepoint);
void (*FontBakedInit)(ImFontAtlas* atlas, ImFontBaked* baked);
void (*FontBakedDestroy)(ImFontAtlas* atlas, ImFontBaked* baked);
bool (*FontBakedAddGlyph)(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* srcs, int srcs_count, ImWchar codepoint);
ImFontLoader() { memset(this, 0, sizeof(*this)); }
};
@@ -3698,6 +3701,7 @@ struct ImFontAtlasPostProcessData
ImFontAtlas* FontAtlas;
ImFont* Font;
ImFontConfig* FontSrc;
ImFontBaked* FontBaked;
ImFontGlyph* Glyph;
// Pixel data
@@ -3723,11 +3727,17 @@ struct ImFontAtlasBuilder
int RectsPackedSurface; // Number of packed pixels. Used when compacting to heuristically find the ideal texture size.
int RectsDiscardedCount;
int RectsDiscardedSurface;
int FrameCount; // Current frame count
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
bool PreloadedAllGlyphsRanges; // Set when missing ImGuiBackendFlags_RendererHasTextures features forces atlas to preload everything.
// Cache of all ImFontBaked
ImStableVector<ImFontBaked,32> BakedPool;
ImGuiStorage BakedMap;
int BakedDiscardedCount;
// Custom rectangle identifiers
ImFontAtlasRectId PackIdMouseCursors; // White pixel + mouse cursors. Also happen to be fallback in case of packing failure.
ImFontAtlasRectId PackIdLinesTexData;
@@ -3750,20 +3760,23 @@ IMGUI_API void ImFontAtlasBuildCompactTexture(ImFontAtlas* atlas);
IMGUI_API ImVec2i ImFontAtlasBuildGetTextureSizeEstimate(ImFontAtlas* atlas);
IMGUI_API bool ImFontAtlasBuildAddFont(ImFontAtlas* atlas, ImFontConfig* src);
IMGUI_API ImFontGlyph* ImFontAtlasBuildAddFontGlyph(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src, const ImFontGlyph* in_glyph);
IMGUI_API void ImFontAtlasBuildSetupFontSpecialGlyphs(ImFontAtlas* atlas, ImFont* font, ImFontConfig* src);
IMGUI_API void ImFontAtlasBuildDiscardFontGlyph(ImFontAtlas* atlas, ImFont* font, ImFontGlyph* glyph);
IMGUI_API void ImFontAtlasBuildDiscardFontGlyphs(ImFontAtlas* atlas, ImFont* font);
IMGUI_API void ImFontAtlasBuildDiscardUnusedBakes(ImFontAtlas* atlas, ImFont* font_filter);
IMGUI_API void ImFontAtlasBuildDiscardFontBaked(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked);
IMGUI_API void ImFontAtlasBuildDiscardFontBakedGlyph(ImFontAtlas* atlas, ImFont* font, ImFontBaked* baked, ImFontGlyph* glyph);
IMGUI_API void ImFontAtlasBuildReloadFont(ImFontAtlas* atlas, ImFont* font); // <--- Your future new best friend!
IMGUI_API void ImFontAtlasBuildPreloadAllGlyphRanges(ImFontAtlas* atlas); // Legacy
IMGUI_API void ImFontAtlasBuildGetOversampleFactors(ImFontConfig* src, int* out_oversample_h, int* out_oversample_v);
IMGUI_API void ImFontAtlasBuildGetOversampleFactors(ImFontConfig* src, float size, int* out_oversample_h, int* out_oversample_v);
IMGUI_API ImFontGlyph* ImFontAtlasBakedAddFontGlyph(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* src, const ImFontGlyph* in_glyph);
IMGUI_API ImGuiID ImFontAtlasBakedGetId(ImGuiID font_id, float baked_size);
IMGUI_API void ImFontAtlasPackInit(ImFontAtlas* atlas);
IMGUI_API ImFontAtlasRectId ImFontAtlasPackAddRect(ImFontAtlas* atlas, int w, int h, ImFontAtlasRectEntry* overwrite_entry = NULL);
IMGUI_API ImFontAtlasRect* ImFontAtlasPackGetRect(ImFontAtlas* atlas, ImFontAtlasRectId id);
IMGUI_API void ImFontAtlasPackDiscardRect(ImFontAtlas* atlas, ImFontAtlasRectId id);
IMGUI_API void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas);
IMGUI_API void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count);
IMGUI_API void ImFontAtlasAddDrawListSharedData(ImFontAtlas* atlas, ImDrawListSharedData* data);
IMGUI_API void ImFontAtlasRemoveDrawListSharedData(ImFontAtlas* atlas, ImDrawListSharedData* data);
IMGUI_API void ImFontAtlasUpdateDrawListsTextures(ImFontAtlas* atlas, ImTextureRef old_tex, ImTextureRef new_tex);
+1 -1
View File
@@ -3375,7 +3375,7 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
ButtonBehavior(row_r, row_id, NULL, NULL);
KeepAliveID(row_id);
const float ascent_scaled = g.Font->Ascent * g.FontScale; // FIXME: Standardize those scaling factors better
const float ascent_scaled = g.FontBaked->Ascent * g.FontScale; // FIXME: Standardize those scaling factors better
const float line_off_for_ascent_x = (ImMax((g.FontSize - ascent_scaled) * 0.5f, 0.0f) / -sin_a) * (flip_label ? -1.0f : 1.0f);
const ImVec2 padding = g.Style.CellPadding; // We will always use swapped component
const ImVec2 align = g.Style.TableAngledHeadersTextAlign;
+18 -15
View File
@@ -1518,7 +1518,7 @@ bool ImGui::TextLink(const char* label)
ColorConvertHSVtoRGB(h, s, v, line_colf.x, line_colf.y, line_colf.z);
}
float line_y = bb.Max.y + ImFloor(g.Font->Descent * g.FontScale * 0.20f);
float line_y = bb.Max.y + ImFloor(g.FontBaked->Descent * g.FontScale * 0.20f);
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf)); // FIXME-TEXT: Underline mode // FIXME-DPI
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
@@ -3956,9 +3956,10 @@ static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char**
static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, const char* text_end, const char** remaining, ImVec2* out_offset, bool stop_on_new_line)
{
ImGuiContext& g = *ctx;
ImFont* font = g.Font;
//ImFont* font = g.Font;
ImFontBaked* baked = g.FontBaked;
const float line_height = g.FontSize;
const float scale = line_height / font->FontSize;
const float scale = line_height / baked->Size;
ImVec2 text_size = ImVec2(0, 0);
float line_width = 0.0f;
@@ -3984,7 +3985,7 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
if (c == '\r')
continue;
line_width += font->GetCharAdvance((ImWchar)c) * scale;
line_width += baked->GetCharAdvance((ImWchar)c) * scale;
}
if (text_size.x < line_width)
@@ -4011,7 +4012,7 @@ namespace ImStb
{
static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->TextLen; }
static char STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->TextLen); return obj->TextSrc[idx]; }
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.FontBaked->GetCharAdvance((ImWchar)c) * g.FontScale; }
static char STB_TEXTEDIT_NEWLINE = '\n';
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
{
@@ -4314,19 +4315,21 @@ void ImGui::PushPasswordFont()
{
ImGuiContext& g = *GImGui;
ImFont* in_font = g.Font;
ImFontBaked* in_baked = g.FontBaked;
ImFontGlyph glyph = *in_baked->FindGlyph('*');
glyph.PackId = -1;
ImFont* out_font = &g.InputTextPasswordFont;
ImFontGlyph* glyph = in_font->FindGlyph('*');
out_font->FontSize = in_font->FontSize;
out_font->Scale = in_font->Scale;
out_font->Ascent = in_font->Ascent;
out_font->Descent = in_font->Descent;
out_font->ContainerAtlas = in_font->ContainerAtlas;
out_font->Glyphs.resize(0);
out_font->Glyphs.push_back(*glyph);
out_font->FallbackGlyphIndex = 0;
out_font->FallbackAdvanceX = glyph->AdvanceX;
out_font->LockDisableLoading = true;
IM_ASSERT(out_font->Glyphs.Size == 1 && out_font->IndexAdvanceX.Size == 0 && out_font->IndexLookup.Size == 0);
ImFontBaked* out_baked = out_font->GetFontBaked(in_baked->Size);
IM_ASSERT(out_baked->Glyphs.Size <= 1 && out_baked->IndexAdvanceX.Size == 0 && out_baked->IndexLookup.Size == 0);
out_baked->Ascent = in_baked->Ascent;
out_baked->Descent = in_baked->Descent;
out_baked->Glyphs.resize(0);
out_baked->Glyphs.push_back(glyph);
out_baked->FallbackGlyphIndex = 0;
out_baked->FallbackAdvanceX = glyph.AdvanceX;
PushFont(out_font);
}
@@ -5354,7 +5357,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else
{
ImVec2 rect_size = InputTextCalcTextSize(&g, p, text_selected_end, &p, NULL, true);
if (rect_size.x <= 0.0f) rect_size.x = IM_TRUNC(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
if (rect_size.x <= 0.0f) rect_size.x = IM_TRUNC(g.FontBaked->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn));
rect.ClipWith(clip_rect);
if (rect.Overlaps(clip_rect))
+84 -47
View File
@@ -46,6 +46,7 @@
#include FT_FREETYPE_H // <freetype/freetype.h>
#include FT_MODULE_H // <freetype/ftmodapi.h>
#include FT_GLYPH_H // <freetype/ftglyph.h>
#include FT_SIZES_H // <freetype/ftsizes.h>
#include FT_SYNTHESIS_H // <freetype/ftsynth.h>
// Handle LunaSVG and PlutoSVG
@@ -150,15 +151,19 @@ namespace
ImGui_ImplFreeType_Data() { memset((void*)this, 0, sizeof(*this)); }
};
// Font parameters and metrics.
struct ImGui_ImplFreeType_FontInfo
// Stored in ImFontBaked::FontBackendData: pointer to SourcesCount instances of this.
struct ImGui_ImplFreeType_FontSrcBakedData
{
float PixelHeight; // Size this font was generated with.
FT_Size FtSize; // This represent a FT_Face with a given size.
// Metrics
float Ascender; // The pixel extents above the baseline in pixels (typically positive).
float Descender; // The extents below the baseline in pixels (typically negative).
float LineSpacing; // The baseline-to-baseline distance. Note that it usually is larger than the sum of the ascender and descender taken as absolute values. There is also no guarantee that no glyphs extend above or below subsequent baselines when using this distance. Think of it as a value the designer of the font finds appropriate.
float LineGap; // The spacing in pixels between one row's descent and the next row's ascent.
float MaxAdvanceWidth; // This field gives the maximum horizontal cursor advance for all glyphs in the font.
ImGui_ImplFreeType_FontSrcBakedData() { memset((void*)this, 0, sizeof(*this)); }
};
// Stored in ImFontConfig::FontLoaderData
@@ -166,20 +171,19 @@ namespace
{
bool InitFont(FT_Library ft_library, ImFontConfig* src, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime.
void CloseFont();
void SetPixelHeight(float pixel_height); // Change font pixel size.
const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint);
void BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch);
ImGui_ImplFreeType_FontSrcData() { memset((void*)this, 0, sizeof(*this)); }
~ImGui_ImplFreeType_FontSrcData() { CloseFont(); }
// Members
ImGui_ImplFreeType_FontInfo Info; // Font descriptor of the current font.
FT_Face FtFace;
unsigned int UserFlags; // = ImFontConfig::RasterizerFlags
FT_Int32 LoadFlags;
FT_Render_Mode RenderMode;
float RasterizationDensity;
float InvRasterizationDensity;
ImFontBaked* BakedLastActivated;
};
bool ImGui_ImplFreeType_FontSrcData::InitFont(FT_Library ft_library, ImFontConfig* src, unsigned int extra_font_builder_flags)
@@ -222,9 +226,6 @@ namespace
RasterizationDensity = src->RasterizerDensity;
InvRasterizationDensity = 1.0f / RasterizationDensity;
memset(&Info, 0, sizeof(Info));
SetPixelHeight(src->SizePixels);
return true;
}
@@ -237,31 +238,6 @@ namespace
}
}
void ImGui_ImplFreeType_FontSrcData::SetPixelHeight(float pixel_height)
{
// Vuhdo (2017): "I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height'
// is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me.
// FT_Set_Pixel_Sizes() doesn't seem to get us the same result."
// (FT_Set_Pixel_Sizes() essentially calls FT_Request_Size() with FT_SIZE_REQUEST_TYPE_NOMINAL)
FT_Size_RequestRec req;
req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
req.width = 0;
req.height = (uint32_t)(pixel_height * 64 * RasterizationDensity);
req.horiResolution = 0;
req.vertResolution = 0;
FT_Request_Size(FtFace, &req);
// Note: To handle multiple sizes later, we may need to use FT_New_Size(), FT_Activate_Size()
// Update font info
FT_Size_Metrics metrics = FtFace->size->metrics;
Info.PixelHeight = pixel_height * InvRasterizationDensity;
Info.Ascender = (float)FT_CEIL(metrics.ascender) * InvRasterizationDensity;
Info.Descender = (float)FT_CEIL(metrics.descender) * InvRasterizationDensity;
Info.LineSpacing = (float)FT_CEIL(metrics.height) * InvRasterizationDensity;
Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender) * InvRasterizationDensity;
Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance) * InvRasterizationDensity;
}
const FT_Glyph_Metrics* ImGui_ImplFreeType_FontSrcData::LoadGlyph(uint32_t codepoint)
{
uint32_t glyph_index = FT_Get_Char_Index(FtFace, codepoint);
@@ -447,12 +423,6 @@ bool ImGui_ImplFreeType_FontSrcInit(ImFontAtlas* atlas, ImFontConfig* src)
if (!bd_font_data->InitFont(bd->Library, src, atlas->FontBuilderFlags))
return false;
if (src->MergeMode == false)
{
ImFont* font = src->DstFont;
font->Ascent = bd_font_data->Info.Ascender;
font->Descent = bd_font_data->Info.Descender;
}
return true;
}
@@ -464,7 +434,65 @@ void ImGui_ImplFreeType_FontSrcDestroy(ImFontAtlas* atlas, ImFontConfig* src)
src->FontLoaderData = NULL;
}
bool ImGui_ImplFreeType_FontAddGlyph(ImFontAtlas* atlas, ImFont* font, ImFontConfig* srcs, int srcs_count, ImWchar codepoint)
void ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontBaked* baked)
{
IM_UNUSED(atlas);
ImFont* font = baked->ContainerFont;
const float size = baked->Size;
IM_ASSERT(baked->FontBackendData == NULL);
ImGui_ImplFreeType_FontSrcBakedData* bd_baked_datas = (ImGui_ImplFreeType_FontSrcBakedData*)IM_ALLOC(sizeof(ImGui_ImplFreeType_FontSrcBakedData) * font->SourcesCount);
baked->FontBackendData = bd_baked_datas;
for (int src_n = 0; src_n < font->SourcesCount; src_n++)
{
ImFontConfig* src = &font->Sources[src_n];
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontBackendData;
bd_font_data->BakedLastActivated = baked;
// We need one FT_Size per source, so create one ImGui_ImplFreeType_FontBakedData for each source.
ImGui_ImplFreeType_FontSrcBakedData* bd_baked_data = &bd_baked_datas[src_n];
FT_New_Size(bd_font_data->FtFace, &bd_baked_data->FtSize);
FT_Activate_Size(bd_baked_data->FtSize);
// Vuhdo 2017: "I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height'
// is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me.
// FT_Set_Pixel_Sizes() doesn't seem to get us the same result."
// (FT_Set_Pixel_Sizes() essentially calls FT_Request_Size() with FT_SIZE_REQUEST_TYPE_NOMINAL)
FT_Size_RequestRec req;
req.type = (bd_font_data->UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
req.width = 0;
req.height = (uint32_t)(size * 64 * bd_font_data->RasterizationDensity);
req.horiResolution = 0;
req.vertResolution = 0;
FT_Request_Size(bd_font_data->FtFace, &req);
// Read metrics
FT_Size_Metrics metrics = bd_baked_data->FtSize->metrics;
bd_baked_data->Ascender = (float)FT_CEIL(metrics.ascender) * bd_font_data->InvRasterizationDensity;
bd_baked_data->Descender = (float)FT_CEIL(metrics.descender) * bd_font_data->InvRasterizationDensity;
bd_baked_data->LineSpacing = (float)FT_CEIL(metrics.height) * bd_font_data->InvRasterizationDensity;
bd_baked_data->LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender) * bd_font_data->InvRasterizationDensity;
bd_baked_data->MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance) * bd_font_data->InvRasterizationDensity;
// Output
baked->Ascent = bd_baked_data->Ascender;
baked->Descent = bd_baked_data->Descender;
}
}
void ImGui_ImplFreeType_FontBakedDestroy(ImFontAtlas* atlas, ImFontBaked* baked)
{
IM_UNUSED(atlas);
ImFont* font = baked->ContainerFont;
ImGui_ImplFreeType_FontSrcBakedData* bd_baked_datas = (ImGui_ImplFreeType_FontSrcBakedData*)baked->FontBackendData;
for (int src_n = 0; src_n < font->SourcesCount; src_n++)
FT_Done_Size(bd_baked_datas[src_n].FtSize);
IM_FREE(bd_baked_datas);
baked->FontBackendData = NULL;
}
bool ImGui_ImplFreeType_FontBakedAddGlyph(ImFontAtlas* atlas, ImFontBaked* baked, ImFontConfig* srcs, int srcs_count, ImWchar codepoint)
{
// Search for first font which has the glyph
ImGui_ImplFreeType_FontSrcData* bd_font_data = NULL;
@@ -481,6 +509,15 @@ bool ImGui_ImplFreeType_FontAddGlyph(ImFontAtlas* atlas, ImFont* font, ImFontCon
if (glyph_index == 0)
return false; // Not found
if (bd_font_data->BakedLastActivated != baked)
{
// Activate current size
int src_n = (int)(font_cfg - srcs);
ImGui_ImplFreeType_FontSrcBakedData* bd_baked_data = &((ImGui_ImplFreeType_FontSrcBakedData*)baked->FontBackendData)[src_n];
FT_Activate_Size(bd_baked_data->FtSize);
bd_font_data->BakedLastActivated = baked;
}
const FT_Glyph_Metrics* metrics = bd_font_data->LoadGlyph(codepoint);
if (metrics == NULL)
return false;
@@ -515,9 +552,7 @@ bool ImGui_ImplFreeType_FontAddGlyph(ImFontAtlas* atlas, ImFont* font, ImFontCon
IM_ASSERT_USER_ERROR(pack_id >= 0, "Out of texture memory.");
return false;
}
ImFontAtlasRect* r = ImFontAtlasPackGetRect(atlas, pack_id);
font->MetricsTotalSurface += w * h;
// Render pixels to our temporary buffer
atlas->Builder->TempBuffer.resize(w * h * 4);
@@ -525,7 +560,7 @@ bool ImGui_ImplFreeType_FontAddGlyph(ImFontAtlas* atlas, ImFont* font, ImFontCon
bd_font_data->BlitGlyph(ft_bitmap, temp_buffer, w);
float font_off_x = src->GlyphOffset.x;
float font_off_y = src->GlyphOffset.y + IM_ROUND(font->Ascent);
float font_off_y = src->GlyphOffset.y + IM_ROUND(baked->Ascent);
float recip_h = 1.0f / src->RasterizerDensity;
float recip_v = 1.0f / src->RasterizerDensity;
@@ -539,19 +574,19 @@ bool ImGui_ImplFreeType_FontAddGlyph(ImFontAtlas* atlas, ImFont* font, ImFontCon
glyph.Visible = true;
glyph.Colored = (ft_bitmap->pixel_mode == FT_PIXEL_MODE_BGRA);
glyph.PackId = pack_id;
ImFontAtlasBuildAddFontGlyph(atlas, font, src, &glyph);
ImFontAtlasBakedAddFontGlyph(atlas, baked, src, &glyph);
// Copy to texture, post-process and queue update for backend
ImTextureData* tex = atlas->TexData;
IM_ASSERT(r->x + r->w <= tex->Width && r->y + r->h <= tex->Height);
ImFontAtlasTextureBlockConvert(temp_buffer, ImTextureFormat_RGBA32, w * 4, tex->GetPixelsAt(r->x, r->y), tex->Format, tex->GetPitch(), w, h);
ImFontAtlasPostProcessData pp_data = { atlas, font, src, &font->Glyphs.back(), tex->GetPixelsAt(r->x, r->y), tex->Format, tex->GetPitch(), w, h };
ImFontAtlasPostProcessData pp_data = { atlas, baked->ContainerFont, src, baked, &baked->Glyphs.back(), tex->GetPixelsAt(r->x, r->y), tex->Format, tex->GetPitch(), w, h };
ImFontAtlasTextureBlockPostProcess(&pp_data);
ImFontAtlasTextureBlockQueueUpload(atlas, tex, r->x, r->y, r->w, r->h);
}
else
{
ImFontAtlasBuildAddFontGlyph(atlas, font, src, &glyph);
ImFontAtlasBakedAddFontGlyph(atlas, baked, src, &glyph);
}
return true;
}
@@ -573,7 +608,9 @@ const ImFontLoader* ImGuiFreeType::GetFontLoader()
loader.FontSrcInit = ImGui_ImplFreeType_FontSrcInit;
loader.FontSrcDestroy = ImGui_ImplFreeType_FontSrcDestroy;
loader.FontSrcContainsGlyph = ImGui_ImplFreetype_FontSrcContainsGlyph;
loader.FontAddGlyph = ImGui_ImplFreeType_FontAddGlyph;
loader.FontBakedInit = ImGui_ImplFreeType_FontBakedInit;
loader.FontBakedDestroy = ImGui_ImplFreeType_FontBakedDestroy;
loader.FontBakedAddGlyph = ImGui_ImplFreeType_FontBakedAddGlyph;
return &loader;
}