[Libreoffice-commits] core.git: Branch 'aoo/trunk' - 2 commits - basegfx/inc basegfx/source default_images/introabout svgio/inc svgio/source
Ariel Constenla-Haile
arielch at apache.org
Fri Oct 11 11:08:11 PDT 2013
basegfx/inc/basegfx/polygon/b2dpolygontools.hxx | 8
basegfx/source/polygon/b2dpolygontools.cxx | 82 +++++++
default_images/introabout/about.png |binary
svgio/inc/svgio/svgreader/svgstyleattributes.hxx | 8
svgio/source/svgreader/svgstyleattributes.cxx | 269 +++++++++++------------
5 files changed, 230 insertions(+), 137 deletions(-)
New commits:
commit 6a73411295de9cda5441b58cf6c5c13f89cdcd80
Author: Ariel Constenla-Haile <arielch at apache.org>
Date: Fri Oct 11 17:20:02 2013 +0000
Remove orb from About dialog's header
diff --git a/default_images/introabout/about.png b/default_images/introabout/about.png
index c1a5464..2e25ec1 100755
Binary files a/default_images/introabout/about.png and b/default_images/introabout/about.png differ
commit ff1eee61fc56b06e436735f5e2b133db56de3608
Author: Armin Le Grand <alg at apache.org>
Date: Fri Oct 11 16:57:46 2013 +0000
i123379 various SVG marker corrections
diff --git a/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx b/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx
index 721779a..c3212ea 100644
--- a/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx
+++ b/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx
@@ -532,6 +532,14 @@ namespace basegfx
*/
bool containsOnlyHorizontalAndVerticalEdges(const B2DPolygon& rCandidate);
+ /// get the tangent with which the given point is entered seen from the previous
+ /// polygon path data. Take into account all stuff like closed state, zero-length edges and others.
+ B2DVector getTangentEnteringPoint(const B2DPolygon& rCandidate, sal_uInt32 nIndex);
+
+ /// get the tangent with which the given point is left seen from the following
+ /// polygon path data. Take into account all stuff like closed state, zero-length edges and others.
+ B2DVector getTangentLeavingPoint(const B2DPolygon& rCandidate, sal_uInt32 nIndex);
+
} // end of namespace tools
} // end of namespace basegfx
diff --git a/basegfx/source/polygon/b2dpolygontools.cxx b/basegfx/source/polygon/b2dpolygontools.cxx
index c30b042d..2c08c29 100644
--- a/basegfx/source/polygon/b2dpolygontools.cxx
+++ b/basegfx/source/polygon/b2dpolygontools.cxx
@@ -3660,6 +3660,88 @@ namespace basegfx
return true;
}
+ B2DVector getTangentEnteringPoint(const B2DPolygon& rCandidate, sal_uInt32 nIndex)
+ {
+ B2DVector aRetval(0.0, 0.0);
+ const sal_uInt32 nCount(rCandidate.count());
+
+ if(nIndex >= nCount)
+ {
+ // out of range
+ return aRetval;
+ }
+
+ // start immediately at prev point compared to nIndex
+ const bool bClosed(rCandidate.isClosed());
+ sal_uInt32 nPrev(bClosed ? (nIndex + nCount - 1) % nCount : nIndex ? nIndex - 1 : nIndex);
+
+ if(nPrev == nIndex)
+ {
+ // no previous, done
+ return aRetval;
+ }
+
+ B2DCubicBezier aSegment;
+
+ // go backward in the polygon; if closed, maximal back to start index (nIndex); if not closed,
+ // until zero. Use nIndex as stop criteria
+ while(nPrev != nIndex)
+ {
+ // get BezierSegment and tangent at the *end* of segment
+ rCandidate.getBezierSegment(nPrev, aSegment);
+ aRetval = aSegment.getTangent(1.0);
+
+ if(!aRetval.equalZero())
+ {
+ // if we have a tangent, return it
+ return aRetval;
+ }
+
+ // prepare index before checked one
+ nPrev = bClosed ? (nPrev + nCount - 1) % nCount : nPrev ? nPrev - 1 : nIndex;
+ }
+
+ return aRetval;
+ }
+
+ B2DVector getTangentLeavingPoint(const B2DPolygon& rCandidate, sal_uInt32 nIndex)
+ {
+ B2DVector aRetval(0.0, 0.0);
+ const sal_uInt32 nCount(rCandidate.count());
+
+ if(nIndex >= nCount)
+ {
+ // out of range
+ return aRetval;
+ }
+
+ // start at nIndex
+ const bool bClosed(rCandidate.isClosed());
+ sal_uInt32 nCurrent(nIndex);
+ B2DCubicBezier aSegment;
+
+ // go forward; if closed, do this until once around and back at start index (nIndex); if not
+ // closed, until last point (nCount - 1). Use nIndex as stop criteria
+ do
+ {
+ // get BezierSegment and tangent at the *beginning* of segment
+ rCandidate.getBezierSegment(nCurrent, aSegment);
+ aRetval = aSegment.getTangent(0.0);
+
+ if(!aRetval.equalZero())
+ {
+ // if we have a tangent, return it
+ return aRetval;
+ }
+
+ // prepare next index
+ nCurrent = bClosed ? (nCurrent + 1) % nCount : nCurrent + 1 < nCount ? nCurrent + 1 : nIndex;
+ }
+ while(nCurrent != nIndex);
+
+ return aRetval;
+ }
+
} // end of namespace tools
} // end of namespace basegfx
diff --git a/svgio/inc/svgio/svgreader/svgstyleattributes.hxx b/svgio/inc/svgio/svgreader/svgstyleattributes.hxx
index 7b3cbef..606cdc0 100644
--- a/svgio/inc/svgio/svgreader/svgstyleattributes.hxx
+++ b/svgio/inc/svgio/svgreader/svgstyleattributes.hxx
@@ -251,14 +251,6 @@ namespace svgio
basegfx::B2DHomMatrix& rMarkerTransform,
basegfx::B2DRange& rClipRange,
const SvgMarkerNode& rMarker) const;
- void add_singleMarker(
- drawinglayer::primitive2d::Primitive2DSequence& rTarget,
- const drawinglayer::primitive2d::Primitive2DSequence& rMarkerPrimitives,
- const basegfx::B2DHomMatrix& rMarkerTransform,
- const basegfx::B2DRange& rClipRange,
- const SvgMarkerNode& rMarker,
- const basegfx::B2DPolygon& rCandidate,
- const sal_uInt32 nIndex) const;
void add_markers(
const basegfx::B2DPolyPolygon& rPath,
drawinglayer::primitive2d::Primitive2DSequence& rTarget) const;
diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx
index 817f3a8..e0df4e0 100644
--- a/svgio/source/svgreader/svgstyleattributes.cxx
+++ b/svgio/source/svgreader/svgstyleattributes.cxx
@@ -746,59 +746,6 @@ namespace svgio
}
}
- double get_markerRotation(
- const SvgMarkerNode& rMarker,
- const basegfx::B2DPolygon& rPolygon,
- const sal_uInt32 nIndex)
- {
- double fAngle(0.0);
- const sal_uInt32 nPointCount(rPolygon.count());
-
- if(nPointCount)
- {
- if(rMarker.getOrientAuto())
- {
- const bool bPrev(rPolygon.isClosed() || nIndex > 0);
- basegfx::B2DCubicBezier aSegment;
- basegfx::B2DVector aPrev;
- basegfx::B2DVector aNext;
-
- if(bPrev)
- {
- rPolygon.getBezierSegment((nIndex - 1) % nPointCount, aSegment);
- aPrev = aSegment.getTangent(1.0);
- }
-
- const bool bNext(rPolygon.isClosed() || nIndex + 1 < nPointCount);
-
- if(bNext)
- {
- rPolygon.getBezierSegment(nIndex % nPointCount, aSegment);
- aNext = aSegment.getTangent(0.0);
- }
-
- if(bPrev && bNext)
- {
- fAngle = atan2(aPrev.getY() + aNext.getY(), aPrev.getX() + aNext.getX());
- }
- else if(bPrev)
- {
- fAngle = atan2(aPrev.getY(), aPrev.getX());
- }
- else if(bNext)
- {
- fAngle = atan2(aNext.getY(), aNext.getX());
- }
- }
- else
- {
- fAngle = rMarker.getAngle();
- }
- }
-
- return fAngle;
- }
-
bool SvgStyleAttributes::prepare_singleMarker(
drawinglayer::primitive2d::Primitive2DSequence& rMarkerPrimitives,
basegfx::B2DHomMatrix& rMarkerTransform,
@@ -889,49 +836,6 @@ namespace svgio
return false;
}
- void SvgStyleAttributes::add_singleMarker(
- drawinglayer::primitive2d::Primitive2DSequence& rTarget,
- const drawinglayer::primitive2d::Primitive2DSequence& rMarkerPrimitives,
- const basegfx::B2DHomMatrix& rMarkerTransform,
- const basegfx::B2DRange& rClipRange,
- const SvgMarkerNode& rMarker,
- const basegfx::B2DPolygon& rCandidate,
- const sal_uInt32 nIndex) const
- {
- const sal_uInt32 nPointCount(rCandidate.count());
-
- if(nPointCount)
- {
- // get and apply rotation
- basegfx::B2DHomMatrix aCombinedTransform(rMarkerTransform);
- aCombinedTransform.rotate(get_markerRotation(rMarker, rCandidate, nIndex));
-
- // get and apply target position
- const basegfx::B2DPoint aPoint(rCandidate.getB2DPoint(nIndex % nPointCount));
- aCombinedTransform.translate(aPoint.getX(), aPoint.getY());
-
- // prepare marker
- drawinglayer::primitive2d::Primitive2DReference xMarker(
- new drawinglayer::primitive2d::TransformPrimitive2D(
- aCombinedTransform,
- rMarkerPrimitives));
-
- if(!rClipRange.isEmpty())
- {
- // marker needs to be clipped, it's bigger as the mapping
- basegfx::B2DPolyPolygon aClipPolygon(basegfx::tools::createPolygonFromRect(rClipRange));
-
- aClipPolygon.transform(aCombinedTransform);
- xMarker = new drawinglayer::primitive2d::MaskPrimitive2D(
- aClipPolygon,
- drawinglayer::primitive2d::Primitive2DSequence(&xMarker, 1));
- }
-
- // add marker
- drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMarker);
- }
- }
-
void SvgStyleAttributes::add_markers(
const basegfx::B2DPolyPolygon& rPath,
drawinglayer::primitive2d::Primitive2DSequence& rTarget) const
@@ -943,51 +847,158 @@ namespace svgio
if(pStart || pMid || pEnd)
{
- const sal_uInt32 nCount(rPath.count());
+ const sal_uInt32 nSubPathCount(rPath.count());
- for (sal_uInt32 a(0); a < nCount; a++)
+ if(nSubPathCount)
{
- const basegfx::B2DPolygon aCandidate(rPath.getB2DPolygon(a));
- const sal_uInt32 nPointCount(aCandidate.count());
+ // remember prepared marker; pStart, pMid and pEnd may all be equal when
+ // only 'marker' was used instead of 'marker-start', 'marker-mid' or 'marker-end',
+ // see 'case SVGTokenMarker' in this file; thus in this case only one common
+ // marker in primitive form will be prepared
+ const SvgMarkerNode* pPrepared = 0;
+
+ // values for the prepared marker, results of prepare_singleMarker
+ drawinglayer::primitive2d::Primitive2DSequence aPreparedMarkerPrimitives;
+ basegfx::B2DHomMatrix aPreparedMarkerTransform;
+ basegfx::B2DRange aPreparedMarkerClipRange;
- if(nPointCount)
+ for (sal_uInt32 a(0); a < nSubPathCount; a++)
{
- const sal_uInt32 nMarkerCount(aCandidate.isClosed() ? nPointCount + 1 : nPointCount);
- drawinglayer::primitive2d::Primitive2DSequence aMarkerPrimitives;
- basegfx::B2DHomMatrix aMarkerTransform;
- basegfx::B2DRange aClipRange;
- const SvgMarkerNode* pPrepared = 0;
+ // iterate over sub-paths
+ const basegfx::B2DPolygon aSubPolygonPath(rPath.getB2DPolygon(a));
+ const sal_uInt32 nSubPolygonPointCount(aSubPolygonPath.count());
+ const bool bSubPolygonPathIsClosed(aSubPolygonPath.isClosed());
- if(pStart && a==0)
+ if(nSubPolygonPointCount)
{
- if(prepare_singleMarker(aMarkerPrimitives, aMarkerTransform, aClipRange, *pStart))
- {
- pPrepared = pStart;
- add_singleMarker(rTarget, aMarkerPrimitives, aMarkerTransform, aClipRange, *pPrepared, aCandidate, 0);
- }
- }
+ // for each sub-path, create one marker per point (when closed, two markers
+ // need to pe created for the 1st point)
+ const sal_uInt32 nTargetMarkerCount(bSubPolygonPathIsClosed ? nSubPolygonPointCount + 1 : nSubPolygonPointCount);
- if(pMid)
- {
- if(pMid == pPrepared || prepare_singleMarker(aMarkerPrimitives, aMarkerTransform, aClipRange, *pMid))
+ for (sal_uInt32 b(0); b < nTargetMarkerCount; b++)
{
- pPrepared = pMid;
- const sal_uInt32 nFirstIndex(a==0 ? 1 : 0);
- const sal_uInt32 nLastIndex(a==nCount-1 ? nMarkerCount-1 : nMarkerCount);
+ const bool bIsFirstMarker(!a && !b);
+ const bool bIsLastMarker(nSubPathCount - 1 == a && nTargetMarkerCount - 1 == b);
+ const SvgMarkerNode* pNeeded = 0;
- for(sal_uInt32 b(nFirstIndex); b < nLastIndex; b++)
+ if(bIsFirstMarker)
{
- add_singleMarker(rTarget, aMarkerPrimitives, aMarkerTransform, aClipRange, *pPrepared, aCandidate, b);
+ // 1st point in 1st sub-polygon, use pStart
+ pNeeded = pStart;
+ }
+ else if(bIsLastMarker)
+ {
+ // last point in last sub-polygon, use pEnd
+ pNeeded = pEnd;
+ }
+ else
+ {
+ // anything in-between, use pMid
+ pNeeded = pMid;
}
- }
- }
- if(pEnd && a==nCount-1)
- {
- if(pEnd == pPrepared || prepare_singleMarker(aMarkerPrimitives, aMarkerTransform, aClipRange, *pEnd))
- {
- pPrepared = pEnd;
- add_singleMarker(rTarget, aMarkerPrimitives, aMarkerTransform, aClipRange, *pPrepared, aCandidate, nMarkerCount - 1);
+ if(!pNeeded)
+ {
+ // no marker needs to be created for this point
+ continue;
+ }
+
+ if(pPrepared != pNeeded)
+ {
+ // if needed marker is not yet prepared, do it now
+ if(prepare_singleMarker(aPreparedMarkerPrimitives, aPreparedMarkerTransform, aPreparedMarkerClipRange, *pNeeded))
+ {
+ pPrepared = pNeeded;
+ }
+ else
+ {
+ // error: could not prepare given marker
+ OSL_ENSURE(false, "OOps, could not prepare given marker as primitives (!)");
+ pPrepared = 0;
+ continue;
+ }
+ }
+
+ // prepare complete transform
+ basegfx::B2DHomMatrix aCombinedTransform(aPreparedMarkerTransform);
+
+ // get rotation
+ if(pPrepared->getOrientAuto())
+ {
+ const sal_uInt32 nPointIndex(b % nSubPolygonPointCount);
+
+ // get entering and leaving tangents; this will search backward/froward
+ // in the polygon to find tangents unequal to zero, skipping empty edges
+ // see basegfx descriptions)
+ // Hint: Mozilla, Inkscape and others use only leaving tangent for start marker
+ // and entering tangent for end marker. To achieve this (if wanted) it is possibe
+ // to make the fetch of aEntering/aLeaving dependent on bIsFirstMarker/bIsLastMarker.
+ // This is not done here, see comment 14 in task #1232379#
+ // or http://www.w3.org/TR/SVG/painting.html#OrientAttribute
+ basegfx::B2DVector aEntering(
+ basegfx::tools::getTangentEnteringPoint(
+ aSubPolygonPath,
+ nPointIndex));
+ basegfx::B2DVector aLeaving(
+ basegfx::tools::getTangentLeavingPoint(
+ aSubPolygonPath,
+ nPointIndex));
+ const bool bEntering(!aEntering.equalZero());
+ const bool bLeaving(!aLeaving.equalZero());
+
+ if(bEntering || bLeaving)
+ {
+ basegfx::B2DVector aSum(0.0, 0.0);
+
+ if(bEntering)
+ {
+ aSum += aEntering.normalize();
+ }
+
+ if(bLeaving)
+ {
+ aSum += aLeaving.normalize();
+ }
+
+ if(!aSum.equalZero())
+ {
+ const double fAngle(atan2(aSum.getY(), aSum.getX()));
+
+ // apply rotation
+ aCombinedTransform.rotate(fAngle);
+ }
+ }
+ }
+ else
+ {
+ // apply rotation
+ aCombinedTransform.rotate(pPrepared->getAngle());
+ }
+
+ // get and apply target position
+ const basegfx::B2DPoint aPoint(aSubPolygonPath.getB2DPoint(b % nSubPolygonPointCount));
+
+ aCombinedTransform.translate(aPoint.getX(), aPoint.getY());
+
+ // prepare marker
+ drawinglayer::primitive2d::Primitive2DReference xMarker(
+ new drawinglayer::primitive2d::TransformPrimitive2D(
+ aCombinedTransform,
+ aPreparedMarkerPrimitives));
+
+ if(!aPreparedMarkerClipRange.isEmpty())
+ {
+ // marker needs to be clipped, it's bigger as the mapping
+ basegfx::B2DPolyPolygon aClipPolygon(basegfx::tools::createPolygonFromRect(aPreparedMarkerClipRange));
+
+ aClipPolygon.transform(aCombinedTransform);
+ xMarker = new drawinglayer::primitive2d::MaskPrimitive2D(
+ aClipPolygon,
+ drawinglayer::primitive2d::Primitive2DSequence(&xMarker, 1));
+ }
+
+ // add marker
+ drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMarker);
}
}
}
More information about the Libreoffice-commits
mailing list