Merge pull request #2969 from iced-rs/feature/snapping-reloaded
Add `crisp` feature for default quad snapping
This commit is contained in:
commit
ca6d992d67
14 changed files with 184 additions and 138 deletions
|
|
@ -55,6 +55,8 @@ smol = ["iced_futures/smol"]
|
||||||
system = ["iced_winit/system"]
|
system = ["iced_winit/system"]
|
||||||
# Enables broken "sRGB linear" blending to reproduce color management of the Web
|
# Enables broken "sRGB linear" blending to reproduce color management of the Web
|
||||||
web-colors = ["iced_renderer/web-colors"]
|
web-colors = ["iced_renderer/web-colors"]
|
||||||
|
# Enables pixel snapping for crisp edges by default (can cause jitter!)
|
||||||
|
crisp = ["iced_core/crisp", "iced_widget/crisp"]
|
||||||
# Enables the WebGL backend
|
# Enables the WebGL backend
|
||||||
webgl = ["iced_renderer/webgl"]
|
webgl = ["iced_renderer/webgl"]
|
||||||
# Enables syntax highligthing
|
# Enables syntax highligthing
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ workspace = true
|
||||||
[features]
|
[features]
|
||||||
auto-detect-theme = ["dep:dark-light"]
|
auto-detect-theme = ["dep:dark-light"]
|
||||||
advanced = []
|
advanced = []
|
||||||
|
crisp = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags.workspace = true
|
bitflags.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,9 @@ pub struct Quad {
|
||||||
|
|
||||||
/// The [`Shadow`] of the [`Quad`].
|
/// The [`Shadow`] of the [`Quad`].
|
||||||
pub shadow: Shadow,
|
pub shadow: Shadow,
|
||||||
|
|
||||||
|
/// Whether the [`Quad`] should be snapped to the pixel grid.
|
||||||
|
pub snap: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Quad {
|
impl Default for Quad {
|
||||||
|
|
@ -83,6 +86,7 @@ impl Default for Quad {
|
||||||
bounds: Rectangle::with_size(Size::ZERO),
|
bounds: Rectangle::with_size(Size::ZERO),
|
||||||
border: Border::default(),
|
border: Border::default(),
|
||||||
shadow: Shadow::default(),
|
shadow: Shadow::default(),
|
||||||
|
snap: cfg!(feature = "crisp"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,134 @@
|
||||||
//! This example showcases a drawing a quad.
|
//! This example showcases a drawing a quad.
|
||||||
|
use iced::border;
|
||||||
|
use iced::widget::{center, column, slider, text, toggler};
|
||||||
|
use iced::{Center, Color, Element, Shadow, Vector};
|
||||||
|
|
||||||
|
pub fn main() -> iced::Result {
|
||||||
|
iced::run(Example::update, Example::view)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Example {
|
||||||
|
radius: border::Radius,
|
||||||
|
border_width: f32,
|
||||||
|
shadow: Shadow,
|
||||||
|
snap: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
#[allow(clippy::enum_variant_names)]
|
||||||
|
enum Message {
|
||||||
|
RadiusTopLeftChanged(f32),
|
||||||
|
RadiusTopRightChanged(f32),
|
||||||
|
RadiusBottomRightChanged(f32),
|
||||||
|
RadiusBottomLeftChanged(f32),
|
||||||
|
BorderWidthChanged(f32),
|
||||||
|
ShadowXOffsetChanged(f32),
|
||||||
|
ShadowYOffsetChanged(f32),
|
||||||
|
ShadowBlurRadiusChanged(f32),
|
||||||
|
SnapToggled(bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Example {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
radius: border::radius(50),
|
||||||
|
border_width: 0.0,
|
||||||
|
shadow: Shadow {
|
||||||
|
color: Color::from_rgba(0.0, 0.0, 0.0, 0.8),
|
||||||
|
offset: Vector::new(0.0, 8.0),
|
||||||
|
blur_radius: 16.0,
|
||||||
|
},
|
||||||
|
snap: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, message: Message) {
|
||||||
|
match message {
|
||||||
|
Message::RadiusTopLeftChanged(radius) => {
|
||||||
|
self.radius = self.radius.top_left(radius);
|
||||||
|
}
|
||||||
|
Message::RadiusTopRightChanged(radius) => {
|
||||||
|
self.radius = self.radius.top_right(radius);
|
||||||
|
}
|
||||||
|
Message::RadiusBottomRightChanged(radius) => {
|
||||||
|
self.radius = self.radius.bottom_right(radius);
|
||||||
|
}
|
||||||
|
Message::RadiusBottomLeftChanged(radius) => {
|
||||||
|
self.radius = self.radius.bottom_left(radius);
|
||||||
|
}
|
||||||
|
Message::BorderWidthChanged(width) => {
|
||||||
|
self.border_width = width;
|
||||||
|
}
|
||||||
|
Message::ShadowXOffsetChanged(x) => {
|
||||||
|
self.shadow.offset.x = x;
|
||||||
|
}
|
||||||
|
Message::ShadowYOffsetChanged(y) => {
|
||||||
|
self.shadow.offset.y = y;
|
||||||
|
}
|
||||||
|
Message::ShadowBlurRadiusChanged(s) => {
|
||||||
|
self.shadow.blur_radius = s;
|
||||||
|
}
|
||||||
|
Message::SnapToggled(snap) => {
|
||||||
|
self.snap = snap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self) -> Element<Message> {
|
||||||
|
let border::Radius {
|
||||||
|
top_left,
|
||||||
|
top_right,
|
||||||
|
bottom_right,
|
||||||
|
bottom_left,
|
||||||
|
} = self.radius;
|
||||||
|
|
||||||
|
let Shadow {
|
||||||
|
offset: Vector { x: sx, y: sy },
|
||||||
|
blur_radius: sr,
|
||||||
|
..
|
||||||
|
} = self.shadow;
|
||||||
|
|
||||||
|
let content = column![
|
||||||
|
quad::CustomQuad::new(
|
||||||
|
200.0,
|
||||||
|
self.radius,
|
||||||
|
self.border_width,
|
||||||
|
self.shadow,
|
||||||
|
self.snap,
|
||||||
|
),
|
||||||
|
text!("Radius: {top_left:.2}/{top_right:.2}/{bottom_right:.2}/{bottom_left:.2}"),
|
||||||
|
slider(1.0..=100.0, top_left, Message::RadiusTopLeftChanged).step(0.01),
|
||||||
|
slider(1.0..=100.0, top_right, Message::RadiusTopRightChanged).step(0.01),
|
||||||
|
slider(1.0..=100.0, bottom_right, Message::RadiusBottomRightChanged)
|
||||||
|
.step(0.01),
|
||||||
|
slider(1.0..=100.0, bottom_left, Message::RadiusBottomLeftChanged)
|
||||||
|
.step(0.01),
|
||||||
|
slider(1.0..=10.0, self.border_width, Message::BorderWidthChanged)
|
||||||
|
.step(0.01),
|
||||||
|
text!("Shadow: {sx:.2}x{sy:.2}, {sr:.2}"),
|
||||||
|
slider(-100.0..=100.0, sx, Message::ShadowXOffsetChanged)
|
||||||
|
.step(0.01),
|
||||||
|
slider(-100.0..=100.0, sy, Message::ShadowYOffsetChanged)
|
||||||
|
.step(0.01),
|
||||||
|
slider(0.0..=100.0, sr, Message::ShadowBlurRadiusChanged)
|
||||||
|
.step(0.01),
|
||||||
|
toggler(self.snap).label("Snap to pixel grid").on_toggle(Message::SnapToggled),
|
||||||
|
]
|
||||||
|
.padding(20)
|
||||||
|
.spacing(20)
|
||||||
|
.max_width(500)
|
||||||
|
.align_x(Center);
|
||||||
|
|
||||||
|
center(content).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Example {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod quad {
|
mod quad {
|
||||||
use iced::advanced::layout::{self, Layout};
|
use iced::advanced::layout::{self, Layout};
|
||||||
use iced::advanced::renderer;
|
use iced::advanced::renderer;
|
||||||
|
|
@ -12,6 +142,7 @@ mod quad {
|
||||||
radius: border::Radius,
|
radius: border::Radius,
|
||||||
border_width: f32,
|
border_width: f32,
|
||||||
shadow: Shadow,
|
shadow: Shadow,
|
||||||
|
snap: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomQuad {
|
impl CustomQuad {
|
||||||
|
|
@ -20,12 +151,14 @@ mod quad {
|
||||||
radius: border::Radius,
|
radius: border::Radius,
|
||||||
border_width: f32,
|
border_width: f32,
|
||||||
shadow: Shadow,
|
shadow: Shadow,
|
||||||
|
snap: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
size,
|
size,
|
||||||
radius,
|
radius,
|
||||||
border_width,
|
border_width,
|
||||||
shadow,
|
shadow,
|
||||||
|
snap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -69,6 +202,7 @@ mod quad {
|
||||||
color: Color::from_rgb(1.0, 0.0, 0.0),
|
color: Color::from_rgb(1.0, 0.0, 0.0),
|
||||||
},
|
},
|
||||||
shadow: self.shadow,
|
shadow: self.shadow,
|
||||||
|
snap: self.snap,
|
||||||
},
|
},
|
||||||
Color::BLACK,
|
Color::BLACK,
|
||||||
);
|
);
|
||||||
|
|
@ -81,125 +215,3 @@ mod quad {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use iced::border;
|
|
||||||
use iced::widget::{center, column, slider, text};
|
|
||||||
use iced::{Center, Color, Element, Shadow, Vector};
|
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
|
||||||
iced::run(Example::update, Example::view)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Example {
|
|
||||||
radius: border::Radius,
|
|
||||||
border_width: f32,
|
|
||||||
shadow: Shadow,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
#[allow(clippy::enum_variant_names)]
|
|
||||||
enum Message {
|
|
||||||
RadiusTopLeftChanged(f32),
|
|
||||||
RadiusTopRightChanged(f32),
|
|
||||||
RadiusBottomRightChanged(f32),
|
|
||||||
RadiusBottomLeftChanged(f32),
|
|
||||||
BorderWidthChanged(f32),
|
|
||||||
ShadowXOffsetChanged(f32),
|
|
||||||
ShadowYOffsetChanged(f32),
|
|
||||||
ShadowBlurRadiusChanged(f32),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Example {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
radius: border::radius(50),
|
|
||||||
border_width: 0.0,
|
|
||||||
shadow: Shadow {
|
|
||||||
color: Color::from_rgba(0.0, 0.0, 0.0, 0.8),
|
|
||||||
offset: Vector::new(0.0, 8.0),
|
|
||||||
blur_radius: 16.0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, message: Message) {
|
|
||||||
match message {
|
|
||||||
Message::RadiusTopLeftChanged(radius) => {
|
|
||||||
self.radius = self.radius.top_left(radius);
|
|
||||||
}
|
|
||||||
Message::RadiusTopRightChanged(radius) => {
|
|
||||||
self.radius = self.radius.top_right(radius);
|
|
||||||
}
|
|
||||||
Message::RadiusBottomRightChanged(radius) => {
|
|
||||||
self.radius = self.radius.bottom_right(radius);
|
|
||||||
}
|
|
||||||
Message::RadiusBottomLeftChanged(radius) => {
|
|
||||||
self.radius = self.radius.bottom_left(radius);
|
|
||||||
}
|
|
||||||
Message::BorderWidthChanged(width) => {
|
|
||||||
self.border_width = width;
|
|
||||||
}
|
|
||||||
Message::ShadowXOffsetChanged(x) => {
|
|
||||||
self.shadow.offset.x = x;
|
|
||||||
}
|
|
||||||
Message::ShadowYOffsetChanged(y) => {
|
|
||||||
self.shadow.offset.y = y;
|
|
||||||
}
|
|
||||||
Message::ShadowBlurRadiusChanged(s) => {
|
|
||||||
self.shadow.blur_radius = s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn view(&self) -> Element<Message> {
|
|
||||||
let border::Radius {
|
|
||||||
top_left,
|
|
||||||
top_right,
|
|
||||||
bottom_right,
|
|
||||||
bottom_left,
|
|
||||||
} = self.radius;
|
|
||||||
|
|
||||||
let Shadow {
|
|
||||||
offset: Vector { x: sx, y: sy },
|
|
||||||
blur_radius: sr,
|
|
||||||
..
|
|
||||||
} = self.shadow;
|
|
||||||
|
|
||||||
let content = column![
|
|
||||||
quad::CustomQuad::new(
|
|
||||||
200.0,
|
|
||||||
self.radius,
|
|
||||||
self.border_width,
|
|
||||||
self.shadow
|
|
||||||
),
|
|
||||||
text!("Radius: {top_left:.2}/{top_right:.2}/{bottom_right:.2}/{bottom_left:.2}"),
|
|
||||||
slider(1.0..=100.0, top_left, Message::RadiusTopLeftChanged).step(0.01),
|
|
||||||
slider(1.0..=100.0, top_right, Message::RadiusTopRightChanged).step(0.01),
|
|
||||||
slider(1.0..=100.0, bottom_right, Message::RadiusBottomRightChanged)
|
|
||||||
.step(0.01),
|
|
||||||
slider(1.0..=100.0, bottom_left, Message::RadiusBottomLeftChanged)
|
|
||||||
.step(0.01),
|
|
||||||
slider(1.0..=10.0, self.border_width, Message::BorderWidthChanged)
|
|
||||||
.step(0.01),
|
|
||||||
text!("Shadow: {sx:.2}x{sy:.2}, {sr:.2}"),
|
|
||||||
slider(-100.0..=100.0, sx, Message::ShadowXOffsetChanged)
|
|
||||||
.step(0.01),
|
|
||||||
slider(-100.0..=100.0, sy, Message::ShadowYOffsetChanged)
|
|
||||||
.step(0.01),
|
|
||||||
slider(0.0..=100.0, sr, Message::ShadowBlurRadiusChanged)
|
|
||||||
.step(0.01),
|
|
||||||
]
|
|
||||||
.padding(20)
|
|
||||||
.spacing(20)
|
|
||||||
.max_width(500)
|
|
||||||
.align_x(Center);
|
|
||||||
|
|
||||||
center(content).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Example {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ impl Layer {
|
||||||
shadow_color: color::pack(quad.shadow.color),
|
shadow_color: color::pack(quad.shadow.color),
|
||||||
shadow_offset: quad.shadow.offset.into(),
|
shadow_offset: quad.shadow.offset.into(),
|
||||||
shadow_blur_radius: quad.shadow.blur_radius,
|
shadow_blur_radius: quad.shadow.blur_radius,
|
||||||
|
snap: quad.snap as u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.quads.add(quad, &background);
|
self.quads.add(quad, &background);
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@ pub struct Quad {
|
||||||
|
|
||||||
/// The shadow blur radius of the [`Quad`].
|
/// The shadow blur radius of the [`Quad`].
|
||||||
pub shadow_blur_radius: f32,
|
pub shadow_blur_radius: f32,
|
||||||
|
|
||||||
|
/// Whether the [`Quad`] should be snapped to the pixel grid.
|
||||||
|
pub snap: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,9 @@ impl Pipeline {
|
||||||
// Border radius
|
// Border radius
|
||||||
8 => Float32x4,
|
8 => Float32x4,
|
||||||
// Border width
|
// Border width
|
||||||
9 => Float32
|
9 => Float32,
|
||||||
|
// Snap
|
||||||
|
10 => Uint32,
|
||||||
),
|
),
|
||||||
}],
|
}],
|
||||||
compilation_options:
|
compilation_options:
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,8 @@ impl Pipeline {
|
||||||
7 => Float32x2,
|
7 => Float32x2,
|
||||||
// Shadow blur radius
|
// Shadow blur radius
|
||||||
8 => Float32,
|
8 => Float32,
|
||||||
|
// Snap
|
||||||
|
9 => Uint32,
|
||||||
),
|
),
|
||||||
}],
|
}],
|
||||||
compilation_options:
|
compilation_options:
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ struct GradientVertexInput {
|
||||||
@location(7) border_color: vec4<f32>,
|
@location(7) border_color: vec4<f32>,
|
||||||
@location(8) border_radius: vec4<f32>,
|
@location(8) border_radius: vec4<f32>,
|
||||||
@location(9) border_width: f32,
|
@location(9) border_width: f32,
|
||||||
|
@location(10) snap: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GradientVertexOutput {
|
struct GradientVertexOutput {
|
||||||
|
|
@ -33,6 +34,14 @@ fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput {
|
||||||
var pos: vec2<f32> = input.position_and_scale.xy * globals.scale;
|
var pos: vec2<f32> = input.position_and_scale.xy * globals.scale;
|
||||||
var scale: vec2<f32> = input.position_and_scale.zw * globals.scale;
|
var scale: vec2<f32> = input.position_and_scale.zw * globals.scale;
|
||||||
|
|
||||||
|
var pos_snap = vec2<f32>(0.0, 0.0);
|
||||||
|
var scale_snap = vec2<f32>(0.0, 0.0);
|
||||||
|
|
||||||
|
if bool(input.snap) {
|
||||||
|
pos_snap = round(pos + vec2(0.001, 0.001)) - pos;
|
||||||
|
scale_snap = round(pos + scale + vec2(0.001, 0.001)) - pos - pos_snap - scale;
|
||||||
|
}
|
||||||
|
|
||||||
var min_border_radius = min(input.position_and_scale.z, input.position_and_scale.w) * 0.5;
|
var min_border_radius = min(input.position_and_scale.z, input.position_and_scale.w) * 0.5;
|
||||||
var border_radius: vec4<f32> = vec4<f32>(
|
var border_radius: vec4<f32> = vec4<f32>(
|
||||||
min(input.border_radius.x, min_border_radius),
|
min(input.border_radius.x, min_border_radius),
|
||||||
|
|
@ -42,10 +51,10 @@ fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput {
|
||||||
);
|
);
|
||||||
|
|
||||||
var transform: mat4x4<f32> = mat4x4<f32>(
|
var transform: mat4x4<f32> = mat4x4<f32>(
|
||||||
vec4<f32>(scale.x + 1.0, 0.0, 0.0, 0.0),
|
vec4<f32>(scale.x + scale_snap.x + 1.0, 0.0, 0.0, 0.0),
|
||||||
vec4<f32>(0.0, scale.y + 1.0, 0.0, 0.0),
|
vec4<f32>(0.0, scale.y + scale_snap.y + 1.0, 0.0, 0.0),
|
||||||
vec4<f32>(0.0, 0.0, 1.0, 0.0),
|
vec4<f32>(0.0, 0.0, 1.0, 0.0),
|
||||||
vec4<f32>(pos - vec2<f32>(0.5, 0.5), 0.0, 1.0)
|
vec4<f32>(pos + pos_snap - vec2<f32>(0.5, 0.5), 0.0, 1.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
out.position = globals.transform * transform * vec4<f32>(vertex_position(input.vertex_index), 0.0, 1.0);
|
out.position = globals.transform * transform * vec4<f32>(vertex_position(input.vertex_index), 0.0, 1.0);
|
||||||
|
|
@ -55,7 +64,7 @@ fn gradient_vs_main(input: GradientVertexInput) -> GradientVertexOutput {
|
||||||
out.colors_4 = input.colors_4;
|
out.colors_4 = input.colors_4;
|
||||||
out.offsets = input.offsets;
|
out.offsets = input.offsets;
|
||||||
out.direction = input.direction * globals.scale;
|
out.direction = input.direction * globals.scale;
|
||||||
out.position_and_scale = vec4<f32>(pos, scale);
|
out.position_and_scale = vec4<f32>(pos + pos_snap, scale + scale_snap);
|
||||||
out.border_color = premultiply(input.border_color);
|
out.border_color = premultiply(input.border_color);
|
||||||
out.border_radius = border_radius * globals.scale;
|
out.border_radius = border_radius * globals.scale;
|
||||||
out.border_width = input.border_width * globals.scale;
|
out.border_width = input.border_width * globals.scale;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ struct SolidVertexInput {
|
||||||
@location(6) shadow_color: vec4<f32>,
|
@location(6) shadow_color: vec4<f32>,
|
||||||
@location(7) shadow_offset: vec2<f32>,
|
@location(7) shadow_offset: vec2<f32>,
|
||||||
@location(8) shadow_blur_radius: f32,
|
@location(8) shadow_blur_radius: f32,
|
||||||
|
@location(9) snap: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SolidVertexOutput {
|
struct SolidVertexOutput {
|
||||||
|
|
@ -30,14 +31,13 @@ fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput {
|
||||||
|
|
||||||
var pos: vec2<f32> = (input.pos + min(input.shadow_offset, vec2<f32>(0.0, 0.0)) - input.shadow_blur_radius) * globals.scale;
|
var pos: vec2<f32> = (input.pos + min(input.shadow_offset, vec2<f32>(0.0, 0.0)) - input.shadow_blur_radius) * globals.scale;
|
||||||
var scale: vec2<f32> = (input.scale + vec2<f32>(abs(input.shadow_offset.x), abs(input.shadow_offset.y)) + input.shadow_blur_radius * 2.0) * globals.scale;
|
var scale: vec2<f32> = (input.scale + vec2<f32>(abs(input.shadow_offset.x), abs(input.shadow_offset.y)) + input.shadow_blur_radius * 2.0) * globals.scale;
|
||||||
var snap: vec2<f32> = vec2<f32>(0.0, 0.0);
|
|
||||||
|
|
||||||
if input.scale.x == 1.0 {
|
var pos_snap = vec2<f32>(0.0, 0.0);
|
||||||
snap.x = round(pos.x) - pos.x;
|
var scale_snap = vec2<f32>(0.0, 0.0);
|
||||||
}
|
|
||||||
|
|
||||||
if input.scale.y == 1.0 {
|
if bool(input.snap) {
|
||||||
snap.y = round(pos.y) - pos.y;
|
pos_snap = round(pos + vec2(0.001, 0.001)) - pos;
|
||||||
|
scale_snap = round(pos + scale + vec2(0.001, 0.001)) - pos - pos_snap - scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
var min_border_radius = min(input.scale.x, input.scale.y) * 0.5;
|
var min_border_radius = min(input.scale.x, input.scale.y) * 0.5;
|
||||||
|
|
@ -49,17 +49,17 @@ fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput {
|
||||||
);
|
);
|
||||||
|
|
||||||
var transform: mat4x4<f32> = mat4x4<f32>(
|
var transform: mat4x4<f32> = mat4x4<f32>(
|
||||||
vec4<f32>(scale.x + 1.0, 0.0, 0.0, 0.0),
|
vec4<f32>(scale.x + scale_snap.x + 1.0, 0.0, 0.0, 0.0),
|
||||||
vec4<f32>(0.0, scale.y + 1.0, 0.0, 0.0),
|
vec4<f32>(0.0, scale.y + scale_snap.y + 1.0, 0.0, 0.0),
|
||||||
vec4<f32>(0.0, 0.0, 1.0, 0.0),
|
vec4<f32>(0.0, 0.0, 1.0, 0.0),
|
||||||
vec4<f32>(pos - vec2<f32>(0.5, 0.5) + snap, 0.0, 1.0)
|
vec4<f32>(pos + pos_snap - vec2<f32>(0.5, 0.5), 0.0, 1.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
out.position = globals.transform * transform * vec4<f32>(vertex_position(input.vertex_index), 0.0, 1.0);
|
out.position = globals.transform * transform * vec4<f32>(vertex_position(input.vertex_index), 0.0, 1.0);
|
||||||
out.color = premultiply(input.color);
|
out.color = premultiply(input.color);
|
||||||
out.border_color = premultiply(input.border_color);
|
out.border_color = premultiply(input.border_color);
|
||||||
out.pos = input.pos * globals.scale + snap;
|
out.pos = input.pos * globals.scale + pos_snap;
|
||||||
out.scale = input.scale * globals.scale;
|
out.scale = input.scale * globals.scale + scale_snap;
|
||||||
out.border_radius = border_radius * globals.scale;
|
out.border_radius = border_radius * globals.scale;
|
||||||
out.border_width = input.border_width * globals.scale;
|
out.border_width = input.border_width * globals.scale;
|
||||||
out.shadow_color = premultiply(input.shadow_color);
|
out.shadow_color = premultiply(input.shadow_color);
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ wgpu = ["iced_renderer/wgpu"]
|
||||||
markdown = ["dep:pulldown-cmark", "dep:url"]
|
markdown = ["dep:pulldown-cmark", "dep:url"]
|
||||||
highlighter = ["dep:iced_highlighter"]
|
highlighter = ["dep:iced_highlighter"]
|
||||||
advanced = []
|
advanced = []
|
||||||
|
crisp = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iced_renderer.workspace = true
|
iced_renderer.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -384,6 +384,7 @@ where
|
||||||
bounds,
|
bounds,
|
||||||
border: style.border,
|
border: style.border,
|
||||||
shadow: style.shadow,
|
shadow: style.shadow,
|
||||||
|
snap: style.snap,
|
||||||
},
|
},
|
||||||
style
|
style
|
||||||
.background
|
.background
|
||||||
|
|
@ -492,6 +493,8 @@ pub struct Style {
|
||||||
pub border: Border,
|
pub border: Border,
|
||||||
/// The [`Shadow`] of the button.
|
/// The [`Shadow`] of the button.
|
||||||
pub shadow: Shadow,
|
pub shadow: Shadow,
|
||||||
|
/// Whether the button should be snapped to the pixel grid.
|
||||||
|
pub snap: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Style {
|
impl Style {
|
||||||
|
|
@ -511,6 +514,7 @@ impl Default for Style {
|
||||||
text_color: Color::BLACK,
|
text_color: Color::BLACK,
|
||||||
border: Border::default(),
|
border: Border::default(),
|
||||||
shadow: Shadow::default(),
|
shadow: Shadow::default(),
|
||||||
|
snap: cfg!(feature = "crisp"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -451,6 +451,7 @@ pub fn draw_background<Renderer>(
|
||||||
bounds,
|
bounds,
|
||||||
border: style.border,
|
border: style.border,
|
||||||
shadow: style.shadow,
|
shadow: style.shadow,
|
||||||
|
snap: style.snap,
|
||||||
},
|
},
|
||||||
style
|
style
|
||||||
.background
|
.background
|
||||||
|
|
@ -592,6 +593,8 @@ pub struct Style {
|
||||||
pub border: Border,
|
pub border: Border,
|
||||||
/// The [`Shadow`] of the container.
|
/// The [`Shadow`] of the container.
|
||||||
pub shadow: Shadow,
|
pub shadow: Shadow,
|
||||||
|
/// Whether the container should be snapped to the pixel grid.
|
||||||
|
pub snap: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Style {
|
impl Style {
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,7 @@ where
|
||||||
bounds: layout.bounds().shrink(1.0),
|
bounds: layout.bounds().shrink(1.0),
|
||||||
shadow: style.shadow,
|
shadow: style.shadow,
|
||||||
border: border::rounded(style.shadow_border_radius),
|
border: border::rounded(style.shadow_border_radius),
|
||||||
|
snap: false,
|
||||||
},
|
},
|
||||||
style.shadow.color,
|
style.shadow.color,
|
||||||
);
|
);
|
||||||
|
|
@ -332,6 +333,7 @@ where
|
||||||
border: border::rounded(
|
border: border::rounded(
|
||||||
style.shadow_border_radius,
|
style.shadow_border_radius,
|
||||||
),
|
),
|
||||||
|
snap: false,
|
||||||
},
|
},
|
||||||
style.shadow.color,
|
style.shadow.color,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue