Commit 48b591db authored by Emil A Eklund's avatar Emil A Eklund Committed by Commit Bot

Compute multi-line lazily for inline painting

Computing whether an inline block spans multiple lines is more expensive
than expected thus causing a small paint performance regression for both
legacy layout and LayoutNG. This patch moves the computation to use-time
thereby avoiding it when cached drawings are used or paint isn't needed.

Bug: 714962
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_layout_ng;luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I97380b2e304c3c3293514ecf118fffdf6f9b9292
Reviewed-on: https://chromium-review.googlesource.com/1170310Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Emil A Eklund <eae@chromium.org>
Cr-Commit-Position: refs/heads/master@{#582501}
parent 86585f8f
......@@ -19,6 +19,7 @@ void InlineBoxPainterBase::PaintBoxDecorationBackground(
const LayoutPoint& paint_offset,
LayoutRect adjusted_frame_rect,
BackgroundImageGeometry geometry,
bool object_has_multiple_boxes,
bool include_logical_left_edge,
bool include_logical_right_edge) {
// Shadow comes first and is behind the background and border.
......@@ -27,14 +28,14 @@ void InlineBoxPainterBase::PaintBoxDecorationBackground(
Color background_color =
line_style_.VisitedDependentColor(GetCSSPropertyBackgroundColor());
PaintFillLayers(box_painter, paint_info, background_color,
line_style_.BackgroundLayers(), adjusted_frame_rect,
geometry);
line_style_.BackgroundLayers(), adjusted_frame_rect, geometry,
object_has_multiple_boxes);
PaintInsetBoxShadow(paint_info, line_style_, adjusted_frame_rect);
IntRect adjusted_clip_rect;
BorderPaintingType border_painting_type =
GetBorderPaintType(adjusted_frame_rect, adjusted_clip_rect);
BorderPaintingType border_painting_type = GetBorderPaintType(
adjusted_frame_rect, adjusted_clip_rect, object_has_multiple_boxes);
switch (border_painting_type) {
case kDontPaintBorders:
break;
......@@ -65,12 +66,16 @@ void InlineBoxPainterBase::PaintFillLayers(BoxPainterBase& box_painter,
const FillLayer& layer,
const LayoutRect& rect,
BackgroundImageGeometry& geometry,
bool object_has_multiple_boxes,
SkBlendMode op) {
// FIXME: This should be a for loop or similar. It's a little non-trivial to
// do so, however, since the layers need to be painted in reverse order.
if (layer.Next())
PaintFillLayers(box_painter, info, c, *layer.Next(), rect, geometry, op);
PaintFillLayer(box_painter, info, c, layer, rect, geometry, op);
if (layer.Next()) {
PaintFillLayers(box_painter, info, c, *layer.Next(), rect, geometry,
object_has_multiple_boxes, op);
}
PaintFillLayer(box_painter, info, c, layer, rect, geometry,
object_has_multiple_boxes, op);
}
void InlineBoxPainterBase::PaintFillLayer(BoxPainterBase& box_painter,
......@@ -79,11 +84,12 @@ void InlineBoxPainterBase::PaintFillLayer(BoxPainterBase& box_painter,
const FillLayer& fill_layer,
const LayoutRect& paint_rect,
BackgroundImageGeometry& geometry,
bool object_has_multiple_boxes,
SkBlendMode op) {
StyleImage* img = fill_layer.GetImage();
bool has_fill_image = img && img->CanRender();
if (!object_has_multiple_boxes_ ||
if (!object_has_multiple_boxes ||
(!has_fill_image && !style_.HasBorderRadius())) {
box_painter.PaintFillLayer(paint_info, c, fill_layer, paint_rect,
kBackgroundBleedNone, geometry, op, false);
......@@ -91,7 +97,7 @@ void InlineBoxPainterBase::PaintFillLayer(BoxPainterBase& box_painter,
}
// Handle fill images that clone or spans multiple lines.
bool multi_line = object_has_multiple_boxes_ &&
bool multi_line = object_has_multiple_boxes &&
style_.BoxDecorationBreak() != EBoxDecorationBreak::kClone;
LayoutRect rect = multi_line
? PaintRectForImageStrip(paint_rect, style_.Direction())
......@@ -103,20 +109,4 @@ void InlineBoxPainterBase::PaintFillLayer(BoxPainterBase& box_painter,
paint_rect.Size());
}
void InlineBoxPainterBase::PaintNormalBoxShadow(const PaintInfo& info,
const ComputedStyle& s,
const LayoutRect& paint_rect) {
BoxPainterBase::PaintNormalBoxShadow(
info, paint_rect, s, include_logical_left_edge_for_box_shadow_,
include_logical_right_edge_for_box_shadow_);
}
void InlineBoxPainterBase::PaintInsetBoxShadow(const PaintInfo& info,
const ComputedStyle& s,
const LayoutRect& paint_rect) {
BoxPainterBase::PaintInsetBoxShadowWithBorderRect(
info, paint_rect, s, include_logical_left_edge_for_box_shadow_,
include_logical_right_edge_for_box_shadow_);
}
} // namespace blink
......@@ -43,6 +43,7 @@ class InlineBoxPainterBase {
const LayoutPoint& paint_offset,
LayoutRect adjusted_frame_rect,
BackgroundImageGeometry,
bool object_has_multiple_boxes,
bool include_logical_left_edge,
bool include_logical_right_edge);
......@@ -53,6 +54,7 @@ class InlineBoxPainterBase {
const FillLayer&,
const LayoutRect&,
BackgroundImageGeometry& geometry,
bool object_has_multiple_boxes,
SkBlendMode op = SkBlendMode::kSrcOver);
void PaintFillLayer(BoxPainterBase&,
const PaintInfo&,
......@@ -60,13 +62,14 @@ class InlineBoxPainterBase {
const FillLayer&,
const LayoutRect&,
BackgroundImageGeometry& geometry,
bool object_has_multiple_boxes,
SkBlendMode op);
void PaintNormalBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect);
void PaintInsetBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect);
virtual void PaintNormalBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect) = 0;
virtual void PaintInsetBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect) = 0;
virtual LayoutRect PaintRectForImageStrip(const LayoutRect&,
TextDirection direction) const = 0;
......@@ -78,7 +81,8 @@ class InlineBoxPainterBase {
};
virtual BorderPaintingType GetBorderPaintType(
const LayoutRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect) const = 0;
IntRect& adjusted_clip_rect,
bool object_has_multiple_boxes) const = 0;
const ImageResourceObserver& image_observer_;
Member<const Document> document_;
......@@ -89,10 +93,6 @@ class InlineBoxPainterBase {
// Style taking ::first-line into account.
const ComputedStyle& line_style_;
bool object_has_multiple_boxes_;
bool include_logical_left_edge_for_box_shadow_;
bool include_logical_right_edge_for_box_shadow_;
};
} // namespace blink
......
......@@ -42,16 +42,6 @@ InlineFlowBoxPainter::InlineFlowBoxPainter(const InlineFlowBox& flow_box)
flow_box.GetLineLayoutItem().StyleRef(),
flow_box.GetLineLayoutItem().StyleRef(flow_box.IsFirstLineStyle())),
inline_flow_box_(flow_box) {
object_has_multiple_boxes_ = inline_flow_box_.PrevForSameLayoutObject() ||
inline_flow_box_.NextForSameLayoutObject();
bool force_include_logical_edges =
(!inline_flow_box_.PrevForSameLayoutObject() &&
!inline_flow_box_.NextForSameLayoutObject()) ||
!inline_flow_box_.Parent();
include_logical_left_edge_for_box_shadow_ =
force_include_logical_edges || inline_flow_box_.IncludeLogicalLeftEdge();
include_logical_right_edge_for_box_shadow_ =
force_include_logical_edges || inline_flow_box_.IncludeLogicalRightEdge();
}
void InlineFlowBoxPainter::Paint(const PaintInfo& paint_info,
......@@ -162,7 +152,8 @@ LayoutRect InlineFlowBoxPainter::PaintRectForImageStrip(
InlineBoxPainterBase::BorderPaintingType
InlineFlowBoxPainter::GetBorderPaintType(const LayoutRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect) const {
IntRect& adjusted_clip_rect,
bool object_has_multiple_boxes) const {
adjusted_clip_rect = PixelSnappedIntRect(adjusted_frame_rect);
if (inline_flow_box_.Parent() &&
inline_flow_box_.GetLineLayoutItem().StyleRef().HasBorderDecoration()) {
......@@ -226,12 +217,14 @@ void InlineFlowBoxPainter::PaintBackgroundBorderShadow(
LayoutRect paint_rect = AdjustedPaintRect(paint_offset);
bool object_has_multiple_boxes = inline_flow_box_.PrevForSameLayoutObject() ||
inline_flow_box_.NextForSameLayoutObject();
const auto& box_model = *ToLayoutBoxModelObject(
LineLayoutAPIShim::LayoutObjectFrom(inline_flow_box_.BoxModelObject()));
BackgroundImageGeometry geometry(box_model);
BoxModelObjectPainter box_painter(box_model, &inline_flow_box_);
PaintBoxDecorationBackground(box_painter, paint_info, paint_offset,
paint_rect, geometry,
paint_rect, geometry, object_has_multiple_boxes,
inline_flow_box_.IncludeLogicalLeftEdge(),
inline_flow_box_.IncludeLogicalRightEdge());
}
......@@ -257,12 +250,15 @@ void InlineFlowBoxPainter::PaintMask(const PaintInfo& paint_info,
const auto& mask_nine_piece_image = box_model.StyleRef().MaskBoxImage();
const auto* mask_box_image = mask_nine_piece_image.GetImage();
bool object_has_multiple_boxes = inline_flow_box_.PrevForSameLayoutObject() ||
inline_flow_box_.NextForSameLayoutObject();
// Figure out if we need to push a transparency layer to render our mask.
BackgroundImageGeometry geometry(box_model);
BoxModelObjectPainter box_painter(box_model, &inline_flow_box_);
PaintFillLayers(box_painter, paint_info, Color::kTransparent,
box_model.StyleRef().MaskLayers(), paint_rect, geometry);
box_model.StyleRef().MaskLayers(), paint_rect, geometry,
object_has_multiple_boxes);
bool has_box_image = mask_box_image && mask_box_image->CanRender();
if (!has_box_image || !mask_box_image->IsLoaded()) {
......@@ -350,4 +346,20 @@ void InlineFlowBoxPainter::RecordHitTestData(const PaintInfo& paint_info,
TouchActionRect(AdjustedPaintRect(paint_offset), touch_action));
}
void InlineFlowBoxPainter::PaintNormalBoxShadow(const PaintInfo& info,
const ComputedStyle& s,
const LayoutRect& paint_rect) {
BoxPainterBase::PaintNormalBoxShadow(
info, paint_rect, s, inline_flow_box_.IncludeLogicalLeftEdge(),
inline_flow_box_.IncludeLogicalRightEdge());
}
void InlineFlowBoxPainter::PaintInsetBoxShadow(const PaintInfo& info,
const ComputedStyle& s,
const LayoutRect& paint_rect) {
BoxPainterBase::PaintInsetBoxShadowWithBorderRect(
info, paint_rect, s, inline_flow_box_.IncludeLogicalLeftEdge(),
inline_flow_box_.IncludeLogicalRightEdge());
}
} // namespace blink
......@@ -37,6 +37,12 @@ class InlineFlowBoxPainter : public InlineBoxPainterBase {
protected:
LayoutRect PaintRectForImageStrip(const LayoutRect&,
TextDirection) const override;
void PaintNormalBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect) override;
void PaintInsetBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect) override;
private:
void PaintBackgroundBorderShadow(const PaintInfo&,
......@@ -45,7 +51,8 @@ class InlineFlowBoxPainter : public InlineBoxPainterBase {
BorderPaintingType GetBorderPaintType(
const LayoutRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect) const override;
IntRect& adjusted_clip_rect,
bool object_has_multiple_boxes) const override;
LayoutRect AdjustedPaintRect(const LayoutPoint& paint_offset) const;
......
......@@ -32,15 +32,6 @@ NGInlineBoxFragmentPainter::NGInlineBoxFragmentPainter(
border_edges_(NGBorderEdges::FromPhysical(
inline_box_fragment.PhysicalFragment().BorderEdges(),
inline_box_fragment.Style().GetWritingMode())) {
NGPaintFragment::FragmentRange fragments =
inline_box_fragment.InlineFragmentsFor(
inline_box_fragment.GetLayoutObject());
NGPaintFragment::FragmentRange::iterator iter = fragments.begin();
object_has_multiple_boxes_ = ++iter != fragments.end();
include_logical_left_edge_for_box_shadow_ =
!object_has_multiple_boxes_ || border_edges_.line_left;
include_logical_right_edge_for_box_shadow_ =
!object_has_multiple_boxes_ || border_edges_.line_right;
}
void NGInlineBoxFragmentPainter::Paint(const PaintInfo& paint_info,
......@@ -87,13 +78,20 @@ void NGInlineBoxFragmentPainter::PaintBackgroundBorderShadow(
LayoutRect adjusted_frame_rect =
LayoutRect(adjusted_paint_offset, frame_rect.Size());
NGPaintFragment::FragmentRange fragments =
inline_box_fragment_.InlineFragmentsFor(
inline_box_fragment_.GetLayoutObject());
NGPaintFragment::FragmentRange::iterator iter = fragments.begin();
bool object_has_multiple_boxes = ++iter != fragments.end();
// TODO(eae): Switch to LayoutNG version of BackgroundImageGeometry.
BackgroundImageGeometry geometry(*static_cast<const LayoutBoxModelObject*>(
inline_box_fragment_.GetLayoutObject()));
NGBoxFragmentPainter box_painter(inline_box_fragment_);
PaintBoxDecorationBackground(
box_painter, paint_info, paint_offset, adjusted_frame_rect, geometry,
border_edges_.line_left, border_edges_.line_right);
object_has_multiple_boxes, border_edges_.line_left,
border_edges_.line_right);
}
void NGInlineBoxFragmentPainter::ComputeFragmentOffsetOnLine(
......@@ -101,7 +99,6 @@ void NGInlineBoxFragmentPainter::ComputeFragmentOffsetOnLine(
LayoutUnit* offset_on_line,
LayoutUnit* total_width) const {
WritingMode writing_mode = inline_box_fragment_.Style().GetWritingMode();
DCHECK(object_has_multiple_boxes_);
NGPaintFragment::FragmentRange fragments =
inline_box_fragment_.InlineFragmentsFor(
inline_box_fragment_.GetLayoutObject());
......@@ -139,7 +136,6 @@ LayoutRect NGInlineBoxFragmentPainter::PaintRectForImageStrip(
// multiple lines, you still paint it as though you had one single line. This
// means each line has to pick up the background where the previous line left
// off.
DCHECK(object_has_multiple_boxes_);
LayoutUnit offset_on_line;
LayoutUnit total_width;
ComputeFragmentOffsetOnLine(direction, &offset_on_line, &total_width);
......@@ -184,7 +180,8 @@ static LayoutRect NGClipRectForNinePieceImageStrip(
InlineBoxPainterBase::BorderPaintingType
NGInlineBoxFragmentPainter::GetBorderPaintType(
const LayoutRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect) const {
IntRect& adjusted_clip_rect,
bool object_has_multiple_boxes) const {
adjusted_clip_rect = PixelSnappedIntRect(adjusted_frame_rect);
if (inline_box_fragment_.Parent() &&
inline_box_fragment_.Style().HasBorderDecoration()) {
......@@ -199,7 +196,7 @@ NGInlineBoxFragmentPainter::GetBorderPaintType(
// The simple case is where we either have no border image or we are the
// only box for this object. In those cases only a single call to draw is
// required.
if (!has_border_image || !object_has_multiple_boxes_)
if (!has_border_image || !object_has_multiple_boxes)
return kPaintBordersWithoutClip;
// We have a border image that spans multiple lines.
......@@ -211,4 +208,20 @@ NGInlineBoxFragmentPainter::GetBorderPaintType(
return kDontPaintBorders;
}
void NGInlineBoxFragmentPainter::PaintNormalBoxShadow(
const PaintInfo& info,
const ComputedStyle& s,
const LayoutRect& paint_rect) {
BoxPainterBase::PaintNormalBoxShadow(
info, paint_rect, s, border_edges_.line_left, border_edges_.line_right);
}
void NGInlineBoxFragmentPainter::PaintInsetBoxShadow(
const PaintInfo& info,
const ComputedStyle& s,
const LayoutRect& paint_rect) {
BoxPainterBase::PaintInsetBoxShadowWithBorderRect(
info, paint_rect, s, border_edges_.line_left, border_edges_.line_right);
}
} // namespace blink
......@@ -37,7 +37,14 @@ class NGInlineBoxFragmentPainter : public InlineBoxPainterBase {
BorderPaintingType GetBorderPaintType(
const LayoutRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect) const override;
IntRect& adjusted_clip_rect,
bool object_has_multiple_boxes) const override;
void PaintNormalBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect) override;
void PaintInsetBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect) override;
private:
void PaintBackgroundBorderShadow(const PaintInfo&,
......
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