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