Fixing padding/shadow calculations on Container

Fixes #158
This commit is contained in:
Jonathan Johnson 2024-07-26 08:58:59 -07:00
parent ba3a4b9b02
commit ffb1475e30
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
4 changed files with 73 additions and 11 deletions

View file

@ -30,6 +30,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
execute change callbacks for the same dynamic at the same time.
- The initial `inner_size` of a `Window` is now used if it is non-zero and
`WindowAttributes::inner_size` is `None`.
- Container's layout and drawing functions now properly round up/down the
measurements to ensure accurate rendering. Fixes [#158][158].
[158]: https://github.com/khonsulabs/cushy/issues/158
### Added
@ -46,6 +50,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `Fraction` now has `LinearInterpolation` and `PercentBetween` implementations.
- `Window::zoom` allows setting a `Dynamic<Fraction>` that scales all DPI-scaled
operations by an additional scaling factor.
- `Edges` and `ContainerShadow` now implement `figures::Round`.
## v0.3.0 (2024-05-12)

6
Cargo.lock generated
View file

@ -1290,7 +1290,7 @@ checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "kludgine"
version = "0.9.0"
source = "git+https://github.com/khonsulabs/kludgine#eca1ac5d3a9dead20c9c94fb849a4e2bf7719654"
source = "git+https://github.com/khonsulabs/kludgine#3a33c18c2875146371c5f483dcb80e2b4ca5a7da"
dependencies = [
"ahash",
"alot",
@ -3126,9 +3126,9 @@ checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
[[package]]
name = "version_check"
version = "0.9.4"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "walkdir"

View file

@ -12,7 +12,7 @@ use std::sync::Arc;
use ahash::AHashMap;
use figures::units::{Lp, Px, UPx};
use figures::{Fraction, IntoSigned, IntoUnsigned, Rect, ScreenScale, Size, Zero};
use figures::{Fraction, IntoSigned, IntoUnsigned, Rect, Round, ScreenScale, Size, Zero};
use intentional::Cast;
pub use kludgine::cosmic_text::{FamilyOwned, Style, Weight};
pub use kludgine::shapes::CornerRadii;
@ -1245,6 +1245,23 @@ where
}
}
impl<T> Round for Edges<T>
where
T: Round,
{
fn round(self) -> Self {
self.map(Round::round)
}
fn ceil(self) -> Self {
self.map(Round::ceil)
}
fn floor(self) -> Self {
self.map(Round::floor)
}
}
impl<T> Edges<T> {
/// Updates `top` and returns self.
#[must_use]

View file

@ -224,13 +224,17 @@ impl Widget for Container {
let shadow = self
.shadow
.get_tracking_invalidate(context)
.into_px(context.gfx.scale());
.into_px(context.gfx.scale())
.ceil();
let child_shadow_offset = shadow.offset.min(Point::ZERO).abs();
let child_shadow_offset = shadow.offset.min(Point::ZERO).abs().ceil();
let child_size = context.gfx.region().size - shadow.spread * 2 - shadow.offset.abs();
let child_area = Rect::new(child_shadow_offset + shadow.spread, child_size);
let corner_radii = context.get(&CornerRadius).into_px(context.gfx.scale());
let corner_radii = context
.get(&CornerRadius)
.into_px(context.gfx.scale())
.ceil();
// check if the shadow would be obscured before we try to draw it.
if child_area.origin != Point::ZERO || child_size != context.gfx.region().size {
@ -255,15 +259,18 @@ impl Widget for Container {
) -> Size<UPx> {
let child = self.child.mounted(context);
let corner_radii = context.get(&CornerRadius).into_upx(context.gfx.scale());
let corner_radii = context
.get(&CornerRadius)
.into_upx(context.gfx.scale())
.ceil();
let max_space = available_space.map(ConstraintLimit::max);
let min_dimension = max_space.width.min(max_space.height);
let max_corner_radii = min_dimension / 2;
let max_corner_radii = (min_dimension / 2).floor();
let corner_radii = corner_radii.map(|r| r.min(max_corner_radii));
let mut padding = self.padding(context).into_upx(context.gfx.scale());
let mut padding = self.padding(context).into_upx(context.gfx.scale()).ceil();
padding.left = padding
.left
.max(corner_radii.top_left / std::f32::consts::PI)
@ -285,7 +292,8 @@ impl Widget for Container {
let shadow = self
.shadow
.get_tracking_invalidate(context)
.into_px(context.gfx.scale());
.into_px(context.gfx.scale())
.ceil();
let shadow_spread = shadow.spread.into_unsigned();
let child_shadow_offset_amount = shadow.offset.abs().into_unsigned();
@ -736,6 +744,38 @@ impl<Unit> ContainerShadow<Unit> {
}
}
impl<Unit> Round for ContainerShadow<Unit>
where
Unit: Round,
{
fn round(self) -> Self {
Self {
color: self.color,
offset: self.offset.round(),
blur_radius: self.blur_radius.round(),
spread: self.spread.round(),
}
}
fn ceil(self) -> Self {
Self {
color: self.color,
offset: self.offset.ceil(),
blur_radius: self.blur_radius.ceil(),
spread: self.spread.ceil(),
}
}
fn floor(self) -> Self {
Self {
color: self.color,
offset: self.offset.floor(),
blur_radius: self.blur_radius.floor(),
spread: self.spread.floor(),
}
}
}
impl<Unit> ScreenScale for ContainerShadow<Unit>
where
Unit: ScreenScale<Lp = Lp, Px = Px, UPx = UPx>,