ladybird/Libraries/LibWeb/HTML/DecodedImageData.h
Aliaksandr Kalenik 852c7a10f3 LibWeb: Let image paint callers own clipping
DecodedImageData::paint() used to take both a destination and a
clip rectangle even though most callers passed the same value. SVG
image painting used that API to wrap every nested SVG display list in
save/add-clip/restore, which put an unbounded command in front of
the bounded nested-list command and made offscreen SVG image content
harder to cull.

Move clipping to ImagePaintable, where the object-fit destination can
be compared with the replaced element box. CSS image and marker
painting continue to draw into their destination rect, while repeated
background images keep their explicit tile clip. The scaled decoded
image display-list command now stores only its destination rect and
uses that as its bounds; playback still clips decoded images to that
rect so bitmap rendering stays unchanged.
2026-06-06 13:23:21 +01:00

47 lines
1.5 KiB
C++

/*
* Copyright (c) 2023-2025, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Optional.h>
#include <AK/RefCounted.h>
#include <LibGfx/DecodedImageFrame.h>
#include <LibGfx/ScalingMode.h>
#include <LibGfx/Size.h>
#include <LibJS/Heap/Cell.h>
#include <LibWeb/Forward.h>
#include <LibWeb/PixelUnits.h>
namespace Web::HTML {
// https://html.spec.whatwg.org/multipage/images.html#img-req-data
class DecodedImageData : public JS::Cell {
GC_CELL(DecodedImageData, JS::Cell);
public:
virtual ~DecodedImageData();
virtual Optional<Gfx::IntRect> frame_rect([[maybe_unused]] size_t frame_index) const = 0;
virtual void paint([[maybe_unused]] DisplayListRecordingContext&, [[maybe_unused]] size_t frame_index, [[maybe_unused]] Gfx::IntRect dst_rect, [[maybe_unused]] Gfx::ScalingMode scaling_mode) const = 0;
virtual Optional<Gfx::DecodedImageFrame> frame(size_t frame_index, Gfx::IntSize = {}) const = 0;
virtual int frame_duration(size_t frame_index) const = 0;
virtual size_t frame_count() const = 0;
virtual size_t loop_count() const = 0;
virtual bool is_animated() const = 0;
virtual size_t notify_frame_advanced(size_t frame_index) { return frame_index; }
virtual Optional<CSSPixels> intrinsic_width() const = 0;
virtual Optional<CSSPixels> intrinsic_height() const = 0;
virtual Optional<CSSPixelFraction> intrinsic_aspect_ratio() const = 0;
protected:
DecodedImageData();
};
}