HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
draw_context.hpp
1// Copyright Take Vos 2020-2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "pipeline_box_vertex.hpp"
8#include "pipeline_image_vertex.hpp"
9#include "pipeline_SDF_vertex.hpp"
10#include "pipeline_alpha_vertex.hpp"
12#include "../geometry/axis_aligned_rectangle.hpp"
13#include "../geometry/matrix.hpp"
14#include "../geometry/corner_radii.hpp"
15#include "../geometry/identity.hpp"
16#include "../geometry/transform.hpp"
17#include "../geometry/circle.hpp"
18#include "../geometry/line_end_cap.hpp"
19#include "../text/text_cursor.hpp"
20#include "../text/text_selection.hpp"
21#include "../text/text_shaper.hpp"
22#include "../color/color.hpp"
23#include "../color/quad_color.hpp"
25#include "../vector_span.hpp"
26
27namespace hi::inline v1 {
28class gfx_device;
29class gfx_device_vulkan;
30class shaped_text;
31class glyph_ids;
32struct paged_image;
33
36enum class border_side {
39 on,
40
43 inside,
44
48};
49
53public:
54 gfx_device_vulkan& device;
55
59
63
67
70 hi::subpixel_orientation subpixel_orientation;
71
75
78 utc_nanoseconds display_time_point;
79
80 draw_context(draw_context const& rhs) noexcept = default;
81 draw_context(draw_context&& rhs) noexcept = default;
82 draw_context& operator=(draw_context const& rhs) noexcept = default;
83 draw_context& operator=(draw_context&& rhs) noexcept = default;
84 ~draw_context() = default;
85
87 gfx_device_vulkan& device,
91 vector_span<pipeline_alpha::vertex>& alpha_vertices) noexcept;
92
95 operator bool() const noexcept
96 {
97 return frame_buffer_index != std::numeric_limits<size_t>::max();
98 }
99
111 widget_layout const& layout,
112 quad const& box,
113 quad_color const& fill_color,
114 quad_color const& border_color,
115 float border_width,
116 hi::border_side border_side,
117 hi::corner_radii const& corner_radius = {}) const noexcept
118 {
119 // clang-format off
120 hilet border_radius = border_width * 0.5f;
121 hilet box_ =
122 border_side == hi::border_side::inside ? box - border_radius :
123 border_side == hi::border_side::outside ? box + border_radius :
124 box;
125 hilet corner_radius_ =
126 border_side == hi::border_side::inside ? corner_radius - border_radius :
127 border_side == hi::border_side::outside ? corner_radius + border_radius :
128 corner_radius;
129 // clang-format on
130
131 return _draw_box(
132 layout.window_clipping_rectangle(),
133 layout.to_window * box_,
134 fill_color,
135 border_color,
136 layout.to_window * border_width,
137 layout.to_window * corner_radius_);
138 }
139
152 widget_layout const& layout,
153 aarectangle const& clipping_rectangle,
154 quad const& box,
155 quad_color const& fill_color,
156 quad_color const& border_color,
157 float border_width,
158 hi::border_side border_side,
159 hi::corner_radii const& corner_radius = {}) const noexcept
160 {
161 // clang-format off
162 hilet border_radius = border_width * 0.5f;
163 hilet box_ =
164 border_side == hi::border_side::inside ? box - border_radius :
165 border_side == hi::border_side::outside ? box + border_radius :
166 box;
167 hilet corner_radius_ =
168 border_side == hi::border_side::inside ? corner_radius - border_radius :
169 border_side == hi::border_side::outside ? corner_radius + border_radius :
170 corner_radius;
171 // clang-format on
172
173 return _draw_box(
174 layout.window_clipping_rectangle(clipping_rectangle),
175 layout.to_window * box_,
176 fill_color,
177 border_color,
178 layout.to_window * border_width,
179 layout.to_window * corner_radius_);
180 }
189 widget_layout const& layout,
190 quad const& box,
191 quad_color const& fill_color,
192 hi::corner_radii const& corner_radius = {}) const noexcept
193 {
194 return _draw_box(
195 layout.window_clipping_rectangle(),
196 layout.to_window * box,
197 fill_color,
198 fill_color,
199 0.0f,
200 layout.to_window * corner_radius);
201 }
202
212 widget_layout const& layout,
213 aarectangle const& clipping_rectangle,
214 quad const& box,
215 quad_color const& fill_color,
216 hi::corner_radii const& corner_radius = {}) const noexcept
217 {
218 return _draw_box(
219 layout.window_clipping_rectangle(clipping_rectangle),
220 layout.to_window * box,
221 fill_color,
222 fill_color,
223 0.0f,
224 layout.to_window * corner_radius);
225 }
226
227 [[nodiscard]] constexpr static rectangle
228 make_rectangle(line_segment const& line, float width, line_end_cap c1, line_end_cap c2) noexcept
229 {
230 auto right = line.direction();
231
232 hilet radius = width * 0.5f;
233 hilet n = normal(right, 0.0f);
234 hilet up = n * width;
235 hilet t = normalize(right);
236
237 auto origin = line.origin() - n * radius;
238
239 // Extend the line by the radius for rounded end-caps.
240 hilet radius_offset = t * radius;
241 if (c1 == line_end_cap::round) {
242 origin -= radius_offset;
243 right += radius_offset;
244 }
245 if (c2 == line_end_cap::round) {
246 right += radius_offset;
247 }
248
249 return rectangle{origin, right, up};
250 }
251
252 [[nodiscard]] constexpr static corner_radii make_corner_radii(float width, line_end_cap c1, line_end_cap c2) noexcept
253 {
254 auto r = f32x4::broadcast(width * 0.5f);
255
256 if (c1 == line_end_cap::flat) {
257 r = zero<0b0101>(r);
258 }
259 if (c2 == line_end_cap::flat) {
260 r = zero<0b1010>(r);
261 }
262
263 return corner_radii{r};
264 }
265
266 void draw_line(
267 widget_layout const& layout,
268 line_segment const& line,
269 float width,
270 quad_color const& fill_color,
271 line_end_cap c1 = line_end_cap::flat,
272 line_end_cap c2 = line_end_cap::flat) const noexcept
273 {
274 hilet line_ = layout.to_window * line;
275 hilet width_ = layout.to_window * width;
276
277 hilet box = make_rectangle(line_, width_, c1, c2);
278 hilet corners = make_corner_radii(width_, c1, c2);
279
280 return _draw_box(layout.window_clipping_rectangle(), box, fill_color, fill_color, 0.0f, corners);
281 }
282
283 void draw_line(
284 widget_layout const& layout,
285 aarectangle const& clipping_rectangle,
286 line_segment const& line,
287 float width,
288 quad_color const& fill_color,
289 line_end_cap c1 = line_end_cap::flat,
290 line_end_cap c2 = line_end_cap::flat) const noexcept
291 {
292 hi_axiom(width != 0.0f);
293 hilet line_ = layout.to_window * line;
294 hilet width_ = layout.to_window * width;
295
296 hilet box = make_rectangle(line_, width_, c1, c2);
297 hilet corners = make_corner_radii(width_, c1, c2);
298
299 return _draw_box(layout.window_clipping_rectangle(clipping_rectangle), box, fill_color, fill_color, 0.0f, corners);
300 }
301
302 [[nodiscard]] constexpr static rectangle make_rectangle(hi::circle const& circle) noexcept
303 {
304 hilet circle_ = f32x4{circle};
305 hilet origin = point3{circle_.xyz1() - circle_.ww00()};
306 hilet right = vector3{circle_.w000() * 2.0f};
307 hilet up = vector3{circle_._0w00() * 2.0f};
308 return rectangle{origin, right, up};
309 }
310
311 [[nodiscard]] constexpr static corner_radii make_corner_radii(hi::circle const& circle) noexcept
312 {
313 return corner_radii{f32x4{circle}.wwww()};
314 }
315
316 void draw_circle(widget_layout const& layout, hi::circle const& circle, quad_color const& fill_color) const noexcept
317 {
318 hilet box = layout.to_window * make_rectangle(circle);
319 hilet corners = layout.to_window * make_corner_radii(circle);
320 return _draw_box(layout.window_clipping_rectangle(), box, fill_color, fill_color, 0.0f, corners);
321 }
322
323 void draw_circle(
324 widget_layout const& layout,
325 aarectangle const clipping_rectangle,
326 hi::circle const& circle,
327 quad_color const& fill_color) const
328 {
329 hilet box = layout.to_window * make_rectangle(circle);
330 hilet corners = layout.to_window * make_corner_radii(circle);
331 return _draw_box(layout.window_clipping_rectangle(clipping_rectangle), box, fill_color, fill_color, 0.0f, corners);
332 }
333
334 void draw_circle(
335 widget_layout const& layout,
336 hi::circle const& circle,
337 quad_color const& fill_color,
338 quad_color const& border_color,
339 float border_width,
340 hi::border_side border_side) const noexcept
341 {
342 // clang-format off
343 hilet circle_ =
344 border_side == hi::border_side::inside ? circle - border_width * 0.5f :
345 border_side == hi::border_side::outside ? circle + border_width * 0.5f :
346 circle;
347 // clang-format on
348
349 hilet box = layout.to_window * make_rectangle(circle_);
350 hilet corners = layout.to_window * make_corner_radii(circle_);
351 return _draw_box(layout.window_clipping_rectangle(), box, fill_color, border_color, border_width, corners);
352 }
353
354 void draw_circle(
355 widget_layout const& layout,
356 aarectangle const& clipping_rectangle,
357 hi::circle const& circle,
358 quad_color const& fill_color,
359 quad_color const& border_color,
360 float border_width,
361 hi::border_side border_side) const noexcept
362 {
363 // clang-format off
364 hilet circle_ =
365 border_side == hi::border_side::inside ? circle - border_width * 0.5f :
366 border_side == hi::border_side::outside ? circle + border_width * 0.5f :
367 circle;
368 // clang-format on
369
370 hilet box = layout.to_window * make_rectangle(circle_);
371 hilet corners = layout.to_window * make_corner_radii(circle_);
372 return _draw_box(
373 layout.window_clipping_rectangle(clipping_rectangle), box, fill_color, border_color, border_width, corners);
374 }
375
384 [[nodiscard]] bool draw_image(widget_layout const& layout, quad const& box, paged_image& image) const noexcept
385 {
386 return _draw_image(layout.window_clipping_rectangle(), layout.to_window * box, image);
387 }
388
398 [[nodiscard]] bool
399 draw_image(widget_layout const& layout, aarectangle const& clipping_rectangle, quad const& box, paged_image& image)
400 const noexcept
401 {
402 return _draw_image(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * box, image);
403 }
404
412 void draw_glyph(widget_layout const& layout, quad const& box, quad_color const& color, glyph_ids const& glyph) const noexcept
413 {
414 return _draw_glyph(layout.window_clipping_rectangle(), layout.to_window * box, color, glyph);
415 }
416
426 widget_layout const& layout,
427 aarectangle clipping_rectangle,
428 quad const& box,
429 quad_color const& color,
430 glyph_ids const& glyph) const noexcept
431 {
432 return _draw_glyph(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * box, color, glyph);
433 }
434
442 void draw_text(widget_layout const& layout, matrix3 const& transform, quad_color const& color, shaped_text const& text)
443 const noexcept
444 {
445 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text, color);
446 }
447
457 widget_layout const& layout,
458 aarectangle const& clipping_rectangle,
459 matrix3 const& transform,
460 quad_color const& color,
461 shaped_text const& text) const noexcept
462 {
463 return _draw_text(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * transform, text, color);
464 }
465
472 void draw_text(widget_layout const& layout, matrix3 const& transform, shaped_text const& text) const noexcept
473 {
474 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text);
475 }
476
484 void draw_text(widget_layout const& layout, matrix3 const& transform, quad_color const& color, text_shaper const& text)
485 const noexcept
486 {
487 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text, color);
488 }
489
496 void draw_text(widget_layout const& layout, quad_color const& color, text_shaper const& text) const noexcept
497 {
498 return _draw_text(layout.window_clipping_rectangle(), layout.to_window, text, color);
499 }
500
510 widget_layout const& layout,
511 aarectangle const& clipping_rectangle,
512 matrix3 const& transform,
513 quad_color const& color,
514 text_shaper const& text) const noexcept
515 {
516 return _draw_text(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * transform, text, color);
517 }
518
527 widget_layout const& layout,
528 aarectangle const& clipping_rectangle,
529 quad_color const& color,
530 text_shaper const& text) const noexcept
531 {
532 return _draw_text(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window, text, color);
533 }
534
541 void draw_text(widget_layout const& layout, matrix3 const& transform, text_shaper const& text) const noexcept
542 {
543 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text);
544 }
545
551 void draw_text(widget_layout const& layout, text_shaper const& text) const noexcept
552 {
553 return _draw_text(layout.window_clipping_rectangle(), layout.to_window, text);
554 }
555
563 void
564 draw_text_selection(widget_layout const& layout, text_shaper const& text, text_selection const& selection, hi::color color)
565 const noexcept
566 {
567 return _draw_text_selection(layout.window_clipping_rectangle(), layout.to_window, text, selection, color);
568 }
569
581 widget_layout const& layout,
582 text_shaper const& text,
583 text_cursor cursor,
584 hi::color primary_color,
585 hi::color secondary_color,
586 bool overwrite_mode,
587 bool dead_character_mode) const noexcept
588 {
589 return _draw_text_cursors(
590 layout.window_clipping_rectangle(),
591 layout.to_window,
592 text,
593 cursor,
594 primary_color,
595 secondary_color,
596 overwrite_mode,
597 dead_character_mode);
598 }
599
608 void make_hole(widget_layout const& layout, quad const& box) const noexcept
609 {
610 return _override_alpha(layout.window_clipping_rectangle(), layout.to_window * box, 0.0f);
611 }
612
613 [[nodiscard]] friend bool overlaps(draw_context const& context, widget_layout const& layout) noexcept
614 {
615 return overlaps(context.scissor_rectangle, layout.window_clipping_rectangle());
616 }
617
618private:
619 vector_span<pipeline_box::vertex> *_box_vertices;
620 vector_span<pipeline_image::vertex> *_image_vertices;
621 vector_span<pipeline_SDF::vertex> *_sdf_vertices;
622 vector_span<pipeline_alpha::vertex> *_alpha_vertices;
623
624 void _override_alpha(aarectangle const& clipping_rectangle, quad box, float alpha) const noexcept;
625
626 void _draw_box(
627 aarectangle const& clipping_rectangle,
628 quad box,
629 quad_color const& fill_color,
630 quad_color const& border_color,
631 float border_width,
632 hi::corner_radii corner_radius) const noexcept;
633
634 void _draw_text(
635 aarectangle const& clipping_rectangle,
636 matrix3 const& transform,
637 shaped_text const& text,
638 std::optional<quad_color> color = {}) const noexcept;
639
640 void _draw_text(
641 aarectangle const& clipping_rectangle,
642 matrix3 const& transform,
643 text_shaper const& text,
644 std::optional<quad_color> color = {}) const noexcept;
645
646 void _draw_text_selection(
647 aarectangle const& clipping_rectangle,
648 matrix3 const& transform,
649 text_shaper const& text,
650 text_selection const& selection,
651 hi::color) const noexcept;
652
653 void _draw_text_insertion_cursor_empty(
654 aarectangle const& clipping_rectangle,
655 matrix3 const& transform,
656 text_shaper const& text,
657 hi::color color) const noexcept;
658
659 void _draw_text_insertion_cursor(
660 aarectangle const& clipping_rectangle,
661 matrix3 const& transform,
662 text_shaper const& text,
663 text_cursor cursor,
664 hi::color color,
665 bool show_flag) const noexcept;
666
667 void _draw_text_overwrite_cursor(
668 aarectangle const& clipping_rectangle,
669 matrix3 const& transform,
670 text_shaper::char_const_iterator it,
671 hi::color color) const noexcept;
672
673 void _draw_text_cursors(
674 aarectangle const& clipping_rectangle,
675 matrix3 const& transform,
676 text_shaper const& text,
677 text_cursor cursor,
678 hi::color primary_color,
679 hi::color secondary_color,
680 bool overwrite_mode,
681 bool dead_character_mode) const noexcept;
682
683 void _draw_glyph(aarectangle const& clipping_rectangle, quad const& box, quad_color const& color, glyph_ids const& glyph)
684 const noexcept;
685
686 [[nodiscard]] bool _draw_image(aarectangle const& clipping_rectangle, quad const& box, paged_image& image) const noexcept;
687};
688
689} // namespace hi::inline v1
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
Defines widget_layout.
DOXYGEN BUG.
Definition algorithm.hpp:15
@ circle
<circle> Encircled form.
border_side
The side where the border is drawn.
Definition draw_context.hpp:36
@ inside
The border is drawn inside the edge of a quad.
@ outside
The border is drawn outside the edge of a quad.
@ on
The border is drawn on the edge of a quad.
This is a RGBA floating point color.
Definition color.hpp:39
Definition quad_color.hpp:12
Class which represents an axis-aligned rectangle.
Definition axis_aligned_rectangle.hpp:20
Definition quad.hpp:17
Draw context for drawing using the HikoGUI shaders.
Definition draw_context.hpp:52
std::size_t frame_buffer_index
The frame buffer index of the image we are currently rendering.
Definition draw_context.hpp:58
void draw_text(widget_layout const &layout, matrix3 const &transform, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:541
void draw_box(widget_layout const &layout, quad const &box, quad_color const &fill_color, hi::corner_radii const &corner_radius={}) const noexcept
Draw a box with rounded corners without a border.
Definition draw_context.hpp:188
float saturation
The tone-mapper's saturation.
Definition draw_context.hpp:74
utc_nanoseconds display_time_point
The time when the drawing will appear on the screen.
Definition draw_context.hpp:78
aarectangle scissor_rectangle
This is the rectangle of the window that is being redrawn.
Definition draw_context.hpp:62
void draw_text(widget_layout const &layout, aarectangle const &clipping_rectangle, matrix3 const &transform, quad_color const &color, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:509
void draw_text(widget_layout const &layout, matrix3 const &transform, shaped_text const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:472
bool draw_image(widget_layout const &layout, aarectangle const &clipping_rectangle, quad const &box, paged_image &image) const noexcept
Draw an image.
Definition draw_context.hpp:399
void draw_text_cursors(widget_layout const &layout, text_shaper const &text, text_cursor cursor, hi::color primary_color, hi::color secondary_color, bool overwrite_mode, bool dead_character_mode) const noexcept
Draw text cursors of shaped text.
Definition draw_context.hpp:580
void draw_text(widget_layout const &layout, quad_color const &color, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:496
void draw_text_selection(widget_layout const &layout, text_shaper const &text, text_selection const &selection, hi::color color) const noexcept
Draw text-selection of shaped text.
Definition draw_context.hpp:564
color background_color
The background color to clear the window with.
Definition draw_context.hpp:66
void draw_glyph(widget_layout const &layout, aarectangle clipping_rectangle, quad const &box, quad_color const &color, glyph_ids const &glyph) const noexcept
Draw a glyph.
Definition draw_context.hpp:425
void draw_text(widget_layout const &layout, matrix3 const &transform, quad_color const &color, shaped_text const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:442
void draw_box(widget_layout const &layout, aarectangle const &clipping_rectangle, quad const &box, quad_color const &fill_color, hi::corner_radii const &corner_radius={}) const noexcept
Draw a box with rounded corners without a border.
Definition draw_context.hpp:211
void make_hole(widget_layout const &layout, quad const &box) const noexcept
Make a hole in the user interface.
Definition draw_context.hpp:608
void draw_glyph(widget_layout const &layout, quad const &box, quad_color const &color, glyph_ids const &glyph) const noexcept
Draw a glyph.
Definition draw_context.hpp:412
void draw_text(widget_layout const &layout, matrix3 const &transform, quad_color const &color, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:484
void draw_box(widget_layout const &layout, quad const &box, quad_color const &fill_color, quad_color const &border_color, float border_width, hi::border_side border_side, hi::corner_radii const &corner_radius={}) const noexcept
Draw a box with rounded corners.
Definition draw_context.hpp:110
void draw_text(widget_layout const &layout, aarectangle const &clipping_rectangle, quad_color const &color, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:526
void draw_text(widget_layout const &layout, aarectangle const &clipping_rectangle, matrix3 const &transform, quad_color const &color, shaped_text const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:456
hi::subpixel_orientation subpixel_orientation
The subpixel orientation for rendering glyphs.
Definition draw_context.hpp:70
void draw_box(widget_layout const &layout, aarectangle const &clipping_rectangle, quad const &box, quad_color const &fill_color, quad_color const &border_color, float border_width, hi::border_side border_side, hi::corner_radii const &corner_radius={}) const noexcept
Draw a box with rounded corners.
Definition draw_context.hpp:151
void draw_text(widget_layout const &layout, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:551
bool draw_image(widget_layout const &layout, quad const &box, paged_image &image) const noexcept
Draw an image.
Definition draw_context.hpp:384
Definition gfx_device_vulkan.hpp:21
This is a image that is uploaded into the texture atlas.
Definition paged_image.hpp:25
A variant of text.
Definition label.hpp:37
A set of glyph-ids of a font which composites into a single glyph.
Definition glyph_ids.hpp:135
A cursor-position in text.
Definition text_cursor.hpp:25
Definition text_selection.hpp:17
Text shaper.
Definition text_shaper.hpp:39
Definition vector_span.hpp:134
T right(T... args)
T max(T... args)