⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svgparserutilities.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*   Copyright (C) 2002, 2003 The Karbon Developers                 2006       Alexander Kellett <lypanov@kde.org>                 2006, 2007 Rob Buis <buis@kde.org>   Copyrigth (C) 2007, 2009 Apple, Inc.  All rights reserved.   This library is free software; you can redistribute it and/or   modify it under the terms of the GNU Library General Public   License as published by the Free Software Foundation; either   version 2 of the License, or (at your option) any later version.   This library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Library General Public License for more details.   You should have received a copy of the GNU Library General Public License   along with this library; see the file COPYING.LIB.  If not, write to   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,   Boston, MA 02110-1301, USA.*/#include "config.h"#if ENABLE(SVG)#include "SVGParserUtilities.h"#include "ExceptionCode.h"#include "FloatConversion.h"#include "FloatPoint.h"#include "Path.h"#include "PlatformString.h"#include "SVGPathSegList.h"#include "SVGPathSegArc.h"#include "SVGPathSegClosePath.h"#include "SVGPathSegCurvetoCubic.h"#include "SVGPathSegCurvetoCubicSmooth.h"#include "SVGPathSegCurvetoQuadratic.h"#include "SVGPathSegCurvetoQuadraticSmooth.h"#include "SVGPathSegLineto.h"#include "SVGPathSegLinetoHorizontal.h"#include "SVGPathSegLinetoVertical.h"#include "SVGPathSegList.h"#include "SVGPathSegMoveto.h"#include "SVGPointList.h"#include "SVGPathElement.h"#include <math.h>#include <wtf/MathExtras.h>namespace WebCore {/* We use this generic _parseNumber function to allow the Path parsing code to work  * at a higher precision internally, without any unnecessary runtime cost or code * complexity */    template <typename FloatType> static bool _parseNumber(const UChar*& ptr, const UChar* end, FloatType& number, bool skip){    int integer, exponent;    FloatType decimal, frac;    int sign, expsign;    const UChar* start = ptr;    exponent = 0;    integer = 0;    frac = 1;    decimal = 0;    sign = 1;    expsign = 1;    // read the sign    if (ptr < end && *ptr == '+')        ptr++;    else if (ptr < end && *ptr == '-') {        ptr++;        sign = -1;    }         if (ptr == end || ((*ptr < '0' || *ptr > '9') && *ptr != '.'))        // The first character of a number must be one of [0-9+-.]        return false;    // read the integer part    while (ptr < end && *ptr >= '0' && *ptr <= '9')        integer = (integer * 10) + *(ptr++) - '0';    if (ptr < end && *ptr == '.') { // read the decimals        ptr++;                // There must be a least one digit following the .        if (ptr >= end || *ptr < '0' || *ptr > '9')            return false;                while (ptr < end && *ptr >= '0' && *ptr <= '9')            decimal += (*(ptr++) - '0') * (frac *= static_cast<FloatType>(0.1));    }    // read the exponent part    if (ptr != start && ptr + 1 < end && (*ptr == 'e' || *ptr == 'E')         && (ptr[1] != 'x' && ptr[1] != 'm')) {         ptr++;        // read the sign of the exponent        if (*ptr == '+')            ptr++;        else if (*ptr == '-') {            ptr++;            expsign = -1;        }                // There must be an exponent        if (ptr >= end || *ptr < '0' || *ptr > '9')            return false;        while (ptr < end && *ptr >= '0' && *ptr <= '9') {            exponent *= 10;            exponent += *ptr - '0';            ptr++;        }    }    number = integer + decimal;    number *= sign * static_cast<FloatType>(pow(10.0, expsign * exponent));    if (start == ptr)        return false;    if (skip)        skipOptionalSpacesOrDelimiter(ptr, end);    return true;}bool parseNumber(const UChar*& ptr, const UChar* end, float& number, bool skip) {    return _parseNumber(ptr, end, number, skip);}// Only used for parsing Pathsstatic bool parseNumber(const UChar*& ptr, const UChar* end, double& number, bool skip = true) {    return _parseNumber(ptr, end, number, skip);}bool parseNumberOptionalNumber(const String& s, float& x, float& y){    if (s.isEmpty())        return false;    const UChar* cur = s.characters();    const UChar* end = cur + s.length();    if (!parseNumber(cur, end, x))        return false;    if (cur == end)        y = x;    else if (!parseNumber(cur, end, y, false))        return false;    return cur == end;}bool pointsListFromSVGData(SVGPointList* pointsList, const String& points){    if (points.isEmpty())        return true;    const UChar* cur = points.characters();    const UChar* end = cur + points.length();    skipOptionalSpaces(cur, end);    bool delimParsed = false;    while (cur < end) {        delimParsed = false;        float xPos = 0.0f;        if (!parseNumber(cur, end, xPos))           return false;        float yPos = 0.0f;        if (!parseNumber(cur, end, yPos, false))            return false;        skipOptionalSpaces(cur, end);        if (cur < end && *cur == ',') {            delimParsed = true;            cur++;        }        skipOptionalSpaces(cur, end);        ExceptionCode ec = 0;        pointsList->appendItem(FloatPoint(xPos, yPos), ec);    }    return cur == end && !delimParsed;}    /**     * Parser for svg path data, contained in the d attribute.     *     * The parser delivers encountered commands and parameters by calling     * methods that correspond to those commands. Clients have to derive     * from this class and implement the abstract command methods.     *     * There are two operating modes. By default the parser just delivers unaltered     * svg path data commands and parameters. In the second mode, it will convert all     * relative coordinates to absolute ones, and convert all curves to cubic beziers.     */    class SVGPathParser {    public:        virtual ~SVGPathParser() { }        bool parseSVG(const String& d, bool process = false);    protected:        virtual void svgMoveTo(double x1, double y1, bool closed, bool abs = true) = 0;        virtual void svgLineTo(double x1, double y1, bool abs = true) = 0;        virtual void svgLineToHorizontal(double, bool /*abs*/ = true) { }        virtual void svgLineToVertical(double /*y*/, bool /*abs*/ = true) { }        virtual void svgCurveToCubic(double x1, double y1, double x2, double y2, double x, double y, bool abs = true) = 0;        virtual void svgCurveToCubicSmooth(double /*x*/, double /*y*/, double /*x2*/, double /*y2*/, bool /*abs*/ = true) { }        virtual void svgCurveToQuadratic(double /*x*/, double /*y*/, double /*x1*/, double /*y1*/, bool /*abs*/ = true) { }        virtual void svgCurveToQuadraticSmooth(double /*x*/, double /*y*/, bool /*abs*/ = true) { }        virtual void svgArcTo(double /*x*/, double /*y*/, double /*r1*/, double /*r2*/, double /*angle*/, bool /*largeArcFlag*/, bool /*sweepFlag*/, bool /*abs*/ = true) { }        virtual void svgClosePath() = 0;    private:        void calculateArc(bool relative, double& curx, double& cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag);    };    bool SVGPathParser::parseSVG(const String& s, bool process){    const UChar* ptr = s.characters();    const UChar* end = ptr + s.length();    double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;    double px1, py1, px2, py2, px3, py3;    bool closed = true;        if (!skipOptionalSpaces(ptr, end)) // skip any leading spaces        return false;        char command = *(ptr++), lastCommand = ' ';    if (command != 'm' && command != 'M') // path must start with moveto        return false;    subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;    while (1) {        skipOptionalSpaces(ptr, end); // skip spaces between command and first coord        bool relative = false;        switch(command)        {            case 'm':                relative = true;            case 'M':            {                if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))                    return false;                if (process) {                    subpathx = curx = relative ? curx + tox : tox;                    subpathy = cury = relative ? cury + toy : toy;                    svgMoveTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury), closed);                } else                    svgMoveTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), closed, !relative);                closed = false;                break;            }            case 'l':                relative = true;            case 'L':            {                if (!parseNumber(ptr, end, tox) || !parseNumber(ptr, end, toy))                    return false;                if (process) {                    curx = relative ? curx + tox : tox;                    cury = relative ? cury + toy : toy;                    svgLineTo(narrowPrecisionToFloat(curx), narrowPrecisionToFloat(cury));                }                else                    svgLineTo(narrowPrecisionToFloat(tox), narrowPrecisionToFloat(toy), !relative);                break;            }            case 'h':            {                if (!parseNumber(ptr, end, tox))                    return false;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -