tdf#108037 Reduce time and memory consumed exporting to PDF
by avoiding making multiple copies of the Primitive2D container
that we pass to TransformPrimitive2D.
Instead, make TransformPrimitive2D store its children using a
GroupPrimitive2D, which means we can share the GroupPrimitive2D
among all the TransformPrimitive2D instances we create.
Change-Id: I8a4398f9db6a6ab013ee24ad53836975fba6f3df
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162951
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx b/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx
index 8c50993..bc91586 100644
--- a/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/fillgraphicprimitive2d.cxx
@@ -70,11 +70,12 @@ namespace drawinglayer::primitive2d
rGraphic,
basegfx::B2DHomMatrix());
rtl::Reference<GroupPrimitive2D> xGroup = new GroupPrimitive2D(std::move(xSeq));
for(const auto &a : aMatrices)
{
rContainer.push_back(new TransformPrimitive2D(
getTransformation() * a,
Primitive2DContainer(xSeq)));
*xGroup));
}
}
else
diff --git a/drawinglayer/source/primitive2d/transformprimitive2d.cxx b/drawinglayer/source/primitive2d/transformprimitive2d.cxx
index 0442cd6..8c36fa9 100644
--- a/drawinglayer/source/primitive2d/transformprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/transformprimitive2d.cxx
@@ -19,6 +19,7 @@
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/Tools.hxx>
#include <utility>
@@ -30,18 +31,27 @@ namespace drawinglayer::primitive2d
TransformPrimitive2D::TransformPrimitive2D(
basegfx::B2DHomMatrix aTransformation,
Primitive2DContainer&& aChildren)
: GroupPrimitive2D(std::move(aChildren)),
maTransformation(std::move(aTransformation))
: maTransformation(std::move(aTransformation)),
mxChildren(new GroupPrimitive2D(std::move(aChildren)))
{
}
TransformPrimitive2D::TransformPrimitive2D(
basegfx::B2DHomMatrix aTransformation,
GroupPrimitive2D& rChildren)
: maTransformation(std::move(aTransformation)),
mxChildren(&rChildren)
{
}
bool TransformPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
if(GroupPrimitive2D::operator==(rPrimitive))
if(BasePrimitive2D::operator==(rPrimitive))
{
const TransformPrimitive2D& rCompare = static_cast< const TransformPrimitive2D& >(rPrimitive);
return (getTransformation() == rCompare.getTransformation());
return maTransformation == rCompare.maTransformation
&& arePrimitive2DReferencesEqual(mxChildren, rCompare.mxChildren);
}
return false;
diff --git a/include/drawinglayer/primitive2d/transformprimitive2d.hxx b/include/drawinglayer/primitive2d/transformprimitive2d.hxx
index 73e589b..8c3c22c 100644
--- a/include/drawinglayer/primitive2d/transformprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/transformprimitive2d.hxx
@@ -46,19 +46,24 @@ namespace drawinglayer::primitive2d
different, transformed states without the need to create those
thousand primitive contents.
*/
class DRAWINGLAYER_DLLPUBLIC TransformPrimitive2D final : public GroupPrimitive2D
class DRAWINGLAYER_DLLPUBLIC TransformPrimitive2D final : public BasePrimitive2D
{
private:
// the transformation to apply to the child geometry
basegfx::B2DHomMatrix maTransformation;
rtl::Reference<GroupPrimitive2D> mxChildren;
public:
/// constructor
TransformPrimitive2D(
basegfx::B2DHomMatrix aTransformation,
Primitive2DContainer&& rChildren);
TransformPrimitive2D(
basegfx::B2DHomMatrix aTransformation,
GroupPrimitive2D& rChildren);
/// data read access
const Primitive2DContainer& getChildren() const { return mxChildren->getChildren(); }
const basegfx::B2DHomMatrix& getTransformation() const { return maTransformation; }
/// compare operator
diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx
index d99e56b..13dff82 100644
--- a/svgio/qa/cppunit/SvgImportTest.cxx
+++ b/svgio/qa/cppunit/SvgImportTest.cxx
@@ -8,6 +8,7 @@
*/
#include <sal/config.h>
#include <sal/log.hxx>
#include <test/bootstrapfixture.hxx>
#include <test/xmltesttools.hxx>
@@ -83,12 +84,27 @@ namespace
{
bool arePrimitive2DSequencesEqual(const Primitive2DSequence& rA, const Primitive2DSequence& rB)
{
return std::equal(rA.begin(), rA.end(), rB.begin(), rB.end(),
auto rv = std::mismatch(rA.begin(), rA.end(), rB.begin(), rB.end(),
[](const css::uno::Reference<css::graphic::XPrimitive2D>& a,
const css::uno::Reference<css::graphic::XPrimitive2D>& b)
{
return drawinglayer::primitive2d::arePrimitive2DReferencesEqual(a, b);
});
if (rv.first == rA.end() && rv.second == rB.end())
return true;
if (rv.first == rA.end() || rv.second == rB.end())
{
SAL_WARN("svgio",
"first seq length == " << rA.size() <<
"second seq length == " << rB.size());
return false;
}
auto idx = std::distance(rA.begin(), rv.first);
SAL_WARN("svgio",
"first difference at index " << idx <<
" expected element " << typeid(*rA[idx]).name() <<
" but got element " << typeid(*rB[idx]).name());
return false;
}
}