[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-5-2+backports' - include/svx svx/Library_svxcore.mk svx/source sw/source
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Wed Oct 24 18:58:17 UTC 2018
include/svx/framelink.hxx | 109 -
include/svx/framelinkarray.hxx | 5
include/svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx | 119 ++
include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx | 1
svx/Library_svxcore.mk | 1
svx/source/dialog/framelink.cxx | 467 --------
svx/source/dialog/framelinkarray.cxx | 260 +---
svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx | 768 ++++++++++++++
sw/source/core/layout/paintfrm.cxx | 194 +--
9 files changed, 1078 insertions(+), 846 deletions(-)
New commits:
commit 1b9bc3c3f6f3fb31802be37592fcf4153d3d420d
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
AuthorDate: Mon Oct 22 10:33:03 2018 +0200
Commit: Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Oct 24 20:57:51 2018 +0200
Reorganize FrameBorderPrimitive creation
Step1: Basic concept, move stuff to svx and new
SdrFrameBorderPrimitive2D
Step2: Adapt all creators/usages to use
SdrFrameBorderData/SdrFrameBorderPrimitive2D,
check functionality
Step3: Re-implement mergre of BorderLinePrimitive2D
during decomposition of SdrFrameBorderPrimitive2D
to keep the number of primitives low from the start,
make merge optional (not urgently needed)
Step4: Migrate and isolate all helper methods
and classes involved in geometry creation of border
lines to the implementation (.cxx) of the new
primitive
Change-Id: I840b6765439bd995f2c57ef36315427b1f0f3e21
Reviewed-on: https://gerrit.libreoffice.org/62247
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand at cib.de>
Reviewed-on: https://gerrit.libreoffice.org/62309
Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx
index 65f1920fd093..5861b9eb58f2 100644
--- a/include/svx/framelink.hxx
+++ b/include/svx/framelink.hxx
@@ -201,115 +201,6 @@ public:
inline bool operator>( const Style& rL, const Style& rR ) { return rR.operator<(rL); }
-// Drawing functions
-class SAL_WARN_UNUSED SVX_DLLPUBLIC StyleVectorCombination
-{
-private:
- struct OffsetAndHalfWidthAndColor
- {
- double mfOffset;
- double mfHalfWidth;
- Color maColor;
-
- OffsetAndHalfWidthAndColor(double offset, double halfWidth, Color color) :
- mfOffset(offset),
- mfHalfWidth(halfWidth),
- maColor(color)
- {}
- };
-
- double mfRefModeOffset;
- basegfx::B2DVector maB2DVector;
- double mfAngle;
- std::vector< OffsetAndHalfWidthAndColor > maOffsets;
-
-public:
- StyleVectorCombination(
- const Style& rStyle,
- const basegfx::B2DVector& rB2DVector,
- const double fAngle,
- bool bMirrored,
- const Color* pForceColor = nullptr);
-
- double getRefModeOffset() const { return mfRefModeOffset; }
- const basegfx::B2DVector& getB2DVector() const { return maB2DVector; }
- double getAngle() const { return mfAngle; }
- bool empty() const { return maOffsets.empty(); }
- size_t size() const { return maOffsets.size(); }
- bool operator<( const StyleVectorCombination& rOther) const { return mfAngle < rOther.mfAngle; }
-
- void getColorAndOffsetAndHalfWidth(size_t nIndex, Color& rColor, double& rfOffset, double& rfHalfWidth) const;
-};
-
-class SAL_WARN_UNUSED SVX_DLLPUBLIC StyleVectorTable
-{
-private:
- std::vector< StyleVectorCombination > maEntries;
-
-public:
- StyleVectorTable()
- : maEntries()
- {
- }
-
- void add(
- const Style& rStyle,
- const basegfx::B2DVector& rMyVector,
- const basegfx::B2DVector& rOtherVector,
- bool bMirrored);
-
- void sort();
-
- bool empty() const { return maEntries.empty(); }
- size_t size() const { return maEntries.size(); }
- const std::vector< StyleVectorCombination >& getEntries() const{ return maEntries; }
-};
-
-/**
- * Helper method to create the correct drawinglayer::primitive2d::BorderLinePrimitive2D
- * for the given data, especially the correct drawinglayer::primitive2d::BorderLine entries
- * including the correctly solved/created LineStartEnd extends
- *
- * rTarget : Here the evtl. created BorderLinePrimitive2D will be appended
- * rOrigin : StartPoint of the Borderline
- * rX : Vector of the Borderline
- * rBorder : svx::frame::Style of the of the Borderline
- * rStartStyleVectorTable : All other Borderlines which have to be taken into account because
- * they have the same StartPoint as the current Borderline. These will be used to calculate
- * the correct LineStartEnd extends tor the BorderLinePrimitive2D. The definition should be
- * built up using svx::frame::StyleVectorTable and StyleVectorTable::add and includes:
- * rStyle : the svx::frame::Style of one other BorderLine
- * rMyVector : the Vector of the *new* to-be-defined BorderLine, identical to rX
- * rOtherVector: the Vector of one other BorderLine (may be, but does not need to be normalized),
- * always *pointing away* from the common StartPoint rOrigin
- * bMirrored : define if rStyle of one other BorderLine shall be mirrored (e.g. bottom-right edges)
- * With multiple BorderLines the definitions have to be CounterClockWise. This will be
- * ensured by StyleVectorTable sorting the entries, but knowing this may allow more efficcient
- * data creation.
- * rEndStyleVectorTable: All other BorderLines that have the same EndPoint. There are differences to
- * the Start definitions:
- * - do not forget to consequently use -rX for rMyVector
- * - definitions have to be ClockWise for the EndBorderLines, will be ensured by sorting
- *
- * If you take all this into account, you will gett correctly extended BorderLinePrimitive2D
- * reprsentations for the new to be defined BorderLine. That extensions will overlap nicely
- * with the corresponding BordreLines and take all multiple line definitions in the ::Style into
- * account.
- * The internal solver is *not limitied* to ::Style(s) with three parts (Left/Gap/Right), this is
- * just due to svx::frame::Style's definitions. A new solver based on this one can be created
- * anytime using more mulötiple borders based on the more flexible
- * std::vector< drawinglayer::primitive2d::BorderLine > if needed.
- */
-SVX_DLLPUBLIC void CreateBorderPrimitives(
- drawinglayer::primitive2d::Primitive2DContainer& rTarget, /// target for created primitives
- const basegfx::B2DPoint& rOrigin, /// start point of borderline
- const basegfx::B2DVector& rX, /// X-Axis of borderline with length
- const Style& rBorder, /// Style of borderline
- const StyleVectorTable& rStartStyleVectorTable, /// Styles and vectors (pointing away) at borderline start, ccw
- const StyleVectorTable& rEndStyleVectorTable, /// Styles and vectors (pointing away) at borderline end, cw
- const Color* pForceColor /// If specified, overrides frame border color.
-);
-
}
}
diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx
index c2c207cec5a8..7a4d8e9df640 100644
--- a/include/svx/framelinkarray.hxx
+++ b/include/svx/framelinkarray.hxx
@@ -323,11 +323,6 @@ private:
ArrayImplPtr mxImpl;
};
-// helper to merge B2DPrimitive(s) in rSource and add to rTarget
-void SVX_DLLPUBLIC HelperMergeInB2DPrimitiveArray(
- const drawinglayer::primitive2d::Primitive2DContainer& rSource,
- drawinglayer::primitive2d::Primitive2DContainer& rTarget);
-
}
}
diff --git a/include/svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx b/include/svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx
new file mode 100755
index 000000000000..611ec6b20285
--- /dev/null
+++ b/include/svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx
@@ -0,0 +1,119 @@
+/* -*- 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_SVX_INC_SDR_PRIMITIVE2D_SDRFRAMEBORDERPRIMITIVE2D_HXX
+#define INCLUDED_SVX_INC_SDR_PRIMITIVE2D_SDRFRAMEBORDERPRIMITIVE2D_HXX
+
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <svx/framelink.hxx>
+
+// predefines
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ class SVX_DLLPUBLIC SdrFrameBorderData
+ {
+ private:
+ basegfx::B2DPoint maOrigin; /// start point of borderline
+ basegfx::B2DVector maX; /// X-Axis of borderline with length
+ svx::frame::Style maStyle; /// Style of borderline
+ Color maColor;
+ bool mbForceColor;
+
+ class SdrConnectStyleData
+ {
+ private:
+ svx::frame::Style maStyle;
+ basegfx::B2DVector maNormalizedPerpendicular;
+ bool mbStyleMirrored;
+
+ public:
+ SdrConnectStyleData(
+ const svx::frame::Style& rStyle,
+ const basegfx::B2DVector& rNormalizedPerpendicular,
+ bool bStyleMirrored);
+
+ const svx::frame::Style& getStyle() const { return maStyle; }
+ const basegfx::B2DVector& getNormalizedPerpendicular() const { return maNormalizedPerpendicular; }
+ bool getStyleMirrored() const { return mbStyleMirrored; }
+ };
+
+ std::vector<SdrConnectStyleData> maStart;
+ std::vector<SdrConnectStyleData> maEnd;
+
+ public:
+ SdrFrameBorderData(
+ const basegfx::B2DPoint& rOrigin,
+ const basegfx::B2DVector& rX,
+ const svx::frame::Style& rStyle,
+ const Color* pForceColor);
+
+ void addSdrConnectStyleData(
+ bool bStart,
+ const svx::frame::Style& rStyle,
+ const basegfx::B2DVector& rNormalizedPerpendicular,
+ bool bStyleMirrored);
+
+ void create2DDecomposition(Primitive2DContainer& rContainer) const;
+ };
+
+ typedef std::vector<SdrFrameBorderData> SdrFrameBorderDataVector;
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ class SVX_DLLPUBLIC SdrFrameBorderPrimitive2D : public BufferedDecompositionPrimitive2D
+ {
+ private:
+ std::shared_ptr<SdrFrameBorderDataVector> maFrameBorders;
+ bool mbMergeResult;
+
+ protected:
+ // local decomposition.
+ virtual Primitive2DContainer create2DDecomposition(
+ const geometry::ViewInformation2D& aViewInformation) const override;
+
+ public:
+ SdrFrameBorderPrimitive2D(
+ std::shared_ptr<SdrFrameBorderDataVector>& rFrameBorders,
+ bool bMergeResult);
+
+ // compare operator
+ virtual bool operator==(const BasePrimitive2D& rPrimitive) const override;
+
+ // data access
+ const SdrFrameBorderDataVector& getFrameBorders() const { return *maFrameBorders.get(); }
+ bool getMergeResult() const { return mbMergeResult; }
+
+ // provide unique ID
+ DeclPrimitive2DIDBlock()
+ };
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+
+#endif // INCLUDED_SVX_INC_SDR_PRIMITIVE2D_SDRFRAMEBORDERPRIMITIVE2D_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx b/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx
index d2a16623dd02..d6cb948a6bf6 100644
--- a/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx
+++ b/include/svx/sdr/primitive2d/svx_primitivetypes2d.hxx
@@ -47,6 +47,7 @@
#define PRIMITIVE2D_ID_SDROLECONTENTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 21)
#define PRIMITIVE2D_ID_SDRAUTOFITTEXTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 22)
#define PRIMITIVE2D_ID_SDRCHAINEDTEXTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 23)
+#define PRIMITIVE2D_ID_SDRFRAMEBORDERTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 24)
#endif // INCLUDED_SVX_SDR_PRIMITIVE2D_SVX_PRIMITIVETYPES2D_HXX
diff --git a/svx/Library_svxcore.mk b/svx/Library_svxcore.mk
index 4bb7dcab835f..8c58029d5949 100644
--- a/svx/Library_svxcore.mk
+++ b/svx/Library_svxcore.mk
@@ -247,6 +247,7 @@ $(eval $(call gb_Library_add_exception_objects,svxcore,\
svx/source/sdr/primitive2d/sdrcaptionprimitive2d \
svx/source/sdr/primitive2d/sdrconnectorprimitive2d \
svx/source/sdr/primitive2d/sdrmeasureprimitive2d \
+ svx/source/sdr/primitive2d/sdrframeborderprimitive2d \
svx/source/sdr/primitive2d/sdrattributecreator \
svx/source/sdr/primitive2d/sdrdecompositiontools \
svx/source/sdr/primitive3d/sdrattributecreator3d \
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index 4474602c78c6..80dd02450576 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -28,10 +28,6 @@
#include <tools/gen.hxx>
#include <editeng/borderline.hxx>
#include <svtools/borderhelper.hxx>
-
-#include <basegfx/polygon/b2dpolygon.hxx>
-#include <basegfx/polygon/b2dpolygontools.hxx>
-
#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
@@ -334,469 +330,6 @@ bool Style::operator<( const Style& rOther) const
// seem to be equal
return false;
}
-
-// Drawing functions
-struct CutSet
-{
- double mfOLML;
- double mfORML;
- double mfOLMR;
- double mfORMR;
-
- CutSet() : mfOLML(0.0), mfORML(0.0), mfOLMR(0.0), mfORMR(0.0)
- {
- }
-
- bool operator<( const CutSet& rOther) const
- {
- const double fA(mfOLML + mfORML + mfOLMR + mfORMR);
- const double fB(rOther.mfOLML + rOther.mfORML + rOther.mfOLMR + rOther.mfORMR);
-
- return fA < fB;
- }
-
- double getSum() const { return mfOLML + mfORML + mfOLMR + mfORMR; }
- } ;
-
-struct ExtendSet
-{
- double mfExtLeft;
- double mfExtRight;
-
- ExtendSet() : mfExtLeft(0.0), mfExtRight(0.0) {}
-};
-
-void getCutSet(
- CutSet& rCutSet,
- const basegfx::B2DPoint& rLeft,
- const basegfx::B2DPoint& rRight,
- const basegfx::B2DVector& rX,
- const basegfx::B2DPoint& rOtherLeft,
- const basegfx::B2DPoint& rOtherRight,
- const basegfx::B2DVector& rOtherX)
-{
- basegfx::tools::findCut(
- rLeft,
- rX,
- rOtherLeft,
- rOtherX,
- CutFlagValue::LINE,
- &rCutSet.mfOLML);
-
- basegfx::tools::findCut(
- rRight,
- rX,
- rOtherLeft,
- rOtherX,
- CutFlagValue::LINE,
- &rCutSet.mfOLMR);
-
- basegfx::tools::findCut(
- rLeft,
- rX,
- rOtherRight,
- rOtherX,
- CutFlagValue::LINE,
- &rCutSet.mfORML);
-
- basegfx::tools::findCut(
- rRight,
- rX,
- rOtherRight,
- rOtherX,
- CutFlagValue::LINE,
- &rCutSet.mfORMR);
-}
-
-void getExtends(
- std::vector<ExtendSet>& rExtendSet, // target Left/Right values to fill
- const basegfx::B2DPoint& rOrigin, // own vector start
- const StyleVectorCombination& rCombination, // own vector and offstets for lines
- const basegfx::B2DVector& rPerpendX, // normalized perpendicular to own vector
- const std::vector< StyleVectorCombination >& rStyleVector) // other vectors emerging in this point
-{
- if(!rCombination.empty() && !rStyleVector.empty() && rCombination.size() == rExtendSet.size())
- {
- const size_t nOffsetA(rCombination.size());
-
- if(1 == nOffsetA)
- {
- Color aMyColor; double fMyOffset(0.0); double fMyHalfWidth(0.0);
- rCombination.getColorAndOffsetAndHalfWidth(0, aMyColor, fMyOffset, fMyHalfWidth);
-
- if(0xff != aMyColor.GetTransparency())
- {
- const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
- const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
- std::vector< CutSet > aCutSets;
-
- for(const auto& rStyleCandidate : rStyleVector)
- {
- const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleCandidate.getB2DVector()));
- const size_t nOffsetB(rStyleCandidate.size());
-
- for(size_t other(0); other < nOffsetB; other++)
- {
- Color aOtherColor; double fOtherOffset(0.0); double fOtherHalfWidth(0.0);
- rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
-
- if(0xff != aOtherColor.GetTransparency())
- {
- const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
- const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
-
- CutSet aNewCutSet;
- getCutSet(aNewCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
- aCutSets.push_back(aNewCutSet);
- }
- }
- }
-
- if(!aCutSets.empty())
- {
- CutSet aCutSet(aCutSets[0]);
- const size_t nNumCutSets(aCutSets.size());
-
- if(1 != nNumCutSets)
- {
- double fCutSet(aCutSet.getSum());
-
- for(size_t a(1); a < nNumCutSets; a++)
- {
- const CutSet& rCandidate(aCutSets[a]);
- const double fCandidate(rCandidate.getSum());
-
- if(basegfx::fTools::equalZero(fCandidate - fCutSet))
- {
- // both have equal center point, use medium cut
- const double fNewOLML(std::max(std::min(rCandidate.mfOLML, rCandidate.mfORML), std::min(aCutSet.mfOLML, aCutSet.mfORML)));
- const double fNewORML(std::min(std::max(rCandidate.mfOLML, rCandidate.mfORML), std::max(aCutSet.mfOLML, aCutSet.mfORML)));
- const double fNewOLMR(std::max(std::min(rCandidate.mfOLMR, rCandidate.mfORMR), std::min(aCutSet.mfOLMR, aCutSet.mfORMR)));
- const double fNewORMR(std::min(std::max(rCandidate.mfOLMR, rCandidate.mfORMR), std::max(aCutSet.mfOLMR, aCutSet.mfORMR)));
- aCutSet.mfOLML = fNewOLML;
- aCutSet.mfORML = fNewORML;
- aCutSet.mfOLMR = fNewOLMR;
- aCutSet.mfORMR = fNewORMR;
- fCutSet = aCutSet.getSum();
- }
- else if(fCandidate < fCutSet)
- {
- // get minimum
- fCutSet = fCandidate;
- aCutSet = rCandidate;
- }
- }
- }
-
- ExtendSet& rExt(rExtendSet[0]);
-
- rExt.mfExtLeft = std::min(aCutSet.mfOLML, aCutSet.mfORML);
- rExt.mfExtRight = std::min(aCutSet.mfOLMR, aCutSet.mfORMR);
- }
- }
- }
- else
- {
- size_t nVisEdgeUp(0);
- size_t nVisEdgeDn(0);
-
- for(size_t my(0); my < nOffsetA; my++)
- {
- Color aMyColor; double fMyOffset(0.0); double fMyHalfWidth(0.0);
- rCombination.getColorAndOffsetAndHalfWidth(my, aMyColor, fMyOffset, fMyHalfWidth);
-
- if(0xff != aMyColor.GetTransparency())
- {
- const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
- const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
- const bool bUpper(my <= (nOffsetA >> 1));
- const StyleVectorCombination& rStyleCandidate(bUpper ? rStyleVector.front() : rStyleVector.back());
- const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleCandidate.getB2DVector()));
- const size_t nOffsetB(rStyleCandidate.size());
- std::vector< CutSet > aCutSets;
-
- for(size_t other(0); other < nOffsetB; other++)
- {
- Color aOtherColor; double fOtherOffset(0.0); double fOtherHalfWidth(0.0);
- rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
-
- if(0xff != aOtherColor.GetTransparency())
- {
- const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
- const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
- CutSet aCutSet;
- getCutSet(aCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
- aCutSets.push_back(aCutSet);
- }
- }
-
- if(!aCutSets.empty())
- {
- // sort: min to start, max to end
- std::sort(aCutSets.begin(), aCutSets.end());
- const bool bOtherUpper(rStyleCandidate.getAngle() > F_PI);
-
- // check if we need min or max
- // bUpper bOtherUpper MinMax
- // t t max
- // t f min
- // f f max
- // f t min
- const bool bMax(bUpper == bOtherUpper);
- size_t nBaseIndex(0);
- const size_t nNumCutSets(aCutSets.size());
-
- if(bMax)
- {
- // access at end
- nBaseIndex = nNumCutSets - 1 - (bUpper ? nVisEdgeUp : nVisEdgeDn);
- }
- else
- {
- // access at start
- nBaseIndex = bUpper ? nVisEdgeUp : nVisEdgeDn;
- }
-
- const size_t nSecuredIndex(std::min(nNumCutSets - 1, std::max(nBaseIndex, static_cast< size_t >(0))));
- const CutSet& rCutSet(aCutSets[nSecuredIndex]);
- ExtendSet& rExt(rExtendSet[my]);
-
- rExt.mfExtLeft = std::min(rCutSet.mfOLML, rCutSet.mfORML);
- rExt.mfExtRight = std::min(rCutSet.mfOLMR, rCutSet.mfORMR);
- }
-
- if(bUpper)
- {
- nVisEdgeUp++;
- }
- else
- {
- nVisEdgeDn++;
- }
- }
- }
- }
- }
-}
-
-StyleVectorCombination::StyleVectorCombination(
- const Style& rStyle,
- const basegfx::B2DVector& rB2DVector,
- double fAngle,
- bool bMirrored,
- const Color* pForceColor)
-: mfRefModeOffset(0.0),
- maB2DVector(rB2DVector),
- mfAngle(fAngle),
- maOffsets()
-{
- if (rStyle.IsUsed())
- {
- RefMode aRefMode(rStyle.GetRefMode());
- Color aPrim(rStyle.GetColorPrim());
- Color aSecn(rStyle.GetColorSecn());
- double fPrim(rStyle.Prim());
- double fSecn(rStyle.Secn());
- const bool bSecnUsed(0.0 != fSecn);
-
- if(bMirrored)
- {
- switch(aRefMode)
- {
- case RefMode::REFMODE_BEGIN: aRefMode = RefMode::REFMODE_END; break;
- case RefMode::REFMODE_END: aRefMode = RefMode::REFMODE_BEGIN; break;
- default: break;
- }
-
- if(bSecnUsed)
- {
- std::swap(aPrim, aSecn);
- std::swap(fPrim, fSecn);
- }
- }
-
- if (RefMode::REFMODE_CENTERED != aRefMode)
- {
- const double fHalfWidth(rStyle.GetWidth() * 0.5);
-
- if (RefMode::REFMODE_BEGIN == aRefMode)
- {
- // move aligned below vector
- mfRefModeOffset = fHalfWidth;
- }
- else if (RefMode::REFMODE_END == aRefMode)
- {
- // move aligned above vector
- mfRefModeOffset = -fHalfWidth;
- }
- }
-
- if (bSecnUsed)
- {
- // both or all three lines used
- const bool bPrimTransparent(0xff == rStyle.GetColorPrim().GetTransparency());
- const bool bDistTransparent(!rStyle.UseGapColor() || 0xff == rStyle.GetColorGap().GetTransparency());
- const bool bSecnTransparent(0xff == aSecn.GetTransparency());
-
- if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent)
- {
- const double a(mfRefModeOffset - (rStyle.GetWidth() * 0.5));
- const double b(a + fPrim);
- const double c(b + rStyle.Dist());
- const double d(c + fSecn);
-
- maOffsets.push_back(
- OffsetAndHalfWidthAndColor(
- (a + b) * 0.5,
- fPrim * 0.5,
- nullptr != pForceColor ? *pForceColor : aPrim));
-
- maOffsets.push_back(
- OffsetAndHalfWidthAndColor(
- (b + c) * 0.5,
- rStyle.Dist() * 0.5,
- rStyle.UseGapColor()
- ? (nullptr != pForceColor ? *pForceColor : rStyle.GetColorGap())
- : Color(COL_TRANSPARENT)));
-
- maOffsets.push_back(
- OffsetAndHalfWidthAndColor(
- (c + d) * 0.5,
- fSecn * 0.5,
- nullptr != pForceColor ? *pForceColor : aSecn));
- }
- }
- else
- {
- // one line used, push two values, from outer to inner
- if(0xff != rStyle.GetColorPrim().GetTransparency())
- {
- maOffsets.push_back(
- OffsetAndHalfWidthAndColor(
- mfRefModeOffset,
- fPrim * 0.5,
- nullptr != pForceColor ? *pForceColor : aPrim));
- }
- }
- }
-}
-
-void StyleVectorCombination::getColorAndOffsetAndHalfWidth(size_t nIndex, Color& rColor, double& rfOffset, double& rfHalfWidth) const
-{
- if(nIndex >= maOffsets.size())
- return;
- const OffsetAndHalfWidthAndColor& rCandidate(maOffsets[nIndex]);
- rfOffset = rCandidate.mfOffset;
- rfHalfWidth = rCandidate.mfHalfWidth;
- rColor = rCandidate.maColor;
-}
-
-void StyleVectorTable::add(
- const Style& rStyle,
- const basegfx::B2DVector& rMyVector,
- const basegfx::B2DVector& rOtherVector,
- bool bMirrored)
-{
- if(rStyle.IsUsed() && !basegfx::areParallel(rMyVector, rOtherVector))
- {
- // create angle between both. angle() needs vectors pointing away from the same point,
- // so take the mirrored one. Add F_PI to get from -pi..+pi to [0..F_PI2] for sorting
- const double fAngle(basegfx::B2DVector(-rMyVector.getX(), -rMyVector.getY()).angle(rOtherVector) + F_PI);
- maEntries.emplace_back(rStyle, rOtherVector, fAngle, bMirrored);
- }
-}
-
-void StyleVectorTable::sort()
-{
- // sort inverse fom highest to lowest
- std::sort(maEntries.begin(), maEntries.end(), [](const StyleVectorCombination& a, const StyleVectorCombination& b) { return a.getAngle() > b.getAngle(); });
-}
-
-void CreateBorderPrimitives(
- drawinglayer::primitive2d::Primitive2DContainer& rTarget,
- const basegfx::B2DPoint& rOrigin,
- const basegfx::B2DVector& rX,
- const Style& rBorder,
- const StyleVectorTable& rStartStyleVectorTable,
- const StyleVectorTable& rEndStyleVectorTable,
- const Color* pForceColor)
-{
- // get offset color pairs for style, one per visible line
- const StyleVectorCombination aCombination(rBorder, rX, 0.0, false, pForceColor);
-
- if(!aCombination.empty())
- {
- const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX));
- const bool bHasStartStyles(!rStartStyleVectorTable.empty());
- const bool bHasEndStyles(!rEndStyleVectorTable.empty());
- const size_t nOffsets(aCombination.size());
- std::vector<ExtendSet> aExtendSetStart(nOffsets);
- std::vector<ExtendSet> aExtendSetEnd(nOffsets);
-
- if(bHasStartStyles)
- {
- // create extends for line starts, use given point/vector and offsets
- getExtends(aExtendSetStart, rOrigin, aCombination, aPerpendX, rStartStyleVectorTable.getEntries());
- }
-
- if(bHasEndStyles)
- {
- // Create extends for line ends, create inverse point/vector and inverse offsets.
- const StyleVectorCombination aMirroredCombination(rBorder, -rX, 0.0, true, pForceColor);
-
- getExtends(aExtendSetEnd, rOrigin + rX, aMirroredCombination, -aPerpendX, rEndStyleVectorTable.getEntries());
-
- // also need to inverse the result to apply to the correct lines
- std::reverse(aExtendSetEnd.begin(), aExtendSetEnd.end());
- }
-
- std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
- const double fNegLength(-rX.getLength());
-
- for(size_t a(0); a < nOffsets; a++)
- {
- Color aMyColor;
- double fMyOffset(0.0);
- double fMyHalfWidth(0.0);
- aCombination.getColorAndOffsetAndHalfWidth(a, aMyColor, fMyOffset, fMyHalfWidth);
- const ExtendSet& rExtStart(aExtendSetStart[a]);
- const ExtendSet& rExtEnd(aExtendSetEnd[a]);
-
- if(0xff == aMyColor.GetTransparency())
- {
- aBorderlines.push_back(
- drawinglayer::primitive2d::BorderLine(
- fMyHalfWidth * 2.0));
- }
- else
- {
- aBorderlines.push_back(
- drawinglayer::primitive2d::BorderLine(
- drawinglayer::attribute::LineAttribute(
- aMyColor.getBColor(),
- fMyHalfWidth * 2.0),
- fNegLength * rExtStart.mfExtLeft,
- fNegLength * rExtStart.mfExtRight,
- fNegLength * rExtEnd.mfExtRight,
- fNegLength * rExtEnd.mfExtLeft));
- }
- }
-
- static double fPatScFact(10.0); // 10.0 multiply, see old code
- const std::vector<double> aDashing(svtools::GetLineDashing(rBorder.Type(), rBorder.PatternScale() * fPatScFact));
- const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing);
- const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * aCombination.getRefModeOffset()));
-
- rTarget.push_back(
- drawinglayer::primitive2d::Primitive2DReference(
- new drawinglayer::primitive2d::BorderLinePrimitive2D(
- aStart,
- aStart + rX,
- aBorderlines,
- aStrokeAttribute)));
- }
-}
-
}
}
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index a2aca66a37fd..147017da01f3 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -25,6 +25,7 @@
#include <algorithm>
#include <vcl/outdev.hxx>
#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
+#include <svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
namespace svx {
@@ -929,26 +930,38 @@ void Array::MirrorSelfX()
}
// drawing
-void HelperCreateHorizontalEntry(
- const Array& rArray, const Style& rStyle, size_t col, size_t row,
- const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX, const basegfx::B2DVector& rY,
- drawinglayer::primitive2d::Primitive2DContainer& rSequence,
- bool bUpper, const Color* pForceColor)
-{
+static void HelperCreateHorizontalEntry(
+ const Array& rArray,
+ const Style& rStyle,
+ size_t col,
+ size_t row,
+ const basegfx::B2DPoint& rOrigin,
+ const basegfx::B2DVector& rX,
+ const basegfx::B2DVector& rY,
+ drawinglayer::primitive2d::SdrFrameBorderDataVector& rData,
+ bool bUpper,
+ const Color* pForceColor)
+{
+ // prepare SdrFrameBorderData
+ rData.emplace_back(
+ bUpper ? rOrigin : basegfx::B2DPoint(rOrigin + rY),
+ rX,
+ rStyle,
+ pForceColor);
+ drawinglayer::primitive2d::SdrFrameBorderData& rInstance(rData.back());
+
// get involved styles at start
const Style& rStartFromTR(rArray.GetCellStyleBL( col, row - 1 ));
const Style& rStartLFromT(rArray.GetCellStyleLeft( col, row - 1 ));
const Style& rStartLFromL(rArray.GetCellStyleTop( col - 1, row ));
const Style& rStartLFromB(rArray.GetCellStyleLeft( col, row ));
const Style& rStartFromBR(rArray.GetCellStyleTL( col, row ));
- StyleVectorTable aStart;
- aStart.add(rStartFromTR, rX, rX - rY, false);
- aStart.add(rStartLFromT, rX, -rY, true);
- aStart.add(rStartLFromL, rX, -rX, true);
- aStart.add(rStartLFromB, rX, rY, false);
- aStart.add(rStartFromBR, rX, rX + rY, false);
- aStart.sort();
+ rInstance.addSdrConnectStyleData(true, rStartFromTR, rX - rY, false);
+ rInstance.addSdrConnectStyleData(true, rStartLFromT, -rY, true);
+ rInstance.addSdrConnectStyleData(true, rStartLFromL, -rX, true);
+ rInstance.addSdrConnectStyleData(true, rStartLFromB, rY, false);
+ rInstance.addSdrConnectStyleData(true, rStartFromBR, rX + rY, false);
// get involved styles at end
const Style& rEndFromTL(rArray.GetCellStyleBR( col, row - 1 ));
@@ -956,47 +969,46 @@ void HelperCreateHorizontalEntry(
const Style& rEndRFromR(rArray.GetCellStyleTop( col + 1, row ));
const Style& rEndRFromB(rArray.GetCellStyleRight( col, row ));
const Style& rEndFromBL(rArray.GetCellStyleTR( col, row ));
- StyleVectorTable aEnd;
- const basegfx::B2DVector aAxis(-rX);
-
- aEnd.add(rEndFromTL, aAxis, aAxis - rY, true);
- aEnd.add(rEndRFromT, aAxis, -rY, true);
- aEnd.add(rEndRFromR, aAxis, rX, false);
- aEnd.add(rEndRFromB, aAxis, rY, false);
- aEnd.add(rEndFromBL, aAxis, rY - rX, true);
- aEnd.sort();
-
- CreateBorderPrimitives(
- rSequence,
- bUpper ? rOrigin : basegfx::B2DPoint(rOrigin + rY),
- rX,
+
+ rInstance.addSdrConnectStyleData(false, rEndFromTL, -rX - rY, true);
+ rInstance.addSdrConnectStyleData(false, rEndRFromT, -rY, true);
+ rInstance.addSdrConnectStyleData(false, rEndRFromR, rX, false);
+ rInstance.addSdrConnectStyleData(false, rEndRFromB, rY, false);
+ rInstance.addSdrConnectStyleData(false, rEndFromBL, rY - rX, true);
+}
+
+static void HelperCreateVerticalEntry(
+ const Array& rArray,
+ const Style& rStyle,
+ size_t col,
+ size_t row,
+ const basegfx::B2DPoint& rOrigin,
+ const basegfx::B2DVector& rX,
+ const basegfx::B2DVector& rY,
+ drawinglayer::primitive2d::SdrFrameBorderDataVector& rData,
+ bool bLeft,
+ const Color* pForceColor)
+{
+ // prepare SdrFrameBorderData
+ rData.emplace_back(
+ bLeft ? rOrigin : basegfx::B2DPoint(rOrigin + rX),
+ rY,
rStyle,
- aStart,
- aEnd,
- pForceColor
- );
-}
+ pForceColor);
+ drawinglayer::primitive2d::SdrFrameBorderData& rInstance(rData.back());
-void HelperCreateVerticalEntry(
- const Array& rArray, const Style& rStyle, size_t col, size_t row,
- const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX, const basegfx::B2DVector& rY,
- drawinglayer::primitive2d::Primitive2DContainer& rSequence,
- bool bLeft, const Color* pForceColor)
-{
// get involved styles at start
const Style& rStartFromBL(rArray.GetCellStyleTR( col - 1, row ));
const Style& rStartTFromL(rArray.GetCellStyleTop( col - 1, row ));
const Style& rStartTFromT(rArray.GetCellStyleLeft( col, row - 1 ));
const Style& rStartTFromR(rArray.GetCellStyleTop( col, row ));
const Style& rStartFromBR(rArray.GetCellStyleTL( col, row ));
- StyleVectorTable aStart;
- aStart.add(rStartFromBR, rY, rX + rY, false);
- aStart.add(rStartTFromR, rY, rX, false);
- aStart.add(rStartTFromT, rY, -rY, true);
- aStart.add(rStartTFromL, rY, -rX, true);
- aStart.add(rStartFromBL, rY, rY - rX, true);
- aStart.sort();
+ rInstance.addSdrConnectStyleData(true, rStartFromBR, rX + rY, false);
+ rInstance.addSdrConnectStyleData(true, rStartTFromR, rX, false);
+ rInstance.addSdrConnectStyleData(true, rStartTFromT, -rY, true);
+ rInstance.addSdrConnectStyleData(true, rStartTFromL, -rX, true);
+ rInstance.addSdrConnectStyleData(true, rStartFromBL, rY - rX, true);
// get involved styles at end
const Style& rEndFromTL(rArray.GetCellStyleBR( col - 1, row ));
@@ -1004,67 +1016,12 @@ void HelperCreateVerticalEntry(
const Style& rEndBFromB(rArray.GetCellStyleLeft( col, row + 1 ));
const Style& rEndBFromR(rArray.GetCellStyleBottom( col, row ));
const Style& rEndFromTR(rArray.GetCellStyleBL( col, row ));
- StyleVectorTable aEnd;
- const basegfx::B2DVector aAxis(-rY);
-
- aEnd.add(rEndFromTR, aAxis, rX - rY, false);
- aEnd.add(rEndBFromR, aAxis, rX, false);
- aEnd.add(rEndBFromB, aAxis, rY, false);
- aEnd.add(rEndBFromL, aAxis, -rX, true);
- aEnd.add(rEndFromTL, aAxis, aAxis - rX, true);
- aEnd.sort();
-
- CreateBorderPrimitives(
- rSequence,
- bLeft ? rOrigin : basegfx::B2DPoint(rOrigin + rX),
- rY,
- rStyle,
- aStart,
- aEnd,
- pForceColor
- );
-}
-void HelperMergeInB2DPrimitiveArray(
- const drawinglayer::primitive2d::Primitive2DContainer& rSource,
- drawinglayer::primitive2d::Primitive2DContainer& rTarget)
-{
- if(rSource.size() > 1)
- {
- drawinglayer::primitive2d::Primitive2DReference aCandidate;
-
- for(const auto& a : rSource)
- {
- if(aCandidate.is())
- {
- const drawinglayer::primitive2d::Primitive2DReference aMerge(
- drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(aCandidate, a));
-
- if(aMerge.is())
- {
- aCandidate = aMerge;
- }
- else
- {
- rTarget.push_back(aCandidate);
- aCandidate = a;
- }
- }
- else
- {
- aCandidate = a;
- }
- }
-
- if(aCandidate.is())
- {
- rTarget.push_back(aCandidate);
- }
- }
- else
- {
- rTarget.append(rSource);
- }
+ rInstance.addSdrConnectStyleData(false, rEndFromTR, rX - rY, false);
+ rInstance.addSdrConnectStyleData(false, rEndBFromR, rX, false);
+ rInstance.addSdrConnectStyleData(false, rEndBFromB, rY, false);
+ rInstance.addSdrConnectStyleData(false, rEndBFromL, -rX, true);
+ rInstance.addSdrConnectStyleData(false, rEndFromTL, -rY - rX, true);
}
drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
@@ -1095,10 +1052,9 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
const size_t nStartCol(nFirstCol > 0 ? nFirstCol - 1 : nFirstCol);
const size_t nEndCol(nLastCol < GetColCount() - 1 ? nLastCol + 1 : nLastCol);
- // various primitive sequences to collect the different border types
- drawinglayer::primitive2d::Primitive2DContainer aHorizontalSequence;
- std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nEndCol - nStartCol + 1);
- drawinglayer::primitive2d::Primitive2DContainer aCrossSequence;
+ // prepare SdrFrameBorderDataVector
+ std::shared_ptr<drawinglayer::primitive2d::SdrFrameBorderDataVector> aData(
+ std::make_shared<drawinglayer::primitive2d::SdrFrameBorderDataVector>());
// remember for which merged cells crossed lines were already created. To
// do so, hold the size_t cell index in a set for fast check
@@ -1148,7 +1104,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
if(rTop.IsUsed())
{
- HelperCreateHorizontalEntry(*this, rTop, nCol, nRow, aOrigin, aX, aY, aHorizontalSequence, true, pForceColor);
+ HelperCreateHorizontalEntry(*this, rTop, nCol, nRow, aOrigin, aX, aY, *aData.get(), true, pForceColor);
}
}
@@ -1160,7 +1116,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
if(rBottom.IsUsed())
{
- HelperCreateHorizontalEntry(*this, rBottom, nCol, nRow + 1, aOrigin, aX, aY, aHorizontalSequence, false, pForceColor);
+ HelperCreateHorizontalEntry(*this, rBottom, nCol, nRow + 1, aOrigin, aX, aY, *aData.get(), false, pForceColor);
}
}
@@ -1173,7 +1129,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
if(rLeft.IsUsed())
{
- HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nStartCol], true, pForceColor);
+ HelperCreateVerticalEntry(*this, rLeft, nCol, nRow, aOrigin, aX, aY, *aData.get(), true, pForceColor);
}
}
@@ -1185,7 +1141,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
if(rRight.IsUsed())
{
- HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, aVerticalSequences[nCol - nStartCol], false, pForceColor);
+ HelperCreateVerticalEntry(*this, rRight, nCol + 1, nRow, aOrigin, aX, aY, *aData.get(), false, pForceColor);
}
}
@@ -1226,69 +1182,51 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
if(rTLBR.IsUsed())
{
/// top-left and bottom-right Style Tables
+ aData->emplace_back(
+ aOrigin,
+ aX + aY,
+ rTLBR,
+ pForceColor);
+ drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
+
/// Fill top-left Style Table
const Style& rTLFromRight(GetCellStyleTop(nCol, nRow));
const Style& rTLFromBottom(GetCellStyleLeft(nCol, nRow));
- StyleVectorTable aStart;
- const basegfx::B2DVector aAxisA(aX + aY);
- aStart.add(rTLFromRight, aAxisA, aX, false);
- aStart.add(rTLFromBottom, aAxisA, aY, false);
- aStart.sort();
+ rInstance.addSdrConnectStyleData(true, rTLFromRight, aX, false);
+ rInstance.addSdrConnectStyleData(true, rTLFromBottom, aY, false);
/// Fill bottom-right Style Table
const Style& rBRFromBottom(GetCellStyleRight(nCol, nRow));
const Style& rBRFromLeft(GetCellStyleBottom(nCol, nRow));
- StyleVectorTable aEnd;
- const basegfx::B2DVector aAxisB(-aX -aY);
-
- aEnd.add(rBRFromBottom, aAxisB, -aY, true);
- aEnd.add(rBRFromLeft, aAxisB, -aX, true);
- aEnd.sort();
- CreateBorderPrimitives(
- aCrossSequence,
- aOrigin,
- aX + aY,
- rTLBR,
- aStart,
- aEnd,
- pForceColor
- );
+ rInstance.addSdrConnectStyleData(false, rBRFromBottom, -aY, true);
+ rInstance.addSdrConnectStyleData(false, rBRFromLeft, -aX, true);
}
if(rBLTR.IsUsed())
{
/// bottom-left and top-right Style Tables
+ aData->emplace_back(
+ aOrigin + aY,
+ aX - aY,
+ rBLTR,
+ pForceColor);
+ drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
+
/// Fill bottom-left Style Table
const Style& rBLFromTop(GetCellStyleLeft(nCol, nRow));
const Style& rBLFromBottom(GetCellStyleBottom(nCol, nRow));
- StyleVectorTable aStart;
- const basegfx::B2DVector aAxisA(aX - aY);
- aStart.add(rBLFromTop, aAxisA, -aY, true);
- aStart.add(rBLFromBottom, aAxisA, aX, false);
- aStart.sort();
+ rInstance.addSdrConnectStyleData(true, rBLFromTop, -aY, true);
+ rInstance.addSdrConnectStyleData(true, rBLFromBottom, aX, false);
/// Fill top-right Style Table
const Style& rTRFromLeft(GetCellStyleTop(nCol, nRow));
const Style& rTRFromBottom(GetCellStyleRight(nCol, nRow));
- StyleVectorTable aEnd;
- const basegfx::B2DVector aAxisB(aY - aX);
-
- aEnd.add(rTRFromLeft, aAxisB, -aX, true);
- aEnd.add(rTRFromBottom, aAxisB, aY, false);
- aEnd.sort();
- CreateBorderPrimitives(
- aCrossSequence,
- aOrigin + aY,
- aX - aY,
- rBLTR,
- aStart,
- aEnd,
- pForceColor
- );
+ rInstance.addSdrConnectStyleData(false, rTRFromLeft, -aX, true);
+ rInstance.addSdrConnectStyleData(false, rTRFromBottom, aY, false);
}
}
}
@@ -1296,16 +1234,20 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange(
}
}
- // to stay compatible, create order as it was formally. Also try to
- // merge primitives as far as possible
- HelperMergeInB2DPrimitiveArray(aHorizontalSequence, aCrossSequence);
+ // create instance of SdrFrameBorderPrimitive2D if
+ // SdrFrameBorderDataVector is used
+ drawinglayer::primitive2d::Primitive2DContainer aSequence;
- for(const auto& aVert : aVerticalSequences)
+ if(!aData->empty())
{
- HelperMergeInB2DPrimitiveArray(aVert, aCrossSequence);
+ aSequence.push_back(
+ drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::SdrFrameBorderPrimitive2D(
+ aData,
+ true)));
}
- return aCrossSequence;
+ return aSequence;
}
drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveArray() const
diff --git a/svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx b/svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx
new file mode 100755
index 000000000000..641968762d32
--- /dev/null
+++ b/svx/source/sdr/primitive2d/sdrframeborderprimitive2d.cxx
@@ -0,0 +1,768 @@
+/* -*- 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 <svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx>
+#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
+#include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <svtools/borderhelper.hxx>
+
+namespace
+{
+ class StyleVectorCombination
+ {
+ private:
+ struct OffsetAndHalfWidthAndColor
+ {
+ double mfOffset;
+ double mfHalfWidth;
+ Color maColor;
+
+ OffsetAndHalfWidthAndColor(double offset, double halfWidth, Color color) :
+ mfOffset(offset),
+ mfHalfWidth(halfWidth),
+ maColor(color)
+ {}
+ };
+
+ double mfRefModeOffset;
+ basegfx::B2DVector maB2DVector;
+ double mfAngle;
+ std::vector< OffsetAndHalfWidthAndColor > maOffsets;
+
+ public:
+ StyleVectorCombination(
+ const svx::frame::Style& rStyle,
+ const basegfx::B2DVector& rB2DVector,
+ double fAngle,
+ bool bMirrored,
+ const Color* pForceColor)
+ : mfRefModeOffset(0.0),
+ maB2DVector(rB2DVector),
+ mfAngle(fAngle),
+ maOffsets()
+ {
+ if (rStyle.IsUsed())
+ {
+ svx::frame::RefMode aRefMode(rStyle.GetRefMode());
+ Color aPrim(rStyle.GetColorPrim());
+ Color aSecn(rStyle.GetColorSecn());
+ double fPrim(rStyle.Prim());
+ double fSecn(rStyle.Secn());
+ const bool bSecnUsed(0.0 != fSecn);
+
+ if(bMirrored)
+ {
+ switch(aRefMode)
+ {
+ case svx::frame::RefMode::REFMODE_BEGIN: aRefMode = svx::frame::RefMode::REFMODE_END; break;
+ case svx::frame::RefMode::REFMODE_END: aRefMode = svx::frame::RefMode::REFMODE_BEGIN; break;
+ default: break;
+ }
+
+ if(bSecnUsed)
+ {
+ std::swap(aPrim, aSecn);
+ std::swap(fPrim, fSecn);
+ }
+ }
+
+ if (svx::frame::RefMode::REFMODE_CENTERED != aRefMode)
+ {
+ const double fHalfWidth(rStyle.GetWidth() * 0.5);
+
+ if (svx::frame::RefMode::REFMODE_BEGIN == aRefMode)
+ {
+ // move aligned below vector
+ mfRefModeOffset = fHalfWidth;
+ }
+ else if (svx::frame::RefMode::REFMODE_END == aRefMode)
+ {
+ // move aligned above vector
+ mfRefModeOffset = -fHalfWidth;
+ }
+ }
+
+ if (bSecnUsed)
+ {
+ // both or all three lines used
+ const bool bPrimTransparent(0xff == rStyle.GetColorPrim().GetTransparency());
+ const bool bDistTransparent(!rStyle.UseGapColor() || 0xff == rStyle.GetColorGap().GetTransparency());
+ const bool bSecnTransparent(0xff == aSecn.GetTransparency());
+
+ if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent)
+ {
+ const double a(mfRefModeOffset - (rStyle.GetWidth() * 0.5));
+ const double b(a + fPrim);
+ const double c(b + rStyle.Dist());
+ const double d(c + fSecn);
+
+ maOffsets.push_back(
+ OffsetAndHalfWidthAndColor(
+ (a + b) * 0.5,
+ fPrim * 0.5,
+ nullptr != pForceColor ? *pForceColor : aPrim));
+
+ maOffsets.push_back(
+ OffsetAndHalfWidthAndColor(
+ (b + c) * 0.5,
+ rStyle.Dist() * 0.5,
+ rStyle.UseGapColor()
+ ? (nullptr != pForceColor ? *pForceColor : rStyle.GetColorGap())
+ : COL_TRANSPARENT));
+
+ maOffsets.push_back(
+ OffsetAndHalfWidthAndColor(
+ (c + d) * 0.5,
+ fSecn * 0.5,
+ nullptr != pForceColor ? *pForceColor : aSecn));
+ }
+ }
+ else
+ {
+ // one line used, push two values, from outer to inner
+ if(0xff != rStyle.GetColorPrim().GetTransparency())
+ {
+ maOffsets.push_back(
+ OffsetAndHalfWidthAndColor(
+ mfRefModeOffset,
+ fPrim * 0.5,
+ nullptr != pForceColor ? *pForceColor : aPrim));
+ }
+ }
+ }
+ }
+
+ double getRefModeOffset() const { return mfRefModeOffset; }
+ const basegfx::B2DVector& getB2DVector() const { return maB2DVector; }
+ double getAngle() const { return mfAngle; }
+ bool empty() const { return maOffsets.empty(); }
+ size_t size() const { return maOffsets.size(); }
+
+ void getColorAndOffsetAndHalfWidth(size_t nIndex, Color& rColor, double& rfOffset, double& rfHalfWidth) const
+ {
+ if(nIndex >= maOffsets.size())
+ return;
+ const OffsetAndHalfWidthAndColor& rCandidate(maOffsets[nIndex]);
+ rfOffset = rCandidate.mfOffset;
+ rfHalfWidth = rCandidate.mfHalfWidth;
+ rColor = rCandidate.maColor;
+ }
+ };
+
+ class StyleVectorTable
+ {
+ private:
+ std::vector< StyleVectorCombination > maEntries;
+
+ public:
+ StyleVectorTable()
+ : maEntries()
+ {
+ }
+
+ void add(
+ const svx::frame::Style& rStyle,
+ const basegfx::B2DVector& rMyVector,
+ const basegfx::B2DVector& rOtherVector,
+ bool bMirrored)
+ {
+ if(rStyle.IsUsed() && !basegfx::areParallel(rMyVector, rOtherVector))
+ {
+ // create angle between both. angle() needs vectors pointing away from the same point,
+ // so take the mirrored one. Add F_PI to get from -pi..+pi to [0..F_PI2] for sorting
+ const double fAngle(basegfx::B2DVector(-rMyVector.getX(), -rMyVector.getY()).angle(rOtherVector) + F_PI);
+ maEntries.emplace_back(rStyle, rOtherVector, fAngle, bMirrored, nullptr);
+ }
+ }
+
+ void sort()
+ {
+ // sort inverse fom highest to lowest
+ std::sort(
+ maEntries.begin(),
+ maEntries.end(),
+ [](const StyleVectorCombination& a, const StyleVectorCombination& b)
+ { return a.getAngle() > b.getAngle(); });
+ }
+
+ bool empty() const { return maEntries.empty(); }
+ const std::vector< StyleVectorCombination >& getEntries() const{ return maEntries; }
+ };
+
+ struct CutSet
+ {
+ double mfOLML;
+ double mfORML;
+ double mfOLMR;
+ double mfORMR;
+
+ CutSet() : mfOLML(0.0), mfORML(0.0), mfOLMR(0.0), mfORMR(0.0)
+ {
+ }
+
+ bool operator<( const CutSet& rOther) const
+ {
+ const double fA(mfOLML + mfORML + mfOLMR + mfORMR);
+ const double fB(rOther.mfOLML + rOther.mfORML + rOther.mfOLMR + rOther.mfORMR);
+
+ return fA < fB;
+ }
+
+ double getSum() const { return mfOLML + mfORML + mfOLMR + mfORMR; }
+ };
+
+ void getCutSet(
+ CutSet& rCutSet,
+ const basegfx::B2DPoint& rLeft,
+ const basegfx::B2DPoint& rRight,
+ const basegfx::B2DVector& rX,
+ const basegfx::B2DPoint& rOtherLeft,
+ const basegfx::B2DPoint& rOtherRight,
+ const basegfx::B2DVector& rOtherX)
+ {
+ basegfx::tools::findCut(
+ rLeft,
+ rX,
+ rOtherLeft,
+ rOtherX,
+ CutFlagValue::LINE,
+ &rCutSet.mfOLML);
+
+ basegfx::tools::findCut(
+ rRight,
+ rX,
+ rOtherLeft,
+ rOtherX,
+ CutFlagValue::LINE,
+ &rCutSet.mfOLMR);
+
+ basegfx::tools::findCut(
+ rLeft,
+ rX,
+ rOtherRight,
+ rOtherX,
+ CutFlagValue::LINE,
+ &rCutSet.mfORML);
+
+ basegfx::tools::findCut(
+ rRight,
+ rX,
+ rOtherRight,
+ rOtherX,
+ CutFlagValue::LINE,
+ &rCutSet.mfORMR);
+ }
+
+ struct ExtendSet
+ {
+ double mfExtLeft;
+ double mfExtRight;
+
+ ExtendSet() : mfExtLeft(0.0), mfExtRight(0.0) {}
+ };
+
+ void getExtends(
+ std::vector<ExtendSet>& rExtendSet, // target Left/Right values to fill
+ const basegfx::B2DPoint& rOrigin, // own vector start
+ const StyleVectorCombination& rCombination, // own vector and offsets for lines
+ const basegfx::B2DVector& rPerpendX, // normalized perpendicular to own vector
+ const std::vector< StyleVectorCombination >& rStyleVector) // other vectors emerging in this point
+ {
+ if(!rCombination.empty() && !rStyleVector.empty() && rCombination.size() == rExtendSet.size())
+ {
+ const size_t nOffsetA(rCombination.size());
+
+ if(1 == nOffsetA)
+ {
+ Color aMyColor; double fMyOffset(0.0); double fMyHalfWidth(0.0);
+ rCombination.getColorAndOffsetAndHalfWidth(0, aMyColor, fMyOffset, fMyHalfWidth);
+
+ if(0xff != aMyColor.GetTransparency())
+ {
+ const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
+ const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
+ std::vector< CutSet > aCutSets;
+
+ for(const auto& rStyleCandidate : rStyleVector)
+ {
+ const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleCandidate.getB2DVector()));
+ const size_t nOffsetB(rStyleCandidate.size());
+
+ for(size_t other(0); other < nOffsetB; other++)
+ {
+ Color aOtherColor; double fOtherOffset(0.0); double fOtherHalfWidth(0.0);
+ rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
+
+ if(0xff != aOtherColor.GetTransparency())
+ {
+ const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
+ const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
+
+ CutSet aNewCutSet;
+ getCutSet(aNewCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
+ aCutSets.push_back(aNewCutSet);
+ }
+ }
+ }
+
+ if(!aCutSets.empty())
+ {
+ CutSet aCutSet(aCutSets[0]);
+ const size_t nNumCutSets(aCutSets.size());
+
+ if(1 != nNumCutSets)
+ {
+ double fCutSet(aCutSet.getSum());
+
+ for(size_t a(1); a < nNumCutSets; a++)
+ {
+ const CutSet& rCandidate(aCutSets[a]);
+ const double fCandidate(rCandidate.getSum());
+
+ if(basegfx::fTools::equalZero(fCandidate - fCutSet))
+ {
+ // both have equal center point, use medium cut
+ const double fNewOLML(std::max(std::min(rCandidate.mfOLML, rCandidate.mfORML), std::min(aCutSet.mfOLML, aCutSet.mfORML)));
+ const double fNewORML(std::min(std::max(rCandidate.mfOLML, rCandidate.mfORML), std::max(aCutSet.mfOLML, aCutSet.mfORML)));
+ const double fNewOLMR(std::max(std::min(rCandidate.mfOLMR, rCandidate.mfORMR), std::min(aCutSet.mfOLMR, aCutSet.mfORMR)));
+ const double fNewORMR(std::min(std::max(rCandidate.mfOLMR, rCandidate.mfORMR), std::max(aCutSet.mfOLMR, aCutSet.mfORMR)));
+ aCutSet.mfOLML = fNewOLML;
+ aCutSet.mfORML = fNewORML;
+ aCutSet.mfOLMR = fNewOLMR;
+ aCutSet.mfORMR = fNewORMR;
+ fCutSet = aCutSet.getSum();
+ }
+ else if(fCandidate < fCutSet)
+ {
+ // get minimum
+ fCutSet = fCandidate;
+ aCutSet = rCandidate;
+ }
+ }
+ }
+
+ ExtendSet& rExt(rExtendSet[0]);
+
+ rExt.mfExtLeft = std::min(aCutSet.mfOLML, aCutSet.mfORML);
+ rExt.mfExtRight = std::min(aCutSet.mfOLMR, aCutSet.mfORMR);
+ }
+ }
+ }
+ else
+ {
+ size_t nVisEdgeUp(0);
+ size_t nVisEdgeDn(0);
+
+ for(size_t my(0); my < nOffsetA; my++)
+ {
+ Color aMyColor; double fMyOffset(0.0); double fMyHalfWidth(0.0);
+ rCombination.getColorAndOffsetAndHalfWidth(my, aMyColor, fMyOffset, fMyHalfWidth);
+
+ if(0xff != aMyColor.GetTransparency())
+ {
+ const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
+ const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
+ const bool bUpper(my <= (nOffsetA >> 1));
+ const StyleVectorCombination& rStyleCandidate(bUpper ? rStyleVector.front() : rStyleVector.back());
+ const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleCandidate.getB2DVector()));
+ const size_t nOffsetB(rStyleCandidate.size());
+ std::vector< CutSet > aCutSets;
+
+ for(size_t other(0); other < nOffsetB; other++)
+ {
+ Color aOtherColor; double fOtherOffset(0.0); double fOtherHalfWidth(0.0);
+ rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
+
+ if(0xff != aOtherColor.GetTransparency())
+ {
+ const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
+ const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
+ CutSet aCutSet;
+ getCutSet(aCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
+ aCutSets.push_back(aCutSet);
+ }
+ }
+
+ if(!aCutSets.empty())
+ {
+ // sort: min to start, max to end
+ std::sort(aCutSets.begin(), aCutSets.end());
+ const bool bOtherUpper(rStyleCandidate.getAngle() > F_PI);
+
+ // check if we need min or max
+ // bUpper bOtherUpper MinMax
+ // t t max
+ // t f min
+ // f f max
+ // f t min
+ const bool bMax(bUpper == bOtherUpper);
+ size_t nBaseIndex(0);
+ const size_t nNumCutSets(aCutSets.size());
+
+ if(bMax)
+ {
+ // access at end
+ nBaseIndex = nNumCutSets - 1 - (bUpper ? nVisEdgeUp : nVisEdgeDn);
+ }
+ else
+ {
+ // access at start
+ nBaseIndex = bUpper ? nVisEdgeUp : nVisEdgeDn;
+ }
+
+ const size_t nSecuredIndex(std::min(nNumCutSets - 1, std::max(nBaseIndex, static_cast< size_t >(0))));
+ const CutSet& rCutSet(aCutSets[nSecuredIndex]);
+ ExtendSet& rExt(rExtendSet[my]);
+
+ rExt.mfExtLeft = std::min(rCutSet.mfOLML, rCutSet.mfORML);
+ rExt.mfExtRight = std::min(rCutSet.mfOLMR, rCutSet.mfORMR);
+ }
+
+ if(bUpper)
+ {
+ nVisEdgeUp++;
+ }
+ else
+ {
+ nVisEdgeDn++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Helper method to create the correct drawinglayer::primitive2d::BorderLinePrimitive2D
+ * for the given data, especially the correct drawinglayer::primitive2d::BorderLine entries
+ * including the correctly solved/created LineStartEnd extends
+ *
+ * rTarget : Here the evtl. created BorderLinePrimitive2D will be appended
+ * rOrigin : StartPoint of the Borderline
+ * rX : Vector of the Borderline
+ * rBorder : svx::frame::Style of the of the Borderline
+ * rStartStyleVectorTable : All other Borderlines which have to be taken into account because
+ * they have the same StartPoint as the current Borderline. These will be used to calculate
+ * the correct LineStartEnd extends tor the BorderLinePrimitive2D. The definition should be
+ * built up using svx::frame::StyleVectorTable and StyleVectorTable::add and includes:
+ * rStyle : the svx::frame::Style of one other BorderLine
+ * rMyVector : the Vector of the *new* to-be-defined BorderLine, identical to rX
+ * rOtherVector: the Vector of one other BorderLine (may be, but does not need to be normalized),
+ * always *pointing away* from the common StartPoint rOrigin
+ * bMirrored : define if rStyle of one other BorderLine shall be mirrored (e.g. bottom-right edges)
+ * With multiple BorderLines the definitions have to be CounterClockWise. This will be
+ * ensured by StyleVectorTable sorting the entries, but knowing this may allow more efficient
+ * data creation.
+ * rEndStyleVectorTable: All other BorderLines that have the same EndPoint. There are differences to
+ * the Start definitions:
+ * - do not forget to consequently use -rX for rMyVector
+ * - definitions have to be ClockWise for the EndBorderLines, will be ensured by sorting
+ *
+ * If you take all this into account, you will gett correctly extended BorderLinePrimitive2D
+ * representations for the new to be defined BorderLine. That extensions will overlap nicely
+ * with the corresponding BorderLines and take all multiple line definitions in the ::Style into
+ * account.
+ * The internal solver is *not limited* to ::Style(s) with three parts (Left/Gap/Right), this is
+ * just due to svx::frame::Style's definitions. A new solver based on this one can be created
+ * anytime using more mulötiple borders based on the more flexible
+ * std::vector< drawinglayer::primitive2d::BorderLine > if needed.
+ */
+ void CreateBorderPrimitives(
+ drawinglayer::primitive2d::Primitive2DContainer& rTarget, /// target for created primitives
+ const basegfx::B2DPoint& rOrigin, /// start point of borderline
+ const basegfx::B2DVector& rX, /// X-Axis of borderline with length
+ const svx::frame::Style& rBorder, /// Style of borderline
+ const StyleVectorTable& rStartStyleVectorTable, /// Styles and vectors (pointing away) at borderline start, ccw
+ const StyleVectorTable& rEndStyleVectorTable, /// Styles and vectors (pointing away) at borderline end, cw
+ const Color* pForceColor) /// If specified, overrides frame border color.
+ {
+ // get offset color pairs for style, one per visible line
+ const StyleVectorCombination aCombination(rBorder, rX, 0.0, false, pForceColor);
+
+ if(aCombination.empty())
+ return;
+
+ const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX));
+ const bool bHasStartStyles(!rStartStyleVectorTable.empty());
+ const bool bHasEndStyles(!rEndStyleVectorTable.empty());
+ const size_t nOffsets(aCombination.size());
+ std::vector<ExtendSet> aExtendSetStart(nOffsets);
+ std::vector<ExtendSet> aExtendSetEnd(nOffsets);
+
+ if(bHasStartStyles)
+ {
+ // create extends for line starts, use given point/vector and offsets
+ getExtends(aExtendSetStart, rOrigin, aCombination, aPerpendX, rStartStyleVectorTable.getEntries());
+ }
+
+ if(bHasEndStyles)
+ {
+ // Create extends for line ends, create inverse point/vector and inverse offsets.
+ const StyleVectorCombination aMirroredCombination(rBorder, -rX, 0.0, true, pForceColor);
+
+ getExtends(aExtendSetEnd, rOrigin + rX, aMirroredCombination, -aPerpendX, rEndStyleVectorTable.getEntries());
+
+ // also need to inverse the result to apply to the correct lines
+ std::reverse(aExtendSetEnd.begin(), aExtendSetEnd.end());
+ }
+
+ std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
+ const double fNegLength(-rX.getLength());
+
+ for(size_t a(0); a < nOffsets; a++)
+ {
+ Color aMyColor;
+ double fMyOffset(0.0);
+ double fMyHalfWidth(0.0);
+ aCombination.getColorAndOffsetAndHalfWidth(a, aMyColor, fMyOffset, fMyHalfWidth);
+ const ExtendSet& rExtStart(aExtendSetStart[a]);
+ const ExtendSet& rExtEnd(aExtendSetEnd[a]);
+
+ if(0xff == aMyColor.GetTransparency())
+ {
+ aBorderlines.push_back(
+ drawinglayer::primitive2d::BorderLine(
+ fMyHalfWidth * 2.0));
+ }
+ else
+ {
+ aBorderlines.push_back(
+ drawinglayer::primitive2d::BorderLine(
+ drawinglayer::attribute::LineAttribute(
+ aMyColor.getBColor(),
+ fMyHalfWidth * 2.0),
+ fNegLength * rExtStart.mfExtLeft,
+ fNegLength * rExtStart.mfExtRight,
+ fNegLength * rExtEnd.mfExtRight,
+ fNegLength * rExtEnd.mfExtLeft));
+ }
+ }
+
+ static double fPatScFact(10.0); // 10.0 multiply, see old code
+ const std::vector<double> aDashing(svtools::GetLineDashing(rBorder.Type(), rBorder.PatternScale() * fPatScFact));
+ const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing);
+ const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * aCombination.getRefModeOffset()));
+
+ rTarget.push_back(
+ drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::BorderLinePrimitive2D(
+ aStart,
+ aStart + rX,
+ aBorderlines,
+ aStrokeAttribute)));
+ }
+}
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ SdrFrameBorderData::SdrConnectStyleData::SdrConnectStyleData(
+ const svx::frame::Style& rStyle,
+ const basegfx::B2DVector& rNormalizedPerpendicular,
+ bool bStyleMirrored)
+ : maStyle(rStyle),
+ maNormalizedPerpendicular(rNormalizedPerpendicular),
+ mbStyleMirrored(bStyleMirrored)
+ {
+ }
+
+ SdrFrameBorderData::SdrFrameBorderData(
+ const basegfx::B2DPoint& rOrigin,
+ const basegfx::B2DVector& rX,
+ const svx::frame::Style& rStyle,
+ const Color* pForceColor)
+ : maOrigin(rOrigin),
+ maX(rX),
+ maStyle(rStyle),
+ maColor(nullptr != pForceColor ? *pForceColor : Color()),
+ mbForceColor(nullptr != pForceColor),
+ maStart(),
+ maEnd()
+ {
+ }
+
+ void SdrFrameBorderData::addSdrConnectStyleData(
+ bool bStart,
+ const svx::frame::Style& rStyle,
+ const basegfx::B2DVector& rNormalizedPerpendicular,
+ bool bStyleMirrored)
+ {
+ if(rStyle.IsUsed())
+ {
+ if(bStart)
+ {
+ maStart.emplace_back(rStyle, rNormalizedPerpendicular, bStyleMirrored);
+ }
+ else
+ {
+ maEnd.emplace_back(rStyle, rNormalizedPerpendicular, bStyleMirrored);
+ }
+ }
+ }
+
+ void SdrFrameBorderData::create2DDecomposition(Primitive2DContainer& rContainer) const
+ {
+ StyleVectorTable aStartVector;
+ StyleVectorTable aEndVector;
+ const basegfx::B2DVector aAxis(-maX);
+
+ for(const auto& rStart : maStart)
+ {
+ aStartVector.add(
+ rStart.getStyle(),
+ maX,
+ rStart.getNormalizedPerpendicular(),
+ rStart.getStyleMirrored());
+ }
+
+ for(const auto& rEnd : maEnd)
+ {
+ aEndVector.add(
+ rEnd.getStyle(),
+ aAxis,
+ rEnd.getNormalizedPerpendicular(),
+ rEnd.getStyleMirrored());
+ }
+
+ aStartVector.sort();
+ aEndVector.sort();
+
+ CreateBorderPrimitives(
+ rContainer,
+ maOrigin,
+ maX,
+ maStyle,
+ aStartVector,
+ aEndVector,
+ mbForceColor ? &maColor : nullptr);
+ }
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+namespace drawinglayer
+{
+ namespace primitive2d
+ {
+ Primitive2DContainer SdrFrameBorderPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*aViewInformation*/) const
+ {
+ Primitive2DContainer aRetval;
+
+ if(getMergeResult())
+ {
+ // decompose all buffered SdrFrameBorderData entries and try to merge them
+ // to reduce existing number of BorderLinePrimitive2D(s)
+ for(const auto& rCandidate : getFrameBorders())
+ {
+ // get decomposition on one SdrFrameBorderData entry
+ Primitive2DContainer aPartial;
+ rCandidate.create2DDecomposition(aPartial);
+
+ for(const auto& aCandidatePartial : aPartial)
+ {
+ if(aRetval.empty())
+ {
+ // no local data yet, just add as 1st entry, done
+ aRetval.push_back(aCandidatePartial);
+ }
+ else
+ {
+ bool bDidMerge(false);
+
+ for(auto& aCandidateRetval : aRetval)
+ {
+ // try to merge by appending new data to existing data
+ const drawinglayer::primitive2d::Primitive2DReference aMergeRetvalPartial(
+ drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(
+ aCandidateRetval,
+ aCandidatePartial));
+
+ if(aMergeRetvalPartial.is())
+ {
+ // could append, replace existing data with merged data, done
+ aCandidateRetval = aMergeRetvalPartial;
+ bDidMerge = true;
+ break;
+ }
+
+ // try to merge by appending existing data to new data
+ const drawinglayer::primitive2d::Primitive2DReference aMergePartialRetval(
+ drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(
+ aCandidatePartial,
+ aCandidateRetval));
+
+ if(aMergePartialRetval.is())
+ {
+ // could append, replace existing data with merged data, done
+ aCandidateRetval = aMergePartialRetval;
+ bDidMerge = true;
+ break;
+ }
+ }
+
+ if(!bDidMerge)
+ {
+ // no merge aftzer checking all existing data, append as new segment
+ aRetval.push_back(aCandidatePartial);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // just decompose all buffered SdrFrameBorderData entries, do not try to merge
+ for(const auto& rCandidate : getFrameBorders())
+ {
+ rCandidate.create2DDecomposition(aRetval);
+ }
+ }
+
+ return aRetval;
+ }
+
+ SdrFrameBorderPrimitive2D::SdrFrameBorderPrimitive2D(
+ std::shared_ptr<SdrFrameBorderDataVector>& rFrameBorders,
+ bool bMergeResult)
+ : BufferedDecompositionPrimitive2D(),
+ maFrameBorders(std::move(rFrameBorders)),
+ mbMergeResult(bMergeResult)
+ {
+ }
+
+ bool SdrFrameBorderPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
+ {
+ if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+ {
+ const SdrFrameBorderPrimitive2D& rCompare = static_cast<const SdrFrameBorderPrimitive2D&>(rPrimitive);
+
+ return maFrameBorders == rCompare.maFrameBorders;
+ }
+
+ return false;
+ }
+
+ // provide unique ID
+ ImplPrimitive2DIDBlock(SdrFrameBorderPrimitive2D, PRIMITIVE2D_ID_SDRFRAMEBORDERTPRIMITIVE2D)
+
+ } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 77a675329219..c8fcefe1a162 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -64,6 +64,7 @@
#include <colfrm.hxx>
#include <sw_primitivetypes2d.hxx>
+#include <svx/sdr/primitive2d/sdrframeborderprimitive2d.hxx>
#include <svx/sdr/contact/viewobjectcontactredirector.hxx>
#include <svx/sdr/contact/viewobjectcontact.hxx>
#include <svx/sdr/contact/viewcontact.hxx>
@@ -2380,8 +2381,10 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
aUpper.Pos() += pUpper->Frame().Pos();
SwRect aUpperAligned( aUpper );
::SwAlignRect( aUpperAligned, gProp.pSGlobalShell, &rDev );
- drawinglayer::primitive2d::Primitive2DContainer aHorizontalSequence;
- drawinglayer::primitive2d::Primitive2DContainer aVerticalSequence;
+
+ // prepare SdrFrameBorderDataVector
+ std::shared_ptr<drawinglayer::primitive2d::SdrFrameBorderDataVector> aData(
+ std::make_shared<drawinglayer::primitive2d::SdrFrameBorderDataVector>());
while ( true )
{
@@ -2519,30 +2522,20 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
if(!aX.equalZero())
{
const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(aX));
- svx::frame::StyleVectorTable aStartVector;
-
- aStartVector.add(aStyles[ 1 ], aX, -aY, true); // aLFromT
- aStartVector.add(aStyles[ 2 ], aX, -aX, true); // aLFromL
- aStartVector.add(aStyles[ 3 ], aX, aY, false); // aLFromB
- aStartVector.sort();
-
- svx::frame::StyleVectorTable aEndVector;
- const basegfx::B2DVector aAxis(-aX);
-
- aEndVector.add(aStyles[ 4 ], aAxis, -aY, true); // aRFromT
- aEndVector.add(aStyles[ 5 ], aAxis, aX, false); // aRFromR
- aEndVector.add(aStyles[ 6 ], aAxis, aY, false); // aRFromB
- aEndVector.sort();
-
- CreateBorderPrimitives(
- aHorizontalSequence,
+ aData->emplace_back(
aOrigin,
aX,
- aStyles[ 0 ],
- aStartVector,
- aEndVector,
- pTmpColor
- );
+ aStyles[0],
+ pTmpColor);
+ drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
+
+ rInstance.addSdrConnectStyleData(true, aStyles[1], -aY, true); // aLFromT
+ rInstance.addSdrConnectStyleData(true, aStyles[2], -aX, true); // aLFromL
+ rInstance.addSdrConnectStyleData(true, aStyles[3], aY, false); // aLFromB
+
+ rInstance.addSdrConnectStyleData(false, aStyles[4], -aY, true); // aRFromT
+ rInstance.addSdrConnectStyleData(false, aStyles[5], aX, false); // aRFromR
+ rInstance.addSdrConnectStyleData(false, aStyles[6], aY, false); // aRFromB
}
}
else // vertical
@@ -2553,30 +2546,20 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
if(!aX.equalZero())
{
const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(aX));
- svx::frame::StyleVectorTable aStartVector;
-
- aStartVector.add(aStyles[ 3 ], aX, -aY, false); // aTFromR
- aStartVector.add(aStyles[ 2 ], aX, -aX, true); // aTFromT
- aStartVector.add(aStyles[ 1 ], aX, aY, true); // aTFromL
- aStartVector.sort();
-
- svx::frame::StyleVectorTable aEndVector;
- const basegfx::B2DVector aAxis(-aX);
-
- aEndVector.add(aStyles[ 6 ], aAxis, -aY, false); // aBFromR
- aEndVector.add(aStyles[ 5 ], aAxis, aX, false); // aBFromB
- aEndVector.add(aStyles[ 4 ], aAxis, aY, true); // aBFromL
- aEndVector.sort();
-
- CreateBorderPrimitives(
- aVerticalSequence,
+ aData->emplace_back(
aOrigin,
aX,
- aStyles[ 0 ],
- aStartVector,
- aEndVector,
- pTmpColor
- );
+ aStyles[0],
+ pTmpColor);
+ drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
+
+ rInstance.addSdrConnectStyleData(true, aStyles[3], -aY, false); // aTFromR
+ rInstance.addSdrConnectStyleData(true, aStyles[2], -aX, true); // aTFromT
+ rInstance.addSdrConnectStyleData(true, aStyles[1], aY, true); // aTFromL
+
+ rInstance.addSdrConnectStyleData(false, aStyles[6], -aY, false); // aBFromR
+ rInstance.addSdrConnectStyleData(false, aStyles[5], aX, false); // aBFromB
+ rInstance.addSdrConnectStyleData(false, aStyles[4], aY, true); // aBFromL
}
}
}
@@ -2584,15 +2567,19 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
++aIter;
}
- // to stay compatible, create order as it was formally. Also try to
- // merge primitives as far as possible
- drawinglayer::primitive2d::Primitive2DContainer aSequence;
-
- svx::frame::HelperMergeInB2DPrimitiveArray(aHorizontalSequence, aSequence);
- svx::frame::HelperMergeInB2DPrimitiveArray(aVerticalSequence, aSequence);
-
- // paint
- mrTabFrame.ProcessPrimitives(aSequence);
+ // create instance of SdrFrameBorderPrimitive2D if
+ // SdrFrameBorderDataVector is used
+ if(!aData->empty())
+ {
+ drawinglayer::primitive2d::Primitive2DContainer aSequence;
+ aSequence.push_back(
+ drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::SdrFrameBorderPrimitive2D(
+ aData,
+ true)));
+ // paint
+ mrTabFrame.ProcessPrimitives(aSequence);
+ }
// restore output device:
rDev.SetDrawMode( nOldDrawMode );
@@ -4508,6 +4495,10 @@ namespace drawinglayer
basegfx::B2DPoint aBottomLeft(getB2DHomMatrix() * basegfx::B2DPoint(0.0, 1.0));
basegfx::B2DPoint aBottomRight(getB2DHomMatrix() * basegfx::B2DPoint(1.0, 1.0));
+ // prepare SdrFrameBorderDataVector
+ std::shared_ptr<drawinglayer::primitive2d::SdrFrameBorderDataVector> aData(
+ std::make_shared<drawinglayer::primitive2d::SdrFrameBorderDataVector>());
+
if(getStyleTop().IsUsed())
{
// move top left/right inwards half border width
@@ -4550,108 +4541,99 @@ namespace drawinglayer
{
// create BorderPrimitive(s) for top border
const basegfx::B2DVector aVector(aTopRight - aTopLeft);
- svx::frame::StyleVectorTable aStartStyleVectorTable;
- svx::frame::StyleVectorTable aEndStyleVectorTable;
+ aData->emplace_back(
+ aTopLeft,
+ aVector,
+ getStyleTop(),
+ nullptr);
+ drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
if(getStyleLeft().IsUsed())
{
- aStartStyleVectorTable.add(getStyleLeft(), aVector, basegfx::B2DVector(aBottomLeft - aTopLeft), false);
+ rInstance.addSdrConnectStyleData(true, getStyleLeft(), basegfx::B2DVector(aBottomLeft - aTopLeft), false);
}
if(getStyleRight().IsUsed())
{
- aEndStyleVectorTable.add(getStyleRight(), -aVector, basegfx::B2DVector(aBottomRight - aTopRight), false);
+ rInstance.addSdrConnectStyleData(false, getStyleRight(), basegfx::B2DVector(aBottomRight - aTopRight), false);
}
-
- CreateBorderPrimitives(
- aRetval,
- aTopLeft,
- aVector,
- getStyleTop(),
- aStartStyleVectorTable,
- aEndStyleVectorTable,
- nullptr);
}
if(getStyleRight().IsUsed())
{
// create BorderPrimitive(s) for right border
const basegfx::B2DVector aVector(aBottomRight - aTopRight);
- svx::frame::StyleVectorTable aStartStyleVectorTable;
- svx::frame::StyleVectorTable aEndStyleVectorTable;
+ aData->emplace_back(
+ aTopRight,
+ aVector,
+ getStyleRight(),
+ nullptr);
+ drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
if(getStyleTop().IsUsed())
{
- aStartStyleVectorTable.add(getStyleTop(), aVector, basegfx::B2DVector(aTopLeft - aTopRight), false);
+ rInstance.addSdrConnectStyleData(true, getStyleTop(), basegfx::B2DVector(aTopLeft - aTopRight), false);
}
if(getStyleBottom().IsUsed())
{
- aEndStyleVectorTable.add(getStyleBottom(), -aVector, basegfx::B2DVector(aBottomLeft - aBottomRight), false);
+ rInstance.addSdrConnectStyleData(false, getStyleBottom(), basegfx::B2DVector(aBottomLeft - aBottomRight), false);
}
-
- CreateBorderPrimitives(
- aRetval,
- aTopRight,
- aVector,
- getStyleRight(),
- aStartStyleVectorTable,
- aEndStyleVectorTable,
- nullptr);
}
if(getStyleBottom().IsUsed())
{
// create BorderPrimitive(s) for bottom border
const basegfx::B2DVector aVector(aBottomLeft - aBottomRight);
- svx::frame::StyleVectorTable aStartStyleVectorTable;
- svx::frame::StyleVectorTable aEndStyleVectorTable;
+ aData->emplace_back(
+ aBottomRight,
+ aVector,
+ getStyleBottom(),
+ nullptr);
+ drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
if(getStyleRight().IsUsed())
{
- aStartStyleVectorTable.add(getStyleRight(), aVector, basegfx::B2DVector(aTopRight - aBottomRight), false);
+ rInstance.addSdrConnectStyleData(true, getStyleRight(), basegfx::B2DVector(aTopRight - aBottomRight), false);
}
if(getStyleLeft().IsUsed())
{
- aEndStyleVectorTable.add(getStyleLeft(), -aVector, basegfx::B2DVector(aTopLeft - aBottomLeft), false);
+ rInstance.addSdrConnectStyleData(false, getStyleLeft(), basegfx::B2DVector(aTopLeft - aBottomLeft), false);
}
-
- CreateBorderPrimitives(
- aRetval,
- aBottomRight,
- aVector,
- getStyleBottom(),
- aStartStyleVectorTable,
- aEndStyleVectorTable,
- nullptr);
}
if(getStyleLeft().IsUsed())
{
// create BorderPrimitive(s) for left border
const basegfx::B2DVector aVector(aTopLeft - aBottomLeft);
- svx::frame::StyleVectorTable aStartStyleVectorTable;
- svx::frame::StyleVectorTable aEndStyleVectorTable;
+ aData->emplace_back(
+ aBottomLeft,
+ aVector,
+ getStyleLeft(),
+ nullptr);
+ drawinglayer::primitive2d::SdrFrameBorderData& rInstance(aData->back());
if(getStyleBottom().IsUsed())
{
- aStartStyleVectorTable.add(getStyleBottom(), aVector, basegfx::B2DVector(aBottomRight - aBottomLeft), false);
+ rInstance.addSdrConnectStyleData(true, getStyleBottom(), basegfx::B2DVector(aBottomRight - aBottomLeft), false);
}
if(getStyleTop().IsUsed())
{
- aEndStyleVectorTable.add(getStyleTop(), -aVector, basegfx::B2DVector(aTopRight - aTopLeft), false);
+ rInstance.addSdrConnectStyleData(false, getStyleTop(), basegfx::B2DVector(aTopRight - aTopLeft), false);
}
+ }
- CreateBorderPrimitives(
- aRetval,
- aBottomLeft,
- aVector,
- getStyleLeft(),
- aStartStyleVectorTable,
- aEndStyleVectorTable,
- nullptr);
+ // create instance of SdrFrameBorderPrimitive2D if
+ // SdrFrameBorderDataVector is used
+ if(!aData->empty())
+ {
+ aRetval.push_back(
+ drawinglayer::primitive2d::Primitive2DReference(
+ new drawinglayer::primitive2d::SdrFrameBorderPrimitive2D(
+ aData,
+ true)));
}
return aRetval;
More information about the Libreoffice-commits
mailing list