[Libreoffice-commits] .: 3 commits - filter/source

Thorsten Behrens thorsten at kemper.freedesktop.org
Mon Feb 14 01:32:20 PST 2011


 filter/source/svg/svgwriter.cxx |  369 +++++++++++++++++++++++++++++++++-------
 filter/source/svg/svgwriter.hxx |   13 +
 2 files changed, 324 insertions(+), 58 deletions(-)

New commits:
commit b6bd3fd33adcffbf467250f1bb87d4a02f85cad3
Author: Kurosawa Takeshi <taken.spc at gmail.com>
Date:   Fri Feb 11 19:29:41 2011 +0900

    Export transparencies as SVG <mask>s
    
    With this patch, SVG export filter supports solid and gradient tranparencies in all fill styles.

diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index 15a61e7..c3f459b 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -39,6 +39,7 @@
 static const char	aXMLElemG[] = "g";
 static const char	aXMLElemDefs[] = "defs";
 static const char	aXMLElemClipPath[] = "clipPath";
+static const char	aXMLElemMask[] = "mask";
 static const char	aXMLElemPattern[] = "pattern";
 static const char	aXMLElemLinearGradient[] = "linearGradient";
 static const char	aXMLElemStop[] = "stop";
@@ -390,7 +391,8 @@ SVGActionWriter::SVGActionWriter( SvXMLExport& rExport, SVGFontExport& rFontExpo
     mbClipAttrChanged( sal_False ),
     mnCurClipId( 1 ),
     mnCurPatternId( 1 ),
-    mnCurGradientId( 1 )
+    mnCurGradientId( 1 ),
+    mnCurMaskId( 1 )
 {
     mpVDev = new VirtualDevice;
     mpVDev->EnableOutput( sal_False );
@@ -908,6 +910,73 @@ Color SVGActionWriter::ImplGetGradientColor( const Color& rStartColor,
 
 // -----------------------------------------------------------------------------
 
+void SVGActionWriter::ImplWriteMask( GDIMetaFile& rMtf,
+                                     const Point& rDestPt,
+                                     const Size& rDestSize,
+                                     const Gradient& rGradient,
+                                     const NMSP_RTL::OUString* pStyle,
+                                     sal_uInt32 nWriteFlags )
+{
+    Point          aSrcPt( rMtf.GetPrefMapMode().GetOrigin() );
+    const Size     aSrcSize( rMtf.GetPrefSize() );
+    const double   fScaleX = aSrcSize.Width() ? (double) rDestSize.Width() / aSrcSize.Width() : 1.0;
+    const double   fScaleY = aSrcSize.Height() ? (double) rDestSize.Height() / aSrcSize.Height() : 1.0;
+    long           nMoveX, nMoveY;
+
+    if( fScaleX != 1.0 || fScaleY != 1.0 )
+    {
+        rMtf.Scale( fScaleX, fScaleY );
+        aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
+    }
+
+    nMoveX = rDestPt.X() - aSrcPt.X(), nMoveY = rDestPt.Y() - aSrcPt.Y();
+
+    if( nMoveX || nMoveY )
+        rMtf.Move( nMoveX, nMoveY );
+
+    FastString aMaskId;
+    aMaskId += B2UCONST( "mask" );
+    aMaskId += GetValueString( ImplGetNextMaskId() );
+
+    {
+        SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, TRUE, TRUE );
+
+        mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aMaskId.GetString() );
+        {
+            SvXMLElementExport aElemMask( mrExport, XML_NAMESPACE_NONE, aXMLElemMask, TRUE, TRUE );
+
+            const PolyPolygon aPolyPolygon( PolyPolygon( Rectangle( rDestPt, rDestSize ) ) );
+            Gradient aGradient( rGradient );
+
+            // swap gradient stops to adopt SVG mask
+            Color aTmpColor( aGradient.GetStartColor() );
+            sal_uInt16 nTmpIntensity( aGradient.GetStartIntensity() );
+            aGradient.SetStartColor( aGradient.GetEndColor() );
+            aGradient.SetStartIntensity( aGradient.GetEndIntensity() ) ;
+            aGradient.SetEndColor( aTmpColor );
+            aGradient.SetEndIntensity( nTmpIntensity );
+
+            ImplWriteGradientEx( aPolyPolygon, aGradient, pStyle, nWriteFlags );
+        }
+    }
+
+    FastString aMaskStyle;
+    aMaskStyle += B2UCONST( "mask:url(#" );
+    aMaskStyle += aMaskId.GetString();
+    aMaskStyle += B2UCONST( ")" );
+    mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aMaskStyle.GetString() );
+
+    {
+        SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
+
+        mpVDev->Push();
+        ImplWriteActions( rMtf, pStyle, nWriteFlags );
+        mpVDev->Pop();
+    }
+}
+
+// -----------------------------------------------------------------------------
+
 void SVGActionWriter::ImplWriteText( const Point& rPos, const String& rText, 
                                      const sal_Int32* pDXArray, long nWidth,
                                      const NMSP_RTL::OUString* pStyle )
