Bug 338142 - Enhance nsSVGPathDataParser, create superclass for reuse

functionality.  Patch by wellsk@us.ibm.com, r=tor, sr=roc.
This commit is contained in:
tor%cs.brown.edu 2006-06-16 17:20:25 +00:00
Родитель fc30af6010
Коммит ea5d30c760
5 изменённых файлов: 766 добавлений и 608 удалений

Просмотреть файл

@ -83,6 +83,7 @@ CPPSRCS = \
nsSVGClassValue.cpp \
nsSVGClipPathElement.cpp \
nsSVGCoordCtxProvider.cpp \
nsSVGDataParser.cpp \
nsSVGDefsElement.cpp \
nsSVGDescElement.cpp \
nsSVGElement.cpp \

Просмотреть файл

@ -0,0 +1,360 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* IBM Corporation
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* 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 "nsSVGUtils.h"
#include <stdlib.h>
#include <math.h>
//----------------------------------------------------------------------
// public interface
nsresult
nsSVGDataParser::Parse(const nsAString &aValue)
{
nsresult rv = NS_OK;
char *str = ToNewUTF8String(aValue);
if (!str)
return NS_ERROR_OUT_OF_MEMORY;
mInputPos = str;
GetNextToken();
rv = Match();
if (mTokenType != END)
rv = NS_ERROR_FAILURE; // not all tokens were consumed
mInputPos = nsnull;
nsMemory::Free(str);
return rv;
}
//----------------------------------------------------------------------
// helpers
void nsSVGDataParser::GetNextToken()
{
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 (*mInputPos != '\0') {
++mInputPos;
}
}
void nsSVGDataParser::RewindTo(const char* aPos)
{
mInputPos = aPos;
GetNextToken();
}
nsresult nsSVGDataParser::Match()
{
return NS_OK;
}
//----------------------------------------------------------------------
nsresult nsSVGDataParser::MatchNonNegativeNumber(float* aX)
{
// XXX inefficient implementation. We probably hit the RewindTo case
// often.
const char* pos = mTokenPos;
nsresult rv = MatchFloatingPointConst();
if (NS_FAILED(rv)) {
RewindTo(pos);
ENSURE_MATCHED(MatchIntegerConst());
}
char* end;
*aX = (float) PR_strtod(pos, &end);
NS_ASSERTION(end == mTokenPos, "number parse error");
return NS_OK;
}
PRBool nsSVGDataParser::IsTokenNonNegativeNumberStarter()
{
return (mTokenType == DIGIT || mTokenType == POINT);
}
//----------------------------------------------------------------------
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;
*aX = (float) PR_strtod(pos, &end);
NS_ASSERTION(end == mTokenPos, "number parse error");
return NS_OK;
}
PRBool 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;
}
PRBool 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());
}
}
}
return NS_OK;
}
//----------------------------------------------------------------------
nsresult nsSVGDataParser::MatchExponent()
{
if (!(tolower(mTokenVal) == 'e')) return NS_ERROR_FAILURE;
GetNextToken();
if (mTokenType == SIGN)
GetNextToken();
ENSURE_MATCHED(MatchDigitSeq());
return NS_OK;
}
PRBool nsSVGDataParser::IsTokenExponentStarter()
{
return (tolower(mTokenVal) == 'e');
}
//----------------------------------------------------------------------
nsresult nsSVGDataParser::MatchDigitSeq()
{
if (!(mTokenType == DIGIT)) return NS_ERROR_FAILURE;
do {
GetNextToken();
} while (mTokenType == DIGIT);
return NS_OK;
}
PRBool nsSVGDataParser::IsTokenDigitSeqStarter()
{
return (mTokenType == DIGIT);
}
//----------------------------------------------------------------------
nsresult nsSVGDataParser::MatchWsp()
{
if (!(mTokenType == WSP)) return NS_ERROR_FAILURE;
do {
GetNextToken();
} while (mTokenType == WSP);
return NS_OK;
}
PRBool 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;
}

Просмотреть файл

@ -0,0 +1,98 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla SVG project.
*
* The Initial Developer of the Original Code is
* IBM Corporation
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __NS_SVGDATAPARSER_H__
#define __NS_SVGDATAPARSER_H__
#include "nsCOMPtr.h"
#include "nsVoidArray.h"
//----------------------------------------------------------------------
// helper macros
#define ENSURE_MATCHED(exp) { nsresult rv = exp; if (NS_FAILED(rv)) return rv; }
////////////////////////////////////////////////////////////////////////
// nsSVGDataParser: a simple abstract class for parsing values
// for path and transform values.
//
class nsSVGDataParser
{
public:
nsresult Parse(const nsAString &aValue);
protected:
const char* mInputPos;
const char* mTokenPos;
enum { DIGIT, WSP, COMMA, POINT, SIGN, LEFT_PAREN, RIGHT_PAREN, OTHER, END } mTokenType;
char mTokenVal;
// helpers
void GetNextToken();
void RewindTo(const char* aPos);
virtual nsresult Match();
nsresult MatchNonNegativeNumber(float* aX);
PRBool IsTokenNonNegativeNumberStarter();
nsresult MatchNumber(float* x);
PRBool IsTokenNumberStarter();
nsresult MatchCommaWsp();
PRBool IsTokenCommaWspStarter();
nsresult MatchIntegerConst();
nsresult MatchFloatingPointConst();
nsresult MatchFractConst();
nsresult MatchExponent();
PRBool IsTokenExponentStarter();
nsresult MatchDigitSeq();
PRBool IsTokenDigitSeqStarter();
nsresult MatchWsp();
PRBool IsTokenWspStarter();
nsresult MatchLeftParen();
nsresult MatchRightParen();
};
#endif // __NS_SVGDATAPARSER_H__

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -39,6 +39,7 @@
#ifndef __NS_SVGPATHDATAPARSER_H__
#define __NS_SVGPATHDATAPARSER_H__
#include "nsSVGDataParser.h"
#include "nsCOMPtr.h"
#include "nsVoidArray.h"
#include "nsIDOMSVGPathSeg.h"
@ -52,18 +53,9 @@ class nsSVGPathList;
// nsIDOMPathSegs from path data strings. The grammar for path data
// can be found in SVG CR 20001102, chapter 8.
class nsSVGPathDataParser
class nsSVGPathDataParser : public nsSVGDataParser
{
public:
virtual nsresult Parse(const nsAString &aValue);
protected:
const char* inputpos;
char tokenval;
const char* tokenpos;
enum { DIGIT, WSP, COMMA, POINT, SIGN, OTHER, END } tokentype;
// Path data storage
virtual nsresult StoreMoveTo(PRBool absCoords, float x, float y) = 0;
virtual nsresult StoreClosePath() = 0;
@ -81,101 +73,73 @@ protected:
virtual nsresult StoreEllipticalArc(PRBool absCoords, float x, float y,
float r1, float r2, float angle,
PRBool largeArcFlag, PRBool sweepFlag) = 0;
nsresult Match();
nsresult MatchCoordPair(float* aX, float* aY);
PRBool IsTokenCoordPairStarter();
// helpers
void getNextToken();
void windBack(const char* pos);
nsresult match(char tok);
nsresult MatchCoord(float* aX);
PRBool IsTokenCoordStarter();
nsresult MatchFlag(PRBool* f);
nsresult matchSvgPath();
nsresult MatchSvgPath();
nsresult matchSubPaths();
PRBool isTokenSubPathsStarter();
nsresult MatchSubPaths();
PRBool IsTokenSubPathsStarter();
nsresult matchSubPath();
PRBool isTokenSubPathStarter();
nsresult MatchSubPath();
PRBool IsTokenSubPathStarter();
nsresult matchSubPathElements();
PRBool isTokenSubPathElementsStarter();
nsresult MatchSubPathElements();
PRBool IsTokenSubPathElementsStarter();
nsresult matchSubPathElement();
PRBool isTokenSubPathElementStarter();
nsresult MatchSubPathElement();
PRBool IsTokenSubPathElementStarter();
nsresult matchMoveto();
nsresult matchMovetoArgSeq(PRBool absCoords);
nsresult MatchMoveto();
nsresult MatchMovetoArgSeq(PRBool absCoords);
nsresult matchClosePath();
nsresult MatchClosePath();
nsresult matchLineto();
nsresult MatchLineto();
nsresult matchLinetoArgSeq(PRBool absCoords);
PRBool isTokenLinetoArgSeqStarter();
nsresult MatchLinetoArgSeq(PRBool absCoords);
PRBool IsTokenLinetoArgSeqStarter();
nsresult matchHorizontalLineto();
nsresult matchHorizontalLinetoArgSeq(PRBool absCoords);
nsresult MatchHorizontalLineto();
nsresult MatchHorizontalLinetoArgSeq(PRBool absCoords);
nsresult matchVerticalLineto();
nsresult matchVerticalLinetoArgSeq(PRBool absCoords);
nsresult MatchVerticalLineto();
nsresult MatchVerticalLinetoArgSeq(PRBool absCoords);
nsresult matchCurveto();
nsresult matchCurvetoArgSeq(PRBool absCoords);
nsresult matchCurvetoArg(float* x, float* y, float* x1,
nsresult MatchCurveto();
nsresult MatchCurvetoArgSeq(PRBool absCoords);
nsresult MatchCurvetoArg(float* x, float* y, float* x1,
float* y1, float* x2, float* y2);
PRBool isTokenCurvetoArgStarter();
PRBool IsTokenCurvetoArgStarter();
nsresult matchSmoothCurveto();
nsresult matchSmoothCurvetoArgSeq(PRBool absCoords);
nsresult matchSmoothCurvetoArg(float* x, float* y, float* x2, float* y2);
PRBool isTokenSmoothCurvetoArgStarter();
nsresult MatchSmoothCurveto();
nsresult MatchSmoothCurvetoArgSeq(PRBool absCoords);
nsresult MatchSmoothCurvetoArg(float* x, float* y, float* x2, float* y2);
PRBool IsTokenSmoothCurvetoArgStarter();
nsresult matchQuadBezierCurveto();
nsresult matchQuadBezierCurvetoArgSeq(PRBool absCoords);
nsresult matchQuadBezierCurvetoArg(float* x, float* y, float* x1, float* y1);
PRBool isTokenQuadBezierCurvetoArgStarter();
nsresult MatchQuadBezierCurveto();
nsresult MatchQuadBezierCurvetoArgSeq(PRBool absCoords);
nsresult MatchQuadBezierCurvetoArg(float* x, float* y, float* x1, float* y1);
PRBool IsTokenQuadBezierCurvetoArgStarter();
nsresult matchSmoothQuadBezierCurveto();
nsresult matchSmoothQuadBezierCurvetoArgSeq(PRBool absCoords);
nsresult MatchSmoothQuadBezierCurveto();
nsresult MatchSmoothQuadBezierCurvetoArgSeq(PRBool absCoords);
nsresult matchEllipticalArc();
nsresult matchEllipticalArcArgSeq(PRBool absCoords);
nsresult matchEllipticalArcArg(float* x, float* y,
nsresult MatchEllipticalArc();
nsresult MatchEllipticalArcArgSeq(PRBool absCoords);
nsresult MatchEllipticalArcArg(float* x, float* y,
float* r1, float* r2, float* angle,
PRBool* largeArcFlag, PRBool* sweepFlag);
PRBool isTokenEllipticalArcArgStarter();
PRBool IsTokenEllipticalArcArgStarter();
nsresult matchCoordPair(float* x, float* y);
PRBool isTokenCoordPairStarter();
nsresult matchCoord(float* x);
PRBool isTokenCoordStarter();
nsresult matchNonNegativeNumber(float* x);
PRBool isTokenNonNegativeNumberStarter();
nsresult matchNumber(float* x);
PRBool isTokenNumberStarter();
nsresult matchFlag(PRBool* f);
nsresult matchCommaWsp();
PRBool isTokenCommaWspStarter();
nsresult matchIntegerConst();
nsresult matchFloatingPointConst();
nsresult matchFractConst();
nsresult matchExponent();
PRBool isTokenExponentStarter();
nsresult matchDigitSeq();
PRBool isTokenDigitSeqStarter();
nsresult matchWsp();
PRBool isTokenWspStarter();
};
};
class nsSVGPathDataParserToInternal : public nsSVGPathDataParser
{