diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/layout/layout_list_item.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/layout/layout_list_item.cc | 147 |
1 files changed, 77 insertions, 70 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_list_item.cc b/chromium/third_party/blink/renderer/core/layout/layout_list_item.cc index 6f882e11a4a..df0dd904451 100644 --- a/chromium/third_party/blink/renderer/core/layout/layout_list_item.cc +++ b/chromium/third_party/blink/renderer/core/layout/layout_list_item.cc @@ -36,7 +36,6 @@ namespace blink { LayoutListItem::LayoutListItem(Element* element) : LayoutBlockFlow(element), - marker_(nullptr), need_block_direction_align_(false) { SetInline(false); @@ -51,13 +50,7 @@ void LayoutListItem::StyleDidChange(StyleDifference diff, StyleImage* current_image = StyleRef().ListStyleImage(); if (StyleRef().ListStyleType() != EListStyleType::kNone || (current_image && !current_image->ErrorOccurred())) { - if (!marker_) - marker_ = LayoutListMarker::CreateAnonymous(this); - marker_->ListItemStyleDidChange(); NotifyOfSubtreeChange(); - } else if (marker_) { - marker_->Destroy(); - marker_ = nullptr; } StyleImage* old_image = old_style ? old_style->ListStyleImage() : nullptr; @@ -70,11 +63,6 @@ void LayoutListItem::StyleDidChange(StyleDifference diff, } void LayoutListItem::WillBeDestroyed() { - if (marker_) { - marker_->Destroy(); - marker_ = nullptr; - } - LayoutBlockFlow::WillBeDestroyed(); if (Style() && StyleRef().ListStyleImage()) @@ -94,7 +82,8 @@ void LayoutListItem::WillBeRemovedFromTree() { } void LayoutListItem::SubtreeDidChange() { - if (!marker_) + LayoutListMarker* marker = Marker(); + if (!marker) return; if (!UpdateMarkerLocation()) @@ -102,8 +91,8 @@ void LayoutListItem::SubtreeDidChange() { // If the marker is inside we need to redo the preferred width calculations // as the size of the item now includes the size of the list marker. - if (marker_->IsInside()) - SetPreferredLogicalWidthsDirty(); + if (marker->IsInsideListMarker()) + SetIntrinsicLogicalWidthsDirty(); } int LayoutListItem::Value() const { @@ -112,13 +101,12 @@ int LayoutListItem::Value() const { } bool LayoutListItem::IsEmpty() const { - return LastChild() == marker_; + return LastChild() == Marker(); } namespace { -LayoutObject* GetParentOfFirstLineBox(LayoutBlockFlow* curr, - LayoutObject* marker) { +LayoutObject* GetParentOfFirstLineBox(LayoutBlockFlow* curr) { LayoutObject* first_child = curr->FirstChild(); if (!first_child) return nullptr; @@ -126,7 +114,7 @@ LayoutObject* GetParentOfFirstLineBox(LayoutBlockFlow* curr, bool in_quirks_mode = curr->GetDocument().InQuirksMode(); for (LayoutObject* curr_child = first_child; curr_child; curr_child = curr_child->NextSibling()) { - if (curr_child == marker) + if (curr_child->IsOutsideListMarker()) continue; if (curr_child->IsInline() && @@ -150,7 +138,7 @@ LayoutObject* GetParentOfFirstLineBox(LayoutBlockFlow* curr, IsA<HTMLOListElement>(*curr_child->GetNode()))) break; - LayoutObject* line_box = GetParentOfFirstLineBox(child_block_flow, marker); + LayoutObject* line_box = GetParentOfFirstLineBox(child_block_flow); if (line_box) return line_box; } @@ -186,21 +174,27 @@ void ForceLogicalHeight(LayoutObject& layout_object, const Length& height) { // marker_container to 0px; else restore it to LogicalHeight of <li>. bool LayoutListItem::PrepareForBlockDirectionAlign( const LayoutObject* line_box_parent) { - LayoutObject* marker_parent = marker_->Parent(); + LayoutListMarker* marker = Marker(); + LayoutObject* marker_parent = marker->Parent(); + bool is_inside = marker->IsInsideListMarker(); // Deal with the situation of layout tree changed. if (marker_parent && marker_parent->IsAnonymous()) { + bool marker_parent_has_lines = + line_box_parent && line_box_parent->IsDescendantOf(marker_parent); // When list-position-style change from outside to inside, we need to - // restore LogicalHeight to auto. So add IsInside(). - if (marker_->IsInside() || marker_->NextSibling()) { + // restore LogicalHeight to auto. So add is_inside. + if (is_inside || marker_parent_has_lines) { // Set marker_container's LogicalHeight to auto. if (marker_parent->StyleRef().LogicalHeight().IsZero()) ForceLogicalHeight(*marker_parent, Length()); - // If marker_parent isn't the ancestor of line_box_parent, marker might - // generate a new empty line. We need to remove marker here.E.g: - // <li><span><div>text<div><span></li> - if (line_box_parent && !line_box_parent->IsDescendantOf(marker_parent)) { - marker_->Remove(); + // If marker_parent_has_lines and the marker is outside, we need to move + // the marker into another parent with 'height: 0' to avoid generating a + // new empty line in cases like <li><span><div>text<div><span></li> + // If the marker is inside and there are inline contents, we want them to + // share the same block container to avoid a line break between them. + if (is_inside != marker_parent_has_lines) { + marker->Remove(); marker_parent = nullptr; } } else if (line_box_parent) { @@ -211,19 +205,18 @@ bool LayoutListItem::PrepareForBlockDirectionAlign( // Create marker_container, set its height to 0px, and add it to li. if (!marker_parent) { LayoutObject* before_child = FirstNonMarkerChild(this); - if (!marker_->IsInside() && before_child && !before_child->IsInline()) { + if (!is_inside && before_child && !before_child->IsInline()) { // Create marker_container and set its LogicalHeight to 0px. LayoutBlock* marker_container = CreateAnonymousBlock(); if (line_box_parent) ForceLogicalHeight(*marker_container, Length::Fixed(0)); - marker_container->AddChild(marker_, - FirstNonMarkerChild(marker_container)); + marker_container->AddChild(marker, FirstNonMarkerChild(marker_container)); AddChild(marker_container, before_child); } else { - AddChild(marker_, before_child); + AddChild(marker, before_child); } - marker_->UpdateMarginsAndContent(); + marker->UpdateMarginsAndContent(); return true; } return false; @@ -241,13 +234,24 @@ static bool IsFirstLeafChild(LayoutObject* container, LayoutObject* child) { } bool LayoutListItem::UpdateMarkerLocation() { - DCHECK(marker_); + DCHECK(Marker()); - LayoutObject* marker_parent = marker_->Parent(); + LayoutListMarker* marker = Marker(); + LayoutObject* marker_parent = marker->Parent(); LayoutObject* line_box_parent = nullptr; - if (!marker_->IsInside()) - line_box_parent = GetParentOfFirstLineBox(this, marker_); + // Make sure a marker originated by a ::before or ::after precedes the + // generated contents. + if (IsPseudoElement()) { + LayoutObject* first_child = marker_parent->SlowFirstChild(); + if (marker != first_child) { + marker->Remove(); + AddChild(marker, first_child); + } + } + + if (marker->IsOutsideListMarker()) + line_box_parent = GetParentOfFirstLineBox(this); if (line_box_parent && (line_box_parent->HasOverflowClip() || !line_box_parent->IsLayoutBlockFlow() || (line_box_parent->IsBox() && @@ -277,13 +281,13 @@ bool LayoutListItem::UpdateMarkerLocation() { if (!marker_parent || (marker_parent != line_box_parent && NormalChildNeedsLayout())) { - marker_->Remove(); - line_box_parent->AddChild(marker_, FirstNonMarkerChild(line_box_parent)); + marker->Remove(); + line_box_parent->AddChild(marker, FirstNonMarkerChild(line_box_parent)); // TODO(rhogan): line_box_parent and marker_parent may be deleted by // AddChild, so they are not safe to reference here. Once we have a safe way // of referencing them delete marker_parent if it is an empty anonymous // block. - marker_->UpdateMarginsAndContent(); + marker->UpdateMarginsAndContent(); return true; } @@ -309,6 +313,7 @@ void LayoutListItem::ComputeVisualOverflow(bool recompute_floats) { AddVisualOverflowFromFloats(); if (VisualOverflowRect() != previous_visual_overflow_rect) { + InvalidateIntersectionObserverCachedRects(); SetShouldCheckForPaintInvalidation(); GetFrameView()->SetIntersectionObservationState(LocalFrameView::kDesired); } @@ -327,7 +332,8 @@ void LayoutListItem::AlignMarkerInBlockDirection() { // layout pass. So if there's no line box in line_box_parent make sure it // back to its original position. bool back_to_original_baseline = false; - LayoutObject* line_box_parent = GetParentOfFirstLineBox(this, marker_); + LayoutListMarker* marker = Marker(); + LayoutObject* line_box_parent = GetParentOfFirstLineBox(this); LayoutBox* line_box_parent_block = nullptr; if (!line_box_parent || !line_box_parent->IsBox()) { back_to_original_baseline = true; @@ -339,12 +345,12 @@ void LayoutListItem::AlignMarkerInBlockDirection() { back_to_original_baseline = true; } - InlineBox* marker_inline_box = marker_->InlineBoxWrapper(); + InlineBox* marker_inline_box = marker->InlineBoxWrapper(); RootInlineBox& marker_root = marker_inline_box->Root(); auto* line_box_parent_block_flow = DynamicTo<LayoutBlockFlow>(line_box_parent_block); if (line_box_parent_block && line_box_parent_block_flow) { - // If marker_ and line_box_parent_block share a same RootInlineBox, no need + // If marker and line_box_parent_block share a same RootInlineBox, no need // to align marker. if (line_box_parent_block_flow->FirstRootBox() == &marker_root) return; @@ -355,7 +361,7 @@ void LayoutListItem::AlignMarkerInBlockDirection() { offset = line_box_parent_block->FirstLineBoxBaseline(); if (back_to_original_baseline || offset == -1) { - line_box_parent_block = marker_->ContainingBlock(); + line_box_parent_block = marker->ContainingBlock(); offset = line_box_parent_block->FirstLineBoxBaseline(); } @@ -369,11 +375,11 @@ void LayoutListItem::AlignMarkerInBlockDirection() { // instead. BaselinePosition is workable when marker is an image. // However, when marker is text, BaselinePosition contains lineheight // information. So use marker_font_metrics.Ascent when marker is text. - if (marker_->IsImage()) { + if (marker->IsImage()) { offset -= marker_inline_box->BaselinePosition(marker_root.BaselineType()); } else { const SimpleFontData* marker_font_data = - marker_->Style(true)->GetFont().PrimaryFont(); + marker->Style(true)->GetFont().PrimaryFont(); if (marker_font_data) { const FontMetrics& marker_font_metrics = marker_font_data->GetFontMetrics(); @@ -382,7 +388,7 @@ void LayoutListItem::AlignMarkerInBlockDirection() { } offset -= marker_inline_box->LogicalTop(); - for (LayoutBox* o = marker_->ParentBox(); o != this; o = o->ParentBox()) { + for (LayoutBox* o = marker->ParentBox(); o != this; o = o->ParentBox()) { offset -= o->LogicalTop(); } @@ -392,24 +398,25 @@ void LayoutListItem::AlignMarkerInBlockDirection() { } void LayoutListItem::UpdateOverflow() { - if (!marker_ || !marker_->Parent() || !marker_->Parent()->IsBox() || - marker_->IsInside() || !marker_->InlineBoxWrapper()) + LayoutListMarker* marker = Marker(); + if (!marker || !marker->Parent() || !marker->Parent()->IsBox() || + marker->IsInsideListMarker() || !marker->InlineBoxWrapper()) return; if (need_block_direction_align_) AlignMarkerInBlockDirection(); - LayoutUnit marker_old_logical_left = marker_->LogicalLeft(); + LayoutUnit marker_old_logical_left = marker->LogicalLeft(); LayoutUnit block_offset; LayoutUnit line_offset; - for (LayoutBox* o = marker_->ParentBox(); o != this; o = o->ParentBox()) { + for (LayoutBox* o = marker->ParentBox(); o != this; o = o->ParentBox()) { block_offset += o->LogicalTop(); line_offset += o->LogicalLeft(); } bool adjust_overflow = false; LayoutUnit marker_logical_left; - InlineBox* marker_inline_box = marker_->InlineBoxWrapper(); + InlineBox* marker_inline_box = marker->InlineBoxWrapper(); RootInlineBox& root = marker_inline_box->Root(); bool hit_self_painting_layer = false; @@ -427,11 +434,11 @@ void LayoutListItem::UpdateOverflow() { // FIXME: Need to account for relative positioning in the layout overflow. if (StyleRef().IsLeftToRightDirection()) { LayoutUnit marker_line_offset = - std::min(marker_->LineOffset(), - LogicalLeftOffsetForLine(marker_->LogicalTop(), + std::min(marker->LineOffset(), + LogicalLeftOffsetForLine(marker->LogicalTop(), kDoNotIndentText, LayoutUnit())); marker_logical_left = marker_line_offset - line_offset - PaddingStart() - - BorderStart() + marker_->MarginStart(); + BorderStart() + marker->MarginStart(); marker_inline_box->MoveInInlineDirection(marker_logical_left - marker_old_logical_left); @@ -468,11 +475,11 @@ void LayoutListItem::UpdateOverflow() { } } else { LayoutUnit marker_line_offset = - std::max(marker_->LineOffset(), - LogicalRightOffsetForLine(marker_->LogicalTop(), + std::max(marker->LineOffset(), + LogicalRightOffsetForLine(marker->LogicalTop(), kDoNotIndentText, LayoutUnit())); marker_logical_left = marker_line_offset - line_offset + PaddingStart() + - BorderStart() + marker_->MarginEnd(); + BorderStart() + marker->MarginEnd(); marker_inline_box->MoveInInlineDirection(marker_logical_left - marker_old_logical_left); @@ -482,11 +489,11 @@ void LayoutListItem::UpdateOverflow() { box->AddReplacedChildrenVisualOverflow(line_top, line_bottom); LayoutRect new_logical_visual_overflow_rect = box->LogicalVisualOverflowRect(line_top, line_bottom); - if (marker_logical_left + marker_->LogicalWidth() > + if (marker_logical_left + marker->LogicalWidth() > new_logical_visual_overflow_rect.MaxX() && !hit_self_painting_layer) { new_logical_visual_overflow_rect.SetWidth( - marker_logical_left + marker_->LogicalWidth() - + marker_logical_left + marker->LogicalWidth() - new_logical_visual_overflow_rect.X()); if (box == root) adjust_overflow = true; @@ -498,10 +505,10 @@ void LayoutListItem::UpdateOverflow() { hit_self_painting_layer = true; LayoutRect new_logical_layout_overflow_rect = box->LogicalLayoutOverflowRect(line_top, line_bottom); - if (marker_logical_left + marker_->LogicalWidth() > + if (marker_logical_left + marker->LogicalWidth() > new_logical_layout_overflow_rect.MaxX()) { new_logical_layout_overflow_rect.SetWidth( - marker_logical_left + marker_->LogicalWidth() - + marker_logical_left + marker->LogicalWidth() - new_logical_layout_overflow_rect.X()); if (box == root) adjust_overflow = true; @@ -518,10 +525,10 @@ void LayoutListItem::UpdateOverflow() { LayoutRect marker_rect( LayoutPoint(marker_logical_left + line_offset, block_offset + marker_inline_box->LogicalTop()), - marker_->Size()); + marker->Size()); if (!StyleRef().IsHorizontalWritingMode()) marker_rect = marker_rect.TransposedRect(); - LayoutBox* object = marker_; + LayoutBox* object = marker; bool found_self_painting_layer = false; do { @@ -549,16 +556,16 @@ void LayoutListItem::Paint(const PaintInfo& paint_info) const { } const String& LayoutListItem::MarkerText() const { - if (marker_) - return marker_->GetText(); + if (LayoutListMarker* marker = Marker()) + return marker->GetText(); return g_null_atom.GetString(); } void LayoutListItem::OrdinalValueChanged() { - if (!marker_) - return; - marker_->SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( - layout_invalidation_reason::kListValueChange); + if (LayoutListMarker* marker = Marker()) { + marker->SetNeedsLayoutAndIntrinsicWidthsRecalcAndFullPaintInvalidation( + layout_invalidation_reason::kListValueChange); + } } } // namespace blink |