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 "gfx_pipeline_box_vulkan.hpp"
8#include "gfx_pipeline_image_vulkan.hpp"
9#include "gfx_pipeline_SDF_vulkan.hpp"
10#include "gfx_pipeline_alpha_vulkan.hpp"
11#include "../settings/settings.hpp"
12#include "../geometry/module.hpp"
13#include "../unicode/unicode.hpp"
14#include "../text/module.hpp"
15#include "../color/module.hpp"
16#include "../container/module.hpp"
17#include "../utility/utility.hpp"
18#include "../macros.hpp"
19
20namespace hi { inline namespace v1 {
21class gfx_device;
22class widget_layout;
23struct gfx_pipeline_image::paged_image;
24
27enum class border_side {
30 on,
31
34 inside,
35
39};
40
41template<typename Context>
42concept draw_attribute = std::same_as<Context, quad_color> or std::same_as<Context, color> or
43 std::same_as<Context, border_side> or std::same_as<Context, line_end_cap> or std::same_as<Context, corner_radii> or
44 std::same_as<Context, aarectangle> or std::same_as<Context, float> or std::same_as<Context, int>;
45
49 unsigned char num_colors = 0;
50 unsigned char num_line_caps = 0;
51
58
64
67 float line_width = 0.0f;
68
71 hi::border_side border_side = hi::border_side::on;
72
76
83
87
91
92 constexpr draw_attributes(draw_attributes const&) noexcept = default;
97
120 {
121 add(args...);
122 }
123
124 constexpr void add() noexcept {}
125
126 template<draw_attribute T>
127 constexpr void add(T const& attribute) noexcept
128 {
129 if constexpr (std::is_same_v<T, quad_color>) {
130 if (num_colors++ == 0) {
132 } else {
134 }
135 hi_axiom(num_colors <= 2);
136
137 } else if constexpr (std::is_same_v<T, color>) {
138 if (num_colors++ == 0) {
139 fill_color = quad_color{attribute};
140 } else {
141 line_color = quad_color{attribute};
142 }
143 hi_axiom(num_colors <= 2);
144
145 } else if constexpr (std::is_same_v<T, line_end_cap>) {
146 if (num_line_caps++ == 0) {
149 } else {
151 }
152 hi_axiom(num_line_caps <= 2);
153
154 } else if constexpr (std::is_same_v<T, hi::border_side>) {
156#ifndef NDEBUG
157 hi_assert(not _has_border_side);
158 _has_border_side = true;
159#endif
160
161 } else if constexpr (std::is_same_v<T, corner_radii>) {
163#ifndef NDEBUG
164 hi_assert(not _has_corner_radii);
165 _has_corner_radii = true;
166#endif
167
168 } else if constexpr (std::is_same_v<T, aarectangle>) {
170#ifndef NDEBUG
171 hi_assert(not _has_clipping_rectangle);
172 _has_clipping_rectangle = true;
173#endif
174
175 } else if constexpr (std::is_same_v<T, float> or std::is_same_v<T, int>) {
177#ifndef NDEBUG
178 hi_assert(not _has_line_width);
179 _has_line_width = true;
180#endif
181 } else {
182 hi_static_no_default();
183 }
184 }
185
186 template<draw_attribute First, draw_attribute Second, draw_attribute... Rest>
187 constexpr void add(First const& first, Second const& second, Rest const&...rest) noexcept
188 {
189 add(first);
190 add(second, rest...);
191 }
192
193private:
194#ifndef NDEBUG
195 bool _has_border_side = false;
196 bool _has_corner_radii = false;
197 bool _has_clipping_rectangle = false;
198 bool _has_line_width = false;
199#endif
200};
201
202template<typename Context>
203concept draw_quad_shape = std::same_as<Context, quad> or std::same_as<Context, rectangle> or std::same_as<Context, aarectangle> or
204 std::same_as<Context, aarectangle>;
205
209public:
210 gfx_device *device;
211
215
219
222 hi::subpixel_orientation subpixel_orientation;
223
226 bool active;
227
231
234 utc_nanoseconds display_time_point;
235
236 draw_context(draw_context const& rhs) noexcept = default;
237 draw_context(draw_context&& rhs) noexcept = default;
238 draw_context& operator=(draw_context const& rhs) noexcept = default;
239 draw_context& operator=(draw_context&& rhs) noexcept = default;
240 ~draw_context() = default;
241
243 gfx_device& device,
248
255
262 template<std::same_as<widget_layout> WidgetLayout>
263 void draw_box(WidgetLayout const& layout, quad const& box, draw_attributes const& attributes) const noexcept
264 {
265 return _draw_box(
266 layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3() * box, attributes);
267 }
268
275 template<std::same_as<widget_layout> WidgetLayout, draw_quad_shape Shape, draw_attribute... Attributes>
276 void draw_box(WidgetLayout const& layout, Shape const& shape, Attributes const&...attributes) const noexcept
277 {
278 return draw_box(layout, make_quad(shape), draw_attributes{attributes...});
279 }
280
287 template<std::same_as<widget_layout> WidgetLayout>
288 void draw_line(WidgetLayout const& layout, line_segment const& line, draw_attributes const& attributes) const noexcept
289 {
290 hilet box = make_rectangle(line, attributes.line_width, attributes.begin_line_cap, attributes.end_line_cap);
291
293 box_attributes.line_width = 0.0f;
294 box_attributes.corner_radius =
295 make_corner_radii(attributes.line_width, attributes.begin_line_cap, attributes.end_line_cap);
296 return draw_box(layout, box, box_attributes);
297 }
298
305 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
306 void draw_line(WidgetLayout const& layout, line_segment const& line, Attributes const&...attributes) const noexcept
307 {
308 return draw_line(layout, line, draw_attributes{attributes...});
309 }
310
317 template<std::same_as<widget_layout> WidgetLayout>
318 void draw_circle(WidgetLayout const& layout, hi::circle const& circle, draw_attributes const& attributes) const noexcept
319 {
321 box_attributes.corner_radius = make_corner_radii(circle);
322 return draw_box(layout, make_rectangle(circle), box_attributes);
323 }
324
331 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
332 void draw_circle(WidgetLayout const& layout, hi::circle const& circle, Attributes const&...attributes) const noexcept
333 {
334 return draw_circle(layout, circle, draw_attributes{attributes...});
335 }
336
346 template<std::same_as<widget_layout> WidgetLayout>
347 [[nodiscard]] bool
348 draw_image(WidgetLayout const& layout, quad const& box, gfx_pipeline_image::paged_image& image, draw_attributes const& attributes) const noexcept
349 {
350 return _draw_image(layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3() * box, image);
351 }
352
362 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
363 [[nodiscard]] bool
365 const noexcept
366 {
367 return draw_image(layout, make_quad(box), image, draw_attributes{attributes...});
368 }
369
377 template<std::same_as<widget_layout> WidgetLayout>
379 WidgetLayout const& layout,
380 quad const& box,
381 hi::font const& font,
382 glyph_id glyph,
383 draw_attributes const& attributes) const noexcept
384 {
385 return _draw_glyph(
386 layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3() * box, font, glyph, attributes);
387 }
388
396 template<std::same_as<widget_layout> WidgetLayout, draw_quad_shape Shape, draw_attribute... Attributes>
398 WidgetLayout const& layout,
399 Shape const& box,
400 hi::font const& font,
401 hi::glyph_id glyph_id,
402 Attributes const&...attributes) const noexcept
403 {
404 return draw_glyph(layout, make_quad(box), font, glyph_id, draw_attributes{attributes...});
405 }
406
414 template<std::same_as<widget_layout> WidgetLayout>
416 WidgetLayout const& layout,
417 quad const& box,
418 font_book::font_glyph_type const& glyph,
419 draw_attributes const& attributes) const noexcept
420 {
421 return _draw_glyph(
422 layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3() * box, *glyph.font, glyph.id, attributes);
423 }
424
432 template<std::same_as<widget_layout> WidgetLayout, draw_quad_shape Shape, draw_attribute... Attributes>
434 WidgetLayout const& layout,
435 Shape const& box,
436 font_book::font_glyph_type const& glyph,
437 Attributes const&...attributes) const noexcept
438 {
439 return draw_glyph(layout, make_quad(box), *glyph.font, glyph.id, draw_attributes{attributes...});
440 }
441
449 template<std::same_as<widget_layout> WidgetLayout>
450 void
451 draw_text(WidgetLayout const& layout, matrix3 const& transform, text_shaper const& text, draw_attributes const& attributes)
452 const noexcept
453 {
454 return _draw_text(
455 layout.clipping_rectangle_on_window(attributes.clipping_rectangle),
456 layout.to_window3() * transform,
457 text,
458 attributes);
459 }
460
468 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
469 void draw_text(WidgetLayout const& layout, matrix3 const& transform, text_shaper const& text, Attributes const&...attributes)
470 const noexcept
471 {
472 return draw_text(layout, transform, text, draw_attributes{attributes...});
473 }
474
481 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
482 void draw_text(WidgetLayout const& layout, text_shaper const& text, Attributes const&...attributes) const noexcept
483 {
484 return draw_text(layout, matrix3{}, text, draw_attributes{attributes...});
485 }
486
494 template<std::same_as<widget_layout> WidgetLayout>
496 WidgetLayout const& layout,
497 text_shaper const& text,
498 text_selection const& selection,
499 draw_attributes const& attributes) const noexcept
500 {
501 return _draw_text_selection(
502 layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3(), text, selection, attributes);
503 }
504
512 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
514 WidgetLayout const& layout,
515 text_shaper const& text,
516 text_selection const& selection,
517 Attributes const&...attributes) const noexcept
518 {
519 return draw_text_selection(layout, text, selection, draw_attributes{attributes...});
520 }
521
531 template<std::same_as<widget_layout> WidgetLayout>
533 WidgetLayout const& layout,
534 text_shaper const& text,
535 text_cursor cursor,
536 bool overwrite_mode,
538 draw_attributes const& attributes) const noexcept
539 {
540 return _draw_text_cursors(
541 layout.clipping_rectangle_on_window(attributes.clipping_rectangle),
542 layout.to_window3(),
543 text,
544 cursor,
547 attributes);
548 }
549
559 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
561 WidgetLayout const& layout,
562 text_shaper const& text,
563 text_cursor cursor,
564 bool overwrite_mode,
566 Attributes const&...attributes) const noexcept
567 {
569 }
570
580 template<std::same_as<widget_layout> WidgetLayout>
581 void draw_hole(WidgetLayout const& layout, quad const& box, draw_attributes const& attributes) const noexcept
582 {
583 return _override_alpha(
584 layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3() * box, attributes);
585 }
586
596 template<std::same_as<widget_layout> WidgetLayout, draw_quad_shape Shape, draw_attribute... Attributes>
597 void draw_hole(WidgetLayout const& layout, Shape const& box, Attributes const&...attributes) const noexcept
598 {
599 return draw_hole(layout, make_quad(box), draw_attributes{attributes...});
600 }
601
609 template<std::same_as<widget_layout> WidgetLayout>
610 [[nodiscard]] friend bool overlaps(draw_context const& context, WidgetLayout const& layout) noexcept
611 {
612 return overlaps(context.scissor_rectangle, layout.clipping_rectangle_on_window());
613 }
614
615private:
620
621 template<draw_quad_shape Shape>
622 [[nodiscard]] constexpr static quad make_quad(Shape const& shape) noexcept
623 {
624 if constexpr (std::is_same_v<Shape, quad>) {
625 return shape;
626 } else {
627 return quad{shape};
628 }
629 }
630
631 [[nodiscard]] constexpr static rectangle
632 make_rectangle(line_segment const& line, float width, line_end_cap c1, line_end_cap c2) noexcept
633 {
634 auto right = line.direction();
635
636 hilet radius = width * 0.5f;
637 hilet n = normal(right, 0.0f);
638 hilet up = n * width;
639 hilet t = normalize(right);
640
641 auto origin = line.origin() - n * radius;
642
643 // Extend the line by the radius for rounded end-caps.
644 hilet radius_offset = t * radius;
645 if (c1 == line_end_cap::round) {
646 origin -= radius_offset;
648 }
649 if (c2 == line_end_cap::round) {
651 }
652
653 return rectangle{origin, right, up};
654 }
655
656 [[nodiscard]] constexpr static rectangle make_rectangle(hi::circle const& circle) noexcept
657 {
658 hilet circle_ = f32x4{circle};
659 hilet origin = point3{circle_.xyz1() - circle_.ww00()};
660 hilet right = vector3{circle_.w000() * 2.0f};
661 hilet up = vector3{circle_._0w00() * 2.0f};
662 return rectangle{origin, right, up};
663 }
664
665 [[nodiscard]] constexpr static corner_radii make_corner_radii(float width, line_end_cap c1, line_end_cap c2) noexcept
666 {
667 auto r = f32x4::broadcast(width * 0.5f);
668
669 if (c1 == line_end_cap::flat) {
670 r = set_zero<0b0101>(r);
671 }
672 if (c2 == line_end_cap::flat) {
673 r = set_zero<0b1010>(r);
674 }
675
676 return corner_radii{r};
677 }
678
679 [[nodiscard]] constexpr static corner_radii make_corner_radii(hi::circle const& circle) noexcept
680 {
681 return corner_radii{f32x4{circle}.wwww()};
682 }
683
684 void _override_alpha(aarectangle const& clipping_rectangle, quad box, draw_attributes const& attributes) const noexcept;
685
686 void _draw_box(aarectangle const& clipping_rectangle, quad box, draw_attributes const& attributes) const noexcept;
687
688 void _draw_text(
689 aarectangle const& clipping_rectangle,
690 matrix3 const& transform,
691 text_shaper const& text,
692 draw_attributes const& attributes) const noexcept;
693
694 void _draw_text_selection(
695 aarectangle const& clipping_rectangle,
696 matrix3 const& transform,
697 text_shaper const& text,
698 text_selection const& selection,
699 draw_attributes const& attributes) const noexcept;
700
701 void _draw_text_insertion_cursor_empty(
702 aarectangle const& clipping_rectangle,
703 matrix3 const& transform,
704 text_shaper const& text,
705 draw_attributes const& attributes) const noexcept;
706
707 void _draw_text_insertion_cursor(
708 aarectangle const& clipping_rectangle,
709 matrix3 const& transform,
710 text_shaper const& text,
711 text_cursor cursor,
712 bool show_flag,
713 draw_attributes const& attributes) const noexcept;
714
715 void _draw_text_overwrite_cursor(
716 aarectangle const& clipping_rectangle,
717 matrix3 const& transform,
718 text_shaper::char_const_iterator it,
719 draw_attributes const& attributes) const noexcept;
720
721 void _draw_text_cursors(
722 aarectangle const& clipping_rectangle,
723 matrix3 const& transform,
724 text_shaper const& text,
725 text_cursor cursor,
726 bool overwrite_mode,
728 draw_attributes const& attributes) const noexcept;
729
730 void _draw_glyph(
731 aarectangle const& clipping_rectangle,
732 quad const& box,
733 hi::font const& font,
734 glyph_id glyph,
735 draw_attributes const& attributes) const noexcept;
736
737 [[nodiscard]] bool
738 _draw_image(aarectangle const& clipping_rectangle, quad const& box, gfx_pipeline_image::paged_image const& image) const noexcept;
739};
740
741}} // namespace hi::v1
line_end_cap
The way two lines should be joined.
Definition line_end_cap.hpp:18
@ right
Align the text to the right side.
@ flat
The end cap of the line is flat.
@ round
The end cap of the line is round.
@ rectangle
The gui_event has rectangle data.
DOXYGEN BUG.
Definition algorithm.hpp:16
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
border_side
The side where the border is drawn.
Definition draw_context.hpp:27
@ 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.
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
A color for each corner of a quad.
Definition quad_color.hpp:20
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:29
static constexpr aarectangle large() noexcept
Create a large axis aligned rectangle.
Definition aarectangle.hpp:42
A type defining a 2D circle.
Definition circle.hpp:19
The 4 radii of the corners of a quad or rectangle.
Definition corner_radii.hpp:19
Line segment.
Definition line_segment.hpp:21
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix3.hpp:30
The draw attributes used to draw shaped into the draw context.
Definition draw_context.hpp:48
aarectangle clipping_rectangle
The rectangle used the clip the shape when drawing.
Definition draw_context.hpp:82
hi::border_side border_side
The side on which side of the edge of a shape the border should be drawn.
Definition draw_context.hpp:71
float line_width
The width of a line, or the width of a border.
Definition draw_context.hpp:67
line_end_cap end_line_cap
The shape of the beginning of a line.
Definition draw_context.hpp:90
quad_color fill_color
The fill color used for the color of a box inside the border.
Definition draw_context.hpp:57
quad_color line_color
The line color used for the color of the border of the box.
Definition draw_context.hpp:63
line_end_cap begin_line_cap
The shape of the beginning of a line.
Definition draw_context.hpp:86
hi::corner_radii corner_radius
The radii of each corner of a quad.
Definition draw_context.hpp:75
Draw context for drawing using the HikoGUI shaders.
Definition draw_context.hpp:208
void draw_glyph(WidgetLayout const &layout, quad const &box, font_book::font_glyph_type const &glyph, draw_attributes const &attributes) const noexcept
Draw a glyph.
Definition draw_context.hpp:415
void draw_text(WidgetLayout const &layout, text_shaper const &text, Attributes const &...attributes) const noexcept
Draw shaped text.
Definition draw_context.hpp:482
void draw_circle(WidgetLayout const &layout, hi::circle const &circle, Attributes const &...attributes) const noexcept
Draw a circle.
Definition draw_context.hpp:332
void draw_text_cursors(WidgetLayout const &layout, text_shaper const &text, text_cursor cursor, bool overwrite_mode, bool dead_character_mode, Attributes const &...attributes) const noexcept
Draw text cursors of shaped text.
Definition draw_context.hpp:560
hi::subpixel_orientation subpixel_orientation
The subpixel orientation for rendering glyphs.
Definition draw_context.hpp:222
friend bool overlaps(draw_context const &context, WidgetLayout const &layout) noexcept
Checks if a widget's layout overlaps with the part of the window that is being drawn.
Definition draw_context.hpp:610
void draw_box(WidgetLayout const &layout, Shape const &shape, Attributes const &...attributes) const noexcept
Draw a box.
Definition draw_context.hpp:276
bool draw_image(WidgetLayout const &layout, draw_quad_shape auto const &box, gfx_pipeline_image::paged_image &image, Attributes const &...attributes) const noexcept
Draw an image.
Definition draw_context.hpp:364
void draw_circle(WidgetLayout const &layout, hi::circle const &circle, draw_attributes const &attributes) const noexcept
Draw a circle.
Definition draw_context.hpp:318
float saturation
The tone-mapper's saturation.
Definition draw_context.hpp:230
void draw_text(WidgetLayout const &layout, matrix3 const &transform, text_shaper const &text, Attributes const &...attributes) const noexcept
Draw shaped text.
Definition draw_context.hpp:469
bool active
Window is active.
Definition draw_context.hpp:226
void draw_glyph(WidgetLayout const &layout, Shape const &box, hi::font const &font, hi::glyph_id glyph_id, Attributes const &...attributes) const noexcept
Draw a glyph.
Definition draw_context.hpp:397
void draw_text_selection(WidgetLayout const &layout, text_shaper const &text, text_selection const &selection, draw_attributes const &attributes) const noexcept
Draw text-selection of shaped text.
Definition draw_context.hpp:495
aarectangle scissor_rectangle
This is the rectangle of the window that is being redrawn.
Definition draw_context.hpp:218
void draw_line(WidgetLayout const &layout, line_segment const &line, Attributes const &...attributes) const noexcept
Draw a line.
Definition draw_context.hpp:306
void draw_glyph(WidgetLayout const &layout, Shape const &box, font_book::font_glyph_type const &glyph, Attributes const &...attributes) const noexcept
Draw a glyph.
Definition draw_context.hpp:433
std::size_t frame_buffer_index
The frame buffer index of the image we are currently rendering.
Definition draw_context.hpp:214
void draw_hole(WidgetLayout const &layout, quad const &box, draw_attributes const &attributes) const noexcept
Make a hole in the user interface.
Definition draw_context.hpp:581
void draw_hole(WidgetLayout const &layout, Shape const &box, Attributes const &...attributes) const noexcept
Make a hole in the user interface.
Definition draw_context.hpp:597
void draw_text_cursors(WidgetLayout const &layout, text_shaper const &text, text_cursor cursor, bool overwrite_mode, bool dead_character_mode, draw_attributes const &attributes) const noexcept
Draw text cursors of shaped text.
Definition draw_context.hpp:532
void draw_line(WidgetLayout const &layout, line_segment const &line, draw_attributes const &attributes) const noexcept
Draw a line.
Definition draw_context.hpp:288
bool draw_image(WidgetLayout const &layout, quad const &box, gfx_pipeline_image::paged_image &image, draw_attributes const &attributes) const noexcept
Draw an image.
Definition draw_context.hpp:348
void draw_text_selection(WidgetLayout const &layout, text_shaper const &text, text_selection const &selection, Attributes const &...attributes) const noexcept
Draw text-selection of shaped text.
Definition draw_context.hpp:513
void draw_glyph(WidgetLayout const &layout, quad const &box, hi::font const &font, glyph_id glyph, draw_attributes const &attributes) const noexcept
Draw a glyph.
Definition draw_context.hpp:378
void draw_box(WidgetLayout const &layout, quad const &box, draw_attributes const &attributes) const noexcept
Draw a box.
Definition draw_context.hpp:263
utc_nanoseconds display_time_point
The time when the drawing will appear on the screen.
Definition draw_context.hpp:234
void draw_text(WidgetLayout const &layout, matrix3 const &transform, text_shaper const &text, draw_attributes const &attributes) const noexcept
Draw shaped text.
Definition draw_context.hpp:451
This is a image that is uploaded into the texture atlas.
Definition gfx_pipeline_image_vulkan.hpp:79
Definition draw_context.hpp:42
Definition draw_context.hpp:203
T max(T... args)