drawinglayer/source/primitive2d/borderlineprimitive2d.cxx | 112 ++++++ include/drawinglayer/primitive2d/borderlineprimitive2d.hxx | 7 include/svx/framelink.hxx | 59 --- svx/source/dialog/framelink.cxx | 88 ++-- svx/source/dialog/framelinkarray.cxx | 114 ++++-- svx/source/table/viewcontactoftableobj.cxx | 22 - sw/source/core/layout/paintfrm.cxx | 235 +------------ 7 files changed, 292 insertions(+), 345 deletions(-)
New commits: commit 1679a909e383c689cc4af9b699baf0d5a165c281 Author: Armin Le Grand <[email protected]> Date: Tue Sep 12 17:28:54 2017 +0200 borderline: merge redefined, mirrored Styles Redefined merge of BorderlinePrimitives, removed old Writer stuff for it. Also added support for handling Styles mirrored for extension calculations Change-Id: Icee5540573c294d3e6c1b98c55e6dda67a82cc16 diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx index 9421ed8b249b..5fc3b57fbbda 100644 --- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx @@ -144,7 +144,7 @@ namespace drawinglayer for(const auto& candidate : maBorderLines) { - const double fWidth(candidate.getAdaptedWidth(mfSmallestAllowedDiscreteGapDistance) * 0.5); + const double fWidth(candidate.getAdaptedWidth(mfSmallestAllowedDiscreteGapDistance)); if(!candidate.isGap()) { @@ -369,6 +369,116 @@ namespace drawinglayer // provide unique ID ImplPrimitive2DIDBlock(BorderLinePrimitive2D, PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D) + Primitive2DReference tryMergeBorderLinePrimitive2D( + const Primitive2DReference& rCandidateA, + const Primitive2DReference& rCandidateB) + { + // try to cast to BorderLinePrimitive2D + const primitive2d::BorderLinePrimitive2D* pCandidateA = dynamic_cast< const primitive2d::BorderLinePrimitive2D* >(rCandidateA.get()); + const primitive2d::BorderLinePrimitive2D* pCandidateB = dynamic_cast< const primitive2d::BorderLinePrimitive2D* >(rCandidateB.get()); + + // we need a comparable BorderLinePrimitive2D + if(nullptr == pCandidateA || nullptr == pCandidateB) + { + return Primitive2DReference(); + } + + // start of candidate has to match end of this + if(!pCandidateA->getEnd().equal(pCandidateB->getStart())) + { + return Primitive2DReference(); + } + + // candidate A needs a length + if(pCandidateA->getStart().equal(pCandidateA->getEnd())) + { + return Primitive2DReference(); + } + + // candidate B needs a length + if(pCandidateB->getStart().equal(pCandidateB->getEnd())) + { + return Primitive2DReference(); + } + + // StrokeAttribute has to be equal + if(!(pCandidateA->getStrokeAttribute() == pCandidateB->getStrokeAttribute())) + { + return Primitive2DReference(); + } + + // direction has to be equal -> cross product == 0.0 + const basegfx::B2DVector aVT(pCandidateA->getEnd() - pCandidateA->getStart()); + const basegfx::B2DVector aVC(pCandidateB->getEnd() - pCandidateB->getStart()); + if(!rtl::math::approxEqual(0.0, aVC.cross(aVT))) + { + return Primitive2DReference(); + } + + // number BorderLines has to be equal + const size_t count(pCandidateA->getBorderLines().size()); + if(count != pCandidateB->getBorderLines().size()) + { + return Primitive2DReference(); + } + + for(size_t a(0); a < count; a++) + { + const BorderLine& rBT(pCandidateA->getBorderLines()[a]); + const BorderLine& rBC(pCandidateB->getBorderLines()[a]); + + // LineAttribute has to be the same + if(!(rBC.getLineAttribute() == rBT.getLineAttribute())) + { + return Primitive2DReference(); + } + + // isGap has to be the same + if(rBC.isGap() != rBT.isGap()) + { + return Primitive2DReference(); + } + + if(!rBT.isGap()) + { + // when not gap, the line extends have at least reach to the center ( > 0.0), + // else there is a extend usage. When > 0.0 they just overlap, no problem + if(rBT.getEndLeft() >= 0.0 + && rBT.getEndRight() >= 0.0 + && rBC.getStartLeft() >= 0.0 + && rBC.getStartRight() >= 0.0) + { + // okay + } + else + { + return Primitive2DReference(); + } + } + } + + // all conditions met, create merged primitive + std::vector< BorderLine > aMergedBorderLines; + + for(size_t a(0); a < count; a++) + { + const BorderLine& rBT(pCandidateA->getBorderLines()[a]); + const BorderLine& rBC(pCandidateB->getBorderLines()[a]); + + aMergedBorderLines.push_back( + BorderLine( + rBT.getLineAttribute(), + rBT.getStartLeft(), rBT.getStartRight(), + rBC.getEndLeft(), rBC.getEndRight())); + } + + return Primitive2DReference( + new BorderLinePrimitive2D( + pCandidateA->getStart(), + pCandidateB->getEnd(), + aMergedBorderLines, + pCandidateA->getStrokeAttribute())); + } } // end of namespace primitive2d } // end of namespace drawinglayer diff --git a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx index 992347c7dc9b..b6634f6ce64e 100644 --- a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx @@ -87,6 +87,13 @@ namespace drawinglayer bool operator==(const BorderLine& rBorderLine) const; }; + /// helper to try to merge two instances of BorderLinePrimitive2D. If it was possible, + /// a merged version is in the returned Primitive2DReference. Lots of preconditions + /// have to be met to allow that, see implementation (and maybe even expand) + Primitive2DReference DRAWINGLAYER_DLLPUBLIC tryMergeBorderLinePrimitive2D( + const Primitive2DReference& rCandidateA, + const Primitive2DReference& rCandidateB); + /** BorderLinePrimitive2D class This is the basic primitive to build frames around objects, e.g. tables. diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx index 9ebb4c85e5aa..1b130efa7f2f 100644 --- a/include/svx/framelink.hxx +++ b/include/svx/framelink.hxx @@ -213,66 +213,27 @@ public: inline bool operator>( const Style& rL, const Style& rR ) { return rR.operator<(rL); } -// Various helper functions - -/** Checks whether two horizontal frame borders are "connectable". - - Two borders are "connectable" in terms of this function, if both can be - drawn with only one call of a border drawing function. This means, the two - frame borders must have equal style and color, and none of the other - vertical and diagonal frame borders break the lines of the two borders in - any way (i.e. two vertical double frame borders would break the horizonal - frame borders). Of course this function can be used for vertical frame - borders as well. - - The following picture shows the meaning of all passed parameters: - - \ rTFromT / - \ | / - rTFromTL | rTFromTR - \ | / - \ | / - ======== rLBorder ========= ========== rRBorder ======= - / | \ - / | \ - rBFromBL | rBFromBR - / | \ - / rBFromB \ - - @return - True, if rLBorder and rRBorder can be drawn in one step without - interruption at their connection point. - */ -SVX_DLLPUBLIC bool CheckFrameBorderConnectable( - const Style& rLBorder, /// Style of the left frame border to connect. - const Style& rRBorder, /// Style of the right frame border to connect. - - const Style& rTFromTL, /// Diagonal frame border from top-left to connection point. - const Style& rTFromT, /// Vertical frame border from top to connection point. - const Style& rTFromTR, /// Horizontal frame border from top-right to connection point. - - const Style& rBFromBL, /// Diagonal frame border from bottom-left to connection point. - const Style& rBFromB, /// Vertical frame border from bottom to connection point. - const Style& rBFromBR /// Horizontal frame border from bottom-right to connection point. -); - - // Drawing functions class SAL_WARN_UNUSED SVX_DLLPUBLIC StyleVectorCombination { private: const Style& mrStyle; - const basegfx::B2DVector& mrB2DVector; + const basegfx::B2DVector maB2DVector; + const bool mbMirrored; + public: - StyleVectorCombination(const Style& rStyle, const basegfx::B2DVector& rB2DVector) : + StyleVectorCombination(const Style& rStyle, const basegfx::B2DVector& rB2DVector, bool bMirrored) : mrStyle(rStyle), - mrB2DVector(rB2DVector) - {} + maB2DVector(rB2DVector), + mbMirrored(bMirrored) + { + } const Style& getStyle() const { return mrStyle; } - const basegfx::B2DVector& getB2DVector() const { return mrB2DVector; } + const basegfx::B2DVector& getB2DVector() const { return maB2DVector; } + bool isMirrored() const { return mbMirrored; } }; typedef std::vector< StyleVectorCombination > StyleVectorTable; diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx index ca66b285f8d4..ce7168040228 100644 --- a/svx/source/dialog/framelink.cxx +++ b/svx/source/dialog/framelink.cxx @@ -334,29 +334,6 @@ bool Style::operator<( const Style& rOther) const return false; } -bool CheckFrameBorderConnectable( const Style& rLBorder, const Style& rRBorder, - const Style& rTFromTL, const Style& rTFromT, const Style& rTFromTR, - const Style& rBFromBL, const Style& rBFromB, const Style& rBFromBR ) -{ - return // returns 1 AND (2a OR 2b) - // 1) only, if both frame borders are equal - (rLBorder == rRBorder) - && - ( - ( - // 2a) if the borders are not double, at least one of the vertical must not be double - !rLBorder.Secn() && (!rTFromT.Secn() || !rBFromB.Secn()) - ) - || - ( - // 2b) if the borders are double, all other borders must not be double - rLBorder.Secn() && - !rTFromTL.Secn() && !rTFromT.Secn() && !rTFromTR.Secn() && - !rBFromBL.Secn() && !rBFromB.Secn() && !rBFromBR.Secn() - ) - ); -} - // Drawing functions struct OffsetAndHalfWidthAndColor { @@ -387,48 +364,70 @@ struct ExtendSet ExtendSet() : mfExtLeft(0.0), mfExtRight(0.0) {} }; -void getOffsetAndHalfWidthAndColorFromStyle(const Style& rStyle, const Color* pForceColor, std::vector< OffsetAndHalfWidthAndColor >& offsets) +double getOffsetAndHalfWidthAndColorFromStyle( + const Style& rStyle, + const Color* pForceColor, + bool bMirrored, + std::vector< OffsetAndHalfWidthAndColor >& offsets) { + // do not forget RefMode offset, primitive is free of it + double fRefModeOffset(0.0); + if (rStyle.IsUsed()) { - // do not forget RefMode offset, primitive is free of it - double fRefModeOffset(0.0); + RefMode aRefMode(rStyle.GetRefMode()); + Color aPrim(rStyle.GetColorPrim()); + Color aSecn(rStyle.GetColorSecn()); + double fPrim(rStyle.Prim()); + double fSecn(rStyle.Secn()); + + if(bMirrored) + { + switch(aRefMode) + { + case RefMode::Begin: aRefMode = RefMode::End; break; + case RefMode::End: aRefMode = RefMode::Begin; break; + default: break; + } + std::swap(aPrim, aSecn); + std::swap(fPrim, fSecn); + } - if (RefMode::Centered != rStyle.GetRefMode()) + if (RefMode::Centered != aRefMode) { const double fHalfWidth(rStyle.GetWidth() * 0.5); - if (RefMode::Begin == rStyle.GetRefMode()) + if (RefMode::Begin == aRefMode) { // move aligned below vector fRefModeOffset = fHalfWidth; } - else if (RefMode::End == rStyle.GetRefMode()) + else if (RefMode::End == aRefMode) { // move aligned above vector fRefModeOffset = -fHalfWidth; } } - if (rStyle.Dist() && rStyle.Secn()) + if (rStyle.Dist() && fSecn) { // 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 == rStyle.GetColorSecn().GetTransparency()); + const bool bSecnTransparent(0xff == aSecn.GetTransparency()); if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent) { const double a(fRefModeOffset - (rStyle.GetWidth() * 0.5)); - const double b(a + rStyle.Prim()); + const double b(a + fPrim); const double c(b + rStyle.Dist()); - const double d(c + rStyle.Secn()); + const double d(c + fSecn); offsets.push_back( OffsetAndHalfWidthAndColor( (a + b) * 0.5, - rStyle.Prim() * 0.5, - nullptr != pForceColor ? *pForceColor : rStyle.GetColorPrim())); + fPrim * 0.5, + nullptr != pForceColor ? *pForceColor : aPrim)); offsets.push_back( OffsetAndHalfWidthAndColor( @@ -441,8 +440,8 @@ void getOffsetAndHalfWidthAndColorFromStyle(const Style& rStyle, const Color* pF offsets.push_back( OffsetAndHalfWidthAndColor( (c + d) * 0.5, - rStyle.Secn() * 0.5, - nullptr != pForceColor ? *pForceColor : rStyle.GetColorSecn())); + fSecn * 0.5, + nullptr != pForceColor ? *pForceColor : aSecn)); } } else @@ -453,11 +452,13 @@ void getOffsetAndHalfWidthAndColorFromStyle(const Style& rStyle, const Color* pF offsets.push_back( OffsetAndHalfWidthAndColor( fRefModeOffset, - rStyle.Prim() * 0.5, - nullptr != pForceColor ? *pForceColor : rStyle.GetColorPrim())); + fPrim * 0.5, + nullptr != pForceColor ? *pForceColor : aPrim)); } } } + + return fRefModeOffset; } void getCutSet( @@ -525,7 +526,7 @@ void getExtends( for(const auto& rStyleVectorCombination : rStyleVectorTable) { std::vector< OffsetAndHalfWidthAndColor > otherOffsets; - getOffsetAndHalfWidthAndColorFromStyle(rStyleVectorCombination.getStyle(), nullptr, otherOffsets); + getOffsetAndHalfWidthAndColorFromStyle(rStyleVectorCombination.getStyle(), nullptr, rStyleVectorCombination.isMirrored(), otherOffsets); if(!otherOffsets.empty()) { @@ -568,7 +569,7 @@ void CreateBorderPrimitives( { // get offset color pairs for style, one per visible line std::vector< OffsetAndHalfWidthAndColor > myOffsets; - getOffsetAndHalfWidthAndColorFromStyle(rBorder, pForceColor, myOffsets); + const double fRefModeOffset(getOffsetAndHalfWidthAndColorFromStyle(rBorder, pForceColor, false, myOffsets)); const size_t nOffsets(myOffsets.size()); if(nOffsets) @@ -624,12 +625,13 @@ void CreateBorderPrimitives( 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 * fRefModeOffset)); rTarget.append( drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::BorderLinePrimitive2D( - rOrigin, - rOrigin + rX, + aStart, + aStart + rX, aBorderlines, aStrokeAttribute))); } diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx index 6052c23f3e8a..2d81caebd3a7 100644 --- a/svx/source/dialog/framelinkarray.cxx +++ b/svx/source/dialog/framelinkarray.cxx @@ -954,11 +954,11 @@ void HelperCreateHorizontalEntry( const Style& rStartFromBR(rArray.GetCellStyleTL( col, row )); StyleVectorTable aStart; - if(rStartFromTR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromTR, rX - rY)); - if(rStartLFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromT, -rY)); - if(rStartLFromL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromL, -rX)); - if(rStartLFromB.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromB, rY)); - if(rStartFromBR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBR, rX + rY)); + if(rStartFromTR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromTR, rX - rY, false)); + if(rStartLFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromT, -rY, true)); + if(rStartLFromL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromL, -rX, true)); + if(rStartLFromB.IsUsed()) aStart.push_back(StyleVectorCombination(rStartLFromB, rY, false)); + if(rStartFromBR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBR, rX + rY, false)); // get involved styles at end const Style& rEndFromTL(rArray.GetCellStyleBR( col, row - 1 )); @@ -968,11 +968,11 @@ void HelperCreateHorizontalEntry( const Style& rEndFromBL(rArray.GetCellStyleTR( col, row )); StyleVectorTable aEnd; - if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, -rX -rY)); - if(rEndRFromT.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromT, -rY)); - if(rEndRFromR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromR, rX)); - if(rEndRFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromB, rY)); - if(rEndFromBL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromBL, rY - rX)); + if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, -rX -rY, true)); + if(rEndRFromT.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromT, -rY, true)); + if(rEndRFromR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromR, rX, false)); + if(rEndRFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndRFromB, rY, false)); + if(rEndFromBL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromBL, rY - rX, true)); CreateBorderPrimitives( rSequence, @@ -999,11 +999,11 @@ void HelperCreateVerticalEntry( const Style& rStartFromBR(rArray.GetCellStyleTL( col, row )); StyleVectorTable aStart; - if(rStartFromBR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBR, rX + rY)); - if(rStartTFromR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromR, rX)); - if(rStartTFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromT, rY)); - if(rStartTFromL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromL, -rX)); - if(rStartFromBL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBL, rY - rX)); + if(rStartFromBR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBR, rX + rY, false)); + if(rStartTFromR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromR, rX, false)); + if(rStartTFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromT, rY, true)); + if(rStartTFromL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromL, -rX, true)); + if(rStartFromBL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBL, rY - rX, true)); // get involved styles at end const Style& rEndFromTL(rArray.GetCellStyleBR( col - 1, row )); @@ -1013,11 +1013,11 @@ void HelperCreateVerticalEntry( const Style& rEndFromTR(rArray.GetCellStyleBL( col, row )); StyleVectorTable aEnd; - if(rEndFromTR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTR, rX - rY)); - if(rEndBFromR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromR, rX)); - if(rEndBFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromB, -rY)); - if(rEndBFromL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromL, rX)); - if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, rX + rY)); + if(rEndFromTR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTR, rX - rY, false)); + if(rEndBFromR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromR, rX, false)); + if(rEndBFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromB, -rY, false)); + if(rEndBFromL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromL, rX, true)); + if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, rX + rY, true)); CreateBorderPrimitives( rSequence, @@ -1069,6 +1069,48 @@ void HelperCreateEntry(const Array& rArray, const Style& rStyle, drawinglayer::p } } +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.append(aCandidate); + aCandidate = a; + } + } + else + { + aCandidate = a; + } + } + + if(aCandidate.is()) + { + rTarget.append(aCandidate); + } + } + else + { + rTarget.append(rSource); + } +} + drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange( size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow, const Color* pForceColor ) const @@ -1078,7 +1120,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange( // various primitive sequences to collect the different border types drawinglayer::primitive2d::Primitive2DContainer aHorizontalSequence; - drawinglayer::primitive2d::Primitive2DContainer aVerticalSequence; + std::vector< drawinglayer::primitive2d::Primitive2DContainer > aVerticalSequences(nLastCol - nFirstCol + 1); drawinglayer::primitive2d::Primitive2DContainer aCrossSequence; for (size_t nRow = nFirstRow; nRow <= nLastRow; ++nRow) @@ -1131,7 +1173,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange( if(rLeft.IsUsed()) { - HelperCreateEntry(*this, rLeft, aVerticalSequence, pForceColor); + HelperCreateEntry(*this, rLeft, aVerticalSequences[nCol - nFirstCol], pForceColor); } } @@ -1141,7 +1183,7 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange( if(rRight.IsUsed()) { - HelperCreateEntry(*this, rRight, aVerticalSequence, pForceColor); + HelperCreateEntry(*this, rRight, aVerticalSequences[nCol - nFirstCol], pForceColor); } } @@ -1156,15 +1198,15 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange( /// Fill top-left Style Table const Style& rTLFromRight(GetCellStyleTop(_nFirstCol, _nFirstRow)); - if(rTLFromRight.IsUsed()) aStart.push_back(StyleVectorCombination(rTLFromRight, aX)); + if(rTLFromRight.IsUsed()) aStart.push_back(StyleVectorCombination(rTLFromRight, aX, false)); const Style& rTLFromBottom(GetCellStyleLeft(_nFirstCol, _nFirstRow)); - if(rTLFromBottom.IsUsed()) aStart.push_back(StyleVectorCombination(rTLFromBottom, aY)); + if(rTLFromBottom.IsUsed()) aStart.push_back(StyleVectorCombination(rTLFromBottom, aY, false)); /// Fill bottom-right Style Table const Style& rBRFromBottom(GetCellStyleRight(_nLastCol, _nLastRow)); - if(rBRFromBottom.IsUsed()) aEnd.push_back(StyleVectorCombination(rBRFromBottom, -aY)); + if(rBRFromBottom.IsUsed()) aEnd.push_back(StyleVectorCombination(rBRFromBottom, -aY, true)); const Style& rBRFromLeft(GetCellStyleBottom(_nLastCol, _nLastRow)); - if(rBRFromLeft.IsUsed()) aEnd.push_back(StyleVectorCombination(rBRFromLeft, -aX)); + if(rBRFromLeft.IsUsed()) aEnd.push_back(StyleVectorCombination(rBRFromLeft, -aX, true)); CreateBorderPrimitives( aCrossSequence, @@ -1186,15 +1228,15 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange( /// Fill bottom-left Style Table const Style& rBLFromTop(GetCellStyleLeft(_nFirstCol, _nLastRow)); - if(rBLFromTop.IsUsed()) aStart.push_back(StyleVectorCombination(rBLFromTop, -aY)); + if(rBLFromTop.IsUsed()) aStart.push_back(StyleVectorCombination(rBLFromTop, -aY, true)); const Style& rBLFromBottom(GetCellStyleBottom(_nFirstCol, _nLastRow)); - if(rBLFromBottom.IsUsed()) aStart.push_back(StyleVectorCombination(rBLFromBottom, aX)); + if(rBLFromBottom.IsUsed()) aStart.push_back(StyleVectorCombination(rBLFromBottom, aX, false)); /// Fill top-right Style Table const Style& rTRFromBottom(GetCellStyleRight(_nLastCol, _nFirstRow)); - if(rTRFromBottom.IsUsed()) aEnd.push_back(StyleVectorCombination(rTRFromBottom, -aY)); + if(rTRFromBottom.IsUsed()) aEnd.push_back(StyleVectorCombination(rTRFromBottom, -aY, true)); const Style& rTRFromLeft(GetCellStyleTop(_nLastCol, _nFirstRow)); - if(rTRFromLeft.IsUsed()) aEnd.push_back(StyleVectorCombination(rTRFromLeft, -aX)); + if(rTRFromLeft.IsUsed()) aEnd.push_back(StyleVectorCombination(rTRFromLeft, -aX, false)); CreateBorderPrimitives( aCrossSequence, @@ -1211,9 +1253,13 @@ drawinglayer::primitive2d::Primitive2DContainer Array::CreateB2DPrimitiveRange( } } - // to stay compatible, create order as it was formally - aCrossSequence.append(aHorizontalSequence); - aCrossSequence.append(aVerticalSequence); + // to stay compatible, create order as it was formally. Also try to + // merge primitives as far as possible + HelperMergeInB2DPrimitiveArray(aHorizontalSequence, aCrossSequence); + for(const auto& aVert : aVerticalSequences) + { + HelperMergeInB2DPrimitiveArray(aVert, aCrossSequence); + } return aCrossSequence; } diff --git a/svx/source/table/viewcontactoftableobj.cxx b/svx/source/table/viewcontactoftableobj.cxx index d696569dc329..87f44432713e 100644 --- a/svx/source/table/viewcontactoftableobj.cxx +++ b/svx/source/table/viewcontactoftableobj.cxx @@ -197,7 +197,7 @@ namespace sdr return svx::frame::Style(); } - void createForVector(drawinglayer::primitive2d::Primitive2DContainer& rContainer, const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX, + void createForVector(bool bHor, drawinglayer::primitive2d::Primitive2DContainer& rContainer, const basegfx::B2DPoint& rOrigin, const basegfx::B2DVector& rX, const svx::frame::Style& rLine, const svx::frame::Style& rLeftA, const svx::frame::Style& rLeftB, const svx::frame::Style& rLeftC, const svx::frame::Style& rRightA, const svx::frame::Style& rRightB, const svx::frame::Style& rRightC) @@ -209,14 +209,14 @@ namespace sdr const double fTwipsToMM(127.0 / 72.0); /// Fill top-left Style Table - if(rLeftA.IsUsed()) aStart.push_back(svx::frame::StyleVectorCombination(rLeftA, -aY)); - if(rLeftB.IsUsed()) aStart.push_back(svx::frame::StyleVectorCombination(rLeftB, -rX)); - if(rLeftC.IsUsed()) aStart.push_back(svx::frame::StyleVectorCombination(rLeftC, aY)); + if(rLeftA.IsUsed()) aStart.push_back(svx::frame::StyleVectorCombination(rLeftA, -aY, bHor ? true : false)); + if(rLeftB.IsUsed()) aStart.push_back(svx::frame::StyleVectorCombination(rLeftB, -rX, bHor ? true : true)); + if(rLeftC.IsUsed()) aStart.push_back(svx::frame::StyleVectorCombination(rLeftC, aY, bHor ? false : true)); /// Fill bottom-right Style Table - if(rRightA.IsUsed()) aEnd.push_back(svx::frame::StyleVectorCombination(rRightA, -aY)); - if(rRightB.IsUsed()) aEnd.push_back(svx::frame::StyleVectorCombination(rRightB, rX)); - if(rRightC.IsUsed()) aEnd.push_back(svx::frame::StyleVectorCombination(rRightC, aY)); + if(rRightA.IsUsed()) aEnd.push_back(svx::frame::StyleVectorCombination(rRightA, -aY, bHor ? true : false)); + if(rRightB.IsUsed()) aEnd.push_back(svx::frame::StyleVectorCombination(rRightB, rX, bHor ? false : false)); + if(rRightC.IsUsed()) aEnd.push_back(svx::frame::StyleVectorCombination(rRightC, aY, bHor ? false : true)); CreateBorderPrimitives( rContainer, @@ -354,28 +354,28 @@ namespace sdr if(aLeftLine.IsUsed()) { - createForVector(aBorderSequence, aOrigin, aY, aLeftLine, + createForVector(false, aBorderSequence, aOrigin, aY, aLeftLine, aTopLine, aLeftFromTLine, aTopFromLLine, aBottomLine, aLeftFromBLine, aBottomFromLLine); } if(aBottomLine.IsUsed()) { - createForVector(aBorderSequence, aOrigin + aY, aX, aBottomLine, + createForVector(true, aBorderSequence, aOrigin + aY, aX, aBottomLine, aLeftLine, aBottomFromLLine, aLeftFromBLine, aRightLine, aBottomFromRLine, aRightFromBLine); } if(aRightLine.IsUsed()) { - createForVector(aBorderSequence, aOrigin + aX, aY, aRightLine, + createForVector(false, aBorderSequence, aOrigin + aX, aY, aRightLine, aTopFromRLine, aRightFromTLine, aTopLine, aBottomFromRLine, aRightFromBLine, aBottomLine); } if(aTopLine.IsUsed()) { - createForVector(aBorderSequence, aOrigin, aX, aTopLine, + createForVector(true, aBorderSequence, aOrigin, aX, aTopLine, aLeftFromTLine, aTopFromLLine, aLeftLine, aRightFromTLine, aTopFromRLine, aRightLine); } diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 9d1928d2bf76..888db6527e77 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -221,7 +221,7 @@ class BorderLines { drawinglayer::primitive2d::Primitive2DContainer m_Lines; public: - void AddBorderLine(css::uno::Reference<BorderLinePrimitive2D> const& xLine, SwPaintProperties const & properties); + void AddBorderLine(const drawinglayer::primitive2d::Primitive2DReference& rLine); drawinglayer::primitive2d::Primitive2DContainer GetBorderLines_Clear() { drawinglayer::primitive2d::Primitive2DContainer lines; @@ -472,197 +472,20 @@ SwSavePaintStatics::~SwSavePaintStatics() gProp.aSScaleY = aSScaleY; } -/** - * Check whether the two primitive can be merged - * - * @param[in] mergeA A primitive start and end position - * @param[in] mergeB B primitive start and end position - * @return 1 if A and B can be merged to a primite staring with A, ending with B - * 2 if A and B can be merged to a primite staring with B, ending with A - * 0 if A and B can't be merged -**/ -static sal_uInt8 lcl_TryMergeLines( - pair<double, double> const& mergeA, - pair<double, double> const& mergeB, - SwPaintProperties const & properties) -{ - double const fMergeGap(properties.nSPixelSzW + properties.nSHalfPixelSzW); // NOT static! - // A is above/before B - if( mergeA.second <= mergeB.first && - mergeA.second + fMergeGap >= mergeB.first ) - { - return 1; - } - // B is above/before A - else if( mergeB.second <= mergeA.first && - mergeB.second + fMergeGap >= mergeA.first ) - { - return 2; - } - return 0; -} - -/** - * Make a new primitive from the two input borderline primitive - * - * @param[in] rLine starting primitive - * @param[in] rOther ending primitive - * @param[in] rStart starting point of merged primitive - * @param[in] rEnd ending point of merged primitive - * @return merged primitive -**/ -static rtl::Reference<BorderLinePrimitive2D> -lcl_MergeBorderLines( - BorderLinePrimitive2D const& rLine, - BorderLinePrimitive2D const& rOther, - basegfx::B2DPoint const& rStart, - basegfx::B2DPoint const& rEnd) -{ - const std::vector< BorderLine >& rLineLeft(rLine.getBorderLines()); - const std::vector< BorderLine >& rOtherLeft(rOther.getBorderLines()); - const size_t aSize(std::min(rLineLeft.size(), rOtherLeft.size())); - std::vector< BorderLine > aNew; - - for(size_t a(0); a < aSize; a++) - { - const BorderLine& la(rLineLeft[a]); - const BorderLine& lb(rOtherLeft[a]); - - if(la.isGap() || lb.isGap()) - { - aNew.push_back(la); - } - else - { - aNew.push_back( - BorderLine( - la.getLineAttribute(), - la.getStartLeft(), - la.getStartRight(), - lb.getEndLeft(), - lb.getEndRight())); - } - } - - return new BorderLinePrimitive2D( - rStart, - rEnd, - aNew, - rLine.getStrokeAttribute()); -} - -/** - * Merge the two borderline if possible. - * - * @param[in] rThis one borderline primitive - * @param[in] rOther other borderline primitive - * @return merged borderline including the two input primitive, if they can be merged - * 0, otherwise -**/ -static rtl::Reference<BorderLinePrimitive2D> -lcl_TryMergeBorderLine(BorderLinePrimitive2D const& rThis, - BorderLinePrimitive2D const& rOther, - SwPaintProperties const & properties) +void BorderLines::AddBorderLine(const drawinglayer::primitive2d::Primitive2DReference& rLine) { - assert(rThis.getEnd().getX() >= rThis.getStart().getX()); - assert(rThis.getEnd().getY() >= rThis.getStart().getY()); - assert(rOther.getEnd().getX() >= rOther.getStart().getX()); - assert(rOther.getEnd().getY() >= rOther.getStart().getY()); - const bool bSameEdgeNumber(rThis.getBorderLines().size() == rOther.getBorderLines().size()); - - if (!bSameEdgeNumber) - { - return nullptr; - } - - double thisHeight = rThis.getEnd().getY() - rThis.getStart().getY(); - double thisWidth = rThis.getEnd().getX() - rThis.getStart().getX(); - double otherHeight = rOther.getEnd().getY() - rOther.getStart().getY(); - double otherWidth = rOther.getEnd().getX() - rOther.getStart().getX(); - - // check for same orientation, same line width, same style and matching colors - bool bSameStuff( - ((thisHeight > thisWidth) == (otherHeight > otherWidth)) - && rThis.getStrokeAttribute() == rOther.getStrokeAttribute()); - - if(bSameStuff) + for (drawinglayer::primitive2d::Primitive2DContainer::reverse_iterator it = m_Lines.rbegin(); it != m_Lines.rend(); ++it) { - const std::vector< BorderLine >& rLineLeft(rThis.getBorderLines()); - const std::vector< BorderLine >& rOtherLeft(rOther.getBorderLines()); - const size_t aSize(std::min(rLineLeft.size(), rOtherLeft.size())); - - for(size_t a(0); bSameStuff && a < aSize; a++) - { - const BorderLine& la(rLineLeft[a]); - const BorderLine& lb(rOtherLeft[a]); - - bSameStuff = la == lb; - } - } - - if (bSameStuff) - { - int nRet = 0; - if (thisHeight > thisWidth) // vertical line - { - if (rtl::math::approxEqual(rThis.getStart().getX(), rOther.getStart().getX())) - { - assert(rtl::math::approxEqual(rThis.getEnd().getX(), rOther.getEnd().getX())); - nRet = lcl_TryMergeLines( - make_pair(rThis.getStart().getY(), rThis.getEnd().getY()), - make_pair(rOther.getStart().getY(),rOther.getEnd().getY()), - properties); - } - } - else // horizontal line - { - if (rtl::math::approxEqual(rThis.getStart().getY(), rOther.getStart().getY())) - { - assert(rtl::math::approxEqual(rThis.getEnd().getY(), rOther.getEnd().getY())); - nRet = lcl_TryMergeLines( - make_pair(rThis.getStart().getX(), rThis.getEnd().getX()), - make_pair(rOther.getStart().getX(),rOther.getEnd().getX()), - properties); - } - } + const drawinglayer::primitive2d::Primitive2DReference aMerged(drawinglayer::primitive2d::tryMergeBorderLinePrimitive2D(*it, rLine)); - // The merged primitive starts with rThis and ends with rOther - if (nRet == 1) - { - basegfx::B2DPoint const start( - rThis.getStart().getX(), rThis.getStart().getY()); - basegfx::B2DPoint const end( - rOther.getEnd().getX(), rOther.getEnd().getY()); - return lcl_MergeBorderLines(rThis, rOther, start, end).get(); - } - // The merged primitive starts with rOther and ends with rThis - else if(nRet == 2) + if (aMerged.is()) { - basegfx::B2DPoint const start( - rOther.getStart().getX(), rOther.getStart().getY()); - basegfx::B2DPoint const end( - rThis.getEnd().getX(), rThis.getEnd().getY()); - return lcl_MergeBorderLines(rOther, rThis, start, end).get(); - } - } - return nullptr; -} - -void BorderLines::AddBorderLine( - css::uno::Reference<BorderLinePrimitive2D> const& xLine, SwPaintProperties const & properties) -{ - for (drawinglayer::primitive2d::Primitive2DContainer::reverse_iterator it = m_Lines.rbegin(); it != m_Lines.rend(); - ++it) - { - rtl::Reference<BorderLinePrimitive2D> const xMerged( - lcl_TryMergeBorderLine(*static_cast<BorderLinePrimitive2D*>((*it).get()), *xLine.get(), properties).get()); - if (xMerged.is()) - { - *it = xMerged.get(); // replace existing line with merged + *it = aMerged; // replace existing line with merged // lcl_TryMergeBorderLine return; } } - m_Lines.push_back(xLine); + + m_Lines.append(rLine); } SwLineRect::SwLineRect( const SwRect &rRect, const Color *pCol, const SvxBorderLineStyle nStyl, @@ -2608,6 +2431,7 @@ 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 aSequence; while ( true ) { @@ -2715,8 +2539,6 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons if(aStyles[0].IsUsed()) { - drawinglayer::primitive2d::Primitive2DContainer aSequence; - if (bHori) { const basegfx::B2DPoint aOrigin(aPaintStart.X(), aPaintStart.Y()); @@ -2728,13 +2550,13 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons svx::frame::StyleVectorTable aStartTable; svx::frame::StyleVectorTable aEndTable; - if(aStyles[ 1 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 1 ], -aY)); // aLFromT - if(aStyles[ 2 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 2 ], -aX)); // aLFromL - if(aStyles[ 3 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 3 ], aY)); // aLFromB + if(aStyles[ 1 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 1 ], -aY, true)); // aLFromT + if(aStyles[ 2 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 2 ], -aX, true)); // aLFromL + if(aStyles[ 3 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 3 ], aY, false)); // aLFromB - if(aStyles[ 4 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 4 ], -aY)); // aRFromT - if(aStyles[ 5 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 5 ], aX)); // aRFromR - if(aStyles[ 6 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 6 ], aY)); // aRFromB + if(aStyles[ 4 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 4 ], -aY, true)); // aRFromT + if(aStyles[ 5 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 5 ], aX, false)); // aRFromR + if(aStyles[ 6 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 6 ], aY, false)); // aRFromB CreateBorderPrimitives( aSequence, @@ -2743,7 +2565,7 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons aStyles[ 0 ], aStartTable, aEndTable, - nullptr + pTmpColor ); } } @@ -2758,13 +2580,13 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons svx::frame::StyleVectorTable aStartTable; svx::frame::StyleVectorTable aEndTable; - if(aStyles[ 3 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 3 ], -aY)); // aTFromR - if(aStyles[ 2 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 2 ], -aX)); // aTFromT - if(aStyles[ 1 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 1 ], aY)); // aTFromL + if(aStyles[ 3 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 3 ], -aY, false)); // aTFromR + if(aStyles[ 2 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 2 ], -aX, true)); // aTFromT + if(aStyles[ 1 ].IsUsed()) aStartTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 1 ], aY, true)); // aTFromL - if(aStyles[ 6 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 6 ], -aY)); // aBFromR - if(aStyles[ 5 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 5 ], aX)); // aBFromB - if(aStyles[ 4 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 4 ], aY)); // aBFromL + if(aStyles[ 6 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 6 ], -aY, false)); // aBFromR + if(aStyles[ 5 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 5 ], aX, false)); // aBFromB + if(aStyles[ 4 ].IsUsed()) aEndTable.push_back(svx::frame::StyleVectorCombination(aStyles[ 4 ], aY, true)); // aBFromL CreateBorderPrimitives( aSequence, @@ -2773,18 +2595,17 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons aStyles[ 0 ], aStartTable, aEndTable, - nullptr + pTmpColor ); } } - - mrTabFrame.ProcessPrimitives(aSequence); } } - ++aIter; } + mrTabFrame.ProcessPrimitives(aSequence); + // restore output device: rDev.SetDrawMode( nOldDrawMode ); } @@ -4839,7 +4660,7 @@ static void lcl_MakeBorderLine(SwRect const& rRect, // When rendering to very small (virtual) devices, like when producing // page thumbnails in a mobile device app, the line geometry can end up // bogus (negative width or height), so just ignore such border lines. - // Otherwise we will run into assertions later in lcl_TryMergeBorderLine() + // Otherwise we will run into assertions later in BorderLinePrimitive2D::tryMerge() // at least. if (aEnd.getX() < aStart.getX() || aEnd.getY() < aStart.getY()) @@ -4894,14 +4715,14 @@ static void lcl_MakeBorderLine(SwRect const& rRect, nExtentRightEnd)); } - rtl::Reference<BorderLinePrimitive2D> xLine( + drawinglayer::primitive2d::Primitive2DReference aLine( new BorderLinePrimitive2D( aStart, aEnd, aBorderlines, aStrokeAttribute)); - properties.pBLines->AddBorderLine(xLine.get(), properties); + properties.pBLines->AddBorderLine(aLine); } /** _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
