summaryrefslogtreecommitdiff
path: root/vcl/win
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-04-24 17:07:30 +0200
committerMiklos Vajna <vmiklos@collabora.com>2019-04-24 18:40:15 +0200
commit51bcbfc88883596fceedfe019e841aab129425c9 (patch)
treea3e92f946038764e5a329abc737ab2aea437b98a /vcl/win
parent27c6d1dbdb3dcad02a244ab942adb9222a461e44 (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. Change-Id: I8fe8e74d3edc0d71ed2f16fcce66c6f5009ed264 Reviewed-on: https://gerrit.libreoffice.org/71245 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
Diffstat (limited to 'vcl/win')
-rw-r--r--vcl/win/gdi/DWriteTextRenderer.cxx21
-rw-r--r--vcl/win/gdi/winlayout.cxx19
2 files changed, 34 insertions, 6 deletions
diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx b/vcl/win/gdi/DWriteTextRenderer.cxx
index 117b35989b1c..dac6452a41a5 100644
--- a/vcl/win/gdi/DWriteTextRenderer.cxx
+++ b/vcl/win/gdi/DWriteTextRenderer.cxx
@@ -232,6 +232,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)
@@ -258,9 +262,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,
@@ -379,6 +384,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 b3fe0132b7df..1d804fcd08d1 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -116,10 +116,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, {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();
@@ -170,6 +171,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();
@@ -314,6 +316,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;
@@ -460,9 +472,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)
{