~mmach/netext73/webkit2gtk

« back to all changes in this revision

Viewing changes to Source/WebCore/style/StyleBuilderConverter.h

  • Committer: mmach
  • Date: 2023-06-16 17:21:37 UTC
  • Revision ID: netbit73@gmail.com-20230616172137-2rqx6yr96ga9g3kp
1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "BasicShapeFunctions.h"
 
30
#include "CSSCalculationValue.h"
 
31
#include "CSSContentDistributionValue.h"
 
32
#include "CSSFontFeatureValue.h"
 
33
#include "CSSFontStyleValue.h"
 
34
#include "CSSFontVariationValue.h"
 
35
#include "CSSFunctionValue.h"
 
36
#include "CSSGridAutoRepeatValue.h"
 
37
#include "CSSGridIntegerRepeatValue.h"
 
38
#include "CSSGridLineNamesValue.h"
 
39
#include "CSSImageGeneratorValue.h"
 
40
#include "CSSImageSetValue.h"
 
41
#include "CSSImageValue.h"
 
42
#include "CSSPrimitiveValue.h"
 
43
#include "CSSPrimitiveValueMappings.h"
 
44
#include "CSSReflectValue.h"
 
45
#include "FontSelectionValueInlines.h"
 
46
#include "Frame.h"
 
47
#include "GridPositionsResolver.h"
 
48
#include "Length.h"
 
49
#include "Pair.h"
 
50
#include "QuotesData.h"
 
51
#include "RuntimeEnabledFeatures.h"
 
52
#include "SVGURIReference.h"
 
53
#include "Settings.h"
 
54
#include "StyleBuilderState.h"
 
55
#include "StyleScrollSnapPoints.h"
 
56
#include "TabSize.h"
 
57
#include "TouchAction.h"
 
58
#include "TransformFunctions.h"
 
59
#include <wtf/Optional.h>
 
60
 
 
61
namespace WebCore {
 
62
namespace Style {
 
63
 
 
64
// Note that we assume the CSS parser only allows valid CSSValue types.
 
65
class BuilderConverter {
 
66
public:
 
67
    static Length convertLength(const BuilderState&, const CSSValue&);
 
68
    static Length convertLengthOrAuto(const BuilderState&, const CSSValue&);
 
69
    static Length convertLengthSizing(const BuilderState&, const CSSValue&);
 
70
    static Length convertLengthMaxSizing(const BuilderState&, const CSSValue&);
 
71
    static TabSize convertTabSize(const BuilderState&, const CSSValue&);
 
72
    template<typename T> static T convertComputedLength(BuilderState&, const CSSValue&);
 
73
    template<typename T> static T convertLineWidth(BuilderState&, const CSSValue&);
 
74
    static float convertSpacing(BuilderState&, const CSSValue&);
 
75
    static LengthSize convertRadius(BuilderState&, const CSSValue&);
 
76
    static LengthPoint convertObjectPosition(BuilderState&, const CSSValue&);
 
77
    static OptionSet<TextDecoration> convertTextDecoration(BuilderState&, const CSSValue&);
 
78
    template<typename T> static T convertNumber(BuilderState&, const CSSValue&);
 
79
    template<typename T> static T convertNumberOrAuto(BuilderState&, const CSSValue&);
 
80
    static short convertWebkitHyphenateLimitLines(BuilderState&, const CSSValue&);
 
81
    template<CSSPropertyID> static NinePieceImage convertBorderImage(BuilderState&, CSSValue&);
 
82
    template<CSSPropertyID> static NinePieceImage convertBorderMask(BuilderState&, CSSValue&);
 
83
    template<CSSPropertyID> static RefPtr<StyleImage> convertStyleImage(BuilderState&, CSSValue&);
 
84
    static ImageOrientation convertImageOrientation(BuilderState&, const CSSValue&);
 
85
    static TransformOperations convertTransform(BuilderState&, const CSSValue&);
 
86
#if ENABLE(DARK_MODE_CSS)
 
87
    static StyleColorScheme convertColorScheme(BuilderState&, const CSSValue&);
 
88
#endif
 
89
    static String convertString(BuilderState&, const CSSValue&);
 
90
    static String convertStringOrAuto(BuilderState&, const CSSValue&);
 
91
    static String convertStringOrNone(BuilderState&, const CSSValue&);
 
92
    static OptionSet<TextEmphasisPosition> convertTextEmphasisPosition(BuilderState&, const CSSValue&);
 
93
    static TextAlignMode convertTextAlign(BuilderState&, const CSSValue&);
 
94
    static RefPtr<ClipPathOperation> convertClipPath(BuilderState&, const CSSValue&);
 
95
    static Resize convertResize(BuilderState&, const CSSValue&);
 
96
    static int convertMarqueeRepetition(BuilderState&, const CSSValue&);
 
97
    static int convertMarqueeSpeed(BuilderState&, const CSSValue&);
 
98
    static Ref<QuotesData> convertQuotes(BuilderState&, const CSSValue&);
 
99
    static TextUnderlinePosition convertTextUnderlinePosition(BuilderState&, const CSSValue&);
 
100
    static TextUnderlineOffset convertTextUnderlineOffset(BuilderState&, const CSSValue&);
 
101
    static TextDecorationThickness convertTextDecorationThickness(BuilderState&, const CSSValue&);
 
102
    static RefPtr<StyleReflection> convertReflection(BuilderState&, const CSSValue&);
 
103
    static IntSize convertInitialLetter(BuilderState&, const CSSValue&);
 
104
    static float convertTextStrokeWidth(BuilderState&, const CSSValue&);
 
105
    static OptionSet<LineBoxContain> convertLineBoxContain(BuilderState&, const CSSValue&);
 
106
    static OptionSet<TextDecorationSkip> convertTextDecorationSkip(BuilderState&, const CSSValue&);
 
107
    static RefPtr<ShapeValue> convertShapeValue(BuilderState&, CSSValue&);
 
108
#if ENABLE(CSS_SCROLL_SNAP)
 
109
    static ScrollSnapType convertScrollSnapType(BuilderState&, const CSSValue&);
 
110
    static ScrollSnapAlign convertScrollSnapAlign(BuilderState&, const CSSValue&);
 
111
#endif
 
112
    static GridTrackSize convertGridTrackSize(BuilderState&, const CSSValue&);
 
113
    static Vector<GridTrackSize> convertGridTrackSizeList(BuilderState&, const CSSValue&);
 
114
    static Optional<GridPosition> convertGridPosition(BuilderState&, const CSSValue&);
 
115
    static GridAutoFlow convertGridAutoFlow(BuilderState&, const CSSValue&);
 
116
    static Optional<Length> convertWordSpacing(BuilderState&, const CSSValue&);
 
117
    static Optional<float> convertPerspective(BuilderState&, const CSSValue&);
 
118
    static Optional<Length> convertMarqueeIncrement(BuilderState&, const CSSValue&);
 
119
    static Optional<FilterOperations> convertFilterOperations(BuilderState&, const CSSValue&);
 
120
#if PLATFORM(IOS_FAMILY)
 
121
    static bool convertTouchCallout(BuilderState&, const CSSValue&);
 
122
#endif
 
123
#if ENABLE(TOUCH_EVENTS)
 
124
    static Color convertTapHighlightColor(BuilderState&, const CSSValue&);
 
125
#endif
 
126
#if ENABLE(POINTER_EVENTS)
 
127
    static OptionSet<TouchAction> convertTouchAction(BuilderState&, const CSSValue&);
 
128
#endif
 
129
#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
 
130
    static bool convertOverflowScrolling(BuilderState&, const CSSValue&);
 
131
#endif
 
132
    static FontFeatureSettings convertFontFeatureSettings(BuilderState&, const CSSValue&);
 
133
    static bool convertSmoothScrolling(BuilderState&, const CSSValue&);
 
134
    static FontSelectionValue convertFontWeightFromValue(const CSSValue&);
 
135
    static FontSelectionValue convertFontStretchFromValue(const CSSValue&);
 
136
    static Optional<FontSelectionValue> convertFontStyleFromValue(const CSSValue&);
 
137
    static FontSelectionValue convertFontWeight(BuilderState&, const CSSValue&);
 
138
    static FontSelectionValue convertFontStretch(BuilderState&, const CSSValue&);
 
139
    static FontSelectionValue convertFontStyle(BuilderState&, const CSSValue&);
 
140
#if ENABLE(VARIATION_FONTS)
 
141
    static FontVariationSettings convertFontVariationSettings(BuilderState&, const CSSValue&);
 
142
#endif
 
143
    static SVGLengthValue convertSVGLengthValue(BuilderState&, const CSSValue&);
 
144
    static Vector<SVGLengthValue> convertSVGLengthVector(BuilderState&, const CSSValue&);
 
145
    static Vector<SVGLengthValue> convertStrokeDashArray(BuilderState&, const CSSValue&);
 
146
    static PaintOrder convertPaintOrder(BuilderState&, const CSSValue&);
 
147
    static float convertOpacity(BuilderState&, const CSSValue&);
 
148
    static String convertSVGURIReference(BuilderState&, const CSSValue&);
 
149
    static Color convertSVGColor(BuilderState&, const CSSValue&);
 
150
    static StyleSelfAlignmentData convertSelfOrDefaultAlignmentData(BuilderState&, const CSSValue&);
 
151
    static StyleContentAlignmentData convertContentAlignmentData(BuilderState&, const CSSValue&);
 
152
    static GlyphOrientation convertGlyphOrientation(BuilderState&, const CSSValue&);
 
153
    static GlyphOrientation convertGlyphOrientationOrAuto(BuilderState&, const CSSValue&);
 
154
    static Optional<Length> convertLineHeight(BuilderState&, const CSSValue&, float multiplier = 1.f);
 
155
    static FontSynthesis convertFontSynthesis(BuilderState&, const CSSValue&);
 
156
    
 
157
    static BreakBetween convertPageBreakBetween(BuilderState&, const CSSValue&);
 
158
    static BreakInside convertPageBreakInside(BuilderState&, const CSSValue&);
 
159
    static BreakBetween convertColumnBreakBetween(BuilderState&, const CSSValue&);
 
160
    static BreakInside convertColumnBreakInside(BuilderState&, const CSSValue&);
 
161
 
 
162
    static OptionSet<HangingPunctuation> convertHangingPunctuation(BuilderState&, const CSSValue&);
 
163
 
 
164
    static OptionSet<SpeakAs> convertSpeakAs(BuilderState&, const CSSValue&);
 
165
 
 
166
    static Length convertPositionComponentX(BuilderState&, const CSSValue&);
 
167
    static Length convertPositionComponentY(BuilderState&, const CSSValue&);
 
168
 
 
169
    static GapLength convertGapLength(BuilderState&, const CSSValue&);
 
170
    
 
171
private:
 
172
    friend class BuilderCustom;
 
173
 
 
174
    static Length convertToRadiusLength(CSSToLengthConversionData&, const CSSPrimitiveValue&);
 
175
    static OptionSet<TextEmphasisPosition> valueToEmphasisPosition(const CSSPrimitiveValue&);
 
176
    static OptionSet<TextDecorationSkip> valueToDecorationSkip(const CSSPrimitiveValue&);
 
177
#if ENABLE(CSS_SCROLL_SNAP)
 
178
    static Length parseSnapCoordinate(BuilderState&, const CSSValue&);
 
179
#endif
 
180
 
 
181
#if ENABLE(DARK_MODE_CSS)
 
182
    static void updateColorScheme(const CSSPrimitiveValue&, StyleColorScheme&);
 
183
#endif
 
184
 
 
185
    static Length convertTo100PercentMinusLength(const Length&);
 
186
    template<CSSValueID, CSSValueID> static Length convertPositionComponent(BuilderState&, const CSSPrimitiveValue&);
 
187
 
 
188
    static GridLength createGridTrackBreadth(const CSSPrimitiveValue&, BuilderState&);
 
189
    static GridTrackSize createGridTrackSize(const CSSValue&, BuilderState&);
 
190
    struct TracksData;
 
191
    static bool createGridTrackList(const CSSValue&, TracksData&, BuilderState&);
 
192
    static bool createGridPosition(const CSSValue&, GridPosition&);
 
193
    static void createImplicitNamedGridLinesFromGridArea(const NamedGridAreaMap&, NamedGridLinesMap&, GridTrackSizingDirection);
 
194
    static CSSToLengthConversionData csstoLengthConversionDataWithTextZoomFactor(BuilderState&);
 
195
};
 
196
 
 
197
inline Length BuilderConverter::convertLength(const BuilderState& builderState, const CSSValue& value)
 
198
{
 
199
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
200
    CSSToLengthConversionData conversionData = builderState.useSVGZoomRulesForLength() ?
 
201
        builderState.cssToLengthConversionData().copyWithAdjustedZoom(1.0f)
 
202
        : builderState.cssToLengthConversionData();
 
203
 
 
204
    if (primitiveValue.isLength()) {
 
205
        Length length = primitiveValue.computeLength<Length>(conversionData);
 
206
        length.setHasQuirk(primitiveValue.isQuirkValue());
 
207
        return length;
 
208
    }
 
209
 
 
210
    if (primitiveValue.isPercentage())
 
211
        return Length(primitiveValue.doubleValue(), Percent);
 
212
 
 
213
    if (primitiveValue.isCalculatedPercentageWithLength())
 
214
        return Length(primitiveValue.cssCalcValue()->createCalculationValue(conversionData));
 
215
 
 
216
    ASSERT_NOT_REACHED();
 
217
    return Length(0, Fixed);
 
218
}
 
219
 
 
220
inline Length BuilderConverter::convertLengthOrAuto(const BuilderState& builderState, const CSSValue& value)
 
221
{
 
222
    if (downcast<CSSPrimitiveValue>(value).valueID() == CSSValueAuto)
 
223
        return Length(Auto);
 
224
    return convertLength(builderState, value);
 
225
}
 
226
 
 
227
inline Length BuilderConverter::convertLengthSizing(const BuilderState& builderState, const CSSValue& value)
 
228
{
 
229
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
230
    switch (primitiveValue.valueID()) {
 
231
    case CSSValueInvalid:
 
232
        return convertLength(builderState, value);
 
233
    case CSSValueIntrinsic:
 
234
        return Length(Intrinsic);
 
235
    case CSSValueMinIntrinsic:
 
236
        return Length(MinIntrinsic);
 
237
    case CSSValueMinContent:
 
238
    case CSSValueWebkitMinContent:
 
239
        return Length(MinContent);
 
240
    case CSSValueMaxContent:
 
241
    case CSSValueWebkitMaxContent:
 
242
        return Length(MaxContent);
 
243
    case CSSValueWebkitFillAvailable:
 
244
        return Length(FillAvailable);
 
245
    case CSSValueFitContent:
 
246
    case CSSValueWebkitFitContent:
 
247
        return Length(FitContent);
 
248
    case CSSValueAuto:
 
249
        return Length(Auto);
 
250
    default:
 
251
        ASSERT_NOT_REACHED();
 
252
        return Length();
 
253
    }
 
254
}
 
255
 
 
256
inline Length BuilderConverter::convertLengthMaxSizing(const BuilderState& builderState, const CSSValue& value)
 
257
{
 
258
    if (downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone)
 
259
        return Length(Undefined);
 
260
    return convertLengthSizing(builderState, value);
 
261
}
 
262
 
 
263
inline TabSize BuilderConverter::convertTabSize(const BuilderState& builderState, const CSSValue& value)
 
264
{
 
265
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
266
    if (primitiveValue.isNumber())
 
267
        return TabSize(primitiveValue.floatValue(), SpaceValueType);
 
268
    return TabSize(primitiveValue.computeLength<float>(builderState.cssToLengthConversionData()), LengthValueType);
 
269
}
 
270
 
 
271
template<typename T>
 
272
inline T BuilderConverter::convertComputedLength(BuilderState& builderState, const CSSValue& value)
 
273
{
 
274
    return downcast<CSSPrimitiveValue>(value).computeLength<T>(builderState.cssToLengthConversionData());
 
275
}
 
276
 
 
277
template<typename T>
 
278
inline T BuilderConverter::convertLineWidth(BuilderState& builderState, const CSSValue& value)
 
279
{
 
280
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
281
    switch (primitiveValue.valueID()) {
 
282
    case CSSValueThin:
 
283
        return 1;
 
284
    case CSSValueMedium:
 
285
        return 3;
 
286
    case CSSValueThick:
 
287
        return 5;
 
288
    case CSSValueInvalid: {
 
289
        // Any original result that was >= 1 should not be allowed to fall below 1.
 
290
        // This keeps border lines from vanishing.
 
291
        T result = convertComputedLength<T>(builderState, value);
 
292
        if (builderState.style().effectiveZoom() < 1.0f && result < 1.0) {
 
293
            T originalLength = primitiveValue.computeLength<T>(builderState.cssToLengthConversionData().copyWithAdjustedZoom(1.0));
 
294
            if (originalLength >= 1.0)
 
295
                return 1;
 
296
        }
 
297
        float minimumLineWidth = 1 / builderState.document().deviceScaleFactor();
 
298
        if (result > 0 && result < minimumLineWidth)
 
299
            return minimumLineWidth;
 
300
        return floorToDevicePixel(result, builderState.document().deviceScaleFactor());
 
301
    }
 
302
    default:
 
303
        ASSERT_NOT_REACHED();
 
304
        return 0;
 
305
    }
 
306
}
 
307
 
 
308
inline float BuilderConverter::convertSpacing(BuilderState& builderState, const CSSValue& value)
 
309
{
 
310
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
311
    if (primitiveValue.valueID() == CSSValueNormal)
 
312
        return 0.f;
 
313
 
 
314
    CSSToLengthConversionData conversionData = builderState.useSVGZoomRulesForLength() ?
 
315
        builderState.cssToLengthConversionData().copyWithAdjustedZoom(1.0f)
 
316
        : builderState.cssToLengthConversionData();
 
317
    return primitiveValue.computeLength<float>(conversionData);
 
318
}
 
319
 
 
320
inline Length BuilderConverter::convertToRadiusLength(CSSToLengthConversionData& conversionData, const CSSPrimitiveValue& value)
 
321
{
 
322
    if (value.isPercentage())
 
323
        return Length(value.doubleValue(), Percent);
 
324
    if (value.isCalculatedPercentageWithLength())
 
325
        return Length(value.cssCalcValue()->createCalculationValue(conversionData));
 
326
    return value.computeLength<Length>(conversionData);
 
327
}
 
328
 
 
329
inline LengthSize BuilderConverter::convertRadius(BuilderState& builderState, const CSSValue& value)
 
330
{
 
331
    auto* pair = downcast<CSSPrimitiveValue>(value).pairValue();
 
332
    if (!pair || !pair->first() || !pair->second())
 
333
        return { { 0, Fixed }, { 0, Fixed } };
 
334
 
 
335
    CSSToLengthConversionData conversionData = builderState.cssToLengthConversionData();
 
336
    LengthSize radius { convertToRadiusLength(conversionData, *pair->first()), convertToRadiusLength(conversionData, *pair->second()) };
 
337
 
 
338
    ASSERT(!radius.width.isNegative());
 
339
    ASSERT(!radius.height.isNegative());
 
340
    if (radius.width.isZero() || radius.height.isZero())
 
341
        return { { 0, Fixed }, { 0, Fixed } };
 
342
 
 
343
    return radius;
 
344
}
 
345
 
 
346
inline Length BuilderConverter::convertTo100PercentMinusLength(const Length& length)
 
347
{
 
348
    if (length.isPercent())
 
349
        return Length(100 - length.value(), Percent);
 
350
    
 
351
    // Turn this into a calc expression: calc(100% - length)
 
352
    Vector<std::unique_ptr<CalcExpressionNode>> lengths;
 
353
    lengths.reserveInitialCapacity(2);
 
354
    lengths.uncheckedAppend(makeUnique<CalcExpressionLength>(Length(100, Percent)));
 
355
    lengths.uncheckedAppend(makeUnique<CalcExpressionLength>(length));
 
356
    auto op = makeUnique<CalcExpressionOperation>(WTFMove(lengths), CalcOperator::Subtract);
 
357
    return Length(CalculationValue::create(WTFMove(op), ValueRangeAll));
 
358
}
 
359
 
 
360
inline Length BuilderConverter::convertPositionComponentX(BuilderState& builderState, const CSSValue& value)
 
361
{
 
362
    return convertPositionComponent<CSSValueLeft, CSSValueRight>(builderState, downcast<CSSPrimitiveValue>(value));
 
363
}
 
364
 
 
365
inline Length BuilderConverter::convertPositionComponentY(BuilderState& builderState, const CSSValue& value)
 
366
{
 
367
    return convertPositionComponent<CSSValueTop, CSSValueBottom>(builderState, downcast<CSSPrimitiveValue>(value));
 
368
}
 
369
 
 
370
template<CSSValueID cssValueFor0, CSSValueID cssValueFor100>
 
371
inline Length BuilderConverter::convertPositionComponent(BuilderState& builderState, const CSSPrimitiveValue& value)
 
372
{
 
373
    Length length;
 
374
 
 
375
    auto* lengthValue = &value;
 
376
    bool relativeToTrailingEdge = false;
 
377
    
 
378
    if (value.isPair()) {
 
379
        auto& first = *value.pairValue()->first();
 
380
        if (first.valueID() == CSSValueRight || first.valueID() == CSSValueBottom)
 
381
            relativeToTrailingEdge = true;
 
382
        lengthValue = value.pairValue()->second();
 
383
    }
 
384
    
 
385
    if (value.isValueID()) {
 
386
        switch (value.valueID()) {
 
387
        case cssValueFor0:
 
388
            return Length(0, Percent);
 
389
        case cssValueFor100:
 
390
            return Length(100, Percent);
 
391
        case CSSValueCenter:
 
392
            return Length(50, Percent);
 
393
        default:
 
394
            ASSERT_NOT_REACHED();
 
395
        }
 
396
    }
 
397
        
 
398
    length = convertLength(builderState, *lengthValue);
 
399
 
 
400
    if (relativeToTrailingEdge)
 
401
        length = convertTo100PercentMinusLength(length);
 
402
 
 
403
    return length;
 
404
}
 
405
 
 
406
inline LengthPoint BuilderConverter::convertObjectPosition(BuilderState& builderState, const CSSValue& value)
 
407
{
 
408
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
409
    Pair* pair = primitiveValue.pairValue();
 
410
    if (!pair || !pair->first() || !pair->second())
 
411
        return RenderStyle::initialObjectPosition();
 
412
 
 
413
    Length lengthX = convertPositionComponent<CSSValueLeft, CSSValueRight>(builderState, *pair->first());
 
414
    Length lengthY = convertPositionComponent<CSSValueTop, CSSValueBottom>(builderState, *pair->second());
 
415
 
 
416
    return LengthPoint(lengthX, lengthY);
 
417
}
 
418
 
 
419
inline OptionSet<TextDecoration> BuilderConverter::convertTextDecoration(BuilderState&, const CSSValue& value)
 
420
{
 
421
    auto result = RenderStyle::initialTextDecoration();
 
422
    if (is<CSSValueList>(value)) {
 
423
        for (auto& currentValue : downcast<CSSValueList>(value))
 
424
            result.add(downcast<CSSPrimitiveValue>(currentValue.get()));
 
425
    }
 
426
    return result;
 
427
}
 
428
 
 
429
template<typename T>
 
430
inline T BuilderConverter::convertNumber(BuilderState&, const CSSValue& value)
 
431
{
 
432
    return downcast<CSSPrimitiveValue>(value).value<T>(CSSUnitType::CSS_NUMBER);
 
433
}
 
434
 
 
435
template<typename T>
 
436
inline T BuilderConverter::convertNumberOrAuto(BuilderState& builderState, const CSSValue& value)
 
437
{
 
438
    if (downcast<CSSPrimitiveValue>(value).valueID() == CSSValueAuto)
 
439
        return -1;
 
440
    return convertNumber<T>(builderState, value);
 
441
}
 
442
 
 
443
inline short BuilderConverter::convertWebkitHyphenateLimitLines(BuilderState&, const CSSValue& value)
 
444
{
 
445
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
446
    if (primitiveValue.valueID() == CSSValueNoLimit)
 
447
        return -1;
 
448
    return primitiveValue.value<short>(CSSUnitType::CSS_NUMBER);
 
449
}
 
450
 
 
451
template<CSSPropertyID property>
 
452
inline NinePieceImage BuilderConverter::convertBorderImage(BuilderState& builderState, CSSValue& value)
 
453
{
 
454
    NinePieceImage image;
 
455
    builderState.styleMap().mapNinePieceImage(property, &value, image);
 
456
    return image;
 
457
}
 
458
 
 
459
template<CSSPropertyID property>
 
460
inline NinePieceImage BuilderConverter::convertBorderMask(BuilderState& builderState, CSSValue& value)
 
461
{
 
462
    NinePieceImage image(NinePieceImage::Type::Mask);
 
463
    builderState.styleMap().mapNinePieceImage(property, &value, image);
 
464
    return image;
 
465
}
 
466
 
 
467
template<CSSPropertyID>
 
468
inline RefPtr<StyleImage> BuilderConverter::convertStyleImage(BuilderState& builderState, CSSValue& value)
 
469
{
 
470
    return builderState.createStyleImage(value);
 
471
}
 
472
 
 
473
inline ImageOrientation BuilderConverter::convertImageOrientation(BuilderState&, const CSSValue& value)
 
474
{
 
475
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
476
    if (primitiveValue.valueID() == CSSValueFromImage)
 
477
        return ImageOrientation::FromImage;
 
478
    return ImageOrientation::None;
 
479
}
 
480
 
 
481
inline TransformOperations BuilderConverter::convertTransform(BuilderState& builderState, const CSSValue& value)
 
482
{
 
483
    TransformOperations operations;
 
484
    transformsForValue(value, builderState.cssToLengthConversionData(), operations);
 
485
    return operations;
 
486
}
 
487
 
 
488
#if ENABLE(DARK_MODE_CSS)
 
489
inline void BuilderConverter::updateColorScheme(const CSSPrimitiveValue& primitiveValue, StyleColorScheme& colorScheme)
 
490
{
 
491
    ASSERT(primitiveValue.isValueID());
 
492
 
 
493
    switch (primitiveValue.valueID()) {
 
494
    case CSSValueAuto:
 
495
        colorScheme = StyleColorScheme();
 
496
        break;
 
497
    case CSSValueOnly:
 
498
        colorScheme.setAllowsTransformations(false);
 
499
        break;
 
500
    case CSSValueLight:
 
501
        colorScheme.add(ColorScheme::Light);
 
502
        break;
 
503
    case CSSValueDark:
 
504
        colorScheme.add(ColorScheme::Dark);
 
505
        break;
 
506
    default:
 
507
        // Unknown identifiers are allowed and ignored.
 
508
        break;
 
509
    }
 
510
}
 
511
 
 
512
inline StyleColorScheme BuilderConverter::convertColorScheme(BuilderState&, const CSSValue& value)
 
513
{
 
514
    StyleColorScheme colorScheme;
 
515
 
 
516
    if (is<CSSValueList>(value)) {
 
517
        for (auto& currentValue : downcast<CSSValueList>(value))
 
518
            updateColorScheme(downcast<CSSPrimitiveValue>(currentValue.get()), colorScheme);
 
519
    } else if (is<CSSPrimitiveValue>(value))
 
520
        updateColorScheme(downcast<CSSPrimitiveValue>(value), colorScheme);
 
521
 
 
522
    // If the value was just "only", that is synonymous for "only light".
 
523
    if (colorScheme.isOnly())
 
524
        colorScheme.add(ColorScheme::Light);
 
525
 
 
526
    return colorScheme;
 
527
}
 
528
#endif
 
529
 
 
530
inline String BuilderConverter::convertString(BuilderState&, const CSSValue& value)
 
531
{
 
532
    return downcast<CSSPrimitiveValue>(value).stringValue();
 
533
}
 
534
 
 
535
inline String BuilderConverter::convertStringOrAuto(BuilderState& builderState, const CSSValue& value)
 
536
{
 
537
    if (downcast<CSSPrimitiveValue>(value).valueID() == CSSValueAuto)
 
538
        return nullAtom();
 
539
    return convertString(builderState, value);
 
540
}
 
541
 
 
542
inline String BuilderConverter::convertStringOrNone(BuilderState& builderState, const CSSValue& value)
 
543
{
 
544
    if (downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone)
 
545
        return nullAtom();
 
546
    return convertString(builderState, value);
 
547
}
 
548
 
 
549
inline OptionSet<TextEmphasisPosition> BuilderConverter::valueToEmphasisPosition(const CSSPrimitiveValue& primitiveValue)
 
550
{
 
551
    ASSERT(primitiveValue.isValueID());
 
552
 
 
553
    switch (primitiveValue.valueID()) {
 
554
    case CSSValueOver:
 
555
        return TextEmphasisPosition::Over;
 
556
    case CSSValueUnder:
 
557
        return TextEmphasisPosition::Under;
 
558
    case CSSValueLeft:
 
559
        return TextEmphasisPosition::Left;
 
560
    case CSSValueRight:
 
561
        return TextEmphasisPosition::Right;
 
562
    default:
 
563
        break;
 
564
    }
 
565
 
 
566
    ASSERT_NOT_REACHED();
 
567
    return RenderStyle::initialTextEmphasisPosition();
 
568
}
 
569
 
 
570
inline OptionSet<TextEmphasisPosition> BuilderConverter::convertTextEmphasisPosition(BuilderState&, const CSSValue& value)
 
571
{
 
572
    if (is<CSSPrimitiveValue>(value))
 
573
        return valueToEmphasisPosition(downcast<CSSPrimitiveValue>(value));
 
574
 
 
575
    OptionSet<TextEmphasisPosition> position;
 
576
    for (auto& currentValue : downcast<CSSValueList>(value))
 
577
        position.add(valueToEmphasisPosition(downcast<CSSPrimitiveValue>(currentValue.get())));
 
578
    return position;
 
579
}
 
580
 
 
581
inline TextAlignMode BuilderConverter::convertTextAlign(BuilderState& builderState, const CSSValue& value)
 
582
{
 
583
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
584
    ASSERT(primitiveValue.isValueID());
 
585
 
 
586
    if (primitiveValue.valueID() != CSSValueWebkitMatchParent)
 
587
        return primitiveValue;
 
588
 
 
589
    auto& parentStyle = builderState.parentStyle();
 
590
    if (parentStyle.textAlign() == TextAlignMode::Start)
 
591
        return parentStyle.isLeftToRightDirection() ? TextAlignMode::Left : TextAlignMode::Right;
 
592
    if (parentStyle.textAlign() == TextAlignMode::End)
 
593
        return parentStyle.isLeftToRightDirection() ? TextAlignMode::Right : TextAlignMode::Left;
 
594
    return parentStyle.textAlign();
 
595
}
 
596
 
 
597
inline RefPtr<ClipPathOperation> BuilderConverter::convertClipPath(BuilderState& builderState, const CSSValue& value)
 
598
{
 
599
    if (is<CSSPrimitiveValue>(value)) {
 
600
        auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
601
        if (primitiveValue.primitiveType() == CSSUnitType::CSS_URI) {
 
602
            String cssURLValue = primitiveValue.stringValue();
 
603
            String fragment = SVGURIReference::fragmentIdentifierFromIRIString(cssURLValue, builderState.document());
 
604
            // FIXME: It doesn't work with external SVG references (see https://bugs.webkit.org/show_bug.cgi?id=126133)
 
605
            return ReferenceClipPathOperation::create(cssURLValue, fragment);
 
606
        }
 
607
        ASSERT(primitiveValue.valueID() == CSSValueNone);
 
608
        return nullptr;
 
609
    }
 
610
 
 
611
    CSSBoxType referenceBox = CSSBoxType::BoxMissing;
 
612
    RefPtr<ClipPathOperation> operation;
 
613
 
 
614
    for (auto& currentValue : downcast<CSSValueList>(value)) {
 
615
        auto& primitiveValue = downcast<CSSPrimitiveValue>(currentValue.get());
 
616
        if (primitiveValue.isShape()) {
 
617
            ASSERT(!operation);
 
618
            operation = ShapeClipPathOperation::create(basicShapeForValue(builderState.cssToLengthConversionData(), *primitiveValue.shapeValue()));
 
619
        } else {
 
620
            ASSERT(primitiveValue.valueID() == CSSValueContentBox
 
621
                || primitiveValue.valueID() == CSSValueBorderBox
 
622
                || primitiveValue.valueID() == CSSValuePaddingBox
 
623
                || primitiveValue.valueID() == CSSValueMarginBox
 
624
                || primitiveValue.valueID() == CSSValueFillBox
 
625
                || primitiveValue.valueID() == CSSValueStrokeBox
 
626
                || primitiveValue.valueID() == CSSValueViewBox);
 
627
            ASSERT(referenceBox == CSSBoxType::BoxMissing);
 
628
            referenceBox = primitiveValue;
 
629
        }
 
630
    }
 
631
    if (operation)
 
632
        downcast<ShapeClipPathOperation>(*operation).setReferenceBox(referenceBox);
 
633
    else {
 
634
        ASSERT(referenceBox != CSSBoxType::BoxMissing);
 
635
        operation = BoxClipPathOperation::create(referenceBox);
 
636
    }
 
637
 
 
638
    return operation;
 
639
}
 
640
 
 
641
inline Resize BuilderConverter::convertResize(BuilderState& builderState, const CSSValue& value)
 
642
{
 
643
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
644
 
 
645
    Resize resize = Resize::None;
 
646
    if (primitiveValue.valueID() == CSSValueAuto)
 
647
        resize = builderState.document().settings().textAreasAreResizable() ? Resize::Both : Resize::None;
 
648
    else
 
649
        resize = primitiveValue;
 
650
 
 
651
    return resize;
 
652
}
 
653
 
 
654
inline int BuilderConverter::convertMarqueeRepetition(BuilderState&, const CSSValue& value)
 
655
{
 
656
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
657
    if (primitiveValue.valueID() == CSSValueInfinite)
 
658
        return -1; // -1 means repeat forever.
 
659
 
 
660
    ASSERT(primitiveValue.isNumber());
 
661
    return primitiveValue.intValue();
 
662
}
 
663
 
 
664
inline int BuilderConverter::convertMarqueeSpeed(BuilderState&, const CSSValue& value)
 
665
{
 
666
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
667
    if (primitiveValue.isTime())
 
668
        return primitiveValue.computeTime<int, CSSPrimitiveValue::Milliseconds>();
 
669
    // For scrollamount support.
 
670
    ASSERT(primitiveValue.isNumber());
 
671
    return primitiveValue.intValue();
 
672
}
 
673
 
 
674
inline Ref<QuotesData> BuilderConverter::convertQuotes(BuilderState&, const CSSValue& value)
 
675
{
 
676
    if (is<CSSPrimitiveValue>(value)) {
 
677
        ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
 
678
        return QuotesData::create(Vector<std::pair<String, String>>());
 
679
    }
 
680
 
 
681
    auto& list = downcast<CSSValueList>(value);
 
682
    Vector<std::pair<String, String>> quotes;
 
683
    quotes.reserveInitialCapacity(list.length() / 2);
 
684
    for (unsigned i = 0; i < list.length(); i += 2) {
 
685
        const CSSValue* first = list.itemWithoutBoundsCheck(i);
 
686
        // item() returns null if out of bounds so this is safe.
 
687
        const CSSValue* second = list.item(i + 1);
 
688
        if (!second)
 
689
            break;
 
690
        String startQuote = downcast<CSSPrimitiveValue>(*first).stringValue();
 
691
        String endQuote = downcast<CSSPrimitiveValue>(*second).stringValue();
 
692
        quotes.append(std::make_pair(startQuote, endQuote));
 
693
    }
 
694
    return QuotesData::create(quotes);
 
695
}
 
696
 
 
697
inline TextUnderlinePosition BuilderConverter::convertTextUnderlinePosition(BuilderState&, const CSSValue& value)
 
698
{
 
699
    ASSERT(is<CSSPrimitiveValue>(value));
 
700
    return downcast<CSSPrimitiveValue>(value);
 
701
}
 
702
 
 
703
inline TextUnderlineOffset BuilderConverter::convertTextUnderlineOffset(BuilderState& builderState, const CSSValue& value)
 
704
{
 
705
    ASSERT(is<CSSPrimitiveValue>(value));
 
706
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
707
    switch (primitiveValue.valueID()) {
 
708
    case CSSValueAuto:
 
709
        return TextUnderlineOffset::createWithAuto();
 
710
    default:
 
711
        ASSERT(primitiveValue.isLength());
 
712
        auto computedLength = convertComputedLength<float>(builderState, primitiveValue);
 
713
        return TextUnderlineOffset::createWithLength(computedLength);
 
714
    }
 
715
}
 
716
 
 
717
inline TextDecorationThickness BuilderConverter::convertTextDecorationThickness(BuilderState& builderState, const CSSValue& value)
 
718
{
 
719
    ASSERT(is<CSSPrimitiveValue>(value));
 
720
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
721
    switch (primitiveValue.valueID()) {
 
722
    case CSSValueAuto:
 
723
        return TextDecorationThickness::createWithAuto();
 
724
    case CSSValueFromFont:
 
725
        return TextDecorationThickness::createFromFont();
 
726
    default:
 
727
        ASSERT(primitiveValue.isLength());
 
728
        auto computedLength = convertComputedLength<float>(builderState, primitiveValue);
 
729
        return TextDecorationThickness::createWithLength(computedLength);
 
730
    }
 
731
}
 
732
 
 
733
inline RefPtr<StyleReflection> BuilderConverter::convertReflection(BuilderState& builderState, const CSSValue& value)
 
734
{
 
735
    if (is<CSSPrimitiveValue>(value)) {
 
736
        ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
 
737
        return nullptr;
 
738
    }
 
739
 
 
740
    auto& reflectValue = downcast<CSSReflectValue>(value);
 
741
 
 
742
    auto reflection = StyleReflection::create();
 
743
    reflection->setDirection(reflectValue.direction());
 
744
    reflection->setOffset(reflectValue.offset().convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(builderState.cssToLengthConversionData()));
 
745
 
 
746
    NinePieceImage mask(NinePieceImage::Type::Mask);
 
747
    builderState.styleMap().mapNinePieceImage(CSSPropertyWebkitBoxReflect, reflectValue.mask(), mask);
 
748
    reflection->setMask(mask);
 
749
 
 
750
    return reflection;
 
751
}
 
752
 
 
753
inline IntSize BuilderConverter::convertInitialLetter(BuilderState&, const CSSValue& value)
 
754
{
 
755
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
756
 
 
757
    if (primitiveValue.valueID() == CSSValueNormal)
 
758
        return IntSize();
 
759
 
 
760
    Pair* pair = primitiveValue.pairValue();
 
761
    ASSERT(pair);
 
762
    ASSERT(pair->first());
 
763
    ASSERT(pair->second());
 
764
 
 
765
    return IntSize(pair->first()->intValue(), pair->second()->intValue());
 
766
}
 
767
 
 
768
inline float BuilderConverter::convertTextStrokeWidth(BuilderState& builderState, const CSSValue& value)
 
769
{
 
770
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
771
 
 
772
    float width = 0;
 
773
    switch (primitiveValue.valueID()) {
 
774
    case CSSValueThin:
 
775
    case CSSValueMedium:
 
776
    case CSSValueThick: {
 
777
        double result = 1.0 / 48;
 
778
        if (primitiveValue.valueID() == CSSValueMedium)
 
779
            result *= 3;
 
780
        else if (primitiveValue.valueID() == CSSValueThick)
 
781
            result *= 5;
 
782
        Ref<CSSPrimitiveValue> emsValue(CSSPrimitiveValue::create(result, CSSUnitType::CSS_EMS));
 
783
        width = convertComputedLength<float>(builderState, emsValue);
 
784
        break;
 
785
    }
 
786
    case CSSValueInvalid: {
 
787
        width = convertComputedLength<float>(builderState, primitiveValue);
 
788
        break;
 
789
    }
 
790
    default:
 
791
        ASSERT_NOT_REACHED();
 
792
        return 0;
 
793
    }
 
794
 
 
795
    return width;
 
796
}
 
797
 
 
798
inline OptionSet<LineBoxContain> BuilderConverter::convertLineBoxContain(BuilderState&, const CSSValue& value)
 
799
{
 
800
    if (is<CSSPrimitiveValue>(value)) {
 
801
        ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
 
802
        return { };
 
803
    }
 
804
 
 
805
    return downcast<CSSLineBoxContainValue>(value).value();
 
806
}
 
807
 
 
808
inline OptionSet<TextDecorationSkip> BuilderConverter::valueToDecorationSkip(const CSSPrimitiveValue& primitiveValue)
 
809
{
 
810
    ASSERT(primitiveValue.isValueID());
 
811
 
 
812
    switch (primitiveValue.valueID()) {
 
813
    case CSSValueAuto:
 
814
        return TextDecorationSkip::Auto;
 
815
    case CSSValueNone:
 
816
        return OptionSet<TextDecorationSkip> { };
 
817
    case CSSValueInk:
 
818
        return TextDecorationSkip::Ink;
 
819
    case CSSValueObjects:
 
820
        return TextDecorationSkip::Objects;
 
821
    default:
 
822
        break;
 
823
    }
 
824
 
 
825
    ASSERT_NOT_REACHED();
 
826
    return OptionSet<TextDecorationSkip> { };
 
827
}
 
828
 
 
829
inline OptionSet<TextDecorationSkip> BuilderConverter::convertTextDecorationSkip(BuilderState&, const CSSValue& value)
 
830
{
 
831
    if (is<CSSPrimitiveValue>(value))
 
832
        return valueToDecorationSkip(downcast<CSSPrimitiveValue>(value));
 
833
 
 
834
    OptionSet<TextDecorationSkip> skip;
 
835
    for (auto& currentValue : downcast<CSSValueList>(value))
 
836
        skip.add(valueToDecorationSkip(downcast<CSSPrimitiveValue>(currentValue.get())));
 
837
    return skip;
 
838
}
 
839
 
 
840
static inline bool isImageShape(const CSSValue& value)
 
841
{
 
842
    return is<CSSImageValue>(value) || is<CSSImageSetValue>(value) || is<CSSImageGeneratorValue>(value);
 
843
}
 
844
 
 
845
inline RefPtr<ShapeValue> BuilderConverter::convertShapeValue(BuilderState& builderState, CSSValue& value)
 
846
{
 
847
    if (is<CSSPrimitiveValue>(value)) {
 
848
        ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
 
849
        return nullptr;
 
850
    }
 
851
 
 
852
    if (isImageShape(value))
 
853
        return ShapeValue::create(builderState.createStyleImage(value).releaseNonNull());
 
854
 
 
855
    RefPtr<BasicShape> shape;
 
856
    CSSBoxType referenceBox = CSSBoxType::BoxMissing;
 
857
    for (auto& currentValue : downcast<CSSValueList>(value)) {
 
858
        auto& primitiveValue = downcast<CSSPrimitiveValue>(currentValue.get());
 
859
        if (primitiveValue.isShape())
 
860
            shape = basicShapeForValue(builderState.cssToLengthConversionData(), *primitiveValue.shapeValue());
 
861
        else if (primitiveValue.valueID() == CSSValueContentBox
 
862
            || primitiveValue.valueID() == CSSValueBorderBox
 
863
            || primitiveValue.valueID() == CSSValuePaddingBox
 
864
            || primitiveValue.valueID() == CSSValueMarginBox)
 
865
            referenceBox = primitiveValue;
 
866
        else {
 
867
            ASSERT_NOT_REACHED();
 
868
            return nullptr;
 
869
        }
 
870
    }
 
871
 
 
872
    if (shape)
 
873
        return ShapeValue::create(shape.releaseNonNull(), referenceBox);
 
874
 
 
875
    if (referenceBox != CSSBoxType::BoxMissing)
 
876
        return ShapeValue::create(referenceBox);
 
877
 
 
878
    ASSERT_NOT_REACHED();
 
879
    return nullptr;
 
880
}
 
881
 
 
882
#if ENABLE(CSS_SCROLL_SNAP)
 
883
 
 
884
inline ScrollSnapType BuilderConverter::convertScrollSnapType(BuilderState&, const CSSValue& value)
 
885
{
 
886
    ScrollSnapType type;
 
887
    auto& values = downcast<CSSValueList>(value);
 
888
    auto& firstValue = downcast<CSSPrimitiveValue>(*values.item(0));
 
889
    if (values.length() == 2) {
 
890
        type.axis = firstValue;
 
891
        type.strictness = downcast<CSSPrimitiveValue>(*values.item(1));
 
892
        return type;
 
893
    }
 
894
 
 
895
    switch (firstValue.valueID()) {
 
896
    case CSSValueNone:
 
897
    case CSSValueMandatory:
 
898
    case CSSValueProximity:
 
899
        type.strictness = firstValue;
 
900
        break;
 
901
    default:
 
902
        type.axis = firstValue;
 
903
        type.strictness = ScrollSnapStrictness::Proximity;
 
904
        break;
 
905
    }
 
906
    return type;
 
907
}
 
908
 
 
909
inline ScrollSnapAlign BuilderConverter::convertScrollSnapAlign(BuilderState&, const CSSValue& value)
 
910
{
 
911
    auto& values = downcast<CSSValueList>(value);
 
912
    ScrollSnapAlign alignment;
 
913
    alignment.x = downcast<CSSPrimitiveValue>(*values.item(0));
 
914
    if (values.length() == 1)
 
915
        alignment.y = alignment.x;
 
916
    else
 
917
        alignment.y = downcast<CSSPrimitiveValue>(*values.item(1));
 
918
    return alignment;
 
919
}
 
920
 
 
921
#endif
 
922
 
 
923
inline GridLength BuilderConverter::createGridTrackBreadth(const CSSPrimitiveValue& primitiveValue, BuilderState& builderState)
 
924
{
 
925
    if (primitiveValue.valueID() == CSSValueMinContent || primitiveValue.valueID() == CSSValueWebkitMinContent)
 
926
        return Length(MinContent);
 
927
 
 
928
    if (primitiveValue.valueID() == CSSValueMaxContent || primitiveValue.valueID() == CSSValueWebkitMaxContent)
 
929
        return Length(MaxContent);
 
930
 
 
931
    // Fractional unit.
 
932
    if (primitiveValue.isFlex())
 
933
        return GridLength(primitiveValue.doubleValue());
 
934
 
 
935
    return primitiveValue.convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion | AutoConversion>(builderState.cssToLengthConversionData());
 
936
}
 
937
 
 
938
inline GridTrackSize BuilderConverter::createGridTrackSize(const CSSValue& value, BuilderState& builderState)
 
939
{
 
940
    if (is<CSSPrimitiveValue>(value))
 
941
        return GridTrackSize(createGridTrackBreadth(downcast<CSSPrimitiveValue>(value), builderState));
 
942
 
 
943
    ASSERT(is<CSSFunctionValue>(value));
 
944
    const auto& function = downcast<CSSFunctionValue>(value);
 
945
 
 
946
    if (function.length() == 1)
 
947
        return GridTrackSize(createGridTrackBreadth(downcast<CSSPrimitiveValue>(*function.itemWithoutBoundsCheck(0)), builderState), FitContentTrackSizing);
 
948
 
 
949
    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(function.length() == 2);
 
950
    GridLength minTrackBreadth(createGridTrackBreadth(downcast<CSSPrimitiveValue>(*function.itemWithoutBoundsCheck(0)), builderState));
 
951
    GridLength maxTrackBreadth(createGridTrackBreadth(downcast<CSSPrimitiveValue>(*function.itemWithoutBoundsCheck(1)), builderState));
 
952
    return GridTrackSize(minTrackBreadth, maxTrackBreadth);
 
953
}
 
954
 
 
955
static void createGridLineNamesList(const CSSValue& value, unsigned currentNamedGridLine, NamedGridLinesMap& namedGridLines, OrderedNamedGridLinesMap& orderedNamedGridLines)
 
956
{
 
957
    ASSERT(value.isGridLineNamesValue());
 
958
 
 
959
    for (auto& namedGridLineValue : downcast<CSSGridLineNamesValue>(value)) {
 
960
        String namedGridLine = downcast<CSSPrimitiveValue>(namedGridLineValue.get()).stringValue();
 
961
        auto result = namedGridLines.add(namedGridLine, Vector<unsigned>());
 
962
        result.iterator->value.append(currentNamedGridLine);
 
963
        auto orderedResult = orderedNamedGridLines.add(currentNamedGridLine, Vector<String>());
 
964
        orderedResult.iterator->value.append(namedGridLine);
 
965
    }
 
966
}
 
967
 
 
968
struct BuilderConverter::TracksData {
 
969
    WTF_MAKE_NONCOPYABLE(TracksData); WTF_MAKE_FAST_ALLOCATED;
 
970
public:
 
971
    TracksData() = default;
 
972
 
 
973
    Vector<GridTrackSize> m_trackSizes;
 
974
    NamedGridLinesMap m_namedGridLines;
 
975
    OrderedNamedGridLinesMap m_orderedNamedGridLines;
 
976
    Vector<GridTrackSize> m_autoRepeatTrackSizes;
 
977
    NamedGridLinesMap m_autoRepeatNamedGridLines;
 
978
    OrderedNamedGridLinesMap m_autoRepeatOrderedNamedGridLines;
 
979
    unsigned m_autoRepeatInsertionPoint { RenderStyle::initialGridAutoRepeatInsertionPoint() };
 
980
    AutoRepeatType m_autoRepeatType { RenderStyle::initialGridAutoRepeatType() };
 
981
};
 
982
 
 
983
inline bool BuilderConverter::createGridTrackList(const CSSValue& value, TracksData& tracksData, BuilderState& builderState)
 
984
{
 
985
    // Handle 'none'.
 
986
    if (is<CSSPrimitiveValue>(value))
 
987
        return downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone;
 
988
 
 
989
    if (!is<CSSValueList>(value))
 
990
        return false;
 
991
 
 
992
    unsigned currentNamedGridLine = 0;
 
993
    auto handleLineNameOrTrackSize = [&](const CSSValue& currentValue) {
 
994
        if (is<CSSGridLineNamesValue>(currentValue))
 
995
            createGridLineNamesList(currentValue, currentNamedGridLine, tracksData.m_namedGridLines, tracksData.m_orderedNamedGridLines);
 
996
        else {
 
997
            ++currentNamedGridLine;
 
998
            tracksData.m_trackSizes.append(createGridTrackSize(currentValue, builderState));
 
999
        }
 
1000
    };
 
1001
 
 
1002
    for (auto& currentValue : downcast<CSSValueList>(value)) {
 
1003
        if (is<CSSGridAutoRepeatValue>(currentValue)) {
 
1004
            ASSERT(tracksData.m_autoRepeatTrackSizes.isEmpty());
 
1005
            unsigned autoRepeatIndex = 0;
 
1006
            CSSValueID autoRepeatID = downcast<CSSGridAutoRepeatValue>(currentValue.get()).autoRepeatID();
 
1007
            ASSERT(autoRepeatID == CSSValueAutoFill || autoRepeatID == CSSValueAutoFit);
 
1008
            tracksData.m_autoRepeatType = autoRepeatID == CSSValueAutoFill ? AutoRepeatType::Fill : AutoRepeatType::Fit;
 
1009
            for (auto& autoRepeatValue : downcast<CSSValueList>(currentValue.get())) {
 
1010
                if (is<CSSGridLineNamesValue>(autoRepeatValue)) {
 
1011
                    createGridLineNamesList(autoRepeatValue.get(), autoRepeatIndex, tracksData.m_autoRepeatNamedGridLines, tracksData.m_autoRepeatOrderedNamedGridLines);
 
1012
                    continue;
 
1013
                }
 
1014
                ++autoRepeatIndex;
 
1015
                tracksData.m_autoRepeatTrackSizes.append(createGridTrackSize(autoRepeatValue.get(), builderState));
 
1016
            }
 
1017
            tracksData.m_autoRepeatInsertionPoint = currentNamedGridLine++;
 
1018
            continue;
 
1019
        }
 
1020
 
 
1021
        if (is<CSSGridIntegerRepeatValue>(currentValue)) {
 
1022
            size_t repetitions = downcast<CSSGridIntegerRepeatValue>(currentValue.get()).repetitions();
 
1023
            for (size_t i = 0; i < repetitions; ++i) {
 
1024
                for (auto& integerRepeatValue : downcast<CSSValueList>(currentValue.get()))
 
1025
                    handleLineNameOrTrackSize(integerRepeatValue);
 
1026
            }
 
1027
            continue;
 
1028
        }
 
1029
 
 
1030
        handleLineNameOrTrackSize(currentValue);
 
1031
    }
 
1032
 
 
1033
    // The parser should have rejected any <track-list> without any <track-size> as
 
1034
    // this is not conformant to the syntax.
 
1035
    ASSERT(!tracksData.m_trackSizes.isEmpty() || !tracksData.m_autoRepeatTrackSizes.isEmpty());
 
1036
    return true;
 
1037
}
 
1038
 
 
1039
inline bool BuilderConverter::createGridPosition(const CSSValue& value, GridPosition& position)
 
1040
{
 
1041
    // We accept the specification's grammar:
 
1042
    // auto | <custom-ident> | [ <integer> && <custom-ident>? ] | [ span && [ <integer> || <custom-ident> ] ]
 
1043
    if (is<CSSPrimitiveValue>(value)) {
 
1044
        auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
1045
        // We translate <ident> to <string> during parsing as it makes handling it simpler.
 
1046
        if (primitiveValue.isString()) {
 
1047
            position.setNamedGridArea(primitiveValue.stringValue());
 
1048
            return true;
 
1049
        }
 
1050
 
 
1051
        ASSERT(primitiveValue.valueID() == CSSValueAuto);
 
1052
        return true;
 
1053
    }
 
1054
 
 
1055
    auto& values = downcast<CSSValueList>(value);
 
1056
    ASSERT(values.length());
 
1057
 
 
1058
    auto it = values.begin();
 
1059
    const CSSPrimitiveValue* currentValue = &downcast<CSSPrimitiveValue>(it->get());
 
1060
    bool isSpanPosition = false;
 
1061
    if (currentValue->valueID() == CSSValueSpan) {
 
1062
        isSpanPosition = true;
 
1063
        ++it;
 
1064
        currentValue = it != values.end() ? &downcast<CSSPrimitiveValue>(it->get()) : nullptr;
 
1065
    }
 
1066
 
 
1067
    int gridLineNumber = 0;
 
1068
    if (currentValue && currentValue->isNumber()) {
 
1069
        gridLineNumber = currentValue->intValue();
 
1070
        ++it;
 
1071
        currentValue = it != values.end() ? &downcast<CSSPrimitiveValue>(it->get()) : nullptr;
 
1072
    }
 
1073
 
 
1074
    String gridLineName;
 
1075
    if (currentValue && currentValue->isString()) {
 
1076
        gridLineName = currentValue->stringValue();
 
1077
        ++it;
 
1078
    }
 
1079
 
 
1080
    ASSERT(it == values.end());
 
1081
    if (isSpanPosition)
 
1082
        position.setSpanPosition(gridLineNumber ? gridLineNumber : 1, gridLineName);
 
1083
    else
 
1084
        position.setExplicitPosition(gridLineNumber, gridLineName);
 
1085
 
 
1086
    return true;
 
1087
}
 
1088
 
 
1089
inline void BuilderConverter::createImplicitNamedGridLinesFromGridArea(const NamedGridAreaMap& namedGridAreas, NamedGridLinesMap& namedGridLines, GridTrackSizingDirection direction)
 
1090
{
 
1091
    for (auto& area : namedGridAreas) {
 
1092
        GridSpan areaSpan = direction == ForRows ? area.value.rows : area.value.columns;
 
1093
        {
 
1094
            auto& startVector = namedGridLines.add(area.key + "-start", Vector<unsigned>()).iterator->value;
 
1095
            startVector.append(areaSpan.startLine());
 
1096
            std::sort(startVector.begin(), startVector.end());
 
1097
        }
 
1098
        {
 
1099
            auto& endVector = namedGridLines.add(area.key + "-end", Vector<unsigned>()).iterator->value;
 
1100
            endVector.append(areaSpan.endLine());
 
1101
            std::sort(endVector.begin(), endVector.end());
 
1102
        }
 
1103
    }
 
1104
}
 
1105
 
 
1106
inline Vector<GridTrackSize> BuilderConverter::convertGridTrackSizeList(BuilderState& builderState, const CSSValue& value)
 
1107
{
 
1108
    ASSERT(value.isValueList());
 
1109
    auto& valueList = downcast<CSSValueList>(value);
 
1110
    Vector<GridTrackSize> trackSizes;
 
1111
    trackSizes.reserveInitialCapacity(valueList.length());
 
1112
    for (auto& currValue : valueList) {
 
1113
        ASSERT(!currValue->isGridLineNamesValue());
 
1114
        ASSERT(!currValue->isGridAutoRepeatValue());
 
1115
        ASSERT(!currValue->isGridIntegerRepeatValue());
 
1116
        trackSizes.uncheckedAppend(convertGridTrackSize(builderState, currValue));
 
1117
    }
 
1118
    return trackSizes;
 
1119
}
 
1120
 
 
1121
inline GridTrackSize BuilderConverter::convertGridTrackSize(BuilderState& builderState, const CSSValue& value)
 
1122
{
 
1123
    return createGridTrackSize(value, builderState);
 
1124
}
 
1125
 
 
1126
inline Optional<GridPosition> BuilderConverter::convertGridPosition(BuilderState&, const CSSValue& value)
 
1127
{
 
1128
    GridPosition gridPosition;
 
1129
    if (createGridPosition(value, gridPosition))
 
1130
        return gridPosition;
 
1131
    return WTF::nullopt;
 
1132
}
 
1133
 
 
1134
inline GridAutoFlow BuilderConverter::convertGridAutoFlow(BuilderState&, const CSSValue& value)
 
1135
{
 
1136
    auto& list = downcast<CSSValueList>(value);
 
1137
    if (!list.length())
 
1138
        return RenderStyle::initialGridAutoFlow();
 
1139
 
 
1140
    auto& first = downcast<CSSPrimitiveValue>(*list.item(0));
 
1141
    auto* second = downcast<CSSPrimitiveValue>(list.item(1));
 
1142
 
 
1143
    GridAutoFlow autoFlow;
 
1144
    switch (first.valueID()) {
 
1145
    case CSSValueRow:
 
1146
        if (second && second->valueID() == CSSValueDense)
 
1147
            autoFlow = AutoFlowRowDense;
 
1148
        else
 
1149
            autoFlow = AutoFlowRow;
 
1150
        break;
 
1151
    case CSSValueColumn:
 
1152
        if (second && second->valueID() == CSSValueDense)
 
1153
            autoFlow = AutoFlowColumnDense;
 
1154
        else
 
1155
            autoFlow = AutoFlowColumn;
 
1156
        break;
 
1157
    case CSSValueDense:
 
1158
        if (second && second->valueID() == CSSValueColumn)
 
1159
            autoFlow = AutoFlowColumnDense;
 
1160
        else
 
1161
            autoFlow = AutoFlowRowDense;
 
1162
        break;
 
1163
    default:
 
1164
        ASSERT_NOT_REACHED();
 
1165
        autoFlow = RenderStyle::initialGridAutoFlow();
 
1166
        break;
 
1167
    }
 
1168
 
 
1169
    return autoFlow;
 
1170
}
 
1171
 
 
1172
inline CSSToLengthConversionData BuilderConverter::csstoLengthConversionDataWithTextZoomFactor(BuilderState& builderState)
 
1173
{
 
1174
    if (auto* frame = builderState.document().frame()) {
 
1175
        float textZoomFactor = builderState.style().textZoom() != TextZoom::Reset ? frame->textZoomFactor() : 1.0f;
 
1176
        return builderState.cssToLengthConversionData().copyWithAdjustedZoom(builderState.style().effectiveZoom() * textZoomFactor);
 
1177
    }
 
1178
    return builderState.cssToLengthConversionData();
 
1179
}
 
1180
 
 
1181
inline Optional<Length> BuilderConverter::convertWordSpacing(BuilderState& builderState, const CSSValue& value)
 
1182
{
 
1183
    Optional<Length> wordSpacing;
 
1184
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
1185
    if (primitiveValue.valueID() == CSSValueNormal)
 
1186
        wordSpacing = RenderStyle::initialWordSpacing();
 
1187
    else if (primitiveValue.isLength())
 
1188
        wordSpacing = primitiveValue.computeLength<Length>(csstoLengthConversionDataWithTextZoomFactor(builderState));
 
1189
    else if (primitiveValue.isPercentage())
 
1190
        wordSpacing = Length(clampTo<float>(primitiveValue.doubleValue(), minValueForCssLength, maxValueForCssLength), Percent);
 
1191
    else if (primitiveValue.isNumber())
 
1192
        wordSpacing = Length(primitiveValue.doubleValue(), Fixed);
 
1193
 
 
1194
    return wordSpacing;
 
1195
}
 
1196
 
 
1197
inline Optional<float> BuilderConverter::convertPerspective(BuilderState& builderState, const CSSValue& value)
 
1198
{
 
1199
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
1200
    if (primitiveValue.valueID() == CSSValueNone)
 
1201
        return 0.f;
 
1202
 
 
1203
    float perspective = -1;
 
1204
    if (primitiveValue.isLength())
 
1205
        perspective = primitiveValue.computeLength<float>(builderState.cssToLengthConversionData());
 
1206
    else if (primitiveValue.isNumber())
 
1207
        perspective = primitiveValue.doubleValue() * builderState.cssToLengthConversionData().zoom();
 
1208
    else
 
1209
        ASSERT_NOT_REACHED();
 
1210
 
 
1211
    return perspective < 0 ? Optional<float>(WTF::nullopt) : Optional<float>(perspective);
 
1212
}
 
1213
 
 
1214
inline Optional<Length> BuilderConverter::convertMarqueeIncrement(BuilderState& builderState, const CSSValue& value)
 
1215
{
 
1216
    Length length = downcast<CSSPrimitiveValue>(value).convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(builderState.cssToLengthConversionData().copyWithAdjustedZoom(1.0f));
 
1217
    if (length.isUndefined())
 
1218
        return WTF::nullopt;
 
1219
    return length;
 
1220
}
 
1221
 
 
1222
inline Optional<FilterOperations> BuilderConverter::convertFilterOperations(BuilderState& builderState, const CSSValue& value)
 
1223
{
 
1224
    FilterOperations operations;
 
1225
    if (builderState.createFilterOperations(value, operations))
 
1226
        return operations;
 
1227
    return WTF::nullopt;
 
1228
}
 
1229
 
 
1230
inline FontFeatureSettings BuilderConverter::convertFontFeatureSettings(BuilderState&, const CSSValue& value)
 
1231
{
 
1232
    if (is<CSSPrimitiveValue>(value)) {
 
1233
        ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNormal);
 
1234
        return { };
 
1235
    }
 
1236
 
 
1237
    FontFeatureSettings settings;
 
1238
    for (auto& item : downcast<CSSValueList>(value)) {
 
1239
        auto& feature = downcast<CSSFontFeatureValue>(item.get());
 
1240
        settings.insert(FontFeature(feature.tag(), feature.value()));
 
1241
    }
 
1242
    return settings;
 
1243
}
 
1244
 
 
1245
inline FontSelectionValue BuilderConverter::convertFontWeightFromValue(const CSSValue& value)
 
1246
{
 
1247
    ASSERT(is<CSSPrimitiveValue>(value));
 
1248
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
1249
 
 
1250
    if (primitiveValue.isNumber())
 
1251
        return FontSelectionValue::clampFloat(primitiveValue.floatValue());
 
1252
 
 
1253
    ASSERT(primitiveValue.isValueID());
 
1254
    switch (primitiveValue.valueID()) {
 
1255
    case CSSValueNormal:
 
1256
        return normalWeightValue();
 
1257
    case CSSValueBold:
 
1258
    case CSSValueBolder:
 
1259
        return boldWeightValue();
 
1260
    case CSSValueLighter:
 
1261
        return lightWeightValue();
 
1262
    default:
 
1263
        ASSERT_NOT_REACHED();
 
1264
        return normalWeightValue();
 
1265
    }
 
1266
}
 
1267
 
 
1268
inline FontSelectionValue BuilderConverter::convertFontStretchFromValue(const CSSValue& value)
 
1269
{
 
1270
    ASSERT(is<CSSPrimitiveValue>(value));
 
1271
    const auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
1272
 
 
1273
    if (primitiveValue.isPercentage())
 
1274
        return FontSelectionValue::clampFloat(primitiveValue.floatValue());
 
1275
 
 
1276
    ASSERT(primitiveValue.isValueID());
 
1277
    if (auto value = fontStretchValue(primitiveValue.valueID()))
 
1278
        return value.value();
 
1279
    ASSERT_NOT_REACHED();
 
1280
    return normalStretchValue();
 
1281
}
 
1282
 
 
1283
// The input value needs to parsed and valid, this function returns WTF::nullopt if the input was "normal".
 
1284
inline Optional<FontSelectionValue> BuilderConverter::convertFontStyleFromValue(const CSSValue& value)
 
1285
{
 
1286
    ASSERT(is<CSSFontStyleValue>(value));
 
1287
    const auto& fontStyleValue = downcast<CSSFontStyleValue>(value);
 
1288
 
 
1289
    auto valueID = fontStyleValue.fontStyleValue->valueID();
 
1290
    if (valueID == CSSValueNormal)
 
1291
        return WTF::nullopt;
 
1292
    if (valueID == CSSValueItalic)
 
1293
        return italicValue();
 
1294
    ASSERT(valueID == CSSValueOblique);
 
1295
    if (auto* obliqueValue = fontStyleValue.obliqueValue.get())
 
1296
        return FontSelectionValue(obliqueValue->value<float>(CSSUnitType::CSS_DEG));
 
1297
    return italicValue();
 
1298
}
 
1299
 
 
1300
inline FontSelectionValue BuilderConverter::convertFontWeight(BuilderState& builderState, const CSSValue& value)
 
1301
{
 
1302
    ASSERT(is<CSSPrimitiveValue>(value));
 
1303
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
1304
    if (primitiveValue.isValueID()) {
 
1305
        auto valueID = primitiveValue.valueID();
 
1306
        if (valueID == CSSValueBolder)
 
1307
            return FontCascadeDescription::bolderWeight(builderState.parentStyle().fontDescription().weight());
 
1308
        if (valueID == CSSValueLighter)
 
1309
            return FontCascadeDescription::lighterWeight(builderState.parentStyle().fontDescription().weight());
 
1310
    }
 
1311
    return convertFontWeightFromValue(value);
 
1312
}
 
1313
 
 
1314
inline FontSelectionValue BuilderConverter::convertFontStretch(BuilderState&, const CSSValue& value)
 
1315
{
 
1316
    return convertFontStretchFromValue(value);
 
1317
}
 
1318
 
 
1319
#if ENABLE(VARIATION_FONTS)
 
1320
inline FontVariationSettings BuilderConverter::convertFontVariationSettings(BuilderState&, const CSSValue& value)
 
1321
{
 
1322
    if (is<CSSPrimitiveValue>(value)) {
 
1323
        ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNormal);
 
1324
        return { };
 
1325
    }
 
1326
 
 
1327
    FontVariationSettings settings;
 
1328
    for (auto& item : downcast<CSSValueList>(value)) {
 
1329
        auto& feature = downcast<CSSFontVariationValue>(item.get());
 
1330
        settings.insert({ feature.tag(), feature.value() });
 
1331
    }
 
1332
    return settings;
 
1333
}
 
