blob: b9a1af54d66d6fdcd1cb5898f68c7a682d1c2604 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NGContainerFragmentBuilder_h
#define NGContainerFragmentBuilder_h
#include "core/CoreExport.h"
#include "core/layout/ng/geometry/ng_bfc_offset.h"
#include "core/layout/ng/geometry/ng_logical_size.h"
#include "core/layout/ng/geometry/ng_margin_strut.h"
#include "core/layout/ng/ng_base_fragment_builder.h"
#include "core/layout/ng/ng_out_of_flow_positioned_descendant.h"
#include "core/layout/ng/ng_writing_mode.h"
#include "platform/text/TextDirection.h"
#include "platform/wtf/Allocator.h"
#include "platform/wtf/RefPtr.h"
namespace blink {
class ComputedStyle;
class NGExclusionSpace;
class NGLayoutResult;
class NGPhysicalFragment;
struct NGUnpositionedFloat;
class CORE_EXPORT NGContainerFragmentBuilder : public NGBaseFragmentBuilder {
STACK_ALLOCATED();
public:
~NGContainerFragmentBuilder() override;
LayoutUnit InlineSize() const { return inline_size_; }
NGContainerFragmentBuilder& SetInlineSize(LayoutUnit);
void SetBlockSize(LayoutUnit block_size) { block_size_ = block_size; }
virtual NGLogicalSize Size() const = 0;
// The NGBfcOffset is where this fragment was positioned within the BFC. If
// it is not set, this fragment may be placed anywhere within the BFC.
const WTF::Optional<NGBfcOffset>& BfcOffset() const { return bfc_offset_; }
NGContainerFragmentBuilder& SetBfcOffset(const NGBfcOffset&);
NGContainerFragmentBuilder& SetEndMarginStrut(const NGMarginStrut&);
NGContainerFragmentBuilder& SetExclusionSpace(
std::unique_ptr<const NGExclusionSpace> exclusion_space);
NGContainerFragmentBuilder& SwapUnpositionedFloats(
Vector<scoped_refptr<NGUnpositionedFloat>>*);
virtual NGContainerFragmentBuilder& AddChild(scoped_refptr<NGLayoutResult>,
const NGLogicalOffset&);
virtual NGContainerFragmentBuilder& AddChild(
scoped_refptr<NGPhysicalFragment>,
const NGLogicalOffset&);
const Vector<scoped_refptr<NGPhysicalFragment>>& Children() const {
return children_;
}
// Builder has non-trivial out-of-flow descendant methods.
// These methods are building blocks for implementation of
// out-of-flow descendants by layout algorithms.
//
// They are intended to be used by layout algorithm like this:
//
// Part 1: layout algorithm positions in-flow children.
// out-of-flow children, and out-of-flow descendants of fragments
// are stored inside builder.
//
// for (child : children)
// if (child->position == (Absolute or Fixed))
// builder->AddOutOfFlowChildCandidate(child);
// else
// fragment = child->Layout()
// builder->AddChild(fragment)
// end
//
// builder->SetSize
//
// Part 2: Out-of-flow layout part positions out-of-flow descendants.
//
// NGOutOfFlowLayoutPart(container_style, builder).Run();
//
// See layout part for builder interaction.
//
// @param direction: default candidate direction is builder's direction.
// Pass in direction if candidates direction does not match.
NGContainerFragmentBuilder& AddOutOfFlowChildCandidate(
NGBlockNode,
const NGLogicalOffset& child_offset);
// Inline candidates are laid out line-relative, not fragment-relative.
NGContainerFragmentBuilder& AddInlineOutOfFlowChildCandidate(
NGBlockNode,
const NGLogicalOffset& child_line_offset,
TextDirection line_direction);
NGContainerFragmentBuilder& AddOutOfFlowDescendant(
NGOutOfFlowPositionedDescendant);
void GetAndClearOutOfFlowDescendantCandidates(
Vector<NGOutOfFlowPositionedDescendant>* descendant_candidates);
protected:
// An out-of-flow positioned-candidate is a temporary data structure used
// within the NGFragmentBuilder.
//
// A positioned-candidate can be:
// 1. A direct out-of-flow positioned child. The child_offset is (0,0).
// 2. A fragment containing an out-of-flow positioned-descendant. The
// child_offset in this case is the containing fragment's offset.
//
// The child_offset is stored as a NGLogicalOffset as the physical offset
// cannot be computed until we know the current fragment's size.
//
// When returning the positioned-candidates (from
// GetAndClearOutOfFlowDescendantCandidates), the NGFragmentBuilder will
// convert the positioned-candidate to a positioned-descendant using the
// physical size the fragment builder.
struct NGOutOfFlowPositionedCandidate {
NGOutOfFlowPositionedDescendant descendant;
NGLogicalOffset child_offset; // Logical offset of child's top left vertex.
bool is_line_relative; // True if offset is relative to line, not fragment.
TextDirection line_direction;
NGOutOfFlowPositionedCandidate(
NGOutOfFlowPositionedDescendant descendant_arg,
NGLogicalOffset child_offset_arg)
: descendant(descendant_arg),
child_offset(child_offset_arg),
is_line_relative(false) {}
NGOutOfFlowPositionedCandidate(
NGOutOfFlowPositionedDescendant descendant_arg,
NGLogicalOffset child_offset_arg,
TextDirection line_direction_arg)
: descendant(descendant_arg),
child_offset(child_offset_arg),
is_line_relative(true),
line_direction(line_direction_arg) {}
};
NGContainerFragmentBuilder(scoped_refptr<const ComputedStyle>,
NGWritingMode,
TextDirection);
LayoutUnit inline_size_;
LayoutUnit block_size_;
WTF::Optional<NGBfcOffset> bfc_offset_;
NGMarginStrut end_margin_strut_;
std::unique_ptr<const NGExclusionSpace> exclusion_space_;
// Floats that need to be positioned by the next in-flow fragment that can
// determine its block position in space.
Vector<scoped_refptr<NGUnpositionedFloat>> unpositioned_floats_;
Vector<NGOutOfFlowPositionedCandidate> oof_positioned_candidates_;
Vector<NGOutOfFlowPositionedDescendant> oof_positioned_descendants_;
Vector<scoped_refptr<NGPhysicalFragment>> children_;
Vector<NGLogicalOffset> offsets_;
};
} // namespace blink
#endif // NGContainerFragmentBuilder