[Libreoffice-commits] core.git: include/vcl vcl/source

Chris Sherlock chris.sherlock79 at gmail.com
Sun Apr 6 20:09:10 PDT 2014


 include/vcl/outdev.hxx     |    6 +
 include/vcl/print.hxx      |    3 
 vcl/source/gdi/outdev4.cxx |  251 ++++++++++++++++++++++-----------------------
 vcl/source/gdi/print.cxx   |   15 ++
 4 files changed, 152 insertions(+), 123 deletions(-)

New commits:
commit 8659d189ec04aca78c8ffff97fcca507ca0a9ec3
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date:   Sun Apr 6 20:57:49 2014 +1000

    fdo#74702 Refactor gradient clipping functions
    
    There are two gradient clipping functions: one uses a normal intersection
    to get the symmetric difference to clip the gradient - this is used by
    OS X and when printing. The other uses XOR clipping, which is an elegant
    trick to implement complex clipping on graphics systems that have minimal
    capabilities.
    cf. http://www.openoffice.org/marketing/ooocon2008/programme/wednesday_1401.pdf
    
    Change-Id: Iab16258c8e758c41a29337525927ba780329e887
    Reviewed-on: https://gerrit.libreoffice.org/8873
    Tested-by: LibreOffice gerrit bot <gerrit at libreoffice.org>
    Reviewed-by: Chris Sherlock <chris.sherlock79 at gmail.com>
    Tested-by: Chris Sherlock <chris.sherlock79 at gmail.com>

diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx
index 016fc16..1195736 100644
--- a/include/vcl/outdev.hxx
+++ b/include/vcl/outdev.hxx
@@ -844,6 +844,12 @@ protected:
     virtual void                EmulateDrawTransparent( const PolyPolygon& rPolyPoly, sal_uInt16 nTransparencePercent );
     void                        DrawInvisiblePolygon( const PolyPolygon& rPolyPoly );
 
+    virtual void                ClipGradientToBounds( Gradient &rGradient, const PolyPolygon &rPolyPoly );
+    void                        ClipGradient( Gradient &rGradient, const PolyPolygon &rPolyPoly, const Rectangle &rBoundRect );
+    void                        XORClipGradient( Gradient &rGradient, const PolyPolygon &rPolyPoly, const Rectangle &rBoundRect );
+
+    virtual void                ClipGradientMetafile ( const Gradient &rGradient, const PolyPolygon &rPolyPoly, const Rectangle &rBoundRect );
+
 private:
     typedef void ( OutputDevice::* FontUpdateHandler_t )( bool );
 
diff --git a/include/vcl/print.hxx b/include/vcl/print.hxx
index d70e7c0..f9179bd 100644
--- a/include/vcl/print.hxx
+++ b/include/vcl/print.hxx
@@ -274,7 +274,10 @@ public:
 
 protected:
     long                        ImplGetGradientStepCount( long nMinRect ) SAL_OVERRIDE;
+    virtual void                ClipGradientToBounds( Gradient &rGradient, const PolyPolygon &rPolyPoly ) SAL_OVERRIDE;
+    virtual void                ClipGradientMetafile ( const Gradient &rGradient, const PolyPolygon &rPolyPoly, const Rectangle &rBoundRect ) SAL_OVERRIDE;
     virtual bool                UsePolyPolygonForComplexGradient() SAL_OVERRIDE;
+
     void                        ScaleBitmap ( Bitmap&, SalTwoRect& ) SAL_OVERRIDE { };
 
 public:
diff --git a/vcl/source/gdi/outdev4.cxx b/vcl/source/gdi/outdev4.cxx
index 4b825f4..51033a5 100644
--- a/vcl/source/gdi/outdev4.cxx
+++ b/vcl/source/gdi/outdev4.cxx
@@ -660,9 +660,9 @@ void OutputDevice::DrawGradient( const Rectangle& rRect,
                 aGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
 
             if( aGradient.GetStyle() == GradientStyle_LINEAR || aGradient.GetStyle() == GradientStyle_AXIAL )
-                ImplDrawLinearGradient( aRect, aGradient, false, NULL );
+                ImplDrawLinearGradient( aRect, rGradient, false, NULL );
             else
-                ImplDrawComplexGradient( aRect, aGradient, false, NULL );
+                ImplDrawComplexGradient( aRect, rGradient, false, NULL );
         }
 
         Pop();
@@ -675,6 +675,129 @@ void OutputDevice::DrawGradient( const Rectangle& rRect,
     }
 }
 
+void OutputDevice::ClipGradientMetafile ( const Gradient &rGradient, const PolyPolygon &rPolyPoly, const Rectangle &rBoundRect )
+{
+    const bool  bOldOutput = IsOutputEnabled();
+
+    EnableOutput( false );
+    Push( PUSH_RASTEROP );
+    SetRasterOp( ROP_XOR );
+    DrawGradient( rBoundRect, rGradient );
+    SetFillColor( COL_BLACK );
+    SetRasterOp( ROP_0 );
+    DrawPolyPolygon( rPolyPoly );
+    SetRasterOp( ROP_XOR );
+    DrawGradient( rBoundRect, rGradient );
+    Pop();
+    EnableOutput( bOldOutput );
+}
+
+void OutputDevice::ClipGradientToBounds ( Gradient &rGradient, const PolyPolygon &rPolyPoly )
+{
+    const Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
+
+    if( ImplGetSVData()->maGDIData.mbNoXORClipping )
+        ClipGradient ( rGradient, rPolyPoly, aBoundRect );
+    else
+        XORClipGradient ( rGradient, rPolyPoly, aBoundRect );
+}
+
+void OutputDevice::ClipGradient ( Gradient &rGradient, const PolyPolygon &rPolyPoly, const Rectangle &rBoundRect )
+{
+    if( !Rectangle( PixelToLogic( Point() ), GetOutputSize() ).IsEmpty() )
+    {
+        // convert rectangle to pixels
+        Rectangle aRect( ImplLogicToDevicePixel( rBoundRect ) );
+        aRect.Justify();
+
+        // do nothing if the rectangle is empty
+        if ( !aRect.IsEmpty() )
+        {
+            if( !mpGraphics && !ImplGetGraphics() )
+                return;
+
+            if( mbInitClipRegion )
+                ImplInitClipRegion();
+
+            if( !mbOutputClipped )
+            {
+                PolyPolygon aClipPolyPoly( ImplLogicToDevicePixel( rPolyPoly ) );
+
+                // draw gradients without border
+                if( mbLineColor || mbInitLineColor )
+                {
+                    mpGraphics->SetLineColor();
+                    mbInitLineColor = true;
+                }
+
+                mbInitFillColor = true;
+
+                // calculate step count if necessary
+                if ( !rGradient.GetSteps() )
+                    rGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
+
+                if( rGradient.GetStyle() == GradientStyle_LINEAR || rGradient.GetStyle() == GradientStyle_AXIAL )
+                    ImplDrawLinearGradient( aRect, rGradient, false, &aClipPolyPoly );
+                else
+                    ImplDrawComplexGradient( aRect, rGradient, false, &aClipPolyPoly );
+            }
+        }
+    }
+}
+
+void OutputDevice::XORClipGradient ( Gradient &rGradient, const PolyPolygon &rPolyPoly, const Rectangle &rBoundRect )
+{
+    const PolyPolygon   aPolyPoly( LogicToPixel( rPolyPoly ) );
+    Point aPoint;
+    Rectangle           aDstRect( aPoint, GetOutputSizePixel() );
+
+    aDstRect.Intersection( rBoundRect );
+
+    ClipToPaintRegion( aDstRect );
+
+    if( !aDstRect.IsEmpty() )
+    {
+        boost::scoped_ptr<VirtualDevice> pVDev;
+        const Size      aDstSize( aDstRect.GetSize() );
+
+        if( HasAlpha() )
+        {
+            // #110958# Pay attention to alpha VDevs here, otherwise,
+            // background will be wrong: Temp VDev has to have alpha, too.
+            pVDev.reset(new VirtualDevice( *this, 0, GetAlphaBitCount() > 1 ? 0 : 1 ));
+        }
+        else
+        {
+            // nothing special here. Plain VDev
+            pVDev.reset(new VirtualDevice());
+        }
+
+        if( pVDev->SetOutputSizePixel( aDstSize) )
+        {
+            MapMode         aVDevMap;
+            const bool      bOldMap = mbMap;
+
+            EnableMapMode( false );
+
+            pVDev->DrawOutDev( Point(), aDstSize, aDstRect.TopLeft(), aDstSize, *this );
+            pVDev->SetRasterOp( ROP_XOR );
+            aVDevMap.SetOrigin( Point( -aDstRect.Left(), -aDstRect.Top() ) );
+            pVDev->SetMapMode( aVDevMap );
+            pVDev->DrawGradient( rBoundRect, rGradient );
+            pVDev->SetFillColor( COL_BLACK );
+            pVDev->SetRasterOp( ROP_0 );
+            pVDev->DrawPolyPolygon( aPolyPoly );
+            pVDev->SetRasterOp( ROP_XOR );
+            pVDev->DrawGradient( rBoundRect, rGradient );
+            aVDevMap.SetOrigin( Point() );
+            pVDev->SetMapMode( aVDevMap );
+            DrawOutDev( aDstRect.TopLeft(), aDstSize, Point(), aDstSize, *pVDev );
+
+            EnableMapMode( bOldMap );
+        }
+    }
+}
+
 void OutputDevice::DrawGradient( const PolyPolygon& rPolyPoly,
                                  const Gradient& rGradient )
 {
@@ -719,34 +842,12 @@ void OutputDevice::DrawGradient( const PolyPolygon& rPolyPoly,
 
         if( mpMetaFile )
         {
-            const Rectangle aRect( rPolyPoly.GetBoundRect() );
+            const Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
 
             mpMetaFile->AddAction( new MetaCommentAction( "XGRAD_SEQ_BEGIN" ) );
             mpMetaFile->AddAction( new MetaGradientExAction( rPolyPoly, rGradient ) );
 
-            if( OUTDEV_PRINTER == meOutDevType )
-            {
-                Push( PUSH_CLIPREGION );
-                IntersectClipRegion(Region(rPolyPoly));
-                DrawGradient( aRect, rGradient );
-                Pop();
-            }
-            else
-            {
-                const bool  bOldOutput = IsOutputEnabled();
-
-                EnableOutput( false );
-                Push( PUSH_RASTEROP );
-                SetRasterOp( ROP_XOR );
-                DrawGradient( aRect, rGradient );
-                SetFillColor( COL_BLACK );
-                SetRasterOp( ROP_0 );
-                DrawPolyPolygon( rPolyPoly );
-                SetRasterOp( ROP_XOR );
-                DrawGradient( aRect, rGradient );
-                Pop();
-                EnableOutput( bOldOutput );
-            }
+            ClipGradientMetafile ( rGradient, rPolyPoly, aBoundRect );
 
             mpMetaFile->AddAction( new MetaCommentAction( "XGRAD_SEQ_END" ) );
         }
@@ -783,103 +884,7 @@ void OutputDevice::DrawGradient( const PolyPolygon& rPolyPoly,
             aGradient.SetEndColor( aEndCol );
         }
 
-        if( OUTDEV_PRINTER == meOutDevType || ImplGetSVData()->maGDIData.mbNoXORClipping )
-        {
-            const Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
-
-            if( !Rectangle( PixelToLogic( Point() ), GetOutputSize() ).IsEmpty() )
-            {
-                // convert rectangle to pixels
-                Rectangle aRect( ImplLogicToDevicePixel( aBoundRect ) );
-                aRect.Justify();
-
-                // do nothing if the rectangle is empty
-                if ( !aRect.IsEmpty() )
-                {
-                    if( !mpGraphics && !ImplGetGraphics() )
-                        return;
-
-                    if( mbInitClipRegion )
-                        ImplInitClipRegion();
-
-                    if( !mbOutputClipped )
-                    {
-                        PolyPolygon aClipPolyPoly( ImplLogicToDevicePixel( rPolyPoly ) );
-
-                        // draw gradients without border
-                        if( mbLineColor || mbInitLineColor )
-                        {
-                            mpGraphics->SetLineColor();
-                            mbInitLineColor = true;
-                        }
-
-                        mbInitFillColor = true;
-
-                        // calculate step count if necessary
-                        if ( !aGradient.GetSteps() )
-                            aGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
-
-                        if( aGradient.GetStyle() == GradientStyle_LINEAR || aGradient.GetStyle() == GradientStyle_AXIAL )
-                            ImplDrawLinearGradient( aRect, aGradient, false, &aClipPolyPoly );
-                        else
-                            ImplDrawComplexGradient( aRect, aGradient, false, &aClipPolyPoly );
-                    }
-                }
-            }
-        }
-        else
-        {
-            const PolyPolygon   aPolyPoly( LogicToPixel( rPolyPoly ) );
-            const Rectangle     aBoundRect( aPolyPoly.GetBoundRect() );
-            Point aPoint;
-            Rectangle           aDstRect( aPoint, GetOutputSizePixel() );
-
-            aDstRect.Intersection( aBoundRect );
-
-            ClipToPaintRegion( aDstRect );
-
-            if( !aDstRect.IsEmpty() )
-            {
-                boost::scoped_ptr<VirtualDevice> pVDev;
-                const Size      aDstSize( aDstRect.GetSize() );
-
-                if( HasAlpha() )
-                {
-                    // #110958# Pay attention to alpha VDevs here, otherwise,
-                    // background will be wrong: Temp VDev has to have alpha, too.
-                    pVDev.reset(new VirtualDevice( *this, 0, GetAlphaBitCount() > 1 ? 0 : 1 ));
-                }
-                else
-                {
-                    // nothing special here. Plain VDev
-                    pVDev.reset(new VirtualDevice());
-                }
-
-                if( pVDev->SetOutputSizePixel( aDstSize) )
-                {
-                    MapMode         aVDevMap;
-                    const bool      bOldMap = mbMap;
-
-                    EnableMapMode( false );
-
-                    pVDev->DrawOutDev( Point(), aDstSize, aDstRect.TopLeft(), aDstSize, *this );
-                    pVDev->SetRasterOp( ROP_XOR );
-                    aVDevMap.SetOrigin( Point( -aDstRect.Left(), -aDstRect.Top() ) );
-                    pVDev->SetMapMode( aVDevMap );
-                    pVDev->DrawGradient( aBoundRect, aGradient );
-                    pVDev->SetFillColor( COL_BLACK );
-                    pVDev->SetRasterOp( ROP_0 );
-                    pVDev->DrawPolyPolygon( aPolyPoly );
-                    pVDev->SetRasterOp( ROP_XOR );
-                    pVDev->DrawGradient( aBoundRect, aGradient );
-                    aVDevMap.SetOrigin( Point() );
-                    pVDev->SetMapMode( aVDevMap );
-                    DrawOutDev( aDstRect.TopLeft(), aDstSize, Point(), aDstSize, *pVDev );
-
-                    EnableMapMode( bOldMap );
-                }
-            }
-        }
+        ClipGradientToBounds ( aGradient, rPolyPoly );
     }
 
     if( mpAlphaVDev )
diff --git a/vcl/source/gdi/print.cxx b/vcl/source/gdi/print.cxx
index 7adfcde..c66f121 100644
--- a/vcl/source/gdi/print.cxx
+++ b/vcl/source/gdi/print.cxx
@@ -1812,4 +1812,19 @@ bool Printer::UsePolyPolygonForComplexGradient()
     return true;
 }
 
+void Printer::ClipGradientToBounds ( Gradient &rGradient, const PolyPolygon &rPolyPoly )
+{
+    const Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
+
+    ClipGradient ( rGradient, rPolyPoly, aBoundRect );
+}
+
+void Printer::ClipGradientMetafile ( const Gradient &rGradient, const PolyPolygon &rPolyPoly, const Rectangle &rBoundRect )
+{
+    Push( PUSH_CLIPREGION );
+    IntersectClipRegion(Region(rPolyPoly));
+    DrawGradient( rBoundRect, rGradient );
+    Pop();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list