3d17a22
From bc839c159d4ee94ef8ca08975cf65be37378ae04 Mon Sep 17 00:00:00 2001
3d17a22
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
3d17a22
Date: Thu, 11 Dec 2014 16:20:49 +0000
3d17a22
Subject: [PATCH] Related: fdo#87242 init VirtualDevice with size of surface
3d17a22
3d17a22
otherwise vcl's clipping doesn't work quite right when the render text
3d17a22
with vcl apis fallback is used.
3d17a22
3d17a22
Manually forced in my case, but it should happen in practice with vertical
3d17a22
text, so if there is a bug about vertical text not appearing in slideshows then
3d17a22
this is part of the fix for that.
3d17a22
3d17a22
Windows and Mac remain unchanged as initialized with 1, 1. If the same problem
3d17a22
affects those platforms then they'll need to be adjusted to remember their
3d17a22
height/widths from the ctor and those values plugged in here instead
3d17a22
3d17a22
(cherry picked from commit f95b0743da4239e047db8638c61f90f8bbe54306)
3d17a22
(cherry picked from commit e2be2c23c1ad61b3bd640be6f16d66f5cd925d38)
3d17a22
3d17a22
Conflicts:
3d17a22
	desktop/source/lib/init.cxx
3d17a22
3d17a22
Related: fdo#87242 merge duplicate clip setup code
3d17a22
3d17a22
favoring the vclcanvas one for the places where
3d17a22
they diverge
3d17a22
3d17a22
(cherry picked from commit f88b5ab8692ee7ecf58b570e703d0e7f10cc2f0d)
3d17a22
(cherry picked from commit e0e96579ce3a248ee5d3b07ecf90f38e2020c555)
3d17a22
3d17a22
Conflicts:
3d17a22
	canvas/source/cairo/cairo_canvashelper_text.cxx
3d17a22
	canvas/source/vcl/canvashelper.cxx
3d17a22
3d17a22
Resolves: fdo#87242 reuse vcl clip for cairo during animations
3d17a22
3d17a22
(cherry picked from commit 94d935eecbba0161de2616c2234b4a5d9d3cad88)
3d17a22
(cherry picked from commit 3a108b0600ce61f7960d561cee9989ab3a48780f)
3d17a22
3d17a22
stray debugging code
3d17a22
3d17a22
(cherry picked from commit 067b560335195b24eeedc4514956029ea975fbbf)
3d17a22
(cherry picked from commit fafc85559097166eceb67c4db4528cc9977e4184)
3d17a22
3d17a22
Change-Id: I2f82f0db0cf446d7db21f0a7ee4f8c15c7ebdb42
3d17a22
18e3d4e7659ebd4cb90c86718c1b1035671b4be3
3d17a22
0a26d4c4092226732620c3852b0402ee45d4fa1d
3d17a22
953389e236739c01226365c33ab777fc3972b69d
3d17a22
---
3d17a22
 canvas/source/cairo/cairo_canvashelper.hxx      |   3 +
3d17a22
 canvas/source/cairo/cairo_canvashelper_text.cxx | 117 ++++++++++--------------
3d17a22
 canvas/source/cairo/cairo_quartz_cairo.cxx      |   2 +-
3d17a22
 canvas/source/cairo/cairo_win32_cairo.cxx       |   2 +-
3d17a22
 canvas/source/cairo/cairo_xlib_cairo.cxx        |   7 +-
3d17a22
 canvas/source/tools/canvastools.cxx             |  75 +++++++++++++++
3d17a22
 canvas/source/vcl/canvashelper.cxx              |  79 +---------------
3d17a22
 include/canvas/canvastools.hxx                  |   6 ++
3d17a22
 include/vcl/virdev.hxx                          |   3 +-
3d17a22
 vcl/source/gdi/virdev.cxx                       |   6 +-
3d17a22
 10 files changed, 147 insertions(+), 153 deletions(-)
