Beispiel #1
0
bool SVGTransformable::parseTransformAttribute(SVGTransformList& list, const UChar*& currTransform, const UChar* end, TransformParsingMode mode)
{
    if (mode == ClearList)
        list.clear();

    bool delimParsed = false;
    while (currTransform < end) {
        delimParsed = false;
        SVGTransform::SVGTransformType type = SVGTransform::SVG_TRANSFORM_UNKNOWN;
        skipOptionalSVGSpaces(currTransform, end);

        if (!parseAndSkipType(currTransform, end, type))
            return false;

        SVGTransform transform;
        if (!parseTransformValue(type, currTransform, end, transform))
            return false;

        list.append(transform);
        skipOptionalSVGSpaces(currTransform, end);
        if (currTransform < end && *currTransform == ',') {
            delimParsed = true;
            ++currTransform;
        }
        skipOptionalSVGSpaces(currTransform, end);
    }

    return !delimParsed;
}
static bool parseKeySplinesInternal(const String& string, Vector<UnitBezier>& result)
{
    const CharType* ptr = string.getCharacters<CharType>();
    const CharType* end = ptr + string.length();

    skipOptionalSVGSpaces(ptr, end);

    while (ptr < end) {
        float posA = 0;
        if (!parseNumber(ptr, end, posA))
            return false;

        float posB = 0;
        if (!parseNumber(ptr, end, posB))
            return false;

        float posC = 0;
        if (!parseNumber(ptr, end, posC))
            return false;

        float posD = 0;
        if (!parseNumber(ptr, end, posD, DisallowWhitespace))
            return false;

        skipOptionalSVGSpaces(ptr, end);

        if (ptr < end && *ptr == ';')
            ptr++;
        skipOptionalSVGSpaces(ptr, end);

        result.append(UnitBezier(posA, posB, posC, posD));
    }

    return ptr == end;
}
SVGParsingError SVGPointList::parse(const CharType*& ptr, const CharType* end)
{
    if (!skipOptionalSVGSpaces(ptr, end))
        return SVGParseStatus::NoError;

    const CharType* listStart = ptr;
    for (;;) {
        float x = 0;
        float y = 0;
        if (!parseNumber(ptr, end, x)
            || !parseNumber(ptr, end, y, DisallowWhitespace))
            return SVGParsingError(SVGParseStatus::ExpectedNumber, ptr - listStart);

        append(SVGPoint::create(FloatPoint(x, y)));

        if (!skipOptionalSVGSpaces(ptr, end))
            break;

        if (*ptr == ',') {
            ++ptr;
            skipOptionalSVGSpaces(ptr, end);

            // ',' requires the list to be continued
            continue;
        }
    }
    return SVGParseStatus::NoError;
}
static bool genericParsePointsList(SVGPointList& pointsList, const CharType*& ptr, const CharType* end)
{
    skipOptionalSVGSpaces(ptr, end);

    bool delimParsed = false;
    while (ptr < end) {
        delimParsed = false;
        float xPos = 0.0f;
        if (!parseNumber(ptr, end, xPos))
           return false;

        float yPos = 0.0f;
        if (!parseNumber(ptr, end, yPos, false))
            return false;

        skipOptionalSVGSpaces(ptr, end);

        if (ptr < end && *ptr == ',') {
            delimParsed = true;
            ptr++;
        }
        skipOptionalSVGSpaces(ptr, end);

        pointsList.append(FloatPoint(xPos, yPos));
    }
    return ptr == end && !delimParsed;
}
Beispiel #5
0
bool SVGPointList::parse(const CharType*& ptr, const CharType* end)
{
    clear();

    skipOptionalSVGSpaces(ptr, end);
    if (ptr >= end)
        return true;

    for (;;) {
        float x = 0.0f;
        float y = 0.0f;
        bool valid = parseNumber(ptr, end, x) && parseNumber(ptr, end, y, false);
        if (!valid) {
            return false;
        }
        append(SVGPoint::create(FloatPoint(x, y)));

        skipOptionalSVGSpaces(ptr, end);
        if (ptr < end && *ptr == ',') {
            ++ptr;
            skipOptionalSVGSpaces(ptr, end);

            // ',' requires the list to be continued
            continue;
        }

        // check end of list
        if (ptr >= end)
            return true;
    }
}
Beispiel #6
0
bool pointsListFromSVGData(SVGPointList& pointsList, const String& points)
{
    if (points.isEmpty())
        return true;
    const UChar* cur = points.characters();
    const UChar* end = cur + points.length();

    skipOptionalSVGSpaces(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;

        skipOptionalSVGSpaces(cur, end);

        if (cur < end && *cur == ',') {
            delimParsed = true;
            cur++;
        }
        skipOptionalSVGSpaces(cur, end);

        pointsList.append(FloatPoint(xPos, yPos));
    }
    return cur == end && !delimParsed;
}
Beispiel #7
0
void SVGRect::parse(const CharType*& ptr, const CharType* end, ExceptionState& exceptionState)
{
    const CharType* start = ptr;

    skipOptionalSVGSpaces(ptr, end);

    float x = 0.0f;
    float y = 0.0f;
    float width = 0.0f;
    float height = 0.0f;
    bool valid = parseNumber(ptr, end, x) && parseNumber(ptr, end, y) && parseNumber(ptr, end, width) && parseNumber(ptr, end, height, DisallowWhitespace);

    if (!valid) {
        exceptionState.throwDOMException(SyntaxError, "Problem parsing rect \"" + String(start, end - start) + "\"");
        setInvalid();
        return;
    }

    skipOptionalSVGSpaces(ptr, end);
    if (ptr < end) { // nothing should come after the last, fourth number
        exceptionState.throwDOMException(SyntaxError, "Problem parsing rect \"" + String(start, end - start) + "\"");
        setInvalid();
        return;
    }

    m_value = FloatRect(x, y, width, height);
    m_isValid = true;
}
static void parseKeySplines(const String& parse, Vector<UnitBezier>& result)
{
    result.clear();
    if (parse.isEmpty())
        return;

    auto upconvertedCharacters = StringView(parse).upconvertedCharacters();
    const UChar* cur = upconvertedCharacters;
    const UChar* end = cur + parse.length();

    skipOptionalSVGSpaces(cur, end);

    bool delimParsed = false;
    while (cur < end) {
        delimParsed = false;
        float posA = 0;
        if (!parseNumber(cur, end, posA)) {
            result.clear();
            return;
        }

        float posB = 0;
        if (!parseNumber(cur, end, posB)) {
            result.clear();
            return;
        }

        float posC = 0;
        if (!parseNumber(cur, end, posC)) {
            result.clear();
            return;
        }

        float posD = 0;
        if (!parseNumber(cur, end, posD, false)) {
            result.clear();
            return;
        }

        skipOptionalSVGSpaces(cur, end);

        if (cur < end && *cur == ';') {
            delimParsed = true;
            cur++;
        }
        skipOptionalSVGSpaces(cur, end);

        result.append(UnitBezier(posA, posB, posC, posD));
    }
    if (!(cur == end && !delimParsed))
        result.clear();
}
Beispiel #9
0
static int parseTransformParamList(const UChar*& ptr, const UChar* end, float* values, int required, int optional)
{
    int optionalParams = 0, requiredParams = 0;
    
    if (!skipOptionalSVGSpaces(ptr, end) || *ptr != '(')
        return -1;
    
    ptr++;
   
    skipOptionalSVGSpaces(ptr, end);

    while (requiredParams < required) {
        if (ptr >= end || !parseNumber(ptr, end, values[requiredParams], false))
            return -1;
        requiredParams++;
        if (requiredParams < required)
            skipOptionalSVGSpacesOrDelimiter(ptr, end);
    }
    if (!skipOptionalSVGSpaces(ptr, end))
        return -1;
    
    bool delimParsed = skipOptionalSVGSpacesOrDelimiter(ptr, end);

    if (ptr >= end)
        return -1;
    
    if (*ptr == ')') { // skip optionals
        ptr++;
        if (delimParsed)
            return -1;
    } else {
        while (optionalParams < optional) {
            if (ptr >= end || !parseNumber(ptr, end, values[requiredParams + optionalParams], false))
                return -1;
            optionalParams++;
            if (optionalParams < optional)
                skipOptionalSVGSpacesOrDelimiter(ptr, end);
        }
        
        if (!skipOptionalSVGSpaces(ptr, end))
            return -1;
        
        delimParsed = skipOptionalSVGSpacesOrDelimiter(ptr, end);
        
        if (ptr >= end || *ptr != ')' || delimParsed)
            return -1;
        ptr++;
    }

    return requiredParams + optionalParams;
}
Beispiel #10
0
bool parseGlyphName(const String& input, HashSet<String>& values)
{
    // FIXME: Parsing error detection is missing.
    values.clear();

    const UChar* ptr = input.characters();
    const UChar* end = ptr + input.length();
    skipOptionalSVGSpaces(ptr, end);

    while (ptr < end) {
        // Leading and trailing white space, and white space before and after separators, will be ignored.
        const UChar* inputStart = ptr;
        while (ptr < end && *ptr != ',')
            ++ptr;

        if (ptr == inputStart)
            break;

        // walk backwards from the ; to ignore any whitespace
        const UChar* inputEnd = ptr - 1;
        while (inputStart < inputEnd && isSVGSpace(*inputEnd))
            --inputEnd;

        values.add(String(inputStart, inputEnd - inputStart + 1));
        skipOptionalSVGSpacesOrDelimiter(ptr, end, ',');
    }

    return true;
}
Beispiel #11
0
static Vector<String> genericParseDelimitedString(const CharType*& ptr, const CharType* end, const char seperator)
{
    Vector<String> values;

    skipOptionalSVGSpaces(ptr, end);

    while (ptr < end) {
        // Leading and trailing white space, and white space before and after semicolon separators, will be ignored.
        const CharType* inputStart = ptr;
        while (ptr < end && *ptr != seperator) // careful not to ignore whitespace inside inputs
            ptr++;

        if (ptr == inputStart)
            break;

        // walk backwards from the ; to ignore any whitespace
        const CharType* inputEnd = ptr - 1;
        while (inputStart < inputEnd && isSVGSpace(*inputEnd))
            inputEnd--;

        values.append(String(inputStart, inputEnd - inputStart + 1));
        skipOptionalSVGSpacesOrDelimiter(ptr, end, seperator);
    }

    return values;
}
Vector<String> parseDelimitedString(const String& input, const char seperator)
{
    Vector<String> values;

    auto upconvertedCharacters = StringView(input).upconvertedCharacters();
    const UChar* ptr = upconvertedCharacters;
    const UChar* end = ptr + input.length();
    skipOptionalSVGSpaces(ptr, end);

    while (ptr < end) {
        // Leading and trailing white space, and white space before and after semicolon separators, will be ignored.
        const UChar* inputStart = ptr;
        while (ptr < end && *ptr != seperator) // careful not to ignore whitespace inside inputs
            ptr++;

        if (ptr == inputStart)
            break;

        // walk backwards from the ; to ignore any whitespace
        const UChar* inputEnd = ptr - 1;
        while (inputStart < inputEnd && isSVGSpace(*inputEnd))
            inputEnd--;

        values.append(String(inputStart, inputEnd - inputStart + 1));
        skipOptionalSVGSpacesOrDelimiter(ptr, end, seperator);
    }

    return values;
}
static void parseKeySplinesInternal(const String& string, Vector<UnitBezier>& result)
{
    const CharType* ptr = string.getCharacters<CharType>();
    const CharType* end = ptr + string.length();

    skipOptionalSVGSpaces(ptr, end);

    bool delimParsed = false;
    while (ptr < end) {
        delimParsed = false;
        float posA = 0;
        if (!parseNumber(ptr, end, posA)) {
            result.clear();
            return;
        }

        float posB = 0;
        if (!parseNumber(ptr, end, posB)) {
            result.clear();
            return;
        }

        float posC = 0;
        if (!parseNumber(ptr, end, posC)) {
            result.clear();
            return;
        }

        float posD = 0;
        if (!parseNumber(ptr, end, posD, false)) {
            result.clear();
            return;
        }

        skipOptionalSVGSpaces(ptr, end);

        if (ptr < end && *ptr == ';') {
            delimParsed = true;
            ptr++;
        }
        skipOptionalSVGSpaces(ptr, end);

        result.append(UnitBezier(posA, posB, posC, posD));
    }
    if (!(ptr == end && !delimParsed))
        result.clear();
}
static bool genericParseRect(const CharType*& ptr, const CharType* end, FloatRect& rect)
{
    skipOptionalSVGSpaces(ptr, end);

    float x = 0;
    float y = 0;
    float width = 0;
    float height = 0;
    bool valid = parseNumber(ptr, end, x) && parseNumber(ptr, end, y) && parseNumber(ptr, end, width) && parseNumber(ptr, end, height, false);
    rect = FloatRect(x, y, width, height);
    return valid;
}
Beispiel #15
0
bool parseRect(const String& string, FloatRect& rect)
{
    const UChar* ptr = string.characters();
    const UChar* end = ptr + string.length();
    skipOptionalSVGSpaces(ptr, end);
    
    float x = 0;
    float y = 0;
    float width = 0;
    float height = 0;
    bool valid = parseNumber(ptr, end, x) && parseNumber(ptr, end, y) && parseNumber(ptr, end, width) && parseNumber(ptr, end, height, false);
    rect = FloatRect(x, y, width, height);
    return valid;
}
Beispiel #16
0
void SVGPoint::parse(const CharType*& ptr, const CharType* end, ExceptionState& exceptionState)
{
    const CharType* start = ptr;

    skipOptionalSVGSpaces(ptr, end);

    float x = 0.0f;
    float y = 0.0f;
    bool valid = parseNumber(ptr, end, x) && parseNumber(ptr, end, y, DisallowWhitespace);

    if (!valid) {
        exceptionState.throwDOMException(SyntaxError, "Problem parsing point \"" + String(start, end - start) + "\"");
        return;
    }

    skipOptionalSVGSpaces(ptr, end);
    if (ptr < end) { // nothing should come after the last, fourth number
        exceptionState.throwDOMException(SyntaxError, "Problem parsing point \"" + String(start, end - start) + "\"");
        return;
    }

    m_value = FloatPoint(x, y);
}
Beispiel #17
0
bool SVGTransformList::parseInternal(const CharType*& ptr, const CharType* end)
{
    clear();

    bool delimParsed = false;
    while (ptr < end) {
        delimParsed = false;
        SVGTransformType transformType = SVG_TRANSFORM_UNKNOWN;
        skipOptionalSVGSpaces(ptr, end);

        if (!parseAndSkipTransformType(ptr, end, transformType))
            return false;

        if (!skipOptionalSVGSpaces(ptr, end) || *ptr != '(')
            return false;
        ptr++;

        RefPtr<SVGTransform> transform = parseTransformOfType(transformType, ptr, end);
        if (!transform)
            return false;

        if (!skipOptionalSVGSpaces(ptr, end) || *ptr != ')')
            return false;
        ptr++;

        append(transform.release());

        skipOptionalSVGSpaces(ptr, end);
        if (ptr < end && *ptr == ',') {
            delimParsed = true;
            ++ptr;
            skipOptionalSVGSpaces(ptr, end);
        }
    }

    return !delimParsed;
}
bool SVGFitToViewBox::parseViewBox(Document* doc, const UChar*& c, const UChar* end, FloatRect& viewBox, bool validate)
{
    String str(c, end - c);

    skipOptionalSVGSpaces(c, end);

    float x = 0.0f;
    float y = 0.0f;
    float width = 0.0f;
    float height = 0.0f;
    bool valid = parseNumber(c, end, x) && parseNumber(c, end, y) && parseNumber(c, end, width) && parseNumber(c, end, height, false);
    if (!validate) {
        viewBox = FloatRect(x, y, width, height);
        return true;
    }
    if (!valid) {
        doc->accessSVGExtensions().reportWarning("Problem parsing viewBox=\"" + str + "\"");
        return false;
    }

    if (width < 0.0) { // check that width is positive
        doc->accessSVGExtensions().reportError("A negative value for ViewBox width is not allowed");
        return false;
    }
    if (height < 0.0) { // check that height is positive
        doc->accessSVGExtensions().reportError("A negative value for ViewBox height is not allowed");
        return false;
    }
    skipOptionalSVGSpaces(c, end);
    if (c < end) { // nothing should come after the last, fourth number
        doc->accessSVGExtensions().reportWarning("Problem parsing viewBox=\"" + str + "\"");
        return false;
    }

    viewBox = FloatRect(x, y, width, height);
    return true;
}
Beispiel #19
0
SVGParsingError SVGPoint::parse(const CharType*& ptr, const CharType* end) {
  float x = 0;
  float y = 0;
  if (!parseNumber(ptr, end, x) ||
      !parseNumber(ptr, end, y, DisallowWhitespace))
    return SVGParseStatus::ExpectedNumber;

  if (skipOptionalSVGSpaces(ptr, end)) {
    // Nothing should come after the second number.
    return SVGParseStatus::TrailingGarbage;
  }

  m_value = FloatPoint(x, y);
  return SVGParseStatus::NoError;
}
static bool parsePoint(const String& s, FloatPoint& point)
{
    if (s.isEmpty())
        return false;
    auto upconvertedCharacters = StringView(s).upconvertedCharacters();
    const UChar* cur = upconvertedCharacters;
    const UChar* end = cur + s.length();
    
    if (!skipOptionalSVGSpaces(cur, end))
        return false;
    
    float x = 0;
    if (!parseNumber(cur, end, x))
        return false;
    
    float y = 0;
    if (!parseNumber(cur, end, y))
        return false;
    
    point = FloatPoint(x, y);
    
    // disallow anything except spaces at the end
    return !skipOptionalSVGSpaces(cur, end);
}
Beispiel #21
0
SVGLengthType stringToLengthType(const CharType*& ptr, const CharType* end)
{
    if (ptr == end)
        return LengthTypeNumber;

    SVGLengthType type = LengthTypeUnknown;
    const CharType firstChar = *ptr++;

    if (firstChar == '%') {
        type = LengthTypePercentage;
    } else if (isHTMLSpace<CharType>(firstChar)) {
        type = LengthTypeNumber;
    } else if (ptr < end) {
        const CharType secondChar = *ptr++;

        if (firstChar == 'p') {
            if (secondChar == 'x')
                type = LengthTypePX;
            if (secondChar == 't')
                type = LengthTypePT;
            if (secondChar == 'c')
                type = LengthTypePC;
        } else if (firstChar == 'e') {
            if (secondChar == 'm')
                type = LengthTypeEMS;
            if (secondChar == 'x')
                type = LengthTypeEXS;
        } else if (firstChar == 'c' && secondChar == 'm') {
            type = LengthTypeCM;
        } else if (firstChar == 'm' && secondChar == 'm') {
            type = LengthTypeMM;
        } else if (firstChar == 'i' && secondChar == 'n') {
            type = LengthTypeIN;
        } else if (isHTMLSpace<CharType>(firstChar) && isHTMLSpace<CharType>(secondChar)) {
            type = LengthTypeNumber;
        }
    }

    if (!skipOptionalSVGSpaces(ptr, end))
        return type;

    return LengthTypeUnknown;
}
bool genericParseNumberOrPercentage(const CharType*& ptr, const CharType* end, float& number)
{
    if (genericParseNumber(ptr, end, number, AllowLeadingWhitespace)) {
        if (ptr == end)
            return true;

        bool isPercentage = (*ptr == '%');
        if (isPercentage)
            ptr++;

        skipOptionalSVGSpaces(ptr, end);

        if (isPercentage)
            number /= 100.f;

        return ptr == end;
    }

    return false;
}
Beispiel #23
0
static bool parseGlyphName(const CharType*& ptr, const CharType* end, HashSet<String>& values)
{
    skipOptionalSVGSpaces(ptr, end);

    while (ptr < end) {
        // Leading and trailing white space, and white space before and after separators, will be ignored.
        const CharType* inputStart = ptr;
        while (ptr < end && *ptr != ',')
            ++ptr;

        if (ptr == inputStart)
            break;

        // walk backwards from the ; to ignore any whitespace
        const CharType* inputEnd = ptr - 1;
        while (inputStart < inputEnd && isSVGSpace(*inputEnd))
            --inputEnd;

        values.add(String(inputStart, inputEnd - inputStart + 1));
        skipOptionalSVGSpacesOrDelimiter(ptr, end, ',');
    }

    return true;
}
bool SVGPreserveAspectRatio::parse(const UChar*& currParam, const UChar* end, bool validate)
{
    // FIXME: Rewrite this parser, without gotos!
    if (!skipOptionalSVGSpaces(currParam, end))
        goto bailOut;

    if (*currParam == 'd') {
        if (!skipString(currParam, end, "defer"))
            goto bailOut;

        // FIXME: We just ignore the "defer" here.
        if (currParam == end)
            return true;

        if (!skipOptionalSVGSpaces(currParam, end))
            goto bailOut;
    }

    if (*currParam == 'n') {
        if (!skipString(currParam, end, "none"))
            goto bailOut;
        m_align = SVG_PRESERVEASPECTRATIO_NONE;
        skipOptionalSVGSpaces(currParam, end);
    } else if (*currParam == 'x') {
        if ((end - currParam) < 8)
            goto bailOut;
        if (currParam[1] != 'M' || currParam[4] != 'Y' || currParam[5] != 'M')
            goto bailOut;
        if (currParam[2] == 'i') {
            if (currParam[3] == 'n') {
                if (currParam[6] == 'i') {
                    if (currParam[7] == 'n')
                        m_align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
                    else if (currParam[7] == 'd')
                        m_align = SVG_PRESERVEASPECTRATIO_XMINYMID;
                    else
                        goto bailOut;
                } else if (currParam[6] == 'a' && currParam[7] == 'x')
                     m_align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
                else
                     goto bailOut;
             } else if (currParam[3] == 'd') {
                if (currParam[6] == 'i') {
                    if (currParam[7] == 'n')
                        m_align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
                    else if (currParam[7] == 'd')
                        m_align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
                    else
                        goto bailOut;
                } else if (currParam[6] == 'a' && currParam[7] == 'x')
                    m_align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
                else
                    goto bailOut;
            } else
                goto bailOut;
        } else if (currParam[2] == 'a' && currParam[3] == 'x') {
            if (currParam[6] == 'i') {
                if (currParam[7] == 'n')
                    m_align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
                else if (currParam[7] == 'd')
                    m_align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
                else
                    goto bailOut;
            } else if (currParam[6] == 'a' && currParam[7] == 'x')
                m_align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
            else
                goto bailOut;
        } else
            goto bailOut;
        currParam += 8;
        skipOptionalSVGSpaces(currParam, end);
    } else
        goto bailOut;

    if (currParam < end) {
        if (*currParam == 'm') {
            if (!skipString(currParam, end, "meet"))
                goto bailOut;
            skipOptionalSVGSpaces(currParam, end);
        } else if (*currParam == 's') {
            if (!skipString(currParam, end, "slice"))
                goto bailOut;
            skipOptionalSVGSpaces(currParam, end);
            if (m_align != SVG_PRESERVEASPECTRATIO_NONE)
                m_meetOrSlice = SVG_MEETORSLICE_SLICE;
        }
    }

    if (end != currParam && validate) {
bailOut:
        m_align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
        m_meetOrSlice = SVG_MEETORSLICE_MEET;
        return false;
    }
    return true;
}
bool SVGPreserveAspectRatio::parseInternal(const CharType*& ptr, const CharType* end, bool validate)
{
    // FIXME: Rewrite this parser, without gotos!
    if (!skipOptionalSVGSpaces(ptr, end))
        goto bailOut;

    if (*ptr == 'd') {
        if (!skipString(ptr, end, "defer"))
            goto bailOut;

        // FIXME: We just ignore the "defer" here.
        if (ptr == end)
            return true;

        if (!skipOptionalSVGSpaces(ptr, end))
            goto bailOut;
    }

    if (*ptr == 'n') {
        if (!skipString(ptr, end, "none"))
            goto bailOut;
        m_align = SVG_PRESERVEASPECTRATIO_NONE;
        skipOptionalSVGSpaces(ptr, end);
    } else if (*ptr == 'x') {
        if ((end - ptr) < 8)
            goto bailOut;
        if (ptr[1] != 'M' || ptr[4] != 'Y' || ptr[5] != 'M')
            goto bailOut;
        if (ptr[2] == 'i') {
            if (ptr[3] == 'n') {
                if (ptr[6] == 'i') {
                    if (ptr[7] == 'n')
                        m_align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
                    else if (ptr[7] == 'd')
                        m_align = SVG_PRESERVEASPECTRATIO_XMINYMID;
                    else
                        goto bailOut;
                } else if (ptr[6] == 'a' && ptr[7] == 'x')
                     m_align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
                else
                     goto bailOut;
            } else if (ptr[3] == 'd') {
                if (ptr[6] == 'i') {
                    if (ptr[7] == 'n')
                        m_align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
                    else if (ptr[7] == 'd')
                        m_align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
                    else
                        goto bailOut;
                } else if (ptr[6] == 'a' && ptr[7] == 'x')
                    m_align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
                else
                    goto bailOut;
            } else
                goto bailOut;
        } else if (ptr[2] == 'a' && ptr[3] == 'x') {
            if (ptr[6] == 'i') {
                if (ptr[7] == 'n')
                    m_align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
                else if (ptr[7] == 'd')
                    m_align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
                else
                    goto bailOut;
            } else if (ptr[6] == 'a' && ptr[7] == 'x')
                m_align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
            else
                goto bailOut;
        } else
            goto bailOut;
        ptr += 8;
        skipOptionalSVGSpaces(ptr, end);
    } else
        goto bailOut;

    if (ptr < end) {
        if (*ptr == 'm') {
            if (!skipString(ptr, end, "meet"))
                goto bailOut;
            skipOptionalSVGSpaces(ptr, end);
        } else if (*ptr == 's') {
            if (!skipString(ptr, end, "slice"))
                goto bailOut;
            skipOptionalSVGSpaces(ptr, end);
            if (m_align != SVG_PRESERVEASPECTRATIO_NONE)
                m_meetOrSlice = SVG_MEETORSLICE_SLICE;
        }
    }

    if (end != ptr && validate) {
bailOut:
        m_align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
        m_meetOrSlice = SVG_MEETORSLICE_MEET;
        return false;
    }
    return true;
}
bool SVGPreserveAspectRatio::parseInternal(const UChar*& currParam, const UChar* end, bool validate)
{
    SVGPreserveAspectRatioType align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
    SVGMeetOrSliceType meetOrSlice = SVG_MEETORSLICE_MEET;

    m_align = align;
    m_meetOrSlice = meetOrSlice;

    if (!skipOptionalSVGSpaces(currParam, end))
        return false;

    if (*currParam == 'd') {
        if (!skipString(currParam, end, "defer")) {
            LOG_ERROR("Skipped to parse except for *defer* value.");
            return false;
        }

        // FIXME: We just ignore the "defer" here.
        if (currParam == end)
            return true;

        if (!skipOptionalSVGSpaces(currParam, end))
            return false;
    }

    if (*currParam == 'n') {
        if (!skipString(currParam, end, "none")) {
            LOG_ERROR("Skipped to parse except for *none* value.");
            return false;
        }
        align = SVG_PRESERVEASPECTRATIO_NONE;
        skipOptionalSVGSpaces(currParam, end);
    } else if (*currParam == 'x') {
        if ((end - currParam) < 8)
            return false;
        if (currParam[1] != 'M' || currParam[4] != 'Y' || currParam[5] != 'M')
            return false;
        if (currParam[2] == 'i') {
            if (currParam[3] == 'n') {
                if (currParam[6] == 'i') {
                    if (currParam[7] == 'n')
                        align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
                    else if (currParam[7] == 'd')
                        align = SVG_PRESERVEASPECTRATIO_XMINYMID;
                    else
                        return false;
                } else if (currParam[6] == 'a' && currParam[7] == 'x')
                    align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
                else
                    return false;
             } else if (currParam[3] == 'd') {
                if (currParam[6] == 'i') {
                    if (currParam[7] == 'n')
                        align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
                    else if (currParam[7] == 'd')
                        align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
                    else
                        return false;
                } else if (currParam[6] == 'a' && currParam[7] == 'x')
                    align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
                else
                    return false;
            } else
                return false;
        } else if (currParam[2] == 'a' && currParam[3] == 'x') {
            if (currParam[6] == 'i') {
                if (currParam[7] == 'n')
                    align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
                else if (currParam[7] == 'd')
                    align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
                else
                    return false;
            } else if (currParam[6] == 'a' && currParam[7] == 'x')
                align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
            else
                return false;
        } else
            return false;
        currParam += 8;
        skipOptionalSVGSpaces(currParam, end);
    } else
        return false;

    if (currParam < end) {
        if (*currParam == 'm') {
            if (!skipString(currParam, end, "meet")) {
                LOG_ERROR("Skipped to parse except for *meet* or *slice* value.");
                return false;
            }
            skipOptionalSVGSpaces(currParam, end);
        } else if (*currParam == 's') {
            if (!skipString(currParam, end, "slice")) {
                LOG_ERROR("Skipped to parse except for *meet* or *slice* value.");
                return false;
            }
            skipOptionalSVGSpaces(currParam, end);
            if (align != SVG_PRESERVEASPECTRATIO_NONE)
                meetOrSlice = SVG_MEETORSLICE_SLICE;
        }
    }

    if (end != currParam && validate)
        return false;

    m_align = align;
    m_meetOrSlice = meetOrSlice;

    return true;
}
bool SVGPreserveAspectRatio::parseInternal(const CharType*& ptr, const CharType* end, bool validate)
{
    SVGPreserveAspectRatioType align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
    SVGMeetOrSliceType meetOrSlice = SVG_MEETORSLICE_MEET;

    setAlign(align);
    setMeetOrSlice(meetOrSlice);

    if (!skipOptionalSVGSpaces(ptr, end))
        return false;

    if (*ptr == 'd') {
        if (!skipString(ptr, end, "defer"))
            return false;

        // FIXME: We just ignore the "defer" here.
        if (ptr == end)
            return true;

        if (!skipOptionalSVGSpaces(ptr, end))
            return false;
    }

    if (*ptr == 'n') {
        if (!skipString(ptr, end, "none"))
            return false;
        align = SVG_PRESERVEASPECTRATIO_NONE;
        skipOptionalSVGSpaces(ptr, end);
    } else if (*ptr == 'x') {
        if ((end - ptr) < 8)
            return false;
        if (ptr[1] != 'M' || ptr[4] != 'Y' || ptr[5] != 'M')
            return false;
        if (ptr[2] == 'i') {
            if (ptr[3] == 'n') {
                if (ptr[6] == 'i') {
                    if (ptr[7] == 'n')
                        align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
                    else if (ptr[7] == 'd')
                        align = SVG_PRESERVEASPECTRATIO_XMINYMID;
                    else
                        return false;
                } else if (ptr[6] == 'a' && ptr[7] == 'x') {
                    align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
                } else {
                    return false;
                }
            } else if (ptr[3] == 'd') {
                if (ptr[6] == 'i') {
                    if (ptr[7] == 'n')
                        align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
                    else if (ptr[7] == 'd')
                        align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
                    else
                        return false;
                } else if (ptr[6] == 'a' && ptr[7] == 'x') {
                    align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } else if (ptr[2] == 'a' && ptr[3] == 'x') {
            if (ptr[6] == 'i') {
                if (ptr[7] == 'n')
                    align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
                else if (ptr[7] == 'd')
                    align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
                else
                    return false;
            } else if (ptr[6] == 'a' && ptr[7] == 'x') {
                align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
            } else {
                return false;
            }
        } else {
            return false;
        }
        ptr += 8;
        skipOptionalSVGSpaces(ptr, end);
    } else {
        return false;
    }

    if (ptr < end) {
        if (*ptr == 'm') {
            if (!skipString(ptr, end, "meet"))
                return false;
            skipOptionalSVGSpaces(ptr, end);
        } else if (*ptr == 's') {
            if (!skipString(ptr, end, "slice"))
                return false;
            skipOptionalSVGSpaces(ptr, end);
            if (align != SVG_PRESERVEASPECTRATIO_NONE)
                meetOrSlice = SVG_MEETORSLICE_SLICE;
        }
    }

    if (end != ptr && validate)
        return false;

    setAlign(align);
    setMeetOrSlice(meetOrSlice);

    return true;
}
SVGPreserveAspectRatio SVGPreserveAspectRatio::parsePreserveAspectRatio(const UChar*& currParam, const UChar* end, bool validate, bool& result)
{
    SVGPreserveAspectRatio aspectRatio;
    aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_NONE;
    aspectRatio.m_meetOrSlice = SVG_MEETORSLICE_MEET;
    result = false;

    // FIXME: Rewrite this parser, without gotos!
    if (!skipOptionalSVGSpaces(currParam, end))
        goto bailOut;

    if (*currParam == 'd') {
        if (!skipString(currParam, end, "defer"))
            goto bailOut;
        // FIXME: We just ignore the "defer" here.
        if (!skipOptionalSVGSpaces(currParam, end))
            goto bailOut;
    }

    if (*currParam == 'n') {
        if (!skipString(currParam, end, "none"))
            goto bailOut;
        skipOptionalSVGSpaces(currParam, end);
    } else if (*currParam == 'x') {
        if ((end - currParam) < 8)
            goto bailOut;
        if (currParam[1] != 'M' || currParam[4] != 'Y' || currParam[5] != 'M')
            goto bailOut;
        if (currParam[2] == 'i') {
            if (currParam[3] == 'n') {
                if (currParam[6] == 'i') {
                    if (currParam[7] == 'n')
                        aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
                    else if (currParam[7] == 'd')
                        aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMINYMID;
                    else
                        goto bailOut;
                } else if (currParam[6] == 'a' && currParam[7] == 'x')
                     aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
                else
                     goto bailOut;
             } else if (currParam[3] == 'd') {
                if (currParam[6] == 'i') {
                    if (currParam[7] == 'n')
                        aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
                    else if (currParam[7] == 'd')
                        aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
                    else
                        goto bailOut;
                } else if (currParam[6] == 'a' && currParam[7] == 'x')
                    aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
                else
                    goto bailOut;
            } else
                goto bailOut;
        } else if (currParam[2] == 'a' && currParam[3] == 'x') {
            if (currParam[6] == 'i') {
                if (currParam[7] == 'n')
                    aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
                else if (currParam[7] == 'd')
                    aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
                else
                    goto bailOut;
            } else if (currParam[6] == 'a' && currParam[7] == 'x')
                aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
            else
                goto bailOut;
        } else
            goto bailOut;
        currParam += 8;
        skipOptionalSVGSpaces(currParam, end);
    } else
        goto bailOut;

    if (currParam < end) {
        if (*currParam == 'm') {
            if (!skipString(currParam, end, "meet"))
                goto bailOut;
            skipOptionalSVGSpaces(currParam, end);
        } else if (*currParam == 's') {
            if (!skipString(currParam, end, "slice"))
                goto bailOut;
            skipOptionalSVGSpaces(currParam, end);
            if (aspectRatio.m_align != SVG_PRESERVEASPECTRATIO_NONE)
                aspectRatio.m_meetOrSlice = SVG_MEETORSLICE_SLICE;    
        }
    }

    if (end != currParam && validate) {
bailOut:
        // FIXME: Should the two values be set to UNKNOWN instead?
        aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_NONE;
        aspectRatio.m_meetOrSlice = SVG_MEETORSLICE_MEET;
    } else
        result = true;

    return aspectRatio;
}
static bool genericParseNumber(const CharType*& cursor, const CharType* end, FloatType& number, WhitespaceMode mode)
{
    FloatType integer, decimal, frac, exponent;
    int sign, expsign;

    exponent = 0;
    integer = 0;
    frac = 1;
    decimal = 0;
    sign = 1;
    expsign = 1;

    if (mode & AllowLeadingWhitespace)
        skipOptionalSVGSpaces(cursor, end);

    const CharType* ptr = cursor;
    // 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, build right-to-left
    const CharType* digitsStart = ptr;
    while (ptr < end && *ptr >= '0' && *ptr <= '9')
        ++ptr; // Advance to first non-digit.

    if (ptr != digitsStart) {
        const CharType* ptrScanIntPart = ptr - 1;
        FloatType multiplier = 1;
        while (ptrScanIntPart >= digitsStart) {
            integer += multiplier * static_cast<FloatType>(*(ptrScanIntPart--) - '0');
            multiplier *= 10;
        }
        // Bail out early if this overflows.
        if (!isValidRange(integer))
            return false;
    }

    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));
    }

    // When we get here we should have consumed either a digit for the integer
    // part or a fractional part (with at least one digit after the '.'.)
    ASSERT(digitsStart != ptr);

    // read the exponent part
    if (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 *= static_cast<FloatType>(10);
            exponent += *ptr - '0';
            ptr++;
        }
        // Make sure exponent is valid.
        if (!isValidRange(exponent) || exponent > std::numeric_limits<FloatType>::max_exponent)
            return false;
    }

    number = integer + decimal;
    number *= sign;

    if (exponent)
        number *= static_cast<FloatType>(pow(10.0, expsign * static_cast<int>(exponent)));

    // Don't return Infinity() or NaN().
    if (!isValidRange(number))
        return false;

    // A valid number has been parsed. Commit cursor.
    cursor = ptr;

    if (mode & AllowTrailingWhitespace)
        skipOptionalSVGSpacesOrDelimiter(cursor, end);

    return true;
}
bool SVGPathStringSource::moveToNextToken()
{
    if (m_is8BitSource)
        return skipOptionalSVGSpaces(m_current.m_character8, m_end.m_character8);
    return skipOptionalSVGSpaces(m_current.m_character16, m_end.m_character16);
}