HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
axis_aligned_rectangle.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2021-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
9#pragma once
10
11#include "alignment.hpp"
12#include "extent.hpp"
13#include "point.hpp"
14#include "margins.hpp"
15#include "../SIMD/module.hpp"
16#include "../utility/module.hpp"
17#include "../concurrency/module.hpp"
18#include <concepts>
19#include <mutex>
20
21namespace hi { inline namespace v1 {
22namespace geo {
26template<typename T>
28public:
29 using value_type = T;
30 using array_type = simd<value_type, 4>;
31
32 constexpr axis_aligned_rectangle() noexcept : v() {}
33 constexpr axis_aligned_rectangle(axis_aligned_rectangle const& rhs) noexcept = default;
34 constexpr axis_aligned_rectangle& operator=(axis_aligned_rectangle const& rhs) noexcept = default;
35 constexpr axis_aligned_rectangle(axis_aligned_rectangle&& rhs) noexcept = default;
36 constexpr axis_aligned_rectangle& operator=(axis_aligned_rectangle&& rhs) noexcept = default;
37
40 [[nodiscard]] constexpr static axis_aligned_rectangle large() noexcept
41 {
42 return {
43 point<value_type, 2>{-large_number_v<value_type>, -large_number_v<value_type>},
44 point<value_type, 2>{large_number_v<value_type>, large_number_v<value_type>}};
45 }
46
47 constexpr explicit axis_aligned_rectangle(array_type const& other) noexcept : v(other)
48 {
50 }
51
59 constexpr axis_aligned_rectangle(value_type x, value_type y, value_type width, value_type height) noexcept :
60 v{x, y, x + width, y + height}
61 {
63 }
64
69 constexpr explicit axis_aligned_rectangle(extent<value_type, 2> const& extent) noexcept :
70 v(static_cast<array_type>(extent)._00xy())
71 {
73 }
74
79 constexpr axis_aligned_rectangle(point<value_type, 2> const& p0, point<value_type, 2> const& p3) noexcept :
80 v(static_cast<array_type>(p0).xy00() + static_cast<array_type>(p3)._00xy())
81 {
82 hi_axiom(p0.holds_invariant());
83 hi_axiom(p3.holds_invariant());
85 }
86
94 constexpr axis_aligned_rectangle(point<value_type, 2> const& p0, extent<value_type, 2> const& extent) noexcept :
95 v(static_cast<array_type>(p0).xyxy() + static_cast<array_type>(extent)._00xy())
96 {
98 }
99
100 constexpr explicit operator array_type() const noexcept
101 {
102 return v;
103 }
104
108 [[nodiscard]] constexpr bool holds_invariant() const noexcept
109 {
110 return (v <= v.zwzw()).mask() == 0b1111;
111 }
112
115 [[nodiscard]] constexpr bool empty() const noexcept
116 {
117 return (v == v.zwxy()).mask() == 0b1111;
118 }
119
122 [[nodiscard]] constexpr explicit operator bool() const noexcept
123 {
124 return not empty();
125 }
126
133 {
134 return *this = *this | rhs;
135 }
136
142 constexpr axis_aligned_rectangle& operator|=(point<value_type, 2> const& rhs) noexcept
143 {
144 return *this = *this | rhs;
145 }
146
147 [[nodiscard]] constexpr point<value_type, 2> operator[](std::size_t i) const noexcept
148 {
149 switch (i) {
150 case 0:
151 return point<value_type, 2>{v.xy01()};
152 case 1:
153 return point<value_type, 2>{v.zy01()};
154 case 2:
155 return point<value_type, 2>{v.xw01()};
156 case 3:
157 return point<value_type, 2>{v.zw01()};
158 default:
160 }
161 }
162
163 template<int I>
164 [[nodiscard]] constexpr friend point<value_type, 2> get(axis_aligned_rectangle const& rhs) noexcept
165 {
166 if constexpr (I == 0) {
167 return point<value_type, 2>{rhs.v.xy01()};
168 } else if constexpr (I == 1) {
169 return point<value_type, 2>{rhs.v.zy01()};
170 } else if constexpr (I == 2) {
171 return point<value_type, 2>{rhs.v.xw01()};
172 } else if constexpr (I == 3) {
173 return point<value_type, 2>{rhs.v.zw01()};
174 } else {
176 }
177 }
178
183 [[nodiscard]] constexpr extent<value_type, 2> size() const noexcept
184 {
185 return extent<value_type, 2>{v.zwzw() - v};
186 }
187
188 [[nodiscard]] constexpr value_type x() const noexcept
189 {
190 return v.x();
191 }
192
193 [[nodiscard]] constexpr value_type y() const noexcept
194 {
195 return v.y();
196 }
197
198 [[nodiscard]] constexpr value_type width() const noexcept
199 {
200 return (v.zwzw() - v).x();
201 }
202
203 [[nodiscard]] constexpr value_type height() const noexcept
204 {
205 return (v.zwzw() - v).y();
206 }
207
208 [[nodiscard]] constexpr value_type bottom() const noexcept
209 {
210 return v.y();
211 }
212
213 [[nodiscard]] constexpr value_type top() const noexcept
214 {
215 return v.w();
216 }
217
218 [[nodiscard]] constexpr value_type left() const noexcept
219 {
220 return v.x();
221 }
222
223 [[nodiscard]] constexpr value_type right() const noexcept
224 {
225 return v.z();
226 }
227
230 [[nodiscard]] constexpr value_type middle() const noexcept
231 {
232 return (bottom() + top()) / value_type{2};
233 }
234
237 [[nodiscard]] constexpr value_type center() const noexcept
238 {
239 return (left() + right()) / value_type{2};
240 }
241
244 [[nodiscard]] constexpr friend point<value_type, 2> midpoint(axis_aligned_rectangle const& rhs) noexcept
245 {
246 return midpoint(get<0>(rhs), get<3>(rhs));
247 }
248
249 constexpr axis_aligned_rectangle& set_width(value_type newWidth) noexcept
250 {
251 v = v.xyxw() + array_type{value_type{0}, value_type{0}, newWidth, value_type{0}};
252 return *this;
253 }
254
255 constexpr axis_aligned_rectangle& set_height(value_type newHeight) noexcept
256 {
257 v = v.xyzy() + array_type{value_type{0}, value_type{0}, value_type{0}, newHeight};
258 return *this;
259 }
260
265 [[nodiscard]] constexpr bool contains(point<value_type, 2> const& rhs) const noexcept
266 {
267 // No need to check with empty due to half open range check.
268 return (static_cast<array_type>(rhs).xyxy() >= v).mask() == 0b0011;
269 }
270
276 [[nodiscard]] constexpr bool contains(point<value_type, 3> const& rhs) const noexcept
277 {
278 return contains(point<value_type, 2>{rhs});
279 }
280
287 [[nodiscard]] friend constexpr axis_aligned_rectangle
288 align(axis_aligned_rectangle haystack, extent<value_type, 2> needle, alignment alignment) noexcept
289 {
290 auto x = value_type{0};
291 if (alignment == horizontal_alignment::left) {
292 x = haystack.left();
293
294 } else if (alignment == horizontal_alignment::right) {
295 x = haystack.right() - needle.width();
296
297 } else if (alignment == horizontal_alignment::center) {
298 x = haystack.center() - needle.width() / value_type{2};
299
300 } else {
302 }
303
304 auto y = value_type{0};
305 if (alignment == vertical_alignment::bottom) {
306 y = haystack.bottom();
307
308 } else if (alignment == vertical_alignment::top) {
309 y = haystack.top() - needle.height();
310
311 } else if (alignment == vertical_alignment::middle) {
312 y = haystack.middle() - needle.height() / value_type{2};
313
314 } else {
316 }
317
318 return {point<value_type, 2>{x, y}, needle};
319 }
320
327 [[nodiscard]] friend constexpr axis_aligned_rectangle
328 align(axis_aligned_rectangle haystack, axis_aligned_rectangle needle, alignment alignment) noexcept
329 {
330 return align(haystack, needle.size(), alignment);
331 }
332
335 [[nodiscard]] static constexpr axis_aligned_rectangle
337 {
338 return align(outside, inside, alignment);
339 }
340
341 [[nodiscard]] friend constexpr bool operator==(axis_aligned_rectangle const& lhs, axis_aligned_rectangle const& rhs) noexcept
342 {
343 return equal(lhs.v, rhs.v);
344 }
345
346 [[nodiscard]] friend constexpr bool overlaps(axis_aligned_rectangle const& lhs, axis_aligned_rectangle const& rhs) noexcept
347 {
348 if (lhs.empty() or rhs.empty()) {
349 return false;
350 }
351
352 hilet rhs_swap = rhs.v.zwxy();
353
354 // lhs.p0.x > rhs.p3.x | lhs.p0.y > rhs.p3.y
355 if (((lhs.v > rhs_swap).mask() & 0b0011) != 0) {
356 return false;
357 }
358
359 // lhs.p3.x < rhs.p0.x | lhs.p3.y < rhs.p0.y
360 if (((lhs.v < rhs_swap).mask() & 0b1100) != 0) {
361 return false;
362 }
363
364 return true;
365 }
366
367 [[nodiscard]] friend constexpr axis_aligned_rectangle
368 operator|(axis_aligned_rectangle const& lhs, axis_aligned_rectangle const& rhs) noexcept
369 {
370 if (!lhs) {
371 return rhs;
372 } else if (!rhs) {
373 return lhs;
374 } else {
375 return axis_aligned_rectangle{min(get<0>(lhs), get<0>(rhs)), max(get<3>(lhs), get<3>(rhs))};
376 }
377 }
378
379 [[nodiscard]] friend constexpr axis_aligned_rectangle
380 operator|(axis_aligned_rectangle const& lhs, point<value_type, 2> const& rhs) noexcept
381 {
382 if (!lhs) {
383 return axis_aligned_rectangle{rhs, rhs};
384 } else {
385 return axis_aligned_rectangle{min(get<0>(lhs), rhs), max(get<3>(lhs), rhs)};
386 }
387 }
388
394 [[nodiscard]] friend constexpr axis_aligned_rectangle operator*(axis_aligned_rectangle const& lhs, value_type rhs) noexcept
395 {
396 hilet new_extent = lhs.size() * rhs;
397 hilet diff = vector<value_type, 2>{new_extent} - vector<value_type, 2>{lhs.size()};
398 hilet offset = diff * 0.5f;
399
400 hilet p0 = get<0>(lhs) - offset;
401 hilet p3 = max(get<3>(lhs) + offset, p0);
402 return axis_aligned_rectangle{p0, p3};
403 }
404
411 [[nodiscard]] friend constexpr axis_aligned_rectangle operator+(axis_aligned_rectangle const& lhs, value_type rhs) noexcept
412 {
413 return axis_aligned_rectangle{lhs.v + neg<0b0011>(array_type::broadcast(rhs))};
414 }
415
422 [[nodiscard]] friend constexpr axis_aligned_rectangle operator-(axis_aligned_rectangle const& lhs, value_type rhs) noexcept
423 {
424 return lhs + -rhs;
425 }
426
433 [[nodiscard]] friend constexpr axis_aligned_rectangle operator-(axis_aligned_rectangle const& lhs, geo::margins<value_type> rhs) noexcept
434 {
435 auto lhs_ = static_cast<simd<value_type, 4>>(lhs);
436 auto rhs_ = static_cast<simd<value_type, 4>>(rhs);
437
438 // The left and bottom margin moves p0 of lhs in positive directions.
439 // the right and top margin moves p3 of lhs in negative directions.
440 return axis_aligned_rectangle{lhs_ + neg<0b1100>(rhs_)};
441 }
442
443 [[nodiscard]] friend constexpr axis_aligned_rectangle round(axis_aligned_rectangle const& rhs) noexcept
444 requires std::is_same_v<value_type, float>
445 {
446 hilet p0 = round(get<0>(rhs));
447 hilet size = round(rhs.size());
448 return axis_aligned_rectangle{p0, size};
449 }
450
453 [[nodiscard]] friend constexpr axis_aligned_rectangle ceil(axis_aligned_rectangle const& rhs) noexcept
454 requires std::is_same_v<value_type, float>
455 {
456 hilet p0 = floor(get<0>(rhs));
457 hilet p3 = ceil(get<3>(rhs));
458 return axis_aligned_rectangle{p0, p3};
459 }
460
463 [[nodiscard]] friend constexpr axis_aligned_rectangle
464 ceil(axis_aligned_rectangle const& lhs, extent<value_type, 2> const& rhs) noexcept
465 {
466 hilet p0 = floor(get<0>(lhs), rhs);
467 hilet p3 = ceil(get<3>(lhs), rhs);
468 return axis_aligned_rectangle{p0, p3};
469 }
470
473 [[nodiscard]] friend constexpr axis_aligned_rectangle floor(axis_aligned_rectangle const& rhs) noexcept
474 requires std::is_same_v<value_type, float>
475 {
476 hilet p0 = ceil(get<0>(rhs));
477 hilet p3 = floor(get<3>(rhs));
478 return axis_aligned_rectangle{p0, p3};
479 }
480
481 [[nodiscard]] friend constexpr axis_aligned_rectangle bounding_rectangle(axis_aligned_rectangle const& rhs) noexcept
482 {
483 return rhs;
484 }
485
489 [[nodiscard]] friend constexpr axis_aligned_rectangle
491 {
492 hilet p0 = max(get<0>(lhs), get<0>(rhs));
493 hilet p3 = min(get<3>(lhs), get<3>(rhs));
494 if (p0.x() < p3.x() && p0.y() < p3.y()) {
495 return {p0, p3};
496 } else {
497 return {};
498 }
499 }
500
501 [[nodiscard]] constexpr friend value_type
502 distance(axis_aligned_rectangle const& lhs, point<value_type, 2> const& rhs) noexcept
503 {
504 hilet lhs_ = static_cast<array_type>(lhs);
505 hilet rhs_ = static_cast<array_type>(rhs);
506 // Only (x,y) of subsequent calculations are valid, (z,w) have garbage values.
507 hilet closest_point = max(min(rhs_, lhs_.zwzw()), lhs_);
508 hilet v_closest_point = closest_point - rhs_;
509 return hypot<0b0011>(v_closest_point);
510 }
511
512private:
518 array_type v;
519};
520
521} // namespace geo
522
523using aarectangle = geo::axis_aligned_rectangle<float>;
524using aarectanglei = geo::axis_aligned_rectangle<int>;
525
533[[nodiscard]] aarectangle fit(aarectangle const& bounds, aarectangle const& rectangle) noexcept;
534
542[[nodiscard]] aarectanglei fit(aarectanglei const& bounds, aarectanglei const& rectangle) noexcept;
543
544template<>
545[[nodiscard]] constexpr aarectanglei narrow_cast(aarectangle const& rhs) noexcept
546{
547 return {narrow_cast<int>(rhs.x()), narrow_cast<int>(rhs.y()), narrow_cast<int>(rhs.width()), narrow_cast<int>(rhs.height())};
548}
549
550template<>
551[[nodiscard]] constexpr aarectangle narrow_cast(aarectanglei const& rhs) noexcept
552{
553 return {
554 narrow_cast<float>(rhs.x()),
555 narrow_cast<float>(rhs.y()),
556 narrow_cast<float>(rhs.width()),
557 narrow_cast<float>(rhs.height())};
558}
559
560}} // namespace hi::v1
561
562template<typename T>
563class std::atomic<hi::geo::axis_aligned_rectangle<T>> {
564public:
565 using value_type = hi::geo::axis_aligned_rectangle<T>;
566 static constexpr bool is_always_lock_free = false;
567
568 constexpr atomic() noexcept = default;
569 atomic(atomic const&) = delete;
570 atomic(atomic&&) = delete;
571 atomic& operator=(atomic const&) = delete;
572 atomic& operator=(atomic&&) = delete;
573
574 constexpr atomic(value_type const& rhs) noexcept : _value(rhs) {}
575 atomic& operator=(value_type const& rhs) noexcept
576 {
577 store(rhs);
578 return *this;
579 }
580
581 operator value_type() const noexcept
582 {
583 return load();
584 }
585
586 [[nodiscard]] bool is_lock_free() const noexcept
587 {
588 return is_always_lock_free;
589 }
590
591 void store(value_type desired, std::memory_order = std::memory_order_seq_cst) noexcept
592 {
593 hilet lock = std::scoped_lock(_mutex);
594 _value = desired;
595 }
596
597 value_type load(std::memory_order = std::memory_order_seq_cst) const noexcept
598 {
599 hilet lock = std::scoped_lock(_mutex);
600 return _value;
601 }
602
603 value_type exchange(value_type desired, std::memory_order = std::memory_order_seq_cst) noexcept
604 {
605 hilet lock = std::scoped_lock(_mutex);
606 return std::exchange(_value, desired);
607 }
608
609 bool compare_exchange_weak(value_type& expected, value_type desired, std::memory_order, std::memory_order) noexcept
610 {
611 hilet lock = std::scoped_lock(_mutex);
612 if (_value == expected) {
613 _value = desired;
614 return true;
615 } else {
616 expected = _value;
617 return false;
618 }
619 }
620
622 value_type& expected,
623 value_type desired,
624 std::memory_order success,
625 std::memory_order failure) noexcept
626 {
627 return compare_exchange_weak(expected, desired, success, failure);
628 }
629
630 bool
631 compare_exchange_weak(value_type& expected, value_type desired, std::memory_order order = std::memory_order_seq_cst) noexcept
632 {
633 return compare_exchange_weak(expected, desired, order, order);
634 }
635
637 value_type& expected,
638 value_type desired,
639 std::memory_order order = std::memory_order_seq_cst) noexcept
640 {
641 return compare_exchange_strong(expected, desired, order, order);
642 }
643
644 value_type fetch_or(value_type arg, std::memory_order = std::memory_order_seq_cst) noexcept
645 {
646 hilet lock = std::scoped_lock(_mutex);
647 auto tmp = _value;
648 _value = tmp | arg;
649 return tmp;
650 }
651
652 value_type operator|=(value_type arg) noexcept
653 {
654 hilet lock = std::scoped_lock(_mutex);
655 return _value |= arg;
656 }
657
658private:
659 value_type _value;
660 mutable hi::unfair_mutex _mutex;
661};
662
663template<typename CharT>
664struct std::formatter<hi::geo::axis_aligned_rectangle<float>, CharT> {
665 auto parse(auto& pc)
666 {
667 return pc.end();
668 }
669
670 auto format(hi::geo::axis_aligned_rectangle<float> const& t, auto& fc)
671 {
672 return std::vformat_to(fc.out(), "{}:{}", std::make_format_args(get<0>(t), t.size()));
673 }
674};
675
676template<typename CharT>
677struct std::formatter<hi::geo::axis_aligned_rectangle<int>, CharT> {
678 auto parse(auto& pc)
679 {
680 return pc.end();
681 }
682
683 auto format(hi::geo::axis_aligned_rectangle<int> const& t, auto& fc)
684 {
685 return std::vformat_to(fc.out(), "{}:{}", std::make_format_args(get<0>(t), t.size()));
686 }
687};
Defined the geo::extent, extent2 and extent3 types.
types and utilities for alignment.
#define hi_static_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:323
#define hi_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:279
#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
@ other
The gui_event does not have associated data.
@ rectangle
The gui_event has rectangle data.
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
aarectangle fit(aarectangle const &bounds, aarectangle const &rectangle) noexcept
Make a rectangle fit inside bounds.
@ inside
The border is drawn inside the edge of a quad.
@ outside
The border is drawn outside the edge of a quad.
Class which represents an axis-aligned rectangle.
Definition axis_aligned_rectangle.hpp:27
static constexpr axis_aligned_rectangle large() noexcept
Create a large axis aligned rectangle.
Definition axis_aligned_rectangle.hpp:40
friend constexpr axis_aligned_rectangle operator-(axis_aligned_rectangle const &lhs, value_type rhs) noexcept
Shrink the rectangle for the same amount in all directions.
Definition axis_aligned_rectangle.hpp:422
static constexpr axis_aligned_rectangle _align(axis_aligned_rectangle outside, axis_aligned_rectangle inside, alignment alignment) noexcept
Need to call the hidden friend function from within another class.
Definition axis_aligned_rectangle.hpp:336
friend constexpr axis_aligned_rectangle intersect(axis_aligned_rectangle const &lhs, axis_aligned_rectangle const &rhs) noexcept
Return the overlapping part of two rectangles.
Definition axis_aligned_rectangle.hpp:490
constexpr axis_aligned_rectangle(point< value_type, 2 > const &p0, extent< value_type, 2 > const &extent) noexcept
Create a rectangle from the size.
Definition axis_aligned_rectangle.hpp:94
friend constexpr axis_aligned_rectangle align(axis_aligned_rectangle haystack, axis_aligned_rectangle needle, alignment alignment) noexcept
Align a rectangle within another rectangle.
Definition axis_aligned_rectangle.hpp:328
friend constexpr axis_aligned_rectangle ceil(axis_aligned_rectangle const &rhs) noexcept
Round rectangle by expanding to pixel edge.
Definition axis_aligned_rectangle.hpp:453
constexpr bool contains(point< value_type, 3 > const &rhs) const noexcept
Check if a 3D coordinate is inside the rectangle.
Definition axis_aligned_rectangle.hpp:276
constexpr extent< value_type, 2 > size() const noexcept
Get size of the rectangle.
Definition axis_aligned_rectangle.hpp:183
constexpr bool empty() const noexcept
Check if the rectangle has no area.
Definition axis_aligned_rectangle.hpp:115
friend constexpr axis_aligned_rectangle operator-(axis_aligned_rectangle const &lhs, geo::margins< value_type > rhs) noexcept
Shrink the rectangle by each margin.
Definition axis_aligned_rectangle.hpp:433
constexpr bool holds_invariant() const noexcept
Make sure p0 is left/bottom from p3.
Definition axis_aligned_rectangle.hpp:108
constexpr bool contains(point< value_type, 2 > const &rhs) const noexcept
Check if a 2D coordinate is inside the rectangle.
Definition axis_aligned_rectangle.hpp:265
friend constexpr axis_aligned_rectangle floor(axis_aligned_rectangle const &rhs) noexcept
Round rectangle by shrinking to pixel edge.
Definition axis_aligned_rectangle.hpp:473
constexpr friend point< value_type, 2 > midpoint(axis_aligned_rectangle const &rhs) noexcept
Get the center of the rectangle.
Definition axis_aligned_rectangle.hpp:244
constexpr value_type center() const noexcept
The center on the x-axis between left and right.
Definition axis_aligned_rectangle.hpp:237
constexpr axis_aligned_rectangle & operator|=(axis_aligned_rectangle const &rhs) noexcept
Expand the current rectangle to include the new rectangle.
Definition axis_aligned_rectangle.hpp:132
constexpr axis_aligned_rectangle(value_type x, value_type y, value_type width, value_type height) noexcept
Create a box from the position and size.
Definition axis_aligned_rectangle.hpp:59
friend constexpr axis_aligned_rectangle operator*(axis_aligned_rectangle const &lhs, value_type rhs) noexcept
Expand the rectangle for the same amount in all directions.
Definition axis_aligned_rectangle.hpp:394
friend constexpr axis_aligned_rectangle operator+(axis_aligned_rectangle const &lhs, value_type rhs) noexcept
Expand the rectangle for the same amount in all directions.
Definition axis_aligned_rectangle.hpp:411
constexpr value_type middle() const noexcept
The middle on the y-axis between bottom and top.
Definition axis_aligned_rectangle.hpp:230
constexpr axis_aligned_rectangle(point< value_type, 2 > const &p0, point< value_type, 2 > const &p3) noexcept
Create a rectangle from the left-bottom and right-top points.
Definition axis_aligned_rectangle.hpp:79
friend constexpr axis_aligned_rectangle align(axis_aligned_rectangle haystack, extent< value_type, 2 > needle, alignment alignment) noexcept
Align a rectangle within another rectangle.
Definition axis_aligned_rectangle.hpp:288
constexpr axis_aligned_rectangle & operator|=(point< value_type, 2 > const &rhs) noexcept
Expand the current rectangle to include the new rectangle.
Definition axis_aligned_rectangle.hpp:142
constexpr axis_aligned_rectangle(extent< value_type, 2 > const &extent) noexcept
Create a rectangle from the size.
Definition axis_aligned_rectangle.hpp:69
friend constexpr axis_aligned_rectangle ceil(axis_aligned_rectangle const &lhs, extent< value_type, 2 > const &rhs) noexcept
Round rectangle by expanding to a certain granularity.
Definition axis_aligned_rectangle.hpp:464
A high-level geometric extent.
Definition extent.hpp:30
The left, bottom, right and top margins.
Definition margins.hpp:21
T compare_exchange_weak(T... args)
T exchange(T... args)
T fetch_or(T... args)
T is_lock_free(T... args)
T load(T... args)
T lock(T... args)
T max(T... args)
T min(T... args)
T operator=(T... args)
T operator|=(T... args)
T store(T... args)