Auto merge of #10246 - mbrubeck:strip-leading, r=pcwalton

Restore stripped whitespace before reflowing text fragments

Fixes #10200. r? @pcwalton

Note: The reftest uses a transition of non-zero duration, because I couldn't find any other way to reproduce the bug.  Unfortunately this makes it unreliable in debug builds. I tried to fix this using reftest-wait with setTimeout and requestAnimationFrame, but it still wouldn't complete the animation consistently.  To make the test work in debug builds we may need `transitionend` events (#10245) or a different way to reproduce the bug.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10246)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-03-29 14:30:40 +05:30
commit 159be44193
5 changed files with 121 additions and 6 deletions

View file

@ -1692,22 +1692,39 @@ impl Fragment {
(&mut SpecificFragmentInfo::ScannedText(ref mut this_info),
&SpecificFragmentInfo::ScannedText(ref other_info)) => {
debug_assert!(util::arc_ptr_eq(&this_info.run, &other_info.run));
this_info.range.extend_to(other_info.range_end_including_stripped_whitespace);
this_info.content_size.inline =
this_info.run.metrics_for_range(&this_info.range).advance_width;
this_info.range_end_including_stripped_whitespace =
other_info.range_end_including_stripped_whitespace;
if other_info.requires_line_break_afterward_if_wrapping_on_newlines() {
this_info.flags.insert(REQUIRES_LINE_BREAK_AFTERWARD_IF_WRAPPING_ON_NEWLINES);
}
self.border_padding.inline_end = next_fragment.border_padding.inline_end;
self.border_box.size.inline = this_info.content_size.inline +
self.border_padding.inline_start_end();
}
_ => panic!("Can only merge two scanned-text fragments!"),
}
self.reset_text_range_and_inline_size();
self.meld_with_next_inline_fragment(&next_fragment);
}
/// Restore any whitespace that was stripped from a text fragment, and recompute inline metrics
/// if necessary.
pub fn reset_text_range_and_inline_size(&mut self) {
match &mut self.specific {
&mut SpecificFragmentInfo::ScannedText(ref mut info) => {
// FIXME (mbrubeck): Do we need to restore leading too?
let range_end = info.range_end_including_stripped_whitespace;
if info.range.end() == range_end {
return
}
info.range.extend_to(range_end);
info.content_size.inline = info.run.metrics_for_range(&info.range).advance_width;
self.border_box.size.inline = info.content_size.inline +
self.border_padding.inline_start_end();
}
_ => {}
}
}
/// Assigns replaced inline-size, padding, and margins for this fragment only if it is replaced
/// content per CSS 2.1 § 10.3.2.
pub fn assign_replaced_inline_size_if_necessary(&mut self, container_inline_size: Au) {

View file

@ -527,6 +527,9 @@ impl LineBreaker {
mut fragment: Fragment,
flow: &InlineFlow,
layout_context: &LayoutContext) {
// Undo any whitespace stripping from previous reflows.
fragment.reset_text_range_and_inline_size();
// Determine initial placement for the fragment if we need to.
//
// Also, determine whether we can legally break the line before, or inside, this fragment.

View file

@ -2084,6 +2084,30 @@
"url": "/_mozilla/css/incremental_text_color_a.html"
}
],
"css/incremental_trailing_whitespace_a.html": [
{
"path": "css/incremental_trailing_whitespace_a.html",
"references": [
[
"/_mozilla/css/incremental_trailing_whitespace_ref.html",
"=="
]
],
"url": "/_mozilla/css/incremental_trailing_whitespace_a.html"
}
],
"css/incremental_trailing_whitespace_ref.html": [
{
"path": "css/incremental_trailing_whitespace_ref.html",
"references": [
[
"/_mozilla/css/incremental_trailing_whitespace_ref.html",
"=="
]
],
"url": "/_mozilla/css/incremental_trailing_whitespace_ref.html"
}
],
"css/incremental_visibility_a.html": [
{
"path": "css/incremental_visibility_a.html",
@ -8422,6 +8446,30 @@
"url": "/_mozilla/css/incremental_text_color_a.html"
}
],
"css/incremental_trailing_whitespace_a.html": [
{
"path": "css/incremental_trailing_whitespace_a.html",
"references": [
[
"/_mozilla/css/incremental_trailing_whitespace_ref.html",
"=="
]
],
"url": "/_mozilla/css/incremental_trailing_whitespace_a.html"
}
],
"css/incremental_trailing_whitespace_ref.html": [
{
"path": "css/incremental_trailing_whitespace_ref.html",
"references": [
[
"/_mozilla/css/incremental_trailing_whitespace_ref.html",
"=="
]
],
"url": "/_mozilla/css/incremental_trailing_whitespace_ref.html"
}
],
"css/incremental_visibility_a.html": [
{
"path": "css/incremental_visibility_a.html",

View file

@ -0,0 +1,27 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>incremental trailing whitespace test</title>
<link rel="match" href="incremental_trailing_whitespace_ref.html">
<style>
#a {
border: 0 solid;
}
#a.go {
border-bottom-width: 4px !important;
}
</style>
</head>
<body>
<div style="display: inline-block; width: 33.3333%;"></div>
<div style="display: inline-block; width: 66.66%;">
<div id="a" style="transition: all .1s ease-out;">Hello</div>
</div>
<script>
document.body.offsetWidth; // force layout
document.querySelector('#a').classList.add('go');
// FIXME (#10245): Wait for the "transitionend" event.
</script>
</body>
</html>

View file

@ -0,0 +1,20 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>incremental trailing whitespace reference</title>
<link rel="match" href="incremental_trailing_whitespace_ref.html">
<style>
#a {
border: 0 solid;
border-bottom-width: 4px !important;
}
</style>
</head>
<body>
<div style="display: inline-block; width: 33.3333%;"></div>
<div style="display: inline-block; width: 66.66%;">
<div id="a">Hello</div>
</div>
</body>
</html>