[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.2' - 2 commits - basegfx/source distro-configs/CPLinux-LOKit.conf include/basegfx
Andras Timar (via logerrit)
logerrit at kemper.freedesktop.org
Tue Apr 28 20:51:32 UTC 2020
basegfx/source/polygon/b2dpolygontools.cxx | 443 ++++++++++++++++------------
distro-configs/CPLinux-LOKit.conf | 1
include/basegfx/polygon/b2dpolygontools.hxx | 24 +
3 files changed, 289 insertions(+), 179 deletions(-)
New commits:
commit ddc81265192f27047f363db0a0ff7dcd493fa4b1
Author: Andras Timar <andras.timar at collabora.com>
AuthorDate: Tue Apr 28 22:50:34 2020 +0200
Commit: Andras Timar <andras.timar at collabora.com>
CommitDate: Tue Apr 28 22:50:34 2020 +0200
add --enable-sal-log to CPLinux-LOKit.conf to help debugging release packages
Change-Id: Ia724186ae93038eddb9e11c6678e6d8522846f85
diff --git a/distro-configs/CPLinux-LOKit.conf b/distro-configs/CPLinux-LOKit.conf
index 75ad26fc2045..9d5518b66897 100644
--- a/distro-configs/CPLinux-LOKit.conf
+++ b/distro-configs/CPLinux-LOKit.conf
@@ -62,3 +62,4 @@
--disable-lotuswordpro
--disable-lpsolve
--enable-symbols
+--enable-sal-log
commit 55c1016740d901668ae2766a5191b24bddb2d2f5
Author: Armin Le Grand (Collabora) <Armin.Le.Grand at me.com>
AuthorDate: Fri Feb 14 12:32:42 2020 +0100
Commit: Andras Timar <andras.timar at collabora.com>
CommitDate: Tue Apr 28 22:42:40 2020 +0200
tdf#130655 added callback interface to ::applyLineDashing
This version of the tooling method allows to avoid collecting line
snippets in a return value PolyPolygon. Instead, offer lambda
functions to get callbacks for created snippets. The original
method using a B2DPolyPolygon return value is adapted to already
use this, so serves as example of usage and ensures that only
one identical algorithm is used.
Change-Id: Ie306968a895ad280fc2425fb40b3244769216ba0
diff --git a/basegfx/source/polygon/b2dpolygontools.cxx b/basegfx/source/polygon/b2dpolygontools.cxx
index e0cfcdba1933..a4fd8378de4d 100644
--- a/basegfx/source/polygon/b2dpolygontools.cxx
+++ b/basegfx/source/polygon/b2dpolygontools.cxx
@@ -1122,7 +1122,102 @@ namespace basegfx
return false;
}
- void applyLineDashing(const B2DPolygon& rCandidate, const std::vector<double>& rDotDashArray, B2DPolyPolygon* pLineTarget, B2DPolyPolygon* pGapTarget, double fDotDashLength)
+ void applyLineDashing(
+ const B2DPolygon& rCandidate,
+ const std::vector<double>& rDotDashArray,
+ B2DPolyPolygon* pLineTarget,
+ B2DPolyPolygon* pGapTarget,
+ double fDotDashLength)
+ {
+ // clear targets in any case
+ if(pLineTarget)
+ {
+ pLineTarget->clear();
+ }
+
+ if(pGapTarget)
+ {
+ pGapTarget->clear();
+ }
+
+ // provide callbacks as lambdas
+ auto aLineCallback(
+ nullptr == pLineTarget
+ ? std::function<void(const basegfx::B2DPolygon&)>()
+ : [&pLineTarget](const basegfx::B2DPolygon& rSnippet){ pLineTarget->append(rSnippet); });
+ auto aGapCallback(
+ nullptr == pGapTarget
+ ? std::function<void(const basegfx::B2DPolygon&)>()
+ : [&pGapTarget](const basegfx::B2DPolygon& rSnippet){ pGapTarget->append(rSnippet); });
+
+ // call version that uses callbacks
+ applyLineDashing(
+ rCandidate,
+ rDotDashArray,
+ aLineCallback,
+ aGapCallback,
+ fDotDashLength);
+ }
+
+ static void implHandleSnippet(
+ const B2DPolygon& rSnippet,
+ std::function<void(const basegfx::B2DPolygon& rSnippet)>& rTargetCallback,
+ B2DPolygon& rFirst,
+ B2DPolygon& rLast)
+ {
+ if(rSnippet.isClosed())
+ {
+ if(!rFirst.count())
+ {
+ rFirst = rSnippet;
+ }
+ else
+ {
+ if(rLast.count())
+ {
+ rTargetCallback(rLast);
+ }
+
+ rLast = rSnippet;
+ }
+ }
+ else
+ {
+ rTargetCallback(rSnippet);
+ }
+ }
+
+ static void implHandleFirstLast(
+ std::function<void(const basegfx::B2DPolygon& rSnippet)>& rTargetCallback,
+ B2DPolygon& rFirst,
+ B2DPolygon& rLast)
+ {
+ if(rFirst.count() && rLast.count()
+ && rFirst.getB2DPoint(0).equal(rLast.getB2DPoint(rLast.count() - 1)))
+ {
+ // start of first and end of last are the same -> merge them
+ rLast.append(rFirst);
+ rLast.removeDoublePoints();
+ rFirst.clear();
+ }
+
+ if(rLast.count())
+ {
+ rTargetCallback(rLast);
+ }
+
+ if(rFirst.count())
+ {
+ rTargetCallback(rFirst);
+ }
+ }
+
+ void applyLineDashing(
+ const B2DPolygon& rCandidate,
+ const std::vector<double>& rDotDashArray,
+ std::function<void(const basegfx::B2DPolygon& rSnippet)> aLineTargetCallback,
+ std::function<void(const basegfx::B2DPolygon& rSnippet)> aGapTargetCallback,
+ double fDotDashLength)
{
const sal_uInt32 nPointCount(rCandidate.count());
const sal_uInt32 nDotDashCount(rDotDashArray.size());
@@ -1132,154 +1227,159 @@ namespace basegfx
fDotDashLength = std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0);
}
- if(fTools::more(fDotDashLength, 0.0) && (pLineTarget || pGapTarget) && nPointCount)
+ if(fTools::lessOrEqual(fDotDashLength, 0.0) || (!aLineTargetCallback && !aGapTargetCallback) || !nPointCount)
{
- // clear targets
- if(pLineTarget)
+ // parameters make no sense, just add source to targets
+ if(aLineTargetCallback)
{
- pLineTarget->clear();
+ aLineTargetCallback(rCandidate);
}
- if(pGapTarget)
+ if(aGapTargetCallback)
{
- pGapTarget->clear();
+ aGapTargetCallback(rCandidate);
}
- // prepare current edge's start
- B2DCubicBezier aCurrentEdge;
- const sal_uInt32 nEdgeCount(rCandidate.isClosed() ? nPointCount : nPointCount - 1);
- aCurrentEdge.setStartPoint(rCandidate.getB2DPoint(0));
+ return;
+ }
- // prepare DotDashArray iteration and the line/gap switching bool
- sal_uInt32 nDotDashIndex(0);
- bool bIsLine(true);
- double fDotDashMovingLength(rDotDashArray[0]);
- B2DPolygon aSnippet;
+ // precalculate maximal acceptable length of candidate polygon assuming
+ // we want to create a maximum of fNumberOfAllowedSnippets. For
+ // fNumberOfAllowedSnippets use ca. 65536, double due to line & gap.
+ static double fNumberOfAllowedSnippets(65535.0 * 2.0);
+ const double fAllowedLength((fNumberOfAllowedSnippets * fDotDashLength) / double(rDotDashArray.size()));
+ const double fCandidateLength(basegfx::utils::getLength(rCandidate));
+ std::vector<double> aDotDashArray(rDotDashArray);
- // iterate over all edges
- for(sal_uInt32 a(0); a < nEdgeCount; a++)
- {
- // update current edge (fill in C1, C2 and end point)
- double fLastDotDashMovingLength(0.0);
- const sal_uInt32 nNextIndex((a + 1) % nPointCount);
- aCurrentEdge.setControlPointA(rCandidate.getNextControlPoint(a));
- aCurrentEdge.setControlPointB(rCandidate.getPrevControlPoint(nNextIndex));
- aCurrentEdge.setEndPoint(rCandidate.getB2DPoint(nNextIndex));
+ if(fCandidateLength > fAllowedLength)
+ {
+ // we would produce more than fNumberOfAllowedSnippets, so
+ // adapt aDotDashArray to exactly produce assumed number. Also
+ // assert this to let the caller know about it.
+ // If this asserts: Please think about checking your DotDashArray
+ // before calling this function or evtl. use the callback version
+ // to *not* produce that much of data. Even then, you may still
+ // think about producing too much runtime (!)
+ assert(true && "applyLineDashing: potentially too expensive to do the requested dismantle - please consider stretched LineDash pattern (!)");
- // check if we have a trivial bezier segment -> possible fallback to edge
- aCurrentEdge.testAndSolveTrivialBezier();
+ // calculate correcting factor, apply to aDotDashArray and fDotDashLength
+ // to enlarge these as needed
+ const double fFactor(fCandidateLength / fAllowedLength);
+ std::for_each(aDotDashArray.begin(), aDotDashArray.end(), [&fFactor](double &f){ f *= fFactor; });
+ fDotDashLength *= fFactor;
+ }
- if(aCurrentEdge.isBezier())
- {
- // bezier segment
- const B2DCubicBezierHelper aCubicBezierHelper(aCurrentEdge);
- const double fEdgeLength(aCubicBezierHelper.getLength());
+ // prepare current edge's start
+ B2DCubicBezier aCurrentEdge;
+ const bool bIsClosed(rCandidate.isClosed());
+ const sal_uInt32 nEdgeCount(bIsClosed ? nPointCount : nPointCount - 1);
+ aCurrentEdge.setStartPoint(rCandidate.getB2DPoint(0));
- if(!fTools::equalZero(fEdgeLength))
- {
- while(fTools::less(fDotDashMovingLength, fEdgeLength))
- {
- // new split is inside edge, create and append snippet [fLastDotDashMovingLength, fDotDashMovingLength]
- const bool bHandleLine(bIsLine && pLineTarget);
- const bool bHandleGap(!bIsLine && pGapTarget);
+ // prepare DotDashArray iteration and the line/gap switching bool
+ sal_uInt32 nDotDashIndex(0);
+ bool bIsLine(true);
+ double fDotDashMovingLength(aDotDashArray[0]);
+ B2DPolygon aSnippet;
- if(bHandleLine || bHandleGap)
- {
- const double fBezierSplitStart(aCubicBezierHelper.distanceToRelative(fLastDotDashMovingLength));
- const double fBezierSplitEnd(aCubicBezierHelper.distanceToRelative(fDotDashMovingLength));
- B2DCubicBezier aBezierSnippet(aCurrentEdge.snippet(fBezierSplitStart, fBezierSplitEnd));
+ // remember 1st and last snippets to try to merge after execution
+ // is complete and hand to callback
+ B2DPolygon aFirstLine, aLastLine;
+ B2DPolygon aFirstGap, aLastGap;
- if(!aSnippet.count())
- {
- aSnippet.append(aBezierSnippet.getStartPoint());
- }
-
- aSnippet.appendBezierSegment(aBezierSnippet.getControlPointA(), aBezierSnippet.getControlPointB(), aBezierSnippet.getEndPoint());
-
- if(bHandleLine)
- {
- pLineTarget->append(aSnippet);
- }
- else
- {
- pGapTarget->append(aSnippet);
- }
+ // iterate over all edges
+ for(sal_uInt32 a(0); a < nEdgeCount; a++)
+ {
+ // update current edge (fill in C1, C2 and end point)
+ double fLastDotDashMovingLength(0.0);
+ const sal_uInt32 nNextIndex((a + 1) % nPointCount);
+ aCurrentEdge.setControlPointA(rCandidate.getNextControlPoint(a));
+ aCurrentEdge.setControlPointB(rCandidate.getPrevControlPoint(nNextIndex));
+ aCurrentEdge.setEndPoint(rCandidate.getB2DPoint(nNextIndex));
- aSnippet.clear();
- }
+ // check if we have a trivial bezier segment -> possible fallback to edge
+ aCurrentEdge.testAndSolveTrivialBezier();
- // prepare next DotDashArray step and flip line/gap flag
- fLastDotDashMovingLength = fDotDashMovingLength;
- fDotDashMovingLength += rDotDashArray[(++nDotDashIndex) % nDotDashCount];
- bIsLine = !bIsLine;
- }
+ if(aCurrentEdge.isBezier())
+ {
+ // bezier segment
+ const B2DCubicBezierHelper aCubicBezierHelper(aCurrentEdge);
+ const double fEdgeLength(aCubicBezierHelper.getLength());
- // append closing snippet [fLastDotDashMovingLength, fEdgeLength]
- const bool bHandleLine(bIsLine && pLineTarget);
- const bool bHandleGap(!bIsLine && pGapTarget);
+ if(!fTools::equalZero(fEdgeLength))
+ {
+ while(fTools::less(fDotDashMovingLength, fEdgeLength))
+ {
+ // new split is inside edge, create and append snippet [fLastDotDashMovingLength, fDotDashMovingLength]
+ const bool bHandleLine(bIsLine && aLineTargetCallback);
+ const bool bHandleGap(!bIsLine && aGapTargetCallback);
if(bHandleLine || bHandleGap)
{
- B2DCubicBezier aRight;
- const double fBezierSplit(aCubicBezierHelper.distanceToRelative(fLastDotDashMovingLength));
-
- aCurrentEdge.split(fBezierSplit, nullptr, &aRight);
+ const double fBezierSplitStart(aCubicBezierHelper.distanceToRelative(fLastDotDashMovingLength));
+ const double fBezierSplitEnd(aCubicBezierHelper.distanceToRelative(fDotDashMovingLength));
+ B2DCubicBezier aBezierSnippet(aCurrentEdge.snippet(fBezierSplitStart, fBezierSplitEnd));
if(!aSnippet.count())
{
- aSnippet.append(aRight.getStartPoint());
+ aSnippet.append(aBezierSnippet.getStartPoint());
}
- aSnippet.appendBezierSegment(aRight.getControlPointA(), aRight.getControlPointB(), aRight.getEndPoint());
+ aSnippet.appendBezierSegment(aBezierSnippet.getControlPointA(), aBezierSnippet.getControlPointB(), aBezierSnippet.getEndPoint());
+
+ if(bHandleLine)
+ {
+ implHandleSnippet(aSnippet, aLineTargetCallback, aFirstLine, aLastLine);
+ }
+
+ if(bHandleGap)
+ {
+ implHandleSnippet(aSnippet, aGapTargetCallback, aFirstGap, aLastGap);
+ }
+
+ aSnippet.clear();
}
- // prepare move to next edge
- fDotDashMovingLength -= fEdgeLength;
+ // prepare next DotDashArray step and flip line/gap flag
+ fLastDotDashMovingLength = fDotDashMovingLength;
+ fDotDashMovingLength += aDotDashArray[(++nDotDashIndex) % nDotDashCount];
+ bIsLine = !bIsLine;
}
- }
- else
- {
- // simple edge
- const double fEdgeLength(aCurrentEdge.getEdgeLength());
- if(!fTools::equalZero(fEdgeLength))
- {
- while(fTools::less(fDotDashMovingLength, fEdgeLength))
- {
- // new split is inside edge, create and append snippet [fLastDotDashMovingLength, fDotDashMovingLength]
- const bool bHandleLine(bIsLine && pLineTarget);
- const bool bHandleGap(!bIsLine && pGapTarget);
+ // append closing snippet [fLastDotDashMovingLength, fEdgeLength]
+ const bool bHandleLine(bIsLine && aLineTargetCallback);
+ const bool bHandleGap(!bIsLine && aGapTargetCallback);
- if(bHandleLine || bHandleGap)
- {
- if(!aSnippet.count())
- {
- aSnippet.append(interpolate(aCurrentEdge.getStartPoint(), aCurrentEdge.getEndPoint(), fLastDotDashMovingLength / fEdgeLength));
- }
+ if(bHandleLine || bHandleGap)
+ {
+ B2DCubicBezier aRight;
+ const double fBezierSplit(aCubicBezierHelper.distanceToRelative(fLastDotDashMovingLength));
- aSnippet.append(interpolate(aCurrentEdge.getStartPoint(), aCurrentEdge.getEndPoint(), fDotDashMovingLength / fEdgeLength));
+ aCurrentEdge.split(fBezierSplit, nullptr, &aRight);
- if(bHandleLine)
- {
- pLineTarget->append(aSnippet);
- }
- else
- {
- pGapTarget->append(aSnippet);
- }
+ if(!aSnippet.count())
+ {
+ aSnippet.append(aRight.getStartPoint());
+ }
- aSnippet.clear();
- }
+ aSnippet.appendBezierSegment(aRight.getControlPointA(), aRight.getControlPointB(), aRight.getEndPoint());
+ }
- // prepare next DotDashArray step and flip line/gap flag
- fLastDotDashMovingLength = fDotDashMovingLength;
- fDotDashMovingLength += rDotDashArray[(++nDotDashIndex) % nDotDashCount];
- bIsLine = !bIsLine;
- }
+ // prepare move to next edge
+ fDotDashMovingLength -= fEdgeLength;
+ }
+ }
+ else
+ {
+ // simple edge
+ const double fEdgeLength(aCurrentEdge.getEdgeLength());
- // append snippet [fLastDotDashMovingLength, fEdgeLength]
- const bool bHandleLine(bIsLine && pLineTarget);
- const bool bHandleGap(!bIsLine && pGapTarget);
+ if(!fTools::equalZero(fEdgeLength))
+ {
+ while(fTools::less(fDotDashMovingLength, fEdgeLength))
+ {
+ // new split is inside edge, create and append snippet [fLastDotDashMovingLength, fDotDashMovingLength]
+ const bool bHandleLine(bIsLine && aLineTargetCallback);
+ const bool bHandleGap(!bIsLine && aGapTargetCallback);
if(bHandleLine || bHandleGap)
{
@@ -1288,89 +1388,76 @@ namespace basegfx
aSnippet.append(interpolate(aCurrentEdge.getStartPoint(), aCurrentEdge.getEndPoint(), fLastDotDashMovingLength / fEdgeLength));
}
- aSnippet.append(aCurrentEdge.getEndPoint());
- }
-
- // prepare move to next edge
- fDotDashMovingLength -= fEdgeLength;
- }
- }
-
- // prepare next edge step (end point gets new start point)
- aCurrentEdge.setStartPoint(aCurrentEdge.getEndPoint());
- }
+ aSnippet.append(interpolate(aCurrentEdge.getStartPoint(), aCurrentEdge.getEndPoint(), fDotDashMovingLength / fEdgeLength));
- // append last intermediate results (if exists)
- if(aSnippet.count())
- {
- if(bIsLine && pLineTarget)
- {
- pLineTarget->append(aSnippet);
- }
- else if(!bIsLine && pGapTarget)
- {
- pGapTarget->append(aSnippet);
- }
- }
+ if(bHandleLine)
+ {
+ implHandleSnippet(aSnippet, aLineTargetCallback, aFirstLine, aLastLine);
+ }
- // check if start and end polygon may be merged
- if(pLineTarget)
- {
- const sal_uInt32 nCount(pLineTarget->count());
+ if(bHandleGap)
+ {
+ implHandleSnippet(aSnippet, aGapTargetCallback, aFirstGap, aLastGap);
+ }
- if(nCount > 1)
- {
- // these polygons were created above, there exists none with less than two points,
- // thus dircet point access below is allowed
- const B2DPolygon aFirst(pLineTarget->getB2DPolygon(0));
- B2DPolygon aLast(pLineTarget->getB2DPolygon(nCount - 1));
+ aSnippet.clear();
+ }
- if(aFirst.getB2DPoint(0).equal(aLast.getB2DPoint(aLast.count() - 1)))
- {
- // start of first and end of last are the same -> merge them
- aLast.append(aFirst);
- aLast.removeDoublePoints();
- pLineTarget->setB2DPolygon(0, aLast);
- pLineTarget->remove(nCount - 1);
+ // prepare next DotDashArray step and flip line/gap flag
+ fLastDotDashMovingLength = fDotDashMovingLength;
+ fDotDashMovingLength += aDotDashArray[(++nDotDashIndex) % nDotDashCount];
+ bIsLine = !bIsLine;
}
- }
- }
-
- if(pGapTarget)
- {
- const sal_uInt32 nCount(pGapTarget->count());
- if(nCount > 1)
- {
- // these polygons were created above, there exists none with less than two points,
- // thus dircet point access below is allowed
- const B2DPolygon aFirst(pGapTarget->getB2DPolygon(0));
- B2DPolygon aLast(pGapTarget->getB2DPolygon(nCount - 1));
+ // append snippet [fLastDotDashMovingLength, fEdgeLength]
+ const bool bHandleLine(bIsLine && aLineTargetCallback);
+ const bool bHandleGap(!bIsLine && aGapTargetCallback);
- if(aFirst.getB2DPoint(0).equal(aLast.getB2DPoint(aLast.count() - 1)))
+ if(bHandleLine || bHandleGap)
{
- // start of first and end of last are the same -> merge them
- aLast.append(aFirst);
- aLast.removeDoublePoints();
- pGapTarget->setB2DPolygon(0, aLast);
- pGapTarget->remove(nCount - 1);
+ if(!aSnippet.count())
+ {
+ aSnippet.append(interpolate(aCurrentEdge.getStartPoint(), aCurrentEdge.getEndPoint(), fLastDotDashMovingLength / fEdgeLength));
+ }
+
+ aSnippet.append(aCurrentEdge.getEndPoint());
}
+
+ // prepare move to next edge
+ fDotDashMovingLength -= fEdgeLength;
}
}
+
+ // prepare next edge step (end point gets new start point)
+ aCurrentEdge.setStartPoint(aCurrentEdge.getEndPoint());
}
- else
+
+ // append last intermediate results (if exists)
+ if(aSnippet.count())
{
- // parameters make no sense, just add source to targets
- if(pLineTarget)
+ const bool bHandleLine(bIsLine && aLineTargetCallback);
+ const bool bHandleGap(!bIsLine && aGapTargetCallback);
+
+ if(bHandleLine)
{
- pLineTarget->append(rCandidate);
+ implHandleSnippet(aSnippet, aLineTargetCallback, aFirstLine, aLastLine);
}
- if(pGapTarget)
+ if(bHandleGap)
{
- pGapTarget->append(rCandidate);
+ implHandleSnippet(aSnippet, aGapTargetCallback, aFirstGap, aLastGap);
}
}
+
+ if(bIsClosed && aLineTargetCallback)
+ {
+ implHandleFirstLast(aLineTargetCallback, aFirstLine, aLastLine);
+ }
+
+ if(bIsClosed && aGapTargetCallback)
+ {
+ implHandleFirstLast(aGapTargetCallback, aFirstGap, aLastGap);
+ }
}
// test if point is inside epsilon-range around an edge defined
diff --git a/include/basegfx/polygon/b2dpolygontools.hxx b/include/basegfx/polygon/b2dpolygontools.hxx
index 57b9130b4399..9defd76ef548 100644
--- a/include/basegfx/polygon/b2dpolygontools.hxx
+++ b/include/basegfx/polygon/b2dpolygontools.hxx
@@ -20,6 +20,9 @@
#ifndef INCLUDED_BASEGFX_POLYGON_B2DPOLYGONTOOLS_HXX
#define INCLUDED_BASEGFX_POLYGON_B2DPOLYGONTOOLS_HXX
+#include <vector>
+#include <functional>
+
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <basegfx/range/b2drectangle.hxx>
@@ -27,7 +30,6 @@
#include <basegfx/polygon/b2dpolygontriangulator.hxx>
#include <com/sun/star/drawing/PointSequence.hpp>
#include <com/sun/star/drawing/FlagSequence.hpp>
-#include <vector>
#include <basegfx/basegfxdllapi.h>
#include <o3tl/typed_flags_set.hxx>
@@ -188,7 +190,27 @@ namespace basegfx
@param fFullDashDotLen
The summed-up length of the rDotDashArray. If zero, it will
be calculated internally.
+
+ There is now a 2nd version that allows to provide callback
+ functions that get called when a snippet of a line/gap is
+ produced and needs to be added. This allows to use it like
+ a 'pipeline'. When using this (e.g. the 1st version uses
+ this internally to guarantee the same algorithm is used)
+ it is not needed to accumulate a potentially huge number
+ of polygons in the result-polyPolygons, but e.g. consume
+ them directly in the caller. Example is renderinmg a
+ dashed line but without creating the potentially huge amount
+ of polygons.
+ The 2nd version will also merge first/last line/gap snippets
+ if the input polygon is closed and the start/end-points match
+ accordingly - at the cost that this will be delivered last.
*/
+ BASEGFX_DLLPUBLIC void applyLineDashing(
+ const B2DPolygon& rCandidate,
+ const std::vector<double>& rDotDashArray,
+ std::function<void(const basegfx::B2DPolygon& rSnippet)> aLineTargetCallback,
+ std::function<void(const basegfx::B2DPolygon& rSnippet)> aGapTargetCallback = std::function<void(const basegfx::B2DPolygon&)>(),
+ double fDotDashLength = 0.0);
BASEGFX_DLLPUBLIC void applyLineDashing(
const B2DPolygon& rCandidate,
const ::std::vector<double>& rDotDashArray,
More information about the Libreoffice-commits
mailing list