mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-26 03:35:33 +00:00
8ad99dd7fa
It's a sub-class of nsAtom, useful for cases where you know you are dealing exclusively with static atoms. The nice thing about it is that you can use raw nsStaticAtom pointers instead of RefPtr<>. (In fact, the AddRef/Release implementations ensure that we'll crash if we use RefPtr<nsStaticAtom>.) MozReview-Commit-ID: 4Q6QHX5h44V --HG-- extra : rebase_source : e4237f85b4821b684db0ef84d1f9c5e17cdee428
274 lines
4.9 KiB
C++
274 lines
4.9 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/ArrayUtils.h"
|
|
|
|
#include "SVGTransformListParser.h"
|
|
#include "SVGContentUtils.h"
|
|
#include "nsSVGTransform.h"
|
|
#include "nsGkAtoms.h"
|
|
#include "nsAtom.h"
|
|
|
|
using namespace mozilla;
|
|
|
|
//----------------------------------------------------------------------
|
|
// private methods
|
|
|
|
bool
|
|
SVGTransformListParser::Parse()
|
|
{
|
|
mTransforms.Clear();
|
|
return ParseTransforms();
|
|
}
|
|
|
|
bool
|
|
SVGTransformListParser::ParseTransforms()
|
|
{
|
|
if (!SkipWsp()) {
|
|
return true;
|
|
}
|
|
|
|
if (!ParseTransform()) {
|
|
return false;
|
|
}
|
|
|
|
while (SkipWsp()) {
|
|
// The SVG BNF allows multiple comma-wsp between transforms
|
|
while (*mIter == ',') {
|
|
++mIter;
|
|
if (!SkipWsp()) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!ParseTransform()) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SVGTransformListParser::ParseTransform()
|
|
{
|
|
RangedPtr<const char16_t> start(mIter);
|
|
while (IsAlpha(*mIter)) {
|
|
++mIter;
|
|
if (mIter == mEnd) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (start == mIter) {
|
|
// Didn't read anything
|
|
return false;
|
|
}
|
|
|
|
const nsAString& transform = Substring(start.get(), mIter.get());
|
|
nsStaticAtom* keyAtom = NS_GetStaticAtom(transform);
|
|
|
|
if (!keyAtom || !SkipWsp()) {
|
|
return false;
|
|
}
|
|
|
|
if (keyAtom == nsGkAtoms::translate) {
|
|
return ParseTranslate();
|
|
}
|
|
if (keyAtom == nsGkAtoms::scale) {
|
|
return ParseScale();
|
|
}
|
|
if (keyAtom == nsGkAtoms::rotate) {
|
|
return ParseRotate();
|
|
}
|
|
if (keyAtom == nsGkAtoms::skewX) {
|
|
return ParseSkewX();
|
|
}
|
|
if (keyAtom == nsGkAtoms::skewY) {
|
|
return ParseSkewY();
|
|
}
|
|
if (keyAtom == nsGkAtoms::matrix) {
|
|
return ParseMatrix();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
SVGTransformListParser::ParseArguments(float* aResult,
|
|
uint32_t aMaxCount,
|
|
uint32_t* aParsedCount)
|
|
{
|
|
if (*mIter != '(') {
|
|
return false;
|
|
}
|
|
++mIter;
|
|
|
|
if (!SkipWsp()) {
|
|
return false;
|
|
}
|
|
|
|
if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[0])) {
|
|
return false;
|
|
}
|
|
*aParsedCount = 1;
|
|
|
|
while (SkipWsp()) {
|
|
if (*mIter == ')') {
|
|
++mIter;
|
|
return true;
|
|
}
|
|
if (*aParsedCount == aMaxCount) {
|
|
return false;
|
|
}
|
|
SkipCommaWsp();
|
|
if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[(*aParsedCount)++])) {
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
SVGTransformListParser::ParseTranslate()
|
|
{
|
|
float t[2];
|
|
uint32_t count;
|
|
|
|
if (!ParseArguments(t, ArrayLength(t), &count)) {
|
|
return false;
|
|
}
|
|
|
|
switch (count) {
|
|
case 1:
|
|
t[1] = 0.f;
|
|
MOZ_FALLTHROUGH;
|
|
case 2:
|
|
{
|
|
nsSVGTransform* transform = mTransforms.AppendElement(fallible);
|
|
if (!transform) {
|
|
return false;
|
|
}
|
|
transform->SetTranslate(t[0], t[1]);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
SVGTransformListParser::ParseScale()
|
|
{
|
|
float s[2];
|
|
uint32_t count;
|
|
|
|
if (!ParseArguments(s, ArrayLength(s), &count)) {
|
|
return false;
|
|
}
|
|
|
|
switch (count) {
|
|
case 1:
|
|
s[1] = s[0];
|
|
MOZ_FALLTHROUGH;
|
|
case 2:
|
|
{
|
|
nsSVGTransform* transform = mTransforms.AppendElement(fallible);
|
|
if (!transform) {
|
|
return false;
|
|
}
|
|
transform->SetScale(s[0], s[1]);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool
|
|
SVGTransformListParser::ParseRotate()
|
|
{
|
|
float r[3];
|
|
uint32_t count;
|
|
|
|
if (!ParseArguments(r, ArrayLength(r), &count)) {
|
|
return false;
|
|
}
|
|
|
|
switch (count) {
|
|
case 1:
|
|
r[1] = r[2] = 0.f;
|
|
MOZ_FALLTHROUGH;
|
|
case 3:
|
|
{
|
|
nsSVGTransform* transform = mTransforms.AppendElement(fallible);
|
|
if (!transform) {
|
|
return false;
|
|
}
|
|
transform->SetRotate(r[0], r[1], r[2]);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
SVGTransformListParser::ParseSkewX()
|
|
{
|
|
float skew;
|
|
uint32_t count;
|
|
|
|
if (!ParseArguments(&skew, 1, &count) || count != 1) {
|
|
return false;
|
|
}
|
|
|
|
nsSVGTransform* transform = mTransforms.AppendElement(fallible);
|
|
if (!transform) {
|
|
return false;
|
|
}
|
|
transform->SetSkewX(skew);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SVGTransformListParser::ParseSkewY()
|
|
{
|
|
float skew;
|
|
uint32_t count;
|
|
|
|
if (!ParseArguments(&skew, 1, &count) || count != 1) {
|
|
return false;
|
|
}
|
|
|
|
nsSVGTransform* transform = mTransforms.AppendElement(fallible);
|
|
if (!transform) {
|
|
return false;
|
|
}
|
|
transform->SetSkewY(skew);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SVGTransformListParser::ParseMatrix()
|
|
{
|
|
float m[6];
|
|
uint32_t count;
|
|
|
|
if (!ParseArguments(m, ArrayLength(m), &count) || count != 6) {
|
|
return false;
|
|
}
|
|
|
|
nsSVGTransform* transform = mTransforms.AppendElement(fallible);
|
|
if (!transform) {
|
|
return false;
|
|
}
|
|
transform->SetMatrix(gfxMatrix(m[0], m[1], m[2], m[3], m[4], m[5]));
|
|
|
|
return true;
|
|
}
|