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); }
PassRefPtrWillBeRawPtr<CSSValue> LengthPairStyleInterpolation::interpolableValueToLengthPair(InterpolableValue* value, InterpolationRange range) { InterpolableList* lengthPair = toInterpolableList(value); RefPtrWillBeRawPtr<CSSPrimitiveValue> first = LengthStyleInterpolation::fromInterpolableValue(*lengthPair->get(0), range); RefPtrWillBeRawPtr<CSSPrimitiveValue> second = LengthStyleInterpolation::fromInterpolableValue(*lengthPair->get(1), range); return CSSValuePair::create(first.release(), second.release(), CSSValuePair::KeepIdenticalValues); }
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()); }
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; }
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()); }
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(); }
static PassRefPtrWillBeRawPtr<CSSValue> createCSSValue(const InterpolableList& values, bool hasPercentage, ValueRange range) { RefPtrWillBeRawPtr<CSSPrimitiveValue> result; size_t firstUnitIndex = CSSPrimitiveValue::LengthUnitTypeCount; size_t unitTypeCount = 0; for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { if ((hasPercentage && i == CSSPrimitiveValue::UnitTypePercentage) || toInterpolableNumber(values.get(i))->value()) { unitTypeCount++; if (unitTypeCount == 1) firstUnitIndex = i; } } switch (unitTypeCount) { case 0: return CSSPrimitiveValue::create(0, CSSPrimitiveValue::UnitType::Pixels); case 1: { double value = clampToRange(toInterpolableNumber(values.get(firstUnitIndex))->value(), range); return CSSPrimitiveValue::create(value, toUnitType(firstUnitIndex)); } default: return CSSPrimitiveValue::create(CSSCalcValue::create(createCalcExpression(values, hasPercentage), range)); } }