فهرست منبع

LibWeb: Parse `@font-face` `unicode-range` descriptor

Sam Atkins 3 سال پیش
والد
کامیت
dbbd6d3508

+ 2 - 1
Userland/Libraries/LibWeb/CSS/FontFace.cpp

@@ -8,9 +8,10 @@
 
 namespace Web::CSS {
 
-FontFace::FontFace(FlyString font_family, Vector<Source> sources)
+FontFace::FontFace(FlyString font_family, Vector<Source> sources, Vector<UnicodeRange> unicode_ranges)
     : m_font_family(move(font_family))
     , m_sources(move(sources))
+    , m_unicode_ranges(move(unicode_ranges))
 {
 }
 

+ 5 - 2
Userland/Libraries/LibWeb/CSS/FontFace.h

@@ -8,6 +8,7 @@
 
 #include <AK/FlyString.h>
 #include <AK/URL.h>
+#include <LibWeb/CSS/UnicodeRange.h>
 
 namespace Web::CSS {
 
@@ -17,16 +18,18 @@ public:
         AK::URL url;
     };
 
-    FontFace(FlyString font_family, Vector<Source> sources);
+    FontFace(FlyString font_family, Vector<Source> sources, Vector<UnicodeRange> unicode_ranges);
     ~FontFace() = default;
 
     FlyString font_family() const { return m_font_family; }
     Vector<Source> const& sources() const { return m_sources; }
-    // FIXME: font-style, font-weight, font-stretch, unicode-range, font-feature-settings
+    Vector<UnicodeRange> const& unicode_ranges() const { return m_unicode_ranges; }
+    // FIXME: font-style, font-weight, font-stretch, font-feature-settings
 
 private:
     FlyString m_font_family;
     Vector<Source> m_sources;
+    Vector<UnicodeRange> m_unicode_ranges;
 };
 
 }

+ 29 - 1
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -4384,6 +4384,7 @@ RefPtr<CSSRule> Parser::parse_font_face_rule(TokenStream<ComponentValue>& tokens
 
     Optional<FlyString> font_family;
     Vector<FontFace::Source> src;
+    Vector<UnicodeRange> unicode_range;
 
     for (auto& declaration_or_at_rule : declarations_and_at_rules) {
         if (declaration_or_at_rule.is_at_rule()) {
@@ -4460,6 +4461,29 @@ RefPtr<CSSRule> Parser::parse_font_face_rule(TokenStream<ComponentValue>& tokens
             if (supported_sources.is_empty())
                 continue;
             src = move(supported_sources);
+            continue;
+        }
+        if (declaration.name().equals_ignoring_case("unicode-range"sv)) {
+            Vector<UnicodeRange> unicode_ranges;
+            bool unicode_range_invalid = false;
+            TokenStream all_tokens { declaration.values() };
+            auto range_token_lists = parse_a_comma_separated_list_of_component_values(all_tokens);
+            for (auto& range_tokens : range_token_lists) {
+                TokenStream range_token_stream { range_tokens };
+                auto maybe_unicode_range = parse_unicode_range(range_token_stream);
+                if (!maybe_unicode_range.has_value()) {
+                    dbgln_if(CSS_PARSER_DEBUG, "CSSParser: @font-face unicode-range format invalid; discarding.");
+                    unicode_range_invalid = true;
+                    break;
+                }
+                unicode_ranges.append(maybe_unicode_range.release_value());
+            }
+
+            if (unicode_range_invalid || unicode_ranges.is_empty())
+                continue;
+
+            unicode_range = move(unicode_ranges);
+            continue;
         }
 
         dbgln_if(CSS_PARSER_DEBUG, "CSSParser: Unrecognized descriptor '{}' in @font-family; discarding.", declaration.name());
@@ -4470,7 +4494,11 @@ RefPtr<CSSRule> Parser::parse_font_face_rule(TokenStream<ComponentValue>& tokens
         return {};
     }
 
-    return CSSFontFaceRule::create(FontFace { font_family.release_value(), move(src) });
+    if (unicode_range.is_empty()) {
+        unicode_range.empend(0x0u, 0x10FFFFu);
+    }
+
+    return CSSFontFaceRule::create(FontFace { font_family.release_value(), move(src), move(unicode_range) });
 }
 
 RefPtr<StyleValue> Parser::parse_list_style_value(Vector<ComponentValue> const& component_values)

+ 7 - 0
Userland/Libraries/LibWeb/Dump.cpp

@@ -580,6 +580,13 @@ void dump_font_face_rule(StringBuilder& builder, CSS::CSSFontFaceRule const& rul
         indent(builder, indent_levels + 2);
         builder.appendff("{}\n", source.url);
     }
+
+    indent(builder, indent_levels + 1);
+    builder.append("unicode-ranges:\n");
+    for (auto const& unicode_range : font_face.unicode_ranges()) {
+        indent(builder, indent_levels + 2);
+        builder.appendff("{}\n", unicode_range.to_string());
+    }
 }
 
 void dump_import_rule(StringBuilder& builder, CSS::CSSImportRule const& rule, int indent_levels)