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