summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2015-12-18 14:38:27 +0200
committerTor Lillqvist <tml@collabora.com>2015-12-18 15:02:47 +0200
commitac04051a3565bb5cde904da9a84b6e22443cf8b5 (patch)
treef7a3f4d6710d6b28e7bfec00366766f62a9b81a2
parent6e80c6b9d40408a745ab0ced5d217118985e4079 (diff)
tdf#95054: Make sure glyphs alpha blend properly in the Graphite+OpenGL case
The problem apparently was that the GraphiteWinLayout::DrawTextImpl() function drew each glyph using a separate call to ExtTextOutW(). That mishandled anti-aliased glyphs (alpha), somewhat in the way as described in the nice long comment (thanks kendy!) in WinLayout::DrawText(). The irony here is that in the case of Graphite fonts and OpenGL, it is exactly from that code block in WinLayout::DrawText() that GraphiteWinLayout::DrawTextImpl() gets called, and in that situation it itself runs into the same or similar problem as the calling code wants to avoid for the run as a whole. It draws each glyph separately, and subsequent glyphs will overwrite the rightmost pixels of the earlier one instead of blend properly. Or something like that. As a solution, change the interface of DrawTextImpl() so that instead of being called once to draw a run of text, it might draw just a part of the run, and in that case expects to be called repeatedly to draw the whole text. The GraphiteWinLayout::DrawTextImpl() implementation does it like this in the case of using OpenGL (as indicated by the presence of a non-null pRectToErase, as added in b7842c93dc06b831d3fa649410ed847358ce9d17 for tdf#95648). The end result is that it draws one glyph at a time into the DC for the bitmap allocated in the caller, WinLayout::DrawText(). The caller uses that bitmap as a texture and blends it into the actual destination, separately for each glyph. For non-Graphite fonts, or when not using OpenGL, nothing should change. No repeated DrawTextImpl calls are done to iterate over a run. Change-Id: Ib7adc30665fc7804913fd2f8886c5b29d9ca42c4 (cherry picked from commit 61085083e4a5060ba7e2135818264d63c6da13c2)
-rw-r--r--vcl/win/source/gdi/winlayout.cxx79
-rw-r--r--vcl/win/source/gdi/winlayout.hxx6
2 files changed, 52 insertions, 33 deletions
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 7c573666edd8..cef4f8a73f5b 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -566,7 +566,10 @@ void WinLayout::DrawText(SalGraphics& rGraphics) const
if (!mbUseOpenGL)
{
// no OpenGL, just classic rendering
- DrawTextImpl(hDC, NULL);
+ Point aPos(0, 0);
+ int nGetNextGlypInfo(0);
+ bool bContinue = DrawTextImpl(hDC, NULL, &aPos, &nGetNextGlypInfo);
+ assert(!bContinue);
}
else if (CacheGlyphs(rGraphics) &&
DrawCachedGlyphs(rGraphics))
@@ -607,40 +610,49 @@ void WinLayout::DrawText(SalGraphics& rGraphics) const
Rectangle aRect;
GetBoundRect(rGraphics, aRect);
- OpenGLCompatibleDC aDC(rGraphics, aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight());
+ WinOpenGLSalGraphicsImpl *pImpl = dynamic_cast<WinOpenGLSalGraphicsImpl*>(rWinGraphics.mpImpl.get());
- // we are making changes to the DC, make sure we got a new one
- assert(aDC.getCompatibleHDC() != hDC);
+ if (pImpl)
+ {
+ pImpl->PreDraw();
- // 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(), mhFont);
+ Point aPos(0, 0);
+ int nGetNextGlypInfo(0);
+ while (true)
+ {
+ OpenGLCompatibleDC aDC(rGraphics, aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight());
- SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0));
- SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255));
+ // we are making changes to the DC, make sure we got a new one
+ assert(aDC.getCompatibleHDC() != hDC);
- UINT nTextAlign = GetTextAlign(hDC);
- SetTextAlign(aDC.getCompatibleHDC(), nTextAlign);
+ // 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(), mhFont);
- // the actual drawing
- DrawTextImpl(aDC.getCompatibleHDC(), &aRect);
+ SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0));
+ SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255));
- COLORREF color = GetTextColor(hDC);
- SalColor salColor = MAKE_SALCOLOR(GetRValue(color), GetGValue(color), GetBValue(color));
+ UINT nTextAlign = GetTextAlign(hDC);
+ SetTextAlign(aDC.getCompatibleHDC(), nTextAlign);
- WinOpenGLSalGraphicsImpl *pImpl = dynamic_cast<WinOpenGLSalGraphicsImpl*>(rWinGraphics.mpImpl.get());
- if (pImpl)
- {
- pImpl->PreDraw();
+ COLORREF color = GetTextColor(hDC);
+ SalColor salColor = MAKE_SALCOLOR(GetRValue(color), GetGValue(color), GetBValue(color));
+
+ // the actual drawing
+ bool bContinue = DrawTextImpl(aDC.getCompatibleHDC(), &aRect, &aPos, &nGetNextGlypInfo);
- std::unique_ptr<OpenGLTexture> xTexture(aDC.getTexture());
- if (xTexture)
- pImpl->DrawMask(*xTexture, salColor, aDC.getTwoRect());
+ std::unique_ptr<OpenGLTexture> xTexture(aDC.getTexture());
+ if (xTexture)
+ pImpl->DrawMask(*xTexture, salColor, aDC.getTwoRect());
+ SelectFont(aDC.getCompatibleHDC(), hOrigFont);
+
+ if (!bContinue)
+ break;
+ }
pImpl->PostDraw();
}
- SelectFont(aDC.getCompatibleHDC(), hOrigFont);
}
}
@@ -1764,7 +1776,10 @@ void UniscribeLayout::Simplify( bool /*bIsBase*/ )
}
}
-void UniscribeLayout::DrawTextImpl(HDC hDC, const Rectangle* /* pRectToErase */) const
+bool UniscribeLayout::DrawTextImpl(HDC hDC,
+ const Rectangle* /* pRectToErase */,
+ Point* /* pPos */,
+ int* /* pGetNextGlypInfo */) const
{
HFONT hOrigFont = DisableFontScaling();
@@ -1812,6 +1827,8 @@ void UniscribeLayout::DrawTextImpl(HDC hDC, const Rectangle* /* pRectToErase */)
if( hOrigFont )
DeleteFont(SelectFont(hDC, hOrigFont));
+
+ return false;
}
bool UniscribeLayout::CacheGlyphs(SalGraphics& rGraphics) const
@@ -2770,7 +2787,10 @@ void GraphiteWinLayout::AdjustLayout(ImplLayoutArgs& rArgs)
maImpl.AdjustLayout(rArgs);
}
-void GraphiteWinLayout::DrawTextImpl(HDC hDC, const Rectangle* pRectToErase) const
+bool GraphiteWinLayout::DrawTextImpl(HDC hDC,
+ const Rectangle* pRectToErase,
+ Point* pPos,
+ int* pGetNextGlypInfo) const
{
if (pRectToErase)
{
@@ -2784,19 +2804,18 @@ void GraphiteWinLayout::DrawTextImpl(HDC hDC, const Rectangle* pRectToErase) con
const int MAX_GLYPHS = 2;
sal_GlyphId glyphIntStr[MAX_GLYPHS];
WORD glyphWStr[MAX_GLYPHS];
- int glyphIndex = 0;
- Point aPos(0,0);
int nGlyphs = 0;
do
{
- nGlyphs = maImpl.GetNextGlyphs(1, glyphIntStr, aPos, glyphIndex);
+ nGlyphs = maImpl.GetNextGlyphs(1, glyphIntStr, *pPos, *pGetNextGlypInfo);
if (nGlyphs < 1)
break;
std::copy(glyphIntStr, glyphIntStr + nGlyphs, glyphWStr);
- ExtTextOutW(hDC, aPos.X(), aPos.Y(), ETO_GLYPH_INDEX, NULL, (LPCWSTR)&(glyphWStr), nGlyphs, NULL);
- } while (nGlyphs);
+ ExtTextOutW(hDC, pPos->X(), pPos->Y(), ETO_GLYPH_INDEX, NULL, (LPCWSTR)&(glyphWStr), nGlyphs, NULL);
+ } while (!pRectToErase);
if( hOrigFont )
DeleteFont(SelectFont(hDC, hOrigFont));
+ return (pRectToErase && nGlyphs >= 1);
}
bool GraphiteWinLayout::CacheGlyphs(SalGraphics& /*rGraphics*/) const
diff --git a/vcl/win/source/gdi/winlayout.hxx b/vcl/win/source/gdi/winlayout.hxx
index db09d1eda308..ff4e5cced2a3 100644
--- a/vcl/win/source/gdi/winlayout.hxx
+++ b/vcl/win/source/gdi/winlayout.hxx
@@ -53,7 +53,7 @@ public:
virtual void DrawText(SalGraphics&) const override;
/// Draw to the provided HDC.
- virtual void DrawTextImpl(HDC hDC, const Rectangle* pRectToErase) const = 0;
+ virtual bool DrawTextImpl(HDC hDC, const Rectangle* pRectToErase, Point* pPos, int* pGetNextGlypInfo) const = 0;
virtual bool CacheGlyphs(SalGraphics& rGraphics) const = 0;
virtual bool DrawCachedGlyphs(SalGraphics& rGraphics) const = 0;
@@ -75,7 +75,7 @@ public:
virtual bool LayoutText( ImplLayoutArgs& ) override;
virtual void AdjustLayout( ImplLayoutArgs& ) override;
- virtual void DrawTextImpl(HDC hDC, const Rectangle* pRectToErase) const override;
+ virtual bool DrawTextImpl(HDC hDC, const Rectangle* pRectToErase, Point* pPos, int* pGetNextGlypInfo) const override;
virtual bool CacheGlyphs(SalGraphics& rGraphics) const override;
virtual bool DrawCachedGlyphs(SalGraphics& rGraphics) const override;
virtual int GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&,
@@ -168,7 +168,7 @@ public:
// used by upper layers
virtual bool LayoutText( ImplLayoutArgs& ) override; // first step of layout
virtual void AdjustLayout( ImplLayoutArgs& ) override; // adjusting after fallback etc.
- virtual void DrawTextImpl(HDC hDC, const Rectangle* pRectToErase) const override;
+ virtual bool DrawTextImpl(HDC hDC, const Rectangle* pRectToErase, Point* pPos, int* pGetNextGlypInfo) const override;
virtual bool CacheGlyphs(SalGraphics& rGraphics) const override;
virtual bool DrawCachedGlyphs(SalGraphics& rGraphics) const override;