diff options
author | Akash Jain <akash96j@gmail.com> | 2016-08-17 21:31:22 +0530 |
---|---|---|
committer | Khaled Hosny <khaledhosny@eglug.org> | 2016-10-18 20:41:30 +0200 |
commit | 5e65efcaa38ea5fbe655a18082a3ba7c8cf7d5fe (patch) | |
tree | f4d343cd38c51bf3ed86561aef951b3abf91db0f /vcl | |
parent | 3eda74cf7e9d23cc08f07c38f3bee04b565ff9db (diff) |
GSoC: Speed up CommonSalLayout by caching hb_face
Cache hb_face so it is not created again and again.
Switch from GDI to DirectWrite on Windows to obtain SFNT table data.
Change-Id: I9c532cd72e1f6b57313f3b7d42a6b9b0633eb0ef
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/CommonSalLayout.hxx | 4 | ||||
-rw-r--r-- | vcl/inc/quartz/salgdi.h | 4 | ||||
-rw-r--r-- | vcl/inc/unx/glyphcache.hxx | 4 | ||||
-rw-r--r-- | vcl/inc/win/salgdi.h | 8 | ||||
-rwxr-xr-x | vcl/inc/win/winlayout.hxx | 1 | ||||
-rw-r--r-- | vcl/quartz/ctfonts.cxx | 3 | ||||
-rw-r--r-- | vcl/source/gdi/CommonSalLayout.cxx | 86 | ||||
-rw-r--r-- | vcl/unx/generic/glyphs/freetype_glyphcache.cxx | 6 | ||||
-rw-r--r-- | vcl/win/gdi/salfont.cxx | 28 | ||||
-rw-r--r-- | vcl/win/gdi/winlayout.cxx | 23 |
10 files changed, 132 insertions, 35 deletions
diff --git a/vcl/inc/CommonSalLayout.hxx b/vcl/inc/CommonSalLayout.hxx index 1fe3a6ebf1c6..73f680b66cd5 100644 --- a/vcl/inc/CommonSalLayout.hxx +++ b/vcl/inc/CommonSalLayout.hxx @@ -44,6 +44,7 @@ class CommonSalLayout : public GenericSalLayout #ifdef _WIN32 HDC mhDC; HFONT mhFont; + D2DWriteTextOutRenderer* mpD2DRenderer; #elif defined(MACOSX) || defined(IOS) const CoreTextStyle& mrCoreTextStyle; #else @@ -53,7 +54,7 @@ class CommonSalLayout : public GenericSalLayout hb_font_t* GetHbFont(); public: #if defined(_WIN32) - explicit CommonSalLayout(HDC, WinFontInstance&); + explicit CommonSalLayout(WinSalGraphics*, WinFontInstance&, const WinFontFace&); void InitFont() const override; #elif defined(MACOSX) || defined(IOS) explicit CommonSalLayout(const CoreTextStyle&); @@ -63,7 +64,6 @@ public: const ServerFont& getFontData() const { return mrServerFont; }; #endif - ~CommonSalLayout(); void SetNeedFallback(ImplLayoutArgs&, sal_Int32, bool); void AdjustLayout(ImplLayoutArgs&) override; bool LayoutText(ImplLayoutArgs&) override; diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h index 104699bc1d89..00b2d8e76409 100644 --- a/vcl/inc/quartz/salgdi.h +++ b/vcl/inc/quartz/salgdi.h @@ -45,6 +45,7 @@ #include "quartz/salgdicommon.hxx" #include <unordered_map> +#include <hb-ot.h> class AquaSalFrame; class FontAttributes; @@ -98,6 +99,8 @@ public: void GetFontMetric( ImplFontMetricDataRef& ) const; bool GetGlyphBoundRect( sal_GlyphId, Rectangle& ) const; bool GetGlyphOutline( sal_GlyphId, basegfx::B2DPolyPolygon& ) const; + hb_face_t* GetHbFace() const { return mpHbFace; } + void SetHbFace(hb_face_t* pHbFace) const { mpHbFace = pHbFace; } const CoreTextFontFace* mpFontData; /// <1.0: font is squeezed, >1.0 font is stretched, else 1.0 @@ -109,6 +112,7 @@ public: private: /// CoreText text style object CFMutableDictionaryRef mpStyleDict; + mutable hb_face_t* mpHbFace; friend class CTLayout; friend class AquaSalGraphics; diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx index 944ffffce8e7..38967bfb0035 100644 --- a/vcl/inc/unx/glyphcache.hxx +++ b/vcl/inc/unx/glyphcache.hxx @@ -35,6 +35,7 @@ #include <sallayout.hxx> #include "fontattributes.hxx" #include "impfontmetricdata.hxx" +#include "hb-ot.h" #include <unordered_map> @@ -181,6 +182,8 @@ public: sal_GlyphId FixupGlyphIndex( sal_GlyphId aGlyphId, sal_UCS4 ) const; bool GetGlyphOutline( sal_GlyphId aGlyphId, basegfx::B2DPolyPolygon& ) const; bool GetAntialiasAdvice() const; + hb_face_t* GetHbFace() { return mpHbFace; } + void SetHbFace( hb_face_t* pHbFace ) { mpHbFace=pHbFace; } private: friend class GlyphCache; @@ -240,6 +243,7 @@ private: GlyphSubstitution maGlyphSubstitution; ServerFontLayoutEngine* mpLayoutEngine; + hb_face_t* mpHbFace; }; // a class for cache entries for physical font instances that are based on serverfonts diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index c4fb26d48a45..ad934108b528 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -44,6 +44,9 @@ # include "postwin.h" #endif +#include <hb-ot.h> +#include <dwrite.h> + class FontSelectPattern; class WinFontInstance; class ImplFontAttrCache; @@ -139,10 +142,12 @@ private: mutable std::unordered_set<sal_UCS4> maGsubTable; mutable bool mbGsubRead; + mutable hb_face_t* mpHbFace; public: bool HasGSUBstitutions( HDC ) const; bool IsGSUBstituted( sal_UCS4 ) const; - static int GetTable( const char pTagName[5], const unsigned char*&, HDC ); + hb_face_t* GetHbFace() const { return mpHbFace; } + void SetHbFace( hb_face_t* pHbFace ) const { mpHbFace = pHbFace; } }; /** Class that creates (and destroys) a compatible Device Context. @@ -353,6 +358,7 @@ private: sal_uLong GetKernPairs(); public: + sal_uLong GetTable( const char pTagName[5], const unsigned char*&, void*&, IDWriteFontFace*& ); // public SalGraphics methods, the interface to the independent vcl part // get device resolution diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx index fd69ee03f242..1f0425133e83 100755 --- a/vcl/inc/win/winlayout.hxx +++ b/vcl/inc/win/winlayout.hxx @@ -482,6 +482,7 @@ public: std::vector<Rectangle> GetGlyphInkBoxes(uint16_t * pGid, uint16_t * pGidEnd) const /*override*/; ID2D1RenderTarget * GetRenderTarget() const { return mpRT; } + IDWriteFontFace * GetDWriteFontFace(HDC) const; IDWriteFontFace * GetFontFace() const { return mpFontFace; } float GetEmHeight() const { return mlfEmHeight; } diff --git a/vcl/quartz/ctfonts.cxx b/vcl/quartz/ctfonts.cxx index 28be80b0b08b..f183c10c3631 100644 --- a/vcl/quartz/ctfonts.cxx +++ b/vcl/quartz/ctfonts.cxx @@ -50,6 +50,7 @@ CoreTextStyle::CoreTextStyle( const FontSelectPattern& rFSD ) , mfFontRotation( 0.0 ) , maFontSelData( rFSD ) , mpStyleDict( nullptr ) + , mpHbFace( nullptr ) { const FontSelectPattern* const pReqFont = &rFSD; @@ -116,6 +117,8 @@ CoreTextStyle::~CoreTextStyle() { if( mpStyleDict ) CFRelease( mpStyleDict ); + if( mpHbFace ) + hb_face_destroy( mpHbFace ); } void CoreTextStyle::GetFontMetric( ImplFontMetricDataRef& rxFontMetric ) const diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx index 89acdb74b506..2e012f37dce7 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -26,6 +26,21 @@ #include <limits> #include <salgdi.hxx> +#if defined(_WIN32) +struct WinSalGraphicsWithIDFace +{ + WinSalGraphics* mpWSL; + IDWriteFontFace* mpIDFace; + void* mpTableContext; + + WinSalGraphicsWithIDFace( WinSalGraphics* pWSL, IDWriteFontFace* pIDFace ) + : mpWSL( pWSL ), + mpIDFace( pIDFace ), + mpTableContext( nullptr ) + {} +}; +#endif + static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData) { char pTagName[5]; @@ -38,8 +53,8 @@ static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pU sal_uLong nLength = 0; #if defined(_WIN32) const unsigned char* pBuffer = nullptr; - HDC* phDC = static_cast<HDC*>(pUserData); - nLength = WinFontFace::GetTable(pTagName, pBuffer, *phDC); + WinSalGraphicsWithIDFace* pWSLWithIDFace = static_cast<WinSalGraphicsWithIDFace*>(pUserData); + nLength = (pWSLWithIDFace->mpWSL)->GetTable(pTagName, pBuffer, pWSLWithIDFace->mpTableContext, pWSLWithIDFace->mpIDFace); #elif defined(MACOSX) || defined(IOS) unsigned char* pBuffer = nullptr; CoreTextFontFace* pFont = static_cast<CoreTextFontFace*>(pUserData); @@ -57,7 +72,15 @@ static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pU hb_blob_t* pBlob = nullptr; if (pBuffer != nullptr) -#if defined(_WIN32) || defined(MACOSX) || defined(IOS) +#if defined(_WIN32) + pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, pWSLWithIDFace, + [](void* pUserData) + { + WinSalGraphicsWithIDFace* pUData = static_cast<WinSalGraphicsWithIDFace*>(pUserData); + pUData->mpIDFace->ReleaseFontTable(pUData->mpTableContext); + } + ); +#elif defined(MACOSX) || defined(IOS) pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, const_cast<unsigned char*>(pBuffer), [](void* data){ delete[] reinterpret_cast<unsigned char*>(data); }); #else @@ -77,13 +100,29 @@ static hb_unicode_funcs_t* getUnicodeFuncs() } #if defined(_WIN32) -CommonSalLayout::CommonSalLayout(HDC hDC, WinFontInstance& rWinFontInstance) -: mhDC(hDC), - mhFont((HFONT)GetCurrentObject(hDC, OBJ_FONT)), +CommonSalLayout::CommonSalLayout(WinSalGraphics* WSL, WinFontInstance& rWinFontInstance, const WinFontFace& rWinFontFace) +: mhFont((HFONT)GetCurrentObject(WSL->getHDC(), OBJ_FONT)), + mhDC(WSL->getHDC()), mpHbFace(nullptr), - maFontSelData(rWinFontInstance.maFontSelData) + maFontSelData(rWinFontInstance.maFontSelData), + mpD2DRenderer(nullptr) { - mpHbFace = hb_face_create_for_tables(getFontTable, &hDC, nullptr); + mpHbFace = rWinFontFace.GetHbFace(); + if(!mpHbFace) + { + mpD2DRenderer = dynamic_cast<D2DWriteTextOutRenderer*>(&TextOutRenderer::get()); + WinSalGraphicsWithIDFace* pWSLWithIDFace = new WinSalGraphicsWithIDFace(WSL, mpD2DRenderer->GetDWriteFontFace(mhDC)); + mpHbFace= hb_face_create_for_tables( getFontTable, pWSLWithIDFace, + [](void* pUserData) + { + WinSalGraphicsWithIDFace* pUData = static_cast<WinSalGraphicsWithIDFace*>( pUserData ); + if(pUData->mpIDFace) + pUData->mpIDFace->Release(); + delete pUData; + } + ); + rWinFontFace.SetHbFace(mpHbFace); + } } void CommonSalLayout::InitFont() const @@ -97,13 +136,18 @@ CommonSalLayout::CommonSalLayout(const CoreTextStyle& rCoreTextStyle) maFontSelData(rCoreTextStyle.maFontSelData), mrCoreTextStyle(rCoreTextStyle) { - CTFontRef pCTFont = static_cast<CTFontRef>(CFDictionaryGetValue(rCoreTextStyle.GetStyleDict(), kCTFontAttributeName)); - CGFontRef pCGFont = CTFontCopyGraphicsFont(pCTFont, NULL); - if (pCGFont) - mpHbFace = hb_coretext_face_create(pCGFont); - else - mpHbFace = hb_face_create_for_tables(getFontTable, const_cast<CoreTextFontFace*>(rCoreTextStyle.mpFontData), nullptr); - CGFontRelease(pCGFont); + mpHbFace = rCoreTextStyle.GetHbFace(); + if(!mpHbFace) + { + CTFontRef pCTFont = static_cast<CTFontRef>(CFDictionaryGetValue(rCoreTextStyle.GetStyleDict(), kCTFontAttributeName)); + CGFontRef pCGFont = CTFontCopyGraphicsFont(pCTFont, NULL); + if (pCGFont) + mpHbFace = hb_coretext_face_create(pCGFont); + else + mpHbFace = hb_face_create_for_tables(getFontTable, const_cast<CoreTextFontFace*>(rCoreTextStyle.mpFontData), nullptr); + CGFontRelease(pCGFont); + rCoreTextStyle.SetHbFace(mpHbFace); + } } #else @@ -112,15 +156,15 @@ CommonSalLayout::CommonSalLayout(ServerFont& rServerFont) maFontSelData(rServerFont.GetFontSelData()), mrServerFont(rServerFont) { - mpHbFace = hb_face_create_for_tables(getFontTable, &rServerFont, nullptr); + mpHbFace = rServerFont.GetHbFace(); + if(!mpHbFace) + { + mpHbFace = hb_face_create_for_tables(getFontTable, &rServerFont, nullptr); + mrServerFont.SetHbFace(mpHbFace); + } } #endif -CommonSalLayout::~CommonSalLayout() -{ - hb_face_destroy(mpHbFace); -} - hb_font_t* CommonSalLayout::GetHbFont() { // HACK. TODO: Get rid of HACK diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx index bc46febae7da..cf919c0bc616 100644 --- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx +++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx @@ -461,7 +461,8 @@ ServerFont::ServerFont( const FontSelectPattern& rFSD, FreetypeFontInfo* pFI ) mbArtItalic( false ), mbArtBold( false ), mbUseGamma( false ), - mpLayoutEngine( nullptr ) + mpLayoutEngine( nullptr ), + mpHbFace( nullptr ) { // TODO: move update of mpFontInstance into FontEntry class when // it becomes responsible for the ServerFont instantiation @@ -610,6 +611,9 @@ ServerFont::~ServerFont() mpFontInfo->ReleaseFaceFT(); + if( mpHbFace ) + hb_face_destroy( mpHbFace ); + ReleaseFromGarbageCollect(); } diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx index 6d4fd5eba630..a832b4596c34 100644 --- a/vcl/win/gdi/salfont.cxx +++ b/vcl/win/gdi/salfont.cxx @@ -865,7 +865,8 @@ WinFontFace::WinFontFace( const FontAttributes& rDFS, mnPitchAndFamily( nPitchAndFamily ), mbAliasSymbolsHigh( false ), mbAliasSymbolsLow( false ), - mbGsubRead( false ) + mbGsubRead( false ), + mpHbFace( nullptr ) { SetBitmapSize( 0, nHeight ); @@ -906,6 +907,9 @@ WinFontFace::~WinFontFace() #endif #endif // ENABLE_GRAPHITE delete mpEncodingVector; + + if( mpHbFace ) + hb_face_destroy( mpHbFace ); } sal_IntPtr WinFontFace::GetFontId() const @@ -1058,16 +1062,22 @@ void WinFontFace::ReadCmapTable( HDC hDC ) const } } -int WinFontFace::GetTable(const char pTagName[5], const unsigned char*& pResBuffer, HDC hDC) +sal_uLong WinSalGraphics::GetTable( const char pTagName[5], const unsigned char*& pResBuffer, void*& pTableContext, IDWriteFontFace*& pIDFace ) { - const DWORD nTableTag = CalcTag( pTagName ); - RawFontData aRawFontData( hDC, nTableTag ); - - if( !aRawFontData.get() ) + if( !pIDFace ) return 0; - - pResBuffer = aRawFontData.steal(); - return aRawFontData.size(); + const void* pResBuf; + UINT32 nSize; + BOOL bExists; + HRESULT hr = S_OK; + const DWORD nTableTag = DWRITE_MAKE_OPENTYPE_TAG( pTagName[0], pTagName[1], pTagName[2], pTagName[3] ); + hr = pIDFace->TryGetFontTable( nTableTag, &pResBuf, &nSize, &pTableContext, &bExists ); + if( SUCCEEDED( hr ) && ( bExists ) ) + { + pResBuffer = static_cast<const unsigned char*>(pResBuf); + return static_cast<sal_uLong>(nSize); + } + return 0; } void WinFontFace::GetFontCapabilities( HDC hDC ) const diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx index 051f3547910f..fe724e4dbf0f 100644 --- a/vcl/win/gdi/winlayout.cxx +++ b/vcl/win/gdi/winlayout.cxx @@ -3518,6 +3518,24 @@ bool D2DWriteTextOutRenderer::operator ()(SalLayout const &rLayout, HDC hDC, return (succeeded && nGlyphs >= 1 && pRectToErase); } +IDWriteFontFace* D2DWriteTextOutRenderer::GetDWriteFontFace(HDC hDC) const +{ + IDWriteFontFace* pFontFace; + bool succeeded = false; + try + { + succeeded = SUCCEEDED(mpGdiInterop->CreateFontFaceFromHdc(hDC, &pFontFace)); + } + catch (const std::exception& e) + { + SAL_WARN("vcl.gdi.opengl", "Error in dwrite while creating font face: " << e.what()); + return nullptr; + } + if(succeeded) + return pFontFace; + else return nullptr; +} + bool D2DWriteTextOutRenderer::BindFont(HDC hDC) { // A TextOutRender can only be bound to one font at a time, so the @@ -3810,7 +3828,7 @@ SalLayout* WinSalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLe if (getenv("SAL_USE_COMMON_LAYOUT")) { - return new CommonSalLayout(getHDC(), rFontInstance); + return new CommonSalLayout(this, rFontInstance, rFontFace); } else { @@ -3973,6 +3991,9 @@ PhysicalFontFace* WinFontFace::Clone() const if ( mpGraphiteData ) mpGraphiteData->AddReference(); #endif + if( mpHbFace ) + hb_face_reference( mpHbFace ); + PhysicalFontFace* pClone = new WinFontFace( *this ); return pClone; } |