287 lines
8.3 KiB
JavaScript
287 lines
8.3 KiB
JavaScript
/*
|
|
* Copyright (C) 2018 Apple Inc. All Rights Reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/*
|
|
namespace Layout {
|
|
class Box {
|
|
public:
|
|
Layout::Container& parent();
|
|
Layout::Box* nextSibling();
|
|
Layout::Box* nextInFlowSibling();
|
|
Layout::Box* nextInFlowOrFloatSibling();
|
|
Layout::Box* previousSibling();
|
|
Layout::Box* previousInFlowSibling();
|
|
|
|
void setParent(Layout::Container&);
|
|
void setNextSibling(Layout::Box&);
|
|
void setPreviousSibling(Layout::Box&);
|
|
|
|
bool isContainer();
|
|
bool isInlineContainer();
|
|
bool isInlineBox();
|
|
bool isBlockLevelBox();
|
|
bool isBlockContainerBox();
|
|
bool isInlineBlockBox();
|
|
bool isInlineLevelBox();
|
|
|
|
void setIsAnonymous(bool);
|
|
bool isAnonymous();
|
|
|
|
bool establishesFormattingContext();
|
|
bool establishesBlockFormattingContext();
|
|
bool establishesInlineFormattingContext();
|
|
|
|
bool isPositioned();
|
|
bool isRelativelyPositioned();
|
|
bool isAbsolutelyPositioned();
|
|
bool isFixedPositioned();
|
|
bool isInFlow();
|
|
bool isOutOfFlowPositioned();
|
|
bool isInFlowPositioned();
|
|
bool isFloatingPositioned();
|
|
bool isFloatingOrOutOfFlowPositioned();
|
|
bool isRootBox();
|
|
Layout::Container* containingBlock();
|
|
bool isDescendantOf(Layout::Container&);
|
|
};
|
|
}
|
|
*/
|
|
|
|
var Layout = { }
|
|
|
|
Layout.Box = class Box {
|
|
constructor(node, id) {
|
|
this.m_id = id;
|
|
this.m_rendererName = null;
|
|
this.m_node = node;
|
|
this.m_parent = null;
|
|
this.m_nextSibling = null;
|
|
this.m_previousSibling = null;
|
|
this.m_isAnonymous = false;
|
|
this.m_displayBox = null;
|
|
}
|
|
|
|
id() {
|
|
return this.m_id;
|
|
}
|
|
|
|
setRendererName(name) {
|
|
this.m_rendererName = name;
|
|
}
|
|
|
|
name() {
|
|
return this.m_rendererName;
|
|
}
|
|
|
|
node() {
|
|
return this.m_node;
|
|
}
|
|
|
|
parent() {
|
|
return this.m_parent;
|
|
}
|
|
|
|
nextSibling() {
|
|
return this.m_nextSibling;
|
|
}
|
|
|
|
nextInFlowSibling() {
|
|
let nextInFlowSibling = this.nextSibling();
|
|
while (nextInFlowSibling) {
|
|
if (nextInFlowSibling.isInFlow())
|
|
return nextInFlowSibling;
|
|
nextInFlowSibling = nextInFlowSibling.nextSibling();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
nextInFlowOrFloatSibling() {
|
|
let nextInFlowSibling = this.nextSibling();
|
|
while (nextInFlowSibling) {
|
|
if (nextInFlowSibling.isInFlow() || nextInFlowSibling.isFloatingPositioned())
|
|
return nextInFlowSibling;
|
|
nextInFlowSibling = nextInFlowSibling.nextSibling();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
previousSibling() {
|
|
return this.m_previousSibling;
|
|
}
|
|
|
|
previousInFlowSibling() {
|
|
let previousInFlowSibling = this.previousSibling();
|
|
while (previousInFlowSibling) {
|
|
if (previousInFlowSibling.isInFlow())
|
|
return previousInFlowSibling;
|
|
previousInFlowSibling = previousInFlowSibling.previousSibling();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
setParent(parent) {
|
|
this.m_parent = parent;
|
|
}
|
|
|
|
setNextSibling(nextSibling) {
|
|
this.m_nextSibling = nextSibling;
|
|
}
|
|
|
|
setPreviousSibling(previousSibling) {
|
|
this.m_previousSibling = previousSibling;
|
|
}
|
|
|
|
isContainer() {
|
|
return this instanceof Layout.Container
|
|
}
|
|
|
|
isInlineContainer() {
|
|
return this instanceof Layout.InlineContainer
|
|
}
|
|
|
|
isInlineBox() {
|
|
return this instanceof Layout.InlineBox;
|
|
}
|
|
|
|
isBlockLevelBox() {
|
|
return Utils.isBlockLevelElement(this.node());
|
|
}
|
|
|
|
isBlockContainerBox() {
|
|
return Utils.isBlockContainerElement(this.node());
|
|
}
|
|
|
|
isInlineBlockBox() {
|
|
return Utils.isInlineBlockElement(this.node());
|
|
}
|
|
|
|
isInlineLevelBox() {
|
|
return Utils.isInlineLevelElement(this.node());
|
|
}
|
|
|
|
setIsAnonymous() {
|
|
this.m_isAnonymous = true;
|
|
}
|
|
|
|
isAnonymous() {
|
|
return this.m_isAnonymous;
|
|
}
|
|
|
|
establishesFormattingContext() {
|
|
if (this.isAnonymous())
|
|
return false;
|
|
return this.establishesBlockFormattingContext() || this.establishesInlineFormattingContext();
|
|
}
|
|
|
|
establishesBlockFormattingContext() {
|
|
// Initial Containing Block always creates a new (inital) block formatting context.
|
|
if (!this.parent())
|
|
return true;
|
|
// 9.4.1 Block formatting contexts
|
|
// Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions)
|
|
// that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport)
|
|
// establish new block formatting contexts for their contents.
|
|
return this.isFloatingPositioned() || this.isAbsolutelyPositioned() || (this.isBlockContainerBox() && !this.isBlockLevelBox())
|
|
|| (this.isBlockLevelBox() && !Utils.isOverflowVisible(this));
|
|
}
|
|
|
|
establishesInlineFormattingContext() {
|
|
return false;
|
|
}
|
|
|
|
isPositioned() {
|
|
return this.isOutOfFlowPositioned() || this.isRelativelyPositioned();
|
|
}
|
|
|
|
isRelativelyPositioned() {
|
|
return Utils.isRelativelyPositioned(this);
|
|
}
|
|
|
|
isAbsolutelyPositioned() {
|
|
return Utils.isAbsolutelyPositioned(this) || this.isFixedPositioned();
|
|
}
|
|
|
|
isFixedPositioned() {
|
|
return Utils.isFixedPositioned(this);
|
|
}
|
|
|
|
isInFlow() {
|
|
if (this.isAnonymous())
|
|
return true;
|
|
return !this.isFloatingOrOutOfFlowPositioned();
|
|
}
|
|
|
|
isOutOfFlowPositioned() {
|
|
return this.isAbsolutelyPositioned();
|
|
}
|
|
|
|
isInFlowPositioned() {
|
|
return this.isPositioned() && !this.isOutOfFlowPositioned();
|
|
}
|
|
|
|
isFloatingPositioned() {
|
|
return Utils.isFloatingPositioned(this);
|
|
}
|
|
|
|
isFloatingOrOutOfFlowPositioned() {
|
|
return this.isFloatingPositioned() || this.isOutOfFlowPositioned();
|
|
}
|
|
|
|
isRootBox() {
|
|
// FIXME: This should just be a simple instanceof check, but we are in the mainframe while the test document is in an iframe
|
|
// Let's just return root for both the RenderView and the <html> element.
|
|
return !this.parent() || !this.parent().parent();
|
|
}
|
|
|
|
containingBlock() {
|
|
if (!this.parent())
|
|
return null;
|
|
if (!this.isPositioned() || this.isInFlowPositioned())
|
|
return this.parent();
|
|
if (this.isOutOfFlowPositioned() && !this.isFixedPositioned()) {
|
|
let ascendant = this.parent();
|
|
while (ascendant.parent() && !ascendant.isPositioned())
|
|
ascendant = ascendant.parent();
|
|
return ascendant;
|
|
}
|
|
if (this.isFixedPositioned()) {
|
|
let ascendant = this.parent();
|
|
while (ascendant.parent())
|
|
ascendant = ascendant.parent();
|
|
return ascendant;
|
|
}
|
|
ASSERT_NOT_REACHED();
|
|
return null;
|
|
}
|
|
|
|
isDescendantOf(container) {
|
|
ASSERT(container);
|
|
let ascendant = this.parent();
|
|
while (ascendant && ascendant != container)
|
|
ascendant = ascendant.parent();
|
|
return !!ascendant;
|
|
}
|
|
}
|