diff --git a/src/components/gfx/display_list.rs b/src/components/gfx/display_list.rs index 1b3df8808cc1..7f44dc224fe6 100644 --- a/src/components/gfx/display_list.rs +++ b/src/components/gfx/display_list.rs @@ -102,10 +102,15 @@ pub struct TextDisplayItem { range: Range, /// The color of the text. - color: Color, + text_color: Color, /// A bitfield of flags for text display items. flags: TextDisplayItemFlags, + + /// The color of text-decorations + underline_color: Color, + overline_color: Color, + line_through_color: Color, } /// Flags for text display items. @@ -202,7 +207,7 @@ impl DisplayItem { text.text_run.get(), &text.range, baseline_origin, - text.color); + text.text_color); }); let width = text.base.bounds.size.width; let underline_size = font_metrics.underline_size; @@ -214,18 +219,18 @@ impl DisplayItem { let underline_y = baseline_origin.y - underline_offset; let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y), Size2D(width, underline_size)); - render_context.draw_solid_color(&underline_bounds, text.color); + render_context.draw_solid_color(&underline_bounds, text.underline_color); } if text_run.decoration.overline || text.flags.override_overline() { let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y), Size2D(width, underline_size)); - render_context.draw_solid_color(&overline_bounds, text.color); + render_context.draw_solid_color(&overline_bounds, text.overline_color); } if text_run.decoration.line_through || text.flags.override_line_through() { let strikeout_y = baseline_origin.y - strikeout_offset; let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y), Size2D(width, strikeout_size)); - render_context.draw_solid_color(&strikeout_bounds, text.color); + render_context.draw_solid_color(&strikeout_bounds, text.line_through_color); } } diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index 3d1429b1a8d8..1f0b3b93edc1 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -629,7 +629,7 @@ impl Flow for BlockFlow { self.base.position.origin = Au::zero_point(); self.base.position.size.width = ctx.shared.screen_size.width; self.base.floats_in = FloatContext::new(self.base.num_floats); - self.base.flags.set_inorder(false); + self.base.flags_info.flags.set_inorder(false); } // The position was set to the containing block by the flow's parent. @@ -640,14 +640,14 @@ impl Flow for BlockFlow { self.float.get_mut_ref().containing_width = remaining_width; // Parent usually sets this, but floats are never inorder - self.base.flags.set_inorder(false); + self.base.flags_info.flags.set_inorder(false); } 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); + self.base.flags_info.flags.set_text_align(style.Text.text_align); // Can compute padding here since we know containing block width. box_.compute_padding(style, remaining_width); @@ -702,7 +702,7 @@ impl Flow for BlockFlow { let has_inorder_children = if self.is_float() { self.base.num_floats > 0 } else { - self.base.flags.inorder() || self.base.num_floats > 0 + self.base.flags_info.flags.inorder() || self.base.num_floats > 0 }; for kid in self.base.child_iter() { @@ -711,18 +711,20 @@ impl Flow for BlockFlow { let child_base = flow::mut_base(*kid); child_base.position.origin.x = x_offset; child_base.position.size.width = remaining_width; - child_base.flags.set_inorder(has_inorder_children); + child_base.flags_info.flags.set_inorder(has_inorder_children); - if !child_base.flags.inorder() { + if !child_base.flags_info.flags.inorder() { child_base.floats_in = FloatContext::new(0); } // 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_alignment_from_parent(self.base.flags) + // FIXME(ksh8281): avoid copy + child_base.flags_info.propagate_text_decoration_from_parent(self.base.flags_info); + + child_base.flags_info.propagate_text_alignment_from_parent(self.base.flags_info) } } diff --git a/src/components/main/layout/box_.rs b/src/components/main/layout/box_.rs index 75e1898145f5..c0cff13159e3 100644 --- a/src/components/main/layout/box_.rs +++ b/src/components/main/layout/box_.rs @@ -35,7 +35,7 @@ use css::node_style::StyledNode; use layout::context::LayoutContext; use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData, ToGfxColor}; use layout::float_context::{ClearType, ClearLeft, ClearRight, ClearBoth}; -use layout::flow::Flow; +use layout::flow::{Flow, FlowFlagsInfo}; use layout::flow; use layout::model::{MaybeAuto, Auto, specified}; use layout::util::OpaqueNode; @@ -747,14 +747,26 @@ impl Box { list.append_item(ClipDisplayItemClass(item)); }); - let color = self.style().Color.color.to_gfx_color(); + let text_color = self.style().Color.color.to_gfx_color(); // Set the various text display item flags. - let flow_flags = flow::base(flow).flags; + let mut flow_flags = flow::base(flow).flags_info; + + let inline_info = self.inline_info.borrow(); + match inline_info.get() { + &Some(ref info) => { + for data in info.parent_info.rev_iter() { + let parent_info = FlowFlagsInfo::new(data.style.get()); + //FIXME(ksh8281) avoid copy + flow_flags.propagate_text_decoration_from_parent(parent_info); + } + }, + &None => {} + } let mut text_flags = TextDisplayItemFlags::new(); - text_flags.set_override_underline(flow_flags.override_underline()); - text_flags.set_override_overline(flow_flags.override_overline()); - text_flags.set_override_line_through(flow_flags.override_line_through()); + text_flags.set_override_underline(flow_flags.flags.override_underline()); + text_flags.set_override_overline(flow_flags.flags.override_overline()); + text_flags.set_override_line_through(flow_flags.flags.override_line_through()); // Create the text box. list.with_mut(|list| { @@ -765,7 +777,10 @@ impl Box { }, text_run: text_box.run.clone(), range: text_box.range, - color: color, + text_color: text_color, + overline_color: flow_flags.overline_color, + underline_color: flow_flags.underline_color, + line_through_color: flow_flags.line_through_color, flags: text_flags, }; diff --git a/src/components/main/layout/flow.rs b/src/components/main/layout/flow.rs index 22719ff9f2b3..dca5777e49fb 100644 --- a/src/components/main/layout/flow.rs +++ b/src/components/main/layout/flow.rs @@ -42,6 +42,8 @@ use extra::container::Deque; use geom::point::Point2D; use geom::rect::Rect; use gfx::display_list::{ClipDisplayItemClass, DisplayList}; +use layout::display_list_builder::ToGfxColor; +use gfx::color::Color; use servo_util::geometry::Au; use std::cast; use std::cell::RefCell; @@ -257,6 +259,15 @@ pub trait PostorderFlowTraversal { } } +pub struct FlowFlagsInfo{ + flags: FlowFlags, + + /// text-decoration colors + underline_color: Color, + overline_color: Color, + line_through_color: Color, +} + /// Flags used in flows, tightly packed to save space. pub struct FlowFlags(u8); @@ -275,25 +286,44 @@ static TEXT_ALIGN_BITMASK: u8 = 0b00110000; /// NB: If you update this field, you must update the bitfields below. static TEXT_ALIGN_SHIFT: u8 = 4; -impl FlowFlags { +impl FlowFlagsInfo { /// Creates a new set of flow flags from the given style. - fn new(style: &ComputedValues) -> FlowFlags { + pub fn new(style: &ComputedValues) -> FlowFlagsInfo { let text_decoration = style.Text.text_decoration; let mut flags = FlowFlags(0); flags.set_override_underline(text_decoration.underline); flags.set_override_overline(text_decoration.overline); flags.set_override_line_through(text_decoration.line_through); - flags + + // TODO(ksh8281) compute text-decoration-color,style,line + let underline_color = style.Color.color.to_gfx_color(); + let overline_color = style.Color.color.to_gfx_color(); + let line_through_color = style.Color.color.to_gfx_color(); + FlowFlagsInfo { + flags: flags, + underline_color: underline_color, + overline_color: overline_color, + line_through_color: line_through_color, + } } /// Propagates text decoration flags from an appropriate parent flow per CSS 2.1 § 16.3.1. - pub fn propagate_text_decoration_from_parent(&mut self, parent: FlowFlags) { - *self = FlowFlags(**self | (*parent & TEXT_DECORATION_OVERRIDE_BITMASK)) + pub fn propagate_text_decoration_from_parent(&mut self, parent: FlowFlagsInfo) { + if !self.flags.override_underline() && parent.flags.override_underline() { + self.underline_color = parent.underline_color; + } + if !self.flags.override_overline() && parent.flags.override_overline() { + self.overline_color = parent.overline_color; + } + if !self.flags.override_line_through() && parent.flags.override_line_through() { + self.line_through_color = parent.line_through_color; + } + self.flags.set_text_decoration_override(parent.flags); } /// 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)) + pub fn propagate_text_alignment_from_parent(&mut self, parent: FlowFlagsInfo) { + self.flags.set_text_align_override(parent.flags); } } @@ -326,6 +356,16 @@ impl FlowFlags { pub fn set_text_align(&mut self, value: text_align::T) { *self = FlowFlags((**self & !TEXT_ALIGN_BITMASK) | ((value as u8) << TEXT_ALIGN_SHIFT)) } + + #[inline] + pub fn set_text_align_override(&mut self, parent: FlowFlags) { + *self = FlowFlags(**self | (*parent & TEXT_ALIGN_BITMASK)) + } + + #[inline] + pub fn set_text_decoration_override(&mut self, parent: FlowFlags) { + *self = FlowFlags(**self | (*parent & TEXT_DECORATION_OVERRIDE_BITMASK)); + } } /// Data common to all flows. @@ -365,8 +405,8 @@ pub struct BaseFlow { num_floats: uint, abs_position: Point2D, - /// Various flags for flows, tightly packed to save space. - flags: FlowFlags, + /// Various flags for flows and some info + flags_info: FlowFlagsInfo, } pub struct BoxIterator { @@ -409,7 +449,7 @@ impl BaseFlow { num_floats: 0, abs_position: Point2D(Au::new(0), Au::new(0)), - flags: FlowFlags::new(style.get()), + flags_info: FlowFlagsInfo::new(style.get()), } } diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs index 28da9b58a269..75c2e42a01b0 100644 --- a/src/components/main/layout/inline.rs +++ b/src/components/main/layout/inline.rs @@ -643,8 +643,9 @@ impl Flow for InlineFlow { for kid in self.base.child_iter() { 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) + child_base.flags_info.flags.set_inorder(self.base.flags_info.flags.inorder()); + // FIXME(ksh8281) avoid copy + child_base.flags_info.propagate_text_alignment_from_parent(self.base.flags_info) } // There are no child contexts, so stop here. @@ -685,7 +686,7 @@ impl Flow for InlineFlow { let mut line_height_offset = Au::new(0); // All lines use text alignment of the flow. - let text_align = self.base.flags.text_align(); + let text_align = self.base.flags_info.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/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index 22e34b2fe976..2fbea22074f4 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -186,7 +186,7 @@ impl<'a> PostorderFlowTraversal for AssignHeightsAndStoreOverflowTraversal<'a> { #[inline] fn should_process(&mut self, flow: &mut Flow) -> bool { - !flow::base(flow).flags.inorder() + !flow::base(flow).flags_info.flags.inorder() } }