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"
11#include "../settings/module.hpp"
12#include "../geometry/module.hpp"
13#include "../unicode/module.hpp"
14#include "../text/module.hpp"
15#include "../color/module.hpp"
16#include "../container/module.hpp"
17#include "../utility/module.hpp"
18
19namespace hi { inline namespace v1 {
20class gfx_device;
21class gfx_device_vulkan;
22class glyph_ids;
23class widget_layout;
24struct paged_image;
25
28enum class border_side {
31 on,
32
35 inside,
36
40};
41
42template<typename Context>
43concept draw_attribute = std::same_as<Context, quad_color> or std::same_as<Context, color> or
44 std::same_as<Context, border_side> or std::same_as<Context, line_end_cap> or std::same_as<Context, corner_radii> or
45 std::same_as<Context, aarectangle> or std::same_as<Context, float> or std::same_as<Context, int>;
46
50 unsigned char num_colors = 0;
51 unsigned char num_line_caps = 0;
52
59
65
68 float line_width = 0.0f;
69
72 hi::border_side border_side = hi::border_side::on;
73
77
84
88
92
93 constexpr draw_attributes(draw_attributes const&) noexcept = default;
94 constexpr draw_attributes(draw_attributes&&) noexcept = default;
95 constexpr draw_attributes& operator=(draw_attributes const&) noexcept = default;
96 constexpr draw_attributes& operator=(draw_attributes&&) noexcept = default;
97 constexpr draw_attributes() noexcept = default;
98
119 template<draw_attribute... Args>
120 constexpr draw_attributes(Args const&...args) noexcept
121 {
122 add(args...);
123 }
124
125 constexpr void add() noexcept {}
126
127 template<draw_attribute T>
128 constexpr void add(T const& attribute) noexcept
129 {
130 if constexpr (std::is_same_v<T, quad_color>) {
131 if (num_colors++ == 0) {
132 fill_color = attribute;
133 } else {
134 line_color = attribute;
135 }
136 hi_axiom(num_colors <= 2);
137
138 } else if constexpr (std::is_same_v<T, color>) {
139 if (num_colors++ == 0) {
140 fill_color = quad_color{attribute};
141 } else {
142 line_color = quad_color{attribute};
143 }
144 hi_axiom(num_colors <= 2);
145
146 } else if constexpr (std::is_same_v<T, line_end_cap>) {
147 if (num_line_caps++ == 0) {
148 begin_line_cap = attribute;
149 end_line_cap = attribute;
150 } else {
151 end_line_cap = attribute;
152 }
153 hi_axiom(num_line_caps <= 2);
154
155 } else if constexpr (std::is_same_v<T, hi::border_side>) {
156 border_side = attribute;
157#ifndef NDEBUG
158 hi_assert(not _has_border_side);
159 _has_border_side = true;
160#endif
161
162 } else if constexpr (std::is_same_v<T, corner_radii>) {
163 corner_radius = attribute;
164#ifndef NDEBUG
165 hi_assert(not _has_corner_radii);
166 _has_corner_radii = true;
167#endif
168
169 } else if constexpr (std::is_same_v<T, aarectangle>) {
170 clipping_rectangle = attribute;
171#ifndef NDEBUG
172 hi_assert(not _has_clipping_rectangle);
173 _has_clipping_rectangle = true;
174#endif
175
176 } else if constexpr (std::is_same_v<T, float> or std::is_same_v<T, int>) {
177 line_width = narrow_cast<float>(attribute);
178#ifndef NDEBUG
179 hi_assert(not _has_line_width);
180 _has_line_width = true;
181#endif
182 } else {
184 }
185 }
186
187 template<draw_attribute First, draw_attribute Second, draw_attribute... Rest>
188 constexpr void add(First const& first, Second const& second, Rest const&...rest) noexcept
189 {
190 add(first);
191 add(second, rest...);
192 }
193
194private:
195#ifndef NDEBUG
196 bool _has_border_side = false;
197 bool _has_corner_radii = false;
198 bool _has_clipping_rectangle = false;
199 bool _has_line_width = false;
200#endif
201};
202
203template<typename Context>
204concept draw_quad_shape = std::same_as<Context, quad> or std::same_as<Context, rectangle> or std::same_as<Context, aarectangle> or
205 std::same_as<Context, aarectangle>;
206
210public:
211 gfx_device_vulkan& device;
212
216
220
223 hi::subpixel_orientation subpixel_orientation;
224
227 bool active;
228
232
235 utc_nanoseconds display_time_point;
236
237 draw_context(draw_context const& rhs) noexcept = default;
238 draw_context(draw_context&& rhs) noexcept = default;
239 draw_context& operator=(draw_context const& rhs) noexcept = default;
240 draw_context& operator=(draw_context&& rhs) noexcept = default;
241 ~draw_context() = default;
242
244 gfx_device_vulkan& device,
245 vector_span<pipeline_box::vertex>& box_vertices,
246 vector_span<pipeline_image::vertex>& image_vertices,
247 vector_span<pipeline_SDF::vertex>& sdf_vertices,
248 vector_span<pipeline_alpha::vertex>& alpha_vertices) noexcept;
249
252 operator bool() const noexcept
253 {
255 }
256
263 template<std::same_as<widget_layout> WidgetLayout>
264 void draw_box(WidgetLayout const& layout, quad const& box, draw_attributes const& attributes) const noexcept
265 {
266 return _draw_box(
267 layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3() * box, attributes);
268 }
269
276 template<std::same_as<widget_layout> WidgetLayout, draw_quad_shape Shape, draw_attribute... Attributes>
277 void draw_box(WidgetLayout const& layout, Shape const& shape, Attributes const&...attributes) const noexcept
278 {
279 return draw_box(layout, make_quad(shape), draw_attributes{attributes...});
280 }
281
288 template<std::same_as<widget_layout> WidgetLayout>
289 void draw_line(WidgetLayout const& layout, line_segment const& line, draw_attributes const& attributes) const noexcept
290 {
291 hilet box = make_rectangle(line, attributes.line_width, attributes.begin_line_cap, attributes.end_line_cap);
292
293 auto box_attributes = attributes;
294 box_attributes.line_width = 0.0f;
295 box_attributes.corner_radius =
296 make_corner_radii(attributes.line_width, attributes.begin_line_cap, attributes.end_line_cap);
297 return draw_box(layout, box, box_attributes);
298 }
299
306 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
307 void draw_line(WidgetLayout const& layout, line_segment const& line, Attributes const&...attributes) const noexcept
308 {
309 return draw_line(layout, line, draw_attributes{attributes...});
310 }
311
318 template<std::same_as<widget_layout> WidgetLayout>
319 void draw_circle(WidgetLayout const& layout, hi::circle const& circle, draw_attributes const& attributes) const noexcept
320 {
321 auto box_attributes = attributes;
322 box_attributes.corner_radius = make_corner_radii(circle);
323 return draw_box(layout, make_rectangle(circle), box_attributes);
324 }
325
332 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
333 void draw_circle(WidgetLayout const& layout, hi::circle const& circle, Attributes const&...attributes) const noexcept
334 {
335 return draw_circle(layout, circle, draw_attributes{attributes...});
336 }
337
347 template<std::same_as<widget_layout> WidgetLayout>
348 [[nodiscard]] bool
349 draw_image(WidgetLayout const& layout, quad const& box, paged_image& image, draw_attributes const& attributes) const noexcept
350 {
351 return _draw_image(layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3() * box, image);
352 }
353
363 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
364 [[nodiscard]] bool
365 draw_image(WidgetLayout const& layout, draw_quad_shape auto const& box, paged_image& image, Attributes const&...attributes)
366 const noexcept
367 {
368 return draw_image(layout, make_quad(box), image, draw_attributes{attributes...});
369 }
370
378 template<std::same_as<widget_layout> WidgetLayout>
379 void draw_glyph(WidgetLayout const& layout, quad const& box, glyph_ids const& glyph, draw_attributes const& attributes)
380 const noexcept
381 {
382 return _draw_glyph(
383 layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3() * box, glyph, attributes);
384 }
385
393 template<std::same_as<widget_layout> WidgetLayout, draw_quad_shape Shape, draw_attribute... Attributes>
394 void draw_glyph(WidgetLayout const& layout, Shape const& box, glyph_ids const& glyph, Attributes const&...attributes)
395 const noexcept
396 {
397 return draw_glyph(layout, make_quad(box), glyph, draw_attributes{attributes...});
398 }
399
407 template<std::same_as<widget_layout> WidgetLayout>
408 void
409 draw_text(WidgetLayout const& layout, matrix3 const& transform, text_shaper const& text, draw_attributes const& attributes)
410 const noexcept
411 {
412 return _draw_text(
413 layout.clipping_rectangle_on_window(attributes.clipping_rectangle),
414 layout.to_window3() * transform,
415 text,
416 attributes);
417 }
418
426 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
427 void draw_text(WidgetLayout const& layout, matrix3 const& transform, text_shaper const& text, Attributes const&...attributes)
428 const noexcept
429 {
430 return draw_text(layout, transform, text, draw_attributes{attributes...});
431 }
432
439 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
440 void draw_text(WidgetLayout const& layout, text_shaper const& text, Attributes const&...attributes) const noexcept
441 {
442 return draw_text(layout, matrix3{}, text, draw_attributes{attributes...});
443 }
444
452 template<std::same_as<widget_layout> WidgetLayout>
454 WidgetLayout const& layout,
455 text_shaper const& text,
456 text_selection const& selection,
457 draw_attributes const& attributes) const noexcept
458 {
459 return _draw_text_selection(
460 layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3(), text, selection, attributes);
461 }
462
470 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
472 WidgetLayout const& layout,
473 text_shaper const& text,
474 text_selection const& selection,
475 Attributes const&...attributes) const noexcept
476 {
477 return draw_text_selection(layout, text, selection, draw_attributes{attributes...});
478 }
479
489 template<std::same_as<widget_layout> WidgetLayout>
491 WidgetLayout const& layout,
492 text_shaper const& text,
493 text_cursor cursor,
494 bool overwrite_mode,
495 bool dead_character_mode,
496 draw_attributes const& attributes) const noexcept
497 {
498 return _draw_text_cursors(
499 layout.clipping_rectangle_on_window(attributes.clipping_rectangle),
500 layout.to_window3(),
501 text,
502 cursor,
503 overwrite_mode,
504 dead_character_mode,
505 attributes);
506 }
507
517 template<std::same_as<widget_layout> WidgetLayout, draw_attribute... Attributes>
519 WidgetLayout const& layout,
520 text_shaper const& text,
521 text_cursor cursor,
522 bool overwrite_mode,
523 bool dead_character_mode,
524 Attributes const&...attributes) const noexcept
525 {
526 return draw_text_cursors(layout, text, cursor, overwrite_mode, dead_character_mode, draw_attributes{attributes...});
527 }
528
538 template<std::same_as<widget_layout> WidgetLayout>
539 void draw_hole(WidgetLayout const& layout, quad const& box, draw_attributes const& attributes) const noexcept
540 {
541 return _override_alpha(
542 layout.clipping_rectangle_on_window(attributes.clipping_rectangle), layout.to_window3() * box, attributes);
543 }
544
554 template<std::same_as<widget_layout> WidgetLayout, draw_quad_shape Shape, draw_attribute... Attributes>
555 void draw_hole(WidgetLayout const& layout, Shape const& box, Attributes const&...attributes) const noexcept
556 {
557 return draw_hole(layout, make_quad(box), draw_attributes{attributes...});
558 }
559
567 template<std::same_as<widget_layout> WidgetLayout>
568 [[nodiscard]] friend bool overlaps(draw_context const& context, WidgetLayout const& layout) noexcept
569 {
570 return overlaps(context.scissor_rectangle, layout.clipping_rectangle_on_window());
571 }
572
573private:
574 vector_span<pipeline_box::vertex> *_box_vertices;
575 vector_span<pipeline_image::vertex> *_image_vertices;
576 vector_span<pipeline_SDF::vertex> *_sdf_vertices;
577 vector_span<pipeline_alpha::vertex> *_alpha_vertices;
578
579 template<draw_quad_shape Shape>
580 [[nodiscard]] constexpr static quad make_quad(Shape const& shape) noexcept
581 {
582 if constexpr (std::is_same_v<Shape, quad>) {
583 return shape;
584 } else {
585 return quad{shape};
586 }
587 }
588
589 [[nodiscard]] constexpr static rectangle
590 make_rectangle(line_segment const& line, float width, line_end_cap c1, line_end_cap c2) noexcept
591 {
592 auto right = line.direction();
593
594 hilet radius = width * 0.5f;
595 hilet n = normal(right, 0.0f);
596 hilet up = n * width;
597 hilet t = normalize(right);
598
599 auto origin = line.origin() - n * radius;
600
601 // Extend the line by the radius for rounded end-caps.
602 hilet radius_offset = t * radius;
603 if (c1 == line_end_cap::round) {
604 origin -= radius_offset;
605 right += radius_offset;
606 }
607 if (c2 == line_end_cap::round) {
608 right += radius_offset;
609 }
610
611 return rectangle{origin, right, up};
612 }
613
614 [[nodiscard]] constexpr static rectangle make_rectangle(hi::circle const& circle) noexcept
615 {
616 hilet circle_ = f32x4{circle};
617 hilet origin = point3{circle_.xyz1() - circle_.ww00()};
618 hilet right = vector3{circle_.w000() * 2.0f};
619 hilet up = vector3{circle_._0w00() * 2.0f};
620 return rectangle{origin, right, up};
621 }
622
623 [[nodiscard]] constexpr static corner_radii make_corner_radii(float width, line_end_cap c1, line_end_cap c2) noexcept
624 {
625 auto r = f32x4::broadcast(width * 0.5f);
626
627 if (c1 == line_end_cap::flat) {
628 r = set_zero<0b0101>(r);
629 }
630 if (c2 == line_end_cap::flat) {
631 r = set_zero<0b1010>(r);
632 }
633
634 return corner_radii{r};
635 }
636
637 [[nodiscard]] constexpr static corner_radii make_corner_radii(hi::circle const& circle) noexcept
638 {
639 return corner_radii{f32x4{circle}.wwww()};
640 }
641
642 void _override_alpha(aarectangle const& clipping_rectangle, quad box, draw_attributes const& attributes) const noexcept;
643
644 void _draw_box(aarectangle const& clipping_rectangle, quad box, draw_attributes const& attributes) const noexcept;
645
646 void _draw_text(
647 aarectangle const& clipping_rectangle,
648 matrix3 const& transform,
649 text_shaper const& text,
650 draw_attributes const& attributes) const noexcept;
651
652 void _draw_text_selection(
653 aarectangle const& clipping_rectangle,
654 matrix3 const& transform,
655 text_shaper const& text,
656 text_selection const& selection,
657 draw_attributes const& attributes) const noexcept;
658
659 void _draw_text_insertion_cursor_empty(
660 aarectangle const& clipping_rectangle,
661 matrix3 const& transform,
662 text_shaper const& text,
663 draw_attributes const& attributes) const noexcept;
664
665 void _draw_text_insertion_cursor(
666 aarectangle const& clipping_rectangle,
667 matrix3 const& transform,
668 text_shaper const& text,
669 text_cursor cursor,
670 bool show_flag,
671 draw_attributes const& attributes) const noexcept;
672
673 void _draw_text_overwrite_cursor(
674 aarectangle const& clipping_rectangle,
675 matrix3 const& transform,
676 text_shaper::char_const_iterator it,
677 draw_attributes const& attributes) const noexcept;
678
679 void _draw_text_cursors(
680 aarectangle const& clipping_rectangle,
681 matrix3 const& transform,
682 text_shaper const& text,
683 text_cursor cursor,
684 bool overwrite_mode,
685 bool dead_character_mode,
686 draw_attributes const& attributes) const noexcept;
687
688 void
689 _draw_glyph(aarectangle const& clipping_rectangle, quad const& box, glyph_ids const& glyph, draw_attributes const& attributes)
690 const noexcept;
691
692 [[nodiscard]] bool
693 _draw_image(aarectangle const& clipping_rectangle, quad const& box, paged_image const& image) const noexcept;
694};
695
696}} // namespace hi::v1
#define hi_static_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:323
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:199
#define hi_axiom(expression,...)
Specify an axiom; an expression that is true.
Definition assert.hpp:253
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
line_end_cap
The way two lines should be joined.
Definition line_end_cap.hpp:17
@ 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:13
geometry/margins.hpp
Definition cache.hpp:11
border_side
The side where the border is drawn.
Definition draw_context.hpp:28
@ 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.
A color for each corner of a quad.
Definition quad_color.hpp:19
Class which represents an axis-aligned rectangle.
Definition aarectangle.hpp:26
static constexpr aarectangle large() noexcept
Create a large axis aligned rectangle.
Definition aarectangle.hpp:39
A type defining a 2D circle.
Definition circle.hpp:18
The 4 radii of the corners of a quad or rectangle.
Definition corner_radii.hpp:18
Line segment.
Definition line_segment.hpp:20
A 2D or 3D homogenius matrix for transforming homogenious vectors and points.
Definition matrix3.hpp:29
The draw attributes used to draw shaped into the draw context.
Definition draw_context.hpp:49
aarectangle clipping_rectangle
The rectangle used the clip the shape when drawing.
Definition draw_context.hpp:83
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:72
float line_width
The width of a line, or the width of a border.
Definition draw_context.hpp:68
line_end_cap end_line_cap
The shape of the beginning of a line.
Definition draw_context.hpp:91
quad_color fill_color
The fill color used for the color of a box inside the border.
Definition draw_context.hpp:58
quad_color line_color
The line color used for the color of the border of the box.
Definition draw_context.hpp:64
line_end_cap begin_line_cap
The shape of the beginning of a line.
Definition draw_context.hpp:87
hi::corner_radii corner_radius
The radii of each corner of a quad.
Definition draw_context.hpp:76
Draw context for drawing using the HikoGUI shaders.
Definition draw_context.hpp:209
bool draw_image(WidgetLayout const &layout, draw_quad_shape auto const &box, paged_image &image, Attributes const &...attributes) const noexcept
Draw an image.
Definition draw_context.hpp:365
void draw_text(WidgetLayout const &layout, text_shaper const &text, Attributes const &...attributes) const noexcept
Draw shaped text.
Definition draw_context.hpp:440
void draw_circle(WidgetLayout const &layout, hi::circle const &circle, Attributes const &...attributes) const noexcept
Draw a circle.
Definition draw_context.hpp:333
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:518
hi::subpixel_orientation subpixel_orientation
The subpixel orientation for rendering glyphs.
Definition draw_context.hpp:223
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:568
void draw_box(WidgetLayout const &layout, Shape const &shape, Attributes const &...attributes) const noexcept
Draw a box.
Definition draw_context.hpp:277
void draw_circle(WidgetLayout const &layout, hi::circle const &circle, draw_attributes const &attributes) const noexcept
Draw a circle.
Definition draw_context.hpp:319
float saturation
The tone-mapper's saturation.
Definition draw_context.hpp:231
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:427
bool active
Window is active.
Definition draw_context.hpp:227
bool draw_image(WidgetLayout const &layout, quad const &box, paged_image &image, draw_attributes const &attributes) const noexcept
Draw an image.
Definition draw_context.hpp:349
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:453
aarectangle scissor_rectangle
This is the rectangle of the window that is being redrawn.
Definition draw_context.hpp:219
void draw_glyph(WidgetLayout const &layout, quad const &box, glyph_ids const &glyph, draw_attributes const &attributes) const noexcept
Draw a glyph.
Definition draw_context.hpp:379
void draw_line(WidgetLayout const &layout, line_segment const &line, Attributes const &...attributes) const noexcept
Draw a line.
Definition draw_context.hpp:307
void draw_glyph(WidgetLayout const &layout, Shape const &box, glyph_ids const &glyph, Attributes const &...attributes) const noexcept
Draw a glyph.
Definition draw_context.hpp:394
std::size_t frame_buffer_index
The frame buffer index of the image we are currently rendering.
Definition draw_context.hpp:215
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:539
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:555
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:490
void draw_line(WidgetLayout const &layout, line_segment const &line, draw_attributes const &attributes) const noexcept
Draw a line.
Definition draw_context.hpp:289
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:471
void draw_box(WidgetLayout const &layout, quad const &box, draw_attributes const &attributes) const noexcept
Draw a box.
Definition draw_context.hpp:264
utc_nanoseconds display_time_point
The time when the drawing will appear on the screen.
Definition draw_context.hpp:235
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:409
Definition draw_context.hpp:43
Definition draw_context.hpp:204
T max(T... args)