[Libreoffice-commits] core.git: Branch 'libreoffice-6-1' - drawinglayer/Library_drawinglayer.mk drawinglayer/source filter/Configuration_filter.mk filter/source include/drawinglayer solenv/clang-format svgio/source

Armin Le Grand Armin.Le.Grand at cib.de
Thu Jun 14 16:46:22 UTC 2018


 drawinglayer/Library_drawinglayer.mk                                           |    1 
 drawinglayer/source/primitive2d/baseprimitive2d.cxx                            |    1 
 drawinglayer/source/primitive2d/pagehierarchyprimitive2d.cxx                   |   40 +
 filter/Configuration_filter.mk                                                 |    3 
 filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics_Draw.xcu |   30 +
 filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu          |    2 
 filter/source/config/fragments/types/svg_Scalable_Vector_Graphics_Draw.xcu     |   29 +
 filter/source/svg/svgfilter.cxx                                                |  260 +++++++---
 filter/source/svg/svgfilter.hxx                                                |    3 
 include/drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx             |    1 
 include/drawinglayer/primitive2d/pagehierarchyprimitive2d.hxx                  |   52 ++
 solenv/clang-format/blacklist                                                  |    2 
 svgio/source/svgreader/svgstyleattributes.cxx                                  |   72 ++
 svgio/source/svgreader/svgsvgnode.cxx                                          |   49 +
 14 files changed, 463 insertions(+), 82 deletions(-)

New commits:
commit 8383bdc2aed96fc7905c20cc5de4ff64641e7949
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Thu Jun 7 09:44:02 2018 +0200

    Replace SVGFilter using SVGIO
    
    Next step is to put more logic into the decision
    if Draw or Impress should be loaded - if we have a
    self-exported Impress, import as Impress, else
    (including all not-self-created SVG Graphics) import
    to Draw.
    To do this it is necessary to be able to import to
    different document formats at all. To do this, add
    an internal filter type to the filter mechanism
    (types/registration/...) and decide in the SVG
    XExtendedFilterDetection::detect from SVGFilter
    which one to use.
    Added tooling for SVG detection and more, see
    SVGFileInfo. This allows to detect for SVG, but
    also if the creator was LO and if it was Draw or
    Impress. The document format/filter is choosen
    accordingly.
    Corrected the error with <g visibility="hidden">
    Slides inisde <g class="SlideGroup"> for import
    of self-exported Impress documents. No idea why
    this was written that way, but needs to be fixed
    to get a visible content at all.
    Also adapted the final mapping from pt to 100thmm
    in SvgSvgNode::decomposeSvgNode. Unfortunately
    (and also for unknown reasons) the self-exported
    Impress does not write svg:width/height values,
    thus the adaption from assumed svg-units (px) to
    100thmm has to be skipped.
    Have identified the place in svgio where I can
    embed Pages/Slides to a helper-Primitive to later
    be able to 'break' such GraphicObjects to multiple
    Pages/Slides. I have added a Primitive called
    PageHierarchyPrimitive2D for this purpose.
    
    Change-Id: I38bfef6e7b16479a025fc754e38b4e21a006ad38
    Reviewed-on: https://gerrit.libreoffice.org/55434
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Armin Le Grand <Armin.Le.Grand at cib.de>
    (cherry picked from commit 3087011e2eb810866276e270a6fc61a7e0998fec)
    Reviewed-on: https://gerrit.libreoffice.org/55786
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

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 7dcd63136243..3c7af57a2af8 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);


More information about the Libreoffice-commits mailing list