mirror of
https://github.com/servo/servo.git
synced 2025-06-21 15:49:04 +01:00
layout: Perform text decoration propagation per CSS 2.1 § 16.3.1 without
going to the DOM.
This commit is contained in:
parent
7b3c3542a3
commit
a2e91d242b
13 changed files with 215 additions and 63 deletions
|
@ -92,12 +92,38 @@ pub struct SolidColorDisplayItem<E> {
|
||||||
|
|
||||||
/// Renders text.
|
/// Renders text.
|
||||||
pub struct TextDisplayItem<E> {
|
pub struct TextDisplayItem<E> {
|
||||||
|
/// Fields common to all display items.
|
||||||
base: BaseDisplayItem<E>,
|
base: BaseDisplayItem<E>,
|
||||||
|
|
||||||
|
/// The text run.
|
||||||
text_run: Arc<~TextRun>,
|
text_run: Arc<~TextRun>,
|
||||||
|
|
||||||
|
/// The range of text within the text run.
|
||||||
range: Range,
|
range: Range,
|
||||||
|
|
||||||
|
/// The color of the text.
|
||||||
color: Color,
|
color: Color,
|
||||||
|
|
||||||
|
/// A bitfield of flags for text display items.
|
||||||
|
flags: TextDisplayItemFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flags for text display items.
|
||||||
|
pub struct TextDisplayItemFlags(u8);
|
||||||
|
|
||||||
|
impl TextDisplayItemFlags {
|
||||||
|
pub fn new() -> TextDisplayItemFlags {
|
||||||
|
TextDisplayItemFlags(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whether underlining is forced on.
|
||||||
|
bitfield!(TextDisplayItemFlags, override_underline, set_override_underline, 0x01)
|
||||||
|
// Whether overlining is forced on.
|
||||||
|
bitfield!(TextDisplayItemFlags, override_overline, set_override_overline, 0x02)
|
||||||
|
// Whether line-through is forced on.
|
||||||
|
bitfield!(TextDisplayItemFlags, override_line_through, set_override_line_through, 0x04)
|
||||||
|
|
||||||
/// Renders an image.
|
/// Renders an image.
|
||||||
pub struct ImageDisplayItem<E> {
|
pub struct ImageDisplayItem<E> {
|
||||||
base: BaseDisplayItem<E>,
|
base: BaseDisplayItem<E>,
|
||||||
|
@ -184,18 +210,18 @@ impl<E> DisplayItem<E> {
|
||||||
let strikeout_size = font_metrics.strikeout_size;
|
let strikeout_size = font_metrics.strikeout_size;
|
||||||
let strikeout_offset = font_metrics.strikeout_offset;
|
let strikeout_offset = font_metrics.strikeout_offset;
|
||||||
|
|
||||||
if text_run.decoration.underline {
|
if text_run.decoration.underline || text.flags.override_underline() {
|
||||||
let underline_y = baseline_origin.y - underline_offset;
|
let underline_y = baseline_origin.y - underline_offset;
|
||||||
let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y),
|
let underline_bounds = Rect(Point2D(baseline_origin.x, underline_y),
|
||||||
Size2D(width, underline_size));
|
Size2D(width, underline_size));
|
||||||
render_context.draw_solid_color(&underline_bounds, text.color);
|
render_context.draw_solid_color(&underline_bounds, text.color);
|
||||||
}
|
}
|
||||||
if text_run.decoration.overline {
|
if text_run.decoration.overline || text.flags.override_overline() {
|
||||||
let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y),
|
let overline_bounds = Rect(Point2D(baseline_origin.x, origin.y),
|
||||||
Size2D(width, underline_size));
|
Size2D(width, underline_size));
|
||||||
render_context.draw_solid_color(&overline_bounds, text.color);
|
render_context.draw_solid_color(&overline_bounds, text.color);
|
||||||
}
|
}
|
||||||
if text_run.decoration.line_through {
|
if text_run.decoration.line_through || text.flags.override_line_through() {
|
||||||
let strikeout_y = baseline_origin.y - strikeout_offset;
|
let strikeout_y = baseline_origin.y - strikeout_offset;
|
||||||
let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y),
|
let strikeout_bounds = Rect(Point2D(baseline_origin.x, strikeout_y),
|
||||||
Size2D(width, strikeout_size));
|
Size2D(width, strikeout_size));
|
||||||
|
|
|
@ -40,6 +40,10 @@ pub use gfx_font_list = font_list;
|
||||||
pub use servo_gfx_font = font;
|
pub use servo_gfx_font = font;
|
||||||
pub use servo_gfx_font_list = font_list;
|
pub use servo_gfx_font_list = font_list;
|
||||||
|
|
||||||
|
// Macros
|
||||||
|
mod macros;
|
||||||
|
|
||||||
|
// Private rendering modules
|
||||||
mod render_context;
|
mod render_context;
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
|
|
22
src/components/gfx/macros.rs
Normal file
22
src/components/gfx/macros.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#[macro_escape];
|
||||||
|
|
||||||
|
macro_rules! bitfield(
|
||||||
|
($bitfieldname:ident, $getter:ident, $setter:ident, $value:expr) => (
|
||||||
|
impl $bitfieldname {
|
||||||
|
#[inline]
|
||||||
|
pub fn $getter(self) -> bool {
|
||||||
|
(*self & $value) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn $setter(&mut self, value: bool) {
|
||||||
|
*self = $bitfieldname((**self & !$value) | (if value { $value } else { 0 }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -501,7 +501,7 @@ impl BlockFlow {
|
||||||
|
|
||||||
// add box that starts block context
|
// add box that starts block context
|
||||||
for box in self.box.iter() {
|
for box in self.box.iter() {
|
||||||
box.build_display_list(builder, dirty, &self.base.abs_position, list)
|
box.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle any out-of-flow elements
|
// TODO: handle any out-of-flow elements
|
||||||
|
@ -532,7 +532,7 @@ impl BlockFlow {
|
||||||
let offset = self.base.abs_position + self.float.get_ref().rel_pos;
|
let offset = self.base.abs_position + self.float.get_ref().rel_pos;
|
||||||
// add box that starts block context
|
// add box that starts block context
|
||||||
for box in self.box.iter() {
|
for box in self.box.iter() {
|
||||||
box.build_display_list(builder, dirty, &offset, list)
|
box.build_display_list(builder, dirty, offset, (&*self) as &Flow, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -621,10 +621,10 @@ impl Flow for BlockFlow {
|
||||||
self.base.position.origin = Au::zero_point();
|
self.base.position.origin = Au::zero_point();
|
||||||
self.base.position.size.width = ctx.screen_size.size.width;
|
self.base.position.size.width = ctx.screen_size.size.width;
|
||||||
self.base.floats_in = FloatContext::new(self.base.num_floats);
|
self.base.floats_in = FloatContext::new(self.base.num_floats);
|
||||||
self.base.is_inorder = false;
|
self.base.flags.set_inorder(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//position was set to the containing block by the flow's parent
|
// The position was set to the containing block by the flow's parent.
|
||||||
let mut remaining_width = self.base.position.size.width;
|
let mut remaining_width = self.base.position.size.width;
|
||||||
let mut x_offset = Au::new(0);
|
let mut x_offset = Au::new(0);
|
||||||
|
|
||||||
|
@ -632,7 +632,7 @@ impl Flow for BlockFlow {
|
||||||
self.float.get_mut_ref().containing_width = remaining_width;
|
self.float.get_mut_ref().containing_width = remaining_width;
|
||||||
|
|
||||||
// Parent usually sets this, but floats are never inorder
|
// Parent usually sets this, but floats are never inorder
|
||||||
self.base.is_inorder = false;
|
self.base.flags.set_inorder(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for box in self.box.iter() {
|
for box in self.box.iter() {
|
||||||
|
@ -677,10 +677,10 @@ impl Flow for BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
let has_inorder_children = if self.is_float() {
|
let has_inorder_children = if self.is_float() {
|
||||||
self.base.num_floats > 0
|
self.base.num_floats > 0
|
||||||
} else {
|
} else {
|
||||||
self.base.is_inorder || self.base.num_floats > 0
|
self.base.flags.inorder() || self.base.num_floats > 0
|
||||||
};
|
};
|
||||||
|
|
||||||
for kid in self.base.child_iter() {
|
for kid in self.base.child_iter() {
|
||||||
assert!(kid.starts_block_flow() || kid.starts_inline_flow());
|
assert!(kid.starts_block_flow() || kid.starts_inline_flow());
|
||||||
|
@ -688,11 +688,16 @@ impl Flow for BlockFlow {
|
||||||
let child_base = flow::mut_base(*kid);
|
let child_base = flow::mut_base(*kid);
|
||||||
child_base.position.origin.x = x_offset;
|
child_base.position.origin.x = x_offset;
|
||||||
child_base.position.size.width = remaining_width;
|
child_base.position.size.width = remaining_width;
|
||||||
child_base.is_inorder = has_inorder_children;
|
child_base.flags.set_inorder(has_inorder_children);
|
||||||
|
|
||||||
if !child_base.is_inorder {
|
if !child_base.flags.inorder() {
|
||||||
child_base.floats_in = FloatContext::new(0);
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@ use gfx::color::rgb;
|
||||||
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
|
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
|
||||||
use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass};
|
use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass};
|
||||||
use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, TextDisplayItem};
|
use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, TextDisplayItem};
|
||||||
use gfx::display_list::{TextDisplayItemClass, ClipDisplayItem, ClipDisplayItemClass};
|
use gfx::display_list::{TextDisplayItemClass, TextDisplayItemFlags, ClipDisplayItem};
|
||||||
|
use gfx::display_list::{ClipDisplayItemClass};
|
||||||
use gfx::font::{FontStyle, FontWeight300};
|
use gfx::font::{FontStyle, FontWeight300};
|
||||||
use gfx::text::text_run::TextRun;
|
use gfx::text::text_run::TextRun;
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
|
@ -27,12 +28,14 @@ use std::cmp::ApproxEq;
|
||||||
use std::num::Zero;
|
use std::num::Zero;
|
||||||
use style::ComputedValues;
|
use style::ComputedValues;
|
||||||
use style::computed_values::{LengthOrPercentage, overflow};
|
use style::computed_values::{LengthOrPercentage, overflow};
|
||||||
use style::computed_values::{border_style, clear, float, font_family, font_style, line_height};
|
use style::computed_values::{border_style, clear, font_family, font_style, line_height};
|
||||||
use style::computed_values::{position, text_align, text_decoration, vertical_align, visibility};
|
use style::computed_values::{text_align, text_decoration, vertical_align, visibility};
|
||||||
|
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData, ToGfxColor};
|
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData, ToGfxColor};
|
||||||
use layout::float_context::{ClearType, ClearLeft, ClearRight, ClearBoth};
|
use layout::float_context::{ClearType, ClearLeft, ClearRight, ClearBoth};
|
||||||
|
use layout::flow::Flow;
|
||||||
|
use layout::flow;
|
||||||
use layout::model::{MaybeAuto, specified};
|
use layout::model::{MaybeAuto, specified};
|
||||||
|
|
||||||
/// Boxes (`struct Box`) are the leaves of the layout tree. They cannot position themselves. In
|
/// Boxes (`struct Box`) are the leaves of the layout tree. They cannot position themselves. In
|
||||||
|
@ -460,41 +463,15 @@ impl Box {
|
||||||
self.style().Box.vertical_align
|
self.style().Box.vertical_align
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the text decoration of the computed style of the nearest `Element` node
|
/// Returns the text decoration of this box, according to the style of the nearest ancestor
|
||||||
|
/// element.
|
||||||
|
///
|
||||||
|
/// NB: This may not be the actual text decoration, because of the override rules specified in
|
||||||
|
/// CSS 2.1 § 16.3.1. Unfortunately, computing this properly doesn't really fit into Servo's
|
||||||
|
/// model. Therefore, this is a best lower bound approximation, but the end result may actually
|
||||||
|
/// have the various decoration flags turned on afterward.
|
||||||
pub fn text_decoration(&self) -> text_decoration::T {
|
pub fn text_decoration(&self) -> text_decoration::T {
|
||||||
/// Computes the propagated value of text-decoration, as specified in CSS 2.1 § 16.3.1
|
self.style().Text.text_decoration
|
||||||
/// TODO: make sure this works with anonymous box generation.
|
|
||||||
fn get_propagated_text_decoration(element: AbstractNode<LayoutView>)
|
|
||||||
-> text_decoration::T {
|
|
||||||
//Skip over non-element nodes in the DOM
|
|
||||||
if !element.is_element() {
|
|
||||||
return match element.parent_node() {
|
|
||||||
None => text_decoration::none,
|
|
||||||
Some(parent) => get_propagated_text_decoration(parent),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Implement correctly.
|
|
||||||
let display_in_flow = true;
|
|
||||||
|
|
||||||
let position = element.style().get().Box.position;
|
|
||||||
let float = element.style().get().Box.float;
|
|
||||||
|
|
||||||
let in_flow = (position == position::static_) && (float == float::none) &&
|
|
||||||
display_in_flow;
|
|
||||||
|
|
||||||
let text_decoration = element.style().get().Text.text_decoration;
|
|
||||||
|
|
||||||
if text_decoration == text_decoration::none && in_flow {
|
|
||||||
match element.parent_node() {
|
|
||||||
None => text_decoration::none,
|
|
||||||
Some(parent) => get_propagated_text_decoration(parent),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
text_decoration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
get_propagated_text_decoration(self.nearest_ancestor_element())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the sum of margin, border, and padding on the left.
|
/// Returns the sum of margin, border, and padding on the left.
|
||||||
|
@ -622,13 +599,14 @@ impl Box {
|
||||||
&self,
|
&self,
|
||||||
_: &DisplayListBuilder,
|
_: &DisplayListBuilder,
|
||||||
dirty: &Rect<Au>,
|
dirty: &Rect<Au>,
|
||||||
offset: &Point2D<Au>,
|
offset: Point2D<Au>,
|
||||||
|
flow: &Flow,
|
||||||
list: &Cell<DisplayList<E>>) {
|
list: &Cell<DisplayList<E>>) {
|
||||||
let box_bounds = self.position.get();
|
let box_bounds = self.position.get();
|
||||||
let absolute_box_bounds = box_bounds.translate(offset);
|
let absolute_box_bounds = box_bounds.translate(&offset);
|
||||||
debug!("Box::build_display_list at rel={}, abs={}: {:s}",
|
debug!("Box::build_display_list at rel={}, abs={}: {:s}",
|
||||||
box_bounds, absolute_box_bounds, self.debug_str());
|
box_bounds, absolute_box_bounds, self.debug_str());
|
||||||
debug!("Box::build_display_list: dirty={}, offset={}", *dirty, *offset);
|
debug!("Box::build_display_list: dirty={}, offset={}", *dirty, offset);
|
||||||
|
|
||||||
if self.style().Box.visibility != visibility::visible {
|
if self.style().Box.visibility != visibility::visible {
|
||||||
return;
|
return;
|
||||||
|
@ -661,6 +639,13 @@ impl Box {
|
||||||
|
|
||||||
let color = self.style().Color.color.to_gfx_color();
|
let color = self.style().Color.color.to_gfx_color();
|
||||||
|
|
||||||
|
// Set the various text display item flags.
|
||||||
|
let flow_flags = flow::base(flow).flags;
|
||||||
|
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());
|
||||||
|
|
||||||
// Create the text box.
|
// Create the text box.
|
||||||
do list.with_mut_ref |list| {
|
do list.with_mut_ref |list| {
|
||||||
let text_display_item = ~TextDisplayItem {
|
let text_display_item = ~TextDisplayItem {
|
||||||
|
@ -671,6 +656,7 @@ impl Box {
|
||||||
text_run: text_box.run.clone(),
|
text_run: text_box.run.clone(),
|
||||||
range: text_box.range,
|
range: text_box.range,
|
||||||
color: color,
|
color: color,
|
||||||
|
flags: text_flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
list.append_item(TextDisplayItemClass(text_display_item))
|
list.append_item(TextDisplayItemClass(text_display_item))
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl ExtraDisplayListData for Nothing {
|
||||||
/// Right now, the builder isn't used for much, but it establishes the pattern we'll need once we
|
/// Right now, the builder isn't used for much, but it establishes the pattern we'll need once we
|
||||||
/// support display-list-based hit testing and so forth.
|
/// support display-list-based hit testing and so forth.
|
||||||
pub struct DisplayListBuilder<'self> {
|
pub struct DisplayListBuilder<'self> {
|
||||||
ctx: &'self LayoutContext,
|
ctx: &'self LayoutContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -33,17 +33,17 @@ use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
||||||
use layout::float_context::{FloatContext, Invalid};
|
use layout::float_context::{FloatContext, Invalid};
|
||||||
use layout::incremental::RestyleDamage;
|
use layout::incremental::RestyleDamage;
|
||||||
use layout::inline::InlineFlow;
|
use layout::inline::InlineFlow;
|
||||||
use gfx::display_list::{ClipDisplayItemClass};
|
|
||||||
|
|
||||||
use extra::dlist::{DList, DListIterator, MutDListIterator};
|
use extra::dlist::{DList, DListIterator, MutDListIterator};
|
||||||
use extra::container::Deque;
|
use extra::container::Deque;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::{ClipDisplayItemClass, DisplayList};
|
||||||
use servo_util::geometry::Au;
|
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
|
use servo_util::geometry::Au;
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use style::ComputedValues;
|
||||||
|
|
||||||
/// Virtual methods that make up a float context.
|
/// Virtual methods that make up a float context.
|
||||||
///
|
///
|
||||||
|
@ -305,6 +305,49 @@ pub trait PostorderFlowTraversal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flags used in flows, tightly packed to save space.
|
||||||
|
pub struct FlowFlags(u8);
|
||||||
|
|
||||||
|
/// The bitmask of flags that represent text decoration fields that get propagated downward.
|
||||||
|
///
|
||||||
|
/// NB: If you update this field, you must update the bitfields below.
|
||||||
|
static TEXT_DECORATION_OVERRIDE_BITMASK: u8 = 0b00001110;
|
||||||
|
|
||||||
|
impl FlowFlags {
|
||||||
|
/// Creates a new set of flow flags from the given style.
|
||||||
|
fn new(style: &ComputedValues) -> FlowFlags {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Whether we need an in-order traversal.
|
||||||
|
bitfield!(FlowFlags, inorder, set_inorder, 0x01)
|
||||||
|
|
||||||
|
// Whether this flow forces `text-decoration: underline` on.
|
||||||
|
//
|
||||||
|
// NB: If you update this, you need to update TEXT_DECORATION_OVERRIDE_BITMASK.
|
||||||
|
bitfield!(FlowFlags, override_underline, set_override_underline, 0x02)
|
||||||
|
|
||||||
|
// Whether this flow forces `text-decoration: overline` on.
|
||||||
|
//
|
||||||
|
// NB: If you update this, you need to update TEXT_DECORATION_OVERRIDE_BITMASK.
|
||||||
|
bitfield!(FlowFlags, override_overline, set_override_overline, 0x04)
|
||||||
|
|
||||||
|
// Whether this flow forces `text-decoration: line-through` on.
|
||||||
|
//
|
||||||
|
// NB: If you update this, you need to update TEXT_DECORATION_OVERRIDE_BITMASK.
|
||||||
|
bitfield!(FlowFlags, override_line_through, set_override_line_through, 0x08)
|
||||||
|
|
||||||
/// Data common to all flows.
|
/// Data common to all flows.
|
||||||
///
|
///
|
||||||
/// FIXME: We need a naming convention for pseudo-inheritance like this. How about
|
/// FIXME: We need a naming convention for pseudo-inheritance like this. How about
|
||||||
|
@ -313,6 +356,7 @@ pub struct FlowData {
|
||||||
node: AbstractNode<LayoutView>,
|
node: AbstractNode<LayoutView>,
|
||||||
restyle_damage: RestyleDamage,
|
restyle_damage: RestyleDamage,
|
||||||
|
|
||||||
|
/// The children of this flow.
|
||||||
children: DList<~Flow:>,
|
children: DList<~Flow:>,
|
||||||
|
|
||||||
/* TODO (Issue #87): debug only */
|
/* TODO (Issue #87): debug only */
|
||||||
|
@ -336,7 +380,9 @@ pub struct FlowData {
|
||||||
floats_out: FloatContext,
|
floats_out: FloatContext,
|
||||||
num_floats: uint,
|
num_floats: uint,
|
||||||
abs_position: Point2D<Au>,
|
abs_position: Point2D<Au>,
|
||||||
is_inorder: bool,
|
|
||||||
|
/// Various flags for flows, tightly packed to save space.
|
||||||
|
flags: FlowFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BoxIterator {
|
pub struct BoxIterator {
|
||||||
|
@ -359,6 +405,7 @@ impl Iterator<@Box> for BoxIterator {
|
||||||
impl FlowData {
|
impl FlowData {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(id: int, node: AbstractNode<LayoutView>) -> FlowData {
|
pub fn new(id: int, node: AbstractNode<LayoutView>) -> FlowData {
|
||||||
|
let style = node.style();
|
||||||
FlowData {
|
FlowData {
|
||||||
node: node,
|
node: node,
|
||||||
restyle_damage: node.restyle_damage(),
|
restyle_damage: node.restyle_damage(),
|
||||||
|
@ -375,7 +422,8 @@ impl FlowData {
|
||||||
floats_out: Invalid,
|
floats_out: Invalid,
|
||||||
num_floats: 0,
|
num_floats: 0,
|
||||||
abs_position: Point2D(Au::new(0), Au::new(0)),
|
abs_position: Point2D(Au::new(0), Au::new(0)),
|
||||||
is_inorder: false
|
|
||||||
|
flags: FlowFlags::new(style.get()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -497,7 +497,7 @@ impl InlineFlow {
|
||||||
self.boxes.len());
|
self.boxes.len());
|
||||||
|
|
||||||
for box in self.boxes.iter() {
|
for box in self.boxes.iter() {
|
||||||
box.build_display_list(builder, dirty, &self.base.abs_position, list)
|
box.build_display_list(builder, dirty, self.base.abs_position, (&*self) as &Flow, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
|
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
|
||||||
|
@ -672,7 +672,7 @@ impl Flow for InlineFlow {
|
||||||
for kid in self.base.child_iter() {
|
for kid in self.base.child_iter() {
|
||||||
let child_base = flow::mut_base(*kid);
|
let child_base = flow::mut_base(*kid);
|
||||||
child_base.position.size.width = self.base.position.size.width;
|
child_base.position.size.width = self.base.position.size.width;
|
||||||
child_base.is_inorder = self.base.is_inorder;
|
child_base.flags.set_inorder(self.base.flags.inorder());
|
||||||
}
|
}
|
||||||
// There are no child contexts, so stop here.
|
// There are no child contexts, so stop here.
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ impl<'self> PostorderFlowTraversal for AssignHeightsAndStoreOverflowTraversal<'s
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn should_process(&mut self, flow: &mut Flow) -> bool {
|
fn should_process(&mut self, flow: &mut Flow) -> bool {
|
||||||
!flow::base(flow).is_inorder
|
!flow::base(flow).flags.inorder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,3 +22,20 @@ macro_rules! spawn_with(
|
||||||
do ($task).spawn_with(( $($var),+ , () )) |( $($var),+ , () )| $body
|
do ($task).spawn_with(( $($var),+ , () )) |( $($var),+ , () )| $body
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
macro_rules! bitfield(
|
||||||
|
($bitfieldname:ident, $getter:ident, $setter:ident, $value:expr) => (
|
||||||
|
impl $bitfieldname {
|
||||||
|
#[inline]
|
||||||
|
pub fn $getter(self) -> bool {
|
||||||
|
(*self & $value) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn $setter(&mut self, value: bool) {
|
||||||
|
*self = $bitfieldname((**self & !$value) | (if value { $value } else { 0 }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
|
@ -17,3 +17,4 @@
|
||||||
== png_rgba_colorspace_a.html png_rgba_colorspace_b.html
|
== png_rgba_colorspace_a.html png_rgba_colorspace_b.html
|
||||||
== border_style_none_a.html border_style_none_b.html
|
== border_style_none_a.html border_style_none_b.html
|
||||||
== acid1_a.html acid1_b.html
|
== acid1_a.html acid1_b.html
|
||||||
|
== text_decoration_propagation_a.html text_decoration_propagation_b.html
|
||||||
|
|
20
src/test/ref/text_decoration_propagation_a.html
Normal file
20
src/test/ref/text_decoration_propagation_a.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>I CAN'T LIVE ANOTHER DAY WITHOUT AIR CONDITIONING!</title>
|
||||||
|
<style>
|
||||||
|
#a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id=a>
|
||||||
|
hi
|
||||||
|
<div id=b>
|
||||||
|
there
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
23
src/test/ref/text_decoration_propagation_b.html
Normal file
23
src/test/ref/text_decoration_propagation_b.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>I CAN'T LIVE ANOTHER DAY WITHOUT AIR CONDITIONING!</title>
|
||||||
|
<style>
|
||||||
|
#a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
#b {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id=a>
|
||||||
|
hi
|
||||||
|
<div id=b>
|
||||||
|
there
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue