⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 272121 in webkit


Ignore:
Timestamp:
Jan 30, 2021, 2:33:00 PM (6 years ago)
Author:
weinig@apple.com
Message:

Additional cleanup of CSSPropertyParserHelpers
​https://bugs.webkit.org/show_bug.cgi?id=221174

Reviewed by Simon Fraser.

  • Added "raw" versions of consumeInteger and consumePositiveInteger.
  • Converted consumePosition and consumeOneOrTwoValuedPosition to use an Optional return value rather than out parameters, using a new PositionCoordinates helper struct.
  • Added consumeNumberOrPercentDividedBy100Raw helper for common patter of supporting eiter a number, or a percentage normalized by dividing it by 100.
  • css/MediaQueryExpression.cpp:
  • css/parser/CSSPropertyParser.cpp:
  • css/parser/CSSPropertyParserHelpers.cpp:
  • css/parser/CSSPropertyParserHelpers.h:
Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r272118 r272121  
     12021-01-30  Sam Weinig  <weinig@apple.com>
     2
     3        Additional cleanup of CSSPropertyParserHelpers
     4        https://bugs.webkit.org/show_bug.cgi?id=221174
     5
     6        Reviewed by Simon Fraser.
     7
     8        - Added "raw" versions of consumeInteger and consumePositiveInteger.
     9        - Converted consumePosition and consumeOneOrTwoValuedPosition to use
     10          an Optional return value rather than out parameters, using a new
     11          PositionCoordinates helper struct.
     12        - Added consumeNumberOrPercentDividedBy100Raw helper for common patter
     13          of supporting eiter a number, or a percentage normalized by dividing
     14          it by 100.
     15
     16        * css/MediaQueryExpression.cpp:
     17        * css/parser/CSSPropertyParser.cpp:
     18        * css/parser/CSSPropertyParserHelpers.cpp:
     19        * css/parser/CSSPropertyParserHelpers.h:
     20
    1212021-01-30  Zalan Bujtas  <zalan@apple.com>
    222
  • trunk/Source/WebCore/css/MediaQueryExpression.cpp

    r270823 r272121  
    221221        if (!CSSPropertyParserHelpers::consumeSlashIncludingWhitespace(range))
    222222            return;
    223         RefPtr<CSSPrimitiveValue> denominatorValue = CSSPropertyParserHelpers::consumePositiveInteger(range);
     223        auto denominatorValue = CSSPropertyParserHelpers::consumePositiveIntegerRaw(range);
    224224        if (!denominatorValue)
    225225            return;
    226226
    227227        unsigned numerator = clampTo<unsigned>(firstValue->doubleValue());
    228         unsigned denominator = clampTo<unsigned>(denominatorValue->doubleValue());
    229         m_value = CSSAspectRatioValue::create(numerator, denominator);
     228        m_value = CSSAspectRatioValue::create(numerator, *denominatorValue);
    230229        m_isValid = true;
    231230        return;
  • trunk/Source/WebCore/css/parser/CSSPropertyParser.cpp

    r272094 r272121  
    371371bool CSSPropertyParser::consumeTransformOrigin(bool important)
    372372{
    373     RefPtr<CSSPrimitiveValue> resultX;
    374     RefPtr<CSSPrimitiveValue> resultY;
    375     if (consumeOneOrTwoValuedPosition(m_range, m_context.mode, UnitlessQuirk::Forbid, resultX, resultY)) {
     373    if (auto resultXY = consumeOneOrTwoValuedPositionCoordinates(m_range, m_context.mode, UnitlessQuirk::Forbid)) {
    376374        m_range.consumeWhitespace();
    377375        bool atEnd = m_range.atEnd();
    378         RefPtr<CSSPrimitiveValue> resultZ = consumeLength(m_range, m_context.mode, ValueRangeAll);
     376        auto resultZ = consumeLength(m_range, m_context.mode, ValueRangeAll);
    379377        bool hasZ = resultZ;
    380378        if (!hasZ && !atEnd)
    381379            return false;
    382         addProperty(CSSPropertyTransformOriginX, CSSPropertyTransformOrigin, resultX.releaseNonNull(), important);
    383         addProperty(CSSPropertyTransformOriginY, CSSPropertyTransformOrigin, resultY.releaseNonNull(), important);
     380        addProperty(CSSPropertyTransformOriginX, CSSPropertyTransformOrigin, WTFMove(resultXY->x), important);
     381        addProperty(CSSPropertyTransformOriginY, CSSPropertyTransformOrigin, WTFMove(resultXY->y), important);
    384382        addProperty(CSSPropertyTransformOriginZ, CSSPropertyTransformOrigin, resultZ ? resultZ.releaseNonNull() : CSSValuePool::singleton().createValue(0, CSSUnitType::CSS_PX), important, !hasZ);
    385383       
    … …  
    391389bool CSSPropertyParser::consumePerspectiveOrigin(bool important)
    392390{
    393     RefPtr<CSSPrimitiveValue> resultX;
    394     RefPtr<CSSPrimitiveValue> resultY;
    395     if (consumePosition(m_range, m_context.mode, UnitlessQuirk::Forbid, PositionSyntax::Position, resultX, resultY)) {
    396         addProperty(CSSPropertyPerspectiveOriginX, CSSPropertyPerspectiveOrigin, resultX.releaseNonNull(), important);
    397         addProperty(CSSPropertyPerspectiveOriginY, CSSPropertyPerspectiveOrigin, resultY.releaseNonNull(), important);
     391    if (auto result = consumePositionCoordinates(m_range, m_context.mode, UnitlessQuirk::Forbid, PositionSyntax::Position)) {
     392        addProperty(CSSPropertyPerspectiveOriginX, CSSPropertyPerspectiveOrigin, WTFMove(result->x), important);
     393        addProperty(CSSPropertyPerspectiveOriginY, CSSPropertyPerspectiveOrigin, WTFMove(result->y), important);
    398394        return true;
    399395    }
    … …  
    475471    if (!range.atEnd() && range.peek().type() != CommaToken) {
    476472        // Feature tag values could follow: <integer> | on | off
    477         if (auto primitiveValue = consumeInteger(range, 0))
    478             tagValue = primitiveValue->intValue();
     473        if (auto integer = consumeIntegerRaw(range, 0))
     474            tagValue = *integer;
    479475        else if (range.peek().id() == CSSValueOn || range.peek().id() == CSSValueOff)
    480476            tagValue = range.consumeIncludingWhitespace().id() == CSSValueOn;
    … …  
    11491145            return nullptr;
    11501146        int i = defaultValue;
    1151         if (RefPtr<CSSPrimitiveValue> counterValue = consumeInteger(range))
    1152             i = counterValue->intValue();
     1147        if (auto counterValue = consumeIntegerRaw(range))
     1148            i = *counterValue;
    11531149        list->append(createPrimitiveValuePair(counterName.releaseNonNull(), CSSPrimitiveValue::create(i, CSSUnitType::CSS_NUMBER), Pair::IdenticalValueEncoding::Coalesce));
    11541150    } while (!range.atEnd());
    … …  
    13331329static RefPtr<CSSPrimitiveValue> consumeLineClamp(CSSParserTokenRange& range)
    13341330{
    1335     RefPtr<CSSPrimitiveValue> clampValue = consumePercent(range, ValueRangeNonNegative);
    1336     if (clampValue)
     1331    if (auto clampValue = consumePercent(range, ValueRangeNonNegative))
    13371332        return clampValue;
    13381333    // When specifying number of lines, don't allow 0 as a valid value.
    … …  
    14551450    CSSParserTokenRange args = consumeFunction(rangeCopy);
    14561451   
    1457     RefPtr<CSSPrimitiveValue> stepsValue = consumePositiveInteger(args);
     1452    auto stepsValue = consumePositiveIntegerRaw(args);
    14581453    if (!stepsValue)
    14591454        return nullptr;
    … …  
    14941489        return nullptr;
    14951490
    1496     auto steps = stepsValue->intValue();
    1497     if (steps <= 1 && stepPosition == StepsTimingFunction::StepPosition::JumpNone)
    1498         return nullptr;
    1499    
     1491    if (*stepsValue == 1 && stepPosition == StepsTimingFunction::StepPosition::JumpNone)
     1492        return nullptr;
     1493
    15001494    range = rangeCopy;
    1501     return CSSStepsTimingFunctionValue::create(steps, stepPosition);
     1495    return CSSStepsTimingFunctionValue::create(*stepsValue, stepPosition);
    15021496}
    15031497
    … …  
    26062600        shape->setRadius(radius.releaseNonNull());
    26072601    if (consumeIdent<CSSValueAt>(args)) {
    2608         RefPtr<CSSPrimitiveValue> centerX;
    2609         RefPtr<CSSPrimitiveValue> centerY;
    2610         if (!consumePosition(args, context.mode, UnitlessQuirk::Forbid, PositionSyntax::Position, centerX, centerY))
    2611             return nullptr;
    2612         shape->setCenterX(centerX.releaseNonNull());
    2613         shape->setCenterY(centerY.releaseNonNull());
     2602        auto centerCoordinates = consumePositionCoordinates(args, context.mode, UnitlessQuirk::Forbid, PositionSyntax::Position);
     2603        if (!centerCoordinates)
     2604            return nullptr;
     2605        shape->setCenterX(WTFMove(centerCoordinates->x));
     2606        shape->setCenterY(WTFMove(centerCoordinates->y));
    26142607    }
    26152608    return shape;
    … …  
    26292622    }
    26302623    if (consumeIdent<CSSValueAt>(args)) {
    2631         RefPtr<CSSPrimitiveValue> centerX;
    2632         RefPtr<CSSPrimitiveValue> centerY;
    2633         if (!consumePosition(args, context.mode, UnitlessQuirk::Forbid, PositionSyntax::Position, centerX, centerY))
    2634             return nullptr;
    2635         shape->setCenterX(centerX.releaseNonNull());
    2636         shape->setCenterY(centerY.releaseNonNull());
     2624        auto centerCoordinates = consumePositionCoordinates(args, context.mode, UnitlessQuirk::Forbid, PositionSyntax::Position);
     2625        if (!centerCoordinates)
     2626            return nullptr;
     2627        shape->setCenterX(WTFMove(centerCoordinates->x));
     2628        shape->setCenterY(WTFMove(centerCoordinates->y));
    26372629    }
    26382630    return shape;
    … …  
    36033595        repeatedValues = CSSGridAutoRepeatValue::create(args.consumeIncludingWhitespace().id());
    36043596    else {
    3605         // FIXME: a consumeIntegerRaw would be more efficient here.
    3606         RefPtr<CSSPrimitiveValue> repetition = consumePositiveInteger(args);
     3597        auto repetition = consumePositiveIntegerRaw(args);
    36073598        if (!repetition)
    36083599            return false;
    3609         repetitions = clampTo<size_t>(repetition->doubleValue(), 0, GridPosition::max());
     3600        repetitions = clampTo<size_t>(static_cast<size_t>(*repetition), 0, GridPosition::max());
    36103601        repeatedValues = CSSValueList::createSpaceSeparated();
    36113602    }
    … …  
    43644355    case CSSPropertyFloodOpacity:
    43654356    case CSSPropertyOpacity:
    4366     {
    4367         RefPtr<CSSValue> parsedValue = consumeNumber(m_range, ValueRangeAll);
    4368         if (parsedValue)
     4357        if (auto parsedValue = consumeNumber(m_range, ValueRangeAll))
    43694358            return parsedValue;
    43704359        return consumePercent(m_range, ValueRangeAll);
    4371     }
    43724360    case CSSPropertyWebkitBoxFlex:
    43734361        return consumeNumber(m_range, ValueRangeAll);
    … …  
    50365024        unsigned index = 0;
    50375025        while (!m_range.atEnd() && index++ < 3) {
    5038             if (auto num = consumeNumberRaw(m_range)) {
    5039                 if (*num < 0)
     5026            if (auto number = consumeNumberRaw(m_range)) {
     5027                if (*number < 0)
    50405028                    return false;
    50415029                if (flexGrow == unsetValue)
    5042                     flexGrow = *num;
     5030                    flexGrow = *number;
    50435031                else if (flexShrink == unsetValue)
    5044                     flexShrink = *num;
    5045                 else if (!*num) // flex only allows a basis of 0 (sans units) if flex-grow and flex-shrink values have already been set.
     5032                    flexShrink = *number;
     5033                else if (!*number) // flex only allows a basis of 0 (sans units) if flex-grow and flex-shrink values have already been set.
    50465034                    flexBasis = CSSPrimitiveValue::create(0, CSSUnitType::CSS_PX);
    50475035                else
    … …  
    52845272{
    52855273    do {
    5286         RefPtr<CSSPrimitiveValue> positionX;
    5287         RefPtr<CSSPrimitiveValue> positionY;
    5288         if (!consumePosition(range, context.mode, unitless, PositionSyntax::BackgroundPosition, positionX, positionY))
     5274        auto position = consumePositionCoordinates(range, context.mode, unitless, PositionSyntax::BackgroundPosition);
     5275        if (!position)
    52895276            return false;
    5290         addBackgroundValue(resultX, positionX.releaseNonNull());
    5291         addBackgroundValue(resultY, positionY.releaseNonNull());
     5277        addBackgroundValue(resultX, WTFMove(position->x));
     5278        addBackgroundValue(resultY, WTFMove(position->y));
    52925279    } while (consumeCommaIncludingWhitespace(range));
    52935280    return true;
    … …  
    53625349                } else if (property == CSSPropertyBackgroundPositionX || property == CSSPropertyWebkitMaskPositionX) {
    53635350                    CSSParserTokenRange rangeCopy = m_range;
    5364                     RefPtr<CSSPrimitiveValue> primitiveValue;
    5365                     RefPtr<CSSPrimitiveValue> primitiveValueY;
    5366                     if (!consumePosition(rangeCopy, m_context.mode, UnitlessQuirk::Forbid, PositionSyntax::BackgroundPosition, primitiveValue, primitiveValueY))
     5351                    auto position = consumePositionCoordinates(rangeCopy, m_context.mode, UnitlessQuirk::Forbid, PositionSyntax::BackgroundPosition);
     5352                    if (!position)
    53675353                        continue;
    5368                     value = primitiveValue;
    5369                     valueY = primitiveValueY;
     5354                    value = WTFMove(position->x);
     5355                    valueY = WTFMove(position->y);
    53705356                    m_range = rangeCopy;
    53715357                } else if (property == CSSPropertyBackgroundSize || property == CSSPropertyWebkitMaskSize) {
  • trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp

    r272094 r272121  
    8484}
    8585
     86static Optional<double> consumeNumberOrPercentDividedBy100Raw(CSSParserTokenRange& range, ValueRange valueRange = ValueRangeAll)
     87{
     88    if (auto percent = consumePercentRaw(range, valueRange))
     89        return *percent / 100.0;
     90    if (auto number = consumeNumberRaw(range, valueRange))
     91        return *number;
     92    return WTF::nullopt;
     93}
     94
    8695// FIXME: consider pulling in the parsing logic from CSSCalculationValue.cpp.
    8796class CalcParser {
    … …  
    112121            return nullptr;
    113122        m_sourceRange = m_range;
    114         double value = std::max(m_calcValue->doubleValue(), minimumValue);
    115         value = std::round(value);
    116         return CSSValuePool::singleton().createValue(value, CSSUnitType::CSS_NUMBER);
     123        return CSSValuePool::singleton().createValue(std::round(std::max(m_calcValue->doubleValue(), minimumValue)), CSSUnitType::CSS_NUMBER);
     124    }
     125
     126    template<typename IntType> Optional<IntType> consumeIntegerTypeRaw(double minimumValue)
     127    {
     128        if (!m_calcValue)
     129            return WTF::nullopt;
     130        m_sourceRange = m_range;
     131        return clampTo<IntType>(std::round(std::max(m_calcValue->doubleValue(), minimumValue)));
    117132    }
    118133
    … …  
    185200};
    186201
    187 RefPtr<CSSPrimitiveValue> consumeInteger(CSSParserTokenRange& range, double minimumValue)
     202template<typename IntType> Optional<IntType> consumeIntegerTypeRaw(CSSParserTokenRange& range, double minimumValue)
    188203{
    189204    const CSSParserToken& token = range.peek();
    190205    if (token.type() == NumberToken) {
    191206        if (token.numericValueType() == NumberValueType || token.numericValue() < minimumValue)
    192             return nullptr;
    193         return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_NUMBER);
     207            return WTF::nullopt;
     208        return clampTo<IntType>(range.consumeIncludingWhitespace().numericValue());
    194209    }
    195210
    196211    if (token.type() != FunctionToken)
    197         return nullptr;
     212        return WTF::nullopt;
    198213
    199214    CalcParser calcParser(range, CalculationCategory::Number);
    200215    if (const CSSCalcValue* calculation = calcParser.value()) {
    201216        if (calculation->category() != CalculationCategory::Number)
    202             return nullptr;
    203         return calcParser.consumeInteger(minimumValue);
    204     }
    205 
     217            return WTF::nullopt;
     218        return calcParser.consumeIntegerTypeRaw<IntType>(minimumValue);
     219    }
     220
     221    return WTF::nullopt;
     222}
     223
     224Optional<int> consumeIntegerRaw(CSSParserTokenRange& range, double minimumValue)
     225{
     226    return consumeIntegerTypeRaw<int>(range, minimumValue);
     227}
     228
     229RefPtr<CSSPrimitiveValue> consumeInteger(CSSParserTokenRange& range, double minimumValue)
     230{
     231    if (auto integer = consumeIntegerRaw(range, minimumValue))
     232        return CSSValuePool::singleton().createValue(*integer, CSSUnitType::CSS_NUMBER);
    206233    return nullptr;
    207234}
    208235
     236Optional<unsigned> consumePositiveIntegerRaw(CSSParserTokenRange& range)
     237{
     238    return consumeIntegerTypeRaw<unsigned>(range, 1);
     239}
     240
    209241RefPtr<CSSPrimitiveValue> consumePositiveInteger(CSSParserTokenRange& range)
    210242{
    211     return consumeInteger(range, 1);
     243    if (auto integer = consumePositiveIntegerRaw(range))
     244        return CSSValuePool::singleton().createValue(*integer, CSSUnitType::CSS_NUMBER);
     245    return nullptr;
    212246}
    213247
    … …  
    724758    uint8_t alphaComponent = 255;
    725759    if (consumeAlphaSeparator()) {
    726         if (auto number = consumeNumberRaw(args))
    727             alphaComponent = convertFloatAlphaTo<uint8_t>(*number);
    728         else if (auto percent = consumePercentRaw(args))
    729             alphaComponent = convertFloatAlphaTo<uint8_t>(*percent / 100.0);
    730         else
     760        auto alpha = consumeNumberOrPercentDividedBy100Raw(args);
     761        if (!alpha)
    731762            return { };
    732     };
     763        alphaComponent = convertFloatAlphaTo<uint8_t>(*alpha);
     764    }
    733765
    734766    if (!args.atEnd())
    … …  
    775807    double alpha = 1.0;
    776808    if (commaConsumed || slashConsumed) {
    777         if (auto number = consumeNumberRaw(args))
    778             alpha = clampTo<double>(*number, 0.0, 1.0);
    779         else if (auto percent = consumePercentRaw(args))
    780             alpha = clampTo<double>(*percent / 100.0f, 0.0, 1.0);
    781         else
     809        auto alphaParameter = consumeNumberOrPercentDividedBy100Raw(args);
     810        if (!alphaParameter)
    782811            return { };
     812        alpha = clampTo<double>(*alphaParameter, 0.0, 1.0);
    783813    }
    784814
    … …  
    794824        return 1.0f;
    795825
    796     if (auto alphaParameter = consumePercentRaw(range, ValueRangeAll))
    797         return clampTo<float>(*alphaParameter / 100.0, 0.0, 1.0);
    798 
    799     if (auto alphaParameter = consumeNumberRaw(range, ValueRangeAll))
     826    if (auto alphaParameter = consumeNumberOrPercentDividedBy100Raw(range))
    800827        return clampTo<float>(*alphaParameter, 0.0, 1.0);
    801828
    … …  
    873900    double channels[3] = { 0, 0, 0 };
    874901    for (int i = 0; i < 3; ++i) {
    875         if (auto number = consumeNumberRaw(args))
    876             channels[i] = *number;
    877         else if (auto percent = consumePercentRaw(args))
    878             channels[i] = *percent / 100.0;
    879         else
     902        auto value = consumeNumberOrPercentDividedBy100Raw(args);
     903        if (!value)
    880904            break;
     905        channels[i] = *value;
    881906    }
    882907
    … …  
    10821107}
    10831108
    1084 static void positionFromOneValue(CSSPrimitiveValue& value, RefPtr<CSSPrimitiveValue>& resultX, RefPtr<CSSPrimitiveValue>& resultY)
     1109static PositionCoordinates positionFromOneValue(CSSPrimitiveValue& value)
    10851110{
    10861111    bool valueAppliesToYAxisOnly = isVerticalPositionKeywordOnly(value);
    1087     resultX = &value;
    1088     resultY = CSSPrimitiveValue::createIdentifier(CSSValueCenter);
    10891112    if (valueAppliesToYAxisOnly)
    1090         std::swap(resultX, resultY);
    1091 }
    1092 
    1093 static bool positionFromTwoValues(CSSPrimitiveValue& value1, CSSPrimitiveValue& value2,
    1094     RefPtr<CSSPrimitiveValue>& resultX, RefPtr<CSSPrimitiveValue>& resultY)
    1095 {
    1096     bool mustOrderAsXY = isHorizontalPositionKeywordOnly(value1) || isVerticalPositionKeywordOnly(value2)
    1097         || !value1.isValueID() || !value2.isValueID();
     1113        return { CSSPrimitiveValue::createIdentifier(CSSValueCenter), value };
     1114    return { value, CSSPrimitiveValue::createIdentifier(CSSValueCenter) };
     1115}
     1116
     1117static Optional<PositionCoordinates> positionFromTwoValues(CSSPrimitiveValue& value1, CSSPrimitiveValue& value2)
     1118{
     1119    bool mustOrderAsXY = isHorizontalPositionKeywordOnly(value1) || isVerticalPositionKeywordOnly(value2) || !value1.isValueID() || !value2.isValueID();
    10981120    bool mustOrderAsYX = isVerticalPositionKeywordOnly(value1) || isHorizontalPositionKeywordOnly(value2);
    10991121    if (mustOrderAsXY && mustOrderAsYX)
    1100         return false;
    1101     resultX = &value1;
    1102     resultY = &value2;
     1122        return WTF::nullopt;
    11031123    if (mustOrderAsYX)
    1104         std::swap(resultX, resultY);
    1105     return true;
     1124        return PositionCoordinates { value2, value1 };
     1125    return PositionCoordinates { value1, value2 };
    11061126}
    11071127
    … …  
    11241144//   [ center | [ top | bottom ] <length-percentage>? ]
    11251145//
    1126 static bool backgroundPositionFromThreeValues(const std::array<CSSPrimitiveValue*, 5>& values, RefPtr<CSSPrimitiveValue>& resultX, RefPtr<CSSPrimitiveValue>& resultY)
    1127 {
     1146static Optional<PositionCoordinates> backgroundPositionFromThreeValues(const std::array<CSSPrimitiveValue*, 5>& values)
     1147{
     1148    RefPtr<CSSPrimitiveValue> resultX;
     1149    RefPtr<CSSPrimitiveValue> resultY;
     1150
    11281151    CSSPrimitiveValue* center = nullptr;
    11291152    for (int i = 0; values[i]; i++) {
    11301153        CSSPrimitiveValue* currentValue = values[i];
    11311154        if (!currentValue->isValueID())
    1132             return false;
     1155            return WTF::nullopt;
    11331156
    11341157        CSSValueID id = currentValue->valueID();
    11351158        if (id == CSSValueCenter) {
    11361159            if (center)
    1137                 return false;
     1160                return WTF::nullopt;
    11381161            center = currentValue;
    11391162            continue;
    … …  
    11481171        if (id == CSSValueLeft || id == CSSValueRight) {
    11491172            if (resultX)
    1150                 return false;
     1173                return WTF::nullopt;
    11511174            resultX = result;
    11521175        } else {
    11531176            ASSERT(id == CSSValueTop || id == CSSValueBottom);
    11541177            if (resultY)
    1155                 return false;
     1178                return WTF::nullopt;
    11561179            resultY = result;
    11571180        }
    … …  
    11611184        ASSERT(resultX || resultY);
    11621185        if (resultX && resultY)
    1163             return false;
     1186            return WTF::nullopt;
    11641187        if (!resultX)
    11651188            resultX = center;
    … …  
    11691192
    11701193    ASSERT(resultX && resultY);
    1171     return true;
     1194    return PositionCoordinates { resultX.releaseNonNull(), resultY.releaseNonNull() };
    11721195}
    11731196
    … …  
    11821205//   [ [ top | bottom ] <length-percentage> ]
    11831206//
    1184 static bool positionFromFourValues(const std::array<CSSPrimitiveValue*, 5>& values, RefPtr<CSSPrimitiveValue>& resultX, RefPtr<CSSPrimitiveValue>& resultY)
    1185 {
     1207static Optional<PositionCoordinates> positionFromFourValues(const std::array<CSSPrimitiveValue*, 5>& values)
     1208{
     1209    RefPtr<CSSPrimitiveValue> resultX;
     1210    RefPtr<CSSPrimitiveValue> resultY;
     1211
    11861212    for (int i = 0; values[i]; i++) {
    11871213        CSSPrimitiveValue* currentValue = values[i];
    11881214        if (!currentValue->isValueID())
    1189             return false;
     1215            return WTF::nullopt;
    11901216
    11911217        CSSValueID id = currentValue->valueID();
    11921218        if (id == CSSValueCenter)
    1193             return false;
     1219            return WTF::nullopt;
    11941220
    11951221        RefPtr<CSSPrimitiveValue> result;
    … …  
    12011227        if (id == CSSValueLeft || id == CSSValueRight) {
    12021228            if (resultX)
    1203                 return false;
     1229                return WTF::nullopt;
    12041230            resultX = result;
    12051231        } else {
    12061232            ASSERT(id == CSSValueTop || id == CSSValueBottom);
    12071233            if (resultY)
    1208                 return false;
     1234                return WTF::nullopt;
    12091235            resultY = result;
    12101236        }
    … …  
    12121238
    12131239    ASSERT(resultX && resultY);
    1214     return true;
     1240    return PositionCoordinates { resultX.releaseNonNull(), resultY.releaseNonNull() };
    12151241}
    12161242
    12171243// FIXME: This may consume from the range upon failure. The background
    12181244// shorthand works around it, but we should just fix it here.
    1219 bool consumePosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, PositionSyntax positionSyntax, RefPtr<CSSPrimitiveValue>& resultX, RefPtr<CSSPrimitiveValue>& resultY)
    1220 {
    1221     RefPtr<CSSPrimitiveValue> value1 = consumePositionComponent(range, cssParserMode, unitless);
     1245Optional<PositionCoordinates> consumePositionCoordinates(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, PositionSyntax positionSyntax)
     1246{
     1247    auto value1 = consumePositionComponent(range, cssParserMode, unitless);
    12221248    if (!value1)
    1223         return false;
    1224 
    1225     RefPtr<CSSPrimitiveValue> value2 = consumePositionComponent(range, cssParserMode, unitless);
    1226     if (!value2) {
    1227         positionFromOneValue(*value1, resultX, resultY);
    1228         return true;
    1229     }
    1230 
    1231     RefPtr<CSSPrimitiveValue> value3 = consumePositionComponent(range, cssParserMode, unitless);
     1249        return WTF::nullopt;
     1250
     1251    auto value2 = consumePositionComponent(range, cssParserMode, unitless);
     1252    if (!value2)
     1253        return positionFromOneValue(*value1);
     1254
     1255    auto value3 = consumePositionComponent(range, cssParserMode, unitless);
    12321256    if (!value3)
    1233         return positionFromTwoValues(*value1, *value2, resultX, resultY);
    1234 
    1235     RefPtr<CSSPrimitiveValue> value4 = consumePositionComponent(range, cssParserMode, unitless);
     1257        return positionFromTwoValues(*value1, *value2);
     1258
     1259    auto value4 = consumePositionComponent(range, cssParserMode, unitless);
    12361260   
    1237     std::array<CSSPrimitiveValue*, 5> values;
    1238     values[0] = value1.get();
    1239     values[1] = value2.get();
    1240     values[2] = value3.get();
    1241     values[3] = value4.get();
    1242     values[4] = nullptr;
     1261    std::array<CSSPrimitiveValue*, 5> values {
     1262        value1.get(),
     1263        value2.get(),
     1264        value3.get(),
     1265        value4.get(),
     1266        nullptr
     1267    };
    12431268   
    12441269    if (value4)
    1245         return positionFromFourValues(values, resultX, resultY);
     1270        return positionFromFourValues(values);
    12461271   
    12471272    if (positionSyntax != PositionSyntax::BackgroundPosition)
    1248         return false;
     1273        return WTF::nullopt;
    12491274   
    1250     return backgroundPositionFromThreeValues(values, resultX, resultY);
     1275    return backgroundPositionFromThreeValues(values);
    12511276}
    12521277
    12531278RefPtr<CSSPrimitiveValue> consumePosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, PositionSyntax positionSyntax)
    12541279{
    1255     RefPtr<CSSPrimitiveValue> resultX;
    1256     RefPtr<CSSPrimitiveValue> resultY;
    1257     if (consumePosition(range, cssParserMode, unitless, positionSyntax, resultX, resultY))
    1258         return CSSPropertyParserHelpersInternal::createPrimitiveValuePair(resultX.releaseNonNull(), resultY.releaseNonNull());
     1280    if (auto coordinates = consumePositionCoordinates(range, cssParserMode, unitless, positionSyntax))
     1281        return CSSPropertyParserHelpersInternal::createPrimitiveValuePair(WTFMove(coordinates->x), WTFMove(coordinates->y));
    12591282    return nullptr;
    12601283}
    12611284
    1262 bool consumeOneOrTwoValuedPosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, RefPtr<CSSPrimitiveValue>& resultX, RefPtr<CSSPrimitiveValue>& resultY)
    1263 {
    1264     RefPtr<CSSPrimitiveValue> value1 = consumePositionComponent(range, cssParserMode, unitless);
     1285Optional<PositionCoordinates> consumeOneOrTwoValuedPositionCoordinates(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
     1286{
     1287    auto value1 = consumePositionComponent(range, cssParserMode, unitless);
    12651288    if (!value1)
    1266         return false;
    1267     RefPtr<CSSPrimitiveValue> value2 = consumePositionComponent(range, cssParserMode, unitless);
    1268     if (!value2) {
    1269         positionFromOneValue(*value1, resultX, resultY);
    1270         return true;
    1271     }
    1272     return positionFromTwoValues(*value1, *value2, resultX, resultY);
     1289        return WTF::nullopt;
     1290    auto value2 = consumePositionComponent(range, cssParserMode, unitless);
     1291    if (!value2)
     1292        return positionFromOneValue(*value1);
     1293    return positionFromTwoValues(*value1, *value2);
    12731294}
    12741295
    … …  
    13111332    } else {
    13121333        ASSERT(id == CSSValueColorStop);
    1313         if (auto percent = consumePercentRaw(args, ValueRangeAll))
    1314             position = *percent / 100.0;
    1315         else if (auto number = consumeNumberRaw(args))
    1316             position = *number;
    1317         else
     1334        auto value = consumeNumberOrPercentDividedBy100Raw(args);
     1335        if (!value)
    13181336            return false;
     1337        position = *value;
    13191338
    13201339        if (!consumeCommaIncludingWhitespace(args))
    … …  
    14371456    auto result = CSSRadialGradientValue::create(repeating, CSSPrefixedRadialGradient);
    14381457
    1439     RefPtr<CSSPrimitiveValue> centerX;
    1440     RefPtr<CSSPrimitiveValue> centerY;
    1441     consumeOneOrTwoValuedPosition(args, cssParserMode, UnitlessQuirk::Forbid, centerX, centerY);
    1442     if ((centerX || centerY) && !consumeCommaIncludingWhitespace(args))
     1458    auto centerCoordinate = consumeOneOrTwoValuedPositionCoordinates(args, cssParserMode, UnitlessQuirk::Forbid);
     1459    if (centerCoordinate && !consumeCommaIncludingWhitespace(args))
    14431460        return nullptr;
    14441461
    … …  
    14671484        return nullptr;
    14681485
    1469     result->setFirstX(centerX.copyRef());
    1470     result->setFirstY(centerY.copyRef());
    1471     result->setSecondX(WTFMove(centerX));
    1472     result->setSecondY(WTFMove(centerY));
     1486    if (centerCoordinate) {
     1487        result->setFirstX(centerCoordinate->x.copyRef());
     1488        result->setFirstY(centerCoordinate->y.copyRef());
     1489        result->setSecondX(WTFMove(centerCoordinate->x));
     1490        result->setSecondY(WTFMove(centerCoordinate->y));
     1491    }
    14731492    result->setShape(WTFMove(shape));
    14741493    result->setSizingBehavior(WTFMove(sizeKeyword));
    … …  
    15391558    if (args.peek().id() == CSSValueAt) {
    15401559        args.consumeIncludingWhitespace();
    1541         consumePosition(args, cssParserMode, UnitlessQuirk::Forbid, PositionSyntax::Position, centerX, centerY);
    1542         if (!(centerX && centerY))
     1560       
     1561        auto centerCoordinate = consumePositionCoordinates(args, cssParserMode, UnitlessQuirk::Forbid, PositionSyntax::Position);
     1562        if (!centerCoordinate)
    15431563            return nullptr;
     1564       
     1565        centerX = WTFMove(centerCoordinate->x);
     1566        centerY = WTFMove(centerCoordinate->y);
    15441567       
    15451568        result->setFirstX(centerX.copyRef());
    … …  
    16141637
    16151638        if (consumeIdent<CSSValueAt>(args)) {
    1616             RefPtr<CSSPrimitiveValue> centerX;
    1617             RefPtr<CSSPrimitiveValue> centerY;
    1618             consumePosition(args, context.mode, UnitlessQuirk::Forbid, PositionSyntax::Position, centerX, centerY);
    1619             if (!(centerX && centerY))
     1639            auto centerCoordinate = consumePositionCoordinates(args, context.mode, UnitlessQuirk::Forbid, PositionSyntax::Position);
     1640            if (!centerCoordinate)
    16201641                return nullptr;
    16211642
    1622             result->setFirstX(centerX.copyRef());
    1623             result->setFirstY(centerY.copyRef());
     1643            result->setFirstX(centerCoordinate->x.copyRef());
     1644            result->setFirstY(centerCoordinate->y.copyRef());
    16241645
    16251646            // Right now, conic gradients have the same start and end centers.
    1626             result->setSecondX(WTFMove(centerX));
    1627             result->setSecondY(WTFMove(centerY));
     1647            result->setSecondX(WTFMove(centerCoordinate->x));
     1648            result->setSecondY(WTFMove(centerCoordinate->y));
    16281649
    16291650            expectComma = true;
    … …  
    16531674static RefPtr<CSSValue> consumeCrossFade(CSSParserTokenRange& args, CSSParserContext context, bool prefixed)
    16541675{
    1655     RefPtr<CSSValue> fromImageValue = consumeImageOrNone(args, context);
     1676    auto fromImageValue = consumeImageOrNone(args, context);
    16561677    if (!fromImageValue || !consumeCommaIncludingWhitespace(args))
    16571678        return nullptr;
    1658     RefPtr<CSSValue> toImageValue = consumeImageOrNone(args, context);
     1679    auto toImageValue = consumeImageOrNone(args, context);
    16591680    if (!toImageValue || !consumeCommaIncludingWhitespace(args))
    16601681        return nullptr;
    16611682
    1662     RefPtr<CSSPrimitiveValue> percentage;
    1663     if (auto percentValue = consumePercent(args, ValueRangeAll))
    1664         percentage = CSSValuePool::singleton().createValue(clampTo<double>(percentValue->doubleValue() / 100.0, 0, 1), CSSUnitType::CSS_NUMBER);
    1665     else if (auto numberValue = consumeNumber(args, ValueRangeAll))
    1666         percentage = CSSValuePool::singleton().createValue(clampTo<double>(numberValue->doubleValue(), 0, 1), CSSUnitType::CSS_NUMBER);
    1667 
     1683    auto percentage = consumeNumberOrPercentDividedBy100Raw(args);
    16681684    if (!percentage)
    16691685        return nullptr;
    1670     return CSSCrossfadeValue::create(fromImageValue.releaseNonNull(), toImageValue.releaseNonNull(), percentage.releaseNonNull(), prefixed);
     1686    auto percentageValue = CSSValuePool::singleton().createValue(clampTo<double>(*percentage, 0, 1), CSSUnitType::CSS_NUMBER);
     1687    return CSSCrossfadeValue::create(fromImageValue.releaseNonNull(), toImageValue.releaseNonNull(), WTFMove(percentageValue), prefixed);
    16711688}
    16721689
  • trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.h

    r272094 r272121  
    7171using LengthOrPercentRaw = Variant<LengthRaw, double>;
    7272
     73Optional<int> consumeIntegerRaw(CSSParserTokenRange&, double minimumValue = -std::numeric_limits<double>::max());
    7374RefPtr<CSSPrimitiveValue> consumeInteger(CSSParserTokenRange&, double minimumValue = -std::numeric_limits<double>::max());
     75Optional<unsigned> consumePositiveIntegerRaw(CSSParserTokenRange&);
    7476RefPtr<CSSPrimitiveValue> consumePositiveInteger(CSSParserTokenRange&);
    7577Optional<double> consumeNumberRaw(CSSParserTokenRange&, ValueRange = ValueRangeAll);
    … …  
    109111};
    110112
     113struct PositionCoordinates {
     114    Ref<CSSPrimitiveValue> x;
     115    Ref<CSSPrimitiveValue> y;
     116};
     117
    111118RefPtr<CSSPrimitiveValue> consumePosition(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk, PositionSyntax);
    112 bool consumePosition(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk, PositionSyntax, RefPtr<CSSPrimitiveValue>& resultX, RefPtr<CSSPrimitiveValue>& resultY);
    113 bool consumeOneOrTwoValuedPosition(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk, RefPtr<CSSPrimitiveValue>& resultX, RefPtr<CSSPrimitiveValue>& resultY);
     119Optional<PositionCoordinates> consumePositionCoordinates(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk, PositionSyntax);
     120Optional<PositionCoordinates> consumeOneOrTwoValuedPositionCoordinates(CSSParserTokenRange&, CSSParserMode, UnitlessQuirk);
    114121
    115122enum class AllowedImageType : uint8_t {
Note: See TracChangeset for help on using the changeset viewer.