Files
ladybird/Libraries/LibWeb/HTML/BitmapDecodedImageData.cpp
Andreas Kling a414136d7c LibWeb: Account text and image storage as external memory
Report DOM character data, decoded image frames, ImageBitmap pixel
buffers, and 2D canvas surfaces through the GC external memory hook.
This lets image and text-heavy pages participate in GC threshold
calculations through their retained backing storage.
2026-05-07 10:03:09 +02:00

83 lines
2.5 KiB
C++

/*
* Copyright (c) 2023, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGC/Heap.h>
#include <LibGfx/Bitmap.h>
#include <LibJS/Runtime/ExternalMemory.h>
#include <LibJS/Runtime/Realm.h>
#include <LibWeb/HTML/BitmapDecodedImageData.h>
#include <LibWeb/Painting/DisplayListRecorder.h>
#include <LibWeb/Painting/DisplayListRecordingContext.h>
namespace Web::HTML {
GC_DEFINE_ALLOCATOR(BitmapDecodedImageData);
ErrorOr<GC::Ref<BitmapDecodedImageData>> BitmapDecodedImageData::create(JS::Realm& realm, Vector<Frame>&& frames, size_t loop_count, bool animated)
{
return realm.create<BitmapDecodedImageData>(move(frames), loop_count, animated);
}
BitmapDecodedImageData::BitmapDecodedImageData(Vector<Frame>&& frames, size_t loop_count, bool animated)
: m_frames(move(frames))
, m_loop_count(loop_count)
, m_animated(animated)
{
}
BitmapDecodedImageData::~BitmapDecodedImageData() = default;
size_t BitmapDecodedImageData::external_memory_size() const
{
size_t size = JS::vector_external_memory_size(m_frames);
for (auto const& frame : m_frames) {
if (frame.frame)
size = JS::saturating_add_external_memory_size(size, frame.frame->bitmap().data_size());
}
return size;
}
RefPtr<Gfx::DecodedImageFrame> BitmapDecodedImageData::frame(size_t frame_index, Gfx::IntSize) const
{
if (frame_index >= m_frames.size())
return nullptr;
return m_frames[frame_index].frame;
}
int BitmapDecodedImageData::frame_duration(size_t frame_index) const
{
if (frame_index >= m_frames.size())
return 0;
return m_frames[frame_index].duration;
}
Optional<CSSPixels> BitmapDecodedImageData::intrinsic_width() const
{
return m_frames.first().frame->width();
}
Optional<CSSPixels> BitmapDecodedImageData::intrinsic_height() const
{
return m_frames.first().frame->height();
}
Optional<CSSPixelFraction> BitmapDecodedImageData::intrinsic_aspect_ratio() const
{
return CSSPixels(m_frames.first().frame->width()) / CSSPixels(m_frames.first().frame->height());
}
Optional<Gfx::IntRect> BitmapDecodedImageData::frame_rect(size_t frame_index) const
{
return m_frames[frame_index].frame->rect();
}
void BitmapDecodedImageData::paint(DisplayListRecordingContext& context, size_t frame_index, Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, Gfx::ScalingMode scaling_mode) const
{
context.display_list_recorder().draw_scaled_decoded_image_frame(dst_rect, clip_rect, *m_frames[frame_index].frame, scaling_mode);
}
}