bool SVGTransformable::parseTransformAttribute(SVGTransformList* list, const UChar*& currTransform, const UChar* end) { bool delimParsed = false; while (currTransform < end) { delimParsed = false; unsigned short type = SVGTransform::SVG_TRANSFORM_UNKNOWN; skipOptionalSpaces(currTransform, end); if (!parseAndSkipType(currTransform, end, type)) return false; SVGTransform t; if (!parseTransformValue(type, currTransform, end, t)) return false; ExceptionCode ec = 0; list->appendItem(t, ec); skipOptionalSpaces(currTransform, end); if (currTransform < end && *currTransform == ',') { delimParsed = true; currTransform++; } skipOptionalSpaces(currTransform, end); } return !delimParsed; }
bool SVGFitToViewBox::parseViewBox(const UChar*& c, const UChar* end, float& x, float& y, float& w, float& h, bool validate) { Document* doc = contextElement()->document(); String str(c, end - c); skipOptionalSpaces(c, end); bool valid = (parseNumber(c, end, x) && parseNumber(c, end, y) && parseNumber(c, end, w) && parseNumber(c, end, h, false)); if (!validate) return true; if (!valid) { doc->accessSVGExtensions()->reportWarning("Problem parsing viewBox=\"" + str + "\""); return false; } if (w < 0.0) { // check that width is positive doc->accessSVGExtensions()->reportError("A negative value for ViewBox width is not allowed"); return false; } else if (h < 0.0) { // check that height is positive doc->accessSVGExtensions()->reportError("A negative value for ViewBox height is not allowed"); return false; } else { skipOptionalSpaces(c, end); if (c < end) { // nothing should come after the last, fourth number doc->accessSVGExtensions()->reportWarning("Problem parsing viewBox=\"" + str + "\""); return false; } } return true; }
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; unsigned short type = SVGTransform::SVG_TRANSFORM_UNKNOWN; skipOptionalSpaces(currTransform, end); if (!parseAndSkipType(currTransform, end, type)) return false; SVGTransform transform; if (!parseTransformValue(type, currTransform, end, transform)) return false; list.append(transform); skipOptionalSpaces(currTransform, end); if (currTransform < end && *currTransform == ',') { delimParsed = true; ++currTransform; } skipOptionalSpaces(currTransform, end); } return !delimParsed; }
void SVGFitToViewBox::parseViewBox(const String& str) { double x = 0, y = 0, w = 0, h = 0; const UChar* c = str.characters(); const UChar* end = c + str.length(); Document* doc = contextElement()->document(); skipOptionalSpaces(c, end); if (!(parseNumber(c, end, x) && parseNumber(c, end, y) && parseNumber(c, end, w) && parseNumber(c, end, h, false))) { doc->accessSVGExtensions()->reportWarning("Problem parsing viewBox=\"" + str + "\""); return; } if (w < 0.0) // check that width is positive doc->accessSVGExtensions()->reportError("A negative value for ViewBox width is not allowed"); else if (h < 0.0) // check that height is positive doc->accessSVGExtensions()->reportError("A negative value for ViewBox height is not allowed"); else { skipOptionalSpaces(c, end); if (c < end) // nothing should come after the last, fourth number doc->accessSVGExtensions()->reportWarning("Problem parsing viewBox=\"" + str + "\""); else setViewBoxBaseValue(FloatRect(x, y, w, h)); } }
int parseTransformParamList(const UChar*& ptr, const UChar* end, float* values, int required, int optional) { int optionalParams = 0, requiredParams = 0; if (!skipOptionalSpaces(ptr, end) || *ptr != '(') return -1; ptr++; skipOptionalSpaces(ptr, end); while (requiredParams < required) { if (ptr >= end || !parseNumber(ptr, end, values[requiredParams], false)) return -1; requiredParams++; if (requiredParams < required) skipOptionalSpacesOrDelimiter(ptr, end); } if (!skipOptionalSpaces(ptr, end)) return -1; bool delimParsed = skipOptionalSpacesOrDelimiter(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) skipOptionalSpacesOrDelimiter(ptr, end); } if (!skipOptionalSpaces(ptr, end)) return -1; delimParsed = skipOptionalSpacesOrDelimiter(ptr, end); if (ptr >= end || *ptr != ')' || delimParsed) return -1; ptr++; } return requiredParams + optionalParams; }
Color SVGColor::colorFromRGBColorString(const String& colorString) { if (colorString.isNull()) return Color(); Color color; String parse = colorString.stripWhiteSpace(); if (parse.startsWith("rgb(")) { double r = -1, g = -1, b = -1; const UChar* ptr = parse.characters() + 4; const UChar* end = parse.characters() + parse.length(); skipOptionalSpaces(ptr, end); if (!parseNumberOrPercent(ptr, end, r) || !parseNumberOrPercent(ptr, end, g) || !parseNumberOrPercent(ptr, end, b)) return Color(); if (*ptr != ')') return Color(); ptr++; if (ptr != end) return Color(); return Color(int(r), int(g), int(b)); } return Color(parse.lower()); }
static bool parsePoint(const String& s, FloatPoint& point) { if (s.isEmpty()) return false; const UChar* cur = s.characters(); const UChar* end = cur + s.length(); if (!skipOptionalSpaces(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 !skipOptionalSpaces(cur, end); }
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 (!skipOptionalSpaces(currParam, end)) goto bail_out; if (*currParam == 'd') { if (!skipString(currParam, end, "defer")) goto bail_out; // FIXME: We just ignore the "defer" here. if (!skipOptionalSpaces(currParam, end)) goto bail_out; } if (*currParam == 'n') { if (!skipString(currParam, end, "none")) goto bail_out; skipOptionalSpaces(currParam, end); } else if (*currParam == 'x') { if ((end - currParam) < 8) goto bail_out; if (currParam[1] != 'M' || currParam[4] != 'Y' || currParam[5] != 'M') goto bail_out; 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 bail_out; } else if (currParam[6] == 'a' && currParam[7] == 'x') aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMINYMAX; else goto bail_out; } 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 bail_out; } else if (currParam[6] == 'a' && currParam[7] == 'x') aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMIDYMAX; else goto bail_out; } else goto bail_out; } 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 bail_out; } else if (currParam[6] == 'a' && currParam[7] == 'x') aspectRatio.m_align = SVG_PRESERVEASPECTRATIO_XMAXYMAX; else goto bail_out; } else goto bail_out; currParam += 8; skipOptionalSpaces(currParam, end); } else goto bail_out; if (currParam < end) { if (*currParam == 'm') { if (!skipString(currParam, end, "meet")) goto bail_out; skipOptionalSpaces(currParam, end); } else if (*currParam == 's') { if (!skipString(currParam, end, "slice")) goto bail_out; skipOptionalSpaces(currParam, end); if (aspectRatio.m_align != SVG_PRESERVEASPECTRATIO_NONE) aspectRatio.m_meetOrSlice = SVG_MEETORSLICE_SLICE; } } if (end != currParam && validate) { bail_out: // 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; }
bool SVGTransformable::parseTransformAttribute(SVGTransformList* list, const AtomicString& transform) { double x[] = {0, 0, 0, 0, 0, 0}; int nr = 0, required = 0, optional = 0; const UChar* currTransform = transform.characters(); const UChar* end = currTransform + transform.length(); bool delimParsed = false; while (currTransform < end) { delimParsed = false; unsigned short type = SVGTransform::SVG_TRANSFORM_UNKNOWN; skipOptionalSpaces(currTransform, end); if (currTransform >= end) return false; if (*currTransform == 's') { if (skipString(currTransform, end, skewXDesc, sizeof(skewXDesc) / sizeof(UChar))) { required = 1; optional = 0; type = SVGTransform::SVG_TRANSFORM_SKEWX; } else if (skipString(currTransform, end, skewYDesc, sizeof(skewYDesc) / sizeof(UChar))) { required = 1; optional = 0; type = SVGTransform::SVG_TRANSFORM_SKEWY; } else if (skipString(currTransform, end, scaleDesc, sizeof(scaleDesc) / sizeof(UChar))) { required = 1; optional = 1; type = SVGTransform::SVG_TRANSFORM_SCALE; } else return false; } else if (skipString(currTransform, end, translateDesc, sizeof(translateDesc) / sizeof(UChar))) { required = 1; optional = 1; type = SVGTransform::SVG_TRANSFORM_TRANSLATE; } else if (skipString(currTransform, end, rotateDesc, sizeof(rotateDesc) / sizeof(UChar))) { required = 1; optional = 2; type = SVGTransform::SVG_TRANSFORM_ROTATE; } else if (skipString(currTransform, end, matrixDesc, sizeof(matrixDesc) / sizeof(UChar))) { required = 6; optional = 0; type = SVGTransform::SVG_TRANSFORM_MATRIX; } else return false; if ((nr = parseTransformParamList(currTransform, end, x, required, optional)) < 0) return false; SVGTransform t; switch (type) { case SVGTransform::SVG_TRANSFORM_SKEWX: t.setSkewX(narrowPrecisionToFloat(x[0])); break; case SVGTransform::SVG_TRANSFORM_SKEWY: t.setSkewY(narrowPrecisionToFloat(x[0])); break; case SVGTransform::SVG_TRANSFORM_SCALE: if (nr == 1) // Spec: if only one param given, assume uniform scaling t.setScale(narrowPrecisionToFloat(x[0]), narrowPrecisionToFloat(x[0])); else t.setScale(narrowPrecisionToFloat(x[0]), narrowPrecisionToFloat(x[1])); break; case SVGTransform::SVG_TRANSFORM_TRANSLATE: if (nr == 1) // Spec: if only one param given, assume 2nd param to be 0 t.setTranslate(narrowPrecisionToFloat(x[0]), 0); else t.setTranslate(narrowPrecisionToFloat(x[0]), narrowPrecisionToFloat(x[1])); break; case SVGTransform::SVG_TRANSFORM_ROTATE: if (nr == 1) t.setRotate(narrowPrecisionToFloat(x[0]), 0, 0); else t.setRotate(narrowPrecisionToFloat(x[0]), narrowPrecisionToFloat(x[1]), narrowPrecisionToFloat(x[2])); break; case SVGTransform::SVG_TRANSFORM_MATRIX: t.setMatrix(AffineTransform(x[0], x[1], x[2], x[3], x[4], x[5])); break; } ExceptionCode ec = 0; list->appendItem(t, ec); skipOptionalSpaces(currTransform, end); if (currTransform < end && *currTransform == ',') { delimParsed = true; currTransform++; } skipOptionalSpaces(currTransform, end); } return !delimParsed; }