1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef AnimatableLength_h 32 #define AnimatableLength_h 33 34 #include "core/animation/AnimatableValue.h" 35 #include "core/css/CSSCalculationValue.h" 36 #include "core/css/CSSPrimitiveValue.h" 37 #include "platform/Length.h" 38 39 namespace WebCore { 40 41 enum NumberRange { 42 AllValues, 43 NonNegativeValues, 44 }; 45 46 // Handles animation of CSS length and percentage values including CSS calc. 47 // See primitiveUnitToNumberType() for the list of supported units. 48 // If created from a CSSPrimitiveValue this class will cache it to be returned in toCSSValue(). 49 class AnimatableLength : public AnimatableValue { 50 public: 51 enum NumberUnitType { 52 UnitTypeCalc, 53 UnitTypePixels, 54 UnitTypePercentage, 55 UnitTypeFontSize, 56 UnitTypeFontXSize, 57 UnitTypeRootFontSize, 58 UnitTypeViewportWidth, 59 UnitTypeViewportHeight, 60 UnitTypeViewportMin, 61 UnitTypeViewportMax, 62 }; 63 ~AnimatableLength()64 virtual ~AnimatableLength() { } 65 static bool canCreateFrom(const CSSValue*); 66 static PassRefPtr<AnimatableLength> create(CSSValue*); 67 static PassRefPtr<AnimatableLength> create(double number, NumberUnitType unitType, CSSPrimitiveValue* cssPrimitiveValue = 0) 68 { 69 return adoptRef(new AnimatableLength(number, unitType, cssPrimitiveValue)); 70 } 71 static PassRefPtr<AnimatableLength> create(PassRefPtr<CSSCalcExpressionNode> calcExpression, CSSPrimitiveValue* cssPrimitiveValue = 0) 72 { 73 return adoptRef(new AnimatableLength(calcExpression, cssPrimitiveValue)); 74 } 75 PassRefPtr<CSSValue> toCSSValue(NumberRange = AllValues) const; 76 Length toLength(const CSSToLengthConversionData&, NumberRange = AllValues) const; 77 78 protected: 79 virtual PassRefPtr<AnimatableValue> interpolateTo(const AnimatableValue*, double fraction) const OVERRIDE; 80 virtual PassRefPtr<AnimatableValue> addWith(const AnimatableValue*) const OVERRIDE; 81 82 private: AnimatableLength(double number,NumberUnitType unitType,CSSPrimitiveValue * cssPrimitiveValue)83 AnimatableLength(double number, NumberUnitType unitType, CSSPrimitiveValue* cssPrimitiveValue) 84 : m_number(number) 85 , m_unitType(unitType) 86 , m_cachedCSSPrimitiveValue(cssPrimitiveValue) 87 { 88 ASSERT(m_unitType != UnitTypeCalc); 89 } AnimatableLength(PassRefPtr<CSSCalcExpressionNode> calcExpression,CSSPrimitiveValue * cssPrimitiveValue)90 AnimatableLength(PassRefPtr<CSSCalcExpressionNode> calcExpression, CSSPrimitiveValue* cssPrimitiveValue) 91 : m_unitType(UnitTypeCalc) 92 , m_calcExpression(calcExpression) 93 , m_cachedCSSPrimitiveValue(cssPrimitiveValue) 94 { 95 ASSERT(m_calcExpression); 96 } type()97 virtual AnimatableType type() const OVERRIDE { return TypeLength; } 98 virtual bool equalTo(const AnimatableValue*) const OVERRIDE; 99 isCalc()100 bool isCalc() const 101 { 102 return m_unitType == UnitTypeCalc; 103 } 104 isViewportUnit()105 bool isViewportUnit() const 106 { 107 return m_unitType == UnitTypeViewportWidth || m_unitType == UnitTypeViewportHeight || m_unitType == UnitTypeViewportMin || m_unitType == UnitTypeViewportMax; 108 } 109 create(const AnimatableLength * leftAddend,const AnimatableLength * rightAddend)110 static PassRefPtr<AnimatableLength> create(const AnimatableLength* leftAddend, const AnimatableLength* rightAddend) 111 { 112 ASSERT(leftAddend && rightAddend); 113 return create(CSSCalcValue::createExpressionNode(leftAddend->toCSSCalcExpressionNode(), rightAddend->toCSSCalcExpressionNode(), CalcAdd)); 114 } 115 116 PassRefPtr<CSSPrimitiveValue> toCSSPrimitiveValue(NumberRange) const; 117 PassRefPtr<CSSCalcExpressionNode> toCSSCalcExpressionNode() const; 118 119 PassRefPtr<AnimatableLength> scale(double) const; clampedNumber(NumberRange range)120 double clampedNumber(NumberRange range) const 121 { 122 ASSERT(!isCalc()); 123 return (range == NonNegativeValues && m_number <= 0) ? 0 : m_number; 124 } 125 126 // Returns true and populates numberType, if primitiveUnit is a primitive length unit. Otherwise, returns false. 127 static bool primitiveUnitToNumberType(unsigned short primitiveUnit, NumberUnitType& numberType); 128 129 static unsigned short numberTypeToPrimitiveUnit(NumberUnitType numberType); 130 131 // Zero is effectively unitless, except in the case of percentage. 132 // http://www.w3.org/TR/css3-values/#calc-computed-value 133 // e.g. calc(100% - 100% + 1em) resolves to calc(0% + 1em), not to calc(1em) isUnitlessZero()134 bool isUnitlessZero() const 135 { 136 return !isCalc() && !m_number && m_unitType != UnitTypePercentage; 137 } 138 commonUnitType(const AnimatableLength * length)139 NumberUnitType commonUnitType(const AnimatableLength* length) const 140 { 141 if (m_unitType == length->m_unitType) 142 return m_unitType; 143 144 if (isUnitlessZero()) 145 return length->m_unitType; 146 if (length->isUnitlessZero()) 147 return m_unitType; 148 149 return UnitTypeCalc; 150 } 151 152 double m_number; 153 const NumberUnitType m_unitType; 154 155 RefPtr<CSSCalcExpressionNode> m_calcExpression; 156 157 mutable RefPtr<CSSPrimitiveValue> m_cachedCSSPrimitiveValue; 158 159 friend class AnimationAnimatableLengthTest; 160 }; 161 162 DEFINE_ANIMATABLE_VALUE_TYPE_CASTS(AnimatableLength, isLength()); 163 164 } // namespace WebCore 165 166 #endif // AnimatableLength_h 167