1 // Copyright 2019 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_INLINE_NG_FRAGMENT_ITEMS_BUILDER_H_ 6 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_FRAGMENT_ITEMS_BUILDER_H_ 7 8 #include "third_party/blink/renderer/core/core_export.h" 9 #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h" 10 #include "third_party/blink/renderer/core/layout/ng/inline/ng_logical_line_item.h" 11 #include "third_party/blink/renderer/platform/text/writing_direction_mode.h" 12 13 namespace blink { 14 15 class NGFragmentItem; 16 class NGFragmentItems; 17 class NGInlineNode; 18 19 // This class builds |NGFragmentItems|. 20 // 21 // Once |NGFragmentItems| is built, it is immutable. 22 class CORE_EXPORT NGFragmentItemsBuilder { 23 STACK_ALLOCATED(); 24 25 public: 26 explicit NGFragmentItemsBuilder(WritingDirectionMode writing_direction); 27 NGFragmentItemsBuilder(const NGInlineNode& node, 28 WritingDirectionMode writing_direction); 29 ~NGFragmentItemsBuilder(); 30 GetWritingDirection()31 WritingDirectionMode GetWritingDirection() const { 32 return writing_direction_; 33 } GetWritingMode()34 WritingMode GetWritingMode() const { 35 return writing_direction_.GetWritingMode(); 36 } Direction()37 TextDirection Direction() const { return writing_direction_.Direction(); } 38 Size()39 wtf_size_t Size() const { return items_.size(); } 40 41 // Returns true if we have any floating descendants which need to be 42 // traversed during the float paint phase. HasFloatingDescendantsForPaint()43 bool HasFloatingDescendantsForPaint() const { 44 return has_floating_descendants_for_paint_; 45 } 46 TextContent(bool first_line)47 const String& TextContent(bool first_line) const { 48 return UNLIKELY(first_line && first_line_text_content_) 49 ? first_line_text_content_ 50 : text_content_; 51 } 52 53 // Adding a line is a three-pass operation, because |NGInlineLayoutAlgorithm| 54 // creates and positions children within a line box, but its parent algorithm 55 // positions the line box. 56 // 57 // 1. |AcquireLogicalLineItems| to get an instance of |NGLogicalLineItems|. 58 // 2. Add items to |NGLogicalLineItems| and create |NGPhysicalFragment|, 59 // then associate them by |AssociateLogicalLineItems|. 60 // 3. |AddLine| adds the |NGPhysicalLineBoxFragment|. 61 // 62 // |NGBlockLayoutAlgorithm| runs these phases in the order for each line. In 63 // this case, one instance of |NGLogicalLineItems| is reused for all lines to 64 // reduce memory allocations. 65 // 66 // Custom layout produces all line boxes first by running only 1 and 2 (in 67 // |NGInlineLayoutAlgorithm|). Then after worklet determined the position and 68 // the order of line boxes, it runs 3 for each line. In this case, 69 // |NGFragmentItemsBuilder| allocates new instance for each line, and keeps 70 // them alive until |AddLine|. 71 NGLogicalLineItems* AcquireLogicalLineItems(); 72 void AssociateLogicalLineItems(NGLogicalLineItems* line_items, 73 const NGPhysicalFragment& line_fragment); 74 void AddLine(const NGPhysicalLineBoxFragment& line, 75 const LogicalOffset& offset); 76 77 // Add to |NGLogicalLineItems| instance pool. |AcquireLogicalLineItems| 78 // uses pooled instances first if available to avoid memory allocations. 79 void AddLogicalLineItemsPool(NGLogicalLineItems* line_items); 80 81 // Add a list marker to the current line. 82 void AddListMarker(const NGPhysicalBoxFragment& marker_fragment, 83 const LogicalOffset& offset); 84 85 // See |AddPreviousItems| below. 86 struct AddPreviousItemsResult { 87 STACK_ALLOCATED(); 88 89 public: 90 const NGInlineBreakToken* inline_break_token = nullptr; 91 LayoutUnit used_block_size; 92 wtf_size_t line_count = 0; 93 bool succeeded = false; 94 }; 95 96 // Add previously laid out |NGFragmentItems|. 97 // 98 // When |stop_at_dirty| is true, this function checks reusability of previous 99 // items and stops copying before the first dirty line. 100 AddPreviousItemsResult AddPreviousItems( 101 const NGPhysicalBoxFragment& container, 102 const NGFragmentItems& items, 103 NGBoxFragmentBuilder* container_builder = nullptr, 104 const NGFragmentItem* end_item = nullptr, 105 wtf_size_t max_lines = 0); 106 107 struct ItemWithOffset { 108 DISALLOW_NEW(); 109 110 public: 111 template <class... Args> ItemWithOffsetItemWithOffset112 explicit ItemWithOffset(const LogicalOffset& offset, Args&&... args) 113 : item(std::forward<Args>(args)...), offset(offset) {} 114 115 const NGFragmentItem& operator*() const { return item; } 116 const NGFragmentItem* operator->() const { return &item; } 117 118 NGFragmentItem item; 119 LogicalOffset offset; 120 }; 121 122 // Give an inline size, the allocation of this vector is hot. "128" is 123 // heuristic. Usually 10-40, some wikipedia pages have >64 items. 124 using ItemWithOffsetList = Vector<ItemWithOffset, 128>; 125 126 // Find |LogicalOffset| of the first |NGFragmentItem| for |LayoutObject|. 127 base::Optional<LogicalOffset> LogicalOffsetFor(const LayoutObject&) const; 128 129 // Moves all the |NGFragmentItem|s by |offset| in the block-direction. 130 void MoveChildrenInBlockDirection(LayoutUnit offset); 131 132 // Converts the |NGFragmentItem| vector to the physical coordinate space and 133 // returns the result. This should only be used for determining the inline 134 // containing block geometry for OOF-positioned nodes. 135 // 136 // Once this method has been called, new items cannot be added. 137 const ItemWithOffsetList& Items(const PhysicalSize& outer_size); 138 139 // Build a |NGFragmentItems|. The builder cannot build twice because data set 140 // to this builder may be cleared. 141 void ToFragmentItems(const PhysicalSize& outer_size, void* data); 142 143 private: 144 void ReleaseCurrentLogicalLineItems(); 145 void MoveCurrentLogicalLineItemsToMap(); 146 147 void AddItems(NGLogicalLineItem* child_begin, NGLogicalLineItem* child_end); 148 149 void ConvertToPhysical(const PhysicalSize& outer_size); 150 151 ItemWithOffsetList items_; 152 String text_content_; 153 String first_line_text_content_; 154 155 // Keeps children of a line until the offset is determined. See |AddLine|. 156 NGLogicalLineItems* current_line_items_ = nullptr; 157 const NGPhysicalFragment* current_line_fragment_ = nullptr; 158 159 HashMap<const NGPhysicalFragment*, NGLogicalLineItems*> line_items_map_; 160 NGLogicalLineItems* line_items_pool_ = nullptr; 161 162 NGInlineNode node_; 163 164 WritingDirectionMode writing_direction_; 165 166 bool has_floating_descendants_for_paint_ = false; 167 bool is_converted_to_physical_ = false; 168 bool is_line_items_pool_acquired_ = false; 169 170 friend class NGFragmentItems; 171 }; 172 173 } // namespace blink 174 175 #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_FRAGMENT_ITEMS_BUILDER_H_ 176