diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index bf8ae12c10f..cf59d0f89aa 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -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 { - 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 where I: Iterator> { - 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; diff --git a/components/style/properties/mod.rs.mako b/components/style/properties/mod.rs.mako index 18c947f3dff..3053e4abb09 100644 --- a/components/style/properties/mod.rs.mako +++ b/components/style/properties/mod.rs.mako @@ -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"> diff --git a/tests/ref/basic.list b/tests/ref/basic.list index 67e6300969f..fedf64bfb12 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -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 diff --git a/tests/ref/word_break_a.html b/tests/ref/word_break_a.html new file mode 100644 index 00000000000..a26155fc16e --- /dev/null +++ b/tests/ref/word_break_a.html @@ -0,0 +1,21 @@ + + + + + + + + +
X XXXXXXX
+ + + diff --git a/tests/ref/word_break_ref.html b/tests/ref/word_break_ref.html new file mode 100644 index 00000000000..58da73b938f --- /dev/null +++ b/tests/ref/word_break_ref.html @@ -0,0 +1,34 @@ + + + + + + + +
+ + +