1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "SVGMotionSMILPathUtils.h"
9 #include "nsCharSeparatedTokenizer.h"
10 #include "nsContentUtils.h" // for NS_ENSURE_FINITE2
11 #include "SVGContentUtils.h"
12 #include "SVGLength.h"
14 using namespace mozilla::gfx
;
18 //----------------------------------------------------------------------
19 // PathGenerator methods
21 // For the dummy 'from' value used in pure by-animation & to-animation
22 void SVGMotionSMILPathUtils::PathGenerator::MoveToOrigin() {
23 MOZ_ASSERT(!mHaveReceivedCommands
,
24 "Not expecting requests for mid-path MoveTo commands");
25 mHaveReceivedCommands
= true;
26 mPathBuilder
->MoveTo(Point(0, 0));
29 // For 'from' and the first entry in 'values'.
30 bool SVGMotionSMILPathUtils::PathGenerator::MoveToAbsolute(
31 const nsAString
& aCoordPairStr
) {
32 MOZ_ASSERT(!mHaveReceivedCommands
,
33 "Not expecting requests for mid-path MoveTo commands");
34 mHaveReceivedCommands
= true;
37 if (!ParseCoordinatePair(aCoordPairStr
, xVal
, yVal
)) {
40 mPathBuilder
->MoveTo(Point(xVal
, yVal
));
44 // For 'to' and every entry in 'values' except the first.
45 bool SVGMotionSMILPathUtils::PathGenerator::LineToAbsolute(
46 const nsAString
& aCoordPairStr
, double& aSegmentDistance
) {
47 mHaveReceivedCommands
= true;
50 if (!ParseCoordinatePair(aCoordPairStr
, xVal
, yVal
)) {
53 Point initialPoint
= mPathBuilder
->CurrentPoint();
55 mPathBuilder
->LineTo(Point(xVal
, yVal
));
56 aSegmentDistance
= NS_hypot(initialPoint
.x
- xVal
, initialPoint
.y
- yVal
);
61 bool SVGMotionSMILPathUtils::PathGenerator::LineToRelative(
62 const nsAString
& aCoordPairStr
, double& aSegmentDistance
) {
63 mHaveReceivedCommands
= true;
66 if (!ParseCoordinatePair(aCoordPairStr
, xVal
, yVal
)) {
69 mPathBuilder
->LineTo(mPathBuilder
->CurrentPoint() + Point(xVal
, yVal
));
70 aSegmentDistance
= NS_hypot(xVal
, yVal
);
74 already_AddRefed
<Path
>
75 SVGMotionSMILPathUtils::PathGenerator::GetResultingPath() {
76 return mPathBuilder
->Finish();
79 //----------------------------------------------------------------------
80 // Helper / protected methods
82 bool SVGMotionSMILPathUtils::PathGenerator::ParseCoordinatePair(
83 const nsAString
& aCoordPairStr
, float& aXVal
, float& aYVal
) {
84 nsCharSeparatedTokenizerTemplate
<nsContentUtils::IsHTMLWhitespace
,
85 nsTokenizerFlags::SeparatorOptional
>
86 tokenizer(aCoordPairStr
, ',');
90 if (!tokenizer
.hasMoreTokens() ||
91 !x
.SetValueFromString(tokenizer
.nextToken())) {
95 if (!tokenizer
.hasMoreTokens() ||
96 !y
.SetValueFromString(tokenizer
.nextToken())) {
100 if (tokenizer
.separatorAfterCurrentToken() || // Trailing comma.
101 tokenizer
.hasMoreTokens()) { // More text remains
105 float xRes
= x
.GetValueInPixels(mSVGElement
, SVGContentUtils::X
);
106 float yRes
= y
.GetValueInPixels(mSVGElement
, SVGContentUtils::Y
);
108 NS_ENSURE_FINITE2(xRes
, yRes
, false);
115 //----------------------------------------------------------------------
116 // MotionValueParser methods
117 bool SVGMotionSMILPathUtils::MotionValueParser::Parse(
118 const nsAString
& aValueStr
) {
120 if (!mPathGenerator
->HaveReceivedCommands()) {
121 // Interpret first value in "values" attribute as the path's initial MoveTo
122 success
= mPathGenerator
->MoveToAbsolute(aValueStr
);
124 success
= !!mPointDistances
->AppendElement(0.0, fallible
);
128 success
= mPathGenerator
->LineToAbsolute(aValueStr
, dist
);
130 mDistanceSoFar
+= dist
;
131 success
= !!mPointDistances
->AppendElement(mDistanceSoFar
, fallible
);
137 } // namespace mozilla