29 double snapToDiscreteUnit(
31 double fMinimalDiscreteUnit)
35 fValue = std::max(fValue, fMinimalDiscreteUnit);
41 class StyleVectorCombination
44 struct OffsetAndHalfWidthAndColor
50 OffsetAndHalfWidthAndColor(
double offset,
double halfWidth,
Color color) :
52 mfHalfWidth(halfWidth),
57 double mfRefModeOffset;
60 std::vector< OffsetAndHalfWidthAndColor >
maOffsets;
63 StyleVectorCombination(
68 const Color* pForceColor,
69 double fMinimalDiscreteUnit)
70 : mfRefModeOffset(0.0),
71 maB2DVector(rB2DVector),
80 const bool bSecnUsed(0.0 != rStyle.
Secn());
85 double fPrim(snapToDiscreteUnit(rStyle.
Prim(), fMinimalDiscreteUnit));
86 const double fDist(snapToDiscreteUnit(rStyle.
Dist(), fMinimalDiscreteUnit));
87 double fSecn(snapToDiscreteUnit(rStyle.
Secn(), fMinimalDiscreteUnit));
91 const double fStyleWidth(fPrim + fDist + fSecn);
104 std::swap(aPrim, aSecn);
105 std::swap(fPrim, fSecn);
111 const double fHalfWidth(fStyleWidth * 0.5);
116 mfRefModeOffset = fHalfWidth;
121 mfRefModeOffset = -fHalfWidth;
130 const bool bSecnTransparent(aSecn.IsFullyTransparent());
132 if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent)
134 const double a(mfRefModeOffset - (fStyleWidth * 0.5));
135 const double b(a + fPrim);
136 const double c(b + fDist);
137 const double d(c + fSecn);
140 OffsetAndHalfWidthAndColor(
143 nullptr != pForceColor ? *pForceColor : aPrim));
146 OffsetAndHalfWidthAndColor(
150 ? (
nullptr != pForceColor ? *pForceColor : rStyle.
GetColorGap())
154 OffsetAndHalfWidthAndColor(
157 nullptr != pForceColor ? *pForceColor : aSecn));
166 OffsetAndHalfWidthAndColor(
169 nullptr != pForceColor ? *pForceColor : aPrim));
174 double getRefModeOffset()
const {
return mfRefModeOffset; }
176 double getAngle()
const {
return mfAngle; }
177 bool empty()
const {
return maOffsets.empty(); }
180 void getColorAndOffsetAndHalfWidth(
size_t nIndex,
Color& rColor,
double& rfOffset,
double& rfHalfWidth)
const
184 const OffsetAndHalfWidthAndColor& rCandidate(maOffsets[nIndex]);
185 rfOffset = rCandidate.mfOffset;
186 rfHalfWidth = rCandidate.mfHalfWidth;
187 rColor = rCandidate.maColor;
191 class StyleVectorTable
194 std::vector< StyleVectorCombination > maEntries;
206 double fMinimalDiscreteUnit)
214 maEntries.emplace_back(
220 fMinimalDiscreteUnit);
229 [](
const StyleVectorCombination& a,
const StyleVectorCombination& b)
230 { return a.getAngle() > b.getAngle(); });
233 bool empty()
const {
return maEntries.empty(); }
234 const std::vector< StyleVectorCombination >& getEntries()
const{
return maEntries; }
244 CutSet() : mfOLML(0.0), mfORML(0.0), mfOLMR(0.0), mfORMR(0.0)
248 bool operator<(
const CutSet& rOther)
const
250 const double fA(mfOLML + mfORML + mfOLMR + mfORMR);
251 const double fB(rOther.mfOLML + rOther.mfORML + rOther.mfOLMR + rOther.mfORMR);
256 double getSum()
const {
return mfOLML + mfORML + mfOLMR + mfORMR; }
306 ExtendSet() : mfExtLeft(0.0), mfExtRight(0.0) {}
310 std::vector<ExtendSet>& rExtendSet,
312 const StyleVectorCombination& rCombination,
314 const std::vector< StyleVectorCombination >& rStyleVector)
316 if(!(!rCombination.empty() && !rStyleVector.empty() && rCombination.size() == rExtendSet.size()))
319 const size_t nOffsetA(rCombination.size());
323 Color aMyColor;
double fMyOffset(0.0);
double fMyHalfWidth(0.0);
324 rCombination.getColorAndOffsetAndHalfWidth(0, aMyColor, fMyOffset, fMyHalfWidth);
328 const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
329 const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
330 std::vector< CutSet > aCutSets;
332 for(
const auto& rStyleCandidate : rStyleVector)
335 const size_t nOffsetB(rStyleCandidate.size());
337 for(
size_t other(0); other < nOffsetB; other++)
339 Color aOtherColor;
double fOtherOffset(0.0);
double fOtherHalfWidth(0.0);
340 rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
344 const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
345 const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
348 getCutSet(aNewCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
349 aCutSets.push_back(aNewCutSet);
354 if(!aCutSets.empty())
356 CutSet aCutSet(aCutSets[0]);
357 const size_t nNumCutSets(aCutSets.size());
361 double fCutSet(aCutSet.getSum());
363 for(
size_t a(1);
a < nNumCutSets;
a++)
365 const CutSet& rCandidate(aCutSets[a]);
366 const double fCandidate(rCandidate.getSum());
371 const double fNewOLML(std::max(std::min(rCandidate.mfOLML, rCandidate.mfORML), std::min(aCutSet.mfOLML, aCutSet.mfORML)));
372 const double fNewORML(std::min(std::max(rCandidate.mfOLML, rCandidate.mfORML), std::max(aCutSet.mfOLML, aCutSet.mfORML)));
373 const double fNewOLMR(std::max(std::min(rCandidate.mfOLMR, rCandidate.mfORMR), std::min(aCutSet.mfOLMR, aCutSet.mfORMR)));
374 const double fNewORMR(std::min(std::max(rCandidate.mfOLMR, rCandidate.mfORMR), std::max(aCutSet.mfOLMR, aCutSet.mfORMR)));
375 aCutSet.mfOLML = fNewOLML;
376 aCutSet.mfORML = fNewORML;
377 aCutSet.mfOLMR = fNewOLMR;
378 aCutSet.mfORMR = fNewORMR;
379 fCutSet = aCutSet.getSum();
381 else if(fCandidate < fCutSet)
384 fCutSet = fCandidate;
385 aCutSet = rCandidate;
390 ExtendSet& rExt(rExtendSet[0]);
392 rExt.mfExtLeft = std::min(aCutSet.mfOLML, aCutSet.mfORML);
393 rExt.mfExtRight = std::min(aCutSet.mfOLMR, aCutSet.mfORMR);
399 size_t nVisEdgeUp(0);
400 size_t nVisEdgeDn(0);
402 for(
size_t my(0); my < nOffsetA; my++)
404 Color aMyColor;
double fMyOffset(0.0);
double fMyHalfWidth(0.0);
405 rCombination.getColorAndOffsetAndHalfWidth(my, aMyColor, fMyOffset, fMyHalfWidth);
409 const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
410 const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
411 const bool bUpper(my <= (nOffsetA >> 1));
412 const StyleVectorCombination& rStyleCandidate(bUpper ? rStyleVector.front() : rStyleVector.back());
414 const size_t nOffsetB(rStyleCandidate.size());
415 std::vector< CutSet > aCutSets;
417 for(
size_t other(0); other < nOffsetB; other++)
419 Color aOtherColor;
double fOtherOffset(0.0);
double fOtherHalfWidth(0.0);
420 rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
424 const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
425 const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
427 getCutSet(aCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
428 aCutSets.push_back(aCutSet);
432 if(!aCutSets.empty())
435 std::sort(aCutSets.begin(), aCutSets.end());
436 const bool bOtherUpper(rStyleCandidate.getAngle() > M_PI);
444 const bool bMax(bUpper == bOtherUpper);
445 size_t nBaseIndex(0);
446 const size_t nNumCutSets(aCutSets.size());
451 nBaseIndex = nNumCutSets - 1 - (bUpper ? nVisEdgeUp : nVisEdgeDn);
456 nBaseIndex = bUpper ? nVisEdgeUp : nVisEdgeDn;
459 const size_t nSecuredIndex(std::clamp(nBaseIndex,
size_t(0),
size_t(nNumCutSets - 1)));
460 const CutSet& rCutSet(aCutSets[nSecuredIndex]);
461 ExtendSet& rExt(rExtendSet[my]);
463 rExt.mfExtLeft = std::min(rCutSet.mfOLML, rCutSet.mfORML);
464 rExt.mfExtRight = std::min(rCutSet.mfOLMR, rCutSet.mfORMR);
515 void CreateBorderPrimitives(
520 const StyleVectorTable& rStartStyleVectorTable,
521 const StyleVectorTable& rEndStyleVectorTable,
522 const Color* pForceColor,
523 double fMinimalDiscreteUnit)
526 const StyleVectorCombination aCombination(
532 fMinimalDiscreteUnit);
534 if(aCombination.empty())
538 const bool bHasStartStyles(!rStartStyleVectorTable.empty());
539 const bool bHasEndStyles(!rEndStyleVectorTable.empty());
540 const size_t nOffsets(aCombination.size());
541 std::vector<ExtendSet> aExtendSetStart(nOffsets);
542 std::vector<ExtendSet> aExtendSetEnd(nOffsets);
547 getExtends(aExtendSetStart, rOrigin, aCombination, aPerpendX, rStartStyleVectorTable.getEntries());
553 const StyleVectorCombination aMirroredCombination(
559 fMinimalDiscreteUnit);
561 getExtends(aExtendSetEnd, rOrigin + rX, aMirroredCombination, -aPerpendX, rEndStyleVectorTable.getEntries());
564 std::reverse(aExtendSetEnd.begin(), aExtendSetEnd.end());
567 std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
568 const double fNegLength(-rX.
getLength());
570 for(
size_t a(0);
a < nOffsets;
a++)
573 double fMyOffset(0.0);
574 double fMyHalfWidth(0.0);
575 aCombination.getColorAndOffsetAndHalfWidth(a, aMyColor, fMyOffset, fMyHalfWidth);
576 const ExtendSet& rExtStart(aExtendSetStart[a]);
577 const ExtendSet& rExtEnd(aExtendSetEnd[a]);
581 aBorderlines.push_back(
583 fMyHalfWidth * 2.0));
587 aBorderlines.push_back(
592 fNegLength * rExtStart.mfExtLeft,
593 fNegLength * rExtStart.mfExtRight,
594 fNegLength * rExtEnd.mfExtRight,
595 fNegLength * rExtEnd.mfExtLeft));
599 static const double fPatScFact(10.0);
602 const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * aCombination.getRefModeOffset()));
609 std::move(aBorderlines),
610 std::move(aStrokeAttribute))));
613 double getMinimalNonZeroValue(
double fCurrent,
double fNew)
619 fCurrent = std::min(fNew, fCurrent);
630 double getMinimalNonZeroBorderWidthFromStyle(
double fCurrent,
const svx::frame::Style& rStyle)
634 fCurrent = getMinimalNonZeroValue(fCurrent, rStyle.
Prim());
635 fCurrent = getMinimalNonZeroValue(fCurrent, rStyle.
Dist());
636 fCurrent = getMinimalNonZeroValue(fCurrent, rStyle.
Secn());
650 maNormalizedPerpendicular(rNormalizedPerpendicular),
651 mbStyleMirrored(bStyleMirrored)
666 const Color* pForceColor)
670 maColor(nullptr != pForceColor ? *pForceColor :
Color()),
685 maStart.emplace_back(rStyle, rNormalizedPerpendicular, bStyleMirrored);
689 maEnd.emplace_back(rStyle, rNormalizedPerpendicular, bStyleMirrored);
696 double fMinimalDiscreteUnit)
const
698 StyleVectorTable aStartVector;
699 StyleVectorTable aEndVector;
702 for(
const auto& rStart :
maStart)
707 rStart.getNormalizedPerpendicular(),
708 rStart.getStyleMirrored(),
709 fMinimalDiscreteUnit);
712 for(
const auto& rEnd :
maEnd)
717 rEnd.getNormalizedPerpendicular(),
718 rEnd.getStyleMirrored(),
719 fMinimalDiscreteUnit);
725 CreateBorderPrimitives(
733 fMinimalDiscreteUnit);
738 double fRetval(getMinimalNonZeroBorderWidthFromStyle(0.0,
maStyle));
740 for(
const auto& rStart :
maStart)
742 fRetval = getMinimalNonZeroBorderWidthFromStyle(fRetval, rStart.getStyle());
745 for(
const auto& rEnd :
maEnd)
747 fRetval = getMinimalNonZeroBorderWidthFromStyle(fRetval, rEnd.getStyle());
790 rCandidate.create2DDecomposition(
792 fMinimalDiscreteUnit);
794 for(
const auto& aCandidatePartial : aPartial)
799 aRetval.
append(aCandidatePartial);
803 bool bDidMerge(
false);
805 for(
auto& aCandidateRetval : aRetval)
813 if(aMergeRetvalPartial.is())
816 aCandidateRetval = aMergeRetvalPartial;
827 if(aMergePartialRetval.is())
830 aCandidateRetval = aMergePartialRetval;
839 aRetval.append(aCandidatePartial);
846 rContainer.
append(std::move(aRetval));
851 bool bForceToSingleDiscreteUnit)
852 : maFrameBorders(
std::move(rFrameBorders)),
853 mfMinimalNonZeroBorderWidth(0.0),
854 mfMinimalNonZeroBorderWidthUsedForDecompose(0.0),
855 mbForceToSingleDiscreteUnit(bForceToSingleDiscreteUnit)
864 rCandidate.getMinimalNonZeroBorderWidth());
871 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
890 double fDiscreteUnit(std::min(fabs(aDiscreteVector.
getX()), fabs(aDiscreteVector.
getY())));
bool IsFullyTransparent() const
basegfx::BColor getBColor() const
double angle(const B2DVector &rVec) const
const Primitive2DContainer & getBuffered2DDecomposition() const
void setBuffered2DDecomposition(Primitive2DContainer &&rNew)
virtual void get2DDecomposition(Primitive2DDecompositionVisitor &rVisitor, const geometry::ViewInformation2D &rViewInformation) const override
void append(const Primitive2DReference &)
svx::frame::Style maStyle
basegfx::B2DVector maNormalizedPerpendicular
bool operator==(const SdrConnectStyleData &rCompare) const
SdrConnectStyleData(const svx::frame::Style &rStyle, const basegfx::B2DVector &rNormalizedPerpendicular, bool bStyleMirrored)
void create2DDecomposition(Primitive2DContainer &rContainer, double fMinDiscreteUnit) const
basegfx::B2DVector maX
start point of borderline
svx::frame::Style maStyle
X-Axis of borderline with length.
SdrFrameBorderData(const basegfx::B2DPoint &rOrigin, const basegfx::B2DVector &rX, const svx::frame::Style &rStyle, const Color *pForceColor)
std::vector< SdrConnectStyleData > maStart
std::vector< SdrConnectStyleData > maEnd
void addSdrConnectStyleData(bool bStart, const svx::frame::Style &rStyle, const basegfx::B2DVector &rNormalizedPerpendicular, bool bStyleMirrored)
double getMinimalNonZeroBorderWidth() const
bool operator==(const SdrFrameBorderData &rCompare) const
Color maColor
Style of borderline.
basegfx::B2DPoint maOrigin
virtual bool operator==(const BasePrimitive2D &rPrimitive) const override
bool doForceToSingleDiscreteUnit() const
const SdrFrameBorderDataVector & getFrameBorders() const
virtual sal_uInt32 getPrimitive2DID() const override
double mfMinimalNonZeroBorderWidthUsedForDecompose
SdrFrameBorderPrimitive2D(SdrFrameBorderDataVector &&rFrameBorders, bool bForceToSingleDiscreteUnit)
virtual void get2DDecomposition(Primitive2DDecompositionVisitor &rVisitor, const geometry::ViewInformation2D &rViewInformation) const override
double mfMinimalNonZeroBorderWidth
virtual void create2DDecomposition(Primitive2DContainer &rContainer, const geometry::ViewInformation2D &aViewInformation) const override
Contains the widths of primary and secondary line of a frame style.
Color GetColorGap() const
Color GetColorSecn() const
Color GetColorPrim() const
RefMode GetRefMode() const
SvxBorderLineStyle Type() const
bool IsUsed() const
Check if this style is used - this depends on it having any width definition.
double PatternScale() const
CutFlagValue findCut(const B2DPoint &rEdge1Start, const B2DVector &rEdge1Delta, const B2DPoint &rEdge2Start, const B2DVector &rEdge2Delta, CutFlagValue aCutFlags, double *pCut1, double *pCut2)
bool areParallel(const B2DVector &rVecA, const B2DVector &rVecB)
B2DVector getNormalizedPerpendicular(const B2DVector &rVec)
Primitive2DReference tryMergeBorderLinePrimitive2D(const BorderLinePrimitive2D *pCandidateA, const BorderLinePrimitive2D *pCandidateB)
std::vector< SdrFrameBorderData > SdrFrameBorderDataVector
RefMode
Specifies how the reference points for frame borders are used.
@ Begin
The reference points specify the begin of the frame border width.
@ End
The reference points specify the end of the frame border width.
@ Centered
Frame borders are drawn centered to the reference points.
#define PRIMITIVE2D_ID_SDRFRAMEBORDERTPRIMITIVE2D
const uno::Sequence< double > maOffsets
bool operator<(const Subset &rLHS, const Subset &rRHS)