1334
#endif
 
1335
 
 
1336
#if PLATFORM(IOS_FAMILY)
 
1337
inline bool BuilderConverter::convertTouchCallout(BuilderState&, const CSSValue& value)
 
1338
{
 
1339
    return !equalLettersIgnoringASCIICase(downcast<CSSPrimitiveValue>(value).stringValue(), "none");
 
1340
}
 
1341
#endif
 
1342
 
 
1343
#if ENABLE(TOUCH_EVENTS)
 
1344
inline Color BuilderConverter::convertTapHighlightColor(BuilderState& builderState, const CSSValue& value)
 
1345
{
 
1346
    return builderState.colorFromPrimitiveValue(downcast<CSSPrimitiveValue>(value));
 
1347
}
 
1348
#endif
 
1349
 
 
1350
#if ENABLE(POINTER_EVENTS)
 
1351
inline OptionSet<TouchAction> BuilderConverter::convertTouchAction(BuilderState&, const CSSValue& value)
 
1352
{
 
1353
    if (is<CSSPrimitiveValue>(value))
 
1354
        return downcast<CSSPrimitiveValue>(value);
 
1355
 
 
1356
    if (is<CSSValueList>(value)) {
 
1357
        OptionSet<TouchAction> touchActions;
 
1358
        for (auto& currentValue : downcast<CSSValueList>(value)) {
 
1359
            auto& primitiveValue = downcast<CSSPrimitiveValue>(currentValue.get());
 
1360
            auto primitiveValueID = primitiveValue.valueID();
 
1361
            if (primitiveValueID != CSSValuePanX && primitiveValueID != CSSValuePanY && primitiveValueID != CSSValuePinchZoom)
 
1362
                return RenderStyle::initialTouchActions();
 
1363
            touchActions.add(primitiveValue);
 
1364
        }
 
1365
        return touchActions;
 
1366
    }
 
1367
 
 
1368
    return RenderStyle::initialTouchActions();
 
1369
}
 
1370
#endif
 
1371
 
 
1372
#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
 
1373
inline bool BuilderConverter::convertOverflowScrolling(BuilderState&, const CSSValue& value)
 
1374
{
 
1375
    return downcast<CSSPrimitiveValue>(value).valueID() == CSSValueTouch;
 
1376
}
 
1377
#endif
 
1378
 
 
1379
inline bool BuilderConverter::convertSmoothScrolling(BuilderState&, const CSSValue& value)
 
1380
{
 
1381
    return downcast<CSSPrimitiveValue>(value).valueID() == CSSValueSmooth;
 
1382
}
 
1383
 
 
1384
inline SVGLengthValue BuilderConverter::convertSVGLengthValue(BuilderState&, const CSSValue& value)
 
1385
{
 
1386
    return SVGLengthValue::fromCSSPrimitiveValue(downcast<CSSPrimitiveValue>(value));
 
1387
}
 
1388
 
 
1389
inline Vector<SVGLengthValue> BuilderConverter::convertSVGLengthVector(BuilderState& builderState, const CSSValue& value)
 
1390
{
 
1391
    auto& valueList = downcast<CSSValueList>(value);
 
1392
 
 
1393
    Vector<SVGLengthValue> svgLengths;
 
1394
    svgLengths.reserveInitialCapacity(valueList.length());
 
1395
    for (auto& item : valueList)
 
1396
        svgLengths.uncheckedAppend(convertSVGLengthValue(builderState, item));
 
1397
 
 
1398
    return svgLengths;
 
1399
}
 
