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