/* * Copyright (c) 2024, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Web::Painting { class DisplayList; struct DrawGlyphRun { NonnullRefPtr glyph_run; double scale { 1 }; Gfx::IntRect rect; Gfx::FloatPoint translation; Color color; Gfx::Orientation orientation { Gfx::Orientation::Horizontal }; void translate_by(Gfx::IntPoint const& offset); }; struct FillRect { Gfx::IntRect rect; Color color; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } }; struct DrawPaintingSurface { Gfx::IntRect dst_rect; NonnullRefPtr surface; Gfx::IntRect src_rect; Gfx::ScalingMode scaling_mode; [[nodiscard]] Gfx::IntRect bounding_rect() const { return dst_rect; } void translate_by(Gfx::IntPoint const& offset) { dst_rect.translate_by(offset); } }; struct DrawScaledImmutableBitmap { Gfx::IntRect dst_rect; Gfx::IntRect clip_rect; NonnullRefPtr bitmap; Gfx::ScalingMode scaling_mode; [[nodiscard]] Gfx::IntRect bounding_rect() const { return clip_rect; } void translate_by(Gfx::IntPoint const& offset) { dst_rect.translate_by(offset); clip_rect.translate_by(offset); } }; struct DrawRepeatedImmutableBitmap { struct Repeat { bool x { false }; bool y { false }; }; Gfx::IntRect dst_rect; Gfx::IntRect clip_rect; NonnullRefPtr bitmap; Gfx::ScalingMode scaling_mode; Repeat repeat; void translate_by(Gfx::IntPoint const& offset) { dst_rect.translate_by(offset); } }; struct Save { }; struct SaveLayer { }; struct Restore { }; struct Translate { Gfx::IntPoint delta; void translate_by(Gfx::IntPoint const& offset) { delta.translate_by(offset); } }; struct AddClipRect { Gfx::IntRect rect; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } bool is_clip_or_mask() const { return true; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } }; struct StackingContextTransform { Gfx::FloatPoint origin; Gfx::FloatMatrix4x4 matrix; }; struct PushStackingContext { float opacity; Gfx::CompositingAndBlendingOperator compositing_and_blending_operator; bool isolate; // 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. StackingContextTransform transform; Optional clip_path = {}; void translate_by(Gfx::IntPoint const& offset) { source_paintable_rect.translate_by(offset); transform.origin.translate_by(offset.to_type()); if (clip_path.has_value()) { clip_path.value().transform(Gfx::AffineTransform().translate(offset.to_type())); } } }; struct PopStackingContext { }; struct PaintLinearGradient { Gfx::IntRect gradient_rect; LinearGradientData linear_gradient_data; [[nodiscard]] Gfx::IntRect bounding_rect() const { return gradient_rect; } void translate_by(Gfx::IntPoint const& offset) { gradient_rect.translate_by(offset); } }; struct PaintOuterBoxShadow { PaintBoxShadowParams box_shadow_params; [[nodiscard]] Gfx::IntRect bounding_rect() const; void translate_by(Gfx::IntPoint const& offset); }; struct PaintInnerBoxShadow { PaintBoxShadowParams box_shadow_params; [[nodiscard]] Gfx::IntRect bounding_rect() const; void translate_by(Gfx::IntPoint const& offset); }; struct PaintTextShadow { NonnullRefPtr glyph_run; double glyph_run_scale { 1 }; Gfx::IntRect shadow_bounding_rect; Gfx::IntRect text_rect; Gfx::FloatPoint draw_location; int blur_radius; Color color; [[nodiscard]] Gfx::IntRect bounding_rect() const { return { draw_location.to_type(), shadow_bounding_rect.size() }; } void translate_by(Gfx::IntPoint const& offset) { draw_location.translate_by(offset.to_type()); } }; struct FillRectWithRoundedCorners { Gfx::IntRect rect; Color color; CornerRadii corner_radii; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } }; struct FillPathUsingColor { Gfx::IntRect path_bounding_rect; Gfx::Path path; Color color; Gfx::WindingRule winding_rule; Gfx::FloatPoint aa_translation; [[nodiscard]] Gfx::IntRect bounding_rect() const { return path_bounding_rect; } void translate_by(Gfx::IntPoint const& offset) { path_bounding_rect.translate_by(offset); aa_translation.translate_by(offset.to_type()); } }; struct FillPathUsingPaintStyle { Gfx::IntRect path_bounding_rect; Gfx::Path path; PaintStyle paint_style; Gfx::WindingRule winding_rule; float opacity; Gfx::FloatPoint aa_translation; [[nodiscard]] Gfx::IntRect bounding_rect() const { return path_bounding_rect; } void translate_by(Gfx::IntPoint const& offset) { path_bounding_rect.translate_by(offset); aa_translation.translate_by(offset.to_type()); } }; struct StrokePathUsingColor { Gfx::Path::CapStyle cap_style; Gfx::Path::JoinStyle join_style; float miter_limit; Vector dash_array; float dash_offset; Gfx::IntRect path_bounding_rect; Gfx::Path path; Color color; float thickness; Gfx::FloatPoint aa_translation; [[nodiscard]] Gfx::IntRect bounding_rect() const { return path_bounding_rect; } void translate_by(Gfx::IntPoint const& offset) { path_bounding_rect.translate_by(offset); aa_translation.translate_by(offset.to_type()); } }; struct StrokePathUsingPaintStyle { Gfx::Path::CapStyle cap_style; Gfx::Path::JoinStyle join_style; float miter_limit; Vector dash_array; float dash_offset; Gfx::IntRect path_bounding_rect; Gfx::Path path; PaintStyle paint_style; float thickness; float opacity = 1.0f; Gfx::FloatPoint aa_translation; [[nodiscard]] Gfx::IntRect bounding_rect() const { return path_bounding_rect; } void translate_by(Gfx::IntPoint const& offset) { path_bounding_rect.translate_by(offset); aa_translation.translate_by(offset.to_type()); } }; struct DrawEllipse { Gfx::IntRect rect; Color color; int thickness; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } }; struct FillEllipse { Gfx::IntRect rect; Color color; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } }; struct DrawLine { Color color; Gfx::IntPoint from; Gfx::IntPoint to; int thickness; Gfx::LineStyle style; Color alternate_color; void translate_by(Gfx::IntPoint const& offset) { from.translate_by(offset); to.translate_by(offset); } }; struct ApplyBackdropFilter { Gfx::IntRect backdrop_region; BorderRadiiData border_radii_data; Optional backdrop_filter; [[nodiscard]] Gfx::IntRect bounding_rect() const { return backdrop_region; } void translate_by(Gfx::IntPoint const& offset) { backdrop_region.translate_by(offset); } }; struct DrawRect { Gfx::IntRect rect; Color color; bool rough; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } }; struct PaintRadialGradient { Gfx::IntRect rect; RadialGradientData radial_gradient_data; Gfx::IntPoint center; Gfx::IntSize size; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } }; struct PaintConicGradient { Gfx::IntRect rect; ConicGradientData conic_gradient_data; Gfx::IntPoint position; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } }; struct DrawTriangleWave { Gfx::IntPoint p1; Gfx::IntPoint p2; Color color; int amplitude; int thickness; void translate_by(Gfx::IntPoint const& offset) { p1.translate_by(offset); p2.translate_by(offset); } }; struct AddRoundedRectClip { CornerRadii corner_radii; Gfx::IntRect border_rect; CornerClip corner_clip; [[nodiscard]] Gfx::IntRect bounding_rect() const { return border_rect; } bool is_clip_or_mask() const { return true; } void translate_by(Gfx::IntPoint const& offset) { border_rect.translate_by(offset); } }; struct AddMask { RefPtr display_list; Gfx::IntRect rect; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } bool is_clip_or_mask() const { return true; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } }; struct PaintNestedDisplayList { RefPtr display_list; ScrollStateSnapshot scroll_state_snapshot; Gfx::IntRect rect; [[nodiscard]] Gfx::IntRect bounding_rect() const { return rect; } void translate_by(Gfx::IntPoint const& offset) { rect.translate_by(offset); } }; struct PaintScrollBar { int scroll_frame_id { 0 }; Gfx::IntRect gutter_rect; Gfx::IntRect thumb_rect; CSSPixelFraction scroll_size; Color thumb_color; Color track_color; bool vertical; void translate_by(Gfx::IntPoint const& offset) { gutter_rect.translate_by(offset); thumb_rect.translate_by(offset); } }; struct ApplyOpacity { float opacity; }; struct ApplyCompositeAndBlendingOperator { Gfx::CompositingAndBlendingOperator compositing_and_blending_operator; }; struct ApplyFilter { Gfx::Filter filter; }; struct ApplyTransform { Gfx::FloatPoint origin; Gfx::FloatMatrix4x4 matrix; void translate_by(Gfx::IntPoint const& offset) { origin.translate_by(offset.to_type()); } }; struct ApplyMaskBitmap { Gfx::IntPoint origin; NonnullRefPtr bitmap; Gfx::Bitmap::MaskKind kind; void translate_by(Gfx::IntPoint const& offset) { origin.translate_by(offset); } }; using Command = Variant< DrawGlyphRun, FillRect, DrawPaintingSurface, DrawScaledImmutableBitmap, DrawRepeatedImmutableBitmap, Save, SaveLayer, Restore, Translate, AddClipRect, PushStackingContext, PopStackingContext, PaintLinearGradient, PaintRadialGradient, PaintConicGradient, PaintOuterBoxShadow, PaintInnerBoxShadow, PaintTextShadow, FillRectWithRoundedCorners, FillPathUsingColor, FillPathUsingPaintStyle, StrokePathUsingColor, StrokePathUsingPaintStyle, DrawEllipse, FillEllipse, DrawLine, ApplyBackdropFilter, DrawRect, DrawTriangleWave, AddRoundedRectClip, AddMask, PaintNestedDisplayList, PaintScrollBar, ApplyOpacity, ApplyCompositeAndBlendingOperator, ApplyFilter, ApplyTransform, ApplyMaskBitmap>; }