source: webkit/trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp

Last change on this file was 295200, checked in by Antti Koivisto, 3 years ago

Re-evaluate queries after subframe size changes
https://bugs.webkit.org/show_bug.cgi?id=241225

Reviewed by Alan Bujtas.

Container queries in frames don't react to frame size changes.

  • LayoutTests/TestExpectations:

Mark imported/w3c/web-platform-tests/css/css-contain/container-queries/inline-size-bfc-floats.html as failure, it has ever
been passing by fluke (there are some containment issues with floats).

  • LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/iframe-in-container-invalidation-expected.txt:
  • LayoutTests/imported/w3c/web-platform-tests/css/css-contain/container-queries/iframe-invalidation-expected.txt:
  • Source/WebCore/css/CSSComputedStyleDeclaration.cpp:

(WebCore::ComputedStyleExtractor::propertyValue):

Ensure we update layout when there are container queries in a subframe, similar to media queries.

  • Source/WebCore/dom/Document.cpp:

(WebCore::Document::resolveStyle):
(WebCore::Document::updateLayout):

  • Source/WebCore/page/FrameView.cpp:

(WebCore::FrameView::updateContentsSize):
(WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive):

  • Source/WebCore/page/FrameViewLayoutContext.cpp:

(WebCore::FrameViewLayoutContext::layout):

Move the container query invalidation loop to the main layout function so all paths are covered.

(WebCore::FrameViewLayoutContext::performLayout):

  • Source/WebCore/page/FrameViewLayoutContext.h:
  • Source/WebCore/style/StyleScopeRuleSets.cpp:

(WebCore::Style::ScopeRuleSets::hasContainerQueries const):

  • Source/WebCore/style/StyleScopeRuleSets.h:

Canonical link: https://commits.webkit.org/251257@main

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