diff options
-rw-r--r-- | components/layout/layout_task.rs | 304 | ||||
-rw-r--r-- | components/layout/lib.rs | 1 | ||||
-rw-r--r-- | components/layout/query.rs | 309 |
3 files changed, 320 insertions, 294 deletions
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index e9a644105b2..e01f6b950e9 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -20,6 +20,8 @@ use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAI use layout_debug; use opaque_node::OpaqueNodeMethods; use parallel::{self, WorkQueueData}; +use query::{LayoutRPCImpl, process_content_box_request, process_content_boxes_request, MarginPadding, Side}; +use query::{MarginRetrievingFragmentBorderBoxIterator, PositionProperty, PositionRetrievingFragmentBorderBoxIterator}; use sequential; use wrapper::LayoutNode; @@ -34,7 +36,7 @@ use euclid::rect::Rect; use euclid::scale_factor::ScaleFactor; use euclid::size::Size2D; use gfx_traits::color; -use gfx::display_list::{ClippingRegion, DisplayItemMetadata, DisplayList, OpaqueNode}; +use gfx::display_list::{ClippingRegion, DisplayList, OpaqueNode}; use gfx::display_list::StackingContext; use gfx::font_cache_task::FontCacheTask; use gfx::paint_task::{LayoutToPaintMsg, PaintLayer}; @@ -52,10 +54,10 @@ use net_traits::{load_bytes_iter, PendingAsyncLoad}; use net_traits::image_cache_task::{ImageCacheTask, ImageCacheResult, ImageCacheChan}; use script::dom::bindings::js::LayoutJS; use script::dom::node::{LayoutData, Node}; -use script::layout_interface::{Animation, ContentBoxResponse, ContentBoxesResponse, NodeGeometryResponse}; -use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC, MouseOverResponse, OffsetParentResponse}; +use script::layout_interface::Animation; +use script::layout_interface::{LayoutChan, LayoutRPC, OffsetParentResponse}; use script::layout_interface::{NewLayoutTaskInfo, Msg, Reflow, ReflowGoal, ReflowQueryType}; -use script::layout_interface::{ResolvedStyleResponse, ScriptLayoutChan, ScriptReflow, TrustedNodeAddress}; +use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress}; use script_traits::{ConstellationControlMsg, LayoutControlMsg, OpaqueScriptLayoutChannel}; use script_traits::{ScriptControlChan, StylesheetLoadResponder}; use selectors::parser::PseudoElement; @@ -76,10 +78,9 @@ use style::properties::longhands::{display, position}; use style::selector_matching::Stylist; use style::stylesheets::{Origin, Stylesheet, CSSRuleIteratorExt}; use url::Url; -use util::cursor::Cursor; use util::geometry::{Au, MAX_RECT, ZERO_POINT}; use util::ipc::OptionalIpcSender; -use util::logical_geometry::{LogicalPoint, WritingMode}; +use util::logical_geometry::LogicalPoint; use util::mem::HeapSizeOf; use util::opts; use util::task::spawn_named_with_send_on_failure; @@ -284,7 +285,7 @@ impl LayoutTaskFactory for LayoutTask { /// The `LayoutTask` `rw_data` lock must remain locked until the first reflow, /// as RPC calls don't make sense until then. Use this in combination with /// `LayoutTask::lock_rw_data` and `LayoutTask::return_rw_data`. -enum RWGuard<'a> { +pub enum RWGuard<'a> { /// If the lock was previously held, from when the task started. Held(MutexGuard<'a, LayoutTaskData>), /// If the lock was just used, and has been returned since there has been @@ -846,33 +847,6 @@ impl LayoutTask { fn verify_flow_tree(&self, _: &mut FlowRef) { } - fn process_content_box_request<'a>(&'a self, - requested_node: TrustedNodeAddress, - layout_root: &mut FlowRef, - rw_data: &mut RWGuard<'a>) { - // FIXME(pcwalton): This has not been updated to handle the stacking context relative - // stuff. So the position is wrong in most cases. - let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); - let mut iterator = UnioningFragmentBorderBoxIterator::new(requested_node); - sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); - rw_data.content_box_response = match iterator.rect { - Some(rect) => rect, - None => Rect::zero() - }; - } - - fn process_content_boxes_request<'a>(&'a self, - requested_node: TrustedNodeAddress, - layout_root: &mut FlowRef, - rw_data: &mut RWGuard<'a>) { - // FIXME(pcwalton): This has not been updated to handle the stacking context relative - // stuff. So the position is wrong in most cases. - let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); - let mut iterator = CollectingFragmentBorderBoxIterator::new(requested_node); - sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); - rw_data.content_boxes_response = iterator.rects; - } - fn process_node_geometry_request<'a>(&'a self, requested_node: TrustedNodeAddress, layout_root: &mut FlowRef, @@ -1218,9 +1192,9 @@ impl LayoutTask { let mut root_flow = (*rw_data.root_flow.as_ref().unwrap()).clone(); match data.query_type { ReflowQueryType::ContentBoxQuery(node) => - self.process_content_box_request(node, &mut root_flow, &mut rw_data), + process_content_box_request(node, &mut root_flow, &mut rw_data), ReflowQueryType::ContentBoxesQuery(node) => - self.process_content_boxes_request(node, &mut root_flow, &mut rw_data), + process_content_boxes_request(node, &mut root_flow, &mut rw_data), ReflowQueryType::NodeGeometryQuery(node) => self.process_node_geometry_request(node, &mut root_flow, &mut rw_data), ReflowQueryType::ResolvedStyleQuery(node, ref pseudo, ref property) => @@ -1452,162 +1426,6 @@ impl LayoutTask { } } -struct LayoutRPCImpl(Arc<Mutex<LayoutTaskData>>); - -impl LayoutRPC for LayoutRPCImpl { - // The neat thing here is that in order to answer the following two queries we only - // need to compare nodes for equality. Thus we can safely work only with `OpaqueNode`. - fn content_box(&self) -> ContentBoxResponse { - let &LayoutRPCImpl(ref rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - ContentBoxResponse(rw_data.content_box_response) - } - - /// Requests the dimensions of all the content boxes, as in the `getClientRects()` call. - fn content_boxes(&self) -> ContentBoxesResponse { - let &LayoutRPCImpl(ref rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - ContentBoxesResponse(rw_data.content_boxes_response.clone()) - } - - fn node_geometry(&self) -> NodeGeometryResponse { - let &LayoutRPCImpl(ref rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - NodeGeometryResponse { - client_rect: rw_data.client_rect_response - } - } - - /// Retrieves the resolved value for a CSS style property. - fn resolved_style(&self) -> ResolvedStyleResponse { - let &LayoutRPCImpl(ref rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - ResolvedStyleResponse(rw_data.resolved_style_response.clone()) - } - - /// Requests the node containing the point of interest. - fn hit_test(&self, _: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()> { - let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y)); - let resp = { - let &LayoutRPCImpl(ref rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - match rw_data.stacking_context { - None => panic!("no root stacking context!"), - Some(ref stacking_context) => { - let mut result = Vec::new(); - stacking_context.hit_test(point, &mut result, true); - if !result.is_empty() { - Some(HitTestResponse(result[0].node.to_untrusted_node_address())) - } else { - None - } - } - } - }; - - if resp.is_some() { - return Ok(resp.unwrap()); - } - Err(()) - } - - fn mouse_over(&self, _: TrustedNodeAddress, point: Point2D<f32>) - -> Result<MouseOverResponse, ()> { - let mut mouse_over_list: Vec<DisplayItemMetadata> = vec!(); - let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y)); - { - let &LayoutRPCImpl(ref rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - match rw_data.stacking_context { - None => panic!("no root stacking context!"), - Some(ref stacking_context) => { - stacking_context.hit_test(point, &mut mouse_over_list, false); - } - } - - // Compute the new cursor. - let cursor = if !mouse_over_list.is_empty() { - mouse_over_list[0].pointing.unwrap() - } else { - Cursor::DefaultCursor - }; - let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan; - constellation_chan.send(ConstellationMsg::SetCursor(cursor)).unwrap(); - } - - if mouse_over_list.is_empty() { - Err(()) - } else { - let response_list = - mouse_over_list.iter() - .map(|metadata| metadata.node.to_untrusted_node_address()) - .collect(); - Ok(MouseOverResponse(response_list)) - } - } - - fn offset_parent(&self) -> OffsetParentResponse { - let &LayoutRPCImpl(ref rw_data) = self; - let rw_data = rw_data.lock().unwrap(); - rw_data.offset_parent_response.clone() - } -} - -struct UnioningFragmentBorderBoxIterator { - node_address: OpaqueNode, - rect: Option<Rect<Au>>, -} - -impl UnioningFragmentBorderBoxIterator { - fn new(node_address: OpaqueNode) -> UnioningFragmentBorderBoxIterator { - UnioningFragmentBorderBoxIterator { - node_address: node_address, - rect: None - } - } -} - -impl FragmentBorderBoxIterator for UnioningFragmentBorderBoxIterator { - fn process(&mut self, _: &Fragment, _: i32, border_box: &Rect<Au>) { - self.rect = match self.rect { - Some(rect) => { - Some(rect.union(border_box)) - } - None => { - Some(*border_box) - } - }; - } - - fn should_process(&mut self, fragment: &Fragment) -> bool { - fragment.contains_node(self.node_address) - } -} - -struct CollectingFragmentBorderBoxIterator { - node_address: OpaqueNode, - rects: Vec<Rect<Au>>, -} - -impl CollectingFragmentBorderBoxIterator { - fn new(node_address: OpaqueNode) -> CollectingFragmentBorderBoxIterator { - CollectingFragmentBorderBoxIterator { - node_address: node_address, - rects: Vec::new(), - } - } -} - -impl FragmentBorderBoxIterator for CollectingFragmentBorderBoxIterator { - fn process(&mut self, _: &Fragment, _: i32, border_box: &Rect<Au>) { - self.rects.push(*border_box); - } - - fn should_process(&mut self, fragment: &Fragment) -> bool { - fragment.contains_node(self.node_address) - } -} - struct FragmentLocatingFragmentIterator { node_address: OpaqueNode, client_rect: Rect<i32>, @@ -1667,108 +1485,6 @@ impl FragmentBorderBoxIterator for FragmentLocatingFragmentIterator { } } -enum Side { - Left, - Right, - Bottom, - Top -} - -enum MarginPadding { - Margin, - Padding -} - -enum PositionProperty { - Left, - Right, - Top, - Bottom, - Width, - Height, -} - -struct PositionRetrievingFragmentBorderBoxIterator { - node_address: OpaqueNode, - result: Option<Au>, - position: Point2D<Au>, - property: PositionProperty, -} - -impl PositionRetrievingFragmentBorderBoxIterator { - fn new(node_address: OpaqueNode, - property: PositionProperty, - position: Point2D<Au>) -> PositionRetrievingFragmentBorderBoxIterator { - PositionRetrievingFragmentBorderBoxIterator { - node_address: node_address, - position: position, - property: property, - result: None, - } - } -} - -impl FragmentBorderBoxIterator for PositionRetrievingFragmentBorderBoxIterator { - fn process(&mut self, _: &Fragment, _: i32, border_box: &Rect<Au>) { - self.result = - Some(match self.property { - PositionProperty::Left => self.position.x, - PositionProperty::Top => self.position.y, - PositionProperty::Width => border_box.size.width, - PositionProperty::Height => border_box.size.height, - // TODO: the following 2 calculations are completely wrong. - // They should return the difference between the parent's and this - // fragment's border boxes. - PositionProperty::Right => border_box.max_x() + self.position.x, - PositionProperty::Bottom => border_box.max_y() + self.position.y, - }); - } - - fn should_process(&mut self, fragment: &Fragment) -> bool { - fragment.contains_node(self.node_address) - } -} - -struct MarginRetrievingFragmentBorderBoxIterator { - node_address: OpaqueNode, - result: Option<Au>, - writing_mode: WritingMode, - margin_padding: MarginPadding, - side: Side, -} - -impl MarginRetrievingFragmentBorderBoxIterator { - fn new(node_address: OpaqueNode, side: Side, margin_padding: - MarginPadding, writing_mode: WritingMode) -> MarginRetrievingFragmentBorderBoxIterator { - MarginRetrievingFragmentBorderBoxIterator { - node_address: node_address, - side: side, - margin_padding: margin_padding, - result: None, - writing_mode: writing_mode, - } - } -} - -impl FragmentBorderBoxIterator for MarginRetrievingFragmentBorderBoxIterator { - fn process(&mut self, fragment: &Fragment, _: i32, _: &Rect<Au>) { - let rect = match self.margin_padding { - MarginPadding::Margin => &fragment.margin, - MarginPadding::Padding => &fragment.border_padding - }; - self.result = Some(match self.side { - Side::Left => rect.left(self.writing_mode), - Side::Right => rect.right(self.writing_mode), - Side::Bottom => rect.bottom(self.writing_mode), - Side::Top => rect.top(self.writing_mode) - }); - } - - fn should_process(&mut self, fragment: &Fragment) -> bool { - fragment.contains_node(self.node_address) - } -} - // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface impl FragmentBorderBoxIterator for ParentOffsetBorderBoxIterator { fn process(&mut self, fragment: &Fragment, level: i32, border_box: &Rect<Au>) { diff --git a/components/layout/lib.rs b/components/layout/lib.rs index c68e5f300cd..5d70db2fc6d 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -85,6 +85,7 @@ pub mod model; pub mod multicol; pub mod opaque_node; pub mod parallel; +pub mod query; pub mod sequential; pub mod table_wrapper; pub mod table; diff --git a/components/layout/query.rs b/components/layout/query.rs new file mode 100644 index 00000000000..01f1c6065b5 --- /dev/null +++ b/components/layout/query.rs @@ -0,0 +1,309 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Utilities for querying the layout, as needed by the layout task. + +use layout_task::{LayoutTaskData, RWGuard}; + +use euclid::point::Point2D; +use euclid::rect::Rect; +use flow_ref::FlowRef; +use fragment::{Fragment, FragmentBorderBoxIterator}; +use gfx::display_list::{DisplayItemMetadata, OpaqueNode}; +use msg::constellation_msg::Msg as ConstellationMsg; +use msg::constellation_msg::ConstellationChan; +use opaque_node::OpaqueNodeMethods; +use script::layout_interface::{ContentBoxResponse, ContentBoxesResponse, NodeGeometryResponse}; +use script::layout_interface::{HitTestResponse, LayoutRPC, MouseOverResponse, OffsetParentResponse}; +use script::layout_interface::{ResolvedStyleResponse, ScriptLayoutChan, TrustedNodeAddress}; +use sequential; + +use std::sync::{Arc, Mutex}; +use util::geometry::Au; +use util::cursor::Cursor; +use util::logical_geometry::WritingMode; + +pub struct LayoutRPCImpl(pub Arc<Mutex<LayoutTaskData>>); + +impl LayoutRPC for LayoutRPCImpl { + + // The neat thing here is that in order to answer the following two queries we only + // need to compare nodes for equality. Thus we can safely work only with `OpaqueNode`. + fn content_box(&self) -> ContentBoxResponse { + let &LayoutRPCImpl(ref rw_data) = self; + let rw_data = rw_data.lock().unwrap(); + ContentBoxResponse(rw_data.content_box_response) + } + + /// Requests the dimensions of all the content boxes, as in the `getClientRects()` call. + fn content_boxes(&self) -> ContentBoxesResponse { + let &LayoutRPCImpl(ref rw_data) = self; + let rw_data = rw_data.lock().unwrap(); + ContentBoxesResponse(rw_data.content_boxes_response.clone()) + } + + fn node_geometry(&self) -> NodeGeometryResponse { + let &LayoutRPCImpl(ref rw_data) = self; + let rw_data = rw_data.lock().unwrap(); + NodeGeometryResponse { + client_rect: rw_data.client_rect_response + } + } + + /// Retrieves the resolved value for a CSS style property. + fn resolved_style(&self) -> ResolvedStyleResponse { + let &LayoutRPCImpl(ref rw_data) = self; + let rw_data = rw_data.lock().unwrap(); + ResolvedStyleResponse(rw_data.resolved_style_response.clone()) + } + + /// Requests the node containing the point of interest. + fn hit_test(&self, _: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()> { + let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y)); + let resp = { + let &LayoutRPCImpl(ref rw_data) = self; + let rw_data = rw_data.lock().unwrap(); + match rw_data.stacking_context { + None => panic!("no root stacking context!"), + Some(ref stacking_context) => { + let mut result = Vec::new(); + stacking_context.hit_test(point, &mut result, true); + if !result.is_empty() { + Some(HitTestResponse(result[0].node.to_untrusted_node_address())) + } else { + None + } + } + } + }; + + if resp.is_some() { + return Ok(resp.unwrap()); + } + Err(()) + } + + fn mouse_over(&self, _: TrustedNodeAddress, point: Point2D<f32>) + -> Result<MouseOverResponse, ()> { + let mut mouse_over_list: Vec<DisplayItemMetadata> = vec!(); + let point = Point2D::new(Au::from_f32_px(point.x), Au::from_f32_px(point.y)); + { + let &LayoutRPCImpl(ref rw_data) = self; + let rw_data = rw_data.lock().unwrap(); + match rw_data.stacking_context { + None => panic!("no root stacking context!"), + Some(ref stacking_context) => { + stacking_context.hit_test(point, &mut mouse_over_list, false); + } + } + + // Compute the new cursor. + let cursor = if !mouse_over_list.is_empty() { + mouse_over_list[0].pointing.unwrap() + } else { + Cursor::DefaultCursor + }; + let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan; + constellation_chan.send(ConstellationMsg::SetCursor(cursor)).unwrap(); + } + + if mouse_over_list.is_empty() { + Err(()) + } else { + let response_list = + mouse_over_list.iter() + .map(|metadata| metadata.node.to_untrusted_node_address()) + .collect(); + Ok(MouseOverResponse(response_list)) + } + } + + fn offset_parent(&self) -> OffsetParentResponse { + let &LayoutRPCImpl(ref rw_data) = self; + let rw_data = rw_data.lock().unwrap(); + rw_data.offset_parent_response.clone() + } +} + +pub struct UnioningFragmentBorderBoxIterator { + pub node_address: OpaqueNode, + pub rect: Option<Rect<Au>>, +} + +impl UnioningFragmentBorderBoxIterator { + pub fn new(node_address: OpaqueNode) -> UnioningFragmentBorderBoxIterator { + UnioningFragmentBorderBoxIterator { + node_address: node_address, + rect: None + } + } +} + +impl FragmentBorderBoxIterator for UnioningFragmentBorderBoxIterator { + fn process(&mut self, _: &Fragment, _: i32, border_box: &Rect<Au>) { + self.rect = match self.rect { + Some(rect) => { + Some(rect.union(border_box)) + } + None => { + Some(*border_box) + } + }; + } + + fn should_process(&mut self, fragment: &Fragment) -> bool { + fragment.contains_node(self.node_address) + } +} + +pub struct CollectingFragmentBorderBoxIterator { + pub node_address: OpaqueNode, + pub rects: Vec<Rect<Au>>, +} + +impl CollectingFragmentBorderBoxIterator { + pub fn new(node_address: OpaqueNode) -> CollectingFragmentBorderBoxIterator { + CollectingFragmentBorderBoxIterator { + node_address: node_address, + rects: Vec::new(), + } + } +} + +impl FragmentBorderBoxIterator for CollectingFragmentBorderBoxIterator { + fn process(&mut self, _: &Fragment, _: i32, border_box: &Rect<Au>) { + self.rects.push(*border_box); + } + + fn should_process(&mut self, fragment: &Fragment) -> bool { + fragment.contains_node(self.node_address) + } +} + +pub enum Side { + Left, + Right, + Bottom, + Top +} + +pub enum MarginPadding { + Margin, + Padding +} + +pub enum PositionProperty { + Left, + Right, + Top, + Bottom, + Width, + Height, +} + +pub struct PositionRetrievingFragmentBorderBoxIterator { + node_address: OpaqueNode, + pub result: Option<Au>, + position: Point2D<Au>, + property: PositionProperty, +} + +impl PositionRetrievingFragmentBorderBoxIterator { + pub fn new(node_address: OpaqueNode, + property: PositionProperty, + position: Point2D<Au>) -> PositionRetrievingFragmentBorderBoxIterator { + PositionRetrievingFragmentBorderBoxIterator { + node_address: node_address, + position: position, + property: property, + result: None, + } + } +} + +impl FragmentBorderBoxIterator for PositionRetrievingFragmentBorderBoxIterator { + fn process(&mut self, _: &Fragment, _: i32, border_box: &Rect<Au>) { + self.result = + Some(match self.property { + PositionProperty::Left => self.position.x, + PositionProperty::Top => self.position.y, + PositionProperty::Width => border_box.size.width, + PositionProperty::Height => border_box.size.height, + // TODO: the following 2 calculations are completely wrong. + // They should return the difference between the parent's and this + // fragment's border boxes. + PositionProperty::Right => border_box.max_x() + self.position.x, + PositionProperty::Bottom => border_box.max_y() + self.position.y, + }); + } + + fn should_process(&mut self, fragment: &Fragment) -> bool { + fragment.contains_node(self.node_address) + } +} + +pub struct MarginRetrievingFragmentBorderBoxIterator { + node_address: OpaqueNode, + pub result: Option<Au>, + writing_mode: WritingMode, + margin_padding: MarginPadding, + side: Side, +} + +impl MarginRetrievingFragmentBorderBoxIterator { + pub fn new(node_address: OpaqueNode, side: Side, margin_padding: + MarginPadding, writing_mode: WritingMode) -> MarginRetrievingFragmentBorderBoxIterator { + MarginRetrievingFragmentBorderBoxIterator { + node_address: node_address, + side: side, + margin_padding: margin_padding, + result: None, + writing_mode: writing_mode, + } + } +} + +impl FragmentBorderBoxIterator for MarginRetrievingFragmentBorderBoxIterator { + fn process(&mut self, fragment: &Fragment, _: i32, _: &Rect<Au>) { + let rect = match self.margin_padding { + MarginPadding::Margin => &fragment.margin, + MarginPadding::Padding => &fragment.border_padding + }; + self.result = Some(match self.side { + Side::Left => rect.left(self.writing_mode), + Side::Right => rect.right(self.writing_mode), + Side::Bottom => rect.bottom(self.writing_mode), + Side::Top => rect.top(self.writing_mode) + }); + } + + fn should_process(&mut self, fragment: &Fragment) -> bool { + fragment.contains_node(self.node_address) + } +} + +pub fn process_content_box_request<'a>(requested_node: TrustedNodeAddress, + layout_root: &mut FlowRef, + rw_data: &mut RWGuard<'a>) { + // FIXME(pcwalton): This has not been updated to handle the stacking context relative + // stuff. So the position is wrong in most cases. + let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); + let mut iterator = UnioningFragmentBorderBoxIterator::new(requested_node); + sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); + rw_data.content_box_response = match iterator.rect { + Some(rect) => rect, + None => Rect::zero() + }; +} + +pub fn process_content_boxes_request<'a>(requested_node: TrustedNodeAddress, + layout_root: &mut FlowRef, + rw_data: &mut RWGuard<'a>) { + // FIXME(pcwalton): This has not been updated to handle the stacking context relative + // stuff. So the position is wrong in most cases. + let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); + let mut iterator = CollectingFragmentBorderBoxIterator::new(requested_node); + sequential::iterate_through_flow_tree_fragment_border_boxes(layout_root, &mut iterator); + rw_data.content_boxes_response = iterator.rects; +} |