diff options
author | Armin Le Grand <Armin.Le.Grand@cib.de> | 2017-09-08 13:39:29 +0200 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@cib.de> | 2017-09-15 12:58:03 +0200 |
commit | 98ceb50c0a65708729df8f2967e616f52db42261 (patch) | |
tree | ee6778f55564729e3bbc85c108235538f1e460a6 | |
parent | 0d2b5305263b01fbefdc998cfc713e36084d6294 (diff) |
borderline: Adapted BorderLinePrimitive2D and usages
Big changes to BorderLinePrimitive2D and BorderLine, freeing
it from one/three entries, going to a free definition using
gaps with width but without color. Adapted usages and creation,
not yet tested much
Change-Id: Ic1255a790401901c3166d200205bc23322b37185
-rw-r--r-- | drawinglayer/CppunitTest_drawinglayer_border.mk | 1 | ||||
-rw-r--r-- | drawinglayer/qa/unit/border.cxx | 105 | ||||
-rw-r--r-- | drawinglayer/source/primitive2d/borderlineprimitive2d.cxx | 434 | ||||
-rw-r--r-- | include/drawinglayer/primitive2d/borderlineprimitive2d.hxx | 124 | ||||
-rw-r--r-- | svx/source/dialog/framelink.cxx | 703 | ||||
-rw-r--r-- | svx/source/dialog/framelinkarray.cxx | 10 | ||||
-rw-r--r-- | sw/source/core/layout/paintfrm.cxx | 187 |
7 files changed, 572 insertions, 992 deletions
diff --git a/drawinglayer/CppunitTest_drawinglayer_border.mk b/drawinglayer/CppunitTest_drawinglayer_border.mk index 194c86a6e8ca..fa2f715590cd 100644 --- a/drawinglayer/CppunitTest_drawinglayer_border.mk +++ b/drawinglayer/CppunitTest_drawinglayer_border.mk @@ -25,6 +25,7 @@ $(eval $(call gb_CppunitTest_use_libraries,drawinglayer_border, \ test \ tl \ unotest \ + svt \ )) $(eval $(call gb_CppunitTest_use_externals,drawinglayer_border,\ diff --git a/drawinglayer/qa/unit/border.cxx b/drawinglayer/qa/unit/border.cxx index a070f9cdff24..e56a40dac379 100644 --- a/drawinglayer/qa/unit/border.cxx +++ b/drawinglayer/qa/unit/border.cxx @@ -25,6 +25,7 @@ #include <vcl/vclptr.hxx> #include <vcl/virdev.hxx> #include <editeng/borderline.hxx> +#include <svtools/borderhelper.hxx> using namespace com::sun::star; @@ -49,7 +50,7 @@ void DrawinglayerBorderTest::testDoubleDecompositionSolid() // 1.47 pixels is 0.03cm at 130% zoom and 96 DPI. basegfx::B2DPoint aStart(0, 20); basegfx::B2DPoint aEnd(100, 20); - double fLeftWidth = 1.47; + double const fLeftWidth = 1.47; double const fDistance = 1.47; double const fRightWidth = 1.47; double const fExtendLeftStart = 0; @@ -58,30 +59,39 @@ void DrawinglayerBorderTest::testDoubleDecompositionSolid() double const fExtendRightEnd = 0; basegfx::BColor aColorRight; basegfx::BColor aColorLeft; - basegfx::BColor aColorGap; - bool const bHasGapColor = false; - SvxBorderLineStyle const nStyle = SvxBorderLineStyle::DOUBLE; + const std::vector<double> aDashing(svtools::GetLineDashing(SvxBorderLineStyle::DOUBLE, 10.0)); + const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing); + std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines; + + aBorderlines.push_back( + drawinglayer::primitive2d::BorderLine( + drawinglayer::attribute::LineAttribute( + aColorLeft, + fLeftWidth), + fExtendLeftStart, + fExtendLeftStart, + fExtendLeftEnd, + fExtendLeftEnd)); + + aBorderlines.push_back( + drawinglayer::primitive2d::BorderLine(fDistance)); + + aBorderlines.push_back( + drawinglayer::primitive2d::BorderLine( + drawinglayer::attribute::LineAttribute( + aColorRight, + fRightWidth), + fExtendRightStart, + fExtendRightStart, + fExtendRightEnd, + fExtendRightEnd)); + rtl::Reference<drawinglayer::primitive2d::BorderLinePrimitive2D> aBorder( new drawinglayer::primitive2d::BorderLinePrimitive2D( aStart, aEnd, - drawinglayer::primitive2d::BorderLine( - fLeftWidth, - aColorLeft, - drawinglayer::primitive2d::BorderLineExtend( - fExtendLeftStart, - fExtendLeftEnd)), - drawinglayer::primitive2d::BorderLine( - fDistance, - aColorGap), - drawinglayer::primitive2d::BorderLine( - fRightWidth, - aColorRight, - drawinglayer::primitive2d::BorderLineExtend( - fExtendRightStart, - fExtendRightEnd)), - bHasGapColor, - nStyle)); + aBorderlines, + aStrokeAttribute)); // Decompose it into polygons. drawinglayer::geometry::ViewInformation2D aView; @@ -126,33 +136,42 @@ void DrawinglayerBorderTest::testDoublePixelProcessing() double const fExtendRightEnd = 0; basegfx::BColor aColorRight; basegfx::BColor aColorLeft; - basegfx::BColor aColorGap; - bool const bHasGapColor = false; - SvxBorderLineStyle const nStyle = SvxBorderLineStyle::DOUBLE; - rtl::Reference<drawinglayer::primitive2d::BorderLinePrimitive2D> xBorder( + const std::vector<double> aDashing(svtools::GetLineDashing(SvxBorderLineStyle::DOUBLE, 10.0)); + const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing); + std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines; + + aBorderlines.push_back( + drawinglayer::primitive2d::BorderLine( + drawinglayer::attribute::LineAttribute( + aColorLeft, + fLeftWidth), + fExtendLeftStart, + fExtendLeftStart, + fExtendLeftEnd, + fExtendLeftEnd)); + + aBorderlines.push_back( + drawinglayer::primitive2d::BorderLine(fDistance)); + + aBorderlines.push_back( + drawinglayer::primitive2d::BorderLine( + drawinglayer::attribute::LineAttribute( + aColorRight, + fRightWidth), + fExtendRightStart, + fExtendRightStart, + fExtendRightEnd, + fExtendRightEnd)); + + rtl::Reference<drawinglayer::primitive2d::BorderLinePrimitive2D> aBorder( new drawinglayer::primitive2d::BorderLinePrimitive2D( aStart, aEnd, - drawinglayer::primitive2d::BorderLine( - fLeftWidth, - aColorLeft, - drawinglayer::primitive2d::BorderLineExtend( - fExtendLeftStart, - fExtendLeftEnd)), - drawinglayer::primitive2d::BorderLine( - fDistance, - aColorGap), - drawinglayer::primitive2d::BorderLine( - fRightWidth, - aColorRight, - drawinglayer::primitive2d::BorderLineExtend( - fExtendRightStart, - fExtendRightEnd)), - bHasGapColor, - nStyle)); + aBorderlines, + aStrokeAttribute)); drawinglayer::primitive2d::Primitive2DContainer aPrimitives; - aPrimitives.push_back(drawinglayer::primitive2d::Primitive2DReference(xBorder.get())); + aPrimitives.push_back(drawinglayer::primitive2d::Primitive2DReference(aBorder.get())); // Process the primitives. pProcessor->process(aPrimitives); diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx index 47da04a10945..9421ed8b249b 100644 --- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx @@ -37,140 +37,56 @@ namespace drawinglayer { namespace primitive2d { - BorderLineExtend::BorderLineExtend() - : mfExtends() - { - } - - BorderLineExtend::BorderLineExtend( - double fStart, - double fEnd) - : mfExtends(2) - { - mfExtends[0] = fStart; - mfExtends[1] = fEnd; - } - - BorderLineExtend::BorderLineExtend( + BorderLine::BorderLine( + const drawinglayer::attribute::LineAttribute& rLineAttribute, double fStartLeft, double fStartRight, double fEndLeft, double fEndRight) - : mfExtends(4) - { - mfExtends[0] = fStartLeft; - mfExtends[1] = fStartRight; - mfExtends[2] = fEndLeft; - mfExtends[3] = fEndRight; - } - - BorderLineExtend::~BorderLineExtend() - { - } - - bool BorderLineExtend::equalStart() const + : maLineAttribute(rLineAttribute), + mfStartLeft(fStartLeft), + mfStartRight(fStartRight), + mfEndLeft(fEndLeft), + mfEndRight(fEndRight), + mbIsGap(false) { - if (mfExtends.empty()|| 2 == mfExtends.size()) - return true; - return mfExtends[0] == mfExtends[1]; } - bool BorderLineExtend::equalEnd() const - { - if (mfExtends.empty() || 2 == mfExtends.size()) - return true; - return mfExtends[2] == mfExtends[3]; - } - - double BorderLineExtend::getStartLeft() const - { - if (mfExtends.empty()) - return 0.0; - return mfExtends[0]; - } - - double BorderLineExtend::getStartRight() const - { - if (mfExtends.empty()) - return 0.0; - if (2 == mfExtends.size()) - return mfExtends[0]; - return mfExtends[1]; - } - - double BorderLineExtend::getEndLeft() const + BorderLine::BorderLine( + double fWidth) + : maLineAttribute(basegfx::BColor(), fWidth), + mfStartLeft(0.0), + mfStartRight(0.0), + mfEndLeft(0.0), + mfEndRight(0.0), + mbIsGap(true) { - if (mfExtends.empty()) - return 0.0; - if (2 == mfExtends.size()) - return mfExtends[1]; - return mfExtends[2]; } - double BorderLineExtend::getEndRight() const { - if (mfExtends.empty()) - return 0.0; - if (2 == mfExtends.size()) - return mfExtends[1]; - return mfExtends[3]; - } - - double BorderLineExtend::getStartAverage() const + BorderLine::~BorderLine() { - if (mfExtends.empty()) - return 0.0; - if (2 == mfExtends.size()) - return mfExtends[0]; - return (mfExtends[0] + mfExtends[1]) * 0.5; } - double BorderLineExtend::getEndAverage() const + bool BorderLine::operator==(const BorderLine& rBorderLine) const { - if (mfExtends.empty()) - return 0.0; - if (2 == mfExtends.size()) - return mfExtends[1]; - return (mfExtends[2] + mfExtends[3]) * 0.5; + return getLineAttribute() == rBorderLine.getLineAttribute() + && getStartLeft() == rBorderLine.getStartLeft() + && getStartRight() == rBorderLine.getStartRight() + && getEndLeft() == rBorderLine.getEndLeft() + && getEndRight() == rBorderLine.getEndRight() + && isGap() == rBorderLine.isGap(); } - bool BorderLineExtend::operator==(const BorderLineExtend& rBorderLineExtend) const + double BorderLine::getAdaptedWidth(double fMinWidth) const { - if (mfExtends.size() == rBorderLineExtend.mfExtends.size()) + if(isGap()) { - return mfExtends == rBorderLineExtend.mfExtends; + return std::max(getLineAttribute().getWidth(), fMinWidth); + } + else + { + return getLineAttribute().getWidth(); } - - return false; - } - - BorderLine::BorderLine( - double fWidth, - const basegfx::BColor& rRGBColor, - const BorderLineExtend& rBorderLineExtend) - : mfWidth(fWidth), - maRGBColor(rRGBColor), - maBorderLineExtend(rBorderLineExtend) - { - } - - BorderLine::BorderLine( - double fWidth, - const basegfx::BColor& rRGBColor) - : mfWidth(fWidth), - maRGBColor(rRGBColor), - maBorderLineExtend() - { - } - - BorderLine::~BorderLine() - { - } - - bool BorderLine::operator==(const BorderLine& rBorderLine) const - { - return getWidth() == rBorderLine.getWidth() - && getRGBColor() == rBorderLine.getRGBColor() - && getBorderLineExtend() == rBorderLine.getBorderLineExtend(); } // helper to add a centered, maybe stroked line primitive to rContainer @@ -179,7 +95,7 @@ namespace drawinglayer const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd, const attribute::LineAttribute& rLineAttribute, - const attribute::StrokeAttribute & rStrokeAttribute) + const attribute::StrokeAttribute& rStrokeAttribute) { basegfx::B2DPolygon aPolygon; @@ -203,94 +119,135 @@ namespace drawinglayer } } + double BorderLinePrimitive2D::getFullWidth() const + { + double fRetval(0.0); + + for(const auto& candidate : maBorderLines) + { + fRetval += candidate.getAdaptedWidth(mfSmallestAllowedDiscreteGapDistance); + } + + return fRetval; + } + void BorderLinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if (!getStart().equal(getEnd())) + if (!getStart().equal(getEnd()) && !getBorderLines().empty()) { // get data and vectors basegfx::B2DVector aVector(getEnd() - getStart()); aVector.normalize(); const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector)); - static double fPatScFact(10.0); // 10.0 multiply, see old code - const std::vector<double> aDashing(svtools::GetLineDashing(getStyle(), getPatternScale() * fPatScFact)); - const attribute::StrokeAttribute aStrokeAttribute(aDashing); + const double fFullWidth(getFullWidth()); + double fOffset(fFullWidth * -0.5); - if (3 == getBorderLines().size()) + for(const auto& candidate : maBorderLines) { - // double line with gap. Use mfDiscreteGapDistance (see get2DDecomposition) as distance. - // That value is prepared to be at least one pixel (discrete unit) so that the - // decomposition is view-dependent in this cases - const BorderLine& rLeft(getBorderLines()[0]); - const BorderLine& rGap(getBorderLines()[1]); - const BorderLine& rRight(getBorderLines()[2]); - const double fFullWidth(rLeft.getWidth() + mfDiscreteGapDistance + rRight.getWidth()); + const double fWidth(candidate.getAdaptedWidth(mfSmallestAllowedDiscreteGapDistance) * 0.5); + if(!candidate.isGap()) { - // inside line (left of vector). Create stroke primitive centered on left line width - const double fDeltaY((rLeft.getWidth() - fFullWidth) * 0.5); - const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY); - const basegfx::B2DPoint aStart(getStart() - (aVector * rLeft.getBorderLineExtend().getStartAverage()) + aDeltaY); - const basegfx::B2DPoint aEnd(getEnd() + (aVector * rLeft.getBorderLineExtend().getEndAverage()) + aDeltaY); - const attribute::LineAttribute aLineAttribute(rLeft.getRGBColor(), rLeft.getWidth()); + 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, - aLineAttribute, - aStrokeAttribute); + candidate.getLineAttribute(), + getStrokeAttribute()); } - if (hasGapColor()) - { - // gap (if visible, found practical usage in Writer MultiColorBorderLines). - // Create stroke primitive on vector with given color centered on gap position - const double fDeltaY(((fFullWidth - mfDiscreteGapDistance) * 0.5) - rRight.getWidth()); - const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY); - const basegfx::B2DPoint aStart(getStart() - (aVector * rGap.getBorderLineExtend().getStartAverage()) + aDeltaY); - const basegfx::B2DPoint aEnd(getEnd() + (aVector * rGap.getBorderLineExtend().getEndAverage()) + aDeltaY); - const attribute::LineAttribute aLineAttribute(rGap.getRGBColor(), mfDiscreteGapDistance); - - addPolygonStrokePrimitive2D( - rContainer, - aStart, - aEnd, - aLineAttribute, - aStrokeAttribute); - } - - { - // outside line (right of vector). Create stroke primitive centered on right line width - const double fDeltaY((fFullWidth - rRight.getWidth()) * 0.5); - const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY); - const basegfx::B2DPoint aStart(getStart() - (aVector * rRight.getBorderLineExtend().getStartAverage()) + aDeltaY); - const basegfx::B2DPoint aEnd(getEnd() + (aVector * rRight.getBorderLineExtend().getEndAverage()) + aDeltaY); - const attribute::LineAttribute aLineAttribute(rRight.getRGBColor(), rRight.getWidth()); - - addPolygonStrokePrimitive2D( - rContainer, - aStart, - aEnd, - aLineAttribute, - aStrokeAttribute); - } - } - else - { - // single line, only inside values used, no vertical offsets - const BorderLine& rBorderLine(getBorderLines()[0]); - const attribute::LineAttribute aLineAttribute(rBorderLine.getRGBColor(), rBorderLine.getWidth()); - - addPolygonStrokePrimitive2D( - rContainer, - getStart() - (aVector * rBorderLine.getBorderLineExtend().getStartAverage()), - getEnd() + (aVector * rBorderLine.getBorderLineExtend().getEndAverage()), - aLineAttribute, - aStrokeAttribute); + fOffset += fWidth; } } } + + + + // static double fPatScFact(10.0); // 10.0 multiply, see old code + // const std::vector<double> aDashing(svtools::GetLineDashing(getStyle(), getPatternScale() * fPatScFact)); + // const attribute::StrokeAttribute aStrokeAttribute(aDashing); + + // if (3 == getBorderLines().size()) + // { + // // double line with gap. Use mfSmallestAllowedDiscreteGapDistance (see get2DDecomposition) as distance. + // // That value is prepared to be at least one pixel (discrete unit) so that the + // // decomposition is view-dependent in this cases + // const BorderLine& rLeft(getBorderLines()[0]); + // const BorderLine& rGap(getBorderLines()[1]); + // const BorderLine& rRight(getBorderLines()[2]); + // const double fFullWidth(rLeft.getWidth() + mfSmallestAllowedDiscreteGapDistance + rRight.getWidth()); + + // { + // // inside line (left of vector). Create stroke primitive centered on left line width + // const double fDeltaY((rLeft.getWidth() - fFullWidth) * 0.5); + // const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY); + // const basegfx::B2DPoint aStart(getStart() - (aVector * rLeft.getBorderLineExtend().getStartAverage()) + aDeltaY); + // const basegfx::B2DPoint aEnd(getEnd() + (aVector * rLeft.getBorderLineExtend().getEndAverage()) + aDeltaY); + // const attribute::LineAttribute aLineAttribute(rLeft.getRGBColor(), rLeft.getWidth()); + + // addPolygonStrokePrimitive2D( + // rContainer, + // aStart, + // aEnd, + // aLineAttribute, + // aStrokeAttribute); + // } + + // if (hasGapColor()) + // { + // // gap (if visible, found practical usage in Writer MultiColorBorderLines). + // // Create stroke primitive on vector with given color centered on gap position + // const double fDeltaY(((fFullWidth - mfSmallestAllowedDiscreteGapDistance) * 0.5) - rRight.getWidth()); + // const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY); + // const basegfx::B2DPoint aStart(getStart() - (aVector * rGap.getBorderLineExtend().getStartAverage()) + aDeltaY); + // const basegfx::B2DPoint aEnd(getEnd() + (aVector * rGap.getBorderLineExtend().getEndAverage()) + aDeltaY); + // const attribute::LineAttribute aLineAttribute(rGap.getRGBColor(), mfSmallestAllowedDiscreteGapDistance); + + // addPolygonStrokePrimitive2D( + // rContainer, + // aStart, + // aEnd, + // aLineAttribute, + // aStrokeAttribute); + // } + + // { + // // outside line (right of vector). Create stroke primitive centered on right line width + // const double fDeltaY((fFullWidth - rRight.getWidth()) * 0.5); + // const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY); + // const basegfx::B2DPoint aStart(getStart() - (aVector * rRight.getBorderLineExtend().getStartAverage()) + aDeltaY); + // const basegfx::B2DPoint aEnd(getEnd() + (aVector * rRight.getBorderLineExtend().getEndAverage()) + aDeltaY); + // const attribute::LineAttribute aLineAttribute(rRight.getRGBColor(), rRight.getWidth()); + + // addPolygonStrokePrimitive2D( + // rContainer, + // aStart, + // aEnd, + // aLineAttribute, + // aStrokeAttribute); + // } + // } + // else + // { + // // single line, only inside values used, no vertical offsets + // const BorderLine& rBorderLine(getBorderLines()[0]); + // const attribute::LineAttribute aLineAttribute(rBorderLine.getRGBColor(), rBorderLine.getWidth()); + + // addPolygonStrokePrimitive2D( + // rContainer, + // getStart() - (aVector * rBorderLine.getBorderLineExtend().getStartAverage()), + // getEnd() + (aVector * rBorderLine.getBorderLineExtend().getEndAverage()), + // aLineAttribute, + // aStrokeAttribute); + // } + // } + // } + bool BorderLinePrimitive2D::isHorizontalOrVertical(const geometry::ViewInformation2D& rViewInformation) const { if (!getStart().equal(getEnd())) @@ -307,42 +264,15 @@ namespace drawinglayer BorderLinePrimitive2D::BorderLinePrimitive2D( const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd, - const BorderLine& rBorderLine, - SvxBorderLineStyle nStyle, - double fPatternScale) - : BufferedDecompositionPrimitive2D(), - maStart(rStart), - maEnd(rEnd), - maBorderLines(), - mbHasGapColor(false), - mnStyle(nStyle), - mfPatternScale(fPatternScale), - mfDiscreteGapDistance(0.0) - { - maBorderLines.push_back(rBorderLine); - } - - BorderLinePrimitive2D::BorderLinePrimitive2D( - const basegfx::B2DPoint& rStart, - const basegfx::B2DPoint& rEnd, - const BorderLine& rLeft, - const BorderLine& rGap, - const BorderLine& rRight, - bool bHasGapColor, - SvxBorderLineStyle nStyle, - double fPatternScale) + const std::vector< BorderLine >& rBorderLines, + const drawinglayer::attribute::StrokeAttribute& rStrokeAttribute) : BufferedDecompositionPrimitive2D(), maStart(rStart), maEnd(rEnd), - maBorderLines(), - mbHasGapColor(bHasGapColor), - mnStyle(nStyle), - mfPatternScale(fPatternScale), - mfDiscreteGapDistance(0.0) + maBorderLines(rBorderLines), + maStrokeAttribute(rStrokeAttribute), + mfSmallestAllowedDiscreteGapDistance(0.0) { - maBorderLines.push_back(rLeft); - maBorderLines.push_back(rGap); - maBorderLines.push_back(rRight); } bool BorderLinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const @@ -353,9 +283,7 @@ namespace drawinglayer if (getStart() == rCompare.getStart() && getEnd() == rCompare.getEnd() - && hasGapColor() == rCompare.hasGapColor() - && getStyle() == rCompare.getStyle() - && getPatternScale() == rCompare.getPatternScale()) + && getStrokeAttribute() == rCompare.getStrokeAttribute()) { if (getBorderLines().size() == rCompare.getBorderLines().size()) { @@ -373,36 +301,64 @@ namespace drawinglayer return false; } + bool BorderLinePrimitive2D::getSmallestGap(double& rfSmallestGap) const + { + bool bGapFound(false); + + for(const auto& candidate : maBorderLines) + { + if(candidate.isGap()) + { + if(bGapFound) + { + rfSmallestGap = std::min(rfSmallestGap, candidate.getLineAttribute().getWidth()); + } + else + { + bGapFound = true; + rfSmallestGap = candidate.getLineAttribute().getWidth(); + } + } + } + + return bGapFound; + } + void BorderLinePrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const { ::osl::MutexGuard aGuard(m_aMutex); - if (!getStart().equal(getEnd()) && 3 == getBorderLines().size()) + if (!getStart().equal(getEnd()) && getBorderLines().size() > 1) { - // Double line with gap. In this case, we want to be view-dependent. - // Get the current DiscreteUnit, look at X and Y and use the maximum - const basegfx::B2DVector aDiscreteVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); - const double fDiscreteUnit(std::min(fabs(aDiscreteVector.getX()), fabs(aDiscreteVector.getY()))); - - // When discrete unit is bigger than distance (distance is less than one pixel), - // force distance to one pixel. Or expressed different, do not let the distance - // get smaller than one pixel. This is done for screen rendering and compatibility. - // This can also be done using DiscreteMetricDependentPrimitive2D as base class - // for this class, but specialization is better here for later buffering (only - // do this when 'double line with gap') - const double fDistance(getBorderLines()[1].getWidth()); - const double fNewDiscreteDistance(std::max(fDiscreteUnit, fDistance)); - - if (!rtl::math::approxEqual(fNewDiscreteDistance, mfDiscreteGapDistance)) + // Line with potential gap. In this case, we want to be view-dependent. + // get the smallest gap + double fSmallestGap(0.0); + + if(getSmallestGap(fSmallestGap)) { - if (!getBuffered2DDecomposition().empty()) + // Get the current DiscreteUnit, look at X and Y and use the maximum + const basegfx::B2DVector aDiscreteVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); + const double fDiscreteUnit(std::min(fabs(aDiscreteVector.getX()), fabs(aDiscreteVector.getY()))); + + // When discrete unit is bigger than distance (distance is less than one pixel), + // force distance to one pixel. Or expressed different, do not let the distance + // get smaller than one pixel. This is done for screen rendering and compatibility. + // This can also be done using DiscreteMetricDependentPrimitive2D as base class + // for this class, but specialization is better here for later buffering (only + // do this when 'double line with gap') + const double fNewDiscreteDistance(std::max(fDiscreteUnit, fSmallestGap)); + + if (!rtl::math::approxEqual(fNewDiscreteDistance, mfSmallestAllowedDiscreteGapDistance)) { - // conditions of last local decomposition have changed, delete - const_cast< BorderLinePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer()); - } + if (!getBuffered2DDecomposition().empty()) + { + // conditions of last local decomposition have changed, delete + const_cast< BorderLinePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer()); + } - // remember value for usage in create2DDecomposition - const_cast< BorderLinePrimitive2D* >(this)->mfDiscreteGapDistance = fNewDiscreteDistance; + // remember value for usage in create2DDecomposition + const_cast< BorderLinePrimitive2D* >(this)->mfSmallestAllowedDiscreteGapDistance = fNewDiscreteDistance; + } } } diff --git a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx index ad28a5eeaac2..992347c7dc9b 100644 --- a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx @@ -26,6 +26,8 @@ #include <basegfx/color/bcolor.hxx> #include <basegfx/matrix/b2dhommatrix.hxx> #include <basegfx/polygon/b2dpolypolygon.hxx> +#include <drawinglayer/attribute/lineattribute.hxx> +#include <drawinglayer/attribute/strokeattribute.hxx> enum class SvxBorderLineStyle : sal_Int16; @@ -33,70 +35,53 @@ namespace drawinglayer { namespace primitive2d { - /** BorderLineExtend class - */ - class DRAWINGLAYER_DLLPUBLIC BorderLineExtend - { - private: - std::vector<double> mfExtends; - - public: - BorderLineExtend(); - BorderLineExtend( - double fStart, - double fEnd); - BorderLineExtend( - double fStartLeft, - double fStartRight, - double fEndLeft, - double fEndRight); - ~BorderLineExtend(); - - bool equalStart() const; - bool equalEnd() const; - - double getStartLeft() const; - double getStartRight() const; - double getEndLeft() const; - double getEndRight() const; - - double getStartAverage() const; - double getEndAverage() const; - - /// compare operator - bool operator==(const BorderLineExtend& rBorderLineExtend) const; - }; - /** BorderLine class - Helper class holding the style definition for a single part of a full NorderLine definition. + Helper class holding the style definition for a single part of a full BorderLine definition. Line extends are for start/end and for Left/Right, seen in vector direction. If Left != Right that means the line has a diagonal start/end */ class DRAWINGLAYER_DLLPUBLIC BorderLine { private: - // line width - double mfWidth; - - // line color - basegfx::BColor maRGBColor; + // line attribute containing Width, Color and others + drawinglayer::attribute::LineAttribute maLineAttribute; // line extends - BorderLineExtend maBorderLineExtend; + double mfStartLeft; + double mfStartRight; + double mfEndLeft; + double mfEndRight; + + // if this is a gap, this is set to true + bool mbIsGap; public: + // Constructor for visible BorderLine segments BorderLine( - double fWidth, - const basegfx::BColor& rRGBColor, - const BorderLineExtend& rBorderLineExtend); - BorderLine( - double fWidth, - const basegfx::BColor& rRGBColor); + const drawinglayer::attribute::LineAttribute& rLineAttribute, + double fStartLeft = 0.0, + double fStartRight = 0.0, + double fEndLeft = 0.0, + double fEndRight = 0.0); + + // Constructor for gap BorderLine segments + BorderLine(double fWidth); + ~BorderLine(); - double getWidth() const { return mfWidth; } - const basegfx::BColor& getRGBColor() const { return maRGBColor; } - const BorderLineExtend& getBorderLineExtend() const { return maBorderLineExtend; } + const drawinglayer::attribute::LineAttribute& getLineAttribute() const { return maLineAttribute; } + double getStartLeft() const { return mfStartLeft; } + double getStartRight() const { return mfStartRight; } + double getEndLeft() const { return mfEndLeft; } + double getEndRight() const { return mfEndRight; } + bool isGap() const { return mbIsGap; } + + /// 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; @@ -117,50 +102,39 @@ namespace drawinglayer basegfx::B2DPoint maStart; basegfx::B2DPoint maEnd; - /// the single BorderLine style definition(s), one or three allowed (see constructors) + /// the single BorderLine style definition(s), one or three mostly used std::vector< BorderLine > maBorderLines; - bool mbHasGapColor; - /// common style definitions - SvxBorderLineStyle mnStyle; - double mfPatternScale; + const drawinglayer::attribute::StrokeAttribute maStrokeAttribute; - // for view dependent decomposition in the case with distance (gap), - // remember the last used concrete mfDistance, see get2DDecomposition + // for view dependent decomposition in the case with existing gaps, + // remember the smallest allowed concrete gap distance, see get2DDecomposition // implementation - double mfDiscreteGapDistance; + double mfSmallestAllowedDiscreteGapDistance; /// create local decomposition virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override; + /// helper to find smallest defined gap in maBorderLines + bool getSmallestGap(double& rfSmallestGap) const; + + /// helper to get the full width taking mfSmallestAllowedDiscreteGapDistance into account + double getFullWidth() const; + public: /// simplified constructor for BorderLine with single edge BorderLinePrimitive2D( const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd, - const BorderLine& rBorderLine, - SvxBorderLineStyle nStyle, - double fPatternScale = 1.0); - - /// constructor for full-fledged BorderLine with two edges and gap - BorderLinePrimitive2D( - const basegfx::B2DPoint& rStart, - const basegfx::B2DPoint& rEnd, - const BorderLine& rLeft, - const BorderLine& rGap, - const BorderLine& rRight, - bool bHasGapColor, - SvxBorderLineStyle nStyle, - double fPatternScale = 1.0); + const std::vector< BorderLine >& rBorderLines, + const drawinglayer::attribute::StrokeAttribute& rStrokeAttribute); /// data read access const basegfx::B2DPoint& getStart() const { return maStart; } const basegfx::B2DPoint& getEnd() const { return maEnd; } const std::vector< BorderLine >& getBorderLines() const { return maBorderLines; } - bool hasGapColor() const { return mbHasGapColor; } - SvxBorderLineStyle getStyle() const { return mnStyle; } - double getPatternScale() const { return mfPatternScale; } + const drawinglayer::attribute::StrokeAttribute& getStrokeAttribute() const { return maStrokeAttribute; } /// helper to decide if AntiAliasing should be used bool isHorizontalOrVertical(const geometry::ViewInformation2D& rViewInformation) const; diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx index 4869535a76f3..ca66b285f8d4 100644 --- a/svx/source/dialog/framelink.cxx +++ b/svx/source/dialog/framelink.cxx @@ -358,404 +358,15 @@ bool CheckFrameBorderConnectable( const Style& rLBorder, const Style& rRBorder, } // Drawing functions -// struct OffsetPair -// { -// double mfLeft; -// double mfRight; - -// OffsetPair(double a, double b) : mfLeft(a), mfRight(b) {} -// }; - -// struct OffsetCutSet -// { -// double mfLeftLeft; -// double mfRightLeft; -// double mfLeftRight; -// double mfRightRight; -// }; - -// const OffsetCutSet* getMinMaxCutSet(bool bMin, const std::vector< OffsetCutSet >& myCutSets) -// { -// if (myCutSets.empty()) -// { -// return nullptr; -// } - -// if (1 == myCutSets.size()) -// { -// return &myCutSets[0]; -// } - -// const OffsetCutSet* pRetval = &myCutSets[0]; -// double fRetval(pRetval->mfLeftLeft + pRetval->mfLeftRight + pRetval->mfRightLeft + pRetval->mfRightRight); - -// for (size_t a(1); a < myCutSets.size(); a++) -// { -// const OffsetCutSet* pCandidate = &myCutSets[a]; -// const double fCandidate(pCandidate->mfLeftLeft + pCandidate->mfLeftRight + pCandidate->mfRightLeft + pCandidate->mfRightRight); - -// if ((bMin && fCandidate < fRetval) || (!bMin && fCandidate > fRetval)) -// { -// pRetval = pCandidate; -// fRetval = fCandidate; -// } -// } - -// return pRetval; -// } - -// void getOffsetPairsFromStyle(const Style& rStyle, std::vector< OffsetPair >& offsets) -// { -// if (rStyle.IsUsed()) -// { -// if (rStyle.Dist() && rStyle.Secn()) -// { -// // both lines used (or all three), push four values, from outer to inner -// switch (rStyle.GetRefMode()) -// { -// case RefMode::Centered: -// { -// const double fHalfFullWidth(rStyle.GetWidth() * 0.5); -// offsets.push_back(OffsetPair(-fHalfFullWidth, rStyle.Prim() - fHalfFullWidth)); -// offsets.push_back(OffsetPair((rStyle.Prim() + rStyle.Dist()) - fHalfFullWidth, fHalfFullWidth)); -// break; -// } -// case RefMode::Begin: -// { -// offsets.push_back(OffsetPair(0.0, rStyle.Prim())); -// offsets.push_back(OffsetPair(rStyle.Prim() + rStyle.Dist(), rStyle.GetWidth())); -// break; -// } -// default: // case RefMode::End: -// { -// const double fFullWidth(rStyle.GetWidth()); -// offsets.push_back(OffsetPair(-fFullWidth, rStyle.Prim() - fFullWidth)); -// offsets.push_back(OffsetPair((rStyle.Prim() + rStyle.Dist()) - fFullWidth, 0.0)); -// break; -// } -// } -// } -// else -// { -// // one line used, push two values, from outer to inner -// switch (rStyle.GetRefMode()) -// { -// case RefMode::Centered: -// offsets.push_back(OffsetPair(rStyle.Prim() * -0.5, rStyle.Prim() * 0.5)); -// break; -// case RefMode::Begin: -// offsets.push_back(OffsetPair(0.0, rStyle.Prim())); -// break; -// default: // case RefMode::End: -// offsets.push_back(OffsetPair(-rStyle.Prim(), 0.0)); -// break; -// } -// } -// } -// } - -// void createCutsWithStyle( -// const basegfx::B2DPoint& rOrigin, -// const basegfx::B2DVector& rOtherVector, -// const basegfx::B2DVector& rOtherUnifiedPerpendicular, -// const OffsetPair& rOtherOffsets, -// const Style& rStyle, -// const basegfx::B2DVector& rMyVector, -// std::vector< OffsetCutSet>& rOtherCuts) -// { -// if (rStyle.IsUsed()) -// { -// // get values dependent on source vector -// const basegfx::B2DVector aMyUnifiedPerpendicular(basegfx::getNormalizedPerpendicular(rMyVector)); -// const basegfx::B2DPoint aOtherPosLeft(rOrigin + (rOtherUnifiedPerpendicular * rOtherOffsets.mfLeft)); -// const basegfx::B2DPoint aOtherPosRight(rOrigin + (rOtherUnifiedPerpendicular * rOtherOffsets.mfRight)); -// std::vector< OffsetPair > myOffsets; - -// // get offsets from outer to inner from target style (one or two) -// getOffsetPairsFromStyle(rStyle, myOffsets); - -// for (const auto& myOffset : myOffsets) -// { -// // get values for new vectors and create all four cuts -// const basegfx::B2DPoint aMyPosLeft(rOrigin + (aMyUnifiedPerpendicular * myOffset.mfLeft)); -// const basegfx::B2DPoint aMyPosRight(rOrigin + (aMyUnifiedPerpendicular * myOffset.mfRight)); -// OffsetCutSet aNewCuts; - -// basegfx::tools::findCut( -// aOtherPosLeft, -// rOtherVector, -// aMyPosLeft, -// rMyVector, -// CutFlagValue::LINE, -// &aNewCuts.mfLeftLeft); - -// basegfx::tools::findCut( -// aOtherPosLeft, -// rOtherVector, -// aMyPosRight, -// rMyVector, -// CutFlagValue::LINE, -// &aNewCuts.mfLeftRight); - -// basegfx::tools::findCut( -// aOtherPosRight, -// rOtherVector, -// aMyPosLeft, -// rMyVector, -// CutFlagValue::LINE, -// &aNewCuts.mfRightLeft); - -// basegfx::tools::findCut( -// aOtherPosRight, -// rOtherVector, -// aMyPosRight, -// rMyVector, -// CutFlagValue::LINE, -// &aNewCuts.mfRightRight); - -// rOtherCuts.push_back(aNewCuts); -// } -// } -// } - -// double getSimpleExtendedLineValues( -// const basegfx::B2DPoint& rOrigin, -// const basegfx::B2DVector& rX, -// const basegfx::B2DVector& rY, -// const basegfx::B2DVector& rPerpendX, -// const OffsetPair& myOffset, -// const Style& rFirst, -// const Style& rSecond, -// bool bEdgeStart, -// double fLength) -// { -// std::vector< OffsetCutSet > myCutSets; -// createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rFirst, rY, myCutSets); -// createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rSecond, rY, myCutSets); -// const OffsetCutSet* pResult = getMinMaxCutSet(bEdgeStart, myCutSets); - -// if (pResult) -// { -// if (bEdgeStart) -// { -// return (pResult->mfLeftRight + pResult->mfRightRight) * -0.5 * fLength; -// } -// else -// { -// return (pResult->mfLeftLeft + pResult->mfRightLeft) * 0.5 * fLength; -// } -// } - -// return 0.0; -// } - -// double getComplexExtendedLineValues( -// const basegfx::B2DPoint& rOrigin, -// const basegfx::B2DVector& rX, -// const basegfx::B2DVector& rY, -// const basegfx::B2DVector& rPerpendX, -// const OffsetPair& myOffset, -// const Style& rFirst, -// const Style& rSecond, -// bool bEdgeStart, -// double fLength) -// { -// std::vector< OffsetCutSet > myCutSets; -// createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rFirst, rY, myCutSets); -// const OffsetCutSet* pResult = getMinMaxCutSet(!bEdgeStart, myCutSets); - -// if (!pResult) -// { -// createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rSecond, rY, myCutSets); -// pResult = getMinMaxCutSet(bEdgeStart, myCutSets); -// } - -// if (pResult) -// { -// if (bEdgeStart) -// { -// return (pResult->mfLeftRight + pResult->mfRightRight) * 0.5 * -fLength; -// } -// else -// { -// return (pResult->mfLeftLeft + pResult->mfRightLeft) * 0.5 * fLength; -// } -// } - -// return 0.0; -// } - -// void CreateBorderPrimitives( -// drawinglayer::primitive2d::Primitive2DContainer& rTarget, -// const basegfx::B2DPoint& rOrigin, -// const basegfx::B2DVector& rX, -// const basegfx::B2DVector& rY, -// const Style& rBorder, -// const Style& /*rLFromTR*/, -// const Style& rLFromT, -// const Style& /*rLFromL*/, -// const Style& rLFromB, -// const Style& /*rLFromBR*/, -// const Style& /*rRFromTL*/, -// const Style& rRFromT, -// const Style& /*rRFromR*/, -// const Style& rRFromB, -// const Style& /*rRFromBL*/, -// const Color* pForceColor) -// { -// if (rBorder.IsUsed()) -// { -// const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX)); -// const double fLength(rX.getLength()); - -// // do not forget RefMode offset, primitive will assume RefMode::Centered -// basegfx::B2DVector aRefModeOffset; - -// if (RefMode::Centered != rBorder.GetRefMode()) -// { -// const double fHalfWidth(rBorder.GetWidth() * 0.5); - -// if (RefMode::Begin == rBorder.GetRefMode()) -// { -// // move aligned below vector -// aRefModeOffset = aPerpendX * fHalfWidth; -// } -// else if (RefMode::End == rBorder.GetRefMode()) -// { -// // move aligned above vector -// aRefModeOffset = aPerpendX * -fHalfWidth; -// } -// } - -// // create start/end (use RefMode) -// const basegfx::B2DPoint aStart(rOrigin + aRefModeOffset); -// const basegfx::B2DPoint aEnd(aStart + rX); - -// // get offsets for my style (one or two) -// std::vector< OffsetPair > myOffsets; -// getOffsetPairsFromStyle(rBorder, myOffsets); - -// if (1 == myOffsets.size()) -// { -// // we are a single edge, calculate cuts with edges coming from above/below -// // to detect the line start/end extensions -// const OffsetPair& myOffset(myOffsets[0]); -// double mfExtendStart(0.0); -// double mfExtendEnd(0.0); - -// // for start: get cuts with all left target styles and use the minimum -// mfExtendStart = getSimpleExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffset, rLFromT, rLFromB, true, fLength); - -// // for end: get cuts with all right target styles and use the maximum -// mfExtendEnd = getSimpleExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffset, rRFromT, rRFromB, false, fLength); - -// rTarget.append( -// drawinglayer::primitive2d::Primitive2DReference( -// new drawinglayer::primitive2d::BorderLinePrimitive2D( -// aStart, -// aEnd, -// drawinglayer::primitive2d::BorderLine( -// rBorder.Prim(), -// (pForceColor ? *pForceColor : rBorder.GetColorPrim()).getBColor(), -// drawinglayer::primitive2d::BorderLineExtend( -// mfExtendStart, -// mfExtendEnd)), -// rBorder.Type(), -// rBorder.PatternScale()))); -// } -// else if (2 == myOffsets.size()) -// { -// // we are a double edge, calculate cuts with edges coming from above/below -// // for both edges to detect the line start/end extensions. In the future this -// // needs to be extended to use two values per extension, getComplexExtendedLineValues -// // internally prepares these already. drawinglayer::primitive2d::BorderLine will -// // then need to take these double entries (maybe a pair) and use them internally. -// double mfExtendLeftStart(0.0); -// double mfExtendLeftEnd(0.0); -// double mfExtendRightStart(0.0); -// double mfExtendRightEnd(0.0); - -// // for start of first edge, get cuts with left targets. Start with upper and take maximum when -// // cut exists. Else use lower and take minimum when cut exists -// mfExtendLeftStart = getComplexExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffsets[0], rLFromT, rLFromB, true, fLength); - -// // for end of first edge, get cuts with right targets. Start with upper and take minimum when -// // cut exists. Else use lower and take maximum when cut exists -// mfExtendLeftEnd = getComplexExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffsets[0], rRFromT, rRFromB, false, fLength); - -// // for start of second edge, get cuts with left targets. Start with lower and take maximum when -// // cut exists. Else use upper and take minimum when cut exists -// mfExtendRightStart = getComplexExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffsets[1], rLFromB, rLFromT, true, fLength); - -// // for end of second edge, get cuts with right targets. Start with lower and take minimum when -// // cut exists. Else use upper and take maximum when cut exists -// mfExtendRightEnd = getComplexExtendedLineValues(rOrigin, rX, rY, aPerpendX, myOffsets[1], rRFromB, rRFromT, false, fLength); - -// // needs to be determined in detail later, for now use the max prolongation -// // from left/right, but do not less than half (0.0). This works decently, -// // but not perfect (see Writer, use three-color-style, look at upper/lower# -// // connections) -// const double fGapLeft(std::max(0.0, std::max(mfExtendLeftStart, mfExtendRightStart))); -// const double fGapRight(std::max(0.0, std::max(mfExtendLeftEnd, mfExtendRightEnd))); - -// rTarget.append( -// drawinglayer::primitive2d::Primitive2DReference( -// new drawinglayer::primitive2d::BorderLinePrimitive2D( -// aStart, -// aEnd, -// drawinglayer::primitive2d::BorderLine( -// rBorder.Prim(), -// (pForceColor ? *pForceColor : rBorder.GetColorPrim()).getBColor(), -// drawinglayer::primitive2d::BorderLineExtend( -// mfExtendLeftStart, -// mfExtendLeftEnd)), -// drawinglayer::primitive2d::BorderLine( -// rBorder.Dist(), -// (pForceColor ? *pForceColor : rBorder.GetColorGap()).getBColor(), -// drawinglayer::primitive2d::BorderLineExtend( -// fGapLeft, -// fGapRight)), -// drawinglayer::primitive2d::BorderLine( -// rBorder.Secn(), -// (pForceColor ? *pForceColor : rBorder.GetColorSecn()).getBColor(), -// drawinglayer::primitive2d::BorderLineExtend( -// mfExtendRightStart, -// mfExtendRightEnd)), -// rBorder.UseGapColor(), -// rBorder.Type(), -// rBorder.PatternScale()))); -// } -// } -// } - - - - - - - - - - - - - - - - - - - - -struct OffsetWidthColor +struct OffsetAndHalfWidthAndColor { double mfOffset; - double mfWidth; + double mfHalfWidth; Color maColor; - OffsetWidthColor(double offset, double width, Color color) : + OffsetAndHalfWidthAndColor(double offset, double halfWidth, Color color) : mfOffset(offset), - mfWidth(width), + mfHalfWidth(halfWidth), maColor(color) {} }; @@ -768,7 +379,15 @@ struct CutSet double mfORMR; }; -void getOffsetWidthColorFromStyle(const Style& rStyle, std::vector< OffsetWidthColor >& offsets) +struct ExtendSet +{ + double mfExtLeft; + double mfExtRight; + + ExtendSet() : mfExtLeft(0.0), mfExtRight(0.0) {} +}; + +void getOffsetAndHalfWidthAndColorFromStyle(const Style& rStyle, const Color* pForceColor, std::vector< OffsetAndHalfWidthAndColor >& offsets) { if (rStyle.IsUsed()) { @@ -794,24 +413,36 @@ void getOffsetWidthColorFromStyle(const Style& rStyle, std::vector< OffsetWidthC if (rStyle.Dist() && rStyle.Secn()) { // both or all three lines used - const double a(fRefModeOffset - (rStyle.GetWidth() * 0.5)); - const double b(a + rStyle.Prim()); - const double c(b + rStyle.Dist()); - const double d(c + rStyle.Secn()); - - if(0xff != rStyle.GetColorPrim().GetTransparency()) - { - offsets.push_back(OffsetWidthColor((a + b) * 0.5, rStyle.Prim(), rStyle.GetColorPrim())); - } - - if(0xff != rStyle.GetColorGap().GetTransparency() && rStyle.UseGapColor()) - { - offsets.push_back(OffsetWidthColor((b + c) * 0.5, rStyle.Dist(), rStyle.GetColorGap())); - } + const bool bPrimTransparent(0xff == rStyle.GetColorPrim().GetTransparency()); + const bool bDistTransparent(!rStyle.UseGapColor() || 0xff == rStyle.GetColorGap().GetTransparency()); + const bool bSecnTransparent(0xff == rStyle.GetColorSecn().GetTransparency()); - if(0xff != rStyle.GetColorSecn().GetTransparency()) + if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent) { - offsets.push_back(OffsetWidthColor((c + d) * 0.5, rStyle.Secn(), rStyle.GetColorSecn())); + const double a(fRefModeOffset - (rStyle.GetWidth() * 0.5)); + const double b(a + rStyle.Prim()); + const double c(b + rStyle.Dist()); + const double d(c + rStyle.Secn()); + + offsets.push_back( + OffsetAndHalfWidthAndColor( + (a + b) * 0.5, + rStyle.Prim() * 0.5, + nullptr != pForceColor ? *pForceColor : rStyle.GetColorPrim())); + + offsets.push_back( + OffsetAndHalfWidthAndColor( + (b + c) * 0.5, + rStyle.Dist() * 0.5, + rStyle.UseGapColor() + ? (nullptr != pForceColor ? *pForceColor : rStyle.GetColorGap()) + : Color(COL_TRANSPARENT))); + + offsets.push_back( + OffsetAndHalfWidthAndColor( + (c + d) * 0.5, + rStyle.Secn() * 0.5, + nullptr != pForceColor ? *pForceColor : rStyle.GetColorSecn())); } } else @@ -819,69 +450,109 @@ void getOffsetWidthColorFromStyle(const Style& rStyle, std::vector< OffsetWidthC // one line used, push two values, from outer to inner if(0xff != rStyle.GetColorPrim().GetTransparency()) { - offsets.push_back(OffsetWidthColor(fRefModeOffset, rStyle.Prim(), rStyle.GetColorPrim())); + offsets.push_back( + OffsetAndHalfWidthAndColor( + fRefModeOffset, + rStyle.Prim() * 0.5, + nullptr != pForceColor ? *pForceColor : rStyle.GetColorPrim())); } } } } -void findCutsWithStyleVectorTable( - std::vector< CutSet >& rCutSet, - const basegfx::B2DPoint& rOrigin, +void getCutSet( + CutSet& rCutSet, + const basegfx::B2DPoint& rLeft, + const basegfx::B2DPoint& rRight, const basegfx::B2DVector& rX, - double fOffset, - double fHalfWidth, - const StyleVectorTable& rStyleVectorTable) + const basegfx::B2DPoint& rOtherLeft, + const basegfx::B2DPoint& rOtherRight, + const basegfx::B2DVector& rOtherX) { - const basegfx::B2DVector aY(basegfx::getNormalizedPerpendicular(rX)); - basegfx::B2DPoint aMyLeft(rOrigin + (aY * (fOffset - fHalfWidth))); - basegfx::B2DPoint aMyRight(rOrigin + (aY * (fOffset + fHalfWidth))); + 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); +} - for(const auto& style : rStyleVectorTable) +void getExtends( + std::vector<ExtendSet>& rExtendSet, // target Left/Right values to fill + const basegfx::B2DPoint& rOrigin, // own vector start + const basegfx::B2DVector& rX, // own vector direction and length + const basegfx::B2DVector& rPerpendX, // normalized perpendicular to rX + const std::vector< OffsetAndHalfWidthAndColor >& rOffsets, // own vector derivations + const StyleVectorTable& rStyleVectorTable) // other vectors emerging in this point +{ + if(!rOffsets.empty() && rOffsets.size() == rExtendSet.size()) { - std::vector< OffsetWidthColor > myOffsets; - getOffsetWidthColorFromStyle(style.getStyle(), myOffsets); - const basegfx::B2DVector aOtherY(basegfx::getNormalizedPerpendicular(style.getB2DVector())); + const size_t nOffsets(rOffsets.size()); - for(const auto& offset : myOffsets) + for(size_t a(0); a < nOffsets; a++) { - basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherY * (offset.mfOffset - (offset.mfWidth * 0.5)))); - basegfx::B2DPoint aOtherRight(rOrigin + (aOtherY * (offset.mfOffset + (offset.mfWidth * 0.5)))); - CutSet aNewCuts; - - basegfx::tools::findCut( - aOtherLeft, - style.getB2DVector(), - aMyLeft, - rX, - CutFlagValue::LINE, - &aNewCuts.mfOLML); - - basegfx::tools::findCut( - aOtherLeft, - style.getB2DVector(), - aMyRight, - rX, - CutFlagValue::LINE, - &aNewCuts.mfOLMR); - - basegfx::tools::findCut( - aOtherRight, - style.getB2DVector(), - aMyLeft, - rX, - CutFlagValue::LINE, - &aNewCuts.mfORML); - - basegfx::tools::findCut( - aOtherRight, - style.getB2DVector(), - aMyRight, - rX, - CutFlagValue::LINE, - &aNewCuts.mfORMR); - - rCutSet.push_back(aNewCuts); + const OffsetAndHalfWidthAndColor& rOffset(rOffsets[a]); + ExtendSet& rExt(rExtendSet[a]); + bool bExtSet(false); + const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (rOffset.mfOffset - rOffset.mfHalfWidth))); + const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (rOffset.mfOffset + rOffset.mfHalfWidth))); + + for(const auto& rStyleVectorCombination : rStyleVectorTable) + { + std::vector< OffsetAndHalfWidthAndColor > otherOffsets; + getOffsetAndHalfWidthAndColorFromStyle(rStyleVectorCombination.getStyle(), nullptr, otherOffsets); + + if(!otherOffsets.empty()) + { + const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleVectorCombination.getB2DVector())); + + 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; + + getCutSet(aCutSet, aLeft, aRight, rX, aOtherLeft, aOtherRight, rStyleVectorCombination.getB2DVector()); + + if(!bExtSet) + { + rExt.mfExtLeft = std::min(aCutSet.mfOLML, aCutSet.mfORML); + rExt.mfExtRight = std::min(aCutSet.mfOLMR, aCutSet.mfORMR); + bExtSet = true; + } + else + { + rExt.mfExtLeft = std::min(rExt.mfExtLeft , std::min(aCutSet.mfOLML, aCutSet.mfORML)); + rExt.mfExtRight = std::min(rExt.mfExtRight , std::min(aCutSet.mfOLMR, aCutSet.mfORMR)); + } + } + } + } } } } @@ -896,79 +567,71 @@ void CreateBorderPrimitives( const Color* pForceColor) { // get offset color pairs for style, one per visible line - std::vector< OffsetWidthColor > myOffsets; - getOffsetWidthColorFromStyle(rBorder, myOffsets); + std::vector< OffsetAndHalfWidthAndColor > myOffsets; + getOffsetAndHalfWidthAndColorFromStyle(rBorder, pForceColor, myOffsets); + const size_t nOffsets(myOffsets.size()); - if(!myOffsets.empty()) + if(nOffsets) { const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX)); const bool bHasStartStyles(!rStartStyleVectorTable.empty()); const bool bHasEndStyles(!rEndStyleVectorTable.empty()); + std::vector<ExtendSet> aExtendSetStart(nOffsets); + std::vector<ExtendSet> aExtendSetEnd(nOffsets); - if(bHasStartStyles || bHasEndStyles) + if(bHasStartStyles) { - // we have start/end styles, get offset values - double fExtStartLeft(0.0); - double fExtStartRight(0.0); - double fExtEndLeft(0.0); - double fExtEndRight(0.0); + // create extends for line starts, use given point/vector and offsets + getExtends(aExtendSetStart, rOrigin, rX, aPerpendX, myOffsets, rStartStyleVectorTable); + } - for(const auto& offset : myOffsets) - { - const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * offset.mfOffset)); - const basegfx::B2DPoint aEnd(aStart + rX); + if(bHasEndStyles) + { + // create extends for line ends, use inverse point/vector and inverse offsets + std::reverse(myOffsets.begin(), myOffsets.end()); + getExtends(aExtendSetEnd, rOrigin + rX, -rX, -aPerpendX, myOffsets, rEndStyleVectorTable); + } - if(bHasStartStyles) - { - // create extends for line starts - std::vector< CutSet > aStartCutSet; - findCutsWithStyleVectorTable(aStartCutSet, rOrigin, rX, offset.mfOffset, offset.mfWidth * 0.5, rStartStyleVectorTable); - } + std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines; + const double fNegLength(-rX.getLength()); - if(bHasEndStyles) - { - // create extends for line ends - std::vector< CutSet > aEndCutSet; - findCutsWithStyleVectorTable(aEndCutSet, rOrigin + rX, -rX, -offset.mfOffset, offset.mfWidth * 0.5, rStartStyleVectorTable); - } + for(size_t a(0); a < nOffsets; a++) + { + const OffsetAndHalfWidthAndColor& rOffset(myOffsets[a]); + const ExtendSet& rExtStart(aExtendSetStart[a]); + const ExtendSet& rExtEnd(aExtendSetEnd[a]); - rTarget.append( - drawinglayer::primitive2d::Primitive2DReference( - new drawinglayer::primitive2d::BorderLinePrimitive2D( - aStart, - aEnd, - drawinglayer::primitive2d::BorderLine( - offset.mfWidth, - (pForceColor ? *pForceColor : offset.maColor).getBColor(), - drawinglayer::primitive2d::BorderLineExtend( - fExtStartLeft, - fExtStartRight, - fExtEndLeft, - fExtEndRight)), - rBorder.Type(), - rBorder.PatternScale()))); + if(0xff == rOffset.maColor.GetTransparency()) + { + aBorderlines.push_back( + drawinglayer::primitive2d::BorderLine( + rOffset.mfHalfWidth * 2.0)); } - } - else - { - // no start/end styles, just create simple BorderLinePrimitive2D - // for each local partial line - for(const auto& offset : myOffsets) + else { - const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * offset.mfOffset)); - const basegfx::B2DPoint aEnd(aStart + rX); - rTarget.append( - drawinglayer::primitive2d::Primitive2DReference( - new drawinglayer::primitive2d::BorderLinePrimitive2D( - aStart, - aEnd, - drawinglayer::primitive2d::BorderLine( - offset.mfWidth, - (pForceColor ? *pForceColor : offset.maColor).getBColor()), - rBorder.Type(), - rBorder.PatternScale()))); + aBorderlines.push_back( + drawinglayer::primitive2d::BorderLine( + drawinglayer::attribute::LineAttribute( + rOffset.maColor.getBColor(), + rOffset.mfHalfWidth * 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); + + rTarget.append( + drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::BorderLinePrimitive2D( + rOrigin, + rOrigin + rX, + aBorderlines, + aStrokeAttribute))); } } diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx index f8897b7c0a77..6052c23f3e8a 100644 --- a/svx/source/dialog/framelinkarray.cxx +++ b/svx/source/dialog/framelinkarray.cxx @@ -85,7 +85,7 @@ typedef std::vector< Cell > CellVec; size_t Cell::GetCellIndex(const Array& rArray) const { - if(-1 == maCellIndex) + if(static_cast<size_t>(-1) == maCellIndex) { rArray.AddCellIndices(); } @@ -102,7 +102,7 @@ basegfx::B2DHomMatrix Cell::CreateCoordinateSystem(const Array& rArray) const const size_t nCellIndex(GetCellIndex(rArray)); - if(-1 != nCellIndex) + if(static_cast<size_t>(-1) != nCellIndex) { const basegfx::B2DRange aRange(rArray.GetCellRange(nCellIndex)); @@ -976,7 +976,7 @@ void HelperCreateHorizontalEntry( CreateBorderPrimitives( rSequence, - bUpper ? rOrigin : rOrigin + rY, + bUpper ? rOrigin : basegfx::B2DPoint(rOrigin + rY), rX, rStyle, aStart, @@ -1021,7 +1021,7 @@ void HelperCreateVerticalEntry( CreateBorderPrimitives( rSequence, - bLeft ? rOrigin : rOrigin + rX, + bLeft ? rOrigin : basegfx::B2DPoint(rOrigin + rX), rY, rStyle, aStart, @@ -1038,7 +1038,7 @@ void HelperCreateEntry(const Array& rArray, const Style& rStyle, drawinglayer::p { const size_t nCellIndex(pCell->GetCellIndex(rArray)); - if(-1 != nCellIndex) + if(static_cast<size_t>(-1) != nCellIndex) { size_t col(nCellIndex % rArray.GetColCount()); size_t row(nCellIndex / rArray.GetColCount()); diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index 63b5064bb26c..ac2d3ba9e21f 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -111,7 +111,6 @@ using namespace ::editeng; using namespace ::com::sun::star; using ::drawinglayer::primitive2d::BorderLinePrimitive2D; using ::drawinglayer::primitive2d::BorderLine; -using ::drawinglayer::primitive2d::BorderLineExtend; using std::pair; using std::make_pair; @@ -519,56 +518,37 @@ lcl_MergeBorderLines( basegfx::B2DPoint const& rStart, basegfx::B2DPoint const& rEnd) { - const BorderLine& rLineLeft = rLine.getBorderLines()[0]; - const BorderLine& rOtherLeft(rOther.getBorderLines()[0]); - - if (1 == rLine.getBorderLines().size()) - { - return new BorderLinePrimitive2D( - rStart, - rEnd, - BorderLine( - rLineLeft.getWidth(), - rLineLeft.getRGBColor(), - BorderLineExtend( - rLineLeft.getBorderLineExtend().getStartLeft(), - rLineLeft.getBorderLineExtend().getStartRight(), - rOtherLeft.getBorderLineExtend().getEndLeft(), - rOtherLeft.getBorderLineExtend().getEndRight())), - rLine.getStyle()); - } - else + 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& rLineGap(rLine.getBorderLines()[1]); - // const BorderLine& rOtherGap(rOther.getBorderLines()[1]); - const BorderLine& rLineRight(rLine.getBorderLines()[2]); - const BorderLine& rOtherRight(rOther.getBorderLines()[2]); - - return new BorderLinePrimitive2D( - rStart, - rEnd, - BorderLine( - rLineLeft.getWidth(), - rLineLeft.getRGBColor(), - BorderLineExtend( - rLineLeft.getBorderLineExtend().getStartLeft(), - rLineLeft.getBorderLineExtend().getStartRight(), - rOtherLeft.getBorderLineExtend().getEndLeft(), - rOtherLeft.getBorderLineExtend().getEndRight())), - BorderLine( - rLineGap.getWidth(), - rLineGap.getRGBColor()), - BorderLine( - rLineRight.getWidth(), - rLineRight.getRGBColor(), - BorderLineExtend( - rLineRight.getBorderLineExtend().getStartLeft(), - rLineRight.getBorderLineExtend().getStartRight(), - rOtherRight.getBorderLineExtend().getEndLeft(), - rOtherRight.getBorderLineExtend().getEndRight())), - rLine.hasGapColor(), - rLine.getStyle()); + 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()); } /** @@ -601,36 +581,24 @@ lcl_TryMergeBorderLine(BorderLinePrimitive2D const& rThis, double otherWidth = rOther.getEnd().getX() - rOther.getStart().getX(); // check for same orientation, same line width, same style and matching colors - bool bSameStuff(false); - const BorderLine& rThisLeft(rThis.getBorderLines()[0]); - const BorderLine& rOtherLeft(rOther.getBorderLines()[0]); + bool bSameStuff( + ((thisHeight > thisWidth) == (otherHeight > otherWidth)) + && rThis.getStrokeAttribute() == rOther.getStrokeAttribute()); - if (1 == rThis.getBorderLines().size()) - { - bSameStuff = ((thisHeight > thisWidth) == (otherHeight > otherWidth)) - && (rtl::math::approxEqual(rThisLeft.getWidth(), rOtherLeft.getWidth())) - && (rThis.getStyle() == rOther.getStyle()) - && (rThisLeft.getRGBColor() == rOtherLeft.getRGBColor()); - } - else + if(bSameStuff) { - const BorderLine& rThisGap(rThis.getBorderLines()[1]); - const BorderLine& rOtherGap(rOther.getBorderLines()[1]); - const BorderLine& rThisRight(rThis.getBorderLines()[2]); - const BorderLine& rOtherRight(rOther.getBorderLines()[2]); + const std::vector< BorderLine >& rLineLeft(rThis.getBorderLines()); + const std::vector< BorderLine >& rOtherLeft(rOther.getBorderLines()); + const size_t aSize(std::min(rLineLeft.size(), rOtherLeft.size())); - bSameStuff = ((thisHeight > thisWidth) == (otherHeight > otherWidth)) - && (rtl::math::approxEqual(rThisLeft.getWidth(), rOtherLeft.getWidth())) - && (rtl::math::approxEqual(rThisGap.getWidth(), rOtherGap.getWidth())) - && (rtl::math::approxEqual(rThisRight.getWidth(), rOtherRight.getWidth())) - && (rThis.getStyle() == rOther.getStyle()) - && (rThisLeft.getRGBColor() == rOtherLeft.getRGBColor()) - && (rThisRight.getRGBColor() == rOtherRight.getRGBColor()) - && (rThis.hasGapColor() == rOther.hasGapColor()) - && (!rThis.hasGapColor() || - (rThisGap.getRGBColor() == rOtherGap.getRGBColor())); - } + for(size_t a(0); bSameStuff && a < aSize; a++) + { + const BorderLine& la(rLineLeft[a]); + const BorderLine& lb(rOtherLeft[a]); + bSameStuff = la == lb; + } + } if (bSameStuff) { @@ -4894,45 +4862,44 @@ static void lcl_MakeBorderLine(SwRect const& rRect, double const nRightWidth = rBorder.GetInWidth(); Color const aLeftColor = rBorder.GetColorOut(isLeftOrTopBorder); Color const aRightColor = rBorder.GetColorIn(isLeftOrTopBorder); + const std::vector<double> aDashing(svtools::GetLineDashing(rBorder.GetBorderLineStyle(), 10.0)); + const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashing); + std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines; - rtl::Reference<BorderLinePrimitive2D> xLine; - - if (basegfx::fTools::equalZero(nRightWidth)) - { - xLine = new BorderLinePrimitive2D( - aStart, - aEnd, - BorderLine( - nLeftWidth, + aBorderlines.push_back( + drawinglayer::primitive2d::BorderLine( + drawinglayer::attribute::LineAttribute( aLeftColor.getBColor(), - BorderLineExtend( - nExtentLeftStart, - nExtentLeftEnd)), - rBorder.GetBorderLineStyle()); - } - else - { - xLine = new BorderLinePrimitive2D( + nLeftWidth), + nExtentLeftStart, + nExtentLeftStart, + nExtentLeftEnd, + nExtentLeftEnd)); + + if (!basegfx::fTools::equalZero(nRightWidth)) + { + drawinglayer::primitive2d::BorderLine( + drawinglayer::attribute::LineAttribute( + rBorder.GetColorGap().getBColor(), + rBorder.GetDistance())); + + aBorderlines.push_back( + drawinglayer::primitive2d::BorderLine( + drawinglayer::attribute::LineAttribute( + aRightColor.getBColor(), + nRightWidth), + nExtentRightStart, + nExtentRightStart, + nExtentRightEnd, + nExtentRightEnd)); + } + + rtl::Reference<BorderLinePrimitive2D> xLine( + new BorderLinePrimitive2D( aStart, aEnd, - BorderLine( - nLeftWidth, - aLeftColor.getBColor(), - BorderLineExtend( - nExtentLeftStart, - nExtentLeftEnd)), - BorderLine( - rBorder.GetDistance(), - rBorder.GetColorGap().getBColor()), - BorderLine( - nRightWidth, - aRightColor.getBColor(), - BorderLineExtend( - nExtentRightStart, - nExtentRightEnd)), - rBorder.HasGapColor(), - rBorder.GetBorderLineStyle()); - } + aBorderlines, + aStrokeAttribute)); properties.pBLines->AddBorderLine(xLine.get(), properties); } |