1/*
2 * Copyright (C) 2004 Zack Rusin <zack@kde.org>
3 * Copyright (C) 2004-2019 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6 * Copyright (C) 2011 Sencha, Inc. All rights reserved.
7 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 */
24
25#include "config.h"
26#include "CSSComputedStyleDeclaration.h"
27
28#include "BasicShapeFunctions.h"
29#include "CSSAnimationController.h"
30#include "CSSAspectRatioValue.h"
31#include "CSSBasicShapes.h"
32#include "CSSBorderImage.h"
33#include "CSSBorderImageSliceValue.h"
34#include "CSSFontFeatureValue.h"
35#include "CSSFontStyleValue.h"
36#include "CSSFontValue.h"
37#include "CSSFontVariationValue.h"
38#include "CSSFunctionValue.h"
39#include "CSSLineBoxContainValue.h"
40#include "CSSPrimitiveValue.h"
41#include "CSSPrimitiveValueMappings.h"
42#include "CSSPropertyNames.h"
43#include "CSSPropertyParser.h"
44#include "CSSReflectValue.h"
45#include "CSSSelector.h"
46#include "CSSShadowValue.h"
47#include "CSSTimingFunctionValue.h"
48#include "CSSValueList.h"
49#include "CSSValuePool.h"
50#include "ComposedTreeAncestorIterator.h"
51#include "ContentData.h"
52#include "CursorList.h"
53#include "DeprecatedCSSOMValue.h"
54#include "Document.h"
55#include "DocumentTimeline.h"
56#include "FontCascade.h"
57#include "FontSelectionValueInlines.h"
58#include "FontTaggedSettings.h"
59#include "NodeRenderStyle.h"
60#include "Pair.h"
61#include "Rect.h"
62#include "RenderBlock.h"
63#include "RenderBox.h"
64#include "RenderInline.h"
65#include "RenderStyle.h"
66#include "RuntimeEnabledFeatures.h"
67#include "SVGElement.h"
68#include "Settings.h"
69#include "ShapeValue.h"
70#include "StyleProperties.h"
71#include "StylePropertyShorthand.h"
72#include "StylePropertyShorthandFunctions.h"
73#include "StyleResolver.h"
74#include "StyleScope.h"
75#include "StyleScrollSnapPoints.h"
76#include "TouchAction.h"
77#include "WebKitFontFamilyNames.h"
78#include "WillChangeData.h"
79#include <wtf/IsoMallocInlines.h>
80#include <wtf/NeverDestroyed.h>
81#include <wtf/text/StringBuilder.h>
82
83#include "CSSGridLineNamesValue.h"
84#include "CSSGridTemplateAreasValue.h"
85#include "RenderGrid.h"
86
87namespace WebCore {
88
89WTF_MAKE_ISO_ALLOCATED_IMPL(CSSComputedStyleDeclaration);
90
91// List of all properties we know how to compute, omitting shorthands.
92static const CSSPropertyID computedProperties[] = {
93 CSSPropertyAlignContent,
94 CSSPropertyAlignItems,
95 CSSPropertyAlignSelf,
96 CSSPropertyAlignmentBaseline,
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 CSSPropertyBaselineShift,
116 CSSPropertyBorderBottomColor,
117 CSSPropertyBorderBottomLeftRadius,
118 CSSPropertyBorderBottomRightRadius,
119 CSSPropertyBorderBottomStyle,
120 CSSPropertyBorderBottomWidth,
121 CSSPropertyBorderCollapse,
122 CSSPropertyBorderImageOutset,
123 CSSPropertyBorderImageRepeat,
124 CSSPropertyBorderImageSlice,
125 CSSPropertyBorderImageSource,
126 CSSPropertyBorderImageWidth,
127 CSSPropertyBorderLeftColor,
128 CSSPropertyBorderLeftStyle,
129 CSSPropertyBorderLeftWidth,
130 CSSPropertyBorderRightColor,
131 CSSPropertyBorderRightStyle,
132 CSSPropertyBorderRightWidth,
133 CSSPropertyBorderTopColor,
134 CSSPropertyBorderTopLeftRadius,
135 CSSPropertyBorderTopRightRadius,
136 CSSPropertyBorderTopStyle,
137 CSSPropertyBorderTopWidth,
138 CSSPropertyBottom,
139 CSSPropertyBoxShadow,
140 CSSPropertyBoxSizing,
141 CSSPropertyBufferedRendering,
142 CSSPropertyCaptionSide,
143 CSSPropertyCaretColor,
144 CSSPropertyClear,
145 CSSPropertyClip,
146 CSSPropertyClipPath,
147 CSSPropertyClipRule,
148 CSSPropertyColor,
149 CSSPropertyColorInterpolation,
150 CSSPropertyColorInterpolationFilters,
151 CSSPropertyColorRendering,
152#if ENABLE(DARK_MODE_CSS)
153 CSSPropertyColorScheme,
154#endif
155 CSSPropertyColumnCount,
156 CSSPropertyColumnFill,
157 CSSPropertyColumnGap,
158 CSSPropertyColumnRuleColor,
159 CSSPropertyColumnRuleStyle,
160 CSSPropertyColumnRuleWidth,
161 CSSPropertyColumnSpan,
162 CSSPropertyColumnWidth,
163 CSSPropertyContent,
164 CSSPropertyCounterIncrement,
165 CSSPropertyCounterReset,
166 CSSPropertyCursor,
167 CSSPropertyCx,
168 CSSPropertyCy,
169 CSSPropertyDirection,
170 CSSPropertyDisplay,
171 CSSPropertyDominantBaseline,
172 CSSPropertyEmptyCells,
173 CSSPropertyFill,
174 CSSPropertyFillOpacity,
175 CSSPropertyFillRule,
176 CSSPropertyFilter,
177 CSSPropertyFlexBasis,
178 CSSPropertyFlexDirection,
179 CSSPropertyFlexFlow,
180 CSSPropertyFlexGrow,
181 CSSPropertyFlexShrink,
182 CSSPropertyFlexWrap,
183 CSSPropertyFloat,
184 CSSPropertyFloodColor,
185 CSSPropertyFloodOpacity,
186 CSSPropertyFontFamily,
187#if ENABLE(VARIATION_FONTS)
188 CSSPropertyFontOpticalSizing,
189#endif
190 CSSPropertyFontSize,
191 CSSPropertyFontStretch,
192 CSSPropertyFontStyle,
193 CSSPropertyFontSynthesis,
194 CSSPropertyFontVariant,
195 CSSPropertyFontVariantAlternates,
196 CSSPropertyFontVariantCaps,
197 CSSPropertyFontVariantEastAsian,
198 CSSPropertyFontVariantLigatures,
199 CSSPropertyFontVariantNumeric,
200 CSSPropertyFontVariantPosition,
201#if ENABLE(VARIATION_FONTS)
202 CSSPropertyFontVariationSettings,
203#endif
204 CSSPropertyFontWeight,
205 CSSPropertyGlyphOrientationHorizontal,
206 CSSPropertyGlyphOrientationVertical,
207 CSSPropertyGridAutoColumns,
208 CSSPropertyGridAutoFlow,
209 CSSPropertyGridAutoRows,
210 CSSPropertyGridColumnEnd,
211 CSSPropertyGridColumnStart,
212 CSSPropertyGridRowEnd,
213 CSSPropertyGridRowStart,
214 CSSPropertyGridTemplateAreas,
215 CSSPropertyGridTemplateColumns,
216 CSSPropertyGridTemplateRows,
217 CSSPropertyHangingPunctuation,
218 CSSPropertyHeight,
219#if ENABLE(CSS_IMAGE_ORIENTATION)
220 CSSPropertyImageOrientation,
221#endif
222 CSSPropertyImageRendering,
223#if ENABLE(CSS_IMAGE_RESOLUTION)
224 CSSPropertyImageResolution,
225#endif
226#if ENABLE(CSS_COMPOSITING)
227 CSSPropertyIsolation,
228#endif
229 CSSPropertyJustifyContent,
230 CSSPropertyJustifyItems,
231 CSSPropertyJustifySelf,
232 CSSPropertyKerning,
233 CSSPropertyLeft,
234 CSSPropertyLetterSpacing,
235 CSSPropertyLightingColor,
236 CSSPropertyLineBreak,
237 CSSPropertyLineHeight,
238 CSSPropertyListStyleImage,
239 CSSPropertyListStylePosition,
240 CSSPropertyListStyleType,
241 CSSPropertyMarginBottom,
242 CSSPropertyMarginLeft,
243 CSSPropertyMarginRight,
244 CSSPropertyMarginTop,
245 CSSPropertyMarkerEnd,
246 CSSPropertyMarkerMid,
247 CSSPropertyMarkerStart,
248 CSSPropertyMask,
249 CSSPropertyMaskType,
250 CSSPropertyMaxHeight,
251 CSSPropertyMaxWidth,
252 CSSPropertyMinHeight,
253 CSSPropertyMinWidth,
254#if ENABLE(CSS_COMPOSITING)
255 CSSPropertyMixBlendMode,
256#endif
257 CSSPropertyObjectFit,
258 CSSPropertyObjectPosition,
259 CSSPropertyOpacity,
260 CSSPropertyOrder,
261 CSSPropertyOrphans,
262 CSSPropertyOutlineColor,
263 CSSPropertyOutlineOffset,
264 CSSPropertyOutlineStyle,
265 CSSPropertyOutlineWidth,
266 CSSPropertyOverflowWrap,
267 CSSPropertyOverflowX,
268 CSSPropertyOverflowY,
269 CSSPropertyPaddingBottom,
270 CSSPropertyPaddingLeft,
271 CSSPropertyPaddingRight,
272 CSSPropertyPaddingTop,
273 CSSPropertyPageBreakAfter,
274 CSSPropertyPageBreakBefore,
275 CSSPropertyPageBreakInside,
276 CSSPropertyPaintOrder,
277 CSSPropertyPerspective,
278 CSSPropertyPerspectiveOrigin,
279 CSSPropertyPlaceContent,
280 CSSPropertyPlaceItems,
281 CSSPropertyPlaceSelf,
282 CSSPropertyPointerEvents,
283 CSSPropertyPosition,
284 CSSPropertyR,
285 CSSPropertyResize,
286 CSSPropertyRight,
287 CSSPropertyRowGap,
288 CSSPropertyRx,
289 CSSPropertyRy,
290#if ENABLE(CSS_SCROLL_SNAP)
291 CSSPropertyScrollPadding,
292 CSSPropertyScrollPaddingBottom,
293 CSSPropertyScrollPaddingLeft,
294 CSSPropertyScrollPaddingRight,
295 CSSPropertyScrollPaddingTop,
296 CSSPropertyScrollSnapAlign,
297 CSSPropertyScrollSnapMargin,
298 CSSPropertyScrollSnapMarginBottom,
299 CSSPropertyScrollSnapMarginLeft,
300 CSSPropertyScrollSnapMarginRight,
301 CSSPropertyScrollSnapMarginTop,
302 CSSPropertyScrollSnapType,
303#endif
304 CSSPropertyShapeImageThreshold,
305 CSSPropertyShapeMargin,
306 CSSPropertyShapeOutside,
307 CSSPropertyShapeRendering,
308 CSSPropertySpeakAs,
309 CSSPropertyStopColor,
310 CSSPropertyStopOpacity,
311 CSSPropertyStroke,
312 CSSPropertyStrokeColor,
313 CSSPropertyStrokeDasharray,
314 CSSPropertyStrokeDashoffset,
315 CSSPropertyStrokeLinecap,
316 CSSPropertyStrokeLinejoin,
317 CSSPropertyStrokeMiterlimit,
318 CSSPropertyStrokeOpacity,
319 CSSPropertyStrokeWidth,
320 CSSPropertyTabSize,
321 CSSPropertyTableLayout,
322 CSSPropertyTextAlign,
323 CSSPropertyTextAnchor,
324 CSSPropertyTextDecoration,
325 CSSPropertyTextDecorationColor,
326 CSSPropertyTextDecorationLine,
327 CSSPropertyTextDecorationSkip,
328 CSSPropertyTextDecorationStyle,
329 CSSPropertyTextIndent,
330 CSSPropertyTextOverflow,
331 CSSPropertyTextRendering,
332 CSSPropertyTextShadow,
333 CSSPropertyTextTransform,
334 CSSPropertyTextUnderlinePosition,
335 CSSPropertyTop,
336#if ENABLE(POINTER_EVENTS)
337 CSSPropertyTouchAction,
338#endif
339 CSSPropertyTransform,
340 CSSPropertyTransformBox,
341 CSSPropertyTransformOrigin,
342 CSSPropertyTransformStyle,
343 CSSPropertyTransitionDelay,
344 CSSPropertyTransitionDuration,
345 CSSPropertyTransitionProperty,
346 CSSPropertyTransitionTimingFunction,
347 CSSPropertyUnicodeBidi,
348 CSSPropertyVectorEffect,
349 CSSPropertyVerticalAlign,
350 CSSPropertyVisibility,
351 CSSPropertyWhiteSpace,
352 CSSPropertyWidows,
353 CSSPropertyWidth,
354 CSSPropertyWillChange,
355 CSSPropertyWordBreak,
356 CSSPropertyWordSpacing,
357 CSSPropertyWordWrap,
358 CSSPropertyWritingMode,
359 CSSPropertyX,
360 CSSPropertyY,
361 CSSPropertyZIndex,
362 CSSPropertyZoom,
363 CSSPropertyAppleColorFilter,
364 CSSPropertyWebkitAppearance,
365#if ENABLE(FILTERS_LEVEL_2)
366 CSSPropertyWebkitBackdropFilter,
367#endif
368 CSSPropertyWebkitBackfaceVisibility,
369 CSSPropertyWebkitBackgroundClip,
370 CSSPropertyWebkitBackgroundComposite,
371 CSSPropertyWebkitBackgroundOrigin,
372 CSSPropertyWebkitBackgroundSize,
373 CSSPropertyWebkitBorderFit,
374 CSSPropertyWebkitBorderHorizontalSpacing,
375 CSSPropertyWebkitBorderImage,
376 CSSPropertyWebkitBorderVerticalSpacing,
377 CSSPropertyWebkitBoxAlign,
378#if ENABLE(CSS_BOX_DECORATION_BREAK)
379 CSSPropertyWebkitBoxDecorationBreak,
380#endif
381 CSSPropertyWebkitBoxDirection,
382 CSSPropertyWebkitBoxFlex,
383 CSSPropertyWebkitBoxFlexGroup,
384 CSSPropertyWebkitBoxLines,
385 CSSPropertyWebkitBoxOrdinalGroup,
386 CSSPropertyWebkitBoxOrient,
387 CSSPropertyWebkitBoxPack,
388 CSSPropertyWebkitBoxReflect,
389 CSSPropertyWebkitBoxShadow,
390 CSSPropertyWebkitClipPath,
391 CSSPropertyWebkitColumnAxis,
392 CSSPropertyWebkitColumnBreakAfter,
393 CSSPropertyWebkitColumnBreakBefore,
394 CSSPropertyWebkitColumnBreakInside,
395 CSSPropertyWebkitColumnProgression,
396#if ENABLE(CURSOR_VISIBILITY)
397 CSSPropertyWebkitCursorVisibility,
398#endif
399 CSSPropertyWebkitFontKerning,
400 CSSPropertyWebkitFontSmoothing,
401 CSSPropertyWebkitHyphenateCharacter,
402 CSSPropertyWebkitHyphenateLimitAfter,
403 CSSPropertyWebkitHyphenateLimitBefore,
404 CSSPropertyWebkitHyphenateLimitLines,
405 CSSPropertyWebkitHyphens,
406 CSSPropertyWebkitInitialLetter,
407 CSSPropertyWebkitLineAlign,
408 CSSPropertyWebkitLineBoxContain,
409 CSSPropertyWebkitLineClamp,
410 CSSPropertyWebkitLineGrid,
411 CSSPropertyWebkitLineSnap,
412 CSSPropertyWebkitLocale,
413 CSSPropertyWebkitMarginAfterCollapse,
414 CSSPropertyWebkitMarginBeforeCollapse,
415 CSSPropertyWebkitMarqueeDirection,
416 CSSPropertyWebkitMarqueeIncrement,
417 CSSPropertyWebkitMarqueeRepetition,
418 CSSPropertyWebkitMarqueeStyle,
419 CSSPropertyWebkitMaskBoxImage,
420 CSSPropertyWebkitMaskBoxImageOutset,
421 CSSPropertyWebkitMaskBoxImageRepeat,
422 CSSPropertyWebkitMaskBoxImageSlice,
423 CSSPropertyWebkitMaskBoxImageSource,
424 CSSPropertyWebkitMaskBoxImageWidth,
425 CSSPropertyWebkitMaskClip,
426 CSSPropertyWebkitMaskComposite,
427 CSSPropertyWebkitMaskImage,
428 CSSPropertyWebkitMaskOrigin,
429 CSSPropertyWebkitMaskPosition,
430 CSSPropertyWebkitMaskRepeat,
431 CSSPropertyWebkitMaskSize,
432 CSSPropertyWebkitMaskSourceType,
433 CSSPropertyWebkitNbspMode,
434#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
435 CSSPropertyWebkitOverflowScrolling,
436#endif
437 CSSPropertyWebkitPrintColorAdjust,
438 CSSPropertyWebkitRtlOrdering,
439#if ENABLE(TOUCH_EVENTS)
440 CSSPropertyWebkitTapHighlightColor,
441#endif
442#if ENABLE(CSS3_TEXT)
443 CSSPropertyWebkitTextAlignLast,
444#endif
445 CSSPropertyWebkitTextCombine,
446 CSSPropertyWebkitTextDecorationsInEffect,
447 CSSPropertyWebkitTextEmphasisColor,
448 CSSPropertyWebkitTextEmphasisPosition,
449 CSSPropertyWebkitTextEmphasisStyle,
450 CSSPropertyWebkitTextFillColor,
451#if ENABLE(CSS3_TEXT)
452 CSSPropertyWebkitTextJustify,
453#endif
454 CSSPropertyWebkitTextOrientation,
455 CSSPropertyWebkitTextSecurity,
456#if ENABLE(TEXT_AUTOSIZING)
457 CSSPropertyWebkitTextSizeAdjust,
458#endif
459 CSSPropertyWebkitTextStrokeColor,
460 CSSPropertyWebkitTextStrokeWidth,
461 CSSPropertyWebkitTextZoom,
462#if PLATFORM(IOS_FAMILY)
463 CSSPropertyWebkitTouchCallout,
464#endif
465 CSSPropertyWebkitTransformStyle,
466 CSSPropertyWebkitUserDrag,
467 CSSPropertyWebkitUserModify,
468 CSSPropertyWebkitUserSelect,
469};
470
471const unsigned numComputedProperties = WTF_ARRAY_LENGTH(computedProperties);
472
473static CSSValueID valueForRepeatRule(int rule)
474{
475 switch (rule) {
476 case RepeatImageRule:
477 return CSSValueRepeat;
478 case RoundImageRule:
479 return CSSValueRound;
480 case SpaceImageRule:
481 return CSSValueSpace;
482 default:
483 return CSSValueStretch;
484 }
485}
486
487static Ref<CSSPrimitiveValue> valueForImageSliceSide(const Length& length)
488{
489 // These values can be percentages, numbers, or while an animation of mixed types is in progress,
490 // a calculation that combines a percentage and a number.
491 if (length.isPercent())
492 return CSSValuePool::singleton().createValue(length.percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
493 if (length.isFixed())
494 return CSSValuePool::singleton().createValue(length.value(), CSSPrimitiveValue::CSS_NUMBER);
495
496 // Calculating the actual length currently in use would require most of the code from RenderBoxModelObject::paintNinePieceImage.
497 // And even if we could do that, it's not clear if that's exactly what we'd want during animation.
498 // FIXME: For now, just return 0.
499 ASSERT(length.isCalculated());
500 return CSSValuePool::singleton().createValue(0, CSSPrimitiveValue::CSS_NUMBER);
501}
502
503static Ref<CSSBorderImageSliceValue> valueForNinePieceImageSlice(const NinePieceImage& image)
504{
505 auto& slices = image.imageSlices();
506
507 RefPtr<CSSPrimitiveValue> top = valueForImageSliceSide(slices.top());
508
509 RefPtr<CSSPrimitiveValue> right;
510 RefPtr<CSSPrimitiveValue> bottom;
511 RefPtr<CSSPrimitiveValue> left;
512
513 if (slices.right() == slices.top() && slices.bottom() == slices.top() && slices.left() == slices.top()) {
514 right = top;
515 bottom = top;
516 left = top;
517 } else {
518 right = valueForImageSliceSide(slices.right());
519
520 if (slices.bottom() == slices.top() && slices.right() == slices.left()) {
521 bottom = top;
522 left = right;
523 } else {
524 bottom = valueForImageSliceSide(slices.bottom());
525
526 if (slices.left() == slices.right())
527 left = right;
528 else
529 left = valueForImageSliceSide(slices.left());
530 }
531 }
532
533 auto quad = Quad::create();
534 quad->setTop(WTFMove(top));
535 quad->setRight(WTFMove(right));
536 quad->setBottom(WTFMove(bottom));
537 quad->setLeft(WTFMove(left));
538
539 return CSSBorderImageSliceValue::create(CSSValuePool::singleton().createValue(WTFMove(quad)), image.fill());
540}
541
542static Ref<CSSPrimitiveValue> valueForNinePieceImageQuad(const LengthBox& box)
543{
544 RefPtr<CSSPrimitiveValue> top;
545 RefPtr<CSSPrimitiveValue> right;
546 RefPtr<CSSPrimitiveValue> bottom;
547 RefPtr<CSSPrimitiveValue> left;
548
549 auto& cssValuePool = CSSValuePool::singleton();
550
551 if (box.top().isRelative())
552 top = cssValuePool.createValue(box.top().value(), CSSPrimitiveValue::CSS_NUMBER);
553 else
554 top = cssValuePool.createValue(box.top());
555
556 if (box.right() == box.top() && box.bottom() == box.top() && box.left() == box.top()) {
557 right = top;
558 bottom = top;
559 left = top;
560 } else {
561 if (box.right().isRelative())
562 right = cssValuePool.createValue(box.right().value(), CSSPrimitiveValue::CSS_NUMBER);
563 else
564 right = cssValuePool.createValue(box.right());
565
566 if (box.bottom() == box.top() && box.right() == box.left()) {
567 bottom = top;
568 left = right;
569 } else {
570 if (box.bottom().isRelative())
571 bottom = cssValuePool.createValue(box.bottom().value(), CSSPrimitiveValue::CSS_NUMBER);
572 else
573 bottom = cssValuePool.createValue(box.bottom());
574
575 if (box.left() == box.right())
576 left = right;
577 else {
578 if (box.left().isRelative())
579 left = cssValuePool.createValue(box.left().value(), CSSPrimitiveValue::CSS_NUMBER);
580 else
581 left = cssValuePool.createValue(box.left());
582 }
583 }
584 }
585
586 auto quad = Quad::create();
587 quad->setTop(WTFMove(top));
588 quad->setRight(WTFMove(right));
589 quad->setBottom(WTFMove(bottom));
590 quad->setLeft(WTFMove(left));
591
592 return cssValuePool.createValue(WTFMove(quad));
593}
594
595static Ref<CSSValue> valueForNinePieceImageRepeat(const NinePieceImage& image)
596{
597 auto& cssValuePool = CSSValuePool::singleton();
598 auto horizontalRepeat = cssValuePool.createIdentifierValue(valueForRepeatRule(image.horizontalRule()));
599 RefPtr<CSSPrimitiveValue> verticalRepeat;
600 if (image.horizontalRule() == image.verticalRule())
601 verticalRepeat = horizontalRepeat.copyRef();
602 else
603 verticalRepeat = cssValuePool.createIdentifierValue(valueForRepeatRule(image.verticalRule()));
604 return cssValuePool.createValue(Pair::create(WTFMove(horizontalRepeat), WTFMove(verticalRepeat)));
605}
606
607static Ref<CSSValue> valueForNinePieceImage(const NinePieceImage& image)
608{
609 if (!image.hasImage())
610 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
611
612 // Image first.
613 RefPtr<CSSValue> imageValue;
614 if (image.image())
615 imageValue = image.image()->cssValue();
616
617 // Create the image slice.
618 RefPtr<CSSBorderImageSliceValue> imageSlices = valueForNinePieceImageSlice(image);
619
620 // Create the border area slices.
621 RefPtr<CSSValue> borderSlices = valueForNinePieceImageQuad(image.borderSlices());
622
623 // Create the border outset.
624 RefPtr<CSSValue> outset = valueForNinePieceImageQuad(image.outset());
625
626 // Create the repeat rules.
627 RefPtr<CSSValue> repeat = valueForNinePieceImageRepeat(image);
628
629 return createBorderImageValue(WTFMove(imageValue), WTFMove(imageSlices), WTFMove(borderSlices), WTFMove(outset), WTFMove(repeat));
630}
631
632inline static Ref<CSSPrimitiveValue> zoomAdjustedPixelValue(double value, const RenderStyle& style)
633{
634 return CSSValuePool::singleton().createValue(adjustFloatForAbsoluteZoom(value, style), CSSPrimitiveValue::CSS_PX);
635}
636
637inline static Ref<CSSPrimitiveValue> zoomAdjustedNumberValue(double value, const RenderStyle& style)
638{
639 return CSSValuePool::singleton().createValue(value / style.effectiveZoom(), CSSPrimitiveValue::CSS_NUMBER);
640}
641
642static Ref<CSSValue> zoomAdjustedPixelValueForLength(const Length& length, const RenderStyle& style)
643{
644 if (length.isFixed())
645 return zoomAdjustedPixelValue(length.value(), style);
646 return CSSValuePool::singleton().createValue(length, style);
647}
648
649static Ref<CSSValue> valueForReflection(const StyleReflection* reflection, const RenderStyle& style)
650{
651 if (!reflection)
652 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
653
654 RefPtr<CSSPrimitiveValue> offset;
655 if (reflection->offset().isPercentOrCalculated())
656 offset = CSSValuePool::singleton().createValue(reflection->offset().percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
657 else
658 offset = zoomAdjustedPixelValue(reflection->offset().value(), style);
659
660 RefPtr<CSSPrimitiveValue> direction;
661 switch (reflection->direction()) {
662 case ReflectionBelow:
663 direction = CSSValuePool::singleton().createIdentifierValue(CSSValueBelow);
664 break;
665 case ReflectionAbove:
666 direction = CSSValuePool::singleton().createIdentifierValue(CSSValueAbove);
667 break;
668 case ReflectionLeft:
669 direction = CSSValuePool::singleton().createIdentifierValue(CSSValueLeft);
670 break;
671 case ReflectionRight:
672 direction = CSSValuePool::singleton().createIdentifierValue(CSSValueRight);
673 break;
674 }
675
676 return CSSReflectValue::create(direction.releaseNonNull(), offset.releaseNonNull(), valueForNinePieceImage(reflection->mask()));
677}
678
679static Ref<CSSValueList> createPositionListForLayer(CSSPropertyID propertyID, const FillLayer& layer, const RenderStyle& style)
680{
681 auto list = CSSValueList::createSpaceSeparated();
682 if (layer.isBackgroundXOriginSet()) {
683 ASSERT_UNUSED(propertyID, propertyID == CSSPropertyBackgroundPosition || propertyID == CSSPropertyWebkitMaskPosition);
684 list->append(CSSValuePool::singleton().createValue(layer.backgroundXOrigin()));
685 }
686 list->append(zoomAdjustedPixelValueForLength(layer.xPosition(), style));
687 if (layer.isBackgroundYOriginSet()) {
688 ASSERT(propertyID == CSSPropertyBackgroundPosition || propertyID == CSSPropertyWebkitMaskPosition);
689 list->append(CSSValuePool::singleton().createValue(layer.backgroundYOrigin()));
690 }
691 list->append(zoomAdjustedPixelValueForLength(layer.yPosition(), style));
692 return list;
693}
694
695static Length getOffsetComputedLength(const RenderStyle& style, CSSPropertyID propertyID)
696{
697 // If specified as a length, the corresponding absolute length; if specified as
698 // a percentage, the specified value; otherwise, 'auto'. Hence, we can just
699 // return the value in the style.
700 //
701 // See http://www.w3.org/TR/CSS21/cascade.html#computed-value
702 switch (propertyID) {
703 case CSSPropertyLeft:
704 return style.left();
705 case CSSPropertyRight:
706 return style.right();
707 case CSSPropertyTop:
708 return style.top();
709 case CSSPropertyBottom:
710 return style.bottom();
711 default:
712 ASSERT_NOT_REACHED();
713 }
714
715 return { };
716}
717
718static LayoutUnit getOffsetUsedStyleRelative(RenderBox& box, CSSPropertyID propertyID)
719{
720 // For relatively positioned boxes, the offset is with respect to the top edges
721 // of the box itself. This ties together top/bottom and left/right to be
722 // opposites of each other.
723 //
724 // See http://www.w3.org/TR/CSS2/visuren.html#relative-positioning
725 //
726 // Specifically;
727 // Since boxes are not split or stretched as a result of 'left' or
728 // 'right', the used values are always: left = -right.
729 // and
730 // Since boxes are not split or stretched as a result of 'top' or
731 // 'bottom', the used values are always: top = -bottom.
732 switch (propertyID) {
733 case CSSPropertyTop:
734 return box.relativePositionOffset().height();
735 case CSSPropertyBottom:
736 return -(box.relativePositionOffset().height());
737 case CSSPropertyLeft:
738 return box.relativePositionOffset().width();
739 case CSSPropertyRight:
740 return -(box.relativePositionOffset().width());
741 default:
742 ASSERT_NOT_REACHED();
743 }
744
745 return 0;
746}
747
748static LayoutUnit getOffsetUsedStyleOutOfFlowPositioned(RenderBlock& container, RenderBox& box, CSSPropertyID propertyID)
749{
750 // For out-of-flow positioned boxes, the offset is how far an box's margin
751 // edge is offset below the edge of the box's containing block.
752 // See http://www.w3.org/TR/CSS2/visuren.html#position-props
753
754 // Margins are included in offsetTop/offsetLeft so we need to remove them here.
755 switch (propertyID) {
756 case CSSPropertyTop:
757 return box.offsetTop() - box.marginTop();
758 case CSSPropertyBottom:
759 return container.clientHeight() - (box.offsetTop() + box.offsetHeight()) - box.marginBottom();
760 case CSSPropertyLeft:
761 return box.offsetLeft() - box.marginLeft();
762 case CSSPropertyRight:
763 return container.clientWidth() - (box.offsetLeft() + box.offsetWidth()) - box.marginRight();
764 default:
765 ASSERT_NOT_REACHED();
766 }
767
768 return 0;
769}
770
771static RefPtr<CSSValue> positionOffsetValue(const RenderStyle& style, CSSPropertyID propertyID, RenderObject* renderer)
772{
773 auto offset = getOffsetComputedLength(style, propertyID);
774
775 // If the element is not displayed; return the "computed value".
776 if (!renderer || !renderer->isBox())
777 return zoomAdjustedPixelValueForLength(offset, style);
778
779 auto& box = downcast<RenderBox>(*renderer);
780 auto* containingBlock = box.containingBlock();
781
782 // Resolve a "computed value" percentage if the element is positioned.
783 if (containingBlock && offset.isPercentOrCalculated() && box.isPositioned()) {
784 bool isVerticalProperty;
785 if (propertyID == CSSPropertyTop || propertyID == CSSPropertyBottom)
786 isVerticalProperty = true;
787 else {
788 ASSERT(propertyID == CSSPropertyLeft || propertyID == CSSPropertyRight);
789 isVerticalProperty = false;
790 }
791 LayoutUnit containingBlockSize;
792 if (box.isStickilyPositioned()) {
793 const RenderBox& enclosingScrollportBox =
794 box.enclosingScrollportBox();
795 if (isVerticalProperty == enclosingScrollportBox.isHorizontalWritingMode())
796 containingBlockSize = enclosingScrollportBox.contentLogicalHeight();
797 else
798 containingBlockSize = enclosingScrollportBox.contentLogicalWidth();
799 } else {
800 if (isVerticalProperty == containingBlock->isHorizontalWritingMode()) {
801 containingBlockSize = box.isOutOfFlowPositioned()
802 ? box.containingBlockLogicalHeightForPositioned(*containingBlock, false)
803 : box.containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding);
804 } else {
805 containingBlockSize = box.isOutOfFlowPositioned()
806 ? box.containingBlockLogicalWidthForPositioned(*containingBlock, nullptr, false)
807 : box.containingBlockLogicalWidthForContent();
808 }
809 }
810 return zoomAdjustedPixelValue(floatValueForLength(offset, containingBlockSize), style);
811 }
812
813 // Return a "computed value" length.
814 if (!offset.isAuto())
815 return zoomAdjustedPixelValueForLength(offset, style);
816
817 // The property won't be overconstrained if its computed value is "auto", so the "used value" can be returned.
818 if (box.isRelativelyPositioned())
819 return zoomAdjustedPixelValue(getOffsetUsedStyleRelative(box, propertyID), style);
820
821 if (containingBlock && box.isOutOfFlowPositioned())
822 return zoomAdjustedPixelValue(getOffsetUsedStyleOutOfFlowPositioned(*containingBlock, box, propertyID), style);
823
824 return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
825}
826
827Ref<CSSPrimitiveValue> ComputedStyleExtractor::currentColorOrValidColor(const RenderStyle* style, const Color& color) const
828{
829 // This function does NOT look at visited information, so that computed style doesn't expose that.
830 if (!color.isValid())
831 return CSSValuePool::singleton().createColorValue(style->color());
832 return CSSValuePool::singleton().createColorValue(color);
833}
834
835static Ref<CSSPrimitiveValue> percentageOrZoomAdjustedValue(Length length, const RenderStyle& style)
836{
837 if (length.isPercent())
838 return CSSValuePool::singleton().createValue(length.percent(), CSSPrimitiveValue::CSS_PERCENTAGE);
839
840 return zoomAdjustedPixelValue(valueForLength(length, 0), style);
841}
842
843static Ref<CSSPrimitiveValue> autoOrZoomAdjustedValue(Length length, const RenderStyle& style)
844{
845 if (length.isAuto())
846 return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
847
848 return zoomAdjustedPixelValue(valueForLength(length, 0), style);
849}
850
851static Ref<CSSValueList> borderRadiusCornerValues(const LengthSize& radius, const RenderStyle& style)
852{
853 auto list = CSSValueList::createSpaceSeparated();
854 list->append(percentageOrZoomAdjustedValue(radius.width, style));
855 list->append(percentageOrZoomAdjustedValue(radius.height, style));
856 return list;
857}
858
859static Ref<CSSValue> borderRadiusCornerValue(const LengthSize& radius, const RenderStyle& style)
860{
861 if (radius.width == radius.height)
862 return percentageOrZoomAdjustedValue(radius.width, style);
863 return borderRadiusCornerValues(radius, style);
864}
865
866static Ref<CSSValueList> borderRadiusShorthandValue(const RenderStyle& style)
867{
868 auto list = CSSValueList::createSlashSeparated();
869 bool showHorizontalBottomLeft = style.borderTopRightRadius().width != style.borderBottomLeftRadius().width;
870 bool showHorizontalBottomRight = showHorizontalBottomLeft || (style.borderBottomRightRadius().width != style.borderTopLeftRadius().width);
871 bool showHorizontalTopRight = showHorizontalBottomRight || (style.borderTopRightRadius().width != style.borderTopLeftRadius().width);
872
873 bool showVerticalBottomLeft = style.borderTopRightRadius().height != style.borderBottomLeftRadius().height;
874 bool showVerticalBottomRight = showVerticalBottomLeft || (style.borderBottomRightRadius().height != style.borderTopLeftRadius().height);
875 bool showVerticalTopRight = showVerticalBottomRight || (style.borderTopRightRadius().height != style.borderTopLeftRadius().height);
876
877 auto topLeftRadius = borderRadiusCornerValues(style.borderTopLeftRadius(), style);
878 auto topRightRadius = borderRadiusCornerValues(style.borderTopRightRadius(), style);
879 auto bottomRightRadius = borderRadiusCornerValues(style.borderBottomRightRadius(), style);
880 auto bottomLeftRadius = borderRadiusCornerValues(style.borderBottomLeftRadius(), style);
881
882 auto horizontalRadii = CSSValueList::createSpaceSeparated();
883 horizontalRadii->append(*topLeftRadius->item(0));
884 if (showHorizontalTopRight)
885 horizontalRadii->append(*topRightRadius->item(0));
886 if (showHorizontalBottomRight)
887 horizontalRadii->append(*bottomRightRadius->item(0));
888 if (showHorizontalBottomLeft)
889 horizontalRadii->append(*bottomLeftRadius->item(0));
890
891 list->append(WTFMove(horizontalRadii));
892
893 auto verticalRadiiList = CSSValueList::createSpaceSeparated();
894 verticalRadiiList->append(*topLeftRadius->item(1));
895 if (showVerticalTopRight)
896 verticalRadiiList->append(*topRightRadius->item(1));
897 if (showVerticalBottomRight)
898 verticalRadiiList->append(*bottomRightRadius->item(1));
899 if (showVerticalBottomLeft)
900 verticalRadiiList->append(*bottomLeftRadius->item(1));
901
902 if (!verticalRadiiList->equals(downcast<CSSValueList>(*list->item(0))))
903 list->append(WTFMove(verticalRadiiList));
904
905 return list;
906}
907
908static LayoutRect sizingBox(RenderObject& renderer)
909{
910 if (!is<RenderBox>(renderer))
911 return LayoutRect();
912
913 auto& box = downcast<RenderBox>(renderer);
914 return box.style().boxSizing() == BoxSizing::BorderBox ? box.borderBoxRect() : box.computedCSSContentBoxRect();
915}
916
917static Ref<CSSFunctionValue> matrixTransformValue(const TransformationMatrix& transform, const RenderStyle& style)
918{
919 RefPtr<CSSFunctionValue> transformValue;
920 auto& cssValuePool = CSSValuePool::singleton();
921 if (transform.isAffine()) {
922 transformValue = CSSFunctionValue::create(CSSValueMatrix);
923
924 transformValue->append(cssValuePool.createValue(transform.a(), CSSPrimitiveValue::CSS_NUMBER));
925 transformValue->append(cssValuePool.createValue(transform.b(), CSSPrimitiveValue::CSS_NUMBER));
926 transformValue->append(cssValuePool.createValue(transform.c(), CSSPrimitiveValue::CSS_NUMBER));
927 transformValue->append(cssValuePool.createValue(transform.d(), CSSPrimitiveValue::CSS_NUMBER));
928 transformValue->append(zoomAdjustedNumberValue(transform.e(), style));
929 transformValue->append(zoomAdjustedNumberValue(transform.f(), style));
930 } else {
931 transformValue = CSSFunctionValue::create(CSSValueMatrix3d);
932
933 transformValue->append(cssValuePool.createValue(transform.m11(), CSSPrimitiveValue::CSS_NUMBER));
934 transformValue->append(cssValuePool.createValue(transform.m12(), CSSPrimitiveValue::CSS_NUMBER));
935 transformValue->append(cssValuePool.createValue(transform.m13(), CSSPrimitiveValue::CSS_NUMBER));
936 transformValue->append(cssValuePool.createValue(transform.m14(), CSSPrimitiveValue::CSS_NUMBER));
937
938 transformValue->append(cssValuePool.createValue(transform.m21(), CSSPrimitiveValue::CSS_NUMBER));
939 transformValue->append(cssValuePool.createValue(transform.m22(), CSSPrimitiveValue::CSS_NUMBER));
940 transformValue->append(cssValuePool.createValue(transform.m23(), CSSPrimitiveValue::CSS_NUMBER));
941 transformValue->append(cssValuePool.createValue(transform.m24(), CSSPrimitiveValue::CSS_NUMBER));
942
943 transformValue->append(cssValuePool.createValue(transform.m31(), CSSPrimitiveValue::CSS_NUMBER));
944 transformValue->append(cssValuePool.createValue(transform.m32(), CSSPrimitiveValue::CSS_NUMBER));
945 transformValue->append(cssValuePool.createValue(transform.m33(), CSSPrimitiveValue::CSS_NUMBER));
946 transformValue->append(cssValuePool.createValue(transform.m34(), CSSPrimitiveValue::CSS_NUMBER));
947
948 transformValue->append(zoomAdjustedNumberValue(transform.m41(), style));
949 transformValue->append(zoomAdjustedNumberValue(transform.m42(), style));
950 transformValue->append(zoomAdjustedNumberValue(transform.m43(), style));
951 transformValue->append(cssValuePool.createValue(transform.m44(), CSSPrimitiveValue::CSS_NUMBER));
952 }
953
954 return transformValue.releaseNonNull();
955}
956
957static Ref<CSSValue> computedTransform(RenderObject* renderer, const RenderStyle& style)
958{
959 // Inline renderers do not support transforms.
960 if (!renderer || is<RenderInline>(*renderer) || !style.hasTransform())
961 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
962
963 FloatRect pixelSnappedRect;
964 if (is<RenderBox>(*renderer))
965 pixelSnappedRect = snapRectToDevicePixels(downcast<RenderBox>(*renderer).borderBoxRect(), renderer->document().deviceScaleFactor());
966
967 TransformationMatrix transform;
968 style.applyTransform(transform, pixelSnappedRect, RenderStyle::ExcludeTransformOrigin);
969 // Note that this does not flatten to an affine transform if ENABLE(3D_TRANSFORMS) is off, by design.
970
971 // FIXME: Need to print out individual functions (https://bugs.webkit.org/show_bug.cgi?id=23924)
972 auto list = CSSValueList::createSpaceSeparated();
973 list->append(matrixTransformValue(transform, style));
974 return list;
975}
976
977static inline Ref<CSSPrimitiveValue> adjustLengthForZoom(double length, const RenderStyle& style, AdjustPixelValuesForComputedStyle adjust)
978{
979 return adjust == AdjustPixelValues ? zoomAdjustedPixelValue(length, style) : CSSValuePool::singleton().createValue(length, CSSPrimitiveValue::CSS_PX);
980}
981
982static inline Ref<CSSPrimitiveValue> adjustLengthForZoom(const Length& length, const RenderStyle& style, AdjustPixelValuesForComputedStyle adjust)
983{
984 return adjust == AdjustPixelValues ? zoomAdjustedPixelValue(length.value(), style) : CSSValuePool::singleton().createValue(length);
985}
986
987Ref<CSSValue> ComputedStyleExtractor::valueForShadow(const ShadowData* shadow, CSSPropertyID propertyID, const RenderStyle& style, AdjustPixelValuesForComputedStyle adjust)
988{
989 auto& cssValuePool = CSSValuePool::singleton();
990 if (!shadow)
991 return cssValuePool.createIdentifierValue(CSSValueNone);
992
993 auto list = CSSValueList::createCommaSeparated();
994 for (const ShadowData* currShadowData = shadow; currShadowData; currShadowData = currShadowData->next()) {
995 auto x = adjustLengthForZoom(currShadowData->x(), style, adjust);
996 auto y = adjustLengthForZoom(currShadowData->y(), style, adjust);
997 auto blur = adjustLengthForZoom(currShadowData->radius(), style, adjust);
998 auto spread = propertyID == CSSPropertyTextShadow ? RefPtr<CSSPrimitiveValue>() : adjustLengthForZoom(currShadowData->spread(), style, adjust);
999 auto style = propertyID == CSSPropertyTextShadow || currShadowData->style() == Normal ? RefPtr<CSSPrimitiveValue>() : cssValuePool.createIdentifierValue(CSSValueInset);
1000 auto color = cssValuePool.createColorValue(currShadowData->color());
1001 list->prepend(CSSShadowValue::create(WTFMove(x), WTFMove(y), WTFMove(blur), WTFMove(spread), WTFMove(style), WTFMove(color)));
1002 }
1003 return list;
1004}
1005
1006Ref<CSSValue> ComputedStyleExtractor::valueForFilter(const RenderStyle& style, const FilterOperations& filterOperations, AdjustPixelValuesForComputedStyle adjust)
1007{
1008 auto& cssValuePool = CSSValuePool::singleton();
1009 if (filterOperations.operations().isEmpty())
1010 return cssValuePool.createIdentifierValue(CSSValueNone);
1011
1012 auto list = CSSValueList::createSpaceSeparated();
1013
1014 Vector<RefPtr<FilterOperation>>::const_iterator end = filterOperations.operations().end();
1015 for (Vector<RefPtr<FilterOperation>>::const_iterator it = filterOperations.operations().begin(); it != end; ++it) {
1016 FilterOperation& filterOperation = **it;
1017
1018 if (filterOperation.type() == FilterOperation::REFERENCE) {
1019 ReferenceFilterOperation& referenceOperation = downcast<ReferenceFilterOperation>(filterOperation);
1020 list->append(cssValuePool.createValue(referenceOperation.url(), CSSPrimitiveValue::CSS_URI));
1021 } else {
1022 RefPtr<CSSFunctionValue> filterValue;
1023 switch (filterOperation.type()) {
1024 case FilterOperation::GRAYSCALE: {
1025 filterValue = CSSFunctionValue::create(CSSValueGrayscale);
1026 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
1027 break;
1028 }
1029 case FilterOperation::SEPIA: {
1030 filterValue = CSSFunctionValue::create(CSSValueSepia);
1031 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
1032 break;
1033 }
1034 case FilterOperation::SATURATE: {
1035 filterValue = CSSFunctionValue::create(CSSValueSaturate);
1036 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
1037 break;
1038 }
1039 case FilterOperation::HUE_ROTATE: {
1040 filterValue = CSSFunctionValue::create(CSSValueHueRotate);
1041 filterValue->append(cssValuePool.createValue(downcast<BasicColorMatrixFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_DEG));
1042 break;
1043 }
1044 case FilterOperation::INVERT: {
1045 filterValue = CSSFunctionValue::create(CSSValueInvert);
1046 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
1047 break;
1048 }
1049 case FilterOperation::APPLE_INVERT_LIGHTNESS: {
1050 filterValue = CSSFunctionValue::create(CSSValueAppleInvertLightness);
1051 break;
1052 }
1053 case FilterOperation::OPACITY: {
1054 filterValue = CSSFunctionValue::create(CSSValueOpacity);
1055 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
1056 break;
1057 }
1058 case FilterOperation::BRIGHTNESS: {
1059 filterValue = CSSFunctionValue::create(CSSValueBrightness);
1060 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
1061 break;
1062 }
1063 case FilterOperation::CONTRAST: {
1064 filterValue = CSSFunctionValue::create(CSSValueContrast);
1065 filterValue->append(cssValuePool.createValue(downcast<BasicComponentTransferFilterOperation>(filterOperation).amount(), CSSPrimitiveValue::CSS_NUMBER));
1066 break;
1067 }
1068 case FilterOperation::BLUR: {
1069 filterValue = CSSFunctionValue::create(CSSValueBlur);
1070 filterValue->append(adjustLengthForZoom(downcast<BlurFilterOperation>(filterOperation).stdDeviation(), style, adjust));
1071 break;
1072 }
1073 case FilterOperation::DROP_SHADOW: {
1074 DropShadowFilterOperation& dropShadowOperation = downcast<DropShadowFilterOperation>(filterOperation);
1075 filterValue = CSSFunctionValue::create(CSSValueDropShadow);
1076 // We want our computed style to look like that of a text shadow (has neither spread nor inset style).
1077 ShadowData shadowData = ShadowData(dropShadowOperation.location(), dropShadowOperation.stdDeviation(), 0, Normal, false, dropShadowOperation.color());
1078 filterValue->append(valueForShadow(&shadowData, CSSPropertyTextShadow, style, adjust));
1079 break;
1080 }
1081 default:
1082 ASSERT_NOT_REACHED();
1083 filterValue = CSSFunctionValue::create(CSSValueInvalid);
1084 break;
1085 }
1086 list->append(filterValue.releaseNonNull());
1087 }
1088 }
1089 return list;
1090}
1091
1092static Ref<CSSValue> specifiedValueForGridTrackBreadth(const GridLength& trackBreadth, const RenderStyle& style)
1093{
1094 if (!trackBreadth.isLength())
1095 return CSSValuePool::singleton().createValue(trackBreadth.flex(), CSSPrimitiveValue::CSS_FR);
1096
1097 const Length& trackBreadthLength = trackBreadth.length();
1098 if (trackBreadthLength.isAuto())
1099 return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1100 return zoomAdjustedPixelValueForLength(trackBreadthLength, style);
1101}
1102
1103static Ref<CSSValue> specifiedValueForGridTrackSize(const GridTrackSize& trackSize, const RenderStyle& style)
1104{
1105 switch (trackSize.type()) {
1106 case LengthTrackSizing:
1107 return specifiedValueForGridTrackBreadth(trackSize.minTrackBreadth(), style);
1108 case FitContentTrackSizing: {
1109 auto fitContentTrackSize = CSSFunctionValue::create(CSSValueFitContent);
1110 fitContentTrackSize->append(zoomAdjustedPixelValueForLength(trackSize.fitContentTrackBreadth().length(), style));
1111 return fitContentTrackSize;
1112 }
1113 default:
1114 ASSERT(trackSize.type() == MinMaxTrackSizing);
1115 if (trackSize.minTrackBreadth().isAuto() && trackSize.maxTrackBreadth().isFlex())
1116 return CSSValuePool::singleton().createValue(trackSize.maxTrackBreadth().flex(), CSSPrimitiveValue::CSS_FR);
1117
1118 auto minMaxTrackBreadths = CSSFunctionValue::create(CSSValueMinmax);
1119 minMaxTrackBreadths->append(specifiedValueForGridTrackBreadth(trackSize.minTrackBreadth(), style));
1120 minMaxTrackBreadths->append(specifiedValueForGridTrackBreadth(trackSize.maxTrackBreadth(), style));
1121 return minMaxTrackBreadths;
1122 }
1123}
1124
1125class OrderedNamedLinesCollector {
1126 WTF_MAKE_NONCOPYABLE(OrderedNamedLinesCollector);
1127public:
1128 OrderedNamedLinesCollector(const RenderStyle& style, bool isRowAxis, unsigned autoRepeatTracksCount)
1129 : m_orderedNamedGridLines(isRowAxis ? style.orderedNamedGridColumnLines() : style.orderedNamedGridRowLines())
1130 , m_orderedNamedAutoRepeatGridLines(isRowAxis ? style.autoRepeatOrderedNamedGridColumnLines() : style.autoRepeatOrderedNamedGridRowLines())
1131 , m_insertionPoint(isRowAxis ? style.gridAutoRepeatColumnsInsertionPoint() : style.gridAutoRepeatRowsInsertionPoint())
1132 , m_autoRepeatTotalTracks(autoRepeatTracksCount)
1133 , m_autoRepeatTrackListLength(isRowAxis ? style.gridAutoRepeatColumns().size() : style.gridAutoRepeatRows().size())
1134 {
1135 }
1136
1137 bool isEmpty() const { return m_orderedNamedGridLines.isEmpty() && m_orderedNamedAutoRepeatGridLines.isEmpty(); }
1138 void collectLineNamesForIndex(CSSGridLineNamesValue&, unsigned index) const;
1139
1140private:
1141
1142 enum NamedLinesType { NamedLines, AutoRepeatNamedLines };
1143 void appendLines(CSSGridLineNamesValue&, unsigned index, NamedLinesType) const;
1144
1145 const OrderedNamedGridLinesMap& m_orderedNamedGridLines;
1146 const OrderedNamedGridLinesMap& m_orderedNamedAutoRepeatGridLines;
1147 unsigned m_insertionPoint;
1148 unsigned m_autoRepeatTotalTracks;
1149 unsigned m_autoRepeatTrackListLength;
1150};
1151
1152void OrderedNamedLinesCollector::appendLines(CSSGridLineNamesValue& lineNamesValue, unsigned index, NamedLinesType type) const
1153{
1154 auto iter = type == NamedLines ? m_orderedNamedGridLines.find(index) : m_orderedNamedAutoRepeatGridLines.find(index);
1155 auto endIter = type == NamedLines ? m_orderedNamedGridLines.end() : m_orderedNamedAutoRepeatGridLines.end();
1156 if (iter == endIter)
1157 return;
1158
1159 auto& cssValuePool = CSSValuePool::singleton();
1160 for (const auto& lineName : iter->value)
1161 lineNamesValue.append(cssValuePool.createValue(lineName, CSSPrimitiveValue::CSS_STRING));
1162}
1163
1164void OrderedNamedLinesCollector::collectLineNamesForIndex(CSSGridLineNamesValue& lineNamesValue, unsigned i) const
1165{
1166 ASSERT(!isEmpty());
1167 if (m_orderedNamedAutoRepeatGridLines.isEmpty() || i < m_insertionPoint) {
1168 appendLines(lineNamesValue, i, NamedLines);
1169 return;
1170 }
1171
1172 ASSERT(m_autoRepeatTotalTracks);
1173
1174 if (i > m_insertionPoint + m_autoRepeatTotalTracks) {
1175 appendLines(lineNamesValue, i - (m_autoRepeatTotalTracks - 1), NamedLines);
1176 return;
1177 }
1178
1179 if (i == m_insertionPoint) {
1180 appendLines(lineNamesValue, i, NamedLines);
1181 appendLines(lineNamesValue, 0, AutoRepeatNamedLines);
1182 return;
1183 }
1184
1185 if (i == m_insertionPoint + m_autoRepeatTotalTracks) {
1186 appendLines(lineNamesValue, m_autoRepeatTrackListLength, AutoRepeatNamedLines);
1187 appendLines(lineNamesValue, m_insertionPoint + 1, NamedLines);
1188 return;
1189 }
1190
1191 unsigned autoRepeatIndexInFirstRepetition = (i - m_insertionPoint) % m_autoRepeatTrackListLength;
1192 if (!autoRepeatIndexInFirstRepetition && i > m_insertionPoint)
1193 appendLines(lineNamesValue, m_autoRepeatTrackListLength, AutoRepeatNamedLines);
1194 appendLines(lineNamesValue, autoRepeatIndexInFirstRepetition, AutoRepeatNamedLines);
1195}
1196
1197static void addValuesForNamedGridLinesAtIndex(OrderedNamedLinesCollector& collector, unsigned i, CSSValueList& list)
1198{
1199 if (collector.isEmpty())
1200 return;
1201
1202 auto lineNames = CSSGridLineNamesValue::create();
1203 collector.collectLineNamesForIndex(lineNames.get(), i);
1204 if (lineNames->length())
1205 list.append(WTFMove(lineNames));
1206}
1207
1208static Ref<CSSValueList> valueForGridTrackSizeList(GridTrackSizingDirection direction, const RenderStyle& style)
1209{
1210 auto& autoTrackSizes = direction == ForColumns ? style.gridAutoColumns() : style.gridAutoRows();
1211
1212 auto list = CSSValueList::createSpaceSeparated();
1213 for (auto& trackSize : autoTrackSizes)
1214 list->append(specifiedValueForGridTrackSize(trackSize, style));
1215 return list;
1216}
1217
1218static Ref<CSSValue> valueForGridTrackList(GridTrackSizingDirection direction, RenderObject* renderer, const RenderStyle& style)
1219{
1220 bool isRowAxis = direction == ForColumns;
1221 bool isRenderGrid = is<RenderGrid>(renderer);
1222 auto& trackSizes = isRowAxis ? style.gridColumns() : style.gridRows();
1223 auto& autoRepeatTrackSizes = isRowAxis ? style.gridAutoRepeatColumns() : style.gridAutoRepeatRows();
1224
1225 // Handle the 'none' case.
1226 bool trackListIsEmpty = trackSizes.isEmpty() && autoRepeatTrackSizes.isEmpty();
1227 if (isRenderGrid && trackListIsEmpty) {
1228 // For grids we should consider every listed track, whether implicitly or explicitly
1229 // created. Empty grids have a sole grid line per axis.
1230 auto& grid = downcast<RenderGrid>(*renderer);
1231 auto& positions = isRowAxis ? grid.columnPositions() : grid.rowPositions();
1232 trackListIsEmpty = positions.size() == 1;
1233 }
1234
1235 if (trackListIsEmpty)
1236 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1237
1238 unsigned autoRepeatTotalTracks = isRenderGrid ? downcast<RenderGrid>(renderer)->autoRepeatCountForDirection(direction) : 0;
1239 OrderedNamedLinesCollector collector(style, isRowAxis, autoRepeatTotalTracks);
1240 auto list = CSSValueList::createSpaceSeparated();
1241 unsigned insertionIndex;
1242 if (isRenderGrid) {
1243 auto computedTrackSizes = downcast<RenderGrid>(*renderer).trackSizesForComputedStyle(direction);
1244 unsigned numTracks = computedTrackSizes.size();
1245
1246 for (unsigned i = 0; i < numTracks; ++i) {
1247 addValuesForNamedGridLinesAtIndex(collector, i, list.get());
1248 list->append(zoomAdjustedPixelValue(computedTrackSizes[i], style));
1249 }
1250 addValuesForNamedGridLinesAtIndex(collector, numTracks + 1, list.get());
1251 insertionIndex = numTracks;
1252 } else {
1253 for (unsigned i = 0; i < trackSizes.size(); ++i) {
1254 addValuesForNamedGridLinesAtIndex(collector, i, list.get());
1255 list->append(specifiedValueForGridTrackSize(trackSizes[i], style));
1256 }
1257 insertionIndex = trackSizes.size();
1258 }
1259
1260 // Those are the trailing <ident>* allowed in the syntax.
1261 addValuesForNamedGridLinesAtIndex(collector, insertionIndex, list.get());
1262 return list;
1263}
1264
1265static Ref<CSSValue> valueForGridPosition(const GridPosition& position)
1266{
1267 auto& cssValuePool = CSSValuePool::singleton();
1268 if (position.isAuto())
1269 return cssValuePool.createIdentifierValue(CSSValueAuto);
1270
1271 if (position.isNamedGridArea())
1272 return cssValuePool.createValue(position.namedGridLine(), CSSPrimitiveValue::CSS_STRING);
1273
1274 auto list = CSSValueList::createSpaceSeparated();
1275 if (position.isSpan()) {
1276 list->append(cssValuePool.createIdentifierValue(CSSValueSpan));
1277 list->append(cssValuePool.createValue(position.spanPosition(), CSSPrimitiveValue::CSS_NUMBER));
1278 } else
1279 list->append(cssValuePool.createValue(position.integerPosition(), CSSPrimitiveValue::CSS_NUMBER));
1280
1281 if (!position.namedGridLine().isNull())
1282 list->append(cssValuePool.createValue(position.namedGridLine(), CSSPrimitiveValue::CSS_STRING));
1283 return list;
1284}
1285
1286static Ref<CSSValue> createTransitionPropertyValue(const Animation& animation)
1287{
1288 switch (animation.animationMode()) {
1289 case Animation::AnimateNone:
1290 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1291 case Animation::AnimateAll:
1292 return CSSValuePool::singleton().createIdentifierValue(CSSValueAll);
1293 case Animation::AnimateSingleProperty:
1294 return CSSValuePool::singleton().createValue(getPropertyNameString(animation.property()), CSSPrimitiveValue::CSS_STRING);
1295 case Animation::AnimateUnknownProperty:
1296 return CSSValuePool::singleton().createValue(animation.unknownProperty(), CSSPrimitiveValue::CSS_STRING);
1297 }
1298 ASSERT_NOT_REACHED();
1299 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1300}
1301
1302static Ref<CSSValueList> transitionPropertyValue(const AnimationList* animationList)
1303{
1304 auto list = CSSValueList::createCommaSeparated();
1305 if (animationList) {
1306 for (size_t i = 0; i < animationList->size(); ++i)
1307 list->append(createTransitionPropertyValue(animationList->animation(i)));
1308 } else
1309 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAll));
1310 return list;
1311}
1312
1313#if ENABLE(CSS_SCROLL_SNAP)
1314
1315static Ref<CSSValueList> valueForScrollSnapType(const ScrollSnapType& type)
1316{
1317 auto value = CSSValueList::createSpaceSeparated();
1318 if (type.strictness == ScrollSnapStrictness::None)
1319 value->append(CSSValuePool::singleton().createValue(CSSValueNone));
1320 else {
1321 value->append(CSSPrimitiveValue::create(type.axis));
1322 value->append(CSSPrimitiveValue::create(type.strictness));
1323 }
1324 return value;
1325}
1326
1327static Ref<CSSValueList> valueForScrollSnapAlignment(const ScrollSnapAlign& alignment)
1328{
1329 auto value = CSSValueList::createSpaceSeparated();
1330 value->append(CSSPrimitiveValue::create(alignment.x));
1331 value->append(CSSPrimitiveValue::create(alignment.y));
1332 return value;
1333}
1334
1335#endif
1336
1337static Ref<CSSValue> willChangePropertyValue(const WillChangeData* willChangeData)
1338{
1339 auto& cssValuePool = CSSValuePool::singleton();
1340 if (!willChangeData || !willChangeData->numFeatures())
1341 return cssValuePool.createIdentifierValue(CSSValueAuto);
1342
1343 auto list = CSSValueList::createCommaSeparated();
1344 for (size_t i = 0; i < willChangeData->numFeatures(); ++i) {
1345 WillChangeData::FeaturePropertyPair feature = willChangeData->featureAt(i);
1346 switch (feature.first) {
1347 case WillChangeData::ScrollPosition:
1348 list->append(cssValuePool.createIdentifierValue(CSSValueScrollPosition));
1349 break;
1350 case WillChangeData::Contents:
1351 list->append(cssValuePool.createIdentifierValue(CSSValueContents));
1352 break;
1353 case WillChangeData::Property:
1354 list->append(cssValuePool.createIdentifierValue(feature.second));
1355 break;
1356 case WillChangeData::Invalid:
1357 ASSERT_NOT_REACHED();
1358 break;
1359 }
1360 }
1361
1362 return list;
1363}
1364
1365static inline void appendLigaturesValue(CSSValueList& list, FontVariantLigatures value, CSSValueID yesValue, CSSValueID noValue)
1366{
1367 switch (value) {
1368 case FontVariantLigatures::Normal:
1369 return;
1370 case FontVariantLigatures::No:
1371 list.append(CSSValuePool::singleton().createIdentifierValue(noValue));
1372 return;
1373 case FontVariantLigatures::Yes:
1374 list.append(CSSValuePool::singleton().createIdentifierValue(yesValue));
1375 return;
1376 }
1377 ASSERT_NOT_REACHED();
1378}
1379
1380static Ref<CSSValue> fontVariantLigaturesPropertyValue(FontVariantLigatures common, FontVariantLigatures discretionary, FontVariantLigatures historical, FontVariantLigatures contextualAlternates)
1381{
1382 auto& cssValuePool = CSSValuePool::singleton();
1383 if (common == FontVariantLigatures::No && discretionary == FontVariantLigatures::No && historical == FontVariantLigatures::No && contextualAlternates == FontVariantLigatures::No)
1384 return cssValuePool.createIdentifierValue(CSSValueNone);
1385 if (common == FontVariantLigatures::Normal && discretionary == FontVariantLigatures::Normal && historical == FontVariantLigatures::Normal && contextualAlternates == FontVariantLigatures::Normal)
1386 return cssValuePool.createIdentifierValue(CSSValueNormal);
1387
1388 auto valueList = CSSValueList::createSpaceSeparated();
1389 appendLigaturesValue(valueList, common, CSSValueCommonLigatures, CSSValueNoCommonLigatures);
1390 appendLigaturesValue(valueList, discretionary, CSSValueDiscretionaryLigatures, CSSValueNoDiscretionaryLigatures);
1391 appendLigaturesValue(valueList, historical, CSSValueHistoricalLigatures, CSSValueNoHistoricalLigatures);
1392 appendLigaturesValue(valueList, contextualAlternates, CSSValueContextual, CSSValueNoContextual);
1393 return valueList;
1394}
1395
1396static Ref<CSSValue> fontVariantPositionPropertyValue(FontVariantPosition position)
1397{
1398 auto& cssValuePool = CSSValuePool::singleton();
1399 CSSValueID valueID = CSSValueNormal;
1400 switch (position) {
1401 case FontVariantPosition::Normal:
1402 break;
1403 case FontVariantPosition::Subscript:
1404 valueID = CSSValueSub;
1405 break;
1406 case FontVariantPosition::Superscript:
1407 valueID = CSSValueSuper;
1408 break;
1409 }
1410 return cssValuePool.createIdentifierValue(valueID);
1411}
1412
1413static Ref<CSSValue> fontVariantCapsPropertyValue(FontVariantCaps caps)
1414{
1415 auto& cssValuePool = CSSValuePool::singleton();
1416 CSSValueID valueID = CSSValueNormal;
1417 switch (caps) {
1418 case FontVariantCaps::Normal:
1419 break;
1420 case FontVariantCaps::Small:
1421 valueID = CSSValueSmallCaps;
1422 break;
1423 case FontVariantCaps::AllSmall:
1424 valueID = CSSValueAllSmallCaps;
1425 break;
1426 case FontVariantCaps::Petite:
1427 valueID = CSSValuePetiteCaps;
1428 break;
1429 case FontVariantCaps::AllPetite:
1430 valueID = CSSValueAllPetiteCaps;
1431 break;
1432 case FontVariantCaps::Unicase:
1433 valueID = CSSValueUnicase;
1434 break;
1435 case FontVariantCaps::Titling:
1436 valueID = CSSValueTitlingCaps;
1437 break;
1438 }
1439 return cssValuePool.createIdentifierValue(valueID);
1440}
1441
1442static Ref<CSSValue> fontVariantNumericPropertyValue(FontVariantNumericFigure figure, FontVariantNumericSpacing spacing, FontVariantNumericFraction fraction, FontVariantNumericOrdinal ordinal, FontVariantNumericSlashedZero slashedZero)
1443{
1444 auto& cssValuePool = CSSValuePool::singleton();
1445 if (figure == FontVariantNumericFigure::Normal && spacing == FontVariantNumericSpacing::Normal && fraction == FontVariantNumericFraction::Normal && ordinal == FontVariantNumericOrdinal::Normal && slashedZero == FontVariantNumericSlashedZero::Normal)
1446 return cssValuePool.createIdentifierValue(CSSValueNormal);
1447
1448 auto valueList = CSSValueList::createSpaceSeparated();
1449 switch (figure) {
1450 case FontVariantNumericFigure::Normal:
1451 break;
1452 case FontVariantNumericFigure::LiningNumbers:
1453 valueList->append(cssValuePool.createIdentifierValue(CSSValueLiningNums));
1454 break;
1455 case FontVariantNumericFigure::OldStyleNumbers:
1456 valueList->append(cssValuePool.createIdentifierValue(CSSValueOldstyleNums));
1457 break;
1458 }
1459
1460 switch (spacing) {
1461 case FontVariantNumericSpacing::Normal:
1462 break;
1463 case FontVariantNumericSpacing::ProportionalNumbers:
1464 valueList->append(cssValuePool.createIdentifierValue(CSSValueProportionalNums));
1465 break;
1466 case FontVariantNumericSpacing::TabularNumbers:
1467 valueList->append(cssValuePool.createIdentifierValue(CSSValueTabularNums));
1468 break;
1469 }
1470
1471 switch (fraction) {
1472 case FontVariantNumericFraction::Normal:
1473 break;
1474 case FontVariantNumericFraction::DiagonalFractions:
1475 valueList->append(cssValuePool.createIdentifierValue(CSSValueDiagonalFractions));
1476 break;
1477 case FontVariantNumericFraction::StackedFractions:
1478 valueList->append(cssValuePool.createIdentifierValue(CSSValueStackedFractions));
1479 break;
1480 }
1481
1482 if (ordinal == FontVariantNumericOrdinal::Yes)
1483 valueList->append(cssValuePool.createIdentifierValue(CSSValueOrdinal));
1484 if (slashedZero == FontVariantNumericSlashedZero::Yes)
1485 valueList->append(cssValuePool.createIdentifierValue(CSSValueSlashedZero));
1486
1487 return valueList;
1488}
1489
1490static Ref<CSSValue> fontVariantAlternatesPropertyValue(FontVariantAlternates alternates)
1491{
1492 auto& cssValuePool = CSSValuePool::singleton();
1493 CSSValueID valueID = CSSValueNormal;
1494 switch (alternates) {
1495 case FontVariantAlternates::Normal:
1496 break;
1497 case FontVariantAlternates::HistoricalForms:
1498 valueID = CSSValueHistoricalForms;
1499 break;
1500 }
1501 return cssValuePool.createIdentifierValue(valueID);
1502}
1503
1504static Ref<CSSValue> fontVariantEastAsianPropertyValue(FontVariantEastAsianVariant variant, FontVariantEastAsianWidth width, FontVariantEastAsianRuby ruby)
1505{
1506 auto& cssValuePool = CSSValuePool::singleton();
1507 if (variant == FontVariantEastAsianVariant::Normal && width == FontVariantEastAsianWidth::Normal && ruby == FontVariantEastAsianRuby::Normal)
1508 return cssValuePool.createIdentifierValue(CSSValueNormal);
1509
1510 auto valueList = CSSValueList::createSpaceSeparated();
1511 switch (variant) {
1512 case FontVariantEastAsianVariant::Normal:
1513 break;
1514 case FontVariantEastAsianVariant::Jis78:
1515 valueList->append(cssValuePool.createIdentifierValue(CSSValueJis78));
1516 break;
1517 case FontVariantEastAsianVariant::Jis83:
1518 valueList->append(cssValuePool.createIdentifierValue(CSSValueJis83));
1519 break;
1520 case FontVariantEastAsianVariant::Jis90:
1521 valueList->append(cssValuePool.createIdentifierValue(CSSValueJis90));
1522 break;
1523 case FontVariantEastAsianVariant::Jis04:
1524 valueList->append(cssValuePool.createIdentifierValue(CSSValueJis04));
1525 break;
1526 case FontVariantEastAsianVariant::Simplified:
1527 valueList->append(cssValuePool.createIdentifierValue(CSSValueSimplified));
1528 break;
1529 case FontVariantEastAsianVariant::Traditional:
1530 valueList->append(cssValuePool.createIdentifierValue(CSSValueTraditional));
1531 break;
1532 }
1533
1534 switch (width) {
1535 case FontVariantEastAsianWidth::Normal:
1536 break;
1537 case FontVariantEastAsianWidth::Full:
1538 valueList->append(cssValuePool.createIdentifierValue(CSSValueFullWidth));
1539 break;
1540 case FontVariantEastAsianWidth::Proportional:
1541 valueList->append(cssValuePool.createIdentifierValue(CSSValueProportionalWidth));
1542 break;
1543 }
1544
1545 if (ruby == FontVariantEastAsianRuby::Yes)
1546 valueList->append(cssValuePool.createIdentifierValue(CSSValueRuby));
1547
1548 return valueList;
1549}
1550
1551static Ref<CSSValueList> delayValue(const AnimationList* animationList)
1552{
1553 auto& cssValuePool = CSSValuePool::singleton();
1554 auto list = CSSValueList::createCommaSeparated();
1555 if (animationList) {
1556 for (size_t i = 0; i < animationList->size(); ++i)
1557 list->append(cssValuePool.createValue(animationList->animation(i).delay(), CSSPrimitiveValue::CSS_S));
1558 } else {
1559 // Note that initialAnimationDelay() is used for both transitions and animations
1560 list->append(cssValuePool.createValue(Animation::initialDelay(), CSSPrimitiveValue::CSS_S));
1561 }
1562 return list;
1563}
1564
1565static Ref<CSSValueList> durationValue(const AnimationList* animationList)
1566{
1567 auto& cssValuePool = CSSValuePool::singleton();
1568 auto list = CSSValueList::createCommaSeparated();
1569 if (animationList) {
1570 for (size_t i = 0; i < animationList->size(); ++i)
1571 list->append(cssValuePool.createValue(animationList->animation(i).duration(), CSSPrimitiveValue::CSS_S));
1572 } else {
1573 // Note that initialAnimationDuration() is used for both transitions and animations
1574 list->append(cssValuePool.createValue(Animation::initialDuration(), CSSPrimitiveValue::CSS_S));
1575 }
1576 return list;
1577}
1578
1579static Ref<CSSValue> createTimingFunctionValue(const TimingFunction& timingFunction)
1580{
1581 switch (timingFunction.type()) {
1582 case TimingFunction::CubicBezierFunction: {
1583 auto& function = downcast<CubicBezierTimingFunction>(timingFunction);
1584 if (function.timingFunctionPreset() != CubicBezierTimingFunction::Custom) {
1585 CSSValueID valueId = CSSValueInvalid;
1586 switch (function.timingFunctionPreset()) {
1587 case CubicBezierTimingFunction::Ease:
1588 valueId = CSSValueEase;
1589 break;
1590 case CubicBezierTimingFunction::EaseIn:
1591 valueId = CSSValueEaseIn;
1592 break;
1593 case CubicBezierTimingFunction::EaseOut:
1594 valueId = CSSValueEaseOut;
1595 break;
1596 default:
1597 ASSERT(function.timingFunctionPreset() == CubicBezierTimingFunction::EaseInOut);
1598 valueId = CSSValueEaseInOut;
1599 break;
1600 }
1601 return CSSValuePool::singleton().createIdentifierValue(valueId);
1602 }
1603 return CSSCubicBezierTimingFunctionValue::create(function.x1(), function.y1(), function.x2(), function.y2());
1604 }
1605 case TimingFunction::StepsFunction: {
1606 auto& function = downcast<StepsTimingFunction>(timingFunction);
1607 return CSSStepsTimingFunctionValue::create(function.numberOfSteps(), function.stepAtStart());
1608 }
1609 case TimingFunction::SpringFunction: {
1610 auto& function = downcast<SpringTimingFunction>(timingFunction);
1611 return CSSSpringTimingFunctionValue::create(function.mass(), function.stiffness(), function.damping(), function.initialVelocity());
1612 }
1613 default:
1614 ASSERT(timingFunction.type() == TimingFunction::LinearFunction);
1615 return CSSValuePool::singleton().createIdentifierValue(CSSValueLinear);
1616 }
1617}
1618
1619static Ref<CSSValueList> timingFunctionValue(const AnimationList* animationList)
1620{
1621 auto list = CSSValueList::createCommaSeparated();
1622 if (animationList) {
1623 for (size_t i = 0; i < animationList->size(); ++i)
1624 list->append(createTimingFunctionValue(*animationList->animation(i).timingFunction()));
1625 } else
1626 // Note that initialAnimationTimingFunction() is used for both transitions and animations
1627 list->append(createTimingFunctionValue(Animation::initialTimingFunction()));
1628 return list;
1629}
1630
1631static Ref<CSSValue> createLineBoxContainValue(unsigned lineBoxContain)
1632{
1633 if (!lineBoxContain)
1634 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1635 return CSSLineBoxContainValue::create(lineBoxContain);
1636}
1637
1638static Element* styleElementForNode(Node* node)
1639{
1640 if (!node)
1641 return nullptr;
1642 if (is<Element>(*node))
1643 return downcast<Element>(node);
1644 return composedTreeAncestors(*node).first();
1645}
1646
1647ComputedStyleExtractor::ComputedStyleExtractor(Node* node, bool allowVisitedStyle, PseudoId pseudoElementSpecifier)
1648 : m_element(styleElementForNode(node))
1649 , m_pseudoElementSpecifier(pseudoElementSpecifier)
1650 , m_allowVisitedStyle(allowVisitedStyle)
1651{
1652}
1653
1654ComputedStyleExtractor::ComputedStyleExtractor(Element* element, bool allowVisitedStyle, PseudoId pseudoElementSpecifier)
1655 : m_element(element)
1656 , m_pseudoElementSpecifier(pseudoElementSpecifier)
1657 , m_allowVisitedStyle(allowVisitedStyle)
1658{
1659}
1660
1661CSSComputedStyleDeclaration::CSSComputedStyleDeclaration(Element& element, bool allowVisitedStyle, const String& pseudoElementName)
1662 : m_element(element)
1663 , m_allowVisitedStyle(allowVisitedStyle)
1664 , m_refCount(1)
1665{
1666 unsigned nameWithoutColonsStart = pseudoElementName[0] == ':' ? (pseudoElementName[1] == ':' ? 2 : 1) : 0;
1667 m_pseudoElementSpecifier = CSSSelector::pseudoId(CSSSelector::parsePseudoElementType(
1668 (pseudoElementName.substringSharingImpl(nameWithoutColonsStart))));
1669}
1670
1671CSSComputedStyleDeclaration::~CSSComputedStyleDeclaration() = default;
1672
1673void CSSComputedStyleDeclaration::ref()
1674{
1675 ++m_refCount;
1676}
1677
1678void CSSComputedStyleDeclaration::deref()
1679{
1680 ASSERT(m_refCount);
1681 if (!--m_refCount)
1682 delete this;
1683}
1684
1685String CSSComputedStyleDeclaration::cssText() const
1686{
1687 StringBuilder result;
1688
1689 for (unsigned i = 0; i < numComputedProperties; i++) {
1690 if (i)
1691 result.append(' ');
1692 result.append(getPropertyName(computedProperties[i]));
1693 result.appendLiteral(": ");
1694 result.append(getPropertyValue(computedProperties[i]));
1695 result.append(';');
1696 }
1697
1698 return result.toString();
1699}
1700
1701ExceptionOr<void> CSSComputedStyleDeclaration::setCssText(const String&)
1702{
1703 return Exception { NoModificationAllowedError };
1704}
1705
1706RefPtr<CSSPrimitiveValue> ComputedStyleExtractor::getFontSizeCSSValuePreferringKeyword()
1707{
1708 if (!m_element)
1709 return nullptr;
1710
1711 m_element->document().updateLayoutIgnorePendingStylesheets();
1712
1713 auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
1714 if (!style)
1715 return nullptr;
1716
1717 if (CSSValueID sizeIdentifier = style->fontDescription().keywordSizeAsIdentifier())
1718 return CSSValuePool::singleton().createIdentifierValue(sizeIdentifier);
1719
1720 return zoomAdjustedPixelValue(style->fontDescription().computedSize(), *style);
1721}
1722
1723bool ComputedStyleExtractor::useFixedFontDefaultSize()
1724{
1725 if (!m_element)
1726 return false;
1727 auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
1728 if (!style)
1729 return false;
1730
1731 return style->fontDescription().useFixedDefaultSize();
1732}
1733
1734static CSSValueID identifierForFamily(const AtomString& family)
1735{
1736 if (family == cursiveFamily)
1737 return CSSValueCursive;
1738 if (family == fantasyFamily)
1739 return CSSValueFantasy;
1740 if (family == monospaceFamily)
1741 return CSSValueMonospace;
1742 if (family == pictographFamily)
1743 return CSSValueWebkitPictograph;
1744 if (family == sansSerifFamily)
1745 return CSSValueSansSerif;
1746 if (family == serifFamily)
1747 return CSSValueSerif;
1748 if (family == systemUiFamily)
1749 return CSSValueSystemUi;
1750 return CSSValueInvalid;
1751}
1752
1753static Ref<CSSPrimitiveValue> valueForFamily(const AtomString& family)
1754{
1755 if (CSSValueID familyIdentifier = identifierForFamily(family))
1756 return CSSValuePool::singleton().createIdentifierValue(familyIdentifier);
1757 return CSSValuePool::singleton().createFontFamilyValue(family);
1758}
1759
1760#if ENABLE(POINTER_EVENTS)
1761static Ref<CSSValue> touchActionFlagsToCSSValue(OptionSet<TouchAction> touchActions)
1762{
1763 auto& cssValuePool = CSSValuePool::singleton();
1764
1765 if (touchActions & TouchAction::Auto)
1766 return cssValuePool.createIdentifierValue(CSSValueAuto);
1767 if (touchActions & TouchAction::None)
1768 return cssValuePool.createIdentifierValue(CSSValueNone);
1769 if (touchActions & TouchAction::Manipulation)
1770 return cssValuePool.createIdentifierValue(CSSValueManipulation);
1771
1772 auto list = CSSValueList::createSpaceSeparated();
1773 if (touchActions & TouchAction::PanX)
1774 list->append(cssValuePool.createIdentifierValue(CSSValuePanX));
1775 if (touchActions & TouchAction::PanY)
1776 list->append(cssValuePool.createIdentifierValue(CSSValuePanY));
1777 if (touchActions & TouchAction::PinchZoom)
1778 list->append(cssValuePool.createIdentifierValue(CSSValuePinchZoom));
1779
1780 if (!list->length())
1781 return cssValuePool.createIdentifierValue(CSSValueAuto);
1782 return list;
1783}
1784#endif
1785
1786static Ref<CSSValue> renderTextDecorationFlagsToCSSValue(OptionSet<TextDecoration> textDecoration)
1787{
1788 auto& cssValuePool = CSSValuePool::singleton();
1789 // Blink value is ignored.
1790 auto list = CSSValueList::createSpaceSeparated();
1791 if (textDecoration & TextDecoration::Underline)
1792 list->append(cssValuePool.createIdentifierValue(CSSValueUnderline));
1793 if (textDecoration & TextDecoration::Overline)
1794 list->append(cssValuePool.createIdentifierValue(CSSValueOverline));
1795 if (textDecoration & TextDecoration::LineThrough)
1796 list->append(cssValuePool.createIdentifierValue(CSSValueLineThrough));
1797#if ENABLE(LETTERPRESS)
1798 if (textDecoration & TextDecoration::Letterpress)
1799 list->append(cssValuePool.createIdentifierValue(CSSValueWebkitLetterpress));
1800#endif
1801
1802 if (!list->length())
1803 return cssValuePool.createIdentifierValue(CSSValueNone);
1804 return list;
1805}
1806
1807static Ref<CSSValue> renderTextDecorationStyleFlagsToCSSValue(TextDecorationStyle textDecorationStyle)
1808{
1809 switch (textDecorationStyle) {
1810 case TextDecorationStyle::Solid:
1811 return CSSValuePool::singleton().createIdentifierValue(CSSValueSolid);
1812 case TextDecorationStyle::Double:
1813 return CSSValuePool::singleton().createIdentifierValue(CSSValueDouble);
1814 case TextDecorationStyle::Dotted:
1815 return CSSValuePool::singleton().createIdentifierValue(CSSValueDotted);
1816 case TextDecorationStyle::Dashed:
1817 return CSSValuePool::singleton().createIdentifierValue(CSSValueDashed);
1818 case TextDecorationStyle::Wavy:
1819 return CSSValuePool::singleton().createIdentifierValue(CSSValueWavy);
1820 }
1821
1822 ASSERT_NOT_REACHED();
1823 return CSSValuePool::singleton().createExplicitInitialValue();
1824}
1825
1826static Ref<CSSValue> renderTextDecorationSkipFlagsToCSSValue(OptionSet<TextDecorationSkip> textDecorationSkip)
1827{
1828 // FIXME: This should probably return a CSSValueList with the set of all TextDecorationSkips.
1829 switch (static_cast<TextDecorationSkip>(textDecorationSkip.toRaw())) {
1830 case TextDecorationSkip::Auto:
1831 return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1832 case TextDecorationSkip::None:
1833 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1834 case TextDecorationSkip::Ink:
1835 return CSSValuePool::singleton().createIdentifierValue(CSSValueInk);
1836 case TextDecorationSkip::Objects:
1837 return CSSValuePool::singleton().createIdentifierValue(CSSValueObjects);
1838 }
1839
1840 ASSERT_NOT_REACHED();
1841 return CSSValuePool::singleton().createExplicitInitialValue();
1842}
1843
1844static Ref<CSSValue> textUnderlineOffsetToCSSValue(const TextUnderlineOffset& textUnderlineOffset)
1845{
1846 if (textUnderlineOffset.isAuto())
1847 return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1848 ASSERT(textUnderlineOffset.isLength());
1849 return CSSValuePool::singleton().createValue(textUnderlineOffset.lengthValue(), CSSPrimitiveValue::CSS_PX);
1850}
1851
1852static Ref<CSSValue> textDecorationThicknessToCSSValue(const TextDecorationThickness& textDecorationThickness)
1853{
1854 if (textDecorationThickness.isAuto())
1855 return CSSValuePool::singleton().createIdentifierValue(CSSValueAuto);
1856 if (textDecorationThickness.isFromFont())
1857 return CSSValuePool::singleton().createIdentifierValue(CSSValueFromFont);
1858 ASSERT(textDecorationThickness.isLength());
1859 return CSSValuePool::singleton().createValue(textDecorationThickness.lengthValue(), CSSPrimitiveValue::CSS_PX);
1860}
1861
1862static Ref<CSSValue> renderEmphasisPositionFlagsToCSSValue(OptionSet<TextEmphasisPosition> textEmphasisPosition)
1863{
1864 ASSERT(!((textEmphasisPosition & TextEmphasisPosition::Over) && (textEmphasisPosition & TextEmphasisPosition::Under)));
1865 ASSERT(!((textEmphasisPosition & TextEmphasisPosition::Left) && (textEmphasisPosition & TextEmphasisPosition::Right)));
1866 auto& cssValuePool = CSSValuePool::singleton();
1867 auto list = CSSValueList::createSpaceSeparated();
1868 if (textEmphasisPosition & TextEmphasisPosition::Over)
1869 list->append(cssValuePool.createIdentifierValue(CSSValueOver));
1870 if (textEmphasisPosition & TextEmphasisPosition::Under)
1871 list->append(cssValuePool.createIdentifierValue(CSSValueUnder));
1872 if (textEmphasisPosition & TextEmphasisPosition::Left)
1873 list->append(cssValuePool.createIdentifierValue(CSSValueLeft));
1874 if (textEmphasisPosition & TextEmphasisPosition::Right)
1875 list->append(cssValuePool.createIdentifierValue(CSSValueRight));
1876 if (!list->length())
1877 return cssValuePool.createIdentifierValue(CSSValueNone);
1878 return list;
1879}
1880
1881static Ref<CSSValue> speakAsToCSSValue(OptionSet<SpeakAs> speakAs)
1882{
1883 auto& cssValuePool = CSSValuePool::singleton();
1884 auto list = CSSValueList::createSpaceSeparated();
1885 if (speakAs & SpeakAs::SpellOut)
1886 list->append(cssValuePool.createIdentifierValue(CSSValueSpellOut));
1887 if (speakAs & SpeakAs::Digits)
1888 list->append(cssValuePool.createIdentifierValue(CSSValueDigits));
1889 if (speakAs & SpeakAs::LiteralPunctuation)
1890 list->append(cssValuePool.createIdentifierValue(CSSValueLiteralPunctuation));
1891 if (speakAs & SpeakAs::NoPunctuation)
1892 list->append(cssValuePool.createIdentifierValue(CSSValueNoPunctuation));
1893 if (!list->length())
1894 return cssValuePool.createIdentifierValue(CSSValueNormal);
1895 return list;
1896}
1897
1898static Ref<CSSValue> hangingPunctuationToCSSValue(OptionSet<HangingPunctuation> hangingPunctuation)
1899{
1900 auto& cssValuePool = CSSValuePool::singleton();
1901 auto list = CSSValueList::createSpaceSeparated();
1902 if (hangingPunctuation & HangingPunctuation::First)
1903 list->append(cssValuePool.createIdentifierValue(CSSValueFirst));
1904 if (hangingPunctuation & HangingPunctuation::AllowEnd)
1905 list->append(cssValuePool.createIdentifierValue(CSSValueAllowEnd));
1906 if (hangingPunctuation & HangingPunctuation::ForceEnd)
1907 list->append(cssValuePool.createIdentifierValue(CSSValueForceEnd));
1908 if (hangingPunctuation & HangingPunctuation::Last)
1909 list->append(cssValuePool.createIdentifierValue(CSSValueLast));
1910 if (!list->length())
1911 return cssValuePool.createIdentifierValue(CSSValueNone);
1912 return list;
1913}
1914
1915static Ref<CSSValue> fillRepeatToCSSValue(FillRepeat xRepeat, FillRepeat yRepeat)
1916{
1917 // For backwards compatibility, if both values are equal, just return one of them. And
1918 // if the two values are equivalent to repeat-x or repeat-y, just return the shorthand.
1919 auto& cssValuePool = CSSValuePool::singleton();
1920 if (xRepeat == yRepeat)
1921 return cssValuePool.createValue(xRepeat);
1922 if (xRepeat == FillRepeat::Repeat && yRepeat == FillRepeat::NoRepeat)
1923 return cssValuePool.createIdentifierValue(CSSValueRepeatX);
1924 if (xRepeat == FillRepeat::NoRepeat && yRepeat == FillRepeat::Repeat)
1925 return cssValuePool.createIdentifierValue(CSSValueRepeatY);
1926
1927 auto list = CSSValueList::createSpaceSeparated();
1928 list->append(cssValuePool.createValue(xRepeat));
1929 list->append(cssValuePool.createValue(yRepeat));
1930 return list;
1931}
1932
1933static Ref<CSSValue> fillSourceTypeToCSSValue(MaskSourceType type)
1934{
1935 switch (type) {
1936 case MaskSourceType::Alpha:
1937 return CSSValuePool::singleton().createValue(CSSValueAlpha);
1938 default:
1939 ASSERT(type == MaskSourceType::Luminance);
1940 return CSSValuePool::singleton().createValue(CSSValueLuminance);
1941 }
1942}
1943
1944static Ref<CSSValue> fillSizeToCSSValue(const FillSize& fillSize, const RenderStyle& style)
1945{
1946 if (fillSize.type == FillSizeType::Contain)
1947 return CSSValuePool::singleton().createIdentifierValue(CSSValueContain);
1948
1949 if (fillSize.type == FillSizeType::Cover)
1950 return CSSValuePool::singleton().createIdentifierValue(CSSValueCover);
1951
1952 if (fillSize.size.height.isAuto())
1953 return zoomAdjustedPixelValueForLength(fillSize.size.width, style);
1954
1955 auto list = CSSValueList::createSpaceSeparated();
1956 list->append(zoomAdjustedPixelValueForLength(fillSize.size.width, style));
1957 list->append(zoomAdjustedPixelValueForLength(fillSize.size.height, style));
1958 return list;
1959}
1960
1961static Ref<CSSValue> altTextToCSSValue(const RenderStyle& style)
1962{
1963 return CSSValuePool::singleton().createValue(style.contentAltText(), CSSPrimitiveValue::CSS_STRING);
1964}
1965
1966static Ref<CSSValueList> contentToCSSValue(const RenderStyle& style)
1967{
1968 auto& cssValuePool = CSSValuePool::singleton();
1969 auto list = CSSValueList::createSpaceSeparated();
1970 for (auto* contentData = style.contentData(); contentData; contentData = contentData->next()) {
1971 if (is<CounterContentData>(*contentData))
1972 list->append(cssValuePool.createValue(downcast<CounterContentData>(*contentData).counter().identifier(), CSSPrimitiveValue::CSS_COUNTER_NAME));
1973 else if (is<ImageContentData>(*contentData))
1974 list->append(downcast<ImageContentData>(*contentData).image().cssValue());
1975 else if (is<TextContentData>(*contentData))
1976 list->append(cssValuePool.createValue(downcast<TextContentData>(*contentData).text(), CSSPrimitiveValue::CSS_STRING));
1977 }
1978 return list;
1979}
1980
1981static Ref<CSSValue> counterToCSSValue(const RenderStyle& style, CSSPropertyID propertyID)
1982{
1983 auto* map = style.counterDirectives();
1984 if (!map)
1985 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
1986
1987 auto& cssValuePool = CSSValuePool::singleton();
1988 auto list = CSSValueList::createSpaceSeparated();
1989 for (auto& keyValue : *map) {
1990 list->append(cssValuePool.createValue(keyValue.key, CSSPrimitiveValue::CSS_STRING));
1991 double number = (propertyID == CSSPropertyCounterIncrement ? keyValue.value.incrementValue : keyValue.value.resetValue).valueOr(0);
1992 list->append(cssValuePool.createValue(number, CSSPrimitiveValue::CSS_NUMBER));
1993 }
1994 return list;
1995}
1996
1997static void logUnimplementedPropertyID(CSSPropertyID propertyID)
1998{
1999 static NeverDestroyed<HashSet<CSSPropertyID>> propertyIDSet;
2000 if (!propertyIDSet.get().add(propertyID).isNewEntry)
2001 return;
2002
2003 LOG_ERROR("WebKit does not yet implement getComputedStyle for '%s'.", getPropertyName(propertyID));
2004}
2005
2006static Ref<CSSValueList> fontFamilyListFromStyle(const RenderStyle& style)
2007{
2008 auto list = CSSValueList::createCommaSeparated();
2009 for (unsigned i = 0; i < style.fontCascade().familyCount(); ++i)
2010 list->append(valueForFamily(style.fontCascade().familyAt(i)));
2011 return list;
2012}
2013
2014static Ref<CSSValue> fontFamilyFromStyle(const RenderStyle& style)
2015{
2016 if (style.fontCascade().familyCount() == 1)
2017 return valueForFamily(style.fontCascade().familyAt(0));
2018 return fontFamilyListFromStyle(style);
2019}
2020
2021static Ref<CSSPrimitiveValue> lineHeightFromStyle(const RenderStyle& style)
2022{
2023 Length length = style.lineHeight();
2024 if (length.isNegative()) // If true, line-height not set; use the font's line spacing.
2025 return zoomAdjustedPixelValue(style.fontMetrics().floatLineSpacing(), style);
2026 if (length.isPercent()) {
2027 // This is imperfect, because it doesn't include the zoom factor and the real computation
2028 // for how high to be in pixels does include things like minimum font size and the zoom factor.
2029 // On the other hand, since font-size doesn't include the zoom factor, we really can't do
2030 // that here either.
2031 return zoomAdjustedPixelValue(static_cast<int>(length.percent() * style.fontDescription().computedSize()) / 100, style);
2032 }
2033 return zoomAdjustedPixelValue(floatValueForLength(length, 0), style);
2034}
2035
2036static Ref<CSSPrimitiveValue> fontSizeFromStyle(const RenderStyle& style)
2037{
2038 return zoomAdjustedPixelValue(style.fontDescription().computedSize(), style);
2039}
2040
2041Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontNonKeywordWeightFromStyleValue(FontSelectionValue weight)
2042{
2043 return CSSValuePool::singleton().createValue(static_cast<float>(weight), CSSPrimitiveValue::CSS_NUMBER);
2044}
2045
2046Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontWeightFromStyleValue(FontSelectionValue weight)
2047{
2048 if (auto value = fontWeightKeyword(weight))
2049 return CSSValuePool::singleton().createIdentifierValue(value.value());
2050 return fontNonKeywordWeightFromStyleValue(weight);
2051}
2052
2053static Ref<CSSPrimitiveValue> fontWeightFromStyle(const RenderStyle& style)
2054{
2055 return ComputedStyleExtractor::fontWeightFromStyleValue(style.fontDescription().weight());
2056}
2057
2058Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontNonKeywordStretchFromStyleValue(FontSelectionValue stretch)
2059{
2060 return CSSValuePool::singleton().createValue(static_cast<float>(stretch), CSSPrimitiveValue::CSS_PERCENTAGE);
2061}
2062
2063Ref<CSSPrimitiveValue> ComputedStyleExtractor::fontStretchFromStyleValue(FontSelectionValue stretch)
2064{
2065 if (auto keyword = fontStretchKeyword(stretch))
2066 return CSSValuePool::singleton().createIdentifierValue(keyword.value());
2067 return fontNonKeywordStretchFromStyleValue(stretch);
2068}
2069
2070static Ref<CSSPrimitiveValue> fontStretchFromStyle(const RenderStyle& style)
2071{
2072 return ComputedStyleExtractor::fontStretchFromStyleValue(style.fontDescription().stretch());
2073}
2074
2075Ref<CSSFontStyleValue> ComputedStyleExtractor::fontNonKeywordStyleFromStyleValue(FontSelectionValue italic)
2076{
2077 return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(CSSValueOblique), CSSValuePool::singleton().createValue(static_cast<float>(italic), CSSPrimitiveValue::CSS_DEG));
2078}
2079
2080Ref<CSSFontStyleValue> ComputedStyleExtractor::fontStyleFromStyleValue(Optional<FontSelectionValue> italic, FontStyleAxis fontStyleAxis)
2081{
2082 if (auto keyword = fontStyleKeyword(italic, fontStyleAxis))
2083 return CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(keyword.value()));
2084 return fontNonKeywordStyleFromStyleValue(italic.value());
2085}
2086
2087static Ref<CSSFontStyleValue> fontStyleFromStyle(const RenderStyle& style)
2088{
2089 return ComputedStyleExtractor::fontStyleFromStyleValue(style.fontDescription().italic(), style.fontDescription().fontStyleAxis());
2090}
2091
2092static Ref<CSSValue> fontVariantFromStyle(const RenderStyle& style)
2093{
2094 if (style.fontDescription().variantSettings().isAllNormal())
2095 return CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
2096
2097 auto list = CSSValueList::createSpaceSeparated();
2098
2099 switch (style.fontDescription().variantCommonLigatures()) {
2100 case FontVariantLigatures::Normal:
2101 break;
2102 case FontVariantLigatures::Yes:
2103 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueCommonLigatures));
2104 break;
2105 case FontVariantLigatures::No:
2106 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoCommonLigatures));
2107 break;
2108 }
2109
2110 switch (style.fontDescription().variantDiscretionaryLigatures()) {
2111 case FontVariantLigatures::Normal:
2112 break;
2113 case FontVariantLigatures::Yes:
2114 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiscretionaryLigatures));
2115 break;
2116 case FontVariantLigatures::No:
2117 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoDiscretionaryLigatures));
2118 break;
2119 }
2120
2121 switch (style.fontDescription().variantHistoricalLigatures()) {
2122 case FontVariantLigatures::Normal:
2123 break;
2124 case FontVariantLigatures::Yes:
2125 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalLigatures));
2126 break;
2127 case FontVariantLigatures::No:
2128 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoHistoricalLigatures));
2129 break;
2130 }
2131
2132 switch (style.fontDescription().variantContextualAlternates()) {
2133 case FontVariantLigatures::Normal:
2134 break;
2135 case FontVariantLigatures::Yes:
2136 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueContextual));
2137 break;
2138 case FontVariantLigatures::No:
2139 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoContextual));
2140 break;
2141 }
2142
2143 switch (style.fontDescription().variantPosition()) {
2144 case FontVariantPosition::Normal:
2145 break;
2146 case FontVariantPosition::Subscript:
2147 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSub));
2148 break;
2149 case FontVariantPosition::Superscript:
2150 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSuper));
2151 break;
2152 }
2153
2154 switch (style.fontDescription().variantCaps()) {
2155 case FontVariantCaps::Normal:
2156 break;
2157 case FontVariantCaps::Small:
2158 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
2159 break;
2160 case FontVariantCaps::AllSmall:
2161 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllSmallCaps));
2162 break;
2163 case FontVariantCaps::Petite:
2164 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValuePetiteCaps));
2165 break;
2166 case FontVariantCaps::AllPetite:
2167 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllPetiteCaps));
2168 break;
2169 case FontVariantCaps::Unicase:
2170 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueUnicase));
2171 break;
2172 case FontVariantCaps::Titling:
2173 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTitlingCaps));
2174 break;
2175 }
2176
2177 switch (style.fontDescription().variantNumericFigure()) {
2178 case FontVariantNumericFigure::Normal:
2179 break;
2180 case FontVariantNumericFigure::LiningNumbers:
2181 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueLiningNums));
2182 break;
2183 case FontVariantNumericFigure::OldStyleNumbers:
2184 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueOldstyleNums));
2185 break;
2186 }
2187
2188 switch (style.fontDescription().variantNumericSpacing()) {
2189 case FontVariantNumericSpacing::Normal:
2190 break;
2191 case FontVariantNumericSpacing::ProportionalNumbers:
2192 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalNums));
2193 break;
2194 case FontVariantNumericSpacing::TabularNumbers:
2195 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTabularNums));
2196 break;
2197 }
2198
2199 switch (style.fontDescription().variantNumericFraction()) {
2200 case FontVariantNumericFraction::Normal:
2201 break;
2202 case FontVariantNumericFraction::DiagonalFractions:
2203 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiagonalFractions));
2204 break;
2205 case FontVariantNumericFraction::StackedFractions:
2206 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStackedFractions));
2207 break;
2208 }
2209
2210 switch (style.fontDescription().variantNumericOrdinal()) {
2211 case FontVariantNumericOrdinal::Normal:
2212 break;
2213 case FontVariantNumericOrdinal::Yes:
2214 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueOrdinal));
2215 break;
2216 }
2217
2218 switch (style.fontDescription().variantNumericSlashedZero()) {
2219 case FontVariantNumericSlashedZero::Normal:
2220 break;
2221 case FontVariantNumericSlashedZero::Yes:
2222 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSlashedZero));
2223 break;
2224 }
2225
2226 switch (style.fontDescription().variantAlternates()) {
2227 case FontVariantAlternates::Normal:
2228 break;
2229 case FontVariantAlternates::HistoricalForms:
2230 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalForms));
2231 break;
2232 }
2233
2234 switch (style.fontDescription().variantEastAsianVariant()) {
2235 case FontVariantEastAsianVariant::Normal:
2236 break;
2237 case FontVariantEastAsianVariant::Jis78:
2238 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis78));
2239 break;
2240 case FontVariantEastAsianVariant::Jis83:
2241 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis83));
2242 break;
2243 case FontVariantEastAsianVariant::Jis90:
2244 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis90));
2245 break;
2246 case FontVariantEastAsianVariant::Jis04:
2247 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis04));
2248 break;
2249 case FontVariantEastAsianVariant::Simplified:
2250 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSimplified));
2251 break;
2252 case FontVariantEastAsianVariant::Traditional:
2253 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueTraditional));
2254 break;
2255 }
2256
2257 switch (style.fontDescription().variantEastAsianWidth()) {
2258 case FontVariantEastAsianWidth::Normal:
2259 break;
2260 case FontVariantEastAsianWidth::Full:
2261 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueFullWidth));
2262 break;
2263 case FontVariantEastAsianWidth::Proportional:
2264 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalWidth));
2265 break;
2266 }
2267
2268 switch (style.fontDescription().variantEastAsianRuby()) {
2269 case FontVariantEastAsianRuby::Normal:
2270 break;
2271 case FontVariantEastAsianRuby::Yes:
2272 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueRuby));
2273 break;
2274 }
2275
2276 return list;
2277}
2278
2279static Ref<CSSValue> fontSynthesisFromStyle(const RenderStyle& style)
2280{
2281 if (style.fontDescription().fontSynthesis() == FontSynthesisNone)
2282 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2283
2284 auto list = CSSValueList::createSpaceSeparated();
2285 if (style.fontDescription().fontSynthesis() & FontSynthesisStyle)
2286 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStyle));
2287 if (style.fontDescription().fontSynthesis() & FontSynthesisWeight)
2288 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueWeight));
2289 if (style.fontDescription().fontSynthesis() & FontSynthesisSmallCaps)
2290 list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
2291 return list;
2292}
2293
2294typedef const Length& (RenderStyle::*RenderStyleLengthGetter)() const;
2295typedef LayoutUnit (RenderBoxModelObject::*RenderBoxComputedCSSValueGetter)() const;
2296
2297template<RenderStyleLengthGetter lengthGetter, RenderBoxComputedCSSValueGetter computedCSSValueGetter>
2298static RefPtr<CSSValue> zoomAdjustedPaddingOrMarginPixelValue(const RenderStyle& style, RenderObject* renderer)
2299{
2300 Length unzoomzedLength = (style.*lengthGetter)();
2301 if (!is<RenderBox>(renderer) || unzoomzedLength.isFixed())
2302 return zoomAdjustedPixelValueForLength(unzoomzedLength, style);
2303 return zoomAdjustedPixelValue((downcast<RenderBox>(*renderer).*computedCSSValueGetter)(), style);
2304}
2305
2306template<RenderStyleLengthGetter lengthGetter>
2307static bool paddingOrMarginIsRendererDependent(const RenderStyle* style, RenderObject* renderer)
2308{
2309 return renderer && style && renderer->isBox() && !(style->*lengthGetter)().isFixed();
2310}
2311
2312static bool positionOffsetValueIsRendererDependent(const RenderStyle* style, RenderObject* renderer)
2313{
2314 return renderer && style && renderer->isBox();
2315}
2316
2317static CSSValueID convertToPageBreak(BreakBetween value)
2318{
2319 if (value == BreakBetween::Page || value == BreakBetween::LeftPage || value == BreakBetween::RightPage
2320 || value == BreakBetween::RectoPage || value == BreakBetween::VersoPage)
2321 return CSSValueAlways; // CSS 2.1 allows us to map these to always.
2322 if (value == BreakBetween::Avoid || value == BreakBetween::AvoidPage)
2323 return CSSValueAvoid;
2324 return CSSValueAuto;
2325}
2326
2327static CSSValueID convertToColumnBreak(BreakBetween value)
2328{
2329 if (value == BreakBetween::Column)
2330 return CSSValueAlways;
2331 if (value == BreakBetween::Avoid || value == BreakBetween::AvoidColumn)
2332 return CSSValueAvoid;
2333 return CSSValueAuto;
2334}
2335
2336static CSSValueID convertToPageBreak(BreakInside value)
2337{
2338 if (value == BreakInside::Avoid || value == BreakInside::AvoidPage)
2339 return CSSValueAvoid;
2340 return CSSValueAuto;
2341}
2342
2343static CSSValueID convertToColumnBreak(BreakInside value)
2344{
2345 if (value == BreakInside::Avoid || value == BreakInside::AvoidColumn)
2346 return CSSValueAvoid;
2347 return CSSValueAuto;
2348}
2349
2350static inline bool isNonReplacedInline(RenderObject& renderer)
2351{
2352 return renderer.isInline() && !renderer.isReplaced();
2353}
2354
2355static bool isLayoutDependent(CSSPropertyID propertyID, const RenderStyle* style, RenderObject* renderer)
2356{
2357 switch (propertyID) {
2358 case CSSPropertyTop:
2359 case CSSPropertyBottom:
2360 case CSSPropertyLeft:
2361 case CSSPropertyRight:
2362 case CSSPropertyInsetBlockStart:
2363 case CSSPropertyInsetBlockEnd:
2364 case CSSPropertyInsetInlineStart:
2365 case CSSPropertyInsetInlineEnd:
2366 return positionOffsetValueIsRendererDependent(style, renderer);
2367 case CSSPropertyWidth:
2368 case CSSPropertyHeight:
2369 case CSSPropertyInlineSize:
2370 case CSSPropertyBlockSize:
2371 return renderer && !renderer->isRenderSVGModelObject() && !isNonReplacedInline(*renderer);
2372 case CSSPropertyPerspectiveOrigin:
2373 case CSSPropertyTransformOrigin:
2374 case CSSPropertyTransform:
2375 case CSSPropertyFilter: // Why are filters layout-dependent?
2376#if ENABLE(FILTERS_LEVEL_2)
2377 case CSSPropertyWebkitBackdropFilter: // Ditto for backdrop-filter.
2378#endif
2379 return true;
2380 case CSSPropertyMargin: {
2381 if (!renderer || !renderer->isBox())
2382 return false;
2383 return !(style && style->marginTop().isFixed() && style->marginRight().isFixed()
2384 && style->marginBottom().isFixed() && style->marginLeft().isFixed());
2385 }
2386 case CSSPropertyMarginTop:
2387 return paddingOrMarginIsRendererDependent<&RenderStyle::marginTop>(style, renderer);
2388 case CSSPropertyMarginRight:
2389 return paddingOrMarginIsRendererDependent<&RenderStyle::marginRight>(style, renderer);
2390 case CSSPropertyMarginBottom:
2391 return paddingOrMarginIsRendererDependent<&RenderStyle::marginBottom>(style, renderer);
2392 case CSSPropertyMarginLeft:
2393 return paddingOrMarginIsRendererDependent<&RenderStyle::marginLeft>(style, renderer);
2394 case CSSPropertyPadding: {
2395 if (!renderer || !renderer->isBox())
2396 return false;
2397 return !(style && style->paddingTop().isFixed() && style->paddingRight().isFixed()
2398 && style->paddingBottom().isFixed() && style->paddingLeft().isFixed());
2399 }
2400 case CSSPropertyPaddingTop:
2401 return paddingOrMarginIsRendererDependent<&RenderStyle::paddingTop>(style, renderer);
2402 case CSSPropertyPaddingRight:
2403 return paddingOrMarginIsRendererDependent<&RenderStyle::paddingRight>(style, renderer);
2404 case CSSPropertyPaddingBottom:
2405 return paddingOrMarginIsRendererDependent<&RenderStyle::paddingBottom>(style, renderer);
2406 case CSSPropertyPaddingLeft:
2407 return paddingOrMarginIsRendererDependent<&RenderStyle::paddingLeft>(style, renderer);
2408 case CSSPropertyGridTemplateColumns:
2409 case CSSPropertyGridTemplateRows:
2410 case CSSPropertyGridTemplate:
2411 case CSSPropertyGrid:
2412 return renderer && renderer->isRenderGrid();
2413 default:
2414 return false;
2415 }
2416}
2417
2418Element* ComputedStyleExtractor::styledElement() const
2419{
2420 if (!m_element)
2421 return nullptr;
2422 PseudoElement* pseudoElement;
2423 if (m_pseudoElementSpecifier == PseudoId::Before && (pseudoElement = m_element->beforePseudoElement()))
2424 return pseudoElement;
2425 if (m_pseudoElementSpecifier == PseudoId::After && (pseudoElement = m_element->afterPseudoElement()))
2426 return pseudoElement;
2427 return m_element.get();
2428}
2429
2430RenderElement* ComputedStyleExtractor::styledRenderer() const
2431{
2432 auto* element = styledElement();
2433 if (!element)
2434 return nullptr;
2435 if (m_pseudoElementSpecifier != PseudoId::None && element == m_element.get())
2436 return nullptr;
2437 if (element->hasDisplayContents())
2438 return nullptr;
2439 return element->renderer();
2440}
2441
2442static bool isImplicitlyInheritedGridOrFlexProperty(CSSPropertyID propertyID)
2443{
2444 // It would be nice if grid and flex worked within normal CSS mechanisms and not invented their own inheritance system.
2445 switch (propertyID) {
2446 case CSSPropertyAlignSelf:
2447 case CSSPropertyJustifySelf:
2448 case CSSPropertyJustifyItems:
2449 // FIXME: In StyleResolver::adjustRenderStyle z-index is adjusted based on the parent display property for grid/flex.
2450 case CSSPropertyZIndex:
2451 return true;
2452 default:
2453 return false;
2454 }
2455}
2456
2457// In CSS 2.1 the returned object should actually contain the "used values"
2458// rather then the "computed values" (despite the name saying otherwise).
2459//
2460// See;
2461// http://www.w3.org/TR/CSS21/cascade.html#used-value
2462// http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration
2463// https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle#Notes
2464RefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const
2465{
2466 return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).propertyValue(propertyID, updateLayout);
2467}
2468
2469Ref<MutableStyleProperties> CSSComputedStyleDeclaration::copyProperties() const
2470{
2471 return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).copyProperties();
2472}
2473
2474static inline bool hasValidStyleForProperty(Element& element, CSSPropertyID propertyID)
2475{
2476 if (element.styleValidity() != Style::Validity::Valid)
2477 return false;
2478 if (element.document().hasPendingFullStyleRebuild())
2479 return false;
2480 if (!element.document().childNeedsStyleRecalc())
2481 return true;
2482
2483 bool isInherited = CSSProperty::isInheritedProperty(propertyID) || isImplicitlyInheritedGridOrFlexProperty(propertyID);
2484 bool maybeExplicitlyInherited = !isInherited;
2485
2486 const auto* currentElement = &element;
2487 for (auto& ancestor : composedTreeAncestors(element)) {
2488 if (ancestor.styleValidity() >= Style::Validity::SubtreeInvalid)
2489 return false;
2490
2491 if (maybeExplicitlyInherited) {
2492 auto* style = currentElement->renderStyle();
2493 maybeExplicitlyInherited = !style || style->hasExplicitlyInheritedProperties();
2494 }
2495
2496 if ((isInherited || maybeExplicitlyInherited) && ancestor.styleValidity() == Style::Validity::ElementInvalid)
2497 return false;
2498
2499 if (ancestor.directChildNeedsStyleRecalc() && currentElement->styleIsAffectedByPreviousSibling())
2500 return false;
2501
2502 currentElement = &ancestor;
2503 }
2504
2505 return true;
2506}
2507
2508static bool updateStyleIfNeededForProperty(Element& element, CSSPropertyID propertyID)
2509{
2510 auto& document = element.document();
2511
2512 document.styleScope().flushPendingUpdate();
2513
2514 if (hasValidStyleForProperty(element, propertyID))
2515 return false;
2516
2517 document.updateStyleIfNeeded();
2518 return true;
2519}
2520
2521static inline const RenderStyle* computeRenderStyleForProperty(Element& element, PseudoId pseudoElementSpecifier, CSSPropertyID propertyID, std::unique_ptr<RenderStyle>& ownedStyle)
2522{
2523 auto* renderer = element.renderer();
2524
2525 if (renderer && renderer->isComposited() && CSSAnimationController::supportsAcceleratedAnimationOfProperty(propertyID)) {
2526 if (auto timeline = element.document().existingTimeline())
2527 ownedStyle = timeline->animatedStyleForRenderer(*renderer);
2528 else
2529 ownedStyle = renderer->animation().animatedStyleForRenderer(*renderer);
2530 if (pseudoElementSpecifier != PseudoId::None && !element.isPseudoElement()) {
2531 // FIXME: This cached pseudo style will only exist if the animation has been run at least once.
2532 return ownedStyle->getCachedPseudoStyle(pseudoElementSpecifier);
2533 }
2534 return ownedStyle.get();
2535 }
2536
2537 return element.computedStyle(element.isPseudoElement() ? PseudoId::None : pseudoElementSpecifier);
2538}
2539
2540static Ref<CSSValue> shapePropertyValue(const RenderStyle& style, const ShapeValue* shapeValue)
2541{
2542 if (!shapeValue)
2543 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2544
2545 if (shapeValue->type() == ShapeValue::Type::Box)
2546 return CSSValuePool::singleton().createValue(shapeValue->cssBox());
2547
2548 if (shapeValue->type() == ShapeValue::Type::Image) {
2549 if (shapeValue->image())
2550 return shapeValue->image()->cssValue();
2551 return CSSValuePool::singleton().createIdentifierValue(CSSValueNone);
2552 }
2553
2554 ASSERT(shapeValue->type() == ShapeValue::Type::Shape);
2555
2556 auto list = CSSValueList::createSpaceSeparated();
2557 list->append(valueForBasicShape(style, *shapeValue->shape()));
2558 if (shapeValue->cssBox() != CSSBoxType::BoxMissing)
2559 list->append(CSSValuePool::singleton().createValue(shapeValue->cssBox()));
2560 return list;
2561}
2562
2563static Ref<CSSValueList> valueForItemPositionWithOverflowAlignment(const StyleSelfAlignmentData& data)
2564{
2565 auto& cssValuePool = CSSValuePool::singleton();
2566 auto result = CSSValueList::createSpaceSeparated();
2567 if (data.positionType() == ItemPositionType::Legacy)
2568 result->append(cssValuePool.createIdentifierValue(CSSValueLegacy));
2569 if (data.position() == ItemPosition::Baseline)
2570 result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2571 else if (data.position() == ItemPosition::LastBaseline) {
2572 result->append(cssValuePool.createIdentifierValue(CSSValueLast));
2573 result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2574 } else {
2575 if (data.position() >= ItemPosition::Center && data.overflow() != OverflowAlignment::Default)
2576 result->append(cssValuePool.createValue(data.overflow()));
2577 if (data.position() == ItemPosition::Legacy)
2578 result->append(cssValuePool.createIdentifierValue(CSSValueNormal));
2579 else
2580 result->append(cssValuePool.createValue(data.position()));
2581 }
2582 ASSERT(result->length() <= 2);
2583 return result;
2584}
2585
2586static Ref<CSSValueList> valueForContentPositionAndDistributionWithOverflowAlignment(const StyleContentAlignmentData& data)
2587{
2588 auto& cssValuePool = CSSValuePool::singleton();
2589 auto result = CSSValueList::createSpaceSeparated();
2590 // Handle content-distribution values
2591 if (data.distribution() != ContentDistribution::Default)
2592 result->append(cssValuePool.createValue(data.distribution()));
2593
2594 // Handle content-position values (either as fallback or actual value)
2595 switch (data.position()) {
2596 case ContentPosition::Normal:
2597 // Handle 'normal' value, not valid as content-distribution fallback.
2598 if (data.distribution() == ContentDistribution::Default)
2599 result->append(cssValuePool.createIdentifierValue(CSSValueNormal));
2600 break;
2601 case ContentPosition::LastBaseline:
2602 result->append(cssValuePool.createIdentifierValue(CSSValueLast));
2603 result->append(cssValuePool.createIdentifierValue(CSSValueBaseline));
2604 break;
2605 default:
2606 // Handle overflow-alignment (only allowed for content-position values)
2607 if ((data.position() >= ContentPosition::Center || data.distribution() != ContentDistribution::Default) && data.overflow() != OverflowAlignment::Default)
2608 result->append(cssValuePool.createValue(data.overflow()));
2609 result->append(cssValuePool.createValue(data.position()));
2610 }
2611
2612 ASSERT(result->length() > 0);
2613 ASSERT(result->length() <= 3);
2614 return result;
2615}
2616
2617static Ref<CSSValue> paintOrder(PaintOrder paintOrder)
2618{
2619 if (paintOrder == PaintOrder::Normal)
2620 return CSSPrimitiveValue::createIdentifier(CSSValueNormal);
2621
2622 auto paintOrderList = CSSValueList::createSpaceSeparated();
2623 switch (paintOrder) {
2624 case PaintOrder::Normal:
2625 ASSERT_NOT_REACHED();
2626 break;
2627 case PaintOrder::Fill:
2628 paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueFill));
2629 break;
2630 case PaintOrder::FillMarkers:
2631 paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueFill));
2632 paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2633 break;
2634 case PaintOrder::Stroke:
2635 paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2636 break;
2637 case PaintOrder::StrokeMarkers:
2638 paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2639 paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2640 break;
2641 case PaintOrder::Markers:
2642 paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2643 break;
2644 case PaintOrder::MarkersStroke:
2645 paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueMarkers));
2646 paintOrderList->append(CSSPrimitiveValue::createIdentifier(CSSValueStroke));
2647 break;
2648 }
2649 return paintOrderList;
2650}
2651
2652inline static bool isFlexOrGrid(ContainerNode* element)
2653{
2654 return element && element->computedStyle() && element->computedStyle()->isDisplayFlexibleOrGridBox();
2655}
2656
2657RefPtr<CSSValue> ComputedStyleExtractor::customPropertyValue(const String& propertyName)
2658{
2659 Element* styledElement = this->styledElement();
2660 if (!styledElement)
2661 return nullptr;
2662
2663 if (updateStyleIfNeededForProperty(*styledElement, CSSPropertyCustom)) {
2664 // Style update may change styledElement() to PseudoElement or back.
2665 styledElement = this->styledElement();
2666 }
2667
2668 std::unique_ptr<RenderStyle> ownedStyle;
2669 auto* style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, CSSPropertyCustom, ownedStyle);
2670 if (!style)
2671 return nullptr;
2672
2673 auto* registered = styledElement->document().getCSSRegisteredCustomPropertySet().get(propertyName);
2674 auto* value = style->getCustomProperty(propertyName);
2675
2676 if (registered && !value)
2677 return registered->initialValueCopy();
2678
2679 if (!value)
2680 return nullptr;
2681
2682 return WTF::switchOn(value->value(), [&](const Ref<CSSVariableReferenceValue>&) {
2683 ASSERT_NOT_REACHED();
2684 return RefPtr<CSSValue>();
2685 }, [&](const CSSValueID&) {
2686 return CSSCustomPropertyValue::create(*value);
2687 }, [&](const Ref<CSSVariableData>&) {
2688 return CSSCustomPropertyValue::create(*value);
2689 }, [&](const Length& value) {
2690 return zoomAdjustedPixelValueForLength(value, *style);
2691 }, [&](const Ref<StyleImage>&) {
2692 return CSSCustomPropertyValue::create(*value);
2693 });
2694}
2695
2696String ComputedStyleExtractor::customPropertyText(const String& propertyName)
2697{
2698 RefPtr<CSSValue> propertyValue = customPropertyValue(propertyName);
2699 return propertyValue ? propertyValue->cssText() : emptyString();
2700}
2701
2702static Ref<CSSFontValue> fontShorthandValueForSelectionProperties(const FontDescription& fontDescription)
2703{
2704 auto computedFont = CSSFontValue::create();
2705
2706 auto variantCaps = fontDescription.variantCaps();
2707 if (variantCaps == FontVariantCaps::Small)
2708 computedFont->variant = CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps);
2709 else if (variantCaps == FontVariantCaps::Normal)
2710 computedFont->variant = CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
2711 else
2712 return CSSFontValue::create();
2713
2714 auto weight = fontDescription.weight();
2715 if (auto value = fontWeightKeyword(weight))
2716 computedFont->weight = CSSValuePool::singleton().createIdentifierValue(value.value());
2717 else if (isCSS21Weight(weight))
2718 computedFont->weight = CSSValuePool::singleton().createValue(static_cast<float>(weight), CSSPrimitiveValue::CSS_NUMBER);
2719 else
2720 return CSSFontValue::create();
2721
2722 if (auto keyword = fontStretchKeyword(fontDescription.stretch()))
2723 computedFont->stretch = CSSValuePool::singleton().createIdentifierValue(keyword.value());
2724 else
2725 return CSSFontValue::create();
2726
2727 if (auto italic = fontStyleKeyword(fontDescription.italic(), fontDescription.fontStyleAxis()))
2728 computedFont->style = CSSFontStyleValue::create(CSSValuePool::singleton().createIdentifierValue(italic.value()));
2729 else
2730 return CSSFontValue::create();
2731
2732 return computedFont;
2733}
2734
2735RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID, EUpdateLayout updateLayout)
2736{
2737 auto* styledElement = this->styledElement();
2738 if (!styledElement)
2739 return nullptr;
2740
2741 std::unique_ptr<RenderStyle> ownedStyle;
2742 const RenderStyle* style = nullptr;
2743 RenderElement* renderer = nullptr;
2744 bool forceFullLayout = false;
2745 if (updateLayout) {
2746 Document& document = m_element->document();
2747
2748 if (updateStyleIfNeededForProperty(*styledElement, propertyID)) {
2749 // Style update may change styledElement() to PseudoElement or back.
2750 styledElement = this->styledElement();
2751 }
2752 renderer = styledRenderer();
2753
2754 if (propertyID == CSSPropertyDisplay && !renderer && is<SVGElement>(*styledElement) && !downcast<SVGElement>(*styledElement).isValid())
2755 return nullptr;
2756
2757 style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, propertyID, ownedStyle);
2758
2759 // FIXME: Some of these cases could be narrowed down or optimized better.
2760 forceFullLayout = isLayoutDependent(propertyID, style, renderer)
2761 || styledElement->isInShadowTree()
2762 || (document.styleScope().resolverIfExists() && document.styleScope().resolverIfExists()->hasViewportDependentMediaQueries() && document.ownerElement());
2763
2764 if (forceFullLayout) {
2765 document.updateLayoutIgnorePendingStylesheets();
2766 styledElement = this->styledElement();
2767 }
2768 }
2769
2770 if (!updateLayout || forceFullLayout) {
2771 style = computeRenderStyleForProperty(*styledElement, m_pseudoElementSpecifier, propertyID, ownedStyle);
2772 renderer = styledRenderer();
2773 }
2774
2775 if (!style)
2776 return nullptr;
2777
2778 return valueForPropertyInStyle(*style, propertyID, renderer);
2779}
2780
2781RefPtr<CSSValue> ComputedStyleExtractor::valueForPropertyInStyle(const RenderStyle& style, CSSPropertyID propertyID, RenderElement* renderer)
2782{
2783 auto& cssValuePool = CSSValuePool::singleton();
2784 propertyID = CSSProperty::resolveDirectionAwareProperty(propertyID, style.direction(), style.writingMode());
2785
2786 switch (propertyID) {
2787 case CSSPropertyInvalid:
2788#if ENABLE(TEXT_AUTOSIZING)
2789 case CSSPropertyInternalTextAutosizingStatus:
2790#endif
2791 break;
2792
2793 case CSSPropertyBackgroundColor:
2794 return cssValuePool.createColorValue(m_allowVisitedStyle? style.visitedDependentColor(CSSPropertyBackgroundColor) : style.backgroundColor());
2795 case CSSPropertyBackgroundImage:
2796 case CSSPropertyWebkitMaskImage: {
2797 auto& layers = propertyID == CSSPropertyWebkitMaskImage ? style.maskLayers() : style.backgroundLayers();
2798 if (!layers.next()) {
2799 if (layers.image())
2800 return layers.image()->cssValue();
2801 return cssValuePool.createIdentifierValue(CSSValueNone);
2802 }
2803 auto list = CSSValueList::createCommaSeparated();
2804 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next()) {
2805 if (currLayer->image())
2806 list->append(currLayer->image()->cssValue());
2807 else
2808 list->append(cssValuePool.createIdentifierValue(CSSValueNone));
2809 }
2810 return list;
2811 }
2812 case CSSPropertyBackgroundSize:
2813 case CSSPropertyWebkitBackgroundSize:
2814 case CSSPropertyWebkitMaskSize: {
2815 auto& layers = propertyID == CSSPropertyWebkitMaskSize ? style.maskLayers() : style.backgroundLayers();
2816 if (!layers.next())
2817 return fillSizeToCSSValue(layers.size(), style);
2818 auto list = CSSValueList::createCommaSeparated();
2819 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2820 list->append(fillSizeToCSSValue(currLayer->size(), style));
2821 return list;
2822 }
2823 case CSSPropertyBackgroundRepeat:
2824 case CSSPropertyWebkitMaskRepeat: {
2825 auto& layers = propertyID == CSSPropertyWebkitMaskRepeat ? style.maskLayers() : style.backgroundLayers();
2826 if (!layers.next())
2827 return fillRepeatToCSSValue(layers.repeatX(), layers.repeatY());
2828 auto list = CSSValueList::createCommaSeparated();
2829 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2830 list->append(fillRepeatToCSSValue(currLayer->repeatX(), currLayer->repeatY()));
2831 return list;
2832 }
2833 case CSSPropertyWebkitMaskSourceType: {
2834 auto& layers = style.maskLayers();
2835 if (!layers.next())
2836 return fillSourceTypeToCSSValue(layers.maskSourceType());
2837 auto list = CSSValueList::createCommaSeparated();
2838 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2839 list->append(fillSourceTypeToCSSValue(currLayer->maskSourceType()));
2840 return list;
2841 }
2842 case CSSPropertyWebkitBackgroundComposite:
2843 case CSSPropertyWebkitMaskComposite: {
2844 auto& layers = propertyID == CSSPropertyWebkitMaskComposite ? style.maskLayers() : style.backgroundLayers();
2845 if (!layers.next())
2846 return cssValuePool.createValue(layers.composite());
2847 auto list = CSSValueList::createCommaSeparated();
2848 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2849 list->append(cssValuePool.createValue(currLayer->composite()));
2850 return list;
2851 }
2852 case CSSPropertyBackgroundAttachment: {
2853 auto& layers = style.backgroundLayers();
2854 if (!layers.next())
2855 return cssValuePool.createValue(layers.attachment());
2856 auto list = CSSValueList::createCommaSeparated();
2857 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2858 list->append(cssValuePool.createValue(currLayer->attachment()));
2859 return list;
2860 }
2861 case CSSPropertyBackgroundClip:
2862 case CSSPropertyBackgroundOrigin:
2863 case CSSPropertyWebkitBackgroundClip:
2864 case CSSPropertyWebkitBackgroundOrigin:
2865 case CSSPropertyWebkitMaskClip:
2866 case CSSPropertyWebkitMaskOrigin: {
2867 auto& layers = (propertyID == CSSPropertyWebkitMaskClip || propertyID == CSSPropertyWebkitMaskOrigin) ? style.maskLayers() : style.backgroundLayers();
2868 bool isClip = propertyID == CSSPropertyBackgroundClip || propertyID == CSSPropertyWebkitBackgroundClip || propertyID == CSSPropertyWebkitMaskClip;
2869 if (!layers.next())
2870 return cssValuePool.createValue(isClip ? layers.clip() : layers.origin());
2871 auto list = CSSValueList::createCommaSeparated();
2872 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2873 list->append(cssValuePool.createValue(isClip ? currLayer->clip() : currLayer->origin()));
2874 return list;
2875 }
2876 case CSSPropertyBackgroundPosition:
2877 case CSSPropertyWebkitMaskPosition: {
2878 auto& layers = propertyID == CSSPropertyWebkitMaskPosition ? style.maskLayers() : style.backgroundLayers();
2879 if (!layers.next())
2880 return createPositionListForLayer(propertyID, layers, style);
2881
2882 auto list = CSSValueList::createCommaSeparated();
2883 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2884 list->append(createPositionListForLayer(propertyID, *currLayer, style));
2885 return list;
2886 }
2887 case CSSPropertyBackgroundPositionX:
2888 case CSSPropertyWebkitMaskPositionX: {
2889 auto& layers = propertyID == CSSPropertyWebkitMaskPositionX ? style.maskLayers() : style.backgroundLayers();
2890 if (!layers.next())
2891 return cssValuePool.createValue(layers.xPosition());
2892
2893 auto list = CSSValueList::createCommaSeparated();
2894 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2895 list->append(cssValuePool.createValue(currLayer->xPosition()));
2896
2897 return list;
2898 }
2899 case CSSPropertyBackgroundPositionY:
2900 case CSSPropertyWebkitMaskPositionY: {
2901 auto& layers = propertyID == CSSPropertyWebkitMaskPositionY ? style.maskLayers() : style.backgroundLayers();
2902 if (!layers.next())
2903 return cssValuePool.createValue(layers.yPosition());
2904
2905 auto list = CSSValueList::createCommaSeparated();
2906 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2907 list->append(cssValuePool.createValue(currLayer->yPosition()));
2908
2909 return list;
2910 }
2911 case CSSPropertyBorderCollapse:
2912 if (style.borderCollapse() == BorderCollapse::Collapse)
2913 return cssValuePool.createIdentifierValue(CSSValueCollapse);
2914 return cssValuePool.createIdentifierValue(CSSValueSeparate);
2915 case CSSPropertyBorderSpacing: {
2916 auto list = CSSValueList::createSpaceSeparated();
2917 list->append(zoomAdjustedPixelValue(style.horizontalBorderSpacing(), style));
2918 list->append(zoomAdjustedPixelValue(style.verticalBorderSpacing(), style));
2919 return list;
2920 }
2921 case CSSPropertyWebkitBorderHorizontalSpacing:
2922 return zoomAdjustedPixelValue(style.horizontalBorderSpacing(), style);
2923 case CSSPropertyWebkitBorderVerticalSpacing:
2924 return zoomAdjustedPixelValue(style.verticalBorderSpacing(), style);
2925 case CSSPropertyBorderImageSource:
2926 if (style.borderImageSource())
2927 return style.borderImageSource()->cssValue();
2928 return cssValuePool.createIdentifierValue(CSSValueNone);
2929 case CSSPropertyBorderTopColor:
2930 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderTopColor)) : currentColorOrValidColor(&style, style.borderTopColor());
2931 case CSSPropertyBorderRightColor:
2932 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderRightColor)) : currentColorOrValidColor(&style, style.borderRightColor());
2933 case CSSPropertyBorderBottomColor:
2934 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderBottomColor)) : currentColorOrValidColor(&style, style.borderBottomColor());
2935 case CSSPropertyBorderLeftColor:
2936 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderLeftColor)) : currentColorOrValidColor(&style, style.borderLeftColor());
2937 case CSSPropertyBorderTopStyle:
2938 return cssValuePool.createValue(style.borderTopStyle());
2939 case CSSPropertyBorderRightStyle:
2940 return cssValuePool.createValue(style.borderRightStyle());
2941 case CSSPropertyBorderBottomStyle:
2942 return cssValuePool.createValue(style.borderBottomStyle());
2943 case CSSPropertyBorderLeftStyle:
2944 return cssValuePool.createValue(style.borderLeftStyle());
2945 case CSSPropertyBorderTopWidth:
2946 return zoomAdjustedPixelValue(style.borderTopWidth(), style);
2947 case CSSPropertyBorderRightWidth:
2948 return zoomAdjustedPixelValue(style.borderRightWidth(), style);
2949 case CSSPropertyBorderBottomWidth:
2950 return zoomAdjustedPixelValue(style.borderBottomWidth(), style);
2951 case CSSPropertyBorderLeftWidth:
2952 return zoomAdjustedPixelValue(style.borderLeftWidth(), style);
2953 case CSSPropertyBottom:
2954 return positionOffsetValue(style, CSSPropertyBottom, renderer);
2955 case CSSPropertyWebkitBoxAlign:
2956 return cssValuePool.createValue(style.boxAlign());
2957#if ENABLE(CSS_BOX_DECORATION_BREAK)
2958 case CSSPropertyWebkitBoxDecorationBreak:
2959 if (style.boxDecorationBreak() == BoxDecorationBreak::Slice)
2960 return cssValuePool.createIdentifierValue(CSSValueSlice);
2961 return cssValuePool.createIdentifierValue(CSSValueClone);
2962#endif
2963 case CSSPropertyWebkitBoxDirection:
2964 return cssValuePool.createValue(style.boxDirection());
2965 case CSSPropertyWebkitBoxFlex:
2966 return cssValuePool.createValue(style.boxFlex(), CSSPrimitiveValue::CSS_NUMBER);
2967 case CSSPropertyWebkitBoxFlexGroup:
2968 return cssValuePool.createValue(style.boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER);
2969 case CSSPropertyWebkitBoxLines:
2970 return cssValuePool.createValue(style.boxLines());
2971 case CSSPropertyWebkitBoxOrdinalGroup:
2972 return cssValuePool.createValue(style.boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER);
2973 case CSSPropertyWebkitBoxOrient:
2974 return cssValuePool.createValue(style.boxOrient());
2975 case CSSPropertyWebkitBoxPack:
2976 return cssValuePool.createValue(style.boxPack());
2977 case CSSPropertyWebkitBoxReflect:
2978 return valueForReflection(style.boxReflect(), style);
2979 case CSSPropertyBoxShadow:
2980 case CSSPropertyWebkitBoxShadow:
2981 return valueForShadow(style.boxShadow(), propertyID, style);
2982 case CSSPropertyCaptionSide:
2983 return cssValuePool.createValue(style.captionSide());
2984 case CSSPropertyCaretColor:
2985 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyCaretColor)) : currentColorOrValidColor(&style, style.caretColor());
2986 case CSSPropertyClear:
2987 return cssValuePool.createValue(style.clear());
2988 case CSSPropertyColor:
2989 return cssValuePool.createColorValue(m_allowVisitedStyle ? style.visitedDependentColor(CSSPropertyColor) : style.color());
2990 case CSSPropertyWebkitPrintColorAdjust:
2991 return cssValuePool.createValue(style.printColorAdjust());
2992 case CSSPropertyWebkitColumnAxis:
2993 return cssValuePool.createValue(style.columnAxis());
2994 case CSSPropertyColumnCount:
2995 if (style.hasAutoColumnCount())
2996 return cssValuePool.createIdentifierValue(CSSValueAuto);
2997 return cssValuePool.createValue(style.columnCount(), CSSPrimitiveValue::CSS_NUMBER);
2998 case CSSPropertyColumnFill:
2999 return cssValuePool.createValue(style.columnFill());
3000 case CSSPropertyColumnGap:
3001 if (style.columnGap().isNormal())
3002 return cssValuePool.createIdentifierValue(CSSValueNormal);
3003 return zoomAdjustedPixelValueForLength(style.columnGap().length(), style);
3004 case CSSPropertyRowGap:
3005 if (style.rowGap().isNormal())
3006 return cssValuePool.createIdentifierValue(CSSValueNormal);
3007 return zoomAdjustedPixelValueForLength(style.rowGap().length(), style);
3008 case CSSPropertyWebkitColumnProgression:
3009 return cssValuePool.createValue(style.columnProgression());
3010 case CSSPropertyColumnRuleColor:
3011 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyOutlineColor)) : currentColorOrValidColor(&style, style.columnRuleColor());
3012 case CSSPropertyColumnRuleStyle:
3013 return cssValuePool.createValue(style.columnRuleStyle());
3014 case CSSPropertyColumnRuleWidth:
3015 return zoomAdjustedPixelValue(style.columnRuleWidth(), style);
3016 case CSSPropertyColumnSpan:
3017 return cssValuePool.createIdentifierValue(style.columnSpan() == ColumnSpan::All ? CSSValueAll : CSSValueNone);
3018 case CSSPropertyWebkitColumnBreakAfter:
3019 return cssValuePool.createValue(convertToColumnBreak(style.breakAfter()));
3020 case CSSPropertyWebkitColumnBreakBefore:
3021 return cssValuePool.createValue(convertToColumnBreak(style.breakBefore()));
3022 case CSSPropertyWebkitColumnBreakInside:
3023 return cssValuePool.createValue(convertToColumnBreak(style.breakInside()));
3024 case CSSPropertyColumnWidth:
3025 if (style.hasAutoColumnWidth())
3026 return cssValuePool.createIdentifierValue(CSSValueAuto);
3027 return zoomAdjustedPixelValue(style.columnWidth(), style);
3028 case CSSPropertyTabSize:
3029 return cssValuePool.createValue(style.tabSize().widthInPixels(1.0), style.tabSize().isSpaces() ? CSSPrimitiveValue::CSS_NUMBER : CSSPrimitiveValue::CSS_PX);
3030 case CSSPropertyCursor: {
3031 RefPtr<CSSValueList> list;
3032 auto* cursors = style.cursors();
3033 if (cursors && cursors->size() > 0) {
3034 list = CSSValueList::createCommaSeparated();
3035 for (unsigned i = 0; i < cursors->size(); ++i)
3036 if (StyleImage* image = cursors->at(i).image())
3037 list->append(image->cssValue());
3038 }
3039 auto value = cssValuePool.createValue(style.cursor());
3040 if (list) {
3041 list->append(WTFMove(value));
3042 return list;
3043 }
3044 return value;
3045 }
3046#if ENABLE(CURSOR_VISIBILITY)
3047 case CSSPropertyWebkitCursorVisibility:
3048 return cssValuePool.createValue(style.cursorVisibility());
3049#endif
3050 case CSSPropertyDirection:
3051 return cssValuePool.createValue(style.direction());
3052 case CSSPropertyDisplay:
3053 return cssValuePool.createValue(style.display());
3054 case CSSPropertyEmptyCells:
3055 return cssValuePool.createValue(style.emptyCells());
3056 case CSSPropertyAlignContent:
3057 return valueForContentPositionAndDistributionWithOverflowAlignment(style.alignContent());
3058 case CSSPropertyAlignItems:
3059 return valueForItemPositionWithOverflowAlignment(style.alignItems());
3060 case CSSPropertyAlignSelf:
3061 return valueForItemPositionWithOverflowAlignment(style.alignSelf());
3062 case CSSPropertyFlex:
3063 return getCSSPropertyValuesForShorthandProperties(flexShorthand());
3064 case CSSPropertyFlexBasis:
3065 return cssValuePool.createValue(style.flexBasis(), style);
3066 case CSSPropertyFlexDirection:
3067 return cssValuePool.createValue(style.flexDirection());
3068 case CSSPropertyFlexFlow:
3069 return getCSSPropertyValuesForShorthandProperties(flexFlowShorthand());
3070 case CSSPropertyFlexGrow:
3071 return cssValuePool.createValue(style.flexGrow());
3072 case CSSPropertyFlexShrink:
3073 return cssValuePool.createValue(style.flexShrink());
3074 case CSSPropertyFlexWrap:
3075 return cssValuePool.createValue(style.flexWrap());
3076 case CSSPropertyJustifyContent:
3077 return valueForContentPositionAndDistributionWithOverflowAlignment(style.justifyContent());
3078 case CSSPropertyJustifyItems:
3079 return valueForItemPositionWithOverflowAlignment(style.justifyItems());
3080 case CSSPropertyJustifySelf:
3081 return valueForItemPositionWithOverflowAlignment(style.justifySelf());
3082 case CSSPropertyPlaceContent:
3083 return getCSSPropertyValuesForShorthandProperties(placeContentShorthand());
3084 case CSSPropertyPlaceItems:
3085 return getCSSPropertyValuesForShorthandProperties(placeItemsShorthand());
3086 case CSSPropertyPlaceSelf:
3087 return getCSSPropertyValuesForShorthandProperties(placeSelfShorthand());
3088 case CSSPropertyOrder:
3089 return cssValuePool.createValue(style.order(), CSSPrimitiveValue::CSS_NUMBER);
3090 case CSSPropertyFloat:
3091 if (style.display() != DisplayType::None && style.hasOutOfFlowPosition())
3092 return cssValuePool.createIdentifierValue(CSSValueNone);
3093 return cssValuePool.createValue(style.floating());
3094 case CSSPropertyFont: {
3095 auto computedFont = fontShorthandValueForSelectionProperties(style.fontDescription());
3096 computedFont->size = fontSizeFromStyle(style);
3097 computedFont->lineHeight = lineHeightFromStyle(style);
3098 computedFont->family = fontFamilyListFromStyle(style);
3099 return computedFont;
3100 }
3101 case CSSPropertyFontFamily:
3102 return fontFamilyFromStyle(style);
3103 case CSSPropertyFontSize:
3104 return fontSizeFromStyle(style);
3105 case CSSPropertyFontStyle:
3106 return fontStyleFromStyle(style);
3107 case CSSPropertyFontStretch:
3108 return fontStretchFromStyle(style);
3109 case CSSPropertyFontVariant:
3110 return fontVariantFromStyle(style);
3111 case CSSPropertyFontWeight:
3112 return fontWeightFromStyle(style);
3113 case CSSPropertyFontSynthesis:
3114 return fontSynthesisFromStyle(style);
3115 case CSSPropertyFontFeatureSettings: {
3116 const FontFeatureSettings& featureSettings = style.fontDescription().featureSettings();
3117 if (!featureSettings.size())
3118 return cssValuePool.createIdentifierValue(CSSValueNormal);
3119 auto list = CSSValueList::createCommaSeparated();
3120 for (auto& feature : featureSettings)
3121 list->append(CSSFontFeatureValue::create(FontTag(feature.tag()), feature.value()));
3122 return list;
3123 }
3124#if ENABLE(VARIATION_FONTS)
3125 case CSSPropertyFontVariationSettings: {
3126 const FontVariationSettings& variationSettings = style.fontDescription().variationSettings();
3127 if (variationSettings.isEmpty())
3128 return cssValuePool.createIdentifierValue(CSSValueNormal);
3129 auto list = CSSValueList::createCommaSeparated();
3130 for (auto& feature : variationSettings)
3131 list->append(CSSFontVariationValue::create(feature.tag(), feature.value()));
3132 return list;
3133 }
3134 case CSSPropertyFontOpticalSizing:
3135 return cssValuePool.createValue(style.fontDescription().opticalSizing());
3136#endif
3137 case CSSPropertyGridAutoFlow: {
3138 auto list = CSSValueList::createSpaceSeparated();
3139 ASSERT(style.isGridAutoFlowDirectionRow() || style.isGridAutoFlowDirectionColumn());
3140 if (style.isGridAutoFlowDirectionRow())
3141 list->append(cssValuePool.createIdentifierValue(CSSValueRow));
3142 else
3143 list->append(cssValuePool.createIdentifierValue(CSSValueColumn));
3144
3145 if (style.isGridAutoFlowAlgorithmDense())
3146 list->append(cssValuePool.createIdentifierValue(CSSValueDense));
3147
3148 return list;
3149 }
3150
3151 // Specs mention that getComputedStyle() should return the used value of the property instead of the computed
3152 // one for grid-template-{rows|columns} but not for the grid-auto-{rows|columns} as things like
3153 // grid-auto-columns: 2fr; cannot be resolved to a value in pixels as the '2fr' means very different things
3154 // depending on the size of the explicit grid or the number of implicit tracks added to the grid. See
3155 // http://lists.w3.org/Archives/Public/www-style/2013Nov/0014.html
3156 case CSSPropertyGridAutoColumns:
3157 return valueForGridTrackSizeList(ForColumns, style);
3158 case CSSPropertyGridAutoRows:
3159 return valueForGridTrackSizeList(ForRows, style);
3160
3161 case CSSPropertyGridTemplateColumns:
3162 return valueForGridTrackList(ForColumns, renderer, style);
3163 case CSSPropertyGridTemplateRows:
3164 return valueForGridTrackList(ForRows, renderer, style);
3165
3166 case CSSPropertyGridColumnStart:
3167 return valueForGridPosition(style.gridItemColumnStart());
3168 case CSSPropertyGridColumnEnd:
3169 return valueForGridPosition(style.gridItemColumnEnd());
3170 case CSSPropertyGridRowStart:
3171 return valueForGridPosition(style.gridItemRowStart());
3172 case CSSPropertyGridRowEnd:
3173 return valueForGridPosition(style.gridItemRowEnd());
3174 case CSSPropertyGridArea:
3175 return getCSSPropertyValuesForGridShorthand(gridAreaShorthand());
3176 case CSSPropertyGridTemplate:
3177 return getCSSPropertyValuesForGridShorthand(gridTemplateShorthand());
3178 case CSSPropertyGrid:
3179 return getCSSPropertyValuesForGridShorthand(gridShorthand());
3180 case CSSPropertyGridColumn:
3181 return getCSSPropertyValuesForGridShorthand(gridColumnShorthand());
3182 case CSSPropertyGridRow:
3183 return getCSSPropertyValuesForGridShorthand(gridRowShorthand());
3184 case CSSPropertyGridTemplateAreas:
3185 if (!style.namedGridAreaRowCount()) {
3186 ASSERT(!style.namedGridAreaColumnCount());
3187 return cssValuePool.createIdentifierValue(CSSValueNone);
3188 }
3189 return CSSGridTemplateAreasValue::create(style.namedGridArea(), style.namedGridAreaRowCount(), style.namedGridAreaColumnCount());
3190 case CSSPropertyGap:
3191 return getCSSPropertyValuesForShorthandProperties(gapShorthand());
3192 case CSSPropertyHeight:
3193 if (renderer && !renderer->isRenderSVGModelObject()) {
3194 // According to http://www.w3.org/TR/CSS2/visudet.html#the-height-property,
3195 // the "height" property does not apply for non-replaced inline elements.
3196 if (!isNonReplacedInline(*renderer))
3197 return zoomAdjustedPixelValue(sizingBox(*renderer).height(), style);
3198 }
3199 return zoomAdjustedPixelValueForLength(style.height(), style);
3200 case CSSPropertyWebkitHyphens:
3201 return cssValuePool.createValue(style.hyphens());
3202 case CSSPropertyWebkitHyphenateCharacter:
3203 if (style.hyphenationString().isNull())
3204 return cssValuePool.createIdentifierValue(CSSValueAuto);
3205 return cssValuePool.createValue(style.hyphenationString(), CSSPrimitiveValue::CSS_STRING);
3206 case CSSPropertyWebkitHyphenateLimitAfter:
3207 if (style.hyphenationLimitAfter() < 0)
3208 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
3209 return CSSPrimitiveValue::create(style.hyphenationLimitAfter(), CSSPrimitiveValue::CSS_NUMBER);
3210 case CSSPropertyWebkitHyphenateLimitBefore:
3211 if (style.hyphenationLimitBefore() < 0)
3212 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
3213 return CSSPrimitiveValue::create(style.hyphenationLimitBefore(), CSSPrimitiveValue::CSS_NUMBER);
3214 case CSSPropertyWebkitHyphenateLimitLines:
3215 if (style.hyphenationLimitLines() < 0)
3216 return CSSPrimitiveValue::createIdentifier(CSSValueNoLimit);
3217 return CSSPrimitiveValue::create(style.hyphenationLimitLines(), CSSPrimitiveValue::CSS_NUMBER);
3218 case CSSPropertyWebkitBorderFit:
3219 if (style.borderFit() == BorderFit::Border)
3220 return cssValuePool.createIdentifierValue(CSSValueBorder);
3221 return cssValuePool.createIdentifierValue(CSSValueLines);
3222#if ENABLE(CSS_IMAGE_ORIENTATION)
3223 case CSSPropertyImageOrientation:
3224 return cssValuePool.createValue(style.imageOrientation());
3225#endif
3226 case CSSPropertyImageRendering:
3227 return CSSPrimitiveValue::create(style.imageRendering());
3228#if ENABLE(CSS_IMAGE_RESOLUTION)
3229 case CSSPropertyImageResolution:
3230 return cssValuePool.createValue(style.imageResolution(), CSSPrimitiveValue::CSS_DPPX);
3231#endif
3232 case CSSPropertyLeft:
3233 return positionOffsetValue(style, CSSPropertyLeft, renderer);
3234 case CSSPropertyLetterSpacing:
3235 if (!style.letterSpacing())
3236 return cssValuePool.createIdentifierValue(CSSValueNormal);
3237 return zoomAdjustedPixelValue(style.letterSpacing(), style);
3238 case CSSPropertyWebkitLineClamp:
3239 if (style.lineClamp().isNone())
3240 return cssValuePool.createIdentifierValue(CSSValueNone);
3241 return cssValuePool.createValue(style.lineClamp().value(), style.lineClamp().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER);
3242 case CSSPropertyLineHeight:
3243 return lineHeightFromStyle(style);
3244 case CSSPropertyListStyleImage:
3245 if (style.listStyleImage())
3246 return style.listStyleImage()->cssValue();
3247 return cssValuePool.createIdentifierValue(CSSValueNone);
3248 case CSSPropertyListStylePosition:
3249 return cssValuePool.createValue(style.listStylePosition());
3250 case CSSPropertyListStyleType:
3251 return cssValuePool.createValue(style.listStyleType());
3252 case CSSPropertyWebkitLocale:
3253 if (style.locale().isNull())
3254 return cssValuePool.createIdentifierValue(CSSValueAuto);
3255 return cssValuePool.createValue(style.locale(), CSSPrimitiveValue::CSS_STRING);
3256 case CSSPropertyMarginTop:
3257 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginTop, &RenderBoxModelObject::marginTop>(style, renderer);
3258 case CSSPropertyMarginRight: {
3259 Length marginRight = style.marginRight();
3260 if (marginRight.isFixed() || !is<RenderBox>(renderer))
3261 return zoomAdjustedPixelValueForLength(marginRight, style);
3262 float value;
3263 if (marginRight.isPercentOrCalculated()) {
3264 // RenderBox gives a marginRight() that is the distance between the right-edge of the child box
3265 // and the right-edge of the containing box, when display == DisplayType::Block. Let's calculate the absolute
3266 // value of the specified margin-right % instead of relying on RenderBox's marginRight() value.
3267 value = minimumValueForLength(marginRight, downcast<RenderBox>(*renderer).containingBlockLogicalWidthForContent());
3268 } else
3269 value = downcast<RenderBox>(*renderer).marginRight();
3270 return zoomAdjustedPixelValue(value, style);
3271 }
3272 case CSSPropertyMarginBottom:
3273 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginBottom, &RenderBoxModelObject::marginBottom>(style, renderer);
3274 case CSSPropertyMarginLeft:
3275 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginLeft, &RenderBoxModelObject::marginLeft>(style, renderer);
3276 case CSSPropertyWebkitMarqueeDirection:
3277 return cssValuePool.createValue(style.marqueeDirection());
3278 case CSSPropertyWebkitMarqueeIncrement:
3279 return cssValuePool.createValue(style.marqueeIncrement());
3280 case CSSPropertyWebkitMarqueeRepetition:
3281 if (style.marqueeLoopCount() < 0)
3282 return cssValuePool.createIdentifierValue(CSSValueInfinite);
3283 return cssValuePool.createValue(style.marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER);
3284 case CSSPropertyWebkitMarqueeStyle:
3285 return cssValuePool.createValue(style.marqueeBehavior());
3286 case CSSPropertyWebkitUserModify:
3287 return cssValuePool.createValue(style.userModify());
3288 case CSSPropertyMaxHeight: {
3289 const Length& maxHeight = style.maxHeight();
3290 if (maxHeight.isUndefined())
3291 return cssValuePool.createIdentifierValue(CSSValueNone);
3292 return zoomAdjustedPixelValueForLength(maxHeight, style);
3293 }
3294 case CSSPropertyMaxWidth: {
3295 const Length& maxWidth = style.maxWidth();
3296 if (maxWidth.isUndefined())
3297 return cssValuePool.createIdentifierValue(CSSValueNone);
3298 return zoomAdjustedPixelValueForLength(maxWidth, style);
3299 }
3300 case CSSPropertyMinHeight:
3301 if (style.minHeight().isAuto()) {
3302 auto* styledElement = this->styledElement();
3303 if (styledElement && isFlexOrGrid(styledElement->parentNode()))
3304 return cssValuePool.createIdentifierValue(CSSValueAuto);
3305 return zoomAdjustedPixelValue(0, style);
3306 }
3307 return zoomAdjustedPixelValueForLength(style.minHeight(), style);
3308 case CSSPropertyMinWidth:
3309 if (style.minWidth().isAuto()) {
3310 auto* styledElement = this->styledElement();
3311 if (styledElement && isFlexOrGrid(styledElement->parentNode()))
3312 return cssValuePool.createIdentifierValue(CSSValueAuto);
3313 return zoomAdjustedPixelValue(0, style);
3314 }
3315 return zoomAdjustedPixelValueForLength(style.minWidth(), style);
3316 case CSSPropertyObjectFit:
3317 return cssValuePool.createValue(style.objectFit());
3318 case CSSPropertyObjectPosition: {
3319 auto list = CSSValueList::createSpaceSeparated();
3320 list->append(zoomAdjustedPixelValueForLength(style.objectPosition().x(), style));
3321 list->append(zoomAdjustedPixelValueForLength(style.objectPosition().y(), style));
3322 return list;
3323 }
3324 case CSSPropertyOpacity:
3325 return cssValuePool.createValue(style.opacity(), CSSPrimitiveValue::CSS_NUMBER);
3326 case CSSPropertyOrphans:
3327 if (style.hasAutoOrphans())
3328 return cssValuePool.createIdentifierValue(CSSValueAuto);
3329 return cssValuePool.createValue(style.orphans(), CSSPrimitiveValue::CSS_NUMBER);
3330 case CSSPropertyOutlineColor:
3331 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyOutlineColor)) : currentColorOrValidColor(&style, style.outlineColor());
3332 case CSSPropertyOutlineOffset:
3333 return zoomAdjustedPixelValue(style.outlineOffset(), style);
3334 case CSSPropertyOutlineStyle:
3335 if (style.outlineStyleIsAuto() == OutlineIsAuto::On)
3336 return cssValuePool.createIdentifierValue(CSSValueAuto);
3337 return cssValuePool.createValue(style.outlineStyle());
3338 case CSSPropertyOutlineWidth:
3339 return zoomAdjustedPixelValue(style.outlineWidth(), style);
3340 case CSSPropertyOverflow:
3341 return cssValuePool.createValue(std::max(style.overflowX(), style.overflowY()));
3342 case CSSPropertyOverflowWrap:
3343 return cssValuePool.createValue(style.overflowWrap());
3344 case CSSPropertyOverflowX:
3345 return cssValuePool.createValue(style.overflowX());
3346 case CSSPropertyOverflowY:
3347 return cssValuePool.createValue(style.overflowY());
3348 case CSSPropertyPaddingTop:
3349 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingTop, &RenderBoxModelObject::computedCSSPaddingTop>(style, renderer);
3350 case CSSPropertyPaddingRight:
3351 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingRight, &RenderBoxModelObject::computedCSSPaddingRight>(style, renderer);
3352 case CSSPropertyPaddingBottom:
3353 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingBottom, &RenderBoxModelObject::computedCSSPaddingBottom>(style, renderer);
3354 case CSSPropertyPaddingLeft:
3355 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingLeft, &RenderBoxModelObject::computedCSSPaddingLeft>(style, renderer);
3356 case CSSPropertyPageBreakAfter:
3357 return cssValuePool.createValue(convertToPageBreak(style.breakAfter()));
3358 case CSSPropertyPageBreakBefore:
3359 return cssValuePool.createValue(convertToPageBreak(style.breakBefore()));
3360 case CSSPropertyPageBreakInside:
3361 return cssValuePool.createValue(convertToPageBreak(style.breakInside()));
3362 case CSSPropertyBreakAfter:
3363 return cssValuePool.createValue(style.breakAfter());
3364 case CSSPropertyBreakBefore:
3365 return cssValuePool.createValue(style.breakBefore());
3366 case CSSPropertyBreakInside:
3367 return cssValuePool.createValue(style.breakInside());
3368 case CSSPropertyHangingPunctuation:
3369 return hangingPunctuationToCSSValue(style.hangingPunctuation());
3370 case CSSPropertyPosition:
3371 return cssValuePool.createValue(style.position());
3372 case CSSPropertyRight:
3373 return positionOffsetValue(style, CSSPropertyRight, renderer);
3374 case CSSPropertyWebkitRubyPosition:
3375 return cssValuePool.createValue(style.rubyPosition());
3376 case CSSPropertyTableLayout:
3377 return cssValuePool.createValue(style.tableLayout());
3378 case CSSPropertyTextAlign:
3379 return cssValuePool.createValue(style.textAlign());
3380 case CSSPropertyTextDecoration:
3381 return renderTextDecorationFlagsToCSSValue(style.textDecoration());
3382#if ENABLE(CSS3_TEXT)
3383 case CSSPropertyWebkitTextAlignLast:
3384 return cssValuePool.createValue(style.textAlignLast());
3385 case CSSPropertyWebkitTextJustify:
3386 return cssValuePool.createValue(style.textJustify());
3387#endif // CSS3_TEXT
3388 case CSSPropertyWebkitTextDecoration:
3389 return getCSSPropertyValuesForShorthandProperties(webkitTextDecorationShorthand());
3390 case CSSPropertyTextDecorationLine:
3391 return renderTextDecorationFlagsToCSSValue(style.textDecoration());
3392 case CSSPropertyTextDecorationStyle:
3393 return renderTextDecorationStyleFlagsToCSSValue(style.textDecorationStyle());
3394 case CSSPropertyTextDecorationColor:
3395 return currentColorOrValidColor(&style, style.textDecorationColor());
3396 case CSSPropertyTextDecorationSkip:
3397 return renderTextDecorationSkipFlagsToCSSValue(style.textDecorationSkip());
3398 case CSSPropertyTextUnderlinePosition:
3399 return cssValuePool.createValue(style.textUnderlinePosition());
3400 case CSSPropertyTextUnderlineOffset:
3401 return textUnderlineOffsetToCSSValue(style.textUnderlineOffset());
3402 case CSSPropertyTextDecorationThickness:
3403 return textDecorationThicknessToCSSValue(style.textDecorationThickness());
3404 case CSSPropertyWebkitTextDecorationsInEffect:
3405 return renderTextDecorationFlagsToCSSValue(style.textDecorationsInEffect());
3406 case CSSPropertyWebkitTextFillColor:
3407 return currentColorOrValidColor(&style, style.textFillColor());
3408 case CSSPropertyWebkitTextEmphasisColor:
3409 return currentColorOrValidColor(&style, style.textEmphasisColor());
3410 case CSSPropertyWebkitTextEmphasisPosition:
3411 return renderEmphasisPositionFlagsToCSSValue(style.textEmphasisPosition());
3412 case CSSPropertyWebkitTextEmphasisStyle:
3413 switch (style.textEmphasisMark()) {
3414 case TextEmphasisMark::None:
3415 return cssValuePool.createIdentifierValue(CSSValueNone);
3416 case TextEmphasisMark::Custom:
3417 return cssValuePool.createValue(style.textEmphasisCustomMark(), CSSPrimitiveValue::CSS_STRING);
3418 case TextEmphasisMark::Auto:
3419 ASSERT_NOT_REACHED();
3420#if ASSERT_DISABLED
3421 FALLTHROUGH;
3422#endif
3423 case TextEmphasisMark::Dot:
3424 case TextEmphasisMark::Circle:
3425 case TextEmphasisMark::DoubleCircle:
3426 case TextEmphasisMark::Triangle:
3427 case TextEmphasisMark::Sesame:
3428 auto list = CSSValueList::createSpaceSeparated();
3429 list->append(cssValuePool.createValue(style.textEmphasisFill()));
3430 list->append(cssValuePool.createValue(style.textEmphasisMark()));
3431 return list;
3432 }
3433 RELEASE_ASSERT_NOT_REACHED();
3434 case CSSPropertyTextIndent: {
3435 // If CSS3_TEXT is disabled or text-indent has only one value(<length> | <percentage>),
3436 // getPropertyCSSValue() returns CSSValue.
3437 auto textIndent = zoomAdjustedPixelValueForLength(style.textIndent(), style);
3438#if ENABLE(CSS3_TEXT)
3439 // If CSS3_TEXT is enabled and text-indent has -webkit-each-line or -webkit-hanging,
3440 // getPropertyCSSValue() returns CSSValueList.
3441 if (style.textIndentLine() == TextIndentLine::EachLine || style.textIndentType() == TextIndentType::Hanging) {
3442 auto list = CSSValueList::createSpaceSeparated();
3443 list->append(WTFMove(textIndent));
3444 if (style.textIndentLine() == TextIndentLine::EachLine)
3445 list->append(cssValuePool.createIdentifierValue(CSSValueWebkitEachLine));
3446 if (style.textIndentType() == TextIndentType::Hanging)
3447 list->append(cssValuePool.createIdentifierValue(CSSValueWebkitHanging));
3448 return list;
3449 }
3450#endif
3451 return textIndent;
3452 }
3453 case CSSPropertyTextShadow:
3454 return valueForShadow(style.textShadow(), propertyID, style);
3455 case CSSPropertyTextRendering:
3456 return cssValuePool.createValue(style.fontDescription().textRenderingMode());
3457 case CSSPropertyTextOverflow:
3458 if (style.textOverflow() == TextOverflow::Ellipsis)
3459 return cssValuePool.createIdentifierValue(CSSValueEllipsis);
3460 return cssValuePool.createIdentifierValue(CSSValueClip);
3461 case CSSPropertyWebkitTextSecurity:
3462 return cssValuePool.createValue(style.textSecurity());
3463#if ENABLE(TEXT_AUTOSIZING)
3464 case CSSPropertyWebkitTextSizeAdjust:
3465 if (style.textSizeAdjust().isAuto())
3466 return cssValuePool.createIdentifierValue(CSSValueAuto);
3467 if (style.textSizeAdjust().isNone())
3468 return cssValuePool.createIdentifierValue(CSSValueNone);
3469 return CSSPrimitiveValue::create(style.textSizeAdjust().percentage(), CSSPrimitiveValue::CSS_PERCENTAGE);
3470#endif
3471 case CSSPropertyWebkitTextStrokeColor:
3472 return currentColorOrValidColor(&style, style.textStrokeColor());
3473 case CSSPropertyWebkitTextStrokeWidth:
3474 return zoomAdjustedPixelValue(style.textStrokeWidth(), style);
3475 case CSSPropertyTextTransform:
3476 return cssValuePool.createValue(style.textTransform());
3477 case CSSPropertyTop:
3478 return positionOffsetValue(style, CSSPropertyTop, renderer);
3479 case CSSPropertyUnicodeBidi:
3480 return cssValuePool.createValue(style.unicodeBidi());
3481 case CSSPropertyVerticalAlign:
3482 switch (style.verticalAlign()) {
3483 case VerticalAlign::Baseline:
3484 return cssValuePool.createIdentifierValue(CSSValueBaseline);
3485 case VerticalAlign::Middle:
3486 return cssValuePool.createIdentifierValue(CSSValueMiddle);
3487 case VerticalAlign::Sub:
3488 return cssValuePool.createIdentifierValue(CSSValueSub);
3489 case VerticalAlign::Super:
3490 return cssValuePool.createIdentifierValue(CSSValueSuper);
3491 case VerticalAlign::TextTop:
3492 return cssValuePool.createIdentifierValue(CSSValueTextTop);
3493 case VerticalAlign::TextBottom:
3494 return cssValuePool.createIdentifierValue(CSSValueTextBottom);
3495 case VerticalAlign::Top:
3496 return cssValuePool.createIdentifierValue(CSSValueTop);
3497 case VerticalAlign::Bottom:
3498 return cssValuePool.createIdentifierValue(CSSValueBottom);
3499 case VerticalAlign::BaselineMiddle:
3500 return cssValuePool.createIdentifierValue(CSSValueWebkitBaselineMiddle);
3501 case VerticalAlign::Length:
3502 return cssValuePool.createValue(style.verticalAlignLength());
3503 }
3504 ASSERT_NOT_REACHED();
3505 return nullptr;
3506 case CSSPropertyVisibility:
3507 return cssValuePool.createValue(style.visibility());
3508 case CSSPropertyWhiteSpace:
3509 return cssValuePool.createValue(style.whiteSpace());
3510 case CSSPropertyWidows:
3511 if (style.hasAutoWidows())
3512 return cssValuePool.createIdentifierValue(CSSValueAuto);
3513 return cssValuePool.createValue(style.widows(), CSSPrimitiveValue::CSS_NUMBER);
3514 case CSSPropertyWidth:
3515 if (renderer && !renderer->isRenderSVGModelObject()) {
3516 // According to http://www.w3.org/TR/CSS2/visudet.html#the-width-property,
3517 // the "width" property does not apply for non-replaced inline elements.
3518 if (!isNonReplacedInline(*renderer))
3519 return zoomAdjustedPixelValue(sizingBox(*renderer).width(), style);
3520 }
3521 return zoomAdjustedPixelValueForLength(style.width(), style);
3522 case CSSPropertyWillChange:
3523 return willChangePropertyValue(style.willChange());
3524 case CSSPropertyWordBreak:
3525 return cssValuePool.createValue(style.wordBreak());
3526 case CSSPropertyWordSpacing:
3527 return zoomAdjustedPixelValue(style.fontCascade().wordSpacing(), style);
3528 case CSSPropertyWordWrap:
3529 return cssValuePool.createValue(style.overflowWrap());
3530 case CSSPropertyLineBreak:
3531 return cssValuePool.createValue(style.lineBreak());
3532 case CSSPropertyWebkitNbspMode:
3533 return cssValuePool.createValue(style.nbspMode());
3534 case CSSPropertyResize:
3535 return cssValuePool.createValue(style.resize());
3536 case CSSPropertyWebkitFontKerning:
3537 return cssValuePool.createValue(style.fontDescription().kerning());
3538 case CSSPropertyWebkitFontSmoothing:
3539 return cssValuePool.createValue(style.fontDescription().fontSmoothing());
3540 case CSSPropertyFontVariantLigatures:
3541 return fontVariantLigaturesPropertyValue(style.fontDescription().variantCommonLigatures(), style.fontDescription().variantDiscretionaryLigatures(), style.fontDescription().variantHistoricalLigatures(), style.fontDescription().variantContextualAlternates());
3542 case CSSPropertyFontVariantPosition:
3543 return fontVariantPositionPropertyValue(style.fontDescription().variantPosition());
3544 case CSSPropertyFontVariantCaps:
3545 return fontVariantCapsPropertyValue(style.fontDescription().variantCaps());
3546 case CSSPropertyFontVariantNumeric:
3547 return fontVariantNumericPropertyValue(style.fontDescription().variantNumericFigure(), style.fontDescription().variantNumericSpacing(), style.fontDescription().variantNumericFraction(), style.fontDescription().variantNumericOrdinal(), style.fontDescription().variantNumericSlashedZero());
3548 case CSSPropertyFontVariantAlternates:
3549 return fontVariantAlternatesPropertyValue(style.fontDescription().variantAlternates());
3550 case CSSPropertyFontVariantEastAsian:
3551 return fontVariantEastAsianPropertyValue(style.fontDescription().variantEastAsianVariant(), style.fontDescription().variantEastAsianWidth(), style.fontDescription().variantEastAsianRuby());
3552 case CSSPropertyZIndex:
3553 if (style.hasAutoZIndex())
3554 return cssValuePool.createIdentifierValue(CSSValueAuto);
3555 return cssValuePool.createValue(style.zIndex(), CSSPrimitiveValue::CSS_NUMBER);
3556 case CSSPropertyZoom:
3557 return cssValuePool.createValue(style.zoom(), CSSPrimitiveValue::CSS_NUMBER);
3558 case CSSPropertyBoxSizing:
3559 if (style.boxSizing() == BoxSizing::ContentBox)
3560 return cssValuePool.createIdentifierValue(CSSValueContentBox);
3561 return cssValuePool.createIdentifierValue(CSSValueBorderBox);
3562 case CSSPropertyAnimationDelay:
3563 return delayValue(style.animations());
3564 case CSSPropertyAnimationDirection: {
3565 auto list = CSSValueList::createCommaSeparated();
3566 const AnimationList* t = style.animations();
3567 if (t) {
3568 for (size_t i = 0; i < t->size(); ++i) {
3569 switch (t->animation(i).direction()) {
3570 case Animation::AnimationDirectionNormal:
3571 list->append(cssValuePool.createIdentifierValue(CSSValueNormal));
3572 break;
3573 case Animation::AnimationDirectionAlternate:
3574 list->append(cssValuePool.createIdentifierValue(CSSValueAlternate));
3575 break;
3576 case Animation::AnimationDirectionReverse:
3577 list->append(cssValuePool.createIdentifierValue(CSSValueReverse));
3578 break;
3579 case Animation::AnimationDirectionAlternateReverse:
3580 list->append(cssValuePool.createIdentifierValue(CSSValueAlternateReverse));
3581 break;
3582 }
3583 }
3584 } else
3585 list->append(cssValuePool.createIdentifierValue(CSSValueNormal));
3586 return list;
3587 }
3588 case CSSPropertyAnimationDuration:
3589 return durationValue(style.animations());
3590 case CSSPropertyAnimationFillMode: {
3591 auto list = CSSValueList::createCommaSeparated();
3592 const AnimationList* t = style.animations();
3593 if (t) {
3594 for (size_t i = 0; i < t->size(); ++i) {
3595 switch (t->animation(i).fillMode()) {
3596 case AnimationFillMode::None:
3597 list->append(cssValuePool.createIdentifierValue(CSSValueNone));
3598 break;
3599 case AnimationFillMode::Forwards:
3600 list->append(cssValuePool.createIdentifierValue(CSSValueForwards));
3601 break;
3602 case AnimationFillMode::Backwards:
3603 list->append(cssValuePool.createIdentifierValue(CSSValueBackwards));
3604 break;
3605 case AnimationFillMode::Both:
3606 list->append(cssValuePool.createIdentifierValue(CSSValueBoth));
3607 break;
3608 }
3609 }
3610 } else
3611 list->append(cssValuePool.createIdentifierValue(CSSValueNone));
3612 return list;
3613 }
3614 case CSSPropertyAnimationIterationCount: {
3615 auto list = CSSValueList::createCommaSeparated();
3616 const AnimationList* t = style.animations();
3617 if (t) {
3618 for (size_t i = 0; i < t->size(); ++i) {
3619 double iterationCount = t->animation(i).iterationCount();
3620 if (iterationCount == Animation::IterationCountInfinite)
3621 list->append(cssValuePool.createIdentifierValue(CSSValueInfinite));
3622 else
3623 list->append(cssValuePool.createValue(iterationCount, CSSPrimitiveValue::CSS_NUMBER));
3624 }
3625 } else
3626 list->append(cssValuePool.createValue(Animation::initialIterationCount(), CSSPrimitiveValue::CSS_NUMBER));
3627 return list;
3628 }
3629 case CSSPropertyAnimationName: {
3630 auto list = CSSValueList::createCommaSeparated();
3631 const AnimationList* t = style.animations();
3632 if (t) {
3633 for (size_t i = 0; i < t->size(); ++i)
3634 list->append(cssValuePool.createValue(t->animation(i).name(), CSSPrimitiveValue::CSS_STRING));
3635 } else
3636 list->append(cssValuePool.createIdentifierValue(CSSValueNone));
3637 return list;
3638 }
3639 case CSSPropertyAnimationPlayState: {
3640 auto list = CSSValueList::createCommaSeparated();
3641 const AnimationList* t = style.animations();
3642 if (t) {
3643 for (size_t i = 0; i < t->size(); ++i) {
3644 switch (t->animation(i).playState()) {
3645 case AnimationPlayState::Playing:
3646 list->append(cssValuePool.createIdentifierValue(CSSValueRunning));
3647 break;
3648 case AnimationPlayState::Paused:
3649 list->append(cssValuePool.createIdentifierValue(CSSValuePaused));
3650 break;
3651 }
3652 }
3653 } else
3654 list->append(cssValuePool.createIdentifierValue(CSSValueRunning));
3655 return list;
3656 }
3657 case CSSPropertyAnimationTimingFunction:
3658 return timingFunctionValue(style.animations());
3659 case CSSPropertyWebkitAppearance:
3660 return cssValuePool.createValue(style.appearance());
3661 case CSSPropertyWebkitAspectRatio:
3662 switch (style.aspectRatioType()) {
3663 case AspectRatioType::Auto:
3664 return cssValuePool.createIdentifierValue(CSSValueAuto);
3665 case AspectRatioType::FromDimensions:
3666 return cssValuePool.createIdentifierValue(CSSValueFromDimensions);
3667 case AspectRatioType::FromIntrinsic:
3668 return cssValuePool.createIdentifierValue(CSSValueFromIntrinsic);
3669 case AspectRatioType::Specified:
3670 return CSSAspectRatioValue::create(style.aspectRatioNumerator(), style.aspectRatioDenominator());
3671 }
3672 ASSERT_NOT_REACHED();
3673 return nullptr;
3674 case CSSPropertyWebkitBackfaceVisibility:
3675 return cssValuePool.createIdentifierValue((style.backfaceVisibility() == BackfaceVisibility::Hidden) ? CSSValueHidden : CSSValueVisible);
3676 case CSSPropertyWebkitBorderImage:
3677 return valueForNinePieceImage(style.borderImage());
3678 case CSSPropertyBorderImageOutset:
3679 return valueForNinePieceImageQuad(style.borderImage().outset());
3680 case CSSPropertyBorderImageRepeat:
3681 return valueForNinePieceImageRepeat(style.borderImage());
3682 case CSSPropertyBorderImageSlice:
3683 return valueForNinePieceImageSlice(style.borderImage());
3684 case CSSPropertyBorderImageWidth:
3685 return valueForNinePieceImageQuad(style.borderImage().borderSlices());
3686 case CSSPropertyWebkitMaskBoxImage:
3687 return valueForNinePieceImage(style.maskBoxImage());
3688 case CSSPropertyWebkitMaskBoxImageOutset:
3689 return valueForNinePieceImageQuad(style.maskBoxImage().outset());
3690 case CSSPropertyWebkitMaskBoxImageRepeat:
3691 return valueForNinePieceImageRepeat(style.maskBoxImage());
3692 case CSSPropertyWebkitMaskBoxImageSlice:
3693 return valueForNinePieceImageSlice(style.maskBoxImage());
3694 case CSSPropertyWebkitMaskBoxImageWidth:
3695 return valueForNinePieceImageQuad(style.maskBoxImage().borderSlices());
3696 case CSSPropertyWebkitMaskBoxImageSource:
3697 if (style.maskBoxImageSource())
3698 return style.maskBoxImageSource()->cssValue();
3699 return cssValuePool.createIdentifierValue(CSSValueNone);
3700 case CSSPropertyWebkitFontSizeDelta:
3701 // Not a real style property -- used by the editing engine -- so has no computed value.
3702 break;
3703 case CSSPropertyWebkitInitialLetter: {
3704 auto drop = !style.initialLetterDrop() ? cssValuePool.createIdentifierValue(CSSValueNormal) : cssValuePool.createValue(style.initialLetterDrop(), CSSPrimitiveValue::CSS_NUMBER);
3705 auto size = !style.initialLetterHeight() ? cssValuePool.createIdentifierValue(CSSValueNormal) : cssValuePool.createValue(style.initialLetterHeight(), CSSPrimitiveValue::CSS_NUMBER);
3706 return cssValuePool.createValue(Pair::create(WTFMove(drop), WTFMove(size)));
3707 }
3708 case CSSPropertyWebkitMarginBottomCollapse:
3709 case CSSPropertyWebkitMarginAfterCollapse:
3710 return cssValuePool.createValue(style.marginAfterCollapse());
3711 case CSSPropertyWebkitMarginTopCollapse:
3712 case CSSPropertyWebkitMarginBeforeCollapse:
3713 return cssValuePool.createValue(style.marginBeforeCollapse());
3714#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
3715 case CSSPropertyWebkitOverflowScrolling:
3716 if (!style.useTouchOverflowScrolling())
3717 return cssValuePool.createIdentifierValue(CSSValueAuto);
3718 return cssValuePool.createIdentifierValue(CSSValueTouch);
3719#endif
3720 case CSSPropertyPerspective:
3721 if (!style.hasPerspective())
3722 return cssValuePool.createIdentifierValue(CSSValueNone);
3723 return zoomAdjustedPixelValue(style.perspective(), style);
3724 case CSSPropertyPerspectiveOrigin: {
3725 auto list = CSSValueList::createSpaceSeparated();
3726 if (renderer) {
3727 LayoutRect box;
3728 if (is<RenderBox>(*renderer))
3729 box = downcast<RenderBox>(*renderer).borderBoxRect();
3730
3731 list->append(zoomAdjustedPixelValue(minimumValueForLength(style.perspectiveOriginX(), box.width()), style));
3732 list->append(zoomAdjustedPixelValue(minimumValueForLength(style.perspectiveOriginY(), box.height()), style));
3733 } else {
3734 list->append(zoomAdjustedPixelValueForLength(style.perspectiveOriginX(), style));
3735 list->append(zoomAdjustedPixelValueForLength(style.perspectiveOriginY(), style));
3736 }
3737 return list;
3738 }
3739 case CSSPropertyWebkitRtlOrdering:
3740 return cssValuePool.createIdentifierValue(style.rtlOrdering() == Order::Visual ? CSSValueVisual : CSSValueLogical);
3741#if ENABLE(TOUCH_EVENTS)
3742 case CSSPropertyWebkitTapHighlightColor:
3743 return currentColorOrValidColor(&style, style.tapHighlightColor());
3744#endif
3745#if ENABLE(POINTER_EVENTS)
3746 case CSSPropertyTouchAction:
3747 return touchActionFlagsToCSSValue(style.touchActions());
3748#endif
3749#if PLATFORM(IOS_FAMILY)
3750 case CSSPropertyWebkitTouchCallout:
3751 return cssValuePool.createIdentifierValue(style.touchCalloutEnabled() ? CSSValueDefault : CSSValueNone);
3752#endif
3753 case CSSPropertyWebkitUserDrag:
3754 return cssValuePool.createValue(style.userDrag());
3755 case CSSPropertyWebkitUserSelect:
3756 return cssValuePool.createValue(style.userSelect());
3757 case CSSPropertyBorderBottomLeftRadius:
3758 return borderRadiusCornerValue(style.borderBottomLeftRadius(), style);
3759 case CSSPropertyBorderBottomRightRadius:
3760 return borderRadiusCornerValue(style.borderBottomRightRadius(), style);
3761 case CSSPropertyBorderTopLeftRadius:
3762 return borderRadiusCornerValue(style.borderTopLeftRadius(), style);
3763 case CSSPropertyBorderTopRightRadius:
3764 return borderRadiusCornerValue(style.borderTopRightRadius(), style);
3765 case CSSPropertyClip: {
3766 if (!style.hasClip())
3767 return cssValuePool.createIdentifierValue(CSSValueAuto);
3768 auto rect = Rect::create();
3769 rect->setTop(autoOrZoomAdjustedValue(style.clip().top(), style));
3770 rect->setRight(autoOrZoomAdjustedValue(style.clip().right(), style));
3771 rect->setBottom(autoOrZoomAdjustedValue(style.clip().bottom(), style));
3772 rect->setLeft(autoOrZoomAdjustedValue(style.clip().left(), style));
3773 return cssValuePool.createValue(WTFMove(rect));
3774 }
3775 case CSSPropertySpeakAs:
3776 return speakAsToCSSValue(style.speakAs());
3777 case CSSPropertyTransform:
3778 return computedTransform(renderer, style);
3779 case CSSPropertyTransformBox:
3780 return CSSPrimitiveValue::create(style.transformBox());
3781 case CSSPropertyTransformOrigin: {
3782 auto list = CSSValueList::createSpaceSeparated();
3783 if (renderer) {
3784 LayoutRect box;
3785 if (is<RenderBox>(*renderer))
3786 box = downcast<RenderBox>(*renderer).borderBoxRect();
3787
3788 list->append(zoomAdjustedPixelValue(minimumValueForLength(style.transformOriginX(), box.width()), style));
3789 list->append(zoomAdjustedPixelValue(minimumValueForLength(style.transformOriginY(), box.height()), style));
3790 if (style.transformOriginZ())
3791 list->append(zoomAdjustedPixelValue(style.transformOriginZ(), style));
3792 } else {
3793 list->append(zoomAdjustedPixelValueForLength(style.transformOriginX(), style));
3794 list->append(zoomAdjustedPixelValueForLength(style.transformOriginY(), style));
3795 if (style.transformOriginZ())
3796 list->append(zoomAdjustedPixelValue(style.transformOriginZ(), style));
3797 }
3798 return list;
3799 }
3800 case CSSPropertyTransformStyle:
3801 case CSSPropertyWebkitTransformStyle:
3802 return cssValuePool.createIdentifierValue((style.transformStyle3D() == TransformStyle3D::Preserve3D) ? CSSValuePreserve3d : CSSValueFlat);
3803 case CSSPropertyTransitionDelay:
3804 return delayValue(style.transitions());
3805 case CSSPropertyTransitionDuration:
3806 return durationValue(style.transitions());
3807 case CSSPropertyTransitionProperty:
3808 return transitionPropertyValue(style.transitions());
3809 case CSSPropertyTransitionTimingFunction:
3810 return timingFunctionValue(style.transitions());
3811 case CSSPropertyTransition: {
3812 if (auto* animationList = style.transitions()) {
3813 auto transitionsList = CSSValueList::createCommaSeparated();
3814 for (size_t i = 0; i < animationList->size(); ++i) {
3815 auto list = CSSValueList::createSpaceSeparated();
3816 auto& animation = animationList->animation(i);
3817 list->append(createTransitionPropertyValue(animation));
3818 list->append(cssValuePool.createValue(animation.duration(), CSSPrimitiveValue::CSS_S));
3819 list->append(createTimingFunctionValue(*animation.timingFunction()));
3820 list->append(cssValuePool.createValue(animation.delay(), CSSPrimitiveValue::CSS_S));
3821 transitionsList->append(WTFMove(list));
3822 }
3823 return transitionsList;
3824 }
3825
3826 auto list = CSSValueList::createSpaceSeparated();
3827 // transition-property default value.
3828 list->append(cssValuePool.createIdentifierValue(CSSValueAll));
3829 list->append(cssValuePool.createValue(Animation::initialDuration(), CSSPrimitiveValue::CSS_S));
3830 list->append(createTimingFunctionValue(Animation::initialTimingFunction()));
3831 list->append(cssValuePool.createValue(Animation::initialDelay(), CSSPrimitiveValue::CSS_S));
3832 return list;
3833 }
3834 case CSSPropertyPointerEvents:
3835 return cssValuePool.createValue(style.pointerEvents());
3836 case CSSPropertyWebkitLineGrid:
3837 if (style.lineGrid().isNull())
3838 return cssValuePool.createIdentifierValue(CSSValueNone);
3839 return cssValuePool.createValue(style.lineGrid(), CSSPrimitiveValue::CSS_STRING);
3840 case CSSPropertyWebkitLineSnap:
3841 return CSSPrimitiveValue::create(style.lineSnap());
3842 case CSSPropertyWebkitLineAlign:
3843 return CSSPrimitiveValue::create(style.lineAlign());
3844 case CSSPropertyWritingMode:
3845 return cssValuePool.createValue(style.writingMode());
3846 case CSSPropertyWebkitTextCombine:
3847 return cssValuePool.createValue(style.textCombine());
3848 case CSSPropertyWebkitTextOrientation:
3849 return CSSPrimitiveValue::create(style.textOrientation());
3850 case CSSPropertyWebkitLineBoxContain:
3851 return createLineBoxContainValue(style.lineBoxContain());
3852 case CSSPropertyAlt:
3853 return altTextToCSSValue(style);
3854 case CSSPropertyContent:
3855 return contentToCSSValue(style);
3856 case CSSPropertyCounterIncrement:
3857 return counterToCSSValue(style, propertyID);
3858 case CSSPropertyCounterReset:
3859 return counterToCSSValue(style, propertyID);
3860 case CSSPropertyWebkitClipPath: {
3861 auto* operation = style.clipPath();
3862 if (!operation)
3863 return cssValuePool.createIdentifierValue(CSSValueNone);
3864 if (is<ReferenceClipPathOperation>(*operation))
3865 return CSSPrimitiveValue::create(downcast<ReferenceClipPathOperation>(*operation).url(), CSSPrimitiveValue::CSS_URI);
3866 auto list = CSSValueList::createSpaceSeparated();
3867 if (is<ShapeClipPathOperation>(*operation)) {
3868 auto& shapeOperation = downcast<ShapeClipPathOperation>(*operation);
3869 list->append(valueForBasicShape(style, shapeOperation.basicShape()));
3870 if (shapeOperation.referenceBox() != CSSBoxType::BoxMissing)
3871 list->append(cssValuePool.createValue(shapeOperation.referenceBox()));
3872 }
3873 if (is<BoxClipPathOperation>(*operation))
3874 list->append(cssValuePool.createValue(downcast<BoxClipPathOperation>(*operation).referenceBox()));
3875 return list;
3876 }
3877 case CSSPropertyShapeMargin:
3878 return cssValuePool.createValue(style.shapeMargin(), style);
3879 case CSSPropertyShapeImageThreshold:
3880 return cssValuePool.createValue(style.shapeImageThreshold(), CSSPrimitiveValue::CSS_NUMBER);
3881 case CSSPropertyShapeOutside:
3882 return shapePropertyValue(style, style.shapeOutside());
3883 case CSSPropertyFilter:
3884 return valueForFilter(style, style.filter());
3885 case CSSPropertyAppleColorFilter:
3886 return valueForFilter(style, style.appleColorFilter());
3887#if ENABLE(FILTERS_LEVEL_2)
3888 case CSSPropertyWebkitBackdropFilter:
3889 return valueForFilter(style, style.backdropFilter());
3890#endif
3891#if ENABLE(CSS_COMPOSITING)
3892 case CSSPropertyMixBlendMode:
3893 return cssValuePool.createValue(style.blendMode());
3894 case CSSPropertyIsolation:
3895 return cssValuePool.createValue(style.isolation());
3896#endif
3897 case CSSPropertyBackgroundBlendMode: {
3898 auto& layers = style.backgroundLayers();
3899 if (!layers.next())
3900 return cssValuePool.createValue(layers.blendMode());
3901 auto list = CSSValueList::createCommaSeparated();
3902 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
3903 list->append(cssValuePool.createValue(currLayer->blendMode()));
3904 return list;
3905 }
3906 case CSSPropertyBackground:
3907 return getBackgroundShorthandValue();
3908 case CSSPropertyBorder: {
3909 auto value = propertyValue(CSSPropertyBorderTop, DoNotUpdateLayout);
3910 const CSSPropertyID properties[3] = { CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft };
3911 for (auto& property : properties) {
3912 if (!compareCSSValuePtr<CSSValue>(value, propertyValue(property, DoNotUpdateLayout)))
3913 return nullptr;
3914 }
3915 return value;
3916 }
3917 case CSSPropertyBorderBlock: {
3918 auto value = propertyValue(CSSPropertyBorderBlockStart, DoNotUpdateLayout);
3919 if (!compareCSSValuePtr<CSSValue>(value, propertyValue(CSSPropertyBorderBlockEnd, DoNotUpdateLayout)))
3920 return nullptr;
3921 return value;
3922 }
3923 case CSSPropertyBorderBlockColor:
3924 return getCSSPropertyValuesFor2SidesShorthand(borderBlockColorShorthand());
3925 case CSSPropertyBorderBlockStyle:
3926 return getCSSPropertyValuesFor2SidesShorthand(borderBlockStyleShorthand());
3927 case CSSPropertyBorderBlockWidth:
3928 return getCSSPropertyValuesFor2SidesShorthand(borderBlockWidthShorthand());
3929 case CSSPropertyBorderBottom:
3930 return getCSSPropertyValuesForShorthandProperties(borderBottomShorthand());
3931 case CSSPropertyBorderColor:
3932 return getCSSPropertyValuesFor4SidesShorthand(borderColorShorthand());
3933 case CSSPropertyBorderLeft:
3934 return getCSSPropertyValuesForShorthandProperties(borderLeftShorthand());
3935 case CSSPropertyBorderImage:
3936 return valueForNinePieceImage(style.borderImage());
3937 case CSSPropertyBorderInline: {
3938 auto value = propertyValue(CSSPropertyBorderInlineStart, DoNotUpdateLayout);
3939 if (!compareCSSValuePtr<CSSValue>(value, propertyValue(CSSPropertyBorderInlineEnd, DoNotUpdateLayout)))
3940 return nullptr;
3941 return value;
3942 }
3943 case CSSPropertyBorderInlineColor:
3944 return getCSSPropertyValuesFor2SidesShorthand(borderInlineColorShorthand());
3945 case CSSPropertyBorderInlineStyle:
3946 return getCSSPropertyValuesFor2SidesShorthand(borderInlineStyleShorthand());
3947 case CSSPropertyBorderInlineWidth:
3948 return getCSSPropertyValuesFor2SidesShorthand(borderInlineWidthShorthand());
3949 case CSSPropertyBorderRadius:
3950 return borderRadiusShorthandValue(style);
3951 case CSSPropertyBorderRight:
3952 return getCSSPropertyValuesForShorthandProperties(borderRightShorthand());
3953 case CSSPropertyBorderStyle:
3954 return getCSSPropertyValuesFor4SidesShorthand(borderStyleShorthand());
3955 case CSSPropertyBorderTop:
3956 return getCSSPropertyValuesForShorthandProperties(borderTopShorthand());
3957 case CSSPropertyBorderWidth:
3958 return getCSSPropertyValuesFor4SidesShorthand(borderWidthShorthand());
3959 case CSSPropertyColumnRule:
3960 return getCSSPropertyValuesForShorthandProperties(columnRuleShorthand());
3961 case CSSPropertyColumns:
3962 return getCSSPropertyValuesForShorthandProperties(columnsShorthand());
3963 case CSSPropertyInset:
3964 return getCSSPropertyValuesFor4SidesShorthand(insetShorthand());
3965 case CSSPropertyInsetBlock:
3966 return getCSSPropertyValuesFor2SidesShorthand(insetBlockShorthand());
3967 case CSSPropertyInsetInline:
3968 return getCSSPropertyValuesFor2SidesShorthand(insetInlineShorthand());
3969 case CSSPropertyListStyle:
3970 return getCSSPropertyValuesForShorthandProperties(listStyleShorthand());
3971 case CSSPropertyMargin:
3972 return getCSSPropertyValuesFor4SidesShorthand(marginShorthand());
3973 case CSSPropertyMarginBlock:
3974 return getCSSPropertyValuesFor2SidesShorthand(marginBlockShorthand());
3975 case CSSPropertyMarginInline:
3976 return getCSSPropertyValuesFor2SidesShorthand(marginInlineShorthand());
3977 case CSSPropertyOutline:
3978 return getCSSPropertyValuesForShorthandProperties(outlineShorthand());
3979 case CSSPropertyPadding:
3980 return getCSSPropertyValuesFor4SidesShorthand(paddingShorthand());
3981 case CSSPropertyPaddingBlock:
3982 return getCSSPropertyValuesFor2SidesShorthand(paddingBlockShorthand());
3983 case CSSPropertyPaddingInline:
3984 return getCSSPropertyValuesFor2SidesShorthand(paddingInlineShorthand());
3985#if ENABLE(CSS_SCROLL_SNAP)
3986 case CSSPropertyScrollSnapMargin:
3987 return getCSSPropertyValuesFor4SidesShorthand(scrollSnapMarginShorthand());
3988 case CSSPropertyScrollSnapMarginBottom:
3989 return zoomAdjustedPixelValueForLength(style.scrollSnapMarginBottom(), style);
3990 case CSSPropertyScrollSnapMarginTop:
3991 return zoomAdjustedPixelValueForLength(style.scrollSnapMarginTop(), style);
3992 case CSSPropertyScrollSnapMarginRight:
3993 return zoomAdjustedPixelValueForLength(style.scrollSnapMarginRight(), style);
3994 case CSSPropertyScrollSnapMarginLeft:
3995 return zoomAdjustedPixelValueForLength(style.scrollSnapMarginLeft(), style);
3996 case CSSPropertyScrollPadding:
3997 return getCSSPropertyValuesFor4SidesShorthand(scrollPaddingShorthand());
3998 case CSSPropertyScrollPaddingBottom:
3999 return zoomAdjustedPixelValueForLength(style.scrollPaddingBottom(), style);
4000 case CSSPropertyScrollPaddingTop:
4001 return zoomAdjustedPixelValueForLength(style.scrollPaddingTop(), style);
4002 case CSSPropertyScrollPaddingRight:
4003 return zoomAdjustedPixelValueForLength(style.scrollPaddingRight(), style);
4004 case CSSPropertyScrollPaddingLeft:
4005 return zoomAdjustedPixelValueForLength(style.scrollPaddingLeft(), style);
4006 case CSSPropertyScrollSnapType:
4007 return valueForScrollSnapType(style.scrollSnapType());
4008 case CSSPropertyScrollSnapAlign:
4009 return valueForScrollSnapAlignment(style.scrollSnapAlign());
4010#endif
4011
4012#if ENABLE(CSS_TRAILING_WORD)
4013 case CSSPropertyAppleTrailingWord:
4014 return cssValuePool.createValue(style.trailingWord());
4015#endif
4016
4017#if ENABLE(APPLE_PAY)
4018 case CSSPropertyApplePayButtonStyle:
4019 return cssValuePool.createValue(style.applePayButtonStyle());
4020 case CSSPropertyApplePayButtonType:
4021 return cssValuePool.createValue(style.applePayButtonType());
4022#endif
4023
4024#if ENABLE(DARK_MODE_CSS)
4025 case CSSPropertyColorScheme: {
4026 if (!RuntimeEnabledFeatures::sharedFeatures().darkModeCSSEnabled())
4027 return nullptr;
4028
4029 auto colorScheme = style.colorScheme();
4030 if (colorScheme.isAuto())
4031 return cssValuePool.createIdentifierValue(CSSValueAuto);
4032
4033 auto list = CSSValueList::createSpaceSeparated();
4034 if (colorScheme.contains(ColorScheme::Light))
4035 list->append(cssValuePool.createIdentifierValue(CSSValueLight));
4036 if (colorScheme.contains(ColorScheme::Dark))
4037 list->append(cssValuePool.createIdentifierValue(CSSValueDark));
4038 if (!colorScheme.allowsTransformations())
4039 list->append(cssValuePool.createIdentifierValue(CSSValueOnly));
4040 ASSERT(list->length());
4041 return list;
4042 }
4043#endif
4044
4045 /* Individual properties not part of the spec */
4046 case CSSPropertyBackgroundRepeatX:
4047 case CSSPropertyBackgroundRepeatY:
4048 break;
4049
4050 // Length properties for SVG.
4051 case CSSPropertyCx:
4052 return zoomAdjustedPixelValueForLength(style.svgStyle().cx(), style);
4053 case CSSPropertyCy:
4054 return zoomAdjustedPixelValueForLength(style.svgStyle().cy(), style);
4055 case CSSPropertyR:
4056 return zoomAdjustedPixelValueForLength(style.svgStyle().r(), style);
4057 case CSSPropertyRx:
4058 return zoomAdjustedPixelValueForLength(style.svgStyle().rx(), style);
4059 case CSSPropertyRy:
4060 return zoomAdjustedPixelValueForLength(style.svgStyle().ry(), style);
4061 case CSSPropertyStrokeDashoffset:
4062 return zoomAdjustedPixelValueForLength(style.svgStyle().strokeDashOffset(), style);
4063 case CSSPropertyX:
4064 return zoomAdjustedPixelValueForLength(style.svgStyle().x(), style);
4065 case CSSPropertyY:
4066 return zoomAdjustedPixelValueForLength(style.svgStyle().y(), style);
4067 case CSSPropertyWebkitTextZoom:
4068 return cssValuePool.createValue(style.textZoom());
4069
4070 case CSSPropertyPaintOrder:
4071 return paintOrder(style.paintOrder());
4072 case CSSPropertyStrokeLinecap:
4073 return CSSPrimitiveValue::create(style.capStyle());
4074 case CSSPropertyStrokeLinejoin:
4075 return CSSPrimitiveValue::create(style.joinStyle());
4076 case CSSPropertyStrokeWidth:
4077 return zoomAdjustedPixelValueForLength(style.strokeWidth(), style);
4078 case CSSPropertyStrokeColor:
4079 return currentColorOrValidColor(&style, style.strokeColor());
4080 case CSSPropertyStrokeMiterlimit:
4081 return CSSPrimitiveValue::create(style.strokeMiterLimit(), CSSPrimitiveValue::CSS_NUMBER);
4082
4083 /* Unimplemented CSS 3 properties (including CSS3 shorthand properties) */
4084 case CSSPropertyAll:
4085 case CSSPropertyAnimation:
4086 case CSSPropertyWebkitTextEmphasis:
4087 break;
4088
4089 /* Directional properties are resolved by resolveDirectionAwareProperty() before the switch. */
4090 case CSSPropertyBorderBlockEnd:
4091 case CSSPropertyBorderBlockEndColor:
4092 case CSSPropertyBorderBlockEndStyle:
4093 case CSSPropertyBorderBlockEndWidth:
4094 case CSSPropertyBorderBlockStart:
4095 case CSSPropertyBorderBlockStartColor:
4096 case CSSPropertyBorderBlockStartStyle:
4097 case CSSPropertyBorderBlockStartWidth:
4098 case CSSPropertyBorderInlineEnd:
4099 case CSSPropertyBorderInlineEndColor:
4100 case CSSPropertyBorderInlineEndStyle:
4101 case CSSPropertyBorderInlineEndWidth:
4102 case CSSPropertyBorderInlineStart:
4103 case CSSPropertyBorderInlineStartColor:
4104 case CSSPropertyBorderInlineStartStyle:
4105 case CSSPropertyBorderInlineStartWidth:
4106 case CSSPropertyInsetBlockEnd:
4107 case CSSPropertyInsetBlockStart:
4108 case CSSPropertyInsetInlineEnd:
4109 case CSSPropertyInsetInlineStart:
4110 case CSSPropertyMarginBlockEnd:
4111 case CSSPropertyMarginBlockStart:
4112 case CSSPropertyMarginInlineEnd:
4113 case CSSPropertyMarginInlineStart:
4114 case CSSPropertyPaddingBlockEnd:
4115 case CSSPropertyPaddingBlockStart:
4116 case CSSPropertyPaddingInlineEnd:
4117 case CSSPropertyPaddingInlineStart:
4118 case CSSPropertyBlockSize:
4119 case CSSPropertyInlineSize:
4120 case CSSPropertyMaxBlockSize:
4121 case CSSPropertyMaxInlineSize:
4122 case CSSPropertyMinBlockSize:
4123 case CSSPropertyMinInlineSize:
4124 ASSERT_NOT_REACHED();
4125 break;
4126
4127 /* Unimplemented @font-face properties */
4128 case CSSPropertySrc:
4129 case CSSPropertyUnicodeRange:
4130 case CSSPropertyFontDisplay:
4131 break;
4132
4133 /* Other unimplemented properties */
4134 case CSSPropertyPage: // for @page
4135 case CSSPropertyQuotes: // FIXME: needs implementation
4136 case CSSPropertySize: // for @page
4137 break;
4138
4139 /* Unimplemented -webkit- properties */
4140 case CSSPropertyWebkitBorderRadius:
4141 case CSSPropertyWebkitMarginCollapse:
4142 case CSSPropertyWebkitMarquee:
4143 case CSSPropertyWebkitMarqueeSpeed:
4144 case CSSPropertyWebkitMask:
4145 case CSSPropertyWebkitMaskRepeatX:
4146 case CSSPropertyWebkitMaskRepeatY:
4147 case CSSPropertyPerspectiveOriginX:
4148 case CSSPropertyPerspectiveOriginY:
4149 case CSSPropertyWebkitTextStroke:
4150 case CSSPropertyTransformOriginX:
4151 case CSSPropertyTransformOriginY:
4152 case CSSPropertyTransformOriginZ:
4153 break;
4154
4155#if ENABLE(CSS_DEVICE_ADAPTATION)
4156 case CSSPropertyMaxZoom:
4157 case CSSPropertyMinZoom:
4158 case CSSPropertyOrientation:
4159 case CSSPropertyUserZoom:
4160 break;
4161#endif
4162
4163 case CSSPropertyBufferedRendering:
4164 case CSSPropertyClipPath:
4165 case CSSPropertyClipRule:
4166 case CSSPropertyMask:
4167 case CSSPropertyEnableBackground:
4168 case CSSPropertyFloodColor:
4169 case CSSPropertyFloodOpacity:
4170 case CSSPropertyLightingColor:
4171 case CSSPropertyStopColor:
4172 case CSSPropertyStopOpacity:
4173 case CSSPropertyColorInterpolation:
4174 case CSSPropertyColorInterpolationFilters:
4175 case CSSPropertyColorProfile:
4176 case CSSPropertyColorRendering:
4177 case CSSPropertyFill:
4178 case CSSPropertyFillOpacity:
4179 case CSSPropertyFillRule:
4180 case CSSPropertyMarker:
4181 case CSSPropertyMarkerEnd:
4182 case CSSPropertyMarkerMid:
4183 case CSSPropertyMarkerStart:
4184 case CSSPropertyMaskType:
4185 case CSSPropertyShapeRendering:
4186 case CSSPropertyStroke:
4187 case CSSPropertyStrokeDasharray:
4188 case CSSPropertyStrokeOpacity:
4189 case CSSPropertyAlignmentBaseline:
4190 case CSSPropertyBaselineShift:
4191 case CSSPropertyDominantBaseline:
4192 case CSSPropertyGlyphOrientationHorizontal:
4193 case CSSPropertyGlyphOrientationVertical:
4194 case CSSPropertyKerning:
4195 case CSSPropertyTextAnchor:
4196 case CSSPropertyVectorEffect:
4197 return svgPropertyValue(propertyID);
4198 case CSSPropertyCustom:
4199 ASSERT_NOT_REACHED();
4200 return nullptr;
4201 }
4202
4203 logUnimplementedPropertyID(propertyID);
4204 return nullptr;
4205}
4206
4207String CSSComputedStyleDeclaration::getPropertyValue(CSSPropertyID propertyID) const
4208{
4209 auto value = getPropertyCSSValue(propertyID);
4210 if (!value)
4211 return emptyString(); // FIXME: Should this be null instead, as it is in StyleProperties::getPropertyValue?
4212 return value->cssText();
4213}
4214
4215unsigned CSSComputedStyleDeclaration::length() const
4216{
4217 updateStyleIfNeededForProperty(m_element.get(), CSSPropertyCustom);
4218
4219 auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
4220 if (!style)
4221 return 0;
4222
4223 return numComputedProperties + style->inheritedCustomProperties().size() + style->nonInheritedCustomProperties().size();
4224}
4225
4226String CSSComputedStyleDeclaration::item(unsigned i) const
4227{
4228 if (i >= length())
4229 return String();
4230
4231 if (i < numComputedProperties)
4232 return getPropertyNameString(computedProperties[i]);
4233
4234 auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
4235 if (!style)
4236 return String();
4237
4238 const auto& inheritedCustomProperties = style->inheritedCustomProperties();
4239
4240 if (i < numComputedProperties + inheritedCustomProperties.size()) {
4241 auto results = copyToVector(inheritedCustomProperties.keys());
4242 return results.at(i - numComputedProperties);
4243 }
4244
4245 const auto& nonInheritedCustomProperties = style->nonInheritedCustomProperties();
4246 auto results = copyToVector(nonInheritedCustomProperties.keys());
4247 return results.at(i - inheritedCustomProperties.size() - numComputedProperties);
4248}
4249
4250bool ComputedStyleExtractor::propertyMatches(CSSPropertyID propertyID, const CSSValue* value)
4251{
4252 if (!m_element)
4253 return false;
4254 if (propertyID == CSSPropertyFontSize && is<CSSPrimitiveValue>(*value)) {
4255 m_element->document().updateLayoutIgnorePendingStylesheets();
4256 if (auto* style = m_element->computedStyle(m_pseudoElementSpecifier)) {
4257 if (CSSValueID sizeIdentifier = style->fontDescription().keywordSizeAsIdentifier()) {
4258 auto& primitiveValue = downcast<CSSPrimitiveValue>(*value);
4259 if (primitiveValue.isValueID() && primitiveValue.valueID() == sizeIdentifier)
4260 return true;
4261 }
4262 }
4263 }
4264 RefPtr<CSSValue> computedValue = propertyValue(propertyID);
4265 return computedValue && value && computedValue->equals(*value);
4266}
4267
4268Ref<MutableStyleProperties> ComputedStyleExtractor::copyProperties()
4269{
4270 return copyPropertiesInSet(computedProperties, numComputedProperties);
4271}
4272
4273Ref<CSSValueList> ComputedStyleExtractor::getCSSPropertyValuesForShorthandProperties(const StylePropertyShorthand& shorthand)
4274{
4275 auto list = CSSValueList::createSpaceSeparated();
4276 for (size_t i = 0; i < shorthand.length(); ++i)
4277 list->append(propertyValue(shorthand.properties()[i], DoNotUpdateLayout).releaseNonNull());
4278 return list;
4279}
4280
4281RefPtr<CSSValueList> ComputedStyleExtractor::getCSSPropertyValuesFor2SidesShorthand(const StylePropertyShorthand& shorthand)
4282{
4283 auto list = CSSValueList::createSpaceSeparated();
4284
4285 // Assume the properties are in the usual order start, end.
4286 auto startValue = propertyValue(shorthand.properties()[0], DoNotUpdateLayout);
4287 auto endValue = propertyValue(shorthand.properties()[1], DoNotUpdateLayout);
4288
4289 // All 2 properties must be specified.
4290 if (!startValue || !endValue)
4291 return nullptr;
4292
4293 bool showEnd = !compareCSSValuePtr(startValue, endValue);
4294
4295 list->append(startValue.releaseNonNull());
4296 if (showEnd)
4297 list->append(endValue.releaseNonNull());
4298
4299 return list;
4300}
4301
4302RefPtr<CSSValueList> ComputedStyleExtractor::getCSSPropertyValuesFor4SidesShorthand(const StylePropertyShorthand& shorthand)
4303{
4304 auto list = CSSValueList::createSpaceSeparated();
4305
4306 // Assume the properties are in the usual order top, right, bottom, left.
4307 auto topValue = propertyValue(shorthand.properties()[0], DoNotUpdateLayout);
4308 auto rightValue = propertyValue(shorthand.properties()[1], DoNotUpdateLayout);
4309 auto bottomValue = propertyValue(shorthand.properties()[2], DoNotUpdateLayout);
4310 auto leftValue = propertyValue(shorthand.properties()[3], DoNotUpdateLayout);
4311
4312 // All 4 properties must be specified.
4313 if (!topValue || !rightValue || !bottomValue || !leftValue)
4314 return nullptr;
4315
4316 bool showLeft = !compareCSSValuePtr(rightValue, leftValue);
4317 bool showBottom = !compareCSSValuePtr(topValue, bottomValue) || showLeft;
4318 bool showRight = !compareCSSValuePtr(topValue, rightValue) || showBottom;
4319
4320 list->append(topValue.releaseNonNull());
4321 if (showRight)
4322 list->append(rightValue.releaseNonNull());
4323 if (showBottom)
4324 list->append(bottomValue.releaseNonNull());
4325 if (showLeft)
4326 list->append(leftValue.releaseNonNull());
4327
4328 return list;
4329}
4330
4331Ref<CSSValueList> ComputedStyleExtractor::getCSSPropertyValuesForGridShorthand(const StylePropertyShorthand& shorthand)
4332{
4333 auto list = CSSValueList::createSlashSeparated();
4334 for (size_t i = 0; i < shorthand.length(); ++i)
4335 list->append(propertyValue(shorthand.properties()[i], DoNotUpdateLayout).releaseNonNull());
4336 return list;
4337}
4338
4339Ref<MutableStyleProperties> ComputedStyleExtractor::copyPropertiesInSet(const CSSPropertyID* set, unsigned length)
4340{
4341 Vector<CSSProperty, 256> list;
4342 list.reserveInitialCapacity(length);
4343 for (unsigned i = 0; i < length; ++i) {
4344 if (auto value = propertyValue(set[i]))
4345 list.append(CSSProperty(set[i], WTFMove(value), false));
4346 }
4347 return MutableStyleProperties::create(list.data(), list.size());
4348}
4349
4350CSSRule* CSSComputedStyleDeclaration::parentRule() const
4351{
4352 return nullptr;
4353}
4354
4355RefPtr<DeprecatedCSSOMValue> CSSComputedStyleDeclaration::getPropertyCSSValue(const String& propertyName)
4356{
4357 if (isCustomPropertyName(propertyName)) {
4358 auto value = ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).customPropertyValue(propertyName);
4359 if (!value)
4360 return nullptr;
4361 return value->createDeprecatedCSSOMWrapper(*this);
4362 }
4363
4364 CSSPropertyID propertyID = cssPropertyID(propertyName);
4365 if (!propertyID)
4366 return nullptr;
4367 auto value = getPropertyCSSValue(propertyID);
4368 if (!value)
4369 return nullptr;
4370 return value->createDeprecatedCSSOMWrapper(*this);
4371}
4372
4373String CSSComputedStyleDeclaration::getPropertyValue(const String &propertyName)
4374{
4375 if (isCustomPropertyName(propertyName))
4376 return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).customPropertyText(propertyName);
4377
4378 CSSPropertyID propertyID = cssPropertyID(propertyName);
4379 if (!propertyID)
4380 return String();
4381 return getPropertyValue(propertyID);
4382}
4383
4384String CSSComputedStyleDeclaration::getPropertyPriority(const String&)
4385{
4386 // All computed styles have a priority of not "important".
4387 return emptyString(); // FIXME: Should this sometimes be null instead of empty, to match a normal style declaration?
4388}
4389
4390String CSSComputedStyleDeclaration::getPropertyShorthand(const String&)
4391{
4392 return emptyString(); // FIXME: Should this sometimes be null instead of empty, to match a normal style declaration?
4393}
4394
4395bool CSSComputedStyleDeclaration::isPropertyImplicit(const String&)
4396{
4397 return false;
4398}
4399
4400ExceptionOr<void> CSSComputedStyleDeclaration::setProperty(const String&, const String&, const String&)
4401{
4402 return Exception { NoModificationAllowedError };
4403}
4404
4405ExceptionOr<String> CSSComputedStyleDeclaration::removeProperty(const String&)
4406{
4407 return Exception { NoModificationAllowedError };
4408}
4409
4410RefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValueInternal(CSSPropertyID propertyID)
4411{
4412 return getPropertyCSSValue(propertyID);
4413}
4414
4415String CSSComputedStyleDeclaration::getPropertyValueInternal(CSSPropertyID propertyID)
4416{
4417 return getPropertyValue(propertyID);
4418}
4419
4420ExceptionOr<bool> CSSComputedStyleDeclaration::setPropertyInternal(CSSPropertyID, const String&, bool)
4421{
4422 return Exception { NoModificationAllowedError };
4423}
4424
4425Ref<CSSValueList> ComputedStyleExtractor::getBackgroundShorthandValue()
4426{
4427 static const CSSPropertyID propertiesBeforeSlashSeperator[5] = { CSSPropertyBackgroundColor, CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat, CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition };
4428 static const CSSPropertyID propertiesAfterSlashSeperator[3] = { CSSPropertyBackgroundSize, CSSPropertyBackgroundOrigin, CSSPropertyBackgroundClip };
4429
4430 auto list = CSSValueList::createSlashSeparated();
4431 list->append(getCSSPropertyValuesForShorthandProperties(StylePropertyShorthand(CSSPropertyBackground, propertiesBeforeSlashSeperator)));
4432 list->append(getCSSPropertyValuesForShorthandProperties(StylePropertyShorthand(CSSPropertyBackground, propertiesAfterSlashSeperator)));
4433 return list;
4434}
4435
4436} // namespace WebCore
4437