Browse Source

LibWeb: Remove all font loaders linked to a StyleSheet when it's deleted

When a style sheet is removed, all font loaders created from that style
sheet should also be removed.
Aliaksandr Kalenik 10 tháng trước cách đây
mục cha
commit
74588a0a16

+ 9 - 0
Userland/Libraries/LibWeb/CSS/CSSStyleSheet.cpp

@@ -402,4 +402,13 @@ Optional<String> CSSStyleSheet::source_text(Badge<DOM::Document>) const
     return m_source_text;
 }
 
+bool CSSStyleSheet::has_associated_font_loader(FontLoader& font_loader) const
+{
+    for (auto& loader : m_associated_font_loaders) {
+        if (loader.ptr() == &font_loader)
+            return true;
+    }
+    return false;
+}
+
 }

+ 9 - 0
Userland/Libraries/LibWeb/CSS/CSSStyleSheet.h

@@ -18,6 +18,7 @@
 namespace Web::CSS {
 
 class CSSImportRule;
+class FontLoader;
 
 struct CSSStyleSheetInit {
     Optional<String> base_url {};
@@ -84,6 +85,12 @@ public:
     void set_source_text(String);
     Optional<String> source_text(Badge<DOM::Document>) const;
 
+    void add_associated_font_loader(WeakPtr<FontLoader const> font_loader)
+    {
+        m_associated_font_loaders.append(font_loader);
+    }
+    bool has_associated_font_loader(FontLoader& font_loader) const;
+
 private:
     CSSStyleSheet(JS::Realm&, CSSRuleList&, MediaList&, Optional<URL::URL> location);
 
@@ -110,6 +117,8 @@ private:
     bool m_constructed { false };
     bool m_disallow_modification { false };
     Optional<bool> m_did_match;
+
+    Vector<WeakPtr<FontLoader const>> m_associated_font_loaders;
 };
 
 }

+ 14 - 2
Userland/Libraries/LibWeb/CSS/StyleComputer.cpp

@@ -2794,12 +2794,24 @@ Optional<FontLoader&> StyleComputer::load_font_face(ParsedFontFace const& font_f
     return loader_ref;
 }
 
-void StyleComputer::load_fonts_from_sheet(CSSStyleSheet const& sheet)
+void StyleComputer::load_fonts_from_sheet(CSSStyleSheet& sheet)
 {
     for (auto const& rule : sheet.rules()) {
         if (!is<CSSFontFaceRule>(*rule))
             continue;
-        (void)load_font_face(static_cast<CSSFontFaceRule const&>(*rule).font_face());
+        auto font_loader = load_font_face(static_cast<CSSFontFaceRule const&>(*rule).font_face());
+        if (font_loader.has_value()) {
+            sheet.add_associated_font_loader(font_loader.value());
+        }
+    }
+}
+
+void StyleComputer::unload_fonts_from_sheet(CSSStyleSheet& sheet)
+{
+    for (auto& [_, font_loader_list] : m_loaded_fonts) {
+        font_loader_list.remove_all_matching([&](auto& font_loader) {
+            return sheet.has_associated_font_loader(*font_loader);
+        });
     }
 }
 

+ 2 - 1
Userland/Libraries/LibWeb/CSS/StyleComputer.h

@@ -144,7 +144,8 @@ public:
 
     Optional<FontLoader&> load_font_face(ParsedFontFace const&, ESCAPING Function<void(FontLoader const&)> on_load = {}, ESCAPING Function<void()> on_fail = {});
 
-    void load_fonts_from_sheet(CSSStyleSheet const&);
+    void load_fonts_from_sheet(CSSStyleSheet&);
+    void unload_fonts_from_sheet(CSSStyleSheet&);
 
     RefPtr<Gfx::FontCascadeList const> compute_font_for_style_values(DOM::Element const* element, Optional<CSS::Selector::PseudoElement::Type> pseudo_element, CSSStyleValue const& font_family, CSSStyleValue const& font_size, CSSStyleValue const& font_style, CSSStyleValue const& font_weight, CSSStyleValue const& font_stretch, int math_depth = 0) const;
 

+ 1 - 0
Userland/Libraries/LibWeb/CSS/StyleSheetList.cpp

@@ -123,6 +123,7 @@ void StyleSheetList::remove_sheet(CSSStyleSheet& sheet)
         return;
     }
 
+    m_document_or_shadow_root->document().style_computer().unload_fonts_from_sheet(sheet);
     m_document_or_shadow_root->document().style_computer().invalidate_rule_cache();
     document_or_shadow_root().invalidate_style(DOM::StyleInvalidationReason::StyleSheetListRemoveSheet);
 }