/* * Copyright (c) 2026, 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 namespace Gfx { struct CanvasLinearGradient { FloatPoint start_point; FloatPoint end_point; Vector color_stops; Optional repeat_length; }; struct CanvasRadialGradient { FloatPoint start_center; float start_radius { 0 }; FloatPoint end_center; float end_radius { 0 }; Vector color_stops; Optional repeat_length; }; struct CanvasConicGradient { FloatPoint center; float start_angle { 0 }; Vector color_stops; Optional repeat_length; }; struct CanvasPatternStyle { Optional image; CanvasPatternPaintStyle::Repetition repetition { CanvasPatternPaintStyle::Repetition::Repeat }; Optional transform; }; using CanvasPaintStyle = Variant; inline constexpr i64 max_canvas_area = 16384 * 16384; namespace CanvasCommands { struct ClearRect { FloatRect rect; Color color; }; struct FillRect { FloatRect rect; Color color; }; struct DrawBitmap { DecodedImageFrame frame; FloatRect dst_rect; IntRect src_rect; ScalingMode scaling_mode { ScalingMode::NearestNeighbor }; Optional filter; float global_alpha { 1 }; CompositingAndBlendingOperator compositing_and_blending_operator { CompositingAndBlendingOperator::SourceOver }; }; struct DrawCanvas { u64 source_canvas_id { 0 }; FloatRect dst_rect; IntRect src_rect; ScalingMode scaling_mode { ScalingMode::NearestNeighbor }; Optional filter; float global_alpha { 1 }; CompositingAndBlendingOperator compositing_and_blending_operator { CompositingAndBlendingOperator::SourceOver }; }; struct FillPath { Path path; CanvasPaintStyle style; WindingRule winding_rule { WindingRule::Nonzero }; float blur_radius { 0 }; Optional filter; float global_alpha { 1 }; CompositingAndBlendingOperator compositing_and_blending_operator { CompositingAndBlendingOperator::SourceOver }; }; struct StrokePath { Path path; CanvasPaintStyle style; float thickness { 1 }; Path::CapStyle cap_style { Path::CapStyle::Butt }; Path::JoinStyle join_style { Path::JoinStyle::Miter }; float miter_limit { 10 }; Vector dash_array; float dash_offset { 0 }; float blur_radius { 0 }; Optional filter; float global_alpha { 1 }; CompositingAndBlendingOperator compositing_and_blending_operator { CompositingAndBlendingOperator::SourceOver }; }; struct SetTransform { AffineTransform transform; }; struct Save { }; struct Restore { }; struct ClipPath { Path path; WindingRule winding_rule { WindingRule::Nonzero }; }; struct Reset { }; } using CanvasCommand = Variant< CanvasCommands::ClearRect, CanvasCommands::FillRect, CanvasCommands::DrawBitmap, CanvasCommands::DrawCanvas, CanvasCommands::FillPath, CanvasCommands::StrokePath, CanvasCommands::SetTransform, CanvasCommands::Save, CanvasCommands::Restore, CanvasCommands::ClipPath, CanvasCommands::Reset>; class CanvasCommandList { public: CanvasCommandList() = default; explicit CanvasCommandList(Vector commands) : m_commands(move(commands)) { } void append(CanvasCommand&& command) { m_commands.append(move(command)); } bool is_empty() const { return m_commands.is_empty(); } size_t size() const { return m_commands.size(); } Vector const& commands() const { return m_commands; } private: Vector m_commands; }; CanvasPaintStyle to_canvas_paint_style(PaintStyle const&); } namespace IPC { template<> ErrorOr encode(Encoder&, Gfx::CanvasLinearGradient const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasRadialGradient const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasConicGradient const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasPatternStyle const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::ClearRect const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::FillRect const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::DrawBitmap const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::DrawCanvas const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::FillPath const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::StrokePath const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::SetTransform const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::Save const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::Restore const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::ClipPath const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::Reset const&); template<> ErrorOr decode(Decoder&); template<> ErrorOr encode(Encoder&, Gfx::CanvasCommandList const&); template<> ErrorOr decode(Decoder&); }