aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/main/layout/block.rs94
-rw-r--r--src/components/main/layout/box.rs105
-rw-r--r--src/components/main/layout/float.rs47
-rw-r--r--src/components/main/layout/inline.rs8
-rw-r--r--src/components/main/layout/model.rs70
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,