PassRefPtrWillBeRawPtr<CSSFunctionValue> FilterStyleInterpolation::fromInterpolableValue(const InterpolableValue& value, CSSValueID functionType, InterpolationRange)
{
    const InterpolableList& list = toInterpolableList(value);
    size_t length = list.length();
    RefPtrWillBeRawPtr<CSSFunctionValue> result = CSSFunctionValue::create(functionType);
    for (size_t i = 0; i < length; ++i) {
        switch (functionType) {
        case CSSValueGrayscale:
        case CSSValueInvert:
        case CSSValueOpacity:
        case CSSValueSepia:
            result->append(CSSPrimitiveValue::create(clampTo<double>(toInterpolableNumber(list.get(i))->value(), 0, 1), CSSPrimitiveValue::UnitType::Number));
            break;
        case CSSValueBrightness:
        case CSSValueContrast:
        case CSSValueSaturate:
            result->append(CSSPrimitiveValue::create(clampTo<double>(toInterpolableNumber(list.get(i))->value(), 0), CSSPrimitiveValue::UnitType::Number));
            break;
        case CSSValueHueRotate:
            result->append(CSSPrimitiveValue::create(toInterpolableNumber(list.get(i))->value(), CSSPrimitiveValue::UnitType::Degrees));
            break;
        case CSSValueBlur:
            result->append(LengthStyleInterpolation::fromInterpolableValue(*list.get(i), RangeNonNegative));
            break;
        case CSSValueDropShadow:
        case CSSValueUrl:
        default:
            ASSERT_NOT_REACHED();
            break;
        }
    }
    return result.release();
}
PassRefPtr<CSSValue> LengthStyleInterpolation::interpolableValueToLength(InterpolableValue* value, ValueRange range)
{
    InterpolableList* listValue = toInterpolableList(value);
    unsigned unitCount = 0;
    for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
        const InterpolableNumber* subValue = toInterpolableNumber(listValue->get(i));
        if (subValue->value()) {
            unitCount++;
        }
    }

    switch (unitCount) {
    case 0:
        return CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PX);
    case 1:
        for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
            const InterpolableNumber* subValue = toInterpolableNumber(listValue->get(i));
            double value = subValue->value();
            if (value) {
                if (range == ValueRangeNonNegative && value < 0)
                    value = 0;
                return CSSPrimitiveValue::create(value, toUnitType(i));
            }
        }
        ASSERT_NOT_REACHED();
    default:
        return CSSPrimitiveValue::create(CSSCalcValue::create(constructCalcExpression(nullptr, listValue, 0), range));
    }
}
static Length resolveInterpolablePixelsOrPercentageLength(const InterpolableList& values, bool hasPercentage, ValueRange range, double zoom)
{
    ASSERT(isPixelsOrPercentOnly(values));
    double pixels = toInterpolableNumber(values.get(CSSPrimitiveValue::UnitTypePixels))->value() * zoom;
    double percentage = toInterpolableNumber(values.get(CSSPrimitiveValue::UnitTypePercentage))->value();
    return createLength(pixels, percentage, hasPercentage, range);
}
Beispiel #4
0
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGNumberOptionalNumberInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const
{
    const InterpolableList& list = toInterpolableList(interpolableValue);
    return SVGNumberOptionalNumber::create(
        SVGNumber::create(toInterpolableNumber(list.get(0))->value()),
        SVGNumber::create(toInterpolableNumber(list.get(1))->value()));
}
PassRefPtrWillBeRawPtr<SVGRect> RectSVGInterpolation::fromInterpolableValue(const InterpolableValue& value)
{
    const InterpolableList& list = toInterpolableList(value);
    RefPtrWillBeRawPtr<SVGRect> result = SVGRect::create();
    result->setX(toInterpolableNumber(list.get(0))->value());
    result->setY(toInterpolableNumber(list.get(1))->value());
    result->setWidth(toInterpolableNumber(list.get(2))->value());
    result->setHeight(toInterpolableNumber(list.get(3))->value());
    return result;
}
Beispiel #6
0
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGRectInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const
{
    const InterpolableList& list = toInterpolableList(interpolableValue);
    RefPtrWillBeRawPtr<SVGRect> result = SVGRect::create();
    result->setX(toInterpolableNumber(list.get(RectX))->value());
    result->setY(toInterpolableNumber(list.get(RectY))->value());
    result->setWidth(toInterpolableNumber(list.get(RectWidth))->value());
    result->setHeight(toInterpolableNumber(list.get(RectHeight))->value());
    return result;
}
void LengthInterpolationFunctions::subtractFromOneHundredPercent(
    InterpolationValue& result) {
  InterpolableList& list = toInterpolableList(*result.interpolableValue);
  for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
    double value = -toInterpolableNumber(*list.get(i)).value();
    if (i == CSSPrimitiveValue::UnitTypePercentage)
      value += 100;
    toInterpolableNumber(*list.getMutable(i)).set(value);
  }
  result.nonInterpolableValue = CSSLengthNonInterpolableValue::create(true);
}
void InterpolableNumber::interpolate(const InterpolableValue &to, const double progress, InterpolableValue& result) const
{
    const InterpolableNumber& toNumber = toInterpolableNumber(to);
    InterpolableNumber& resultNumber = toInterpolableNumber(result);

    if (progress == 0 || m_value == toNumber.m_value)
        resultNumber.m_value = m_value;
    else if (progress == 1)
        resultNumber.m_value = toNumber.m_value;
    else
        resultNumber.m_value = m_value * (1 - progress) + toNumber.m_value * progress;
}
FilterOperation* FilterInterpolationFunctions::createFilter(
    const InterpolableValue& interpolableValue,
    const NonInterpolableValue& untypedNonInterpolableValue,
    const StyleResolverState& state) {
  const FilterNonInterpolableValue& nonInterpolableValue =
      toFilterNonInterpolableValue(untypedNonInterpolableValue);
  FilterOperation::OperationType type = nonInterpolableValue.type();

  switch (type) {
    case FilterOperation::GRAYSCALE:
    case FilterOperation::HUE_ROTATE:
    case FilterOperation::SATURATE:
    case FilterOperation::SEPIA: {
      double value =
          clampParameter(toInterpolableNumber(interpolableValue).value(), type);
      return BasicColorMatrixFilterOperation::create(value, type);
    }

    case FilterOperation::BRIGHTNESS:
    case FilterOperation::CONTRAST:
    case FilterOperation::INVERT:
    case FilterOperation::OPACITY: {
      double value =
          clampParameter(toInterpolableNumber(interpolableValue).value(), type);
      return BasicComponentTransferFilterOperation::create(value, type);
    }

    case FilterOperation::BLUR: {
      Length stdDeviation = LengthInterpolationFunctions::createLength(
          interpolableValue, nonInterpolableValue.typeNonInterpolableValue(),
          state.cssToLengthConversionData(), ValueRangeNonNegative);
      return BlurFilterOperation::create(stdDeviation);
    }

    case FilterOperation::DROP_SHADOW: {
      ShadowData shadowData = ShadowInterpolationFunctions::createShadowData(
          interpolableValue, nonInterpolableValue.typeNonInterpolableValue(),
          state);
      Color color = shadowData.color().isCurrentColor()
                        ? Color::black
                        : shadowData.color().getColor();
      return DropShadowFilterOperation::create(
          IntPoint(shadowData.x(), shadowData.y()), shadowData.blur(), color);
    }

    default:
      NOTREACHED();
      return nullptr;
  }
}
TEST_F(AnimationInterpolableValueTest, ScaleAndAddLists)
{
    OwnPtrWillBeRawPtr<InterpolableList> baseList = InterpolableList::create(3);
    baseList->set(0, InterpolableNumber::create(5));
    baseList->set(1, InterpolableNumber::create(10));
    baseList->set(2, InterpolableNumber::create(15));
    OwnPtrWillBeRawPtr<InterpolableList> addList = InterpolableList::create(3);
    addList->set(0, InterpolableNumber::create(1));
    addList->set(1, InterpolableNumber::create(2));
    addList->set(2, InterpolableNumber::create(3));
    scaleAndAdd(*baseList, 2, *addList);
    EXPECT_FLOAT_EQ(11, toInterpolableNumber(baseList->get(0))->value());
    EXPECT_FLOAT_EQ(22, toInterpolableNumber(baseList->get(1))->value());
    EXPECT_FLOAT_EQ(33, toInterpolableNumber(baseList->get(2))->value());
}
SVGPropertyBase* SVGPointListInterpolationType::appliedSVGValue(
    const InterpolableValue& interpolableValue,
    const NonInterpolableValue*) const {
  SVGPointList* result = SVGPointList::create();

  const InterpolableList& list = toInterpolableList(interpolableValue);
  DCHECK_EQ(list.length() % 2, 0U);
  for (size_t i = 0; i < list.length(); i += 2) {
    FloatPoint point =
        FloatPoint(toInterpolableNumber(list.get(i))->value(),
                   toInterpolableNumber(list.get(i + 1))->value());
    result->append(SVGPoint::create(point));
  }

  return result;
}
double consumeInterpolableCoordinateAxis(const InterpolableValue* number,
                                         bool isAbsolute,
                                         double& currentValue) {
  double previousValue = currentValue;
  currentValue = toInterpolableNumber(number)->value();
  return isAbsolute ? currentValue : currentValue - previousValue;
}
Beispiel #13
0
void PathInterpolationFunctions::composite(
    UnderlyingValueOwner& underlyingValueOwner,
    double underlyingFraction,
    const InterpolationType& type,
    const InterpolationValue& value) {
  const InterpolableList& list = toInterpolableList(*value.interpolableValue);
  double neutralComponent =
      toInterpolableNumber(list.get(PathNeutralIndex))->value();

  if (neutralComponent == 0) {
    underlyingValueOwner.set(type, value);
    return;
  }

  DCHECK(pathSegTypesMatch(
      toSVGPathNonInterpolableValue(
          *underlyingValueOwner.value().nonInterpolableValue)
          .pathSegTypes(),
      toSVGPathNonInterpolableValue(*value.nonInterpolableValue)
          .pathSegTypes()));
  underlyingValueOwner.mutableValue().interpolableValue->scaleAndAdd(
      neutralComponent, *value.interpolableValue);
  underlyingValueOwner.mutableValue().nonInterpolableValue =
      value.nonInterpolableValue.get();
}
void CSSBorderImageLengthBoxInterpolationType::apply(
    const InterpolableValue& interpolableValue,
    const NonInterpolableValue* nonInterpolableValue,
    InterpolationEnvironment& environment) const {
  const SideNumbers& sideNumbers =
      toCSSBorderImageLengthBoxNonInterpolableValue(nonInterpolableValue)
          ->sideNumbers();
  const Vector<RefPtr<NonInterpolableValue>>& nonInterpolableValues =
      toCSSBorderImageLengthBoxNonInterpolableValue(nonInterpolableValue)
          ->sideNonInterpolableValues();
  const InterpolableList& list = toInterpolableList(interpolableValue);
  const auto& convertSide =
      [&sideNumbers, &list, &environment,
       &nonInterpolableValues](size_t index) -> BorderImageLength {
    if (sideNumbers.isNumber[index])
      return clampTo<double>(toInterpolableNumber(list.get(index))->value(), 0);
    return LengthInterpolationFunctions::createLength(
        *list.get(index), nonInterpolableValues[index].get(),
        environment.state().cssToLengthConversionData(), ValueRangeNonNegative);
  };
  BorderImageLengthBox box(convertSide(SideTop), convertSide(SideRight),
                           convertSide(SideBottom), convertSide(SideLeft));
  BorderImageLengthBoxPropertyFunctions::setBorderImageLengthBox(
      cssProperty(), *environment.state().style(), box);
}
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGAngleInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const
{
    double doubleValue = toInterpolableNumber(interpolableValue).value();
    RefPtrWillBeRawPtr<SVGAngle> result = SVGAngle::create();
    result->newValueSpecifiedUnits(SVGAngle::SVG_ANGLETYPE_DEG, doubleValue);
    return result.release();
}
Beispiel #16
0
PassRefPtrWillBeRawPtr<SVGPropertyBase> SVGNumberListInterpolationType::appliedSVGValue(const InterpolableValue& interpolableValue, const NonInterpolableValue*) const
{
    RefPtrWillBeRawPtr<SVGNumberList> result = SVGNumberList::create();
    const InterpolableList& list = toInterpolableList(interpolableValue);
    for (size_t i = 0; i < list.length(); i++)
        result->append(SVGNumber::create(toInterpolableNumber(list.get(i))->value()));
    return result.release();
}
TEST_F(AnimationInterpolableValueTest, SimpleList)
{
    OwnPtrWillBeRawPtr<InterpolableList> listA = InterpolableList::create(3);
    listA->set(0, InterpolableNumber::create(0));
    listA->set(1, InterpolableNumber::create(42));
    listA->set(2, InterpolableNumber::create(20.5));

    OwnPtrWillBeRawPtr<InterpolableList> listB = InterpolableList::create(3);
    listB->set(0, InterpolableNumber::create(100));
    listB->set(1, InterpolableNumber::create(-200));
    listB->set(2, InterpolableNumber::create(300));

    RefPtrWillBeRawPtr<Interpolation> i = interpolateLists(listA.release(), listB.release(), 0.3);
    InterpolableList* outList = toInterpolableList(interpolationValue(*i.get()));
    EXPECT_FLOAT_EQ(30, toInterpolableNumber(outList->get(0))->value());
    EXPECT_FLOAT_EQ(-30.6f, toInterpolableNumber(outList->get(1))->value());
    EXPECT_FLOAT_EQ(104.35f, toInterpolableNumber(outList->get(2))->value());
}
PassRefPtrWillBeRawPtr<CSSValue> DoubleStyleInterpolation::interpolableValueToDouble(const InterpolableValue* value, bool isNumber, InterpolationRange clamp)
{
    ASSERT(value->isNumber());
    double doubleValue = clampToRange(toInterpolableNumber(value)->value(), clamp);

    if (isNumber)
        return CSSPrimitiveValue::create(doubleValue, CSSPrimitiveValue::UnitType::Number);
    return CSSPrimitiveValue::create(doubleValue, CSSPrimitiveValue::UnitType::Degrees);
}
PassRefPtrWillBeRawPtr<CSSValue> DoubleStyleInterpolation::interpolableValueToDouble(InterpolableValue* value, ClampRange clamp)
{
    ASSERT(value->isNumber());
    double doubleValue = toInterpolableNumber(value)->value();
    if (clamp == ClampOpacity) {
        doubleValue = clampTo<float>(doubleValue, 0, nextafterf(1, 0));
    }
    return CSSPrimitiveValue::create(doubleValue, CSSPrimitiveValue::CSS_NUMBER);
}
PassOwnPtrWillBeRawPtr<InterpolableValue> InterpolableNumber::interpolate(const InterpolableValue &to, const double progress) const
{
    const InterpolableNumber* toNumber = toInterpolableNumber(&to);
    if (!progress)
        return create(m_value);
    if (progress == 1)
        return create(toNumber->m_value);
    return create(m_value * (1 - progress) + toNumber->m_value * progress);
}
PathSegmentData consumeInterpolableArc(const InterpolableValue& value,
                                       SVGPathSegType segType,
                                       PathCoordinates& coordinates) {
  const InterpolableList& list = toInterpolableList(value);
  bool isAbsolute = isAbsolutePathSegType(segType);
  PathSegmentData segment;
  segment.command = segType;
  segment.targetPoint.setX(consumeInterpolableCoordinateAxis(
      list.get(0), isAbsolute, coordinates.currentX));
  segment.targetPoint.setY(consumeInterpolableCoordinateAxis(
      list.get(1), isAbsolute, coordinates.currentY));
  segment.arcRadii().setX(toInterpolableNumber(list.get(2))->value());
  segment.arcRadii().setY(toInterpolableNumber(list.get(3))->value());
  segment.setArcAngle(toInterpolableNumber(list.get(4))->value());
  segment.arcLarge = toInterpolableBool(list.get(5))->value();
  segment.arcSweep = toInterpolableBool(list.get(6))->value();
  return segment;
}
PassRefPtrWillBeRawPtr<CSSPrimitiveValue> ColorStyleInterpolation::interpolableValueToColor(const InterpolableValue& value)
{
    ASSERT(value.isList());
    const InterpolableList* list = toInterpolableList(&value);

    double alpha = toInterpolableNumber(list->get(3))->value();
    if (!alpha)
        return CSSPrimitiveValue::createColor(Color::transparent);

    // Clamping is inside makeRGBA.
    unsigned rgba = makeRGBA(
                        round(toInterpolableNumber(list->get(0))->value() / alpha),
                        round(toInterpolableNumber(list->get(1))->value() / alpha),
                        round(toInterpolableNumber(list->get(2))->value() / alpha),
                        round(alpha));

    return CSSPrimitiveValue::createColor(rgba);
}
PassRefPtrWillBeRawPtr<CSSValue> DoubleStyleInterpolation::interpolableValueToMotionRotation(InterpolableValue* value, bool flag)
{
    RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
    if (flag)
        list->append(CSSPrimitiveValue::createIdentifier(CSSValueAuto));
    ASSERT(value->isNumber());
    list->append(CSSPrimitiveValue::create(toInterpolableNumber(value)->value(), CSSPrimitiveValue::UnitType::Degrees));
    return list.release();
}
static bool isPixelsOrPercentOnly(const InterpolableList& values)
{
    for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
        if (i == CSSPrimitiveValue::UnitTypePixels || i == CSSPrimitiveValue::UnitTypePercentage)
            continue;
        if (toInterpolableNumber(values.get(i))->value())
            return false;
    }
    return true;
}
Beispiel #25
0
SVGPropertyBase* SVGNumberListInterpolationType::appliedSVGValue(
    const InterpolableValue& interpolableValue,
    const NonInterpolableValue*) const {
    SVGNumberList* result = SVGNumberList::create();
    const InterpolableList& list = toInterpolableList(interpolableValue);
    for (size_t i = 0; i < list.length(); i++)
        result->append(
            SVGNumber::create(toInterpolableNumber(list.get(i))->value()));
    return result;
}
void CSSTransformInterpolationType::apply(
    const InterpolableValue& interpolableValue,
    const NonInterpolableValue* untypedNonInterpolableValue,
    InterpolationEnvironment& environment) const {
  double progress = toInterpolableNumber(interpolableValue).value();
  const CSSTransformNonInterpolableValue& nonInterpolableValue =
      toCSSTransformNonInterpolableValue(*untypedNonInterpolableValue);
  environment.state().style()->setTransform(
      nonInterpolableValue.getInterpolatedTransform(progress));
}
Beispiel #27
0
void CSSRotateInterpolationType::apply(
    const InterpolableValue& interpolableValue,
    const NonInterpolableValue* untypedNonInterpolableValue,
    InterpolationEnvironment& environment) const {
  double progress = toInterpolableNumber(interpolableValue).value();
  const CSSRotateNonInterpolableValue& nonInterpolableValue =
      toCSSRotateNonInterpolableValue(*untypedNonInterpolableValue);
  Rotation rotation = nonInterpolableValue.slerpedRotation(progress);
  environment.state().style()->setRotate(
      RotateTransformOperation::create(rotation, TransformOperation::Rotate3D));
}
TEST_F(AnimationDoubleStyleInterpolationTest, Clamping)
{
    RefPtrWillBeRawPtr<Interpolation> interpolableDouble = DoubleStyleInterpolation::create(
        *CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER),
        *CSSPrimitiveValue::create(0.6, CSSPrimitiveValue::CSS_NUMBER),
        CSSPropertyLineHeight,
        CSSPrimitiveValue::CSS_NUMBER,
        RangeAll);
    interpolableDouble->interpolate(0, 0.4);
    // progVal = start*(1-prog) + end*prog
    EXPECT_EQ(0.24, toInterpolableNumber(getCachedValue(*interpolableDouble))->value());
}
static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> createCalcExpression(const InterpolableList& values, bool hasPercentage)
{
    RefPtrWillBeRawPtr<CSSCalcExpressionNode> result = nullptr;
    for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
        double value = toInterpolableNumber(values.get(i))->value();
        if (value || (i == CSSPrimitiveValue::UnitTypePercentage && hasPercentage)) {
            RefPtrWillBeRawPtr<CSSCalcExpressionNode> node = CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(value, toUnitType(i)));
            result = result ? CSSCalcValue::createExpressionNode(result.release(), node.release(), CalcAdd) : node.release();
        }
    }
    ASSERT(result);
    return result.release();
}
TEST_F(AnimationInterpolableValueTest, NestedList)
{
    OwnPtrWillBeRawPtr<InterpolableList> listA = InterpolableList::create(3);
    listA->set(0, InterpolableNumber::create(0));
    OwnPtrWillBeRawPtr<InterpolableList> subListA = InterpolableList::create(1);
    subListA->set(0, InterpolableNumber::create(100));
    listA->set(1, subListA.release());
    listA->set(2, InterpolableBool::create(false));

    OwnPtrWillBeRawPtr<InterpolableList> listB = InterpolableList::create(3);
    listB->set(0, InterpolableNumber::create(100));
    OwnPtrWillBeRawPtr<InterpolableList> subListB = InterpolableList::create(1);
    subListB->set(0, InterpolableNumber::create(50));
    listB->set(1, subListB.release());
    listB->set(2, InterpolableBool::create(true));

    RefPtrWillBeRawPtr<Interpolation> i = interpolateLists(listA.release(), listB.release(), 0.5);
    InterpolableList* outList = toInterpolableList(interpolationValue(*i.get()));
    EXPECT_FLOAT_EQ(50, toInterpolableNumber(outList->get(0))->value());
    EXPECT_FLOAT_EQ(75, toInterpolableNumber(toInterpolableList(outList->get(1))->get(0))->value());
    EXPECT_TRUE(toInterpolableBool(outList->get(2))->value());
}