blob: 0e8fbe870fbe67dd50acc0f5356d808bbf2c5320 [file] [log] [blame]
// Copyright 2016 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 THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_OUT_OF_FLOW_LAYOUT_PART_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_OUT_OF_FLOW_LAYOUT_PART_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "base/optional.h"
#include "third_party/blink/renderer/core/layout/geometry/logical_rect.h"
#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
#include "third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
#include "third_party/blink/renderer/core/style/computed_style_base_constants.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace blink {
class ComputedStyle;
class LayoutBox;
class LayoutObject;
class NGBlockBreakToken;
class NGBlockNode;
class NGBoxFragmentBuilder;
class NGLayoutResult;
class NGPhysicalContainerFragment;
struct NGLink;
struct NGLogicalOutOfFlowPositionedNode;
// Helper class for positioning of out-of-flow blocks.
// It should be used together with NGBoxFragmentBuilder.
// See NGBoxFragmentBuilder::AddOutOfFlowChildCandidate documentation
// for example of using these classes together.
class CORE_EXPORT NGOutOfFlowLayoutPart {
STACK_ALLOCATED();
public:
NGOutOfFlowLayoutPart(const NGBlockNode& container_node,
const NGConstraintSpace& container_space,
NGBoxFragmentBuilder* container_builder);
// The |container_builder|, |container_space|, and |container_style|
// parameters are all with respect to the containing block of the relevant
// out-of-flow positioned descendants. If the CSS "containing block" of such
// an out-of-flow positioned descendant isn't a true block (e.g. a relatively
// positioned inline instead), the containing block here is the containing
// block of said non-block.
NGOutOfFlowLayoutPart(
bool is_absolute_container,
bool is_fixed_container,
const ComputedStyle& container_style,
const NGConstraintSpace& container_space,
NGBoxFragmentBuilder* container_builder,
base::Optional<LogicalSize> initial_containing_block_fixed_size =
base::nullopt);
// Normally this function lays out and positions all out-of-flow objects from
// the container_builder and additional ones it discovers through laying out
// those objects. However, if only_layout is specified, only that object will
// get laid out; any additional ones will be stored as out-of-flow
// descendants in the builder for use via
// LayoutResult::OutOfFlowPositionedDescendants.
void Run(const LayoutBox* only_layout = nullptr);
private:
// Information needed to position descendant within a containing block.
// Geometry expressed here is complicated:
// There are two types of containing blocks:
// 1) Default containing block (DCB)
// Containing block passed in NGOutOfFlowLayoutPart constructor.
// It is the block element inside which this algorighm runs.
// All OOF descendants not in inline containing block are placed in DCB.
// 2) Inline containing block
// OOF descendants might be positioned wrt inline containing block.
// Inline containing block is positioned wrt default containing block.
struct ContainingBlockInfo {
STACK_ALLOCATED();
public:
// The writing direction of the container.
WritingDirectionMode writing_direction = {WritingMode::kHorizontalTb,
TextDirection::kLtr};
// Size and offset of the container.
LogicalRect rect;
};
// TODO(almaher): Move this to the multicol algorithm in upcoming refactor.
// This stores the information needed to update a multicol child inside an
// existing multicol fragment. This is used during nested fragmentation of an
// OOF positioned element.
struct MulticolChildInfo {
// The mutable link of a multicol child.
NGLink* mutable_link;
// The multicol break token that stores a reference to |mutable_link|'s
// break token in its list of child break tokens.
const NGBlockBreakToken* parent_break_token;
explicit MulticolChildInfo(NGLink* mutable_link,
NGBlockBreakToken* parent_break_token = nullptr)
: mutable_link(mutable_link), parent_break_token(parent_break_token) {}
};
bool SweepLegacyCandidates(HashSet<const LayoutObject*>* placed_objects);
const ContainingBlockInfo GetContainingBlockInfo(
const NGLogicalOutOfFlowPositionedNode&,
const NGPhysicalContainerFragment* = nullptr);
void ComputeInlineContainingBlocks(
const Vector<NGLogicalOutOfFlowPositionedNode>&);
void LayoutCandidates(Vector<NGLogicalOutOfFlowPositionedNode>* candidates,
const LayoutBox* only_layout,
HashSet<const LayoutObject*>* placed_objects);
scoped_refptr<const NGLayoutResult> LayoutCandidate(
const NGLogicalOutOfFlowPositionedNode&,
const LayoutBox* only_layout);
void LayoutOOFsInMulticol(const NGBlockNode& multicol);
// Layout the OOF nodes that are descendants of a fragmentation context root.
// |multicol_children| holds the children of an inner multicol if
// we are laying out OOF elements inside a nested fragmentation context.
void LayoutFragmentainerDescendants(
Vector<NGLogicalOutOfFlowPositionedNode>* descendants,
LayoutUnit column_inline_progression,
Vector<MulticolChildInfo>* multicol_children = nullptr);
scoped_refptr<const NGLayoutResult> LayoutFragmentainerDescendant(
const NGLogicalOutOfFlowPositionedNode&);
scoped_refptr<const NGLayoutResult> Layout(
NGBlockNode,
const NGConstraintSpace&,
const NGLogicalStaticPosition&,
PhysicalSize container_physical_content_size,
const ContainingBlockInfo&,
const WritingDirectionMode,
const LayoutBox* only_layout,
bool is_fragmentainer_descendant = false);
bool IsContainingBlockForCandidate(const NGLogicalOutOfFlowPositionedNode&);
scoped_refptr<const NGLayoutResult> GenerateFragment(
NGBlockNode node,
const LogicalSize& container_content_size_in_child_writing_mode,
const base::Optional<LayoutUnit>& block_estimate,
const NGLogicalOutOfFlowDimensions& node_dimensions,
const LayoutUnit block_offset,
const NGBlockBreakToken* break_token,
const NGConstraintSpace* fragmentainer_constraint_space,
bool should_use_fixed_block_size);
void AddOOFResultsToFragmentainer(
const Vector<scoped_refptr<const NGLayoutResult>>& results,
wtf_size_t index,
LayoutUnit column_inline_progression,
Vector<MulticolChildInfo>* multicol_children = nullptr);
const NGConstraintSpace& GetFragmentainerConstraintSpace(wtf_size_t index);
void AddOOFResultToFragmentainerResults(
const scoped_refptr<const NGLayoutResult> result,
wtf_size_t index);
void ComputeStartFragmentIndexAndRelativeOffset(
const ContainingBlockInfo& container_info,
WritingMode default_writing_mode,
LayoutUnit block_estimate,
wtf_size_t* start_index,
LogicalOffset* offset) const;
NGBoxFragmentBuilder* container_builder_;
ContainingBlockInfo default_containing_block_info_for_absolute_;
ContainingBlockInfo default_containing_block_info_for_fixed_;
HashMap<const LayoutObject*, ContainingBlockInfo> containing_blocks_map_;
HashMap<wtf_size_t, NGConstraintSpace> fragmentainer_constraint_space_map_;
// Map of fragmentainer indexes to a list of descendant layout results to
// be added as children.
HashMap<wtf_size_t, Vector<scoped_refptr<const NGLayoutResult>>>
fragmentainer_descendant_results_;
const WritingMode writing_mode_;
const WritingDirectionMode default_writing_direction_;
// The block size of the multi-column (before adjustment for spanners, etc.)
// This is used to calculate the column size of any newly added proxy
// fragments when handling fragmentation for abspos elements.
LayoutUnit original_column_block_size_ = kIndefiniteSize;
bool is_absolute_container_;
bool is_fixed_container_;
bool allow_first_tier_oof_cache_;
bool has_block_fragmentation_;
bool can_traverse_fragments_ = false;
bool nested_fragmentation_context_ = false;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_OUT_OF_FLOW_LAYOUT_PART_H_