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