tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SVGPointListSMILType.cpp (6386B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "SVGPointListSMILType.h"
      8 
      9 #include <math.h>
     10 
     11 #include "SVGPointList.h"
     12 #include "mozilla/SMILValue.h"
     13 #include "nsMathUtils.h"
     14 
     15 namespace mozilla {
     16 
     17 /*static*/
     18 SVGPointListSMILType SVGPointListSMILType::sSingleton;
     19 
     20 //----------------------------------------------------------------------
     21 // nsISMILType implementation
     22 
     23 void SVGPointListSMILType::InitValue(SMILValue& aValue) const {
     24  MOZ_ASSERT(aValue.IsNull(), "Unexpected value type");
     25 
     26  aValue.mU.mPtr = new SVGPointListAndInfo();
     27  aValue.mType = this;
     28 }
     29 
     30 void SVGPointListSMILType::DestroyValue(SMILValue& aValue) const {
     31  MOZ_ASSERT(aValue.mType == this, "Unexpected SMIL value type");
     32  delete static_cast<SVGPointListAndInfo*>(aValue.mU.mPtr);
     33  aValue.mU.mPtr = nullptr;
     34  aValue.mType = SMILNullType::Singleton();
     35 }
     36 
     37 nsresult SVGPointListSMILType::Assign(SMILValue& aDest,
     38                                      const SMILValue& aSrc) const {
     39  MOZ_ASSERT(aDest.mType == aSrc.mType, "Incompatible SMIL types");
     40  MOZ_ASSERT(aDest.mType == this, "Unexpected SMIL value");
     41 
     42  const SVGPointListAndInfo* src =
     43      static_cast<const SVGPointListAndInfo*>(aSrc.mU.mPtr);
     44  SVGPointListAndInfo* dest = static_cast<SVGPointListAndInfo*>(aDest.mU.mPtr);
     45 
     46  return dest->CopyFrom(*src);
     47 }
     48 
     49 bool SVGPointListSMILType::IsEqual(const SMILValue& aLeft,
     50                                   const SMILValue& aRight) const {
     51  MOZ_ASSERT(aLeft.mType == aRight.mType, "Incompatible SMIL types");
     52  MOZ_ASSERT(aLeft.mType == this, "Unexpected type for SMIL value");
     53 
     54  return *static_cast<const SVGPointListAndInfo*>(aLeft.mU.mPtr) ==
     55         *static_cast<const SVGPointListAndInfo*>(aRight.mU.mPtr);
     56 }
     57 
     58 nsresult SVGPointListSMILType::Add(SMILValue& aDest,
     59                                   const SMILValue& aValueToAdd,
     60                                   uint32_t aCount) const {
     61  MOZ_ASSERT(aDest.mType == this, "Unexpected SMIL type");
     62  MOZ_ASSERT(aValueToAdd.mType == this, "Incompatible SMIL type");
     63 
     64  SVGPointListAndInfo& dest = *static_cast<SVGPointListAndInfo*>(aDest.mU.mPtr);
     65  const SVGPointListAndInfo& valueToAdd =
     66      *static_cast<const SVGPointListAndInfo*>(aValueToAdd.mU.mPtr);
     67 
     68  MOZ_ASSERT(dest.Element() || valueToAdd.Element(),
     69             "Target element propagation failure");
     70 
     71  if (valueToAdd.IsIdentity()) {
     72    return NS_OK;
     73  }
     74  if (dest.IsIdentity()) {
     75    if (!dest.SetLength(valueToAdd.Length())) {
     76      return NS_ERROR_OUT_OF_MEMORY;
     77    }
     78    for (uint32_t i = 0; i < dest.Length(); ++i) {
     79      dest[i] = aCount * valueToAdd[i];
     80    }
     81    dest.SetInfo(valueToAdd.Element());  // propagate target element info!
     82    return NS_OK;
     83  }
     84  MOZ_ASSERT(dest.Element() == valueToAdd.Element(),
     85             "adding values from different elements...?");
     86  if (dest.Length() != valueToAdd.Length()) {
     87    // For now we only support animation between lists with the same number of
     88    // items. SVGContentUtils::ReportToConsole
     89    return NS_ERROR_FAILURE;
     90  }
     91  for (uint32_t i = 0; i < dest.Length(); ++i) {
     92    dest[i] += aCount * valueToAdd[i];
     93  }
     94  dest.SetInfo(valueToAdd.Element());  // propagate target element info!
     95  return NS_OK;
     96 }
     97 
     98 nsresult SVGPointListSMILType::ComputeDistance(const SMILValue& aFrom,
     99                                               const SMILValue& aTo,
    100                                               double& aDistance) const {
    101  MOZ_ASSERT(aFrom.mType == this, "Unexpected SMIL type");
    102  MOZ_ASSERT(aTo.mType == this, "Incompatible SMIL type");
    103 
    104  const SVGPointListAndInfo& from =
    105      *static_cast<const SVGPointListAndInfo*>(aFrom.mU.mPtr);
    106  const SVGPointListAndInfo& to =
    107      *static_cast<const SVGPointListAndInfo*>(aTo.mU.mPtr);
    108 
    109  if (from.Length() != to.Length()) {
    110    // Lists in the 'values' attribute must have the same length.
    111    // SVGContentUtils::ReportToConsole
    112    return NS_ERROR_FAILURE;
    113  }
    114 
    115  // We return the root of the sum of the squares of the distances between the
    116  // points at each corresponding index.
    117 
    118  double total = 0.0;
    119 
    120  for (uint32_t i = 0; i < to.Length(); ++i) {
    121    double dx = to[i].mX - from[i].mX;
    122    double dy = to[i].mY - from[i].mY;
    123    total += dx * dx + dy * dy;
    124  }
    125  double distance = sqrt(total);
    126  if (!std::isfinite(distance)) {
    127    return NS_ERROR_FAILURE;
    128  }
    129  aDistance = distance;
    130 
    131  return NS_OK;
    132 }
    133 
    134 nsresult SVGPointListSMILType::Interpolate(const SMILValue& aStartVal,
    135                                           const SMILValue& aEndVal,
    136                                           double aUnitDistance,
    137                                           SMILValue& aResult) const {
    138  MOZ_ASSERT(aStartVal.mType == aEndVal.mType,
    139             "Trying to interpolate different types");
    140  MOZ_ASSERT(aStartVal.mType == this, "Unexpected types for interpolation");
    141  MOZ_ASSERT(aResult.mType == this, "Unexpected result type");
    142 
    143  const SVGPointListAndInfo& start =
    144      *static_cast<const SVGPointListAndInfo*>(aStartVal.mU.mPtr);
    145  const SVGPointListAndInfo& end =
    146      *static_cast<const SVGPointListAndInfo*>(aEndVal.mU.mPtr);
    147  SVGPointListAndInfo& result =
    148      *static_cast<SVGPointListAndInfo*>(aResult.mU.mPtr);
    149 
    150  MOZ_ASSERT(end.Element(), "Can't propagate target element");
    151  MOZ_ASSERT(start.Element() == end.Element() || !start.Element(),
    152             "Different target elements");
    153 
    154  if (start.Element() &&  // 'start' is not an "identity" value
    155      start.Length() != end.Length()) {
    156    // For now we only support animation between lists of the same length.
    157    // SVGContentUtils::ReportToConsole
    158    return NS_ERROR_FAILURE;
    159  }
    160  if (!result.SetLength(end.Length())) {
    161    return NS_ERROR_OUT_OF_MEMORY;
    162  }
    163 
    164  result.SetInfo(end.Element());  // propagate target element info!
    165 
    166  if (start.Length() != end.Length()) {
    167    MOZ_ASSERT(start.Length() == 0, "Not an identity value");
    168    for (uint32_t i = 0; i < end.Length(); ++i) {
    169      result[i] = aUnitDistance * end[i];
    170    }
    171    return NS_OK;
    172  }
    173  for (uint32_t i = 0; i < end.Length(); ++i) {
    174    result[i] = start[i] + (end[i] - start[i]) * aUnitDistance;
    175  }
    176  return NS_OK;
    177 }
    178 
    179 }  // namespace mozilla