mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +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::fmt;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use string_cache::Atom;
|
||||
use style::{ComputedValues, TElement, TNode, cascade_anonymous};
|
||||
use style::computed_values::{LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
use style::computed_values::{LengthOrPercentageOrNone};
|
||||
use style::computed_values::{clear, overflow_wrap, position, text_align};
|
||||
use style::computed_values::{text_decoration, vertical_align, white_space};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use style::computed_values::{clear, overflow_wrap, position, text_align, text_decoration};
|
||||
use style::computed_values::{vertical_align, white_space, word_break};
|
||||
use url::Url;
|
||||
|
||||
/// 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.
|
||||
pub fn calculate_split_position(&self, max_inline_size: Au, starts_line: bool)
|
||||
-> Option<SplitResult> {
|
||||
let text_fragment_info = match self.specific {
|
||||
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Table |
|
||||
SpecificFragmentInfo::TableCell | SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::InlineBlock(_) |
|
||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => return None,
|
||||
SpecificFragmentInfo::TableColumn(_) => panic!("Table column fragments do not have inline_size"),
|
||||
SpecificFragmentInfo::UnscannedText(_) => {
|
||||
panic!("Unscanned text fragments should have been scanned by now!")
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => text_fragment_info,
|
||||
};
|
||||
let text_fragment_info =
|
||||
if let SpecificFragmentInfo::ScannedText(ref text_fragment_info) = self.specific {
|
||||
text_fragment_info
|
||||
} else {
|
||||
return None
|
||||
};
|
||||
|
||||
let mut flags = SplitOptions::empty();
|
||||
if starts_line {
|
||||
|
@ -1157,11 +1153,27 @@ impl Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
let natural_word_breaking_strategy =
|
||||
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)
|
||||
match self.style().get_inheritedtext().word_break {
|
||||
word_break::T::normal => {
|
||||
// Break at normal word boundaries.
|
||||
let natural_word_breaking_strategy =
|
||||
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,
|
||||
|
@ -1172,16 +1184,12 @@ impl Fragment {
|
|||
flags: SplitOptions)
|
||||
-> Option<SplitResult>
|
||||
where I: Iterator<TextRunSlice<'a>> {
|
||||
let text_fragment_info = match self.specific {
|
||||
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::Table |
|
||||
SpecificFragmentInfo::TableCell | SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::InlineBlock(_) |
|
||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => return None,
|
||||
SpecificFragmentInfo::TableColumn(_) => panic!("Table column fragments do not have inline_size"),
|
||||
SpecificFragmentInfo::UnscannedText(_) => {
|
||||
panic!("Unscanned text fragments should have been scanned by now!")
|
||||
}
|
||||
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => text_fragment_info,
|
||||
};
|
||||
let text_fragment_info =
|
||||
if let SpecificFragmentInfo::ScannedText(ref text_fragment_info) = self.specific {
|
||||
text_fragment_info
|
||||
} else {
|
||||
return None
|
||||
};
|
||||
|
||||
let mut pieces_processed_count: uint = 0;
|
||||
let mut remaining_inline_size = max_inline_size;
|
||||
|
|
|
@ -1322,6 +1322,9 @@ pub mod longhands {
|
|||
// name per CSS-TEXT 6.2.
|
||||
${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)}
|
||||
|
||||
<%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
|
||||
== stacking_context_overflow_a.html stacking_context_overflow_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