Coverage Report

Created: 2026-02-14 08:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibWeb/HTML/Canvas/CanvasState.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
3
 * Copyright (c) 2023, MacDue <macdue@dueutil.tech>
4
 *
5
 * SPDX-License-Identifier: BSD-2-Clause
6
 */
7
8
#pragma once
9
10
#include <AK/Variant.h>
11
#include <AK/Vector.h>
12
#include <LibGfx/AffineTransform.h>
13
#include <LibGfx/Color.h>
14
#include <LibGfx/Font/Font.h>
15
#include <LibGfx/PaintStyle.h>
16
#include <LibGfx/PathClipper.h>
17
#include <LibWeb/Bindings/CanvasRenderingContext2DPrototype.h>
18
#include <LibWeb/HTML/CanvasGradient.h>
19
#include <LibWeb/HTML/CanvasPattern.h>
20
21
namespace Web::HTML {
22
23
// https://html.spec.whatwg.org/multipage/canvas.html#canvasstate
24
class CanvasState {
25
public:
26
0
    virtual ~CanvasState() = default;
27
28
    void save();
29
    void restore();
30
    void reset();
31
    bool is_context_lost();
32
33
    using FillOrStrokeVariant = Variant<Gfx::Color, JS::Handle<CanvasGradient>, JS::Handle<CanvasPattern>>;
34
35
    struct FillOrStrokeStyle {
36
        FillOrStrokeStyle(Gfx::Color color)
37
0
            : m_fill_or_stroke_style(color)
38
0
        {
39
0
        }
40
41
        FillOrStrokeStyle(JS::Handle<CanvasGradient> gradient)
42
0
            : m_fill_or_stroke_style(gradient)
43
0
        {
44
0
        }
45
46
        FillOrStrokeStyle(JS::Handle<CanvasPattern> pattern)
47
0
            : m_fill_or_stroke_style(pattern)
48
0
        {
49
0
        }
50
51
        NonnullRefPtr<Gfx::PaintStyle> to_gfx_paint_style();
52
53
        Optional<Gfx::Color> as_color() const;
54
        Gfx::Color to_color_but_fixme_should_accept_any_paint_style() const;
55
56
        using JsFillOrStrokeStyle = Variant<String, JS::Handle<CanvasGradient>, JS::Handle<CanvasPattern>>;
57
58
        JsFillOrStrokeStyle to_js_fill_or_stroke_style() const
59
0
        {
60
0
            return m_fill_or_stroke_style.visit(
61
0
                [&](Gfx::Color color) -> JsFillOrStrokeStyle {
62
0
                    return color.to_string(Gfx::Color::HTMLCompatibleSerialization::Yes);
63
0
                },
64
0
                [&](auto handle) -> JsFillOrStrokeStyle {
65
0
                    return handle;
66
0
                });
Unexecuted instantiation: AK::Variant<AK::String, JS::Handle<Web::HTML::CanvasGradient>, JS::Handle<Web::HTML::CanvasPattern> > Web::HTML::CanvasState::FillOrStrokeStyle::to_js_fill_or_stroke_style() const::{lambda(auto:1)#1}::operator()<JS::Handle<Web::HTML::CanvasPattern> >(JS::Handle<Web::HTML::CanvasPattern>) const
Unexecuted instantiation: AK::Variant<AK::String, JS::Handle<Web::HTML::CanvasGradient>, JS::Handle<Web::HTML::CanvasPattern> > Web::HTML::CanvasState::FillOrStrokeStyle::to_js_fill_or_stroke_style() const::{lambda(auto:1)#1}::operator()<JS::Handle<Web::HTML::CanvasGradient> >(JS::Handle<Web::HTML::CanvasGradient>) const
67
0
        }
68
69
    private:
70
        FillOrStrokeVariant m_fill_or_stroke_style;
71
        RefPtr<Gfx::PaintStyle> m_color_paint_style { nullptr };
72
    };
73
74
    // https://html.spec.whatwg.org/multipage/canvas.html#drawing-state
75
    struct DrawingState {
76
        Gfx::AffineTransform transform;
77
        FillOrStrokeStyle fill_style { Gfx::Color::Black };
78
        FillOrStrokeStyle stroke_style { Gfx::Color::Black };
79
        float line_width { 1 };
80
        Bindings::CanvasLineCap line_cap { Bindings::CanvasLineCap::Butt };
81
        Bindings::CanvasLineJoin line_join { Bindings::CanvasLineJoin::Miter };
82
        float miter_limit { 10 };
83
        Vector<double> dash_list;
84
        float line_dash_offset { 0 };
85
        bool image_smoothing_enabled { true };
86
        Bindings::ImageSmoothingQuality image_smoothing_quality { Bindings::ImageSmoothingQuality::Low };
87
        float global_alpha = { 1 };
88
        Optional<Gfx::ClipPath> clip;
89
        RefPtr<CSS::CSSStyleValue> font_style_value { nullptr };
90
        RefPtr<Gfx::Font const> current_font { nullptr };
91
        Bindings::CanvasTextAlign text_align { Bindings::CanvasTextAlign::Start };
92
        Bindings::CanvasTextBaseline text_baseline { Bindings::CanvasTextBaseline::Alphabetic };
93
    };
94
0
    DrawingState& drawing_state() { return m_drawing_state; }
95
0
    DrawingState const& drawing_state() const { return m_drawing_state; }
96
97
0
    void clear_drawing_state_stack() { m_drawing_state_stack.clear(); }
98
0
    void reset_drawing_state() { m_drawing_state = {}; }
99
100
    virtual void reset_to_default_state() = 0;
101
102
protected:
103
0
    CanvasState() = default;
104
105
private:
106
    DrawingState m_drawing_state;
107
    Vector<DrawingState> m_drawing_state_stack;
108
109
    // https://html.spec.whatwg.org/multipage/canvas.html#concept-canvas-context-lost
110
    bool m_context_lost { false };
111
};
112
113
}