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_LAYOUT_INPUT_NODE_H_
6 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_INPUT_NODE_H_
7 
8 #include "base/optional.h"
9 #include "third_party/blink/renderer/core/core_export.h"
10 #include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
11 #include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
12 #include "third_party/blink/renderer/core/layout/layout_box.h"
13 #include "third_party/blink/renderer/core/layout/ng/layout_box_utils.h"
14 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h"
15 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
16 #include "third_party/blink/renderer/platform/text/writing_mode.h"
17 
18 namespace blink {
19 
20 class ComputedStyle;
21 class DisplayLockContext;
22 class Document;
23 class LayoutObject;
24 class LayoutBox;
25 class NGConstraintSpace;
26 class NGPaintFragment;
27 struct MinMaxSizes;
28 struct PhysicalSize;
29 
30 // Input to the min/max inline size calculation algorithm for child nodes. Child
31 // nodes within the same formatting context need to know which floats are beside
32 // them.
33 struct MinMaxSizesInput {
34   // The min-max size calculation (un-intuitively) requires a percentage
35   // resolution size!
36   // This occurs when a replaced element has an intrinsic size. E.g.
37   // <div style="float: left; height: 100px">
38   //   <img sr="intrinsic-ratio-1x1.png" style="height: 50%;" />
39   // </div>
40   // In the above example float ends up with a width of 50px.
41   //
42   // As we don't perform any tree walking, we need to pass the percentage
43   // resolution block-size for min/max down the min/max size calculation.
MinMaxSizesInputMinMaxSizesInput44   explicit MinMaxSizesInput(LayoutUnit percentage_resolution_block_size)
45       : percentage_resolution_block_size(percentage_resolution_block_size) {}
46   LayoutUnit float_left_inline_size;
47   LayoutUnit float_right_inline_size;
48   LayoutUnit percentage_resolution_block_size;
49 };
50 
51 // Represents the input to a layout algorithm for a given node. The layout
52 // engine should use the style, node type to determine which type of layout
53 // algorithm to use to produce fragments for this node.
54 class CORE_EXPORT NGLayoutInputNode {
55   DISALLOW_NEW();
56 
57  public:
58   enum NGLayoutInputNodeType {
59     kBlock,
60     kInline
61     // When adding new values, ensure type_ below has enough bits.
62   };
63 
Create(LayoutBox * box,NGLayoutInputNodeType type)64   static NGLayoutInputNode Create(LayoutBox* box, NGLayoutInputNodeType type) {
65     // This function should create an instance of the subclass. This works
66     // because subclasses are not virtual and do not add fields.
67     return NGLayoutInputNode(box, type);
68   }
69 
NGLayoutInputNode(std::nullptr_t)70   NGLayoutInputNode(std::nullptr_t) : box_(nullptr), type_(kBlock) {}
71 
Type()72   NGLayoutInputNodeType Type() const {
73     return static_cast<NGLayoutInputNodeType>(type_);
74   }
IsInline()75   bool IsInline() const { return type_ == kInline; }
IsBlock()76   bool IsBlock() const { return type_ == kBlock; }
77 
IsBlockFlow()78   bool IsBlockFlow() const { return IsBlock() && box_->IsLayoutBlockFlow(); }
IsLayoutNGCustom()79   bool IsLayoutNGCustom() const {
80     return IsBlock() && box_->IsLayoutNGCustom();
81   }
IsColumnSpanAll()82   bool IsColumnSpanAll() const { return IsBlock() && box_->IsColumnSpanAll(); }
IsFloating()83   bool IsFloating() const { return IsBlock() && box_->IsFloating(); }
IsOutOfFlowPositioned()84   bool IsOutOfFlowPositioned() const {
85     return IsBlock() && box_->IsOutOfFlowPositioned();
86   }
IsReplaced()87   bool IsReplaced() const { return box_->IsLayoutReplaced(); }
IsAbsoluteContainer()88   bool IsAbsoluteContainer() const {
89     return box_->CanContainAbsolutePositionObjects();
90   }
IsFixedContainer()91   bool IsFixedContainer() const {
92     return box_->CanContainFixedPositionObjects();
93   }
IsBody()94   bool IsBody() const { return IsBlock() && box_->IsBody(); }
IsDocumentElement()95   bool IsDocumentElement() const { return box_->IsDocumentElement(); }
IsFlexItem()96   bool IsFlexItem() const { return IsBlock() && box_->IsFlexItemIncludingNG(); }
IsFlexibleBox()97   bool IsFlexibleBox() const {
98     return IsBlock() && box_->IsFlexibleBoxIncludingNG();
99   }
ShouldBeConsideredAsReplaced()100   bool ShouldBeConsideredAsReplaced() const {
101     return box_->ShouldBeConsideredAsReplaced();
102   }
IsListItem()103   bool IsListItem() const { return IsBlock() && box_->IsLayoutNGListItem(); }
IsListMarker()104   bool IsListMarker() const {
105     return IsBlock() && box_->IsLayoutNGOutsideListMarker();
106   }
ListMarkerOccupiesWholeLine()107   bool ListMarkerOccupiesWholeLine() const {
108     DCHECK(IsListMarker());
109     return ToLayoutNGOutsideListMarker(box_)->NeedsOccupyWholeLine();
110   }
IsFieldsetContainer()111   bool IsFieldsetContainer() const {
112     return IsBlock() && box_->IsLayoutNGFieldset();
113   }
114 
115   // Return true if this is the legend child of a fieldset that gets special
116   // treatment (i.e. placed over the block-start border).
IsRenderedLegend()117   bool IsRenderedLegend() const {
118     return IsBlock() && box_->IsRenderedLegend();
119   }
IsTable()120   bool IsTable() const { return IsBlock() && box_->IsTable(); }
121 
IsMathRoot()122   bool IsMathRoot() const { return box_->IsMathMLRoot(); }
123 
IsAnonymousBlock()124   bool IsAnonymousBlock() const { return box_->IsAnonymousBlock(); }
125 
126   // If the node is a quirky container for margin collapsing, see:
127   // https://html.spec.whatwg.org/C/#margin-collapsing-quirks
128   // NOTE: The spec appears to only somewhat match reality.
IsQuirkyContainer()129   bool IsQuirkyContainer() const {
130     return box_->GetDocument().InQuirksMode() &&
131            (box_->IsBody() || box_->IsTableCell());
132   }
133 
134   // Return true if this node is monolithic for block fragmentation.
IsMonolithic()135   bool IsMonolithic() const {
136     // Lines are always monolithic. We cannot block-fragment inside them.
137     if (IsInline())
138       return true;
139     return box_->GetPaginationBreakability() == LayoutBox::kForbidBreaks;
140   }
141 
CreatesNewFormattingContext()142   bool CreatesNewFormattingContext() const {
143     return IsBlock() && box_->CreatesNewFormattingContext();
144   }
145 
146   // Returns true if this node should pass its percentage resolution block-size
147   // to its children. Typically only quirks-mode, auto block-size, block nodes.
UseParentPercentageResolutionBlockSizeForChildren()148   bool UseParentPercentageResolutionBlockSizeForChildren() const {
149     auto* layout_block = DynamicTo<LayoutBlock>(box_);
150     if (IsBlock() && layout_block) {
151       return LayoutBoxUtils::SkipContainingBlockForPercentHeightCalculation(
152           layout_block);
153     }
154 
155     return false;
156   }
157 
158   // Returns border box.
159   MinMaxSizes ComputeMinMaxSizes(WritingMode,
160                                  const MinMaxSizesInput&,
161                                  const NGConstraintSpace* = nullptr);
162 
163   // Returns intrinsic sizing information for replaced elements.
164   // ComputeReplacedSize can use it to compute actual replaced size.
165   // Corresponds to Legacy's LayoutReplaced::IntrinsicSizingInfo.
166   // Use NGBlockNode::GetAspectRatio to get the aspect ratio.
167   void IntrinsicSize(base::Optional<LayoutUnit>* computed_inline_size,
168                      base::Optional<LayoutUnit>* computed_block_size) const;
169 
170   // Returns the next sibling.
171   NGLayoutInputNode NextSibling();
172 
GetDocument()173   Document& GetDocument() const { return box_->GetDocument(); }
174 
175   PhysicalSize InitialContainingBlockSize() const;
176 
177   // Returns the LayoutObject which is associated with this node.
GetLayoutBox()178   LayoutBox* GetLayoutBox() const { return box_; }
179 
Style()180   const ComputedStyle& Style() const { return box_->StyleRef(); }
181 
ShouldApplySizeContainment()182   bool ShouldApplySizeContainment() const {
183     return box_->ShouldApplySizeContainment();
184   }
185 
186   // CSS intrinsic sizing getters.
187   // https://drafts.csswg.org/css-sizing-4/#intrinsic-size-override
188   // Note that this returns kIndefiniteSize if the override was not specified.
OverrideIntrinsicContentInlineSize()189   LayoutUnit OverrideIntrinsicContentInlineSize() const {
190     if (box_->HasOverrideIntrinsicContentLogicalWidth())
191       return box_->OverrideIntrinsicContentLogicalWidth();
192     return kIndefiniteSize;
193   }
194   // Note that this returns kIndefiniteSize if the override was not specified.
OverrideIntrinsicContentBlockSize()195   LayoutUnit OverrideIntrinsicContentBlockSize() const {
196     if (box_->HasOverrideIntrinsicContentLogicalHeight())
197       return box_->OverrideIntrinsicContentLogicalHeight();
198     return kIndefiniteSize;
199   }
200 
DefaultIntrinsicContentInlineSize()201   LayoutUnit DefaultIntrinsicContentInlineSize() const {
202     return box_->DefaultIntrinsicContentInlineSize();
203   }
DefaultIntrinsicContentBlockSize()204   LayoutUnit DefaultIntrinsicContentBlockSize() const {
205     return box_->DefaultIntrinsicContentBlockSize();
206   }
207 
208   // Display locking functionality.
GetDisplayLockContext()209   const DisplayLockContext& GetDisplayLockContext() const {
210     DCHECK(box_->GetDisplayLockContext());
211     return *box_->GetDisplayLockContext();
212   }
LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget target)213   bool LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget target) const {
214     return box_->LayoutBlockedByDisplayLock(target);
215   }
216 
217   // Returns the first NGPaintFragment for this node. When block fragmentation
218   // occurs, there will be multiple NGPaintFragment for a node.
219   const NGPaintFragment* PaintFragment() const;
220 
GetCustomLayoutChild()221   CustomLayoutChild* GetCustomLayoutChild() const {
222     // TODO(ikilpatrick): Support NGInlineNode.
223     DCHECK(IsBlock());
224     return box_->GetCustomLayoutChild();
225   }
226 
227   String ToString() const;
228 
229   explicit operator bool() const { return box_ != nullptr; }
230 
231   bool operator==(const NGLayoutInputNode& other) const {
232     return box_ == other.box_;
233   }
234 
235   bool operator!=(const NGLayoutInputNode& other) const {
236     return !(*this == other);
237   }
238 
239 #if DCHECK_IS_ON()
240   void ShowNodeTree() const;
241 #endif
242 
243  protected:
NGLayoutInputNode(LayoutBox * box,NGLayoutInputNodeType type)244   NGLayoutInputNode(LayoutBox* box, NGLayoutInputNodeType type)
245       : box_(box), type_(type) {}
246 
247   void GetOverrideIntrinsicSize(
248       base::Optional<LayoutUnit>* computed_inline_size,
249       base::Optional<LayoutUnit>* computed_block_size) const;
250 
251   LayoutBox* box_;
252 
253   unsigned type_ : 1;  // NGLayoutInputNodeType
254 };
255 
256 }  // namespace blink
257 
258 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_LAYOUT_INPUT_NODE_H_
259