Commit e744b301 authored by Koji Ishii's avatar Koji Ishii Committed by Commit Bot

[FragmentItem] Use |PaintBlockFlowContents|

Before this patch, |NGFragmentItem| used its own function to
paint inline children of |LayoutBlockFlow|. This patch
changes it to use |PaintBlockFlowContents| by making the
function support |NGFragmentItem|.

Fixes ~45 failiures.

Bug: 982194
Change-Id: I9f4de6c71f85cf14722fcb8b1721719445dd1f08
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1994556Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Commit-Queue: Koji Ishii <kojii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#731835}
parent 1bb360e0
...@@ -157,6 +157,23 @@ NGInlineCursor NGInlineCursor::CursorForDescendants() const { ...@@ -157,6 +157,23 @@ NGInlineCursor NGInlineCursor::CursorForDescendants() const {
return NGInlineCursor(); return NGInlineCursor();
} }
void NGInlineCursor::ExpandRootToContainingBlock() {
if (root_paint_fragment_) {
root_paint_fragment_ = root_paint_fragment_->Root();
return;
}
if (fragment_items_) {
const unsigned index_diff = items_.data() - fragment_items_->Items().data();
DCHECK_LT(index_diff, fragment_items_->Items().size());
const unsigned item_index = item_iter_ - items_.begin();
items_ = fragment_items_->Items();
// Update the iterator to the one for the new span.
MoveToItem(items_.begin() + item_index + index_diff);
return;
}
NOTREACHED();
}
bool NGInlineCursor::HasSoftWrapToNextLine() const { bool NGInlineCursor::HasSoftWrapToNextLine() const {
DCHECK(IsLineBox()); DCHECK(IsLineBox());
const NGInlineBreakToken& break_token = CurrentInlineBreakToken(); const NGInlineBreakToken& break_token = CurrentInlineBreakToken();
......
...@@ -101,6 +101,12 @@ class CORE_EXPORT NGInlineCursor { ...@@ -101,6 +101,12 @@ class CORE_EXPORT NGInlineCursor {
// has no children, returns an empty cursor. // has no children, returns an empty cursor.
NGInlineCursor CursorForDescendants() const; NGInlineCursor CursorForDescendants() const;
// If |this| is created by |CursorForDescendants()| to traverse parts of an
// inline formatting context, expand the traversable range to the containing
// |LayoutBlockFlow|. Does nothing if |this| is for an inline formatting
// context.
void ExpandRootToContainingBlock();
// True if current position has soft wrap to next line. It is error to call // True if current position has soft wrap to next line. It is error to call
// other than line. // other than line.
bool HasSoftWrapToNextLine() const; bool HasSoftWrapToNextLine() const;
......
...@@ -181,7 +181,8 @@ Vector<PhysicalRect> BuildBackplate(NGInlineCursor* descendants, ...@@ -181,7 +181,8 @@ Vector<PhysicalRect> BuildBackplate(NGInlineCursor* descendants,
// inlines. // inlines.
for (; *descendants; descendants->MoveToNext()) { for (; *descendants; descendants->MoveToNext()) {
const NGPaintFragment* child = descendants->CurrentPaintFragment(); const NGPaintFragment* child = descendants->CurrentPaintFragment();
DCHECK(child); // TODO(kojii): Support NGFragmentItem if (!child) // TODO(kojii): Support NGFragmentItem
continue;
const NGPhysicalFragment& child_fragment = child->PhysicalFragment(); const NGPhysicalFragment& child_fragment = child->PhysicalFragment();
if (child_fragment.IsHiddenForPaint() || child_fragment.IsFloating()) if (child_fragment.IsHiddenForPaint() || child_fragment.IsFloating())
continue; continue;
...@@ -232,6 +233,12 @@ PhysicalRect NGBoxFragmentPainter::SelfInkOverflow() const { ...@@ -232,6 +233,12 @@ PhysicalRect NGBoxFragmentPainter::SelfInkOverflow() const {
->PhysicalSelfVisualOverflowRect(); ->PhysicalSelfVisualOverflowRect();
} }
PhysicalRect NGBoxFragmentPainter::ContentsInkOverflow() const {
const NGPhysicalFragment& fragment = PhysicalFragment();
return ToLayoutBox(fragment.GetLayoutObject())
->PhysicalContentsVisualOverflowRect();
}
void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) { void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) {
if (PhysicalFragment().IsPaintedAtomically() && if (PhysicalFragment().IsPaintedAtomically() &&
!box_fragment_.HasSelfPaintingLayer()) !box_fragment_.HasSelfPaintingLayer())
...@@ -384,9 +391,13 @@ void NGBoxFragmentPainter::PaintObject( ...@@ -384,9 +391,13 @@ void NGBoxFragmentPainter::PaintObject(
paint_offset_to_inline_formatting_context, paint_offset_to_inline_formatting_context,
descendants_); descendants_);
} else if (items_) { } else if (items_) {
// Paint |NGFragmentItems| for this block if we have one. if (physical_box_fragment.IsBlockFlow()) {
NGInlineCursor cursor(*items_); PaintBlockFlowContents(paint_info, paint_offset);
PaintInlineItems(paint_info.ForDescendants(), paint_offset, &cursor); } else {
DCHECK(physical_box_fragment.IsInlineBox());
NGInlineCursor cursor(*items_);
PaintInlineItems(paint_info.ForDescendants(), paint_offset, &cursor);
}
} else if (physical_box_fragment.ChildrenInline()) { } else if (physical_box_fragment.ChildrenInline()) {
DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()); DCHECK(!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled());
DCHECK(paint_fragment_); DCHECK(paint_fragment_);
...@@ -445,14 +456,12 @@ void NGBoxFragmentPainter::PaintBlockFlowContents( ...@@ -445,14 +456,12 @@ void NGBoxFragmentPainter::PaintBlockFlowContents(
const PhysicalOffset& paint_offset) { const PhysicalOffset& paint_offset) {
const NGPhysicalBoxFragment& fragment = PhysicalFragment(); const NGPhysicalBoxFragment& fragment = PhysicalFragment();
const LayoutObject* layout_object = fragment.GetLayoutObject(); const LayoutObject* layout_object = fragment.GetLayoutObject();
DCHECK(fragment.ChildrenInline()); DCHECK(fragment.ChildrenInline());
DCHECK(paint_fragment_);
// When the layout-tree gets into a bad state, we can end up trying to paint // When the layout-tree gets into a bad state, we can end up trying to paint
// a fragment with inline children, without a paint fragment. See: // a fragment with inline children, without a paint fragment. See:
// http://crbug.com/1022545 // http://crbug.com/1022545
if (!paint_fragment_) { if ((!paint_fragment_ && !items_) || layout_object->NeedsLayout()) {
NOTREACHED(); NOTREACHED();
return; return;
} }
...@@ -470,7 +479,7 @@ void NGBoxFragmentPainter::PaintBlockFlowContents( ...@@ -470,7 +479,7 @@ void NGBoxFragmentPainter::PaintBlockFlowContents(
// |LayoutOverflow()|, but this can be approximiated with // |LayoutOverflow()|, but this can be approximiated with
// |ContentsInkOverflow()|. // |ContentsInkOverflow()|.
PhysicalRect content_ink_rect = fragment.LocalRect(); PhysicalRect content_ink_rect = fragment.LocalRect();
content_ink_rect.Unite(paint_fragment_->ContentsInkOverflow()); content_ink_rect.Unite(ContentsInkOverflow());
content_ink_rect.offset += PhysicalOffset(paint_offset); content_ink_rect.offset += PhysicalOffset(paint_offset);
if (!paint_info.GetCullRect().Intersects(content_ink_rect.ToLayoutRect())) if (!paint_info.GetCullRect().Intersects(content_ink_rect.ToLayoutRect()))
return; return;
...@@ -478,7 +487,13 @@ void NGBoxFragmentPainter::PaintBlockFlowContents( ...@@ -478,7 +487,13 @@ void NGBoxFragmentPainter::PaintBlockFlowContents(
DCHECK(layout_object->IsLayoutBlockFlow()); DCHECK(layout_object->IsLayoutBlockFlow());
const auto& layout_block = To<LayoutBlock>(*layout_object); const auto& layout_block = To<LayoutBlock>(*layout_object);
DCHECK(layout_block.ChildrenInline()); DCHECK(layout_block.ChildrenInline());
NGInlineCursor children(*paint_fragment_); if (paint_fragment_) {
NGInlineCursor children(*paint_fragment_);
PaintLineBoxChildren(&children, paint_info.ForDescendants(), paint_offset);
return;
}
DCHECK(items_);
NGInlineCursor children(*items_);
PaintLineBoxChildren(&children, paint_info.ForDescendants(), paint_offset); PaintLineBoxChildren(&children, paint_info.ForDescendants(), paint_offset);
} }
...@@ -1005,10 +1020,6 @@ void NGBoxFragmentPainter::PaintAllPhasesAtomically( ...@@ -1005,10 +1020,6 @@ void NGBoxFragmentPainter::PaintAllPhasesAtomically(
void NGBoxFragmentPainter::PaintInlineItems(const PaintInfo& paint_info, void NGBoxFragmentPainter::PaintInlineItems(const PaintInfo& paint_info,
const PhysicalOffset& paint_offset, const PhysicalOffset& paint_offset,
NGInlineCursor* cursor) { NGInlineCursor* cursor) {
ScopedPaintTimingDetectorBlockPaintHook
scoped_paint_timing_detector_block_paint_hook;
// TODO(kojii): Copy more from |PaintLineBoxChildren|.
while (*cursor) { while (*cursor) {
const NGFragmentItem* item = cursor->CurrentItem(); const NGFragmentItem* item = cursor->CurrentItem();
DCHECK(item); DCHECK(item);
...@@ -1017,19 +1028,15 @@ void NGBoxFragmentPainter::PaintInlineItems(const PaintInfo& paint_info, ...@@ -1017,19 +1028,15 @@ void NGBoxFragmentPainter::PaintInlineItems(const PaintInfo& paint_info,
case NGFragmentItem::kGeneratedText: case NGFragmentItem::kGeneratedText:
PaintTextItem(*cursor, paint_info, paint_offset); PaintTextItem(*cursor, paint_info, paint_offset);
break; break;
case NGFragmentItem::kLine:
if (PaintLineBoxItem(*item, paint_info, paint_offset) ==
kSkipChildren) {
cursor->MoveToNextSkippingChildren();
continue;
}
break;
case NGFragmentItem::kBox: case NGFragmentItem::kBox:
if (PaintBoxItem(*item, paint_info, paint_offset) == kSkipChildren) { if (PaintBoxItem(*item, paint_info, paint_offset) == kSkipChildren) {
cursor->MoveToNextSkippingChildren(); cursor->MoveToNextSkippingChildren();
continue; continue;
} }
break; break;
case NGFragmentItem::kLine:
NOTREACHED();
break;
} }
cursor->MoveToNext(); cursor->MoveToNext();
} }
...@@ -1102,6 +1109,11 @@ void NGBoxFragmentPainter::PaintLineBoxChildren( ...@@ -1102,6 +1109,11 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
return; return;
} }
if (UNLIKELY(children->IsItemCursor())) {
PaintLineBoxChildItems(children, paint_info, paint_offset);
return;
}
const bool is_horizontal = box_fragment_.Style().IsHorizontalWritingMode(); const bool is_horizontal = box_fragment_.Style().IsHorizontalWritingMode();
for (; *children; children->MoveToNextSkippingChildren()) { for (; *children; children->MoveToNextSkippingChildren()) {
const NGPaintFragment* line = children->CurrentPaintFragment(); const NGPaintFragment* line = children->CurrentPaintFragment();
...@@ -1139,6 +1151,56 @@ void NGBoxFragmentPainter::PaintLineBoxChildren( ...@@ -1139,6 +1151,56 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
} }
} }
void NGBoxFragmentPainter::PaintLineBoxChildItems(
NGInlineCursor* children,
const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) {
const bool is_horizontal = box_fragment_.Style().IsHorizontalWritingMode();
for (; *children; children->MoveToNextSkippingChildren()) {
const NGFragmentItem* child_item = children->CurrentItem();
DCHECK(child_item);
// Check if CullRect intersects with this child, only in block direction
// because soft-wrap and <br> needs to paint outside of InkOverflow() in
// inline direction.
const PhysicalOffset& child_offset = paint_offset + child_item->Offset();
const PhysicalRect child_rect = child_item->InkOverflow();
if (is_horizontal) {
LayoutUnit y = child_rect.offset.top + child_offset.top;
if (!paint_info.GetCullRect().IntersectsVerticalRange(
y, y + child_rect.size.height))
continue;
} else {
LayoutUnit x = child_rect.offset.left + child_offset.left;
if (!paint_info.GetCullRect().IntersectsHorizontalRange(
x, x + child_rect.size.width))
continue;
}
if (child_item->Type() == NGFragmentItem::kLine) {
const NGPhysicalLineBoxFragment* line_box_fragment =
child_item->LineBoxFragment();
DCHECK(line_box_fragment);
PaintLineBox(*line_box_fragment, *child_item,
/* line_box_paint_fragment */ nullptr, child_item,
paint_info, child_offset);
NGInlineCursor line_box_cursor = children->CursorForDescendants();
PaintInlineItems(paint_info, paint_offset, &line_box_cursor);
continue;
}
if (const NGPhysicalBoxFragment* child_fragment =
child_item->BoxFragment()) {
if (child_fragment->IsListMarker()) {
PaintBoxItem(*child_item, paint_info, paint_offset);
continue;
}
}
NOTREACHED();
}
}
void NGBoxFragmentPainter::PaintBackplate(NGInlineCursor* line_boxes, void NGBoxFragmentPainter::PaintBackplate(NGInlineCursor* line_boxes,
const PaintInfo& paint_info, const PaintInfo& paint_info,
const PhysicalOffset& paint_offset) { const PhysicalOffset& paint_offset) {
......
...@@ -105,6 +105,9 @@ class NGBoxFragmentPainter : public BoxPainterBase { ...@@ -105,6 +105,9 @@ class NGBoxFragmentPainter : public BoxPainterBase {
void PaintLineBoxChildren(NGInlineCursor* children, void PaintLineBoxChildren(NGInlineCursor* children,
const PaintInfo&, const PaintInfo&,
const PhysicalOffset& paint_offset); const PhysicalOffset& paint_offset);
void PaintLineBoxChildItems(NGInlineCursor* children,
const PaintInfo&,
const PhysicalOffset& paint_offset);
void PaintLineBox(const NGPhysicalFragment& line_box_fragment, void PaintLineBox(const NGPhysicalFragment& line_box_fragment,
const DisplayItemClient& display_item_client, const DisplayItemClient& display_item_client,
const NGPaintFragment* line_box_paint_fragment, const NGPaintFragment* line_box_paint_fragment,
...@@ -250,6 +253,7 @@ class NGBoxFragmentPainter : public BoxPainterBase { ...@@ -250,6 +253,7 @@ class NGBoxFragmentPainter : public BoxPainterBase {
} }
const NGBorderEdges& BorderEdges() const; const NGBorderEdges& BorderEdges() const;
PhysicalRect SelfInkOverflow() const; PhysicalRect SelfInkOverflow() const;
PhysicalRect ContentsInkOverflow() const;
const NGPhysicalBoxFragment& box_fragment_; const NGPhysicalBoxFragment& box_fragment_;
const DisplayItemClient& display_item_client_; const DisplayItemClient& display_item_client_;
......
...@@ -64,6 +64,26 @@ inline const NGPaintFragment& AsDisplayItemClient( ...@@ -64,6 +64,26 @@ inline const NGPaintFragment& AsDisplayItemClient(
return cursor.PaintFragment(); return cursor.PaintFragment();
} }
inline const NGInlineCursor& InlineCursorForBlockFlow(
const NGInlineCursor& cursor,
base::Optional<NGInlineCursor>* storage) {
if (*storage)
return **storage;
*storage = cursor;
(*storage)->ExpandRootToContainingBlock();
return **storage;
}
inline const NGInlineCursor& InlineCursorForBlockFlow(
const NGTextPainterCursor& cursor,
base::Optional<NGInlineCursor>* storage) {
if (*storage)
return **storage;
storage->emplace(cursor.RootPaintFragment());
(*storage)->MoveTo(cursor.PaintFragment());
return **storage;
}
// TODO(yosin): Remove |GetTextFragmentPaintInfo| once the transition to // TODO(yosin): Remove |GetTextFragmentPaintInfo| once the transition to
// |NGFragmentItem| is done. http://crbug.com/982194 // |NGFragmentItem| is done. http://crbug.com/982194
inline NGTextFragmentPaintInfo GetTextFragmentPaintInfo( inline NGTextFragmentPaintInfo GetTextFragmentPaintInfo(
...@@ -98,28 +118,13 @@ inline std::pair<LayoutUnit, LayoutUnit> GetLineLeftAndRightForOffsets( ...@@ -98,28 +118,13 @@ inline std::pair<LayoutUnit, LayoutUnit> GetLineLeftAndRightForOffsets(
// |NGFragmentItem| is done. http://crbug.com/982194 // |NGFragmentItem| is done. http://crbug.com/982194
inline LayoutSelectionStatus ComputeLayoutSelectionStatus( inline LayoutSelectionStatus ComputeLayoutSelectionStatus(
const NGInlineCursor& cursor) { const NGInlineCursor& cursor) {
return cursor.CurrentItem() return cursor.CurrentLayoutObject()
->GetLayoutObject()
->GetDocument() ->GetDocument()
.GetFrame() .GetFrame()
->Selection() ->Selection()
.ComputeLayoutSelectionStatus(cursor); .ComputeLayoutSelectionStatus(cursor);
} }
inline LayoutSelectionStatus ComputeLayoutSelectionStatus(
const NGTextPainterCursor& cursor) {
// Note:: Because of this function is hot, we should not use |NGInlineCursor|
// on paint fragment which requires traversing ancestors to root.
NGInlineCursor inline_cursor(cursor.RootPaintFragment());
inline_cursor.MoveTo(cursor.PaintFragment());
return cursor.CurrentItem()
->GetLayoutObject()
->GetDocument()
.GetFrame()
->Selection()
.ComputeLayoutSelectionStatus(inline_cursor);
}
// TODO(yosin): Remove |ComputeLocalRect| once the transition to // TODO(yosin): Remove |ComputeLocalRect| once the transition to
// |NGFragmentItem| is done. http://crbug.com/982194 // |NGFragmentItem| is done. http://crbug.com/982194
inline PhysicalRect ComputeLocalRect(const NGFragmentItem& text_item, inline PhysicalRect ComputeLocalRect(const NGFragmentItem& text_item,
...@@ -326,20 +331,11 @@ template <typename Cursor> ...@@ -326,20 +331,11 @@ template <typename Cursor>
NGTextFragmentPainter<Cursor>::NGTextFragmentPainter(const Cursor& cursor) NGTextFragmentPainter<Cursor>::NGTextFragmentPainter(const Cursor& cursor)
: cursor_(cursor) {} : cursor_(cursor) {}
static PhysicalRect ComputeLocalSelectionRectForText(
const NGTextPainterCursor& cursor,
const LayoutSelectionStatus& selection_status) {
NGInlineCursor inline_cursor(cursor.RootPaintFragment());
inline_cursor.MoveTo(cursor.PaintFragment());
return ComputeLocalSelectionRectForText(inline_cursor, selection_status);
}
// Logic is copied from InlineTextBoxPainter::PaintSelection. // Logic is copied from InlineTextBoxPainter::PaintSelection.
// |selection_start| and |selection_end| should be between // |selection_start| and |selection_end| should be between
// [text_fragment.StartOffset(), text_fragment.EndOffset()]. // [text_fragment.StartOffset(), text_fragment.EndOffset()].
template <typename Cursor>
static void PaintSelection(GraphicsContext& context, static void PaintSelection(GraphicsContext& context,
const Cursor& cursor, const NGInlineCursor& cursor,
Node* node, Node* node,
const Document& document, const Document& document,
const ComputedStyle& style, const ComputedStyle& style,
...@@ -400,7 +396,9 @@ void NGTextFragmentPainter<Cursor>::Paint(const PaintInfo& paint_info, ...@@ -400,7 +396,9 @@ void NGTextFragmentPainter<Cursor>::Paint(const PaintInfo& paint_info,
layout_object->IsSelected(); layout_object->IsSelected();
base::Optional<LayoutSelectionStatus> selection_status; base::Optional<LayoutSelectionStatus> selection_status;
if (have_selection) { if (have_selection) {
selection_status = ComputeLayoutSelectionStatus(cursor_); const NGInlineCursor& root_inline_cursor =
InlineCursorForBlockFlow(cursor_, &inline_cursor_for_block_flow_);
selection_status = ComputeLayoutSelectionStatus(root_inline_cursor);
DCHECK_LE(selection_status->start, selection_status->end); DCHECK_LE(selection_status->start, selection_status->end);
have_selection = selection_status->start < selection_status->end; have_selection = selection_status->start < selection_status->end;
} }
...@@ -483,7 +481,9 @@ void NGTextFragmentPainter<Cursor>::Paint(const PaintInfo& paint_info, ...@@ -483,7 +481,9 @@ void NGTextFragmentPainter<Cursor>::Paint(const PaintInfo& paint_info,
markers_to_paint, box_rect.offset, style, markers_to_paint, box_rect.offset, style,
DocumentMarkerPaintPhase::kBackground, nullptr); DocumentMarkerPaintPhase::kBackground, nullptr);
if (have_selection) { if (have_selection) {
PaintSelection(context, cursor_, node, document, style, const NGInlineCursor& root_inline_cursor =
InlineCursorForBlockFlow(cursor_, &inline_cursor_for_block_flow_);
PaintSelection(context, root_inline_cursor, node, document, style,
selection_style.fill_color, box_rect, *selection_status); selection_style.fill_color, box_rect, *selection_status);
} }
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_TEXT_FRAGMENT_PAINTER_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_TEXT_FRAGMENT_PAINTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_TEXT_FRAGMENT_PAINTER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_TEXT_FRAGMENT_PAINTER_H_
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h" #include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h" #include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h" #include "third_party/blink/renderer/core/style/computed_style_constants.h"
...@@ -80,6 +81,7 @@ class NGTextFragmentPainter { ...@@ -80,6 +81,7 @@ class NGTextFragmentPainter {
const PhysicalOffset& paint_offset); const PhysicalOffset& paint_offset);
const Cursor& cursor_; const Cursor& cursor_;
base::Optional<NGInlineCursor> inline_cursor_for_block_flow_;
}; };
extern template class NGTextFragmentPainter<NGTextPainterCursor>; extern template class NGTextFragmentPainter<NGTextPainterCursor>;
......
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