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