1#![feature(iter_advance_by)]
2#![feature(stmt_expr_attributes)]
3#![feature(trusted_len)]
4
5#![deny(warnings)]
6#![allow(unstable_name_collisions)] #![doc(test(attr(deny(warnings))))]
8#![doc(test(attr(allow(dead_code))))]
9#![doc(test(attr(allow(unused_variables))))]
10#![allow(clippy::collapsible_else_if)]
11#![allow(clippy::collapsible_if)]
12#![allow(clippy::manual_map)]
13#![allow(clippy::many_single_char_names)]
14#![allow(clippy::too_many_arguments)]
15
16#![no_std]
17
18#[cfg(feature="serde")]
19extern crate alloc;
20
21#[cfg(feature="serde")]
22use alloc::format;
23use core::cmp::{min, max};
24#[cfg(feature="serde")]
25use core::fmt::{self, Formatter};
26use core::iter::{FusedIterator, TrustedLen};
27use core::num::{NonZeroI16, NonZeroUsize};
28use core::ops::{Add, AddAssign, Sub, SubAssign, Neg, Index, IndexMut};
29#[cfg(feature="serde")]
30use core::str::FromStr;
31use either::{Either, Left, Right};
32use enum_derive_2018::{EnumDisplay, EnumFromStr};
33use macro_attr_2018::macro_attr;
34use num_traits::Zero;
35#[cfg(test)]
36use quickcheck::{Arbitrary, Gen};
37#[cfg(feature="serde")]
38use serde::{Serialize, Deserialize, Serializer, Deserializer};
39#[cfg(feature="serde")]
40use serde::de::{self, Unexpected};
41#[cfg(feature="serde")]
42use serde::de::Error as de_Error;
43
44#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
45pub struct Range1d {
46 pub start: i16,
47 pub end: i16,
48}
49
50impl Range1d {
51 pub fn new(start: i16, end: i16) -> Self {
52 Range1d { start, end }
53 }
54
55 pub fn len(self) -> u16 { self.end.wrapping_sub(self.start) as u16 }
56
57 pub fn inclusive(start: i16, end: i16) -> Option<Self> {
58 let res = Range1d { start, end: end.wrapping_add(1) };
59 if res.is_empty() { None } else { Some(res) }
60 }
61
62 pub fn contains(self, coord: i16) -> bool {
63 (coord.wrapping_sub(self.start) as u16) < (self.end.wrapping_sub(self.start) as u16)
64 }
65
66 pub fn is_empty(self) -> bool {
67 self.start == self.end
68 }
69
70 pub fn intersect(self, other: Range1d) -> Range1d {
71 let (long, short) = if self.len() <= other.len() {
72 (other, self)
73 } else {
74 (self, other)
75 };
76 if long.contains(short.start) {
77 if long.contains(short.end) {
78 short
79 } else {
80 Range1d::new(short.start, long.end)
81 }
82 } else {
83 if long.contains(short.end) {
84 Range1d::new(long.start, short.end)
85 } else {
86 Range1d::new(self.start, self.start)
87 }
88 }
89 }
90
91 pub fn union(self, other: Range1d) -> Option<Range1d> {
92 let (long, short) = if self.len() <= other.len() {
93 (other, self)
94 } else {
95 (self, other)
96 };
97 if long.contains(short.start) {
98 if long.contains(short.end) {
99 if Range1d::new(long.start, short.end).len() >= Range1d::new(long.start, short.start).len() {
100 Some(long)
101 } else {
102 None
103 }
104 } else {
105 let res = Range1d::new(long.start, short.end);
106 if res.is_empty() { None } else { Some(res) }
107 }
108 } else {
109 if long.contains(short.end) {
110 let res = Range1d::new(short.start, long.end);
111 if res.is_empty() { None } else { Some(res) }
112 } else {
113 if other.is_empty() {
114 Some(self)
115 } else if self.is_empty() {
116 Some(other)
117 } else {
118 let u = Range1d::new(self.start, other.end);
119 let v = Range1d::new(other.start, self.end);
120 if u.is_empty() {
121 if v.is_empty() { None } else { Some(v) }
122 } else {
123 Some(if v.is_empty() {
124 u
125 } else {
126 if u.len() < v.len() { u } else { v }
127 })
128 }
129 }
130 }
131 }
132 }
133}
134
135impl Iterator for Range1d {
136 type Item = i16;
137
138 fn next(&mut self) -> Option<i16> {
139 if !self.is_empty() {
140 let item = self.start;
141 self.start = self.start.wrapping_add(1);
142 Some(item)
143 } else {
144 None
145 }
146 }
147
148 fn size_hint(&self) -> (usize, Option<usize>) {
149 let len = self.len();
150 (len, Some(len))
151 }
152
153 fn count(self) -> usize { self.len() as usize }
154
155 fn last(self) -> Option<i16> {
156 if self.is_empty() { None } else { Some(self.end) }
157 }
158
159 fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
160 if let Some(rem) = n.checked_sub(self.len()).and_then(NonZeroUsize::new) {
161 self.start = self.end;
162 return Err(rem);
163 }
164 self.start = self.start.wrapping_add(n as u16 as i16);
165 Ok(())
166 }
167}
168
169impl FusedIterator for Range1d { }
170
171impl DoubleEndedIterator for Range1d {
172 fn next_back(&mut self) -> Option<i16> {
173 if !self.is_empty() {
174 let item = self.end;
175 self.end = self.end.wrapping_sub(1);
176 Some(item)
177 } else {
178 None
179 }
180 }
181
182 fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
183 if let Some(rem) = n.checked_sub(self.len()).and_then(NonZeroUsize::new) {
184 self.end = self.start;
185 return Err(rem);
186 }
187 self.end = self.end.wrapping_sub(n as u16 as i16);
188 Ok(())
189 }
190}
191
192impl ExactSizeIterator for Range1d {
193 fn len(&self) -> usize {
194 Range1d::len(*self) as usize
195 }
196}
197
198unsafe impl TrustedLen for Range1d { }
199
200macro_attr! {
201 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
202 #[derive(Eq, PartialEq, Debug, Hash, Clone, Copy, Ord, PartialOrd)]
203 #[derive(EnumDisplay!, EnumFromStr!)]
204 pub enum Side {
205 Left,
206 Top,
207 Right,
208 Bottom
209 }
210}
211
212#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
213pub struct Point {
214 pub x: i16,
215 pub y: i16,
216}
217
218#[cfg(feature="serde")]
219#[derive(Serialize, Deserialize)]
220#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
221#[serde(rename="Point")]
222struct PointNHRSurrogate {
223 x: i16,
224 y: i16,
225}
226
227#[cfg(feature="serde")]
228impl Serialize for Point {
229 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
230 if serializer.is_human_readable() {
231 serializer.serialize_str(&format!("{},{}", self.x, self.y))
232 } else {
233 PointNHRSurrogate { x: self.x, y: self.y }.serialize(serializer)
234 }
235 }
236}
237
238#[cfg(feature="serde")]
239struct PointHRDeVisitor;
240
241#[cfg(feature="serde")]
242impl<'de> de::Visitor<'de> for PointHRDeVisitor {
243 type Value = Point;
244
245 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
246 write!(formatter, "two i16 separated by comma")
247 }
248
249 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: de::Error {
250 let mut parts = v.split(',');
251 let x = parts.next().ok_or_else(|| E::invalid_value(Unexpected::Str(v), &self))?;
252 let y = parts.next().ok_or_else(|| E::invalid_value(Unexpected::Str(v), &self))?;
253 if parts.next().is_some() {
254 return Err(E::invalid_value(Unexpected::Str(v), &self));
255 }
256 let x = i16::from_str(x).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))?;
257 let y = i16::from_str(y).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))?;
258 Ok(Point { x, y })
259 }
260}
261
262#[cfg(feature="serde")]
263impl<'de> Deserialize<'de> for Point {
264 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
265 if deserializer.is_human_readable() {
266 deserializer.deserialize_str(PointHRDeVisitor)
267 } else {
268 let p = PointNHRSurrogate::deserialize(deserializer)?;
269 Ok(Point { x: p.x, y: p.y })
270 }
271 }
272}
273
274impl Point {
275 pub fn offset(self, d: Vector) -> Point {
276 Point { x: self.x.wrapping_add(d.x), y: self.y.wrapping_add(d.y) }
277 }
278
279 pub fn offset_from(self, other: Point) -> Vector {
280 Vector { x: self.x.wrapping_sub(other.x), y: self.y.wrapping_sub(other.y) }
281 }
282
283 pub fn relative_to(self, base: Point) -> Point {
284 Point { x: self.x.wrapping_sub(base.x), y: self.y.wrapping_sub(base.y) }
285 }
286
287 pub fn absolute_with(self, base: Point) -> Point {
288 Point { x: self.x.wrapping_add(base.x), y: self.y.wrapping_add(base.y) }
289 }
290}
291
292#[cfg(test)]
293impl Arbitrary for Point {
294 fn arbitrary(g: &mut Gen) -> Self {
295 let a = <(_, _)>::arbitrary(g);
296 Point { x: a.0, y: a.1 }
297 }
298}
299
300#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
301pub struct Vector {
302 pub x: i16,
303 pub y: i16,
304}
305
306#[cfg(feature="serde")]
307#[derive(Serialize, Deserialize)]
308#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
309#[serde(rename="Vector")]
310struct VectorNHRSurrogate {
311 x: i16,
312 y: i16,
313}
314
315#[cfg(feature="serde")]
316impl Serialize for Vector {
317 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
318 if serializer.is_human_readable() {
319 serializer.serialize_str(&format!("{},{}", self.x, self.y))
320 } else {
321 VectorNHRSurrogate { x: self.x, y: self.y }.serialize(serializer)
322 }
323 }
324}
325
326#[cfg(feature="serde")]
327struct VectorHRDeVisitor;
328
329#[cfg(feature="serde")]
330impl<'de> de::Visitor<'de> for VectorHRDeVisitor {
331 type Value = Vector;
332
333 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
334 write!(formatter, "two i16 separated by comma")
335 }
336
337 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: de::Error {
338 let mut parts = v.split(',');
339 let x = parts.next().ok_or_else(|| E::invalid_value(Unexpected::Str(v), &self))?;
340 let y = parts.next().ok_or_else(|| E::invalid_value(Unexpected::Str(v), &self))?;
341 if parts.next().is_some() {
342 return Err(E::invalid_value(Unexpected::Str(v), &self));
343 }
344 let x = i16::from_str(x).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))?;
345 let y = i16::from_str(y).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))?;
346 Ok(Vector { x, y })
347 }
348}
349
350#[cfg(feature="serde")]
351impl<'de> Deserialize<'de> for Vector {
352 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
353 if deserializer.is_human_readable() {
354 deserializer.deserialize_str(VectorHRDeVisitor)
355 } else {
356 let p = VectorNHRSurrogate::deserialize(deserializer)?;
357 Ok(Vector { x: p.x, y: p.y })
358 }
359 }
360}
361
362impl Vector {
363 pub const fn null() -> Vector { Vector { x: 0, y: 0 } }
364
365 pub fn is_null(self) -> bool { self.x == 0 && self.y == 0 }
366
367 pub fn rect_area(self) -> u32 { (self.x as u16 as u32) * (self.y as u16 as u32) }
368
369 pub fn max(self, other: Vector) -> Vector {
370 Vector {
371 x: max(self.x as u16, other.x as u16) as i16,
372 y: max(self.y as u16, other.y as u16) as i16,
373 }
374 }
375
376 pub fn min(self, other: Vector) -> Vector {
377 Vector {
378 x: min(self.x as u16, other.x as u16) as i16,
379 y: min(self.y as u16, other.y as u16) as i16,
380 }
381 }
382}
383
384impl Default for Vector {
385 fn default() -> Self { Vector::null() }
386}
387
388impl Zero for Vector {
389 fn zero() -> Self { Vector::null() }
390
391 fn is_zero(&self) -> bool { self.is_null() }
392
393 fn set_zero(&mut self) { *self = Vector::null() }
394}
395
396impl Add for Vector {
397 type Output = Self;
398
399 fn add(self, other: Self) -> Self {
400 Vector { x: self.x.wrapping_add(other.x), y: self.y.wrapping_add(other.y) }
401 }
402}
403
404impl AddAssign for Vector {
405 fn add_assign(&mut self, other: Self) {
406 *self = *self + other;
407 }
408}
409
410impl Sub for Vector {
411 type Output = Self;
412
413 fn sub(self, other: Self) -> Self {
414 Vector { x: self.x.wrapping_sub(other.x), y: self.y.wrapping_sub(other.y) }
415 }
416}
417
418impl SubAssign for Vector {
419 fn sub_assign(&mut self, other: Self) {
420 *self = *self - other;
421 }
422}
423
424impl Neg for Vector {
425 type Output = Self;
426
427 fn neg(self) -> Self {
428 Vector::null() - self
429 }
430}
431
432#[cfg(test)]
433impl Arbitrary for Vector {
434 fn arbitrary(g: &mut Gen) -> Self {
435 let a = <(_, _)>::arbitrary(g);
436 Vector { x: a.0, y: a.1 }
437 }
438}
439
440#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
441#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
442pub struct VBand {
443 pub l: i16,
444 pub w: NonZeroI16,
445}
446
447impl VBand {
448 pub fn from_l_r(l: i16, r: i16) -> Option<VBand> {
449 NonZeroI16::new(r.wrapping_sub(l)).map(|w| VBand { l, w })
450 }
451
452 pub fn from_h_range(h_range: Range1d) -> Option<VBand> {
453 VBand::from_l_r(h_range.start, h_range.end)
454 }
455
456 pub fn r(self) -> i16 { self.l.wrapping_add(self.w.get()) }
457
458 pub fn h_range(self) -> Range1d { Range1d::new(self.l, self.r()) }
459
460 pub fn offset(self, d: Vector) -> VBand {
461 VBand { l: self.l.wrapping_add(d.x), w: self.w }
462 }
463
464 pub fn relative_to(self, base: Point) -> VBand {
465 VBand { l: self.l.wrapping_sub(base.x), w: self.w }
466 }
467
468 pub fn absolute_with(self, base: Point) -> VBand {
469 VBand { l: self.l.wrapping_add(base.x), w: self.w }
470 }
471}
472
473#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
474#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
475pub struct HBand {
476 pub t: i16,
477 pub h: NonZeroI16,
478}
479
480impl HBand {
481 pub fn from_t_b(t: i16, b: i16) -> Option<HBand> {
482 NonZeroI16::new(b.wrapping_sub(t)).map(|h| HBand { t, h })
483 }
484
485 pub fn from_v_range(v_range: Range1d) -> Option<HBand> {
486 HBand::from_t_b(v_range.start, v_range.end)
487 }
488
489 pub fn b(self) -> i16 { self.t.wrapping_add(self.h.get()) }
490
491 pub fn v_range(self) -> Range1d { Range1d::new(self.t, self.b()) }
492
493 pub fn offset(self, d: Vector) -> HBand {
494 HBand { t: self.t.wrapping_add(d.y), h: self.h }
495 }
496
497 pub fn relative_to(self, base: Point) -> HBand {
498 HBand { t: self.t.wrapping_sub(base.y), h: self.h }
499 }
500
501 pub fn absolute_with(self, base: Point) -> HBand {
502 HBand { t: self.t.wrapping_add(base.y), h: self.h }
503 }
504}
505
506#[cfg(feature="serde")]
507fn deserialize_thickness_value<'de, D>(d: D) -> Result<i32, D::Error> where D: Deserializer<'de> {
508 let value = i32::deserialize(d)?;
509 if value >= -(u16::MAX as u32 as i32) && value <= u16::MAX as u32 as i32 { return Ok(value); }
510 Err(D::Error::invalid_value(
511 Unexpected::Signed(value.into()),
512 &"integer in the -(2¹⁶ - 1) ..= (2¹⁶ - 1) range"
513 ))
514}
515
516#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy, Default)]
517pub struct Thickness {
518 l: i32,
519 r: i32,
520 t: i32,
521 b: i32,
522}
523
524#[cfg(feature="serde")]
525#[derive(Serialize, Deserialize)]
526#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
527#[serde(rename="Thickness")]
528struct ThicknessNHRSurrogate {
529 #[serde(deserialize_with="deserialize_thickness_value")]
530 l: i32,
531 #[serde(deserialize_with="deserialize_thickness_value")]
532 t: i32,
533 #[serde(deserialize_with="deserialize_thickness_value")]
534 r: i32,
535 #[serde(deserialize_with="deserialize_thickness_value")]
536 b: i32,
537}
538
539#[cfg(feature="serde")]
540impl Serialize for Thickness {
541 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
542 if serializer.is_human_readable() {
543 serializer.serialize_str(&format!("{},{},{},{}", self.l, self.t, self.r, self.b))
544 } else {
545 ThicknessNHRSurrogate { l: self.l, t: self.t, r: self.r, b: self.b }.serialize(serializer)
546 }
547 }
548}
549
550#[cfg(feature="serde")]
551struct ThicknessHRDeVisitor;
552
553#[cfg(feature="serde")]
554impl<'de> de::Visitor<'de> for ThicknessHRDeVisitor {
555 type Value = Thickness;
556
557 fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
558 write!(formatter, "four integers in the -(2¹⁶ - 1) ..= (2¹⁶ - 1) range separated by comma")
559 }
560
561 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: de::Error {
562 let mut parts = v.split(',');
563 let l = parts.next().ok_or_else(|| E::invalid_value(Unexpected::Str(v), &self))?;
564 let t = parts.next().ok_or_else(|| E::invalid_value(Unexpected::Str(v), &self))?;
565 let r = parts.next().ok_or_else(|| E::invalid_value(Unexpected::Str(v), &self))?;
566 let b = parts.next().ok_or_else(|| E::invalid_value(Unexpected::Str(v), &self))?;
567 if parts.next().is_some() {
568 return Err(E::invalid_value(Unexpected::Str(v), &self));
569 }
570 let l = i32::from_str(l).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))?;
571 let t = i32::from_str(t).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))?;
572 let r = i32::from_str(r).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))?;
573 let b = i32::from_str(b).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))?;
574 if l < -(u16::MAX as u32 as i32) || l > u16::MAX as u32 as i32 {
575 return Err(E::invalid_value(Unexpected::Str(v), &self));
576 }
577 if t < -(u16::MAX as u32 as i32) || t > u16::MAX as u32 as i32 {
578 return Err(E::invalid_value(Unexpected::Str(v), &self));
579 }
580 if r < -(u16::MAX as u32 as i32) || r > u16::MAX as u32 as i32 {
581 return Err(E::invalid_value(Unexpected::Str(v), &self));
582 }
583 if b < -(u16::MAX as u32 as i32) || b > u16::MAX as u32 as i32 {
584 return Err(E::invalid_value(Unexpected::Str(v), &self));
585 }
586 Ok(Thickness::new(l, t, r, b))
587 }
588}
589
590#[cfg(feature="serde")]
591impl<'de> Deserialize<'de> for Thickness {
592 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
593 if deserializer.is_human_readable() {
594 deserializer.deserialize_str(ThicknessHRDeVisitor)
595 } else {
596 let p = ThicknessNHRSurrogate::deserialize(deserializer)?;
597 Ok(Thickness::new(p.l, p.t, p.r, p.b))
598 }
599 }
600}
601
602impl Thickness {
603 pub const fn new(l: i32, t: i32, r: i32, b: i32) -> Self {
604 assert!(l >= -(u16::MAX as u32 as i32) && l <= u16::MAX as u32 as i32);
605 assert!(t >= -(u16::MAX as u32 as i32) && t <= u16::MAX as u32 as i32);
606 assert!(r >= -(u16::MAX as u32 as i32) && r <= u16::MAX as u32 as i32);
607 assert!(b >= -(u16::MAX as u32 as i32) && b <= u16::MAX as u32 as i32);
608 Thickness { l, t, r, b }
609 }
610
611 pub const unsafe fn new_unchecked(l: i32, t: i32, r: i32, b: i32) -> Self {
615 Thickness { l, t, r, b }
616 }
617
618 pub const fn all(a: i32) -> Thickness {
619 assert!(a >= -(u16::MAX as u32 as i32) && a <= u16::MAX as u32 as i32);
620 Thickness { l: a, t: a, r: a, b: a }
621 }
622
623 pub fn l(self) -> i32 { self.l }
624
625 pub fn t(self) -> i32 { self.t }
626
627 pub fn r(self) -> i32 { self.r }
628
629 pub fn b(self) -> i32 { self.b }
630
631 pub fn align(inner: Vector, outer: Vector, h_align: HAlign, v_align: VAlign) -> Thickness {
632 let h_neg = inner.x as u16 > outer.x as u16;
633 let (outer_x, inner_x) = if h_neg { (inner.x, outer.x) } else { (outer.x, inner.x) };
634 let w = (outer_x as u16) - (inner_x as u16);
635 let (l, r) = match h_align {
636 HAlign::Left => (0, w),
637 HAlign::Right => (w, 0),
638 HAlign::Center => {
639 let l = w / 2;
640 let r = w - l;
641 (l, r)
642 }
643 };
644 let v_neg = inner.y as u16 > outer.y as u16;
645 let (outer_y, inner_y) = if v_neg { (inner.y, outer.y) } else { (outer.y, inner.y) };
646 let h = (outer_y as u16) - (inner_y as u16);
647 let (t, b) = match v_align {
648 VAlign::Top => (0, h),
649 VAlign::Bottom => (h, 0),
650 VAlign::Center => {
651 let t = h / 2;
652 let b = h - t;
653 (t, b)
654 }
655 };
656 let l = l as u32 as i32;
657 let t = t as u32 as i32;
658 let r = r as u32 as i32;
659 let b = b as u32 as i32;
660 Thickness {
661 l: if h_neg { -l } else { l },
662 t: if v_neg { -t } else { t },
663 r: if h_neg { -r } else { r },
664 b: if v_neg { -b } else { b }
665 }
666 }
667
668 fn shrink_near(thickness: u16, rect: (i16, i16)) -> (i16, i16) {
669 let thickness = min(thickness, rect.1 as u16);
670 (rect.0.wrapping_add(thickness as i16), rect.1.wrapping_sub(thickness as i16))
671 }
672
673 fn shrink_far(thickness: u16, rect: (i16, i16)) -> (i16, i16) {
674 let thickness = min(thickness, rect.1 as u16);
675 (rect.0, rect.1.wrapping_sub(thickness as i16))
676 }
677
678 fn expand_near(thickness: u16, rect: (i16, i16)) -> (i16, i16) {
679 let thickness = min(thickness, u16::MAX - (rect.1 as u16));
680 (rect.0.wrapping_sub(thickness as i16), rect.1.wrapping_add(thickness as i16))
681 }
682
683 fn expand_far(thickness: u16, rect: (i16, i16)) -> (i16, i16) {
684 let thickness = min(thickness, u16::MAX - (rect.1 as u16));
685 (rect.0, rect.1.wrapping_add(thickness as i16))
686 }
687
688 pub fn shrink_rect(self, rect: Rect) -> Rect {
689 let (l, w) = if self.l < 0 {
690 Self::expand_near((-self.l) as u32 as u16, (rect.l(), rect.w()))
691 } else {
692 Self::shrink_near(self.l as u32 as u16, (rect.l(), rect.w()))
693 };
694 let (t, h) = if self.t < 0 {
695 Self::expand_near((-self.t) as u32 as u16, (rect.t(), rect.h()))
696 } else {
697 Self::shrink_near(self.t as u32 as u16, (rect.t(), rect.h()))
698 };
699 let (l, w) = if self.r < 0 {
700 Self::expand_far((-self.r) as u32 as u16, (l, w))
701 } else {
702 Self::shrink_far(self.r as u32 as u16, (l, w))
703 };
704 let (t, h) = if self.b < 0 {
705 Self::expand_far((-self.b) as u32 as u16, (t, h))
706 } else {
707 Self::shrink_far(self.b as u32 as u16, (t, h))
708 };
709 Rect { tl: Point { x: l, y: t }, size: Vector { x: w, y: h } }
710 }
711
712 pub fn expand_rect(self, rect: Rect) -> Rect {
713 (-self).shrink_rect(rect)
714 }
715
716 pub fn shrink_optional_rect_size(
717 self, rect_width: Option<i16>, rect_height: Option<i16>
718 ) -> (Option<i16>, Option<i16>) {
719 let size = self.shrink_rect_size(Vector { x: rect_width.unwrap_or(0), y: rect_height.unwrap_or(0) });
720 (rect_width.map(|_| size.x), rect_height.map(|_| size.y))
721 }
722
723 pub fn expand_optional_rect_size(
724 self, rect_width: Option<i16>, rect_height: Option<i16>
725 ) -> (Option<i16>, Option<i16>) {
726 let size = self.expand_rect_size(Vector { x: rect_width.unwrap_or(0), y: rect_height.unwrap_or(0) });
727 (rect_width.map(|_| size.x), rect_height.map(|_| size.y))
728 }
729
730 pub fn shrink_rect_size(self, rect_size: Vector) -> Vector {
731 self.shrink_rect(Rect { tl: Point { x: 0, y: 0 }, size: rect_size }).size
732 }
733
734 pub fn expand_rect_size(self, rect_size: Vector) -> Vector {
735 self.expand_rect(Rect { tl: Point { x: 0, y: 0 }, size: rect_size }).size
736 }
737
738 pub fn shrink_band_h(self, band_h: i16) -> i16 {
739 let (_, h) = if self.t < 0 {
740 Self::expand_near((-self.t) as u32 as u16, (0, band_h))
741 } else {
742 Self::shrink_near(self.t as u32 as u16, (0, band_h))
743 };
744 h
745 }
746
747 pub fn expand_band_h(self, band_h: i16) -> i16 {
748 (-self).shrink_band_h(band_h)
749 }
750
751 pub fn shrink_band_w(self, band_w: i16) -> i16 {
752 let (_, w) = if self.l < 0 {
753 Self::expand_near((-self.t) as u32 as u16, (0, band_w))
754 } else {
755 Self::shrink_near(self.t as u32 as u16, (0, band_w))
756 };
757 w
758 }
759
760 pub fn expand_band_w(self, band_w: i16) -> i16 {
761 (-self).shrink_band_w(band_w)
762 }
763
764 fn add_side(this: i32, other: i32) -> i32 {
765 if this < 0 {
766 if other < 0 {
767 -(((-this) as u32 as u16).saturating_add((-other) as u32 as u16) as u32 as i32)
768 } else {
769 other + this
770 }
771 } else {
772 if other > 0 {
773 (this as u32 as u16).saturating_add(other as u32 as u16) as u32 as i32
774 } else {
775 other + this
776 }
777 }
778 }
779}
780
781impl Add for Thickness {
782 type Output = Self;
783
784 fn add(self, other: Self) -> Self {
785 let l = Self::add_side(self.l, other.l);
786 let t = Self::add_side(self.t, other.t);
787 let r = Self::add_side(self.r, other.r);
788 let b = Self::add_side(self.b, other.b);
789 Thickness { l, t, r, b }
790 }
791}
792
793impl AddAssign for Thickness {
794 fn add_assign(&mut self, other: Self) {
795 *self = *self + other;
796 }
797}
798
799impl Sub for Thickness {
800 type Output = Self;
801
802 fn sub(self, other: Self) -> Self {
803 self + (-other)
804 }
805}
806
807impl SubAssign for Thickness {
808 fn sub_assign(&mut self, other: Self) {
809 *self = *self - other;
810 }
811}
812
813impl Neg for Thickness {
814 type Output = Self;
815
816 fn neg(self) -> Self {
817 Thickness { l: -self.l, t: -self.t, r: -self.r, b: -self.b }
818 }
819}
820
821impl Index<Side> for Thickness {
822 type Output = i32;
823
824 fn index(&self, index: Side) -> &i32 {
825 match index {
826 Side::Left => &self.l,
827 Side::Top => &self.t,
828 Side::Right => &self.r,
829 Side::Bottom => &self.b
830 }
831 }
832}
833
834impl IndexMut<Side> for Thickness {
835 fn index_mut(&mut self, index: Side) -> &mut i32 {
836 match index {
837 Side::Left => &mut self.l,
838 Side::Top => &mut self.t,
839 Side::Right => &mut self.r,
840 Side::Bottom => &mut self.b
841 }
842 }
843}
844
845macro_attr! {
846 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
847 #[derive(Eq, PartialEq, Debug, Hash, Clone, Copy, Ord, PartialOrd)]
848 #[derive(EnumDisplay!, EnumFromStr!)]
849 pub enum HAlign { Left, Center, Right }
850}
851
852macro_attr! {
853 #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
854 #[derive(Eq, PartialEq, Debug, Hash, Clone, Copy, Ord, PartialOrd)]
855 #[derive(EnumDisplay!, EnumFromStr!)]
856 pub enum VAlign { Top, Center, Bottom }
857}
858
859pub struct RectPoints {
860 rect: Rect,
861 x: i16,
862}
863
864impl Iterator for RectPoints {
865 type Item = Point;
866
867 fn next(&mut self) -> Option<Point> {
868 if self.rect.is_empty() {
869 return None;
870 }
871 let item = Point { x: self.x, y: self.rect.t() };
872 self.x = self.x.wrapping_add(1);
873 if self.x == self.rect.r() {
874 self.x = self.rect.l();
875 self.rect.tl = Point { x: self.x, y: self.rect.t().wrapping_add(1) };
876 self.rect.size = Vector { x: self.rect.w(), y: self.rect.h().wrapping_sub(1) };
877 }
878 Some(item)
879 }
880
881 fn size_hint(&self) -> (usize, Option<usize>) {
882 let len = self.rect.area() - (self.x.wrapping_sub(self.rect.l()) as u16 as u32);
883 if len as usize as u32 == len {
884 (len as usize, Some(len as usize))
885 } else {
886 (usize::MAX, None)
887 }
888 }
889
890 fn count(self) -> usize { self.size_hint().1.unwrap() }
891
892 fn last(self) -> Option<Point> {
893 if self.rect.is_empty() { None } else { Some(self.rect.br_inner()) }
894 }
895
896 fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
897 if let Some(rem) = self.size_hint().1.and_then(|len| n.checked_sub(len)).and_then(NonZeroUsize::new) {
898 self.x = self.rect.l();
899 self.rect.tl = self.rect.bl();
900 return Err(rem);
901 }
902 let n = n as u32;
903 let current_line_last = self.rect.r().wrapping_sub(self.x) as u16 as u32;
904 if n < current_line_last {
905 self.x = self.x.wrapping_add(n as u16 as i16);
906 return Ok(());
907 }
908 let n = n - current_line_last;
909 let skip_lines = 1i16.wrapping_add((n / self.rect.w() as u32) as u16 as i16);
910 self.rect.tl = Point { x: self.rect.l(), y: self.rect.t().wrapping_add(skip_lines) };
911 self.rect.size = Vector { x: self.rect.w(), y: self.rect.h().wrapping_sub(skip_lines) };
912 self.x = (n % self.rect.w() as u32) as u16 as i16;
913 Ok(())
914 }
915}
916
917impl FusedIterator for RectPoints { }
918
919#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
920#[derive(Eq, PartialEq, Debug, Hash, Clone, Copy)]
921pub struct Rect {
922 pub tl: Point,
923 pub size: Vector,
924}
925
926impl Rect {
927 pub fn from_tl_br(tl: Point, br: Point) -> Rect {
928 Rect { tl, size: br.offset_from(tl) }
929 }
930
931 pub fn from_h_v_ranges(h_range: Range1d, v_range: Range1d) -> Rect {
932 Rect::from_tl_br(
933 Point { x: h_range.start, y: v_range.start },
934 Point { x: h_range.end, y: v_range.end }
935 )
936 }
937
938 pub fn is_empty(self) -> bool { self.w() == 0 || self.h() == 0 }
939
940 pub fn w(self) -> i16 { self.size.x }
941
942 pub fn h(self) -> i16 { self.size.y }
943
944 pub fn l(self) -> i16 { self.tl.x }
945
946 pub fn t(self) -> i16 { self.tl.y }
947
948 pub fn r(self) -> i16 { self.tl.x.wrapping_add(self.size.x) }
949
950 pub fn b(self) -> i16 { self.tl.y.wrapping_add(self.size.y) }
951
952 pub fn tr(self) -> Point { Point { x: self.r(), y: self.t() } }
953
954 pub fn bl(self) -> Point { Point { x: self.l(), y: self.b() } }
955
956 pub fn br(self) -> Point { Point { x: self.r(), y: self.b() } }
957
958 pub fn r_inner(self) -> i16 {
959 self.l().wrapping_add((self.size.x as u16).saturating_sub(1) as i16)
960 }
961
962 pub fn b_inner(self) -> i16 {
963 self.t().wrapping_add((self.size.y as u16).saturating_sub(1) as i16)
964 }
965
966 pub fn tr_inner(self) -> Point { Point { x: self.r_inner(), y: self.t() } }
967
968 pub fn bl_inner(self) -> Point { Point { x: self.l(), y: self.b_inner() } }
969
970 pub fn br_inner(self) -> Point { Point { x: self.r_inner(), y: self.b_inner() } }
971
972 pub fn area(self) -> u32 { self.size.rect_area() }
973
974 pub fn points(self) -> RectPoints { RectPoints { rect: self, x: self.l() } }
975
976 pub fn h_range(self) -> Range1d { Range1d { start: self.l(), end: self.r() } }
977
978 pub fn v_range(self) -> Range1d { Range1d { start: self.t(), end: self.b() } }
979
980 pub fn contains(self, p: Point) -> bool {
981 self.h_range().contains(p.x) && self.v_range().contains(p.y)
982 }
983
984 pub fn intersect(self, other: Rect) -> Rect {
985 let h = self.h_range().intersect(other.h_range());
986 let v = self.v_range().intersect(other.v_range());
987 Rect::from_h_v_ranges(h, v)
988 }
989
990 pub fn intersect_h_band(self, band: HBand) -> Rect {
991 let v = self.v_range().intersect(band.v_range());
992 Rect::from_h_v_ranges(self.h_range(), v)
993 }
994
995 pub fn intersect_v_band(self, band: VBand) -> Rect {
996 let h = self.h_range().intersect(band.h_range());
997 Rect::from_h_v_ranges(h, self.v_range())
998 }
999
1000 pub fn union(self, other: Rect) -> Option<Either<Either<HBand, VBand>, Rect>> {
1001 if other.is_empty() { return Some(Right(self)); }
1002 if self.is_empty() { return Some(Right(other)); }
1003 let hr = self.h_range().union(other.h_range());
1004 let vr = self.v_range().union(other.v_range());
1005 if let Some(hr) = hr {
1006 if let Some(vr) = vr {
1007 Some(Right(Rect::from_h_v_ranges(hr, vr)))
1008 } else {
1009 Some(Left(Right(VBand::from_h_range(hr).unwrap())))
1010 }
1011 } else {
1012 if let Some(vr) = vr {
1013 Some(Left(Left(HBand::from_v_range(vr).unwrap())))
1014 } else {
1015 None
1016 }
1017 }
1018 }
1019
1020 pub fn union_intersect(self, union_with: Rect, intersect_with: Rect) -> Rect {
1021 match self.union(union_with) {
1022 None => intersect_with,
1023 Some(Right(rect)) => rect.intersect(intersect_with),
1024 Some(Left(Right(v_band))) => Rect {
1025 tl: Point { x: v_band.l, y: intersect_with.t() },
1026 size: Vector { x: v_band.w.get(), y: intersect_with.h() }
1027 },
1028 Some(Left(Left(h_band))) => Rect {
1029 tl: Point { y: h_band.t, x: intersect_with.l() },
1030 size: Vector { y: h_band.h.get(), x: intersect_with.w() }
1031 },
1032 }
1033 }
1034
1035 pub fn offset(self, d: Vector) -> Rect {
1036 Rect { tl: self.tl.offset(d), size: self.size }
1037 }
1038
1039 pub fn relative_to(self, base: Point) -> Rect {
1040 Rect { tl: self.tl.relative_to(base), size: self.size }
1041 }
1042
1043 pub fn absolute_with(self, base: Point) -> Rect {
1044 Rect { tl: self.tl.absolute_with(base), size: self.size }
1045 }
1046
1047 pub fn t_line(self) -> Rect {
1048 let height = min(1, self.size.y as u16) as i16;
1049 Rect { tl: self.tl, size: Vector { x: self.size.x, y: height } }
1050 }
1051
1052 pub fn b_line(self) -> Rect {
1053 let height = min(1, self.size.y as u16) as i16;
1054 Rect {
1055 tl: Point { x: self.l(), y: self.b().wrapping_sub(height) },
1056 size: Vector { x: self.size.x, y: height }
1057 }
1058 }
1059
1060 pub fn l_line(self) -> Rect {
1061 let width = min(1, self.size.x as u16) as i16;
1062 Rect { tl: self.tl, size: Vector { x: width, y: self.size.y } }
1063 }
1064
1065 pub fn r_line(self) -> Rect {
1066 let width = min(1, self.size.x as u16) as i16;
1067 Rect {
1068 tl: Point { x: self.r().wrapping_sub(width), y: self.t() },
1069 size: Vector { x: width, y: self.size.y }
1070 }
1071 }
1072}
1073
1074#[cfg(test)]
1075impl Arbitrary for Rect {
1076 fn arbitrary(g: &mut Gen) -> Self {
1077 let a = <(Point, Point)>::arbitrary(g);
1078 Rect::from_tl_br(a.0, a.1)
1079 }
1080}
1081
1082#[cfg(test)]
1083mod tests {
1084 use quickcheck::TestResult;
1085 use quickcheck_macros::quickcheck;
1086 use crate::*;
1087
1088 #[test]
1089 fn test_range_iterator() {
1090 let r = Range1d::new(0, 29).step_by(2);
1091 assert_eq!(r.count(), 15);
1092 }
1093
1094 #[quickcheck]
1095 fn rect_area(r: Rect) -> bool {
1096 r.area() == r.size.rect_area()
1097 }
1098
1099 #[quickcheck]
1100 #[allow(clippy::bool_comparison)]
1101 fn rect_is_empty_area(r: Rect) -> bool {
1102 !r.is_empty() == (r.area() > 0)
1103 }
1104
1105 #[quickcheck]
1106 fn null_size_rect_is_empty(tl: Point) -> bool {
1107 Rect { tl, size: Vector::null() }.is_empty()
1108 }
1109
1110 #[quickcheck]
1111 fn rect_empty_intersect(tl1: Point, r2: Rect) -> bool {
1112 let r1 = Rect { tl: tl1, size: Vector::null() };
1113 r1.intersect(r2) == r1
1114 }
1115
1116 #[quickcheck]
1117 fn rect_intersect_empty(r1: Rect, tl2: Point) -> bool {
1118 let r2 = Rect { tl: tl2, size: Vector::null() };
1119 r1.is_empty() || r1.contains(r1.intersect(r2).tl)
1120 }
1121
1122 #[quickcheck]
1123 fn rect_intersect_contains(r1: Rect, r2: Rect, p: Point) -> bool {
1124 r1.intersect(r2).contains(p) || !(r1.contains(p) && r2.contains(p))
1125 }
1126
1127 #[quickcheck]
1128 fn rect_union_contains(r1: Rect, r2: Rect, p: Point) -> bool {
1129 r1.union(r2).map_or(true, |u| u.either(|_| true, |u| u.contains(p))) || !(r1.contains(p) || r2.contains(p))
1130 }
1131
1132 #[quickcheck]
1133 fn rect_empty_h_union(tl1: Point, r2: Rect, w: i16) -> bool {
1134 let r1 = Rect { tl: tl1, size: Vector { x: w, y: 0} };
1135 r2.is_empty() || r1.union(r2).unwrap().right().unwrap() == r2
1136 }
1137
1138 #[quickcheck]
1139 fn rect_union_empty_h(r1: Rect, tl2: Point, w: i16) -> bool {
1140 let r2 = Rect { tl: tl2, size: Vector { x: w, y: 0 } };
1141 r1.union(r2).unwrap().right().unwrap() == r1
1142 }
1143
1144 #[quickcheck]
1145 fn rect_empty_w_union(tl1: Point, r2: Rect, h: i16) -> bool {
1146 let r1 = Rect { tl: tl1, size: Vector { x: 0, y: h } };
1147 r2.is_empty() || r1.union(r2).unwrap().right().unwrap() == r2
1148 }
1149
1150 #[quickcheck]
1151 fn rect_union_empty_w(r1: Rect, tl2: Point, h: i16) -> bool {
1152 let r2 = Rect { tl: tl2, size: Vector { x: 0, y: h } };
1153 r1.union(r2).unwrap().right().unwrap() == r1
1154 }
1155
1156 #[quickcheck]
1157 fn rect_contains_all_self_points(r: Rect) -> TestResult {
1158 if r.area() > 100000 { return TestResult::discard(); }
1159 TestResult::from_bool(r.points().all(|x| r.contains(x)))
1160 }
1161}