168be2b
From f13d0ae5a68c3ae93d2839a1cc8ff3fe96622a6e Mon Sep 17 00:00:00 2001
168be2b
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
168be2b
Date: Wed, 20 Mar 2019 15:41:20 +0000
168be2b
Subject: [PATCH] rhbz#1690732 basic font variation support
168be2b
168be2b
on the fontconfig/harfbuzz/cairo drawing path for preset variations
168be2b
168be2b
Related: rhbz#1690732 FC_INDEX doesn't mean exactly what it used to mean
168be2b
168be2b
its been repurposed to hold font face variation information too
168be2b
168be2b
(cherry picked from commit 3681e8d8e6270912090b22445e67899bc2207e39)
168be2b
168be2b
Change-Id: I95ef68aecfd59687ae9aae58e01e394c83c6ea9e
168be2b
---
168be2b
 vcl/inc/unx/fc_fontoptions.hxx                |  2 +-
168be2b
 vcl/inc/unx/fontmanager.hxx                   |  6 +-
168be2b
 vcl/inc/unx/freetype_glyphcache.hxx           |  9 +--
168be2b
 vcl/inc/unx/glyphcache.hxx                    |  8 ++-
168be2b
 vcl/unx/generic/fontmanager/fontconfig.cxx    | 54 ++++++++++++------
168be2b
 vcl/unx/generic/fontmanager/fontmanager.cxx   | 20 ++++++-
168be2b
 vcl/unx/generic/gdi/cairotextrender.cxx       |  3 +-
168be2b
 .../generic/glyphs/freetype_glyphcache.cxx    | 55 +++++++++++++++++--
168be2b
 vcl/unx/generic/glyphs/glyphcache.cxx         |  5 +-
168be2b
 vcl/unx/generic/print/genpspgraphics.cxx      |  3 +-
168be2b
 10 files changed, 129 insertions(+), 36 deletions(-)
168be2b
168be2b
diff --git a/vcl/inc/unx/fc_fontoptions.hxx b/vcl/inc/unx/fc_fontoptions.hxx
168be2b
index 4e21a4d28c3e..c5ea38ce4f54 100644
168be2b
--- a/vcl/inc/unx/fc_fontoptions.hxx
168be2b
+++ b/vcl/inc/unx/fc_fontoptions.hxx
168be2b
@@ -34,7 +34,7 @@ public:
168be2b
                             mpPattern(pPattern) {}
168be2b
                         ~FontConfigFontOptions();
168be2b
 
168be2b
-    void                SyncPattern(const OString& rFileName, int nFontFace, bool bEmbolden);
168be2b
+    void                SyncPattern(const OString& rFileName, sal_uInt32 nFontFace, sal_uInt32 nFontVariation, bool bEmbolden);
168be2b
     FcPattern*          GetPattern() const;
168be2b
     static void         cairo_font_options_substitute(FcPattern* pPattern);
168be2b
 private:
168be2b
diff --git a/vcl/inc/unx/fontmanager.hxx b/vcl/inc/unx/fontmanager.hxx
168be2b
index e19b5f3fc9ae..d796aba7e944 100644
168be2b
--- a/vcl/inc/unx/fontmanager.hxx
168be2b
+++ b/vcl/inc/unx/fontmanager.hxx
168be2b
@@ -131,6 +131,7 @@ class VCL_PLUGIN_PUBLIC PrintFontManager
168be2b
         int               m_nDirectory;       // atom containing system dependent path
168be2b
         OString           m_aFontFile;        // relative to directory
168be2b
         int               m_nCollectionEntry; // 0 for regular fonts, 0 to ... for fonts stemming from collections
168be2b
+        int               m_nVariationEntry;  // 0 for regular fonts, 0 to ... for fonts stemming from font variations
168be2b
 
168be2b
         explicit PrintFont();
168be2b
     };
168be2b
@@ -154,7 +155,7 @@ class VCL_PLUGIN_PUBLIC PrintFontManager
168be2b
     bool analyzeSfntFile(PrintFont* pFont) const;
168be2b
     // finds the font id for the nFaceIndex face in this font file
168be2b
     // There may be multiple font ids for font collections
168be2b
-    fontID findFontFileID( int nDirID, const OString& rFile, int nFaceIndex ) const;
168be2b
+    fontID findFontFileID(int nDirID, const OString& rFile, int nFaceIndex, int nVariationIndex) const;
168be2b
 
168be2b
     // There may be multiple font ids for font collections
168be2b
     std::vector<fontID> findFontFileIDs( int nDirID, const OString& rFile ) const;
168be2b
@@ -242,6 +243,9 @@ public:
168be2b
     // get the ttc face number
168be2b
     int getFontFaceNumber( fontID nFontID ) const;
168be2b
 
168be2b
+    // get the ttc face variation
168be2b
+    int getFontFaceVariation( fontID nFontID ) const;
168be2b
+
168be2b
     // get a specific fonts ascend
168be2b
     int getFontAscend( fontID nFontID ) const;
168be2b
 
168be2b
diff --git a/vcl/inc/unx/freetype_glyphcache.hxx b/vcl/inc/unx/freetype_glyphcache.hxx
168be2b
index 774eec877957..3c09fe9b4157 100644
168be2b
--- a/vcl/inc/unx/freetype_glyphcache.hxx
168be2b
+++ b/vcl/inc/unx/freetype_glyphcache.hxx
168be2b
@@ -55,10 +55,9 @@ private:
168be2b
 class FreetypeFontInfo
168be2b
 {
168be2b
 public:
168be2b
-                           FreetypeFontInfo( const FontAttributes&,
168be2b
-                               const OString& rNativeFileName,
168be2b
-                               int nFaceNum, sal_IntPtr nFontId);
168be2b
-                          ~FreetypeFontInfo();
168be2b
+    FreetypeFontInfo(const FontAttributes&, const OString& rNativeFileName,
168be2b
+                     int nFaceNum, int nFaceVariation, sal_IntPtr nFontId);
168be2b
+    ~FreetypeFontInfo();
168be2b
 
168be2b
     const unsigned char*  GetTable( const char*, sal_uLong* pLength) const;
168be2b
 
168be2b
@@ -67,6 +66,7 @@ public:
168be2b
 
168be2b
     const OString&        GetFontFileName() const   { return mpFontFile->GetFileName(); }
168be2b
     int                   GetFontFaceIndex() const  { return mnFaceNum; }
168be2b
+    int                   GetFontFaceVariation() const  { return mnFaceVariation; }
168be2b
     sal_IntPtr            GetFontId() const         { return mnFontId; }
168be2b
     bool                  IsSymbolFont() const      { return maDevFontAttributes.IsSymbolFont(); }
168be2b
     const FontAttributes& GetFontAttributes() const { return maDevFontAttributes; }
168be2b
@@ -80,6 +80,7 @@ private:
168be2b
     FT_FaceRec_*    maFaceFT;
168be2b
     FreetypeFontFile* const mpFontFile;
168be2b
     const int       mnFaceNum;
168be2b
+    const int       mnFaceVariation;
168be2b
     int             mnRefCount;
168be2b
     sal_IntPtr const mnFontId;
168be2b
     FontAttributes  maDevFontAttributes;
168be2b
diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx
168be2b
index 59811d6a144a..77a764e6e058 100644
168be2b
--- a/vcl/inc/unx/glyphcache.hxx
168be2b
+++ b/vcl/inc/unx/glyphcache.hxx
168be2b
@@ -57,9 +57,9 @@ public:
168be2b
 
168be2b
     static GlyphCache&      GetInstance();
168be2b
 
168be2b
-    void                    AddFontFile(
168be2b
-                                const OString& rNormalizedName,
168be2b
-                                int nFaceNum, sal_IntPtr nFontId,
168be2b
+    void                    AddFontFile(const OString& rNormalizedName,
168be2b
+                                int nFaceNum, int nVariantNum,
168be2b
+                                sal_IntPtr nFontId,
168be2b
                                 const FontAttributes&);
168be2b
 
168be2b
     void                    AnnounceFonts( PhysicalFontCollection* ) const;
168be2b
@@ -98,6 +98,7 @@ public:
168be2b
 
168be2b
     const OString&          GetFontFileName() const;
168be2b
     int                     GetFontFaceIndex() const;
168be2b
+    int                     GetFontFaceVariation() const;
168be2b
     bool                    TestFont() const { return mbFaceOk;}
168be2b
     FT_Face                 GetFtFace() const;
168be2b
     int                     GetLoadFlags() const { return (mnLoadFlags & ~FT_LOAD_IGNORE_TRANSFORM); }
168be2b
@@ -117,6 +118,7 @@ public:
168be2b
 
168be2b
     FreetypeFontInstance*   GetFontInstance() const { return mpFontInstance.get(); }
168be2b
 
168be2b
+    void                    SetFontVariationsOnHBFont(hb_font_t* pHbFace) const;
168be2b
 private:
168be2b
     friend class GlyphCache;
168be2b
     friend class FreetypeFontInstance;
168be2b
diff --git a/vcl/unx/generic/fontmanager/fontconfig.cxx b/vcl/unx/generic/fontmanager/fontconfig.cxx
168be2b
index 76598746bec6..7205ef386668 100644
168be2b
--- a/vcl/unx/generic/fontmanager/fontconfig.cxx
168be2b
+++ b/vcl/unx/generic/fontmanager/fontconfig.cxx
168be2b
@@ -467,6 +467,22 @@ static void lcl_FcFontSetRemove(FcFontSet* pFSet, int i)
168be2b
     memmove(pFSet->fonts + i, pFSet->fonts + i + 1, nTail*sizeof(FcPattern*));
168be2b
 }
168be2b
 
168be2b
+namespace
168be2b
+{
168be2b
+    // for variable fonts, FC_INDEX has been changed such that the lower half is now the
168be2b
+    // index of the font within the collection, and the upper half has been repurposed
168be2b
+    // as the index within the variations
168be2b
+    unsigned int GetCollectionIndex(unsigned int nEntryId)
168be2b
+    {
168be2b
+        return nEntryId & 0xFFFF;
168be2b
+    }
168be2b
+
168be2b
+    unsigned int GetVariationIndex(unsigned int nEntryId)
168be2b
+    {
168be2b
+        return nEntryId >> 16;
168be2b
+    }
168be2b
+}
168be2b
+
168be2b
 void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o_rVisitedPaths )
168be2b
 {
168be2b
     int nFonts = 0;
168be2b
@@ -487,7 +503,7 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o
168be2b
             int weight = 0;
168be2b
             int width = 0;
168be2b
             int spacing = 0;
168be2b
-            int nCollectionEntry = -1;
168be2b
+            int nEntryId = -1;
168be2b
             FcBool outline = false;
168be2b
 
168be2b
             FcResult eFileRes         = FcPatternGetString(pFSet->fonts[i], FC_FILE, 0, &file;;
168be2b
@@ -500,7 +516,7 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o
168be2b
             FcResult eWidthRes        = FcPatternGetInteger(pFSet->fonts[i], FC_WIDTH, 0, &width);
168be2b
             FcResult eSpacRes         = FcPatternGetInteger(pFSet->fonts[i], FC_SPACING, 0, &spacing);
168be2b
             FcResult eOutRes          = FcPatternGetBool(pFSet->fonts[i], FC_OUTLINE, 0, &outline);
168be2b
-            FcResult eIndexRes        = FcPatternGetInteger(pFSet->fonts[i], FC_INDEX, 0, &nCollectionEntry);
168be2b
+            FcResult eIndexRes        = FcPatternGetInteger(pFSet->fonts[i], FC_INDEX, 0, &nEntryId);
168be2b
             FcResult eFormatRes       = FcPatternGetString(pFSet->fonts[i], FC_FONTFORMAT, 0, &format);
168be2b
 
168be2b
             if( eFileRes != FcResultMatch || eFamilyRes != FcResultMatch || eOutRes != FcResultMatch )
168be2b
@@ -565,8 +581,9 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o
168be2b
             else // more than one font
168be2b
             {
168be2b
                 // a collection entry, get the correct index
168be2b
-                if( eIndexRes == FcResultMatch && nCollectionEntry != -1 )
168be2b
+                if( eIndexRes == FcResultMatch && nEntryId != -1 )
168be2b
                 {
168be2b
+                    int nCollectionEntry = GetCollectionIndex(nEntryId);
168be2b
                     for (auto & font : aFonts)
168be2b
                     {
168be2b
                         if( font->m_nCollectionEntry == nCollectionEntry )
168be2b
@@ -583,14 +600,14 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o
168be2b
                     // additional entries will be created in the cache
168be2b
                     // if this is a new index (that is if the loop above
168be2b
                     // ran to the end of the list)
168be2b
-                    xUpdate->m_nCollectionEntry = nCollectionEntry;
168be2b
+                    xUpdate->m_nCollectionEntry = GetCollectionIndex(nEntryId);
168be2b
                 }
168be2b
                 else
168be2b
                 {
168be2b
                     SAL_INFO(
168be2b
                         "vcl.fonts",
168be2b
                         "multiple fonts for file, but no index in fontconfig pattern ! (index res ="
168be2b
-                        << eIndexRes << " collection entry = " << nCollectionEntry
168be2b
+                        << eIndexRes << " collection entry = " << nEntryId
168be2b
                         << "; file will not be used");
168be2b
                     // we have found more than one font in this file
168be2b
                     // but fontconfig will not tell us which index is meant
168be2b
@@ -610,9 +627,9 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o
168be2b
                 if( eSlantRes == FcResultMatch )
168be2b
                     xUpdate->m_eItalic = convertSlant(slant);
168be2b
                 if( eStyleRes == FcResultMatch )
168be2b
-                {
168be2b
                     xUpdate->m_aStyleName = OStringToOUString( OString( reinterpret_cast<char*>(style) ), RTL_TEXTENCODING_UTF8 );
168be2b
-                }
168be2b
+                if( eIndexRes == FcResultMatch )
168be2b
+                    xUpdate->m_nVariationEntry = GetVariationIndex(nEntryId);
168be2b
 
168be2b
                 // sort into known fonts
168be2b
                 fontID aFont = m_nNextFontID++;
168be2b
@@ -933,16 +950,16 @@ void PrintFontManager::Substitute(FontSelectPattern &rPattern, OUString& rMissin
168be2b
             //extract the closest match
168be2b
             FcChar8* file = nullptr;
168be2b
             FcResult eFileRes = FcPatternGetString(pSet->fonts[0], FC_FILE, 0, &file;;
168be2b
-            int nCollectionEntry = 0;
168be2b
-            FcResult eIndexRes = FcPatternGetInteger(pSet->fonts[0], FC_INDEX, 0, &nCollectionEntry);
168be2b
+            int nEntryId = 0;
168be2b
+            FcResult eIndexRes = FcPatternGetInteger(pSet->fonts[0], FC_INDEX, 0, &nEntryId);
168be2b
             if (eIndexRes != FcResultMatch)
168be2b
-                nCollectionEntry = 0;
168be2b
+                nEntryId = 0;
168be2b
             if( eFileRes == FcResultMatch )
168be2b
             {
168be2b
                 OString aDir, aBase, aOrgPath( reinterpret_cast<char*>(file) );
168be2b
                 splitPath( aOrgPath, aDir, aBase );
168be2b
                 int nDirID = getDirectoryAtom( aDir );
168be2b
-                fontID aFont = findFontFileID( nDirID, aBase, nCollectionEntry );
168be2b
+                fontID aFont = findFontFileID(nDirID, aBase, GetCollectionIndex(nEntryId), GetVariationIndex(nEntryId));
168be2b
                 if( aFont > 0 )
168be2b
                 {
168be2b
                     FastPrintFontInfo aInfo;
168be2b
@@ -1060,12 +1077,13 @@ FcPattern *FontConfigFontOptions::GetPattern() const
168be2b
     return mpPattern;
168be2b
 }
168be2b
 
168be2b
-void FontConfigFontOptions::SyncPattern(const OString& rFileName, int nIndex, bool bEmbolden)
168be2b
+void FontConfigFontOptions::SyncPattern(const OString& rFileName, sal_uInt32 nIndex, sal_uInt32 nVariation, bool bEmbolden)
168be2b
 {
168be2b
     FcPatternDel(mpPattern, FC_FILE);
168be2b
     FcPatternAddString(mpPattern, FC_FILE, reinterpret_cast<FcChar8 const *>(rFileName.getStr()));
168be2b
     FcPatternDel(mpPattern, FC_INDEX);
168be2b
-    FcPatternAddInteger(mpPattern, FC_INDEX, nIndex);
168be2b
+    sal_uInt32 nFcIndex = (nVariation << 16) | nIndex;
168be2b
+    FcPatternAddInteger(mpPattern, FC_INDEX, nFcIndex);
168be2b
     FcPatternDel(mpPattern, FC_EMBOLDEN);
168be2b
     FcPatternAddBool(mpPattern, FC_EMBOLDEN, bEmbolden ? FcTrue : FcFalse);
168be2b
 }
168be2b
@@ -1145,16 +1163,18 @@ void PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const css::lang::Loc
168be2b
             //extract the closest match
168be2b
             FcChar8* file = nullptr;
168be2b
             FcResult eFileRes = FcPatternGetString(pSet->fonts[0], FC_FILE, 0, &file;;
168be2b
-            int nCollectionEntry = 0;
168be2b
-            FcResult eIndexRes = FcPatternGetInteger(pSet->fonts[0], FC_INDEX, 0, &nCollectionEntry);
168be2b
+            int nEntryId = 0;
168be2b
+            FcResult eIndexRes = FcPatternGetInteger(pSet->fonts[0], FC_INDEX, 0, &nEntryId);
168be2b
             if (eIndexRes != FcResultMatch)
168be2b
-                nCollectionEntry = 0;
168be2b
+                nEntryId = 0;
168be2b
             if( eFileRes == FcResultMatch )
168be2b
             {
168be2b
                 OString aDir, aBase, aOrgPath( reinterpret_cast<char*>(file) );
168be2b
                 splitPath( aOrgPath, aDir, aBase );
168be2b
                 int nDirID = getDirectoryAtom( aDir );
168be2b
-                fontID aFont = findFontFileID( nDirID, aBase, nCollectionEntry );
168be2b
+                fontID aFont = findFontFileID(nDirID, aBase,
168be2b
+                                              GetCollectionIndex(nEntryId),
168be2b
+                                              GetVariationIndex(nEntryId));
168be2b
                 if( aFont > 0 )
168be2b
                     getFontFastInfo( aFont, rInfo );
168be2b
             }
168be2b
diff --git a/vcl/unx/generic/fontmanager/fontmanager.cxx b/vcl/unx/generic/fontmanager/fontmanager.cxx
168be2b
index 394c5484a5bd..16e8b786dc88 100644
168be2b
--- a/vcl/unx/generic/fontmanager/fontmanager.cxx
168be2b
+++ b/vcl/unx/generic/fontmanager/fontmanager.cxx
168be2b
@@ -108,6 +108,7 @@ PrintFontManager::PrintFont::PrintFont()
168be2b
 ,   m_nYMax(0)
168be2b
 ,   m_nDirectory(0)
168be2b
 ,   m_nCollectionEntry(0)
168be2b
+,   m_nVariationEntry(0)
168be2b
 {
168be2b
 }
168be2b
 
168be2b
@@ -278,7 +279,7 @@ std::vector<std::unique_ptr<PrintFontManager::PrintFont>> PrintFontManager::anal
168be2b
     return aNewFonts;
168be2b
 }
168be2b
 
168be2b
-fontID PrintFontManager::findFontFileID( int nDirID, const OString& rFontFile, int nFaceIndex ) const
168be2b
+fontID PrintFontManager::findFontFileID(int nDirID, const OString& rFontFile, int nFaceIndex, int nVariationIndex) const
168be2b
 {
168be2b
     fontID nID = 0;
168be2b
 
168be2b
@@ -293,7 +294,9 @@ fontID PrintFontManager::findFontFileID( int nDirID, const OString& rFontFile, i
168be2b
             continue;
168be2b
         PrintFont* const pFont = (*it).second.get();
168be2b
         if (pFont->m_nDirectory == nDirID &&
168be2b
-            pFont->m_aFontFile == rFontFile && pFont->m_nCollectionEntry == nFaceIndex)
168be2b
+            pFont->m_aFontFile == rFontFile &&
168be2b
+            pFont->m_nCollectionEntry == nFaceIndex &&
168be2b
+            pFont->m_nVariationEntry == nVariationIndex)
168be2b
         {
168be2b
             nID = it->first;
168be2b
             if (nID)
168be2b
@@ -838,6 +841,19 @@ int PrintFontManager::getFontFaceNumber( fontID nFontID ) const
168be2b
     return nRet;
168be2b
 }
168be2b
 
168be2b
+int PrintFontManager::getFontFaceVariation( fontID nFontID ) const
168be2b
+{
168be2b
+    int nRet = 0;
168be2b
+    PrintFont* pFont = getFont( nFontID );
168be2b
+    if (pFont)
168be2b
+    {
168be2b
+        nRet = pFont->m_nVariationEntry;
168be2b
+        if (nRet < 0)
168be2b
+            nRet = 0;
168be2b
+    }
168be2b
+    return nRet;
168be2b
+}
168be2b
+
168be2b
 FontFamily PrintFontManager::matchFamilyName( const OUString& rFamily )
168be2b
 {
168be2b
     typedef struct {
168be2b
diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx
168be2b
index c8956d02226b..f9e6a0a522a1 100644
168be2b
--- a/vcl/unx/generic/gdi/cairotextrender.cxx
168be2b
+++ b/vcl/unx/generic/gdi/cairotextrender.cxx
168be2b
@@ -408,12 +408,13 @@ void CairoTextRender::GetDevFontList( PhysicalFontCollection* pFontCollection )
168be2b
 
168be2b
         // normalize face number to the GlyphCache
168be2b
         int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
168be2b
+        int nVariantNum = rMgr.getFontFaceVariation( aInfo.m_nID );
168be2b
 
168be2b
         // inform GlyphCache about this font provided by the PsPrint subsystem
168be2b
         FontAttributes aDFA = GenPspGraphics::Info2FontAttributes( aInfo );
168be2b
         aDFA.IncreaseQualityBy( 4096 );
168be2b
         const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
168be2b
-        rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
168be2b
+        rGC.AddFontFile( rFileName, nFaceNum, nVariantNum, aInfo.m_nID, aDFA );
168be2b
    }
168be2b
 
168be2b
     // announce glyphcache fonts
168be2b
diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
168be2b
index 42bf6d0a98b9..1fcb0938ef77 100644
168be2b
--- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
168be2b
+++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx
168be2b
@@ -47,6 +47,7 @@
168be2b
 #include <ft2build.h>
168be2b
 #include FT_FREETYPE_H
168be2b
 #include FT_GLYPH_H
168be2b
+#include FT_MULTIPLE_MASTERS_H
168be2b
 #include FT_OUTLINE_H
168be2b
 #include FT_SIZES_H
168be2b
 #include FT_SYNTHESIS_H
168be2b
@@ -166,11 +167,12 @@ void FreetypeFontFile::Unmap()
168be2b
 }
168be2b
 
168be2b
 FreetypeFontInfo::FreetypeFontInfo( const FontAttributes& rDevFontAttributes,
168be2b
-    const OString& rNativeFileName, int nFaceNum, sal_IntPtr nFontId)
168be2b
+    const OString& rNativeFileName, int nFaceNum, int nFaceVariation, sal_IntPtr nFontId)
168be2b
 :
168be2b
     maFaceFT( nullptr ),
168be2b
     mpFontFile( FreetypeFontFile::FindFontFile( rNativeFileName ) ),
168be2b
     mnFaceNum( nFaceNum ),
168be2b
+    mnFaceVariation( nFaceVariation ),
168be2b
     mnRefCount( 0 ),
168be2b
     mnFontId( nFontId ),
168be2b
     maDevFontAttributes( rDevFontAttributes )
168be2b
@@ -194,12 +196,50 @@ FT_FaceRec_* FreetypeFontInfo::GetFaceFT()
168be2b
             mpFontFile->GetFileSize(), mnFaceNum, &maFaceFT );
168be2b
         if( (rc != FT_Err_Ok) || (maFaceFT->num_glyphs <= 0) )
168be2b
             maFaceFT = nullptr;
168be2b
+
168be2b
+        if (maFaceFT && mnFaceVariation)
168be2b
+        {
168be2b
+            FT_MM_Var *pFtMMVar;
168be2b
+            if (FT_Get_MM_Var(maFaceFT, &pFtMMVar) == 0)
168be2b
+            {
168be2b
+                if (static_cast<sal_uInt32>(mnFaceVariation) <= pFtMMVar->num_namedstyles)
168be2b
+                {
168be2b
+                    FT_Var_Named_Style *instance = &pFtMMVar->namedstyle[mnFaceVariation - 1];
168be2b
+                    FT_Set_Var_Design_Coordinates(maFaceFT, pFtMMVar->num_axis, instance->coords);
168be2b
+                }
168be2b
+                FT_Done_MM_Var(aLibFT, pFtMMVar);
168be2b
+            }
168be2b
+        }
168be2b
     }
168be2b
 
168be2b
    ++mnRefCount;
168be2b
    return maFaceFT;
168be2b
 }
168be2b
 
168be2b
+void FreetypeFont::SetFontVariationsOnHBFont(hb_font_t* pHbFace) const
168be2b
+{
168be2b
+    sal_uInt32 nFaceVariation = mpFontInfo->GetFontFaceVariation();
168be2b
+    if (maFaceFT && nFaceVariation)
168be2b
+    {
168be2b
+        FT_MM_Var *pFtMMVar;
168be2b
+        if (FT_Get_MM_Var(maFaceFT, &pFtMMVar) == 0)
168be2b
+        {
168be2b
+            if (nFaceVariation <= pFtMMVar->num_namedstyles)
168be2b
+            {
168be2b
+                FT_Var_Named_Style *instance = &pFtMMVar->namedstyle[nFaceVariation - 1];
168be2b
+                std::vector<hb_variation_t> aVariations(pFtMMVar->num_axis);
168be2b
+                for (FT_UInt i = 0; i < pFtMMVar->num_axis; ++i)
168be2b
+                {
168be2b
+                    aVariations[i].tag = pFtMMVar->axis[i].tag;
168be2b
+                    aVariations[i].value = instance->coords[i] / 65536.0;
168be2b
+                }
168be2b
+                hb_font_set_variations(pHbFace, aVariations.data(), aVariations.size());
168be2b
+            }
168be2b
+            FT_Done_MM_Var(aLibFT, pFtMMVar);
168be2b
+        }
168be2b
+    }
168be2b
+}
168be2b
+
168be2b
 void FreetypeFontInfo::ReleaseFaceFT()
168be2b
 {
168be2b
     if (--mnRefCount <= 0)
168be2b
@@ -289,8 +329,8 @@ FT_Face FreetypeFont::GetFtFace() const
168be2b
     return maFaceFT;
168be2b
 }
168be2b
 
168be2b
-void GlyphCache::AddFontFile( const OString& rNormalizedName,
168be2b
-    int nFaceNum, sal_IntPtr nFontId, const FontAttributes& rDevFontAttr)
168be2b
+void GlyphCache::AddFontFile(const OString& rNormalizedName,
168be2b
+    int nFaceNum, int nVariantNum, sal_IntPtr nFontId, const FontAttributes& rDevFontAttr)
168be2b
 {
168be2b
     if( rNormalizedName.isEmpty() )
168be2b
         return;
168be2b
@@ -299,7 +339,7 @@ void GlyphCache::AddFontFile( const OString& rNormalizedName,
168be2b
         return;
168be2b
 
168be2b
     FreetypeFontInfo* pFontInfo = new FreetypeFontInfo( rDevFontAttr,
168be2b
-        rNormalizedName, nFaceNum, nFontId);
168be2b
+        rNormalizedName, nFaceNum, nVariantNum, nFontId);
168be2b
     m_aFontInfoList[ nFontId ].reset(pFontInfo);
168be2b
     if( m_nMaxFontId < nFontId )
168be2b
         m_nMaxFontId = nFontId;
168be2b
@@ -441,7 +481,7 @@ const FontConfigFontOptions* FreetypeFont::GetFontOptions() const
168be2b
     if (!mxFontOptions)
168be2b
     {
168be2b
         mxFontOptions.reset(GetFCFontOptions(mpFontInfo->GetFontAttributes(), mpFontInstance->GetFontSelectPattern().mnHeight));
168be2b
-        mxFontOptions->SyncPattern(GetFontFileName(), GetFontFaceIndex(), NeedsArtificialBold());
168be2b
+        mxFontOptions->SyncPattern(GetFontFileName(), GetFontFaceIndex(), GetFontFaceVariation(), NeedsArtificialBold());
168be2b
     }
168be2b
     return mxFontOptions.get();
168be2b
 }
168be2b
@@ -461,6 +501,11 @@ int FreetypeFont::GetFontFaceIndex() const
168be2b
     return mpFontInfo->GetFontFaceIndex();
168be2b
 }
168be2b
 
168be2b
+int FreetypeFont::GetFontFaceVariation() const
168be2b
+{
168be2b
+    return mpFontInfo->GetFontFaceVariation();
168be2b
+}
168be2b
+
168be2b
 FreetypeFont::~FreetypeFont()
168be2b
 {
168be2b
     if( maSizeFT )
168be2b
diff --git a/vcl/unx/generic/glyphs/glyphcache.cxx b/vcl/unx/generic/glyphs/glyphcache.cxx
168be2b
index b541fe1861fe..d4a32f30a521 100644
168be2b
--- a/vcl/unx/generic/glyphs/glyphcache.cxx
168be2b
+++ b/vcl/unx/generic/glyphs/glyphcache.cxx
168be2b
@@ -298,7 +298,10 @@ static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pU
168be2b
 
168be2b
 hb_font_t* FreetypeFontInstance::ImplInitHbFont()
168be2b
 {
168be2b
-    return InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr));
168be2b
+    hb_font_t* pRet = InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr));
168be2b
+    assert(mpFreetypeFont);
168be2b
+    mpFreetypeFont->SetFontVariationsOnHBFont(pRet);
168be2b
+    return pRet;
168be2b
 }
168be2b
 
168be2b
 bool FreetypeFontInstance::ImplGetGlyphBoundRect(sal_GlyphId nId, tools::Rectangle& rRect, bool bVertical) const
168be2b
diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx
168be2b
index e40b9fd5cc82..c5675bfa3bcd 100644
168be2b
--- a/vcl/unx/generic/print/genpspgraphics.cxx
168be2b
+++ b/vcl/unx/generic/print/genpspgraphics.cxx
168be2b
@@ -694,9 +694,10 @@ bool GenPspGraphics::AddTempDevFontHelper( PhysicalFontCollection* pFontCollecti
168be2b
         aDFA.IncreaseQualityBy( 5800 );
168be2b
 
168be2b
         int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
168be2b
+        int nVariantNum = rMgr.getFontFaceVariation( aInfo.m_nID );
168be2b
 
168be2b
         const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
168be2b
-        rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
168be2b
+        rGC.AddFontFile( rFileName, nFaceNum, nVariantNum, aInfo.m_nID, aDFA );
168be2b
     }
168be2b
 
168be2b
     // announce new font to device's font list
168be2b
-- 
168be2b
2.21.0
168be2b