You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by al...@apache.org on 2011/12/12 12:00:26 UTC

svn commit: r1213186 - in /incubator/ooo/branches/alg/svgreplacement/main: basegfx/inc/basegfx/polygon/ basegfx/source/polygon/ svgio/inc/svgio/svgreader/ svgio/source/svgreader/

Author: alg
Date: Mon Dec 12 11:00:25 2011
New Revision: 1213186

URL: http://svn.apache.org/viewvc?rev=1213186&view=rev
Log:
svg: added support fo rfillRule in clipPath and normal geometry

Modified:
    incubator/ooo/branches/alg/svgreplacement/main/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx
    incubator/ooo/branches/alg/svgreplacement/main/basegfx/source/polygon/b2dpolypolygoncutter.cxx
    incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgstyleattributes.hxx
    incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgtoken.hxx
    incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgtools.hxx
    incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstyleattributes.cxx
    incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgtoken.cxx
    incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgtools.cxx

Modified: incubator/ooo/branches/alg/svgreplacement/main/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx?rev=1213186&r1=1213185&r2=1213186&view=diff
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx (original)
+++ incubator/ooo/branches/alg/svgreplacement/main/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx Mon Dec 12 11:00:25 2011
@@ -65,6 +65,13 @@ namespace basegfx
 		// can be combined for logical polygon operations or polygon clipping.
 		B2DPolyPolygon stripDispensablePolygons(const B2DPolyPolygon& rCandidate, bool bKeepAboveZero = false);
 
+        // geometrically convert PolyPolygons which are proposed to use nonzero fill rule
+        // to a representation where evenodd paint will give the same result. To do this
+        // all intersections and self-intersections get solved (the polygons will be rearranged
+        // if needed). Then all polygons which are inside another one with the same orientation
+        // get deleted
+        B2DPolyPolygon createNonzeroConform(const B2DPolyPolygon& rCandidate);
+
         // For convenience: The four basic operations OR, XOR, AND and DIFF for
         // two PolyPolygons. These are combinations of the above methods. To not be forced
         // to do evtl. already done preparations twice, You have to do the operations Yourself.

Modified: incubator/ooo/branches/alg/svgreplacement/main/basegfx/source/polygon/b2dpolypolygoncutter.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/basegfx/source/polygon/b2dpolypolygoncutter.cxx?rev=1213186&r1=1213185&r2=1213186&view=diff
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/basegfx/source/polygon/b2dpolypolygoncutter.cxx (original)
+++ incubator/ooo/branches/alg/svgreplacement/main/basegfx/source/polygon/b2dpolypolygoncutter.cxx Mon Dec 12 11:00:25 2011
@@ -701,6 +701,94 @@ namespace basegfx
 
 		//////////////////////////////////////////////////////////////////////////////
 
