mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-27 19:59:03 +00:00
LibWeb: Fix null layout node dereference in SVGMaskable
This makes sure `get_mask_type_of_svg()` finds the mask or clipPath by looking at its child layout nodes. Previously, it went via the DOM node of the mask or clipPath, which is not always correct as there is not a 1-to-1 mapping from mask DOM node to SVGMaskBox (or SVGClipBox). Fixes #24186
This commit is contained in:
parent
3a7bea7402
commit
130aff12b1
Notes:
sideshowbarker
2024-07-17 07:16:27 +09:00
Author: https://github.com/MacDue
Commit: 130aff12b1
Pull-request: https://github.com/SerenityOS/serenity/pull/24223
Issue: https://github.com/SerenityOS/serenity/issues/24186
1 changed files with 23 additions and 7 deletions
|
@ -15,14 +15,30 @@
|
|||
|
||||
namespace Web::Painting {
|
||||
|
||||
template<typename T>
|
||||
static T const* first_child_layout_node_of_type(SVG::SVGGraphicsElement const& graphics_element)
|
||||
{
|
||||
return graphics_element.layout_node()->first_child_of_type<T>();
|
||||
}
|
||||
|
||||
static auto get_mask_box(SVG::SVGGraphicsElement const& graphics_element)
|
||||
{
|
||||
return first_child_layout_node_of_type<Layout::SVGMaskBox>(graphics_element);
|
||||
}
|
||||
|
||||
static auto get_clip_box(SVG::SVGGraphicsElement const& graphics_element)
|
||||
{
|
||||
return first_child_layout_node_of_type<Layout::SVGClipBox>(graphics_element);
|
||||
}
|
||||
|
||||
Optional<CSSPixelRect> SVGMaskable::get_masking_area_of_svg() const
|
||||
{
|
||||
auto const& graphics_element = verify_cast<SVG::SVGGraphicsElement const>(*dom_node_of_svg());
|
||||
Optional<CSSPixelRect> masking_area = {};
|
||||
if (auto* mask_box = graphics_element.layout_node()->first_child_of_type<Layout::SVGMaskBox>()) {
|
||||
if (auto* mask_box = get_mask_box(graphics_element)) {
|
||||
masking_area = mask_box->dom_node().resolve_masking_area(mask_box->paintable_box()->absolute_border_box_rect());
|
||||
}
|
||||
if (auto* clip_box = graphics_element.layout_node()->first_child_of_type<Layout::SVGClipBox>()) {
|
||||
if (auto* clip_box = get_clip_box(graphics_element)) {
|
||||
// This is a bit ad-hoc, but if we have both a mask and a clip-path, intersect the two areas to find the masking area.
|
||||
auto clip_area = clip_box->paintable_box()->absolute_border_box_rect();
|
||||
if (masking_area.has_value())
|
||||
|
@ -48,9 +64,9 @@ static Gfx::Bitmap::MaskKind mask_type_to_gfx_mask_kind(CSS::MaskType mask_type)
|
|||
Optional<Gfx::Bitmap::MaskKind> SVGMaskable::get_mask_type_of_svg() const
|
||||
{
|
||||
auto const& graphics_element = verify_cast<SVG::SVGGraphicsElement const>(*dom_node_of_svg());
|
||||
if (auto mask = graphics_element.mask())
|
||||
return mask_type_to_gfx_mask_kind(mask->layout_node()->computed_values().mask_type());
|
||||
if (graphics_element.clip_path())
|
||||
if (auto* mask_box = get_mask_box(graphics_element))
|
||||
return mask_type_to_gfx_mask_kind(mask_box->computed_values().mask_type());
|
||||
if (get_clip_box(graphics_element))
|
||||
return Gfx::Bitmap::MaskKind::Alpha;
|
||||
return {};
|
||||
}
|
||||
|
@ -77,11 +93,11 @@ RefPtr<Gfx::Bitmap> SVGMaskable::calculate_mask_of_svg(PaintContext& context, CS
|
|||
return mask_bitmap;
|
||||
};
|
||||
RefPtr<Gfx::Bitmap> mask_bitmap = {};
|
||||
if (auto* mask_box = graphics_element.layout_node()->first_child_of_type<Layout::SVGMaskBox>()) {
|
||||
if (auto* mask_box = get_mask_box(graphics_element)) {
|
||||
auto& mask_paintable = static_cast<PaintableBox const&>(*mask_box->paintable());
|
||||
mask_bitmap = paint_mask_or_clip(mask_paintable);
|
||||
}
|
||||
if (auto* clip_box = graphics_element.layout_node()->first_child_of_type<Layout::SVGClipBox>()) {
|
||||
if (auto* clip_box = get_clip_box(graphics_element)) {
|
||||
auto& clip_paintable = static_cast<PaintableBox const&>(*clip_box->paintable());
|
||||
auto clip_bitmap = paint_mask_or_clip(clip_paintable);
|
||||
// Combine the clip-path with the mask (if present).
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue