/src/serenity/Userland/Libraries/LibWeb/Painting/PaintStyle.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <AK/RefCounted.h> |
10 | | #include <AK/Variant.h> |
11 | | #include <LibGfx/PaintStyle.h> |
12 | | |
13 | | namespace Web::Painting { |
14 | | |
15 | | struct ColorStop { |
16 | | Color color; |
17 | | float position = AK::NaN<float>; |
18 | | Optional<float> transition_hint = {}; |
19 | | }; |
20 | | |
21 | | class SVGGradientPaintStyle : public RefCounted<SVGGradientPaintStyle> { |
22 | | public: |
23 | 0 | virtual NonnullRefPtr<Gfx::SVGGradientPaintStyle> create_gfx_paint_style() const { VERIFY_NOT_REACHED(); } |
24 | | |
25 | | void set_gradient_transform(Gfx::AffineTransform transform); |
26 | | |
27 | | enum class SpreadMethod { |
28 | | Pad, |
29 | | Repeat, |
30 | | Reflect |
31 | | }; |
32 | | |
33 | 0 | void set_spread_method(SpreadMethod spread_method) { m_spread_method = spread_method; } |
34 | | |
35 | 0 | Optional<Gfx::AffineTransform> const& scale_adjusted_inverse_gradient_transform() const { return m_inverse_transform; } |
36 | 0 | float gradient_transform_scale() const { return m_scale; } |
37 | 0 | SpreadMethod spread_method() const { return m_spread_method; } |
38 | | |
39 | | void add_color_stop(float position, Color color, Optional<float> transition_hint = {}) |
40 | 0 | { |
41 | 0 | return add_color_stop(ColorStop { color, position, transition_hint }); |
42 | 0 | } |
43 | | |
44 | | void add_color_stop(ColorStop stop, bool sort = true) |
45 | 0 | { |
46 | 0 | m_color_stops.append(stop); |
47 | 0 | if (sort) |
48 | 0 | quick_sort(m_color_stops, [](auto& a, auto& b) { return a.position < b.position; }); |
49 | 0 | } |
50 | | |
51 | 0 | ReadonlySpan<ColorStop> color_stops() const { return m_color_stops; } |
52 | 0 | Optional<float> repeat_length() const { return m_repeat_length; } |
53 | | |
54 | 0 | virtual ~SVGGradientPaintStyle() = default; |
55 | | |
56 | | protected: |
57 | | Vector<ColorStop, 4> m_color_stops; |
58 | | Optional<float> m_repeat_length; |
59 | | |
60 | | Optional<Gfx::AffineTransform> m_inverse_transform {}; |
61 | | float m_scale { 1.0f }; |
62 | | SpreadMethod m_spread_method { SpreadMethod::Pad }; |
63 | | }; |
64 | | |
65 | | class SVGLinearGradientPaintStyle final : public SVGGradientPaintStyle { |
66 | | public: |
67 | | static NonnullRefPtr<SVGLinearGradientPaintStyle> create(Gfx::FloatPoint start_point, Gfx::FloatPoint end_point) |
68 | 0 | { |
69 | 0 | return adopt_ref(*new SVGLinearGradientPaintStyle(start_point, end_point)); |
70 | 0 | } |
71 | | |
72 | | NonnullRefPtr<Gfx::SVGGradientPaintStyle> create_gfx_paint_style() const override; |
73 | | |
74 | 0 | void set_start_point(Gfx::FloatPoint start_point) { m_start_point = start_point; } |
75 | 0 | void set_end_point(Gfx::FloatPoint end_point) { m_end_point = end_point; } |
76 | | |
77 | | private: |
78 | | SVGLinearGradientPaintStyle(Gfx::FloatPoint start_point, Gfx::FloatPoint end_point) |
79 | 0 | : m_start_point(start_point) |
80 | 0 | , m_end_point(end_point) |
81 | 0 | { |
82 | 0 | } |
83 | | |
84 | | Gfx::FloatPoint m_start_point; |
85 | | Gfx::FloatPoint m_end_point; |
86 | | }; |
87 | | |
88 | | class SVGRadialGradientPaintStyle final : public SVGGradientPaintStyle { |
89 | | public: |
90 | | static NonnullRefPtr<SVGRadialGradientPaintStyle> create(Gfx::FloatPoint start_center, float start_radius, Gfx::FloatPoint end_center, float end_radius) |
91 | 0 | { |
92 | 0 | return adopt_ref(*new SVGRadialGradientPaintStyle(start_center, start_radius, end_center, end_radius)); |
93 | 0 | } |
94 | | |
95 | | NonnullRefPtr<Gfx::SVGGradientPaintStyle> create_gfx_paint_style() const override; |
96 | | |
97 | 0 | void set_start_center(Gfx::FloatPoint start_center) { m_start_center = start_center; } |
98 | 0 | void set_start_radius(float start_radius) { m_start_radius = start_radius; } |
99 | 0 | void set_end_center(Gfx::FloatPoint end_center) { m_end_center = end_center; } |
100 | 0 | void set_end_radius(float end_radius) { m_end_radius = end_radius; } |
101 | | |
102 | | private: |
103 | | SVGRadialGradientPaintStyle(Gfx::FloatPoint start_center, float start_radius, Gfx::FloatPoint end_center, float end_radius) |
104 | 0 | : m_start_center(start_center) |
105 | 0 | , m_start_radius(start_radius) |
106 | 0 | , m_end_center(end_center) |
107 | 0 | , m_end_radius(end_radius) |
108 | 0 | { |
109 | 0 | } |
110 | | |
111 | | Gfx::FloatPoint m_start_center; |
112 | | float m_start_radius { 0.0f }; |
113 | | Gfx::FloatPoint m_end_center; |
114 | | float m_end_radius { 0.0f }; |
115 | | }; |
116 | | |
117 | | } |