Commit 414c5c87 authored by Emil A Eklund's avatar Emil A Eklund Committed by Commit Bot

Reland "[LayoutNG] Fix border/background painting for multi-line"

Fix border, background, and mask painting for inline blocks spanning two
or more lines or that are otherwise fragmented across multiple entities.

This involved refactoring the existing inline box painting code to allow
code sharing between legacy and LayoutNG painting code. It also required
changing LayoutNG painting to further distinguish between inline and non
inline boxes as the background image painting code in particular require
taking the other fragments for a fragmented object into account when the
image offsets and clipping is computed.

Finally, this cleans up the flow box paint logic for both legacy and NG.

This reverts r561186 (01dda95e) which in
turn was a revert of the original patch (r558871) which was reverted due
to a performance regression in blink_perf.paint color-changes benchmark.

To avoid the regression this patch moves construction of the box painter
from the inline box painter constructor to the paint methods where it is
needed, thereby avoiding the construction overhead in cases where cached
drawings may be reused. It also limits the lifecycle of the box painter.

Bug: 714962, 844624
Test: fast/backgrounds/border-radius-split-background-image.html

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: I87ae744fdd204133e40b50721eca6947c81da817
Reviewed-on: https://chromium-review.googlesource.com/1144216
Commit-Queue: Emil A Eklund <eae@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577385}
parent 5e8f9218
...@@ -476,8 +476,6 @@ crbug.com/591099 external/wpt/xhr/open-url-redirected-worker-origin.htm [ Failur ...@@ -476,8 +476,6 @@ crbug.com/591099 external/wpt/xhr/open-url-redirected-worker-origin.htm [ Failur
crbug.com/591099 external/wpt/xhr/send-authentication-prompt-2-manual.htm [ Failure ] crbug.com/591099 external/wpt/xhr/send-authentication-prompt-2-manual.htm [ Failure ]
crbug.com/591099 fast/backgrounds/background-clip-text.html [ Failure ] crbug.com/591099 fast/backgrounds/background-clip-text.html [ Failure ]
crbug.com/591099 fast/backgrounds/background-leakage-transforms.html [ Failure ] crbug.com/591099 fast/backgrounds/background-leakage-transforms.html [ Failure ]
crbug.com/591099 fast/backgrounds/border-radius-split-background-image.html [ Failure ]
crbug.com/591099 fast/backgrounds/border-radius-split-background.html [ Failure ]
crbug.com/591099 fast/backgrounds/quirks-mode-line-box-backgrounds.html [ Failure ] crbug.com/591099 fast/backgrounds/quirks-mode-line-box-backgrounds.html [ Failure ]
crbug.com/591099 fast/backgrounds/size/backgroundSize16.html [ Failure ] crbug.com/591099 fast/backgrounds/size/backgroundSize16.html [ Failure ]
crbug.com/591099 fast/block/basic/quirk-percent-height-table-cell.html [ Failure ] crbug.com/591099 fast/block/basic/quirk-percent-height-table-cell.html [ Failure ]
...@@ -492,13 +490,9 @@ crbug.com/591099 fast/block/positioning/positioned-child-inside-relative-positio ...@@ -492,13 +490,9 @@ crbug.com/591099 fast/block/positioning/positioned-child-inside-relative-positio
crbug.com/591099 fast/borders/bidi-002.html [ Failure ] crbug.com/591099 fast/borders/bidi-002.html [ Failure ]
crbug.com/859497 fast/borders/bidi-009a.html [ Failure ] crbug.com/859497 fast/borders/bidi-009a.html [ Failure ]
crbug.com/591099 fast/borders/border-image-border-radius.html [ Failure ] crbug.com/591099 fast/borders/border-image-border-radius.html [ Failure ]
crbug.com/714962 fast/borders/border-image-outset-split-inline.html [ Failure ]
crbug.com/714962 fast/borders/border-styles-split.html [ Failure ]
crbug.com/591099 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ] crbug.com/591099 fast/borders/inline-mask-overlay-image-outset-vertical-rl.html [ Failure ]
crbug.com/591099 fast/box-shadow/box-shadow.html [ Failure ] crbug.com/591099 fast/box-shadow/box-shadow.html [ Failure ]
crbug.com/591099 fast/box-shadow/inset-subpixel.html [ Failure ] crbug.com/591099 fast/box-sizing/replaced.html [ Failure Pass ]
crbug.com/591099 fast/box-shadow/inset.html [ Failure ]
crbug.com/591099 fast/box-sizing/replaced.html [ Failure ]
crbug.com/591099 fast/css-generated-content/first-letter-next-sibling-crash.html [ Crash ] crbug.com/591099 fast/css-generated-content/first-letter-next-sibling-crash.html [ Crash ]
crbug.com/591099 fast/css-generated-content/float-first-letter-siblings-convert-to-inline.html [ Crash ] crbug.com/591099 fast/css-generated-content/float-first-letter-siblings-convert-to-inline.html [ Crash ]
crbug.com/591099 fast/css-grid-layout/grid-align-baseline-vertical.html [ Failure ] crbug.com/591099 fast/css-grid-layout/grid-align-baseline-vertical.html [ Failure ]
...@@ -547,10 +541,7 @@ crbug.com/591099 fast/inline/absolute-positioned-block-in-centred-block.html [ F ...@@ -547,10 +541,7 @@ crbug.com/591099 fast/inline/absolute-positioned-block-in-centred-block.html [ F
crbug.com/714962 fast/inline/continuation-outlines-with-layers-2.html [ Failure ] crbug.com/714962 fast/inline/continuation-outlines-with-layers-2.html [ Failure ]
crbug.com/591099 fast/inline/continuation-outlines-with-layers.html [ Failure ] crbug.com/591099 fast/inline/continuation-outlines-with-layers.html [ Failure ]
crbug.com/591099 fast/inline/continuation-outlines.html [ Failure ] crbug.com/591099 fast/inline/continuation-outlines.html [ Failure ]
crbug.com/591099 fast/inline/inline-box-background-long-image.html [ Failure ]
crbug.com/591099 fast/inline/inline-box-background-repeat-x.html [ Failure ]
crbug.com/591099 fast/inline/inline-box-background-repeat-y.html [ Failure ] crbug.com/591099 fast/inline/inline-box-background-repeat-y.html [ Failure ]
crbug.com/591099 fast/inline/inline-box-background.html [ Failure ]
crbug.com/591099 fast/inline/inline-focus-ring-under-absolute-enclosing-relative-div.html [ Failure ] crbug.com/591099 fast/inline/inline-focus-ring-under-absolute-enclosing-relative-div.html [ Failure ]
crbug.com/591099 fast/inline/inline-with-empty-inline-children.html [ Failure ] crbug.com/591099 fast/inline/inline-with-empty-inline-children.html [ Failure ]
crbug.com/591099 fast/inline/nested-text-descendants.html [ Failure ] crbug.com/591099 fast/inline/nested-text-descendants.html [ Failure ]
...@@ -594,13 +585,10 @@ crbug.com/591099 fast/text/unicode-fallback-font.html [ Failure ] ...@@ -594,13 +585,10 @@ crbug.com/591099 fast/text/unicode-fallback-font.html [ Failure ]
crbug.com/591099 fast/text/whitespace/018.html [ Failure ] crbug.com/591099 fast/text/whitespace/018.html [ Failure ]
crbug.com/591099 fast/writing-mode/auto-sizing-orthogonal-flows.html [ Failure ] crbug.com/591099 fast/writing-mode/auto-sizing-orthogonal-flows.html [ Failure ]
crbug.com/714962 fast/writing-mode/background-vertical-lr.html [ Failure ] crbug.com/714962 fast/writing-mode/background-vertical-lr.html [ Failure ]
crbug.com/591099 fast/writing-mode/background-vertical-rl.html [ Failure ]
crbug.com/591099 fast/writing-mode/basic-vertical-line.html [ Failure ] crbug.com/591099 fast/writing-mode/basic-vertical-line.html [ Failure ]
crbug.com/591099 fast/writing-mode/border-image-vertical-lr.html [ Failure ] crbug.com/591099 fast/writing-mode/border-image-vertical-lr.html [ Failure ]
crbug.com/714962 fast/writing-mode/border-image-vertical-rl.html [ Failure ]
crbug.com/591099 fast/writing-mode/border-radius-clipping-vertical-lr.html [ Failure ] crbug.com/591099 fast/writing-mode/border-radius-clipping-vertical-lr.html [ Failure ]
crbug.com/714962 fast/writing-mode/border-styles-vertical-lr.html [ Failure ] crbug.com/714962 fast/writing-mode/border-styles-vertical-lr.html [ Failure ]
crbug.com/714962 fast/writing-mode/border-styles-vertical-rl.html [ Failure ]
crbug.com/591099 fast/writing-mode/fieldsets.html [ Failure ] crbug.com/591099 fast/writing-mode/fieldsets.html [ Failure ]
crbug.com/714962 fast/writing-mode/flipped-blocks-hit-test-line-edges.html [ Failure ] crbug.com/714962 fast/writing-mode/flipped-blocks-hit-test-line-edges.html [ Failure ]
crbug.com/591099 fast/writing-mode/percentage-height-orthogonal-writing-modes.html [ Failure ] crbug.com/591099 fast/writing-mode/percentage-height-orthogonal-writing-modes.html [ Failure ]
......
layer at (0,0) size 800x600
LayoutView at (0,0) size 800x600
layer at (0,0) size 800x600
LayoutNGBlockFlow {HTML} at (0,0) size 800x600
LayoutNGBlockFlow {BODY} at (8,8) size 784x584
LayoutNGBlockFlow {DIV} at (0,0) size 179x452 [border: (1px solid #000000)]
LayoutInline {SPAN} at (0,0) size 177x418 [bgcolor=#808080] [border: (2px solid #000000)]
LayoutText {#text} at (3,19) size 50x114
text run at (3,19) width 50: " "
LayoutBR {BR} at (53,19) size 0x0
LayoutText {#text} at (1,169) size 125x114
text run at (1,169) width 125: " "
LayoutBR {BR} at (126,169) size 0x0
LayoutText {#text} at (1,319) size 175x114
text run at (1,319) width 175: " "
LayoutText {#text} at (0,0) size 0x0
LayoutText {#text} at (179,394) size 4x19
text run at (179,394) width 4: " "
LayoutNGBlockFlow {DIV} at (183,230) size 452x179 [border: (1px solid #000000)]
LayoutInline {SPAN} at (0,0) size 418x177 [bgcolor=#808080] [border: (2px solid #000000)]
LayoutText {#text} at (319,3) size 114x50
text run at (319,3) width 50: " "
LayoutBR {BR} at (319,53) size 0x0
LayoutText {#text} at (169,1) size 114x125
text run at (169,1) width 125: " "
LayoutBR {BR} at (169,126) size 0x0
LayoutText {#text} at (19,1) size 114x175
text run at (19,1) width 175: " "
LayoutText {#text} at (0,0) size 0x0
LayoutText {#text} at (0,0) size 0x0
layer at (0,0) size 800x600
LayoutView at (0,0) size 800x600
layer at (0,0) size 800x600
LayoutNGBlockFlow {HTML} at (0,0) size 800x600
LayoutNGBlockFlow {BODY} at (8,8) size 784x584
LayoutNGBlockFlow {DIV} at (0,0) size 179x452 [border: (1px solid #000000)]
LayoutInline {SPAN} at (0,0) size 177x418 [bgcolor=#C0C0C0] [border: (2px solid #000000)]
LayoutText {#text} at (3,19) size 50x114
text run at (3,19) width 50: " "
LayoutBR {BR} at (53,19) size 0x0
LayoutText {#text} at (1,169) size 125x114
text run at (1,169) width 125: " "
LayoutBR {BR} at (126,169) size 0x0
LayoutText {#text} at (1,319) size 175x114
text run at (1,319) width 175: " "
LayoutText {#text} at (0,0) size 0x0
LayoutText {#text} at (179,394) size 4x19
text run at (179,394) width 4: " "
LayoutNGBlockFlow {DIV} at (183,230) size 452x179 [border: (1px solid #000000)]
LayoutInline {SPAN} at (0,0) size 418x177 [bgcolor=#C0C0C0] [border: (2px solid #000000)]
LayoutText {#text} at (319,3) size 114x50
text run at (319,3) width 50: " "
LayoutBR {BR} at (319,53) size 0x0
LayoutText {#text} at (169,1) size 114x125
text run at (169,1) width 125: " "
LayoutBR {BR} at (169,126) size 0x0
LayoutText {#text} at (19,1) size 114x175
text run at (19,1) width 175: " "
LayoutText {#text} at (0,0) size 0x0
LayoutText {#text} at (0,0) size 0x0
...@@ -112,6 +112,8 @@ blink_core_sources("paint") { ...@@ -112,6 +112,8 @@ blink_core_sources("paint") {
"html_canvas_painter.h", "html_canvas_painter.h",
"image_painter.cc", "image_painter.cc",
"image_painter.h", "image_painter.h",
"inline_box_painter_base.cc",
"inline_box_painter_base.h",
"inline_flow_box_painter.cc", "inline_flow_box_painter.cc",
"inline_flow_box_painter.h", "inline_flow_box_painter.h",
"inline_painter.cc", "inline_painter.cc",
...@@ -136,6 +138,8 @@ blink_core_sources("paint") { ...@@ -136,6 +138,8 @@ blink_core_sources("paint") {
"ng/ng_box_fragment_painter.h", "ng/ng_box_fragment_painter.h",
"ng/ng_fragment_painter.cc", "ng/ng_fragment_painter.cc",
"ng/ng_fragment_painter.h", "ng/ng_fragment_painter.h",
"ng/ng_inline_box_fragment_painter.cc",
"ng/ng_inline_box_fragment_painter.h",
"ng/ng_paint_fragment.cc", "ng/ng_paint_fragment.cc",
"ng/ng_paint_fragment.h", "ng/ng_paint_fragment.h",
"ng/ng_paint_fragment_traversal.cc", "ng/ng_paint_fragment_traversal.cc",
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/paint/inline_box_painter_base.h"
#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
#include "third_party/blink/renderer/core/paint/box_painter_base.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
namespace blink {
void InlineBoxPainterBase::PaintBoxDecorationBackground(
BoxPainterBase& box_painter,
const PaintInfo& paint_info,
const LayoutPoint& paint_offset,
LayoutRect adjusted_frame_rect,
BackgroundImageGeometry geometry,
bool include_logical_left_edge,
bool include_logical_right_edge) {
// Shadow comes first and is behind the background and border.
PaintNormalBoxShadow(paint_info, line_style_, adjusted_frame_rect);
Color background_color =
line_style_.VisitedDependentColor(GetCSSPropertyBackgroundColor());
PaintFillLayers(box_painter, paint_info, background_color,
line_style_.BackgroundLayers(), adjusted_frame_rect,
geometry);
PaintInsetBoxShadow(paint_info, line_style_, adjusted_frame_rect);
IntRect adjusted_clip_rect;
BorderPaintingType border_painting_type =
GetBorderPaintType(adjusted_frame_rect, adjusted_clip_rect);
switch (border_painting_type) {
case kDontPaintBorders:
break;
case kPaintBordersWithoutClip:
BoxPainterBase::PaintBorder(
image_observer_, *document_, node_, paint_info, adjusted_frame_rect,
line_style_, kBackgroundBleedNone, include_logical_left_edge,
include_logical_right_edge);
break;
case kPaintBordersWithClip:
// FIXME: What the heck do we do with RTL here? The math we're using is
// obviously not right, but it isn't even clear how this should work at
// all.
LayoutRect image_strip_paint_rect =
PaintRectForImageStrip(adjusted_frame_rect, TextDirection::kLtr);
GraphicsContextStateSaver state_saver(paint_info.context);
paint_info.context.Clip(adjusted_clip_rect);
BoxPainterBase::PaintBorder(image_observer_, *document_, node_,
paint_info, image_strip_paint_rect,
line_style_);
break;
}
}
void InlineBoxPainterBase::PaintFillLayers(BoxPainterBase& box_painter,
const PaintInfo& info,
const Color& c,
const FillLayer& layer,
const LayoutRect& rect,
BackgroundImageGeometry& geometry,
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);
}
void InlineBoxPainterBase::PaintFillLayer(BoxPainterBase& box_painter,
const PaintInfo& paint_info,
const Color& c,
const FillLayer& fill_layer,
const LayoutRect& paint_rect,
BackgroundImageGeometry& geometry,
SkBlendMode op) {
StyleImage* img = fill_layer.GetImage();
bool has_fill_image = img && img->CanRender();
if (!object_has_multiple_boxes_ ||
(!has_fill_image && !style_.HasBorderRadius())) {
box_painter.PaintFillLayer(paint_info, c, fill_layer, paint_rect,
kBackgroundBleedNone, geometry, op, false);
return;
}
// Handle fill images that clone or spans multiple lines.
bool multi_line = object_has_multiple_boxes_ &&
style_.BoxDecorationBreak() != EBoxDecorationBreak::kClone;
LayoutRect rect = multi_line
? PaintRectForImageStrip(paint_rect, style_.Direction())
: paint_rect;
GraphicsContextStateSaver state_saver(paint_info.context);
paint_info.context.Clip(PixelSnappedIntRect(paint_rect));
box_painter.PaintFillLayer(paint_info, c, fill_layer, rect,
kBackgroundBleedNone, geometry, op, multi_line,
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
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_BOX_PAINTER_BASE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_BOX_PAINTER_BASE_H_
#include "third_party/blink/renderer/core/paint/box_painter_base.h"
#include "third_party/blink/renderer/core/style/shadow_data.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
class Color;
class FillLayer;
class IntRect;
class LayoutPoint;
class LayoutRect;
struct PaintInfo;
class ComputedStyle;
// Common base class for InlineFlowBoxPainter and NGInlineBoxFragmentPainter.
// Implements layout agnostic inline box painting behavior.
class InlineBoxPainterBase {
STACK_ALLOCATED();
public:
InlineBoxPainterBase(const ImageResourceObserver& image_observer,
const Document* document,
Node* node,
const ComputedStyle& style,
const ComputedStyle& line_style)
: image_observer_(image_observer),
document_(document),
node_(node),
style_(style),
line_style_(line_style) {}
void PaintBoxDecorationBackground(BoxPainterBase&,
const PaintInfo&,
const LayoutPoint& paint_offset,
LayoutRect adjusted_frame_rect,
BackgroundImageGeometry,
bool include_logical_left_edge,
bool include_logical_right_edge);
protected:
void PaintFillLayers(BoxPainterBase&,
const PaintInfo&,
const Color&,
const FillLayer&,
const LayoutRect&,
BackgroundImageGeometry& geometry,
SkBlendMode op = SkBlendMode::kSrcOver);
void PaintFillLayer(BoxPainterBase&,
const PaintInfo&,
const Color&,
const FillLayer&,
const LayoutRect&,
BackgroundImageGeometry& geometry,
SkBlendMode op);
void PaintNormalBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect);
void PaintInsetBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect);
virtual LayoutRect PaintRectForImageStrip(const LayoutRect&,
TextDirection direction) const = 0;
enum BorderPaintingType {
kDontPaintBorders,
kPaintBordersWithoutClip,
kPaintBordersWithClip
};
virtual BorderPaintingType GetBorderPaintType(
const LayoutRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect) const = 0;
const ImageResourceObserver& image_observer_;
Member<const Document> document_;
Member<Node> node_;
// Style for the corresponding node.
const ComputedStyle& style_;
// 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
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_BOX_PAINTER_BASE_H_
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_FLOW_BOX_PAINTER_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_FLOW_BOX_PAINTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_FLOW_BOX_PAINTER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_INLINE_FLOW_BOX_PAINTER_H_
#include "third_party/blink/renderer/core/paint/box_model_object_painter.h"
#include "third_party/blink/renderer/core/paint/inline_box_painter_base.h"
#include "third_party/blink/renderer/core/style/shadow_data.h" #include "third_party/blink/renderer/core/style/shadow_data.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h" #include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/text/text_direction.h" #include "third_party/blink/renderer/platform/text/text_direction.h"
...@@ -12,23 +14,19 @@ ...@@ -12,23 +14,19 @@
namespace blink { namespace blink {
class Color;
class FillLayer;
class InlineFlowBox; class InlineFlowBox;
class IntRect; class IntRect;
class LayoutPoint; class LayoutPoint;
class LayoutRect; class LayoutRect;
class LayoutSize;
class LayoutUnit; class LayoutUnit;
struct PaintInfo; struct PaintInfo;
class ComputedStyle;
class InlineFlowBoxPainter { class InlineFlowBoxPainter : public InlineBoxPainterBase {
STACK_ALLOCATED(); STACK_ALLOCATED();
public: public:
InlineFlowBoxPainter(const InlineFlowBox& inline_flow_box) InlineFlowBoxPainter(const InlineFlowBox&);
: inline_flow_box_(inline_flow_box) {}
void Paint(const PaintInfo&, void Paint(const PaintInfo&,
const LayoutPoint& paint_offset, const LayoutPoint& paint_offset,
const LayoutUnit line_top, const LayoutUnit line_top,
...@@ -36,40 +34,18 @@ class InlineFlowBoxPainter { ...@@ -36,40 +34,18 @@ class InlineFlowBoxPainter {
LayoutRect FrameRectClampedToLineTopAndBottomIfNeeded() const; LayoutRect FrameRectClampedToLineTopAndBottomIfNeeded() const;
protected:
LayoutRect PaintRectForImageStrip(const LayoutRect&,
TextDirection) const override;
private: private:
void PaintBoxDecorationBackground(const PaintInfo&, void PaintBackgroundBorderShadow(const PaintInfo&,
const LayoutPoint& paint_offset); const LayoutPoint& paint_offset);
void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset); void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset);
void PaintFillLayers(const PaintInfo&,
const Color&, BorderPaintingType GetBorderPaintType(
const FillLayer&, const LayoutRect& adjusted_frame_rect,
const LayoutRect&, IntRect& adjusted_clip_rect) const override;
SkBlendMode op = SkBlendMode::kSrcOver);
void PaintFillLayer(const PaintInfo&,
const Color&,
const FillLayer&,
const LayoutRect&,
SkBlendMode op);
inline bool ShouldForceIncludeLogicalEdges() const;
inline bool IncludeLogicalLeftEdgeForBoxShadow() const;
inline bool IncludeLogicalRightEdgeForBoxShadow() const;
void PaintNormalBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect);
void PaintInsetBoxShadow(const PaintInfo&,
const ComputedStyle&,
const LayoutRect& paint_rect);
LayoutRect PaintRectForImageStrip(const LayoutPoint& paint_offset,
const LayoutSize& frame_size,
TextDirection) const;
enum BorderPaintingType {
kDontPaintBorders,
kPaintBordersWithoutClip,
kPaintBordersWithClip
};
BorderPaintingType GetBorderPaintType(const LayoutRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect) const;
LayoutRect AdjustedPaintRect(const LayoutPoint& paint_offset) const; LayoutRect AdjustedPaintRect(const LayoutPoint& paint_offset) const;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/paint/list_marker_painter.h" #include "third_party/blink/renderer/core/paint/list_marker_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_box_clipper.h" #include "third_party/blink/renderer/core/paint/ng/ng_box_clipper.h"
#include "third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h" #include "third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.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/paint/ng/ng_text_fragment_painter.h" #include "third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h" #include "third_party/blink/renderer/core/paint/object_painter.h"
...@@ -176,17 +177,6 @@ void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) { ...@@ -176,17 +177,6 @@ void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) {
PaintOverflowControlsIfNeeded(info, paint_offset); PaintOverflowControlsIfNeeded(info, paint_offset);
} }
void NGBoxFragmentPainter::PaintInlineBox(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
const LayoutPoint adjusted_paint_offset =
paint_offset + box_fragment_.Offset().ToLayoutPoint();
if (paint_info.phase == PaintPhase::kForeground &&
box_fragment_.Style().Visibility() == EVisibility::kVisible)
PaintBoxDecorationBackground(paint_info, adjusted_paint_offset);
PaintObject(paint_info, adjusted_paint_offset, true);
}
void NGBoxFragmentPainter::PaintObject( void NGBoxFragmentPainter::PaintObject(
const PaintInfo& paint_info, const PaintInfo& paint_info,
const LayoutPoint& paint_offset, const LayoutPoint& paint_offset,
...@@ -335,7 +325,7 @@ void NGBoxFragmentPainter::PaintInlineChild(const NGPaintFragment& child, ...@@ -335,7 +325,7 @@ void NGBoxFragmentPainter::PaintInlineChild(const NGPaintFragment& child,
} else if (fragment.Type() == NGPhysicalFragment::kFragmentBox) { } else if (fragment.Type() == NGPhysicalFragment::kFragmentBox) {
if (child.HasSelfPaintingLayer()) if (child.HasSelfPaintingLayer())
return; return;
NGBoxFragmentPainter(child).PaintInlineBox(descendants_info, paint_offset); NGInlineBoxFragmentPainter(child).Paint(descendants_info, paint_offset);
} else { } else {
NOTREACHED(); NOTREACHED();
} }
...@@ -440,7 +430,6 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackground( ...@@ -440,7 +430,6 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackground(
NGPhysicalSize size = box_fragment_.Size(); NGPhysicalSize size = box_fragment_.Size();
paint_rect = LayoutRect(LayoutPoint(), LayoutSize(size.width, size.height)); paint_rect = LayoutRect(LayoutPoint(), LayoutSize(size.width, size.height));
} }
paint_rect.MoveBy(paint_offset); paint_rect.MoveBy(paint_offset);
bool painting_overflow_contents = bool painting_overflow_contents =
...@@ -776,15 +765,21 @@ void NGBoxFragmentPainter::PaintTextClipMask(GraphicsContext& context, ...@@ -776,15 +765,21 @@ void NGBoxFragmentPainter::PaintTextClipMask(GraphicsContext& context,
bool object_has_multiple_boxes) { bool object_has_multiple_boxes) {
PaintInfo paint_info(context, mask_rect, PaintPhase::kTextClip, PaintInfo paint_info(context, mask_rect, PaintPhase::kTextClip,
kGlobalPaintNormalPhase, 0); kGlobalPaintNormalPhase, 0);
const LayoutSize local_offset = box_fragment_.Offset().ToLayoutSize(); LayoutSize local_offset = box_fragment_.Offset().ToLayoutSize();
if (PhysicalFragment().IsBlockFlow()) { if (object_has_multiple_boxes) {
// TODO(layout-dev): Add support for box-decoration-break: slice NGInlineBoxFragmentPainter inline_box_painter(box_fragment_);
// See BoxModelObjectPainter::LogicalOffsetOnLine if (box_fragment_.Style().BoxDecorationBreak() ==
// if (box_fragment_.Style().BoxDecorationBreak() == EBoxDecorationBreak::kSlice) {
// EBoxDecorationBreak::kSlice) { LayoutUnit offset_on_line;
// local_offset -= LogicalOffsetOnLine(*flow_box_); LayoutUnit total_width;
//} inline_box_painter.ComputeFragmentOffsetOnLine(
PaintBlockFlowContents(paint_info, paint_offset - local_offset); box_fragment_.Style().Direction(), &offset_on_line, &total_width);
LayoutSize line_offset(offset_on_line, LayoutUnit());
local_offset -= box_fragment_.Style().IsHorizontalWritingMode()
? line_offset
: line_offset.TransposedSize();
}
inline_box_painter.Paint(paint_info, paint_offset - local_offset);
} else { } else {
PaintObject(paint_info, paint_offset - local_offset); PaintObject(paint_info, paint_offset - local_offset);
} }
......
...@@ -34,7 +34,9 @@ class NGBoxFragmentPainter : public BoxPainterBase { ...@@ -34,7 +34,9 @@ class NGBoxFragmentPainter : public BoxPainterBase {
NGBoxFragmentPainter(const NGPaintFragment&); NGBoxFragmentPainter(const NGPaintFragment&);
void Paint(const PaintInfo&); void Paint(const PaintInfo&);
void PaintInlineBox(const PaintInfo&, const LayoutPoint& paint_offset); void PaintObject(const PaintInfo&,
const LayoutPoint&,
bool suppress_box_decoration_background = false);
// Hit tests this box fragment. // Hit tests this box fragment.
// @param physical_offset Physical offset of this box fragment in paint layer. // @param physical_offset Physical offset of this box fragment in paint layer.
...@@ -82,9 +84,6 @@ class NGBoxFragmentPainter : public BoxPainterBase { ...@@ -82,9 +84,6 @@ class NGBoxFragmentPainter : public BoxPainterBase {
const LayoutPoint& paint_offset); const LayoutPoint& paint_offset);
void PaintInlineChildBoxUsingLegacyFallback(const NGPhysicalFragment&, void PaintInlineChildBoxUsingLegacyFallback(const NGPhysicalFragment&,
const PaintInfo&); const PaintInfo&);
void PaintObject(const PaintInfo&,
const LayoutPoint&,
bool suppress_box_decoration_background = false);
void PaintBlockFlowContents(const PaintInfo&, void PaintBlockFlowContents(const PaintInfo&,
const LayoutPoint& paint_offset); const LayoutPoint& paint_offset);
void PaintInlineChild(const NGPaintFragment&, void PaintInlineChild(const NGPaintFragment&,
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h"
#include "third_party/blink/renderer/core/layout/background_bleed_avoidance.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_phase.h"
#include "third_party/blink/renderer/core/style/nine_piece_image.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
namespace blink {
NGInlineBoxFragmentPainter::NGInlineBoxFragmentPainter(
const NGPaintFragment& inline_box_fragment)
: InlineBoxPainterBase(
inline_box_fragment,
&inline_box_fragment.GetLayoutObject()->GetDocument(),
inline_box_fragment.GetLayoutObject()->GeneratingNode(),
inline_box_fragment.Style(),
// TODO(layout-dev): Should be first-line style.
inline_box_fragment.Style()),
inline_box_fragment_(inline_box_fragment),
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,
const LayoutPoint& paint_offset) {
const LayoutPoint adjusted_paint_offset =
paint_offset + inline_box_fragment_.Offset().ToLayoutPoint();
if (paint_info.phase == PaintPhase::kForeground)
PaintBackgroundBorderShadow(paint_info, adjusted_paint_offset);
NGBoxFragmentPainter box_painter(inline_box_fragment_);
box_painter.PaintObject(paint_info, adjusted_paint_offset, true);
}
void NGInlineBoxFragmentPainter::PaintBackgroundBorderShadow(
const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
DCHECK(paint_info.phase == PaintPhase::kForeground);
if (inline_box_fragment_.Style().Visibility() != EVisibility::kVisible)
return;
// You can use p::first-line to specify a background. If so, the root line
// boxes for a line may actually have to paint a background.
bool should_paint_box_decoration_background;
if (inline_box_fragment_.Parent()) {
should_paint_box_decoration_background =
inline_box_fragment_.Style().HasBoxDecorationBackground();
} else {
// TODO(kojii): Get from fragment once available.
bool is_first_line = false;
should_paint_box_decoration_background =
is_first_line && line_style_ != style_;
}
if (!should_paint_box_decoration_background)
return;
if (DrawingRecorder::UseCachedDrawingIfPossible(
paint_info.context, inline_box_fragment_,
DisplayItem::kBoxDecorationBackground))
return;
DrawingRecorder recorder(paint_info.context, inline_box_fragment_,
DisplayItem::kBoxDecorationBackground);
LayoutRect frame_rect =
inline_box_fragment_.PhysicalFragment().LocalRect().ToLayoutRect();
LayoutPoint adjusted_paint_offset = paint_offset;
LayoutRect adjusted_frame_rect =
LayoutRect(adjusted_paint_offset, frame_rect.Size());
// 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);
}
void NGInlineBoxFragmentPainter::ComputeFragmentOffsetOnLine(
TextDirection direction,
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());
LayoutUnit before;
LayoutUnit after;
bool before_self = true;
for (auto iter = fragments.begin(); iter != fragments.end(); ++iter) {
if (*iter == &inline_box_fragment_) {
before_self = false;
continue;
}
if (before_self)
before += NGFragment(writing_mode, iter->PhysicalFragment()).InlineSize();
else
after += NGFragment(writing_mode, iter->PhysicalFragment()).InlineSize();
}
NGFragment logical_fragment(writing_mode,
inline_box_fragment_.PhysicalFragment());
*total_width = before + after + logical_fragment.InlineSize();
// We're iterating over the fragments in physical order before so we need to
// swap before and after for RTL.
*offset_on_line = direction == TextDirection::kLtr ? before : after;
}
LayoutRect NGInlineBoxFragmentPainter::PaintRectForImageStrip(
const LayoutRect& paint_rect,
TextDirection direction) const {
// We have a fill/border/mask image that spans multiple lines.
// We need to adjust the offset by the width of all previous lines.
// Think of background painting on inlines as though you had one long line, a
// single continuous strip. Even though that strip has been broken up across
// 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);
if (inline_box_fragment_.Style().IsHorizontalWritingMode()) {
return LayoutRect(paint_rect.X() - offset_on_line, paint_rect.Y(),
total_width, paint_rect.Height());
}
return LayoutRect(paint_rect.X(), paint_rect.Y() - offset_on_line,
paint_rect.Width(), total_width);
}
static LayoutRect NGClipRectForNinePieceImageStrip(
const ComputedStyle& style,
const NGBorderEdges& border_edges,
const NinePieceImage& image,
const LayoutRect& paint_rect) {
LayoutRect clip_rect(paint_rect);
LayoutRectOutsets outsets = style.ImageOutsets(image);
if (style.IsHorizontalWritingMode()) {
clip_rect.SetY(paint_rect.Y() - outsets.Top());
clip_rect.SetHeight(paint_rect.Height() + outsets.Top() + outsets.Bottom());
if (border_edges.line_left) {
clip_rect.SetX(paint_rect.X() - outsets.Left());
clip_rect.SetWidth(paint_rect.Width() + outsets.Left());
}
if (border_edges.line_right)
clip_rect.SetWidth(clip_rect.Width() + outsets.Right());
} else {
clip_rect.SetX(paint_rect.X() - outsets.Left());
clip_rect.SetWidth(paint_rect.Width() + outsets.Left() + outsets.Right());
if (border_edges.line_left) {
clip_rect.SetY(paint_rect.Y() - outsets.Top());
clip_rect.SetHeight(paint_rect.Height() + outsets.Top());
}
if (border_edges.line_right)
clip_rect.SetHeight(clip_rect.Height() + outsets.Bottom());
}
return clip_rect;
}
InlineBoxPainterBase::BorderPaintingType
NGInlineBoxFragmentPainter::GetBorderPaintType(
const LayoutRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect) const {
adjusted_clip_rect = PixelSnappedIntRect(adjusted_frame_rect);
if (inline_box_fragment_.Parent() &&
inline_box_fragment_.Style().HasBorderDecoration()) {
const NinePieceImage& border_image =
inline_box_fragment_.Style().BorderImage();
StyleImage* border_image_source = border_image.GetImage();
bool has_border_image =
border_image_source && border_image_source->CanRender();
if (has_border_image && !border_image_source->IsLoaded())
return kDontPaintBorders;
// 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_)
return kPaintBordersWithoutClip;
// We have a border image that spans multiple lines.
adjusted_clip_rect = PixelSnappedIntRect(NGClipRectForNinePieceImageStrip(
inline_box_fragment_.Style(), border_edges_, border_image,
adjusted_frame_rect));
return kPaintBordersWithClip;
}
return kDontPaintBorders;
}
} // namespace blink
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_INLINE_BOX_FRAGMENT_PAINTER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_INLINE_BOX_FRAGMENT_PAINTER_H_
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_border_edges.h"
#include "third_party/blink/renderer/core/paint/inline_box_painter_base.h"
#include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/skia/include/core/SkBlendMode.h"
namespace blink {
class LayoutRect;
class NGPaintFragment;
struct PaintInfo;
// Painter for LayoutNG inline box fragments. Delegates to NGBoxFragmentPainter
// for all box painting logic that isn't specific to inline boxes.
class NGInlineBoxFragmentPainter : public InlineBoxPainterBase {
STACK_ALLOCATED();
public:
NGInlineBoxFragmentPainter(const NGPaintFragment&);
void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
void ComputeFragmentOffsetOnLine(TextDirection,
LayoutUnit* offset_on_line,
LayoutUnit* total_width) const;
protected:
LayoutRect PaintRectForImageStrip(const LayoutRect&,
TextDirection direction) const override;
BorderPaintingType GetBorderPaintType(
const LayoutRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect) const override;
private:
void PaintBackgroundBorderShadow(const PaintInfo&,
const LayoutPoint& paint_offset);
const NGPaintFragment& inline_box_fragment_;
NGBorderEdges border_edges_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_INLINE_BOX_FRAGMENT_PAINTER_H_
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h" #include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
#include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h" #include "third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h"
namespace blink { namespace blink {
...@@ -345,7 +346,7 @@ void NGPaintFragment::PaintInlineBoxForDescendants( ...@@ -345,7 +346,7 @@ void NGPaintFragment::PaintInlineBoxForDescendants(
DCHECK(layout_object); DCHECK(layout_object);
for (const auto& child : Children()) { for (const auto& child : Children()) {
if (child->GetLayoutObject() == layout_object) { if (child->GetLayoutObject() == layout_object) {
NGBoxFragmentPainter(*child).PaintInlineBox( NGInlineBoxFragmentPainter(*child).Paint(
paint_info, paint_offset + offset.ToLayoutPoint() /*, paint_offset*/); paint_info, paint_offset + offset.ToLayoutPoint() /*, paint_offset*/);
continue; continue;
} }
......
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