mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
layout: Implement word-break: break-all
per CSS3-TEXT § 5.2.
This commit is contained in:
parent
df6a7959df
commit
0627d4c599
5 changed files with 95 additions and 28 deletions
|
@ -39,13 +39,13 @@ use servo_util::str::is_whitespace;
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
use style::{ComputedValues, TElement, TNode, cascade_anonymous};
|
use style::{ComputedValues, TElement, TNode, cascade_anonymous};
|
||||||
use style::computed_values::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
use style::computed_values::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
use style::computed_values::{LengthOrPercentageOrNone};
|
use style::computed_values::{LengthOrPercentageOrNone};
|
||||||
use style::computed_values::{clear, overflow_wrap, position, text_align};
|
use style::computed_values::{clear, overflow_wrap, position, text_align, text_decoration};
|
||||||
use style::computed_values::{text_decoration, vertical_align, white_space};
|
use style::computed_values::{vertical_align, white_space, word_break};
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// Fragments (`struct Fragment`) are the leaves of the layout tree. They cannot position
|
/// Fragments (`struct Fragment`) are the leaves of the layout tree. They cannot position
|
||||||
|
@ -1138,16 +1138,12 @@ impl Fragment {
|
||||||
/// information are both optional due to the possibility of them being whitespace.
|
/// information are both optional due to the possibility of them being whitespace.
|
||||||
pub fn calculate_split_position(&self, max_inline_size: Au, starts_line: bool)
|
pub fn calculate_split_position(&self, max_inline_size: Au, starts_line: bool)
|
||||||
-> Option<SplitResult> {
|
-> Option<SplitResult> {
|
||||||
let text_fragment_info = match self.specific {
|
let text_fragment_info =
|
||||||
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Table |
|
if let SpecificFragmentInfo::ScannedText(ref text_fragment_info) = self.specific {
|
||||||
SpecificFragmentInfo::TableCell | SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::InlineBlock(_) |
|
text_fragment_info
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => return None,
|
} else {
|
||||||
SpecificFragmentInfo::TableColumn(_) => panic!("Table column fragments do not have inline_size"),
|
return None
|
||||||
SpecificFragmentInfo::UnscannedText(_) => {
|
};
|
||||||
panic!("Unscanned text fragments should have been scanned by now!")
|
|
||||||
}
|
|
||||||
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => text_fragment_info,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut flags = SplitOptions::empty();
|
let mut flags = SplitOptions::empty();
|
||||||
if starts_line {
|
if starts_line {
|
||||||
|
@ -1157,11 +1153,27 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let natural_word_breaking_strategy =
|
match self.style().get_inheritedtext().word_break {
|
||||||
text_fragment_info.run.natural_word_slices_in_range(&text_fragment_info.range);
|
word_break::T::normal => {
|
||||||
self.calculate_split_position_using_breaking_strategy(natural_word_breaking_strategy,
|
// Break at normal word boundaries.
|
||||||
max_inline_size,
|
let natural_word_breaking_strategy =
|
||||||
flags)
|
text_fragment_info.run.natural_word_slices_in_range(&text_fragment_info.range);
|
||||||
|
self.calculate_split_position_using_breaking_strategy(
|
||||||
|
natural_word_breaking_strategy,
|
||||||
|
max_inline_size,
|
||||||
|
flags)
|
||||||
|
}
|
||||||
|
word_break::T::break_all => {
|
||||||
|
// Break at character boundaries.
|
||||||
|
let character_breaking_strategy =
|
||||||
|
text_fragment_info.run.character_slices_in_range(&text_fragment_info.range);
|
||||||
|
flags.remove(RETRY_AT_CHARACTER_BOUNDARIES);
|
||||||
|
return self.calculate_split_position_using_breaking_strategy(
|
||||||
|
character_breaking_strategy,
|
||||||
|
max_inline_size,
|
||||||
|
flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A helper method that uses the breaking strategy described by `slice_iterator` (at present,
|
/// A helper method that uses the breaking strategy described by `slice_iterator` (at present,
|
||||||
|
@ -1172,16 +1184,12 @@ impl Fragment {
|
||||||
flags: SplitOptions)
|
flags: SplitOptions)
|
||||||
-> Option<SplitResult>
|
-> Option<SplitResult>
|
||||||
where I: Iterator<TextRunSlice<'a>> {
|
where I: Iterator<TextRunSlice<'a>> {
|
||||||
let text_fragment_info = match self.specific {
|
let text_fragment_info =
|
||||||
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Table |
|
if let SpecificFragmentInfo::ScannedText(ref text_fragment_info) = self.specific {
|
||||||
SpecificFragmentInfo::TableCell | SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::InlineBlock(_) |
|
text_fragment_info
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => return None,
|
} else {
|
||||||
SpecificFragmentInfo::TableColumn(_) => panic!("Table column fragments do not have inline_size"),
|
return None
|
||||||
SpecificFragmentInfo::UnscannedText(_) => {
|
};
|
||||||
panic!("Unscanned text fragments should have been scanned by now!")
|
|
||||||
}
|
|
||||||
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => text_fragment_info,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut pieces_processed_count: uint = 0;
|
let mut pieces_processed_count: uint = 0;
|
||||||
let mut remaining_inline_size = max_inline_size;
|
let mut remaining_inline_size = max_inline_size;
|
||||||
|
|
|
@ -1322,6 +1322,9 @@ pub mod longhands {
|
||||||
// name per CSS-TEXT 6.2.
|
// name per CSS-TEXT 6.2.
|
||||||
${single_keyword("overflow-wrap", "normal break-word")}
|
${single_keyword("overflow-wrap", "normal break-word")}
|
||||||
|
|
||||||
|
// TODO(pcwalton): Support `word-break: keep-all` once we have better CJK support.
|
||||||
|
${single_keyword("word-break", "normal break-all")}
|
||||||
|
|
||||||
${new_style_struct("Text", is_inherited=False)}
|
${new_style_struct("Text", is_inherited=False)}
|
||||||
|
|
||||||
<%self:longhand name="text-decoration">
|
<%self:longhand name="text-decoration">
|
||||||
|
|
|
@ -224,3 +224,4 @@ fragment=top != ../html/acid2.html acid2_ref.html
|
||||||
== border_radius_clip_a.html border_radius_clip_ref.html
|
== border_radius_clip_a.html border_radius_clip_ref.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
|
||||||
|
== word_break_a.html word_break_ref.html
|
||||||
|
|
21
tests/ref/word_break_a.html
Normal file
21
tests/ref/word_break_a.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Tests that `word-break: break-all` works. -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="css/ahem.css">
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
word-break: break-all;
|
||||||
|
width: 300px;
|
||||||
|
color: purple;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<section>X XXXXXXX</section>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
34
tests/ref/word_break_ref.html
Normal file
34
tests/ref/word_break_ref.html
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- Tests that `word-break: break-all` works. -->
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
background: purple;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
#a {
|
||||||
|
width: 100px;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
#b {
|
||||||
|
left: 200px;
|
||||||
|
top: 0;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
#c {
|
||||||
|
left: 0;
|
||||||
|
top: 100px;
|
||||||
|
width: 300px;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id=a></div><div id=b></div><div id=c></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue