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