mirror of
https://github.com/ocornut/imgui.git
synced 2026-05-09 21:29:26 +08:00
Fonts: Baked system, with auto-bind, v10.
# Conflicts: # imgui_internal.h
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+26
-13
@@ -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
@@ -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
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user