[Libreoffice-commits] core.git: Branch 'libreoffice-5-0' - vcl/inc vcl/source

Miklos Vajna vmiklos at collabora.co.uk
Fri Aug 7 08:28:16 PDT 2015


 vcl/inc/window.h             |   20 ++++
 vcl/source/outdev/rect.cxx   |    2 
 vcl/source/window/cursor.cxx |    9 +
 vcl/source/window/paint.cxx  |  215 +++++++++++++++++++++++--------------------
 4 files changed, 146 insertions(+), 100 deletions(-)

New commits:
commit ec5da2f76adbfeaf1cebc6fb0e0dea08a7bdfe79
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Fri Aug 7 16:35:11 2015 +0200

    Resolves: tdf#92982 vcl rendercontext: handle buffered paint of vcl::Cursor
    
    Instead of painting on the vcl::Window directly, take a
    PaintBufferGuard, and use the vcl::RenderContext of it, that may be
    either the vcl::Window or the toplevel frame's buffer.
    
    Trigger the paint of the buffer by informing the guard what area was
    painted. In case of direct painting, both the ctor and the dtor of the
    guard is a NOP.
    
    This means that finally we can also assert Invert() calls on the output
    device, so that direct paint can't happen when double-buffering.
    
    Also:
    
    - make PaintBufferGuard visible outside paint.cxx
    - move buffer paint logic to PaintBufferGuard
    
    (cherry picked from commits c85b25114a756e1abb3e68a4c7d3630c486917b5,
    a6c7a0bf105c399d087e2d9f843dbd9b175fdf42 and
    c64a7ce1fcd1e30956a77530d0b76ad493841024)
    
    Change-Id: I0322563369dc63b3c49061cbe7c4a911cb13a2e2
    Reviewed-on: https://gerrit.libreoffice.org/17576
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Jenkins <ci at libreoffice.org>

diff --git a/vcl/inc/window.h b/vcl/inc/window.h
index 60f9b1a..213e215 100644
--- a/vcl/inc/window.h
+++ b/vcl/inc/window.h
@@ -378,6 +378,26 @@ public:
     ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > mxDNDListenerContainer;
 };
 
+/// Sets up the buffer to have settings matching the window, and restores the original state in the dtor.
+class PaintBufferGuard
+{
+    ImplFrameData* mpFrameData;
+    VclPtr<vcl::Window> m_pWindow;
+    bool mbBackground;
+    Wallpaper maBackground;
+    AllSettings maSettings;
+    long mnOutOffX;
+    long mnOutOffY;
+    Rectangle m_aPaintRect;
+public:
+    PaintBufferGuard(ImplFrameData* pFrameData, vcl::Window* pWindow);
+    ~PaintBufferGuard();
+    /// If this is called, then the dtor will also copy rRectangle to the window from the buffer, before restoring the state.
+    void SetPaintRect(const Rectangle& rRectangle);
+    /// Returns either the frame's buffer or the window, in case of no buffering.
+    vcl::RenderContext* GetRenderContext();
+};
+
 // helper methods
 
 bool ImplHandleMouseEvent( vcl::Window* pWindow, MouseNotifyEvent nSVEvent, bool bMouseLeave,
diff --git a/vcl/source/outdev/rect.cxx b/vcl/source/outdev/rect.cxx
index dfa491a..03afdf9 100644
--- a/vcl/source/outdev/rect.cxx
+++ b/vcl/source/outdev/rect.cxx
@@ -131,6 +131,7 @@ void OutputDevice::DrawRect( const Rectangle& rRect,
 
 void OutputDevice::Invert( const Rectangle& rRect, sal_uInt16 nFlags )
 {
+    assert(!is_double_buffered_window());
     if ( !IsDeviceOutputNecessary() )
         return;
 
@@ -163,6 +164,7 @@ void OutputDevice::Invert( const Rectangle& rRect, sal_uInt16 nFlags )
 
 void OutputDevice::Invert( const Polygon& rPoly, sal_uInt16 nFlags )
 {
+    assert(!is_double_buffered_window());
     if ( !IsDeviceOutputNecessary() )
         return;
 
diff --git a/vcl/source/window/cursor.cxx b/vcl/source/window/cursor.cxx
index 0bcad80..1968a26 100644
--- a/vcl/source/window/cursor.cxx
+++ b/vcl/source/window/cursor.cxx
@@ -44,7 +44,9 @@ struct ImplCursorData
 static void ImplCursorInvert( ImplCursorData* pData )
 {
     vcl::Window* pWindow  = pData->mpWindow;
-    vcl::RenderContext* pRenderContext = pWindow->GetOutDev();
+    PaintBufferGuard aGuard(pWindow->ImplGetWindowImpl()->mpFrameData, pWindow);
+    vcl::RenderContext* pRenderContext = aGuard.GetRenderContext();
+    Rectangle aPaintRect;
     bool    bMapMode = pRenderContext->IsMapModeEnabled();
     pRenderContext->EnableMapMode( false );
     sal_uInt16 nInvertStyle;
@@ -109,11 +111,16 @@ static void ImplCursorInvert( ImplCursorData* pData )
             if ( pData->mnOrientation )
                 aPoly.Rotate( pData->maPixRotOff, pData->mnOrientation );
             pRenderContext->Invert( aPoly, nInvertStyle );
+            aPaintRect = aPoly.GetBoundRect();
         }
     }
     else
+    {
         pRenderContext->Invert( aRect, nInvertStyle );
+        aPaintRect = aRect;
+    }
     pRenderContext->EnableMapMode( bMapMode );
+    aGuard.SetPaintRect(pRenderContext->PixelToLogic(aPaintRect));
 }
 
 void vcl::Cursor::ImplDraw()
diff --git a/vcl/source/window/paint.cxx b/vcl/source/window/paint.cxx
index 81f601d..19f5cdc 100644
--- a/vcl/source/window/paint.cxx
+++ b/vcl/source/window/paint.cxx
@@ -40,87 +40,124 @@
 #define IMPL_PAINT_ERASE            ((sal_uInt16)0x0010)
 #define IMPL_PAINT_CHECKRTL         ((sal_uInt16)0x0020)
 
-/// Sets up the buffer to have settings matching the window, and restore the original state in the dtor.
-class PaintBufferGuard
+// PaintBufferGuard
+
+PaintBufferGuard::PaintBufferGuard(ImplFrameData* pFrameData, vcl::Window* pWindow)
+    : mpFrameData(pFrameData),
+    m_pWindow(pWindow),
+    mbBackground(false),
+    mnOutOffX(0),
+    mnOutOffY(0)
 {
-    ImplFrameData* mpFrameData;
-    bool mbBackground;
-    Wallpaper maBackground;
-    AllSettings maSettings;
-    long mnOutOffX;
-    long mnOutOffY;
-public:
-    PaintBufferGuard(ImplFrameData* pFrameData, vcl::Window* pWindow)
-        : mpFrameData(pFrameData),
-        mbBackground(false),
-        mnOutOffX(0),
-        mnOutOffY(0)
-    {
-        // transfer various settings
-        // FIXME: this must disappear as we move to RenderContext only,
-        // the painting must become state-less, so that no actual
-        // vcl::Window setting affects this
-        mbBackground = pFrameData->mpBuffer->IsBackground();
-        if (pWindow->IsBackground())
+    if (!pFrameData->mpBuffer)
+        return;
+
+    // transfer various settings
+    // FIXME: this must disappear as we move to RenderContext only,
+    // the painting must become state-less, so that no actual
+    // vcl::Window setting affects this
+    mbBackground = pFrameData->mpBuffer->IsBackground();
+    if (pWindow->IsBackground())
+    {
+        maBackground = pFrameData->mpBuffer->GetBackground();
+        pFrameData->mpBuffer->SetBackground(pWindow->GetBackground());
+    }
+    //else
+        //SAL_WARN("vcl.doublebuffering", "the root of the double-buffering hierarchy should not have a transparent background");
+
+    PushFlags nFlags = PushFlags::NONE;
+    nFlags |= PushFlags::CLIPREGION;
+    nFlags |= PushFlags::FILLCOLOR;
+    nFlags |= PushFlags::FONT;
+    nFlags |= PushFlags::LINECOLOR;
+    nFlags |= PushFlags::MAPMODE;
+    maSettings = pFrameData->mpBuffer->GetSettings();
+    nFlags |= PushFlags::REFPOINT;
+    nFlags |= PushFlags::TEXTCOLOR;
+    nFlags |= PushFlags::TEXTLINECOLOR;
+    nFlags |= PushFlags::OVERLINECOLOR;
+    nFlags |= PushFlags::TEXTFILLCOLOR;
+    nFlags |= PushFlags::TEXTALIGN;
+    nFlags |= PushFlags::RASTEROP;
+    nFlags |= PushFlags::TEXTLAYOUTMODE;
+    nFlags |= PushFlags::TEXTLANGUAGE;
+    pFrameData->mpBuffer->Push(nFlags);
+    pFrameData->mpBuffer->SetClipRegion(pWindow->GetClipRegion());
+    pFrameData->mpBuffer->SetFillColor(pWindow->GetFillColor());
+    pFrameData->mpBuffer->SetFont(pWindow->GetFont());
+    pFrameData->mpBuffer->SetLineColor(pWindow->GetLineColor());
+    pFrameData->mpBuffer->SetMapMode(pWindow->GetMapMode());
+    pFrameData->mpBuffer->SetRefPoint(pWindow->GetRefPoint());
+    pFrameData->mpBuffer->SetSettings(pWindow->GetSettings());
+    pFrameData->mpBuffer->SetTextColor(pWindow->GetTextColor());
+    pFrameData->mpBuffer->SetTextLineColor(pWindow->GetTextLineColor());
+    pFrameData->mpBuffer->SetOverlineColor(pWindow->GetOverlineColor());
+    pFrameData->mpBuffer->SetTextFillColor(pWindow->GetTextFillColor());
+    pFrameData->mpBuffer->SetTextAlign(pWindow->GetTextAlign());
+    pFrameData->mpBuffer->SetRasterOp(pWindow->GetRasterOp());
+    pFrameData->mpBuffer->SetLayoutMode(pWindow->GetLayoutMode());
+    pFrameData->mpBuffer->SetDigitLanguage(pWindow->GetDigitLanguage());
+
+    mnOutOffX = pFrameData->mpBuffer->GetOutOffXPixel();
+    mnOutOffY = pFrameData->mpBuffer->GetOutOffYPixel();
+    pFrameData->mpBuffer->SetOutOffXPixel(pWindow->GetOutOffXPixel());
+    pFrameData->mpBuffer->SetOutOffYPixel(pWindow->GetOutOffYPixel());
+}
+
+PaintBufferGuard::~PaintBufferGuard()
+{
+    if (!mpFrameData->mpBuffer)
+        return;
+
+    if (!m_aPaintRect.IsEmpty())
+    {
+        // copy the buffer content to the actual window
+        // export VCL_DOUBLEBUFFERING_AVOID_PAINT=1 to see where we are
+        // painting directly instead of using Invalidate()
+        // [ie. everything you can see was painted directly to the
+        // window either above or in eg. an event handler]
+        if (!getenv("VCL_DOUBLEBUFFERING_AVOID_PAINT"))
         {
-            maBackground = pFrameData->mpBuffer->GetBackground();
-            pFrameData->mpBuffer->SetBackground(pWindow->GetBackground());
+            // Make sure that the +1 value GetSize() adds to the size is in pixels.
+            Size aPaintRectSize;
+            if (m_pWindow->GetMapMode().GetMapUnit() == MAP_PIXEL)
+            {
+                aPaintRectSize = m_aPaintRect.GetSize();
+            }
+            else
+            {
+                Rectangle aRectanglePixel = m_pWindow->LogicToPixel(m_aPaintRect);
+                aPaintRectSize = m_pWindow->PixelToLogic(aRectanglePixel.GetSize());
+            }
+
+            m_pWindow->DrawOutDev(m_aPaintRect.TopLeft(), aPaintRectSize, m_aPaintRect.TopLeft(), aPaintRectSize, *mpFrameData->mpBuffer.get());
         }
-        //else
-            //SAL_WARN("vcl.doublebuffering", "the root of the double-buffering hierarchy should not have a transparent background");
-
-        PushFlags nFlags = PushFlags::NONE;
-        nFlags |= PushFlags::CLIPREGION;
-        nFlags |= PushFlags::FILLCOLOR;
-        nFlags |= PushFlags::FONT;
-        nFlags |= PushFlags::LINECOLOR;
-        nFlags |= PushFlags::MAPMODE;
-        maSettings = pFrameData->mpBuffer->GetSettings();
-        nFlags |= PushFlags::REFPOINT;
-        nFlags |= PushFlags::TEXTCOLOR;
-        nFlags |= PushFlags::TEXTLINECOLOR;
-        nFlags |= PushFlags::OVERLINECOLOR;
-        nFlags |= PushFlags::TEXTFILLCOLOR;
-        nFlags |= PushFlags::TEXTALIGN;
-        nFlags |= PushFlags::RASTEROP;
-        nFlags |= PushFlags::TEXTLAYOUTMODE;
-        nFlags |= PushFlags::TEXTLANGUAGE;
-        pFrameData->mpBuffer->Push(nFlags);
-        pFrameData->mpBuffer->SetClipRegion(pWindow->GetClipRegion());
-        pFrameData->mpBuffer->SetFillColor(pWindow->GetFillColor());
-        pFrameData->mpBuffer->SetFont(pWindow->GetFont());
-        pFrameData->mpBuffer->SetLineColor(pWindow->GetLineColor());
-        pFrameData->mpBuffer->SetMapMode(pWindow->GetMapMode());
-        pFrameData->mpBuffer->SetRefPoint(pWindow->GetRefPoint());
-        pFrameData->mpBuffer->SetSettings(pWindow->GetSettings());
-        pFrameData->mpBuffer->SetTextColor(pWindow->GetTextColor());
-        pFrameData->mpBuffer->SetTextLineColor(pWindow->GetTextLineColor());
-        pFrameData->mpBuffer->SetOverlineColor(pWindow->GetOverlineColor());
-        pFrameData->mpBuffer->SetTextFillColor(pWindow->GetTextFillColor());
-        pFrameData->mpBuffer->SetTextAlign(pWindow->GetTextAlign());
-        pFrameData->mpBuffer->SetRasterOp(pWindow->GetRasterOp());
-        pFrameData->mpBuffer->SetLayoutMode(pWindow->GetLayoutMode());
-        pFrameData->mpBuffer->SetDigitLanguage(pWindow->GetDigitLanguage());
-
-        mnOutOffX = pFrameData->mpBuffer->GetOutOffXPixel();
-        mnOutOffY = pFrameData->mpBuffer->GetOutOffYPixel();
-        pFrameData->mpBuffer->SetOutOffXPixel(pWindow->GetOutOffXPixel());
-        pFrameData->mpBuffer->SetOutOffYPixel(pWindow->GetOutOffYPixel());
-    }
-    ~PaintBufferGuard()
-    {
-        // Restore buffer state.
-        mpFrameData->mpBuffer->SetOutOffXPixel(mnOutOffX);
-        mpFrameData->mpBuffer->SetOutOffYPixel(mnOutOffY);
-
-        mpFrameData->mpBuffer->Pop();
-        mpFrameData->mpBuffer->SetSettings(maSettings);
-        if (mbBackground)
-            mpFrameData->mpBuffer->SetBackground(maBackground);
-        else
-            mpFrameData->mpBuffer->SetBackground();
     }
-};
+
+    // Restore buffer state.
+    mpFrameData->mpBuffer->SetOutOffXPixel(mnOutOffX);
+    mpFrameData->mpBuffer->SetOutOffYPixel(mnOutOffY);
+
+    mpFrameData->mpBuffer->Pop();
+    mpFrameData->mpBuffer->SetSettings(maSettings);
+    if (mbBackground)
+        mpFrameData->mpBuffer->SetBackground(maBackground);
+    else
+        mpFrameData->mpBuffer->SetBackground();
+}
+
+void PaintBufferGuard::SetPaintRect(const Rectangle& rRectangle)
+{
+    m_aPaintRect = rRectangle;
+}
+
+vcl::RenderContext* PaintBufferGuard::GetRenderContext()
+{
+    if (mpFrameData->mpBuffer)
+        return mpFrameData->mpBuffer;
+    else
+        return m_pWindow;
+}
 
 class PaintHelper
 {
@@ -200,28 +237,8 @@ void PaintHelper::PaintBuffer()
     assert(pFrameData->mbInBufferedPaint);
     assert(m_bStartedBufferedPaint);
 
-    // copy the buffer content to the actual window
-    // export VCL_DOUBLEBUFFERING_AVOID_PAINT=1 to see where we are
-    // painting directly instead of using Invalidate()
-    // [ie. everything you can see was painted directly to the
-    // window either above or in eg. an event handler]
-    if (!getenv("VCL_DOUBLEBUFFERING_AVOID_PAINT"))
-    {
-        // Make sure that the +1 value GetSize() adds to the size is in pixels.
-        Size aPaintRectSize;
-        if (m_pWindow->GetMapMode().GetMapUnit() == MAP_PIXEL)
-        {
-            aPaintRectSize = m_aPaintRect.GetSize();
-        }
-        else
-        {
-            Rectangle aRectanglePixel = m_pWindow->LogicToPixel(m_aPaintRect);
-            aPaintRectSize = m_pWindow->PixelToLogic(aRectanglePixel.GetSize());
-        }
-
-        PaintBufferGuard g(pFrameData, m_pWindow);
-        m_pWindow->DrawOutDev(m_aPaintRect.TopLeft(), aPaintRectSize, m_aPaintRect.TopLeft(), aPaintRectSize, *pFrameData->mpBuffer.get());
-    }
+    PaintBufferGuard aGuard(pFrameData, m_pWindow);
+    aGuard.SetPaintRect(m_aPaintRect);
 }
 
 void PaintHelper::DoPaint(const vcl::Region* pRegion)


More information about the Libreoffice-commits mailing list