Fix crash when selections exceed the container's bounds
This commit is contained in:
parent
ae447ca1d9
commit
d10fc6ce3f
6 changed files with 40 additions and 11 deletions
|
@ -54,7 +54,13 @@ impl PathBuilder {
|
||||||
self.current = point;
|
self.current = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self, color: ColorU) -> Path {
|
pub fn build(mut self, color: ColorU, clip_bounds: Option<RectF>) -> Path {
|
||||||
|
if let Some(clip_bounds) = clip_bounds {
|
||||||
|
self.bounds = self
|
||||||
|
.bounds
|
||||||
|
.intersection(clip_bounds)
|
||||||
|
.unwrap_or(RectF::default());
|
||||||
|
}
|
||||||
Path {
|
Path {
|
||||||
bounds: self.bounds,
|
bounds: self.bounds,
|
||||||
color,
|
color,
|
||||||
|
|
|
@ -181,6 +181,8 @@ impl Renderer {
|
||||||
vertices.push(shaders::GPUIPathVertex {
|
vertices.push(shaders::GPUIPathVertex {
|
||||||
xy_position: (atlas_origin + xy_position).to_float2(),
|
xy_position: (atlas_origin + xy_position).to_float2(),
|
||||||
st_position: vertex.st_position.to_float2(),
|
st_position: vertex.st_position.to_float2(),
|
||||||
|
clip_rect_origin: atlas_origin.to_float2(),
|
||||||
|
clip_rect_size: size.to_float2(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,4 +63,6 @@ typedef enum {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
vector_float2 xy_position;
|
vector_float2 xy_position;
|
||||||
vector_float2 st_position;
|
vector_float2 st_position;
|
||||||
|
vector_float2 clip_rect_origin;
|
||||||
|
vector_float2 clip_rect_size;
|
||||||
} GPUIPathVertex;
|
} GPUIPathVertex;
|
||||||
|
|
|
@ -218,21 +218,33 @@ fragment float4 sprite_fragment(
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PathAtlasVertexOutput {
|
||||||
|
float4 position [[position]];
|
||||||
|
float2 st_position;
|
||||||
|
float clip_rect_distance [[clip_distance]] [4];
|
||||||
|
};
|
||||||
|
|
||||||
struct PathAtlasFragmentInput {
|
struct PathAtlasFragmentInput {
|
||||||
float4 position [[position]];
|
float4 position [[position]];
|
||||||
float2 st_position;
|
float2 st_position;
|
||||||
};
|
};
|
||||||
|
|
||||||
vertex PathAtlasFragmentInput path_atlas_vertex(
|
vertex PathAtlasVertexOutput path_atlas_vertex(
|
||||||
uint vertex_id [[vertex_id]],
|
uint vertex_id [[vertex_id]],
|
||||||
constant GPUIPathVertex *vertices [[buffer(GPUIPathAtlasVertexInputIndexVertices)]],
|
constant GPUIPathVertex *vertices [[buffer(GPUIPathAtlasVertexInputIndexVertices)]],
|
||||||
constant float2 *atlas_size [[buffer(GPUIPathAtlasVertexInputIndexAtlasSize)]]
|
constant float2 *atlas_size [[buffer(GPUIPathAtlasVertexInputIndexAtlasSize)]]
|
||||||
) {
|
) {
|
||||||
GPUIPathVertex v = vertices[vertex_id];
|
GPUIPathVertex v = vertices[vertex_id];
|
||||||
float4 device_position = to_device_position(v.xy_position, *atlas_size);
|
float4 device_position = to_device_position(v.xy_position, *atlas_size);
|
||||||
return PathAtlasFragmentInput {
|
return PathAtlasVertexOutput {
|
||||||
device_position,
|
device_position,
|
||||||
v.st_position,
|
v.st_position,
|
||||||
|
{
|
||||||
|
v.xy_position.x - v.clip_rect_origin.x,
|
||||||
|
v.clip_rect_origin.x + v.clip_rect_size.x - v.xy_position.x,
|
||||||
|
v.xy_position.y - v.clip_rect_origin.y,
|
||||||
|
v.clip_rect_origin.y + v.clip_rect_size.y - v.xy_position.y
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -156,7 +156,9 @@ impl Layer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_path(&mut self, path: Path) {
|
fn push_path(&mut self, path: Path) {
|
||||||
self.paths.push(path);
|
if !path.bounds.is_empty() {
|
||||||
|
self.paths.push(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paths(&self) -> &[Path] {
|
pub fn paths(&self) -> &[Path] {
|
||||||
|
|
|
@ -259,7 +259,7 @@ impl BufferElement {
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
selection.paint(ctx.scene);
|
selection.paint(bounds, ctx.scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
if view.cursors_visible() {
|
if view.cursors_visible() {
|
||||||
|
@ -586,16 +586,21 @@ struct SelectionLine {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Selection {
|
impl Selection {
|
||||||
fn paint(&self, scene: &mut Scene) {
|
fn paint(&self, bounds: RectF, scene: &mut Scene) {
|
||||||
if self.lines.len() >= 2 && self.lines[0].start_x > self.lines[1].end_x {
|
if self.lines.len() >= 2 && self.lines[0].start_x > self.lines[1].end_x {
|
||||||
self.paint_lines(self.start_y, &self.lines[0..1], scene);
|
self.paint_lines(self.start_y, &self.lines[0..1], bounds, scene);
|
||||||
self.paint_lines(self.start_y + self.line_height, &self.lines[1..], scene);
|
self.paint_lines(
|
||||||
|
self.start_y + self.line_height,
|
||||||
|
&self.lines[1..],
|
||||||
|
bounds,
|
||||||
|
scene,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
self.paint_lines(self.start_y, &self.lines, scene);
|
self.paint_lines(self.start_y, &self.lines, bounds, scene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint_lines(&self, start_y: f32, lines: &[SelectionLine], scene: &mut Scene) {
|
fn paint_lines(&self, start_y: f32, lines: &[SelectionLine], bounds: RectF, scene: &mut Scene) {
|
||||||
if lines.is_empty() {
|
if lines.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -675,7 +680,7 @@ impl Selection {
|
||||||
path.curve_to(first_top_left + top_curve_width, first_top_left);
|
path.curve_to(first_top_left + top_curve_width, first_top_left);
|
||||||
path.line_to(first_top_right - top_curve_width);
|
path.line_to(first_top_right - top_curve_width);
|
||||||
|
|
||||||
scene.push_path(path.build(ColorF::new(0.639, 0.839, 1.0, 1.0).to_u8()));
|
scene.push_path(path.build(ColorF::new(0.639, 0.839, 1.0, 1.0).to_u8(), Some(bounds)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue