[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / css / StyleBuilderCustom.h
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #pragma once
28
29 #include "CSSAspectRatioValue.h"
30 #include "CSSCursorImageValue.h"
31 #include "CSSFontFamily.h"
32 #include "CSSFontValue.h"
33 #include "CSSGradientValue.h"
34 #include "CSSGridTemplateAreasValue.h"
35 #include "CSSRegisteredCustomProperty.h"
36 #include "CSSShadowValue.h"
37 #include "Counter.h"
38 #include "CounterContent.h"
39 #include "CursorList.h"
40 #include "ElementAncestorIterator.h"
41 #include "FontVariantBuilder.h"
42 #include "Frame.h"
43 #include "HTMLElement.h"
44 #include "Rect.h"
45 #include "SVGElement.h"
46 #include "SVGRenderStyle.h"
47 #include "StyleBuilderConverter.h"
48 #include "StyleCachedImage.h"
49 #include "StyleFontSizeFunctions.h"
50 #include "StyleGeneratedImage.h"
51 #include "StyleResolver.h"
52 #include "WillChangeData.h"
53
54 namespace WebCore {
55
56 #define DECLARE_PROPERTY_CUSTOM_HANDLERS(property) \
57     static void applyInherit##property(StyleResolver&); \
58     static void applyInitial##property(StyleResolver&); \
59     static void applyValue##property(StyleResolver&, CSSValue&)
60
61 template<typename T> inline T forwardInheritedValue(T&& value) { return std::forward<T>(value); }
62 inline Length forwardInheritedValue(const Length& value) { auto copy = value; return copy; }
63 inline LengthSize forwardInheritedValue(const LengthSize& value) { auto copy = value; return copy; }
64 inline LengthBox forwardInheritedValue(const LengthBox& value) { auto copy = value; return copy; }
65 inline GapLength forwardInheritedValue(const GapLength& value) { auto copy = value; return copy; }
66
67 // Note that we assume the CSS parser only allows valid CSSValue types.
68 class StyleBuilderCustom {
69 public:
70     // Custom handling of inherit, initial and value setting.
71     DECLARE_PROPERTY_CUSTOM_HANDLERS(BorderImageOutset);
72     DECLARE_PROPERTY_CUSTOM_HANDLERS(BorderImageRepeat);
73     DECLARE_PROPERTY_CUSTOM_HANDLERS(BorderImageSlice);
74     DECLARE_PROPERTY_CUSTOM_HANDLERS(BorderImageWidth);
75     DECLARE_PROPERTY_CUSTOM_HANDLERS(BoxShadow);
76     DECLARE_PROPERTY_CUSTOM_HANDLERS(Clip);
77     DECLARE_PROPERTY_CUSTOM_HANDLERS(Content);
78     DECLARE_PROPERTY_CUSTOM_HANDLERS(CounterIncrement);
79     DECLARE_PROPERTY_CUSTOM_HANDLERS(CounterReset);
80     DECLARE_PROPERTY_CUSTOM_HANDLERS(Cursor);
81     DECLARE_PROPERTY_CUSTOM_HANDLERS(Fill);
82     DECLARE_PROPERTY_CUSTOM_HANDLERS(FontFamily);
83     DECLARE_PROPERTY_CUSTOM_HANDLERS(FontSize);
84     DECLARE_PROPERTY_CUSTOM_HANDLERS(FontStyle);
85 #if ENABLE(CSS_IMAGE_RESOLUTION)
86     DECLARE_PROPERTY_CUSTOM_HANDLERS(ImageResolution);
87 #endif
88 #if ENABLE(TEXT_AUTOSIZING)
89     DECLARE_PROPERTY_CUSTOM_HANDLERS(LineHeight);
90 #endif
91     DECLARE_PROPERTY_CUSTOM_HANDLERS(OutlineStyle);
92     DECLARE_PROPERTY_CUSTOM_HANDLERS(Size);
93     DECLARE_PROPERTY_CUSTOM_HANDLERS(Stroke);
94     DECLARE_PROPERTY_CUSTOM_HANDLERS(TextIndent);
95     DECLARE_PROPERTY_CUSTOM_HANDLERS(TextShadow);
96     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitAspectRatio);
97     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitBoxShadow);
98     DECLARE_PROPERTY_CUSTOM_HANDLERS(FontVariantLigatures);
99     DECLARE_PROPERTY_CUSTOM_HANDLERS(FontVariantNumeric);
100     DECLARE_PROPERTY_CUSTOM_HANDLERS(FontVariantEastAsian);
101     DECLARE_PROPERTY_CUSTOM_HANDLERS(GridTemplateAreas);
102     DECLARE_PROPERTY_CUSTOM_HANDLERS(GridTemplateColumns);
103     DECLARE_PROPERTY_CUSTOM_HANDLERS(GridTemplateRows);
104     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitMaskBoxImageOutset);
105     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitMaskBoxImageRepeat);
106     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitMaskBoxImageSlice);
107     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitMaskBoxImageWidth);
108     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitTextEmphasisStyle);
109     DECLARE_PROPERTY_CUSTOM_HANDLERS(Zoom);
110
111     // Custom handling of initial + inherit value setting only.
112     static void applyInitialWebkitMaskImage(StyleResolver&) { }
113     static void applyInheritWebkitMaskImage(StyleResolver&) { }
114     static void applyInitialFontFeatureSettings(StyleResolver&) { }
115     static void applyInheritFontFeatureSettings(StyleResolver&) { }
116 #if ENABLE(VARIATION_FONTS)
117     static void applyInitialFontVariationSettings(StyleResolver&) { }
118     static void applyInheritFontVariationSettings(StyleResolver&) { }
119 #endif
120
121     // Custom handling of inherit + value setting only.
122     static void applyInheritDisplay(StyleResolver&);
123     static void applyValueDisplay(StyleResolver&, CSSValue&);
124
125     // Custom handling of value setting only.
126     static void applyValueBaselineShift(StyleResolver&, CSSValue&);
127     static void applyValueDirection(StyleResolver&, CSSValue&);
128     static void applyValueVerticalAlign(StyleResolver&, CSSValue&);
129     static void applyInitialTextAlign(StyleResolver&);
130     static void applyValueTextAlign(StyleResolver&, CSSValue&);
131     static void applyValueWebkitLocale(StyleResolver&, CSSValue&);
132     static void applyValueWebkitTextOrientation(StyleResolver&, CSSValue&);
133 #if ENABLE(TEXT_AUTOSIZING)
134     static void applyValueWebkitTextSizeAdjust(StyleResolver&, CSSValue&);
135 #endif
136     static void applyValueWebkitTextZoom(StyleResolver&, CSSValue&);
137     static void applyValueWritingMode(StyleResolver&, CSSValue&);
138     static void applyValueAlt(StyleResolver&, CSSValue&);
139     static void applyValueWillChange(StyleResolver&, CSSValue&);
140
141 #if ENABLE(DARK_MODE_CSS)
142     static void applyValueColorScheme(StyleResolver&, CSSValue&);
143 #endif
144
145     static void applyValueStrokeWidth(StyleResolver&, CSSValue&);
146     static void applyValueStrokeColor(StyleResolver&, CSSValue&);
147
148     static void applyInitialCustomProperty(StyleResolver&, const CSSRegisteredCustomProperty*, const AtomString& name);
149     static void applyInheritCustomProperty(StyleResolver&, const CSSRegisteredCustomProperty*, const AtomString& name);
150     static void applyValueCustomProperty(StyleResolver&, const CSSRegisteredCustomProperty*, CSSCustomPropertyValue&);
151
152 private:
153     static void resetEffectiveZoom(StyleResolver&);
154
155     static Length mmLength(double mm);
156     static Length inchLength(double inch);
157     static bool getPageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height);
158
159     template <CSSPropertyID id>
160     static void applyTextOrBoxShadowValue(StyleResolver&, CSSValue&);
161     static bool isValidDisplayValue(StyleResolver&, DisplayType);
162
163     enum CounterBehavior {Increment = 0, Reset};
164     template <CounterBehavior counterBehavior>
165     static void applyInheritCounter(StyleResolver&);
166     template <CounterBehavior counterBehavior>
167     static void applyValueCounter(StyleResolver&, CSSValue&);
168
169     static float largerFontSize(float size);
170     static float smallerFontSize(float size);
171     static float determineRubyTextSizeMultiplier(StyleResolver&);
172 };
173
174 inline void StyleBuilderCustom::applyValueDirection(StyleResolver& styleResolver, CSSValue& value)
175 {
176     styleResolver.style()->setDirection(downcast<CSSPrimitiveValue>(value));
177     styleResolver.style()->setHasExplicitlySetDirection(true);
178 }
179
180 inline void StyleBuilderCustom::applyInitialTextAlign(StyleResolver& styleResolver)
181 {
182     styleResolver.style()->setTextAlign(RenderStyle::initialTextAlign());
183     styleResolver.style()->setHasExplicitlySetTextAlign(true);
184 }
185
186 inline void StyleBuilderCustom::applyValueTextAlign(StyleResolver& styleResolver, CSSValue& value)
187 {
188     styleResolver.style()->setTextAlign(StyleBuilderConverter::convertTextAlign(styleResolver, value));
189     styleResolver.style()->setHasExplicitlySetTextAlign(true);
190 }
191
192 inline void StyleBuilderCustom::resetEffectiveZoom(StyleResolver& styleResolver)
193 {
194     // Reset the zoom in effect. This allows the setZoom method to accurately compute a new zoom in effect.
195     styleResolver.setEffectiveZoom(styleResolver.parentStyle() ? styleResolver.parentStyle()->effectiveZoom() : RenderStyle::initialZoom());
196 }
197
198 inline void StyleBuilderCustom::applyInitialZoom(StyleResolver& styleResolver)
199 {
200     resetEffectiveZoom(styleResolver);
201     styleResolver.setZoom(RenderStyle::initialZoom());
202 }
203
204 inline void StyleBuilderCustom::applyInheritZoom(StyleResolver& styleResolver)
205 {
206     resetEffectiveZoom(styleResolver);
207     styleResolver.setZoom(styleResolver.parentStyle()->zoom());
208 }
209
210 inline void StyleBuilderCustom::applyValueZoom(StyleResolver& styleResolver, CSSValue& value)
211 {
212     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
213
214     if (primitiveValue.valueID() == CSSValueNormal) {
215         resetEffectiveZoom(styleResolver);
216         styleResolver.setZoom(RenderStyle::initialZoom());
217     } else if (primitiveValue.valueID() == CSSValueReset) {
218         styleResolver.setEffectiveZoom(RenderStyle::initialZoom());
219         styleResolver.setZoom(RenderStyle::initialZoom());
220     } else if (primitiveValue.valueID() == CSSValueDocument) {
221         float docZoom = styleResolver.rootElementStyle() ? styleResolver.rootElementStyle()->zoom() : RenderStyle::initialZoom();
222         styleResolver.setEffectiveZoom(docZoom);
223         styleResolver.setZoom(docZoom);
224     } else if (primitiveValue.isPercentage()) {
225         resetEffectiveZoom(styleResolver);
226         if (float percent = primitiveValue.floatValue())
227             styleResolver.setZoom(percent / 100.0f);
228     } else if (primitiveValue.isNumber()) {
229         resetEffectiveZoom(styleResolver);
230         if (float number = primitiveValue.floatValue())
231             styleResolver.setZoom(number);
232     }
233 }
234 inline Length StyleBuilderCustom::mmLength(double mm)
235 {
236     Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(mm, CSSPrimitiveValue::CSS_MM));
237     return value.get().computeLength<Length>(CSSToLengthConversionData());
238 }
239 inline Length StyleBuilderCustom::inchLength(double inch)
240 {
241     Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(inch, CSSPrimitiveValue::CSS_IN));
242     return value.get().computeLength<Length>(CSSToLengthConversionData());
243 }
244 bool StyleBuilderCustom::getPageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height)
245 {
246     static NeverDestroyed<Length> a5Width(mmLength(148));
247     static NeverDestroyed<Length> a5Height(mmLength(210));
248     static NeverDestroyed<Length> a4Width(mmLength(210));
249     static NeverDestroyed<Length> a4Height(mmLength(297));
250     static NeverDestroyed<Length> a3Width(mmLength(297));
251     static NeverDestroyed<Length> a3Height(mmLength(420));
252     static NeverDestroyed<Length> b5Width(mmLength(176));
253     static NeverDestroyed<Length> b5Height(mmLength(250));
254     static NeverDestroyed<Length> b4Width(mmLength(250));
255     static NeverDestroyed<Length> b4Height(mmLength(353));
256     static NeverDestroyed<Length> letterWidth(inchLength(8.5));
257     static NeverDestroyed<Length> letterHeight(inchLength(11));
258     static NeverDestroyed<Length> legalWidth(inchLength(8.5));
259     static NeverDestroyed<Length> legalHeight(inchLength(14));
260     static NeverDestroyed<Length> ledgerWidth(inchLength(11));
261     static NeverDestroyed<Length> ledgerHeight(inchLength(17));
262
263     if (!pageSizeName)
264         return false;
265
266     switch (pageSizeName->valueID()) {
267     case CSSValueA5:
268         width = a5Width;
269         height = a5Height;
270         break;
271     case CSSValueA4:
272         width = a4Width;
273         height = a4Height;
274         break;
275     case CSSValueA3:
276         width = a3Width;
277         height = a3Height;
278         break;
279     case CSSValueB5:
280         width = b5Width;
281         height = b5Height;
282         break;
283     case CSSValueB4:
284         width = b4Width;
285         height = b4Height;
286         break;
287     case CSSValueLetter:
288         width = letterWidth;
289         height = letterHeight;
290         break;
291     case CSSValueLegal:
292         width = legalWidth;
293         height = legalHeight;
294         break;
295     case CSSValueLedger:
296         width = ledgerWidth;
297         height = ledgerHeight;
298         break;
299     default:
300         return false;
301     }
302
303     if (pageOrientation) {
304         switch (pageOrientation->valueID()) {
305         case CSSValueLandscape:
306             std::swap(width, height);
307             break;
308         case CSSValuePortrait:
309             // Nothing to do.
310             break;
311         default:
312             return false;
313         }
314     }
315     return true;
316 }
317
318 inline void StyleBuilderCustom::applyValueVerticalAlign(StyleResolver& styleResolver, CSSValue& value)
319 {
320     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
321     if (primitiveValue.valueID())
322         styleResolver.style()->setVerticalAlign(primitiveValue);
323     else
324         styleResolver.style()->setVerticalAlignLength(primitiveValue.convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(styleResolver.state().cssToLengthConversionData()));
325 }
326
327 #if ENABLE(CSS_IMAGE_RESOLUTION)
328
329 inline void StyleBuilderCustom::applyInheritImageResolution(StyleResolver& styleResolver)
330 {
331     styleResolver.style()->setImageResolutionSource(styleResolver.parentStyle()->imageResolutionSource());
332     styleResolver.style()->setImageResolutionSnap(styleResolver.parentStyle()->imageResolutionSnap());
333     styleResolver.style()->setImageResolution(styleResolver.parentStyle()->imageResolution());
334 }
335
336 inline void StyleBuilderCustom::applyInitialImageResolution(StyleResolver& styleResolver)
337 {
338     styleResolver.style()->setImageResolutionSource(RenderStyle::initialImageResolutionSource());
339     styleResolver.style()->setImageResolutionSnap(RenderStyle::initialImageResolutionSnap());
340     styleResolver.style()->setImageResolution(RenderStyle::initialImageResolution());
341 }
342
343 inline void StyleBuilderCustom::applyValueImageResolution(StyleResolver& styleResolver, CSSValue& value)
344 {
345     ImageResolutionSource source = RenderStyle::initialImageResolutionSource();
346     ImageResolutionSnap snap = RenderStyle::initialImageResolutionSnap();
347     double resolution = RenderStyle::initialImageResolution();
348     for (auto& item : downcast<CSSValueList>(value)) {
349         CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(item.get());
350         if (primitiveValue.valueID() == CSSValueFromImage)
351             source = ImageResolutionSource::FromImage;
352         else if (primitiveValue.valueID() == CSSValueSnap)
353             snap = ImageResolutionSnap::Pixels;
354         else
355             resolution = primitiveValue.doubleValue(CSSPrimitiveValue::CSS_DPPX);
356     }
357     styleResolver.style()->setImageResolutionSource(source);
358     styleResolver.style()->setImageResolutionSnap(snap);
359     styleResolver.style()->setImageResolution(resolution);
360 }
361
362 #endif // ENABLE(CSS_IMAGE_RESOLUTION)
363
364 inline void StyleBuilderCustom::applyInheritSize(StyleResolver&) { }
365
366 inline void StyleBuilderCustom::applyInitialSize(StyleResolver&) { }
367
368 inline void StyleBuilderCustom::applyValueSize(StyleResolver& styleResolver, CSSValue& value)
369 {
370     styleResolver.style()->resetPageSizeType();
371
372     if (!is<CSSValueList>(value))
373         return;
374
375     Length width;
376     Length height;
377     PageSizeType pageSizeType = PAGE_SIZE_AUTO;
378
379     auto& valueList = downcast<CSSValueList>(value);
380     switch (valueList.length()) {
381     case 2: {
382         auto firstValue = valueList.itemWithoutBoundsCheck(0);
383         auto secondValue = valueList.itemWithoutBoundsCheck(1);
384         // <length>{2} | <page-size> <orientation>
385         if (!is<CSSPrimitiveValue>(*firstValue) || !is<CSSPrimitiveValue>(*secondValue))
386             return;
387         auto& firstPrimitiveValue = downcast<CSSPrimitiveValue>(*firstValue);
388         auto& secondPrimitiveValue = downcast<CSSPrimitiveValue>(*secondValue);
389         if (firstPrimitiveValue.isLength()) {
390             // <length>{2}
391             if (!secondPrimitiveValue.isLength())
392                 return;
393             CSSToLengthConversionData conversionData = styleResolver.state().cssToLengthConversionData().copyWithAdjustedZoom(1.0f);
394             width = firstPrimitiveValue.computeLength<Length>(conversionData);
395             height = secondPrimitiveValue.computeLength<Length>(conversionData);
396         } else {
397             // <page-size> <orientation>
398             // The value order is guaranteed. See CSSParser::parseSizeParameter.
399             if (!getPageSizeFromName(&firstPrimitiveValue, &secondPrimitiveValue, width, height))
400                 return;
401         }
402         pageSizeType = PAGE_SIZE_RESOLVED;
403         break;
404     }
405     case 1: {
406         auto value = valueList.itemWithoutBoundsCheck(0);
407         // <length> | auto | <page-size> | [ portrait | landscape]
408         if (!is<CSSPrimitiveValue>(*value))
409             return;
410         auto& primitiveValue = downcast<CSSPrimitiveValue>(*value);
411         if (primitiveValue.isLength()) {
412             // <length>
413             pageSizeType = PAGE_SIZE_RESOLVED;
414             width = height = primitiveValue.computeLength<Length>(styleResolver.state().cssToLengthConversionData().copyWithAdjustedZoom(1.0f));
415         } else {
416             switch (primitiveValue.valueID()) {
417             case 0:
418                 return;
419             case CSSValueAuto:
420                 pageSizeType = PAGE_SIZE_AUTO;
421                 break;
422             case CSSValuePortrait:
423                 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT;
424                 break;
425             case CSSValueLandscape:
426                 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE;
427                 break;
428             default:
429                 // <page-size>
430                 pageSizeType = PAGE_SIZE_RESOLVED;
431                 if (!getPageSizeFromName(&primitiveValue, nullptr, width, height))
432                     return;
433             }
434         }
435         break;
436     }
437     default:
438         return;
439     }
440     styleResolver.style()->setPageSizeType(pageSizeType);
441     styleResolver.style()->setPageSize({ WTFMove(width), WTFMove(height) });
442 }
443
444 inline void StyleBuilderCustom::applyInheritTextIndent(StyleResolver& styleResolver)
445 {
446     styleResolver.style()->setTextIndent(Length { styleResolver.parentStyle()->textIndent() });
447 #if ENABLE(CSS3_TEXT)
448     styleResolver.style()->setTextIndentLine(styleResolver.parentStyle()->textIndentLine());
449     styleResolver.style()->setTextIndentType(styleResolver.parentStyle()->textIndentType());
450 #endif
451 }
452
453 inline void StyleBuilderCustom::applyInitialTextIndent(StyleResolver& styleResolver)
454 {
455     styleResolver.style()->setTextIndent(RenderStyle::initialTextIndent());
456 #if ENABLE(CSS3_TEXT)
457     styleResolver.style()->setTextIndentLine(RenderStyle::initialTextIndentLine());
458     styleResolver.style()->setTextIndentType(RenderStyle::initialTextIndentType());
459 #endif
460 }
461
462 inline void StyleBuilderCustom::applyValueTextIndent(StyleResolver& styleResolver, CSSValue& value)
463 {
464     Length lengthOrPercentageValue;
465 #if ENABLE(CSS3_TEXT)
466     TextIndentLine textIndentLineValue = RenderStyle::initialTextIndentLine();
467     TextIndentType textIndentTypeValue = RenderStyle::initialTextIndentType();
468 #endif
469     for (auto& item : downcast<CSSValueList>(value)) {
470         auto& primitiveValue = downcast<CSSPrimitiveValue>(item.get());
471         if (!primitiveValue.valueID())
472             lengthOrPercentageValue = primitiveValue.convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(styleResolver.state().cssToLengthConversionData());
473 #if ENABLE(CSS3_TEXT)
474         else if (primitiveValue.valueID() == CSSValueWebkitEachLine)
475             textIndentLineValue = TextIndentLine::EachLine;
476         else if (primitiveValue.valueID() == CSSValueWebkitHanging)
477             textIndentTypeValue = TextIndentType::Hanging;
478 #endif
479     }
480
481     if (lengthOrPercentageValue.isUndefined())
482         return;
483
484     styleResolver.style()->setTextIndent(WTFMove(lengthOrPercentageValue));
485 #if ENABLE(CSS3_TEXT)
486     styleResolver.style()->setTextIndentLine(textIndentLineValue);
487     styleResolver.style()->setTextIndentType(textIndentTypeValue);
488 #endif
489 }
490
491 enum BorderImageType { BorderImage, WebkitMaskBoxImage };
492 enum BorderImageModifierType { Outset, Repeat, Slice, Width };
493 template <BorderImageType type, BorderImageModifierType modifier>
494 class ApplyPropertyBorderImageModifier {
495 public:
496     static void applyInheritValue(StyleResolver& styleResolver)
497     {
498         NinePieceImage image(getValue(styleResolver.style()));
499         switch (modifier) {
500         case Outset:
501             image.copyOutsetFrom(getValue(styleResolver.parentStyle()));
502             break;
503         case Repeat:
504             image.copyRepeatFrom(getValue(styleResolver.parentStyle()));
505             break;
506         case Slice:
507             image.copyImageSlicesFrom(getValue(styleResolver.parentStyle()));
508             break;
509         case Width:
510             image.copyBorderSlicesFrom(getValue(styleResolver.parentStyle()));
511             break;
512         }
513         setValue(styleResolver.style(), image);
514     }
515
516     static void applyInitialValue(StyleResolver& styleResolver)
517     {
518         NinePieceImage image(getValue(styleResolver.style()));
519         switch (modifier) {
520         case Outset:
521             image.setOutset(LengthBox(0));
522             break;
523         case Repeat:
524             image.setHorizontalRule(StretchImageRule);
525             image.setVerticalRule(StretchImageRule);
526             break;
527         case Slice:
528             // Masks have a different initial value for slices. Preserve the value of 0 for backwards compatibility.
529             image.setImageSlices(type == BorderImage ? LengthBox(Length(100, Percent), Length(100, Percent), Length(100, Percent), Length(100, Percent)) : LengthBox());
530             image.setFill(false);
531             break;
532         case Width:
533             // FIXME: This is a local variable to work around a bug in the GCC 8.1 Address Sanitizer.
534             // Might be slightly less efficient when the type is not BorderImage since this is unused in that case.
535             // Should be switched back to a temporary when possible. See https://webkit.org/b/186980
536             LengthBox lengthBox(Length(1, Relative), Length(1, Relative), Length(1, Relative), Length(1, Relative));
537             // Masks have a different initial value for widths. They use an 'auto' value rather than trying to fit to the border.
538             image.setBorderSlices(type == BorderImage ? lengthBox : LengthBox());
539             break;
540         }
541         setValue(styleResolver.style(), image);
542     }
543
544     static void applyValue(StyleResolver& styleResolver, CSSValue& value)
545     {
546         NinePieceImage image(getValue(styleResolver.style()));
547         switch (modifier) {
548         case Outset:
549             image.setOutset(styleResolver.styleMap()->mapNinePieceImageQuad(value));
550             break;
551         case Repeat:
552             styleResolver.styleMap()->mapNinePieceImageRepeat(value, image);
553             break;
554         case Slice:
555             styleResolver.styleMap()->mapNinePieceImageSlice(value, image);
556             break;
557         case Width:
558             image.setBorderSlices(styleResolver.styleMap()->mapNinePieceImageQuad(value));
559             break;
560         }
561         setValue(styleResolver.style(), image);
562     }
563
564 private:
565     static const NinePieceImage& getValue(const RenderStyle* style)
566     {
567         return type == BorderImage ? style->borderImage() : style->maskBoxImage();
568     }
569
570     static void setValue(RenderStyle* style, const NinePieceImage& value)
571     {
572         return type == BorderImage ? style->setBorderImage(value) : style->setMaskBoxImage(value);
573     }
574 };
575
576 #define DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(type, modifier) \
577 inline void StyleBuilderCustom::applyInherit##type##modifier(StyleResolver& styleResolver) \
578 { \
579     ApplyPropertyBorderImageModifier<type, modifier>::applyInheritValue(styleResolver); \
580 } \
581 inline void StyleBuilderCustom::applyInitial##type##modifier(StyleResolver& styleResolver) \
582 { \
583     ApplyPropertyBorderImageModifier<type, modifier>::applyInitialValue(styleResolver); \
584 } \
585 inline void StyleBuilderCustom::applyValue##type##modifier(StyleResolver& styleResolver, CSSValue& value) \
586 { \
587     ApplyPropertyBorderImageModifier<type, modifier>::applyValue(styleResolver, value); \
588 }
589
590 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(BorderImage, Outset)
591 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(BorderImage, Repeat)
592 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(BorderImage, Slice)
593 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(BorderImage, Width)
594 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(WebkitMaskBoxImage, Outset)
595 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(WebkitMaskBoxImage, Repeat)
596 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(WebkitMaskBoxImage, Slice)
597 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(WebkitMaskBoxImage, Width)
598
599 #if ENABLE(TEXT_AUTOSIZING)
600
601 inline void StyleBuilderCustom::applyInheritLineHeight(StyleResolver& styleResolver)
602 {
603     styleResolver.style()->setLineHeight(Length { styleResolver.parentStyle()->lineHeight() });
604     styleResolver.style()->setSpecifiedLineHeight(Length { styleResolver.parentStyle()->specifiedLineHeight() });
605 }
606
607 inline void StyleBuilderCustom::applyInitialLineHeight(StyleResolver& styleResolver)
608 {
609     styleResolver.style()->setLineHeight(RenderStyle::initialLineHeight());
610     styleResolver.style()->setSpecifiedLineHeight(RenderStyle::initialSpecifiedLineHeight());
611 }
612
613 static inline float computeBaseSpecifiedFontSize(const Document& document, const RenderStyle& style, bool percentageAutosizingEnabled)
614 {
615     float result = style.specifiedFontSize();
616     auto* frame = document.frame();
617     if (frame && style.textZoom() != TextZoom::Reset)
618         result *= frame->textZoomFactor();
619     result *= style.effectiveZoom();
620     if (percentageAutosizingEnabled && !document.settings().textAutosizingUsesIdempotentMode())
621         result *= style.textSizeAdjust().multiplier();
622     return result;
623 }
624
625 static inline float computeLineHeightMultiplierDueToFontSize(const Document& document, const RenderStyle& style, const CSSPrimitiveValue& value)
626 {
627     bool percentageAutosizingEnabled = document.settings().textAutosizingEnabled() && style.textSizeAdjust().isPercentage();
628
629     if (value.isLength()) {
630         auto minimumFontSize = document.settings().minimumFontSize();
631         if (minimumFontSize > 0) {
632             auto specifiedFontSize = computeBaseSpecifiedFontSize(document, style, percentageAutosizingEnabled);
633             // Small font sizes cause a preposterously large (near infinity) line-height. Add a fuzz-factor of 1px which opts out of
634             // boosted line-height.
635             if (specifiedFontSize < minimumFontSize && specifiedFontSize >= 1) {
636                 // FIXME: There are two settings which are relevant here: minimum font size, and minimum logical font size (as
637                 // well as things like the zoom property, text zoom on the page, and text autosizing). The minimum logical font
638                 // size is nonzero by default, and already incorporated into the computed font size, so if we just use the ratio
639                 // of the computed : specified font size, it will be > 1 in the cases where the minimum logical font size kicks
640                 // in. In general, this is the right thing to do, however, this kind of blanket change is too risky to perform
641                 // right now. https://bugs.webkit.org/show_bug.cgi?id=174570 tracks turning this on. For now, we can just pretend
642                 // that the minimum font size is the only thing affecting the computed font size.
643
644                 // This calculation matches the line-height computed size calculation in
645                 // TextAutoSizing::Value::adjustTextNodeSizes().
646                 auto scaleChange = minimumFontSize / specifiedFontSize;
647                 return scaleChange;
648             }
649         }
650     }
651
652     if (percentageAutosizingEnabled && !document.settings().textAutosizingUsesIdempotentMode())
653         return style.textSizeAdjust().multiplier();
654     return 1;
655 }
656
657 inline void StyleBuilderCustom::applyValueLineHeight(StyleResolver& styleResolver, CSSValue& value)
658 {
659     Optional<Length> lineHeight = StyleBuilderConverter::convertLineHeight(styleResolver, value, 1);
660     if (!lineHeight)
661         return;
662
663     Length computedLineHeight;
664     if (lineHeight.value().isNegative())
665         computedLineHeight = lineHeight.value();
666     else {
667         auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
668         auto multiplier = computeLineHeightMultiplierDueToFontSize(styleResolver.document(), *styleResolver.style(), primitiveValue);
669         if (multiplier == 1)
670             computedLineHeight = lineHeight.value();
671         else
672             computedLineHeight = StyleBuilderConverter::convertLineHeight(styleResolver, value, multiplier).value();
673     }
674
675     styleResolver.style()->setLineHeight(WTFMove(computedLineHeight));
676     styleResolver.style()->setSpecifiedLineHeight(WTFMove(lineHeight.value()));
677 }
678
679 #endif
680
681 inline void StyleBuilderCustom::applyInheritOutlineStyle(StyleResolver& styleResolver)
682 {
683     styleResolver.style()->setOutlineStyleIsAuto(styleResolver.parentStyle()->outlineStyleIsAuto());
684     styleResolver.style()->setOutlineStyle(styleResolver.parentStyle()->outlineStyle());
685 }
686
687 inline void StyleBuilderCustom::applyInitialOutlineStyle(StyleResolver& styleResolver)
688 {
689     styleResolver.style()->setOutlineStyleIsAuto(RenderStyle::initialOutlineStyleIsAuto());
690     styleResolver.style()->setOutlineStyle(RenderStyle::initialBorderStyle());
691 }
692
693 inline void StyleBuilderCustom::applyValueOutlineStyle(StyleResolver& styleResolver, CSSValue& value)
694 {
695     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
696
697     styleResolver.style()->setOutlineStyleIsAuto(primitiveValue);
698     styleResolver.style()->setOutlineStyle(primitiveValue);
699 }
700
701 inline void StyleBuilderCustom::applyInitialClip(StyleResolver& styleResolver)
702 {
703     styleResolver.style()->setClip(Length(), Length(), Length(), Length());
704     styleResolver.style()->setHasClip(false);
705 }
706
707 inline void StyleBuilderCustom::applyInheritClip(StyleResolver& styleResolver)
708 {
709     auto* parentStyle = styleResolver.parentStyle();
710     if (!parentStyle->hasClip())
711         return applyInitialClip(styleResolver);
712     styleResolver.style()->setClip(Length { parentStyle->clipTop() }, Length { parentStyle->clipRight() },
713         Length { parentStyle->clipBottom() }, Length { parentStyle->clipLeft() });
714     styleResolver.style()->setHasClip(true);
715 }
716
717 inline void StyleBuilderCustom::applyValueClip(StyleResolver& styleResolver, CSSValue& value)
718 {
719     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
720     if (auto* rect = primitiveValue.rectValue()) {
721         auto conversionData = styleResolver.state().cssToLengthConversionData();
722         auto top = rect->top()->convertToLength<FixedIntegerConversion | PercentConversion | AutoConversion>(conversionData);
723         auto right = rect->right()->convertToLength<FixedIntegerConversion | PercentConversion | AutoConversion>(conversionData);
724         auto bottom = rect->bottom()->convertToLength<FixedIntegerConversion | PercentConversion | AutoConversion>(conversionData);
725         auto left = rect->left()->convertToLength<FixedIntegerConversion | PercentConversion | AutoConversion>(conversionData);
726         styleResolver.style()->setClip(WTFMove(top), WTFMove(right), WTFMove(bottom), WTFMove(left));
727         styleResolver.style()->setHasClip(true);
728     } else {
729         ASSERT(primitiveValue.valueID() == CSSValueAuto);
730         applyInitialClip(styleResolver);
731     }
732 }
733
734 inline void StyleBuilderCustom::applyValueWebkitLocale(StyleResolver& styleResolver, CSSValue& value)
735 {
736     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
737
738     FontCascadeDescription fontDescription = styleResolver.style()->fontDescription();
739     if (primitiveValue.valueID() == CSSValueAuto)
740         fontDescription.setLocale(nullAtom());
741     else
742         fontDescription.setLocale(primitiveValue.stringValue());
743     styleResolver.setFontDescription(WTFMove(fontDescription));
744 }
745
746 inline void StyleBuilderCustom::applyValueWritingMode(StyleResolver& styleResolver, CSSValue& value)
747 {
748     styleResolver.setWritingMode(downcast<CSSPrimitiveValue>(value));
749     styleResolver.style()->setHasExplicitlySetWritingMode(true);
750 }
751
752 inline void StyleBuilderCustom::applyValueWebkitTextOrientation(StyleResolver& styleResolver, CSSValue& value)
753 {
754     styleResolver.setTextOrientation(downcast<CSSPrimitiveValue>(value));
755 }
756
757 #if ENABLE(TEXT_AUTOSIZING)
758 inline void StyleBuilderCustom::applyValueWebkitTextSizeAdjust(StyleResolver& styleResolver, CSSValue& value)
759 {
760     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
761     if (primitiveValue.valueID() == CSSValueAuto)
762         styleResolver.style()->setTextSizeAdjust(TextSizeAdjustment(AutoTextSizeAdjustment));
763     else if (primitiveValue.valueID() == CSSValueNone)
764         styleResolver.style()->setTextSizeAdjust(TextSizeAdjustment(NoTextSizeAdjustment));
765     else
766         styleResolver.style()->setTextSizeAdjust(TextSizeAdjustment(primitiveValue.floatValue()));
767
768     styleResolver.state().setFontDirty(true);
769 }
770 #endif
771
772 inline void StyleBuilderCustom::applyValueWebkitTextZoom(StyleResolver& styleResolver, CSSValue& value)
773 {
774     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
775     if (primitiveValue.valueID() == CSSValueNormal)
776         styleResolver.style()->setTextZoom(TextZoom::Normal);
777     else if (primitiveValue.valueID() == CSSValueReset)
778         styleResolver.style()->setTextZoom(TextZoom::Reset);
779     styleResolver.state().setFontDirty(true);
780 }
781
782 #if ENABLE(DARK_MODE_CSS)
783 inline void StyleBuilderCustom::applyValueColorScheme(StyleResolver& styleResolver, CSSValue& value)
784 {
785     styleResolver.style()->setColorScheme(StyleBuilderConverter::convertColorScheme(styleResolver, value));
786     styleResolver.style()->setHasExplicitlySetColorScheme(true);
787 }
788 #endif
789
790 template<CSSPropertyID property>
791 inline void StyleBuilderCustom::applyTextOrBoxShadowValue(StyleResolver& styleResolver, CSSValue& value)
792 {
793     if (is<CSSPrimitiveValue>(value)) {
794         ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
795         if (property == CSSPropertyTextShadow)
796             styleResolver.style()->setTextShadow(nullptr);
797         else
798             styleResolver.style()->setBoxShadow(nullptr);
799         return;
800     }
801
802     bool isFirstEntry = true;
803     for (auto& item : downcast<CSSValueList>(value)) {
804         auto& shadowValue = downcast<CSSShadowValue>(item.get());
805         auto conversionData = styleResolver.state().cssToLengthConversionData();
806         int x = shadowValue.x->computeLength<int>(conversionData);
807         int y = shadowValue.y->computeLength<int>(conversionData);
808         int blur = shadowValue.blur ? shadowValue.blur->computeLength<int>(conversionData) : 0;
809         int spread = shadowValue.spread ? shadowValue.spread->computeLength<int>(conversionData) : 0;
810         ShadowStyle shadowStyle = shadowValue.style && shadowValue.style->valueID() == CSSValueInset ? Inset : Normal;
811         Color color;
812         if (shadowValue.color)
813             color = styleResolver.colorFromPrimitiveValue(*shadowValue.color);
814         else
815             color = styleResolver.style()->color();
816         auto shadowData = makeUnique<ShadowData>(IntPoint(x, y), blur, spread, shadowStyle, property == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent);
817         if (property == CSSPropertyTextShadow)
818             styleResolver.style()->setTextShadow(WTFMove(shadowData), !isFirstEntry); // add to the list if this is not the first entry
819         else
820             styleResolver.style()->setBoxShadow(WTFMove(shadowData), !isFirstEntry); // add to the list if this is not the first entry
821         isFirstEntry = false;
822     }
823 }
824
825 inline void StyleBuilderCustom::applyInitialTextShadow(StyleResolver& styleResolver)
826 {
827     styleResolver.style()->setTextShadow(nullptr);
828 }
829
830 inline void StyleBuilderCustom::applyInheritTextShadow(StyleResolver& styleResolver)
831 {
832     styleResolver.style()->setTextShadow(styleResolver.parentStyle()->textShadow() ? makeUnique<ShadowData>(*styleResolver.parentStyle()->textShadow()) : nullptr);
833 }
834
835 inline void StyleBuilderCustom::applyValueTextShadow(StyleResolver& styleResolver, CSSValue& value)
836 {
837     applyTextOrBoxShadowValue<CSSPropertyTextShadow>(styleResolver, value);
838 }
839
840 inline void StyleBuilderCustom::applyInitialBoxShadow(StyleResolver& styleResolver)
841 {
842     styleResolver.style()->setBoxShadow(nullptr);
843 }
844
845 inline void StyleBuilderCustom::applyInheritBoxShadow(StyleResolver& styleResolver)
846 {
847     styleResolver.style()->setBoxShadow(styleResolver.parentStyle()->boxShadow() ? makeUnique<ShadowData>(*styleResolver.parentStyle()->boxShadow()) : nullptr);
848 }
849
850 inline void StyleBuilderCustom::applyValueBoxShadow(StyleResolver& styleResolver, CSSValue& value)
851 {
852     applyTextOrBoxShadowValue<CSSPropertyBoxShadow>(styleResolver, value);
853 }
854
855 inline void StyleBuilderCustom::applyInitialWebkitBoxShadow(StyleResolver& styleResolver)
856 {
857     applyInitialBoxShadow(styleResolver);
858 }
859
860 inline void StyleBuilderCustom::applyInheritWebkitBoxShadow(StyleResolver& styleResolver)
861 {
862     applyInheritBoxShadow(styleResolver);
863 }
864
865 inline void StyleBuilderCustom::applyValueWebkitBoxShadow(StyleResolver& styleResolver, CSSValue& value)
866 {
867     applyTextOrBoxShadowValue<CSSPropertyWebkitBoxShadow>(styleResolver, value);
868 }
869
870 inline void StyleBuilderCustom::applyInitialFontFamily(StyleResolver& styleResolver)
871 {
872     auto fontDescription = styleResolver.style()->fontDescription();
873     auto initialDesc = FontCascadeDescription();
874
875     // We need to adjust the size to account for the generic family change from monospace to non-monospace.
876     if (fontDescription.useFixedDefaultSize()) {
877         if (CSSValueID sizeIdentifier = fontDescription.keywordSizeAsIdentifier())
878             styleResolver.setFontSize(fontDescription, Style::fontSizeForKeyword(sizeIdentifier, false, styleResolver.document()));
879     }
880     if (!initialDesc.firstFamily().isEmpty())
881         fontDescription.setFamilies(initialDesc.families());
882
883     styleResolver.setFontDescription(WTFMove(fontDescription));
884 }
885
886 inline void StyleBuilderCustom::applyInheritFontFamily(StyleResolver& styleResolver)
887 {
888     auto fontDescription = styleResolver.style()->fontDescription();
889     auto parentFontDescription = styleResolver.parentStyle()->fontDescription();
890
891     fontDescription.setFamilies(parentFontDescription.families());
892     fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
893     styleResolver.setFontDescription(WTFMove(fontDescription));
894 }
895
896 inline void StyleBuilderCustom::applyValueFontFamily(StyleResolver& styleResolver, CSSValue& value)
897 {
898     auto& valueList = downcast<CSSValueList>(value);
899
900     auto fontDescription = styleResolver.style()->fontDescription();
901     // Before mapping in a new font-family property, we should reset the generic family.
902     bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
903
904     Vector<AtomString> families;
905     families.reserveInitialCapacity(valueList.length());
906
907     for (auto& item : valueList) {
908         auto& contentValue = downcast<CSSPrimitiveValue>(item.get());
909         AtomString family;
910         bool isGenericFamily = false;
911         if (contentValue.isFontFamily()) {
912             const CSSFontFamily& fontFamily = contentValue.fontFamily();
913             family = fontFamily.familyName;
914             // If the family name was resolved by the CSS parser from a system font ID, then it is generic.
915             isGenericFamily = fontFamily.fromSystemFontID;
916         } else {
917             switch (contentValue.valueID()) {
918             case CSSValueWebkitBody:
919                 family = styleResolver.settings().standardFontFamily();
920                 break;
921             case CSSValueSerif:
922                 family = serifFamily;
923                 isGenericFamily = true;
924                 break;
925             case CSSValueSansSerif:
926                 family = sansSerifFamily;
927                 isGenericFamily = true;
928                 break;
929             case CSSValueCursive:
930                 family = cursiveFamily;
931                 isGenericFamily = true;
932                 break;
933             case CSSValueFantasy:
934                 family = fantasyFamily;
935                 isGenericFamily = true;
936                 break;
937             case CSSValueMonospace:
938                 family = monospaceFamily;
939                 isGenericFamily = true;
940                 break;
941             case CSSValueWebkitPictograph:
942                 family = pictographFamily;
943                 isGenericFamily = true;
944                 break;
945             case CSSValueSystemUi:
946                 family = systemUiFamily;
947                 isGenericFamily = true;
948                 break;
949             default:
950                 break;
951             }
952         }
953
954         if (family.isEmpty())
955             continue;
956         if (families.isEmpty())
957             fontDescription.setIsSpecifiedFont(!isGenericFamily);
958         families.uncheckedAppend(family);
959     }
960
961     if (families.isEmpty())
962         return;
963     fontDescription.setFamilies(families);
964
965     if (fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize) {
966         if (CSSValueID sizeIdentifier = fontDescription.keywordSizeAsIdentifier())
967             styleResolver.setFontSize(fontDescription, Style::fontSizeForKeyword(sizeIdentifier, !oldFamilyUsedFixedDefaultSize, styleResolver.document()));
968     }
969
970     styleResolver.setFontDescription(WTFMove(fontDescription));
971 }
972
973 inline bool StyleBuilderCustom::isValidDisplayValue(StyleResolver& styleResolver, DisplayType display)
974 {
975     if (is<SVGElement>(styleResolver.element()) && styleResolver.style()->styleType() == PseudoId::None)
976         return display == DisplayType::Inline || display == DisplayType::Block || display == DisplayType::None;
977     return true;
978 }
979
980 inline void StyleBuilderCustom::applyInheritDisplay(StyleResolver& styleResolver)
981 {
982     DisplayType display = styleResolver.parentStyle()->display();
983     if (isValidDisplayValue(styleResolver, display))
984         styleResolver.style()->setDisplay(display);
985 }
986
987 inline void StyleBuilderCustom::applyValueDisplay(StyleResolver& styleResolver, CSSValue& value)
988 {
989     DisplayType display = downcast<CSSPrimitiveValue>(value);
990     if (isValidDisplayValue(styleResolver, display))
991         styleResolver.style()->setDisplay(display);
992 }
993
994 inline void StyleBuilderCustom::applyValueBaselineShift(StyleResolver& styleResolver, CSSValue& value)
995 {
996     SVGRenderStyle& svgStyle = styleResolver.style()->accessSVGStyle();
997     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
998     if (primitiveValue.isValueID()) {
999         switch (primitiveValue.valueID()) {
1000         case CSSValueBaseline:
1001             svgStyle.setBaselineShift(BaselineShift::Baseline);
1002             break;
1003         case CSSValueSub:
1004             svgStyle.setBaselineShift(BaselineShift::Sub);
1005             break;
1006         case CSSValueSuper:
1007             svgStyle.setBaselineShift(BaselineShift::Super);
1008             break;
1009         default:
1010             break;
1011         }
1012     } else {
1013         svgStyle.setBaselineShift(BaselineShift::Length);
1014         svgStyle.setBaselineShiftValue(SVGLengthValue::fromCSSPrimitiveValue(primitiveValue));
1015     }
1016 }
1017
1018 inline void StyleBuilderCustom::applyInitialWebkitAspectRatio(StyleResolver& styleResolver)
1019 {
1020     styleResolver.style()->setAspectRatioType(RenderStyle::initialAspectRatioType());
1021     styleResolver.style()->setAspectRatioDenominator(RenderStyle::initialAspectRatioDenominator());
1022     styleResolver.style()->setAspectRatioNumerator(RenderStyle::initialAspectRatioNumerator());
1023 }
1024
1025 inline void StyleBuilderCustom::applyInheritWebkitAspectRatio(StyleResolver& styleResolver)
1026 {
1027     if (styleResolver.parentStyle()->aspectRatioType() == AspectRatioType::Auto)
1028         return;
1029     styleResolver.style()->setAspectRatioType(styleResolver.parentStyle()->aspectRatioType());
1030     styleResolver.style()->setAspectRatioDenominator(styleResolver.parentStyle()->aspectRatioDenominator());
1031     styleResolver.style()->setAspectRatioNumerator(styleResolver.parentStyle()->aspectRatioNumerator());
1032 }
1033
1034 inline void StyleBuilderCustom::applyValueWebkitAspectRatio(StyleResolver& styleResolver, CSSValue& value)
1035 {
1036     if (is<CSSPrimitiveValue>(value)) {
1037         auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
1038
1039         if (primitiveValue.valueID() == CSSValueFromDimensions)
1040             return styleResolver.style()->setAspectRatioType(AspectRatioType::FromDimensions);
1041         if (primitiveValue.valueID() == CSSValueFromIntrinsic)
1042             return styleResolver.style()->setAspectRatioType(AspectRatioType::FromIntrinsic);
1043
1044         ASSERT(primitiveValue.valueID() == CSSValueAuto);
1045         return styleResolver.style()->setAspectRatioType(AspectRatioType::Auto);
1046     }
1047
1048     auto& aspectRatioValue = downcast<CSSAspectRatioValue>(value);
1049     styleResolver.style()->setAspectRatioType(AspectRatioType::Specified);
1050     styleResolver.style()->setAspectRatioDenominator(aspectRatioValue.denominatorValue());
1051     styleResolver.style()->setAspectRatioNumerator(aspectRatioValue.numeratorValue());
1052 }
1053
1054 inline void StyleBuilderCustom::applyInitialWebkitTextEmphasisStyle(StyleResolver& styleResolver)
1055 {
1056     styleResolver.style()->setTextEmphasisFill(RenderStyle::initialTextEmphasisFill());
1057     styleResolver.style()->setTextEmphasisMark(RenderStyle::initialTextEmphasisMark());
1058     styleResolver.style()->setTextEmphasisCustomMark(RenderStyle::initialTextEmphasisCustomMark());
1059 }
1060
1061 inline void StyleBuilderCustom::applyInheritWebkitTextEmphasisStyle(StyleResolver& styleResolver)
1062 {
1063     styleResolver.style()->setTextEmphasisFill(styleResolver.parentStyle()->textEmphasisFill());
1064     styleResolver.style()->setTextEmphasisMark(styleResolver.parentStyle()->textEmphasisMark());
1065     styleResolver.style()->setTextEmphasisCustomMark(styleResolver.parentStyle()->textEmphasisCustomMark());
1066 }
1067
1068 inline void StyleBuilderCustom::applyValueWebkitTextEmphasisStyle(StyleResolver& styleResolver, CSSValue& value)
1069 {
1070     if (is<CSSValueList>(value)) {
1071         auto& list = downcast<CSSValueList>(value);
1072         ASSERT(list.length() == 2);
1073
1074         for (auto& item : list) {
1075             CSSPrimitiveValue& value = downcast<CSSPrimitiveValue>(item.get());
1076             if (value.valueID() == CSSValueFilled || value.valueID() == CSSValueOpen)
1077                 styleResolver.style()->setTextEmphasisFill(value);
1078             else
1079                 styleResolver.style()->setTextEmphasisMark(value);
1080         }
1081         styleResolver.style()->setTextEmphasisCustomMark(nullAtom());
1082         return;
1083     }
1084
1085     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
1086     if (primitiveValue.isString()) {
1087         styleResolver.style()->setTextEmphasisFill(TextEmphasisFill::Filled);
1088         styleResolver.style()->setTextEmphasisMark(TextEmphasisMark::Custom);
1089         styleResolver.style()->setTextEmphasisCustomMark(primitiveValue.stringValue());
1090         return;
1091     }
1092
1093     styleResolver.style()->setTextEmphasisCustomMark(nullAtom());
1094
1095     if (primitiveValue.valueID() == CSSValueFilled || primitiveValue.valueID() == CSSValueOpen) {
1096         styleResolver.style()->setTextEmphasisFill(primitiveValue);
1097         styleResolver.style()->setTextEmphasisMark(TextEmphasisMark::Auto);
1098     } else {
1099         styleResolver.style()->setTextEmphasisFill(TextEmphasisFill::Filled);
1100         styleResolver.style()->setTextEmphasisMark(primitiveValue);
1101     }
1102 }
1103
1104 template <StyleBuilderCustom::CounterBehavior counterBehavior>
1105 inline void StyleBuilderCustom::applyInheritCounter(StyleResolver& styleResolver)
1106 {
1107     auto& map = styleResolver.style()->accessCounterDirectives();
1108     for (auto& keyValue : const_cast<RenderStyle*>(styleResolver.parentStyle())->accessCounterDirectives()) {
1109         auto& directives = map.add(keyValue.key, CounterDirectives { }).iterator->value;
1110         if (counterBehavior == Reset)
1111             directives.resetValue = keyValue.value.resetValue;
1112         else
1113             directives.incrementValue = keyValue.value.incrementValue;
1114     }
1115 }
1116
1117 template <StyleBuilderCustom::CounterBehavior counterBehavior>
1118 inline void StyleBuilderCustom::applyValueCounter(StyleResolver& styleResolver, CSSValue& value)
1119 {
1120     bool setCounterIncrementToNone = counterBehavior == Increment && is<CSSPrimitiveValue>(value) && downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone;
1121
1122     if (!is<CSSValueList>(value) && !setCounterIncrementToNone)
1123         return;
1124
1125     CounterDirectiveMap& map = styleResolver.style()->accessCounterDirectives();
1126     for (auto& keyValue : map) {
1127         if (counterBehavior == Reset)
1128             keyValue.value.resetValue = WTF::nullopt;
1129         else
1130             keyValue.value.incrementValue = WTF::nullopt;
1131     }
1132
1133     if (setCounterIncrementToNone)
1134         return;
1135
1136     for (auto& item : downcast<CSSValueList>(value)) {
1137         Pair* pair = downcast<CSSPrimitiveValue>(item.get()).pairValue();
1138         AtomString identifier = pair->first()->stringValue();
1139         int value = pair->second()->intValue();
1140         auto& directives = map.add(identifier, CounterDirectives { }).iterator->value;
1141         if (counterBehavior == Reset)
1142             directives.resetValue = value;
1143         else
1144             directives.incrementValue = saturatedAddition(directives.incrementValue.valueOr(0), value);
1145     }
1146 }
1147
1148 inline void StyleBuilderCustom::applyInitialCounterIncrement(StyleResolver&) { }
1149
1150 inline void StyleBuilderCustom::applyInheritCounterIncrement(StyleResolver& styleResolver)
1151 {
1152     applyInheritCounter<Increment>(styleResolver);
1153 }
1154
1155 inline void StyleBuilderCustom::applyValueCounterIncrement(StyleResolver& styleResolver, CSSValue& value)
1156 {
1157     applyValueCounter<Increment>(styleResolver, value);
1158 }
1159
1160 inline void StyleBuilderCustom::applyInitialCounterReset(StyleResolver&) { }
1161
1162 inline void StyleBuilderCustom::applyInheritCounterReset(StyleResolver& styleResolver)
1163 {
1164     applyInheritCounter<Reset>(styleResolver);
1165 }
1166
1167 inline void StyleBuilderCustom::applyValueCounterReset(StyleResolver& styleResolver, CSSValue& value)
1168 {
1169     applyValueCounter<Reset>(styleResolver, value);
1170 }
1171
1172 inline void StyleBuilderCustom::applyInitialCursor(StyleResolver& styleResolver)
1173 {
1174     styleResolver.style()->clearCursorList();
1175     styleResolver.style()->setCursor(RenderStyle::initialCursor());
1176 }
1177
1178 inline void StyleBuilderCustom::applyInheritCursor(StyleResolver& styleResolver)
1179 {
1180     styleResolver.style()->setCursor(styleResolver.parentStyle()->cursor());
1181     styleResolver.style()->setCursorList(styleResolver.parentStyle()->cursors());
1182 }
1183
1184 inline void StyleBuilderCustom::applyValueCursor(StyleResolver& styleResolver, CSSValue& value)
1185 {
1186     styleResolver.style()->clearCursorList();
1187     if (is<CSSPrimitiveValue>(value)) {
1188         CursorType cursor = downcast<CSSPrimitiveValue>(value);
1189         if (styleResolver.style()->cursor() != cursor)
1190             styleResolver.style()->setCursor(cursor);
1191         return;
1192     }
1193
1194     styleResolver.style()->setCursor(CursorType::Auto);
1195     auto& list = downcast<CSSValueList>(value);
1196     for (auto& item : list) {
1197         if (is<CSSCursorImageValue>(item)) {
1198             auto& image = downcast<CSSCursorImageValue>(item.get());
1199             styleResolver.style()->addCursor(styleResolver.styleImage(image), image.hotSpot());
1200             continue;
1201         }
1202
1203         styleResolver.style()->setCursor(downcast<CSSPrimitiveValue>(item.get()));
1204         ASSERT_WITH_MESSAGE(item.ptr() == list.item(list.length() - 1), "Cursor ID fallback should always be last in the list");
1205         return;
1206     }
1207 }
1208
1209 inline void StyleBuilderCustom::applyInitialFill(StyleResolver& styleResolver)
1210 {
1211     auto& svgStyle = styleResolver.style()->accessSVGStyle();
1212     svgStyle.setFillPaint(SVGRenderStyle::initialFillPaintType(), SVGRenderStyle::initialFillPaintColor(), SVGRenderStyle::initialFillPaintUri(), styleResolver.applyPropertyToRegularStyle(), styleResolver.applyPropertyToVisitedLinkStyle());
1213 }
1214
1215 inline void StyleBuilderCustom::applyInheritFill(StyleResolver& styleResolver)
1216 {
1217     auto& svgStyle = styleResolver.style()->accessSVGStyle();
1218     auto& svgParentStyle = styleResolver.parentStyle()->svgStyle();
1219     svgStyle.setFillPaint(svgParentStyle.fillPaintType(), svgParentStyle.fillPaintColor(), svgParentStyle.fillPaintUri(), styleResolver.applyPropertyToRegularStyle(), styleResolver.applyPropertyToVisitedLinkStyle());
1220
1221 }
1222
1223 inline void StyleBuilderCustom::applyValueFill(StyleResolver& styleResolver, CSSValue& value)
1224 {
1225     auto& svgStyle = styleResolver.style()->accessSVGStyle();
1226     const auto* localValue = value.isPrimitiveValue() ? &downcast<CSSPrimitiveValue>(value) : nullptr;
1227     String url;
1228     if (value.isValueList()) {
1229         const CSSValueList& list = downcast<CSSValueList>(value);
1230         url = downcast<CSSPrimitiveValue>(list.item(0))->stringValue();
1231         localValue = downcast<CSSPrimitiveValue>(list.item(1));
1232     }
1233
1234     if (!localValue)
1235         return;
1236
1237     Color color;
1238     auto paintType = SVGPaintType::RGBColor;
1239     if (localValue->isURI()) {
1240         paintType = SVGPaintType::URI;
1241         url = localValue->stringValue();
1242     } else if (localValue->isValueID() && localValue->valueID() == CSSValueNone)
1243         paintType = url.isEmpty() ? SVGPaintType::None : SVGPaintType::URINone;
1244     else if (localValue->isValueID() && localValue->valueID() == CSSValueCurrentcolor) {
1245         color = styleResolver.style()->color();
1246         paintType = url.isEmpty() ? SVGPaintType::CurrentColor : SVGPaintType::URICurrentColor;
1247     } else {
1248         color = styleResolver.colorFromPrimitiveValue(*localValue);
1249         paintType = url.isEmpty() ? SVGPaintType::RGBColor : SVGPaintType::URIRGBColor;
1250     }
1251     svgStyle.setFillPaint(paintType, color, url, styleResolver.applyPropertyToRegularStyle(), styleResolver.applyPropertyToVisitedLinkStyle());
1252 }
1253
1254 inline void StyleBuilderCustom::applyInitialStroke(StyleResolver& styleResolver)
1255 {
1256     SVGRenderStyle& svgStyle = styleResolver.style()->accessSVGStyle();
1257     svgStyle.setStrokePaint(SVGRenderStyle::initialStrokePaintType(), SVGRenderStyle::initialStrokePaintColor(), SVGRenderStyle::initialStrokePaintUri(), styleResolver.applyPropertyToRegularStyle(), styleResolver.applyPropertyToVisitedLinkStyle());
1258 }
1259
1260 inline void StyleBuilderCustom::applyInheritStroke(StyleResolver& styleResolver)
1261 {
1262     auto& svgStyle = styleResolver.style()->accessSVGStyle();
1263     auto& svgParentStyle = styleResolver.parentStyle()->svgStyle();
1264     svgStyle.setStrokePaint(svgParentStyle.strokePaintType(), svgParentStyle.strokePaintColor(), svgParentStyle.strokePaintUri(), styleResolver.applyPropertyToRegularStyle(), styleResolver.applyPropertyToVisitedLinkStyle());
1265 }
1266
1267 inline void StyleBuilderCustom::applyValueStroke(StyleResolver& styleResolver, CSSValue& value)
1268 {
1269     auto& svgStyle = styleResolver.style()->accessSVGStyle();
1270     const auto* localValue = value.isPrimitiveValue() ? &downcast<CSSPrimitiveValue>(value) : nullptr;
1271     String url;
1272     if (value.isValueList()) {
1273         const CSSValueList& list = downcast<CSSValueList>(value);
1274         url = downcast<CSSPrimitiveValue>(list.item(0))->stringValue();
1275         localValue = downcast<CSSPrimitiveValue>(list.item(1));
1276     }
1277
1278     if (!localValue)
1279         return;
1280
1281     Color color;
1282     auto paintType = SVGPaintType::RGBColor;
1283     if (localValue->isURI()) {
1284         paintType = SVGPaintType::URI;
1285         url = downcast<CSSPrimitiveValue>(localValue)->stringValue();
1286     } else if (localValue->isValueID() && localValue->valueID() == CSSValueNone)
1287         paintType = url.isEmpty() ? SVGPaintType::None : SVGPaintType::URINone;
1288     else if (localValue->isValueID() && localValue->valueID() == CSSValueCurrentcolor) {
1289         color = styleResolver.style()->color();
1290         paintType = url.isEmpty() ? SVGPaintType::CurrentColor : SVGPaintType::URICurrentColor;
1291     } else {
1292         color = styleResolver.colorFromPrimitiveValue(*localValue);
1293         paintType = url.isEmpty() ? SVGPaintType::RGBColor : SVGPaintType::URIRGBColor;
1294     }
1295     svgStyle.setStrokePaint(paintType, color, url, styleResolver.applyPropertyToRegularStyle(), styleResolver.applyPropertyToVisitedLinkStyle());
1296 }
1297
1298 inline void StyleBuilderCustom::applyInitialContent(StyleResolver& styleResolver)
1299 {
1300     styleResolver.style()->clearContent();
1301 }
1302
1303 inline void StyleBuilderCustom::applyInheritContent(StyleResolver&)
1304 {
1305     // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
1306     // note is a reminder that eventually "inherit" needs to be supported.
1307 }
1308
1309 inline void StyleBuilderCustom::applyValueContent(StyleResolver& styleResolver, CSSValue& value)
1310 {
1311     if (is<CSSPrimitiveValue>(value)) {
1312         const auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
1313         ASSERT_UNUSED(primitiveValue, primitiveValue.valueID() == CSSValueNormal || primitiveValue.valueID() == CSSValueNone);
1314         styleResolver.style()->clearContent();
1315         return;
1316     }
1317
1318     bool didSet = false;
1319     for (auto& item : downcast<CSSValueList>(value)) {
1320         if (is<CSSImageGeneratorValue>(item)) {
1321             if (is<CSSGradientValue>(item))
1322                 styleResolver.style()->setContent(StyleGeneratedImage::create(downcast<CSSGradientValue>(item.get()).gradientWithStylesResolved(styleResolver)), didSet);
1323             else
1324                 styleResolver.style()->setContent(StyleGeneratedImage::create(downcast<CSSImageGeneratorValue>(item.get())), didSet);
1325             didSet = true;
1326         } else if (is<CSSImageSetValue>(item)) {
1327             styleResolver.style()->setContent(StyleCachedImage::create(item), didSet);
1328             didSet = true;
1329         }
1330
1331         if (is<CSSImageValue>(item)) {
1332             styleResolver.style()->setContent(StyleCachedImage::create(item), didSet);
1333             didSet = true;
1334             continue;
1335         }
1336
1337         if (!is<CSSPrimitiveValue>(item))
1338             continue;
1339
1340         auto& contentValue = downcast<CSSPrimitiveValue>(item.get());
1341         if (contentValue.isString()) {
1342             styleResolver.style()->setContent(contentValue.stringValue().impl(), didSet);
1343             didSet = true;
1344         } else if (contentValue.isAttr()) {
1345             // FIXME: Can a namespace be specified for an attr(foo)?
1346             if (styleResolver.style()->styleType() == PseudoId::None)
1347                 styleResolver.style()->setHasAttrContent();
1348             else
1349                 const_cast<RenderStyle*>(styleResolver.parentStyle())->setHasAttrContent();
1350             QualifiedName attr(nullAtom(), contentValue.stringValue().impl(), nullAtom());
1351             const AtomString& value = styleResolver.element()->getAttribute(attr);
1352             styleResolver.style()->setContent(value.isNull() ? emptyAtom() : value.impl(), didSet);
1353             didSet = true;
1354             // Register the fact that the attribute value affects the style.
1355             styleResolver.ruleSets().mutableFeatures().registerContentAttribute(attr.localName());
1356         } else if (contentValue.isCounter()) {
1357             auto* counterValue = contentValue.counterValue();
1358             ListStyleType listStyleType = ListStyleType::None;
1359             CSSValueID listStyleIdent = counterValue->listStyleIdent();
1360             if (listStyleIdent != CSSValueNone)
1361                 listStyleType = static_cast<ListStyleType>(listStyleIdent - CSSValueDisc);
1362             auto counter = makeUnique<CounterContent>(counterValue->identifier(), listStyleType, counterValue->separator());
1363             styleResolver.style()->setContent(WTFMove(counter), didSet);
1364             didSet = true;
1365         } else {
1366             switch (contentValue.valueID()) {
1367             case CSSValueOpenQuote:
1368                 styleResolver.style()->setContent(QuoteType::OpenQuote, didSet);
1369                 didSet = true;
1370                 break;
1371             case CSSValueCloseQuote:
1372                 styleResolver.style()->setContent(QuoteType::CloseQuote, didSet);
1373                 didSet = true;
1374                 break;
1375             case CSSValueNoOpenQuote:
1376                 styleResolver.style()->setContent(QuoteType::NoOpenQuote, didSet);
1377                 didSet = true;
1378                 break;
1379             case CSSValueNoCloseQuote:
1380                 styleResolver.style()->setContent(QuoteType::NoCloseQuote, didSet);
1381                 didSet = true;
1382                 break;
1383             default:
1384                 // normal and none do not have any effect.
1385                 break;
1386             }
1387         }
1388     }
1389     if (!didSet)
1390         styleResolver.style()->clearContent();
1391 }
1392
1393 inline void StyleBuilderCustom::applyInheritFontVariantLigatures(StyleResolver& styleResolver)
1394 {
1395     auto fontDescription = styleResolver.fontDescription();
1396     fontDescription.setVariantCommonLigatures(styleResolver.parentFontDescription().variantCommonLigatures());
1397     fontDescription.setVariantDiscretionaryLigatures(styleResolver.parentFontDescription().variantDiscretionaryLigatures());
1398     fontDescription.setVariantHistoricalLigatures(styleResolver.parentFontDescription().variantHistoricalLigatures());
1399     fontDescription.setVariantContextualAlternates(styleResolver.parentFontDescription().variantContextualAlternates());
1400     styleResolver.setFontDescription(WTFMove(fontDescription));
1401 }
1402
1403 inline void StyleBuilderCustom::applyInitialFontVariantLigatures(StyleResolver& styleResolver)
1404 {
1405     auto fontDescription = styleResolver.fontDescription();
1406     fontDescription.setVariantCommonLigatures(FontVariantLigatures::Normal);
1407     fontDescription.setVariantDiscretionaryLigatures(FontVariantLigatures::Normal);
1408     fontDescription.setVariantHistoricalLigatures(FontVariantLigatures::Normal);
1409     fontDescription.setVariantContextualAlternates(FontVariantLigatures::Normal);
1410     styleResolver.setFontDescription(WTFMove(fontDescription));
1411 }
1412
1413 inline void StyleBuilderCustom::applyValueFontVariantLigatures(StyleResolver& styleResolver, CSSValue& value)
1414 {
1415     auto fontDescription = styleResolver.fontDescription();
1416     auto variantLigatures = extractFontVariantLigatures(value);
1417     fontDescription.setVariantCommonLigatures(variantLigatures.commonLigatures);
1418     fontDescription.setVariantDiscretionaryLigatures(variantLigatures.discretionaryLigatures);
1419     fontDescription.setVariantHistoricalLigatures(variantLigatures.historicalLigatures);
1420     fontDescription.setVariantContextualAlternates(variantLigatures.contextualAlternates);
1421     styleResolver.setFontDescription(WTFMove(fontDescription));
1422 }
1423
1424 inline void StyleBuilderCustom::applyInheritFontVariantNumeric(StyleResolver& styleResolver)
1425 {
1426     auto fontDescription = styleResolver.fontDescription();
1427     fontDescription.setVariantNumericFigure(styleResolver.parentFontDescription().variantNumericFigure());
1428     fontDescription.setVariantNumericSpacing(styleResolver.parentFontDescription().variantNumericSpacing());
1429     fontDescription.setVariantNumericFraction(styleResolver.parentFontDescription().variantNumericFraction());
1430     fontDescription.setVariantNumericOrdinal(styleResolver.parentFontDescription().variantNumericOrdinal());
1431     fontDescription.setVariantNumericSlashedZero(styleResolver.parentFontDescription().variantNumericSlashedZero());
1432     styleResolver.setFontDescription(WTFMove(fontDescription));
1433 }
1434
1435 inline void StyleBuilderCustom::applyInitialFontVariantNumeric(StyleResolver& styleResolver)
1436 {
1437     auto fontDescription = styleResolver.fontDescription();
1438     fontDescription.setVariantNumericFigure(FontVariantNumericFigure::Normal);
1439     fontDescription.setVariantNumericSpacing(FontVariantNumericSpacing::Normal);
1440     fontDescription.setVariantNumericFraction(FontVariantNumericFraction::Normal);
1441     fontDescription.setVariantNumericOrdinal(FontVariantNumericOrdinal::Normal);
1442     fontDescription.setVariantNumericSlashedZero(FontVariantNumericSlashedZero::Normal);
1443     styleResolver.setFontDescription(WTFMove(fontDescription));
1444 }
1445
1446 inline void StyleBuilderCustom::applyValueFontVariantNumeric(StyleResolver& styleResolver, CSSValue& value)
1447 {
1448     auto fontDescription = styleResolver.fontDescription();
1449     auto variantNumeric = extractFontVariantNumeric(value);
1450     fontDescription.setVariantNumericFigure(variantNumeric.figure);
1451     fontDescription.setVariantNumericSpacing(variantNumeric.spacing);
1452     fontDescription.setVariantNumericFraction(variantNumeric.fraction);
1453     fontDescription.setVariantNumericOrdinal(variantNumeric.ordinal);
1454     fontDescription.setVariantNumericSlashedZero(variantNumeric.slashedZero);
1455     styleResolver.setFontDescription(WTFMove(fontDescription));
1456 }
1457
1458 inline void StyleBuilderCustom::applyInheritFontVariantEastAsian(StyleResolver& styleResolver)
1459 {
1460     auto fontDescription = styleResolver.fontDescription();
1461     fontDescription.setVariantEastAsianVariant(styleResolver.parentFontDescription().variantEastAsianVariant());
1462     fontDescription.setVariantEastAsianWidth(styleResolver.parentFontDescription().variantEastAsianWidth());
1463     fontDescription.setVariantEastAsianRuby(styleResolver.parentFontDescription().variantEastAsianRuby());
1464     styleResolver.setFontDescription(WTFMove(fontDescription));
1465 }
1466
1467 inline void StyleBuilderCustom::applyInitialFontVariantEastAsian(StyleResolver& styleResolver)
1468 {
1469     auto fontDescription = styleResolver.fontDescription();
1470     fontDescription.setVariantEastAsianVariant(FontVariantEastAsianVariant::Normal);
1471     fontDescription.setVariantEastAsianWidth(FontVariantEastAsianWidth::Normal);
1472     fontDescription.setVariantEastAsianRuby(FontVariantEastAsianRuby::Normal);
1473     styleResolver.setFontDescription(WTFMove(fontDescription));
1474 }
1475
1476 inline void StyleBuilderCustom::applyValueFontVariantEastAsian(StyleResolver& styleResolver, CSSValue& value)
1477 {
1478     auto fontDescription = styleResolver.fontDescription();
1479     auto variantEastAsian = extractFontVariantEastAsian(value);
1480     fontDescription.setVariantEastAsianVariant(variantEastAsian.variant);
1481     fontDescription.setVariantEastAsianWidth(variantEastAsian.width);
1482     fontDescription.setVariantEastAsianRuby(variantEastAsian.ruby);
1483     styleResolver.setFontDescription(WTFMove(fontDescription));
1484 }
1485
1486 inline void StyleBuilderCustom::applyInitialFontSize(StyleResolver& styleResolver)
1487 {
1488     auto fontDescription = styleResolver.style()->fontDescription();
1489     float size = Style::fontSizeForKeyword(CSSValueMedium, fontDescription.useFixedDefaultSize(), styleResolver.document());
1490
1491     if (size < 0)
1492         return;
1493
1494     fontDescription.setKeywordSizeFromIdentifier(CSSValueMedium);
1495     styleResolver.setFontSize(fontDescription, size);
1496     styleResolver.setFontDescription(WTFMove(fontDescription));
1497 }
1498
1499 inline void StyleBuilderCustom::applyInheritFontSize(StyleResolver& styleResolver)
1500 {
1501     const auto& parentFontDescription = styleResolver.parentStyle()->fontDescription();
1502     float size = parentFontDescription.specifiedSize();
1503
1504     if (size < 0)
1505         return;
1506
1507     auto fontDescription = styleResolver.style()->fontDescription();
1508     fontDescription.setKeywordSize(parentFontDescription.keywordSize());
1509     styleResolver.setFontSize(fontDescription, size);
1510     styleResolver.setFontDescription(WTFMove(fontDescription));
1511 }
1512
1513 // When the CSS keyword "larger" is used, this function will attempt to match within the keyword
1514 // table, and failing that, will simply multiply by 1.2.
1515 inline float StyleBuilderCustom::largerFontSize(float size)
1516 {
1517     // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to
1518     // the next size level.
1519     return size * 1.2f;
1520 }
1521
1522 // Like the previous function, but for the keyword "smaller".
1523 inline float StyleBuilderCustom::smallerFontSize(float size)
1524 {
1525     // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to
1526     // the next size level.
1527     return size / 1.2f;
1528 }
1529
1530 inline float StyleBuilderCustom::determineRubyTextSizeMultiplier(StyleResolver& styleResolver)
1531 {
1532     if (styleResolver.style()->rubyPosition() != RubyPosition::InterCharacter)
1533         return 0.5f;
1534
1535     // FIXME: This hack is to ensure tone marks are the same size as
1536     // the bopomofo. This code will go away if we make a special renderer
1537     // for the tone marks eventually.
1538     if (auto* element = styleResolver.state().element()) {
1539         for (auto& ancestor : ancestorsOfType<HTMLElement>(*element)) {
1540             if (ancestor.hasTagName(HTMLNames::rtTag))
1541                 return 1.0f;
1542         }
1543     }
1544     return 0.25f;
1545 }
1546
1547 inline void StyleBuilderCustom::applyInitialFontStyle(StyleResolver& styleResolver)
1548 {
1549     auto fontDescription = styleResolver.fontDescription();
1550     fontDescription.setItalic(FontCascadeDescription::initialItalic());
1551     fontDescription.setFontStyleAxis(FontCascadeDescription::initialFontStyleAxis());
1552     styleResolver.setFontDescription(WTFMove(fontDescription));
1553 }
1554
1555 inline void StyleBuilderCustom::applyInheritFontStyle(StyleResolver& styleResolver)
1556 {
1557     auto fontDescription = styleResolver.fontDescription();
1558     fontDescription.setItalic(styleResolver.parentFontDescription().italic());
1559     fontDescription.setFontStyleAxis(styleResolver.parentFontDescription().fontStyleAxis());
1560     styleResolver.setFontDescription(WTFMove(fontDescription));
1561 }
1562
1563 inline void StyleBuilderCustom::applyValueFontStyle(StyleResolver& styleResolver, CSSValue& value)
1564 {
1565     auto& fontStyleValue = downcast<CSSFontStyleValue>(value);
1566     auto fontDescription = styleResolver.fontDescription();
1567     fontDescription.setItalic(StyleBuilderConverter::convertFontStyleFromValue(fontStyleValue));
1568     fontDescription.setFontStyleAxis(fontStyleValue.fontStyleValue->valueID() == CSSValueItalic ? FontStyleAxis::ital : FontStyleAxis::slnt);
1569     styleResolver.setFontDescription(WTFMove(fontDescription));
1570 }
1571
1572 inline void StyleBuilderCustom::applyValueFontSize(StyleResolver& styleResolver, CSSValue& value)
1573 {
1574     auto fontDescription = styleResolver.style()->fontDescription();
1575     fontDescription.setKeywordSizeFromIdentifier(CSSValueInvalid);
1576
1577     float parentSize = 0;
1578     bool parentIsAbsoluteSize = false;
1579     if (auto* parentStyle = styleResolver.parentStyle()) {
1580         parentSize = parentStyle->fontDescription().specifiedSize();
1581         parentIsAbsoluteSize = parentStyle->fontDescription().isAbsoluteSize();
1582     }
1583
1584     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
1585     float size;
1586     if (CSSValueID ident = primitiveValue.valueID()) {
1587         fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize && (ident == CSSValueLarger || ident == CSSValueSmaller || ident == CSSValueWebkitRubyText));
1588
1589         // Keywords are being used.
1590         switch (ident) {
1591         case CSSValueXxSmall:
1592         case CSSValueXSmall:
1593         case CSSValueSmall:
1594         case CSSValueMedium:
1595         case CSSValueLarge:
1596         case CSSValueXLarge:
1597         case CSSValueXxLarge:
1598         case CSSValueWebkitXxxLarge:
1599             size = Style::fontSizeForKeyword(ident, fontDescription.useFixedDefaultSize(), styleResolver.document());
1600             fontDescription.setKeywordSizeFromIdentifier(ident);
1601             break;
1602         case CSSValueLarger:
1603             size = largerFontSize(parentSize);
1604             break;
1605         case CSSValueSmaller:
1606             size = smallerFontSize(parentSize);
1607             break;
1608         case CSSValueWebkitRubyText:
1609             size = determineRubyTextSizeMultiplier(styleResolver) * parentSize;
1610             break;
1611         default:
1612             return;
1613         }
1614     } else {
1615         fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize || !(primitiveValue.isPercentage() || primitiveValue.isFontRelativeLength()));
1616         if (primitiveValue.isLength()) {
1617             size = primitiveValue.computeLength<float>(CSSToLengthConversionData(styleResolver.parentStyle(), styleResolver.rootElementStyle(), styleResolver.document().renderView(), 1.0f, true));
1618             styleResolver.state().setFontSizeHasViewportUnits(primitiveValue.isViewportPercentageLength());
1619         } else if (primitiveValue.isPercentage())
1620             size = (primitiveValue.floatValue() * parentSize) / 100.0f;
1621         else if (primitiveValue.isCalculatedPercentageWithLength()) {
1622             const auto& conversionData = styleResolver.state().cssToLengthConversionData();
1623             CSSToLengthConversionData parentConversionData { styleResolver.parentStyle(), conversionData.rootStyle(), styleResolver.document().renderView(), 1.0f, true };
1624             size = primitiveValue.cssCalcValue()->createCalculationValue(parentConversionData)->evaluate(parentSize);
1625         } else
1626             return;
1627     }
1628
1629     if (size < 0)
1630         return;
1631
1632     styleResolver.setFontSize(fontDescription, std::min(maximumAllowedFontSize, size));
1633     styleResolver.setFontDescription(WTFMove(fontDescription));
1634 }
1635
1636 inline void StyleBuilderCustom::applyInitialGridTemplateAreas(StyleResolver& styleResolver)
1637 {
1638     styleResolver.style()->setNamedGridArea(RenderStyle::initialNamedGridArea());
1639     styleResolver.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount());
1640     styleResolver.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount());
1641 }
1642
1643 inline void StyleBuilderCustom::applyInheritGridTemplateAreas(StyleResolver& styleResolver)
1644 {
1645     styleResolver.style()->setNamedGridArea(styleResolver.parentStyle()->namedGridArea());
1646     styleResolver.style()->setNamedGridAreaRowCount(styleResolver.parentStyle()->namedGridAreaRowCount());
1647     styleResolver.style()->setNamedGridAreaColumnCount(styleResolver.parentStyle()->namedGridAreaColumnCount());
1648 }
1649
1650 inline void StyleBuilderCustom::applyValueGridTemplateAreas(StyleResolver& styleResolver, CSSValue& value)
1651 {
1652     if (is<CSSPrimitiveValue>(value)) {
1653         ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
1654         return;
1655     }
1656
1657     auto& gridTemplateAreasValue = downcast<CSSGridTemplateAreasValue>(value);
1658     const NamedGridAreaMap& newNamedGridAreas = gridTemplateAreasValue.gridAreaMap();
1659
1660     NamedGridLinesMap namedGridColumnLines = styleResolver.style()->namedGridColumnLines();
1661     NamedGridLinesMap namedGridRowLines = styleResolver.style()->namedGridRowLines();
1662     StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridColumnLines, ForColumns);
1663     StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridRowLines, ForRows);
1664     styleResolver.style()->setNamedGridColumnLines(namedGridColumnLines);
1665     styleResolver.style()->setNamedGridRowLines(namedGridRowLines);
1666
1667     styleResolver.style()->setNamedGridArea(gridTemplateAreasValue.gridAreaMap());
1668     styleResolver.style()->setNamedGridAreaRowCount(gridTemplateAreasValue.rowCount());
1669     styleResolver.style()->setNamedGridAreaColumnCount(gridTemplateAreasValue.columnCount());
1670 }
1671
1672 inline void StyleBuilderCustom::applyInitialGridTemplateColumns(StyleResolver& styleResolver)
1673 {
1674     styleResolver.style()->setGridColumns(RenderStyle::initialGridColumns());
1675     styleResolver.style()->setNamedGridColumnLines(RenderStyle::initialNamedGridColumnLines());
1676     styleResolver.style()->setOrderedNamedGridColumnLines(RenderStyle::initialOrderedNamedGridColumnLines());
1677 }
1678
1679 inline void StyleBuilderCustom::applyInheritGridTemplateColumns(StyleResolver& styleResolver)
1680 {
1681     styleResolver.style()->setGridColumns(styleResolver.parentStyle()->gridColumns());
1682     styleResolver.style()->setNamedGridColumnLines(styleResolver.parentStyle()->namedGridColumnLines());
1683     styleResolver.style()->setOrderedNamedGridColumnLines(styleResolver.parentStyle()->orderedNamedGridColumnLines());
1684 }
1685
1686 #define SET_TRACKS_DATA(tracksData, style, TrackType) \
1687     style->setGrid##TrackType##s(tracksData.m_trackSizes); \
1688     style->setNamedGrid##TrackType##Lines(tracksData.m_namedGridLines); \
1689     style->setOrderedNamedGrid##TrackType##Lines(tracksData.m_orderedNamedGridLines); \
1690     style->setGridAutoRepeat##TrackType##s(tracksData.m_autoRepeatTrackSizes); \
1691     style->setGridAutoRepeat##TrackType##sInsertionPoint(tracksData.m_autoRepeatInsertionPoint); \
1692     style->setAutoRepeatNamedGrid##TrackType##Lines(tracksData.m_autoRepeatNamedGridLines); \
1693     style->setAutoRepeatOrderedNamedGrid##TrackType##Lines(tracksData.m_autoRepeatOrderedNamedGridLines); \
1694     style->setGridAutoRepeat##TrackType##sType(tracksData.m_autoRepeatType); \
1695     style->setGridAutoRepeat##TrackType##sInsertionPoint(tracksData.m_autoRepeatInsertionPoint);
1696
1697 inline void StyleBuilderCustom::applyValueGridTemplateColumns(StyleResolver& styleResolver, CSSValue& value)
1698 {
1699     StyleBuilderConverter::TracksData tracksData;
1700     if (!StyleBuilderConverter::createGridTrackList(value, tracksData, styleResolver))
1701         return;
1702     const NamedGridAreaMap& namedGridAreas = styleResolver.style()->namedGridArea();
1703     if (!namedGridAreas.isEmpty())
1704         StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(namedGridAreas, tracksData.m_namedGridLines, ForColumns);
1705
1706     SET_TRACKS_DATA(tracksData, styleResolver.style(), Column);
1707 }
1708
1709 inline void StyleBuilderCustom::applyInitialGridTemplateRows(StyleResolver& styleResolver)
1710 {
1711     styleResolver.style()->setGridRows(RenderStyle::initialGridRows());
1712     styleResolver.style()->setNamedGridRowLines(RenderStyle::initialNamedGridRowLines());
1713     styleResolver.style()->setOrderedNamedGridRowLines(RenderStyle::initialOrderedNamedGridRowLines());
1714 }
1715
1716 inline void StyleBuilderCustom::applyInheritGridTemplateRows(StyleResolver& styleResolver)
1717 {
1718     styleResolver.style()->setGridRows(styleResolver.parentStyle()->gridRows());
1719     styleResolver.style()->setNamedGridRowLines(styleResolver.parentStyle()->namedGridRowLines());
1720     styleResolver.style()->setOrderedNamedGridRowLines(styleResolver.parentStyle()->orderedNamedGridRowLines());
1721 }
1722
1723 inline void StyleBuilderCustom::applyValueGridTemplateRows(StyleResolver& styleResolver, CSSValue& value)
1724 {
1725     StyleBuilderConverter::TracksData tracksData;
1726     if (!StyleBuilderConverter::createGridTrackList(value, tracksData, styleResolver))
1727         return;
1728     const NamedGridAreaMap& namedGridAreas = styleResolver.style()->namedGridArea();
1729     if (!namedGridAreas.isEmpty())
1730         StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(namedGridAreas, tracksData.m_namedGridLines, ForRows);
1731
1732     SET_TRACKS_DATA(tracksData, styleResolver.style(), Row);
1733 }
1734
1735 void StyleBuilderCustom::applyValueAlt(StyleResolver& styleResolver, CSSValue& value)
1736 {
1737     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
1738     if (primitiveValue.isString())
1739         styleResolver.style()->setContentAltText(primitiveValue.stringValue());
1740     else if (primitiveValue.isAttr()) {
1741         // FIXME: Can a namespace be specified for an attr(foo)?
1742         if (styleResolver.style()->styleType() == PseudoId::None)
1743             styleResolver.style()->setUnique();
1744         else
1745             const_cast<RenderStyle*>(styleResolver.parentStyle())->setUnique();
1746
1747         QualifiedName attr(nullAtom(), primitiveValue.stringValue(), nullAtom());
1748         const AtomString& value = styleResolver.element()->getAttribute(attr);
1749         styleResolver.style()->setContentAltText(value.isNull() ? emptyAtom() : value);
1750
1751         // Register the fact that the attribute value affects the style.
1752         styleResolver.ruleSets().mutableFeatures().registerContentAttribute(attr.localName());
1753     } else
1754         styleResolver.style()->setContentAltText(emptyAtom());
1755 }
1756
1757 inline void StyleBuilderCustom::applyValueWillChange(StyleResolver& styleResolver, CSSValue& value)
1758 {
1759     if (is<CSSPrimitiveValue>(value)) {
1760         ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueAuto);
1761         styleResolver.style()->setWillChange(nullptr);
1762         return;
1763     }
1764
1765     auto willChange = WillChangeData::create();
1766     for (auto& item : downcast<CSSValueList>(value)) {
1767         if (!is<CSSPrimitiveValue>(item))
1768             continue;
1769         auto& primitiveValue = downcast<CSSPrimitiveValue>(item.get());
1770         switch (primitiveValue.valueID()) {
1771         case CSSValueScrollPosition:
1772             willChange->addFeature(WillChangeData::Feature::ScrollPosition);
1773             break;
1774         case CSSValueContents:
1775             willChange->addFeature(WillChangeData::Feature::Contents);
1776             break;
1777         default:
1778             if (primitiveValue.isPropertyID())
1779                 willChange->addFeature(WillChangeData::Feature::Property, primitiveValue.propertyID());
1780             break;
1781         }
1782     }
1783     styleResolver.style()->setWillChange(WTFMove(willChange));
1784 }
1785
1786 inline void StyleBuilderCustom::applyValueStrokeWidth(StyleResolver& styleResolver, CSSValue& value)
1787 {
1788     styleResolver.style()->setStrokeWidth(StyleBuilderConverter::convertLength(styleResolver, value));
1789     styleResolver.style()->setHasExplicitlySetStrokeWidth(true);
1790 }
1791
1792 inline void StyleBuilderCustom::applyValueStrokeColor(StyleResolver& styleResolver, CSSValue& value)
1793 {
1794     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
1795     if (styleResolver.applyPropertyToRegularStyle())
1796         styleResolver.style()->setStrokeColor(styleResolver.colorFromPrimitiveValue(primitiveValue, /* forVisitedLink */ false));
1797     if (styleResolver.applyPropertyToVisitedLinkStyle())
1798         styleResolver.style()->setVisitedLinkStrokeColor(styleResolver.colorFromPrimitiveValue(primitiveValue, /* forVisitedLink */ true));
1799     styleResolver.style()->setHasExplicitlySetStrokeColor(true);
1800 }
1801
1802 inline void StyleBuilderCustom::applyInitialCustomProperty(StyleResolver& styleResolver, const CSSRegisteredCustomProperty* registered, const AtomString& name)
1803 {
1804     if (registered && registered->initialValue()) {
1805         auto initialValue = registered->initialValueCopy();
1806         applyValueCustomProperty(styleResolver, registered, *initialValue);
1807         return;
1808     }
1809
1810     auto invalid = CSSCustomPropertyValue::createUnresolved(name, CSSValueInvalid);
1811     applyValueCustomProperty(styleResolver, registered, invalid.get());
1812 }
1813
1814 inline void StyleBuilderCustom::applyInheritCustomProperty(StyleResolver& styleResolver, const CSSRegisteredCustomProperty* registered, const AtomString& name)
1815 {
1816     auto* parentValue = styleResolver.parentStyle() ? styleResolver.parentStyle()->inheritedCustomProperties().get(name) : nullptr;
1817     if (parentValue && !(registered && !registered->inherits))
1818         applyValueCustomProperty(styleResolver, registered, *parentValue);
1819     else
1820         applyInitialCustomProperty(styleResolver, registered, name);
1821 }
1822
1823 inline void StyleBuilderCustom::applyValueCustomProperty(StyleResolver& styleResolver, const CSSRegisteredCustomProperty* registered, CSSCustomPropertyValue& value)
1824 {
1825     ASSERT(value.isResolved());
1826     const auto& name = value.name();
1827
1828     if (!registered || registered->inherits)
1829         styleResolver.style()->setInheritedCustomPropertyValue(name, makeRef(value));
1830     else
1831         styleResolver.style()->setNonInheritedCustomPropertyValue(name, makeRef(value));
1832 }
1833
1834 } // namespace WebCore