1400
 
 
1401
inline Vector<SVGLengthValue> BuilderConverter::convertStrokeDashArray(BuilderState& builderState, const CSSValue& value)
 
1402
{
 
1403
    if (is<CSSPrimitiveValue>(value)) {
 
1404
        ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
 
1405
        return SVGRenderStyle::initialStrokeDashArray();
 
1406
    }
 
1407
 
 
1408
    return convertSVGLengthVector(builderState, value);
 
1409
}
 
1410
 
 
1411
inline PaintOrder BuilderConverter::convertPaintOrder(BuilderState&, const CSSValue& value)
 
1412
{
 
1413
    if (is<CSSPrimitiveValue>(value)) {
 
1414
        ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNormal);
 
1415
        return PaintOrder::Normal;
 
1416
    }
 
1417
 
 
1418
    auto& orderTypeList = downcast<CSSValueList>(value);
 
1419
    switch (downcast<CSSPrimitiveValue>(*orderTypeList.itemWithoutBoundsCheck(0)).valueID()) {
 
1420
    case CSSValueFill:
 
1421
        return orderTypeList.length() > 1 ? PaintOrder::FillMarkers : PaintOrder::Fill;
 
1422
    case CSSValueStroke:
 
1423
        return orderTypeList.length() > 1 ? PaintOrder::StrokeMarkers : PaintOrder::Stroke;
 
1424
    case CSSValueMarkers:
 
1425
        return orderTypeList.length() > 1 ? PaintOrder::MarkersStroke : PaintOrder::Markers;
 
1426
    default:
 
1427
        ASSERT_NOT_REACHED();
 
1428
        return PaintOrder::Normal;
 
1429
    }
 
1430
}
 
1431
 
 
1432
inline float BuilderConverter::convertOpacity(BuilderState&, const CSSValue& value)
 
1433
{
 
1434
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
1435
    float opacity = primitiveValue.floatValue();
 
1436
    if (primitiveValue.isPercentage())
 
1437
        opacity /= 100.0f;
 
1438
    return std::max(0.0f, std::min(1.0f, opacity));
 
1439
}
 
1440
 
 
1441
inline String BuilderConverter::convertSVGURIReference(BuilderState& builderState, const CSSValue& value)
 
1442
{
 
1443
    String s;
 
1444
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
1445
    if (primitiveValue.isURI())
 
1446
        s = primitiveValue.stringValue();
 
1447
 
 
1448
    return SVGURIReference::fragmentIdentifierFromIRIString(s, builderState.document());
 
1449
}
 
1450
 
 
1451
inline Color BuilderConverter::convertSVGColor(BuilderState& builderState, const CSSValue& value)
 
1452
{
 
1453
    return builderState.colorFromPrimitiveValue(downcast<CSSPrimitiveValue>(value));
 
1454
}
 
1455
 
 
1456
inline StyleSelfAlignmentData BuilderConverter::convertSelfOrDefaultAlignmentData(BuilderState&, const CSSValue& value)
 
