mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
🐛 Update atlas when removing shape
This commit is contained in:
parent
3f0d103cb3
commit
9cf787d154
@ -2817,6 +2817,24 @@ impl RenderState {
|
||||
paint.set_color(self.background_color);
|
||||
s.canvas().draw_rect(tile_rect, &paint);
|
||||
});
|
||||
// Keep Cache surface coherent for render_from_cache.
|
||||
if !self.options.is_fast_mode() {
|
||||
if !self.cache_cleared_this_render {
|
||||
self.surfaces.clear_cache(self.background_color);
|
||||
self.cache_cleared_this_render = true;
|
||||
}
|
||||
let aligned_rect = self.get_aligned_tile_bounds(current_tile);
|
||||
self.surfaces.apply_mut(SurfaceId::Cache as u32, |s| {
|
||||
let mut paint = skia::Paint::default();
|
||||
paint.set_color(self.background_color);
|
||||
s.canvas().draw_rect(aligned_rect, &paint);
|
||||
});
|
||||
}
|
||||
|
||||
// Clear atlas region to transparent so background shows through.
|
||||
let _ = self
|
||||
.surfaces
|
||||
.clear_doc_rect_in_atlas(&mut self.gpu_state, self.render_area);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,6 +289,33 @@ impl Surfaces {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn clear_doc_rect_in_atlas(
|
||||
&mut self,
|
||||
gpu_state: &mut GpuState,
|
||||
doc_rect: skia::Rect,
|
||||
) -> Result<()> {
|
||||
if doc_rect.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.ensure_atlas_contains(gpu_state, doc_rect)?;
|
||||
|
||||
// Destination is document-space rect mapped into atlas pixel coords.
|
||||
let dst = skia::Rect::from_xywh(
|
||||
(doc_rect.left - self.atlas_origin.x) * self.atlas_scale,
|
||||
(doc_rect.top - self.atlas_origin.y) * self.atlas_scale,
|
||||
doc_rect.width() * self.atlas_scale,
|
||||
doc_rect.height() * self.atlas_scale,
|
||||
);
|
||||
|
||||
let canvas = self.atlas.canvas();
|
||||
canvas.save();
|
||||
canvas.clip_rect(dst, None, true);
|
||||
canvas.clear(skia::Color::TRANSPARENT);
|
||||
canvas.restore();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn clear_tiles(&mut self) {
|
||||
self.tiles.clear();
|
||||
}
|
||||
|
||||
@ -160,14 +160,24 @@ impl State {
|
||||
|
||||
// Only remove the children when is being deleted from the owner
|
||||
if shape.parent_id.is_none() || shape.parent_id == Some(parent_id) {
|
||||
let tiles::TileRect(rsx, rsy, rex, rey) =
|
||||
self.render_state.get_tiles_for_shape(shape, &self.shapes);
|
||||
for x in rsx..=rex {
|
||||
for y in rsy..=rey {
|
||||
let tile = tiles::Tile(x, y);
|
||||
self.render_state.remove_cached_tile(tile);
|
||||
self.render_state.tiles.remove_shape_at(tile, shape.id);
|
||||
}
|
||||
// IMPORTANT:
|
||||
// Do NOT use `get_tiles_for_shape` here. That method intersects the shape
|
||||
// tiles with the current interest area, which means we'd only invalidate
|
||||
// the subset currently near the viewport. When the user later pans/zooms
|
||||
// to reveal previously cached tiles, stale pixels could reappear.
|
||||
//
|
||||
// Instead, remove the shape from *all* tiles where it was indexed, and
|
||||
// drop cached tiles for those entries.
|
||||
let indexed_tiles: Vec<tiles::Tile> = self
|
||||
.render_state
|
||||
.tiles
|
||||
.get_tiles_of(shape.id)
|
||||
.map(|t| t.iter().copied().collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
for tile in indexed_tiles {
|
||||
self.render_state.remove_cached_tile(tile);
|
||||
self.render_state.tiles.remove_shape_at(tile, shape.id);
|
||||
}
|
||||
|
||||
if let Some(shape_to_delete) = self.shapes.get(&id) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user