mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-09 12:01:58 +00:00
Allow passing a corner radius and borders to rendered images
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
96ade8668f
commit
95da665095
6 changed files with 101 additions and 50 deletions
|
@ -29,6 +29,10 @@ impl Color {
|
|||
Self(ColorU::white())
|
||||
}
|
||||
|
||||
pub fn red() -> Self {
|
||||
Self(ColorU::from_u32(0xff0000ff))
|
||||
}
|
||||
|
||||
pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
Self(ColorU::new(r, g, b, a))
|
||||
}
|
||||
|
|
|
@ -1,16 +1,34 @@
|
|||
use crate::{
|
||||
geometry::{rect::RectF, vector::Vector2F},
|
||||
json::{json, ToJson},
|
||||
scene, DebugContext, Element, Event, EventContext, ImageData, LayoutContext, PaintContext,
|
||||
SizeConstraint,
|
||||
scene, Border, DebugContext, Element, Event, EventContext, ImageData, LayoutContext,
|
||||
PaintContext, SizeConstraint,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Image(Arc<ImageData>);
|
||||
pub struct Image {
|
||||
data: Arc<ImageData>,
|
||||
border: Border,
|
||||
corner_radius: f32,
|
||||
}
|
||||
|
||||
impl Image {
|
||||
pub fn new(data: Arc<ImageData>) -> Self {
|
||||
Self(data)
|
||||
Self {
|
||||
data,
|
||||
border: Default::default(),
|
||||
corner_radius: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_corner_radius(mut self, corner_radius: f32) -> Self {
|
||||
self.corner_radius = corner_radius;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_border(mut self, border: Border) -> Self {
|
||||
self.border = border;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +53,9 @@ impl Element for Image {
|
|||
) -> Self::PaintState {
|
||||
cx.scene.push_image(scene::Image {
|
||||
bounds,
|
||||
data: self.0.clone(),
|
||||
border: self.border,
|
||||
corner_radius: self.corner_radius,
|
||||
data: self.data.clone(),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -657,6 +657,8 @@ impl Renderer {
|
|||
for image in images {
|
||||
let origin = image.bounds.origin() * scale_factor;
|
||||
let target_size = image.bounds.size() * scale_factor;
|
||||
let corner_radius = image.corner_radius * scale_factor;
|
||||
let border_width = image.border.width * scale_factor;
|
||||
let (alloc_id, atlas_bounds) = self
|
||||
.prev_rendered_images
|
||||
.remove(&image.data.id)
|
||||
|
@ -675,6 +677,12 @@ impl Renderer {
|
|||
target_size: target_size.to_float2(),
|
||||
source_size: atlas_bounds.size().to_float2(),
|
||||
atlas_origin: atlas_bounds.origin().to_float2(),
|
||||
border_top: border_width * (image.border.top as usize as f32),
|
||||
border_right: border_width * (image.border.right as usize as f32),
|
||||
border_bottom: border_width * (image.border.bottom as usize as f32),
|
||||
border_left: border_width * (image.border.left as usize as f32),
|
||||
border_color: image.border.color.to_uchar4(),
|
||||
corner_radius,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -97,4 +97,10 @@ typedef struct
|
|||
vector_float2 target_size;
|
||||
vector_float2 source_size;
|
||||
vector_float2 atlas_origin;
|
||||
float border_top;
|
||||
float border_right;
|
||||
float border_bottom;
|
||||
float border_left;
|
||||
vector_uchar4 border_color;
|
||||
float corner_radius;
|
||||
} GPUIImage;
|
||||
|
|
|
@ -34,46 +34,19 @@ float blur_along_x(float x, float y, float sigma, float corner, float2 halfSize)
|
|||
|
||||
struct QuadFragmentInput {
|
||||
float4 position [[position]];
|
||||
vector_float2 origin;
|
||||
vector_float2 size;
|
||||
vector_uchar4 background_color;
|
||||
float2 atlas_position; // only used in the image shader
|
||||
float2 origin;
|
||||
float2 size;
|
||||
float4 background_color;
|
||||
float border_top;
|
||||
float border_right;
|
||||
float border_bottom;
|
||||
float border_left;
|
||||
vector_uchar4 border_color;
|
||||
float4 border_color;
|
||||
float corner_radius;
|
||||
};
|
||||
|
||||
vertex QuadFragmentInput quad_vertex(
|
||||
uint unit_vertex_id [[vertex_id]],
|
||||
uint quad_id [[instance_id]],
|
||||
constant float2 *unit_vertices [[buffer(GPUIQuadInputIndexVertices)]],
|
||||
constant GPUIQuad *quads [[buffer(GPUIQuadInputIndexQuads)]],
|
||||
constant GPUIUniforms *uniforms [[buffer(GPUIQuadInputIndexUniforms)]]
|
||||
) {
|
||||
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||
GPUIQuad quad = quads[quad_id];
|
||||
float2 position = unit_vertex * quad.size + quad.origin;
|
||||
float4 device_position = to_device_position(position, uniforms->viewport_size);
|
||||
|
||||
return QuadFragmentInput {
|
||||
device_position,
|
||||
quad.origin,
|
||||
quad.size,
|
||||
quad.background_color,
|
||||
quad.border_top,
|
||||
quad.border_right,
|
||||
quad.border_bottom,
|
||||
quad.border_left,
|
||||
quad.border_color,
|
||||
quad.corner_radius,
|
||||
};
|
||||
}
|
||||
|
||||
fragment float4 quad_fragment(
|
||||
QuadFragmentInput input [[stage_in]]
|
||||
) {
|
||||
float4 quad_sdf(QuadFragmentInput input) {
|
||||
float2 half_size = input.size / 2.;
|
||||
float2 center = input.origin + half_size;
|
||||
float2 center_to_point = input.position.xy - center;
|
||||
|
@ -95,12 +68,12 @@ fragment float4 quad_fragment(
|
|||
|
||||
float4 color;
|
||||
if (border_width == 0.) {
|
||||
color = coloru_to_colorf(input.background_color);
|
||||
color = input.background_color;
|
||||
} else {
|
||||
float inset_distance = distance + border_width;
|
||||
color = mix(
|
||||
coloru_to_colorf(input.border_color),
|
||||
coloru_to_colorf(input.background_color),
|
||||
input.border_color,
|
||||
input.background_color,
|
||||
saturate(0.5 - inset_distance)
|
||||
);
|
||||
}
|
||||
|
@ -109,6 +82,39 @@ fragment float4 quad_fragment(
|
|||
return coverage * color;
|
||||
}
|
||||
|
||||
vertex QuadFragmentInput quad_vertex(
|
||||
uint unit_vertex_id [[vertex_id]],
|
||||
uint quad_id [[instance_id]],
|
||||
constant float2 *unit_vertices [[buffer(GPUIQuadInputIndexVertices)]],
|
||||
constant GPUIQuad *quads [[buffer(GPUIQuadInputIndexQuads)]],
|
||||
constant GPUIUniforms *uniforms [[buffer(GPUIQuadInputIndexUniforms)]]
|
||||
) {
|
||||
float2 unit_vertex = unit_vertices[unit_vertex_id];
|
||||
GPUIQuad quad = quads[quad_id];
|
||||
float2 position = unit_vertex * quad.size + quad.origin;
|
||||
float4 device_position = to_device_position(position, uniforms->viewport_size);
|
||||
|
||||
return QuadFragmentInput {
|
||||
device_position,
|
||||
float2(0., 0.),
|
||||
quad.origin,
|
||||
quad.size,
|
||||
coloru_to_colorf(quad.background_color),
|
||||
quad.border_top,
|
||||
quad.border_right,
|
||||
quad.border_bottom,
|
||||
quad.border_left,
|
||||
coloru_to_colorf(quad.border_color),
|
||||
quad.corner_radius,
|
||||
};
|
||||
}
|
||||
|
||||
fragment float4 quad_fragment(
|
||||
QuadFragmentInput input [[stage_in]]
|
||||
) {
|
||||
return quad_sdf(input);
|
||||
}
|
||||
|
||||
struct ShadowFragmentInput {
|
||||
float4 position [[position]];
|
||||
vector_float2 origin;
|
||||
|
@ -217,12 +223,7 @@ fragment float4 sprite_fragment(
|
|||
return color;
|
||||
}
|
||||
|
||||
struct ImageFragmentInput {
|
||||
float4 position [[position]];
|
||||
float2 atlas_position;
|
||||
};
|
||||
|
||||
vertex ImageFragmentInput image_vertex(
|
||||
vertex QuadFragmentInput image_vertex(
|
||||
uint unit_vertex_id [[vertex_id]],
|
||||
uint image_id [[instance_id]],
|
||||
constant float2 *unit_vertices [[buffer(GPUIImageVertexInputIndexVertices)]],
|
||||
|
@ -236,18 +237,28 @@ vertex ImageFragmentInput image_vertex(
|
|||
float4 device_position = to_device_position(position, *viewport_size);
|
||||
float2 atlas_position = (unit_vertex * image.source_size + image.atlas_origin) / *atlas_size;
|
||||
|
||||
return ImageFragmentInput {
|
||||
return QuadFragmentInput {
|
||||
device_position,
|
||||
atlas_position,
|
||||
image.origin,
|
||||
image.target_size,
|
||||
float4(0.),
|
||||
image.border_top,
|
||||
image.border_right,
|
||||
image.border_bottom,
|
||||
image.border_left,
|
||||
coloru_to_colorf(image.border_color),
|
||||
image.corner_radius,
|
||||
};
|
||||
}
|
||||
|
||||
fragment float4 image_fragment(
|
||||
ImageFragmentInput input [[stage_in]],
|
||||
QuadFragmentInput input [[stage_in]],
|
||||
texture2d<float> atlas [[ texture(GPUIImageFragmentInputIndexAtlas) ]]
|
||||
) {
|
||||
constexpr sampler atlas_sampler(mag_filter::linear, min_filter::linear);
|
||||
return atlas.sample(atlas_sampler, input.atlas_position);
|
||||
input.background_color = atlas.sample(atlas_sampler, input.atlas_position);
|
||||
return quad_sdf(input);
|
||||
}
|
||||
|
||||
struct PathAtlasVertexOutput {
|
||||
|
|
|
@ -128,6 +128,8 @@ pub struct PathVertex {
|
|||
|
||||
pub struct Image {
|
||||
pub bounds: RectF,
|
||||
pub border: Border,
|
||||
pub corner_radius: f32,
|
||||
pub data: Arc<ImageData>,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue