[css-align] Implement the place-items shorthand
[WebKit-https.git] / Source / WebCore / css / CSSComputedStyleDeclaration.cpp
1 /*
2  * Copyright (C) 2004 Zack Rusin <zack@kde.org>
3  * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
4  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
5  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6  * Copyright (C) 2011 Sencha, Inc. All rights reserved.
7  * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301  USA
23  */
24
25 #include "config.h"
26 #include "CSSComputedStyleDeclaration.h"
27
28 #include "BasicShapeFunctions.h"
29 #include "BasicShapes.h"
30 #include "CSSAnimationController.h"
31 #include "CSSAnimationTriggerScrollValue.h"
32 #include "CSSAspectRatioValue.h"
33 #include "CSSBasicShapes.h"
34 #include "CSSBorderImage.h"
35 #include "CSSBorderImageSliceValue.h"
36 #include "CSSCustomPropertyValue.h"
37 #include "CSSFontFeatureValue.h"
38 #include "CSSFontStyleValue.h"
39 #include "CSSFontValue.h"
40 #include "CSSFontVariationValue.h"
41 #include "CSSFunctionValue.h"
42 #include "CSSLineBoxContainValue.h"
43 #include "CSSPrimitiveValue.h"
44 #include "CSSPrimitiveValueMappings.h"
45 #include "CSSPropertyNames.h"
46 #include "CSSPropertyParser.h"
47 #include "CSSReflectValue.h"
48 #include "CSSSelector.h"
49 #include "CSSShadowValue.h"
50 #include "CSSTimingFunctionValue.h"
51 #include "CSSValueList.h"
52 #include "CSSValuePool.h"
53 #include "ComposedTreeAncestorIterator.h"
54 #include "ContentData.h"
55 #include "CounterContent.h"
56 #include "CursorList.h"
57 #include "DeprecatedCSSOMValue.h"
58 #include "Document.h"
59 #include "ExceptionCode.h"
60 #include "FontSelectionValueInlines.h"
61 #include "FontTaggedSettings.h"
62 #include "HTMLFrameOwnerElement.h"
63 #include "NodeRenderStyle.h"
64 #include "Pair.h"
65 #include "PseudoElement.h"
66 #include "Rect.h"
67 #include "RenderBlock.h"
68 #include "RenderBox.h"
69 #include "RenderStyle.h"
70 #include "RuntimeEnabledFeatures.h"
71 #include "SVGElement.h"
72 #include "Settings.h"
73 #include "ShapeValue.h"
74 #include "StyleInheritedData.h"
75 #include "StyleProperties.h"
76 #include "StylePropertyShorthand.h"
77 #include "StylePropertyShorthandFunctions.h"
78 #include "StyleResolver.h"
79 #include "StyleScope.h"
80 #include "StyleScrollSnapPoints.h"
81 #include "Text.h"
82 #include "WebKitFontFamilyNames.h"
83 #include "WillChangeData.h"
84 #include <wtf/NeverDestroyed.h>
85 #include <wtf/text/StringBuilder.h>
86
87 #include "CSSGridLineNamesValue.h"
88 #include "CSSGridTemplateAreasValue.h"
89 #include "RenderGrid.h"
90
91 #if ENABLE(DASHBOARD_SUPPORT)
92 #include "DashboardRegion.h"
93 #endif
94
95 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
96 #include "AnimationTrigger.h"
97 #endif
98
99 namespace WebCore {
100
101 // List of all properties we know how to compute, omitting shorthands.
102 static const CSSPropertyID computedProperties[] = {
103     CSSPropertyAlt,
104     CSSPropertyAnimationDelay,
105     CSSPropertyAnimationDirection,
106     CSSPropertyAnimationDuration,
107     CSSPropertyAnimationFillMode,
108     CSSPropertyAnimationIterationCount,
109     CSSPropertyAnimationName,
110     CSSPropertyAnimationPlayState,
111     CSSPropertyAnimationTimingFunction,
112     CSSPropertyBackgroundAttachment,
113     CSSPropertyBackgroundBlendMode,
114     CSSPropertyBackgroundClip,
115     CSSPropertyBackgroundColor,
116     CSSPropertyBackgroundImage,
117     CSSPropertyBackgroundOrigin,
118     CSSPropertyBackgroundPosition, // more-specific background-position-x/y are non-standard
119     CSSPropertyBackgroundRepeat,
120     CSSPropertyBackgroundSize,
121     CSSPropertyBorderBottomColor,
122     CSSPropertyBorderBottomLeftRadius,
123     CSSPropertyBorderBottomRightRadius,
124     CSSPropertyBorderBottomStyle,
125     CSSPropertyBorderBottomWidth,
126     CSSPropertyBorderCollapse,
127     CSSPropertyBorderImageOutset,
128     CSSPropertyBorderImageRepeat,
129     CSSPropertyBorderImageSlice,
130     CSSPropertyBorderImageSource,
131     CSSPropertyBorderImageWidth,
132     CSSPropertyBorderLeftColor,
133     CSSPropertyBorderLeftStyle,
134     CSSPropertyBorderLeftWidth,
135     CSSPropertyBorderRightColor,
136     CSSPropertyBorderRightStyle,
137     CSSPropertyBorderRightWidth,
138     CSSPropertyBorderTopColor,
139     CSSPropertyBorderTopLeftRadius,
140     CSSPropertyBorderTopRightRadius,
141     CSSPropertyBorderTopStyle,
142     CSSPropertyBorderTopWidth,
143     CSSPropertyBottom,
144     CSSPropertyBoxShadow,
145     CSSPropertyBoxSizing,
146     CSSPropertyCaptionSide,
147     CSSPropertyClear,
148     CSSPropertyClip,
149     CSSPropertyColor,
150     CSSPropertyCounterIncrement,
151     CSSPropertyCounterReset,
152     CSSPropertyContent,
153     CSSPropertyCursor,
154     CSSPropertyDirection,
155     CSSPropertyDisplay,
156     CSSPropertyEmptyCells,
157     CSSPropertyFloat,
158     CSSPropertyFontFamily,
159     CSSPropertyFontSize,
160     CSSPropertyFontStretch,
161     CSSPropertyFontStyle,
162     CSSPropertyFontSynthesis,
163     CSSPropertyFontVariant,
164     CSSPropertyFontWeight,
165 #if ENABLE(VARIATION_FONTS)
166     CSSPropertyFontOpticalSizing,
167 #endif
168     CSSPropertyHangingPunctuation,
169     CSSPropertyHeight,
170 #if ENABLE(CSS_IMAGE_ORIENTATION)
171     CSSPropertyImageOrientation,
172 #endif
173     CSSPropertyImageRendering,
174 #if ENABLE(CSS_IMAGE_RESOLUTION)
175     CSSPropertyImageResolution,
176 #endif
177     CSSPropertyLeft,
178     CSSPropertyLetterSpacing,
179     CSSPropertyLineHeight,
180     CSSPropertyListStyleImage,
181     CSSPropertyListStylePosition,
182     CSSPropertyListStyleType,
183     CSSPropertyMarginBottom,
184     CSSPropertyMarginLeft,
185     CSSPropertyMarginRight,
186     CSSPropertyMarginTop,
187     CSSPropertyMaxHeight,
188     CSSPropertyMaxWidth,
189     CSSPropertyMinHeight,
190     CSSPropertyMinWidth,
191     CSSPropertyObjectFit,
192     CSSPropertyObjectPosition,
193     CSSPropertyOpacity,
194     CSSPropertyOrphans,
195     CSSPropertyOutlineColor,
196     CSSPropertyOutlineOffset,
197     CSSPropertyOutlineStyle,
198     CSSPropertyOutlineWidth,
199     CSSPropertyOverflowWrap,
200     CSSPropertyOverflowX,
201     CSSPropertyOverflowY,
202     CSSPropertyPaddingBottom,
203     CSSPropertyPaddingLeft,
204     CSSPropertyPaddingRight,
205     CSSPropertyPaddingTop,
206     CSSPropertyPageBreakAfter,
207     CSSPropertyPageBreakBefore,
208     CSSPropertyPageBreakInside,
209     CSSPropertyPointerEvents,
210     CSSPropertyPosition,
211     CSSPropertyResize,
212     CSSPropertyRight,
213     CSSPropertySpeak,
214     CSSPropertyTableLayout,
215     CSSPropertyTabSize,
216     CSSPropertyTextAlign,
217     CSSPropertyTextDecoration,
218 #if ENABLE(CSS3_TEXT)
219     CSSPropertyWebkitTextAlignLast,
220     CSSPropertyWebkitTextJustify,
221 #endif // CSS3_TEXT
222     CSSPropertyWebkitTextDecorationLine,
223     CSSPropertyWebkitTextDecorationStyle,
224     CSSPropertyWebkitTextDecorationColor,
225     CSSPropertyWebkitTextDecorationSkip,
226     CSSPropertyWebkitTextUnderlinePosition,
227     CSSPropertyTextIndent,
228     CSSPropertyTextRendering,
229     CSSPropertyTextShadow,
230     CSSPropertyTextOverflow,
231     CSSPropertyTextTransform,
232     CSSPropertyTop,
233     CSSPropertyTransform,
234     CSSPropertyTransformOrigin,
235     CSSPropertyTransformStyle,
236     CSSPropertyTransitionDelay,
237     CSSPropertyTransitionDuration,
238     CSSPropertyTransitionProperty,
239     CSSPropertyTransitionTimingFunction,
240     CSSPropertyUnicodeBidi,
241     CSSPropertyVerticalAlign,
242     CSSPropertyVisibility,
243     CSSPropertyWhiteSpace,
244     CSSPropertyWidows,
245     CSSPropertyWidth,
246     CSSPropertyWillChange,
247     CSSPropertyWordBreak,
248     CSSPropertyWordSpacing,
249     CSSPropertyWordWrap,
250 #if ENABLE(CSS_SCROLL_SNAP)
251     CSSPropertyScrollSnapMargin,
252     CSSPropertyScrollSnapMarginLeft,
253     CSSPropertyScrollSnapMarginTop,
254     CSSPropertyScrollSnapMarginRight,
255     CSSPropertyScrollSnapMarginBottom,
256     CSSPropertyScrollPadding,
257     CSSPropertyScrollPaddingLeft,
258     CSSPropertyScrollPaddingTop,
259     CSSPropertyScrollPaddingRight,
260     CSSPropertyScrollPaddingBottom,
261     CSSPropertyScrollSnapType,
262     CSSPropertyScrollSnapAlign,
263 #endif
264     CSSPropertyZIndex,
265     CSSPropertyZoom,
266 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
267     CSSPropertyWebkitAnimationTrigger,
268 #endif
269     CSSPropertyWebkitAppearance,
270     CSSPropertyWebkitBackfaceVisibility,
271     CSSPropertyWebkitBackgroundClip,
272     CSSPropertyWebkitBackgroundComposite,
273     CSSPropertyWebkitBackgroundOrigin,
274     CSSPropertyWebkitBackgroundSize,
275 #if ENABLE(CSS_COMPOSITING)
276     CSSPropertyMixBlendMode,
277     CSSPropertyIsolation,
278 #endif
279     CSSPropertyWebkitBorderFit,
280     CSSPropertyWebkitBorderHorizontalSpacing,
281     CSSPropertyWebkitBorderImage,
282     CSSPropertyWebkitBorderVerticalSpacing,
283     CSSPropertyWebkitBoxAlign,
284 #if ENABLE(CSS_BOX_DECORATION_BREAK)
285     CSSPropertyWebkitBoxDecorationBreak,
286 #endif
287     CSSPropertyWebkitBoxDirection,
288     CSSPropertyWebkitBoxFlex,
289     CSSPropertyWebkitBoxFlexGroup,
290     CSSPropertyWebkitBoxLines,
291     CSSPropertyWebkitBoxOrdinalGroup,
292     CSSPropertyWebkitBoxOrient,
293     CSSPropertyWebkitBoxPack,
294     CSSPropertyWebkitBoxReflect,
295     CSSPropertyWebkitBoxShadow,
296     CSSPropertyWebkitClipPath,
297     CSSPropertyWebkitColumnBreakAfter,
298     CSSPropertyWebkitColumnBreakBefore,
299     CSSPropertyWebkitColumnBreakInside,
300     CSSPropertyWebkitColumnAxis,
301     CSSPropertyColumnCount,
302     CSSPropertyColumnFill,
303     CSSPropertyColumnGap,
304     CSSPropertyWebkitColumnProgression,
305     CSSPropertyColumnRuleColor,
306     CSSPropertyColumnRuleStyle,
307     CSSPropertyColumnRuleWidth,
308     CSSPropertyColumnSpan,
309     CSSPropertyColumnWidth,
310 #if ENABLE(CURSOR_VISIBILITY)
311     CSSPropertyWebkitCursorVisibility,
312 #endif
313 #if ENABLE(DASHBOARD_SUPPORT)
314     CSSPropertyWebkitDashboardRegion,
315 #endif
316     CSSPropertyAlignContent,
317     CSSPropertyAlignItems,
318     CSSPropertyAlignSelf,
319     CSSPropertyFilter,
320     CSSPropertyFlexBasis,
321     CSSPropertyFlexDirection,
322     CSSPropertyFlexFlow,
323     CSSPropertyFlexGrow,
324     CSSPropertyFlexShrink,
325     CSSPropertyFlexWrap,
326     CSSPropertyJustifyContent,
327     CSSPropertyJustifySelf,
328     CSSPropertyJustifyItems,
329     CSSPropertyPlaceContent,
330     CSSPropertyPlaceItems,
331 #if ENABLE(FILTERS_LEVEL_2)
332     CSSPropertyWebkitBackdropFilter,
333 #endif
334     CSSPropertyWebkitFontKerning,
335     CSSPropertyWebkitFontSmoothing,
336     CSSPropertyFontVariantLigatures,
337     CSSPropertyFontVariantPosition,
338     CSSPropertyFontVariantCaps,
339     CSSPropertyFontVariantNumeric,
340     CSSPropertyFontVariantAlternates,
341     CSSPropertyFontVariantEastAsian,
342 #if ENABLE(VARIATION_FONTS)
343     CSSPropertyFontVariationSettings,
344 #endif
345     CSSPropertyGridAutoColumns,
346     CSSPropertyGridAutoFlow,
347     CSSPropertyGridAutoRows,
348     CSSPropertyGridColumnEnd,
349     CSSPropertyGridColumnStart,
350     CSSPropertyGridTemplateAreas,
351     CSSPropertyGridTemplateColumns,
352     CSSPropertyGridTemplateRows,
353     CSSPropertyGridRowEnd,
354     CSSPropertyGridRowStart,
355     CSSPropertyGridColumnGap,
356     CSSPropertyGridRowGap,
357     CSSPropertyWebkitHyphenateCharacter,
358     CSSPropertyWebkitHyphenateLimitAfter,
359     CSSPropertyWebkitHyphenateLimitBefore,
360     CSSPropertyWebkitHyphenateLimitLines,
361     CSSPropertyWebkitHyphens,
362     CSSPropertyWebkitInitialLetter,
363     CSSPropertyWebkitLineAlign,
364     CSSPropertyWebkitLineBoxContain,
365     CSSPropertyLineBreak,
366     CSSPropertyWebkitLineClamp,
367     CSSPropertyWebkitLineGrid,
368     CSSPropertyWebkitLineSnap,
369     CSSPropertyWebkitLocale,
370     CSSPropertyWebkitMarginBeforeCollapse,
371     CSSPropertyWebkitMarginAfterCollapse,
372     CSSPropertyWebkitMarqueeDirection,
373     CSSPropertyWebkitMarqueeIncrement,
374     CSSPropertyWebkitMarqueeRepetition,
375     CSSPropertyWebkitMarqueeStyle,
376     CSSPropertyWebkitMaskBoxImage,
377     CSSPropertyWebkitMaskBoxImageOutset,
378     CSSPropertyWebkitMaskBoxImageRepeat,
379     CSSPropertyWebkitMaskBoxImageSlice,
380     CSSPropertyWebkitMaskBoxImageSource,
381     CSSPropertyWebkitMaskBoxImageWidth,
382     CSSPropertyWebkitMaskClip,
383     CSSPropertyWebkitMaskComposite,
384     CSSPropertyWebkitMaskImage,
385     CSSPropertyWebkitMaskOrigin,
386     CSSPropertyWebkitMaskPosition,
387     CSSPropertyWebkitMaskRepeat,
388     CSSPropertyWebkitMaskSize,
389     CSSPropertyWebkitMaskSourceType,
390     CSSPropertyWebkitNbspMode,
391     CSSPropertyOrder,
392 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
393     CSSPropertyWebkitOverflowScrolling,
394 #endif
395     CSSPropertyPerspective,
396     CSSPropertyPerspectiveOrigin,
397     CSSPropertyWebkitPrintColorAdjust,
398     CSSPropertyWebkitRtlOrdering,
399 #if PLATFORM(IOS)
400     CSSPropertyWebkitTouchCallout,
401 #endif
402     CSSPropertyShapeOutside,
403 #if ENABLE(TOUCH_EVENTS)
404     CSSPropertyWebkitTapHighlightColor,
405 #endif
406     CSSPropertyWebkitTextCombine,
407     CSSPropertyWebkitTextDecorationsInEffect,
408     CSSPropertyWebkitTextEmphasisColor,
409     CSSPropertyWebkitTextEmphasisPosition,
410     CSSPropertyWebkitTextEmphasisStyle,
411     CSSPropertyWebkitTextFillColor,
412     CSSPropertyWebkitTextOrientation,
413     CSSPropertyWebkitTextSecurity,
414 #if ENABLE(TEXT_AUTOSIZING)
415     CSSPropertyWebkitTextSizeAdjust,
416 #endif
417     CSSPropertyWebkitTextStrokeColor,
418     CSSPropertyWebkitTextStrokeWidth,
419     CSSPropertyWebkitTextZoom,
420     CSSPropertyWebkitTransformStyle,
421     CSSPropertyWebkitUserDrag,
422     CSSPropertyWebkitUserModify,
423     CSSPropertyWebkitUserSelect,
424 #if ENABLE(CSS_REGIONS)
425     CSSPropertyWebkitFlowInto,
426     CSSPropertyWebkitFlowFrom,
427     CSSPropertyWebkitRegionBreakAfter,
428     CSSPropertyWebkitRegionBreakBefore,
429     CSSPropertyWebkitRegionBreakInside,
430     CSSPropertyWebkitRegionFragment,
431 #endif
432     CSSPropertyShapeImageThreshold,
433     CSSPropertyShapeMargin,
434     CSSPropertyShapeOutside,
435     CSSPropertyShapeRendering,
436     CSSPropertyBufferedRendering,
437     CSSPropertyClipPath,
438     CSSPropertyClipRule,
439     CSSPropertyCx,
440     CSSPropertyCy,
441     CSSPropertyMask,
442     CSSPropertyMaskType,
443     CSSPropertyFilter,
444     CSSPropertyFloodColor,
445     CSSPropertyFloodOpacity,
446     CSSPropertyLightingColor,
447     CSSPropertyStopColor,
448     CSSPropertyStopOpacity,
449     CSSPropertyColorInterpolation,
450     CSSPropertyColorInterpolationFilters,
451     CSSPropertyColorRendering,
452     CSSPropertyFill,
453     CSSPropertyFillOpacity,
454     CSSPropertyFillRule,
455     CSSPropertyMarkerEnd,
456     CSSPropertyMarkerMid,
457     CSSPropertyMarkerStart,
458     CSSPropertyPaintOrder,
459     CSSPropertyR,
460     CSSPropertyRx,
461     CSSPropertyRy,
462     CSSPropertyStroke,
463     CSSPropertyStrokeDasharray,
464     CSSPropertyStrokeDashoffset,
465     CSSPropertyStrokeLinecap,
466     CSSPropertyStrokeLinejoin,
467     CSSPropertyStrokeMiterlimit,
468     CSSPropertyStrokeOpacity,
469     CSSPropertyStrokeWidth,
470     CSSPropertyAlignmentBaseline,
471     CSSPropertyBaselineShift,
472     CSSPropertyDominantBaseline,
473     CSSPropertyKerning,
474     CSSPropertyTextAnchor,
475     CSSPropertyWritingMode,
476     CSSPropertyGlyphOrientationHorizontal,
477     CSSPropertyGlyphOrientationVertical,
478     CSSPropertyWebkitSvgShadow,
479     CSSPropertyVectorEffect,
480     CSSPropertyX,
481     CSSPropertyY
482 };
483
484 const unsigned numComputedProperties = WTF_ARRAY_LENGTH(computedProperties);
485
486 static CSSValueID valueForRepeatRule(int rule)
487 {
488     switch (rule) {
489         case RepeatImageRule:
490             return CSSValueRepeat;
491         case RoundImageRule:
492             return CSSValueRound;
493         case SpaceImageRule:
494             return CSSValueSpace;
495         default:
496             return CSSValueStretch;
497     }
498 }
499
500 static Ref<CSSPrimitiveValue> valueForImageSliceSide(const Length& length)
501 {
502     // These values can be percentages, numbers, or while an animation of mixed types is in progress,
503     // a calculation that combines a percentage and a number.
504     if (length.isPercent())
505         return CSSValuePool::singleton().createValue(length.percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
506     if (length.isFixed())
507         return CSSValuePool::singleton().createValue(length.value(), CSSPrimitiveValue::CSS_NUMBER);
508
509     // Calculating the actual length currently in use would require most of the code from RenderBoxModelObject::paintNinePieceImage.
510     // And even if we could do that, it's not clear if that's exactly what we'd want during animation.
511     // FIXME: For now, just return 0.
512     ASSERT(length.isCalculated());
513     return CSSValuePool::singleton().createValue(0, CSSPrimitiveValue::CSS_NUMBER);
514 }
515
516 static Ref<CSSBorderImageSliceValue> valueForNinePieceImageSlice(const NinePieceImage& image)
517 {
518     auto& slices = image.imageSlices();
519
520     RefPtr<CSSPrimitiveValue> top = valueForImageSliceSide(slices.top());
521
522     RefPtr<CSSPrimitiveValue> right;
523     RefPtr<CSSPrimitiveValue> bottom;
524     RefPtr<CSSPrimitiveValue> left;
525
526     if (slices.right() == slices.top() && slices.bottom() == slices.top() && slices.left() == slices.top()) {
527         right = top;
528         bottom = top;
529         left = top;
530     } else {
531         right = valueForImageSliceSide(slices.right());
532
533         if (slices.bottom() == slices.top() && slices.right() == slices.left()) {
534             bottom = top;
535             left = right;
536         } else {
537             bottom = valueForImageSliceSide(slices.bottom());
538
539             if (slices.left() == slices.right())
540                 left = right;
541             else
542                 left = valueForImageSliceSide(slices.left());
543         }
544     }
545
546     auto quad = Quad::create();
547     quad->setTop(WTFMove(top));
548     quad->setRight(WTFMove(right));
549     quad->setBottom(WTFMove(bottom));
550     quad->setLeft(WTFMove(left));
551
552     return CSSBorderImageSliceValue::create(CSSValuePool::singleton().createValue(WTFMove(quad)), image.fill());
553 }
554
555 static Ref<CSSPrimitiveValue> valueForNinePieceImageQuad(const LengthBox& box)
556 {
557     RefPtr<CSSPrimitiveValue> top;
558     RefPtr<CSSPrimitiveValue> right;
559     RefPtr<CSSPrimitiveValue> bottom;
560     RefPtr<CSSPrimitiveValue> left;
561
562     auto& cssValuePool = CSSValuePool::singleton();
563
564     if (box.top().isRelative())
565         top = cssValuePool.createValue(box.top().value(), CSSPrimitiveValue::CSS_NUMBER);
566     else
567         top = cssValuePool.createValue(box.top());
568
569     if (box.right() == box.top() && box.bottom() == box.top() && box.left() == box.top()) {
570         right = top;
571         bottom = top;
572         left = top;
573     } else {
574         if (box.right().isRelative())
575             right = cssValuePool.createValue(box.right().value(), CSSPrimitiveValue::CSS_NUMBER);
576         else
577             right = cssValuePool.createValue(box.right());
578
579         if (box.bottom() == box.top() && box.right() == box.left()) {
580             bottom = top;
581             left = right;
582         } else {
583             if (box.bottom().isRelative())
584                 bottom = cssValuePool.createValue(box.bottom().value(), CSSPrimitiveValue::CSS_NUMBER);
585             else
586                 bottom = cssValuePool.createValue(box.bottom());
587
588             if (box.left() == box.right())
589                 left = right;
590             else {
591                 if (box.left().isRelative())
592                     left = cssValuePool.createValue(box.left().value(), CSSPrimitiveValue::CSS_NUMBER);
593                 else
594                     left = cssValuePool.createValue(box.left());
595             }
596         }
597     }
598
599     auto quad = Quad::create();
600     quad->setTop(WTFMove(top));
601     quad->setRight(WTFMove(right));
602     quad->setBottom(WTFMove(bottom));
603     quad->setLeft(WTFMove(left));
604
605     return cssValuePool.createValue(WTFMove(quad));
606 }
607
608 static Ref<CSSValue> valueForNinePieceImageRepeat(const NinePieceImage& image)
609 {
610     auto& cssValuePool = CSSValuePool::singleton();
611     auto horizontalRepeat = cssValuePool.createIdentifierValue(valueForRepeatRule(image.horizontalRule()));
612     RefPtr<CSSPrimitiveValue> verticalRepeat;
613     if (image.horizontalRule() == image.verticalRule())
614         verticalRepeat = horizontalRepeat.copyRef();
615     else
616         verticalRepeat = cssValuePool.createIdentifierValue(valueForRepeatRule(image.verticalRule()));
617     return cssValuePool.createValue(Pair::create(WTFMove(horizontalRepeat), WTFMove(verticalRepeat)));
618 }
619
620 static Ref<CSSValue> valueForNinePieceImage(const NinePieceImage& image)
621 {
622     if (!image.hasImage())
623         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
624
625     // Image first.
626     RefPtr<CSSValue> imageValue;
627     if (image.image())
628         imageValue = image.image()->cssValue();
629
630     // Create the image slice.
631     RefPtr<CSSBorderImageSliceValue> imageSlices = valueForNinePieceImageSlice(image);
632
633     // Create the border area slices.
634     RefPtr<CSSValue> borderSlices = valueForNinePieceImageQuad(image.borderSlices());
635
636     // Create the border outset.
637     RefPtr<CSSValue> outset = valueForNinePieceImageQuad(image.outset());
638
639     // Create the repeat rules.
640     RefPtr<CSSValue> repeat = valueForNinePieceImageRepeat(image);
641
642     return createBorderImageValue(WTFMove(imageValue), WTFMove(imageSlices), WTFMove(borderSlices), WTFMove(outset), WTFMove(repeat));
643 }
644
645 inline static Ref<CSSPrimitiveValue> zoomAdjustedPixelValue(double value, const RenderStyle& style)
646 {
647     return CSSValuePool::singleton().createValue(adjustFloatForAbsoluteZoom(value, style), CSSPrimitiveValue::CSS_PX);
648 }
649
650 inline static Ref<CSSPrimitiveValue> zoomAdjustedNumberValue(double value, const RenderStyle& style)
651 {
652     return CSSValuePool::singleton().createValue(value / style.effectiveZoom(), CSSPrimitiveValue::CSS_NUMBER);
653 }
654
655 static Ref<CSSValue> zoomAdjustedPixelValueForLength(const Length& length, const RenderStyle& style)
656 {
657     if (length.isFixed())
658         return zoomAdjustedPixelValue(length.value(), style);
659     return CSSValuePool::singleton().createValue(length, style);
660 }
661
662 static Ref<CSSValue> valueForReflection(const StyleReflection* reflection, const RenderStyle& style)
663 {
664     if (!reflection)
665         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
666
667     RefPtr<CSSPrimitiveValue> offset;
668     if (reflection->offset().isPercentOrCalculated())
669         offset = CSSValuePool::singleton().createValue(reflection->offset().percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
670     else
671         offset = zoomAdjustedPixelValue(reflection->offset().value(), style);
672
673     RefPtr<CSSPrimitiveValue> direction;
674     switch (reflection->direction()) {
675     case ReflectionBelow:
676         direction = CSSValuePool::singleton().createIdentifierValue(CSSValueBelow);
677         break;
678     case ReflectionAbove:
679         direction = CSSValuePool::singleton().createIdentifierValue(CSSValueAbove);
680         break;
681     case ReflectionLeft:
682         direction = CSSValuePool::singleton().createIdentifierValue(CSSValueLeft);
683         break;
684     case ReflectionRight:
685         direction = CSSValuePool::singleton().createIdentifierValue(CSSValueRight);
686         break;
687     }
688
689     return CSSReflectValue::create(direction.releaseNonNull(), offset.releaseNonNull(), valueForNinePieceImage(reflection->mask()));
690 }
691
692 static Ref<CSSValueList> createPositionListForLayer(CSSPropertyID propertyID, const FillLayer& layer, const RenderStyle& style)
693 {
694     auto list = CSSValueList::createSpaceSeparated();
695     if (layer.isBackgroundXOriginSet()) {
696         ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPosition || propertyID == CSSPropertyWebkitMaskPosition);
697         list->append(CSSValuePool::singleton().createValue(layer.backgroundXOrigin()));
698     }
699     list->append(zoomAdjustedPixelValueForLength(layer.xPosition(), style));
700     if (layer.isBackgroundYOriginSet()) {
701         ASSERT(propertyID == CSSPropertyBackgroundPosition || propertyID == CSSPropertyWebkitMaskPosition);
702         list->append(CSSValuePool::singleton().createValue(layer.backgroundYOrigin()));
703     }
704     list->append(zoomAdjustedPixelValueForLength(layer.yPosition(), style));
705     return list;
706 }
707
708 static RefPtr<CSSValue> positionOffsetValue(const RenderStyle& style, CSSPropertyID propertyID)
709 {
710     Length length;
711     switch (propertyID) {
712         case CSSPropertyLeft:
713             length = style.left();
714             break;
715         case CSSPropertyRight:
716             length = style.right();
717             break;
718         case CSSPropertyTop:
719             length = style.top();
720             break;
721         case CSSPropertyBottom:
722             length = style.bottom();
723             break;
724         default:
725             return nullptr;
726     }
727
728     if (style.hasOutOfFlowPosition()) {
729         if (length.isFixed())
730             return zoomAdjustedPixelValue(length.value(), style);
731
732         return CSSValuePool::singleton().createValue(length);
733     }
734
735     if (style.hasInFlowPosition()) {
736         // FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined.
737         // In other words if left is auto and right is not auto, then left's computed value is negative right().
738         // So we should get the opposite length unit and see if it is auto.
739         return CSSValuePool::singleton().createValue(length);
740     }
741
742     return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
743 }
744
745 RefPtr<CSSPrimitiveValue> ComputedStyleExtractor::currentColorOrValidColor(const RenderStyle* style, const Color& color) const
746 {
747     // This function does NOT look at visited information, so that computed style doesn't expose that.
748     if (!color.isValid())
749         return CSSValuePool::singleton().createColorValue(style->color());
750     return CSSValuePool::singleton().createColorValue(color);
751 }
752
753 static Ref<CSSPrimitiveValue> percentageOrZoomAdjustedValue(Length length, const RenderStyle& style)
754 {
755     if (length.isPercent())
756         return CSSValuePool::singleton().createValue(length.percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
757     
758     return zoomAdjustedPixelValue(valueForLength(length, 0), style);
759 }
760
761 static Ref<CSSPrimitiveValue> autoOrZoomAdjustedValue(Length length, const RenderStyle& style)
762 {
763     if (length.isAuto())
764         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
765
766     return zoomAdjustedPixelValue(valueForLength(length, 0), style);
767 }
768
769 static Ref<CSSValueList> borderRadiusCornerValues(const LengthSize& radius, const RenderStyle& style)
770 {
771     auto list = CSSValueList::createSpaceSeparated();
772     list->append(percentageOrZoomAdjustedValue(radius.width, style));
773     list->append(percentageOrZoomAdjustedValue(radius.height, style));
774     return list;
775 }
776
777 static Ref<CSSValue> borderRadiusCornerValue(const LengthSize& radius, const RenderStyle& style)
778 {
779     if (radius.width == radius.height)
780         return percentageOrZoomAdjustedValue(radius.width, style);
781     return borderRadiusCornerValues(radius, style);
782 }
783
784 static Ref<CSSValueList> borderRadiusShorthandValue(const RenderStyle& style)
785 {
786     auto list = CSSValueList::createSlashSeparated();
787     bool showHorizontalBottomLeft = style.borderTopRightRadius().width != style.borderBottomLeftRadius().width;
788     bool showHorizontalBottomRight = showHorizontalBottomLeft || (style.borderBottomRightRadius().width != style.borderTopLeftRadius().width);
789     bool showHorizontalTopRight = showHorizontalBottomRight || (style.borderTopRightRadius().width != style.borderTopLeftRadius().width);
790
791     bool showVerticalBottomLeft = style.borderTopRightRadius().height != style.borderBottomLeftRadius().height;
792     bool showVerticalBottomRight = showVerticalBottomLeft || (style.borderBottomRightRadius().height != style.borderTopLeftRadius().height);
793     bool showVerticalTopRight = showVerticalBottomRight || (style.borderTopRightRadius().height != style.borderTopLeftRadius().height);
794
795     auto topLeftRadius = borderRadiusCornerValues(style.borderTopLeftRadius(), style);
796     auto topRightRadius = borderRadiusCornerValues(style.borderTopRightRadius(), style);
797     auto bottomRightRadius = borderRadiusCornerValues(style.borderBottomRightRadius(), style);
798     auto bottomLeftRadius = borderRadiusCornerValues(style.borderBottomLeftRadius(), style);
799
800     auto horizontalRadii = CSSValueList::createSpaceSeparated();
801     horizontalRadii->append(*topLeftRadius->item(0));
802     if (showHorizontalTopRight)
803         horizontalRadii->append(*topRightRadius->item(0));
804     if (showHorizontalBottomRight)
805         horizontalRadii->append(*bottomRightRadius->item(0));
806     if (showHorizontalBottomLeft)
807         horizontalRadii->append(*bottomLeftRadius->item(0));
808
809     list->append(WTFMove(horizontalRadii));
810
811     auto verticalRadiiList = CSSValueList::createSpaceSeparated();
812     verticalRadiiList->append(*topLeftRadius->item(1));
813     if (showVerticalTopRight)
814         verticalRadiiList->append(*topRightRadius->item(1));
815     if (showVerticalBottomRight)
816         verticalRadiiList->append(*bottomRightRadius->item(1));
817     if (showVerticalBottomLeft)
818         verticalRadiiList->append(*bottomLeftRadius->item(1));
819
820     if (!verticalRadiiList->equals(downcast<CSSValueList>(*list->item(0))))
821         list->append(WTFMove(verticalRadiiList));
822
823     return list;
824 }
825
826 static LayoutRect sizingBox(RenderObject& renderer)
827 {
828     if (!is<RenderBox>(renderer))
829         return LayoutRect();
830
831     auto& box = downcast<RenderBox>(renderer);
832     return box.style().boxSizing() == BORDER_BOX ? box.borderBoxRect() : box.computedCSSContentBoxRect();
833 }
834
835 static Ref<CSSFunctionValue> matrixTransformValue(const TransformationMatrix& transform, const RenderStyle& style)
836 {
837     RefPtr<CSSFunctionValue> transformValue;
838     auto& cssValuePool = CSSValuePool::singleton();
839     if (transform.isAffine()) {
840         transformValue = CSSFunctionValue::create(CSSValueMatrix);
841
842         transformValue->append(cssValuePool.createValue(transform.a(), CSSPrimitiveValue::CSS_NUMBER));
843         transformValue->append(cssValuePool.createValue(transform.b(), CSSPrimitiveValue::CSS_NUMBER));
844         transformValue->append(cssValuePool.createValue(transform.c(), CSSPrimitiveValue::CSS_NUMBER));
845         transformValue->append(cssValuePool.createValue(transform.d(), CSSPrimitiveValue::CSS_NUMBER));
846         transformValue->append(zoomAdjustedNumberValue(transform.e(), style));
847         transformValue->append(zoomAdjustedNumberValue(transform.f(), style));
848     } else {
849         transformValue = CSSFunctionValue::create(CSSValueMatrix3d);
850
851         transformValue->append(cssValuePool.createValue(transform.m11(), CSSPrimitiveValue::CSS_NUMBER));
852         transformValue->append(cssValuePool.createValue(transform.m12(), CSSPrimitiveValue::CSS_NUMBER));
853         transformValue->append(cssValuePool.createValue(transform.m13(), CSSPrimitiveValue::CSS_NUMBER));
854         transformValue->append(cssValuePool.createValue(transform.m14(), CSSPrimitiveValue::CSS_NUMBER));
855
856         transformValue->append(cssValuePool.createValue(transform.m21(), CSSPrimitiveValue::CSS_NUMBER));
857         transformValue->append(cssValuePool.createValue(transform.m22(), CSSPrimitiveValue::CSS_NUMBER));
858         transformValue->append(cssValuePool.createValue(transform.m23(), CSSPrimitiveValue::CSS_NUMBER));
859         transformValue->append(cssValuePool.createValue(transform.m24(), CSSPrimitiveValue::CSS_NUMBER));
860
861         transformValue->append(cssValuePool.createValue(transform.m31(), CSSPrimitiveValue::CSS_NUMBER));
862         transformValue->append(cssValuePool.createValue(transform.m32(), CSSPrimitiveValue::CSS_NUMBER));
863         transformValue->append(cssValuePool.createValue(transform.m33(), CSSPrimitiveValue::CSS_NUMBER));
864         transformValue->append(cssValuePool.createValue(transform.m34(), CSSPrimitiveValue::CSS_NUMBER));
865
866         transformValue->append(zoomAdjustedNumberValue(transform.m41(), style));
867         transformValue->append(zoomAdjustedNumberValue(transform.m42(), style));
868         transformValue->append(zoomAdjustedNumberValue(transform.m43(), style));
869         transformValue->append(cssValuePool.createValue(transform.m44(), CSSPrimitiveValue::CSS_NUMBER));
870     }
871
872     return transformValue.releaseNonNull();
873 }
874
875 static Ref<CSSValue> computedTransform(RenderObject* renderer, const RenderStyle& style)
876 {
877     if (!renderer || !renderer->hasTransform())
878         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
879
880     FloatRect pixelSnappedRect;
881     if (is<RenderBox>(*renderer))
882         pixelSnappedRect = snapRectToDevicePixels(downcast<RenderBox>(*renderer).borderBoxRect(), renderer->document().deviceScaleFactor());
883
884     TransformationMatrix transform;
885     style.applyTransform(transform, pixelSnappedRect, RenderStyle::ExcludeTransformOrigin);
886     // Note that this does not flatten to an affine transform if ENABLE(3D_TRANSFORMS) is off, by design.
887
888     // FIXME: Need to print out individual functions (https://bugs.webkit.org/show_bug.cgi?id=23924)
889     auto list = CSSValueList::createSpaceSeparated();
890     list->append(matrixTransformValue(transform, style));
891     return WTFMove(list);
892 }
893
894 static inline Ref<CSSPrimitiveValue> adjustLengthForZoom(double length, const RenderStyle& style, AdjustPixelValuesForComputedStyle adjust)
895 {
896     return adjust == AdjustPixelValues ? zoomAdjustedPixelValue(length, style) : CSSValuePool::singleton().createValue(length, CSSPrimitiveValue::CSS_PX);
897 }
898
899 static inline Ref<CSSPrimitiveValue> adjustLengthForZoom(const Length& length, const RenderStyle& style, AdjustPixelValuesForComputedStyle adjust)
900 {
901     return adjust == AdjustPixelValues ? zoomAdjustedPixelValue(length.value(), style) : CSSValuePool::singleton().createValue(length);
902 }
903
904 Ref<CSSValue> ComputedStyleExtractor::valueForShadow(const ShadowData* shadow, CSSPropertyID propertyID, const RenderStyle& style, AdjustPixelValuesForComputedStyle adjust)
905 {
906     auto& cssValuePool = CSSValuePool::singleton();
907     if (!shadow)
908         return cssValuePool.createIdentifierValue(CSSValueNone);
909
910     auto list = CSSValueList::createCommaSeparated();
911     for (const ShadowData* currShadowData = shadow; currShadowData; currShadowData = currShadowData->next()) {
912         auto x = adjustLengthForZoom(currShadowData->x(), style, adjust);
913         auto y = adjustLengthForZoom(currShadowData->y(), style, adjust);
914         auto blur = adjustLengthForZoom(currShadowData->radius(), style, adjust);
915         auto spread = propertyID == CSSPropertyTextShadow ? RefPtr<CSSPrimitiveValue>() : adjustLengthForZoom(currShadowData->spread(), style, adjust);
916         auto style = propertyID == CSSPropertyTextShadow || currShadowData->style() == Normal ? RefPtr<CSSPrimitiveValue>() : cssValuePool.createIdentifierValue(CSSValueInset);
917         auto color = cssValuePool.createColorValue(currShadowData->color());
918         list->prepend(CSSShadowValue::create(WTFMove(x), WTFMove(y), WTFMove(blur), WTFMove(spread), WTFMove(style), WTFMove(color)));
919     }
920     return WTFMove(list);
921 }
922
923 Ref<CSSValue> ComputedStyleExtractor::valueForFilter(const RenderStyle& style, const FilterOperations& filterOperations, AdjustPixelValuesForComputedStyle adjust)
924 {
925     auto& cssValuePool = CSSValuePool::singleton();
926     if (filterOperations.operations().isEmpty())
927         return cssValuePool.createIdentifierValue(CSSValueNone);
928
929     auto list = CSSValueList::createSpaceSeparated();
930
931     Vector<RefPtr<FilterOperation>>::const_iterator end = filterOperations.operations().end();
932     for (Vector<RefPtr<FilterOperation>>::const_iterator it = filterOperations.operations().begin(); it != end; ++it) {
933         FilterOperation& filterOperation = **it;
934
935         if (filterOperation.type() == FilterOperation::REFERENCE) {
936             ReferenceFilterOperation& referenceOperation = downcast<ReferenceFilterOperation>(filterOperation);
937             list->append(cssValuePool.createValue(referenceOperation.url(), CSSPrimitiveValue::CSS_URI));
938         } else {
939             RefPtr<CSSFunctionValue> filterValue;
940             switch (filterOperation.type()) {
941             case FilterOperation::GRAYSCALE: {
942                 filterValue = CSSFunctionValue::create(CSSValueGrayscale);
943                 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
944                 break;
945             }
946             case FilterOperation::SEPIA: {
947                 filterValue = CSSFunctionValue::create(CSSValueSepia);
948                 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
949                 break;
950             }
951             case FilterOperation::SATURATE: {
952                 filterValue = CSSFunctionValue::create(CSSValueSaturate);
953                 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
954                 break;
955             }
956             case FilterOperation::HUE_ROTATE: {
957                 filterValue = CSSFunctionValue::create(CSSValueHueRotate);
958                 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_DEG));
959                 break;
960             }
961             case FilterOperation::INVERT: {
962                 filterValue = CSSFunctionValue::create(CSSValueInvert);
963                 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
964                 break;
965             }
966             case FilterOperation::OPACITY: {
967                 filterValue = CSSFunctionValue::create(CSSValueOpacity);
968                 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
969                 break;
970             }
971             case FilterOperation::BRIGHTNESS: {
972                 filterValue = CSSFunctionValue::create(CSSValueBrightness);
973                 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
974                 break;
975             }
976             case FilterOperation::CONTRAST: {
977                 filterValue = CSSFunctionValue::create(CSSValueContrast);
978                 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
979                 break;
980             }
981             case FilterOperation::BLUR: {
982                 filterValue = CSSFunctionValue::create(CSSValueBlur);
983                 filterValue->append(adjustLengthForZoom(downcast<BlurFilterOperation>(filterOperation).stdDeviation(), style, adjust));
984                 break;
985             }
986             case FilterOperation::DROP_SHADOW: {
987                 DropShadowFilterOperation& dropShadowOperation = downcast<DropShadowFilterOperation>(filterOperation);
988                 filterValue = CSSFunctionValue::create(CSSValueDropShadow);
989                 // We want our computed style to look like that of a text shadow (has neither spread nor inset style).
990                 ShadowData shadowData = ShadowData(dropShadowOperation.location(), dropShadowOperation.stdDeviation(), 0, Normal, false, dropShadowOperation.color());
991                 filterValue->append(valueForShadow(&shadowData, CSSPropertyTextShadow, style, adjust));
992                 break;
993             }
994             default:
995                 ASSERT_NOT_REACHED();
996                 filterValue = CSSFunctionValue::create(CSSValueInvalid);
997                 break;
998             }
999             list->append(filterValue.releaseNonNull());
1000         }
1001     }
1002     return WTFMove(list);
1003 }
1004
1005 static Ref<CSSValue> specifiedValueForGridTrackBreadth(const GridLength& trackBreadth, const RenderStyle& style)
1006 {
1007     if (!trackBreadth.isLength())
1008         return CSSValuePool::singleton().createValue(trackBreadth.flex(), CSSPrimitiveValue::CSS_FR);
1009
1010     const Length& trackBreadthLength = trackBreadth.length();
1011     if (trackBreadthLength.isAuto())
1012         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1013     return zoomAdjustedPixelValueForLength(trackBreadthLength, style);
1014 }
1015
1016 static Ref<CSSValue> specifiedValueForGridTrackSize(const GridTrackSize& trackSize, const RenderStyle& style)
1017 {
1018     switch (trackSize.type()) {
1019     case LengthTrackSizing:
1020         return specifiedValueForGridTrackBreadth(trackSize.minTrackBreadth(), style);
1021     case FitContentTrackSizing: {
1022         auto fitContentTrackSize = CSSFunctionValue::create(CSSValueFitContent);
1023         fitContentTrackSize->append(zoomAdjustedPixelValueForLength(trackSize.fitContentTrackBreadth().length(), style));
1024         return WTFMove(fitContentTrackSize);
1025     }
1026     default:
1027         ASSERT(trackSize.type() == MinMaxTrackSizing);
1028         if (trackSize.minTrackBreadth().isAuto() && trackSize.maxTrackBreadth().isFlex())
1029             return CSSValuePool::singleton().createValue(trackSize.maxTrackBreadth().flex(), CSSPrimitiveValue::CSS_FR);
1030
1031         auto minMaxTrackBreadths = CSSFunctionValue::create(CSSValueMinmax);
1032         minMaxTrackBreadths->append(specifiedValueForGridTrackBreadth(trackSize.minTrackBreadth(), style));
1033         minMaxTrackBreadths->append(specifiedValueForGridTrackBreadth(trackSize.maxTrackBreadth(), style));
1034         return WTFMove(minMaxTrackBreadths);
1035     }
1036 }
1037
1038 class OrderedNamedLinesCollector {
1039     WTF_MAKE_NONCOPYABLE(OrderedNamedLinesCollector);
1040 public:
1041     OrderedNamedLinesCollector(const RenderStyle& style, bool isRowAxis, unsigned autoRepeatTracksCount)
1042         : m_orderedNamedGridLines(isRowAxis ? style.orderedNamedGridColumnLines() : style.orderedNamedGridRowLines())
1043         , m_orderedNamedAutoRepeatGridLines(isRowAxis ? style.autoRepeatOrderedNamedGridColumnLines() : style.autoRepeatOrderedNamedGridRowLines())
1044         , m_insertionPoint(isRowAxis ? style.gridAutoRepeatColumnsInsertionPoint() : style.gridAutoRepeatRowsInsertionPoint())
1045         , m_autoRepeatTotalTracks(autoRepeatTracksCount)
1046         , m_autoRepeatTrackListLength(isRowAxis ? style.gridAutoRepeatColumns().size() : style.gridAutoRepeatRows().size())
1047     {
1048     }
1049
1050     bool isEmpty() const { return m_orderedNamedGridLines.isEmpty() && m_orderedNamedAutoRepeatGridLines.isEmpty(); }
1051     void collectLineNamesForIndex(CSSGridLineNamesValue&, unsigned index) const;
1052
1053 private:
1054
1055     enum NamedLinesType { NamedLines, AutoRepeatNamedLines };
1056     void appendLines(CSSGridLineNamesValue&, unsigned index, NamedLinesType) const;
1057
1058     const OrderedNamedGridLinesMap& m_orderedNamedGridLines;
1059     const OrderedNamedGridLinesMap& m_orderedNamedAutoRepeatGridLines;
1060     unsigned m_insertionPoint;
1061     unsigned m_autoRepeatTotalTracks;
1062     unsigned m_autoRepeatTrackListLength;
1063 };
1064
1065 void OrderedNamedLinesCollector::appendLines(CSSGridLineNamesValue& lineNamesValue, unsigned index, NamedLinesType type) const
1066 {
1067     auto iter = type == NamedLines ? m_orderedNamedGridLines.find(index) : m_orderedNamedAutoRepeatGridLines.find(index);
1068     auto endIter = type == NamedLines ? m_orderedNamedGridLines.end() : m_orderedNamedAutoRepeatGridLines.end();
1069     if (iter == endIter)
1070         return;
1071
1072     auto& cssValuePool = CSSValuePool::singleton();
1073     for (auto lineName : iter->value)
1074         lineNamesValue.append(cssValuePool.createValue(lineName, CSSPrimitiveValue::CSS_STRING));
1075 }
1076
1077 void OrderedNamedLinesCollector::collectLineNamesForIndex(CSSGridLineNamesValue& lineNamesValue, unsigned i) const
1078 {
1079     ASSERT(!isEmpty());
1080     if (m_orderedNamedAutoRepeatGridLines.isEmpty() || i < m_insertionPoint) {
1081         appendLines(lineNamesValue, i, NamedLines);
1082         return;
1083     }
1084
1085     ASSERT(m_autoRepeatTotalTracks);
1086
1087     if (i > m_insertionPoint + m_autoRepeatTotalTracks) {
1088         appendLines(lineNamesValue, i - (m_autoRepeatTotalTracks - 1), NamedLines);
1089         return;
1090     }
1091
1092     if (i == m_insertionPoint) {
1093         appendLines(lineNamesValue, i, NamedLines);
1094         appendLines(lineNamesValue, 0, AutoRepeatNamedLines);
1095         return;
1096     }
1097
1098     if (i == m_insertionPoint + m_autoRepeatTotalTracks) {
1099         appendLines(lineNamesValue, m_autoRepeatTrackListLength, AutoRepeatNamedLines);
1100         appendLines(lineNamesValue, m_insertionPoint + 1, NamedLines);
1101         return;
1102     }
1103
1104     unsigned autoRepeatIndexInFirstRepetition = (i - m_insertionPoint) % m_autoRepeatTrackListLength;
1105     if (!autoRepeatIndexInFirstRepetition && i > m_insertionPoint)
1106         appendLines(lineNamesValue, m_autoRepeatTrackListLength, AutoRepeatNamedLines);
1107     appendLines(lineNamesValue, autoRepeatIndexInFirstRepetition, AutoRepeatNamedLines);
1108 }
1109
1110 static void addValuesForNamedGridLinesAtIndex(OrderedNamedLinesCollector& collector, unsigned i, CSSValueList& list)
1111 {
1112     if (collector.isEmpty())
1113         return;
1114
1115     auto lineNames = CSSGridLineNamesValue::create();
1116     collector.collectLineNamesForIndex(lineNames.get(), i);
1117     if (lineNames->length())
1118         list.append(WTFMove(lineNames));
1119 }
1120
1121 static Ref<CSSValueList> valueForGridTrackSizeList(GridTrackSizingDirection direction, const RenderStyle& style)
1122 {
1123     auto& autoTrackSizes = direction == ForColumns ? style.gridAutoColumns() : style.gridAutoRows();
1124
1125     auto list = CSSValueList::createSpaceSeparated();
1126     for (auto& trackSize : autoTrackSizes)
1127         list->append(specifiedValueForGridTrackSize(trackSize, style));
1128     return list;
1129 }
1130
1131 static Ref<CSSValue> valueForGridTrackList(GridTrackSizingDirection direction, RenderObject* renderer, const RenderStyle& style)
1132 {
1133     bool isRowAxis = direction == ForColumns;
1134     bool isRenderGrid = is<RenderGrid>(renderer);
1135     auto& trackSizes = isRowAxis ? style.gridColumns() : style.gridRows();
1136     auto& autoRepeatTrackSizes = isRowAxis ? style.gridAutoRepeatColumns() : style.gridAutoRepeatRows();
1137
1138     // Handle the 'none' case.
1139     bool trackListIsEmpty = trackSizes.isEmpty() && autoRepeatTrackSizes.isEmpty();
1140     if (isRenderGrid && trackListIsEmpty) {
1141         // For grids we should consider every listed track, whether implicitly or explicitly
1142         // created. Empty grids have a sole grid line per axis.
1143         auto& grid = downcast<RenderGrid>(*renderer);
1144         auto& positions = isRowAxis ? grid.columnPositions() : grid.rowPositions();
1145         trackListIsEmpty = positions.size() == 1;
1146     }
1147
1148     if (trackListIsEmpty)
1149         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1150
1151     unsigned autoRepeatTotalTracks = isRenderGrid ? downcast<RenderGrid>(renderer)->autoRepeatCountForDirection(direction) : 0;
1152     OrderedNamedLinesCollector collector(style, isRowAxis, autoRepeatTotalTracks);
1153     auto list = CSSValueList::createSpaceSeparated();
1154     unsigned insertionIndex;
1155     if (isRenderGrid) {
1156         auto computedTrackSizes = downcast<RenderGrid>(*renderer).trackSizesForComputedStyle(direction);
1157         unsigned numTracks = computedTrackSizes.size();
1158
1159         for (unsigned i = 0; i < numTracks; ++i) {
1160             addValuesForNamedGridLinesAtIndex(collector, i, list.get());
1161             list->append(zoomAdjustedPixelValue(computedTrackSizes[i], style));
1162         }
1163         addValuesForNamedGridLinesAtIndex(collector, numTracks + 1, list.get());
1164         insertionIndex = numTracks;
1165     } else {
1166         for (unsigned i = 0; i < trackSizes.size(); ++i) {
1167             addValuesForNamedGridLinesAtIndex(collector, i, list.get());
1168             list->append(specifiedValueForGridTrackSize(trackSizes[i], style));
1169         }
1170         insertionIndex = trackSizes.size();
1171     }
1172
1173     // Those are the trailing <ident>* allowed in the syntax.
1174     addValuesForNamedGridLinesAtIndex(collector, insertionIndex, list.get());
1175     return WTFMove(list);
1176 }
1177
1178 static Ref<CSSValue> valueForGridPosition(const GridPosition& position)
1179 {
1180     auto& cssValuePool = CSSValuePool::singleton();
1181     if (position.isAuto())
1182         return cssValuePool.createIdentifierValue(CSSValueAuto);
1183
1184     if (position.isNamedGridArea())
1185         return cssValuePool.createValue(position.namedGridLine(), CSSPrimitiveValue::CSS_STRING);
1186
1187     auto list = CSSValueList::createSpaceSeparated();
1188     if (position.isSpan()) {
1189         list->append(cssValuePool.createIdentifierValue(CSSValueSpan));
1190         list->append(cssValuePool.createValue(position.spanPosition(), CSSPrimitiveValue::CSS_NUMBER));
1191     } else
1192         list->append(cssValuePool.createValue(position.integerPosition(), CSSPrimitiveValue::CSS_NUMBER));
1193
1194     if (!position.namedGridLine().isNull())
1195         list->append(cssValuePool.createValue(position.namedGridLine(), CSSPrimitiveValue::CSS_STRING));
1196     return WTFMove(list);
1197 }
1198
1199 static Ref<CSSValue> createTransitionPropertyValue(const Animation& animation)
1200 {
1201     if (animation.animationMode() == Animation::AnimateNone)
1202         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1203     if (animation.animationMode() == Animation::AnimateAll)
1204         return CSSValuePool::singleton().createIdentifierValue(CSSValueAll);
1205     return CSSValuePool::singleton().createValue(getPropertyNameString(animation.property()), CSSPrimitiveValue::CSS_STRING);
1206 }
1207
1208 static Ref<CSSValueList> transitionPropertyValue(const AnimationList* animationList)
1209 {
1210     auto list = CSSValueList::createCommaSeparated();
1211     if (animationList) {
1212         for (size_t i = 0; i < animationList->size(); ++i)
1213             list->append(createTransitionPropertyValue(animationList->animation(i)));
1214     } else
1215         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAll));
1216     return list;
1217 }
1218
1219 #if ENABLE(CSS_SCROLL_SNAP)
1220
1221 static Ref<CSSValueList> valueForScrollSnapType(const ScrollSnapType& type)
1222 {
1223     auto value = CSSValueList::createSpaceSeparated();
1224     if (type.strictness == ScrollSnapStrictness::None)
1225         value->append(CSSValuePool::singleton().createValue(CSSValueNone));
1226     else {
1227         value->append(CSSPrimitiveValue::create(type.axis));
1228         value->append(CSSPrimitiveValue::create(type.strictness));
1229     }
1230     return value;
1231 }
1232
1233 static Ref<CSSValueList> valueForScrollSnapAlignment(const ScrollSnapAlign& alignment)
1234 {
1235     auto value = CSSValueList::createSpaceSeparated();
1236     value->append(CSSPrimitiveValue::create(alignment.x));
1237     value->append(CSSPrimitiveValue::create(alignment.y));
1238     return value;
1239 }
1240
1241 #endif
1242
1243 static Ref<CSSValue> willChangePropertyValue(const WillChangeData* willChangeData)
1244 {
1245     auto& cssValuePool = CSSValuePool::singleton();
1246     if (!willChangeData || !willChangeData->numFeatures())
1247         return cssValuePool.createIdentifierValue(CSSValueAuto);
1248
1249     auto list = CSSValueList::createCommaSeparated();
1250     for (size_t i = 0; i < willChangeData->numFeatures(); ++i) {
1251         WillChangeData::FeaturePropertyPair feature = willChangeData->featureAt(i);
1252         switch (feature.first) {
1253         case WillChangeData::ScrollPosition:
1254             list->append(cssValuePool.createIdentifierValue(CSSValueScrollPosition));
1255             break;
1256         case WillChangeData::Contents:
1257             list->append(cssValuePool.createIdentifierValue(CSSValueContents));
1258             break;
1259         case WillChangeData::Property:
1260             list->append(cssValuePool.createIdentifierValue(feature.second));
1261             break;
1262         case WillChangeData::Invalid:
1263             ASSERT_NOT_REACHED();
1264             break;
1265         }
1266     }
1267
1268     return WTFMove(list);
1269 }
1270
1271 static inline void appendLigaturesValue(CSSValueList& list, FontVariantLigatures value, CSSValueID yesValue, CSSValueID noValue)
1272 {
1273     switch (value) {
1274     case FontVariantLigatures::Normal:
1275         return;
1276     case FontVariantLigatures::No:
1277         list.append(CSSValuePool::singleton().createIdentifierValue(noValue));
1278         return;
1279     case FontVariantLigatures::Yes:
1280         list.append(CSSValuePool::singleton().createIdentifierValue(yesValue));
1281         return;
1282     }
1283     ASSERT_NOT_REACHED();
1284 }
1285
1286 static Ref<CSSValue> fontVariantLigaturesPropertyValue(FontVariantLigatures common, FontVariantLigatures discretionary, FontVariantLigatures historical, FontVariantLigatures contextualAlternates)
1287 {
1288     auto& cssValuePool = CSSValuePool::singleton();
1289     if (common == FontVariantLigatures::No && discretionary == FontVariantLigatures::No && historical == FontVariantLigatures::No && contextualAlternates == FontVariantLigatures::No)
1290         return cssValuePool.createIdentifierValue(CSSValueNone);
1291     if (common == FontVariantLigatures::Normal && discretionary == FontVariantLigatures::Normal && historical == FontVariantLigatures::Normal && contextualAlternates == FontVariantLigatures::Normal)
1292         return cssValuePool.createIdentifierValue(CSSValueNormal);
1293
1294     auto valueList = CSSValueList::createSpaceSeparated();
1295     appendLigaturesValue(valueList, common, CSSValueCommonLigatures, CSSValueNoCommonLigatures);
1296     appendLigaturesValue(valueList, discretionary, CSSValueDiscretionaryLigatures, CSSValueNoDiscretionaryLigatures);
1297     appendLigaturesValue(valueList, historical, CSSValueHistoricalLigatures, CSSValueNoHistoricalLigatures);
1298     appendLigaturesValue(valueList, contextualAlternates, CSSValueContextual, CSSValueNoContextual);
1299     return WTFMove(valueList);
1300 }
1301
1302 static Ref<CSSValue> fontVariantPositionPropertyValue(FontVariantPosition position)
1303 {
1304     auto& cssValuePool = CSSValuePool::singleton();
1305     CSSValueID valueID = CSSValueNormal;
1306     switch (position) {
1307     case FontVariantPosition::Normal:
1308         break;
1309     case FontVariantPosition::Subscript:
1310         valueID = CSSValueSub;
1311         break;
1312     case FontVariantPosition::Superscript:
1313         valueID = CSSValueSuper;
1314         break;
1315     }
1316     return cssValuePool.createIdentifierValue(valueID);
1317 }
1318
1319 static Ref<CSSValue> fontVariantCapsPropertyValue(FontVariantCaps caps)
1320 {
1321     auto& cssValuePool = CSSValuePool::singleton();
1322     CSSValueID valueID = CSSValueNormal;
1323     switch (caps) {
1324     case FontVariantCaps::Normal:
1325         break;
1326     case FontVariantCaps::Small:
1327         valueID = CSSValueSmallCaps;
1328         break;
1329     case FontVariantCaps::AllSmall:
1330         valueID = CSSValueAllSmallCaps;
1331         break;
1332     case FontVariantCaps::Petite:
1333         valueID = CSSValuePetiteCaps;
1334         break;
1335     case FontVariantCaps::AllPetite:
1336         valueID = CSSValueAllPetiteCaps;
1337         break;
1338     case FontVariantCaps::Unicase:
1339         valueID = CSSValueUnicase;
1340         break;
1341     case FontVariantCaps::Titling:
1342         valueID = CSSValueTitlingCaps;
1343         break;
1344     }
1345     return cssValuePool.createIdentifierValue(valueID);
1346 }
1347
1348 static Ref<CSSValue> fontVariantNumericPropertyValue(FontVariantNumericFigure figure, FontVariantNumericSpacing spacing, FontVariantNumericFraction fraction, FontVariantNumericOrdinal ordinal, FontVariantNumericSlashedZero slashedZero)
1349 {
1350     auto& cssValuePool = CSSValuePool::singleton();
1351     if (figure == FontVariantNumericFigure::Normal && spacing == FontVariantNumericSpacing::Normal && fraction == FontVariantNumericFraction::Normal && ordinal == FontVariantNumericOrdinal::Normal && slashedZero == FontVariantNumericSlashedZero::Normal)
1352         return cssValuePool.createIdentifierValue(CSSValueNormal);
1353
1354     auto valueList = CSSValueList::createSpaceSeparated();
1355     switch (figure) {
1356     case FontVariantNumericFigure::Normal:
1357         break;
1358     case FontVariantNumericFigure::LiningNumbers:
1359         valueList->append(cssValuePool.createIdentifierValue(CSSValueLiningNums));
1360         break;
1361     case FontVariantNumericFigure::OldStyleNumbers:
1362         valueList->append(cssValuePool.createIdentifierValue(CSSValueOldstyleNums));
1363         break;
1364     }
1365
1366     switch (spacing) {
1367     case FontVariantNumericSpacing::Normal:
1368         break;
1369     case FontVariantNumericSpacing::ProportionalNumbers:
1370         valueList->append(cssValuePool.createIdentifierValue(CSSValueProportionalNums));
1371         break;
1372     case FontVariantNumericSpacing::TabularNumbers:
1373         valueList->append(cssValuePool.createIdentifierValue(CSSValueTabularNums));
1374         break;
1375     }
1376
1377     switch (fraction) {
1378     case FontVariantNumericFraction::Normal:
1379         break;
1380     case FontVariantNumericFraction::DiagonalFractions:
1381         valueList->append(cssValuePool.createIdentifierValue(CSSValueDiagonalFractions));
1382         break;
1383     case FontVariantNumericFraction::StackedFractions:
1384         valueList->append(cssValuePool.createIdentifierValue(CSSValueStackedFractions));
1385         break;
1386     }
1387
1388     if (ordinal == FontVariantNumericOrdinal::Yes)
1389         valueList->append(cssValuePool.createIdentifierValue(CSSValueOrdinal));
1390     if (slashedZero == FontVariantNumericSlashedZero::Yes)
1391         valueList->append(cssValuePool.createIdentifierValue(CSSValueSlashedZero));
1392
1393     return WTFMove(valueList);
1394 }
1395
1396 static Ref<CSSValue> fontVariantAlternatesPropertyValue(FontVariantAlternates alternates)
1397 {
1398     auto& cssValuePool = CSSValuePool::singleton();
1399     CSSValueID valueID = CSSValueNormal;
1400     switch (alternates) {
1401     case FontVariantAlternates::Normal:
1402         break;
1403     case FontVariantAlternates::HistoricalForms:
1404         valueID = CSSValueHistoricalForms;
1405         break;
1406     }
1407     return cssValuePool.createIdentifierValue(valueID);
1408 }
1409
1410 static Ref<CSSValue> fontVariantEastAsianPropertyValue(FontVariantEastAsianVariant variant, FontVariantEastAsianWidth width, FontVariantEastAsianRuby ruby)
1411 {
1412     auto& cssValuePool = CSSValuePool::singleton();
1413     if (variant == FontVariantEastAsianVariant::Normal && width == FontVariantEastAsianWidth::Normal && ruby == FontVariantEastAsianRuby::Normal)
1414         return cssValuePool.createIdentifierValue(CSSValueNormal);
1415
1416     auto valueList = CSSValueList::createSpaceSeparated();
1417     switch (variant) {
1418     case FontVariantEastAsianVariant::Normal:
1419         break;
1420     case FontVariantEastAsianVariant::Jis78:
1421         valueList->append(cssValuePool.createIdentifierValue(CSSValueJis78));
1422         break;
1423     case FontVariantEastAsianVariant::Jis83:
1424         valueList->append(cssValuePool.createIdentifierValue(CSSValueJis83));
1425         break;
1426     case FontVariantEastAsianVariant::Jis90:
1427         valueList->append(cssValuePool.createIdentifierValue(CSSValueJis90));
1428         break;
1429     case FontVariantEastAsianVariant::Jis04:
1430         valueList->append(cssValuePool.createIdentifierValue(CSSValueJis04));
1431         break;
1432     case FontVariantEastAsianVariant::Simplified:
1433         valueList->append(cssValuePool.createIdentifierValue(CSSValueSimplified));
1434         break;
1435     case FontVariantEastAsianVariant::Traditional:
1436         valueList->append(cssValuePool.createIdentifierValue(CSSValueTraditional));
1437         break;
1438     }
1439
1440     switch (width) {
1441     case FontVariantEastAsianWidth::Normal:
1442         break;
1443     case FontVariantEastAsianWidth::Full:
1444         valueList->append(cssValuePool.createIdentifierValue(CSSValueFullWidth));
1445         break;
1446     case FontVariantEastAsianWidth::Proportional:
1447         valueList->append(cssValuePool.createIdentifierValue(CSSValueProportionalWidth));
1448         break;
1449     }
1450
1451     if (ruby == FontVariantEastAsianRuby::Yes)
1452         valueList->append(cssValuePool.createIdentifierValue(CSSValueRuby));
1453
1454     return WTFMove(valueList);
1455 }
1456
1457 static Ref<CSSValueList> delayValue(const AnimationList* animationList)
1458 {
1459     auto& cssValuePool = CSSValuePool::singleton();
1460     auto list = CSSValueList::createCommaSeparated();
1461     if (animationList) {
1462         for (size_t i = 0; i < animationList->size(); ++i)
1463             list->append(cssValuePool.createValue(animationList->animation(i).delay(), CSSPrimitiveValue::CSS_S));
1464     } else {
1465         // Note that initialAnimationDelay() is used for both transitions and animations
1466         list->append(cssValuePool.createValue(Animation::initialDelay(), CSSPrimitiveValue::CSS_S));
1467     }
1468     return list;
1469 }
1470
1471 static Ref<CSSValueList> durationValue(const AnimationList* animationList)
1472 {
1473     auto& cssValuePool = CSSValuePool::singleton();
1474     auto list = CSSValueList::createCommaSeparated();
1475     if (animationList) {
1476         for (size_t i = 0; i < animationList->size(); ++i)
1477             list->append(cssValuePool.createValue(animationList->animation(i).duration(), CSSPrimitiveValue::CSS_S));
1478     } else {
1479         // Note that initialAnimationDuration() is used for both transitions and animations
1480         list->append(cssValuePool.createValue(Animation::initialDuration(), CSSPrimitiveValue::CSS_S));
1481     }
1482     return list;
1483 }
1484
1485 static Ref<CSSValue> createTimingFunctionValue(const TimingFunction& timingFunction)
1486 {
1487     switch (timingFunction.type()) {
1488     case TimingFunction::CubicBezierFunction: {
1489         auto& function = static_cast<const CubicBezierTimingFunction&>(timingFunction);
1490         if (function.timingFunctionPreset() != CubicBezierTimingFunction::Custom) {
1491             CSSValueID valueId = CSSValueInvalid;
1492             switch (function.timingFunctionPreset()) {
1493             case CubicBezierTimingFunction::Ease:
1494                 valueId = CSSValueEase;
1495                 break;
1496             case CubicBezierTimingFunction::EaseIn:
1497                 valueId = CSSValueEaseIn;
1498                 break;
1499             case CubicBezierTimingFunction::EaseOut:
1500                 valueId = CSSValueEaseOut;
1501                 break;
1502             default:
1503                 ASSERT(function.timingFunctionPreset() == CubicBezierTimingFunction::EaseInOut);
1504                 valueId = CSSValueEaseInOut;
1505                 break;
1506             }
1507             return CSSValuePool::singleton().createIdentifierValue(valueId);
1508         }
1509         return CSSCubicBezierTimingFunctionValue::create(function.x1(), function.y1(), function.x2(), function.y2());
1510     }
1511     case TimingFunction::StepsFunction: {
1512         auto& function = static_cast<const StepsTimingFunction&>(timingFunction);
1513         return CSSStepsTimingFunctionValue::create(function.numberOfSteps(), function.stepAtStart());
1514     }
1515     case TimingFunction::SpringFunction: {
1516         auto& function = static_cast<const SpringTimingFunction&>(timingFunction);
1517         return CSSSpringTimingFunctionValue::create(function.mass(), function.stiffness(), function.damping(), function.initialVelocity());
1518     }
1519     default:
1520         ASSERT(timingFunction.type() == TimingFunction::LinearFunction);
1521         return CSSValuePool::singleton().createIdentifierValue(CSSValueLinear);
1522     }
1523 }
1524
1525 static Ref<CSSValueList> timingFunctionValue(const AnimationList* animationList)
1526 {
1527     auto list = CSSValueList::createCommaSeparated();
1528     if (animationList) {
1529         for (size_t i = 0; i < animationList->size(); ++i)
1530             list->append(createTimingFunctionValue(*animationList->animation(i).timingFunction()));
1531     } else
1532         // Note that initialAnimationTimingFunction() is used for both transitions and animations
1533         list->append(createTimingFunctionValue(Animation::initialTimingFunction()));
1534     return list;
1535 }
1536
1537 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
1538
1539 static Ref<CSSValue> createAnimationTriggerValue(const AnimationTrigger& trigger, const RenderStyle& style)
1540 {
1541     switch (trigger.type()) {
1542     case AnimationTrigger::AnimationTriggerType::ScrollAnimationTriggerType: {
1543         auto& scrollAnimationTrigger = downcast<ScrollAnimationTrigger>(trigger);
1544         if (scrollAnimationTrigger.endValue().isAuto())
1545             return CSSAnimationTriggerScrollValue::create(zoomAdjustedPixelValueForLength(scrollAnimationTrigger.startValue(), style));
1546         return CSSAnimationTriggerScrollValue::create(zoomAdjustedPixelValueForLength(scrollAnimationTrigger.startValue(), style),
1547                                                       zoomAdjustedPixelValueForLength(scrollAnimationTrigger.endValue(), style));
1548     }
1549     default:
1550         ASSERT(trigger.type() == AnimationTrigger::AnimationTriggerType::AutoAnimationTriggerType);
1551         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1552     }
1553 }
1554
1555 static Ref<CSSValueList> animationTriggerValue(const AnimationList* animationList, const RenderStyle& style)
1556 {
1557     auto list = CSSValueList::createCommaSeparated();
1558     if (animationList) {
1559         for (size_t i = 0; i < animationList->size(); ++i)
1560             list->append(createAnimationTriggerValue(*animationList->animation(i).trigger(), style));
1561     } else
1562         list->append(createAnimationTriggerValue(Animation::initialTrigger().get(), style));
1563     return list;
1564 }
1565
1566 #endif
1567
1568 static Ref<CSSValue> createLineBoxContainValue(unsigned lineBoxContain)
1569 {
1570     if (!lineBoxContain)
1571         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1572     return CSSLineBoxContainValue::create(lineBoxContain);
1573 }
1574
1575 static Element* styleElementForNode(Node* node)
1576 {
1577     if (!node)
1578         return nullptr;
1579     if (is<Element>(*node))
1580         return downcast<Element>(node);
1581     return composedTreeAncestors(*node).first();
1582 }
1583
1584 ComputedStyleExtractor::ComputedStyleExtractor(Node* node, bool allowVisitedStyle, PseudoId pseudoElementSpecifier)
1585     : m_element(styleElementForNode(node))
1586     , m_pseudoElementSpecifier(pseudoElementSpecifier)
1587     , m_allowVisitedStyle(allowVisitedStyle)
1588 {
1589 }
1590
1591 ComputedStyleExtractor::ComputedStyleExtractor(Element* element, bool allowVisitedStyle, PseudoId pseudoElementSpecifier)
1592     : m_element(element)
1593     , m_pseudoElementSpecifier(pseudoElementSpecifier)
1594     , m_allowVisitedStyle(allowVisitedStyle)
1595 {
1596 }
1597
1598 CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(Element& element, bool allowVisitedStyle, const String& pseudoElementName)
1599     : m_element(element)
1600     , m_allowVisitedStyle(allowVisitedStyle)
1601     , m_refCount(1)
1602 {
1603     unsigned nameWithoutColonsStart = pseudoElementName[0] == ':' ? (pseudoElementName[1] == ':' ? 2 : 1) : 0;
1604     m_pseudoElementSpecifier = CSSSelector::pseudoId(CSSSelector::parsePseudoElementType(
1605     (pseudoElementName.substringSharingImpl(nameWithoutColonsStart))));
1606 }
1607
1608 CSSComputedStyleDeclaration::~CSSComputedStyleDeclaration()
1609 {
1610 }
1611
1612 void CSSComputedStyleDeclaration::ref()
1613 {
1614     ++m_refCount;
1615 }
1616
1617 void CSSComputedStyleDeclaration::deref()
1618 {
1619     ASSERT(m_refCount);
1620     if (!--m_refCount)
1621         delete this;
1622 }
1623
1624 String CSSComputedStyleDeclaration::cssText() const
1625 {
1626     StringBuilder result;
1627
1628     for (unsigned i = 0; i < numComputedProperties; i++) {
1629         if (i)
1630             result.append(' ');
1631         result.append(getPropertyName(computedProperties[i]));
1632         result.appendLiteral(": ");
1633         result.append(getPropertyValue(computedProperties[i]));
1634         result.append(';');
1635     }
1636
1637     return result.toString();
1638 }
1639
1640 ExceptionOr<void> CSSComputedStyleDeclaration::setCssText(const String&)
1641 {
1642     return Exception { NO_MODIFICATION_ALLOWED_ERR };
1643 }
1644
1645 RefPtr<CSSPrimitiveValue> ComputedStyleExtractor::getFontSizeCSSValuePreferringKeyword()
1646 {
1647     if (!m_element)
1648         return nullptr;
1649
1650     m_element->document().updateLayoutIgnorePendingStylesheets();
1651
1652     auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
1653     if (!style)
1654         return nullptr;
1655
1656     if (CSSValueID sizeIdentifier = style->fontDescription().keywordSizeAsIdentifier())
1657         return CSSValuePool::singleton().createIdentifierValue(sizeIdentifier);
1658
1659     return zoomAdjustedPixelValue(style->fontDescription().computedSize(), *style);
1660 }
1661
1662 bool ComputedStyleExtractor::useFixedFontDefaultSize()
1663 {
1664     if (!m_element)
1665         return false;
1666     auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
1667     if (!style)
1668         return false;
1669
1670     return style->fontDescription().useFixedDefaultSize();
1671 }
1672
1673
1674 static CSSValueID identifierForFamily(const AtomicString& family)
1675 {
1676     if (family == cursiveFamily)
1677         return CSSValueCursive;
1678     if (family == fantasyFamily)
1679         return CSSValueFantasy;
1680     if (family == monospaceFamily)
1681         return CSSValueMonospace;
1682     if (family == pictographFamily)
1683         return CSSValueWebkitPictograph;
1684     if (family == sansSerifFamily)
1685         return CSSValueSansSerif;
1686     if (family == serifFamily)
1687         return CSSValueSerif;
1688     if (family == systemUiFamily)
1689         return CSSValueSystemUi;
1690     return CSSValueInvalid;
1691 }
1692
1693 static Ref<CSSPrimitiveValue> valueForFamily(const AtomicString& family)
1694 {
1695     if (CSSValueID familyIdentifier = identifierForFamily(family))
1696         return CSSValuePool::singleton().createIdentifierValue(familyIdentifier);
1697     return CSSValuePool::singleton().createFontFamilyValue(family);
1698 }
1699
1700 static Ref<CSSValue> renderTextDecorationFlagsToCSSValue(int textDecoration)
1701 {
1702     auto& cssValuePool = CSSValuePool::singleton();
1703     // Blink value is ignored.
1704     auto list = CSSValueList::createSpaceSeparated();
1705     if (textDecoration & TextDecorationUnderline)
1706         list->append(cssValuePool.createIdentifierValue(CSSValueUnderline));
1707     if (textDecoration & TextDecorationOverline)
1708         list->append(cssValuePool.createIdentifierValue(CSSValueOverline));
1709     if (textDecoration & TextDecorationLineThrough)
1710         list->append(cssValuePool.createIdentifierValue(CSSValueLineThrough));
1711 #if ENABLE(LETTERPRESS)
1712     if (textDecoration & TextDecorationLetterpress)
1713         list->append(cssValuePool.createIdentifierValue(CSSValueWebkitLetterpress));
1714 #endif
1715
1716     if (!list->length())
1717         return cssValuePool.createIdentifierValue(CSSValueNone);
1718     return WTFMove(list);
1719 }
1720
1721 static Ref<CSSValue> renderTextDecorationStyleFlagsToCSSValue(TextDecorationStyle textDecorationStyle)
1722 {
1723     switch (textDecorationStyle) {
1724     case TextDecorationStyleSolid:
1725         return CSSValuePool::singleton().createIdentifierValue(CSSValueSolid);
1726     case TextDecorationStyleDouble:
1727         return CSSValuePool::singleton().createIdentifierValue(CSSValueDouble);
1728     case TextDecorationStyleDotted:
1729         return CSSValuePool::singleton().createIdentifierValue(CSSValueDotted);
1730     case TextDecorationStyleDashed:
1731         return CSSValuePool::singleton().createIdentifierValue(CSSValueDashed);
1732     case TextDecorationStyleWavy:
1733         return CSSValuePool::singleton().createIdentifierValue(CSSValueWavy);
1734     }
1735
1736     ASSERT_NOT_REACHED();
1737     return CSSValuePool::singleton().createExplicitInitialValue();
1738 }
1739
1740 static Ref<CSSValue> renderTextDecorationSkipFlagsToCSSValue(TextDecorationSkip textDecorationSkip)
1741 {
1742     switch (textDecorationSkip) {
1743     case TextDecorationSkipAuto:
1744         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1745     case TextDecorationSkipNone:
1746         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1747     case TextDecorationSkipInk:
1748         return CSSValuePool::singleton().createIdentifierValue(CSSValueInk);
1749     case TextDecorationSkipObjects:
1750         return CSSValuePool::singleton().createIdentifierValue(CSSValueObjects);
1751     }
1752
1753     ASSERT_NOT_REACHED();
1754     return CSSValuePool::singleton().createExplicitInitialValue();
1755 }
1756
1757 static Ref<CSSValue> renderEmphasisPositionFlagsToCSSValue(TextEmphasisPosition textEmphasisPosition)
1758 {
1759     ASSERT(!((textEmphasisPosition & TextEmphasisPositionOver) && (textEmphasisPosition & TextEmphasisPositionUnder)));
1760     ASSERT(!((textEmphasisPosition & TextEmphasisPositionLeft) && (textEmphasisPosition & TextEmphasisPositionRight)));
1761     auto& cssValuePool = CSSValuePool::singleton();
1762     auto list = CSSValueList::createSpaceSeparated();
1763     if (textEmphasisPosition & TextEmphasisPositionOver)
1764         list->append(cssValuePool.createIdentifierValue(CSSValueOver));
1765     if (textEmphasisPosition & TextEmphasisPositionUnder)
1766         list->append(cssValuePool.createIdentifierValue(CSSValueUnder));
1767     if (textEmphasisPosition & TextEmphasisPositionLeft)
1768         list->append(cssValuePool.createIdentifierValue(CSSValueLeft));
1769     if (textEmphasisPosition & TextEmphasisPositionRight)
1770         list->append(cssValuePool.createIdentifierValue(CSSValueRight));
1771     if (!list->length())
1772         return cssValuePool.createIdentifierValue(CSSValueNone);
1773     return WTFMove(list);
1774 }
1775
1776 static Ref<CSSValue> hangingPunctuationToCSSValue(HangingPunctuation hangingPunctuation)
1777 {
1778     auto& cssValuePool = CSSValuePool::singleton();
1779     auto list = CSSValueList::createSpaceSeparated();
1780     if (hangingPunctuation & FirstHangingPunctuation)
1781         list->append(cssValuePool.createIdentifierValue(CSSValueFirst));
1782     if (hangingPunctuation & AllowEndHangingPunctuation)
1783         list->append(cssValuePool.createIdentifierValue(CSSValueAllowEnd));
1784     if (hangingPunctuation & ForceEndHangingPunctuation)
1785         list->append(cssValuePool.createIdentifierValue(CSSValueForceEnd));
1786     if (hangingPunctuation & LastHangingPunctuation)
1787         list->append(cssValuePool.createIdentifierValue(CSSValueLast));
1788     if (!list->length())
1789         return cssValuePool.createIdentifierValue(CSSValueNone);
1790     return WTFMove(list);
1791 }
1792     
1793 static Ref<CSSValue> fillRepeatToCSSValue(EFillRepeat xRepeat, EFillRepeat yRepeat)
1794 {
1795     // For backwards compatibility, if both values are equal, just return one of them. And
1796     // if the two values are equivalent to repeat-x or repeat-y, just return the shorthand.
1797     auto& cssValuePool = CSSValuePool::singleton();
1798     if (xRepeat == yRepeat)
1799         return cssValuePool.createValue(xRepeat);
1800     if (xRepeat == RepeatFill && yRepeat == NoRepeatFill)
1801         return cssValuePool.createIdentifierValue(CSSValueRepeatX);
1802     if (xRepeat == NoRepeatFill && yRepeat == RepeatFill)
1803         return cssValuePool.createIdentifierValue(CSSValueRepeatY);
1804
1805     auto list = CSSValueList::createSpaceSeparated();
1806     list->append(cssValuePool.createValue(xRepeat));
1807     list->append(cssValuePool.createValue(yRepeat));
1808     return WTFMove(list);
1809 }
1810
1811 static Ref<CSSValue> fillSourceTypeToCSSValue(EMaskSourceType type)
1812 {
1813     switch (type) {
1814     case MaskAlpha:
1815         return CSSValuePool::singleton().createValue(CSSValueAlpha);
1816     default:
1817         ASSERT(type == MaskLuminance);
1818         return CSSValuePool::singleton().createValue(CSSValueLuminance);
1819     }
1820 }
1821
1822 static Ref<CSSValue> fillSizeToCSSValue(const FillSize& fillSize, const RenderStyle& style)
1823 {
1824     if (fillSize.type == Contain)
1825         return CSSValuePool::singleton().createIdentifierValue(CSSValueContain);
1826
1827     if (fillSize.type == Cover)
1828         return CSSValuePool::singleton().createIdentifierValue(CSSValueCover);
1829
1830     if (fillSize.size.height.isAuto())
1831         return zoomAdjustedPixelValueForLength(fillSize.size.width, style);
1832
1833     auto list = CSSValueList::createSpaceSeparated();
1834     list->append(zoomAdjustedPixelValueForLength(fillSize.size.width, style));
1835     list->append(zoomAdjustedPixelValueForLength(fillSize.size.height, style));
1836     return WTFMove(list);
1837 }
1838
1839 static Ref<CSSValue> altTextToCSSValue(const RenderStyle& style)
1840 {
1841     return CSSValuePool::singleton().createValue(style.contentAltText(), CSSPrimitiveValue::CSS_STRING);
1842 }
1843     
1844 static Ref<CSSValueList> contentToCSSValue(const RenderStyle& style)
1845 {
1846     auto& cssValuePool = CSSValuePool::singleton();
1847     auto list = CSSValueList::createSpaceSeparated();
1848     for (auto* contentData = style.contentData(); contentData; contentData = contentData->next()) {
1849         if (is<CounterContentData>(*contentData))
1850             list->append(cssValuePool.createValue(downcast<CounterContentData>(*contentData).counter().identifier(), CSSPrimitiveValue::CSS_COUNTER_NAME));
1851         else if (is<ImageContentData>(*contentData))
1852             list->append(downcast<ImageContentData>(*contentData).image().cssValue());
1853         else if (is<TextContentData>(*contentData))
1854             list->append(cssValuePool.createValue(downcast<TextContentData>(*contentData).text(), CSSPrimitiveValue::CSS_STRING));
1855     }
1856     if (style.hasFlowFrom())
1857         list->append(cssValuePool.createValue(style.regionThread(), CSSPrimitiveValue::CSS_STRING));
1858     return list;
1859 }
1860
1861 static Ref<CSSValue> counterToCSSValue(const RenderStyle& style, CSSPropertyID propertyID)
1862 {
1863     auto* map = style.counterDirectives();
1864     if (!map)
1865         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1866
1867     auto& cssValuePool = CSSValuePool::singleton();
1868     auto list = CSSValueList::createSpaceSeparated();
1869     for (CounterDirectiveMap::const_iterator it = map->begin(); it != map->end(); ++it) {
1870         list->append(cssValuePool.createValue(it->key, CSSPrimitiveValue::CSS_STRING));
1871         short number = propertyID == CSSPropertyCounterIncrement ? it->value.incrementValue() : it->value.resetValue();
1872         list->append(cssValuePool.createValue((double)number, CSSPrimitiveValue::CSS_NUMBER));
1873     }
1874     return WTFMove(list);
1875 }
1876
1877 static void logUnimplementedPropertyID(CSSPropertyID propertyID)
1878 {
1879     static NeverDestroyed<HashSet<CSSPropertyID>> propertyIDSet;
1880     if (!propertyIDSet.get().add(propertyID).isNewEntry)
1881         return;
1882
1883     LOG_ERROR("WebKit does not yet implement getComputedStyle for '%s'.", getPropertyName(propertyID));
1884 }
1885
1886 static Ref<CSSValueList> fontFamilyListFromStyle(const RenderStyle& style)
1887 {
1888     auto list = CSSValueList::createCommaSeparated();
1889     for (unsigned i = 0; i < style.fontCascade().familyCount(); ++i)
1890         list->append(valueForFamily(style.fontCascade().familyAt(i)));
1891     return list;
1892 }
1893
1894 static Ref<CSSValue> fontFamilyFromStyle(const RenderStyle& style)
1895 {
1896     if (style.fontCascade().familyCount() == 1)
1897         return valueForFamily(style.fontCascade().familyAt(0));
1898     return fontFamilyListFromStyle(style);
1899 }
1900
1901 static Ref<CSSPrimitiveValue> lineHeightFromStyle(const RenderStyle& style)
1902 {
1903     Length length = style.lineHeight();
1904     if (length.isNegative()) // If true, line-height not set; use the font's line spacing.
1905         return zoomAdjustedPixelValue(style.fontMetrics().floatLineSpacing(), style);
1906     if (length.isPercent()) {
1907         // This is imperfect, because it doesn't include the zoom factor and the real computation
1908         // for how high to be in pixels does include things like minimum font size and the zoom factor.
1909         // On the other hand, since font-size doesn't include the zoom factor, we really can't do
1910         // that here either.
1911         return zoomAdjustedPixelValue(static_cast<int>(length.percent() * style.fontDescription().specifiedSize()) / 100, style);
1912     }
1913     return zoomAdjustedPixelValue(floatValueForLength(length, 0), style);
1914 }
1915
1916 static Ref<CSSPrimitiveValue> fontSizeFromStyle(const RenderStyle& style)
1917 {
1918     return zoomAdjustedPixelValue(style.fontDescription().computedSize(), style);
1919 }
1920
1921 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontNonKeywordWeightFromStyleValue(FontSelectionValue weight)
1922 {
1923     return CSSValuePool::singleton().createValue(static_cast<float>(weight), CSSPrimitiveValue::CSS_NUMBER);
1924 }
1925
1926 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontWeightFromStyleValue(FontSelectionValue weight)
1927 {
1928     if (auto value = fontWeightKeyword(weight))
1929         return CSSValuePool::singleton().createIdentifierValue(value.value());
1930     return fontNonKeywordWeightFromStyleValue(weight);
1931 }
1932
1933 static Ref<CSSPrimitiveValue> fontWeightFromStyle(const RenderStyle& style)
1934 {
1935     return ComputedStyleExtractor::fontWeightFromStyleValue(style.fontDescription().weight());
1936 }
1937
1938 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontNonKeywordStretchFromStyleValue(FontSelectionValue stretch)
1939 {
1940     return CSSValuePool::singleton().createValue(static_cast<float>(stretch), CSSPrimitiveValue::CSS_PERCENTAGE);
1941 }
1942
1943 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontStretchFromStyleValue(FontSelectionValue stretch)
1944 {
1945     if (auto keyword = fontStretchKeyword(stretch))
1946         return CSSValuePool::singleton().createIdentifierValue(keyword.value());
1947     return fontNonKeywordStretchFromStyleValue(stretch);
1948 }
1949
1950 static Ref<CSSPrimitiveValue> fontStretchFromStyle(const RenderStyle& style)
1951 {
1952     return ComputedStyleExtractor::fontStretchFromStyleValue(style.fontDescription().stretch());
1953 }
1954
1955 Ref<CSSFontStyleValue> ComputedStyleExtractor::fontNonKeywordStyleFromStyleValue(FontSelectionValue italic)
1956 {
1957     return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(CSSValueOblique), CSSValuePool::singleton().createValue(static_cast<float>(italic), CSSPrimitiveValue::CSS_DEG));
1958 }
1959
1960 Ref<CSSFontStyleValue> ComputedStyleExtractor::fontStyleFromStyleValue(FontSelectionValue italic)
1961 {
1962     if (auto keyword = fontStyleKeyword(italic))
1963         return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(keyword.value()));
1964     return fontNonKeywordStyleFromStyleValue(italic);
1965 }
1966
1967 static Ref<CSSFontStyleValue> fontStyleFromStyle(const RenderStyle& style)
1968 {
1969     return ComputedStyleExtractor::fontStyleFromStyleValue(style.fontDescription().italic());
1970 }
1971
1972 static Ref<CSSValue> fontVariantFromStyle(const RenderStyle& style)
1973 {
1974     if (style.fontDescription().variantSettings().isAllNormal())
1975         return CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
1976
1977     auto list = CSSValueList::createSpaceSeparated();
1978
1979     switch (style.fontDescription().variantCommonLigatures()) {
1980     case FontVariantLigatures::Normal:
1981         break;
1982     case FontVariantLigatures::Yes:
1983         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueCommonLigatures));
1984         break;
1985     case FontVariantLigatures::No:
1986         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoCommonLigatures));
1987         break;
1988     }
1989
1990     switch (style.fontDescription().variantDiscretionaryLigatures()) {
1991     case FontVariantLigatures::Normal:
1992         break;
1993     case FontVariantLigatures::Yes:
1994         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiscretionaryLigatures));
1995         break;
1996     case FontVariantLigatures::No:
1997         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoDiscretionaryLigatures));
1998         break;
1999     }
2000
2001     switch (style.fontDescription().variantHistoricalLigatures()) {
2002     case FontVariantLigatures::Normal:
2003         break;
2004     case FontVariantLigatures::Yes:
2005         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalLigatures));
2006         break;
2007     case FontVariantLigatures::No:
2008         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoHistoricalLigatures));
2009         break;
2010     }
2011
2012     switch (style.fontDescription().variantContextualAlternates()) {
2013     case FontVariantLigatures::Normal:
2014         break;
2015     case FontVariantLigatures::Yes:
2016         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueContextual));
2017         break;
2018     case FontVariantLigatures::No:
2019         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoContextual));
2020         break;
2021     }
2022
2023     switch (style.fontDescription().variantPosition()) {
2024     case FontVariantPosition::Normal:
2025         break;
2026     case FontVariantPosition::Subscript:
2027         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSub));
2028         break;
2029     case FontVariantPosition::Superscript:
2030         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSuper));
2031         break;
2032     }
2033
2034     switch (style.fontDescription().variantCaps()) {
2035     case FontVariantCaps::Normal:
2036         break;
2037     case FontVariantCaps::Small:
2038         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
2039         break;
2040     case FontVariantCaps::AllSmall:
2041         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllSmallCaps));
2042         break;
2043     case FontVariantCaps::Petite:
2044         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValuePetiteCaps));
2045         break;
2046     case FontVariantCaps::AllPetite:
2047         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllPetiteCaps));
2048         break;
2049     case FontVariantCaps::Unicase:
2050         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueUnicase));
2051         break;
2052     case FontVariantCaps::Titling:
2053         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTitlingCaps));
2054         break;
2055     }
2056
2057     switch (style.fontDescription().variantNumericFigure()) {
2058     case FontVariantNumericFigure::Normal:
2059         break;
2060     case FontVariantNumericFigure::LiningNumbers:
2061         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueLiningNums));
2062         break;
2063     case FontVariantNumericFigure::OldStyleNumbers:
2064         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueOldstyleNums));
2065         break;
2066     }
2067
2068     switch (style.fontDescription().variantNumericSpacing()) {
2069     case FontVariantNumericSpacing::Normal:
2070         break;
2071     case FontVariantNumericSpacing::ProportionalNumbers:
2072         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalNums));
2073         break;
2074     case FontVariantNumericSpacing::TabularNumbers:
2075         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTabularNums));
2076         break;
2077     }
2078
2079     switch (style.fontDescription().variantNumericFraction()) {
2080     case FontVariantNumericFraction::Normal:
2081         break;
2082     case FontVariantNumericFraction::DiagonalFractions:
2083         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiagonalFractions));
2084         break;
2085     case FontVariantNumericFraction::StackedFractions:
2086         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStackedFractions));
2087         break;
2088     }
2089
2090     switch (style.fontDescription().variantNumericOrdinal()) {
2091     case FontVariantNumericOrdinal::Normal:
2092         break;
2093     case FontVariantNumericOrdinal::Yes:
2094         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueOrdinal));
2095         break;
2096     }
2097
2098     switch (style.fontDescription().variantNumericSlashedZero()) {
2099     case FontVariantNumericSlashedZero::Normal:
2100         break;
2101     case FontVariantNumericSlashedZero::Yes:
2102         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSlashedZero));
2103         break;
2104     }
2105
2106     switch (style.fontDescription().variantAlternates()) {
2107     case FontVariantAlternates::Normal:
2108         break;
2109     case FontVariantAlternates::HistoricalForms:
2110         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalForms));
2111         break;
2112     }
2113
2114     switch (style.fontDescription().variantEastAsianVariant()) {
2115     case FontVariantEastAsianVariant::Normal:
2116         break;
2117     case FontVariantEastAsianVariant::Jis78:
2118         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis78));
2119         break;
2120     case FontVariantEastAsianVariant::Jis83:
2121         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis83));
2122         break;
2123     case FontVariantEastAsianVariant::Jis90:
2124         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis90));
2125         break;
2126     case FontVariantEastAsianVariant::Jis04:
2127         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis04));
2128         break;
2129     case FontVariantEastAsianVariant::Simplified:
2130         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSimplified));
2131         break;
2132     case FontVariantEastAsianVariant::Traditional:
2133         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTraditional));
2134         break;
2135     }
2136
2137     switch (style.fontDescription().variantEastAsianWidth()) {
2138     case FontVariantEastAsianWidth::Normal:
2139         break;
2140     case FontVariantEastAsianWidth::Full:
2141         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueFullWidth));
2142         break;
2143     case FontVariantEastAsianWidth::Proportional:
2144         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalWidth));
2145         break;
2146     }
2147
2148     switch (style.fontDescription().variantEastAsianRuby()) {
2149     case FontVariantEastAsianRuby::Normal:
2150         break;
2151     case FontVariantEastAsianRuby::Yes:
2152         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueRuby));
2153         break;
2154     }
2155
2156     return WTFMove(list);
2157 }
2158
2159 static Ref<CSSValue> fontSynthesisFromStyle(const RenderStyle& style)
2160 {
2161     if (style.fontDescription().fontSynthesis() == FontSynthesisNone)
2162         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2163
2164     auto list = CSSValueList::createSpaceSeparated();
2165     if (style.fontDescription().fontSynthesis() & FontSynthesisStyle)
2166         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStyle));
2167     if (style.fontDescription().fontSynthesis() & FontSynthesisWeight)
2168         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueWeight));
2169     if (style.fontDescription().fontSynthesis() & FontSynthesisSmallCaps)
2170         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
2171     return WTFMove(list);
2172 }
2173
2174 typedef const Length& (RenderStyle::*RenderStyleLengthGetter)() const;
2175 typedef LayoutUnit (RenderBoxModelObject::*RenderBoxComputedCSSValueGetter)() const;
2176
2177 template<RenderStyleLengthGetter lengthGetter, RenderBoxComputedCSSValueGetter computedCSSValueGetter>
2178 static RefPtr<CSSValue> zoomAdjustedPaddingOrMarginPixelValue(const RenderStyle& style, RenderObject* renderer)
2179 {
2180     Length unzoomzedLength = (style.*lengthGetter)();
2181     if (!is<RenderBox>(renderer) || unzoomzedLength.isFixed())
2182         return zoomAdjustedPixelValueForLength(unzoomzedLength, style);
2183     return zoomAdjustedPixelValue((downcast<RenderBox>(*renderer).*computedCSSValueGetter)(), style);
2184 }
2185
2186 template<RenderStyleLengthGetter lengthGetter>
2187 static bool paddingOrMarginIsRendererDependent(const RenderStyle* style, RenderObject* renderer)
2188 {
2189     return renderer && style && renderer->isBox() && !(style->*lengthGetter)().isFixed();
2190 }
2191
2192 static CSSValueID convertToPageBreak(BreakBetween value)
2193 {
2194     if (value == PageBreakBetween || value == LeftPageBreakBetween || value == RightPageBreakBetween
2195         || value == RectoPageBreakBetween || value == VersoPageBreakBetween)
2196         return CSSValueAlways; // CSS 2.1 allows us to map these to always.
2197     if (value == AvoidBreakBetween || value == AvoidPageBreakBetween)
2198         return CSSValueAvoid;
2199     return CSSValueAuto;
2200 }
2201
2202 static CSSValueID convertToColumnBreak(BreakBetween value)
2203 {
2204     if (value == ColumnBreakBetween)
2205         return CSSValueAlways;
2206     if (value == AvoidBreakBetween || value == AvoidColumnBreakBetween)
2207         return CSSValueAvoid;
2208     return CSSValueAuto;
2209 }
2210
2211 static CSSValueID convertToPageBreak(BreakInside value)
2212 {
2213     if (value == AvoidBreakInside || value == AvoidPageBreakInside)
2214         return CSSValueAvoid;
2215     return CSSValueAuto;
2216 }
2217
2218 static CSSValueID convertToColumnBreak(BreakInside value)
2219 {
2220     if (value == AvoidBreakInside || value == AvoidColumnBreakInside)
2221         return CSSValueAvoid;
2222     return CSSValueAuto;
2223 }
2224
2225 #if ENABLE(CSS_REGIONS)
2226 static CSSValueID convertToRegionBreak(BreakBetween value)
2227 {
2228     if (value == RegionBreakBetween)
2229         return CSSValueAlways;
2230     if (value == AvoidBreakBetween || value == AvoidRegionBreakBetween)
2231         return CSSValueAvoid;
2232     return CSSValueAuto;
2233 }
2234     
2235 static CSSValueID convertToRegionBreak(BreakInside value)
2236 {
2237     if (value == AvoidBreakInside || value == AvoidRegionBreakInside)
2238         return CSSValueAvoid;
2239     return CSSValueAuto;
2240 }
2241 #endif
2242     
2243 static bool isLayoutDependent(CSSPropertyID propertyID, const RenderStyle* style, RenderObject* renderer)
2244 {
2245     switch (propertyID) {
2246     case CSSPropertyWidth:
2247     case CSSPropertyHeight:
2248     case CSSPropertyPerspectiveOrigin:
2249     case CSSPropertyTransformOrigin:
2250     case CSSPropertyTransform:
2251     case CSSPropertyFilter:
2252 #if ENABLE(FILTERS_LEVEL_2)
2253     case CSSPropertyWebkitBackdropFilter:
2254 #endif
2255         return true;
2256     case CSSPropertyMargin: {
2257         if (!renderer || !renderer->isBox())
2258             return false;
2259         return !(style && style->marginTop().isFixed() && style->marginRight().isFixed()
2260             && style->marginBottom().isFixed() && style->marginLeft().isFixed());
2261     }
2262     case CSSPropertyMarginTop:
2263         return paddingOrMarginIsRendererDependent<&RenderStyle::marginTop>(style, renderer);
2264     case CSSPropertyMarginRight:
2265         return paddingOrMarginIsRendererDependent<&RenderStyle::marginRight>(style, renderer);
2266     case CSSPropertyMarginBottom:
2267         return paddingOrMarginIsRendererDependent<&RenderStyle::marginBottom>(style, renderer);
2268     case CSSPropertyMarginLeft:
2269         return paddingOrMarginIsRendererDependent<&RenderStyle::marginLeft>(style, renderer);
2270     case CSSPropertyPadding: {
2271         if (!renderer || !renderer->isBox())
2272             return false;
2273         return !(style && style->paddingTop().isFixed() && style->paddingRight().isFixed()
2274             && style->paddingBottom().isFixed() && style->paddingLeft().isFixed());
2275     }
2276     case CSSPropertyPaddingTop:
2277         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingTop>(style, renderer);
2278     case CSSPropertyPaddingRight:
2279         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingRight>(style, renderer);
2280     case CSSPropertyPaddingBottom:
2281         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingBottom>(style, renderer);
2282     case CSSPropertyPaddingLeft:
2283         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingLeft>(style, renderer); 
2284     case CSSPropertyGridTemplateColumns:
2285     case CSSPropertyGridTemplateRows:
2286     case CSSPropertyGridTemplate:
2287     case CSSPropertyGrid:
2288         return renderer && renderer->isRenderGrid();
2289     default:
2290         return false;
2291     }
2292 }
2293
2294 Element* ComputedStyleExtractor::styledElement()
2295 {
2296     if (!m_element)
2297         return nullptr;
2298     PseudoElement* pseudoElement;
2299     if (m_pseudoElementSpecifier == BEFORE && (pseudoElement = m_element->beforePseudoElement()))
2300         return pseudoElement;
2301     if (m_pseudoElementSpecifier == AFTER && (pseudoElement = m_element->afterPseudoElement()))
2302         return pseudoElement;
2303     return m_element.get();
2304 }
2305
2306 static StyleSelfAlignmentData resolveLegacyJustifyItems(const StyleSelfAlignmentData& data)
2307 {
2308     if (data.positionType() == LegacyPosition)
2309         return { data.position(), OverflowAlignmentDefault };
2310     return data;
2311 }
2312
2313 static StyleSelfAlignmentData resolveJustifyItemsAuto(const StyleSelfAlignmentData& data, Node* parent)
2314 {
2315     if (data.position() != ItemPositionAuto)
2316         return data;
2317
2318     // If the inherited value of justify-items includes the 'legacy' keyword, 'auto' computes to the inherited value.
2319     const auto& inheritedValue = (!parent || !parent->computedStyle()) ? RenderStyle::initialDefaultAlignment() : parent->computedStyle()->justifyItems();
2320     if (inheritedValue.positionType() == LegacyPosition)
2321         return inheritedValue;
2322     if (inheritedValue.position() == ItemPositionAuto)
2323         return resolveJustifyItemsAuto(inheritedValue, parent->parentNode());
2324     return { ItemPositionNormal, OverflowAlignmentDefault };
2325 }
2326
2327 static StyleSelfAlignmentData resolveJustifySelfAuto(const StyleSelfAlignmentData& data, Node* parent)
2328 {
2329     if (data.position() != ItemPositionAuto)
2330         return data;
2331
2332     // The 'auto' keyword computes to the computed value of justify-items on the parent or 'normal' if the box has no parent.
2333     if (!parent || !parent->computedStyle())
2334         return { ItemPositionNormal, OverflowAlignmentDefault };
2335     return resolveLegacyJustifyItems(resolveJustifyItemsAuto(parent->computedStyle()->justifyItems(), parent->parentNode()));
2336 }
2337
2338 static StyleSelfAlignmentData resolveAlignSelfAuto(const StyleSelfAlignmentData& data, Node* parent)
2339 {
2340     if (data.position() != ItemPositionAuto)
2341         return data;
2342
2343     // The 'auto' keyword computes to the computed value of align-items on the parent or 'normal' if the box has no parent.
2344     if (!parent || !parent->computedStyle())
2345         return { ItemPositionNormal, OverflowAlignmentDefault };
2346     return parent->computedStyle()->alignItems();
2347 }
2348
2349 static bool isImplicitlyInheritedGridOrFlexProperty(CSSPropertyID propertyID)
2350 {
2351     // It would be nice if grid and flex worked within normal CSS mechanisms and not invented their own inheritance system.
2352     switch (propertyID) {
2353     case CSSPropertyAlignSelf:
2354     case CSSPropertyJustifySelf:
2355     case CSSPropertyJustifyItems:
2356     // FIXME: In StyleResolver::adjustRenderStyle z-index is adjusted based on the parent display property for grid/flex.
2357     case CSSPropertyZIndex:
2358         return true;
2359     default:
2360         return false;
2361     }
2362 }
2363
2364 RefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const
2365 {
2366     return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).propertyValue(propertyID, updateLayout);
2367 }
2368
2369 Ref<MutableStyleProperties> CSSComputedStyleDeclaration::copyProperties() const
2370 {
2371     return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).copyProperties();
2372 }
2373
2374 static inline bool hasValidStyleForProperty(Element& element, CSSPropertyID propertyID)
2375 {
2376     if (element.styleValidity() != Style::Validity::Valid)
2377         return false;
2378     if (element.document().hasPendingForcedStyleRecalc())
2379         return false;
2380     if (!element.document().childNeedsStyleRecalc())
2381         return true;
2382
2383     bool isInherited = CSSProperty::isInheritedProperty(propertyID) || isImplicitlyInheritedGridOrFlexProperty(propertyID);
2384     bool maybeExplicitlyInherited = !isInherited;
2385
2386     const auto* currentElement = &element;
2387     for (auto& ancestor : composedTreeAncestors(element)) {
2388         if (ancestor.styleValidity() >= Style::Validity::SubtreeInvalid)
2389             return false;
2390
2391         if (maybeExplicitlyInherited) {
2392             auto* style = currentElement->renderStyle();
2393             maybeExplicitlyInherited = !style || style->hasExplicitlyInheritedProperties();
2394         }
2395
2396         if ((isInherited || maybeExplicitlyInherited) && ancestor.styleValidity() == Style::Validity::ElementInvalid)
2397             return false;
2398
2399         if (ancestor.directChildNeedsStyleRecalc() && currentElement->styleIsAffectedByPreviousSibling())
2400             return false;
2401
2402         currentElement = &ancestor;
2403     }
2404
2405     return true;
2406 }
2407
2408 static bool updateStyleIfNeededForProperty(Element& element, CSSPropertyID propertyID)
2409 {
2410     auto& document = element.document();
2411
2412     document.styleScope().flushPendingUpdate();
2413
2414     if (hasValidStyleForProperty(element, propertyID))
2415         return false;
2416
2417     document.updateStyleIfNeeded();
2418     return true;
2419 }
2420
2421 static inline const RenderStyle* computeRenderStyleForProperty(Element& element, PseudoId pseudoElementSpecifier, CSSPropertyID propertyID, std::unique_ptr<RenderStyle>& ownedStyle)
2422 {
2423     auto* renderer = element.renderer();
2424
2425     if (renderer && renderer->isComposited() && CSSAnimationController::supportsAcceleratedAnimationOfProperty(propertyID)) {
2426         ownedStyle = renderer->animation().getAnimatedStyleForRenderer(*renderer);
2427         if (pseudoElementSpecifier && !element.isPseudoElement()) {
2428             // FIXME: This cached pseudo style will only exist if the animation has been run at least once.
2429             return ownedStyle->getCachedPseudoStyle(pseudoElementSpecifier);
2430         }
2431         return ownedStyle.get();
2432     }
2433
2434     return element.computedStyle(element.isPseudoElement() ? NOPSEUDO : pseudoElementSpecifier);
2435 }
2436
2437 static Ref<CSSValue> shapePropertyValue(const RenderStyle& style, const ShapeValue* shapeValue)
2438 {
2439     if (!shapeValue)
2440         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2441
2442     if (shapeValue->type() == ShapeValue::Type::Box)
2443         return CSSValuePool::singleton().createValue(shapeValue->cssBox());
2444
2445     if (shapeValue->type() == ShapeValue::Type::Image) {
2446         if (shapeValue->image())
2447             return shapeValue->image()->cssValue();
2448         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2449     }
2450
2451     ASSERT(shapeValue->type() == ShapeValue::Type::Shape);
2452
2453     auto list = CSSValueList::createSpaceSeparated();
2454     list->append(valueForBasicShape(style, *shapeValue->shape()));
2455     if (shapeValue->cssBox() != BoxMissing)
2456         list->append(CSSValuePool::singleton().createValue(shapeValue->cssBox()));
2457     return WTFMove(list);
2458 }
2459
2460 static Ref<CSSValueList> valueForItemPositionWithOverflowAlignment(const StyleSelfAlignmentData& data)
2461 {
2462     auto& cssValuePool = CSSValuePool::singleton();
2463     auto result = CSSValueList::createSpaceSeparated();
2464     if (data.positionType() == LegacyPosition)
2465         result->append(cssValuePool.createIdentifierValue(CSSValueLegacy));
2466     if (data.position() == ItemPositionBaseline)
2467         result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2468     else if (data.position() == ItemPositionLastBaseline) {
2469         result->append(cssValuePool.createIdentifierValue(CSSValueLast));
2470         result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2471     } else
2472         result->append(cssValuePool.createValue(data.position()));
2473     if (data.position() >= ItemPositionCenter && data.overflow() != OverflowAlignmentDefault)
2474         result->append(cssValuePool.createValue(data.overflow()));
2475     ASSERT(result->length() <= 2);
2476     return result;
2477 }
2478
2479 static Ref<CSSValueList> valueForContentPositionAndDistributionWithOverflowAlignment(const StyleContentAlignmentData& data, CSSValueID normalBehaviorValueID)
2480 {
2481     auto& cssValuePool = CSSValuePool::singleton();
2482     auto result = CSSValueList::createSpaceSeparated();
2483     // Handle content-distribution values
2484     if (data.distribution() != ContentDistributionDefault)
2485         result->append(cssValuePool.createValue(data.distribution()));
2486
2487     bool gridEnabled = false;
2488     gridEnabled = RuntimeEnabledFeatures::sharedFeatures().isCSSGridLayoutEnabled();
2489
2490     // Handle content-position values (either as fallback or actual value)
2491     switch (data.position()) {
2492     case ContentPositionNormal:
2493         // Handle 'normal' value, not valid as content-distribution fallback.
2494         if (data.distribution() == ContentDistributionDefault)
2495             result->append(cssValuePool.createIdentifierValue(gridEnabled ? CSSValueNormal : normalBehaviorValueID));
2496         break;
2497     case ContentPositionLastBaseline:
2498         result->append(cssValuePool.createIdentifierValue(CSSValueLast));
2499         result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2500         break;
2501     default:
2502         result->append(cssValuePool.createValue(data.position()));
2503     }
2504
2505     // Handle overflow-alignment (only allowed for content-position values)
2506     if ((data.position() >= ContentPositionCenter || data.distribution() != ContentDistributionDefault) && data.overflow() != OverflowAlignmentDefault)
2507         result->append(cssValuePool.createValue(data.overflow()));
2508     ASSERT(result->length() > 0);
2509     ASSERT(result->length() <= 3);
2510     return result;
2511 }
2512
2513 static Ref<CSSValue> paintOrder(PaintOrder paintOrder)
2514 {
2515     if (paintOrder == PaintOrder::Normal)
2516         return CSSPrimitiveValue::createIdentifier(CSSValueNormal);
2517     
2518     auto paintOrderList = CSSValueList::createSpaceSeparated();
2519     switch (paintOrder) {
2520     case PaintOrder::Normal:
2521         ASSERT_NOT_REACHED();
2522         break;
2523     case PaintOrder::Fill:
2524         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueFill));
2525         break;
2526     case PaintOrder::FillMarkers:
2527         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueFill));
2528         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2529         break;
2530     case PaintOrder::Stroke:
2531         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2532         break;
2533     case PaintOrder::StrokeMarkers:
2534         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2535         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2536         break;
2537     case PaintOrder::Markers:
2538         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2539         break;
2540     case PaintOrder::MarkersStroke:
2541         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2542         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2543         break;
2544     }
2545     return WTFMove(paintOrderList);
2546 }
2547
2548 inline static bool isFlexOrGrid(ContainerNode* element)
2549 {
2550     return element && element->computedStyle() && element->computedStyle()->isDisplayFlexibleOrGridBox();
2551 }
2552
2553 RefPtr<CSSValue> ComputedStyleExtractor::customPropertyValue(const String& propertyName)
2554 {
2555     Element* styledElement = this->styledElement();
2556     if (!styledElement)
2557         return nullptr;
2558     
2559     if (updateStyleIfNeededForProperty(*styledElement, CSSPropertyCustom)) {
2560         // Style update may change styledElement() to PseudoElement or back.
2561         styledElement = this->styledElement();
2562     }
2563
2564     std::unique_ptr<RenderStyle> ownedStyle;
2565     auto* style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, CSSPropertyCustom, ownedStyle);
2566     if (!style)
2567         return nullptr;
2568
2569     return style->customProperties().get(propertyName);
2570 }
2571
2572 String ComputedStyleExtractor::customPropertyText(const String& propertyName)
2573 {
2574     RefPtr<CSSValue> propertyValue = customPropertyValue(propertyName);
2575     return propertyValue ? propertyValue->cssText() : emptyString();
2576 }
2577
2578 static Ref<CSSFontValue> fontShorthandValueForSelectionProperties(const FontDescription& fontDescription)
2579 {
2580     auto computedFont = CSSFontValue::create();
2581
2582     auto variantCaps = fontDescription.variantCaps();
2583     if (variantCaps == FontVariantCaps::Small)
2584         computedFont->variant = CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps);
2585     else if (variantCaps == FontVariantCaps::Normal)
2586         computedFont->variant = CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
2587     else
2588         return CSSFontValue::create();
2589
2590     auto weight = fontDescription.weight();
2591     if (auto value = fontWeightKeyword(weight))
2592         computedFont->weight = CSSValuePool::singleton().createIdentifierValue(value.value());
2593     else if (isCSS21Weight(weight))
2594         computedFont->weight = CSSValuePool::singleton().createValue(static_cast<float>(weight), CSSPrimitiveValue::CSS_NUMBER);
2595     else
2596         return CSSFontValue::create();
2597
2598     if (auto keyword = fontStretchKeyword(fontDescription.stretch()))
2599         computedFont->stretch = CSSValuePool::singleton().createIdentifierValue(keyword.value());
2600     else
2601         return CSSFontValue::create();
2602
2603     if (auto italic = fontStyleKeyword(fontDescription.italic()))
2604         computedFont->style = CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(italic.value()));
2605     else
2606         return CSSFontValue::create();
2607
2608     return computedFont;
2609 }
2610
2611 RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID, EUpdateLayout updateLayout)
2612 {
2613     auto* styledElement = this->styledElement();
2614     if (!styledElement)
2615         return nullptr;
2616
2617     std::unique_ptr<RenderStyle> ownedStyle;
2618     const RenderStyle* style = nullptr;
2619     RenderObject* renderer = nullptr;
2620     bool forceFullLayout = false;
2621     if (updateLayout) {
2622         Document& document = m_element->document();
2623
2624         if (updateStyleIfNeededForProperty(*styledElement, propertyID)) {
2625             // Style update may change styledElement() to PseudoElement or back.
2626             styledElement = this->styledElement();
2627         }
2628         renderer = styledElement->renderer();
2629
2630         if (propertyID == CSSPropertyDisplay && !renderer && is<SVGElement>(*styledElement) && !downcast<SVGElement>(*styledElement).isValid())
2631             return nullptr;
2632
2633         style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, propertyID, ownedStyle);
2634
2635         // FIXME: Some of these cases could be narrowed down or optimized better.
2636         forceFullLayout = isLayoutDependent(propertyID, style, renderer)
2637             || styledElement->isInShadowTree()
2638             || (document.styleScope().resolverIfExists() && document.styleScope().resolverIfExists()->hasViewportDependentMediaQueries() && document.ownerElement());
2639
2640         if (forceFullLayout) {
2641             document.updateLayoutIgnorePendingStylesheets();
2642             styledElement = this->styledElement();
2643         }
2644     }
2645
2646     if (!updateLayout || forceFullLayout) {
2647         style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, propertyID, ownedStyle);
2648         renderer = styledElement->renderer();
2649     }
2650
2651     if (!style)
2652         return nullptr;
2653
2654     auto& cssValuePool = CSSValuePool::singleton();
2655     propertyID = CSSProperty::resolveDirectionAwareProperty(propertyID, style->direction(), style->writingMode());
2656
2657     switch (propertyID) {
2658         case CSSPropertyInvalid:
2659             break;
2660
2661         case CSSPropertyBackgroundColor:
2662             return cssValuePool.createColorValue(m_allowVisitedStyle? style->visitedDependentColor(CSSPropertyBackgroundColor) : style->backgroundColor());
2663         case CSSPropertyBackgroundImage:
2664         case CSSPropertyWebkitMaskImage: {
2665             auto& layers = propertyID == CSSPropertyWebkitMaskImage ? style->maskLayers() : style->backgroundLayers();
2666             if (!layers.next()) {
2667                 if (layers.image())
2668                     return layers.image()->cssValue();
2669                 return cssValuePool.createIdentifierValue(CSSValueNone);
2670             }
2671             auto list = CSSValueList::createCommaSeparated();
2672             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next()) {
2673                 if (currLayer->image())
2674                     list->append(currLayer->image()->cssValue());
2675                 else
2676                     list->append(cssValuePool.createIdentifierValue(CSSValueNone));
2677             }
2678             return WTFMove(list);
2679         }
2680         case CSSPropertyBackgroundSize:
2681         case CSSPropertyWebkitBackgroundSize:
2682         case CSSPropertyWebkitMaskSize: {
2683             auto& layers = propertyID == CSSPropertyWebkitMaskSize ? style->maskLayers() : style->backgroundLayers();
2684             if (!layers.next())
2685                 return fillSizeToCSSValue(layers.size(), *style);
2686             auto list = CSSValueList::createCommaSeparated();
2687             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2688                 list->append(fillSizeToCSSValue(currLayer->size(), *style));
2689             return WTFMove(list);
2690         }
2691         case CSSPropertyBackgroundRepeat:
2692         case CSSPropertyWebkitMaskRepeat: {
2693             auto& layers = propertyID == CSSPropertyWebkitMaskRepeat ? style->maskLayers() : style->backgroundLayers();
2694             if (!layers.next())
2695                 return fillRepeatToCSSValue(layers.repeatX(), layers.repeatY());
2696             auto list = CSSValueList::createCommaSeparated();
2697             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2698                 list->append(fillRepeatToCSSValue(currLayer->repeatX(), currLayer->repeatY()));
2699             return WTFMove(list);
2700         }
2701         case CSSPropertyWebkitMaskSourceType: {
2702             auto& layers = style->maskLayers();
2703             if (!layers.next())
2704                 return fillSourceTypeToCSSValue(layers.maskSourceType());
2705             auto list = CSSValueList::createCommaSeparated();
2706             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2707                 list->append(fillSourceTypeToCSSValue(currLayer->maskSourceType()));
2708             return WTFMove(list);
2709         }
2710         case CSSPropertyWebkitBackgroundComposite:
2711         case CSSPropertyWebkitMaskComposite: {
2712             auto& layers = propertyID == CSSPropertyWebkitMaskComposite ? style->maskLayers() : style->backgroundLayers();
2713             if (!layers.next())
2714                 return cssValuePool.createValue(layers.composite());
2715             auto list = CSSValueList::createCommaSeparated();
2716             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2717                 list->append(cssValuePool.createValue(currLayer->composite()));
2718             return WTFMove(list);
2719         }
2720         case CSSPropertyBackgroundAttachment: {
2721             auto& layers = style->backgroundLayers();
2722             if (!layers.next())
2723                 return cssValuePool.createValue(layers.attachment());
2724             auto list = CSSValueList::createCommaSeparated();
2725             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2726                 list->append(cssValuePool.createValue(currLayer->attachment()));
2727             return WTFMove(list);
2728         }
2729         case CSSPropertyBackgroundClip:
2730         case CSSPropertyBackgroundOrigin:
2731         case CSSPropertyWebkitBackgroundClip:
2732         case CSSPropertyWebkitBackgroundOrigin:
2733         case CSSPropertyWebkitMaskClip:
2734         case CSSPropertyWebkitMaskOrigin: {
2735             auto& layers = (propertyID == CSSPropertyWebkitMaskClip || propertyID == CSSPropertyWebkitMaskOrigin) ? style->maskLayers() : style->backgroundLayers();
2736             bool isClip = propertyID == CSSPropertyBackgroundClip || propertyID == CSSPropertyWebkitBackgroundClip || propertyID == CSSPropertyWebkitMaskClip;
2737             if (!layers.next())
2738                 return cssValuePool.createValue(isClip ? layers.clip() : layers.origin());
2739             auto list = CSSValueList::createCommaSeparated();
2740             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2741                 list->append(cssValuePool.createValue(isClip ? currLayer->clip() : currLayer->origin()));
2742             return WTFMove(list);
2743         }
2744         case CSSPropertyBackgroundPosition:
2745         case CSSPropertyWebkitMaskPosition: {
2746             auto& layers = propertyID == CSSPropertyWebkitMaskPosition ? style->maskLayers() : style->backgroundLayers();
2747             if (!layers.next())
2748                 return createPositionListForLayer(propertyID, layers, *style);
2749
2750             auto list = CSSValueList::createCommaSeparated();
2751             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2752                 list->append(createPositionListForLayer(propertyID, *currLayer, *style));
2753             return WTFMove(list);
2754         }
2755         case CSSPropertyBackgroundPositionX:
2756         case CSSPropertyWebkitMaskPositionX: {
2757             auto& layers = propertyID == CSSPropertyWebkitMaskPositionX ? style->maskLayers() : style->backgroundLayers();
2758             if (!layers.next())
2759                 return cssValuePool.createValue(layers.xPosition());
2760
2761             auto list = CSSValueList::createCommaSeparated();
2762             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2763                 list->append(cssValuePool.createValue(currLayer->xPosition()));
2764
2765             return WTFMove(list);
2766         }
2767         case CSSPropertyBackgroundPositionY:
2768         case CSSPropertyWebkitMaskPositionY: {
2769             auto& layers = propertyID == CSSPropertyWebkitMaskPositionY ? style->maskLayers() : style->backgroundLayers();
2770             if (!layers.next())
2771                 return cssValuePool.createValue(layers.yPosition());
2772
2773             auto list = CSSValueList::createCommaSeparated();
2774             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2775                 list->append(cssValuePool.createValue(currLayer->yPosition()));
2776
2777             return WTFMove(list);
2778         }
2779         case CSSPropertyBorderCollapse:
2780             if (style->borderCollapse())
2781                 return cssValuePool.createIdentifierValue(CSSValueCollapse);
2782             return cssValuePool.createIdentifierValue(CSSValueSeparate);
2783         case CSSPropertyBorderSpacing: {
2784             auto list = CSSValueList::createSpaceSeparated();
2785             list->append(zoomAdjustedPixelValue(style->horizontalBorderSpacing(), *style));
2786             list->append(zoomAdjustedPixelValue(style->verticalBorderSpacing(), *style));
2787             return WTFMove(list);
2788         }
2789         case CSSPropertyWebkitBorderHorizontalSpacing:
2790             return zoomAdjustedPixelValue(style->horizontalBorderSpacing(), *style);
2791         case CSSPropertyWebkitBorderVerticalSpacing:
2792             return zoomAdjustedPixelValue(style->verticalBorderSpacing(), *style);
2793         case CSSPropertyBorderImageSource:
2794             if (style->borderImageSource())
2795                 return style->borderImageSource()->cssValue();
2796             return cssValuePool.createIdentifierValue(CSSValueNone);
2797         case CSSPropertyBorderTopColor:
2798             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyBorderTopColor)) : currentColorOrValidColor(style, style->borderTopColor());
2799         case CSSPropertyBorderRightColor:
2800             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyBorderRightColor)) : currentColorOrValidColor(style, style->borderRightColor());
2801         case CSSPropertyBorderBottomColor:
2802             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyBorderBottomColor)) : currentColorOrValidColor(style, style->borderBottomColor());
2803         case CSSPropertyBorderLeftColor:
2804             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyBorderLeftColor)) : currentColorOrValidColor(style, style->borderLeftColor());
2805         case CSSPropertyBorderTopStyle:
2806             return cssValuePool.createValue(style->borderTopStyle());
2807         case CSSPropertyBorderRightStyle:
2808             return cssValuePool.createValue(style->borderRightStyle());
2809         case CSSPropertyBorderBottomStyle:
2810             return cssValuePool.createValue(style->borderBottomStyle());
2811         case CSSPropertyBorderLeftStyle:
2812             return cssValuePool.createValue(style->borderLeftStyle());
2813         case CSSPropertyBorderTopWidth:
2814             return zoomAdjustedPixelValue(style->borderTopWidth(), *style);
2815         case CSSPropertyBorderRightWidth:
2816             return zoomAdjustedPixelValue(style->borderRightWidth(), *style);
2817         case CSSPropertyBorderBottomWidth:
2818             return zoomAdjustedPixelValue(style->borderBottomWidth(), *style);
2819         case CSSPropertyBorderLeftWidth:
2820             return zoomAdjustedPixelValue(style->borderLeftWidth(), *style);
2821         case CSSPropertyBottom:
2822             return positionOffsetValue(*style, CSSPropertyBottom);
2823         case CSSPropertyWebkitBoxAlign:
2824             return cssValuePool.createValue(style->boxAlign());
2825 #if ENABLE(CSS_BOX_DECORATION_BREAK)
2826         case CSSPropertyWebkitBoxDecorationBreak:
2827             if (style->boxDecorationBreak() == DSLICE)
2828                 return cssValuePool.createIdentifierValue(CSSValueSlice);
2829         return cssValuePool.createIdentifierValue(CSSValueClone);
2830 #endif
2831         case CSSPropertyWebkitBoxDirection:
2832             return cssValuePool.createValue(style->boxDirection());
2833         case CSSPropertyWebkitBoxFlex:
2834             return cssValuePool.createValue(style->boxFlex(), CSSPrimitiveValue::CSS_NUMBER);
2835         case CSSPropertyWebkitBoxFlexGroup:
2836             return cssValuePool.createValue(style->boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER);
2837         case CSSPropertyWebkitBoxLines:
2838             return cssValuePool.createValue(style->boxLines());
2839         case CSSPropertyWebkitBoxOrdinalGroup:
2840             return cssValuePool.createValue(style->boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER);
2841         case CSSPropertyWebkitBoxOrient:
2842             return cssValuePool.createValue(style->boxOrient());
2843         case CSSPropertyWebkitBoxPack:
2844             return cssValuePool.createValue(style->boxPack());
2845         case CSSPropertyWebkitBoxReflect:
2846             return valueForReflection(style->boxReflect(), *style);
2847         case CSSPropertyBoxShadow:
2848         case CSSPropertyWebkitBoxShadow:
2849             return valueForShadow(style->boxShadow(), propertyID, *style);
2850         case CSSPropertyCaptionSide:
2851             return cssValuePool.createValue(style->captionSide());
2852         case CSSPropertyClear:
2853             return cssValuePool.createValue(style->clear());
2854         case CSSPropertyColor:
2855             return cssValuePool.createColorValue(m_allowVisitedStyle ? style->visitedDependentColor(CSSPropertyColor) : style->color());
2856         case CSSPropertyWebkitPrintColorAdjust:
2857             return cssValuePool.createValue(style->printColorAdjust());
2858         case CSSPropertyWebkitColumnAxis:
2859             return cssValuePool.createValue(style->columnAxis());
2860         case CSSPropertyColumnCount:
2861             if (style->hasAutoColumnCount())
2862                 return cssValuePool.createIdentifierValue(CSSValueAuto);
2863             return cssValuePool.createValue(style->columnCount(), CSSPrimitiveValue::CSS_NUMBER);
2864         case CSSPropertyColumnFill:
2865             return cssValuePool.createValue(style->columnFill());
2866         case CSSPropertyColumnGap:
2867             if (style->hasNormalColumnGap())
2868                 return cssValuePool.createIdentifierValue(CSSValueNormal);
2869             return zoomAdjustedPixelValue(style->columnGap(), *style);
2870         case CSSPropertyWebkitColumnProgression:
2871             return cssValuePool.createValue(style->columnProgression());
2872         case CSSPropertyColumnRuleColor:
2873             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor)) : currentColorOrValidColor(style, style->columnRuleColor());
2874         case CSSPropertyColumnRuleStyle:
2875             return cssValuePool.createValue(style->columnRuleStyle());
2876         case CSSPropertyColumnRuleWidth:
2877             return zoomAdjustedPixelValue(style->columnRuleWidth(), *style);
2878         case CSSPropertyColumnSpan:
2879             return cssValuePool.createIdentifierValue(style->columnSpan() ? CSSValueAll : CSSValueNone);
2880         case CSSPropertyWebkitColumnBreakAfter:
2881             return cssValuePool.createValue(convertToColumnBreak(style->breakAfter()));
2882         case CSSPropertyWebkitColumnBreakBefore:
2883             return cssValuePool.createValue(convertToColumnBreak(style->breakBefore()));
2884         case CSSPropertyWebkitColumnBreakInside:
2885             return cssValuePool.createValue(convertToColumnBreak(style->breakInside()));
2886         case CSSPropertyColumnWidth:
2887             if (style->hasAutoColumnWidth())
2888                 return cssValuePool.createIdentifierValue(CSSValueAuto);
2889             return zoomAdjustedPixelValue(style->columnWidth(), *style);
2890         case CSSPropertyTabSize:
2891             return cssValuePool.createValue(style->tabSize(), CSSPrimitiveValue::CSS_NUMBER);
2892 #if ENABLE(CSS_REGIONS)
2893         case CSSPropertyWebkitRegionBreakAfter:
2894             return cssValuePool.createValue(convertToRegionBreak(style->breakAfter()));
2895         case CSSPropertyWebkitRegionBreakBefore:
2896             return cssValuePool.createValue(convertToRegionBreak(style->breakBefore()));
2897         case CSSPropertyWebkitRegionBreakInside:
2898             return cssValuePool.createValue(convertToRegionBreak(style->breakInside()));
2899 #endif
2900         case CSSPropertyCursor: {
2901             RefPtr<CSSValueList> list;
2902             auto* cursors = style->cursors();
2903             if (cursors && cursors->size() > 0) {
2904                 list = CSSValueList::createCommaSeparated();
2905                 for (unsigned i = 0; i < cursors->size(); ++i)
2906                     if (StyleImage* image = cursors->at(i).image())
2907                         list->append(image->cssValue());
2908             }
2909             auto value = cssValuePool.createValue(style->cursor());
2910             if (list) {
2911                 list->append(WTFMove(value));
2912                 return list;
2913             }
2914             return WTFMove(value);
2915         }
2916 #if ENABLE(CURSOR_VISIBILITY)
2917         case CSSPropertyWebkitCursorVisibility:
2918             return cssValuePool.createValue(style->cursorVisibility());
2919 #endif
2920         case CSSPropertyDirection:
2921             return cssValuePool.createValue(style->direction());
2922         case CSSPropertyDisplay:
2923             return cssValuePool.createValue(style->display());
2924         case CSSPropertyEmptyCells:
2925             return cssValuePool.createValue(style->emptyCells());
2926         case CSSPropertyAlignContent:
2927             return valueForContentPositionAndDistributionWithOverflowAlignment(style->alignContent(), CSSValueStretch);
2928         case CSSPropertyAlignItems:
2929             return valueForItemPositionWithOverflowAlignment(style->alignItems());
2930         case CSSPropertyAlignSelf:
2931             return valueForItemPositionWithOverflowAlignment(resolveAlignSelfAuto(style->alignSelf(), styledElement->parentNode()));
2932         case CSSPropertyFlex:
2933             return getCSSPropertyValuesForShorthandProperties(flexShorthand());
2934         case CSSPropertyFlexBasis:
2935             return cssValuePool.createValue(style->flexBasis(), *style);
2936         case CSSPropertyFlexDirection:
2937             return cssValuePool.createValue(style->flexDirection());
2938         case CSSPropertyFlexFlow:
2939             return getCSSPropertyValuesForShorthandProperties(flexFlowShorthand());
2940         case CSSPropertyFlexGrow:
2941             return cssValuePool.createValue(style->flexGrow());
2942         case CSSPropertyFlexShrink:
2943             return cssValuePool.createValue(style->flexShrink());
2944         case CSSPropertyFlexWrap:
2945             return cssValuePool.createValue(style->flexWrap());
2946         case CSSPropertyJustifyContent:
2947             return valueForContentPositionAndDistributionWithOverflowAlignment(style->justifyContent(), CSSValueFlexStart);
2948         case CSSPropertyJustifyItems:
2949             return valueForItemPositionWithOverflowAlignment(resolveJustifyItemsAuto(style->justifyItems(), styledElement->parentNode()));
2950         case CSSPropertyJustifySelf:
2951             return valueForItemPositionWithOverflowAlignment(resolveJustifySelfAuto(style->justifySelf(), styledElement->parentNode()));
2952         case CSSPropertyPlaceContent:
2953             return getCSSPropertyValuesForShorthandProperties(placeContentShorthand());
2954         case CSSPropertyPlaceItems:
2955             return getCSSPropertyValuesForShorthandProperties(placeItemsShorthand());
2956         case CSSPropertyOrder:
2957             return cssValuePool.createValue(style->order(), CSSPrimitiveValue::CSS_NUMBER);
2958         case CSSPropertyFloat:
2959             if (style->display() != NONE && style->hasOutOfFlowPosition())
2960                 return cssValuePool.createIdentifierValue(CSSValueNone);
2961             return cssValuePool.createValue(style->floating());
2962         case CSSPropertyFont: {
2963             auto computedFont = fontShorthandValueForSelectionProperties(style->fontDescription());
2964             computedFont->size = fontSizeFromStyle(*style);
2965             computedFont->lineHeight = lineHeightFromStyle(*style);
2966             computedFont->family = fontFamilyListFromStyle(*style);
2967             return WTFMove(computedFont);
2968         }
2969         case CSSPropertyFontFamily:
2970             return fontFamilyFromStyle(*style);
2971         case CSSPropertyFontSize:
2972             return fontSizeFromStyle(*style);
2973         case CSSPropertyFontStyle:
2974             return fontStyleFromStyle(*style);
2975         case CSSPropertyFontStretch:
2976             return fontStretchFromStyle(*style);
2977         case CSSPropertyFontVariant:
2978             return fontVariantFromStyle(*style);
2979         case CSSPropertyFontWeight:
2980             return fontWeightFromStyle(*style);
2981         case CSSPropertyFontSynthesis:
2982             return fontSynthesisFromStyle(*style);
2983         case CSSPropertyFontFeatureSettings: {
2984             const FontFeatureSettings& featureSettings = style->fontDescription().featureSettings();
2985             if (!featureSettings.size())
2986                 return cssValuePool.createIdentifierValue(CSSValueNormal);
2987             auto list = CSSValueList::createCommaSeparated();
2988             for (auto& feature : featureSettings)
2989                 list->append(CSSFontFeatureValue::create(FontTag(feature.tag()), feature.value()));
2990             return WTFMove(list);
2991         }
2992 #if ENABLE(VARIATION_FONTS)
2993         case CSSPropertyFontVariationSettings: {
2994             const FontVariationSettings& variationSettings = style->fontDescription().variationSettings();
2995             if (variationSettings.isEmpty())
2996                 return cssValuePool.createIdentifierValue(CSSValueNormal);
2997             auto list = CSSValueList::createCommaSeparated();
2998             for (auto& feature : variationSettings)
2999                 list->append(CSSFontVariationValue::create(feature.tag(), feature.value()));
3000             return WTFMove(list);
3001         }
3002         case CSSPropertyFontOpticalSizing:
3003             return cssValuePool.createValue(style->fontDescription().opticalSizing());
3004 #endif
3005         case CSSPropertyGridAutoFlow: {
3006             auto list = CSSValueList::createSpaceSeparated();
3007             ASSERT(style->isGridAutoFlowDirectionRow() || style->isGridAutoFlowDirectionColumn());
3008             if (style->isGridAutoFlowDirectionRow())
3009                 list->append(cssValuePool.createIdentifierValue(CSSValueRow));
3010             else
3011                 list->append(cssValuePool.createIdentifierValue(CSSValueColumn));
3012
3013             if (style->isGridAutoFlowAlgorithmDense())
3014                 list->append(cssValuePool.createIdentifierValue(CSSValueDense));
3015
3016             return WTFMove(list);
3017         }
3018
3019         // Specs mention that getComputedStyle() should return the used value of the property instead of the computed
3020         // one for grid-template-{rows|columns} but not for the grid-auto-{rows|columns} as things like
3021         // grid-auto-columns: 2fr; cannot be resolved to a value in pixels as the '2fr' means very different things
3022         // depending on the size of the explicit grid or the number of implicit tracks added to the grid. See
3023         // http://lists.w3.org/Archives/Public/www-style/2013Nov/0014.html
3024         case CSSPropertyGridAutoColumns:
3025             return valueForGridTrackSizeList(ForColumns, *style);
3026         case CSSPropertyGridAutoRows:
3027             return valueForGridTrackSizeList(ForRows, *style);
3028
3029         case CSSPropertyGridTemplateColumns:
3030             return valueForGridTrackList(ForColumns, renderer, *style);
3031         case CSSPropertyGridTemplateRows:
3032             return valueForGridTrackList(ForRows, renderer, *style);
3033
3034         case CSSPropertyGridColumnStart:
3035             return valueForGridPosition(style->gridItemColumnStart());
3036         case CSSPropertyGridColumnEnd:
3037             return valueForGridPosition(style->gridItemColumnEnd());
3038         case CSSPropertyGridRowStart:
3039             return valueForGridPosition(style->gridItemRowStart());
3040         case CSSPropertyGridRowEnd:
3041             return valueForGridPosition(style->gridItemRowEnd());
3042         case CSSPropertyGridArea:
3043             return getCSSPropertyValuesForGridShorthand(gridAreaShorthand());
3044         case CSSPropertyGridTemplate:
3045             return getCSSPropertyValuesForGridShorthand(gridTemplateShorthand());
3046         case CSSPropertyGrid:
3047             return getCSSPropertyValuesForGridShorthand(gridShorthand());
3048         case CSSPropertyGridColumn:
3049             return getCSSPropertyValuesForGridShorthand(gridColumnShorthand());
3050         case CSSPropertyGridRow:
3051             return getCSSPropertyValuesForGridShorthand(gridRowShorthand());
3052         case CSSPropertyGridTemplateAreas:
3053             if (!style->namedGridAreaRowCount()) {
3054                 ASSERT(!style->namedGridAreaColumnCount());
3055                 return cssValuePool.createIdentifierValue(CSSValueNone);
3056             }
3057             return CSSGridTemplateAreasValue::create(style->namedGridArea(), style->namedGridAreaRowCount(), style->namedGridAreaColumnCount());
3058         case CSSPropertyGridColumnGap:
3059             return zoomAdjustedPixelValueForLength(style->gridColumnGap(), *style);
3060         case CSSPropertyGridRowGap:
3061             return zoomAdjustedPixelValueForLength(style->gridRowGap(), *style);
3062         case CSSPropertyGridGap:
3063             return getCSSPropertyValuesForGridShorthand(gridGapShorthand());
3064         case CSSPropertyHeight:
3065             if (renderer && !renderer->isRenderSVGModelObject()) {
3066                 // According to http://www.w3.org/TR/CSS2/visudet.html#the-height-property,
3067                 // the "height" property does not apply for non-replaced inline elements.
3068                 if (!renderer->isReplaced() && renderer->isInline())
3069                     return cssValuePool.createIdentifierValue(CSSValueAuto);
3070                 return zoomAdjustedPixelValue(sizingBox(*renderer).height(), *style);
3071             }
3072             return zoomAdjustedPixelValueForLength(style->height(), *style);
3073         case CSSPropertyWebkitHyphens:
3074             return cssValuePool.createValue(style->hyphens());
3075         case CSSPropertyWebkitHyphenateCharacter:
3076             if (style->hyphenationString().isNull())
3077                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3078             return cssValuePool.createValue(style->hyphenationString(), CSSPrimitiveValue::CSS_STRING);
3079         case CSSPropertyWebkitHyphenateLimitAfter:
3080             if (style->hyphenationLimitAfter() < 0)
3081                 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
3082             return CSSPrimitiveValue::create(style->hyphenationLimitAfter(), CSSPrimitiveValue::CSS_NUMBER);
3083         case CSSPropertyWebkitHyphenateLimitBefore:
3084             if (style->hyphenationLimitBefore() < 0)
3085                 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
3086             return CSSPrimitiveValue::create(style->hyphenationLimitBefore(), CSSPrimitiveValue::CSS_NUMBER);
3087         case CSSPropertyWebkitHyphenateLimitLines:
3088             if (style->hyphenationLimitLines() < 0)
3089                 return CSSPrimitiveValue::createIdentifier(CSSValueNoLimit);
3090             return CSSPrimitiveValue::create(style->hyphenationLimitLines(), CSSPrimitiveValue::CSS_NUMBER);
3091         case CSSPropertyWebkitBorderFit:
3092             if (style->borderFit() == BorderFitBorder)
3093                 return cssValuePool.createIdentifierValue(CSSValueBorder);
3094             return cssValuePool.createIdentifierValue(CSSValueLines);
3095 #if ENABLE(CSS_IMAGE_ORIENTATION)
3096         case CSSPropertyImageOrientation:
3097             return cssValuePool.createValue(style->imageOrientation());
3098 #endif
3099         case CSSPropertyImageRendering:
3100             return CSSPrimitiveValue::create(style->imageRendering());
3101 #if ENABLE(CSS_IMAGE_RESOLUTION)
3102         case CSSPropertyImageResolution:
3103             return cssValuePool.createValue(style->imageResolution(), CSSPrimitiveValue::CSS_DPPX);
3104 #endif
3105         case CSSPropertyLeft:
3106             return positionOffsetValue(*style, CSSPropertyLeft);
3107         case CSSPropertyLetterSpacing:
3108             if (!style->letterSpacing())
3109                 return cssValuePool.createIdentifierValue(CSSValueNormal);
3110             return zoomAdjustedPixelValue(style->letterSpacing(), *style);
3111         case CSSPropertyWebkitLineClamp:
3112             if (style->lineClamp().isNone())
3113                 return cssValuePool.createIdentifierValue(CSSValueNone);
3114             return cssValuePool.createValue(style->lineClamp().value(), style->lineClamp().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER);
3115         case CSSPropertyLineHeight:
3116             return lineHeightFromStyle(*style);
3117         case CSSPropertyListStyleImage:
3118             if (style->listStyleImage())
3119                 return style->listStyleImage()->cssValue();
3120             return cssValuePool.createIdentifierValue(CSSValueNone);
3121         case CSSPropertyListStylePosition:
3122             return cssValuePool.createValue(style->listStylePosition());
3123         case CSSPropertyListStyleType:
3124             return cssValuePool.createValue(style->listStyleType());
3125         case CSSPropertyWebkitLocale:
3126             if (style->locale().isNull())
3127                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3128             return cssValuePool.createValue(style->locale(), CSSPrimitiveValue::CSS_STRING);
3129         case CSSPropertyMarginTop:
3130             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginTop, &RenderBoxModelObject::marginTop>(*style, renderer);
3131         case CSSPropertyMarginRight: {
3132             Length marginRight = style->marginRight();
3133             if (marginRight.isFixed() || !is<RenderBox>(renderer))
3134                 return zoomAdjustedPixelValueForLength(marginRight, *style);
3135             float value;
3136             if (marginRight.isPercentOrCalculated()) {
3137                 // RenderBox gives a marginRight() that is the distance between the right-edge of the child box
3138                 // and the right-edge of the containing box, when display == BLOCK. Let's calculate the absolute
3139                 // value of the specified margin-right % instead of relying on RenderBox's marginRight() value.
3140                 value = minimumValueForLength(marginRight, downcast<RenderBox>(*renderer).containingBlockLogicalWidthForContent());
3141             } else
3142                 value = downcast<RenderBox>(*renderer).marginRight();
3143             return zoomAdjustedPixelValue(value, *style);
3144         }
3145         case CSSPropertyMarginBottom:
3146             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginBottom, &RenderBoxModelObject::marginBottom>(*style, renderer);
3147         case CSSPropertyMarginLeft:
3148             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginLeft, &RenderBoxModelObject::marginLeft>(*style, renderer);
3149         case CSSPropertyWebkitMarqueeDirection:
3150             return cssValuePool.createValue(style->marqueeDirection());
3151         case CSSPropertyWebkitMarqueeIncrement:
3152             return cssValuePool.createValue(style->marqueeIncrement());
3153         case CSSPropertyWebkitMarqueeRepetition:
3154             if (style->marqueeLoopCount() < 0)
3155                 return cssValuePool.createIdentifierValue(CSSValueInfinite);
3156             return cssValuePool.createValue(style->marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER);
3157         case CSSPropertyWebkitMarqueeStyle:
3158             return cssValuePool.createValue(style->marqueeBehavior());
3159         case CSSPropertyWebkitUserModify:
3160             return cssValuePool.createValue(style->userModify());
3161         case CSSPropertyMaxHeight: {
3162             const Length& maxHeight = style->maxHeight();
3163             if (maxHeight.isUndefined())
3164                 return cssValuePool.createIdentifierValue(CSSValueNone);
3165             return zoomAdjustedPixelValueForLength(maxHeight, *style);
3166         }
3167         case CSSPropertyMaxWidth: {
3168             const Length& maxWidth = style->maxWidth();
3169             if (maxWidth.isUndefined())
3170                 return cssValuePool.createIdentifierValue(CSSValueNone);
3171             return zoomAdjustedPixelValueForLength(maxWidth, *style);
3172         }
3173         case CSSPropertyMinHeight:
3174             if (style->minHeight().isAuto()) {
3175                 if (isFlexOrGrid(styledElement->parentNode()))
3176                     return cssValuePool.createIdentifierValue(CSSValueAuto);
3177                 return zoomAdjustedPixelValue(0, *style);
3178             }
3179             return zoomAdjustedPixelValueForLength(style->minHeight(), *style);
3180         case CSSPropertyMinWidth:
3181             if (style->minWidth().isAuto()) {
3182                 if (isFlexOrGrid(styledElement->parentNode()))
3183                     return cssValuePool.createIdentifierValue(CSSValueAuto);
3184                 return zoomAdjustedPixelValue(0, *style);
3185             }
3186             return zoomAdjustedPixelValueForLength(style->minWidth(), *style);
3187         case CSSPropertyObjectFit:
3188             return cssValuePool.createValue(style->objectFit());
3189         case CSSPropertyObjectPosition: {
3190             auto list = CSSValueList::createSpaceSeparated();
3191             list->append(zoomAdjustedPixelValueForLength(style->objectPosition().x(), *style));
3192             list->append(zoomAdjustedPixelValueForLength(style->objectPosition().y(), *style));
3193             return WTFMove(list);
3194         }
3195         case CSSPropertyOpacity:
3196             return cssValuePool.createValue(style->opacity(), CSSPrimitiveValue::CSS_NUMBER);
3197         case CSSPropertyOrphans:
3198             if (style->hasAutoOrphans())
3199                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3200             return cssValuePool.createValue(style->orphans(), CSSPrimitiveValue::CSS_NUMBER);
3201         case CSSPropertyOutlineColor:
3202             return m_allowVisitedStyle ? cssValuePool.createColorValue(style->visitedDependentColor(CSSPropertyOutlineColor)) : currentColorOrValidColor(style, style->outlineColor());
3203         case CSSPropertyOutlineOffset:
3204             return zoomAdjustedPixelValue(style->outlineOffset(), *style);
3205         case CSSPropertyOutlineStyle:
3206             if (style->outlineStyleIsAuto())
3207                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3208             return cssValuePool.createValue(style->outlineStyle());
3209         case CSSPropertyOutlineWidth:
3210             return zoomAdjustedPixelValue(style->outlineWidth(), *style);
3211         case CSSPropertyOverflow:
3212             return cssValuePool.createValue(std::max(style->overflowX(), style->overflowY()));
3213         case CSSPropertyOverflowWrap:
3214             return cssValuePool.createValue(style->overflowWrap());
3215         case CSSPropertyOverflowX:
3216             return cssValuePool.createValue(style->overflowX());
3217         case CSSPropertyOverflowY:
3218             return cssValuePool.createValue(style->overflowY());
3219         case CSSPropertyPaddingTop:
3220             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingTop, &RenderBoxModelObject::computedCSSPaddingTop>(*style, renderer);
3221         case CSSPropertyPaddingRight:
3222             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingRight, &RenderBoxModelObject::computedCSSPaddingRight>(*style, renderer);
3223         case CSSPropertyPaddingBottom:
3224             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingBottom, &RenderBoxModelObject::computedCSSPaddingBottom>(*style, renderer);
3225         case CSSPropertyPaddingLeft:
3226             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingLeft, &RenderBoxModelObject::computedCSSPaddingLeft>(*style, renderer);
3227         case CSSPropertyPageBreakAfter:
3228             return cssValuePool.createValue(convertToPageBreak(style->breakAfter()));
3229         case CSSPropertyPageBreakBefore:
3230             return cssValuePool.createValue(convertToPageBreak(style->breakBefore()));
3231         case CSSPropertyPageBreakInside:
3232             return cssValuePool.createValue(convertToPageBreak(style->breakInside()));
3233         case CSSPropertyBreakAfter:
3234             return cssValuePool.createValue(style->breakAfter());
3235         case CSSPropertyBreakBefore:
3236             return cssValuePool.createValue(style->breakBefore());
3237         case CSSPropertyBreakInside:
3238             return cssValuePool.createValue(style->breakInside());
3239         case CSSPropertyHangingPunctuation:
3240             return hangingPunctuationToCSSValue(style->hangingPunctuation());
3241         case CSSPropertyPosition:
3242             return cssValuePool.createValue(style->position());
3243         case CSSPropertyRight:
3244             return positionOffsetValue(*style, CSSPropertyRight);
3245         case CSSPropertyWebkitRubyPosition:
3246             return cssValuePool.createValue(style->rubyPosition());
3247         case CSSPropertyTableLayout:
3248             return cssValuePool.createValue(style->tableLayout());
3249         case CSSPropertyTextAlign:
3250             return cssValuePool.createValue(style->textAlign());