[LFC] Miscellaneous fixes to ensure no assertion in LayoutContext::layout
[WebKit-https.git] / Source / WebCore / layout / displaytree / DisplayBox.h
1 /*
2  * Copyright (C) 2018 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
29
30 #include "LayoutPoint.h"
31 #include "LayoutRect.h"
32 #include "LayoutUnit.h"
33 #include "RenderStyleConstants.h"
34 #include <wtf/IsoMalloc.h>
35
36 namespace WebCore {
37
38 class RenderStyle;
39
40 namespace Layout {
41 class BlockFormattingContext;
42 class FormattingContext;
43 class LayoutContext;
44 }
45
46 namespace Display {
47
48 class Box {
49     WTF_MAKE_ISO_ALLOCATED(Box);
50 public:
51     friend class Layout::BlockFormattingContext;
52     friend class Layout::FormattingContext;
53     friend class Layout::LayoutContext;
54
55     class Rect {
56     public:
57         Rect() = default;
58         
59         LayoutUnit top() const;
60         LayoutUnit left() const;
61         LayoutPoint topLeft() const;
62
63         LayoutUnit bottom() const;
64         LayoutUnit right() const;        
65         LayoutPoint bottomRight() const;
66
67         LayoutUnit width() const;
68         LayoutUnit height() const;
69         LayoutSize size() const;
70
71         void setTop(LayoutUnit);
72         void setLeft(LayoutUnit);
73         void setTopLeft(const LayoutPoint&);
74         void setWidth(LayoutUnit);
75         void setHeight(LayoutUnit);
76         void setSize(const LayoutSize&);
77
78         void shiftLeftTo(LayoutUnit);
79         void shiftRightTo(LayoutUnit);
80         void shiftTopTo(LayoutUnit);
81         void shiftBottomTo(LayoutUnit);
82
83         void expand(LayoutUnit, LayoutUnit);
84
85         Rect clone() const;
86         operator LayoutRect() const;
87
88     private:
89 #if !ASSERT_DISABLED
90         void invalidateTop() { m_hasValidTop = false; }
91         void invalidateLeft() { m_hasValidLeft = false; }
92         void invalidateWidth() { m_hasValidWidth = false; }
93         void invalidateHeight() { m_hasValidHeight = false; }
94         void invalidatePosition();
95
96         bool hasValidPosition() const { return m_hasValidTop && m_hasValidLeft; }
97         bool hasValidSize() const { return m_hasValidWidth && m_hasValidHeight; }
98         bool hasValidGeometry() const { return hasValidPosition() && hasValidSize(); }
99     
100         void setHasValidPosition();
101         void setHasValidSize();
102
103         bool m_hasValidTop { false };
104         bool m_hasValidLeft { false };
105         bool m_hasValidWidth { false };
106         bool m_hasValidHeight { false };
107 #endif
108         LayoutRect m_rect;
109     };
110
111     ~Box();
112
113     Rect rect() const { return m_rect; }
114
115     LayoutUnit top() const { return m_rect.top(); }
116     LayoutUnit left() const { return m_rect.left(); }
117     LayoutUnit bottom() const { return m_rect.bottom(); }
118     LayoutUnit right() const { return m_rect.right(); }
119
120     LayoutPoint topLeft() const { return m_rect.topLeft(); }
121     LayoutPoint bottomRight() const { return m_rect.bottomRight(); }
122
123     LayoutSize size() const { return m_rect.size(); }
124     LayoutUnit width() const { return m_rect.width(); }
125     LayoutUnit height() const { return m_rect.height(); }
126
127     LayoutUnit marginTop() const;
128     LayoutUnit marginLeft() const;
129     LayoutUnit marginBottom() const;
130     LayoutUnit marginRight() const;
131
132     LayoutUnit borderTop() const;
133     LayoutUnit borderLeft() const;
134     LayoutUnit borderBottom() const;
135     LayoutUnit borderRight() const;
136
137     LayoutUnit paddingTop() const;
138     LayoutUnit paddingLeft() const;
139     LayoutUnit paddingBottom() const;
140     LayoutUnit paddingRight() const;
141
142     Rect marginBox() const;
143     Rect borderBox() const;
144     Rect paddingBox() const;
145     Rect contentBox() const;
146
147 private:
148     Box(const RenderStyle&);
149
150     struct Style {
151         Style(const RenderStyle&);
152
153         BoxSizing boxSizing { BoxSizing::ContentBox };
154     };
155
156     void setTopLeft(const LayoutPoint& topLeft) { m_rect.setTopLeft(topLeft); }
157     void setTop(LayoutUnit top) { m_rect.setTop(top); }
158     void setLeft(LayoutUnit left) { m_rect.setLeft(left); }
159     void setWidth(LayoutUnit width) { m_rect.setWidth(width); }
160     void setHeight(LayoutUnit height) { m_rect.setHeight(height); }
161     void setSize(const LayoutSize& size) { m_rect.setSize(size); }
162
163     struct Edges {
164         Edges() = default;
165         Edges(LayoutUnit top, LayoutUnit left, LayoutUnit bottom, LayoutUnit right)
166             : top(top)
167             , left(left)
168             , bottom(bottom)
169             , right(right)
170             { }
171
172         LayoutUnit top;
173         LayoutUnit left;
174         LayoutUnit bottom;
175         LayoutUnit right;
176     };
177     void setMargin(Edges);
178     void setBorder(Edges);
179     void setPadding(Edges);
180
181 #if !ASSERT_DISABLED
182     void invalidateMargin() { m_hasValidMargin = false; }
183     void invalidateBorder() { m_hasValidBorder = false; }
184     void invalidatePadding() { m_hasValidPadding = false; }
185
186     void setHasValidMargin() { m_hasValidMargin = true; }
187     void setHasValidBorder() { m_hasValidBorder = true; }
188     void setHasValidPadding() { m_hasValidPadding = true; }
189 #endif
190
191     const Style m_style;
192
193     Rect m_rect;
194
195     Edges m_margin;
196     Edges m_border;
197     Edges m_padding;
198
199 #if !ASSERT_DISABLED
200     bool m_hasValidMargin { false };
201     bool m_hasValidBorder { false };
202     bool m_hasValidPadding { false };
203 #endif
204 };
205
206 #if !ASSERT_DISABLED
207 inline void Box::Rect::invalidatePosition()
208 {
209     invalidateTop();
210     invalidateLeft();
211 }
212
213 inline void Box::Rect::setHasValidPosition()
214 {
215     m_hasValidTop = true;
216     m_hasValidLeft = true;
217 }
218
219 inline void Box::Rect::setHasValidSize()
220 {
221     m_hasValidWidth = true;
222     m_hasValidHeight = true;
223 }
224 #endif
225
226 inline LayoutUnit Box::Rect::top() const
227 {
228     ASSERT(m_hasValidTop);
229     return m_rect.y();
230 }
231
232 inline LayoutUnit Box::Rect::left() const
233 {
234     ASSERT(m_hasValidLeft);
235     return m_rect.x();
236 }
237
238 inline LayoutUnit Box::Rect::bottom() const
239 {
240     ASSERT(m_hasValidTop && m_hasValidHeight);
241     return m_rect.maxY();
242 }
243
244 inline LayoutUnit Box::Rect::right() const
245 {
246     ASSERT(m_hasValidLeft && m_hasValidWidth);
247     return m_rect.maxX();
248 }
249
250 inline LayoutPoint Box::Rect::topLeft() const
251 {
252     ASSERT(hasValidPosition());
253     return m_rect.minXMinYCorner();
254 }
255
256 inline LayoutPoint Box::Rect::bottomRight() const
257 {
258     ASSERT(hasValidGeometry());
259     return m_rect.maxXMaxYCorner();
260 }
261
262 inline LayoutSize Box::Rect::size() const
263 {
264     ASSERT(hasValidSize());
265     return m_rect.size();
266 }
267
268 inline LayoutUnit Box::Rect::width() const
269 {
270     ASSERT(m_hasValidWidth);
271     return m_rect.width();
272 }
273
274 inline LayoutUnit Box::Rect::height() const
275 {
276     ASSERT(m_hasValidHeight);
277     return m_rect.height();
278 }
279
280 inline void Box::Rect::setTopLeft(const LayoutPoint& topLeft)
281 {
282 #if !ASSERT_DISABLED
283     setHasValidPosition();
284 #endif
285     m_rect.setLocation(topLeft);
286 }
287
288 inline void Box::Rect::setTop(LayoutUnit top)
289 {
290 #if !ASSERT_DISABLED
291     m_hasValidTop = true;
292 #endif
293     m_rect.setY(top);
294 }
295
296 inline void Box::Rect::setLeft(LayoutUnit left)
297 {
298 #if !ASSERT_DISABLED
299     m_hasValidLeft = true;
300 #endif
301     m_rect.setX(left);
302 }
303
304 inline void Box::Rect::setWidth(LayoutUnit width)
305 {
306 #if !ASSERT_DISABLED
307     m_hasValidWidth = true;
308 #endif
309     ASSERT(m_hasValidLeft);
310     m_rect.setWidth(width);
311 }
312
313 inline void Box::Rect::setHeight(LayoutUnit height)
314 {
315 #if !ASSERT_DISABLED
316     m_hasValidHeight = true;
317 #endif
318     ASSERT(m_hasValidTop);
319     m_rect.setHeight(height);
320 }
321
322 inline void Box::Rect::setSize(const LayoutSize& size)
323 {
324 #if !ASSERT_DISABLED
325     setHasValidSize();
326 #endif
327     m_rect.setSize(size);
328 }
329
330 inline void Box::Rect::shiftLeftTo(LayoutUnit left)
331 {
332     ASSERT(m_hasValidLeft);
333     m_rect.shiftXEdgeTo(left);
334 }
335
336 inline void Box::Rect::shiftRightTo(LayoutUnit right)
337 {
338     ASSERT(m_hasValidLeft && m_hasValidWidth);
339     m_rect.shiftMaxXEdgeTo(right);
340 }
341
342 inline void Box::Rect::shiftTopTo(LayoutUnit top)
343 {
344     ASSERT(m_hasValidTop);
345     m_rect.shiftYEdgeTo(top);
346 }
347
348 inline void Box::Rect::shiftBottomTo(LayoutUnit bottom)
349 {
350     ASSERT(m_hasValidTop && m_hasValidHeight);
351     m_rect.shiftMaxYEdgeTo(bottom);
352 }
353
354 inline void Box::Rect::expand(LayoutUnit width, LayoutUnit height)
355 {
356     ASSERT(hasValidGeometry());
357     m_rect.expand(width, height);
358 }
359
360 inline Box::Rect Box::Rect::clone() const
361 {
362     Rect rect;
363 #if !ASSERT_DISABLED
364     rect.m_hasValidTop = m_hasValidTop;
365     rect.m_hasValidLeft = m_hasValidLeft;
366     rect.m_hasValidWidth = m_hasValidWidth;
367     rect.m_hasValidHeight  = m_hasValidHeight;
368 #endif 
369     rect.m_rect = m_rect;
370     return rect;
371 }
372
373 inline Box::Rect::operator LayoutRect() const
374 {
375     ASSERT(hasValidGeometry()); 
376     return m_rect;
377 }
378
379 inline void Box::setMargin(Edges margin)
380 {
381 #if !ASSERT_DISABLED
382     setHasValidMargin();
383 #endif
384     m_margin = margin;
385 }
386
387 inline void Box::setBorder(Edges border)
388 {
389 #if !ASSERT_DISABLED
390     setHasValidBorder();
391 #endif
392     m_border = border;
393 }
394
395 inline void Box::setPadding(Edges padding)
396 {
397 #if !ASSERT_DISABLED
398     setHasValidPadding();
399 #endif
400     m_padding = padding;
401 }
402
403 inline LayoutUnit Box::marginTop() const
404 {
405     ASSERT(m_hasValidMargin);
406     return m_margin.top;
407 }
408
409 inline LayoutUnit Box::marginLeft() const
410 {
411     ASSERT(m_hasValidMargin);
412     return m_margin.left;
413 }
414
415 inline LayoutUnit Box::marginBottom() const
416 {
417     ASSERT(m_hasValidMargin);
418     return m_margin.bottom;
419 }
420
421 inline LayoutUnit Box::marginRight() const
422 {
423     ASSERT(m_hasValidMargin);
424     return m_margin.right;
425 }
426
427 inline LayoutUnit Box::paddingTop() const
428 {
429     ASSERT(m_hasValidPadding);
430     return m_padding.top;
431 }
432
433 inline LayoutUnit Box::paddingLeft() const
434 {
435     ASSERT(m_hasValidPadding);
436     return m_padding.left;
437 }
438
439 inline LayoutUnit Box::paddingBottom() const
440 {
441     ASSERT(m_hasValidPadding);
442     return m_padding.bottom;
443 }
444
445 inline LayoutUnit Box::paddingRight() const
446 {
447     ASSERT(m_hasValidPadding);
448     return m_padding.right;
449 }
450
451 inline LayoutUnit Box::borderTop() const
452 {
453     ASSERT(m_hasValidBorder);
454     return m_border.top;
455 }
456
457 inline LayoutUnit Box::borderLeft() const
458 {
459     ASSERT(m_hasValidBorder);
460     return m_border.left;
461 }
462
463 inline LayoutUnit Box::borderBottom() const
464 {
465     ASSERT(m_hasValidBorder);
466     return m_border.bottom;
467 }
468
469 inline LayoutUnit Box::borderRight() const
470 {
471     ASSERT(m_hasValidBorder);
472     return m_border.right;
473 }
474
475 }
476 }
477 #endif