/src/serenity/Userland/Libraries/LibGfx/Painter.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <AK/Forward.h> |
10 | | #include <AK/Memory.h> |
11 | | #include <AK/NonnullRefPtr.h> |
12 | | #include <AK/Utf8View.h> |
13 | | #include <AK/Vector.h> |
14 | | #include <LibGfx/Color.h> |
15 | | #include <LibGfx/Font/FontDatabase.h> |
16 | | #include <LibGfx/Forward.h> |
17 | | #include <LibGfx/Gradients.h> |
18 | | #include <LibGfx/GrayscaleBitmap.h> |
19 | | #include <LibGfx/LineStyle.h> |
20 | | #include <LibGfx/PaintStyle.h> |
21 | | #include <LibGfx/Point.h> |
22 | | #include <LibGfx/Rect.h> |
23 | | #include <LibGfx/ScalingMode.h> |
24 | | #include <LibGfx/Size.h> |
25 | | #include <LibGfx/TextAlignment.h> |
26 | | #include <LibGfx/TextDirection.h> |
27 | | #include <LibGfx/TextElision.h> |
28 | | #include <LibGfx/TextWrapping.h> |
29 | | #include <LibGfx/WindingRule.h> |
30 | | |
31 | | namespace Gfx { |
32 | | |
33 | | ALWAYS_INLINE static Color color_for_format(BitmapFormat format, ARGB32 value) |
34 | 3.32G | { |
35 | 3.32G | switch (format) { |
36 | 3.32G | case BitmapFormat::BGRA8888: |
37 | 3.32G | return Color::from_argb(value); |
38 | 0 | case BitmapFormat::BGRx8888: |
39 | 0 | return Color::from_rgb(value); |
40 | | // FIXME: Handle other formats |
41 | 0 | default: |
42 | 0 | VERIFY_NOT_REACHED(); |
43 | 3.32G | } |
44 | 3.32G | } Unexecuted instantiation: PNGLoader.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: TinyVGLoader.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: GradientPainting.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) EdgeFlagPathRasterizer.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Line | Count | Source | 34 | 3.32G | { | 35 | 3.32G | switch (format) { | 36 | 3.32G | case BitmapFormat::BGRA8888: | 37 | 3.32G | return Color::from_argb(value); | 38 | 0 | case BitmapFormat::BGRx8888: | 39 | 0 | return Color::from_rgb(value); | 40 | | // FIXME: Handle other formats | 41 | 0 | default: | 42 | 0 | VERIFY_NOT_REACHED(); | 43 | 3.32G | } | 44 | 3.32G | } |
Unexecuted instantiation: AntiAliasingPainter.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: WebPLoader.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: Painter.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: BitmapFont.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: Font.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: Glyf.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: Path.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: VectorGraphic.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: CanvasRenderingContext2D.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: TraversableNavigable.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: BorderRadiusCornerClipper.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: DisplayListPlayerCPU.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: AffineDisplayListPlayerCPU.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: PaintableBox.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: SVGMaskable.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: ShadowPainting.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: SVGDecodedImageData.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) Unexecuted instantiation: PathClipper.cpp:Gfx::color_for_format(Gfx::BitmapFormat, unsigned int) |
45 | | |
46 | | class Painter { |
47 | | public: |
48 | | static constexpr int LINE_SPACING = 4; |
49 | | |
50 | | explicit Painter(Gfx::Bitmap&); |
51 | 2.77k | ~Painter() = default; |
52 | | |
53 | | void clear_rect(IntRect const&, Color); |
54 | | void fill_rect(IntRect const&, Color); |
55 | | void fill_rect(IntRect const&, PaintStyle const&); |
56 | | void fill_rect_with_dither_pattern(IntRect const&, Color, Color); |
57 | | void fill_rect_with_checkerboard(IntRect const&, IntSize, Color color_dark, Color color_light); |
58 | | void fill_rect_with_gradient(Orientation, IntRect const&, Color gradient_start, Color gradient_end); |
59 | | void fill_rect_with_gradient(IntRect const&, Color gradient_start, Color gradient_end); |
60 | | void fill_rect_with_linear_gradient(IntRect const&, ReadonlySpan<ColorStop>, float angle, Optional<float> repeat_length = {}); |
61 | | void fill_rect_with_conic_gradient(IntRect const&, ReadonlySpan<ColorStop>, IntPoint center, float start_angle, Optional<float> repeat_length = {}); |
62 | | void fill_rect_with_radial_gradient(IntRect const&, ReadonlySpan<ColorStop>, IntPoint center, IntSize size, Optional<float> repeat_length = {}, Optional<float> rotation_angle = {}); |
63 | | void fill_rect_with_rounded_corners(IntRect const&, Color, int radius); |
64 | | void fill_rect_with_rounded_corners(IntRect const&, Color, int top_left_radius, int top_right_radius, int bottom_right_radius, int bottom_left_radius); |
65 | | void fill_ellipse(IntRect const&, Color); |
66 | | void draw_rect(IntRect const&, Color, bool rough = false); |
67 | | void draw_rect_with_thickness(IntRect const&, Color, int thickness); |
68 | | void draw_focus_rect(IntRect const&, Color); |
69 | | void draw_bitmap(IntPoint, CharacterBitmap const&, Color = Color()); |
70 | | void draw_bitmap(IntPoint, GlyphBitmap const&, Color = Color()); |
71 | | void draw_scaled_bitmap(IntRect const& dst_rect, Gfx::Bitmap const&, IntRect const& src_rect, float opacity = 1.0f, ScalingMode = ScalingMode::NearestNeighbor); |
72 | | void draw_scaled_bitmap(IntRect const& dst_rect, Gfx::Bitmap const&, FloatRect const& src_rect, float opacity = 1.0f, ScalingMode = ScalingMode::NearestNeighbor); |
73 | | void draw_scaled_bitmap_with_transform(IntRect const& dst_rect, Gfx::Bitmap const&, FloatRect const& src_rect, Gfx::AffineTransform const&, float opacity = 1.0f, ScalingMode = ScalingMode::NearestNeighbor); |
74 | | void draw_triangle(IntPoint, IntPoint, IntPoint, Color); |
75 | | void draw_triangle(IntPoint offset, ReadonlySpan<IntPoint>, Color); |
76 | | void draw_ellipse_intersecting(IntRect const&, Color, int thickness = 1); |
77 | | void set_pixel(IntPoint, Color, bool blend = false); |
78 | 0 | void set_pixel(int x, int y, Color color, bool blend = false) { set_pixel({ x, y }, color, blend); } |
79 | | Optional<Color> get_pixel(IntPoint); |
80 | | ErrorOr<NonnullRefPtr<Bitmap>> get_region_bitmap(IntRect const&, BitmapFormat format, Optional<IntRect&> actual_region = {}); |
81 | | void draw_line(IntPoint, IntPoint, Color, int thickness = 1, LineStyle style = LineStyle::Solid, Color alternate_color = Color::Transparent); |
82 | | void draw_triangle_wave(IntPoint, IntPoint, Color color, int amplitude, int thickness = 1); |
83 | | void draw_quadratic_bezier_curve(IntPoint control_point, IntPoint, IntPoint, Color, int thickness = 1, LineStyle style = LineStyle::Solid); |
84 | | void draw_cubic_bezier_curve(IntPoint control_point_0, IntPoint control_point_1, IntPoint, IntPoint, Color, int thickness = 1, LineStyle style = LineStyle::Solid); |
85 | | void draw_elliptical_arc(IntPoint p1, IntPoint p2, IntPoint center, FloatSize radii, float x_axis_rotation, float theta_1, float theta_delta, Color, int thickness = 1, LineStyle style = LineStyle::Solid); |
86 | | void blit(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, float opacity = 1.0f, bool apply_alpha = true); |
87 | | void blit_dimmed(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect); |
88 | | void blit_brightened(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect); |
89 | | void blit_filtered(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, Function<Color(Color)> const&, bool apply_alpha = true); |
90 | | void draw_tiled_bitmap(IntRect const& dst_rect, Gfx::Bitmap const&); |
91 | | void blit_offset(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, IntPoint); |
92 | | void blit_disabled(IntPoint, Gfx::Bitmap const&, IntRect const&, Palette const&); |
93 | | void blit_tiled(IntRect const&, Gfx::Bitmap const&, IntRect const& src_rect); |
94 | | void draw_text(FloatRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
95 | | void draw_text(FloatRect const&, StringView, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
96 | | void draw_text(FloatRect const&, Utf32View const&, Font const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
97 | | void draw_text(FloatRect const&, Utf32View const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
98 | | void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, FloatRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
99 | | void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, FloatRect const&, Utf8View const&, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
100 | | void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, FloatRect const&, Utf32View const&, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
101 | | void draw_text(IntRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
102 | | void draw_text(IntRect const&, StringView, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
103 | | void draw_text(IntRect const&, Utf32View const&, Font const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
104 | | void draw_text(IntRect const&, Utf32View const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
105 | | void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, IntRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
106 | | void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, IntRect const&, Utf8View const&, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
107 | | void draw_text(Function<void(FloatRect const&, Utf8CodePointIterator&)>, IntRect const&, Utf32View const&, Font const&, TextAlignment = TextAlignment::TopLeft, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap); |
108 | | void draw_ui_text(Gfx::IntRect const&, StringView, Gfx::Font const&, TextAlignment, Gfx::Color); |
109 | | void draw_glyph(IntPoint, u32, Color); |
110 | | void draw_glyph(IntPoint, u32, Font const&, Color); |
111 | | void draw_emoji(IntPoint, Gfx::Bitmap const&, Font const&); |
112 | | void draw_glyph_or_emoji(IntPoint, u32, Font const&, Color); |
113 | | void draw_glyph_or_emoji(IntPoint, Utf8CodePointIterator&, Font const&, Color); |
114 | | void draw_glyph(FloatPoint, u32, Color); |
115 | | void draw_glyph(FloatPoint, u32, Font const&, Color); |
116 | | void draw_glyph_or_emoji(FloatPoint, u32, Font const&, Color); |
117 | | void draw_glyph_or_emoji(FloatPoint, Utf8CodePointIterator&, Font const&, Color); |
118 | | void draw_circle_arc_intersecting(IntRect const&, IntPoint, int radius, Color, int thickness); |
119 | | |
120 | | // Streamlined text drawing routine that does no wrapping/elision/alignment. |
121 | | void draw_text_run(IntPoint baseline_start, Utf8View const&, Font const&, Color); |
122 | | void draw_text_run(FloatPoint baseline_start, Utf8View const&, Font const&, Color); |
123 | | |
124 | | enum class CornerOrientation { |
125 | | TopLeft, |
126 | | TopRight, |
127 | | BottomRight, |
128 | | BottomLeft |
129 | | }; |
130 | | void fill_rounded_corner(IntRect const&, int radius, Color, CornerOrientation); |
131 | | |
132 | | static void for_each_line_segment_on_bezier_curve(FloatPoint control_point, FloatPoint p1, FloatPoint p2, Function<void(FloatPoint, FloatPoint)>&); |
133 | | static void for_each_line_segment_on_bezier_curve(FloatPoint control_point, FloatPoint p1, FloatPoint p2, Function<void(FloatPoint, FloatPoint)>&&); |
134 | | |
135 | | static void for_each_line_segment_on_cubic_bezier_curve(FloatPoint control_point_0, FloatPoint control_point_1, FloatPoint p1, FloatPoint p2, Function<void(FloatPoint, FloatPoint)>&); |
136 | | static void for_each_line_segment_on_cubic_bezier_curve(FloatPoint control_point_0, FloatPoint control_point_1, FloatPoint p1, FloatPoint p2, Function<void(FloatPoint, FloatPoint)>&&); |
137 | | |
138 | | static void for_each_line_segment_on_elliptical_arc(FloatPoint p1, FloatPoint p2, FloatPoint center, FloatSize radii, float x_axis_rotation, float theta_1, float theta_delta, Function<void(FloatPoint, FloatPoint)>&); |
139 | | static void for_each_line_segment_on_elliptical_arc(FloatPoint p1, FloatPoint p2, FloatPoint center, FloatSize radii, float x_axis_rotation, float theta_1, float theta_delta, Function<void(FloatPoint, FloatPoint)>&&); |
140 | | |
141 | | void stroke_path(Path const&, Color, int thickness); |
142 | | |
143 | | void fill_path(Path const&, Color, WindingRule rule = WindingRule::Nonzero); |
144 | | void fill_path(Path const&, PaintStyle const& paint_style, float opacity = 1.0f, WindingRule rule = WindingRule::Nonzero); |
145 | | |
146 | | Font const& font() const |
147 | 0 | { |
148 | 0 | if (!state().font) |
149 | 0 | return FontDatabase::default_font(); |
150 | 0 | return *state().font; |
151 | 0 | } |
152 | 0 | void set_font(Font const& font) { state().font = &font; } |
153 | | |
154 | | enum class DrawOp { |
155 | | Copy, |
156 | | Xor, |
157 | | Invert |
158 | | }; |
159 | 0 | void set_draw_op(DrawOp op) { state().draw_op = op; } |
160 | 0 | DrawOp draw_op() const { return state().draw_op; } |
161 | | |
162 | | void add_clip_rect(IntRect const& rect); |
163 | | void clear_clip_rect(); |
164 | | |
165 | 0 | void translate(int dx, int dy) { translate({ dx, dy }); } |
166 | 0 | void translate(IntPoint delta) { state().translation.translate_by(delta); } |
167 | | |
168 | 906k | IntPoint translation() const { return state().translation; } |
169 | | |
170 | 7.42M | [[nodiscard]] Gfx::Bitmap& target() { return *m_target; } |
171 | | |
172 | 0 | void save() { m_state_stack.append(m_state_stack.last()); } |
173 | | void restore() |
174 | 0 | { |
175 | 0 | VERIFY(m_state_stack.size() > 1); |
176 | 0 | m_state_stack.take_last(); |
177 | 0 | } |
178 | | |
179 | 906k | IntRect clip_rect() const { return state().clip_rect; } |
180 | | |
181 | 907k | int scale() const { return state().scale; } |
182 | | |
183 | | protected: |
184 | | friend GradientLine; |
185 | | friend AntiAliasingPainter; |
186 | | template<unsigned SamplesPerPixel> |
187 | | friend class EdgeFlagPathRasterizer; |
188 | | |
189 | 0 | IntRect to_physical(IntRect const& r) const { return r.translated(translation()) * scale(); } |
190 | 0 | IntPoint to_physical(IntPoint p) const { return p.translated(translation()) * scale(); } |
191 | | void set_physical_pixel_with_draw_op(u32& pixel, Color); |
192 | | void fill_physical_scanline_with_draw_op(int y, int x, int width, Color color); |
193 | | void fill_rect_with_draw_op(IntRect const&, Color); |
194 | | void blit_with_opacity(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, float opacity, bool apply_alpha = true); |
195 | | void draw_physical_pixel(IntPoint, Color, int thickness = 1); |
196 | | void set_physical_pixel(IntPoint, Color color, bool blend); |
197 | | |
198 | | struct State { |
199 | | Font const* font; |
200 | | IntPoint translation; |
201 | | int scale = 1; |
202 | | IntRect clip_rect; |
203 | | DrawOp draw_op; |
204 | | }; |
205 | | |
206 | 11.0k | State& state() { return m_state_stack.last(); } |
207 | 2.72M | State const& state() const { return m_state_stack.last(); } |
208 | | |
209 | | void fill_physical_rect(IntRect const&, Color); |
210 | | |
211 | | IntRect m_clip_origin; |
212 | | NonnullRefPtr<Gfx::Bitmap> m_target; |
213 | | Vector<State, 4> m_state_stack; |
214 | | |
215 | | private: |
216 | | Vector<DirectionalRun> split_text_into_directional_runs(Utf8View const&, TextDirection initial_direction); |
217 | | bool text_contains_bidirectional_text(Utf8View const&, TextDirection); |
218 | | template<typename DrawGlyphFunction> |
219 | | void do_draw_text(FloatRect const&, Utf8View const& text, Font const&, TextAlignment, TextElision, TextWrapping, DrawGlyphFunction); |
220 | | }; |
221 | | |
222 | | class PainterStateSaver { |
223 | | public: |
224 | | explicit PainterStateSaver(Painter&); |
225 | | ~PainterStateSaver(); |
226 | | |
227 | | private: |
228 | | Painter& m_painter; |
229 | | }; |
230 | | |
231 | | ByteString parse_ampersand_string(StringView, Optional<size_t>* underline_offset = nullptr); |
232 | | |
233 | | } |