incubator-ooo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a..@apache.org
Subject svn commit: r1402475 - in /incubator/ooo/trunk/main: basegfx/inc/basegfx/polygon/ basegfx/source/polygon/ drawinglayer/source/processor2d/ filter/source/flash/ filter/source/graphicfilter/eos2met/ svtools/source/filter/wmf/ vcl/ vcl/inc/vcl/ vcl/source...
Date Fri, 26 Oct 2012 12:00:48 GMT
Author: alg
Date: Fri Oct 26 12:00:48 2012
New Revision: 1402475

URL: http://svn.apache.org/viewvc?rev=1402475&view=rev
Log:
#121267# added support for taking clipping into account for metafile-based exporters to vector formats

Added:
    incubator/ooo/trunk/main/vcl/inc/vcl/gdimetafiletools.hxx   (with props)
    incubator/ooo/trunk/main/vcl/source/gdi/gdimetafiletools.cxx   (with props)
Modified:
    incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx
    incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx
    incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolypolygontools.cxx
    incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
    incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclprocessor2d.cxx
    incubator/ooo/trunk/main/filter/source/flash/swfexporter.cxx
    incubator/ooo/trunk/main/filter/source/graphicfilter/eos2met/eos2met.cxx
    incubator/ooo/trunk/main/svtools/source/filter/wmf/wmf.cxx
    incubator/ooo/trunk/main/vcl/Library_vcl.mk
    incubator/ooo/trunk/main/vcl/Package_inc.mk

Modified: incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx?rev=1402475&r1=1402474&r2=1402475&view=diff
==============================================================================
--- incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx (original)
+++ incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx Fri Oct 26 12:00:48 2012
@@ -98,7 +98,13 @@ namespace basegfx
 		*/
 		B2DRange getRange(const B2DPolyPolygon& rCandidate);
 			
-		/** Apply given LineDashing to given polyPolygon
+		// get signed area of polygon
+		double getSignedArea(const B2DPolyPolygon& rCandidate);
+
+		// get area of polygon
+		double getArea(const B2DPolyPolygon& rCandidate);
+
+        /** Apply given LineDashing to given polyPolygon
 
 			For a description see applyLineDashing in b2dpolygontoos.hxx
 		*/

Modified: incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx?rev=1402475&r1=1402474&r2=1402475&view=diff
==============================================================================
--- incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx (original)
+++ incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx Fri Oct 26 12:00:48 2012
@@ -519,8 +519,6 @@ namespace basegfx
 					fRetval -= aPreviousPoint.getY() * aCurrentPoint.getX();
 				}
 
-				fRetval /= 2.0;
-
 				// correct to zero if small enough. Also test the quadratic
 				// of the result since the precision is near quadratic due to
 				// the algorithm

Modified: incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolypolygontools.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolypolygontools.cxx?rev=1402475&r1=1402474&r2=1402475&view=diff
==============================================================================
--- incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolypolygontools.cxx (original)
+++ incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolypolygontools.cxx Fri Oct 26 12:00:48 2012
@@ -263,7 +263,27 @@ namespace basegfx
 			return aRetval;
 		}
 
-		void applyLineDashing(const B2DPolyPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B2DPolyPolygon* pLineTarget, B2DPolyPolygon* pGapTarget, double fFullDashDotLen)
+		double getSignedArea(const B2DPolyPolygon& rCandidate)
+		{
+			double fRetval(0.0);
+			const sal_uInt32 nPolygonCount(rCandidate.count());
+
+			for(sal_uInt32 a(0L); a < nPolygonCount; a++)
+			{
+				const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
+
+                fRetval += tools::getSignedArea(aCandidate);
+			}
+
+			return fRetval;
+		}
+
+		double getArea(const B2DPolyPolygon& rCandidate)
+		{
+			return fabs(getSignedArea(rCandidate));
+		}
+
+        void applyLineDashing(const B2DPolyPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B2DPolyPolygon* pLineTarget, B2DPolyPolygon* pGapTarget, double fFullDashDotLen)
 		{
 			if(0.0 == fFullDashDotLen && rDotDashArray.size())
 			{

Modified: incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx?rev=1402475&r1=1402474&r2=1402475&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx Fri Oct 26 12:00:48 2012
@@ -1155,14 +1155,29 @@ namespace drawinglayer
     					// direct draw of hairline; use default processing
     					// support SvtGraphicStroke MetaCommentAction
 					    const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rHairlinePrimitive.getBColor()));
-					    SvtGraphicStroke* pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
-                            rHairlinePrimitive.getB2DPolygon(), 
-                            &aLineColor, 
-                            0, 0, 0, 0);
+                        SvtGraphicStroke* pSvtGraphicStroke = 0;
+
+                        // #121267# Not needed, does not give better quality compared with
+                        // the META_POLYPOLYGON_ACTION written by RenderPolygonHairlinePrimitive2D
+                        // below
+                        bool bSupportSvtGraphicStroke(false);
+
+                        if(bSupportSvtGraphicStroke)
+                        {
+                            pSvtGraphicStroke = impTryToCreateSvtGraphicStroke(
+                                rHairlinePrimitive.getB2DPolygon(), 
+                                &aLineColor, 
+                                0, 0, 0, 0);
+
+    					    impStartSvtGraphicStroke(pSvtGraphicStroke);
+                        }
 
-					    impStartSvtGraphicStroke(pSvtGraphicStroke);
 					    RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), false);
-					    impEndSvtGraphicStroke(pSvtGraphicStroke);
+					    
+                        if(bSupportSvtGraphicStroke)
+                        {
+                            impEndSvtGraphicStroke(pSvtGraphicStroke);
+                        }
                     }
 					break;
 				}
@@ -1631,7 +1646,12 @@ namespace drawinglayer
 				    // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
 				    SvtGraphicFill* pSvtGraphicFill = 0;
 
-				    if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
+                    // #121267# Not needed, does not give better quality compared with
+                    // the META_POLYPOLYGON_ACTION written by the DrawPolyPolygon command
+                    // below
+                    bool bSupportSvtGraphicFill(false);
+
+				    if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count())
 				    {
 					    // setup simple color fill stuff like in impgrfll
 					    pSvtGraphicFill = new SvtGraphicFill(
@@ -1656,9 +1676,17 @@ namespace drawinglayer
 				    mpOutputDevice->SetLineColor();
 
 				    // call VCL directly; encapsulate with SvtGraphicFill
-                    impStartSvtGraphicFill(pSvtGraphicFill);
-				    mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
-				    impEndSvtGraphicFill(pSvtGraphicFill);
+                    if(bSupportSvtGraphicFill)
+                    {
+                            impStartSvtGraphicFill(pSvtGraphicFill);
+                    }
+				    
+                    mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
+				    
+                    if(bSupportSvtGraphicFill)
+                    {
+                        impEndSvtGraphicFill(pSvtGraphicFill);
+                    }
 
 					break;
 				}
@@ -1716,16 +1744,13 @@ namespace drawinglayer
                                 // 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(PolyPolygon(basegfx::tools::adaptiveSubdivideByAngle(maClipPolyPolygon))));
-								//mpOutputDevice->SetClipRegion(Region(PolyPolygon(maClipPolyPolygon)));
-								mpOutputDevice->SetClipRegion(Region(maClipPolyPolygon));
-                            }
+                                mpOutputDevice->SetClipRegion(Region(maClipPolyPolygon));
+
+                                // recursively paint content
+                                // #121267# Only need to process sub-content when clip polygon is *not* empty.
+                                // If it is empty, the clip is empty and there can be nothing inside.
+                                process(rMaskCandidate.getChildren());
 
-					        // recursively paint content
-					        process(rMaskCandidate.getChildren());
-                            
-                            if(maClipPolyPolygon.count())
-                            {
                                 // restore VCL clip region
                                 mpOutputDevice->Pop();
                             }
@@ -1816,8 +1841,13 @@ namespace drawinglayer
 
 							    // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support
 							    SvtGraphicFill* pSvtGraphicFill = 0;
+                                
+                                // #121267# Not needed, does not give better quality compared with
+                                // the META_POLYPOLYGON_ACTION written by the DrawPolyPolygon command
+                                // below
+                                bool bSupportSvtGraphicFill(false);
 
-							    if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count())
+							    if(bSupportSvtGraphicFill && !mnSvtGraphicFillCount && aLocalPolyPolygon.count())
 							    {
 								    // setup simple color with transparence fill stuff like in impgrfll
 								    pSvtGraphicFill = new SvtGraphicFill(
@@ -1843,11 +1873,19 @@ namespace drawinglayer
 							    mpOutputDevice->SetLineColor();
 
 							    // call VCL directly; encapsulate with SvtGraphicFill
-                                impStartSvtGraphicFill(pSvtGraphicFill);
+                                if(bSupportSvtGraphicFill)
+                                {
+                                    impStartSvtGraphicFill(pSvtGraphicFill);
+                                }
+
 							    mpOutputDevice->DrawTransparent(
 								    PolyPolygon(aLocalPolyPolygon), 
 								    nTransPercentVcl);
-							    impEndSvtGraphicFill(pSvtGraphicFill);
+							    
+                                if(bSupportSvtGraphicFill)
+                                {
+                                    impEndSvtGraphicFill(pSvtGraphicFill);
+                                }
 						    }
 						    else
 						    {

Modified: incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclprocessor2d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclprocessor2d.cxx?rev=1402475&r1=1402474&r2=1402475&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclprocessor2d.cxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclprocessor2d.cxx Fri Oct 26 12:00:48 2012
@@ -512,14 +512,16 @@ namespace drawinglayer
 						        // nBWidth, nBHeight is the pixel size of the neede bitmap. To not need to scale it
 						        // in vcl many times, create a size-optimized version
 						        const Size aNeededBitmapSizePixel(nBWidth, nBHeight);
-                                BitmapEx aBitmapEx(rFillGraphicAttribute.getGraphic().GetBitmapEx(
-                                    GraphicConversionParameters(
-                                        aNeededBitmapSizePixel, // get the correct size immediately
-                                        false, // no unlimited size
-                                        false, // Use AntiAliasing
-                                        false, //SnapHorVerLines
-                                        true // ScaleHighQuality
-                                        )));
+                                BitmapEx aBitmapEx(rFillGraphicAttribute.getGraphic().GetBitmapEx());
+                                static bool bEnablePreScaling(true);
+                                const bool bPreScaled(bEnablePreScaling && nBWidth * nBHeight < (250 * 250));
+
+                                if(bPreScaled)
+                                {
+                                    // ... but only up to a maximum size, else it gets too expensive
+                                    aBitmapEx.Scale(aNeededBitmapSizePixel, BMP_SCALE_INTERPOLATE);
+                                }
+
 					            bool bPainted(false);
 
 					            if(maBColorModifierStack.count())
@@ -606,7 +608,14 @@ namespace drawinglayer
 
                                                 if(aOutRectPixel.IsOver(aVisiblePixel))
                                                 {
-                                                    mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
+                                                    if(bPreScaled)
+                                                    {
+                                                        mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
+                                                    }
+                                                    else
+                                                    {
+                                                        mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aNeededBitmapSizePixel, aBitmapEx);
+                                                    }
                                                 }
                                             }
                                         }
@@ -626,7 +635,14 @@ namespace drawinglayer
 
                                                 if(aOutRectPixel.IsOver(aVisiblePixel))
                                                 {
-                                                    mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
+                                                    if(bPreScaled)
+                                                    {
+                                                        mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
+                                                    }
+                                                    else
+                                                    {
+                                                        mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aNeededBitmapSizePixel, aBitmapEx);
+                                                    }
                                                 }
                                             }
                                         }

Modified: incubator/ooo/trunk/main/filter/source/flash/swfexporter.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/filter/source/flash/swfexporter.cxx?rev=1402475&r1=1402474&r2=1402475&view=diff
==============================================================================
--- incubator/ooo/trunk/main/filter/source/flash/swfexporter.cxx (original)
+++ incubator/ooo/trunk/main/filter/source/flash/swfexporter.cxx Fri Oct 26 12:00:48 2012
@@ -41,6 +41,7 @@
 #include <vcl/metaact.hxx>
 #include <svtools/wmf.hxx>
 #include <svtools/filter.hxx>
+#include <vcl/gdimetafiletools.hxx>
 
 #include "swfexporter.hxx"
 #include "swfwriter.hxx"
@@ -721,8 +722,18 @@ bool FlashExporter::getMetaFile( Referen
 
 	}
 	else
+    {
 		rMtf.Read( *aFile.GetStream( STREAM_READ ) );
 
+        if(usesClipActions(rMtf))
+        {
+            // #121267# It is necessary to prepare the metafile since the export does *not* support
+            // clip regions. This tooling method clips the geometry content of the metafile internally 
+            // against it's own clip regions, so that the export is safe to ignore clip regions
+            clipMetafileContentAgainstOwnRegions(rMtf);
+        }
+    }
+
 	int icount = rMtf.GetActionCount();
 	return icount != 0;
 }

Modified: incubator/ooo/trunk/main/filter/source/graphicfilter/eos2met/eos2met.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/filter/source/graphicfilter/eos2met/eos2met.cxx?rev=1402475&r1=1402474&r2=1402475&view=diff
==============================================================================
--- incubator/ooo/trunk/main/filter/source/graphicfilter/eos2met/eos2met.cxx (original)
+++ incubator/ooo/trunk/main/filter/source/graphicfilter/eos2met/eos2met.cxx Fri Oct 26 12:00:48 2012
@@ -41,7 +41,7 @@
 #include <vcl/svapp.hxx>
 #include <vcl/msgbox.hxx>
 #include <svl/solar.hrc>
-
+#include <vcl/gdimetafiletools.hxx>
 
 // -----------------------------Feld-Typen-------------------------------
 
@@ -2588,8 +2588,20 @@ sal_Bool METWriter::WriteMET( const GDIM
 //================== GraphicExport - die exportierte Funktion ================
 
 extern "C" sal_Bool __LOADONCALLAPI GraphicExport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* pFilterConfigItem, sal_Bool )
-{	METWriter aMETWriter;
+{
+    METWriter aMETWriter;
+
+    // #119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
+    GDIMetaFile aMetafile(rGraphic.GetGDIMetaFile());
+
+    if(usesClipActions(aMetafile))
+    {
+        // #121267# It is necessary to prepare the metafile since the export does *not* support
+        // clip regions. This tooling method clips the geometry content of the metafile internally 
+        // against it's own clip regions, so that the export is safe to ignore clip regions
+        clipMetafileContentAgainstOwnRegions(aMetafile);
+    }
 
     // #119735# just use GetGDIMetaFile, it will create a bufferd version of contained bitmap now automatically
-    return aMETWriter.WriteMET( rGraphic.GetGDIMetaFile(), rStream, pFilterConfigItem );
+    return aMETWriter.WriteMET( aMetafile, rStream, pFilterConfigItem );
 }

Modified: incubator/ooo/trunk/main/svtools/source/filter/wmf/wmf.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/svtools/source/filter/wmf/wmf.cxx?rev=1402475&r1=1402474&r2=1402475&view=diff
==============================================================================
--- incubator/ooo/trunk/main/svtools/source/filter/wmf/wmf.cxx (original)
+++ incubator/ooo/trunk/main/svtools/source/filter/wmf/wmf.cxx Fri Oct 26 12:00:48 2012
@@ -28,6 +28,7 @@
 #include "emfwr.hxx"
 #include "wmfwr.hxx"
 #include <svtools/wmf.hxx>
+#include <vcl/gdimetafiletools.hxx>
 
 // -----------------------------------------------------------------------------
 
@@ -83,7 +84,17 @@ sal_Bool ConvertGDIMetaFileToWMF( const 
 							  FilterConfigItem* pConfigItem, sal_Bool bPlaceable)
 {
 	WMFWriter aWMFWriter;
-	return aWMFWriter.WriteWMF( rMTF, rTargetStream, pConfigItem, bPlaceable );
+    GDIMetaFile aGdiMetaFile(rMTF);
+
+    if(usesClipActions(aGdiMetaFile))
+    {
+        // #121267# It is necessary to prepare the metafile since the export does *not* support
+        // clip regions. This tooling method clips the geometry content of the metafile internally 
+        // against it's own clip regions, so that the export is safe to ignore clip regions
+        clipMetafileContentAgainstOwnRegions(aGdiMetaFile);
+    }
+
+    return aWMFWriter.WriteWMF( aGdiMetaFile, rTargetStream, pConfigItem, bPlaceable );
 }
 
 // -----------------------------------------------------------------------------
@@ -92,7 +103,17 @@ sal_Bool ConvertGDIMetaFileToEMF( const 
 							  FilterConfigItem* pConfigItem )
 {
 	EMFWriter aEMFWriter;
-	return aEMFWriter.WriteEMF( rMTF, rTargetStream, pConfigItem );
+    GDIMetaFile aGdiMetaFile(rMTF);
+
+    if(usesClipActions(aGdiMetaFile))
+    {
+        // #121267# It is necessary to prepare the metafile since the export does *not* support
+        // clip regions. This tooling method clips the geometry content of the metafile internally 
+        // against it's own clip regions, so that the export is safe to ignore clip regions
+        clipMetafileContentAgainstOwnRegions(aGdiMetaFile);
+    }
+
+    return aEMFWriter.WriteEMF( aGdiMetaFile, rTargetStream, pConfigItem );
 }
 
 // -----------------------------------------------------------------------------

Modified: incubator/ooo/trunk/main/vcl/Library_vcl.mk
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/vcl/Library_vcl.mk?rev=1402475&r1=1402474&r2=1402475&view=diff
==============================================================================
--- incubator/ooo/trunk/main/vcl/Library_vcl.mk (original)
+++ incubator/ooo/trunk/main/vcl/Library_vcl.mk Fri Oct 26 12:00:48 2012
@@ -337,6 +337,7 @@ $(eval $(call gb_Library_add_exception_o
     vcl/source/gdi/extoutdevdata \
     vcl/source/gdi/font \
     vcl/source/gdi/gdimtf \
+    vcl/source/gdi/gdimetafiletools \
     vcl/source/gdi/gfxlink \
     vcl/source/gdi/gradient \
     vcl/source/gdi/graph \

Modified: incubator/ooo/trunk/main/vcl/Package_inc.mk
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/vcl/Package_inc.mk?rev=1402475&r1=1402474&r2=1402475&view=diff
==============================================================================
--- incubator/ooo/trunk/main/vcl/Package_inc.mk (original)
+++ incubator/ooo/trunk/main/vcl/Package_inc.mk Fri Oct 26 12:00:48 2012
@@ -62,6 +62,7 @@ $(eval $(call gb_Package_add_file,vcl_in
 $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/font.hxx,vcl/font.hxx))
 $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/fontmanager.hxx,vcl/fontmanager.hxx))
 $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/gdimtf.hxx,vcl/gdimtf.hxx))
+$(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/gdimetafiletools.hxx,vcl/gdimetafiletools.hxx))
 $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/gfxlink.hxx,vcl/gfxlink.hxx))
 $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/gradient.hxx,vcl/gradient.hxx))
 $(eval $(call gb_Package_add_file,vcl_inc,inc/vcl/graph.h,vcl/graph.h))

Added: incubator/ooo/trunk/main/vcl/inc/vcl/gdimetafiletools.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/vcl/inc/vcl/gdimetafiletools.hxx?rev=1402475&view=auto
==============================================================================
--- incubator/ooo/trunk/main/vcl/inc/vcl/gdimetafiletools.hxx (added)
+++ incubator/ooo/trunk/main/vcl/inc/vcl/gdimetafiletools.hxx Fri Oct 26 12:00:48 2012
@@ -0,0 +1,47 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+#ifndef _SV_GDIMETAFILETOOLS_HXX
+#define _SV_GDIMETAFILETOOLS_HXX
+
+#include <vcl/gdimtf.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// #121267# Added tooling to be able to support old exporters which are based on 
+// metafiles as graphic content, but do not implement using the contained clip 
+// regions.
+// The given metafile will internall yclip it's graphic content against the 
+// included clip regions so that it is safe to ignore clip actions there. This
+// is not done completely, but implemented and extended as needed (on demand)
+// since all this is a workarund; the better and long term solution will be to
+// reimplement these im/exports to use primitives and not metafiles as bese 
+// information.
+
+void VCL_DLLPUBLIC clipMetafileContentAgainstOwnRegions(GDIMetaFile& rSource);
+
+//////////////////////////////////////////////////////////////////////////////
+// Allow to check if a Metafile contains clipping or not
+
+bool VCL_DLLPUBLIC usesClipActions(const GDIMetaFile& rSource);
+
+//////////////////////////////////////////////////////////////////////////////
+
+#endif // _SV_GDIMETAFILETOOLS_HXX

Propchange: incubator/ooo/trunk/main/vcl/inc/vcl/gdimetafiletools.hxx
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/ooo/trunk/main/vcl/source/gdi/gdimetafiletools.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/vcl/source/gdi/gdimetafiletools.cxx?rev=1402475&view=auto
==============================================================================
--- incubator/ooo/trunk/main/vcl/source/gdi/gdimetafiletools.cxx (added)
+++ incubator/ooo/trunk/main/vcl/source/gdi/gdimetafiletools.cxx Fri Oct 26 12:00:48 2012
@@ -0,0 +1,1104 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <vcl/gdimetafiletools.hxx>
+#include <vcl/metaact.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/graphictools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+// helpers
+
+namespace
+{
+    bool handleGeometricContent(
+        const basegfx::B2DPolyPolygon& rClip,
+        const basegfx::B2DPolyPolygon& rSource,
+        GDIMetaFile& rTarget,
+        bool bStroke)
+    {
+        if(rSource.count() && rClip.count())
+        {
+            const basegfx::B2DPolyPolygon aResult(
+                basegfx::tools::clipPolyPolygonOnPolyPolygon(
+                    rSource,
+                    rClip,
+                    true, // inside
+                    bStroke));
+
+            if(aResult.count())
+            {
+                if(aResult == rSource)
+                {
+                    // not clipped, but inside. Add original
+                    return false;
+                }
+                else
+                {
+                    // add clipped geometry
+                    if(bStroke)
+                    {
+                        for(sal_uInt32 a(0); a < aResult.count(); a++)
+                        {
+                            rTarget.AddAction(
+                                new MetaPolyLineAction(
+                                    Polygon(aResult.getB2DPolygon(a))));
+                        }
+                    }
+                    else
+                    {
+                        rTarget.AddAction(
+                            new MetaPolyPolygonAction(
+                                PolyPolygon(aResult)));
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
+
+    bool handleGradientContent(
+        const basegfx::B2DPolyPolygon& rClip,
+        const basegfx::B2DPolyPolygon& rSource,
+        const Gradient& rGradient,
+        GDIMetaFile& rTarget)
+    {
+        if(rSource.count() && rClip.count())
+        {
+            const basegfx::B2DPolyPolygon aResult(
+                basegfx::tools::clipPolyPolygonOnPolyPolygon(
+                    rSource,
+                    rClip,
+                    true, // inside
+                    false)); // stroke
+
+            if(aResult.count())
+            {
+                if(aResult == rSource)
+                {
+                    // not clipped, but inside. Add original
+                    return false;
+                }
+                else
+                {
+                    // add clipped geometry
+                    rTarget.AddAction(
+                        new MetaGradientExAction(
+                            PolyPolygon(aResult),
+                            rGradient));
+                }
+            }
+        }
+
+        return true;
+    }
+
+    bool handleBitmapContent(
+        const basegfx::B2DPolyPolygon& rClip,
+        const Point& rPoint,
+        const Size& rSize,
+        const BitmapEx& rBitmapEx,
+        GDIMetaFile& rTarget)
+    {
+        if(!rSize.Width() || !rSize.Height() || rBitmapEx.IsEmpty())
+        {
+            // bitmap or size is empty
+            return true;
+        }
+
+        const basegfx::B2DRange aLogicBitmapRange(
+            rPoint.X(), rPoint.Y(),
+            rPoint.X() + rSize.Width(), rPoint.Y() + rSize.Height());
+        const basegfx::B2DPolyPolygon aClipOfBitmap(
+            basegfx::tools::clipPolyPolygonOnRange(
+                rClip, 
+                aLogicBitmapRange, 
+                true,
+                false)); // stroke
+
+        if(!aClipOfBitmap.count())
+        {
+            // outside clip region
+            return true;
+        }
+
+        // inside or overlapping. Use area to find out if it is completely
+        // covering (inside) or overlapping
+        const double fClipArea(basegfx::tools::getArea(aClipOfBitmap));
+        const double fBitmapArea(
+            aLogicBitmapRange.getWidth() * aLogicBitmapRange.getWidth() + 
+            aLogicBitmapRange.getHeight() * aLogicBitmapRange.getHeight());
+        const double fFactor(fClipArea / fBitmapArea);
+
+        if(basegfx::fTools::more(fFactor, 1.0 - 0.001))
+        {
+            // completely covering (with 0.1% tolerance)
+            return false;
+        }
+
+        // needs clipping (with 0.1% tolerance). Prepare VirtualDevice
+        // in pixel mode for alpha channel painting (black is transparent,
+        // white to paint 100% opacity)
+        const Size aSizePixel(rBitmapEx.GetSizePixel());
+        VirtualDevice aVDev;
+
+        aVDev.SetOutputSizePixel(aSizePixel);
+        aVDev.EnableMapMode(false);
+        aVDev.SetFillColor(COL_WHITE);
+        aVDev.SetLineColor();
+
+        if(rBitmapEx.IsTransparent())
+        {
+            // use given alpha channel
+            aVDev.DrawBitmap(Point(0, 0), rBitmapEx.GetAlpha().GetBitmap());
+        }
+        else
+        {
+            // reset alpha channel
+            aVDev.SetBackground(Wallpaper(Color(COL_BLACK)));
+            aVDev.Erase();
+        }
+
+        // transform polygon from clipping to pixel coordinates
+        basegfx::B2DPolyPolygon aPixelPoly(aClipOfBitmap);
+        basegfx::B2DHomMatrix aTransform;
+
+        aTransform.translate(-aLogicBitmapRange.getMinX(), -aLogicBitmapRange.getMinY());
+        aTransform.scale(
+            static_cast< double >(aSizePixel.Width()) / aLogicBitmapRange.getWidth(), 
+            static_cast< double >(aSizePixel.Height()) / aLogicBitmapRange.getHeight());
+        aPixelPoly.transform(aTransform);
+
+        // to fill the non-covered parts, use the Xor fill rule of
+        // PolyPolygon painting. Start with a all-covering polygon and
+        // add the clip polygon one
+        basegfx::B2DPolyPolygon aInvertPixelPoly;
+
+        aInvertPixelPoly.append(
+            basegfx::tools::createPolygonFromRect(
+                basegfx::B2DRange(
+                    0.0, 0.0,
+                    aSizePixel.Width(), aSizePixel.Height())));
+        aInvertPixelPoly.append(aPixelPoly);
+
+        // paint as alpha
+        aVDev.DrawPolyPolygon(aInvertPixelPoly);
+
+        // get created alpha mask and set defaults
+        AlphaMask aAlpha(
+            aVDev.GetBitmap(
+                Point(0, 0),
+                aSizePixel));
+
+        aAlpha.SetPrefSize(rBitmapEx.GetPrefSize());
+        aAlpha.SetPrefMapMode(rBitmapEx.GetPrefMapMode());
+
+        // add new action replacing the old one
+        rTarget.AddAction(
+            new MetaBmpExScaleAction(
+                Point(
+                    basegfx::fround(aLogicBitmapRange.getMinX()), 
+                    basegfx::fround(aLogicBitmapRange.getMinY())),
+                Size(
+                    basegfx::fround(aLogicBitmapRange.getWidth()), 
+                    basegfx::fround(aLogicBitmapRange.getHeight())),
+                BitmapEx(rBitmapEx.GetBitmap(), aAlpha)));
+
+        return true;
+    }
+
+    void addSvtGraphicStroke(const SvtGraphicStroke& rStroke, GDIMetaFile& rTarget)
+    {
+        // write SvtGraphicFill
+        SvMemoryStream aMemStm;
+        aMemStm << rStroke;
+        rTarget.AddAction(
+            new MetaCommentAction(
+                "XPATHSTROKE_SEQ_BEGIN", 
+                0, 
+                static_cast< const sal_uInt8* >(aMemStm.GetData()), 
+                aMemStm.Seek(STREAM_SEEK_TO_END)));
+    }
+
+    void addSvtGraphicFill(const SvtGraphicFill &rFilling, GDIMetaFile& rTarget)
+    {
+        // write SvtGraphicFill
+        SvMemoryStream aMemStm;
+        aMemStm << rFilling;
+        rTarget.AddAction(
+            new MetaCommentAction(
+                "XPATHFILL_SEQ_BEGIN", 
+                0, 
+                static_cast< const sal_uInt8* >(aMemStm.GetData()), 
+                aMemStm.Seek(STREAM_SEEK_TO_END)));
+    }
+} // end of anonymous namespace
+
+//////////////////////////////////////////////////////////////////////////////
+// #121267# Tooling to internally clip geometry against internal clip regions
+
+void clipMetafileContentAgainstOwnRegions(GDIMetaFile& rSource)
+{
+    const sal_uLong nObjCount(rSource.GetActionCount());
+
+    if(!nObjCount)
+    {
+        return;
+    }
+
+    // prepare target data container and push/pop stack data
+    GDIMetaFile aTarget;
+    bool bChanged(false);
+    std::vector< basegfx::B2DPolyPolygon > aClips;
+    std::vector< sal_uInt16 > aPushFlags;
+    std::vector< MapMode > aMapModes;
+
+    // start with empty region
+    aClips.push_back(basegfx::B2DPolyPolygon());
+
+    // start with default MapMode (MAP_PIXEL)
+    aMapModes.push_back(MapMode());
+
+    for(sal_uLong i(0); i < nObjCount; ++i)
+    {
+        const MetaAction* pAction(rSource.GetAction(i));
+        const sal_uInt16 nType(pAction->GetType());
+        bool bDone(false);
+
+        // basic operation takes care of clipregion actions (four) and push/pop of these
+        // to steer the currently set clip region. There *is* an active
+        // clip region when (aClips.size() && aClips.back().count()), see
+        // below
+        switch(nType)
+        {
+            case META_CLIPREGION_ACTION :
+            {
+                const MetaClipRegionAction* pA = static_cast< const MetaClipRegionAction* >(pAction);
+
+                if(pA->IsClipping())
+                {
+                    const Region& rRegion = pA->GetRegion();
+                    const basegfx::B2DPolyPolygon aNewClip(rRegion.GetAsB2DPolyPolygon());
+
+                    aClips.back() = aNewClip;
+                }
+                else
+                {
+                    aClips.back() = basegfx::B2DPolyPolygon();
+                }
+
+                break;
+            }
+
+            case META_ISECTRECTCLIPREGION_ACTION :
+            {
+                const MetaISectRectClipRegionAction* pA = static_cast< const MetaISectRectClipRegionAction* >(pAction);
+                const Rectangle& rRect = pA->GetRect();
+
+                if(!rRect.IsEmpty() && aClips.size() && aClips.back().count())
+                {
+                    const basegfx::B2DRange aClipRange(
+                        rRect.Left(), rRect.Top(),
+                        rRect.Right(), rRect.Bottom());
+
+                    aClips.back() = basegfx::tools::clipPolyPolygonOnRange(
+                        aClips.back(),
+                        aClipRange,
+                        true, // inside
+                        false); // stroke
+                }
+                break;
+            }
+
+            case META_ISECTREGIONCLIPREGION_ACTION :
+            {
+                const MetaISectRegionClipRegionAction* pA = static_cast< const MetaISectRegionClipRegionAction* >(pAction);
+                const Region& rRegion = pA->GetRegion();
+
+                if(!rRegion.IsEmpty() && aClips.size() && aClips.back().count())
+                {
+                    const basegfx::B2DPolyPolygon aNewClip(rRegion.GetAsB2DPolyPolygon());
+
+                    aClips.back() = basegfx::tools::clipPolyPolygonOnPolyPolygon(
+                        aClips.back(), 
+                        aNewClip, 
+                        true,  // inside
+                        false); // stroke
+                }
+                break;
+            }
+
+            case META_MOVECLIPREGION_ACTION :
+            {
+                const MetaMoveClipRegionAction* pA = static_cast< const MetaMoveClipRegionAction* >(pAction);
+                const long aHorMove(pA->GetHorzMove());
+                const long aVerMove(pA->GetVertMove());
+
+                if((aHorMove || aVerMove) && aClips.size() && aClips.back().count())
+                {
+                    aClips.back().transform(
+                        basegfx::tools::createTranslateB2DHomMatrix(
+                            aHorMove,
+                            aVerMove));
+                }
+                break;
+            }
+
+            case META_PUSH_ACTION :
+            {
+                const MetaPushAction* pA = static_cast< const MetaPushAction* >(pAction);
+                const sal_uInt16 nFlags(pA->GetFlags());
+
+                aPushFlags.push_back(nFlags);
+
+                if(nFlags & PUSH_CLIPREGION)
+                {
+                    aClips.push_back(aClips.back());
+                }
+
+                if(nFlags & PUSH_MAPMODE)
+                {
+                    aMapModes.push_back(aMapModes.back());
+                }
+                break;
+            }
+
+            case META_POP_ACTION :
+            {
+                const MetaPopAction* pA = static_cast< const MetaPopAction* >(pAction);
+
+                if(aPushFlags.size())
+                {
+                    const sal_uInt16 nFlags(aPushFlags.back());
+                    aPushFlags.pop_back();
+
+                    if(nFlags & PUSH_CLIPREGION)
+                    {
+                        if(aClips.size() > 1)
+                        {
+                            aClips.pop_back();
+                        }
+                        else
+                        {
+                            OSL_ENSURE(false, "Wrong POP() in ClipRegions (!)");
+                        }
+                    }
+
+                    if(nFlags & PUSH_MAPMODE)
+                    {
+                        if(aMapModes.size() > 1)
+                        {
+                            aMapModes.pop_back();
+                        }
+                        else
+                        {
+                            OSL_ENSURE(false, "Wrong POP() in MapModes (!)");
+                        }
+                    }
+                }
+                else
+                {
+                    OSL_ENSURE(false, "Invalid pop() without push() (!)");
+                }
+
+                break;
+            }
+
+            case META_MAPMODE_ACTION :
+            {
+                const MetaMapModeAction* pA = static_cast< const MetaMapModeAction* >(pAction);
+
+                aMapModes.back() = pA->GetMapMode();
+                break;
+            }
+
+            default:
+            {
+                break;
+            }
+        }
+
+        // this area contains all actions which could potentially be clipped. Since
+        // this tooling is only a fallback (see comments in header), only the needed
+        // actions will be implemented. Extend using the pattern for the already
+        // implemented actions.
+        if(aClips.size() && aClips.back().count())
+        {
+            switch(nType)
+            {
+                //
+                // pixel actions, just check on inside
+                //
+                case META_PIXEL_ACTION :
+                {
+                    const MetaPixelAction* pA = static_cast< const MetaPixelAction* >(pAction);
+                    const Point& rPoint = pA->GetPoint();
+
+                    if(!basegfx::tools::isInside(
+                        aClips.back(), 
+                        basegfx::B2DPoint(rPoint.X(), rPoint.Y())))
+                    {
+                        // when not inside, do not add original
+                        bDone = true;
+                    }
+                    break;
+                }
+
+                case META_POINT_ACTION :
+                {
+                    const MetaPointAction* pA = static_cast< const MetaPointAction* >(pAction);
+                    const Point& rPoint = pA->GetPoint();
+
+                    if(!basegfx::tools::isInside(
+                        aClips.back(), 
+                        basegfx::B2DPoint(rPoint.X(), rPoint.Y())))
+                    {
+                        // when not inside, do not add original
+                        bDone = true;
+                    }
+                    break;
+                }
+
+                //
+                // geometry actions
+                //
+                case META_LINE_ACTION :
+                {
+                    const MetaLineAction* pA = static_cast< const MetaLineAction* >(pAction);
+                    const Point& rStart(pA->GetStartPoint());
+                    const Point& rEnd(pA->GetEndPoint());
+                    basegfx::B2DPolygon aLine;
+
+                    aLine.append(basegfx::B2DPoint(rStart.X(), rStart.Y()));
+                    aLine.append(basegfx::B2DPoint(rEnd.X(), rEnd.Y()));
+
+                    bDone = handleGeometricContent(
+                        aClips.back(),
+                        basegfx::B2DPolyPolygon(aLine),
+                        aTarget,
+                        true); // stroke
+                    break;
+                }
+
+                case META_RECT_ACTION :
+                {
+                    const MetaRectAction* pA = static_cast< const MetaRectAction* >(pAction);
+                    const Rectangle& rRect = pA->GetRect();
+
+                    if(rRect.IsEmpty())
+                    {
+                        bDone = true;
+                    }
+                    else
+                    {
+
+                        bDone = handleGeometricContent(
+                            aClips.back(),
+                            basegfx::B2DPolyPolygon(
+                                basegfx::tools::createPolygonFromRect(
+                                    basegfx::B2DRange(
+                                        rRect.Left(), rRect.Top(),
+                                        rRect.Right(), rRect.Bottom()))),
+                            aTarget,
+                            false); // stroke
+                    }
+                    break;
+                }
+
+                case META_ROUNDRECT_ACTION :
+                {
+                    const MetaRoundRectAction* pA = static_cast< const MetaRoundRectAction* >(pAction);
+                    const Rectangle& rRect = pA->GetRect();
+
+                    if(rRect.IsEmpty())
+                    {
+                        bDone = true;
+                    }
+                    else
+                    {
+                        const sal_uInt32 nHor(pA->GetHorzRound());
+                        const sal_uInt32 nVer(pA->GetVertRound());
+                        const basegfx::B2DRange aRange(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom());
+                        basegfx::B2DPolygon aOutline;
+
+                        if(nHor || nVer)
+                        {
+                            double fRadiusX((nHor * 2.0) / (aRange.getWidth() > 0.0 ? aRange.getWidth() : 1.0));
+                            double fRadiusY((nVer * 2.0) / (aRange.getHeight() > 0.0 ? aRange.getHeight() : 1.0));
+                            fRadiusX = std::max(0.0, std::min(1.0, fRadiusX));
+                            fRadiusY = std::max(0.0, std::min(1.0, fRadiusY));
+
+                            aOutline = basegfx::tools::createPolygonFromRect(aRange, fRadiusX, fRadiusY);
+                        }
+                        else
+                        {
+                            aOutline = basegfx::tools::createPolygonFromRect(aRange);
+                        }
+
+                        bDone = handleGeometricContent(
+                            aClips.back(),
+                            basegfx::B2DPolyPolygon(aOutline),
+                            aTarget,
+                            false); // stroke
+                    }
+                    break;
+                }
+
+                case META_ELLIPSE_ACTION :
+                {
+                    const MetaEllipseAction* pA = static_cast< const MetaEllipseAction* >(pAction);
+                    const Rectangle& rRect = pA->GetRect();
+
+                    if(rRect.IsEmpty())
+                    {
+                        bDone = true;
+                    }
+                    else
+                    {
+                        const basegfx::B2DRange aRange(rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom());
+
+                        bDone = handleGeometricContent(
+                            aClips.back(),
+                            basegfx::B2DPolyPolygon(
+                                basegfx::tools::createPolygonFromEllipse(
+                                    aRange.getCenter(), 
+                                    aRange.getWidth() * 0.5, 
+                                    aRange.getHeight() * 0.5)),
+                            aTarget,
+                            false); // stroke
+                    }
+                    break;
+                }
+
+                case META_ARC_ACTION :
+                {
+                    const MetaArcAction* pA = static_cast< const MetaArcAction* >(pAction);
+                    const Rectangle& rRect = pA->GetRect();
+
+                    if(rRect.IsEmpty())
+                    {
+                        bDone = true;
+                    }
+                    else
+                    {
+                        const Polygon aToolsPoly(
+                            rRect, 
+                            pA->GetStartPoint(), 
+                            pA->GetEndPoint(), 
+                            POLY_ARC);
+                        
+                        bDone = handleGeometricContent(
+                            aClips.back(),
+                            basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
+                            aTarget,
+                            true); // stroke
+                    }
+                    break;
+                }
+
+                case META_PIE_ACTION :
+                {
+                    const MetaPieAction* pA = static_cast< const MetaPieAction* >(pAction);
+                    const Rectangle& rRect = pA->GetRect();
+
+                    if(rRect.IsEmpty())
+                    {
+                        bDone = true;
+                    }
+                    else
+                    {
+                        const Polygon aToolsPoly(
+                            rRect, 
+                            pA->GetStartPoint(), 
+                            pA->GetEndPoint(), 
+                            POLY_PIE);
+
+                        bDone = handleGeometricContent(
+                            aClips.back(),
+                            basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
+                            aTarget,
+                            false); // stroke
+                    }
+                    break;
+                }
+
+                case META_CHORD_ACTION :
+                {
+                    const MetaChordAction* pA = static_cast< const MetaChordAction* >(pAction);
+                    const Rectangle& rRect = pA->GetRect();
+
+                    if(rRect.IsEmpty())
+                    {
+                        bDone = true;
+                    }
+                    else
+                    {
+                        const Polygon aToolsPoly(
+                            rRect, 
+                            pA->GetStartPoint(), 
+                            pA->GetEndPoint(), 
+                            POLY_CHORD);
+                        
+                        bDone = handleGeometricContent(
+                            aClips.back(),
+                            basegfx::B2DPolyPolygon(aToolsPoly.getB2DPolygon()),
+                            aTarget,
+                            false); // stroke
+                    }
+                    break;
+                }
+
+                case META_POLYLINE_ACTION :
+                {
+                    const MetaPolyLineAction* pA = static_cast< const MetaPolyLineAction* >(pAction);
+
+                    bDone = handleGeometricContent(
+                        aClips.back(),
+                        basegfx::B2DPolyPolygon(pA->GetPolygon().getB2DPolygon()),
+                        aTarget,
+                        true); // stroke
+                    break;
+                }
+
+                case META_POLYGON_ACTION :
+                {
+                    const MetaPolygonAction* pA = static_cast< const MetaPolygonAction* >(pAction);
+
+                    bDone = handleGeometricContent(
+                        aClips.back(),
+                        basegfx::B2DPolyPolygon(pA->GetPolygon().getB2DPolygon()),
+                        aTarget,
+                        false); // stroke
+                    break;
+                }
+
+                case META_POLYPOLYGON_ACTION :
+                {
+                    const MetaPolyPolygonAction* pA = static_cast< const MetaPolyPolygonAction* >(pAction);
+                    const PolyPolygon& rPoly = pA->GetPolyPolygon();
+
+                    bDone = handleGeometricContent(
+                        aClips.back(),
+                        rPoly.getB2DPolyPolygon(),
+                        aTarget,
+                        false); // stroke
+                    break;
+                }
+
+                //
+                // bitmap actions, create BitmapEx with alpha channel derived
+                // from clipping
+                //
+                case META_BMPEX_ACTION :
+                {
+                    const MetaBmpExAction* pA = static_cast< const MetaBmpExAction* >(pAction);
+                    const BitmapEx& rBitmapEx = pA->GetBitmapEx();
+
+                    // the logical size depends on the PrefSize of the given bitmap in
+                    // combination with the current MapMode
+                    Size aLogicalSize(rBitmapEx.GetPrefSize());
+
+                    if(MAP_PIXEL == rBitmapEx.GetPrefMapMode().GetMapUnit())
+                    {
+                        aLogicalSize = Application::GetDefaultDevice()->PixelToLogic(aLogicalSize, aMapModes.back().GetMapUnit()); 
+                    }
+                    else
+                    {
+                        aLogicalSize = OutputDevice::LogicToLogic(aLogicalSize, rBitmapEx.GetPrefMapMode(), aMapModes.back().GetMapUnit());
+                    }
+
+                    bDone = handleBitmapContent(
+                        aClips.back(), 
+                        pA->GetPoint(),
+                        aLogicalSize,
+                        rBitmapEx,
+                        aTarget);
+                    break;
+                }
+
+                case META_BMP_ACTION :
+                {
+                    const MetaBmpAction* pA = static_cast< const MetaBmpAction* >(pAction);
+                    const Bitmap& rBitmap = pA->GetBitmap();
+
+                    // the logical size depends on the PrefSize of the given bitmap in
+                    // combination with the current MapMode
+                    Size aLogicalSize(rBitmap.GetPrefSize());
+
+                    if(MAP_PIXEL == rBitmap.GetPrefMapMode().GetMapUnit())
+                    {
+                        aLogicalSize = Application::GetDefaultDevice()->PixelToLogic(aLogicalSize, aMapModes.back().GetMapUnit()); 
+                    }
+                    else
+                    {
+                        aLogicalSize = OutputDevice::LogicToLogic(aLogicalSize, rBitmap.GetPrefMapMode(), aMapModes.back().GetMapUnit());
+                    }
+
+                    bDone = handleBitmapContent(
+                        aClips.back(), 
+                        pA->GetPoint(),
+                        aLogicalSize,
+                        BitmapEx(rBitmap),
+                        aTarget);
+                    break;
+                }
+
+                case META_BMPEXSCALE_ACTION :
+                {
+                    const MetaBmpExScaleAction* pA = static_cast< const MetaBmpExScaleAction* >(pAction);
+
+                    bDone = handleBitmapContent(
+                        aClips.back(), 
+                        pA->GetPoint(),
+                        pA->GetSize(),
+                        pA->GetBitmapEx(),
+                        aTarget);
+                    break;
+                }
+
+                case META_BMPSCALE_ACTION :
+                {
+                    const MetaBmpScaleAction* pA = static_cast< const MetaBmpScaleAction* >(pAction);
+
+                    bDone = handleBitmapContent(
+                        aClips.back(), 
+                        pA->GetPoint(),
+                        pA->GetSize(),
+                        BitmapEx(pA->GetBitmap()),
+                        aTarget);
+                    break;
+                }
+
+                case META_BMPEXSCALEPART_ACTION :
+                {
+                    const MetaBmpExScalePartAction* pA = static_cast< const MetaBmpExScalePartAction* >(pAction);
+                    const BitmapEx& rBitmapEx = pA->GetBitmapEx();
+
+                    if(rBitmapEx.IsEmpty())
+                    {
+                        // empty content
+                        bDone = true;
+                    }
+                    else
+                    {
+                        BitmapEx aCroppedBitmapEx(rBitmapEx);
+                        const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize());
+
+                        if(aCropRectangle.IsEmpty())
+                        {
+                            // empty content
+                            bDone = true;
+                        }
+                        else
+                        {
+                            aCroppedBitmapEx.Crop(aCropRectangle);
+                            bDone = handleBitmapContent(
+                                aClips.back(), 
+                                pA->GetDestPoint(),
+                                pA->GetDestSize(),
+                                aCroppedBitmapEx,
+                                aTarget);
+                        }
+                    }
+                    break;
+                }
+
+                case META_BMPSCALEPART_ACTION :
+                {
+                    const MetaBmpScalePartAction* pA = static_cast< const MetaBmpScalePartAction* >(pAction);
+                    const Bitmap& rBitmap = pA->GetBitmap();
+
+                    if(rBitmap.IsEmpty())
+                    {
+                        // empty content
+                        bDone = true;
+                    }
+                    else
+                    {
+                        Bitmap aCroppedBitmap(rBitmap);
+                        const Rectangle aCropRectangle(pA->GetSrcPoint(), pA->GetSrcSize());
+
+                        if(aCropRectangle.IsEmpty())
+                        {
+                            // empty content
+                            bDone = true;
+                        }
+                        else
+                        {
+                            aCroppedBitmap.Crop(aCropRectangle);
+                            bDone = handleBitmapContent(
+                                aClips.back(), 
+                                pA->GetDestPoint(),
+                                pA->GetDestSize(),
+                                BitmapEx(aCroppedBitmap),
+                                aTarget);
+                        }
+                    }
+                    break;
+                }
+
+                //
+                // need to handle all those 'hacks' which hide data in comments
+                //
+                case META_COMMENT_ACTION :
+                {
+                    const MetaCommentAction* pA = static_cast< const MetaCommentAction* >(pAction);
+                    const ByteString& rComment = pA->GetComment();
+
+                    if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XGRAD_SEQ_BEGIN"))
+                    {
+                        // nothing to do; this just means that between here and XGRAD_SEQ_END
+                        // exists a META_GRADIENTEX_ACTION mixed with Xor-tricked painiting
+                        // commands. This comment is used to scan over these and filter for
+                        // the gradient action. It is needed to support META_GRADIENTEX_ACTION 
+                        // in this processor to solve usages.
+                    }
+                    else if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XPATHFILL_SEQ_BEGIN"))
+                    {
+                        SvtGraphicFill aFilling;
+                        PolyPolygon aPath;
+
+                        {   // read SvtGraphicFill
+                            SvMemoryStream aMemStm((void*)pA->GetData(), pA->GetDataSize(),STREAM_READ);
+                            aMemStm >> aFilling;
+                        }
+
+                        aFilling.getPath(aPath);
+
+                        if(aPath.Count())
+                        {
+                            const basegfx::B2DPolyPolygon aSource(aPath.getB2DPolyPolygon());
+                            const basegfx::B2DPolyPolygon aResult(
+                                basegfx::tools::clipPolyPolygonOnPolyPolygon(
+                                    aSource,
+                                    aClips.back(),
+                                    true, // inside
+                                    false)); // stroke
+
+                            if(aResult.count())
+                            {
+                                if(aResult != aSource)
+                                {
+                                    // add clipped geometry
+                                    aFilling.setPath(PolyPolygon(aResult));
+                                    addSvtGraphicFill(aFilling, aTarget);
+                                    bDone = true;
+                                }
+                            }
+                            else
+                            {
+                                // exchange with empty polygon
+                                aFilling.setPath(PolyPolygon());
+                                addSvtGraphicFill(aFilling, aTarget);
+                                bDone = true;
+                            }
+                        }
+                    }
+                    else if(COMPARE_EQUAL == rComment.CompareIgnoreCaseToAscii("XPATHSTROKE_SEQ_BEGIN"))
+                    {
+                        SvtGraphicStroke aStroke;
+                        Polygon aPath;
+
+                        {   // read SvtGraphicFill
+                            SvMemoryStream aMemStm((void*)pA->GetData(), pA->GetDataSize(),STREAM_READ);
+                            aMemStm >> aStroke;
+                        }
+
+                        aStroke.getPath(aPath);
+
+                        if(aPath.GetSize())
+                        {
+                            const basegfx::B2DPolygon aSource(aPath.getB2DPolygon());
+                            const basegfx::B2DPolyPolygon aResult(
+                                basegfx::tools::clipPolygonOnPolyPolygon(
+                                    aSource,
+                                    aClips.back(),
+                                    true, // inside
+                                    true)); // stroke
+
+                            if(aResult.count())
+                            {
+                                if(aResult.count() > 1 || aResult.getB2DPolygon(0) != aSource)
+                                {
+                                    // add clipped geometry
+                                    for(sal_uInt32 a(0); a < aResult.count(); a++)
+                                    {
+                                        aStroke.setPath(Polygon(aResult.getB2DPolygon(a)));
+                                        addSvtGraphicStroke(aStroke, aTarget);
+                                    }
+
+                                    bDone = true;
+                                }
+                            }
+                            else
+                            {
+                                // exchange with empty polygon
+                                aStroke.setPath(Polygon());
+                                addSvtGraphicStroke(aStroke, aTarget);
+                                bDone = true;
+                            }
+
+                        }
+                    }
+                    break;
+                }
+
+                //
+                // need to handle gradient fills (hopefully only unroated ones)
+                //
+
+                case META_GRADIENT_ACTION :
+                {
+                    const MetaGradientAction* pA = static_cast< const MetaGradientAction* >(pAction);
+                    const Rectangle& rRect = pA->GetRect();
+
+                    if(rRect.IsEmpty())
+                    {
+                        bDone = true;
+                    }
+                    else
+                    {
+                        bDone = handleGradientContent(
+                            aClips.back(),
+                            basegfx::B2DPolyPolygon(
+                                basegfx::tools::createPolygonFromRect(
+                                    basegfx::B2DRange(
+                                        rRect.Left(), rRect.Top(),
+                                        rRect.Right(), rRect.Bottom()))),
+                            pA->GetGradient(),
+                            aTarget);
+                    }
+
+
+                    break;
+                }
+
+                case META_GRADIENTEX_ACTION :
+                {
+                    const MetaGradientExAction* pA = static_cast< const MetaGradientExAction* >(pAction);
+                    const PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
+
+                    bDone = handleGradientContent(
+                        aClips.back(),
+                        rPolyPoly.getB2DPolyPolygon(),
+                        pA->GetGradient(),
+                        aTarget);
+                    break;
+                }
+
+                // not (yet) supported actions
+                //
+                // META_NULL_ACTION
+                // META_TEXT_ACTION
+                // META_TEXTARRAY_ACTION
+                // META_STRETCHTEXT_ACTION
+                // META_TEXTRECT_ACTION
+                // META_MASK_ACTION
+                // META_MASKSCALE_ACTION
+                // META_MASKSCALEPART_ACTION
+                // META_HATCH_ACTION
+                // META_WALLPAPER_ACTION
+                // META_FILLCOLOR_ACTION
+                // META_TEXTCOLOR_ACTION
+                // META_TEXTFILLCOLOR_ACTION
+                // META_TEXTALIGN_ACTION
+                // META_MAPMODE_ACTION
+                // META_FONT_ACTION
+                // META_TRANSPARENT_ACTION
+                // META_EPS_ACTION
+                // META_REFPOINT_ACTION
+                // META_TEXTLINECOLOR_ACTION
+                // META_TEXTLINE_ACTION
+                // META_FLOATTRANSPARENT_ACTION
+                // META_LAYOUTMODE_ACTION
+                // META_TEXTLANGUAGE_ACTION
+                // META_OVERLINECOLOR_ACTION
+
+                // if an action is not handled at all, it will simply get copied to the
+                // target (see below). This is the default for all non-implemented actions
+                default:
+                {
+                    break;
+                }
+            }
+        }
+
+        if(bDone)
+        {
+            bChanged = true;
+        }
+        else
+        {
+            const_cast< MetaAction* >(pAction)->Duplicate();
+            aTarget.AddAction(const_cast< MetaAction* >(pAction));
+        }
+    }
+
+    if(bChanged)
+    {
+        // when changed, copy back and do not forget to set MapMode 
+        // and PrefSize
+        aTarget.SetPrefMapMode(rSource.GetPrefMapMode());
+        aTarget.SetPrefSize(rSource.GetPrefSize());
+        rSource = aTarget;
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+bool VCL_DLLPUBLIC usesClipActions(const GDIMetaFile& rSource)
+{
+    const sal_uLong nObjCount(rSource.GetActionCount());
+
+    for(sal_uLong i(0); i < nObjCount; ++i)
+    {
+        const MetaAction* pAction(rSource.GetAction(i));
+        const sal_uInt16 nType(pAction->GetType());
+
+        switch(nType)
+        {
+            case META_CLIPREGION_ACTION :
+            case META_ISECTRECTCLIPREGION_ACTION :
+            case META_ISECTREGIONCLIPREGION_ACTION :
+            case META_MOVECLIPREGION_ACTION :
+            {
+                return true;
+                break;
+            }
+
+            default: break;
+        }
+    }
+
+    return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// eof

Propchange: incubator/ooo/trunk/main/vcl/source/gdi/gdimetafiletools.cxx
------------------------------------------------------------------------------
    svn:executable = *



Mime
View raw message