[Libreoffice-commits] core.git: Branch 'libreoffice-5-1' - vcl/win

Tor Lillqvist tml at collabora.com
Fri Dec 18 05:18:56 PST 2015


 vcl/win/source/gdi/winlayout.cxx |   79 ++++++++++++++++++++++++---------------
 vcl/win/source/gdi/winlayout.hxx |    6 +-
 2 files changed, 52 insertions(+), 33 deletions(-)

New commits:
commit ac04051a3565bb5cde904da9a84b6e22443cf8b5
Author: Tor Lillqvist <tml at collabora.com>
Date:   Fri Dec 18 14:38:27 2015 +0200

    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)

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 7c57366..cef4f8a 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 db09d1e..ff4e5cc 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;
 


More information about the Libreoffice-commits mailing list