Line data Source code
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/. */
6 :
7 : #include "SVGMotionSMILPathUtils.h"
8 :
9 : #include "nsCharSeparatedTokenizer.h"
10 : #include "nsContentUtils.h" // for NS_ENSURE_FINITE2
11 : #include "SVGContentUtils.h"
12 : #include "SVGLength.h"
13 :
14 : using namespace mozilla::gfx;
15 :
16 : namespace mozilla {
17 :
18 : //----------------------------------------------------------------------
19 : // PathGenerator methods
20 :
21 : // For the dummy 'from' value used in pure by-animation & to-animation
22 : void
23 0 : SVGMotionSMILPathUtils::PathGenerator::
24 : MoveToOrigin()
25 : {
26 0 : MOZ_ASSERT(!mHaveReceivedCommands,
27 : "Not expecting requests for mid-path MoveTo commands");
28 0 : mHaveReceivedCommands = true;
29 0 : mPathBuilder->MoveTo(Point(0, 0));
30 0 : }
31 :
32 : // For 'from' and the first entry in 'values'.
33 : bool
34 0 : SVGMotionSMILPathUtils::PathGenerator::
35 : MoveToAbsolute(const nsAString& aCoordPairStr)
36 : {
37 0 : MOZ_ASSERT(!mHaveReceivedCommands,
38 : "Not expecting requests for mid-path MoveTo commands");
39 0 : mHaveReceivedCommands = true;
40 :
41 : float xVal, yVal;
42 0 : if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) {
43 0 : return false;
44 : }
45 0 : mPathBuilder->MoveTo(Point(xVal, yVal));
46 0 : return true;
47 : }
48 :
49 : // For 'to' and every entry in 'values' except the first.
50 : bool
51 0 : SVGMotionSMILPathUtils::PathGenerator::
52 : LineToAbsolute(const nsAString& aCoordPairStr, double& aSegmentDistance)
53 : {
54 0 : mHaveReceivedCommands = true;
55 :
56 : float xVal, yVal;
57 0 : if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) {
58 0 : return false;
59 : }
60 0 : Point initialPoint = mPathBuilder->CurrentPoint();
61 :
62 0 : mPathBuilder->LineTo(Point(xVal, yVal));
63 0 : aSegmentDistance = NS_hypot(initialPoint.x - xVal, initialPoint.y -yVal);
64 0 : return true;
65 : }
66 :
67 : // For 'by'.
68 : bool
69 0 : SVGMotionSMILPathUtils::PathGenerator::
70 : LineToRelative(const nsAString& aCoordPairStr, double& aSegmentDistance)
71 : {
72 0 : mHaveReceivedCommands = true;
73 :
74 : float xVal, yVal;
75 0 : if (!ParseCoordinatePair(aCoordPairStr, xVal, yVal)) {
76 0 : return false;
77 : }
78 0 : mPathBuilder->LineTo(mPathBuilder->CurrentPoint() + Point(xVal, yVal));
79 0 : aSegmentDistance = NS_hypot(xVal, yVal);
80 0 : return true;
81 : }
82 :
83 : already_AddRefed<Path>
84 0 : SVGMotionSMILPathUtils::PathGenerator::GetResultingPath()
85 : {
86 0 : return mPathBuilder->Finish();
87 : }
88 :
89 : //----------------------------------------------------------------------
90 : // Helper / protected methods
91 :
92 : bool
93 0 : SVGMotionSMILPathUtils::PathGenerator::
94 : ParseCoordinatePair(const nsAString& aCoordPairStr,
95 : float& aXVal, float& aYVal)
96 : {
97 : nsCharSeparatedTokenizerTemplate<IsSVGWhitespace>
98 : tokenizer(aCoordPairStr, ',',
99 0 : nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
100 :
101 0 : SVGLength x, y;
102 :
103 0 : if (!tokenizer.hasMoreTokens() ||
104 0 : !x.SetValueFromString(tokenizer.nextToken())) {
105 0 : return false;
106 : }
107 :
108 0 : if (!tokenizer.hasMoreTokens() ||
109 0 : !y.SetValueFromString(tokenizer.nextToken())) {
110 0 : return false;
111 : }
112 :
113 0 : if (tokenizer.separatorAfterCurrentToken() || // Trailing comma.
114 0 : tokenizer.hasMoreTokens()) { // More text remains
115 0 : return false;
116 : }
117 :
118 0 : float xRes = x.GetValueInUserUnits(mSVGElement, SVGContentUtils::X);
119 0 : float yRes = y.GetValueInUserUnits(mSVGElement, SVGContentUtils::Y);
120 :
121 0 : NS_ENSURE_FINITE2(xRes, yRes, false);
122 :
123 0 : aXVal = xRes;
124 0 : aYVal = yRes;
125 0 : return true;
126 : }
127 :
128 : //----------------------------------------------------------------------
129 : // MotionValueParser methods
130 : bool
131 0 : SVGMotionSMILPathUtils::MotionValueParser::
132 : Parse(const nsAString& aValueStr)
133 : {
134 : bool success;
135 0 : if (!mPathGenerator->HaveReceivedCommands()) {
136 : // Interpret first value in "values" attribute as the path's initial MoveTo
137 0 : success = mPathGenerator->MoveToAbsolute(aValueStr);
138 0 : if (success) {
139 0 : success = !!mPointDistances->AppendElement(0.0, fallible);
140 : }
141 : } else {
142 : double dist;
143 0 : success = mPathGenerator->LineToAbsolute(aValueStr, dist);
144 0 : if (success) {
145 0 : mDistanceSoFar += dist;
146 0 : success = !!mPointDistances->AppendElement(mDistanceSoFar, fallible);
147 : }
148 : }
149 0 : return success;
150 : }
151 :
152 : } // namespace mozilla
|