diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2014-10-10 15:13:12 -0700 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2014-10-13 21:40:36 -0700 |
commit | bffaad118e2e73c3fbeee4a160f2b0d7d3ff4952 (patch) | |
tree | 061604ce620c43fbbf80d6937a07ecc82e021fc3 /components/layout/layout_task.rs | |
parent | f350879574194bb612eac88e21d0920e9827afa7 (diff) | |
download | servo-bffaad118e2e73c3fbeee4a160f2b0d7d3ff4952.tar.gz servo-bffaad118e2e73c3fbeee4a160f2b0d7d3ff4952.zip |
layout: Rewrite clipping to be per-display-item instead of having
a separate `ClipDisplayItem`.
We push down clipping areas during absolute position calculation. This
makes display items into a flat list, improving cache locality. It
dramatically simplifies the code all around.
Because we need to push down clip rects even for absolutely-positioned
children of non-absolutely-positioned flows, this patch alters the
parallel traversal to compute absolute positions for
absolutely-positioned children at the same time it computes absolute
positions for other children. This doesn't seem to break anything either
in theory (since the overall order remains correct) or in practice. It
simplifies the parallel traversal code quite a bit.
See the relevant Gecko bug:
https://bugzilla.mozilla.org/show_bug.cgi?id=615734
Diffstat (limited to 'components/layout/layout_task.rs')
-rw-r--r-- | components/layout/layout_task.rs | 90 |
1 files changed, 23 insertions, 67 deletions
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 22068ae460b..03ea97d8583 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -26,8 +26,8 @@ use encoding::all::UTF_8; use geom::point::Point2D; use geom::rect::Rect; use geom::size::Size2D; -use gfx::display_list::{ClipDisplayItemClass, ContentStackingLevel, DisplayItem}; -use gfx::display_list::{DisplayItemIterator, DisplayList, OpaqueNode}; +use gfx::display_list::{ContentStackingLevel, DisplayItem, DisplayItemIterator, DisplayList}; +use gfx::display_list::{OpaqueNode}; use gfx::render_task::{RenderInitMsg, RenderChan, RenderLayer}; use gfx::{render_task, color}; use layout_traits; @@ -852,7 +852,6 @@ impl LayoutRPC for LayoutRPCImpl { mut iter: DisplayItemIterator, node: OpaqueNode) { for item in iter { - union_boxes_for_node(accumulator, item.children(), node); if item.base().node == node { match *accumulator { None => *accumulator = Some(item.base().bounds), @@ -884,7 +883,6 @@ impl LayoutRPC for LayoutRPCImpl { mut iter: DisplayItemIterator, node: OpaqueNode) { for item in iter { - add_boxes_for_node(accumulator, item.children(), node); if item.base().node == node { accumulator.push(item.base().bounds) } @@ -907,47 +905,25 @@ impl LayoutRPC for LayoutRPCImpl { /// Requests the node containing the point of interest fn hit_test(&self, _: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()> { - fn hit_test<'a,I:Iterator<&'a DisplayItem>>(x: Au, y: Au, mut iterator: I) - -> Option<HitTestResponse> { + fn hit_test<'a,I>(point: Point2D<Au>, mut iterator: I) + -> Option<HitTestResponse> + where I: Iterator<&'a DisplayItem> { for item in iterator { - match *item { - ClipDisplayItemClass(ref cc) => { - if geometry::rect_contains_point(cc.base.bounds, Point2D(x, y)) { - let ret = hit_test(x, y, cc.children.list.iter().rev()); - if !ret.is_none() { - return ret - } - } - continue - } - _ => {} - } - - let bounds = item.bounds(); - - // TODO(tikue): This check should really be performed by a method of - // DisplayItem. - if x < bounds.origin.x + bounds.size.width && - bounds.origin.x <= x && - y < bounds.origin.y + bounds.size.height && - bounds.origin.y <= y { - return Some(HitTestResponse(item.base() - .node - .to_untrusted_node_address())) + // TODO(tikue): This check should really be performed by a method of `DisplayItem`. + if geometry::rect_contains_point(item.base().clip_rect, point) && + geometry::rect_contains_point(item.bounds(), point) { + return Some(HitTestResponse(item.base().node.to_untrusted_node_address())) } } - let ret: Option<HitTestResponse> = None; - ret + None } - let (x, y) = (Au::from_frac_px(point.x as f64), - Au::from_frac_px(point.y as f64)); - + let point = Point2D(Au::from_frac_px(point.x as f64), Au::from_frac_px(point.y as f64)); let resp = { let &LayoutRPCImpl(ref rw_data) = self; let rw_data = rw_data.lock(); match rw_data.display_list { None => fail!("no display list!"), - Some(ref display_list) => hit_test(x, y, display_list.list.iter().rev()), + Some(ref display_list) => hit_test(point, display_list.list.iter().rev()), } }; @@ -957,49 +933,29 @@ impl LayoutRPC for LayoutRPCImpl { Err(()) } - fn mouse_over(&self, _: TrustedNodeAddress, point: Point2D<f32>) -> Result<MouseOverResponse, ()> { - fn mouse_over_test<'a, - I:Iterator<&'a DisplayItem>>( - x: Au, - y: Au, - mut iterator: I, - result: &mut Vec<UntrustedNodeAddress>) { + fn mouse_over(&self, _: TrustedNodeAddress, point: Point2D<f32>) + -> Result<MouseOverResponse, ()> { + fn mouse_over_test<'a,I>(point: Point2D<Au>, + mut iterator: I, + result: &mut Vec<UntrustedNodeAddress>) + where I: Iterator<&'a DisplayItem> { for item in iterator { - match *item { - ClipDisplayItemClass(ref cc) => { - mouse_over_test(x, y, cc.children.list.iter().rev(), result); - } - _ => { - let bounds = item.bounds(); - - // TODO(tikue): This check should really be performed by a method - // of DisplayItem. - if x < bounds.origin.x + bounds.size.width && - bounds.origin.x <= x && - y < bounds.origin.y + bounds.size.height && - bounds.origin.y <= y { - result.push(item.base() - .node - .to_untrusted_node_address()); - } - } + // TODO(tikue): This check should really be performed by a method of `DisplayItem`. + if geometry::rect_contains_point(item.bounds(), point) { + result.push(item.base().node.to_untrusted_node_address()) } } } let mut mouse_over_list: Vec<UntrustedNodeAddress> = vec!(); - let (x, y) = (Au::from_frac_px(point.x as f64), Au::from_frac_px(point.y as f64)); - + let point = Point2D(Au::from_frac_px(point.x as f64), Au::from_frac_px(point.y as f64)); { let &LayoutRPCImpl(ref rw_data) = self; let rw_data = rw_data.lock(); match rw_data.display_list { None => fail!("no display list!"), Some(ref display_list) => { - mouse_over_test(x, - y, - display_list.list.iter().rev(), - &mut mouse_over_list); + mouse_over_test(point, display_list.list.iter().rev(), &mut mouse_over_list); } }; } |