diff options
author | Caolán McNamara <caolanm@redhat.com> | 2019-03-21 12:12:49 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2019-03-22 11:15:27 +0100 |
commit | cb54bb89494218589227246f1923d8a24ab1676a (patch) | |
tree | 8702b630c767233c4a8850d68c982c18811f09da /vcl/unx | |
parent | c094442f997054bbfdacc0d9f213dc218453d29c (diff) |
rhbz#1690732 basic font variation support
on the fontconfig/harfbuzz/cairo drawing path for preset variations
Change-Id: I95ef68aecfd59687ae9aae58e01e394c83c6ea9e
Reviewed-on: https://gerrit.libreoffice.org/69505
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl/unx')
-rw-r--r-- | vcl/unx/generic/fontmanager/fontconfig.cxx | 48 | ||||
-rw-r--r-- | vcl/unx/generic/fontmanager/fontmanager.cxx | 20 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/cairotextrender.cxx | 3 | ||||
-rw-r--r-- | vcl/unx/generic/glyphs/freetype_glyphcache.cxx | 71 | ||||
-rw-r--r-- | vcl/unx/generic/glyphs/glyphcache.cxx | 5 | ||||
-rw-r--r-- | vcl/unx/generic/print/genpspgraphics.cxx | 3 |
6 files changed, 117 insertions, 33 deletions
diff --git a/vcl/unx/generic/fontmanager/fontconfig.cxx b/vcl/unx/generic/fontmanager/fontconfig.cxx index 374321bc1eb3..003e163d8777 100644 --- a/vcl/unx/generic/fontmanager/fontconfig.cxx +++ b/vcl/unx/generic/fontmanager/fontconfig.cxx @@ -472,9 +472,14 @@ namespace // for variable fonts, FC_INDEX has been changed such that the lower half is now the // index of the font within the collection, and the upper half has been repurposed // as the index within the variations - unsigned int GetCollectionIndex(unsigned int nCollectionEntryId) + unsigned int GetCollectionIndex(unsigned int nEntryId) { - return nCollectionEntryId & 0xFFFF; + return nEntryId & 0xFFFF; + } + + unsigned int GetVariationIndex(unsigned int nEntryId) + { + return nEntryId >> 16; } } @@ -498,7 +503,7 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o int weight = 0; int width = 0; int spacing = 0; - int nCollectionEntryId = -1; + int nEntryId = -1; FcBool outline = false; FcResult eFileRes = FcPatternGetString(pFSet->fonts[i], FC_FILE, 0, &file); @@ -511,7 +516,7 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o FcResult eWidthRes = FcPatternGetInteger(pFSet->fonts[i], FC_WIDTH, 0, &width); FcResult eSpacRes = FcPatternGetInteger(pFSet->fonts[i], FC_SPACING, 0, &spacing); FcResult eOutRes = FcPatternGetBool(pFSet->fonts[i], FC_OUTLINE, 0, &outline); - FcResult eIndexRes = FcPatternGetInteger(pFSet->fonts[i], FC_INDEX, 0, &nCollectionEntryId); + FcResult eIndexRes = FcPatternGetInteger(pFSet->fonts[i], FC_INDEX, 0, &nEntryId); FcResult eFormatRes = FcPatternGetString(pFSet->fonts[i], FC_FONTFORMAT, 0, &format); if( eFileRes != FcResultMatch || eFamilyRes != FcResultMatch || eOutRes != FcResultMatch ) @@ -576,9 +581,9 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o else // more than one font { // a collection entry, get the correct index - if( eIndexRes == FcResultMatch && nCollectionEntryId != -1 ) + if( eIndexRes == FcResultMatch && nEntryId != -1 ) { - int nCollectionEntry = GetCollectionIndex(nCollectionEntryId); + int nCollectionEntry = GetCollectionIndex(nEntryId); for (auto & font : aFonts) { if( font->m_nCollectionEntry == nCollectionEntry ) @@ -595,14 +600,14 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o // additional entries will be created in the cache // if this is a new index (that is if the loop above // ran to the end of the list) - xUpdate->m_nCollectionEntry = GetCollectionIndex(nCollectionEntryId); + xUpdate->m_nCollectionEntry = GetCollectionIndex(nEntryId); } else { SAL_INFO( "vcl.fonts", "multiple fonts for file, but no index in fontconfig pattern ! (index res =" - << eIndexRes << " collection entry = " << nCollectionEntryId + << eIndexRes << " collection entry = " << nEntryId << "; file will not be used"); // we have found more than one font in this file // but fontconfig will not tell us which index is meant @@ -622,9 +627,9 @@ void PrintFontManager::countFontconfigFonts( std::unordered_map<OString, int>& o if( eSlantRes == FcResultMatch ) xUpdate->m_eItalic = convertSlant(slant); if( eStyleRes == FcResultMatch ) - { xUpdate->m_aStyleName = OStringToOUString( OString( reinterpret_cast<char*>(style) ), RTL_TEXTENCODING_UTF8 ); - } + if( eIndexRes == FcResultMatch ) + xUpdate->m_nVariationEntry = GetVariationIndex(nEntryId); // sort into known fonts fontID aFont = m_nNextFontID++; @@ -945,16 +950,16 @@ void PrintFontManager::Substitute(FontSelectPattern &rPattern, OUString& rMissin //extract the closest match FcChar8* file = nullptr; FcResult eFileRes = FcPatternGetString(pSet->fonts[0], FC_FILE, 0, &file); - int nCollectionEntryId = 0; - FcResult eIndexRes = FcPatternGetInteger(pSet->fonts[0], FC_INDEX, 0, &nCollectionEntryId); + int nEntryId = 0; + FcResult eIndexRes = FcPatternGetInteger(pSet->fonts[0], FC_INDEX, 0, &nEntryId); if (eIndexRes != FcResultMatch) - nCollectionEntryId = 0; + nEntryId = 0; if( eFileRes == FcResultMatch ) { OString aDir, aBase, aOrgPath( reinterpret_cast<char*>(file) ); splitPath( aOrgPath, aDir, aBase ); int nDirID = getDirectoryAtom( aDir ); - fontID aFont = findFontFileID( nDirID, aBase, GetCollectionIndex(nCollectionEntryId) ); + fontID aFont = findFontFileID(nDirID, aBase, GetCollectionIndex(nEntryId), GetVariationIndex(nEntryId)); if( aFont > 0 ) { FastPrintFontInfo aInfo; @@ -1076,12 +1081,13 @@ FcPattern *FontConfigFontOptions::GetPattern() const return mpPattern; } -void FontConfigFontOptions::SyncPattern(const OString& rFileName, int nIndex, bool bEmbolden) +void FontConfigFontOptions::SyncPattern(const OString& rFileName, sal_uInt32 nIndex, sal_uInt32 nVariation, bool bEmbolden) { FcPatternDel(mpPattern, FC_FILE); FcPatternAddString(mpPattern, FC_FILE, reinterpret_cast<FcChar8 const *>(rFileName.getStr())); FcPatternDel(mpPattern, FC_INDEX); - FcPatternAddInteger(mpPattern, FC_INDEX, nIndex); + sal_uInt32 nFcIndex = (nVariation << 16) | nIndex; + FcPatternAddInteger(mpPattern, FC_INDEX, nFcIndex); FcPatternDel(mpPattern, FC_EMBOLDEN); FcPatternAddBool(mpPattern, FC_EMBOLDEN, bEmbolden ? FcTrue : FcFalse); } @@ -1161,16 +1167,18 @@ void PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const css::lang::Loc //extract the closest match FcChar8* file = nullptr; FcResult eFileRes = FcPatternGetString(pSet->fonts[0], FC_FILE, 0, &file); - int nCollectionEntry = 0; - FcResult eIndexRes = FcPatternGetInteger(pSet->fonts[0], FC_INDEX, 0, &nCollectionEntry); + int nEntryId = 0; + FcResult eIndexRes = FcPatternGetInteger(pSet->fonts[0], FC_INDEX, 0, &nEntryId); if (eIndexRes != FcResultMatch) - nCollectionEntry = 0; + nEntryId = 0; if( eFileRes == FcResultMatch ) { OString aDir, aBase, aOrgPath( reinterpret_cast<char*>(file) ); splitPath( aOrgPath, aDir, aBase ); int nDirID = getDirectoryAtom( aDir ); - fontID aFont = findFontFileID( nDirID, aBase, nCollectionEntry ); + fontID aFont = findFontFileID(nDirID, aBase, + GetCollectionIndex(nEntryId), + GetVariationIndex(nEntryId)); if( aFont > 0 ) getFontFastInfo( aFont, rInfo ); } diff --git a/vcl/unx/generic/fontmanager/fontmanager.cxx b/vcl/unx/generic/fontmanager/fontmanager.cxx index b681fba944d2..21aa4d768d1b 100644 --- a/vcl/unx/generic/fontmanager/fontmanager.cxx +++ b/vcl/unx/generic/fontmanager/fontmanager.cxx @@ -108,6 +108,7 @@ PrintFontManager::PrintFont::PrintFont() , m_nYMax(0) , m_nDirectory(0) , m_nCollectionEntry(0) +, m_nVariationEntry(0) { } @@ -275,7 +276,7 @@ std::vector<std::unique_ptr<PrintFontManager::PrintFont>> PrintFontManager::anal return aNewFonts; } -fontID PrintFontManager::findFontFileID( int nDirID, const OString& rFontFile, int nFaceIndex ) const +fontID PrintFontManager::findFontFileID(int nDirID, const OString& rFontFile, int nFaceIndex, int nVariationIndex) const { fontID nID = 0; @@ -290,7 +291,9 @@ fontID PrintFontManager::findFontFileID( int nDirID, const OString& rFontFile, i continue; PrintFont* const pFont = (*it).second.get(); if (pFont->m_nDirectory == nDirID && - pFont->m_aFontFile == rFontFile && pFont->m_nCollectionEntry == nFaceIndex) + pFont->m_aFontFile == rFontFile && + pFont->m_nCollectionEntry == nFaceIndex && + pFont->m_nVariationEntry == nVariationIndex) { nID = it->first; if (nID) @@ -835,6 +838,19 @@ int PrintFontManager::getFontFaceNumber( fontID nFontID ) const return nRet; } +int PrintFontManager::getFontFaceVariation( fontID nFontID ) const +{ + int nRet = 0; + PrintFont* pFont = getFont( nFontID ); + if (pFont) + { + nRet = pFont->m_nVariationEntry; + if (nRet < 0) + nRet = 0; + } + return nRet; +} + FontFamily PrintFontManager::matchFamilyName( const OUString& rFamily ) { struct family_t { diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx index 2c368e6a765e..d6355e65f173 100644 --- a/vcl/unx/generic/gdi/cairotextrender.cxx +++ b/vcl/unx/generic/gdi/cairotextrender.cxx @@ -407,12 +407,13 @@ void CairoTextRender::GetDevFontList( PhysicalFontCollection* pFontCollection ) // normalize face number to the GlyphCache int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID ); + int nVariantNum = rMgr.getFontFaceVariation( aInfo.m_nID ); // inform GlyphCache about this font provided by the PsPrint subsystem FontAttributes aDFA = GenPspGraphics::Info2FontAttributes( aInfo ); aDFA.IncreaseQualityBy( 4096 ); const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID ); - rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA ); + rGC.AddFontFile( rFileName, nFaceNum, nVariantNum, aInfo.m_nID, aDFA ); } // announce glyphcache fonts diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx index 7926df64f12c..42eff115aaee 100644 --- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx +++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx @@ -47,6 +47,7 @@ #include <ft2build.h> #include FT_FREETYPE_H #include FT_GLYPH_H +#include FT_MULTIPLE_MASTERS_H #include FT_OUTLINE_H #include FT_SIZES_H #include FT_SYNTHESIS_H @@ -60,6 +61,7 @@ // TODO: move file mapping stuff to OSL #include <unistd.h> +#include <dlfcn.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/mman.h> @@ -162,11 +164,12 @@ void FreetypeFontFile::Unmap() } FreetypeFontInfo::FreetypeFontInfo( const FontAttributes& rDevFontAttributes, - const OString& rNativeFileName, int nFaceNum, sal_IntPtr nFontId) + const OString& rNativeFileName, int nFaceNum, int nFaceVariation, sal_IntPtr nFontId) : maFaceFT( nullptr ), mpFontFile( FreetypeFontFile::FindFontFile( rNativeFileName ) ), mnFaceNum( nFaceNum ), + mnFaceVariation( nFaceVariation ), mnRefCount( 0 ), mnFontId( nFontId ), maDevFontAttributes( rDevFontAttributes ) @@ -181,6 +184,18 @@ FreetypeFontInfo::~FreetypeFontInfo() { } +namespace +{ + void dlFT_Done_MM_Var(FT_Library library, FT_MM_Var *amaster) + { + static auto func = reinterpret_cast<void(*)(FT_Library, FT_MM_Var*)>(dlsym(nullptr, "FT_Done_MM_Var")); + if (func) + func(library, amaster); + else + free(amaster); + } +} + FT_FaceRec_* FreetypeFontInfo::GetFaceFT() { if (!maFaceFT && mpFontFile->Map()) @@ -190,12 +205,50 @@ FT_FaceRec_* FreetypeFontInfo::GetFaceFT() mpFontFile->GetFileSize(), mnFaceNum, &maFaceFT ); if( (rc != FT_Err_Ok) || (maFaceFT->num_glyphs <= 0) ) maFaceFT = nullptr; + + if (maFaceFT && mnFaceVariation) + { + FT_MM_Var *pFtMMVar; + if (FT_Get_MM_Var(maFaceFT, &pFtMMVar) == 0) + { + if (static_cast<sal_uInt32>(mnFaceVariation) <= pFtMMVar->num_namedstyles) + { + FT_Var_Named_Style *instance = &pFtMMVar->namedstyle[mnFaceVariation - 1]; + FT_Set_Var_Design_Coordinates(maFaceFT, pFtMMVar->num_axis, instance->coords); + } + dlFT_Done_MM_Var(aLibFT, pFtMMVar); + } + } } ++mnRefCount; return maFaceFT; } +void FreetypeFont::SetFontVariationsOnHBFont(hb_font_t* pHbFace) const +{ + sal_uInt32 nFaceVariation = mpFontInfo->GetFontFaceVariation(); + if (maFaceFT && nFaceVariation) + { + FT_MM_Var *pFtMMVar; + if (FT_Get_MM_Var(maFaceFT, &pFtMMVar) == 0) + { + if (nFaceVariation <= pFtMMVar->num_namedstyles) + { + FT_Var_Named_Style *instance = &pFtMMVar->namedstyle[nFaceVariation - 1]; + std::vector<hb_variation_t> aVariations(pFtMMVar->num_axis); + for (FT_UInt i = 0; i < pFtMMVar->num_axis; ++i) + { + aVariations[i].tag = pFtMMVar->axis[i].tag; + aVariations[i].value = instance->coords[i] / 65536.0; + } + hb_font_set_variations(pHbFace, aVariations.data(), aVariations.size()); + } + dlFT_Done_MM_Var(aLibFT, pFtMMVar); + } + } +} + void FreetypeFontInfo::ReleaseFaceFT() { if (--mnRefCount <= 0) @@ -259,9 +312,6 @@ void GlyphCache::InitFreetype() { /*FT_Error rcFT =*/ FT_Init_FreeType( &aLibFT ); - FT_Int nMajor = 0, nMinor = 0, nPatch = 0; - FT_Library_Version(aLibFT, &nMajor, &nMinor, &nPatch); - // TODO: remove when the priorities are selected by UI char* pEnv; pEnv = ::getenv( "SAL_EMBEDDED_BITMAP_PRIORITY" ); @@ -281,8 +331,8 @@ FT_Face FreetypeFont::GetFtFace() const return maFaceFT; } -void GlyphCache::AddFontFile( const OString& rNormalizedName, - int nFaceNum, sal_IntPtr nFontId, const FontAttributes& rDevFontAttr) +void GlyphCache::AddFontFile(const OString& rNormalizedName, + int nFaceNum, int nVariantNum, sal_IntPtr nFontId, const FontAttributes& rDevFontAttr) { if( rNormalizedName.isEmpty() ) return; @@ -291,7 +341,7 @@ void GlyphCache::AddFontFile( const OString& rNormalizedName, return; FreetypeFontInfo* pFontInfo = new FreetypeFontInfo( rDevFontAttr, - rNormalizedName, nFaceNum, nFontId); + rNormalizedName, nFaceNum, nVariantNum, nFontId); m_aFontInfoList[ nFontId ].reset(pFontInfo); if( m_nMaxFontId < nFontId ) m_nMaxFontId = nFontId; @@ -433,7 +483,7 @@ const FontConfigFontOptions* FreetypeFont::GetFontOptions() const if (!mxFontOptions) { mxFontOptions.reset(GetFCFontOptions(mpFontInfo->GetFontAttributes(), mpFontInstance->GetFontSelectPattern().mnHeight)); - mxFontOptions->SyncPattern(GetFontFileName(), GetFontFaceIndex(), NeedsArtificialBold()); + mxFontOptions->SyncPattern(GetFontFileName(), GetFontFaceIndex(), GetFontFaceVariation(), NeedsArtificialBold()); } return mxFontOptions.get(); } @@ -453,6 +503,11 @@ int FreetypeFont::GetFontFaceIndex() const return mpFontInfo->GetFontFaceIndex(); } +int FreetypeFont::GetFontFaceVariation() const +{ + return mpFontInfo->GetFontFaceVariation(); +} + FreetypeFont::~FreetypeFont() { if( maSizeFT ) diff --git a/vcl/unx/generic/glyphs/glyphcache.cxx b/vcl/unx/generic/glyphs/glyphcache.cxx index 3578e99174b1..0aa8be45e84a 100644 --- a/vcl/unx/generic/glyphs/glyphcache.cxx +++ b/vcl/unx/generic/glyphs/glyphcache.cxx @@ -298,7 +298,10 @@ static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pU hb_font_t* FreetypeFontInstance::ImplInitHbFont() { - return InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr)); + hb_font_t* pRet = InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr)); + assert(mpFreetypeFont); + mpFreetypeFont->SetFontVariationsOnHBFont(pRet); + return pRet; } bool FreetypeFontInstance::ImplGetGlyphBoundRect(sal_GlyphId nId, tools::Rectangle& rRect, bool bVertical) const diff --git a/vcl/unx/generic/print/genpspgraphics.cxx b/vcl/unx/generic/print/genpspgraphics.cxx index 13d17c56222b..b62bd7f90e8f 100644 --- a/vcl/unx/generic/print/genpspgraphics.cxx +++ b/vcl/unx/generic/print/genpspgraphics.cxx @@ -693,9 +693,10 @@ bool GenPspGraphics::AddTempDevFontHelper( PhysicalFontCollection* pFontCollecti aDFA.IncreaseQualityBy( 5800 ); int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID ); + int nVariantNum = rMgr.getFontFaceVariation( aInfo.m_nID ); const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID ); - rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA ); + rGC.AddFontFile( rFileName, nFaceNum, nVariantNum, aInfo.m_nID, aDFA ); } // announce new font to device's font list |