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