/* * Copyright (c) 2026, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include namespace Gfx { CanvasPaintStyle to_canvas_paint_style(PaintStyle const& paint_style) { if (auto const* solid_color = as_if(paint_style)) return solid_color->color(); if (auto const* linear_gradient = as_if(paint_style)) { return CanvasLinearGradient { .start_point = linear_gradient->start_point(), .end_point = linear_gradient->end_point(), .color_stops = Vector { linear_gradient->color_stops() }, .repeat_length = linear_gradient->repeat_length(), }; } if (auto const* radial_gradient = as_if(paint_style)) { return CanvasRadialGradient { .start_center = radial_gradient->start_center(), .start_radius = radial_gradient->start_radius(), .end_center = radial_gradient->end_center(), .end_radius = radial_gradient->end_radius(), .color_stops = Vector { radial_gradient->color_stops() }, .repeat_length = radial_gradient->repeat_length(), }; } if (auto const* conic_gradient = as_if(paint_style)) { return CanvasConicGradient { .center = conic_gradient->center(), .start_angle = conic_gradient->start_angle(), .color_stops = Vector { conic_gradient->color_stops() }, .repeat_length = conic_gradient->repeat_length(), }; } if (auto const* pattern = as_if(paint_style)) { return CanvasPatternStyle { .image = pattern->image(), .repetition = pattern->repetition(), .transform = pattern->transform(), }; } VERIFY_NOT_REACHED(); } } namespace IPC { template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasLinearGradient const& gradient) { TRY(encoder.encode(gradient.start_point)); TRY(encoder.encode(gradient.end_point)); TRY(encoder.encode(gradient.color_stops)); TRY(encoder.encode(gradient.repeat_length)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasLinearGradient { .start_point = TRY(decoder.decode()), .end_point = TRY(decoder.decode()), .color_stops = TRY(decoder.decode>()), .repeat_length = TRY(decoder.decode>()), }; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasRadialGradient const& gradient) { TRY(encoder.encode(gradient.start_center)); TRY(encoder.encode(gradient.start_radius)); TRY(encoder.encode(gradient.end_center)); TRY(encoder.encode(gradient.end_radius)); TRY(encoder.encode(gradient.color_stops)); TRY(encoder.encode(gradient.repeat_length)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasRadialGradient { .start_center = TRY(decoder.decode()), .start_radius = TRY(decoder.decode()), .end_center = TRY(decoder.decode()), .end_radius = TRY(decoder.decode()), .color_stops = TRY(decoder.decode>()), .repeat_length = TRY(decoder.decode>()), }; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasConicGradient const& gradient) { TRY(encoder.encode(gradient.center)); TRY(encoder.encode(gradient.start_angle)); TRY(encoder.encode(gradient.color_stops)); TRY(encoder.encode(gradient.repeat_length)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasConicGradient { .center = TRY(decoder.decode()), .start_angle = TRY(decoder.decode()), .color_stops = TRY(decoder.decode>()), .repeat_length = TRY(decoder.decode>()), }; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasPatternStyle const& pattern) { TRY(encoder.encode(pattern.image)); TRY(encoder.encode(pattern.repetition)); TRY(encoder.encode(pattern.transform)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasPatternStyle { .image = TRY(decoder.decode>()), .repetition = TRY(decoder.decode()), .transform = TRY(decoder.decode>()), }; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasCommands::ClearRect const& command) { TRY(encoder.encode(command.rect)); TRY(encoder.encode(command.color)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasCommands::ClearRect { .rect = TRY(decoder.decode()), .color = TRY(decoder.decode()), }; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasCommands::FillRect const& command) { TRY(encoder.encode(command.rect)); TRY(encoder.encode(command.color)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasCommands::FillRect { .rect = TRY(decoder.decode()), .color = TRY(decoder.decode()), }; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasCommands::DrawBitmap const& command) { TRY(encoder.encode(command.frame)); TRY(encoder.encode(command.dst_rect)); TRY(encoder.encode(command.src_rect)); TRY(encoder.encode(command.scaling_mode)); TRY(encoder.encode(command.filter)); TRY(encoder.encode(command.global_alpha)); TRY(encoder.encode(command.compositing_and_blending_operator)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasCommands::DrawBitmap { .frame = TRY(decoder.decode()), .dst_rect = TRY(decoder.decode()), .src_rect = TRY(decoder.decode()), .scaling_mode = TRY(decoder.decode()), .filter = TRY(decoder.decode>()), .global_alpha = TRY(decoder.decode()), .compositing_and_blending_operator = TRY(decoder.decode()), }; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasCommands::DrawCanvas const& command) { TRY(encoder.encode(command.source_canvas_id)); TRY(encoder.encode(command.dst_rect)); TRY(encoder.encode(command.src_rect)); TRY(encoder.encode(command.scaling_mode)); TRY(encoder.encode(command.filter)); TRY(encoder.encode(command.global_alpha)); TRY(encoder.encode(command.compositing_and_blending_operator)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasCommands::DrawCanvas { .source_canvas_id = TRY(decoder.decode()), .dst_rect = TRY(decoder.decode()), .src_rect = TRY(decoder.decode()), .scaling_mode = TRY(decoder.decode()), .filter = TRY(decoder.decode>()), .global_alpha = TRY(decoder.decode()), .compositing_and_blending_operator = TRY(decoder.decode()), }; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasCommands::FillPath const& command) { TRY(encoder.encode(command.path)); TRY(encoder.encode(command.style)); TRY(encoder.encode(command.winding_rule)); TRY(encoder.encode(command.blur_radius)); TRY(encoder.encode(command.filter)); TRY(encoder.encode(command.global_alpha)); TRY(encoder.encode(command.compositing_and_blending_operator)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasCommands::FillPath { .path = TRY(decoder.decode()), .style = TRY(decoder.decode()), .winding_rule = TRY(decoder.decode()), .blur_radius = TRY(decoder.decode()), .filter = TRY(decoder.decode>()), .global_alpha = TRY(decoder.decode()), .compositing_and_blending_operator = TRY(decoder.decode()), }; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasCommands::StrokePath const& command) { TRY(encoder.encode(command.path)); TRY(encoder.encode(command.style)); TRY(encoder.encode(command.thickness)); TRY(encoder.encode(command.cap_style)); TRY(encoder.encode(command.join_style)); TRY(encoder.encode(command.miter_limit)); TRY(encoder.encode(command.dash_array)); TRY(encoder.encode(command.dash_offset)); TRY(encoder.encode(command.blur_radius)); TRY(encoder.encode(command.filter)); TRY(encoder.encode(command.global_alpha)); TRY(encoder.encode(command.compositing_and_blending_operator)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasCommands::StrokePath { .path = TRY(decoder.decode()), .style = TRY(decoder.decode()), .thickness = TRY(decoder.decode()), .cap_style = TRY(decoder.decode()), .join_style = TRY(decoder.decode()), .miter_limit = TRY(decoder.decode()), .dash_array = TRY(decoder.decode>()), .dash_offset = TRY(decoder.decode()), .blur_radius = TRY(decoder.decode()), .filter = TRY(decoder.decode>()), .global_alpha = TRY(decoder.decode()), .compositing_and_blending_operator = TRY(decoder.decode()), }; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasCommands::SetTransform const& command) { TRY(encoder.encode(command.transform)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasCommands::SetTransform { .transform = TRY(decoder.decode()), }; } template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::Save const&) { return {}; } template<> ErrorOr decode(Decoder&) { return Gfx::CanvasCommands::Save {}; } template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::Restore const&) { return {}; } template<> ErrorOr decode(Decoder&) { return Gfx::CanvasCommands::Restore {}; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasCommands::ClipPath const& command) { TRY(encoder.encode(command.path)); TRY(encoder.encode(command.winding_rule)); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasCommands::ClipPath { .path = TRY(decoder.decode()), .winding_rule = TRY(decoder.decode()), }; } template<> ErrorOr encode(Encoder&, Gfx::CanvasCommands::Reset const&) { return {}; } template<> ErrorOr decode(Decoder&) { return Gfx::CanvasCommands::Reset {}; } template<> ErrorOr encode(Encoder& encoder, Gfx::CanvasCommandList const& command_list) { TRY(encoder.encode(command_list.commands())); return {}; } template<> ErrorOr decode(Decoder& decoder) { return Gfx::CanvasCommandList { TRY(decoder.decode>()) }; } }