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 da4afde084..7bb8f8cd38 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 2cc8587c30..e2677e9651 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 3f1894763d..b87fd356cc 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 9776803902..279fb810cb 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 18b44c21be..5f2e51c09b 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; };