summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
authorMarco Cecchetti <marco.cecchetti@collabora.com>2016-06-19 23:45:20 +0200
committerMarco Cecchetti <mrcekets@gmail.com>2016-07-01 09:42:35 +0000
commit880c6e40f694342408681929ae5c4fe12bd63332 (patch)
tree745ed6528d947d8118d995538d0ebe5d72c883dc /filter
parent0f95f4f99cf09b597cb9d7b575aed7ba776919dd (diff)
bccu#1307 - svg filter - added support for clip region meta action
Change-Id: I90beea5e101a14f0dc9df8c7db0bb55782aba110 Reviewed-on: https://gerrit.libreoffice.org/26832 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.cxx100
-rw-r--r--filter/source/svg/svgwriter.hxx19
2 files changed, 115 insertions, 4 deletions
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
index 7328886a4584..0fe1cd0f8e20 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();
}
@@ -1742,6 +1757,8 @@ SVGActionWriter::SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport
mnCurGradientId( 1 ),
mnCurMaskId( 1 ),
mnCurPatternId( 1 ),
+ mnCurClipPathId( 1 ),
+ mpCurrentClipRegionElem(),
mrExport( rExport ),
maContextHandler(),
mrCurrentState( maContextHandler.getCurrentState() ),
@@ -2122,6 +2139,54 @@ void SVGActionWriter::ImplWriteShape( const SVGShapeDescriptor& rShape )
}
+
+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,
@@ -3613,10 +3678,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 ):
@@ -3626,8 +3721,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 );
@@ -3694,6 +3787,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 5c3b75772ba9..74cda8a7bee7 100644
--- a/filter/source/svg/svgwriter.hxx
+++ b/filter/source/svg/svgwriter.hxx
@@ -85,6 +85,12 @@ struct SVGState
// Color aFillColor;
// basegfx::B2DLineJoin aLineJoin;
// com::sun::star::drawing::LineCap aLineCap;
+ sal_Int32 nRegionClipPathId;
+
+ SVGState()
+ : aFont()
+ , nRegionClipPathId( 0 )
+ {}
};
// - PartialState -
@@ -92,6 +98,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; }
@@ -101,13 +108,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;
}
};
@@ -121,7 +132,7 @@ private:
SVGState maCurrentState;
public:
- PushFlags getLastUsedFlags() const;
+ PushFlags getPushFlags() const;
SVGState& getCurrentState();
void pushState( PushFlags eFlags );
void popState();
@@ -308,6 +319,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;
@@ -335,6 +348,10 @@ private:
void ImplWritePolyPolygon( const tools::PolyPolygon& rPolyPoly, bool bLineOnly,
bool bApplyMapping = true );
void ImplWriteShape( const SVGShapeDescriptor& rShape );
+ 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 );