Improve acid2. Fix line height calculation. Text fragments get correct enclosing element style.

* Enabled acid2 on mac + linux. Updated the reference image. The only difference from the
real acid2 now is the paint order and a 1 pixel horizontal offset on the nose.
* Change line-height to be calculated correctly.
* Apply enclosing element style to text fragments.
This commit is contained in:
Glenn Watson 2014-09-26 17:12:22 +10:00
parent 20f5fdd000
commit cf79e64a5a
14 changed files with 118 additions and 101 deletions

View file

@ -1575,7 +1575,8 @@ impl Flow for BlockFlow {
fragment_intrinsic_inline_sizes.minimum_inline_size); fragment_intrinsic_inline_sizes.minimum_inline_size);
intrinsic_inline_sizes.preferred_inline_size = max(intrinsic_inline_sizes.preferred_inline_size, intrinsic_inline_sizes.preferred_inline_size = max(intrinsic_inline_sizes.preferred_inline_size,
fragment_intrinsic_inline_sizes.preferred_inline_size); fragment_intrinsic_inline_sizes.preferred_inline_size);
intrinsic_inline_sizes.surround_inline_size = fragment_intrinsic_inline_sizes.surround_inline_size; intrinsic_inline_sizes.surround_inline_size = intrinsic_inline_sizes.surround_inline_size +
fragment_intrinsic_inline_sizes.surround_inline_size;
self.base.intrinsic_inline_sizes = intrinsic_inline_sizes; self.base.intrinsic_inline_sizes = intrinsic_inline_sizes;
match self.fragment.style().get_box().float { match self.fragment.style().get_box().float {

View file

@ -421,7 +421,7 @@ impl<'a> FlowConstructor<'a> {
let mut fragment = Fragment::from_opaque_node_and_style(whitespace_node, let mut fragment = Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_style.clone(), whitespace_style.clone(),
fragment_info); fragment_info);
inline_fragment_accumulator.fragments.push(&mut fragment, whitespace_style); inline_fragment_accumulator.fragments.push(&mut fragment);
} }
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(_)) => { ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(_)) => {
// TODO: Implement anonymous table objects for missing parents // TODO: Implement anonymous table objects for missing parents
@ -449,7 +449,7 @@ impl<'a> FlowConstructor<'a> {
if node.get_pseudo_element_type() != Normal { if node.get_pseudo_element_type() != Normal {
let fragment_info = UnscannedTextFragment(UnscannedTextFragmentInfo::new(node)); let fragment_info = UnscannedTextFragment(UnscannedTextFragmentInfo::new(node));
let mut fragment = Fragment::new_from_specific_info(node, fragment_info); let mut fragment = Fragment::new_from_specific_info(node, fragment_info);
inline_fragment_accumulator.fragments.push(&mut fragment, node.style().clone()); inline_fragment_accumulator.fragments.push(&mut fragment);
first_fragment = false; first_fragment = false;
} }
@ -585,7 +585,7 @@ impl<'a> FlowConstructor<'a> {
let mut fragment = Fragment::from_opaque_node_and_style(whitespace_node, let mut fragment = Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_style.clone(), whitespace_style.clone(),
fragment_info); fragment_info);
fragment_accumulator.fragments.push(&mut fragment, whitespace_style) fragment_accumulator.fragments.push(&mut fragment)
} }
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(_)) => { ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(_)) => {
// TODO: Implement anonymous table objects for missing parents // TODO: Implement anonymous table objects for missing parents
@ -639,7 +639,7 @@ impl<'a> FlowConstructor<'a> {
}; };
let mut fragments = InlineFragments::new(); let mut fragments = InlineFragments::new();
fragments.push(&mut fragment, node.style().clone()); fragments.push(&mut fragment);
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult { let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
splits: Vec::new(), splits: Vec::new(),
@ -661,7 +661,7 @@ impl<'a> FlowConstructor<'a> {
let mut fragment = Fragment::new_from_specific_info(node, fragment_info); let mut fragment = Fragment::new_from_specific_info(node, fragment_info);
let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node); let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
fragment_accumulator.fragments.push(&mut fragment, node.style().clone()); fragment_accumulator.fragments.push(&mut fragment);
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult { let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
splits: Vec::new(), splits: Vec::new(),

View file

@ -8,8 +8,9 @@ use css::node_style::StyledNode;
use construct::FlowConstructor; use construct::FlowConstructor;
use context::LayoutContext; use context::LayoutContext;
use util::{LayoutDataAccess, LayoutDataWrapper}; use util::{LayoutDataAccess, LayoutDataWrapper};
use wrapper::{LayoutElement, LayoutNode, PostorderNodeMutTraversal, ThreadSafeLayoutNode}; use wrapper::{LayoutElement, LayoutNode, PostorderNodeMutTraversal, ThreadSafeLayoutNode, TLayoutNode};
use script::dom::node::{TextNodeTypeId};
use servo_util::atom::Atom; use servo_util::atom::Atom;
use servo_util::bloom::BloomFilter; use servo_util::bloom::BloomFilter;
use servo_util::cache::{Cache, LRUCache, SimpleHashCache}; use servo_util::cache::{Cache, LRUCache, SimpleHashCache};
@ -616,6 +617,12 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
match &mut *layout_data_ref { match &mut *layout_data_ref {
&None => fail!("no layout data"), &None => fail!("no layout data"),
&Some(ref mut layout_data) => { &Some(ref mut layout_data) => {
match self.type_id() {
Some(TextNodeTypeId) => {
let cloned_parent_style = parent_style.unwrap().clone();
layout_data.shared_data.style = Some(cloned_parent_style);
}
_ => {
self.cascade_node_pseudo_element(parent_style, self.cascade_node_pseudo_element(parent_style,
applicable_declarations.normal.as_slice(), applicable_declarations.normal.as_slice(),
&mut layout_data.shared_data.style, &mut layout_data.shared_data.style,
@ -638,4 +645,6 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
} }
} }
} }
}
}
} }

View file

@ -540,11 +540,16 @@ impl Fragment {
/// `border_padding`. Other consumers of this information should simply consult that field. /// `border_padding`. Other consumers of this information should simply consult that field.
#[inline] #[inline]
fn border_width(&self) -> LogicalMargin<Au> { fn border_width(&self) -> LogicalMargin<Au> {
let mut style_border_width = match self.specific {
ScannedTextFragment(_) => LogicalMargin::zero(self.style.writing_mode),
_ => self.style().logical_border_width(),
};
match self.inline_context { match self.inline_context {
None => self.style().logical_border_width(), None => style_border_width,
Some(ref inline_fragment_context) => { Some(ref inline_fragment_context) => {
let zero = LogicalMargin::zero(self.style.writing_mode); inline_fragment_context.styles.iter().fold(style_border_width,
inline_fragment_context.styles.iter().fold(zero, |acc, style| acc + style.logical_border_width()) |acc, style| acc + style.logical_border_width())
} }
} }
} }
@ -579,12 +584,16 @@ impl Fragment {
TableColumnFragment(_) | TableRowFragment | TableColumnFragment(_) | TableRowFragment |
TableWrapperFragment => LogicalMargin::zero(self.style.writing_mode), TableWrapperFragment => LogicalMargin::zero(self.style.writing_mode),
_ => { _ => {
let mut style_padding = match self.specific {
ScannedTextFragment(_) => LogicalMargin::zero(self.style.writing_mode),
_ => model::padding_from_style(self.style(), containing_block_inline_size),
};
match self.inline_context { match self.inline_context {
None => model::padding_from_style(self.style(), containing_block_inline_size), None => style_padding,
Some(ref inline_fragment_context) => { Some(ref inline_fragment_context) => {
let zero = LogicalMargin::zero(self.style.writing_mode); inline_fragment_context.styles.iter().fold(style_padding,
inline_fragment_context.styles.iter() |acc, style| acc + model::padding_from_style(&**style, Au(0)))
.fold(zero, |acc, style| acc + model::padding_from_style(&**style, Au(0)))
} }
} }
} }
@ -614,13 +623,14 @@ impl Fragment {
} }
// Go over the ancestor fragments and add all relative offsets (if any). // Go over the ancestor fragments and add all relative offsets (if any).
let mut rel_pos = LogicalSize::zero(self.style.writing_mode); let mut rel_pos = if self.style().get_box().position == position::relative {
from_style(self.style(), containing_block_size)
} else {
LogicalSize::zero(self.style.writing_mode)
};
match self.inline_context { match self.inline_context {
None => { None => {}
if self.style().get_box().position == position::relative {
rel_pos = rel_pos + from_style(self.style(), containing_block_size);
}
}
Some(ref inline_fragment_context) => { Some(ref inline_fragment_context) => {
for style in inline_fragment_context.styles.iter() { for style in inline_fragment_context.styles.iter() {
if style.get_box().position == position::relative { if style.get_box().position == position::relative {
@ -960,10 +970,15 @@ impl Fragment {
layout_context.shared.dirty, layout_context.shared.dirty,
flow_origin); flow_origin);
let may_need_clip = match self.specific {
ScannedTextFragment(_) => false,
_ => true,
};
let mut accumulator = ChildDisplayListAccumulator::new(self.style(), let mut accumulator = ChildDisplayListAccumulator::new(self.style(),
absolute_fragment_bounds, absolute_fragment_bounds,
self.node, self.node,
ContentStackingLevel); ContentStackingLevel,
may_need_clip);
if self.style().get_inheritedbox().visibility != visibility::visible { if self.style().get_inheritedbox().visibility != visibility::visible {
return accumulator return accumulator
} }
@ -994,14 +1009,13 @@ impl Fragment {
&absolute_fragment_bounds); &absolute_fragment_bounds);
} }
} }
None => { None => {}
}
self.build_display_list_for_background_if_applicable(&*self.style, self.build_display_list_for_background_if_applicable(&*self.style,
display_list, display_list,
layout_context, layout_context,
level, level,
&absolute_fragment_bounds); &absolute_fragment_bounds);
}
}
// Add a border, if applicable. // Add a border, if applicable.
// //
@ -1015,7 +1029,11 @@ impl Fragment {
level); level);
} }
} }
None => { None => {}
}
match self.specific {
ScannedTextFragment(_) => {},
_ => {
self.build_display_list_for_borders_if_applicable(&*self.style, self.build_display_list_for_borders_if_applicable(&*self.style,
display_list, display_list,
&absolute_fragment_bounds, &absolute_fragment_bounds,
@ -1670,17 +1688,18 @@ pub struct ChildDisplayListAccumulator {
impl ChildDisplayListAccumulator { impl ChildDisplayListAccumulator {
/// Creates a `ChildDisplayListAccumulator` from the `overflow` property in the given style. /// Creates a `ChildDisplayListAccumulator` from the `overflow` property in the given style.
fn new(style: &ComputedValues, bounds: Rect<Au>, node: OpaqueNode, level: StackingLevel) fn new(style: &ComputedValues, bounds: Rect<Au>, node: OpaqueNode,
level: StackingLevel, may_need_clip: bool)
-> ChildDisplayListAccumulator { -> ChildDisplayListAccumulator {
ChildDisplayListAccumulator { ChildDisplayListAccumulator {
clip_display_item: match style.get_box().overflow { clip_display_item: match (may_need_clip, style.get_box().overflow) {
overflow::hidden | overflow::auto | overflow::scroll => { (true, overflow::hidden) | (true, overflow::auto) | (true, overflow::scroll) => {
Some(box ClipDisplayItem { Some(box ClipDisplayItem {
base: BaseDisplayItem::new(bounds, node, level), base: BaseDisplayItem::new(bounds, node, level),
children: DisplayList::new(), children: DisplayList::new(),
}) })
}, },
overflow::visible => None, (false, _) | (_, overflow::visible) => None,
} }
} }
} }

View file

@ -674,8 +674,7 @@ impl InlineFragments {
} }
/// Pushes a new inline fragment. /// Pushes a new inline fragment.
pub fn push(&mut self, fragment: &mut Fragment, style: Arc<ComputedValues>) { pub fn push(&mut self, fragment: &mut Fragment) {
fragment.add_inline_context_style(style);
self.fragments.push(fragment.clone()); self.fragments.push(fragment.clone());
} }
@ -821,12 +820,9 @@ impl InlineFlow {
vertical_align::baseline => (-ascent, false), vertical_align::baseline => (-ascent, false),
vertical_align::middle => { vertical_align::middle => {
// TODO: x-block-size value should be used from font info. // TODO: x-block-size value should be used from font info.
let xblock_size = Au(0); // TODO: The code below passes our current reftests but
let fragment_block_size = fragment.content_block_size(layout_context); // doesn't work in all situations. Add vertical align reftests and fix this.
let offset_block_start = -(xblock_size + fragment_block_size).scale_by(0.5); (-ascent, false)
*block_size_above_baseline = offset_block_start.scale_by(-1.0);
*depth_below_baseline = fragment_block_size - *block_size_above_baseline;
(offset_block_start, false)
}, },
vertical_align::sub => { vertical_align::sub => {
// TODO: The proper position for subscripts should be used. Lower the baseline to // TODO: The proper position for subscripts should be used. Lower the baseline to
@ -917,7 +913,27 @@ impl InlineFlow {
let font_metrics = text::font_metrics_for_style(font_context, &font_style); let font_metrics = text::font_metrics_for_style(font_context, &font_style);
let line_height = text::line_height_from_style(style, &font_metrics); let line_height = text::line_height_from_style(style, &font_metrics);
let inline_metrics = InlineMetrics::from_font_metrics(&font_metrics, line_height); let inline_metrics = InlineMetrics::from_font_metrics(&font_metrics, line_height);
(inline_metrics.block_size_above_baseline, inline_metrics.depth_below_baseline)
let mut block_size_above_baseline = inline_metrics.block_size_above_baseline;
let mut depth_below_baseline = inline_metrics.depth_below_baseline;
for frag in self.fragments.fragments.iter() {
match frag.inline_context {
Some(ref inline_context) => {
for style in inline_context.styles.iter() {
let font_style = text::computed_style_to_font_style(&**style);
let font_metrics = text::font_metrics_for_style(font_context, &font_style);
let line_height = text::line_height_from_style(&**style, &font_metrics);
let inline_metrics = InlineMetrics::from_font_metrics(&font_metrics, line_height);
block_size_above_baseline = Au::max(block_size_above_baseline, inline_metrics.block_size_above_baseline);
depth_below_baseline = Au::max(depth_below_baseline, inline_metrics.depth_below_baseline);
}
}
None => {}
}
}
(block_size_above_baseline, depth_below_baseline)
} }
} }
@ -954,6 +970,9 @@ impl Flow for InlineFlow {
intrinsic_inline_sizes.preferred_inline_size = intrinsic_inline_sizes.preferred_inline_size =
intrinsic_inline_sizes.preferred_inline_size + intrinsic_inline_sizes.preferred_inline_size +
fragment_intrinsic_inline_sizes.preferred_inline_size; fragment_intrinsic_inline_sizes.preferred_inline_size;
intrinsic_inline_sizes.surround_inline_size =
intrinsic_inline_sizes.surround_inline_size +
fragment_intrinsic_inline_sizes.surround_inline_size;
} }
self.base.intrinsic_inline_sizes = intrinsic_inline_sizes; self.base.intrinsic_inline_sizes = intrinsic_inline_sizes;

View file

@ -244,6 +244,10 @@ impl Flow for TableWrapperFlow {
self self
} }
fn as_immutable_table_wrapper<'a>(&'a self) -> &'a TableWrapperFlow {
self
}
fn as_block<'a>(&'a mut self) -> &'a mut BlockFlow { fn as_block<'a>(&'a mut self) -> &'a mut BlockFlow {
&mut self.block_flow &mut self.block_flow
} }

View file

@ -317,12 +317,10 @@ pub fn computed_style_to_font_style(style: &ComputedValues) -> FontStyle {
/// Returns the line block-size needed by the given computed style and font size. /// Returns the line block-size needed by the given computed style and font size.
pub fn line_height_from_style(style: &ComputedValues, metrics: &FontMetrics) -> Au { pub fn line_height_from_style(style: &ComputedValues, metrics: &FontMetrics) -> Au {
let font_size = style.get_font().font_size; let font_size = style.get_font().font_size;
let from_inline = match style.get_inheritedbox().line_height { match style.get_inheritedbox().line_height {
line_height::Normal => metrics.line_gap, line_height::Normal => metrics.line_gap,
line_height::Number(l) => font_size.scale_by(l), line_height::Number(l) => font_size.scale_by(l),
line_height::Length(l) => l line_height::Length(l) => l
}; }
let minimum = style.get_inheritedbox()._servo_minimum_line_height;
Au::max(from_inline, minimum)
} }

View file

@ -212,7 +212,6 @@ pub mod computed {
pub struct Context { pub struct Context {
pub inherited_font_weight: longhands::font_weight::computed_value::T, pub inherited_font_weight: longhands::font_weight::computed_value::T,
pub inherited_font_size: longhands::font_size::computed_value::T, pub inherited_font_size: longhands::font_size::computed_value::T,
pub inherited_minimum_line_height: longhands::_servo_minimum_line_height::T,
pub inherited_text_decorations_in_effect: longhands::_servo_text_decorations_in_effect::T, pub inherited_text_decorations_in_effect: longhands::_servo_text_decorations_in_effect::T,
pub inherited_height: longhands::height::T, pub inherited_height: longhands::height::T,
pub color: longhands::color::computed_value::T, pub color: longhands::color::computed_value::T,

View file

@ -424,36 +424,6 @@ pub mod longhands {
} }
</%self:single_component_value> </%self:single_component_value>
<%self:longhand name="-servo-minimum-line-height" derived_from="line-height">
pub use super::computed_as_specified as to_computed_value;
pub type SpecifiedValue = line_height::SpecifiedValue;
pub mod computed_value {
pub type T = super::super::Au;
}
#[inline]
pub fn get_initial_value() -> computed_value::T {
Au(0)
}
#[inline]
pub fn derive_from_line_height(value: line_height::computed_value::T,
context: &computed::Context)
-> Au {
if context.display != display::computed_value::inline {
match value {
line_height::Normal => context.font_size.scale_by(DEFAULT_LINE_HEIGHT),
line_height::Number(percentage) => context.font_size.scale_by(percentage),
line_height::Length(length) => length,
}
} else {
context.inherited_minimum_line_height
}
}
</%self:longhand>
${switch_to_style_struct("Box")} ${switch_to_style_struct("Box")}
<%self:single_component_value name="vertical-align"> <%self:single_component_value name="vertical-align">
@ -1983,8 +1953,6 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock],
inherited_font_weight: inherited_font_style.font_weight, inherited_font_weight: inherited_font_style.font_weight,
inherited_font_size: inherited_font_style.font_size, inherited_font_size: inherited_font_style.font_size,
inherited_height: inherited_style.get_box().height, inherited_height: inherited_style.get_box().height,
inherited_minimum_line_height: inherited_style.get_inheritedbox()
._servo_minimum_line_height,
inherited_text_decorations_in_effect: inherited_text_decorations_in_effect:
inherited_style.get_inheritedtext()._servo_text_decorations_in_effect, inherited_style.get_inheritedtext()._servo_text_decorations_in_effect,
// To be overridden by applicable declarations: // To be overridden by applicable declarations:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Before After
Before After

View file

@ -106,7 +106,7 @@ fragment=top != ../html/acid2.html acid2_ref.html
# Should be != with expected failure: # Should be != with expected failure:
# FIXME: use the real test when pixel-snapping for scrolling is fixed. # FIXME: use the real test when pixel-snapping for scrolling is fixed.
#fragment=top == ../html/acid2.html acid2_ref_broken.html #fragment=top == ../html/acid2.html acid2_ref_broken.html
flaky_gpu,flaky_linux == acid2_noscroll.html acid2_ref_broken.html == acid2_noscroll.html acid2_ref_broken.html
!= inline_background_a.html inline_background_ref.html != inline_background_a.html inline_background_ref.html
== inline_element_border_a.html inline_element_border_ref.html == inline_element_border_a.html inline_element_border_ref.html

View file

@ -1,10 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<link rel="stylesheet" type="text/css" href="css/ahem.css">
<style type="text/css"> <style type="text/css">
body { body {
background-color: #f6f6f6; background-color: #f6f6f6;
font-size: 128px;
} }
</style> </style>
</head> </head>

View file

@ -1,10 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<link rel="stylesheet" type="text/css" href="css/ahem.css">
<style type="text/css"> <style type="text/css">
body { body {
background-color: #f6f6f6; background-color: #f6f6f6;
font-size: 128px;
} }
</style> </style>
</head> </head>

View file

@ -1,10 +1,10 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<link rel="stylesheet" type="text/css" href="css/ahem.css">
<style type="text/css"> <style type="text/css">
body { body {
background-color: #f6f6f6; background-color: #f6f6f6;
font-size: 128px;
} }
</style> </style>
</head> </head>