Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/svg/SVGTransformListParser.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
#include "mozilla/ArrayUtils.h"
8
9
#include "SVGTransformListParser.h"
10
#include "SVGContentUtils.h"
11
#include "nsSVGTransform.h"
12
#include "nsGkAtoms.h"
13
#include "nsAtom.h"
14
15
using namespace mozilla;
16
17
//----------------------------------------------------------------------
18
// private methods
19
20
bool
21
SVGTransformListParser::Parse()
22
0
{
23
0
  mTransforms.Clear();
24
0
  return ParseTransforms();
25
0
}
26
27
bool
28
SVGTransformListParser::ParseTransforms()
29
0
{
30
0
  if (!SkipWsp()) {
31
0
    return true;
32
0
  }
33
0
34
0
  if (!ParseTransform()) {
35
0
    return false;
36
0
  }
37
0
38
0
  while (SkipWsp()) {
39
0
    // The SVG BNF allows multiple comma-wsp between transforms
40
0
    while (*mIter == ',') {
41
0
      ++mIter;
42
0
      if (!SkipWsp()) {
43
0
        return false;
44
0
      }
45
0
    }
46
0
47
0
    if (!ParseTransform()) {
48
0
      return false;
49
0
    }
50
0
  }
51
0
  return true;
52
0
}
53
54
bool
55
SVGTransformListParser::ParseTransform()
56
0
{
57
0
  RangedPtr<const char16_t> start(mIter);
58
0
  while (IsAlpha(*mIter)) {
59
0
    ++mIter;
60
0
    if (mIter == mEnd) {
61
0
      return false;
62
0
    }
63
0
  }
64
0
65
0
  if (start == mIter) {
66
0
    // Didn't read anything
67
0
    return false;
68
0
  }
69
0
70
0
  const nsAString& transform = Substring(start.get(), mIter.get());
71
0
  nsStaticAtom* keyAtom = NS_GetStaticAtom(transform);
72
0
73
0
  if (!keyAtom || !SkipWsp()) {
74
0
    return false;
75
0
  }
76
0
77
0
  if (keyAtom == nsGkAtoms::translate) {
78
0
    return ParseTranslate();
79
0
  }
80
0
  if (keyAtom == nsGkAtoms::scale) {
81
0
    return ParseScale();
82
0
  }
83
0
  if (keyAtom == nsGkAtoms::rotate) {
84
0
    return ParseRotate();
85
0
  }
86
0
  if (keyAtom == nsGkAtoms::skewX) {
87
0
    return ParseSkewX();
88
0
  }
89
0
  if (keyAtom == nsGkAtoms::skewY) {
90
0
    return ParseSkewY();
91
0
  }
92
0
  if (keyAtom == nsGkAtoms::matrix) {
93
0
    return ParseMatrix();
94
0
  }
95
0
  return false;
96
0
}
97
98
bool
99
SVGTransformListParser::ParseArguments(float* aResult,
100
                                       uint32_t aMaxCount,
101
                                       uint32_t* aParsedCount)
102
0
{
103
0
  if (*mIter != '(') {
104
0
    return false;
105
0
  }
106
0
  ++mIter;
107
0
108
0
  if (!SkipWsp()) {
109
0
    return false;
110
0
  }
111
0
112
0
  if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[0])) {
113
0
    return false;
114
0
  }
115
0
  *aParsedCount = 1;
116
0
117
0
  while (SkipWsp()) {
118
0
    if (*mIter == ')') {
119
0
      ++mIter;
120
0
      return true;
121
0
    }
122
0
    if (*aParsedCount == aMaxCount) {
123
0
      return false;
124
0
    }
125
0
    SkipCommaWsp();
126
0
    if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[(*aParsedCount)++])) {
127
0
      return false;
128
0
    }
129
0
  }
130
0
  return false;
131
0
}
132
133
bool
134
SVGTransformListParser::ParseTranslate()
135
0
{
136
0
  float t[2];
137
0
  uint32_t count;
138
0
139
0
  if (!ParseArguments(t, ArrayLength(t), &count)) {
140
0
    return false;
141
0
  }
142
0
143
0
  switch (count) {
144
0
    case 1:
145
0
      t[1] = 0.f;
146
0
      MOZ_FALLTHROUGH;
147
0
    case 2:
148
0
    {
149
0
      nsSVGTransform* transform = mTransforms.AppendElement(fallible);
150
0
      if (!transform) {
151
0
        return false;
152
0
      }
153
0
      transform->SetTranslate(t[0], t[1]);
154
0
      return true;
155
0
    }
156
0
  }
157
0
158
0
  return false;
159
0
}
160
161
bool
162
SVGTransformListParser::ParseScale()
163
0
{
164
0
  float s[2];
165
0
  uint32_t count;
166
0
167
0
  if (!ParseArguments(s, ArrayLength(s), &count)) {
168
0
    return false;
169
0
  }
170
0
171
0
  switch (count) {
172
0
    case 1:
173
0
      s[1] = s[0];
174
0
      MOZ_FALLTHROUGH;
175
0
    case 2:
176
0
    {
177
0
      nsSVGTransform* transform = mTransforms.AppendElement(fallible);
178
0
      if (!transform) {
179
0
        return false;
180
0
      }
181
0
      transform->SetScale(s[0], s[1]);
182
0
      return true;
183
0
    }
184
0
  }
185
0
186
0
  return false;
187
0
}
188
189
190
bool
191
SVGTransformListParser::ParseRotate()
192
0
{
193
0
  float r[3];
194
0
  uint32_t count;
195
0
196
0
  if (!ParseArguments(r, ArrayLength(r), &count)) {
197
0
    return false;
198
0
  }
199
0
200
0
  switch (count) {
201
0
    case 1:
202
0
      r[1] = r[2] = 0.f;
203
0
      MOZ_FALLTHROUGH;
204
0
    case 3:
205
0
    {
206
0
      nsSVGTransform* transform = mTransforms.AppendElement(fallible);
207
0
      if (!transform) {
208
0
        return false;
209
0
      }
210
0
      transform->SetRotate(r[0], r[1], r[2]);
211
0
      return true;
212
0
    }
213
0
  }
214
0
215
0
  return false;
216
0
}
217
218
bool
219
SVGTransformListParser::ParseSkewX()
220
0
{
221
0
  float skew;
222
0
  uint32_t count;
223
0
224
0
  if (!ParseArguments(&skew, 1, &count) || count != 1) {
225
0
    return false;
226
0
  }
227
0
228
0
  nsSVGTransform* transform = mTransforms.AppendElement(fallible);
229
0
  if (!transform) {
230
0
    return false;
231
0
  }
232
0
  transform->SetSkewX(skew);
233
0
234
0
  return true;
235
0
}
236
237
bool
238
SVGTransformListParser::ParseSkewY()
239
0
{
240
0
  float skew;
241
0
  uint32_t count;
242
0
243
0
  if (!ParseArguments(&skew, 1, &count) || count != 1) {
244
0
    return false;
245
0
  }
246
0
247
0
  nsSVGTransform* transform = mTransforms.AppendElement(fallible);
248
0
  if (!transform) {
249
0
    return false;
250
0
  }
251
0
  transform->SetSkewY(skew);
252
0
253
0
  return true;
254
0
}
255
256
bool
257
SVGTransformListParser::ParseMatrix()
258
0
{
259
0
  float m[6];
260
0
  uint32_t count;
261
0
262
0
  if (!ParseArguments(m, ArrayLength(m), &count) || count != 6) {
263
0
    return false;
264
0
  }
265
0
266
0
  nsSVGTransform* transform = mTransforms.AppendElement(fallible);
267
0
  if (!transform) {
268
0
    return false;
269
0
  }
270
0
  transform->SetMatrix(gfxMatrix(m[0], m[1], m[2], m[3], m[4], m[5]));
271
0
272
0
  return true;
273
0
}