1use std::collections::{BTreeMap, HashMap};
6
7use kurbo::{BezPath, Rect as KRect, Shape, Vec2};
8use rstar::{AABB, RTree, RTreeObject};
9
10use crate::render::{Draw, Frame};
11
12use super::*;
13
14#[derive(Clone, PartialEq, Debug)]
17pub(super) enum What {
18 Chunk(Order),
19 Run(RunId),
20}
21
22#[derive(Clone, PartialEq)]
24pub(super) struct Entry {
25 pub(super) what: What,
26 pub(super) bounds: KRect,
27}
28
29impl RTreeObject for Entry {
30 type Envelope = AABB<[f64; 2]>;
31 fn envelope(&self) -> Self::Envelope {
32 aabb(self.bounds)
33 }
34}
35
36pub(super) struct Found<'a> {
39 pub(super) order: &'a Order,
40 pub(super) at: Vec2,
41 pub(super) cut: Option<KRect>,
42}
43
44#[derive(Default)]
47pub(super) struct Extent {
48 x0: BTreeMap<i64, usize>,
49 y0: BTreeMap<i64, usize>,
50 x1: BTreeMap<i64, usize>,
51 y1: BTreeMap<i64, usize>,
52}
53
54pub(super) fn key(v: f64) -> i64 {
56 (v * 1e6).round() as i64
57}
58
59impl Extent {
60 pub(super) fn add(&mut self, r: KRect) {
61 for (m, v) in [
62 (&mut self.x0, r.x0),
63 (&mut self.y0, r.y0),
64 (&mut self.x1, r.x1),
65 (&mut self.y1, r.y1),
66 ] {
67 *m.entry(key(v)).or_default() += 1;
68 }
69 }
70
71 pub(super) fn remove(&mut self, r: KRect) {
72 for (m, v) in [
73 (&mut self.x0, r.x0),
74 (&mut self.y0, r.y0),
75 (&mut self.x1, r.x1),
76 (&mut self.y1, r.y1),
77 ] {
78 let k = key(v);
79 if let Some(n) = m.get_mut(&k) {
80 *n -= 1;
81 if *n == 0 {
82 m.remove(&k);
83 }
84 }
85 }
86 }
87
88 pub(super) fn rect(&self) -> Option<KRect> {
89 let low = |m: &BTreeMap<i64, usize>| m.keys().next().map(|k| *k as f64 / 1e6);
90 let high = |m: &BTreeMap<i64, usize>| m.keys().next_back().map(|k| *k as f64 / 1e6);
91 Some(KRect::new(
92 low(&self.x0)?,
93 low(&self.y0)?,
94 high(&self.x1)?,
95 high(&self.y1)?,
96 ))
97 }
98}
99
100pub struct List {
104 pub trees: Trees,
105 pub(super) chunks: BTreeMap<Order, Chunk>,
106 pub(super) root: SpaceIndex,
107 pub(super) runs: Vec<Option<Run>>,
108 pub(super) free_runs: Vec<RunId>,
109 pub(super) stale: std::collections::BTreeSet<(RunId, crate::tree::OrderKey)>,
111 pub root_transform: Id,
113 pub root_clip: Id,
115 pub area: Frame,
117}
118
119impl Default for List {
120 fn default() -> Self {
121 List::new()
122 }
123}
124
125impl List {
126 pub fn new() -> List {
129 let mut trees = Trees::default();
130 let root_transform = trees.transforms.add(Transform {
131 parent: None,
132 offset: Vec2::ZERO,
133 item: None,
134 });
135 let root_clip = trees.clips.add(Clip {
136 parent: None,
137 transform: root_transform,
138 path: BezPath::new(),
139 });
140 List {
141 trees,
142 chunks: BTreeMap::new(),
143 root: SpaceIndex::default(),
144 runs: Vec::new(),
145 free_runs: Vec::new(),
146 stale: Default::default(),
147 root_transform,
148 root_clip,
149 area: Frame {
150 x: 0.0,
151 y: 0.0,
152 width: 0.0,
153 height: 0.0,
154 },
155 }
156 }
157
158 pub fn of(area: Frame, build: impl FnOnce(&mut Builder)) -> List {
161 let mut list = List::new();
162 list.set_area(area);
163 let (t, c) = (list.root_transform, list.root_clip);
164 let mut b = Builder::new(&mut list.trees, t, c, None);
165 build(&mut b);
166 let made = b.finish();
167 list.put(
168 Vec::new(),
169 Chunk::new(t, Space::Root, Vec2::ZERO, made, Vec::new(), None, None),
170 );
171 list
172 }
173
174 pub fn load(&mut self, chunks: Vec<(Order, Chunk)>) {
177 let mut entries: Vec<Entry> = std::mem::take(&mut self.root.index).into_iter().collect();
178 for (order, chunk) in chunks {
179 if chunk.space != Space::Root {
180 self.put(order, chunk);
181 continue;
182 }
183 if let Some(r) = chunk.cover() {
184 self.root.covers.add(r);
185 }
186 if let Some(bounds) = chunk.reach() {
187 entries.push(Entry {
188 what: What::Chunk(order.clone()),
189 bounds,
190 });
191 }
192 self.chunks.insert(order, chunk);
193 }
194 self.root.index = RTree::bulk_load(entries);
195 self.flush();
196 }
197
198 pub fn set_area(&mut self, area: Frame) {
200 self.area = area;
201 self.trees.clips.get_mut(self.root_clip).path = frame_rect(area).to_path(0.1);
202 }
203
204 pub fn covered(&self) -> Option<KRect> {
206 self.root.covers.rect()
207 }
208
209 pub fn chunk(&self, order: &Order) -> Option<&Chunk> {
210 self.chunks.get(order)
211 }
212
213 pub fn chunks(&self) -> impl Iterator<Item = (&Order, &Chunk)> {
215 self.chunks.iter()
216 }
217
218 fn local(&mut self, space: &Space) -> &mut SpaceIndex {
220 match space {
221 Space::Root => &mut self.root,
222 Space::Item(r, k) => self.runs[*r as usize]
223 .as_mut()
224 .expect("a live run")
225 .spaces
226 .entry(k.clone())
227 .or_default(),
228 }
229 }
230
231 pub fn take(&mut self, order: &Order) -> Option<Chunk> {
233 let chunk = self.chunks.remove(order)?;
234 let (reach, cover, space) = (chunk.reach(), chunk.cover(), chunk.space.clone());
235 if self.space_lives(&space) {
236 let local = self.local(&space);
237 if let Some(bounds) = reach {
238 local.index.remove(&Entry {
239 what: What::Chunk(order.clone()),
240 bounds,
241 });
242 }
243 if let Some(r) = cover {
244 local.covers.remove(r);
245 }
246 self.touch(&space);
247 }
248 Some(chunk)
249 }
250
251 pub fn put(&mut self, order: Order, chunk: Chunk) {
253 let (reach, cover, space) = (chunk.reach(), chunk.cover(), chunk.space.clone());
254 let local = self.local(&space);
255 if let Some(bounds) = reach {
256 local.index.insert(Entry {
257 what: What::Chunk(order.clone()),
258 bounds,
259 });
260 }
261 if let Some(r) = cover {
262 local.covers.add(r);
263 }
264 self.touch(&space);
265 self.chunks.insert(order, chunk);
266 }
267
268 fn space_lives(&self, space: &Space) -> bool {
269 match space {
270 Space::Root => true,
271 Space::Item(r, _) => self.runs.get(*r as usize).is_some_and(|r| r.is_some()),
272 }
273 }
274
275 fn touch(&mut self, space: &Space) {
277 if let Space::Item(r, k) = space {
278 self.stale.insert((*r, k.clone()));
279 }
280 }
281
282 pub fn add_run(&mut self, space: Space) -> RunId {
284 let run = Run::new(space);
285 match self.free_runs.pop() {
286 Some(id) => {
287 self.runs[id as usize] = Some(run);
288 id
289 }
290 None => {
291 self.runs.push(Some(run));
292 (self.runs.len() - 1) as RunId
293 }
294 }
295 }
296
297 pub fn run(&self, id: RunId) -> &Run {
298 self.runs[id as usize].as_ref().expect("a live run")
299 }
300
301 pub fn run_mut(&mut self, id: RunId) -> &mut Run {
302 self.runs[id as usize].as_mut().expect("a live run")
303 }
304
305 pub fn remove_run(&mut self, id: RunId) {
308 self.place_run(id, None, None);
309 let space = self.run(id).space.clone();
310 self.runs[id as usize] = None;
311 self.free_runs.push(id);
312 self.stale.retain(|(r, _)| *r != id);
313 self.touch(&space);
314 }
315
316 pub fn place_child(&mut self, id: RunId, key: crate::tree::OrderKey, placed: Option<Placed>) {
319 let run = self.run_mut(id);
320 match placed {
321 Some(p) => run.set(key.clone(), p),
322 None => {
323 run.unset(&key);
324 run.spaces.remove(&key);
325 }
326 }
327 self.stale.remove(&(id, key));
328 self.resum(id);
329 }
330
331 pub fn resum(&mut self, id: RunId) {
334 let (reach, cover) = self.run(id).extents();
335 self.place_run(id, reach, cover);
336 }
337
338 fn place_run(&mut self, id: RunId, reach: Option<KRect>, cover: Option<KRect>) {
339 let (space, old_reach, old_cover) = {
340 let run = self.run(id);
341 (run.space.clone(), run.entry, run.cover)
342 };
343 if old_reach == reach && old_cover == cover {
344 return;
345 }
346 let local = self.local(&space);
347 if let Some(bounds) = old_reach {
348 local.index.remove(&Entry {
349 what: What::Run(id),
350 bounds,
351 });
352 }
353 if let Some(r) = old_cover {
354 local.covers.remove(r);
355 }
356 if let Some(bounds) = reach {
357 local.index.insert(Entry {
358 what: What::Run(id),
359 bounds,
360 });
361 }
362 if let Some(r) = cover {
363 local.covers.add(r);
364 }
365 let run = self.run_mut(id);
366 run.entry = reach;
367 run.cover = cover;
368 self.touch(&space);
369 }
370
371 pub fn flush(&mut self) {
374 while let Some((r, k)) = self.stale.pop_last() {
375 if !self.space_lives(&Space::Item(r, k.clone())) {
376 continue;
377 }
378 let run = self.run_mut(r);
379 if let Some(p) = run.items.get(&k).cloned() {
380 run.set(k, p);
381 }
382 self.resum(r);
383 }
384 }
385
386 pub fn free(&mut self, made: &Made) {
388 for &c in &made.clips {
389 self.trees.clips.remove(c);
390 }
391 for &e in &made.effects {
392 self.trees.effects.remove(e);
393 }
394 }
395
396 pub(super) fn found(&self, rect: KRect, pixel: f64) -> Vec<Found<'_>> {
400 let mut out = Vec::new();
401 self.found_in(&self.root, Vec2::ZERO, None, rect, pixel, &mut out);
402 out.sort_by(|a, b| a.order.cmp(b.order));
403 out
404 }
405
406 fn found_in<'a>(
407 &'a self,
408 local: &'a SpaceIndex,
409 at: Vec2,
410 cut: Option<KRect>,
411 rect: KRect,
412 pixel: f64,
413 out: &mut Vec<Found<'a>>,
414 ) {
415 let inside = rect - at;
416 for e in local.index.locate_in_envelope_intersecting(&aabb(inside)) {
417 if e.bounds.width() < pixel && e.bounds.height() < pixel {
418 continue;
419 }
420 match &e.what {
421 What::Chunk(order) => out.push(Found { order, at, cut }),
422 What::Run(id) => {
423 let run = self.run(*id);
424 let outer = run.cut.map(|c| c + at);
425 let cut = match (cut, outer) {
426 (Some(a), Some(b)) => Some(a.intersect(b)),
427 (a, b) => a.or(b),
428 };
429 let rect = match outer {
430 Some(c) => rect.intersect(c),
431 None => rect,
432 };
433 if rect.width() < 0.0 || rect.height() < 0.0 {
434 continue;
435 }
436 for (k, child) in run.touching(rect - at) {
437 if let Some(space) = run.spaces.get(k) {
438 self.found_in(space, at + child, cut, rect, pixel, out);
439 }
440 }
441 }
442 }
443 }
444 }
445
446 pub fn unrounded(&self, rect: KRect) -> Vec<(RunId, crate::tree::OrderKey)> {
451 let mut out = Vec::new();
452 self.unrounded_in(&self.root, Vec2::ZERO, rect, &mut out);
453 out
454 }
455
456 fn unrounded_in(
457 &self,
458 local: &SpaceIndex,
459 at: Vec2,
460 rect: KRect,
461 out: &mut Vec<(RunId, crate::tree::OrderKey)>,
462 ) {
463 for e in local
464 .index
465 .locate_in_envelope_intersecting(&aabb(rect - at))
466 {
467 let What::Run(id) = &e.what else { continue };
468 let run = self.run(*id);
469 let rect = match run.cut {
470 Some(c) => rect.intersect(c + at),
471 None => rect,
472 };
473 if rect.width() < 0.0 || rect.height() < 0.0 {
474 continue;
475 }
476 for (k, child, fresh) in run.touching_rounded(rect - at) {
477 if !fresh {
478 out.push((*id, k.clone()));
479 } else if let Some(space) = run.spaces.get(k) {
480 self.unrounded_in(space, at + child, rect, out);
481 }
482 }
483 }
484 }
485
486 pub fn query(&self, rect: KRect, pixel: f64) -> Vec<(Vec2, &Chunk, &Command)> {
490 let mut out = Vec::new();
491 for f in self.found(rect, pixel) {
492 let chunk = &self.chunks[f.order];
493 let origin = f.at + chunk.origin;
494 let local = rect - origin;
495 let mut at: Vec<usize> = chunk
496 .index
497 .locate_in_envelope_intersecting(&aabb(local))
498 .map(|l| l.at)
499 .collect();
500 at.sort_unstable();
501 out.extend(at.into_iter().map(|i| (origin, chunk, &chunk.commands[i])));
502 }
503 out
504 }
505
506 pub fn space_at(&self, space: &Space) -> Vec2 {
508 match space {
509 Space::Root => Vec2::ZERO,
510 Space::Item(r, k) => {
511 let run = self.run(*r);
512 self.space_at(&run.space) + run.child_at(k).unwrap_or(Vec2::ZERO)
513 }
514 }
515 }
516
517 pub(super) fn world(&self, mut transform: Id) -> Vec2 {
519 let mut at = Vec2::ZERO;
520 loop {
521 let t = self.trees.transforms.get(transform);
522 at += t.offset;
523 if let Some((r, k)) = &t.item {
524 return at + self.space_at(&Space::Item(*r, k.clone()));
525 }
526 match t.parent {
527 Some(p) => transform = p,
528 None => return at,
529 }
530 }
531 }
532
533 pub fn swap_images(&mut self, last_of: &HashMap<u64, peniko::ImageData>) {
536 for chunk in self.chunks.values_mut() {
537 for c in &mut chunk.commands {
538 if let Draw::Fill(_, crate::render::Paint::Image(data, _)) = &mut c.draw
539 && let Some(old) = last_of.get(&data.data.id())
540 {
541 *data = old.clone();
542 }
543 }
544 }
545 }
546}
547
548pub(super) fn frame_rect(f: Frame) -> KRect {
549 KRect::new(
550 f.x as f64,
551 f.y as f64,
552 (f.x + f.width) as f64,
553 (f.y + f.height) as f64,
554 )
555}
556
557#[cfg(test)]
558mod tests;