Use `u8` in `Rounding`, and introduce `Roundingf` (#5563)
* Part of https://github.com/emilk/egui/issues/4019 As part of the work on adding a custom `Border` to everything, I want to make sure that the size of `RectShape`, `Frame` and the future `Border` is kept small (for performance reasons). This PR changes the storage of the corner radius of rectangles from four `f32` (one for each corner) into four `u8`. This mean the corner radius can only be an integer in the range 0-255 (in ui points). This should be enough for most people. If you want to manipulate rounding using `f32`, there is a new `Roundingf` to fill that niche.
This commit is contained in:
parent
3ffe1ed774
commit
249f8bcb93
|
|
@ -1230,7 +1230,7 @@ egui_extras::install_image_loaders(egui_ctx);
|
||||||
* [Tweaked the default visuals style](https://github.com/emilk/egui/pull/450).
|
* [Tweaked the default visuals style](https://github.com/emilk/egui/pull/450).
|
||||||
* Plot: Renamed `Curve` to `Line`.
|
* Plot: Renamed `Curve` to `Line`.
|
||||||
* `TopPanel::top` is now `TopBottomPanel::top`.
|
* `TopPanel::top` is now `TopBottomPanel::top`.
|
||||||
* `SidePanel::left` no longet takes the default width by argument, but by a builder call.
|
* `SidePanel::left` no longer takes the default width by argument, but by a builder call.
|
||||||
* `SidePanel::left` is resizable by default.
|
* `SidePanel::left` is resizable by default.
|
||||||
|
|
||||||
### 🐛 Fixed
|
### 🐛 Fixed
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,9 @@ use crate::{
|
||||||
TextStyle, Ui, UiKind, Vec2b, WidgetInfo, WidgetRect, WidgetText, WidgetType,
|
TextStyle, Ui, UiKind, Vec2b, WidgetInfo, WidgetRect, WidgetText, WidgetType,
|
||||||
};
|
};
|
||||||
use emath::GuiRounding as _;
|
use emath::GuiRounding as _;
|
||||||
use epaint::{emath, pos2, vec2, Galley, Pos2, Rect, RectShape, Rounding, Shape, Stroke, Vec2};
|
use epaint::{
|
||||||
|
emath, pos2, vec2, Galley, Pos2, Rect, RectShape, Rounding, Roundingf, Shape, Stroke, Vec2,
|
||||||
|
};
|
||||||
|
|
||||||
use super::scroll_area::ScrollBarVisibility;
|
use super::scroll_area::ScrollBarVisibility;
|
||||||
use super::{area, resize, Area, Frame, Resize, ScrollArea};
|
use super::{area, resize, Area, Frame, Resize, ScrollArea};
|
||||||
|
|
@ -486,8 +488,9 @@ impl<'open> Window<'open> {
|
||||||
let style = ctx.style();
|
let style = ctx.style();
|
||||||
let spacing = window_margin.top + window_margin.bottom;
|
let spacing = window_margin.top + window_margin.bottom;
|
||||||
let height = ctx.fonts(|f| title.font_height(f, &style)) + spacing;
|
let height = ctx.fonts(|f| title.font_height(f, &style)) + spacing;
|
||||||
window_frame.rounding.ne = window_frame.rounding.ne.clamp(0.0, height / 2.0);
|
let half_height = (height / 2.0).round() as _;
|
||||||
window_frame.rounding.nw = window_frame.rounding.nw.clamp(0.0, height / 2.0);
|
window_frame.rounding.ne = window_frame.rounding.ne.clamp(0, half_height);
|
||||||
|
window_frame.rounding.nw = window_frame.rounding.nw.clamp(0, half_height);
|
||||||
(height, spacing)
|
(height, spacing)
|
||||||
} else {
|
} else {
|
||||||
(0.0, 0.0)
|
(0.0, 0.0)
|
||||||
|
|
@ -603,8 +606,8 @@ impl<'open> Window<'open> {
|
||||||
let mut round = window_frame.rounding;
|
let mut round = window_frame.rounding;
|
||||||
|
|
||||||
if !is_collapsed {
|
if !is_collapsed {
|
||||||
round.se = 0.0;
|
round.se = 0;
|
||||||
round.sw = 0.0;
|
round.sw = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
area_content_ui.painter().set(
|
area_content_ui.painter().set(
|
||||||
|
|
@ -682,6 +685,7 @@ fn paint_resize_corner(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Adjust the corner offset to accommodate for window rounding
|
// Adjust the corner offset to accommodate for window rounding
|
||||||
|
let radius = radius as f32;
|
||||||
let offset =
|
let offset =
|
||||||
((2.0_f32.sqrt() * (1.0 + radius) - radius) * 45.0_f32.to_radians().cos()).max(2.0);
|
((2.0_f32.sqrt() * (1.0 + radius) - radius) * 45.0_f32.to_radians().cos()).max(2.0);
|
||||||
|
|
||||||
|
|
@ -1022,7 +1026,7 @@ fn paint_frame_interaction(ui: &Ui, rect: Rect, interaction: ResizeInteraction)
|
||||||
bottom = interaction.bottom.hover;
|
bottom = interaction.bottom.hover;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rounding = ui.visuals().window_rounding;
|
let rounding = Roundingf::from(ui.visuals().window_rounding);
|
||||||
let Rect { min, max } = rect;
|
let Rect { min, max } = rect;
|
||||||
|
|
||||||
let mut points = Vec::new();
|
let mut points = Vec::new();
|
||||||
|
|
|
||||||
|
|
@ -1291,7 +1291,7 @@ impl Visuals {
|
||||||
warn_fg_color: Color32::from_rgb(255, 143, 0), // orange
|
warn_fg_color: Color32::from_rgb(255, 143, 0), // orange
|
||||||
error_fg_color: Color32::from_rgb(255, 0, 0), // red
|
error_fg_color: Color32::from_rgb(255, 0, 0), // red
|
||||||
|
|
||||||
window_rounding: Rounding::same(6.0),
|
window_rounding: Rounding::same(6),
|
||||||
window_shadow: Shadow {
|
window_shadow: Shadow {
|
||||||
offset: vec2(10.0, 20.0),
|
offset: vec2(10.0, 20.0),
|
||||||
blur: 15.0,
|
blur: 15.0,
|
||||||
|
|
@ -1302,7 +1302,7 @@ impl Visuals {
|
||||||
window_stroke: Stroke::new(1.0, Color32::from_gray(60)),
|
window_stroke: Stroke::new(1.0, Color32::from_gray(60)),
|
||||||
window_highlight_topmost: true,
|
window_highlight_topmost: true,
|
||||||
|
|
||||||
menu_rounding: Rounding::same(6.0),
|
menu_rounding: Rounding::same(6),
|
||||||
|
|
||||||
panel_fill: Color32::from_gray(27),
|
panel_fill: Color32::from_gray(27),
|
||||||
|
|
||||||
|
|
@ -1412,7 +1412,7 @@ impl Widgets {
|
||||||
bg_fill: Color32::from_gray(27),
|
bg_fill: Color32::from_gray(27),
|
||||||
bg_stroke: Stroke::new(1.0, Color32::from_gray(60)), // separators, indentation lines
|
bg_stroke: Stroke::new(1.0, Color32::from_gray(60)), // separators, indentation lines
|
||||||
fg_stroke: Stroke::new(1.0, Color32::from_gray(140)), // normal text color
|
fg_stroke: Stroke::new(1.0, Color32::from_gray(140)), // normal text color
|
||||||
rounding: Rounding::same(2.0),
|
rounding: Rounding::same(2),
|
||||||
expansion: 0.0,
|
expansion: 0.0,
|
||||||
},
|
},
|
||||||
inactive: WidgetVisuals {
|
inactive: WidgetVisuals {
|
||||||
|
|
@ -1420,7 +1420,7 @@ impl Widgets {
|
||||||
bg_fill: Color32::from_gray(60), // checkbox background
|
bg_fill: Color32::from_gray(60), // checkbox background
|
||||||
bg_stroke: Default::default(),
|
bg_stroke: Default::default(),
|
||||||
fg_stroke: Stroke::new(1.0, Color32::from_gray(180)), // button text
|
fg_stroke: Stroke::new(1.0, Color32::from_gray(180)), // button text
|
||||||
rounding: Rounding::same(2.0),
|
rounding: Rounding::same(2),
|
||||||
expansion: 0.0,
|
expansion: 0.0,
|
||||||
},
|
},
|
||||||
hovered: WidgetVisuals {
|
hovered: WidgetVisuals {
|
||||||
|
|
@ -1428,7 +1428,7 @@ impl Widgets {
|
||||||
bg_fill: Color32::from_gray(70),
|
bg_fill: Color32::from_gray(70),
|
||||||
bg_stroke: Stroke::new(1.0, Color32::from_gray(150)), // e.g. hover over window edge or button
|
bg_stroke: Stroke::new(1.0, Color32::from_gray(150)), // e.g. hover over window edge or button
|
||||||
fg_stroke: Stroke::new(1.5, Color32::from_gray(240)),
|
fg_stroke: Stroke::new(1.5, Color32::from_gray(240)),
|
||||||
rounding: Rounding::same(3.0),
|
rounding: Rounding::same(3),
|
||||||
expansion: 1.0,
|
expansion: 1.0,
|
||||||
},
|
},
|
||||||
active: WidgetVisuals {
|
active: WidgetVisuals {
|
||||||
|
|
@ -1436,7 +1436,7 @@ impl Widgets {
|
||||||
bg_fill: Color32::from_gray(55),
|
bg_fill: Color32::from_gray(55),
|
||||||
bg_stroke: Stroke::new(1.0, Color32::WHITE),
|
bg_stroke: Stroke::new(1.0, Color32::WHITE),
|
||||||
fg_stroke: Stroke::new(2.0, Color32::WHITE),
|
fg_stroke: Stroke::new(2.0, Color32::WHITE),
|
||||||
rounding: Rounding::same(2.0),
|
rounding: Rounding::same(2),
|
||||||
expansion: 1.0,
|
expansion: 1.0,
|
||||||
},
|
},
|
||||||
open: WidgetVisuals {
|
open: WidgetVisuals {
|
||||||
|
|
@ -1444,7 +1444,7 @@ impl Widgets {
|
||||||
bg_fill: Color32::from_gray(27),
|
bg_fill: Color32::from_gray(27),
|
||||||
bg_stroke: Stroke::new(1.0, Color32::from_gray(60)),
|
bg_stroke: Stroke::new(1.0, Color32::from_gray(60)),
|
||||||
fg_stroke: Stroke::new(1.0, Color32::from_gray(210)),
|
fg_stroke: Stroke::new(1.0, Color32::from_gray(210)),
|
||||||
rounding: Rounding::same(2.0),
|
rounding: Rounding::same(2),
|
||||||
expansion: 0.0,
|
expansion: 0.0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -1457,7 +1457,7 @@ impl Widgets {
|
||||||
bg_fill: Color32::from_gray(248),
|
bg_fill: Color32::from_gray(248),
|
||||||
bg_stroke: Stroke::new(1.0, Color32::from_gray(190)), // separators, indentation lines
|
bg_stroke: Stroke::new(1.0, Color32::from_gray(190)), // separators, indentation lines
|
||||||
fg_stroke: Stroke::new(1.0, Color32::from_gray(80)), // normal text color
|
fg_stroke: Stroke::new(1.0, Color32::from_gray(80)), // normal text color
|
||||||
rounding: Rounding::same(2.0),
|
rounding: Rounding::same(2),
|
||||||
expansion: 0.0,
|
expansion: 0.0,
|
||||||
},
|
},
|
||||||
inactive: WidgetVisuals {
|
inactive: WidgetVisuals {
|
||||||
|
|
@ -1465,7 +1465,7 @@ impl Widgets {
|
||||||
bg_fill: Color32::from_gray(230), // checkbox background
|
bg_fill: Color32::from_gray(230), // checkbox background
|
||||||
bg_stroke: Default::default(),
|
bg_stroke: Default::default(),
|
||||||
fg_stroke: Stroke::new(1.0, Color32::from_gray(60)), // button text
|
fg_stroke: Stroke::new(1.0, Color32::from_gray(60)), // button text
|
||||||
rounding: Rounding::same(2.0),
|
rounding: Rounding::same(2),
|
||||||
expansion: 0.0,
|
expansion: 0.0,
|
||||||
},
|
},
|
||||||
hovered: WidgetVisuals {
|
hovered: WidgetVisuals {
|
||||||
|
|
@ -1473,7 +1473,7 @@ impl Widgets {
|
||||||
bg_fill: Color32::from_gray(220),
|
bg_fill: Color32::from_gray(220),
|
||||||
bg_stroke: Stroke::new(1.0, Color32::from_gray(105)), // e.g. hover over window edge or button
|
bg_stroke: Stroke::new(1.0, Color32::from_gray(105)), // e.g. hover over window edge or button
|
||||||
fg_stroke: Stroke::new(1.5, Color32::BLACK),
|
fg_stroke: Stroke::new(1.5, Color32::BLACK),
|
||||||
rounding: Rounding::same(3.0),
|
rounding: Rounding::same(3),
|
||||||
expansion: 1.0,
|
expansion: 1.0,
|
||||||
},
|
},
|
||||||
active: WidgetVisuals {
|
active: WidgetVisuals {
|
||||||
|
|
@ -1481,7 +1481,7 @@ impl Widgets {
|
||||||
bg_fill: Color32::from_gray(165),
|
bg_fill: Color32::from_gray(165),
|
||||||
bg_stroke: Stroke::new(1.0, Color32::BLACK),
|
bg_stroke: Stroke::new(1.0, Color32::BLACK),
|
||||||
fg_stroke: Stroke::new(2.0, Color32::BLACK),
|
fg_stroke: Stroke::new(2.0, Color32::BLACK),
|
||||||
rounding: Rounding::same(2.0),
|
rounding: Rounding::same(2),
|
||||||
expansion: 1.0,
|
expansion: 1.0,
|
||||||
},
|
},
|
||||||
open: WidgetVisuals {
|
open: WidgetVisuals {
|
||||||
|
|
@ -1489,7 +1489,7 @@ impl Widgets {
|
||||||
bg_fill: Color32::from_gray(220),
|
bg_fill: Color32::from_gray(220),
|
||||||
bg_stroke: Stroke::new(1.0, Color32::from_gray(160)),
|
bg_stroke: Stroke::new(1.0, Color32::from_gray(160)),
|
||||||
fg_stroke: Stroke::new(1.0, Color32::BLACK),
|
fg_stroke: Stroke::new(1.0, Color32::BLACK),
|
||||||
rounding: Rounding::same(2.0),
|
rounding: Rounding::same(2),
|
||||||
expansion: 0.0,
|
expansion: 0.0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -2420,9 +2420,16 @@ impl Widget for &mut Rounding {
|
||||||
|
|
||||||
// Apply the checkbox:
|
// Apply the checkbox:
|
||||||
if same {
|
if same {
|
||||||
*self = Rounding::same((self.nw + self.ne + self.sw + self.se) / 4.0);
|
*self = Rounding::from(self.average());
|
||||||
} else if self.is_same() {
|
} else {
|
||||||
self.se *= 1.00001; // prevent collapsing into sameness
|
// Make sure we aren't same:
|
||||||
|
if self.is_same() {
|
||||||
|
if self.average() == 0.0 {
|
||||||
|
self.se = 1;
|
||||||
|
} else {
|
||||||
|
self.se -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
response
|
response
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ fn color_button(ui: &mut Ui, color: Color32, open: bool) -> Response {
|
||||||
|
|
||||||
show_color_at(ui.painter(), color, rect);
|
show_color_at(ui.painter(), color, rect);
|
||||||
|
|
||||||
let rounding = visuals.rounding.at_most(2.0); // Can't do more rounding because the background grid doesn't do any rounding
|
let rounding = visuals.rounding.at_most(2); // Can't do more rounding because the background grid doesn't do any rounding
|
||||||
ui.painter()
|
ui.painter()
|
||||||
.rect_stroke(rect, rounding, (2.0, visuals.bg_fill)); // fill is intentional, because default style has no border
|
.rect_stroke(rect, rounding, (2.0, visuals.bg_fill)); // fill is intentional, because default style has no border
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,8 @@ impl Widget for ProgressBar {
|
||||||
let rounding = rounding.unwrap_or_else(|| corner_radius.into());
|
let rounding = rounding.unwrap_or_else(|| corner_radius.into());
|
||||||
ui.painter()
|
ui.painter()
|
||||||
.rect(outer_rect, rounding, visuals.extreme_bg_color, Stroke::NONE);
|
.rect(outer_rect, rounding, visuals.extreme_bg_color, Stroke::NONE);
|
||||||
let min_width = 2.0 * rounding.sw.at_least(rounding.nw).at_most(corner_radius);
|
let min_width =
|
||||||
|
2.0 * f32::max(rounding.sw as _, rounding.nw as _).at_most(corner_radius);
|
||||||
let filled_width = (outer_rect.width() * progress).at_least(min_width);
|
let filled_width = (outer_rect.width() * progress).at_least(min_width);
|
||||||
let inner_rect =
|
let inner_rect =
|
||||||
Rect::from_min_size(outer_rect.min, vec2(filled_width, outer_rect.height()));
|
Rect::from_min_size(outer_rect.min, vec2(filled_width, outer_rect.height()));
|
||||||
|
|
|
||||||
|
|
@ -780,10 +780,10 @@ impl<'a> Slider<'a> {
|
||||||
// The trailing rect has to be drawn differently depending on the orientation.
|
// The trailing rect has to be drawn differently depending on the orientation.
|
||||||
match self.orientation {
|
match self.orientation {
|
||||||
SliderOrientation::Horizontal => {
|
SliderOrientation::Horizontal => {
|
||||||
trailing_rail_rect.max.x = center.x + rounding.nw;
|
trailing_rail_rect.max.x = center.x + rounding.nw as f32;
|
||||||
}
|
}
|
||||||
SliderOrientation::Vertical => {
|
SliderOrientation::Vertical => {
|
||||||
trailing_rail_rect.min.y = center.y - rounding.se;
|
trailing_rail_rect.min.y = center.y - rounding.se as f32;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ impl crate::View for PanZoom {
|
||||||
.show(ui.ctx(), |ui| {
|
.show(ui.ctx(), |ui| {
|
||||||
ui.set_clip_rect(transform.inverse() * rect);
|
ui.set_clip_rect(transform.inverse() * rect);
|
||||||
egui::Frame::default()
|
egui::Frame::default()
|
||||||
.rounding(egui::Rounding::same(4.0))
|
.rounding(egui::Rounding::same(4))
|
||||||
.inner_margin(egui::Margin::same(8.0))
|
.inner_margin(egui::Margin::same(8.0))
|
||||||
.stroke(ui.ctx().style().visuals.window_stroke)
|
.stroke(ui.ctx().style().visuals.window_stroke)
|
||||||
.fill(ui.style().visuals.panel_fill)
|
.fill(ui.style().visuals.panel_fill)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ pub mod image;
|
||||||
mod margin;
|
mod margin;
|
||||||
mod mesh;
|
mod mesh;
|
||||||
pub mod mutex;
|
pub mod mutex;
|
||||||
|
mod rounding;
|
||||||
|
mod roundingf;
|
||||||
mod shadow;
|
mod shadow;
|
||||||
mod shape;
|
mod shape;
|
||||||
pub mod shape_transform;
|
pub mod shape_transform;
|
||||||
|
|
@ -47,10 +49,12 @@ pub use self::{
|
||||||
image::{ColorImage, FontImage, ImageData, ImageDelta},
|
image::{ColorImage, FontImage, ImageData, ImageDelta},
|
||||||
margin::Margin,
|
margin::Margin,
|
||||||
mesh::{Mesh, Mesh16, Vertex},
|
mesh::{Mesh, Mesh16, Vertex},
|
||||||
|
rounding::Rounding,
|
||||||
|
roundingf::Roundingf,
|
||||||
shadow::Shadow,
|
shadow::Shadow,
|
||||||
shape::{
|
shape::{
|
||||||
CircleShape, EllipseShape, PaintCallback, PaintCallbackInfo, PathShape, RectShape,
|
CircleShape, EllipseShape, PaintCallback, PaintCallbackInfo, PathShape, RectShape, Shape,
|
||||||
Rounding, Shape, TextShape,
|
TextShape,
|
||||||
},
|
},
|
||||||
stats::PaintStats,
|
stats::PaintStats,
|
||||||
stroke::{PathStroke, Stroke, StrokeKind},
|
stroke::{PathStroke, Stroke, StrokeKind},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,220 @@
|
||||||
|
/// How rounded the corners of things should be.
|
||||||
|
///
|
||||||
|
/// The rounding uses `u8` to save space,
|
||||||
|
/// so the amount of rounding is limited to integers in the range `[0, 255]`.
|
||||||
|
///
|
||||||
|
/// For calculations, you may want to use [`crate::Roundingf`] instead, which uses `f32`.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
pub struct Rounding {
|
||||||
|
/// Radius of the rounding of the North-West (left top) corner.
|
||||||
|
pub nw: u8,
|
||||||
|
|
||||||
|
/// Radius of the rounding of the North-East (right top) corner.
|
||||||
|
pub ne: u8,
|
||||||
|
|
||||||
|
/// Radius of the rounding of the South-West (left bottom) corner.
|
||||||
|
pub sw: u8,
|
||||||
|
|
||||||
|
/// Radius of the rounding of the South-East (right bottom) corner.
|
||||||
|
pub se: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Rounding {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::ZERO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for Rounding {
|
||||||
|
#[inline]
|
||||||
|
fn from(radius: u8) -> Self {
|
||||||
|
Self::same(radius)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<f32> for Rounding {
|
||||||
|
#[inline]
|
||||||
|
fn from(radius: f32) -> Self {
|
||||||
|
Self::same(radius.round() as u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rounding {
|
||||||
|
/// No rounding on any corner.
|
||||||
|
pub const ZERO: Self = Self {
|
||||||
|
nw: 0,
|
||||||
|
ne: 0,
|
||||||
|
sw: 0,
|
||||||
|
se: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Same rounding on all four corners.
|
||||||
|
#[inline]
|
||||||
|
pub const fn same(radius: u8) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: radius,
|
||||||
|
ne: radius,
|
||||||
|
sw: radius,
|
||||||
|
se: radius,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Do all corners have the same rounding?
|
||||||
|
#[inline]
|
||||||
|
pub fn is_same(self) -> bool {
|
||||||
|
self.nw == self.ne && self.nw == self.sw && self.nw == self.se
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make sure each corner has a rounding of at least this.
|
||||||
|
#[inline]
|
||||||
|
pub fn at_least(self, min: u8) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: self.nw.max(min),
|
||||||
|
ne: self.ne.max(min),
|
||||||
|
sw: self.sw.max(min),
|
||||||
|
se: self.se.max(min),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make sure each corner has a rounding of at most this.
|
||||||
|
#[inline]
|
||||||
|
pub fn at_most(self, max: u8) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: self.nw.min(max),
|
||||||
|
ne: self.ne.min(max),
|
||||||
|
sw: self.sw.min(max),
|
||||||
|
se: self.se.min(max),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Average rounding of the corners.
|
||||||
|
pub fn average(&self) -> f32 {
|
||||||
|
(self.nw as f32 + self.ne as f32 + self.sw as f32 + self.se as f32) / 4.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Add for Rounding {
|
||||||
|
type Output = Self;
|
||||||
|
#[inline]
|
||||||
|
fn add(self, rhs: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: self.nw + rhs.nw,
|
||||||
|
ne: self.ne + rhs.ne,
|
||||||
|
sw: self.sw + rhs.sw,
|
||||||
|
se: self.se + rhs.se,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::AddAssign for Rounding {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
*self = Self {
|
||||||
|
nw: self.nw + rhs.nw,
|
||||||
|
ne: self.ne + rhs.ne,
|
||||||
|
sw: self.sw + rhs.sw,
|
||||||
|
se: self.se + rhs.se,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::AddAssign<u8> for Rounding {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, rhs: u8) {
|
||||||
|
*self = Self {
|
||||||
|
nw: self.nw.saturating_add(rhs),
|
||||||
|
ne: self.ne.saturating_add(rhs),
|
||||||
|
sw: self.sw.saturating_add(rhs),
|
||||||
|
se: self.se.saturating_add(rhs),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Sub for Rounding {
|
||||||
|
type Output = Self;
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, rhs: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: self.nw.saturating_sub(rhs.nw),
|
||||||
|
ne: self.ne.saturating_sub(rhs.ne),
|
||||||
|
sw: self.sw.saturating_sub(rhs.sw),
|
||||||
|
se: self.se.saturating_sub(rhs.se),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::SubAssign for Rounding {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
|
*self = Self {
|
||||||
|
nw: self.nw.saturating_sub(rhs.nw),
|
||||||
|
ne: self.ne.saturating_sub(rhs.ne),
|
||||||
|
sw: self.sw.saturating_sub(rhs.sw),
|
||||||
|
se: self.se.saturating_sub(rhs.se),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::SubAssign<u8> for Rounding {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, rhs: u8) {
|
||||||
|
*self = Self {
|
||||||
|
nw: self.nw.saturating_sub(rhs),
|
||||||
|
ne: self.ne.saturating_sub(rhs),
|
||||||
|
sw: self.sw.saturating_sub(rhs),
|
||||||
|
se: self.se.saturating_sub(rhs),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Div<f32> for Rounding {
|
||||||
|
type Output = Self;
|
||||||
|
#[inline]
|
||||||
|
fn div(self, rhs: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: (self.nw as f32 / rhs) as u8,
|
||||||
|
ne: (self.ne as f32 / rhs) as u8,
|
||||||
|
sw: (self.sw as f32 / rhs) as u8,
|
||||||
|
se: (self.se as f32 / rhs) as u8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DivAssign<f32> for Rounding {
|
||||||
|
#[inline]
|
||||||
|
fn div_assign(&mut self, rhs: f32) {
|
||||||
|
*self = Self {
|
||||||
|
nw: (self.nw as f32 / rhs) as u8,
|
||||||
|
ne: (self.ne as f32 / rhs) as u8,
|
||||||
|
sw: (self.sw as f32 / rhs) as u8,
|
||||||
|
se: (self.se as f32 / rhs) as u8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Mul<f32> for Rounding {
|
||||||
|
type Output = Self;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, rhs: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: (self.nw as f32 * rhs) as u8,
|
||||||
|
ne: (self.ne as f32 * rhs) as u8,
|
||||||
|
sw: (self.sw as f32 * rhs) as u8,
|
||||||
|
se: (self.se as f32 * rhs) as u8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::MulAssign<f32> for Rounding {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, rhs: f32) {
|
||||||
|
*self = Self {
|
||||||
|
nw: (self.nw as f32 * rhs) as u8,
|
||||||
|
ne: (self.ne as f32 * rhs) as u8,
|
||||||
|
sw: (self.sw as f32 * rhs) as u8,
|
||||||
|
se: (self.se as f32 * rhs) as u8,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,236 @@
|
||||||
|
use crate::Rounding;
|
||||||
|
|
||||||
|
/// How rounded the corners of things should be, in `f32`.
|
||||||
|
///
|
||||||
|
/// This is used for calculations, but storage is usually done with the more compact [`Rounding`].
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
pub struct Roundingf {
|
||||||
|
/// Radius of the rounding of the North-West (left top) corner.
|
||||||
|
pub nw: f32,
|
||||||
|
|
||||||
|
/// Radius of the rounding of the North-East (right top) corner.
|
||||||
|
pub ne: f32,
|
||||||
|
|
||||||
|
/// Radius of the rounding of the South-West (left bottom) corner.
|
||||||
|
pub sw: f32,
|
||||||
|
|
||||||
|
/// Radius of the rounding of the South-East (right bottom) corner.
|
||||||
|
pub se: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Rounding> for Roundingf {
|
||||||
|
#[inline]
|
||||||
|
fn from(rounding: Rounding) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: rounding.nw as f32,
|
||||||
|
ne: rounding.ne as f32,
|
||||||
|
sw: rounding.sw as f32,
|
||||||
|
se: rounding.se as f32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Roundingf> for Rounding {
|
||||||
|
#[inline]
|
||||||
|
fn from(rounding: Roundingf) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: rounding.nw.round() as u8,
|
||||||
|
ne: rounding.ne.round() as u8,
|
||||||
|
sw: rounding.sw.round() as u8,
|
||||||
|
se: rounding.se.round() as u8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Roundingf {
|
||||||
|
#[inline]
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::ZERO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<f32> for Roundingf {
|
||||||
|
#[inline]
|
||||||
|
fn from(radius: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: radius,
|
||||||
|
ne: radius,
|
||||||
|
sw: radius,
|
||||||
|
se: radius,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Roundingf {
|
||||||
|
/// No rounding on any corner.
|
||||||
|
pub const ZERO: Self = Self {
|
||||||
|
nw: 0.0,
|
||||||
|
ne: 0.0,
|
||||||
|
sw: 0.0,
|
||||||
|
se: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Same rounding on all four corners.
|
||||||
|
#[inline]
|
||||||
|
pub const fn same(radius: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: radius,
|
||||||
|
ne: radius,
|
||||||
|
sw: radius,
|
||||||
|
se: radius,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Do all corners have the same rounding?
|
||||||
|
#[inline]
|
||||||
|
pub fn is_same(&self) -> bool {
|
||||||
|
self.nw == self.ne && self.nw == self.sw && self.nw == self.se
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make sure each corner has a rounding of at least this.
|
||||||
|
#[inline]
|
||||||
|
pub fn at_least(&self, min: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: self.nw.max(min),
|
||||||
|
ne: self.ne.max(min),
|
||||||
|
sw: self.sw.max(min),
|
||||||
|
se: self.se.max(min),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make sure each corner has a rounding of at most this.
|
||||||
|
#[inline]
|
||||||
|
pub fn at_most(&self, max: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: self.nw.min(max),
|
||||||
|
ne: self.ne.min(max),
|
||||||
|
sw: self.sw.min(max),
|
||||||
|
se: self.se.min(max),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Add for Roundingf {
|
||||||
|
type Output = Self;
|
||||||
|
#[inline]
|
||||||
|
fn add(self, rhs: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: self.nw + rhs.nw,
|
||||||
|
ne: self.ne + rhs.ne,
|
||||||
|
sw: self.sw + rhs.sw,
|
||||||
|
se: self.se + rhs.se,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::AddAssign for Roundingf {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
*self = Self {
|
||||||
|
nw: self.nw + rhs.nw,
|
||||||
|
ne: self.ne + rhs.ne,
|
||||||
|
sw: self.sw + rhs.sw,
|
||||||
|
se: self.se + rhs.se,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::AddAssign<f32> for Roundingf {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, rhs: f32) {
|
||||||
|
*self = Self {
|
||||||
|
nw: self.nw + rhs,
|
||||||
|
ne: self.ne + rhs,
|
||||||
|
sw: self.sw + rhs,
|
||||||
|
se: self.se + rhs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Sub for Roundingf {
|
||||||
|
type Output = Self;
|
||||||
|
#[inline]
|
||||||
|
fn sub(self, rhs: Self) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: self.nw - rhs.nw,
|
||||||
|
ne: self.ne - rhs.ne,
|
||||||
|
sw: self.sw - rhs.sw,
|
||||||
|
se: self.se - rhs.se,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::SubAssign for Roundingf {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, rhs: Self) {
|
||||||
|
*self = Self {
|
||||||
|
nw: self.nw - rhs.nw,
|
||||||
|
ne: self.ne - rhs.ne,
|
||||||
|
sw: self.sw - rhs.sw,
|
||||||
|
se: self.se - rhs.se,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::SubAssign<f32> for Roundingf {
|
||||||
|
#[inline]
|
||||||
|
fn sub_assign(&mut self, rhs: f32) {
|
||||||
|
*self = Self {
|
||||||
|
nw: self.nw - rhs,
|
||||||
|
ne: self.ne - rhs,
|
||||||
|
sw: self.sw - rhs,
|
||||||
|
se: self.se - rhs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Div<f32> for Roundingf {
|
||||||
|
type Output = Self;
|
||||||
|
#[inline]
|
||||||
|
fn div(self, rhs: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: self.nw / rhs,
|
||||||
|
ne: self.ne / rhs,
|
||||||
|
sw: self.sw / rhs,
|
||||||
|
se: self.se / rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DivAssign<f32> for Roundingf {
|
||||||
|
#[inline]
|
||||||
|
fn div_assign(&mut self, rhs: f32) {
|
||||||
|
*self = Self {
|
||||||
|
nw: self.nw / rhs,
|
||||||
|
ne: self.ne / rhs,
|
||||||
|
sw: self.sw / rhs,
|
||||||
|
se: self.se / rhs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Mul<f32> for Roundingf {
|
||||||
|
type Output = Self;
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, rhs: f32) -> Self {
|
||||||
|
Self {
|
||||||
|
nw: self.nw * rhs,
|
||||||
|
ne: self.ne * rhs,
|
||||||
|
sw: self.sw * rhs,
|
||||||
|
se: self.se * rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::MulAssign<f32> for Roundingf {
|
||||||
|
#[inline]
|
||||||
|
fn mul_assign(&mut self, rhs: f32) {
|
||||||
|
*self = Self {
|
||||||
|
nw: self.nw * rhs,
|
||||||
|
ne: self.ne * rhs,
|
||||||
|
sw: self.sw * rhs,
|
||||||
|
se: self.se * rhs,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ impl Shadow {
|
||||||
} = *self;
|
} = *self;
|
||||||
|
|
||||||
let rect = rect.translate(offset).expand(spread);
|
let rect = rect.translate(offset).expand(spread);
|
||||||
let rounding = rounding.into() + Rounding::same(spread.abs());
|
let rounding = rounding.into() + Rounding::from(spread.abs());
|
||||||
|
|
||||||
RectShape::filled(rect, rounding, color).with_blur_width(blur)
|
RectShape::filled(rect, rounding, color).with_blur_width(blur)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use std::{any::Any, sync::Arc};
|
||||||
use crate::{
|
use crate::{
|
||||||
stroke::PathStroke,
|
stroke::PathStroke,
|
||||||
text::{FontId, Fonts, Galley},
|
text::{FontId, Fonts, Galley},
|
||||||
Color32, Mesh, Stroke, TextureId,
|
Color32, Mesh, Rounding, Stroke, TextureId,
|
||||||
};
|
};
|
||||||
use emath::{pos2, Align2, Pos2, Rangef, Rect, TSTransform, Vec2};
|
use emath::{pos2, Align2, Pos2, Rangef, Rect, TSTransform, Vec2};
|
||||||
|
|
||||||
|
|
@ -779,214 +779,6 @@ impl From<RectShape> for Shape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
|
||||||
/// How rounded the corners of things should be
|
|
||||||
pub struct Rounding {
|
|
||||||
/// Radius of the rounding of the North-West (left top) corner.
|
|
||||||
pub nw: f32,
|
|
||||||
|
|
||||||
/// Radius of the rounding of the North-East (right top) corner.
|
|
||||||
pub ne: f32,
|
|
||||||
|
|
||||||
/// Radius of the rounding of the South-West (left bottom) corner.
|
|
||||||
pub sw: f32,
|
|
||||||
|
|
||||||
/// Radius of the rounding of the South-East (right bottom) corner.
|
|
||||||
pub se: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Rounding {
|
|
||||||
#[inline]
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::ZERO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<f32> for Rounding {
|
|
||||||
#[inline]
|
|
||||||
fn from(radius: f32) -> Self {
|
|
||||||
Self {
|
|
||||||
nw: radius,
|
|
||||||
ne: radius,
|
|
||||||
sw: radius,
|
|
||||||
se: radius,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rounding {
|
|
||||||
/// No rounding on any corner.
|
|
||||||
pub const ZERO: Self = Self {
|
|
||||||
nw: 0.0,
|
|
||||||
ne: 0.0,
|
|
||||||
sw: 0.0,
|
|
||||||
se: 0.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub const fn same(radius: f32) -> Self {
|
|
||||||
Self {
|
|
||||||
nw: radius,
|
|
||||||
ne: radius,
|
|
||||||
sw: radius,
|
|
||||||
se: radius,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Do all corners have the same rounding?
|
|
||||||
#[inline]
|
|
||||||
pub fn is_same(&self) -> bool {
|
|
||||||
self.nw == self.ne && self.nw == self.sw && self.nw == self.se
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Make sure each corner has a rounding of at least this.
|
|
||||||
#[inline]
|
|
||||||
pub fn at_least(&self, min: f32) -> Self {
|
|
||||||
Self {
|
|
||||||
nw: self.nw.max(min),
|
|
||||||
ne: self.ne.max(min),
|
|
||||||
sw: self.sw.max(min),
|
|
||||||
se: self.se.max(min),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Make sure each corner has a rounding of at most this.
|
|
||||||
#[inline]
|
|
||||||
pub fn at_most(&self, max: f32) -> Self {
|
|
||||||
Self {
|
|
||||||
nw: self.nw.min(max),
|
|
||||||
ne: self.ne.min(max),
|
|
||||||
sw: self.sw.min(max),
|
|
||||||
se: self.se.min(max),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::Add for Rounding {
|
|
||||||
type Output = Self;
|
|
||||||
#[inline]
|
|
||||||
fn add(self, rhs: Self) -> Self {
|
|
||||||
Self {
|
|
||||||
nw: self.nw + rhs.nw,
|
|
||||||
ne: self.ne + rhs.ne,
|
|
||||||
sw: self.sw + rhs.sw,
|
|
||||||
se: self.se + rhs.se,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::AddAssign for Rounding {
|
|
||||||
#[inline]
|
|
||||||
fn add_assign(&mut self, rhs: Self) {
|
|
||||||
*self = Self {
|
|
||||||
nw: self.nw + rhs.nw,
|
|
||||||
ne: self.ne + rhs.ne,
|
|
||||||
sw: self.sw + rhs.sw,
|
|
||||||
se: self.se + rhs.se,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::AddAssign<f32> for Rounding {
|
|
||||||
#[inline]
|
|
||||||
fn add_assign(&mut self, rhs: f32) {
|
|
||||||
*self = Self {
|
|
||||||
nw: self.nw + rhs,
|
|
||||||
ne: self.ne + rhs,
|
|
||||||
sw: self.sw + rhs,
|
|
||||||
se: self.se + rhs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::Sub for Rounding {
|
|
||||||
type Output = Self;
|
|
||||||
#[inline]
|
|
||||||
fn sub(self, rhs: Self) -> Self {
|
|
||||||
Self {
|
|
||||||
nw: self.nw - rhs.nw,
|
|
||||||
ne: self.ne - rhs.ne,
|
|
||||||
sw: self.sw - rhs.sw,
|
|
||||||
se: self.se - rhs.se,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::SubAssign for Rounding {
|
|
||||||
#[inline]
|
|
||||||
fn sub_assign(&mut self, rhs: Self) {
|
|
||||||
*self = Self {
|
|
||||||
nw: self.nw - rhs.nw,
|
|
||||||
ne: self.ne - rhs.ne,
|
|
||||||
sw: self.sw - rhs.sw,
|
|
||||||
se: self.se - rhs.se,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::SubAssign<f32> for Rounding {
|
|
||||||
#[inline]
|
|
||||||
fn sub_assign(&mut self, rhs: f32) {
|
|
||||||
*self = Self {
|
|
||||||
nw: self.nw - rhs,
|
|
||||||
ne: self.ne - rhs,
|
|
||||||
sw: self.sw - rhs,
|
|
||||||
se: self.se - rhs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::Div<f32> for Rounding {
|
|
||||||
type Output = Self;
|
|
||||||
#[inline]
|
|
||||||
fn div(self, rhs: f32) -> Self {
|
|
||||||
Self {
|
|
||||||
nw: self.nw / rhs,
|
|
||||||
ne: self.ne / rhs,
|
|
||||||
sw: self.sw / rhs,
|
|
||||||
se: self.se / rhs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::DivAssign<f32> for Rounding {
|
|
||||||
#[inline]
|
|
||||||
fn div_assign(&mut self, rhs: f32) {
|
|
||||||
*self = Self {
|
|
||||||
nw: self.nw / rhs,
|
|
||||||
ne: self.ne / rhs,
|
|
||||||
sw: self.sw / rhs,
|
|
||||||
se: self.se / rhs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::Mul<f32> for Rounding {
|
|
||||||
type Output = Self;
|
|
||||||
#[inline]
|
|
||||||
fn mul(self, rhs: f32) -> Self {
|
|
||||||
Self {
|
|
||||||
nw: self.nw * rhs,
|
|
||||||
ne: self.ne * rhs,
|
|
||||||
sw: self.sw * rhs,
|
|
||||||
se: self.se * rhs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::MulAssign<f32> for Rounding {
|
|
||||||
#[inline]
|
|
||||||
fn mul_assign(&mut self, rhs: f32) {
|
|
||||||
*self = Self {
|
|
||||||
nw: self.nw * rhs,
|
|
||||||
ne: self.ne * rhs,
|
|
||||||
sw: self.sw * rhs,
|
|
||||||
se: self.se * rhs,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// How to paint some text on screen.
|
/// How to paint some text on screen.
|
||||||
|
|
|
||||||
|
|
@ -525,7 +525,7 @@ impl Path {
|
||||||
|
|
||||||
pub mod path {
|
pub mod path {
|
||||||
//! Helpers for constructing paths
|
//! Helpers for constructing paths
|
||||||
use crate::shape::Rounding;
|
use crate::Rounding;
|
||||||
use emath::{pos2, Pos2, Rect};
|
use emath::{pos2, Pos2, Rect};
|
||||||
|
|
||||||
/// overwrites existing points
|
/// overwrites existing points
|
||||||
|
|
@ -548,6 +548,8 @@ pub mod path {
|
||||||
// Duplicated vertices can happen when one side is all rounding, with no straight edge between.
|
// Duplicated vertices can happen when one side is all rounding, with no straight edge between.
|
||||||
let eps = f32::EPSILON * rect.size().max_elem();
|
let eps = f32::EPSILON * rect.size().max_elem();
|
||||||
|
|
||||||
|
let r = crate::Roundingf::from(r);
|
||||||
|
|
||||||
add_circle_quadrant(path, pos2(max.x - r.se, max.y - r.se), r.se, 0.0); // south east
|
add_circle_quadrant(path, pos2(max.x - r.se, max.y - r.se), r.se, 0.0); // south east
|
||||||
|
|
||||||
if rect.width() <= r.se + r.sw + eps {
|
if rect.width() <= r.se + r.sw + eps {
|
||||||
|
|
@ -628,7 +630,7 @@ pub mod path {
|
||||||
let half_width = rect.width() * 0.5;
|
let half_width = rect.width() * 0.5;
|
||||||
let half_height = rect.height() * 0.5;
|
let half_height = rect.height() * 0.5;
|
||||||
let max_cr = half_width.min(half_height);
|
let max_cr = half_width.min(half_height);
|
||||||
rounding.at_most(max_cr).at_least(0.0)
|
rounding.at_most(max_cr.floor() as _).at_least(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1741,7 +1743,7 @@ impl Tessellator {
|
||||||
.at_most(rect.size().min_elem() - eps)
|
.at_most(rect.size().min_elem() - eps)
|
||||||
.at_least(0.0);
|
.at_least(0.0);
|
||||||
|
|
||||||
rounding += Rounding::same(0.5 * blur_width);
|
rounding += Rounding::from(0.5 * blur_width);
|
||||||
|
|
||||||
self.feathering = self.feathering.max(blur_width);
|
self.feathering = self.feathering.max(blur_width);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue