2 * Copyright (C) 2018 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 constructor(node, id) {
29 this.m_rendererName = null;
32 this.m_nextSibling = null;
33 this.m_previousSibling = null;
34 this.m_isAnonymous = false;
35 this.m_rect = new LayoutRect(new LayoutPoint(0, 0), new LayoutSize(0, 0));
36 this.m_establishedFormattingContext = null;
43 setRendererName(name) {
44 this.m_rendererName = name;
48 return this.m_rendererName;
60 return this.m_nextSibling;
64 let nextInFlowSibling = this.nextSibling();
65 while (nextInFlowSibling) {
66 if (nextInFlowSibling.isInFlow())
67 return nextInFlowSibling;
68 nextInFlowSibling = nextInFlowSibling.nextSibling();
74 return this.m_previousSibling;
77 previousInFlowSibling() {
78 let previousInFlowSibling = this.previousSibling();
79 while (previousInFlowSibling) {
80 if (previousInFlowSibling.isInFlow())
81 return previousInFlowSibling;
82 previousInFlowSibling = previousInFlowSibling.previousSibling();
88 this.m_parent = parent;
91 setNextSibling(nextSibling) {
92 this.m_nextSibling = nextSibling;
95 setPreviousSibling(previousSibling) {
96 this.m_previousSibling = previousSibling;
100 return this.m_rect.clone();
104 return this.rect().topLeft();
108 return this.rect().bottomRight();
111 setTopLeft(topLeft) {
112 this.m_rect.setTopLeft(topLeft);
116 this.m_rect.setSize(size);
120 this.m_rect.setWidth(width);
124 this.m_rect.setHeight(height);
132 return Utils.isBlockLevelElement(this.node());
135 isBlockContainerBox() {
136 return Utils.isBlockContainerElement(this.node());
140 return Utils.isInlineLevelElement(this.node());
144 this.m_isAnonymous = true;
148 return this.m_isAnonymous;
151 establishesFormattingContext() {
152 if (this.isAnonymous())
154 return this.establishesBlockFormattingContext() || this.establishesInlineFormattingContext();
157 establishedFormattingContext() {
158 if (this.establishesFormattingContext() && !this.m_establishedFormattingContext)
159 this.m_establishedFormattingContext = this.establishesBlockFormattingContext() ? new BlockFormattingContext(this) : new InlineFormattingContext(this);
160 return this.m_establishedFormattingContext;
163 establishesBlockFormattingContext() {
164 // 9.4.1 Block formatting contexts
165 // Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions)
166 // that are not block boxes, and block boxes with 'overflow' other than 'visible' (except when that value has been propagated to the viewport)
167 // establish new block formatting contexts for their contents.
168 return this.isFloatingPositioned() || this.isAbsolutePositioned() || (this.isBlockContainerBox() && !this.isBlockLevelBox())
169 || (this.isBlockLevelBox() && !Utils.isOverflowVisible(this));
172 establishesInlineFormattingContext() {
177 return this.isOutOfFlowPositioned() || this.isRelativePositioned();
180 isRelativePositioned() {
181 return Utils.isRelativePositioned(this);
184 isAbsolutePositioned() {
185 return Utils.isAbsolutePositioned(this);
188 isFixedPositioned() {
189 return Utils.isFixedPositioned(this);
193 if (this.isAnonymous())
195 return !this.isFloatingOrOutOfFlowPositioned();
198 isOutOfFlowPositioned() {
199 return this.isAbsolutePositioned() || this.isFixedPositioned();
202 isInFlowPositioned() {
203 return this.isPositioned() && !this.isOutOfFlowPositioned();
206 isFloatingPositioned() {
207 return Utils.isFloatingPositioned(this);
210 isFloatingOrOutOfFlowPositioned() {
211 return this.isFloatingPositioned() || this.isOutOfFlowPositioned();
215 // FIXME: This should just be a simple instanceof check, but we are in the mainframe while the test document is in an iframe
216 // Let's just return root for both the RenderView and the <html> element.
217 return !this.parent() || !this.parent().parent();
223 if (!this.isPositioned() || this.isInFlowPositioned())
224 return this.parent();
225 let parent = this.parent();
226 while (parent.parent()) {
227 if (this.isAbsolutePositioned() && parent.isPositioned())
229 parent = parent.parent();
235 return new LayoutRect(new LayoutPoint(0, 0), this.rect().size());
239 let paddingBox = this.borderBox();
240 let borderSize = Utils.computedBorderTopLeft(this);
241 paddingBox.moveBy(borderSize);
242 paddingBox.shrinkBy(borderSize);
243 paddingBox.shrinkBy(Utils.computedBorderBottomRight(this));
248 let contentBox = this.paddingBox();
249 let paddingSize = Utils.computedPaddingTopLeft(this);
250 contentBox.moveBy(paddingSize);
251 contentBox.shrinkBy(paddingSize);
252 contentBox.shrinkBy(Utils.computedPaddingBottomRight(this));