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