blob: f96a7a49c8128192cbab420754744ef88fb3ee20 [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.
#include "core/layout/ng/ng_box.h"
#include "core/layout/LayoutObject.h"
#include "core/layout/ng/layout_ng_block_flow.h"
#include "core/layout/ng/ng_block_layout_algorithm.h"
#include "core/layout/ng/ng_box_iterator.h"
#include "core/layout/ng/ng_constraint_space.h"
#include "core/layout/ng/ng_fragment.h"
#include "core/layout/ng/ng_fragment_builder.h"
#include "core/layout/ng/ng_writing_mode.h"
#include "core/layout/LayoutBlockFlow.h"
#include "core/layout/LayoutBox.h"
namespace blink {
bool NGBox::Layout(const NGConstraintSpace* constraint_space,
NGFragment** out) {
// We can either use the new layout code to do the layout and then copy the
// resulting size to the LayoutObject, or use the old layout code and
// synthesize a fragment.
NGFragment* fragment = nullptr;
if (canUseNewLayout()) {
NGBlockLayoutAlgorithm algorithm(style(), childIterator());
// Change the coordinate system of the constraint space.
NGConstraintSpace* child_constraint_space = new NGConstraintSpace(
FromPlatformWritingMode(style()->getWritingMode()), constraint_space);
if (!algorithm.Layout(child_constraint_space, &fragment))
return false;
m_layoutBox->setLogicalWidth(fragment->InlineSize());
m_layoutBox->setLogicalHeight(fragment->BlockSize());
if (m_layoutBox->isLayoutBlock())
toLayoutBlock(m_layoutBox)->layoutPositionedObjects(true);
m_layoutBox->clearNeedsLayout();
} else {
// TODO(layout-ng): If fixedSize is true, set the override width/height too
NGLogicalSize container_size = constraint_space->ContainerSize();
m_layoutBox->setOverrideContainingBlockContentLogicalWidth(
container_size.inline_size);
m_layoutBox->setOverrideContainingBlockContentLogicalHeight(
container_size.block_size);
if (m_layoutBox->isLayoutNGBlockFlow() && m_layoutBox->needsLayout()) {
toLayoutNGBlockFlow(m_layoutBox)->LayoutBlockFlow::layoutBlock(true);
} else {
m_layoutBox->layoutIfNeeded();
}
LayoutRect overflow = m_layoutBox->layoutOverflowRect();
// TODO(layout-ng): This does not handle writing modes correctly (for
// overflow & the enums)
NGFragmentBuilder builder(NGFragmentBase::FragmentBox);
builder.SetInlineSize(m_layoutBox->logicalWidth())
.SetBlockSize(m_layoutBox->logicalHeight())
.SetInlineOverflow(overflow.width())
.SetBlockOverflow(overflow.height());
fragment = builder.ToFragment();
}
*out = fragment;
return true;
}
const ComputedStyle* NGBox::style() const {
return m_layoutBox->style();
}
NGBoxIterator NGBox::childIterator() {
return NGBoxIterator(firstChild());
}
NGBox NGBox::nextSibling() const {
return m_layoutBox ? NGBox(m_layoutBox->nextSibling()) : NGBox();
}
NGBox NGBox::firstChild() const {
return m_layoutBox ? NGBox(m_layoutBox->slowFirstChild()) : NGBox();
}
void NGBox::positionUpdated(const NGFragment& fragment) {
m_layoutBox->setLogicalLeft(fragment.InlineOffset());
m_layoutBox->setLogicalTop(fragment.BlockOffset());
}
bool NGBox::canUseNewLayout() {
if (!m_layoutBox)
return true;
if (m_layoutBox->isLayoutBlockFlow() && !m_layoutBox->childrenInline())
return true;
return false;
}
} // namespace blink