summaryrefslogtreecommitdiff
path: root/indra/llrender/llfontfreetype.cpp
diff options
context:
space:
mode:
authorAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2026-04-14 23:17:36 +0300
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2026-04-15 22:27:56 +0300
commit6ee601c642b3a4fa182334eb1ca015d71d6eaedd (patch)
tree08f58a6dd7f430a21b63d87be5b73ed7fbae5508 /indra/llrender/llfontfreetype.cpp
parent45f8e60cb4ec113e0bf07f28f84405e25ba356fd (diff)
#2023 Load from a variable font
WIP, beacsue variable fonts are not yeat included.
Diffstat (limited to 'indra/llrender/llfontfreetype.cpp')
-rw-r--r--indra/llrender/llfontfreetype.cpp106
1 files changed, 92 insertions, 14 deletions
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index 063e308da0..9b00df2bf6 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -39,6 +39,7 @@
// For some reason, this won't work if it's not wrapped in the ifdef
#ifdef FT_FREETYPE_H
#include FT_FREETYPE_H
+#include FT_MULTIPLE_MASTERS_H
#endif
#include "lldir.h"
@@ -165,7 +166,7 @@ LLFontFreetype::~LLFontFreetype()
// mFallbackFonts cleaned up by LLPointer destructor
}
-bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags)
+bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, S32 weight, bool is_fallback, S32 face_n, EFontHinting hinting, S32 flags)
{
// Don't leak face objects. This is also needed to deal with
// changed font file names.
@@ -191,6 +192,18 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
mIsFallback = is_fallback;
mHinting = hinting;
mFontFlags = flags;
+ mWeight = weight;
+
+ bool variable_font = false;
+ if (weight >= 0)
+ {
+ variable_font = setVariationAxis("wght", static_cast<F32>(weight));
+
+ // For Inter, also set optical size based on point size
+ // This makes text look better at different sizes
+ setVariationAxis("opsz", point_size);
+ }
+
F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi
error = FT_Set_Char_Size(mFTFace, /* handle to face object */
@@ -252,6 +265,12 @@ bool LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
// Ex: Inter SemiBold doesn't have FT_STYLE_FLAG_BOLD and without this style it would be bolded programmatically.
mStyle |= LLFontGL::BOLD;
}
+ else if (weight >= 600 && variable_font)
+ {
+ // If the font is heavy enough, consider it bold and avoid programmatic bolding
+ // even if it doesn't have the bold style set.
+ mStyle |= LLFontGL::BOLD;
+ }
if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC)
{
@@ -359,12 +378,8 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
- if (mFTFace->face_flags & FT_FACE_FLAG_SCALABLE)
- {
- // Return the X advance
- return (F32)(delta.x * (1.0 / 64.0));
- }
- return (F32)delta.x;
+ // ft_kerning_unfitted mode always returns 26.6 fixed-point values
+ return (F32)(delta.x * (1.0 / 64.0));
}
F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const
@@ -379,12 +394,8 @@ F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LL
llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
- if (mFTFace->face_flags & FT_FACE_FLAG_SCALABLE)
- {
- // Return the X advance
- return (F32)(delta.x * (1.0 / 64.0));
- }
- return (F32)delta.x;
+ // ft_kerning_unfitted mode always returns 26.6 fixed-point values
+ return (F32)(delta.x * (1.0 / 64.0));
}
bool LLFontFreetype::hasGlyph(llwchar wch) const
@@ -697,7 +708,7 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, ll
void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
{
resetBitmapCache();
- loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mIsFallback, 0, mHinting, mFontFlags);
+ loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mWeight, mIsFallback, 0, mHinting, mFontFlags);
if (!mIsFallback)
{
// This is the head of the list - need to rebuild ourself and all fallbacks.
@@ -865,6 +876,73 @@ void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32
}
}
+bool LLFontFreetype::setVariationAxis(const std::string& axis_tag, F32 value)
+{
+ if (!mFTFace)
+ return false;
+
+ // Check if this is a variable font
+ FT_MM_Var* master = nullptr;
+ if (FT_Get_MM_Var(mFTFace, &master) != 0)
+ {
+ // Not a variable font - this is not an error, just silently skip
+ return false;
+ }
+
+ // Find the axis by tag (e.g., "wght" for weight)
+ FT_UInt axis_index = 0;
+ bool found = false;
+ for (FT_UInt i = 0; i < master->num_axis; i++)
+ {
+ // Compare the 4-byte tag
+ if (master->axis[i].tag == FT_MAKE_TAG(axis_tag[0], axis_tag[1], axis_tag[2], axis_tag[3]))
+ {
+ axis_index = i;
+ found = true;
+
+ // Clamp value to valid range for this axis
+ F32 min_val = master->axis[i].minimum / 65536.0f;
+ F32 max_val = master->axis[i].maximum / 65536.0f;
+ value = llclamp(value, min_val, max_val);
+
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ FT_Done_MM_Var(gFTLibrary, master);
+ LL_WARNS_ONCE("FontVariation") << "Axis '" << axis_tag << "' not found in font: " << mName << LL_ENDL;
+ return false;
+ }
+
+ FT_UInt num_coords = master->num_axis;
+ FT_Fixed* coords = new FT_Fixed[num_coords];
+
+ // Get current coordinates
+ FT_Get_Var_Design_Coordinates(mFTFace, num_coords, coords);
+
+ // Update the specific axis
+ coords[axis_index] = (FT_Fixed)(value * 65536.0f);
+
+ // Set all coordinates
+ int error = FT_Set_Var_Design_Coordinates(mFTFace, num_coords, coords);
+
+ delete[] coords;
+ FT_Done_MM_Var(gFTLibrary, master);
+
+ if (error != 0)
+ {
+ LL_WARNS() << "Failed to set variation coordinates for " << axis_tag
+ << " = " << value << " in font: " << mName << LL_ENDL;
+ return false;
+ }
+
+ LL_INFOS("FontVariation") << "Set " << axis_tag << " = " << value
+ << " for font: " << mName << LL_ENDL;
+ return true;
+}
+
namespace ll
{