diff --git a/Cargo.lock b/Cargo.lock index e409bd7b6f8..30b04455ca9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3338,6 +3338,7 @@ dependencies = [ "gfx", "gfx_traits", "html5ever", + "icu_segmenter", "ipc-channel", "lazy_static", "log", diff --git a/Cargo.toml b/Cargo.toml index 42e636914ca..d501ee84f61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,7 @@ http = "0.2" hyper = "0.14" hyper-rustls = { version = "0.24", default-features = false, features = ["acceptor", "http1", "http2", "logging", "tls12", "webpki-tokio"] } hyper_serde = { path = "components/hyper_serde" } +icu_segmenter = "1.5.0" image = "0.24" imsz = "0.2" indexmap = { version = "2.2.6", features = ["std"] } diff --git a/components/layout_2020/Cargo.toml b/components/layout_2020/Cargo.toml index 5810cfee983..45283da0257 100644 --- a/components/layout_2020/Cargo.toml +++ b/components/layout_2020/Cargo.toml @@ -9,7 +9,7 @@ publish = false [lib] name = "layout_2020" path = "lib.rs" -test = false +test = true doctest = false [dependencies] @@ -26,6 +26,7 @@ fxhash = { workspace = true } gfx = { path = "../gfx" } gfx_traits = { workspace = true } html5ever = { workspace = true } +icu_segmenter = { workspace = true } ipc-channel = { workspace = true } log = { workspace = true } net_traits = { workspace = true } diff --git a/components/layout_2020/flow/inline/construct.rs b/components/layout_2020/flow/inline/construct.rs index b88b5014f01..e3f4d8055a0 100644 --- a/components/layout_2020/flow/inline/construct.rs +++ b/components/layout_2020/flow/inline/construct.rs @@ -131,8 +131,16 @@ impl InlineFormattingContextBuilder { ArcRefCell::new(InlineLevelBox::Atomic(independent_formatting_context)); self.current_inline_level_boxes() .push(inline_level_box.clone()); + + // Push an object replacement character for this atomic, which will ensure that the line breaker + // inserts a line breaking opportunity here. + let string_to_push = "\u{fffc}"; + self.text_segments.push(string_to_push.to_owned()); + self.current_text_offset += string_to_push.len(); + self.last_inline_box_ended_with_collapsible_white_space = false; self.on_word_boundary = true; + inline_level_box } diff --git a/components/layout_2020/flow/inline/line_breaker.rs b/components/layout_2020/flow/inline/line_breaker.rs new file mode 100644 index 00000000000..28301fdadf8 --- /dev/null +++ b/components/layout_2020/flow/inline/line_breaker.rs @@ -0,0 +1,120 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use std::ops::Range; + +use icu_segmenter::LineSegmenter; + +pub(crate) struct LineBreaker { + linebreaks: Vec, + current_offset: usize, +} + +impl LineBreaker { + pub(crate) fn new(string: &str) -> Self { + let line_segmenter = LineSegmenter::new_auto(); + Self { + // From https://docs.rs/icu_segmenter/1.5.0/icu_segmenter/struct.LineSegmenter.html + // > For consistency with the grapheme, word, and sentence segmenters, there is always a + // > breakpoint returned at index 0, but this breakpoint is not a meaningful line break + // > opportunity. + // + // Skip this first line break opportunity, as it isn't interesting to us. + linebreaks: line_segmenter.segment_str(string).skip(1).collect(), + current_offset: 0, + } + } + + pub(crate) fn advance_to_linebreaks_in_range(&mut self, text_range: Range) -> &[usize] { + let linebreaks_in_range = self.linebreaks_in_range_after_current_offset(text_range); + self.current_offset = linebreaks_in_range.end; + &self.linebreaks[linebreaks_in_range] + } + + fn linebreaks_in_range_after_current_offset(&self, text_range: Range) -> Range { + assert!(text_range.start <= text_range.end); + + let mut linebreaks_range = self.current_offset..self.linebreaks.len(); + + while self.linebreaks[linebreaks_range.start] < text_range.start && + linebreaks_range.len() > 1 + { + linebreaks_range.start += 1; + } + + let mut ending_linebreak_index = linebreaks_range.start; + while self.linebreaks[ending_linebreak_index] < text_range.end && + ending_linebreak_index < self.linebreaks.len() - 1 + { + ending_linebreak_index += 1; + } + linebreaks_range.end = ending_linebreak_index; + linebreaks_range + } +} + +#[test] +fn test_linebreaker_ranges() { + let linebreaker = LineBreaker::new("abc def"); + assert_eq!(linebreaker.linebreaks, [4, 7]); + assert_eq!( + linebreaker.linebreaks_in_range_after_current_offset(0..5), + 0..1 + ); + // The last linebreak should not be included for the text range we are interested in. + assert_eq!( + linebreaker.linebreaks_in_range_after_current_offset(0..7), + 0..1 + ); + + let linebreaker = LineBreaker::new("abc d def"); + assert_eq!(linebreaker.linebreaks, [4, 6, 9]); + assert_eq!( + linebreaker.linebreaks_in_range_after_current_offset(0..5), + 0..1 + ); + assert_eq!( + linebreaker.linebreaks_in_range_after_current_offset(0..7), + 0..2 + ); + assert_eq!( + linebreaker.linebreaks_in_range_after_current_offset(0..9), + 0..2 + ); + + assert_eq!( + linebreaker.linebreaks_in_range_after_current_offset(4..9), + 0..2 + ); + + std::panic::catch_unwind(|| { + let linebreaker = LineBreaker::new("abc def"); + linebreaker.linebreaks_in_range_after_current_offset(5..2); + }) + .expect_err("Reversed range should cause an assertion failure."); +} + +#[test] +fn test_linebreaker_stateful_advance() { + let mut linebreaker = LineBreaker::new("abc d def"); + assert_eq!(linebreaker.linebreaks, [4, 6, 9]); + assert!(linebreaker.advance_to_linebreaks_in_range(0..7) == &[4, 6]); + assert!(linebreaker.advance_to_linebreaks_in_range(8..9).is_empty()); + + // We've already advanced, so a range from the beginning shouldn't affect things. + assert!(linebreaker.advance_to_linebreaks_in_range(0..9).is_empty()); + + linebreaker.current_offset = 0; + + // Sending a value out of range shoudn't break things. + assert!(linebreaker.advance_to_linebreaks_in_range(0..999) == &[4, 6]); + + linebreaker.current_offset = 0; + + std::panic::catch_unwind(|| { + let mut linebreaker = LineBreaker::new("abc d def"); + linebreaker.advance_to_linebreaks_in_range(2..0); + }) + .expect_err("Reversed range should cause an assertion failure."); +} diff --git a/components/layout_2020/flow/inline/mod.rs b/components/layout_2020/flow/inline/mod.rs index 4856e86c4bc..773c93a0a97 100644 --- a/components/layout_2020/flow/inline/mod.rs +++ b/components/layout_2020/flow/inline/mod.rs @@ -70,6 +70,7 @@ pub mod construct; pub mod line; +mod line_breaker; pub mod text_run; use std::cell::OnceCell; @@ -84,6 +85,7 @@ use line::{ layout_line_items, AbsolutelyPositionedLineItem, AtomicLineItem, FloatLineItem, InlineBoxLineItem, LineItem, LineItemLayoutState, LineMetrics, TextRunLineItem, }; +use line_breaker::LineBreaker; use serde::Serialize; use servo_arc::Arc; use style::computed_values::text_wrap_mode::T as TextWrapMode; @@ -1593,13 +1595,13 @@ impl InlineFormattingContext { let text_content: String = builder.text_segments.into_iter().collect(); let mut font_metrics = Vec::new(); - let mut linebreaker = None; + let mut new_linebreaker = LineBreaker::new(text_content.as_str()); inline_formatting_context.foreach(|iter_item| match iter_item { InlineFormattingContextIterItem::Item(InlineLevelBox::TextRun(ref mut text_run)) => { - text_run.break_and_shape( - &text_content[text_run.text_range.clone()], + text_run.segment_and_shape( + &text_content, &layout_context.font_context, - &mut linebreaker, + &mut new_linebreaker, &mut font_metrics, ); }, diff --git a/components/layout_2020/flow/inline/text_run.rs b/components/layout_2020/flow/inline/text_run.rs index 5ac92e91f16..0b563703f46 100644 --- a/components/layout_2020/flow/inline/text_run.rs +++ b/components/layout_2020/flow/inline/text_run.rs @@ -18,13 +18,13 @@ use servo_arc::Arc; use style::computed_values::text_rendering::T as TextRendering; use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse; use style::computed_values::word_break::T as WordBreak; -use style::properties::style_structs::InheritedText; use style::properties::ComputedValues; use style::str::char_is_whitespace; use style::values::computed::OverflowWrap; use unicode_script::Script; -use xi_unicode::{linebreak_property, LineBreakLeafIter}; +use xi_unicode::linebreak_property; +use super::line_breaker::LineBreaker; use super::{FontKeyAndMetrics, InlineFormattingContextState}; use crate::fragment_tree::BaseFragmentInfo; @@ -84,8 +84,8 @@ pub(crate) struct TextRunSegment { #[serde(skip_serializing)] pub script: Script, - /// The range of bytes in the [`TextRun`]'s text that this segment covers. - pub range: ServoRange, + /// The range of bytes in the parent [`super::InlineFormattingContext`]'s text content. + pub range: Range, /// Whether or not the linebreaker said that we should allow a line break at the start of this /// segment. @@ -96,11 +96,11 @@ pub(crate) struct TextRunSegment { } impl TextRunSegment { - fn new(font_index: usize, script: Script, byte_index: ByteIndex) -> Self { + fn new(font_index: usize, script: Script, start_offset: usize) -> Self { Self { script, font_index, - range: ServoRange::new(byte_index, ByteIndex(0)), + range: start_offset..start_offset, runs: Vec::new(), break_at_start: false, } @@ -167,6 +167,158 @@ impl TextRunSegment { ); } } + + fn shape_and_push_range( + &mut self, + range: &Range, + formatting_context_text: &str, + segment_font: &FontRef, + options: &ShapingOptions, + ) { + self.runs.push(GlyphRun { + glyph_store: segment_font.shape_text(&formatting_context_text[range.clone()], options), + range: ServoRange::new( + ByteIndex(range.start as isize), + ByteIndex(range.len() as isize), + ), + }); + } + + /// Shape the text of this [`TextRunSegment`], first finding "words" for the shaper by processing + /// the linebreaks found in the owning [`super::InlineFormattingContext`]. Linebreaks are filtered, + /// based on the style of the parent inline box. + fn shape_text( + &mut self, + parent_style: &ComputedValues, + formatting_context_text: &str, + linebreaker: &mut LineBreaker, + shaping_options: &ShapingOptions, + font: FontRef, + ) { + // Gather the linebreaks that apply to this segment from the inline formatting context's collection + // of line breaks. Also add a simulated break at the end of the segment in order to ensure the final + // piece of text is processed. + let range = self.range.clone(); + let linebreaks = linebreaker.advance_to_linebreaks_in_range(self.range.clone()); + let linebreak_iter = linebreaks.iter().chain(std::iter::once(&range.end)); + + self.runs.clear(); + self.runs.reserve(linebreaks.len()); + self.break_at_start = false; + + let text_style = parent_style.get_inherited_text().clone(); + let can_break_anywhere = text_style.word_break == WordBreak::BreakAll || + text_style.overflow_wrap == OverflowWrap::Anywhere || + text_style.overflow_wrap == OverflowWrap::BreakWord; + + let mut last_slice_end = self.range.start; + for break_index in linebreak_iter { + if *break_index == self.range.start { + self.break_at_start = true; + continue; + } + + // Extend the slice to the next UAX#14 line break opportunity. + let mut slice = last_slice_end..*break_index; + let word = &formatting_context_text[slice.clone()]; + + // Split off any trailing whitespace into a separate glyph run. + let mut whitespace = slice.end..slice.end; + let mut rev_char_indices = word.char_indices().rev().peekable(); + let ends_with_newline = rev_char_indices + .peek() + .map_or(false, |&(_, character)| character == '\n'); + if let Some((first_white_space_index, first_white_space_character)) = rev_char_indices + .take_while(|&(_, character)| char_is_whitespace(character)) + .last() + { + whitespace.start = slice.start + first_white_space_index; + + // If line breaking for a piece of text that has `white-space-collapse: break-spaces` there + // is a line break opportunity *after* every preserved space, but not before. This means + // that we should not split off the first whitespace, unless that white-space is a preserved + // newline. + // + // An exception to this is if the style tells us that we can break in the middle of words. + if text_style.white_space_collapse == WhiteSpaceCollapse::BreakSpaces && + first_white_space_character != '\n' && + !can_break_anywhere + { + whitespace.start += first_white_space_character.len_utf8(); + } + + slice.end = whitespace.start; + } + + // If there's no whitespace and `word-break` is set to `keep-all`, try increasing the slice. + // TODO: This should only happen for CJK text. + let can_break_anywhere = text_style.word_break == WordBreak::BreakAll || + text_style.overflow_wrap == OverflowWrap::Anywhere || + text_style.overflow_wrap == OverflowWrap::BreakWord; + if whitespace.is_empty() && + *break_index != self.range.end && + text_style.word_break == WordBreak::KeepAll && + !can_break_anywhere + { + continue; + } + + // Only advance the last_slice_end if we are not going to try to expand the slice. + last_slice_end = *break_index; + + // Push the non-whitespace part of the range. + if !slice.is_empty() { + self.shape_and_push_range(&slice, formatting_context_text, &font, shaping_options); + } + + if whitespace.is_empty() { + continue; + } + + let mut options = *shaping_options; + options + .flags + .insert(ShapingFlags::IS_WHITESPACE_SHAPING_FLAG); + + // If `white-space-collapse: break-spaces` is active, insert a line breaking opportunity + // between each white space character in the white space that we trimmed off. + if text_style.white_space_collapse == WhiteSpaceCollapse::BreakSpaces { + let start_index = whitespace.start; + for (index, character) in formatting_context_text[whitespace].char_indices() { + let index = start_index + index; + self.shape_and_push_range( + &(index..index + character.len_utf8()), + formatting_context_text, + &font, + &options, + ); + } + continue; + } + + // The breaker breaks after every newline, so either there is none, + // or there is exactly one at the very end. In the latter case, + // split it into a different run. That's because shaping considers + // a newline to have the same advance as a space, but during layout + // we want to treat the newline as having no advance. + if ends_with_newline && whitespace.len() > 1 { + self.shape_and_push_range( + &(whitespace.start..whitespace.end - 1), + formatting_context_text, + &font, + &options, + ); + self.shape_and_push_range( + &(whitespace.end - 1..whitespace.end), + formatting_context_text, + &font, + &options, + ); + } else { + self.shape_and_push_range(&whitespace, formatting_context_text, &font, &options); + } + } + } } impl TextRun { @@ -185,14 +337,13 @@ impl TextRun { } } - pub(super) fn break_and_shape( + pub(super) fn segment_and_shape( &mut self, - text_content: &str, + formatting_context_text: &str, font_context: &FontContext, - linebreaker: &mut Option, + linebreaker: &mut LineBreaker, font_cache: &mut Vec, ) { - let segment_results = self.segment_text(text_content, font_context, font_cache); let inherited_text_style = self.parent_style.get_inherited_text().clone(); let letter_spacing = if inherited_text_style.letter_spacing.0.px() != 0. { Some(app_units::Au::from(inherited_text_style.letter_spacing.0)) @@ -208,13 +359,12 @@ impl TextRun { flags.insert(ShapingFlags::IGNORE_LIGATURES_SHAPING_FLAG); flags.insert(ShapingFlags::DISABLE_KERNING_SHAPING_FLAG) } - if inherited_text_style.word_break == WordBreak::KeepAll { - flags.insert(ShapingFlags::KEEP_ALL_FLAG); - } let specified_word_spacing = &inherited_text_style.word_spacing; let style_word_spacing: Option = specified_word_spacing.to_length().map(|l| l.into()); - let segments = segment_results + + let segments = self + .segment_text_by_font(formatting_context_text, font_context, font_cache) .into_iter() .map(|(mut segment, font)| { let word_spacing = style_word_spacing.unwrap_or_else(|| { @@ -224,20 +374,21 @@ impl TextRun { .unwrap_or(gfx::font::LAST_RESORT_GLYPH_ADVANCE); specified_word_spacing.to_used_value(Au::from_f64_px(space_width)) }); + let shaping_options = ShapingOptions { letter_spacing, word_spacing, script: segment.script, flags, }; - (segment.runs, segment.break_at_start) = break_and_shape( - font, - &text_content[segment.range.begin().0 as usize..segment.range.end().0 as usize], - &inherited_text_style, - &shaping_options, - linebreaker, - ); + segment.shape_text( + &self.parent_style, + formatting_context_text, + linebreaker, + &shaping_options, + font, + ); segment }) .collect(); @@ -249,9 +400,9 @@ impl TextRun { /// font and script. Fonts may differ when glyphs are found in fallback fonts. Fonts are stored /// in the `font_cache` which is a cache of all font keys and metrics used in this /// [`super::InlineFormattingContext`]. - fn segment_text( + fn segment_text_by_font( &mut self, - text_content: &str, + formatting_context_text: &str, font_context: &FontContext, font_cache: &mut Vec, ) -> Vec<(TextRunSegment, FontRef)> { @@ -259,15 +410,16 @@ impl TextRun { let mut current: Option<(TextRunSegment, FontRef)> = None; let mut results = Vec::new(); - let char_iterator = TwoCharsAtATimeIterator::new(text_content.chars()); - let mut next_byte_index = 0; + let text_run_text = &formatting_context_text[self.text_range.clone()]; + let char_iterator = TwoCharsAtATimeIterator::new(text_run_text.chars()); + let mut next_byte_index = self.text_range.start; for (character, next_character) in char_iterator { let current_byte_index = next_byte_index; next_byte_index += character.len_utf8(); let prevents_soft_wrap_opportunity = char_prevents_soft_wrap_opportunity_when_before_or_after_atomic(character); - if current_byte_index == 0 && prevents_soft_wrap_opportunity { + if current_byte_index == self.text_range.start && prevents_soft_wrap_opportunity { self.prevent_soft_wrap_opportunity_at_start = true; } self.prevent_soft_wrap_opportunity_at_end = prevents_soft_wrap_opportunity; @@ -296,17 +448,19 @@ impl TextRun { // Add the new segment and finish the existing one, if we had one. If the first // characters in the run were control characters we may be creating the first - // segment in the middle of the run (ie the start should be 0). + // segment in the middle of the run (ie the start should be the start of this + // text run's text). let start_byte_index = match current { - Some(_) => ByteIndex(current_byte_index as isize), - None => ByteIndex(0_isize), + Some(_) => current_byte_index, + None => self.text_range.start, }; let new = ( TextRunSegment::new(font_index, script, start_byte_index), font, ); if let Some(mut finished) = current.replace(new) { - finished.0.range.extend_to(start_byte_index); + // The end of the previous segment is the start of the next one. + finished.0.range.end = current_byte_index; results.push(finished); } } @@ -317,7 +471,7 @@ impl TextRun { current = font_group.write().first(font_context).map(|font| { let font_index = add_or_get_font(&font, font_cache); ( - TextRunSegment::new(font_index, Script::Common, ByteIndex(0)), + TextRunSegment::new(font_index, Script::Common, self.text_range.start), font, ) }) @@ -325,10 +479,7 @@ impl TextRun { // Extend the last segment to the end of the string and add it to the results. if let Some(mut last_segment) = current.take() { - last_segment - .0 - .range - .extend_to(ByteIndex(text_content.len() as isize)); + last_segment.0.range.end = self.text_range.end; results.push(last_segment); } @@ -463,129 +614,3 @@ where Some((character, self.next_character)) } } - -pub fn break_and_shape( - font: FontRef, - text: &str, - text_style: &InheritedText, - shaping_options: &ShapingOptions, - breaker: &mut Option, -) -> (Vec, bool) { - let mut glyphs = vec![]; - - if breaker.is_none() { - if text.is_empty() { - return (glyphs, true); - } - *breaker = Some(LineBreakLeafIter::new(text, 0)); - } - - let breaker = breaker.as_mut().unwrap(); - - let mut push_range = |range: &Range, options: &ShapingOptions| { - glyphs.push(GlyphRun { - glyph_store: font.shape_text(&text[range.clone()], options), - range: ServoRange::new( - ByteIndex(range.start as isize), - ByteIndex(range.len() as isize), - ), - }); - }; - - let can_break_anywhere = text_style.word_break == WordBreak::BreakAll || - text_style.overflow_wrap == OverflowWrap::Anywhere || - text_style.overflow_wrap == OverflowWrap::BreakWord; - - let mut break_at_zero = false; - let mut last_slice_end = 0; - while last_slice_end != text.len() { - let (break_index, _is_hard_break) = breaker.next(text); - if break_index == 0 { - break_at_zero = true; - } - - // Extend the slice to the next UAX#14 line break opportunity. - let mut slice = last_slice_end..break_index; - let word = &text[slice.clone()]; - - // Split off any trailing whitespace into a separate glyph run. - let mut whitespace = slice.end..slice.end; - let mut rev_char_indices = word.char_indices().rev().peekable(); - let ends_with_newline = rev_char_indices.peek().map_or(false, |&(_, c)| c == '\n'); - if let Some((first_white_space_index, first_white_space_character)) = rev_char_indices - .take_while(|&(_, c)| char_is_whitespace(c)) - .last() - { - whitespace.start = slice.start + first_white_space_index; - - // If line breaking for a piece of text that has `white-space-collapse: break-spaces` there - // is a line break opportunity *after* every preserved space, but not before. This means - // that we should not split off the first whitespace, unless that white-space is a preserved - // newline. - // - // An exception to this is if the style tells us that we can break in the middle of words. - if text_style.white_space_collapse == WhiteSpaceCollapse::BreakSpaces && - first_white_space_character != '\n' && - !can_break_anywhere - { - whitespace.start += first_white_space_character.len_utf8(); - } - - slice.end = whitespace.start; - } - - // If there's no whitespace and `word-break` is set to `keep-all`, try increasing the slice. - // TODO: This should only happen for CJK text. - let can_break_anywhere = text_style.word_break == WordBreak::BreakAll || - text_style.overflow_wrap == OverflowWrap::Anywhere || - text_style.overflow_wrap == OverflowWrap::BreakWord; - if whitespace.is_empty() && - break_index != text.len() && - text_style.word_break == WordBreak::KeepAll && - !can_break_anywhere - { - continue; - } - - // Only advance the last_slice_end if we are not going to try to expand the slice. - last_slice_end = break_index; - - // Push the non-whitespace part of the range. - if !slice.is_empty() { - push_range(&slice, shaping_options); - } - - if whitespace.is_empty() { - continue; - } - - let mut options = *shaping_options; - options - .flags - .insert(ShapingFlags::IS_WHITESPACE_SHAPING_FLAG); - - // If `white-space-collapse: break-spaces` is active, insert a line breaking opportunity - // between each white space character in the white space that we trimmed off. - if text_style.white_space_collapse == WhiteSpaceCollapse::BreakSpaces { - let start_index = whitespace.start; - for (index, character) in text[whitespace].char_indices() { - let index = start_index + index; - push_range(&(index..index + character.len_utf8()), &options); - } - continue; - } - - // The breaker breaks after every newline, so either there is none, - // or there is exactly one at the very end. In the latter case, - // split it into a different run. That's because shaping considers - // a newline to have the same advance as a space, but during layout - // we want to treat the newline as having no advance. - if ends_with_newline && whitespace.len() > 1 { - push_range(&(whitespace.start..whitespace.end - 1), &options); - push_range(&(whitespace.end - 1..whitespace.end), &options); - } else { - push_range(&whitespace, &options); - } - } - (glyphs, break_at_zero) -} diff --git a/tests/wpt/meta/css/css-text/line-break/line-break-anywhere-overrides-uax-behavior-015.html.ini b/tests/wpt/meta/css/css-text/line-break/line-break-anywhere-overrides-uax-behavior-015.html.ini new file mode 100644 index 00000000000..a402bca6a59 --- /dev/null +++ b/tests/wpt/meta/css/css-text/line-break/line-break-anywhere-overrides-uax-behavior-015.html.ini @@ -0,0 +1,2 @@ +[line-break-anywhere-overrides-uax-behavior-015.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-break/line-break-normal-015b.xht.ini b/tests/wpt/meta/css/css-text/line-break/line-break-normal-015b.xht.ini deleted file mode 100644 index 45a7609fed1..00000000000 --- a/tests/wpt/meta/css/css-text/line-break/line-break-normal-015b.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-break-normal-015b.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-break/line-break-strict-015b.xht.ini b/tests/wpt/meta/css/css-text/line-break/line-break-strict-015b.xht.ini deleted file mode 100644 index fcc474b48ee..00000000000 --- a/tests/wpt/meta/css/css-text/line-break/line-break-strict-015b.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-break-strict-015b.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-013.html.ini b/tests/wpt/meta/css/css-text/line-breaking/line-breaking-013.html.ini deleted file mode 100644 index e6270623da9..00000000000 --- a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-013.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-breaking-013.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-014.html.ini b/tests/wpt/meta/css/css-text/line-breaking/line-breaking-014.html.ini deleted file mode 100644 index d9ffea5b5ee..00000000000 --- a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-014.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-breaking-014.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-021.html.ini b/tests/wpt/meta/css/css-text/line-breaking/line-breaking-021.html.ini deleted file mode 100644 index 0301f562755..00000000000 --- a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-021.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-breaking-021.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-024.html.ini b/tests/wpt/meta/css/css-text/line-breaking/line-breaking-024.html.ini deleted file mode 100644 index c90a18a4db9..00000000000 --- a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-024.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-breaking-024.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-025.html.ini b/tests/wpt/meta/css/css-text/line-breaking/line-breaking-025.html.ini deleted file mode 100644 index 490e03342d8..00000000000 --- a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-025.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-breaking-025.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-026.html.ini b/tests/wpt/meta/css/css-text/line-breaking/line-breaking-026.html.ini deleted file mode 100644 index 885652a0c25..00000000000 --- a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-026.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-breaking-026.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-027.html.ini b/tests/wpt/meta/css/css-text/line-breaking/line-breaking-027.html.ini deleted file mode 100644 index 7b586c55a96..00000000000 --- a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-027.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-breaking-027.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-atomic-010.html.ini b/tests/wpt/meta/css/css-text/line-breaking/line-breaking-atomic-010.html.ini deleted file mode 100644 index cf5b8690fa8..00000000000 --- a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-atomic-010.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-breaking-atomic-010.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-atomic-011.html.ini b/tests/wpt/meta/css/css-text/line-breaking/line-breaking-atomic-011.html.ini deleted file mode 100644 index 239a3ccdfcf..00000000000 --- a/tests/wpt/meta/css/css-text/line-breaking/line-breaking-atomic-011.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[line-breaking-atomic-011.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-001-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-001-ref.html.ini deleted file mode 100644 index 4dd39974a1f..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-001-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-001-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-002-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-002-ref.html.ini deleted file mode 100644 index ba8f3bd25c6..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-002-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-002-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-003-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-003-ref.html.ini deleted file mode 100644 index d7596d53dcd..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-003-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-003-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-008-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-008-ref.html.ini deleted file mode 100644 index 72e4697e0c4..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-008-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-008-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-009-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-009-ref.html.ini deleted file mode 100644 index a454e7544d1..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-009-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-009-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-010-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-010-ref.html.ini deleted file mode 100644 index 5cd24f212ed..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-010-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-010-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-011-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-011-ref.html.ini deleted file mode 100644 index ae855864b96..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-011-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-011-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-014-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-014-ref.html.ini deleted file mode 100644 index 720907a8f2e..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-014-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-014-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-016-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-016-ref.html.ini deleted file mode 100644 index 1e260bb1a34..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-016-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-016-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-020-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-020-ref.html.ini deleted file mode 100644 index 43014fcbcca..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-020-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-020-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-021-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-021-ref.html.ini deleted file mode 100644 index b99803ef7f7..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-021-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-021-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/reference/shaping-022-ref.html.ini b/tests/wpt/meta/css/css-text/shaping/reference/shaping-022-ref.html.ini deleted file mode 100644 index 11850dc34a2..00000000000 --- a/tests/wpt/meta/css/css-text/shaping/reference/shaping-022-ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[shaping-022-ref.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-001.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-001.html.ini new file mode 100644 index 00000000000..b2a8c375d53 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-001.html.ini @@ -0,0 +1,2 @@ +[shaping-001.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-002.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-002.html.ini new file mode 100644 index 00000000000..8a834e9d091 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-002.html.ini @@ -0,0 +1,2 @@ +[shaping-002.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-003.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-003.html.ini new file mode 100644 index 00000000000..10dbd45d9d5 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-003.html.ini @@ -0,0 +1,2 @@ +[shaping-003.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-008.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-008.html.ini new file mode 100644 index 00000000000..ff792047b90 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-008.html.ini @@ -0,0 +1,2 @@ +[shaping-008.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-014.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-014.html.ini new file mode 100644 index 00000000000..fea8dc15852 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-014.html.ini @@ -0,0 +1,2 @@ +[shaping-014.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-016.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-016.html.ini new file mode 100644 index 00000000000..3080b2780f9 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-016.html.ini @@ -0,0 +1,2 @@ +[shaping-016.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-017.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-017.html.ini new file mode 100644 index 00000000000..b1a14fb2c12 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-017.html.ini @@ -0,0 +1,2 @@ +[shaping-017.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-018.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-018.html.ini new file mode 100644 index 00000000000..58570ef90b9 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-018.html.ini @@ -0,0 +1,2 @@ +[shaping-018.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-020.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-020.html.ini new file mode 100644 index 00000000000..b331edad0ab --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-020.html.ini @@ -0,0 +1,2 @@ +[shaping-020.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-021.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-021.html.ini new file mode 100644 index 00000000000..051cd9c380a --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-021.html.ini @@ -0,0 +1,2 @@ +[shaping-021.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-022.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-022.html.ini new file mode 100644 index 00000000000..ce3ec82e5e4 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-022.html.ini @@ -0,0 +1,2 @@ +[shaping-022.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-023.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-023.html.ini new file mode 100644 index 00000000000..44e9d85cdf3 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-023.html.ini @@ -0,0 +1,2 @@ +[shaping-023.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-024.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-024.html.ini new file mode 100644 index 00000000000..0d4e1eba867 --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-024.html.ini @@ -0,0 +1,2 @@ +[shaping-024.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/shaping/shaping-025.html.ini b/tests/wpt/meta/css/css-text/shaping/shaping-025.html.ini new file mode 100644 index 00000000000..23a42235a3b --- /dev/null +++ b/tests/wpt/meta/css/css-text/shaping/shaping-025.html.ini @@ -0,0 +1,2 @@ +[shaping-025.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/word-break/word-break-manual-001.html.ini b/tests/wpt/meta/css/css-text/word-break/word-break-manual-001.html.ini new file mode 100644 index 00000000000..3f3a90f56a7 --- /dev/null +++ b/tests/wpt/meta/css/css-text/word-break/word-break-manual-001.html.ini @@ -0,0 +1,2 @@ +[word-break-manual-001.html] + expected: FAIL diff --git a/tests/wpt/meta/css/css-text/word-break/word-break-normal-002.html.ini b/tests/wpt/meta/css/css-text/word-break/word-break-normal-002.html.ini deleted file mode 100644 index db03fede0af..00000000000 --- a/tests/wpt/meta/css/css-text/word-break/word-break-normal-002.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[word-break-normal-002.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/word-break/word-break-normal-003.html.ini b/tests/wpt/meta/css/css-text/word-break/word-break-normal-003.html.ini deleted file mode 100644 index 795ac13c70b..00000000000 --- a/tests/wpt/meta/css/css-text/word-break/word-break-normal-003.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[word-break-normal-003.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/word-break/word-break-normal-th-000.html.ini b/tests/wpt/meta/css/css-text/word-break/word-break-normal-th-000.html.ini deleted file mode 100644 index db1cf94a0b8..00000000000 --- a/tests/wpt/meta/css/css-text/word-break/word-break-normal-th-000.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[word-break-normal-th-000.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/word-break/word-break-normal-th-001.html.ini b/tests/wpt/meta/css/css-text/word-break/word-break-normal-th-001.html.ini deleted file mode 100644 index ae690e382e8..00000000000 --- a/tests/wpt/meta/css/css-text/word-break/word-break-normal-th-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[word-break-normal-th-001.html] - expected: FAIL