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