@@ -1508,28 +1577,8 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
                 {
                     const MetaFloatTransparentAction*	pA = (const MetaFloatTransparentAction*) pAction;
                     GDIMetaFile							aTmpMtf( pA->GetGDIMetaFile() );
-                    Point								aSrcPt( aTmpMtf.GetPrefMapMode().GetOrigin() );
-                    const Size							aSrcSize( aTmpMtf.GetPrefSize() );
-                    const Point							aDestPt( pA->GetPoint() );
-                    const Size							aDestSize( pA->GetSize() );
-                    const double						fScaleX = aSrcSize.Width() ? (double) aDestSize.Width() / aSrcSize.Width() : 1.0;
-                    const double						fScaleY = aSrcSize.Height() ? (double) aDestSize.Height() / aSrcSize.Height() : 1.0;
-                    long								nMoveX, nMoveY;
-
-                    if( fScaleX != 1.0 || fScaleY != 1.0 )
-                    {
-                        aTmpMtf.Scale( fScaleX, fScaleY );
-                        aSrcPt.X() = FRound( aSrcPt.X() * fScaleX ), aSrcPt.Y() = FRound( aSrcPt.Y() * fScaleY );
-                    }
-
-                    nMoveX = aDestPt.X() - aSrcPt.X(), nMoveY = aDestPt.Y() - aSrcPt.Y();
-
-                    if( nMoveX || nMoveY )
-                        aTmpMtf.Move( nMoveX, nMoveY );
-
-                    mpVDev->Push();
-                    ImplWriteActions( aTmpMtf, pStyle, nWriteFlags );
-                    mpVDev->Pop();
+                    ImplWriteMask( aTmpMtf, pA->GetPoint(), pA->GetSize(),
+                                   pA->GetGradient(), pStyle, nWriteFlags  );
                 }
             }
             break;
diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx
index f5928d1..26470af 100644
--- a/filter/source/svg/svgwriter.hxx
+++ b/filter/source/svg/svgwriter.hxx
@@ -166,6 +166,7 @@ private:
     sal_Int32				mnCurClipId;
     sal_Int32				mnCurPatternId;
     sal_Int32				mnCurGradientId;
+    sal_Int32				mnCurMaskId;
     Stack					maContextStack;
     VirtualDevice*			mpVDev;
     MapMode					maTargetMapMode;
@@ -192,6 +193,7 @@ private:
     void					ImplWriteGradientStop( const Color& rColor, double fOffset );
     Color					ImplGetColorWithIntensity( const Color& rColor, USHORT nIntensity );
     Color					ImplGetGradientColor( const Color& rStartColor, const Color& rEndColor, double fOffset );
+    void					ImplWriteMask( GDIMetaFile& rMtf, const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient, const ::rtl::OUString* pStyle, sal_uInt32 nWriteFlags );
     void					ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, const ::rtl::OUString* pStyle = NULL );
     void                ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, const ::rtl::OUString* pStyle, Color aTextColor );
     void					ImplWriteBmp( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz, const ::rtl::OUString* pStyle = NULL );
@@ -203,6 +205,7 @@ private:
     sal_Int32				ImplGetNextClipId() { return mnCurClipId++; }
     sal_Int32				ImplGetNextPatternId() { return mnCurPatternId++; }
     sal_Int32				ImplGetNextGradientId() { return mnCurGradientId++; }
+    sal_Int32				ImplGetNextMaskId() { return mnCurMaskId++; }
 
 public:
 
commit 08b4a1c24457f2ae3d3b664272049be7c3a25eca
Author: Kurosawa Takeshi <taken.spc at gmail.com>
Date:   Fri Feb 11 19:23:10 2011 +0900

    Export linear and axial gradients as SVG <linearGraidents>s

diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index b0e2a0f..15a61e7 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -40,6 +40,8 @@ static const char	aXMLElemG[] = "g";
 static const char	aXMLElemDefs[] = "defs";
 static const char	aXMLElemClipPath[] = "clipPath";
 static const char	aXMLElemPattern[] = "pattern";
+static const char	aXMLElemLinearGradient[] = "linearGradient";
+static const char	aXMLElemStop[] = "stop";
 static const char	aXMLElemLine[] = "line";
 static const char	aXMLElemRect[] = "rect";
 static const char	aXMLElemEllipse[] = "ellipse";
@@ -68,6 +70,8 @@ static const char	aXMLAttrWidth[] = "width";
 static const char	aXMLAttrHeight[] = "height";
 static const char	aXMLAttrPoints[] = "points";
 static const char	aXMLAttrPatternUnits[] = "patternUnits";
+static const char	aXMLAttrGradientUnits[] = "gradientUnits";
+static const char	aXMLAttrOffset[] = "offset";
 static const char	aXMLAttrXLinkHRef[] = "xlink:href";
 
 // --------------
@@ -227,6 +231,21 @@ NMSP_RTL::OUString SVGAttributeWriter::GetFontStyle( const Font& rFont )
 
 // -----------------------------------------------------------------------------
 
+NMSP_RTL::OUString SVGAttributeWriter::GetColorStyle( const Color& rColor )
+{
+    FastString aStyle;
+    aStyle += B2UCONST( "rgb(" );
+    aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rColor.GetRed() );
+    aStyle += B2UCONST( "," );
+    aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rColor.GetGreen() );
+    aStyle += B2UCONST( "," );
+    aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rColor.GetBlue() );
+    aStyle += B2UCONST( ")" );
+    return aStyle.GetString();
+}
+
+// -----------------------------------------------------------------------------
+
 NMSP_RTL::OUString SVGAttributeWriter::GetPaintStyle( const Color& rLineColor, const Color& rFillColor, const LineInfo* pLineInfo )
 {
     FastString aStyle;
@@ -239,13 +258,7 @@ NMSP_RTL::OUString SVGAttributeWriter::GetPaintStyle( const Color& rLineColor, c
     else
     {
         // line color value in rgb
-        aStyle += B2UCONST( "rgb(" );
-        aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetRed() );
-        aStyle += B2UCONST( "," );
-        aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetGreen() );
-        aStyle += B2UCONST( "," );
-        aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rLineColor.GetBlue() );
-        aStyle += B2UCONST( ")" );
+        aStyle += GetColorStyle( rLineColor );
 
         // line color opacity in percent if neccessary
         if( rLineColor.GetTransparency() )
@@ -327,13 +340,7 @@ NMSP_RTL::OUString SVGAttributeWriter::GetPaintStyle( const Color& rLineColor, c
     else
     {
         // fill color value in rgb
-        aStyle += B2UCONST( "rgb(" );
-        aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetRed() );
-        aStyle += B2UCONST( "," );
-        aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetGreen() );
-        aStyle += B2UCONST( "," );
-        aStyle += NMSP_RTL::OUString::valueOf( (sal_Int32) rFillColor.GetBlue() );
-        aStyle += B2UCONST( ")" );
+        aStyle += GetColorStyle( rFillColor );
 
         // fill color opacity in percent if neccessary
         if( rFillColor.GetTransparency() )
