From 9a1d4d593bda3a6c8f1353cceb679091f7008698 Mon Sep 17 00:00:00 2001 From: Jack Moffitt Date: Thu, 18 Jul 2013 19:31:52 -0600 Subject: [PATCH] Properly account for relative CSS units in borders, margins, padding, and widths. --- src/components/main/layout/block.rs | 14 ++-- src/components/main/layout/box.rs | 27 ++++--- src/components/main/layout/float.rs | 20 ++++-- src/components/main/layout/model.rs | 107 ++++++++++++++++------------ src/support/css/rust-css | 2 +- 5 files changed, 103 insertions(+), 67 deletions(-) diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index c73cbb2a494..73b4f1a7c7e 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -202,14 +202,16 @@ impl BlockFlowData { // Top and bottom margins for blocks are 0 if auto. let margin_top = MaybeAuto::from_margin(style.margin_top(), - remaining_width).spec_or_default(Au(0)); + remaining_width, + style.font_size()).spec_or_default(Au(0)); let margin_bottom = MaybeAuto::from_margin(style.margin_bottom(), - remaining_width).spec_or_default(Au(0)); + remaining_width, + style.font_size()).spec_or_default(Au(0)); let (width, margin_left, margin_right) = - (MaybeAuto::from_width(style.width(), remaining_width), - MaybeAuto::from_margin(style.margin_left(), remaining_width), - MaybeAuto::from_margin(style.margin_right(), remaining_width)); + (MaybeAuto::from_width(style.width(), remaining_width, style.font_size()), + MaybeAuto::from_margin(style.margin_left(), remaining_width, style.font_size()), + MaybeAuto::from_margin(style.margin_right(), remaining_width, style.font_size())); let (width, margin_left, margin_right) = self.compute_horiz(width, margin_left, @@ -297,7 +299,7 @@ impl BlockFlowData { for self.box.iter().advance |&box| { let style = box.style(); - let maybe_height = MaybeAuto::from_height(style.height(), Au(0)); + let maybe_height = MaybeAuto::from_height(style.height(), Au(0), style.font_size()); let maybe_height = maybe_height.spec_or_default(Au(0)); height = geometry::max(height, maybe_height); } diff --git a/src/components/main/layout/box.rs b/src/components/main/layout/box.rs index fe4cd77aa89..73f0def93f9 100644 --- a/src/components/main/layout/box.rs +++ b/src/components/main/layout/box.rs @@ -388,14 +388,25 @@ impl RenderBox { if(!base.node.is_element()) { Au(0) } else { - - let w = MaybeAuto::from_width(self.style().width(), Au(0)).spec_or_default(Au(0)); - let ml = MaybeAuto::from_margin(self.style().margin_left(), Au(0)).spec_or_default(Au(0)); - let mr = MaybeAuto::from_margin(self.style().margin_right(), Au(0)).spec_or_default(Au(0)); - let pl = base.model.compute_padding_length(self.style().padding_left(), Au(0)); - let pr = base.model.compute_padding_length(self.style().padding_right(), Au(0)); - let bl = base.model.compute_border_width(self.style().border_left_width()); - let br = base.model.compute_border_width(self.style().border_right_width()); + let style = self.style(); + let font_size = style.font_size(); + let w = MaybeAuto::from_width(style.width(), + Au(0), + font_size).spec_or_default(Au(0)); + let ml = MaybeAuto::from_margin(style.margin_left(), + Au(0), + font_size).spec_or_default(Au(0)); + let mr = MaybeAuto::from_margin(style.margin_right(), + Au(0), + font_size).spec_or_default(Au(0)); + let pl = base.model.compute_padding_length(style.padding_left(), + Au(0), + font_size); + let pr = base.model.compute_padding_length(style.padding_right(), + Au(0), + font_size); + let bl = base.model.compute_border_width(style.border_left_width(), font_size); + let br = base.model.compute_border_width(style.border_right_width(), font_size); w + ml + mr + pl + pr + bl + br } diff --git a/src/components/main/layout/float.rs b/src/components/main/layout/float.rs index 898ce9ebfe2..7f0399eef8e 100644 --- a/src/components/main/layout/float.rs +++ b/src/components/main/layout/float.rs @@ -106,13 +106,17 @@ impl FloatFlowData { // Margins for floats are 0 if auto. let margin_top = MaybeAuto::from_margin(style.margin_top(), - remaining_width).spec_or_default(Au(0)); + remaining_width, + style.font_size()).spec_or_default(Au(0)); let margin_bottom = MaybeAuto::from_margin(style.margin_bottom(), - remaining_width).spec_or_default(Au(0)); + remaining_width, + style.font_size()).spec_or_default(Au(0)); let margin_left = MaybeAuto::from_margin(style.margin_left(), - remaining_width).spec_or_default(Au(0)); + remaining_width, + style.font_size()).spec_or_default(Au(0)); let margin_right = MaybeAuto::from_margin(style.margin_right(), - remaining_width).spec_or_default(Au(0)); + remaining_width, + style.font_size()).spec_or_default(Au(0)); @@ -122,7 +126,8 @@ impl FloatFlowData { let width = MaybeAuto::from_width(style.width(), - remaining_width).spec_or_default(shrink_to_fit); + remaining_width, + style.font_size()).spec_or_default(shrink_to_fit); debug!("assign_widths_float -- width: %?", width); model.margin.top = margin_top; @@ -197,9 +202,10 @@ impl FloatFlowData { //TODO(eatkinson): compute heights properly using the 'height' property. for self.box.iter().advance |&box| { - let height_prop = - MaybeAuto::from_height(box.style().height(), Au(0)).spec_or_default(Au(0)); + MaybeAuto::from_height(box.style().height(), + Au(0), + box.style().font_size()).spec_or_default(Au(0)); height = geometry::max(height, height_prop) + noncontent_height; debug!("assign_height_float -- height: %?", height); diff --git a/src/components/main/layout/model.rs b/src/components/main/layout/model.rs index 4bd45dabe17..b3fc4d8d0c1 100644 --- a/src/components/main/layout/model.rs +++ b/src/components/main/layout/model.rs @@ -10,7 +10,7 @@ use gfx::geometry::Au; use newcss::complete::CompleteStyle; use newcss::units::{Em, Pt, Px}; use newcss::values::{CSSBorderWidth, CSSBorderWidthLength, CSSBorderWidthMedium}; -use newcss::values::{CSSBorderWidthThick, CSSBorderWidthThin}; +use newcss::values::{CSSBorderWidthThick, CSSBorderWidthThin, CSSFontSize, CSSFontSizeLength}; use newcss::values::{CSSWidth, CSSWidthLength, CSSWidthPercentage, CSSWidthAuto}; use newcss::values::{CSSHeight, CSSHeightLength, CSSHeightPercentage, CSSHeightAuto}; use newcss::values::{CSSMargin, CSSMarginLength, CSSMarginPercentage, CSSMarginAuto}; @@ -30,45 +30,60 @@ pub enum MaybeAuto { Specified(Au), } -impl MaybeAuto{ - pub fn from_margin(margin: CSSMargin, cb_width: Au) -> MaybeAuto{ +impl MaybeAuto { + pub fn from_margin(margin: CSSMargin, cb_width: Au, font_size: CSSFontSize) -> MaybeAuto { match margin { CSSMarginAuto => Auto, - //FIXME(eatkinson): Compute percents properly CSSMarginPercentage(percent) => Specified(cb_width.scale_by(percent/100.0)), - //FIXME(eatkinson): Compute pt and em values properly - CSSMarginLength(Px(v)) | - CSSMarginLength(Pt(v)) | - CSSMarginLength(Em(v)) => Specified(Au::from_frac_px(v)), + CSSMarginLength(Px(v)) => Specified(Au::from_frac_px(v)), + CSSMarginLength(Pt(v)) => Specified(Au::from_pt(v)), + CSSMarginLength(Em(em)) => match font_size { + CSSFontSizeLength(Px(v)) => + Specified(Au::from_frac_px(em * v)), + CSSFontSizeLength(Pt(v)) => + Specified(Au::from_pt(em * v)), + _ => fail!(~"expected non-relative font size"), + } } } - pub fn from_width(width: CSSWidth, cb_width: Au) -> MaybeAuto{ - match width{ + pub fn from_width(width: CSSWidth, cb_width: Au, font_size: CSSFontSize) -> MaybeAuto { + match width { CSSWidthAuto => Auto, CSSWidthPercentage(percent) => Specified(cb_width.scale_by(percent/100.0)), - //FIXME(eatkinson): Compute pt and em values properly - CSSWidthLength(Px(v)) | - CSSWidthLength(Pt(v)) | - CSSWidthLength(Em(v)) => Specified(Au::from_frac_px(v)), + CSSWidthLength(Px(v)) => Specified(Au::from_frac_px(v)), + CSSWidthLength(Pt(v)) => Specified(Au::from_pt(v)), + CSSWidthLength(Em(em)) => match font_size { + CSSFontSizeLength(Px(v)) => + Specified(Au::from_frac_px(em * v)), + CSSFontSizeLength(Pt(v)) => + Specified(Au::from_pt(em * v)), + _ => fail!(~"expected non-relative font size"), + } } } - pub fn from_height(height: CSSHeight, cb_height: Au) -> MaybeAuto{ + pub fn from_height(height: CSSHeight, cb_height: Au, font_size: CSSFontSize) -> MaybeAuto { match height { CSSHeightAuto => Auto, CSSHeightPercentage(percent) => Specified(cb_height.scale_by(percent/100.0)), - //FIXME(eatkinson): Compute pt and em values properly - CSSHeightLength(Px(v)) | - CSSHeightLength(Pt(v)) | - CSSHeightLength(Em(v)) => Specified(Au::from_frac_px(v)), + CSSHeightLength(Px(v)) => Specified(Au::from_frac_px(v)), + CSSHeightLength(Pt(v)) => Specified(Au::from_pt(v)), + CSSHeightLength(Em(em)) => match font_size { + CSSFontSizeLength(Px(v)) => + Specified(Au::from_frac_px(em * v)), + CSSFontSizeLength(Pt(v)) => + Specified(Au::from_pt(em * v)), + _ => fail!(~"expected non-relative font size"), + } + } } - pub fn spec_or_default(&self, default: Au) -> Au{ - match *self{ + pub fn spec_or_default(&self, default: Au) -> Au { + match *self { Auto => default, - Specified(value) => value + Specified(value) => value, } } } @@ -92,17 +107,17 @@ impl BoxModel { /// Populates the box model parameters from the given computed style. pub fn compute_borders(&mut self, style: CompleteStyle) { // Compute the borders. - self.border.top = self.compute_border_width(style.border_top_width()); - self.border.right = self.compute_border_width(style.border_right_width()); - self.border.bottom = self.compute_border_width(style.border_bottom_width()); - self.border.left = self.compute_border_width(style.border_left_width()); + self.border.top = self.compute_border_width(style.border_top_width(), style.font_size()); + self.border.right = self.compute_border_width(style.border_right_width(), style.font_size()); + self.border.bottom = self.compute_border_width(style.border_bottom_width(), style.font_size()); + self.border.left = self.compute_border_width(style.border_left_width(), style.font_size()); } - pub fn compute_padding(&mut self, style: CompleteStyle, cb_width: Au){ - self.padding.top = self.compute_padding_length(style.padding_top(), cb_width); - self.padding.right = self.compute_padding_length(style.padding_right(), cb_width); - self.padding.bottom = self.compute_padding_length(style.padding_bottom(), cb_width); - self.padding.left = self.compute_padding_length(style.padding_left(), cb_width); + pub fn compute_padding(&mut self, style: CompleteStyle, cb_width: Au) { + self.padding.top = self.compute_padding_length(style.padding_top(), cb_width, style.font_size()); + self.padding.right = self.compute_padding_length(style.padding_right(), cb_width, style.font_size()); + self.padding.bottom = self.compute_padding_length(style.padding_bottom(), cb_width, style.font_size()); + self.padding.left = self.compute_padding_length(style.padding_left(), cb_width, style.font_size()); } pub fn noncontent_width(&self) -> Au { @@ -116,28 +131,30 @@ impl BoxModel { } /// Helper function to compute the border width in app units from the CSS border width. - pub fn compute_border_width(&self, width: CSSBorderWidth) -> Au { + pub fn compute_border_width(&self, width: CSSBorderWidth, font_size: CSSFontSize) -> Au { match width { - CSSBorderWidthLength(Px(v)) | - CSSBorderWidthLength(Em(v)) | - CSSBorderWidthLength(Pt(v)) => { - // FIXME(pcwalton): Handle `em` and `pt` correctly. - Au::from_frac_px(v) - } + CSSBorderWidthLength(Px(v)) => Au::from_frac_px(v), + CSSBorderWidthLength(Pt(v)) => Au::from_pt(v), + CSSBorderWidthLength(Em(em)) => match font_size { + CSSFontSizeLength(Px(v)) => Au::from_frac_px(em * v), + CSSFontSizeLength(Pt(v)) => Au::from_pt(em * v), + _ => fail!(~"expected non-relative font size"), + }, CSSBorderWidthThin => Au::from_px(1), CSSBorderWidthMedium => Au::from_px(5), CSSBorderWidthThick => Au::from_px(10), } } - pub fn compute_padding_length(&self, padding: CSSPadding, content_box_width: Au) -> Au { + pub fn compute_padding_length(&self, padding: CSSPadding, content_box_width: Au, font_size: CSSFontSize) -> Au { match padding { - CSSPaddingLength(Px(v)) | - CSSPaddingLength(Pt(v)) | - CSSPaddingLength(Em(v)) => { - // FIXME(eatkinson): Handle 'em' and 'pt' correctly - Au::from_frac_px(v) - } + CSSPaddingLength(Px(v)) => Au::from_frac_px(v), + CSSPaddingLength(Pt(v)) => Au::from_pt(v), + CSSPaddingLength(Em(em)) => match font_size { + CSSFontSizeLength(Px(v)) => Au::from_frac_px(em * v), + CSSFontSizeLength(Pt(v)) => Au::from_pt(em * v), + _ => fail!(~"expected non-relative font size"), + }, CSSPaddingPercentage(p) => content_box_width.scale_by(p/100.0) } } diff --git a/src/support/css/rust-css b/src/support/css/rust-css index 7a584804a98..8b9cf93fb03 160000 --- a/src/support/css/rust-css +++ b/src/support/css/rust-css @@ -1 +1 @@ -Subproject commit 7a584804a98b5731fb53d216c3f059e5a0c7ea5c +Subproject commit 8b9cf93fb03027d0f125afbd84cf758bd8d2d676