Bug 1444460 [wpt PR 9948] - gyroscope: Rename LocalCoordinateSystem to GyroscopeLocal...
[gecko.git] / dom / svg / SVGTransformListParser.cpp
blobca04003036513782e7283d1b3c1eac7491db2baf
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 "mozilla/ArrayUtils.h"
9 #include "SVGTransformListParser.h"
10 #include "SVGContentUtils.h"
11 #include "nsSVGTransform.h"
12 #include "nsGkAtoms.h"
13 #include "nsAtom.h"
15 using namespace mozilla;
17 //----------------------------------------------------------------------
18 // private methods
20 bool
21 SVGTransformListParser::Parse()
23 mTransforms.Clear();
24 return ParseTransforms();
27 bool
28 SVGTransformListParser::ParseTransforms()
30 if (!SkipWsp()) {
31 return true;
34 if (!ParseTransform()) {
35 return false;
38 while (SkipWsp()) {
39 // The SVG BNF allows multiple comma-wsp between transforms
40 while (*mIter == ',') {
41 ++mIter;
42 if (!SkipWsp()) {
43 return false;
47 if (!ParseTransform()) {
48 return false;
51 return true;
54 bool
55 SVGTransformListParser::ParseTransform()
57 RangedPtr<const char16_t> start(mIter);
58 while (IsAlpha(*mIter)) {
59 ++mIter;
60 if (mIter == mEnd) {
61 return false;
65 if (start == mIter) {
66 // Didn't read anything
67 return false;
70 const nsAString& transform = Substring(start.get(), mIter.get());
71 nsStaticAtom* keyAtom = NS_GetStaticAtom(transform);
73 if (!keyAtom || !SkipWsp()) {
74 return false;
77 if (keyAtom == nsGkAtoms::translate) {
78 return ParseTranslate();
80 if (keyAtom == nsGkAtoms::scale) {
81 return ParseScale();
83 if (keyAtom == nsGkAtoms::rotate) {
84 return ParseRotate();
86 if (keyAtom == nsGkAtoms::skewX) {
87 return ParseSkewX();
89 if (keyAtom == nsGkAtoms::skewY) {
90 return ParseSkewY();
92 if (keyAtom == nsGkAtoms::matrix) {
93 return ParseMatrix();
95 return false;
98 bool
99 SVGTransformListParser::ParseArguments(float* aResult,
100 uint32_t aMaxCount,
101 uint32_t* aParsedCount)
103 if (*mIter != '(') {
104 return false;
106 ++mIter;
108 if (!SkipWsp()) {
109 return false;
112 if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[0])) {
113 return false;
115 *aParsedCount = 1;
117 while (true) {
118 RangedPtr<const char16_t> iter(mIter);
119 if (!SkipWsp()) {
120 return false;
122 if (*mIter == ')') {
123 ++mIter;
124 return true;
126 if (*aParsedCount == aMaxCount) {
127 return false;
129 SkipCommaWsp();
130 if (iter == mIter) {
131 // There must be either whitespace or a comma between values
132 return false;
134 if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[(*aParsedCount)++])) {
135 return false;
138 return false;
141 bool
142 SVGTransformListParser::ParseTranslate()
144 float t[2];
145 uint32_t count;
147 if (!ParseArguments(t, ArrayLength(t), &count)) {
148 return false;
151 switch (count) {
152 case 1:
153 t[1] = 0.f;
154 MOZ_FALLTHROUGH;
155 case 2:
157 nsSVGTransform* transform = mTransforms.AppendElement(fallible);
158 if (!transform) {
159 return false;
161 transform->SetTranslate(t[0], t[1]);
162 return true;
166 return false;
169 bool
170 SVGTransformListParser::ParseScale()
172 float s[2];
173 uint32_t count;
175 if (!ParseArguments(s, ArrayLength(s), &count)) {
176 return false;
179 switch (count) {
180 case 1:
181 s[1] = s[0];
182 MOZ_FALLTHROUGH;
183 case 2:
185 nsSVGTransform* transform = mTransforms.AppendElement(fallible);
186 if (!transform) {
187 return false;
189 transform->SetScale(s[0], s[1]);
190 return true;
194 return false;
198 bool
199 SVGTransformListParser::ParseRotate()
201 float r[3];
202 uint32_t count;
204 if (!ParseArguments(r, ArrayLength(r), &count)) {
205 return false;
208 switch (count) {
209 case 1:
210 r[1] = r[2] = 0.f;
211 MOZ_FALLTHROUGH;
212 case 3:
214 nsSVGTransform* transform = mTransforms.AppendElement(fallible);
215 if (!transform) {
216 return false;
218 transform->SetRotate(r[0], r[1], r[2]);
219 return true;
223 return false;
226 bool
227 SVGTransformListParser::ParseSkewX()
229 float skew;
230 uint32_t count;
232 if (!ParseArguments(&skew, 1, &count) || count != 1) {
233 return false;
236 nsSVGTransform* transform = mTransforms.AppendElement(fallible);
237 if (!transform) {
238 return false;
240 transform->SetSkewX(skew);
242 return true;
245 bool
246 SVGTransformListParser::ParseSkewY()
248 float skew;
249 uint32_t count;
251 if (!ParseArguments(&skew, 1, &count) || count != 1) {
252 return false;
255 nsSVGTransform* transform = mTransforms.AppendElement(fallible);
256 if (!transform) {
257 return false;
259 transform->SetSkewY(skew);
261 return true;
264 bool
265 SVGTransformListParser::ParseMatrix()
267 float m[6];
268 uint32_t count;
270 if (!ParseArguments(m, ArrayLength(m), &count) || count != 6) {
271 return false;
274 nsSVGTransform* transform = mTransforms.AppendElement(fallible);
275 if (!transform) {
276 return false;
278 transform->SetMatrix(gfxMatrix(m[0], m[1], m[2], m[3], m[4], m[5]));
280 return true;