Bug 570258: Some more atom usage cleanup. r=jst
[mozilla-central.git] / content / svg / content / src / nsSVGTransformListParser.cpp
blobf77f0a4aa6d3f5c553c70e0175746224268386a9
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is the Mozilla SVG project.
17 * The Initial Developer of the Original Code is
18 * IBM Corporation
19 * Portions created by the Initial Developer are Copyright (C) 2006
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsSVGTransformListParser.h"
39 #include "prdtoa.h"
40 #include "nsSVGTransform.h"
41 #include "nsSVGMatrix.h"
42 #include "nsDOMError.h"
43 #include "nsGkAtoms.h"
44 #include "nsReadableUtils.h"
45 #include "nsCRT.h"
46 #include "nsCOMArray.h"
47 #include "nsContentUtils.h"
48 #include "nsIDOMClassInfo.h"
50 //----------------------------------------------------------------------
51 // public interface
53 nsSVGTransformListParser::nsSVGTransformListParser(nsCOMArray<nsIDOMSVGTransform>* aTransforms)
54 : mTransform(aTransforms)
58 //----------------------------------------------------------------------
59 // private methods
61 nsresult
62 nsSVGTransformListParser::Match()
64 return MatchTransformList();
68 nsresult
69 nsSVGTransformListParser::MatchTransformList()
71 MatchWsp();
73 if (IsTokenTransformStarter()) {
74 ENSURE_MATCHED(MatchTransforms());
77 MatchWsp();
79 return NS_OK;
83 nsresult
84 nsSVGTransformListParser::MatchTransforms()
86 ENSURE_MATCHED(MatchTransform());
88 while (mTokenType != END) {
89 const char* pos = mTokenPos;
91 /* Curiously the SVG BNF allows multiple comma-wsp between transforms */
92 while (IsTokenCommaWspStarter()) {
93 ENSURE_MATCHED(MatchCommaWsp());
96 if (IsTokenTransformStarter()) {
97 ENSURE_MATCHED(MatchTransform());
98 } else {
99 if (pos != mTokenPos) RewindTo(pos);
100 break;
104 return NS_OK;
108 nsresult
109 nsSVGTransformListParser::GetTransformToken(nsIAtom** aKeyAtom,
110 PRBool aAdvancePos)
112 if (mTokenType != OTHER || *mTokenPos == '\0') {
113 return NS_ERROR_FAILURE;
116 nsresult rv = NS_OK;
118 const char* delimiters = "\x20\x9\xD\xA,(";
119 char* delimiterStart = PL_strnpbrk(mTokenPos, delimiters, 11);
120 if (delimiterStart != 0) {
121 /* save this character and null it out */
122 char holdingChar = *delimiterStart;
123 *delimiterStart = '\0';
125 PRUint32 len;
126 if (mTokenPos != 0 && (len = nsCRT::strlen(mTokenPos)) > 0) {
127 *aKeyAtom = NS_NewAtom(Substring(mTokenPos, mTokenPos + len));
129 if (aAdvancePos) {
130 mInputPos = mTokenPos + len;
131 mTokenPos = mInputPos;
133 } else {
134 rv = NS_ERROR_FAILURE;
136 /* reset character back to original */
137 *delimiterStart = holdingChar;
138 } else {
139 rv = NS_ERROR_FAILURE;
142 return rv;
146 nsresult
147 nsSVGTransformListParser::MatchTransform()
149 nsCOMPtr<nsIAtom> keyatom;
151 nsresult rv = GetTransformToken(getter_AddRefs(keyatom), PR_TRUE);
152 if (NS_FAILED(rv)) {
153 return rv;
156 if (keyatom == nsGkAtoms::translate) {
157 ENSURE_MATCHED(MatchTranslate());
158 } else if (keyatom == nsGkAtoms::scale) {
159 ENSURE_MATCHED(MatchScale());
160 } else if (keyatom == nsGkAtoms::rotate) {
161 ENSURE_MATCHED(MatchRotate());
162 } else if (keyatom == nsGkAtoms::skewX) {
163 ENSURE_MATCHED(MatchSkewX());
164 } else if (keyatom == nsGkAtoms::skewY) {
165 ENSURE_MATCHED(MatchSkewY());
166 } else if (keyatom == nsGkAtoms::matrix) {
167 ENSURE_MATCHED(MatchMatrix());
168 } else {
169 return NS_ERROR_FAILURE;
172 return NS_OK;
176 PRBool
177 nsSVGTransformListParser::IsTokenTransformStarter()
179 nsCOMPtr<nsIAtom> keyatom;
181 nsresult rv = GetTransformToken(getter_AddRefs(keyatom), PR_FALSE);
182 if (NS_FAILED(rv)) {
183 return PR_FALSE;
186 if (keyatom == nsGkAtoms::translate ||
187 keyatom == nsGkAtoms::scale ||
188 keyatom == nsGkAtoms::rotate ||
189 keyatom == nsGkAtoms::skewX ||
190 keyatom == nsGkAtoms::skewY ||
191 keyatom == nsGkAtoms::matrix) {
192 return PR_TRUE;
195 return PR_FALSE;
198 nsresult
199 nsSVGTransformListParser::MatchNumberArguments(float *aResult,
200 PRUint32 aMaxNum,
201 PRUint32 *aParsedNum)
203 *aParsedNum = 0;
205 MatchWsp();
207 ENSURE_MATCHED(MatchLeftParen());
209 MatchWsp();
211 ENSURE_MATCHED(MatchNumber(&aResult[0]));
212 *aParsedNum = 1;
214 while (IsTokenCommaWspStarter()) {
215 MatchWsp();
216 if (mTokenType == RIGHT_PAREN) {
217 break;
219 if (*aParsedNum == aMaxNum) {
220 return NS_ERROR_FAILURE;
222 if (IsTokenCommaWspStarter()) {
223 MatchCommaWsp();
225 ENSURE_MATCHED(MatchNumber(&aResult[(*aParsedNum)++]));
228 MatchWsp();
230 ENSURE_MATCHED(MatchRightParen());
232 return NS_OK;
235 nsIDOMSVGTransform *
236 nsSVGTransformListParser::AppendTransform()
238 nsCOMPtr<nsIDOMSVGTransform> transform;
239 NS_NewSVGTransform(getter_AddRefs(transform));
240 if (transform) {
241 mTransform->AppendObject(transform);
243 return transform;
246 nsresult
247 nsSVGTransformListParser::MatchTranslate()
249 GetNextToken();
251 float t[2];
252 PRUint32 count;
254 ENSURE_MATCHED(MatchNumberArguments(t, NS_ARRAY_LENGTH(t), &count));
256 switch (count) {
257 case 1:
258 t[1] = 0.f;
259 // fall-through
260 case 2:
262 nsIDOMSVGTransform *transform = AppendTransform();
263 NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
264 transform->SetTranslate(t[0], t[1]);
265 break;
267 default:
268 return NS_ERROR_FAILURE;
271 return NS_OK;
275 nsresult
276 nsSVGTransformListParser::MatchScale()
278 GetNextToken();
280 float s[2];
281 PRUint32 count;
283 ENSURE_MATCHED(MatchNumberArguments(s, NS_ARRAY_LENGTH(s), &count));
285 switch (count) {
286 case 1:
287 s[1] = s[0];
288 // fall-through
289 case 2:
291 nsIDOMSVGTransform *transform = AppendTransform();
292 NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
293 transform->SetScale(s[0], s[1]);
294 break;
296 default:
297 return NS_ERROR_FAILURE;
300 return NS_OK;
304 nsresult
305 nsSVGTransformListParser::MatchRotate()
307 GetNextToken();
309 float r[3];
310 PRUint32 count;
312 ENSURE_MATCHED(MatchNumberArguments(r, NS_ARRAY_LENGTH(r), &count));
314 switch (count) {
315 case 1:
316 r[1] = r[2] = 0.f;
317 // fall-through
318 case 3:
320 nsIDOMSVGTransform *transform = AppendTransform();
321 NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
322 transform->SetRotate(r[0], r[1], r[2]);
323 break;
325 default:
326 return NS_ERROR_FAILURE;
329 return NS_OK;
333 nsresult
334 nsSVGTransformListParser::MatchSkewX()
336 GetNextToken();
338 float skew;
339 PRUint32 count;
341 ENSURE_MATCHED(MatchNumberArguments(&skew, 1, &count));
343 if (count != 1) {
344 return NS_ERROR_FAILURE;
347 nsIDOMSVGTransform *transform = AppendTransform();
348 NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
349 transform->SetSkewX(skew);
351 return NS_OK;
355 nsresult
356 nsSVGTransformListParser::MatchSkewY()
358 GetNextToken();
360 float skew;
361 PRUint32 count;
363 ENSURE_MATCHED(MatchNumberArguments(&skew, 1, &count));
365 if (count != 1) {
366 return NS_ERROR_FAILURE;
369 nsIDOMSVGTransform *transform = AppendTransform();
370 NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
371 transform->SetSkewY(skew);
373 return NS_OK;
377 nsresult
378 nsSVGTransformListParser::MatchMatrix()
380 GetNextToken();
382 float m[6];
383 PRUint32 count;
385 ENSURE_MATCHED(MatchNumberArguments(m, NS_ARRAY_LENGTH(m), &count));
387 if (count != 6) {
388 return NS_ERROR_FAILURE;
391 nsCOMPtr<nsIDOMSVGMatrix> matrix;
392 NS_NewSVGMatrix(getter_AddRefs(matrix),
393 m[0], m[1], m[2], m[3], m[4], m[5]);
394 NS_ENSURE_TRUE(matrix, NS_ERROR_OUT_OF_MEMORY);
396 nsIDOMSVGTransform *transform = AppendTransform();
397 NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
398 transform->SetMatrix(matrix);
400 return NS_OK;