mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 09:39:39 +00:00
LibWeb/CSS: Parse and use tech() in @font-face { src }
This commit is contained in:
parent
5b42f8d707
commit
d611806f18
Notes:
github-actions[bot]
2025-06-05 11:39:21 +00:00
Author: https://github.com/AtkinsSJ
Commit: d611806f18
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4983
Reviewed-by: https://github.com/shannonbooth
10 changed files with 131 additions and 35 deletions
|
@ -258,6 +258,20 @@
|
||||||
"right",
|
"right",
|
||||||
"oblique"
|
"oblique"
|
||||||
],
|
],
|
||||||
|
"font-tech": [
|
||||||
|
"avar2",
|
||||||
|
"color-cbdt",
|
||||||
|
"color-colrv0",
|
||||||
|
"color-colrv1",
|
||||||
|
"color-sbix",
|
||||||
|
"color-svg",
|
||||||
|
"features-aat",
|
||||||
|
"features-graphite",
|
||||||
|
"features-opentype",
|
||||||
|
"incremental",
|
||||||
|
"palettes",
|
||||||
|
"variations"
|
||||||
|
],
|
||||||
"font-variant-alternates": [
|
"font-variant-alternates": [
|
||||||
"normal",
|
"normal",
|
||||||
"historical-forms"
|
"historical-forms"
|
||||||
|
|
|
@ -534,35 +534,47 @@ bool font_format_is_supported(FlyString const& name)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool font_tech_is_supported(FlyString const& name)
|
bool font_tech_is_supported(FontTech font_tech)
|
||||||
{
|
{
|
||||||
// https://drafts.csswg.org/css-fonts-4/#font-tech-definitions
|
// https://drafts.csswg.org/css-fonts-4/#font-tech-definitions
|
||||||
// FIXME: Determine this automatically somehow?
|
// FIXME: Determine this automatically somehow?
|
||||||
if (name.equals_ignoring_ascii_case("features-opentype"sv))
|
switch (font_tech) {
|
||||||
|
case FontTech::FeaturesOpentype:
|
||||||
return true;
|
return true;
|
||||||
if (name.equals_ignoring_ascii_case("features-aat"sv))
|
case FontTech::FeaturesAat:
|
||||||
return false;
|
return false;
|
||||||
if (name.equals_ignoring_ascii_case("features-graphite"sv))
|
case FontTech::FeaturesGraphite:
|
||||||
return false;
|
return false;
|
||||||
if (name.equals_ignoring_ascii_case("variations"sv))
|
case FontTech::Variations:
|
||||||
return true;
|
return true;
|
||||||
if (name.equals_ignoring_ascii_case("color-colrv0"sv))
|
case FontTech::ColorColrv0:
|
||||||
return true;
|
return true;
|
||||||
if (name.equals_ignoring_ascii_case("color-colrv1"sv))
|
case FontTech::ColorColrv1:
|
||||||
return true;
|
return true;
|
||||||
if (name.equals_ignoring_ascii_case("color-svg"sv))
|
case FontTech::ColorSvg:
|
||||||
return false;
|
return false;
|
||||||
if (name.equals_ignoring_ascii_case("color-sbix"sv))
|
case FontTech::ColorSbix:
|
||||||
return false;
|
return false;
|
||||||
if (name.equals_ignoring_ascii_case("color-cbdt"sv))
|
case FontTech::ColorCbdt:
|
||||||
return false;
|
return false;
|
||||||
if (name.equals_ignoring_ascii_case("palettes"sv))
|
case FontTech::Palettes:
|
||||||
return false;
|
return false;
|
||||||
if (name.equals_ignoring_ascii_case("incremental"sv))
|
case FontTech::Incremental:
|
||||||
return false;
|
return false;
|
||||||
// https://drafts.csswg.org/css-fonts-5/#font-tech-definitions
|
// https://drafts.csswg.org/css-fonts-5/#font-tech-definitions
|
||||||
if (name.equals_ignoring_ascii_case("avar2"sv))
|
case FontTech::Avar2:
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool font_tech_is_supported(FlyString const& name)
|
||||||
|
{
|
||||||
|
if (auto keyword = keyword_from_string(name); keyword.has_value()) {
|
||||||
|
if (auto font_tech = keyword_to_font_tech(*keyword); font_tech.has_value()) {
|
||||||
|
return font_tech_is_supported(*font_tech);
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,8 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
bool font_format_is_supported(FlyString const& name);
|
bool font_format_is_supported(FlyString const& name);
|
||||||
|
|
||||||
|
bool font_tech_is_supported(FontTech);
|
||||||
bool font_tech_is_supported(FlyString const& name);
|
bool font_tech_is_supported(FlyString const& name);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@
|
||||||
"appworkspace",
|
"appworkspace",
|
||||||
"auto",
|
"auto",
|
||||||
"auto-add",
|
"auto-add",
|
||||||
|
"avar2",
|
||||||
"b4",
|
"b4",
|
||||||
"b5",
|
"b5",
|
||||||
"back",
|
"back",
|
||||||
|
@ -128,7 +129,12 @@
|
||||||
"collapse",
|
"collapse",
|
||||||
"color",
|
"color",
|
||||||
"color-burn",
|
"color-burn",
|
||||||
|
"color-cbdt",
|
||||||
|
"color-colrv0",
|
||||||
|
"color-colrv1",
|
||||||
"color-dodge",
|
"color-dodge",
|
||||||
|
"color-sbix",
|
||||||
|
"color-svg",
|
||||||
"column",
|
"column",
|
||||||
"column-reverse",
|
"column-reverse",
|
||||||
"common-ligatures",
|
"common-ligatures",
|
||||||
|
@ -191,6 +197,9 @@
|
||||||
"false",
|
"false",
|
||||||
"fantasy",
|
"fantasy",
|
||||||
"fast",
|
"fast",
|
||||||
|
"features-aat",
|
||||||
|
"features-graphite",
|
||||||
|
"features-opentype",
|
||||||
"field",
|
"field",
|
||||||
"fieldtext",
|
"fieldtext",
|
||||||
"fill",
|
"fill",
|
||||||
|
@ -231,6 +240,7 @@
|
||||||
"inactivecaption",
|
"inactivecaption",
|
||||||
"inactivecaptiontext",
|
"inactivecaptiontext",
|
||||||
"increasing",
|
"increasing",
|
||||||
|
"incremental",
|
||||||
"infinite",
|
"infinite",
|
||||||
"infinity",
|
"infinity",
|
||||||
"infobackground",
|
"infobackground",
|
||||||
|
@ -363,6 +373,7 @@
|
||||||
"padding-box",
|
"padding-box",
|
||||||
"paged",
|
"paged",
|
||||||
"paint",
|
"paint",
|
||||||
|
"palettes",
|
||||||
"pan-down",
|
"pan-down",
|
||||||
"pan-left",
|
"pan-left",
|
||||||
"pan-right",
|
"pan-right",
|
||||||
|
@ -523,6 +534,7 @@
|
||||||
"uppercase",
|
"uppercase",
|
||||||
"upright",
|
"upright",
|
||||||
"use-credentials",
|
"use-credentials",
|
||||||
|
"variations",
|
||||||
"vertical-lr",
|
"vertical-lr",
|
||||||
"vertical-rl",
|
"vertical-rl",
|
||||||
"vertical-text",
|
"vertical-text",
|
||||||
|
|
|
@ -37,11 +37,10 @@ Vector<ParsedFontFace::Source> ParsedFontFace::sources_from_style_value(CSSStyle
|
||||||
auto add_source = [&sources](FontSourceStyleValue const& font_source) {
|
auto add_source = [&sources](FontSourceStyleValue const& font_source) {
|
||||||
font_source.source().visit(
|
font_source.source().visit(
|
||||||
[&](FontSourceStyleValue::Local const& local) {
|
[&](FontSourceStyleValue::Local const& local) {
|
||||||
sources.empend(extract_font_name(local.name), OptionalNone {});
|
sources.empend(extract_font_name(local.name), OptionalNone {}, Vector<FontTech> {});
|
||||||
},
|
},
|
||||||
[&](URL const& url) {
|
[&](URL const& url) {
|
||||||
// FIXME: tech()
|
sources.empend(url, font_source.format(), font_source.tech());
|
||||||
sources.empend(url, font_source.format());
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ class ParsedFontFace {
|
||||||
public:
|
public:
|
||||||
struct Source {
|
struct Source {
|
||||||
Variant<FlyString, URL> local_or_url;
|
Variant<FlyString, URL> local_or_url;
|
||||||
// FIXME: Do we need to keep this around, or is it only needed to discard unwanted formats during parsing?
|
|
||||||
Optional<FlyString> format;
|
Optional<FlyString> format;
|
||||||
|
Vector<FontTech> tech;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Vector<Source> sources_from_style_value(CSSStyleValue const&);
|
static Vector<Source> sources_from_style_value(CSSStyleValue const&);
|
||||||
|
|
|
@ -3888,17 +3888,20 @@ RefPtr<FontSourceStyleValue const> Parser::parse_font_source_value(TokenStream<C
|
||||||
TokenStream function_tokens { function.value };
|
TokenStream function_tokens { function.value };
|
||||||
if (auto family_name = parse_family_name_value(function_tokens)) {
|
if (auto family_name = parse_family_name_value(function_tokens)) {
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
return FontSourceStyleValue::create(FontSourceStyleValue::Local { family_name.release_nonnull() }, {});
|
return FontSourceStyleValue::create(FontSourceStyleValue::Local { family_name.release_nonnull() }, {}, {});
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <url> [ format(<font-format>)]? [ tech( <font-tech>#)]?
|
// <url> [ format(<font-format>)]? [ tech( <font-tech>#)]?
|
||||||
|
|
||||||
|
// <url>
|
||||||
auto url = parse_url_function(tokens);
|
auto url = parse_url_function(tokens);
|
||||||
if (!url.has_value())
|
if (!url.has_value())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Optional<FlyString> format;
|
Optional<FlyString> format;
|
||||||
|
Vector<FontTech> tech;
|
||||||
|
|
||||||
tokens.discard_whitespace();
|
tokens.discard_whitespace();
|
||||||
|
|
||||||
|
@ -3920,10 +3923,10 @@ RefPtr<FontSourceStyleValue const> Parser::parse_font_source_value(TokenStream<C
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Some of the formats support an optional "-variations" suffix that's really supposed to map to tech(variations).
|
// NOTE: Some of the formats support an optional "-variations" suffix that's really supposed to map to tech(variations).
|
||||||
// Once we support tech(*), we should ensure this propagates correctly.
|
|
||||||
if (format_name.is_one_of("woff2-variations"sv, "woff-variations"sv, "truetype-variations"sv, "opentype-variations"sv)) {
|
if (format_name.is_one_of("woff2-variations"sv, "woff-variations"sv, "truetype-variations"sv, "opentype-variations"sv)) {
|
||||||
format_name = MUST(format_name.to_string().substring_from_byte_offset(0, format_name.bytes().size() - strlen("-variations")));
|
format_name = MUST(format_name.to_string().substring_from_byte_offset(0, format_name.bytes().size() - strlen("-variations")));
|
||||||
|
tech.append(FontTech::Variations);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!font_format_is_supported(format_name)) {
|
if (!font_format_is_supported(format_name)) {
|
||||||
|
@ -3942,10 +3945,53 @@ RefPtr<FontSourceStyleValue const> Parser::parse_font_source_value(TokenStream<C
|
||||||
|
|
||||||
tokens.discard_whitespace();
|
tokens.discard_whitespace();
|
||||||
|
|
||||||
// FIXME: [ tech( <font-tech>#)]?
|
// [ tech( <font-tech>#)]?
|
||||||
|
if (tokens.next_token().is_function("tech"sv)) {
|
||||||
|
auto const& function = tokens.consume_a_token().function();
|
||||||
|
auto context_guard = push_temporary_value_parsing_context(FunctionContext { function.name });
|
||||||
|
|
||||||
|
TokenStream function_tokens { function.value };
|
||||||
|
auto tech_items = parse_a_comma_separated_list_of_component_values(function_tokens);
|
||||||
|
if (tech_items.is_empty()) {
|
||||||
|
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: font source invalid (`tech()` has no arguments); discarding.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const& tech_item : tech_items) {
|
||||||
|
TokenStream tech_tokens { tech_item };
|
||||||
|
tech_tokens.discard_whitespace();
|
||||||
|
auto& ident_token = tech_tokens.consume_a_token();
|
||||||
|
if (!ident_token.is(Token::Type::Ident)) {
|
||||||
|
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: font source invalid (`tech()` parameters must be idents, got: {}); discarding.", ident_token.to_debug_string());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
tech_tokens.discard_whitespace();
|
||||||
|
if (tech_tokens.has_next_token()) {
|
||||||
|
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: font source invalid (`tech()` has trailing tokens); discarding.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& font_tech_name = ident_token.token().ident();
|
||||||
|
if (auto keyword = keyword_from_string(font_tech_name); keyword.has_value()) {
|
||||||
|
if (auto font_tech = keyword_to_font_tech(*keyword); font_tech.has_value()) {
|
||||||
|
|
||||||
|
if (!font_tech_is_supported(*font_tech)) {
|
||||||
|
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: font source tech({}) not supported; skipping.", font_tech_name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
tech.append(font_tech.release_value());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: font source invalid (`{}` is not a supported value in `tech()`); discarding.", font_tech_name);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
return FontSourceStyleValue::create(url.release_value(), move(format));
|
return FontSourceStyleValue::create(url.release_value(), move(format), move(tech));
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue const> Parser::resolve_unresolved_style_value(ParsingParams const& context, DOM::Element& element, Optional<PseudoElement> pseudo_element, PropertyID property_id, UnresolvedStyleValue const& unresolved)
|
NonnullRefPtr<CSSStyleValue const> Parser::resolve_unresolved_style_value(ParsingParams const& context, DOM::Element& element, Optional<PseudoElement> pseudo_element, PropertyID property_id, UnresolvedStyleValue const& unresolved)
|
||||||
|
|
|
@ -9,10 +9,11 @@
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
|
||||||
FontSourceStyleValue::FontSourceStyleValue(Source source, Optional<FlyString> format)
|
FontSourceStyleValue::FontSourceStyleValue(Source source, Optional<FlyString> format, Vector<FontTech> tech)
|
||||||
: StyleValueWithDefaultOperators(Type::FontSource)
|
: StyleValueWithDefaultOperators(Type::FontSource)
|
||||||
, m_source(move(source))
|
, m_source(move(source))
|
||||||
, m_format(move(format))
|
, m_format(move(format))
|
||||||
|
, m_tech(move(tech))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +37,6 @@ String FontSourceStyleValue::to_string(SerializationMode) const
|
||||||
},
|
},
|
||||||
[this](URL const& url) {
|
[this](URL const& url) {
|
||||||
// <url> [ format(<font-format>)]? [ tech( <font-tech>#)]?
|
// <url> [ format(<font-format>)]? [ tech( <font-tech>#)]?
|
||||||
// FIXME: tech()
|
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
builder.append(url.to_string());
|
builder.append(url.to_string());
|
||||||
|
|
||||||
|
@ -46,6 +46,14 @@ String FontSourceStyleValue::to_string(SerializationMode) const
|
||||||
builder.append(")"sv);
|
builder.append(")"sv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_tech.is_empty()) {
|
||||||
|
builder.append(" tech("sv);
|
||||||
|
serialize_a_comma_separated_list(builder, m_tech, [](auto& builder, FontTech const tech) {
|
||||||
|
return builder.append(CSS::to_string(tech));
|
||||||
|
});
|
||||||
|
builder.append(")"sv);
|
||||||
|
}
|
||||||
|
|
||||||
return builder.to_string_without_validation();
|
return builder.to_string_without_validation();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <AK/FlyString.h>
|
#include <AK/FlyString.h>
|
||||||
#include <LibWeb/CSS/CSSStyleValue.h>
|
#include <LibWeb/CSS/CSSStyleValue.h>
|
||||||
|
#include <LibWeb/CSS/Enums.h>
|
||||||
#include <LibWeb/CSS/URL.h>
|
#include <LibWeb/CSS/URL.h>
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
@ -19,24 +20,26 @@ public:
|
||||||
};
|
};
|
||||||
using Source = Variant<Local, URL>;
|
using Source = Variant<Local, URL>;
|
||||||
|
|
||||||
static ValueComparingNonnullRefPtr<FontSourceStyleValue const> create(Source source, Optional<FlyString> format)
|
static ValueComparingNonnullRefPtr<FontSourceStyleValue const> create(Source source, Optional<FlyString> format, Vector<FontTech> tech)
|
||||||
{
|
{
|
||||||
return adopt_ref(*new (nothrow) FontSourceStyleValue(move(source), move(format)));
|
return adopt_ref(*new (nothrow) FontSourceStyleValue(move(source), move(format), move(tech)));
|
||||||
}
|
}
|
||||||
virtual ~FontSourceStyleValue() override;
|
virtual ~FontSourceStyleValue() override;
|
||||||
|
|
||||||
Source const& source() const { return m_source; }
|
Source const& source() const { return m_source; }
|
||||||
Optional<FlyString> const& format() const { return m_format; }
|
Optional<FlyString> const& format() const { return m_format; }
|
||||||
|
Vector<FontTech> const& tech() const { return m_tech; }
|
||||||
|
|
||||||
virtual String to_string(SerializationMode) const override;
|
virtual String to_string(SerializationMode) const override;
|
||||||
|
|
||||||
bool properties_equal(FontSourceStyleValue const&) const;
|
bool properties_equal(FontSourceStyleValue const&) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FontSourceStyleValue(Source source, Optional<FlyString> format);
|
FontSourceStyleValue(Source source, Optional<FlyString> format, Vector<FontTech> tech);
|
||||||
|
|
||||||
Source m_source;
|
Source m_source;
|
||||||
Optional<FlyString> m_format;
|
Optional<FlyString> m_format;
|
||||||
|
Vector<FontTech> m_tech;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,17 @@ Harness status: OK
|
||||||
|
|
||||||
Found 39 tests
|
Found 39 tests
|
||||||
|
|
||||||
28 Pass
|
34 Pass
|
||||||
11 Fail
|
5 Fail
|
||||||
Pass Check that src: url("foo.ttf") is valid
|
Pass Check that src: url("foo.ttf") is valid
|
||||||
Pass Check that src: url("foo.ttf") tech() is invalid
|
Pass Check that src: url("foo.ttf") tech() is invalid
|
||||||
Fail Check that src: url("foo.ttf") tech(features-opentype) is valid
|
Pass Check that src: url("foo.ttf") tech(features-opentype) is valid
|
||||||
Fail Check that src: url("foo.ttf") tech(features-aat) is valid
|
Fail Check that src: url("foo.ttf") tech(features-aat) is valid
|
||||||
Fail Check that src: url("foo.ttf") tech(color-COLRv0) is valid
|
Pass Check that src: url("foo.ttf") tech(color-COLRv0) is valid
|
||||||
Fail Check that src: url("foo.ttf") tech(color-COLRv1) is valid
|
Pass Check that src: url("foo.ttf") tech(color-COLRv1) is valid
|
||||||
Fail Check that src: url("foo.ttf") tech(color-sbix) is valid
|
Fail Check that src: url("foo.ttf") tech(color-sbix) is valid
|
||||||
Fail Check that src: url("foo.ttf") tech(color-CBDT) is valid
|
Fail Check that src: url("foo.ttf") tech(color-CBDT) is valid
|
||||||
Fail Check that src: url("foo.ttf") tech(variations) is valid
|
Pass Check that src: url("foo.ttf") tech(variations) is valid
|
||||||
Fail Check that src: url("foo.ttf") tech(palettes) is valid
|
Fail Check that src: url("foo.ttf") tech(palettes) is valid
|
||||||
Pass Check that src: url("foo.ttf") tech("features-opentype") is invalid
|
Pass Check that src: url("foo.ttf") tech("features-opentype") is invalid
|
||||||
Pass Check that src: url("foo.ttf") tech("color-COLRv0") is invalid
|
Pass Check that src: url("foo.ttf") tech("color-COLRv0") is invalid
|
||||||
|
@ -31,7 +31,7 @@ Pass Check that src: url("foo.ttf") tech(normal) is invalid
|
||||||
Pass Check that src: url("foo.ttf") tech(xyzzy) is invalid
|
Pass Check that src: url("foo.ttf") tech(xyzzy) is invalid
|
||||||
Pass Check that src: url("foo.ttf") tech(xyzzy, features-opentype) is invalid
|
Pass Check that src: url("foo.ttf") tech(xyzzy, features-opentype) is invalid
|
||||||
Pass Check that src: url("foo.ttf") tech(features-opentype, xyzzy) is invalid
|
Pass Check that src: url("foo.ttf") tech(features-opentype, xyzzy) is invalid
|
||||||
Fail Check that src: url("foo.ttf") format(opentype) tech(features-opentype) is valid
|
Pass Check that src: url("foo.ttf") format(opentype) tech(features-opentype) is valid
|
||||||
Pass Check that src: url("foo.ttf") tech(features-opentype) format(opentype) is invalid
|
Pass Check that src: url("foo.ttf") tech(features-opentype) format(opentype) is invalid
|
||||||
Pass Check that src: url("foo.ttf") tech(incremental), url("bar.html") is valid
|
Pass Check that src: url("foo.ttf") tech(incremental), url("bar.html") is valid
|
||||||
Pass Check that src: url("foo.ttf") tech(incremental, color-SVG, features-graphite, features-aat), url("bar.html") is valid
|
Pass Check that src: url("foo.ttf") tech(incremental, color-SVG, features-graphite, features-aat), url("bar.html") is valid
|
||||||
|
@ -41,5 +41,5 @@ Pass Check that src: url("foo.ttf") tech(features-graphite), url("bar.html") is
|
||||||
Pass Check that src: url("foo.ttf") dummy("opentype") tech(variations) is invalid
|
Pass Check that src: url("foo.ttf") dummy("opentype") tech(variations) is invalid
|
||||||
Pass Check that src: url("foo.ttf") dummy("opentype") dummy(variations) is invalid
|
Pass Check that src: url("foo.ttf") dummy("opentype") dummy(variations) is invalid
|
||||||
Pass Check that src: url("foo.ttf") format(opentype) tech(features-opentype) dummy(something) is invalid
|
Pass Check that src: url("foo.ttf") format(opentype) tech(features-opentype) dummy(something) is invalid
|
||||||
Fail Check that src: url("foo.ttf") format(dummy), url("foo.ttf") tech(variations) is valid
|
Pass Check that src: url("foo.ttf") format(dummy), url("foo.ttf") tech(variations) is valid
|
||||||
Pass Check that src: url("foo.ttf") tech(color), url("bar.html") is valid
|
Pass Check that src: url("foo.ttf") tech(color), url("bar.html") is valid
|
Loading…
Add table
Add a link
Reference in a new issue