OLD | NEW |
---|---|
(Empty) | |
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 #include "core/layout/ng/ng_out_of_flow_layout_part.h" | |
6 | |
7 #include "core/layout/ng/ng_absolute_utils.h" | |
8 #include "core/layout/ng/ng_block_node.h" | |
9 #include "core/layout/ng/ng_constraint_space_builder.h" | |
10 #include "core/layout/ng/ng_fragment_base.h" | |
11 #include "core/layout/ng/ng_length_utils.h" | |
12 #include "core/style/ComputedStyle.h" | |
13 | |
14 namespace blink { | |
15 | |
16 NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart( | |
17 PassRefPtr<const ComputedStyle> container_style, | |
18 NGLogicalSize container_size) { | |
19 contains_fixed_ = container_style->canContainFixedPositionObjects(); | |
20 contains_absolute_ = | |
21 container_style->canContainAbsolutePositionObjects() || contains_fixed_; | |
22 // Initialize ConstraintSpace | |
23 NGLogicalSize space_size = container_size; | |
24 NGBoxStrut borders = ComputeBorders(*container_style); | |
25 space_size.block_size -= borders.BlockSum(); | |
26 space_size.inline_size -= borders.InlineSum(); | |
27 parent_offset_ = NGLogicalOffset{borders.inline_start, borders.block_start}; | |
28 parent_physical_offset_ = parent_offset_.ConvertToPhysical( | |
29 FromPlatformWritingMode(container_style->getWritingMode()), | |
30 container_style->direction(), | |
31 container_size.ConvertToPhysical( | |
32 FromPlatformWritingMode(container_style->getWritingMode())), | |
33 NGPhysicalSize()); | |
34 NGConstraintSpaceBuilder space_builder( | |
35 FromPlatformWritingMode(container_style->getWritingMode())); | |
36 space_builder.SetAvailableSize(space_size); | |
37 space_builder.SetIsNewFormattingContext(true); | |
38 space_builder.SetTextDirection(container_style->direction()); | |
39 parent_space_ = space_builder.ToConstraintSpace(); | |
40 } | |
41 | |
42 bool NGOutOfFlowLayoutPart::StartLayout( | |
43 NGBlockNode* node, | |
44 const NGStaticPosition& static_position) { | |
45 EPosition position = node->Style()->position(); | |
46 if ((contains_absolute_ && position == AbsolutePosition) || | |
47 (contains_fixed_ && position == FixedPosition)) { | |
48 node_ = node; | |
49 static_position_ = static_position; | |
50 // Adjust static_position origin. static_position coordinate origin is | |
51 // border_box, absolute position coordinate origin is padding box. | |
52 static_position_.offset -= parent_physical_offset_; | |
53 node_fragment_ = nullptr; | |
54 node_position_ = NGAbsolutePhysicalPosition(); | |
55 inline_estimate_.reset(); | |
56 block_estimate_.reset(); | |
57 state_ = kComputeInlineEstimate; | |
58 return true; | |
59 } | |
60 return false; | |
61 } | |
62 | |
63 NGLayoutStatus NGOutOfFlowLayoutPart::Layout(NGFragmentBase** fragment, | |
64 NGLogicalOffset* offset) { | |
65 DCHECK(node_); | |
66 switch (state_) { | |
67 case kComputeInlineEstimate: | |
68 if (ComputeInlineSizeEstimate()) | |
69 state_ = kPartialPosition; | |
70 break; | |
71 case kPartialPosition: | |
72 node_position_ = ComputePartialAbsoluteWithChildInlineSize( | |
73 *parent_space_, *node_->Style(), static_position_, inline_estimate_); | |
74 state_ = kComputeBlockEstimate; | |
75 break; | |
76 case kComputeBlockEstimate: | |
77 if (ComputeBlockSizeEstimate()) | |
78 state_ = kFullPosition; | |
79 break; | |
80 case kFullPosition: | |
81 ComputeFullAbsoluteWithChildBlockSize(*parent_space_, *node_->Style(), | |
82 static_position_, block_estimate_, | |
83 &node_position_); | |
84 state_ = kGenerateFragment; | |
85 break; | |
86 case kGenerateFragment: | |
87 block_estimate_ = | |
88 node_position_.size.ConvertToLogical(parent_space_->WritingMode()) | |
89 .block_size; | |
90 if (!ComputeNodeFragment()) | |
91 return kNotFinished; | |
92 state_ = kDone; | |
93 break; | |
94 case kDone: | |
95 *fragment = node_fragment_; | |
96 // Compute offset | |
97 NGBoxStrut inset = node_position_.inset.ConvertToLogical( | |
98 parent_space_->WritingMode(), parent_space_->Direction()); | |
99 offset->inline_offset = inset.inline_start + parent_offset_.inline_offset; | |
100 offset->block_offset = inset.block_start + parent_offset_.block_offset; | |
101 return kNewFragment; | |
102 } | |
103 return kNotFinished; | |
104 } | |
105 | |
106 bool NGOutOfFlowLayoutPart::ComputeInlineSizeEstimate() { | |
107 if (AbsoluteNeedsChildInlineSize(*node_->Style())) { | |
108 MinAndMaxContentSizes size; | |
109 if (node_->ComputeMinAndMaxContentSizes(&size)) { | |
110 inline_estimate_ = | |
111 size.ShrinkToFit(parent_space_->AvailableSize().inline_size); | |
112 return true; | |
113 } | |
114 return false; | |
115 } | |
116 return true; | |
117 } | |
118 | |
119 bool NGOutOfFlowLayoutPart::ComputeBlockSizeEstimate() { | |
120 if (AbsoluteNeedsChildBlockSize(*node_->Style())) { | |
121 if (ComputeNodeFragment()) { | |
122 block_estimate_ = node_fragment_->BlockSize(); | |
123 return true; | |
124 } | |
125 return false; | |
126 } | |
127 return true; | |
128 } | |
129 | |
130 bool NGOutOfFlowLayoutPart::ComputeNodeFragment() { | |
131 if (node_fragment_) | |
132 return true; | |
133 if (!node_space_) { | |
134 NGConstraintSpaceBuilder builder(parent_space_->WritingMode()); | |
135 LayoutUnit inline_width = | |
136 node_position_.size.ConvertToLogical(parent_space_->WritingMode()) | |
137 .inline_size; | |
138 // Node fragment is computed in one of these two scenarios: | |
139 // 1. To estimate block size | |
140 // In this case, available block_size is parent's size. | |
141 // 2. To compute final block fragment, when block size is known. | |
142 | |
143 NGLogicalSize available_size = | |
144 NGLogicalSize(inline_width, parent_space_->AvailableSize().block_size); | |
145 if (block_estimate_) | |
atotic
2016/12/28 20:35:16
I was wrong. block_estimate is needed here because
cbiesinger
2017/01/04 00:13:16
I misread the code, I think. We set block_estimate
atotic
2017/01/04 01:34:35
ack.
| |
146 available_size.block_size = *block_estimate_; | |
147 builder.SetAvailableSize(available_size); | |
148 builder.SetPercentageResolutionSize(available_size); | |
149 if (block_estimate_) | |
150 builder.SetIsFixedSizeBlock(true); | |
151 builder.SetIsFixedSizeInline(true); | |
152 builder.SetIsNewFormattingContext(true); | |
153 node_space_ = builder.ToConstraintSpace(); | |
154 } | |
155 NGFragmentBase* fragment; | |
156 if (node_->Layout(node_space_, &fragment)) { | |
157 node_fragment_ = fragment; | |
158 return true; | |
159 } | |
160 return false; | |
161 } | |
162 | |
163 DEFINE_TRACE(NGOutOfFlowLayoutPart) { | |
164 visitor->trace(node_); | |
165 visitor->trace(parent_space_); | |
166 visitor->trace(node_fragment_); | |
167 visitor->trace(node_space_); | |
168 } | |
169 } | |
OLD | NEW |