зеркало из https://github.com/mozilla/gecko-dev.git
Bug 930443 - Convert SVGPathSegUtils to Moz2D. r=heycam
This commit is contained in:
Родитель
e8c916e8ce
Коммит
4377d14f29
|
@ -4,10 +4,13 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "SVGPathSegUtils.h"
|
||||
|
||||
#include "gfx2DGlue.h"
|
||||
#include "nsSVGPathDataParser.h"
|
||||
#include "nsTextFormatter.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
static const float PATH_SEG_LENGTH_TOLERANCE = 0.0000001f;
|
||||
static const uint32_t MAX_RECURSION = 10;
|
||||
|
@ -80,14 +83,14 @@ SVGPathSegUtils::GetValueAsString(const float* aSeg, nsAString& aValue)
|
|||
|
||||
|
||||
static float
|
||||
CalcDistanceBetweenPoints(const gfxPoint& aP1, const gfxPoint& aP2)
|
||||
CalcDistanceBetweenPoints(const Point& aP1, const Point& aP2)
|
||||
{
|
||||
return NS_hypot(aP2.x - aP1.x, aP2.y - aP1.y);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
SplitQuadraticBezier(const gfxPoint* aCurve, gfxPoint* aLeft, gfxPoint* aRight)
|
||||
SplitQuadraticBezier(const Point* aCurve, Point* aLeft, Point* aRight)
|
||||
{
|
||||
aLeft[0].x = aCurve[0].x;
|
||||
aLeft[0].y = aCurve[0].y;
|
||||
|
@ -102,9 +105,9 @@ SplitQuadraticBezier(const gfxPoint* aCurve, gfxPoint* aLeft, gfxPoint* aRight)
|
|||
}
|
||||
|
||||
static void
|
||||
SplitCubicBezier(const gfxPoint* aCurve, gfxPoint* aLeft, gfxPoint* aRight)
|
||||
SplitCubicBezier(const Point* aCurve, Point* aLeft, Point* aRight)
|
||||
{
|
||||
gfxPoint tmp;
|
||||
Point tmp;
|
||||
tmp.x = (aCurve[1].x + aCurve[2].x) / 4;
|
||||
tmp.y = (aCurve[1].y + aCurve[2].y) / 4;
|
||||
aLeft[0].x = aCurve[0].x;
|
||||
|
@ -124,12 +127,12 @@ SplitCubicBezier(const gfxPoint* aCurve, gfxPoint* aLeft, gfxPoint* aRight)
|
|||
}
|
||||
|
||||
static gfxFloat
|
||||
CalcBezLengthHelper(gfxPoint* aCurve, uint32_t aNumPts,
|
||||
CalcBezLengthHelper(const Point* aCurve, uint32_t aNumPts,
|
||||
uint32_t aRecursionCount,
|
||||
void (*aSplit)(const gfxPoint*, gfxPoint*, gfxPoint*))
|
||||
void (*aSplit)(const Point*, Point*, Point*))
|
||||
{
|
||||
gfxPoint left[4];
|
||||
gfxPoint right[4];
|
||||
Point left[4];
|
||||
Point right[4];
|
||||
gfxFloat length = 0, dist;
|
||||
for (uint32_t i = 0; i < aNumPts - 1; i++) {
|
||||
length += CalcDistanceBetweenPoints(aCurve[i], aCurve[i+1]);
|
||||
|
@ -146,18 +149,18 @@ CalcBezLengthHelper(gfxPoint* aCurve, uint32_t aNumPts,
|
|||
}
|
||||
|
||||
static inline gfxFloat
|
||||
CalcLengthOfCubicBezier(const gfxPoint& aPos, const gfxPoint &aCP1,
|
||||
const gfxPoint& aCP2, const gfxPoint &aTo)
|
||||
CalcLengthOfCubicBezier(const Point& aPos, const Point &aCP1,
|
||||
const Point& aCP2, const Point &aTo)
|
||||
{
|
||||
gfxPoint curve[4] = { aPos, aCP1, aCP2, aTo };
|
||||
Point curve[4] = { aPos, aCP1, aCP2, aTo };
|
||||
return CalcBezLengthHelper(curve, 4, 0, SplitCubicBezier);
|
||||
}
|
||||
|
||||
static inline gfxFloat
|
||||
CalcLengthOfQuadraticBezier(const gfxPoint& aPos, const gfxPoint& aCP,
|
||||
const gfxPoint& aTo)
|
||||
CalcLengthOfQuadraticBezier(const Point& aPos, const Point& aCP,
|
||||
const Point& aTo)
|
||||
{
|
||||
gfxPoint curve[3] = { aPos, aCP, aTo };
|
||||
Point curve[3] = { aPos, aCP, aTo };
|
||||
return CalcBezLengthHelper(curve, 3, 0, SplitQuadraticBezier);
|
||||
}
|
||||
|
||||
|
@ -175,7 +178,7 @@ TraverseClosePath(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseMovetoAbs(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
aState.start = aState.pos = gfxPoint(aArgs[0], aArgs[1]);
|
||||
aState.start = aState.pos = Point(aArgs[0], aArgs[1]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
// aState.length is unchanged, since move commands don't affect path length.
|
||||
aState.cp1 = aState.cp2 = aState.start;
|
||||
|
@ -185,7 +188,7 @@ TraverseMovetoAbs(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseMovetoRel(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
aState.start = aState.pos += gfxPoint(aArgs[0], aArgs[1]);
|
||||
aState.start = aState.pos += Point(aArgs[0], aArgs[1]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
// aState.length is unchanged, since move commands don't affect path length.
|
||||
aState.cp1 = aState.cp2 = aState.start;
|
||||
|
@ -195,7 +198,7 @@ TraverseMovetoRel(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseLinetoAbs(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to(aArgs[0], aArgs[1]);
|
||||
Point to(aArgs[0], aArgs[1]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
aState.length += CalcDistanceBetweenPoints(aState.pos, to);
|
||||
aState.cp1 = aState.cp2 = to;
|
||||
|
@ -206,7 +209,7 @@ TraverseLinetoAbs(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseLinetoRel(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
|
||||
Point to = aState.pos + Point(aArgs[0], aArgs[1]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
aState.length += CalcDistanceBetweenPoints(aState.pos, to);
|
||||
aState.cp1 = aState.cp2 = to;
|
||||
|
@ -217,7 +220,7 @@ TraverseLinetoRel(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseLinetoHorizontalAbs(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to(aArgs[0], aState.pos.y);
|
||||
Point to(aArgs[0], aState.pos.y);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
aState.length += fabs(to.x - aState.pos.x);
|
||||
aState.cp1 = aState.cp2 = to;
|
||||
|
@ -238,7 +241,7 @@ TraverseLinetoHorizontalRel(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseLinetoVerticalAbs(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to(aState.pos.x, aArgs[0]);
|
||||
Point to(aState.pos.x, aArgs[0]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
aState.length += fabs(to.y - aState.pos.y);
|
||||
aState.cp1 = aState.cp2 = to;
|
||||
|
@ -259,10 +262,10 @@ TraverseLinetoVerticalRel(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseCurvetoCubicAbs(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to(aArgs[4], aArgs[5]);
|
||||
Point to(aArgs[4], aArgs[5]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
gfxPoint cp1(aArgs[0], aArgs[1]);
|
||||
gfxPoint cp2(aArgs[2], aArgs[3]);
|
||||
Point cp1(aArgs[0], aArgs[1]);
|
||||
Point cp2(aArgs[2], aArgs[3]);
|
||||
aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
|
||||
aState.cp2 = cp2;
|
||||
aState.cp1 = to;
|
||||
|
@ -273,10 +276,10 @@ TraverseCurvetoCubicAbs(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseCurvetoCubicSmoothAbs(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to(aArgs[2], aArgs[3]);
|
||||
Point to(aArgs[2], aArgs[3]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
gfxPoint cp1 = aState.pos - (aState.cp2 - aState.pos);
|
||||
gfxPoint cp2(aArgs[0], aArgs[1]);
|
||||
Point cp1 = aState.pos - (aState.cp2 - aState.pos);
|
||||
Point cp2(aArgs[0], aArgs[1]);
|
||||
aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
|
||||
aState.cp2 = cp2;
|
||||
aState.cp1 = to;
|
||||
|
@ -287,10 +290,10 @@ TraverseCurvetoCubicSmoothAbs(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseCurvetoCubicRel(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to = aState.pos + gfxPoint(aArgs[4], aArgs[5]);
|
||||
Point to = aState.pos + Point(aArgs[4], aArgs[5]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
gfxPoint cp1 = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
|
||||
gfxPoint cp2 = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
|
||||
Point cp1 = aState.pos + Point(aArgs[0], aArgs[1]);
|
||||
Point cp2 = aState.pos + Point(aArgs[2], aArgs[3]);
|
||||
aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
|
||||
aState.cp2 = cp2;
|
||||
aState.cp1 = to;
|
||||
|
@ -301,10 +304,10 @@ TraverseCurvetoCubicRel(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseCurvetoCubicSmoothRel(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
|
||||
Point to = aState.pos + Point(aArgs[2], aArgs[3]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
gfxPoint cp1 = aState.pos - (aState.cp2 - aState.pos);
|
||||
gfxPoint cp2 = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
|
||||
Point cp1 = aState.pos - (aState.cp2 - aState.pos);
|
||||
Point cp2 = aState.pos + Point(aArgs[0], aArgs[1]);
|
||||
aState.length += (float)CalcLengthOfCubicBezier(aState.pos, cp1, cp2, to);
|
||||
aState.cp2 = cp2;
|
||||
aState.cp1 = to;
|
||||
|
@ -315,9 +318,9 @@ TraverseCurvetoCubicSmoothRel(const float* aArgs, SVGPathTraversalState& aState)
|
|||
static void
|
||||
TraverseCurvetoQuadraticAbs(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to(aArgs[2], aArgs[3]);
|
||||
Point to(aArgs[2], aArgs[3]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
gfxPoint cp(aArgs[0], aArgs[1]);
|
||||
Point cp(aArgs[0], aArgs[1]);
|
||||
aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
|
||||
aState.cp1 = cp;
|
||||
aState.cp2 = to;
|
||||
|
@ -329,9 +332,9 @@ static void
|
|||
TraverseCurvetoQuadraticSmoothAbs(const float* aArgs,
|
||||
SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to(aArgs[0], aArgs[1]);
|
||||
Point to(aArgs[0], aArgs[1]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
gfxPoint cp = aState.pos - (aState.cp1 - aState.pos);
|
||||
Point cp = aState.pos - (aState.cp1 - aState.pos);
|
||||
aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
|
||||
aState.cp1 = cp;
|
||||
aState.cp2 = to;
|
||||
|
@ -342,9 +345,9 @@ TraverseCurvetoQuadraticSmoothAbs(const float* aArgs,
|
|||
static void
|
||||
TraverseCurvetoQuadraticRel(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to = aState.pos + gfxPoint(aArgs[2], aArgs[3]);
|
||||
Point to = aState.pos + Point(aArgs[2], aArgs[3]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
gfxPoint cp = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
|
||||
Point cp = aState.pos + Point(aArgs[0], aArgs[1]);
|
||||
aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
|
||||
aState.cp1 = cp;
|
||||
aState.cp2 = to;
|
||||
|
@ -356,9 +359,9 @@ static void
|
|||
TraverseCurvetoQuadraticSmoothRel(const float* aArgs,
|
||||
SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to = aState.pos + gfxPoint(aArgs[0], aArgs[1]);
|
||||
Point to = aState.pos + Point(aArgs[0], aArgs[1]);
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
gfxPoint cp = aState.pos - (aState.cp1 - aState.pos);
|
||||
Point cp = aState.pos - (aState.cp1 - aState.pos);
|
||||
aState.length += (float)CalcLengthOfQuadraticBezier(aState.pos, cp, to);
|
||||
aState.cp1 = cp;
|
||||
aState.cp2 = to;
|
||||
|
@ -373,39 +376,43 @@ TraverseArcAbs(const float* aArgs, SVGPathTraversalState& aState)
|
|||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
float dist = 0;
|
||||
gfxPoint radii(aArgs[0], aArgs[1]);
|
||||
gfxPoint bez[4] = { aState.pos, gfxPoint(0, 0),
|
||||
gfxPoint(0, 0), gfxPoint(0, 0) };
|
||||
nsSVGArcConverter converter(aState.pos, to, radii, aArgs[2],
|
||||
gfxPoint pos = ThebesPoint(aState.pos);
|
||||
gfxPoint bez[4] = { pos, gfxPoint(0, 0), gfxPoint(0, 0), gfxPoint(0, 0) };
|
||||
nsSVGArcConverter converter(pos, to, radii, aArgs[2],
|
||||
aArgs[3] != 0, aArgs[4] != 0);
|
||||
while (converter.GetNextSegment(&bez[1], &bez[2], &bez[3])) {
|
||||
dist += CalcBezLengthHelper(bez, 4, 0, SplitCubicBezier);
|
||||
Point moz2dbez[4] = { ToPoint(bez[0]), ToPoint(bez[1]),
|
||||
ToPoint(bez[2]), ToPoint(bez[3]) };
|
||||
dist += CalcBezLengthHelper(moz2dbez, 4, 0, SplitCubicBezier);
|
||||
bez[0] = bez[3];
|
||||
}
|
||||
aState.length += dist;
|
||||
aState.cp1 = aState.cp2 = to;
|
||||
aState.cp1 = aState.cp2 = ToPoint(to);
|
||||
}
|
||||
aState.pos = to;
|
||||
aState.pos = ToPoint(to);
|
||||
}
|
||||
|
||||
static void
|
||||
TraverseArcRel(const float* aArgs, SVGPathTraversalState& aState)
|
||||
{
|
||||
gfxPoint to = aState.pos + gfxPoint(aArgs[5], aArgs[6]);
|
||||
gfxPoint to = ThebesPoint(aState.pos + Point(aArgs[5], aArgs[6]));
|
||||
if (aState.ShouldUpdateLengthAndControlPoints()) {
|
||||
float dist = 0;
|
||||
gfxPoint radii(aArgs[0], aArgs[1]);
|
||||
gfxPoint bez[4] = { aState.pos, gfxPoint(0, 0),
|
||||
gfxPoint(0, 0), gfxPoint(0, 0) };
|
||||
nsSVGArcConverter converter(aState.pos, to, radii, aArgs[2],
|
||||
gfxPoint pos = ThebesPoint(aState.pos);
|
||||
gfxPoint bez[4] = { pos, gfxPoint(0, 0), gfxPoint(0, 0), gfxPoint(0, 0) };
|
||||
nsSVGArcConverter converter(pos, to, radii, aArgs[2],
|
||||
aArgs[3] != 0, aArgs[4] != 0);
|
||||
while (converter.GetNextSegment(&bez[1], &bez[2], &bez[3])) {
|
||||
dist += CalcBezLengthHelper(bez, 4, 0, SplitCubicBezier);
|
||||
Point moz2dbez[4] = { ToPoint(bez[0]), ToPoint(bez[1]),
|
||||
ToPoint(bez[2]), ToPoint(bez[3]) };
|
||||
dist += CalcBezLengthHelper(moz2dbez, 4, 0, SplitCubicBezier);
|
||||
bez[0] = bez[3];
|
||||
}
|
||||
aState.length += dist;
|
||||
aState.cp1 = aState.cp2 = to;
|
||||
aState.cp1 = aState.cp2 = ToPoint(to);
|
||||
}
|
||||
aState.pos = to;
|
||||
aState.pos = ToPoint(to);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define MOZILLA_SVGPATHSEGUTILS_H__
|
||||
|
||||
#include "gfxPoint.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsMemory.h"
|
||||
|
||||
|
@ -46,6 +47,8 @@ static const unsigned short PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
|
|||
*/
|
||||
struct SVGPathTraversalState
|
||||
{
|
||||
typedef gfx::Point Point;
|
||||
|
||||
enum TraversalMode {
|
||||
eUpdateAll,
|
||||
eUpdateOnlyStartAndCurrentPos
|
||||
|
@ -62,17 +65,17 @@ struct SVGPathTraversalState
|
|||
|
||||
bool ShouldUpdateLengthAndControlPoints() { return mode == eUpdateAll; }
|
||||
|
||||
gfxPoint start; // start point of current sub path (reset each moveto)
|
||||
Point start; // start point of current sub path (reset each moveto)
|
||||
|
||||
gfxPoint pos; // current position (end point of previous segment)
|
||||
Point pos; // current position (end point of previous segment)
|
||||
|
||||
gfxPoint cp1; // quadratic control point - if the previous segment was a
|
||||
// quadratic bezier curve then this is set to the absolute
|
||||
// position of its control point, otherwise its set to pos
|
||||
Point cp1; // quadratic control point - if the previous segment was a
|
||||
// quadratic bezier curve then this is set to the absolute
|
||||
// position of its control point, otherwise its set to pos
|
||||
|
||||
gfxPoint cp2; // cubic control point - if the previous segment was a cubic
|
||||
// bezier curve then this is set to the absolute position of
|
||||
// its second control point, otherwise it's set to pos
|
||||
Point cp2; // cubic control point - if the previous segment was a cubic
|
||||
// bezier curve then this is set to the absolute position of
|
||||
// its second control point, otherwise it's set to pos
|
||||
|
||||
float length; // accumulated path length
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче