summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
authorMarco Cecchetti <marco.cecchetti@collabora.com>2016-06-19 23:45:20 +0200
committerMarco Cecchetti <marco.cecchetti@collabora.com>2016-07-01 11:05:23 +0200
commit97ed7868e571d2aa2f1585f9379204546c49286d (patch)
treebadd3d82db871873413afcd7c77f50f34d9ccee7 /filter
parente9b86135459ee16348eabb8e1fb56fee94a209ad (diff)
bccu#1307 - svg filter - added support for clip region meta action
Change-Id: Ie5177c7a0c3679db6f72c9a656c9474eac2cf047 Reviewed-on: https://gerrit.libreoffice.org/26506 Reviewed-by: Marco Cecchetti <mrcekets@gmail.com> Tested-by: Marco Cecchetti <mrcekets@gmail.com>
Diffstat (limited to 'filter')
-rw-r--r--filter/source/svg/svgwriter.cxx101
-rw-r--r--filter/source/svg/svgwriter.hxx19
2 files changed, 116 insertions, 4 deletions
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index 579d6f05151b..1f433540694b 100644
--- a/filter/source/svg/svgwriter.cxx
+++ b/filter/source/svg/svgwriter.cxx
@@ -32,8 +32,11 @@
#include <memory>
+static const char aPrefixClipPathId[] = "clip_path_";
+
static const char aXMLElemG[] = "g";
static const char aXMLElemA[] = "a";
+static const char aXMLElemClipPath[] = "clipPath";
static const char aXMLElemDefs[] = "defs";
static const char aXMLElemLine[] = "line";
static const char aXMLElemRect[] = "rect";
@@ -51,6 +54,8 @@ static const char aXMLElemStop[] = "stop";
static const char aXMLAttrTransform[] = "transform";
static const char aXMLAttrStyle[] = "style";
static const char aXMLAttrId[] = "id";
+static const char aXMLAttrClipPath[] = "clip-path";
+static const char aXMLAttrClipPathUnits[] = "clipPathUnits";
static const char aXMLAttrD[] = "d";
static const char aXMLAttrX[] = "x";
static const char aXMLAttrY[] = "y";
@@ -95,7 +100,7 @@ static sal_Char const XML_UNO_NAME_NRULE_NUMBERINGTYPE[] = "NumberingType";
static sal_Char const XML_UNO_NAME_NRULE_BULLET_CHAR[] = "BulletChar";
-PushFlags SVGContextHandler::getLastUsedFlags() const
+PushFlags SVGContextHandler::getPushFlags() const
{
if (maStateStack.empty())
return PushFlags::NONE;
@@ -119,6 +124,11 @@ void SVGContextHandler::pushState( PushFlags eFlags )
aPartialState.setFont( maCurrentState.aFont );
}
+ if (eFlags & PushFlags::CLIPREGION)
+ {
+ aPartialState.mnRegionClipPathId = maCurrentState.nRegionClipPathId;
+ }
+
maStateStack.push( std::move(aPartialState) );
}
@@ -135,6 +145,11 @@ void SVGContextHandler::popState()
maCurrentState.aFont = rPartialState.getFont( vcl::Font() );
}
+ if (eFlags & PushFlags::CLIPREGION)
+ {
+ maCurrentState.nRegionClipPathId = rPartialState.mnRegionClipPathId;
+ }
+
maStateStack.pop();
}
@@ -1712,6 +1727,8 @@ SVGActionWriter::SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport
mnCurGradientId( 1 ),
mnCurMaskId( 1 ),
mnCurPatternId( 1 ),
+ mnCurClipPathId( 1 ),
+ mpCurrentClipRegionElem(),
mrExport( rExport ),
maContextHandler(),
mrCurrentState( maContextHandler.getCurrentState() ),
@@ -2101,6 +2118,55 @@ void SVGActionWriter::ImplWriteShape( const SVGShapeDescriptor& rShape, bool bAp
ImplWritePolyPolygon( aPolyPoly, bLineOnly, false );
}
+
+
+void SVGActionWriter::ImplCreateClipPathDef( const tools::PolyPolygon& rPolyPoly )
+{
+ OUString aClipPathId = aPrefixClipPathId + OUString::number( mnCurClipPathId++ );
+
+ SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
+
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aClipPathId );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrClipPathUnits, "userSpaceOnUse" );
+ SvXMLElementExport aElemClipPath( mrExport, XML_NAMESPACE_NONE, aXMLElemClipPath, true, true );
+
+ ImplWritePolyPolygon(rPolyPoly, false, true);
+ }
+}
+
+void SVGActionWriter::ImplStartClipRegion(sal_Int32 nClipPathId)
+{
+ assert(!mpCurrentClipRegionElem);
+
+ if (nClipPathId == 0)
+ return;
+
+ OUString aUrl = OUString("url(#") + aPrefixClipPathId + OUString::number( nClipPathId ) + ")";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrClipPath, aUrl );
+ mpCurrentClipRegionElem.reset( new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true ) );
+}
+
+void SVGActionWriter::ImplEndClipRegion()
+{
+ if (mpCurrentClipRegionElem)
+ {
+ mpCurrentClipRegionElem.reset();
+ }
+}
+
+void SVGActionWriter::ImplWriteClipPath( const tools::PolyPolygon& rPolyPoly )
+{
+ ImplEndClipRegion();
+
+ if( rPolyPoly.Count() == 0 )
+ return;
+
+ ImplCreateClipPathDef(rPolyPoly);
+ mrCurrentState.nRegionClipPathId = mnCurClipPathId - 1;
+ ImplStartClipRegion( mrCurrentState.nRegionClipPathId );
+}
+
void SVGActionWriter::ImplWritePattern( const tools::PolyPolygon& rPolyPoly,
const Hatch* pHatch,
const Gradient* pGradient,
@@ -3599,10 +3665,40 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
case( MetaActionType::MOVECLIPREGION ):
{
const_cast<MetaAction*>(pAction)->Execute( mpVDev );
+ const vcl::Region& rClipRegion = mpVDev->GetActiveClipRegion();
+ ImplWriteClipPath( rClipRegion.GetAsPolyPolygon() );
+
mbClipAttrChanged = true;
}
break;
+ case( MetaActionType::PUSH ):
+ {
+ const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
+ PushFlags mnFlags = pA->GetFlags();
+
+ const_cast<MetaAction*>(pAction)->Execute( mpVDev );
+
+ maContextHandler.pushState( mnFlags );
+ }
+ break;
+
+ case( MetaActionType::POP ):
+ {
+ const_cast<MetaAction*>(pAction)->Execute( mpVDev );
+
+ PushFlags mnFlags = maContextHandler.getPushFlags();
+
+ maContextHandler.popState();
+
+ if( mnFlags & PushFlags::CLIPREGION )
+ {
+ ImplEndClipRegion();
+ ImplStartClipRegion( mrCurrentState.nRegionClipPathId );
+ }
+ }
+ break;
+
case( MetaActionType::REFPOINT ):
case( MetaActionType::MAPMODE ):
case( MetaActionType::LINECOLOR ):
@@ -3612,8 +3708,6 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
case( MetaActionType::TEXTCOLOR ):
case( MetaActionType::TEXTALIGN ):
case( MetaActionType::FONT ):
- case( MetaActionType::PUSH ):
- case( MetaActionType::POP ):
case( MetaActionType::LAYOUTMODE ):
{
const_cast<MetaAction*>(pAction)->Execute( mpVDev );
@@ -3678,6 +3772,7 @@ void SVGActionWriter::WriteMetaFile( const Point& rPos100thmm,
ImplWriteActions( rMtf, nWriteFlags, pElementId, pXShape, pTextEmbeddedBitmapMtf );
maTextWriter.endTextParagraph();
+ ImplEndClipRegion();
// draw open shape that doesn't have a border
if( mapCurShape.get() )
diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx
index afb9ebc5c90f..d0d3312d078a 100644
--- a/filter/source/svg/svgwriter.hxx
+++ b/filter/source/svg/svgwriter.hxx
@@ -89,6 +89,12 @@ struct SVGState
// Color aFillColor;
// basegfx::B2DLineJoin aLineJoin;
// com::sun::star::drawing::LineCap aLineCap;
+ sal_Int32 nRegionClipPathId;
+
+ SVGState()
+ : aFont()
+ , nRegionClipPathId( 0 )
+ {}
};
@@ -98,6 +104,7 @@ struct PartialState
{
PushFlags meFlags;
::std::unique_ptr<vcl::Font> mupFont;
+ sal_Int32 mnRegionClipPathId;
const vcl::Font& getFont( const vcl::Font& rDefaultFont ) const
{ return mupFont ? *mupFont : rDefaultFont; }
@@ -107,13 +114,17 @@ struct PartialState
PartialState()
: meFlags( PushFlags::NONE )
+ , mupFont()
+ , mnRegionClipPathId( 0 )
{}
PartialState(PartialState&& aPartialState)
: meFlags( aPartialState.meFlags )
, mupFont( std::move( aPartialState.mupFont ) )
+ , mnRegionClipPathId( aPartialState.mnRegionClipPathId )
{
aPartialState.meFlags = PushFlags::NONE;
+ aPartialState.mnRegionClipPathId = 0;
}
};
@@ -127,7 +138,7 @@ private:
SVGState maCurrentState;
public:
- PushFlags getLastUsedFlags() const;
+ PushFlags getPushFlags() const;
SVGState& getCurrentState();
void pushState( PushFlags eFlags );
void popState();
@@ -325,6 +336,8 @@ private:
sal_Int32 mnCurGradientId;
sal_Int32 mnCurMaskId;
sal_Int32 mnCurPatternId;
+ sal_Int32 mnCurClipPathId;
+ ::std::unique_ptr< SvXMLElementExport > mpCurrentClipRegionElem;
::std::unique_ptr< SVGShapeDescriptor > mapCurShape;
SVGExport& mrExport;
SVGContextHandler maContextHandler;
@@ -357,6 +370,10 @@ private:
void ImplWritePolyPolygon( const tools::PolyPolygon& rPolyPoly, bool bLineOnly,
bool bApplyMapping = true );
void ImplWriteShape( const SVGShapeDescriptor& rShape, bool bApplyMapping = true );
+ void ImplCreateClipPathDef( const tools::PolyPolygon& rPolyPoly );
+ void ImplStartClipRegion(sal_Int32 nClipPathId);
+ void ImplEndClipRegion();
+ void ImplWriteClipPath( const tools::PolyPolygon& rPolyPoly );
void ImplWriteGradientEx( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient, sal_uInt32 nWriteFlags);
void ImplWriteGradientLinear( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient );
void ImplWriteGradientStop( const Color& rColor, double fOffset );