summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurosawa Takeshi <taken.spc@gmail.com>2011-02-11 18:55:42 +0900
committerThorsten Behrens <tbehrens@novell.com>2011-02-14 10:31:57 +0100
commit20aa1d724d1e784240d9157fc979ecbda81209c0 (patch)
treef199681c433653754c0d76cd062481cd9f2e0ce0
parent6be83c9a3a5aafdcaf8982ea6a9c25bbd9e07276 (diff)
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.
-rw-r--r--filter/source/svg/svgwriter.cxx85
-rw-r--r--filter/source/svg/svgwriter.hxx3
2 files changed, 62 insertions, 26 deletions
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index b33e84a72..b0e2a0fad 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 dfdc559df..6ec245253 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: