Kaydet (Commit) 51bcbfc8 authored tarafından Miklos Vajna's avatar Miklos Vajna

Related: tdf#113076 vcl win DirectWrite: handle stretched text

Commit a51b7a1c (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/71245Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
üst 27c6d1db
...@@ -81,6 +81,18 @@ private: ...@@ -81,6 +81,18 @@ private:
D2DTextAntiAliasMode meTextAntiAliasMode; 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 #endif // INCLUDED_VCL_INC_WIN_DWRITERENDERER_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -151,6 +151,7 @@ public: ...@@ -151,6 +151,7 @@ public:
~WinFontInstance() override; ~WinFontInstance() override;
bool hasHScale() const; bool hasHScale() const;
float getHScale() const;
void SetGraphics(WinSalGraphics*); void SetGraphics(WinSalGraphics*);
WinSalGraphics* GetGraphics() const { return m_pGraphics; } WinSalGraphics* GetGraphics() const { return m_pGraphics; }
......
...@@ -232,6 +232,10 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa ...@@ -232,6 +232,10 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa
if (!GetDWriteFaceFromHDC(hDC, &mpFontFace, &mlfEmHeight)) if (!GetDWriteFaceFromHDC(hDC, &mpFontFace, &mlfEmHeight))
return false; return false;
const WinFontInstance& rWinFont = static_cast<const WinFontInstance&>(rLayout.GetFont());
float fHScale = rWinFont.getHScale();
WinFontStretchGuard aStretchGuard(mpRT, fHScale);
tools::Rectangle bounds; tools::Rectangle bounds;
bool succeeded = rLayout.GetBoundRect(bounds); bool succeeded = rLayout.GetBoundRect(bounds);
if (succeeded) if (succeeded)
...@@ -258,9 +262,10 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa ...@@ -258,9 +262,10 @@ bool D2DWriteTextOutRenderer::performRender(GenericSalLayout const & rLayout, Sa
while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart)) while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart))
{ {
UINT16 glyphIndices[] = { pGlyph->m_aGlyphId }; 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 }, }; 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 = { DWRITE_GLYPH_RUN glyphs = {
mpFontFace, mpFontFace,
mlfEmHeight, mlfEmHeight,
...@@ -379,6 +384,18 @@ bool D2DWriteTextOutRenderer::GetDWriteFaceFromHDC(HDC hDC, IDWriteFontFace ** p ...@@ -379,6 +384,18 @@ bool D2DWriteTextOutRenderer::GetDWriteFaceFromHDC(HDC hDC, IDWriteFontFace ** p
return succeeded; 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: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -116,10 +116,11 @@ bool WinFontInstance::CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, S ...@@ -116,10 +116,11 @@ bool WinFontInstance::CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, S
std::vector<float> aGlyphAdv(1); // offsets between glyphs std::vector<float> aGlyphAdv(1); // offsets between glyphs
std::vector<DWRITE_GLYPH_OFFSET> aGlyphOffset(1, {0.0f, 0.0f}); std::vector<DWRITE_GLYPH_OFFSET> aGlyphOffset(1, {0.0f, 0.0f});
std::vector<int> aEnds(1); // end of each glyph box std::vector<int> aEnds(1); // end of each glyph box
float fHScale = getHScale();
float totWidth = 0; float totWidth = 0;
{ {
int overhang = aInkBoxes[0].Left(); 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; aElement.maLeftOverhangs = overhang;
aGlyphAdv[0] = blackWidth + aElement.getExtraSpace(); aGlyphAdv[0] = blackWidth + aElement.getExtraSpace();
...@@ -170,6 +171,7 @@ bool WinFontInstance::CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, S ...@@ -170,6 +171,7 @@ bool WinFontInstance::CacheGlyphToAtlas(HDC hDC, HFONT hFont, int nGlyphIndex, S
0 0
}; };
WinFontStretchGuard aStretchGuard(pRT, fHScale);
pRT->BeginDraw(); pRT->BeginDraw();
pRT->DrawGlyphRun(baseline, &glyphs, pBrush); pRT->DrawGlyphRun(baseline, &glyphs, pBrush);
HRESULT hResult = pRT->EndDraw(); HRESULT hResult = pRT->EndDraw();
...@@ -314,6 +316,16 @@ bool WinFontInstance::hasHScale() const ...@@ -314,6 +316,16 @@ bool WinFontInstance::hasHScale() const
return nWidth != nHeight; 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) static hb_blob_t* getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData)
{ {
sal_uLong nLength = 0; sal_uLong nLength = 0;
...@@ -460,9 +472,8 @@ void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout) ...@@ -460,9 +472,8 @@ void WinSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
const HFONT hLayoutFont = pWinFont->GetHFONT(); const HFONT hLayoutFont = pWinFont->GetHFONT();
bool bUseOpenGL = OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter; bool bUseOpenGL = OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter;
// Our DirectWrite renderer is incomplete, skip it for non-horizontal or // Our DirectWrite renderer is incomplete, skip it for non-horizontal text.
// stretched text. bool bForceGDI = rLayout.GetOrientation();
bool bForceGDI = rLayout.GetOrientation() || (pWinFont->hasHScale() && !bUseOpenGL);
if (!bUseOpenGL) if (!bUseOpenGL)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment