Blob Blame History Raw
From 628b75715c99df9716ab487f1bb1cad0f086d7ea Mon Sep 17 00:00:00 2001
From: Armin Le Grand <alg@apache.org>
Date: Wed, 23 Jul 2014 16:35:32 +0000
Subject: [PATCH 058/137] Resolves: fdo#81598 #i125300# enhanced handling of
 multiple ClipRegions...

in MetafileProcessor

(cherry picked from commit 02e2c7b225036c6478a1f7e8315a9c8361025a7f)

Change-Id: Iefefc36c040507795bc2c25fe8d4a610eb12adb9
(cherry picked from commit 2ddfaf1f03135c10d33e0e99ebe8a56d3783d214)
Reviewed-on: https://gerrit.libreoffice.org/10505
Reviewed-by: David Tardon <dtardon@redhat.com>
Tested-by: David Tardon <dtardon@redhat.com>
---
 .../source/processor2d/vclmetafileprocessor2d.cxx  | 65 ++++++++++++++++++----
 1 file changed, 54 insertions(+), 11 deletions(-)

diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
index 94fc972..e6b2dd5 100644
--- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
@@ -1760,17 +1760,52 @@ namespace drawinglayer
 
                             if(maClipPolyPolygon.count())
                             {
-                                // there is already a clip polygon set; build clipped union of
-                                // current mask polygon and new one
-                                maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(
-                                    aMask,
-                                    maClipPolyPolygon,
-                                    true, // #i106516# we want the inside of aMask, not the outside
-                                    false);
+                                // due to the cost of PolyPolygon clipping and numerical reasons try first if the current
+                                // and the new ClipRegion are ranges. If yes, processing can be simplified
+                                if(basegfx::tools::isRectangle(aMask)
+                                    && basegfx::tools::isRectangle(maClipPolyPolygon))
+                                {
+                                    // both ClipPolygons are rectangles
+                                    if(aMask.getB2DRange().equal(maClipPolyPolygon.getB2DRange()))
+                                    {
+                                        // equal -> no change in ClipRegion needed, leave
+                                        // maClipPolyPolygon unchanged
+                                    }
+                                    else
+                                    {
+                                        // not equal -> create new ClipRegion from the two ranges
+                                        basegfx::B2DRange aClipRange(aMask.getB2DRange());
+
+                                        aClipRange.intersect(maClipPolyPolygon.getB2DRange());
+
+                                        if(aClipRange.isEmpty())
+                                        {
+                                            // no common ClipRegion -> set empty ClipRegion, no content to show
+                                            maClipPolyPolygon.clear();
+                                        }
+                                        else
+                                        {
+                                            // use common ClipRegion as new ClipRegion
+                                            maClipPolyPolygon = basegfx::B2DPolyPolygon(
+                                                basegfx::tools::createPolygonFromRect(aClipRange));
+                                        }
+                                    }
+                                }
+                                else
+                                {
+                                    // The current ClipRegion or the new one is not a rectangle;
+                                    // there is already a clip polygon set; build clipped union of
+                                    // current mask polygon and new one
+                                    maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(
+                                        aMask,
+                                        maClipPolyPolygon,
+                                        true, // #i106516# we want the inside of aMask, not the outside
+                                        false);
+                                }
                             }
                             else
                             {
-                                // use mask directly
+                                // use new mask directly as ClipRegion
                                 maClipPolyPolygon = aMask;
                             }
 
@@ -1779,8 +1814,13 @@ namespace drawinglayer
                                 // set VCL clip region; subdivide before conversion to tools polygon. Subdivision necessary (!)
                                 // Removed subdivision and fixed in Region::ImplPolyPolyRegionToBandRegionFunc() in VCL where
                                 // the ClipRegion is built from the Polygon. A AdaptiveSubdivide on the source polygon was missing there
-                                mpOutputDevice->Push(PUSH_CLIPREGION);
-                                mpOutputDevice->SetClipRegion(Region(maClipPolyPolygon));
+                                const bool bNewClipRegion(maClipPolyPolygon != aLastClipPolyPolygon);
+
+                                if(bNewClipRegion)
+                                {
+                                    mpOutputDevice->Push(PUSH_CLIPREGION);
+                                    mpOutputDevice->SetClipRegion(Region(maClipPolyPolygon));
+                                }
 
                                 // recursively paint content
                                 // #i121267# Only need to process sub-content when clip polygon is *not* empty.
@@ -1788,7 +1828,10 @@ namespace drawinglayer
                                 process(rMaskCandidate.getChildren());
 
                                 // restore VCL clip region
-                                mpOutputDevice->Pop();
+                                if(bNewClipRegion)
+                                {
+                                    mpOutputDevice->Pop();
+                                }
                             }
 
                             // restore to rescued clip polygon
-- 
1.9.3