HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
draw_context.hpp
1// Copyright Take Vos 2020.
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"
24#include "../widgets/widget_layout.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
47 outside
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(
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
151 widget_layout const& layout,
152 aarectangle const& clipping_rectangle,
153 quad const& box,
154 quad_color const& fill_color,
155 quad_color const& border_color,
156 float border_width,
157 hi::border_side border_side,
158 hi::corner_radii const& corner_radius = {}) const noexcept
159 {
160 // clang-format off
161 hilet border_radius = border_width * 0.5f;
162 hilet box_ =
163 border_side == hi::border_side::inside ? box - border_radius :
164 border_side == hi::border_side::outside ? box + border_radius :
165 box;
166 hilet corner_radius_ =
167 border_side == hi::border_side::inside ? corner_radius - border_radius :
168 border_side == hi::border_side::outside ? corner_radius + border_radius :
169 corner_radius;
170 // clang-format on
171
172 return _draw_box(
173 layout.window_clipping_rectangle(clipping_rectangle),
174 layout.to_window * box_,
175 fill_color,
176 border_color,
177 layout.to_window * border_width,
178 layout.to_window * corner_radius_);
179 }
188 widget_layout const& layout,
189 quad const& box,
190 quad_color const& fill_color,
191 hi::corner_radii const& corner_radius = {}) const noexcept
192 {
193 return _draw_box(
195 layout.to_window * box,
196 fill_color,
197 fill_color,
198 0.0f,
199 layout.to_window * corner_radius);
200 }
201
211 widget_layout const& layout,
212 aarectangle const& clipping_rectangle,
213 quad const& box,
214 quad_color const& fill_color,
215 hi::corner_radii const& corner_radius = {}) const noexcept
216 {
217 return _draw_box(
218 layout.window_clipping_rectangle(clipping_rectangle),
219 layout.to_window * box,
220 fill_color,
221 fill_color,
222 0.0f,
223 layout.to_window * corner_radius);
224 }
225
226 [[nodiscard]] constexpr static rectangle
227 make_rectangle(line_segment const& line, float width, line_end_cap c1, line_end_cap c2) noexcept
228 {
229 auto right = line.direction();
230
231 hilet radius = width * 0.5f;
232 hilet n = normal(right, 0.0f);
233 hilet up = n * width;
234 hilet t = normalize(right);
235
236 auto origin = line.origin() - n * radius;
237
238 // Extend the line by the radius for rounded end-caps.
239 hilet radius_offset = t * radius;
240 if (c1 == line_end_cap::round) {
241 origin -= radius_offset;
242 right += radius_offset;
243 }
244 if (c2 == line_end_cap::round) {
245 right += radius_offset;
246 }
247
248 return rectangle{origin, right, up};
249 }
250
251 [[nodiscard]] constexpr static corner_radii make_corner_radii(float width, line_end_cap c1, line_end_cap c2) noexcept
252 {
253 auto r = f32x4::broadcast(width * 0.5f);
254
255 if (c1 == line_end_cap::flat) {
256 r = zero<0b0101>(r);
257 }
258 if (c2 == line_end_cap::flat) {
259 r = zero<0b1010>(r);
260 }
261
262 return corner_radii{r};
263 }
264
265 void draw_line(
266 widget_layout const& layout,
267 line_segment const& line,
268 float width,
269 quad_color const& fill_color,
270 line_end_cap c1 = line_end_cap::flat,
271 line_end_cap c2 = line_end_cap::flat) const noexcept
272 {
273 hilet line_ = layout.to_window * line;
274 hilet width_ = layout.to_window * width;
275
276 hilet box = make_rectangle(line_, width_, c1, c2);
277 hilet corners = make_corner_radii(width_, c1, c2);
278
279 return _draw_box(layout.window_clipping_rectangle(), box, fill_color, fill_color, 0.0f, corners);
280 }
281
282 void draw_line(
283 widget_layout const& layout,
284 aarectangle const& clipping_rectangle,
285 line_segment const& line,
286 float width,
287 quad_color const& fill_color,
288 line_end_cap c1 = line_end_cap::flat,
289 line_end_cap c2 = line_end_cap::flat) const noexcept
290 {
291 hi_axiom(width != 0.0f);
292 hilet line_ = layout.to_window * line;
293 hilet width_ = layout.to_window * width;
294
295 hilet box = make_rectangle(line_, width_, c1, c2);
296 hilet corners = make_corner_radii(width_, c1, c2);
297
298 return _draw_box(layout.window_clipping_rectangle(clipping_rectangle), box, fill_color, fill_color, 0.0f, corners);
299 }
300
301 [[nodiscard]] constexpr static rectangle make_rectangle(hi::circle const& circle) noexcept
302 {
303 hilet circle_ = f32x4{circle};
304 hilet origin = point3{circle_.xyz1() - circle_.ww00()};
305 hilet right = vector3{circle_.w000() * 2.0f};
306 hilet up = vector3{circle_._0w00() * 2.0f};
307 return rectangle{origin, right, up};
308 }
309
310 [[nodiscard]] constexpr static corner_radii make_corner_radii(hi::circle const& circle) noexcept
311 {
312 return corner_radii{f32x4{circle}.wwww()};
313 }
314
315 void draw_circle(widget_layout const& layout, hi::circle const& circle, quad_color const& fill_color) const noexcept
316 {
317 hilet box = layout.to_window * make_rectangle(circle);
318 hilet corners = layout.to_window * make_corner_radii(circle);
319 return _draw_box(layout.window_clipping_rectangle(), box, fill_color, fill_color, 0.0f, corners);
320 }
321
322 void draw_circle(
323 widget_layout const& layout,
324 aarectangle const clipping_rectangle,
325 hi::circle const& circle,
326 quad_color const& fill_color) const
327 {
328 hilet box = layout.to_window * make_rectangle(circle);
329 hilet corners = layout.to_window * make_corner_radii(circle);
330 return _draw_box(layout.window_clipping_rectangle(clipping_rectangle), box, fill_color, fill_color, 0.0f, corners);
331 }
332
333 void draw_circle(
334 widget_layout const& layout,
335 hi::circle const& circle,
336 quad_color const& fill_color,
337 quad_color const& border_color,
338 float border_width,
339 hi::border_side border_side) const noexcept
340 {
341 // clang-format off
342 hilet circle_ =
343 border_side == hi::border_side::inside ? circle - border_width * 0.5f :
344 border_side == hi::border_side::outside ? circle + border_width * 0.5f :
345 circle;
346 // clang-format on
347
348 hilet box = layout.to_window * make_rectangle(circle_);
349 hilet corners = layout.to_window * make_corner_radii(circle_);
350 return _draw_box(layout.window_clipping_rectangle(), box, fill_color, border_color, border_width, corners);
351 }
352
353 void draw_circle(
354 widget_layout const& layout,
355 aarectangle const& clipping_rectangle,
356 hi::circle const& circle,
357 quad_color const& fill_color,
358 quad_color const& border_color,
359 float border_width,
360 hi::border_side border_side) const noexcept
361 {
362 // clang-format off
363 hilet circle_ =
364 border_side == hi::border_side::inside ? circle - border_width * 0.5f :
365 border_side == hi::border_side::outside ? circle + border_width * 0.5f :
366 circle;
367 // clang-format on
368
369 hilet box = layout.to_window * make_rectangle(circle_);
370 hilet corners = layout.to_window * make_corner_radii(circle_);
371 return _draw_box(
372 layout.window_clipping_rectangle(clipping_rectangle), box, fill_color, border_color, border_width, corners);
373 }
374
383 [[nodiscard]] bool draw_image(widget_layout const& layout, quad const& box, paged_image& image) const noexcept
384 {
385 return _draw_image(layout.window_clipping_rectangle(), layout.to_window * box, image);
386 }
387
397 [[nodiscard]] bool
398 draw_image(widget_layout const& layout, aarectangle const& clipping_rectangle, quad const& box, paged_image& image)
399 const noexcept
400 {
401 return _draw_image(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * box, image);
402 }
403
411 void draw_glyph(widget_layout const& layout, quad const& box, quad_color const& color, glyph_ids const& glyph) const noexcept
412 {
413 return _draw_glyph(layout.window_clipping_rectangle(), layout.to_window * box, color, glyph);
414 }
415
425 widget_layout const& layout,
426 aarectangle clipping_rectangle,
427 quad const& box,
428 quad_color const& color,
429 glyph_ids const& glyph) const noexcept
430 {
431 return _draw_glyph(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * box, color, glyph);
432 }
433
441 void draw_text(widget_layout const& layout, matrix3 const& transform, quad_color const& color, shaped_text const& text)
442 const noexcept
443 {
444 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text, color);
445 }
446
456 widget_layout const& layout,
457 aarectangle const& clipping_rectangle,
458 matrix3 const& transform,
459 quad_color const& color,
460 shaped_text const& text) const noexcept
461 {
462 return _draw_text(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * transform, text, color);
463 }
464
471 void draw_text(widget_layout const& layout, matrix3 const& transform, shaped_text const& text) const noexcept
472 {
473 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text);
474 }
475
483 void draw_text(widget_layout const& layout, matrix3 const& transform, quad_color const& color, text_shaper const& text)
484 const noexcept
485 {
486 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text, color);
487 }
488
495 void draw_text(widget_layout const& layout, quad_color const& color, text_shaper const& text) const noexcept
496 {
497 return _draw_text(layout.window_clipping_rectangle(), layout.to_window, text, color);
498 }
499
509 widget_layout const& layout,
510 aarectangle const& clipping_rectangle,
511 matrix3 const& transform,
512 quad_color const& color,
513 text_shaper const& text) const noexcept
514 {
515 return _draw_text(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * transform, text, color);
516 }
517
526 widget_layout const& layout,
527 aarectangle const& clipping_rectangle,
528 quad_color const& color,
529 text_shaper const& text) const noexcept
530 {
531 return _draw_text(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window, text, color);
532 }
533
540 void draw_text(widget_layout const& layout, matrix3 const& transform, text_shaper const& text) const noexcept
541 {
542 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text);
543 }
544
550 void draw_text(widget_layout const& layout, text_shaper const& text) const noexcept
551 {
552 return _draw_text(layout.window_clipping_rectangle(), layout.to_window, text);
553 }
554
562 void
563 draw_text_selection(widget_layout const& layout, text_shaper const& text, text_selection const& selection, hi::color color)
564 const noexcept
565 {
566 return _draw_text_selection(layout.window_clipping_rectangle(), layout.to_window, text, selection, color);
567 }
568
580 widget_layout const& layout,
581 text_shaper const& text,
582 text_cursor cursor,
583 hi::color primary_color,
584 hi::color secondary_color,
585 bool overwrite_mode,
586 bool dead_character_mode) const noexcept
587 {
588 return _draw_text_cursors(
590 layout.to_window,
591 text,
592 cursor,
593 primary_color,
594 secondary_color,
595 overwrite_mode,
596 dead_character_mode);
597 }
598
607 void make_hole(widget_layout const& layout, quad const& box) const noexcept
608 {
609 return _override_alpha(layout.window_clipping_rectangle(), layout.to_window * box, 0.0f);
610 }
611
612 [[nodiscard]] friend bool overlaps(draw_context const& context, widget_layout const& layout) noexcept
613 {
614 return overlaps(context.scissor_rectangle, layout.window_clipping_rectangle());
615 }
616
617private:
618 vector_span<pipeline_box::vertex> *_box_vertices;
619 vector_span<pipeline_image::vertex> *_image_vertices;
620 vector_span<pipeline_SDF::vertex> *_sdf_vertices;
621 vector_span<pipeline_alpha::vertex> *_alpha_vertices;
622
623 void _override_alpha(aarectangle const& clipping_rectangle, quad box, float alpha) const noexcept;
624
625 void _draw_box(
626 aarectangle const& clipping_rectangle,
627 quad box,
628 quad_color const& fill_color,
629 quad_color const& border_color,
630 float border_width,
631 hi::corner_radii corner_radius) const noexcept;
632
633 void _draw_text(
634 aarectangle const& clipping_rectangle,
635 matrix3 const& transform,
636 shaped_text const& text,
637 std::optional<quad_color> color = {}) const noexcept;
638
639 void _draw_text(
640 aarectangle const& clipping_rectangle,
641 matrix3 const& transform,
642 text_shaper const& text,
643 std::optional<quad_color> color = {}) const noexcept;
644
645 void _draw_text_selection(
646 aarectangle const& clipping_rectangle,
647 matrix3 const& transform,
648 text_shaper const& text,
649 text_selection const& selection,
650 hi::color) const noexcept;
651
652 void _draw_text_insertion_cursor_empty(
653 aarectangle const& clipping_rectangle,
654 matrix3 const& transform,
655 text_shaper const& text,
656 hi::color color) const noexcept;
657
658 void _draw_text_insertion_cursor(
659 aarectangle const& clipping_rectangle,
660 matrix3 const& transform,
661 text_shaper const& text,
662 text_cursor cursor,
663 hi::color color,
664 bool show_flag) const noexcept;
665
666 void _draw_text_overwrite_cursor(
667 aarectangle const& clipping_rectangle,
668 matrix3 const& transform,
669 text_shaper::char_const_iterator it,
670 hi::color color) const noexcept;
671
672 void _draw_text_cursors(
673 aarectangle const& clipping_rectangle,
674 matrix3 const& transform,
675 text_shaper const& text,
676 text_cursor cursor,
677 hi::color primary_color,
678 hi::color secondary_color,
679 bool overwrite_mode,
680 bool dead_character_mode) const noexcept;
681
682 void _draw_glyph(aarectangle const& clipping_rectangle, quad const& box, quad_color const& color, glyph_ids const& glyph)
683 const noexcept;
684
685 [[nodiscard]] bool _draw_image(aarectangle const& clipping_rectangle, quad const& box, paged_image& image) const noexcept;
686};
687
688} // namespace hi::inline v1
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
This is a RGBA floating point color.
Definition color.hpp:39
Definition quad_color.hpp:9
Class which represents an axis-aligned rectangle.
Definition axis_aligned_rectangle.hpp:20
Definition quad.hpp:14
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:540
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:187
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:508
void draw_text(widget_layout const &layout, matrix3 const &transform, shaped_text const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:471
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:398
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:579
void draw_text(widget_layout const &layout, quad_color const &color, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:495
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:563
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:424
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:441
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:210
void make_hole(widget_layout const &layout, quad const &box) const noexcept
Make a hole in the user interface.
Definition draw_context.hpp:607
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:411
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:483
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:525
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:455
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:150
void draw_text(widget_layout const &layout, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:550
bool draw_image(widget_layout const &layout, quad const &box, paged_image &image) const noexcept
Draw an image.
Definition draw_context.hpp:383
Definition gfx_device_vulkan.hpp:21
This is a image that is uploaded into the texture atlas.
Definition paged_image.hpp:25
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
Definition widget_layout.hpp:18
constexpr aarectangle window_clipping_rectangle() const noexcept
Get the clipping rectangle in window coordinate system.
Definition widget_layout.hpp:113
matrix3 to_window
This matrix transforms local coordinates to window coordinates.
Definition widget_layout.hpp:36
T right(T... args)
T max(T... args)