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
diff --git a/drawinglayer/CppunitTest_drawinglayer_border.mk b/drawinglayer/CppunitTest_drawinglayer_border.mk
index 194c86a..fa2f715 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 a070f9c..e56a40d 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 47da04a..9421ed8 100644
--- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
@@ -37,128 +37,29 @@ 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
{
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
{
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
{
if (mfExtends.empty())
return 0.0;
if (2 == mfExtends.size())
return mfExtends[0];
return (mfExtends[0] + mfExtends[1]) * 0.5;
}
double BorderLineExtend::getEndAverage() const
{
if (mfExtends.empty())
return 0.0;
if (2 == mfExtends.size())
return mfExtends[1];
return (mfExtends[2] + mfExtends[3]) * 0.5;
}
bool BorderLineExtend::operator==(const BorderLineExtend& rBorderLineExtend) const
{
if (mfExtends.size() == rBorderLineExtend.mfExtends.size())
{
return mfExtends == rBorderLineExtend.mfExtends;
}
return false;
}
BorderLine::BorderLine(
double fWidth,
const basegfx::BColor& rRGBColor,
const BorderLineExtend& rBorderLineExtend)
: mfWidth(fWidth),
maRGBColor(rRGBColor),
maBorderLineExtend(rBorderLineExtend)
: maLineAttribute(rLineAttribute),
mfStartLeft(fStartLeft),
mfStartRight(fStartRight),
mfEndLeft(fEndLeft),
mfEndRight(fEndRight),
mbIsGap(false)
{
}
BorderLine::BorderLine(
double fWidth,
const basegfx::BColor& rRGBColor)
: mfWidth(fWidth),
maRGBColor(rRGBColor),
maBorderLineExtend()
double fWidth)
: maLineAttribute(basegfx::BColor(), fWidth),
mfStartLeft(0.0),
mfStartRight(0.0),
mfEndLeft(0.0),
mfEndRight(0.0),
mbIsGap(true)
{
}
@@ -168,9 +69,24 @@ namespace drawinglayer
bool BorderLine::operator==(const BorderLine& rBorderLine) const
{
return getWidth() == rBorderLine.getWidth()
&& getRGBColor() == rBorderLine.getRGBColor()
&& getBorderLineExtend() == rBorderLine.getBorderLineExtend();
return getLineAttribute() == rBorderLine.getLineAttribute()
&& getStartLeft() == rBorderLine.getStartLeft()
&& getStartRight() == rBorderLine.getStartRight()
&& getEndLeft() == rBorderLine.getEndLeft()
&& getEndRight() == rBorderLine.getEndRight()
&& isGap() == rBorderLine.isGap();
}
double BorderLine::getAdaptedWidth(double fMinWidth) const
{
if(isGap())
{
return std::max(getLineAttribute().getWidth(), fMinWidth);
}
else
{
return getLineAttribute().getWidth();
}
}
// 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)
const std::vector< BorderLine >& rBorderLines,
const drawinglayer::attribute::StrokeAttribute& rStrokeAttribute)
: BufferedDecompositionPrimitive2D(),
maStart(rStart),
maEnd(rEnd),
maBorderLines(),
mbHasGapColor(false),
mnStyle(nStyle),
mfPatternScale(fPatternScale),
mfDiscreteGapDistance(0.0)
maBorderLines(rBorderLines),
maStrokeAttribute(rStrokeAttribute),
mfSmallestAllowedDiscreteGapDistance(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)
: BufferedDecompositionPrimitive2D(),
maStart(rStart),
maEnd(rEnd),
maBorderLines(),
mbHasGapColor(bHasGapColor),
mnStyle(nStyle),
mfPatternScale(fPatternScale),
mfDiscreteGapDistance(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())));
// Line with potential gap. In this case, we want to be view-dependent.
// get the smallest gap
double fSmallestGap(0.0);
// 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))
if(getSmallestGap(fSmallestGap))
{
if (!getBuffered2DDecomposition().empty())
{
// conditions of last local decomposition have changed, delete
const_cast< BorderLinePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer());
}
// 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())));
// remember value for usage in create2DDecomposition
const_cast< BorderLinePrimitive2D* >(this)->mfDiscreteGapDistance = fNewDiscreteDistance;
// 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))
{
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)->mfSmallestAllowedDiscreteGapDistance = fNewDiscreteDistance;
}
}
}
diff --git a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx
index ad28a5e..992347c 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 4869535..ca66b28 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());
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.GetColorPrim().GetTransparency())
if(!bPrimTransparent || !bDistTransparent || !bSecnTransparent)
{
offsets.push_back(OffsetWidthColor((a + b) * 0.5, rStyle.Prim(), rStyle.GetColorPrim()));
}
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.GetColorGap().GetTransparency() && rStyle.UseGapColor())
{
offsets.push_back(OffsetWidthColor((b + c) * 0.5, rStyle.Dist(), rStyle.GetColorGap()));
}
offsets.push_back(
OffsetAndHalfWidthAndColor(
(a + b) * 0.5,
rStyle.Prim() * 0.5,
nullptr != pForceColor ? *pForceColor : rStyle.GetColorPrim()));
if(0xff != rStyle.GetColorSecn().GetTransparency())
{
offsets.push_back(OffsetWidthColor((c + d) * 0.5, rStyle.Secn(), rStyle.GetColorSecn()));
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);
for(const auto& style : rStyleVectorTable)
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);
}
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;
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)));
basegfx::tools::findCut(
aOtherLeft,
style.getB2DVector(),
aMyLeft,
rX,
CutFlagValue::LINE,
&aNewCuts.mfOLML);
for(const auto& rStyleVectorCombination : rStyleVectorTable)
{
std::vector< OffsetAndHalfWidthAndColor > otherOffsets;
getOffsetAndHalfWidthAndColorFromStyle(rStyleVectorCombination.getStyle(), nullptr, otherOffsets);
basegfx::tools::findCut(
aOtherLeft,
style.getB2DVector(),
aMyRight,
rX,
CutFlagValue::LINE,
&aNewCuts.mfOLMR);
if(!otherOffsets.empty())
{
const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleVectorCombination.getB2DVector()));
basegfx::tools::findCut(
aOtherRight,
style.getB2DVector(),
aMyLeft,
rX,
CutFlagValue::LINE,
&aNewCuts.mfORML);
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;
basegfx::tools::findCut(
aOtherRight,
style.getB2DVector(),
aMyRight,
rX,
CutFlagValue::LINE,
&aNewCuts.mfORMR);
getCutSet(aCutSet, aLeft, aRight, rX, aOtherLeft, aOtherRight, rStyleVectorCombination.getB2DVector());
rCutSet.push_back(aNewCuts);
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)
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);
}
std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
const double fNegLength(-rX.getLength());
for(size_t a(0); a < nOffsets; a++)
{
const OffsetAndHalfWidthAndColor& rOffset(myOffsets[a]);
const ExtendSet& rExtStart(aExtendSetStart[a]);
const ExtendSet& rExtEnd(aExtendSetEnd[a]);
if(0xff == rOffset.maColor.GetTransparency())
{
const basegfx::B2DPoint aStart(rOrigin + (aPerpendX * offset.mfOffset));
const basegfx::B2DPoint aEnd(aStart + rX);
if(bHasStartStyles)
{
// create extends for line starts
std::vector< CutSet > aStartCutSet;
findCutsWithStyleVectorTable(aStartCutSet, rOrigin, rX, offset.mfOffset, offset.mfWidth * 0.5, rStartStyleVectorTable);
}
if(bHasEndStyles)
{
// create extends for line ends
std::vector< CutSet > aEndCutSet;
findCutsWithStyleVectorTable(aEndCutSet, rOrigin + rX, -rX, -offset.mfOffset, offset.mfWidth * 0.5, rStartStyleVectorTable);
}
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())));
aBorderlines.push_back(
drawinglayer::primitive2d::BorderLine(
rOffset.mfHalfWidth * 2.0));
}
else
{
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));
}
}
else
{
// no start/end styles, just create simple BorderLinePrimitive2D
// for each local partial line
for(const auto& offset : myOffsets)
{
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())));
}
}
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 f8897b7..6052c23 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 63b5064..ac2d3ba 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]);
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;
if (1 == rLine.getBorderLines().size())
for(size_t a(0); a < aSize; a++)
{
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 BorderLine& rLineGap(rLine.getBorderLines()[1]);
// const BorderLine& rOtherGap(rOther.getBorderLines()[1]);
const BorderLine& rLineRight(rLine.getBorderLines()[2]);
const BorderLine& rOtherRight(rOther.getBorderLines()[2]);
const BorderLine& la(rLineLeft[a]);
const BorderLine& lb(rOtherLeft[a]);
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());
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())
if(bSameStuff)
{
bSameStuff = ((thisHeight > thisWidth) == (otherHeight > otherWidth))
&& (rtl::math::approxEqual(rThisLeft.getWidth(), rOtherLeft.getWidth()))
&& (rThis.getStyle() == rOther.getStyle())
&& (rThisLeft.getRGBColor() == rOtherLeft.getRGBColor());
}
else
{
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;
aBorderlines.push_back(
drawinglayer::primitive2d::BorderLine(
drawinglayer::attribute::LineAttribute(
aLeftColor.getBColor(),
nLeftWidth),
nExtentLeftStart,
nExtentLeftStart,
nExtentLeftEnd,
nExtentLeftEnd));
if (basegfx::fTools::equalZero(nRightWidth))
if (!basegfx::fTools::equalZero(nRightWidth))
{
xLine = new BorderLinePrimitive2D(
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)),
rBorder.GetBorderLineStyle());
}
else
{
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);
}