summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.h
blob: 478e697015acb4d0d99859a279a8b90ecb40ea59 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
// 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/layout/ng/inline/ng_physical_line_box_fragment.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/allocator.h"

namespace blink {

class NGPaintFragment;
struct PaintInfo;
struct PhysicalRect;

// Common base class for NGInlineBoxFragmentPainter and
// NGLineBoxFragmentPainter.
class NGInlineBoxFragmentPainterBase : public InlineBoxPainterBase {
  STACK_ALLOCATED();

 public:
  void ComputeFragmentOffsetOnLine(TextDirection,
                                   LayoutUnit* offset_on_line,
                                   LayoutUnit* total_width) const;

 protected:
  NGInlineBoxFragmentPainterBase(
      const NGPhysicalFragment& inline_box_fragment,
      const NGPaintFragment* inline_box_paint_fragment,
      const NGFragmentItem* inline_box_item,
      const LayoutObject& layout_object,
      const ComputedStyle& style,
      const ComputedStyle& line_style)
      : InlineBoxPainterBase(layout_object,
                             &layout_object.GetDocument(),
                             layout_object.GeneratingNode(),
                             style,
                             line_style),
        inline_box_fragment_(inline_box_fragment),
        inline_box_paint_fragment_(inline_box_paint_fragment),
        inline_box_item_(inline_box_item) {
#if DCHECK_IS_ON()
    if (inline_box_paint_fragment) {
      DCHECK_EQ(&inline_box_paint_fragment->PhysicalFragment(),
                &inline_box_fragment);
      DCHECK(!inline_box_item);
    } else if (inline_box_item) {
      if (inline_box_item->BoxFragment())
        DCHECK_EQ(inline_box_item->BoxFragment(), &inline_box_fragment);
      else
        DCHECK_EQ(inline_box_item->LineBoxFragment(), &inline_box_fragment);
    } else {
      NOTREACHED();
    }
#endif
  }

  // Constructor for |NGPaintFragment|.
  NGInlineBoxFragmentPainterBase(const NGPaintFragment& inline_box_fragment,
                                 const LayoutObject& layout_object,
                                 const ComputedStyle& style,
                                 const ComputedStyle& line_style)
      : NGInlineBoxFragmentPainterBase(inline_box_fragment.PhysicalFragment(),
                                       &inline_box_fragment,
                                       /* inline_box_item */ nullptr,
                                       layout_object,
                                       style,
                                       line_style) {}

  // Constructor for |NGFragmentItem|.
  NGInlineBoxFragmentPainterBase(
      const NGFragmentItem& inline_box_item,
      const NGPhysicalBoxFragment& inline_box_fragment,
      const LayoutObject& layout_object,
      const ComputedStyle& style,
      const ComputedStyle& line_style)
      : NGInlineBoxFragmentPainterBase(inline_box_fragment,
                                       /* inline_box_paint_fragment */ nullptr,
                                       &inline_box_item,
                                       layout_object,
                                       style,
                                       line_style) {}

  const DisplayItemClient& GetDisplayItemClient() const {
    if (inline_box_paint_fragment_)
      return *inline_box_paint_fragment_;
    DCHECK(inline_box_item_);
    return *inline_box_item_;
  }

  const virtual NGBorderEdges BorderEdges() const = 0;

  PhysicalRect PaintRectForImageStrip(const PhysicalRect&,
                                      TextDirection direction) const override;

  BorderPaintingType GetBorderPaintType(
      const PhysicalRect& adjusted_frame_rect,
      IntRect& adjusted_clip_rect,
      bool object_has_multiple_boxes) const override;
  void PaintNormalBoxShadow(const PaintInfo&,
                            const ComputedStyle&,
                            const PhysicalRect& paint_rect) override;
  void PaintInsetBoxShadow(const PaintInfo&,
                           const ComputedStyle&,
                           const PhysicalRect& paint_rect) override;

  void PaintBackgroundBorderShadow(const PaintInfo&,
                                   const PhysicalOffset& paint_offset);

  const NGPhysicalFragment& inline_box_fragment_;
  const NGPaintFragment* inline_box_paint_fragment_ = nullptr;
  const NGFragmentItem* inline_box_item_ = nullptr;
};

// Painter for LayoutNG inline box fragments. Delegates to NGBoxFragmentPainter
// for all box painting logic that isn't specific to inline boxes.
class NGInlineBoxFragmentPainter : public NGInlineBoxFragmentPainterBase {
  STACK_ALLOCATED();

