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
3 // found in the LICENSE file.
4 
5 #include "third_party/blink/renderer/core/animation/length_property_functions.h"
6 
7 #include "third_party/blink/renderer/core/style/computed_style.h"
8 
9 namespace blink {
10 
GetValueRange(const CSSProperty & property)11 ValueRange LengthPropertyFunctions::GetValueRange(const CSSProperty& property) {
12   switch (property.PropertyID()) {
13     case CSSPropertyID::kBorderBottomWidth:
14     case CSSPropertyID::kBorderLeftWidth:
15     case CSSPropertyID::kBorderRightWidth:
16     case CSSPropertyID::kBorderTopWidth:
17     case CSSPropertyID::kFlexBasis:
18     case CSSPropertyID::kHeight:
19     case CSSPropertyID::kLineHeight:
20     case CSSPropertyID::kMaxHeight:
21     case CSSPropertyID::kMaxWidth:
22     case CSSPropertyID::kMinHeight:
23     case CSSPropertyID::kMinWidth:
24     case CSSPropertyID::kOutlineWidth:
25     case CSSPropertyID::kPaddingBottom:
26     case CSSPropertyID::kPaddingLeft:
27     case CSSPropertyID::kPaddingRight:
28     case CSSPropertyID::kPaddingTop:
29     case CSSPropertyID::kPerspective:
30     case CSSPropertyID::kR:
31     case CSSPropertyID::kRx:
32     case CSSPropertyID::kRy:
33     case CSSPropertyID::kShapeMargin:
34     case CSSPropertyID::kStrokeWidth:
35     case CSSPropertyID::kWebkitBorderHorizontalSpacing:
36     case CSSPropertyID::kWebkitBorderVerticalSpacing:
37     case CSSPropertyID::kColumnGap:
38     case CSSPropertyID::kRowGap:
39     case CSSPropertyID::kColumnWidth:
40     case CSSPropertyID::kWidth:
41     case CSSPropertyID::kTabSize:
42       return kValueRangeNonNegative;
43     default:
44       return kValueRangeAll;
45   }
46 }
47 
IsZoomedLength(const CSSProperty & property)48 bool LengthPropertyFunctions::IsZoomedLength(const CSSProperty& property) {
49   return property.PropertyID() != CSSPropertyID::kStrokeWidth;
50 }
51 
GetPixelsForKeyword(const CSSProperty & property,CSSValueID value_id,double & result)52 bool LengthPropertyFunctions::GetPixelsForKeyword(const CSSProperty& property,
53                                                   CSSValueID value_id,
54                                                   double& result) {
55   switch (property.PropertyID()) {
56     case CSSPropertyID::kBaselineShift:
57       if (value_id == CSSValueID::kBaseline) {
58         result = 0;
59         return true;
60       }
61       return false;
62     case CSSPropertyID::kBorderBottomWidth:
63     case CSSPropertyID::kBorderLeftWidth:
64     case CSSPropertyID::kBorderRightWidth:
65     case CSSPropertyID::kBorderTopWidth:
66     case CSSPropertyID::kColumnRuleWidth:
67     case CSSPropertyID::kOutlineWidth:
68       if (value_id == CSSValueID::kThin) {
69         result = 1;
70         return true;
71       }
72       if (value_id == CSSValueID::kMedium) {
73         result = 3;
74         return true;
75       }
76       if (value_id == CSSValueID::kThick) {
77         result = 5;
78         return true;
79       }
80       return false;
81     case CSSPropertyID::kLetterSpacing:
82     case CSSPropertyID::kWordSpacing:
83       if (value_id == CSSValueID::kNormal) {
84         result = 0;
85         return true;
86       }
87       return false;
88     default:
89       return false;
90   }
91 }
92 
GetInitialLength(const CSSProperty & property,Length & result)93 bool LengthPropertyFunctions::GetInitialLength(const CSSProperty& property,
94                                                Length& result) {
95   switch (property.PropertyID()) {
96     // The computed value of "initial" for the following properties is 0px if
97     // the associated *-style property resolves to "none" or "hidden".
98     // - border-width:
99     //   https://drafts.csswg.org/css-backgrounds-3/#the-border-width
100     // - outline-width: https://drafts.csswg.org/css-ui-3/#outline-width
101     // - column-rule-width: https://drafts.csswg.org/css-multicol-1/#crw
102     // We ignore this value adjustment for animations and use the wrong value
103     // for hidden widths to avoid having to restart our animations based on the
104     // computed *-style values. This is acceptable since animations running on
105     // hidden widths are unobservable to the user, even via getComputedStyle().
106     case CSSPropertyID::kBorderBottomWidth:
107     case CSSPropertyID::kBorderLeftWidth:
108     case CSSPropertyID::kBorderRightWidth:
109     case CSSPropertyID::kBorderTopWidth:
110       result = Length::Fixed(ComputedStyleInitialValues::InitialBorderWidth());
111       return true;
112     case CSSPropertyID::kOutlineWidth:
113       result = Length::Fixed(ComputedStyleInitialValues::InitialOutlineWidth());
114       return true;
115     case CSSPropertyID::kColumnRuleWidth:
116       result =
117           Length::Fixed(ComputedStyleInitialValues::InitialColumnRuleWidth());
118       return true;
119 
120     default:
121       return GetLength(property, ComputedStyle::InitialStyle(), result);
122   }
123 }
124 
GetLength(const CSSProperty & property,const ComputedStyle & style,Length & result)125 bool LengthPropertyFunctions::GetLength(const CSSProperty& property,
126                                         const ComputedStyle& style,
127                                         Length& result) {
128   switch (property.PropertyID()) {
129     case CSSPropertyID::kBottom:
130       result = style.Bottom();
131       return true;
132     case CSSPropertyID::kCx:
133       result = style.SvgStyle().Cx();
134       return true;
135     case CSSPropertyID::kCy:
136       result = style.SvgStyle().Cy();
137       return true;
138     case CSSPropertyID::kFlexBasis:
139       result = style.FlexBasis();
140       return true;
141     case CSSPropertyID::kHeight:
142       result = style.Height();
143       return true;
144     case CSSPropertyID::kLeft:
145       result = style.Left();
146       return true;
147     case CSSPropertyID::kMarginBottom:
148       result = style.MarginBottom();
149       return true;
150     case CSSPropertyID::kMarginLeft:
151       result = style.MarginLeft();
152       return true;
153     case CSSPropertyID::kMarginRight:
154       result = style.MarginRight();
155       return true;
156     case CSSPropertyID::kMarginTop:
157       result = style.MarginTop();
158       return true;
159     case CSSPropertyID::kMaxHeight:
160       result = style.MaxHeight();
161       return true;
162     case CSSPropertyID::kMaxWidth:
163       result = style.MaxWidth();
164       return true;
165     case CSSPropertyID::kMinHeight:
166       result = style.MinHeight();
167       return true;
168     case CSSPropertyID::kMinWidth:
169       result = style.MinWidth();
170       return true;
171     case CSSPropertyID::kOffsetDistance:
172       result = style.OffsetDistance();
173       return true;
174     case CSSPropertyID::kPaddingBottom:
175       result = style.PaddingBottom();
176       return true;
177     case CSSPropertyID::kPaddingLeft:
178       result = style.PaddingLeft();
179       return true;
180     case CSSPropertyID::kPaddingRight:
181       result = style.PaddingRight();
182       return true;
183     case CSSPropertyID::kPaddingTop:
184       result = style.PaddingTop();
185       return true;
186     case CSSPropertyID::kR:
187       result = style.SvgStyle().R();
188       return true;
189     case CSSPropertyID::kRight:
190       result = style.Right();
191       return true;
192     case CSSPropertyID::kRx:
193       result = style.SvgStyle().Rx();
194       return true;
195     case CSSPropertyID::kRy:
196       result = style.SvgStyle().Ry();
197       return true;
198     case CSSPropertyID::kShapeMargin:
199       result = style.ShapeMargin();
200       return true;
201     case CSSPropertyID::kStrokeDashoffset:
202       result = style.StrokeDashOffset();
203       return true;
204     case CSSPropertyID::kTextIndent:
205       result = style.TextIndent();
206       return true;
207     case CSSPropertyID::kTop:
208       result = style.Top();
209       return true;
210     case CSSPropertyID::kWebkitPerspectiveOriginX:
211       result = style.PerspectiveOriginX();
212       return true;
213     case CSSPropertyID::kWebkitPerspectiveOriginY:
214       result = style.PerspectiveOriginY();
215       return true;
216     case CSSPropertyID::kWebkitTransformOriginX:
217       result = style.TransformOriginX();
218       return true;
219     case CSSPropertyID::kWebkitTransformOriginY:
220       result = style.TransformOriginY();
221       return true;
222     case CSSPropertyID::kWidth:
223       result = style.Width();
224       return true;
225     case CSSPropertyID::kX:
226       result = style.SvgStyle().X();
227       return true;
228     case CSSPropertyID::kY:
229       result = style.SvgStyle().Y();
230       return true;
231 
232     case CSSPropertyID::kBorderBottomWidth:
233       result = Length::Fixed(style.BorderBottomWidth());
234       return true;
235     case CSSPropertyID::kBorderLeftWidth:
236       result = Length::Fixed(style.BorderLeftWidth());
237       return true;
238     case CSSPropertyID::kBorderRightWidth:
239       result = Length::Fixed(style.BorderRightWidth());
240       return true;
241     case CSSPropertyID::kBorderTopWidth:
242       result = Length::Fixed(style.BorderTopWidth());
243       return true;
244     case CSSPropertyID::kLetterSpacing:
245       result = Length::Fixed(style.LetterSpacing());
246       return true;
247     case CSSPropertyID::kOutlineOffset:
248       result = Length::Fixed(style.OutlineOffset());
249       return true;
250     case CSSPropertyID::kOutlineWidth:
251       result = Length::Fixed(style.OutlineWidth());
252       return true;
253     case CSSPropertyID::kWebkitBorderHorizontalSpacing:
254       result = Length::Fixed(style.HorizontalBorderSpacing());
255       return true;
256     case CSSPropertyID::kWebkitBorderVerticalSpacing:
257       result = Length::Fixed(style.VerticalBorderSpacing());
258       return true;
259     case CSSPropertyID::kRowGap:
260       if (!style.RowGap())
261         return false;
262       result = *style.RowGap();
263       return true;
264     case CSSPropertyID::kColumnGap:
265       if (!style.ColumnGap())
266         return false;
267       result = *style.ColumnGap();
268       return true;
269     case CSSPropertyID::kColumnRuleWidth:
270       result = Length::Fixed(style.ColumnRuleWidth());
271       return true;
272     case CSSPropertyID::kWebkitTransformOriginZ:
273       result = Length::Fixed(style.TransformOriginZ());
274       return true;
275     case CSSPropertyID::kWordSpacing:
276       result = Length::Fixed(style.WordSpacing());
277       return true;
278 
279     case CSSPropertyID::kBaselineShift:
280       if (style.BaselineShift() != BS_LENGTH)
281         return false;
282       result = style.BaselineShiftValue();
283       return true;
284     case CSSPropertyID::kLineHeight:
285       // Percent Lengths are used to represent numbers on line-height.
286       if (style.SpecifiedLineHeight().IsPercentOrCalc())
287         return false;
288       result = style.SpecifiedLineHeight();
289       return true;
290     case CSSPropertyID::kTabSize:
291       if (style.GetTabSize().IsSpaces())
292         return false;
293       result = Length::Fixed(style.GetTabSize().float_value_);
294       return true;
295     case CSSPropertyID::kPerspective:
296       if (!style.HasPerspective())
297         return false;
298       result = Length::Fixed(style.Perspective());
299       return true;
300     case CSSPropertyID::kStrokeWidth:
301       DCHECK(!IsZoomedLength(CSSProperty::Get(CSSPropertyID::kStrokeWidth)));
302       result = style.StrokeWidth().length();
303       return true;
304     case CSSPropertyID::kVerticalAlign:
305       if (style.VerticalAlign() != EVerticalAlign::kLength)
306         return false;
307       result = style.GetVerticalAlignLength();
308       return true;
309     case CSSPropertyID::kColumnWidth:
310       if (style.HasAutoColumnWidth())
311         return false;
312       result = Length::Fixed(style.ColumnWidth());
313       return true;
314     default:
315       return false;
316   }
317 }
318 
SetLength(const CSSProperty & property,ComputedStyle & style,const Length & value)319 bool LengthPropertyFunctions::SetLength(const CSSProperty& property,
320                                         ComputedStyle& style,
321                                         const Length& value) {
322   switch (property.PropertyID()) {
323     // Setters that take a Length value.
324     case CSSPropertyID::kBaselineShift:
325       style.SetBaselineShiftValue(value);
326       return true;
327     case CSSPropertyID::kBottom:
328       style.SetBottom(value);
329       return true;
330     case CSSPropertyID::kCx:
331       style.SetCx(value);
332       return true;
333     case CSSPropertyID::kCy:
334       style.SetCy(value);
335       return true;
336     case CSSPropertyID::kFlexBasis:
337       style.SetFlexBasis(value);
338       return true;
339     case CSSPropertyID::kHeight:
340       style.SetHeight(value);
341       return true;
342     case CSSPropertyID::kLeft:
343       style.SetLeft(value);
344       return true;
345     case CSSPropertyID::kMarginBottom:
346       style.SetMarginBottom(value);
347       return true;
348     case CSSPropertyID::kMarginLeft:
349       style.SetMarginLeft(value);
350       return true;
351     case CSSPropertyID::kMarginRight:
352       style.SetMarginRight(value);
353       return true;
354     case CSSPropertyID::kMarginTop:
355       style.SetMarginTop(value);
356       return true;
357     case CSSPropertyID::kMaxHeight:
358       style.SetMaxHeight(value);
359       return true;
360     case CSSPropertyID::kMaxWidth:
361       style.SetMaxWidth(value);
362       return true;
363     case CSSPropertyID::kMinHeight:
364       style.SetMinHeight(value);
365       return true;
366     case CSSPropertyID::kMinWidth:
367       style.SetMinWidth(value);
368       return true;
369     case CSSPropertyID::kOffsetDistance:
370       style.SetOffsetDistance(value);
371       return true;
372     case CSSPropertyID::kPaddingBottom:
373       style.SetPaddingBottom(value);
374       return true;
375     case CSSPropertyID::kPaddingLeft:
376       style.SetPaddingLeft(value);
377       return true;
378     case CSSPropertyID::kPaddingRight:
379       style.SetPaddingRight(value);
380       return true;
381     case CSSPropertyID::kPaddingTop:
382       style.SetPaddingTop(value);
383       return true;
384     case CSSPropertyID::kR:
385       style.SetR(value);
386       return true;
387     case CSSPropertyID::kRx:
388       style.SetRx(value);
389       return true;
390     case CSSPropertyID::kRy:
391       style.SetRy(value);
392       return true;
393     case CSSPropertyID::kRight:
394       style.SetRight(value);
395       return true;
396     case CSSPropertyID::kShapeMargin:
397       style.SetShapeMargin(value);
398       return true;
399     case CSSPropertyID::kStrokeDashoffset:
400       style.SetStrokeDashOffset(value);
401       return true;
402     case CSSPropertyID::kTop:
403       style.SetTop(value);
404       return true;
405     case CSSPropertyID::kWidth:
406       style.SetWidth(value);
407       return true;
408     case CSSPropertyID::kWebkitPerspectiveOriginX:
409       style.SetPerspectiveOriginX(value);
410       return true;
411     case CSSPropertyID::kWebkitPerspectiveOriginY:
412       style.SetPerspectiveOriginY(value);
413       return true;
414     case CSSPropertyID::kWebkitTransformOriginX:
415       style.SetTransformOriginX(value);
416       return true;
417     case CSSPropertyID::kWebkitTransformOriginY:
418       style.SetTransformOriginY(value);
419       return true;
420     case CSSPropertyID::kX:
421       style.SetX(value);
422       return true;
423     case CSSPropertyID::kY:
424       style.SetY(value);
425       return true;
426 
427     case CSSPropertyID::kLineHeight:
428       // Percent Lengths are used to represent numbers on line-height.
429       if (value.IsPercentOrCalc())
430         return false;
431       style.SetLineHeight(value);
432       return true;
433 
434     // TODO(alancutter): Support setters that take a numeric value (need to
435     // resolve percentages).
436     case CSSPropertyID::kBorderBottomWidth:
437     case CSSPropertyID::kBorderLeftWidth:
438     case CSSPropertyID::kBorderRightWidth:
439     case CSSPropertyID::kBorderTopWidth:
440     case CSSPropertyID::kLetterSpacing:
441     case CSSPropertyID::kOutlineOffset:
442     case CSSPropertyID::kOutlineWidth:
443     case CSSPropertyID::kPerspective:
444     case CSSPropertyID::kStrokeWidth:
445     case CSSPropertyID::kVerticalAlign:
446     case CSSPropertyID::kWebkitBorderHorizontalSpacing:
447     case CSSPropertyID::kWebkitBorderVerticalSpacing:
448     case CSSPropertyID::kColumnGap:
449     case CSSPropertyID::kRowGap:
450     case CSSPropertyID::kColumnRuleWidth:
451     case CSSPropertyID::kColumnWidth:
452     case CSSPropertyID::kWebkitTransformOriginZ:
453     case CSSPropertyID::kWordSpacing:
454     case CSSPropertyID::kTabSize:
455       return false;
456 
457       return false;
458 
459     default:
460       return false;
461   }
462 }
463 
464 }  // namespace blink
465