3d17a22
3d17a22
diff --git a/canvas/source/cairo/cairo_canvashelper.hxx b/canvas/source/cairo/cairo_canvashelper.hxx
3d17a22
index 9258e7c..ccb03ac 100644
3d17a22
--- a/canvas/source/cairo/cairo_canvashelper.hxx
3d17a22
+++ b/canvas/source/cairo/cairo_canvashelper.hxx
3d17a22
@@ -310,6 +310,9 @@ namespace cairocanvas
3d17a22
         ::cairo::CairoSharedPtr     mpCairo;
3d17a22
         ::cairo::SurfaceSharedPtr   mpSurface;
3d17a22
         ::basegfx::B2ISize maSize;
3d17a22
+
3d17a22
+        void clip_cairo_from_dev(::OutputDevice& rOutDev);
3d17a22
+
3d17a22
     };
3d17a22
 
3d17a22
     /// also needed from SpriteHelper
3d17a22
diff --git a/canvas/source/cairo/cairo_canvashelper_text.cxx b/canvas/source/cairo/cairo_canvashelper_text.cxx
3d17a22
index d65f2de..78a2ddf 100644
3d17a22
--- a/canvas/source/cairo/cairo_canvashelper_text.cxx
3d17a22
+++ b/canvas/source/cairo/cairo_canvashelper_text.cxx
3d17a22
@@ -127,73 +127,7 @@ namespace cairocanvas
3d17a22
 
3d17a22
         // TODO(P2): Don't change clipping all the time, maintain current clip
3d17a22
         // state and change only when update is necessary
3d17a22
-
3d17a22
-        // accumulate non-empty clips into one region
3d17a22
-        // ==========================================
3d17a22
-
3d17a22
-        Region aClipRegion;
3d17a22
-
3d17a22
-        if( viewState.Clip.is() )
3d17a22
-        {
3d17a22
-            ::basegfx::B2DPolyPolygon aClipPoly(
3d17a22
-                ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
3d17a22
-                    viewState.Clip) );
3d17a22
-
3d17a22
-            if( aClipPoly.count() )
3d17a22
-            {
3d17a22
-                // setup non-empty clipping
3d17a22
-                ::basegfx::B2DHomMatrix aMatrix;
3d17a22
-                aClipPoly.transform(
3d17a22
-                    ::basegfx::unotools::homMatrixFromAffineMatrix( aMatrix,
3d17a22
-                                                                    viewState.AffineTransform ) );
3d17a22
-
3d17a22
-                aClipRegion = Region::GetRegionFromPolyPolygon( ::PolyPolygon( aClipPoly ) );
3d17a22
-            }
3d17a22
-        }
3d17a22
-
3d17a22
-        if( renderState.Clip.is() )
3d17a22
-        {
3d17a22
-            ::basegfx::B2DPolyPolygon aClipPoly(
3d17a22
-                ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
3d17a22
-                    renderState.Clip) );
3d17a22
-
3d17a22
-            ::basegfx::B2DHomMatrix aMatrix;
3d17a22
-            aClipPoly.transform(
3d17a22
-                ::canvas::tools::mergeViewAndRenderTransform( aMatrix,
3d17a22
-                                                              viewState,
3d17a22
-                                                              renderState ) );
3d17a22
-
3d17a22
-            if( aClipPoly.count() )
3d17a22
-            {
3d17a22
-                // setup non-empty clipping
3d17a22
-                Region aRegion = Region::GetRegionFromPolyPolygon( ::PolyPolygon( aClipPoly ) );
3d17a22
-
3d17a22
-                if( aClipRegion.IsEmpty() )
3d17a22
-                    aClipRegion = aRegion;
3d17a22
-                else
3d17a22
-                    aClipRegion.Intersect( aRegion );
3d17a22
-            }
3d17a22
-            else
3d17a22
-            {
3d17a22
-                // clip polygon is empty
3d17a22
-                aClipRegion.SetEmpty();
3d17a22
-            }
3d17a22
-        }
3d17a22
-
3d17a22
-        // setup accumulated clip region. Note that setting an
3d17a22
-        // empty clip region denotes "clip everything" on the
3d17a22
-        // OutputDevice (which is why we translate that into
3d17a22
-        // SetClipRegion() here). When both view and render clip
3d17a22
-        // are empty, aClipRegion remains default-constructed,
3d17a22
-        // i.e. empty, too.
3d17a22
-        if( aClipRegion.IsEmpty() )
3d17a22
-        {
3d17a22
-            rOutDev.SetClipRegion();
3d17a22
-        }
3d17a22
-        else
3d17a22
-        {
3d17a22
-            rOutDev.SetClipRegion( aClipRegion );
3d17a22
-        }
3d17a22
+        ::canvas::tools::clipOutDev(viewState, renderState, rOutDev);
3d17a22
 
3d17a22
         if( eColorType != IGNORE_COLOR )
3d17a22
         {
3d17a22
@@ -238,6 +172,31 @@ namespace cairocanvas
3d17a22
         return nTransparency;
3d17a22
     }
3d17a22
 
3d17a22
+    class DeviceSettingsGuard
3d17a22
+    {
3d17a22
+    private:
3d17a22
+        OutputDevice *mpVirtualDevice;
3d17a22
+        cairo_t *mpCairo;
3d17a22
+        bool mbMappingWasEnabled;
3d17a22
+    public:
3d17a22
+        DeviceSettingsGuard(OutputDevice *pVirtualDevice, cairo_t *pCairo)
3d17a22
+            : mpVirtualDevice(pVirtualDevice)
3d17a22
+            , mpCairo(pCairo)
3d17a22
+            , mbMappingWasEnabled(mpVirtualDevice->IsMapModeEnabled())
3d17a22
+        {
3d17a22
+            cairo_save(mpCairo);
3d17a22
+            mpVirtualDevice->Push();
3d17a22
+            mpVirtualDevice->EnableMapMode(false);
3d17a22
+        }
3d17a22
+
3d17a22
+        ~DeviceSettingsGuard()
3d17a22
+        {
3d17a22
+            mpVirtualDevice->EnableMapMode(mbMappingWasEnabled);
3d17a22
+            mpVirtualDevice->Pop();
3d17a22
+            cairo_restore(mpCairo);
3d17a22
+        }
3d17a22
+    };
3d17a22
+
3d17a22
     bool setupTextOutput( OutputDevice&                                     rOutDev,
3d17a22
                           const rendering::XCanvas*                         pOwner,
3d17a22
                           ::Point&                                          o_rOutPos,
3d17a22
@@ -247,14 +206,12 @@ namespace cairocanvas
3d17a22
     {
3d17a22
         setupOutDevState( rOutDev, pOwner, viewState, renderState, TEXT_COLOR );
3d17a22
 
3d17a22
-        ::Font aVCLFont;
3d17a22
-
3d17a22
         CanvasFont* pFont = dynamic_cast< CanvasFont* >( xFont.get() );
3d17a22
 
3d17a22
         ENSURE_ARG_OR_THROW( pFont,
3d17a22
                          "CanvasHelper::setupTextOutput(): Font not compatible with this canvas" );
3d17a22
 
3d17a22
-        aVCLFont = pFont->getVCLFont();
3d17a22
+        ::Font aVCLFont = pFont->getVCLFont();
3d17a22
 
3d17a22
         Color aColor( COL_BLACK );
3d17a22
 
3d17a22
@@ -273,10 +230,20 @@ namespace cairocanvas
3d17a22
 
3d17a22
         rOutDev.SetFont( aVCLFont );
3d17a22
 
3d17a22
-
3d17a22
         return true;
3d17a22
     }
3d17a22
 
3d17a22
+    //set the clip of the rOutDev to the cairo surface
3d17a22
+    void CanvasHelper::clip_cairo_from_dev(::OutputDevice& rOutDev)
3d17a22
+    {
3d17a22
+        Region aRegion(rOutDev.GetClipRegion());
3d17a22
+        if (!aRegion.IsEmpty() && !aRegion.IsNull())
3d17a22
+        {
3d17a22
+            doPolyPolygonImplementation(aRegion.GetAsB2DPolyPolygon(), Clip, mpCairo.get(),
3d17a22
+                                        NULL, mpSurfaceProvider, rendering::FillRule_EVEN_ODD);
3d17a22
+        }
3d17a22
+    }
3d17a22
+
3d17a22
     uno::Reference< rendering::XCachedPrimitive > CanvasHelper::drawText( const rendering::XCanvas*                         pOwner,
3d17a22
                                                                           const rendering::StringContext&                   text,
3d17a22
                                                                           const uno::Reference< rendering::XCanvasFont >&   xFont,
3d17a22
@@ -297,6 +264,8 @@ namespace cairocanvas
3d17a22
 
3d17a22
         if( mpVirtualDevice )
3d17a22
         {
3d17a22
+            DeviceSettingsGuard aGuard(mpVirtualDevice.get(), mpCairo.get());
3d17a22
+
3d17a22
 #if defined CAIRO_HAS_WIN32_SURFACE
3d17a22
             // FIXME: Some kind of work-araound...
3d17a22
             cairo_rectangle (mpSurface->getCairo().get(), 0, 0, 0, 0);
3d17a22
@@ -330,6 +299,8 @@ namespace cairocanvas
3d17a22
             // TODO(F2): alpha
3d17a22
             mpVirtualDevice->SetLayoutMode( nLayoutMode );
3d17a22
 
3d17a22
+            clip_cairo_from_dev(*mpVirtualDevice);
3d17a22
+
3d17a22
             OSL_TRACE(":cairocanvas::CanvasHelper::drawText(O,t,f,v,r,d): %s", OUStringToOString( text.Text.copy( text.StartPosition, text.Length ),
3d17a22
                                                                                                          RTL_TEXTENCODING_UTF8 ).getStr());
3d17a22
 
3d17a22
@@ -357,6 +328,8 @@ namespace cairocanvas
3d17a22
 
3d17a22
             if( mpVirtualDevice )
3d17a22
             {
3d17a22
+                DeviceSettingsGuard aGuard(mpVirtualDevice.get(), mpCairo.get());
3d17a22
+
3d17a22
 #if defined CAIRO_HAS_WIN32_SURFACE
3d17a22
                 // FIXME: Some kind of work-araound...
3d17a22
                 cairo_rectangle( mpSurface->getCairo().get(), 0, 0, 0, 0);
3d17a22
@@ -371,6 +344,8 @@ namespace cairocanvas
3d17a22
                 if( !setupTextOutput( *mpVirtualDevice, pOwner, aOutpos, viewState, renderState, xLayoutedText->getFont() ) )
3d17a22
                     return uno::Reference< rendering::XCachedPrimitive >(NULL); // no output necessary
3d17a22
 
3d17a22
+                clip_cairo_from_dev(*mpVirtualDevice);
3d17a22
+
3d17a22
                 // TODO(F2): What about the offset scalings?
3d17a22
                 pTextLayout->draw( mpSurface, *mpVirtualDevice, aOutpos, viewState, renderState );
3d17a22
             }
3d17a22
diff --git a/canvas/source/cairo/cairo_quartz_cairo.cxx b/canvas/source/cairo/cairo_quartz_cairo.cxx
3d17a22
index 07951ee..6b8b9aa 100644
3d17a22
--- a/canvas/source/cairo/cairo_quartz_cairo.cxx
3d17a22
+++ b/canvas/source/cairo/cairo_quartz_cairo.cxx
3d17a22
@@ -269,7 +269,7 @@ namespace cairo
3d17a22
         aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
3d17a22
         aSystemGraphicsData.rCGContext = getCGContext();
3d17a22
         return boost::shared_ptr<VirtualDevice>(
3d17a22
-            new VirtualDevice( &aSystemGraphicsData, getDepth() ));
3d17a22
+            new VirtualDevice( &aSystemGraphicsData, Size(1, 1), getDepth() ));
3d17a22
     }
3d17a22
 
3d17a22
     /**
3d17a22
diff --git a/canvas/source/cairo/cairo_win32_cairo.cxx b/canvas/source/cairo/cairo_win32_cairo.cxx
3d17a22
index a70add9..8d53b4f 100644
3d17a22
--- a/canvas/source/cairo/cairo_win32_cairo.cxx
3d17a22
+++ b/canvas/source/cairo/cairo_win32_cairo.cxx
3d17a22
@@ -197,7 +197,7 @@ namespace cairo
3d17a22
         aSystemGraphicsData.hDC = cairo_win32_surface_get_dc( mpSurface.get() );
3d17a22
 
3d17a22
         return boost::shared_ptr<VirtualDevice>(
3d17a22
-            new VirtualDevice( &aSystemGraphicsData, sal::static_int_cast<USHORT>(getDepth()) ));
3d17a22
+            new VirtualDevice( &aSystemGraphicsData, Size(1, 1), sal::static_int_cast<USHORT>(getDepth()) ));
3d17a22
     }
3d17a22
 
3d17a22
 
3d17a22
diff --git a/canvas/source/cairo/cairo_xlib_cairo.cxx b/canvas/source/cairo/cairo_xlib_cairo.cxx
3d17a22
index 9b49c7e..79ab2a5 100644
3d17a22
--- a/canvas/source/cairo/cairo_xlib_cairo.cxx
3d17a22
+++ b/canvas/source/cairo/cairo_xlib_cairo.cxx
3d17a22
@@ -277,8 +277,13 @@ namespace cairo
3d17a22
         aSystemGraphicsData.hDrawable = getDrawable();
3d17a22
         aSystemGraphicsData.pXRenderFormat = getRenderFormat();
3d17a22
 
3d17a22
+        int width = cairo_xlib_surface_get_width(mpSurface.get());
3d17a22
+        int height = cairo_xlib_surface_get_height(mpSurface.get());
3d17a22
+
3d17a22
         return boost::shared_ptr<VirtualDevice>(
3d17a22
-            new VirtualDevice( &aSystemGraphicsData, std::max( getDepth(), 0 ) ));
3d17a22
+            new VirtualDevice(&aSystemGraphicsData,
3d17a22
+                              Size(width, height),
3d17a22
+                              std::max(getDepth(), 0)));
3d17a22
     }
3d17a22
 
3d17a22
     /**
3d17a22
diff --git a/canvas/source/tools/canvastools.cxx b/canvas/source/tools/canvastools.cxx
3d17a22
index ae79cc9..6698f58 100644
3d17a22
--- a/canvas/source/tools/canvastools.cxx
3d17a22
+++ b/canvas/source/tools/canvastools.cxx
3d17a22
@@ -1290,6 +1290,81 @@ namespace canvas
3d17a22
                                    nColorSteps ) );
3d17a22
         }
3d17a22
 
3d17a22
+        void clipOutDev(const rendering::ViewState& viewState,
3d17a22
+                        const rendering::RenderState& renderState,
3d17a22
+                        OutputDevice& rOutDev,
3d17a22
+                        OutputDevice* p2ndOutDev)
3d17a22
+        {
3d17a22
+            // accumulate non-empty clips into one region
3d17a22
+            Region aClipRegion(true);
3d17a22
+
3d17a22
+            if( viewState.Clip.is() )
3d17a22
+            {
3d17a22
+                ::basegfx::B2DPolyPolygon aClipPoly(
3d17a22
+                    ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(viewState.Clip) );
3d17a22
+
3d17a22
+                if( aClipPoly.count() )
3d17a22
+                {
3d17a22
+                    // setup non-empty clipping
3d17a22
+                    ::basegfx::B2DHomMatrix aMatrix;
3d17a22
+                    aClipPoly.transform(
3d17a22
+                        ::basegfx::unotools::homMatrixFromAffineMatrix( aMatrix,
3d17a22
+                                                                        viewState.AffineTransform ) );
3d17a22
+
3d17a22
+                    aClipRegion = Region::GetRegionFromPolyPolygon( PolyPolygon( aClipPoly ) );
3d17a22
+                }
3d17a22
+                else
3d17a22
+                {
3d17a22
+                    // clip polygon is empty
3d17a22
+                    aClipRegion.SetEmpty();
3d17a22
+                }
3d17a22
+            }
3d17a22
+
3d17a22
+            if( renderState.Clip.is() )
3d17a22
+            {
3d17a22
+                ::basegfx::B2DPolyPolygon aClipPoly(
3d17a22
+                    ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(renderState.Clip) );
3d17a22
+
3d17a22
+                ::basegfx::B2DHomMatrix aMatrix;
3d17a22
+                aClipPoly.transform(
3d17a22
+                    ::canvas::tools::mergeViewAndRenderTransform( aMatrix,
3d17a22
+                                                                  viewState,
3d17a22
+                                                                  renderState ) );
3d17a22
+
3d17a22
+                if( aClipPoly.count() )
3d17a22
+                {
3d17a22
+                    // setup non-empty clipping
3d17a22
+                    Region aRegion = Region::GetRegionFromPolyPolygon( PolyPolygon( aClipPoly ) );
3d17a22
+                    aClipRegion.Intersect( aRegion );
3d17a22
+                }
3d17a22
+                else
3d17a22
+                {
3d17a22
+                    // clip polygon is empty
3d17a22
+                    aClipRegion.SetEmpty();
3d17a22
+                }
3d17a22
+            }
3d17a22
+
3d17a22
+            // setup accumulated clip region. Note that setting an
3d17a22
+            // empty clip region denotes "clip everything" on the
3d17a22
+            // OutputDevice (which is why we translate that into
3d17a22
+            // SetClipRegion() here). When both view and render clip
3d17a22
+            // are empty, aClipRegion remains default-constructed,
3d17a22
+            // i.e. empty, too.
3d17a22
+            if( aClipRegion.IsNull() )
3d17a22
+            {
3d17a22
+                rOutDev.SetClipRegion();
3d17a22
+
3d17a22
+                if( p2ndOutDev )
3d17a22
+                    p2ndOutDev->SetClipRegion();
3d17a22
+            }
3d17a22
+            else
3d17a22
+            {
3d17a22
+                rOutDev.SetClipRegion( aClipRegion );
3d17a22
+
3d17a22
+                if( p2ndOutDev )
3d17a22
+                    p2ndOutDev->SetClipRegion( aClipRegion );
3d17a22
+            }
3d17a22
+        }
3d17a22
     } // namespace tools
3d17a22
 
3d17a22
 } // namespace canvas
3d17a22
diff --git a/canvas/source/vcl/canvashelper.cxx b/canvas/source/vcl/canvashelper.cxx
3d17a22
index 0bd3954..5424e9e 100644
3d17a22
--- a/canvas/source/vcl/canvashelper.cxx
3d17a22
+++ b/canvas/source/vcl/canvashelper.cxx
3d17a22
@@ -1236,78 +1236,7 @@ namespace vclcanvas
3d17a22
 
3d17a22
         // TODO(P2): Don't change clipping all the time, maintain current clip
3d17a22
         // state and change only when update is necessary
3d17a22
-
3d17a22
-        // accumulate non-empty clips into one region
3d17a22
-        // ==========================================
3d17a22
-
3d17a22
-        Region aClipRegion(true);
3d17a22
-
3d17a22
-        if( viewState.Clip.is() )
3d17a22
-        {
3d17a22
-            ::basegfx::B2DPolyPolygon aClipPoly(
3d17a22
-                ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(viewState.Clip) );
3d17a22
-
3d17a22
-            if( aClipPoly.count() )
3d17a22
-            {
3d17a22
-                // setup non-empty clipping
3d17a22
-                ::basegfx::B2DHomMatrix aMatrix;
3d17a22
-                aClipPoly.transform(
3d17a22
-                    ::basegfx::unotools::homMatrixFromAffineMatrix( aMatrix,
3d17a22
-                                                                    viewState.AffineTransform ) );
3d17a22
-
3d17a22
-                aClipRegion = Region::GetRegionFromPolyPolygon( ::PolyPolygon( aClipPoly ) );
3d17a22
-            }
3d17a22
-            else
3d17a22
-            {
3d17a22
-                // clip polygon is empty
3d17a22
-                aClipRegion.SetEmpty();
3d17a22
-            }
3d17a22
-        }
3d17a22
-
3d17a22
-        if( renderState.Clip.is() )
3d17a22
-        {
3d17a22
-            ::basegfx::B2DPolyPolygon aClipPoly(
3d17a22
-                ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(renderState.Clip) );
3d17a22
-
3d17a22
-            ::basegfx::B2DHomMatrix aMatrix;
3d17a22
-            aClipPoly.transform(
3d17a22
-                ::canvas::tools::mergeViewAndRenderTransform( aMatrix,
3d17a22
-                                                              viewState,
3d17a22
-                                                              renderState ) );
3d17a22
-
3d17a22
-            if( aClipPoly.count() )
3d17a22
-            {
3d17a22
-                // setup non-empty clipping
3d17a22
-                Region aRegion = Region::GetRegionFromPolyPolygon( ::PolyPolygon( aClipPoly ) );
3d17a22
-                aClipRegion.Intersect( aRegion );
3d17a22
-            }
3d17a22
-            else
3d17a22
-            {
3d17a22
-                // clip polygon is empty
3d17a22
-                aClipRegion.SetEmpty();
3d17a22
-            }
3d17a22
-        }
3d17a22
-
3d17a22
-        // setup accumulated clip region. Note that setting an
3d17a22
-        // empty clip region denotes "clip everything" on the
3d17a22
-        // OutputDevice (which is why we translate that into
3d17a22
-        // SetClipRegion() here). When both view and render clip
3d17a22
-        // are empty, aClipRegion remains default-constructed,
3d17a22
-        // i.e. empty, too.
3d17a22
-        if( aClipRegion.IsNull() )
3d17a22
-        {
3d17a22
-            rOutDev.SetClipRegion();
3d17a22
-
3d17a22
-            if( p2ndOutDev )
3d17a22
-                p2ndOutDev->SetClipRegion();
3d17a22
-        }
3d17a22
-        else
3d17a22
-        {
3d17a22
-            rOutDev.SetClipRegion( aClipRegion );
3d17a22
-
3d17a22
-            if( p2ndOutDev )
3d17a22
-                p2ndOutDev->SetClipRegion( aClipRegion );
3d17a22
-        }
3d17a22
+        ::canvas::tools::clipOutDev(viewState, renderState, rOutDev, p2ndOutDev);
3d17a22
 
3d17a22
         Color aColor( COL_WHITE );
3d17a22
 
3d17a22
@@ -1373,18 +1302,16 @@ namespace vclcanvas
3d17a22
         ENSURE_OR_THROW( mpOutDev.get(),
3d17a22
                          "outdev null. Are we disposed?" );
3d17a22
 
3d17a22
-        setupOutDevState( viewState, renderState, TEXT_COLOR );
3d17a22
-
3d17a22
         OutputDevice& rOutDev( mpOutDev->getOutDev() );
3d17a22
 
3d17a22
-        ::Font aVCLFont;
3d17a22
+        setupOutDevState( viewState, renderState, TEXT_COLOR );
3d17a22
 
3d17a22
         CanvasFont* pFont = dynamic_cast< CanvasFont* >( xFont.get() );
3d17a22
 
3d17a22
         ENSURE_ARG_OR_THROW( pFont,
3d17a22
                              "Font not compatible with this canvas" );
3d17a22
 
3d17a22
-        aVCLFont = pFont->getVCLFont();
3d17a22
+        ::Font aVCLFont = pFont->getVCLFont();
3d17a22
 
3d17a22
         Color aColor( COL_BLACK );
3d17a22
 
3d17a22
diff --git a/include/canvas/canvastools.hxx b/include/canvas/canvastools.hxx
3d17a22
index de5a76c..3881537 100644
3d17a22
--- a/include/canvas/canvastools.hxx
3d17a22
+++ b/include/canvas/canvastools.hxx
3d17a22
@@ -77,6 +77,7 @@ namespace com { namespace sun { namespace star { namespace awt
3d17a22
 } } } }
3d17a22
 
3d17a22
 class Color;
3d17a22
+class OutputDevice;
3d17a22
 
3d17a22
 namespace canvas
3d17a22
 {
3d17a22
@@ -579,6 +580,11 @@ namespace canvas
3d17a22
             ::std::size_t       mnEntries;
3d17a22
             bool                mbCaseSensitive;
3d17a22
         };
3d17a22
+
3d17a22
+        CANVASTOOLS_DLLPUBLIC void clipOutDev(const css::rendering::ViewState& viewState,
3d17a22
+                        const css::rendering::RenderState& renderState,
3d17a22
+                        OutputDevice& rOutDev,
3d17a22
+                        OutputDevice* p2ndOutDev=NULL);
3d17a22
     }
3d17a22
 }
3d17a22
 
3d17a22
diff --git a/include/vcl/virdev.hxx b/include/vcl/virdev.hxx
3d17a22
index 87205c7..1c0a412 100644
3d17a22
--- a/include/vcl/virdev.hxx
3d17a22
+++ b/include/vcl/virdev.hxx
3d17a22
@@ -110,7 +110,8 @@ public:
3d17a22
         Any rendering will happen directly on the context and not on any intermediate bitmap.
3d17a22
         Note: This might not be supported on all platforms !
3d17a22
     */
3d17a22
-    explicit            VirtualDevice( const SystemGraphicsData *pData, sal_uInt16 nBitCount );
3d17a22
+    explicit            VirtualDevice(const SystemGraphicsData *pData, const Size &rSize,
3d17a22
+                                      sal_uInt16 nBitCount);
3d17a22
 
3d17a22
     virtual             ~VirtualDevice();
3d17a22
 
3d17a22
diff --git a/vcl/source/gdi/virdev.cxx b/vcl/source/gdi/virdev.cxx
3d17a22
index 6378785..9dcc286 100644
3d17a22
--- a/vcl/source/gdi/virdev.cxx
3d17a22
+++ b/vcl/source/gdi/virdev.cxx
3d17a22
@@ -236,13 +236,15 @@ VirtualDevice::VirtualDevice( const OutputDevice& rCompDev, sal_uInt16 nBitCount
3d17a22
     mnAlphaDepth = sal::static_int_cast<sal_Int8>(nAlphaBitCount);
3d17a22
 }
3d17a22
 
3d17a22
-VirtualDevice::VirtualDevice( const SystemGraphicsData *pData, sal_uInt16 nBitCount )
3d17a22
+VirtualDevice::VirtualDevice(const SystemGraphicsData *pData, const Size &rSize,
3d17a22
+                             sal_uInt16 nBitCount)
3d17a22
 :   mpVirDev( NULL ),
3d17a22
     meRefDevMode( REFDEV_NONE )
3d17a22
 {
3d17a22
     SAL_INFO( "vcl.gdi", "VirtualDevice::VirtualDevice( " << nBitCount << " )" );
3d17a22
 
3d17a22
-    ImplInitVirDev( Application::GetDefaultDevice(), 1, 1, nBitCount, pData );
3d17a22
+    ImplInitVirDev(Application::GetDefaultDevice(), rSize.Width(), rSize.Height(),
3d17a22
+                   nBitCount, pData);
3d17a22
 }
3d17a22
 
3d17a22
 VirtualDevice::~VirtualDevice()
3d17a22
-- 
3d17a22
1.9.3
3d17a22