Rebased ref, commits from common ancestor:
commit b71081f25fbde5c9b59314f425aa962311e6f9f5
Author: Khaled Hosny <[email protected]>
AuthorDate: Mon Mar 2 01:02:18 2026 +0200
Commit: Khaled Hosny <[email protected]>
CommitDate: Mon Mar 2 01:04:55 2026 +0200
xx
Change-Id: I9383b49d2a520fb9c03e9971e802af60eb142969
diff --git a/vcl/inc/unx/fc_fontoptions.hxx b/vcl/inc/unx/fc_fontoptions.hxx
index 73bcf3421bc5..51bec972f3a5 100644
--- a/vcl/inc/unx/fc_fontoptions.hxx
+++ b/vcl/inc/unx/fc_fontoptions.hxx
@@ -21,6 +21,8 @@
#include <rtl/string.hxx>
#include <vcl/dllapi.h>
+#include <hb.h>
+#include <vector>
typedef struct _FcPattern FcPattern;
class VCL_DLLPUBLIC FontConfigFontOptions
@@ -31,6 +33,7 @@ public:
~FontConfigFontOptions();
void SyncPattern(const OString& rFileName, sal_uInt32
nFontFace, sal_uInt32 nFontVariation, bool bEmbolden);
+ static void AddVariations(FcPattern* pPattern, const
std::vector<hb_variation_t>& rVariations);
FcPattern* GetPattern() const;
static void cairo_font_options_substitute(FcPattern* pPattern);
private:
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index af5a620484c8..4ea145303218 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -382,6 +382,37 @@ void AquaGraphicsBackend::drawTextLayout(const
GenericSalLayout& rLayout)
}
CTFontRef pCTFont = rFont.GetCTFont();
+ CTFontRef pVarFont = nullptr;
+ const auto& variations = rFont.GetVariations();
+ if (!variations.empty())
+ {
+ CFMutableDictionaryRef pVarDict =
CFDictionaryCreateMutable(kCFAllocatorDefault, variations.size(),
+
&kCFTypeDictionaryKeyCallBacks,
+
&kCFTypeDictionaryValueCallBacks);
+ for (const auto& var : variations)
+ {
+ hb_tag_t nTag = var.tag;
+ CFNumberRef pTag = CFNumberCreate(kCFAllocatorDefault,
kCFNumberSInt32Type, &nTag);
+ double fValue = var.value;
+ CFNumberRef pValue = CFNumberCreate(kCFAllocatorDefault,
kCFNumberDoubleType, &fValue);
+ CFDictionaryAddValue(pVarDict, pTag, pValue);
+ CFRelease(pTag);
+ CFRelease(pValue);
+ }
+ CFDictionaryRef pAttrDict = CFDictionaryCreate(kCFAllocatorDefault,
+ (const
void**)&kCTFontVariationAttribute,
+ (const
void**)&pVarDict, 1,
+
&kCFTypeDictionaryKeyCallBacks,
+
&kCFTypeDictionaryValueCallBacks);
+ CTFontDescriptorRef pVarDesc =
CTFontDescriptorCreateWithAttributes(pAttrDict);
+ pVarFont = CTFontCreateCopyWithAttributes(pCTFont, 0.0, nullptr,
pVarDesc);
+ pCTFont = pVarFont;
+
+ CFRelease(pVarDesc);
+ CFRelease(pAttrDict);
+ CFRelease(pVarDict);
+ }
+
CGAffineTransform aRotMatrix =
CGAffineTransformMakeRotation(-rFont.mfFontRotation);
basegfx::B2DPoint aPos;
@@ -412,7 +443,11 @@ void AquaGraphicsBackend::drawTextLayout(const
GenericSalLayout& rLayout)
}
if (aGlyphIds.empty())
+ {
+ if (pVarFont)
+ CFRelease(pVarFont);
return;
+ }
assert(aGlyphIds.size() == aGlyphPos.size());
#if 0
@@ -481,6 +516,9 @@ void AquaGraphicsBackend::drawTextLayout(const
GenericSalLayout& rLayout)
}
mrShared.maContextHolder.restoreState();
+
+ if (pVarFont)
+ CFRelease(pVarFont);
}
void AquaSalGraphics::SetFont(LogicalFontInstance* pReqFont, int
nFallbackLevel)
diff --git a/vcl/unx/generic/fontmanager/fontconfig.cxx
b/vcl/unx/generic/fontmanager/fontconfig.cxx
index b33675cd7b2a..0ee9ecfa8284 100644
--- a/vcl/unx/generic/fontmanager/fontconfig.cxx
+++ b/vcl/unx/generic/fontmanager/fontconfig.cxx
@@ -1295,6 +1295,10 @@ FcPattern *FontConfigFontOptions::GetPattern() const
return mpPattern;
}
+#ifndef FC_FONT_VARIATIONS
+#define FC_FONT_VARIATIONS "fontvariations"
+#endif
+
void FontConfigFontOptions::SyncPattern(const OString& rFileName, sal_uInt32
nIndex, sal_uInt32 nVariation, bool bEmbolden)
{
FcPatternDel(mpPattern, FC_FILE);
@@ -1306,6 +1310,24 @@ void FontConfigFontOptions::SyncPattern(const OString&
rFileName, sal_uInt32 nIn
FcPatternAddBool(mpPattern, FC_EMBOLDEN, bEmbolden ? FcTrue : FcFalse);
}
+void FontConfigFontOptions::AddVariations(FcPattern* pPattern, const
std::vector<hb_variation_t>& rVariations)
+{
+ if (rVariations.empty())
+ return;
+
+ OStringBuffer aVarStr;
+ for (const auto& var : rVariations)
+ {
+ if (!aVarStr.isEmpty())
+ aVarStr.append(',');
+ char tag[4];
+ hb_tag_to_string(var.tag, tag);
+ aVarStr.append(tag, 4).append('=').append(OString::number(var.value));
+ }
+ FcPatternDel(pPattern, FC_FONT_VARIATIONS);
+ FcPatternAddString(pPattern, FC_FONT_VARIATIONS, reinterpret_cast<const
FcChar8*>(aVarStr.getStr()));
+}
+
std::unique_ptr<FontConfigFontOptions> PrintFontManager::getFontOptions(const
FontAttributes& rInfo, int nSize)
{
FontOptionsKey aKey{ rInfo.GetFamilyName(), nSize, rInfo.GetItalic(),
diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx
b/vcl/unx/generic/gdi/cairotextrender.cxx
index 14ee838df33d..03617b91cc9c 100644
--- a/vcl/unx/generic/gdi/cairotextrender.cxx
+++ b/vcl/unx/generic/gdi/cairotextrender.cxx
@@ -29,8 +29,10 @@
#include <sallayout.hxx>
#include <salinst.hxx>
+#include <hb.h>
#include <cairo.h>
#include <cairo-ft.h>
+#include <fontconfig/fontconfig.h>
#if defined(CAIRO_HAS_SVG_SURFACE)
#include <cairo-svg.h>
#elif defined(CAIRO_HAS_PDF_SURFACE)
@@ -43,6 +45,7 @@ namespace {
typedef struct FT_FaceRec_* FT_Face;
+
class CairoFontsCache : public CacheOwner
{
public:
@@ -52,12 +55,22 @@ public:
const FontConfigFontOptions *mpOptions;
bool mbEmbolden;
bool mbVerticalMetrics;
+ std::vector<hb_variation_t> maVariations;
bool operator ==(const CacheId& rOther) const
{
- return maFace == rOther.maFace &&
- mpOptions == rOther.mpOptions &&
- mbEmbolden == rOther.mbEmbolden &&
- mbVerticalMetrics == rOther.mbVerticalMetrics;
+ if (maFace != rOther.maFace ||
+ mpOptions != rOther.mpOptions ||
+ mbEmbolden != rOther.mbEmbolden ||
+ mbVerticalMetrics != rOther.mbVerticalMetrics ||
+ maVariations.size() != rOther.maVariations.size())
+ return false;
+ for (size_t i = 0; i < maVariations.size(); ++i)
+ {
+ if (maVariations[i].tag != rOther.maVariations[i].tag ||
+ maVariations[i].value != rOther.maVariations[i].value)
+ return false;
+ }
+ return true;
}
};
@@ -227,7 +240,14 @@ static void ApplyFont(cairo_t* cr, const
CairoFontsCache::CacheId& rId, double n
{
const FontConfigFontOptions *pOptions = rId.mpOptions;
FcPattern *pPattern = pOptions->GetPattern();
+ if (!rId.maVariations.empty())
+ {
+ pPattern = FcPatternDuplicate(pPattern);
+ FontConfigFontOptions::AddVariations(pPattern, rId.maVariations);
+ }
font_face = cairo_ft_font_face_create_for_pattern(pPattern);
+ if (!rId.maVariations.empty())
+ FcPatternDestroy(pPattern);
rCache.CacheFont(font_face, rId);
}
cairo_set_font_face(cr, font_face);
@@ -268,6 +288,7 @@ static CairoFontsCache::CacheId makeCacheId(const
GenericSalLayout& rLayout)
aId.mpOptions = rFont.GetFontOptions();
aId.mbEmbolden = rInstance.NeedsArtificialBold();
aId.mbVerticalMetrics = false;
+ aId.maVariations = rInstance.GetVariations();
return aId;
}