Related: tdf#132536 drop FreetypeManager FreetypeFont caching

the FreetypeFont only makes sense in the context of the FreetypeFontInstance it
belongs to so remove the faux "garbage collection" and just have FreetypeFontInstance
own the FreetypeFont and keep it simple.

Setting a value low enough to make the garbage collection kick in just crasheed
libreoffice by pulling FreetypeFont out from under living FreetypeFontInstance
seeing as the Cache/Uncache was by the FreeTypeTextRenderImpl not the
FreetypeFontInstance which had HarfBuff faces which continued to point to the
removed FreetypeFont

There is still a cache at the LogicalFontInstance level, so this aligns the
libfreetype platforms with windows, mac etc.

Change-Id: Iac669fae8dc1df81a5bc10d2943d84a2ff623180
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94546
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
This commit is contained in:
Caolán McNamara
2020-05-19 16:36:36 +01:00
parent 78b7e1dfba
commit f73980ed15
30 changed files with 111 additions and 501 deletions

View File

@@ -1768,8 +1768,6 @@ vcl/inc/skia/utils.hxx:62
void SkiaHelper::dump(const class SkBitmap &,const char *) void SkiaHelper::dump(const class SkBitmap &,const char *)
vcl/inc/skia/zone.hxx:22 vcl/inc/skia/zone.hxx:22
void SkiaZone::relaxWatchdogTimings() void SkiaZone::relaxWatchdogTimings()
vcl/inc/unx/glyphcache.hxx:108
void FreetypeManager::ClearFontOptions()
vcl/inc/unx/gtk/gtkframe.hxx:217 vcl/inc/unx/gtk/gtkframe.hxx:217
void ensure_dbus_setup(struct _GdkWindow *,class GtkSalFrame *) void ensure_dbus_setup(struct _GdkWindow *,class GtkSalFrame *)
vcl/inc/unx/saldisp.hxx:377 vcl/inc/unx/saldisp.hxx:377

View File

@@ -106,7 +106,7 @@ class SAL_DLLPUBLIC_RTTI FreetypeFontInstance : public LogicalFontInstance
{ {
friend rtl::Reference<LogicalFontInstance> FreetypeFontFace::CreateFontInstance(const FontSelectPattern&) const; friend rtl::Reference<LogicalFontInstance> FreetypeFontFace::CreateFontInstance(const FontSelectPattern&) const;
FreetypeFont* mpFreetypeFont; std::unique_ptr<FreetypeFont> mxFreetypeFont;
virtual hb_font_t* ImplInitHbFont() override; virtual hb_font_t* ImplInitHbFont() override;
virtual bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const override; virtual bool ImplGetGlyphBoundRect(sal_GlyphId, tools::Rectangle&, bool) const override;
@@ -117,8 +117,7 @@ protected:
public: public:
virtual ~FreetypeFontInstance() override; virtual ~FreetypeFontInstance() override;
void SetFreetypeFont(FreetypeFont* p); FreetypeFont& GetFreetypeFont() const { return *mxFreetypeFont; }
FreetypeFont* GetFreetypeFont() const { return mpFreetypeFont; }
virtual bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const override; virtual bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const override;
}; };

View File

@@ -22,14 +22,15 @@
#include <textrender.hxx> #include <textrender.hxx>
class FreetypeFont; class FreetypeFontInstance;
// Generic implementation that uses freetype, but DrawTextLayout() // Generic implementation that uses freetype, but DrawTextLayout()
// still needs implementing (e.g. by Cairo or Skia). // still needs implementing (e.g. by Cairo or Skia).
class VCL_DLLPUBLIC FreeTypeTextRenderImpl : public TextRenderImpl class VCL_DLLPUBLIC FreeTypeTextRenderImpl : public TextRenderImpl
{ {
protected: protected:
FreetypeFont* mpFreetypeFont[ MAX_FALLBACK ]; rtl::Reference<FreetypeFontInstance>
mpFreetypeFont[ MAX_FALLBACK ];
Color mnTextColor; Color mnTextColor;

View File

@@ -32,7 +32,7 @@ class PhysicalFontCollection;
namespace psp { struct JobData; class PrinterGfx; } namespace psp { struct JobData; class PrinterGfx; }
class FreetypeFont; class FreetypeFontInstance;
class FontAttributes; class FontAttributes;
class SalInfoPrinter; class SalInfoPrinter;
class ImplFontMetricData; class ImplFontMetricData;
@@ -42,7 +42,8 @@ class VCL_DLLPUBLIC GenPspGraphics final : public SalGraphics
psp::JobData* m_pJobData; psp::JobData* m_pJobData;
psp::PrinterGfx* m_pPrinterGfx; psp::PrinterGfx* m_pPrinterGfx;
FreetypeFont* m_pFreetypeFont[ MAX_FALLBACK ]; rtl::Reference<FreetypeFontInstance>
m_pFreetypeFont[ MAX_FALLBACK ];
public: public:
GenPspGraphics(); GenPspGraphics();
virtual ~GenPspGraphics() override; virtual ~GenPspGraphics() override;

View File

@@ -52,7 +52,7 @@ namespace vcl { struct FontCapabilities; }
/** /**
* The FreetypeManager caches various aspects of Freetype fonts * The FreetypeManager caches various aspects of Freetype fonts
* *
* It mainly consists of three std::unordered_map lists, which hold the items of the cache. * It mainly consists of two std::unordered_map lists, which hold the items of the cache.
* *
* They form kind of a tree, with FreetypeFontFile as the roots, referenced by multiple FreetypeFontInfo * They form kind of a tree, with FreetypeFontFile as the roots, referenced by multiple FreetypeFontInfo
* entries, which are referenced by the FreetypeFont items. * entries, which are referenced by the FreetypeFont items.
@@ -63,17 +63,13 @@ namespace vcl { struct FontCapabilities; }
* The respective resources are: * The respective resources are:
* FreetypeFontFile = holds the mmapped font file, as long as it's used by any FreetypeFontInfo. * FreetypeFontFile = holds the mmapped font file, as long as it's used by any FreetypeFontInfo.
* FreetypeFontInfo = holds the FT_FaceRec_ object, as long as it's used by any FreetypeFont. * FreetypeFontInfo = holds the FT_FaceRec_ object, as long as it's used by any FreetypeFont.
* FreetypeFont = holds the FT_SizeRec_. * FreetypeFont = holds the FT_SizeRec_ and is owned by a FreetypeFontInstance
* *
* FreetypeFontInfo therefore is embedded in the Freetype subclass of PhysicalFontFace. * FreetypeFontInfo therefore is embedded in the Freetype subclass of PhysicalFontFace.
* FreetypeFont is embedded in the Freetype subclass of LogicalFontInstance. * FreetypeFont is owned by FreetypeFontInstance, the Freetype subclass of LogicalFontInstance.
* *
* Nowadays there is not really a reason to have separate files for the classes, as the FreetypeManager * Nowadays there is not really a reason to have separate files for the classes, as the FreetypeManager
* is just about handling of Freetype based fonts, not some abstract glyphs. * is just about handling of Freetype based fonts, not some abstract glyphs.
*
* One additional note: the byte-size based garbage collection of unused fonts can currently be assumed
* to be broken. Since the move of the glyph rect cache into the ImplFontCache, so it can be used by all
* platforms, it just takes too long to kick-in, as there is no real accounting left.
**/ **/
class VCL_DLLPUBLIC FreetypeManager final class VCL_DLLPUBLIC FreetypeManager final
{ {
@@ -89,23 +85,9 @@ public:
void AnnounceFonts( PhysicalFontCollection* ) const; void AnnounceFonts( PhysicalFontCollection* ) const;
FreetypeFont* CacheFont(LogicalFontInstance* pFontInstance);
void UncacheFont( FreetypeFont& );
/** Try to GarbageCollect an explicit logical font
*
* This should just be called from the ~ImplFontCache destructor, which holds the mapping of the
* FontSelectPattern to the LogicalFontInstance per OutputDevice. All other users should just
* call CacheFont and UncacheFont correctly. When the ImplFontCache is destroyed with its
* OutputDevice, we can safely garbage collection its unused entries, as these can't be reused.
*
* It's always safe to call this, as it just ignores the used bytes when considering a font for
* garbage collection, which normally keeps unreferenced fonts alive.
**/
void TryGarbageCollectFont(LogicalFontInstance*);
void ClearFontCache(); void ClearFontCache();
void ClearFontOptions();
FreetypeFont* CreateFont(FreetypeFontInstance* pLogicalFont);
private: private:
// to access the constructor (can't use InitFreetypeManager function, because it's private?!) // to access the constructor (can't use InitFreetypeManager function, because it's private?!)
@@ -113,23 +95,11 @@ private:
explicit FreetypeManager(); explicit FreetypeManager();
static void InitFreetype(); static void InitFreetype();
void GarbageCollect();
FreetypeFont* CreateFont(LogicalFontInstance* pLogicalFont);
FreetypeFontFile* FindFontFile(const OString& rNativeFileName); FreetypeFontFile* FindFontFile(const OString& rNativeFileName);
// the FreetypeManager's FontList matches a font request to a serverfont instance typedef std::unordered_map<sal_IntPtr, std::shared_ptr<FreetypeFontInfo>> FontInfoList;
// the FontList key's mpFontData member is reinterpreted as integer font id
struct IFSD_Equal{ bool operator()( const rtl::Reference<LogicalFontInstance>&, const rtl::Reference<LogicalFontInstance>& ) const; };
struct IFSD_Hash{ size_t operator()( const rtl::Reference<LogicalFontInstance>& ) const; };
typedef std::unordered_map<rtl::Reference<LogicalFontInstance>,std::unique_ptr<FreetypeFont>,IFSD_Hash,IFSD_Equal > FontList;
typedef std::unordered_map<sal_IntPtr, std::unique_ptr<FreetypeFontInfo>> FontInfoList;
typedef std::unordered_map<const char*, std::unique_ptr<FreetypeFontFile>, rtl::CStringHash, rtl::CStringEqual> FontFileList; typedef std::unordered_map<const char*, std::unique_ptr<FreetypeFontFile>, rtl::CStringHash, rtl::CStringEqual> FontFileList;
FontList maFontList;
static constexpr sal_uLong gnMaxSize = 1500000; // max overall cache size in bytes
mutable sal_uLong mnBytesUsed;
FreetypeFont* mpCurrentGCFont;
FontInfoList m_aFontInfoList; FontInfoList m_aFontInfoList;
sal_IntPtr m_nMaxFontId; sal_IntPtr m_nMaxFontId;
@@ -148,7 +118,6 @@ public:
FT_Face GetFtFace() const; FT_Face GetFtFace() const;
int GetLoadFlags() const { return (mnLoadFlags & ~FT_LOAD_IGNORE_TRANSFORM); } int GetLoadFlags() const { return (mnLoadFlags & ~FT_LOAD_IGNORE_TRANSFORM); }
const FontConfigFontOptions* GetFontOptions() const; const FontConfigFontOptions* GetFontOptions() const;
void ClearFontOptions();
bool NeedsArtificialBold() const { return mbArtBold; } bool NeedsArtificialBold() const { return mbArtBold; }
bool NeedsArtificialItalic() const { return mbArtItalic; } bool NeedsArtificialItalic() const { return mbArtItalic; }
@@ -161,7 +130,7 @@ public:
bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const; bool GetGlyphOutline(sal_GlyphId, basegfx::B2DPolyPolygon&, bool) const;
bool GetAntialiasAdvice() const; bool GetAntialiasAdvice() const;
FreetypeFontInstance* GetFontInstance() const { return mpFontInstance.get(); } FreetypeFontInstance& GetFontInstance() const { return mrFontInstance; }
void SetFontVariationsOnHBFont(hb_font_t* pHbFace) const; void SetFontVariationsOnHBFont(hb_font_t* pHbFace) const;
@@ -172,26 +141,14 @@ public:
static bool AlmostHorizontalDrainsRenderingPool(int nRatio, const FontSelectPattern& rFSD); static bool AlmostHorizontalDrainsRenderingPool(int nRatio, const FontSelectPattern& rFSD);
private: private:
friend class FreetypeFontInstance;
friend class FreetypeManager; friend class FreetypeManager;
explicit FreetypeFont(LogicalFontInstance*, FreetypeFontInfo*);
void AddRef() const { ++mnRefCount; } explicit FreetypeFont(FreetypeFontInstance&, std::shared_ptr<FreetypeFontInfo>& rFontInfo);
long GetRefCount() const { return mnRefCount; }
long Release() const;
sal_uLong GetByteCount() const { return mnBytesUsed; }
void ReleaseFromGarbageCollect();
void ApplyGlyphTransform(bool bVertical, FT_Glyph) const; void ApplyGlyphTransform(bool bVertical, FT_Glyph) const;
rtl::Reference<FreetypeFontInstance> mpFontInstance; FreetypeFontInstance& mrFontInstance;
// used by FreetypeManager for cache LRU algorithm
mutable long mnRefCount;
mutable sal_uLong mnBytesUsed;
FreetypeFont* mpPrevGCFont;
FreetypeFont* mpNextGCFont;
// 16.16 fixed point values used for a rotated font // 16.16 fixed point values used for a rotated font
long mnCos; long mnCos;
@@ -199,7 +156,7 @@ private:
int mnWidth; int mnWidth;
int mnPrioAntiAlias; int mnPrioAntiAlias;
FreetypeFontInfo* mpFontInfo; std::shared_ptr<FreetypeFontInfo> mxFontInfo;
FT_Int mnLoadFlags; FT_Int mnLoadFlags;
double mfStretch; double mfStretch;
FT_FaceRec_* maFaceFT; FT_FaceRec_* maFaceFT;

View File

@@ -31,7 +31,7 @@
void SkiaTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalGraphics& rGraphics) void SkiaTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalGraphics& rGraphics)
{ {
const FreetypeFontInstance& rInstance = static_cast<FreetypeFontInstance&>(rLayout.GetFont()); const FreetypeFontInstance& rInstance = static_cast<FreetypeFontInstance&>(rLayout.GetFont());
const FreetypeFont& rFont = *rInstance.GetFreetypeFont(); const FreetypeFont& rFont = rInstance.GetFreetypeFont();
const FontSelectPattern& rFSD = rInstance.GetFontSelectPattern(); const FontSelectPattern& rFSD = rInstance.GetFontSelectPattern();
int nHeight = rFSD.mnHeight; int nHeight = rFSD.mnHeight;
int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight; int nWidth = rFSD.mnWidth ? rFSD.mnWidth : nHeight;

View File

@@ -96,9 +96,6 @@ ImplFontCache::~ImplFontCache()
{ {
for (const auto & rLFI : maFontInstanceList) for (const auto & rLFI : maFontInstanceList)
{ {
#if !(defined(_WIN32) || defined(MACOSX) || defined(IOS))
FreetypeManager::get().TryGarbageCollectFont(rLFI.second.get());
#endif
rLFI.second->mpFontCache = nullptr; rLFI.second->mpFontCache = nullptr;
} }
} }

View File

@@ -66,14 +66,6 @@ bool SalLayoutGlyphsImpl::IsValid() const
return false; return false;
if (empty()) if (empty())
return false; return false;
#if (defined UNX && !defined MACOSX && !defined IOS)
const FreetypeFontInstance* pFFI = dynamic_cast<FreetypeFontInstance*>(m_rFontInstance.get());
if (pFFI && !pFFI->GetFreetypeFont())
{
m_rFontInstance.clear();
return false;
}
#endif
return true; return true;
} }

View File

@@ -115,7 +115,7 @@ namespace
void CairoTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalGraphics& rGraphics) void CairoTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalGraphics& rGraphics)
{ {
const FreetypeFontInstance& rInstance = static_cast<FreetypeFontInstance&>(rLayout.GetFont()); const FreetypeFontInstance& rInstance = static_cast<FreetypeFontInstance&>(rLayout.GetFont());
const FreetypeFont& rFont = *rInstance.GetFreetypeFont(); const FreetypeFont& rFont = rInstance.GetFreetypeFont();
std::vector<cairo_glyph_t> cairo_glyphs; std::vector<cairo_glyph_t> cairo_glyphs;
std::vector<int> glyph_extrarotation; std::vector<int> glyph_extrarotation;

View File

@@ -39,8 +39,6 @@
FreeTypeTextRenderImpl::FreeTypeTextRenderImpl() FreeTypeTextRenderImpl::FreeTypeTextRenderImpl()
: mnTextColor(Color(0x00, 0x00, 0x00)) //black : mnTextColor(Color(0x00, 0x00, 0x00)) //black
{ {
for(FreetypeFont* & rp : mpFreetypeFont)
rp = nullptr;
} }
FreeTypeTextRenderImpl::~FreeTypeTextRenderImpl() FreeTypeTextRenderImpl::~FreeTypeTextRenderImpl()
@@ -53,51 +51,37 @@ void FreeTypeTextRenderImpl::SetFont(LogicalFontInstance *pEntry, int nFallbackL
// release all no longer needed font resources // release all no longer needed font resources
for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i ) for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
{ {
if( mpFreetypeFont[i] != nullptr ) // old server side font is no longer referenced
{ mpFreetypeFont[i] = nullptr;
// old server side font is no longer referenced
FreetypeManager::get().UncacheFont( *mpFreetypeFont[i] );
mpFreetypeFont[i] = nullptr;
}
} }
// return early if there is no new font // return early if there is no new font
if( !pEntry ) if( !pEntry )
return; return;
// handle the request for a non-native X11-font => use the FreetypeManager FreetypeFontInstance* pFreetypeFont = static_cast<FreetypeFontInstance*>(pEntry);
FreetypeFont* pFreetypeFont = FreetypeManager::get().CacheFont(pEntry); mpFreetypeFont[ nFallbackLevel ] = pFreetypeFont;
if( pFreetypeFont != nullptr )
{
// ignore fonts with e.g. corrupted font files
if( !pFreetypeFont->TestFont() )
{
FreetypeManager::get().UncacheFont( *pFreetypeFont );
return;
}
// register to use the font // ignore fonts with e.g. corrupted font files
mpFreetypeFont[ nFallbackLevel ] = pFreetypeFont; if (!mpFreetypeFont[nFallbackLevel]->GetFreetypeFont().TestFont())
} mpFreetypeFont[nFallbackLevel] = nullptr;
} }
FontCharMapRef FreeTypeTextRenderImpl::GetFontCharMap() const FontCharMapRef FreeTypeTextRenderImpl::GetFontCharMap() const
{ {
if( !mpFreetypeFont[0] ) if (!mpFreetypeFont[0])
return nullptr; return nullptr;
return mpFreetypeFont[0]->GetFreetypeFont().GetFontCharMap();
return mpFreetypeFont[0]->GetFontCharMap();
} }
bool FreeTypeTextRenderImpl::GetFontCapabilities(vcl::FontCapabilities &rGetImplFontCapabilities) const bool FreeTypeTextRenderImpl::GetFontCapabilities(vcl::FontCapabilities &rGetImplFontCapabilities) const
{ {
if (!mpFreetypeFont[0]) if (!mpFreetypeFont[0])
return false; return false;
return mpFreetypeFont[0]->GetFontCapabilities(rGetImplFontCapabilities); return mpFreetypeFont[0]->GetFreetypeFont().GetFontCapabilities(rGetImplFontCapabilities);
} }
// SalGraphics // SalGraphics
void void
FreeTypeTextRenderImpl::SetTextColor( Color nColor ) FreeTypeTextRenderImpl::SetTextColor( Color nColor )
{ {
@@ -157,8 +141,8 @@ void FreeTypeTextRenderImpl::GetFontMetric( ImplFontMetricDataRef& rxFontMetric,
if( nFallbackLevel >= MAX_FALLBACK ) if( nFallbackLevel >= MAX_FALLBACK )
return; return;
if( mpFreetypeFont[nFallbackLevel] != nullptr ) if (mpFreetypeFont[nFallbackLevel])
mpFreetypeFont[nFallbackLevel]->GetFontMetric(rxFontMetric); mpFreetypeFont[nFallbackLevel]->GetFreetypeFont().GetFontMetric(rxFontMetric);
} }
std::unique_ptr<GenericSalLayout> FreeTypeTextRenderImpl::GetTextLayout(int nFallbackLevel) std::unique_ptr<GenericSalLayout> FreeTypeTextRenderImpl::GetTextLayout(int nFallbackLevel)
@@ -166,7 +150,7 @@ std::unique_ptr<GenericSalLayout> FreeTypeTextRenderImpl::GetTextLayout(int nFal
assert(mpFreetypeFont[nFallbackLevel]); assert(mpFreetypeFont[nFallbackLevel]);
if (!mpFreetypeFont[nFallbackLevel]) if (!mpFreetypeFont[nFallbackLevel])
return nullptr; return nullptr;
return std::make_unique<GenericSalLayout>(*mpFreetypeFont[nFallbackLevel]->GetFontInstance()); return std::make_unique<GenericSalLayout>(*mpFreetypeFont[nFallbackLevel]);
} }
#if ENABLE_CAIRO_CANVAS #if ENABLE_CAIRO_CANVAS
@@ -177,15 +161,15 @@ SystemFontData FreeTypeTextRenderImpl::GetSysFontData( int nFallbackLevel ) cons
if (nFallbackLevel >= MAX_FALLBACK) nFallbackLevel = MAX_FALLBACK - 1; if (nFallbackLevel >= MAX_FALLBACK) nFallbackLevel = MAX_FALLBACK - 1;
if (nFallbackLevel < 0 ) nFallbackLevel = 0; if (nFallbackLevel < 0 ) nFallbackLevel = 0;
if (mpFreetypeFont[nFallbackLevel] != nullptr) if (mpFreetypeFont[nFallbackLevel])
{ {
const FreetypeFont* rFont = mpFreetypeFont[nFallbackLevel]; FreetypeFont& rFreetypeFont = mpFreetypeFont[nFallbackLevel]->GetFreetypeFont();
aSysFontData.nFontId = rFont->GetFtFace(); aSysFontData.nFontId = rFreetypeFont.GetFtFace();
aSysFontData.nFontFlags = rFont->GetLoadFlags(); aSysFontData.nFontFlags = rFreetypeFont.GetLoadFlags();
aSysFontData.bFakeBold = rFont->NeedsArtificialBold(); aSysFontData.bFakeBold = rFreetypeFont.NeedsArtificialBold();
aSysFontData.bFakeItalic = rFont->NeedsArtificialItalic(); aSysFontData.bFakeItalic = rFreetypeFont.NeedsArtificialItalic();
aSysFontData.bAntialias = rFont->GetAntialiasAdvice(); aSysFontData.bAntialias = rFreetypeFont.GetAntialiasAdvice();
aSysFontData.bVerticalCharacterType = rFont->GetFontInstance()->GetFontSelectPattern().mbVertical; aSysFontData.bVerticalCharacterType = mpFreetypeFont[nFallbackLevel]->GetFontSelectPattern().mbVertical;
} }
return aSysFontData; return aSysFontData;

View File

@@ -101,7 +101,7 @@ FreetypeFontFile::FreetypeFontFile( const OString& rNativeFileName )
bool FreetypeFontFile::Map() bool FreetypeFontFile::Map()
{ {
if( mnRefCount++ <= 0 ) if (mnRefCount++ == 0)
{ {
const char* pFileName = maNativeFileName.getStr(); const char* pFileName = maNativeFileName.getStr();
int nFile = open( pFileName, O_RDONLY ); int nFile = open( pFileName, O_RDONLY );
@@ -128,11 +128,14 @@ bool FreetypeFontFile::Map()
void FreetypeFontFile::Unmap() void FreetypeFontFile::Unmap()
{ {
if( (--mnRefCount > 0) || (mpFileMap == nullptr) ) if (--mnRefCount != 0)
return; return;
assert(mnRefCount >= 0 && "how did this go negative\n");
munmap( mpFileMap, mnFileSize ); if (mpFileMap)
mpFileMap = nullptr; {
munmap(mpFileMap, mnFileSize);
mpFileMap = nullptr;
}
} }
FreetypeFontInfo::FreetypeFontInfo( const FontAttributes& rDevFontAttributes, FreetypeFontInfo::FreetypeFontInfo( const FontAttributes& rDevFontAttributes,
@@ -199,7 +202,7 @@ FT_FaceRec_* FreetypeFontInfo::GetFaceFT()
void FreetypeFont::SetFontVariationsOnHBFont(hb_font_t* pHbFace) const void FreetypeFont::SetFontVariationsOnHBFont(hb_font_t* pHbFace) const
{ {
sal_uInt32 nFaceVariation = mpFontInfo->GetFontFaceVariation(); sal_uInt32 nFaceVariation = mxFontInfo->GetFontFaceVariation();
if (maFaceFT && nFaceVariation) if (maFaceFT && nFaceVariation)
{ {
FT_MM_Var *pFtMMVar; FT_MM_Var *pFtMMVar;
@@ -223,12 +226,16 @@ void FreetypeFont::SetFontVariationsOnHBFont(hb_font_t* pHbFace) const
void FreetypeFontInfo::ReleaseFaceFT() void FreetypeFontInfo::ReleaseFaceFT()
{ {
if (--mnRefCount <= 0) if (--mnRefCount == 0)
{ {
FT_Done_Face( maFaceFT ); if (maFaceFT)
maFaceFT = nullptr; {
FT_Done_Face(maFaceFT);
maFaceFT = nullptr;
}
mpFontFile->Unmap(); mpFontFile->Unmap();
} }
assert(mnRefCount >= 0 && "how did this go negative\n");
} }
static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);} static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
@@ -360,7 +367,7 @@ void FreetypeManager::AnnounceFonts( PhysicalFontCollection* pToAdd ) const
} }
} }
FreetypeFont* FreetypeManager::CreateFont(LogicalFontInstance* pFontInstance) FreetypeFont* FreetypeManager::CreateFont(FreetypeFontInstance* pFontInstance)
{ {
// find a FontInfo matching to the font id // find a FontInfo matching to the font id
if (!pFontInstance) if (!pFontInstance)
@@ -372,12 +379,11 @@ FreetypeFont* FreetypeManager::CreateFont(LogicalFontInstance* pFontInstance)
sal_IntPtr nFontId = pFontFace->GetFontId(); sal_IntPtr nFontId = pFontFace->GetFontId();
FontInfoList::iterator it = m_aFontInfoList.find(nFontId); FontInfoList::iterator it = m_aFontInfoList.find(nFontId);
FreetypeFontInfo* pFontInfo = it != m_aFontInfoList.end() ? it->second.get() : nullptr;
if (!pFontInfo) if (it == m_aFontInfoList.end())
return nullptr; return nullptr;
return new FreetypeFont(pFontInstance, pFontInfo); return new FreetypeFont(*pFontInstance, it->second);
} }
FreetypeFontFace::FreetypeFontFace( FreetypeFontInfo* pFI, const FontAttributes& rDFA ) FreetypeFontFace::FreetypeFontFace( FreetypeFontInfo* pFI, const FontAttributes& rDFA )
@@ -393,16 +399,12 @@ rtl::Reference<LogicalFontInstance> FreetypeFontFace::CreateFontInstance(const F
// FreetypeFont // FreetypeFont
FreetypeFont::FreetypeFont(LogicalFontInstance* pFontInstance, FreetypeFontInfo* pFI ) FreetypeFont::FreetypeFont(FreetypeFontInstance& rFontInstance, std::shared_ptr<FreetypeFontInfo>& rFI)
: mpFontInstance(static_cast<FreetypeFontInstance*>(pFontInstance)), : mrFontInstance(rFontInstance),
mnRefCount(1),
mnBytesUsed( sizeof(FreetypeFont) ),
mpPrevGCFont( nullptr ),
mpNextGCFont( nullptr ),
mnCos( 0x10000), mnCos( 0x10000),
mnSin( 0 ), mnSin( 0 ),
mnPrioAntiAlias(nDefaultPrioAntiAlias), mnPrioAntiAlias(nDefaultPrioAntiAlias),
mpFontInfo( pFI ), mxFontInfo(rFI),
mnLoadFlags( 0 ), mnLoadFlags( 0 ),
maFaceFT( nullptr ), maFaceFT( nullptr ),
maSizeFT( nullptr ), maSizeFT( nullptr ),
@@ -411,13 +413,10 @@ FreetypeFont::FreetypeFont(LogicalFontInstance* pFontInstance, FreetypeFontInfo*
mbArtBold(false) mbArtBold(false)
{ {
int nPrioEmbedded = nDefaultPrioEmbedded; int nPrioEmbedded = nDefaultPrioEmbedded;
// TODO: move update of mpFontInstance into FontEntry class when
// it becomes responsible for the FreetypeFont instantiation
mpFontInstance->SetFreetypeFont( this );
maFaceFT = pFI->GetFaceFT(); maFaceFT = mxFontInfo->GetFaceFT();
const FontSelectPattern& rFSD = pFontInstance->GetFontSelectPattern(); const FontSelectPattern& rFSD = rFontInstance.GetFontSelectPattern();
if( rFSD.mnOrientation != 0 ) if( rFSD.mnOrientation != 0 )
{ {
@@ -446,7 +445,7 @@ FreetypeFont::FreetypeFont(LogicalFontInstance* pFontInstance, FreetypeFontInfo*
FT_Select_Charmap(maFaceFT, FT_ENCODING_UNICODE); FT_Select_Charmap(maFaceFT, FT_ENCODING_UNICODE);
if( mpFontInfo->IsSymbolFont() ) if( mxFontInfo->IsSymbolFont() )
{ {
FT_Encoding eEncoding = FT_ENCODING_MS_SYMBOL; FT_Encoding eEncoding = FT_ENCODING_MS_SYMBOL;
FT_Select_Charmap(maFaceFT, eEncoding); FT_Select_Charmap(maFaceFT, eEncoding);
@@ -457,8 +456,8 @@ FreetypeFont::FreetypeFont(LogicalFontInstance* pFontInstance, FreetypeFontInfo*
// TODO: query GASP table for load flags // TODO: query GASP table for load flags
mnLoadFlags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_TRANSFORM; mnLoadFlags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_TRANSFORM;
mbArtItalic = (rFSD.GetItalic() != ITALIC_NONE && pFI->GetFontAttributes().GetItalic() == ITALIC_NONE); mbArtItalic = (rFSD.GetItalic() != ITALIC_NONE && mxFontInfo->GetFontAttributes().GetItalic() == ITALIC_NONE);
mbArtBold = (rFSD.GetWeight() > WEIGHT_MEDIUM && pFI->GetFontAttributes().GetWeight() <= WEIGHT_MEDIUM); mbArtBold = (rFSD.GetWeight() > WEIGHT_MEDIUM && mxFontInfo->GetFontAttributes().GetWeight() <= WEIGHT_MEDIUM);
if( ((mnCos != 0) && (mnSin != 0)) || (nPrioEmbedded <= 0) ) if( ((mnCos != 0) && (mnSin != 0)) || (nPrioEmbedded <= 0) )
mnLoadFlags |= FT_LOAD_NO_BITMAP; mnLoadFlags |= FT_LOAD_NO_BITMAP;
@@ -483,30 +482,25 @@ const FontConfigFontOptions* FreetypeFont::GetFontOptions() const
{ {
if (!mxFontOptions) if (!mxFontOptions)
{ {
mxFontOptions = GetFCFontOptions(mpFontInfo->GetFontAttributes(), mpFontInstance->GetFontSelectPattern().mnHeight); mxFontOptions = GetFCFontOptions(mxFontInfo->GetFontAttributes(), mrFontInstance.GetFontSelectPattern().mnHeight);
mxFontOptions->SyncPattern(GetFontFileName(), GetFontFaceIndex(), GetFontFaceVariation(), NeedsArtificialBold()); mxFontOptions->SyncPattern(GetFontFileName(), GetFontFaceIndex(), GetFontFaceVariation(), NeedsArtificialBold());
} }
return mxFontOptions.get(); return mxFontOptions.get();
} }
void FreetypeFont::ClearFontOptions()
{
mxFontOptions.reset();
}
const OString& FreetypeFont::GetFontFileName() const const OString& FreetypeFont::GetFontFileName() const
{ {
return mpFontInfo->GetFontFileName(); return mxFontInfo->GetFontFileName();
} }
int FreetypeFont::GetFontFaceIndex() const int FreetypeFont::GetFontFaceIndex() const
{ {
return mpFontInfo->GetFontFaceIndex(); return mxFontInfo->GetFontFaceIndex();
} }
int FreetypeFont::GetFontFaceVariation() const int FreetypeFont::GetFontFaceVariation() const
{ {
return mpFontInfo->GetFontFaceVariation(); return mxFontInfo->GetFontFaceVariation();
} }
FreetypeFont::~FreetypeFont() FreetypeFont::~FreetypeFont()
@@ -514,18 +508,14 @@ FreetypeFont::~FreetypeFont()
if( maSizeFT ) if( maSizeFT )
FT_Done_Size( maSizeFT ); FT_Done_Size( maSizeFT );
mpFontInfo->ReleaseFaceFT(); mxFontInfo->ReleaseFaceFT();
mpFontInstance.clear();
ReleaseFromGarbageCollect();
} }
void FreetypeFont::GetFontMetric(ImplFontMetricDataRef const & rxTo) const void FreetypeFont::GetFontMetric(ImplFontMetricDataRef const & rxTo) const
{ {
rxTo->FontAttributes::operator =(mpFontInfo->GetFontAttributes()); rxTo->FontAttributes::operator =(mxFontInfo->GetFontAttributes());
rxTo->SetOrientation( mpFontInstance->GetFontSelectPattern().mnOrientation ); rxTo->SetOrientation(mrFontInstance.GetFontSelectPattern().mnOrientation);
//Always consider [star]symbol as symbol fonts //Always consider [star]symbol as symbol fonts
if ( IsStarSymbol( rxTo->GetFamilyName() ) ) if ( IsStarSymbol( rxTo->GetFamilyName() ) )
@@ -533,7 +523,7 @@ void FreetypeFont::GetFontMetric(ImplFontMetricDataRef const & rxTo) const
FT_Activate_Size( maSizeFT ); FT_Activate_Size( maSizeFT );
rxTo->ImplCalcLineSpacing(mpFontInstance.get()); rxTo->ImplCalcLineSpacing(&mrFontInstance);
rxTo->SetSlant( 0 ); rxTo->SetSlant( 0 );
rxTo->SetWidth( mnWidth ); rxTo->SetWidth( mnWidth );
@@ -572,13 +562,13 @@ void FreetypeFont::GetFontMetric(ImplFontMetricDataRef const & rxTo) const
} }
// initialize kashida width // initialize kashida width
rxTo->SetMinKashida(mpFontInstance->GetKashidaWidth()); rxTo->SetMinKashida(mrFontInstance.GetKashidaWidth());
} }
void FreetypeFont::ApplyGlyphTransform(bool bVertical, FT_Glyph pGlyphFT ) const void FreetypeFont::ApplyGlyphTransform(bool bVertical, FT_Glyph pGlyphFT ) const
{ {
// shortcut most common case // shortcut most common case
if (!mpFontInstance->GetFontSelectPattern().mnOrientation && !bVertical) if (!mrFontInstance.GetFontSelectPattern().mnOrientation && !bVertical)
return; return;
const FT_Size_Metrics& rMetrics = maFaceFT->size->metrics; const FT_Size_Metrics& rMetrics = maFaceFT->size->metrics;
@@ -670,14 +660,14 @@ bool FreetypeFont::GetGlyphBoundRect(sal_GlyphId nID, tools::Rectangle& rRect, b
bool FreetypeFont::GetAntialiasAdvice() const bool FreetypeFont::GetAntialiasAdvice() const
{ {
// TODO: also use GASP info // TODO: also use GASP info
return !mpFontInstance->GetFontSelectPattern().mbNonAntialiased && (mnPrioAntiAlias > 0); return !mrFontInstance.GetFontSelectPattern().mbNonAntialiased && (mnPrioAntiAlias > 0);
} }
// determine unicode ranges in font // determine unicode ranges in font
FontCharMapRef FreetypeFont::GetFontCharMap() const FontCharMapRef FreetypeFont::GetFontCharMap() const
{ {
return mpFontInfo->GetFontCharMap(); return mxFontInfo->GetFontCharMap();
} }
const FontCharMapRef& FreetypeFontInfo::GetFontCharMap() const FontCharMapRef& FreetypeFontInfo::GetFontCharMap()
@@ -713,7 +703,7 @@ bool FreetypeFont::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities)
sal_uLong nLength = 0; sal_uLong nLength = 0;
// load OS/2 table // load OS/2 table
const FT_Byte* pOS2 = mpFontInfo->GetTable("OS/2", &nLength); const FT_Byte* pOS2 = mxFontInfo->GetTable("OS/2", &nLength);
if (pOS2) if (pOS2)
{ {
bRet = vcl::getTTCoverage( bRet = vcl::getTTCoverage(
@@ -955,7 +945,7 @@ bool FreetypeFont::GetGlyphOutline(sal_GlyphId nId, basegfx::B2DPolyPolygon& rB2
const unsigned char* FreetypeFont::GetTable(const char* pName, sal_uLong* pLength) const const unsigned char* FreetypeFont::GetTable(const char* pName, sal_uLong* pLength) const
{ {
return mpFontInfo->GetTable( pName, pLength ); return mxFontInfo->GetTable( pName, pLength );
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -27,9 +27,7 @@
#include <sal/log.hxx> #include <sal/log.hxx>
FreetypeManager::FreetypeManager() FreetypeManager::FreetypeManager()
: mnBytesUsed(sizeof(FreetypeManager)), : m_nMaxFontId(0)
mpCurrentGCFont(nullptr)
, m_nMaxFontId(0)
{ {
InitFreetype(); InitFreetype();
} }
@@ -41,106 +39,9 @@ FreetypeManager::~FreetypeManager()
void FreetypeManager::ClearFontCache() void FreetypeManager::ClearFontCache()
{ {
for (auto &aFontPair : maFontList)
static_cast<FreetypeFontInstance*>(aFontPair.first.get())->SetFreetypeFont(nullptr);
maFontList.clear();
mpCurrentGCFont = nullptr;
m_aFontInfoList.clear(); m_aFontInfoList.clear();
} }
void FreetypeManager::ClearFontOptions()
{
for (auto const& font : maFontList)
{
FreetypeFont* pFreetypeFont = font.second.get();
// free demand-loaded FontConfig related data
pFreetypeFont->ClearFontOptions();
}
}
static sal_IntPtr GetFontId(const LogicalFontInstance& rFontInstance)
{
if (rFontInstance.GetFontFace())
return rFontInstance.GetFontFace()->GetFontId();
return 0;
}
inline
size_t FreetypeManager::IFSD_Hash::operator()(const rtl::Reference<LogicalFontInstance>& rFontInstance) const
{
// TODO: is it worth to improve this hash function?
sal_uIntPtr nFontId = GetFontId(*rFontInstance);
const FontSelectPattern& rFontSelData = rFontInstance->GetFontSelectPattern();
if (rFontSelData.maTargetName.indexOf(FontSelectPattern::FEAT_PREFIX)
!= -1)
{
OString aFeatName = OUStringToOString( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 );
nFontId ^= aFeatName.hashCode();
}
std::size_t seed = 0;
boost::hash_combine(seed, nFontId);
boost::hash_combine(seed, rFontSelData.mnHeight);
boost::hash_combine(seed, rFontSelData.mnOrientation);
boost::hash_combine(seed, size_t(rFontSelData.mbVertical));
boost::hash_combine(seed, rFontSelData.GetItalic());
boost::hash_combine(seed, rFontSelData.GetWeight());
boost::hash_combine(seed, static_cast<sal_uInt16>(rFontSelData.meLanguage));
return seed;
}
bool FreetypeManager::IFSD_Equal::operator()(const rtl::Reference<LogicalFontInstance>& rAFontInstance,
const rtl::Reference<LogicalFontInstance>& rBFontInstance) const
{
if (!rAFontInstance->GetFontCache() || !rBFontInstance->GetFontCache())
return false;
// check font ids
if (GetFontId(*rAFontInstance) != GetFontId(*rBFontInstance))
return false;
const FontSelectPattern& rA = rAFontInstance->GetFontSelectPattern();
const FontSelectPattern& rB = rBFontInstance->GetFontSelectPattern();
// compare with the requested metrics
if( (rA.mnHeight != rB.mnHeight)
|| (rA.mnOrientation != rB.mnOrientation)
|| (rA.mbVertical != rB.mbVertical)
|| (rA.mbNonAntialiased != rB.mbNonAntialiased) )
return false;
if( (rA.GetItalic() != rB.GetItalic())
|| (rA.GetWeight() != rB.GetWeight()) )
return false;
// NOTE: ignoring meFamily deliberately
// compare with the requested width, allow default width
int nAWidth = rA.mnWidth != 0 ? rA.mnWidth : rA.mnHeight;
int nBWidth = rB.mnWidth != 0 ? rB.mnWidth : rB.mnHeight;
if( nAWidth != nBWidth )
return false;
if (rA.meLanguage != rB.meLanguage)
return false;
// check for features
if ((rA.maTargetName.indexOf(FontSelectPattern::FEAT_PREFIX)
!= -1 ||
rB.maTargetName.indexOf(FontSelectPattern::FEAT_PREFIX)
!= -1) && rA.maTargetName != rB.maTargetName)
return false;
if (rA.mbEmbolden != rB.mbEmbolden)
return false;
if (rA.maItalicMatrix != rB.maItalicMatrix)
return false;
return true;
}
FreetypeManager& FreetypeManager::get() FreetypeManager& FreetypeManager::get()
{ {
GenericUnixSalData* const pSalData(GetGenericUnixSalData()); GenericUnixSalData* const pSalData(GetGenericUnixSalData());
@@ -148,117 +49,6 @@ FreetypeManager& FreetypeManager::get()
return *pSalData->GetFreetypeManager(); return *pSalData->GetFreetypeManager();
} }
FreetypeFont* FreetypeManager::CacheFont(LogicalFontInstance* pFontInstance)
{
// a serverfont request has a fontid > 0
if (GetFontId(*pFontInstance) <= 0)
return nullptr;
FontList::iterator it = maFontList.find(pFontInstance);
if( it != maFontList.end() )
{
FreetypeFont* pFound = it->second.get();
assert(pFound);
pFound->AddRef();
return pFound;
}
// font not cached yet => create new font item
FreetypeFont* pNew = CreateFont(pFontInstance);
if( pNew )
{
maFontList[pFontInstance].reset(pNew);
mnBytesUsed += pNew->GetByteCount();
// enable garbage collection for new font
if( !mpCurrentGCFont )
{
mpCurrentGCFont = pNew;
pNew->mpNextGCFont = pNew;
pNew->mpPrevGCFont = pNew;
}
else
{
pNew->mpNextGCFont = mpCurrentGCFont;
pNew->mpPrevGCFont = mpCurrentGCFont->mpPrevGCFont;
pNew->mpPrevGCFont->mpNextGCFont = pNew;
mpCurrentGCFont->mpPrevGCFont = pNew;
}
}
return pNew;
}
void FreetypeManager::UncacheFont( FreetypeFont& rFreetypeFont )
{
if( (rFreetypeFont.Release() <= 0) && (gnMaxSize <= mnBytesUsed) )
{
mpCurrentGCFont = &rFreetypeFont;
GarbageCollect();
}
}
void FreetypeManager::TryGarbageCollectFont(LogicalFontInstance *pFontInstance)
{
if (maFontList.empty() || !pFontInstance)
return;
FreetypeFontInstance* pFFI = dynamic_cast<FreetypeFontInstance*>(pFontInstance);
if (!pFFI)
return;
FreetypeFont* pFreetypeFont = pFFI->GetFreetypeFont();
if (pFreetypeFont && (pFreetypeFont->GetRefCount() <= 0))
{
mpCurrentGCFont = pFreetypeFont;
GarbageCollect();
}
}
void FreetypeManager::GarbageCollect()
{
// when current GC font has been destroyed get another one
if( !mpCurrentGCFont )
{
FontList::iterator it = maFontList.begin();
if( it != maFontList.end() )
mpCurrentGCFont = it->second.get();
}
// unless there is no other font to collect
if( !mpCurrentGCFont )
return;
// prepare advance to next font for garbage collection
FreetypeFont* const pFreetypeFont = mpCurrentGCFont;
mpCurrentGCFont = pFreetypeFont->mpNextGCFont;
if( (pFreetypeFont != mpCurrentGCFont) // no other fonts
&& (pFreetypeFont->GetRefCount() <= 0) ) // font still used
{
SAL_WARN_IF( (pFreetypeFont->GetRefCount() != 0), "vcl",
"FreetypeManager::GC detected RefCount underflow" );
// free all pFreetypeFont related data
if( pFreetypeFont == mpCurrentGCFont )
mpCurrentGCFont = nullptr;
mnBytesUsed -= pFreetypeFont->GetByteCount();
// remove font from list of garbage collected fonts
if( pFreetypeFont->mpPrevGCFont )
pFreetypeFont->mpPrevGCFont->mpNextGCFont = pFreetypeFont->mpNextGCFont;
if( pFreetypeFont->mpNextGCFont )
pFreetypeFont->mpNextGCFont->mpPrevGCFont = pFreetypeFont->mpPrevGCFont;
if( pFreetypeFont == mpCurrentGCFont )
mpCurrentGCFont = nullptr;
#ifndef NDEBUG
int nErased =
#endif
maFontList.erase(pFreetypeFont->GetFontInstance());
assert(1 == nErased);
}
}
FreetypeFontFile* FreetypeManager::FindFontFile(const OString& rNativeFileName) FreetypeFontFile* FreetypeManager::FindFontFile(const OString& rNativeFileName)
{ {
// font file already known? (e.g. for ttc, synthetic, aliased fonts) // font file already known? (e.g. for ttc, synthetic, aliased fonts)
@@ -274,33 +64,10 @@ FreetypeFontFile* FreetypeManager::FindFontFile(const OString& rNativeFileName)
return pFontFile; return pFontFile;
} }
void FreetypeFont::ReleaseFromGarbageCollect()
{
// remove from GC list
FreetypeFont* pPrev = mpPrevGCFont;
FreetypeFont* pNext = mpNextGCFont;
if( pPrev ) pPrev->mpNextGCFont = pNext;
if( pNext ) pNext->mpPrevGCFont = pPrev;
mpPrevGCFont = nullptr;
mpNextGCFont = nullptr;
}
long FreetypeFont::Release() const
{
SAL_WARN_IF( mnRefCount <= 0, "vcl", "FreetypeFont: RefCount underflow" );
return --mnRefCount;
}
FreetypeFontInstance::FreetypeFontInstance(const PhysicalFontFace& rPFF, const FontSelectPattern& rFSP) FreetypeFontInstance::FreetypeFontInstance(const PhysicalFontFace& rPFF, const FontSelectPattern& rFSP)
: LogicalFontInstance(rPFF, rFSP) : LogicalFontInstance(rPFF, rFSP)
, mpFreetypeFont(nullptr) , mxFreetypeFont(FreetypeManager::get().CreateFont(this))
{}
void FreetypeFontInstance::SetFreetypeFont(FreetypeFont* p)
{ {
if (p == mpFreetypeFont)
return;
mpFreetypeFont = p;
} }
FreetypeFontInstance::~FreetypeFontInstance() FreetypeFontInstance::~FreetypeFontInstance()
@@ -314,9 +81,9 @@ static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pU
sal_uLong nLength = 0; sal_uLong nLength = 0;
FreetypeFontInstance* pFontInstance = static_cast<FreetypeFontInstance*>( pUserData ); FreetypeFontInstance* pFontInstance = static_cast<FreetypeFontInstance*>( pUserData );
FreetypeFont* pFont = pFontInstance->GetFreetypeFont(); FreetypeFont& rFont = pFontInstance->GetFreetypeFont();
const char* pBuffer = reinterpret_cast<const char*>( const char* pBuffer = reinterpret_cast<const char*>(
pFont->GetTable(pTagName, &nLength) ); rFont.GetTable(pTagName, &nLength) );
hb_blob_t* pBlob = nullptr; hb_blob_t* pBlob = nullptr;
if (pBuffer != nullptr) if (pBuffer != nullptr)
@@ -328,25 +95,25 @@ static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pU
hb_font_t* FreetypeFontInstance::ImplInitHbFont() hb_font_t* FreetypeFontInstance::ImplInitHbFont()
{ {
hb_font_t* pRet = InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr)); hb_font_t* pRet = InitHbFont(hb_face_create_for_tables(getFontTable, this, nullptr));
assert(mpFreetypeFont); assert(mxFreetypeFont);
mpFreetypeFont->SetFontVariationsOnHBFont(pRet); mxFreetypeFont->SetFontVariationsOnHBFont(pRet);
return pRet; return pRet;
} }
bool FreetypeFontInstance::ImplGetGlyphBoundRect(sal_GlyphId nId, tools::Rectangle& rRect, bool bVertical) const bool FreetypeFontInstance::ImplGetGlyphBoundRect(sal_GlyphId nId, tools::Rectangle& rRect, bool bVertical) const
{ {
assert(mpFreetypeFont); assert(mxFreetypeFont);
if (!mpFreetypeFont) if (!mxFreetypeFont)
return false; return false;
return mpFreetypeFont->GetGlyphBoundRect(nId, rRect, bVertical); return mxFreetypeFont->GetGlyphBoundRect(nId, rRect, bVertical);
} }
bool FreetypeFontInstance::GetGlyphOutline(sal_GlyphId nId, basegfx::B2DPolyPolygon& rPoly, bool bVertical) const bool FreetypeFontInstance::GetGlyphOutline(sal_GlyphId nId, basegfx::B2DPolyPolygon& rPoly, bool bVertical) const
{ {
assert(mpFreetypeFont); assert(mxFreetypeFont);
if (!mpFreetypeFont) if (!mxFreetypeFont)
return false; return false;
return mpFreetypeFont->GetGlyphOutline(nId, rPoly, bVertical); return mxFreetypeFont->GetGlyphOutline(nId, rPoly, bVertical);
} }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -245,13 +245,10 @@ SalPrinterBmp::GetPixelIdx (sal_uInt32 nRow, sal_uInt32 nColumn) const
/******************************************************* /*******************************************************
* GenPspGraphics * * GenPspGraphics *
*******************************************************/ *******************************************************/
GenPspGraphics::GenPspGraphics() GenPspGraphics::GenPspGraphics()
: m_pJobData( nullptr ), : m_pJobData( nullptr ),
m_pPrinterGfx( nullptr ) m_pPrinterGfx( nullptr )
{ {
for(FreetypeFont* & rp : m_pFreetypeFont)
rp = nullptr;
} }
void GenPspGraphics::Init(psp::JobData* pJob, psp::PrinterGfx* pGfx) void GenPspGraphics::Init(psp::JobData* pJob, psp::PrinterGfx* pGfx)
@@ -558,7 +555,7 @@ namespace {
class PspSalLayout : public GenericSalLayout class PspSalLayout : public GenericSalLayout
{ {
public: public:
PspSalLayout(psp::PrinterGfx&, const FreetypeFont& rFont); PspSalLayout(psp::PrinterGfx&, LogicalFontInstance &rFontInstance);
void InitFont() const final override; void InitFont() const final override;
@@ -574,8 +571,8 @@ private:
} }
PspSalLayout::PspSalLayout(::psp::PrinterGfx& rGfx, const FreetypeFont& rFont) PspSalLayout::PspSalLayout(::psp::PrinterGfx& rGfx, LogicalFontInstance &rFontInstance)
: GenericSalLayout(*rFont.GetFontInstance()) : GenericSalLayout(rFontInstance)
, mrPrinterGfx(rGfx) , mrPrinterGfx(rGfx)
{ {
mnFontID = mrPrinterGfx.GetFontID(); mnFontID = mrPrinterGfx.GetFontID();
@@ -604,17 +601,18 @@ void GenPspGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
FontCharMapRef GenPspGraphics::GetFontCharMap() const FontCharMapRef GenPspGraphics::GetFontCharMap() const
{ {
if( !m_pFreetypeFont[0] ) if (!m_pFreetypeFont[0])
return nullptr; return nullptr;
return m_pFreetypeFont[0]->GetFontCharMap(); return m_pFreetypeFont[0]->GetFreetypeFont().GetFontCharMap();
} }
bool GenPspGraphics::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const bool GenPspGraphics::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
{ {
if (!m_pFreetypeFont[0]) if (!m_pFreetypeFont[0])
return false; return false;
return m_pFreetypeFont[0]->GetFontCapabilities(rFontCapabilities);
return m_pFreetypeFont[0]->GetFreetypeFont().GetFontCapabilities(rFontCapabilities);
} }
void GenPspGraphics::SetFont(LogicalFontInstance *pFontInstance, int nFallbackLevel) void GenPspGraphics::SetFont(LogicalFontInstance *pFontInstance, int nFallbackLevel)
@@ -622,12 +620,8 @@ void GenPspGraphics::SetFont(LogicalFontInstance *pFontInstance, int nFallbackLe
// release all fonts that are to be overridden // release all fonts that are to be overridden
for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i ) for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
{ {
if( m_pFreetypeFont[i] != nullptr ) // old server side font is no longer referenced
{ m_pFreetypeFont[i] = nullptr;
// old server side font is no longer referenced
FreetypeManager::get().UncacheFont(*m_pFreetypeFont[i]);
m_pFreetypeFont[i] = nullptr;
}
} }
// return early if there is no new font // return early if there is no new font
@@ -656,14 +650,12 @@ void GenPspGraphics::SetFont(LogicalFontInstance *pFontInstance, int nFallbackLe
// also set the serverside font for layouting // also set the serverside font for layouting
// requesting a font provided by builtin rasterizer // requesting a font provided by builtin rasterizer
FreetypeFont* pFreetypeFont = FreetypeManager::get().CacheFont(pFontInstance); FreetypeFontInstance* pFreetypeFont = static_cast<FreetypeFontInstance*>(pFontInstance);
if( pFreetypeFont != nullptr ) m_pFreetypeFont[ nFallbackLevel ] = pFreetypeFont;
{
if( pFreetypeFont->TestFont() ) // ignore fonts with e.g. corrupted font files
m_pFreetypeFont[ nFallbackLevel ] = pFreetypeFont; if (!m_pFreetypeFont[nFallbackLevel]->GetFreetypeFont().TestFont())
else m_pFreetypeFont[nFallbackLevel] = nullptr;
FreetypeManager::get().UncacheFont( *pFreetypeFont );
}
// set the printer font // set the printer font
m_pPrinterGfx->SetFont( nID, m_pPrinterGfx->SetFont( nID,
@@ -749,7 +741,7 @@ void GenPspGraphics::GetFontMetric(ImplFontMetricDataRef& rxFontMetric, int nFal
return; return;
if (m_pFreetypeFont[nFallbackLevel]) if (m_pFreetypeFont[nFallbackLevel])
m_pFreetypeFont[nFallbackLevel]->GetFontMetric(rxFontMetric); m_pFreetypeFont[nFallbackLevel]->GetFreetypeFont().GetFontMetric(rxFontMetric);
} }
std::unique_ptr<GenericSalLayout> GenPspGraphics::GetTextLayout(int nFallbackLevel) std::unique_ptr<GenericSalLayout> GenPspGraphics::GetTextLayout(int nFallbackLevel)

View File

@@ -33,10 +33,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportDOCX(aStream); (void)TestImportDOCX(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -33,10 +33,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportFODP(aStream); (void)TestImportFODP(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -28,10 +28,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportFODS(aStream); (void)TestImportFODS(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -33,10 +33,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportFODT(aStream); (void)TestImportFODT(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -27,10 +27,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportHTML(aStream); (void)TestImportHTML(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -23,10 +23,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportMML(aStream); (void)TestImportMML(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -129,10 +129,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportPPT(aStream); (void)TestImportPPT(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -27,10 +27,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportPPTX(aStream); (void)TestImportPPTX(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -84,10 +84,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportRTF(aStream); (void)TestImportRTF(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -77,10 +77,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportCalcRTF(aStream); (void)TestImportCalcRTF(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -47,10 +47,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportWKS(aStream); (void)TestImportWKS(aStream);
// fontconfigs alloc mechanism is too complicated for lsan/valgrind so
// force the fontconfig options to be released now, they are demand loaded
// so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -62,10 +62,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
GDIMetaFile aGDIMetaFile; GDIMetaFile aGDIMetaFile;
(void)ReadWindowMetafile(aStream, aGDIMetaFile); (void)ReadWindowMetafile(aStream, aGDIMetaFile);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -98,10 +98,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportWW2(aStream); (void)TestImportWW2(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -100,10 +100,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportWW6(aStream); (void)TestImportWW6(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -100,10 +100,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportWW8(aStream); (void)TestImportWW8(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -47,10 +47,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportXLS(aStream); (void)TestImportXLS(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }

View File

@@ -25,10 +25,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{ {
SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ); SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
(void)TestImportXLSX(aStream); (void)TestImportXLSX(aStream);
//fontconfigs alloc mechanism is too complicated for lsan/valgrind so
//force the fontconfig options to be released now, they are demand loaded
//so will be recreated if necessary
FreetypeManager::get().ClearFontOptions();
return 0; return 0;
} }