egui/emath/src/rect.rs

500 lines
13 KiB
Rust
Raw Normal View History

use std::f32::INFINITY;
use std::ops::RangeInclusive;
2021-01-10 10:37:47 +00:00
use crate::*;
/// A rectangular region of space.
///
2022-01-26 21:09:19 +00:00
/// Usually a `Rect` has a positive (or zero) size,
/// and then [`Self::min`] `<=` [`Self::max`].
/// In these cases [`Self::min`] is the left-top corner
/// and [`Self::max`] is the right-bottom corner.
///
/// A rectangle is allowed to have a negative size, which happens when the order
/// of `min` and `max` are swapped. These are usually a sign of an error.
///
/// Normally the unit is points (logical pixels) in screen space coordinates.
#[repr(C)]
#[derive(Clone, Copy, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
pub struct Rect {
2022-01-26 21:09:19 +00:00
/// One of the corners of the rectangle, usually the left top one.
pub min: Pos2,
2022-01-26 21:09:19 +00:00
/// The other corner, opposing [`Self::min`]. Usually the right bottom one.
pub max: Pos2,
}
impl Rect {
2022-01-26 21:09:19 +00:00
/// Infinite rectangle that contains every point.
pub const EVERYTHING: Self = Self {
min: pos2(-INFINITY, -INFINITY),
max: pos2(INFINITY, INFINITY),
};
2021-02-21 09:12:08 +00:00
/// The inverse of [`Self::EVERYTHING`]: stretches from positive infinity to negative infinity.
/// Contains no points.
///
2022-01-26 21:09:19 +00:00
/// This is useful as the seed for bounding boxes.
///
/// # Example:
/// ```
/// # use emath::*;
/// let mut rect = Rect::NOTHING;
2022-01-26 21:09:19 +00:00
/// assert!(rect.size() == Vec2::splat(-f32::INFINITY));
/// assert!(rect.contains(pos2(0.0, 0.0)) == false);
/// rect.extend_with(pos2(2.0, 1.0));
/// rect.extend_with(pos2(0.0, 3.0));
/// assert_eq!(rect, Rect::from_min_max(pos2(0.0, 1.0), pos2(2.0, 3.0)))
/// ```
pub const NOTHING: Self = Self {
min: pos2(INFINITY, INFINITY),
max: pos2(-INFINITY, -INFINITY),
};
/// An invalid `Rect` filled with [`f32::NAN`];
pub const NAN: Self = Self {
min: pos2(f32::NAN, f32::NAN),
2022-01-26 21:09:19 +00:00
max: pos2(f32::NAN, f32::NAN),
};
#[inline(always)]
pub const fn from_min_max(min: Pos2, max: Pos2) -> Self {
Rect { min, max }
}
2022-01-26 21:09:19 +00:00
/// left-top corner plus a size (stretching right-down).
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
pub fn from_min_size(min: Pos2, size: Vec2) -> Self {
Rect {
min,
max: min + size,
}
}
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
pub fn from_center_size(center: Pos2, size: Vec2) -> Self {
Rect {
min: center - size * 0.5,
max: center + size * 0.5,
}
}
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
2021-01-10 09:41:04 +00:00
pub fn from_x_y_ranges(x_range: RangeInclusive<f32>, y_range: RangeInclusive<f32>) -> Self {
Rect {
min: pos2(*x_range.start(), *y_range.start()),
max: pos2(*x_range.end(), *y_range.end()),
}
}
2021-02-07 13:55:39 +00:00
2022-01-26 21:09:19 +00:00
/// Returns the bounding rectangle of the two points.
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline]
pub fn from_two_pos(a: Pos2, b: Pos2) -> Self {
Rect {
2021-02-07 13:55:39 +00:00
min: pos2(a.x.min(b.x), a.y.min(b.y)),
max: pos2(a.x.max(b.x), a.y.max(b.y)),
}
}
2021-01-10 09:41:04 +00:00
2022-01-26 21:09:19 +00:00
/// Bounding-box around the points.
pub fn from_points(points: &[Pos2]) -> Self {
let mut rect = Rect::NOTHING;
for &p in points {
rect.extend_with(p);
}
rect
}
2021-03-14 15:42:06 +00:00
/// A `Rect` that contains every point to the right of the given X coordinate.
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline]
2021-03-14 15:42:06 +00:00
pub fn everything_right_of(left_x: f32) -> Self {
let mut rect = Self::EVERYTHING;
rect.set_left(left_x);
rect
}
/// A `Rect` that contains every point to the left of the given X coordinate.
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline]
2021-03-14 15:42:06 +00:00
pub fn everything_left_of(right_x: f32) -> Self {
let mut rect = Self::EVERYTHING;
rect.set_right(right_x);
rect
}
/// A `Rect` that contains every point below a certain y coordinate
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline]
2021-03-14 15:42:06 +00:00
pub fn everything_below(top_y: f32) -> Self {
let mut rect = Self::EVERYTHING;
rect.set_top(top_y);
rect
}
/// A `Rect` that contains every point above a certain y coordinate
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline]
2021-03-14 15:42:06 +00:00
pub fn everything_above(bottom_y: f32) -> Self {
let mut rect = Self::EVERYTHING;
rect.set_bottom(bottom_y);
rect
}
/// Expand by this much in each direction, keeping the center
#[must_use]
pub fn expand(self, amnt: f32) -> Self {
self.expand2(Vec2::splat(amnt))
}
/// Expand by this much in each direction, keeping the center
#[must_use]
pub fn expand2(self, amnt: Vec2) -> Self {
Rect::from_min_max(self.min - amnt, self.max + amnt)
}
/// Shrink by this much in each direction, keeping the center
#[must_use]
pub fn shrink(self, amnt: f32) -> Self {
self.shrink2(Vec2::splat(amnt))
}
/// Shrink by this much in each direction, keeping the center
#[must_use]
pub fn shrink2(self, amnt: Vec2) -> Self {
Rect::from_min_max(self.min + amnt, self.max - amnt)
}
#[must_use]
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline]
pub fn translate(self, amnt: Vec2) -> Self {
Rect::from_min_size(self.min + amnt, self.size())
}
/// Rotate the bounds (will expand the `Rect`)
#[must_use]
#[inline]
pub fn rotate_bb(self, rot: crate::Rot2) -> Self {
let a = rot * self.left_top().to_vec2();
let b = rot * self.right_top().to_vec2();
let c = rot * self.left_bottom().to_vec2();
let d = rot * self.right_bottom().to_vec2();
Self::from_min_max(
a.min(b).min(c).min(d).to_pos2(),
a.max(b).max(c).max(d).to_pos2(),
)
}
#[must_use]
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline]
pub fn intersects(self, other: Rect) -> bool {
self.min.x <= other.max.x
&& other.min.x <= self.max.x
&& self.min.y <= other.max.y
&& other.min.y <= self.max.y
}
/// keep min
pub fn set_width(&mut self, w: f32) {
self.max.x = self.min.x + w;
}
/// keep min
pub fn set_height(&mut self, h: f32) {
self.max.y = self.min.y + h;
}
/// Keep size
pub fn set_center(&mut self, center: Pos2) {
*self = self.translate(center - self.center());
}
#[must_use]
#[inline(always)]
pub fn contains(&self, p: Pos2) -> bool {
self.min.x <= p.x && p.x <= self.max.x && self.min.y <= p.y && p.y <= self.max.y
}
#[must_use]
pub fn contains_rect(&self, other: Rect) -> bool {
self.contains(other.min) && self.contains(other.max)
}
/// Return the given points clamped to be inside the rectangle
/// Panics if [`Self::is_negative`].
#[must_use]
pub fn clamp(&self, p: Pos2) -> Pos2 {
p.clamp(self.min, self.max)
}
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
pub fn extend_with(&mut self, p: Pos2) {
self.min = self.min.min(p);
self.max = self.max.max(p);
}
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
2021-02-14 20:39:04 +00:00
/// Expand to include the given x coordinate
pub fn extend_with_x(&mut self, x: f32) {
self.min.x = self.min.x.min(x);
self.max.x = self.max.x.max(x);
}
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
2021-02-14 20:39:04 +00:00
/// Expand to include the given y coordinate
pub fn extend_with_y(&mut self, y: f32) {
self.min.y = self.min.y.min(y);
self.max.y = self.max.y.max(y);
}
/// The union of two bounding rectangle, i.e. the minimum `Rect`
/// that contains both input rectangles.
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
#[must_use]
pub fn union(self, other: Rect) -> Rect {
Rect {
min: self.min.min(other.min),
max: self.max.max(other.max),
}
}
/// The intersection of two `Rect`, i.e. the area covered by both.
#[inline]
#[must_use]
pub fn intersect(self, other: Rect) -> Self {
Self {
min: self.min.max(other.min),
max: self.max.min(other.max),
}
}
#[inline(always)]
pub fn center(&self) -> Pos2 {
Pos2 {
x: (self.min.x + self.max.x) / 2.0,
y: (self.min.y + self.max.y) / 2.0,
}
}
#[inline(always)]
pub fn size(&self) -> Vec2 {
self.max - self.min
}
#[inline(always)]
pub fn width(&self) -> f32 {
self.max.x - self.min.x
}
#[inline(always)]
pub fn height(&self) -> f32 {
self.max.y - self.min.y
}
/// Width / height
///
/// * `aspect_ratio < 1`: portrait / high
/// * `aspect_ratio = 1`: square
/// * `aspect_ratio > 1`: landscape / wide
pub fn aspect_ratio(&self) -> f32 {
self.width() / self.height()
}
/// `[2, 1]` for wide screen, and `[1, 2]` for portrait, etc.
/// At least one dimension = 1, the other >= 1
/// Returns the proportions required to letter-box a square view area.
pub fn square_proportions(&self) -> Vec2 {
let w = self.width();
let h = self.height();
if w > h {
vec2(w / h, 1.0)
} else {
vec2(1.0, h / w)
}
}
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
pub fn area(&self) -> f32 {
self.width() * self.height()
}
#[inline]
pub fn distance_sq_to_pos(&self, pos: Pos2) -> f32 {
let dx = if self.min.x > pos.x {
self.min.x - pos.x
} else if pos.x > self.max.x {
pos.x - self.max.x
} else {
0.0
};
let dy = if self.min.y > pos.y {
self.min.y - pos.y
} else if pos.y > self.max.y {
pos.y - self.max.y
} else {
0.0
};
dx * dx + dy * dy
}
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
2020-10-01 20:40:49 +00:00
pub fn x_range(&self) -> RangeInclusive<f32> {
self.min.x..=self.max.x
}
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
2020-10-01 20:40:49 +00:00
pub fn y_range(&self) -> RangeInclusive<f32> {
self.min.y..=self.max.y
}
New text layout (#682) This PR introduces a completely rewritten text layout engine which is simpler and more powerful. It allows mixing different text styles (heading, body, etc) and formats (color, underlining, strikethrough, …) in the same layout pass, and baked into the same `Galley`. This opens up the door to having a syntax-highlighed code editor, or a WYSIWYG markdown editor. One major change is the color is now baked in at layout time. However, many widgets changes text color on hovered. But we need to do the text layout before we know if it is hovered. Therefor the painter has an option to override the text color of a galley. ## Performance Text layout alone is about 20% slower, but a lot of that is because more tessellation is done upfront. Text tessellation is now a lot faster, but text layout + tessellation still lands at a net loss of 5-10% in performance. There are however a few tricks to speed it up (like using `smallvec`) which I am saving for later. Text layout is also cached, meaning that in most cases (when all text isn't changing each frame) text tessellation is actually more important (and that's more than 2x faster!). Sadly, the actual text cache lookup is significantly slower (300ns -> 600ns). That's because the `TextLayoutJob` is a lot bigger (it has more options, like underlining, fonts etc), so it is slower to hash and compare. I have an idea how to speed this up, but I need to do some other work before I can implement that. All in all, the performance impact on `demo_with_tesselate__realistic` is about 5-6% in the red. Not great; not terrible. The benefits are worth it, but I also think with some work I can get that down significantly, hopefully down to the old levels.
2021-09-03 16:18:00 +00:00
#[inline(always)]
pub fn bottom_up_range(&self) -> RangeInclusive<f32> {
self.max.y..=self.min.y
}
/// `width < 0 || height < 0`
#[inline(always)]
pub fn is_negative(&self) -> bool {
self.max.x < self.min.x || self.max.y < self.min.y
}
/// `width > 0 && height > 0`
#[inline(always)]
pub fn is_positive(&self) -> bool {
self.min.x < self.max.x && self.min.y < self.max.y
}
/// True if all members are also finite.
#[inline(always)]
pub fn is_finite(&self) -> bool {
self.min.is_finite() && self.max.is_finite()
}
/// True if any member is NaN.
#[inline(always)]
pub fn any_nan(self) -> bool {
self.min.any_nan() || self.max.any_nan()
}
2021-03-14 15:42:06 +00:00
}
2021-03-14 15:42:06 +00:00
/// ## Convenience functions (assumes origin is towards left top):
impl Rect {
/// `min.x`
#[inline(always)]
pub fn left(&self) -> f32 {
self.min.x
}
2021-03-14 15:42:06 +00:00
/// `min.x`
#[inline(always)]
2021-03-14 15:42:06 +00:00
pub fn left_mut(&mut self) -> &mut f32 {
&mut self.min.x
}
/// `min.x`
#[inline(always)]
2021-03-14 15:42:06 +00:00
pub fn set_left(&mut self, x: f32) {
self.min.x = x;
}
/// `max.x`
#[inline(always)]
pub fn right(&self) -> f32 {
self.max.x
}
2021-03-14 15:42:06 +00:00
/// `max.x`
#[inline(always)]
2021-03-14 15:42:06 +00:00
pub fn right_mut(&mut self) -> &mut f32 {
&mut self.max.x
}
/// `max.x`
#[inline(always)]
2021-03-14 15:42:06 +00:00
pub fn set_right(&mut self, x: f32) {
self.max.x = x;
}
/// `min.y`
#[inline(always)]
pub fn top(&self) -> f32 {
self.min.y
}
2021-03-14 15:42:06 +00:00
/// `min.y`
#[inline(always)]
2021-03-14 15:42:06 +00:00
pub fn top_mut(&mut self) -> &mut f32 {
&mut self.min.y
}
/// `min.y`
#[inline(always)]
2021-03-14 15:42:06 +00:00
pub fn set_top(&mut self, y: f32) {
self.min.y = y;
}
/// `max.y`
#[inline(always)]
pub fn bottom(&self) -> f32 {
self.max.y
}
2021-03-14 15:42:06 +00:00
/// `max.y`
#[inline(always)]
2021-03-14 15:42:06 +00:00
pub fn bottom_mut(&mut self) -> &mut f32 {
&mut self.max.y
}
/// `max.y`
#[inline(always)]
2021-03-14 15:42:06 +00:00
pub fn set_bottom(&mut self, y: f32) {
self.max.y = y;
}
#[inline(always)]
pub fn left_top(&self) -> Pos2 {
pos2(self.left(), self.top())
}
#[inline(always)]
pub fn center_top(&self) -> Pos2 {
pos2(self.center().x, self.top())
}
#[inline(always)]
pub fn right_top(&self) -> Pos2 {
pos2(self.right(), self.top())
}
#[inline(always)]
pub fn left_center(&self) -> Pos2 {
pos2(self.left(), self.center().y)
}
#[inline(always)]
pub fn right_center(&self) -> Pos2 {
pos2(self.right(), self.center().y)
}
#[inline(always)]
pub fn left_bottom(&self) -> Pos2 {
pos2(self.left(), self.bottom())
}
#[inline(always)]
pub fn center_bottom(&self) -> Pos2 {
pos2(self.center().x, self.bottom())
}
#[inline(always)]
pub fn right_bottom(&self) -> Pos2 {
pos2(self.right(), self.bottom())
}
}
impl std::fmt::Debug for Rect {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "[{:?} - {:?}]", self.min, self.max)
}
}
/// from (min, max) or (left top, right bottom)
impl From<[Pos2; 2]> for Rect {
fn from([min, max]: [Pos2; 2]) -> Self {
Self { min, max }
}
}