diff options
-rw-r--r-- | drawinglayer/Library_drawinglayer.mk | 1 | ||||
-rw-r--r-- | drawinglayer/source/primitive2d/baseprimitive2d.cxx | 1 | ||||
-rwxr-xr-x | drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx | 40 | ||||
-rw-r--r-- | filter/Configuration_filter.mk | 3 | ||||
-rwxr-xr-x | filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics_Draw.xcu | 30 | ||||
-rw-r--r-- | filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu | 2 | ||||
-rwxr-xr-x | filter/source/config/fragments/types/svg_Scalable_Vector_Graphics_Draw.xcu | 29 | ||||
-rw-r--r-- | filter/source/svg/svgfilter.cxx | 260 | ||||
-rw-r--r-- | filter/source/svg/svgfilter.hxx | 3 | ||||
-rw-r--r-- | include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx | 1 | ||||
-rwxr-xr-x | include/drawinglayer/primitive2d/pagehierarchyprimitive2d.hxx | 52 | ||||
-rw-r--r-- | solenv/clang-format/blacklist | 2 | ||||
-rw-r--r-- | svgio/source/svgreader/svgstyleattributes.cxx | 72 | ||||
-rw-r--r-- | svgio/source/svgreader/svgsvgnode.cxx | 49 |
14 files changed, 463 insertions, 82 deletions
diff --git a/drawinglayer/Library_drawinglayer.mk b/drawinglayer/Library_drawinglayer.mk index 91c137d56c29..26b6a9c37ba4 100644 --- a/drawinglayer/Library_drawinglayer.mk +++ b/drawinglayer/Library_drawinglayer.mk @@ -95,6 +95,7 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\ drawinglayer/source/primitive2d/metafileprimitive2d \ drawinglayer/source/primitive2d/modifiedcolorprimitive2d \ drawinglayer/source/primitive2d/objectinfoprimitive2d \ + drawinglayer/source/primitive2d/pagehierarchyprimitive2d \ drawinglayer/source/primitive2d/pagepreviewprimitive2d \ drawinglayer/source/primitive2d/patternfillprimitive2d \ drawinglayer/source/primitive2d/pointarrayprimitive2d \ diff --git a/drawinglayer/source/primitive2d/baseprimitive2d.cxx b/drawinglayer/source/primitive2d/baseprimitive2d.cxx index cd45da11bae5..d9fac66c63dd 100644 --- a/drawinglayer/source/primitive2d/baseprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/baseprimitive2d.cxx @@ -367,6 +367,7 @@ namespace drawinglayer case PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D: return OUString("PATTERNFILL"); case PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D: return OUString("OBJECTINFO"); case PRIMITIVE2D_ID_POLYPOLYGONSELECTIONPRIMITIVE2D: return OUString("POLYPOLYGONSELECTION"); + case PRIMITIVE2D_ID_PAGEHIERARCHYPRIMITIVE2D: return OUString("PAGEHIERARCHY"); default: return OUString::number((nId >> 16) & 0xFF) + "|" + OUString::number(nId & 0xFF); } } diff --git a/drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx b/drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx new file mode 100755 index 000000000000..19225b01e9a6 --- /dev/null +++ b/drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx @@ -0,0 +1,40 @@ +/* -*- 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 <drawinglayer/primitive2d/pagehierarchyprimitive2d.hxx> +#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> + +using namespace com::sun::star; + +namespace drawinglayer +{ + namespace primitive2d + { + PageHierarchyPrimitive2D::PageHierarchyPrimitive2D(const Primitive2DContainer& rChildren) + : GroupPrimitive2D(rChildren) + { + } + + // provide unique ID + ImplPrimitive2DIDBlock(PageHierarchyPrimitive2D, PRIMITIVE2D_ID_PAGEHIERARCHYPRIMITIVE2D) + + } // end of namespace primitive2d +} // end of namespace drawinglayer + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/Configuration_filter.mk b/filter/Configuration_filter.mk index 35d7620f6f70..d7a6322e5564 100644 --- a/filter/Configuration_filter.mk +++ b/filter/Configuration_filter.mk @@ -695,6 +695,7 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_drawgraphics_typ ppm_Portable_Pixelmap \ psd_Adobe_Photoshop \ ras_Sun_Rasterfile \ + svg_Scalable_Vector_Graphics_Draw \ svg_Scalable_Vector_Graphics \ svm_StarView_Metafile \ tga_Truevision_TARGA \ @@ -721,6 +722,7 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_drawgraphics_f PPM___Portable_Pixelmap \ PSD___Adobe_Photoshop \ RAS___Sun_Rasterfile \ + SVG___Scalable_Vector_Graphics_Draw \ SVG___Scalable_Vector_Graphics \ SVM___StarView_Metafile \ TGA___Truevision_TARGA \ @@ -761,6 +763,7 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_impressgraphics_ png_Portable_Network_Graphic \ ppm_Portable_Pixelmap \ ras_Sun_Rasterfile \ + svg_Scalable_Vector_Graphics_Draw \ svg_Scalable_Vector_Graphics \ svm_StarView_Metafile \ tif_Tag_Image_File \ diff --git a/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics_Draw.xcu b/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics_Draw.xcu new file mode 100755 index 000000000000..eb98d7f940e8 --- /dev/null +++ b/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics_Draw.xcu @@ -0,0 +1,30 @@ +<!-- + * 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 . +--> + <node oor:name="SVG - Scalable Vector Graphics Draw" oor:op="replace"> + <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop> + <prop oor:name="UIComponent"/> + <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop> + <prop oor:name="UserData"><value></value></prop> + <prop oor:name="UIName"> + <value xml:lang="en-US">SVG - Scalable Vector Graphics Draw</value> + </prop> + <prop oor:name="FileFormatVersion"><value>0</value></prop> + <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics_Draw</value></prop> + <prop oor:name="TemplateName"/> + <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop> + </node> diff --git a/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu b/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu index f811f9bb9c9e..a2015a536873 100644 --- a/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu +++ b/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu @@ -20,7 +20,7 @@ <prop oor:name="URLPattern"/> <prop oor:name="Extensions"><value>svg svgz</value></prop> <prop oor:name="MediaType"><value>image/svg+xml</value></prop> - <prop oor:name="Preferred"><value>true</value></prop> + <prop oor:name="Preferred"><value>false</value></prop> <prop oor:name="PreferredFilter"><value>SVG - Scalable Vector Graphics</value></prop> <prop oor:name="UIName"> <value>SVG - Scalable Vector Graphics</value> diff --git a/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics_Draw.xcu b/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics_Draw.xcu new file mode 100755 index 000000000000..4b3b9cab58b1 --- /dev/null +++ b/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics_Draw.xcu @@ -0,0 +1,29 @@ +<!-- + * 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 . +--> + <node oor:name="svg_Scalable_Vector_Graphics_Draw" oor:op="replace" > + <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop> + <prop oor:name="URLPattern"/> + <prop oor:name="Extensions"><value>svg svgz</value></prop> + <prop oor:name="MediaType"><value>image/svg+xml</value></prop> + <prop oor:name="Preferred"><value>true</value></prop> + <prop oor:name="PreferredFilter"><value>SVG - Scalable Vector Graphics Draw</value></prop> + <prop oor:name="UIName"> + <value>SVG - Scalable Vector Graphics Draw</value> + </prop> + <prop oor:name="ClipboardFormat"/> + </node> diff --git a/filter/source/svg/svgfilter.cxx b/filter/source/svg/svgfilter.cxx index 1ec09f65ab05..ddc81b4f89e5 100644 --- a/filter/source/svg/svgfilter.cxx +++ b/filter/source/svg/svgfilter.cxx @@ -64,6 +64,7 @@ using namespace ::com::sun::star; namespace { + static const char constFilterNameDraw[] = "svg_Scalable_Vector_Graphics_Draw"; static const char constFilterName[] = "svg_Scalable_Vector_Graphics"; } @@ -254,19 +255,22 @@ sal_Bool SAL_CALL SVGFilter::filter( const Sequence< PropertyValue >& rDescripto // pTargetSdrPage->SetBorder(...) and // pTargetSdrPage->SetSize(...), // but ::adaptSizeAndBorderForAllPages + // Do use original Size and borders to get as close to original + // as possible for better turn-arounds. pTargetSdrPage->getSdrModelFromSdrPage().adaptSizeAndBorderForAllPages( Size( - aGraphicSize.Width() + nAllBorder + nAllBorder, - aGraphicSize.Height() + nAllBorder + nAllBorder), + aGraphicSize.Width(), + aGraphicSize.Height()), nAllBorder, nAllBorder, nAllBorder, nAllBorder); - // set pos/size at SdrGraphicObj - add offset to PageBorder + // set pos/size at SdrGraphicObj - use zero position for + // better turn-around results aNewSdrGrafObj->SetSnapRect( tools::Rectangle( - Point(nAllBorder, nAllBorder), + Point(0, 0), aGraphicSize)); // insert to page (owner change of SdrGrafObj) @@ -472,86 +476,220 @@ void SAL_CALL SVGFilter::setTargetDocument( const Reference< XComponent >& xDoc mxDstDoc = xDoc; } -bool SVGFilter::isStreamGZip(const uno::Reference<io::XInputStream>& xInput) +// There is already another SVG-Type_Detector, see +// vcl/source/filter/graphicfilter.cxx ("DOCTYPE svg"), +// but since these start from different preconditions it is not +// easy to unify these. For now, use this local helper. +class SVGFileInfo { - uno::Reference<io::XSeekable> xSeek(xInput, uno::UNO_QUERY); - if(xSeek.is()) - xSeek->seek(0); - - uno::Sequence<sal_Int8> aBuffer(2); - const sal_uInt64 nBytes = xInput->readBytes(aBuffer, 2); - if (nBytes == 2) +private: + const uno::Reference<io::XInputStream>& mxInput; + uno::Sequence< sal_Int8 > mnFirstBytes; + sal_Int32 mnFirstBytesSize; + sal_uInt64 mnFirstRead; + bool mbProcessed; + bool mbIsSVG; + + bool impCheckForMagic( + const sal_Int8* pMagic, + const sal_Int32 nMagicSize) { - const sal_Int8* pBuffer = aBuffer.getConstArray(); - if (pBuffer[0] == 0x1F && static_cast<sal_uInt8>(pBuffer[1]) == 0x8B) - return true; + const sal_Int8* pBuffer(mnFirstBytes.getConstArray()); + return std::search( + pBuffer, + pBuffer + mnFirstRead, + pMagic, + pMagic + nMagicSize) != pBuffer + mnFirstRead; } - return false; -} -bool SVGFilter::isStreamSvg(const uno::Reference<io::XInputStream>& xInput) -{ - uno::Reference<io::XSeekable> xSeek(xInput, uno::UNO_QUERY); - if(xSeek.is()) - xSeek->seek(0); + void impEnsureProcessed() + { + if(mbProcessed) + { + return; + } - const sal_Int32 nLookAhead = 1024; - uno::Sequence<sal_Int8> aBuffer(nLookAhead); - const sal_uInt64 nBytes = xInput->readBytes(aBuffer, nLookAhead); - const sal_Int8* pBuffer = aBuffer.getConstArray(); + mbProcessed = true; - sal_Int8 aMagic1[] = {'<', 's', 'v', 'g'}; - sal_Int32 const aMagic1Size = SAL_N_ELEMENTS(aMagic1); + if(!mxInput.is()) + { + return; + } - if (std::search(pBuffer, pBuffer + nBytes, aMagic1, aMagic1 + aMagic1Size) != pBuffer + nBytes ) - return true; + if(0 == mnFirstBytesSize) + { + return; + } - sal_Int8 aMagic2[] = {'D', 'O', 'C', 'T', 'Y', 'P', 'E', ' ', 's', 'v', 'g'}; - sal_Int32 const aMagic2Size = SAL_N_ELEMENTS(aMagic2); + mnFirstBytes.realloc(mnFirstBytesSize); - return std::search(pBuffer, pBuffer + nBytes, aMagic2, aMagic2 + aMagic2Size) != pBuffer + nBytes; -} + if(mnFirstBytesSize != mnFirstBytes.getLength()) + { + return; + } -OUString SAL_CALL SVGFilter::detect(Sequence<PropertyValue>& rDescriptor) -{ - utl::MediaDescriptor aMediaDescriptor(rDescriptor); - uno::Reference<io::XInputStream> xInput(aMediaDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()], UNO_QUERY); + std::unique_ptr< SvStream > aStream(utl::UcbStreamHelper::CreateStream(mxInput, true)); - if (!xInput.is()) - return OUString(); + if(!aStream.get()) + { + return; + } + + const sal_uLong nStreamPos(aStream->Tell()); + aStream->Seek(STREAM_SEEK_TO_END); + const sal_uLong nStreamLen(aStream->Tell() - nStreamPos); + aStream->Seek(nStreamPos); - try { - if (isStreamGZip(xInput)) + if(aStream->GetError()) { - std::unique_ptr<SvStream> aStream(utl::UcbStreamHelper::CreateStream(xInput, true )); - if(!aStream.get()) - return OUString(); + return; + } + + mnFirstRead = aStream->ReadBytes( + &mnFirstBytes[0], + std::min(nStreamLen, sal_uLong(mnFirstBytesSize))); - SvStream* pMemoryStream = new SvMemoryStream; - uno::Reference<io::XSeekable> xSeek(xInput, uno::UNO_QUERY); - if (!xSeek.is()) - return OUString(); - xSeek->seek(0); + if(aStream->GetError()) + { + return; + } + // check if it is gzipped -> svgz + if(mnFirstBytes[0] == 0x1F && static_cast<sal_uInt8>(mnFirstBytes[1]) == 0x8B) + { ZCodec aCodec; - aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, false, true); - aCodec.Decompress(*aStream.get(), *pMemoryStream); + + aCodec.BeginCompression( + ZCODEC_DEFAULT_COMPRESSION, + false, + true); + mnFirstRead = aCodec.Read( + *aStream, + reinterpret_cast< sal_uInt8* >(mnFirstBytes.getArray()), + mnFirstBytesSize); aCodec.EndCompression(); - pMemoryStream->Seek(STREAM_SEEK_TO_BEGIN); - uno::Reference<io::XInputStream> xDecompressedInput(new utl::OSeekableInputStreamWrapper(pMemoryStream, true)); + } + + if(!mbIsSVG) + { + const sal_Int8 aMagic[] = {'<', 's', 'v', 'g'}; + const sal_Int32 nMagicSize(SAL_N_ELEMENTS(aMagic)); - if (xDecompressedInput.is() && isStreamSvg(xDecompressedInput)) - return OUString(constFilterName); + mbIsSVG = impCheckForMagic(aMagic, nMagicSize); } - else + + if(!mbIsSVG) { - if (isStreamSvg(xInput)) - return OUString(constFilterName); + const sal_Int8 aMagic[] = {'D', 'O', 'C', 'T', 'Y', 'P', 'E', ' ', 's', 'v', 'g'}; + const sal_Int32 nMagicSize(SAL_N_ELEMENTS(aMagic)); + + mbIsSVG = impCheckForMagic(aMagic, nMagicSize); } - } catch (css::io::IOException & e) { + + return; + } + +public: + SVGFileInfo( + const uno::Reference<io::XInputStream>& xInput, + sal_Int32 nFirstBytesSize = 4096) + : mxInput(xInput), + mnFirstBytes(), + mnFirstBytesSize(nFirstBytesSize), + mnFirstRead(0), + mbProcessed(false), + mbIsSVG(false) + { + // For the default buffer size: Use not too big + // (not more than 16K), but also not too small + // (not less than 1/2K), see comments at + // ImpPeekGraphicFormat, SVG section. + // I remember these cases and it *can* happen + // that SVGs have quite massive comments in their + // headings (!) + // Limit to plausible sizes, also for security reasons + mnFirstBytesSize = std::min(sal_Int32(512), mnFirstBytesSize); + mnFirstBytesSize = std::max(sal_Int32(16384), mnFirstBytesSize); + } + + bool isSVG() + { + impEnsureProcessed(); + + return mbIsSVG; + } + + bool isOwnFormat() + { + impEnsureProcessed(); + + if(mbIsSVG) + { + // xmlns:ooo + const sal_Int8 aMagic[] = {'x', 'm', 'l', 'n', 's', ':', 'o', 'o', 'o'}; + const sal_Int32 nMagicSize(SAL_N_ELEMENTS(aMagic)); + + return impCheckForMagic(aMagic, nMagicSize); + } + + return false; + } + + bool isImpress() + { + impEnsureProcessed(); + + if(mbIsSVG) + { + // ooo:meta_slides + const sal_Int8 aMagic[] = {'o', 'o', 'o', ':', 'm', 'e', 't', 'a', '_', 's', 'l', 'i', 'd', 'e', 's'}; + const sal_Int32 nMagicSize(SAL_N_ELEMENTS(aMagic)); + + return impCheckForMagic(aMagic, nMagicSize); + } + + return false; + } +}; + +OUString SAL_CALL SVGFilter::detect(Sequence<PropertyValue>& rDescriptor) +{ + utl::MediaDescriptor aMediaDescriptor(rDescriptor); + uno::Reference<io::XInputStream> xInput(aMediaDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()], UNO_QUERY); + OUString aRetval; + + if (!xInput.is()) + { + return aRetval; + } + + try + { + SVGFileInfo aSVGFileInfo(xInput, 2048); + + if(aSVGFileInfo.isSVG()) + { + // We have SVG - set default document format to Draw + aRetval = OUString(constFilterNameDraw); + + if(aSVGFileInfo.isOwnFormat()) + { + // it's a file that was written/exported by LO + if(aSVGFileInfo.isImpress()) + { + // it was written by Impress export. Set document + // format for import to Impress + aRetval = OUString(constFilterName); + } + } + } + } + catch (css::io::IOException & e) + { SAL_WARN("filter.svg", "caught " << e); } - return OUString(); + + return aRetval; } #define SVG_FILTER_IMPL_NAME "com.sun.star.comp.Draw.SVGFilter" diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx index 5f117c3310ee..1b5254e25469 100644 --- a/filter/source/svg/svgfilter.hxx +++ b/filter/source/svg/svgfilter.hxx @@ -266,9 +266,6 @@ private: const Reference< XPropertySetInfo > & rxPropSetInfo ); DECL_LINK( CalcFieldHdl, EditFieldInfo*, void ); - static bool isStreamGZip(const css::uno::Reference<css::io::XInputStream>& xInput); - static bool isStreamSvg(const css::uno::Reference<css::io::XInputStream>& xInput); - protected: // XFilter diff --git a/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx b/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx index 7dcc2455effb..98d009deda6b 100644 --- a/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx +++ b/include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx @@ -102,6 +102,7 @@ #define PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 67) #define PRIMITIVE2D_ID_OBJECTINFOPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 68) #define PRIMITIVE2D_ID_POLYPOLYGONSELECTIONPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 69) +#define PRIMITIVE2D_ID_PAGEHIERARCHYPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_DRAWINGLAYER| 70) // When you add a new primitive, please update the drawinglayer::primitive2d::idToString() function // in drawinglayer/source/primitive2d/baseprimitive2d.cxx. diff --git a/include/drawinglayer/primitive2d/pagehierarchyprimitive2d.hxx b/include/drawinglayer/primitive2d/pagehierarchyprimitive2d.hxx new file mode 100755 index 000000000000..e2c9b1d603ab --- /dev/null +++ b/include/drawinglayer/primitive2d/pagehierarchyprimitive2d.hxx @@ -0,0 +1,52 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_PAGEHIERARCHYPRIMITIVE2D_HXX +#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_PAGEHIERARCHYPRIMITIVE2D_HXX + +#include <drawinglayer/drawinglayerdllapi.h> + +#include <drawinglayer/primitive2d/groupprimitive2d.hxx> +#include <rtl/ustring.hxx> + + +namespace drawinglayer +{ + namespace primitive2d + { + /** PageHierarchyPrimitive2D class + + This primitive encapsulates text lines. + */ + class DRAWINGLAYER_DLLPUBLIC PageHierarchyPrimitive2D : public GroupPrimitive2D + { + private: + public: + /// constructor + explicit PageHierarchyPrimitive2D(const Primitive2DContainer& rChildren); + + /// provide unique ID + DeclPrimitive2DIDBlock() + }; + } // end of namespace primitive2d +} // end of namespace drawinglayer + +#endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_PAGEHIERARCHYPRIMITIVE2D_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/solenv/clang-format/blacklist b/solenv/clang-format/blacklist index 79c639c82cb9..a0e79ad167dc 100644 --- a/solenv/clang-format/blacklist +++ b/solenv/clang-format/blacklist @@ -3941,6 +3941,7 @@ drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx drawinglayer/source/primitive2d/texteffectprimitive2d.cxx drawinglayer/source/primitive2d/textenumsprimitive2d.cxx drawinglayer/source/primitive2d/texthierarchyprimitive2d.cxx +drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx drawinglayer/source/primitive2d/textlayoutdevice.cxx drawinglayer/source/primitive2d/textlineprimitive2d.cxx drawinglayer/source/primitive2d/textprimitive2d.cxx @@ -6281,6 +6282,7 @@ include/drawinglayer/primitive2d/textdecoratedprimitive2d.hxx include/drawinglayer/primitive2d/texteffectprimitive2d.hxx include/drawinglayer/primitive2d/textenumsprimitive2d.hxx include/drawinglayer/primitive2d/texthierarchyprimitive2d.hxx +include/drawinglayer/primitive2d/pagehierarchyprimitive2d.hxx include/drawinglayer/primitive2d/textlayoutdevice.hxx include/drawinglayer/primitive2d/textlineprimitive2d.hxx include/drawinglayer/primitive2d/textprimitive2d.hxx diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx index f1bc7c737aae..2d96cfb9d022 100644 --- a/svgio/source/svgreader/svgstyleattributes.cxx +++ b/svgio/source/svgreader/svgstyleattributes.cxx @@ -38,6 +38,7 @@ #include <drawinglayer/primitive2d/patternfillprimitive2d.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> #include <drawinglayer/primitive2d/maskprimitive2d.hxx> +#include <drawinglayer/primitive2d/pagehierarchyprimitive2d.hxx> namespace svgio { @@ -1196,13 +1197,48 @@ namespace svgio // #i124852# transform may be needed when userSpaceOnUse pMask->apply(aSource, pTransform); } + } + + // This is part of the SVG import of self-written SVGs from + // Draw/Impress containing multiple Slides/Pages. To be able + // to later 'break' these to multiple Pages if wanted, embed + // each Page-Content in a identifiable Primitive Grouping + // Object. + // This is the case when the current Node is a GroupNode, has + // class="Page" set, has a parent that also is a GroupNode + // at which class="Slide" is set. + // Multiple Slides/Pages are possible for Draw and Impress. + if(SVGTokenG == mrOwner.getType() && mrOwner.getClass()) + { + const OUString aOwnerClass(*mrOwner.getClass()); - if(!aSource.empty()) // test again, applied mask may have lead to empty geometry + if("Page" == aOwnerClass) { - // append to current target - rTarget.append(aSource); + const SvgNode* pParent(mrOwner.getParent()); + + if(nullptr != pParent && SVGTokenG == pParent->getType() && pParent->getClass()) + { + const OUString aParentClass(*pParent->getClass()); + + if("Slide" == aParentClass) + { + // embed to grouping primitive to identify the + // Slide/Page information + const drawinglayer::primitive2d::Primitive2DReference xRef( + new drawinglayer::primitive2d::PageHierarchyPrimitive2D( + aSource)); + + aSource = drawinglayer::primitive2d::Primitive2DContainer { xRef }; + } + } } } + + if(!aSource.empty()) // test again, applied mask may have lead to empty geometry + { + // append to current target + rTarget.append(aSource); + } } } @@ -2216,6 +2252,36 @@ namespace svgio return Visibility_visible; } + // Visibility correction/exception for self-exported SVGs: + // When Impress exports single or multi-page SVGs, it puts the + // single slides into <g visibility="hidden">. Not sure why + // whis happens, but this leads (correctly) to empty imported + // Graphics. + // Thus, if Visibility_hidden is active and owner is a SVGTokenG + // and it's parent is also a SVGTokenG and it has a Class 'SlideGroup' + // set, check if we are an Impress export. + // We are an Impress export if an SVG-Node titled 'ooo:meta_slides' + // exists. + // All togehter gives: + if(Visibility_hidden == maVisibility + && SVGTokenG == mrOwner.getType() + && nullptr != mrOwner.getDocument().findSvgNodeById("ooo:meta_slides")) + { + const SvgNode* pParent(mrOwner.getParent()); + + if(nullptr != pParent && SVGTokenG == pParent->getType() && pParent->getClass()) + { + const OUString aClass(*pParent->getClass()); + + if("SlideGroup" == aClass) + { + // if we detect this exception, + // ovverride Visibility_hidden -> Visibility_visible + return Visibility_visible; + } + } + } + return maVisibility; } diff --git a/svgio/source/svgreader/svgsvgnode.cxx b/svgio/source/svgreader/svgsvgnode.cxx index 40dfaca1a402..524e6d360030 100644 --- a/svgio/source/svgreader/svgsvgnode.cxx +++ b/svgio/source/svgreader/svgsvgnode.cxx @@ -26,6 +26,7 @@ #include <basegfx/matrix/b2dhommatrixtools.hxx> #include <drawinglayer/primitive2d/polygonprimitive2d.hxx> #include <drawinglayer/primitive2d/hiddengeometryprimitive2d.hxx> +#include <svgdocument.hxx> namespace svgio { @@ -670,21 +671,41 @@ namespace svgio if(!aSequence.empty()) { - // embed in transform primitive to scale to 1/100th mm - // where 1 inch == 25.4 mm to get from Svg coordinates (px) to - // drawinglayer coordinates - const double fScaleTo100thmm(25.4 * 100.0 / F_SVG_PIXEL_PER_INCH); - const basegfx::B2DHomMatrix aTransform( - basegfx::utils::createScaleB2DHomMatrix( - fScaleTo100thmm, - fScaleTo100thmm)); - - const drawinglayer::primitive2d::Primitive2DReference xTransform( - new drawinglayer::primitive2d::TransformPrimitive2D( - aTransform, - aSequence)); + // Another correction: + // If no Width/Height is set (usually done in + // <svg ... width="215.9mm" height="279.4mm" >) which + // is the case for own-Impress-exports, assume that + // the Units are alrteady 100ThMM. + // Maybe only for own-Impress-exports, thus may need to be + // &&ed with getDocument().findSvgNodeById("ooo:meta_slides"), + // but does not need to be. + bool bEmbedInFinalTransformPxTo100ThMM(true); + + if(getDocument().findSvgNodeById("ooo:meta_slides") + && !getWidth().isSet() + && !getHeight().isSet()) + { + bEmbedInFinalTransformPxTo100ThMM = false; + } + + if(bEmbedInFinalTransformPxTo100ThMM) + { + // embed in transform primitive to scale to 1/100th mm + // where 1 inch == 25.4 mm to get from Svg coordinates (px) to + // drawinglayer coordinates + const double fScaleTo100thmm(25.4 * 100.0 / F_SVG_PIXEL_PER_INCH); + const basegfx::B2DHomMatrix aTransform( + basegfx::utils::createScaleB2DHomMatrix( + fScaleTo100thmm, + fScaleTo100thmm)); + + const drawinglayer::primitive2d::Primitive2DReference xTransform( + new drawinglayer::primitive2d::TransformPrimitive2D( + aTransform, + aSequence)); - aSequence = drawinglayer::primitive2d::Primitive2DContainer { xTransform }; + aSequence = drawinglayer::primitive2d::Primitive2DContainer { xTransform }; + } // append to result rTarget.append(aSequence); |