@@ -382,7 +389,8 @@ SVGActionWriter::SVGActionWriter( SvXMLExport& rExport, SVGFontExport& rFontExpo
     mpContext( NULL ),
     mbClipAttrChanged( sal_False ),
     mnCurClipId( 1 ),
-    mnCurPatternId( 1 )
+    mnCurPatternId( 1 ),
+    mnCurGradientId( 1 )
 {
     mpVDev = new VirtualDevice;
     mpVDev->EnableOutput( sal_False );
@@ -732,7 +740,170 @@ void SVGActionWriter::ImplWritePattern( const PolyPolygon& rPolyPoly,
 void SVGActionWriter::ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient,
                                            const NMSP_RTL::OUString* pStyle, sal_uInt32 nWriteFlags )
 {
-    ImplWritePattern( rPolyPoly, NULL, &rGradient, pStyle, nWriteFlags );
+    if ( rGradient.GetStyle() == GRADIENT_LINEAR ||
+         rGradient.GetStyle() == GRADIENT_AXIAL )
+    {
+        ImplWriteGradientLinear( rPolyPoly, rGradient );
+    }
+    else
+    {
+        ImplWritePattern( rPolyPoly, NULL, &rGradient, pStyle, nWriteFlags );
+    }
+}
+
+void SVGActionWriter::ImplWriteGradientLinear( const PolyPolygon& rPolyPoly,
+                                               const Gradient& rGradient )
+{
+    if( rPolyPoly.Count() )
+    {
+        SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
+
+        FastString aGradientId;
+        aGradientId += B2UCONST( "gradient" );
+        aGradientId += GetValueString( ImplGetNextGradientId() );
+
+        {
+            SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, TRUE, TRUE );
+
+            mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aGradientId.GetString() );
+            {
+                Rectangle aTmpRect;
+                Point aTmpCenter;
+                rGradient.GetBoundRect( rPolyPoly.GetBoundRect(), aTmpRect, aTmpCenter );
+                const Rectangle aRect( ImplMap( aTmpRect) );
+                const Point aCenter( ImplMap( aTmpCenter) );
+                const sal_uInt16 nAngle = rGradient.GetAngle() % 3600;
+
+                Polygon aPoly( 2 );
+                // Setting x value of a gradient vector to rotation center to
+                // place a gradient vector in a target polygon.
+                // This would help editing it in SVG editors like inkscape.
+                aPoly[ 0 ].X() = aPoly[ 1 ].X() = aCenter.X();
+                aPoly[ 0 ].Y() = aRect.Top();
+                aPoly[ 1 ].Y() = aRect.Bottom();
+                aPoly.Rotate( aCenter, nAngle );
+
+                mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, GetValueString( aPoly[ 0 ].X() ) );
+                mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, GetValueString( aPoly[ 0 ].Y() ) );
+                mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, GetValueString( aPoly[ 1 ].X() ) );
+                mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, GetValueString( aPoly[ 1 ].Y() ) );
+
+                mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrGradientUnits,
+                                       NMSP_RTL::OUString( RTL_CONSTASCII_USTRINGPARAM( "userSpaceOnUse" ) ) );
+            }
+
+            {
+                SvXMLElementExport aElemLinearGradient( mrExport, XML_NAMESPACE_NONE, aXMLElemLinearGradient, TRUE, TRUE );
+
+                const Color aStartColor = ImplGetColorWithIntensity( rGradient.GetStartColor(), rGradient.GetStartIntensity() );
+                const Color aEndColor = ImplGetColorWithIntensity( rGradient.GetEndColor(), rGradient.GetEndIntensity() );
+                double fBorderOffset = rGradient.GetBorder() / 100.0;
+                const sal_uInt16 nSteps = rGradient.GetSteps();
+                if( rGradient.GetStyle() == GRADIENT_LINEAR )
+                {
+                    // Emulate non-smooth gradient
+                    if( 0 < nSteps && nSteps < 100 )
+                    {
+                        double fOffsetStep = ( 1.0 - fBorderOffset ) / (double)nSteps;
+                        for( sal_uInt16 i = 0; i < nSteps; i++ ) {
+                            Color aColor = ImplGetGradientColor( aStartColor, aEndColor, i / (double) nSteps );
+                            ImplWriteGradientStop( aColor, fBorderOffset + ( i + 1 ) * fOffsetStep );
+                            aColor = ImplGetGradientColor( aStartColor, aEndColor, ( i + 1 ) / (double) nSteps );
+                            ImplWriteGradientStop( aColor, fBorderOffset + ( i + 1 ) * fOffsetStep );
+                        }
+                    }
+                    else
+                    {
+                        ImplWriteGradientStop( aStartColor, fBorderOffset );
+                        ImplWriteGradientStop( aEndColor, 1.0 );
+                    }
+                }
+                else
+                {
+                    fBorderOffset /= 2;
+                    // Emulate non-smooth gradient
+                    if( 0 < nSteps && nSteps < 100 )
+                    {
+                        double fOffsetStep = ( 0.5 - fBorderOffset ) / (double)nSteps;
+                        // Upper half
+                        for( sal_uInt16 i = 0; i < nSteps; i++ )
+                        {
+                            Color aColor = ImplGetGradientColor( aEndColor, aStartColor, i / (double) nSteps );
+                            ImplWriteGradientStop( aColor, fBorderOffset + i * fOffsetStep );
+                            aColor = ImplGetGradientColor( aEndColor, aStartColor, (i + 1 ) / (double) nSteps );
+                            ImplWriteGradientStop( aColor, fBorderOffset + i * fOffsetStep );
+                        }
+                        // Lower half
+                        for( sal_uInt16 i = 0; i < nSteps; i++ )
+                        {
+                            Color aColor = ImplGetGradientColor( aStartColor, aEndColor, i / (double) nSteps );
+                            ImplWriteGradientStop( aColor, 0.5 + (i + 1) * fOffsetStep );
+                            aColor = ImplGetGradientColor( aStartColor, aEndColor, (i + 1 ) / (double) nSteps );
+                            ImplWriteGradientStop( aColor, 0.5 + (i + 1) * fOffsetStep );
+                        }
+                    }
+                    else
+                    {
+                        ImplWriteGradientStop( aEndColor, fBorderOffset );
+                        ImplWriteGradientStop( aStartColor, 0.5 );
+                        ImplWriteGradientStop( aEndColor, 1.0 - fBorderOffset );
+                    }
+                }
+            }
+        }
+
+        FastString aGradientStyle;
+        aGradientStyle += B2UCONST( "fill:" );
+        aGradientStyle += B2UCONST( "url(#" );
+        aGradientStyle += aGradientId.GetString();
+        aGradientStyle += B2UCONST( ")" );
+
+        {
+            ImplWritePolyPolygon( rPolyPoly, sal_False, &aGradientStyle.GetString() );
+        }
+    }
+}
+
+void SVGActionWriter::ImplWriteGradientStop( const Color& rColor, double fOffset )
+{
+    mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, NMSP_RTL::OUString::valueOf( fOffset ) );
+
+    FastString aStyle;
+    aStyle += B2UCONST( "stop-color:" );
+    aStyle += mpContext->GetColorStyle ( rColor );
+
+    mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle.GetString() );
+    {
+        SvXMLElementExport aElemStartStop( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, TRUE, TRUE );
+    }
+}
+
+Color SVGActionWriter::ImplGetColorWithIntensity( const Color& rColor,
+                                                  sal_uInt16 nIntensity )
+{
+     sal_uInt8 nNewRed = (sal_uInt8)( (long)rColor.GetRed() * nIntensity / 100L );
+     sal_uInt8 nNewGreen = (sal_uInt8)( (long)rColor.GetGreen() * nIntensity / 100L );
+     sal_uInt8 nNewBlue = (sal_uInt8)( (long)rColor.GetBlue() * nIntensity / 100L );
+     return Color( nNewRed, nNewGreen, nNewBlue);
+}
+
+Color SVGActionWriter::ImplGetGradientColor( const Color& rStartColor,
+                                             const Color& rEndColor,
+                                             double fOffset )
+{
+    long nRedStep = rEndColor.GetRed() - rStartColor.GetRed();
+    long nNewRed = rStartColor.GetRed() + (long)( nRedStep * fOffset );
+    nNewRed = ( nNewRed < 0 ) ? 0 : ( nNewRed > 0xFF) ? 0xFF : nNewRed;
+
+    long nGreenStep = rEndColor.GetGreen() - rStartColor.GetGreen();
+    long nNewGreen = rStartColor.GetGreen() + (long)( nGreenStep * fOffset );
+    nNewGreen = ( nNewGreen < 0 ) ? 0 : ( nNewGreen > 0xFF) ? 0xFF : nNewGreen;
+
+    long nBlueStep = rEndColor.GetBlue() - rStartColor.GetBlue();
+    long nNewBlue = rStartColor.GetBlue() + (long)( nBlueStep * fOffset );
+    nNewBlue = ( nNewBlue < 0 ) ? 0 : ( nNewBlue > 0xFF) ? 0xFF : nNewBlue;
+
+    return Color( (sal_uInt8)nNewRed, (sal_uInt8)nNewGreen, (sal_uInt8)nNewBlue );
 }
 
 // -----------------------------------------------------------------------------
diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx
index 6ec2452..f5928d1 100644
--- a/filter/source/svg/svgwriter.hxx
+++ b/filter/source/svg/svgwriter.hxx
@@ -140,6 +140,7 @@ public:
     virtual					~SVGAttributeWriter();
 
     ::rtl::OUString			GetFontStyle( const Font& rFont );
+    ::rtl::OUString			GetColorStyle( const Color& rColor );
     ::rtl::OUString			GetPaintStyle( const Color& rLineColor, const Color& rFillColor, const LineInfo* pLineInfo );
 
     void					SetFontAttr( const Font& rFont );
@@ -164,6 +165,7 @@ private:
     sal_Bool				mbClipAttrChanged;
     sal_Int32				mnCurClipId;
     sal_Int32				mnCurPatternId;
+    sal_Int32				mnCurGradientId;
     Stack					maContextStack;
     VirtualDevice*			mpVDev;
     MapMode					maTargetMapMode;
@@ -186,6 +188,10 @@ private:
     void					ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bLineOnly, const ::rtl::OUString* pStyle = NULL );
     void					ImplWritePattern( const PolyPolygon& rPolyPoly, const Hatch* pHatch, const Gradient* pGradient, const ::rtl::OUString* pStyle, sal_uInt32 nWriteFlags );
     void					ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient, const ::rtl::OUString* pStyle, sal_uInt32 nWriteFlags );
