mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Add resize functionality to quadtrees
This commit is contained in:
parent
1d04d5f1bc
commit
b0b62e2c53
1 changed files with 76 additions and 6 deletions
|
@ -8,7 +8,7 @@
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use std::uint::{div_ceil, next_power_of_two};
|
use std::uint::{div_ceil, next_power_of_two, range};
|
||||||
use std::vec::build_sized;
|
use std::vec::build_sized;
|
||||||
use std::util::replace;
|
use std::util::replace;
|
||||||
use gfx::render_task::BufferRequest;
|
use gfx::render_task::BufferRequest;
|
||||||
|
@ -17,7 +17,7 @@ use servo_msg::compositor_msg::Tile;
|
||||||
/// Parent to all quadtree nodes. Stores variables needed at all levels. All method calls
|
/// Parent to all quadtree nodes. Stores variables needed at all levels. All method calls
|
||||||
/// at this level are in pixel coordinates.
|
/// at this level are in pixel coordinates.
|
||||||
pub struct Quadtree<T> {
|
pub struct Quadtree<T> {
|
||||||
root: QuadtreeNode<T>,
|
root: ~QuadtreeNode<T>,
|
||||||
max_tile_size: uint,
|
max_tile_size: uint,
|
||||||
max_mem: Option<uint>,
|
max_mem: Option<uint>,
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ impl<T: Tile> Quadtree<T> {
|
||||||
let size = power_of_two * tile_size;
|
let size = power_of_two * tile_size;
|
||||||
|
|
||||||
Quadtree {
|
Quadtree {
|
||||||
root: QuadtreeNode {
|
root: ~QuadtreeNode {
|
||||||
tile: None,
|
tile: None,
|
||||||
origin: Point2D(0f32, 0f32),
|
origin: Point2D(0f32, 0f32),
|
||||||
size: size as f32,
|
size: size as f32,
|
||||||
|
@ -126,6 +126,48 @@ impl<T: Tile> Quadtree<T> {
|
||||||
scale, self.max_tile_size as f32 / scale);
|
scale, self.max_tile_size as f32 / scale);
|
||||||
(ret, redisplay)
|
(ret, redisplay)
|
||||||
}
|
}
|
||||||
|
/// Resize the quadtree. This can add more space, changing the root node, or it can shrink, making
|
||||||
|
/// an internal node the new root.
|
||||||
|
/// TODO: return tiles after shrinking
|
||||||
|
pub fn resize(&mut self, height: uint, width: uint) {
|
||||||
|
let longer = width.max(&height);
|
||||||
|
let new_num_tiles = div_ceil(longer, self.max_tile_size);
|
||||||
|
let new_size = next_power_of_two(new_num_tiles);
|
||||||
|
let difference = (new_size as f32 / self.root.size as f32).log2() as int;
|
||||||
|
if difference > 0 {
|
||||||
|
let difference = difference as uint;
|
||||||
|
for range(0, difference) |i| {
|
||||||
|
let new_root = ~QuadtreeNode {
|
||||||
|
tile: None,
|
||||||
|
origin: Point2D(0f32, 0f32),
|
||||||
|
size: new_size as f32 / ((difference - i - 1) as f32).exp2(),
|
||||||
|
quadrants: [None, None, None, None],
|
||||||
|
render_flag: false,
|
||||||
|
tile_mem: self.root.tile_mem,
|
||||||
|
};
|
||||||
|
self.root.quadrants[TL as int] = Some(replace(&mut self.root, new_root));
|
||||||
|
}
|
||||||
|
} else if difference < 0 {
|
||||||
|
let difference = difference.abs() as uint;
|
||||||
|
for difference.times {
|
||||||
|
let remove = replace(&mut self.root.quadrants[TL as int], None);
|
||||||
|
match remove {
|
||||||
|
Some(child) => self.root = child,
|
||||||
|
None => {
|
||||||
|
self.root = ~QuadtreeNode {
|
||||||
|
tile: None,
|
||||||
|
origin: Point2D(0f32, 0f32),
|
||||||
|
size: new_size as f32,
|
||||||
|
quadrants: [None, None, None, None],
|
||||||
|
render_flag: false,
|
||||||
|
tile_mem: 0,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate html to visualize the tree. For debugging purposes only.
|
/// Generate html to visualize the tree. For debugging purposes only.
|
||||||
pub fn get_html(&self) -> ~str {
|
pub fn get_html(&self) -> ~str {
|
||||||
|
@ -470,9 +512,9 @@ impl<T: Tile> QuadtreeNode<T> {
|
||||||
BL | BR => self.origin.y + new_size,
|
BL | BR => self.origin.y + new_size,
|
||||||
};
|
};
|
||||||
let mut child = ~QuadtreeNode::new_child(new_x, new_y, new_size);
|
let mut child = ~QuadtreeNode::new_child(new_x, new_y, new_size);
|
||||||
let (a, b, c) = child.get_tile_rects(new_window, scale, tile_size);
|
let ret = child.get_tile_rects(new_window, scale, tile_size);
|
||||||
self.quadrants[*quad as int] = Some(child);
|
self.quadrants[*quad as int] = Some(child);
|
||||||
(a, b, c)
|
ret
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -484,7 +526,6 @@ impl<T: Tile> QuadtreeNode<T> {
|
||||||
(ret, redisplay, delta)
|
(ret, redisplay, delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Generate html to visualize the tree.
|
/// Generate html to visualize the tree.
|
||||||
/// This is really inefficient, but it's for testing only.
|
/// This is really inefficient, but it's for testing only.
|
||||||
fn get_html(&self) -> ~str {
|
fn get_html(&self) -> ~str {
|
||||||
|
@ -525,6 +566,35 @@ impl<T: Tile> QuadtreeNode<T> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn test_resize() {
|
||||||
|
struct T {
|
||||||
|
a: int,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tile for T {
|
||||||
|
fn get_mem(&self) -> uint {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_valid(&self, _: f32) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut q = Quadtree::new(6, 6, 1, None);
|
||||||
|
q.add_tile(0, 0, 1f32, T{a: 0});
|
||||||
|
q.add_tile(5, 5, 1f32, T{a: 1});
|
||||||
|
q.resize(8, 1);
|
||||||
|
assert!(q.root.size == 8.0);
|
||||||
|
q.resize(18, 1);
|
||||||
|
assert!(q.root.size == 32.0);
|
||||||
|
q.resize(8, 1);
|
||||||
|
assert!(q.root.size == 8.0);
|
||||||
|
q.resize(3, 1);
|
||||||
|
assert!(q.root.size == 4.0);
|
||||||
|
assert!(q.get_all_tiles().len() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test() {
|
pub fn test() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue