1/*
2 * Copyright (C) 2004 Zack Rusin <zack@kde.org>
3 * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6 * Copyright (C) 2011 Sencha, Inc. All rights reserved.
7 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 * 02110-1301 USA
23 */
24
25#include "config.h"
26#include "CSSComputedStyleDeclaration.h"
27
28#include "BasicShapeFunctions.h"
29#include "CSSAnimationController.h"
30#include "CSSAspectRatioValue.h"
31#include "CSSBasicShapes.h"
32#include "CSSBorderImage.h"
33#include "CSSBorderImageSliceValue.h"
34#include "CSSFontFeatureValue.h"
35#include "CSSFontStyleValue.h"
36#include "CSSFontValue.h"
37#include "CSSFontVariationValue.h"
38#include "CSSFunctionValue.h"
39#include "CSSLineBoxContainValue.h"
40#include "CSSPrimitiveValue.h"
41#include "CSSPrimitiveValueMappings.h"
42#include "CSSPropertyNames.h"
43#include "CSSPropertyParser.h"
44#include "CSSReflectValue.h"
45#include "CSSSelector.h"
46#include "CSSShadowValue.h"
47#include "CSSTimingFunctionValue.h"
48#include "CSSValueList.h"
49#include "CSSValuePool.h"
50#include "ComposedTreeAncestorIterator.h"
51#include "ContentData.h"
52#include "CursorList.h"
53#include "DeprecatedCSSOMValue.h"
54#include "Document.h"
55#include "DocumentTimeline.h"
56#include "FontCascade.h"
57#include "FontSelectionValueInlines.h"
58#include "FontTaggedSettings.h"
59#include "NodeRenderStyle.h"
60#include "Pair.h"
61#include "Rect.h"
62#include "RenderBlock.h"
63#include "RenderBox.h"
64#include "RenderInline.h"
65#include "RenderStyle.h"
66#include "RuntimeEnabledFeatures.h"
67#include "SVGElement.h"
68#include "Settings.h"
69#include "ShapeValue.h"
70#include "StyleProperties.h"
71#include "StylePropertyShorthand.h"
72#include "StylePropertyShorthandFunctions.h"
73#include "StyleResolver.h"
74#include "StyleScope.h"
75#include "StyleScrollSnapPoints.h"
76#include "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
87#if ENABLE(DASHBOARD_SUPPORT)
88#include "DashboardRegion.h"
89#endif
90
91namespace WebCore {
92
93WTF_MAKE_ISO_ALLOCATED_IMPL(CSSComputedStyleDeclaration);
94
95// List of all properties we know how to compute, omitting shorthands.
96static const CSSPropertyID computedProperties[] = {
97 CSSPropertyAlt,
98 CSSPropertyAnimationDelay,
99 CSSPropertyAnimationDirection,
100 CSSPropertyAnimationDuration,
101 CSSPropertyAnimationFillMode,
102 CSSPropertyAnimationIterationCount,
103 CSSPropertyAnimationName,
104 CSSPropertyAnimationPlayState,
105 CSSPropertyAnimationTimingFunction,
106 CSSPropertyBackgroundAttachment,
107 CSSPropertyBackgroundBlendMode,
108 CSSPropertyBackgroundClip,
109 CSSPropertyBackgroundColor,
110 CSSPropertyBackgroundImage,
111 CSSPropertyBackgroundOrigin,
112 CSSPropertyBackgroundPosition, // more-specific background-position-x/y are non-standard
113 CSSPropertyBackgroundRepeat,
114 CSSPropertyBackgroundSize,
115 CSSPropertyBorderBottomColor,
116 CSSPropertyBorderBottomLeftRadius,
117 CSSPropertyBorderBottomRightRadius,
118 CSSPropertyBorderBottomStyle,
119 CSSPropertyBorderBottomWidth,
120 CSSPropertyBorderCollapse,
121 CSSPropertyBorderImageOutset,
122 CSSPropertyBorderImageRepeat,
123 CSSPropertyBorderImageSlice,
124 CSSPropertyBorderImageSource,
125 CSSPropertyBorderImageWidth,
126 CSSPropertyBorderLeftColor,
127 CSSPropertyBorderLeftStyle,
128 CSSPropertyBorderLeftWidth,
129 CSSPropertyBorderRightColor,
130 CSSPropertyBorderRightStyle,
131 CSSPropertyBorderRightWidth,
132 CSSPropertyBorderTopColor,
133 CSSPropertyBorderTopLeftRadius,
134 CSSPropertyBorderTopRightRadius,
135 CSSPropertyBorderTopStyle,
136 CSSPropertyBorderTopWidth,
137 CSSPropertyBottom,
138 CSSPropertyBoxShadow,
139 CSSPropertyBoxSizing,
140 CSSPropertyCaptionSide,
141 CSSPropertyCaretColor,
142 CSSPropertyClear,
143 CSSPropertyClip,
144 CSSPropertyColor,
145 CSSPropertyAppleColorFilter,
146 CSSPropertyCounterIncrement,
147 CSSPropertyCounterReset,
148 CSSPropertyContent,
149 CSSPropertyCursor,
150 CSSPropertyDirection,
151 CSSPropertyDisplay,
152 CSSPropertyEmptyCells,
153 CSSPropertyFloat,
154 CSSPropertyFontFamily,
155 CSSPropertyFontSize,
156 CSSPropertyFontStretch,
157 CSSPropertyFontStyle,
158 CSSPropertyFontSynthesis,
159 CSSPropertyFontVariant,
160 CSSPropertyFontWeight,
161#if ENABLE(VARIATION_FONTS)
162 CSSPropertyFontOpticalSizing,
163#endif
164 CSSPropertyHangingPunctuation,
165 CSSPropertyHeight,
166#if ENABLE(CSS_IMAGE_ORIENTATION)
167 CSSPropertyImageOrientation,
168#endif
169 CSSPropertyImageRendering,
170#if ENABLE(CSS_IMAGE_RESOLUTION)
171 CSSPropertyImageResolution,
172#endif
173 CSSPropertyLeft,
174 CSSPropertyLetterSpacing,
175 CSSPropertyLineHeight,
176 CSSPropertyListStyleImage,
177 CSSPropertyListStylePosition,
178 CSSPropertyListStyleType,
179 CSSPropertyMarginBottom,
180 CSSPropertyMarginLeft,
181 CSSPropertyMarginRight,
182 CSSPropertyMarginTop,
183 CSSPropertyMaxHeight,
184 CSSPropertyMaxWidth,
185 CSSPropertyMinHeight,
186 CSSPropertyMinWidth,
187 CSSPropertyObjectFit,
188 CSSPropertyObjectPosition,
189 CSSPropertyOpacity,
190 CSSPropertyOrphans,
191 CSSPropertyOutlineColor,
192 CSSPropertyOutlineOffset,
193 CSSPropertyOutlineStyle,
194 CSSPropertyOutlineWidth,
195 CSSPropertyOverflowWrap,
196 CSSPropertyOverflowX,
197 CSSPropertyOverflowY,
198 CSSPropertyPaddingBottom,
199 CSSPropertyPaddingLeft,
200 CSSPropertyPaddingRight,
201 CSSPropertyPaddingTop,
202 CSSPropertyPageBreakAfter,
203 CSSPropertyPageBreakBefore,
204 CSSPropertyPageBreakInside,
205 CSSPropertyPointerEvents,
206 CSSPropertyPosition,
207 CSSPropertyResize,
208 CSSPropertyRight,
209 CSSPropertySpeakAs,
210 CSSPropertyTableLayout,
211 CSSPropertyTabSize,
212 CSSPropertyTextAlign,
213 CSSPropertyTextDecoration,
214#if ENABLE(CSS3_TEXT)
215 CSSPropertyWebkitTextAlignLast,
216 CSSPropertyWebkitTextJustify,
217#endif // CSS3_TEXT
218 CSSPropertyTextDecorationLine,
219 CSSPropertyTextDecorationStyle,
220 CSSPropertyTextDecorationColor,
221 CSSPropertyTextDecorationSkip,
222 CSSPropertyTextUnderlinePosition,
223 CSSPropertyTextIndent,
224 CSSPropertyTextRendering,
225 CSSPropertyTextShadow,
226 CSSPropertyTextOverflow,
227 CSSPropertyTextTransform,
228 CSSPropertyTop,
229 CSSPropertyTransform,
230 CSSPropertyTransformBox,
231 CSSPropertyTransformOrigin,
232 CSSPropertyTransformStyle,
233 CSSPropertyTransitionDelay,
234 CSSPropertyTransitionDuration,
235 CSSPropertyTransitionProperty,
236 CSSPropertyTransitionTimingFunction,
237 CSSPropertyUnicodeBidi,
238 CSSPropertyVerticalAlign,
239 CSSPropertyVisibility,
240 CSSPropertyWhiteSpace,
241 CSSPropertyWidows,
242 CSSPropertyWidth,
243 CSSPropertyWillChange,
244 CSSPropertyWordBreak,
245 CSSPropertyWordSpacing,
246 CSSPropertyWordWrap,
247#if ENABLE(CSS_SCROLL_SNAP)
248 CSSPropertyScrollSnapMargin,
249 CSSPropertyScrollSnapMarginLeft,
250 CSSPropertyScrollSnapMarginTop,
251 CSSPropertyScrollSnapMarginRight,
252 CSSPropertyScrollSnapMarginBottom,
253 CSSPropertyScrollPadding,
254 CSSPropertyScrollPaddingLeft,
255 CSSPropertyScrollPaddingTop,
256 CSSPropertyScrollPaddingRight,
257 CSSPropertyScrollPaddingBottom,
258 CSSPropertyScrollSnapType,
259 CSSPropertyScrollSnapAlign,
260#endif
261 CSSPropertyZIndex,
262 CSSPropertyZoom,
263 CSSPropertyWebkitAppearance,
264 CSSPropertyWebkitBackfaceVisibility,
265 CSSPropertyWebkitBackgroundClip,
266 CSSPropertyWebkitBackgroundComposite,
267 CSSPropertyWebkitBackgroundOrigin,
268 CSSPropertyWebkitBackgroundSize,
269#if ENABLE(CSS_COMPOSITING)
270 CSSPropertyMixBlendMode,
271 CSSPropertyIsolation,
272#endif
273 CSSPropertyWebkitBorderFit,
274 CSSPropertyWebkitBorderHorizontalSpacing,
275 CSSPropertyWebkitBorderImage,
276 CSSPropertyWebkitBorderVerticalSpacing,
277 CSSPropertyWebkitBoxAlign,
278#if ENABLE(CSS_BOX_DECORATION_BREAK)
279 CSSPropertyWebkitBoxDecorationBreak,
280#endif
281 CSSPropertyWebkitBoxDirection,
282 CSSPropertyWebkitBoxFlex,
283 CSSPropertyWebkitBoxFlexGroup,
284 CSSPropertyWebkitBoxLines,
285 CSSPropertyWebkitBoxOrdinalGroup,
286 CSSPropertyWebkitBoxOrient,
287 CSSPropertyWebkitBoxPack,
288 CSSPropertyWebkitBoxReflect,
289 CSSPropertyWebkitBoxShadow,
290 CSSPropertyWebkitClipPath,
291 CSSPropertyWebkitColumnBreakAfter,
292 CSSPropertyWebkitColumnBreakBefore,
293 CSSPropertyWebkitColumnBreakInside,
294 CSSPropertyWebkitColumnAxis,
295 CSSPropertyColumnCount,
296 CSSPropertyColumnFill,
297 CSSPropertyColumnGap,
298 CSSPropertyRowGap,
299 CSSPropertyWebkitColumnProgression,
300 CSSPropertyColumnRuleColor,
301 CSSPropertyColumnRuleStyle,
302 CSSPropertyColumnRuleWidth,
303 CSSPropertyColumnSpan,
304 CSSPropertyColumnWidth,
305#if ENABLE(CURSOR_VISIBILITY)
306 CSSPropertyWebkitCursorVisibility,
307#endif
308#if ENABLE(DASHBOARD_SUPPORT)
309 CSSPropertyWebkitDashboardRegion,
310#endif
311 CSSPropertyAlignContent,
312 CSSPropertyAlignItems,
313 CSSPropertyAlignSelf,
314 CSSPropertyFilter,
315 CSSPropertyFlexBasis,
316 CSSPropertyFlexDirection,
317 CSSPropertyFlexFlow,
318 CSSPropertyFlexGrow,
319 CSSPropertyFlexShrink,
320 CSSPropertyFlexWrap,
321 CSSPropertyJustifyContent,
322 CSSPropertyJustifySelf,
323 CSSPropertyJustifyItems,
324 CSSPropertyPlaceContent,
325 CSSPropertyPlaceItems,
326 CSSPropertyPlaceSelf,
327#if ENABLE(FILTERS_LEVEL_2)
328 CSSPropertyWebkitBackdropFilter,
329#endif
330 CSSPropertyWebkitFontKerning,
331 CSSPropertyWebkitFontSmoothing,
332 CSSPropertyFontVariantLigatures,
333 CSSPropertyFontVariantPosition,
334 CSSPropertyFontVariantCaps,
335 CSSPropertyFontVariantNumeric,
336 CSSPropertyFontVariantAlternates,
337 CSSPropertyFontVariantEastAsian,
338#if ENABLE(VARIATION_FONTS)
339 CSSPropertyFontVariationSettings,
340#endif
341 CSSPropertyGridAutoColumns,
342 CSSPropertyGridAutoFlow,
343 CSSPropertyGridAutoRows,
344 CSSPropertyGridColumnEnd,
345 CSSPropertyGridColumnStart,
346 CSSPropertyGridTemplateAreas,
347 CSSPropertyGridTemplateColumns,
348 CSSPropertyGridTemplateRows,
349 CSSPropertyGridRowEnd,
350 CSSPropertyGridRowStart,
351 CSSPropertyWebkitHyphenateCharacter,
352 CSSPropertyWebkitHyphenateLimitAfter,
353 CSSPropertyWebkitHyphenateLimitBefore,
354 CSSPropertyWebkitHyphenateLimitLines,
355 CSSPropertyWebkitHyphens,
356 CSSPropertyWebkitInitialLetter,
357 CSSPropertyWebkitLineAlign,
358 CSSPropertyWebkitLineBoxContain,
359 CSSPropertyLineBreak,
360 CSSPropertyWebkitLineClamp,
361 CSSPropertyWebkitLineGrid,
362 CSSPropertyWebkitLineSnap,
363 CSSPropertyWebkitLocale,
364 CSSPropertyWebkitMarginBeforeCollapse,
365 CSSPropertyWebkitMarginAfterCollapse,
366 CSSPropertyWebkitMarqueeDirection,
367 CSSPropertyWebkitMarqueeIncrement,
368 CSSPropertyWebkitMarqueeRepetition,
369 CSSPropertyWebkitMarqueeStyle,
370 CSSPropertyWebkitMaskBoxImage,
371 CSSPropertyWebkitMaskBoxImageOutset,
372 CSSPropertyWebkitMaskBoxImageRepeat,
373 CSSPropertyWebkitMaskBoxImageSlice,
374 CSSPropertyWebkitMaskBoxImageSource,
375 CSSPropertyWebkitMaskBoxImageWidth,
376 CSSPropertyWebkitMaskClip,
377 CSSPropertyWebkitMaskComposite,
378 CSSPropertyWebkitMaskImage,
379 CSSPropertyWebkitMaskOrigin,
380 CSSPropertyWebkitMaskPosition,
381 CSSPropertyWebkitMaskRepeat,
382 CSSPropertyWebkitMaskSize,
383 CSSPropertyWebkitMaskSourceType,
384 CSSPropertyWebkitNbspMode,
385 CSSPropertyOrder,
386#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
387 CSSPropertyWebkitOverflowScrolling,
388#endif
389 CSSPropertyPerspective,
390 CSSPropertyPerspectiveOrigin,
391 CSSPropertyWebkitPrintColorAdjust,
392 CSSPropertyWebkitRtlOrdering,
393#if PLATFORM(IOS_FAMILY)
394 CSSPropertyWebkitTouchCallout,
395#endif
396#if ENABLE(TOUCH_EVENTS)
397 CSSPropertyWebkitTapHighlightColor,
398#endif
399 CSSPropertyWebkitTextCombine,
400 CSSPropertyWebkitTextDecorationsInEffect,
401 CSSPropertyWebkitTextEmphasisColor,
402 CSSPropertyWebkitTextEmphasisPosition,
403 CSSPropertyWebkitTextEmphasisStyle,
404 CSSPropertyWebkitTextFillColor,
405 CSSPropertyWebkitTextOrientation,
406 CSSPropertyWebkitTextSecurity,
407#if ENABLE(TEXT_AUTOSIZING)
408 CSSPropertyWebkitTextSizeAdjust,
409#endif
410 CSSPropertyWebkitTextStrokeColor,
411 CSSPropertyWebkitTextStrokeWidth,
412 CSSPropertyWebkitTextZoom,
413 CSSPropertyWebkitTransformStyle,
414 CSSPropertyWebkitUserDrag,
415 CSSPropertyWebkitUserModify,
416 CSSPropertyWebkitUserSelect,
417 CSSPropertyShapeImageThreshold,
418 CSSPropertyShapeMargin,
419 CSSPropertyShapeOutside,
420 CSSPropertyShapeRendering,
421 CSSPropertyBufferedRendering,
422 CSSPropertyClipPath,
423 CSSPropertyClipRule,
424 CSSPropertyCx,
425 CSSPropertyCy,
426 CSSPropertyMask,
427 CSSPropertyMaskType,
428 CSSPropertyFloodColor,
429 CSSPropertyFloodOpacity,
430 CSSPropertyLightingColor,
431 CSSPropertyStopColor,
432 CSSPropertyStopOpacity,
433 CSSPropertyColorInterpolation,
434 CSSPropertyColorInterpolationFilters,
435 CSSPropertyColorRendering,
436 CSSPropertyFill,
437 CSSPropertyFillOpacity,
438 CSSPropertyFillRule,
439 CSSPropertyMarkerEnd,
440 CSSPropertyMarkerMid,
441 CSSPropertyMarkerStart,
442 CSSPropertyPaintOrder,
443 CSSPropertyR,
444 CSSPropertyRx,
445 CSSPropertyRy,
446 CSSPropertyStroke,
447 CSSPropertyStrokeColor,
448 CSSPropertyStrokeDasharray,
449 CSSPropertyStrokeDashoffset,
450 CSSPropertyStrokeLinecap,
451 CSSPropertyStrokeLinejoin,
452 CSSPropertyStrokeMiterlimit,
453 CSSPropertyStrokeOpacity,
454 CSSPropertyStrokeWidth,
455#if ENABLE(DARK_MODE_CSS)
456 CSSPropertyColorScheme,
457#endif
458 CSSPropertyAlignmentBaseline,
459 CSSPropertyBaselineShift,
460 CSSPropertyDominantBaseline,
461 CSSPropertyKerning,
462 CSSPropertyTextAnchor,
463 CSSPropertyWritingMode,
464 CSSPropertyGlyphOrientationHorizontal,
465 CSSPropertyGlyphOrientationVertical,
466 CSSPropertyVectorEffect,
467 CSSPropertyX,
468 CSSPropertyY
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 AtomicString& 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 AtomicString& 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 break;
2789
2790 case CSSPropertyBackgroundColor:
2791 return cssValuePool.createColorValue(m_allowVisitedStyle? style.visitedDependentColor(CSSPropertyBackgroundColor) : style.backgroundColor());
2792 case CSSPropertyBackgroundImage:
2793 case CSSPropertyWebkitMaskImage: {
2794 auto& layers = propertyID == CSSPropertyWebkitMaskImage ? style.maskLayers() : style.backgroundLayers();
2795 if (!layers.next()) {
2796 if (layers.image())
2797 return layers.image()->cssValue();
2798 return cssValuePool.createIdentifierValue(CSSValueNone);
2799 }
2800 auto list = CSSValueList::createCommaSeparated();
2801 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next()) {
2802 if (currLayer->image())
2803 list->append(currLayer->image()->cssValue());
2804 else
2805 list->append(cssValuePool.createIdentifierValue(CSSValueNone));
2806 }
2807 return list;
2808 }
2809 case CSSPropertyBackgroundSize:
2810 case CSSPropertyWebkitBackgroundSize:
2811 case CSSPropertyWebkitMaskSize: {
2812 auto& layers = propertyID == CSSPropertyWebkitMaskSize ? style.maskLayers() : style.backgroundLayers();
2813 if (!layers.next())
2814 return fillSizeToCSSValue(layers.size(), style);
2815 auto list = CSSValueList::createCommaSeparated();
2816 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2817 list->append(fillSizeToCSSValue(currLayer->size(), style));
2818 return list;
2819 }
2820 case CSSPropertyBackgroundRepeat:
2821 case CSSPropertyWebkitMaskRepeat: {
2822 auto& layers = propertyID == CSSPropertyWebkitMaskRepeat ? style.maskLayers() : style.backgroundLayers();
2823 if (!layers.next())
2824 return fillRepeatToCSSValue(layers.repeatX(), layers.repeatY());
2825 auto list = CSSValueList::createCommaSeparated();
2826 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2827 list->append(fillRepeatToCSSValue(currLayer->repeatX(), currLayer->repeatY()));
2828 return list;
2829 }
2830 case CSSPropertyWebkitMaskSourceType: {
2831 auto& layers = style.maskLayers();
2832 if (!layers.next())
2833 return fillSourceTypeToCSSValue(layers.maskSourceType());
2834 auto list = CSSValueList::createCommaSeparated();
2835 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2836 list->append(fillSourceTypeToCSSValue(currLayer->maskSourceType()));
2837 return list;
2838 }
2839 case CSSPropertyWebkitBackgroundComposite:
2840 case CSSPropertyWebkitMaskComposite: {
2841 auto& layers = propertyID == CSSPropertyWebkitMaskComposite ? style.maskLayers() : style.backgroundLayers();
2842 if (!layers.next())
2843 return cssValuePool.createValue(layers.composite());
2844 auto list = CSSValueList::createCommaSeparated();
2845 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2846 list->append(cssValuePool.createValue(currLayer->composite()));
2847 return list;
2848 }
2849 case CSSPropertyBackgroundAttachment: {
2850 auto& layers = style.backgroundLayers();
2851 if (!layers.next())
2852 return cssValuePool.createValue(layers.attachment());
2853 auto list = CSSValueList::createCommaSeparated();
2854 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2855 list->append(cssValuePool.createValue(currLayer->attachment()));
2856 return list;
2857 }
2858 case CSSPropertyBackgroundClip:
2859 case CSSPropertyBackgroundOrigin:
2860 case CSSPropertyWebkitBackgroundClip:
2861 case CSSPropertyWebkitBackgroundOrigin:
2862 case CSSPropertyWebkitMaskClip:
2863 case CSSPropertyWebkitMaskOrigin: {
2864 auto& layers = (propertyID == CSSPropertyWebkitMaskClip || propertyID == CSSPropertyWebkitMaskOrigin) ? style.maskLayers() : style.backgroundLayers();
2865 bool isClip = propertyID == CSSPropertyBackgroundClip || propertyID == CSSPropertyWebkitBackgroundClip || propertyID == CSSPropertyWebkitMaskClip;
2866 if (!layers.next())
2867 return cssValuePool.createValue(isClip ? layers.clip() : layers.origin());
2868 auto list = CSSValueList::createCommaSeparated();
2869 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2870 list->append(cssValuePool.createValue(isClip ? currLayer->clip() : currLayer->origin()));
2871 return list;
2872 }
2873 case CSSPropertyBackgroundPosition:
2874 case CSSPropertyWebkitMaskPosition: {
2875 auto& layers = propertyID == CSSPropertyWebkitMaskPosition ? style.maskLayers() : style.backgroundLayers();
2876 if (!layers.next())
2877 return createPositionListForLayer(propertyID, layers, style);
2878
2879 auto list = CSSValueList::createCommaSeparated();
2880 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2881 list->append(createPositionListForLayer(propertyID, *currLayer, style));
2882 return list;
2883 }
2884 case CSSPropertyBackgroundPositionX:
2885 case CSSPropertyWebkitMaskPositionX: {
2886 auto& layers = propertyID == CSSPropertyWebkitMaskPositionX ? style.maskLayers() : style.backgroundLayers();
2887 if (!layers.next())
2888 return cssValuePool.createValue(layers.xPosition());
2889
2890 auto list = CSSValueList::createCommaSeparated();
2891 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2892 list->append(cssValuePool.createValue(currLayer->xPosition()));
2893
2894 return list;
2895 }
2896 case CSSPropertyBackgroundPositionY:
2897 case CSSPropertyWebkitMaskPositionY: {
2898 auto& layers = propertyID == CSSPropertyWebkitMaskPositionY ? style.maskLayers() : style.backgroundLayers();
2899 if (!layers.next())
2900 return cssValuePool.createValue(layers.yPosition());
2901
2902 auto list = CSSValueList::createCommaSeparated();
2903 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
2904 list->append(cssValuePool.createValue(currLayer->yPosition()));
2905
2906 return list;
2907 }
2908 case CSSPropertyBorderCollapse:
2909 if (style.borderCollapse() == BorderCollapse::Collapse)
2910 return cssValuePool.createIdentifierValue(CSSValueCollapse);
2911 return cssValuePool.createIdentifierValue(CSSValueSeparate);
2912 case CSSPropertyBorderSpacing: {
2913 auto list = CSSValueList::createSpaceSeparated();
2914 list->append(zoomAdjustedPixelValue(style.horizontalBorderSpacing(), style));
2915 list->append(zoomAdjustedPixelValue(style.verticalBorderSpacing(), style));
2916 return list;
2917 }
2918 case CSSPropertyWebkitBorderHorizontalSpacing:
2919 return zoomAdjustedPixelValue(style.horizontalBorderSpacing(), style);
2920 case CSSPropertyWebkitBorderVerticalSpacing:
2921 return zoomAdjustedPixelValue(style.verticalBorderSpacing(), style);
2922 case CSSPropertyBorderImageSource:
2923 if (style.borderImageSource())
2924 return style.borderImageSource()->cssValue();
2925 return cssValuePool.createIdentifierValue(CSSValueNone);
2926 case CSSPropertyBorderTopColor:
2927 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderTopColor)) : currentColorOrValidColor(&style, style.borderTopColor());
2928 case CSSPropertyBorderRightColor:
2929 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderRightColor)) : currentColorOrValidColor(&style, style.borderRightColor());
2930 case CSSPropertyBorderBottomColor:
2931 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderBottomColor)) : currentColorOrValidColor(&style, style.borderBottomColor());
2932 case CSSPropertyBorderLeftColor:
2933 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyBorderLeftColor)) : currentColorOrValidColor(&style, style.borderLeftColor());
2934 case CSSPropertyBorderTopStyle:
2935 return cssValuePool.createValue(style.borderTopStyle());
2936 case CSSPropertyBorderRightStyle:
2937 return cssValuePool.createValue(style.borderRightStyle());
2938 case CSSPropertyBorderBottomStyle:
2939 return cssValuePool.createValue(style.borderBottomStyle());
2940 case CSSPropertyBorderLeftStyle:
2941 return cssValuePool.createValue(style.borderLeftStyle());
2942 case CSSPropertyBorderTopWidth:
2943 return zoomAdjustedPixelValue(style.borderTopWidth(), style);
2944 case CSSPropertyBorderRightWidth:
2945 return zoomAdjustedPixelValue(style.borderRightWidth(), style);
2946 case CSSPropertyBorderBottomWidth:
2947 return zoomAdjustedPixelValue(style.borderBottomWidth(), style);
2948 case CSSPropertyBorderLeftWidth:
2949 return zoomAdjustedPixelValue(style.borderLeftWidth(), style);
2950 case CSSPropertyBottom:
2951 return positionOffsetValue(style, CSSPropertyBottom, renderer);
2952 case CSSPropertyWebkitBoxAlign:
2953 return cssValuePool.createValue(style.boxAlign());
2954#if ENABLE(CSS_BOX_DECORATION_BREAK)
2955 case CSSPropertyWebkitBoxDecorationBreak:
2956 if (style.boxDecorationBreak() == BoxDecorationBreak::Slice)
2957 return cssValuePool.createIdentifierValue(CSSValueSlice);
2958 return cssValuePool.createIdentifierValue(CSSValueClone);
2959#endif
2960 case CSSPropertyWebkitBoxDirection:
2961 return cssValuePool.createValue(style.boxDirection());
2962 case CSSPropertyWebkitBoxFlex:
2963 return cssValuePool.createValue(style.boxFlex(), CSSPrimitiveValue::CSS_NUMBER);
2964 case CSSPropertyWebkitBoxFlexGroup:
2965 return cssValuePool.createValue(style.boxFlexGroup(), CSSPrimitiveValue::CSS_NUMBER);
2966 case CSSPropertyWebkitBoxLines:
2967 return cssValuePool.createValue(style.boxLines());
2968 case CSSPropertyWebkitBoxOrdinalGroup:
2969 return cssValuePool.createValue(style.boxOrdinalGroup(), CSSPrimitiveValue::CSS_NUMBER);
2970 case CSSPropertyWebkitBoxOrient:
2971 return cssValuePool.createValue(style.boxOrient());
2972 case CSSPropertyWebkitBoxPack:
2973 return cssValuePool.createValue(style.boxPack());
2974 case CSSPropertyWebkitBoxReflect:
2975 return valueForReflection(style.boxReflect(), style);
2976 case CSSPropertyBoxShadow:
2977 case CSSPropertyWebkitBoxShadow:
2978 return valueForShadow(style.boxShadow(), propertyID, style);
2979 case CSSPropertyCaptionSide:
2980 return cssValuePool.createValue(style.captionSide());
2981 case CSSPropertyCaretColor:
2982 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyCaretColor)) : currentColorOrValidColor(&style, style.caretColor());
2983 case CSSPropertyClear:
2984 return cssValuePool.createValue(style.clear());
2985 case CSSPropertyColor:
2986 return cssValuePool.createColorValue(m_allowVisitedStyle ? style.visitedDependentColor(CSSPropertyColor) : style.color());
2987 case CSSPropertyWebkitPrintColorAdjust:
2988 return cssValuePool.createValue(style.printColorAdjust());
2989 case CSSPropertyWebkitColumnAxis:
2990 return cssValuePool.createValue(style.columnAxis());
2991 case CSSPropertyColumnCount:
2992 if (style.hasAutoColumnCount())
2993 return cssValuePool.createIdentifierValue(CSSValueAuto);
2994 return cssValuePool.createValue(style.columnCount(), CSSPrimitiveValue::CSS_NUMBER);
2995 case CSSPropertyColumnFill:
2996 return cssValuePool.createValue(style.columnFill());
2997 case CSSPropertyColumnGap:
2998 if (style.columnGap().isNormal())
2999 return cssValuePool.createIdentifierValue(CSSValueNormal);
3000 return zoomAdjustedPixelValueForLength(style.columnGap().length(), style);
3001 case CSSPropertyRowGap:
3002 if (style.rowGap().isNormal())
3003 return cssValuePool.createIdentifierValue(CSSValueNormal);
3004 return zoomAdjustedPixelValueForLength(style.rowGap().length(), style);
3005 case CSSPropertyWebkitColumnProgression:
3006 return cssValuePool.createValue(style.columnProgression());
3007 case CSSPropertyColumnRuleColor:
3008 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyOutlineColor)) : currentColorOrValidColor(&style, style.columnRuleColor());
3009 case CSSPropertyColumnRuleStyle:
3010 return cssValuePool.createValue(style.columnRuleStyle());
3011 case CSSPropertyColumnRuleWidth:
3012 return zoomAdjustedPixelValue(style.columnRuleWidth(), style);
3013 case CSSPropertyColumnSpan:
3014 return cssValuePool.createIdentifierValue(style.columnSpan() == ColumnSpan::All ? CSSValueAll : CSSValueNone);
3015 case CSSPropertyWebkitColumnBreakAfter:
3016 return cssValuePool.createValue(convertToColumnBreak(style.breakAfter()));
3017 case CSSPropertyWebkitColumnBreakBefore:
3018 return cssValuePool.createValue(convertToColumnBreak(style.breakBefore()));
3019 case CSSPropertyWebkitColumnBreakInside:
3020 return cssValuePool.createValue(convertToColumnBreak(style.breakInside()));
3021 case CSSPropertyColumnWidth:
3022 if (style.hasAutoColumnWidth())
3023 return cssValuePool.createIdentifierValue(CSSValueAuto);
3024 return zoomAdjustedPixelValue(style.columnWidth(), style);
3025 case CSSPropertyTabSize:
3026 return cssValuePool.createValue(style.tabSize(), CSSPrimitiveValue::CSS_NUMBER);
3027 case CSSPropertyCursor: {
3028 RefPtr<CSSValueList> list;
3029 auto* cursors = style.cursors();
3030 if (cursors && cursors->size() > 0) {
3031 list = CSSValueList::createCommaSeparated();
3032 for (unsigned i = 0; i < cursors->size(); ++i)
3033 if (StyleImage* image = cursors->at(i).image())
3034 list->append(image->cssValue());
3035 }
3036 auto value = cssValuePool.createValue(style.cursor());
3037 if (list) {
3038 list->append(WTFMove(value));
3039 return list;
3040 }
3041 return value;
3042 }
3043#if ENABLE(CURSOR_VISIBILITY)
3044 case CSSPropertyWebkitCursorVisibility:
3045 return cssValuePool.createValue(style.cursorVisibility());
3046#endif
3047 case CSSPropertyDirection:
3048 return cssValuePool.createValue(style.direction());
3049 case CSSPropertyDisplay:
3050 return cssValuePool.createValue(style.display());
3051 case CSSPropertyEmptyCells:
3052 return cssValuePool.createValue(style.emptyCells());
3053 case CSSPropertyAlignContent:
3054 return valueForContentPositionAndDistributionWithOverflowAlignment(style.alignContent());
3055 case CSSPropertyAlignItems:
3056 return valueForItemPositionWithOverflowAlignment(style.alignItems());
3057 case CSSPropertyAlignSelf:
3058 return valueForItemPositionWithOverflowAlignment(style.alignSelf());
3059 case CSSPropertyFlex:
3060 return getCSSPropertyValuesForShorthandProperties(flexShorthand());
3061 case CSSPropertyFlexBasis:
3062 return cssValuePool.createValue(style.flexBasis(), style);
3063 case CSSPropertyFlexDirection:
3064 return cssValuePool.createValue(style.flexDirection());
3065 case CSSPropertyFlexFlow:
3066 return getCSSPropertyValuesForShorthandProperties(flexFlowShorthand());
3067 case CSSPropertyFlexGrow:
3068 return cssValuePool.createValue(style.flexGrow());
3069 case CSSPropertyFlexShrink:
3070 return cssValuePool.createValue(style.flexShrink());
3071 case CSSPropertyFlexWrap:
3072 return cssValuePool.createValue(style.flexWrap());
3073 case CSSPropertyJustifyContent:
3074 return valueForContentPositionAndDistributionWithOverflowAlignment(style.justifyContent());
3075 case CSSPropertyJustifyItems:
3076 return valueForItemPositionWithOverflowAlignment(style.justifyItems());
3077 case CSSPropertyJustifySelf:
3078 return valueForItemPositionWithOverflowAlignment(style.justifySelf());
3079 case CSSPropertyPlaceContent:
3080 return getCSSPropertyValuesForShorthandProperties(placeContentShorthand());
3081 case CSSPropertyPlaceItems:
3082 return getCSSPropertyValuesForShorthandProperties(placeItemsShorthand());
3083 case CSSPropertyPlaceSelf:
3084 return getCSSPropertyValuesForShorthandProperties(placeSelfShorthand());
3085 case CSSPropertyOrder:
3086 return cssValuePool.createValue(style.order(), CSSPrimitiveValue::CSS_NUMBER);
3087 case CSSPropertyFloat:
3088 if (style.display() != DisplayType::None && style.hasOutOfFlowPosition())
3089 return cssValuePool.createIdentifierValue(CSSValueNone);
3090 return cssValuePool.createValue(style.floating());
3091 case CSSPropertyFont: {
3092 auto computedFont = fontShorthandValueForSelectionProperties(style.fontDescription());
3093 computedFont->size = fontSizeFromStyle(style);
3094 computedFont->lineHeight = lineHeightFromStyle(style);
3095 computedFont->family = fontFamilyListFromStyle(style);
3096 return computedFont;
3097 }
3098 case CSSPropertyFontFamily:
3099 return fontFamilyFromStyle(style);
3100 case CSSPropertyFontSize:
3101 return fontSizeFromStyle(style);
3102 case CSSPropertyFontStyle:
3103 return fontStyleFromStyle(style);
3104 case CSSPropertyFontStretch:
3105 return fontStretchFromStyle(style);
3106 case CSSPropertyFontVariant:
3107 return fontVariantFromStyle(style);
3108 case CSSPropertyFontWeight:
3109 return fontWeightFromStyle(style);
3110 case CSSPropertyFontSynthesis:
3111 return fontSynthesisFromStyle(style);
3112 case CSSPropertyFontFeatureSettings: {
3113 const FontFeatureSettings& featureSettings = style.fontDescription().featureSettings();
3114 if (!featureSettings.size())
3115 return cssValuePool.createIdentifierValue(CSSValueNormal);
3116 auto list = CSSValueList::createCommaSeparated();
3117 for (auto& feature : featureSettings)
3118 list->append(CSSFontFeatureValue::create(FontTag(feature.tag()), feature.value()));
3119 return list;
3120 }
3121#if ENABLE(VARIATION_FONTS)
3122 case CSSPropertyFontVariationSettings: {
3123 const FontVariationSettings& variationSettings = style.fontDescription().variationSettings();
3124 if (variationSettings.isEmpty())
3125 return cssValuePool.createIdentifierValue(CSSValueNormal);
3126 auto list = CSSValueList::createCommaSeparated();
3127 for (auto& feature : variationSettings)
3128 list->append(CSSFontVariationValue::create(feature.tag(), feature.value()));
3129 return list;
3130 }
3131 case CSSPropertyFontOpticalSizing:
3132 return cssValuePool.createValue(style.fontDescription().opticalSizing());
3133#endif
3134 case CSSPropertyGridAutoFlow: {
3135 auto list = CSSValueList::createSpaceSeparated();
3136 ASSERT(style.isGridAutoFlowDirectionRow() || style.isGridAutoFlowDirectionColumn());
3137 if (style.isGridAutoFlowDirectionRow())
3138 list->append(cssValuePool.createIdentifierValue(CSSValueRow));
3139 else
3140 list->append(cssValuePool.createIdentifierValue(CSSValueColumn));
3141
3142 if (style.isGridAutoFlowAlgorithmDense())
3143 list->append(cssValuePool.createIdentifierValue(CSSValueDense));
3144
3145 return list;
3146 }
3147
3148 // Specs mention that getComputedStyle() should return the used value of the property instead of the computed
3149 // one for grid-template-{rows|columns} but not for the grid-auto-{rows|columns} as things like
3150 // grid-auto-columns: 2fr; cannot be resolved to a value in pixels as the '2fr' means very different things
3151 // depending on the size of the explicit grid or the number of implicit tracks added to the grid. See
3152 // http://lists.w3.org/Archives/Public/www-style/2013Nov/0014.html
3153 case CSSPropertyGridAutoColumns:
3154 return valueForGridTrackSizeList(ForColumns, style);
3155 case CSSPropertyGridAutoRows:
3156 return valueForGridTrackSizeList(ForRows, style);
3157
3158 case CSSPropertyGridTemplateColumns:
3159 return valueForGridTrackList(ForColumns, renderer, style);
3160 case CSSPropertyGridTemplateRows:
3161 return valueForGridTrackList(ForRows, renderer, style);
3162
3163 case CSSPropertyGridColumnStart:
3164 return valueForGridPosition(style.gridItemColumnStart());
3165 case CSSPropertyGridColumnEnd:
3166 return valueForGridPosition(style.gridItemColumnEnd());
3167 case CSSPropertyGridRowStart:
3168 return valueForGridPosition(style.gridItemRowStart());
3169 case CSSPropertyGridRowEnd:
3170 return valueForGridPosition(style.gridItemRowEnd());
3171 case CSSPropertyGridArea:
3172 return getCSSPropertyValuesForGridShorthand(gridAreaShorthand());
3173 case CSSPropertyGridTemplate:
3174 return getCSSPropertyValuesForGridShorthand(gridTemplateShorthand());
3175 case CSSPropertyGrid:
3176 return getCSSPropertyValuesForGridShorthand(gridShorthand());
3177 case CSSPropertyGridColumn:
3178 return getCSSPropertyValuesForGridShorthand(gridColumnShorthand());
3179 case CSSPropertyGridRow:
3180 return getCSSPropertyValuesForGridShorthand(gridRowShorthand());
3181 case CSSPropertyGridTemplateAreas:
3182 if (!style.namedGridAreaRowCount()) {
3183 ASSERT(!style.namedGridAreaColumnCount());
3184 return cssValuePool.createIdentifierValue(CSSValueNone);
3185 }
3186 return CSSGridTemplateAreasValue::create(style.namedGridArea(), style.namedGridAreaRowCount(), style.namedGridAreaColumnCount());
3187 case CSSPropertyGap:
3188 return getCSSPropertyValuesForShorthandProperties(gapShorthand());
3189 case CSSPropertyHeight:
3190 if (renderer && !renderer->isRenderSVGModelObject()) {
3191 // According to http://www.w3.org/TR/CSS2/visudet.html#the-height-property,
3192 // the "height" property does not apply for non-replaced inline elements.
3193 if (isNonReplacedInline(*renderer))
3194 return cssValuePool.createIdentifierValue(CSSValueAuto);
3195 return zoomAdjustedPixelValue(sizingBox(*renderer).height(), style);
3196 }
3197 return zoomAdjustedPixelValueForLength(style.height(), style);
3198 case CSSPropertyWebkitHyphens:
3199 return cssValuePool.createValue(style.hyphens());
3200 case CSSPropertyWebkitHyphenateCharacter:
3201 if (style.hyphenationString().isNull())
3202 return cssValuePool.createIdentifierValue(CSSValueAuto);
3203 return cssValuePool.createValue(style.hyphenationString(), CSSPrimitiveValue::CSS_STRING);
3204 case CSSPropertyWebkitHyphenateLimitAfter:
3205 if (style.hyphenationLimitAfter() < 0)
3206 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
3207 return CSSPrimitiveValue::create(style.hyphenationLimitAfter(), CSSPrimitiveValue::CSS_NUMBER);
3208 case CSSPropertyWebkitHyphenateLimitBefore:
3209 if (style.hyphenationLimitBefore() < 0)
3210 return CSSPrimitiveValue::createIdentifier(CSSValueAuto);
3211 return CSSPrimitiveValue::create(style.hyphenationLimitBefore(), CSSPrimitiveValue::CSS_NUMBER);
3212 case CSSPropertyWebkitHyphenateLimitLines:
3213 if (style.hyphenationLimitLines() < 0)
3214 return CSSPrimitiveValue::createIdentifier(CSSValueNoLimit);
3215 return CSSPrimitiveValue::create(style.hyphenationLimitLines(), CSSPrimitiveValue::CSS_NUMBER);
3216 case CSSPropertyWebkitBorderFit:
3217 if (style.borderFit() == BorderFit::Border)
3218 return cssValuePool.createIdentifierValue(CSSValueBorder);
3219 return cssValuePool.createIdentifierValue(CSSValueLines);
3220#if ENABLE(CSS_IMAGE_ORIENTATION)
3221 case CSSPropertyImageOrientation:
3222 return cssValuePool.createValue(style.imageOrientation());
3223#endif
3224 case CSSPropertyImageRendering:
3225 return CSSPrimitiveValue::create(style.imageRendering());
3226#if ENABLE(CSS_IMAGE_RESOLUTION)
3227 case CSSPropertyImageResolution:
3228 return cssValuePool.createValue(style.imageResolution(), CSSPrimitiveValue::CSS_DPPX);
3229#endif
3230 case CSSPropertyLeft:
3231 return positionOffsetValue(style, CSSPropertyLeft, renderer);
3232 case CSSPropertyLetterSpacing:
3233 if (!style.letterSpacing())
3234 return cssValuePool.createIdentifierValue(CSSValueNormal);
3235 return zoomAdjustedPixelValue(style.letterSpacing(), style);
3236 case CSSPropertyWebkitLineClamp:
3237 if (style.lineClamp().isNone())
3238 return cssValuePool.createIdentifierValue(CSSValueNone);
3239 return cssValuePool.createValue(style.lineClamp().value(), style.lineClamp().isPercentage() ? CSSPrimitiveValue::CSS_PERCENTAGE : CSSPrimitiveValue::CSS_NUMBER);
3240 case CSSPropertyLineHeight:
3241 return lineHeightFromStyle(style);
3242 case CSSPropertyListStyleImage:
3243 if (style.listStyleImage())
3244 return style.listStyleImage()->cssValue();
3245 return cssValuePool.createIdentifierValue(CSSValueNone);
3246 case CSSPropertyListStylePosition:
3247 return cssValuePool.createValue(style.listStylePosition());
3248 case CSSPropertyListStyleType:
3249 return cssValuePool.createValue(style.listStyleType());
3250 case CSSPropertyWebkitLocale:
3251 if (style.locale().isNull())
3252 return cssValuePool.createIdentifierValue(CSSValueAuto);
3253 return cssValuePool.createValue(style.locale(), CSSPrimitiveValue::CSS_STRING);
3254 case CSSPropertyMarginTop:
3255 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginTop, &RenderBoxModelObject::marginTop>(style, renderer);
3256 case CSSPropertyMarginRight: {
3257 Length marginRight = style.marginRight();
3258 if (marginRight.isFixed() || !is<RenderBox>(renderer))
3259 return zoomAdjustedPixelValueForLength(marginRight, style);
3260 float value;
3261 if (marginRight.isPercentOrCalculated()) {
3262 // RenderBox gives a marginRight() that is the distance between the right-edge of the child box
3263 // and the right-edge of the containing box, when display == DisplayType::Block. Let's calculate the absolute
3264 // value of the specified margin-right % instead of relying on RenderBox's marginRight() value.
3265 value = minimumValueForLength(marginRight, downcast<RenderBox>(*renderer).containingBlockLogicalWidthForContent());
3266 } else
3267 value = downcast<RenderBox>(*renderer).marginRight();
3268 return zoomAdjustedPixelValue(value, style);
3269 }
3270 case CSSPropertyMarginBottom:
3271 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginBottom, &RenderBoxModelObject::marginBottom>(style, renderer);
3272 case CSSPropertyMarginLeft:
3273 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::marginLeft, &RenderBoxModelObject::marginLeft>(style, renderer);
3274 case CSSPropertyWebkitMarqueeDirection:
3275 return cssValuePool.createValue(style.marqueeDirection());
3276 case CSSPropertyWebkitMarqueeIncrement:
3277 return cssValuePool.createValue(style.marqueeIncrement());
3278 case CSSPropertyWebkitMarqueeRepetition:
3279 if (style.marqueeLoopCount() < 0)
3280 return cssValuePool.createIdentifierValue(CSSValueInfinite);
3281 return cssValuePool.createValue(style.marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER);
3282 case CSSPropertyWebkitMarqueeStyle:
3283 return cssValuePool.createValue(style.marqueeBehavior());
3284 case CSSPropertyWebkitUserModify:
3285 return cssValuePool.createValue(style.userModify());
3286 case CSSPropertyMaxHeight: {
3287 const Length& maxHeight = style.maxHeight();
3288 if (maxHeight.isUndefined())
3289 return cssValuePool.createIdentifierValue(CSSValueNone);
3290 return zoomAdjustedPixelValueForLength(maxHeight, style);
3291 }
3292 case CSSPropertyMaxWidth: {
3293 const Length& maxWidth = style.maxWidth();
3294 if (maxWidth.isUndefined())
3295 return cssValuePool.createIdentifierValue(CSSValueNone);
3296 return zoomAdjustedPixelValueForLength(maxWidth, style);
3297 }
3298 case CSSPropertyMinHeight:
3299 if (style.minHeight().isAuto()) {
3300 auto* styledElement = this->styledElement();
3301 if (styledElement && isFlexOrGrid(styledElement->parentNode()))
3302 return cssValuePool.createIdentifierValue(CSSValueAuto);
3303 return zoomAdjustedPixelValue(0, style);
3304 }
3305 return zoomAdjustedPixelValueForLength(style.minHeight(), style);
3306 case CSSPropertyMinWidth:
3307 if (style.minWidth().isAuto()) {
3308 auto* styledElement = this->styledElement();
3309 if (styledElement && isFlexOrGrid(styledElement->parentNode()))
3310 return cssValuePool.createIdentifierValue(CSSValueAuto);
3311 return zoomAdjustedPixelValue(0, style);
3312 }
3313 return zoomAdjustedPixelValueForLength(style.minWidth(), style);
3314 case CSSPropertyObjectFit:
3315 return cssValuePool.createValue(style.objectFit());
3316 case CSSPropertyObjectPosition: {
3317 auto list = CSSValueList::createSpaceSeparated();
3318 list->append(zoomAdjustedPixelValueForLength(style.objectPosition().x(), style));
3319 list->append(zoomAdjustedPixelValueForLength(style.objectPosition().y(), style));
3320 return list;
3321 }
3322 case CSSPropertyOpacity:
3323 return cssValuePool.createValue(style.opacity(), CSSPrimitiveValue::CSS_NUMBER);
3324 case CSSPropertyOrphans:
3325 if (style.hasAutoOrphans())
3326 return cssValuePool.createIdentifierValue(CSSValueAuto);
3327 return cssValuePool.createValue(style.orphans(), CSSPrimitiveValue::CSS_NUMBER);
3328 case CSSPropertyOutlineColor:
3329 return m_allowVisitedStyle ? cssValuePool.createColorValue(style.visitedDependentColor(CSSPropertyOutlineColor)) : currentColorOrValidColor(&style, style.outlineColor());
3330 case CSSPropertyOutlineOffset:
3331 return zoomAdjustedPixelValue(style.outlineOffset(), style);
3332 case CSSPropertyOutlineStyle:
3333 if (style.outlineStyleIsAuto() == OutlineIsAuto::On)
3334 return cssValuePool.createIdentifierValue(CSSValueAuto);
3335 return cssValuePool.createValue(style.outlineStyle());
3336 case CSSPropertyOutlineWidth:
3337 return zoomAdjustedPixelValue(style.outlineWidth(), style);
3338 case CSSPropertyOverflow:
3339 return cssValuePool.createValue(std::max(style.overflowX(), style.overflowY()));
3340 case CSSPropertyOverflowWrap:
3341 return cssValuePool.createValue(style.overflowWrap());
3342 case CSSPropertyOverflowX:
3343 return cssValuePool.createValue(style.overflowX());
3344 case CSSPropertyOverflowY:
3345 return cssValuePool.createValue(style.overflowY());
3346 case CSSPropertyPaddingTop:
3347 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingTop, &RenderBoxModelObject::computedCSSPaddingTop>(style, renderer);
3348 case CSSPropertyPaddingRight:
3349 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingRight, &RenderBoxModelObject::computedCSSPaddingRight>(style, renderer);
3350 case CSSPropertyPaddingBottom:
3351 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingBottom, &RenderBoxModelObject::computedCSSPaddingBottom>(style, renderer);
3352 case CSSPropertyPaddingLeft:
3353 return zoomAdjustedPaddingOrMarginPixelValue<&RenderStyle::paddingLeft, &RenderBoxModelObject::computedCSSPaddingLeft>(style, renderer);
3354 case CSSPropertyPageBreakAfter:
3355 return cssValuePool.createValue(convertToPageBreak(style.breakAfter()));
3356 case CSSPropertyPageBreakBefore:
3357 return cssValuePool.createValue(convertToPageBreak(style.breakBefore()));
3358 case CSSPropertyPageBreakInside:
3359 return cssValuePool.createValue(convertToPageBreak(style.breakInside()));
3360 case CSSPropertyBreakAfter:
3361 return cssValuePool.createValue(style.breakAfter());
3362 case CSSPropertyBreakBefore:
3363 return cssValuePool.createValue(style.breakBefore());
3364 case CSSPropertyBreakInside:
3365 return cssValuePool.createValue(style.breakInside());
3366 case CSSPropertyHangingPunctuation:
3367 return hangingPunctuationToCSSValue(style.hangingPunctuation());
3368 case CSSPropertyPosition:
3369 return cssValuePool.createValue(style.position());
3370 case CSSPropertyRight:
3371 return positionOffsetValue(style, CSSPropertyRight, renderer);
3372 case CSSPropertyWebkitRubyPosition:
3373 return cssValuePool.createValue(style.rubyPosition());
3374 case CSSPropertyTableLayout:
3375 return cssValuePool.createValue(style.tableLayout());
3376 case CSSPropertyTextAlign:
3377 return cssValuePool.createValue(style.textAlign());
3378 case CSSPropertyTextDecoration:
3379 return renderTextDecorationFlagsToCSSValue(style.textDecoration());
3380#if ENABLE(CSS3_TEXT)
3381 case CSSPropertyWebkitTextAlignLast:
3382 return cssValuePool.createValue(style.textAlignLast());
3383 case CSSPropertyWebkitTextJustify:
3384 return cssValuePool.createValue(style.textJustify());
3385#endif // CSS3_TEXT
3386 case CSSPropertyWebkitTextDecoration:
3387 return getCSSPropertyValuesForShorthandProperties(webkitTextDecorationShorthand());
3388 case CSSPropertyTextDecorationLine:
3389 return renderTextDecorationFlagsToCSSValue(style.textDecoration());
3390 case CSSPropertyTextDecorationStyle:
3391 return renderTextDecorationStyleFlagsToCSSValue(style.textDecorationStyle());
3392 case CSSPropertyTextDecorationColor:
3393 return currentColorOrValidColor(&style, style.textDecorationColor());
3394 case CSSPropertyTextDecorationSkip:
3395 return renderTextDecorationSkipFlagsToCSSValue(style.textDecorationSkip());
3396 case CSSPropertyTextUnderlinePosition:
3397 return cssValuePool.createValue(style.textUnderlinePosition());
3398 case CSSPropertyTextUnderlineOffset:
3399 return textUnderlineOffsetToCSSValue(style.textUnderlineOffset());
3400 case CSSPropertyTextDecorationThickness:
3401 return textDecorationThicknessToCSSValue(style.textDecorationThickness());
3402 case CSSPropertyWebkitTextDecorationsInEffect:
3403 return renderTextDecorationFlagsToCSSValue(style.textDecorationsInEffect());
3404 case CSSPropertyWebkitTextFillColor:
3405 return currentColorOrValidColor(&style, style.textFillColor());
3406 case CSSPropertyWebkitTextEmphasisColor:
3407 return currentColorOrValidColor(&style, style.textEmphasisColor());
3408 case CSSPropertyWebkitTextEmphasisPosition:
3409 return renderEmphasisPositionFlagsToCSSValue(style.textEmphasisPosition());
3410 case CSSPropertyWebkitTextEmphasisStyle:
3411 switch (style.textEmphasisMark()) {
3412 case TextEmphasisMark::None:
3413 return cssValuePool.createIdentifierValue(CSSValueNone);
3414 case TextEmphasisMark::Custom:
3415 return cssValuePool.createValue(style.textEmphasisCustomMark(), CSSPrimitiveValue::CSS_STRING);
3416 case TextEmphasisMark::Auto:
3417 ASSERT_NOT_REACHED();
3418#if ASSERT_DISABLED
3419 FALLTHROUGH;
3420#endif
3421 case TextEmphasisMark::Dot:
3422 case TextEmphasisMark::Circle:
3423 case TextEmphasisMark::DoubleCircle:
3424 case TextEmphasisMark::Triangle:
3425 case TextEmphasisMark::Sesame:
3426 auto list = CSSValueList::createSpaceSeparated();
3427 list->append(cssValuePool.createValue(style.textEmphasisFill()));
3428 list->append(cssValuePool.createValue(style.textEmphasisMark()));
3429 return list;
3430 }
3431 RELEASE_ASSERT_NOT_REACHED();
3432 case CSSPropertyTextIndent: {
3433 // If CSS3_TEXT is disabled or text-indent has only one value(<length> | <percentage>),
3434 // getPropertyCSSValue() returns CSSValue.
3435 auto textIndent = zoomAdjustedPixelValueForLength(style.textIndent(), style);
3436#if ENABLE(CSS3_TEXT)
3437 // If CSS3_TEXT is enabled and text-indent has -webkit-each-line or -webkit-hanging,
3438 // getPropertyCSSValue() returns CSSValueList.
3439 if (style.textIndentLine() == TextIndentLine::EachLine || style.textIndentType() == TextIndentType::Hanging) {
3440 auto list = CSSValueList::createSpaceSeparated();
3441 list->append(WTFMove(textIndent));
3442 if (style.textIndentLine() == TextIndentLine::EachLine)
3443 list->append(cssValuePool.createIdentifierValue(CSSValueWebkitEachLine));
3444 if (style.textIndentType() == TextIndentType::Hanging)
3445 list->append(cssValuePool.createIdentifierValue(CSSValueWebkitHanging));
3446 return list;
3447 }
3448#endif
3449 return textIndent;
3450 }
3451 case CSSPropertyTextShadow:
3452 return valueForShadow(style.textShadow(), propertyID, style);
3453 case CSSPropertyTextRendering:
3454 return cssValuePool.createValue(style.fontDescription().textRenderingMode());
3455 case CSSPropertyTextOverflow:
3456 if (style.textOverflow() == TextOverflow::Ellipsis)
3457 return cssValuePool.createIdentifierValue(CSSValueEllipsis);
3458 return cssValuePool.createIdentifierValue(CSSValueClip);
3459 case CSSPropertyWebkitTextSecurity:
3460 return cssValuePool.createValue(style.textSecurity());
3461#if ENABLE(TEXT_AUTOSIZING)
3462 case CSSPropertyWebkitTextSizeAdjust:
3463 if (style.textSizeAdjust().isAuto())
3464 return cssValuePool.createIdentifierValue(CSSValueAuto);
3465 if (style.textSizeAdjust().isNone())
3466 return cssValuePool.createIdentifierValue(CSSValueNone);
3467 return CSSPrimitiveValue::create(style.textSizeAdjust().percentage(), CSSPrimitiveValue::CSS_PERCENTAGE);
3468#endif
3469 case CSSPropertyWebkitTextStrokeColor:
3470 return currentColorOrValidColor(&style, style.textStrokeColor());
3471 case CSSPropertyWebkitTextStrokeWidth:
3472 return zoomAdjustedPixelValue(style.textStrokeWidth(), style);
3473 case CSSPropertyTextTransform:
3474 return cssValuePool.createValue(style.textTransform());
3475 case CSSPropertyTop:
3476 return positionOffsetValue(style, CSSPropertyTop, renderer);
3477 case CSSPropertyUnicodeBidi:
3478 return cssValuePool.createValue(style.unicodeBidi());
3479 case CSSPropertyVerticalAlign:
3480 switch (style.verticalAlign()) {
3481 case VerticalAlign::Baseline:
3482 return cssValuePool.createIdentifierValue(CSSValueBaseline);
3483 case VerticalAlign::Middle:
3484 return cssValuePool.createIdentifierValue(CSSValueMiddle);
3485 case VerticalAlign::Sub:
3486 return cssValuePool.createIdentifierValue(CSSValueSub);
3487 case VerticalAlign::Super:
3488 return cssValuePool.createIdentifierValue(CSSValueSuper);
3489 case VerticalAlign::TextTop:
3490 return cssValuePool.createIdentifierValue(CSSValueTextTop);
3491 case VerticalAlign::TextBottom:
3492 return cssValuePool.createIdentifierValue(CSSValueTextBottom);
3493 case VerticalAlign::Top:
3494 return cssValuePool.createIdentifierValue(CSSValueTop);
3495 case VerticalAlign::Bottom:
3496 return cssValuePool.createIdentifierValue(CSSValueBottom);
3497 case VerticalAlign::BaselineMiddle:
3498 return cssValuePool.createIdentifierValue(CSSValueWebkitBaselineMiddle);
3499 case VerticalAlign::Length:
3500 return cssValuePool.createValue(style.verticalAlignLength());
3501 }
3502 ASSERT_NOT_REACHED();
3503 return nullptr;
3504 case CSSPropertyVisibility:
3505 return cssValuePool.createValue(style.visibility());
3506 case CSSPropertyWhiteSpace:
3507 return cssValuePool.createValue(style.whiteSpace());
3508 case CSSPropertyWidows:
3509 if (style.hasAutoWidows())
3510 return cssValuePool.createIdentifierValue(CSSValueAuto);
3511 return cssValuePool.createValue(style.widows(), CSSPrimitiveValue::CSS_NUMBER);
3512 case CSSPropertyWidth:
3513 if (renderer && !renderer->isRenderSVGModelObject()) {
3514 // According to http://www.w3.org/TR/CSS2/visudet.html#the-width-property,
3515 // the "width" property does not apply for non-replaced inline elements.
3516 if (isNonReplacedInline(*renderer))
3517 return cssValuePool.createIdentifierValue(CSSValueAuto);
3518 return zoomAdjustedPixelValue(sizingBox(*renderer).width(), style);
3519 }
3520 return zoomAdjustedPixelValueForLength(style.width(), style);
3521 case CSSPropertyWillChange:
3522 return willChangePropertyValue(style.willChange());
3523 case CSSPropertyWordBreak:
3524 return cssValuePool.createValue(style.wordBreak());
3525 case CSSPropertyWordSpacing:
3526 return zoomAdjustedPixelValue(style.fontCascade().wordSpacing(), style);
3527 case CSSPropertyWordWrap:
3528 return cssValuePool.createValue(style.overflowWrap());
3529 case CSSPropertyLineBreak:
3530 return cssValuePool.createValue(style.lineBreak());
3531 case CSSPropertyWebkitNbspMode:
3532 return cssValuePool.createValue(style.nbspMode());
3533 case CSSPropertyResize:
3534 return cssValuePool.createValue(style.resize());
3535 case CSSPropertyWebkitFontKerning:
3536 return cssValuePool.createValue(style.fontDescription().kerning());
3537 case CSSPropertyWebkitFontSmoothing:
3538 return cssValuePool.createValue(style.fontDescription().fontSmoothing());
3539 case CSSPropertyFontVariantLigatures:
3540 return fontVariantLigaturesPropertyValue(style.fontDescription().variantCommonLigatures(), style.fontDescription().variantDiscretionaryLigatures(), style.fontDescription().variantHistoricalLigatures(), style.fontDescription().variantContextualAlternates());
3541 case CSSPropertyFontVariantPosition:
3542 return fontVariantPositionPropertyValue(style.fontDescription().variantPosition());
3543 case CSSPropertyFontVariantCaps:
3544 return fontVariantCapsPropertyValue(style.fontDescription().variantCaps());
3545 case CSSPropertyFontVariantNumeric:
3546 return fontVariantNumericPropertyValue(style.fontDescription().variantNumericFigure(), style.fontDescription().variantNumericSpacing(), style.fontDescription().variantNumericFraction(), style.fontDescription().variantNumericOrdinal(), style.fontDescription().variantNumericSlashedZero());
3547 case CSSPropertyFontVariantAlternates:
3548 return fontVariantAlternatesPropertyValue(style.fontDescription().variantAlternates());
3549 case CSSPropertyFontVariantEastAsian:
3550 return fontVariantEastAsianPropertyValue(style.fontDescription().variantEastAsianVariant(), style.fontDescription().variantEastAsianWidth(), style.fontDescription().variantEastAsianRuby());
3551 case CSSPropertyZIndex:
3552 if (style.hasAutoZIndex())
3553 return cssValuePool.createIdentifierValue(CSSValueAuto);
3554 return cssValuePool.createValue(style.zIndex(), CSSPrimitiveValue::CSS_NUMBER);
3555 case CSSPropertyZoom:
3556 return cssValuePool.createValue(style.zoom(), CSSPrimitiveValue::CSS_NUMBER);
3557 case CSSPropertyBoxSizing:
3558 if (style.boxSizing() == BoxSizing::ContentBox)
3559 return cssValuePool.createIdentifierValue(CSSValueContentBox);
3560 return cssValuePool.createIdentifierValue(CSSValueBorderBox);
3561#if ENABLE(DASHBOARD_SUPPORT)
3562 case CSSPropertyWebkitDashboardRegion:
3563 {
3564 const Vector<StyleDashboardRegion>& regions = style.dashboardRegions();
3565 unsigned count = regions.size();
3566 if (count == 1 && regions[0].type == StyleDashboardRegion::None)
3567 return cssValuePool.createIdentifierValue(CSSValueNone);
3568
3569 RefPtr<DashboardRegion> firstRegion;
3570 DashboardRegion* previousRegion = nullptr;
3571 for (unsigned i = 0; i < count; i++) {
3572 auto region = DashboardRegion::create();
3573 StyleDashboardRegion styleRegion = regions[i];
3574
3575 region->m_label = styleRegion.label;
3576 LengthBox offset = styleRegion.offset;
3577 region->setTop(zoomAdjustedPixelValue(offset.top().value(), style));
3578 region->setRight(zoomAdjustedPixelValue(offset.right().value(), style));
3579 region->setBottom(zoomAdjustedPixelValue(offset.bottom().value(), style));
3580 region->setLeft(zoomAdjustedPixelValue(offset.left().value(), style));
3581 region->m_isRectangle = (styleRegion.type == StyleDashboardRegion::Rectangle);
3582 region->m_isCircle = (styleRegion.type == StyleDashboardRegion::Circle);
3583
3584 if (previousRegion)
3585 previousRegion->m_next = region.copyRef();
3586 else
3587 firstRegion = region.copyRef();
3588 previousRegion = region.ptr();
3589 }
3590 return cssValuePool.createValue(WTFMove(firstRegion));
3591 }
3592#endif
3593 case CSSPropertyAnimationDelay:
3594 return delayValue(style.animations());
3595 case CSSPropertyAnimationDirection: {
3596 auto list = CSSValueList::createCommaSeparated();
3597 const AnimationList* t = style.animations();
3598 if (t) {
3599 for (size_t i = 0; i < t->size(); ++i) {
3600 switch (t->animation(i).direction()) {
3601 case Animation::AnimationDirectionNormal:
3602 list->append(cssValuePool.createIdentifierValue(CSSValueNormal));
3603 break;
3604 case Animation::AnimationDirectionAlternate:
3605 list->append(cssValuePool.createIdentifierValue(CSSValueAlternate));
3606 break;
3607 case Animation::AnimationDirectionReverse:
3608 list->append(cssValuePool.createIdentifierValue(CSSValueReverse));
3609 break;
3610 case Animation::AnimationDirectionAlternateReverse:
3611 list->append(cssValuePool.createIdentifierValue(CSSValueAlternateReverse));
3612 break;
3613 }
3614 }
3615 } else
3616 list->append(cssValuePool.createIdentifierValue(CSSValueNormal));
3617 return list;
3618 }
3619 case CSSPropertyAnimationDuration:
3620 return durationValue(style.animations());
3621 case CSSPropertyAnimationFillMode: {
3622 auto list = CSSValueList::createCommaSeparated();
3623 const AnimationList* t = style.animations();
3624 if (t) {
3625 for (size_t i = 0; i < t->size(); ++i) {
3626 switch (t->animation(i).fillMode()) {
3627 case AnimationFillMode::None:
3628 list->append(cssValuePool.createIdentifierValue(CSSValueNone));
3629 break;
3630 case AnimationFillMode::Forwards:
3631 list->append(cssValuePool.createIdentifierValue(CSSValueForwards));
3632 break;
3633 case AnimationFillMode::Backwards:
3634 list->append(cssValuePool.createIdentifierValue(CSSValueBackwards));
3635 break;
3636 case AnimationFillMode::Both:
3637 list->append(cssValuePool.createIdentifierValue(CSSValueBoth));
3638 break;
3639 }
3640 }
3641 } else
3642 list->append(cssValuePool.createIdentifierValue(CSSValueNone));
3643 return list;
3644 }
3645 case CSSPropertyAnimationIterationCount: {
3646 auto list = CSSValueList::createCommaSeparated();
3647 const AnimationList* t = style.animations();
3648 if (t) {
3649 for (size_t i = 0; i < t->size(); ++i) {
3650 double iterationCount = t->animation(i).iterationCount();
3651 if (iterationCount == Animation::IterationCountInfinite)
3652 list->append(cssValuePool.createIdentifierValue(CSSValueInfinite));
3653 else
3654 list->append(cssValuePool.createValue(iterationCount, CSSPrimitiveValue::CSS_NUMBER));
3655 }
3656 } else
3657 list->append(cssValuePool.createValue(Animation::initialIterationCount(), CSSPrimitiveValue::CSS_NUMBER));
3658 return list;
3659 }
3660 case CSSPropertyAnimationName: {
3661 auto list = CSSValueList::createCommaSeparated();
3662 const AnimationList* t = style.animations();
3663 if (t) {
3664 for (size_t i = 0; i < t->size(); ++i)
3665 list->append(cssValuePool.createValue(t->animation(i).name(), CSSPrimitiveValue::CSS_STRING));
3666 } else
3667 list->append(cssValuePool.createIdentifierValue(CSSValueNone));
3668 return list;
3669 }
3670 case CSSPropertyAnimationPlayState: {
3671 auto list = CSSValueList::createCommaSeparated();
3672 const AnimationList* t = style.animations();
3673 if (t) {
3674 for (size_t i = 0; i < t->size(); ++i) {
3675 switch (t->animation(i).playState()) {
3676 case AnimationPlayState::Playing:
3677 list->append(cssValuePool.createIdentifierValue(CSSValueRunning));
3678 break;
3679 case AnimationPlayState::Paused:
3680 list->append(cssValuePool.createIdentifierValue(CSSValuePaused));
3681 break;
3682 }
3683 }
3684 } else
3685 list->append(cssValuePool.createIdentifierValue(CSSValueRunning));
3686 return list;
3687 }
3688 case CSSPropertyAnimationTimingFunction:
3689 return timingFunctionValue(style.animations());
3690 case CSSPropertyWebkitAppearance:
3691 return cssValuePool.createValue(style.appearance());
3692 case CSSPropertyWebkitAspectRatio:
3693 switch (style.aspectRatioType()) {
3694 case AspectRatioType::Auto:
3695 return cssValuePool.createIdentifierValue(CSSValueAuto);
3696 case AspectRatioType::FromDimensions:
3697 return cssValuePool.createIdentifierValue(CSSValueFromDimensions);
3698 case AspectRatioType::FromIntrinsic:
3699 return cssValuePool.createIdentifierValue(CSSValueFromIntrinsic);
3700 case AspectRatioType::Specified:
3701 return CSSAspectRatioValue::create(style.aspectRatioNumerator(), style.aspectRatioDenominator());
3702 }
3703 ASSERT_NOT_REACHED();
3704 return nullptr;
3705 case CSSPropertyWebkitBackfaceVisibility:
3706 return cssValuePool.createIdentifierValue((style.backfaceVisibility() == BackfaceVisibility::Hidden) ? CSSValueHidden : CSSValueVisible);
3707 case CSSPropertyWebkitBorderImage:
3708 return valueForNinePieceImage(style.borderImage());
3709 case CSSPropertyBorderImageOutset:
3710 return valueForNinePieceImageQuad(style.borderImage().outset());
3711 case CSSPropertyBorderImageRepeat:
3712 return valueForNinePieceImageRepeat(style.borderImage());
3713 case CSSPropertyBorderImageSlice:
3714 return valueForNinePieceImageSlice(style.borderImage());
3715 case CSSPropertyBorderImageWidth:
3716 return valueForNinePieceImageQuad(style.borderImage().borderSlices());
3717 case CSSPropertyWebkitMaskBoxImage:
3718 return valueForNinePieceImage(style.maskBoxImage());
3719 case CSSPropertyWebkitMaskBoxImageOutset:
3720 return valueForNinePieceImageQuad(style.maskBoxImage().outset());
3721 case CSSPropertyWebkitMaskBoxImageRepeat:
3722 return valueForNinePieceImageRepeat(style.maskBoxImage());
3723 case CSSPropertyWebkitMaskBoxImageSlice:
3724 return valueForNinePieceImageSlice(style.maskBoxImage());
3725 case CSSPropertyWebkitMaskBoxImageWidth:
3726 return valueForNinePieceImageQuad(style.maskBoxImage().borderSlices());
3727 case CSSPropertyWebkitMaskBoxImageSource:
3728 if (style.maskBoxImageSource())
3729 return style.maskBoxImageSource()->cssValue();
3730 return cssValuePool.createIdentifierValue(CSSValueNone);
3731 case CSSPropertyWebkitFontSizeDelta:
3732 // Not a real style property -- used by the editing engine -- so has no computed value.
3733 break;
3734 case CSSPropertyWebkitInitialLetter: {
3735 auto drop = !style.initialLetterDrop() ? cssValuePool.createIdentifierValue(CSSValueNormal) : cssValuePool.createValue(style.initialLetterDrop(), CSSPrimitiveValue::CSS_NUMBER);
3736 auto size = !style.initialLetterHeight() ? cssValuePool.createIdentifierValue(CSSValueNormal) : cssValuePool.createValue(style.initialLetterHeight(), CSSPrimitiveValue::CSS_NUMBER);
3737 return cssValuePool.createValue(Pair::create(WTFMove(drop), WTFMove(size)));
3738 }
3739 case CSSPropertyWebkitMarginBottomCollapse:
3740 case CSSPropertyWebkitMarginAfterCollapse:
3741 return cssValuePool.createValue(style.marginAfterCollapse());
3742 case CSSPropertyWebkitMarginTopCollapse:
3743 case CSSPropertyWebkitMarginBeforeCollapse:
3744 return cssValuePool.createValue(style.marginBeforeCollapse());
3745#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
3746 case CSSPropertyWebkitOverflowScrolling:
3747 if (!style.useTouchOverflowScrolling())
3748 return cssValuePool.createIdentifierValue(CSSValueAuto);
3749 return cssValuePool.createIdentifierValue(CSSValueTouch);
3750#endif
3751 case CSSPropertyPerspective:
3752 if (!style.hasPerspective())
3753 return cssValuePool.createIdentifierValue(CSSValueNone);
3754 return zoomAdjustedPixelValue(style.perspective(), style);
3755 case CSSPropertyPerspectiveOrigin: {
3756 auto list = CSSValueList::createSpaceSeparated();
3757 if (renderer) {
3758 LayoutRect box;
3759 if (is<RenderBox>(*renderer))
3760 box = downcast<RenderBox>(*renderer).borderBoxRect();
3761
3762 list->append(zoomAdjustedPixelValue(minimumValueForLength(style.perspectiveOriginX(), box.width()), style));
3763 list->append(zoomAdjustedPixelValue(minimumValueForLength(style.perspectiveOriginY(), box.height()), style));
3764 } else {
3765 list->append(zoomAdjustedPixelValueForLength(style.perspectiveOriginX(), style));
3766 list->append(zoomAdjustedPixelValueForLength(style.perspectiveOriginY(), style));
3767 }
3768 return list;
3769 }
3770 case CSSPropertyWebkitRtlOrdering:
3771 return cssValuePool.createIdentifierValue(style.rtlOrdering() == Order::Visual ? CSSValueVisual : CSSValueLogical);
3772#if ENABLE(TOUCH_EVENTS)
3773 case CSSPropertyWebkitTapHighlightColor:
3774 return currentColorOrValidColor(&style, style.tapHighlightColor());
3775#endif
3776#if ENABLE(POINTER_EVENTS)
3777 case CSSPropertyTouchAction:
3778 return touchActionFlagsToCSSValue(style.touchActions());
3779#endif
3780#if PLATFORM(IOS_FAMILY)
3781 case CSSPropertyWebkitTouchCallout:
3782 return cssValuePool.createIdentifierValue(style.touchCalloutEnabled() ? CSSValueDefault : CSSValueNone);
3783#endif
3784 case CSSPropertyWebkitUserDrag:
3785 return cssValuePool.createValue(style.userDrag());
3786 case CSSPropertyWebkitUserSelect:
3787 return cssValuePool.createValue(style.userSelect());
3788 case CSSPropertyBorderBottomLeftRadius:
3789 return borderRadiusCornerValue(style.borderBottomLeftRadius(), style);
3790 case CSSPropertyBorderBottomRightRadius:
3791 return borderRadiusCornerValue(style.borderBottomRightRadius(), style);
3792 case CSSPropertyBorderTopLeftRadius:
3793 return borderRadiusCornerValue(style.borderTopLeftRadius(), style);
3794 case CSSPropertyBorderTopRightRadius:
3795 return borderRadiusCornerValue(style.borderTopRightRadius(), style);
3796 case CSSPropertyClip: {
3797 if (!style.hasClip())
3798 return cssValuePool.createIdentifierValue(CSSValueAuto);
3799 auto rect = Rect::create();
3800 rect->setTop(autoOrZoomAdjustedValue(style.clip().top(), style));
3801 rect->setRight(autoOrZoomAdjustedValue(style.clip().right(), style));
3802 rect->setBottom(autoOrZoomAdjustedValue(style.clip().bottom(), style));
3803 rect->setLeft(autoOrZoomAdjustedValue(style.clip().left(), style));
3804 return cssValuePool.createValue(WTFMove(rect));
3805 }
3806 case CSSPropertySpeakAs:
3807 return speakAsToCSSValue(style.speakAs());
3808 case CSSPropertyTransform:
3809 return computedTransform(renderer, style);
3810 case CSSPropertyTransformBox:
3811 return CSSPrimitiveValue::create(style.transformBox());
3812 case CSSPropertyTransformOrigin: {
3813 auto list = CSSValueList::createSpaceSeparated();
3814 if (renderer) {
3815 LayoutRect box;
3816 if (is<RenderBox>(*renderer))
3817 box = downcast<RenderBox>(*renderer).borderBoxRect();
3818
3819 list->append(zoomAdjustedPixelValue(minimumValueForLength(style.transformOriginX(), box.width()), style));
3820 list->append(zoomAdjustedPixelValue(minimumValueForLength(style.transformOriginY(), box.height()), style));
3821 if (style.transformOriginZ())
3822 list->append(zoomAdjustedPixelValue(style.transformOriginZ(), style));
3823 } else {
3824 list->append(zoomAdjustedPixelValueForLength(style.transformOriginX(), style));
3825 list->append(zoomAdjustedPixelValueForLength(style.transformOriginY(), style));
3826 if (style.transformOriginZ())
3827 list->append(zoomAdjustedPixelValue(style.transformOriginZ(), style));
3828 }
3829 return list;
3830 }
3831 case CSSPropertyTransformStyle:
3832 case CSSPropertyWebkitTransformStyle:
3833 return cssValuePool.createIdentifierValue((style.transformStyle3D() == TransformStyle3D::Preserve3D) ? CSSValuePreserve3d : CSSValueFlat);
3834 case CSSPropertyTransitionDelay:
3835 return delayValue(style.transitions());
3836 case CSSPropertyTransitionDuration:
3837 return durationValue(style.transitions());
3838 case CSSPropertyTransitionProperty:
3839 return transitionPropertyValue(style.transitions());
3840 case CSSPropertyTransitionTimingFunction:
3841 return timingFunctionValue(style.transitions());
3842 case CSSPropertyTransition: {
3843 if (auto* animationList = style.transitions()) {
3844 auto transitionsList = CSSValueList::createCommaSeparated();
3845 for (size_t i = 0; i < animationList->size(); ++i) {
3846 auto list = CSSValueList::createSpaceSeparated();
3847 auto& animation = animationList->animation(i);
3848 list->append(createTransitionPropertyValue(animation));
3849 list->append(cssValuePool.createValue(animation.duration(), CSSPrimitiveValue::CSS_S));
3850 list->append(createTimingFunctionValue(*animation.timingFunction()));
3851 list->append(cssValuePool.createValue(animation.delay(), CSSPrimitiveValue::CSS_S));
3852 transitionsList->append(WTFMove(list));
3853 }
3854 return transitionsList;
3855 }
3856
3857 auto list = CSSValueList::createSpaceSeparated();
3858 // transition-property default value.
3859 list->append(cssValuePool.createIdentifierValue(CSSValueAll));
3860 list->append(cssValuePool.createValue(Animation::initialDuration(), CSSPrimitiveValue::CSS_S));
3861 list->append(createTimingFunctionValue(Animation::initialTimingFunction()));
3862 list->append(cssValuePool.createValue(Animation::initialDelay(), CSSPrimitiveValue::CSS_S));
3863 return list;
3864 }
3865 case CSSPropertyPointerEvents:
3866 return cssValuePool.createValue(style.pointerEvents());
3867 case CSSPropertyWebkitLineGrid:
3868 if (style.lineGrid().isNull())
3869 return cssValuePool.createIdentifierValue(CSSValueNone);
3870 return cssValuePool.createValue(style.lineGrid(), CSSPrimitiveValue::CSS_STRING);
3871 case CSSPropertyWebkitLineSnap:
3872 return CSSPrimitiveValue::create(style.lineSnap());
3873 case CSSPropertyWebkitLineAlign:
3874 return CSSPrimitiveValue::create(style.lineAlign());
3875 case CSSPropertyWritingMode:
3876 return cssValuePool.createValue(style.writingMode());
3877 case CSSPropertyWebkitTextCombine:
3878 return cssValuePool.createValue(style.textCombine());
3879 case CSSPropertyWebkitTextOrientation:
3880 return CSSPrimitiveValue::create(style.textOrientation());
3881 case CSSPropertyWebkitLineBoxContain:
3882 return createLineBoxContainValue(style.lineBoxContain());
3883 case CSSPropertyAlt:
3884 return altTextToCSSValue(style);
3885 case CSSPropertyContent:
3886 return contentToCSSValue(style);
3887 case CSSPropertyCounterIncrement:
3888 return counterToCSSValue(style, propertyID);
3889 case CSSPropertyCounterReset:
3890 return counterToCSSValue(style, propertyID);
3891 case CSSPropertyWebkitClipPath: {
3892 auto* operation = style.clipPath();
3893 if (!operation)
3894 return cssValuePool.createIdentifierValue(CSSValueNone);
3895 if (is<ReferenceClipPathOperation>(*operation))
3896 return CSSPrimitiveValue::create(downcast<ReferenceClipPathOperation>(*operation).url(), CSSPrimitiveValue::CSS_URI);
3897 auto list = CSSValueList::createSpaceSeparated();
3898 if (is<ShapeClipPathOperation>(*operation)) {
3899 auto& shapeOperation = downcast<ShapeClipPathOperation>(*operation);
3900 list->append(valueForBasicShape(style, shapeOperation.basicShape()));
3901 if (shapeOperation.referenceBox() != CSSBoxType::BoxMissing)
3902 list->append(cssValuePool.createValue(shapeOperation.referenceBox()));
3903 }
3904 if (is<BoxClipPathOperation>(*operation))
3905 list->append(cssValuePool.createValue(downcast<BoxClipPathOperation>(*operation).referenceBox()));
3906 return list;
3907 }
3908 case CSSPropertyShapeMargin:
3909 return cssValuePool.createValue(style.shapeMargin(), style);
3910 case CSSPropertyShapeImageThreshold:
3911 return cssValuePool.createValue(style.shapeImageThreshold(), CSSPrimitiveValue::CSS_NUMBER);
3912 case CSSPropertyShapeOutside:
3913 return shapePropertyValue(style, style.shapeOutside());
3914 case CSSPropertyFilter:
3915 return valueForFilter(style, style.filter());
3916 case CSSPropertyAppleColorFilter:
3917 return valueForFilter(style, style.appleColorFilter());
3918#if ENABLE(FILTERS_LEVEL_2)
3919 case CSSPropertyWebkitBackdropFilter:
3920 return valueForFilter(style, style.backdropFilter());
3921#endif
3922#if ENABLE(CSS_COMPOSITING)
3923 case CSSPropertyMixBlendMode:
3924 return cssValuePool.createValue(style.blendMode());
3925 case CSSPropertyIsolation:
3926 return cssValuePool.createValue(style.isolation());
3927#endif
3928 case CSSPropertyBackgroundBlendMode: {
3929 auto& layers = style.backgroundLayers();
3930 if (!layers.next())
3931 return cssValuePool.createValue(layers.blendMode());
3932 auto list = CSSValueList::createCommaSeparated();
3933 for (auto* currLayer = &layers; currLayer; currLayer = currLayer->next())
3934 list->append(cssValuePool.createValue(currLayer->blendMode()));
3935 return list;
3936 }
3937 case CSSPropertyBackground:
3938 return getBackgroundShorthandValue();
3939 case CSSPropertyBorder: {
3940 auto value = propertyValue(CSSPropertyBorderTop, DoNotUpdateLayout);
3941 const CSSPropertyID properties[3] = { CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft };
3942 for (auto& property : properties) {
3943 if (!compareCSSValuePtr<CSSValue>(value, propertyValue(property, DoNotUpdateLayout)))
3944 return nullptr;
3945 }
3946 return value;
3947 }
3948 case CSSPropertyBorderBlock: {
3949 auto value = propertyValue(CSSPropertyBorderBlockStart, DoNotUpdateLayout);
3950 if (!compareCSSValuePtr<CSSValue>(value, propertyValue(CSSPropertyBorderBlockEnd, DoNotUpdateLayout)))
3951 return nullptr;
3952 return value;
3953 }
3954 case CSSPropertyBorderBlockColor:
3955 return getCSSPropertyValuesFor2SidesShorthand(borderBlockColorShorthand());
3956 case CSSPropertyBorderBlockStyle:
3957 return getCSSPropertyValuesFor2SidesShorthand(borderBlockStyleShorthand());
3958 case CSSPropertyBorderBlockWidth:
3959 return getCSSPropertyValuesFor2SidesShorthand(borderBlockWidthShorthand());
3960 case CSSPropertyBorderBottom:
3961 return getCSSPropertyValuesForShorthandProperties(borderBottomShorthand());
3962 case CSSPropertyBorderColor:
3963 return getCSSPropertyValuesFor4SidesShorthand(borderColorShorthand());
3964 case CSSPropertyBorderLeft:
3965 return getCSSPropertyValuesForShorthandProperties(borderLeftShorthand());
3966 case CSSPropertyBorderImage:
3967 return valueForNinePieceImage(style.borderImage());
3968 case CSSPropertyBorderInline: {
3969 auto value = propertyValue(CSSPropertyBorderInlineStart, DoNotUpdateLayout);
3970 if (!compareCSSValuePtr<CSSValue>(value, propertyValue(CSSPropertyBorderInlineEnd, DoNotUpdateLayout)))
3971 return nullptr;
3972 return value;
3973 }
3974 case CSSPropertyBorderInlineColor:
3975 return getCSSPropertyValuesFor2SidesShorthand(borderInlineColorShorthand());
3976 case CSSPropertyBorderInlineStyle:
3977 return getCSSPropertyValuesFor2SidesShorthand(borderInlineStyleShorthand());
3978 case CSSPropertyBorderInlineWidth:
3979 return getCSSPropertyValuesFor2SidesShorthand(borderInlineWidthShorthand());
3980 case CSSPropertyBorderRadius:
3981 return borderRadiusShorthandValue(style);
3982 case CSSPropertyBorderRight:
3983 return getCSSPropertyValuesForShorthandProperties(borderRightShorthand());
3984 case CSSPropertyBorderStyle:
3985 return getCSSPropertyValuesFor4SidesShorthand(borderStyleShorthand());
3986 case CSSPropertyBorderTop:
3987 return getCSSPropertyValuesForShorthandProperties(borderTopShorthand());
3988 case CSSPropertyBorderWidth:
3989 return getCSSPropertyValuesFor4SidesShorthand(borderWidthShorthand());
3990 case CSSPropertyColumnRule:
3991 return getCSSPropertyValuesForShorthandProperties(columnRuleShorthand());
3992 case CSSPropertyColumns:
3993 return getCSSPropertyValuesForShorthandProperties(columnsShorthand());
3994 case CSSPropertyInset:
3995 return getCSSPropertyValuesFor4SidesShorthand(insetShorthand());
3996 case CSSPropertyInsetBlock:
3997 return getCSSPropertyValuesFor2SidesShorthand(insetBlockShorthand());
3998 case CSSPropertyInsetInline:
3999 return getCSSPropertyValuesFor2SidesShorthand(insetInlineShorthand());
4000 case CSSPropertyListStyle:
4001 return getCSSPropertyValuesForShorthandProperties(listStyleShorthand());
4002 case CSSPropertyMargin:
4003 return getCSSPropertyValuesFor4SidesShorthand(marginShorthand());
4004 case CSSPropertyMarginBlock:
4005 return getCSSPropertyValuesFor2SidesShorthand(marginBlockShorthand());
4006 case CSSPropertyMarginInline:
4007 return getCSSPropertyValuesFor2SidesShorthand(marginInlineShorthand());
4008 case CSSPropertyOutline:
4009 return getCSSPropertyValuesForShorthandProperties(outlineShorthand());
4010 case CSSPropertyPadding:
4011 return getCSSPropertyValuesFor4SidesShorthand(paddingShorthand());
4012 case CSSPropertyPaddingBlock:
4013 return getCSSPropertyValuesFor2SidesShorthand(paddingBlockShorthand());
4014 case CSSPropertyPaddingInline:
4015 return getCSSPropertyValuesFor2SidesShorthand(paddingInlineShorthand());
4016#if ENABLE(CSS_SCROLL_SNAP)
4017 case CSSPropertyScrollSnapMargin:
4018 return getCSSPropertyValuesFor4SidesShorthand(scrollSnapMarginShorthand());
4019 case CSSPropertyScrollSnapMarginBottom:
4020 return zoomAdjustedPixelValueForLength(style.scrollSnapMarginBottom(), style);
4021 case CSSPropertyScrollSnapMarginTop:
4022 return zoomAdjustedPixelValueForLength(style.scrollSnapMarginTop(), style);
4023 case CSSPropertyScrollSnapMarginRight:
4024 return zoomAdjustedPixelValueForLength(style.scrollSnapMarginRight(), style);
4025 case CSSPropertyScrollSnapMarginLeft:
4026 return zoomAdjustedPixelValueForLength(style.scrollSnapMarginLeft(), style);
4027 case CSSPropertyScrollPadding:
4028 return getCSSPropertyValuesFor4SidesShorthand(scrollPaddingShorthand());
4029 case CSSPropertyScrollPaddingBottom:
4030 return zoomAdjustedPixelValueForLength(style.scrollPaddingBottom(), style);
4031 case CSSPropertyScrollPaddingTop:
4032 return zoomAdjustedPixelValueForLength(style.scrollPaddingTop(), style);
4033 case CSSPropertyScrollPaddingRight:
4034 return zoomAdjustedPixelValueForLength(style.scrollPaddingRight(), style);
4035 case CSSPropertyScrollPaddingLeft:
4036 return zoomAdjustedPixelValueForLength(style.scrollPaddingLeft(), style);
4037 case CSSPropertyScrollSnapType:
4038 return valueForScrollSnapType(style.scrollSnapType());
4039 case CSSPropertyScrollSnapAlign:
4040 return valueForScrollSnapAlignment(style.scrollSnapAlign());
4041#endif
4042
4043#if ENABLE(CSS_TRAILING_WORD)
4044 case CSSPropertyAppleTrailingWord:
4045 return cssValuePool.createValue(style.trailingWord());
4046#endif
4047
4048#if ENABLE(APPLE_PAY)
4049 case CSSPropertyApplePayButtonStyle:
4050 return cssValuePool.createValue(style.applePayButtonStyle());
4051 case CSSPropertyApplePayButtonType:
4052 return cssValuePool.createValue(style.applePayButtonType());
4053#endif
4054
4055#if ENABLE(DARK_MODE_CSS)
4056 case CSSPropertyColorScheme: {
4057 if (!RuntimeEnabledFeatures::sharedFeatures().darkModeCSSEnabled())
4058 return nullptr;
4059
4060 auto colorScheme = style.colorScheme();
4061 if (colorScheme.isAuto())
4062 return cssValuePool.createIdentifierValue(CSSValueAuto);
4063
4064 auto list = CSSValueList::createSpaceSeparated();
4065 if (colorScheme.contains(ColorScheme::Light))
4066 list->append(cssValuePool.createIdentifierValue(CSSValueLight));
4067 if (colorScheme.contains(ColorScheme::Dark))
4068 list->append(cssValuePool.createIdentifierValue(CSSValueDark));
4069 if (!colorScheme.allowsTransformations())
4070 list->append(cssValuePool.createIdentifierValue(CSSValueOnly));
4071 ASSERT(list->length());
4072 return list;
4073 }
4074#endif
4075
4076 /* Individual properties not part of the spec */
4077 case CSSPropertyBackgroundRepeatX:
4078 case CSSPropertyBackgroundRepeatY:
4079 break;
4080
4081 // Length properties for SVG.
4082 case CSSPropertyCx:
4083 return zoomAdjustedPixelValueForLength(style.svgStyle().cx(), style);
4084 case CSSPropertyCy:
4085 return zoomAdjustedPixelValueForLength(style.svgStyle().cy(), style);
4086 case CSSPropertyR:
4087 return zoomAdjustedPixelValueForLength(style.svgStyle().r(), style);
4088 case CSSPropertyRx:
4089 return zoomAdjustedPixelValueForLength(style.svgStyle().rx(), style);
4090 case CSSPropertyRy:
4091 return zoomAdjustedPixelValueForLength(style.svgStyle().ry(), style);
4092 case CSSPropertyStrokeDashoffset:
4093 return zoomAdjustedPixelValueForLength(style.svgStyle().strokeDashOffset(), style);
4094 case CSSPropertyX:
4095 return zoomAdjustedPixelValueForLength(style.svgStyle().x(), style);
4096 case CSSPropertyY:
4097 return zoomAdjustedPixelValueForLength(style.svgStyle().y(), style);
4098 case CSSPropertyWebkitTextZoom:
4099 return cssValuePool.createValue(style.textZoom());
4100
4101 case CSSPropertyPaintOrder:
4102 return paintOrder(style.paintOrder());
4103 case CSSPropertyStrokeLinecap:
4104 return CSSPrimitiveValue::create(style.capStyle());
4105 case CSSPropertyStrokeLinejoin:
4106 return CSSPrimitiveValue::create(style.joinStyle());
4107 case CSSPropertyStrokeWidth:
4108 return zoomAdjustedPixelValueForLength(style.strokeWidth(), style);
4109 case CSSPropertyStrokeColor:
4110 return currentColorOrValidColor(&style, style.strokeColor());
4111 case CSSPropertyStrokeMiterlimit:
4112 return CSSPrimitiveValue::create(style.strokeMiterLimit(), CSSPrimitiveValue::CSS_NUMBER);
4113
4114 /* Unimplemented CSS 3 properties (including CSS3 shorthand properties) */
4115 case CSSPropertyAll:
4116 case CSSPropertyAnimation:
4117 case CSSPropertyWebkitTextEmphasis:
4118 break;
4119
4120 /* Directional properties are resolved by resolveDirectionAwareProperty() before the switch. */
4121 case CSSPropertyBorderBlockEnd:
4122 case CSSPropertyBorderBlockEndColor:
4123 case CSSPropertyBorderBlockEndStyle:
4124 case CSSPropertyBorderBlockEndWidth:
4125 case CSSPropertyBorderBlockStart:
4126 case CSSPropertyBorderBlockStartColor:
4127 case CSSPropertyBorderBlockStartStyle:
4128 case CSSPropertyBorderBlockStartWidth:
4129 case CSSPropertyBorderInlineEnd:
4130 case CSSPropertyBorderInlineEndColor:
4131 case CSSPropertyBorderInlineEndStyle:
4132 case CSSPropertyBorderInlineEndWidth:
4133 case CSSPropertyBorderInlineStart:
4134 case CSSPropertyBorderInlineStartColor:
4135 case CSSPropertyBorderInlineStartStyle:
4136 case CSSPropertyBorderInlineStartWidth:
4137 case CSSPropertyInsetBlockEnd:
4138 case CSSPropertyInsetBlockStart:
4139 case CSSPropertyInsetInlineEnd:
4140 case CSSPropertyInsetInlineStart:
4141 case CSSPropertyMarginBlockEnd:
4142 case CSSPropertyMarginBlockStart:
4143 case CSSPropertyMarginInlineEnd:
4144 case CSSPropertyMarginInlineStart:
4145 case CSSPropertyPaddingBlockEnd:
4146 case CSSPropertyPaddingBlockStart:
4147 case CSSPropertyPaddingInlineEnd:
4148 case CSSPropertyPaddingInlineStart:
4149 case CSSPropertyBlockSize:
4150 case CSSPropertyInlineSize:
4151 case CSSPropertyMaxBlockSize:
4152 case CSSPropertyMaxInlineSize:
4153 case CSSPropertyMinBlockSize:
4154 case CSSPropertyMinInlineSize:
4155 ASSERT_NOT_REACHED();
4156 break;
4157
4158 /* Unimplemented @font-face properties */
4159 case CSSPropertySrc:
4160 case CSSPropertyUnicodeRange:
4161 case CSSPropertyFontDisplay:
4162 break;
4163
4164 /* Other unimplemented properties */
4165 case CSSPropertyPage: // for @page
4166 case CSSPropertyQuotes: // FIXME: needs implementation
4167 case CSSPropertySize: // for @page
4168 break;
4169
4170 /* Unimplemented -webkit- properties */
4171 case CSSPropertyWebkitBorderRadius:
4172 case CSSPropertyWebkitMarginCollapse:
4173 case CSSPropertyWebkitMarquee:
4174 case CSSPropertyWebkitMarqueeSpeed:
4175 case CSSPropertyWebkitMask:
4176 case CSSPropertyWebkitMaskRepeatX:
4177 case CSSPropertyWebkitMaskRepeatY:
4178 case CSSPropertyPerspectiveOriginX:
4179 case CSSPropertyPerspectiveOriginY:
4180 case CSSPropertyWebkitTextStroke:
4181 case CSSPropertyTransformOriginX:
4182 case CSSPropertyTransformOriginY:
4183 case CSSPropertyTransformOriginZ:
4184 break;
4185
4186#if ENABLE(CSS_DEVICE_ADAPTATION)
4187 case CSSPropertyMaxZoom:
4188 case CSSPropertyMinZoom:
4189 case CSSPropertyOrientation:
4190 case CSSPropertyUserZoom:
4191 break;
4192#endif
4193
4194 case CSSPropertyBufferedRendering:
4195 case CSSPropertyClipPath:
4196 case CSSPropertyClipRule:
4197 case CSSPropertyMask:
4198 case CSSPropertyEnableBackground:
4199 case CSSPropertyFloodColor:
4200 case CSSPropertyFloodOpacity:
4201 case CSSPropertyLightingColor:
4202 case CSSPropertyStopColor:
4203 case CSSPropertyStopOpacity:
4204 case CSSPropertyColorInterpolation:
4205 case CSSPropertyColorInterpolationFilters:
4206 case CSSPropertyColorProfile:
4207 case CSSPropertyColorRendering:
4208 case CSSPropertyFill:
4209 case CSSPropertyFillOpacity:
4210 case CSSPropertyFillRule:
4211 case CSSPropertyMarker:
4212 case CSSPropertyMarkerEnd:
4213 case CSSPropertyMarkerMid:
4214 case CSSPropertyMarkerStart:
4215 case CSSPropertyMaskType:
4216 case CSSPropertyShapeRendering:
4217 case CSSPropertyStroke:
4218 case CSSPropertyStrokeDasharray:
4219 case CSSPropertyStrokeOpacity:
4220 case CSSPropertyAlignmentBaseline:
4221 case CSSPropertyBaselineShift:
4222 case CSSPropertyDominantBaseline:
4223 case CSSPropertyGlyphOrientationHorizontal:
4224 case CSSPropertyGlyphOrientationVertical:
4225 case CSSPropertyKerning:
4226 case CSSPropertyTextAnchor:
4227 case CSSPropertyVectorEffect:
4228 return svgPropertyValue(propertyID, DoNotUpdateLayout);
4229 case CSSPropertyCustom:
4230 ASSERT_NOT_REACHED();
4231 return nullptr;
4232 }
4233
4234 logUnimplementedPropertyID(propertyID);
4235 return nullptr;
4236}
4237
4238String CSSComputedStyleDeclaration::getPropertyValue(CSSPropertyID propertyID) const
4239{
4240 auto value = getPropertyCSSValue(propertyID);
4241 if (!value)
4242 return emptyString(); // FIXME: Should this be null instead, as it is in StyleProperties::getPropertyValue?
4243 return value->cssText();
4244}
4245
4246unsigned CSSComputedStyleDeclaration::length() const
4247{
4248 updateStyleIfNeededForProperty(m_element.get(), CSSPropertyCustom);
4249
4250 auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
4251 if (!style)
4252 return 0;
4253
4254 return numComputedProperties + style->inheritedCustomProperties().size() + style->nonInheritedCustomProperties().size();
4255}
4256
4257String CSSComputedStyleDeclaration::item(unsigned i) const
4258{
4259 if (i >= length())
4260 return String();
4261
4262 if (i < numComputedProperties)
4263 return getPropertyNameString(computedProperties[i]);
4264
4265 auto* style = m_element->computedStyle(m_pseudoElementSpecifier);
4266 if (!style)
4267 return String();
4268
4269 const auto& inheritedCustomProperties = style->inheritedCustomProperties();
4270
4271 if (i < numComputedProperties + inheritedCustomProperties.size()) {
4272 auto results = copyToVector(inheritedCustomProperties.keys());
4273 return results.at(i - numComputedProperties);
4274 }
4275
4276 const auto& nonInheritedCustomProperties = style->nonInheritedCustomProperties();
4277 auto results = copyToVector(nonInheritedCustomProperties.keys());
4278 return results.at(i - inheritedCustomProperties.size() - numComputedProperties);
4279}
4280
4281bool ComputedStyleExtractor::propertyMatches(CSSPropertyID propertyID, const CSSValue* value)
4282{
4283 if (!m_element)
4284 return false;
4285 if (propertyID == CSSPropertyFontSize && is<CSSPrimitiveValue>(*value)) {
4286 m_element->document().updateLayoutIgnorePendingStylesheets();
4287 if (auto* style = m_element->computedStyle(m_pseudoElementSpecifier)) {
4288 if (CSSValueID sizeIdentifier = style->fontDescription().keywordSizeAsIdentifier()) {
4289 auto& primitiveValue = downcast<CSSPrimitiveValue>(*value);
4290 if (primitiveValue.isValueID() && primitiveValue.valueID() == sizeIdentifier)
4291 return true;
4292 }
4293 }
4294 }
4295 RefPtr<CSSValue> computedValue = propertyValue(propertyID);
4296 return computedValue && value && computedValue->equals(*value);
4297}
4298
4299Ref<MutableStyleProperties> ComputedStyleExtractor::copyProperties()
4300{
4301 return copyPropertiesInSet(computedProperties, numComputedProperties);
4302}
4303
4304Ref<CSSValueList> ComputedStyleExtractor::getCSSPropertyValuesForShorthandProperties(const StylePropertyShorthand& shorthand)
4305{
4306 auto list = CSSValueList::createSpaceSeparated();
4307 for (size_t i = 0; i < shorthand.length(); ++i)
4308 list->append(propertyValue(shorthand.properties()[i], DoNotUpdateLayout).releaseNonNull());
4309 return list;
4310}
4311
4312RefPtr<CSSValueList> ComputedStyleExtractor::getCSSPropertyValuesFor2SidesShorthand(const StylePropertyShorthand& shorthand)
4313{
4314 auto list = CSSValueList::createSpaceSeparated();
4315
4316 // Assume the properties are in the usual order start, end.
4317 auto startValue = propertyValue(shorthand.properties()[0], DoNotUpdateLayout);
4318 auto endValue = propertyValue(shorthand.properties()[1], DoNotUpdateLayout);
4319
4320 // All 2 properties must be specified.
4321 if (!startValue || !endValue)
4322 return nullptr;
4323
4324 bool showEnd = !compareCSSValuePtr(startValue, endValue);
4325
4326 list->append(startValue.releaseNonNull());
4327 if (showEnd)
4328 list->append(endValue.releaseNonNull());
4329
4330 return list;
4331}
4332
4333RefPtr<CSSValueList> ComputedStyleExtractor::getCSSPropertyValuesFor4SidesShorthand(const StylePropertyShorthand& shorthand)
4334{
4335 auto list = CSSValueList::createSpaceSeparated();
4336
4337 // Assume the properties are in the usual order top, right, bottom, left.
4338 auto topValue = propertyValue(shorthand.properties()[0], DoNotUpdateLayout);
4339 auto rightValue = propertyValue(shorthand.properties()[1], DoNotUpdateLayout);
4340 auto bottomValue = propertyValue(shorthand.properties()[2], DoNotUpdateLayout);
4341 auto leftValue = propertyValue(shorthand.properties()[3], DoNotUpdateLayout);
4342
4343 // All 4 properties must be specified.
4344 if (!topValue || !rightValue || !bottomValue || !leftValue)
4345 return nullptr;
4346
4347 bool showLeft = !compareCSSValuePtr(rightValue, leftValue);
4348 bool showBottom = !compareCSSValuePtr(topValue, bottomValue) || showLeft;
4349 bool showRight = !compareCSSValuePtr(topValue, rightValue) || showBottom;
4350
4351 list->append(topValue.releaseNonNull());
4352 if (showRight)
4353 list->append(rightValue.releaseNonNull());
4354 if (showBottom)
4355 list->append(bottomValue.releaseNonNull());
4356 if (showLeft)
4357 list->append(leftValue.releaseNonNull());
4358
4359 return list;
4360}
4361
4362Ref<CSSValueList> ComputedStyleExtractor::getCSSPropertyValuesForGridShorthand(const StylePropertyShorthand& shorthand)
4363{
4364 auto list = CSSValueList::createSlashSeparated();
4365 for (size_t i = 0; i < shorthand.length(); ++i)
4366 list->append(propertyValue(shorthand.properties()[i], DoNotUpdateLayout).releaseNonNull());
4367 return list;
4368}
4369
4370Ref<MutableStyleProperties> ComputedStyleExtractor::copyPropertiesInSet(const CSSPropertyID* set, unsigned length)
4371{
4372 Vector<CSSProperty, 256> list;
4373 list.reserveInitialCapacity(length);
4374 for (unsigned i = 0; i < length; ++i) {
4375 if (auto value = propertyValue(set[i]))
4376 list.append(CSSProperty(set[i], WTFMove(value), false));
4377 }
4378 return MutableStyleProperties::create(list.data(), list.size());
4379}
4380
4381CSSRule* CSSComputedStyleDeclaration::parentRule() const
4382{
4383 return nullptr;
4384}
4385
4386RefPtr<DeprecatedCSSOMValue> CSSComputedStyleDeclaration::getPropertyCSSValue(const String& propertyName)
4387{
4388 if (isCustomPropertyName(propertyName)) {
4389 auto value = ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).customPropertyValue(propertyName);
4390 if (!value)
4391 return nullptr;
4392 return value->createDeprecatedCSSOMWrapper(*this);
4393 }
4394
4395 CSSPropertyID propertyID = cssPropertyID(propertyName);
4396 if (!propertyID)
4397 return nullptr;
4398 auto value = getPropertyCSSValue(propertyID);
4399 if (!value)
4400 return nullptr;
4401 return value->createDeprecatedCSSOMWrapper(*this);
4402}
4403
4404String CSSComputedStyleDeclaration::getPropertyValue(const String &propertyName)
4405{
4406 if (isCustomPropertyName(propertyName))
4407 return ComputedStyleExtractor(m_element.ptr(), m_allowVisitedStyle, m_pseudoElementSpecifier).customPropertyText(propertyName);
4408
4409 CSSPropertyID propertyID = cssPropertyID(propertyName);
4410 if (!propertyID)
4411 return String();
4412 return getPropertyValue(propertyID);
4413}
4414
4415String CSSComputedStyleDeclaration::getPropertyPriority(const String&)
4416{
4417 // All computed styles have a priority of not "important".
4418 return emptyString(); // FIXME: Should this sometimes be null instead of empty, to match a normal style declaration?
4419}
4420
4421String CSSComputedStyleDeclaration::getPropertyShorthand(const String&)
4422{
4423 return emptyString(); // FIXME: Should this sometimes be null instead of empty, to match a normal style declaration?
4424}
4425
4426bool CSSComputedStyleDeclaration::isPropertyImplicit(const String&)
4427{
4428 return false;
4429}
4430
4431ExceptionOr<void> CSSComputedStyleDeclaration::setProperty(const String&, const String&, const String&)
4432{
4433 return Exception { NoModificationAllowedError };
4434}
4435
4436ExceptionOr<String> CSSComputedStyleDeclaration::removeProperty(const String&)
4437{
4438 return Exception { NoModificationAllowedError };
4439}
4440
4441RefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValueInternal(CSSPropertyID propertyID)
4442{
4443 return getPropertyCSSValue(propertyID);
4444}
4445
4446String CSSComputedStyleDeclaration::getPropertyValueInternal(CSSPropertyID propertyID)
4447{
4448 return getPropertyValue(propertyID);
4449}
4450
4451ExceptionOr<bool> CSSComputedStyleDeclaration::setPropertyInternal(CSSPropertyID, const String&, bool)
4452{
4453 return Exception { NoModificationAllowedError };
4454}
4455
4456Ref<CSSValueList> ComputedStyleExtractor::getBackgroundShorthandValue()
4457{
4458 static const CSSPropertyID propertiesBeforeSlashSeperator[5] = { CSSPropertyBackgroundColor, CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat, CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition };
4459 static const CSSPropertyID propertiesAfterSlashSeperator[3] = { CSSPropertyBackgroundSize, CSSPropertyBackgroundOrigin, CSSPropertyBackgroundClip };
4460
4461 auto list = CSSValueList::createSlashSeparated();
4462 list->append(getCSSPropertyValuesForShorthandProperties(StylePropertyShorthand(CSSPropertyBackground, propertiesBeforeSlashSeperator)));
4463 list->append(getCSSPropertyValuesForShorthandProperties(StylePropertyShorthand(CSSPropertyBackground, propertiesAfterSlashSeperator)));
4464 return list;
4465}
4466
4467} // namespace WebCore
4468