mirror of
https://github.com/servo/servo.git
synced 2025-06-06 00:25:37 +00:00
layout: Implement <table width>
and <center>
.
Improves Hacker News.
This commit is contained in:
parent
263b69cf7f
commit
4b9cd4e65d
13 changed files with 160 additions and 36 deletions
|
@ -55,7 +55,7 @@ use std::cmp::{max, min};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use style::computed_values::{border_collapse, box_sizing, display, float, overflow_x, overflow_y};
|
use style::computed_values::{border_collapse, box_sizing, display, float, overflow_x, overflow_y};
|
||||||
use style::computed_values::{position};
|
use style::computed_values::{position, text_align};
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
use style::values::computed::{LengthOrPercentageOrNone};
|
use style::values::computed::{LengthOrPercentageOrNone};
|
||||||
|
@ -1954,6 +1954,7 @@ pub struct ISizeConstraintInput {
|
||||||
pub inline_end_margin: MaybeAuto,
|
pub inline_end_margin: MaybeAuto,
|
||||||
pub inline_start: MaybeAuto,
|
pub inline_start: MaybeAuto,
|
||||||
pub inline_end: MaybeAuto,
|
pub inline_end: MaybeAuto,
|
||||||
|
pub text_align: text_align::T,
|
||||||
pub available_inline_size: Au,
|
pub available_inline_size: Au,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1963,6 +1964,7 @@ impl ISizeConstraintInput {
|
||||||
inline_end_margin: MaybeAuto,
|
inline_end_margin: MaybeAuto,
|
||||||
inline_start: MaybeAuto,
|
inline_start: MaybeAuto,
|
||||||
inline_end: MaybeAuto,
|
inline_end: MaybeAuto,
|
||||||
|
text_align: text_align::T,
|
||||||
available_inline_size: Au)
|
available_inline_size: Au)
|
||||||
-> ISizeConstraintInput {
|
-> ISizeConstraintInput {
|
||||||
ISizeConstraintInput {
|
ISizeConstraintInput {
|
||||||
|
@ -1971,6 +1973,7 @@ impl ISizeConstraintInput {
|
||||||
inline_end_margin: inline_end_margin,
|
inline_end_margin: inline_end_margin,
|
||||||
inline_start: inline_start,
|
inline_start: inline_start,
|
||||||
inline_end: inline_end,
|
inline_end: inline_end,
|
||||||
|
text_align: text_align,
|
||||||
available_inline_size: available_inline_size,
|
available_inline_size: available_inline_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2066,6 +2069,7 @@ pub trait ISizeAndMarginsComputer {
|
||||||
containing_block_inline_size),
|
containing_block_inline_size),
|
||||||
MaybeAuto::from_style(position.inline_end,
|
MaybeAuto::from_style(position.inline_end,
|
||||||
containing_block_inline_size),
|
containing_block_inline_size),
|
||||||
|
style.get_inheritedtext().text_align,
|
||||||
available_inline_size)
|
available_inline_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2241,18 +2245,28 @@ pub trait ISizeAndMarginsComputer {
|
||||||
// available_inline-size
|
// available_inline-size
|
||||||
let (inline_start_margin, mut inline_size, inline_end_margin) =
|
let (inline_start_margin, mut inline_size, inline_end_margin) =
|
||||||
match (inline_start_margin, computed_inline_size, inline_end_margin) {
|
match (inline_start_margin, computed_inline_size, inline_end_margin) {
|
||||||
// If all have a computed value other than 'auto', the system is
|
// If all have a computed value other than 'auto', the system is over-constrained.
|
||||||
// over-constrained so we discard the end margin.
|
|
||||||
(MaybeAuto::Specified(margin_start),
|
(MaybeAuto::Specified(margin_start),
|
||||||
MaybeAuto::Specified(inline_size),
|
MaybeAuto::Specified(inline_size),
|
||||||
MaybeAuto::Specified(margin_end)) => {
|
MaybeAuto::Specified(margin_end)) => {
|
||||||
if parent_has_same_direction {
|
match (input.text_align, parent_has_same_direction) {
|
||||||
(margin_start, inline_size, available_inline_size -
|
(text_align::T::servo_center, _) => {
|
||||||
(margin_start + inline_size))
|
// This is used for `<center>` and friends per HTML5 § 14.3.3. Make the
|
||||||
} else {
|
// inline-start and inline-end margins equal per HTML5 § 14.2.
|
||||||
(available_inline_size - (margin_end + inline_size),
|
let margin = (available_inline_size - inline_size).scale_by(0.5);
|
||||||
inline_size,
|
(margin, inline_size, margin)
|
||||||
margin_end)
|
}
|
||||||
|
(_, true) => {
|
||||||
|
// Ignore the end margin.
|
||||||
|
(margin_start, inline_size, available_inline_size -
|
||||||
|
(margin_start + inline_size))
|
||||||
|
}
|
||||||
|
(_, false) => {
|
||||||
|
// Ignore the start margin.
|
||||||
|
(available_inline_size - (margin_end + inline_size),
|
||||||
|
inline_size,
|
||||||
|
margin_end)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If exactly one value is 'auto', solve for it
|
// If exactly one value is 'auto', solve for it
|
||||||
|
|
|
@ -917,7 +917,7 @@ impl InlineFlow {
|
||||||
InlineFlow::justify_inline_fragments(fragments, line, slack_inline_size)
|
InlineFlow::justify_inline_fragments(fragments, line, slack_inline_size)
|
||||||
}
|
}
|
||||||
text_align::T::justify | text_align::T::start => {}
|
text_align::T::justify | text_align::T::start => {}
|
||||||
text_align::T::center => {
|
text_align::T::center | text_align::T::servo_center => {
|
||||||
inline_start_position_for_fragment = inline_start_position_for_fragment +
|
inline_start_position_for_fragment = inline_start_position_for_fragment +
|
||||||
slack_inline_size.scale_by(0.5)
|
slack_inline_size.scale_by(0.5)
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,14 @@ pub trait PresentationalHintSynthesis {
|
||||||
E: TElement<'a> +
|
E: TElement<'a> +
|
||||||
TElementAttributes<'a>,
|
TElementAttributes<'a>,
|
||||||
V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>;
|
V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>;
|
||||||
|
/// Synthesizes rules for the legacy `width` attribute.
|
||||||
|
fn synthesize_presentational_hint_for_legacy_width_attribute<'a,E,V>(
|
||||||
|
&self,
|
||||||
|
element: E,
|
||||||
|
matching_rules_list: &mut V,
|
||||||
|
shareable: &mut bool)
|
||||||
|
where E: TElement<'a> + TElementAttributes<'a>,
|
||||||
|
V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PresentationalHintSynthesis for Stylist {
|
impl PresentationalHintSynthesis for Stylist {
|
||||||
|
@ -97,27 +105,20 @@ impl PresentationalHintSynthesis for Stylist {
|
||||||
|
|
||||||
match element.get_local_name() {
|
match element.get_local_name() {
|
||||||
name if *name == atom!("td") => {
|
name if *name == atom!("td") => {
|
||||||
match element.get_length_attribute(LengthAttribute::Width) {
|
self.synthesize_presentational_hint_for_legacy_width_attribute(
|
||||||
LengthOrPercentageOrAuto::Auto => {}
|
element,
|
||||||
LengthOrPercentageOrAuto::Percentage(percentage) => {
|
matching_rules_list,
|
||||||
let width_value = specified::LengthOrPercentageOrAuto::Percentage(percentage);
|
shareable);
|
||||||
matching_rules_list.push(from_declaration(
|
|
||||||
PropertyDeclaration::Width(SpecifiedValue(width_value))));
|
|
||||||
*shareable = false
|
|
||||||
}
|
|
||||||
LengthOrPercentageOrAuto::Length(length) => {
|
|
||||||
let width_value = specified::LengthOrPercentageOrAuto::Length(specified::Length::Absolute(length));
|
|
||||||
matching_rules_list.push(from_declaration(
|
|
||||||
PropertyDeclaration::Width(SpecifiedValue(width_value))));
|
|
||||||
*shareable = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.synthesize_presentational_hint_for_legacy_border_attribute(
|
self.synthesize_presentational_hint_for_legacy_border_attribute(
|
||||||
element,
|
element,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
shareable);
|
shareable);
|
||||||
}
|
}
|
||||||
name if *name == atom!("table") => {
|
name if *name == atom!("table") => {
|
||||||
|
self.synthesize_presentational_hint_for_legacy_width_attribute(
|
||||||
|
element,
|
||||||
|
matching_rules_list,
|
||||||
|
shareable);
|
||||||
self.synthesize_presentational_hint_for_legacy_border_attribute(
|
self.synthesize_presentational_hint_for_legacy_border_attribute(
|
||||||
element,
|
element,
|
||||||
matching_rules_list,
|
matching_rules_list,
|
||||||
|
@ -221,6 +222,31 @@ impl PresentationalHintSynthesis for Stylist {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn synthesize_presentational_hint_for_legacy_width_attribute<'a,E,V>(
|
||||||
|
&self,
|
||||||
|
element: E,
|
||||||
|
matching_rules_list: &mut V,
|
||||||
|
shareable: &mut bool)
|
||||||
|
where E: TElement<'a> + TElementAttributes<'a>,
|
||||||
|
V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>> {
|
||||||
|
match element.get_length_attribute(LengthAttribute::Width) {
|
||||||
|
LengthOrPercentageOrAuto::Auto => {}
|
||||||
|
LengthOrPercentageOrAuto::Percentage(percentage) => {
|
||||||
|
let width_value = specified::LengthOrPercentageOrAuto::Percentage(percentage);
|
||||||
|
matching_rules_list.push(from_declaration(
|
||||||
|
PropertyDeclaration::Width(SpecifiedValue(width_value))));
|
||||||
|
*shareable = false
|
||||||
|
}
|
||||||
|
LengthOrPercentageOrAuto::Length(length) => {
|
||||||
|
let width_value = specified::LengthOrPercentageOrAuto::Length(
|
||||||
|
specified::Length::Absolute(length));
|
||||||
|
matching_rules_list.push(from_declaration(
|
||||||
|
PropertyDeclaration::Width(SpecifiedValue(width_value))));
|
||||||
|
*shareable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1735,10 +1735,10 @@ pub mod longhands {
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
macro_rules! define_text_align {
|
macro_rules! define_text_align {
|
||||||
( $( $name: ident => $discriminant: expr, )+ ) => {
|
( $( $name: ident ( $string: expr ) => $discriminant: expr, )+ ) => {
|
||||||
define_css_keyword_enum! { T:
|
define_css_keyword_enum! { T:
|
||||||
$(
|
$(
|
||||||
stringify!($name) => $name,
|
$string => $name,
|
||||||
)+
|
)+
|
||||||
}
|
}
|
||||||
impl T {
|
impl T {
|
||||||
|
@ -1761,12 +1761,13 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
define_text_align! {
|
define_text_align! {
|
||||||
start => 0,
|
start("start") => 0,
|
||||||
end => 1,
|
end("end") => 1,
|
||||||
left => 2,
|
left("left") => 2,
|
||||||
right => 3,
|
right("right") => 3,
|
||||||
center => 4,
|
center("center") => 4,
|
||||||
justify => 5,
|
justify("justify") => 5,
|
||||||
|
servo_center("-servo-center") => 6,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline] pub fn get_initial_value() -> computed_value::T {
|
#[inline] pub fn get_initial_value() -> computed_value::T {
|
||||||
|
|
|
@ -11,7 +11,6 @@ pre[wrap] { white-space: pre-wrap; }
|
||||||
FIXME: also "align descendants"
|
FIXME: also "align descendants"
|
||||||
https://html.spec.whatwg.org/multipage/#align-descendants
|
https://html.spec.whatwg.org/multipage/#align-descendants
|
||||||
*/
|
*/
|
||||||
center, div[align=center i], div[align=middle i] { text-align: center; }
|
|
||||||
div[align=left i] { text-align: left; }
|
div[align=left i] { text-align: left; }
|
||||||
div[align=right i] { text-align: right; }
|
div[align=right i] { text-align: right; }
|
||||||
div[align=justify i] { text-align: justify; }
|
div[align=justify i] { text-align: justify; }
|
||||||
|
|
|
@ -19,6 +19,17 @@ table {
|
||||||
font-size: initial;
|
font-size: initial;
|
||||||
line-height: initial;
|
line-height: initial;
|
||||||
white-space: initial;
|
white-space: initial;
|
||||||
|
/* text-align: initial; -- see FIXME below */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME(pcwalton): Actually saying `text-align: initial` above breaks `<table>` inside `<center>`
|
||||||
|
* in quirks mode. This is because we (following Gecko, WebKit, and Blink) implement the HTML5
|
||||||
|
* align-descendants rules with a special `text-align: -servo-center`. `text-align: initial`, if
|
||||||
|
* placed on the `<table>` element per the spec, would break this behavior. So we place it on
|
||||||
|
* `<tbody>` instead.
|
||||||
|
*/
|
||||||
|
tbody {
|
||||||
text-align: initial;
|
text-align: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,3 +19,5 @@ td[align="left"] { text-align: left; }
|
||||||
td[align="center"] { text-align: center; }
|
td[align="center"] { text-align: center; }
|
||||||
td[align="right"] { text-align: right; }
|
td[align="right"] { text-align: right; }
|
||||||
|
|
||||||
|
center, div[align=center i], div[align=middle i] { text-align: -servo-center; }
|
||||||
|
|
||||||
|
|
|
@ -261,6 +261,7 @@ experimental != overconstrained_block.html overconstrained_block_ref.html
|
||||||
== root_pseudo_a.html root_pseudo_b.html
|
== root_pseudo_a.html root_pseudo_b.html
|
||||||
experimental == rtl_body.html rtl_body_ref.html
|
experimental == rtl_body.html rtl_body_ref.html
|
||||||
experimental == rtl_simple.html rtl_simple_ref.html
|
experimental == rtl_simple.html rtl_simple_ref.html
|
||||||
|
== servo_center_a.html servo_center_ref.html
|
||||||
== setattribute_id_restyle_a.html setattribute_id_restyle_b.html
|
== setattribute_id_restyle_a.html setattribute_id_restyle_b.html
|
||||||
== stacking_context_overflow_a.html stacking_context_overflow_ref.html
|
== stacking_context_overflow_a.html stacking_context_overflow_ref.html
|
||||||
== stacking_context_overflow_relative_outline_a.html stacking_context_overflow_relative_outline_ref.html
|
== stacking_context_overflow_relative_outline_a.html stacking_context_overflow_relative_outline_ref.html
|
||||||
|
@ -279,6 +280,7 @@ experimental == rtl_simple.html rtl_simple_ref.html
|
||||||
== table_percentage_capping_a.html table_percentage_capping_ref.html
|
== table_percentage_capping_a.html table_percentage_capping_ref.html
|
||||||
== table_percentage_width_a.html table_percentage_width_ref.html
|
== table_percentage_width_a.html table_percentage_width_ref.html
|
||||||
experimental == table_row_direction_a.html table_row_direction_ref.html
|
experimental == table_row_direction_a.html table_row_direction_ref.html
|
||||||
|
== table_width_attribute_a.html table_width_attribute_ref.html
|
||||||
== text_align_complex_a.html text_align_complex_ref.html
|
== text_align_complex_a.html text_align_complex_ref.html
|
||||||
== text_align_justify_a.html text_align_justify_ref.html
|
== text_align_justify_a.html text_align_justify_ref.html
|
||||||
experimental == text_align_rtl.html text_align_rtl_ref.html
|
experimental == text_align_rtl.html text_align_rtl_ref.html
|
||||||
|
|
20
tests/ref/servo_center_a.html
Normal file
20
tests/ref/servo_center_a.html
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
width: 85%;
|
||||||
|
background: gold;
|
||||||
|
}
|
||||||
|
tbody {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<center>
|
||||||
|
<table><tr><td>a</td></tr></table>
|
||||||
|
</center>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
18
tests/ref/servo_center_ref.html
Normal file
18
tests/ref/servo_center_ref.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
width: 85%;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
background: gold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table><tr><td>a</td></tr></table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
15
tests/ref/table_width_attribute_a.html
Normal file
15
tests/ref/table_width_attribute_a.html
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
background: gold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table width=85%><tr><td>a</td></tr></table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
16
tests/ref/table_width_attribute_ref.html
Normal file
16
tests/ref/table_width_attribute_ref.html
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
width: 85%;
|
||||||
|
background: gold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table><tr><td>a</td></tr></table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
type: reftest
|
type: reftest
|
||||||
reftype: ==
|
reftype: ==
|
||||||
refurl: /html/rendering/non-replaced-elements/tables/table-width-150percent-ref.html
|
refurl: /html/rendering/non-replaced-elements/tables/table-width-150percent-ref.html
|
||||||
expected: FAIL
|
expected: PASS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue