diff options
author | Marco Cecchetti <marco.cecchetti@collabora.com> | 2016-06-17 16:22:47 +0200 |
---|---|---|
committer | Marco Cecchetti <mrcekets@gmail.com> | 2016-07-01 09:41:58 +0000 |
commit | 0f95f4f99cf09b597cb9d7b575aed7ba776919dd (patch) | |
tree | ce6ef1c479dcfb27ee923d53e640a6b443a25a65 | |
parent | 1085035078ac1546238be5de2ec47f70a8caffb1 (diff) |
svg filter - rewritten context handling
Change-Id: I9c18f6ca641de2957cbbf8fd57035f5aa2e5c294
Reviewed-on: https://gerrit.libreoffice.org/26831
Reviewed-by: Marco Cecchetti <mrcekets@gmail.com>
Tested-by: Marco Cecchetti <mrcekets@gmail.com>
-rw-r--r-- | filter/source/svg/svgwriter.cxx | 115 | ||||
-rw-r--r-- | filter/source/svg/svgwriter.hxx | 93 |
2 files changed, 144 insertions, 64 deletions
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx index fc874c1b7835..7328886a4584 100644 --- a/filter/source/svg/svgwriter.cxx +++ b/filter/source/svg/svgwriter.cxx @@ -94,9 +94,54 @@ static const char aOOOAttrNumberingType[] = NSPREFIX "numbering-type"; static sal_Char const XML_UNO_NAME_NRULE_NUMBERINGTYPE[] = "NumberingType"; static sal_Char const XML_UNO_NAME_NRULE_BULLET_CHAR[] = "BulletChar"; -SVGAttributeWriter::SVGAttributeWriter( SVGExport& rExport, SVGFontExport& rFontExport ) + +PushFlags SVGContextHandler::getLastUsedFlags() const +{ + if (maStateStack.empty()) + return PushFlags::NONE; + + const PartialState& rPartialState = maStateStack.top(); + return rPartialState.meFlags; +} + +SVGState& SVGContextHandler::getCurrentState() +{ + return maCurrentState; +} + +void SVGContextHandler::pushState( PushFlags eFlags ) +{ + PartialState aPartialState; + aPartialState.meFlags = eFlags; + + if (eFlags & PushFlags::FONT) + { + aPartialState.setFont( maCurrentState.aFont ); + } + + maStateStack.push( std::move(aPartialState) ); +} + +void SVGContextHandler::popState() +{ + if (maStateStack.empty()) + return; + + const PartialState& rPartialState = maStateStack.top(); + PushFlags eFlags = rPartialState.meFlags; + + if (eFlags & PushFlags::FONT) + { + maCurrentState.aFont = rPartialState.getFont( vcl::Font() ); + } + + maStateStack.pop(); +} + +SVGAttributeWriter::SVGAttributeWriter( SVGExport& rExport, SVGFontExport& rFontExport, SVGState& rCurState ) : mrExport( rExport ) , mrFontExport( rFontExport ) + , mrCurrentState( rCurState ) , mpElemFont( nullptr ) { } @@ -292,12 +337,14 @@ void SVGAttributeWriter::AddGradientDef( const Rectangle& rObjRect, const Gradie void SVGAttributeWriter::SetFontAttr( const vcl::Font& rFont ) { - if( rFont != maCurFont ) + vcl::Font& rCurFont = mrCurrentState.aFont; + + if( rFont != rCurFont ) { OUString aFontStyle, aTextDecoration; sal_Int32 nFontWeight; - maCurFont = rFont; + rCurFont = rFont; // Font Family setFontFamily(); @@ -384,23 +431,25 @@ void SVGAttributeWriter::endFontSettings() void SVGAttributeWriter::setFontFamily() { + vcl::Font& rCurFont = mrCurrentState.aFont; + if( mrExport.IsUsePositionedCharacters() ) { - mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontFamily, mrFontExport.GetMappedFontName( maCurFont.GetFamilyName() ) ); + mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontFamily, mrFontExport.GetMappedFontName( rCurFont.GetFamilyName() ) ); } else { sal_Int32 nNextTokenPos( 0 ); - const OUString& rsFontName = maCurFont.GetFamilyName(); + const OUString& rsFontName = rCurFont.GetFamilyName(); OUString sFontFamily( rsFontName.getToken( 0, ';', nNextTokenPos ) ); - FontPitch ePitch = maCurFont.GetPitch(); + FontPitch ePitch = rCurFont.GetPitch(); if( ePitch == PITCH_FIXED ) { sFontFamily += ", monospace"; } else { - FontFamily eFamily = maCurFont.GetFamilyType(); + FontFamily eFamily = rCurFont.GetFamilyType(); if( eFamily == FAMILY_ROMAN ) sFontFamily += ", serif"; else if( eFamily == FAMILY_SWISS ) @@ -410,10 +459,9 @@ void SVGAttributeWriter::setFontFamily() } } - -SVGTextWriter::SVGTextWriter( SVGExport& rExport ) +SVGTextWriter::SVGTextWriter( SVGExport& rExport, SVGAttributeWriter& rAttributeWriter ) : mrExport( rExport ), - mpContext( nullptr ), + mrAttributeWriter( rAttributeWriter ), mpVDev( nullptr ), mbIsTextShapeStarted( false ), mrTextShape(), @@ -1361,7 +1409,7 @@ void SVGTextWriter::implWriteBulletChars() "," + OUString::number( rInfo.aPos.Y() ) + ")"; mrExport.AddAttribute( XML_NAMESPACE_NONE, "transform", sPosition ); - mpContext->AddPaintAttr( COL_TRANSPARENT, rInfo.aColor ); + mrAttributeWriter.AddPaintAttr( COL_TRANSPARENT, rInfo.aColor ); SvXMLElementExport aPositioningElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true ); @@ -1664,9 +1712,8 @@ void SVGTextWriter::implWriteTextPortion( const Point& rPos, } addFontAttributes( /* isTexTContainer: */ false ); - assert(mpContext); //invalid context object - mpContext->AddPaintAttr( COL_TRANSPARENT, aTextColor ); + mrAttributeWriter.AddPaintAttr( COL_TRANSPARENT, aTextColor ); // <a> tag for link should be the innermost tag, inside <tspan> if( !mbIsPlaceholderShape && mbIsURLField && !msUrl.isEmpty() ) @@ -1696,9 +1743,10 @@ SVGActionWriter::SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport mnCurMaskId( 1 ), mnCurPatternId( 1 ), mrExport( rExport ), - mrFontExport( rFontExport ), - mpContext( nullptr ), - maTextWriter( rExport ), + maContextHandler(), + mrCurrentState( maContextHandler.getCurrentState() ), + maAttributeWriter( rExport, rFontExport, mrCurrentState ), + maTextWriter( rExport, maAttributeWriter ), mbClipAttrChanged( false ), mbIsPlaceholderShape( false ) { @@ -1711,7 +1759,6 @@ SVGActionWriter::SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport SVGActionWriter::~SVGActionWriter() { - DBG_ASSERT( !mpContext, "Not all contexts are closed" ); mpVDev.disposeAndClear(); } @@ -1997,7 +2044,7 @@ void SVGActionWriter::ImplWriteShape( const SVGShapeDescriptor& rShape ) const bool bLineOnly = ( rShape.maShapeFillColor == Color( COL_TRANSPARENT ) ) && ( !rShape.mapShapeGradient.get() ); Rectangle aBoundRect( aPolyPoly.GetBoundRect() ); - mpContext->AddPaintAttr( rShape.maShapeLineColor, rShape.maShapeFillColor, &aBoundRect, rShape.mapShapeGradient.get() ); + maAttributeWriter.AddPaintAttr( rShape.maShapeLineColor, rShape.maShapeFillColor, &aBoundRect, rShape.mapShapeGradient.get() ); if( !rShape.maId.isEmpty() ) mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, rShape.maId ); @@ -2500,7 +2547,7 @@ void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText, } - mpContext->AddPaintAttr( COL_TRANSPARENT, aTextColor ); + maAttributeWriter.AddPaintAttr( COL_TRANSPARENT, aTextColor ); // for each line of text there should be at least one group element SvXMLElementExport aSVGGElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, false ); @@ -2768,7 +2815,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, { const MetaPixelAction* pA = static_cast<const MetaPixelAction*>(pAction); - mpContext->AddPaintAttr( pA->GetColor(), pA->GetColor() ); + maAttributeWriter.AddPaintAttr( pA->GetColor(), pA->GetColor() ); ImplWriteLine( pA->GetPoint(), pA->GetPoint(), &pA->GetColor() ); } } @@ -2780,7 +2827,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, { const MetaPointAction* pA = static_cast<const MetaPointAction*>(pAction); - mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() ); + maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() ); ImplWriteLine( pA->GetPoint(), pA->GetPoint() ); } } @@ -2792,7 +2839,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, { const MetaLineAction* pA = static_cast<const MetaLineAction*>(pAction); - mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() ); + maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() ); ImplWriteLine( pA->GetStartPoint(), pA->GetEndPoint() ); } } @@ -2802,7 +2849,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, { if( nWriteFlags & SVGWRITER_WRITE_FILL ) { - mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); ImplWriteRect( static_cast<const MetaRectAction*>(pAction)->GetRect() ); } } @@ -2814,7 +2861,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, { const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pAction); - mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); ImplWriteRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() ); } } @@ -2827,7 +2874,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pAction); const Rectangle& rRect = pA->GetRect(); - mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); ImplWriteEllipse( rRect.Center(), rRect.GetWidth() >> 1, rRect.GetHeight() >> 1 ); } } @@ -2873,7 +2920,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, if( aPoly.GetSize() ) { - mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); ImplWritePolyPolygon( aPoly, false ); } } @@ -2889,7 +2936,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, if( rPoly.GetSize() ) { - mpContext->AddPaintAttr( mpVDev->GetLineColor(), Color( COL_TRANSPARENT ) ); + maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), Color( COL_TRANSPARENT ) ); ImplAddLineAttr( pA->GetLineInfo() ); ImplWritePolyPolygon( rPoly, true ); } @@ -2906,7 +2953,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, if( rPolyPoly.Count() ) { - mpContext->AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); + maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() ); ImplWritePolyPolygon( rPolyPoly, false ); } } @@ -2960,7 +3007,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, aNewLineColor.SetTransparency( sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) ); aNewFillColor.SetTransparency( sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) ); - mpContext->AddPaintAttr( aNewLineColor, aNewFillColor ); + maAttributeWriter.AddPaintAttr( aNewLineColor, aNewFillColor ); ImplWritePolyPolygon( rPolyPoly, false ); } } @@ -3478,7 +3525,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, if( mrExport.IsUsePositionedCharacters() ) { vcl::Font aFont = ImplSetCorrectFontHeight(); - mpContext->SetFontAttr( aFont ); + maAttributeWriter.SetFontAttr( aFont ); ImplWriteText( pA->GetPoint(), aText, nullptr, 0 ); } else @@ -3501,7 +3548,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, if( mrExport.IsUsePositionedCharacters() ) { vcl::Font aFont = ImplSetCorrectFontHeight(); - mpContext->SetFontAttr( aFont ); + maAttributeWriter.SetFontAttr( aFont ); ImplWriteText( pA->GetRect().TopLeft(), pA->GetText(), nullptr, 0 ); } maTextWriter.writeTextPortion( pA->GetRect().TopLeft(), pA->GetText() ); @@ -3523,7 +3570,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, if( mrExport.IsUsePositionedCharacters() ) { vcl::Font aFont = ImplSetCorrectFontHeight(); - mpContext->SetFontAttr( aFont ); + maAttributeWriter.SetFontAttr( aFont ); ImplWriteText( pA->GetPoint(), aText, pA->GetDXArray(), 0 ); } else @@ -3548,7 +3595,7 @@ void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf, if( mrExport.IsUsePositionedCharacters() ) { vcl::Font aFont = ImplSetCorrectFontHeight(); - mpContext->SetFontAttr( aFont ); + maAttributeWriter.SetFontAttr( aFont ); ImplWriteText( pA->GetPoint(), aText, nullptr, pA->GetWidth() ); } else @@ -3642,7 +3689,6 @@ void SVGActionWriter::WriteMetaFile( const Point& rPos100thmm, aMapMode.SetOrigin( aOffset += aMapMode.GetOrigin() ); mpVDev->SetMapMode( aMapMode ); - ImplAcquireContext(); mapCurShape.reset(); @@ -3656,7 +3702,6 @@ void SVGActionWriter::WriteMetaFile( const Point& rPos100thmm, mapCurShape.reset(); } - ImplReleaseContext(); mpVDev->Pop(); } diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx index 76c2df0b1592..5c3b75772ba9 100644 --- a/filter/source/svg/svgwriter.hxx +++ b/filter/source/svg/svgwriter.hxx @@ -57,9 +57,11 @@ #include <com/sun/star/style/NumberingType.hpp> #include <com/sun/star/svg/XSVGWriter.hpp> +#include <memory> #include <stack> #include <unordered_map> + using namespace ::com::sun::star::uno; using namespace ::com::sun::star::container; using namespace ::com::sun::star::lang; @@ -75,6 +77,59 @@ using namespace ::com::sun::star::xml::sax; #define SVGWRITER_WRITE_TEXT 0x00000002 #define SVGWRITER_NO_SHAPE_COMMENTS 0x01000000 + +struct SVGState +{ + vcl::Font aFont; +// Color aLineColor; +// Color aFillColor; +// basegfx::B2DLineJoin aLineJoin; +// com::sun::star::drawing::LineCap aLineCap; +}; +// - PartialState - + +struct PartialState +{ + PushFlags meFlags; + ::std::unique_ptr<vcl::Font> mupFont; + + const vcl::Font& getFont( const vcl::Font& rDefaultFont ) const + { return mupFont ? *mupFont : rDefaultFont; } + + void setFont( const vcl::Font& rFont ) + { mupFont.reset( new vcl::Font(rFont) ); } + + PartialState() + : meFlags( PushFlags::NONE ) + {} + + PartialState(PartialState&& aPartialState) + : meFlags( aPartialState.meFlags ) + , mupFont( std::move( aPartialState.mupFont ) ) + { + aPartialState.meFlags = PushFlags::NONE; + } +}; + + +// - SVGContextHandler - + +class SVGContextHandler +{ +private: + ::std::stack<PartialState> maStateStack; + SVGState maCurrentState; + +public: + PushFlags getLastUsedFlags() const; + SVGState& getCurrentState(); + void pushState( PushFlags eFlags ); + void popState(); +}; + + +// - SVGAttributeWriter - + class SVGActionWriter; class SVGExport; class SVGFontExport; @@ -84,16 +139,17 @@ class SVGAttributeWriter { private: - vcl::Font maCurFont; SVGExport& mrExport; SVGFontExport& mrFontExport; + SVGState& mrCurrentState; SvXMLElementExport* mpElemFont; - static double ImplRound( double fVal ); + static double ImplRound( double fVal ); + public: - SVGAttributeWriter( SVGExport& rExport, SVGFontExport& rFontExport ); + SVGAttributeWriter( SVGExport& rExport, SVGFontExport& rFontExport, SVGState& rCurState ); virtual ~SVGAttributeWriter(); void AddColorAttr( const char* pColorAttrName, const char* pColorOpacityAttrName, const Color& rColor ); @@ -154,7 +210,7 @@ class SVGTextWriter private: SVGExport& mrExport; - SVGAttributeWriter* mpContext; + SVGAttributeWriter& mrAttributeWriter; VclPtr<VirtualDevice> mpVDev; bool mbIsTextShapeStarted; Reference<XText> mrTextShape; @@ -187,7 +243,7 @@ class SVGTextWriter vcl::Font maParentFont; public: - explicit SVGTextWriter( SVGExport& rExport ); + explicit SVGTextWriter( SVGExport& rExport, SVGAttributeWriter& rAttributeWriter ); virtual ~SVGTextWriter(); sal_Int32 setTextPosition( const GDIMetaFile& rMtf, sal_uLong& nCurAction ); @@ -222,11 +278,6 @@ class SVGTextWriter mpTargetMapMode = &rTargetMapMode; } - void setContext( SVGAttributeWriter* pContext ) - { - mpContext = pContext; - } - void setTextShape( const Reference<XText>& rxText, const GDIMetaFile* pTextEmbeddedBitmapMtf ) { @@ -257,11 +308,11 @@ private: sal_Int32 mnCurGradientId; sal_Int32 mnCurMaskId; sal_Int32 mnCurPatternId; - ::std::stack< SVGAttributeWriter* > maContextStack; ::std::unique_ptr< SVGShapeDescriptor > mapCurShape; SVGExport& mrExport; - SVGFontExport& mrFontExport; - SVGAttributeWriter* mpContext; + SVGContextHandler maContextHandler; + SVGState& mrCurrentState; + SVGAttributeWriter maAttributeWriter; SVGTextWriter maTextWriter; VclPtr<VirtualDevice> mpVDev; MapMode maTargetMapMode; @@ -269,22 +320,6 @@ private: bool mbIsPlaceholderShape; - void ImplAcquireContext() - { - maContextStack.push( mpContext = new SVGAttributeWriter( mrExport, mrFontExport ) ); - maTextWriter.setContext( mpContext ); - } - void ImplReleaseContext() - { - if (!maContextStack.empty()) - { - delete maContextStack.top(); - maContextStack.pop(); - } - mpContext = (maContextStack.empty() ? nullptr : maContextStack.top()); - maTextWriter.setContext( mpContext ); - } - long ImplMap( sal_Int32 nVal ) const; Point& ImplMap( const Point& rPt, Point& rDstPt ) const; Size& ImplMap( const Size& rSz, Size& rDstSz ) const; |