2023-10-15 04:27:48 +02:00
|
|
|
/*
|
2025-07-06 18:07:43 +02:00
|
|
|
* Copyright (c) 2023-2025, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
2023-10-15 04:27:48 +02:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <AK/Forward.h>
|
|
|
|
#include <AK/Vector.h>
|
|
|
|
#include <LibGfx/Color.h>
|
|
|
|
#include <LibGfx/Forward.h>
|
2023-11-24 14:45:45 +01:00
|
|
|
#include <LibGfx/ImmutableBitmap.h>
|
2025-07-10 19:24:30 +02:00
|
|
|
#include <LibGfx/LineStyle.h>
|
2023-10-15 04:27:48 +02:00
|
|
|
#include <LibGfx/PaintStyle.h>
|
|
|
|
#include <LibGfx/Palette.h>
|
2024-08-09 14:00:10 +02:00
|
|
|
#include <LibGfx/Path.h>
|
2023-10-15 04:27:48 +02:00
|
|
|
#include <LibGfx/Point.h>
|
|
|
|
#include <LibGfx/Rect.h>
|
2024-06-05 10:10:38 +02:00
|
|
|
#include <LibGfx/ScalingMode.h>
|
2025-07-10 19:24:30 +02:00
|
|
|
#include <LibWeb/Forward.h>
|
2023-10-15 04:27:48 +02:00
|
|
|
#include <LibWeb/Painting/BorderRadiiData.h>
|
|
|
|
#include <LibWeb/Painting/BorderRadiusCornerClipper.h>
|
2025-07-13 03:55:24 +02:00
|
|
|
#include <LibWeb/Painting/ClipFrame.h>
|
2023-10-15 04:27:48 +02:00
|
|
|
#include <LibWeb/Painting/GradientData.h>
|
2024-06-07 18:06:25 +03:00
|
|
|
#include <LibWeb/Painting/PaintBoxShadowParams.h>
|
2025-08-02 21:16:51 +02:00
|
|
|
#include <LibWeb/Painting/PaintStyle.h>
|
2025-08-18 16:21:09 +01:00
|
|
|
#include <LibWeb/Painting/ShouldAntiAlias.h>
|
2023-10-15 04:27:48 +02:00
|
|
|
|
|
|
|
namespace Web::Painting {
|
|
|
|
|
2025-07-10 19:24:30 +02:00
|
|
|
struct StackingContextTransform {
|
|
|
|
Gfx::FloatPoint origin;
|
|
|
|
Gfx::FloatMatrix4x4 matrix;
|
|
|
|
};
|
|
|
|
|
2024-06-23 18:40:10 +02:00
|
|
|
class DisplayListRecorder {
|
|
|
|
AK_MAKE_NONCOPYABLE(DisplayListRecorder);
|
|
|
|
AK_MAKE_NONMOVABLE(DisplayListRecorder);
|
2024-02-14 16:36:42 +01:00
|
|
|
|
2023-10-15 04:27:48 +02:00
|
|
|
public:
|
2024-08-06 15:26:47 +03:00
|
|
|
void fill_rect(Gfx::IntRect const& rect, Color color);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2025-08-02 21:16:51 +02:00
|
|
|
struct FillPathParams {
|
2024-08-09 14:00:10 +02:00
|
|
|
Gfx::Path path;
|
2025-08-02 21:16:51 +02:00
|
|
|
float opacity = 1.0f;
|
|
|
|
PaintStyleOrColor paint_style_or_color;
|
2024-06-05 10:21:28 +02:00
|
|
|
Gfx::WindingRule winding_rule = Gfx::WindingRule::EvenOdd;
|
2025-08-18 16:21:09 +01:00
|
|
|
ShouldAntiAlias should_anti_alias { ShouldAntiAlias::Yes };
|
2023-10-15 04:27:48 +02:00
|
|
|
};
|
2025-08-02 21:16:51 +02:00
|
|
|
void fill_path(FillPathParams params);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2025-08-02 20:04:12 +02:00
|
|
|
struct StrokePathParams {
|
2024-11-21 15:09:31 -05:00
|
|
|
Gfx::Path::CapStyle cap_style;
|
|
|
|
Gfx::Path::JoinStyle join_style;
|
|
|
|
float miter_limit;
|
|
|
|
Vector<float> dash_array;
|
|
|
|
float dash_offset;
|
2024-08-09 14:00:10 +02:00
|
|
|
Gfx::Path path;
|
2025-08-02 20:04:12 +02:00
|
|
|
float opacity = 1.0f;
|
|
|
|
PaintStyleOrColor paint_style_or_color;
|
2023-10-15 04:27:48 +02:00
|
|
|
float thickness;
|
2025-08-18 16:21:09 +01:00
|
|
|
ShouldAntiAlias should_anti_alias { ShouldAntiAlias::Yes };
|
2023-10-15 04:27:48 +02:00
|
|
|
};
|
2025-08-02 20:04:12 +02:00
|
|
|
void stroke_path(StrokePathParams);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
|
|
|
void draw_ellipse(Gfx::IntRect const& a_rect, Color color, int thickness);
|
|
|
|
|
2024-04-20 10:20:01 +02:00
|
|
|
void fill_ellipse(Gfx::IntRect const& a_rect, Color color);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2024-08-06 15:26:47 +03:00
|
|
|
void fill_rect_with_linear_gradient(Gfx::IntRect const& gradient_rect, LinearGradientData const& data);
|
|
|
|
void fill_rect_with_conic_gradient(Gfx::IntRect const& rect, ConicGradientData const& data, Gfx::IntPoint const& position);
|
|
|
|
void fill_rect_with_radial_gradient(Gfx::IntRect const& rect, RadialGradientData const& data, Gfx::IntPoint center, Gfx::IntSize size);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
|
|
|
void draw_rect(Gfx::IntRect const& rect, Color color, bool rough = false);
|
|
|
|
|
2024-09-25 15:44:58 +02:00
|
|
|
void draw_painting_surface(Gfx::IntRect const& dst_rect, NonnullRefPtr<Gfx::PaintingSurface>, Gfx::IntRect const& src_rect, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
|
2025-02-04 21:51:51 +01:00
|
|
|
void draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::IntRect const& clip_rect, Gfx::ImmutableBitmap const& bitmap, Gfx::ScalingMode scaling_mode = Gfx::ScalingMode::NearestNeighbor);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2025-07-10 19:24:30 +02:00
|
|
|
void draw_repeated_immutable_bitmap(Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, NonnullRefPtr<Gfx::ImmutableBitmap const> bitmap, Gfx::ScalingMode scaling_mode, bool repeat_x, bool repeat_y);
|
2024-07-23 15:36:28 +03:00
|
|
|
|
2024-06-05 10:25:10 +02:00
|
|
|
void draw_line(Gfx::IntPoint from, Gfx::IntPoint to, Color color, int thickness = 1, Gfx::LineStyle style = Gfx::LineStyle::Solid, Color alternate_color = Color::Transparent);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2024-06-21 07:50:48 +02:00
|
|
|
void draw_text(Gfx::IntRect const&, String, Gfx::Font const&, Gfx::TextAlignment, Color);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
|
|
|
// Streamlined text drawing routine that does no wrapping/elision/alignment.
|
2025-07-26 16:31:22 +02:00
|
|
|
void draw_glyph_run(Gfx::FloatPoint baseline_start, Gfx::GlyphRun const& glyph_run, Color color, Gfx::IntRect const& rect, double scale, Gfx::Orientation);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
|
|
|
void add_clip_rect(Gfx::IntRect const& rect);
|
|
|
|
|
|
|
|
void translate(Gfx::IntPoint delta);
|
|
|
|
|
2024-10-11 15:18:39 +02:00
|
|
|
void push_scroll_frame_id(Optional<i32> id);
|
|
|
|
void pop_scroll_frame_id();
|
2024-08-10 14:24:25 +02:00
|
|
|
|
2025-07-13 03:55:24 +02:00
|
|
|
void push_clip_frame(RefPtr<ClipFrame const>);
|
|
|
|
void pop_clip_frame();
|
|
|
|
|
2023-10-15 04:27:48 +02:00
|
|
|
void save();
|
2025-03-29 23:12:11 +01:00
|
|
|
void save_layer();
|
2023-10-15 04:27:48 +02:00
|
|
|
void restore();
|
|
|
|
|
|
|
|
struct PushStackingContextParams {
|
|
|
|
float opacity;
|
2025-01-22 09:50:49 +01:00
|
|
|
Gfx::CompositingAndBlendingOperator compositing_and_blending_operator;
|
|
|
|
bool isolate;
|
LibWeb: Don't encode painting limitations in RecordingPainter API
The current set of stacking context commands do not encode the
information needed to correctly paint the stacking context, instead,
they're based on the limitations of the current CPU renderer.
Stacking contexts should be able to be transformed by an arbitrary
3D transformation matrix, not just scaled from a source to a destination
rect. The `_with_mask()` stacking context also should not be separate
from the regular stacking context.
```c++
push_stacking_context(
bool semitransparent_or_has_non_identity_transform,
float opacity, Gfx::FloatRect const& source_rect,
Gfx::FloatRect const& transformed_destination_rect,
Gfx::IntPoint const& painter_location);
pop_stacking_context(
bool semitransparent_or_has_non_identity_transform,
Gfx::Painter::ScalingMode scaling_mode);
push_stacking_context_with_mask(
Gfx::IntRect const& paint_rect);
pop_stacking_context_with_mask(
Gfx::IntRect const& paint_rect,
RefPtr<Gfx::Bitmap> const& mask_bitmap,
Gfx::Bitmap::MaskKind mask_kind, float opacity);
```
This patch replaces this APIs with just:
```c++
push_stacking_context(
float opacity,
bool is_fixed_position,
Gfx::IntRect const& source_paintable_rect,
Gfx::IntPoint post_transform_translation,
CSS::ImageRendering image_rendering,
StackingContextTransform transform,
Optional<StackingContextMask> mask);
pop_stacking_context()
```
And moves the implementation details into the executor, this should
allow future backends to implement stacking contexts without these
limitations.
2023-11-18 14:23:59 +00:00
|
|
|
StackingContextTransform transform;
|
2024-08-20 17:27:08 +02:00
|
|
|
Optional<Gfx::Path> clip_path = {};
|
2023-10-15 04:27:48 +02:00
|
|
|
};
|
|
|
|
void push_stacking_context(PushStackingContextParams params);
|
LibWeb: Don't encode painting limitations in RecordingPainter API
The current set of stacking context commands do not encode the
information needed to correctly paint the stacking context, instead,
they're based on the limitations of the current CPU renderer.
Stacking contexts should be able to be transformed by an arbitrary
3D transformation matrix, not just scaled from a source to a destination
rect. The `_with_mask()` stacking context also should not be separate
from the regular stacking context.
```c++
push_stacking_context(
bool semitransparent_or_has_non_identity_transform,
float opacity, Gfx::FloatRect const& source_rect,
Gfx::FloatRect const& transformed_destination_rect,
Gfx::IntPoint const& painter_location);
pop_stacking_context(
bool semitransparent_or_has_non_identity_transform,
Gfx::Painter::ScalingMode scaling_mode);
push_stacking_context_with_mask(
Gfx::IntRect const& paint_rect);
pop_stacking_context_with_mask(
Gfx::IntRect const& paint_rect,
RefPtr<Gfx::Bitmap> const& mask_bitmap,
Gfx::Bitmap::MaskKind mask_kind, float opacity);
```
This patch replaces this APIs with just:
```c++
push_stacking_context(
float opacity,
bool is_fixed_position,
Gfx::IntRect const& source_paintable_rect,
Gfx::IntPoint post_transform_translation,
CSS::ImageRendering image_rendering,
StackingContextTransform transform,
Optional<StackingContextMask> mask);
pop_stacking_context()
```
And moves the implementation details into the executor, this should
allow future backends to implement stacking contexts without these
limitations.
2023-11-18 14:23:59 +00:00
|
|
|
void pop_stacking_context();
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2025-07-25 01:39:31 +02:00
|
|
|
void paint_nested_display_list(RefPtr<DisplayList> display_list, Gfx::IntRect rect);
|
2024-08-08 14:17:54 +03:00
|
|
|
|
2024-07-29 14:13:34 +03:00
|
|
|
void add_rounded_rect_clip(CornerRadii corner_radii, Gfx::IntRect border_rect, CornerClip corner_clip);
|
2024-08-06 15:26:47 +03:00
|
|
|
void add_mask(RefPtr<DisplayList> display_list, Gfx::IntRect rect);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2025-05-11 12:44:54 +02:00
|
|
|
void apply_backdrop_filter(Gfx::IntRect const& backdrop_region, BorderRadiiData const& border_radii_data, Gfx::Filter const& backdrop_filter);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2025-08-01 12:07:17 +02:00
|
|
|
void paint_outer_box_shadow(PaintBoxShadowParams params);
|
|
|
|
void paint_inner_box_shadow(PaintBoxShadowParams params);
|
2024-12-09 10:24:26 +01:00
|
|
|
void paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Gfx::GlyphRun const&, double glyph_run_scale, Color color, Gfx::FloatPoint draw_location);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2024-11-25 17:30:31 +04:00
|
|
|
void fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, CornerRadius top_left_radius, CornerRadius top_right_radius, CornerRadius bottom_right_radius, CornerRadius bottom_left_radius);
|
2024-08-06 15:26:47 +03:00
|
|
|
void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius);
|
|
|
|
void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int top_left_radius, int top_right_radius, int bottom_right_radius, int bottom_left_radius);
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2025-05-26 22:36:12 +01:00
|
|
|
void paint_scrollbar(int scroll_frame_id, Gfx::IntRect gutter_rect, Gfx::IntRect thumb_rect, CSSPixelFraction scroll_size, Color thumb_color, Color track_color, bool vertical);
|
2024-08-17 18:56:56 +02:00
|
|
|
|
2024-10-09 02:57:57 +02:00
|
|
|
void apply_opacity(float opacity);
|
2025-01-22 09:50:49 +01:00
|
|
|
void apply_compositing_and_blending_operator(Gfx::CompositingAndBlendingOperator compositing_and_blending_operator);
|
2025-05-11 12:44:54 +02:00
|
|
|
void apply_filter(Gfx::Filter filter);
|
2024-10-09 02:57:57 +02:00
|
|
|
void apply_transform(Gfx::FloatPoint origin, Gfx::FloatMatrix4x4);
|
2024-11-10 01:50:09 +01:00
|
|
|
void apply_mask_bitmap(Gfx::IntPoint origin, Gfx::ImmutableBitmap const&, Gfx::Bitmap::MaskKind);
|
2024-10-09 02:57:57 +02:00
|
|
|
|
2024-06-23 18:40:10 +02:00
|
|
|
DisplayListRecorder(DisplayList&);
|
|
|
|
~DisplayListRecorder();
|
2023-10-15 04:27:48 +02:00
|
|
|
|
2025-07-06 18:07:43 +02:00
|
|
|
int m_save_nesting_level { 0 };
|
|
|
|
|
2023-12-16 14:06:47 +01:00
|
|
|
private:
|
2024-10-11 15:18:39 +02:00
|
|
|
Vector<Optional<i32>> m_scroll_frame_id_stack;
|
2025-07-13 03:55:24 +02:00
|
|
|
Vector<RefPtr<ClipFrame const>> m_clip_frame_stack;
|
2025-08-01 04:24:09 +02:00
|
|
|
DisplayList& m_display_list;
|
2023-10-15 04:27:48 +02:00
|
|
|
};
|
|
|
|
|
2024-06-23 18:40:10 +02:00
|
|
|
class DisplayListRecorderStateSaver {
|
2023-10-15 04:27:48 +02:00
|
|
|
public:
|
2025-08-01 04:59:06 +02:00
|
|
|
explicit DisplayListRecorderStateSaver(DisplayListRecorder& recorder)
|
|
|
|
: m_recorder(recorder)
|
2023-10-15 04:27:48 +02:00
|
|
|
{
|
2025-08-01 04:59:06 +02:00
|
|
|
m_recorder.save();
|
2023-10-15 04:27:48 +02:00
|
|
|
}
|
|
|
|
|
2024-06-23 18:40:10 +02:00
|
|
|
~DisplayListRecorderStateSaver()
|
2023-10-15 04:27:48 +02:00
|
|
|
{
|
2025-08-01 04:59:06 +02:00
|
|
|
m_recorder.restore();
|
2023-10-15 04:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2025-08-01 04:59:06 +02:00
|
|
|
DisplayListRecorder& m_recorder;
|
2023-10-15 04:27:48 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|