blob: 2af7dfee71cf1e61d6c22b3c21152bfbcbfb925f [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_PHYSICAL_BOX_FRAGMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_BOX_FRAGMENT_H_
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
#include "third_party/blink/renderer/core/layout/ng/mathml/ng_mathml_paint_info.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h"
#include "third_party/blink/renderer/platform/graphics/scroll_types.h"
#include "third_party/blink/renderer/platform/wtf/casting.h"
namespace blink {
class NGBoxFragmentBuilder;
enum class NGOutlineType;
class CORE_EXPORT NGPhysicalBoxFragment final
: public NGPhysicalContainerFragment {
public:
static scoped_refptr<const NGPhysicalBoxFragment> Create(
NGBoxFragmentBuilder* builder,
WritingMode block_or_line_writing_mode);
using PassKey = util::PassKey<NGPhysicalBoxFragment>;
NGPhysicalBoxFragment(PassKey,
NGBoxFragmentBuilder* builder,
const NGPhysicalBoxStrut& borders,
const NGPhysicalBoxStrut& padding,
bool has_rare_data,
WritingMode block_or_line_writing_mode);
scoped_refptr<const NGLayoutResult> CloneAsHiddenForPaint() const;
~NGPhysicalBoxFragment() {
if (has_fragment_items_)
ComputeItemsAddress()->~NGFragmentItems();
if (has_rare_data_)
ComputeRareDataAddress()->~RareData();
for (const NGLink& child : Children())
child.fragment->Release();
}
// Returns |NGFragmentItems| if this fragment has one.
bool HasItems() const { return has_fragment_items_; }
const NGFragmentItems* Items() const {
return has_fragment_items_ ? ComputeItemsAddress() : nullptr;
}
base::Optional<LayoutUnit> Baseline() const {
if (has_baseline_)
return baseline_;
return base::nullopt;
}
base::Optional<LayoutUnit> LastBaseline() const {
if (has_last_baseline_)
return last_baseline_;
return base::nullopt;
}
const NGPhysicalBoxStrut Borders() const {
if (!has_borders_)
return NGPhysicalBoxStrut();
return *ComputeBordersAddress();
}
const NGPhysicalBoxStrut Padding() const {
if (!has_padding_)
return NGPhysicalBoxStrut();
return *ComputePaddingAddress();
}
bool HasOutOfFlowPositionedFragmentainerDescendants() const {
if (!has_rare_data_)
return false;
return !ComputeRareDataAddress()
->oof_positioned_fragmentainer_descendants.IsEmpty();
}
base::span<NGPhysicalOutOfFlowPositionedNode>
OutOfFlowPositionedFragmentainerDescendants() const {
if (!has_rare_data_)
return base::span<NGPhysicalOutOfFlowPositionedNode>();
Vector<NGPhysicalOutOfFlowPositionedNode>& descendants =
const_cast<Vector<NGPhysicalOutOfFlowPositionedNode>&>(
ComputeRareDataAddress()->oof_positioned_fragmentainer_descendants);
return {descendants.data(), descendants.size()};
}
NGPixelSnappedPhysicalBoxStrut PixelSnappedPadding() const {
if (!has_padding_)
return NGPixelSnappedPhysicalBoxStrut();
return ComputePaddingAddress()->SnapToDevicePixels();
}
bool HasSelfPaintingLayer() const;
// Return true if this is either a container that establishes an inline
// formatting context, or if it's non-atomic inline content participating in
// one. Empty blocks don't establish an inline formatting context.
//
// The return value from this method is undefined and irrelevant if the object
// establishes a different type of formatting context than block/inline, such
// as table or flexbox.
//
// Example:
// <div> <!-- false -->
// <div> <!-- true -->
// <div style="float:left;"></div> <!-- false -->
// <div style="float:left;"> <!-- true -->
// xxx <!-- true -->
// </div>
// <div style="float:left;"> <!-- false -->
// <div style="float:left;"></div> <!-- false -->
// </div>
// <span> <!-- true -->
// xxx <!-- true -->
// <span style="display:inline-block;"> <!-- false -->
// <div></div> <!-- false -->
// </span>
// <span style="display:inline-block;"> <!-- true -->
// xxx <!-- true -->
// </span>
// <span style="display:inline-flex;"> <!-- N/A -->
bool IsInlineFormattingContext() const {
return is_inline_formatting_context_;
}
PhysicalRect ScrollableOverflow(TextHeightType height_type) const;
PhysicalRect ScrollableOverflowFromChildren(TextHeightType height_type) const;
// TODO(layout-dev): These three methods delegate to legacy layout for now,
// update them to use LayoutNG based overflow information from the fragment
// and change them to use NG geometry types once LayoutNG supports overflow.
PhysicalRect OverflowClipRect(
const PhysicalOffset& location,
OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize) const;
LayoutSize PixelSnappedScrolledContentOffset() const;
PhysicalSize ScrollSize() const;
// Compute visual overflow of this box in the local coordinate.
PhysicalRect ComputeSelfInkOverflow() const;
// Contents ink overflow includes anything that would bleed out of the box and
// would be clipped by the overflow clip ('overflow' != visible). This
// corresponds to children that overflows their parent.
PhysicalRect ContentsInkOverflow() const {
// TODO(layout-dev): Implement box fragment overflow.
return LocalRect();
}
// Fragment offset is this fragment's offset from parent.
// Needed to compensate for LayoutInline Legacy code offsets.
void AddSelfOutlineRects(const PhysicalOffset& additional_offset,
NGOutlineType include_block_overflows,
Vector<PhysicalRect>* outline_rects) const;
UBiDiLevel BidiLevel() const;
// Bitmask for border edges, see NGBorderEdges::Physical.
unsigned BorderEdges() const { return border_edge_; }
NGPixelSnappedPhysicalBoxStrut BorderWidths() const;
// Return true if this is the first fragment generated from a node.
bool IsFirstForNode() const { return is_first_for_node_; }
#if DCHECK_IS_ON()
void CheckSameForSimplifiedLayout(const NGPhysicalBoxFragment&,
bool check_same_block_size) const;
#endif
bool HasExtraMathMLPainting() const {
if (IsMathMLFraction())
return true;
if (has_rare_data_ && ComputeRareDataAddress()->mathml_paint_info)
return true;
return false;
}
const NGMathMLPaintInfo& GetMathMLPaintInfo() const {
return *ComputeRareDataAddress()->mathml_paint_info;
}
private:
struct RareData {
RareData(NGBoxFragmentBuilder*, PhysicalSize size);
Vector<NGPhysicalOutOfFlowPositionedNode>
oof_positioned_fragmentainer_descendants;
const std::unique_ptr<NGMathMLPaintInfo> mathml_paint_info;
};
const NGFragmentItems* ComputeItemsAddress() const {
DCHECK(has_fragment_items_ || has_borders_ || has_padding_ ||
has_rare_data_);
const NGLink* children_end = children_ + Children().size();
return reinterpret_cast<const NGFragmentItems*>(children_end);
}
const NGPhysicalBoxStrut* ComputeBordersAddress() const {
DCHECK(has_borders_ || has_padding_ || has_rare_data_);
const NGFragmentItems* items = ComputeItemsAddress();
if (!has_fragment_items_)
return reinterpret_cast<const NGPhysicalBoxStrut*>(items);
return reinterpret_cast<const NGPhysicalBoxStrut*>(
reinterpret_cast<const uint8_t*>(items) + items->ByteSize());
}
const NGPhysicalBoxStrut* ComputePaddingAddress() const {
DCHECK(has_padding_ || has_rare_data_);
const NGPhysicalBoxStrut* address = ComputeBordersAddress();
return has_borders_ ? address + 1 : address;
}
const RareData* ComputeRareDataAddress() const {
DCHECK(has_rare_data_);
NGPhysicalBoxStrut* address =
const_cast<NGPhysicalBoxStrut*>(ComputePaddingAddress());
return has_padding_ ? reinterpret_cast<RareData*>(address + 1)
: reinterpret_cast<RareData*>(address);
}
#if DCHECK_IS_ON()
void CheckIntegrity() const;
#endif
LayoutUnit baseline_;
LayoutUnit last_baseline_;
NGLink children_[];
// borders, padding, and oof_positioned_fragmentainer_descendants come after
// |children_| if they are not zero.
};
template <>
struct DowncastTraits<NGPhysicalBoxFragment> {
static bool AllowFrom(const NGPhysicalFragment& fragment) {
return fragment.Type() == NGPhysicalFragment::kFragmentBox;
}
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_NG_PHYSICAL_BOX_FRAGMENT_H_