1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "config.h"
#include "core/animation/LengthStyleInterpolation.h"
#include "core/css/CSSCalculationValue.h"
#include "core/css/resolver/StyleBuilder.h"
namespace blink {
bool LengthStyleInterpolation::canCreateFrom(const CSSValue& value)
{
if (value.isPrimitiveValue()) {
const CSSPrimitiveValue& primitiveValue = blink::toCSSPrimitiveValue(value);
if (primitiveValue.cssCalcValue())
return true;
CSSPrimitiveValue::LengthUnitType type;
// Only returns true if the type is a primitive length unit.
return CSSPrimitiveValue::unitTypeToLengthUnitType(primitiveValue.primitiveType(), type);
}
return value.isCalcValue();
}
PassOwnPtrWillBeRawPtr<InterpolableValue> LengthStyleInterpolation::lengthToInterpolableValue(const CSSValue& value)
{
OwnPtrWillBeRawPtr<InterpolableList> listOfValuesAndTypes = InterpolableList::create(2);
OwnPtrWillBeRawPtr<InterpolableList> listOfValues = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount);
OwnPtrWillBeRawPtr<InterpolableList> listOfTypes = InterpolableList::create(CSSPrimitiveValue::LengthUnitTypeCount);
const CSSPrimitiveValue& primitive = toCSSPrimitiveValue(value);
CSSLengthArray arrayOfValues;
CSSPrimitiveValue::CSSLengthTypeArray arrayOfTypes;
for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++)
arrayOfValues.append(0);
arrayOfTypes.ensureSize(CSSPrimitiveValue::LengthUnitTypeCount);
primitive.accumulateLengthArray(arrayOfValues, arrayOfTypes);
for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
listOfValues->set(i, InterpolableNumber::create(arrayOfValues.at(i)));
listOfTypes->set(i, InterpolableNumber::create(arrayOfTypes.get(i)));
}
listOfValuesAndTypes->set(0, listOfValues.release());
listOfValuesAndTypes->set(1, listOfTypes.release());
return listOfValuesAndTypes.release();
}
namespace {
static CSSPrimitiveValue::UnitType toUnitType(int lengthUnitType)
{
return static_cast<CSSPrimitiveValue::UnitType>(CSSPrimitiveValue::lengthUnitTypeToUnitType(static_cast<CSSPrimitiveValue::LengthUnitType>(lengthUnitType)));
}
static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> constructCalcExpression(PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> previous, const InterpolableList* list, size_t position)
{
const InterpolableList* listOfValues = toInterpolableList(list->get(0));
const InterpolableList* listOfTypes = toInterpolableList(list->get(1));
while (position != CSSPrimitiveValue::LengthUnitTypeCount) {
const InterpolableNumber *subValueType = toInterpolableNumber(listOfTypes->get(position));
if (subValueType->value()) {
RefPtrWillBeRawPtr<CSSCalcExpressionNode> next;
double value = toInterpolableNumber(listOfValues->get(position))->value();
if (previous)
next = CSSCalcValue::createExpressionNode(previous, CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(value, toUnitType(position))), CalcAdd);
else
next = CSSCalcValue::createExpressionNode(CSSPrimitiveValue::create(value, toUnitType(position)));
return constructCalcExpression(next, list, position + 1);
}
position++;
}
return previous;
}
}
PassRefPtrWillBeRawPtr<CSSPrimitiveValue> LengthStyleInterpolation::interpolableValueToLength(const InterpolableValue* value, ValueRange range)
{
const InterpolableList* listOfValuesAndTypes = toInterpolableList(value);
const InterpolableList* listOfValues = toInterpolableList(listOfValuesAndTypes->get(0));
const InterpolableList* listOfTypes = toInterpolableList(listOfValuesAndTypes->get(1));
unsigned unitTypeCount = 0;
for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
const InterpolableNumber* subType = toInterpolableNumber(listOfTypes->get(i));
if (subType->value()) {
unitTypeCount++;
}
}
switch (unitTypeCount) {
case 0:
// TODO: this case should never be reached. This issue should be fixed once we have multiple interpolators.
return CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_PX);
case 1:
for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) {
const InterpolableNumber *subValueType = toInterpolableNumber(listOfTypes->get(i));
if (subValueType->value()) {
double value = toInterpolableNumber(listOfValues->get(i))->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, listOfValuesAndTypes, 0), range));
}
}
void LengthStyleInterpolation::apply(StyleResolverState& state) const
{
StyleBuilder::applyProperty(m_id, state, interpolableValueToLength(m_cachedValue.get(), m_range).get());
}
void LengthStyleInterpolation::trace(Visitor* visitor)
{
StyleInterpolation::trace(visitor);
}
}
|