diff --git a/vcl/inc/unx/font/FreetypeFont.hxx b/vcl/inc/unx/font/FreetypeFont.hxx index dc30bfc46b23..03e0336c5807 100644 --- a/vcl/inc/unx/font/FreetypeFont.hxx +++ b/vcl/inc/unx/font/FreetypeFont.hxx @@ -37,15 +37,12 @@ class VCL_DLLPUBLIC FreetypeFont final : public LogicalFontInstance FreetypeFontFace::CreateFontInstance(const vcl::font::FontSelectPattern&) const; public: - virtual ~FreetypeFont() override; - const FreetypeFontFace* GetFontFace() const { return static_cast(LogicalFontInstance::GetFontFace()); } - bool TestFont() const { return mbFaceOk; } - FT_Face GetFtFace() const; + bool TestFont() const; const FontConfigFontOptions* GetFontOptions() const; bool GetAntialiasAdvice() const; @@ -53,15 +50,9 @@ public: private: explicit FreetypeFont(const FreetypeFontFace&, const vcl::font::FontSelectPattern&); - int mnWidth; int mnPrioAntiAlias; - double mfStretch; - FT_FaceRec_* maFaceFT; - FT_SizeRec_* maSizeFT; mutable std::unique_ptr mxFontOptions; - - bool mbFaceOk; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/unx/font/FreetypeFontFace.hxx b/vcl/inc/unx/font/FreetypeFontFace.hxx index 48fbc54d9289..ff7f974cdf61 100644 --- a/vcl/inc/unx/font/FreetypeFontFace.hxx +++ b/vcl/inc/unx/font/FreetypeFontFace.hxx @@ -21,54 +21,18 @@ #include -#include -#include FT_FREETYPE_H -#include FT_GLYPH_H - #include #include #include -class FreetypeFontList; - -// FreetypeFontFile has the responsibility that a font file is only mapped once. -// (#86621#) the old directly ft-managed solution caused it to be mapped -// in up to nTTC*nSizes*nOrientation*nSynthetic times -class FreetypeFontFile final -{ -public: - bool Map(); - void Unmap(); - - const unsigned char* GetBuffer() const { return mpFileMap; } - int GetFileSize() const { return mnFileSize; } - const OString& GetFileName() const { return maNativeFileName; } - int GetLangBoost() const { return mnLangBoost; } - -private: - friend class FreetypeFontList; - explicit FreetypeFontFile( OString aNativeFileName ); - - const OString maNativeFileName; - unsigned char* mpFileMap; - int mnFileSize; - int mnRefCount; - int mnLangBoost; - intptr_t mnHandle; -}; - // FreetypeFontFace corresponds to an unscaled font face class FreetypeFontFace final : public vcl::font::PhysicalFontFace { public: - FreetypeFontFace( const FontAttributes&, FreetypeFontFile* const pFontFile, + FreetypeFontFace( const FontAttributes&, OString aNativeFileName, int nFaceNum, int nFaceVariation, sal_IntPtr nFontId ); - FT_FaceRec_* GetFaceFT() const; - void ReleaseFaceFT() const; - - FreetypeFontFile* GetFontFile() const { return mpFontFile; } - const OString& GetFontFileName() const { return mpFontFile->GetFileName(); } + const OString& GetFontFileName() const { return maNativeFileName; } int GetFontFaceIndex() const { return mnFaceNum; } int GetFontFaceVariation() const { return mnFaceVariation; } @@ -81,11 +45,9 @@ public: const std::vector& GetVariations(const LogicalFontInstance&) const override; private: - mutable FT_FaceRec_* maFaceFT; - FreetypeFontFile* const mpFontFile; + const OString maNativeFileName; const int mnFaceNum; const int mnFaceVariation; - mutable int mnRefCount; const sal_IntPtr mnFontId; }; diff --git a/vcl/inc/unx/font/FreetypeFontList.hxx b/vcl/inc/unx/font/FreetypeFontList.hxx index 9adbb733f245..a890cd9458b2 100644 --- a/vcl/inc/unx/font/FreetypeFontList.hxx +++ b/vcl/inc/unx/font/FreetypeFontList.hxx @@ -33,27 +33,19 @@ #include #include -class FreetypeFontFile; namespace vcl::font { class PhysicalFontCollection; } -FT_Library GetFreetypeLibrary(); int GetDefaultAntiAliasPrio(); /** * The FreetypeFontList is the list of the fonts we know about. * - * It enumerates them from fontconfig, maps a font id to the FreetypeFontFace - * for it, and keeps the mmapped font files those faces read from. The faces it - * hands to a PhysicalFontCollection are the very same objects, shared by every - * collection. - * - * The resources are: - * FreetypeFontFile = holds the mmapped font file, as long as it's used by any face. - * FreetypeFontFace = holds the FT_FaceRec_ object, as long as it's used by any FreetypeFont. - * FreetypeFont = holds the FT_SizeRec_; it is the Freetype LogicalFontInstance. + * It enumerates them from fontconfig and maps a font id to the FreetypeFontFace + * for it. The faces it hands to a PhysicalFontCollection are the very same + * objects, shared by every collection. **/ class VCL_DLLPUBLIC FreetypeFontList final { @@ -80,17 +72,13 @@ private: SAL_DLLPRIVATE void Init(); - SAL_DLLPRIVATE static void InitFreetype(); - SAL_DLLPRIVATE FreetypeFontFile* FindFontFile(const OString& rNativeFileName); SAL_DLLPRIVATE void AddFontFace(const FontAttributes& rDFA, const OString& rFileName, int nFaceNum, int nVariationNum); typedef std::unordered_map> FontFaceList; - typedef std::unordered_map, rtl::CStringHash, rtl::CStringEqual> FontFileList; sal_IntPtr m_nNextFontId = 1; FontFaceList m_aFontFaceList; - FontFileList m_aFontFileList; std::unordered_map> m_aFontFileToFontId; }; diff --git a/vcl/unx/generic/font/FreetypeFont.cxx b/vcl/unx/generic/font/FreetypeFont.cxx index 826aca1b669f..5fa061892344 100644 --- a/vcl/unx/generic/font/FreetypeFont.cxx +++ b/vcl/unx/generic/font/FreetypeFont.cxx @@ -27,60 +27,19 @@ #include #include -#include - -#include -#include FT_FREETYPE_H -#include FT_SIZES_H - -FT_Face FreetypeFont::GetFtFace() const -{ - FT_Activate_Size( maSizeFT ); - - return maFaceFT; -} +#include // FreetypeFont FreetypeFont::FreetypeFont(const FreetypeFontFace& rFontFace, const vcl::font::FontSelectPattern& rFSD) -: LogicalFontInstance(rFontFace, rFSD), - mnPrioAntiAlias(GetDefaultAntiAliasPrio()), - maFaceFT( nullptr ), - maSizeFT( nullptr ), - mbFaceOk( false ) + : LogicalFontInstance(rFontFace, rFSD) + , mnPrioAntiAlias(GetDefaultAntiAliasPrio()) { - maFaceFT = rFontFace.GetFaceFT(); +} - // set the pixel size of the font instance - mnWidth = rFSD.mnWidth; - if( !mnWidth ) - mnWidth = rFSD.mnHeight; - if (rFSD.mnHeight == 0) - { - SAL_WARN("vcl", "FreetypeFont divide by zero"); - mfStretch = 1.0; - return; - } - mfStretch = static_cast(mnWidth) / rFSD.mnHeight; - // sanity checks (e.g. #i66394#, #i66244#, #i66537#) - if (mnWidth < 0) - { - SAL_WARN("vcl", "FreetypeFont negative font width of: " << mnWidth); - return; - } - - SAL_WARN_IF(mfStretch > +64.0 || mfStretch < -64.0, "vcl", "FreetypeFont excessive stretch of: " << mfStretch); - - if( !maFaceFT ) - return; - - FT_New_Size( maFaceFT, &maSizeFT ); - FT_Activate_Size( maSizeFT ); - /* This might fail for color bitmap fonts, but that is fine since we will - * not need any glyph data from FreeType in this case */ - /*FT_Error rc = */ FT_Set_Pixel_Sizes( maFaceFT, mnWidth, rFSD.mnHeight ); - - mbFaceOk = true; +bool FreetypeFont::TestFont() const +{ + return hb_face_get_glyph_count(GetFontFace()->GetHbFace()) > 0; } namespace @@ -104,14 +63,6 @@ const FontConfigFontOptions* FreetypeFont::GetFontOptions() const return mxFontOptions.get(); } -FreetypeFont::~FreetypeFont() -{ - if( maSizeFT ) - FT_Done_Size( maSizeFT ); - - GetFontFace()->ReleaseFaceFT(); -} - bool FreetypeFont::GetAntialiasAdvice() const { // TODO: also use GASP info diff --git a/vcl/unx/generic/font/FreetypeFontFace.cxx b/vcl/unx/generic/font/FreetypeFontFace.cxx index 996a2da90da8..69dcdee241fe 100644 --- a/vcl/unx/generic/font/FreetypeFontFace.cxx +++ b/vcl/unx/generic/font/FreetypeFontFace.cxx @@ -23,177 +23,23 @@ #include #include -#include #include #include -#include -#include - -#include -#include -#include - -#include -#include FT_FREETYPE_H - #include -#include -#include -#include - -#ifdef _WIN32 -#define strncasecmp(x, y, z) _strnicmp(x, y, z) -#endif - -namespace -{ -const char* getLangBoost() -{ - const LanguageType eLang = Application::GetSettings().GetUILanguageTag().getLanguageType(); - if (eLang == LANGUAGE_JAPANESE) - return "jan"; - if (MsLangId::isKorean(eLang)) - return "kor"; - if (MsLangId::isSimplifiedChinese(eLang)) - return "zhs"; - if (MsLangId::isTraditionalChinese(eLang)) - return "zht"; - return nullptr; -} -} - -FreetypeFontFile::FreetypeFontFile(OString aNativeFileName) - : maNativeFileName(std::move(aNativeFileName)) - , mpFileMap(nullptr) - , mnFileSize(0) - , mnRefCount(0) - , mnLangBoost(0) - , mnHandle(0) -{ - // boost font preference if UI language is mentioned in filename - int nPos = maNativeFileName.lastIndexOf('_'); - if (nPos == -1 || maNativeFileName[nPos + 1] == '.') - mnLangBoost += 0x1000; // no langinfo => good - else - { - static const char* pLangBoost = nullptr; - static bool bOnce = true; - if (bOnce) - { - bOnce = false; - pLangBoost = getLangBoost(); - } - - if (pLangBoost && !strncasecmp(pLangBoost, &maNativeFileName.getStr()[nPos + 1], 3)) - mnLangBoost += 0x2000; // matching langinfo => better - } -} - -bool FreetypeFontFile::Map() -{ - if (mnRefCount++ == 0) - { - const char* pFileName = maNativeFileName.getStr(); - int nFile; - int nFD; - int n; - if (sscanf(pFileName, "/:FD:/%d%n", &nFD, &n) == 1 && pFileName[n] == '\0') - { - lseek(nFD, 0, SEEK_SET); - nFile = wrap_dup(nFD); - } - else - nFile = wrap_open(pFileName, O_RDONLY, 0); - if (nFile < 0) - { - SAL_WARN("vcl.unx.freetype", - "open('" << maNativeFileName << "') failed: " << strerror(errno)); - return false; - } - - struct stat aStat; - int nRet = wrap_fstat(nFile, &aStat); - if (nRet < 0) - { - SAL_WARN("vcl.unx.freetype", - "fstat on '" << maNativeFileName << "' failed: " << strerror(errno)); - wrap_close(nFile); - return false; - } - mnFileSize = aStat.st_size; - mpFileMap = static_cast(wrap_mmap(mnFileSize, nFile, &mnHandle)); - if (mpFileMap == MAP_FAILED) - { - SAL_WARN("vcl.unx.freetype", - "mmap of '" << maNativeFileName << "' failed: " << strerror(errno)); - mpFileMap = nullptr; - } - else - SAL_INFO("vcl.unx.freetype", "mmap'ed '" << maNativeFileName << "' successfully"); - wrap_close(nFile); - } - - return (mpFileMap != nullptr); -} - -void FreetypeFontFile::Unmap() -{ - if (--mnRefCount != 0) - return; - assert(mnRefCount >= 0 && "how did this go negative\n"); - if (mpFileMap) - { - wrap_munmap(mpFileMap, mnFileSize, mnHandle); - mpFileMap = nullptr; - } -} - FreetypeFontFace::FreetypeFontFace(const FontAttributes& rDevFontAttributes, - FreetypeFontFile* const pFontFile, int nFaceNum, - int nFaceVariation, sal_IntPtr nFontId) + OString aNativeFileName, int nFaceNum, int nFaceVariation, + sal_IntPtr nFontId) : vcl::font::PhysicalFontFace(rDevFontAttributes) - , maFaceFT(nullptr) - , mpFontFile(pFontFile) + , maNativeFileName(std::move(aNativeFileName)) , mnFaceNum(nFaceNum) , mnFaceVariation(nFaceVariation) - , mnRefCount(0) , mnFontId(nFontId) { // prefer font with low ID IncreaseQualityBy(10000 - nFontId); - // prefer font with matching file names - IncreaseQualityBy(mpFontFile->GetLangBoost()); -} - -FT_FaceRec_* FreetypeFontFace::GetFaceFT() const -{ - if (!maFaceFT && mpFontFile->Map()) - { - FT_Error rc = FT_New_Memory_Face(GetFreetypeLibrary(), mpFontFile->GetBuffer(), - mpFontFile->GetFileSize(), mnFaceNum, &maFaceFT); - if ((rc != FT_Err_Ok) || (maFaceFT->num_glyphs <= 0)) - maFaceFT = nullptr; - } - - ++mnRefCount; - return maFaceFT; -} - -void FreetypeFontFace::ReleaseFaceFT() const -{ - if (--mnRefCount == 0) - { - if (maFaceFT) - { - FT_Done_Face(maFaceFT); - maFaceFT = nullptr; - } - mpFontFile->Unmap(); - } - assert(mnRefCount >= 0 && "how did this go negative\n"); } rtl::Reference @@ -202,36 +48,13 @@ FreetypeFontFace::CreateFontInstance(const vcl::font::FontSelectPattern& rFSD) c return new FreetypeFont(*this, rFSD); } -namespace -{ -hb_blob_t* CreateHbBlob(FreetypeFontFile* pFontFile) -{ - auto pFileName = pFontFile->GetFileName().getStr(); - int nFD; - int n; - if (sscanf(pFileName, "/:FD:/%d%n", &nFD, &n) == 1 && pFileName[n] == '\0') - { - if (pFontFile->Map()) - return hb_blob_create( - reinterpret_cast(pFontFile->GetBuffer()), pFontFile->GetFileSize(), - HB_MEMORY_MODE_READONLY, pFontFile, - [](void* data) { static_cast(data)->Unmap(); }); - pFontFile->Unmap(); - return hb_blob_get_empty(); - } - return hb_blob_create_from_file(pFileName); -} -} - hb_face_t* FreetypeFontFace::GetHbFace() const { if (!mpHbFace) { - auto pFontFile = GetFontFile(); - auto nIndex = GetFontFaceIndex(); - auto pHbBlob = CreateHbBlob(pFontFile); - mpHbFace = hb_face_create(pHbBlob, nIndex); - hb_blob_destroy(pHbBlob); + hb_blob_t* pBlob = hb_blob_create_from_file(maNativeFileName.getStr()); + mpHbFace = hb_face_create(pBlob, GetFontFaceIndex()); + hb_blob_destroy(pBlob); } return mpHbFace; } diff --git a/vcl/unx/generic/font/FreetypeFontList.cxx b/vcl/unx/generic/font/FreetypeFontList.cxx index db09bd5fa438..b6fe3e6fc7f7 100644 --- a/vcl/unx/generic/font/FreetypeFontList.cxx +++ b/vcl/unx/generic/font/FreetypeFontList.cxx @@ -32,11 +32,6 @@ #include #include -#include -#include FT_FREETYPE_H - -static FT_Library aLibFT = nullptr; - // TODO: remove when the priorities are selected by UI // if (AH==0) => disable autohinting // if (AA==0) => disable antialiasing @@ -44,27 +39,15 @@ static FT_Library aLibFT = nullptr; // if (AA prio <= AH prio) => antialias + autohint // if (AH do not autohint when antialiasing // if (EB do not autohint for monochrome -static int nDefaultPrioAntiAlias = 1; - -FT_Library GetFreetypeLibrary() { return aLibFT; } +static int nDefaultPrioAntiAlias = 1; int GetDefaultAntiAliasPrio() { return nDefaultPrioAntiAlias; } -void FreetypeFontList::InitFreetype() -{ - /*FT_Error rcFT =*/ FT_Init_FreeType( &aLibFT ); - - // TODO: remove when the priorities are selected by UI - char* pEnv; - pEnv = ::getenv( "SAL_ANTIALIASED_TEXT_PRIORITY" ); - if( pEnv ) - nDefaultPrioAntiAlias = pEnv[0] - '0'; -} - - FreetypeFontList::FreetypeFontList() { - InitFreetype(); + // TODO: remove when the priorities are selected by UI + if (const char* pEnv = ::getenv("SAL_ANTIALIASED_TEXT_PRIORITY")) + nDefaultPrioAntiAlias = pEnv[0] - '0'; } void FreetypeFontList::Init() @@ -82,11 +65,7 @@ void FreetypeFontList::Init() SAL_INFO("vcl.fonts", "have " << m_aFontFaceList.size() << " fonts"); } -FreetypeFontList::~FreetypeFontList() -{ - // the faces point at the font files, so they have to go first - m_aFontFaceList.clear(); -} +FreetypeFontList::~FreetypeFontList() {} FreetypeFontList& FreetypeFontList::get() { @@ -95,21 +74,6 @@ FreetypeFontList& FreetypeFontList::get() return *pSalData->GetFreetypeFontList(); } -FreetypeFontFile* FreetypeFontList::FindFontFile(const OString& rNativeFileName) -{ - // font file already known? (e.g. for ttc, synthetic, aliased fonts) - const char* pFileName = rNativeFileName.getStr(); - FontFileList::const_iterator it = m_aFontFileList.find(pFileName); - if (it != m_aFontFileList.end()) - return it->second.get(); - - // no => create new one - FreetypeFontFile* pFontFile = new FreetypeFontFile(rNativeFileName); - pFileName = pFontFile->maNativeFileName.getStr(); - m_aFontFileList[pFileName].reset(pFontFile); - return pFontFile; -} - void FreetypeFontList::AddFontFace(const FontAttributes& rDevFontAttr, const OString& rFileName, int nFaceNum, int nVariationNum) { @@ -117,8 +81,8 @@ void FreetypeFontList::AddFontFace(const FontAttributes& rDevFontAttr, const OSt return; const sal_IntPtr nFontId = m_nNextFontId++; - m_aFontFaceList[ nFontId ] = new FreetypeFontFace( rDevFontAttr, - FindFontFile(rFileName), nFaceNum, nVariationNum, nFontId); + m_aFontFaceList[nFontId] + = new FreetypeFontFace(rDevFontAttr, rFileName, nFaceNum, nVariationNum, nFontId); m_aFontFileToFontId[ rFileName ].insert( nFontId ); } diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx index f6f950be0d89..dbf54bff1c6a 100644 --- a/vcl/unx/generic/gdi/cairotextrender.cxx +++ b/vcl/unx/generic/gdi/cairotextrender.cxx @@ -41,20 +41,18 @@ namespace { -typedef struct FT_FaceRec_* FT_Face; - class CairoFontsCache : public CacheOwner { public: struct CacheId { - FT_Face maFace; + const void* mpFace; const FontConfigFontOptions *mpOptions; bool mbEmbolden; bool mbVerticalMetrics; bool operator ==(const CacheId& rOther) const { - return maFace == rOther.maFace && + return mpFace == rOther.mpFace && mpOptions == rOther.mpOptions && mbEmbolden == rOther.mbEmbolden && mbVerticalMetrics == rOther.mbVerticalMetrics; @@ -261,9 +259,8 @@ static CairoFontsCache::CacheId makeCacheId(const GenericSalLayout& rLayout) { const FreetypeFont& rFont = static_cast(rLayout.GetFont()); - FT_Face aFace = rFont.GetFtFace(); CairoFontsCache::CacheId aId; - aId.maFace = aFace; + aId.mpFace = rFont.GetFontFace(); aId.mpOptions = rFont.GetFontOptions(); aId.mbEmbolden = rFont.NeedsArtificialBold(); aId.mbVerticalMetrics = false;