tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SVGTransformListParser.cpp (5012B)


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