diff options
author | Armin Le Grand <Armin.Le.Grand@cib.de> | 2018-05-10 17:49:19 +0200 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@cib.de> | 2018-05-18 20:11:35 +0200 |
commit | 3ca7be09834a26fbd1c371deabd7a58111092676 (patch) | |
tree | 560c1ee287e529b8879bbc2375b5a48f87c65a51 | |
parent | c845135b7b605257b5c94b382d88627282cb05a3 (diff) |
Replace SVGFilter using SVGIO
Target of this change is to get rid of the SVGFilter
in current LO which is based on the standard-ODF importer
using it's functionality by passing in/handing over
temporary created XML-Stream-Data.
First step is to alternatively import the given SVG
file to a newly created Document and to strip the
existing Filter-Code.
Adding the first prototype of the changed import. It
is capable of importing the given SVG to the created
Draw/Impress document. It adds the SVG which gets imported
by SVGIO as GraphicObject. It adapts sizes and positions of
Page and GraphicObject to have a smooth import.
Adding stripping of SVGFilter and used ressources. Done
as deep as possible, hopefully all places found.
Adapted now to create an Impress document. Also added needed
adaptions to PageSize(s), including layout and PresObj stuff
to make all MasterPages/LayoutPages work correctly.
Added reaction on empty SVG. This is needed since the
PageSize is adapted to the Graphic. With empty Graphic
a Size(0,0) results and this goes wrong.
Change-Id: Ia364a5783bee7dadcbe91e700efbabc121cf98f9
Reviewed-on: https://gerrit.libreoffice.org/54096
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Armin Le Grand <Armin.Le.Grand@cib.de>
26 files changed, 454 insertions, 4010 deletions
diff --git a/Repository.mk b/Repository.mk index 4cd3f1036637..7a019e2d311b 100644 --- a/Repository.mk +++ b/Repository.mk @@ -53,7 +53,6 @@ $(eval $(call gb_Helper_register_executables,NONE, \ regsvrex \ saxparser \ sp2bv \ - svg2odf \ svidl \ $(if $(ENABLE_ONLINE_UPDATE_MAR),\ test_updater_dialog \ diff --git a/compilerplugins/clang/store/constantfunction.cxx b/compilerplugins/clang/store/constantfunction.cxx index 19c28df00db5..f3dd4f8a39c5 100644 --- a/compilerplugins/clang/store/constantfunction.cxx +++ b/compilerplugins/clang/store/constantfunction.cxx @@ -109,10 +109,6 @@ bool ConstantFunction::VisitFunctionDecl(const FunctionDecl * pFunctionDecl) { if (aFileName == SRCDIR "/extensions/source/plugin/unx/npnapi.cxx") { return true; } - // template magic - if (aFileName == SRCDIR "/filter/source/svg/svgreader.cxx") { - return true; - } // vcl/unx/gtk3 re-using vcl/unx/gtk: if (aFileName.find("/../../gtk/") != std::string::npos) { return true; diff --git a/filter/Executable_svg2odf.mk b/filter/Executable_svg2odf.mk deleted file mode 100644 index d63808600bb1..000000000000 --- a/filter/Executable_svg2odf.mk +++ /dev/null @@ -1,46 +0,0 @@ -# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- -# -# 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/. -# - -$(eval $(call gb_Executable_Executable,svg2odf)) - -$(eval $(call gb_Executable_set_targettype_gui,svg2odf,YES)) - -$(eval $(call gb_Executable_use_external,svg2odf,boost_headers)) - -$(eval $(call gb_Executable_use_sdk_api,svg2odf)) - -$(eval $(call gb_Executable_set_include,svg2odf,\ - $$(INCLUDE) \ - -I$(SRCDIR)/filter/inc \ -)) - -$(eval $(call gb_Executable_use_libraries,svg2odf,\ - svgfilter \ - svxcore \ - editeng \ - xo \ - svt \ - vcl \ - svl \ - utl \ - tl \ - sax \ - comphelper \ - basegfx \ - cppuhelper \ - cppu \ - sal \ -)) - -$(eval $(call gb_Executable_add_exception_objects,svg2odf,\ - filter/source/svg/test/svg2odf \ - filter/source/svg/test/odfserializer \ -)) - -# vim: set ts=4 sw=4 et: diff --git a/filter/Library_svgfilter.mk b/filter/Library_svgfilter.mk index 9708b8ca6ed8..bdd917a50a0c 100644 --- a/filter/Library_svgfilter.mk +++ b/filter/Library_svgfilter.mk @@ -68,13 +68,7 @@ $(eval $(call gb_Library_use_externals,svgfilter,\ )) $(eval $(call gb_Library_add_exception_objects,svgfilter,\ - filter/source/svg/b2dellipse \ - filter/source/svg/parserfragments \ filter/source/svg/svgfilter \ - filter/source/svg/svgimport \ - filter/source/svg/svgreader \ - filter/source/svg/tokenmap \ - filter/source/svg/units \ filter/source/svg/svgexport \ filter/source/svg/svgfontexport \ filter/source/svg/svgwriter \ diff --git a/filter/Module_filter.mk b/filter/Module_filter.mk index 08aa0f2d395b..2d380fbd91ac 100644 --- a/filter/Module_filter.mk +++ b/filter/Module_filter.mk @@ -47,12 +47,6 @@ $(eval $(call gb_Module_add_l10n_targets,filter,\ AllLangMoTarget_flt \ )) -ifneq (,$(filter DESKTOP,$(BUILD_TYPE))) -$(eval $(call gb_Module_add_targets,filter,\ - Executable_svg2odf \ -)) -endif - $(eval $(call gb_Module_add_check_targets,filter,\ CppunitTest_filter_xslt \ CppunitTest_filter_priority \ diff --git a/filter/inc/parserfragments.hxx b/filter/inc/parserfragments.hxx deleted file mode 100644 index f8b456029892..000000000000 --- a/filter/inc/parserfragments.hxx +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- 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/. - */ -#ifndef INCLUDED_FILTER_INC_PARSERFRAGMENTS_HXX -#define INCLUDED_FILTER_INC_PARSERFRAGMENTS_HXX - -#include <sal/config.h> -#include <vector> -#include <utility> -#include <rtl/ustring.hxx> - -namespace basegfx -{ - class B2DHomMatrix; - class B2DRange; -} -namespace svgi -{ - struct ARGBColor; - - /// Parse given string for one of the SVG color grammars - bool parseColor( const char* sColor, ARGBColor& rColor ); - bool parseOpacity( const char* sOpacity, ARGBColor& rColor ); - - /// Parse given string for one of the SVG transformation grammars - bool parseTransform( const char* sTransform, basegfx::B2DHomMatrix& rTransform ); - - /// Parse given string for the viewBox attribute - bool parseViewBox( const char* sViewbox, basegfx::B2DRange& rRect ); - - /// Parse given string for a list of double values, comma-delimited - bool parseDashArray( const char* sDashArray, std::vector<double>& rOutputVector ); - - /** Parse paint uri - - @param o_rPaintUri - Start and end ptr for uri substring (within - [sPaintUri,sPaintUri+strlen(sPaintUri)] - - @param io_rColor - The optional paint color to use. if o_rPaintUri is empty, - parser sets io_rColor.second to false for color="None", to - true and keeps current io_rColor.first entry for - "currentColor", and to true and sets io_rColor.first to parsed - color otherwise. - - @param sPaintUri - String to parse. Permitted to contain the optional paint - stuff, like fallback color. - - @return true, if a paint uri was successfully parsed. - */ - bool parsePaintUri( std::pair<const char*,const char*>& o_rPaintUri, - std::pair<ARGBColor,bool>& io_rColor, - const char* sPaintUri ); - - /// Parse given string for the xlink attribute - bool parseXlinkHref( const char* xlink, OUString& data ); - -} // namespace svgi - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/inc/svgreader.hxx b/filter/inc/svgreader.hxx deleted file mode 100644 index 3149e1770158..000000000000 --- a/filter/inc/svgreader.hxx +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- 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/. - */ -#ifndef INCLUDED_FILTER_INC_SVGREADER_HXX -#define INCLUDED_FILTER_INC_SVGREADER_HXX - -#include <filter/dllapi.h> - -#include <com/sun/star/uno/XComponentContext.hpp> -#include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/xml/sax/XDocumentHandler.hpp> -#include <com/sun/star/io/XInputStream.hpp> -#include <xmloff/xmlimp.hxx> - -namespace svgi -{ - -class SVGReader -{ -private: - const css::uno::Reference< css::uno::XComponentContext > m_xContext; - const css::uno::Reference< css::io::XInputStream > m_xInputStream; - const css::uno::Reference< css::xml::sax::XDocumentHandler > m_xDocumentHandler; - - SVGReader( const css::uno::Reference<css::uno::XComponentContext>& xContext, - const css::uno::Reference< css::io::XInputStream >& xInputStream, - const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler, - SvXMLImport *pFastHandler); - -public: - FILTER_DLLPUBLIC SVGReader( const css::uno::Reference<css::uno::XComponentContext>& xContext, - const css::uno::Reference< css::io::XInputStream >& xInputStream, - const css::uno::Reference< css::xml::sax::XDocumentHandler >& xDocumentHandler ); - - FILTER_DLLPUBLIC bool parseAndConvert(); -}; - -} // namespace svgi - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu b/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu index b6d816ea4620..c5cae01dde53 100644 --- a/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu +++ b/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu @@ -26,5 +26,5 @@ <prop oor:name="FileFormatVersion"><value>0</value></prop> <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop> <prop oor:name="TemplateName"/> - <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop> + <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop> </node> diff --git a/filter/source/svg/b2dellipse.cxx b/filter/source/svg/b2dellipse.cxx deleted file mode 100644 index b4761090c446..000000000000 --- a/filter/source/svg/b2dellipse.cxx +++ /dev/null @@ -1,27 +0,0 @@ -/* -*- 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/. - */ -#include "b2dellipse.hxx" - -#include <basegfx/point/b2dpoint.hxx> -#include <basegfx/matrix/b2dhommatrix.hxx> - -namespace basegfx -{ - B2DEllipse::B2DEllipse(const basegfx::B2DPoint& rCenter, const basegfx::B2DTuple& rRadius) - : maCenter(rCenter), maRadius(rRadius) - { - } - - B2DEllipse::~B2DEllipse() - { - } - -} // end of namespace basegfx - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/b2dellipse.hxx b/filter/source/svg/b2dellipse.hxx deleted file mode 100644 index af97794ee420..000000000000 --- a/filter/source/svg/b2dellipse.hxx +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- 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/. - */ -#ifndef INCLUDED_FILTER_SOURCE_SVG_B2DELLIPSE_HXX -#define INCLUDED_FILTER_SOURCE_SVG_B2DELLIPSE_HXX - -#include <sal/types.h> - -#include <o3tl/cow_wrapper.hxx> - -#include <basegfx/point/b2dpoint.hxx> - -#include <basegfx/tuple/b2dtuple.hxx> - -#include <basegfx/vector/b2enums.hxx> - -namespace basegfx -{ - class B2DPoint; -} // end of namespace basegfx - -namespace basegfx -{ - class B2DEllipse - { - private: - const basegfx::B2DPoint maCenter; - const basegfx::B2DTuple maRadius; - - public: - B2DEllipse(const B2DEllipse& rEllipse); - B2DEllipse(const basegfx::B2DPoint& rCenter, const basegfx::B2DTuple& rRadius); - ~B2DEllipse(); - - // assignment operator - B2DEllipse& operator=(const B2DEllipse& rEllipse); - - // Coordinate interface - const basegfx::B2DPoint& getB2DEllipseCenter() const { return maCenter; } - const basegfx::B2DTuple& getB2DEllipseRadius() const { return maRadius; } - }; -} // end of namespace basegfx - -#endif // INCLUDED_FILTER_SOURCE_SVG_B2DELLIPSE_HXX - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/parserfragments.cxx b/filter/source/svg/parserfragments.cxx deleted file mode 100644 index 02c37089cf0d..000000000000 --- a/filter/source/svg/parserfragments.cxx +++ /dev/null @@ -1,587 +0,0 @@ -/* -*- 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/. - */ - -#include <parserfragments.hxx> -#include "spirit_supplements.hxx" -#include <gfxtypes.hxx> - -#include <basegfx/utils/canvastools.hxx> -#include <com/sun/star/geometry/AffineMatrix2D.hpp> - -#include <limits.h> -#include <boost/bind.hpp> -#include <boost/spirit/include/classic.hpp> -#include <boost/spirit/include/classic_while.hpp> -#include <numeric> -#include <algorithm> - -#include "units.hxx" -#include "tokenmap.hxx" -#include <sal/log.hxx> - -using namespace ::com::sun::star; - -namespace svgi -{ - -inline sal_uInt8 hex2int( char val ) -{ - return val <= '9' ? val-'0' : (val < 'a' ? val+10-'A' : val+10-'a'); -} - -void setFourBitColor( double& rChannel, char nChar ) -{ - const sal_uInt8 nVal(hex2int(nChar)); - rChannel = (nVal*16+nVal)/255.0; -} - -void setEightBitColor( double& rChannel, const char* pStart ) -{ - const sal_uInt8 nVal0(hex2int(pStart[0])); - const sal_uInt8 nVal1(hex2int(pStart[1])); - rChannel = (nVal0*16+nVal1)/255.0; -} - -void setIntColor( double& rChannel, sal_uInt8 nVal ) -{ - rChannel = nVal/255.0; -} - -void setPercentColor( double& rChannel, double nVal ) -{ - rChannel = nVal/100.0; -} - -void calcRotation(std::vector<geometry::AffineMatrix2D>& rTransforms, - geometry::AffineMatrix2D& rCurrTransform, - double fRotationAngle) -{ - ::basegfx::B2DHomMatrix aCurr; - aCurr.translate(-rCurrTransform.m02,-rCurrTransform.m12); - aCurr.rotate(fRotationAngle*M_PI/180); - aCurr.translate(rCurrTransform.m02,rCurrTransform.m12); - - rTransforms.push_back( - basegfx::unotools::affineMatrixFromHomMatrix( - rCurrTransform, - aCurr)); -} - -void calcSkewX(std::vector<geometry::AffineMatrix2D>& rTransforms, - double fSkewAngle) -{ - geometry::AffineMatrix2D aMat(1.0,tan(fSkewAngle*M_PI/180),0.0, - 0.0,1.0,0.0); - rTransforms.push_back(aMat); -} - -void calcSkewY(std::vector<geometry::AffineMatrix2D>& rTransforms, - double fSkewAngle) -{ - geometry::AffineMatrix2D aMat(1.0,0.0,0.0, - tan(fSkewAngle*M_PI/180),1.0,0.0); - rTransforms.push_back(aMat); -} - -void assign_twice(double& r_oVal1, double& r_oVal2, const double& rInVal ) -{ - r_oVal1 = r_oVal2 = rInVal; -} - -geometry::AffineMatrix2D multiplyMatrix( const geometry::AffineMatrix2D& rLHS, - const geometry::AffineMatrix2D& rRHS ) -{ - basegfx::B2DHomMatrix aLHS; - basegfx::B2DHomMatrix aRHS; - - basegfx::unotools::homMatrixFromAffineMatrix(aLHS,rLHS); - basegfx::unotools::homMatrixFromAffineMatrix(aRHS,rRHS); - - aRHS*=aLHS; - - geometry::AffineMatrix2D aRet; - return basegfx::unotools::affineMatrixFromHomMatrix(aRet,aRHS); -} - -namespace -{ - struct ColorGrammar : public ::boost::spirit::classic::grammar< ColorGrammar > - { - public: - ARGBColor& m_rColor; - explicit ColorGrammar( ARGBColor& rColor ) : m_rColor(rColor) {} - template< typename ScannerT > - struct definition - { - ::boost::spirit::classic::rule< ScannerT > colorExpression; - explicit definition( const ColorGrammar& self ) - { - using namespace ::boost::spirit::classic; - - auto lambdaSetEightBitColorR = [&self](const char* pStart, const char* /*nChar*/){ setEightBitColor(self.m_rColor.r, pStart); }; - auto lambdaSetEightBitColorG = [&self](const char* pStart, const char* /*nChar*/){ setEightBitColor(self.m_rColor.g, pStart); }; - auto lambdaSetEightBitColorB = [&self](const char* pStart, const char* /*nChar*/){ setEightBitColor(self.m_rColor.b, pStart); }; - auto lambdaSetFourBitColorR = [&self](char nChar){ setFourBitColor(self.m_rColor.r, nChar); }; - auto lambdaSetFourBitColorG = [&self](char nChar){ setFourBitColor(self.m_rColor.g, nChar); }; - auto lambdaSetFourBitColorB = [&self](char nChar){ setFourBitColor(self.m_rColor.b, nChar); }; - auto lambdaSetIntColorR = [&self](sal_uInt8 nVal){ setIntColor(self.m_rColor.r, nVal); }; - auto lambdaSetIntColorG = [&self](sal_uInt8 nVal){ setIntColor(self.m_rColor.g, nVal); }; - auto lambdaSetIntColorB = [&self](sal_uInt8 nVal){ setIntColor(self.m_rColor.b, nVal); }; - auto lambdaSetPercentColorR = [&self](double nVal){ setPercentColor(self.m_rColor.r, nVal); }; - auto lambdaSetPercentColorG = [&self](double nVal){ setPercentColor(self.m_rColor.g, nVal); }; - auto lambdaSetPercentColorB = [&self](double nVal){ setPercentColor(self.m_rColor.b, nVal); }; - int_parser<sal_uInt8,10,1,3> byte_p; - colorExpression = - ( - // the #rrggbb form - ('#' >> (xdigit_p >> xdigit_p)[ lambdaSetEightBitColorR ] - >> (xdigit_p >> xdigit_p)[ lambdaSetEightBitColorG ] - >> (xdigit_p >> xdigit_p)[ lambdaSetEightBitColorB ] ) - | - // the #rgb form - ('#' >> xdigit_p[ lambdaSetFourBitColorR ] - >> xdigit_p[ lambdaSetFourBitColorG ] - >> xdigit_p[ lambdaSetFourBitColorB ] ) - | - // rgb() form - (str_p("rgb") - >> '(' >> - ( - // rgb(int,int,int) - (byte_p[ lambdaSetIntColorR ] >> ',' >> - byte_p[ lambdaSetIntColorG ] >> ',' >> - byte_p[ lambdaSetIntColorB ] ) - | - // rgb(double,double,double) - (real_p[assign_a(self.m_rColor.r)] >> ',' >> - real_p[assign_a(self.m_rColor.g)] >> ',' >> - real_p[assign_a(self.m_rColor.b)]) - | - // rgb(percent,percent,percent) - (real_p[ lambdaSetPercentColorR ] >> "%," >> - real_p[ lambdaSetPercentColorG ] >> "%," >> - real_p[ lambdaSetPercentColorB ] >> "%") - ) - >> ')') - ); - } - ::boost::spirit::classic::rule<ScannerT> const& start() const { return colorExpression; } - }; - }; -} - -bool parseColor( const char* sColor, ARGBColor& rColor ) -{ - using namespace ::boost::spirit::classic; - - if( parse(sColor, - ColorGrammar(rColor) >> end_p, - space_p).full ) - { - // free-form color found & parsed - return true; - } - - // no free-form color - maybe a color name? - // trim white space before - while( *sColor && - (*sColor==' ' || *sColor=='\t' || *sColor=='\r' || *sColor=='\n') ) - ++sColor; - // trim white space after - int nLen=strlen(sColor)-1; - while( nLen && - (sColor[nLen]==' ' || sColor[nLen]=='\t' || sColor[nLen]=='\r' || sColor[nLen]=='\n') ) - --nLen; - switch (getTokenId(sColor, nLen+1)) - { - case XML_ALICEBLUE: rColor = ARGBColor(240,248,255); return true; - case XML_ANTIQUEWHITE: rColor = ARGBColor(250,235,215); return true; - case XML_AQUA: rColor = ARGBColor(0,255,255); return true; - case XML_AQUAMARINE: rColor = ARGBColor(127,255,212); return true; - case XML_AZURE: rColor = ARGBColor(240,255,255); return true; - case XML_BEIGE: rColor = ARGBColor(245,245,220); return true; - case XML_BISQUE: rColor = ARGBColor(255,228,196); return true; - case XML_BLACK: rColor = ARGBColor(0,0,0); return true; - case XML_BLANCHEDALMOND: rColor = ARGBColor(255,235,205); return true; - case XML_BLUE: rColor = ARGBColor(0,0,255); return true; - case XML_BLUEVIOLET: rColor = ARGBColor(138,43,226); return true; - case XML_BROWN: rColor = ARGBColor(165,42,42); return true; - case XML_BURLYWOOD: rColor = ARGBColor(222,184,135); return true; - case XML_CADETBLUE: rColor = ARGBColor(95,158,160); return true; - case XML_CHARTREUSE: rColor = ARGBColor(127,255,0); return true; - case XML_CHOCOLATE: rColor = ARGBColor(210,105,30); return true; - case XML_CORAL: rColor = ARGBColor(255,127,80); return true; - case XML_CORNFLOWERBLUE: rColor = ARGBColor(100,149,237); return true; - case XML_CORNSILK: rColor = ARGBColor(255,248,220); return true; - case XML_CRIMSON: rColor = ARGBColor(220,20,60); return true; - case XML_CYAN: rColor = ARGBColor(0,255,255); return true; - case XML_DARKBLUE: rColor = ARGBColor(0,0,139); return true; - case XML_DARKCYAN: rColor = ARGBColor(0,139,139); return true; - case XML_DARKGOLDENROD: rColor = ARGBColor(184,134,11); return true; - case XML_DARKGRAY: rColor = ARGBColor(169,169,169); return true; - case XML_DARKGREEN: rColor = ARGBColor(0,100,0); return true; - case XML_DARKGREY: rColor = ARGBColor(169,169,169); return true; - case XML_DARKKHAKI: rColor = ARGBColor(189,183,107); return true; - case XML_DARKMAGENTA: rColor = ARGBColor(139,0,139); return true; - case XML_DARKOLIVEGREEN: rColor = ARGBColor(85,107,47); return true; - case XML_DARKORANGE: rColor = ARGBColor(255,140,0); return true; - case XML_DARKORCHID: rColor = ARGBColor(153,50,204); return true; - case XML_DARKRED: rColor = ARGBColor(139,0,0); return true; - case XML_DARKSALMON: rColor = ARGBColor(233,150,122); return true; - case XML_DARKSEAGREEN: rColor = ARGBColor(143,188,143); return true; - case XML_DARKSLATEBLUE: rColor = ARGBColor(72,61,139); return true; - case XML_DARKSLATEGRAY: rColor = ARGBColor(47,79,79); return true; - case XML_DARKSLATEGREY: rColor = ARGBColor(47,79,79); return true; - case XML_DARKTURQUOISE: rColor = ARGBColor(0,206,209); return true; - case XML_DARKVIOLET: rColor = ARGBColor(148,0,211); return true; - case XML_DEEPPINK: rColor = ARGBColor(255,20,147); return true; - case XML_DEEPSKYBLUE: rColor = ARGBColor(0,191,255); return true; - case XML_DIMGRAY: rColor = ARGBColor(105,105,105); return true; - case XML_DIMGREY: rColor = ARGBColor(105,105,105); return true; - case XML_DODGERBLUE: rColor = ARGBColor(30,144,255); return true; - case XML_FIREBRICK: rColor = ARGBColor(178,34,34); return true; - case XML_FLORALWHITE: rColor = ARGBColor(255,250,240); return true; - case XML_FORESTGREEN: rColor = ARGBColor(34,139,34); return true; - case XML_FUCHSIA: rColor = ARGBColor(255,0,255); return true; - case XML_GAINSBORO: rColor = ARGBColor(220,220,220); return true; - case XML_GHOSTWHITE: rColor = ARGBColor(248,248,255); return true; - case XML_GOLD: rColor = ARGBColor(255,215,0); return true; - case XML_GOLDENROD: rColor = ARGBColor(218,165,32); return true; - case XML_GRAY: rColor = ARGBColor(128,128,128); return true; - case XML_GREY: rColor = ARGBColor(128,128,128); return true; - case XML_GREEN: rColor = ARGBColor(0,128,0); return true; - case XML_GREENYELLOW: rColor = ARGBColor(173,255,47); return true; - case XML_HONEYDEW: rColor = ARGBColor(240,255,240); return true; - case XML_HOTPINK: rColor = ARGBColor(255,105,180); return true; - case XML_INDIANRED: rColor = ARGBColor(205,92,92); return true; - case XML_INDIGO: rColor = ARGBColor(75,0,130); return true; - case XML_IVORY: rColor = ARGBColor(255,255,240); return true; - case XML_KHAKI: rColor = ARGBColor(240,230,140); return true; - case XML_LAVENDER: rColor = ARGBColor(230,230,250); return true; - case XML_LAVENDERBLUSH: rColor = ARGBColor(255,240,245); return true; - case XML_LAWNGREEN: rColor = ARGBColor(124,252,0); return true; - case XML_LEMONCHIFFON: rColor = ARGBColor(255,250,205); return true; - case XML_LIGHTBLUE: rColor = ARGBColor(173,216,230); return true; - case XML_LIGHTCORAL: rColor = ARGBColor(240,128,128); return true; - case XML_LIGHTCYAN: rColor = ARGBColor(224,255,255); return true; - case XML_LIGHTGOLDENRODYELLOW: rColor = ARGBColor(250,250,210); return true; - case XML_LIGHTGRAY: rColor = ARGBColor(211,211,211); return true; - case XML_LIGHTGREEN: rColor = ARGBColor(144,238,144); return true; - case XML_LIGHTGREY: rColor = ARGBColor(211,211,211); return true; - case XML_LIGHTPINK: rColor = ARGBColor(255,182,193); return true; - case XML_LIGHTSALMON: rColor = ARGBColor(255,160,122); return true; - case XML_LIGHTSEAGREEN: rColor = ARGBColor(32,178,170); return true; - case XML_LIGHTSKYBLUE: rColor = ARGBColor(135,206,250); return true; - case XML_LIGHTSLATEGRAY: rColor = ARGBColor(119,136,153); return true; - case XML_LIGHTSLATEGREY: rColor = ARGBColor(119,136,153); return true; - case XML_LIGHTSTEELBLUE: rColor = ARGBColor(176,196,222); return true; - case XML_LIGHTYELLOW: rColor = ARGBColor(255,255,224); return true; - case XML_LIME: rColor = ARGBColor(0,255,0); return true; - case XML_LIMEGREEN: rColor = ARGBColor(50,205,50); return true; - case XML_LINEN: rColor = ARGBColor(250,240,230); return true; - case XML_MAGENTA: rColor = ARGBColor(255,0,255); return true; - case XML_MAROON: rColor = ARGBColor(128,0,0); return true; - case XML_MEDIUMAQUAMARINE: rColor = ARGBColor(102,205,170); return true; - case XML_MEDIUMBLUE: rColor = ARGBColor(0,0,205); return true; - case XML_MEDIUMORCHID: rColor = ARGBColor(186,85,211); return true; - case XML_MEDIUMPURPLE: rColor = ARGBColor(147,112,219); return true; - case XML_MEDIUMSEAGREEN: rColor = ARGBColor(60,179,113); return true; - case XML_MEDIUMSLATEBLUE: rColor = ARGBColor(123,104,238); return true; - case XML_MEDIUMSPRINGGREEN: rColor = ARGBColor(0,250,154); return true; - case XML_MEDIUMTURQUOISE: rColor = ARGBColor(72,209,204); return true; - case XML_MEDIUMVIOLETRED: rColor = ARGBColor(199,21,133); return true; - case XML_MIDNIGHTBLUE: rColor = ARGBColor(25,25,112); return true; - case XML_MINTCREAM: rColor = ARGBColor(245,255,250); return true; - case XML_MISTYROSE: rColor = ARGBColor(255,228,225); return true; - case XML_MOCCASIN: rColor = ARGBColor(255,228,181); return true; - case XML_NAVAJOWHITE: rColor = ARGBColor(255,222,173); return true; - case XML_NAVY: rColor = ARGBColor(0,0,128); return true; - case XML_OLDLACE: rColor = ARGBColor(253,245,230); return true; - case XML_OLIVE: rColor = ARGBColor(128,128,0); return true; - case XML_OLIVEDRAB: rColor = ARGBColor(107,142,35); return true; - case XML_ORANGE: rColor = ARGBColor(255,165,0); return true; - case XML_ORANGERED: rColor = ARGBColor(255,69,0); return true; - case XML_ORCHID: rColor = ARGBColor(218,112,214); return true; - case XML_PALEGOLDENROD: rColor = ARGBColor(238,232,170); return true; - case XML_PALEGREEN: rColor = ARGBColor(152,251,152); return true; - case XML_PALETURQUOISE: rColor = ARGBColor(175,238,238); return true; - case XML_PALEVIOLETRED: rColor = ARGBColor(219,112,147); return true; - case XML_PAPAYAWHIP: rColor = ARGBColor(255,239,213); return true; - case XML_PEACHPUFF: rColor = ARGBColor(255,218,185); return true; - case XML_PERU: rColor = ARGBColor(205,133,63); return true; - case XML_PINK: rColor = ARGBColor(255,192,203); return true; - case XML_PLUM: rColor = ARGBColor(221,160,221); return true; - case XML_POWDERBLUE: rColor = ARGBColor(176,224,230); return true; - case XML_PURPLE: rColor = ARGBColor(128,0,128); return true; - case XML_RED: rColor = ARGBColor(255,0,0); return true; - case XML_ROSYBROWN: rColor = ARGBColor(188,143,143); return true; - case XML_ROYALBLUE: rColor = ARGBColor(65,105,225); return true; - case XML_SADDLEBROWN: rColor = ARGBColor(139,69,19); return true; - case XML_SALMON: rColor = ARGBColor(250,128,114); return true; - case XML_SANDYBROWN: rColor = ARGBColor(244,164,96); return true; - case XML_SEAGREEN: rColor = ARGBColor(46,139,87); return true; - case XML_SEASHELL: rColor = ARGBColor(255,245,238); return true; - case XML_SIENNA: rColor = ARGBColor(160,82,45); return true; - case XML_SILVER: rColor = ARGBColor(192,192,192); return true; - case XML_SKYBLUE: rColor = ARGBColor(135,206,235); return true; - case XML_SLATEBLUE: rColor = ARGBColor(106,90,205); return true; - case XML_SLATEGRAY: rColor = ARGBColor(112,128,144); return true; - case XML_SLATEGREY: rColor = ARGBColor(112,128,144); return true; - case XML_SNOW: rColor = ARGBColor(255,250,250); return true; - case XML_SPRINGGREEN: rColor = ARGBColor(0,255,127); return true; - case XML_STEELBLUE: rColor = ARGBColor(70,130,180); return true; - case XML_TAN: rColor = ARGBColor(210,180,140); return true; - case XML_TEAL: rColor = ARGBColor(0,128,128); return true; - case XML_THISTLE: rColor = ARGBColor(216,191,216); return true; - case XML_TOMATO: rColor = ARGBColor(255,99,71); return true; - case XML_TURQUOISE: rColor = ARGBColor(64,224,208); return true; - case XML_VIOLET: rColor = ARGBColor(238,130,238); return true; - case XML_WHEAT: rColor = ARGBColor(245,222,179); return true; - case XML_WHITE: rColor = ARGBColor(255,255,255); return true; - case XML_WHITESMOKE: rColor = ARGBColor(245,245,245); return true; - case XML_YELLOW: rColor = ARGBColor(255,255,0); return true; - case XML_YELLOWGREEN: rColor = ARGBColor(154,205,50); return true; - - default: - return false; // no color at all, I'd guess. - } -} - -bool parseOpacity (const char* sOpacity, ARGBColor& rColor ) -{ - using namespace ::boost::spirit::classic; - - if( parse(sOpacity, - // Begin grammar - ( - real_p[assign_a(rColor.a)] - ) >> end_p, - // End grammar - space_p).full ) - { - return true; - } - return false; -} - - -bool parseTransform( const char* sTransform, basegfx::B2DHomMatrix& rTransform ) -{ - using namespace ::boost::spirit::classic; - - double fRefOffsetX(0.0); - double fRefOffsetY(0.0); - bool bRefTransform(false); - - double fRotationAngle=0.0; - double fSkewAngle=0.0; - geometry::AffineMatrix2D aIdentityTransform; - geometry::AffineMatrix2D aCurrTransform; - std::vector<geometry::AffineMatrix2D> aTransforms; - aIdentityTransform.m00 = 1.0; aIdentityTransform.m11 = 1.0; - aCurrTransform = aIdentityTransform; - - const bool bRes = parse(sTransform, - // Begin grammar - ( - // identity transform - str_p("none") - | - // the ref() form - (str_p("ref") - >> '(' - >> str_p("svg")[assign_a(bRefTransform,true)] - >> !(real_p[assign_a(fRefOffsetX)] >> (',' | eps_p) >> - real_p[assign_a(fRefOffsetY)]) - >> ')') - | - // the transform-list form - (list_p( - ( - // matrix(a,b,c,d,e,f) - (str_p("matrix") - >> '(' - >> real_p[assign_a(aCurrTransform.m00)] >> (',' | eps_p) - >> real_p[assign_a(aCurrTransform.m10)] >> (',' | eps_p) - >> real_p[assign_a(aCurrTransform.m01)] >> (',' | eps_p) - >> real_p[assign_a(aCurrTransform.m11)] >> (',' | eps_p) - >> real_p[assign_a(aCurrTransform.m02)] >> (',' | eps_p) - >> real_p[assign_a(aCurrTransform.m12)] - >> ')')[push_back_a(aTransforms,aCurrTransform)] - | - // translate(x,[y]) - (str_p("translate") - >> '(' - >> real_p[boost::bind(&assign_twice, - boost::ref(aCurrTransform.m02), - boost::ref(aCurrTransform.m12),_1)] - >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m12)]) - >> ')')[push_back_a(aTransforms,aCurrTransform)] - | - // scale(x,[y]) - (str_p("scale") - >> '(' - >> real_p[boost::bind(&assign_twice, - boost::ref(aCurrTransform.m00), - boost::ref(aCurrTransform.m11),_1)] - >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m11)]) - >> ')')[push_back_a(aTransforms,aCurrTransform)] - | - // rotate(phi,[cx, cy]) - (str_p("rotate") - >> '(' - >> real_p[assign_a(fRotationAngle)] - >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m02)] - >> (',' | eps_p) >> real_p[assign_a(aCurrTransform.m12)]) - >> ')')[boost::bind(&calcRotation, - boost::ref(aTransforms), - boost::ref(aCurrTransform), - boost::cref(fRotationAngle))] - | - // skewX(phi) - (str_p("skewX") - >> '(' - >> real_p[assign_a(fSkewAngle)] - >> ')')[boost::bind(&calcSkewX, - boost::ref(aTransforms), - boost::cref(fSkewAngle))] - | - // skewY(phi) - (str_p("skewY") - >> '(' - >> real_p[assign_a(fSkewAngle)] - >> ')')[boost::bind(&calcSkewY, - boost::ref(aTransforms), - boost::cref(fSkewAngle))] - // reset current transform after every push - )[assign_a(aCurrTransform,aIdentityTransform)], - // list delimiter is either ',' or space - ',' | eps_p )) - ) >> end_p, - // End grammar - space_p).full; - - if( !bRes ) - return false; - - // fold all transformations into one - const geometry::AffineMatrix2D aTotalTransform( - std::accumulate(aTransforms.begin(), - aTransforms.end(), - aIdentityTransform, - &multiplyMatrix)); - - basegfx::unotools::homMatrixFromAffineMatrix( - rTransform, - aTotalTransform); - - // TODO(F1): handle the ref case - return bRes; -} - - -bool parseViewBox( const char* sViewbox, basegfx::B2DRange& rRect ) -{ - using namespace ::boost::spirit::classic; - - double x=0.0,y=0.0,w=0.0,h=0.0; - - const bool bRes = parse(sViewbox, - // Begin grammar - ( - // either comma- or space-delimited list of four doubles - real_p[assign_a(x)] >> (',' | eps_p) >> - real_p[assign_a(y)] >> (',' | eps_p) >> - real_p[assign_a(w)] >> (',' | eps_p) >> - real_p[assign_a(h)] >> end_p - ), - // End grammar - space_p).full; - - if( !bRes ) - return false; - - rRect = basegfx::B2DRange(x,y,x+w,y+h); - - return true; -} - - -bool parseDashArray( const char* sDashArray, std::vector<double>& rOutputVector ) -{ - using namespace ::boost::spirit::classic; - - rOutputVector.clear(); - return parse(sDashArray, - // Begin grammar - ( - // parse comma-delimited list of doubles (have to use the - // 'direct' variant, as otherwise spirit refactors our - // parser to push both real num and comma to push_back_a) - list_p.direct - ( - real_p[push_back_a(rOutputVector)], - // list delimiter is either ',' or space - ',' | eps_p - ) - ) >> end_p, - // End grammar - space_p).full; -} - - -bool parsePaintUri( std::pair<const char*,const char*>& o_rPaintUri, - std::pair<ARGBColor,bool>& io_rColor, - const char* sPaintUri ) -{ - using namespace ::boost::spirit::classic; - - const bool bRes = parse(sPaintUri, - // Begin grammar - ( - str_p("url(") >> !( str_p("'") ) >> "#" >> - (+(anychar_p - (str_p("'") | str_p(")"))))[assign_a(o_rPaintUri)] >> - !( str_p("'") ) >> str_p(")") >> - *( str_p("none")[assign_a(io_rColor.second,false)] | - str_p("currentColor")[assign_a(io_rColor.second,true)] | - ColorGrammar(io_rColor.first) - // TODO(F1): named color - ) - ) >> end_p, - // End grammar - space_p).full; - - return bRes; -} - - -bool parseXlinkHref( const char* sXlinkHref, OUString& data ) -{ - OUString sLink(OUString::createFromAscii(sXlinkHref)); - - if (sLink.startsWith("data:")) - { - sal_Int32 nIndex=0; - OUString aCurrToken = sLink.getToken(0,',',nIndex); - - // the inplace "data" uri - if ( !aCurrToken.isEmpty() ) - { - data = sLink.copy(nIndex); - SAL_INFO("filter.svg", data); - return true; - } - } - - return false; -} - -} // namespace svgi - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/svgfilter.cxx b/filter/source/svg/svgfilter.cxx index 94fe876e3faa..1ec09f65ab05 100644 --- a/filter/source/svg/svgfilter.cxx +++ b/filter/source/svg/svgfilter.cxx @@ -52,6 +52,12 @@ #include "svgfilter.hxx" #include "svgwriter.hxx" +#include <svx/unopage.hxx> +#include <vcl/graphicfilter.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdograf.hxx> +#include <svl/itempool.hxx> + #include <memory> using namespace ::com::sun::star; @@ -94,14 +100,185 @@ SVGFilter::~SVGFilter() sal_Bool SAL_CALL SVGFilter::filter( const Sequence< PropertyValue >& rDescriptor ) { SolarMutexGuard aGuard; - vcl::Window* pFocusWindow = Application::GetFocusWindow(); - bool bRet; + vcl::Window* pFocusWindow(Application::GetFocusWindow()); + bool bRet(false); - if( pFocusWindow ) + if(pFocusWindow) + { pFocusWindow->EnterWait(); + } + + if(mxDstDoc.is()) + { + // Import. Use an endless loop to have easy exits for error handling + while(true) + { + // use MediaDescriptor to get needed data out of Sequence< PropertyValue > + utl::MediaDescriptor aMediaDescriptor(rDescriptor); + uno::Reference<io::XInputStream> xInputStream; + uno::Reference<task::XStatusIndicator> xStatus; + + xInputStream.set(aMediaDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()], UNO_QUERY); + xStatus.set(aMediaDescriptor[utl::MediaDescriptor::PROP_STATUSINDICATOR()], UNO_QUERY); + + if(!xInputStream.is() || !xStatus.is()) + { + // we need the InputStream and StatusIndicator + break; + } + + // get the DrawPagesSupplier + uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSupplier( mxDstDoc, uno::UNO_QUERY ); + + if(!xDrawPagesSupplier.is()) + { + // we need the DrawPagesSupplier + break; + } + + // get the DrawPages + uno::Reference< drawing::XDrawPages > xDrawPages( xDrawPagesSupplier->getDrawPages(), uno::UNO_QUERY ); + + if(!xDrawPages.is()) + { + // we need the DrawPages + break; + } + + // check DrawPageCount (there should be one by default) + sal_Int32 nDrawPageCount(xDrawPages->getCount()); + + if(0 == nDrawPageCount) + { + // at least one DrawPage should be there - we need that + break; + } + + // get that DrawPage + uno::Reference< drawing::XDrawPage > xDrawPage( xDrawPages->getByIndex(0), uno::UNO_QUERY ); + + if(!xDrawPage.is()) + { + // we need that DrawPage + break; + } - if( mxDstDoc.is() ) - bRet = implImport( rDescriptor ); + // get that DrawPage's UNO API implementation + SvxDrawPage* pSvxDrawPage(SvxDrawPage::getImplementation(xDrawPage)); + + if(nullptr == pSvxDrawPage || nullptr == pSvxDrawPage->GetSdrPage()) + { + // we need a SvxDrawPage + break; + } + + // get the SvStream to work with + std::unique_ptr< SvStream > aStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + + if(!aStream.get()) + { + // we need the SvStream + break; + } + + // create a GraphicFilter and load the SVG (format already known, thus *could* + // be handed over to ImportGraphic - but detection is fast). + // As a bonus, zipped data is already detected and handled there + GraphicFilter aGraphicFilter; + Graphic aGraphic; + const ErrCode nGraphicFilterErrorCode(aGraphicFilter.ImportGraphic(aGraphic, OUString(), *aStream.get())); + + if(ERRCODE_NONE != nGraphicFilterErrorCode) + { + // SVG import error, cannot continue + break; + } + + // get the GraphicPrefSize early to check if we have any content + // (the SVG may contain nothing and/or just <g visibility="hidden"> stuff...) + const Size aGraphicPrefSize(aGraphic.GetPrefSize()); + + if(0 == aGraphicPrefSize.Width() || 0 == aGraphicPrefSize.Height()) + { + // SVG has no displayable content, stop import. + // Also possible would be to get the sequence< Primitives > + // from aGraphic and check if it is empty. + // Possibility to set some error message here to tell + // the user what/why loading went wrong, but I do not + // know how this could be done here + break; + } + + // create a SdrModel-GraphicObject to insert to page + SdrPage* pTargetSdrPage(pSvxDrawPage->GetSdrPage()); + std::unique_ptr< SdrGrafObj, SdrObjectFreeOp > aNewSdrGrafObj( + new SdrGrafObj( + pTargetSdrPage->getSdrModelFromSdrPage(), + aGraphic)); + + if(!aNewSdrGrafObj.get()) + { + // could not create GraphicObject + break; + } + + // Evtl. adapt the GraphicPrefSize to target-MapMode of target-Model + // (should be 100thmm here, but just stay safe by doing the conversion) + const MapMode aGraphicPrefMapMode(aGraphic.GetPrefMapMode()); + const MapUnit eDestUnit(pTargetSdrPage->getSdrModelFromSdrPage().GetItemPool().GetMetric(0)); + const MapUnit eSrcUnit(aGraphicPrefMapMode.GetMapUnit()); + Size aGraphicSize(aGraphicPrefSize); + + if (eDestUnit != eSrcUnit) + { + aGraphicSize = Size( + OutputDevice::LogicToLogic(aGraphicSize.Width(), eSrcUnit, eDestUnit), + OutputDevice::LogicToLogic(aGraphicSize.Height(), eSrcUnit, eDestUnit)); + } + + // Based on GraphicSize, set size of Page. Do not forget to adapt PageBorders, + // but interpret them relative to PageSize so that they do not 'expolde/shrink' + // in comparison. Use a common scaling factor for hor/ver to not get + // asynchronous border distances, though. All in all this will adapt borders + // nicely and is based on office-defaults for standard-page-border-sizes. + const Size aPageSize(pTargetSdrPage->GetSize()); + const double fBorderRelation(( + static_cast< double >(pTargetSdrPage->GetLeftBorder()) / aPageSize.Width() + + static_cast< double >(pTargetSdrPage->GetRightBorder()) / aPageSize.Width() + + static_cast< double >(pTargetSdrPage->GetUpperBorder()) / aPageSize.Height() + + static_cast< double >(pTargetSdrPage->GetLowerBorder()) / aPageSize.Height()) / 4.0); + const long nAllBorder(basegfx::fround((aGraphicSize.Width() + aGraphicSize.Height()) * fBorderRelation * 0.5)); + + // Adapt PageSize and Border stuff. To get all MasterPages and PresObjs + // correctly adapted, do not just use + // pTargetSdrPage->SetBorder(...) and + // pTargetSdrPage->SetSize(...), + // but ::adaptSizeAndBorderForAllPages + pTargetSdrPage->getSdrModelFromSdrPage().adaptSizeAndBorderForAllPages( + Size( + aGraphicSize.Width() + nAllBorder + nAllBorder, + aGraphicSize.Height() + nAllBorder + nAllBorder), + nAllBorder, + nAllBorder, + nAllBorder, + nAllBorder); + + // set pos/size at SdrGraphicObj - add offset to PageBorder + aNewSdrGrafObj->SetSnapRect( + tools::Rectangle( + Point(nAllBorder, nAllBorder), + aGraphicSize)); + + // insert to page (owner change of SdrGrafObj) + pTargetSdrPage->InsertObject(aNewSdrGrafObj.release()); + + // done - set positive result now + bRet = true; + + // always leave helper endless loop + break; + }; + } else if( mxSrcDoc.is() ) { // #i124608# detect selection diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx index 63616a9e0c53..5f117c3310ee 100644 --- a/filter/source/svg/svgfilter.hxx +++ b/filter/source/svg/svgfilter.hxx @@ -223,9 +223,6 @@ private: Link<EditFieldInfo*,void> maNewFieldHdl; /// @throws css::uno::RuntimeException - bool implImport( const Sequence< PropertyValue >& rDescriptor ); - - /// @throws css::uno::RuntimeException bool implExport( const Sequence< PropertyValue >& rDescriptor ); static Reference< XWriter > implCreateExportDocumentHandler( const Reference< XOutputStream >& rxOStm ); diff --git a/filter/source/svg/svgimport.cxx b/filter/source/svg/svgimport.cxx deleted file mode 100644 index 5b39d2aa9c37..000000000000 --- a/filter/source/svg/svgimport.cxx +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- 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 . - */ - - -#include "svgfilter.hxx" -#include <svgreader.hxx> - -#include <rtl/ref.hxx> - -#include <com/sun/star/lang/XMultiServiceFactory.hpp> - -#include <com/sun/star/lang/XComponent.hpp> - -#include <com/sun/star/uno/Any.hxx> - -#include <com/sun/star/beans/PropertyValue.hpp> - -#include <com/sun/star/xml/sax/XParser.hpp> -#include <com/sun/star/xml/sax/InputSource.hpp> -#include <com/sun/star/xml/XImportFilter.hpp> - -#include <com/sun/star/io/XActiveDataSource.hpp> -#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> -#include <com/sun/star/task/XStatusIndicator.hpp> - -#include <unotools/mediadescriptor.hxx> -#include <unotools/ucbstreamhelper.hxx> -#include <tools/zcodec.hxx> - -#include <memory> - -using namespace ::com::sun::star; -using namespace ::svgi; - -bool SVGFilter::implImport(const Sequence< PropertyValue >& rDescriptor) -{ - utl::MediaDescriptor aMediaDescriptor(rDescriptor); - uno::Reference<io::XInputStream> xInputStream; - uno::Reference<task::XStatusIndicator> xStatus; - - xInputStream.set(aMediaDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()], UNO_QUERY); - xStatus.set(aMediaDescriptor[utl::MediaDescriptor::PROP_STATUSINDICATOR()], UNO_QUERY); - - if (isStreamGZip(xInputStream)) - { - uno::Reference<io::XSeekable> xSeek(xInputStream, uno::UNO_QUERY); - if (!xSeek.is()) - return false; - xSeek->seek(0); - - std::unique_ptr<SvStream> aStream(utl::UcbStreamHelper::CreateStream(xInputStream, true )); - if(!aStream.get()) - return false; - - SvStream* pMemoryStream = new SvMemoryStream; - ZCodec aCodec; - aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, false, true); - aCodec.Decompress(*aStream.get(), *pMemoryStream); - aCodec.EndCompression(); - pMemoryStream->Seek(STREAM_SEEK_TO_BEGIN); - uno::Reference<io::XInputStream> xDecompressedInput(new utl::OSeekableInputStreamWrapper(pMemoryStream, true)); - if (!xDecompressedInput.is()) - return false; - xInputStream = xDecompressedInput; - } - else - { - uno::Reference<io::XSeekable> xSeek(xInputStream, uno::UNO_QUERY); - if (xSeek.is()) - xSeek->seek(0); - } - - OSL_ASSERT(xInputStream.is()); - if(!xInputStream.is()) - return false; - - Reference < XDocumentHandler > xInternalHandler( - mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.comp.Draw.XMLOasisImporter", mxContext ), UNO_QUERY ); - - // The XImporter sets up an empty target document for XDocumentHandler to write to.. - uno::Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY); - xImporter->setTargetDocument(mxDstDoc); - - bool bRet = false; - SVGReader aReader(mxContext, xInputStream, xInternalHandler); - try - { - bRet = aReader.parseAndConvert(); - } - catch (const RuntimeException&) - { - throw; - } - catch (const Exception& e) - { - throw css::lang::WrappedTargetRuntimeException("SVGFilter::implImport non-RuntimeException", - static_cast<uno::XWeak*>(this), uno::makeAny(e)); - } - return bRet; -} - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/svgreader.cxx b/filter/source/svg/svgreader.cxx deleted file mode 100644 index 1bffc82e9190..000000000000 --- a/filter/source/svg/svgreader.cxx +++ /dev/null @@ -1,2304 +0,0 @@ -/* -*- 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/. - */ - -#include <svgreader.hxx> -#include <xmloff/attrlist.hxx> -#include <gfxtypes.hxx> -#include "units.hxx" -#include <parserfragments.hxx> -#include "tokenmap.hxx" -#include "b2dellipse.hxx" - -#include <rtl/math.hxx> -#include <rtl/ref.hxx> -#include <rtl/ustring.hxx> -#include <rtl/ustrbuf.hxx> -#include <basegfx/vector/b2enums.hxx> -#include <basegfx/range/b2drange.hxx> -#include <basegfx/matrix/b2dhommatrix.hxx> -#include <basegfx/polygon/b2dpolypolygon.hxx> -#include <basegfx/polygon/b2dlinegeometry.hxx> -#include <basegfx/polygon/b2dpolygontools.hxx> -#include <basegfx/polygon/b2dpolypolygontools.hxx> -#include <com/sun/star/io/XSeekable.hpp> -#include <com/sun/star/xml/sax/XParser.hpp> -#include <com/sun/star/xml/dom/DocumentBuilder.hpp> -#include <com/sun/star/xml/dom/NodeType.hpp> - -#include <basegfx/polygon/b2dpolygoncutandtouch.hxx> -#include <basegfx/polygon/b2dpolypolygoncutter.hxx> -#include <unotools/streamwrap.hxx> -#include <sax/tools/converter.hxx> -#include <vcl/graph.hxx> -#include <vcl/virdev.hxx> -#include <vcl/gradient.hxx> -#include <vcl/graphicfilter.hxx> -#include <tools/zcodec.hxx> - -#include <map> - -#define OASIS_STR "urn:oasis:names:tc:opendocument:xmlns:" - -using namespace ::com::sun::star; - -namespace svgi -{ - enum SvgiVisitorCaller {STYLE_ANNOTATOR, SHAPE_WRITER, STYLE_WRITER}; -namespace -{ - -/** visits all children of the specified type with the given functor - */ -template<typename Func> void visitChildren(const Func& rFunc, - const uno::Reference<xml::dom::XElement>& rElem, - xml::dom::NodeType eChildType ) -{ - uno::Reference<xml::dom::XNodeList> xChildren( rElem->getChildNodes() ); - const sal_Int32 nNumNodes( xChildren->getLength() ); - for( sal_Int32 i=0; i<nNumNodes; ++i ) - { - SAL_INFO("filter.svg", "node type: " << sal::static_int_cast<sal_uInt32>(xChildren->item(i)->getNodeType()) << " tag name " << xChildren->item(i)->getNodeName() << " value |" << xChildren->item(i)->getNodeValue() << "|"); - if( xChildren->item(i)->getNodeType() == eChildType ) - rFunc( *xChildren->item(i).get() ); - } -} - -/** Visit all elements of the given tree (in-order traversal) - - Given functor is called for every element, and passed the - element's attributes, if any - */ -template<typename Func> void visitElements(Func& rFunc, - const uno::Reference<xml::dom::XElement>& rElem, - SvgiVisitorCaller eCaller) -{ - if( rElem->hasAttributes() ) - rFunc(rElem, rElem->getAttributes()); - else - rFunc(rElem); - - // notify children processing - rFunc.push(); - - if (eCaller == SHAPE_WRITER && rElem->getTagName() == "defs") - return; - - // recurse over children - uno::Reference<xml::dom::XNodeList> xChildren( rElem->getChildNodes() ); - const sal_Int32 nNumNodes( xChildren->getLength() ); - for( sal_Int32 i=0; i<nNumNodes; ++i ) - { - if( xChildren->item(i)->getNodeType() == xml::dom::NodeType_ELEMENT_NODE ){ - visitElements( rFunc, - uno::Reference<xml::dom::XElement>( - xChildren->item(i), - uno::UNO_QUERY_THROW), - eCaller ); - } - } - - // children processing done - rFunc.pop(); -} - -template<typename value_type> value_type square(value_type v) -{ - return v*v; -} - -double colorDiffSquared(const ARGBColor& rCol1, const ARGBColor& rCol2) -{ - return - square(rCol1.a-rCol2.a) - + square(rCol1.r-rCol2.r) - + square(rCol1.g-rCol2.g) - + square(rCol1.b-rCol2.b); -} - -/** - check whether a polypolygon contains both open and closed - polygons -**/ -bool PolyPolygonIsMixedOpenAndClosed( const basegfx::B2DPolyPolygon& rPoly ) -{ - bool bRetval(false); - bool bOpen(false); - bool bClosed(false); - - // PolyPolygon is mixed open and closed if there is more than one - // polygon and there are both closed and open polygons. - for( sal_uInt32 a(0); !bRetval && a < rPoly.count(); a++ ) - { - if ( rPoly.getB2DPolygon(a).isClosed() ) - { - bClosed = true; - } - else - { - bOpen = true; - } - - bRetval = (bClosed && bOpen); - } - - return bRetval; -} - -typedef std::map<OUString,std::size_t> ElementRefMapType; - -struct AnnotatingVisitor -{ - AnnotatingVisitor(StatePool& rStatePool, - StateMap& rStateMap, - const State& rInitialState, - const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, - std::vector< uno::Reference<xml::dom::XElement> >& rUseElementVector, - bool& rGradientNotFound) : - mnCurrStateId(0), - maCurrState(), - maParentStates(), - mrStates(rStatePool), - mrStateMap(rStateMap), - mxDocumentHandler(xDocumentHandler), - maGradientVector(), - maGradientStopVector(), - maElementVector(), - mrUseElementVector(rUseElementVector), - mrGradientNotFound(rGradientNotFound) - { - maParentStates.push_back(rInitialState); - } - - void operator()( const uno::Reference<xml::dom::XElement>& xElem) - { - const sal_Int32 nTagId(getTokenId(xElem->getTagName())); - if (nTagId != XML_TEXT && nTagId != XML_TSPAN) - return; - - maCurrState = maParentStates.back(); - maCurrState.maTransform.identity(); - maCurrState.maViewBox.reset(); - // if necessary, serialize to automatic-style section - writeStyle(xElem,nTagId); - } - - bool IsAncestorId(const uno::Reference<xml::dom::XNode>& xParentNode, const OUString& rValue) - { - bool bSelfCycle = false; - if (xParentNode.is() && xParentNode->getNodeType() == xml::dom::NodeType_ELEMENT_NODE) - { - if (xParentNode->hasAttributes()) - { - const uno::Reference<xml::dom::XNamedNodeMap> xParentAttributes = xParentNode->getAttributes(); - const sal_Int32 nFooNumAttrs(xParentAttributes->getLength()); - for (sal_Int32 i=0; i < nFooNumAttrs; ++i) - { - const sal_Int32 nTokenId(getTokenId(xParentAttributes->item(i)->getNodeName())); - if (XML_ID == nTokenId) - { - OUString sParentID = xParentAttributes->item(i)->getNodeValue(); - bSelfCycle = sParentID == rValue; - break; - } - } - } - - if (!bSelfCycle) - bSelfCycle = IsAncestorId(xParentNode->getParentNode(), rValue); - } - return bSelfCycle; - } - - void operator()( const uno::Reference<xml::dom::XElement>& xElem, - const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes ) - { - const sal_Int32 nTagId(getTokenId(xElem->getTagName())); - switch (nTagId) - { - case XML_LINEARGRADIENT: - { - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - maGradientVector.emplace_back(Gradient::LINEAR); - - // do we have a reference to a parent gradient? parse - // that first, as it sets our defaults here (manually - // tracking default state on each Gradient variable is - // much more overhead) - uno::Reference<xml::dom::XNode> xNode(xAttributes->getNamedItem("href")); - if(xNode.is()) - { - const OUString sValue(xNode->getNodeValue()); - ElementRefMapType::iterator aFound=maGradientIdMap.end(); - if ( sValue.startsWith("#") ) - aFound = maGradientIdMap.find(sValue.copy(1)); - else - aFound = maGradientIdMap.find(sValue); - - if( aFound != maGradientIdMap.end() ) - maGradientVector.back() = maGradientVector[aFound->second]; - else - { - mrGradientNotFound = true; - maGradientVector.pop_back(); - return; - } - } - - // do that after dereferencing, to prevent hyperlinked - // gradient to clobber our Id again - maGradientVector.back().mnId = maGradientVector.size()-1; - maGradientVector.back().meType = Gradient::LINEAR; // has been clobbered as well - - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - parseLinearGradientData( maGradientVector.back(), - maGradientVector.size()-1, - getTokenId(xAttributes->item(i)->getNodeName()), - xAttributes->item(i)->getNodeValue() ); - } - break; - } - case XML_RADIALGRADIENT: - { - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - maGradientVector.emplace_back(Gradient::RADIAL); - - // do we have a reference to a parent gradient? parse - // that first, as it sets our defaults here (manually - // tracking default state on each Gradient variable is - // much more overhead) - uno::Reference<xml::dom::XNode> xNode(xAttributes->getNamedItem("href")); - if(xNode.is()) - { - const OUString sValue(xNode->getNodeValue()); - ElementRefMapType::iterator aFound=maGradientIdMap.end(); - if ( sValue.startsWith("#") ) - aFound = maGradientIdMap.find(sValue.copy(1)); - else - aFound = maGradientIdMap.find(sValue); - - if( aFound != maGradientIdMap.end() ) - maGradientVector.back() = maGradientVector[aFound->second]; - else - { - mrGradientNotFound = true; - maGradientVector.pop_back(); - return; - } - } - - // do that after dereferencing, to prevent hyperlinked - // gradient to clobber our Id again - maGradientVector.back().mnId = maGradientVector.size()-1; - maGradientVector.back().meType = Gradient::RADIAL; // has been clobbered as well - - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - parseRadialGradientData( maGradientVector.back(), - maGradientVector.size()-1, - getTokenId(xAttributes->item(i)->getNodeName()), - xAttributes->item(i)->getNodeValue() ); - } - break; - } - case XML_USE: - { - uno::Reference<xml::dom::XNode> xNode(xAttributes->getNamedItem("href")); - if(xNode.is()) - { - OUString sValue(xNode->getNodeValue()); - ElementRefMapType::iterator aFound=maElementIdMap.end(); - if ( sValue.startsWith("#") ) - sValue = sValue.copy(1); - aFound = maElementIdMap.find(sValue); - bool bFound = aFound != maElementIdMap.end(); - if (bFound) - { - const bool bSelfCycle = IsAncestorId(xElem->getParentNode(), sValue); - if (bSelfCycle) - { - SAL_WARN("filter.svg", "\"use\" declaration with target of ancestor node, causing use cycle"); - //drop this invalid self-referencing "use" node - maElementIdMap.erase(aFound); - bFound = false; - } - } - - if (bFound) - { - uno::Reference<xml::dom::XElement> xRefElem( - maElementVector[aFound->second]->cloneNode(true), uno::UNO_QUERY); - - xRefElem->removeAttribute("id"); - - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - OUString sAttributeValue; - double x=0.0, y=0.0; - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - sAttributeValue = xAttributes->item(i)->getNodeValue(); - const sal_Int32 nAttribId( - getTokenId(xAttributes->item(i)->getNodeName())); - - switch(nAttribId) - { - case XML_ID: - maElementVector.push_back(xElem); - maElementIdMap.insert(std::make_pair(sAttributeValue, - maElementVector.size() - 1)); - break; - case XML_X: - x = convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_Y: - y = convLength(sAttributeValue,maCurrState,'v'); - break; - case XML_TRANSFORM: - break; - default: - OUString sAttributeName = xAttributes->item(i)->getNodeName(); - xRefElem->setAttribute(sAttributeName, sAttributeValue); - break; - } - } - std::stringstream ssAttrValue; - ssAttrValue << xRefElem->getAttribute("transform"); - ssAttrValue << xElem->getAttribute("transform"); - ssAttrValue << " translate(" << x << "," << y << ")"; - - OUString attrValue(OUString::createFromAscii (ssAttrValue.str().c_str())); - xRefElem->setAttribute("transform", attrValue); - - mrUseElementVector.push_back(xRefElem); - - visitElements((*this), xRefElem, STYLE_ANNOTATOR); - } - } - break; - } - case XML_STOP: - { - if (!maGradientVector.empty()) - { - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - maGradientStopVector.emplace_back(); - maGradientVector.back().maStops.push_back(maGradientStopVector.size()-1); - - // first parse 'color' as 'stop-color' might depend on it - // if 'stop-color''s value is "currentColor" and parsed previously - uno::Reference<xml::dom::XNode> xNodeColor(xAttributes->getNamedItem("color")); - if(xNodeColor.is()) - parseGradientStop( maGradientStopVector.back(), - maGradientStopVector.size()-1, - XML_STOP_COLOR, - xNodeColor->getNodeValue() ); - - //now, parse the rest of attributes - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - const sal_Int32 nTokenId( - getTokenId(xAttributes->item(i)->getNodeName())); - if ( nTokenId != XML_COLOR ) - parseGradientStop( maGradientStopVector.back(), - maGradientStopVector.size()-1, - nTokenId, - xAttributes->item(i)->getNodeValue() ); - } - } - break; - } - default: - { - if ( !mrGradientNotFound ) - { - // init state. inherit defaults from parent. - maCurrState = maParentStates.back(); - maCurrState.maTransform.identity(); - maCurrState.maViewBox.reset(); - - // first parse 'color' and 'style' as 'fill' and 'stroke' might depend on them - // if their values are "currentColor" and parsed previously - uno::Reference<xml::dom::XNode> xNodeColor(xAttributes->getNamedItem("color")); - if(xNodeColor.is()) - parseAttribute(XML_COLOR, xNodeColor->getNodeValue()); - - uno::Reference<xml::dom::XNode> xNodeStyle(xAttributes->getNamedItem("style")); - if(xNodeStyle.is()) - parseStyle(xNodeStyle->getNodeValue()); - - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - OUString sAttributeValue; - - //now, parse the rest of attributes - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - sAttributeValue = xAttributes->item(i)->getNodeValue(); - const sal_Int32 nTokenId( - getTokenId(xAttributes->item(i)->getNodeName())); - if( XML_ID == nTokenId ) - { - maElementVector.push_back(xElem); - maElementIdMap.insert(std::make_pair(sAttributeValue, - maElementVector.size() - 1)); - } - else if (nTokenId != XML_COLOR && nTokenId != XML_STYLE) - parseAttribute(nTokenId, - sAttributeValue); - } - - // all attributes parsed, can calc total CTM now - basegfx::B2DHomMatrix aLocalTransform; - if( !maCurrState.maViewBox.isEmpty() && - maCurrState.maViewBox.getWidth() != 0.0 && - maCurrState.maViewBox.getHeight() != 0.0 ) - { - // transform aViewBox into viewport, keep aspect ratio - aLocalTransform.translate(-maCurrState.maViewBox.getMinX(), - -maCurrState.maViewBox.getMinY()); - double scaleW = maCurrState.maViewport.getWidth()/maCurrState.maViewBox.getWidth(); - double scaleH = maCurrState.maViewport.getHeight()/maCurrState.maViewBox.getHeight(); - double scale = (scaleW < scaleH) ? scaleW : scaleH; - aLocalTransform.scale(scale,scale); - } - else if( !maParentStates.back().maViewBox.isEmpty() ) - maCurrState.maViewBox = maParentStates.back().maViewBox; - - maCurrState.maCTM = maCurrState.maCTM*maCurrState.maTransform*aLocalTransform; - - // if necessary, serialize to automatic-style section - writeStyle(xElem,nTagId); - } - } - } - } - - static OUString getStyleName( const char* sPrefix, sal_Int32 nId ) - { - return OUString::createFromAscii(sPrefix)+OUString::number(nId); - } - - bool hasGradientOpacity( const Gradient& rGradient ) - { - return - (rGradient.maStops.size() > 1) && - (maGradientStopVector[ - rGradient.maStops[0]].maStopColor.a != 1.0 || - maGradientStopVector[ - rGradient.maStops[1]].maStopColor.a != 1.0); - } - - struct StopSorter - { - explicit StopSorter( const std::vector< GradientStop >& rStopVec ) : - mrStopVec(rStopVec) - {} - - bool operator()( std::size_t rLHS, std::size_t rRHS ) - { - return mrStopVec[rLHS].mnStopPosition < mrStopVec[rRHS].mnStopPosition; - } - - const std::vector< GradientStop >& mrStopVec; - }; - - void optimizeGradientStops( Gradient& rGradient ) - { - // sort for increasing stop position - std::sort(rGradient.maStops.begin(),rGradient.maStops.end(), - StopSorter(maGradientStopVector)); - - if( rGradient.maStops.size() < 3 ) - return; //easy! :-) - - // join similar colors - std::vector<std::size_t> aNewStops { rGradient.maStops.front() }; - for( std::size_t i=1; i<rGradient.maStops.size(); ++i ) - { - if( maGradientStopVector[rGradient.maStops[i]].maStopColor != - maGradientStopVector[aNewStops.back()].maStopColor ) - aNewStops.push_back(rGradient.maStops[i]); - } - - rGradient.maStops = aNewStops; - if (rGradient.maStops.size() < 2) - { - return; // can't optimize further... - } - - // axial gradient, maybe? - if( rGradient.meType == Gradient::LINEAR && - rGradient.maStops.size() == 3 && - maGradientStopVector[rGradient.maStops.front()].maStopColor == - maGradientStopVector[rGradient.maStops.back()].maStopColor ) - { - // yep - keep it at that - return; - } - - // find out most significant color difference, and limit to - // those two stops around this border (metric is - // super-simplistic: take euclidean distance of colors, weigh - // with stop distance) - std::size_t nMaxIndex=0; - double fMaxDistance=0.0; - for( std::size_t i=1; i<rGradient.maStops.size(); ++i ) - { - const double fCurrDistance( - colorDiffSquared( - maGradientStopVector[rGradient.maStops[i-1]].maStopColor, - maGradientStopVector[rGradient.maStops[i]].maStopColor) * - (square(maGradientStopVector[rGradient.maStops[i-1]].mnStopPosition) + - square(maGradientStopVector[rGradient.maStops[i]].mnStopPosition)) ); - - if( fCurrDistance > fMaxDistance ) - { - nMaxIndex = i-1; - fMaxDistance = fCurrDistance; - } - } - rGradient.maStops[0] = rGradient.maStops[nMaxIndex]; - rGradient.maStops[1] = rGradient.maStops[nMaxIndex+1]; - rGradient.maStops.erase(rGradient.maStops.begin()+2,rGradient.maStops.end()); - } - - static sal_Int8 toByteColor( double val ) - { - // TODO(Q3): duplicated from vcl::unotools - return sal::static_int_cast<sal_Int8>( - basegfx::fround(val*255.0)); - } - - static OUString getOdfColor( const ARGBColor& rColor ) - { - // TODO(Q3): duplicated from pdfimport - OUStringBuffer aBuf( 7 ); - const sal_uInt8 nRed ( toByteColor(rColor.r) ); - const sal_uInt8 nGreen( toByteColor(rColor.g) ); - const sal_uInt8 nBlue ( toByteColor(rColor.b) ); - aBuf.append( '#' ); - if( nRed < 0x10 ) - aBuf.append( '0' ); - aBuf.append( sal_Int32(nRed), 16 ); - if( nGreen < 0x10 ) - aBuf.append( '0' ); - aBuf.append( sal_Int32(nGreen), 16 ); - if( nBlue < 0x10 ) - aBuf.append( '0' ); - aBuf.append( sal_Int32(nBlue), 16 ); - - // TODO(F3): respect alpha transparency (polygons etc.) - OSL_ASSERT(rColor.a == 1.0); - - return aBuf.makeStringAndClear(); - } - - static OUString getOdfAlign( TextAlign eAlign ) - { - switch(eAlign) - { - default: - case BEFORE: - return OUString("start"); - case CENTER: - return OUString("center"); - case AFTER: - return OUString("end"); - } - } - - bool writeStyle(State& rState, const sal_Int32 nTagId) - { - rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() ); - uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() ); - - if (XML_TEXT == nTagId || XML_TSPAN == nTagId) { - rState.mbIsText = true; - basegfx::B2DTuple aScale, aTranslate; - double fRotate, fShearX; - if (rState.maCTM.decompose(aScale, aTranslate, fRotate, fShearX)) - { - rState.mnFontSize *= aScale.getX(); - } - } - - std::pair<StatePool::iterator, - bool> aRes = mrStates.insert(rState); - SAL_INFO ("filter.svg", "size " << mrStates.size() << " id " << const_cast<State&>(*aRes.first).mnStyleId); - - if( !aRes.second ) - return false; // not written - - ++mnCurrStateId; - - // mnStyleId does not take part in hashing/comparison - const_cast<State&>(*aRes.first).mnStyleId = mnCurrStateId; - SAL_INFO ("filter.svg", " --> " << const_cast<State&>(*aRes.first).mnStyleId); - - mrStateMap.insert(std::make_pair( - mnCurrStateId, - rState)); - - // find two representative stop colors (as ODF only support - // start&end color) - optimizeGradientStops(rState.maFillGradient); - - if( !mxDocumentHandler.is() ) - return true; // cannot write style, svm import case - - // do we have a gradient fill? then write out gradient as well - if( rState.meFillType == GRADIENT && rState.maFillGradient.maStops.size() > 0 ) - { - // if only one stop-color is defined - if( rState.maFillGradient.maStops.size() == 1 ) - rState.maFillGradient.maStops.push_back(rState.maFillGradient.maStops[0]); - - // TODO(F3): ODF12 supposedly also groks svg:linear/radialGradient. But CL says: nope. - xAttrs->AddAttribute( "draw:name", getStyleName("svggradient", rState.maFillGradient.mnId) ); - if( rState.maFillGradient.meType == Gradient::LINEAR ) - { - // should the optimizeGradientStops method decide that - // this is a three-color gradient, it prolly wanted us - // to take axial instead - xAttrs->AddAttribute( "draw:style", - rState.maFillGradient.maStops.size() == 3 ? - OUString("axial") : - OUString("linear") ); - } - else - { - xAttrs->AddAttribute( "draw:style", "ellipsoid" ); - xAttrs->AddAttribute( "draw:cx", "50%" ); - xAttrs->AddAttribute( "draw:cy", "50%" ); - } - - basegfx::B2DTuple rScale, rTranslate; - double rRotate, rShearX; - if( rState.maFillGradient.maTransform.decompose(rScale, rTranslate, rRotate, rShearX) ) - xAttrs->AddAttribute( "draw:angle", - OUString::number(rRotate*1800.0/M_PI ) ); - xAttrs->AddAttribute( "draw:start-color", - getOdfColor( - maGradientStopVector[ - rState.maFillGradient.maStops[0]].maStopColor) ); - xAttrs->AddAttribute( "draw:end-color", - getOdfColor( - maGradientStopVector[ - rState.maFillGradient.maStops[1]].maStopColor) ); - xAttrs->AddAttribute( "draw:border", "0%" ); - mxDocumentHandler->startElement( "draw:gradient", xUnoAttrs ); - mxDocumentHandler->endElement( "draw:gradient" ); - - if( hasGradientOpacity(rState.maFillGradient) ) - { - // need to write out opacity style as well - xAttrs->Clear(); - xAttrs->AddAttribute( "draw:name", getStyleName("svgopacity", rState.maFillGradient.mnId) ); - if( rState.maFillGradient.meType == Gradient::LINEAR ) - { - xAttrs->AddAttribute( "draw:style", "linear" ); - } - else - { - xAttrs->AddAttribute( "draw:style", "ellipsoid" ); - xAttrs->AddAttribute( "draw:cx", "50%" ); - xAttrs->AddAttribute( "draw:cy", "50%" ); - } - - // modulate gradient opacity with overall fill opacity - xAttrs->AddAttribute( "draw:end", - OUString::number( - maGradientStopVector[ - rState.maFillGradient.maStops[0]].maStopColor.a* - maCurrState.mnFillOpacity*maCurrState.mnOpacity*100.0)+"%" ); - xAttrs->AddAttribute( "draw:start", - OUString::number( - maGradientStopVector[ - rState.maFillGradient.maStops[1]].maStopColor.a* - maCurrState.mnFillOpacity*maCurrState.mnOpacity*100.0)+"%" ); - xAttrs->AddAttribute( "draw:border", "0%" ); - mxDocumentHandler->startElement( "draw:opacity", xUnoAttrs ); - mxDocumentHandler->endElement( "draw:opacity" ); - } - } - - // serialize to automatic-style section - if( nTagId == XML_TEXT || nTagId == XML_TSPAN) - { - // write paragraph style attributes - xAttrs->Clear(); - - xAttrs->AddAttribute( "style:name", getStyleName("svgparagraphstyle", mnCurrStateId) ); - xAttrs->AddAttribute( "style:family", "paragraph" ); - mxDocumentHandler->startElement( "style:style", xUnoAttrs ); - - xAttrs->Clear(); - xAttrs->AddAttribute( "fo:text-align", getOdfAlign(rState.meTextAnchor)); - - mxDocumentHandler->startElement( "style:paragraph-properties", xUnoAttrs ); - mxDocumentHandler->endElement( "style:paragraph-properties" ); - mxDocumentHandler->endElement( "style:style" ); - - // write text style attributes - xAttrs->Clear(); - - xAttrs->AddAttribute( "style:name", getStyleName("svgtextstyle", mnCurrStateId) ); - xAttrs->AddAttribute( "style:family", "text" ); - mxDocumentHandler->startElement( "style:style", xUnoAttrs ); - xAttrs->Clear(); - xAttrs->AddAttribute( "fo:font-family", rState.maFontFamily); - xAttrs->AddAttribute( "fo:font-size", - OUString::number(pt2mm(rState.mnFontSize))+"mm"); - xAttrs->AddAttribute( "fo:font-style", rState.maFontStyle); - xAttrs->AddAttribute( "fo:font-variant", rState.maFontVariant); - xAttrs->AddAttribute( "fo:font-weight", - OUString::number(rState.mnFontWeight)); - xAttrs->AddAttribute( "fo:color", getOdfColor(rState.maFillColor)); - - mxDocumentHandler->startElement( "style:text-properties", xUnoAttrs ); - mxDocumentHandler->endElement( "style:text-properties" ); - mxDocumentHandler->endElement( "style:style" ); - } - - xAttrs->Clear(); - xAttrs->AddAttribute( "style:name" , getStyleName("svggraphicstyle", mnCurrStateId) ); - xAttrs->AddAttribute( "style:family", "graphic" ); - mxDocumentHandler->startElement( "style:style", xUnoAttrs ); - - xAttrs->Clear(); - // text or shape? if the former, no use in processing any - // graphic attributes except stroke color, ODF can do ~nothing - // with text shapes - if( nTagId == XML_TEXT || nTagId == XML_TSPAN ) - { - //xAttrs->AddAttribute( "draw:auto-grow-height", "true"); - xAttrs->AddAttribute( "draw:auto-grow-width", "true"); - xAttrs->AddAttribute( "draw:textarea-horizontal-align", "left"); - //xAttrs->AddAttribute( "draw:textarea-vertical-align", "top"); - xAttrs->AddAttribute( "fo:min-height", "0cm"); - - xAttrs->AddAttribute( "fo:padding-top", "0cm"); - xAttrs->AddAttribute( "fo:padding-left", "0cm"); - xAttrs->AddAttribute( "fo:padding-right", "0cm"); - xAttrs->AddAttribute( "fo:padding-bottom", "0cm"); - - // disable any background shape - xAttrs->AddAttribute( "draw:stroke", "none"); - xAttrs->AddAttribute( "draw:fill", "none"); - } - else - { - if( rState.meFillType != NONE ) - { - if( rState.meFillType == GRADIENT ) - { - // don't fill the gradient if there's no stop element present - if( rState.maFillGradient.maStops.size() == 0 ) - xAttrs->AddAttribute( "draw:fill", "none" ); - else - { - xAttrs->AddAttribute( "draw:fill", "gradient"); - xAttrs->AddAttribute( "draw:fill-gradient-name", - getStyleName("svggradient", rState.maFillGradient.mnId) ); - if( hasGradientOpacity(rState.maFillGradient) ) - { - // needs transparency gradient as well - xAttrs->AddAttribute( "draw:opacity-name", - getStyleName("svgopacity", rState.maFillGradient.mnId) ); - } - else if( maCurrState.mnFillOpacity*maCurrState.mnOpacity != 1.0 ) - xAttrs->AddAttribute( "draw:opacity", - OUString::number(100.0*maCurrState.mnFillOpacity*maCurrState.mnOpacity)+"%" ); - } - } - else - { - xAttrs->AddAttribute( "draw:fill", "solid"); - xAttrs->AddAttribute( "draw:fill-color", getOdfColor(rState.maFillColor)); - if( maCurrState.mnFillOpacity*maCurrState.mnOpacity != 1.0 ) - xAttrs->AddAttribute( "draw:opacity", - OUString::number(100.0*maCurrState.mnFillOpacity*maCurrState.mnOpacity)+"%" ); - } - } - else - xAttrs->AddAttribute( "draw:fill", "none"); - - if( rState.meStrokeType == SOLID ) - { - xAttrs->AddAttribute( "draw:stroke", "solid"); - xAttrs->AddAttribute( "svg:stroke-color", getOdfColor(rState.maStrokeColor)); - } - else if( rState.meStrokeType == DASH ) - { - xAttrs->AddAttribute( "draw:stroke", "dash"); - xAttrs->AddAttribute( "draw:stroke-dash", "dash"+OUString::number(mnCurrStateId)); - xAttrs->AddAttribute( "svg:stroke-color", getOdfColor(rState.maStrokeColor)); - } - else - xAttrs->AddAttribute( "draw:stroke", "none"); - - if( maCurrState.mnStrokeWidth != 0.0 ) - { - ::basegfx::B2DVector aVec(maCurrState.mnStrokeWidth,0); - aVec *= maCurrState.maCTM; - xAttrs->AddAttribute( "svg:stroke-width", OUString::number( pt2mm(aVec.getLength()) )+"mm"); - } - if( maCurrState.meLineJoin == basegfx::B2DLineJoin::Miter ) - xAttrs->AddAttribute( "draw:stroke-linejoin", "miter"); - else if( maCurrState.meLineJoin == basegfx::B2DLineJoin::Round ) - xAttrs->AddAttribute( "draw:stroke-linejoin", "round"); - else if( maCurrState.meLineJoin == basegfx::B2DLineJoin::Bevel ) - xAttrs->AddAttribute( "draw:stroke-linejoin", "bevel"); - if( maCurrState.mnStrokeOpacity*maCurrState.mnOpacity != 1.0 ) - xAttrs->AddAttribute( "svg:stroke-opacity", - OUString::number(100.0*maCurrState.mnStrokeOpacity*maCurrState.mnOpacity)+"%"); - } - - mxDocumentHandler->startElement( "style:graphic-properties", xUnoAttrs ); - mxDocumentHandler->endElement( "style:graphic-properties" ); - mxDocumentHandler->endElement( "style:style" ); - - return true; // newly written - } - - void writeStyle(const uno::Reference<xml::dom::XElement>& xElem, const sal_Int32 nTagId) - { - SAL_INFO ("filter.svg", "writeStyle xElem " << xElem->getTagName()); - - sal_Int32 nStyleId=0; - if( writeStyle(maCurrState, nTagId) ) - nStyleId = mnCurrStateId; - else - nStyleId = mrStates.find(maCurrState)->mnStyleId; - - xElem->setAttribute("internal-style-ref", - OUString::number( - nStyleId) - +"$0"); - } - - void push() - { - maParentStates.push_back(maCurrState); - } - - void pop() - { - maParentStates.pop_back(); - } - - void parseLinearGradientData( Gradient& io_rCurrGradient, - const sal_Int32 nGradientNumber, - const sal_Int32 nTokenId, - const OUString& sValue ) - { - switch(nTokenId) - { - case XML_GRADIENTTRANSFORM: - { - OString aValueUtf8( sValue.getStr(), - sValue.getLength(), - RTL_TEXTENCODING_UTF8 ); - parseTransform(aValueUtf8.getStr(),io_rCurrGradient.maTransform); - break; - } - case XML_X1: - io_rCurrGradient.maCoords.linear.mfX1 = convLength(sValue,maCurrState,'h'); - break; - case XML_X2: - io_rCurrGradient.maCoords.linear.mfX2 = convLength(sValue,maCurrState,'h'); - break; - case XML_Y1: - io_rCurrGradient.maCoords.linear.mfY1 = convLength(sValue,maCurrState,'v'); - break; - case XML_Y2: - io_rCurrGradient.maCoords.linear.mfY2 = convLength(sValue,maCurrState,'v'); - break; - case XML_ID: - maGradientIdMap.insert(std::make_pair(sValue,nGradientNumber)); - break; - case XML_GRADIENTUNITS: - if (getTokenId(sValue) == XML_OBJECTBOUNDINGBOX) - io_rCurrGradient.mbBoundingBoxUnits = true; - else - io_rCurrGradient.mbBoundingBoxUnits = false; - break; - default: - break; - } - } - - void parseRadialGradientData( Gradient& io_rCurrGradient, - const sal_Int32 nGradientNumber, - const sal_Int32 nTokenId, - const OUString& sValue ) - { - switch(nTokenId) - { - case XML_GRADIENTTRANSFORM: - { - OString aValueUtf8( sValue.getStr(), - sValue.getLength(), - RTL_TEXTENCODING_UTF8 ); - parseTransform(aValueUtf8.getStr(),io_rCurrGradient.maTransform); - break; - } - case XML_CX: - io_rCurrGradient.maCoords.radial.mfCX = convLength(sValue,maCurrState,'h'); - break; - case XML_CY: - io_rCurrGradient.maCoords.radial.mfCY = convLength(sValue,maCurrState,'v'); - break; - case XML_FX: - io_rCurrGradient.maCoords.radial.mfFX = convLength(sValue,maCurrState,'h'); - break; - case XML_FY: - io_rCurrGradient.maCoords.radial.mfFY = convLength(sValue,maCurrState,'v'); - break; - case XML_R: - io_rCurrGradient.maCoords.radial.mfR = convLength(sValue,maCurrState,'r'); - break; - case XML_ID: - maGradientIdMap.insert(std::make_pair(sValue,nGradientNumber)); - break; - case XML_GRADIENTUNITS: - if (getTokenId(sValue) == XML_OBJECTBOUNDINGBOX) - io_rCurrGradient.mbBoundingBoxUnits = true; - else - io_rCurrGradient.mbBoundingBoxUnits = false; - break; - default: - break; - } - } - - void parseGradientStop( GradientStop& io_rGradientStop, - const sal_Int32 nStopNumber, - const sal_Int32 nTokenId, - const OUString& sValue ) - { - switch(nTokenId) - { - case XML_HREF: - { - ElementRefMapType::iterator aFound=maStopIdMap.end(); - if ( sValue.startsWith("#") ) - aFound = maStopIdMap.find(sValue.copy(1)); - else - aFound = maStopIdMap.find(sValue); - - if( aFound != maStopIdMap.end() ) - io_rGradientStop = maGradientStopVector[aFound->second]; - break; - } - case XML_ID: - maStopIdMap.insert(std::make_pair(sValue,nStopNumber)); - break; - case XML_STOP_COLOR: - if( maGradientVector.empty() || - maGradientVector.back().maStops.empty() ) - break; - parseColor( sValue.toUtf8().getStr(), maGradientStopVector[ - maGradientVector.back().maStops.back()].maStopColor ); - break; - case XML_STOP_OPACITY: - if( maGradientVector.empty() || - maGradientVector.back().maStops.empty() ) - break; - parseOpacity( sValue.toUtf8().getStr(), - maGradientStopVector[ - maGradientVector.back().maStops.back()].maStopColor ); - break; - case XML_OFFSET: - io_rGradientStop.mnStopPosition = sValue.toDouble(); - break; - case XML_STYLE: - parseStyle( sValue ); - break; - default: - break; - } - } - - void parseAttribute( const sal_Int32 nTokenId, - const OUString& sValue ) - { - OString aValueUtf8( sValue.getStr(), - sValue.getLength(), - RTL_TEXTENCODING_UTF8 ); - switch(nTokenId) - { - case XML_WIDTH: - { - const double fViewPortWidth( - convLength(sValue,maCurrState,'h')); - - maCurrState.maViewport.expand( - basegfx::B2DTuple(fViewPortWidth,0.0)); - break; - } - case XML_HEIGHT: - { - const double fViewPortHeight( - convLength(sValue,maCurrState,'v')); - - maCurrState.maViewport.expand( - basegfx::B2DTuple(0.0,fViewPortHeight)); - break; - } - case XML_VIEWBOX: - { - // TODO(F1): preserveAspectRatio - parseViewBox( - aValueUtf8.getStr(), - maCurrState.maViewBox); - break; - } - case XML_FILL_RULE: - { - if( aValueUtf8 == "evenodd" ) - maCurrState.meFillRule = EVEN_ODD; - else if( aValueUtf8 == "nonzero" ) - maCurrState.meFillRule = NON_ZERO; - else if( aValueUtf8 == "inherit" ) - maCurrState.meFillRule = maParentStates.back().meFillRule; - break; - } - case XML_OPACITY: - if( aValueUtf8 == "inherit" ) - maCurrState.mnOpacity = maParentStates.back().mnOpacity; - else - maCurrState.mnOpacity = aValueUtf8.toDouble(); - break; - case XML_FILL_OPACITY: - if( aValueUtf8 == "inherit" ) - maCurrState.mnFillOpacity = maParentStates.back().mnFillOpacity; - else { - maCurrState.mnFillOpacity = aValueUtf8.toDouble(); - if( maCurrState.mnFillOpacity > 1 ) - maCurrState.mnFillOpacity = 1; - } - break; - case XML_STROKE_WIDTH: - { - if( aValueUtf8 == "inherit" ) - maCurrState.mnStrokeWidth = maParentStates.back().mnStrokeWidth; - else - maCurrState.mnStrokeWidth = convLength(sValue,maCurrState,'r'); - break; - } - case XML_STROKE_LINECAP: - { - if( aValueUtf8 == "butt" ) - maCurrState.meLineCap = BUTT; - else if( aValueUtf8 == "round" ) - maCurrState.meLineCap = ROUND; - else if( aValueUtf8 == "square" ) - maCurrState.meLineCap = RECT; - else if( aValueUtf8 == "inherit" ) - maCurrState.meLineCap = maParentStates.back().meLineCap; - break; - } - case XML_STROKE_LINEJOIN: - { - if( aValueUtf8 == "miter" ) - maCurrState.meLineJoin = basegfx::B2DLineJoin::Miter; - else if( aValueUtf8 == "round" ) - maCurrState.meLineJoin = basegfx::B2DLineJoin::Round; - else if( aValueUtf8 == "bevel" ) - maCurrState.meLineJoin = basegfx::B2DLineJoin::Bevel; - else if( aValueUtf8 == "inherit" ) - maCurrState.meLineJoin = maParentStates.back().meLineJoin; - break; - } - case XML_STROKE_MITERLIMIT: - { - if( aValueUtf8 == "inherit" ) - maCurrState.mnMiterLimit = maParentStates.back().mnMiterLimit; - else - maCurrState.mnMiterLimit = aValueUtf8.toDouble(); - break; - } - case XML_STROKE_DASHOFFSET: - { - if( aValueUtf8 == "inherit" ) - maCurrState.mnDashOffset = maParentStates.back().mnDashOffset; - else - maCurrState.mnDashOffset = convLength(sValue,maCurrState,'r'); - break; - } - case XML_STROKE_DASHARRAY: - { - if( aValueUtf8 == "none" ) - { - maCurrState.maDashArray.clear(); - maCurrState.meStrokeType = SOLID; - } - else if( aValueUtf8 == "inherit" ) - maCurrState.maDashArray = maParentStates.back().maDashArray; - else - { - if( parseDashArray(aValueUtf8.getStr(), - maCurrState.maDashArray) ) - { - maCurrState.meStrokeType = DASH; - } - else - { - maCurrState.meStrokeType = SOLID; - } - } - break; - } - case XML_STROKE_OPACITY: - if( aValueUtf8 == "inherit" ) - maCurrState.mnStrokeOpacity = maParentStates.back().mnStrokeOpacity; - else - maCurrState.mnStrokeOpacity = aValueUtf8.toDouble(); - break; - case XML_FILL: - { - const State& rParent( maParentStates.back() ); - parsePaint( sValue, - aValueUtf8.getStr(), - maCurrState.meFillType, - maCurrState.maFillColor, - maCurrState.maFillGradient, - rParent.meFillType, - rParent.maFillColor, - rParent.maFillGradient ); - break; - } - case XML_STROKE: - { - const State& rParent( maParentStates.back() ); - parsePaint( sValue, - aValueUtf8.getStr(), - maCurrState.meStrokeType, - maCurrState.maStrokeColor, - maCurrState.maStrokeGradient, - rParent.meStrokeType, - rParent.maStrokeColor, - rParent.maStrokeGradient ); - break; - } - case XML_COLOR: - { - if( aValueUtf8 == "inherit" ) - maCurrState.maCurrentColor = maParentStates.back().maCurrentColor; - else - parseColor(aValueUtf8.getStr(), maCurrState.maCurrentColor); - break; - } - case XML_TRANSFORM: - { - basegfx::B2DHomMatrix aTransform; - parseTransform(aValueUtf8.getStr(),aTransform); - maCurrState.maTransform = maCurrState.maTransform*aTransform; - break; - } - case XML_FONT_FAMILY: - maCurrState.maFontFamily=sValue; - break; - case XML_FONT_SIZE: - maCurrState.mnParentFontSize=maParentStates.back().mnFontSize; - maCurrState.mnFontSize=convLength(sValue,maCurrState,'v'); - break; - case XML_FONT_STYLE: - parseFontStyle(maCurrState,sValue,aValueUtf8.getStr()); - break; - case XML_FONT_WEIGHT: - maCurrState.mnFontWeight=sValue.toDouble(); - break; - case XML_FONT_VARIANT: - parseFontVariant(maCurrState,sValue,aValueUtf8.getStr()); - break; - case XML_TEXT_ANCHOR: - parseTextAlign(maCurrState,aValueUtf8.getStr()); - break; - case XML_STOP_COLOR: - case XML_STOP_OPACITY: - parseGradientStop( maGradientStopVector.back(), - maGradientStopVector.size()-1, - nTokenId, sValue ); - break; - case XML_TOKEN_INVALID: - SAL_INFO("filter.svg", "unhandled token"); - break; - default: - SAL_INFO("filter.svg", "unhandled token " << getTokenName(nTokenId)); - break; - } - } - - void parseStyle( const OUString& sValue ) - { - // split individual style attributes - sal_Int32 nIndex=0, nDummyIndex=0; - OUString aCurrToken; - do - { - aCurrToken=sValue.getToken(0,';',nIndex); - - if( !aCurrToken.isEmpty() ) - { - // split attrib & value - nDummyIndex=0; - OUString aCurrAttrib( - aCurrToken.getToken(0,':',nDummyIndex).trim()); - OSL_ASSERT(nDummyIndex!=-1); - nDummyIndex=0; - OUString aCurrValue( - aCurrToken.getToken(1,':',nDummyIndex).trim()); - OSL_ASSERT(nDummyIndex==-1); - - // recurse into normal attribute parsing - parseAttribute( getTokenId(aCurrAttrib), - aCurrValue ); - } - } - while( nIndex != -1 ); - } - - static void parseFontStyle( State& io_rInitialState, - const OUString& rValue, - const char* sValue ) - { - if( strcmp(sValue,"inherit") != 0 ) - io_rInitialState.maFontStyle = rValue; - } - - static void parseFontVariant( State& io_rInitialState, - const OUString& rValue, - const char* sValue ) - { - if( strcmp(sValue,"inherit") != 0 ) - io_rInitialState.maFontVariant = rValue; - } - - static void parseTextAlign( State& io_rInitialState, - const char* sValue ) - { - if( strcmp(sValue,"start") == 0 ) - io_rInitialState.meTextAnchor = BEFORE; - else if( strcmp(sValue,"middle") == 0 ) - io_rInitialState.meTextAnchor = CENTER; - else if( strcmp(sValue,"end") == 0 ) - io_rInitialState.meTextAnchor = AFTER; - // keep current val for sValue == "inherit" - } - - void parsePaint( const OUString& rValue, - const char* sValue, - PaintType& rType, - ARGBColor& rColor, - Gradient& rGradient, - const PaintType& rInheritType, - const ARGBColor& rInheritColor, - const Gradient& rInheritGradient ) - { - std::pair<const char*,const char*> aPaintUri(nullptr,nullptr); - std::pair<ARGBColor,bool> aColor(maCurrState.maCurrentColor, - false); - if( strcmp(sValue,"none") == 0 ) - rType = NONE; - else if( strcmp(sValue,"currentColor") == 0 ) - { - rType = SOLID; - rColor = maCurrState.maCurrentColor; - } - else if( strcmp(sValue,"inherit") == 0) - { - rType = rInheritType; - rColor = rInheritColor; - rGradient = rInheritGradient; - } - else if( parsePaintUri(aPaintUri,aColor,sValue) ) - { - if( aPaintUri.first != aPaintUri.second ) - { - // assuming gradient. assumption does not hold generally - if( strstr(sValue,")") && rValue.getLength() > 5 ) - { - ElementRefMapType::iterator aRes; - if( (aRes=maGradientIdMap.find( - rValue.copy(aPaintUri.first-sValue, - aPaintUri.second-aPaintUri.first))) != maGradientIdMap.end() ) - { - rGradient = maGradientVector[aRes->second]; - rType = GRADIENT; - } - } - } - else if( aColor.second ) - { - rType = SOLID; - rColor = aColor.first; - } - else - { - rType = NONE; - } - } - else - { - rType = SOLID; - parseColor(sValue,rColor); - } - } - - sal_Int32 mnCurrStateId; - State maCurrState; - std::vector<State> maParentStates; - StatePool& mrStates; - StateMap& mrStateMap; - uno::Reference<xml::sax::XDocumentHandler> mxDocumentHandler; - std::vector< Gradient > maGradientVector; - std::vector< GradientStop > maGradientStopVector; - std::vector< uno::Reference<xml::dom::XElement> > maElementVector; - std::vector< uno::Reference<xml::dom::XElement> >& mrUseElementVector; - ElementRefMapType maGradientIdMap; - ElementRefMapType maStopIdMap; - ElementRefMapType maElementIdMap; - bool& mrGradientNotFound; -}; - -/// Annotate svg styles with unique references to state pool -void annotateStyles( StatePool& rStatePool, - StateMap& rStateMap, - const State& rInitialState, - uno::Reference<xml::dom::XElement> const & rElem, - const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl, - std::vector< uno::Reference<xml::dom::XElement> >& rUseElementVector ) -{ - bool bGradientNotFound = false; - AnnotatingVisitor aVisitor(rStatePool, rStateMap, rInitialState, xDocHdl, rUseElementVector, bGradientNotFound); - visitElements(aVisitor, rElem, STYLE_ANNOTATOR); - - //Sometimes, xlink:href in gradients refers to another gradient which hasn't been parsed yet. - // if that happens, we'll need to parse the styles again, so everything gets referred. - if( bGradientNotFound ) - { - visitElements(aVisitor, rElem, STYLE_ANNOTATOR); - } -} - -struct ShapeWritingVisitor -{ - ShapeWritingVisitor(StateMap& rStateMap, - const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) : - mrStateMap(rStateMap), - mxDocumentHandler(xDocumentHandler), - mnShapeNum(0) - {} - - void operator()( const uno::Reference<xml::dom::XElement>& ) - { - } - - void operator()( const uno::Reference<xml::dom::XElement>& xElem, - const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes ) - { - rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() ); - uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() ); - - sal_Int32 nDummyIndex(0); - OUString sStyleId( - xElem->getAttribute("internal-style-ref").getToken( - 0,'$',nDummyIndex)); - StateMap::iterator pOrigState=mrStateMap.find( - sStyleId.toInt32()); - - if( pOrigState == mrStateMap.end() ) - return; // non-exportable element, e.g. linearGradient - - maCurrState = pOrigState->second; - - const sal_Int32 nTokenId(getTokenId(xElem->getNodeName())); - switch(nTokenId) - { - case XML_LINE: - { - // collect attributes - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - OUString sAttributeValue; - double x1=0.0,y1=0.0,x2=0.0,y2=0.0; - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - sAttributeValue = xAttributes->item(i)->getNodeValue(); - const sal_Int32 nAttribId( - getTokenId(xAttributes->item(i)->getNodeName())); - switch(nAttribId) - { - case XML_X1: - x1= convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_X2: - x2 = convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_Y1: - y1 = convLength(sAttributeValue,maCurrState,'v'); - break; - case XML_Y2: - y2 = convLength(sAttributeValue,maCurrState,'v'); - break; - default: - // skip - break; - } - } - - if ( x1 != x2 || y1 != y2 ) { - OUString sLinePath = "M"+OUString::number(x1)+"," - +OUString::number(y1)+"L"+OUString::number(x2)+"," - +OUString::number(y2); - basegfx::B2DPolyPolygon aPoly; - basegfx::utils::importFromSvgD(aPoly, sLinePath, false, nullptr); - - writePathShape(xAttrs, - xUnoAttrs, - sStyleId, - aPoly); - } - - break; - } - case XML_POLYGON: - case XML_POLYLINE: - { - OUString sPoints = xElem->hasAttribute("points") ? xElem->getAttribute("points") : ""; - basegfx::B2DPolygon aPoly; - (void)basegfx::utils::importFromSvgPoints(aPoly, sPoints); - if( nTokenId == XML_POLYGON || maCurrState.meFillType != NONE ) - aPoly.setClosed(true); - - writePathShape(xAttrs, - xUnoAttrs, - sStyleId, - basegfx::B2DPolyPolygon(aPoly)); - break; - } - case XML_RECT: - { - // collect attributes - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - OUString sAttributeValue; - bool bRxSeen=false, bRySeen=false; - double x=0.0,y=0.0,width=0.0,height=0.0,rx=0.0,ry=0.0; - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - sAttributeValue = xAttributes->item(i)->getNodeValue(); - const sal_Int32 nAttribId( - getTokenId(xAttributes->item(i)->getNodeName())); - switch(nAttribId) - { - case XML_X: - x = convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_Y: - y = convLength(sAttributeValue,maCurrState,'v'); - break; - case XML_WIDTH: - width = convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_HEIGHT: - height = convLength(sAttributeValue,maCurrState,'v'); - break; - case XML_RX: - rx = convLength(sAttributeValue,maCurrState,'h'); - bRxSeen=true; - break; - case XML_RY: - ry = convLength(sAttributeValue,maCurrState,'v'); - bRySeen=true; - break; - default: - // skip - break; - } - } - - if ( (width > 0) && (height > 0) ) { - if( bRxSeen && !bRySeen ) - ry = rx; - else if( bRySeen && !bRxSeen ) - rx = ry; - - basegfx::B2DPolygon aPoly; - aPoly = basegfx::utils::createPolygonFromRect( - basegfx::B2DRange(x,y,x+width,y+height), - rx/(0.5*width), ry/(0.5*height) ); - - writePathShape(xAttrs, - xUnoAttrs, - sStyleId, - basegfx::B2DPolyPolygon(aPoly)); - } - break; - } - case XML_PATH: - { - OUString sPath = xElem->hasAttribute("d") ? xElem->getAttribute("d") : ""; - basegfx::B2DPolyPolygon aPoly; - basegfx::utils::importFromSvgD(aPoly, sPath, false, nullptr); - - if ((maCurrState.meStrokeType == NONE) && - (maCurrState.meFillType != NONE) && - !aPoly.isClosed()) - { - aPoly.setClosed(true); - } - - // tdf#51165: rendering of paths with open and closed polygons is not implemented - // split mixed polypolygons into single polygons and add them one by one - if( PolyPolygonIsMixedOpenAndClosed(aPoly) ) - { - for( sal_uInt32 i(0); i<aPoly.count(); ++i ) { - writePathShape(xAttrs, - xUnoAttrs, - sStyleId, - basegfx::B2DPolyPolygon(aPoly.getB2DPolygon(i))); - } - } - else - { - writePathShape(xAttrs, - xUnoAttrs, - sStyleId, - aPoly); - } - break; - } - case XML_CIRCLE: - { - // collect attributes - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - OUString sAttributeValue; - double cx=0.0,cy=0.0,r=0.0; - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - sAttributeValue = xAttributes->item(i)->getNodeValue(); - const sal_Int32 nAttribId( - getTokenId(xAttributes->item(i)->getNodeName())); - switch(nAttribId) - { - case XML_CX: - cx = convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_CY: - cy = convLength(sAttributeValue,maCurrState,'v'); - break; - case XML_R: - r = convLength(sAttributeValue,maCurrState,'r'); - break; - default: - // skip - break; - } - } - - if ( r > 0 ) - writeEllipseShape(xAttrs, - xUnoAttrs, - sStyleId, - basegfx::B2DEllipse(basegfx::B2DPoint(cx, cy), basegfx::B2DTuple(r,r))); - break; - } - case XML_ELLIPSE: - { - // collect attributes - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - OUString sAttributeValue; - double cx=0.0,cy=0.0,rx=0.0, ry=0.0; - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - sAttributeValue = xAttributes->item(i)->getNodeValue(); - const sal_Int32 nAttribId( - getTokenId(xAttributes->item(i)->getNodeName())); - switch(nAttribId) - { - case XML_CX: - cx = convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_CY: - cy = convLength(sAttributeValue,maCurrState,'v'); - break; - case XML_RX: - rx = convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_RY: - ry = convLength(sAttributeValue,maCurrState,'v'); - break; - default: - // skip - break; - } - } - - if ( rx > 0 && ry > 0 ) - writeEllipseShape(xAttrs, - xUnoAttrs, - sStyleId, - basegfx::B2DEllipse(basegfx::B2DPoint(cx, cy), basegfx::B2DTuple(rx,ry))); - break; - } - case XML_IMAGE: - { - // collect attributes - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - OUString sAttributeValue; - double x=0.0, y=0.0, width=0.0, height=0.0; - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - sAttributeValue = xAttributes->item(i)->getNodeValue(); - const sal_Int32 nAttribId( - getTokenId(xAttributes->item(i)->getNodeName())); - switch(nAttribId) - { - case XML_X: - x = convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_Y: - y = convLength(sAttributeValue,maCurrState,'v'); - break; - case XML_WIDTH: - width = convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_HEIGHT: - height = convLength(sAttributeValue,maCurrState,'v'); - break; - default: - // skip - break; - } - } - // extract basic transformations out of CTM - basegfx::B2DTuple aScale, aTranslate; - double fRotate, fShearX; - if (maCurrState.maCTM.decompose(aScale, aTranslate, fRotate, fShearX)) - { - // apply transform - x *= aScale.getX(); - width *= aScale.getX(); - y *= aScale.getY(); - height *= aScale.getY(); - x += aTranslate.getX(); - y += aTranslate.getY(); - //TODO: Rotate - } - - OUString sValue = xElem->hasAttribute("href") ? xElem->getAttribute("href") : ""; - OString aValueUtf8( sValue.getStr(), sValue.getLength(), RTL_TEXTENCODING_UTF8 ); - OUString sLinkValue; - parseXlinkHref(aValueUtf8.getStr(), sLinkValue); - - if (!sLinkValue.isEmpty()) - writeBinaryData(xAttrs, xUnoAttrs, basegfx::B2DRange(x,y,x+width,y+height), sLinkValue); - break; - } - case XML_TSPAN: - case XML_TEXT: - { - // collect text from all TEXT_NODE children into sText - OUStringBuffer sText; - visitChildren( - [&sText] (xml::dom::XNode & rNode) { - return sText.append(rNode.getNodeValue()); - }, - xElem, - xml::dom::NodeType_TEXT_NODE); - - // collect attributes - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - OUString sAttributeValue; - double x=0.0,y=0.0; - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - sAttributeValue = xAttributes->item(i)->getNodeValue(); - const sal_Int32 nAttribId( - getTokenId(xAttributes->item(i)->getNodeName())); - switch(nAttribId) - { - case XML_X: - x = convLength(sAttributeValue,maCurrState,'h'); - break; - case XML_Y: - y = convLength(sAttributeValue,maCurrState,'v'); - break; - default: - // skip - break; - } - } - - // actually export text - xAttrs->Clear(); - - - // extract basic transformations out of CTM - basegfx::B2DTuple aScale, aTranslate; - double fRotate, fShearX; - if (maCurrState.maCTM.decompose(aScale, aTranslate, fRotate, fShearX)) - { - // some heuristic attempts to have text output - // baseline-relative - y -= 2.0*maCurrState.mnFontSize/aScale.getX()/3.0; - // apply transform - x *= aScale.getX(); - y *= aScale.getY(); - x += aTranslate.getX(); - y += aTranslate.getY(); - //TODO: Rotate - } - else { - // some heuristic attempts to have text output - // baseline-relative - y -= 2.0*maCurrState.mnFontSize/3.0; - } - - xAttrs->AddAttribute( "svg:x", OUString::number(pt2mm(x))+"mm"); - xAttrs->AddAttribute( "svg:y", OUString::number(pt2mm(y))+"mm"); - xAttrs->AddAttribute( "draw:style-name", "svggraphicstyle"+sStyleId ); - - mxDocumentHandler->startElement("draw:frame", xUnoAttrs); - - xAttrs->Clear(); - mxDocumentHandler->startElement("draw:text-box", xUnoAttrs); - xAttrs->AddAttribute( "text:style-name", "svgparagraphstyle"+sStyleId); - mxDocumentHandler->startElement("text:p", xUnoAttrs); - - xAttrs->Clear(); - xAttrs->AddAttribute( "text:style-name", "svgtextstyle"+sStyleId); - mxDocumentHandler->startElement("text:span", xUnoAttrs); - - xAttrs->Clear(); - mxDocumentHandler->characters(sText.makeStringAndClear()); - mxDocumentHandler->endElement("text:span"); - mxDocumentHandler->endElement("text:p"); - mxDocumentHandler->endElement("draw:text-box"); - mxDocumentHandler->endElement("draw:frame"); - break; - } - } - } - - static void push() - {} - - static void pop() - {} - - void writeBinaryData( rtl::Reference<SvXMLAttributeList> const & xAttrs, - const uno::Reference<xml::sax::XAttributeList>& xUnoAttrs, - const basegfx::B2DRange& rShapeBounds, - const OUString& data) - { - xAttrs->Clear(); - xAttrs->AddAttribute( "svg:x", OUString::number(pt2mm(rShapeBounds.getMinX()))+"mm"); - xAttrs->AddAttribute( "svg:y", OUString::number(pt2mm(rShapeBounds.getMinY()))+"mm"); - xAttrs->AddAttribute( "svg:width", OUString::number(pt2mm(rShapeBounds.getWidth()))+"mm"); - xAttrs->AddAttribute( "svg:height", OUString::number(pt2mm(rShapeBounds.getHeight()))+"mm"); - - mxDocumentHandler->startElement("draw:frame", xUnoAttrs); - - xAttrs->Clear(); - mxDocumentHandler->startElement("draw:image", xUnoAttrs); - - mxDocumentHandler->startElement("office:binary-data", xUnoAttrs); - - mxDocumentHandler->characters(data); - - mxDocumentHandler->endElement("office:binary-data"); - - mxDocumentHandler->endElement("draw:image"); - - mxDocumentHandler->endElement("draw:frame"); - } - - - void writeEllipseShape( rtl::Reference<SvXMLAttributeList> const & xAttrs, - const uno::Reference<xml::sax::XAttributeList>& xUnoAttrs, - const OUString& rStyleId, - const basegfx::B2DEllipse& rEllipse) - { - State aState = maCurrState; - - xAttrs->Clear(); - - basegfx::B2DPolygon aPoly = basegfx::utils::createPolygonFromEllipse(rEllipse.getB2DEllipseCenter(), - rEllipse.getB2DEllipseRadius().getX(), rEllipse.getB2DEllipseRadius().getY()); - writePathShape(xAttrs, xUnoAttrs, rStyleId, basegfx::B2DPolyPolygon(aPoly)); - } - - void writePathShape( rtl::Reference<SvXMLAttributeList> const & xAttrs, - const uno::Reference<xml::sax::XAttributeList>& xUnoAttrs, - const OUString& rStyleId, - const basegfx::B2DPolyPolygon& rPoly ) - { - // we might need to split up polypolygon into multiple path - // shapes (e.g. when emulating line stroking) - std::vector<basegfx::B2DPolyPolygon> aPolys(1,rPoly); - State aState = maCurrState; - - xAttrs->Clear(); - - // TODO(F2): separate out shear, rotate etc. - // apply transformation to polygon, to keep draw - // import in 100th mm - for (basegfx::B2DPolyPolygon & aPoly : aPolys) - { - aPoly.transform(aState.maCTM); - } - - for(basegfx::B2DPolyPolygon & aPoly : aPolys) - { - const basegfx::B2DRange aBounds( - aPoly.areControlPointsUsed() ? - basegfx::utils::getRange( - basegfx::utils::adaptiveSubdivideByAngle(aPoly)) : - basegfx::utils::getRange(aPoly)); - fillShapeProperties(xAttrs, - aBounds, - "svggraphicstyle"+rStyleId); - - // force path coordinates to 100th millimeter, after - // putting polygon data at origin (ODF viewbox - // calculations largely untested codepaths, as OOo always - // writes "0 0 w h" viewboxes) - basegfx::B2DHomMatrix aNormalize; - aNormalize.translate(-aBounds.getMinX(),-aBounds.getMinY()); - aNormalize.scale(2540.0/72.0,2540.0/72.0); - aPoly.transform(aNormalize); - - xAttrs->AddAttribute( "svg:d", basegfx::utils::exportToSvgD( - aPoly, - false, // no relative coords. causes rounding errors - false, // no quad bezier detection. crashes older versions. - false )); - mxDocumentHandler->startElement("draw:path", xUnoAttrs); - mxDocumentHandler->endElement("draw:path"); - } - } - - void fillShapeProperties( rtl::Reference<SvXMLAttributeList> const & xAttrs, - const basegfx::B2DRange& rShapeBounds, - const OUString& rStyleName ) - { - xAttrs->AddAttribute( "draw:z-index", OUString::number( mnShapeNum++ )); - xAttrs->AddAttribute( "draw:style-name", rStyleName); - xAttrs->AddAttribute( "svg:width", OUString::number(pt2mm(rShapeBounds.getWidth()))+"mm"); - xAttrs->AddAttribute( "svg:height", OUString::number(pt2mm(rShapeBounds.getHeight()))+"mm"); - - // OOo expects the viewbox to be in 100th of mm - xAttrs->AddAttribute( "svg:viewBox", - "0 0 " - + OUString::number( - basegfx::fround(pt100thmm(rShapeBounds.getWidth())) ) - + " " - + OUString::number( - basegfx::fround(pt100thmm(rShapeBounds.getHeight())) )); - - // TODO(F1): decompose transformation in calling code, and use - // transform attribute here - // writeTranslate(maCurrState.maCTM, xAttrs); - xAttrs->AddAttribute( "svg:x", OUString::number(pt2mm(rShapeBounds.getMinX()))+"mm"); - xAttrs->AddAttribute( "svg:y", OUString::number(pt2mm(rShapeBounds.getMinY()))+"mm"); - } - - State maCurrState; - StateMap& mrStateMap; - uno::Reference<xml::sax::XDocumentHandler> mxDocumentHandler; - sal_Int32 mnShapeNum; -}; - -/// Write out shapes from DOM tree -void writeShapes( StateMap& rStateMap, - const uno::Reference<xml::dom::XElement>& rElem, - const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl, - std::vector< uno::Reference<xml::dom::XElement> >& rUseElementVector ) -{ - ShapeWritingVisitor aVisitor(rStateMap,xDocHdl); - visitElements(aVisitor, rElem, SHAPE_WRITER); - - for (auto const& useElement : rUseElementVector) - { - visitElements(aVisitor, useElement, SHAPE_WRITER); - } -} - -} // namespace - -struct OfficeStylesWritingVisitor -{ - OfficeStylesWritingVisitor( StateMap& rStateMap, - const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) : - mrStateMap(rStateMap), - mxDocumentHandler(xDocumentHandler) - {} - void operator()( const uno::Reference<xml::dom::XElement>& /*xElem*/ ) - { - } - void operator()( const uno::Reference<xml::dom::XElement>& xElem, - const uno::Reference<xml::dom::XNamedNodeMap>& /*xAttributes*/ ) - { - rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() ); - uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() ); - - sal_Int32 nDummyIndex(0); - OUString sStyleId( - xElem->getAttribute("internal-style-ref").getToken( - 0,'$',nDummyIndex)); - StateMap::iterator pOrigState=mrStateMap.find( - sStyleId.toInt32()); - - if( pOrigState == mrStateMap.end() ) - return; // non-exportable element, e.g. linearGradient - - maCurrState = pOrigState->second; - - if( maCurrState.meStrokeType == DASH ) - { - sal_Int32 dots1, dots2; - double dots1_length, dots2_length, dash_distance; - SvgDashArray2Odf( &dots1, &dots1_length, &dots2, &dots2_length, &dash_distance ); - - xAttrs->Clear(); - xAttrs->AddAttribute( "draw:name", "dash"+sStyleId ); - xAttrs->AddAttribute( "draw:display-name", "dash"+sStyleId ); - xAttrs->AddAttribute( "draw:style", "rect" ); - if ( dots1>0 ) { - xAttrs->AddAttribute( "draw:dots1", OUString::number(dots1) ); - xAttrs->AddAttribute( "draw:dots1-length", OUString::number(pt2mm(convLength( OUString::number(dots1_length), maCurrState, 'h' )))+"mm" ); - } - xAttrs->AddAttribute( "draw:distance", OUString::number(pt2mm(convLength( OUString::number(dash_distance), maCurrState, 'h' )))+"mm" ); - if ( dots2>0 ) { - xAttrs->AddAttribute( "draw:dots2", OUString::number(dots2) ); - xAttrs->AddAttribute( "draw:dots2-length", OUString::number(pt2mm(convLength( OUString::number(dots2_length), maCurrState, 'h' )))+"mm" ); - } - - mxDocumentHandler->startElement( "draw:stroke-dash", xUnoAttrs); - mxDocumentHandler->endElement( "draw:stroke-dash" ); - } - } - - void SvgDashArray2Odf( sal_Int32 *dots1, double *dots1_length, sal_Int32 *dots2, double *dots2_length, double *dash_distance ) - { - *dots1 = 0; - *dots1_length = 0; - *dots2 = 0; - *dots2_length = 0; - *dash_distance = 0; - - if( maCurrState.maDashArray.empty() ) { - return; - } - - double effective_dasharray_size = maCurrState.maDashArray.size(); - if( maCurrState.maDashArray.size() % 2 == 1 ) - effective_dasharray_size = maCurrState.maDashArray.size()*2; - - *dash_distance = maCurrState.maDashArray[1%maCurrState.maDashArray.size()]; - sal_Int32 dist_count = 1; - for( int i=3; i<effective_dasharray_size; i+=2 ) { - *dash_distance = ((dist_count * *dash_distance) + maCurrState.maDashArray[i%maCurrState.maDashArray.size()])/(dist_count+1); - ++dist_count; - } - - *dots1 = 1; - *dots1_length = maCurrState.maDashArray[0]; - int i=2; - while( ( i<effective_dasharray_size ) && ( maCurrState.maDashArray[i%maCurrState.maDashArray.size()] == *dots1_length ) ) { - ++(*dots1); - i += 2; - } - if( i<effective_dasharray_size ) { - *dots2 = 1; - *dots2_length = maCurrState.maDashArray[i]; - i+=2; - while( ( i<effective_dasharray_size ) && ( maCurrState.maDashArray[i%maCurrState.maDashArray.size()] == *dots2_length ) ) { - ++(*dots2); - i += 2; - } - } - - SAL_INFO("filter.svg", "SvgDashArray2Odf " << *dash_distance << " " << *dots1 << " " << *dots1_length << " " << *dots2 << " " << *dots2_length ); - } - - static void push() {} - static void pop() {} - - State maCurrState; - StateMap& mrStateMap; - uno::Reference<xml::sax::XDocumentHandler> mxDocumentHandler; -}; - -static void writeOfficeStyles( StateMap& rStateMap, - const uno::Reference<xml::dom::XElement>& rElem, - const uno::Reference<xml::sax::XDocumentHandler>& xDocHdl ) -{ - OfficeStylesWritingVisitor aVisitor( rStateMap, xDocHdl ); - visitElements( aVisitor, rElem, STYLE_WRITER ); - -} - -#ifdef DEBUG_FILTER_SVGREADER -struct DumpingVisitor -{ - void operator()( const uno::Reference<xml::dom::XElement>& xElem ) - { - SAL_WARN("filter", "name: " << xElem->getTagName()); - } - - void operator()( const uno::Reference<xml::dom::XElement>& xElem, - const uno::Reference<xml::dom::XNamedNodeMap>& xAttributes ) - { - SAL_WARN("filter", "name: " << xElem->getTagName()); - const sal_Int32 nNumAttrs( xAttributes->getLength() ); - for( sal_Int32 i=0; i<nNumAttrs; ++i ) - { - SAL_WARN("filter", xAttributes->item(i)->getNodeName() << "=" << xAttributes->item(i)->getNodeValue()); - } - } - - void push() {} - void pop() {} -}; - -static void dumpTree( const uno::Reference<xml::dom::XElement> xElem ) -{ - DumpingVisitor aVisitor; - visitElements(aVisitor, xElem, STYLE_ANNOTATOR); -} -#endif - - -SVGReader::SVGReader(const uno::Reference<uno::XComponentContext>& xContext, - const uno::Reference<io::XInputStream>& xInputStream, - const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler) : - SVGReader(xContext, xInputStream, xDocumentHandler, dynamic_cast<SvXMLImport *>(xDocumentHandler.get())) -{ -} - -SVGReader::SVGReader(const uno::Reference<uno::XComponentContext>& xContext, - const uno::Reference<io::XInputStream>& xInputStream, - const uno::Reference<xml::sax::XDocumentHandler>& xDocumentHandler, - SvXMLImport *pFastHandler) : - m_xContext( xContext ), - m_xInputStream( xInputStream ), - m_xDocumentHandler( pFastHandler != nullptr ? new SvXMLLegacyToFastDocHandler(pFastHandler) : xDocumentHandler ) -{ -} - -bool SVGReader::parseAndConvert() -{ - uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder = xml::dom::DocumentBuilder::create(m_xContext); - - uno::Reference<xml::dom::XDocument> xDom( - xDomBuilder->parse(m_xInputStream), - uno::UNO_QUERY_THROW ); - - uno::Reference<xml::dom::XElement> xDocElem( xDom->getDocumentElement(), - uno::UNO_QUERY_THROW ); - - // the root state for svg document - State aInitialState; - - - // doc boilerplate - - - m_xDocumentHandler->startDocument(); - - // get the document dimensions - - // if the "width" and "height" attributes are missing, inkscape fakes - // A4 portrait for. Let's do the same. - if (!xDocElem->hasAttribute("width")) - xDocElem->setAttribute("width", "210mm"); - if (!xDocElem->hasAttribute("height")) - xDocElem->setAttribute("height", "297mm"); - - double fViewPortWidth( pt2mm(convLength(xDocElem->getAttribute("width"),aInitialState,'h')) ); - double fViewPortHeight( pt2mm(convLength(xDocElem->getAttribute("height"),aInitialState,'v')) ); - - // document prolog - rtl::Reference<SvXMLAttributeList> xAttrs( new SvXMLAttributeList() ); - uno::Reference<xml::sax::XAttributeList> xUnoAttrs( xAttrs.get() ); - - xAttrs->AddAttribute( "xmlns:office", OASIS_STR "office:1.0" ); - xAttrs->AddAttribute( "xmlns:style", OASIS_STR "style:1.0" ); - xAttrs->AddAttribute( "xmlns:text", OASIS_STR "text:1.0" ); - xAttrs->AddAttribute( "xmlns:svg", OASIS_STR "svg-compatible:1.0" ); - xAttrs->AddAttribute( "xmlns:table", OASIS_STR "table:1.0" ); - xAttrs->AddAttribute( "xmlns:draw", OASIS_STR "drawing:1.0" ); - xAttrs->AddAttribute( "xmlns:fo", OASIS_STR "xsl-fo-compatible:1.0" ); - xAttrs->AddAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink"); - xAttrs->AddAttribute( "xmlns:dc", "http://purl.org/dc/elements/1.1/"); - xAttrs->AddAttribute( "xmlns:number", OASIS_STR "datastyle:1.0" ); - xAttrs->AddAttribute( "xmlns:presentation", OASIS_STR "presentation:1.0" ); - xAttrs->AddAttribute( "xmlns:math", "http://www.w3.org/1998/Math/MathML"); - xAttrs->AddAttribute( "xmlns:form", OASIS_STR "form:1.0" ); - xAttrs->AddAttribute( "xmlns:script", OASIS_STR "script:1.0" ); - xAttrs->AddAttribute( "xmlns:config", OASIS_STR "config:1.0" ); - xAttrs->AddAttribute( "xmlns:dom", "http://www.w3.org/2001/xml-events"); - xAttrs->AddAttribute( "xmlns:xforms", "http://www.w3.org/2002/xforms"); - xAttrs->AddAttribute( "xmlns:xsd", "http://www.w3.org/2001/XMLSchema"); - xAttrs->AddAttribute( "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); - xAttrs->AddAttribute( "office:version", "1.0"); - xAttrs->AddAttribute( "office:mimetype", "application/vnd.oasis.opendocument.graphics"); - - m_xDocumentHandler->startElement( "office:document", xUnoAttrs ); - - xAttrs->Clear(); - - m_xDocumentHandler->startElement( "office:settings", xUnoAttrs); - - xAttrs->AddAttribute( "config:name", "ooo:view-settings"); - m_xDocumentHandler->startElement( "config:config-item-set", xUnoAttrs); - - xAttrs->Clear(); - - xAttrs->AddAttribute( "config:name", "VisibleAreaTop"); - xAttrs->AddAttribute( "config:type", "int"); - m_xDocumentHandler->startElement( "config:config-item", xUnoAttrs); - - m_xDocumentHandler->characters( "0" ); - - m_xDocumentHandler->endElement( "config:config-item" ); - - xAttrs->Clear(); - - xAttrs->AddAttribute( "config:name", "VisibleAreaLeft" ); - xAttrs->AddAttribute( "config:type", "int" ); - m_xDocumentHandler->startElement( "config:config-item" , xUnoAttrs); - - m_xDocumentHandler->characters( "0" ); - - m_xDocumentHandler->endElement( "config:config-item" ); - - xAttrs->Clear(); - - xAttrs->AddAttribute( "config:name" , "VisibleAreaWidth" ); - xAttrs->AddAttribute( "config:type" , "int" ); - m_xDocumentHandler->startElement( "config:config-item" , xUnoAttrs); - - sal_Int64 iWidth = sal_Int64(fViewPortWidth); - m_xDocumentHandler->characters( OUString::number(iWidth) ); - - m_xDocumentHandler->endElement( "config:config-item" ); - - xAttrs->Clear(); - - xAttrs->AddAttribute( "config:name", "VisibleAreaHeight" ); - xAttrs->AddAttribute( "config:type", "int" ); - m_xDocumentHandler->startElement( "config:config-item", xUnoAttrs); - - sal_Int64 iHeight = sal_Int64(fViewPortHeight); - m_xDocumentHandler->characters( OUString::number(iHeight) ); - - m_xDocumentHandler->endElement( "config:config-item" ); - - m_xDocumentHandler->endElement( "config:config-item-set" ); - - m_xDocumentHandler->endElement( "office:settings" ); - - xAttrs->Clear(); - - m_xDocumentHandler->startElement( "office:automatic-styles", - xUnoAttrs ); - - xAttrs->AddAttribute( "style:name", "pagelayout1"); - m_xDocumentHandler->startElement( "style:page-layout", xUnoAttrs ); - // TODO(Q3): this is super-ugly. In-place container come to mind. - xAttrs->Clear(); - - // make page viewport-width times viewport-height mm large - add - // 5% border at every side - xAttrs->AddAttribute( "fo:margin-top", "0mm"); - xAttrs->AddAttribute( "fo:margin-bottom", "0mm"); - xAttrs->AddAttribute( "fo:margin-left", "0mm"); - xAttrs->AddAttribute( "fo:margin-right", "0mm"); - xAttrs->AddAttribute( "fo:page-width", OUString::number(fViewPortWidth)+"mm"); - xAttrs->AddAttribute( "fo:page-height", OUString::number(fViewPortHeight)+"mm"); - xAttrs->AddAttribute( "style:print-orientation", - fViewPortWidth > fViewPortHeight ? OUString("landscape") : OUString("portrait") ); - m_xDocumentHandler->startElement( "style:page-layout-properties", xUnoAttrs ); - m_xDocumentHandler->endElement( "style:page-layout-properties" ); - m_xDocumentHandler->endElement( "style:page-layout" ); - - xAttrs->Clear(); - xAttrs->AddAttribute( "style:name", "pagestyle1" ); - xAttrs->AddAttribute( "style:family", "drawing-page" ); - m_xDocumentHandler->startElement( "style:style", xUnoAttrs ); - - xAttrs->Clear(); - xAttrs->AddAttribute( "draw:background-size", "border"); - xAttrs->AddAttribute( "draw:fill", "none"); - m_xDocumentHandler->startElement( "style:drawing-page-properties", xUnoAttrs ); - m_xDocumentHandler->endElement( "style:drawing-page-properties" ); - m_xDocumentHandler->endElement( "style:style" ); - - StatePool aStatePool; - StateMap aStateMap; - std::vector< uno::Reference<xml::dom::XElement> > aUseElementVector; - - annotateStyles(aStatePool,aStateMap,aInitialState, - xDocElem,m_xDocumentHandler,aUseElementVector); - -#ifdef DEBUG_FILTER_SVGREADER - dumpTree(xDocElem); -#endif - - m_xDocumentHandler->endElement( "office:automatic-styles" ); - - xAttrs->Clear(); - m_xDocumentHandler->startElement( "office:styles", xUnoAttrs); - writeOfficeStyles( aStateMap, - xDocElem, - m_xDocumentHandler); - m_xDocumentHandler->endElement( "office:styles" ); - - - m_xDocumentHandler->startElement( "office:master-styles", xUnoAttrs ); - xAttrs->Clear(); - xAttrs->AddAttribute( "style:name", "Default"); - xAttrs->AddAttribute( "style:page-layout-name", "pagelayout1"); - xAttrs->AddAttribute( "draw:style-name", "pagestyle1"); - m_xDocumentHandler->startElement( "style:master-page", xUnoAttrs ); - m_xDocumentHandler->endElement( "style:master-page" ); - - m_xDocumentHandler->endElement( "office:master-styles" ); - - - xAttrs->Clear(); - m_xDocumentHandler->startElement( "office:body", xUnoAttrs ); - m_xDocumentHandler->startElement( "office:drawing", xUnoAttrs ); - - xAttrs->Clear(); - xAttrs->AddAttribute( "draw:master-page-name", "Default"); - xAttrs->AddAttribute( "draw:style-name", "pagestyle1"); - m_xDocumentHandler->startElement("draw:page", xUnoAttrs); - - // write out all shapes - writeShapes(aStateMap, - xDocElem, - m_xDocumentHandler, - aUseElementVector); - - m_xDocumentHandler->endElement( "draw:page" ); - m_xDocumentHandler->endElement( "office:drawing" ); - m_xDocumentHandler->endElement( "office:body" ); - m_xDocumentHandler->endElement( "office:document" ); - m_xDocumentHandler->endDocument(); - - return true; -} - -} // namespace svgi - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/test/parsertest.cxx b/filter/source/svg/test/parsertest.cxx deleted file mode 100644 index 8cb367ea9a6d..000000000000 --- a/filter/source/svg/test/parsertest.cxx +++ /dev/null @@ -1,172 +0,0 @@ -/* -*- 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/. - */ - -#include <sal/types.h> -#include <cppunit/TestAssert.h> -#include <cppunit/TestFixture.h> -#include <cppunit/extensions/HelperMacros.h> - -#include "gfxtypes.hxx" -#include "parserfragments.hxx" - -using namespace svgi; - -class TestParser : public CppUnit::TestFixture -{ -public: - void testParseColor() - { - ARGBColor aTmp; - - const char* sIn="#102030 "; - ARGBColor aOut(16, 32, 48); - CPPUNIT_ASSERT_MESSAGE( "Consuming color #112233", - parseColor( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing color #112233", - aOut==aTmp ); - - sIn=" #321"; - aOut=ARGBColor(51, 34, 17); - CPPUNIT_ASSERT_MESSAGE( "Consuming color #321", - parseColor( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing color #321", - aOut==aTmp ); - - sIn="rgb(100,200,\t 50)"; - aOut=ARGBColor(100, 200, 50); - CPPUNIT_ASSERT_MESSAGE( "Consuming color rgb(100,200,50)", - parseColor( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing color rgb(100,200,50)", - aOut==aTmp ); - - sIn="rgb(0.1, \t0.2,0.9)"; - aOut=ARGBColor(0.1, 0.2, 0.9); - CPPUNIT_ASSERT_MESSAGE( "Consuming color rgb(0.1,0.2,0.9)", - parseColor( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing color rgb(0.1,0.2,0.9)", - aOut==aTmp ); - - sIn=" burlywood "; - aOut=ARGBColor(222,184,135); - CPPUNIT_ASSERT_MESSAGE( "Consuming color burlywood", - parseColor( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing color burlywood", - aOut==aTmp ); - } - - void testParseOpacity() - { - ARGBColor aTmp; - - const char* sIn=" 0.123 "; - ARGBColor aOut(0.123, 0.0, 0.0, 0.0); - CPPUNIT_ASSERT_MESSAGE( "Consuming opacity 0.123", - parseOpacity( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing opacity 0.123", - aOut==aTmp ); - } - - void testParseTransform() - { - basegfx::B2DHomMatrix aOut; - - const char* sIn=" none "; - basegfx::B2DHomMatrix aTmp; - CPPUNIT_ASSERT_MESSAGE( "Consuming transformation none", - parseTransform( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing transformation none", - aOut==aTmp ); - - sIn=" scale( 10 ) "; - aOut.identity(); - aOut.scale(10.0,10.0); - CPPUNIT_ASSERT_MESSAGE( "Consuming transformation scale(10)", - parseTransform( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing transformation scale(10)", - aOut==aTmp ); - - sIn=" scale( 10 20.12 ) "; - aOut.identity(); - aOut.scale(10.0,20.12); - CPPUNIT_ASSERT_MESSAGE( "Consuming transformation scale(10 20.12)", - parseTransform( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing transformation scale(10 20.12)", - aOut==aTmp ); - - sIn="matrix( 1,2 3,4,5 6 )"; - aOut.identity(); - aOut.set(0,0,1.0); aOut.set(1,0,2.0); aOut.set(0,1,3.0); aOut.set(1,1,4.0); aOut.set(0,2,5.0); aOut.set(1,2,6.0); - CPPUNIT_ASSERT_MESSAGE( "Consuming transformation matrix(1,2,3,4,5,6)", - parseTransform( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing transformation matrix(1,2,3,4,5,6)", - aOut==aTmp ); - - sIn="matrix( 1 0 0 1 -10 -10 ) translate(10) scale(10), rotate(90)"; - aOut.identity(); - aOut.set(0,0,0.0); aOut.set(1,0,10.0); aOut.set(0,1,-10.0); aOut.set(1,1,0.0); aOut.set(0,2,0.0); aOut.set(1,2,0.0); - CPPUNIT_ASSERT_MESSAGE( "Consuming transformation matrix(1,2,3,4,5,6)", - parseTransform( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing transformation matrix(1,2,3,4,5,6)", - aOut==aTmp ); - - sIn="skewX(45)"; - aOut.identity(); - aOut.set(0,0,1.0); aOut.set(1,0,1.0); aOut.set(0,1,0.0); aOut.set(1,1,1.0); aOut.set(0,2,0.0); aOut.set(1,2,0.0); - CPPUNIT_ASSERT_MESSAGE( "Consuming transformation skewX(45)", - parseTransform( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing transformation skewX(45)", - aOut==aTmp ); - - sIn="skewY(45)"; - aOut.identity(); - aOut.set(0,0,1.0); aOut.set(1,0,0.0); aOut.set(0,1,1.0); aOut.set(1,1,1.0); aOut.set(0,2,0.0); aOut.set(1,2,0.0); - CPPUNIT_ASSERT_MESSAGE( "Consuming transformation skewY(45)", - parseTransform( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing transformation skewY(45)", - aOut==aTmp ); - } - - void testParseViewBox() - { - basegfx::B2DRange aTmp; - - const char* sIn=" 10 20, 30.5,5 "; - basegfx::B2DRange aOut(10,20,40.5,25); - CPPUNIT_ASSERT_MESSAGE( "Consuming 10,20,30.5,5", - parseViewBox( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing 10,20,30.5,5", - aOut==aTmp ); - } - - void testParseDashArray() - { - std::vector<double> aTmp; - - const char* sIn=" 10,20, -10.00 "; - std::vector<double> aOut; aOut.push_back(10.0); aOut.push_back(20.0); aOut.push_back(-10.0); - CPPUNIT_ASSERT_MESSAGE( "Consuming 10,20,-10.00", - parseDashArray( sIn, aTmp ) ); - CPPUNIT_ASSERT_MESSAGE( "Parsing 10,20,-10.00", - aOut==aTmp ); - } - - CPPUNIT_TEST_SUITE(TestParser); - CPPUNIT_TEST(testParseColor); - CPPUNIT_TEST(testParseOpacity); - CPPUNIT_TEST(testParseTransform); - CPPUNIT_TEST(testParseViewBox); - CPPUNIT_TEST(testParseDashArray); - // TODO: CPPUNIT_TEST(testParseXlinkHref); - CPPUNIT_TEST_SUITE_END(); -}; - - -CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(TestParser, "test svg parser fragments"); - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/test/svg2odf.cxx b/filter/source/svg/test/svg2odf.cxx deleted file mode 100644 index 524c2e79424e..000000000000 --- a/filter/source/svg/test/svg2odf.cxx +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- 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 . - */ - -#include <svgreader.hxx> -#include "odfserializer.hxx" - -#include <sal/main.h> -#include <osl/file.hxx> -#include <osl/process.h> -#include <rtl/bootstrap.hxx> - -#include <cppuhelper/implbase.hxx> -#include <cppuhelper/bootstrap.hxx> -#include <comphelper/processfactory.hxx> -#include <comphelper/oslfile2streamwrap.hxx> - -using namespace ::com::sun::star; - -namespace -{ - class OutputWrap : public cppu::WeakImplHelper< - io::XOutputStream> - { - osl::File maFile; - - public: - - explicit OutputWrap( const OUString& rURL ) : maFile(rURL) - { - maFile.open( osl_File_OpenFlag_Create|osl_File_OpenFlag_Write ); - } - - virtual void SAL_CALL writeBytes( const css::uno::Sequence< ::sal_Int8 >& aData ) override - - { - sal_uInt64 nBytesWritten(0); - maFile.write(aData.getConstArray(),aData.getLength(),nBytesWritten); - } - - virtual void SAL_CALL flush() override - { - } - - virtual void SAL_CALL closeOutput() override - { - maFile.close(); - } - }; -} - -SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) -{ - if( argc != 4 ) - { - SAL_WARN("filter.svg", "Invocation: svg2odf <base_url> <dst_url> <ini_file>. Exiting" ); - return 1; - } - - int nRet = 1; - - try - { - OUString aBaseURL, aTmpURL, aSrcURL, aDstURL, aIniUrl; - - osl_getProcessWorkingDir(&aBaseURL.pData); - osl_getFileURLFromSystemPath( OUString::createFromAscii(argv[1]).pData, - &aTmpURL.pData ); - osl_getAbsoluteFileURL(aBaseURL.pData,aTmpURL.pData,&aSrcURL.pData); - - osl_getFileURLFromSystemPath( OUString::createFromAscii(argv[2]).pData, - &aTmpURL.pData ); - osl_getAbsoluteFileURL(aBaseURL.pData,aTmpURL.pData,&aDstURL.pData); - - osl_getFileURLFromSystemPath( OUString::createFromAscii(argv[3]).pData, - &aTmpURL.pData ); - osl_getAbsoluteFileURL(aBaseURL.pData,aTmpURL.pData,&aIniUrl.pData); - - // bootstrap UNO - uno::Reference< lang::XMultiServiceFactory > xFactory; - uno::Reference< uno::XComponentContext > xCtx; - xCtx = ::cppu::defaultBootstrap_InitialComponentContext(aIniUrl); - xFactory.set(xCtx->getServiceManager(), uno::UNO_QUERY); - if (!xFactory.is()) - { - SAL_WARN("filter.svg", "Could not bootstrap UNO, installation must be in disorder. Exiting." ); - return 1; - } - - ::comphelper::setProcessServiceFactory( xFactory ); - - osl::File aInputFile(aSrcURL); - if( osl::FileBase::E_None!=aInputFile.open(osl_File_OpenFlag_Read) ) - { - SAL_WARN("filter.svg", "Cannot open input file" ); - return 1; - } - - svgi::SVGReader aReader(xCtx, - uno::Reference<io::XInputStream>( - new comphelper::OSLInputStreamWrapper(aInputFile)), - svgi::createSerializer(new OutputWrap(aDstURL))); - nRet = aReader.parseAndConvert() ? 0 : 1; - - } - catch (const uno::Exception& e) - { - SAL_WARN("filter.svg", "Fatal exception: " << e); - return 1; - } - catch (const std::exception &e) - { - SAL_WARN("filter.svg", "Fatal exception: " << e.what()); - return 1; - } - return nRet; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/tokenmap.cxx b/filter/source/svg/tokenmap.cxx deleted file mode 100644 index 3362803887cd..000000000000 --- a/filter/source/svg/tokenmap.cxx +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- 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 . - */ - -#include "tokenmap.hxx" -#include <string.h> - -namespace svgi -{ - -#if defined __clang__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" -#if __has_warning("-Wdeprecated-register") -#pragma GCC diagnostic ignored "-Wdeprecated-register" -#endif -#endif -#include <tokens.cxx> -#if defined __clang__ -#pragma GCC diagnostic pop -#endif - -sal_Int32 getTokenId( const char* sIdent, sal_Int32 nLen ) -{ - const struct xmltoken* t = Perfect_Hash::in_word_set( sIdent, nLen ); - if( t ) - return t->nToken; - else - return XML_TOKEN_INVALID; -} - -sal_Int32 getTokenId( const OUString& sIdent ) -{ - OString aUTF8( sIdent.getStr(), - sIdent.getLength(), - RTL_TEXTENCODING_UTF8 ); - return getTokenId( aUTF8.getStr(), aUTF8.getLength() ); -} - -const char* getTokenName( sal_Int32 nTokenId ) -{ - if( nTokenId >= XML_TOKEN_COUNT ) - return nullptr; - - const xmltoken* pCurr=wordlist; - const xmltoken* pEnd=wordlist+SAL_N_ELEMENTS(wordlist); - while( pCurr != pEnd ) - { - if(pCurr->nToken == nTokenId) - return pCurr->name; - ++pCurr; - } - - return nullptr; -} - -} // namespace svgi - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/tokenmap.hxx b/filter/source/svg/tokenmap.hxx deleted file mode 100644 index b227d07a01ac..000000000000 --- a/filter/source/svg/tokenmap.hxx +++ /dev/null @@ -1,27 +0,0 @@ -/* -*- 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/. - */ -#ifndef INCLUDED_FILTER_SOURCE_SVG_TOKENMAP_HXX -#define INCLUDED_FILTER_SOURCE_SVG_TOKENMAP_HXX - -#include <tokens.hxx> - -#include <rtl/string.hxx> -#include <rtl/ustring.hxx> - -namespace svgi -{ - sal_Int32 getTokenId( const char* sIdent, sal_Int32 nLen ); - sal_Int32 getTokenId( const OUString& sIdent ); - const char* getTokenName( sal_Int32 nTokenId ); - -} // namespace svgi - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/units.cxx b/filter/source/svg/units.cxx deleted file mode 100644 index d3537b3af72e..000000000000 --- a/filter/source/svg/units.cxx +++ /dev/null @@ -1,143 +0,0 @@ -/* -*- 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/. - */ - -#include "units.hxx" -#include <basegfx/range/b2drange.hxx> -#include <gfxtypes.hxx> -#include <rtl/ustring.hxx> -#include <boost/spirit/include/classic.hpp> - -namespace svgi -{ - -double convLength( const OUString& value, SvgUnit unit, const State& rState, char dir ) -{ - // convert svg unit to internal coordinates ("pixel"). Since the - // OOo drawing layer is still largely integer-based, the initial - // viewport transformation includes a certain scale factor - double fRet(value.toDouble()); - switch ( unit ) - { - case SVG_LENGTH_UNIT_CM: fRet *= F_SVG_PIXEL_PER_INCH/2.54; break; - case SVG_LENGTH_UNIT_IN: fRet *= F_SVG_PIXEL_PER_INCH; break; - case SVG_LENGTH_UNIT_MM: fRet *= F_SVG_PIXEL_PER_INCH/25.4; break; - case SVG_LENGTH_UNIT_PC: fRet *= F_SVG_PIXEL_PER_INCH/6.0; break; - case SVG_LENGTH_UNIT_PT: fRet *= F_SVG_PIXEL_PER_INCH/72.0; break; - case SVG_LENGTH_UNIT_EM: fRet *= rState.mnFontSize; break; - case SVG_LENGTH_UNIT_EX: fRet *= rState.mnFontSize / 2.0; break; - case SVG_LENGTH_UNIT_USER: - case SVG_LENGTH_UNIT_PX: - // no unit defaults to PX in svg, assume display to have 90DPI - break; - case SVG_LENGTH_FONT_SIZE: - { - //In CSS2, the suggested scaling factor between adjacent indexes is 1.2 - if ( value == "xx-small" ) - fRet = rState.mnFontSize / 1.728; - else if ( value == "x-small" ) - fRet = rState.mnFontSize / 1.44; - else if ( value == "small" ) - fRet = rState.mnFontSize / 1.2; - else if ( value == "smaller" ) - fRet = rState.mnParentFontSize / 1.2; - else if ( value == "initial" || value == "medium" ) - fRet = rState.mnFontSize; - else if ( value == "larger" ) - fRet = rState.mnParentFontSize * 1.2; - else if ( value == "large" ) - fRet = rState.mnFontSize * 1.2; - else if ( value == "x-large" ) - fRet = rState.mnFontSize * 1.44; - else if ( value == "xx-large" ) - fRet = rState.mnFontSize * 1.728; - - break; - } - case SVG_LENGTH_UNIT_PERCENTAGE: - { - double fBoxLen; - if (rState.maViewBox.isEmpty()) - { - basegfx::B2DRange aDefaultBox(0, 0, - convLength("210", SVG_LENGTH_UNIT_MM, rState, 'h'), - convLength("297", SVG_LENGTH_UNIT_MM, rState, 'v')); - fBoxLen = (dir=='h' ? aDefaultBox.getWidth() : - (dir=='v' ? aDefaultBox.getHeight() : - aDefaultBox.getRange().getLength())); - } - else - { - fBoxLen = (dir=='h' ? rState.maViewBox.getWidth() : - (dir=='v' ? rState.maViewBox.getHeight() : - rState.maViewBox.getRange().getLength())); - } - - fRet *= fBoxLen/100.0; - } - break; - default: SAL_WARN("filter.svg", "Unknown length type" ); break; - } - - return fRet; -} - -double convLength( const OUString& sValue, const State& rState, char dir ) -{ - //FIXME: convert deprecated spirit::classic to use spirit::qi - using namespace ::boost::spirit::classic; - - OString aUTF8 = OUStringToOString( sValue, - RTL_TEXTENCODING_UTF8 ); - - std::string sVal; - SvgUnit eUnit=SVG_LENGTH_UNIT_PX; - const bool bRes = parse(aUTF8.getStr(), - // Begin grammar - ( - //parse font-size keywords (ie: xx-large, medium ) - ( +alpha_p >> !(str_p("-") >> +alpha_p) )[assign_a(sVal)] - >> str_p("")[assign_a(eUnit,SVG_LENGTH_FONT_SIZE)] | - //take the first part and ignore the units - ( +(anychar_p - - (str_p("cm") | - str_p("em") | - str_p("ex") | - str_p("in") | - str_p("mm") | - str_p("pc") | - str_p("pt") | - str_p("px") | - str_p("%"))) - )[assign_a(sVal)] - >> ( str_p("cm") [assign_a(eUnit,SVG_LENGTH_UNIT_CM)] - | str_p("em") [assign_a(eUnit,SVG_LENGTH_UNIT_EM)] - | str_p("ex") [assign_a(eUnit,SVG_LENGTH_UNIT_EX)] - | str_p("in") [assign_a(eUnit,SVG_LENGTH_UNIT_IN)] - | str_p("mm") [assign_a(eUnit,SVG_LENGTH_UNIT_MM)] - | str_p("pc") [assign_a(eUnit,SVG_LENGTH_UNIT_PC)] - | str_p("pt") [assign_a(eUnit,SVG_LENGTH_UNIT_PT)] - | str_p("px") [assign_a(eUnit,SVG_LENGTH_UNIT_PX)] - | str_p("%") [assign_a(eUnit,SVG_LENGTH_UNIT_PERCENTAGE)] - | str_p("") [assign_a(eUnit,SVG_LENGTH_UNIT_USER)] - | end_p) - ), - // End grammar - space_p).full; - - if( !bRes ) - return 0.0; - - OUString oVal = OUString::createFromAscii(sVal.c_str()).replaceAll(",","."); - - return convLength(oVal,eUnit,rState,dir); -} - -} // namespace svgi - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/svg/units.hxx b/filter/source/svg/units.hxx deleted file mode 100644 index 06b7217c1b6c..000000000000 --- a/filter/source/svg/units.hxx +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- 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/. - */ -#ifndef INCLUDED_FILTER_SOURCE_SVG_UNITS_HXX -#define INCLUDED_FILTER_SOURCE_SVG_UNITS_HXX - -#include <sal/config.h> -#include <rtl/ustring.hxx> - -namespace svgi -{ - // recommended value for this device dependent unit, see CSS2 section 4.3.2 Lengths - // Same as in svgio - #define F_SVG_PIXEL_PER_INCH 90.0 - - struct State; - enum SvgUnit - { - SVG_LENGTH_UNIT_CM, - SVG_LENGTH_UNIT_EM, - SVG_LENGTH_UNIT_EX, - SVG_LENGTH_UNIT_IN, - SVG_LENGTH_UNIT_MM, - SVG_LENGTH_UNIT_PC, - SVG_LENGTH_UNIT_PT, - SVG_LENGTH_UNIT_PX, - SVG_LENGTH_UNIT_PERCENTAGE, - SVG_LENGTH_UNIT_USER, - SVG_LENGTH_FONT_SIZE - }; - - /** return svg_length_t in 100th's of mm - @param fVal value to convert - @param unit unit the value is in - @param rState current state (needed for viewport dimensions etc.) - @param dir direction - either 'h' or 'v' for horizonal or vertical, resp. - */ - double convLength( const OUString& sVal, SvgUnit unit, const State& rState, char dir ); - - /** return svg_length_t in 100th's of mm - @param sValue value to convert - @param rState current state (needed for viewport dimensions etc.) - @param dir direction - either 'h' or 'v' for horizonal or vertical, resp. - */ - double convLength( const OUString& sValue, const State& rState, char dir ); - - inline double pt2mm(double fVal) { return fVal*25.4/72.0; } - inline double pt100thmm(double fVal) { return fVal*2540.0/72.0; } - -} // namespace svgi - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/svdmodel.hxx b/include/svx/svdmodel.hxx index 0b7b5ab5cc40..cc5ad89b74dc 100644 --- a/include/svx/svdmodel.hxx +++ b/include/svx/svdmodel.hxx @@ -214,8 +214,16 @@ public: sal_uInt16 getHandoutPageCount() const { return mnHandoutPageCount; } void setHandoutPageCount( sal_uInt16 nHandoutPageCount ) { mnHandoutPageCount = nHandoutPageCount; } -protected: + // Adapt to given Size and Borders scaling all contained data, maybe + // including PresObj's in higher derivations + virtual void adaptSizeAndBorderForAllPages( + const Size& rNewSize, + long nLeft = 0, + long nRight = 0, + long nUpper = 0, + long nLower = 0); +protected: virtual css::uno::Reference< css::uno::XInterface > createUnoModel(); private: diff --git a/sd/inc/drawdoc.hxx b/sd/inc/drawdoc.hxx index ac824cf90653..a302fa6eb726 100644 --- a/sd/inc/drawdoc.hxx +++ b/sd/inc/drawdoc.hxx @@ -77,6 +77,7 @@ struct SpellCallbackInfo; class SdDrawDocument; class SdCustomShow; class SdCustomShowList; +class SdUndoGroup; namespace sd { @@ -202,8 +203,34 @@ protected: public: - SAL_DLLPRIVATE SdDrawDocument(DocumentType eType, SfxObjectShell* pDocSh); - SAL_DLLPRIVATE virtual ~SdDrawDocument() override; + SAL_DLLPRIVATE SdDrawDocument(DocumentType eType, SfxObjectShell* pDocSh); + SAL_DLLPRIVATE virtual ~SdDrawDocument() override; + + // Adapt to given Size and Borders scaling all contained data, maybe + // including PresObj's in higher derivations + virtual void adaptSizeAndBorderForAllPages( + const Size& rNewSize, + long nLeft = 0, + long nRight = 0, + long nUpper = 0, + long nLower = 0) override; + + // Adapt PageSize for all Pages of PageKind ePageKind. Also + // set Borders to left/right/upper/lower, ScaleAll, Orientation, + // PaperBin and BackgroundFullSize. Create Undo-Actions when + // a SdUndoGroup is given (then used from the View probably) + void AdaptPageSizeForAllPages( + const Size& rNewSize, + PageKind ePageKind, + SdUndoGroup* pUndoGroup = nullptr, + long nLeft = 0, + long nRight = 0, + long nUpper = 0, + long nLower = 0, + bool bScaleAll = false, + Orientation eOrientation = Orientation::Landscape, + sal_uInt16 nPaperBin = 0, + bool bBackgroundFullSize = false); SAL_DLLPRIVATE SdDrawDocument* AllocSdDrawDocument() const; SAL_DLLPRIVATE virtual SdrModel* AllocModel() const override; //forwards to AllocSdDrawDocument diff --git a/sd/source/core/drawdoc.cxx b/sd/source/core/drawdoc.cxx index 36d6a82e251e..0c152e067594 100644 --- a/sd/source/core/drawdoc.cxx +++ b/sd/source/core/drawdoc.cxx @@ -96,7 +96,8 @@ #include <optsitem.hxx> #include <FrameView.hxx> #include <undo/undomanager.hxx> - +#include <sdundogr.hxx> +#include <undopage.hxx> #include <tools/tenccvt.hxx> #include <vcl/settings.hxx> @@ -392,6 +393,179 @@ SdDrawDocument::~SdDrawDocument() mpCharClass.reset(); } +void SdDrawDocument::adaptSizeAndBorderForAllPages( + const Size& rNewSize, + long nLeft, + long nRight, + long nUpper, + long nLower) +{ + const sal_uInt16 nMasterPageCnt(GetMasterSdPageCount(PageKind::Standard)); + const sal_uInt16 nPageCnt(GetSdPageCount(PageKind::Standard)); + + if(0 == nMasterPageCnt && 0 == nPageCnt) + { + return; + } + + SdPage* pPage(0 != nPageCnt ? GetSdPage(0, PageKind::Standard) : GetMasterSdPage(0, PageKind::Standard)); + + // call fully implemented local version, including getting + // some more information from one of the Pages (1st one) + AdaptPageSizeForAllPages( + rNewSize, + PageKind::Standard, + nullptr, + nLeft, + nRight, + nUpper, + nLower, + true, + pPage->GetOrientation(), + pPage->GetPaperBin(), + pPage->IsBackgroundFullSize()); + + // adjust handout page to new format of the standard page + if(0 != nPageCnt) + { + GetSdPage(0, PageKind::Handout)->CreateTitleAndLayout(true); + } +} + +void SdDrawDocument::AdaptPageSizeForAllPages( + const Size& rNewSize, + PageKind ePageKind, + SdUndoGroup* pUndoGroup, + long nLeft, + long nRight, + long nUpper, + long nLower, + bool bScaleAll, + Orientation eOrientation, + sal_uInt16 nPaperBin, + bool bBackgroundFullSize) +{ + sal_uInt16 i; + const sal_uInt16 nMasterPageCnt(GetMasterSdPageCount(ePageKind)); + const sal_uInt16 nPageCnt(GetSdPageCount(ePageKind)); + + if(0 == nMasterPageCnt && 0 == nPageCnt) + { + return; + } + + for (i = 0; i < nMasterPageCnt; i++) + { + // first, handle all master pages + SdPage* pPage(GetMasterSdPage(i, ePageKind)); + + if(pUndoGroup) + { + SdUndoAction* pUndo( + new SdPageFormatUndoAction( + this, + pPage, + pPage->GetSize(), + pPage->GetLeftBorder(), pPage->GetRightBorder(), + pPage->GetUpperBorder(), pPage->GetLowerBorder(), + pPage->GetOrientation(), + pPage->GetPaperBin(), + pPage->IsBackgroundFullSize(), + rNewSize, + nLeft, nRight, + nUpper, nLower, + bScaleAll, + eOrientation, + nPaperBin, + bBackgroundFullSize)); + pUndoGroup->AddAction(pUndo); + } + + if (rNewSize.Width() > 0 || nLeft >= 0 || nRight >= 0 || nUpper >= 0 || nLower >= 0) + { + ::tools::Rectangle aNewBorderRect(nLeft, nUpper, nRight, nLower); + pPage->ScaleObjects(rNewSize, aNewBorderRect, bScaleAll); + + if (rNewSize.Width() > 0) + { + pPage->SetSize(rNewSize); + } + } + + if( nLeft >= 0 || nRight >= 0 || nUpper >= 0 || nLower >= 0 ) + { + pPage->SetBorder(nLeft, nUpper, nRight, nLower); + } + + pPage->SetOrientation(eOrientation); + pPage->SetPaperBin( nPaperBin ); + pPage->SetBackgroundFullSize( bBackgroundFullSize ); + + if ( ePageKind == PageKind::Standard ) + { + GetMasterSdPage(i, PageKind::Notes)->CreateTitleAndLayout(); + } + + pPage->CreateTitleAndLayout(); + } + + for (i = 0; i < nPageCnt; i++) + { + // then, handle all pages + SdPage* pPage(GetSdPage(i, ePageKind)); + + if(pUndoGroup) + { + SdUndoAction* pUndo( + new SdPageFormatUndoAction( + this, + pPage, + pPage->GetSize(), + pPage->GetLeftBorder(), pPage->GetRightBorder(), + pPage->GetUpperBorder(), pPage->GetLowerBorder(), + pPage->GetOrientation(), + pPage->GetPaperBin(), + pPage->IsBackgroundFullSize(), + rNewSize, + nLeft, nRight, + nUpper, nLower, + bScaleAll, + eOrientation, + nPaperBin, + bBackgroundFullSize)); + pUndoGroup->AddAction(pUndo); + } + + if (rNewSize.Width() > 0 || nLeft >= 0 || nRight >= 0 || nUpper >= 0 || nLower >= 0) + { + ::tools::Rectangle aNewBorderRect(nLeft, nUpper, nRight, nLower); + pPage->ScaleObjects(rNewSize, aNewBorderRect, bScaleAll); + + if (rNewSize.Width() > 0) + { + pPage->SetSize(rNewSize); + } + } + + if( nLeft >= 0 || nRight >= 0 || nUpper >= 0 || nLower >= 0 ) + { + pPage->SetBorder(nLeft, nUpper, nRight, nLower); + } + + pPage->SetOrientation(eOrientation); + pPage->SetPaperBin( nPaperBin ); + pPage->SetBackgroundFullSize( bBackgroundFullSize ); + + if ( ePageKind == PageKind::Standard ) + { + SdPage* pNotesPage = GetSdPage(i, PageKind::Notes); + pNotesPage->SetAutoLayout( pNotesPage->GetAutoLayout() ); + } + + pPage->SetAutoLayout( pPage->GetAutoLayout() ); + } +} + SdrModel* SdDrawDocument::AllocModel() const { return AllocSdDrawDocument(); diff --git a/sd/source/ui/view/viewshe2.cxx b/sd/source/ui/view/viewshe2.cxx index f20469071b72..6c1ad846131c 100644 --- a/sd/source/ui/view/viewshe2.cxx +++ b/sd/source/ui/view/viewshe2.cxx @@ -470,139 +470,65 @@ void ViewShell::SetPageSizeAndBorder(PageKind ePageKind, const Size& rNewSize, Orientation eOrientation, sal_uInt16 nPaperBin, bool bBackgroundFullSize) { - SdPage* pPage = nullptr; - SdUndoGroup* pUndoGroup = nullptr; - pUndoGroup = new SdUndoGroup(GetDoc()); - OUString aString(SdResId(STR_UNDO_CHANGE_PAGEFORMAT)); - pUndoGroup->SetComment(aString); - SfxViewShell* pViewShell = GetViewShell(); - OSL_ASSERT (pViewShell!=nullptr); - - sal_uInt16 i, nPageCnt = GetDoc()->GetMasterSdPageCount(ePageKind); - - Broadcast (ViewShellHint(ViewShellHint::HINT_PAGE_RESIZE_START)); + const sal_uInt16 nMasterPageCnt(GetDoc()->GetMasterSdPageCount(ePageKind)); + const sal_uInt16 nPageCnt(GetDoc()->GetSdPageCount(ePageKind)); - for (i = 0; i < nPageCnt; i++) + if(0 == nPageCnt && 0 == nMasterPageCnt) { - // first, handle all master pages - pPage = GetDoc()->GetMasterSdPage(i, ePageKind); - - SdUndoAction* pUndo = new SdPageFormatUndoAction(GetDoc(), pPage, - pPage->GetSize(), - pPage->GetLeftBorder(), pPage->GetRightBorder(), - pPage->GetUpperBorder(), pPage->GetLowerBorder(), - pPage->GetOrientation(), - pPage->GetPaperBin(), - pPage->IsBackgroundFullSize(), - rNewSize, - nLeft, nRight, - nUpper, nLower, - bScaleAll, - eOrientation, - nPaperBin, - bBackgroundFullSize); - pUndoGroup->AddAction(pUndo); - - if (rNewSize.Width() > 0 || - nLeft >= 0 || nRight >= 0 || nUpper >= 0 || nLower >= 0) - { - ::tools::Rectangle aNewBorderRect(nLeft, nUpper, nRight, nLower); - pPage->ScaleObjects(rNewSize, aNewBorderRect, bScaleAll); - - if (rNewSize.Width() > 0) - pPage->SetSize(rNewSize); - } - - if( nLeft >= 0 || nRight >= 0 || nUpper >= 0 || nLower >= 0 ) - { - pPage->SetBorder(nLeft, nUpper, nRight, nLower); - } - - pPage->SetOrientation(eOrientation); - pPage->SetPaperBin( nPaperBin ); - pPage->SetBackgroundFullSize( bBackgroundFullSize ); - - if ( ePageKind == PageKind::Standard ) - GetDoc()->GetMasterSdPage(i, PageKind::Notes)->CreateTitleAndLayout(); - - pPage->CreateTitleAndLayout(); + return; } - nPageCnt = GetDoc()->GetSdPageCount(ePageKind); - - for (i = 0; i < nPageCnt; i++) - { - // then, handle all pages - pPage = GetDoc()->GetSdPage(i, ePageKind); - - SdUndoAction* pUndo = new SdPageFormatUndoAction(GetDoc(), pPage, - pPage->GetSize(), - pPage->GetLeftBorder(), pPage->GetRightBorder(), - pPage->GetUpperBorder(), pPage->GetLowerBorder(), - pPage->GetOrientation(), - pPage->GetPaperBin(), - pPage->IsBackgroundFullSize(), - rNewSize, - nLeft, nRight, - nUpper, nLower, - bScaleAll, - eOrientation, - nPaperBin, - bBackgroundFullSize); - pUndoGroup->AddAction(pUndo); - - if (rNewSize.Width() > 0 || - nLeft >= 0 || nRight >= 0 || nUpper >= 0 || nLower >= 0) - { - ::tools::Rectangle aNewBorderRect(nLeft, nUpper, nRight, nLower); - pPage->ScaleObjects(rNewSize, aNewBorderRect, bScaleAll); - - if (rNewSize.Width() > 0) - pPage->SetSize(rNewSize); - } - - if( nLeft >= 0 || nRight >= 0 || nUpper >= 0 || nLower >= 0 ) - { - pPage->SetBorder(nLeft, nUpper, nRight, nLower); - } - - pPage->SetOrientation(eOrientation); - pPage->SetPaperBin( nPaperBin ); - pPage->SetBackgroundFullSize( bBackgroundFullSize ); - - if ( ePageKind == PageKind::Standard ) - { - SdPage* pNotesPage = GetDoc()->GetSdPage(i, PageKind::Notes); - pNotesPage->SetAutoLayout( pNotesPage->GetAutoLayout() ); - } + SdUndoGroup* pUndoGroup(new SdUndoGroup(GetDoc())); + pUndoGroup->SetComment(SdResId(STR_UNDO_CHANGE_PAGEFORMAT)); + Broadcast (ViewShellHint(ViewShellHint::HINT_PAGE_RESIZE_START)); - pPage->SetAutoLayout( pPage->GetAutoLayout() ); - } + // use Model-based method at SdDrawDocument + GetDoc()->AdaptPageSizeForAllPages( + rNewSize, + ePageKind, + pUndoGroup, + nLeft, + nRight, + nUpper, + nLower, + bScaleAll, + eOrientation, + nPaperBin, + bBackgroundFullSize); // adjust handout page to new format of the standard page - if( (ePageKind == PageKind::Standard) || (ePageKind == PageKind::Handout) ) + if(0 != nPageCnt && ((ePageKind == PageKind::Standard) || (ePageKind == PageKind::Handout))) + { GetDoc()->GetSdPage(0, PageKind::Handout)->CreateTitleAndLayout(true); + } // handed over undo group to undo manager - pViewShell->GetViewFrame()->GetObjectShell() - ->GetUndoManager()->AddUndoAction(pUndoGroup); + SfxViewShell* pViewShell(GetViewShell()); - long nWidth = pPage->GetSize().Width(); - long nHeight = pPage->GetSize().Height(); + if(nullptr != pViewShell) + { + pViewShell->GetViewFrame()->GetObjectShell()->GetUndoManager()->AddUndoAction(pUndoGroup); + } - Point aPageOrg(nWidth, nHeight / 2); - Size aViewSize(nWidth * 3, nHeight * 2); + // calculate View-Sizes + SdPage* pPage(0 != nPageCnt + ? GetDoc()->GetSdPage(0, ePageKind) + : GetDoc()->GetMasterSdPage(0, ePageKind)); + const long nWidth(pPage->GetSize().Width()); + const long nHeight(pPage->GetSize().Height()); + const Point aPageOrg(nWidth, nHeight / 2); + const Size aViewSize(nWidth * 3, nHeight * 2); + Point aVisAreaPos; + ::sd::View* pView(GetView()); + const Point aNewOrigin(pPage->GetLeftBorder(), pPage->GetUpperBorder()); InitWindows(aPageOrg, aViewSize, Point(-1, -1), true); - Point aVisAreaPos; - if ( GetDocSh()->GetCreateMode() == SfxObjectCreateMode::EMBEDDED ) { aVisAreaPos = GetDocSh()->GetVisArea(ASPECT_CONTENT).TopLeft(); } - ::sd::View* pView = GetView(); if (pView) { pView->SetWorkArea(::tools::Rectangle(Point() - aVisAreaPos - aPageOrg, aViewSize)); @@ -610,20 +536,19 @@ void ViewShell::SetPageSizeAndBorder(PageKind ePageKind, const Size& rNewSize, UpdateScrollBars(); - Point aNewOrigin(pPage->GetLeftBorder(), pPage->GetUpperBorder()); - if (pView) { pView->GetSdrPageView()->SetPageOrigin(aNewOrigin); } - pViewShell->GetViewFrame()->GetBindings().Invalidate(SID_RULER_NULL_OFFSET); - - // zoom onto (new) page size - pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_SIZE_PAGE, - SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + if(nullptr != pViewShell) + { + pViewShell->GetViewFrame()->GetBindings().Invalidate(SID_RULER_NULL_OFFSET); + // zoom onto (new) page size + pViewShell->GetViewFrame()->GetDispatcher()->Execute(SID_SIZE_PAGE, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD); + } - Broadcast (ViewShellHint(ViewShellHint::HINT_PAGE_RESIZE_END)); + Broadcast(ViewShellHint(ViewShellHint::HINT_PAGE_RESIZE_END)); } /** diff --git a/svx/source/svdraw/svdmodel.cxx b/svx/source/svdraw/svdmodel.cxx index 5be0dffeac55..1b17da722a86 100644 --- a/svx/source/svdraw/svdmodel.cxx +++ b/svx/source/svdraw/svdmodel.cxx @@ -1718,6 +1718,18 @@ void SdrModel::setUnoModel( const css::uno::Reference< css::uno::XInterface >& x mxUnoModel = xModel; } +void SdrModel::adaptSizeAndBorderForAllPages( + const Size& /*rNewSize*/, + long /*nLeft*/, + long /*nRight*/, + long /*nUpper*/, + long /*nLower*/) +{ + // base implementation does currently nothing. It may be added if needed, + // but we are on SdrModel level here, thus probably have not enough information + // to do this for higher-level (derived) Models (e.g. Draw/Impress) +} + uno::Reference< uno::XInterface > SdrModel::createUnoModel() { OSL_FAIL( "SdrModel::createUnoModel() - base implementation should not be called!" ); |