Checkpoint

This commit is contained in:
Antonio Scandurra 2023-10-04 18:38:08 +02:00
parent 133c3a330c
commit 5aa45607eb
5 changed files with 25 additions and 57 deletions

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
BorrowWindow, ContentMask, Element, IsZero, Layout, LayoutId, Result, SharedString, Style, BorrowWindow, Element, Layout, LayoutId, Result, SharedString, Style, StyleHelpers, Styled,
StyleHelpers, Styled, ViewContext, ViewContext,
}; };
use futures::FutureExt; use futures::FutureExt;
use refineable::RefinementCascade; use refineable::RefinementCascade;
@ -73,17 +73,7 @@ impl<S: 'static> Element for Img<S> {
.and_then(ResultExt::log_err) .and_then(ResultExt::log_err)
{ {
let corner_radii = style.corner_radii.to_pixels(bounds, cx.rem_size()); let corner_radii = style.corner_radii.to_pixels(bounds, cx.rem_size());
if corner_radii.is_zero() { cx.paint_image(bounds, corner_radii, order, data, self.grayscale)?;
cx.paint_image(bounds, order, data, self.grayscale)?;
} else {
cx.with_content_mask(
ContentMask {
bounds,
corner_radii,
},
|cx| cx.paint_image(bounds, order, data, self.grayscale),
)?;
}
} else { } else {
log::warn!("image not loaded yet"); log::warn!("image not loaded yet");
// cx.spawn(|this, mut cx| async move { // cx.spawn(|this, mut cx| async move {

View file

@ -106,11 +106,7 @@ fragment float4 quad_fragment(QuadVertexOutput input [[stage_in]],
color = float4(premultiplied_output_rgb, output_alpha); color = float4(premultiplied_output_rgb, output_alpha);
} }
float clip_distance = return color * float4(1., 1., 1., saturate(0.5 - distance));
quad_sdf(input.position.xy, quad.clip_bounds, quad.clip_corner_radii);
return color *
float4(1., 1., 1.,
saturate(0.5 - distance) * saturate(0.5 - clip_distance));
} }
struct MonochromeSpriteVertexOutput { struct MonochromeSpriteVertexOutput {
@ -131,8 +127,9 @@ vertex MonochromeSpriteVertexOutput monochrome_sprite_vertex(
float2 unit_vertex = unit_vertices[unit_vertex_id]; float2 unit_vertex = unit_vertices[unit_vertex_id];
MonochromeSprite sprite = sprites[sprite_id]; MonochromeSprite sprite = sprites[sprite_id];
// Don't apply content mask at the vertex level because we don't have time to make sampling from the texture match the mask.
float4 device_position = to_device_position( float4 device_position = to_device_position(
unit_vertex, sprite.bounds, sprite.content_mask.bounds, viewport_size); unit_vertex, sprite.bounds, sprite.bounds, viewport_size);
float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size); float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);
float4 color = hsla_to_rgba(sprite.color); float4 color = hsla_to_rgba(sprite.color);
return MonochromeSpriteVertexOutput{device_position, tile_position, color, return MonochromeSpriteVertexOutput{device_position, tile_position, color,
@ -148,8 +145,11 @@ fragment float4 monochrome_sprite_fragment(
min_filter::linear); min_filter::linear);
float4 sample = float4 sample =
atlas_texture.sample(atlas_texture_sampler, input.tile_position); atlas_texture.sample(atlas_texture_sampler, input.tile_position);
float clip_distance = quad_sdf(input.position.xy, sprite.content_mask.bounds, float clip_distance = quad_sdf(
sprite.content_mask.corner_radii); input.position.xy,
sprite.content_mask.bounds,
Corners_ScaledPixels { 0., 0., 0., 0. }
);
float4 color = input.color; float4 color = input.color;
color.a *= sample.a * saturate(0.5 - clip_distance); color.a *= sample.a * saturate(0.5 - clip_distance);
return color; return color;
@ -172,8 +172,9 @@ vertex PolychromeSpriteVertexOutput polychrome_sprite_vertex(
float2 unit_vertex = unit_vertices[unit_vertex_id]; float2 unit_vertex = unit_vertices[unit_vertex_id];
PolychromeSprite sprite = sprites[sprite_id]; PolychromeSprite sprite = sprites[sprite_id];
// Don't apply content mask at the vertex level because we don't have time to make sampling from the texture match the mask.
float4 device_position = to_device_position( float4 device_position = to_device_position(
unit_vertex, sprite.bounds, sprite.content_mask.bounds, viewport_size); unit_vertex, sprite.bounds, sprite.bounds, viewport_size);
float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size); float2 tile_position = to_tile_position(unit_vertex, sprite.tile, atlas_size);
return PolychromeSpriteVertexOutput{device_position, tile_position, return PolychromeSpriteVertexOutput{device_position, tile_position,
sprite_id}; sprite_id};
@ -188,8 +189,10 @@ fragment float4 polychrome_sprite_fragment(
min_filter::linear); min_filter::linear);
float4 sample = float4 sample =
atlas_texture.sample(atlas_texture_sampler, input.tile_position); atlas_texture.sample(atlas_texture_sampler, input.tile_position);
float clip_distance = quad_sdf(input.position.xy, sprite.content_mask.bounds, float quad_distance = quad_sdf(input.position.xy, sprite.bounds, sprite.corner_radii);
sprite.content_mask.corner_radii); float clip_distance = quad_sdf(input.position.xy, sprite.content_mask.bounds, Corners_ScaledPixels { 0., 0., 0., 0. });
float distance = max(quad_distance, clip_distance);
float4 color = sample; float4 color = sample;
if (sprite.grayscale) { if (sprite.grayscale) {
float grayscale = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b; float grayscale = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
@ -197,7 +200,7 @@ fragment float4 polychrome_sprite_fragment(
color.g = grayscale; color.g = grayscale;
color.b = grayscale; color.b = grayscale;
} }
color.a *= saturate(0.5 - clip_distance); color.a *= saturate(0.5 - distance);
return color; return color;
} }

View file

@ -275,6 +275,7 @@ pub struct PolychromeSprite {
pub order: u32, pub order: u32,
pub bounds: Bounds<ScaledPixels>, pub bounds: Bounds<ScaledPixels>,
pub content_mask: ScaledContentMask, pub content_mask: ScaledContentMask,
pub corner_radii: Corners<ScaledPixels>,
pub tile: AtlasTile, pub tile: AtlasTile,
pub grayscale: bool, pub grayscale: bool,
} }

View file

@ -202,7 +202,6 @@ impl Style {
let min = current_mask.bounds.origin; let min = current_mask.bounds.origin;
let max = current_mask.bounds.lower_right(); let max = current_mask.bounds.lower_right();
let mut mask_corner_radii = Corners::default();
let mask_bounds = match ( let mask_bounds = match (
self.overflow.x == Overflow::Visible, self.overflow.x == Overflow::Visible,
self.overflow.y == Overflow::Visible, self.overflow.y == Overflow::Visible,
@ -220,14 +219,10 @@ impl Style {
point(bounds.lower_right().x, max.y), point(bounds.lower_right().x, max.y),
), ),
// both hidden // both hidden
(false, false) => { (false, false) => bounds,
mask_corner_radii = self.corner_radii.to_pixels(bounds, cx.rem_size());
bounds
}
}; };
let mask = ContentMask { let mask = ContentMask {
bounds: mask_bounds, bounds: mask_bounds,
corner_radii: mask_corner_radii,
}; };
cx.with_content_mask(mask, f) cx.with_content_mask(mask, f)

View file

@ -76,24 +76,18 @@ impl Window {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ContentMask { pub struct ContentMask {
pub bounds: Bounds<Pixels>, pub bounds: Bounds<Pixels>,
pub corner_radii: Corners<Pixels>,
} }
impl ContentMask { impl ContentMask {
pub fn scale(&self, factor: f32) -> ScaledContentMask { pub fn scale(&self, factor: f32) -> ScaledContentMask {
ScaledContentMask { ScaledContentMask {
bounds: self.bounds.scale(factor), bounds: self.bounds.scale(factor),
corner_radii: self.corner_radii.scale(factor),
} }
} }
pub fn intersect(&self, other: &Self) -> Self { pub fn intersect(&self, other: &Self) -> Self {
let bounds = self.bounds.intersect(&other.bounds); let bounds = self.bounds.intersect(&other.bounds);
// todo!("intersect corner radii") ContentMask { bounds }
ContentMask {
bounds,
corner_radii: self.corner_radii,
}
} }
} }
@ -101,7 +95,6 @@ impl ContentMask {
#[repr(C)] #[repr(C)]
pub struct ScaledContentMask { pub struct ScaledContentMask {
bounds: Bounds<ScaledPixels>, bounds: Bounds<ScaledPixels>,
corner_radii: Corners<ScaledPixels>,
} }
pub struct WindowContext<'a, 'w> { pub struct WindowContext<'a, 'w> {
@ -202,23 +195,6 @@ impl<'a, 'w> WindowContext<'a, 'w> {
result result
} }
pub fn clip<F, R>(
&mut self,
bounds: Bounds<Pixels>,
corner_radii: Corners<Pixels>,
f: impl FnOnce(&mut Self) -> R,
) -> R {
let clip_mask = ContentMask {
bounds,
corner_radii,
};
self.window.content_mask_stack.push(clip_mask);
let result = f(self);
self.window.content_mask_stack.pop();
result
}
pub fn current_layer_id(&self) -> LayerId { pub fn current_layer_id(&self) -> LayerId {
self.window.current_layer_id.clone() self.window.current_layer_id.clone()
} }
@ -318,6 +294,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
PolychromeSprite { PolychromeSprite {
order, order,
bounds, bounds,
corner_radii: Default::default(),
content_mask, content_mask,
tile, tile,
grayscale: false, grayscale: false,
@ -371,6 +348,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
pub fn paint_image( pub fn paint_image(
&mut self, &mut self,
bounds: Bounds<Pixels>, bounds: Bounds<Pixels>,
corner_radii: Corners<Pixels>,
order: u32, order: u32,
data: Arc<ImageData>, data: Arc<ImageData>,
grayscale: bool, grayscale: bool,
@ -387,6 +365,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
Ok((data.size(), Cow::Borrowed(data.as_bytes()))) Ok((data.size(), Cow::Borrowed(data.as_bytes())))
})?; })?;
let content_mask = self.content_mask().scale(scale_factor); let content_mask = self.content_mask().scale(scale_factor);
let corner_radii = corner_radii.scale(scale_factor);
self.window.scene.insert( self.window.scene.insert(
layer_id, layer_id,
@ -394,6 +373,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
order, order,
bounds, bounds,
content_mask, content_mask,
corner_radii,
tile, tile,
grayscale, grayscale,
}, },
@ -505,7 +485,6 @@ pub trait BorrowWindow: BorrowAppContext {
origin: Point::default(), origin: Point::default(),
size: self.window().content_size, size: self.window().content_size,
}, },
corner_radii: Default::default(),
}) })
} }