From ab65fe804cf3a97bd172b5551b553b9bcde6d756 Mon Sep 17 00:00:00 2001 From: Armin Le Grand Date: Thu, 14 Sep 2017 16:45:56 +0200 Subject: borderline: Extended decompose Decompose of BorderLinePrimitive2D extended to take care of non-perpendicular line endings for matching. Improved matching, one error in calc fixed Change-Id: I869a75385711b58e6725daba0f22be8a98158ad9 --- .../source/primitive2d/borderlineprimitive2d.cxx | 121 +++++++++++++++++++-- .../primitive2d/borderlineprimitive2d.hxx | 4 - sc/source/ui/view/output.cxx | 2 +- svx/source/dialog/framelink.cxx | 51 ++++++--- 4 files changed, 150 insertions(+), 28 deletions(-) diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx index 6295d4673c36..0b6dda423adf 100644 --- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx @@ -149,15 +149,118 @@ namespace drawinglayer if(!candidate.isGap()) { const basegfx::B2DVector aDeltaY(aPerpendicular * (fOffset + (fWidth * 0.5))); - const basegfx::B2DPoint aStart(getStart() - (aVector * candidate.getStartAverage()) + aDeltaY); - const basegfx::B2DPoint aEnd(getEnd() + (aVector * candidate.getEndAverage()) + aDeltaY); - - addPolygonStrokePrimitive2D( - rContainer, - aStart, - aEnd, - candidate.getLineAttribute(), - getStrokeAttribute()); + const basegfx::B2DPoint aStart(getStart() + aDeltaY); + const basegfx::B2DPoint aEnd(getEnd() + aDeltaY); + const bool bStartPerpendicular(rtl::math::approxEqual(candidate.getStartLeft(), candidate.getStartRight())); + const bool bEndPerpendicular(rtl::math::approxEqual(candidate.getEndLeft(), candidate.getEndRight())); + + if(bStartPerpendicular && bEndPerpendicular) + { + // start and end extends lead to an edge perpendicular to the line, so we can just use + // a PolygonStrokePrimitive2D for representation + addPolygonStrokePrimitive2D( + rContainer, + aStart - (aVector * candidate.getStartLeft()), + aEnd + (aVector * candidate.getEndLeft()), + candidate.getLineAttribute(), + getStrokeAttribute()); + } + else + { + // start and/or end extensions lead to a lineStart/End that is *not* + // perpendicular to the line itself + if(getStrokeAttribute().isDefault() || 0.0 == getStrokeAttribute().getFullDotDashLen()) + { + // without stroke, we can simply represent that using a filled polygon + const basegfx::B2DVector aHalfLineOffset(aPerpendicular * (candidate.getLineAttribute().getWidth() * 0.5)); + basegfx::B2DPolygon aPolygon; + + aPolygon.append(aStart - aHalfLineOffset - (aVector * candidate.getStartLeft())); + aPolygon.append(aEnd - aHalfLineOffset + (aVector * candidate.getEndLeft())); + aPolygon.append(aEnd + aHalfLineOffset + (aVector * candidate.getEndRight())); + aPolygon.append(aStart + aHalfLineOffset - (aVector * candidate.getStartRight())); + + rContainer.push_back( + new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + candidate.getLineAttribute().getColor())); + } + else + { + // with stroke, we have a problem - a filled polygon would lose the + // stroke. Let's represent the start and/or end as triangles, the main + // line still as PolygonStrokePrimitive2D. + // Fill default line Start/End for stroke, so we need no adaptions in else pathes + basegfx::B2DPoint aStrokeStart(aStart - (aVector * candidate.getStartLeft())); + basegfx::B2DPoint aStrokeEnd(aEnd + (aVector * candidate.getEndLeft())); + const basegfx::B2DVector aHalfLineOffset(aPerpendicular * (candidate.getLineAttribute().getWidth() * 0.5)); + + if(!bStartPerpendicular) + { + const double fMin(std::min(candidate.getStartLeft(), candidate.getStartRight())); + const double fMax(std::max(candidate.getStartLeft(), candidate.getStartRight())); + basegfx::B2DPolygon aPolygon; + + // create a triangle with min/max values for LineStart and add + if(rtl::math::approxEqual(candidate.getStartLeft(), fMax)) + { + aPolygon.append(aStart - aHalfLineOffset - (aVector * candidate.getStartLeft())); + } + + aPolygon.append(aStart - aHalfLineOffset - (aVector * fMin)); + aPolygon.append(aStart + aHalfLineOffset - (aVector * fMin)); + + if(rtl::math::approxEqual(candidate.getStartRight(), fMax)) + { + aPolygon.append(aStart + aHalfLineOffset - (aVector * candidate.getStartRight())); + } + + rContainer.push_back( + new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + candidate.getLineAttribute().getColor())); + + // Adapt StrokeStart accordingly + aStrokeStart = aStart - (aVector * fMin); + } + + if(!bEndPerpendicular) + { + const double fMin(std::min(candidate.getEndLeft(), candidate.getEndRight())); + const double fMax(std::max(candidate.getEndLeft(), candidate.getEndRight())); + basegfx::B2DPolygon aPolygon; + + // create a triangle with min/max values for LineEnd and add + if(rtl::math::approxEqual(candidate.getEndLeft(), fMax)) + { + aPolygon.append(aEnd - aHalfLineOffset + (aVector * candidate.getEndLeft())); + } + + if(rtl::math::approxEqual(candidate.getEndRight(), fMax)) + { + aPolygon.append(aEnd + aHalfLineOffset + (aVector * candidate.getEndRight())); + } + + aPolygon.append(aEnd + aHalfLineOffset + (aVector * fMin)); + aPolygon.append(aEnd - aHalfLineOffset + (aVector * fMin)); + + rContainer.push_back( + new PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + candidate.getLineAttribute().getColor())); + + // Adapt StrokeEnd accordingly + aStrokeEnd = aEnd + (aVector * fMin); + } + + addPolygonStrokePrimitive2D( + rContainer, + aStrokeStart, + aStrokeEnd, + candidate.getLineAttribute(), + getStrokeAttribute()); + } + } } fOffset += fWidth; diff --git a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx index b6634f6ce64e..cb57e40fbe8a 100644 --- a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx @@ -79,10 +79,6 @@ namespace drawinglayer /// helper to get adapted width (maximum) double getAdaptedWidth(double fMinWidth) const; - /// helper to get average values Start/End - double getStartAverage() const { return 0.5 * (mfStartLeft + mfStartRight); } - double getEndAverage() const { return 0.5 * (mfEndLeft + mfEndRight); } - /// compare operator bool operator==(const BorderLine& rBorderLine) const; }; diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx index da4c342d44d6..858ea99ef83f 100644 --- a/sc/source/ui/view/output.cxx +++ b/sc/source/ui/view/output.cxx @@ -660,7 +660,7 @@ void ScOutputData::SetCellRotations() const double fOrient((bLayoutRTL ? -1.0 : 1.0) * nAttrRotate * F_PI18000); // 1/100th degrees -> [0..2PI] svx::frame::Array& rArray = mrTabInfo.maArray; - rArray.SetCellRotation(nY+1, nX+1, eRotMode, fOrient); + rArray.SetCellRotation(nX+1, nY+1, eRotMode, fOrient); } } } diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx index ea5b33315cfc..e205560df33c 100644 --- a/svx/source/dialog/framelink.cxx +++ b/svx/source/dialog/framelink.cxx @@ -550,12 +550,15 @@ void getAllCutSets( for(const auto& rOtherOffset : otherOffsets) { - const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset - rOtherOffset.mfHalfWidth))); - const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset + rOtherOffset.mfHalfWidth))); - CutSet aCutSet; + if(0xff != rOtherOffset.maColor.GetTransparency()) + { + const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset - rOtherOffset.mfHalfWidth))); + const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset + rOtherOffset.mfHalfWidth))); + CutSet aCutSet; - getCutSet(aCutSet, rLeft, rRight, rX, aOtherLeft, aOtherRight, rStyleVectorCombination.getB2DVector()); - rCutSets.push_back(aCutSet); + getCutSet(aCutSet, rLeft, rRight, rX, aOtherLeft, aOtherRight, rStyleVectorCombination.getB2DVector()); + rCutSets.push_back(aCutSet); + } } } } @@ -586,22 +589,42 @@ CutSet getMinMaxCutSet( { const CutSet& rCandidate(rCutSets[a]); const double fCandidate(rCandidate.mfOLML + rCandidate.mfORML + rCandidate.mfOLMR + rCandidate.mfORMR); + bool bCopy(false); - if(bMin) + if(basegfx::fTools::equalZero(fCandidate - fRetval)) { - if(fCandidate < fRetval) + // both are equal (use basegfx::fTools::equalZero and *not* rtl::math::approxEqual here, that is too precise) + const bool bPerpendR(rtl::math::approxEqual(aRetval.mfOLML, aRetval.mfOLMR) || rtl::math::approxEqual(aRetval.mfORML, aRetval.mfORMR)); + const bool bPerpendC(rtl::math::approxEqual(rCandidate.mfOLML, rCandidate.mfOLMR) || rtl::math::approxEqual(rCandidate.mfORML, rCandidate.mfORMR)); + + if(!bPerpendR && !bPerpendC) + { + // when both are not perpend, create medium cut + const double fNewOLML(std::max(std::min(rCandidate.mfOLML, rCandidate.mfORML), std::min(aRetval.mfOLML, aRetval.mfORML))); + const double fNewORML(std::min(std::max(rCandidate.mfOLML, rCandidate.mfORML), std::max(aRetval.mfOLML, aRetval.mfORML))); + const double fNewOLMR(std::max(std::min(rCandidate.mfOLMR, rCandidate.mfORMR), std::min(aRetval.mfOLMR, aRetval.mfORMR))); + const double fNewORMR(std::min(std::max(rCandidate.mfOLMR, rCandidate.mfORMR), std::max(aRetval.mfOLMR, aRetval.mfORMR))); + aRetval.mfOLML = fNewOLML; + aRetval.mfORML = fNewORML; + aRetval.mfOLMR = fNewOLMR; + aRetval.mfORMR = fNewORMR; + fRetval = aRetval.mfOLML + aRetval.mfORML + aRetval.mfOLMR + aRetval.mfORMR; + } + else { - fRetval = fCandidate; - aRetval = rCandidate; + // if equal and perpend differs, perpend one is assumed smaller + bCopy = ((bMin && bPerpendC && !bPerpendR) || (!bMin && !bPerpendC && bPerpendR)); } } else { - if(fCandidate > fRetval) - { - fRetval = fCandidate; - aRetval = rCandidate; - } + bCopy = ((bMin && fCandidate < fRetval) || (!bMin && fCandidate > fRetval)); + } + + if(bCopy) + { + fRetval = fCandidate; + aRetval = rCandidate; } } -- cgit v1.2.3