borderline: first versionj with line end adaptions
Added usage of defined extensions to the BorderLinePrimitive,
also added a first version to detect all cuts with adjacent
borders and produce the correct extensions, for single and
double lines. Not completely happy with it, but a first
version
Change-Id: I4b12a6cc0a70278bd5c506e9b3b2c5c126930dad
diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
index 84ea9ff..a9822d6 100644
--- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
@@ -144,8 +144,8 @@ namespace drawinglayer
// single line, only inside values used, no vertical offsets
addPolygonStrokePrimitive2D(
rContainer,
getStart(),
getEnd(),
getStart() - (aVector * getExtendLeftStart()),
getEnd() + (aVector * getExtendLeftEnd()),
getRGBColorLeft(),
getLeftWidth(),
getStyle(),
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index c193285..de93c93 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -345,6 +345,153 @@ double lcl_GetExtent(
return nCut;
}
void getOffsetsFromStyle(const Style& rStyle, std::vector< double >& offsets)
{
if (rStyle.Prim())
{
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(-fHalfFullWidth);
offsets.push_back(rStyle.Prim() - fHalfFullWidth);
offsets.push_back((rStyle.Prim() + rStyle.Dist()) - fHalfFullWidth);
offsets.push_back(fHalfFullWidth);
break;
}
case RefMode::Begin:
offsets.push_back(0.0);
offsets.push_back(rStyle.Prim());
offsets.push_back(rStyle.Prim() + rStyle.Dist());
offsets.push_back(rStyle.GetWidth());
break;
default: // case RefMode::End:
{
const double fFullWidth(rStyle.GetWidth());
offsets.push_back(-fFullWidth);
offsets.push_back(rStyle.Prim() - fFullWidth);
offsets.push_back((rStyle.Prim() + rStyle.Dist()) - fFullWidth);
offsets.push_back(0.0);
break;
}
}
}
else
{
// one line used, push two values, from outer to inner
switch (rStyle.GetRefMode())
{
case RefMode::Centered:
offsets.push_back(rStyle.Prim() * -0.5);
offsets.push_back(rStyle.Prim() * 0.5);
break;
case RefMode::Begin:
offsets.push_back(0.0);
offsets.push_back(rStyle.Prim());
break;
default: // case RefMode::End:
offsets.push_back(-rStyle.Prim());
offsets.push_back(0.0);
break;
}
}
}
}
void compareToStyle(
const basegfx::B2DPoint& rOrigin,
const basegfx::B2DVector& rOtherVector,
const basegfx::B2DVector& rOtherUnifiedPerpendicular,
const std::vector< double >& rOtherOffsets,
const Style& rStyle,
const basegfx::B2DVector& rMyVector,
std::vector< std::vector< double >>& rOtherCuts)
{
if (rStyle.Prim())
{
std::vector< double > myOffsets;
// get offsets from outer to inner (two or four, depending on style)
getOffsetsFromStyle(rStyle, myOffsets);
if (!myOffsets.empty())
{
const basegfx::B2DVector aMyUnifiedPerpendicular(basegfx::getNormalizedPerpendicular(rMyVector));
for (size_t a(0); a < rOtherOffsets.size(); a++)
{
const basegfx::B2DPoint aOtherPos(rOrigin + (rOtherUnifiedPerpendicular * rOtherOffsets[a]));
for (size_t b(0); b < myOffsets.size(); b++)
{
const basegfx::B2DPoint aMyPos(rOrigin + (aMyUnifiedPerpendicular * myOffsets[b]));
double fCut(0.0);
basegfx::tools::findCut(
aOtherPos,
rOtherVector,
aMyPos,
rMyVector,
CutFlagValue::LINE,
&fCut);
rOtherCuts[a].push_back(fCut);
}
}
}
}
}
double getMinMaxCut(bool bMin, const std::vector< double >& rVector)
{
if (rVector.empty())
{
return 0.0;
}
if (1 == rVector.size())
{
return rVector[0];
}
double fRetval(rVector[0]);
for (size_t a(1); a < rVector.size(); a++)
{
fRetval = bMin ? std::min(fRetval, rVector[a]) : std::max(fRetval, rVector[a]);
}
return fRetval;
}
std::vector< double > getMinMaxCuts(bool bMin, const std::vector< std::vector< double >>& rCuts)
{
std::vector< double > aRetval(rCuts.size());
for (size_t a(0); a < rCuts.size(); a++)
{
aRetval[a] = getMinMaxCut(bMin, rCuts[a]);
}
return aRetval;
}
bool areCutsEmpty(std::vector< std::vector< double >>& rCuts)
{
for (const auto& rVec : rCuts)
{
if (!rVec.empty())
{
return false;
}
}
return true;
}
void CreateBorderPrimitives(
drawinglayer::primitive2d::Primitive2DContainer& rTarget,
const basegfx::B2DPoint& rOrigin,
@@ -363,7 +510,158 @@ void CreateBorderPrimitives(
const DiagStyle& /*rRFromBL*/,
const Color* pForceColor)
{
if (rBorder.Prim() || rBorder.Secn())
static bool bCheckNewStuff(true);
if (bCheckNewStuff && rBorder.Prim())
{
double mfExtendLeftStart(0.0);
double mfExtendLeftEnd(0.0);
double mfExtendRightStart(0.0);
double mfExtendRightEnd(0.0);
std::vector< double > myOffsets;
getOffsetsFromStyle(rBorder, myOffsets);
const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX));
const double fLength(rX.getLength());
if (2 == myOffsets.size())
{
std::vector< std::vector< double >> myCutsS(myOffsets.size());
compareToStyle(rOrigin, rX, aPerpendX, myOffsets, rLFromT, rY, myCutsS);
compareToStyle(rOrigin, rX, aPerpendX, myOffsets, rLFromB, rY, myCutsS);
std::vector< double > nMinCutsS(getMinMaxCuts(true, myCutsS));
mfExtendLeftStart = ((nMinCutsS[0] + nMinCutsS[1]) * 0.5) * -1.0 * fLength;
std::vector< std::vector< double >> myCutsE(myOffsets.size());
compareToStyle(rOrigin, rX, aPerpendX, myOffsets, rRFromT, rY, myCutsE);
compareToStyle(rOrigin, rX, aPerpendX, myOffsets, rRFromB, rY, myCutsE);
std::vector< double > nMinCutsE(getMinMaxCuts(false, myCutsE));
mfExtendLeftEnd = ((nMinCutsE[0] + nMinCutsE[1]) * 0.5) * fLength;
}
else if (4 == myOffsets.size())
{
{
std::vector< double > myOffsetsA;
myOffsetsA.push_back(myOffsets[0]);
myOffsetsA.push_back(myOffsets[1]);
std::vector< std::vector< double >> myCutsS(myOffsetsA.size());
std::vector< double > nMinCutsS;
compareToStyle(rOrigin, rX, aPerpendX, myOffsetsA, rLFromT, rY, myCutsS);
if (!areCutsEmpty(myCutsS))
{
nMinCutsS = getMinMaxCuts(false, myCutsS);
}
else
{
compareToStyle(rOrigin, rX, aPerpendX, myOffsetsA, rLFromB, rY, myCutsS);
nMinCutsS = getMinMaxCuts(true, myCutsS);
}
mfExtendLeftStart = ((nMinCutsS[0] + nMinCutsS[1]) * 0.5) * -1.0 * fLength;
std::vector< std::vector< double >> myCutsE(myOffsetsA.size());
std::vector< double > nMinCutsE;
compareToStyle(rOrigin, rX, aPerpendX, myOffsetsA, rRFromT, rY, myCutsE);
if (!areCutsEmpty(myCutsE))
{
nMinCutsE = getMinMaxCuts(true, myCutsE);
}
else
{
compareToStyle(rOrigin, rX, aPerpendX, myOffsetsA, rRFromB, rY, myCutsE);
nMinCutsE = getMinMaxCuts(false, myCutsE);
}
mfExtendLeftEnd = ((nMinCutsE[0] + nMinCutsE[1]) * 0.5) * fLength;
}
{
std::vector< double > myOffsetsB;
myOffsetsB.push_back(myOffsets[2]);
myOffsetsB.push_back(myOffsets[3]);
std::vector< std::vector< double >> myCutsS(myOffsetsB.size());
std::vector< double > nMinCutsS;
compareToStyle(rOrigin, rX, aPerpendX, myOffsetsB, rLFromB, rY, myCutsS);
if (!areCutsEmpty(myCutsS))
{
nMinCutsS = getMinMaxCuts(false, myCutsS);
}
else
{
compareToStyle(rOrigin, rX, aPerpendX, myOffsetsB, rLFromT, rY, myCutsS);
nMinCutsS = getMinMaxCuts(true, myCutsS);
}
mfExtendRightStart = ((nMinCutsS[0] + nMinCutsS[1]) * 0.5) * -1.0 * fLength;
std::vector< std::vector< double >> myCutsE(myOffsetsB.size());
std::vector< double > nMinCutsE;
compareToStyle(rOrigin, rX, aPerpendX, myOffsetsB, rRFromB, rY, myCutsE);
if (!areCutsEmpty(myCutsE))
{
nMinCutsE = getMinMaxCuts(true, myCutsE);
}
else
{
compareToStyle(rOrigin, rX, aPerpendX, myOffsetsB, rRFromT, rY, myCutsE);
nMinCutsE = getMinMaxCuts(false, myCutsE);
}
mfExtendRightEnd = ((nMinCutsE[0] + nMinCutsE[1]) * 0.5) * fLength;
}
}
// do not forget RefMode offset, primitive will assume RefMode::Centered
basegfx::B2DVector aRefModeOffset;
if (RefMode::Centered != rBorder.GetRefMode())
{
const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX));
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 for RefMode::Centered
const basegfx::B2DPoint aStart(rOrigin + aRefModeOffset);
const basegfx::B2DPoint aEnd(aStart + rX);
rTarget.append(
drawinglayer::primitive2d::Primitive2DReference(
new drawinglayer::primitive2d::BorderLinePrimitive2D(
aStart,
aEnd,
rBorder.Prim(),
rBorder.Dist(),
rBorder.Secn(),
mfExtendLeftStart,
mfExtendLeftEnd,
mfExtendRightStart,
mfExtendRightEnd,
(pForceColor ? *pForceColor : rBorder.GetColorSecn()).getBColor(),
(pForceColor ? *pForceColor : rBorder.GetColorPrim()).getBColor(),
(pForceColor ? *pForceColor : rBorder.GetColorGap()).getBColor(),
rBorder.UseGapColor(),
rBorder.Type(),
rBorder.PatternScale())));
}
if (!bCheckNewStuff && (rBorder.Prim() || rBorder.Secn()))
{
basegfx::B2DPoint aStart(rOrigin);
basegfx::B2DPoint aEnd(rOrigin + rX);