-
Notifications
You must be signed in to change notification settings - Fork 6.6k
/
ng_box_fragment_builder.h
705 lines (599 loc) · 28.3 KB
/
ng_box_fragment_builder.h
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
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
// Copyright 2016 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_NG_NG_BOX_FRAGMENT_BUILDER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BOX_FRAGMENT_BUILDER_H_
#include "base/dcheck_is_on.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/renderer/core/layout/geometry/box_sides.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_fragment_geometry.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
#include "third_party/blink/renderer/core/layout/ng/mathml/ng_mathml_paint_info.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_break_token.h"
#include "third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h"
#include "third_party/blink/renderer/core/layout/ng/table/ng_table_fragment_data.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
namespace blink {
class NGPhysicalFragment;
class CORE_EXPORT NGBoxFragmentBuilder final
: public NGContainerFragmentBuilder {
STACK_ALLOCATED();
public:
NGBoxFragmentBuilder(NGLayoutInputNode node,
scoped_refptr<const ComputedStyle> style,
const NGConstraintSpace* space,
WritingDirectionMode writing_direction)
: NGContainerFragmentBuilder(node,
std::move(style),
space,
writing_direction),
box_type_(NGPhysicalFragment::NGBoxType::kNormalBox),
is_inline_formatting_context_(node.IsInline()) {}
// Build a fragment for LayoutObject without NGLayoutInputNode. LayoutInline
// has NGInlineItem but does not have corresponding NGLayoutInputNode.
NGBoxFragmentBuilder(LayoutObject* layout_object,
scoped_refptr<const ComputedStyle> style,
WritingDirectionMode writing_direction)
: NGContainerFragmentBuilder(/* node */ nullptr,
std::move(style),
/* space */ nullptr,
writing_direction),
box_type_(NGPhysicalFragment::NGBoxType::kNormalBox),
is_inline_formatting_context_(true) {
layout_object_ = layout_object;
}
void SetInitialFragmentGeometry(
const NGFragmentGeometry& initial_fragment_geometry) {
initial_fragment_geometry_ = &initial_fragment_geometry;
size_ = initial_fragment_geometry_->border_box_size;
is_initial_block_size_indefinite_ = size_.block_size == kIndefiniteSize;
border_padding_ =
initial_fragment_geometry.border + initial_fragment_geometry.padding;
border_scrollbar_padding_ =
border_padding_ + initial_fragment_geometry.scrollbar;
if (space_) {
child_available_size_ = CalculateChildAvailableSize(
*space_, To<NGBlockNode>(node_), size_, border_scrollbar_padding_);
}
}
void AdjustBorderScrollbarPaddingForFragmentation(
const NGBlockBreakToken* break_token) {
if (LIKELY(!break_token))
return;
if (break_token->IsBreakBefore())
return;
border_scrollbar_padding_.block_start = LayoutUnit();
}
void AdjustBorderScrollbarPaddingForTableCell() {
if (!space_->IsTableCell())
return;
border_scrollbar_padding_ +=
ComputeIntrinsicPadding(*space_, *style_, Scrollbar());
}
const NGFragmentGeometry& InitialFragmentGeometry() const {
DCHECK(initial_fragment_geometry_);
return *initial_fragment_geometry_;
}
// Use the block-size setters/getters further down instead of the inherited
// ones.
LayoutUnit BlockSize() const = delete;
void SetBlockSize(LayoutUnit block_size) = delete;
// Set the total border-box block-size of all the fragments to be generated
// from this node (as if we stitched them together). Layout algorithms are
// expected to pass this value, and at the end of layout (if block
// fragmentation is needed), the fragmentation machinery will be invoked to
// adjust the block-size to the correct size, ensuring that we break at the
// best location.
void SetFragmentsTotalBlockSize(LayoutUnit block_size) {
#if DCHECK_IS_ON()
// Note that we just store the block-size in a shared field. We have a flag
// for debugging, to assert that we know what we're doing when attempting to
// access the data.
block_size_is_for_all_fragments_ = true;
#endif
size_.block_size = block_size;
}
LayoutUnit FragmentsTotalBlockSize() const {
#if DCHECK_IS_ON()
if (has_block_fragmentation_)
DCHECK(block_size_is_for_all_fragments_);
DCHECK(size_.block_size != kIndefiniteSize);
#endif
return size_.block_size;
}
// Set the final block-size of this fragment.
void SetFragmentBlockSize(LayoutUnit block_size) {
#if DCHECK_IS_ON()
// Note that we just store the block-size in a shared field. We have a flag
// for debugging, to assert that we know what we're doing when attempting to
// access the data.
block_size_is_for_all_fragments_ = false;
#endif
size_.block_size = block_size;
}
LayoutUnit FragmentBlockSize() const {
#if DCHECK_IS_ON()
if (has_block_fragmentation_)
DCHECK(!block_size_is_for_all_fragments_);
DCHECK(size_.block_size != kIndefiniteSize);
#endif
return size_.block_size;
}
void SetIntrinsicBlockSize(LayoutUnit intrinsic_block_size) {
intrinsic_block_size_ = intrinsic_block_size;
}
LayoutUnit IntrinsicBlockSize() const { return intrinsic_block_size_; }
const NGBoxStrut& Borders() const {
DCHECK(initial_fragment_geometry_);
DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
return initial_fragment_geometry_->border;
}
const NGBoxStrut& Scrollbar() const {
DCHECK(initial_fragment_geometry_);
return initial_fragment_geometry_->scrollbar;
}
const NGBoxStrut& Padding() const {
DCHECK(initial_fragment_geometry_);
return initial_fragment_geometry_->padding;
}
const LogicalSize& InitialBorderBoxSize() const {
DCHECK(initial_fragment_geometry_);
return initial_fragment_geometry_->border_box_size;
}
const NGBoxStrut& BorderPadding() const {
DCHECK(initial_fragment_geometry_);
return border_padding_;
}
const NGBoxStrut& BorderScrollbarPadding() const {
DCHECK(initial_fragment_geometry_);
return border_scrollbar_padding_;
}
// The child available-size is subtly different from the content-box size of
// an element. For an anonymous-block the child available-size is equal to
// its non-anonymous parent (similar to percentages).
const LogicalSize& ChildAvailableSize() const {
DCHECK(initial_fragment_geometry_);
DCHECK(space_);
return child_available_size_;
}
const NGBlockNode& Node() {
DCHECK(node_);
return To<NGBlockNode>(node_);
}
// Add a break token for a child that doesn't yet have any fragments, because
// its first fragment is to be produced in the next fragmentainer. This will
// add a break token for the child, but no fragment. Break appeal should
// always be provided for regular in-flow children. For other types of
// children it may be omitted, if the break shouldn't affect the appeal of
// breaking inside this container.
void AddBreakBeforeChild(NGLayoutInputNode child,
absl::optional<NGBreakAppeal> appeal,
bool is_forced_break);
// Add a layout result. This involves appending the fragment and its relative
// offset to the builder, but also keeping track of out-of-flow positioned
// descendants, propagating fragmentainer breaks, and more. In some cases,
// such as grid, the relative offset may need to be computed ahead of time.
// If so, a |relative_offset| will be passed in. Otherwise, the relative
// offset will be calculated as normal.
void AddResult(const NGLayoutResult&,
const LogicalOffset,
absl::optional<LogicalOffset> relative_offset = absl::nullopt,
bool propagate_oof_descendants = true);
void AddChild(
const NGPhysicalFragment&,
const LogicalOffset&,
const NGInlineContainer<LogicalOffset>* inline_container = nullptr,
const NGMarginStrut* margin_strut = nullptr,
bool is_self_collapsing = false,
absl::optional<LogicalOffset> relative_offset = absl::nullopt,
absl::optional<LayoutUnit> adjustment_for_oof_propagation = LayoutUnit());
// Manually add a break token to the builder. Note that we're assuming that
// this break token is for content in the same flow as this parent.
void AddBreakToken(scoped_refptr<const NGBreakToken>,
bool is_in_parallel_flow = false);
void AddOutOfFlowLegacyCandidate(NGBlockNode,
const NGLogicalStaticPosition&,
const LayoutInline* inline_container);
// Specify whether this will be the first fragment generated for the node.
void SetIsFirstForNode(bool is_first) { is_first_for_node_ = is_first; }
// Set how much of the block-size we've used so far for this box. This will be
// the sum of the block-size of all previous fragments PLUS the one we're
// building now.
void SetConsumedBlockSize(LayoutUnit size) { consumed_block_size_ = size; }
// Set how much to adjust |consumed_block_size_| for legacy write-back. See
// NGBlockBreakToken::ConsumedBlockSizeForLegacy() for more details.
void SetConsumedBlockSizeLegacyAdjustment(LayoutUnit adjustment) {
consumed_block_size_legacy_adjustment_ = adjustment;
}
// Set how much of the column block-size we've used so far. This will be used
// to determine the block-size of any new columns added by descendant
// out-of-flow positioned elements.
void SetBlockOffsetForAdditionalColumns(LayoutUnit size) {
block_offset_for_additional_columns_ = size;
}
LayoutUnit BlockOffsetForAdditionalColumns() const {
return block_offset_for_additional_columns_;
}
void SetSequenceNumber(unsigned sequence_number) {
sequence_number_ = sequence_number;
}
// During regular layout a break token is created at the end of layout, if
// required. When re-using a previous fragment and its children, though, we
// may want to just re-use the break token as well.
void PresetNextBreakToken(scoped_refptr<const NGBreakToken> break_token) {
// We should either do block fragmentation as part of normal layout, or
// pre-set a break token.
DCHECK(!did_break_self_);
DCHECK(child_break_tokens_.IsEmpty());
break_token_ = std::move(break_token);
}
// Return true if we broke inside this node on our own initiative (typically
// not because of a child break, but rather due to the size of this node).
bool DidBreakSelf() const { return did_break_self_; }
void SetDidBreakSelf() { did_break_self_ = true; }
// Store the previous break token, if one exists.
void SetPreviousBreakToken(
scoped_refptr<const NGBlockBreakToken> break_token) {
previous_break_token_ = std::move(break_token);
}
const NGBlockBreakToken* PreviousBreakToken() const {
return previous_break_token_.get();
}
// Return true if we need to break before or inside any child, doesn't matter
// if it's in-flow or not. As long as there are only breaks in parallel flows,
// we may continue layout, but when we're done, we'll need to create a break
// token for this fragment nevertheless, so that we re-enter, descend and
// resume at the broken children in the next fragmentainer.
bool HasChildBreakInside() const {
if (!child_break_tokens_.IsEmpty())
return true;
// Inline nodes produce a "finished" trailing break token even if we don't
// need to block-fragment.
return last_inline_break_token_.get();
}
// Return true if we need to break before or inside any in-flow child that
// doesn't establish a parallel flow. When this happens, we want to finish our
// fragment, create a break token, and resume in the next fragmentainer.
bool HasInflowChildBreakInside() const {
return has_inflow_child_break_inside_;
}
// Return true if we need to break before or inside any floated child. Floats
// are encapsulated by their container if the container establishes a new
// block formatting context.
bool HasFloatBreakInside() const { return has_float_break_inside_; }
// Report space shortage, i.e. how much more space would have been sufficient
// to prevent some piece of content from breaking. This information may be
// used by the column balancer to stretch columns.
void PropagateSpaceShortage(LayoutUnit space_shortage) {
DCHECK_GT(space_shortage, LayoutUnit());
// Space shortage should only be reported when we already have a tentative
// fragmentainer block-size. It's meaningless to talk about space shortage
// in the initial column balancing pass, because then we have no
// fragmentainer block-size at all, so who's to tell what's too short or
// not?
DCHECK(!IsInitialColumnBalancingPass());
if (minimal_space_shortage_ > space_shortage)
minimal_space_shortage_ = space_shortage;
}
LayoutUnit MinimalSpaceShortage() const { return minimal_space_shortage_; }
void PropagateTallestUnbreakableBlockSize(LayoutUnit unbreakable_block_size) {
// We should only calculate the block-size of the tallest piece of
// unbreakable content during the initial column balancing pass, when we
// haven't set a tentative fragmentainer block-size yet.
DCHECK(IsInitialColumnBalancingPass());
tallest_unbreakable_block_size_ =
std::max(tallest_unbreakable_block_size_, unbreakable_block_size);
}
void SetIsInitialColumnBalancingPass() {
// Note that we have no dedicated flag for being in the initial column
// balancing pass here. We'll just bump tallest_unbreakable_block_size_ to
// 0, so that NGLayoutResult knows that we need to store unbreakable
// block-size.
DCHECK_EQ(tallest_unbreakable_block_size_, LayoutUnit::Min());
tallest_unbreakable_block_size_ = LayoutUnit();
}
bool IsInitialColumnBalancingPass() const {
return tallest_unbreakable_block_size_ >= LayoutUnit();
}
void SetInitialBreakBeforeIfNeeded(EBreakBetween break_before) {
if (!initial_break_before_)
initial_break_before_ = break_before;
}
void SetPreviousBreakAfter(EBreakBetween break_after) {
previous_break_after_ = break_after;
}
// Set when this subtree has modified the incoming margin-strut, such that it
// may change our final position.
void SetSubtreeModifiedMarginStrut() {
DCHECK(!BfcBlockOffset());
subtree_modified_margin_strut_ = true;
}
// Join/"collapse" the previous (stored) break-after value with the next
// break-before value, to determine how to deal with breaking between two
// in-flow siblings.
EBreakBetween JoinedBreakBetweenValue(EBreakBetween break_before) const;
// Return the number of line boxes laid out.
int LineCount() const { return line_count_; }
// Set when we have iterated over all the children. This means that all
// children have been fully laid out, or have break tokens. No more children
// left to discover.
void SetHasSeenAllChildren() { has_seen_all_children_ = true; }
bool HasSeenAllChildren() { return has_seen_all_children_; }
void SetIsAtBlockEnd() { is_at_block_end_ = true; }
bool IsAtBlockEnd() const { return is_at_block_end_; }
// See |NGPhysicalBoxFragment::InflowBounds|.
void SetInflowBounds(const LogicalRect& inflow_bounds) {
DCHECK_NE(box_type_, NGPhysicalBoxFragment::NGBoxType::kInlineBox);
DCHECK(Node().IsScrollContainer());
#if DCHECK_IS_ON()
is_inflow_bounds_explicitly_set_ = true;
#endif
inflow_bounds_ = inflow_bounds;
}
void SetMayHaveDescendantAboveBlockStart(bool b) {
#if DCHECK_IS_ON()
is_may_have_descendant_above_block_start_explicitly_set_ = true;
#endif
may_have_descendant_above_block_start_ = b;
}
void SetColumnSpanner(NGBlockNode spanner) { column_spanner_ = spanner; }
bool FoundColumnSpanner() const { return !!column_spanner_; }
void SetLinesUntilClamp(const absl::optional<int>& value) {
lines_until_clamp_ = value;
}
void SetEarlyBreak(scoped_refptr<const NGEarlyBreak> breakpoint,
NGBreakAppeal appeal) {
early_break_ = breakpoint;
break_appeal_ = appeal;
}
bool HasEarlyBreak() const { return early_break_.get(); }
const NGEarlyBreak& EarlyBreak() const {
DCHECK(early_break_.get());
return *early_break_.get();
}
// Set the highest break appeal found so far. This is either:
// 1: The highest appeal of a breakpoint found by our container
// 2: The appeal of a possible early break inside
// 3: The appeal of an actual break inside (to be stored in a break token)
void SetBreakAppeal(NGBreakAppeal appeal) { break_appeal_ = appeal; }
NGBreakAppeal BreakAppeal() const { return break_appeal_; }
// Offsets are not supposed to be set during fragment construction, so we
// do not provide a setter here.
// Creates the fragment. Can only be called once.
scoped_refptr<const NGLayoutResult> ToBoxFragment() {
DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
return ToBoxFragment(GetWritingMode());
}
scoped_refptr<const NGLayoutResult> ToInlineBoxFragment() {
// The logical coordinate for inline box uses line-relative writing-mode,
// not
// flow-relative.
DCHECK_EQ(BoxType(), NGPhysicalFragment::kInlineBox);
return ToBoxFragment(ToLineWritingMode(GetWritingMode()));
}
NGPhysicalFragment::NGBoxType BoxType() const;
void SetBoxType(NGPhysicalFragment::NGBoxType box_type) {
box_type_ = box_type;
}
bool IsFragmentainerBoxType() const {
return BoxType() == NGPhysicalFragment::kColumnBox;
}
void SetIsFieldsetContainer() { is_fieldset_container_ = true; }
void SetIsTableNGPart() { is_table_ng_part_ = true; }
void SetIsLegacyLayoutRoot() { is_legacy_layout_root_ = true; }
void SetIsInlineFormattingContext(bool is_inline_formatting_context) {
is_inline_formatting_context_ = is_inline_formatting_context;
}
void SetIsMathMLFraction() { is_math_fraction_ = true; }
void SetIsMathMLOperator() { is_math_operator_ = true; }
void SetMathMLPaintInfo(
UChar operator_character,
scoped_refptr<const ShapeResultView> operator_shape_result_view,
LayoutUnit operator_inline_size,
LayoutUnit operator_ascent,
LayoutUnit operator_descent) {
if (!mathml_paint_info_)
mathml_paint_info_ = std::make_unique<NGMathMLPaintInfo>();
mathml_paint_info_->operator_character = operator_character;
mathml_paint_info_->operator_shape_result_view =
std::move(operator_shape_result_view);
mathml_paint_info_->operator_inline_size = operator_inline_size;
mathml_paint_info_->operator_ascent = operator_ascent;
mathml_paint_info_->operator_descent = operator_descent;
}
void SetMathMLPaintInfo(
scoped_refptr<const ShapeResultView> operator_shape_result_view,
LayoutUnit operator_inline_size,
LayoutUnit operator_ascent,
LayoutUnit operator_descent,
LayoutUnit radical_operator_inline_offset,
const NGBoxStrut& radical_base_margins) {
if (!mathml_paint_info_)
mathml_paint_info_ = std::make_unique<NGMathMLPaintInfo>();
mathml_paint_info_->operator_character = kSquareRootCharacter;
mathml_paint_info_->operator_shape_result_view =
std::move(operator_shape_result_view);
mathml_paint_info_->operator_inline_size = operator_inline_size;
mathml_paint_info_->operator_ascent = operator_ascent;
mathml_paint_info_->operator_descent = operator_descent;
mathml_paint_info_->radical_base_margins = radical_base_margins;
mathml_paint_info_->radical_operator_inline_offset =
radical_operator_inline_offset;
}
void SetSidesToInclude(LogicalBoxSides sides_to_include) {
sides_to_include_ = sides_to_include;
}
// Either this function or SetBoxType must be called before ToBoxFragment().
void SetIsNewFormattingContext(bool is_new_fc) { is_new_fc_ = is_new_fc; }
void SetCustomLayoutData(
scoped_refptr<SerializedScriptValue> custom_layout_data) {
custom_layout_data_ = std::move(custom_layout_data);
}
// Sets the alignment baseline for this fragment.
void SetBaseline(LayoutUnit baseline) { baseline_ = baseline; }
absl::optional<LayoutUnit> Baseline() const { return baseline_; }
// Sets the last baseline for this fragment.
void SetLastBaseline(LayoutUnit baseline) {
DCHECK_EQ(space_->BaselineAlgorithmType(),
NGBaselineAlgorithmType::kInlineBlock);
last_baseline_ = baseline;
}
absl::optional<LayoutUnit> LastBaseline() const { return last_baseline_; }
// The inline block baseline is at the block end margin edge under some
// circumstances. This function updates |LastBaseline| in such cases.
void SetLastBaselineToBlockEndMarginEdgeIfNeeded();
void SetTableGridRect(const PhysicalRect& table_grid_rect) {
table_grid_rect_ = table_grid_rect;
}
void SetTableColumnGeometries(
const NGTableFragmentData::ColumnGeometries& table_column_geometries) {
table_column_geometries_ = table_column_geometries;
}
void SetTableCollapsedBorders(const NGTableBorders& table_collapsed_borders) {
table_collapsed_borders_ = &table_collapsed_borders;
}
void SetTableCollapsedBordersGeometry(
std::unique_ptr<NGTableFragmentData::CollapsedBordersGeometry>
table_collapsed_borders_geometry) {
table_collapsed_borders_geometry_ =
std::move(table_collapsed_borders_geometry);
}
void SetTableColumnCount(wtf_size_t table_column_count) {
table_column_count_ = table_column_count;
}
void SetTableCellColumnIndex(wtf_size_t table_cell_column_index) {
table_cell_column_index_ = table_cell_column_index;
}
void TransferGridData(std::unique_ptr<NGGridData> grid_data) {
grid_data_ = std::move(grid_data);
}
const NGGridData& GetNGGridData() const {
DCHECK(grid_data_);
return *grid_data_.get();
}
// The |NGFragmentItemsBuilder| for the inline formatting context of this box.
NGFragmentItemsBuilder* ItemsBuilder() { return items_builder_; }
void SetItemsBuilder(NGFragmentItemsBuilder* builder) {
items_builder_ = builder;
}
// Returns offset for given child. DCHECK if child not found.
// Warning: Do not call unless necessary.
LogicalOffset GetChildOffset(const LayoutObject* child) const;
#if DCHECK_IS_ON()
// If we don't participate in a fragmentation context, this method can check
// that all block fragmentation related fields have their initial value.
void CheckNoBlockFragmentation() const;
#endif
// Moves all the children by |offset| in the block-direction. (Ensure that
// any baselines, OOFs, etc, are also moved by the appropriate amount).
void MoveChildrenInBlockDirection(LayoutUnit offset);
void SetMathItalicCorrection(LayoutUnit italic_correction);
void AdjustOffsetsForFragmentainerDescendant(
NGLogicalOutOfFlowPositionedNode& descendant,
bool only_fixedpos_containing_block = false);
void AdjustFixedposContainingBlockForFragmentainerDescendants();
void AdjustFixedposContainingBlockForInnerMulticols();
// OOF positioned elements inside a fragmentation context are laid out once
// they reach the fragmentation context root, so we need to adjust the offset
// of its containing block to be relative to the fragmentation context
// root. This allows us to determine the proper offset for the OOF inside the
// same context. The block offset returned is the block contribution from
// previous fragmentainers, if the current builder is a fragmentainer.
// Otherwise, |fragmentainer_consumed_block_size| will be used. In some cases,
// for example, we won't be able to calculate the adjustment from the builder.
// This would happen when an OOF positioned element is nested inside another
// OOF positioned element. The nested OOF will never have propagated up
// through a fragmentainer builder. In such cases, the necessary adjustment
// will be passed in via |fragmentainer_consumed_block_size|.
LayoutUnit BlockOffsetAdjustmentForFragmentainer(
LayoutUnit fragmentainer_consumed_block_size = LayoutUnit()) const;
private:
// Update whether we have fragmented in this flow.
void PropagateBreak(const NGLayoutResult&);
void SetHasForcedBreak() {
has_forced_break_ = true;
minimal_space_shortage_ = LayoutUnit::Max();
}
scoped_refptr<const NGLayoutResult> ToBoxFragment(WritingMode);
const NGFragmentGeometry* initial_fragment_geometry_ = nullptr;
NGBoxStrut border_padding_;
NGBoxStrut border_scrollbar_padding_;
LogicalSize child_available_size_;
LayoutUnit intrinsic_block_size_;
absl::optional<LogicalRect> inflow_bounds_;
NGFragmentItemsBuilder* items_builder_ = nullptr;
NGBlockNode column_spanner_ = nullptr;
NGPhysicalFragment::NGBoxType box_type_;
bool may_have_descendant_above_block_start_ = false;
bool is_fieldset_container_ = false;
bool is_table_ng_part_ = false;
bool is_initial_block_size_indefinite_ = false;
bool is_inline_formatting_context_;
bool is_first_for_node_ = true;
bool did_break_self_ = false;
bool has_inflow_child_break_inside_ = false;
bool has_float_break_inside_ = false;
bool has_forced_break_ = false;
bool is_new_fc_ = false;
bool subtree_modified_margin_strut_ = false;
bool has_seen_all_children_ = false;
bool is_math_fraction_ = false;
bool is_math_operator_ = false;
bool is_at_block_end_ = false;
bool has_violating_break_ = false;
LayoutUnit consumed_block_size_;
LayoutUnit consumed_block_size_legacy_adjustment_;
LayoutUnit block_offset_for_additional_columns_;
unsigned sequence_number_ = 0;
LayoutUnit minimal_space_shortage_ = LayoutUnit::Max();
LayoutUnit tallest_unbreakable_block_size_ = LayoutUnit::Min();
// The break-before value on the initial child we cannot honor. There's no
// valid class A break point before a first child, only *between* siblings.
absl::optional<EBreakBetween> initial_break_before_;
// The break-after value of the previous in-flow sibling.
EBreakBetween previous_break_after_ = EBreakBetween::kAuto;
absl::optional<LayoutUnit> baseline_;
absl::optional<LayoutUnit> last_baseline_;
// Table specific types.
absl::optional<PhysicalRect> table_grid_rect_;
absl::optional<NGTableFragmentData::ColumnGeometries>
table_column_geometries_;
scoped_refptr<const NGTableBorders> table_collapsed_borders_;
std::unique_ptr<NGTableFragmentData::CollapsedBordersGeometry>
table_collapsed_borders_geometry_;
absl::optional<wtf_size_t> table_column_count_;
// Table cell specific types.
absl::optional<wtf_size_t> table_cell_column_index_;
// Grid specific types.
std::unique_ptr<NGGridData> grid_data_;
LogicalBoxSides sides_to_include_;
scoped_refptr<SerializedScriptValue> custom_layout_data_;
absl::optional<int> lines_until_clamp_;
std::unique_ptr<NGMathMLPaintInfo> mathml_paint_info_;
absl::optional<NGLayoutResult::MathData> math_data_;
scoped_refptr<const NGBlockBreakToken> previous_break_token_;
#if DCHECK_IS_ON()
// Describes what size_.block_size represents; either the size of a single
// fragment (false), or the size of all fragments for a node (true).
bool block_size_is_for_all_fragments_ = false;
// If any fragment has been added with an offset including the relative
// position, we also need the inflow-bounds set explicitly.
bool needs_inflow_bounds_explicitly_set_ = false;
bool needs_may_have_descendant_above_block_start_explicitly_set_ = false;
bool is_inflow_bounds_explicitly_set_ = false;
bool is_may_have_descendant_above_block_start_explicitly_set_ = false;
#endif
friend class NGBlockBreakToken;
friend class NGPhysicalBoxFragment;
friend class NGLayoutResult;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BOX_FRAGMENT_BUILDER_H_