Files
ladybird/Libraries/LibWeb/Painting/SVGMaskable.h
Aliaksandr Kalenik e190f3ec23 LibWeb: Compute SVG mask/clip transforms using layout tree hierarchy
No observable behavior change — this is a refactoring of how SVG
transforms are computed for mask and clip content.

Previously, SVGGraphicsElement::get_transform() computed accumulated
transforms by walking the DOM tree. This didn't work correctly for masks
and clips because their DOM structure differs from layout: in the DOM,
mask/clip elements are siblings or ancestors of their targets, but in
the layout tree they become children of the target element. Walking the
DOM tree caused transforms from the target's ancestors to incorrectly
leak into mask/clip content.

The fix walks the layout tree instead of the DOM tree, which means
transform computation must happen during layout (where we have access to
the layout tree structure) rather than on-demand from the DOM element.
This moves the logic to SVGFormattingContext and removes get_transform()
since it can no longer serve its purpose — the DOM element only provides
element_transform() for its own transform now.

During layout, we walk up the layout tree and stop at mask/clip
boundaries, ensuring mask/clip content stays in its own coordinate
space. The target's accumulated transform is applied separately at paint
time.
2026-02-05 09:00:56 +01:00

35 lines
932 B
C++

/*
* Copyright (c) 2024-2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/Forward.h>
#include <LibWeb/Forward.h>
#include <LibWeb/PixelUnits.h>
#pragma once
namespace Web::Painting {
class SVGMaskable {
public:
virtual ~SVGMaskable() = default;
virtual GC::Ptr<DOM::Node const> dom_node_of_svg() const = 0;
// For <mask> element
Optional<CSSPixelRect> get_svg_mask_area() const;
Optional<Gfx::MaskKind> get_svg_mask_type() const;
RefPtr<DisplayList> calculate_svg_mask_display_list(DisplayListRecordingContext&, CSSPixelRect const& mask_area) const;
// For <clipPath> element
Optional<CSSPixelRect> get_svg_clip_area() const;
RefPtr<DisplayList> calculate_svg_clip_display_list(DisplayListRecordingContext&, CSSPixelRect const& clip_area) const;
private:
Gfx::AffineTransform target_svg_transform() const;
};
}