From 54bd322881a3ce316596ec535e59ce0b0dcf2da0 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 18 Dec 2019 20:57:18 +0100 Subject: [PATCH] LibHTML: Mark image bitmaps outside the visible viewport as volatile When the visible viewport rect changes, we walk the layout tree and check where each LayoutImage is in relation to the viewport rect. Images outside have their bitmaps marked as volatile. Note that the bitmaps are managed by ImageDecoder objects. If a bitmap is purged by the kernel while volatile, we construct a new ImageDecoder next time we need pixels for the image. --- Libraries/LibHTML/DOM/HTMLImageElement.cpp | 14 ++++++++++++++ Libraries/LibHTML/DOM/HTMLImageElement.h | 5 ++++- Libraries/LibHTML/Frame.cpp | 4 ++++ Libraries/LibHTML/Layout/LayoutDocument.cpp | 15 ++++++++++++++- Libraries/LibHTML/Layout/LayoutDocument.h | 2 ++ 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/Libraries/LibHTML/DOM/HTMLImageElement.cpp b/Libraries/LibHTML/DOM/HTMLImageElement.cpp index da4afde0848..7bb8f8cd38d 100644 --- a/Libraries/LibHTML/DOM/HTMLImageElement.cpp +++ b/Libraries/LibHTML/DOM/HTMLImageElement.cpp @@ -80,3 +80,17 @@ const GraphicsBitmap* HTMLImageElement::bitmap() const return nullptr; return m_image_decoder->bitmap(); } + +void HTMLImageElement::set_volatile(Badge, bool v) +{ + if (!m_image_decoder) + return; + if (v) { + m_image_decoder->set_volatile(); + return; + } + bool has_image = m_image_decoder->set_nonvolatile(); + if (has_image) + return; + m_image_decoder = ImageDecoder::create(m_encoded_data.data(), m_encoded_data.size()); +} diff --git a/Libraries/LibHTML/DOM/HTMLImageElement.h b/Libraries/LibHTML/DOM/HTMLImageElement.h index 2cc8587c30e..e2677e9651d 100644 --- a/Libraries/LibHTML/DOM/HTMLImageElement.h +++ b/Libraries/LibHTML/DOM/HTMLImageElement.h @@ -4,6 +4,8 @@ #include #include +class LayoutDocument; + class HTMLImageElement : public HTMLElement { public: HTMLImageElement(Document&, const String& tag_name); @@ -19,12 +21,13 @@ public: const GraphicsBitmap* bitmap() const; const ImageDecoder* image_decoder() const { return m_image_decoder; } + void set_volatile(Badge, bool); + private: void load_image(const String& src); virtual RefPtr create_layout_node(const StyleProperties* parent_style) const override; RefPtr m_image_decoder; - mutable RefPtr m_bitmap; ByteBuffer m_encoded_data; }; diff --git a/Libraries/LibHTML/Frame.cpp b/Libraries/LibHTML/Frame.cpp index 3f1894763d3..b87fd356ccf 100644 --- a/Libraries/LibHTML/Frame.cpp +++ b/Libraries/LibHTML/Frame.cpp @@ -1,6 +1,7 @@ #include #include #include +#include Frame::Frame(HtmlView& html_view) : m_html_view(html_view.make_weak_ptr()) @@ -37,6 +38,9 @@ void Frame::set_viewport_rect(const Rect& rect) if (m_viewport_rect == rect) return; m_viewport_rect = rect; + + if (m_document && m_document->layout_node()) + m_document->layout_node()->did_set_viewport_rect({}, rect); } void Frame::set_needs_display(const Rect& rect) diff --git a/Libraries/LibHTML/Layout/LayoutDocument.cpp b/Libraries/LibHTML/Layout/LayoutDocument.cpp index 97768039029..279fb810cbf 100644 --- a/Libraries/LibHTML/Layout/LayoutDocument.cpp +++ b/Libraries/LibHTML/Layout/LayoutDocument.cpp @@ -1,6 +1,7 @@ -#include #include +#include #include +#include LayoutDocument::LayoutDocument(const Document& document, NonnullRefPtr style) : LayoutBlock(&document, move(style)) @@ -29,3 +30,15 @@ void LayoutDocument::layout() }); rect().set_bottom(lowest_bottom); } + +void LayoutDocument::did_set_viewport_rect(Badge, const Rect& a_viewport_rect) +{ + FloatRect viewport_rect(a_viewport_rect.x(), a_viewport_rect.y(), a_viewport_rect.width(), a_viewport_rect.height()); + for_each_in_subtree([&](auto& layout_node) { + if (is(layout_node)) { + auto& image = to(layout_node); + const_cast(image.node()).set_volatile({}, !viewport_rect.intersects(image.rect())); + } + return IterationDecision::Continue; + }); +} diff --git a/Libraries/LibHTML/Layout/LayoutDocument.h b/Libraries/LibHTML/Layout/LayoutDocument.h index 18b44c21bed..5f2e51c09b6 100644 --- a/Libraries/LibHTML/Layout/LayoutDocument.h +++ b/Libraries/LibHTML/Layout/LayoutDocument.h @@ -15,6 +15,8 @@ public: const LayoutRange& selection() const { return m_selection; } LayoutRange& selection() { return m_selection; } + void did_set_viewport_rect(Badge, const Rect&); + private: LayoutRange m_selection; };