mirror of
https://github.com/servo/servo.git
synced 2025-07-25 00:00:20 +01:00
layout: Implement caption-side
per CSS 2.1 § 17.4.1.
`caption-side` is used by 4% of pages by number of loads.
This commit is contained in:
parent
636641f905
commit
a3f6f4e75b
7 changed files with 144 additions and 15 deletions
|
@ -52,7 +52,8 @@ use std::collections::DList;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::atomic::Relaxed;
|
use std::sync::atomic::Relaxed;
|
||||||
use style::ComputedValues;
|
use style::ComputedValues;
|
||||||
use style::computed_values::{display, empty_cells, float, list_style_position, position};
|
use style::computed_values::{caption_side, display, empty_cells, float, list_style_position};
|
||||||
|
use style::computed_values::{position};
|
||||||
use sync::Arc;
|
use sync::Arc;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -778,19 +779,26 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TableCaptionFlow is populated underneath TableWrapperFlow
|
/// Places any table captions found under the given table wrapper, if the value of their
|
||||||
fn place_table_caption_under_table_wrapper(&mut self,
|
/// `caption-side` property is equal to the given `side`.
|
||||||
table_wrapper_flow: &mut FlowRef,
|
fn place_table_caption_under_table_wrapper_on_side(&mut self,
|
||||||
node: &ThreadSafeLayoutNode) {
|
table_wrapper_flow: &mut FlowRef,
|
||||||
|
node: &ThreadSafeLayoutNode,
|
||||||
|
side: caption_side::T) {
|
||||||
|
// Only flows that are table captions are matched here.
|
||||||
for kid in node.children() {
|
for kid in node.children() {
|
||||||
match kid.swap_out_construction_result() {
|
match kid.swap_out_construction_result() {
|
||||||
ConstructionResult::None | ConstructionResult::ConstructionItem(_) => {}
|
ConstructionResult::Flow(mut kid_flow, _) => {
|
||||||
ConstructionResult::Flow(kid_flow, _) => {
|
if kid_flow.deref().is_table_caption() &&
|
||||||
// Only kid flows with table-caption are matched here.
|
kid_flow.as_block()
|
||||||
if kid_flow.deref().is_table_caption() {
|
.fragment
|
||||||
|
.style()
|
||||||
|
.get_inheritedtable()
|
||||||
|
.caption_side == side {
|
||||||
table_wrapper_flow.add_new_child(kid_flow);
|
table_wrapper_flow.add_new_child(kid_flow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ConstructionResult::None | ConstructionResult::ConstructionItem(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -842,17 +850,19 @@ impl<'a> FlowConstructor<'a> {
|
||||||
let table_flow = box TableFlow::from_node_and_fragment(node, table_fragment);
|
let table_flow = box TableFlow::from_node_and_fragment(node, table_fragment);
|
||||||
let table_flow = FlowRef::new(table_flow as Box<Flow>);
|
let table_flow = FlowRef::new(table_flow as Box<Flow>);
|
||||||
|
|
||||||
// We first populate the TableFlow with other flows than TableCaptionFlow.
|
// First populate the table flow with its children.
|
||||||
// We then populate the TableWrapperFlow with TableCaptionFlow, and attach
|
|
||||||
// the TableFlow to the TableWrapperFlow
|
|
||||||
let construction_result = self.build_flow_for_block(table_flow, node);
|
let construction_result = self.build_flow_for_block(table_flow, node);
|
||||||
self.place_table_caption_under_table_wrapper(&mut wrapper_flow, node);
|
|
||||||
|
|
||||||
let mut abs_descendants = Descendants::new();
|
let mut abs_descendants = Descendants::new();
|
||||||
let mut fixed_descendants = Descendants::new();
|
let mut fixed_descendants = Descendants::new();
|
||||||
|
|
||||||
// NOTE: The order of captions and table are not the same order as in the DOM tree.
|
// The order of the caption and the table are not necessarily the same order as in the DOM
|
||||||
// All caption blocks are placed before the table flow
|
// tree. All caption blocks are placed before or after the table flow, depending on the
|
||||||
|
// value of `caption-side`.
|
||||||
|
self.place_table_caption_under_table_wrapper_on_side(&mut wrapper_flow,
|
||||||
|
node,
|
||||||
|
caption_side::top);
|
||||||
|
|
||||||
match construction_result {
|
match construction_result {
|
||||||
ConstructionResult::Flow(table_flow, table_abs_descendants) => {
|
ConstructionResult::Flow(table_flow, table_abs_descendants) => {
|
||||||
wrapper_flow.add_new_child(table_flow);
|
wrapper_flow.add_new_child(table_flow);
|
||||||
|
@ -861,6 +871,11 @@ impl<'a> FlowConstructor<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the value of `caption-side` is `bottom`, place it now.
|
||||||
|
self.place_table_caption_under_table_wrapper_on_side(&mut wrapper_flow,
|
||||||
|
node,
|
||||||
|
caption_side::bottom);
|
||||||
|
|
||||||
// The flow is done.
|
// The flow is done.
|
||||||
wrapper_flow.finish();
|
wrapper_flow.finish();
|
||||||
let is_positioned = wrapper_flow.as_block().is_positioned();
|
let is_positioned = wrapper_flow.as_block().is_positioned();
|
||||||
|
|
|
@ -1330,6 +1330,8 @@ pub mod longhands {
|
||||||
|
|
||||||
${single_keyword("empty-cells", "show hide")}
|
${single_keyword("empty-cells", "show hide")}
|
||||||
|
|
||||||
|
${single_keyword("caption-side", "top bottom")}
|
||||||
|
|
||||||
// CSS 2.1, Section 18 - User interface
|
// CSS 2.1, Section 18 - User interface
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -216,3 +216,5 @@ fragment=top != ../html/acid2.html acid2_ref.html
|
||||||
== inset.html inset_ref.html
|
== inset.html inset_ref.html
|
||||||
== outset.html outset_ref.html
|
== outset.html outset_ref.html
|
||||||
== empty_cells_a.html empty_cells_ref.html
|
== empty_cells_a.html empty_cells_ref.html
|
||||||
|
== table_caption_top_a.html table_caption_top_ref.html
|
||||||
|
== table_caption_bottom_a.html table_caption_bottom_ref.html
|
||||||
|
|
28
tests/ref/table_caption_bottom_a.html
Normal file
28
tests/ref/table_caption_bottom_a.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Tests that `caption-side` places the caption on the right side. -->
|
||||||
|
<style>
|
||||||
|
caption {
|
||||||
|
background-color: blue;
|
||||||
|
color: white;
|
||||||
|
caption-side: bottom;
|
||||||
|
padding: 0;
|
||||||
|
text-align: left;
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table border=0 cellspacing=0 cellpadding=0>
|
||||||
|
<tr><td>Kitten</td><td>Kätzchen</td><td>Chaton</td><td>Koneko</td></tr>
|
||||||
|
<tr><td>Cat</td><td>Katze</td><td>Chat</td><td>Neko</td></tr>
|
||||||
|
<caption>Vocabulary</caption>
|
||||||
|
<tr><td>Dog</td><td>Hund</td><td>Chien</td><td>Inu</td></tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
27
tests/ref/table_caption_bottom_ref.html
Normal file
27
tests/ref/table_caption_bottom_ref.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Tests that `caption-side` places the caption on the right side. -->
|
||||||
|
<style>
|
||||||
|
section {
|
||||||
|
background-color: blue;
|
||||||
|
color: white;
|
||||||
|
padding: 0;
|
||||||
|
text-align: left;
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table border=0 cellspacing=0 cellpadding=0>
|
||||||
|
<tr><td>Kitten</td><td>Kätzchen</td><td>Chaton</td><td>Koneko</td></tr>
|
||||||
|
<tr><td>Cat</td><td>Katze</td><td>Chat</td><td>Neko</td></tr>
|
||||||
|
<tr><td>Dog</td><td>Hund</td><td>Chien</td><td>Inu</td></tr>
|
||||||
|
</table>
|
||||||
|
<section>Vocabulary</section>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
28
tests/ref/table_caption_top_a.html
Normal file
28
tests/ref/table_caption_top_a.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Tests that `caption-side` places the caption on the right side. -->
|
||||||
|
<style>
|
||||||
|
caption {
|
||||||
|
background-color: blue;
|
||||||
|
color: white;
|
||||||
|
caption-side: top;
|
||||||
|
padding: 0;
|
||||||
|
text-align: left;
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table border=0 cellspacing=0 cellpadding=0>
|
||||||
|
<tr><td>Kitten</td><td>Kätzchen</td><td>Chaton</td><td>Koneko</td></tr>
|
||||||
|
<caption>Vocabulary</caption>
|
||||||
|
<tr><td>Cat</td><td>Katze</td><td>Chat</td><td>Neko</td></tr>
|
||||||
|
<tr><td>Dog</td><td>Hund</td><td>Chien</td><td>Inu</td></tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
27
tests/ref/table_caption_top_ref.html
Normal file
27
tests/ref/table_caption_top_ref.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Tests that `caption-side` places the caption on the right side. -->
|
||||||
|
<style>
|
||||||
|
section {
|
||||||
|
background-color: blue;
|
||||||
|
color: white;
|
||||||
|
padding: 0;
|
||||||
|
text-align: left;
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<section>Vocabulary</section>
|
||||||
|
<table border=0 cellspacing=0 cellpadding=0>
|
||||||
|
<tr><td>Kitten</td><td>Kätzchen</td><td>Chaton</td><td>Koneko</td></tr>
|
||||||
|
<tr><td>Cat</td><td>Katze</td><td>Chat</td><td>Neko</td></tr>
|
||||||
|
<tr><td>Dog</td><td>Hund</td><td>Chien</td><td>Inu</td></tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue