diff --git a/Ladybird/CMakeLists.txt b/Ladybird/CMakeLists.txt index 5f54f42c56..cdbacedde9 100644 --- a/Ladybird/CMakeLists.txt +++ b/Ladybird/CMakeLists.txt @@ -51,6 +51,7 @@ set(SOURCES CookieJar.cpp EventLoopPluginQt.cpp FontPluginQt.cpp + ImageCodecPluginLadybird.cpp RequestManagerQt.cpp main.cpp WebView.cpp diff --git a/Ladybird/ImageCodecPluginLadybird.cpp b/Ladybird/ImageCodecPluginLadybird.cpp new file mode 100644 index 0000000000..c00c10ac43 --- /dev/null +++ b/Ladybird/ImageCodecPluginLadybird.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022, Dex♪ + * Copyright (c) 2022, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#define AK_DONT_REPLACE_STD + +#include "ImageCodecPluginLadybird.h" +#include +#include +#include + +namespace Ladybird { + +ImageCodecPluginLadybird::~ImageCodecPluginLadybird() = default; + +static Optional decode_image_with_qt(ReadonlyBytes data) +{ + auto image = QImage::fromData(data.data(), static_cast(data.size())); + if (image.isNull()) + return {}; + image = image.convertToFormat(QImage::Format::Format_ARGB32); + auto bitmap = MUST(Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, Gfx::IntSize(image.width(), image.height()))); + for (int y = 0; y < image.height(); ++y) { + memcpy(bitmap->scanline_u8(y), image.scanLine(y), image.width() * 4); + } + Vector frames; + + frames.append(Web::Platform::Frame { + bitmap, + }); + return Web::Platform::DecodedImage { + false, + 0, + move(frames), + }; +} + +static Optional decode_image_with_libgfx(ReadonlyBytes data) +{ + auto decoder = Gfx::ImageDecoder::try_create(data); + + if (!decoder || !decoder->frame_count()) { + return {}; + } + + bool had_errors = false; + Vector frames; + for (size_t i = 0; i < decoder->frame_count(); ++i) { + auto frame_or_error = decoder->frame(i); + if (frame_or_error.is_error()) { + frames.append({ {}, 0 }); + had_errors = true; + } else { + auto frame = frame_or_error.release_value(); + frames.append({ move(frame.image), static_cast(frame.duration) }); + } + } + + if (had_errors) + return {}; + + return Web::Platform::DecodedImage { + decoder->is_animated(), + static_cast(decoder->loop_count()), + move(frames), + }; +} + +Optional ImageCodecPluginLadybird::decode_image(ReadonlyBytes data) +{ + auto image = decode_image_with_libgfx(data); + if (image.has_value()) + return image; + return decode_image_with_qt(data); +} + +} diff --git a/Ladybird/ImageCodecPluginLadybird.h b/Ladybird/ImageCodecPluginLadybird.h new file mode 100644 index 0000000000..ae2e49ee39 --- /dev/null +++ b/Ladybird/ImageCodecPluginLadybird.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022, Dex♪ + * Copyright (c) 2022, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Ladybird { + +class ImageCodecPluginLadybird final : public Web::Platform::ImageCodecPlugin { +public: + ImageCodecPluginLadybird() = default; + virtual ~ImageCodecPluginLadybird() override; + + virtual Optional decode_image(ReadonlyBytes data) override; +}; + +} diff --git a/Ladybird/WebView.cpp b/Ladybird/WebView.cpp index 93f5fc9a48..42902ba5c8 100644 --- a/Ladybird/WebView.cpp +++ b/Ladybird/WebView.cpp @@ -12,6 +12,7 @@ #include "CookieJar.h" #include "EventLoopPluginQt.h" #include "FontPluginQt.h" +#include "ImageCodecPluginLadybird.h" #include "RequestManagerQt.h" #include #include @@ -30,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -654,80 +653,6 @@ void WebView::resizeEvent(QResizeEvent* event) m_page_client->set_viewport_rect(rect); } -static Optional decode_image_with_qt(ReadonlyBytes data) -{ - auto image = QImage::fromData(data.data(), static_cast(data.size())); - if (image.isNull()) - return {}; - image = image.convertToFormat(QImage::Format::Format_ARGB32); - auto bitmap = MUST(Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, Gfx::IntSize(image.width(), image.height()))); - for (int y = 0; y < image.height(); ++y) { - memcpy(bitmap->scanline_u8(y), image.scanLine(y), image.width() * 4); - } - Vector frames; - - frames.append(Web::ImageDecoding::Frame { - bitmap, - }); - return Web::ImageDecoding::DecodedImage { - false, - 0, - move(frames), - }; -} - -static Optional decode_image_with_libgfx(ReadonlyBytes data) -{ - auto decoder = Gfx::ImageDecoder::try_create(data); - - if (!decoder || !decoder->frame_count()) { - return {}; - } - - bool had_errors = false; - Vector frames; - for (size_t i = 0; i < decoder->frame_count(); ++i) { - auto frame_or_error = decoder->frame(i); - if (frame_or_error.is_error()) { - frames.append({ {}, 0 }); - had_errors = true; - } else { - auto frame = frame_or_error.release_value(); - frames.append({ move(frame.image), static_cast(frame.duration) }); - } - } - - if (had_errors) - return {}; - - return Web::ImageDecoding::DecodedImage { - decoder->is_animated(), - static_cast(decoder->loop_count()), - move(frames), - }; -} - -class HeadlessImageDecoderClient : public Web::ImageDecoding::Decoder { -public: - static NonnullRefPtr create() - { - return adopt_ref(*new HeadlessImageDecoderClient()); - } - - virtual ~HeadlessImageDecoderClient() override = default; - - virtual Optional decode_image(ReadonlyBytes data) override - { - auto image = decode_image_with_libgfx(data); - if (image.has_value()) - return image; - return decode_image_with_qt(data); - } - -private: - explicit HeadlessImageDecoderClient() = default; -}; - class HeadlessWebSocketClientManager : public Web::WebSockets::WebSocketClientManager { public: class HeadlessWebSocket @@ -851,8 +776,8 @@ static void platform_init() void initialize_web_engine() { Web::Platform::EventLoopPlugin::install(*new Ladybird::EventLoopPluginQt); + Web::Platform::ImageCodecPlugin::install(*new Ladybird::ImageCodecPluginLadybird); - Web::ImageDecoding::Decoder::initialize(HeadlessImageDecoderClient::create()); Web::ResourceLoader::initialize(RequestManagerQt::create()); Web::WebSockets::WebSocketClientManager::initialize(HeadlessWebSocketClientManager::create());