nsresult SVGNumberList::SetValueFromString(const nsAString& aValue) { SVGNumberList temp; nsCharSeparatedTokenizerTemplate<IsSVGWhitespace> tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); nsAutoCString str; // outside loop to minimize memory churn while (tokenizer.hasMoreTokens()) { CopyUTF16toUTF8(tokenizer.nextToken(), str); // NS_ConvertUTF16toUTF8 const char *token = str.get(); if (*token == '\0') { return NS_ERROR_DOM_SYNTAX_ERR; // nothing between commas } char *end; float num = float(PR_strtod(token, &end)); if (*end != '\0' || !NS_finite(num)) { return NS_ERROR_DOM_SYNTAX_ERR; } if (!temp.AppendItem(num)) { return NS_ERROR_OUT_OF_MEMORY; } } if (tokenizer.lastTokenEndedWithSeparator()) { return NS_ERROR_DOM_SYNTAX_ERR; // trailing comma } return CopyFrom(temp); }
NS_INTERFACE_MAP_END /* Implementation */ static nsresult GetValueFromString(const nsAString &aValueAsString, bool aPercentagesAllowed, float *aValue) { 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_finite(*aValue)) { return NS_ERROR_DOM_SYNTAX_ERR; } if (*rest == '%' && aPercentagesAllowed) { *aValue /= 100; ++rest; } if (*rest == '\0') { return NS_OK; } return NS_ERROR_DOM_SYNTAX_ERR; }
float DOMSVGLength::GetValue(ErrorResult& aRv) { if (mVal) { if (mIsAnimValItem) { mSVGElement->FlushAnimations(); return mVal->GetAnimValue(mSVGElement); } return mVal->GetBaseValue(mSVGElement); } if (mIsAnimValItem && HasOwner()) { Element()->FlushAnimations(); // May make HasOwner() == false } if (HasOwner()) { float value = InternalItem().GetValueInUserUnits(Element(), Axis()); if (!NS_finite(value)) { aRv.Throw(NS_ERROR_FAILURE); } return value; } else if (mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER || mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_PX) { return mValue; } // else [SVGWG issue] Can't convert this length's value to user units // ReportToConsole aRv.Throw(NS_ERROR_FAILURE); return 0.0f; }
void SVGMarkerElement::SetOrientToAngle(SVGAngle& angle, ErrorResult& rv) { float f = angle.Value(); if (!NS_finite(f)) { rv.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR); return; } mAngleAttributes[ORIENT].SetBaseValue(f, this, true); }
float SVGLength::GetValueInSpecifiedUnit(PRUint8 aUnit, const nsSVGElement *aElement, PRUint8 aAxis) const { if (aUnit == mUnit) { return mValue; } if ((aUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER && mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_PX) || (aUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_PX && mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER)) { return mValue; } if (IsAbsoluteUnit(aUnit) && IsAbsoluteUnit(mUnit)) { return mValue * GetAbsUnitsPerAbsUnit(aUnit, mUnit); } // Otherwise we do a two step convertion via user units. This can only // succeed if aElement is non-null (although that's not sufficent to // guarantee success). float userUnitsPerCurrentUnit = GetUserUnitsPerUnit(aElement, aAxis); float userUnitsPerNewUnit = SVGLength(0.0f, aUnit).GetUserUnitsPerUnit(aElement, aAxis); NS_ASSERTION(userUnitsPerCurrentUnit >= 0 || !NS_finite(userUnitsPerCurrentUnit), "bad userUnitsPerCurrentUnit"); NS_ASSERTION(userUnitsPerNewUnit >= 0 || !NS_finite(userUnitsPerNewUnit), "bad userUnitsPerNewUnit"); float value = mValue * userUnitsPerCurrentUnit / userUnitsPerNewUnit; // userUnitsPerCurrentUnit could be infinity, or userUnitsPerNewUnit could // be zero. if (NS_finite(value)) { return value; } return std::numeric_limits<float>::quiet_NaN(); }
NS_IMETHODIMP DOMSVGLength::NewValueSpecifiedUnits(uint16_t aUnit, float aValue) { if (!NS_finite(aValue)) { return NS_ERROR_ILLEGAL_VALUE; } ErrorResult rv; NewValueSpecifiedUnits(aUnit, aValue, rv); return rv.ErrorCode(); }
NS_IMETHODIMP DOMSVGLength::SetValueInSpecifiedUnits(float aValue) { if (!NS_finite(aValue)) { return NS_ERROR_ILLEGAL_VALUE; } ErrorResult rv; SetValueInSpecifiedUnits(aValue, rv); return rv.ErrorCode(); }
void DOMSVGLength::ConvertToSpecifiedUnits(uint16_t aUnit, ErrorResult& aRv) { if (mIsAnimValItem) { aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return; } if (mVal) { mVal->ConvertToSpecifiedUnits(aUnit, mSVGElement); return; } if (!SVGLength::IsValidUnitType(aUnit)) { aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return; } if (HasOwner()) { if (InternalItem().GetUnit() == aUnit) { return; } float val = InternalItem().GetValueInSpecifiedUnit( aUnit, Element(), Axis()); if (NS_finite(val)) { AutoChangeLengthNotifier notifier(this); InternalItem().SetValueAndUnit(val, aUnit); return; } } else { SVGLength len(mValue, mUnit); float val = len.GetValueInSpecifiedUnit(aUnit, nullptr, 0); if (NS_finite(val)) { mValue = val; mUnit = aUnit; return; } } // else [SVGWG issue] Can't convert unit // ReportToConsole aRv.Throw(NS_ERROR_FAILURE); }
already_AddRefed<SVGMatrix> SVGMatrix::SkewX(float angle, ErrorResult& rv) { double ta = tan( angle*radPerDegree ); if (!NS_finite(ta)) { rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return nullptr; } const gfxMatrix& mx = Matrix(); gfxMatrix skewMx(mx.xx, mx.yx, (float) (mx.xy + mx.xx*ta), (float) (mx.yy + mx.yx*ta), mx.x0, mx.y0); nsRefPtr<SVGMatrix> matrix = new SVGMatrix(skewMx); return matrix.forget(); }
already_AddRefed<SVGMatrix> SVGMatrix::SkewY(float angle, ErrorResult& rv) { double ta = tan( angle*radPerDegree ); if (!NS_finite(ta)) { rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return nullptr; } const gfxMatrix& mx = GetMatrix(); gfxMatrix skewMx((float) (mx._11 + mx._21*ta), (float) (mx._12 + mx._22*ta), mx._21, mx._22, mx._31, mx._32); nsRefPtr<SVGMatrix> matrix = new SVGMatrix(skewMx); return matrix.forget(); }
void DOMSVGLength::SetValue(float aUserUnitValue, ErrorResult& aRv) { if (mIsAnimValItem) { aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return; } if (mVal) { mVal->SetBaseValue(aUserUnitValue, mSVGElement, true); return; } // Although the value passed in is in user units, this method does not turn // this length into a user unit length. Instead it converts the user unit // value to this length's current unit and sets that, leaving this length's // unit as it is. if (HasOwner()) { if (InternalItem().GetValueInUserUnits(Element(), Axis()) == aUserUnitValue) { return; } float uuPerUnit = InternalItem().GetUserUnitsPerUnit(Element(), Axis()); if (uuPerUnit > 0) { float newValue = aUserUnitValue / uuPerUnit; if (NS_finite(newValue)) { AutoChangeLengthNotifier notifier(this); InternalItem().SetValueAndUnit(newValue, InternalItem().GetUnit()); return; } } } else if (mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER || mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_PX) { mValue = aUserUnitValue; return; } // else [SVGWG issue] Can't convert user unit value to this length's unit // ReportToConsole aRv.Throw(NS_ERROR_FAILURE); }
PRBool SVGLength::SetValueFromString(const nsAString &aValue) { float tmpValue; PRUint16 tmpUnit; NS_ConvertUTF16toUTF8 value(aValue); const char *str = value.get(); while (*str != '\0' && IsSVGWhitespace(*str)) { ++str; } char *unit; tmpValue = float(PR_strtod(str, &unit)); if (unit != str && NS_finite(tmpValue)) { char *theRest = unit; if (*unit != '\0' && !IsSVGWhitespace(*unit)) { while (*theRest != '\0' && !IsSVGWhitespace(*theRest)) { ++theRest; } nsCAutoString unitStr(unit, theRest - unit); tmpUnit = GetUnitTypeForString(unitStr.get()); if (tmpUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN) { // nsSVGUtils::ReportToConsole return PR_FALSE; } } else { tmpUnit = nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER; } while (*theRest && IsSVGWhitespace(*theRest)) { ++theRest; } if (!*theRest) { mValue = tmpValue; mUnit = tmpUnit; return PR_TRUE; } } return PR_FALSE; }
int32_t SVGAnimatedTransformList::SMILAnimatedTransformList::ParseParameterList( const nsAString& aSpec, float* aVars, int32_t 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_finite(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; }
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_finite(*aValue)) { *aUnitType = GetUnitTypeForString(rest); if (IsValidUnitType(*aUnitType)) { return NS_OK; } } return NS_ERROR_DOM_SYNTAX_ERR; }
void SVGTransform::SetSkewY(float angle, ErrorResult& rv) { if (mIsAnimValItem) { rv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return; } if (Transform().Type() == SVG_TRANSFORM_SKEWY && Transform().Angle() == angle) { return; } if (!NS_finite(tan(angle * kRadPerDegree))) { rv.Throw(NS_ERROR_RANGE_ERR); return; } AutoChangeTransformNotifier notifier(this); DebugOnly<nsresult> result = Transform().SetSkewY(angle); MOZ_ASSERT(NS_SUCCEEDED(result), "SetSkewY unexpectedly failed"); }
nsresult SVGPointListSMILType::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 SVGPointListAndInfo& from = *static_cast<const SVGPointListAndInfo*>(aFrom.mU.mPtr); const SVGPointListAndInfo& to = *static_cast<const SVGPointListAndInfo*>(aTo.mU.mPtr); if (from.Length() != to.Length()) { // Lists in the 'values' attribute must have the same length. // SVGContentUtils::ReportToConsole return NS_ERROR_FAILURE; } // We return the root of the sum of the squares of the distances between the // points at each corresponding index. double total = 0.0; for (uint32_t i = 0; i < to.Length(); ++i) { double dx = to[i].mX - from[i].mX; double dy = to[i].mY - from[i].mY; total += dx * dx + dy * dy; } double distance = sqrt(total); if (!NS_finite(distance)) { return NS_ERROR_FAILURE; } aDistance = distance; return NS_OK; }
bool SVGLength::SetValueFromString(const nsAString &aValue) { float tmpValue; uint16_t tmpUnit; NS_ConvertUTF16toUTF8 value(aValue); const char *str = value.get(); while (*str != '\0' && IsSVGWhitespace(*str)) { ++str; } char *unit; tmpValue = float(PR_strtod(str, &unit)); if (unit != str && NS_finite(tmpValue)) { char *theRest = unit; while (*theRest != '\0' && !IsSVGWhitespace(*theRest)) { ++theRest; } tmpUnit = GetUnitTypeForString( Substring(aValue, unit - str, theRest - unit)); if (tmpUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_UNKNOWN) { // SVGContentUtils::ReportToConsole return false; } while (*theRest && IsSVGWhitespace(*theRest)) { ++theRest; } if (!*theRest) { mValue = tmpValue; mUnit = tmpUnit; return true; } } return false; }
nsresult SVGNumberListSMILType::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 SVGNumberListAndInfo& from = *static_cast<const SVGNumberListAndInfo*>(aFrom.mU.mPtr); const SVGNumberListAndInfo& to = *static_cast<const SVGNumberListAndInfo*>(aTo.mU.mPtr); if (from.Length() != to.Length()) { // Lists in the 'values' attribute must have the same length. // nsSVGUtils::ReportToConsole return NS_ERROR_FAILURE; } // We return the root of the sum of the squares of the delta between the // numbers at each correspanding index. double total = 0.0; for (PRUint32 i = 0; i < to.Length(); ++i) { double delta = to[i] - from[i]; total += delta * delta; } double distance = sqrt(total); if (!NS_finite(distance)) { return NS_ERROR_FAILURE; } aDistance = distance; return NS_OK; }
nsresult SVGPointList::SetValueFromString(const nsAString& aValue) { // The spec says that the list is parsed and accepted up to the first error // encountered, so we must call CopyFrom even if an error occurs. We still // want to throw any error code from setAttribute if there's a problem // though, so we must take care to return any error code. nsresult rv = NS_OK; SVGPointList temp; nsCharSeparatedTokenizerTemplate<IsSVGWhitespace> tokenizer(aValue, ',', nsCharSeparatedTokenizer::SEPARATOR_OPTIONAL); nsAutoCString str1, str2; // outside loop to minimize memory churn while (tokenizer.hasMoreTokens()) { CopyUTF16toUTF8(tokenizer.nextToken(), str1); const char *token1 = str1.get(); if (*token1 == '\0') { rv = NS_ERROR_DOM_SYNTAX_ERR; break; } char *end; float x = float(PR_strtod(token1, &end)); if (end == token1 || !NS_finite(x)) { rv = NS_ERROR_DOM_SYNTAX_ERR; break; } const char *token2; if (*end == '-') { // It's possible for the token to be 10-30 which has // no separator but needs to be parsed as 10, -30 token2 = end; } else { if (!tokenizer.hasMoreTokens()) { rv = NS_ERROR_DOM_SYNTAX_ERR; break; } CopyUTF16toUTF8(tokenizer.nextToken(), str2); token2 = str2.get(); if (*token2 == '\0') { rv = NS_ERROR_DOM_SYNTAX_ERR; break; } } float y = float(PR_strtod(token2, &end)); if (*end != '\0' || !NS_finite(y)) { rv = NS_ERROR_DOM_SYNTAX_ERR; break; } temp.AppendItem(SVGPoint(x, y)); } if (tokenizer.lastTokenEndedWithSeparator()) { rv = NS_ERROR_DOM_SYNTAX_ERR; // trailing comma } nsresult rv2 = CopyFrom(temp); if (NS_FAILED(rv2)) { return rv2; // prioritize OOM error code over syntax errors } return rv; }
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 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_finite(distance)) { return NS_ERROR_FAILURE; } aDistance = distance; return NS_OK; }