diff options
Diffstat (limited to '')
-rw-r--r-- | filter/source/svg/svgwriter.hxx | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx new file mode 100644 index 000000000..d48d68bde --- /dev/null +++ b/filter/source/svg/svgwriter.hxx @@ -0,0 +1,406 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <cppuhelper/implbase.hxx> +#include <rtl/ustring.hxx> +#include <osl/diagnose.h> +#include <vcl/gdimtf.hxx> +#include <vcl/metaact.hxx> +#include <vcl/virdev.hxx> +#include <vcl/graphictools.hxx> +#include <xmloff/xmlexp.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/text/XTextContent.hpp> +#include <com/sun/star/text/XTextRange.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; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::svg; +using namespace ::com::sun::star::xml::sax; + +inline constexpr OUStringLiteral SVG_DTD_STRING = u"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"; + +#define SVGWRITER_WRITE_FILL 0x00000001 +#define SVGWRITER_WRITE_TEXT 0x00000002 +#define SVGWRITER_NO_SHAPE_COMMENTS 0x01000000 + +// This must match the same type definition in svgexport.hxx +typedef std::unordered_map< BitmapChecksum, std::unique_ptr< GDIMetaFile > > MetaBitmapActionMap; + +struct SVGState +{ + vcl::Font aFont; +// Color aLineColor; +// Color aFillColor; +// basegfx::B2DLineJoin aLineJoin; +// com::sun::star::drawing::LineCap aLineCap; + sal_Int32 nRegionClipPathId; + + SVGState() + : aFont() + , nRegionClipPathId( 0 ) + {} +}; +// - PartialState - + +struct PartialState +{ + vcl::PushFlags meFlags; + ::std::optional<vcl::Font> mupFont; + sal_Int32 mnRegionClipPathId; + + const vcl::Font& getFont( const vcl::Font& rDefaultFont ) const + { return mupFont ? *mupFont : rDefaultFont; } + + void setFont( const vcl::Font& rFont ) + { mupFont = rFont; } + + PartialState() + : meFlags( vcl::PushFlags::NONE ) + , mupFont() + , mnRegionClipPathId( 0 ) + {} + + PartialState(PartialState&& aPartialState) noexcept + : meFlags( aPartialState.meFlags ) + , mupFont( std::move( aPartialState.mupFont ) ) + , mnRegionClipPathId( aPartialState.mnRegionClipPathId ) + { + aPartialState.meFlags = vcl::PushFlags::NONE; + aPartialState.mnRegionClipPathId = 0; + } +}; + + +// - SVGContextHandler - + +class SVGContextHandler +{ +private: + ::std::stack<PartialState> maStateStack; + SVGState maCurrentState; + +public: + vcl::PushFlags getPushFlags() const; + SVGState& getCurrentState(); + void pushState( vcl::PushFlags eFlags ); + void popState(); +}; + + +// - SVGAttributeWriter - + +class SVGActionWriter; +class SVGExport; +class SVGFontExport; + + +class SVGAttributeWriter final +{ +private: + + SVGExport& mrExport; + SVGFontExport& mrFontExport; + SVGState& mrCurrentState; + std::unique_ptr<SvXMLElementExport> mpElemFont; + + + static double ImplRound( double fVal ); + +public: + + SVGAttributeWriter( SVGExport& rExport, SVGFontExport& rFontExport, SVGState& rCurState ); + ~SVGAttributeWriter(); + + void AddColorAttr( const OUString& pColorAttrName, const OUString& pColorOpacityAttrName, const Color& rColor ); + void AddGradientDef( const tools::Rectangle& rObjRect,const Gradient& rGradient, OUString& rGradientId ); + void AddPaintAttr( const Color& rLineColor, const Color& rFillColor, + const tools::Rectangle* pObjBoundRect = nullptr, const Gradient* pFillGradient = nullptr ); + + void SetFontAttr( const vcl::Font& rFont ); + void startFontSettings(); + void endFontSettings(); + void setFontFamily(); + + static void ImplGetColorStr( const Color& rColor, OUString& rColorStr ); +}; + +struct SVGShapeDescriptor +{ + tools::PolyPolygon maShapePolyPoly; + Color maShapeFillColor; + Color maShapeLineColor; + sal_Int32 mnStrokeWidth; + SvtGraphicStroke::DashArray maDashArray; + ::std::unique_ptr< Gradient > mapShapeGradient; + OUString maId; + basegfx::B2DLineJoin maLineJoin; + css::drawing::LineCap maLineCap; + + + SVGShapeDescriptor() : + maShapeFillColor( COL_TRANSPARENT ), + maShapeLineColor( COL_TRANSPARENT ), + mnStrokeWidth( 0 ), + maLineJoin(basegfx::B2DLineJoin::Miter), // miter is Svg 'stroke-linejoin' default + maLineCap(css::drawing::LineCap_BUTT) // butt is Svg 'stroke-linecap' default + { + } +}; + + +class SVGAttributeWriter; +class SVGExport; +class GDIMetaFile; + + +struct BulletListItemInfo +{ + vcl::Font aFont; + Color aColor; + Point aPos; + sal_Unicode cBulletChar; +}; + + +class SVGTextWriter final +{ + private: + SVGExport& mrExport; + SVGAttributeWriter& mrAttributeWriter; + SVGActionWriter& mrActionWriter; + VclPtr<VirtualDevice> mpVDev; + bool mbIsTextShapeStarted; + Reference<XText> mrTextShape; + OUString msShapeId; + Reference<XEnumeration> mrParagraphEnumeration; + Reference<XTextContent> mrCurrentTextParagraph; + Reference<XEnumeration> mrTextPortionEnumeration; + Reference<XTextRange> mrCurrentTextPortion; + const GDIMetaFile* mpTextEmbeddedBitmapMtf; + MapMode* mpTargetMapMode; + std::unique_ptr<SvXMLElementExport> mpTextShapeElem; + std::unique_ptr<SvXMLElementExport> mpTextParagraphElem; + std::unique_ptr<SvXMLElementExport> mpTextPositionElem; + OUString maTextOpacity; + sal_Int32 mnLeftTextPortionLength; + Point maTextPos; + tools::Long mnTextWidth; + bool mbPositioningNeeded; + bool mbIsNewListItem; + sal_Int16 meNumberingType; + sal_Unicode mcBulletChar; + std::unordered_map< OUString, BulletListItemInfo > maBulletListItemMap; + bool mbIsListLevelStyleImage; + bool mbLineBreak; + bool mbIsURLField; + OUString msUrl; + OUString msHyperlinkIdList; + OUString msPageCount; + OUString msDateTimeType; + OUString msTextFieldType; + bool mbIsPlaceholderShape; + static const bool mbIWS = false; + vcl::Font maCurrentFont; + vcl::Font maParentFont; + + public: + explicit SVGTextWriter(SVGExport& rExport, SVGAttributeWriter& rAttributeWriter, + SVGActionWriter& mrActionWriter); + ~SVGTextWriter(); + + sal_Int32 setTextPosition(const GDIMetaFile& rMtf, size_t& nCurAction, + sal_uInt32 nWriteFlags); + void setTextProperties( const GDIMetaFile& rMtf, size_t nCurAction ); + void addFontAttributes( bool bIsTextContainer ); + + void createParagraphEnumeration(); + bool nextParagraph(); + bool nextTextPortion(); + + bool isTextShapeStarted() const { return mbIsTextShapeStarted; } + void startTextShape(); + void endTextShape(); + void startTextParagraph(); + void endTextParagraph(); + void startTextPosition( bool bExportX = true, bool bExportY = true); + void endTextPosition(); + bool hasTextOpacity() const; + void implExportHyperlinkIds(); + void implWriteBulletChars(); + template< typename MetaBitmapActionType > + void writeBitmapPlaceholder( const MetaBitmapActionType* pAction ); + void implWriteEmbeddedBitmaps(); + void writeTextPortion( const Point& rPos, const OUString& rText ); + void implWriteTextPortion( const Point& rPos, const OUString& rText, + Color aTextColor ); + + void setVirtualDevice( VirtualDevice* pVDev, MapMode& rTargetMapMode ) + { + if( !pVDev ) + OSL_FAIL( "SVGTextWriter::setVirtualDevice: invalid virtual device." ); + mpVDev = pVDev; + mpTargetMapMode = &rTargetMapMode; + } + + void setTextShape( const Reference<XText>& rxText, + const GDIMetaFile* pTextEmbeddedBitmapMtf ) + { + mrTextShape.set( rxText ); + mpTextEmbeddedBitmapMtf = pTextEmbeddedBitmapMtf; + } + + private: + void implMap( const Size& rSz, Size& rDstSz ) const; + void implMap( const Point& rPt, Point& rDstPt ) const; + void implSetCurrentFont(); + void implSetFontFamily(); + + template< typename SubType > + bool implGetTextPosition( const MetaAction* pAction, Point& raPos, bool& bEmpty ); + template< typename SubType > + bool implGetTextPositionFromBitmap( const MetaAction* pAction, Point& raPos, bool& rbEmpty ); + + void implRegisterInterface( const Reference< XInterface >& rxIf ); + const OUString & implGetValidIDFromInterface( const Reference< XInterface >& rxIf ); +}; + + +class SVGActionWriter final +{ +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; + SVGState& mrCurrentState; + SVGAttributeWriter maAttributeWriter; + SVGTextWriter maTextWriter; + VclPtr<VirtualDevice> mpVDev; + MapMode maTargetMapMode; + bool mbClipAttrChanged; + bool mbIsPlaceholderShape; + const MetaBitmapActionMap* mpEmbeddedBitmapsMap; + bool mbIsPreview; + + + tools::Long ImplMap( sal_Int32 nVal ) const; + Point& ImplMap( const Point& rPt, Point& rDstPt ) const; + Size& ImplMap( const Size& rSz, Size& rDstSz ) const; + void ImplMap( const tools::Rectangle& rRect, tools::Rectangle& rDstRect ) const; + tools::Polygon& ImplMap( const tools::Polygon& rPoly, tools::Polygon& rDstPoly ) const; + tools::PolyPolygon& ImplMap( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rDstPolyPoly ) const; + + void ImplWriteLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor = nullptr ); + void ImplWriteRect( const tools::Rectangle& rRect, tools::Long nRadX = 0, tools::Long nRadY = 0 ); + void ImplWriteEllipse( const Point& rCenter, tools::Long nRadX, tools::Long nRadY ); + void ImplWritePattern( const tools::PolyPolygon& rPolyPoly, const Hatch* pHatch, const Gradient* pGradient, sal_uInt32 nWriteFlags ); + void ImplAddLineAttr( const LineInfo &rAttrs ); + 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 ); + static Color ImplGetColorWithIntensity( const Color& rColor, sal_uInt16 nIntensity ); + static Color ImplGetGradientColor( const Color& rStartColor, const Color& rEndColor, double fOffset ); + void ImplWriteMask( GDIMetaFile& rMtf, const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient, sal_uInt32 nWriteFlags ); + void ImplWriteText( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth ); + void ImplWriteText( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth, Color aTextColor ); + void ImplWriteBmp( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz, const css::uno::Reference<css::drawing::XShape>* pShape); + + void ImplWriteActions( const GDIMetaFile& rMtf, + sal_uInt32 nWriteFlags, + const OUString& aElementId, + const Reference< css::drawing::XShape >* pXShape = nullptr, + const GDIMetaFile* pTextEmbeddedBitmapMtf = nullptr ); + + vcl::Font ImplSetCorrectFontHeight() const; + +public: + + static OUString GetPathString( const tools::PolyPolygon& rPolyPoly, bool bLine ); + static BitmapChecksum GetChecksum( const MetaAction* pAction ); + +public: + SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport ); + ~SVGActionWriter(); + + void WriteMetaFile( const Point& rPos100thmm, + const Size& rSize100thmm, + const GDIMetaFile& rMtf, + sal_uInt32 nWriteFlags, + const OUString& aElementId = "", + const Reference< css::drawing::XShape >* pXShape = nullptr, + const GDIMetaFile* pTextEmbeddedBitmapMtf = nullptr ); + + void SetEmbeddedBitmapRefs( const MetaBitmapActionMap* pEmbeddedBitmapsMap ); + void StartMask(const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient, + sal_uInt32 nWriteFlags, OUString* pTextStyle = nullptr); + void SetPreviewMode(bool bState = true) { mbIsPreview = bState; } +}; + + +class SVGWriter : public cppu::WeakImplHelper< XSVGWriter, XServiceInfo > +{ +private: + Reference< XComponentContext > mxContext; + Sequence< css::beans::PropertyValue > maFilterData; + +public: + explicit SVGWriter( const Sequence<Any>& args, + const Reference< XComponentContext >& rxCtx ); + virtual ~SVGWriter() override; + + // XSVGWriter + virtual void SAL_CALL write( const Reference<XDocumentHandler>& rxDocHandler, + const Sequence<sal_Int8>& rMtfSeq ) override; + + // XServiceInfo + virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override; + virtual OUString SAL_CALL getImplementationName() override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |