Remove ENABLE(SATURATED_LAYOUT_ARITHMETIC) guards
[WebKit-https.git] / Source / WebCore / rendering / LayoutState.cpp
1 /*
2  * Copyright (C) 2007, 2013 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #include "config.h"
27 #include "LayoutState.h"
28
29 #include "RenderFlowThread.h"
30 #include "RenderInline.h"
31 #include "RenderLayer.h"
32 #include "RenderMultiColumnFlowThread.h"
33 #include "RenderView.h"
34
35 namespace WebCore {
36
37 LayoutState::LayoutState(std::unique_ptr<LayoutState> next, RenderBox* renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged)
38     : m_next(WTF::move(next))
39 #ifndef NDEBUG
40     , m_renderer(renderer)
41 #endif
42 {
43     ASSERT(m_next);
44
45     bool fixed = renderer->isOutOfFlowPositioned() && renderer->style().position() == FixedPosition;
46     if (fixed) {
47         // FIXME: This doesn't work correctly with transforms.
48         FloatPoint fixedOffset = renderer->view().localToAbsolute(FloatPoint(), IsFixed);
49         m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()) + offset;
50     } else
51         m_paintOffset = m_next->m_paintOffset + offset;
52
53     if (renderer->isOutOfFlowPositioned() && !fixed) {
54         if (RenderElement* container = renderer->container()) {
55             if (container->isInFlowPositioned() && is<RenderInline>(*container))
56                 m_paintOffset += downcast<RenderInline>(*container).offsetForInFlowPositionedInline(renderer);
57         }
58     }
59
60     m_layoutOffset = m_paintOffset;
61
62     if (renderer->isInFlowPositioned() && renderer->hasLayer())
63         m_paintOffset += renderer->layer()->offsetForInFlowPosition();
64
65     m_clipped = !fixed && m_next->m_clipped;
66     if (m_clipped)
67         m_clipRect = m_next->m_clipRect;
68
69     if (renderer->hasOverflowClip()) {
70         LayoutRect clipRect(toLayoutPoint(m_paintOffset) + renderer->view().layoutDelta(), renderer->cachedSizeForOverflowClip());
71         if (m_clipped)
72             m_clipRect.intersect(clipRect);
73         else {
74             m_clipRect = clipRect;
75             m_clipped = true;
76         }
77
78         m_paintOffset -= renderer->scrolledContentOffset();
79     }
80
81     // If we establish a new page height, then cache the offset to the top of the first page.
82     // We can compare this later on to figure out what part of the page we're actually on,
83     if (pageLogicalHeight || renderer->isRenderFlowThread()) {
84         m_pageLogicalHeight = pageLogicalHeight;
85         bool isFlipped = renderer->style().isFlippedBlocksWritingMode();
86         m_pageOffset = LayoutSize(m_layoutOffset.width() + (!isFlipped ? renderer->borderLeft() + renderer->paddingLeft() : renderer->borderRight() + renderer->paddingRight()),
87                                m_layoutOffset.height() + (!isFlipped ? renderer->borderTop() + renderer->paddingTop() : renderer->borderBottom() + renderer->paddingBottom()));
88         m_pageLogicalHeightChanged = pageLogicalHeightChanged;
89         m_isPaginated = true;
90     } else {
91         // If we don't establish a new page height, then propagate the old page height and offset down.
92         m_pageLogicalHeight = m_next->m_pageLogicalHeight;
93         m_pageLogicalHeightChanged = m_next->m_pageLogicalHeightChanged;
94         m_pageOffset = m_next->m_pageOffset;
95         
96         // Disable pagination for objects we don't support. For now this includes overflow:scroll/auto, inline blocks and
97         // writing mode roots.
98         if (renderer->isUnsplittableForPagination()) {
99             m_pageLogicalHeight = 0;
100             m_isPaginated = false;
101         } else
102             m_isPaginated = m_pageLogicalHeight || renderer->flowThreadContainingBlock();
103     }
104     
105     // Propagate line grid information.
106     propagateLineGridInfo(renderer);
107
108     m_layoutDelta = m_next->m_layoutDelta;
109 #if !ASSERT_DISABLED
110     m_layoutDeltaXSaturated = m_next->m_layoutDeltaXSaturated;
111     m_layoutDeltaYSaturated = m_next->m_layoutDeltaYSaturated;
112 #endif
113
114     if (lineGrid() && (lineGrid()->style().writingMode() == renderer->style().writingMode()) && is<RenderMultiColumnFlowThread>(*renderer))
115         downcast<RenderMultiColumnFlowThread>(*renderer).computeLineGridPaginationOrigin(*this);
116
117     // If we have a new grid to track, then add it to our set.
118     if (renderer->style().lineGrid() != RenderStyle::initialLineGrid() && is<RenderBlockFlow>(*renderer))
119         establishLineGrid(downcast<RenderBlockFlow>(renderer));
120
121     // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
122 }
123
124 LayoutState::LayoutState(RenderObject& root)
125     : m_clipped(false)
126     , m_isPaginated(false)
127     , m_pageLogicalHeightChanged(false)
128 #if !ASSERT_DISABLED
129     , m_layoutDeltaXSaturated(false)
130     , m_layoutDeltaYSaturated(false)
131 #endif    
132 #ifndef NDEBUG
133     , m_renderer(&root)
134 #endif
135 {
136     if (RenderElement* container = root.container()) {
137         FloatPoint absContentPoint = container->localToAbsolute(FloatPoint(), UseTransforms);
138         m_paintOffset = LayoutSize(absContentPoint.x(), absContentPoint.y());
139
140         if (container->hasOverflowClip()) {
141             m_clipped = true;
142             auto& containerBox = downcast<RenderBox>(*container);
143             m_clipRect = LayoutRect(toLayoutPoint(m_paintOffset), containerBox.cachedSizeForOverflowClip());
144             m_paintOffset -= containerBox.scrolledContentOffset();
145         }
146     }
147 }
148
149 void LayoutState::clearPaginationInformation()
150 {
151     m_pageLogicalHeight = m_next->m_pageLogicalHeight;
152     m_pageOffset = m_next->m_pageOffset;
153 }
154
155 LayoutUnit LayoutState::pageLogicalOffset(RenderBox* child, LayoutUnit childLogicalOffset) const
156 {
157     if (child->isHorizontalWritingMode())
158         return m_layoutOffset.height() + childLogicalOffset - m_pageOffset.height();
159     return m_layoutOffset.width() + childLogicalOffset - m_pageOffset.width();
160 }
161
162 void LayoutState::propagateLineGridInfo(RenderBox* renderer)
163 {
164     // Disable line grids for objects we don't support. For now this includes overflow:scroll/auto, inline blocks and
165     // writing mode roots.
166     if (!m_next || renderer->isUnsplittableForPagination())
167         return;
168
169     m_lineGrid = m_next->m_lineGrid;
170     m_lineGridOffset = m_next->m_lineGridOffset;
171     m_lineGridPaginationOrigin = m_next->m_lineGridPaginationOrigin;
172 }
173
174 void LayoutState::establishLineGrid(RenderBlockFlow* block)
175 {
176     // First check to see if this grid has been established already.
177     if (m_lineGrid) {
178         if (m_lineGrid->style().lineGrid() == block->style().lineGrid())
179             return;
180         RenderBlockFlow* currentGrid = m_lineGrid;
181         for (LayoutState* currentState = m_next.get(); currentState; currentState = currentState->m_next.get()) {
182             if (currentState->m_lineGrid == currentGrid)
183                 continue;
184             currentGrid = currentState->m_lineGrid;
185             if (!currentGrid)
186                 break;
187             if (currentGrid->style().lineGrid() == block->style().lineGrid()) {
188                 m_lineGrid = currentGrid;
189                 m_lineGridOffset = currentState->m_lineGridOffset;
190                 return;
191             }
192         }
193     }
194     
195     // We didn't find an already-established grid with this identifier. Our render object establishes the grid.
196     m_lineGrid = block;
197     m_lineGridOffset = m_layoutOffset; 
198 }
199
200 } // namespace WebCore