summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKhaled Hosny <khaledhosny@eglug.org>2016-10-21 03:01:43 +0200
committerKhaled Hosny <khaledhosny@eglug.org>2016-10-21 18:48:18 +0000
commit36bafd3d4ad7fa75649eeab0c9cd1b3d6f53d8e8 (patch)
tree658cf276fcedaa15123bc69af8f1523872cd9b73
parent59d6d5579528a66e55b75987d2d959968db485a8 (diff)
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@gmail.com> Reviewed-by: Khaled Hosny <khaledhosny@eglug.org> Tested-by: Khaled Hosny <khaledhosny@eglug.org>
-rw-r--r--vcl/inc/win/salgdi.h2
-rw-r--r--vcl/win/gdi/winlayout.cxx88
2 files changed, 87 insertions, 3 deletions
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 9837a067d7d0..d694cf66a367 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 8c16b9dcafd0..476248ee6ab1 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: */