NS_IMETHODIMP nsSVGLength::SetValueAsString(const nsAString & aValueAsString) { nsresult rv = NS_OK; char *str = ToNewCString(aValueAsString); char* number = str; while (*number && isspace(*number)) ++number; if (*number) { char *rest; float value = float(PR_strtod(number, &rest)); if (rest!=number) { const char* unitStr = nsCRT::strtok(rest, "\x20\x9\xD\xA", &rest); PRUint16 unitType = SVG_LENGTHTYPE_UNKNOWN; if (!unitStr || *unitStr=='\0') { unitType = SVG_LENGTHTYPE_NUMBER; } else { nsCOMPtr<nsIAtom> unitAtom = do_GetAtom(unitStr); if (unitAtom == nsGkAtoms::px) unitType = SVG_LENGTHTYPE_PX; else if (unitAtom == nsGkAtoms::mm) unitType = SVG_LENGTHTYPE_MM; else if (unitAtom == nsGkAtoms::cm) unitType = SVG_LENGTHTYPE_CM; else if (unitAtom == nsGkAtoms::in) unitType = SVG_LENGTHTYPE_IN; else if (unitAtom == nsGkAtoms::pt) unitType = SVG_LENGTHTYPE_PT; else if (unitAtom == nsGkAtoms::pc) unitType = SVG_LENGTHTYPE_PC; else if (unitAtom == nsGkAtoms::em) unitType = SVG_LENGTHTYPE_EMS; else if (unitAtom == nsGkAtoms::ex) unitType = SVG_LENGTHTYPE_EXS; else if (unitAtom == nsGkAtoms::percentage) unitType = SVG_LENGTHTYPE_PERCENTAGE; } if (IsValidUnitType(unitType) && NS_FloatIsFinite(value)) { WillModify(); mValueInSpecifiedUnits = value; mSpecifiedUnitType = unitType; DidModify(); } else { // parse error // not a valid unit type rv = NS_ERROR_DOM_SYNTAX_ERR; } } else { // parse error // no number rv = NS_ERROR_DOM_SYNTAX_ERR; } } nsMemory::Free(str); return rv; }
nsresult nsSVGElement::ParseNumberOptionalNumber(const nsAString& aValue, PRUint32 aIndex1, PRUint32 aIndex2) { NS_ConvertUTF16toUTF8 value(aValue); const char *str = value.get(); if (NS_IsAsciiWhitespace(*str)) return NS_ERROR_FAILURE; char *rest; float x = float(PR_strtod(str, &rest)); float y = x; if (str == rest || !NS_FloatIsFinite(x)) { //first value was illformed return NS_ERROR_FAILURE; } if (*rest != '\0') { while (NS_IsAsciiWhitespace(*rest)) { ++rest; } if (*rest == ',') { ++rest; } y = float(PR_strtod(rest, &rest)); if (*rest != '\0' || !NS_FloatIsFinite(y)) { //second value was illformed or there was trailing content return NS_ERROR_FAILURE; } } NumberAttributesInfo numberInfo = GetNumberInfo(); numberInfo.mNumbers[aIndex1].SetBaseValue(x, this, PR_FALSE); numberInfo.mNumbers[aIndex2].SetBaseValue(y, this, PR_FALSE); return NS_OK; }
static nsresult GetValueFromString(const nsAString &aValueAsString, float *aValue, PRUint16 *aUnitType) { NS_ConvertUTF16toUTF8 value(aValueAsString); const char *str = value.get(); if (NS_IsAsciiWhitespace(*str)) return NS_ERROR_DOM_SYNTAX_ERR; char *rest; *aValue = float(PR_strtod(str, &rest)); if (rest != str && NS_FloatIsFinite(*aValue)) { *aUnitType = GetUnitTypeForString(rest); if (IsValidUnitType(*aUnitType)) { return NS_OK; } } return NS_ERROR_DOM_SYNTAX_ERR; }
PRInt32 nsSVGTransformSMILAttr::ParseParameterList(const nsAString& aSpec, float* aVars, PRInt32 aNVars) { NS_ConvertUTF16toUTF8 spec(aSpec); nsACString::const_iterator start, end; spec.BeginReading(start); spec.EndReading(end); SkipWsp(start, end); int numArgsFound = 0; while (start != end) { char const *arg = start.get(); char *argend; float f = float(PR_strtod(arg, &argend)); if (arg == argend || argend > end.get() || !NS_FloatIsFinite(f)) return -1; if (numArgsFound < aNVars) { aVars[numArgsFound] = f; } start.advance(argend - arg); numArgsFound++; SkipWsp(start, end); if (*start == ',') { ++start; SkipWsp(start, end); } } return numArgsFound; }
nsresult SVGLengthListSMILType::ComputeDistance(const nsSMILValue& aFrom, const nsSMILValue& aTo, double& aDistance) const { NS_PRECONDITION(aFrom.mType == this, "Unexpected SMIL type"); NS_PRECONDITION(aTo.mType == this, "Incompatible SMIL type"); const SVGLengthListAndInfo& from = *static_cast<const SVGLengthListAndInfo*>(aFrom.mU.mPtr); const SVGLengthListAndInfo& to = *static_cast<const SVGLengthListAndInfo*>(aTo.mU.mPtr); // To understand this code, see the comments documenting our Init() method, // and documenting SVGLengthListAndInfo::CanZeroPadList(). NS_ASSERTION((from.CanZeroPadList() == to.CanZeroPadList()) || (from.CanZeroPadList() && from.IsEmpty()) || (to.CanZeroPadList() && to.IsEmpty()), "Only \"zero\" nsSMILValues from the SMIL engine should " "return PR_TRUE for CanZeroPadList() when the attribute " "being animated can't be zero padded"); if ((from.Length() < to.Length() && !from.CanZeroPadList()) || (to.Length() < from.Length() && !to.CanZeroPadList())) { // nsSVGUtils::ReportToConsole return NS_ERROR_FAILURE; } // We return the root of the sum of the squares of the deltas between the // user unit values of the lengths at each correspanding index. In the // general case, paced animation is probably not useful, but this strategy at // least does the right thing for paced animation in the face of simple // 'values' lists such as: // // values="100 200 300; 101 201 301; 110 210 310" // // I.e. half way through the simple duration we'll get "105 205 305". double total = 0.0; PRUint32 i = 0; for (; i < from.Length() && i < to.Length(); ++i) { double f = from[i].GetValueInUserUnits(from.Element(), from.Axis()); double t = to[i].GetValueInUserUnits(to.Element(), to.Axis()); double delta = t - f; total += delta * delta; } // In the case that from.Length() != to.Length(), one of the following loops // will run. (OK since CanZeroPadList()==true for the other list.) for (; i < from.Length(); ++i) { double f = from[i].GetValueInUserUnits(from.Element(), from.Axis()); total += f * f; } for (; i < to.Length(); ++i) { double t = to[i].GetValueInUserUnits(to.Element(), to.Axis()); total += t * t; } float distance = sqrt(total); if (!NS_FloatIsFinite(distance)) { return NS_ERROR_FAILURE; } aDistance = distance; return NS_OK; }