diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/main/layout/block.rs | 94 | ||||
-rw-r--r-- | src/components/main/layout/box.rs | 105 | ||||
-rw-r--r-- | src/components/main/layout/float.rs | 47 | ||||
-rw-r--r-- | src/components/main/layout/inline.rs | 8 | ||||
-rw-r--r-- | src/components/main/layout/model.rs | 70 |
5 files changed, 150 insertions, 174 deletions
diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index 0e36591218c..24565896ff7 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -127,12 +127,10 @@ impl BlockFlow { } }; - let mut model_ref = base.model.mutate(); - let model = &mut model_ref.ptr; - top_offset = clearance + model.margin.top + model.border.top + model.padding.top; + top_offset = clearance + base.margin.top + base.border.top + base.padding.top; cur_y = cur_y + top_offset; - bottom_offset = model.margin.bottom + model.border.bottom + model.padding.bottom; - left_offset = model.offset(); + bottom_offset = base.margin.bottom + base.border.bottom + base.padding.bottom; + left_offset = base.offset(); } if inorder { @@ -160,17 +158,15 @@ impl BlockFlow { let mut first_in_flow = true; for &box in self.box.iter() { let base = box.base(); - let mut model_ref = base.model.mutate(); - let model = &mut model_ref.ptr; - if !self.is_root && model.border.top == Au::new(0) && model.padding.top == Au::new(0) { - collapsible = model.margin.top; + if !self.is_root && base.border.top == Au::new(0) && base.padding.top == Au::new(0) { + collapsible = base.margin.top; top_margin_collapsible = true; } - if !self.is_root && model.border.bottom == Au::new(0) && model.padding.bottom == Au::new(0) { + if !self.is_root && base.border.bottom == Au::new(0) && base.padding.bottom == Au::new(0) { bottom_margin_collapsible = true; } - margin_top = model.margin.top; - margin_bottom = model.margin.bottom; + margin_top = base.margin.top; + margin_bottom = base.margin.bottom; } for kid in self.base.child_iter() { @@ -220,23 +216,22 @@ impl BlockFlow { let mut noncontent_height = Au::new(0); for box in self.box.iter() { - let base = box.base(); - let mut model_ref = base.model.mutate(); + let base = box.mut_base(); let mut position_ref = base.position.mutate(); - let (model, position) = (&mut model_ref.ptr, &mut position_ref.ptr); + let position = &mut position_ref.ptr; // The associated box is the border box of this flow. - model.margin.top = margin_top; - model.margin.bottom = margin_bottom; + base.margin.top = margin_top; + base.margin.bottom = margin_bottom; - position.origin.y = clearance + model.margin.top; + position.origin.y = clearance + base.margin.top; - noncontent_height = model.padding.top + model.padding.bottom + model.border.top + - model.border.bottom; + noncontent_height = base.padding.top + base.padding.bottom + base.border.top + + base.border.bottom; position.size.height = height + noncontent_height; - noncontent_height = noncontent_height + clearance + model.margin.top + - model.margin.bottom; + noncontent_height = noncontent_height + clearance + base.margin.top + + base.margin.bottom; } self.base.position.size.height = height + noncontent_height; @@ -257,18 +252,18 @@ impl BlockFlow { -> bool { if self.base.node.is_iframe_element() { let x = self.base.abs_position.x + do self.box.map_default(Au::new(0)) |box| { - let model = box.base().model.get(); - model.margin.left + model.border.left + model.padding.left + let base = box.base(); + base.margin.left + base.border.left + base.padding.left }; let y = self.base.abs_position.y + do self.box.map_default(Au::new(0)) |box| { - let model = box.base().model.get(); - model.margin.top + model.border.top + model.padding.top + let base = box.base(); + base.margin.top + base.border.top + base.padding.top }; let w = self.base.position.size.width - do self.box.map_default(Au::new(0)) |box| { - box.base().model.get().noncontent_width() + box.base().noncontent_width() }; let h = self.base.position.size.height - do self.box.map_default(Au::new(0)) |box| { - box.base().model.get().noncontent_height() + box.base().noncontent_height() }; do self.base.node.with_mut_iframe_element |iframe_element| { iframe_element.size.get_mut_ref().set_rect(Rect(Point2D(to_frac_px(x) as f32, @@ -339,9 +334,10 @@ impl FlowContext for BlockFlow { these widths will not include child elements, just padding etc. */ for box in self.box.iter() { { - // Can compute border width here since it doesn't depend on anything. + let mut_base = box.mut_base(); let base = box.base(); - base.model.mutate().ptr.compute_borders(base.style()) + // Can compute border width here since it doesn't depend on anything. + mut_base.compute_borders(base.style()) } let (this_minimum_width, this_preferred_width) = box.minimum_and_preferred_widths(); @@ -374,16 +370,14 @@ impl FlowContext for BlockFlow { let mut x_offset = Au::new(0); for &box in self.box.iter() { - let base = box.base(); + let base = box.mut_base(); let style = base.style(); - let mut model_ref = base.model.mutate(); - let model = &mut model_ref.ptr; // Can compute padding here since we know containing block width. - model.compute_padding(style, remaining_width); + base.compute_padding(style, remaining_width); - // Margins are 0 right now so model.noncontent_width() is just borders + padding. - let available_width = remaining_width - model.noncontent_width(); + // Margins are 0 right now so base.noncontent_width() is just borders + padding. + let available_width = remaining_width - base.noncontent_width(); // Top and bottom margins for blocks are 0 if auto. let margin_top = MaybeAuto::from_style(style.Margin.margin_top, @@ -426,19 +420,19 @@ impl FlowContext for BlockFlow { } }; - model.margin.top = margin_top; - model.margin.right = margin_right; - model.margin.bottom = margin_bottom; - model.margin.left = margin_left; + base.margin.top = margin_top; + base.margin.right = margin_right; + base.margin.bottom = margin_bottom; + base.margin.left = margin_left; - x_offset = model.offset(); + x_offset = base.offset(); remaining_width = width; //The associated box is the border box of this flow let position_ref = base.position.mutate(); - position_ref.ptr.origin.x = model.margin.left; - let padding_and_borders = model.padding.left + model.padding.right + - model.border.left + model.border.right; + position_ref.ptr.origin.x = base.margin.left; + let padding_and_borders = base.padding.left + base.padding.right + + base.border.left + base.border.right; position_ref.ptr.size.width = remaining_width + padding_and_borders; } @@ -482,26 +476,24 @@ impl FlowContext for BlockFlow { collapsible: &mut Au) { for &box in self.box.iter() { let base = box.base(); - let mut model_ref = base.model.mutate(); - let model = &mut model_ref.ptr; // The top margin collapses with its first in-flow block-level child's // top margin if the parent has no top border, no top padding. if *first_in_flow && top_margin_collapsible { // If top-margin of parent is less than top-margin of its first child, // the parent box goes down until its top is aligned with the child. - if *margin_top < model.margin.top { + if *margin_top < base.margin.top { // TODO: The position of child floats should be updated and this // would influence clearance as well. See #725 - let extra_margin = model.margin.top - *margin_top; + let extra_margin = base.margin.top - *margin_top; *top_offset = *top_offset + extra_margin; - *margin_top = model.margin.top; + *margin_top = base.margin.top; } } // The bottom margin of an in-flow block-level element collapses // with the top margin of its next in-flow block-level sibling. - *collapsing = geometry::min(model.margin.top, *collapsible); - *collapsible = model.margin.bottom; + *collapsing = geometry::min(base.margin.top, *collapsible); + *collapsible = base.margin.bottom; } *first_in_flow = false; diff --git a/src/components/main/layout/box.rs b/src/components/main/layout/box.rs index 572ddb4d134..e2ca7b5d164 100644 --- a/src/components/main/layout/box.rs +++ b/src/components/main/layout/box.rs @@ -28,12 +28,12 @@ use std::unstable::raw::Box; use style::ComputedValues; use style::computed_values::{ border_style, clear, float, font_family, font_style, line_height, - position, text_align, text_decoration, vertical_align}; + position, text_align, text_decoration, vertical_align, LengthOrPercentage}; use css::node_style::StyledNode; use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData, ToGfxColor}; use layout::float_context::{ClearType, ClearLeft, ClearRight, ClearBoth}; -use layout::model::{BoxModel, MaybeAuto}; +use layout::model::{MaybeAuto, specified}; /// Boxes (`struct Box`) are the leaves of the layout tree. They cannot position themselves. In /// general, boxes do not have a simple correspondence with CSS boxes in the specification: @@ -119,6 +119,8 @@ impl Clone for @RenderBox { pub trait RenderBoxUtils { fn base<'a>(&'a self) -> &'a RenderBoxBase; + fn mut_base<'a>(&'a self) -> &'a mut RenderBoxBase; + /// Returns true if this element is replaced content. This is true for images, form elements, /// and so on. fn is_replaced(&self) -> bool; @@ -172,6 +174,7 @@ pub trait RenderBoxUtils { pub trait RenderBoxRefUtils<'self> { fn base(self) -> &'self RenderBoxBase; + fn mut_base(self) -> &'self mut RenderBoxBase; } /// A box that represents a generic render box. @@ -618,13 +621,22 @@ pub struct RenderBoxBase { /// The position of this box relative to its owning flow. position: Slot<Rect<Au>>, - /// The core parameters (border, padding, margin) used by the box model. - model: Slot<BoxModel>, - /// A debug ID. /// /// TODO(#87) Make this only present in debug builds. - id: int + id: int, + + /// the border of the content box. + border: SideOffsets2D<Au>, + + /// the padding of the content box. + padding: SideOffsets2D<Au>, + + /// the margin of the content box. + margin: SideOffsets2D<Au>, + + /// The width of the content box. + content_box_width: Au, } impl RenderBoxBase { @@ -634,8 +646,11 @@ impl RenderBoxBase { RenderBoxBase { node: node, position: Slot::init(Au::zero_rect()), - model: Slot::init(Zero::zero()), id: id, + border: Zero::zero(), + padding: Zero::zero(), + margin: Zero::zero(), + content_box_width: Zero::zero(), } } @@ -655,13 +670,11 @@ impl RenderBoxBase { let margin_right = MaybeAuto::from_style(style.Margin.margin_right, Au::new(0)).specified_or_zero(); - let mut model_ref = self.model.mutate(); - let model = &mut model_ref.ptr; - let padding_left = model.compute_padding_length(style.Padding.padding_left, Au::new(0)); - let padding_right = model.compute_padding_length(style.Padding.padding_right, Au::new(0)); + let padding_left = self.compute_padding_length(style.Padding.padding_left, Au::new(0)); + let padding_right = self.compute_padding_length(style.Padding.padding_right, Au::new(0)); - width + margin_left + margin_right + padding_left + padding_right + model.border.left + - model.border.right + width + margin_left + margin_right + padding_left + padding_right + self.border.left + + self.border.right } pub fn calculate_line_height(&self, font_size: Au) -> Au { @@ -672,23 +685,50 @@ impl RenderBoxBase { } } - pub fn compute_padding(&self, containing_block_width: Au) { - self.model.mutate().ptr.compute_padding(self.node.style(), containing_block_width); + /// Populates the box model border parameters from the given computed style. + pub fn compute_borders(&mut self, style: &ComputedValues) { + self.border.top = style.Border.border_top_width; + self.border.right = style.Border.border_right_width; + self.border.bottom = style.Border.border_bottom_width; + self.border.left = style.Border.border_left_width; } - pub fn get_noncontent_width(&self) -> Au { - let model_ref = self.model.mutate(); - model_ref.ptr.border.left + model_ref.ptr.padding.left + model_ref.ptr.border.right + - model_ref.ptr.padding.right + /// Populates the box model padding parameters from the given computed style. + pub fn compute_padding(&mut self, style: &ComputedValues, containing_block_width: Au) { + self.padding.top = self.compute_padding_length(style.Padding.padding_top, + containing_block_width); + self.padding.right = self.compute_padding_length(style.Padding.padding_right, + containing_block_width); + self.padding.bottom = self.compute_padding_length(style.Padding.padding_bottom, + containing_block_width); + self.padding.left = self.compute_padding_length(style.Padding.padding_left, + containing_block_width); + } + + pub fn compute_padding_length(&self, padding: LengthOrPercentage, content_box_width: Au) -> Au { + specified(padding, content_box_width) + } + + pub fn noncontent_width(&self) -> Au { + let left = self.margin.left + self.border.left + self.padding.left; + let right = self.margin.right + self.border.right + self.padding.right; + left + right + } + + pub fn noncontent_height(&self) -> Au { + let top = self.margin.top + self.border.top + self.padding.top; + let bottom = self.margin.bottom + self.border.bottom + self.padding.bottom; + top + bottom } /// The box formed by the content edge as defined in CSS 2.1 § 8.1. Coordinates are relative to /// the owning flow. pub fn content_box(&self) -> Rect<Au> { - let (position, model) = (self.position.get(), self.model.get()); - let origin = Point2D(position.origin.x + model.border.left + model.padding.left, + let position = self.position.get(); + let origin = Point2D(position.origin.x + self.border.left + self.padding.left, position.origin.y); - let size = Size2D(position.size.width - self.get_noncontent_width(), position.size.height); + let noncontent_width = self.border.left + self.padding.left + self.border.right + self.padding.right; + let size = Size2D(position.size.width - noncontent_width, position.size.height); Rect(origin, size) } @@ -824,6 +864,10 @@ impl RenderBoxBase { get_propagated_text_decoration(self.nearest_ancestor_element()) } + pub fn offset(&self) -> Au { + self.margin.left + self.border.left + self.padding.left + } + } impl RenderBoxUtils for @RenderBox { @@ -835,6 +879,13 @@ impl RenderBoxUtils for @RenderBox { } } + fn mut_base<'a>(&'a self) -> &'a mut RenderBoxBase { + unsafe { + let (_, box_ptr): (uint, *Box<RenderBoxBase>) = cast::transmute(*self); + cast::transmute_mut(&(*box_ptr).data) + } + } + fn is_replaced(&self) -> bool { self.class() == ImageRenderBoxClass } @@ -894,7 +945,7 @@ impl RenderBoxUtils for @RenderBox { abs_bounds: &Rect<Au>) { // Fast path. let base = self.base(); - let border = base.model.get().border; + let border = base.border; if border.is_zero() { return } @@ -1115,5 +1166,13 @@ impl<'self> RenderBoxRefUtils<'self> for &'self RenderBox { cast::transmute(box_ptr) } } + + #[inline(always)] + fn mut_base(self) -> &'self mut RenderBoxBase { + unsafe { + let (_, box_ptr): (uint, *mut RenderBoxBase) = cast::transmute(self); + cast::transmute(box_ptr) + } + } } diff --git a/src/components/main/layout/float.rs b/src/components/main/layout/float.rs index 23cd1f3e47e..3559ca4e842 100644 --- a/src/components/main/layout/float.rs +++ b/src/components/main/layout/float.rs @@ -127,8 +127,7 @@ impl FlowContext for FloatFlow { for box in self.box.iter() { { - let base = box.base(); - base.model.mutate().ptr.compute_borders(base.style()); + box.mut_base().compute_borders(box.base().style()); } let (this_minimum_width, this_preferred_width) = box.minimum_and_preferred_widths(); @@ -153,13 +152,13 @@ impl FlowContext for FloatFlow { for &box in self.box.iter() { let base = box.base(); + let mut_base = box.mut_base(); let style = base.style(); let mut position_ref = base.position.mutate(); - let mut model_ref = base.model.mutate(); - let (position, model) = (&mut position_ref.ptr, &mut model_ref.ptr); + let position = &mut position_ref.ptr; // Can compute padding here since we know containing block width. - model.compute_padding(style, remaining_width); + mut_base.compute_padding(style, remaining_width); // Margins for floats are 0 if auto. let margin_top = MaybeAuto::from_style(style.Margin.margin_top, @@ -180,19 +179,19 @@ impl FlowContext for FloatFlow { remaining_width).specified_or_default(shrink_to_fit); debug!("assign_widths_float -- width: {}", width); - model.margin.top = margin_top; - model.margin.right = margin_right; - model.margin.bottom = margin_bottom; - model.margin.left = margin_left; + mut_base.margin.top = margin_top; + mut_base.margin.right = margin_right; + mut_base.margin.bottom = margin_bottom; + mut_base.margin.left = margin_left; - x_offset = model.offset(); + x_offset = base.offset(); remaining_width = width; // The associated box is the border box of this flow. - position.origin.x = model.margin.left; + position.origin.x = base.margin.left; - let padding_and_borders = model.padding.left + model.padding.right + - model.border.left + model.border.right; + let padding_and_borders = base.padding.left + base.padding.right + + base.border.left + base.border.right; position.size.width = remaining_width + padding_and_borders; } @@ -231,12 +230,11 @@ impl FlowContext for FloatFlow { Some(clear) => self.base.floats_in.clearance(clear), }; - let model = base.model.get(); - let noncontent_width = model.padding.left + model.padding.right + model.border.left + - model.border.right; + let noncontent_width = base.padding.left + base.padding.right + base.border.left + + base.border.right; - full_noncontent_width = noncontent_width + model.margin.left + model.margin.right; - margin_height = model.margin.top + model.margin.bottom; + full_noncontent_width = noncontent_width + base.margin.left + base.margin.right; + margin_height = base.margin.top + base.margin.bottom; } let info = PlacementInfo { @@ -270,9 +268,7 @@ impl FlowContext for FloatFlow { for &box in self.box.iter() { let base = box.base(); - let model_ref = base.model.borrow(); - top_offset = model_ref.ptr.margin.top + model_ref.ptr.border.top + - model_ref.ptr.padding.top; + top_offset = base.margin.top + base.border.top + base.padding.top; cur_y = cur_y + top_offset; } @@ -287,15 +283,14 @@ impl FlowContext for FloatFlow { let mut noncontent_height; for box in self.box.iter() { let base = box.base(); - let mut model_ref = base.model.mutate(); let mut position_ref = base.position.mutate(); - let (model, position) = (&mut model_ref.ptr, &mut position_ref.ptr); + let position = &mut position_ref.ptr; // The associated box is the border box of this flow. - position.origin.y = model.margin.top; + position.origin.y = base.margin.top; - noncontent_height = model.padding.top + model.padding.bottom + model.border.top + - model.border.bottom; + noncontent_height = base.padding.top + base.padding.bottom + base.border.top + + base.border.bottom; //TODO(eatkinson): compute heights properly using the 'height' property. let height_prop = MaybeAuto::from_style(base.style().Box.height, diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs index b1add7e39d2..39fda3b7961 100644 --- a/src/components/main/layout/inline.rs +++ b/src/components/main/layout/inline.rs @@ -681,10 +681,10 @@ impl FlowContext for InlineFlow { let mut top; let mut bottom; { - let model = image_box.base.model.get(); - top = model.border.top + model.padding.top + model.margin.top; - bottom = model.border.bottom + model.padding.bottom + - model.margin.bottom; + let base = &image_box.base; + top = base.border.top + base.padding.top + base.margin.top; + bottom = base.border.bottom + base.padding.bottom + + base.margin.bottom; } let noncontent_height = top + bottom; diff --git a/src/components/main/layout/model.rs b/src/components/main/layout/model.rs index f44c2ce0db0..2a8b6af2f69 100644 --- a/src/components/main/layout/model.rs +++ b/src/components/main/layout/model.rs @@ -4,22 +4,9 @@ //! Borders, padding, and margins. -use std::num::Zero; -use geom::side_offsets::SideOffsets2D; use servo_util::geometry::Au; -use style::ComputedValues; use computed = style::computed_values; -/// Encapsulates the borders, padding, and margins, which we collectively call the "box model". -#[deriving(Clone)] -pub struct BoxModel { - border: SideOffsets2D<Au>, - padding: SideOffsets2D<Au>, - margin: SideOffsets2D<Au>, - /// The width of the content box. - content_box_width: Au, -} - /// Useful helper data type when computing values for blocks and positioned elements. pub enum MaybeAuto { Auto, @@ -51,63 +38,6 @@ impl MaybeAuto { } } -impl Zero for BoxModel { - fn zero() -> BoxModel { - BoxModel { - border: Zero::zero(), - padding: Zero::zero(), - margin: Zero::zero(), - content_box_width: Zero::zero(), - } - } - - fn is_zero(&self) -> bool { - self.padding.is_zero() && self.border.is_zero() && self.margin.is_zero() - } -} - -impl BoxModel { - /// Populates the box model border parameters from the given computed style. - pub fn compute_borders(&mut self, style: &ComputedValues) { - self.border.top = style.Border.border_top_width; - self.border.right = style.Border.border_right_width; - self.border.bottom = style.Border.border_bottom_width; - self.border.left = style.Border.border_left_width; - } - - /// Populates the box model padding parameters from the given computed style. - pub fn compute_padding(&mut self, style: &ComputedValues, containing_width: Au) { - self.padding.top = self.compute_padding_length(style.Padding.padding_top, - containing_width); - self.padding.right = self.compute_padding_length(style.Padding.padding_right, - containing_width); - self.padding.bottom = self.compute_padding_length(style.Padding.padding_bottom, - containing_width); - self.padding.left = self.compute_padding_length(style.Padding.padding_left, - containing_width); - } - - pub fn noncontent_width(&self) -> Au { - let left = self.margin.left + self.border.left + self.padding.left; - let right = self.margin.right + self.border.right + self.padding.right; - left + right - } - - pub fn noncontent_height(&self) -> Au { - let top = self.margin.top + self.border.top + self.padding.top; - let bottom = self.margin.bottom + self.border.bottom + self.padding.bottom; - top + bottom - } - - pub fn offset(&self) -> Au { - self.margin.left + self.border.left + self.padding.left - } - - pub fn compute_padding_length(&self, padding: computed::LengthOrPercentage, content_box_width: Au) -> Au { - specified(padding, content_box_width) - } -} - pub fn specified_or_none(length: computed::LengthOrPercentageOrNone, containing_length: Au) -> Option<Au> { match length { computed::LPN_None => None, |