handwritin: Grow and shrink the canvas without refreshing
This commit is contained in:
@ -18,6 +18,7 @@ const CHUNK_SIZE: usize = 64;
|
|||||||
/// Rasterize onto a resizeable canvas.
|
/// Rasterize onto a resizeable canvas.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct CanvasRasterizer {
|
pub struct CanvasRasterizer {
|
||||||
|
image_size: [usize; 2],
|
||||||
tiles: HashMap<[usize; 2], Tile>,
|
tiles: HashMap<[usize; 2], Tile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,12 +50,30 @@ impl Tile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CanvasRasterizer {
|
impl CanvasRasterizer {
|
||||||
//pub fn clear(&mut self) {
|
|
||||||
// self.image = ColorImage::new(self.image.size, Color32::TRANSPARENT);
|
|
||||||
// self.texture_is_dirty = true;
|
|
||||||
//}
|
|
||||||
|
|
||||||
pub fn set_size(&mut self, width: usize, height: usize) {
|
pub fn set_size(&mut self, width: usize, height: usize) {
|
||||||
|
self.image_size = [width, height];
|
||||||
|
self.populate_tiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
log::error!("clearing all tiles");
|
||||||
|
self.tiles.clear();
|
||||||
|
self.populate_tiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_and_set_size(&mut self, width: usize, height: usize) {
|
||||||
|
self.image_size = [width, height];
|
||||||
|
self.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn populate_tiles(&mut self) {
|
||||||
|
let [width, height] = self.image_size;
|
||||||
|
|
||||||
|
// discard tiles that are out of bounds
|
||||||
|
self.tiles.retain(|_, tile| {
|
||||||
|
tile.bounding_box.x_from <= width && tile.bounding_box.y_from <= height
|
||||||
|
});
|
||||||
|
|
||||||
let chunk = |max: usize| {
|
let chunk = |max: usize| {
|
||||||
(0..)
|
(0..)
|
||||||
.step_by(CHUNK_SIZE)
|
.step_by(CHUNK_SIZE)
|
||||||
@ -62,6 +81,7 @@ impl CanvasRasterizer {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// create new tiles where we need them
|
||||||
for (xi, _x) in chunk(width) {
|
for (xi, _x) in chunk(width) {
|
||||||
for (yi, _y) in chunk(height) {
|
for (yi, _y) in chunk(height) {
|
||||||
self.tiles
|
self.tiles
|
||||||
@ -71,13 +91,6 @@ impl CanvasRasterizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_and_set_size(&mut self, width: usize, height: usize) {
|
|
||||||
log::error!("clearing all tiles");
|
|
||||||
self.tiles.clear();
|
|
||||||
|
|
||||||
self.set_size(width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rasterize<'a>(
|
pub fn rasterize<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
point_to_pixel: TSTransform,
|
point_to_pixel: TSTransform,
|
||||||
|
|||||||
@ -105,20 +105,9 @@ struct MeshContext {
|
|||||||
|
|
||||||
pub pixels_per_point: f32,
|
pub pixels_per_point: f32,
|
||||||
|
|
||||||
/// Canvas size in points
|
|
||||||
pub size: Vec2,
|
|
||||||
|
|
||||||
pub stroke: Stroke,
|
pub stroke: Stroke,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeshContext {
|
|
||||||
/// Calculate canvas size in pixels
|
|
||||||
pub fn pixel_size(&self) -> [usize; 2] {
|
|
||||||
let Vec2 { x, y } = self.size * self.pixels_per_point;
|
|
||||||
[x, y].map(|f| f.ceil() as usize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Handwriting {
|
impl Default for Handwriting {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -379,7 +368,6 @@ impl Handwriting {
|
|||||||
let new_context = MeshContext {
|
let new_context = MeshContext {
|
||||||
ui_theme: ui.ctx().theme(),
|
ui_theme: ui.ctx().theme(),
|
||||||
pixels_per_point: ui.pixels_per_point(),
|
pixels_per_point: ui.pixels_per_point(),
|
||||||
size: mesh_rect.size(),
|
|
||||||
stroke: style.stroke,
|
stroke: style.stroke,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -388,6 +376,13 @@ impl Handwriting {
|
|||||||
self.e.refresh_texture = true;
|
self.e.refresh_texture = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let [px_width, px_height] = {
|
||||||
|
let Vec2 { x, y } = mesh_rect.size() * new_context.pixels_per_point;
|
||||||
|
[x, y].map(|f| f.ceil() as usize)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.e.canvas_rasterizer.set_size(px_width, px_height);
|
||||||
|
|
||||||
if self.e.refresh_texture {
|
if self.e.refresh_texture {
|
||||||
// ...if we do, rasterize the entire texture from scratch
|
// ...if we do, rasterize the entire texture from scratch
|
||||||
self.refresh_texture(style, new_context);
|
self.refresh_texture(style, new_context);
|
||||||
@ -457,11 +452,10 @@ impl Handwriting {
|
|||||||
// debug_assert!(vertex.pos.y.is_finite(), "{} must be finite", vertex.pos.y);
|
// debug_assert!(vertex.pos.y.is_finite(), "{} must be finite", vertex.pos.y);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
let [px_x, px_y] = mesh_context.pixel_size();
|
|
||||||
let point_to_pixel = TSTransform::from_scaling(mesh_context.pixels_per_point);
|
let point_to_pixel = TSTransform::from_scaling(mesh_context.pixels_per_point);
|
||||||
let triangles = mesh_triangles(&self.e.mesh);
|
let triangles = mesh_triangles(&self.e.mesh);
|
||||||
|
|
||||||
self.e.canvas_rasterizer.clear_and_set_size(px_x, px_y);
|
self.e.canvas_rasterizer.clear();
|
||||||
self.e
|
self.e
|
||||||
.canvas_rasterizer
|
.canvas_rasterizer
|
||||||
.rasterize(point_to_pixel, triangles);
|
.rasterize(point_to_pixel, triangles);
|
||||||
|
|||||||
Reference in New Issue
Block a user