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