Bug 186344 - font-synthesis inline/computed style in non-canonical
Summary: font-synthesis inline/computed style in non-canonical
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: CSS (show other bugs)
Version: Safari 11
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Joonghun Park
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2018-06-06 04:08 PDT by Eric Willigers
Modified: 2021-11-06 16:18 PDT (History)
13 users (show)

See Also:


Attachments
Patch (7.17 KB, patch)
2021-11-02 17:59 PDT, Joonghun Park
no flags Details | Formatted Diff | Diff
Patch (44.41 KB, patch)
2021-11-02 22:23 PDT, Joonghun Park
no flags Details | Formatted Diff | Diff
Patch (69.44 KB, patch)
2021-11-03 06:07 PDT, Joonghun Park
no flags Details | Formatted Diff | Diff
Update layout test results for ios and common (98.48 KB, patch)
2021-11-04 00:39 PDT, Joonghun Park
no flags Details | Formatted Diff | Diff
Canonicalize CSSValueList at parsing stage in consumeFontSynthesis (98.64 KB, patch)
2021-11-05 21:51 PDT, Joonghun Park
no flags Details | Formatted Diff | Diff
Patch for landing (98.15 KB, patch)
2021-11-06 05:00 PDT, Joonghun Park
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Eric Willigers 2018-06-06 04:08:48 PDT
Test case:
https://jsfiddle.net/ericwilligers/2q9cmrha/

Spec:
https://drafts.csswg.org/css-fonts-3/#propdef-font-synthesis
none | [ weight || style ]

If the values  'weight style'  or  'style weight'  are assigned, the computed style should be 'weight style', but WebKit gives  'style weight'.
Comment 1 Myles C. Maxfield 2018-06-18 15:59:45 PDT
I thought the spec was in the process of changing the syntax fairly dramatically? I mean, we can flip the order super easily, but if we're going to be changing our implementation substantially, we may want to wait.
Comment 2 Sam Sneddon [:gsnedders] 2021-10-20 08:34:58 PDT
Looks like we're gaining interoperability on that ordering, so I guess we should:

https://wpt.fyi/results/css/css-fonts/parsing/font-synthesis-valid.html?label=master&label=experimental&product=chrome&product=firefox&product=webkitgtk&product=safari&aligned
Comment 3 Joonghun Park 2021-11-02 17:59:21 PDT
Created attachment 443153 [details]
Patch
Comment 4 Joonghun Park 2021-11-02 18:54:30 PDT
Comment on attachment 443153 [details]
Patch

Layout test results will be updated with the next patchset.
Comment 5 Myles C. Maxfield 2021-11-02 19:08:07 PDT
Comment on attachment 443153 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=443153&action=review

r=mews

> Source/WebCore/css/StyleProperties.cpp:173
> +        case CSSPropertyFontSynthesis:
> +            return fontSynthesisPropertyValue(*value);

This is a surprising place for this code. Why is this here and not below (or maybe even in another function?)
Comment 6 Simon Fraser (smfr) 2021-11-02 20:04:30 PDT
Comment on attachment 443153 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=443153&action=review

>> Source/WebCore/css/StyleProperties.cpp:173
>> +            return fontSynthesisPropertyValue(*value);
> 
> This is a surprising place for this code. Why is this here and not below (or maybe even in another function?)

Falling through from CSSPropertyStrokeOpacity and returning a fontSynthesisPropertyValue() doesn't seem right.
Comment 7 Joonghun Park 2021-11-02 21:05:05 PDT
Comment on attachment 443153 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=443153&action=review

>>> Source/WebCore/css/StyleProperties.cpp:173
>>> +            return fontSynthesisPropertyValue(*value);
>> 
>> This is a surprising place for this code. Why is this here and not below (or maybe even in another function?)
> 
> Falling through from CSSPropertyStrokeOpacity and returning a fontSynthesisPropertyValue() doesn't seem right.