1457
{
 
1458
    StyleSelfAlignmentData alignmentData = RenderStyle::initialSelfAlignment();
 
1459
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
1460
    if (Pair* pairValue = primitiveValue.pairValue()) {
 
1461
        if (pairValue->first()->valueID() == CSSValueLegacy) {
 
1462
            alignmentData.setPositionType(ItemPositionType::Legacy);
 
1463
            alignmentData.setPosition(*pairValue->second());
 
1464
        } else if (pairValue->first()->valueID() == CSSValueFirst)
 
1465
            alignmentData.setPosition(ItemPosition::Baseline);
 
1466
        else if (pairValue->first()->valueID() == CSSValueLast)
 
1467
            alignmentData.setPosition(ItemPosition::LastBaseline);
 
1468
        else {
 
1469
            alignmentData.setOverflow(*pairValue->first());
 
1470
            alignmentData.setPosition(*pairValue->second());
 
1471
        }
 
1472
    } else
 
1473
        alignmentData.setPosition(primitiveValue);
 
1474
    return alignmentData;
 
1475
}
 
1476
 
 
1477
inline StyleContentAlignmentData BuilderConverter::convertContentAlignmentData(BuilderState&, const CSSValue& value)
 
1478
{
 
1479
    StyleContentAlignmentData alignmentData = RenderStyle::initialContentAlignment();
 
1480
    if (!is<CSSContentDistributionValue>(value))
 
1481
        return alignmentData;
 
1482
    auto& contentValue = downcast<CSSContentDistributionValue>(value);
 
1483
    if (contentValue.distribution()->valueID() != CSSValueInvalid)
 
1484
        alignmentData.setDistribution(contentValue.distribution().get());
 
1485
    if (contentValue.position()->valueID() != CSSValueInvalid)
 
1486
        alignmentData.setPosition(contentValue.position().get());
 
1487
    if (contentValue.overflow()->valueID() != CSSValueInvalid)
 
1488
        alignmentData.setOverflow(contentValue.overflow().get());
 
1489
    return alignmentData;
 
1490
}
 
