diff --git a/components/layout/block.rs b/components/layout/block.rs
index 0df2bbe3f3a..78ed9d581c5 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -55,7 +55,7 @@ use std::cmp::{max, min};
use std::fmt;
use std::sync::Arc;
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::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
use style::values::computed::{LengthOrPercentageOrNone};
@@ -1954,6 +1954,7 @@ pub struct ISizeConstraintInput {
pub inline_end_margin: MaybeAuto,
pub inline_start: MaybeAuto,
pub inline_end: MaybeAuto,
+ pub text_align: text_align::T,
pub available_inline_size: Au,
}
@@ -1963,6 +1964,7 @@ impl ISizeConstraintInput {
inline_end_margin: MaybeAuto,
inline_start: MaybeAuto,
inline_end: MaybeAuto,
+ text_align: text_align::T,
available_inline_size: Au)
-> ISizeConstraintInput {
ISizeConstraintInput {
@@ -1971,6 +1973,7 @@ impl ISizeConstraintInput {
inline_end_margin: inline_end_margin,
inline_start: inline_start,
inline_end: inline_end,
+ text_align: text_align,
available_inline_size: available_inline_size,
}
}
@@ -2066,6 +2069,7 @@ pub trait ISizeAndMarginsComputer {
containing_block_inline_size),
MaybeAuto::from_style(position.inline_end,
containing_block_inline_size),
+ style.get_inheritedtext().text_align,
available_inline_size)
}
@@ -2241,18 +2245,28 @@ pub trait ISizeAndMarginsComputer {
// available_inline-size
let (inline_start_margin, mut 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
- // over-constrained so we discard the end margin.
+ // If all have a computed value other than 'auto', the system is over-constrained.
(MaybeAuto::Specified(margin_start),
MaybeAuto::Specified(inline_size),
MaybeAuto::Specified(margin_end)) => {
- if parent_has_same_direction {
- (margin_start, inline_size, available_inline_size -
- (margin_start + inline_size))
- } else {
- (available_inline_size - (margin_end + inline_size),
- inline_size,
- margin_end)
+ match (input.text_align, parent_has_same_direction) {
+ (text_align::T::servo_center, _) => {
+ // This is used for `
` and friends per HTML5 § 14.3.3. Make the
+ // inline-start and inline-end margins equal per HTML5 § 14.2.
+ let margin = (available_inline_size - inline_size).scale_by(0.5);
+ (margin, inline_size, margin)
+ }
+ (_, 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
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index 03548ce8483..bb4a4354b1a 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -917,7 +917,7 @@ impl InlineFlow {
InlineFlow::justify_inline_fragments(fragments, line, slack_inline_size)
}
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 +
slack_inline_size.scale_by(0.5)
}
diff --git a/components/style/legacy.rs b/components/style/legacy.rs
index 2c7caa16998..b10376981a8 100644
--- a/components/style/legacy.rs
+++ b/components/style/legacy.rs
@@ -75,6 +75,14 @@ pub trait PresentationalHintSynthesis {
E: TElement<'a> +
TElementAttributes<'a>,
V: VecLike>>;
+ /// 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>>;
}
impl PresentationalHintSynthesis for Stylist {
@@ -97,27 +105,20 @@ impl PresentationalHintSynthesis for Stylist {
match element.get_local_name() {
name if *name == atom!("td") => {
- 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
- }
- }
+ self.synthesize_presentational_hint_for_legacy_width_attribute(
+ element,
+ matching_rules_list,
+ shareable);
self.synthesize_presentational_hint_for_legacy_border_attribute(
element,
matching_rules_list,
shareable);
}
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(
element,
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>> {
+ 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
+ }
+ }
+ }
}
diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs
index d5130bf0f98..fdcbb8b9a59 100644
--- a/components/style/properties.mako.rs
+++ b/components/style/properties.mako.rs
@@ -1735,10 +1735,10 @@ pub mod longhands {
impl ComputedValueAsSpecified for SpecifiedValue {}
pub mod computed_value {
macro_rules! define_text_align {
- ( $( $name: ident => $discriminant: expr, )+ ) => {
+ ( $( $name: ident ( $string: expr ) => $discriminant: expr, )+ ) => {
define_css_keyword_enum! { T:
$(
- stringify!($name) => $name,
+ $string => $name,
)+
}
impl T {
@@ -1761,12 +1761,13 @@ pub mod longhands {
}
}
define_text_align! {
- start => 0,
- end => 1,
- left => 2,
- right => 3,
- center => 4,
- justify => 5,
+ start("start") => 0,
+ end("end") => 1,
+ left("left") => 2,
+ right("right") => 3,
+ center("center") => 4,
+ justify("justify") => 5,
+ servo_center("-servo-center") => 6,
}
}
#[inline] pub fn get_initial_value() -> computed_value::T {
diff --git a/resources/presentational-hints.css b/resources/presentational-hints.css
index 47404a5db0b..a22560b9e32 100644
--- a/resources/presentational-hints.css
+++ b/resources/presentational-hints.css
@@ -11,7 +11,6 @@ pre[wrap] { white-space: pre-wrap; }
FIXME: also "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=right i] { text-align: right; }
div[align=justify i] { text-align: justify; }
diff --git a/resources/quirks-mode.css b/resources/quirks-mode.css
index 284c877358a..78a3c2d8a9b 100644
--- a/resources/quirks-mode.css
+++ b/resources/quirks-mode.css
@@ -19,6 +19,17 @@ table {
font-size: initial;
line-height: initial;
white-space: initial;
+ /* text-align: initial; -- see FIXME below */
+}
+
+/*
+ * FIXME(pcwalton): Actually saying `text-align: initial` above breaks `` inside ``
+ * 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 `` element per the spec, would break this behavior. So we place it on
+ * `` instead.
+ */
+tbody {
text-align: initial;
}
diff --git a/resources/servo.css b/resources/servo.css
index 6008dafc2db..143dad0bbbe 100644
--- a/resources/servo.css
+++ b/resources/servo.css
@@ -19,3 +19,5 @@ td[align="left"] { text-align: left; }
td[align="center"] { text-align: center; }
td[align="right"] { text-align: right; }
+center, div[align=center i], div[align=middle i] { text-align: -servo-center; }
+
diff --git a/tests/ref/basic.list b/tests/ref/basic.list
index b1c87ce6ea7..e747d7113db 100644
--- a/tests/ref/basic.list
+++ b/tests/ref/basic.list
@@ -261,6 +261,7 @@ experimental != overconstrained_block.html overconstrained_block_ref.html
== root_pseudo_a.html root_pseudo_b.html
experimental == rtl_body.html rtl_body_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
== stacking_context_overflow_a.html stacking_context_overflow_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_width_a.html table_percentage_width_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_justify_a.html text_align_justify_ref.html
experimental == text_align_rtl.html text_align_rtl_ref.html
diff --git a/tests/ref/servo_center_a.html b/tests/ref/servo_center_a.html
new file mode 100644
index 00000000000..b43bf1830b0
--- /dev/null
+++ b/tests/ref/servo_center_a.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/ref/servo_center_ref.html b/tests/ref/servo_center_ref.html
new file mode 100644
index 00000000000..3d72f794091
--- /dev/null
+++ b/tests/ref/servo_center_ref.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/ref/table_width_attribute_a.html b/tests/ref/table_width_attribute_a.html
new file mode 100644
index 00000000000..463deb178de
--- /dev/null
+++ b/tests/ref/table_width_attribute_a.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/ref/table_width_attribute_ref.html b/tests/ref/table_width_attribute_ref.html
new file mode 100644
index 00000000000..7ccf3ea21a9
--- /dev/null
+++ b/tests/ref/table_width_attribute_ref.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/wpt/metadata/html/rendering/non-replaced-elements/tables/table-width-150percent.html.ini b/tests/wpt/metadata/html/rendering/non-replaced-elements/tables/table-width-150percent.html.ini
index 02e6e907813..76a75c6f128 100644
--- a/tests/wpt/metadata/html/rendering/non-replaced-elements/tables/table-width-150percent.html.ini
+++ b/tests/wpt/metadata/html/rendering/non-replaced-elements/tables/table-width-150percent.html.ini
@@ -2,4 +2,4 @@
type: reftest
reftype: ==
refurl: /html/rendering/non-replaced-elements/tables/table-width-150percent-ref.html
- expected: FAIL
+ expected: PASS