Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 5
0
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();
}
Ejemplo n.º 6
0
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();
}
Ejemplo n.º 7
0
NS_IMETHODIMP
DOMSVGLength::SetValueInSpecifiedUnits(float aValue)
{
  if (!NS_finite(aValue)) {
    return NS_ERROR_ILLEGAL_VALUE;
  }

  ErrorResult rv;
  SetValueInSpecifiedUnits(aValue, rv);
  return rv.ErrorCode();
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
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();
}
Ejemplo n.º 10
0
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();
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 19
0
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;
}