Keep animated ImageStyleValue frame advancement owned by the style value. The current frame and loop state live there, so a separate document scheduler would duplicate ownership of that state. Start the ImageStyleValue timer only while it has layout clients. Stop it when the last client unregisters, or when a finite animation completes. Expose a document-scoped active timer count through internals for focused regression tests. Clear image observers when layout nodes detach. Use current-node cleanup for per-DOM-node clearing, and explicit subtree cleanup for tree replacement, full tree teardown, and synthetic pseudo-elements. This keeps large document clearing linear. Unregister generated-content image providers during layout detach instead of waiting for GC to finalize the provider. Cover hidden animated background images, generated content images, layout node replacement, full layout tree teardown, and document scoping for the internals counter.
52 lines
1.5 KiB
C++
52 lines
1.5 KiB
C++
/*
|
|
* Copyright (c) 2023, Andreas Kling <andreas@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Optional.h>
|
|
#include <LibGC/Cell.h>
|
|
#include <LibGfx/DecodedImageFrame.h>
|
|
#include <LibGfx/Size.h>
|
|
#include <LibWeb/Forward.h>
|
|
#include <LibWeb/PixelUnits.h>
|
|
|
|
namespace Web::Layout {
|
|
|
|
class ImageProvider {
|
|
public:
|
|
virtual ~ImageProvider() { }
|
|
|
|
virtual bool is_image_available() const = 0;
|
|
|
|
virtual size_t current_frame_index() const = 0;
|
|
|
|
virtual GC::Ptr<HTML::DecodedImageData> decoded_image_data() const = 0;
|
|
|
|
virtual Optional<CSSPixels> intrinsic_width() const = 0;
|
|
virtual Optional<CSSPixels> intrinsic_height() const = 0;
|
|
Optional<CSSPixelSize> intrinsic_size() const;
|
|
virtual Optional<CSSPixelFraction> intrinsic_aspect_ratio() const = 0;
|
|
|
|
virtual Optional<Gfx::DecodedImageFrame> current_image_frame() const;
|
|
virtual Optional<Gfx::DecodedImageFrame> current_image_frame_sized(Gfx::IntSize) const = 0;
|
|
|
|
virtual Optional<Gfx::DecodedImageFrame> default_image_frame() const;
|
|
virtual Optional<Gfx::DecodedImageFrame> default_image_frame_sized(Gfx::IntSize) const;
|
|
|
|
virtual void set_visible_in_viewport(bool) = 0;
|
|
virtual void layout_node_was_detached() const { }
|
|
|
|
virtual void image_provider_visit_edges(GC::Cell::Visitor& visitor) const
|
|
{
|
|
visitor.visit(to_html_element());
|
|
}
|
|
|
|
protected:
|
|
virtual GC::Ptr<DOM::Element const> to_html_element() const = 0;
|
|
static void did_update_alt_text(ImageBox&);
|
|
};
|
|
|
|
}
|