18ff918bb6acf4930feb381a452967833c7ea730
[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     CSSPropertyRowGap,
301     CSSPropertyWebkitColumnProgression,
302     CSSPropertyColumnRuleColor,
303     CSSPropertyColumnRuleStyle,
304     CSSPropertyColumnRuleWidth,
305     CSSPropertyColumnSpan,
306     CSSPropertyColumnWidth,
307 #if ENABLE(CURSOR_VISIBILITY)
308     CSSPropertyWebkitCursorVisibility,
309 #endif
310 #if ENABLE(DASHBOARD_SUPPORT)
311     CSSPropertyWebkitDashboardRegion,
312 #endif
313     CSSPropertyAlignContent,
314     CSSPropertyAlignItems,
315     CSSPropertyAlignSelf,
316     CSSPropertyFilter,
317     CSSPropertyFlexBasis,
318     CSSPropertyFlexDirection,
319     CSSPropertyFlexFlow,
320     CSSPropertyFlexGrow,
321     CSSPropertyFlexShrink,
322     CSSPropertyFlexWrap,
323     CSSPropertyJustifyContent,
324     CSSPropertyJustifySelf,
325     CSSPropertyJustifyItems,
326     CSSPropertyPlaceContent,
327     CSSPropertyPlaceItems,
328     CSSPropertyPlaceSelf,
329 #if ENABLE(FILTERS_LEVEL_2)
330     CSSPropertyWebkitBackdropFilter,
331 #endif
332     CSSPropertyWebkitFontKerning,
333     CSSPropertyWebkitFontSmoothing,
334     CSSPropertyFontVariantLigatures,
335     CSSPropertyFontVariantPosition,
336     CSSPropertyFontVariantCaps,
337     CSSPropertyFontVariantNumeric,
338     CSSPropertyFontVariantAlternates,
339     CSSPropertyFontVariantEastAsian,
340 #if ENABLE(VARIATION_FONTS)
341     CSSPropertyFontVariationSettings,
342 #endif
343     CSSPropertyGridAutoColumns,
344     CSSPropertyGridAutoFlow,
345     CSSPropertyGridAutoRows,
346     CSSPropertyGridColumnEnd,
347     CSSPropertyGridColumnStart,
348     CSSPropertyGridTemplateAreas,
349     CSSPropertyGridTemplateColumns,
350     CSSPropertyGridTemplateRows,
351     CSSPropertyGridRowEnd,
352     CSSPropertyGridRowStart,
353     CSSPropertyWebkitHyphenateCharacter,
354     CSSPropertyWebkitHyphenateLimitAfter,
355     CSSPropertyWebkitHyphenateLimitBefore,
356     CSSPropertyWebkitHyphenateLimitLines,
357     CSSPropertyWebkitHyphens,
358     CSSPropertyWebkitInitialLetter,
359     CSSPropertyWebkitLineAlign,
360     CSSPropertyWebkitLineBoxContain,
361     CSSPropertyLineBreak,
362     CSSPropertyWebkitLineClamp,
363     CSSPropertyWebkitLinesClamp,
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 = downcast<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 = downcast<StepsTimingFunction>(timingFunction);
1569         return CSSStepsTimingFunctionValue::create(function.numberOfSteps(), function.stepAtStart());
1570     }
1571     case TimingFunction::FramesFunction: {
1572         auto& function = downcast<FramesTimingFunction>(timingFunction);
1573         return CSSFramesTimingFunctionValue::create(function.numberOfFrames());
1574     }
1575     case TimingFunction::SpringFunction: {
1576         auto& function = downcast<SpringTimingFunction>(timingFunction);
1577         return CSSSpringTimingFunctionValue::create(function.mass(), function.stiffness(), function.damping(), function.initialVelocity());
1578     }
1579     default:
1580         ASSERT(timingFunction.type() == TimingFunction::LinearFunction);
1581         return CSSValuePool::singleton().createIdentifierValue(CSSValueLinear);
1582     }
1583 }
1584
1585 static Ref<CSSValueList> timingFunctionValue(const AnimationList* animationList)
1586 {
1587     auto list = CSSValueList::createCommaSeparated();
1588     if (animationList) {
1589         for (size_t i = 0; i < animationList->size(); ++i)
1590             list->append(createTimingFunctionValue(*animationList->animation(i).timingFunction()));
1591     } else
1592         // Note that initialAnimationTimingFunction() is used for both transitions and animations
1593         list->append(createTimingFunctionValue(Animation::initialTimingFunction()));
1594     return list;
1595 }
1596
1597 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
1598
1599 static Ref<CSSValue> createAnimationTriggerValue(const AnimationTrigger& trigger, const RenderStyle& style)
1600 {
1601     switch (trigger.type()) {
1602     case AnimationTrigger::AnimationTriggerType::ScrollAnimationTriggerType: {
1603         auto& scrollAnimationTrigger = downcast<ScrollAnimationTrigger>(trigger);
1604         if (scrollAnimationTrigger.endValue().isAuto())
1605             return CSSAnimationTriggerScrollValue::create(zoomAdjustedPixelValueForLength(scrollAnimationTrigger.startValue(), style));
1606         return CSSAnimationTriggerScrollValue::create(zoomAdjustedPixelValueForLength(scrollAnimationTrigger.startValue(), style),
1607                                                       zoomAdjustedPixelValueForLength(scrollAnimationTrigger.endValue(), style));
1608     }
1609     default:
1610         ASSERT(trigger.type() == AnimationTrigger::AnimationTriggerType::AutoAnimationTriggerType);
1611         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1612     }
1613 }
1614
1615 static Ref<CSSValueList> animationTriggerValue(const AnimationList* animationList, const RenderStyle& style)
1616 {
1617     auto list = CSSValueList::createCommaSeparated();
1618     if (animationList) {
1619         for (size_t i = 0; i < animationList->size(); ++i)
1620             list->append(createAnimationTriggerValue(*animationList->animation(i).trigger(), style));
1621     } else
1622         list->append(createAnimationTriggerValue(Animation::initialTrigger().get(), style));
1623     return list;
1624 }
1625
1626 #endif
1627
1628 static Ref<CSSValue> createLineBoxContainValue(unsigned lineBoxContain)
1629 {
1630     if (!lineBoxContain)
1631         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1632     return CSSLineBoxContainValue::create(lineBoxContain);
1633 }
1634
1635 static Element* styleElementForNode(Node* node)
1636 {
1637     if (!node)
1638         return nullptr;
1639     if (is<Element>(*node))
1640         return downcast<Element>(node);
1641     return composedTreeAncestors(*node).first();
1642 }
1643
1644 ComputedStyleExtractor::ComputedStyleExtractor(Node* node, bool allowVisitedStyle, PseudoId pseudoElementSpecifier)
1645     : m_element(styleElementForNode(node))
1646     , m_pseudoElementSpecifier(pseudoElementSpecifier)
1647     , m_allowVisitedStyle(allowVisitedStyle)
1648 {
1649 }
1650
1651 ComputedStyleExtractor::ComputedStyleExtractor(Element* element, bool allowVisitedStyle, PseudoId pseudoElementSpecifier)
1652     : m_element(element)
1653     , m_pseudoElementSpecifier(pseudoElementSpecifier)
1654     , m_allowVisitedStyle(allowVisitedStyle)
1655 {
1656 }
1657
1658 CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(Element& element, bool allowVisitedStyle, const String& pseudoElementName)
1659     : m_element(element)
1660     , m_allowVisitedStyle(allowVisitedStyle)
1661     , m_refCount(1)
1662 {
1663     unsigned nameWithoutColonsStart = pseudoElementName[0] == ':' ? (pseudoElementName[1] == ':' ? 2 : 1) : 0;
1664     m_pseudoElementSpecifier = CSSSelector::pseudoId(CSSSelector::parsePseudoElementType(
1665     (pseudoElementName.substringSharingImpl(nameWithoutColonsStart))));
1666 }
1667
1668 CSSComputedStyleDeclaration::~CSSComputedStyleDeclaration() = default;
1669
1670 void CSSComputedStyleDeclaration::ref()
1671 {
1672     ++m_refCount;
1673 }
1674
1675 void CSSComputedStyleDeclaration::deref()
1676 {
1677     ASSERT(m_refCount);
1678     if (!--m_refCount)
1679         delete this;
1680 }
1681
1682 String CSSComputedStyleDeclaration::cssText() const
1683 {
1684     StringBuilder result;
1685
1686     for (unsigned i = 0; i < numComputedProperties; i++) {
1687         if (i)
1688             result.append(' ');
1689         result.append(getPropertyName(computedProperties[i]));
1690         result.appendLiteral(": ");
1691         result.append(getPropertyValue(computedProperties[i]));
1692         result.append(';');
1693     }
1694
1695     return result.toString();
1696 }
1697
1698 ExceptionOr<void> CSSComputedStyleDeclaration::setCssText(const String&)
1699 {
1700     return Exception { NoModificationAllowedError };
1701 }
1702
1703 RefPtr<CSSPrimitiveValue> ComputedStyleExtractor::getFontSizeCSSValuePreferringKeyword()
1704 {
1705     if (!m_element)
1706         return nullptr;
1707
1708     m_element->document().updateLayoutIgnorePendingStylesheets();
1709
1710     auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
1711     if (!style)
1712         return nullptr;
1713
1714     if (CSSValueID sizeIdentifier = style->fontDescription().keywordSizeAsIdentifier())
1715         return CSSValuePool::singleton().createIdentifierValue(sizeIdentifier);
1716
1717     return zoomAdjustedPixelValue(style->fontDescription().computedSize(), *style);
1718 }
1719
1720 bool ComputedStyleExtractor::useFixedFontDefaultSize()
1721 {
1722     if (!m_element)
1723         return false;
1724     auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
1725     if (!style)
1726         return false;
1727
1728     return style->fontDescription().useFixedDefaultSize();
1729 }
1730
1731
1732 static CSSValueID identifierForFamily(const AtomicString& family)
1733 {
1734     if (family == cursiveFamily)
1735         return CSSValueCursive;
1736     if (family == fantasyFamily)
1737         return CSSValueFantasy;
1738     if (family == monospaceFamily)
1739         return CSSValueMonospace;
1740     if (family == pictographFamily)
1741         return CSSValueWebkitPictograph;
1742     if (family == sansSerifFamily)
1743         return CSSValueSansSerif;
1744     if (family == serifFamily)
1745         return CSSValueSerif;
1746     if (family == systemUiFamily)
1747         return CSSValueSystemUi;
1748     return CSSValueInvalid;
1749 }
1750
1751 static Ref<CSSPrimitiveValue> valueForFamily(const AtomicString& family)
1752 {
1753     if (CSSValueID familyIdentifier = identifierForFamily(family))
1754         return CSSValuePool::singleton().createIdentifierValue(familyIdentifier);
1755     return CSSValuePool::singleton().createFontFamilyValue(family);
1756 }
1757
1758 static Ref<CSSValue> renderTextDecorationFlagsToCSSValue(int textDecoration)
1759 {
1760     auto& cssValuePool = CSSValuePool::singleton();
1761     // Blink value is ignored.
1762     auto list = CSSValueList::createSpaceSeparated();
1763     if (textDecoration & TextDecorationUnderline)
1764         list->append(cssValuePool.createIdentifierValue(CSSValueUnderline));
1765     if (textDecoration & TextDecorationOverline)
1766         list->append(cssValuePool.createIdentifierValue(CSSValueOverline));
1767     if (textDecoration & TextDecorationLineThrough)
1768         list->append(cssValuePool.createIdentifierValue(CSSValueLineThrough));
1769 #if ENABLE(LETTERPRESS)
1770     if (textDecoration & TextDecorationLetterpress)
1771         list->append(cssValuePool.createIdentifierValue(CSSValueWebkitLetterpress));
1772 #endif
1773
1774     if (!list->length())
1775         return cssValuePool.createIdentifierValue(CSSValueNone);
1776     return WTFMove(list);
1777 }
1778
1779 static Ref<CSSValue> renderTextDecorationStyleFlagsToCSSValue(TextDecorationStyle textDecorationStyle)
1780 {
1781     switch (textDecorationStyle) {
1782     case TextDecorationStyleSolid:
1783         return CSSValuePool::singleton().createIdentifierValue(CSSValueSolid);
1784     case TextDecorationStyleDouble:
1785         return CSSValuePool::singleton().createIdentifierValue(CSSValueDouble);
1786     case TextDecorationStyleDotted:
1787         return CSSValuePool::singleton().createIdentifierValue(CSSValueDotted);
1788     case TextDecorationStyleDashed:
1789         return CSSValuePool::singleton().createIdentifierValue(CSSValueDashed);
1790     case TextDecorationStyleWavy:
1791         return CSSValuePool::singleton().createIdentifierValue(CSSValueWavy);
1792     }
1793
1794     ASSERT_NOT_REACHED();
1795     return CSSValuePool::singleton().createExplicitInitialValue();
1796 }
1797
1798 static Ref<CSSValue> renderTextDecorationSkipFlagsToCSSValue(TextDecorationSkip textDecorationSkip)
1799 {
1800     switch (textDecorationSkip) {
1801     case TextDecorationSkipAuto:
1802         return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1803     case TextDecorationSkipNone:
1804         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1805     case TextDecorationSkipInk:
1806         return CSSValuePool::singleton().createIdentifierValue(CSSValueInk);
1807     case TextDecorationSkipObjects:
1808         return CSSValuePool::singleton().createIdentifierValue(CSSValueObjects);
1809     }
1810
1811     ASSERT_NOT_REACHED();
1812     return CSSValuePool::singleton().createExplicitInitialValue();
1813 }
1814
1815 static Ref<CSSValue> renderEmphasisPositionFlagsToCSSValue(TextEmphasisPosition textEmphasisPosition)
1816 {
1817     ASSERT(!((textEmphasisPosition & TextEmphasisPositionOver) && (textEmphasisPosition & TextEmphasisPositionUnder)));
1818     ASSERT(!((textEmphasisPosition & TextEmphasisPositionLeft) && (textEmphasisPosition & TextEmphasisPositionRight)));
1819     auto& cssValuePool = CSSValuePool::singleton();
1820     auto list = CSSValueList::createSpaceSeparated();
1821     if (textEmphasisPosition & TextEmphasisPositionOver)
1822         list->append(cssValuePool.createIdentifierValue(CSSValueOver));
1823     if (textEmphasisPosition & TextEmphasisPositionUnder)
1824         list->append(cssValuePool.createIdentifierValue(CSSValueUnder));
1825     if (textEmphasisPosition & TextEmphasisPositionLeft)
1826         list->append(cssValuePool.createIdentifierValue(CSSValueLeft));
1827     if (textEmphasisPosition & TextEmphasisPositionRight)
1828         list->append(cssValuePool.createIdentifierValue(CSSValueRight));
1829     if (!list->length())
1830         return cssValuePool.createIdentifierValue(CSSValueNone);
1831     return WTFMove(list);
1832 }
1833
1834 static Ref<CSSValue> speakAsToCSSValue(ESpeakAs speakAs)
1835 {
1836     auto& cssValuePool = CSSValuePool::singleton();
1837     auto list = CSSValueList::createSpaceSeparated();
1838     if (speakAs & SpeakNormal)
1839         list->append(cssValuePool.createIdentifierValue(CSSValueNormal));
1840     if (speakAs & SpeakSpellOut)
1841         list->append(cssValuePool.createIdentifierValue(CSSValueSpellOut));
1842     if (speakAs & SpeakDigits)
1843         list->append(cssValuePool.createIdentifierValue(CSSValueDigits));
1844     if (speakAs & SpeakLiteralPunctuation)
1845         list->append(cssValuePool.createIdentifierValue(CSSValueLiteralPunctuation));
1846     if (speakAs & SpeakNoPunctuation)
1847         list->append(cssValuePool.createIdentifierValue(CSSValueNoPunctuation));
1848     if (!list->length())
1849         return cssValuePool.createIdentifierValue(CSSValueNormal);
1850     return WTFMove(list);
1851 }
1852     
1853 static Ref<CSSValue> hangingPunctuationToCSSValue(HangingPunctuation hangingPunctuation)
1854 {
1855     auto& cssValuePool = CSSValuePool::singleton();
1856     auto list = CSSValueList::createSpaceSeparated();
1857     if (hangingPunctuation & FirstHangingPunctuation)
1858         list->append(cssValuePool.createIdentifierValue(CSSValueFirst));
1859     if (hangingPunctuation & AllowEndHangingPunctuation)
1860         list->append(cssValuePool.createIdentifierValue(CSSValueAllowEnd));
1861     if (hangingPunctuation & ForceEndHangingPunctuation)
1862         list->append(cssValuePool.createIdentifierValue(CSSValueForceEnd));
1863     if (hangingPunctuation & LastHangingPunctuation)
1864         list->append(cssValuePool.createIdentifierValue(CSSValueLast));
1865     if (!list->length())
1866         return cssValuePool.createIdentifierValue(CSSValueNone);
1867     return WTFMove(list);
1868 }
1869     
1870 static Ref<CSSValue> fillRepeatToCSSValue(EFillRepeat xRepeat, EFillRepeat yRepeat)
1871 {
1872     // For backwards compatibility, if both values are equal, just return one of them. And
1873     // if the two values are equivalent to repeat-x or repeat-y, just return the shorthand.
1874     auto& cssValuePool = CSSValuePool::singleton();
1875     if (xRepeat == yRepeat)
1876         return cssValuePool.createValue(xRepeat);
1877     if (xRepeat == RepeatFill && yRepeat == NoRepeatFill)
1878         return cssValuePool.createIdentifierValue(CSSValueRepeatX);
1879     if (xRepeat == NoRepeatFill && yRepeat == RepeatFill)
1880         return cssValuePool.createIdentifierValue(CSSValueRepeatY);
1881
1882     auto list = CSSValueList::createSpaceSeparated();
1883     list->append(cssValuePool.createValue(xRepeat));
1884     list->append(cssValuePool.createValue(yRepeat));
1885     return WTFMove(list);
1886 }
1887
1888 static Ref<CSSValue> fillSourceTypeToCSSValue(EMaskSourceType type)
1889 {
1890     switch (type) {
1891     case MaskAlpha:
1892         return CSSValuePool::singleton().createValue(CSSValueAlpha);
1893     default:
1894         ASSERT(type == MaskLuminance);
1895         return CSSValuePool::singleton().createValue(CSSValueLuminance);
1896     }
1897 }
1898
1899 static Ref<CSSValue> fillSizeToCSSValue(const FillSize& fillSize, const RenderStyle& style)
1900 {
1901     if (fillSize.type == Contain)
1902         return CSSValuePool::singleton().createIdentifierValue(CSSValueContain);
1903
1904     if (fillSize.type == Cover)
1905         return CSSValuePool::singleton().createIdentifierValue(CSSValueCover);
1906
1907     if (fillSize.size.height.isAuto())
1908         return zoomAdjustedPixelValueForLength(fillSize.size.width, style);
1909
1910     auto list = CSSValueList::createSpaceSeparated();
1911     list->append(zoomAdjustedPixelValueForLength(fillSize.size.width, style));
1912     list->append(zoomAdjustedPixelValueForLength(fillSize.size.height, style));
1913     return WTFMove(list);
1914 }
1915
1916 static Ref<CSSValue> altTextToCSSValue(const RenderStyle& style)
1917 {
1918     return CSSValuePool::singleton().createValue(style.contentAltText(), CSSPrimitiveValue::CSS_STRING);
1919 }
1920     
1921 static Ref<CSSValueList> contentToCSSValue(const RenderStyle& style)
1922 {
1923     auto& cssValuePool = CSSValuePool::singleton();
1924     auto list = CSSValueList::createSpaceSeparated();
1925     for (auto* contentData = style.contentData(); contentData; contentData = contentData->next()) {
1926         if (is<CounterContentData>(*contentData))
1927             list->append(cssValuePool.createValue(downcast<CounterContentData>(*contentData).counter().identifier(), CSSPrimitiveValue::CSS_COUNTER_NAME));
1928         else if (is<ImageContentData>(*contentData))
1929             list->append(downcast<ImageContentData>(*contentData).image().cssValue());
1930         else if (is<TextContentData>(*contentData))
1931             list->append(cssValuePool.createValue(downcast<TextContentData>(*contentData).text(), CSSPrimitiveValue::CSS_STRING));
1932     }
1933     return list;
1934 }
1935
1936 static Ref<CSSValue> counterToCSSValue(const RenderStyle& style, CSSPropertyID propertyID)
1937 {
1938     auto* map = style.counterDirectives();
1939     if (!map)
1940         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1941
1942     auto& cssValuePool = CSSValuePool::singleton();
1943     auto list = CSSValueList::createSpaceSeparated();
1944     for (auto& keyValue : *map) {
1945         list->append(cssValuePool.createValue(keyValue.key, CSSPrimitiveValue::CSS_STRING));
1946         double number = (propertyID == CSSPropertyCounterIncrement ? keyValue.value.incrementValue : keyValue.value.resetValue).value_or(0);
1947         list->append(cssValuePool.createValue(number, CSSPrimitiveValue::CSS_NUMBER));
1948     }
1949     return WTFMove(list);
1950 }
1951
1952 static void logUnimplementedPropertyID(CSSPropertyID propertyID)
1953 {
1954     static NeverDestroyed<HashSet<CSSPropertyID>> propertyIDSet;
1955     if (!propertyIDSet.get().add(propertyID).isNewEntry)
1956         return;
1957
1958     LOG_ERROR("WebKit does not yet implement getComputedStyle for '%s'.", getPropertyName(propertyID));
1959 }
1960
1961 static Ref<CSSValueList> fontFamilyListFromStyle(const RenderStyle& style)
1962 {
1963     auto list = CSSValueList::createCommaSeparated();
1964     for (unsigned i = 0; i < style.fontCascade().familyCount(); ++i)
1965         list->append(valueForFamily(style.fontCascade().familyAt(i)));
1966     return list;
1967 }
1968
1969 static Ref<CSSValue> fontFamilyFromStyle(const RenderStyle& style)
1970 {
1971     if (style.fontCascade().familyCount() == 1)
1972         return valueForFamily(style.fontCascade().familyAt(0));
1973     return fontFamilyListFromStyle(style);
1974 }
1975
1976 static Ref<CSSPrimitiveValue> lineHeightFromStyle(const RenderStyle& style)
1977 {
1978     Length length = style.lineHeight();
1979     if (length.isNegative()) // If true, line-height not set; use the font's line spacing.
1980         return zoomAdjustedPixelValue(style.fontMetrics().floatLineSpacing(), style);
1981     if (length.isPercent()) {
1982         // This is imperfect, because it doesn't include the zoom factor and the real computation
1983         // for how high to be in pixels does include things like minimum font size and the zoom factor.
1984         // On the other hand, since font-size doesn't include the zoom factor, we really can't do
1985         // that here either.
1986         return zoomAdjustedPixelValue(static_cast<int>(length.percent() * style.fontDescription().computedSize()) / 100, style);
1987     }
1988     return zoomAdjustedPixelValue(floatValueForLength(length, 0), style);
1989 }
1990
1991 static Ref<CSSPrimitiveValue> fontSizeFromStyle(const RenderStyle& style)
1992 {
1993     return zoomAdjustedPixelValue(style.fontDescription().computedSize(), style);
1994 }
1995
1996 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontNonKeywordWeightFromStyleValue(FontSelectionValue weight)
1997 {
1998     return CSSValuePool::singleton().createValue(static_cast<float>(weight), CSSPrimitiveValue::CSS_NUMBER);
1999 }
2000
2001 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontWeightFromStyleValue(FontSelectionValue weight)
2002 {
2003     if (auto value = fontWeightKeyword(weight))
2004         return CSSValuePool::singleton().createIdentifierValue(value.value());
2005     return fontNonKeywordWeightFromStyleValue(weight);
2006 }
2007
2008 static Ref<CSSPrimitiveValue> fontWeightFromStyle(const RenderStyle& style)
2009 {
2010     return ComputedStyleExtractor::fontWeightFromStyleValue(style.fontDescription().weight());
2011 }
2012
2013 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontNonKeywordStretchFromStyleValue(FontSelectionValue stretch)
2014 {
2015     return CSSValuePool::singleton().createValue(static_cast<float>(stretch), CSSPrimitiveValue::CSS_PERCENTAGE);
2016 }
2017
2018 Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontStretchFromStyleValue(FontSelectionValue stretch)
2019 {
2020     if (auto keyword = fontStretchKeyword(stretch))
2021         return CSSValuePool::singleton().createIdentifierValue(keyword.value());
2022     return fontNonKeywordStretchFromStyleValue(stretch);
2023 }
2024
2025 static Ref<CSSPrimitiveValue> fontStretchFromStyle(const RenderStyle& style)
2026 {
2027     return ComputedStyleExtractor::fontStretchFromStyleValue(style.fontDescription().stretch());
2028 }
2029
2030 Ref<CSSFontStyleValue> ComputedStyleExtractor::fontNonKeywordStyleFromStyleValue(FontSelectionValue italic)
2031 {
2032     return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(CSSValueOblique), CSSValuePool::singleton().createValue(static_cast<float>(italic), CSSPrimitiveValue::CSS_DEG));
2033 }
2034
2035 Ref<CSSFontStyleValue> ComputedStyleExtractor::fontStyleFromStyleValue(FontSelectionValue italic, FontStyleAxis fontStyleAxis)
2036 {
2037     if (auto keyword = fontStyleKeyword(italic, fontStyleAxis))
2038         return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(keyword.value()));
2039     return fontNonKeywordStyleFromStyleValue(italic);
2040 }
2041
2042 static Ref<CSSFontStyleValue> fontStyleFromStyle(const RenderStyle& style)
2043 {
2044     return ComputedStyleExtractor::fontStyleFromStyleValue(style.fontDescription().italic(), style.fontDescription().fontStyleAxis());
2045 }
2046
2047 static Ref<CSSValue> fontVariantFromStyle(const RenderStyle& style)
2048 {
2049     if (style.fontDescription().variantSettings().isAllNormal())
2050         return CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
2051
2052     auto list = CSSValueList::createSpaceSeparated();
2053
2054     switch (style.fontDescription().variantCommonLigatures()) {
2055     case FontVariantLigatures::Normal:
2056         break;
2057     case FontVariantLigatures::Yes:
2058         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueCommonLigatures));
2059         break;
2060     case FontVariantLigatures::No:
2061         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoCommonLigatures));
2062         break;
2063     }
2064
2065     switch (style.fontDescription().variantDiscretionaryLigatures()) {
2066     case FontVariantLigatures::Normal:
2067         break;
2068     case FontVariantLigatures::Yes:
2069         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiscretionaryLigatures));
2070         break;
2071     case FontVariantLigatures::No:
2072         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoDiscretionaryLigatures));
2073         break;
2074     }
2075
2076     switch (style.fontDescription().variantHistoricalLigatures()) {
2077     case FontVariantLigatures::Normal:
2078         break;
2079     case FontVariantLigatures::Yes:
2080         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalLigatures));
2081         break;
2082     case FontVariantLigatures::No:
2083         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoHistoricalLigatures));
2084         break;
2085     }
2086
2087     switch (style.fontDescription().variantContextualAlternates()) {
2088     case FontVariantLigatures::Normal:
2089         break;
2090     case FontVariantLigatures::Yes:
2091         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueContextual));
2092         break;
2093     case FontVariantLigatures::No:
2094         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoContextual));
2095         break;
2096     }
2097
2098     switch (style.fontDescription().variantPosition()) {
2099     case FontVariantPosition::Normal:
2100         break;
2101     case FontVariantPosition::Subscript:
2102         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSub));
2103         break;
2104     case FontVariantPosition::Superscript:
2105         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSuper));
2106         break;
2107     }
2108
2109     switch (style.fontDescription().variantCaps()) {
2110     case FontVariantCaps::Normal:
2111         break;
2112     case FontVariantCaps::Small:
2113         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
2114         break;
2115     case FontVariantCaps::AllSmall:
2116         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllSmallCaps));
2117         break;
2118     case FontVariantCaps::Petite:
2119         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValuePetiteCaps));
2120         break;
2121     case FontVariantCaps::AllPetite:
2122         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllPetiteCaps));
2123         break;
2124     case FontVariantCaps::Unicase:
2125         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueUnicase));
2126         break;
2127     case FontVariantCaps::Titling:
2128         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTitlingCaps));
2129         break;
2130     }
2131
2132     switch (style.fontDescription().variantNumericFigure()) {
2133     case FontVariantNumericFigure::Normal:
2134         break;
2135     case FontVariantNumericFigure::LiningNumbers:
2136         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueLiningNums));
2137         break;
2138     case FontVariantNumericFigure::OldStyleNumbers:
2139         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueOldstyleNums));
2140         break;
2141     }
2142
2143     switch (style.fontDescription().variantNumericSpacing()) {
2144     case FontVariantNumericSpacing::Normal:
2145         break;
2146     case FontVariantNumericSpacing::ProportionalNumbers:
2147         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalNums));
2148         break;
2149     case FontVariantNumericSpacing::TabularNumbers:
2150         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTabularNums));
2151         break;
2152     }
2153
2154     switch (style.fontDescription().variantNumericFraction()) {
2155     case FontVariantNumericFraction::Normal:
2156         break;
2157     case FontVariantNumericFraction::DiagonalFractions:
2158         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiagonalFractions));
2159         break;
2160     case FontVariantNumericFraction::StackedFractions:
2161         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStackedFractions));
2162         break;
2163     }
2164
2165     switch (style.fontDescription().variantNumericOrdinal()) {
2166     case FontVariantNumericOrdinal::Normal:
2167         break;
2168     case FontVariantNumericOrdinal::Yes:
2169         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueOrdinal));
2170         break;
2171     }
2172
2173     switch (style.fontDescription().variantNumericSlashedZero()) {
2174     case FontVariantNumericSlashedZero::Normal:
2175         break;
2176     case FontVariantNumericSlashedZero::Yes:
2177         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSlashedZero));
2178         break;
2179     }
2180
2181     switch (style.fontDescription().variantAlternates()) {
2182     case FontVariantAlternates::Normal:
2183         break;
2184     case FontVariantAlternates::HistoricalForms:
2185         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalForms));
2186         break;
2187     }
2188
2189     switch (style.fontDescription().variantEastAsianVariant()) {
2190     case FontVariantEastAsianVariant::Normal:
2191         break;
2192     case FontVariantEastAsianVariant::Jis78:
2193         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis78));
2194         break;
2195     case FontVariantEastAsianVariant::Jis83:
2196         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis83));
2197         break;
2198     case FontVariantEastAsianVariant::Jis90:
2199         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis90));
2200         break;
2201     case FontVariantEastAsianVariant::Jis04:
2202         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis04));
2203         break;
2204     case FontVariantEastAsianVariant::Simplified:
2205         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSimplified));
2206         break;
2207     case FontVariantEastAsianVariant::Traditional:
2208         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTraditional));
2209         break;
2210     }
2211
2212     switch (style.fontDescription().variantEastAsianWidth()) {
2213     case FontVariantEastAsianWidth::Normal:
2214         break;
2215     case FontVariantEastAsianWidth::Full:
2216         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueFullWidth));
2217         break;
2218     case FontVariantEastAsianWidth::Proportional:
2219         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalWidth));
2220         break;
2221     }
2222
2223     switch (style.fontDescription().variantEastAsianRuby()) {
2224     case FontVariantEastAsianRuby::Normal:
2225         break;
2226     case FontVariantEastAsianRuby::Yes:
2227         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueRuby));
2228         break;
2229     }
2230
2231     return WTFMove(list);
2232 }
2233
2234 static Ref<CSSValue> fontSynthesisFromStyle(const RenderStyle& style)
2235 {
2236     if (style.fontDescription().fontSynthesis() == FontSynthesisNone)
2237         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2238
2239     auto list = CSSValueList::createSpaceSeparated();
2240     if (style.fontDescription().fontSynthesis() & FontSynthesisStyle)
2241         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStyle));
2242     if (style.fontDescription().fontSynthesis() & FontSynthesisWeight)
2243         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueWeight));
2244     if (style.fontDescription().fontSynthesis() & FontSynthesisSmallCaps)
2245         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
2246     return WTFMove(list);
2247 }
2248
2249 typedef const Length& (RenderStyle::*RenderStyleLengthGetter)() const;
2250 typedef LayoutUnit (RenderBoxModelObject::*RenderBoxComputedCSSValueGetter)() const;
2251
2252 template<RenderStyleLengthGetter lengthGetter, RenderBoxComputedCSSValueGetter computedCSSValueGetter>
2253 static RefPtr<CSSValue> zoomAdjustedPaddingOrMarginPixelValue(const RenderStyle& style, RenderObject* renderer)
2254 {
2255     Length unzoomzedLength = (style.*lengthGetter)();
2256     if (!is<RenderBox>(renderer) || unzoomzedLength.isFixed())
2257         return zoomAdjustedPixelValueForLength(unzoomzedLength, style);
2258     return zoomAdjustedPixelValue((downcast<RenderBox>(*renderer).*computedCSSValueGetter)(), style);
2259 }
2260
2261 template<RenderStyleLengthGetter lengthGetter>
2262 static bool paddingOrMarginIsRendererDependent(const RenderStyle* style, RenderObject* renderer)
2263 {
2264     return renderer && style && renderer->isBox() && !(style->*lengthGetter)().isFixed();
2265 }
2266
2267 static bool positionOffsetValueIsRendererDependent(const RenderStyle* style, RenderObject* renderer)
2268 {
2269     return renderer && style && renderer->isBox();
2270 }
2271
2272 static CSSValueID convertToPageBreak(BreakBetween value)
2273 {
2274     if (value == PageBreakBetween || value == LeftPageBreakBetween || value == RightPageBreakBetween
2275         || value == RectoPageBreakBetween || value == VersoPageBreakBetween)
2276         return CSSValueAlways; // CSS 2.1 allows us to map these to always.
2277     if (value == AvoidBreakBetween || value == AvoidPageBreakBetween)
2278         return CSSValueAvoid;
2279     return CSSValueAuto;
2280 }
2281
2282 static CSSValueID convertToColumnBreak(BreakBetween value)
2283 {
2284     if (value == ColumnBreakBetween)
2285         return CSSValueAlways;
2286     if (value == AvoidBreakBetween || value == AvoidColumnBreakBetween)
2287         return CSSValueAvoid;
2288     return CSSValueAuto;
2289 }
2290
2291 static CSSValueID convertToPageBreak(BreakInside value)
2292 {
2293     if (value == AvoidBreakInside || value == AvoidPageBreakInside)
2294         return CSSValueAvoid;
2295     return CSSValueAuto;
2296 }
2297
2298 static CSSValueID convertToColumnBreak(BreakInside value)
2299 {
2300     if (value == AvoidBreakInside || value == AvoidColumnBreakInside)
2301         return CSSValueAvoid;
2302     return CSSValueAuto;
2303 }
2304
2305 static inline bool isNonReplacedInline(RenderObject& renderer)
2306 {
2307     return renderer.isInline() && !renderer.isReplaced();
2308 }
2309
2310 static bool isLayoutDependent(CSSPropertyID propertyID, const RenderStyle* style, RenderObject* renderer)
2311 {
2312     switch (propertyID) {
2313     case CSSPropertyTop:
2314     case CSSPropertyBottom:
2315     case CSSPropertyLeft:
2316     case CSSPropertyRight:
2317         return positionOffsetValueIsRendererDependent(style, renderer);
2318     case CSSPropertyWidth:
2319     case CSSPropertyHeight:
2320         return renderer && !renderer->isRenderSVGModelObject() && !isNonReplacedInline(*renderer);
2321     case CSSPropertyPerspectiveOrigin:
2322     case CSSPropertyTransformOrigin:
2323     case CSSPropertyTransform:
2324     case CSSPropertyFilter: // Why are filters layout-dependent?
2325 #if ENABLE(FILTERS_LEVEL_2)
2326     case CSSPropertyWebkitBackdropFilter: // Ditto for backdrop-filter.
2327 #endif
2328         return true;
2329     case CSSPropertyMargin: {
2330         if (!renderer || !renderer->isBox())
2331             return false;
2332         return !(style && style->marginTop().isFixed() && style->marginRight().isFixed()
2333             && style->marginBottom().isFixed() && style->marginLeft().isFixed());
2334     }
2335     case CSSPropertyMarginTop:
2336         return paddingOrMarginIsRendererDependent<&RenderStyle::marginTop>(style, renderer);
2337     case CSSPropertyMarginRight:
2338         return paddingOrMarginIsRendererDependent<&RenderStyle::marginRight>(style, renderer);
2339     case CSSPropertyMarginBottom:
2340         return paddingOrMarginIsRendererDependent<&RenderStyle::marginBottom>(style, renderer);
2341     case CSSPropertyMarginLeft:
2342         return paddingOrMarginIsRendererDependent<&RenderStyle::marginLeft>(style, renderer);
2343     case CSSPropertyPadding: {
2344         if (!renderer || !renderer->isBox())
2345             return false;
2346         return !(style && style->paddingTop().isFixed() && style->paddingRight().isFixed()
2347             && style->paddingBottom().isFixed() && style->paddingLeft().isFixed());
2348     }
2349     case CSSPropertyPaddingTop:
2350         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingTop>(style, renderer);
2351     case CSSPropertyPaddingRight:
2352         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingRight>(style, renderer);
2353     case CSSPropertyPaddingBottom:
2354         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingBottom>(style, renderer);
2355     case CSSPropertyPaddingLeft:
2356         return paddingOrMarginIsRendererDependent<&RenderStyle::paddingLeft>(style, renderer); 
2357     case CSSPropertyGridTemplateColumns:
2358     case CSSPropertyGridTemplateRows:
2359     case CSSPropertyGridTemplate:
2360     case CSSPropertyGrid:
2361         return renderer && renderer->isRenderGrid();
2362     default:
2363         return false;
2364     }
2365 }
2366
2367 Element* ComputedStyleExtractor::styledElement() const
2368 {
2369     if (!m_element)
2370         return nullptr;
2371     PseudoElement* pseudoElement;
2372     if (m_pseudoElementSpecifier == BEFORE && (pseudoElement = m_element->beforePseudoElement()))
2373         return pseudoElement;
2374     if (m_pseudoElementSpecifier == AFTER && (pseudoElement = m_element->afterPseudoElement()))
2375         return pseudoElement;
2376     return m_element.get();
2377 }
2378
2379
2380 RenderElement* ComputedStyleExtractor::styledRenderer() const
2381 {
2382     auto* element = styledElement();
2383     if (!element)
2384         return nullptr;
2385     if (m_pseudoElementSpecifier != NOPSEUDO && element == m_element.get())
2386         return nullptr;
2387     if (element->hasDisplayContents())
2388         return nullptr;
2389     return element->renderer();
2390 }
2391
2392 static bool isImplicitlyInheritedGridOrFlexProperty(CSSPropertyID propertyID)
2393 {
2394     // It would be nice if grid and flex worked within normal CSS mechanisms and not invented their own inheritance system.
2395     switch (propertyID) {
2396     case CSSPropertyAlignSelf:
2397     case CSSPropertyJustifySelf:
2398     case CSSPropertyJustifyItems:
2399     // FIXME: In StyleResolver::adjustRenderStyle z-index is adjusted based on the parent display property for grid/flex.
2400     case CSSPropertyZIndex:
2401         return true;
2402     default:
2403         return false;
2404     }
2405 }
2406
2407 // In CSS 2.1 the returned object should actually contain the "used values"
2408 // rather then the "computed values" (despite the name saying otherwise).
2409 //
2410 // See;
2411 // http://www.w3.org/TR/CSS21/cascade.html#used-value
2412 // http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration
2413 // https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle#Notes
2414 RefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const
2415 {
2416     return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).propertyValue(propertyID, updateLayout);
2417 }
2418
2419 Ref<MutableStyleProperties> CSSComputedStyleDeclaration::copyProperties() const
2420 {
2421     return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).copyProperties();
2422 }
2423
2424 static inline bool hasValidStyleForProperty(Element& element, CSSPropertyID propertyID)
2425 {
2426     if (element.styleValidity() != Style::Validity::Valid)
2427         return false;
2428     if (element.document().hasPendingForcedStyleRecalc())
2429         return false;
2430     if (!element.document().childNeedsStyleRecalc())
2431         return true;
2432
2433     bool isInherited = CSSProperty::isInheritedProperty(propertyID) || isImplicitlyInheritedGridOrFlexProperty(propertyID);
2434     bool maybeExplicitlyInherited = !isInherited;
2435
2436     const auto* currentElement = &element;
2437     for (auto& ancestor : composedTreeAncestors(element)) {
2438         if (ancestor.styleValidity() >= Style::Validity::SubtreeInvalid)
2439             return false;
2440
2441         if (maybeExplicitlyInherited) {
2442             auto* style = currentElement->renderStyle();
2443             maybeExplicitlyInherited = !style || style->hasExplicitlyInheritedProperties();
2444         }
2445
2446         if ((isInherited || maybeExplicitlyInherited) && ancestor.styleValidity() == Style::Validity::ElementInvalid)
2447             return false;
2448
2449         if (ancestor.directChildNeedsStyleRecalc() && currentElement->styleIsAffectedByPreviousSibling())
2450             return false;
2451
2452         currentElement = &ancestor;
2453     }
2454
2455     return true;
2456 }
2457
2458 static bool updateStyleIfNeededForProperty(Element& element, CSSPropertyID propertyID)
2459 {
2460     auto& document = element.document();
2461
2462     document.styleScope().flushPendingUpdate();
2463
2464     if (hasValidStyleForProperty(element, propertyID))
2465         return false;
2466
2467     document.updateStyleIfNeeded();
2468     return true;
2469 }
2470
2471 static inline const RenderStyle* computeRenderStyleForProperty(Element& element, PseudoId pseudoElementSpecifier, CSSPropertyID propertyID, std::unique_ptr<RenderStyle>& ownedStyle)
2472 {
2473     auto* renderer = element.renderer();
2474
2475     if (renderer && renderer->isComposited() && CSSAnimationController::supportsAcceleratedAnimationOfProperty(propertyID)) {
2476         if (auto timeline = element.document().existingTimeline())
2477             ownedStyle = timeline->animatedStyleForRenderer(*renderer);
2478         else
2479             ownedStyle = renderer->animation().animatedStyleForRenderer(*renderer);
2480         if (pseudoElementSpecifier && !element.isPseudoElement()) {
2481             // FIXME: This cached pseudo style will only exist if the animation has been run at least once.
2482             return ownedStyle->getCachedPseudoStyle(pseudoElementSpecifier);
2483         }
2484         return ownedStyle.get();
2485     }
2486
2487     return element.computedStyle(element.isPseudoElement() ? NOPSEUDO : pseudoElementSpecifier);
2488 }
2489
2490 static Ref<CSSValue> shapePropertyValue(const RenderStyle& style, const ShapeValue* shapeValue)
2491 {
2492     if (!shapeValue)
2493         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2494
2495     if (shapeValue->type() == ShapeValue::Type::Box)
2496         return CSSValuePool::singleton().createValue(shapeValue->cssBox());
2497
2498     if (shapeValue->type() == ShapeValue::Type::Image) {
2499         if (shapeValue->image())
2500             return shapeValue->image()->cssValue();
2501         return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2502     }
2503
2504     ASSERT(shapeValue->type() == ShapeValue::Type::Shape);
2505
2506     auto list = CSSValueList::createSpaceSeparated();
2507     list->append(valueForBasicShape(style, *shapeValue->shape()));
2508     if (shapeValue->cssBox() != BoxMissing)
2509         list->append(CSSValuePool::singleton().createValue(shapeValue->cssBox()));
2510     return WTFMove(list);
2511 }
2512
2513 static Ref<CSSValueList> valueForItemPositionWithOverflowAlignment(const StyleSelfAlignmentData& data)
2514 {
2515     auto& cssValuePool = CSSValuePool::singleton();
2516     auto result = CSSValueList::createSpaceSeparated();
2517     if (data.positionType() == LegacyPosition)
2518         result->append(cssValuePool.createIdentifierValue(CSSValueLegacy));
2519     if (data.position() == ItemPositionBaseline)
2520         result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2521     else if (data.position() == ItemPositionLastBaseline) {
2522         result->append(cssValuePool.createIdentifierValue(CSSValueLast));
2523         result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2524     } else {
2525         if (data.position() >= ItemPositionCenter && data.overflow() != OverflowAlignmentDefault)
2526             result->append(cssValuePool.createValue(data.overflow()));
2527         if (data.position() == ItemPositionLegacy)
2528             result->append(cssValuePool.createIdentifierValue(CSSValueNormal));
2529         else
2530             result->append(cssValuePool.createValue(data.position()));
2531     }
2532     ASSERT(result->length() <= 2);
2533     return result;
2534 }
2535
2536 static Ref<CSSValueList> valueForContentPositionAndDistributionWithOverflowAlignment(const StyleContentAlignmentData& data)
2537 {
2538     auto& cssValuePool = CSSValuePool::singleton();
2539     auto result = CSSValueList::createSpaceSeparated();
2540     // Handle content-distribution values
2541     if (data.distribution() != ContentDistributionDefault)
2542         result->append(cssValuePool.createValue(data.distribution()));
2543
2544     // Handle content-position values (either as fallback or actual value)
2545     switch (data.position()) {
2546     case ContentPositionNormal:
2547         // Handle 'normal' value, not valid as content-distribution fallback.
2548         if (data.distribution() == ContentDistributionDefault)
2549             result->append(cssValuePool.createIdentifierValue(CSSValueNormal));
2550         break;
2551     case ContentPositionLastBaseline:
2552         result->append(cssValuePool.createIdentifierValue(CSSValueLast));
2553         result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2554         break;
2555     default:
2556         // Handle overflow-alignment (only allowed for content-position values)
2557         if ((data.position() >= ContentPositionCenter || data.distribution() != ContentDistributionDefault) && data.overflow() != OverflowAlignmentDefault)
2558             result->append(cssValuePool.createValue(data.overflow()));
2559         result->append(cssValuePool.createValue(data.position()));
2560     }
2561
2562     ASSERT(result->length() > 0);
2563     ASSERT(result->length() <= 3);
2564     return result;
2565 }
2566
2567 static Ref<CSSValue> paintOrder(PaintOrder paintOrder)
2568 {
2569     if (paintOrder == PaintOrder::Normal)
2570         return CSSPrimitiveValue::createIdentifier(CSSValueNormal);
2571     
2572     auto paintOrderList = CSSValueList::createSpaceSeparated();
2573     switch (paintOrder) {
2574     case PaintOrder::Normal:
2575         ASSERT_NOT_REACHED();
2576         break;
2577     case PaintOrder::Fill:
2578         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueFill));
2579         break;
2580     case PaintOrder::FillMarkers:
2581         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueFill));
2582         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2583         break;
2584     case PaintOrder::Stroke:
2585         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2586         break;
2587     case PaintOrder::StrokeMarkers:
2588         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2589         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2590         break;
2591     case PaintOrder::Markers:
2592         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2593         break;
2594     case PaintOrder::MarkersStroke:
2595         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2596         paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2597         break;
2598     }
2599     return WTFMove(paintOrderList);
2600 }
2601
2602 inline static bool isFlexOrGrid(ContainerNode* element)
2603 {
2604     return element && element->computedStyle() && element->computedStyle()->isDisplayFlexibleOrGridBox();
2605 }
2606
2607 RefPtr<CSSValue> ComputedStyleExtractor::customPropertyValue(const String& propertyName)
2608 {
2609     Element* styledElement = this->styledElement();
2610     if (!styledElement)
2611         return nullptr;
2612     
2613     if (updateStyleIfNeededForProperty(*styledElement, CSSPropertyCustom)) {
2614         // Style update may change styledElement() to PseudoElement or back.
2615         styledElement = this->styledElement();
2616     }
2617
2618     std::unique_ptr<RenderStyle> ownedStyle;
2619     auto* style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, CSSPropertyCustom, ownedStyle);
2620     if (!style)
2621         return nullptr;
2622
2623     return style->customProperties().get(propertyName);
2624 }
2625
2626 String ComputedStyleExtractor::customPropertyText(const String& propertyName)
2627 {
2628     RefPtr<CSSValue> propertyValue = customPropertyValue(propertyName);
2629     return propertyValue ? propertyValue->cssText() : emptyString();
2630 }
2631
2632 static Ref<CSSFontValue> fontShorthandValueForSelectionProperties(const FontDescription& fontDescription)
2633 {
2634     auto computedFont = CSSFontValue::create();
2635
2636     auto variantCaps = fontDescription.variantCaps();
2637     if (variantCaps == FontVariantCaps::Small)
2638         computedFont->variant = CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps);
2639     else if (variantCaps == FontVariantCaps::Normal)
2640         computedFont->variant = CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
2641     else
2642         return CSSFontValue::create();
2643
2644     auto weight = fontDescription.weight();
2645     if (auto value = fontWeightKeyword(weight))
2646         computedFont->weight = CSSValuePool::singleton().createIdentifierValue(value.value());
2647     else if (isCSS21Weight(weight))
2648         computedFont->weight = CSSValuePool::singleton().createValue(static_cast<float>(weight), CSSPrimitiveValue::CSS_NUMBER);
2649     else
2650         return CSSFontValue::create();
2651
2652     if (auto keyword = fontStretchKeyword(fontDescription.stretch()))
2653         computedFont->stretch = CSSValuePool::singleton().createIdentifierValue(keyword.value());
2654     else
2655         return CSSFontValue::create();
2656
2657     if (auto italic = fontStyleKeyword(fontDescription.italic(), fontDescription.fontStyleAxis()))
2658         computedFont->style = CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(italic.value()));
2659     else
2660         return CSSFontValue::create();
2661
2662     return computedFont;
2663 }
2664
2665 RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID, EUpdateLayout updateLayout)
2666 {
2667     auto* styledElement = this->styledElement();
2668     if (!styledElement)
2669         return nullptr;
2670
2671     std::unique_ptr<RenderStyle> ownedStyle;
2672     const RenderStyle* style = nullptr;
2673     RenderElement* renderer = nullptr;
2674     bool forceFullLayout = false;
2675     if (updateLayout) {
2676         Document& document = m_element->document();
2677
2678         if (updateStyleIfNeededForProperty(*styledElement, propertyID)) {
2679             // Style update may change styledElement() to PseudoElement or back.
2680             styledElement = this->styledElement();
2681         }
2682         renderer = styledRenderer();
2683
2684         if (propertyID == CSSPropertyDisplay && !renderer && is<SVGElement>(*styledElement) && !downcast<SVGElement>(*styledElement).isValid())
2685             return nullptr;
2686
2687         style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, propertyID, ownedStyle);
2688
2689         // FIXME: Some of these cases could be narrowed down or optimized better.
2690         forceFullLayout = isLayoutDependent(propertyID, style, renderer)
2691             || styledElement->isInShadowTree()
2692             || (document.styleScope().resolverIfExists() && document.styleScope().resolverIfExists()->hasViewportDependentMediaQueries() && document.ownerElement());
2693
2694         if (forceFullLayout) {
2695             document.updateLayoutIgnorePendingStylesheets();
2696             styledElement = this->styledElement();
2697         }
2698     }
2699
2700     if (!updateLayout || forceFullLayout) {
2701         style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, propertyID, ownedStyle);
2702         renderer = styledRenderer();
2703     }
2704
2705     if (!style)
2706         return nullptr;
2707
2708     return valueForPropertyinStyle(*style, propertyID, renderer);
2709 }
2710
2711 RefPtr<CSSValue> ComputedStyleExtractor::valueForPropertyinStyle(const RenderStyle& style, CSSPropertyID propertyID, RenderElement* renderer)
2712 {
2713     auto& cssValuePool = CSSValuePool::singleton();
2714     propertyID = CSSProperty::resolveDirectionAwareProperty(propertyID, style.direction(), style.writingMode());
2715
2716     switch (propertyID) {
2717         case CSSPropertyInvalid:
2718             break;
2719
2720         case CSSPropertyBackgroundColor:
2721             return cssValuePool.createColorValue(m_allowVisitedStyle? style.visitedDependentColor(CSSPropertyBackgroundColor) : style.backgroundColor());
2722         case CSSPropertyBackgroundImage:
2723         case CSSPropertyWebkitMaskImage: {
2724             auto& layers = propertyID == CSSPropertyWebkitMaskImage ? style.maskLayers() : style.backgroundLayers();
2725             if (!layers.next()) {
2726                 if (layers.image())
2727                     return layers.image()->cssValue();
2728                 return cssValuePool.createIdentifierValue(CSSValueNone);
2729             }
2730             auto list = CSSValueList::createCommaSeparated();
2731             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next()) {
2732                 if (currLayer->image())
2733                     list->append(currLayer->image()->cssValue());
2734                 else
2735                     list->append(cssValuePool.createIdentifierValue(CSSValueNone));
2736             }
2737             return WTFMove(list);
2738         }
2739         case CSSPropertyBackgroundSize:
2740         case CSSPropertyWebkitBackgroundSize:
2741         case CSSPropertyWebkitMaskSize: {
2742             auto& layers = propertyID == CSSPropertyWebkitMaskSize ? style.maskLayers() : style.backgroundLayers();
2743             if (!layers.next())
2744                 return fillSizeToCSSValue(layers.size(), style);
2745             auto list = CSSValueList::createCommaSeparated();
2746             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2747                 list->append(fillSizeToCSSValue(currLayer->size(), style));
2748             return WTFMove(list);
2749         }
2750         case CSSPropertyBackgroundRepeat:
2751         case CSSPropertyWebkitMaskRepeat: {
2752             auto& layers = propertyID == CSSPropertyWebkitMaskRepeat ? style.maskLayers() : style.backgroundLayers();
2753             if (!layers.next())
2754                 return fillRepeatToCSSValue(layers.repeatX(), layers.repeatY());
2755             auto list = CSSValueList::createCommaSeparated();
2756             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2757                 list->append(fillRepeatToCSSValue(currLayer->repeatX(), currLayer->repeatY()));
2758             return WTFMove(list);
2759         }
2760         case CSSPropertyWebkitMaskSourceType: {
2761             auto& layers = style.maskLayers();
2762             if (!layers.next())
2763                 return fillSourceTypeToCSSValue(layers.maskSourceType());
2764             auto list = CSSValueList::createCommaSeparated();
2765             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2766                 list->append(fillSourceTypeToCSSValue(currLayer->maskSourceType()));
2767             return WTFMove(list);
2768         }
2769         case CSSPropertyWebkitBackgroundComposite:
2770         case CSSPropertyWebkitMaskComposite: {
2771             auto& layers = propertyID == CSSPropertyWebkitMaskComposite ? style.maskLayers() : style.backgroundLayers();
2772             if (!layers.next())
2773                 return cssValuePool.createValue(layers.composite());
2774             auto list = CSSValueList::createCommaSeparated();
2775             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2776                 list->append(cssValuePool.createValue(currLayer->composite()));
2777             return WTFMove(list);
2778         }
2779         case CSSPropertyBackgroundAttachment: {
2780             auto& layers = style.backgroundLayers();
2781             if (!layers.next())
2782                 return cssValuePool.createValue(layers.attachment());
2783             auto list = CSSValueList::createCommaSeparated();
2784             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2785                 list->append(cssValuePool.createValue(currLayer->attachment()));
2786             return WTFMove(list);
2787         }
2788         case CSSPropertyBackgroundClip:
2789         case CSSPropertyBackgroundOrigin:
2790         case CSSPropertyWebkitBackgroundClip:
2791         case CSSPropertyWebkitBackgroundOrigin:
2792         case CSSPropertyWebkitMaskClip:
2793         case CSSPropertyWebkitMaskOrigin: {
2794             auto& layers = (propertyID == CSSPropertyWebkitMaskClip || propertyID == CSSPropertyWebkitMaskOrigin) ? style.maskLayers() : style.backgroundLayers();
2795             bool isClip = propertyID == CSSPropertyBackgroundClip || propertyID == CSSPropertyWebkitBackgroundClip || propertyID == CSSPropertyWebkitMaskClip;
2796             if (!layers.next())
2797                 return cssValuePool.createValue(isClip ? layers.clip() : layers.origin());
2798             auto list = CSSValueList::createCommaSeparated();
2799             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2800                 list->append(cssValuePool.createValue(isClip ? currLayer->clip() : currLayer->origin()));
2801             return WTFMove(list);
2802         }
2803         case CSSPropertyBackgroundPosition:
2804         case CSSPropertyWebkitMaskPosition: {
2805             auto& layers = propertyID == CSSPropertyWebkitMaskPosition ? style.maskLayers() : style.backgroundLayers();
2806             if (!layers.next())
2807                 return createPositionListForLayer(propertyID, layers, style);
2808
2809             auto list = CSSValueList::createCommaSeparated();
2810             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2811                 list->append(createPositionListForLayer(propertyID, *currLayer, style));
2812             return WTFMove(list);
2813         }
2814         case CSSPropertyBackgroundPositionX:
2815         case CSSPropertyWebkitMaskPositionX: {
2816             auto& layers = propertyID == CSSPropertyWebkitMaskPositionX ? style.maskLayers() : style.backgroundLayers();
2817             if (!layers.next())
2818                 return cssValuePool.createValue(layers.xPosition());
2819
2820             auto list = CSSValueList::createCommaSeparated();
2821             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2822                 list->append(cssValuePool.createValue(currLayer->xPosition()));
2823
2824             return WTFMove(list);
2825         }
2826         case CSSPropertyBackgroundPositionY:
2827         case CSSPropertyWebkitMaskPositionY: {
2828             auto& layers = propertyID == CSSPropertyWebkitMaskPositionY ? style.maskLayers() : style.backgroundLayers();
2829             if (!layers.next())
2830                 return cssValuePool.createValue(layers.yPosition());
2831
2832             auto list = CSSValueList::createCommaSeparated();
2833             for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2834                 list->append(cssValuePool.createValue(currLayer->yPosition()));
2835
2836             return WTFMove(list);
2837         }
2838         case CSSPropertyBorderCollapse:
2839             if (style.borderCollapse())
2840                 return cssValuePool.createIdentifierValue(CSSValueCollapse);
2841             return cssValuePool.createIdentifierValue(CSSValueSeparate);
2842         case CSSPropertyBorderSpacing: {
2843             auto list = CSSValueList::createSpaceSeparated();
2844             list->append(zoomAdjustedPixelValue(style.horizontalBorderSpacing(), style));
2845             list->append(zoomAdjustedPixelValue(style.verticalBorderSpacing(), style));
2846             return WTFMove(list);
2847         }
2848         case CSSPropertyWebkitBorderHorizontalSpacing:
2849             return zoomAdjustedPixelValue(style.horizontalBorderSpacing(), style);
2850         case CSSPropertyWebkitBorderVerticalSpacing:
2851             return zoomAdjustedPixelValue(style.verticalBorderSpacing(), style);
2852         case CSSPropertyBorderImageSource:
2853             if (style.borderImageSource())
2854                 return style.borderImageSource()->cssValue();
2855             return cssValuePool.createIdentifierValue(CSSValueNone);
2856         case CSSPropertyBorderTopColor:
2857             return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderTopColor)) : currentColorOrValidColor(&style, style.borderTopColor());
2858         case CSSPropertyBorderRightColor:
2859             return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderRightColor)) : currentColorOrValidColor(&style, style.borderRightColor());
2860         case CSSPropertyBorderBottomColor:
2861             return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderBottomColor)) : currentColorOrValidColor(&style, style.borderBottomColor());
2862         case CSSPropertyBorderLeftColor:
2863             return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderLeftColor)) : currentColorOrValidColor(&style, style.borderLeftColor());
2864         case CSSPropertyBorderTopStyle:
2865             return cssValuePool.createValue(style.borderTopStyle());
2866         case CSSPropertyBorderRightStyle:
2867             return cssValuePool.createValue(style.borderRightStyle());
2868         case CSSPropertyBorderBottomStyle:
2869             return cssValuePool.createValue(style.borderBottomStyle());
2870         case CSSPropertyBorderLeftStyle:
2871             return cssValuePool.createValue(style.borderLeftStyle());
2872         case CSSPropertyBorderTopWidth:
2873             return zoomAdjustedPixelValue(style.borderTopWidth(), style);
2874         case CSSPropertyBorderRightWidth:
2875             return zoomAdjustedPixelValue(style.borderRightWidth(), style);
2876         case CSSPropertyBorderBottomWidth:
2877             return zoomAdjustedPixelValue(style.borderBottomWidth(), style);
2878         case CSSPropertyBorderLeftWidth:
2879             return zoomAdjustedPixelValue(style.borderLeftWidth(), style);
2880         case CSSPropertyBottom:
2881             return positionOffsetValue(style, CSSPropertyBottom, renderer);
2882         case CSSPropertyWebkitBoxAlign:
2883             return cssValuePool.createValue(style.boxAlign());
2884 #if ENABLE(CSS_BOX_DECORATION_BREAK)
2885         case CSSPropertyWebkitBoxDecorationBreak:
2886             if (style.boxDecorationBreak() == DSLICE)
2887                 return cssValuePool.createIdentifierValue(CSSValueSlice);
2888         return cssValuePool.createIdentifierValue(CSSValueClone);
2889 #endif
2890         case CSSPropertyWebkitBoxDirection:
2891             return cssValuePool.createValue(style.boxDirection());
2892         case CSSPropertyWebkitBoxFlex:
2893             return cssValuePool.createValue(style.boxFlex(), CSSPrimitiveValue::CSS_NUMBER);
2894         case CSSPropertyWebkitBoxFlexGroup:
2895             return cssValuePool.createValue(style.boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER);
2896         case CSSPropertyWebkitBoxLines:
2897             return cssValuePool.createValue(style.boxLines());
2898         case CSSPropertyWebkitBoxOrdinalGroup:
2899             return cssValuePool.createValue(style.boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER);
2900         case CSSPropertyWebkitBoxOrient:
2901             return cssValuePool.createValue(style.boxOrient());
2902         case CSSPropertyWebkitBoxPack:
2903             return cssValuePool.createValue(style.boxPack());
2904         case CSSPropertyWebkitBoxReflect:
2905             return valueForReflection(style.boxReflect(), style);
2906         case CSSPropertyBoxShadow:
2907         case CSSPropertyWebkitBoxShadow:
2908             return valueForShadow(style.boxShadow(), propertyID, style);
2909         case CSSPropertyCaptionSide:
2910             return cssValuePool.createValue(style.captionSide());
2911         case CSSPropertyCaretColor:
2912             return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyCaretColor)) : currentColorOrValidColor(&style, style.caretColor());
2913         case CSSPropertyClear:
2914             return cssValuePool.createValue(style.clear());
2915         case CSSPropertyColor:
2916             return cssValuePool.createColorValue(m_allowVisitedStyle ? style.visitedDependentColor(CSSPropertyColor) : style.color());
2917         case CSSPropertyWebkitPrintColorAdjust:
2918             return cssValuePool.createValue(style.printColorAdjust());
2919         case CSSPropertyWebkitColumnAxis:
2920             return cssValuePool.createValue(style.columnAxis());
2921         case CSSPropertyColumnCount:
2922             if (style.hasAutoColumnCount())
2923                 return cssValuePool.createIdentifierValue(CSSValueAuto);
2924             return cssValuePool.createValue(style.columnCount(), CSSPrimitiveValue::CSS_NUMBER);
2925         case CSSPropertyColumnFill:
2926             return cssValuePool.createValue(style.columnFill());
2927         case CSSPropertyColumnGap:
2928             if (style.columnGap().isNormal())
2929                 return cssValuePool.createIdentifierValue(CSSValueNormal);
2930             return zoomAdjustedPixelValueForLength(style.columnGap().length(), style);
2931         case CSSPropertyRowGap:
2932             if (style.rowGap().isNormal())
2933                 return cssValuePool.createIdentifierValue(CSSValueNormal);
2934             return zoomAdjustedPixelValueForLength(style.rowGap().length(), style);
2935         case CSSPropertyWebkitColumnProgression:
2936             return cssValuePool.createValue(style.columnProgression());
2937         case CSSPropertyColumnRuleColor:
2938             return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyOutlineColor)) : currentColorOrValidColor(&style, style.columnRuleColor());
2939         case CSSPropertyColumnRuleStyle:
2940             return cssValuePool.createValue(style.columnRuleStyle());
2941         case CSSPropertyColumnRuleWidth:
2942             return zoomAdjustedPixelValue(style.columnRuleWidth(), style);
2943         case CSSPropertyColumnSpan:
2944             return cssValuePool.createIdentifierValue(style.columnSpan() ? CSSValueAll : CSSValueNone);
2945         case CSSPropertyWebkitColumnBreakAfter:
2946             return cssValuePool.createValue(convertToColumnBreak(style.breakAfter()));
2947         case CSSPropertyWebkitColumnBreakBefore:
2948             return cssValuePool.createValue(convertToColumnBreak(style.breakBefore()));
2949         case CSSPropertyWebkitColumnBreakInside:
2950             return cssValuePool.createValue(convertToColumnBreak(style.breakInside()));
2951         case CSSPropertyColumnWidth:
2952             if (style.hasAutoColumnWidth())
2953                 return cssValuePool.createIdentifierValue(CSSValueAuto);
2954             return zoomAdjustedPixelValue(style.columnWidth(), style);
2955         case CSSPropertyTabSize:
2956             return cssValuePool.createValue(style.tabSize(), CSSPrimitiveValue::CSS_NUMBER);
2957         case CSSPropertyCursor: {
2958             RefPtr<CSSValueList> list;
2959             auto* cursors = style.cursors();
2960             if (cursors && cursors->size() > 0) {
2961                 list = CSSValueList::createCommaSeparated();
2962                 for (unsigned i = 0; i < cursors->size(); ++i)
2963                     if (StyleImage* image = cursors->at(i).image())
2964                         list->append(image->cssValue());
2965             }
2966             auto value = cssValuePool.createValue(style.cursor());
2967             if (list) {
2968                 list->append(WTFMove(value));
2969                 return list;
2970             }
2971             return WTFMove(value);
2972         }
2973 #if ENABLE(CURSOR_VISIBILITY)
2974         case CSSPropertyWebkitCursorVisibility:
2975             return cssValuePool.createValue(style.cursorVisibility());
2976 #endif
2977         case CSSPropertyDirection:
2978             return cssValuePool.createValue(style.direction());
2979         case CSSPropertyDisplay:
2980             return cssValuePool.createValue(style.display());
2981         case CSSPropertyEmptyCells:
2982             return cssValuePool.createValue(style.emptyCells());
2983         case CSSPropertyAlignContent:
2984             return valueForContentPositionAndDistributionWithOverflowAlignment(style.alignContent());
2985         case CSSPropertyAlignItems:
2986             return valueForItemPositionWithOverflowAlignment(style.alignItems());
2987         case CSSPropertyAlignSelf:
2988             return valueForItemPositionWithOverflowAlignment(style.alignSelf());
2989         case CSSPropertyFlex:
2990             return getCSSPropertyValuesForShorthandProperties(flexShorthand());
2991         case CSSPropertyFlexBasis:
2992             return cssValuePool.createValue(style.flexBasis(), style);
2993         case CSSPropertyFlexDirection:
2994             return cssValuePool.createValue(style.flexDirection());
2995         case CSSPropertyFlexFlow:
2996             return getCSSPropertyValuesForShorthandProperties(flexFlowShorthand());
2997         case CSSPropertyFlexGrow:
2998             return cssValuePool.createValue(style.flexGrow());
2999         case CSSPropertyFlexShrink:
3000             return cssValuePool.createValue(style.flexShrink());
3001         case CSSPropertyFlexWrap:
3002             return cssValuePool.createValue(style.flexWrap());
3003         case CSSPropertyJustifyContent:
3004             return valueForContentPositionAndDistributionWithOverflowAlignment(style.justifyContent());
3005         case CSSPropertyJustifyItems:
3006             return valueForItemPositionWithOverflowAlignment(style.justifyItems());
3007         case CSSPropertyJustifySelf:
3008             return valueForItemPositionWithOverflowAlignment(style.justifySelf());
3009         case CSSPropertyPlaceContent:
3010             return getCSSPropertyValuesForShorthandProperties(placeContentShorthand());
3011         case CSSPropertyPlaceItems:
3012             return getCSSPropertyValuesForShorthandProperties(placeItemsShorthand());
3013         case CSSPropertyPlaceSelf:
3014             return getCSSPropertyValuesForShorthandProperties(placeSelfShorthand());
3015         case CSSPropertyOrder:
3016             return cssValuePool.createValue(style.order(), CSSPrimitiveValue::CSS_NUMBER);
3017         case CSSPropertyFloat:
3018             if (style.display() != NONE && style.hasOutOfFlowPosition())
3019                 return cssValuePool.createIdentifierValue(CSSValueNone);
3020             return cssValuePool.createValue(style.floating());
3021         case CSSPropertyFont: {
3022             auto computedFont = fontShorthandValueForSelectionProperties(style.fontDescription());
3023             computedFont->size = fontSizeFromStyle(style);
3024             computedFont->lineHeight = lineHeightFromStyle(style);
3025             computedFont->family = fontFamilyListFromStyle(style);
3026             return WTFMove(computedFont);
3027         }
3028         case CSSPropertyFontFamily:
3029             return fontFamilyFromStyle(style);
3030         case CSSPropertyFontSize:
3031             return fontSizeFromStyle(style);
3032         case CSSPropertyFontStyle:
3033             return fontStyleFromStyle(style);
3034         case CSSPropertyFontStretch:
3035             return fontStretchFromStyle(style);
3036         case CSSPropertyFontVariant:
3037             return fontVariantFromStyle(style);
3038         case CSSPropertyFontWeight:
3039             return fontWeightFromStyle(style);
3040         case CSSPropertyFontSynthesis:
3041             return fontSynthesisFromStyle(style);
3042         case CSSPropertyFontFeatureSettings: {
3043             const FontFeatureSettings& featureSettings = style.fontDescription().featureSettings();
3044             if (!featureSettings.size())
3045                 return cssValuePool.createIdentifierValue(CSSValueNormal);
3046             auto list = CSSValueList::createCommaSeparated();
3047             for (auto& feature : featureSettings)
3048                 list->append(CSSFontFeatureValue::create(FontTag(feature.tag()), feature.value()));
3049             return WTFMove(list);
3050         }
3051 #if ENABLE(VARIATION_FONTS)
3052         case CSSPropertyFontVariationSettings: {
3053             const FontVariationSettings& variationSettings = style.fontDescription().variationSettings();
3054             if (variationSettings.isEmpty())
3055                 return cssValuePool.createIdentifierValue(CSSValueNormal);
3056             auto list = CSSValueList::createCommaSeparated();
3057             for (auto& feature : variationSettings)
3058                 list->append(CSSFontVariationValue::create(feature.tag(), feature.value()));
3059             return WTFMove(list);
3060         }
3061         case CSSPropertyFontOpticalSizing:
3062             return cssValuePool.createValue(style.fontDescription().opticalSizing());
3063 #endif
3064         case CSSPropertyGridAutoFlow: {
3065             auto list = CSSValueList::createSpaceSeparated();
3066             ASSERT(style.isGridAutoFlowDirectionRow() || style.isGridAutoFlowDirectionColumn());
3067             if (style.isGridAutoFlowDirectionRow())
3068                 list->append(cssValuePool.createIdentifierValue(CSSValueRow));
3069             else
3070                 list->append(cssValuePool.createIdentifierValue(CSSValueColumn));
3071
3072             if (style.isGridAutoFlowAlgorithmDense())
3073                 list->append(cssValuePool.createIdentifierValue(CSSValueDense));
3074
3075             return WTFMove(list);
3076         }
3077
3078         // Specs mention that getComputedStyle() should return the used value of the property instead of the computed
3079         // one for grid-template-{rows|columns} but not for the grid-auto-{rows|columns} as things like
3080         // grid-auto-columns: 2fr; cannot be resolved to a value in pixels as the '2fr' means very different things
3081         // depending on the size of the explicit grid or the number of implicit tracks added to the grid. See
3082         // http://lists.w3.org/Archives/Public/www-style/2013Nov/0014.html
3083         case CSSPropertyGridAutoColumns:
3084             return valueForGridTrackSizeList(ForColumns, style);
3085         case CSSPropertyGridAutoRows:
3086             return valueForGridTrackSizeList(ForRows, style);
3087
3088         case CSSPropertyGridTemplateColumns:
3089             return valueForGridTrackList(ForColumns, renderer, style);
3090         case CSSPropertyGridTemplateRows:
3091             return valueForGridTrackList(ForRows, renderer, style);
3092
3093         case CSSPropertyGridColumnStart:
3094             return valueForGridPosition(style.gridItemColumnStart());
3095         case CSSPropertyGridColumnEnd:
3096             return valueForGridPosition(style.gridItemColumnEnd());
3097         case CSSPropertyGridRowStart:
3098             return valueForGridPosition(style.gridItemRowStart());
3099         case CSSPropertyGridRowEnd:
3100             return valueForGridPosition(style.gridItemRowEnd());
3101         case CSSPropertyGridArea:
3102             return getCSSPropertyValuesForGridShorthand(gridAreaShorthand());
3103         case CSSPropertyGridTemplate:
3104             return getCSSPropertyValuesForGridShorthand(gridTemplateShorthand());
3105         case CSSPropertyGrid:
3106             return getCSSPropertyValuesForGridShorthand(gridShorthand());
3107         case CSSPropertyGridColumn:
3108             return getCSSPropertyValuesForGridShorthand(gridColumnShorthand());
3109         case CSSPropertyGridRow:
3110             return getCSSPropertyValuesForGridShorthand(gridRowShorthand());
3111         case CSSPropertyGridTemplateAreas:
3112             if (!style.namedGridAreaRowCount()) {
3113                 ASSERT(!style.namedGridAreaColumnCount());
3114                 return cssValuePool.createIdentifierValue(CSSValueNone);
3115             }
3116             return CSSGridTemplateAreasValue::create(style.namedGridArea(), style.namedGridAreaRowCount(), style.namedGridAreaColumnCount());
3117         case CSSPropertyGap:
3118             return getCSSPropertyValuesForShorthandProperties(gapShorthand());
3119         case CSSPropertyHeight:
3120             if (renderer && !renderer->isRenderSVGModelObject()) {
3121                 // According to http://www.w3.org/TR/CSS2/visudet.html#the-height-property,
3122                 // the "height" property does not apply for non-replaced inline elements.
3123                 if (isNonReplacedInline(*renderer))
3124                     return cssValuePool.createIdentifierValue(CSSValueAuto);
3125                 return zoomAdjustedPixelValue(sizingBox(*renderer).height(), style);
3126             }
3127             return zoomAdjustedPixelValueForLength(style.height(), style);
3128         case CSSPropertyWebkitHyphens:
3129             return cssValuePool.createValue(style.hyphens());
3130         case CSSPropertyWebkitHyphenateCharacter:
3131             if (style.hyphenationString().isNull())
3132                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3133             return cssValuePool.createValue(style.hyphenationString(), CSSPrimitiveValue::CSS_STRING);
3134         case CSSPropertyWebkitHyphenateLimitAfter:
3135             if (style.hyphenationLimitAfter() < 0)
3136                 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
3137             return CSSPrimitiveValue::create(style.hyphenationLimitAfter(), CSSPrimitiveValue::CSS_NUMBER);
3138         case CSSPropertyWebkitHyphenateLimitBefore:
3139             if (style.hyphenationLimitBefore() < 0)
3140                 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
3141             return CSSPrimitiveValue::create(style.hyphenationLimitBefore(), CSSPrimitiveValue::CSS_NUMBER);
3142         case CSSPropertyWebkitHyphenateLimitLines:
3143             if (style.hyphenationLimitLines() < 0)
3144                 return CSSPrimitiveValue::createIdentifier(CSSValueNoLimit);
3145             return CSSPrimitiveValue::create(style.hyphenationLimitLines(), CSSPrimitiveValue::CSS_NUMBER);
3146         case CSSPropertyWebkitBorderFit:
3147             if (style.borderFit() == BorderFitBorder)
3148                 return cssValuePool.createIdentifierValue(CSSValueBorder);
3149             return cssValuePool.createIdentifierValue(CSSValueLines);
3150 #if ENABLE(CSS_IMAGE_ORIENTATION)
3151         case CSSPropertyImageOrientation:
3152             return cssValuePool.createValue(style.imageOrientation());
3153 #endif
3154         case CSSPropertyImageRendering:
3155             return CSSPrimitiveValue::create(style.imageRendering());
3156 #if ENABLE(CSS_IMAGE_RESOLUTION)
3157         case CSSPropertyImageResolution:
3158             return cssValuePool.createValue(style.imageResolution(), CSSPrimitiveValue::CSS_DPPX);
3159 #endif
3160         case CSSPropertyLeft:
3161             return positionOffsetValue(style, CSSPropertyLeft, renderer);
3162         case CSSPropertyLetterSpacing:
3163             if (!style.letterSpacing())
3164                 return cssValuePool.createIdentifierValue(CSSValueNormal);
3165             return zoomAdjustedPixelValue(style.letterSpacing(), style);
3166         case CSSPropertyWebkitLineClamp:
3167             if (style.lineClamp().isNone())
3168                 return cssValuePool.createIdentifierValue(CSSValueNone);
3169             return cssValuePool.createValue(style.lineClamp().value(), style.lineClamp().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER);
3170         case CSSPropertyWebkitLinesClamp: {
3171             if (style.linesClamp().isNone())
3172                 return cssValuePool.createIdentifierValue(CSSValueNone);
3173             auto list = CSSValueList::createSpaceSeparated();
3174             list->append(cssValuePool.createValue(style.linesClamp().start().value(), style.linesClamp().start().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER));
3175             list->append(cssValuePool.createValue(style.linesClamp().end().value(), style.linesClamp().end().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER));
3176             list->append(cssValuePool.createValue(style.linesClamp().center(), CSSPrimitiveValue::CSS_STRING));
3177             return WTFMove(list);
3178         }
3179         case CSSPropertyLineHeight:
3180             return lineHeightFromStyle(style);
3181         case CSSPropertyListStyleImage:
3182             if (style.listStyleImage())
3183                 return style.listStyleImage()->cssValue();
3184             return cssValuePool.createIdentifierValue(CSSValueNone);
3185         case CSSPropertyListStylePosition:
3186             return cssValuePool.createValue(style.listStylePosition());
3187         case CSSPropertyListStyleType:
3188             return cssValuePool.createValue(style.listStyleType());
3189         case CSSPropertyWebkitLocale:
3190             if (style.locale().isNull())
3191                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3192             return cssValuePool.createValue(style.locale(), CSSPrimitiveValue::CSS_STRING);
3193         case CSSPropertyMarginTop:
3194             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginTop, &RenderBoxModelObject::marginTop>(style, renderer);
3195         case CSSPropertyMarginRight: {
3196             Length marginRight = style.marginRight();
3197             if (marginRight.isFixed() || !is<RenderBox>(renderer))
3198                 return zoomAdjustedPixelValueForLength(marginRight, style);
3199             float value;
3200             if (marginRight.isPercentOrCalculated()) {
3201                 // RenderBox gives a marginRight() that is the distance between the right-edge of the child box
3202                 // and the right-edge of the containing box, when display == BLOCK. Let's calculate the absolute
3203                 // value of the specified margin-right % instead of relying on RenderBox's marginRight() value.
3204                 value = minimumValueForLength(marginRight, downcast<RenderBox>(*renderer).containingBlockLogicalWidthForContent());
3205             } else
3206                 value = downcast<RenderBox>(*renderer).marginRight();
3207             return zoomAdjustedPixelValue(value, style);
3208         }
3209         case CSSPropertyMarginBottom:
3210             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginBottom, &RenderBoxModelObject::marginBottom>(style, renderer);
3211         case CSSPropertyMarginLeft:
3212             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginLeft, &RenderBoxModelObject::marginLeft>(style, renderer);
3213         case CSSPropertyWebkitMarqueeDirection:
3214             return cssValuePool.createValue(style.marqueeDirection());
3215         case CSSPropertyWebkitMarqueeIncrement:
3216             return cssValuePool.createValue(style.marqueeIncrement());
3217         case CSSPropertyWebkitMarqueeRepetition:
3218             if (style.marqueeLoopCount() < 0)
3219                 return cssValuePool.createIdentifierValue(CSSValueInfinite);
3220             return cssValuePool.createValue(style.marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER);
3221         case CSSPropertyWebkitMarqueeStyle:
3222             return cssValuePool.createValue(style.marqueeBehavior());
3223         case CSSPropertyWebkitUserModify:
3224             return cssValuePool.createValue(style.userModify());
3225         case CSSPropertyMaxHeight: {
3226             const Length& maxHeight = style.maxHeight();
3227             if (maxHeight.isUndefined())
3228                 return cssValuePool.createIdentifierValue(CSSValueNone);
3229             return zoomAdjustedPixelValueForLength(maxHeight, style);
3230         }
3231         case CSSPropertyMaxWidth: {
3232             const Length& maxWidth = style.maxWidth();
3233             if (maxWidth.isUndefined())
3234                 return cssValuePool.createIdentifierValue(CSSValueNone);
3235             return zoomAdjustedPixelValueForLength(maxWidth, style);
3236         }
3237         case CSSPropertyMinHeight:
3238             if (style.minHeight().isAuto()) {
3239                 auto* styledElement = this->styledElement();
3240                 if (styledElement && isFlexOrGrid(styledElement->parentNode()))
3241                     return cssValuePool.createIdentifierValue(CSSValueAuto);
3242                 return zoomAdjustedPixelValue(0, style);
3243             }
3244             return zoomAdjustedPixelValueForLength(style.minHeight(), style);
3245         case CSSPropertyMinWidth:
3246             if (style.minWidth().isAuto()) {
3247                 auto* styledElement = this->styledElement();
3248                 if (styledElement && isFlexOrGrid(styledElement->parentNode()))
3249                     return cssValuePool.createIdentifierValue(CSSValueAuto);
3250                 return zoomAdjustedPixelValue(0, style);
3251             }
3252             return zoomAdjustedPixelValueForLength(style.minWidth(), style);
3253         case CSSPropertyObjectFit:
3254             return cssValuePool.createValue(style.objectFit());
3255         case CSSPropertyObjectPosition: {
3256             auto list = CSSValueList::createSpaceSeparated();
3257             list->append(zoomAdjustedPixelValueForLength(style.objectPosition().x(), style));
3258             list->append(zoomAdjustedPixelValueForLength(style.objectPosition().y(), style));
3259             return WTFMove(list);
3260         }
3261         case CSSPropertyOpacity:
3262             return cssValuePool.createValue(style.opacity(), CSSPrimitiveValue::CSS_NUMBER);
3263         case CSSPropertyOrphans:
3264             if (style.hasAutoOrphans())
3265                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3266             return cssValuePool.createValue(style.orphans(), CSSPrimitiveValue::CSS_NUMBER);
3267         case CSSPropertyOutlineColor:
3268             return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyOutlineColor)) : currentColorOrValidColor(&style, style.outlineColor());
3269         case CSSPropertyOutlineOffset:
3270             return zoomAdjustedPixelValue(style.outlineOffset(), style);
3271         case CSSPropertyOutlineStyle:
3272             if (style.outlineStyleIsAuto())
3273                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3274             return cssValuePool.createValue(style.outlineStyle());
3275         case CSSPropertyOutlineWidth:
3276             return zoomAdjustedPixelValue(style.outlineWidth(), style);
3277         case CSSPropertyOverflow:
3278             return cssValuePool.createValue(std::max(style.overflowX(), style.overflowY()));
3279         case CSSPropertyOverflowWrap:
3280             return cssValuePool.createValue(style.overflowWrap());
3281         case CSSPropertyOverflowX:
3282             return cssValuePool.createValue(style.overflowX());
3283         case CSSPropertyOverflowY:
3284             return cssValuePool.createValue(style.overflowY());
3285         case CSSPropertyPaddingTop:
3286             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingTop, &RenderBoxModelObject::computedCSSPaddingTop>(style, renderer);
3287         case CSSPropertyPaddingRight:
3288             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingRight, &RenderBoxModelObject::computedCSSPaddingRight>(style, renderer);
3289         case CSSPropertyPaddingBottom:
3290             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingBottom, &RenderBoxModelObject::computedCSSPaddingBottom>(style, renderer);
3291         case CSSPropertyPaddingLeft:
3292             return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingLeft, &RenderBoxModelObject::computedCSSPaddingLeft>(style, renderer);
3293         case CSSPropertyPageBreakAfter:
3294             return cssValuePool.createValue(convertToPageBreak(style.breakAfter()));
3295         case CSSPropertyPageBreakBefore:
3296             return cssValuePool.createValue(convertToPageBreak(style.breakBefore()));
3297         case CSSPropertyPageBreakInside:
3298             return cssValuePool.createValue(convertToPageBreak(style.breakInside()));
3299         case CSSPropertyBreakAfter:
3300             return cssValuePool.createValue(style.breakAfter());
3301         case CSSPropertyBreakBefore:
3302             return cssValuePool.createValue(style.breakBefore());
3303         case CSSPropertyBreakInside:
3304             return cssValuePool.createValue(style.breakInside());
3305         case CSSPropertyHangingPunctuation:
3306             return hangingPunctuationToCSSValue(style.hangingPunctuation());
3307         case CSSPropertyPosition:
3308             return cssValuePool.createValue(style.position());
3309         case CSSPropertyRight:
3310             return positionOffsetValue(style, CSSPropertyRight, renderer);
3311         case CSSPropertyWebkitRubyPosition:
3312             return cssValuePool.createValue(style.rubyPosition());
3313         case CSSPropertyTableLayout:
3314             return cssValuePool.createValue(style.tableLayout());
3315         case CSSPropertyTextAlign:
3316             return cssValuePool.createValue(style.textAlign());
3317         case CSSPropertyTextDecoration:
3318             return renderTextDecorationFlagsToCSSValue(style.textDecoration());
3319 #if ENABLE(CSS3_TEXT)
3320         case CSSPropertyWebkitTextAlignLast:
3321             return cssValuePool.createValue(style.textAlignLast());
3322         case CSSPropertyWebkitTextJustify:
3323             return cssValuePool.createValue(style.textJustify());
3324 #endif // CSS3_TEXT
3325         case CSSPropertyWebkitTextDecoration:
3326             return getCSSPropertyValuesForShorthandProperties(webkitTextDecorationShorthand());
3327         case CSSPropertyWebkitTextDecorationLine:
3328             return renderTextDecorationFlagsToCSSValue(style.textDecoration());
3329         case CSSPropertyWebkitTextDecorationStyle:
3330             return renderTextDecorationStyleFlagsToCSSValue(style.textDecorationStyle());
3331         case CSSPropertyWebkitTextDecorationColor:
3332             return currentColorOrValidColor(&style, style.textDecorationColor());
3333         case CSSPropertyWebkitTextDecorationSkip:
3334             return renderTextDecorationSkipFlagsToCSSValue(style.textDecorationSkip());
3335         case CSSPropertyWebkitTextUnderlinePosition:
3336             return cssValuePool.createValue(style.textUnderlinePosition());
3337         case CSSPropertyWebkitTextDecorationsInEffect:
3338             return renderTextDecorationFlagsToCSSValue(style.textDecorationsInEffect());
3339         case CSSPropertyWebkitTextFillColor:
3340             return currentColorOrValidColor(&style, style.textFillColor());
3341         case CSSPropertyWebkitTextEmphasisColor:
3342             return currentColorOrValidColor(&style, style.textEmphasisColor());
3343         case CSSPropertyWebkitTextEmphasisPosition:
3344             return renderEmphasisPositionFlagsToCSSValue(style.textEmphasisPosition());
3345         case CSSPropertyWebkitTextEmphasisStyle:
3346             switch (style.textEmphasisMark()) {
3347             case TextEmphasisMarkNone:
3348                 return cssValuePool.createIdentifierValue(CSSValueNone);
3349             case TextEmphasisMarkCustom:
3350                 return cssValuePool.createValue(style.textEmphasisCustomMark(), CSSPrimitiveValue::CSS_STRING);
3351             case TextEmphasisMarkAuto:
3352                 ASSERT_NOT_REACHED();
3353 #if ASSERT_DISABLED
3354                 FALLTHROUGH;
3355 #endif
3356             case TextEmphasisMarkDot:
3357             case TextEmphasisMarkCircle:
3358             case TextEmphasisMarkDoubleCircle:
3359             case TextEmphasisMarkTriangle:
3360             case TextEmphasisMarkSesame:
3361                 auto list = CSSValueList::createSpaceSeparated();
3362                 list->append(cssValuePool.createValue(style.textEmphasisFill()));
3363                 list->append(cssValuePool.createValue(style.textEmphasisMark()));
3364                 return WTFMove(list);
3365             }
3366             RELEASE_ASSERT_NOT_REACHED();
3367         case CSSPropertyTextIndent: {
3368             // If CSS3_TEXT is disabled or text-indent has only one value(<length> | <percentage>),
3369             // getPropertyCSSValue() returns CSSValue.
3370             auto textIndent = zoomAdjustedPixelValueForLength(style.textIndent(), style);
3371 #if ENABLE(CSS3_TEXT)
3372             // If CSS3_TEXT is enabled and text-indent has -webkit-each-line or -webkit-hanging,
3373             // getPropertyCSSValue() returns CSSValueList.
3374             if (style.textIndentLine() == TextIndentEachLine || style.textIndentType() == TextIndentHanging) {
3375                 auto list = CSSValueList::createSpaceSeparated();
3376                 list->append(WTFMove(textIndent));
3377                 if (style.textIndentLine() == TextIndentEachLine)
3378                     list->append(cssValuePool.createIdentifierValue(CSSValueWebkitEachLine));
3379                 if (style.textIndentType() == TextIndentHanging)
3380                     list->append(cssValuePool.createIdentifierValue(CSSValueWebkitHanging));
3381                 return WTFMove(list);
3382             }
3383 #endif
3384             return WTFMove(textIndent);
3385         }
3386         case CSSPropertyTextShadow:
3387             return valueForShadow(style.textShadow(), propertyID, style);
3388         case CSSPropertyTextRendering:
3389             return cssValuePool.createValue(style.fontDescription().textRenderingMode());
3390         case CSSPropertyTextOverflow:
3391             if (style.textOverflow())
3392                 return cssValuePool.createIdentifierValue(CSSValueEllipsis);
3393             return cssValuePool.createIdentifierValue(CSSValueClip);
3394         case CSSPropertyWebkitTextSecurity:
3395             return cssValuePool.createValue(style.textSecurity());
3396 #if ENABLE(TEXT_AUTOSIZING)
3397         case CSSPropertyWebkitTextSizeAdjust:
3398             if (style.textSizeAdjust().isAuto())
3399                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3400             if (style.textSizeAdjust().isNone())
3401                 return cssValuePool.createIdentifierValue(CSSValueNone);
3402             return CSSPrimitiveValue::create(style.textSizeAdjust().percentage(), CSSPrimitiveValue::CSS_PERCENTAGE);
3403 #endif
3404         case CSSPropertyWebkitTextStrokeColor:
3405             return currentColorOrValidColor(&style, style.textStrokeColor());
3406         case CSSPropertyWebkitTextStrokeWidth:
3407             return zoomAdjustedPixelValue(style.textStrokeWidth(), style);
3408         case CSSPropertyTextTransform:
3409             return cssValuePool.createValue(style.textTransform());
3410         case CSSPropertyTop:
3411             return positionOffsetValue(style, CSSPropertyTop, renderer);
3412         case CSSPropertyUnicodeBidi:
3413             return cssValuePool.createValue(style.unicodeBidi());
3414         case CSSPropertyVerticalAlign:
3415             switch (style.verticalAlign()) {
3416                 case BASELINE:
3417                     return cssValuePool.createIdentifierValue(CSSValueBaseline);
3418                 case MIDDLE:
3419                     return cssValuePool.createIdentifierValue(CSSValueMiddle);
3420                 case SUB:
3421                     return cssValuePool.createIdentifierValue(CSSValueSub);
3422                 case SUPER:
3423                     return cssValuePool.createIdentifierValue(CSSValueSuper);
3424                 case TEXT_TOP:
3425                     return cssValuePool.createIdentifierValue(CSSValueTextTop);
3426                 case TEXT_BOTTOM:
3427                     return cssValuePool.createIdentifierValue(CSSValueTextBottom);
3428                 case TOP:
3429                     return cssValuePool.createIdentifierValue(CSSValueTop);
3430                 case BOTTOM:
3431                     return cssValuePool.createIdentifierValue(CSSValueBottom);
3432                 case BASELINE_MIDDLE:
3433                     return cssValuePool.createIdentifierValue(CSSValueWebkitBaselineMiddle);
3434                 case LENGTH:
3435                     return cssValuePool.createValue(style.verticalAlignLength());
3436             }
3437             ASSERT_NOT_REACHED();
3438             return nullptr;
3439         case CSSPropertyVisibility:
3440             return cssValuePool.createValue(style.visibility());
3441         case CSSPropertyWhiteSpace:
3442             return cssValuePool.createValue(style.whiteSpace());
3443         case CSSPropertyWidows:
3444             if (style.hasAutoWidows())
3445                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3446             return cssValuePool.createValue(style.widows(), CSSPrimitiveValue::CSS_NUMBER);
3447         case CSSPropertyWidth:
3448             if (renderer && !renderer->isRenderSVGModelObject()) {
3449                 // According to http://www.w3.org/TR/CSS2/visudet.html#the-width-property,
3450                 // the "width" property does not apply for non-replaced inline elements.
3451                 if (isNonReplacedInline(*renderer))
3452                     return cssValuePool.createIdentifierValue(CSSValueAuto);
3453                 return zoomAdjustedPixelValue(sizingBox(*renderer).width(), style);
3454             }
3455             return zoomAdjustedPixelValueForLength(style.width(), style);
3456         case CSSPropertyWillChange:
3457             return willChangePropertyValue(style.willChange());
3458         case CSSPropertyWordBreak:
3459             return cssValuePool.createValue(style.wordBreak());
3460         case CSSPropertyWordSpacing:
3461             return zoomAdjustedPixelValue(style.fontCascade().wordSpacing(), style);
3462         case CSSPropertyWordWrap:
3463             return cssValuePool.createValue(style.overflowWrap());
3464         case CSSPropertyLineBreak:
3465             return cssValuePool.createValue(style.lineBreak());
3466         case CSSPropertyWebkitNbspMode:
3467             return cssValuePool.createValue(style.nbspMode());
3468         case CSSPropertyResize:
3469             return cssValuePool.createValue(style.resize());
3470         case CSSPropertyWebkitFontKerning:
3471             return cssValuePool.createValue(style.fontDescription().kerning());
3472         case CSSPropertyWebkitFontSmoothing:
3473             return cssValuePool.createValue(style.fontDescription().fontSmoothing());
3474         case CSSPropertyFontVariantLigatures:
3475             return fontVariantLigaturesPropertyValue(style.fontDescription().variantCommonLigatures(), style.fontDescription().variantDiscretionaryLigatures(), style.fontDescription().variantHistoricalLigatures(), style.fontDescription().variantContextualAlternates());
3476         case CSSPropertyFontVariantPosition:
3477             return fontVariantPositionPropertyValue(style.fontDescription().variantPosition());
3478         case CSSPropertyFontVariantCaps:
3479             return fontVariantCapsPropertyValue(style.fontDescription().variantCaps());
3480         case CSSPropertyFontVariantNumeric:
3481             return fontVariantNumericPropertyValue(style.fontDescription().variantNumericFigure(), style.fontDescription().variantNumericSpacing(), style.fontDescription().variantNumericFraction(), style.fontDescription().variantNumericOrdinal(), style.fontDescription().variantNumericSlashedZero());
3482         case CSSPropertyFontVariantAlternates:
3483             return fontVariantAlternatesPropertyValue(style.fontDescription().variantAlternates());
3484         case CSSPropertyFontVariantEastAsian:
3485             return fontVariantEastAsianPropertyValue(style.fontDescription().variantEastAsianVariant(), style.fontDescription().variantEastAsianWidth(), style.fontDescription().variantEastAsianRuby());
3486         case CSSPropertyZIndex:
3487             if (style.hasAutoZIndex())
3488                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3489             return cssValuePool.createValue(style.zIndex(), CSSPrimitiveValue::CSS_NUMBER);
3490         case CSSPropertyZoom:
3491             return cssValuePool.createValue(style.zoom(), CSSPrimitiveValue::CSS_NUMBER);
3492         case CSSPropertyBoxSizing:
3493             if (style.boxSizing() == CONTENT_BOX)
3494                 return cssValuePool.createIdentifierValue(CSSValueContentBox);
3495             return cssValuePool.createIdentifierValue(CSSValueBorderBox);
3496 #if ENABLE(DASHBOARD_SUPPORT)
3497         case CSSPropertyWebkitDashboardRegion:
3498         {
3499             const Vector<StyleDashboardRegion>& regions = style.dashboardRegions();
3500             unsigned count = regions.size();
3501             if (count == 1 && regions[0].type == StyleDashboardRegion::None)
3502                 return cssValuePool.createIdentifierValue(CSSValueNone);
3503
3504             RefPtr<DashboardRegion> firstRegion;
3505             DashboardRegion* previousRegion = nullptr;
3506             for (unsigned i = 0; i < count; i++) {
3507                 auto region = DashboardRegion::create();
3508                 StyleDashboardRegion styleRegion = regions[i];
3509
3510                 region->m_label = styleRegion.label;
3511                 LengthBox offset = styleRegion.offset;
3512                 region->setTop(zoomAdjustedPixelValue(offset.top().value(), style));
3513                 region->setRight(zoomAdjustedPixelValue(offset.right().value(), style));
3514                 region->setBottom(zoomAdjustedPixelValue(offset.bottom().value(), style));
3515                 region->setLeft(zoomAdjustedPixelValue(offset.left().value(), style));
3516                 region->m_isRectangle = (styleRegion.type == StyleDashboardRegion::Rectangle);
3517                 region->m_isCircle = (styleRegion.type == StyleDashboardRegion::Circle);
3518
3519                 if (previousRegion)
3520                     previousRegion->m_next = region.copyRef();
3521                 else
3522                     firstRegion = region.copyRef();
3523                 previousRegion = region.ptr();
3524             }
3525             return cssValuePool.createValue(WTFMove(firstRegion));
3526         }
3527 #endif
3528         case CSSPropertyAnimationDelay:
3529             return delayValue(style.animations());
3530         case CSSPropertyAnimationDirection: {
3531             auto list = CSSValueList::createCommaSeparated();
3532             const AnimationList* t = style.animations();
3533             if (t) {
3534                 for (size_t i = 0; i < t->size(); ++i) {
3535                     switch (t->animation(i).direction()) {
3536                     case Animation::AnimationDirectionNormal:
3537                         list->append(cssValuePool.createIdentifierValue(CSSValueNormal));
3538                         break;
3539                     case Animation::AnimationDirectionAlternate:
3540                         list->append(cssValuePool.createIdentifierValue(CSSValueAlternate));
3541                         break;
3542                     case Animation::AnimationDirectionReverse:
3543                         list->append(cssValuePool.createIdentifierValue(CSSValueReverse));
3544                         break;
3545                     case Animation::AnimationDirectionAlternateReverse:
3546                         list->append(cssValuePool.createIdentifierValue(CSSValueAlternateReverse));
3547                         break;
3548                     }
3549                 }
3550             } else
3551                 list->append(cssValuePool.createIdentifierValue(CSSValueNormal));
3552             return WTFMove(list);
3553         }
3554         case CSSPropertyAnimationDuration:
3555             return durationValue(style.animations());
3556         case CSSPropertyAnimationFillMode: {
3557             auto list = CSSValueList::createCommaSeparated();
3558             const AnimationList* t = style.animations();
3559             if (t) {
3560                 for (size_t i = 0; i < t->size(); ++i) {
3561                     switch (t->animation(i).fillMode()) {
3562                     case AnimationFillModeNone:
3563                         list->append(cssValuePool.createIdentifierValue(CSSValueNone));
3564                         break;
3565                     case AnimationFillModeForwards:
3566                         list->append(cssValuePool.createIdentifierValue(CSSValueForwards));
3567                         break;
3568                     case AnimationFillModeBackwards:
3569                         list->append(cssValuePool.createIdentifierValue(CSSValueBackwards));
3570                         break;
3571                     case AnimationFillModeBoth:
3572                         list->append(cssValuePool.createIdentifierValue(CSSValueBoth));
3573                         break;
3574                     }
3575                 }
3576             } else
3577                 list->append(cssValuePool.createIdentifierValue(CSSValueNone));
3578             return WTFMove(list);
3579         }
3580         case CSSPropertyAnimationIterationCount: {
3581             auto list = CSSValueList::createCommaSeparated();
3582             const AnimationList* t = style.animations();
3583             if (t) {
3584                 for (size_t i = 0; i < t->size(); ++i) {
3585                     double iterationCount = t->animation(i).iterationCount();
3586                     if (iterationCount == Animation::IterationCountInfinite)
3587                         list->append(cssValuePool.createIdentifierValue(CSSValueInfinite));
3588                     else
3589                         list->append(cssValuePool.createValue(iterationCount, CSSPrimitiveValue::CSS_NUMBER));
3590                 }
3591             } else
3592                 list->append(cssValuePool.createValue(Animation::initialIterationCount(), CSSPrimitiveValue::CSS_NUMBER));
3593             return WTFMove(list);
3594         }
3595         case CSSPropertyAnimationName: {
3596             auto list = CSSValueList::createCommaSeparated();
3597             const AnimationList* t = style.animations();
3598             if (t) {
3599                 for (size_t i = 0; i < t->size(); ++i)
3600                     list->append(cssValuePool.createValue(t->animation(i).name(), CSSPrimitiveValue::CSS_STRING));
3601             } else
3602                 list->append(cssValuePool.createIdentifierValue(CSSValueNone));
3603             return WTFMove(list);
3604         }
3605         case CSSPropertyAnimationPlayState: {
3606             auto list = CSSValueList::createCommaSeparated();
3607             const AnimationList* t = style.animations();
3608             if (t) {
3609                 for (size_t i = 0; i < t->size(); ++i) {
3610                     int prop = t->animation(i).playState();
3611                     if (prop == AnimPlayStatePlaying)
3612                         list->append(cssValuePool.createIdentifierValue(CSSValueRunning));
3613                     else
3614                         list->append(cssValuePool.createIdentifierValue(CSSValuePaused));
3615                 }
3616             } else
3617                 list->append(cssValuePool.createIdentifierValue(CSSValueRunning));
3618             return WTFMove(list);
3619         }
3620         case CSSPropertyAnimationTimingFunction:
3621             return timingFunctionValue(style.animations());
3622 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
3623         case CSSPropertyWebkitAnimationTrigger:
3624             return animationTriggerValue(style.animations(), style);
3625 #endif
3626         case CSSPropertyWebkitAppearance:
3627             return cssValuePool.createValue(style.appearance());
3628         case CSSPropertyWebkitAspectRatio:
3629             if (style.aspectRatioType() == AspectRatioAuto)
3630                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3631             if (style.aspectRatioType() == AspectRatioFromDimensions)
3632                 return cssValuePool.createIdentifierValue(CSSValueFromDimensions);
3633             if (style.aspectRatioType() == AspectRatioFromIntrinsic)
3634                 return cssValuePool.createIdentifierValue(CSSValueFromIntrinsic);
3635             return CSSAspectRatioValue::create(style.aspectRatioNumerator(), style.aspectRatioDenominator());
3636         case CSSPropertyWebkitBackfaceVisibility:
3637             return cssValuePool.createIdentifierValue((style.backfaceVisibility() == BackfaceVisibilityHidden) ? CSSValueHidden : CSSValueVisible);
3638         case CSSPropertyWebkitBorderImage:
3639             return valueForNinePieceImage(style.borderImage());
3640         case CSSPropertyBorderImageOutset:
3641             return valueForNinePieceImageQuad(style.borderImage().outset());
3642         case CSSPropertyBorderImageRepeat:
3643             return valueForNinePieceImageRepeat(style.borderImage());
3644         case CSSPropertyBorderImageSlice:
3645             return valueForNinePieceImageSlice(style.borderImage());
3646         case CSSPropertyBorderImageWidth:
3647             return valueForNinePieceImageQuad(style.borderImage().borderSlices());
3648         case CSSPropertyWebkitMaskBoxImage:
3649             return valueForNinePieceImage(style.maskBoxImage());
3650         case CSSPropertyWebkitMaskBoxImageOutset:
3651             return valueForNinePieceImageQuad(style.maskBoxImage().outset());
3652         case CSSPropertyWebkitMaskBoxImageRepeat:
3653             return valueForNinePieceImageRepeat(style.maskBoxImage());
3654         case CSSPropertyWebkitMaskBoxImageSlice:
3655             return valueForNinePieceImageSlice(style.maskBoxImage());
3656         case CSSPropertyWebkitMaskBoxImageWidth:
3657             return valueForNinePieceImageQuad(style.maskBoxImage().borderSlices());
3658         case CSSPropertyWebkitMaskBoxImageSource:
3659             if (style.maskBoxImageSource())
3660                 return style.maskBoxImageSource()->cssValue();
3661             return cssValuePool.createIdentifierValue(CSSValueNone);
3662         case CSSPropertyWebkitFontSizeDelta:
3663             // Not a real style property -- used by the editing engine -- so has no computed value.
3664             break;
3665         case CSSPropertyWebkitInitialLetter: {
3666             auto drop = !style.initialLetterDrop() ? cssValuePool.createIdentifierValue(CSSValueNormal) : cssValuePool.createValue(style.initialLetterDrop(), CSSPrimitiveValue::CSS_NUMBER);
3667             auto size = !style.initialLetterHeight() ? cssValuePool.createIdentifierValue(CSSValueNormal) : cssValuePool.createValue(style.initialLetterHeight(), CSSPrimitiveValue::CSS_NUMBER);
3668             return cssValuePool.createValue(Pair::create(WTFMove(drop), WTFMove(size)));
3669         }
3670         case CSSPropertyWebkitMarginBottomCollapse:
3671         case CSSPropertyWebkitMarginAfterCollapse:
3672             return cssValuePool.createValue(style.marginAfterCollapse());
3673         case CSSPropertyWebkitMarginTopCollapse:
3674         case CSSPropertyWebkitMarginBeforeCollapse:
3675             return cssValuePool.createValue(style.marginBeforeCollapse());
3676 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
3677         case CSSPropertyWebkitOverflowScrolling:
3678             if (!style.useTouchOverflowScrolling())
3679                 return cssValuePool.createIdentifierValue(CSSValueAuto);
3680             return cssValuePool.createIdentifierValue(CSSValueTouch);
3681 #endif
3682         case CSSPropertyPerspective:
3683             if (!style.hasPerspective())
3684                 return cssValuePool.createIdentifierValue(CSSValueNone);
3685             return zoomAdjustedPixelValue(style.perspective(), style);
3686         case CSSPropertyPerspectiveOrigin: {
3687             auto list = CSSValueList::createSpaceSeparated();
3688             if (renderer) {
3689                 LayoutRect box;
3690                 if (is<RenderBox>(*renderer))
3691                     box = downcast<RenderBox>(*renderer).borderBoxRect();
3692
3693                 list->append(zoomAdjustedPixelValue(minimumValueForLength(style.perspectiveOriginX(), box.width()), style));
3694                 list->append(zoomAdjustedPixelValue(minimumValueForLength(style.perspectiveOriginY(), box.height()), style));
3695             }
3696             else {
3697                 list->append(zoomAdjustedPixelValueForLength(style.perspectiveOriginX(), style));
3698                 list->append(zoomAdjustedPixelValueForLength(style.perspectiveOriginY(), style));
3699
3700             }
3701             return WTFMove(list);
3702         }