I moved this callsite to above. Originally I placed this here because it was right before default switch but I didn't see the FALLTHROUGH.
And it seems that below place is for shorthand properties, so I will place this call as below.

if (auto value = getPropertyCSSValue(propertyID)) {
        switch (propertyID) {
        case CSSPropertyFontSynthesis:
            return fontSynthesisPropertyValue(*value);
        case CSSPropertyFillOpacity:
        case CSSPropertyFloodOpacity:
...
Comment 8 Joonghun Park 2021-11-02 22:23:50 PDT
Created attachment 443174 [details]
Patch
Comment 9 Joonghun Park 2021-11-02 22:59:56 PDT
I updated layout test result on Ubuntu 21.10
and will update layout test result on macOS 12.0.1 too in the next patchset.
Comment 10 Joonghun Park 2021-11-03 06:07:11 PDT
Created attachment 443195 [details]
Patch
Comment 11 Joonghun Park 2021-11-03 06:19:48 PDT
Could you please review this patch again? I think this patch is ready for review now.
Comment 12 Joonghun Park 2021-11-04 00:39:26 PDT
Created attachment 443281 [details]
Update layout test results for ios and common
Comment 13 Joonghun Park 2021-11-04 13:55:14 PDT
Hi, please review this patch when you are available. It seems that ews has passed.
Comment 14 Myles C. Maxfield 2021-11-05 17:23:47 PDT
Comment on attachment 443281 [details]
Update layout test results for ios and common

View in context: https://bugs.webkit.org/attachment.cgi?id=443281&action=review

> Source/WebCore/css/StyleProperties.cpp:505
> +String StyleProperties::fontSynthesisPropertyValue(CSSValue& value) const
> +{
> +    String valueStr = value.cssText();
> +    if (isCSSWideValueKeyword(valueStr) || is<CSSPrimitiveValue>(value))
> +        return valueStr;
> +
> +    if (is<CSSValueList>(value)) {
> +        bool hasWeight = false;
> +        bool hasStyle = false;
> +        if (downcast<CSSValueList>(value).hasValue(CSSValuePool::singleton().createIdentifierValue(CSSValueWeight).ptr()))
> +            hasWeight = true;
> +        if (downcast<CSSValueList>(value).hasValue(CSSValuePool::singleton().createIdentifierValue(CSSValueStyle).ptr()))
> +            hasStyle = true;
> +        return makeString(hasWeight ? "weight" : "", (hasWeight && hasStyle) ? " " : "", hasStyle ? "style" : "");
> +    }
> +
> +    return String();
> +}

I think, instead of writing this function, we should change consumeFontSynthesis() in CSSPropertyParser.cpp to just canonicalize the list at parsing time. Canonicalizing at parse time would be a simpler solution, and there would not have to be another special case here - StyleProperties::getPropertyValue() would be entirely unmodified.

Maybe something like this:

    bool foundWeight = false;
    bool foundStyle = false;
    bool foundSmallCaps = false;
    while (true) {
        auto ident = consumeIdent<CSSValueWeight, CSSValueStyle, CSSValueSmallCaps>(range);
        if (!ident)
            break;
        switch (ident->valueID()) {
        case CSSValueWeight:
            if (foundWeight)
                return nullptr;
            foundWeight = true;
        case CSSValueStyle:
            if (foundStyle)
                return nullptr;
            foundStyle = true;
        case CSSValueSmallCaps:
            if (foundSmallCaps)
                return nullptr;
            foundSmallCaps = true;
        }
    }

    RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
    if (foundWeight)
        list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueWeight));
    if (foundStyle)
        list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStyle));
    if (foundSmallCaps)
        list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));

    if (!list->length())
        return nullptr;
    return list;

It's probably even possible to make this more concise by using lambdas.
Comment 15 Joonghun Park 2021-11-05 20:39:37 PDT
Comment on attachment 443281 [details]
Update layout test results for ios and common

View in context: https://bugs.webkit.org/attachment.cgi?id=443281&action=review

>> Source/WebCore/css/StyleProperties.cpp:505
>> +}
> 
> I think, instead of writing this function, we should change consumeFontSynthesis() in CSSPropertyParser.cpp to just canonicalize the list at parsing time. Canonicalizing at parse time would be a simpler solution, and there would not have to be another special case here - StyleProperties::getPropertyValue() would be entirely unmodified.
> 
> Maybe something like this:
> 
>     bool foundWeight = false;
>     bool foundStyle = false;
>     bool foundSmallCaps = false;
>     while (true) {
>         auto ident = consumeIdent<CSSValueWeight, CSSValueStyle, CSSValueSmallCaps>(range);
>         if (!ident)
>             break;
>         switch (ident->valueID()) {
>         case CSSValueWeight:
>             if (foundWeight)
>                 return nullptr;
>             foundWeight = true;
>         case CSSValueStyle:
>             if (foundStyle)
>                 return nullptr;
>             foundStyle = true;
>         case CSSValueSmallCaps:
>             if (foundSmallCaps)
>                 return nullptr;
>             foundSmallCaps = true;
>         }
>     }
> 
>     RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
>     if (foundWeight)
>         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueWeight));
>     if (foundStyle)
>         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueStyle));
>     if (foundSmallCaps)
>         list->append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
> 
>     if (!list->length())
>         return nullptr;
>     return list;
> 
> It's probably even possible to make this more concise by using lambdas.

Thank you for your review, Myles:) I applied your comment in the next patchset and will upload it soon.
Comment 16 Joonghun Park 2021-11-05 21:51:33 PDT
Created attachment 443477 [details]
Canonicalize CSSValueList at parsing stage in consumeFontSynthesis
Comment 17 Myles C. Maxfield 2021-11-06 00:45:04 PDT
Comment on attachment 443477 [details]
Canonicalize CSSValueList at parsing stage in consumeFontSynthesis

View in context: https://bugs.webkit.org/attachment.cgi?id=443477&action=review

> Source/WebCore/css/parser/CSSPropertyParser.cpp:995
> +    auto makeCanonicalizedList = [](CSSParserTokenRange& range) -> RefPtr<CSSValueList> {

The fact that this code is in a lambda doesn't seem to be useful. When I mentioned "lambda" I was suggesting using it as a tool to reduce (nearly-)duplicated code.

If it's not possible to reduce (nearly-)duplicated code, I suggest we promote this code to no longer be within a lambda.
Comment 18 Joonghun Park 2021-11-06 04:57:58 PDT
Comment on attachment 443477 [details]
Canonicalize CSSValueList at parsing stage in consumeFontSynthesis

View in context: https://bugs.webkit.org/attachment.cgi?id=443477&action=review

>> Source/WebCore/css/parser/CSSPropertyParser.cpp:995
>> +    auto makeCanonicalizedList = [](CSSParserTokenRange& range) -> RefPtr<CSSValueList> {
> 
> The fact that this code is in a lambda doesn't seem to be useful. When I mentioned "lambda" I was suggesting using it as a tool to reduce (nearly-)duplicated code.
> 
> If it's not possible to reduce (nearly-)duplicated code, I suggest we promote this code to no longer be within a lambda.

I added a small tiny lambda below, except that I promoted all the codes to no longer be within a lambda in the next patchset. Thank you for your review.

auto checkAndMarkExistence = [](bool* found) {
    if (*found)
        return false;
    return *found = true;
};
Comment 19 Joonghun Park 2021-11-06 05:00:30 PDT
Created attachment 443482 [details]
Patch for landing
Comment 20 EWS 2021-11-06 16:07:32 PDT
Committed r285383 (243940@main): <https://commits.webkit.org/243940@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 443482 [details].
Comment 21 Radar WebKit Bug Importer 2021-11-06 16:08:17 PDT
<rdar://problem/85105405>
Comment 22 Myles C. Maxfield 2021-11-06 16:18:00 PDT
Committed r285384 (243941@main): <https://commits.webkit.org/243941@main>