Index: third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc |
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc |
index f9353d41fea54f95dfc13600589115dc821e94fd..4bb239f596d26b44643673aa8a265a8fd07e6ed0 100644 |
--- a/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc |
+++ b/third_party/WebKit/Source/core/layout/ng/ng_line_builder.cc |
@@ -8,18 +8,59 @@ |
#include "core/layout/LayoutBlockFlow.h" |
#include "core/layout/line/LineInfo.h" |
#include "core/layout/line/RootInlineBox.h" |
+#include "core/layout/ng/layout_ng_block_flow.h" |
#include "core/layout/ng/ng_bidi_paragraph.h" |
+#include "core/layout/ng/ng_block_layout_algorithm.h" |
#include "core/layout/ng/ng_box_fragment.h" |
#include "core/layout/ng/ng_constraint_space.h" |
#include "core/layout/ng/ng_constraint_space_builder.h" |
+#include "core/layout/ng/ng_floating_object.h" |
+#include "core/layout/ng/ng_floats_utils.h" |
#include "core/layout/ng/ng_fragment_builder.h" |
#include "core/layout/ng/ng_inline_node.h" |
#include "core/layout/ng/ng_length_utils.h" |
+#include "core/layout/ng/ng_space_utils.h" |
#include "core/layout/ng/ng_text_fragment.h" |
#include "core/style/ComputedStyle.h" |
#include "platform/text/BidiRunList.h" |
namespace blink { |
+namespace { |
+ |
+RefPtr<NGConstraintSpace> CreateConstraintSpaceForFloat( |
+ const ComputedStyle& style, |
+ const NGConstraintSpace& parent_space, |
+ NGConstraintSpaceBuilder* space_builder) { |
+ DCHECK(space_builder) << "space_builder cannot be null here"; |
+ bool is_new_bfc = |
+ IsNewFormattingContextForInFlowBlockLevelChild(parent_space, style); |
+ return space_builder->SetIsNewFormattingContext(is_new_bfc) |
+ .SetTextDirection(style.direction()) |
+ .SetIsShrinkToFit(ShouldShrinkToFit(parent_space, style)) |
+ .ToConstraintSpace(FromPlatformWritingMode(style.getWritingMode())); |
+} |
+ |
+NGLogicalOffset GetOriginPointForFloats(const NGConstraintSpace& space, |
+ LayoutUnit content_size) { |
+ NGLogicalOffset origin_point = space.BfcOffset(); |
+ origin_point.block_offset += content_size; |
+ return origin_point; |
+} |
+ |
+void PositionPendingFloats(const NGLogicalOffset& origin_point, |
+ NGConstraintSpace* space, |
+ NGFragmentBuilder* builder) { |
+ DCHECK(builder) << "Builder cannot be null here"; |
+ |
+ for (auto& floating_object : builder->UnpositionedFloats()) { |
+ NGLogicalOffset offset = PositionFloat(origin_point, space->BfcOffset(), |
+ floating_object.get(), space); |
+ builder->AddFloatingObject(floating_object, offset); |
+ } |
+ builder->MutableUnpositionedFloats().clear(); |
+} |
+ |
+} // namespace |
NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box, |
NGConstraintSpace* constraint_space) |
@@ -28,7 +69,8 @@ NGLineBuilder::NGLineBuilder(NGInlineNode* inline_box, |
container_builder_(NGPhysicalFragment::kFragmentBox, inline_box_), |
container_layout_result_(nullptr), |
is_horizontal_writing_mode_( |
- blink::IsHorizontalWritingMode(constraint_space->WritingMode())) |
+ blink::IsHorizontalWritingMode(constraint_space->WritingMode())), |
+ space_builder_(constraint_space) |
#if DCHECK_IS_ON() |
, |
is_bidi_reordered_(false) |
@@ -114,9 +156,9 @@ void NGLineBuilder::SetEnd(unsigned index, |
item.AssertEndOffset(new_end_offset); |
if (item.Type() == NGLayoutInlineItem::kFloating) { |
- // Floats can affect the position and available width of the current line |
- // if it fits. |
- // TODO(kojii): Implement. |
+ LayoutAndPositionFloat( |
+ LayoutUnit(end_position_) + inline_size_since_current_end, |
+ item.GetLayoutObject()); |
} |
last_index_ = index; |
@@ -221,6 +263,9 @@ void NGLineBuilder::CreateLineUpToLastBreakOpportunity() { |
is_bidi_reordered_ = false; |
#endif |
+ NGLogicalOffset origin_point = |
+ GetOriginPointForFloats(ConstraintSpace(), content_size_); |
+ PositionPendingFloats(origin_point, constraint_space_, &container_builder_); |
FindNextLayoutOpportunity(); |
} |
@@ -258,6 +303,47 @@ void NGLineBuilder::BidiReorder(Vector<LineItemChunk, 32>* line_item_chunks) { |
line_item_chunks->swap(line_item_chunks_in_visual_order); |
} |
+// TODO(glebl): Add the support of clearance for inline floats. |
+void NGLineBuilder::LayoutAndPositionFloat(LayoutUnit end_position, |
+ LayoutObject* layout_object) { |
+ LayoutNGBlockFlow* block_flow = toLayoutNGBlockFlow(layout_object); |
+ NGBlockNode* node = new NGBlockNode(block_flow); |
+ |
+ RefPtr<NGConstraintSpace> float_space = CreateConstraintSpaceForFloat( |
+ node->Style(), ConstraintSpace(), &space_builder_); |
+ // TODO(glebl): add the fragmentation support: |
+ // same writing mode - get the inline size ComputeInlineSizeForFragment to |
+ // determine if it fits on this line, then perform layout with the correct |
+ // fragmentation line. |
+ // diff writing mode - get the inline size from performing layout. |
+ RefPtr<NGLayoutResult> layout_result = node->Layout(float_space.get()); |
+ |
+ NGBoxFragment float_fragment( |
+ float_space->WritingMode(), |
+ toNGPhysicalBoxFragment(layout_result->PhysicalFragment().get())); |
+ |
+ RefPtr<NGFloatingObject> floating_object = NGFloatingObject::Create( |
+ float_space.get(), constraint_space_, node->Style(), NGBoxStrut(), |
+ layout_result->PhysicalFragment().get()); |
+ |
+ bool float_does_not_fit = end_position + float_fragment.InlineSize() > |
+ current_opportunity_.InlineSize(); |
+ // Check if we already have a pending float. That's because a float cannot be |
+ // higher than any block or floated box generated before. |
+ if (!container_builder_.UnpositionedFloats().isEmpty() || |
+ float_does_not_fit) { |
+ container_builder_.AddUnpositionedFloat(floating_object); |
+ } else { |
+ NGLogicalOffset origin_point = |
+ GetOriginPointForFloats(ConstraintSpace(), content_size_); |
+ NGLogicalOffset offset = |
+ PositionFloat(origin_point, constraint_space_->BfcOffset(), |
+ floating_object.get(), constraint_space_); |
+ container_builder_.AddFloatingObject(floating_object, offset); |
+ FindNextLayoutOpportunity(); |
+ } |
+} |
+ |
void NGLineBuilder::PlaceItems( |
const Vector<LineItemChunk, 32>& line_item_chunks) { |
const Vector<NGLayoutInlineItem>& items = inline_box_->Items(); |
@@ -325,12 +411,6 @@ void NGLineBuilder::PlaceItems( |
ConstraintSpace().Direction(), |
NGPhysicalOffset())); |
continue; |
- } else if (item.Type() == NGLayoutInlineItem::kFloating) { |
- // TODO(kojii): Implement float. |
- DLOG(ERROR) << "Floats in inline not implemented yet."; |
- // TODO(kojii): Temporarily clearNeedsLayout() for not to assert. |
- item.GetLayoutObject()->clearNeedsLayout(); |
- continue; |
} else { |
continue; |
} |