Commit 8d47c1f6 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

Move inline box placeholders to before children

This patch changes |NGInlineLayoutAlgorithm| to place inline
box placeholders to before children.

Before this patch, they were created after children, only
when the inline box is not culled. This change:
1. Reduces the insertion to |Vector| in |CreateBoxFragments|,
   which involves memory copy. This is not common today, but
   will be common when |NGFragmentItem| is enabled.
2. Allows easier implementation to "disable culled inline
   boxes" when |NGFragmetnItem| is enabled.

There should be no behavior changes.

Bug: 982194
Change-Id: I0d7077e4c9b78b99276afc2e7919258b33bd4ea6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1980663Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#728439}
parent 02d4b120
......@@ -82,15 +82,15 @@ void NGFragmentItemsBuilder::AddItems(Child* child_begin, Child* child_end) {
// Floats are in the fragment tree, not in the fragment item list.
DCHECK(!box.IsFloating());
// Take the fast path when we know |child| does not have child items.
if (child.children_count <= 1) {
// Compute |has_floating_descendants_for_paint_| to optimize tree
// traversal in paint.
if (!has_floating_descendants_for_paint_ && box.IsFloating())
has_floating_descendants_for_paint_ = true;
DCHECK(child.HasBidiLevel());
items_.push_back(std::make_unique<NGFragmentItem>(
box, 1, DirectionFromLevel(child.bidi_level)));
box, 1, child.ResolvedDirection()));
offsets_.push_back(child.offset);
++child_iter;
continue;
......@@ -116,9 +116,8 @@ void NGFragmentItemsBuilder::AddItems(Child* child_begin, Child* child_end) {
wtf_size_t item_count = items_.size() - box_start_index;
// Create an item for the start of the box.
DCHECK(child.HasBidiLevel());
items_[box_start_index] = std::make_unique<NGFragmentItem>(
box, item_count, DirectionFromLevel(child.bidi_level));
box, item_count, child.ResolvedDirection());
continue;
}
......
......@@ -105,7 +105,8 @@ bool NGInlineBoxState::CanAddTextOfStyle(
NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems(
const ComputedStyle& line_style,
FontBaseline baseline_type,
bool line_height_quirk) {
bool line_height_quirk,
NGLineBoxFragmentBuilder::ChildList* line_box) {
if (stack_.IsEmpty()) {
// For the first line, push a box state for the line itself.
stack_.resize(1);
......@@ -114,7 +115,9 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems(
} else {
// For the following lines, clear states that are not shared across lines.
for (NGInlineBoxState& box : stack_) {
box.fragment_start = 0;
box.fragment_start = line_box->size();
if (&box != stack_.begin())
AddBoxFragmentPlaceholder(&box, line_box, baseline_type);
if (!line_height_quirk)
box.metrics = box.text_metrics;
else
......@@ -133,15 +136,15 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems(
DCHECK(box_data_list_.IsEmpty());
// Initialize the box state for the line box.
NGInlineBoxState& line_box = LineBoxState();
if (line_box.style != &line_style) {
line_box.style = &line_style;
NGInlineBoxState& line_box_state = LineBoxState();
if (line_box_state.style != &line_style) {
line_box_state.style = &line_style;
// Use a "strut" (a zero-width inline box with the element's font and
// line height properties) as the initial metrics for the line box.
// https://drafts.csswg.org/css2/visudet.html#strut
if (!line_height_quirk)
line_box.ComputeTextMetrics(line_style, baseline_type);
line_box_state.ComputeTextMetrics(line_style, baseline_type);
}
return &stack_.back();
......@@ -150,31 +153,32 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems(
NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag(
const NGInlineItem& item,
const NGInlineItemResult& item_result,
const NGLineBoxFragmentBuilder::ChildList& line_box) {
DCHECK(item.Style());
NGInlineBoxState* box = OnOpenTag(*item.Style(), line_box);
box->item = &item;
if (item.ShouldCreateBoxFragment())
box->SetNeedsBoxFragment();
// Compute box properties regardless of needs_box_fragment since close tag may
// also set needs_box_fragment.
box->has_start_edge = item_result.has_edge;
box->margin_inline_start = item_result.margins.inline_start;
box->margin_inline_end = item_result.margins.inline_end;
box->borders = item_result.borders;
box->padding = item_result.padding;
FontBaseline baseline_type,
NGLineBoxFragmentBuilder::ChildList* line_box) {
NGInlineBoxState* box =
OnOpenTag(item, item_result, baseline_type, *line_box);
AddBoxFragmentPlaceholder(box, line_box, baseline_type);
return box;
}
NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag(
const ComputedStyle& style,
const NGInlineItem& item,
const NGInlineItemResult& item_result,
FontBaseline baseline_type,
const NGLineBoxFragmentBuilder::ChildList& line_box) {
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
stack_.resize(stack_.size() + 1);
NGInlineBoxState* box = &stack_.back();
box->fragment_start = line_box.size();
box->style = &style;
box->item = &item;
box->needs_box_fragment = item.ShouldCreateBoxFragment();
box->has_start_edge = item_result.has_edge;
box->margin_inline_start = item_result.margins.inline_start;
box->margin_inline_end = item_result.margins.inline_end;
box->borders = item_result.borders;
box->padding = item_result.padding;
return box;
}
......@@ -209,8 +213,8 @@ void NGInlineLayoutStateStack::OnEndPlaceItems(
// Copy the final offset to |box_data_list_|.
for (BoxData& box_data : box_data_list_) {
const NGLineBoxFragmentBuilder::Child& placeholder =
(*line_box)[box_data.fragment_end];
DCHECK(!placeholder.HasFragment());
(*line_box)[box_data.fragment_start];
DCHECK(placeholder.IsPlaceholder());
box_data.offset = placeholder.offset;
}
}
......@@ -220,7 +224,7 @@ void NGInlineLayoutStateStack::EndBoxState(
NGLineBoxFragmentBuilder::ChildList* line_box,
FontBaseline baseline_type) {
if (box->needs_box_fragment)
AddBoxFragmentPlaceholder(box, line_box, baseline_type);
AddBoxData(box, line_box);
PositionPending position_pending =
ApplyBaselineShift(box, line_box, baseline_type);
......@@ -251,12 +255,11 @@ void NGInlineLayoutStateStack::AddBoxFragmentPlaceholder(
NGInlineBoxState* box,
NGLineBoxFragmentBuilder::ChildList* line_box,
FontBaseline baseline_type) {
DCHECK(box->needs_box_fragment);
DCHECK(box->style);
const ComputedStyle& style = *box->style;
LogicalOffset offset;
LogicalSize size;
LayoutUnit block_offset;
LayoutUnit block_size;
if (!is_empty_line_) {
// The inline box should have the height of the font metrics without the
// line-height property. Compute from style because |box->metrics| includes
......@@ -265,16 +268,29 @@ void NGInlineLayoutStateStack::AddBoxFragmentPlaceholder(
// Extend the block direction of the box by borders and paddings. Inline
// direction is already included into positions in NGLineBreaker.
offset.block_offset =
block_offset =
-metrics.ascent - (box->borders.line_over + box->padding.line_over);
size.block_size = metrics.LineHeight() + box->borders.BlockSum() +
box->padding.BlockSum();
block_size = metrics.LineHeight() + box->borders.BlockSum() +
box->padding.BlockSum();
}
line_box->AddChild(block_offset, block_size);
DCHECK((*line_box)[line_box->size() - 1].IsPlaceholder());
}
unsigned fragment_end = line_box->size();
// Add a |BoxData|, for each close-tag that needs a box fragment.
void NGInlineLayoutStateStack::AddBoxData(
NGInlineBoxState* box,
NGLineBoxFragmentBuilder::ChildList* line_box) {
DCHECK(box->needs_box_fragment);
DCHECK(box->style);
const ComputedStyle& style = *box->style;
NGLineBoxFragmentBuilder::Child& placeholder =
(*line_box)[box->fragment_start];
DCHECK(placeholder.IsPlaceholder());
const unsigned fragment_end = line_box->size();
DCHECK(box->item);
BoxData& box_data = box_data_list_.emplace_back(
box->fragment_start, fragment_end, box->item, size);
box->fragment_start, fragment_end, box->item, placeholder.size);
box_data.padding = box->padding;
if (box->has_start_edge) {
box_data.has_line_left_edge = true;
......@@ -297,31 +313,23 @@ void NGInlineLayoutStateStack::AddBoxFragmentPlaceholder(
box_data.margin_border_padding_line_right);
}
if (fragment_end > box->fragment_start) {
// The start is marked only in BoxData, while end is marked
// in both BoxData and the list itself.
// With a list of 4 text fragments:
// | 0 | 1 | 2 | 3 |
// |text0|text1|text2|text3|
// By adding a BoxData(2,4) (end is exclusive), it becomes:
// | 0 | 1 | 2 | 3 | 4 |
// |text0|text1|text2|text3|null |
// The "null" is added to the list to compute baseline shift of the box
// separately from text fragments.
line_box->AddChild(offset);
} else {
// Do not defer creating a box fragment if this is an empty inline box.
// An empty box fragment is still flat that we do not have to defer.
// Also, placeholders cannot be reordred if empty.
offset.inline_offset += box_data.margin_line_left;
LayoutUnit advance = box_data.margin_border_padding_line_left +
box_data.margin_border_padding_line_right;
box_data.size.inline_size =
advance - box_data.margin_line_left - box_data.margin_line_right;
line_box->AddChild(box_data.CreateBoxFragment(line_box), offset, advance,
/* bidi_level */ 0);
box_data_list_.pop_back();
}
DCHECK((*line_box)[box->fragment_start].IsPlaceholder());
DCHECK_GT(fragment_end, box->fragment_start);
if (fragment_end > box->fragment_start + 1)
return;
// Do not defer creating a box fragment if this is an empty inline box.
// An empty box fragment is still flat that we do not have to defer.
// Also, placeholders cannot be reordred if empty.
placeholder.offset.inline_offset += box_data.margin_line_left;
LayoutUnit advance = box_data.margin_border_padding_line_left +
box_data.margin_border_padding_line_right;
box_data.size.inline_size =
advance - box_data.margin_line_left - box_data.margin_line_right;
placeholder.layout_result = box_data.CreateBoxFragment(line_box);
placeholder.inline_size = advance;
DCHECK(!placeholder.children_count);
box_data_list_.pop_back();
}
void NGInlineLayoutStateStack::ChildInserted(unsigned index) {
......@@ -348,6 +356,7 @@ void NGInlineLayoutStateStack::PrepareForReorder(
unsigned box_data_index = 0;
for (const BoxData& box_data : box_data_list_) {
box_data_index++;
DCHECK((*line_box)[box_data.fragment_start].IsPlaceholder());
for (unsigned i = box_data.fragment_start; i < box_data.fragment_end; i++) {
NGLineBoxFragmentBuilder::Child& child = (*line_box)[i];
if (!child.box_data_index)
......@@ -358,10 +367,11 @@ void NGInlineLayoutStateStack::PrepareForReorder(
// When boxes are nested, placeholders have indexes to which box it should be
// added. Copy them to BoxData.
for (BoxData& box_data : box_data_list_) {
const NGLineBoxFragmentBuilder::Child& placeholder =
(*line_box)[box_data.fragment_end];
DCHECK(!placeholder.HasFragment());
box_data.parent_box_data_index = placeholder.box_data_index;
if (!box_data.fragment_start)
continue;
const NGLineBoxFragmentBuilder::Child& parent =
(*line_box)[box_data.fragment_start - 1];
box_data.parent_box_data_index = parent.box_data_index;
}
}
......@@ -569,24 +579,20 @@ void NGInlineLayoutStateStack::CreateBoxFragments(
unsigned end = box_data.fragment_end;
DCHECK_GT(end, start);
NGLineBoxFragmentBuilder::Child* child = &(*line_box)[start];
scoped_refptr<const NGLayoutResult> box_fragment =
box_data.CreateBoxFragment(line_box);
if (!child->HasFragment()) {
if (child->IsPlaceholder()) {
child->layout_result = std::move(box_fragment);
child->offset = box_data.offset;
child->children_count = end - start;
} else {
// In most cases, |start_child| is moved to the children of the box, and
// is empty. It's not empty when it's out-of-flow. Insert in such case.
// TODO(kojii): With |NGFragmentItem|, all cases hit this code. Consider
// creating an empty item beforehand to avoid inserting.
line_box->InsertChild(start, std::move(box_fragment), box_data.offset,
LayoutUnit(), 0);
ChildInserted(start + 1);
child = &(*line_box)[start];
child->children_count = end - start + 1;
continue;
}
// |AddBoxFragmentPlaceholder| adds a placeholder at |fragment_start|, but
// bidi reordering may move it. Insert in such case.
line_box->InsertChild(start, std::move(box_fragment), box_data.offset,
end - start + 1);
ChildInserted(start + 1);
}
box_data_list_.clear();
......@@ -826,8 +832,10 @@ NGLineHeightMetrics NGInlineLayoutStateStack::MetricsForTopAndBottomAlign(
continue;
// |block_offset| is the top position when the baseline is at 0.
LayoutUnit box_ascent =
-line_box[box_data.fragment_end].offset.block_offset;
const NGLineBoxFragmentBuilder::Child& placeholder =
line_box[box_data.fragment_start];
DCHECK(placeholder.IsPlaceholder());
LayoutUnit box_ascent = -placeholder.offset.block_offset;
NGLineHeightMetrics box_metrics(box_ascent,
box_data.size.block_size - box_ascent);
// The top/bottom of inline boxes should not include their paddings.
......@@ -892,6 +900,8 @@ void NGInlineBoxState::CheckSame(const NGInlineBoxState& other) const {
DCHECK_EQ(needs_box_fragment, other.needs_box_fragment);
// TODO: fast/borders/rtl-border-05.html
// if (needs_box_fragment)
DCHECK_EQ(has_start_edge, other.has_start_edge);
// |has_end_edge| may not match because it will be computed in |OnCloseTag|.
......
......@@ -116,14 +116,22 @@ class CORE_EXPORT NGInlineLayoutStateStack {
// Initialize the box state stack for a new line.
// @return The initial box state for the line.
NGInlineBoxState* OnBeginPlaceItems(const ComputedStyle&, FontBaseline, bool);
NGInlineBoxState* OnBeginPlaceItems(
const ComputedStyle&,
FontBaseline,
bool line_height_quirk,
NGLineBoxFragmentBuilder::ChildList* line_box);
// Push a box state stack.
NGInlineBoxState* OnOpenTag(const NGInlineItem&,
const NGInlineItemResult&,
FontBaseline baseline_type,
const NGLineBoxFragmentBuilder::ChildList&);
NGInlineBoxState* OnOpenTag(const ComputedStyle&,
const NGLineBoxFragmentBuilder::ChildList&);
// This variation adds a box placeholder to |line_box|.
NGInlineBoxState* OnOpenTag(const NGInlineItem&,
const NGInlineItemResult&,
FontBaseline baseline_type,
NGLineBoxFragmentBuilder::ChildList* line_box);
// Pop a box state stack.
NGInlineBoxState* OnCloseTag(NGLineBoxFragmentBuilder::ChildList*,
......@@ -182,6 +190,7 @@ class CORE_EXPORT NGInlineLayoutStateStack {
void AddBoxFragmentPlaceholder(NGInlineBoxState*,
NGLineBoxFragmentBuilder::ChildList*,
FontBaseline);
void AddBoxData(NGInlineBoxState*, NGLineBoxFragmentBuilder::ChildList*);
enum PositionPending { kPositionNotPending, kPositionPending };
......
......@@ -77,8 +77,10 @@ NGInlineLayoutAlgorithm::~NGInlineLayoutAlgorithm() = default;
NGInlineBoxState* NGInlineLayoutAlgorithm::HandleOpenTag(
const NGInlineItem& item,
const NGInlineItemResult& item_result,
NGLineBoxFragmentBuilder::ChildList* line_box,
NGInlineLayoutStateStack* box_states) const {
NGInlineBoxState* box = box_states->OnOpenTag(item, item_result, line_box_);
NGInlineBoxState* box =
box_states->OnOpenTag(item, item_result, baseline_type_, line_box);
// Compute text metrics for all inline boxes since even empty inlines
// influence the line height, except when quirks mode and the box is empty
// for the purpose of empty block calculation.
......@@ -160,12 +162,13 @@ void NGInlineLayoutAlgorithm::RebuildBoxStates(
}
// Create box states for tags that are not closed yet.
NGLineBoxFragmentBuilder::ChildList line_box;
box_states->OnBeginPlaceItems(line_info.LineStyle(), baseline_type_,
quirks_mode_);
quirks_mode_, &line_box);
for (const NGInlineItem* item : open_items) {
NGInlineItemResult item_result;
NGLineBreaker::ComputeOpenTagResult(*item, ConstraintSpace(), &item_result);
HandleOpenTag(*item, item_result, box_states);
HandleOpenTag(*item, item_result, &line_box, box_states);
}
}
......@@ -175,9 +178,9 @@ void NGInlineLayoutAlgorithm::CheckBoxStates(
const NGInlineBreakToken* break_token) const {
NGInlineLayoutStateStack rebuilt;
RebuildBoxStates(line_info, break_token, &rebuilt);
rebuilt.OnBeginPlaceItems(line_info.LineStyle(), baseline_type_,
quirks_mode_);
NGLineBoxFragmentBuilder::ChildList line_box;
rebuilt.OnBeginPlaceItems(line_info.LineStyle(), baseline_type_, quirks_mode_,
&line_box);
DCHECK(box_states_);
box_states_->CheckSame(rebuilt);
}
......@@ -201,8 +204,8 @@ void NGInlineLayoutAlgorithm::CreateLine(
// The baseline is adjusted after the height of the line box is computed.
const ComputedStyle& line_style = line_info->LineStyle();
box_states_->SetIsEmptyLine(line_info->IsEmptyLine());
NGInlineBoxState* box =
box_states_->OnBeginPlaceItems(line_style, baseline_type_, quirks_mode_);
NGInlineBoxState* box = box_states_->OnBeginPlaceItems(
line_style, baseline_type_, quirks_mode_, &line_box_);
#if DCHECK_IS_ON()
if (is_box_states_from_context_)
CheckBoxStates(*line_info, BreakToken());
......@@ -261,7 +264,7 @@ void NGInlineLayoutAlgorithm::CreateLine(
} else if (item.Type() == NGInlineItem::kControl) {
PlaceControlItem(item, *line_info, &item_result, box);
} else if (item.Type() == NGInlineItem::kOpenTag) {
box = HandleOpenTag(item, item_result, box_states_);
box = HandleOpenTag(item, item_result, &line_box_, box_states_);
} else if (item.Type() == NGInlineItem::kCloseTag) {
box = HandleCloseTag(item, item_result, box);
} else if (item.Type() == NGInlineItem::kAtomicInline) {
......@@ -459,7 +462,8 @@ NGInlineBoxState* NGInlineLayoutAlgorithm::PlaceAtomicInline(
// position += item_result->margins.LineLeft(style.Direction());
item_result->has_edge = true;
NGInlineBoxState* box = box_states_->OnOpenTag(item, *item_result, line_box_);
NGInlineBoxState* box =
box_states_->OnOpenTag(item, *item_result, baseline_type_, line_box_);
PlaceLayoutResult(item_result, box, box->margin_inline_start);
return box_states_->OnCloseTag(&line_box_, box, baseline_type_);
}
......@@ -485,7 +489,8 @@ void NGInlineLayoutAlgorithm::PlaceLayoutResult(NGInlineItemResult* item_result,
LayoutUnit line_top = item_result->margins.line_over - metrics.ascent;
line_box_.AddChild(std::move(item_result->layout_result),
LogicalOffset{inline_offset, line_top},
item_result->inline_size, item.BidiLevel());
item_result->inline_size, /* children_count */ 0,
item.BidiLevel());
}
// Place all out-of-flow objects in |line_box_|.
......@@ -1086,22 +1091,9 @@ void NGInlineLayoutAlgorithm::BidiReorder(TextDirection base_direction) {
// For opaque items, copy bidi levels from adjacent items.
if (has_opaque_items) {
UBiDiLevel last_level = levels.front();
if (last_level == kOpaqueBidiLevel) {
for (const UBiDiLevel level : levels) {
if (level != kOpaqueBidiLevel) {
last_level = level;
break;
}
}
}
// If all items are opaque, use the base direction.
if (last_level == kOpaqueBidiLevel) {
if (IsLtr(base_direction))
return;
last_level = 1;
}
for (UBiDiLevel& level : levels) {
// Use the paragraph level for trailing opaque items.
UBiDiLevel last_level = IsLtr(base_direction) ? 0 : 1;
for (UBiDiLevel& level : base::Reversed(levels)) {
if (level == kOpaqueBidiLevel)
level = last_level;
else
......
......@@ -69,6 +69,7 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
NGInlineBoxState* HandleOpenTag(const NGInlineItem&,
const NGInlineItemResult&,
NGLineBoxFragmentBuilder::ChildList*,
NGInlineLayoutStateStack*) const;
NGInlineBoxState* HandleCloseTag(const NGInlineItem&,
const NGInlineItemResult&,
......
......@@ -82,6 +82,7 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
// The offset of the border box, initially in this child coordinate system.
// |ComputeInlinePositions()| converts it to the offset within the line box.
LogicalOffset offset;
LogicalSize size;
// The offset of a positioned float wrt. the root BFC. This should only be
// set for positioned floats.
NGBfcOffset bfc_offset;
......@@ -103,7 +104,8 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
Child() = default;
// Create a placeholder. A placeholder does not have a fragment nor a bidi
// level.
Child(LogicalOffset offset) : offset(offset) {}
Child(LayoutUnit block_offset, LayoutUnit block_size)
: offset(LayoutUnit(), block_offset), size(LayoutUnit(), block_size) {}
// Crete a bidi control. A bidi control does not have a fragment, but has
// bidi level and affects bidi reordering.
Child(UBiDiLevel bidi_level) : bidi_level(bidi_level) {}
......@@ -111,10 +113,12 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
Child(scoped_refptr<const NGLayoutResult> layout_result,
LogicalOffset offset,
LayoutUnit inline_size,
unsigned children_count,
UBiDiLevel bidi_level)
: layout_result(std::move(layout_result)),
offset(offset),
inline_size(inline_size),
children_count(children_count),
bidi_level(bidi_level) {}
// Create an in-flow |NGPhysicalTextFragment|.
Child(scoped_refptr<const NGPhysicalTextFragment> fragment,
......@@ -185,6 +189,12 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
return &layout_result->PhysicalFragment();
return fragment.get();
}
TextDirection ResolvedDirection() const {
// Inline boxes are not leaves that they don't have directions.
DCHECK(HasBidiLevel() || layout_result->PhysicalFragment().IsInlineBox());
return HasBidiLevel() ? DirectionFromLevel(bidi_level)
: TextDirection::kLtr;
}
};
// A vector of Child.
......@@ -235,10 +245,10 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
void InsertChild(unsigned index,
scoped_refptr<const NGLayoutResult> layout_result,
const LogicalOffset& offset,
LayoutUnit inline_size,
UBiDiLevel bidi_level) {
unsigned children_count) {
children_.insert(index, Child{std::move(layout_result), offset,
inline_size, bidi_level});
/* inline_size */ LayoutUnit(),
children_count, /* bidi_level */ 0});
}
void MoveInInlineDirection(LayoutUnit);
......
......@@ -78,7 +78,7 @@ crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule3-outside-right-002.xht
crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-left-001.xht [ Failure ]
crbug.com/982194 external/wpt/css/CSS2/floats/floats-rule7-outside-right-001.xht [ Failure ]
crbug.com/982194 external/wpt/css/CSS2/floats/hit-test-floats-001.html [ Failure ]
crbug.com/982194 external/wpt/css/CSS2/positioning/abspos-float-with-inline-container.html [ Crash ]
crbug.com/982194 external/wpt/css/CSS2/positioning/abspos-float-with-inline-container.html [ Crash Failure ]
crbug.com/982194 external/wpt/css/CSS2/positioning/toogle-abspos-on-relpos-inline-child.html [ Failure ]
crbug.com/982194 external/wpt/css/css-contain/contain-layout-017.html [ Pass ]
crbug.com/982194 external/wpt/css/css-contain/contain-paint-021.html [ Pass ]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment