SVGTransformListParser.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/ArrayUtils.h"
  6. #include "SVGTransformListParser.h"
  7. #include "SVGContentUtils.h"
  8. #include "nsSVGTransform.h"
  9. #include "nsGkAtoms.h"
  10. #include "nsIAtom.h"
  11. using namespace mozilla;
  12. //----------------------------------------------------------------------
  13. // private methods
  14. bool
  15. SVGTransformListParser::Parse()
  16. {
  17. mTransforms.Clear();
  18. return ParseTransforms();
  19. }
  20. bool
  21. SVGTransformListParser::ParseTransforms()
  22. {
  23. if (!SkipWsp()) {
  24. return true;
  25. }
  26. if (!ParseTransform()) {
  27. return false;
  28. }
  29. while (SkipWsp()) {
  30. // The SVG BNF allows multiple comma-wsp between transforms
  31. while (*mIter == ',') {
  32. ++mIter;
  33. if (!SkipWsp()) {
  34. return false;
  35. }
  36. }
  37. if (!ParseTransform()) {
  38. return false;
  39. }
  40. }
  41. return true;
  42. }
  43. bool
  44. SVGTransformListParser::ParseTransform()
  45. {
  46. RangedPtr<const char16_t> start(mIter);
  47. while (IsAlpha(*mIter)) {
  48. ++mIter;
  49. if (mIter == mEnd) {
  50. return false;
  51. }
  52. }
  53. if (start == mIter) {
  54. // Didn't read anything
  55. return false;
  56. }
  57. const nsAString& transform = Substring(start.get(), mIter.get());
  58. nsIAtom* keyAtom = NS_GetStaticAtom(transform);
  59. if (!keyAtom || !SkipWsp()) {
  60. return false;
  61. }
  62. if (keyAtom == nsGkAtoms::translate) {
  63. return ParseTranslate();
  64. }
  65. if (keyAtom == nsGkAtoms::scale) {
  66. return ParseScale();
  67. }
  68. if (keyAtom == nsGkAtoms::rotate) {
  69. return ParseRotate();
  70. }
  71. if (keyAtom == nsGkAtoms::skewX) {
  72. return ParseSkewX();
  73. }
  74. if (keyAtom == nsGkAtoms::skewY) {
  75. return ParseSkewY();
  76. }
  77. if (keyAtom == nsGkAtoms::matrix) {
  78. return ParseMatrix();
  79. }
  80. return false;
  81. }
  82. bool
  83. SVGTransformListParser::ParseArguments(float* aResult,
  84. uint32_t aMaxCount,
  85. uint32_t* aParsedCount)
  86. {
  87. if (*mIter != '(') {
  88. return false;
  89. }
  90. ++mIter;
  91. if (!SkipWsp()) {
  92. return false;
  93. }
  94. if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[0])) {
  95. return false;
  96. }
  97. *aParsedCount = 1;
  98. while (SkipWsp()) {
  99. if (*mIter == ')') {
  100. ++mIter;
  101. return true;
  102. }
  103. if (*aParsedCount == aMaxCount) {
  104. return false;
  105. }
  106. SkipCommaWsp();
  107. if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[(*aParsedCount)++])) {
  108. return false;
  109. }
  110. }
  111. return false;
  112. }
  113. bool
  114. SVGTransformListParser::ParseTranslate()
  115. {
  116. float t[2];
  117. uint32_t count;
  118. if (!ParseArguments(t, ArrayLength(t), &count)) {
  119. return false;
  120. }
  121. switch (count) {
  122. case 1:
  123. t[1] = 0.f;
  124. MOZ_FALLTHROUGH;
  125. case 2:
  126. {
  127. nsSVGTransform* transform = mTransforms.AppendElement(fallible);
  128. if (!transform) {
  129. return false;
  130. }
  131. transform->SetTranslate(t[0], t[1]);
  132. return true;
  133. }
  134. }
  135. return false;
  136. }
  137. bool
  138. SVGTransformListParser::ParseScale()
  139. {
  140. float s[2];
  141. uint32_t count;
  142. if (!ParseArguments(s, ArrayLength(s), &count)) {
  143. return false;
  144. }
  145. switch (count) {
  146. case 1:
  147. s[1] = s[0];
  148. MOZ_FALLTHROUGH;
  149. case 2:
  150. {
  151. nsSVGTransform* transform = mTransforms.AppendElement(fallible);
  152. if (!transform) {
  153. return false;
  154. }
  155. transform->SetScale(s[0], s[1]);
  156. return true;
  157. }
  158. }
  159. return false;
  160. }
  161. bool
  162. SVGTransformListParser::ParseRotate()
  163. {
  164. float r[3];
  165. uint32_t count;
  166. if (!ParseArguments(r, ArrayLength(r), &count)) {
  167. return false;
  168. }
  169. switch (count) {
  170. case 1:
  171. r[1] = r[2] = 0.f;
  172. MOZ_FALLTHROUGH;
  173. case 3:
  174. {
  175. nsSVGTransform* transform = mTransforms.AppendElement(fallible);
  176. if (!transform) {
  177. return false;
  178. }
  179. transform->SetRotate(r[0], r[1], r[2]);
  180. return true;
  181. }
  182. }
  183. return false;
  184. }
  185. bool
  186. SVGTransformListParser::ParseSkewX()
  187. {
  188. float skew;
  189. uint32_t count;
  190. if (!ParseArguments(&skew, 1, &count) || count != 1) {
  191. return false;
  192. }
  193. nsSVGTransform* transform = mTransforms.AppendElement(fallible);
  194. if (!transform) {
  195. return false;
  196. }
  197. transform->SetSkewX(skew);
  198. return true;
  199. }
  200. bool
  201. SVGTransformListParser::ParseSkewY()
  202. {
  203. float skew;
  204. uint32_t count;
  205. if (!ParseArguments(&skew, 1, &count) || count != 1) {
  206. return false;
  207. }
  208. nsSVGTransform* transform = mTransforms.AppendElement(fallible);
  209. if (!transform) {
  210. return false;
  211. }
  212. transform->SetSkewY(skew);
  213. return true;
  214. }
  215. bool
  216. SVGTransformListParser::ParseMatrix()
  217. {
  218. float m[6];
  219. uint32_t count;
  220. if (!ParseArguments(m, ArrayLength(m), &count) || count != 6) {
  221. return false;
  222. }
  223. nsSVGTransform* transform = mTransforms.AppendElement(fallible);
  224. if (!transform) {
  225. return false;
  226. }
  227. transform->SetMatrix(gfxMatrix(m[0], m[1], m[2], m[3], m[4], m[5]));
  228. return true;
  229. }