summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-04-24 17:07:30 +0200
committerLuboš Luňák <l.lunak@collabora.com>2019-04-29 11:48:31 +0200
commit4266020a78e98d7271e7dca8f5727cd7a419afc6 (patch)
treed96fa643989dbbfaaf199a7a51f82e95e501d088 /vcl
parentdc3752ef01e7646af1978337aa5ba458f27774b6 (diff)
Related: tdf#113076 vcl win DirectWrite: handle stretched text
Commit a51b7a1c3a7e7cf7b0c733e1dec40288278c1884 (tdf#103831, tdf#100986: Force using GDI when needed, 2017-03-03) noted that the DirectWrite text renderer doesn't support stretched text, add support for this now by setting a DirectWrite transform matrix that only does horizontal scaling. With this, tdf#113076 is kept fixed, but at the same time manually stretched text keeps working. Previously the glyphs of the text had the correct size and position, but the glyphs themselves where not streched, but simply aligned to the left. (cherry picked from commit 51bcbfc88883596fceedfe019e841aab129425c9) Change-Id: I8fe8e74d3edc0d71ed2f16fcce66c6f5009ed264 Reviewed-on: https://gerrit.libreoffice.org/71289 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/win/DWriteTextRenderer.hxx12
-rw-r--r--vcl/inc/win/winlayout.hxx1
-rw-r--r--vcl/win/gdi/DWriteTextRenderer.cxx21
-rw-r--r--vcl/win/gdi/winlayout.cxx19
4 files changed, 47 insertions, 6 deletions
diff --git a/vcl/inc/win/DWriteTextRenderer.hxx b/vcl/inc/win/DWriteTextRenderer.hxx
index 0e81b67167d1..270c4772716f 100644
--- a/vcl/inc/win/DWriteTextRenderer.hxx
+++ b/vcl/inc/win/DWriteTextRenderer.hxx
@@ -95,6 +95,18 @@ private:
D2DTextAntiAliasMode meTextAntiAliasMode;
};
+/// Sets and unsets the needed DirectWrite transform to support the font's horizontal scaling.
+class WinFontStretchGuard
+{
+public:
+ WinFontStretchGuard(ID2D1RenderTarget* pRenderTarget, float fHScale);
+ ~WinFontStretchGuard();
+
+private:
+ ID2D1RenderTarget* mpRenderTarget;
+ D2D1::Matrix3x2F maTransform;
+};
+
#endif // INCLUDED_VCL_INC_WIN_DWRITERENDERER_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx
index 042e30e9f299..2bbd87a12206 100644
--- a/vcl/inc/win/winlayout.hxx
+++ b/vcl/inc/win/winlayout.hxx
@@ -151,6 +151,7 @@ public:
~WinFontInstance() override;
bool hasHScale() const;
+ float getHScale() const;
void SetGraphics(WinSalGraphics*);
WinSalGraphics* GetGraphics() const { return m_pGraphics; }
diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx b/vcl/win/gdi/DWriteTextRenderer.cxx
index 6dbfdbf403c3..50ec50897c80 100644
--- a/vcl/win/gdi/DWriteTextRenderer.cxx
+++ b/vcl/win/gdi/DWriteTextRenderer.cxx
@@ -271,6 +271,10 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa
if (!GetDWriteFaceFromHDC(hDC, &mpFontFace, &mlfEmHeight))
return false;
+ const WinFontInstance& rWinFont = static_cast<const WinFontInstance&>(rLayout.GetFont());
+ float fHScale = rWinFont.getHScale();
+ WinFontStretchGuard aStretchGuard(mpRT, fHScale);
+
tools::Rectangle bounds;
bool succeeded = rLayout.GetBoundRect(bounds);
if (succeeded)
@@ -297,9 +301,10 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa
while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart))
{
UINT16 glyphIndices[] = { pGlyph->m_aGlyphId };
- FLOAT glyphAdvances[] = { static_cast<FLOAT>(pGlyph->m_nNewWidth) };
+ FLOAT glyphAdvances[] = { static_cast<FLOAT>(pGlyph->m_nNewWidth) / fHScale };
DWRITE_GLYPH_OFFSET glyphOffsets[] = { { 0.0f, 0.0f }, };
- D2D1_POINT_2F baseline = { static_cast<FLOAT>(aPos.X() - bounds.Left()), static_cast<FLOAT>(aPos.Y() - bounds.Top()) };
+ D2D1_POINT_2F baseline = { static_cast<FLOAT>(aPos.X() - bounds.Left()) / fHScale,
+ static_cast<FLOAT>(aPos.Y() - bounds.Top()) };
DWRITE_GLYPH_RUN glyphs = {
mpFontFace,
mlfEmHeight,
@@ -418,6 +423,18 @@ bool D2DWriteTextOutRenderer::GetDWriteFaceFromHDC(HDC hDC, IDWriteFontFace ** p
return succeeded;
}
+WinFontStretchGuard::WinFontStretchGuard(ID2D1RenderTarget* pRenderTarget, float fHScale)
+ : mpRenderTarget(pRenderTarget)
+{
+ pRenderTarget->GetTransform(&maTransform);
+ if (fHScale == 1.0f)
+ return;
+
+ D2D1::Matrix3x2F aTransform
+ = maTransform * D2D1::Matrix3x2F::Scale(D2D1::Size(fHScale, 1.0f), D2D1::Point2F(0, 0));
+ mpRenderTarget->SetTransform(aTransform);
+}
+WinFontStretchGuard::~WinFontStretchGuard() { mpRenderTarget->SetTransform(maTransform); }
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index 3aa8133be598..b9453f7b96d1 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -117,10 +117,11 @@ bool WinFontInstance::CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, S
std::vector<float> aGlyphAdv(1); // offsets between glyphs
std::vector<DWRITE_GLYPH_OFFSET> aGlyphOffset(1, DWRITE_GLYPH_OFFSET{0.0f, 0.0f});
std::vector<int> aEnds(1); // end of each glyph box
+ float fHScale = getHScale();
float totWidth = 0;
{
int overhang = aInkBoxes[0].Left();
- int blackWidth = aInkBoxes[0].getWidth(); // width of non-AA pixels
+ int blackWidth = aInkBoxes[0].getWidth() * fHScale; // width of non-AA pixels
aElement.maLeftOverhangs = overhang;
aGlyphAdv[0] = blackWidth + aElement.getExtraSpace();
@@ -171,6 +172,7 @@ bool WinFontInstance::CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, S
0
};
+ WinFontStretchGuard aStretchGuard(pRT, fHScale);
pRT->BeginDraw();
pRT->DrawGlyphRun(baseline, &glyphs, pBrush);
HRESULT hResult = pRT->EndDraw();
@@ -320,6 +322,16 @@ bool WinFontInstance::hasHScale() const
return nWidth != nHeight;
}
+float WinFontInstance::getHScale() const
+{
+ const FontSelectPattern& rPattern = GetFontSelectPattern();
+ int nHeight(rPattern.mnHeight);
+ if (!nHeight)
+ return 1.0;
+ float nWidth(rPattern.mnWidth ? rPattern.mnWidth * GetAverageWidthFactor() : nHeight);
+ return nWidth / nHeight;
+}
+
static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData)
{
sal_uLong nLength = 0;
@@ -467,9 +479,8 @@ void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
const HFONT hLayoutFont = pWinFont->GetHFONT();
bool bUseOpenGL = OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter;
- // Our DirectWrite renderer is incomplete, skip it for non-horizontal or
- // stretched text.
- bool bForceGDI = rLayout.GetOrientation() || (pWinFont->hasHScale() && !bUseOpenGL);
+ // Our DirectWrite renderer is incomplete, skip it for non-horizontal text.
+ bool bForceGDI = rLayout.GetOrientation();
if (!bUseOpenGL)
{