From 5b685bc1bdfdaf6ac5815e7d19dfc42fe9183c82 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 13 Dec 2013 16:05:39 -0800 Subject: [PATCH] layout: Stop going to the DOM for text alignment. Verified against the existing text alignment reftests. --- src/components/main/layout/block.rs | 19 +++++++++++----- src/components/main/layout/flow.rs | 29 +++++++++++++++++++++++++ src/components/main/layout/inline.rs | 12 +++++----- src/components/style/properties.rs.mako | 2 +- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index 7171887378e..ff85f4e14ad 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -585,11 +585,13 @@ impl Flow for BlockFlow { /// Dual boxes consume some width first, and the remainder is assigned to all child (block) /// contexts. fn assign_widths(&mut self, ctx: &mut LayoutContext) { - if self.is_float() { - debug!("assign_widths_float: assigning width for flow {}", self.base.id); - } else { - debug!("assign_widths_block: assigning width for flow {}", self.base.id); - } + debug!("assign_widths({}): assigning width for flow {}", + if self.is_float() { + "float" + } else { + "block" + }, + self.base.id); if self.is_root { debug!("Setting root position"); @@ -613,6 +615,9 @@ impl Flow for BlockFlow { for box in self.box.iter() { let style = box.style(); + // The text alignment of a block flow is the text alignment of its box's style. + self.base.flags.set_text_align(style.Text.text_align); + // Can compute padding here since we know containing block width. box.compute_padding(style, remaining_width); @@ -672,7 +677,9 @@ impl Flow for BlockFlow { // Per CSS 2.1 ยง 16.3.1, text decoration propagates to all children in flow. // // TODO(pcwalton): When we have out-of-flow children, don't unconditionally propagate. - child_base.flags.propagate_text_decoration_from_parent(self.base.flags) + child_base.flags.propagate_text_decoration_from_parent(self.base.flags); + + child_base.flags.propagate_text_alignment_from_parent(self.base.flags) } } diff --git a/src/components/main/layout/flow.rs b/src/components/main/layout/flow.rs index 25d9d08e522..4b612286b30 100644 --- a/src/components/main/layout/flow.rs +++ b/src/components/main/layout/flow.rs @@ -44,6 +44,7 @@ use servo_util::geometry::Au; use std::cast; use std::cell::Cell; use style::ComputedValues; +use style::computed_values::text_align; /// Virtual methods that make up a float context. /// @@ -313,6 +314,16 @@ pub struct FlowFlags(u8); /// NB: If you update this field, you must update the bitfields below. static TEXT_DECORATION_OVERRIDE_BITMASK: u8 = 0b00001110; +/// The bitmask of flags that represent the text alignment field. +/// +/// NB: If you update this field, you must update the bitfields below. +static TEXT_ALIGN_BITMASK: u8 = 0b00110000; + +/// The number of bits we must shift off to handle the text alignment field. +/// +/// NB: If you update this field, you must update the bitfields below. +static TEXT_ALIGN_SHIFT: u8 = 4; + impl FlowFlags { /// Creates a new set of flow flags from the given style. fn new(style: &ComputedValues) -> FlowFlags { @@ -328,6 +339,11 @@ impl FlowFlags { pub fn propagate_text_decoration_from_parent(&mut self, parent: FlowFlags) { *self = FlowFlags(**self | (*parent & TEXT_DECORATION_OVERRIDE_BITMASK)) } + + /// Propagates text alignment flags from an appropriate parent flow per CSS 2.1. + pub fn propagate_text_alignment_from_parent(&mut self, parent: FlowFlags) { + *self = FlowFlags(**self | (*parent & TEXT_ALIGN_BITMASK)) + } } // Whether we need an in-order traversal. @@ -348,6 +364,19 @@ bitfield!(FlowFlags, override_overline, set_override_overline, 0x04) // NB: If you update this, you need to update TEXT_DECORATION_OVERRIDE_BITMASK. bitfield!(FlowFlags, override_line_through, set_override_line_through, 0x08) +// The text alignment for this flow. +impl FlowFlags { + #[inline] + pub fn text_align(self) -> text_align::T { + FromPrimitive::from_u8((*self & TEXT_ALIGN_BITMASK) >> TEXT_ALIGN_SHIFT).unwrap() + } + + #[inline] + pub fn set_text_align(&mut self, value: text_align::T) { + *self = FlowFlags((**self & !TEXT_ALIGN_BITMASK) | ((value as u8) << TEXT_ALIGN_SHIFT)) + } +} + /// Data common to all flows. /// /// FIXME: We need a naming convention for pseudo-inheritance like this. How about diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs index 17603d7e52f..d0057215d4f 100644 --- a/src/components/main/layout/inline.rs +++ b/src/components/main/layout/inline.rs @@ -17,13 +17,13 @@ use extra::container::Deque; use extra::ringbuf::RingBuf; use geom::{Point2D, Rect, Size2D}; use gfx::display_list::DisplayList; -use style::computed_values::text_align; -use style::computed_values::vertical_align; use servo_util::geometry::Au; use servo_util::range::Range; use std::cell::Cell; use std::u16; use std::util; +use style::computed_values::text_align; +use style::computed_values::vertical_align; /// Lineboxes are represented as offsets into the child list, rather than /// as an object that "owns" boxes. Choosing a different set of line @@ -644,7 +644,8 @@ impl Flow for InlineFlow { // // TODO: Combine this with `LineboxScanner`'s walk in the box list, or put this into `Box`. - debug!("assign_widths_inline: floats_in: {:?}", self.base.floats_in); + debug!("InlineFlow::assign_widths: floats_in: {:?}", self.base.floats_in); + { let this = &mut *self; for box in this.boxes.iter() { @@ -656,6 +657,7 @@ impl Flow for InlineFlow { let child_base = flow::mut_base(*kid); child_base.position.size.width = self.base.position.size.width; child_base.flags.set_inorder(self.base.flags.inorder()); + child_base.flags.propagate_text_alignment_from_parent(self.base.flags) } // There are no child contexts, so stop here. @@ -695,8 +697,8 @@ impl Flow for InlineFlow { let mut line_height_offset = Au::new(0); - // All lines use text alignment from base (non-inline) node - let text_align = self.base.node.style().get().Text.text_align; + // All lines use text alignment of the flow. + let text_align = self.base.flags.text_align(); // Now, go through each line and lay out the boxes inside. for line in self.lines.mut_iter() { diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index ca0bcac6b0c..e8b10bc4669 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -106,7 +106,7 @@ pub mod longhands { <%self:single_component_value name="${name}" inherited="${inherited}"> ${caller.body()} pub mod computed_value { - #[deriving(Eq, Clone)] + #[deriving(Eq, Clone, FromPrimitive)] pub enum T { % for value in values.split(): ${to_rust_ident(value)},