aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/layout_task.rs304
-rw-r--r--components/layout/lib.rs1
-rw-r--r--components/layout/query.rs309
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;
+}