mirror of
https://github.com/penpot/penpot.git
synced 2025-07-18 22:37:23 +02:00
♻️ Refactor tile iteration
This commit is contained in:
parent
55d21761fc
commit
ef95e3ecb0
6 changed files with 160 additions and 114 deletions
|
@ -75,13 +75,8 @@ pub fn render_debug_shape(render_state: &mut RenderState, element: &Shape, inter
|
|||
.draw_rect(rect, &paint);
|
||||
}
|
||||
|
||||
pub fn render_debug_tiles_for_viewbox(
|
||||
render_state: &mut RenderState,
|
||||
sx: i32,
|
||||
sy: i32,
|
||||
ex: i32,
|
||||
ey: i32,
|
||||
) {
|
||||
pub fn render_debug_tiles_for_viewbox(render_state: &mut RenderState) {
|
||||
let tiles::TileRect(sx, sy, ex, ey) = render_state.tile_viewbox.interest_rect;
|
||||
let canvas = render_state.surfaces.canvas(SurfaceId::Debug);
|
||||
let mut paint = skia::Paint::default();
|
||||
paint.set_style(skia::PaintStyle::Stroke);
|
||||
|
@ -102,7 +97,9 @@ pub fn render_debug_viewbox_tiles(render_state: &mut RenderState) {
|
|||
paint.set_color(skia::Color::from_rgb(255, 0, 127));
|
||||
paint.set_stroke_width(1.);
|
||||
|
||||
let (sx, sy, ex, ey) = tiles::get_tiles_for_viewbox(render_state.viewbox, scale);
|
||||
let tile_size = tiles::get_tile_size(scale);
|
||||
let tiles::TileRect(sx, sy, ex, ey) =
|
||||
tiles::get_tiles_for_rect(render_state.viewbox.area, tile_size);
|
||||
let str_rect = format!("{} {} {} {}", sx, sy, ex, ey);
|
||||
|
||||
let debug_font = render_state.fonts.debug_font();
|
||||
|
@ -135,11 +132,12 @@ pub fn render_debug_tiles(render_state: &mut RenderState) {
|
|||
paint.set_color(skia::Color::from_rgb(127, 0, 255));
|
||||
paint.set_stroke_width(1.);
|
||||
|
||||
let (sx, sy, ex, ey) = tiles::get_tiles_for_viewbox(render_state.viewbox, scale);
|
||||
let tile_size = tiles::get_tile_size(scale);
|
||||
let tiles::TileRect(sx, sy, ex, ey) =
|
||||
tiles::get_tiles_for_rect(render_state.viewbox.area, tile_size);
|
||||
for y in sy..=ey {
|
||||
for x in sx..=ex {
|
||||
let tile = (x, y);
|
||||
let tile = tiles::Tile(x, y);
|
||||
let shape_count = render_state.tiles.get_shapes_at(tile).iter().len();
|
||||
if shape_count == 0 {
|
||||
continue;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::shapes::Shape;
|
||||
use skia_safe::{self as skia, IRect, Paint, RRect};
|
||||
|
||||
use super::{gpu_state::GpuState, tiles::Tile, tiles::TILE_SIZE};
|
||||
use super::{gpu_state::GpuState, tiles::Tile, tiles::TileViewbox, tiles::TILE_SIZE};
|
||||
|
||||
use base64::{engine::general_purpose, Engine as _};
|
||||
use std::collections::HashMap;
|
||||
|
@ -241,15 +241,12 @@ impl Surfaces {
|
|||
.reset_matrix();
|
||||
}
|
||||
|
||||
pub fn cache_clear_visited(&mut self) {
|
||||
self.tiles.clear_visited();
|
||||
}
|
||||
|
||||
pub fn cache_visit(&mut self, tile: Tile) {
|
||||
self.tiles.visit(tile);
|
||||
}
|
||||
|
||||
pub fn cache_current_tile_texture(&mut self, tile: Tile, tile_rect: skia::Rect) {
|
||||
pub fn cache_current_tile_texture(
|
||||
&mut self,
|
||||
tile_viewbox: &TileViewbox,
|
||||
tile: &Tile,
|
||||
tile_rect: &skia::Rect,
|
||||
) {
|
||||
let rect = IRect::from_xywh(
|
||||
self.margins.width,
|
||||
self.margins.height,
|
||||
|
@ -258,7 +255,7 @@ impl Surfaces {
|
|||
);
|
||||
|
||||
if let Some(snapshot) = self.current.image_snapshot_with_bounds(rect) {
|
||||
self.tiles.add(tile, snapshot.clone());
|
||||
self.tiles.add(tile_viewbox, tile, snapshot.clone());
|
||||
self.cache.canvas().draw_image_rect(
|
||||
snapshot.clone(),
|
||||
None,
|
||||
|
@ -290,14 +287,12 @@ impl Surfaces {
|
|||
|
||||
pub struct TileTextureCache {
|
||||
grid: HashMap<Tile, skia::Image>,
|
||||
visited: HashMap<Tile, bool>,
|
||||
}
|
||||
|
||||
impl TileTextureCache {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
grid: HashMap::new(),
|
||||
visited: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,13 +306,13 @@ impl TileTextureCache {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, tile: Tile, image: skia::Image) {
|
||||
pub fn add(&mut self, tile_viewbox: &TileViewbox, tile: &Tile, image: skia::Image) {
|
||||
if self.grid.len() > TEXTURES_CACHE_CAPACITY {
|
||||
let marked: Vec<_> = self
|
||||
.grid
|
||||
.iter_mut()
|
||||
.filter_map(|(tile, _)| {
|
||||
if !self.visited.contains_key(tile) {
|
||||
if !tile_viewbox.is_visible(tile) {
|
||||
Some(*tile)
|
||||
} else {
|
||||
None
|
||||
|
@ -327,7 +322,7 @@ impl TileTextureCache {
|
|||
.collect();
|
||||
self.remove_list(marked);
|
||||
}
|
||||
self.grid.insert(tile, image);
|
||||
self.grid.insert(*tile, image);
|
||||
}
|
||||
|
||||
pub fn get(&mut self, tile: Tile) -> Result<&mut skia::Image, String> {
|
||||
|
@ -346,12 +341,4 @@ impl TileTextureCache {
|
|||
pub fn clear(&mut self) {
|
||||
self.grid.clear();
|
||||
}
|
||||
|
||||
pub fn clear_visited(&mut self) {
|
||||
self.visited.clear();
|
||||
}
|
||||
|
||||
pub fn visit(&mut self, tile: Tile) {
|
||||
self.visited.insert(tile, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
use crate::uuid::Uuid;
|
||||
use crate::view::Viewbox;
|
||||
use indexmap::IndexSet;
|
||||
use skia_safe as skia;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub type Tile = (i32, i32);
|
||||
pub type TileWithDistance = (i32, i32, i32);
|
||||
|
||||
pub const TILE_SIZE: f32 = 512.;
|
||||
|
||||
// @see https://en.wikipedia.org/wiki/Taxicab_geometry
|
||||
pub fn manhattan_distance(a: (i32, i32), b: (i32, i32)) -> i32 {
|
||||
(a.0 - b.0).abs() + (a.1 - b.1).abs()
|
||||
}
|
||||
|
||||
pub fn get_tile_dimensions() -> skia::ISize {
|
||||
(TILE_SIZE as i32, TILE_SIZE as i32).into()
|
||||
}
|
||||
|
||||
pub fn get_tiles_for_rect(rect: skia::Rect, tile_size: f32) -> (i32, i32, i32, i32) {
|
||||
// start
|
||||
let sx = (rect.left / tile_size).floor() as i32;
|
||||
let sy = (rect.top / tile_size).floor() as i32;
|
||||
// end
|
||||
let ex = (rect.right / tile_size).floor() as i32;
|
||||
let ey = (rect.bottom / tile_size).floor() as i32;
|
||||
(sx, sy, ex, ey)
|
||||
}
|
||||
|
||||
pub fn get_tiles_for_viewbox(viewbox: Viewbox, scale: f32) -> (i32, i32, i32, i32) {
|
||||
let tile_size = get_tile_size(scale);
|
||||
get_tiles_for_rect(viewbox.area, tile_size)
|
||||
}
|
||||
|
||||
pub fn get_tiles_for_viewbox_with_interest(
|
||||
viewbox: Viewbox,
|
||||
interest: i32,
|
||||
scale: f32,
|
||||
) -> (i32, i32, i32, i32) {
|
||||
let (sx, sy, ex, ey) = get_tiles_for_viewbox(viewbox, scale);
|
||||
(sx - interest, sy - interest, ex + interest, ey + interest)
|
||||
}
|
||||
|
||||
pub fn get_tile_pos((x, y): Tile, scale: f32) -> (f32, f32) {
|
||||
(
|
||||
x as f32 * get_tile_size(scale),
|
||||
y as f32 * get_tile_size(scale),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_tile_size(scale: f32) -> f32 {
|
||||
1. / scale * TILE_SIZE
|
||||
}
|
||||
|
||||
pub fn get_tile_rect(tile: Tile, scale: f32) -> skia::Rect {
|
||||
let (tx, ty) = get_tile_pos(tile, scale);
|
||||
let ts = get_tile_size(scale);
|
||||
skia::Rect::from_xywh(tx, ty, ts, ts)
|
||||
}
|
||||
|
||||
// This structure is usseful to keep all the shape uuids by shape id.
|
||||
pub struct TileHashMap {
|
||||
grid: HashMap<Tile, IndexSet<Uuid>>,
|
||||
index: HashMap<Uuid, HashSet<Tile>>,
|
||||
}
|
||||
|
||||
impl TileHashMap {
|
||||
pub fn new() -> Self {
|
||||
TileHashMap {
|
||||
grid: HashMap::new(),
|
||||
index: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_shapes_at(&mut self, tile: Tile) -> Option<&IndexSet<Uuid>> {
|
||||
self.grid.get(&tile)
|
||||
}
|
||||
|
||||
pub fn remove_shape_at(&mut self, tile: Tile, id: Uuid) {
|
||||
if let Some(shapes) = self.grid.get_mut(&tile) {
|
||||
shapes.shift_remove(&id);
|
||||
}
|
||||
|
||||
if let Some(tiles) = self.index.get_mut(&id) {
|
||||
tiles.remove(&tile);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_tiles_of(&mut self, shape_id: Uuid) -> Option<&HashSet<Tile>> {
|
||||
self.index.get(&shape_id)
|
||||
}
|
||||
|
||||
pub fn add_shape_at(&mut self, tile: Tile, shape_id: Uuid) {
|
||||
self.grid.entry(tile).or_default();
|
||||
self.index.entry(shape_id).or_default();
|
||||
|
||||
let tile_set = self.grid.get_mut(&tile).unwrap();
|
||||
tile_set.insert(shape_id);
|
||||
|
||||
let index_set = self.index.get_mut(&shape_id).unwrap();
|
||||
index_set.insert(tile);
|
||||
}
|
||||
|
||||
pub fn invalidate(&mut self) {
|
||||
self.grid.clear();
|
||||
self.index.clear();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue