mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 929011 - Simplify path and transform parsing. r=dholbert
This commit is contained in:
parent
c57c578dc0
commit
2a9ecaa6e6
@ -10,7 +10,6 @@
|
||||
// Keep others in (case-insensitive) order:
|
||||
#include "gfxMatrix.h"
|
||||
#include "mozilla/dom/SVGSVGElement.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "nsFontMetrics.h"
|
||||
#include "nsIFrame.h"
|
||||
@ -390,24 +389,22 @@ DecimalDigitValue(PRUnichar aCh)
|
||||
|
||||
template<class floatType>
|
||||
bool
|
||||
SVGContentUtils::ParseNumber(const nsAString& aString,
|
||||
floatType& aValue,
|
||||
nsAString& aLeftOver)
|
||||
SVGContentUtils::ParseNumber(RangedPtr<const PRUnichar>& aIter,
|
||||
const RangedPtr<const PRUnichar>& aEnd,
|
||||
floatType& aValue)
|
||||
{
|
||||
mozilla::RangedPtr<const PRUnichar> iter(aString.Data(), aString.Length());
|
||||
const mozilla::RangedPtr<const PRUnichar> end(aString.Data() + aString.Length(),
|
||||
aString.Data(), aString.Length());
|
||||
|
||||
if (iter == end) {
|
||||
if (aIter == aEnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RangedPtr<const PRUnichar> iter(aIter);
|
||||
|
||||
// Sign of the mantissa (-1 or 1).
|
||||
int32_t sign = *iter == '-' ? -1 : 1;
|
||||
|
||||
if (*iter == '-' || *iter == '+') {
|
||||
++iter;
|
||||
if (iter == end) {
|
||||
if (iter == aEnd) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -424,9 +421,9 @@ SVGContentUtils::ParseNumber(const nsAString& aString,
|
||||
do {
|
||||
intPart = floatType(10) * intPart + DecimalDigitValue(*iter);
|
||||
++iter;
|
||||
} while (iter != end && IsDigit(*iter));
|
||||
} while (iter != aEnd && IsDigit(*iter));
|
||||
|
||||
if (iter != end) {
|
||||
if (iter != aEnd) {
|
||||
gotDot = *iter == '.';
|
||||
}
|
||||
}
|
||||
@ -436,7 +433,7 @@ SVGContentUtils::ParseNumber(const nsAString& aString,
|
||||
|
||||
if (gotDot) {
|
||||
++iter;
|
||||
if (iter == end || !IsDigit(*iter)) {
|
||||
if (iter == aEnd || !IsDigit(*iter)) {
|
||||
return false;
|
||||
}
|
||||
// Power of ten by which we need to divide our next digit
|
||||
@ -445,23 +442,23 @@ SVGContentUtils::ParseNumber(const nsAString& aString,
|
||||
fracPart += DecimalDigitValue(*iter) / divisor;
|
||||
divisor *= 10;
|
||||
++iter;
|
||||
} while (iter != end && IsDigit(*iter));
|
||||
} while (iter != aEnd && IsDigit(*iter));
|
||||
}
|
||||
|
||||
bool gotE = false;
|
||||
int32_t exponent = 0;
|
||||
int32_t expSign;
|
||||
|
||||
if (iter != end && (*iter == 'e' || *iter == 'E')) {
|
||||
if (iter != aEnd && (*iter == 'e' || *iter == 'E')) {
|
||||
|
||||
mozilla::RangedPtr<const PRUnichar> expIter(iter);
|
||||
RangedPtr<const PRUnichar> expIter(iter);
|
||||
|
||||
++expIter;
|
||||
if (expIter != end) {
|
||||
if (expIter != aEnd) {
|
||||
expSign = *expIter == '-' ? -1 : 1;
|
||||
if (*expIter == '-' || *expIter == '+') {
|
||||
++expIter;
|
||||
if (expIter != end && IsDigit(*expIter)) {
|
||||
if (expIter != aEnd && IsDigit(*expIter)) {
|
||||
// At this point we're sure this is an exponent
|
||||
// and not the start of a unit such as em or ex.
|
||||
gotE = true;
|
||||
@ -474,41 +471,54 @@ SVGContentUtils::ParseNumber(const nsAString& aString,
|
||||
do {
|
||||
exponent = 10 * exponent + DecimalDigitValue(*iter);
|
||||
++iter;
|
||||
} while (iter != end && IsDigit(*iter));
|
||||
} while (iter != aEnd && IsDigit(*iter));
|
||||
}
|
||||
}
|
||||
|
||||
// Assemble the number
|
||||
aValue = sign * (intPart + fracPart);
|
||||
floatType value = sign * (intPart + fracPart);
|
||||
if (gotE) {
|
||||
aValue *= pow(floatType(10), floatType(expSign * exponent));
|
||||
value *= pow(floatType(10), floatType(expSign * exponent));
|
||||
}
|
||||
|
||||
aLeftOver = Substring(iter.get(), end.get());
|
||||
return NS_finite(aValue);
|
||||
if (!NS_finite(value)) {
|
||||
return false;
|
||||
}
|
||||
aIter = iter;
|
||||
aValue = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool
|
||||
SVGContentUtils::ParseNumber<float>(const nsAString& aString,
|
||||
float& aValue,
|
||||
nsAString& aLeftOver);
|
||||
SVGContentUtils::ParseNumber<float>(RangedPtr<const PRUnichar>& aIter,
|
||||
const RangedPtr<const PRUnichar>& aEnd,
|
||||
float& aValue);
|
||||
template bool
|
||||
SVGContentUtils::ParseNumber<double>(const nsAString& aString,
|
||||
double& aValue,
|
||||
nsAString& aLeftOver);
|
||||
SVGContentUtils::ParseNumber<double>(RangedPtr<const PRUnichar>& aIter,
|
||||
const RangedPtr<const PRUnichar>& aEnd,
|
||||
double& aValue);
|
||||
|
||||
RangedPtr<const PRUnichar>
|
||||
SVGContentUtils::GetStartRangedPtr(const nsAString& aString)
|
||||
{
|
||||
return RangedPtr<const PRUnichar>(aString.Data(), aString.Length());
|
||||
}
|
||||
|
||||
RangedPtr<const PRUnichar>
|
||||
SVGContentUtils::GetEndRangedPtr(const nsAString& aString)
|
||||
{
|
||||
return RangedPtr<const PRUnichar>(aString.Data() + aString.Length(),
|
||||
aString.Data(), aString.Length());
|
||||
}
|
||||
|
||||
template<class floatType>
|
||||
bool
|
||||
SVGContentUtils::ParseNumber(const nsAString& aString,
|
||||
floatType& aValue)
|
||||
{
|
||||
nsAutoString leftOver;
|
||||
RangedPtr<const PRUnichar> iter = GetStartRangedPtr(aString);
|
||||
const RangedPtr<const PRUnichar> end = GetEndRangedPtr(aString);
|
||||
|
||||
if (!ParseNumber(aString, aValue, leftOver)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return leftOver.IsEmpty();
|
||||
return ParseNumber(iter, end, aValue) && iter == end;
|
||||
}
|
||||
|
||||
template bool
|
||||
@ -522,9 +532,8 @@ bool
|
||||
SVGContentUtils::ParseInteger(const nsAString& aString,
|
||||
int32_t& aValue)
|
||||
{
|
||||
mozilla::RangedPtr<const PRUnichar> iter(aString.Data(), aString.Length());
|
||||
const mozilla::RangedPtr<const PRUnichar> end(aString.Data() + aString.Length(),
|
||||
aString.Data(), aString.Length());
|
||||
RangedPtr<const PRUnichar> iter = GetStartRangedPtr(aString);
|
||||
const RangedPtr<const PRUnichar> end = GetEndRangedPtr(aString);
|
||||
|
||||
if (iter == end) {
|
||||
return false;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "gfxMatrix.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
@ -132,16 +133,24 @@ public:
|
||||
float aViewboxWidth, float aViewboxHeight,
|
||||
const SVGPreserveAspectRatio &aPreserveAspectRatio);
|
||||
|
||||
static mozilla::RangedPtr<const PRUnichar>
|
||||
GetStartRangedPtr(const nsAString& aString);
|
||||
|
||||
static mozilla::RangedPtr<const PRUnichar>
|
||||
GetEndRangedPtr(const nsAString& aString);
|
||||
|
||||
/**
|
||||
* Parse a number of the form:
|
||||
* number ::= integer ([Ee] integer)? | [+-]? [0-9]* "." [0-9]+ ([Ee] integer)?
|
||||
* Parsing fails if the number cannot be represented by a floatType.
|
||||
* Anything after the number is returned in aLeftOver.
|
||||
* If parsing succeeds, aIter is updated so that it points to the character
|
||||
* after the end of the number, otherwise it is left unchanged
|
||||
*/
|
||||
template<class floatType>
|
||||
static bool
|
||||
ParseNumber(const nsAString& aString, floatType& aValue,
|
||||
nsAString& aLeftOver);
|
||||
ParseNumber(mozilla::RangedPtr<const PRUnichar>& aIter,
|
||||
const mozilla::RangedPtr<const PRUnichar>& aEnd,
|
||||
floatType& aValue);
|
||||
|
||||
/**
|
||||
* Parse a number of the form:
|
||||
|
@ -34,15 +34,20 @@ SVGLength::GetValueAsString(nsAString &aValue) const
|
||||
}
|
||||
|
||||
bool
|
||||
SVGLength::SetValueFromString(const nsAString &aValueAsString)
|
||||
SVGLength::SetValueFromString(const nsAString &aString)
|
||||
{
|
||||
nsAutoString units;
|
||||
RangedPtr<const PRUnichar> iter =
|
||||
SVGContentUtils::GetStartRangedPtr(aString);
|
||||
const RangedPtr<const PRUnichar> end =
|
||||
SVGContentUtils::GetEndRangedPtr(aString);
|
||||
|
||||
float value;
|
||||
|
||||
if (!SVGContentUtils::ParseNumber(aValueAsString, value, units)) {
|
||||
if (!SVGContentUtils::ParseNumber(iter, end, value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nsAString& units = Substring(iter.get(), end.get());
|
||||
uint16_t unitType = GetUnitTypeForString(units);
|
||||
if (!IsValidUnitType(unitType)) {
|
||||
return false;
|
||||
|
@ -241,13 +241,13 @@ SVGMotionSMILAnimationFunction::RebuildPathAndVerticesFromPathAttr()
|
||||
|
||||
// Generate gfxPath from |path| attr
|
||||
SVGPathData path;
|
||||
nsSVGPathDataParserToInternal pathParser(&path);
|
||||
nsSVGPathDataParser pathParser(pathSpec, &path);
|
||||
|
||||
// We ignore any failure returned from Parse() since the SVG spec says to
|
||||
// accept all segments up to the first invalid token. Instead we must
|
||||
// explicitly check that the parse produces at least one path segment (if
|
||||
// the path data doesn't begin with a valid "M", then it's invalid).
|
||||
pathParser.Parse(pathSpec);
|
||||
pathParser.Parse();
|
||||
if (!path.Length()) {
|
||||
return;
|
||||
}
|
||||
|
@ -71,8 +71,8 @@ SVGPathData::SetValueFromString(const nsAString& aValue)
|
||||
// the first error. We still return any error though so that callers know if
|
||||
// there's a problem.
|
||||
|
||||
nsSVGPathDataParserToInternal pathParser(this);
|
||||
return pathParser.Parse(aValue);
|
||||
nsSVGPathDataParser pathParser(aValue, this);
|
||||
return pathParser.Parse() ? NS_OK : NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
class gfxContext;
|
||||
class gfxPath;
|
||||
class nsSVGPathDataParserToInternal; // IWYU pragma: keep
|
||||
class nsSVGPathDataParser; // IWYU pragma: keep
|
||||
|
||||
struct gfxMatrix;
|
||||
struct nsSVGMark;
|
||||
@ -78,8 +78,8 @@ class SVGPathData
|
||||
friend class SVGAnimatedPathSegList;
|
||||
friend class DOMSVGPathSegList;
|
||||
friend class DOMSVGPathSeg;
|
||||
friend class ::nsSVGPathDataParserToInternal;
|
||||
// nsSVGPathDataParserToInternal will not keep wrappers in sync, so consumers
|
||||
friend class ::nsSVGPathDataParser;
|
||||
// nsSVGPathDataParser will not keep wrappers in sync, so consumers
|
||||
// are responsible for that!
|
||||
|
||||
typedef gfx::DrawTarget DrawTarget;
|
||||
|
@ -60,15 +60,21 @@ SVGPointList::SetValueFromString(const nsAString& aValue)
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
|
||||
const nsAString& token = tokenizer.nextToken();
|
||||
|
||||
RangedPtr<const PRUnichar> iter =
|
||||
SVGContentUtils::GetStartRangedPtr(token);
|
||||
const RangedPtr<const PRUnichar> end =
|
||||
SVGContentUtils::GetEndRangedPtr(token);
|
||||
|
||||
float x;
|
||||
nsAutoString leftOver;
|
||||
if (!SVGContentUtils::ParseNumber(tokenizer.nextToken(), x, leftOver)) {
|
||||
if (!SVGContentUtils::ParseNumber(iter, end, x)) {
|
||||
rv = NS_ERROR_DOM_SYNTAX_ERR;
|
||||
break;
|
||||
}
|
||||
|
||||
float y;
|
||||
if (leftOver.IsEmpty()) {
|
||||
if (iter == end) {
|
||||
if (!tokenizer.hasMoreTokens() ||
|
||||
!SVGContentUtils::ParseNumber(tokenizer.nextToken(), y)) {
|
||||
rv = NS_ERROR_DOM_SYNTAX_ERR;
|
||||
@ -77,6 +83,7 @@ SVGPointList::SetValueFromString(const nsAString& aValue)
|
||||
} else {
|
||||
// It's possible for the token to be 10-30 which has
|
||||
// no separator but needs to be parsed as 10, -30
|
||||
const nsAString& leftOver = Substring(iter.get(), end.get());
|
||||
if (leftOver[0] != '-' || !SVGContentUtils::ParseNumber(leftOver, y)) {
|
||||
rv = NS_ERROR_DOM_SYNTAX_ERR;
|
||||
break;
|
||||
|
@ -70,10 +70,8 @@ SVGTransformList::GetValueAsString(nsAString& aValue) const
|
||||
nsresult
|
||||
SVGTransformList::SetValueFromString(const nsAString& aValue)
|
||||
{
|
||||
SVGTransformListParser parser;
|
||||
nsresult rv = parser.Parse(aValue);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
SVGTransformListParser parser(aValue);
|
||||
if (!parser.Parse()) {
|
||||
// there was a parse error.
|
||||
return NS_ERROR_DOM_SYNTAX_ERR;
|
||||
}
|
||||
|
@ -7,201 +7,138 @@
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "SVGTransformListParser.h"
|
||||
#include "SVGContentUtils.h"
|
||||
#include "nsSVGTransform.h"
|
||||
#include "nsError.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "plstr.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// private methods
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::Match()
|
||||
bool
|
||||
SVGTransformListParser::Parse()
|
||||
{
|
||||
mTransforms.Clear();
|
||||
return MatchTransformList();
|
||||
return ParseTransforms();
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::MatchTransformList()
|
||||
{
|
||||
MatchWsp();
|
||||
|
||||
if (IsTokenTransformStarter()) {
|
||||
ENSURE_MATCHED(MatchTransforms());
|
||||
}
|
||||
|
||||
MatchWsp();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::MatchTransforms()
|
||||
{
|
||||
ENSURE_MATCHED(MatchTransform());
|
||||
|
||||
while (mTokenType != END) {
|
||||
const char* pos = mTokenPos;
|
||||
|
||||
/* Curiously the SVG BNF allows multiple comma-wsp between transforms */
|
||||
while (IsTokenCommaWspStarter()) {
|
||||
ENSURE_MATCHED(MatchCommaWsp());
|
||||
}
|
||||
|
||||
if (IsTokenTransformStarter()) {
|
||||
ENSURE_MATCHED(MatchTransform());
|
||||
} else {
|
||||
if (pos != mTokenPos) RewindTo(pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::GetTransformToken(nsIAtom** aKeyAtom,
|
||||
bool aAdvancePos)
|
||||
{
|
||||
if (mTokenType != OTHER || *mTokenPos == '\0') {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
const char* delimiters = "\x20\x9\xD\xA,(";
|
||||
char* delimiterStart = PL_strnpbrk(mTokenPos, delimiters, 11);
|
||||
if (delimiterStart != 0) {
|
||||
/* save this character and null it out */
|
||||
char holdingChar = *delimiterStart;
|
||||
*delimiterStart = '\0';
|
||||
|
||||
uint32_t len;
|
||||
if ((len = strlen(mTokenPos)) > 0) {
|
||||
*aKeyAtom = NS_NewAtom(Substring(mTokenPos, mTokenPos + len)).get();
|
||||
|
||||
if (aAdvancePos) {
|
||||
mInputPos = mTokenPos + len;
|
||||
mTokenPos = mInputPos;
|
||||
}
|
||||
} else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
/* reset character back to original */
|
||||
*delimiterStart = holdingChar;
|
||||
} else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::MatchTransform()
|
||||
{
|
||||
nsCOMPtr<nsIAtom> keyatom;
|
||||
|
||||
nsresult rv = GetTransformToken(getter_AddRefs(keyatom), true);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (keyatom == nsGkAtoms::translate) {
|
||||
ENSURE_MATCHED(MatchTranslate());
|
||||
} else if (keyatom == nsGkAtoms::scale) {
|
||||
ENSURE_MATCHED(MatchScale());
|
||||
} else if (keyatom == nsGkAtoms::rotate) {
|
||||
ENSURE_MATCHED(MatchRotate());
|
||||
} else if (keyatom == nsGkAtoms::skewX) {
|
||||
ENSURE_MATCHED(MatchSkewX());
|
||||
} else if (keyatom == nsGkAtoms::skewY) {
|
||||
ENSURE_MATCHED(MatchSkewY());
|
||||
} else if (keyatom == nsGkAtoms::matrix) {
|
||||
ENSURE_MATCHED(MatchMatrix());
|
||||
} else {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SVGTransformListParser::IsTokenTransformStarter()
|
||||
SVGTransformListParser::ParseTransforms()
|
||||
{
|
||||
nsCOMPtr<nsIAtom> keyatom;
|
||||
|
||||
nsresult rv = GetTransformToken(getter_AddRefs(keyatom), false);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keyatom == nsGkAtoms::translate ||
|
||||
keyatom == nsGkAtoms::scale ||
|
||||
keyatom == nsGkAtoms::rotate ||
|
||||
keyatom == nsGkAtoms::skewX ||
|
||||
keyatom == nsGkAtoms::skewY ||
|
||||
keyatom == nsGkAtoms::matrix) {
|
||||
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 PRUnichar> 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());
|
||||
nsIAtom* 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;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::MatchNumberArguments(float *aResult,
|
||||
uint32_t aMaxNum,
|
||||
uint32_t *aParsedNum)
|
||||
bool
|
||||
SVGTransformListParser::ParseArguments(float* aResult,
|
||||
uint32_t aMaxCount,
|
||||
uint32_t* aParsedCount)
|
||||
{
|
||||
*aParsedNum = 0;
|
||||
if (*mIter != '(') {
|
||||
return false;
|
||||
}
|
||||
++mIter;
|
||||
|
||||
MatchWsp();
|
||||
|
||||
ENSURE_MATCHED(MatchLeftParen());
|
||||
|
||||
MatchWsp();
|
||||
|
||||
ENSURE_MATCHED(MatchNumber(&aResult[0]));
|
||||
*aParsedNum = 1;
|
||||
|
||||
while (IsTokenCommaWspStarter()) {
|
||||
MatchWsp();
|
||||
if (mTokenType == RIGHT_PAREN) {
|
||||
break;
|
||||
}
|
||||
if (*aParsedNum == aMaxNum) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (IsTokenCommaWspStarter()) {
|
||||
MatchCommaWsp();
|
||||
}
|
||||
ENSURE_MATCHED(MatchNumber(&aResult[(*aParsedNum)++]));
|
||||
if (!SkipWsp()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MatchWsp();
|
||||
if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[0])) {
|
||||
return false;
|
||||
}
|
||||
*aParsedCount = 1;
|
||||
|
||||
ENSURE_MATCHED(MatchRightParen());
|
||||
|
||||
return NS_OK;
|
||||
while (SkipWsp()) {
|
||||
if (*mIter == ')') {
|
||||
++mIter;
|
||||
return true;
|
||||
}
|
||||
if (*aParsedCount == aMaxCount) {
|
||||
return false;
|
||||
}
|
||||
SkipCommaWsp();
|
||||
if (!SVGContentUtils::ParseNumber(mIter, mEnd, aResult[(*aParsedCount)++])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::MatchTranslate()
|
||||
bool
|
||||
SVGTransformListParser::ParseTranslate()
|
||||
{
|
||||
GetNextToken();
|
||||
|
||||
float t[2];
|
||||
uint32_t count;
|
||||
|
||||
ENSURE_MATCHED(MatchNumberArguments(t, ArrayLength(t), &count));
|
||||
if (!ParseArguments(t, ArrayLength(t), &count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (count) {
|
||||
case 1:
|
||||
@ -210,27 +147,26 @@ SVGTransformListParser::MatchTranslate()
|
||||
case 2:
|
||||
{
|
||||
nsSVGTransform* transform = mTransforms.AppendElement();
|
||||
NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!transform) {
|
||||
return false;
|
||||
}
|
||||
transform->SetTranslate(t[0], t[1]);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::MatchScale()
|
||||
bool
|
||||
SVGTransformListParser::ParseScale()
|
||||
{
|
||||
GetNextToken();
|
||||
|
||||
float s[2];
|
||||
uint32_t count;
|
||||
|
||||
ENSURE_MATCHED(MatchNumberArguments(s, ArrayLength(s), &count));
|
||||
if (!ParseArguments(s, ArrayLength(s), &count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (count) {
|
||||
case 1:
|
||||
@ -239,27 +175,27 @@ SVGTransformListParser::MatchScale()
|
||||
case 2:
|
||||
{
|
||||
nsSVGTransform* transform = mTransforms.AppendElement();
|
||||
NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!transform) {
|
||||
return false;
|
||||
}
|
||||
transform->SetScale(s[0], s[1]);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::MatchRotate()
|
||||
bool
|
||||
SVGTransformListParser::ParseRotate()
|
||||
{
|
||||
GetNextToken();
|
||||
|
||||
float r[3];
|
||||
uint32_t count;
|
||||
|
||||
ENSURE_MATCHED(MatchNumberArguments(r, ArrayLength(r), &count));
|
||||
if (!ParseArguments(r, ArrayLength(r), &count)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (count) {
|
||||
case 1:
|
||||
@ -268,79 +204,70 @@ SVGTransformListParser::MatchRotate()
|
||||
case 3:
|
||||
{
|
||||
nsSVGTransform* transform = mTransforms.AppendElement();
|
||||
NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!transform) {
|
||||
return false;
|
||||
}
|
||||
transform->SetRotate(r[0], r[1], r[2]);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::MatchSkewX()
|
||||
bool
|
||||
SVGTransformListParser::ParseSkewX()
|
||||
{
|
||||
GetNextToken();
|
||||
|
||||
float skew;
|
||||
uint32_t count;
|
||||
|
||||
ENSURE_MATCHED(MatchNumberArguments(&skew, 1, &count));
|
||||
|
||||
if (count != 1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!ParseArguments(&skew, 1, &count) || count != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsSVGTransform* transform = mTransforms.AppendElement();
|
||||
NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!transform) {
|
||||
return false;
|
||||
}
|
||||
transform->SetSkewX(skew);
|
||||
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::MatchSkewY()
|
||||
bool
|
||||
SVGTransformListParser::ParseSkewY()
|
||||
{
|
||||
GetNextToken();
|
||||
|
||||
float skew;
|
||||
uint32_t count;
|
||||
|
||||
ENSURE_MATCHED(MatchNumberArguments(&skew, 1, &count));
|
||||
|
||||
if (count != 1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!ParseArguments(&skew, 1, &count) || count != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsSVGTransform* transform = mTransforms.AppendElement();
|
||||
NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!transform) {
|
||||
return false;
|
||||
}
|
||||
transform->SetSkewY(skew);
|
||||
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
SVGTransformListParser::MatchMatrix()
|
||||
bool
|
||||
SVGTransformListParser::ParseMatrix()
|
||||
{
|
||||
GetNextToken();
|
||||
|
||||
float m[6];
|
||||
uint32_t count;
|
||||
|
||||
ENSURE_MATCHED(MatchNumberArguments(m, ArrayLength(m), &count));
|
||||
|
||||
if (count != 6) {
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!ParseArguments(m, ArrayLength(m), &count) || count != 6) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsSVGTransform* transform = mTransforms.AppendElement();
|
||||
NS_ENSURE_TRUE(transform, NS_ERROR_OUT_OF_MEMORY);
|
||||
if (!transform) {
|
||||
return false;
|
||||
}
|
||||
transform->SetMatrix(gfxMatrix(m[0], m[1], m[2], m[3], m[4], m[5]));
|
||||
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
@ -12,14 +12,11 @@
|
||||
#include "nsTArray.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// SVGTransformListParser: taken from nsSVGPathDataParser, a simple
|
||||
// recursive descent parser that builds the transform lists from the
|
||||
// transform attributes. The grammar for path data
|
||||
// SVGTransformListParser: A simple recursive descent parser that builds
|
||||
// transform lists from transform attributes. The grammar for path data
|
||||
// can be found in SVG 1.1, chapter 7.
|
||||
// http://www.w3.org/TR/SVG11/coords.html#TransformAttribute
|
||||
|
||||
class nsIAtom;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class nsSVGTransform;
|
||||
@ -27,36 +24,33 @@ class nsSVGTransform;
|
||||
class SVGTransformListParser : public nsSVGDataParser
|
||||
{
|
||||
public:
|
||||
SVGTransformListParser(const nsAString& aValue)
|
||||
: nsSVGDataParser(aValue) {}
|
||||
|
||||
bool Parse();
|
||||
|
||||
const nsTArray<nsSVGTransform>& GetTransformList() const {
|
||||
return mTransforms;
|
||||
}
|
||||
|
||||
private:
|
||||
nsTArray<nsSVGTransform> mTransforms;
|
||||
|
||||
// helpers
|
||||
virtual nsresult Match() MOZ_OVERRIDE;
|
||||
bool ParseArguments(float *aResult,
|
||||
uint32_t aMaxCount,
|
||||
uint32_t *aParsedCount);
|
||||
|
||||
nsresult MatchNumberArguments(float *aResult,
|
||||
uint32_t aMaxNum,
|
||||
uint32_t *aParsedNum);
|
||||
bool ParseTransforms();
|
||||
|
||||
nsresult MatchTransformList();
|
||||
bool ParseTransform();
|
||||
|
||||
nsresult GetTransformToken(nsIAtom** aKeyatom, bool aAdvancePos);
|
||||
nsresult MatchTransforms();
|
||||
bool ParseTranslate();
|
||||
bool ParseScale();
|
||||
bool ParseRotate();
|
||||
bool ParseSkewX();
|
||||
bool ParseSkewY();
|
||||
bool ParseMatrix();
|
||||
|
||||
nsresult MatchTransform();
|
||||
|
||||
bool IsTokenTransformStarter();
|
||||
|
||||
nsresult MatchTranslate();
|
||||
|
||||
nsresult MatchScale();
|
||||
nsresult MatchRotate();
|
||||
nsresult MatchSkewX();
|
||||
nsresult MatchSkewY();
|
||||
nsresult MatchMatrix();
|
||||
FallibleTArray<nsSVGTransform> mTransforms;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -94,16 +94,20 @@ GetValueString(nsAString &aValueAsString, float aValue, uint16_t aUnitType)
|
||||
}
|
||||
|
||||
static bool
|
||||
GetValueFromString(const nsAString& aValueAsString,
|
||||
GetValueFromString(const nsAString& aString,
|
||||
float& aValue,
|
||||
uint16_t* aUnitType)
|
||||
{
|
||||
nsAutoString units;
|
||||
RangedPtr<const PRUnichar> iter =
|
||||
SVGContentUtils::GetStartRangedPtr(aString);
|
||||
const RangedPtr<const PRUnichar> end =
|
||||
SVGContentUtils::GetEndRangedPtr(aString);
|
||||
|
||||
if (!SVGContentUtils::ParseNumber(aValueAsString, aValue, units)) {
|
||||
if (!SVGContentUtils::ParseNumber(iter, end, aValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nsAString& units = Substring(iter.get(), end.get());
|
||||
*aUnitType = GetUnitTypeForString(units);
|
||||
return IsValidUnitType(*aUnitType);
|
||||
}
|
||||
|
@ -3,298 +3,37 @@
|
||||
* 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/. */
|
||||
|
||||
/**
|
||||
* NOTE:
|
||||
*
|
||||
* How should subclasses use this class?
|
||||
* This class was separated from the nsSVGPathDataParser class to share
|
||||
* functionality found to be common in other descent parsers in this component.
|
||||
*
|
||||
* A subclass should implement a Match method which gets invoked from the
|
||||
* Parse method. The Parse method can be overridden, as required.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "nsSVGDataParser.h"
|
||||
#include "prdtoa.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "SVGContentUtils.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// public interface
|
||||
|
||||
nsresult
|
||||
nsSVGDataParser::Parse(const nsAString &aValue)
|
||||
nsSVGDataParser::nsSVGDataParser(const nsAString& aValue)
|
||||
: mIter(SVGContentUtils::GetStartRangedPtr(aValue)),
|
||||
mEnd(SVGContentUtils::GetEndRangedPtr(aValue))
|
||||
{
|
||||
char *str = ToNewUTF8String(aValue);
|
||||
if (!str)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mInputPos = str;
|
||||
|
||||
GetNextToken();
|
||||
nsresult rv = Match();
|
||||
if (mTokenType != END)
|
||||
rv = NS_ERROR_FAILURE; // not all tokens were consumed
|
||||
|
||||
mInputPos = nullptr;
|
||||
nsMemory::Free(str);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// helpers
|
||||
|
||||
void nsSVGDataParser::GetNextToken()
|
||||
bool
|
||||
nsSVGDataParser::SkipCommaWsp()
|
||||
{
|
||||
mTokenPos = mInputPos;
|
||||
mTokenVal = *mInputPos;
|
||||
|
||||
switch (mTokenVal) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
mTokenType = DIGIT;
|
||||
break;
|
||||
case '\x20': case '\x9': case '\xd': case '\xa':
|
||||
mTokenType = WSP;
|
||||
break;
|
||||
case ',':
|
||||
mTokenType = COMMA;
|
||||
break;
|
||||
case '+': case '-':
|
||||
mTokenType = SIGN;
|
||||
break;
|
||||
case '.':
|
||||
mTokenType = POINT;
|
||||
break;
|
||||
case '(':
|
||||
mTokenType = LEFT_PAREN;
|
||||
break;
|
||||
case ')':
|
||||
mTokenType = RIGHT_PAREN;
|
||||
break;
|
||||
case '\0':
|
||||
mTokenType = END;
|
||||
break;
|
||||
default:
|
||||
mTokenType = OTHER;
|
||||
if (!SkipWsp()) {
|
||||
// end of string
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*mInputPos != '\0') {
|
||||
++mInputPos;
|
||||
if (*mIter != ',') {
|
||||
return true;
|
||||
}
|
||||
++mIter;
|
||||
return SkipWsp();
|
||||
}
|
||||
|
||||
void nsSVGDataParser::RewindTo(const char* aPos)
|
||||
bool
|
||||
nsSVGDataParser::SkipWsp()
|
||||
{
|
||||
mInputPos = aPos;
|
||||
GetNextToken();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult nsSVGDataParser::MatchNumber(float* aX)
|
||||
{
|
||||
const char* pos = mTokenPos;
|
||||
|
||||
if (mTokenType == SIGN)
|
||||
GetNextToken();
|
||||
|
||||
const char* pos2 = mTokenPos;
|
||||
|
||||
nsresult rv = MatchFloatingPointConst();
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
RewindTo(pos2);
|
||||
ENSURE_MATCHED(MatchIntegerConst());
|
||||
}
|
||||
|
||||
char* end;
|
||||
/* PR_strtod is not particularily fast. We only need a float and not a double so
|
||||
* we could probably use something faster here if needed. The CSS parser uses
|
||||
* nsCSSScanner::ParseNumber() instead of PR_strtod. See bug 516396 for some
|
||||
* additional info. */
|
||||
*aX = float(PR_strtod(pos, &end));
|
||||
if (pos != end && NS_finite(*aX)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool nsSVGDataParser::IsTokenNumberStarter()
|
||||
{
|
||||
return (mTokenType == DIGIT || mTokenType == POINT || mTokenType == SIGN);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult nsSVGDataParser::MatchCommaWsp()
|
||||
{
|
||||
switch (mTokenType) {
|
||||
case WSP:
|
||||
ENSURE_MATCHED(MatchWsp());
|
||||
if (mTokenType == COMMA)
|
||||
GetNextToken();
|
||||
break;
|
||||
case COMMA:
|
||||
GetNextToken();
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
while (IsTokenWspStarter()) {
|
||||
ENSURE_MATCHED(MatchWsp());
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsSVGDataParser::IsTokenCommaWspStarter()
|
||||
{
|
||||
return (IsTokenWspStarter() || mTokenType == COMMA);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult nsSVGDataParser::MatchIntegerConst()
|
||||
{
|
||||
ENSURE_MATCHED(MatchDigitSeq());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult nsSVGDataParser::MatchFloatingPointConst()
|
||||
{
|
||||
// XXX inefficient implementation. It would be nice if we could make
|
||||
// this predictive and wouldn't have to backtrack...
|
||||
|
||||
const char* pos = mTokenPos;
|
||||
|
||||
nsresult rv = MatchFractConst();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (IsTokenExponentStarter())
|
||||
ENSURE_MATCHED(MatchExponent());
|
||||
}
|
||||
else {
|
||||
RewindTo(pos);
|
||||
ENSURE_MATCHED(MatchDigitSeq());
|
||||
ENSURE_MATCHED(MatchExponent());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult nsSVGDataParser::MatchFractConst()
|
||||
{
|
||||
if (mTokenType == POINT) {
|
||||
GetNextToken();
|
||||
ENSURE_MATCHED(MatchDigitSeq());
|
||||
}
|
||||
else {
|
||||
ENSURE_MATCHED(MatchDigitSeq());
|
||||
if (mTokenType == POINT) {
|
||||
GetNextToken();
|
||||
if (IsTokenDigitSeqStarter()) {
|
||||
ENSURE_MATCHED(MatchDigitSeq());
|
||||
}
|
||||
while (mIter != mEnd) {
|
||||
if (!IsSVGWhitespace(*mIter)) {
|
||||
return true;
|
||||
}
|
||||
++mIter;
|
||||
}
|
||||
return NS_OK;
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult nsSVGDataParser::MatchExponent()
|
||||
{
|
||||
if (!(tolower(mTokenVal) == 'e')) return NS_ERROR_FAILURE;
|
||||
|
||||
GetNextToken();
|
||||
|
||||
if (mTokenType == SIGN)
|
||||
GetNextToken();
|
||||
|
||||
ENSURE_MATCHED(MatchDigitSeq());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsSVGDataParser::IsTokenExponentStarter()
|
||||
{
|
||||
return (tolower(mTokenVal) == 'e');
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult nsSVGDataParser::MatchDigitSeq()
|
||||
{
|
||||
if (!(mTokenType == DIGIT)) return NS_ERROR_FAILURE;
|
||||
|
||||
do {
|
||||
GetNextToken();
|
||||
} while (mTokenType == DIGIT);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsSVGDataParser::IsTokenDigitSeqStarter()
|
||||
{
|
||||
return (mTokenType == DIGIT);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult nsSVGDataParser::MatchWsp()
|
||||
{
|
||||
if (!(mTokenType == WSP)) return NS_ERROR_FAILURE;
|
||||
|
||||
do {
|
||||
GetNextToken();
|
||||
} while (mTokenType == WSP);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsSVGDataParser::IsTokenWspStarter()
|
||||
{
|
||||
return (mTokenType == WSP);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult nsSVGDataParser::MatchLeftParen()
|
||||
{
|
||||
switch (mTokenType) {
|
||||
case LEFT_PAREN:
|
||||
GetNextToken();
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsSVGDataParser::MatchRightParen()
|
||||
{
|
||||
switch (mTokenType) {
|
||||
case RIGHT_PAREN:
|
||||
GetNextToken();
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -6,57 +6,32 @@
|
||||
#ifndef __NS_SVGDATAPARSER_H__
|
||||
#define __NS_SVGDATAPARSER_H__
|
||||
|
||||
#include "nsError.h"
|
||||
#include "mozilla/RangedPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// helper macros
|
||||
#define ENSURE_MATCHED(exp) { nsresult rv = exp; if (NS_FAILED(rv)) return rv; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsSVGDataParser: a simple abstract class for parsing values
|
||||
// nsSVGDataParser: a simple base class for parsing values
|
||||
// for path and transform values.
|
||||
//
|
||||
class nsSVGDataParser
|
||||
{
|
||||
public:
|
||||
nsresult Parse(const nsAString &aValue);
|
||||
nsSVGDataParser(const nsAString& aValue);
|
||||
|
||||
protected:
|
||||
const char* mInputPos;
|
||||
static bool IsAlpha(PRUnichar aCh) {
|
||||
// Exclude non-ascii characters before calling isalpha
|
||||
return (aCh & 0x7f) == aCh && isalpha(aCh);
|
||||
}
|
||||
|
||||
const char* mTokenPos;
|
||||
enum { DIGIT, WSP, COMMA, POINT, SIGN, LEFT_PAREN, RIGHT_PAREN, OTHER, END } mTokenType;
|
||||
char mTokenVal;
|
||||
// Returns true if there are more characters to read, false otherwise.
|
||||
bool SkipCommaWsp();
|
||||
|
||||
// helpers
|
||||
void GetNextToken();
|
||||
void RewindTo(const char* aPos);
|
||||
virtual nsresult Match()=0;
|
||||
// Returns true if there are more characters to read, false otherwise.
|
||||
bool SkipWsp();
|
||||
|
||||
nsresult MatchNumber(float* x);
|
||||
bool IsTokenNumberStarter();
|
||||
|
||||
nsresult MatchCommaWsp();
|
||||
bool IsTokenCommaWspStarter();
|
||||
|
||||
nsresult MatchIntegerConst();
|
||||
|
||||
nsresult MatchFloatingPointConst();
|
||||
|
||||
nsresult MatchFractConst();
|
||||
|
||||
nsresult MatchExponent();
|
||||
bool IsTokenExponentStarter();
|
||||
|
||||
nsresult MatchDigitSeq();
|
||||
bool IsTokenDigitSeqStarter();
|
||||
|
||||
nsresult MatchWsp();
|
||||
bool IsTokenWspStarter();
|
||||
|
||||
nsresult MatchLeftParen();
|
||||
nsresult MatchRightParen();
|
||||
mozilla::RangedPtr<const PRUnichar> mIter;
|
||||
const mozilla::RangedPtr<const PRUnichar> mEnd;
|
||||
};
|
||||
|
||||
|
||||
|
@ -122,14 +122,19 @@ GetValueString(nsAString &aValueAsString, float aValue, uint16_t aUnitType)
|
||||
}
|
||||
|
||||
static bool
|
||||
GetValueFromString(const nsAString& aValueAsString,
|
||||
GetValueFromString(const nsAString& aString,
|
||||
float& aValue,
|
||||
uint16_t* aUnitType)
|
||||
{
|
||||
nsAutoString units;
|
||||
if (!SVGContentUtils::ParseNumber(aValueAsString, aValue, units)) {
|
||||
RangedPtr<const PRUnichar> iter =
|
||||
SVGContentUtils::GetStartRangedPtr(aString);
|
||||
const RangedPtr<const PRUnichar> end =
|
||||
SVGContentUtils::GetEndRangedPtr(aString);
|
||||
|
||||
if (!SVGContentUtils::ParseNumber(iter, end, aValue)) {
|
||||
return false;
|
||||
}
|
||||
const nsAString& units = Substring(iter.get(), end.get());
|
||||
*aUnitType = GetUnitTypeForString(units);
|
||||
return IsValidUnitType(*aUnitType);
|
||||
}
|
||||
|
@ -49,22 +49,28 @@ static nsSVGAttrTearoffTable<nsSVGNumber2, nsSVGNumber2::DOMAnimatedNumber>
|
||||
sSVGAnimatedNumberTearoffTable;
|
||||
|
||||
static bool
|
||||
GetValueFromString(const nsAString& aValueAsString,
|
||||
GetValueFromString(const nsAString& aString,
|
||||
bool aPercentagesAllowed,
|
||||
float& aValue)
|
||||
{
|
||||
nsAutoString units;
|
||||
RangedPtr<const PRUnichar> iter =
|
||||
SVGContentUtils::GetStartRangedPtr(aString);
|
||||
const RangedPtr<const PRUnichar> end =
|
||||
SVGContentUtils::GetEndRangedPtr(aString);
|
||||
|
||||
if (!SVGContentUtils::ParseNumber(aValueAsString, aValue, units)) {
|
||||
if (!SVGContentUtils::ParseNumber(iter, end, aValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aPercentagesAllowed && units.EqualsLiteral("%")) {
|
||||
aValue /= 100;
|
||||
return true;
|
||||
if (aPercentagesAllowed) {
|
||||
const nsAString& units = Substring(iter.get(), end.get());
|
||||
if (units.EqualsLiteral("%")) {
|
||||
aValue /= 100;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return units.IsEmpty();
|
||||
return iter == end;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,91 +22,43 @@ class SVGPathData;
|
||||
|
||||
class nsSVGPathDataParser : public nsSVGDataParser
|
||||
{
|
||||
protected:
|
||||
// Path data storage
|
||||
virtual nsresult StoreMoveTo(bool absCoords, float x, float y) = 0;
|
||||
virtual nsresult StoreClosePath() = 0;
|
||||
virtual nsresult StoreLineTo(bool absCoords, float x, float y) = 0;
|
||||
virtual nsresult StoreHLineTo(bool absCoords, float x) = 0;
|
||||
virtual nsresult StoreVLineTo(bool absCoords, float y) = 0;
|
||||
virtual nsresult StoreCurveTo(bool absCoords, float x, float y,
|
||||
float x1, float y1, float x2, float y2) = 0;
|
||||
virtual nsresult StoreSmoothCurveTo(bool absCoords, float x, float y,
|
||||
float x2, float y2) = 0;
|
||||
virtual nsresult StoreQuadCurveTo(bool absCoords, float x, float y,
|
||||
float x1, float y1) = 0;
|
||||
virtual nsresult StoreSmoothQuadCurveTo(bool absCoords,
|
||||
float x, float y) = 0;
|
||||
virtual nsresult StoreEllipticalArc(bool absCoords, float x, float y,
|
||||
float r1, float r2, float angle,
|
||||
bool largeArcFlag, bool sweepFlag) = 0;
|
||||
virtual nsresult Match() MOZ_OVERRIDE;
|
||||
public:
|
||||
nsSVGPathDataParser(const nsAString& aValue,
|
||||
mozilla::SVGPathData* aList)
|
||||
: nsSVGDataParser(aValue),
|
||||
mPathSegList(aList)
|
||||
{
|
||||
MOZ_ASSERT(aList, "null path data");
|
||||
}
|
||||
|
||||
nsresult MatchCoordPair(float* aX, float* aY);
|
||||
bool IsTokenCoordPairStarter();
|
||||
bool Parse();
|
||||
|
||||
nsresult MatchCoord(float* aX);
|
||||
bool IsTokenCoordStarter();
|
||||
private:
|
||||
|
||||
nsresult MatchFlag(bool* f);
|
||||
bool ParseCoordPair(float& aX, float& aY);
|
||||
bool ParseFlag(bool& aFlag);
|
||||
|
||||
nsresult MatchSvgPath();
|
||||
bool ParsePath();
|
||||
bool IsStartOfSubPath() const;
|
||||
bool ParseSubPath();
|
||||
|
||||
nsresult MatchSubPaths();
|
||||
bool IsTokenSubPathsStarter();
|
||||
bool ParseSubPathElements();
|
||||
bool ParseSubPathElement(PRUnichar aCommandType,
|
||||
bool aAbsCoords);
|
||||
|
||||
nsresult MatchSubPath();
|
||||
bool IsTokenSubPathStarter();
|
||||
bool ParseMoveto();
|
||||
bool ParseClosePath();
|
||||
bool ParseLineto(bool aAbsCoords);
|
||||
bool ParseHorizontalLineto(bool aAbsCoords);
|
||||
bool ParseVerticalLineto(bool aAbsCoords);
|
||||
bool ParseCurveto(bool aAbsCoords);
|
||||
bool ParseSmoothCurveto(bool aAbsCoords);
|
||||
bool ParseQuadBezierCurveto(bool aAbsCoords);
|
||||
bool ParseSmoothQuadBezierCurveto(bool aAbsCoords);
|
||||
bool ParseEllipticalArc(bool aAbsCoords);
|
||||
|
||||
nsresult MatchSubPathElements();
|
||||
bool IsTokenSubPathElementsStarter();
|
||||
|
||||
nsresult MatchSubPathElement();
|
||||
bool IsTokenSubPathElementStarter();
|
||||
|
||||
nsresult MatchMoveto();
|
||||
nsresult MatchMovetoArgSeq(bool absCoords);
|
||||
|
||||
nsresult MatchClosePath();
|
||||
|
||||
nsresult MatchLineto();
|
||||
|
||||
nsresult MatchLinetoArgSeq(bool absCoords);
|
||||
bool IsTokenLinetoArgSeqStarter();
|
||||
|
||||
nsresult MatchHorizontalLineto();
|
||||
nsresult MatchHorizontalLinetoArgSeq(bool absCoords);
|
||||
|
||||
nsresult MatchVerticalLineto();
|
||||
nsresult MatchVerticalLinetoArgSeq(bool absCoords);
|
||||
|
||||
nsresult MatchCurveto();
|
||||
nsresult MatchCurvetoArgSeq(bool absCoords);
|
||||
nsresult MatchCurvetoArg(float* x, float* y, float* x1,
|
||||
float* y1, float* x2, float* y2);
|
||||
bool IsTokenCurvetoArgStarter();
|
||||
|
||||
nsresult MatchSmoothCurveto();
|
||||
nsresult MatchSmoothCurvetoArgSeq(bool absCoords);
|
||||
nsresult MatchSmoothCurvetoArg(float* x, float* y, float* x2, float* y2);
|
||||
bool IsTokenSmoothCurvetoArgStarter();
|
||||
|
||||
nsresult MatchQuadBezierCurveto();
|
||||
nsresult MatchQuadBezierCurvetoArgSeq(bool absCoords);
|
||||
nsresult MatchQuadBezierCurvetoArg(float* x, float* y, float* x1, float* y1);
|
||||
bool IsTokenQuadBezierCurvetoArgStarter();
|
||||
|
||||
nsresult MatchSmoothQuadBezierCurveto();
|
||||
nsresult MatchSmoothQuadBezierCurvetoArgSeq(bool absCoords);
|
||||
|
||||
nsresult MatchEllipticalArc();
|
||||
nsresult MatchEllipticalArcArgSeq(bool absCoords);
|
||||
nsresult MatchEllipticalArcArg(float* x, float* y,
|
||||
float* r1, float* r2, float* angle,
|
||||
bool* largeArcFlag, bool* sweepFlag);
|
||||
bool IsTokenEllipticalArcArgStarter();
|
||||
|
||||
};
|
||||
mozilla::SVGPathData * const mPathSegList;
|
||||
};
|
||||
|
||||
class nsSVGArcConverter
|
||||
{
|
||||
@ -128,34 +80,4 @@ protected:
|
||||
Point mFrom, mC;
|
||||
};
|
||||
|
||||
class nsSVGPathDataParserToInternal : public nsSVGPathDataParser
|
||||
{
|
||||
public:
|
||||
nsSVGPathDataParserToInternal(mozilla::SVGPathData *aList)
|
||||
: mPathSegList(aList)
|
||||
{}
|
||||
nsresult Parse(const nsAString &aValue);
|
||||
|
||||
protected:
|
||||
virtual nsresult StoreMoveTo(bool absCoords, float x, float y) MOZ_OVERRIDE;
|
||||
virtual nsresult StoreClosePath() MOZ_OVERRIDE;
|
||||
virtual nsresult StoreLineTo(bool absCoords, float x, float y) MOZ_OVERRIDE;
|
||||
virtual nsresult StoreHLineTo(bool absCoords, float x) MOZ_OVERRIDE;
|
||||
virtual nsresult StoreVLineTo(bool absCoords, float y) MOZ_OVERRIDE;
|
||||
virtual nsresult StoreCurveTo(bool absCoords, float x, float y,
|
||||
float x1, float y1, float x2, float y2) MOZ_OVERRIDE;
|
||||
virtual nsresult StoreSmoothCurveTo(bool absCoords, float x, float y,
|
||||
float x2, float y2) MOZ_OVERRIDE;
|
||||
virtual nsresult StoreQuadCurveTo(bool absCoords, float x, float y,
|
||||
float x1, float y1) MOZ_OVERRIDE;
|
||||
virtual nsresult StoreSmoothQuadCurveTo(bool absCoords,
|
||||
float x, float y) MOZ_OVERRIDE;
|
||||
virtual nsresult StoreEllipticalArc(bool absCoords, float x, float y,
|
||||
float r1, float r2, float angle,
|
||||
bool largeArcFlag, bool sweepFlag) MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
mozilla::SVGPathData *mPathSegList;
|
||||
};
|
||||
|
||||
#endif // __NS_SVGPATHDATAPARSER_H__
|
||||
|
Loading…
Reference in New Issue
Block a user