[Libreoffice-commits] core.git: vcl/inc vcl/win
Khaled Hosny
khaledhosny at eglug.org
Fri Oct 21 18:48:45 UTC 2016
vcl/inc/win/salgdi.h | 2 +
vcl/win/gdi/winlayout.cxx | 88 ++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 87 insertions(+), 3 deletions(-)
New commits:
commit 36bafd3d4ad7fa75649eeab0c9cd1b3d6f53d8e8
Author: Khaled Hosny <khaledhosny at eglug.org>
Date: Fri Oct 21 03:01:43 2016 +0200
tdf#103365: Try to fix Windows OpenGL rendering
Essentially an adapted copy of WinLayout::DrawText(). Avoiding code
duplication would have been nicer, but it is going to be too complicated
and the other copy is going away soonish anyway.
Change-Id: I7db4008a0db3d01d71d106e06fe413658f9bf42d
Reviewed-on: https://gerrit.libreoffice.org/30123
Reviewed-by: akash <akash96j at gmail.com>
Reviewed-by: Khaled Hosny <khaledhosny at eglug.org>
Tested-by: Khaled Hosny <khaledhosny at eglug.org>
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 9837a06..d694cf6 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -357,6 +357,8 @@ private:
// get kernign pairs of the current font
sal_uLong GetKernPairs();
+ void DrawTextLayout(const CommonSalLayout&, HDC);
+
public:
static sal_uLong GetTable( const char pTagName[5], const unsigned char*&, void*&, IDWriteFontFace*& );
// public SalGraphics methods, the interface to the independent vcl part
diff --git a/vcl/win/gdi/winlayout.cxx b/vcl/win/gdi/winlayout.cxx
index 8c16b9d..476248e 100644
--- a/vcl/win/gdi/winlayout.cxx
+++ b/vcl/win/gdi/winlayout.cxx
@@ -4004,10 +4004,8 @@ LogicalFontInstance* WinFontFace::CreateFontInstance( FontSelectPattern& rFSD )
return pFontInstance;
}
-void WinSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout)
+void WinSalGraphics::DrawTextLayout(const CommonSalLayout& rLayout, HDC hDC)
{
- HDC hDC = getHDC();
-
if (getenv("SAL_DWRITE_COMMON_LAYOUT"))
{
Point aPos(0, 0);
@@ -4032,4 +4030,88 @@ void WinSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout)
}
}
+void WinSalGraphics::DrawSalLayout(const CommonSalLayout& rLayout)
+{
+ HDC hDC = getHDC();
+ bool bUseOpenGL = OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter;
+ if (!bUseOpenGL)
+ {
+ // no OpenGL, just classic rendering
+ DrawTextLayout(rLayout, hDC);
+ }
+ else
+ {
+ // We have to render the text to a hidden texture, and draw it.
+ //
+ // Note that Windows GDI does not really support the alpha correctly
+ // when drawing - ie. it draws nothing to the alpha channel when
+ // rendering the text, even the antialiasing is done as 'real' pixels,
+ // not alpha...
+ //
+ // Luckily, this does not really limit us:
+ //
+ // To blend properly, we draw the texture, but then use it as an alpha
+ // channel for solid color (that will define the text color). This
+ // destroys the subpixel antialiasing - turns it into 'classic'
+ // antialiasing - but that is the best we can do, because the subpixel
+ // antialiasing needs to know what is in the background: When the
+ // background is white, or white-ish, it does the subpixel, but when
+ // there is a color, it just darkens the color (and does this even
+ // when part of the character is on a colored background, and part on
+ // white). It has to work this way, the results would look strange
+ // otherwise.
+ //
+ // For the GL rendering to work even with the subpixel antialiasing,
+ // we would need to get the current texture from the screen, let GDI
+ // draw the text to it (so that it can decide well where to use the
+ // subpixel and where not), and draw the result - but in that case we
+ // don't need alpha anyway.
+ //
+ // TODO: check the performance of this 2nd approach at some stage and
+ // switch to that if it performs well.
+
+ Rectangle aRect;
+ rLayout.GetBoundRect(*this, aRect);
+
+ WinOpenGLSalGraphicsImpl *pImpl = dynamic_cast<WinOpenGLSalGraphicsImpl*>(mpImpl.get());
+
+ if (pImpl)
+ {
+ pImpl->PreDraw();
+
+ OpenGLCompatibleDC aDC(*this, aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight());
+
+ // we are making changes to the DC, make sure we got a new one
+ assert(aDC.getCompatibleHDC() != hDC);
+
+ RECT aWinRect = { aRect.Left(), aRect.Top(), aRect.Left() + aRect.GetWidth(), aRect.Top() + aRect.GetHeight() };
+ ::FillRect(aDC.getCompatibleHDC(), &aWinRect, static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH)));
+
+ // 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)));
+
+ ::SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0));
+ ::SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255));
+
+ UINT nTextAlign = ::GetTextAlign(hDC);
+ ::SetTextAlign(aDC.getCompatibleHDC(), nTextAlign);
+
+ COLORREF color = ::GetTextColor(hDC);
+ SalColor salColor = MAKE_SALCOLOR(GetRValue(color), GetGValue(color), GetBValue(color));
+
+ // the actual drawing
+ DrawTextLayout(rLayout, aDC.getCompatibleHDC());
+
+ std::unique_ptr<OpenGLTexture> xTexture(aDC.getTexture());
+ if (xTexture)
+ pImpl->DrawMask(*xTexture, salColor, aDC.getTwoRect());
+
+ ::SelectFont(aDC.getCompatibleHDC(), hOrigFont);
+
+ pImpl->PostDraw();
+ }
+ }
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
More information about the Libreoffice-commits
mailing list