+        B2DPolyPolygon createNonzeroConform(const B2DPolyPolygon& rCandidate)
+        {
+            B2DPolyPolygon aCandidate;
+
+            // remove all self-intersections and intersections
+            if(rCandidate.count() == 1)
+            {
+                aCandidate = basegfx::tools::solveCrossovers(rCandidate.getB2DPolygon(0));
+            }
+            else
+            {
+                aCandidate = basegfx::tools::solveCrossovers(rCandidate);
+            }
+
+            // cleanup evtl. neutral polygons
+            aCandidate = basegfx::tools::stripNeutralPolygons(aCandidate);
+
+            // remove all polygons which have the same orientation as the polygon they are directly contained in
+            const sal_uInt32 nCount(aCandidate.count());
+            
+            if(nCount > 1)
+            {
+                sal_uInt32 a, b;
+                ::std::vector< StripHelper > aHelpers;
+                aHelpers.resize(nCount);
+
+                for(a = 0; a < nCount; a++)
+                {
+                    const B2DPolygon aCand(aCandidate.getB2DPolygon(a));
+                    StripHelper* pNewHelper = &(aHelpers[a]);
+                    pNewHelper->maRange = tools::getRange(aCand);
+                    pNewHelper->meOrinetation = tools::getOrientation(aCand);
+
+                    // initialize with own orientation
+                    pNewHelper->mnDepth = (ORIENTATION_NEGATIVE == pNewHelper->meOrinetation ? -1 : 1);
+                }
+
+                for(a = 0; a < nCount - 1; a++)
+                {
+                    const B2DPolygon aCandA(aCandidate.getB2DPolygon(a));
+                    StripHelper& rHelperA = aHelpers[a];
+                    
+                    for(b = a + 1; b < nCount; b++)
+                    {
+                        const B2DPolygon aCandB(aCandidate.getB2DPolygon(b));
+                        StripHelper& rHelperB = aHelpers[b];
+                        const bool bAInB(rHelperB.maRange.isInside(rHelperA.maRange) && tools::isInside(aCandB, aCandA, true));
+
+                        if(bAInB)
+                        {
+                            // A is inside B, add orientation of B to A
+                            rHelperA.mnDepth += (ORIENTATION_NEGATIVE == rHelperB.meOrinetation ? -1 : 1);
+                        }
+
+                        const bool bBInA(rHelperA.maRange.isInside(rHelperB.maRange) && tools::isInside(aCandA, aCandB, true));
+
+                        if(bBInA)
+                        {
+                            // B is inside A, add orientation of A to B
+                            rHelperB.mnDepth += (ORIENTATION_NEGATIVE == rHelperA.meOrinetation ? -1 : 1);
+                        }
+                    }
+                }
+
+                const B2DPolyPolygon aSource(aCandidate);
+                aCandidate.clear();
+
+                for(a = 0L; a < nCount; a++)
+                {
+                    const StripHelper& rHelper = aHelpers[a];
+                    // for contained unequal oriented polygons sum will be 0
+                    // for contained equal it will be >=2 or <=-2
+                    // for free polygons (not contained) it will be 1 or -1
+                    // -> accept all which are >=-1 && <= 1
+                    bool bAcceptEntry(rHelper.mnDepth >= -1 && rHelper.mnDepth <= 1);
+
+                    if(bAcceptEntry)
+                    {
+                        aCandidate.append(aSource.getB2DPolygon(a));
+                    }
+                }
+            }
+
+            return aCandidate;
+        }
+
+        //////////////////////////////////////////////////////////////////////////////
+
 		B2DPolyPolygon stripDispensablePolygons(const B2DPolyPolygon& rCandidate, bool bKeepAboveZero)
 		{
 			const sal_uInt32 nCount(rCandidate.count());

Modified: incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgstyleattributes.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgstyleattributes.hxx?rev=1213186&r1=1213185&r2=1213186&view=diff
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgstyleattributes.hxx (original)
+++ incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgstyleattributes.hxx Mon Dec 12 11:00:25 2011
@@ -179,6 +179,9 @@ namespace svgio
             // vaules for fill, stroke, strokeWidth and others
             bool                        mbIsClipPathContent : 1;
 
+            // ClipRule setting (only valid wne mbIsClipPathContent == true)
+            bool                        mbClipRule : 1; // true == nonzero(default), false == evenodd
+
             /// internal helpers
             void add_fillGradient(
                 const basegfx::B2DPolyPolygon& rPath, 
@@ -328,7 +331,6 @@ namespace svgio
             // MaskXLink content
             const rtl::OUString getMaskXLink() const { return maMaskXLink; }
             void setMaskXLink(const rtl::OUString& rNew) { maMaskXLink = rNew; }
-
         };
     } // end of namespace svgreader
 } // end of namespace svgio

Modified: incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgtoken.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgtoken.hxx?rev=1213186&r1=1213185&r2=1213186&view=diff
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgtoken.hxx (original)
+++ incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgtoken.hxx Mon Dec 12 11:00:25 2011
@@ -90,6 +90,7 @@ namespace svgio
             SVGTokenClipPathUnits,
             SVGTokenMaskUnits,
             SVGTokenMaskContentUnits,
+            SVGTokenClipRule,
 
             // AspectRatio and params
             SVGTokenPreserveAspectRatio,

Modified: incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgtools.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgtools.hxx?rev=1213186&r1=1213185&r2=1213186&view=diff
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgtools.hxx (original)
+++ incubator/ooo/branches/alg/svgreplacement/main/svgio/inc/svgio/svgreader/svgtools.hxx Mon Dec 12 11:00:25 2011
@@ -45,6 +45,8 @@ namespace svgio
         {
             static const rtl::OUString aStrUserSpaceOnUse;
             static const rtl::OUString aStrObjectBoundingBox;
+            static const rtl::OUString aStrNonzero;
+            static const rtl::OUString aStrEvenOdd;
         };
 
         enum SvgUnits

Modified: incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstyleattributes.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstyleattributes.cxx?rev=1213186&r1=1213185&r2=1213186&view=diff
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstyleattributes.cxx (original)
+++ incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstyleattributes.cxx Mon Dec 12 11:00:25 2011
@@ -36,6 +36,8 @@
 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
 #include <svgio/svgreader/svgclippathnode.hxx>
 #include <svgio/svgreader/svgmasknode.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
 
 //////////////////////////////////////////////////////////////////////////////
 
@@ -649,13 +651,23 @@ namespace svgio
             }
 
             drawinglayer::primitive2d::Primitive2DVector aNewPrimitives;
