summaryrefslogtreecommitdiff
path: root/vcl/win
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2017-12-26 15:14:31 +0000
committerKhaled Hosny <khaledhosny@eglug.org>2018-05-08 00:55:27 +0200
commitbdccb7e9991d83029eb2f2f11327b54534a00db8 (patch)
treec32e95c49849647dc72c1071f375f3d2b67d8d7a /vcl/win
parent9615e45d2e2bac79c252a018846e4f20012cfa34 (diff)
Refactor CommonSalLayout font handling
Moves all platform specific code from CommonSalLayout into the platform specific plugins. This way the vcl library won't depend on the Qt5 libraries and the Qt5Font header can be moved into the qt5 VCL plugin. While at it, switch the CommonSalLayouts font reference from the FontSelectPattern to the LogicalFontInstance and also add the harfbuzz font handling to the instance. Change-Id: Ida910b8d88837ea949a2f84394ccc0cfae153060 Reviewed-on: https://gerrit.libreoffice.org/47408 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Khaled Hosny <khaledhosny@eglug.org>
Diffstat (limited to 'vcl/win')
-rw-r--r--vcl/win/gdi/salfont.cxx16
-rw-r--r--vcl/win/gdi/winlayout.cxx95
-rw-r--r--vcl/win/window/salframe.cxx2
3 files changed, 92 insertions, 21 deletions
diff --git a/vcl/win/gdi/salfont.cxx b/vcl/win/gdi/salfont.cxx
index 2c96edc91fbe..62d9f7d85dd7 100644
--- a/vcl/win/gdi/salfont.cxx
+++ b/vcl/win/gdi/salfont.cxx
@@ -622,8 +622,7 @@ WinFontFace::WinFontFace( const FontAttributes& rDFS,
meWinCharSet( eWinCharSet ),
mnPitchAndFamily( nPitchAndFamily ),
mbAliasSymbolsHigh( false ),
- mbAliasSymbolsLow( false ),
- mpHbFont( nullptr )
+ mbAliasSymbolsLow( false )
{
SetBitmapSize( 0, nHeight );
@@ -652,9 +651,6 @@ WinFontFace::WinFontFace( const FontAttributes& rDFS,
WinFontFace::~WinFontFace()
{
mxUnicodeMap.clear();
-
- if( mpHbFont )
- hb_font_destroy( mpHbFont );
}
sal_IntPtr WinFontFace::GetFontId() const
@@ -662,6 +658,16 @@ sal_IntPtr WinFontFace::GetFontId() const
return mnId;
}
+PhysicalFontFace* WinFontFace::Clone() const
+{
+ return new WinFontFace(*this);
+}
+
+LogicalFontInstance* WinFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
+{
+ return new WinFontInstance(*this, rFSD);
+}
+
static inline DWORD CalcTag( const char p[5]) { return (p[0]+(p[1]<<8)+(p[2]<<16)+(p[3]<<24)); }
void WinFontFace::UpdateFromHDC( HDC hDC ) const
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index cc37b866848d..3188f7f3d0bb 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -251,7 +251,7 @@ bool ExTextOutRenderer::operator ()(CommonSalLayout const &rLayout,
HFONT hAltFont = nullptr;
bool bUseAltFont = false;
bool bShift = false;
- if (rLayout.getFontSelData().mbVertical)
+ if (rLayout.getFont().GetFontSelectPattern().mbVertical)
{
LOGFONTW aLogFont;
GetObjectW(hFont, sizeof(aLogFont), &aLogFont);
@@ -307,7 +307,9 @@ std::unique_ptr<SalLayout> WinSalGraphics::GetTextLayout(ImplLayoutArgs& /*rArgs
assert(mpWinFontEntry[nFallbackLevel]->GetFontFace());
- return std::unique_ptr<SalLayout>(new CommonSalLayout(getHDC(), *mpWinFontEntry[nFallbackLevel]));
+ mpWinFontEntry[nFallbackLevel]->SetHDC(getHDC());
+ CommonSalLayout *aLayout = new CommonSalLayout(*mpWinFontEntry[nFallbackLevel]);
+ return std::unique_ptr<SalLayout>(aLayout);
}
LogicalFontInstance * WinSalGraphics::GetWinFontEntry(int const nFallbackLevel)
@@ -324,18 +326,76 @@ WinFontInstance::~WinFontInstance()
{
}
-PhysicalFontFace* WinFontFace::Clone() const
+bool WinFontInstance::hasHScale() const
{
- if( mpHbFont )
- hb_font_reference( mpHbFont );
+ const FontSelectPattern &rPattern = GetFontSelectPattern();
+ int nHeight(rPattern.mnHeight);
+ int nWidth(rPattern.mnWidth ? rPattern.mnWidth * GetAverageWidthFactor() : nHeight);
+ return nWidth != nHeight;
+}
- PhysicalFontFace* pClone = new WinFontFace( *this );
- return pClone;
+static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData)
+{
+ sal_uLong nLength = 0;
+ unsigned char* pBuffer = nullptr;
+ HFONT hFont = static_cast<HFONT>(pUserData);
+ HDC hDC = GetDC(nullptr);
+ HGDIOBJ hOrigFont = SelectObject(hDC, hFont);
+ nLength = ::GetFontData(hDC, OSL_NETDWORD(nTableTag), 0, nullptr, 0);
+ if (nLength > 0 && nLength != GDI_ERROR)
+ {
+ pBuffer = new unsigned char[nLength];
+ ::GetFontData(hDC, OSL_NETDWORD(nTableTag), 0, pBuffer, nLength);
+ }
+ SelectObject(hDC, hOrigFont);
+ ReleaseDC(nullptr, hDC);
+
+ hb_blob_t* pBlob = nullptr;
+ if (pBuffer != nullptr)
+ pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY,
+ pBuffer, [](void* data){ delete[] static_cast<unsigned char*>(data); });
+ return pBlob;
}
-LogicalFontInstance* WinFontFace::CreateFontInstance(const FontSelectPattern& rFSD) const
+hb_font_t* WinFontInstance::ImplInitHbFont()
{
- return new WinFontInstance(*this, rFSD);
+ assert(m_hDC);
+ m_hFont = static_cast<HFONT>(GetCurrentObject(m_hDC, OBJ_FONT));
+ hb_font_t* pHbFont = InitHbFont(hb_face_create_for_tables(getFontTable, m_hFont, nullptr));
+
+ // Calculate the AverageWidthFactor, see LogicalFontInstance::GetScale().
+ if (GetFontSelectPattern().mnWidth)
+ {
+ double nUPEM = hb_face_get_upem(hb_font_get_face(pHbFont));
+
+ LOGFONTW aLogFont;
+ GetObjectW(m_hFont, sizeof(LOGFONTW), &aLogFont);
+
+ // Set the height (font size) to EM to minimize rounding errors.
+ aLogFont.lfHeight = -nUPEM;
+ // Set width to the default to get the original value in the metrics.
+ aLogFont.lfWidth = 0;
+
+ // Get the font metrics.
+ HFONT hNewFont = CreateFontIndirectW(&aLogFont);
+ HFONT hOldFont = static_cast<HFONT>(SelectObject(m_hDC, hNewFont));
+ TEXTMETRICW aFontMetric;
+ GetTextMetricsW(m_hDC, &aFontMetric);
+ SelectObject(m_hDC, hOldFont);
+ DeleteObject(hNewFont);
+
+ SetAverageWidthFactor(nUPEM / aFontMetric.tmAveCharWidth);
+ }
+
+ return pHbFont;
+}
+
+void WinFontInstance::SetHDC(const HDC hDC)
+{
+ if (m_hDC == hDC)
+ return;
+ ReleaseHbFont();
+ m_hDC = hDC;
}
bool WinSalGraphics::CacheGlyphs(const CommonSalLayout& rLayout)
@@ -345,8 +405,8 @@ bool WinSalGraphics::CacheGlyphs(const CommonSalLayout& rLayout)
return false;
HDC hDC = getHDC();
- HFONT hFONT = rLayout.getHFONT();
- WinFontInstance& rFont = rLayout.getWinFontInstance();
+ WinFontInstance& rFont = *static_cast<WinFontInstance*>(&rLayout.getFont());
+ HFONT hFONT = rFont.GetHFONT();
int nStart = 0;
Point aPos(0, 0);
@@ -377,7 +437,7 @@ bool WinSalGraphics::DrawCachedGlyphs(const CommonSalLayout& rLayout)
if (!pImpl)
return false;
- WinFontInstance& rFont = rLayout.getWinFontInstance();
+ WinFontInstance& rFont = *static_cast<WinFontInstance*>(&rLayout.getFont());
int nStart = 0;
Point aPos(0, 0);
@@ -412,9 +472,12 @@ void WinSalGraphics::DrawTextLayout(const CommonSalLayout& rLayout)
{
HDC hDC = getHDC();
+ HFONT hFont = static_cast<const WinFontInstance*>(&rLayout.getFont())->GetHFONT();
+ HGDIOBJ hOrigFont = SelectObject(hDC, hFont);
+
// Our DirectWrite renderer is incomplete, skip it for non-horizontal or
// stretched text.
- bool bForceGDI = rLayout.GetOrientation() || rLayout.hasHScale();
+ bool bForceGDI = rLayout.GetOrientation() || static_cast<const WinFontInstance*>(&rLayout.getFont())->hasHScale();
bool bUseOpenGL = OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter;
if (!bUseOpenGL)
@@ -477,7 +540,7 @@ void WinSalGraphics::DrawTextLayout(const CommonSalLayout& rLayout)
// setup the hidden DC with black color and white background, we will
// use the result of the text drawing later as a mask only
- HFONT hOrigFont = ::SelectFont(aDC.getCompatibleHDC(), static_cast<HFONT>(::GetCurrentObject(hDC, OBJ_FONT)));
+ HFONT hOFont = ::SelectFont(aDC.getCompatibleHDC(), hFont);
::SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0));
::SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255));
@@ -495,11 +558,13 @@ void WinSalGraphics::DrawTextLayout(const CommonSalLayout& rLayout)
if (xTexture)
pImpl->DrawMask(*xTexture, salColor, aDC.getTwoRect());
- ::SelectFont(aDC.getCompatibleHDC(), hOrigFont);
+ ::SelectFont(aDC.getCompatibleHDC(), hOFont);
pImpl->PostDraw();
}
}
+
+ SelectObject(hDC, hOrigFont);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx
index ed65a8698d70..633e97c6670e 100644
--- a/vcl/win/window/salframe.cxx
+++ b/vcl/win/window/salframe.cxx
@@ -2184,7 +2184,7 @@ static void ImplSalFrameSetInputContext( HWND hWnd, const SalInputContext* pCont
// specified by this font name; but it seems to decide whether
// to use that font's horizontal or vertical variant based on a
// '@' in front of this font name.
- ImplGetLogFontFromFontSelect(hDC, pContext->mpFont,
+ ImplGetLogFontFromFontSelect(hDC, &pContext->mpFont->GetFontSelectPattern(),
nullptr, aLogFont);
ReleaseDC( pFrame->mhWnd, hDC );
ImmSetCompositionFontW( hIMC, &aLogFont );