summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/layout/api/line_layout_item.h
blob: 07fb907c449bb8b8f6702e5c4a620de5fa5c47bc (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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
// Copyright 2015 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_LAYOUT_API_LINE_LAYOUT_ITEM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_API_LINE_LAYOUT_ITEM_H_

#include "base/dcheck_is_on.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/platform/geometry/layout_unit.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"

namespace blink {

class ComputedStyle;
class Document;
class HitTestRequest;
class HitTestLocation;
class LayoutObject;
class LineLayoutBox;
class LineLayoutAPIShim;

static LayoutObject* const kHashTableDeletedValue =
    reinterpret_cast<LayoutObject*>(-1);

class LineLayoutItem {
  DISALLOW_NEW();

 public:
  explicit LineLayoutItem(LayoutObject* layout_object)
      : layout_object_(layout_object) {}

  explicit LineLayoutItem(WTF::HashTableDeletedValueType)
      : layout_object_(kHashTableDeletedValue) {}

  LineLayoutItem(std::nullptr_t) : layout_object_(nullptr) {}

  LineLayoutItem() : layout_object_(nullptr) {}

  explicit operator bool() const { return layout_object_; }

  bool IsEqual(const LayoutObject* layout_object) const {
    return layout_object_ == layout_object;
  }

  bool operator==(const LineLayoutItem& other) const {
    return layout_object_ == other.layout_object_;
  }

  bool operator!=(const LineLayoutItem& other) const {
    return !(*this == other);
  }

  String DebugName() const { return layout_object_->DebugName(); }

  bool NeedsLayout() const { return layout_object_->NeedsLayout(); }

  Node* GetNode() const { return layout_object_->GetNode(); }

  Node* NonPseudoNode() const { return layout_object_->NonPseudoNode(); }

  Node* GetNodeForOwnerNodeId() const {
    auto* layout_text_fragment = DynamicTo<LayoutTextFragment>(layout_object_);
    if (layout_text_fragment)
      return layout_text_fragment->AssociatedTextNode();
    return layout_object_->GetNode();
  }

  LineLayoutItem Parent() const {
    return LineLayoutItem(layout_object_->Parent());
  }

  // Implemented in LineLayoutBox.h
  // Intentionally returns a LineLayoutBox to avoid exposing LayoutBlock
  // to the line layout code.
  LineLayoutBox ContainingBlock() const;

  LineLayoutItem Container() const {
    return LineLayoutItem(layout_object_->Container());
  }

  bool IsDescendantOf(const LineLayoutItem item) const {
    return layout_object_->IsDescendantOf(item.layout_object_);
  }

  void UpdateHitTestResult(HitTestResult& result, const PhysicalOffset& point) {
    return layout_object_->UpdateHitTestResult(result, point);
  }

  LineLayoutItem NextSibling() const {
    return LineLayoutItem(layout_object_->NextSibling());
  }

  LineLayoutItem PreviousSibling() const {
    return LineLayoutItem(layout_object_->PreviousSibling());
  }

  LineLayoutItem SlowFirstChild() const {
    return LineLayoutItem(layout_object_->SlowFirstChild());
  }

  LineLayoutItem SlowLastChild() const {
    return LineLayoutItem(layout_object_->SlowLastChild());
  }

  // TODO(dgrogan/eae): Collapse these 4 methods to 1. Settle on pointer or
  // ref. Give firstLine a default value.
  const ComputedStyle* Style() const { return layout_object_->Style(); }

  const ComputedStyle& StyleRef() const { return layout_object_->StyleRef(); }

  const ComputedStyle* Style(bool first_line) const {
    return layout_object_->Style(first_line);
  }

  const ComputedStyle& StyleRef(bool first_line) const {
    return layout_object_->StyleRef(first_line);
  }

  Document& GetDocument() const { return layout_object_->GetDocument(); }

  bool PreservesNewline() const {
    if (IsSVGInlineText())
      return false;

    return StyleRef().PreserveNewline();
  }

  unsigned length() const { return layout_object_->length(); }

  void DirtyLinesFromChangedChild(
      LineLayoutItem item,
      MarkingBehavior marking_behaviour = kMarkContainerChain) const {
    layout_object_->DirtyLinesFromChangedChild(item.GetLayoutObject(),
                                               marking_behaviour);
  }

  bool AncestorLineBoxDirty() const {
    return layout_object_->AncestorLineBoxDirty();
  }

  // TODO(dgrogan/eae): Remove this method and replace every call with an ||.
  bool IsFloatingOrOutOfFlowPositioned() const {
    return layout_object_->IsFloatingOrOutOfFlowPositioned();
  }

  bool IsFloating() const { return layout_object_->IsFloating(); }

  bool IsOutOfFlowPositioned() const {
    return layout_object_->IsOutOfFlowPositioned();
  }

  bool IsBox() const { return layout_object_->IsBox(); }

  bool IsBoxModelObject() const { return layout_object_->IsBoxModelObject(); }

  bool IsBR() const { return layout_object_->IsBR(); }

  bool IsCombineText() const { return layout_object_->IsCombineText(); }

  bool IsHorizontalWritingMode() const {
    return layout_object_->IsHorizontalWritingMode();
  }

  bool IsImage() const { return layout_object_->IsImage(); }

  bool IsInline() const { return layout_object_->IsInline(); }

  bool IsInlineBlockOrInlineTable() const {
    return layout_object_->IsInlineBlockOrInlineTable();
  }

  bool IsInlineElementContinuation() const {
    return layout_object_->IsInlineElementContinuation();
  }

  // TODO(dgrogan/eae): Replace isType with an enum in the API? As it stands
  // we mix isProperty and isType, which is confusing.
  bool IsLayoutBlock() const { return layout_object_->IsLayoutBlock(); }

  bool IsLayoutBlockFlow() const { return layout_object_->IsLayoutBlockFlow(); }

  bool IsLayoutInline() const { return layout_object_->IsLayoutInline(); }

  bool IsListMarker() const { return layout_object_->IsListMarker(); }

  bool IsAtomicInlineLevel() const {
    return layout_object_->IsAtomicInlineLevel();
  }

  bool IsRubyText() const { return layout_object_->IsRubyText(); }

  bool IsRubyRun() const { return layout_object_->IsRubyRun(); }

  bool IsRubyBase() const { return layout_object_->IsRubyBase(); }

  bool IsSVGInline() const { return layout_object_->IsSVGInline(); }

  bool IsSVGInlineText() const { return layout_object_->IsSVGInlineText(); }

  bool IsSVGText() const { return layout_object_->IsSVGText(); }

  bool IsSVGTextPath() const { return layout_object_->IsSVGTextPath(); }

  bool IsTableCell() const { return layout_object_->IsTableCell(); }

  bool IsText() const { return layout_object_->IsText(); }

  bool IsEmptyText() const {
    return IsText() && To<LayoutText>(layout_object_)->GetText().IsEmpty();
  }

  bool HasLayer() const { return layout_object_->HasLayer(); }

  bool SelfNeedsLayout() const { return layout_object_->SelfNeedsLayout(); }

  // |SetAncestorLineBoxDirty()| invalidates |layout_object|, should be
  // |LayoutInline|, with |kLineBoxesChanged|.
  // Note: |AncestorLineBoxDirty| flag itself is used for preventing
  // invalidation on |layout_object_| more than once and used only in
  // |LineBoxList::DirtyLinesFromChangedChild()|.
  void SetAncestorLineBoxDirty() const {
    layout_object_->SetAncestorLineBoxDirty();
  }

  // TODO(yosin): We should not use |CaretMaxOffset()|, because this function
  // may be used for creating invalid pointer, e.g. <hr>@1.
  int CaretMaxOffset() const {
    if (layout_object_->IsAtomicInlineLevel()) {
      if (Node* const node = layout_object_->GetNode())
        return std::max(1u, GetNode()->CountChildren());
      return 1;
    }
    if (layout_object_->IsHR())
      return 1;
    return 0;
  }

  bool HasFlippedBlocksWritingMode() const {
    return layout_object_->HasFlippedBlocksWritingMode();
  }

  bool VisibleToHitTestRequest(const HitTestRequest& request) const {
    return layout_object_->VisibleToHitTestRequest(request);
  }

  bool HitTestAllPhases(HitTestResult& result,
                        const HitTestLocation& hit_test_location,
                        const PhysicalOffset& accumulated_offset) {
    return layout_object_->HitTestAllPhases(result, hit_test_location,
                                            accumulated_offset);
  }

  bool IsSelected() const { return layout_object_->IsSelected(); }

  // TODO(dgrogan/eae): Needed for Color::current. Can we move this somewhere?
  Color ResolveColor(const ComputedStyle& style_to_use,
                     const CSSProperty& color_property) {
    return layout_object_->ResolveColor(style_to_use, color_property);
  }

  bool IsInFlowPositioned() const {
    return layout_object_->IsInFlowPositioned();
  }

  bool IsRelPositioned() const { return layout_object_->IsRelPositioned(); }

  // TODO(dgrogan/eae): Can we change this to GlobalToLocal and vice versa
  // instead of having 4 methods? See localToAbsoluteQuad below.
  PositionWithAffinity PositionForPoint(const PhysicalOffset& point) {
    return layout_object_->PositionForPoint(point);
  }

  PositionWithAffinity CreatePositionWithAffinity(int offset,
                                                  TextAffinity affinity) {
    return layout_object_->CreatePositionWithAffinity(offset, affinity);
  }

  PositionWithAffinity PositionAfterThis() const {
    return layout_object_->PositionAfterThis();
  }

  PositionWithAffinity PositionBeforeThis() const {
    return layout_object_->PositionBeforeThis();
  }

  LineLayoutItem PreviousInPreOrder(const LayoutObject* stay_within) const {
    return LineLayoutItem(layout_object_->PreviousInPreOrder(stay_within));
  }

  bool IsScrollContainer() const { return layout_object_->IsScrollContainer(); }

  // TODO(dgrogan/eae): Can we instead add a TearDown method to the API
  // instead of exposing this and other shutdown code to line layout?
  bool DocumentBeingDestroyed() const {
    return layout_object_->DocumentBeingDestroyed();
  }

  bool IsHashTableDeletedValue() const {
    return layout_object_ == kHashTableDeletedValue;
  }

  void SetShouldDoFullPaintInvalidation() {
    layout_object_->SetShouldDoFullPaintInvalidation();
  }

  void SlowSetPaintingLayerNeedsRepaint() {
    ObjectPaintInvalidator(*layout_object_).SlowSetPaintingLayerNeedsRepaint();
  }

  void SetIsTruncated(bool set_truncation) {
    layout_object_->SetIsTruncated(set_truncation);
  }

  bool IsTruncated() { return layout_object_->IsTruncated(); }

  bool EverHadLayout() const { return layout_object_->EverHadLayout(); }

  struct LineLayoutItemHash {
    STATIC_ONLY(LineLayoutItemHash);
    static unsigned GetHash(const LineLayoutItem& key) {
      return WTF::PtrHash<LayoutObject>::GetHash(key.layout_object_);
    }
    static bool Equal(const LineLayoutItem& a, const LineLayoutItem& b) {
      return WTF::PtrHash<LayoutObject>::Equal(a.layout_object_,
                                               b.layout_object_);
    }
    static const bool safe_to_compare_to_empty_or_deleted = true;
  };

#if DCHECK_IS_ON()

  const char* GetName() const { return layout_object_->GetName(); }

  // Intentionally returns a void* to avoid exposing LayoutObject* to the line
  // layout code.
  void* DebugPointer() const { return layout_object_; }

  void ShowTreeForThis() const { layout_object_->ShowTreeForThis(); }

  String DecoratedName() const { return layout_object_->DecoratedName(); }

#endif

  LayoutObject* GetLayoutObject() { return layout_object_; }
  const LayoutObject* GetLayoutObject() const { return layout_object_; }

 private:
  LayoutObject* layout_object_;

  friend class LayoutBlockFlow;
  friend class LineLayoutAPIShim;
  friend class LineLayoutBlockFlow;
  friend class LineLayoutBox;
  friend class LineLayoutRubyRun;
};

}  // namespace blink

namespace WTF {

template <>
struct DefaultHash<blink::LineLayoutItem> {
  using Hash = blink::LineLayoutItem::LineLayoutItemHash;
};

template <>
struct HashTraits<blink::LineLayoutItem>
    : SimpleClassHashTraits<blink::LineLayoutItem> {
  STATIC_ONLY(HashTraits);
};

}  // namespace WTF

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_API_LINE_LAYOUT_ITEM_H_