[LFC] Adjust static position with containing block's content box top/left
[WebKit-https.git] / Source / WebCore / layout / displaytree / DisplayBox.h
index e9d429f8ac99444898e4128ad56ad1dfe00b0c69..ba2d866a1a21be4b54acaf9ba64428c631838788 100644 (file)
 #include "LayoutPoint.h"
 #include "LayoutRect.h"
 #include "LayoutUnit.h"
+#include "RenderStyleConstants.h"
 #include <wtf/IsoMalloc.h>
 
 namespace WebCore {
+
+class RenderStyle;
+
+namespace Layout {
+class BlockFormattingContext;
+class FormattingContext;
+class LayoutContext;
+}
+
 namespace Display {
 
 class Box {
     WTF_MAKE_ISO_ALLOCATED(Box);
 public:
-    friend class FormattingContext;
+    friend class Layout::BlockFormattingContext;
+    friend class Layout::FormattingContext;
+    friend class Layout::LayoutContext;
 
-    ~Box();
+    class Rect {
+    public:
+        Rect() = default;
+        
+        LayoutUnit top() const;
+        LayoutUnit left() const;
+        LayoutPoint topLeft() const;
 
-    LayoutRect rect() const { return m_rect; }
+        LayoutUnit bottom() const;
+        LayoutUnit right() const;        
+        LayoutPoint bottomRight() const;
 
-    LayoutUnit top() const { return m_rect.y(); }
-    LayoutUnit left() const { return m_rect.x(); }
-    LayoutUnit bottom() const { return m_rect.maxY(); }
-    LayoutUnit right() const { return m_rect.maxX(); }
+        LayoutUnit width() const;
+        LayoutUnit height() const;
+        LayoutSize size() const;
 
-    LayoutPoint topLeft() const { return m_rect.location(); }
-    LayoutPoint bottomRight() const { return m_rect.location(); }
+        void setTop(LayoutUnit);
+        void setLeft(LayoutUnit);
+        void setTopLeft(const LayoutPoint&);
+        void setWidth(LayoutUnit);
+        void setHeight(LayoutUnit);
+        void setSize(const LayoutSize&);
 
-    LayoutSize size() const { return m_rect.size(); }
-    LayoutUnit width() const { return m_rect.width(); }
-    LayoutUnit height() const { return m_rect.height(); }
+        void shiftLeftTo(LayoutUnit);
+        void shiftRightTo(LayoutUnit);
+        void shiftTopTo(LayoutUnit);
+        void shiftBottomTo(LayoutUnit);
 
-    LayoutUnit marginTop() const { return m_marginTop; }
-    LayoutUnit marginLeft() const { return m_marginLeft; }
-    LayoutUnit marginBottom() const { return m_marginBottom; }
-    LayoutUnit marginRight() const { return m_marginRight; }
+        void moveHorizontally(LayoutUnit);
+        void moveVertically(LayoutUnit);
 
-    LayoutRect marginBox() const;
-    LayoutRect borderBox() const;
-    LayoutRect paddingBox() const;
-    LayoutRect contentBox() const;
+        void expand(LayoutUnit, LayoutUnit);
 
-    const Box* parent() const { return m_parent; }
-    const Box* nextSibling() const { return m_parent; }
-    const Box* previousSibling() const { return m_parent; }
-    const Box* firstChild() const { return m_firstChild; }
-    const Box* lastChild() const { return m_lastChild; }
+        Rect clone() const;
+        operator LayoutRect() const;
+
+    private:
+#if !ASSERT_DISABLED
+        void invalidateTop() { m_hasValidTop = false; }
+        void invalidateLeft() { m_hasValidLeft = false; }
+        void invalidateWidth() { m_hasValidWidth = false; }
+        void invalidateHeight() { m_hasValidHeight = false; }
+        void invalidatePosition();
+
+        bool hasValidPosition() const { return m_hasValidTop && m_hasValidLeft; }
+        bool hasValidSize() const { return m_hasValidWidth && m_hasValidHeight; }
+        bool hasValidGeometry() const { return hasValidPosition() && hasValidSize(); }
     
+        void setHasValidPosition();
+        void setHasValidSize();
+
+        bool m_hasValidTop { false };
+        bool m_hasValidLeft { false };
+        bool m_hasValidWidth { false };
+        bool m_hasValidHeight { false };
+#endif
+        LayoutRect m_rect;
+    };
+
+    ~Box();
+
+    LayoutUnit top() const { return m_topLeft.y(); }
+    LayoutUnit left() const { return m_topLeft.x(); }
+    LayoutUnit bottom() const { return top() + height(); }
+    LayoutUnit right() const { return left() + width(); }
+
+    LayoutPoint topLeft() const { return m_topLeft; }
+    LayoutPoint bottomRight() const { return { right(), bottom() }; }
+
+    LayoutSize size() const { return { width(), height() }; }
+    LayoutUnit width() const { return borderLeft() + paddingLeft() + contentBoxWidth() + paddingRight() + borderRight(); }
+    LayoutUnit height() const { return borderTop() + paddingTop() + contentBoxHeight() + paddingBottom() + borderBottom(); }
+    LayoutRect rect() const { return { left(), top(), width(), height() }; }
+
+    LayoutUnit marginTop() const;
+    LayoutUnit marginLeft() const;
+    LayoutUnit marginBottom() const;
+    LayoutUnit marginRight() const;
+
+    LayoutUnit borderTop() const;
+    LayoutUnit borderLeft() const;
+    LayoutUnit borderBottom() const;
+    LayoutUnit borderRight() const;
+
+    LayoutUnit paddingTop() const;
+    LayoutUnit paddingLeft() const;
+    LayoutUnit paddingBottom() const;
+    LayoutUnit paddingRight() const;
+
+    LayoutUnit contentBoxTop() const { return borderTop() + paddingTop(); }
+    LayoutUnit contentBoxLeft() const { return borderLeft() + paddingLeft(); }
+    LayoutUnit contentBoxHeight() const;
+    LayoutUnit contentBoxWidth() const;
+
+    Rect marginBox() const;
+    Rect borderBox() const;
+    Rect paddingBox() const;
+    Rect contentBox() const;
+
 private:
-    Box();
-
-    void setRect(const LayoutRect& rect) { m_rect = rect; }
-    void setTopLeft(const LayoutPoint& topLeft) { m_rect.setLocation(topLeft); }
-    void setTop(LayoutUnit top) { m_rect.setY(top); }
-    void setLeft(LayoutUnit left) { m_rect.setX(left); }
-    void setSize(const LayoutSize& size) { m_rect.setSize(size); }
-    void setWidth(LayoutUnit width) { m_rect.setWidth(width); }
-    void setHeight(LayoutUnit height) { m_rect.setHeight(height); }
-
-    void setMarginTop(LayoutUnit marginTop) { m_marginTop = marginTop; }
-    void setMarginLeft(LayoutUnit marginLeft) { m_marginLeft = marginLeft; }
-    void setMarginBottom(LayoutUnit marginBottom) { m_marginBottom = marginBottom; }
-    void setMarginRight(LayoutUnit marginRight) { m_marginRight = marginRight; }
-
-    void setBorderTop(LayoutUnit borderTop) { m_borderTop = borderTop; }
-    void setBorderLeft(LayoutUnit borderLeft) { m_borderLeft = borderLeft; }
-    void setBorderBottom(LayoutUnit borderBottom) { m_borderBottom = borderBottom; }
-    void setBorderRight(LayoutUnit borderRight) { m_borderRight = borderRight; }
-
-    void setPaddingTop(LayoutUnit paddingTop) { m_paddingTop = paddingTop; }
-    void setPaddingLeft(LayoutUnit paddingLeft) { m_paddingLeft = paddingLeft; }
-    void setPaddingBottom(LayoutUnit paddingBottom) { m_paddingBottom = paddingBottom; }
-    void setPaddingRight(LayoutUnit paddingRight) { m_paddingRight = paddingRight; }
-
-    void setParent(Box& parent) { m_parent = &parent; }
-    void setNextSibling(Box& nextSibling) { m_nextSibling = &nextSibling; }
-    void setPreviousSibling(Box& previousSibling) { m_previousSibling = &previousSibling; }
-    void setFirstChild(Box& firstChild) { m_firstChild = &firstChild; }
-    void setLastChild(Box& lastChild) { m_lastChild = &lastChild; }
-
-    LayoutRect m_rect;
-    LayoutUnit m_marginTop;
-    LayoutUnit m_marginLeft;
-    LayoutUnit m_marginBottom;
-    LayoutUnit m_marginRight;
-
-    LayoutUnit m_borderTop;
-    LayoutUnit m_borderLeft;
-    LayoutUnit m_borderBottom;
-    LayoutUnit m_borderRight;
-
-    LayoutUnit m_paddingTop;
-    LayoutUnit m_paddingLeft;
-    LayoutUnit m_paddingBottom;
-    LayoutUnit m_paddingRight;
-
-    const Box* m_parent { nullptr };
-    const Box* m_nextSibling { nullptr };
-    const Box* m_previousSibling { nullptr };
-    const Box* m_firstChild { nullptr };
-    const Box* m_lastChild { nullptr };
+    Box(const RenderStyle&);
+
+    struct Style {
+        Style(const RenderStyle&);
+
+        BoxSizing boxSizing { BoxSizing::ContentBox };
+    };
+
+    void setTopLeft(const LayoutPoint& topLeft) { m_topLeft = topLeft; }
+    void setTop(LayoutUnit top) { m_topLeft.setY(top); }
+    void setLeft(LayoutUnit left) { m_topLeft.setX(left); }
+    void moveHorizontally(LayoutUnit offset) { m_topLeft.move(offset, { }); }
+    void moveVertically(LayoutUnit offset) { m_topLeft.move({ }, offset); }
+
+    void setContentBoxHeight(LayoutUnit);
+    void setContentBoxWidth(LayoutUnit);
+
+    struct HorizontalEdges {
+        LayoutUnit left;
+        LayoutUnit right;
+    };
+
+    struct VerticalEdges {
+        LayoutUnit top;
+        LayoutUnit bottom;
+    };
+
+    struct Edges {
+        HorizontalEdges horizontal;
+        VerticalEdges vertical;
+    };
+
+    void setHorizontalMargin(HorizontalEdges);
+    void setVerticalMargin(VerticalEdges);
+    void setBorder(Edges);
+    void setPadding(Edges);
 
+#if !ASSERT_DISABLED
+    void invalidateMargin();
+    void invalidateBorder() { m_hasValidBorder = false; }
+    void invalidatePadding() { m_hasValidPadding = false; }
+
+    void setHasValidVerticalMargin() { m_hasValidVerticalMargin = true; }
+    void setHasValidHorizontalMargin() { m_hasValidHorizontalMargin = true; }
+
+    void setHasValidBorder() { m_hasValidBorder = true; }
+    void setHasValidPadding() { m_hasValidPadding = true; }
+
+    void setHasValidContentHeight() { m_hasValidContentHeight = true; }
+    void setHasValidContentWidth() { m_hasValidContentWidth = true; }
+#endif
+
+    const Style m_style;
+
+    LayoutPoint m_topLeft;
+    LayoutUnit m_contentWidth;
+    LayoutUnit m_contentHeight;
+
+    Edges m_margin;
+    Edges m_border;
+    Edges m_padding;
+
+#if !ASSERT_DISABLED
+    bool m_hasValidHorizontalMargin { false };
+    bool m_hasValidVerticalMargin { false };
+    bool m_hasValidBorder { false };
+    bool m_hasValidPadding { false };
+    bool m_hasValidContentHeight { false };
+    bool m_hasValidContentWidth { false };
+#endif
 };
 
+#if !ASSERT_DISABLED
+inline void Box::Rect::invalidatePosition()
+{
+    invalidateTop();
+    invalidateLeft();
+}
+
+inline void Box::Rect::setHasValidPosition()
+{
+    m_hasValidTop = true;
+    m_hasValidLeft = true;
+}
+
+inline void Box::Rect::setHasValidSize()
+{
+    m_hasValidWidth = true;
+    m_hasValidHeight = true;
+}
+
+inline void Box::invalidateMargin()
+{
+    m_hasValidHorizontalMargin = false;
+    m_hasValidVerticalMargin = false;
+}
+#endif
+
+inline LayoutUnit Box::Rect::top() const
+{
+    ASSERT(m_hasValidTop);
+    return m_rect.y();
+}
+
+inline LayoutUnit Box::Rect::left() const
+{
+    ASSERT(m_hasValidLeft);
+    return m_rect.x();
+}
+
+inline LayoutUnit Box::Rect::bottom() const
+{
+    ASSERT(m_hasValidTop && m_hasValidHeight);
+    return m_rect.maxY();
+}
+
+inline LayoutUnit Box::Rect::right() const
+{
+    ASSERT(m_hasValidLeft && m_hasValidWidth);
+    return m_rect.maxX();
+}
+
+inline LayoutPoint Box::Rect::topLeft() const
+{
+    ASSERT(hasValidPosition());
+    return m_rect.minXMinYCorner();
+}
+
+inline LayoutPoint Box::Rect::bottomRight() const
+{
+    ASSERT(hasValidGeometry());
+    return m_rect.maxXMaxYCorner();
+}
+
+inline LayoutSize Box::Rect::size() const
+{
+    ASSERT(hasValidSize());
+    return m_rect.size();
+}
+
+inline LayoutUnit Box::Rect::width() const
+{
+    ASSERT(m_hasValidWidth);
+    return m_rect.width();
+}
+
+inline LayoutUnit Box::Rect::height() const
+{
+    ASSERT(m_hasValidHeight);
+    return m_rect.height();
+}
+
+inline void Box::Rect::setTopLeft(const LayoutPoint& topLeft)
+{
+#if !ASSERT_DISABLED
+    setHasValidPosition();
+#endif
+    m_rect.setLocation(topLeft);
+}
+
+inline void Box::Rect::setTop(LayoutUnit top)
+{
+#if !ASSERT_DISABLED
+    m_hasValidTop = true;
+#endif
+    m_rect.setY(top);
+}
+
+inline void Box::Rect::setLeft(LayoutUnit left)
+{
+#if !ASSERT_DISABLED
+    m_hasValidLeft = true;
+#endif
+    m_rect.setX(left);
+}
+
+inline void Box::Rect::setWidth(LayoutUnit width)
+{
+#if !ASSERT_DISABLED
+    m_hasValidWidth = true;
+#endif
+    m_rect.setWidth(width);
+}
+
+inline void Box::Rect::setHeight(LayoutUnit height)
+{
+#if !ASSERT_DISABLED
+    m_hasValidHeight = true;
+#endif
+    m_rect.setHeight(height);
+}
+
+inline void Box::Rect::setSize(const LayoutSize& size)
+{
+#if !ASSERT_DISABLED
+    setHasValidSize();
+#endif
+    m_rect.setSize(size);
+}
+
+inline void Box::Rect::shiftLeftTo(LayoutUnit left)
+{
+    ASSERT(m_hasValidLeft);
+    m_rect.shiftXEdgeTo(left);
+}
+
+inline void Box::Rect::shiftRightTo(LayoutUnit right)
+{
+    ASSERT(m_hasValidLeft && m_hasValidWidth);
+    m_rect.shiftMaxXEdgeTo(right);
+}
+
+inline void Box::Rect::shiftTopTo(LayoutUnit top)
+{
+    ASSERT(m_hasValidTop);
+    m_rect.shiftYEdgeTo(top);
+}
+
+inline void Box::Rect::shiftBottomTo(LayoutUnit bottom)
+{
+    ASSERT(m_hasValidTop && m_hasValidHeight);
+    m_rect.shiftMaxYEdgeTo(bottom);
+}
+
+inline void Box::Rect::moveHorizontally(LayoutUnit offset)
+{
+    ASSERT(m_hasValidLeft);
+    m_rect.move(offset, { });
+}
+
+inline void Box::Rect::moveVertically(LayoutUnit offset)
+{
+    ASSERT(m_hasValidTop);
+    m_rect.move({ }, offset);
+}
+
+inline void Box::Rect::expand(LayoutUnit width, LayoutUnit height)
+{
+    ASSERT(hasValidGeometry());
+    m_rect.expand(width, height);
+}
+
+inline Box::Rect Box::Rect::clone() const
+{
+    Rect rect;
+#if !ASSERT_DISABLED
+    rect.m_hasValidTop = m_hasValidTop;
+    rect.m_hasValidLeft = m_hasValidLeft;
+    rect.m_hasValidWidth = m_hasValidWidth;
+    rect.m_hasValidHeight  = m_hasValidHeight;
+#endif 
+    rect.m_rect = m_rect;
+    return rect;
+}
+
+inline Box::Rect::operator LayoutRect() const
+{
+    ASSERT(hasValidGeometry()); 
+    return m_rect;
+}
+
+inline void Box::setContentBoxHeight(LayoutUnit height)
+{ 
+#if !ASSERT_DISABLED
+    setHasValidContentHeight();
+#endif
+    m_contentHeight = height;
+}
+
+inline void Box::setContentBoxWidth(LayoutUnit width)
+{ 
+#if !ASSERT_DISABLED
+    setHasValidContentWidth();
+#endif
+    m_contentWidth = width;
+}
+
+inline LayoutUnit Box::contentBoxHeight() const
+{
+    ASSERT(m_hasValidContentHeight);
+    return m_contentHeight;
+}
+
+inline LayoutUnit Box::contentBoxWidth() const
+{
+    ASSERT(m_hasValidContentWidth);
+    return m_contentWidth;
+}
+
+inline void Box::setHorizontalMargin(HorizontalEdges margin)
+{
+#if !ASSERT_DISABLED
+    setHasValidHorizontalMargin();
+#endif
+    m_margin.horizontal = margin;
+}
+
+inline void Box::setVerticalMargin(VerticalEdges margin)
+{
+#if !ASSERT_DISABLED
+    setHasValidVerticalMargin();
+#endif
+    m_margin.vertical = margin;
+}
+
+inline void Box::setBorder(Edges border)
+{
+#if !ASSERT_DISABLED
+    setHasValidBorder();
+#endif
+    m_border = border;
+}
+
+inline void Box::setPadding(Edges padding)
+{
+#if !ASSERT_DISABLED
+    setHasValidPadding();
+#endif
+    m_padding = padding;
+}
+
+inline LayoutUnit Box::marginTop() const
+{
+    ASSERT(m_hasValidVerticalMargin);
+    return m_margin.vertical.top;
+}
+
+inline LayoutUnit Box::marginLeft() const
+{
+    ASSERT(m_hasValidHorizontalMargin);
+    return m_margin.horizontal.left;
+}
+
+inline LayoutUnit Box::marginBottom() const
+{
+    ASSERT(m_hasValidVerticalMargin);
+    return m_margin.vertical.bottom;
+}
+
+inline LayoutUnit Box::marginRight() const
+{
+    ASSERT(m_hasValidHorizontalMargin);
+    return m_margin.horizontal.right;
+}
+
+inline LayoutUnit Box::paddingTop() const
+{
+    ASSERT(m_hasValidPadding);
+    return m_padding.vertical.top;
+}
+
+inline LayoutUnit Box::paddingLeft() const
+{
+    ASSERT(m_hasValidPadding);
+    return m_padding.horizontal.left;
+}
+
+inline LayoutUnit Box::paddingBottom() const
+{
+    ASSERT(m_hasValidPadding);
+    return m_padding.vertical.bottom;
+}
+
+inline LayoutUnit Box::paddingRight() const
+{
+    ASSERT(m_hasValidPadding);
+    return m_padding.horizontal.right;
+}
+
+inline LayoutUnit Box::borderTop() const
+{
+    ASSERT(m_hasValidBorder);
+    return m_border.vertical.top;
+}
+
+inline LayoutUnit Box::borderLeft() const
+{
+    ASSERT(m_hasValidBorder);
+    return m_border.horizontal.left;
+}
+
+inline LayoutUnit Box::borderBottom() const
+{
+    ASSERT(m_hasValidBorder);
+    return m_border.vertical.bottom;
+}
+
+inline LayoutUnit Box::borderRight() const
+{
+    ASSERT(m_hasValidBorder);
+    return m_border.horizontal.right;
+}
+
 }
 }
 #endif