0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-01 11:59:17 -05:00

♻️ Refactor navigate() method

This commit is contained in:
Belén Albeza 2024-11-26 15:06:49 +01:00
parent 52a705ac02
commit 5ce6cbff6f
3 changed files with 70 additions and 55 deletions

View file

@ -55,8 +55,13 @@ impl GpuState {
pub(crate) struct CachedSurfaceImage { pub(crate) struct CachedSurfaceImage {
pub image: Image, pub image: Image,
pub viewbox: Viewbox, pub viewbox: Viewbox,
// is_complete indicates if stored image renders the complete shape tree has_all_shapes: bool,
pub is_complete: bool, }
impl CachedSurfaceImage {
fn is_dirty(&self, viewbox: &Viewbox) -> bool {
!self.has_all_shapes && !self.viewbox.area.contains(viewbox.area)
}
} }
#[derive(Debug, Default, Copy, Clone, PartialEq)] #[derive(Debug, Default, Copy, Clone, PartialEq)]
@ -198,49 +203,20 @@ impl RenderState {
.clear(skia::Color::TRANSPARENT); .clear(skia::Color::TRANSPARENT);
} }
pub fn navigate(&mut self, viewbox: &Viewbox, shapes: &HashMap<Uuid, Shape>) { pub fn navigate(
self.reset_canvas(); &mut self,
if let Some(cached_surface_image) = &self.cached_surface_image { viewbox: &Viewbox,
// If we are drawing something bigger than the visible let's do a redraw shapes: &HashMap<Uuid, Shape>,
if !cached_surface_image.is_complete ) -> Result<(), String> {
&& ((viewbox.x > cached_surface_image.viewbox.x) if let Some(cached_surface_image) = self.cached_surface_image.as_ref() {
|| (-viewbox.x + viewbox.area.width() if cached_surface_image.is_dirty(viewbox) {
> -cached_surface_image.viewbox.x
+ cached_surface_image.viewbox.area.width())
|| (viewbox.y > cached_surface_image.viewbox.y)
|| (-viewbox.y + viewbox.area.height()
> -cached_surface_image.viewbox.y
+ cached_surface_image.viewbox.area.height()))
{
self.render_all(viewbox, shapes, true); self.render_all(viewbox, shapes, true);
} else { } else {
let image = &cached_surface_image.image; self.render_all_from_cache(viewbox)?;
let paint = skia::Paint::default();
self.final_surface.canvas().save();
self.drawing_surface.canvas().save();
let navigate_zoom = viewbox.zoom / cached_surface_image.viewbox.zoom;
let navigate_x = cached_surface_image.viewbox.zoom
* (viewbox.x - cached_surface_image.viewbox.x);
let navigate_y = cached_surface_image.viewbox.zoom
* (viewbox.y - cached_surface_image.viewbox.y);
self.final_surface
.canvas()
.scale((navigate_zoom, navigate_zoom));
self.final_surface
.canvas()
.translate((navigate_x, navigate_y));
self.final_surface
.canvas()
.draw_image(image.clone(), (0, 0), Some(&paint));
self.final_surface.canvas().restore();
self.drawing_surface.canvas().restore();
} }
} }
self.flush(); Ok(())
} }
pub fn render_all( pub fn render_all(
@ -251,14 +227,14 @@ impl RenderState {
) { ) {
self.reset_canvas(); self.reset_canvas();
self.scale(viewbox.zoom, viewbox.zoom); self.scale(viewbox.zoom, viewbox.zoom);
self.translate(viewbox.x, viewbox.y); self.translate(viewbox.pan_x, viewbox.pan_y);
let is_complete = self.render_shape_tree(&Uuid::nil(), viewbox, shapes); let is_complete = self.render_shape_tree(&Uuid::nil(), viewbox, shapes);
if generate_cached_surface_image || self.cached_surface_image.is_none() { if generate_cached_surface_image || self.cached_surface_image.is_none() {
self.cached_surface_image = Some(CachedSurfaceImage { self.cached_surface_image = Some(CachedSurfaceImage {
image: self.final_surface.image_snapshot(), image: self.final_surface.image_snapshot(),
viewbox: viewbox.clone(), viewbox: viewbox.clone(),
is_complete, has_all_shapes: is_complete,
}); });
} }
@ -269,6 +245,41 @@ impl RenderState {
self.flush(); self.flush();
} }
fn render_all_from_cache(&mut self, viewbox: &Viewbox) -> Result<(), String> {
self.reset_canvas();
let cached = self
.cached_surface_image
.as_ref()
.ok_or("Uninitialized cached surface image")?;
let image = &cached.image;
let paint = skia::Paint::default();
self.final_surface.canvas().save();
self.drawing_surface.canvas().save();
let navigate_zoom = viewbox.zoom / cached.viewbox.zoom;
let navigate_x = cached.viewbox.zoom * (viewbox.pan_x - cached.viewbox.pan_x);
let navigate_y = cached.viewbox.zoom * (viewbox.pan_y - cached.viewbox.pan_y);
self.final_surface
.canvas()
.scale((navigate_zoom, navigate_zoom));
self.final_surface
.canvas()
.translate((navigate_x, navigate_y));
self.final_surface
.canvas()
.draw_image(image.clone(), (0, 0), Some(&paint));
self.final_surface.canvas().restore();
self.drawing_surface.canvas().restore();
self.flush();
Ok(())
}
fn render_debug_view(&mut self, viewbox: &Viewbox) { fn render_debug_view(&mut self, viewbox: &Viewbox) {
let mut paint = skia::Paint::default(); let mut paint = skia::Paint::default();
paint.set_style(skia::PaintStyle::Stroke); paint.set_style(skia::PaintStyle::Stroke);

View file

@ -27,8 +27,8 @@ impl<'a> State<'a> {
current_shape: None, current_shape: None,
shapes: HashMap::with_capacity(capacity), shapes: HashMap::with_capacity(capacity),
viewbox: Viewbox { viewbox: Viewbox {
x: 0., pan_x: 0.,
y: 0., pan_y: 0.,
zoom: 1., zoom: 1.,
width: width as f32, width: width as f32,
height: height as f32, height: height as f32,
@ -47,7 +47,11 @@ impl<'a> State<'a> {
} }
pub fn navigate(&mut self) { pub fn navigate(&mut self) {
self.render_state.navigate(&self.viewbox, &self.shapes); // TODO: propagate error to main fn
let _ = self
.render_state
.navigate(&self.viewbox, &self.shapes)
.unwrap();
} }
pub fn render_all(&mut self, generate_cached_surface_image: bool) { pub fn render_all(&mut self, generate_cached_surface_image: bool) {

View file

@ -2,8 +2,8 @@ use skia_safe as skia;
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub(crate) struct Viewbox { pub(crate) struct Viewbox {
pub x: f32, pub pan_x: f32,
pub y: f32, pub pan_y: f32,
pub width: f32, pub width: f32,
pub height: f32, pub height: f32,
pub zoom: f32, pub zoom: f32,
@ -11,13 +11,13 @@ pub(crate) struct Viewbox {
} }
impl Viewbox { impl Viewbox {
pub fn set_all(&mut self, zoom: f32, x: f32, y: f32) -> &Self { pub fn set_all(&mut self, zoom: f32, x: f32, y: f32) -> &mut Self {
self.x = x; self.pan_x = x;
self.y = y; self.pan_y = y;
self.zoom = zoom; self.zoom = zoom;
self.area.set_xywh( self.area.set_xywh(
-self.x, -self.pan_x,
-self.y, -self.pan_y,
self.width / self.zoom, self.width / self.zoom,
self.height / self.zoom, self.height / self.zoom,
); );
@ -31,9 +31,9 @@ impl Viewbox {
self self
} }
pub fn set_xy(&mut self, x: f32, y: f32) -> &Self { pub fn set_xy(&mut self, x: f32, y: f32) -> &mut Self {
self.x = x; self.pan_x = x;
self.y = y; self.pan_y = y;
self.area.left = -x; self.area.left = -x;
self.area.top = -y; self.area.top = -y;
self self