1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BOX_FRAGMENT_BUILDER_H_
6 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BOX_FRAGMENT_BUILDER_H_
7 
8 #include "third_party/blink/renderer/core/layout/geometry/box_sides.h"
9 #include "third_party/blink/renderer/core/layout/geometry/physical_rect.h"
10 #include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
11 #include "third_party/blink/renderer/core/layout/ng/geometry/ng_fragment_geometry.h"
12 #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
13 #include "third_party/blink/renderer/core/layout/ng/mathml/ng_mathml_paint_info.h"
14 #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
15 #include "third_party/blink/renderer/core/layout/ng/ng_break_token.h"
16 #include "third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h"
17 #include "third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.h"
18 #include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
19 #include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
20 #include "third_party/blink/renderer/core/layout/ng/table/ng_table_borders.h"
21 #include "third_party/blink/renderer/core/layout/ng/table/ng_table_fragment_data.h"
22 #include "third_party/blink/renderer/core/style/computed_style_constants.h"
23 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
24 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
25 
26 namespace blink {
27 
28 class NGPhysicalFragment;
29 
30 class CORE_EXPORT NGBoxFragmentBuilder final
31     : public NGContainerFragmentBuilder {
32   DISALLOW_NEW();
33 
34  public:
NGBoxFragmentBuilder(NGLayoutInputNode node,scoped_refptr<const ComputedStyle> style,const NGConstraintSpace * space,WritingDirectionMode writing_direction)35   NGBoxFragmentBuilder(NGLayoutInputNode node,
36                        scoped_refptr<const ComputedStyle> style,
37                        const NGConstraintSpace* space,
38                        WritingDirectionMode writing_direction)
39       : NGContainerFragmentBuilder(node,
40                                    std::move(style),
41                                    space,
42                                    writing_direction),
43         box_type_(NGPhysicalFragment::NGBoxType::kNormalBox),
44         is_inline_formatting_context_(node.IsInline()) {}
45 
46   // Build a fragment for LayoutObject without NGLayoutInputNode. LayoutInline
47   // has NGInlineItem but does not have corresponding NGLayoutInputNode.
NGBoxFragmentBuilder(LayoutObject * layout_object,scoped_refptr<const ComputedStyle> style,WritingDirectionMode writing_direction)48   NGBoxFragmentBuilder(LayoutObject* layout_object,
49                        scoped_refptr<const ComputedStyle> style,
50                        WritingDirectionMode writing_direction)
51       : NGContainerFragmentBuilder(/* node */ nullptr,
52                                    std::move(style),
53                                    /* space */ nullptr,
54                                    writing_direction),
55         box_type_(NGPhysicalFragment::NGBoxType::kNormalBox),
56         is_inline_formatting_context_(true) {
57     layout_object_ = layout_object;
58   }
59 
SetInitialFragmentGeometry(const NGFragmentGeometry & initial_fragment_geometry)60   void SetInitialFragmentGeometry(
61       const NGFragmentGeometry& initial_fragment_geometry) {
62     initial_fragment_geometry_ = &initial_fragment_geometry;
63     size_ = initial_fragment_geometry_->border_box_size;
64     is_initial_block_size_indefinite_ = size_.block_size == kIndefiniteSize;
65 
66     border_padding_ =
67         initial_fragment_geometry.border + initial_fragment_geometry.padding;
68     border_scrollbar_padding_ =
69         border_padding_ + initial_fragment_geometry.scrollbar;
70     if (space_) {
71       child_available_size_ = CalculateChildAvailableSize(
72           *space_, To<NGBlockNode>(node_), size_, border_scrollbar_padding_);
73     }
74   }
75 
AdjustBorderScrollbarPaddingForFragmentation(const NGBlockBreakToken * break_token)76   void AdjustBorderScrollbarPaddingForFragmentation(
77       const NGBlockBreakToken* break_token) {
78     if (LIKELY(!break_token))
79       return;
80     if (break_token->IsBreakBefore())
81       return;
82     border_scrollbar_padding_.block_start = LayoutUnit();
83   }
84 
AdjustBorderScrollbarPaddingForTableCell()85   void AdjustBorderScrollbarPaddingForTableCell() {
86     if (!space_->IsTableCell())
87       return;
88     border_scrollbar_padding_ +=
89         ComputeIntrinsicPadding(*space_, *style_, Scrollbar());
90   }
91 
InitialFragmentGeometry()92   const NGFragmentGeometry& InitialFragmentGeometry() const {
93     DCHECK(initial_fragment_geometry_);
94     return *initial_fragment_geometry_;
95   }
96 
97   // Use the block-size setters/getters further down instead of the inherited
98   // ones.
99   LayoutUnit BlockSize() const = delete;
100   void SetBlockSize(LayoutUnit block_size) = delete;
101 
102   // Set the total border-box block-size of all the fragments to be generated
103   // from this node (as if we stitched them together). Layout algorithms are
104   // expected to pass this value, and at the end of layout (if block
105   // fragmentation is needed), the fragmentation machinery will be invoked to
106   // adjust the block-size to the correct size, ensuring that we break at the
107   // best location.
SetFragmentsTotalBlockSize(LayoutUnit block_size)108   void SetFragmentsTotalBlockSize(LayoutUnit block_size) {
109 #if DCHECK_IS_ON()
110     // Note that we just store the block-size in a shared field. We have a flag
111     // for debugging, to assert that we know what we're doing when attempting to
112     // access the data.
113     block_size_is_for_all_fragments_ = true;
114 #endif
115     size_.block_size = block_size;
116   }
FragmentsTotalBlockSize()117   LayoutUnit FragmentsTotalBlockSize() const {
118 #if DCHECK_IS_ON()
119     if (has_block_fragmentation_)
120       DCHECK(block_size_is_for_all_fragments_);
121 #endif
122     return size_.block_size;
123   }
124 
125   // Set the final block-size of this fragment.
SetFragmentBlockSize(LayoutUnit block_size)126   void SetFragmentBlockSize(LayoutUnit block_size) {
127 #if DCHECK_IS_ON()
128     // Note that we just store the block-size in a shared field. We have a flag
129     // for debugging, to assert that we know what we're doing when attempting to
130     // access the data.
131     block_size_is_for_all_fragments_ = false;
132 #endif
133     size_.block_size = block_size;
134   }
135 
FragmentBlockSize()136   LayoutUnit FragmentBlockSize() const {
137 #if DCHECK_IS_ON()
138     if (has_block_fragmentation_)
139       DCHECK(!block_size_is_for_all_fragments_);
140 #endif
141     return size_.block_size;
142   }
143 
SetOverflowBlockSize(LayoutUnit overflow_block_size)144   void SetOverflowBlockSize(LayoutUnit overflow_block_size) {
145     overflow_block_size_ = overflow_block_size;
146   }
SetIntrinsicBlockSize(LayoutUnit intrinsic_block_size)147   void SetIntrinsicBlockSize(LayoutUnit intrinsic_block_size) {
148     intrinsic_block_size_ = intrinsic_block_size;
149   }
IntrinsicBlockSize()150   LayoutUnit IntrinsicBlockSize() const { return intrinsic_block_size_; }
Borders()151   const NGBoxStrut& Borders() const {
152     DCHECK(initial_fragment_geometry_);
153     DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
154     return initial_fragment_geometry_->border;
155   }
Scrollbar()156   const NGBoxStrut& Scrollbar() const {
157     DCHECK(initial_fragment_geometry_);
158     return initial_fragment_geometry_->scrollbar;
159   }
Padding()160   const NGBoxStrut& Padding() const {
161     DCHECK(initial_fragment_geometry_);
162     return initial_fragment_geometry_->padding;
163   }
InitialBorderBoxSize()164   const LogicalSize& InitialBorderBoxSize() const {
165     DCHECK(initial_fragment_geometry_);
166     return initial_fragment_geometry_->border_box_size;
167   }
BorderPadding()168   const NGBoxStrut& BorderPadding() const {
169     DCHECK(initial_fragment_geometry_);
170     return border_padding_;
171   }
BorderScrollbarPadding()172   const NGBoxStrut& BorderScrollbarPadding() const {
173     DCHECK(initial_fragment_geometry_);
174     return border_scrollbar_padding_;
175   }
176   // The child available-size is subtly different from the content-box size of
177   // an element. For an anonymous-block the child available-size is equal to
178   // its non-anonymous parent (similar to percentages).
ChildAvailableSize()179   const LogicalSize& ChildAvailableSize() const {
180     DCHECK(initial_fragment_geometry_);
181     DCHECK(space_);
182     return child_available_size_;
183   }
Node()184   const NGBlockNode& Node() {
185     DCHECK(node_);
186     return To<NGBlockNode>(node_);
187   }
188 
189   // Add a break token for a child that doesn't yet have any fragments, because
190   // its first fragment is to be produced in the next fragmentainer. This will
191   // add a break token for the child, but no fragment. Break appeal should
192   // always be provided for regular in-flow children. For other types of
193   // children it may be omitted, if the break shouldn't affect the appeal of
194   // breaking inside this container.
195   void AddBreakBeforeChild(NGLayoutInputNode child,
196                            base::Optional<NGBreakAppeal> appeal,
197                            bool is_forced_break);
198 
199   // Add a layout result. This involves appending the fragment and its relative
200   // offset to the builder, but also keeping track of out-of-flow positioned
201   // descendants, propagating fragmentainer breaks, and more.
202   void AddResult(const NGLayoutResult&, const LogicalOffset);
203 
AddChild(scoped_refptr<const NGPhysicalTextFragment> child,const LogicalOffset & offset)204   void AddChild(scoped_refptr<const NGPhysicalTextFragment> child,
205                 const LogicalOffset& offset) {
206     AddChildInternal(child, offset);
207   }
208 
209   void AddChild(const NGPhysicalContainerFragment&,
210                 const LogicalOffset&,
211                 const LayoutInline* inline_container = nullptr,
212                 const NGMarginStrut* margin_strut = nullptr,
213                 bool is_self_collapsing = false);
214 
215   // Manually add a break token to the builder. Note that we're assuming that
216   // this break token is for content in the same flow as this parent.
217   void AddBreakToken(scoped_refptr<const NGBreakToken>,
218                      bool is_in_parallel_flow = false);
219 
220   void AddOutOfFlowLegacyCandidate(NGBlockNode,
221                                    const NGLogicalStaticPosition&,
222                                    const LayoutInline* inline_container);
223 
224   // Specify whether this will be the first fragment generated for the node.
SetIsFirstForNode(bool is_first)225   void SetIsFirstForNode(bool is_first) { is_first_for_node_ = is_first; }
226 
227   // Set how much of the block-size we've used so far for this box. This will be
228   // the sum of the block-size of all previous fragments PLUS the one we're
229   // building now.
SetConsumedBlockSize(LayoutUnit size)230   void SetConsumedBlockSize(LayoutUnit size) { consumed_block_size_ = size; }
231 
232   // Set how much of the column block-size we've used so far. This will be used
233   // to determine the block-size of any new columns added by descendant
234   // out-of-flow positioned elements.
SetBlockOffsetForAdditionalColumns(LayoutUnit size)235   void SetBlockOffsetForAdditionalColumns(LayoutUnit size) {
236     block_offset_for_additional_columns_ = size;
237   }
BlockOffsetForAdditionalColumns()238   LayoutUnit BlockOffsetForAdditionalColumns() const {
239     return block_offset_for_additional_columns_;
240   }
241 
SetSequenceNumber(unsigned sequence_number)242   void SetSequenceNumber(unsigned sequence_number) {
243     sequence_number_ = sequence_number;
244   }
245 
246   // Return true if we broke inside this node on our own initiative (typically
247   // not because of a child break, but rather due to the size of this node).
DidBreakSelf()248   bool DidBreakSelf() const { return did_break_self_; }
SetDidBreakSelf()249   void SetDidBreakSelf() { did_break_self_ = true; }
250 
251   // Store the previous break token, if one exists.
SetPreviousBreakToken(scoped_refptr<const NGBlockBreakToken> break_token)252   void SetPreviousBreakToken(
253       scoped_refptr<const NGBlockBreakToken> break_token) {
254     previous_break_token_ = std::move(break_token);
255   }
PreviousBreakToken()256   const NGBlockBreakToken* PreviousBreakToken() const {
257     return previous_break_token_.get();
258   }
259 
260   // Return true if we need to break before or inside any child, doesn't matter
261   // if it's in-flow or not. As long as there are only breaks in parallel flows,
262   // we may continue layout, but when we're done, we'll need to create a break
263   // token for this fragment nevertheless, so that we re-enter, descend and
264   // resume at the broken children in the next fragmentainer.
HasChildBreakInside()265   bool HasChildBreakInside() const {
266     if (!child_break_tokens_.IsEmpty())
267       return true;
268     // Inline nodes produce a "finished" trailing break token even if we don't
269     // need to block-fragment.
270     return !inline_break_tokens_.IsEmpty() &&
271            !inline_break_tokens_.back()->IsFinished();
272   }
273 
274   // Return true if we need to break before or inside any in-flow child that
275   // doesn't establish a parallel flow. When this happens, we want to finish our
276   // fragment, create a break token, and resume in the next fragmentainer.
HasInflowChildBreakInside()277   bool HasInflowChildBreakInside() const {
278     return has_inflow_child_break_inside_;
279   }
280 
281   // Return true if we need to break before or inside any floated child. Floats
282   // are encapsulated by their container if the container establishes a new
283   // block formatting context.
HasFloatBreakInside()284   bool HasFloatBreakInside() const { return has_float_break_inside_; }
285 
286   // Report space shortage, i.e. how much more space would have been sufficient
287   // to prevent some piece of content from breaking. This information may be
288   // used by the column balancer to stretch columns.
PropagateSpaceShortage(LayoutUnit space_shortage)289   void PropagateSpaceShortage(LayoutUnit space_shortage) {
290     DCHECK_GT(space_shortage, LayoutUnit());
291 
292     // Space shortage should only be reported when we already have a tentative
293     // fragmentainer block-size. It's meaningless to talk about space shortage
294     // in the initial column balancing pass, because then we have no
295     // fragmentainer block-size at all, so who's to tell what's too short or
296     // not?
297     DCHECK(!IsInitialColumnBalancingPass());
298 
299     if (minimal_space_shortage_ > space_shortage)
300       minimal_space_shortage_ = space_shortage;
301   }
MinimalSpaceShortage()302   LayoutUnit MinimalSpaceShortage() const { return minimal_space_shortage_; }
303 
PropagateTallestUnbreakableBlockSize(LayoutUnit unbreakable_block_size)304   void PropagateTallestUnbreakableBlockSize(LayoutUnit unbreakable_block_size) {
305     // We should only calculate the block-size of the tallest piece of
306     // unbreakable content during the initial column balancing pass, when we
307     // haven't set a tentative fragmentainer block-size yet.
308     DCHECK(IsInitialColumnBalancingPass());
309 
310     tallest_unbreakable_block_size_ =
311         std::max(tallest_unbreakable_block_size_, unbreakable_block_size);
312   }
313 
SetIsInitialColumnBalancingPass()314   void SetIsInitialColumnBalancingPass() {
315     // Note that we have no dedicated flag for being in the initial column
316     // balancing pass here. We'll just bump tallest_unbreakable_block_size_ to
317     // 0, so that NGLayoutResult knows that we need to store unbreakable
318     // block-size.
319     DCHECK_EQ(tallest_unbreakable_block_size_, LayoutUnit::Min());
320     tallest_unbreakable_block_size_ = LayoutUnit();
321   }
IsInitialColumnBalancingPass()322   bool IsInitialColumnBalancingPass() const {
323     return tallest_unbreakable_block_size_ >= LayoutUnit();
324   }
325 
SetInitialBreakBefore(EBreakBetween break_before)326   void SetInitialBreakBefore(EBreakBetween break_before) {
327     initial_break_before_ = break_before;
328   }
329 
SetPreviousBreakAfter(EBreakBetween break_after)330   void SetPreviousBreakAfter(EBreakBetween break_after) {
331     previous_break_after_ = break_after;
332   }
333 
334   // Set when this subtree has modified the incoming margin-strut, such that it
335   // may change our final position.
SetSubtreeModifiedMarginStrut()336   void SetSubtreeModifiedMarginStrut() {
337     DCHECK(!BfcBlockOffset());
338     subtree_modified_margin_strut_ = true;
339   }
340 
341   // Join/"collapse" the previous (stored) break-after value with the next
342   // break-before value, to determine how to deal with breaking between two
343   // in-flow siblings.
344   EBreakBetween JoinedBreakBetweenValue(EBreakBetween break_before) const;
345 
346   // Return the number of line boxes laid out.
LineCount()347   int LineCount() const { return inline_break_tokens_.size(); }
348 
349   // Set when we have iterated over all the children. This means that all
350   // children have been fully laid out, or have break tokens. No more children
351   // left to discover.
SetHasSeenAllChildren()352   void SetHasSeenAllChildren() { has_seen_all_children_ = true; }
HasSeenAllChildren()353   bool HasSeenAllChildren() { return has_seen_all_children_; }
354 
SetIsAtBlockEnd()355   void SetIsAtBlockEnd() { is_at_block_end_ = true; }
IsAtBlockEnd()356   bool IsAtBlockEnd() const { return is_at_block_end_; }
357 
SetColumnSpanner(NGBlockNode spanner)358   void SetColumnSpanner(NGBlockNode spanner) { column_spanner_ = spanner; }
FoundColumnSpanner()359   bool FoundColumnSpanner() const { return !!column_spanner_; }
360 
SetLinesUntilClamp(const base::Optional<int> & value)361   void SetLinesUntilClamp(const base::Optional<int>& value) {
362     lines_until_clamp_ = value;
363   }
364 
SetEarlyBreak(scoped_refptr<const NGEarlyBreak> breakpoint,NGBreakAppeal appeal)365   void SetEarlyBreak(scoped_refptr<const NGEarlyBreak> breakpoint,
366                      NGBreakAppeal appeal) {
367     early_break_ = breakpoint;
368     break_appeal_ = appeal;
369   }
HasEarlyBreak()370   bool HasEarlyBreak() const { return early_break_.get(); }
EarlyBreak()371   const NGEarlyBreak& EarlyBreak() const {
372     DCHECK(early_break_.get());
373     return *early_break_.get();
374   }
375 
376   // Set the highest break appeal found so far. This is either:
377   // 1: The highest appeal of a breakpoint found by our container
378   // 2: The appeal of a possible early break inside
379   // 3: The appeal of an actual break inside (to be stored in a break token)
SetBreakAppeal(NGBreakAppeal appeal)380   void SetBreakAppeal(NGBreakAppeal appeal) { break_appeal_ = appeal; }
BreakAppeal()381   NGBreakAppeal BreakAppeal() const { return break_appeal_; }
382 
383   // Offsets are not supposed to be set during fragment construction, so we
384   // do not provide a setter here.
385 
386   // Creates the fragment. Can only be called once.
ToBoxFragment()387   scoped_refptr<const NGLayoutResult> ToBoxFragment() {
388     DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
389     return ToBoxFragment(GetWritingMode());
390   }
ToInlineBoxFragment()391   scoped_refptr<const NGLayoutResult> ToInlineBoxFragment() {
392     // The logical coordinate for inline box uses line-relative writing-mode,
393     // not
394     // flow-relative.
395     DCHECK_EQ(BoxType(), NGPhysicalFragment::kInlineBox);
396     return ToBoxFragment(ToLineWritingMode(GetWritingMode()));
397   }
398 
399   scoped_refptr<const NGLayoutResult> Abort(NGLayoutResult::EStatus);
400 
401   NGPhysicalFragment::NGBoxType BoxType() const;
SetBoxType(NGPhysicalFragment::NGBoxType box_type)402   void SetBoxType(NGPhysicalFragment::NGBoxType box_type) {
403     box_type_ = box_type;
404   }
IsFragmentainerBoxType()405   bool IsFragmentainerBoxType() const {
406     return BoxType() == NGPhysicalFragment::kColumnBox;
407   }
SetIsFieldsetContainer()408   void SetIsFieldsetContainer() { is_fieldset_container_ = true; }
SetIsTableNGPart()409   void SetIsTableNGPart() { is_table_ng_part_ = true; }
SetIsLegacyLayoutRoot()410   void SetIsLegacyLayoutRoot() { is_legacy_layout_root_ = true; }
411 
SetIsInlineFormattingContext(bool is_inline_formatting_context)412   void SetIsInlineFormattingContext(bool is_inline_formatting_context) {
413     is_inline_formatting_context_ = is_inline_formatting_context;
414   }
415 
SetIsMathMLFraction()416   void SetIsMathMLFraction() { is_math_fraction_ = true; }
SetIsMathMLOperator()417   void SetIsMathMLOperator() { is_math_operator_ = true; }
SetMathMLPaintInfo(UChar operator_character,scoped_refptr<const ShapeResultView> operator_shape_result_view,LayoutUnit operator_inline_size,LayoutUnit operator_ascent,LayoutUnit operator_descent)418   void SetMathMLPaintInfo(
419       UChar operator_character,
420       scoped_refptr<const ShapeResultView> operator_shape_result_view,
421       LayoutUnit operator_inline_size,
422       LayoutUnit operator_ascent,
423       LayoutUnit operator_descent) {
424     if (!mathml_paint_info_)
425       mathml_paint_info_ = std::make_unique<NGMathMLPaintInfo>();
426 
427     mathml_paint_info_->operator_character = operator_character;
428     mathml_paint_info_->operator_shape_result_view =
429         std::move(operator_shape_result_view);
430 
431     mathml_paint_info_->operator_inline_size = operator_inline_size;
432     mathml_paint_info_->operator_ascent = operator_ascent;
433     mathml_paint_info_->operator_descent = operator_descent;
434   }
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)435   void SetMathMLPaintInfo(
436       scoped_refptr<const ShapeResultView> operator_shape_result_view,
437       LayoutUnit operator_inline_size,
438       LayoutUnit operator_ascent,
439       LayoutUnit operator_descent,
440       LayoutUnit radical_operator_inline_offset,
441       const NGBoxStrut& radical_base_margins) {
442     if (!mathml_paint_info_)
443       mathml_paint_info_ = std::make_unique<NGMathMLPaintInfo>();
444 
445     mathml_paint_info_->operator_character = kSquareRootCharacter;
446     mathml_paint_info_->operator_shape_result_view =
447         std::move(operator_shape_result_view);
448 
449     mathml_paint_info_->operator_inline_size = operator_inline_size;
450     mathml_paint_info_->operator_ascent = operator_ascent;
451     mathml_paint_info_->operator_descent = operator_descent;
452     mathml_paint_info_->radical_base_margins = radical_base_margins;
453     mathml_paint_info_->radical_operator_inline_offset =
454         radical_operator_inline_offset;
455   }
456 
SetSidesToInclude(LogicalBoxSides sides_to_include)457   void SetSidesToInclude(LogicalBoxSides sides_to_include) {
458     sides_to_include_ = sides_to_include;
459   }
460 
461   // Either this function or SetBoxType must be called before ToBoxFragment().
SetIsNewFormattingContext(bool is_new_fc)462   void SetIsNewFormattingContext(bool is_new_fc) { is_new_fc_ = is_new_fc; }
463 
SetCustomLayoutData(scoped_refptr<SerializedScriptValue> custom_layout_data)464   void SetCustomLayoutData(
465       scoped_refptr<SerializedScriptValue> custom_layout_data) {
466     custom_layout_data_ = std::move(custom_layout_data);
467   }
468 
469   // Sets the alignment baseline for this fragment.
SetBaseline(LayoutUnit baseline)470   void SetBaseline(LayoutUnit baseline) { baseline_ = baseline; }
Baseline()471   base::Optional<LayoutUnit> Baseline() const { return baseline_; }
472 
473   // Sets the last baseline for this fragment.
SetLastBaseline(LayoutUnit baseline)474   void SetLastBaseline(LayoutUnit baseline) {
475     DCHECK_EQ(space_->BaselineAlgorithmType(),
476               NGBaselineAlgorithmType::kInlineBlock);
477     last_baseline_ = baseline;
478   }
LastBaseline()479   base::Optional<LayoutUnit> LastBaseline() const { return last_baseline_; }
480 
481   // The inline block baseline is at the block end margin edge under some
482   // circumstances. This function updates |LastBaseline| in such cases.
483   void SetLastBaselineToBlockEndMarginEdgeIfNeeded();
484 
SetTableGridRect(const PhysicalRect & table_grid_rect)485   void SetTableGridRect(const PhysicalRect& table_grid_rect) {
486     table_grid_rect_ = table_grid_rect;
487   }
488 
SetTableColumnGeometry(const NGTableFragmentData::ColumnGeometries & table_column_geometries)489   void SetTableColumnGeometry(
490       const NGTableFragmentData::ColumnGeometries& table_column_geometries) {
491     table_column_geometries_ = table_column_geometries;
492   }
493 
SetTableCollapsedBorders(const NGTableBorders & table_collapsed_borders)494   void SetTableCollapsedBorders(const NGTableBorders& table_collapsed_borders) {
495     table_collapsed_borders_ = &table_collapsed_borders;
496   }
497 
SetTableCollapsedBordersGeometry(std::unique_ptr<NGTableFragmentData::CollapsedBordersGeometry> table_collapsed_borders_geometry)498   void SetTableCollapsedBordersGeometry(
499       std::unique_ptr<NGTableFragmentData::CollapsedBordersGeometry>
500           table_collapsed_borders_geometry) {
501     table_collapsed_borders_geometry_ =
502         std::move(table_collapsed_borders_geometry);
503   }
504 
SetTableColumnCount(wtf_size_t table_column_count)505   void SetTableColumnCount(wtf_size_t table_column_count) {
506     table_column_count_ = table_column_count;
507   }
508 
SetTableCellColumnIndex(wtf_size_t table_cell_column_index)509   void SetTableCellColumnIndex(wtf_size_t table_cell_column_index) {
510     table_cell_column_index_ = table_cell_column_index;
511   }
512 
513   // The |NGFragmentItemsBuilder| for the inline formatting context of this box.
ItemsBuilder()514   NGFragmentItemsBuilder* ItemsBuilder() { return items_builder_; }
SetItemsBuilder(NGFragmentItemsBuilder * builder)515   void SetItemsBuilder(NGFragmentItemsBuilder* builder) {
516     items_builder_ = builder;
517   }
518 
519   // Returns offset for given child. DCHECK if child not found.
520   // Warning: Do not call unless necessary.
521   LogicalOffset GetChildOffset(const LayoutObject* child) const;
522 
523   // Inline containing block geometry is defined by two rectangles, generated
524   // by fragments of the LayoutInline.
525   struct InlineContainingBlockGeometry {
526     DISALLOW_NEW();
527     // Union of fragments generated on the first line.
528     PhysicalRect start_fragment_union_rect;
529     // Union of fragments generated on the last line.
530     PhysicalRect end_fragment_union_rect;
531   };
532 
533   using InlineContainingBlockMap =
534       HashMap<const LayoutObject*,
535               base::Optional<InlineContainingBlockGeometry>>;
536 
537   // Computes the geometry required for any inline containing blocks.
538   // |inline_containing_block_map| is a map whose keys specify which inline
539   // containing block geometry is required.
540   void ComputeInlineContainerGeometryFromFragmentTree(
541       InlineContainingBlockMap* inline_containing_block_map);
542   void ComputeInlineContainerGeometry(
543       InlineContainingBlockMap* inline_containing_block_map);
544 
545 #if DCHECK_IS_ON()
546   // If we don't participate in a fragmentation context, this method can check
547   // that all block fragmentation related fields have their initial value.
548   void CheckNoBlockFragmentation() const;
549 #endif
550 
551   // Moves all the children by |offset| in the block-direction. (Ensure that
552   // any baselines, OOFs, etc, are also moved by the appropriate amount).
553   void MoveChildrenInBlockDirection(LayoutUnit offset);
554 
555   void SetMathItalicCorrection(LayoutUnit italic_correction);
556 
557  private:
558   // Update whether we have fragmented in this flow.
559   void PropagateBreak(const NGLayoutResult&);
560 
SetHasForcedBreak()561   void SetHasForcedBreak() {
562     has_forced_break_ = true;
563     minimal_space_shortage_ = LayoutUnit::Max();
564   }
565 
566   scoped_refptr<const NGLayoutResult> ToBoxFragment(WritingMode);
567 
568   const NGFragmentGeometry* initial_fragment_geometry_ = nullptr;
569   NGBoxStrut border_padding_;
570   NGBoxStrut border_scrollbar_padding_;
571   LogicalSize child_available_size_;
572   LayoutUnit overflow_block_size_ = kIndefiniteSize;
573   LayoutUnit intrinsic_block_size_;
574   base::Optional<LogicalRect> inflow_bounds_;
575 
576   NGFragmentItemsBuilder* items_builder_ = nullptr;
577 
578   NGBlockNode column_spanner_ = nullptr;
579 
580   NGPhysicalFragment::NGBoxType box_type_;
581   bool may_have_descendant_above_block_start_ = false;
582   bool is_fieldset_container_ = false;
583   bool is_table_ng_part_ = false;
584   bool is_initial_block_size_indefinite_ = false;
585   bool is_inline_formatting_context_;
586   bool is_first_for_node_ = true;
587   bool did_break_self_ = false;
588   bool has_inflow_child_break_inside_ = false;
589   bool has_float_break_inside_ = false;
590   bool has_forced_break_ = false;
591   bool is_new_fc_ = false;
592   bool subtree_modified_margin_strut_ = false;
593   bool has_seen_all_children_ = false;
594   bool is_math_fraction_ = false;
595   bool is_math_operator_ = false;
596   bool is_at_block_end_ = false;
597   LayoutUnit consumed_block_size_;
598   LayoutUnit block_offset_for_additional_columns_;
599   unsigned sequence_number_ = 0;
600 
601   LayoutUnit minimal_space_shortage_ = LayoutUnit::Max();
602   LayoutUnit tallest_unbreakable_block_size_ = LayoutUnit::Min();
603 
604   // The break-before value on the initial child we cannot honor. There's no
605   // valid class A break point before a first child, only *between* siblings.
606   EBreakBetween initial_break_before_ = EBreakBetween::kAuto;
607 
608   // The break-after value of the previous in-flow sibling.
609   EBreakBetween previous_break_after_ = EBreakBetween::kAuto;
610 
611   base::Optional<LayoutUnit> baseline_;
612   base::Optional<LayoutUnit> last_baseline_;
613 
614   // Table specific types.
615   base::Optional<PhysicalRect> table_grid_rect_;
616   base::Optional<NGTableFragmentData::ColumnGeometries>
617       table_column_geometries_;
618   scoped_refptr<const NGTableBorders> table_collapsed_borders_;
619   std::unique_ptr<NGTableFragmentData::CollapsedBordersGeometry>
620       table_collapsed_borders_geometry_;
621   base::Optional<wtf_size_t> table_column_count_;
622 
623   // Table cell specific types.
624   base::Optional<wtf_size_t> table_cell_column_index_;
625 
626   LogicalBoxSides sides_to_include_;
627 
628   scoped_refptr<SerializedScriptValue> custom_layout_data_;
629   base::Optional<int> lines_until_clamp_;
630 
631   std::unique_ptr<NGMathMLPaintInfo> mathml_paint_info_;
632   base::Optional<NGLayoutResult::MathData> math_data_;
633 
634   scoped_refptr<const NGBlockBreakToken> previous_break_token_;
635 
636 #if DCHECK_IS_ON()
637   // Describes what size_.block_size represents; either the size of a single
638   // fragment (false), or the size of all fragments for a node (true).
639   bool block_size_is_for_all_fragments_ = false;
640 #endif
641 
642   friend class NGBlockBreakToken;
643   friend class NGPhysicalBoxFragment;
644   friend class NGLayoutResult;
645 };
646 
647 }  // namespace blink
648 
649 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_BOX_FRAGMENT_BUILDER_H_
650