OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "core/animation/LengthListPropertyFunctions.h" | 5 #include "core/animation/LengthListPropertyFunctions.h" |
6 | 6 |
7 #include "core/style/ComputedStyle.h" | 7 #include "core/style/ComputedStyle.h" |
8 | 8 |
9 namespace blink { | 9 namespace blink { |
10 | 10 |
11 namespace { | 11 namespace { |
12 | 12 |
13 const FillLayer* getFillLayer(CSSPropertyID property, const ComputedStyle& style
) | 13 const FillLayer* getFillLayer(CSSPropertyID property, const ComputedStyle& style
) |
14 { | 14 { |
15 switch (property) { | 15 switch (property) { |
16 case CSSPropertyBackgroundPositionX: | 16 case CSSPropertyBackgroundPositionX: |
17 case CSSPropertyBackgroundPositionY: | 17 case CSSPropertyBackgroundPositionY: |
| 18 case CSSPropertyBackgroundSize: |
18 return &style.backgroundLayers(); | 19 return &style.backgroundLayers(); |
19 case CSSPropertyWebkitMaskPositionX: | 20 case CSSPropertyWebkitMaskPositionX: |
20 case CSSPropertyWebkitMaskPositionY: | 21 case CSSPropertyWebkitMaskPositionY: |
| 22 case CSSPropertyWebkitMaskSize: |
21 return &style.maskLayers(); | 23 return &style.maskLayers(); |
22 default: | 24 default: |
23 ASSERT_NOT_REACHED(); | 25 ASSERT_NOT_REACHED(); |
24 return nullptr; | 26 return nullptr; |
25 } | 27 } |
26 } | 28 } |
27 | 29 |
28 FillLayer* accessFillLayer(CSSPropertyID property, ComputedStyle& style) | 30 FillLayer* accessFillLayer(CSSPropertyID property, ComputedStyle& style) |
29 { | 31 { |
30 switch (property) { | 32 switch (property) { |
31 case CSSPropertyBackgroundPositionX: | 33 case CSSPropertyBackgroundPositionX: |
32 case CSSPropertyBackgroundPositionY: | 34 case CSSPropertyBackgroundPositionY: |
| 35 case CSSPropertyBackgroundSize: |
33 return &style.accessBackgroundLayers(); | 36 return &style.accessBackgroundLayers(); |
34 case CSSPropertyWebkitMaskPositionX: | 37 case CSSPropertyWebkitMaskPositionX: |
35 case CSSPropertyWebkitMaskPositionY: | 38 case CSSPropertyWebkitMaskPositionY: |
| 39 case CSSPropertyWebkitMaskSize: |
36 return &style.accessMaskLayers(); | 40 return &style.accessMaskLayers(); |
37 default: | 41 default: |
38 ASSERT_NOT_REACHED(); | 42 ASSERT_NOT_REACHED(); |
39 return nullptr; | 43 return nullptr; |
40 } | 44 } |
41 } | 45 } |
42 | 46 |
43 struct FillLayerMethods { | 47 struct FillLayerMethods { |
44 FillLayerMethods(CSSPropertyID property) | 48 FillLayerMethods(CSSPropertyID property) |
45 { | 49 { |
| 50 isSet = nullptr; |
| 51 getLength = nullptr; |
| 52 setLength = nullptr; |
| 53 getFillSize = nullptr; |
| 54 setFillSize = nullptr; |
| 55 clear = nullptr; |
46 switch (property) { | 56 switch (property) { |
47 case CSSPropertyBackgroundPositionX: | 57 case CSSPropertyBackgroundPositionX: |
48 case CSSPropertyWebkitMaskPositionX: | 58 case CSSPropertyWebkitMaskPositionX: |
49 isSet = &FillLayer::isXPositionSet; | 59 isSet = &FillLayer::isXPositionSet; |
50 get = &FillLayer::xPosition; | 60 getLength = &FillLayer::xPosition; |
51 set = &FillLayer::setXPosition; | 61 setLength = &FillLayer::setXPosition; |
52 clear = &FillLayer::clearXPosition; | 62 clear = &FillLayer::clearXPosition; |
53 break; | 63 break; |
54 case CSSPropertyBackgroundPositionY: | 64 case CSSPropertyBackgroundPositionY: |
55 case CSSPropertyWebkitMaskPositionY: | 65 case CSSPropertyWebkitMaskPositionY: |
56 isSet = &FillLayer::isYPositionSet; | 66 isSet = &FillLayer::isYPositionSet; |
57 get = &FillLayer::yPosition; | 67 getLength = &FillLayer::yPosition; |
58 set = &FillLayer::setYPosition; | 68 setLength = &FillLayer::setYPosition; |
59 clear = &FillLayer::clearYPosition; | 69 clear = &FillLayer::clearYPosition; |
60 break; | 70 break; |
| 71 case CSSPropertyBackgroundSize: |
| 72 case CSSPropertyWebkitMaskSize: |
| 73 isSet = &FillLayer::isSizeSet; |
| 74 getFillSize = &FillLayer::size; |
| 75 setFillSize = &FillLayer::setSize; |
| 76 clear = &FillLayer::clearSize; |
| 77 break; |
61 default: | 78 default: |
62 ASSERT_NOT_REACHED(); | 79 ASSERT_NOT_REACHED(); |
63 isSet = nullptr; | |
64 get = nullptr; | |
65 set = nullptr; | |
66 clear = nullptr; | |
67 break; | 80 break; |
68 } | 81 } |
69 } | 82 } |
70 | 83 |
71 bool (FillLayer::*isSet)() const; | 84 bool (FillLayer::*isSet)() const; |
72 const Length& (FillLayer::*get)() const; | 85 const Length& (FillLayer::*getLength)() const; |
73 void (FillLayer::*set)(const Length&); | 86 void (FillLayer::*setLength)(const Length&); |
| 87 FillSize (FillLayer::*getFillSize)() const; |
| 88 void (FillLayer::*setFillSize)(const FillSize&); |
74 void (FillLayer::*clear)(); | 89 void (FillLayer::*clear)(); |
75 }; | 90 }; |
76 | 91 |
77 } // namespace | 92 } // namespace |
78 | 93 |
79 ValueRange LengthListPropertyFunctions::valueRange(CSSPropertyID property) | 94 ValueRange LengthListPropertyFunctions::valueRange(CSSPropertyID property) |
80 { | 95 { |
81 switch (property) { | 96 switch (property) { |
82 case CSSPropertyBackgroundPositionX: | 97 case CSSPropertyBackgroundPositionX: |
83 case CSSPropertyBackgroundPositionY: | 98 case CSSPropertyBackgroundPositionY: |
84 case CSSPropertyObjectPosition: | 99 case CSSPropertyObjectPosition: |
85 case CSSPropertyPerspectiveOrigin: | 100 case CSSPropertyPerspectiveOrigin: |
86 case CSSPropertyTransformOrigin: | 101 case CSSPropertyTransformOrigin: |
87 case CSSPropertyWebkitMaskPositionX: | 102 case CSSPropertyWebkitMaskPositionX: |
88 case CSSPropertyWebkitMaskPositionY: | 103 case CSSPropertyWebkitMaskPositionY: |
89 return ValueRangeAll; | 104 return ValueRangeAll; |
90 | 105 |
| 106 case CSSPropertyBackgroundSize: |
91 case CSSPropertyBorderBottomLeftRadius: | 107 case CSSPropertyBorderBottomLeftRadius: |
92 case CSSPropertyBorderBottomRightRadius: | 108 case CSSPropertyBorderBottomRightRadius: |
93 case CSSPropertyBorderTopLeftRadius: | 109 case CSSPropertyBorderTopLeftRadius: |
94 case CSSPropertyBorderTopRightRadius: | 110 case CSSPropertyBorderTopRightRadius: |
95 case CSSPropertyStrokeDasharray: | 111 case CSSPropertyStrokeDasharray: |
| 112 case CSSPropertyWebkitMaskSize: |
96 return ValueRangeNonNegative; | 113 return ValueRangeNonNegative; |
97 | 114 |
98 default: | 115 default: |
99 ASSERT_NOT_REACHED(); | 116 ASSERT_NOT_REACHED(); |
100 return ValueRangeAll; | 117 return ValueRangeAll; |
101 } | 118 } |
102 } | 119 } |
103 | 120 |
104 Vector<Length> LengthListPropertyFunctions::getInitialLengthList(CSSPropertyID p
roperty) | 121 bool LengthListPropertyFunctions::getInitialLengthList(CSSPropertyID property, V
ector<Length>& result) |
105 { | 122 { |
106 return getLengthList(property, *ComputedStyle::initialStyle()); | 123 return getLengthList(property, *ComputedStyle::initialStyle(), result); |
107 } | 124 } |
108 | 125 |
109 static Vector<Length> toVector(const LengthPoint& point) | 126 static bool appendToVector(const LengthPoint& point, Vector<Length>& result) |
110 { | 127 { |
111 Vector<Length> result(2); | 128 result.append(point.x()); |
112 result[0] = point.x(); | 129 result.append(point.y()); |
113 result[1] = point.y(); | 130 return true; |
114 return result; | |
115 } | 131 } |
116 | 132 |
117 static Vector<Length> toVector(const LengthSize& size) | 133 static bool appendToVector(const LengthSize& size, Vector<Length>& result) |
118 { | 134 { |
119 Vector<Length> result(2); | 135 result.append(size.width()); |
120 result[0] = size.width(); | 136 result.append(size.height()); |
121 result[1] = size.height(); | 137 return true; |
122 return result; | |
123 } | 138 } |
124 | 139 |
125 static Vector<Length> toVector(const TransformOrigin& transformOrigin) | 140 static bool appendToVector(const TransformOrigin& transformOrigin, Vector<Length
>& result) |
126 { | 141 { |
127 Vector<Length> result(3); | 142 result.append(transformOrigin.x()); |
128 result[0] = transformOrigin.x(); | 143 result.append(transformOrigin.y()); |
129 result[1] = transformOrigin.y(); | 144 result.append(Length(transformOrigin.z(), Fixed)); |
130 result[2] = Length(transformOrigin.z(), Fixed); | 145 return true; |
131 return result; | |
132 } | 146 } |
133 | 147 |
134 Vector<Length> LengthListPropertyFunctions::getLengthList(CSSPropertyID property
, const ComputedStyle& style) | 148 bool LengthListPropertyFunctions::getLengthList(CSSPropertyID property, const Co
mputedStyle& style, Vector<Length>& result) |
135 { | 149 { |
| 150 ASSERT(result.isEmpty()); |
| 151 |
136 switch (property) { | 152 switch (property) { |
137 case CSSPropertyStrokeDasharray: { | 153 case CSSPropertyStrokeDasharray: { |
138 if (style.strokeDashArray()) | 154 if (style.strokeDashArray()) |
139 return style.strokeDashArray()->vector(); | 155 result.appendVector(style.strokeDashArray()->vector()); |
140 return Vector<Length>(); | 156 return true; |
141 } | |
142 case CSSPropertyObjectPosition: | |
143 return toVector(style.objectPosition()); | |
144 case CSSPropertyPerspectiveOrigin: | |
145 return toVector(style.perspectiveOrigin()); | |
146 case CSSPropertyBorderBottomLeftRadius: | |
147 return toVector(style.borderBottomLeftRadius()); | |
148 case CSSPropertyBorderBottomRightRadius: | |
149 return toVector(style.borderBottomRightRadius()); | |
150 case CSSPropertyBorderTopLeftRadius: | |
151 return toVector(style.borderTopLeftRadius()); | |
152 case CSSPropertyBorderTopRightRadius: | |
153 return toVector(style.borderTopRightRadius()); | |
154 case CSSPropertyTransformOrigin: | |
155 return toVector(style.transformOrigin()); | |
156 default: | |
157 break; | |
158 } | 157 } |
159 | 158 |
160 Vector<Length> result; | 159 case CSSPropertyObjectPosition: |
161 const FillLayer* fillLayer = getFillLayer(property, style); | 160 return appendToVector(style.objectPosition(), result); |
162 FillLayerMethods fillLayerMethods(property); | 161 case CSSPropertyPerspectiveOrigin: |
163 while (fillLayer && (fillLayer->*fillLayerMethods.isSet)()) { | 162 return appendToVector(style.perspectiveOrigin(), result); |
164 result.append((fillLayer->*fillLayerMethods.get)()); | 163 case CSSPropertyBorderBottomLeftRadius: |
165 fillLayer = fillLayer->next(); | 164 return appendToVector(style.borderBottomLeftRadius(), result); |
| 165 case CSSPropertyBorderBottomRightRadius: |
| 166 return appendToVector(style.borderBottomRightRadius(), result); |
| 167 case CSSPropertyBorderTopLeftRadius: |
| 168 return appendToVector(style.borderTopLeftRadius(), result); |
| 169 case CSSPropertyBorderTopRightRadius: |
| 170 return appendToVector(style.borderTopRightRadius(), result); |
| 171 case CSSPropertyTransformOrigin: |
| 172 return appendToVector(style.transformOrigin(), result); |
| 173 |
| 174 case CSSPropertyBackgroundPositionX: |
| 175 case CSSPropertyBackgroundPositionY: |
| 176 case CSSPropertyWebkitMaskPositionX: |
| 177 case CSSPropertyWebkitMaskPositionY: { |
| 178 const FillLayer* fillLayer = getFillLayer(property, style); |
| 179 FillLayerMethods fillLayerMethods(property); |
| 180 while (fillLayer && (fillLayer->*fillLayerMethods.isSet)()) { |
| 181 result.append((fillLayer->*fillLayerMethods.getLength)()); |
| 182 fillLayer = fillLayer->next(); |
| 183 } |
| 184 return true; |
166 } | 185 } |
167 return result; | 186 case CSSPropertyBackgroundSize: |
| 187 case CSSPropertyWebkitMaskSize: { |
| 188 const FillLayer* fillLayer = getFillLayer(property, style); |
| 189 FillLayerMethods fillLayerMethods(property); |
| 190 while (fillLayer && (fillLayer->*fillLayerMethods.isSet)()) { |
| 191 FillSize fillSize = (fillLayer->*fillLayerMethods.getFillSize)(); |
| 192 if (fillSize.type != SizeLength) { |
| 193 result.clear(); |
| 194 return false; |
| 195 } |
| 196 result.append(fillSize.size.width()); |
| 197 result.append(fillSize.size.height()); |
| 198 fillLayer = fillLayer->next(); |
| 199 } |
| 200 return true; |
| 201 } |
| 202 |
| 203 default: |
| 204 ASSERT_NOT_REACHED(); |
| 205 return false; |
| 206 } |
168 } | 207 } |
169 | 208 |
170 static LengthPoint pointFromVector(const Vector<Length>& list) | 209 static LengthPoint pointFromVector(const Vector<Length>& list) |
171 { | 210 { |
172 ASSERT(list.size() == 2); | 211 ASSERT(list.size() == 2); |
173 return LengthPoint(list[0], list[1]); | 212 return LengthPoint(list[0], list[1]); |
174 } | 213 } |
175 | 214 |
176 static LengthSize sizeFromVector(const Vector<Length>& list) | 215 static LengthSize sizeFromVector(const Vector<Length>& list) |
177 { | 216 { |
178 ASSERT(list.size() == 2); | 217 ASSERT(list.size() == 2); |
179 return LengthSize(list[0], list[1]); | 218 return LengthSize(list[0], list[1]); |
180 } | 219 } |
181 | 220 |
182 static TransformOrigin transformOriginFromVector(const Vector<Length>& list) | 221 static TransformOrigin transformOriginFromVector(const Vector<Length>& list) |
183 { | 222 { |
184 ASSERT(list.size() == 3); | 223 ASSERT(list.size() == 3); |
185 return TransformOrigin(list[0], list[1], list[2].pixels()); | 224 return TransformOrigin(list[0], list[1], list[2].pixels()); |
186 } | 225 } |
187 | 226 |
188 void LengthListPropertyFunctions::setLengthList(CSSPropertyID property, Computed
Style& style, Vector<Length>&& lengthList) | 227 void LengthListPropertyFunctions::setLengthList(CSSPropertyID property, Computed
Style& style, Vector<Length>&& lengthList) |
189 { | 228 { |
190 switch (property) { | 229 switch (property) { |
191 case CSSPropertyStrokeDasharray: | 230 case CSSPropertyStrokeDasharray: |
192 style.setStrokeDashArray(lengthList.isEmpty() ? nullptr : RefVector<Leng
th>::create(std::move(lengthList))); | 231 style.setStrokeDashArray(lengthList.isEmpty() ? nullptr : RefVector<Leng
th>::create(std::move(lengthList))); |
193 return; | 232 return; |
| 233 |
194 case CSSPropertyObjectPosition: | 234 case CSSPropertyObjectPosition: |
195 style.setObjectPosition(pointFromVector(lengthList)); | 235 style.setObjectPosition(pointFromVector(lengthList)); |
196 return; | 236 return; |
197 case CSSPropertyPerspectiveOrigin: | 237 case CSSPropertyPerspectiveOrigin: |
198 style.setPerspectiveOrigin(pointFromVector(lengthList)); | 238 style.setPerspectiveOrigin(pointFromVector(lengthList)); |
199 return; | 239 return; |
| 240 |
200 case CSSPropertyBorderBottomLeftRadius: | 241 case CSSPropertyBorderBottomLeftRadius: |
201 style.setBorderBottomLeftRadius(sizeFromVector(lengthList)); | 242 style.setBorderBottomLeftRadius(sizeFromVector(lengthList)); |
202 return; | 243 return; |
203 case CSSPropertyBorderBottomRightRadius: | 244 case CSSPropertyBorderBottomRightRadius: |
204 style.setBorderBottomRightRadius(sizeFromVector(lengthList)); | 245 style.setBorderBottomRightRadius(sizeFromVector(lengthList)); |
205 return; | 246 return; |
206 case CSSPropertyBorderTopLeftRadius: | 247 case CSSPropertyBorderTopLeftRadius: |
207 style.setBorderTopLeftRadius(sizeFromVector(lengthList)); | 248 style.setBorderTopLeftRadius(sizeFromVector(lengthList)); |
208 return; | 249 return; |
209 case CSSPropertyBorderTopRightRadius: | 250 case CSSPropertyBorderTopRightRadius: |
210 style.setBorderTopRightRadius(sizeFromVector(lengthList)); | 251 style.setBorderTopRightRadius(sizeFromVector(lengthList)); |
211 return; | 252 return; |
| 253 |
212 case CSSPropertyTransformOrigin: | 254 case CSSPropertyTransformOrigin: |
213 style.setTransformOrigin(transformOriginFromVector(lengthList)); | 255 style.setTransformOrigin(transformOriginFromVector(lengthList)); |
214 return; | 256 return; |
215 default: | 257 |
216 break; | 258 case CSSPropertyBackgroundPositionX: |
| 259 case CSSPropertyBackgroundPositionY: |
| 260 case CSSPropertyWebkitMaskPositionX: |
| 261 case CSSPropertyWebkitMaskPositionY: { |
| 262 FillLayer* fillLayer = accessFillLayer(property, style); |
| 263 FillLayer* prev = nullptr; |
| 264 FillLayerMethods fillLayerMethods(property); |
| 265 for (size_t i = 0; i < lengthList.size(); i++) { |
| 266 if (!fillLayer) |
| 267 fillLayer = prev->ensureNext(); |
| 268 (fillLayer->*fillLayerMethods.setLength)(lengthList[i]); |
| 269 prev = fillLayer; |
| 270 fillLayer = fillLayer->next(); |
| 271 } |
| 272 while (fillLayer) { |
| 273 (fillLayer->*fillLayerMethods.clear)(); |
| 274 fillLayer = fillLayer->next(); |
| 275 } |
| 276 return; |
217 } | 277 } |
218 | 278 |
219 FillLayer* fillLayer = accessFillLayer(property, style); | 279 case CSSPropertyBackgroundSize: |
220 FillLayer* prev = nullptr; | 280 case CSSPropertyWebkitMaskSize: { |
221 FillLayerMethods fillLayerMethods(property); | 281 ASSERT(lengthList.size() % 2 == 0); |
222 for (size_t i = 0; i < lengthList.size(); i++) { | 282 FillLayer* fillLayer = accessFillLayer(property, style); |
223 if (!fillLayer) | 283 FillLayer* prev = nullptr; |
224 fillLayer = prev->ensureNext(); | 284 FillLayerMethods fillLayerMethods(property); |
225 (fillLayer->*fillLayerMethods.set)(lengthList[i]); | 285 for (size_t i = 0; i < lengthList.size() / 2; i++) { |
226 prev = fillLayer; | 286 if (!fillLayer) |
227 fillLayer = fillLayer->next(); | 287 fillLayer = prev->ensureNext(); |
| 288 FillSize fillSize(SizeLength, LengthSize(lengthList[2 * i], lengthLi
st[2 * i + 1])); |
| 289 (fillLayer->*fillLayerMethods.setFillSize)(fillSize); |
| 290 prev = fillLayer; |
| 291 fillLayer = fillLayer->next(); |
| 292 } |
| 293 while (fillLayer) { |
| 294 (fillLayer->*fillLayerMethods.clear)(); |
| 295 fillLayer = fillLayer->next(); |
| 296 } |
| 297 return; |
228 } | 298 } |
229 while (fillLayer) { | 299 |
230 (fillLayer->*fillLayerMethods.clear)(); | 300 default: |
231 fillLayer = fillLayer->next(); | 301 ASSERT_NOT_REACHED(); |
| 302 break; |
232 } | 303 } |
233 } | 304 } |
234 | 305 |
235 } // namespace blink | 306 } // namespace blink |
OLD | NEW |