Multiple display list support

This commit is contained in:
Isabelle Carter 2014-01-22 09:57:25 -08:00
parent 7e3075522d
commit 0892fada74
7 changed files with 172 additions and 103 deletions

View file

@ -27,11 +27,62 @@ use std::cast::transmute_region;
use std::vec::VecIterator;
use style::computed_values::border_style;
pub struct DisplayListCollection<E> {
lists: ~[DisplayList<E>]
}
impl<E> DisplayListCollection<E> {
pub fn new() -> DisplayListCollection<E> {
DisplayListCollection {
lists: ~[]
}
}
pub fn iter<'a>(&'a self) -> DisplayListIterator<'a,E> {
ParentDisplayListIterator(self.lists.iter())
}
pub fn add_list(&mut self, list: DisplayList<E>) {
self.lists.push(list);
}
pub fn draw_lists_into_context(&self, render_context: &mut RenderContext) {
for list in self.lists.iter() {
list.draw_into_context(render_context);
}
debug!("{:?}", self.dump());
}
fn dump(&self) {
let mut index = 0;
for list in self.lists.iter() {
debug!("dumping display list {:d}:", index);
list.dump();
index = index + 1;
}
}
}
/// A list of rendering operations to be performed.
pub struct DisplayList<E> {
list: ~[DisplayItem<E>]
}
pub enum DisplayListIterator<'a,E> {
EmptyDisplayListIterator,
ParentDisplayListIterator(VecIterator<'a,DisplayList<E>>),
}
impl<'a,E> Iterator<&'a DisplayList<E>> for DisplayListIterator<'a,E> {
#[inline]
fn next(&mut self) -> Option<&'a DisplayList<E>> {
match *self {
EmptyDisplayListIterator => None,
ParentDisplayListIterator(ref mut subiterator) => subiterator.next(),
}
}
}
impl<E> DisplayList<E> {
/// Creates a new display list.
pub fn new() -> DisplayList<E> {
@ -62,7 +113,6 @@ impl<E> DisplayList<E> {
item.draw_into_context(render_context)
}
debug!("Ending display list.");
debug!("{:?}", self.dump());
}
/// Returns a preorder iterator over the given display list.

View file

@ -24,13 +24,14 @@ use std::comm::{Chan, Port, SharedChan};
use extra::arc::Arc;
use buffer_map::BufferMap;
use display_list::DisplayList;
use font_context::{FontContext, FontContextInfo};
use display_list::DisplayListCollection;
use font_context::{FontContext, FontContextInfo};
use opts::Opts;
use render_context::RenderContext;
pub struct RenderLayer<T> {
display_list: Arc<DisplayList<T>>,
display_list_collection: Arc<DisplayListCollection<T>>,
size: Size2D<uint>,
color: Color
}
@ -305,7 +306,7 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
// Draw the display list.
profile(time::RenderingDrawingCategory, self.profiler_chan.clone(), || {
render_layer.display_list.get().draw_into_context(&mut ctx);
render_layer.display_list_collection.get().draw_lists_into_context(&mut ctx);
ctx.draw_target.flush();
});
}

View file

