mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
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:
parent
20f5fdd000
commit
cf79e64a5a
14 changed files with 118 additions and 101 deletions
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 |
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue