/* * Copyright (c) 2022, Sam Atkins * Copyright (c) 2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Web::HTML { // https://html.spec.whatwg.org/multipage/canvas.html#canvasstate class CanvasState { public: virtual ~CanvasState() = default; virtual Gfx::Painter* painter_for_canvas_state() = 0; virtual Gfx::Path& path_for_canvas_state() = 0; void save(); void restore(); void reset(); bool is_context_lost(); using FillOrStrokeVariant = Variant, GC::Root>; struct FillOrStrokeStyle { FillOrStrokeStyle(Gfx::Color color) : m_fill_or_stroke_style(color) { } FillOrStrokeStyle(GC::Root gradient) : m_fill_or_stroke_style(gradient) { } FillOrStrokeStyle(GC::Root pattern) : m_fill_or_stroke_style(pattern) { } NonnullRefPtr to_gfx_paint_style(); Optional as_color() const; Gfx::Color to_color_but_fixme_should_accept_any_paint_style() const; using JsFillOrStrokeStyle = Variant, GC::Root>; JsFillOrStrokeStyle to_js_fill_or_stroke_style() const { return m_fill_or_stroke_style.visit( [&](Gfx::Color color) -> JsFillOrStrokeStyle { return color.to_string(Gfx::Color::HTMLCompatibleSerialization::Yes); }, [&](auto handle) -> JsFillOrStrokeStyle { return handle; }); } private: FillOrStrokeVariant m_fill_or_stroke_style; RefPtr m_color_paint_style { nullptr }; }; // https://html.spec.whatwg.org/multipage/canvas.html#drawing-state struct DrawingState { Gfx::AffineTransform transform; FillOrStrokeStyle fill_style { Gfx::Color::Black }; FillOrStrokeStyle stroke_style { Gfx::Color::Black }; float shadow_offset_x { 0.0f }; float shadow_offset_y { 0.0f }; float shadow_blur { 0.0f }; Gfx::Color shadow_color { Gfx::Color::Transparent }; Vector filters; Optional filters_string; float line_width { 1 }; Bindings::CanvasLineCap line_cap { Bindings::CanvasLineCap::Butt }; Bindings::CanvasLineJoin line_join { Bindings::CanvasLineJoin::Miter }; float miter_limit { 10 }; Vector dash_list; float line_dash_offset { 0 }; bool image_smoothing_enabled { true }; Bindings::ImageSmoothingQuality image_smoothing_quality { Bindings::ImageSmoothingQuality::Low }; float global_alpha = { 1 }; Gfx::CompositingAndBlendingOperator current_compositing_and_blending_operator = Gfx::CompositingAndBlendingOperator::SourceOver; RefPtr font_style_value { nullptr }; RefPtr current_font { nullptr }; Bindings::CanvasTextAlign text_align { Bindings::CanvasTextAlign::Start }; Bindings::CanvasTextBaseline text_baseline { Bindings::CanvasTextBaseline::Alphabetic }; }; DrawingState& drawing_state() { return m_drawing_state; } DrawingState const& drawing_state() const { return m_drawing_state; } void clear_drawing_state_stack() { m_drawing_state_stack.clear(); } void reset_drawing_state() { m_drawing_state = {}; } virtual void reset_to_default_state() = 0; protected: CanvasState() = default; private: DrawingState m_drawing_state; Vector m_drawing_state_stack; // https://html.spec.whatwg.org/multipage/canvas.html#concept-canvas-context-lost bool m_context_lost { false }; }; }