+            basegfx::B2DPolyPolygon aPath(rPath);
+            const bool bNeedToCheckClipRule(SVGTokenPath == mrOwner.getType() || SVGTokenPolygon == mrOwner.getType());
+            const bool bClipPathIsNonzero(!bIsLine && bNeedToCheckClipRule && mbIsClipPathContent && mbClipRule);
+            const bool bFillRuleIsNonzero(!bIsLine && bNeedToCheckClipRule && !mbIsClipPathContent && getFillRule());
+
+            if(bClipPathIsNonzero || bFillRuleIsNonzero)
+            {
+                // nonzero is wanted, solve geometrically (see description on basegfx)
+                aPath = basegfx::tools::createNonzeroConform(aPath);
+            }
 
             if(!bIsLine)
             {
-                add_fill(rPath, aNewPrimitives, aGeoRange);
+                add_fill(aPath, aNewPrimitives, aGeoRange);
             }
 
-            add_stroke(rPath, aNewPrimitives, aGeoRange);
+            add_stroke(aPath, aNewPrimitives, aGeoRange);
 
             if(pTransform && !aNewPrimitives.empty())
             {
@@ -704,7 +716,8 @@ namespace svgio
 
             maFillRule(true),
             maFillRuleSet(false),
-            mbIsClipPathContent(SVGTokenClipPathNode == mrOwner.getType())
+            mbIsClipPathContent(SVGTokenClipPathNode == mrOwner.getType()),
+            mbClipRule(true)
         {
             if(!mbIsClipPathContent)
             {
@@ -763,15 +776,12 @@ namespace svgio
                 {
                     if(aContent.getLength())
                     {
-                        static rtl::OUString aStrNonzero(rtl::OUString::createFromAscii("nonzero"));
-                        static rtl::OUString aStrEvenOdd(rtl::OUString::createFromAscii("evenodd"));
-
-                        if(aContent.match(aStrNonzero))
+                        if(aContent.match(commonStrings::aStrNonzero))
                         {
                             maFillRule = true;
                             maFillRuleSet = true;
                         }
-                        else if(aContent.match(aStrEvenOdd))
+                        else if(aContent.match(commonStrings::aStrEvenOdd))
                         {
                             maFillRule = false;
                             maFillRuleSet = true;
@@ -1258,6 +1268,21 @@ namespace svgio
                     readLocalUrl(aContent, maMaskXLink);
                     break;
                 }
+                case SVGTokenClipRule:
+                {
+                    if(aContent.getLength())
+                    {
+                        if(aContent.match(commonStrings::aStrNonzero))
+                        {
+                            mbClipRule = true;
+                        }
+                        else if(aContent.match(commonStrings::aStrEvenOdd))
+                        {
+                            mbClipRule = false;
+                        }
+                    }
+                    break;
+                }
             }
         }
 

Modified: incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgtoken.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgtoken.cxx?rev=1213186&r1=1213185&r2=1213186&view=diff
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgtoken.cxx (original)
+++ incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgtoken.cxx Mon Dec 12 11:00:25 2011
@@ -81,6 +81,7 @@ namespace svgio
         static rtl::OUString aSVGStrClipPathUnits(rtl::OUString::createFromAscii("clipPathUnits")); 
         static rtl::OUString aSVGStrMaskUnits(rtl::OUString::createFromAscii("maskUnits")); 
         static rtl::OUString aSVGStrMaskContentUnits(rtl::OUString::createFromAscii("maskContentUnits")); 
+        static rtl::OUString aSVGStrClipRule(rtl::OUString::createFromAscii("clip-rule")); 
 
         static rtl::OUString aSVGStrPreserveAspectRatio(rtl::OUString::createFromAscii("preserveAspectRatio")); 
         static rtl::OUString aSVGStrDefer(rtl::OUString::createFromAscii("defer")); 
@@ -204,6 +205,7 @@ namespace svgio
                 aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrClipPathUnits, SVGTokenClipPathUnits));
                 aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMaskUnits, SVGTokenMaskUnits));
                 aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrMaskContentUnits, SVGTokenMaskContentUnits));
+                aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrClipRule, SVGTokenClipRule));
 
                 aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrPreserveAspectRatio, SVGTokenPreserveAspectRatio));
                 aSVGTokenMapperList.insert(SVGTokenValueType(aSVGStrDefer, SVGTokenDefer));

Modified: incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgtools.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgtools.cxx?rev=1213186&r1=1213185&r2=1213186&view=diff
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgtools.cxx (original)
+++ incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgtools.cxx Mon Dec 12 11:00:25 2011
@@ -49,6 +49,8 @@ namespace svgio
         // common non-token strings
         const rtl::OUString commonStrings::aStrUserSpaceOnUse(rtl::OUString::createFromAscii("userSpaceOnUse"));
         const rtl::OUString commonStrings::aStrObjectBoundingBox(rtl::OUString::createFromAscii("objectBoundingBox"));
+        const rtl::OUString commonStrings::aStrNonzero(rtl::OUString::createFromAscii("nonzero"));
+        const rtl::OUString commonStrings::aStrEvenOdd(rtl::OUString::createFromAscii("evenodd"));
 
         basegfx::B2DHomMatrix SvgAspectRatio::createLinearMapping(const basegfx::B2DRange& rTarget, const basegfx::B2DRange& rSource)
         {