Kaydet (Commit) 16fd7af9 authored tarafından Armin Le Grand's avatar Armin Le Grand

borderline: extended the expand logic

Extended and checked the expand logic for creating
the line extends. Now creating quite the right lines,
will need to check some speccial cases. Also some
cleanups.

Change-Id: I3a3bd4d23c7017ecd873147df2d93af61de39fa6
üst 1f02af4d
......@@ -165,89 +165,6 @@ namespace drawinglayer
}
}
// 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()))
......
......@@ -380,6 +380,7 @@ double getOffsetAndHalfWidthAndColorFromStyle(
Color aSecn(rStyle.GetColorSecn());
double fPrim(rStyle.Prim());
double fSecn(rStyle.Secn());
const bool bSecnUsed(0.0 != fSecn);
if(bMirrored)
{
......@@ -389,8 +390,12 @@ double getOffsetAndHalfWidthAndColorFromStyle(
case RefMode::End: aRefMode = RefMode::Begin; break;
default: break;
}
std::swap(aPrim, aSecn);
std::swap(fPrim, fSecn);
if(bSecnUsed)
{
std::swap(aPrim, aSecn);
std::swap(fPrim, fSecn);
}
}
if (RefMode::Centered != aRefMode)
......@@ -409,7 +414,7 @@ double getOffsetAndHalfWidthAndColorFromStyle(
}
}
if (rStyle.Dist() && fSecn)
if (bSecnUsed)
{
// both or all three lines used
const bool bPrimTransparent(0xff == rStyle.GetColorPrim().GetTransparency());
......@@ -503,6 +508,103 @@ void getCutSet(
&rCutSet.mfORMR);
}
void getAllCutSets(
std::vector< CutSet >& rCutSets,
const basegfx::B2DPoint& rOrigin,
const basegfx::B2DPoint& rLeft,
const basegfx::B2DPoint& rRight,
const basegfx::B2DVector& rX,
const StyleVectorTable& rStyleVectorTable,
bool bUpper,
bool bLower)
{
for(const auto& rStyleVectorCombination : rStyleVectorTable)
{
if(bUpper || bLower)
{
// use only upper or lower vectors compared to rX
const double fCross(rX.cross(rStyleVectorCombination.getB2DVector()));
if(bUpper && fCross > 0.0)
{
// upper vectors wanted, but is lower
continue;
}
if(bLower && fCross < 0.0)
{
// lower vectors wanted, but is upper
continue;
}
}
std::vector< OffsetAndHalfWidthAndColor > otherOffsets;
getOffsetAndHalfWidthAndColorFromStyle(rStyleVectorCombination.getStyle(), nullptr, rStyleVectorCombination.isMirrored(), 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, rLeft, rRight, rX, aOtherLeft, aOtherRight, rStyleVectorCombination.getB2DVector());
rCutSets.push_back(aCutSet);
}
}
}
}
CutSet getMinMaxCutSet(
bool bMin,
const std::vector< CutSet >& rCutSets)
{
if(rCutSets.empty())
{
CutSet aRetval;
aRetval.mfOLML = aRetval.mfORML = aRetval.mfOLMR = aRetval.mfORMR = 0.0;
return aRetval;
}
const size_t aSize(rCutSets.size());
if(1 == aSize)
{
return rCutSets[0];
}
CutSet aRetval(rCutSets[0]);
double fRetval(aRetval.mfOLML + aRetval.mfORML + aRetval.mfOLMR + aRetval.mfORMR);
for(size_t a(1); a < aSize; a++)
{
const CutSet& rCandidate(rCutSets[a]);
const double fCandidate(rCandidate.mfOLML + rCandidate.mfORML + rCandidate.mfOLMR + rCandidate.mfORMR);
if(bMin)
{
if(fCandidate < fRetval)
{
fRetval = fCandidate;
aRetval = rCandidate;
}
}
else
{
if(fCandidate > fRetval)
{
fRetval = fCandidate;
aRetval = rCandidate;
}
}
}
return aRetval;
}
void getExtends(
std::vector<ExtendSet>& rExtendSet, // target Left/Right values to fill
const basegfx::B2DPoint& rOrigin, // own vector start
......@@ -518,41 +620,99 @@ void getExtends(
for(size_t a(0); a < nOffsets; a++)
{
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)
if(0xff != rOffset.maColor.GetTransparency())
{
std::vector< OffsetAndHalfWidthAndColor > otherOffsets;
getOffsetAndHalfWidthAndColorFromStyle(rStyleVectorCombination.getStyle(), nullptr, rStyleVectorCombination.isMirrored(), otherOffsets);
const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (rOffset.mfOffset - rOffset.mfHalfWidth)));
const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (rOffset.mfOffset + rOffset.mfHalfWidth)));
std::vector< CutSet > aCutSets;
CutSet aResult;
bool bResultSet(false);
if(1 == nOffsets)
{
// single line:
// - get all CutSets
// - get minimum values as extension (biggest possible overlap)
getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, false, false);
if(!otherOffsets.empty())
if(!aCutSets.empty())
{
aResult = getMinMaxCutSet(true, aCutSets);
bResultSet = true;
}
}
else
{
const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleVectorCombination.getB2DVector()));
// multiple lines
const bool bUpper(a < (nOffsets >> 1));
const bool bLower(a > (nOffsets >> 1));
for(const auto& rOtherOffset : otherOffsets)
if(bUpper)
{
const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset - rOtherOffset.mfHalfWidth)));
const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset + rOtherOffset.mfHalfWidth)));
CutSet aCutSet;
getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, true, false);
if(!aCutSets.empty())
{
aResult = getMinMaxCutSet(false, aCutSets);
bResultSet = true;
}
else
{
getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, false, true);
getCutSet(aCutSet, aLeft, aRight, rX, aOtherLeft, aOtherRight, rStyleVectorCombination.getB2DVector());
if(!aCutSets.empty())
{
aResult = getMinMaxCutSet(true, aCutSets);
bResultSet = true;
}
}
}
else if(bLower)
{
getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, false, true);
if(!bExtSet)
if(!aCutSets.empty())
{
rExt.mfExtLeft = std::min(aCutSet.mfOLML, aCutSet.mfORML);
rExt.mfExtRight = std::min(aCutSet.mfOLMR, aCutSet.mfORMR);
bExtSet = true;
aResult = getMinMaxCutSet(false, aCutSets);
bResultSet = 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));
getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, true, false);
if(!aCutSets.empty())
{
aResult = getMinMaxCutSet(true, aCutSets);
bResultSet = true;
}
}
}
else // middle line
{
getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, false, false);
if(!aCutSets.empty())
{
const CutSet aResultMin(getMinMaxCutSet(true, aCutSets));
const CutSet aResultMax(getMinMaxCutSet(false, aCutSets));
aResult.mfOLML = (aResultMin.mfOLML + aResultMax.mfOLML) * 0.5;
aResult.mfORML = (aResultMin.mfORML + aResultMax.mfORML) * 0.5;
aResult.mfOLMR = (aResultMin.mfOLMR + aResultMax.mfOLMR) * 0.5;
aResult.mfORMR = (aResultMin.mfORMR + aResultMax.mfORMR) * 0.5;
bResultSet = true;
}
}
}
if(bResultSet)
{
ExtendSet& rExt(rExtendSet[a]);
rExt.mfExtLeft = std::min(aResult.mfOLML, aResult.mfORML);
rExt.mfExtRight = std::min(aResult.mfOLMR, aResult.mfORMR);
}
}
}
}
......@@ -588,9 +748,22 @@ void CreateBorderPrimitives(
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);
// Create extends for line ends, use inverse point/vector and inverse offsets.
// Offsets need to be inverted for different width of lines. To invert, change
// order, but also sign of offset. Do this on a copy since myOffsets will be
// used below to create the primitives
std::vector< OffsetAndHalfWidthAndColor > myInverseOffsets(myOffsets);
std::reverse(myInverseOffsets.begin(), myInverseOffsets.end());
for(auto& offset : myInverseOffsets)
{
offset.mfOffset *= -1;
}
getExtends(aExtendSetEnd, rOrigin + rX, -rX, -aPerpendX, myInverseOffsets, rEndStyleVectorTable);
// also need to reverse the result to apply to the correct lines
std::reverse(aExtendSetEnd.begin(), aExtendSetEnd.end());
}
std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
......
......@@ -988,7 +988,7 @@ void HelperCreateVerticalEntry(
if(rStartFromBR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBR, rX + rY, false));
if(rStartTFromR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromR, rX, false));
if(rStartTFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromT, rY, true));
if(rStartTFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromT, -rY, true));
if(rStartTFromL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromL, -rX, true));
if(rStartFromBL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBL, rY - rX, true));
......@@ -1002,9 +1002,9 @@ void HelperCreateVerticalEntry(
if(rEndFromTR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTR, rX - rY, false));
if(rEndBFromR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromR, rX, false));
if(rEndBFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromB, -rY, false));
if(rEndBFromL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromL, rX, true));
if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, rX + rY, true));
if(rEndBFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromB, rY, false));
if(rEndBFromL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromL, -rX, true));
if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, -rX - rY, true));
CreateBorderPrimitives(
rSequence,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment