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
15 * The Original Code is the Mozilla SVG project.
17 * The Initial Developer of the Original Code is
19 * Portions created by the Initial Developer are Copyright (C) 2006
20 * the Initial Developer. All Rights Reserved.
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"
40 #include "nsSVGTransform.h"
41 #include "nsSVGMatrix.h"
42 #include "nsDOMError.h"
43 #include "nsGkAtoms.h"
44 #include "nsReadableUtils.h"
46 #include "nsCOMArray.h"
47 #include "nsContentUtils.h"
48 #include "nsIDOMClassInfo.h"
50 //----------------------------------------------------------------------
53 nsSVGTransformListParser::nsSVGTransformListParser(nsCOMArray
<nsIDOMSVGTransform
>* aTransforms
)
54 : mTransform(aTransforms
)
58 //----------------------------------------------------------------------
62 nsSVGTransformListParser::Match()
64 return MatchTransformList();
69 nsSVGTransformListParser::MatchTransformList()
73 if (IsTokenTransformStarter()) {
74 ENSURE_MATCHED(MatchTransforms());
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());
99 if (pos
!= mTokenPos
) RewindTo(pos
);
109 nsSVGTransformListParser::GetTransformToken(nsIAtom
** aKeyAtom
,
112 if (mTokenType
!= OTHER
|| *mTokenPos
== '\0') {
113 return NS_ERROR_FAILURE
;
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';
126 if (mTokenPos
!= 0 && (len
= nsCRT::strlen(mTokenPos
)) > 0) {
127 *aKeyAtom
= NS_NewAtom(Substring(mTokenPos
, mTokenPos
+ len
));
130 mInputPos
= mTokenPos
+ len
;
131 mTokenPos
= mInputPos
;
134 rv
= NS_ERROR_FAILURE
;
136 /* reset character back to original */
137 *delimiterStart
= holdingChar
;
139 rv
= NS_ERROR_FAILURE
;
147 nsSVGTransformListParser::MatchTransform()
149 nsCOMPtr
<nsIAtom
> keyatom
;
151 nsresult rv
= GetTransformToken(getter_AddRefs(keyatom
), PR_TRUE
);
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());
169 return NS_ERROR_FAILURE
;
177 nsSVGTransformListParser::IsTokenTransformStarter()
179 nsCOMPtr
<nsIAtom
> keyatom
;
181 nsresult rv
= GetTransformToken(getter_AddRefs(keyatom
), 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
) {
199 nsSVGTransformListParser::MatchNumberArguments(float *aResult
,
201 PRUint32
*aParsedNum
)
207 ENSURE_MATCHED(MatchLeftParen());
211 ENSURE_MATCHED(MatchNumber(&aResult
[0]));
214 while (IsTokenCommaWspStarter()) {
216 if (mTokenType
== RIGHT_PAREN
) {
219 if (*aParsedNum
== aMaxNum
) {
220 return NS_ERROR_FAILURE
;
222 if (IsTokenCommaWspStarter()) {
225 ENSURE_MATCHED(MatchNumber(&aResult
[(*aParsedNum
)++]));
230 ENSURE_MATCHED(MatchRightParen());
236 nsSVGTransformListParser::AppendTransform()
238 nsCOMPtr
<nsIDOMSVGTransform
> transform
;
239 NS_NewSVGTransform(getter_AddRefs(transform
));
241 mTransform
->AppendObject(transform
);
247 nsSVGTransformListParser::MatchTranslate()
254 ENSURE_MATCHED(MatchNumberArguments(t
, NS_ARRAY_LENGTH(t
), &count
));
262 nsIDOMSVGTransform
*transform
= AppendTransform();
263 NS_ENSURE_TRUE(transform
, NS_ERROR_OUT_OF_MEMORY
);
264 transform
->SetTranslate(t
[0], t
[1]);
268 return NS_ERROR_FAILURE
;
276 nsSVGTransformListParser::MatchScale()
283 ENSURE_MATCHED(MatchNumberArguments(s
, NS_ARRAY_LENGTH(s
), &count
));
291 nsIDOMSVGTransform
*transform
= AppendTransform();
292 NS_ENSURE_TRUE(transform
, NS_ERROR_OUT_OF_MEMORY
);
293 transform
->SetScale(s
[0], s
[1]);
297 return NS_ERROR_FAILURE
;
305 nsSVGTransformListParser::MatchRotate()
312 ENSURE_MATCHED(MatchNumberArguments(r
, NS_ARRAY_LENGTH(r
), &count
));
320 nsIDOMSVGTransform
*transform
= AppendTransform();
321 NS_ENSURE_TRUE(transform
, NS_ERROR_OUT_OF_MEMORY
);
322 transform
->SetRotate(r
[0], r
[1], r
[2]);
326 return NS_ERROR_FAILURE
;
334 nsSVGTransformListParser::MatchSkewX()
341 ENSURE_MATCHED(MatchNumberArguments(&skew
, 1, &count
));
344 return NS_ERROR_FAILURE
;
347 nsIDOMSVGTransform
*transform
= AppendTransform();
348 NS_ENSURE_TRUE(transform
, NS_ERROR_OUT_OF_MEMORY
);
349 transform
->SetSkewX(skew
);
356 nsSVGTransformListParser::MatchSkewY()
363 ENSURE_MATCHED(MatchNumberArguments(&skew
, 1, &count
));
366 return NS_ERROR_FAILURE
;
369 nsIDOMSVGTransform
*transform
= AppendTransform();
370 NS_ENSURE_TRUE(transform
, NS_ERROR_OUT_OF_MEMORY
);
371 transform
->SetSkewY(skew
);
378 nsSVGTransformListParser::MatchMatrix()
385 ENSURE_MATCHED(MatchNumberArguments(m
, NS_ARRAY_LENGTH(m
), &count
));
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
);