Bug 1881621 - Add colors/color_canvas.html tests to dom/canvas/test/reftest. r=bradwerth
[gecko.git] / dom / svg / SVGTransformListParser.cpp
blob227139fe0197cf15d089cb1e5a25348adf34435f
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 "SVGTransformListParser.h"
9 #include "mozilla/ArrayUtils.h"
10 #include "SVGContentUtils.h"
11 #include "SVGTransform.h"
12 #include "nsGkAtoms.h"
13 #include "nsAtom.h"
15 namespace mozilla {
17 //----------------------------------------------------------------------
18 // private methods
20 bool SVGTransformListParser::Parse() {
21 mTransforms.Clear();
22 return ParseTransforms();
25 bool SVGTransformListParser::ParseTransforms() {
26 if (!SkipWsp()) {
27 return true;
30 if (!ParseTransform()) {
31 return false;
34 while (SkipWsp()) {
35 // The SVG BNF allows multiple comma-wsp between transforms
36 while (*mIter == ',') {
37 ++mIter;
38 if (!SkipWsp()) {
39 return false;
43 if (!ParseTransform()) {
44 return false;
47 return true;
50 bool SVGTransformListParser::ParseTransform() {
51 RangedPtr<const char16_t> start(mIter);
52 while (IsAsciiAlpha(*mIter)) {
53 ++mIter;
54 if (mIter == mEnd) {
55 return false;
59 if (start == mIter) {
60 // Didn't read anything
61 return false;
64 const nsAString& transform = Substring(start.get(), mIter.get());
65 nsStaticAtom* keyAtom = NS_GetStaticAtom(transform);
67 if (!keyAtom || !SkipWsp()) {
68 return false;
71 if (keyAtom == nsGkAtoms::translate) {
72 return ParseTranslate();
74 if (keyAtom == nsGkAtoms::scale) {
75 return ParseScale();
77 if (keyAtom == nsGkAtoms::rotate) {
78 return ParseRotate();
80 if (keyAtom == nsGkAtoms::skewX) {
81 return ParseSkewX();
83 if (keyAtom == nsGkAtoms::skewY) {
84 return ParseSkewY();
86 if (keyAtom == nsGkAtoms::matrix) {
87 return ParseMatrix();
89 return false;
92 bool SVGTransformListParser::ParseArguments(float* aResult, uint32_t aMaxCount,
93 uint32_t* aParsedCount) {
94 if (*mIter != '(') {
95 return false;
97 ++mIter;
99 if (!SkipWsp()) {
100 return false;
103 if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[0])) {
104 return false;
106 *aParsedCount = 1;
108 while (SkipWsp()) {
109 if (*mIter == ')') {
110 ++mIter;
111 return true;
113 if (*aParsedCount == aMaxCount) {
114 return false;
116 SkipCommaWsp();
117 if (!SVGContentUtils::ParseNumber(mIter, mEnd,
118 aResult[(*aParsedCount)++])) {
119 return false;
122 return false;
125 bool SVGTransformListParser::ParseTranslate() {
126 float t[2];
127 uint32_t count;
129 if (!ParseArguments(t, ArrayLength(t), &count)) {
130 return false;
133 switch (count) {
134 case 1:
135 t[1] = 0.f;
136 [[fallthrough]];
137 case 2: {
138 SVGTransform* transform = mTransforms.AppendElement(fallible);
139 if (!transform) {
140 return false;
142 transform->SetTranslate(t[0], t[1]);
143 return true;
147 return false;
150 bool SVGTransformListParser::ParseScale() {
151 float s[2];
152 uint32_t count;
154 if (!ParseArguments(s, ArrayLength(s), &count)) {
155 return false;
158 switch (count) {
159 case 1:
160 s[1] = s[0];
161 [[fallthrough]];
162 case 2: {
163 SVGTransform* transform = mTransforms.AppendElement(fallible);
164 if (!transform) {
165 return false;
167 transform->SetScale(s[0], s[1]);
168 return true;
172 return false;
175 bool SVGTransformListParser::ParseRotate() {
176 float r[3];
177 uint32_t count;
179 if (!ParseArguments(r, ArrayLength(r), &count)) {
180 return false;
183 switch (count) {
184 case 1:
185 r[1] = r[2] = 0.f;
186 [[fallthrough]];
187 case 3: {
188 SVGTransform* transform = mTransforms.AppendElement(fallible);
189 if (!transform) {
190 return false;
192 transform->SetRotate(r[0], r[1], r[2]);
193 return true;
197 return false;
200 bool SVGTransformListParser::ParseSkewX() {
201 float skew;
202 uint32_t count;
204 if (!ParseArguments(&skew, 1, &count) || count != 1) {
205 return false;
208 SVGTransform* transform = mTransforms.AppendElement(fallible);
209 if (!transform) {
210 return false;
212 transform->SetSkewX(skew);
214 return true;
217 bool SVGTransformListParser::ParseSkewY() {
218 float skew;
219 uint32_t count;
221 if (!ParseArguments(&skew, 1, &count) || count != 1) {
222 return false;
225 SVGTransform* transform = mTransforms.AppendElement(fallible);
226 if (!transform) {
227 return false;
229 transform->SetSkewY(skew);
231 return true;
234 bool SVGTransformListParser::ParseMatrix() {
235 float m[6];
236 uint32_t count;
238 if (!ParseArguments(m, ArrayLength(m), &count) || count != 6) {
239 return false;
242 SVGTransform* transform = mTransforms.AppendElement(fallible);
243 if (!transform) {
244 return false;
246 transform->SetMatrix(gfxMatrix(m[0], m[1], m[2], m[3], m[4], m[5]));
248 return true;
251 } // namespace mozilla