https://bugs.webkit.org/show_bug.cgi?id=184126
Reviewed by Antti Koivisto.
It holds the floating state (left/right floating stack) for a given formatting state (Block or Inline).
(FormattingState -> FloatingState/FormattingContext -> FloatingContext)
* LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js:
(BlockFormattingContext):
* LayoutReloaded/FormattingContext/FloatingContext.js:
(FloatingContext):
(FloatingContext.prototype.computePosition):
(FloatingContext.prototype.bottom):
(FloatingContext.prototype._positionForFloating):
(FloatingContext.prototype._positionForClear):
(FloatingContext.prototype._findInnerMostLeftAndRight):
(FloatingContext.prototype._isEmpty):
(FloatingContext.prototype._floatingState):
(FloatingContext.prototype._formattingContext):
(FloatingContext.prototype._lastFloating):
(FloatingContext.prototype._leftFloatingStack):
(FloatingContext.prototype._rightFloatingStack):
(FloatingContext.prototype._addFloating): Deleted.
* LayoutReloaded/FormattingContext/FormattingContext.js:
(FormattingContext):
* LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js:
(InlineFormattingContext):
* LayoutReloaded/FormattingState/BlockFormattingState.js:
(BlockFormattingState):
* LayoutReloaded/FormattingState/FloatingState.js: Copied from Tools/LayoutReloaded/FormattingState/InlineFormattingState.js.
(FloatingState):
(FloatingState.prototype.addFloating):
(FloatingState.prototype.leftFloatingStack):
(FloatingState.prototype.rightFloatingStack):
(FloatingState.prototype.lastFloating):
(FloatingState.prototype.formattingContext):
* LayoutReloaded/FormattingState/FormattingState.js:
(FormattingState):
(FormattingState.prototype.floatingState):
* LayoutReloaded/FormattingState/InlineFormattingState.js:
(InlineFormattingState):
* LayoutReloaded/test/index.html:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230067
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2018-03-28 Zalan Bujtas <zalan@apple.com>
+
+ [LayoutReloaded] Introduce FloatingState.
+ https://bugs.webkit.org/show_bug.cgi?id=184126
+
+ Reviewed by Antti Koivisto.
+
+ It holds the floating state (left/right floating stack) for a given formatting state (Block or Inline).
+ (FormattingState -> FloatingState/FormattingContext -> FloatingContext)
+
+ * LayoutReloaded/FormattingContext/BlockFormatting/BlockFormattingContext.js:
+ (BlockFormattingContext):
+ * LayoutReloaded/FormattingContext/FloatingContext.js:
+ (FloatingContext):
+ (FloatingContext.prototype.computePosition):
+ (FloatingContext.prototype.bottom):
+ (FloatingContext.prototype._positionForFloating):
+ (FloatingContext.prototype._positionForClear):
+ (FloatingContext.prototype._findInnerMostLeftAndRight):
+ (FloatingContext.prototype._isEmpty):
+ (FloatingContext.prototype._floatingState):
+ (FloatingContext.prototype._formattingContext):
+ (FloatingContext.prototype._lastFloating):
+ (FloatingContext.prototype._leftFloatingStack):
+ (FloatingContext.prototype._rightFloatingStack):
+ (FloatingContext.prototype._addFloating): Deleted.
+ * LayoutReloaded/FormattingContext/FormattingContext.js:
+ (FormattingContext):
+ * LayoutReloaded/FormattingContext/InlineFormatting/InlineFormattingContext.js:
+ (InlineFormattingContext):
+ * LayoutReloaded/FormattingState/BlockFormattingState.js:
+ (BlockFormattingState):
+ * LayoutReloaded/FormattingState/FloatingState.js: Copied from Tools/LayoutReloaded/FormattingState/InlineFormattingState.js.
+ (FloatingState):
+ (FloatingState.prototype.addFloating):
+ (FloatingState.prototype.leftFloatingStack):
+ (FloatingState.prototype.rightFloatingStack):
+ (FloatingState.prototype.lastFloating):
+ (FloatingState.prototype.formattingContext):
+ * LayoutReloaded/FormattingState/FormattingState.js:
+ (FormattingState):
+ (FormattingState.prototype.floatingState):
+ * LayoutReloaded/FormattingState/InlineFormattingState.js:
+ (InlineFormattingState):
+ * LayoutReloaded/test/index.html:
+
2018-03-28 Zalan Bujtas <zalan@apple.com>
[LayoutReloaded] Convert floating left/right stack display boxes absolute to the formatting context's root.
class BlockFormattingContext extends FormattingContext {
constructor(blockFormattingState) {
super(blockFormattingState);
- // New block formatting context always establishes a new floating context.
- this.m_floatingContext = new FloatingContext(this);
}
layout() {
// All geometry here is absolute to the formatting context's root.
class FloatingContext {
- constructor(formattingContext) {
- this.m_leftFloatingBoxStack = new Array();
- this.m_rightFloatingBoxStack = new Array();
- this.m_lastFloating = null;
- this.m_formattingContext = formattingContext;
+ constructor(floatingState) {
+ this.m_floatingState = floatingState;
}
computePosition(layoutBox) {
let displayBox = this._formattingContext().displayBox(layoutBox);
if (layoutBox.isFloatingPositioned()) {
displayBox.setTopLeft(this._positionForFloating(layoutBox));
- this._addFloating(layoutBox);
+ this._floatingState().addFloating(layoutBox);
return;
}
if (Utils.hasClear(layoutBox))
}
bottom() {
- let leftBottom = this._bottom(this.m_leftFloatingBoxStack);
- let rightBottom = this._bottom(this.m_rightFloatingBoxStack);
+ let leftBottom = this._bottom(this._leftFloatingStack());
+ let rightBottom = this._bottom(this._rightFloatingStack());
if (Number.isNaN(leftBottom) && Number.isNaN(rightBottom))
return Number.NaN;
if (!Number.isNaN(leftBottom) && !Number.isNaN(rightBottom))
let absoluteFloatingBox = this._formattingContext().absoluteMarginBox(floatingBox);
if (this._isEmpty())
return this._adjustedFloatingPosition(floatingBox, absoluteFloatingBox.top());
- let verticalPosition = Math.max(absoluteFloatingBox.top(), this.m_lastFloating.top());
+ let verticalPosition = Math.max(absoluteFloatingBox.top(), this._lastFloating().top());
let spaceNeeded = absoluteFloatingBox.width();
while (true) {
let floatingPair = this._findInnerMostLeftAndRight(verticalPosition);
let leftBottom = Number.NaN;
let rightBottom = Number.NaN;
if (Utils.hasClearLeft(layoutBox) || Utils.hasClearBoth(layoutBox))
- leftBottom = this._bottom(this.m_leftFloatingBoxStack);
+ leftBottom = this._bottom(this._leftFloatingStack());
if (Utils.hasClearRight(layoutBox) || Utils.hasClearBoth(layoutBox))
- rightBottom = this._bottom(this.m_rightFloatingBoxStack);
+ rightBottom = this._bottom(this._rightFloatingStack());
if (!Number.isNaN(leftBottom) && !Number.isNaN(rightBottom))
return new LayoutPoint(Math.max(leftBottom, rightBottom), displayBox.left());
return this._positionForFloating(layoutBox);
}
- _addFloating(floatingBox) {
- // Convert floating box to absolute.
- let floatingDisplayBox = this._formattingContext().displayBox(floatingBox).clone();
- floatingDisplayBox.setRect(this._formattingContext().absoluteMarginBox(floatingBox));
- this.m_lastFloating = floatingDisplayBox;
- if (Utils.isFloatingLeft(floatingBox)) {
- this.m_leftFloatingBoxStack.push(floatingDisplayBox);
- return;
- }
- this.m_rightFloatingBoxStack.push(floatingDisplayBox);
- }
-
_findInnerMostLeftAndRight(verticalPosition) {
- let leftFloating = this._findFloatingAtVerticalPosition(verticalPosition, this.m_leftFloatingBoxStack);
- let rightFloating = this._findFloatingAtVerticalPosition(verticalPosition, this.m_rightFloatingBoxStack);
+ let leftFloating = this._findFloatingAtVerticalPosition(verticalPosition, this._leftFloatingStack());
+ let rightFloating = this._findFloatingAtVerticalPosition(verticalPosition, this._rightFloatingStack());
return { left: leftFloating, right: rightFloating };
}
}
_isEmpty() {
- return !this.m_leftFloatingBoxStack.length && !this.m_rightFloatingBoxStack.length;
+ return !this._leftFloatingStack().length && !this._rightFloatingStack().length;
}
_adjustedFloatingPosition(floatingBox, verticalPosition, leftRightFloatings) {
return max;
}
+ _floatingState() {
+ return this.m_floatingState;
+ }
+
_formattingContext() {
- return this.m_formattingContext;
+ return this._floatingState().formattingContext();
+ }
+
+ _lastFloating() {
+ return this._floatingState().lastFloating();
+ }
+
+ _leftFloatingStack() {
+ return this._floatingState().leftFloatingStack();
+ }
+
+ _rightFloatingStack() {
+ return this._floatingState().rightFloatingStack();
}
}
class FormattingContext {
constructor(formattingState) {
this.m_formattingState = formattingState;
- this.m_floatingContext = null;
+ this.m_floatingContext = new FloatingContext(formattingState.floatingState());
this.m_layoutStack = new Array();
}
class InlineFormattingContext extends FormattingContext {
constructor(inlineFormattingState) {
super(inlineFormattingState);
- // If the block container box that initiates this inline formatting contex also establishes a block context, create a new float for us.
ASSERT(this.formattingRoot().isBlockContainerBox());
- if (this.formattingRoot().establishesBlockFormattingContext())
- this.m_floatingContext = new FloatingContext(this);
}
layout() {
class BlockFormattingState extends FormattingState {
constructor(formattingRoot, layoutState) {
super(layoutState, formattingRoot);
+ // New block formatting context always establishes a new floating context.
+ this.m_floatingState = new FloatingState(this);
this.m_formattingContext = new BlockFormattingContext(this);
}
}
--- /dev/null
+/*
+ * 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.
+ */
+
+class FloatingState {
+ constructor(formattingState) {
+ this.m_formattingState = formattingState;
+ this.m_leftFloatingBoxStack = new Array();
+ this.m_rightFloatingBoxStack = new Array();
+ this.m_lastFloating = null;
+ }
+
+ addFloating(floatingBox) {
+ // Convert floating box to absolute.
+ let floatingDisplayBox = this.formattingContext().displayBox(floatingBox).clone();
+ floatingDisplayBox.setRect(this.formattingContext().absoluteMarginBox(floatingBox));
+ this.m_lastFloating = floatingDisplayBox;
+ if (Utils.isFloatingLeft(floatingBox)) {
+ this.m_leftFloatingBoxStack.push(floatingDisplayBox);
+ return;
+ }
+ this.m_rightFloatingBoxStack.push(floatingDisplayBox);
+ }
+
+ leftFloatingStack() {
+ return this.m_leftFloatingBoxStack;
+ }
+
+ rightFloatingStack() {
+ return this.m_rightFloatingBoxStack;
+ }
+
+ lastFloating() {
+ return this.m_lastFloating;
+ }
+
+ formattingContext() {
+ return this.m_formattingState.formattingContext();
+ }
+}
this.m_layoutState = layoutState;
this.m_formattingContext = null;
this.m_formattingRoot = formattingRoot;
+ this.m_floatingState = null;
this.m_displayToLayout = new Map();
}
return this.m_layoutState;
}
+ floatingState() {
+ return this.m_floatingState;
+ }
+
createDisplayBox(layoutBox) {
let displayBox = new Display.Box(layoutBox.node());
this.m_displayToLayout.set(layoutBox, displayBox);
class InlineFormattingState extends FormattingState {
constructor(formattingRoot, layoutState) {
super(layoutState, formattingRoot);
+ // If the block container box that initiates this inline formatting contex also establishes a block context, create a new float for us.
+ if (this.formattingRoot().establishesBlockFormattingContext())
+ this.m_floatingState = new FloatingState(this);
+ else {
+ // TODO: use parent formatting context's floating state.
+ }
this.m_formattingContext = new InlineFormattingContext(this);
this.m_lines = new Array();
}
addJS("../FormattingState/FormattingState.js");
addJS("../FormattingState/BlockFormattingState.js");
addJS("../FormattingState/InlineFormattingState.js");
+addJS("../FormattingState/FloatingState.js");
addJS("../FormattingContext/FormattingContext.js");
addJS("../FormattingContext/FloatingContext.js");
addJS("../FormattingContext/BlockFormatting/BlockFormattingContext.js");