filter/source/svg/svgwriter.cxx | 101 ++++++++++++++++++++++++++++++++++++++-- filter/source/svg/svgwriter.hxx | 19 +++++++ 2 files changed, 116 insertions(+), 4 deletions(-)
New commits: commit ac094c9fad665654c7049bef5565025efce93c47 Author: Marco Cecchetti <marco.cecche...@collabora.com> Date: Sun Jun 19 23:45:20 2016 +0200 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 <mrcek...@gmail.com> Tested-by: Marco Cecchetti <mrcek...@gmail.com> diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx index f2e5470..9859195 100644 --- a/filter/source/svg/svgwriter.cxx +++ b/filter/source/svg/svgwriter.cxx @@ -33,8 +33,11 @@ #include <boost/shared_array.hpp> +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"; @@ -52,6 +55,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"; @@ -96,7 +101,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; @@ -120,6 +125,11 @@ void SVGContextHandler::pushState( PushFlags eFlags ) aPartialState.setFont( maCurrentState.aFont ); } + if (eFlags & PushFlags::CLIPREGION) + { + aPartialState.mnRegionClipPathId = maCurrentState.nRegionClipPathId; + } + maStateStack.push( std::move(aPartialState) ); } @@ -136,6 +146,11 @@ void SVGContextHandler::popState() maCurrentState.aFont = rPartialState.getFont( vcl::Font() ); } + if (eFlags & PushFlags::CLIPREGION) + { + maCurrentState.nRegionClipPathId = rPartialState.mnRegionClipPathId; + } + maStateStack.pop(); } @@ -1716,6 +1731,8 @@ SVGActionWriter::SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport mnCurGradientId( 1 ), mnCurMaskId( 1 ), mnCurPatternId( 1 ), + mnCurClipPathId( 1 ), + mpCurrentClipRegionElem(), mrExport( rExport ), mrFontExport( rFontExport ), maContextHandler(), @@ -2106,6 +2123,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, @@ -3604,10 +3670,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 ): @@ -3617,8 +3713,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 ); @@ -3683,6 +3777,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 d1384bc..e0f9185 100644 --- a/filter/source/svg/svgwriter.hxx +++ b/filter/source/svg/svgwriter.hxx @@ -90,6 +90,12 @@ struct SVGState // Color aFillColor; // basegfx::B2DLineJoin aLineJoin; // com::sun::star::drawing::LineCap aLineCap; + sal_Int32 nRegionClipPathId; + + SVGState() + : aFont() + , nRegionClipPathId( 0 ) + {} }; @@ -99,6 +105,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; } @@ -108,13 +115,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; } }; @@ -128,7 +139,7 @@ private: SVGState maCurrentState; public: - PushFlags getLastUsedFlags() const; + PushFlags getPushFlags() const; SVGState& getCurrentState(); void pushState( PushFlags eFlags ); void popState(); @@ -338,6 +349,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; SVGFontExport& mrFontExport; @@ -371,6 +384,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 ); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits