Skip to content

[css-fonts-4] @font-face src tech() multiple value syntax #9054

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vitorroriz opened this issue Jul 11, 2023 · 5 comments
Closed

[css-fonts-4] @font-face src tech() multiple value syntax #9054

vitorroriz opened this issue Jul 11, 2023 · 5 comments

Comments

@vitorroriz
Copy link

vitorroriz commented Jul 11, 2023

tech() accepts multiple values, being @font-face src descriptor syntax:

<url> [ format(<font-format>)]? [ tech( <font-tech>#)]? | local(<font-face-name>)

Spec says:

If a component value is parsed correctly and is of a font format or font tech that the UA supports, add it to the list of supported sources. If parsing a component value results in a parsing error or its format or tech are unsupported, do not add it to the list of supported sources.

However, I'm confused if an engine should validate tech(A, B) only if it supports both A and B technologies, or if it supports A or B techonologies.

I think it makes more sense to be A and B although I've interpreted as A or B at first and implemented it that way for WebKit. This resulted in a bug filed at https://bugs.webkit.org/show_bug.cgi?id=258948.

I've added a test case locally on font-face-src-tech enforcing the and behavior. It seems that Blink behavior is already and but Gecko behavior is or, but it can be that it is failing for another reason for Gecko.

WPT export attempt : web-platform-tests/wpt#40950

I'd like to clarify what's the expected behavior here.

Use case:

@font face {
...
src: url("font1.otf") tech(A, B), url("font2.otf") tech(A);
}
@vitorroriz
Copy link
Author

vitorroriz commented Jul 11, 2023

@jfkthame could you confirm Gecko behavior, please? Thanks!

@jfkthame
Copy link
Contributor

However, I'm confused if an engine should validate tech(A, B) only if it supports both A and B technologies, or if it supports A or B techonologies.

I think it makes more sense to be A and B although I've interpreted as A or B at first and implemented it that way for WebKit. This resulted in a bug filed at https://bugs.webkit.org/show_bug.cgi?id=258948.

The spec text re Selecting items in the src says that:

Conformant user agents must skip downloading a font resource if [...] any of the font technologies are unsupported by the user agent

(my emphasis), so it's definitely supposed to be "A and B".

What's a bit confusing, though, is that in Parsing the src descriptor, the spec says:

If parsing a component value results in a parsing error or its format or tech are unsupported, do not add it to the list of supported sources.

If there are no supported entries at the end of this process, the value for the src descriptor is a parse error.

which means that if any of the requested technologies is unsupported, the source is not added to the list at all; and therefore the need to "skip downloading a font resource" shouldn't arise as it won't be in the list. (Parsing the descriptor happens before there's any question of selecting items in the source list.)

And if the list ends up empty because the only source (or all sources) were dropped as unsupported, the spec says this is a parse error. This seems a bit strange to me; it's not (in my mind) a parse error, it's a perfectly valid rule that doesn't happen to provide any usable resources. I'm sure this must have been discussed at some point, but don't recall the details offhand.

Anyhow, I'll take a look at what Gecko is doing....

@vitorroriz
Copy link
Author

vitorroriz commented Jul 11, 2023

ah, so you are rejecting the font, based on tech/format, on loading and not on parsing, that explains why tech(incremental, features-opentype) is valid for Gecko but does not load the font in local tests. Blink seems to be rejecting it directly at parsing (same for WebKit).

I've created an issue about that a while ago #8793. cdoublev was wondering the same I guess.

@jfkthame
Copy link
Contributor

Yeah -- from testing in the web console, it looks like Gecko is doing what I'd intuitively expect: the src descriptor is valid provided the argument(s) to the tech() function are (all) valid keywords. Throwing an unknown keyword in there will cause the source to be dropped (and if all source entries are dropped, we have a parse error). But a valid source with unsupported tech doesn't result in a parse error, it's just an unusable source and will be skipped during loading.

Some experiments:

> style = document.createElement("style") 
< <style>

> document.body.appendChild(style) 
< <style>

> style.textContent = "@font-face { font-family: foo; src: url(foo.ttf) tech(features-opentype, color-SVG); }" 
< "@font-face { font-family: foo; src: url(foo.ttf) tech(features-opentype, color-SVG); }" 

// Valid src descriptor, even though `incremental` is not a supported technology:
> style.textContent = "@font-face { font-family: foo; src: url(foo.ttf) tech(features-opentype, incremental); }" 
< "@font-face { font-family: foo; src: url(foo.ttf) tech(features-opentype, incremental); }" 

> style.textContent = "@font-face { font-family: foo; src: url(foo.ttf) tech(incremental); }" 
< "@font-face { font-family: foo; src: url(foo.ttf) tech(incremental); }" 

// Unknown keyword causes the src list entry to be dropped, leaving the list empty, which is invalid:
> style.textContent = "@font-face { font-family: foo; src: url(foo.ttf) tech(features-unknown); }" 
! Unknown descriptor 'src: url(foo.ttf) tech(features-unknown);' in @font-face rule. Skipped to next declaration. blank:1:72
< "@font-face { font-family: foo; src: url(foo.ttf) tech(features-unknown); }" 

// This is true even if there are valid keywords alongside the invalid one:
> style.textContent = "@font-face { font-family: foo; src: url(foo.ttf) tech(features-opentype, color-SVG, unknown); }" 
! Unknown descriptor 'src: url(foo.ttf) tech(features-opentype, color-SVG, unknown);' in @font-face rule. Skipped to next declaration. blank:1:93
< "@font-face { font-family: foo; src: url(foo.ttf) tech(features-opentype, color-SVG, unknown); }" 

// But only the bad source is dropped, so if there's another entry in the list, the descriptor is still valid:
> style.textContent = "@font-face { font-family: foo; src: url(foo.ttf) tech(features-opentype, color-SVG, unknown), url(bar.ttf); }" 
< "@font-face { font-family: foo; src: url(foo.ttf) tech(features-opentype, color-SVG, unknown), url(bar.ttf); }" 

@vitorroriz
Copy link
Author

Thank you for the help! I'm closing this one as it was clarified it should be as jfkthame mentioned:

the src descriptor is valid provided the argument(s) to the tech() function are (all) valid keywords

The discussion about invalidation on parsing vs loading is scheduled for Agenda+ at: #8793

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants