OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "config.h" | 5 #include "config.h" |
6 #include "core/animation/LengthStyleInterpolation.h" | 6 #include "core/animation/LengthStyleInterpolation.h" |
7 | 7 |
| 8 #include "core/animation/css/CSSAnimatableValueFactory.h" |
8 #include "core/css/CSSCalculationValue.h" | 9 #include "core/css/CSSCalculationValue.h" |
9 #include "core/css/resolver/StyleBuilder.h" | 10 #include "core/css/resolver/StyleBuilder.h" |
| 11 #include "core/css/resolver/StyleResolverState.h" |
| 12 #include "platform/CalculationValue.h" |
10 | 13 |
11 namespace blink { | 14 namespace blink { |
12 | 15 |
13 bool LengthStyleInterpolation::canCreateFrom(const CSSValue& value) | 16 bool LengthStyleInterpolation::canCreateFrom(const CSSValue& value) |
14 { | 17 { |
15 if (value.isPrimitiveValue()) { | 18 if (value.isPrimitiveValue()) { |
16 const CSSPrimitiveValue& primitiveValue = blink::toCSSPrimitiveValue(val
ue); | 19 const CSSPrimitiveValue& primitiveValue = blink::toCSSPrimitiveValue(val
ue); |
17 if (primitiveValue.cssCalcValue()) | 20 if (primitiveValue.cssCalcValue()) |
18 return true; | 21 return true; |
19 | 22 |
(...skipping 25 matching lines...) Expand all Loading... |
45 listOfValues->set(i, InterpolableNumber::create(arrayOfValues.at(i))); | 48 listOfValues->set(i, InterpolableNumber::create(arrayOfValues.at(i))); |
46 listOfTypes->set(i, InterpolableNumber::create(arrayOfTypes.get(i))); | 49 listOfTypes->set(i, InterpolableNumber::create(arrayOfTypes.get(i))); |
47 } | 50 } |
48 | 51 |
49 listOfValuesAndTypes->set(0, listOfValues.release()); | 52 listOfValuesAndTypes->set(0, listOfValues.release()); |
50 listOfValuesAndTypes->set(1, listOfTypes.release()); | 53 listOfValuesAndTypes->set(1, listOfTypes.release()); |
51 | 54 |
52 return listOfValuesAndTypes.release(); | 55 return listOfValuesAndTypes.release(); |
53 } | 56 } |
54 | 57 |
| 58 bool LengthStyleInterpolation::isPixelsOrPercentOnly(const InterpolableValue& va
lue) |
| 59 { |
| 60 const InterpolableList& types = *toInterpolableList(toInterpolableList(value
).get(1)); |
| 61 bool result = false; |
| 62 for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { |
| 63 bool typeIsPresent = toInterpolableNumber(types.get(i))->value(); |
| 64 if (i == CSSPrimitiveValue::UnitTypePixels) |
| 65 result |= typeIsPresent; |
| 66 else if (i == CSSPrimitiveValue::UnitTypePercentage) |
| 67 result |= typeIsPresent; |
| 68 else if (typeIsPresent) |
| 69 return false; |
| 70 } |
| 71 return result; |
| 72 } |
| 73 |
| 74 LengthStyleInterpolation::LengthSetter LengthStyleInterpolation::lengthSetterFor
Property(CSSPropertyID property) |
| 75 { |
| 76 switch (property) { |
| 77 case CSSPropertyBottom: |
| 78 return &LayoutStyle::setBottom; |
| 79 case CSSPropertyFlexBasis: |
| 80 return &LayoutStyle::setFlexBasis; |
| 81 case CSSPropertyHeight: |
| 82 return &LayoutStyle::setHeight; |
| 83 case CSSPropertyLeft: |
| 84 return &LayoutStyle::setLeft; |
| 85 case CSSPropertyLineHeight: |
| 86 return &LayoutStyle::setLineHeight; |
| 87 case CSSPropertyMarginBottom: |
| 88 return &LayoutStyle::setMarginBottom; |
| 89 case CSSPropertyMarginLeft: |
| 90 return &LayoutStyle::setMarginLeft; |
| 91 case CSSPropertyMarginRight: |
| 92 return &LayoutStyle::setMarginRight; |
| 93 case CSSPropertyMarginTop: |
| 94 return &LayoutStyle::setMarginTop; |
| 95 case CSSPropertyMaxHeight: |
| 96 return &LayoutStyle::setMaxHeight; |
| 97 case CSSPropertyMaxWidth: |
| 98 return &LayoutStyle::setMaxWidth; |
| 99 case CSSPropertyMinHeight: |
| 100 return &LayoutStyle::setMinHeight; |
| 101 case CSSPropertyMinWidth: |
| 102 return &LayoutStyle::setMinWidth; |
| 103 case CSSPropertyMotionOffset: |
| 104 return &LayoutStyle::setMotionOffset; |
| 105 case CSSPropertyPaddingBottom: |
| 106 return &LayoutStyle::setPaddingBottom; |
| 107 case CSSPropertyPaddingLeft: |
| 108 return &LayoutStyle::setPaddingLeft; |
| 109 case CSSPropertyPaddingRight: |
| 110 return &LayoutStyle::setPaddingRight; |
| 111 case CSSPropertyPaddingTop: |
| 112 return &LayoutStyle::setPaddingTop; |
| 113 case CSSPropertyRight: |
| 114 return &LayoutStyle::setRight; |
| 115 case CSSPropertyShapeMargin: |
| 116 return &LayoutStyle::setShapeMargin; |
| 117 case CSSPropertyTop: |
| 118 return &LayoutStyle::setTop; |
| 119 case CSSPropertyWidth: |
| 120 return &LayoutStyle::setWidth; |
| 121 // These properties don't have a LayoutStyle setter with the signature void(
*)(const Length&). |
| 122 case CSSPropertyBaselineShift: |
| 123 case CSSPropertyBorderBottomWidth: |
| 124 case CSSPropertyBorderLeftWidth: |
| 125 case CSSPropertyBorderRightWidth: |
| 126 case CSSPropertyBorderTopWidth: |
| 127 case CSSPropertyFontSize: |
| 128 case CSSPropertyLetterSpacing: |
| 129 case CSSPropertyOutlineOffset: |
| 130 case CSSPropertyOutlineWidth: |
| 131 case CSSPropertyPerspective: |
| 132 case CSSPropertyStrokeDashoffset: |
| 133 case CSSPropertyVerticalAlign: |
| 134 case CSSPropertyWebkitBorderHorizontalSpacing: |
| 135 case CSSPropertyWebkitBorderVerticalSpacing: |
| 136 case CSSPropertyWebkitColumnGap: |
| 137 case CSSPropertyWebkitColumnRuleWidth: |
| 138 case CSSPropertyWebkitColumnWidth: |
| 139 case CSSPropertyWordSpacing: |
| 140 return nullptr; |
| 141 default: |
| 142 ASSERT_NOT_REACHED(); |
| 143 return nullptr; |
| 144 } |
| 145 } |
| 146 |
55 namespace { | 147 namespace { |
56 | 148 |
57 static CSSPrimitiveValue::UnitType toUnitType(int lengthUnitType) | 149 static CSSPrimitiveValue::UnitType toUnitType(int lengthUnitType) |
58 { | 150 { |
59 return static_cast<CSSPrimitiveValue::UnitType>(CSSPrimitiveValue::lengthUni
tTypeToUnitType(static_cast<CSSPrimitiveValue::LengthUnitType>(lengthUnitType)))
; | 151 return static_cast<CSSPrimitiveValue::UnitType>(CSSPrimitiveValue::lengthUni
tTypeToUnitType(static_cast<CSSPrimitiveValue::LengthUnitType>(lengthUnitType)))
; |
60 } | 152 } |
61 | 153 |
62 static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> constructCalcExpression(Pas
sRefPtrWillBeRawPtr<CSSCalcExpressionNode> previous, const InterpolableList* lis
t, size_t position) | 154 static PassRefPtrWillBeRawPtr<CSSCalcExpressionNode> constructCalcExpression(Pas
sRefPtrWillBeRawPtr<CSSCalcExpressionNode> previous, const InterpolableList* lis
t, size_t position) |
63 { | 155 { |
64 const InterpolableList* listOfValues = toInterpolableList(list->get(0)); | 156 const InterpolableList* listOfValues = toInterpolableList(list->get(0)); |
65 const InterpolableList* listOfTypes = toInterpolableList(list->get(1)); | 157 const InterpolableList* listOfTypes = toInterpolableList(list->get(1)); |
66 while (position != CSSPrimitiveValue::LengthUnitTypeCount) { | 158 while (position != CSSPrimitiveValue::LengthUnitTypeCount) { |
67 const InterpolableNumber *subValueType = toInterpolableNumber(listOfType
s->get(position)); | 159 const InterpolableNumber *subValueType = toInterpolableNumber(listOfType
s->get(position)); |
68 if (subValueType->value()) { | 160 if (subValueType->value()) { |
69 RefPtrWillBeRawPtr<CSSCalcExpressionNode> next; | 161 RefPtrWillBeRawPtr<CSSCalcExpressionNode> next; |
70 double value = toInterpolableNumber(listOfValues->get(position))->va
lue(); | 162 double value = toInterpolableNumber(listOfValues->get(position))->va
lue(); |
71 if (previous) | 163 if (previous) |
72 next = CSSCalcValue::createExpressionNode(previous, CSSCalcValue
::createExpressionNode(CSSPrimitiveValue::create(value, toUnitType(position))),
CalcAdd); | 164 next = CSSCalcValue::createExpressionNode(previous, CSSCalcValue
::createExpressionNode(CSSPrimitiveValue::create(value, toUnitType(position))),
CalcAdd); |
73 else | 165 else |
74 next = CSSCalcValue::createExpressionNode(CSSPrimitiveValue::cre
ate(value, toUnitType(position))); | 166 next = CSSCalcValue::createExpressionNode(CSSPrimitiveValue::cre
ate(value, toUnitType(position))); |
75 return constructCalcExpression(next, list, position + 1); | 167 return constructCalcExpression(next, list, position + 1); |
76 } | 168 } |
77 position++; | 169 position++; |
78 } | 170 } |
79 return previous; | 171 return previous; |
80 } | 172 } |
81 | 173 |
| 174 static double clampToRange(double x, ValueRange range) |
| 175 { |
| 176 return (range == ValueRangeNonNegative && x < 0) ? 0 : x; |
| 177 } |
| 178 |
| 179 static Length lengthFromInterpolableValue(const InterpolableValue& value, Interp
olationRange interpolationRange, float zoom) |
| 180 { |
| 181 const InterpolableList& values = *toInterpolableList(toInterpolableList(valu
e).get(0)); |
| 182 const InterpolableList& types = *toInterpolableList(toInterpolableList(value
).get(1)); |
| 183 bool hasPixels = toInterpolableNumber(types.get(CSSPrimitiveValue::UnitTypeP
ixels))->value(); |
| 184 bool hasPercent = toInterpolableNumber(types.get(CSSPrimitiveValue::UnitType
Percentage))->value(); |
| 185 |
| 186 ValueRange range = (interpolationRange == RangeNonNegative) ? ValueRangeNonN
egative : ValueRangeAll; |
| 187 PixelsAndPercent pixelsAndPercent(0, 0); |
| 188 if (hasPixels) |
| 189 pixelsAndPercent.pixels = toInterpolableNumber(values.get(CSSPrimitiveVa
lue::UnitTypePixels))->value() * zoom; |
| 190 if (hasPercent) |
| 191 pixelsAndPercent.percent = toInterpolableNumber(values.get(CSSPrimitiveV
alue::UnitTypePercentage))->value(); |
| 192 |
| 193 if (hasPixels && hasPercent) |
| 194 return Length(CalculationValue::create(pixelsAndPercent, range)); |
| 195 if (hasPixels) |
| 196 return Length(clampToRange(pixelsAndPercent.pixels, range), Fixed); |
| 197 if (hasPercent) |
| 198 return Length(clampToRange(pixelsAndPercent.percent, range), Percent); |
| 199 ASSERT_NOT_REACHED(); |
| 200 return Length(0, Fixed); |
| 201 } |
| 202 |
82 } | 203 } |
83 | 204 |
84 PassRefPtrWillBeRawPtr<CSSPrimitiveValue> LengthStyleInterpolation::fromInterpol
ableValue(const InterpolableValue& value, InterpolationRange range) | 205 PassRefPtrWillBeRawPtr<CSSPrimitiveValue> LengthStyleInterpolation::fromInterpol
ableValue(const InterpolableValue& value, InterpolationRange range) |
85 { | 206 { |
86 const InterpolableList* listOfValuesAndTypes = toInterpolableList(&value); | 207 const InterpolableList* listOfValuesAndTypes = toInterpolableList(&value); |
87 const InterpolableList* listOfValues = toInterpolableList(listOfValuesAndTyp
es->get(0)); | 208 const InterpolableList* listOfValues = toInterpolableList(listOfValuesAndTyp
es->get(0)); |
88 const InterpolableList* listOfTypes = toInterpolableList(listOfValuesAndType
s->get(1)); | 209 const InterpolableList* listOfTypes = toInterpolableList(listOfValuesAndType
s->get(1)); |
89 unsigned unitTypeCount = 0; | 210 unsigned unitTypeCount = 0; |
90 for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { | 211 for (size_t i = 0; i < CSSPrimitiveValue::LengthUnitTypeCount; i++) { |
91 const InterpolableNumber* subType = toInterpolableNumber(listOfTypes->ge
t(i)); | 212 const InterpolableNumber* subType = toInterpolableNumber(listOfTypes->ge
t(i)); |
(...skipping 18 matching lines...) Expand all Loading... |
110 } | 231 } |
111 ASSERT_NOT_REACHED(); | 232 ASSERT_NOT_REACHED(); |
112 default: | 233 default: |
113 ValueRange valueRange = (range == RangeNonNegative) ? ValueRangeNonNegat
ive : ValueRangeAll; | 234 ValueRange valueRange = (range == RangeNonNegative) ? ValueRangeNonNegat
ive : ValueRangeAll; |
114 return CSSPrimitiveValue::create(CSSCalcValue::create(constructCalcExpre
ssion(nullptr, listOfValuesAndTypes, 0), valueRange)); | 235 return CSSPrimitiveValue::create(CSSCalcValue::create(constructCalcExpre
ssion(nullptr, listOfValuesAndTypes, 0), valueRange)); |
115 } | 236 } |
116 } | 237 } |
117 | 238 |
118 void LengthStyleInterpolation::apply(StyleResolverState& state) const | 239 void LengthStyleInterpolation::apply(StyleResolverState& state) const |
119 { | 240 { |
120 StyleBuilder::applyProperty(m_id, state, fromInterpolableValue(*m_cachedValu
e.get(), m_range).get()); | 241 if (m_lengthSetter) { |
| 242 (state.style()->*m_lengthSetter)(lengthFromInterpolableValue(*m_cachedVa
lue, m_range, state.style()->effectiveZoom())); |
| 243 #if ENABLE(ASSERT) |
| 244 RefPtrWillBeRawPtr<AnimatableValue> before = CSSAnimatableValueFactory::
create(m_id, *state.style()); |
| 245 StyleBuilder::applyProperty(m_id, state, fromInterpolableValue(*m_cached
Value, m_range).get()); |
| 246 RefPtrWillBeRawPtr<AnimatableValue> after = CSSAnimatableValueFactory::c
reate(m_id, *state.style()); |
| 247 ASSERT(before->equals(*after)); |
| 248 #endif |
| 249 } else { |
| 250 StyleBuilder::applyProperty(m_id, state, fromInterpolableValue(*m_cached
Value, m_range).get()); |
| 251 } |
121 } | 252 } |
122 | 253 |
123 DEFINE_TRACE(LengthStyleInterpolation) | 254 DEFINE_TRACE(LengthStyleInterpolation) |
124 { | 255 { |
125 StyleInterpolation::trace(visitor); | 256 StyleInterpolation::trace(visitor); |
126 } | 257 } |
127 | 258 |
128 } | 259 } |
OLD | NEW |