@ -14,7 +14,7 @@ use layout::float_context::{FloatContext, PlacementInfo, Invalid, FloatType};
use std::cell::RefCell;
use geom::{Point2D, Rect, SideOffsets2D};
use gfx::display_list::DisplayList;
use gfx::display_list::{DisplayList, DisplayListCollection};
use servo_util::geometry::Au;
use servo_util::geometry;
@ -496,22 +496,31 @@ impl BlockFlow {
&mut self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
list: &RefCell<DisplayList<E>>)
-> bool {
mut index: uint,
lists: &RefCell<DisplayListCollection<E>>)
-> uint {
if self.is_float() {
return self.build_display_list_float(builder, dirty, list);
self.build_display_list_float(builder, dirty, index, lists);
return index;
}
if self.is_fixed {
lists.with_mut(|lists| {
index = lists.lists.len();
lists.add_list(DisplayList::<E>::new());
});
}
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
if !abs_rect.intersects(dirty) {
return true;
return index;
}
debug!("build_display_list_block: adding display element");
// add box that starts block context
for box_ in self.box_.iter() {
box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list)
box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, index, lists);
}
// TODO: handle any out-of-flow elements
let this_position = self.base.abs_position;
@ -521,24 +530,26 @@ impl BlockFlow {
child_base.abs_position = this_position + child_base.position.origin;
}
false
index
}
pub fn build_display_list_float<E:ExtraDisplayListData>(
&mut self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
list: &RefCell<DisplayList<E>>)
index: uint,
lists: &RefCell<DisplayListCollection<E>>)
-> bool {
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
if !abs_rect.intersects(dirty) {
return true
return true;
}
let offset = self.base.abs_position + self.float.get_ref().rel_pos;
// add box that starts block context
for box_ in self.box_.iter() {
box_.build_display_list(builder, dirty, offset, (&*self) as &Flow, list)
box_.build_display_list(builder, dirty, offset, (&*self) as &Flow, index, lists);
}

View file

@ -9,10 +9,10 @@ use extra::arc::{MutexArc, Arc};
use geom::{Point2D, Rect, Size2D, SideOffsets2D};
use gfx::color::rgb;
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass};
use gfx::display_list::{ImageDisplayItem, ImageDisplayItemClass};
use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, TextDisplayItem};
use gfx::display_list::{TextDisplayItemClass, TextDisplayItemFlags, ClipDisplayItem};
use gfx::display_list::{ClipDisplayItemClass};
use gfx::display_list::{ClipDisplayItemClass, DisplayListCollection};
use gfx::font::FontStyle;
use gfx::text::text_run::TextRun;
@ -784,7 +784,8 @@ impl Box {
pub fn paint_inline_background_border_if_applicable<E:ExtraDisplayListData>(
&self,
list: &RefCell<DisplayList<E>>,
index: uint,
lists: &RefCell<DisplayListCollection<E>>,
absolute_bounds: &Rect<Au>,
offset: &Point2D<Au>) {
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
@ -803,7 +804,7 @@ impl Box {
info.style.get().Background.background_color);
if !background_color.alpha.approx_eq(&0.0) {
list.with_mut(|list| {
lists.with_mut(|lists| {
let solid_color_display_item = ~SolidColorDisplayItem {
base: BaseDisplayItem {
bounds: bg_rect.clone(),
@ -812,7 +813,7 @@ impl Box {
color: background_color.to_gfx_color(),
};
list.append_item(SolidColorDisplayItemClass(solid_color_display_item))
lists.lists[index].append_item(SolidColorDisplayItemClass(solid_color_display_item))
});
}
let border = &info.border;
@ -834,7 +835,7 @@ impl Box {
let left_style = style.Border.border_left_style;
list.with_mut(|list| {
lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem {
bounds: bg_rect,
@ -851,7 +852,7 @@ impl Box {
left_style)
};
list.append_item(BorderDisplayItemClass(border_display_item))
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item))
});
bg_rect.origin.x = bg_rect.origin.x + border.left;
@ -865,7 +866,8 @@ impl Box {
/// necessary.
pub fn paint_background_if_applicable<E:ExtraDisplayListData>(
&self,
list: &RefCell<DisplayList<E>>,
index: uint,
lists: &RefCell<DisplayListCollection<E>>,
absolute_bounds: &Rect<Au>) {
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
// needed. We could use display list optimization to clean this up, but it still seems
@ -874,7 +876,7 @@ impl Box {
let style = self.style();
let background_color = style.resolve_color(style.Background.background_color);
if !background_color.alpha.approx_eq(&0.0) {
list.with_mut(|list| {
lists.with_mut(|lists| {
let solid_color_display_item = ~SolidColorDisplayItem {
base: BaseDisplayItem {
bounds: *absolute_bounds,
@ -883,8 +885,8 @@ impl Box {
color: background_color.to_gfx_color(),
};
list.append_item(SolidColorDisplayItemClass(solid_color_display_item))
})
lists.lists[index].append_item(SolidColorDisplayItemClass(solid_color_display_item))
});
}
}
@ -892,7 +894,8 @@ impl Box {
/// necessary.
pub fn paint_borders_if_applicable<E:ExtraDisplayListData>(
&self,
list: &RefCell<DisplayList<E>>,
index: uint,
lists: &RefCell<DisplayListCollection<E>>,
abs_bounds: &Rect<Au>) {
// Fast path.
let border = self.border.get();
@ -916,7 +919,7 @@ impl Box {
- self.noncontent_inline_right();
// Append the border to the display list.
list.with_mut(|list| {
lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem {
bounds: abs_bounds,
@ -933,7 +936,7 @@ impl Box {
left_style)
};
list.append_item(BorderDisplayItemClass(border_display_item))
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item))
});
}
@ -957,7 +960,8 @@ impl Box {
dirty: &Rect<Au>,
offset: Point2D<Au>,
flow: &Flow,
list: &RefCell<DisplayList<E>>) {
index: uint,
lists: &RefCell<DisplayListCollection<E>>) {
let box_bounds = self.position.get();
let absolute_box_bounds = box_bounds.translate(&offset);
debug!("Box::build_display_list at rel={}, abs={}: {:s}",
@ -975,14 +979,14 @@ impl Box {
return;
}
self.paint_inline_background_border_if_applicable(list, &absolute_box_bounds, &offset);
self.paint_inline_background_border_if_applicable(index, lists, &absolute_box_bounds, &offset);
// Add the background to the list, if applicable.
self.paint_background_if_applicable(list, &absolute_box_bounds);
self.paint_background_if_applicable(index, lists, &absolute_box_bounds);
match self.specific {
UnscannedTextBox(_) => fail!("Shouldn't see unscanned boxes here."),
ScannedTextBox(ref text_box) => {
list.with_mut(|list| {
lists.with_mut(|lists| {
let item = ~ClipDisplayItem {
base: BaseDisplayItem {
bounds: absolute_box_bounds,
@ -991,7 +995,7 @@ impl Box {
child_list: ~[],
need_clip: false
};
list.append_item(ClipDisplayItemClass(item));
lists.lists[index].append_item(ClipDisplayItemClass(item));
});
let text_color = self.style().Color.color.to_gfx_color();
@ -1022,7 +1026,7 @@ impl Box {
- self.noncontent_inline_right();
// Create the text box.
list.with_mut(|list| {
lists.with_mut(|lists| {
let text_display_item = ~TextDisplayItem {
base: BaseDisplayItem {
bounds: bounds,
@ -1037,7 +1041,7 @@ impl Box {
flags: text_flags,
};
list.append_item(TextDisplayItemClass(text_display_item))
lists.lists[index].append_item(TextDisplayItemClass(text_display_item));
});
// Draw debug frames for text bounds.
@ -1048,7 +1052,7 @@ impl Box {
// Compute the text box bounds and draw a border surrounding them.
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
list.with_mut(|list| {
lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem {
bounds: absolute_box_bounds,
@ -1059,7 +1063,7 @@ impl Box {
style: SideOffsets2D::new_all_same(border_style::solid)
};
list.append_item(BorderDisplayItemClass(border_display_item))
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item));
});
// Draw a rectangle representing the baselines.
@ -1070,7 +1074,7 @@ impl Box {
let baseline = Rect(absolute_box_bounds.origin + Point2D(Au(0), ascent),
Size2D(absolute_box_bounds.size.width, Au(0)));
list.with_mut(|list| {
lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem {
bounds: baseline,
@ -1081,12 +1085,12 @@ impl Box {
style: SideOffsets2D::new_all_same(border_style::dashed)
};
list.append_item(BorderDisplayItemClass(border_display_item))
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item));
});
});
},
GenericBox | IframeBox(..) => {
list.with_mut(|list| {
lists.with_mut(|lists| {
let item = ~ClipDisplayItem {
base: BaseDisplayItem {
bounds: absolute_box_bounds,
@ -1095,7 +1099,7 @@ impl Box {
child_list: ~[],
need_clip: self.needs_clip()
};
list.append_item(ClipDisplayItemClass(item));
lists.lists[index].append_item(ClipDisplayItemClass(item));
});
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
@ -1103,7 +1107,7 @@ impl Box {
debug!("{:?}", {
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
list.with_mut(|list| {
lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem {
bounds: absolute_box_bounds,
@ -1114,12 +1118,12 @@ impl Box {
style: SideOffsets2D::new_all_same(border_style::solid)
};
list.append_item(BorderDisplayItemClass(border_display_item))
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item));
});
});
},
ImageBox(ref image_box) => {
list.with_mut(|list| {
lists.with_mut(|lists| {
let item = ~ClipDisplayItem {
base: BaseDisplayItem {
bounds: absolute_box_bounds,
@ -1128,7 +1132,7 @@ impl Box {
child_list: ~[],
need_clip: false
};
list.append_item(ClipDisplayItemClass(item));
lists.lists[index].append_item(ClipDisplayItemClass(item));
});
let mut image_ref = image_box.image.borrow_mut();
@ -1146,7 +1150,7 @@ impl Box {
debug!("(building display list) building image box");
// Place the image into the display list.
list.with_mut(|list| {
lists.with_mut(|lists| {
let image_display_item = ~ImageDisplayItem {
base: BaseDisplayItem {
bounds: bounds,
@ -1154,7 +1158,7 @@ impl Box {
},
image: image.clone(),
};
list.append_item(ImageDisplayItemClass(image_display_item));
lists.lists[index].append_item(ImageDisplayItemClass(image_display_item));
});
}
None => {
@ -1169,7 +1173,7 @@ impl Box {
debug!("{:?}", {
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
list.with_mut(|list| {
lists.with_mut(|lists| {
let border_display_item = ~BorderDisplayItem {
base: BaseDisplayItem {
bounds: absolute_box_bounds,
@ -1180,7 +1184,7 @@ impl Box {
style: SideOffsets2D::new_all_same(border_style::solid)
};
list.append_item(BorderDisplayItemClass(border_display_item))
lists.lists[index].append_item(BorderDisplayItemClass(border_display_item))
});
});
@ -1207,7 +1211,8 @@ impl Box {
// Add a border, if applicable.
//
// TODO: Outlines.
self.paint_borders_if_applicable(list, &absolute_box_bounds);
self.paint_borders_if_applicable(index, lists, &absolute_box_bounds);
}
/// Returns the *minimum width* and *preferred width* of this box as defined by CSS 2.1.

View file

@ -41,7 +41,7 @@ use extra::dlist::{DList, DListIterator, MutDListIterator};
use extra::container::Deque;
use geom::point::Point2D;
use geom::rect::Rect;
use gfx::display_list::{ClipDisplayItemClass, DisplayList};
use gfx::display_list::{ClipDisplayItemClass, DisplayListCollection, DisplayList};
use layout::display_list_builder::ToGfxColor;
use gfx::color::Color;
use servo_util::geometry::Au;
@ -206,12 +206,13 @@ pub trait MutableFlowUtils {
/// Computes the overflow region for this flow.
fn store_overflow(self, _: &mut LayoutContext);
/// Builds a display list for this flow and its children.
fn build_display_list<E:ExtraDisplayListData>(
/// builds the display lists
fn build_display_lists<E:ExtraDisplayListData>(
self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
list: &RefCell<DisplayList<E>>)
index: uint,
mut list: &RefCell<DisplayListCollection<E>>)
-> bool;
}
@ -699,33 +700,37 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
mut_base(self).overflow = overflow
}
fn build_display_list<E:ExtraDisplayListData>(
fn build_display_lists<E:ExtraDisplayListData>(
self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
list: &RefCell<DisplayList<E>>)
mut index: uint,
lists: &RefCell<DisplayListCollection<E>>)
-> bool {
debug!("Flow: building display list for f{}", base(self).id);
match self.class() {
BlockFlowClass => self.as_block().build_display_list_block(builder, dirty, list),
InlineFlowClass => self.as_inline().build_display_list_inline(builder, dirty, list),
index = match self.class() {
BlockFlowClass => self.as_block().build_display_list_block(builder, dirty, index, lists),
InlineFlowClass => self.as_inline().build_display_list_inline(builder, dirty, index, lists),
};
if list.with_mut(|list| list.list.len() == 0) {
if lists.with_mut(|lists| lists.lists[index].list.len() == 0) {
return true;
}
let child_list = ~RefCell::new(DisplayList::new());
let mut child_lists = DisplayListCollection::new();
child_lists.add_list(DisplayList::new());
let child_lists = RefCell::new(child_lists);
for kid in child_iter(self) {
kid.build_display_list(builder,dirty,child_list);
kid.build_display_lists(builder, dirty, 0u, &child_lists);
}
let mut child_list = Some(child_list.unwrap());
list.with_mut(|list| {
let result = list.list.mut_rev_iter().position(|item| {
let mut child_lists = Some(child_lists.unwrap());
lists.with_mut(|lists| {
let mut child_lists = child_lists.take_unwrap();
let result = lists.lists[index].list.mut_rev_iter().position(|item| {
match *item {
ClipDisplayItemClass(ref mut item) => {
item.child_list.push_all_move(child_list.take_unwrap().list);
item.child_list.push_all_move(child_lists.lists.shift().list);
true
},
_ => false,
@ -736,6 +741,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
fail!("fail to find parent item");
}
lists.lists.push_all_move(child_lists.lists);
});
true
}

View file

@ -16,7 +16,7 @@ use layout::float_context::{PlacementInfo, FloatLeft};
use extra::container::Deque;
use extra::ringbuf::RingBuf;
use geom::{Point2D, Rect, Size2D};
use gfx::display_list::DisplayList;
use gfx::display_list::DisplayListCollection;
use servo_util::geometry::Au;
use servo_util::range::Range;
use std::cell::RefCell;
@ -495,11 +495,12 @@ impl InlineFlow {
&self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
list: &RefCell<DisplayList<E>>)
-> bool {
index: uint,
lists: &RefCell<DisplayListCollection<E>>)
-> uint {
let abs_rect = Rect(self.base.abs_position, self.base.position.size);
if !abs_rect.intersects(dirty) {
return true;
return index;
}
// TODO(#228): Once we form line boxes and have their cached bounds, we can be smarter and
@ -509,14 +510,14 @@ impl InlineFlow {
self.boxes.len());
for box_ in self.boxes.iter() {
box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list)
box_.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, index, lists);
}
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
// should the flow be nested inside the box somehow?
// For now, don't traverse the subtree rooted here
true
index
}
/// Returns the relative offset from the baseline for this box, taking into account the value

View file

@ -25,7 +25,8 @@ use layout::wrapper::LayoutNode;
use extra::arc::{Arc, MutexArc};
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::{ClipDisplayItemClass, DisplayItem, DisplayItemIterator, DisplayList};
use gfx::display_list::{ClipDisplayItemClass, DisplayItem, DisplayItemIterator};
use gfx::display_list::{DisplayList, DisplayListCollection};
use gfx::font_context::FontContextInfo;
use gfx::opts::Opts;
use gfx::render_task::{RenderMsg, RenderChan, RenderLayer};
@ -89,7 +90,7 @@ pub struct LayoutTask {
screen_size: Size2D<Au>,
/// A cached display list.
display_list: Option<Arc<DisplayList<OpaqueNode>>>,
display_list_collection: Option<Arc<DisplayListCollection<OpaqueNode>>>,
stylist: ~Stylist,
@ -273,7 +274,7 @@ impl LayoutTask {
screen_size: screen_size,
leaf_set: MutexArc::new(LeafSet::new()),
display_list: None,
display_list_collection: None,
stylist: ~new_stylist(),
parallel_traversal: parallel_traversal,
profiler_chan: profiler_chan,
@ -575,14 +576,16 @@ impl LayoutTask {
if data.goal == ReflowForDisplay {
profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone(), || {
let root_size = flow::base(layout_root).position.size;
let display_list = ~RefCell::new(DisplayList::<OpaqueNode>::new());
let mut display_list_collection = DisplayListCollection::new();
display_list_collection.add_list(DisplayList::<OpaqueNode>::new());
let display_list_collection = ~RefCell::new(display_list_collection);
let dirty = flow::base(layout_root).position.clone();
let display_list_builder = DisplayListBuilder {
ctx: &layout_ctx,
};
layout_root.build_display_list(&display_list_builder, &dirty, display_list);
layout_root.build_display_lists(&display_list_builder, &dirty, 0u, display_list_collection);
let display_list = Arc::new(display_list.unwrap());
let display_list_collection = Arc::new(display_list_collection.unwrap());
let mut color = color::rgba(255.0, 255.0, 255.0, 255.0);
@ -607,13 +610,13 @@ impl LayoutTask {
}
let render_layer = RenderLayer {
display_list: display_list.clone(),
display_list_collection: display_list_collection.clone(),
size: Size2D(root_size.width.to_nearest_px() as uint,
root_size.height.to_nearest_px() as uint),
color: color
};
self.display_list = Some(display_list.clone());
self.display_list_collection = Some(display_list_collection.clone());
debug!("Layout done!");
@ -656,8 +659,9 @@ impl LayoutTask {
}
let mut rect = None;
let display_list = self.display_list.as_ref().unwrap().get();
union_boxes_for_node(&mut rect, display_list.iter(), node);
for display_list in self.display_list_collection.as_ref().unwrap().get().iter() {
union_boxes_for_node(&mut rect, display_list.iter(), node);
}
reply_chan.send(ContentBoxResponse(rect.unwrap_or(Au::zero_rect())))
}
ContentBoxesQuery(node, reply_chan) => {
@ -676,8 +680,9 @@ impl LayoutTask {
}
let mut boxes = ~[];
let display_list = self.display_list.as_ref().unwrap().get();
add_boxes_for_node(&mut boxes, display_list.iter(), node);
for display_list in self.display_list_collection.as_ref().unwrap().get().iter() {
add_boxes_for_node(&mut boxes, display_list.iter(), node);
}
reply_chan.send(ContentBoxesResponse(boxes))
}
HitTestQuery(_, point, reply_chan) => {
@ -717,27 +722,17 @@ impl LayoutTask {
let ret: Option<HitTestResponse> = None;
ret
}
let response = {
match self.display_list {
Some(ref list) => {
let display_list = list.get();
let (x, y) = (Au::from_frac_px(point.x as f64),
Au::from_frac_px(point.y as f64));
let resp = hit_test(x,y,display_list.list);
if resp.is_none() {
Err(())
} else {
Ok(resp.unwrap())
}
}
None => {
error!("Can't hit test: no display list");
Err(())
},
for display_list in self.display_list_collection.as_ref().unwrap().get().lists.rev_iter() {
let (x, y) = (Au::from_frac_px(point.x as f64),
Au::from_frac_px(point.y as f64));
let resp = hit_test(x,y,display_list.list);
if resp.is_some() {
reply_chan.send(Ok(resp.unwrap()));
return
}
};
}
reply_chan.send(Err(()));
reply_chan.send(response)
}
}
}