summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorAkash Jain <akash96j@gmail.com>2016-08-17 21:31:22 +0530
committerKhaled Hosny <khaledhosny@eglug.org>2016-10-18 20:41:30 +0200
commit5e65efcaa38ea5fbe655a18082a3ba7c8cf7d5fe (patch)
treef4d343cd38c51bf3ed86561aef951b3abf91db0f /vcl
parent3eda74cf7e9d23cc08f07c38f3bee04b565ff9db (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.hxx4
-rw-r--r--vcl/inc/quartz/salgdi.h4
-rw-r--r--vcl/inc/unx/glyphcache.hxx4
-rw-r--r--vcl/inc/win/salgdi.h8
-rwxr-xr-xvcl/inc/win/winlayout.hxx1
-rw-r--r--vcl/quartz/ctfonts.cxx3
-rw-r--r--vcl/source/gdi/CommonSalLayout.cxx86
-rw-r--r--vcl/unx/generic/glyphs/freetype_glyphcache.cxx6
-rw-r--r--vcl/win/gdi/salfont.cxx28
-rw-r--r--vcl/win/gdi/winlayout.cxx23
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;
}