+    void					ImplWriteGradientLinear( const PolyPolygon& rPolyPoly, const Gradient& rGradient );
+    void					ImplWriteGradientStop( const Color& rColor, double fOffset );
+    Color					ImplGetColorWithIntensity( const Color& rColor, USHORT nIntensity );
+    Color					ImplGetGradientColor( const Color& rStartColor, const Color& rEndColor, double fOffset );
     void					ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, const ::rtl::OUString* pStyle = NULL );
     void                ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, const ::rtl::OUString* pStyle, Color aTextColor );
     void					ImplWriteBmp( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz, const ::rtl::OUString* pStyle = NULL );
@@ -196,6 +202,7 @@ private:
     void					ImplWriteActions( const GDIMetaFile& rMtf, const ::rtl::OUString* pStyle, sal_uInt32 nWriteFlags );
     sal_Int32				ImplGetNextClipId() { return mnCurClipId++; }
     sal_Int32				ImplGetNextPatternId() { return mnCurPatternId++; }
+    sal_Int32				ImplGetNextGradientId() { return mnCurGradientId++; }
 
 public:
 
commit 20aa1d724d1e784240d9157fc979ecbda81209c0
Author: Kurosawa Takeshi <taken.spc at gmail.com>
Date:   Fri Feb 11 18:55:42 2011 +0900

    Export hatches and gradients as SVG <pattern>s
    
    This patch tends not to improve a visual look, but improve semantic
    structure of an exported file.

diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index b33e84a..b0e2a0f 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -39,6 +39,7 @@
 static const char	aXMLElemG[] = "g";
 static const char	aXMLElemDefs[] = "defs";
 static const char	aXMLElemClipPath[] = "clipPath";
+static const char	aXMLElemPattern[] = "pattern";
 static const char	aXMLElemLine[] = "line";
 static const char	aXMLElemRect[] = "rect";
 static const char	aXMLElemEllipse[] = "ellipse";
@@ -66,6 +67,7 @@ static const char	aXMLAttrRY[] = "ry";
 static const char	aXMLAttrWidth[] = "width";
 static const char	aXMLAttrHeight[] = "height";
 static const char	aXMLAttrPoints[] = "points";
+static const char	aXMLAttrPatternUnits[] = "patternUnits";
 static const char	aXMLAttrXLinkHRef[] = "xlink:href";
 
 // --------------
@@ -379,7 +381,8 @@ SVGActionWriter::SVGActionWriter( SvXMLExport& rExport, SVGFontExport& rFontExpo
     mrFontExport( rFontExport ),
     mpContext( NULL ),
     mbClipAttrChanged( sal_False ),
-    mnCurClipId( 1 )
+    mnCurClipId( 1 ),
+    mnCurPatternId( 1 )
 {
     mpVDev = new VirtualDevice;
     mpVDev->EnableOutput( sal_False );
@@ -659,48 +662,81 @@ void SVGActionWriter::ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bo
 
 // -----------------------------------------------------------------------------
 
-void SVGActionWriter::ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient,
-                                           const NMSP_RTL::OUString* pStyle, sal_uInt32 nWriteFlags )
+void SVGActionWriter::ImplWritePattern( const PolyPolygon& rPolyPoly,
+                                        const Hatch* pHatch,
+                                        const Gradient* pGradient,
+                                        const NMSP_RTL::OUString* pStyle,
+                                        sal_uInt32 nWriteFlags )
 {
     if( rPolyPoly.Count() )
     {
-        SvXMLElementExport	aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
-        FastString			aClipId;
-        FastString			aClipStyle;
+        SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
 
-        aClipId += B2UCONST( "clip" );
-        aClipId += NMSP_RTL::OUString::valueOf( ImplGetNextClipId() );
+        FastString aPatternId;
+        aPatternId += B2UCONST( "pattern" );
+        aPatternId += GetValueString( ImplGetNextPatternId() );
 
         {
             SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, TRUE, TRUE );
 
-            mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aClipId.GetString() );
+            mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aPatternId.GetString() );
+
+            Rectangle aRect( ImplMap( rPolyPoly.GetBoundRect() ) );
+            mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, GetValueString( aRect.Left() ) );
+            mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, GetValueString( aRect.Top() ) );
+            mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, GetValueString( aRect.GetWidth() ) );
+            mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, GetValueString( aRect.GetHeight() ) );
+
+            mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrPatternUnits, NMSP_RTL::OUString( RTL_CONSTASCII_USTRINGPARAM( "userSpaceOnUse") ) );
 
             {
-                SvXMLElementExport aElemClipPath( mrExport, XML_NAMESPACE_NONE, aXMLElemClipPath, TRUE, TRUE );
-                ImplWritePolyPolygon( rPolyPoly, sal_False );
+                SvXMLElementExport aElemPattern( mrExport, XML_NAMESPACE_NONE, aXMLElemPattern, TRUE, TRUE );
+
+                // The origin of a pattern is positioned at (aRect.Left(), aRect.Top()).
+                // So we need to adjust the pattern coordinate.
+                FastString aTransform;
+                aTransform += B2UCONST( "translate" );
+                aTransform += B2UCONST( "(" );
+                aTransform += GetValueString( -aRect.Left() );
+                aTransform += B2UCONST( "," );
+                aTransform += GetValueString( -aRect.Top() );
+                aTransform += B2UCONST( ")" );
+                mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform.GetString() );
+
+                {
+                    SvXMLElementExport aElemG2( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
+
+                    GDIMetaFile aTmpMtf;
+                    if( pHatch )
+                        mpVDev->AddHatchActions( rPolyPoly, *pHatch, aTmpMtf );
+                    else if ( pGradient )
+                        mpVDev->AddGradientActions( rPolyPoly.GetBoundRect(), *pGradient, aTmpMtf );
+                    ImplWriteActions( aTmpMtf, pStyle, nWriteFlags );
+                }
             }
         }
 
-        // create new context with clippath set
-        aClipStyle += B2UCONST( "clip-path:URL(#" );
-        aClipStyle += aClipId.GetString();
-        aClipStyle += B2UCONST( ")" );
-
-        mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aClipStyle.GetString() );
+        FastString aPatternStyle;
+        aPatternStyle += B2UCONST( "fill:url(#" );
+        aPatternStyle += aPatternId.GetString();
+        aPatternStyle += B2UCONST( ")" );
 
         {
-            GDIMetaFile			aTmpMtf;
-            SvXMLElementExport	aElemG2( mrExport, XML_NAMESPACE_NONE, aXMLElemG, TRUE, TRUE );
-
-            mpVDev->AddGradientActions( rPolyPoly.GetBoundRect(), rGradient, aTmpMtf );
-            ImplWriteActions( aTmpMtf, pStyle, nWriteFlags );
+            ImplWritePolyPolygon( rPolyPoly, sal_False, &aPatternStyle.GetString() );
         }
     }
 }
 
 // -----------------------------------------------------------------------------
 
+void SVGActionWriter::ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient,
+                                           const NMSP_RTL::OUString* pStyle, sal_uInt32 nWriteFlags )
+{
+    ImplWritePattern( rPolyPoly, NULL, &rGradient, pStyle, nWriteFlags );
+}
+
+// -----------------------------------------------------------------------------
+
 void SVGActionWriter::ImplWriteText( const Point& rPos, const String& rText, 
                                      const sal_Int32* pDXArray, long nWidth,
                                      const NMSP_RTL::OUString* pStyle )
@@ -1267,10 +1303,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
                 if( nWriteFlags & SVGWRITER_WRITE_FILL )
                 {
                     const MetaHatchAction*	pA = (const MetaHatchAction*) pAction;
-                    GDIMetaFile				aTmpMtf;
-
-                    mpVDev->AddHatchActions( pA->GetPolyPolygon(), pA->GetHatch(), aTmpMtf );
-                    ImplWriteActions( aTmpMtf, pStyle, nWriteFlags );
+                    ImplWritePattern( pA->GetPolyPolygon(), &pA->GetHatch(), NULL, pStyle, nWriteFlags );
                 }
             }
             break;
diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx
index dfdc559..6ec2452 100644
--- a/filter/source/svg/svgwriter.hxx
+++ b/filter/source/svg/svgwriter.hxx
@@ -163,6 +163,7 @@ private:
     SVGAttributeWriter*		mpContext;
     sal_Bool				mbClipAttrChanged;
     sal_Int32				mnCurClipId;
+    sal_Int32				mnCurPatternId;
     Stack					maContextStack;
     VirtualDevice*			mpVDev;
     MapMode					maTargetMapMode;
@@ -183,6 +184,7 @@ private:
     void					ImplWriteRect( const Rectangle& rRect, long nRadX = 0, long nRadY = 0, const ::rtl::OUString* pStyle = NULL );
     void					ImplWriteEllipse( const Point& rCenter, long nRadX, long nRadY, const ::rtl::OUString* pStyle = NULL );
     void					ImplWritePolyPolygon( const PolyPolygon& rPolyPoly, sal_Bool bLineOnly, const ::rtl::OUString* pStyle = NULL );
+    void					ImplWritePattern( const PolyPolygon& rPolyPoly, const Hatch* pHatch, const Gradient* pGradient, const ::rtl::OUString* pStyle, sal_uInt32 nWriteFlags );
     void					ImplWriteGradientEx( const PolyPolygon& rPolyPoly, const Gradient& rGradient, const ::rtl::OUString* pStyle, sal_uInt32 nWriteFlags );
     void					ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, const ::rtl::OUString* pStyle = NULL );
     void                ImplWriteText( const Point& rPos, const String& rText, const sal_Int32* pDXArray, long nWidth, const ::rtl::OUString* pStyle, Color aTextColor );
@@ -193,6 +195,7 @@ private:
     
     void					ImplWriteActions( const GDIMetaFile& rMtf, const ::rtl::OUString* pStyle, sal_uInt32 nWriteFlags );
     sal_Int32				ImplGetNextClipId() { return mnCurClipId++; }
+    sal_Int32				ImplGetNextPatternId() { return mnCurPatternId++; }
 
 public:
 


More information about the Libreoffice-commits mailing list