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