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