LibWeb: Migrate CSS filter application to new ApplyFilters command

This helps reuse this code in other areas, such as for filters for SVGs
This commit is contained in:
Saksham Mittal 2024-11-22 19:53:59 +05:30 committed by Alexander Kalenik
commit 8562b0e33b
Notes: github-actions[bot] 2024-11-23 19:22:17 +00:00
8 changed files with 53 additions and 31 deletions

View file

@ -27,6 +27,7 @@
#include <LibGfx/Size.h>
#include <LibGfx/TextAlignment.h>
#include <LibGfx/TextLayout.h>
#include <LibWeb/CSS/ComputedValues.h>
#include <LibWeb/CSS/Enums.h>
#include <LibWeb/Painting/BorderRadiiData.h>
#include <LibWeb/Painting/BorderRadiusCornerClipper.h>
@ -118,7 +119,6 @@ struct StackingContextTransform {
struct PushStackingContext {
float opacity;
CSS::ResolvedFilter filter;
// The bounding box of the source paintable (pre-transform).
Gfx::IntRect source_paintable_rect;
// A translation to be applied after the stacking context has been transformed.
@ -408,6 +408,11 @@ struct ApplyOpacity {
float opacity;
};
struct ApplyFilters {
float opacity;
CSS::ResolvedFilter filter;
};
struct ApplyTransform {
Gfx::FloatPoint origin;
Gfx::FloatMatrix4x4 matrix;
@ -463,6 +468,7 @@ using Command = Variant<
PaintNestedDisplayList,
PaintScrollBar,
ApplyOpacity,
ApplyFilters,
ApplyTransform,
ApplyMaskBitmap>;

View file

@ -122,6 +122,7 @@ void DisplayListPlayer::execute(DisplayList& display_list)
else HANDLE_COMMAND(PaintScrollBar, paint_scrollbar)
else HANDLE_COMMAND(PaintNestedDisplayList, paint_nested_display_list)
else HANDLE_COMMAND(ApplyOpacity, apply_opacity)
else HANDLE_COMMAND(ApplyFilters, apply_filters)
else HANDLE_COMMAND(ApplyTransform, apply_transform)
else HANDLE_COMMAND(ApplyMaskBitmap, apply_mask_bitmap)
else VERIFY_NOT_REACHED();

View file

@ -76,6 +76,7 @@ private:
virtual void paint_nested_display_list(PaintNestedDisplayList const&) = 0;
virtual void paint_scrollbar(PaintScrollBar const&) = 0;
virtual void apply_opacity(ApplyOpacity const&) = 0;
virtual void apply_filters(ApplyFilters const&) = 0;
virtual void apply_transform(ApplyTransform const&) = 0;
virtual void apply_mask_bitmap(ApplyMaskBitmap const&) = 0;
virtual bool would_be_fully_clipped_by_painter(Gfx::IntRect) const = 0;

View file

@ -396,33 +396,7 @@ void DisplayListPlayerSkia::push_stacking_context(PushStackingContext const& com
.translate(-command.transform.origin);
auto matrix = to_skia_matrix(new_transform);
if (!command.filter.is_none()) {
sk_sp<SkImageFilter> image_filter;
auto append_filter = [&image_filter](auto new_filter) {
if (image_filter)
image_filter = SkImageFilters::Compose(new_filter, image_filter);
else
image_filter = new_filter;
};
// Apply filters in order
for (auto const& filter_function : command.filter.filters)
append_filter(to_skia_image_filter(filter_function));
// We apply opacity as a color filter here so we only need to save and restore a single layer.
if (command.opacity < 1) {
append_filter(to_skia_image_filter(CSS::ResolvedFilter::FilterFunction {
CSS::ResolvedFilter::Color {
CSS::FilterOperation::Color::Type::Opacity,
command.opacity,
},
}));
}
SkPaint paint;
paint.setImageFilter(image_filter);
canvas.saveLayer(nullptr, &paint);
} else if (command.opacity < 1) {
if (command.opacity < 1) {
auto source_paintable_rect = to_skia_rect(command.source_paintable_rect);
SkRect dest;
matrix.mapRect(&dest, source_paintable_rect);
@ -1105,6 +1079,41 @@ void DisplayListPlayerSkia::apply_opacity(ApplyOpacity const& command)
canvas.saveLayer(nullptr, &paint);
}
void DisplayListPlayerSkia::apply_filters(ApplyFilters const& command)
{
if (command.filter.is_none()) {
return;
}
sk_sp<SkImageFilter> image_filter;
auto append_filter = [&image_filter](auto new_filter) {
if (image_filter)
image_filter = SkImageFilters::Compose(new_filter, image_filter);
else
image_filter = new_filter;
};
// Apply filters in order
for (auto filter : command.filter.filters) {
append_filter(to_skia_image_filter(filter));
}
// We apply opacity as a color filter here so we only need to save and restore a single layer.
if (command.opacity < 1) {
append_filter(to_skia_image_filter(CSS::ResolvedFilter::FilterFunction {
CSS::ResolvedFilter::Color {
CSS::FilterOperation::Color::Type::Opacity,
command.opacity,
},
}));
}
SkPaint paint;
paint.setImageFilter(image_filter);
auto& canvas = surface().canvas();
canvas.saveLayer(nullptr, &paint);
return;
}
void DisplayListPlayerSkia::apply_transform(ApplyTransform const& command)
{
auto affine_transform = Gfx::extract_2d_affine_transform(command.matrix);

View file

@ -63,6 +63,7 @@ private:
void paint_scrollbar(PaintScrollBar const&) override;
void paint_nested_display_list(PaintNestedDisplayList const&) override;
void apply_opacity(ApplyOpacity const&) override;
void apply_filters(ApplyFilters const&) override;
void apply_transform(ApplyTransform const&) override;
void apply_mask_bitmap(ApplyMaskBitmap const&) override;

View file

@ -295,7 +295,6 @@ void DisplayListRecorder::push_stacking_context(PushStackingContextParams params
{
append(PushStackingContext {
.opacity = params.opacity,
.filter = params.filter,
.source_paintable_rect = params.source_paintable_rect,
.transform = {
.origin = params.transform.origin,
@ -408,6 +407,11 @@ void DisplayListRecorder::apply_opacity(float opacity)
append(ApplyOpacity { .opacity = opacity });
}
void DisplayListRecorder::apply_filters(float opacity, CSS::ResolvedFilter filter)
{
append(ApplyFilters { .opacity = opacity, .filter = filter });
}
void DisplayListRecorder::apply_transform(Gfx::FloatPoint origin, Gfx::FloatMatrix4x4 matrix)
{
append(ApplyTransform {

View file

@ -121,7 +121,6 @@ public:
struct PushStackingContextParams {
float opacity;
CSS::ResolvedFilter filter;
bool is_fixed_position;
Gfx::IntRect source_paintable_rect;
StackingContextTransform transform;
@ -150,6 +149,7 @@ public:
void paint_scrollbar(int scroll_frame_id, Gfx::IntRect, CSSPixelFraction scroll_size, bool vertical);
void apply_opacity(float opacity);
void apply_filters(float opacity, CSS::ResolvedFilter filter);
void apply_transform(Gfx::FloatPoint origin, Gfx::FloatMatrix4x4);
void apply_mask_bitmap(Gfx::IntPoint origin, Gfx::ImmutableBitmap const&, Gfx::Bitmap::MaskKind);

View file

@ -301,7 +301,6 @@ void StackingContext::paint(PaintContext& context) const
DisplayListRecorder::PushStackingContextParams push_stacking_context_params {
.opacity = opacity,
.filter = paintable_box().computed_values().filter(),
.is_fixed_position = paintable_box().is_fixed_position(),
.source_paintable_rect = source_paintable_rect,
.transform = {
@ -328,6 +327,7 @@ void StackingContext::paint(PaintContext& context) const
context.display_list_recorder().push_scroll_frame_id(*paintable_box().scroll_frame_id());
}
context.display_list_recorder().push_stacking_context(push_stacking_context_params);
context.display_list_recorder().apply_filters(opacity, paintable_box().computed_values().filter());
if (auto mask_image = computed_values.mask_image()) {
auto mask_display_list = DisplayList::create();