summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2017-07-26 16:34:52 +0200
committerArmin Le Grand <Armin.Le.Grand@cib.de>2017-07-28 17:51:57 +0200
commit7202cfa0d3bae430f8fcb8508ed389583a14539b (patch)
tree034dc592b38cffaba2fbb1987615c2774bb2e6bb
parent5e061435a74a5461e6b9fa5a48ce44d266a3d957 (diff)
borderline: Unified primitive creation
Overhauled the edge extension calculations to better use all existing cuts, for cases with single and double lines. Also a preparation for more complex edge cuts. Changed BorderLine paint in Writer, it was setting the svx::frame::RefMode attribute at the Style *and* was manually moving the geometry which lead to a double applying of the offsets Change-Id: I446d04632050272849f43accb8dcbde574d10cf4
-rw-r--r--svx/source/dialog/framelink.cxx371
-rw-r--r--sw/source/core/layout/paintfrm.cxx45
2 files changed, 217 insertions, 199 deletions
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index e5b6abb8f5f8..c746e881679c 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -345,7 +345,53 @@ double lcl_GetExtent(
return nCut;
}
-void getOffsetsFromStyle(const Style& rStyle, std::vector< double >& offsets)
+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.Prim())
{
@@ -357,25 +403,21 @@ void getOffsetsFromStyle(const Style& rStyle, std::vector< double >& offsets)
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);
+ 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(0.0);
- offsets.push_back(rStyle.Prim());
- offsets.push_back(rStyle.Prim() + rStyle.Dist());
- offsets.push_back(rStyle.GetWidth());
+ {
+ 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(-fFullWidth);
- offsets.push_back(rStyle.Prim() - fFullWidth);
- offsets.push_back((rStyle.Prim() + rStyle.Dist()) - fFullWidth);
- offsets.push_back(0.0);
+ offsets.push_back(OffsetPair(-fFullWidth, rStyle.Prim() - fFullWidth));
+ offsets.push_back(OffsetPair((rStyle.Prim() + rStyle.Dist()) - fFullWidth, 0.0));
break;
}
}
@@ -386,110 +428,132 @@ void getOffsetsFromStyle(const Style& rStyle, std::vector< double >& offsets)
switch (rStyle.GetRefMode())
{
case RefMode::Centered:
- offsets.push_back(rStyle.Prim() * -0.5);
- offsets.push_back(rStyle.Prim() * 0.5);
+ offsets.push_back(OffsetPair(rStyle.Prim() * -0.5, rStyle.Prim() * 0.5));
break;
case RefMode::Begin:
- offsets.push_back(0.0);
- offsets.push_back(rStyle.Prim());
+ offsets.push_back(OffsetPair(0.0, rStyle.Prim()));
break;
default: // case RefMode::End:
- offsets.push_back(-rStyle.Prim());
- offsets.push_back(0.0);
+ offsets.push_back(OffsetPair(-rStyle.Prim(), 0.0));
break;
}
}
}
}
-void compareToStyle(
+void createCutsWithStyle(
const basegfx::B2DPoint& rOrigin,
const basegfx::B2DVector& rOtherVector,
const basegfx::B2DVector& rOtherUnifiedPerpendicular,
- const std::vector< double >& rOtherOffsets,
+ const OffsetPair& rOtherOffsets,
const Style& rStyle,
const basegfx::B2DVector& rMyVector,
- std::vector< std::vector< double >>& rOtherCuts)
+ std::vector< OffsetCutSet>& rOtherCuts)
{
if (rStyle.Prim())
{
- std::vector< double > myOffsets;
+ // 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 (two or four, depending on style)
- getOffsetsFromStyle(rStyle, myOffsets);
+ // get offsets from outer to inner from target style (one or two)
+ getOffsetPairsFromStyle(rStyle, myOffsets);
- if (!myOffsets.empty())
+ for (const auto& myOffset : myOffsets)
{
- 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);
- }
- }
+ // 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 getMinMaxCut(bool bMin, const std::vector< double >& rVector)
+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)
{
- if (rVector.empty())
- {
- return 0.0;
- }
-
- if (1 == rVector.size())
- {
- return rVector[0];
- }
-
- double fRetval(rVector[0]);
+ 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);
- for (size_t a(1); a < rVector.size(); a++)
+ if (pResult)
{
- fRetval = bMin ? std::min(fRetval, rVector[a]) : std::max(fRetval, rVector[a]);
+ return (pResult->mfLeftRight + pResult->mfRightRight) * 0.5 * (bEdgeStart ? -fLength : fLength);
}
- return fRetval;
+ return 0.0;
}
-std::vector< double > getMinMaxCuts(bool bMin, const std::vector< std::vector< double >>& rCuts)
+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< double > aRetval(rCuts.size());
+ std::vector< OffsetCutSet > myCutSets;
+ createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rFirst, rY, myCutSets);
+ const OffsetCutSet* pResult = getMinMaxCutSet(!bEdgeStart, myCutSets);
- for (size_t a(0); a < rCuts.size(); a++)
+ if (!pResult)
{
- aRetval[a] = getMinMaxCut(bMin, rCuts[a]);
+ createCutsWithStyle(rOrigin, rX, rPerpendX, myOffset, rSecond, rY, myCutSets);
+ pResult = getMinMaxCutSet(bEdgeStart, myCutSets);
}
- return aRetval;
-}
-
-bool areCutsEmpty(std::vector< std::vector< double >>& rCuts)
-{
- for (const auto& rVec : rCuts)
+ if (pResult)
{
- if (!rVec.empty())
- {
- return false;
- }
+ return (pResult->mfLeftRight + pResult->mfRightRight) * 0.5 * (bEdgeStart ? -fLength : fLength);
}
-
- return true;
}
void CreateBorderPrimitives(
@@ -512,12 +576,6 @@ void CreateBorderPrimitives(
{
if (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());
@@ -526,7 +584,6 @@ void CreateBorderPrimitives(
if (RefMode::Centered != rBorder.GetRefMode())
{
- const basegfx::B2DVector aPerpendX(basegfx::getNormalizedPerpendicular(rX));
const double fHalfWidth(rBorder.GetWidth() * 0.5);
if (RefMode::Begin == rBorder.GetRefMode())
@@ -541,23 +598,27 @@ void CreateBorderPrimitives(
}
}
- // create start/end for RefMode::Centered
+ // create start/end (use RefMode)
const basegfx::B2DPoint aStart(rOrigin + aRefModeOffset);
const basegfx::B2DPoint aEnd(aStart + rX);
- if (2 == myOffsets.size())
+ // get offsets for my style (one or two)
+ std::vector< OffsetPair > myOffsets;
+ getOffsetPairsFromStyle(rBorder, myOffsets);
+
+ if (1 == 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;
+ // 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(
@@ -567,88 +628,35 @@ void CreateBorderPrimitives(
drawinglayer::primitive2d::BorderLine(
rBorder.Prim(),
(pForceColor ? *pForceColor : rBorder.GetColorPrim()).getBColor(),
- mfExtendLeftStart,
- mfExtendLeftEnd),
+ mfExtendStart,
+ mfExtendEnd),
rBorder.Type(),
rBorder.PatternScale())));
}
- else if (4 == myOffsets.size())
+ else if (2 == myOffsets.size())
{
- {
- std::vector< double > myOffsetsA;
- myOffsetsA.push_back(myOffsets[0]);
- myOffsetsA.push_back(myOffsets[1]);
+ // we are a double edge, calculate cuts with edges coming from above/below
+ // for both edges to detect the line start/end extensions
+ double mfExtendLeftStart(0.0);
+ double mfExtendLeftEnd(0.0);
+ double mfExtendRightStart(0.0);
+ double mfExtendRightEnd(0.0);
- std::vector< std::vector< double >> myCutsS(myOffsetsA.size());
- std::vector< double > nMinCutsS;
- compareToStyle(rOrigin, rX, aPerpendX, myOffsetsA, rLFromT, rY, myCutsS);
+ // 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);
- 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;
+ // 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);
- std::vector< std::vector< double >> myCutsE(myOffsetsA.size());
- std::vector< double > nMinCutsE;
- compareToStyle(rOrigin, rX, aPerpendX, myOffsetsA, rRFromT, rY, myCutsE);
+ // 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);
- 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;
- }
+ // 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);
rTarget.append(
drawinglayer::primitive2d::Primitive2DReference(
@@ -720,16 +728,19 @@ void CreateDiagFrameBorderPrimitives(
const basegfx::B2DVector& rYAxis,
const Style& rTLBR,
const Style& rBLTR,
- const Style& rTLFromB,
- const Style& rTLFromR,
- const Style& rBRFromT,
- const Style& rBRFromL,
- const Style& rBLFromT,
- const Style& rBLFromR,
- const Style& rTRFromB,
- const Style& rTRFromL,
+ const Style& /*rTLFromB*/,
+ const Style& /*rTLFromR*/,
+ const Style& /*rBRFromT*/,
+ const Style& /*rBRFromL*/,
+ const Style& /*rBLFromT*/,
+ const Style& /*rBLFromR*/,
+ const Style& /*rTRFromB*/,
+ const Style& /*rTRFromL*/,
const Color* pForceColor)
{
+ // currently the diagonal edges are just added as-is without cutting them against the incoming
+ // edges. This needs to be improved in the future, so please do *not* remove the currently unused
+ // parameters from above
if (rTLBR.Prim())
{
// top-left to bottom-right
diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx
index 20c362b0f8e4..407ac441ecf7 100644
--- a/sw/source/core/layout/paintfrm.cxx
+++ b/sw/source/core/layout/paintfrm.cxx
@@ -2771,25 +2771,32 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons
// logically vertical lines are painted centered on the line,
// logically horizontal lines are painted "below" the line
- bool const isBelow((mrTabFrame.IsVertical()) ? !bHori : bHori);
- double const offsetStart = (isBelow)
- ? aStyles[0].GetWidth() / 2.0
- : std::max<double>(aStyles[1].GetWidth(),
- aStyles[3].GetWidth()) / 2.0;
- double const offsetEnd = (isBelow)
- ? aStyles[0].GetWidth() / 2.0
- : std::max<double>(aStyles[4].GetWidth(),
- aStyles[6].GetWidth()) / 2.0;
- if (mrTabFrame.IsVertical())
- {
- aPaintStart.X() -= static_cast<long>(offsetStart + 0.5);
- aPaintEnd.X() -= static_cast<long>(offsetEnd + 0.5);
- }
- else
- {
- aPaintStart.Y() += static_cast<long>(offsetStart + 0.5);
- aPaintEnd.Y() += static_cast<long>(offsetEnd + 0.5);
- }
+ //
+ // This does not need to be done here, it is set in SwTabFramePainter::Insert
+ // already using SetRefMode(...) as property of the BorderLine Style, see there.
+ // When additionally adding the offset here manually, it will be applied
+ // double and will be rendered wrong. This did not happen before because
+ // the setting of the svx::frame::RefMode at svx::frame::Style was ignored there.
+ //
+ // bool const isBelow((mrTabFrame.IsVertical()) ? !bHori : bHori);
+ // double const offsetStart = (isBelow)
+ // ? aStyles[0].GetWidth() / 2.0
+ // : std::max<double>(aStyles[1].GetWidth(),
+ // aStyles[3].GetWidth()) / 2.0;
+ // double const offsetEnd = (isBelow)
+ // ? aStyles[0].GetWidth() / 2.0
+ // : std::max<double>(aStyles[4].GetWidth(),
+ // aStyles[6].GetWidth()) / 2.0;
+ // if (mrTabFrame.IsVertical())
+ // {
+ // aPaintStart.X() -= static_cast<long>(offsetStart + 0.5);
+ // aPaintEnd.X() -= static_cast<long>(offsetEnd + 0.5);
+ // }
+ // else
+ // {
+ // aPaintStart.Y() += static_cast<long>(offsetStart + 0.5);
+ // aPaintEnd.Y() += static_cast<long>(offsetEnd + 0.5);
+ // }
if (bHori)
{