From 1aed554cfafa10b6f5e046956d01aac21fce3737 Mon Sep 17 00:00:00 2001 From: "vladimir%pobox.com" Date: Fri, 2 Sep 2005 20:24:24 +0000 Subject: [PATCH] b=306088, simplify nssvgtransformlist::setvaluestring, r=tor --- .../svg/content/src/nsSVGTransformList.cpp | 170 +++++++++--------- content/svg/content/src/nsSVGTransformList.h | 1 + 2 files changed, 89 insertions(+), 82 deletions(-) diff --git a/content/svg/content/src/nsSVGTransformList.cpp b/content/svg/content/src/nsSVGTransformList.cpp index 4822ab7e7f80..876489410faa 100644 --- a/content/svg/content/src/nsSVGTransformList.cpp +++ b/content/svg/content/src/nsSVGTransformList.cpp @@ -140,7 +140,6 @@ nsSVGTransformList::SetValueString(const nsAString& aValue) char* args; const char* delimiters1 = "\x20\x9\xD\xA,("; const char* delimiters2 = "()"; - const char* delimiters3 = "\x20\x9\xD\xA,"; nsCOMArray xforms; while ((keyword = nsCRT::strtok(rest, delimiters1, &rest))) { @@ -162,123 +161,82 @@ nsSVGTransformList::SetValueString(const nsAString& aValue) nsCOMPtr keyatom = do_GetAtom(keyword); if (keyatom == nsSVGAtoms::translate) { - char* arg1 = nsCRT::strtok(args, delimiters3, &args); - if (!arg1) { + // tx [ty=0] + float t[2] = { 0.f }; + PRInt32 num_parsed = ParseParameterList(args, t, 2); + if (num_parsed != 1 && num_parsed != 2) { rv = NS_ERROR_FAILURE; break; // parse error } - char* arg2 = nsCRT::strtok(args, delimiters3, &args); - char* end; - float tx = (float) PR_strtod(arg1, &end); - float ty = arg2 ? (float) PR_strtod(arg2, &end) : 0.0f; - transform->SetTranslate(tx, ty); + + transform->SetTranslate(t[0], t[1]); } else if (keyatom == nsSVGAtoms::scale) { - char* arg1 = nsCRT::strtok(args, delimiters3, &args); - if (!arg1) { + // sx [sy=sx] + float s[2] = { 0.f }; + PRInt32 num_parsed = ParseParameterList(args, s, 2); + if (num_parsed != 1 && num_parsed != 2) { rv = NS_ERROR_FAILURE; break; // parse error } - char* arg2 = nsCRT::strtok(args, delimiters3, &args); - char* end; - float sx = (float) PR_strtod(arg1, &end); - float sy = arg2 ? (float) PR_strtod(arg2, &end) : sx; - transform->SetScale(sx, sy); - } + + if (num_parsed == 1) + s[1] = s[0]; + + transform->SetScale(s[0], s[1]); + } else if (keyatom == nsSVGAtoms::rotate) { - char* arg1 = nsCRT::strtok(args, delimiters3, &args); - if (!arg1) { + // r [x0=0 y0=0] + float r[3] = { 0.f }; + PRInt32 num_parsed = ParseParameterList(args, r, 3); + if (num_parsed != 1 && num_parsed != 3) { rv = NS_ERROR_FAILURE; break; // parse error } - char* arg2 = nsCRT::strtok(args, delimiters3, &args); - char* arg3 = arg2 ? nsCRT::strtok(args, delimiters3, &args) : nsnull; - if (arg2 && !arg3) { - rv = NS_ERROR_FAILURE; - break; // parse error - } - char* end; - float angle = (float) PR_strtod(arg1, &end); - float cx = arg2 ? (float) PR_strtod(arg2, &end) : 0.0f; - float cy = arg3 ? (float) PR_strtod(arg3, &end) : 0.0f; - transform->SetRotate(angle, cx, cy); - } + + transform->SetRotate(r[0], r[1], r[2]); + } else if (keyatom == nsSVGAtoms::skewX) { - char* arg1 = nsCRT::strtok(args, delimiters3, &args); - if (!arg1) { + // x-angle + float angle; + PRInt32 num_parsed = ParseParameterList(args, &angle, 1); + if (num_parsed != 1) { rv = NS_ERROR_FAILURE; break; // parse error } - - char* end; - float angle = (float) PR_strtod(arg1, &end); + transform->SetSkewX(angle); - } + } else if (keyatom == nsSVGAtoms::skewY) { - char* arg1 = nsCRT::strtok(args, delimiters3, &args); - if (!arg1) { + // y-angle + float angle; + PRInt32 num_parsed = ParseParameterList(args, &angle, 1); + if (num_parsed != 1) { rv = NS_ERROR_FAILURE; break; // parse error } - char* end; - float angle = (float) PR_strtod(arg1, &end); + transform->SetSkewY(angle); } else if (keyatom == nsSVGAtoms::matrix) { - char *arg, *end; - - arg = nsCRT::strtok(args, delimiters3, &args); - if (!arg) { + // a b c d e f + float m[6]; + PRInt32 num_parsed = ParseParameterList(args, m, 6); + if (num_parsed != 6) { rv = NS_ERROR_FAILURE; break; // parse error } - float a = (float) PR_strtod(arg, &end); - - arg = nsCRT::strtok(args, delimiters3, &args); - if (!arg) { - rv = NS_ERROR_FAILURE; - break; // parse error - } - float b = (float) PR_strtod(arg, &end); - - arg = nsCRT::strtok(args, delimiters3, &args); - if (!arg) { - rv = NS_ERROR_FAILURE; - break; // parse error - } - float c = (float) PR_strtod(arg, &end); - - arg = nsCRT::strtok(args, delimiters3, &args); - if (!arg) { - rv = NS_ERROR_FAILURE; - break; // parse error - } - float d = (float) PR_strtod(arg, &end); - - arg = nsCRT::strtok(args, delimiters3, &args); - if (!arg) { - rv = NS_ERROR_FAILURE; - break; // parse error - } - float e = (float) PR_strtod(arg, &end); - - arg = nsCRT::strtok(args, delimiters3, &args); - if (!arg) { - rv = NS_ERROR_FAILURE; - break; // parse error - } - float f = (float) PR_strtod(arg, &end); nsCOMPtr matrix; NS_NewSVGMatrix(getter_AddRefs(matrix), - a, b, c, d, e, f); + m[0], m[1], m[2], m[3], m[4], m[5]); NS_ASSERTION(matrix, "couldn't create matrix"); transform->SetMatrix(matrix); } else { // parse error rv = NS_ERROR_FAILURE; break; - } + } xforms.AppendObject(transform); } @@ -302,6 +260,54 @@ nsSVGTransformList::SetValueString(const nsAString& aValue) return rv; } +// helper for SetValueString +// parse up to nvars comma-separated parameters into vars, returning +// the number of variables actually provided. +// +// -1 will be returned if any of the arguments can't be converted to a +// float. The return value may be higher than nvars, if more +// arguments were provided; no attempt is made to actually parse any +// more arguments than nvars. +// +// note that this would accept ",,," and will just return 0 +// arguments found, instead of -1. This is because the numeric +// values can have spaces surrounding them, but the spaces can also +// be used as delimiters. strtok doesn't tell us what the +// delimiter is, so we have no way to distinguish +// ' 20,20 ' from ',,20,20,,' (or from ',,20 20,,', for that matter). +// +// XXX If someone knows for sure that it's not ok to mix commas and +// spaces as delimiters, then we can scan the string for a comma, +// and if found use a delimiter of just ",", otherwise use a set of +// spaces (without a comma). +PRInt32 +nsSVGTransformList::ParseParameterList(char *paramstr, float *vars, PRInt32 nvars) +{ + if (!paramstr) + return 0; + + char *arg, *argend, *argrest = paramstr; + int num_args_found = 0; + float f; + + const char* arg_delimiters = "\x20\x09\x0d\x0a,"; + + while ((arg = nsCRT::strtok(argrest, arg_delimiters, &argrest))) { + if (num_args_found < nvars) { + f = (float) PR_strtod(arg, &argend); + if (arg == argend) + return -1; + + vars[num_args_found] = f; + } + + arg = argrest; + num_args_found++; + } + + return num_args_found; +} + NS_IMETHODIMP nsSVGTransformList::GetValueString(nsAString& aValue) { diff --git a/content/svg/content/src/nsSVGTransformList.h b/content/svg/content/src/nsSVGTransformList.h index addf958d3233..91bd6757f664 100644 --- a/content/svg/content/src/nsSVGTransformList.h +++ b/content/svg/content/src/nsSVGTransformList.h @@ -83,6 +83,7 @@ public: PRBool AppendElement(nsIDOMSVGTransform* aElement); protected: + PRInt32 ParseParameterList(char *paramstr, float *vars, PRInt32 nvars); void ReleaseTransforms(); nsAutoVoidArray mTransforms;