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"
11#include "../geometry/axis_aligned_rectangle.hpp"
12#include "../geometry/matrix.hpp"
13#include "../geometry/corner_radii.hpp"
14#include "../geometry/identity.hpp"
15#include "../geometry/transform.hpp"
16#include "../geometry/circle.hpp"
17#include "../geometry/line_end_cap.hpp"
18#include "../text/text_cursor.hpp"
19#include "../text/text_selection.hpp"
20#include "../text/text_shaper.hpp"
21#include "../color/color.hpp"
22#include "../color/quad_color.hpp"
23#include "../widgets/widget_layout.hpp"
24#include "../vspan.hpp"
25
26namespace hi::inline v1 {
27class gfx_device;
28class gfx_device_vulkan;
29class shaped_text;
30class glyph_ids;
31struct paged_image;
32
35enum class border_side {
38 on,
39
42 inside,
43
46 outside
47};
48
52public:
53 gfx_device_vulkan &device;
54
58
62
66
69 hi::subpixel_orientation subpixel_orientation;
70
74
77 utc_nanoseconds display_time_point;
78
79 draw_context(draw_context const &rhs) noexcept = default;
80 draw_context(draw_context &&rhs) noexcept = default;
81 draw_context &operator=(draw_context const &rhs) noexcept = default;
82 draw_context &operator=(draw_context &&rhs) noexcept = default;
83 ~draw_context() = default;
84
86 gfx_device_vulkan &device,
87 vspan<pipeline_box::vertex> &boxVertices,
88 vspan<pipeline_image::vertex> &imageVertices,
89 vspan<pipeline_SDF::vertex> &sdfVertices) noexcept;
90
93 operator bool() const noexcept
94 {
95 return frame_buffer_index != std::numeric_limits<size_t>::max();
96 }
97
109 widget_layout const &layout,
110 quad const &box,
111 quad_color const &fill_color,
112 quad_color const &border_color,
113 float border_width,
114 hi::border_side border_side,
115 hi::corner_radii const &corner_radius = {}) const noexcept
116 {
117 // clang-format off
118 hilet border_radius = border_width * 0.5f;
119 hilet box_ =
120 border_side == hi::border_side::inside ? box - border_radius :
121 border_side == hi::border_side::outside ? box + border_radius :
122 box;
123 hilet corner_radius_ =
124 border_side == hi::border_side::inside ? corner_radius - border_radius :
125 border_side == hi::border_side::outside ? corner_radius + border_radius :
126 corner_radius;
127 // clang-format on
128
129 return _draw_box(
131 layout.to_window * box_,
132 fill_color,
133 border_color,
134 layout.to_window * border_width,
135 layout.to_window * corner_radius_);
136 }
137
149 widget_layout const &layout,
150 aarectangle const &clipping_rectangle,
151 quad const &box,
152 quad_color const &fill_color,
153 quad_color const &border_color,
154 float border_width,
155 hi::border_side border_side,
156 hi::corner_radii const &corner_radius = {}) const noexcept
157 {
158 // clang-format off
159 hilet border_radius = border_width * 0.5f;
160 hilet box_ =
161 border_side == hi::border_side::inside ? box - border_radius :
162 border_side == hi::border_side::outside ? box + border_radius :
163 box;
164 hilet corner_radius_ =
165 border_side == hi::border_side::inside ? corner_radius - border_radius :
166 border_side == hi::border_side::outside ? corner_radius + border_radius :
167 corner_radius;
168 // clang-format on
169
170 return _draw_box(
171 layout.window_clipping_rectangle(clipping_rectangle),
172 layout.to_window * box_,
173 fill_color,
174 border_color,
175 layout.to_window * border_width,
176 layout.to_window * corner_radius_);
177 }
186 widget_layout const &layout,
187 quad const &box,
188 quad_color const &fill_color,
189 hi::corner_radii const &corner_radius = {}) const noexcept
190 {
191 return _draw_box(
193 layout.to_window * box,
194 fill_color,
195 fill_color,
196 0.0f,
197 layout.to_window * corner_radius);
198 }
199
209 widget_layout const &layout,
210 aarectangle const &clipping_rectangle,
211 quad const &box,
212 quad_color const &fill_color,
213 hi::corner_radii const &corner_radius = {}) const noexcept
214 {
215 return _draw_box(
216 layout.window_clipping_rectangle(clipping_rectangle),
217 layout.to_window * box,
218 fill_color,
219 fill_color,
220 0.0f,
221 layout.to_window * corner_radius);
222 }
223
224 [[nodiscard]] constexpr static rectangle
225 make_rectangle(line_segment const &line, float width, line_end_cap c1, line_end_cap c2) noexcept
226 {
227 auto right = line.direction();
228
229 hilet radius = width * 0.5f;
230 hilet n = normal(right, 0.0f);
231 hilet up = n * width;
232 hilet t = normalize(right);
233
234 auto origin = line.origin() - n * radius;
235
236 // Extend the line by the radius for rounded end-caps.
237 hilet radius_offset = t * radius;
238 if (c1 == line_end_cap::round) {
239 origin -= radius_offset;
240 right += radius_offset;
241 }
242 if (c2 == line_end_cap::round) {
243 right += radius_offset;
244 }
245
246 return rectangle{origin, right, up};
247 }
248
249 [[nodiscard]] constexpr static corner_radii make_corner_radii(float width, line_end_cap c1, line_end_cap c2) noexcept
250 {
251 auto r = f32x4::broadcast(width * 0.5f);
252
253 if (c1 == line_end_cap::flat) {
254 r = zero<0b0101>(r);
255 }
256 if (c2 == line_end_cap::flat) {
257 r = zero<0b1010>(r);
258 }
259
260 return corner_radii{r};
261 }
262
263 void draw_line(
264 widget_layout const &layout,
265 line_segment const &line,
266 float width,
267 quad_color const &fill_color,
268 line_end_cap c1 = line_end_cap::flat,
269 line_end_cap c2 = line_end_cap::flat) const noexcept
270 {
271 hilet line_ = layout.to_window * line;
272 hilet width_ = layout.to_window * width;
273
274 hilet box = make_rectangle(line_, width_, c1, c2);
275 hilet corners = make_corner_radii(width_, c1, c2);
276
277 return _draw_box(layout.window_clipping_rectangle(), box, fill_color, fill_color, 0.0f, corners);
278 }
279
280 void draw_line(
281 widget_layout const &layout,
282 aarectangle const &clipping_rectangle,
283 line_segment const &line,
284 float width,
285 quad_color const &fill_color,
286 line_end_cap c1 = line_end_cap::flat,
287 line_end_cap c2 = line_end_cap::flat) const noexcept
288 {
289 hi_axiom(width != 0.0f);
290 hilet line_ = layout.to_window * line;
291 hilet width_ = layout.to_window * width;
292
293 hilet box = make_rectangle(line_, width_, c1, c2);
294 hilet corners = make_corner_radii(width_, c1, c2);
295
296 return _draw_box(layout.window_clipping_rectangle(clipping_rectangle), box, fill_color, fill_color, 0.0f, corners);
297 }
298
299 [[nodiscard]] constexpr static rectangle make_rectangle(hi::circle const &circle) noexcept
300 {
301 hilet circle_ = f32x4{circle};
302 hilet origin = point3{circle_.xyz1() - circle_.ww00()};
303 hilet right = vector3{circle_.w000() * 2.0f};
304 hilet up = vector3{circle_._0w00() * 2.0f};
305 return rectangle{origin, right, up};
306 }
307
308 [[nodiscard]] constexpr static corner_radii make_corner_radii(hi::circle const &circle) noexcept
309 {
310 return corner_radii{f32x4{circle}.wwww()};
311 }
312
313 void draw_circle(widget_layout const &layout, hi::circle const &circle, quad_color const &fill_color) const noexcept
314 {
315 hilet box = layout.to_window * make_rectangle(circle);
316 hilet corners = layout.to_window * make_corner_radii(circle);
317 return _draw_box(layout.window_clipping_rectangle(), box, fill_color, fill_color, 0.0f, corners);
318 }
319
320 void draw_circle(
321 widget_layout const &layout,
322 aarectangle const clipping_rectangle,
323 hi::circle const &circle,
324 quad_color const &fill_color) const
325 {
326 hilet box = layout.to_window * make_rectangle(circle);
327 hilet corners = layout.to_window * make_corner_radii(circle);
328 return _draw_box(layout.window_clipping_rectangle(clipping_rectangle), box, fill_color, fill_color, 0.0f, corners);
329 }
330
331 void draw_circle(
332 widget_layout const &layout,
333 hi::circle const &circle,
334 quad_color const &fill_color,
335 quad_color const &border_color,
336 float border_width,
337 hi::border_side border_side) const noexcept
338 {
339 // clang-format off
340 hilet circle_ =
341 border_side == hi::border_side::inside ? circle - border_width * 0.5f :
342 border_side == hi::border_side::outside ? circle + border_width * 0.5f :
343 circle;
344 // clang-format on
345
346 hilet box = layout.to_window * make_rectangle(circle_);
347 hilet corners = layout.to_window * make_corner_radii(circle_);
348 return _draw_box(layout.window_clipping_rectangle(), box, fill_color, border_color, border_width, corners);
349 }
350
351 void draw_circle(
352 widget_layout const &layout,
353 aarectangle const &clipping_rectangle,
354 hi::circle const &circle,
355 quad_color const &fill_color,
356 quad_color const &border_color,
357 float border_width,
358 hi::border_side border_side) const noexcept
359 {
360 // clang-format off
361 hilet circle_ =
362 border_side == hi::border_side::inside ? circle - border_width * 0.5f :
363 border_side == hi::border_side::outside ? circle + border_width * 0.5f :
364 circle;
365 // clang-format on
366
367 hilet box = layout.to_window * make_rectangle(circle_);
368 hilet corners = layout.to_window * make_corner_radii(circle_);
369 return _draw_box(
370 layout.window_clipping_rectangle(clipping_rectangle), box, fill_color, border_color, border_width, corners);
371 }
372
381 [[nodiscard]] bool draw_image(widget_layout const &layout, quad const &box, paged_image &image) const noexcept
382 {
383 return _draw_image(layout.window_clipping_rectangle(), layout.to_window * box, image);
384 }
385
395 [[nodiscard]] bool
396 draw_image(widget_layout const &layout, aarectangle const &clipping_rectangle, quad const &box, paged_image &image)
397 const noexcept
398 {
399 return _draw_image(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * box, image);
400 }
401
409 void draw_glyph(widget_layout const &layout, quad const &box, quad_color const &color, glyph_ids const &glyph) const noexcept
410 {
411 return _draw_glyph(layout.window_clipping_rectangle(), layout.to_window * box, color, glyph);
412 }
413
423 widget_layout const &layout,
424 aarectangle clipping_rectangle,
425 quad const &box,
426 quad_color const &color,
427 glyph_ids const &glyph) const noexcept
428 {
429 return _draw_glyph(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * box, color, glyph);
430 }
431
439 void draw_text(widget_layout const &layout, matrix3 const &transform, quad_color const &color, shaped_text const &text)
440 const noexcept
441 {
442 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text, color);
443 }
444
454 widget_layout const &layout,
455 aarectangle const &clipping_rectangle,
456 matrix3 const &transform,
457 quad_color const &color,
458 shaped_text const &text) const noexcept
459 {
460 return _draw_text(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * transform, text, color);
461 }
462
469 void draw_text(widget_layout const &layout, matrix3 const &transform, shaped_text const &text) const noexcept
470 {
471 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text);
472 }
473
481 void draw_text(widget_layout const &layout, matrix3 const &transform, quad_color const &color, text_shaper const &text)
482 const noexcept
483 {
484 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text, color);
485 }
486
493 void draw_text(widget_layout const &layout, quad_color const &color, text_shaper const &text) const noexcept
494 {
495 return _draw_text(layout.window_clipping_rectangle(), layout.to_window, text, color);
496 }
497
507 widget_layout const &layout,
508 aarectangle const &clipping_rectangle,
509 matrix3 const &transform,
510 quad_color const &color,
511 text_shaper const &text) const noexcept
512 {
513 return _draw_text(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window * transform, text, color);
514 }
515
524 widget_layout const &layout,
525 aarectangle const &clipping_rectangle,
526 quad_color const &color,
527 text_shaper const &text) const noexcept
528 {
529 return _draw_text(layout.window_clipping_rectangle(clipping_rectangle), layout.to_window, text, color);
530 }
531
538 void draw_text(widget_layout const &layout, matrix3 const &transform, text_shaper const &text) const noexcept
539 {
540 return _draw_text(layout.window_clipping_rectangle(), layout.to_window * transform, text);
541 }
542
548 void draw_text(widget_layout const &layout, text_shaper const &text) const noexcept
549 {
550 return _draw_text(layout.window_clipping_rectangle(), layout.to_window, text);
551 }
552
560 void
561 draw_text_selection(widget_layout const &layout, text_shaper const &text, text_selection const &selection, hi::color color)
562 const noexcept
563 {
564 return _draw_text_selection(layout.window_clipping_rectangle(), layout.to_window, text, selection, color);
565 }
566
578 widget_layout const &layout,
579 text_shaper const &text,
580 text_cursor cursor,
581 hi::color primary_color,
582 hi::color secondary_color,
583 bool overwrite_mode,
584 bool dead_character_mode) const noexcept
585 {
586 return _draw_text_cursors(
588 layout.to_window,
589 text,
590 cursor,
591 primary_color,
592 secondary_color,
593 overwrite_mode,
594 dead_character_mode);
595 }
596
597 [[nodiscard]] friend bool overlaps(draw_context const &context, widget_layout const &layout) noexcept
598 {
599 return overlaps(context.scissor_rectangle, layout.window_clipping_rectangle());
600 }
601
602private:
603 vspan<pipeline_box::vertex> *_box_vertices;
604 vspan<pipeline_image::vertex> *_image_vertices;
605 vspan<pipeline_SDF::vertex> *_sdf_vertices;
606
607 void _draw_box(
608 aarectangle const &clipping_rectangle,
609 quad box,
610 quad_color const &fill_color,
611 quad_color const &border_color,
612 float border_width,
613 hi::corner_radii corner_radius) const noexcept;
614
615 void _draw_text(
616 aarectangle const &clipping_rectangle,
617 matrix3 const &transform,
618 shaped_text const &text,
619 std::optional<quad_color> color = {}) const noexcept;
620
621 void _draw_text(
622 aarectangle const &clipping_rectangle,
623 matrix3 const &transform,
624 text_shaper const &text,
625 std::optional<quad_color> color = {}) const noexcept;
626
627 void _draw_text_selection(
628 aarectangle const &clipping_rectangle,
629 matrix3 const &transform,
630 text_shaper const &text,
631 text_selection const &selection,
632 hi::color) const noexcept;
633
634 void _draw_text_insertion_cursor_empty(
635 aarectangle const &clipping_rectangle,
636 matrix3 const &transform,
637 text_shaper const &text,
638 hi::color color) const noexcept;
639
640 void _draw_text_insertion_cursor(
641 aarectangle const &clipping_rectangle,
642 matrix3 const &transform,
643 text_shaper const &text,
644 text_cursor cursor,
645 hi::color color,
646 bool show_flag) const noexcept;
647
648 void _draw_text_overwrite_cursor(
649 aarectangle const &clipping_rectangle,
650 matrix3 const &transform,
651 text_shaper::char_const_iterator it,
652 hi::color color) const noexcept;
653
654 void _draw_text_cursors(
655 aarectangle const &clipping_rectangle,
656 matrix3 const &transform,
657 text_shaper const &text,
658 text_cursor cursor,
659 hi::color primary_color,
660 hi::color secondary_color,
661 bool overwrite_mode,
662 bool dead_character_mode) const noexcept;
663
664 void _draw_glyph(aarectangle const &clipping_rectangle, quad const &box, quad_color const &color, glyph_ids const &glyph)
665 const noexcept;
666
667 [[nodiscard]] bool _draw_image(aarectangle const &clipping_rectangle, quad const &box, paged_image &image) const noexcept;
668};
669
670} // 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:37
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:51
std::size_t frame_buffer_index
The frame buffer index of the image we are currently rendering.
Definition draw_context.hpp:57
void draw_text(widget_layout const &layout, matrix3 const &transform, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:538
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:185
float saturation
The tone-mapper's saturation.
Definition draw_context.hpp:73
utc_nanoseconds display_time_point
The time when the drawing will appear on the screen.
Definition draw_context.hpp:77
aarectangle scissor_rectangle
This is the rectangle of the window that is being redrawn.
Definition draw_context.hpp:61
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:506
void draw_text(widget_layout const &layout, matrix3 const &transform, shaped_text const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:469
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:396
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:577
void draw_text(widget_layout const &layout, quad_color const &color, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:493
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:561
color background_color
The background color to clear the window with.
Definition draw_context.hpp:65
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:422
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:439
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:208
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:409
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:481
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:108
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:523
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:453
hi::subpixel_orientation subpixel_orientation
The subpixel orientation for rendering glyphs.
Definition draw_context.hpp:69
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:148
void draw_text(widget_layout const &layout, text_shaper const &text) const noexcept
Draw shaped text.
Definition draw_context.hpp:548
bool draw_image(widget_layout const &layout, quad const &box, paged_image &image) const noexcept
Draw an image.
Definition draw_context.hpp:381
Definition gfx_device_vulkan.hpp:20
This is a image that is uploaded into the texture atlas.
Definition paged_image.hpp:25
A set of glyph-ids of a font which composites into a single glyph.
Definition glyph_ids.hpp:127
Definition text_cursor.hpp:18
Definition text_selection.hpp:17
Text shaper.
Definition text_shaper.hpp:39
Definition vspan.hpp:134
Definition widget_layout.hpp:17
constexpr aarectangle window_clipping_rectangle() const noexcept
Get the clipping rectangle in window coordinate system.
Definition widget_layout.hpp:112
matrix3 to_window
This matrix transforms local coordinates to window coordinates.
Definition widget_layout.hpp:35
T right(T... args)
T max(T... args)