mirror of
https://github.com/ocornut/imgui.git
synced 2026-11-06 06:25:54 +01:00
Allow configuring variable axes in FreeType
This commit is contained in:
parent
c91bcea7a8
commit
2c6218e324
23
imgui.h
23
imgui.h
@ -3527,6 +3527,26 @@ struct ImTextureData
|
||||
// [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontAtlasFlags, ImFontAtlas, ImFontGlyphRangesBuilder, ImFont)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Helper macro to create OpenType axis tags (e.g., IM_FONT_TAG('w','g','h','t') for weight)
|
||||
#define IM_FONT_TAG(c1,c2,c3,c4) (((ImU32)(ImU8)(c1)<<24)|((ImU32)(ImU8)(c2)<<16)|((ImU32)(ImU8)(c3)<<8)|((ImU32)(ImU8)(c4)))
|
||||
|
||||
// Variable font axis setting (for use with ImFontConfigVarAxes)
|
||||
struct ImFontConfigVarAxis
|
||||
{
|
||||
ImU32 Tag; // OpenType axis tag (use IM_FONT_TAG('w','g','h','t'), etc.)
|
||||
float Value; // Axis value
|
||||
ImFontConfigVarAxis() { memset(this, 0, sizeof(*this)); }
|
||||
ImFontConfigVarAxis(ImU32 tag, float value) { Tag = tag; Value = value; }
|
||||
};
|
||||
|
||||
// Container for variable font axis settings (pointer + count pattern)
|
||||
struct ImFontConfigVarAxes
|
||||
{
|
||||
const ImFontConfigVarAxis* Axes; // Pointer to axis array (data must persist as long as font is alive)
|
||||
int AxesCount; // Number of entries in Axes array
|
||||
ImFontConfigVarAxes() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// A font input/source (we may rename this to ImFontSource in the future)
|
||||
struct ImFontConfig
|
||||
{
|
||||
@ -3557,6 +3577,9 @@ struct ImFontConfig
|
||||
float RasterizerDensity; // 1.0f // [LEGACY: this only makes sense when ImGuiBackendFlags_RendererHasTextures is not supported] DPI scale multiplier for rasterization. Not altering other font metrics: makes it easy to swap between e.g. a 100% and a 400% fonts for a zooming display, or handle Retina screen. IMPORTANT: If you change this it is expected that you increase/decrease font scale roughly to the inverse of this, otherwise quality may look lowered.
|
||||
float ExtraSizeScale; // 1.0f // Extra rasterizer scale over SizePixels.
|
||||
|
||||
// Variable font settings (requires FreeType loader)
|
||||
ImFontConfigVarAxes VarAxes; // {} // [Variable fonts] Generic axis settings for any OpenType axis. Use IM_FONT_TAG() macro for tags.
|
||||
|
||||
// [Internal]
|
||||
ImFontFlags Flags; // Font flags (don't use just yet, will be exposed in upcoming 1.92.X updates)
|
||||
ImFont* DstFont; // Target font (as we merging fonts, multiple ImFontConfig may target the same font)
|
||||
|
||||
@ -48,6 +48,8 @@
|
||||
#include FT_GLYPH_H // <freetype/ftglyph.h>
|
||||
#include FT_SIZES_H // <freetype/ftsizes.h>
|
||||
#include FT_SYNTHESIS_H // <freetype/ftsynth.h>
|
||||
#include FT_MULTIPLE_MASTERS_H // <freetype/ftmm.h>
|
||||
#include FT_TRUETYPE_TABLES_H // <freetype/tttables.h>
|
||||
|
||||
// Handle LunaSVG and PlutoSVG
|
||||
#if defined(IMGUI_ENABLE_FREETYPE_LUNASVG) && defined(IMGUI_ENABLE_FREETYPE_PLUTOSVG)
|
||||
@ -433,6 +435,38 @@ static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* s
|
||||
FT_New_Size(bd_font_data->FtFace, &bd_baked_data->FtSize);
|
||||
FT_Activate_Size(bd_baked_data->FtSize);
|
||||
|
||||
// Variable font axis support - configure design BEFORE size request
|
||||
FT_MM_Var* mm_var = nullptr;
|
||||
if (FT_Get_MM_Var(bd_font_data->FtFace, &mm_var) == 0 && mm_var != nullptr)
|
||||
{
|
||||
FT_Fixed* coords = (FT_Fixed*)IM_ALLOC(mm_var->num_axis * sizeof(FT_Fixed));
|
||||
// Initialize to font's default values (not current values which may be cached)
|
||||
for (FT_UInt i = 0; i < mm_var->num_axis; i++)
|
||||
coords[i] = mm_var->axis[i].def;
|
||||
|
||||
// Helper to clamp and set axis value
|
||||
auto SetAxis = [&](FT_UInt i, float value) {
|
||||
float axis_min = (float)mm_var->axis[i].minimum / 65536.0f;
|
||||
float axis_max = (float)mm_var->axis[i].maximum / 65536.0f;
|
||||
if (value < axis_min) value = axis_min;
|
||||
if (value > axis_max) value = axis_max;
|
||||
coords[i] = (FT_Fixed)(value * 65536.0f);
|
||||
};
|
||||
|
||||
// Apply axis settings from VarAxes (user-provided values override font defaults)
|
||||
for (FT_UInt i = 0; i < mm_var->num_axis; i++)
|
||||
{
|
||||
FT_ULong tag = mm_var->axis[i].tag;
|
||||
for (int j = 0; j < src->VarAxes.AxesCount; j++)
|
||||
if (tag == (FT_ULong)src->VarAxes.Axes[j].Tag)
|
||||
SetAxis(i, src->VarAxes.Axes[j].Value);
|
||||
}
|
||||
|
||||
FT_Set_Var_Design_Coordinates(bd_font_data->FtFace, mm_var->num_axis, coords);
|
||||
IM_FREE(coords);
|
||||
FT_Done_MM_Var(bd_font_data->FtFace->glyph->library, mm_var);
|
||||
}
|
||||
|
||||
// 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."
|
||||
@ -606,6 +640,66 @@ bool ImGuiFreeType::DebugEditFontLoaderFlags(unsigned int* p_font_loader_flags)
|
||||
return edited;
|
||||
}
|
||||
|
||||
int ImGuiFreeType::GetFontAxes(const char* filename, ImFontVarAxisInfo* out_axes, int max_axes)
|
||||
{
|
||||
// Initialize FreeType library (temporary, just for this query)
|
||||
FT_Library ft_library;
|
||||
if (FT_Init_FreeType(&ft_library) != 0)
|
||||
return -1;
|
||||
|
||||
// Load font face
|
||||
FT_Face ft_face;
|
||||
if (FT_New_Face(ft_library, filename, 0, &ft_face) != 0)
|
||||
{
|
||||
FT_Done_FreeType(ft_library);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Query variable font axes
|
||||
int result = 0;
|
||||
FT_MM_Var* mm_var = nullptr;
|
||||
if (FT_Get_MM_Var(ft_face, &mm_var) == 0 && mm_var != nullptr)
|
||||
{
|
||||
result = (int)mm_var->num_axis;
|
||||
|
||||
// Fill output array if provided
|
||||
if (out_axes != nullptr)
|
||||
{
|
||||
int count = (result < max_axes) ? result : max_axes;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
const FT_Var_Axis& axis = mm_var->axis[i];
|
||||
out_axes[i].Tag = (ImU32)axis.tag;
|
||||
out_axes[i].Minimum = (float)axis.minimum / 65536.0f;
|
||||
out_axes[i].Default = (float)axis.def / 65536.0f;
|
||||
out_axes[i].Maximum = (float)axis.maximum / 65536.0f;
|
||||
|
||||
// Copy axis name (FreeType provides null-terminated string)
|
||||
if (axis.name)
|
||||
{
|
||||
size_t len = strlen(axis.name);
|
||||
if (len >= sizeof(out_axes[i].Name))
|
||||
len = sizeof(out_axes[i].Name) - 1;
|
||||
memcpy(out_axes[i].Name, axis.name, len);
|
||||
out_axes[i].Name[len] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
out_axes[i].Name[0] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FT_Done_MM_Var(ft_library, mm_var);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
FT_Done_Face(ft_face);
|
||||
FT_Done_FreeType(ft_library);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||
// For more details, see https://gitlab.freedesktop.org/freetype/freetype-demos/-/blob/master/src/rsvg-port.c
|
||||
// The original code from the demo is licensed under CeCILL-C Free Software License Agreement (https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/LICENSE.TXT)
|
||||
|
||||
@ -58,6 +58,16 @@ enum ImGuiFreeTypeLoaderFlags_
|
||||
typedef ImGuiFreeTypeLoaderFlags_ ImGuiFreeTypeBuilderFlags_;
|
||||
#endif
|
||||
|
||||
// Variable font axis information (returned by GetFontAxes)
|
||||
struct ImFontVarAxisInfo
|
||||
{
|
||||
ImU32 Tag; // OpenType axis tag (use IM_FONT_TAG to compare, e.g., IM_FONT_TAG('w','g','h','t'))
|
||||
char Name[64]; // Human-readable axis name (e.g., "Weight", "Width", "Optical Size")
|
||||
float Minimum; // Minimum axis value
|
||||
float Default; // Default axis value
|
||||
float Maximum; // Maximum axis value
|
||||
};
|
||||
|
||||
namespace ImGuiFreeType
|
||||
{
|
||||
// This is automatically assigned when using '#define IMGUI_ENABLE_FREETYPE'.
|
||||
@ -73,6 +83,12 @@ namespace ImGuiFreeType
|
||||
// Display UI to edit ImFontAtlas::FontLoaderFlags (shared) or ImFontConfig::FontLoaderFlags (single source)
|
||||
IMGUI_API bool DebugEditFontLoaderFlags(ImGuiFreeTypeLoaderFlags* p_font_loader_flags);
|
||||
|
||||
// Query variable font axes from a font file (standalone utility, no atlas required)
|
||||
// Returns number of axes found, or -1 on error (file not found, not a valid font, etc.)
|
||||
// If out_axes is NULL, just returns the axis count without writing data.
|
||||
// Axes array should have at least 'max_axes' elements.
|
||||
IMGUI_API int GetFontAxes(const char* filename, ImFontVarAxisInfo* out_axes, int max_axes);
|
||||
|
||||
// Obsolete names (will be removed)
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
//IMGUI_API const ImFontBuilderIO* GetBuilderForFreeType(); // Renamed/changed in 1.92. Change 'io.Fonts->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType()' to 'io.Fonts->SetFontLoader(ImGuiFreeType::GetFontLoader())' if you need runtime selection.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user