/src/serenity/Userland/Libraries/LibWeb/HTML/Canvas/CanvasFillStrokeStyles.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org> |
3 | | * Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org> |
4 | | * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> |
5 | | * Copyright (c) 2023, MacDue <macdue@dueutil.tech> |
6 | | * |
7 | | * SPDX-License-Identifier: BSD-2-Clause |
8 | | */ |
9 | | |
10 | | #pragma once |
11 | | |
12 | | #include <AK/String.h> |
13 | | #include <LibWeb/CSS/Parser/Parser.h> |
14 | | #include <LibWeb/HTML/Canvas/CanvasState.h> |
15 | | #include <LibWeb/HTML/CanvasGradient.h> |
16 | | #include <LibWeb/HTML/CanvasPattern.h> |
17 | | |
18 | | namespace Web::HTML { |
19 | | |
20 | | // https://html.spec.whatwg.org/multipage/canvas.html#canvasfillstrokestyles |
21 | | template<typename IncludingClass> |
22 | | class CanvasFillStrokeStyles { |
23 | | public: |
24 | | ~CanvasFillStrokeStyles() = default; |
25 | | using FillOrStrokeStyleVariant = Variant<String, JS::Handle<CanvasGradient>, JS::Handle<CanvasPattern>>; |
26 | | |
27 | | void set_fill_style(FillOrStrokeStyleVariant style) |
28 | 0 | { |
29 | 0 | auto& realm = static_cast<IncludingClass&>(*this).realm(); |
30 | | |
31 | | // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-fillstyle |
32 | 0 | style.visit( |
33 | | // 1. If the given value is a string, then: |
34 | 0 | [&](String const& string) { |
35 | | // 1. Let context be this's canvas attribute's value, if that is an element; otherwise null. |
36 | 0 | auto parser = CSS::Parser::Parser::create(CSS::Parser::ParsingContext(realm), string); |
37 | | |
38 | | // 2. Let parsedValue be the result of parsing the given value with context if non-null. |
39 | | // FIXME: Parse a color value |
40 | | // https://drafts.csswg.org/css-color/#parse-a-css-color-value |
41 | 0 | auto style_value = parser.parse_as_css_value(CSS::PropertyID::Color); |
42 | 0 | if (style_value && style_value->has_color()) { |
43 | 0 | auto parsedValue = style_value->to_color(OptionalNone()); |
44 | | |
45 | | // 4. Set this's fill style to parsedValue. |
46 | 0 | my_drawing_state().fill_style = parsedValue; |
47 | 0 | } else { |
48 | | // 3. If parsedValue is failure, then return. |
49 | 0 | return; |
50 | 0 | } |
51 | | |
52 | | // 5. Return. |
53 | 0 | return; |
54 | 0 | }, |
55 | 0 | [&](auto fill_or_stroke_style) { |
56 | | // FIXME: 2. If the given value is a CanvasPattern object that is marked as not origin-clean, then set this's origin-clean flag to false. |
57 | | |
58 | | // 3. Set this's fill style to the given value. |
59 | 0 | my_drawing_state().fill_style = fill_or_stroke_style; |
60 | 0 | }); Unexecuted instantiation: auto Web::HTML::CanvasFillStrokeStyles<Web::HTML::CanvasRenderingContext2D>::set_fill_style(AK::Variant<AK::String, JS::Handle<Web::HTML::CanvasGradient>, JS::Handle<Web::HTML::CanvasPattern> >)::{lambda(auto:1)#1}::operator()<JS::Handle<Web::HTML::CanvasGradient> >(JS::Handle<Web::HTML::CanvasGradient>) constUnexecuted instantiation: auto Web::HTML::CanvasFillStrokeStyles<Web::HTML::CanvasRenderingContext2D>::set_fill_style(AK::Variant<AK::String, JS::Handle<Web::HTML::CanvasGradient>, JS::Handle<Web::HTML::CanvasPattern> >)::{lambda(auto:1)#1}::operator()<JS::Handle<Web::HTML::CanvasPattern> >(JS::Handle<Web::HTML::CanvasPattern>) const |
61 | 0 | } |
62 | | |
63 | | FillOrStrokeStyleVariant fill_style() const |
64 | 0 | { |
65 | 0 | return my_drawing_state().fill_style.to_js_fill_or_stroke_style(); |
66 | 0 | } |
67 | | |
68 | | void set_stroke_style(FillOrStrokeStyleVariant style) |
69 | 0 | { |
70 | 0 | auto& realm = static_cast<IncludingClass&>(*this).realm(); |
71 | | |
72 | | // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-strokestyle |
73 | |
|
74 | 0 | style.visit( |
75 | | // 1. If the given value is a string, then: |
76 | 0 | [&](String const& string) { |
77 | | // 1. Let context be this's canvas attribute's value, if that is an element; otherwise null. |
78 | 0 | auto parser = CSS::Parser::Parser::create(CSS::Parser::ParsingContext(realm), string); |
79 | | |
80 | | // 2. Let parsedValue be the result of parsing the given value with context if non-null. |
81 | | // FIXME: Parse a color value |
82 | | // https://drafts.csswg.org/css-color/#parse-a-css-color-value |
83 | 0 | auto style_value = parser.parse_as_css_value(CSS::PropertyID::Color); |
84 | 0 | if (style_value && style_value->has_color()) { |
85 | 0 | auto parsedValue = style_value->to_color(OptionalNone()); |
86 | | |
87 | | // 4. Set this's stroke style to parsedValue. |
88 | 0 | my_drawing_state().stroke_style = parsedValue; |
89 | 0 | } else { |
90 | | // 3. If parsedValue is failure, then return. |
91 | 0 | return; |
92 | 0 | } |
93 | | |
94 | | // 5. Return. |
95 | 0 | return; |
96 | 0 | }, |
97 | 0 | [&](auto fill_or_stroke_style) { |
98 | | // FIXME: 2. If the given value is a CanvasPattern object that is marked as not origin-clean, then set this's origin-clean flag to false. |
99 | | |
100 | | // 3. Set this's stroke style to the given value. |
101 | 0 | my_drawing_state().fill_style = fill_or_stroke_style; |
102 | 0 | }); Unexecuted instantiation: auto Web::HTML::CanvasFillStrokeStyles<Web::HTML::CanvasRenderingContext2D>::set_stroke_style(AK::Variant<AK::String, JS::Handle<Web::HTML::CanvasGradient>, JS::Handle<Web::HTML::CanvasPattern> >)::{lambda(auto:1)#1}::operator()<JS::Handle<Web::HTML::CanvasGradient> >(JS::Handle<Web::HTML::CanvasGradient>) constUnexecuted instantiation: auto Web::HTML::CanvasFillStrokeStyles<Web::HTML::CanvasRenderingContext2D>::set_stroke_style(AK::Variant<AK::String, JS::Handle<Web::HTML::CanvasGradient>, JS::Handle<Web::HTML::CanvasPattern> >)::{lambda(auto:1)#1}::operator()<JS::Handle<Web::HTML::CanvasPattern> >(JS::Handle<Web::HTML::CanvasPattern>) const |
103 | 0 | } |
104 | | |
105 | | FillOrStrokeStyleVariant stroke_style() const |
106 | 0 | { |
107 | 0 | return my_drawing_state().stroke_style.to_js_fill_or_stroke_style(); |
108 | 0 | } |
109 | | |
110 | | WebIDL::ExceptionOr<JS::NonnullGCPtr<CanvasGradient>> create_radial_gradient(double x0, double y0, double r0, double x1, double y1, double r1) |
111 | 0 | { |
112 | 0 | auto& realm = static_cast<IncludingClass&>(*this).realm(); |
113 | 0 | return CanvasGradient::create_radial(realm, x0, y0, r0, x1, y1, r1); |
114 | 0 | } |
115 | | |
116 | | JS::NonnullGCPtr<CanvasGradient> create_linear_gradient(double x0, double y0, double x1, double y1) |
117 | 0 | { |
118 | 0 | auto& realm = static_cast<IncludingClass&>(*this).realm(); |
119 | 0 | return CanvasGradient::create_linear(realm, x0, y0, x1, y1).release_value_but_fixme_should_propagate_errors(); |
120 | 0 | } |
121 | | |
122 | | JS::NonnullGCPtr<CanvasGradient> create_conic_gradient(double start_angle, double x, double y) |
123 | 0 | { |
124 | 0 | auto& realm = static_cast<IncludingClass&>(*this).realm(); |
125 | 0 | return CanvasGradient::create_conic(realm, start_angle, x, y).release_value_but_fixme_should_propagate_errors(); |
126 | 0 | } |
127 | | |
128 | | WebIDL::ExceptionOr<JS::GCPtr<CanvasPattern>> create_pattern(CanvasImageSource const& image, StringView repetition) |
129 | 0 | { |
130 | 0 | auto& realm = static_cast<IncludingClass&>(*this).realm(); |
131 | 0 | return CanvasPattern::create(realm, image, repetition); |
132 | 0 | } |
133 | | |
134 | | protected: |
135 | | CanvasFillStrokeStyles() = default; |
136 | | |
137 | | private: |
138 | 0 | CanvasState::DrawingState& my_drawing_state() { return reinterpret_cast<IncludingClass&>(*this).drawing_state(); } |
139 | 0 | CanvasState::DrawingState const& my_drawing_state() const { return reinterpret_cast<IncludingClass const&>(*this).drawing_state(); } |
140 | | }; |
141 | | |
142 | | } |