summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Applications/Browser/main.cpp5
-rw-r--r--Libraries/LibWeb/CMakeLists.txt2
-rw-r--r--Libraries/LibWeb/DOM/HTMLImageElement.cpp5
-rw-r--r--Libraries/LibWeb/DOM/HTMLImageElement.h1
-rw-r--r--Libraries/LibWeb/Layout/LayoutImage.cpp12
-rw-r--r--Libraries/LibWeb/Loader/ImageLoader.cpp54
-rw-r--r--Libraries/LibWeb/Loader/ImageLoader.h5
-rw-r--r--Libraries/LibWeb/Loader/ImageResource.cpp26
-rw-r--r--Libraries/LibWeb/Loader/ImageResource.h5
-rw-r--r--Libraries/LibWeb/Loader/Resource.cpp6
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());
}