e2956030411816f3636d249c2636faa37c870646
[WebKit-https.git] / Source / WebCore / css / StyleBuilderCustom.h
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  * Copyright (C) 2014 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #ifndef StyleBuilderCustom_h
28 #define StyleBuilderCustom_h
29
30 #include "CSSAspectRatioValue.h"
31 #include "CSSCursorImageValue.h"
32 #include "CSSFontFamily.h"
33 #include "CSSFontValue.h"
34 #include "CSSGradientValue.h"
35 #include "CSSShadowValue.h"
36 #include "Counter.h"
37 #include "CounterContent.h"
38 #include "CursorList.h"
39 #include "DashboardRegion.h"
40 #include "ElementAncestorIterator.h"
41 #include "Frame.h"
42 #include "HTMLElement.h"
43 #include "LocaleToScriptMapping.h"
44 #include "Rect.h"
45 #include "RenderTheme.h"
46 #include "SVGElement.h"
47 #include "SVGRenderStyle.h"
48 #include "StyleBuilderConverter.h"
49 #include "StyleFontSizeFunctions.h"
50 #include "StyleGeneratedImage.h"
51 #include "StyleResolver.h"
52
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(WebkitFontVariantLigatures);
93 #if ENABLE(CSS_GRID_LAYOUT)
94     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitGridTemplateAreas);
95     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitGridTemplateColumns);
96     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitGridTemplateRows);
97 #endif // ENABLE(CSS_GRID_LAYOUT)
98     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitMaskBoxImageOutset);
99     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitMaskBoxImageRepeat);
100     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitMaskBoxImageSlice);
101     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitMaskBoxImageWidth);
102     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitSvgShadow);
103     DECLARE_PROPERTY_CUSTOM_HANDLERS(WebkitTextEmphasisStyle);
104     DECLARE_PROPERTY_CUSTOM_HANDLERS(Zoom);
105
106     // Custom handling of initial + inherit value setting only.
107     static void applyInitialWebkitMaskImage(StyleResolver&) { }
108     static void applyInheritWebkitMaskImage(StyleResolver&) { }
109     static void applyInitialWebkitFontFeatureSettings(StyleResolver&) { }
110     static void applyInheritWebkitFontFeatureSettings(StyleResolver&) { }
111
112     // Custom handling of inherit + value setting only.
113     static void applyInheritDisplay(StyleResolver&);
114     static void applyValueDisplay(StyleResolver&, CSSValue&);
115
116     // Custom handling of value setting only.
117     static void applyValueBaselineShift(StyleResolver&, CSSValue&);
118     static void applyValueDirection(StyleResolver&, CSSValue&);
119     static void applyValueVerticalAlign(StyleResolver&, CSSValue&);
120 #if ENABLE(DASHBOARD_SUPPORT)
121     static void applyValueWebkitDashboardRegion(StyleResolver&, CSSValue&);
122 #endif
123     static void applyValueWebkitJustifySelf(StyleResolver&, CSSValue&);
124     static void applyValueWebkitLocale(StyleResolver&, CSSValue&);
125     static void applyValueWebkitTextOrientation(StyleResolver&, CSSValue&);
126 #if ENABLE(IOS_TEXT_AUTOSIZING)
127     static void applyValueWebkitTextSizeAdjust(StyleResolver&, CSSValue&);
128 #endif
129     static void applyValueWebkitWritingMode(StyleResolver&, CSSValue&);
130     static void applyValueAlt(StyleResolver&, CSSValue&);
131 #if ENABLE(CSS_SCROLL_SNAP)
132     static void applyInitialWebkitScrollSnapPointsX(StyleResolver&);
133     static void applyInheritWebkitScrollSnapPointsX(StyleResolver&);
134     static void applyInitialWebkitScrollSnapPointsY(StyleResolver&);
135     static void applyInheritWebkitScrollSnapPointsY(StyleResolver&);
136 #endif
137
138 private:
139     static void resetEffectiveZoom(StyleResolver&);
140
141     static Length mmLength(double mm);
142     static Length inchLength(double inch);
143     static bool getPageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height);
144
145     template <CSSPropertyID id>
146     static void applyTextOrBoxShadowValue(StyleResolver&, CSSValue&);
147     static bool isValidDisplayValue(StyleResolver&, EDisplay);
148
149     enum CounterBehavior {Increment = 0, Reset};
150     template <CounterBehavior counterBehavior>
151     static void applyInheritCounter(StyleResolver&);
152     template <CounterBehavior counterBehavior>
153     static void applyValueCounter(StyleResolver&, CSSValue&);
154
155     static float largerFontSize(float size);
156     static float smallerFontSize(float size);
157     static float determineRubyTextSizeMultiplier(StyleResolver&);
158 };
159
160 inline void StyleBuilderCustom::applyValueDirection(StyleResolver& styleResolver, CSSValue& value)
161 {
162     styleResolver.style()->setDirection(downcast<CSSPrimitiveValue>(value));
163
164     Element* element = styleResolver.element();
165     if (element && styleResolver.element() == element->document().documentElement())
166         element->document().setDirectionSetOnDocumentElement(true);
167 }
168
169 inline void StyleBuilderCustom::resetEffectiveZoom(StyleResolver& styleResolver)
170 {
171     // Reset the zoom in effect. This allows the setZoom method to accurately compute a new zoom in effect.
172     styleResolver.setEffectiveZoom(styleResolver.parentStyle() ? styleResolver.parentStyle()->effectiveZoom() : RenderStyle::initialZoom());
173 }
174
175 inline void StyleBuilderCustom::applyInitialZoom(StyleResolver& styleResolver)
176 {
177     resetEffectiveZoom(styleResolver);
178     styleResolver.setZoom(RenderStyle::initialZoom());
179 }
180
181 inline void StyleBuilderCustom::applyInheritZoom(StyleResolver& styleResolver)
182 {
183     resetEffectiveZoom(styleResolver);
184     styleResolver.setZoom(styleResolver.parentStyle()->zoom());
185 }
186
187 inline void StyleBuilderCustom::applyValueZoom(StyleResolver& styleResolver, CSSValue& value)
188 {
189     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
190
191     if (primitiveValue.getValueID() == CSSValueNormal) {
192         resetEffectiveZoom(styleResolver);
193         styleResolver.setZoom(RenderStyle::initialZoom());
194     } else if (primitiveValue.getValueID() == CSSValueReset) {
195         styleResolver.setEffectiveZoom(RenderStyle::initialZoom());
196         styleResolver.setZoom(RenderStyle::initialZoom());
197     } else if (primitiveValue.getValueID() == CSSValueDocument) {
198         float docZoom = styleResolver.rootElementStyle() ? styleResolver.rootElementStyle()->zoom() : RenderStyle::initialZoom();
199         styleResolver.setEffectiveZoom(docZoom);
200         styleResolver.setZoom(docZoom);
201     } else if (primitiveValue.isPercentage()) {
202         resetEffectiveZoom(styleResolver);
203         if (float percent = primitiveValue.getFloatValue())
204             styleResolver.setZoom(percent / 100.0f);
205     } else if (primitiveValue.isNumber()) {
206         resetEffectiveZoom(styleResolver);
207         if (float number = primitiveValue.getFloatValue())
208             styleResolver.setZoom(number);
209     }
210 }
211 inline Length StyleBuilderCustom::mmLength(double mm)
212 {
213     Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(mm, CSSPrimitiveValue::CSS_MM));
214     return value.get().computeLength<Length>(CSSToLengthConversionData());
215 }
216 inline Length StyleBuilderCustom::inchLength(double inch)
217 {
218     Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(inch, CSSPrimitiveValue::CSS_IN));
219     return value.get().computeLength<Length>(CSSToLengthConversionData());
220 }
221 bool StyleBuilderCustom::getPageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height)
222 {
223     static NeverDestroyed<Length> a5Width(mmLength(148));
224     static NeverDestroyed<Length> a5Height(mmLength(210));
225     static NeverDestroyed<Length> a4Width(mmLength(210));
226     static NeverDestroyed<Length> a4Height(mmLength(297));
227     static NeverDestroyed<Length> a3Width(mmLength(297));
228     static NeverDestroyed<Length> a3Height(mmLength(420));
229     static NeverDestroyed<Length> b5Width(mmLength(176));
230     static NeverDestroyed<Length> b5Height(mmLength(250));
231     static NeverDestroyed<Length> b4Width(mmLength(250));
232     static NeverDestroyed<Length> b4Height(mmLength(353));
233     static NeverDestroyed<Length> letterWidth(inchLength(8.5));
234     static NeverDestroyed<Length> letterHeight(inchLength(11));
235     static NeverDestroyed<Length> legalWidth(inchLength(8.5));
236     static NeverDestroyed<Length> legalHeight(inchLength(14));
237     static NeverDestroyed<Length> ledgerWidth(inchLength(11));
238     static NeverDestroyed<Length> ledgerHeight(inchLength(17));
239
240     if (!pageSizeName)
241         return false;
242
243     switch (pageSizeName->getValueID()) {
244     case CSSValueA5:
245         width = a5Width;
246         height = a5Height;
247         break;
248     case CSSValueA4:
249         width = a4Width;
250         height = a4Height;
251         break;
252     case CSSValueA3:
253         width = a3Width;
254         height = a3Height;
255         break;
256     case CSSValueB5:
257         width = b5Width;
258         height = b5Height;
259         break;
260     case CSSValueB4:
261         width = b4Width;
262         height = b4Height;
263         break;
264     case CSSValueLetter:
265         width = letterWidth;
266         height = letterHeight;
267         break;
268     case CSSValueLegal:
269         width = legalWidth;
270         height = legalHeight;
271         break;
272     case CSSValueLedger:
273         width = ledgerWidth;
274         height = ledgerHeight;
275         break;
276     default:
277         return false;
278     }
279
280     if (pageOrientation) {
281         switch (pageOrientation->getValueID()) {
282         case CSSValueLandscape:
283             std::swap(width, height);
284             break;
285         case CSSValuePortrait:
286             // Nothing to do.
287             break;
288         default:
289             return false;
290         }
291     }
292     return true;
293 }
294
295 inline void StyleBuilderCustom::applyValueVerticalAlign(StyleResolver& styleResolver, CSSValue& value)
296 {
297     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
298     if (primitiveValue.getValueID())
299         styleResolver.style()->setVerticalAlign(primitiveValue);
300     else
301         styleResolver.style()->setVerticalAlignLength(primitiveValue.convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(styleResolver.state().cssToLengthConversionData()));
302 }
303
304 #if ENABLE(DASHBOARD_SUPPORT)
305 static Length convertToIntLength(const CSSPrimitiveValue* primitiveValue, const CSSToLengthConversionData& conversionData)
306 {
307     return primitiveValue ? primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(conversionData) : Length(Undefined);
308 }
309
310 inline void StyleBuilderCustom::applyValueWebkitDashboardRegion(StyleResolver& styleResolver, CSSValue& value)
311 {
312     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
313     if (primitiveValue.getValueID() == CSSValueNone) {
314         styleResolver.style()->setDashboardRegions(RenderStyle::noneDashboardRegions());
315         return;
316     }
317
318     DashboardRegion* region = primitiveValue.getDashboardRegionValue();
319     if (!region)
320         return;
321
322     DashboardRegion* first = region;
323     while (region) {
324         Length top = convertToIntLength(region->top(), styleResolver.state().cssToLengthConversionData().copyWithAdjustedZoom(1.0f));
325         Length right = convertToIntLength(region->right(), styleResolver.state().cssToLengthConversionData().copyWithAdjustedZoom(1.0f));
326         Length bottom = convertToIntLength(region->bottom(), styleResolver.state().cssToLengthConversionData().copyWithAdjustedZoom(1.0f));
327         Length left = convertToIntLength(region->left(), styleResolver.state().cssToLengthConversionData().copyWithAdjustedZoom(1.0f));
328
329         if (top.isUndefined())
330             top = Length();
331         if (right.isUndefined())
332             right = Length();
333         if (bottom.isUndefined())
334             bottom = Length();
335         if (left.isUndefined())
336             left = Length();
337
338         if (region->m_isCircle)
339             styleResolver.style()->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
340         else if (region->m_isRectangle)
341             styleResolver.style()->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
342         region = region->m_next.get();
343     }
344
345     styleResolver.document().setHasAnnotatedRegions(true);
346 }
347 #endif // ENABLE(DASHBOARD_SUPPORT)
348
349 #if ENABLE(CSS_IMAGE_RESOLUTION)
350 inline void StyleBuilderCustom::applyInheritImageResolution(StyleResolver& styleResolver)
351 {
352     styleResolver.style()->setImageResolutionSource(styleResolver.parentStyle()->imageResolutionSource());
353     styleResolver.style()->setImageResolutionSnap(styleResolver.parentStyle()->imageResolutionSnap());
354     styleResolver.style()->setImageResolution(styleResolver.parentStyle()->imageResolution());
355 }
356
357 inline void StyleBuilderCustom::applyInitialImageResolution(StyleResolver& styleResolver)
358 {
359     styleResolver.style()->setImageResolutionSource(RenderStyle::initialImageResolutionSource());
360     styleResolver.style()->setImageResolutionSnap(RenderStyle::initialImageResolutionSnap());
361     styleResolver.style()->setImageResolution(RenderStyle::initialImageResolution());
362 }
363
364 inline void StyleBuilderCustom::applyValueImageResolution(StyleResolver& styleResolver, CSSValue& value)
365 {
366     ImageResolutionSource source = RenderStyle::initialImageResolutionSource();
367     ImageResolutionSnap snap = RenderStyle::initialImageResolutionSnap();
368     double resolution = RenderStyle::initialImageResolution();
369     for (auto& item : downcast<CSSValueList>(value)) {
370         CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(item.get());
371         if (primitiveValue.getValueID() == CSSValueFromImage)
372             source = ImageResolutionFromImage;
373         else if (primitiveValue.getValueID() == CSSValueSnap)
374             snap = ImageResolutionSnapPixels;
375         else
376             resolution = primitiveValue.getDoubleValue(CSSPrimitiveValue::CSS_DPPX);
377     }
378     styleResolver.style()->setImageResolutionSource(source);
379     styleResolver.style()->setImageResolutionSnap(snap);
380     styleResolver.style()->setImageResolution(resolution);
381 }
382 #endif // ENABLE(CSS_IMAGE_RESOLUTION)
383
384 inline void StyleBuilderCustom::applyInheritSize(StyleResolver&) { }
385 inline void StyleBuilderCustom::applyInitialSize(StyleResolver&) { }
386 inline void StyleBuilderCustom::applyValueSize(StyleResolver& styleResolver, CSSValue& value)
387 {
388     styleResolver.style()->resetPageSizeType();
389     Length width;
390     Length height;
391     PageSizeType pageSizeType = PAGE_SIZE_AUTO;
392     if (!is<CSSValueList>(value))
393         return;
394
395     auto& valueList = downcast<CSSValueList>(value);
396     switch (valueList.length()) {
397     case 2: {
398         CSSValue* firstValue = valueList.itemWithoutBoundsCheck(0);
399         CSSValue* secondValue = valueList.itemWithoutBoundsCheck(1);
400         // <length>{2} | <page-size> <orientation>
401         if (!is<CSSPrimitiveValue>(*firstValue) || !is<CSSPrimitiveValue>(*secondValue))
402             return;
403         auto& firstPrimitiveValue = downcast<CSSPrimitiveValue>(*firstValue);
404         auto& secondPrimitiveValue = downcast<CSSPrimitiveValue>(*secondValue);
405         if (firstPrimitiveValue.isLength()) {
406             // <length>{2}
407             if (!secondPrimitiveValue.isLength())
408                 return;
409             CSSToLengthConversionData conversionData = styleResolver.state().cssToLengthConversionData().copyWithAdjustedZoom(1.0f);
410             width = firstPrimitiveValue.computeLength<Length>(conversionData);
411             height = secondPrimitiveValue.computeLength<Length>(conversionData);
412         } else {
413             // <page-size> <orientation>
414             // The value order is guaranteed. See CSSParser::parseSizeParameter.
415             if (!getPageSizeFromName(&firstPrimitiveValue, &secondPrimitiveValue, width, height))
416                 return;
417         }
418         pageSizeType = PAGE_SIZE_RESOLVED;
419         break;
420     }
421     case 1: {
422         CSSValue* value = valueList.itemWithoutBoundsCheck(0);
423         // <length> | auto | <page-size> | [ portrait | landscape]
424         if (!is<CSSPrimitiveValue>(*value))
425             return;
426         auto& primitiveValue = downcast<CSSPrimitiveValue>(*value);
427         if (primitiveValue.isLength()) {
428             // <length>
429             pageSizeType = PAGE_SIZE_RESOLVED;
430             width = height = primitiveValue.computeLength<Length>(styleResolver.state().cssToLengthConversionData().copyWithAdjustedZoom(1.0f));
431         } else {
432             switch (primitiveValue.getValueID()) {
433             case 0:
434                 return;
435             case CSSValueAuto:
436                 pageSizeType = PAGE_SIZE_AUTO;
437                 break;
438             case CSSValuePortrait:
439                 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT;
440                 break;
441             case CSSValueLandscape:
442                 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE;
443                 break;
444             default:
445                 // <page-size>
446                 pageSizeType = PAGE_SIZE_RESOLVED;
447                 if (!getPageSizeFromName(&primitiveValue, nullptr, width, height))
448                     return;
449             }
450         }
451         break;
452     }
453     default:
454         return;
455     }
456     styleResolver.style()->setPageSizeType(pageSizeType);
457     styleResolver.style()->setPageSize(LengthSize(width, height));
458 }
459
460 inline void StyleBuilderCustom::applyInheritTextIndent(StyleResolver& styleResolver)
461 {
462     styleResolver.style()->setTextIndent(styleResolver.parentStyle()->textIndent());
463 #if ENABLE(CSS3_TEXT)
464     styleResolver.style()->setTextIndentLine(styleResolver.parentStyle()->textIndentLine());
465     styleResolver.style()->setTextIndentType(styleResolver.parentStyle()->textIndentType());
466 #endif
467 }
468
469 inline void StyleBuilderCustom::applyInitialTextIndent(StyleResolver& styleResolver)
470 {
471     styleResolver.style()->setTextIndent(RenderStyle::initialTextIndent());
472 #if ENABLE(CSS3_TEXT)
473     styleResolver.style()->setTextIndentLine(RenderStyle::initialTextIndentLine());
474     styleResolver.style()->setTextIndentType(RenderStyle::initialTextIndentType());
475 #endif
476 }
477
478 inline void StyleBuilderCustom::applyValueTextIndent(StyleResolver& styleResolver, CSSValue& value)
479 {
480     Length lengthOrPercentageValue;
481 #if ENABLE(CSS3_TEXT)
482     TextIndentLine textIndentLineValue = RenderStyle::initialTextIndentLine();
483     TextIndentType textIndentTypeValue = RenderStyle::initialTextIndentType();
484 #endif
485     for (auto& item : downcast<CSSValueList>(value)) {
486         auto& primitiveValue = downcast<CSSPrimitiveValue>(item.get());
487         if (!primitiveValue.getValueID())
488             lengthOrPercentageValue = primitiveValue.convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(styleResolver.state().cssToLengthConversionData());
489 #if ENABLE(CSS3_TEXT)
490         else if (primitiveValue.getValueID() == CSSValueWebkitEachLine)
491             textIndentLineValue = TextIndentEachLine;
492         else if (primitiveValue.getValueID() == CSSValueWebkitHanging)
493             textIndentTypeValue = TextIndentHanging;
494 #endif
495     }
496
497     if (lengthOrPercentageValue.isUndefined())
498         return;
499
500     styleResolver.style()->setTextIndent(lengthOrPercentageValue);
501 #if ENABLE(CSS3_TEXT)
502     styleResolver.style()->setTextIndentLine(textIndentLineValue);
503     styleResolver.style()->setTextIndentType(textIndentTypeValue);
504 #endif
505 }
506
507 enum BorderImageType { BorderImage, WebkitMaskBoxImage };
508 enum BorderImageModifierType { Outset, Repeat, Slice, Width };
509 template <BorderImageType type, BorderImageModifierType modifier>
510 class ApplyPropertyBorderImageModifier {
511 public:
512     static void applyInheritValue(StyleResolver& styleResolver)
513     {
514         NinePieceImage image(getValue(styleResolver.style()));
515         switch (modifier) {
516         case Outset:
517             image.copyOutsetFrom(getValue(styleResolver.parentStyle()));
518             break;
519         case Repeat:
520             image.copyRepeatFrom(getValue(styleResolver.parentStyle()));
521             break;
522         case Slice:
523             image.copyImageSlicesFrom(getValue(styleResolver.parentStyle()));
524             break;
525         case Width:
526             image.copyBorderSlicesFrom(getValue(styleResolver.parentStyle()));
527             break;
528         }
529         setValue(styleResolver.style(), image);
530     }
531
532     static void applyInitialValue(StyleResolver& styleResolver)
533     {
534         NinePieceImage image(getValue(styleResolver.style()));
535         switch (modifier) {
536         case Outset:
537             image.setOutset(LengthBox(0));
538             break;
539         case Repeat:
540             image.setHorizontalRule(StretchImageRule);
541             image.setVerticalRule(StretchImageRule);
542             break;
543         case Slice:
544             // Masks have a different initial value for slices. Preserve the value of 0 for backwards compatibility.
545             image.setImageSlices(type == BorderImage ? LengthBox(Length(100, Percent), Length(100, Percent), Length(100, Percent), Length(100, Percent)) : LengthBox());
546             image.setFill(false);
547             break;
548         case Width:
549             // Masks have a different initial value for widths. They use an 'auto' value rather than trying to fit to the border.
550             image.setBorderSlices(type == BorderImage ? LengthBox(Length(1, Relative), Length(1, Relative), Length(1, Relative), Length(1, Relative)) : LengthBox());
551             break;
552         }
553         setValue(styleResolver.style(), image);
554     }
555
556     static void applyValue(StyleResolver& styleResolver, CSSValue& value)
557     {
558         NinePieceImage image(getValue(styleResolver.style()));
559         switch (modifier) {
560         case Outset:
561             image.setOutset(styleResolver.styleMap()->mapNinePieceImageQuad(value));
562             break;
563         case Repeat:
564             styleResolver.styleMap()->mapNinePieceImageRepeat(value, image);
565             break;
566         case Slice:
567             styleResolver.styleMap()->mapNinePieceImageSlice(value, image);
568             break;
569         case Width:
570             image.setBorderSlices(styleResolver.styleMap()->mapNinePieceImageQuad(value));
571             break;
572         }
573         setValue(styleResolver.style(), image);
574     }
575
576 private:
577     static const NinePieceImage& getValue(RenderStyle* style)
578     {
579         return type == BorderImage ? style->borderImage() : style->maskBoxImage();
580     }
581
582     static void setValue(RenderStyle* style, const NinePieceImage& value)
583     {
584         return type == BorderImage ? style->setBorderImage(value) : style->setMaskBoxImage(value);
585     }
586 };
587
588 #define DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(type, modifier) \
589 inline void StyleBuilderCustom::applyInherit##type##modifier(StyleResolver& styleResolver) \
590 { \
591     ApplyPropertyBorderImageModifier<type, modifier>::applyInheritValue(styleResolver); \
592 } \
593 inline void StyleBuilderCustom::applyInitial##type##modifier(StyleResolver& styleResolver) \
594 { \
595     ApplyPropertyBorderImageModifier<type, modifier>::applyInitialValue(styleResolver); \
596 } \
597 inline void StyleBuilderCustom::applyValue##type##modifier(StyleResolver& styleResolver, CSSValue& value) \
598 { \
599     ApplyPropertyBorderImageModifier<type, modifier>::applyValue(styleResolver, value); \
600 }
601
602 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(BorderImage, Outset)
603 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(BorderImage, Repeat)
604 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(BorderImage, Slice)
605 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(BorderImage, Width)
606 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(WebkitMaskBoxImage, Outset)
607 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(WebkitMaskBoxImage, Repeat)
608 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(WebkitMaskBoxImage, Slice)
609 DEFINE_BORDER_IMAGE_MODIFIER_HANDLER(WebkitMaskBoxImage, Width)
610
611 #if ENABLE(IOS_TEXT_AUTOSIZING)
612
613 inline void StyleBuilderCustom::applyInheritLineHeight(StyleResolver& styleResolver)
614 {
615     styleResolver.style()->setLineHeight(styleResolver.parentStyle()->lineHeight());
616     styleResolver.style()->setSpecifiedLineHeight(styleResolver.parentStyle()->specifiedLineHeight());
617 }
618
619 inline void StyleBuilderCustom::applyInitialLineHeight(StyleResolver& styleResolver)
620 {
621     styleResolver.style()->setLineHeight(RenderStyle::initialLineHeight());
622     styleResolver.style()->setSpecifiedLineHeight(RenderStyle::initialSpecifiedLineHeight());
623 }
624
625 inline void StyleBuilderCustom::applyValueLineHeight(StyleResolver& styleResolver, CSSValue& value)
626 {
627     float multiplier = styleResolver.style()->textSizeAdjust().isPercentage() ? styleResolver.style()->textSizeAdjust().multiplier() : 1.f;
628     Optional<Length> lineHeight = StyleBuilderConverter::convertLineHeight(styleResolver, value, multiplier);
629     if (!lineHeight)
630         return;
631
632     styleResolver.style()->setLineHeight(lineHeight.value());
633     styleResolver.style()->setSpecifiedLineHeight(lineHeight.value());
634 }
635
636 #endif
637
638 inline void StyleBuilderCustom::applyInheritOutlineStyle(StyleResolver& styleResolver)
639 {
640     styleResolver.style()->setOutlineStyleIsAuto(styleResolver.parentStyle()->outlineStyleIsAuto());
641     styleResolver.style()->setOutlineStyle(styleResolver.parentStyle()->outlineStyle());
642 }
643
644 inline void StyleBuilderCustom::applyInitialOutlineStyle(StyleResolver& styleResolver)
645 {
646     styleResolver.style()->setOutlineStyleIsAuto(RenderStyle::initialOutlineStyleIsAuto());
647     styleResolver.style()->setOutlineStyle(RenderStyle::initialBorderStyle());
648 }
649
650 inline void StyleBuilderCustom::applyValueOutlineStyle(StyleResolver& styleResolver, CSSValue& value)
651 {
652     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
653
654     styleResolver.style()->setOutlineStyleIsAuto(primitiveValue);
655     styleResolver.style()->setOutlineStyle(primitiveValue);
656 }
657
658 inline void StyleBuilderCustom::applyInitialClip(StyleResolver& styleResolver)
659 {
660     styleResolver.style()->setClip(Length(), Length(), Length(), Length());
661     styleResolver.style()->setHasClip(false);
662 }
663
664 inline void StyleBuilderCustom::applyInheritClip(StyleResolver& styleResolver)
665 {
666     RenderStyle* parentStyle = styleResolver.parentStyle();
667     if (!parentStyle->hasClip())
668         return applyInitialClip(styleResolver);
669     styleResolver.style()->setClip(parentStyle->clipTop(), parentStyle->clipRight(), parentStyle->clipBottom(), parentStyle->clipLeft());
670     styleResolver.style()->setHasClip(true);
671 }
672
673 inline void StyleBuilderCustom::applyValueClip(StyleResolver& styleResolver, CSSValue& value)
674 {
675     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
676
677     if (Rect* rect = primitiveValue.getRectValue()) {
678         auto conversionData = styleResolver.state().cssToLengthConversionData();
679         Length top = rect->top()->convertToLength<FixedIntegerConversion | PercentConversion | AutoConversion>(conversionData);
680         Length right = rect->right()->convertToLength<FixedIntegerConversion | PercentConversion | AutoConversion>(conversionData);
681         Length bottom = rect->bottom()->convertToLength<FixedIntegerConversion | PercentConversion | AutoConversion>(conversionData);
682         Length left = rect->left()->convertToLength<FixedIntegerConversion | PercentConversion | AutoConversion>(conversionData);
683         styleResolver.style()->setClip(top, right, bottom, left);
684         styleResolver.style()->setHasClip(true);
685     } else {
686         ASSERT(primitiveValue.getValueID() == CSSValueAuto);
687         applyInitialClip(styleResolver);
688     }
689 }
690
691 inline void StyleBuilderCustom::applyValueWebkitLocale(StyleResolver& styleResolver, CSSValue& value)
692 {
693     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
694
695     if (primitiveValue.getValueID() == CSSValueAuto)
696         styleResolver.style()->setLocale(nullAtom);
697     else
698         styleResolver.style()->setLocale(primitiveValue.getStringValue());
699     
700     FontDescription fontDescription = styleResolver.style()->fontDescription();
701     fontDescription.setScript(localeToScriptCodeForFontSelection(styleResolver.style()->locale()));
702     styleResolver.setFontDescription(fontDescription);
703 }
704
705 inline void StyleBuilderCustom::applyValueWebkitWritingMode(StyleResolver& styleResolver, CSSValue& value)
706 {
707     styleResolver.setWritingMode(downcast<CSSPrimitiveValue>(value));
708
709     // FIXME: It is not ok to modify document state while applying style.
710     auto& state = styleResolver.state();
711     if (state.element() && state.element() == state.document().documentElement())
712         state.document().setWritingModeSetOnDocumentElement(true);
713 }
714
715 inline void StyleBuilderCustom::applyValueWebkitTextOrientation(StyleResolver& styleResolver, CSSValue& value)
716 {
717     styleResolver.setTextOrientation(downcast<CSSPrimitiveValue>(value));
718 }
719
720 #if ENABLE(IOS_TEXT_AUTOSIZING)
721 inline void StyleBuilderCustom::applyValueWebkitTextSizeAdjust(StyleResolver& styleResolver, CSSValue& value)
722 {
723     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
724     if (primitiveValue.getValueID() == CSSValueAuto)
725         styleResolver.style()->setTextSizeAdjust(TextSizeAdjustment(AutoTextSizeAdjustment));
726     else if (primitiveValue.getValueID() == CSSValueNone)
727         styleResolver.style()->setTextSizeAdjust(TextSizeAdjustment(NoTextSizeAdjustment));
728     else
729         styleResolver.style()->setTextSizeAdjust(TextSizeAdjustment(primitiveValue.getFloatValue()));
730
731     styleResolver.state().setFontDirty(true);
732 }
733 #endif
734
735 inline void StyleBuilderCustom::applyValueWebkitJustifySelf(StyleResolver& styleResolver, CSSValue& value)
736 {
737     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
738
739     if (Pair* pairValue = primitiveValue.getPairValue()) {
740         styleResolver.style()->setJustifySelf(*pairValue->first());
741         styleResolver.style()->setJustifySelfOverflowAlignment(*pairValue->second());
742     } else
743         styleResolver.style()->setJustifySelf(primitiveValue);
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     FontDescription fontDescription = styleResolver.style()->fontDescription();
829     FontDescription initialDesc = FontDescription();
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     FontDescription fontDescription = styleResolver.style()->fontDescription();
845     FontDescription 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     FontDescription 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     FontDescription fontDescription = styleResolver.fontDescription();
1248     fontDescription.setWeight(FontWeightNormal);
1249     styleResolver.setFontDescription(fontDescription);
1250 }
1251
1252 inline void StyleBuilderCustom::applyInheritFontWeight(StyleResolver& styleResolver)
1253 {
1254     FontDescription 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     FontDescription 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::applyInitialWebkitFontVariantLigatures(StyleResolver& styleResolver)
1394 {
1395     FontDescription fontDescription = styleResolver.fontDescription();
1396
1397     fontDescription.setCommonLigaturesState(FontDescription::NormalLigaturesState);
1398     fontDescription.setDiscretionaryLigaturesState(FontDescription::NormalLigaturesState);
1399     fontDescription.setHistoricalLigaturesState(FontDescription::NormalLigaturesState);
1400
1401     styleResolver.setFontDescription(fontDescription);
1402 }
1403
1404 inline void StyleBuilderCustom::applyInheritWebkitFontVariantLigatures(StyleResolver& styleResolver)
1405 {
1406     const FontDescription& parentFontDescription = styleResolver.parentFontDescription();
1407     FontDescription fontDescription = styleResolver.fontDescription();
1408
1409     fontDescription.setCommonLigaturesState(parentFontDescription.commonLigaturesState());
1410     fontDescription.setDiscretionaryLigaturesState(parentFontDescription.discretionaryLigaturesState());
1411     fontDescription.setHistoricalLigaturesState(parentFontDescription.historicalLigaturesState());
1412
1413     styleResolver.setFontDescription(fontDescription);
1414 }
1415
1416 inline void StyleBuilderCustom::applyValueWebkitFontVariantLigatures(StyleResolver& styleResolver, CSSValue& value)
1417 {
1418     FontDescription::LigaturesState commonLigaturesState = FontDescription::NormalLigaturesState;
1419     FontDescription::LigaturesState discretionaryLigaturesState = FontDescription::NormalLigaturesState;
1420     FontDescription::LigaturesState historicalLigaturesState = FontDescription::NormalLigaturesState;
1421
1422     if (is<CSSValueList>(value)) {
1423         for (auto& item : downcast<CSSValueList>(value)) {
1424             switch (downcast<CSSPrimitiveValue>(item.get()).getValueID()) {
1425             case CSSValueNoCommonLigatures:
1426                 commonLigaturesState = FontDescription::DisabledLigaturesState;
1427                 break;
1428             case CSSValueCommonLigatures:
1429                 commonLigaturesState = FontDescription::EnabledLigaturesState;
1430                 break;
1431             case CSSValueNoDiscretionaryLigatures:
1432                 discretionaryLigaturesState = FontDescription::DisabledLigaturesState;
1433                 break;
1434             case CSSValueDiscretionaryLigatures:
1435                 discretionaryLigaturesState = FontDescription::EnabledLigaturesState;
1436                 break;
1437             case CSSValueNoHistoricalLigatures:
1438                 historicalLigaturesState = FontDescription::DisabledLigaturesState;
1439                 break;
1440             case CSSValueHistoricalLigatures:
1441                 historicalLigaturesState = FontDescription::EnabledLigaturesState;
1442                 break;
1443             default:
1444                 ASSERT_NOT_REACHED();
1445                 break;
1446             }
1447         }
1448     } else
1449         ASSERT(downcast<CSSPrimitiveValue>(value).getValueID() == CSSValueNormal);
1450
1451     FontDescription fontDescription = styleResolver.fontDescription();
1452     fontDescription.setCommonLigaturesState(commonLigaturesState);
1453     fontDescription.setDiscretionaryLigaturesState(discretionaryLigaturesState);
1454     fontDescription.setHistoricalLigaturesState(historicalLigaturesState);
1455     styleResolver.setFontDescription(fontDescription);
1456 }
1457
1458 inline void StyleBuilderCustom::applyInitialFontSize(StyleResolver& styleResolver)
1459 {
1460     FontDescription fontDescription = styleResolver.style()->fontDescription();
1461     float size = Style::fontSizeForKeyword(CSSValueMedium, fontDescription.useFixedDefaultSize(), styleResolver.document());
1462
1463     if (size < 0)
1464         return;
1465
1466     fontDescription.setKeywordSizeFromIdentifier(CSSValueMedium);
1467     styleResolver.setFontSize(fontDescription, size);
1468     styleResolver.setFontDescription(fontDescription);
1469 }
1470
1471 inline void StyleBuilderCustom::applyInheritFontSize(StyleResolver& styleResolver)
1472 {
1473     const FontDescription& parentFontDescription = styleResolver.parentStyle()->fontDescription();
1474     float size = parentFontDescription.specifiedSize();
1475
1476     if (size < 0)
1477         return;
1478
1479     FontDescription fontDescription = styleResolver.style()->fontDescription();
1480     fontDescription.setKeywordSize(parentFontDescription.keywordSize());
1481     styleResolver.setFontSize(fontDescription, size);
1482     styleResolver.setFontDescription(fontDescription);
1483 }
1484
1485 // When the CSS keyword "larger" is used, this function will attempt to match within the keyword
1486 // table, and failing that, will simply multiply by 1.2.
1487 inline float StyleBuilderCustom::largerFontSize(float size)
1488 {
1489     // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to
1490     // the next size level.
1491     return size * 1.2f;
1492 }
1493
1494 // Like the previous function, but for the keyword "smaller".
1495 inline float StyleBuilderCustom::smallerFontSize(float size)
1496 {
1497     // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to
1498     // the next size level.
1499     return size / 1.2f;
1500 }
1501
1502 inline float StyleBuilderCustom::determineRubyTextSizeMultiplier(StyleResolver& styleResolver)
1503 {
1504     if (styleResolver.style()->rubyPosition() != RubyPositionInterCharacter)
1505         return 0.5f;
1506
1507     // FIXME: This hack is to ensure tone marks are the same size as
1508     // the bopomofo. This code will go away if we make a special renderer
1509     // for the tone marks eventually.
1510     if (auto* element = styleResolver.state().element()) {
1511         for (auto& ancestor : ancestorsOfType<HTMLElement>(*element)) {
1512             if (ancestor.hasTagName(HTMLNames::rtTag))
1513                 return 1.0f;
1514         }
1515     }
1516     return 0.25f;
1517 }
1518
1519 inline void StyleBuilderCustom::applyValueFontSize(StyleResolver& styleResolver, CSSValue& value)
1520 {
1521     FontDescription fontDescription = styleResolver.style()->fontDescription();
1522     fontDescription.setKeywordSizeFromIdentifier(CSSValueInvalid);
1523
1524     float parentSize = 0;
1525     bool parentIsAbsoluteSize = false;
1526     if (auto* parentStyle = styleResolver.parentStyle()) {
1527         parentSize = parentStyle->fontDescription().specifiedSize();
1528         parentIsAbsoluteSize = parentStyle->fontDescription().isAbsoluteSize();
1529     }
1530
1531     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
1532     float size;
1533     if (CSSValueID ident = primitiveValue.getValueID()) {
1534         fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize && (ident == CSSValueLarger || ident == CSSValueSmaller || ident == CSSValueWebkitRubyText));
1535
1536         // Keywords are being used.
1537         switch (ident) {
1538         case CSSValueXxSmall:
1539         case CSSValueXSmall:
1540         case CSSValueSmall:
1541         case CSSValueMedium:
1542         case CSSValueLarge:
1543         case CSSValueXLarge:
1544         case CSSValueXxLarge:
1545         case CSSValueWebkitXxxLarge:
1546             size = Style::fontSizeForKeyword(ident, fontDescription.useFixedDefaultSize(), styleResolver.document());
1547             fontDescription.setKeywordSizeFromIdentifier(ident);
1548             break;
1549         case CSSValueLarger:
1550             size = largerFontSize(parentSize);
1551             break;
1552         case CSSValueSmaller:
1553             size = smallerFontSize(parentSize);
1554             break;
1555         case CSSValueWebkitRubyText:
1556             size = determineRubyTextSizeMultiplier(styleResolver) * parentSize;
1557             break;
1558         default:
1559             return;
1560         }
1561     } else {
1562         fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize || !(primitiveValue.isPercentage() || primitiveValue.isFontRelativeLength()));
1563         if (primitiveValue.isLength()) {
1564             size = primitiveValue.computeLength<float>(CSSToLengthConversionData(styleResolver.parentStyle(), styleResolver.rootElementStyle(), styleResolver.document().renderView(), 1.0f, true));
1565             styleResolver.state().setFontSizeHasViewportUnits(primitiveValue.isViewportPercentageLength());
1566         } else if (primitiveValue.isPercentage())
1567             size = (primitiveValue.getFloatValue() * parentSize) / 100.0f;
1568         else if (primitiveValue.isCalculatedPercentageWithLength())
1569             size = primitiveValue.cssCalcValue()->createCalculationValue(styleResolver.state().cssToLengthConversionData().copyWithAdjustedZoom(1.0f))->evaluate(parentSize);
1570         else
1571             return;
1572     }
1573
1574     if (size < 0)
1575         return;
1576
1577     styleResolver.setFontSize(fontDescription, std::min(maximumAllowedFontSize, size));
1578     styleResolver.setFontDescription(fontDescription);
1579 }
1580
1581 #if ENABLE(CSS_GRID_LAYOUT)
1582 inline void StyleBuilderCustom::applyInitialWebkitGridTemplateAreas(StyleResolver& styleResolver)
1583 {
1584     styleResolver.style()->setNamedGridArea(RenderStyle::initialNamedGridArea());
1585     styleResolver.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount());
1586     styleResolver.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount());
1587 }
1588
1589 inline void StyleBuilderCustom::applyInheritWebkitGridTemplateAreas(StyleResolver& styleResolver)
1590 {
1591     styleResolver.style()->setNamedGridArea(styleResolver.parentStyle()->namedGridArea());
1592     styleResolver.style()->setNamedGridAreaRowCount(styleResolver.parentStyle()->namedGridAreaRowCount());
1593     styleResolver.style()->setNamedGridAreaColumnCount(styleResolver.parentStyle()->namedGridAreaColumnCount());
1594 }
1595
1596 inline void StyleBuilderCustom::applyValueWebkitGridTemplateAreas(StyleResolver& styleResolver, CSSValue& value)
1597 {
1598     if (is<CSSPrimitiveValue>(value)) {
1599         ASSERT(downcast<CSSPrimitiveValue>(value).getValueID() == CSSValueNone);
1600         return;
1601     }
1602
1603     auto& gridTemplateAreasValue = downcast<CSSGridTemplateAreasValue>(value);
1604     const NamedGridAreaMap& newNamedGridAreas = gridTemplateAreasValue.gridAreaMap();
1605
1606     NamedGridLinesMap namedGridColumnLines = styleResolver.style()->namedGridColumnLines();
1607     NamedGridLinesMap namedGridRowLines = styleResolver.style()->namedGridRowLines();
1608     StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridColumnLines, ForColumns);
1609     StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(newNamedGridAreas, namedGridRowLines, ForRows);
1610     styleResolver.style()->setNamedGridColumnLines(namedGridColumnLines);
1611     styleResolver.style()->setNamedGridRowLines(namedGridRowLines);
1612
1613     styleResolver.style()->setNamedGridArea(gridTemplateAreasValue.gridAreaMap());
1614     styleResolver.style()->setNamedGridAreaRowCount(gridTemplateAreasValue.rowCount());
1615     styleResolver.style()->setNamedGridAreaColumnCount(gridTemplateAreasValue.columnCount());
1616 }
1617
1618 inline void StyleBuilderCustom::applyInitialWebkitGridTemplateColumns(StyleResolver& styleResolver)
1619 {
1620     styleResolver.style()->setGridColumns(RenderStyle::initialGridColumns());
1621     styleResolver.style()->setNamedGridColumnLines(RenderStyle::initialNamedGridColumnLines());
1622     styleResolver.style()->setOrderedNamedGridColumnLines(RenderStyle::initialOrderedNamedGridColumnLines());
1623 }
1624
1625 inline void StyleBuilderCustom::applyInheritWebkitGridTemplateColumns(StyleResolver& styleResolver)
1626 {
1627     styleResolver.style()->setGridColumns(styleResolver.parentStyle()->gridColumns());
1628     styleResolver.style()->setNamedGridColumnLines(styleResolver.parentStyle()->namedGridColumnLines());
1629     styleResolver.style()->setOrderedNamedGridColumnLines(styleResolver.parentStyle()->orderedNamedGridColumnLines());
1630 }
1631
1632 inline void StyleBuilderCustom::applyValueWebkitGridTemplateColumns(StyleResolver& styleResolver, CSSValue& value)
1633 {
1634     Vector<GridTrackSize> trackSizes;
1635     NamedGridLinesMap namedGridLines;
1636     OrderedNamedGridLinesMap orderedNamedGridLines;
1637     if (!StyleBuilderConverter::createGridTrackList(value, trackSizes, namedGridLines, orderedNamedGridLines, styleResolver))
1638         return;
1639     const NamedGridAreaMap& namedGridAreas = styleResolver.style()->namedGridArea();
1640     if (!namedGridAreas.isEmpty())
1641         StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(namedGridAreas, namedGridLines, ForColumns);
1642
1643     styleResolver.style()->setGridColumns(trackSizes);
1644     styleResolver.style()->setNamedGridColumnLines(namedGridLines);
1645     styleResolver.style()->setOrderedNamedGridColumnLines(orderedNamedGridLines);
1646 }
1647
1648 inline void StyleBuilderCustom::applyInitialWebkitGridTemplateRows(StyleResolver& styleResolver)
1649 {
1650     styleResolver.style()->setGridRows(RenderStyle::initialGridRows());
1651     styleResolver.style()->setNamedGridRowLines(RenderStyle::initialNamedGridRowLines());
1652     styleResolver.style()->setOrderedNamedGridRowLines(RenderStyle::initialOrderedNamedGridRowLines());
1653 }
1654
1655 inline void StyleBuilderCustom::applyInheritWebkitGridTemplateRows(StyleResolver& styleResolver)
1656 {
1657     styleResolver.style()->setGridRows(styleResolver.parentStyle()->gridRows());
1658     styleResolver.style()->setNamedGridRowLines(styleResolver.parentStyle()->namedGridRowLines());
1659     styleResolver.style()->setOrderedNamedGridRowLines(styleResolver.parentStyle()->orderedNamedGridRowLines());
1660 }
1661
1662 inline void StyleBuilderCustom::applyValueWebkitGridTemplateRows(StyleResolver& styleResolver, CSSValue& value)
1663 {
1664     Vector<GridTrackSize> trackSizes;
1665     NamedGridLinesMap namedGridLines;
1666     OrderedNamedGridLinesMap orderedNamedGridLines;
1667     if (!StyleBuilderConverter::createGridTrackList(value, trackSizes, namedGridLines, orderedNamedGridLines, styleResolver))
1668         return;
1669     const NamedGridAreaMap& namedGridAreas = styleResolver.style()->namedGridArea();
1670     if (!namedGridAreas.isEmpty())
1671         StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(namedGridAreas, namedGridLines, ForRows);
1672
1673     styleResolver.style()->setGridRows(trackSizes);
1674     styleResolver.style()->setNamedGridRowLines(namedGridLines);
1675     styleResolver.style()->setOrderedNamedGridRowLines(orderedNamedGridLines);
1676 }
1677 #endif // ENABLE(CSS_GRID_LAYOUT)
1678
1679 void StyleBuilderCustom::applyValueAlt(StyleResolver& styleResolver, CSSValue& value)
1680 {
1681     auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
1682     if (primitiveValue.isString())
1683         styleResolver.style()->setContentAltText(primitiveValue.getStringValue());
1684     else if (primitiveValue.isAttr()) {
1685         // FIXME: Can a namespace be specified for an attr(foo)?
1686         if (styleResolver.style()->styleType() == NOPSEUDO)
1687             styleResolver.style()->setUnique();
1688         else
1689             styleResolver.parentStyle()->setUnique();
1690
1691         QualifiedName attr(nullAtom, primitiveValue.getStringValue(), nullAtom);
1692         const AtomicString& value = styleResolver.element()->getAttribute(attr);
1693         styleResolver.style()->setContentAltText(value.isNull() ? emptyAtom : value);
1694
1695         // Register the fact that the attribute value affects the style.
1696         styleResolver.ruleSets().features().attributeCanonicalLocalNamesInRules.add(attr.localName().impl());
1697         styleResolver.ruleSets().features().attributeLocalNamesInRules.add(attr.localName().impl());
1698     } else
1699         styleResolver.style()->setContentAltText(emptyAtom);
1700 }
1701
1702 #if ENABLE(CSS_SCROLL_SNAP)
1703 inline void StyleBuilderCustom::applyInitialWebkitScrollSnapPointsX(StyleResolver& styleResolver)
1704 {
1705     styleResolver.style()->setScrollSnapPointsX(nullptr);
1706 }
1707
1708 inline void StyleBuilderCustom::applyInheritWebkitScrollSnapPointsX(StyleResolver& styleResolver)
1709 {
1710     styleResolver.style()->setScrollSnapPointsX(styleResolver.parentStyle()->scrollSnapPointsX() ? std::make_unique<ScrollSnapPoints>(*styleResolver.parentStyle()->scrollSnapPointsX()) : nullptr);
1711 }
1712
1713 inline void StyleBuilderCustom::applyInitialWebkitScrollSnapPointsY(StyleResolver& styleResolver)
1714 {
1715     styleResolver.style()->setScrollSnapPointsY(nullptr);
1716 }
1717
1718 inline void StyleBuilderCustom::applyInheritWebkitScrollSnapPointsY(StyleResolver& styleResolver)
1719 {
1720     styleResolver.style()->setScrollSnapPointsY(styleResolver.parentStyle()->scrollSnapPointsY() ? std::make_unique<ScrollSnapPoints>(*styleResolver.parentStyle()->scrollSnapPointsY()) : nullptr);
1721 }
1722 #endif
1723
1724 } // namespace WebCore
1725
1726 #endif // StyleBuilderCustom_h