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),
81 const bool bSecnUsed(0.0 != rStyle.
Secn());
86 double fPrim(snapToDiscreteUnit(rStyle.
Prim(), fMinimalDiscreteUnit));
87 const double fDist(snapToDiscreteUnit(rStyle.
Dist(), fMinimalDiscreteUnit));
88 double fSecn(snapToDiscreteUnit(rStyle.
Secn(), fMinimalDiscreteUnit));
92 const double fStyleWidth(fPrim + fDist + fSecn);
105 std::swap(aPrim, aSecn);
106 std::swap(fPrim, fSecn);
112 const double fHalfWidth(fStyleWidth * 0.5);
117 mfRefModeOffset = fHalfWidth;
122 mfRefModeOffset = -fHalfWidth;
131 const bool bSecnTransparent(aSecn.IsFullyTransparent());
133 if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent)
135 const double a(mfRefModeOffset - (fStyleWidth * 0.5));
136 const double b(a + fPrim);
137 const double c(b + fDist);
138 const double d(c + fSecn);
141 OffsetAndHalfWidthAndColor(
144 nullptr != pForceColor ? *pForceColor : aPrim));
147 OffsetAndHalfWidthAndColor(
151 ? (
nullptr != pForceColor ? *pForceColor : rStyle.
GetColorGap())
155 OffsetAndHalfWidthAndColor(
158 nullptr != pForceColor ? *pForceColor : aSecn));
167 OffsetAndHalfWidthAndColor(
170 nullptr != pForceColor ? *pForceColor : aPrim));
175 double getRefModeOffset()
const {
return mfRefModeOffset; }
177 double getAngle()
const {
return mfAngle; }
178 bool empty()
const {
return maOffsets.empty(); }
179 size_t size()
const {
return maOffsets.size(); }
181 void getColorAndOffsetAndHalfWidth(
size_t nIndex,
Color& rColor,
double& rfOffset,
double& rfHalfWidth)
const
183 if(nIndex >= maOffsets.size())
185 const OffsetAndHalfWidthAndColor& rCandidate(maOffsets[nIndex]);
186 rfOffset = rCandidate.mfOffset;
187 rfHalfWidth = rCandidate.mfHalfWidth;
188 rColor = rCandidate.maColor;
192 class StyleVectorTable
195 std::vector< StyleVectorCombination > maEntries;
208 double fMinimalDiscreteUnit)
216 maEntries.emplace_back(
222 fMinimalDiscreteUnit);
231 [](
const StyleVectorCombination&
a,
const StyleVectorCombination& b)
232 {
return a.getAngle() > b.getAngle(); });
235 bool empty()
const {
return maEntries.empty(); }
236 const std::vector< StyleVectorCombination >& getEntries()
const{
return maEntries; }
246 CutSet() : mfOLML(0.0), mfORML(0.0), mfOLMR(0.0), mfORMR(0.0)
250 bool operator<(
const CutSet& rOther)
const
252 const double fA(mfOLML + mfORML + mfOLMR + mfORMR);
253 const double fB(rOther.mfOLML + rOther.mfORML + rOther.mfOLMR + rOther.mfORMR);
258 double getSum()
const {
return mfOLML + mfORML + mfOLMR + mfORMR; }
308 ExtendSet() : mfExtLeft(0.0), mfExtRight(0.0) {}
312 std::vector<ExtendSet>& rExtendSet,
314 const StyleVectorCombination& rCombination,
316 const std::vector< StyleVectorCombination >& rStyleVector)
318 if(!(!rCombination.empty() && !rStyleVector.empty() && rCombination.size() == rExtendSet.size()))
321 const size_t nOffsetA(rCombination.size());
325 Color aMyColor;
double fMyOffset(0.0);
double fMyHalfWidth(0.0);
326 rCombination.getColorAndOffsetAndHalfWidth(0, aMyColor, fMyOffset, fMyHalfWidth);
330 const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
331 const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
332 std::vector< CutSet > aCutSets;
334 for(
const auto& rStyleCandidate : rStyleVector)
337 const size_t nOffsetB(rStyleCandidate.size());
339 for(
size_t other(0); other < nOffsetB; other++)
341 Color aOtherColor;
double fOtherOffset(0.0);
double fOtherHalfWidth(0.0);
342 rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
346 const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
347 const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
350 getCutSet(aNewCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
351 aCutSets.push_back(aNewCutSet);
356 if(!aCutSets.empty())
358 CutSet aCutSet(aCutSets[0]);
359 const size_t nNumCutSets(aCutSets.size());
363 double fCutSet(aCutSet.getSum());
365 for(
size_t a(1); a < nNumCutSets; a++)
367 const CutSet& rCandidate(aCutSets[a]);
368 const double fCandidate(rCandidate.getSum());
373 const double fNewOLML(std::max(std::min(rCandidate.mfOLML, rCandidate.mfORML), std::min(aCutSet.mfOLML, aCutSet.mfORML)));
374 const double fNewORML(std::min(std::max(rCandidate.mfOLML, rCandidate.mfORML), std::max(aCutSet.mfOLML, aCutSet.mfORML)));
375 const double fNewOLMR(std::max(std::min(rCandidate.mfOLMR, rCandidate.mfORMR), std::min(aCutSet.mfOLMR, aCutSet.mfORMR)));
376 const double fNewORMR(std::min(std::max(rCandidate.mfOLMR, rCandidate.mfORMR), std::max(aCutSet.mfOLMR, aCutSet.mfORMR)));
377 aCutSet.mfOLML = fNewOLML;
378 aCutSet.mfORML = fNewORML;
379 aCutSet.mfOLMR = fNewOLMR;
380 aCutSet.mfORMR = fNewORMR;
381 fCutSet = aCutSet.getSum();
383 else if(fCandidate < fCutSet)
386 fCutSet = fCandidate;
387 aCutSet = rCandidate;
392 ExtendSet& rExt(rExtendSet[0]);
394 rExt.mfExtLeft = std::min(aCutSet.mfOLML, aCutSet.mfORML);
395 rExt.mfExtRight = std::min(aCutSet.mfOLMR, aCutSet.mfORMR);
401 size_t nVisEdgeUp(0);
402 size_t nVisEdgeDn(0);
404 for(
size_t my(0); my < nOffsetA; my++)
406 Color aMyColor;
double fMyOffset(0.0);
double fMyHalfWidth(0.0);
407 rCombination.getColorAndOffsetAndHalfWidth(my, aMyColor, fMyOffset, fMyHalfWidth);
411 const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (fMyOffset - fMyHalfWidth)));
412 const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (fMyOffset + fMyHalfWidth)));
413 const bool bUpper(my <= (nOffsetA >> 1));
414 const StyleVectorCombination& rStyleCandidate(bUpper ? rStyleVector.front() : rStyleVector.back());
416 const size_t nOffsetB(rStyleCandidate.size());
417 std::vector< CutSet > aCutSets;
419 for(
size_t other(0); other < nOffsetB; other++)
421 Color aOtherColor;
double fOtherOffset(0.0);
double fOtherHalfWidth(0.0);
422 rStyleCandidate.getColorAndOffsetAndHalfWidth(other, aOtherColor, fOtherOffset, fOtherHalfWidth);
426 const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (fOtherOffset - fOtherHalfWidth)));
427 const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (fOtherOffset + fOtherHalfWidth)));
429 getCutSet(aCutSet, aLeft, aRight, rCombination.getB2DVector(), aOtherLeft, aOtherRight, rStyleCandidate.getB2DVector());
430 aCutSets.push_back(aCutSet);
434 if(!aCutSets.empty())
437 std::sort(aCutSets.begin(), aCutSets.end());
438 const bool bOtherUpper(rStyleCandidate.getAngle() >
F_PI);
446 const bool bMax(bUpper == bOtherUpper);
447 size_t nBaseIndex(0);
448 const size_t nNumCutSets(aCutSets.size());
453 nBaseIndex = nNumCutSets - 1 - (bUpper ? nVisEdgeUp : nVisEdgeDn);
458 nBaseIndex = bUpper ? nVisEdgeUp : nVisEdgeDn;
461 const size_t nSecuredIndex(std::clamp(nBaseIndex,
size_t(0),
size_t(nNumCutSets - 1)));
462 const CutSet& rCutSet(aCutSets[nSecuredIndex]);
463 ExtendSet& rExt(rExtendSet[my]);
465 rExt.mfExtLeft = std::min(rCutSet.mfOLML, rCutSet.mfORML);
466 rExt.mfExtRight = std::min(rCutSet.mfOLMR, rCutSet.mfORMR);
517 void CreateBorderPrimitives(
522 const StyleVectorTable& rStartStyleVectorTable,
523 const StyleVectorTable& rEndStyleVectorTable,
524 const Color* pForceColor,
525 double fMinimalDiscreteUnit)
528 const StyleVectorCombination aCombination(
534 fMinimalDiscreteUnit);
536 if(aCombination.empty())
540 const bool bHasStartStyles(!rStartStyleVectorTable.empty());
541 const bool bHasEndStyles(!rEndStyleVectorTable.empty());
542 const size_t nOffsets(aCombination.size());
543 std::vector<ExtendSet> aExtendSetStart(nOffsets);
544 std::vector<ExtendSet> aExtendSetEnd(nOffsets);
549 getExtends(aExtendSetStart, rOrigin, aCombination, aPerpendX, rStartStyleVectorTable.getEntries());
555 const StyleVectorCombination aMirroredCombination(
561 fMinimalDiscreteUnit);
563 getExtends(aExtendSetEnd, rOrigin + rX, aMirroredCombination, -aPerpendX, rEndStyleVectorTable.getEntries());
566 std::reverse(aExtendSetEnd.begin(), aExtendSetEnd.end());
569 std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
570 const double fNegLength(-rX.
getLength());
572 for(
size_t a(0); a < nOffsets; a++)
575 double fMyOffset(0.0);
576 double fMyHalfWidth(0.0);
577 aCombination.getColorAndOffsetAndHalfWidth(a, aMyColor, fMyOffset, fMyHalfWidth);
578 const ExtendSet& rExtStart(aExtendSetStart[a]);
579 const ExtendSet& rExtEnd(aExtendSetEnd[a]);
583 aBorderlines.push_back(
585 fMyHalfWidth * 2.0));
589 aBorderlines.push_back(
594 fNegLength * rExtStart.mfExtLeft,
595 fNegLength * rExtStart.mfExtRight,
596 fNegLength * rExtEnd.mfExtRight,
597 fNegLength * rExtEnd.mfExtLeft));
601 static const double fPatScFact(10.0);
604 const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * aCombination.getRefModeOffset()));
615 double getMinimalNonZeroValue(
double fCurrent,
double fNew)
621 fCurrent = std::min(fNew, fCurrent);
632 double getMinimalNonZeroBorderWidthFromStyle(
double fCurrent,
const svx::frame::Style& rStyle)
636 fCurrent = getMinimalNonZeroValue(fCurrent, rStyle.
Prim());
637 fCurrent = getMinimalNonZeroValue(fCurrent, rStyle.
Dist());
638 fCurrent = getMinimalNonZeroValue(fCurrent, rStyle.
Secn());
652 maNormalizedPerpendicular(rNormalizedPerpendicular),
653 mbStyleMirrored(bStyleMirrored)
668 const Color* pForceColor)
672 maColor(nullptr != pForceColor ? *pForceColor :
Color()),
689 maStart.emplace_back(rStyle, rNormalizedPerpendicular, bStyleMirrored);
693 maEnd.emplace_back(rStyle, rNormalizedPerpendicular, bStyleMirrored);
700 double fMinimalDiscreteUnit)
const
702 StyleVectorTable aStartVector;
703 StyleVectorTable aEndVector;
706 for(
const auto& rStart :
maStart)
711 rStart.getNormalizedPerpendicular(),
712 rStart.getStyleMirrored(),
713 fMinimalDiscreteUnit);
716 for(
const auto& rEnd :
maEnd)
721 rEnd.getNormalizedPerpendicular(),
722 rEnd.getStyleMirrored(),
723 fMinimalDiscreteUnit);
729 CreateBorderPrimitives(
737 fMinimalDiscreteUnit);
742 double fRetval(getMinimalNonZeroBorderWidthFromStyle(0.0,
maStyle));
744 for(
const auto& rStart :
maStart)
746 fRetval = getMinimalNonZeroBorderWidthFromStyle(fRetval, rStart.getStyle());
749 for(
const auto& rEnd :
maEnd)
751 fRetval = getMinimalNonZeroBorderWidthFromStyle(fRetval, rEnd.getStyle());
794 rCandidate.create2DDecomposition(
796 fMinimalDiscreteUnit);
798 for(
const auto& aCandidatePartial : aPartial)
803 aRetval.
append(aCandidatePartial);
807 bool bDidMerge(
false);
809 for(
auto& aCandidateRetval : aRetval)
814 static_cast<BorderLinePrimitive2D*>(aCandidateRetval.get()),
815 static_cast<BorderLinePrimitive2D*>(aCandidatePartial.get())));
817 if(aMergeRetvalPartial.is())
820 aCandidateRetval = aMergeRetvalPartial;
828 static_cast<BorderLinePrimitive2D*>(aCandidatePartial.get()),
829 static_cast<BorderLinePrimitive2D*>(aCandidateRetval.get())));
831 if(aMergePartialRetval.is())
834 aCandidateRetval = aMergePartialRetval;
843 aRetval.append(aCandidatePartial);
850 rContainer.insert(rContainer.end(), aRetval.begin(), aRetval.end());
854 std::shared_ptr<SdrFrameBorderDataVector>& rFrameBorders,
855 bool bForceToSingleDiscreteUnit)
857 maFrameBorders(
std::move(rFrameBorders)),
858 mfMinimalNonZeroBorderWidth(0.0),
859 mfMinimalNonZeroBorderWidthUsedForDecompose(0.0),
860 mbForceToSingleDiscreteUnit(bForceToSingleDiscreteUnit)
869 rCandidate.getMinimalNonZeroBorderWidth());
876 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
897 double fDiscreteUnit(std::min(fabs(aDiscreteVector.getX()), fabs(aDiscreteVector.getY())));
RefMode
Specifies how the reference points for frame borders are used.
const std::shared_ptr< SdrFrameBorderDataVector > & getFrameBorders() const
virtual void create2DDecomposition(Primitive2DContainer &rContainer, const geometry::ViewInformation2D &aViewInformation) const override
virtual void get2DDecomposition(Primitive2DDecompositionVisitor &rVisitor, const geometry::ViewInformation2D &rViewInformation) const override
RefMode GetRefMode() const
The reference points specify the begin of the frame border width.
SvxBorderLineStyle Type() const
bool areParallel(const B2DVector &rVecA, const B2DVector &rVecB)
Color GetColorSecn() const
The reference points specify the end of the frame border width.
Color GetColorGap() const
bool IsUsed() const
Check if this style is used - this depends on it having any width definition.
std::vector< SdrConnectStyleData > maEnd
virtual bool operator==(const BasePrimitive2D &rPrimitive) const override
void create2DDecomposition(Primitive2DContainer &rContainer, double fMinDiscreteUnit) const
void addSdrConnectStyleData(bool bStart, const svx::frame::Style &rStyle, const basegfx::B2DVector &rNormalizedPerpendicular, bool bStyleMirrored)
Primitive2DReference DRAWINGLAYER_DLLPUBLIC tryMergeBorderLinePrimitive2D(const BorderLinePrimitive2D *pCandidateA, const BorderLinePrimitive2D *pCandidateB)
bool doForceToSingleDiscreteUnit() const
double getMinimalNonZeroBorderWidth() const
bool operator==(const SdrConnectStyleData &rCompare) const
bool operator==(const SdrFrameBorderData &rCompare) const
std::vector< SdrConnectStyleData > maStart
basegfx::B2DVector maNormalizedPerpendicular
const Primitive2DContainer & getBuffered2DDecomposition() const
const uno::Sequence< double > maOffsets
virtual void append(const Primitive2DReference &) override
bool IsFullyTransparent() const
ImplPrimitive2DIDBlock(BorderLinePrimitive2D, PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D) Primitive2DReference tryMergeBorderLinePrimitive2D(const BorderLinePrimitive2D *pCandidateA
SdrFrameBorderData(const basegfx::B2DPoint &rOrigin, const basegfx::B2DVector &rX, const svx::frame::Style &rStyle, const Color *pForceColor)
basegfx::B2DVector maX
start point of borderline
double PatternScale() const
svx::frame::Style maStyle
X-Axis of borderline with length.
css::uno::Reference< css::graphic::XPrimitive2D > Primitive2DReference
Color GetColorPrim() const
bool operator<(const Subset &rLHS, const Subset &rRHS)
SdrFrameBorderPrimitive2D(std::shared_ptr< SdrFrameBorderDataVector > &rFrameBorders, bool bForceToSingleDiscreteUnit)
double mfMinimalNonZeroBorderWidthUsedForDecompose
SdrConnectStyleData(const svx::frame::Style &rStyle, const basegfx::B2DVector &rNormalizedPerpendicular, bool bStyleMirrored)
Contains the widths of primary and secondary line of a frame style.
CutFlagValue findCut(const B2DPoint &rEdge1Start, const B2DVector &rEdge1Delta, const B2DPoint &rEdge2Start, const B2DVector &rEdge2Delta, CutFlagValue aCutFlags, double *pCut1, double *pCut2)
basegfx::BColor getBColor() const
svx::frame::Style maStyle
#define PRIMITIVE2D_ID_SDRFRAMEBORDERTPRIMITIVE2D
Frame borders are drawn centered to the reference points.
double mfMinimalNonZeroBorderWidth
B2DVector getNormalizedPerpendicular(const B2DVector &rVec)
virtual void get2DDecomposition(Primitive2DDecompositionVisitor &rVisitor, const geometry::ViewInformation2D &rViewInformation) const override
void setBuffered2DDecomposition(const Primitive2DContainer &rNew)
Color maColor
Style of borderline.
basegfx::B2DPoint maOrigin