1491
 
 
1492
inline GlyphOrientation BuilderConverter::convertGlyphOrientation(BuilderState&, const CSSValue& value)
 
1493
{
 
1494
    float angle = fabsf(fmodf(downcast<CSSPrimitiveValue>(value).floatValue(), 360.0f));
 
1495
    if (angle <= 45.0f || angle > 315.0f)
 
1496
        return GlyphOrientation::Degrees0;
 
1497
    if (angle > 45.0f && angle <= 135.0f)
 
1498
        return GlyphOrientation::Degrees90;
 
1499
    if (angle > 135.0f && angle <= 225.0f)
 
1500
        return GlyphOrientation::Degrees180;
 
1501
    return GlyphOrientation::Degrees270;
 
1502
}
 
1503
 
 
1504
inline GlyphOrientation BuilderConverter::convertGlyphOrientationOrAuto(BuilderState& builderState, const CSSValue& value)
 
1505
{
 
1506
    if (downcast<CSSPrimitiveValue>(value).valueID() == CSSValueAuto)
 
1507
        return GlyphOrientation::Auto;
 
1508
    return convertGlyphOrientation(builderState, value);
 
1509
}
 
1510
 
 
1511
inline Optional<Length> BuilderConverter::convertLineHeight(BuilderState& builderState, const CSSValue& value, float multiplier)
 
1512
{
 
1513
    auto& primitiveValue = downcast<CSSPrimitiveValue>(value);
 
1514
    if (primitiveValue.valueID() == CSSValueNormal)
 
1515
        return RenderStyle::initialLineHeight();
 
1516
 
 
1517
    if (primitiveValue.isLength()) {
 
1518
        Length length = primitiveValue.computeLength<Length>(BuilderConverter::csstoLengthConversionDataWithTextZoomFactor(builderState));
 
1519
        if (multiplier != 1.f)
 
1520
            length = Length(length.value() * multiplier, Fixed);
 
1521
        return length;
 
1522
    }
 
1523
 
 
1524
    // Line-height percentages need to inherit as if they were Fixed pixel values. In the example:
 
1525
    // <div style="font-size: 10px; line-height: 150%;"><div style="font-size: 100px;"></div></div>
 
1526
    // the inner element should have line-height of 15px. However, in this example:
 
1527
    // <div style="font-size: 10px; line-height: 1.5;"><div style="font-size: 100px;"></div></div>
 
1528
    // the inner element should have a line-height of 150px. Therefore, we map percentages to Fixed
 
1529
    // values and raw numbers to percentages.
 
1530
    if (primitiveValue.isPercentage()) {
 
1531
        // FIXME: percentage should not be restricted to an integer here.
 
1532
        return Length((builderState.style().computedFontSize() * primitiveValue.intValue()) / 100, Fixed);
 
1533
    }
 
1534
    if (primitiveValue.isNumber())
 
1535
        return Length(primitiveValue.doubleValue() * 100.0, Percent);
 
1536
 
 
1537
    // FIXME: The parser should only emit the above types, so this should never be reached. We should change the
 
1538
    // type of this function to return just a Length (and not an Optional).
 
1539
    return WTF::nullopt;
 
1540
}
 
1541
 
 
1542
inline FontSynthesis BuilderConverter::convertFontSynthesis(BuilderState&, const CSSValue& value)
 
1543
{
 
1544
    if (is<CSSPrimitiveValue>(value)) {
 
1545
        ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNone);
 
1546
        return FontSynthesisNone;
 
1547
    }
 
1548
 
 
1549
    FontSynthesis result = FontSynthesisNone;
 
1550
    ASSERT(is<CSSValueList>(value));
 
1551
    for (const CSSValue& v : downcast<CSSValueList>(value)) {
 
1552
        switch (downcast<CSSPrimitiveValue>(v).valueID()) {
 
1553
        case CSSValueWeight:
 
1554
            result |= FontSynthesisWeight;
 
1555
            break;
 
1556
        case CSSValueStyle:
 
1557
            result |= FontSynthesisStyle;
 
1558
            break;
 
1559
        case CSSValueSmallCaps:
 
1560
            result |= FontSynthesisSmallCaps;
 
1561
            break;
 
1562
        default:
 
1563
            ASSERT_NOT_REACHED();
 
1564
            break;
 
1565
        }
 
1566
    }
 
1567
 
 
1568
    return result;
 
1569
}
 
1570
    
 
1571
inline OptionSet<SpeakAs> BuilderConverter::convertSpeakAs(BuilderState&, const CSSValue& value)
 
1572
{
 
1573
    auto result = RenderStyle::initialSpeakAs();
 
1574
    if (is<CSSValueList>(value)) {
 
1575
        for (auto& currentValue : downcast<CSSValueList>(value))
 
1576
            result.add(downcast<CSSPrimitiveValue>(currentValue.get()));
 
1577
    }
 
1578
    return result;
 
1579
}
 
1580
 
 
1581
inline OptionSet<HangingPunctuation> BuilderConverter::convertHangingPunctuation(BuilderState&, const CSSValue& value)
 
1582
{
 
1583
    auto result = RenderStyle::initialHangingPunctuation();
 
1584
    if (is<CSSValueList>(value)) {
 
1585
        for (auto& currentValue : downcast<CSSValueList>(value))
 
1586
            result.add(downcast<CSSPrimitiveValue>(currentValue.get()));
 
1587
    }
 
1588
    return result;
 
1589
}
 
1590
 
 
1591
inline GapLength BuilderConverter::convertGapLength(BuilderState& builderState, const CSSValue& value)
 
1592
{
 
1593
    return (downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNormal) ? GapLength() : GapLength(convertLength(builderState, value));
 
1594
}
 
1595
 
 
1596
}
 
1597
}