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

View file

@ -8,8 +8,9 @@ use css::node_style::StyledNode;
use construct::FlowConstructor;
use context::LayoutContext;
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::bloom::BloomFilter;
use servo_util::cache::{Cache, LRUCache, SimpleHashCache};
@ -616,24 +617,32 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
match &mut *layout_data_ref {
&None => fail!("no layout data"),
&Some(ref mut layout_data) => {
self.cascade_node_pseudo_element(parent_style,
applicable_declarations.normal.as_slice(),
&mut layout_data.shared_data.style,
applicable_declarations_cache,
applicable_declarations.normal_shareable);
if applicable_declarations.before.len() > 0 {
self.cascade_node_pseudo_element(Some(layout_data.shared_data.style.as_ref().unwrap()),
applicable_declarations.before.as_slice(),
&mut layout_data.data.before_style,
applicable_declarations_cache,
false);
}
if applicable_declarations.after.len() > 0 {
self.cascade_node_pseudo_element(Some(layout_data.shared_data.style.as_ref().unwrap()),
applicable_declarations.after.as_slice(),
&mut layout_data.data.after_style,
applicable_declarations_cache,
false);
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,
applicable_declarations.normal.as_slice(),
&mut layout_data.shared_data.style,
applicable_declarations_cache,
applicable_declarations.normal_shareable);
if applicable_declarations.before.len() > 0 {
self.cascade_node_pseudo_element(Some(layout_data.shared_data.style.as_ref().unwrap()),
applicable_declarations.before.as_slice(),
&mut layout_data.data.before_style,
applicable_declarations_cache,
false);
}
if applicable_declarations.after.len() > 0 {
self.cascade_node_pseudo_element(Some(layout_data.shared_data.style.as_ref().unwrap()),
applicable_declarations.after.as_slice(),
&mut layout_data.data.after_style,
applicable_declarations_cache,
false);
}
}
}
}
}

View file

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

View file

@ -674,8 +674,7 @@ impl InlineFragments {
}
/// Pushes a new inline fragment.
pub fn push(&mut self, fragment: &mut Fragment, style: Arc<ComputedValues>) {
fragment.add_inline_context_style(style);
pub fn push(&mut self, fragment: &mut Fragment) {
self.fragments.push(fragment.clone());
}
@ -821,12 +820,9 @@ impl InlineFlow {
vertical_align::baseline => (-ascent, false),
vertical_align::middle => {
// TODO: x-block-size value should be used from font info.
let xblock_size = Au(0);
let fragment_block_size = fragment.content_block_size(layout_context);
let offset_block_start = -(xblock_size + fragment_block_size).scale_by(0.5);
*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)
// TODO: The code below passes our current reftests but
// doesn't work in all situations. Add vertical align reftests and fix this.
(-ascent, false)
},
vertical_align::sub => {
// 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 line_height = text::line_height_from_style(style, &font_metrics);
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 +
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;

View file

@ -244,6 +244,10 @@ impl Flow for TableWrapperFlow {
self
}
fn as_immutable_table_wrapper<'a>(&'a self) -> &'a TableWrapperFlow {
self
}
fn as_block<'a>(&'a mut self) -> &'a mut BlockFlow {
&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.
pub fn line_height_from_style(style: &ComputedValues, metrics: &FontMetrics) -> Au {
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::Number(l) => font_size.scale_by(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 inherited_font_weight: longhands::font_weight::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_height: longhands::height::T,
pub color: longhands::color::computed_value::T,

View file

@ -424,36 +424,6 @@ pub mod longhands {
}
</%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")}
<%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_size: inherited_font_style.font_size,
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_style.get_inheritedtext()._servo_text_decorations_in_effect,
// 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:
# FIXME: use the real test when pixel-snapping for scrolling is fixed.
#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_element_border_a.html inline_element_border_ref.html

View file

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

View file

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

View file

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