diff options
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!" ); |