 public:
  // Constructor for |NGPaintFragment|.
  NGInlineBoxFragmentPainter(const NGPaintFragment& inline_box_fragment)
      : NGInlineBoxFragmentPainterBase(inline_box_fragment,
                                       *inline_box_fragment.GetLayoutObject(),
                                       inline_box_fragment.Style(),
                                       inline_box_fragment.Style()) {
    DCHECK_EQ(inline_box_fragment.PhysicalFragment().Type(),
              NGPhysicalFragment::NGFragmentType::kFragmentBox);
    DCHECK_EQ(inline_box_fragment.PhysicalFragment().BoxType(),
              NGPhysicalFragment::NGBoxType::kInlineBox);
  }

  // Constructor for |NGFragmentItem|.
  NGInlineBoxFragmentPainter(const NGFragmentItem& inline_box_item,
                             const NGPhysicalBoxFragment& inline_box_fragment,
                             NGInlineCursor* descendants = nullptr)
      : NGInlineBoxFragmentPainterBase(inline_box_item,
                                       inline_box_fragment,
                                       *inline_box_fragment.GetLayoutObject(),
                                       inline_box_fragment.Style(),
                                       inline_box_fragment.Style()),
        descendants_(descendants) {
    DCHECK_EQ(inline_box_fragment.Type(),
              NGPhysicalFragment::NGFragmentType::kFragmentBox);
    DCHECK_EQ(inline_box_fragment.BoxType(),
              NGPhysicalFragment::NGBoxType::kInlineBox);
  }

  void Paint(const PaintInfo&, const PhysicalOffset& paint_offset);

  static void PaintAllFragments(const LayoutInline& layout_inline,
                                const PaintInfo&,
                                const PhysicalOffset& paint_offset);

 private:
  const NGPhysicalBoxFragment& PhysicalFragment() const {
    return static_cast<const NGPhysicalBoxFragment&>(inline_box_fragment_);
  }

  const NGBorderEdges BorderEdges() const final;

  mutable base::Optional<NGBorderEdges> border_edges_;
  NGInlineCursor* descendants_ = nullptr;
};

// Painter for LayoutNG line box fragments. Line boxes don't paint anything,
// except when ::first-line style has background properties specified.
// https://drafts.csswg.org/css-pseudo-4/#first-line-styling
class NGLineBoxFragmentPainter : public NGInlineBoxFragmentPainterBase {
  STACK_ALLOCATED();

 public:
  NGLineBoxFragmentPainter(const NGPhysicalFragment& line_box_fragment,
                           const NGPaintFragment* line_box_paint_fragment,
                           const NGFragmentItem* line_box_item,
                           const NGPhysicalBoxFragment& block_fragment,
                           const NGPaintFragment* block_paint_fragment)
      : NGLineBoxFragmentPainter(line_box_fragment,
                                 line_box_paint_fragment,
                                 line_box_item,
                                 block_fragment,
                                 block_paint_fragment,
                                 *block_fragment.GetLayoutObject()) {}

  static bool NeedsPaint(const NGPhysicalFragment& line_fragment) {
    DCHECK_EQ(line_fragment.Type(),
              NGPhysicalFragment::NGFragmentType::kFragmentLineBox);
    return line_fragment.UsesFirstLineStyle();
  }

  // Borders are not part of ::first-line style and therefore not painted, but
  // the function name is kept consistent with other classes.
  void PaintBackgroundBorderShadow(const PaintInfo&,
                                   const PhysicalOffset& paint_offset);

 private:
  NGLineBoxFragmentPainter(const NGPhysicalFragment& line_box_fragment,
                           const NGPaintFragment* line_box_paint_fragment,
                           const NGFragmentItem* line_box_item,
                           const NGPhysicalBoxFragment& block_fragment,
                           const NGPaintFragment* block_paint_fragment,
                           const LayoutObject& layout_block_flow)
      : NGInlineBoxFragmentPainterBase(
            line_box_fragment,
            line_box_paint_fragment,
            line_box_item,
            layout_block_flow,
            // Use the style from the containing block. |line_fragment.Style()|
            // is a copy at the time of the last layout to reflect the line
            // direction, and its paint properties may have been changed.
            // TODO(kojii): Reconsider |line_fragment.Style()|.
            layout_block_flow.StyleRef(),
            layout_block_flow.FirstLineStyleRef()),
        block_fragment_(block_fragment),
        block_paint_fragment_(block_paint_fragment) {
    DCHECK_EQ(line_box_fragment.Type(),
              NGPhysicalFragment::NGFragmentType::kFragmentLineBox);
    DCHECK(NeedsPaint(line_box_fragment));
    DCHECK(layout_block_flow.IsLayoutNGMixin());
  }

  const NGPhysicalLineBoxFragment& PhysicalFragment() const {
    return static_cast<const NGPhysicalLineBoxFragment&>(inline_box_fragment_);
  }

  const NGBorderEdges BorderEdges() const final { return NGBorderEdges(); }

  const NGPhysicalBoxFragment& block_fragment_;
  const NGPaintFragment* block_paint_fragment_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_INLINE_BOX_FRAGMENT_PAINTER_H_