mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
auto merge of #1278 : saneyuki/servo/rm_box, r=pcwalton
This commit is contained in:
commit
37f9427b6c
5 changed files with 150 additions and 174 deletions
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue