diff options
-rw-r--r-- | Applications/Browser/main.cpp | 5 | ||||
-rw-r--r-- | Libraries/LibWeb/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/HTMLImageElement.cpp | 5 | ||||
-rw-r--r-- | Libraries/LibWeb/DOM/HTMLImageElement.h | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/LayoutImage.cpp | 12 | ||||
-rw-r--r-- | Libraries/LibWeb/Loader/ImageLoader.cpp | 54 | ||||
-rw-r--r-- | Libraries/LibWeb/Loader/ImageLoader.h | 5 | ||||
-rw-r--r-- | Libraries/LibWeb/Loader/ImageResource.cpp | 26 | ||||
-rw-r--r-- | Libraries/LibWeb/Loader/ImageResource.h | 5 | ||||
-rw-r--r-- | Libraries/LibWeb/Loader/Resource.cpp | 6 |
10 files changed, 96 insertions, 25 deletions
diff --git a/Applications/Browser/main.cpp b/Applications/Browser/main.cpp index f8fdf7804a..9982276ebf 100644 --- a/Applications/Browser/main.cpp +++ b/Applications/Browser/main.cpp @@ -102,6 +102,11 @@ int main(int argc, char** argv) return 1; } + if (unveil("/tmp/portal/image", "rw") < 0) { + perror("unveil"); + return 1; + } + unveil(nullptr, nullptr); auto m_config = Core::ConfigFile::get_for_app("Browser"); diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index fb3cf7c7d0..c966491981 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -193,4 +193,4 @@ add_custom_command( ) serenity_lib(LibWeb web) -target_link_libraries(LibWeb LibCore LibJS LibMarkdown LibGemini LibGUI LibGfx LibTextCodec LibProtocol) +target_link_libraries(LibWeb LibCore LibJS LibMarkdown LibGemini LibGUI LibGfx LibTextCodec LibProtocol LibImageDecoderClient) diff --git a/Libraries/LibWeb/DOM/HTMLImageElement.cpp b/Libraries/LibWeb/DOM/HTMLImageElement.cpp index 52d9601d17..7c0e969f8d 100644 --- a/Libraries/LibWeb/DOM/HTMLImageElement.cpp +++ b/Libraries/LibWeb/DOM/HTMLImageElement.cpp @@ -77,11 +77,6 @@ RefPtr<LayoutNode> HTMLImageElement::create_layout_node(const StyleProperties* p return adopt(*new LayoutImage(*this, move(style), m_image_loader)); } -const Gfx::ImageDecoder* HTMLImageElement::image_decoder() const -{ - return m_image_loader.image_decoder(); -} - const Gfx::Bitmap* HTMLImageElement::bitmap() const { return m_image_loader.bitmap(); diff --git a/Libraries/LibWeb/DOM/HTMLImageElement.h b/Libraries/LibWeb/DOM/HTMLImageElement.h index a981bb432c..a4a0870194 100644 --- a/Libraries/LibWeb/DOM/HTMLImageElement.h +++ b/Libraries/LibWeb/DOM/HTMLImageElement.h @@ -49,7 +49,6 @@ public: String src() const { return attribute(HTML::AttributeNames::src); } const Gfx::Bitmap* bitmap() const; - const Gfx::ImageDecoder* image_decoder() const; private: void animate(); diff --git a/Libraries/LibWeb/Layout/LayoutImage.cpp b/Libraries/LibWeb/Layout/LayoutImage.cpp index 94de65f0ef..17848fc900 100644 --- a/Libraries/LibWeb/Layout/LayoutImage.cpp +++ b/Libraries/LibWeb/Layout/LayoutImage.cpp @@ -44,14 +44,12 @@ LayoutImage::~LayoutImage() int LayoutImage::preferred_width() const { - auto* decoder = m_image_loader.image_decoder(); - return node().attribute(HTML::AttributeNames::width).to_int().value_or(decoder ? decoder->width() : 0); + return node().attribute(HTML::AttributeNames::width).to_int().value_or(m_image_loader.width()); } int LayoutImage::preferred_height() const { - auto* decoder = m_image_loader.image_decoder(); - return node().attribute(HTML::AttributeNames::height).to_int().value_or(decoder ? decoder->height() : 0); + return node().attribute(HTML::AttributeNames::height).to_int().value_or(m_image_loader.height()); } void LayoutImage::layout(LayoutMode layout_mode) @@ -97,8 +95,8 @@ void LayoutImage::paint(PaintContext& context, PaintPhase phase) if (alt.is_empty()) alt = image_element.src(); context.painter().draw_text(enclosing_int_rect(absolute_rect()), alt, Gfx::TextAlignment::Center, style().color_or_fallback(CSS::PropertyID::Color, document(), Color::Black), Gfx::TextElision::Right); - } else if (m_image_loader.bitmap()) { - context.painter().draw_scaled_bitmap(enclosing_int_rect(absolute_rect()), *m_image_loader.bitmap(), m_image_loader.bitmap()->rect()); + } else if (auto* bitmap = m_image_loader.bitmap()) { + context.painter().draw_scaled_bitmap(enclosing_int_rect(absolute_rect()), *bitmap, bitmap->rect()); } } } @@ -106,7 +104,7 @@ void LayoutImage::paint(PaintContext& context, PaintPhase phase) bool LayoutImage::renders_as_alt_text() const { if (is<HTMLImageElement>(node())) - return !m_image_loader.image_decoder(); + return !m_image_loader.has_image(); return false; } diff --git a/Libraries/LibWeb/Loader/ImageLoader.cpp b/Libraries/LibWeb/Loader/ImageLoader.cpp index c581242d4c..8e1218ae9b 100644 --- a/Libraries/LibWeb/Loader/ImageLoader.cpp +++ b/Libraries/LibWeb/Loader/ImageLoader.cpp @@ -67,18 +67,23 @@ void ImageLoader::resource_did_load() return; } +#ifdef IMAGE_LOADER_DEBUG if (!resource()->has_encoded_data()) { dbg() << "ImageLoader: Resource did load, no encoded data. URL: " << resource()->url(); } else { dbg() << "ImageLoader: Resource did load, has encoded data. URL: " << resource()->url(); } - m_decoder = resource()->ensure_decoder(); +#endif - if (m_decoder->is_animated() && m_decoder->frame_count() > 1) { - const auto& first_frame = m_decoder->frame(0); - m_timer->set_interval(first_frame.duration); - m_timer->on_timeout = [this] { animate(); }; - m_timer->start(); + if (resource()->should_decode_in_process()) { + m_decoder = resource()->ensure_decoder(); + + if (m_decoder->is_animated() && m_decoder->frame_count() > 1) { + const auto& first_frame = m_decoder->frame(0); + m_timer->set_interval(first_frame.duration); + m_timer->on_timeout = [this] { animate(); }; + m_timer->start(); + } } if (on_load) @@ -120,16 +125,43 @@ void ImageLoader::resource_did_fail() void ImageLoader::resource_did_replace_decoder() { - m_decoder = resource()->ensure_decoder(); + if (resource()->should_decode_in_process()) { + m_decoder = resource()->ensure_decoder(); + } +} + +bool ImageLoader::has_image() const +{ + if (!resource()) + return false; + if (resource()->should_decode_in_process()) + return image_decoder(); + return true; +} + +unsigned ImageLoader::width() const +{ + if (!resource()) + return 0; + if (resource()->should_decode_in_process()) + return image_decoder() ? image_decoder()->width() : 0; + return bitmap() ? bitmap()->width() : 0; +} + +unsigned ImageLoader::height() const +{ + if (!resource()) + return 0; + if (resource()->should_decode_in_process()) + return image_decoder() ? image_decoder()->height() : 0; + return bitmap() ? bitmap()->height() : 0; } const Gfx::Bitmap* ImageLoader::bitmap() const { - if (!m_decoder) + if (!resource()) return nullptr; - if (m_decoder->is_animated()) - return m_decoder->frame(m_current_frame_index).image; - return m_decoder->bitmap(); + return resource()->bitmap(0); } const Gfx::ImageDecoder* ImageLoader::image_decoder() const diff --git a/Libraries/LibWeb/Loader/ImageLoader.h b/Libraries/LibWeb/Loader/ImageLoader.h index 71cd48ff64..2bebcaa6fa 100644 --- a/Libraries/LibWeb/Loader/ImageLoader.h +++ b/Libraries/LibWeb/Loader/ImageLoader.h @@ -41,8 +41,13 @@ public: const Gfx::Bitmap* bitmap() const; const Gfx::ImageDecoder* image_decoder() const; + bool has_image() const; + void set_visible_in_viewport(bool) const; + unsigned width() const; + unsigned height() const; + Function<void()> on_load; Function<void()> on_fail; Function<void()> on_animate; diff --git a/Libraries/LibWeb/Loader/ImageResource.cpp b/Libraries/LibWeb/Loader/ImageResource.cpp index efacec3aa1..35a02d0e79 100644 --- a/Libraries/LibWeb/Loader/ImageResource.cpp +++ b/Libraries/LibWeb/Loader/ImageResource.cpp @@ -27,6 +27,7 @@ #include <AK/Function.h> #include <LibGfx/Bitmap.h> #include <LibGfx/ImageDecoder.h> +#include <LibImageDecoderClient/Client.h> #include <LibWeb/Loader/ImageResource.h> namespace Web { @@ -40,6 +41,11 @@ ImageResource::~ImageResource() { } +bool ImageResource::should_decode_in_process() const +{ + return mime_type() == "image/gif"; +} + Gfx::ImageDecoder& ImageResource::ensure_decoder() { if (!m_decoder) @@ -47,6 +53,26 @@ Gfx::ImageDecoder& ImageResource::ensure_decoder() return *m_decoder; } +const Gfx::Bitmap* ImageResource::bitmap(size_t frame_index) const +{ + if (!has_encoded_data()) + return nullptr; + + if (should_decode_in_process()) { + if (!m_decoder) + return nullptr; + if (m_decoder->is_animated()) + return m_decoder->frame(frame_index).image; + return m_decoder->bitmap(); + } + if (!m_decoded_image && !m_has_attempted_decode) { + auto image_decoder_client = ImageDecoderClient::Client::construct(); + m_decoded_image = image_decoder_client->decode_image(encoded_data()); + m_has_attempted_decode = true; + } + return m_decoded_image; +} + void ImageResource::update_volatility() { if (!m_decoder) diff --git a/Libraries/LibWeb/Loader/ImageResource.h b/Libraries/LibWeb/Loader/ImageResource.h index 474e78debd..1cf88a8f5b 100644 --- a/Libraries/LibWeb/Loader/ImageResource.h +++ b/Libraries/LibWeb/Loader/ImageResource.h @@ -36,12 +36,17 @@ class ImageResource final : public Resource { public: virtual ~ImageResource() override; Gfx::ImageDecoder& ensure_decoder(); + const Gfx::Bitmap* bitmap(size_t frame_index) const; + + bool should_decode_in_process() const; void update_volatility(); private: explicit ImageResource(const LoadRequest&); RefPtr<Gfx::ImageDecoder> m_decoder; + mutable RefPtr<Gfx::Bitmap> m_decoded_image; + mutable bool m_has_attempted_decode { false }; }; class ImageResourceClient : public ResourceClient { diff --git a/Libraries/LibWeb/Loader/Resource.cpp b/Libraries/LibWeb/Loader/Resource.cpp index 780c3b4113..493a783d39 100644 --- a/Libraries/LibWeb/Loader/Resource.cpp +++ b/Libraries/LibWeb/Loader/Resource.cpp @@ -107,15 +107,21 @@ void Resource::did_load(Badge<ResourceLoader>, const ByteBuffer& data, const Has auto content_type = headers.get("Content-Type"); if (content_type.has_value()) { +#ifdef RESOURCE_DEBUG dbg() << "Content-Type header: _" << content_type.value() << "_"; +#endif m_encoding = encoding_from_content_type(content_type.value()); m_mime_type = mime_type_from_content_type(content_type.value()); } else if (url().protocol() == "data" && !url().data_mime_type().is_empty()) { +#ifdef RESOURCE_DEBUG dbg() << "This is a data URL with mime-type _" << url().data_mime_type() << "_"; +#endif m_encoding = "utf-8"; // FIXME: This doesn't seem nice. m_mime_type = url().data_mime_type(); } else { +#ifdef RESOURCE_DEBUG dbg() << "No Content-Type header to go on! Guessing based on filename..."; +#endif m_encoding = "utf-8"; // FIXME: This doesn't seem nice. m_mime_type = guess_mime_type_based_on_filename(url()); } |