LibWeb: Paint/apply basic-shape clip paths to PaintableBoxes

Currently, these only work when there are no CSS transforms (as the
stacking context painting is not set up to handle that case yet). This
is still enough to get most chat/comment markers working on GitHub
though :^)
This commit is contained in:
MacDue 2024-05-26 00:28:48 +01:00 committed by Andreas Kling
parent 517379ff80
commit 9e2c4f84fd
Notes: sideshowbarker 2024-07-17 00:23:42 +09:00
2 changed files with 40 additions and 3 deletions

View file

@ -869,4 +869,41 @@ void PaintableBox::set_needs_display() const
navigable->set_needs_display(absolute_rect());
}
Optional<CSSPixelRect> PaintableBox::get_masking_area() const
{
// FIXME: Support clip-paths with transforms.
if (!combined_css_transform().is_identity_or_translation())
return {};
auto clip_path = computed_values().clip_path();
// FIXME: Support other clip sources.
if (!clip_path.has_value() || !clip_path->is_basic_shape())
return {};
// FIXME: Support other geometry boxes. See: https://drafts.fxtf.org/css-masking/#typedef-geometry-box
return absolute_border_box_rect();
}
Optional<Gfx::Bitmap::MaskKind> PaintableBox::get_mask_type() const
{
// Always an alpha mask as only basic shapes are supported right now.
return Gfx::Bitmap::MaskKind::Alpha;
}
RefPtr<Gfx::Bitmap> PaintableBox::calculate_mask(PaintContext& context, CSSPixelRect const& masking_area) const
{
VERIFY(computed_values().clip_path()->is_basic_shape());
auto const& basic_shape = computed_values().clip_path()->basic_shape();
auto path = basic_shape.to_path(masking_area, layout_node());
auto device_pixel_scale = context.device_pixels_per_css_pixel();
path = path.copy_transformed(Gfx::AffineTransform {}.set_scale(device_pixel_scale, device_pixel_scale));
auto mask_rect = context.enclosing_device_rect(masking_area);
auto maybe_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, mask_rect.size().to_type<int>());
if (maybe_bitmap.is_error())
return {};
auto bitmap = maybe_bitmap.release_value();
Gfx::Painter painter(*bitmap);
Gfx::AntiAliasingPainter aa_painter(painter);
aa_painter.fill_path(path, Color::Black);
return bitmap;
}
}

View file

@ -29,9 +29,9 @@ public:
virtual void paint(PaintContext&, PaintPhase) const override;
virtual Optional<CSSPixelRect> get_masking_area() const { return {}; }
virtual Optional<Gfx::Bitmap::MaskKind> get_mask_type() const { return {}; }
virtual RefPtr<Gfx::Bitmap> calculate_mask(PaintContext&, CSSPixelRect const&) const { return {}; }
virtual Optional<CSSPixelRect> get_masking_area() const;
virtual Optional<Gfx::Bitmap::MaskKind> get_mask_type() const;
virtual RefPtr<Gfx::Bitmap> calculate_mask(PaintContext&, CSSPixelRect const&) const;
Layout::Box& layout_box() { return static_cast<Layout::Box&>(Paintable::layout_node()); }
Layout::Box const& layout_box() const { return static_cast<Layout::Box const&>(Paintable::layout_node()); }