[LFC] Move geometry data structures to a dedicated file
[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 "LayoutUnits.h"
31 #include "RenderStyleConstants.h"
32 #include <wtf/IsoMalloc.h>
33
34 namespace WebCore {
35
36 class RenderStyle;
37
38 namespace Layout {
39 class BlockFormattingContext;
40 class FormattingContext;
41 class LayoutContext;
42 }
43
44 namespace Display {
45
46 class Box {
47     WTF_MAKE_ISO_ALLOCATED(Box);
48 public:
49     friend class Layout::BlockFormattingContext;
50     friend class Layout::FormattingContext;
51     friend class Layout::LayoutContext;
52
53     class Rect {
54     public:
55         Rect() = default;
56         
57         LayoutUnit top() const;
58         LayoutUnit left() const;
59         LayoutPoint topLeft() const;
60
61         LayoutUnit bottom() const;
62         LayoutUnit right() const;        
63         LayoutPoint bottomRight() const;
64
65         LayoutUnit width() const;
66         LayoutUnit height() const;
67         LayoutSize size() const;
68
69         void setTop(LayoutUnit);
70         void setLeft(LayoutUnit);
71         void setTopLeft(const LayoutPoint&);
72         void setWidth(LayoutUnit);
73         void setHeight(LayoutUnit);
74         void setSize(const LayoutSize&);
75
76         void shiftLeftTo(LayoutUnit);
77         void shiftRightTo(LayoutUnit);
78         void shiftTopTo(LayoutUnit);
79         void shiftBottomTo(LayoutUnit);
80
81         void moveHorizontally(LayoutUnit);
82         void moveVertically(LayoutUnit);
83
84         void expand(LayoutUnit, LayoutUnit);
85
86         Rect clone() const;
87         operator LayoutRect() const;
88
89     private:
90 #if !ASSERT_DISABLED
91         void invalidateTop() { m_hasValidTop = false; }
92         void invalidateLeft() { m_hasValidLeft = false; }
93         void invalidateWidth() { m_hasValidWidth = false; }
94         void invalidateHeight() { m_hasValidHeight = false; }
95         void invalidatePosition();
96
97         bool hasValidPosition() const { return m_hasValidTop && m_hasValidLeft; }
98         bool hasValidSize() const { return m_hasValidWidth && m_hasValidHeight; }
99         bool hasValidGeometry() const { return hasValidPosition() && hasValidSize(); }
100     
101         void setHasValidPosition();
102         void setHasValidSize();
103
104         bool m_hasValidTop { false };
105         bool m_hasValidLeft { false };
106         bool m_hasValidWidth { false };
107         bool m_hasValidHeight { false };
108 #endif
109         LayoutRect m_rect;
110     };
111
112     ~Box();
113
114     LayoutUnit top() const { return m_topLeft.y(); }
115     LayoutUnit left() const { return m_topLeft.x(); }
116     LayoutUnit bottom() const { return top() + height(); }
117     LayoutUnit right() const { return left() + width(); }
118
119     LayoutPoint topLeft() const { return m_topLeft; }
120     LayoutPoint bottomRight() const { return { right(), bottom() }; }
121
122     LayoutSize size() const { return { width(), height() }; }
123     LayoutUnit width() const { return borderLeft() + paddingLeft() + contentBoxWidth() + paddingRight() + borderRight(); }
124     LayoutUnit height() const { return borderTop() + paddingTop() + contentBoxHeight() + paddingBottom() + borderBottom(); }
125     LayoutRect rect() const { return { left(), top(), width(), height() }; }
126
127     LayoutUnit marginTop() const;
128     LayoutUnit marginLeft() const;
129     LayoutUnit marginBottom() const;
130     LayoutUnit marginRight() const;
131
132     LayoutUnit nonCollapsedMarginTop() const;
133     LayoutUnit nonCollapsedMarginBottom() const;
134
135     LayoutUnit borderTop() const;
136     LayoutUnit borderLeft() const;
137     LayoutUnit borderBottom() const;
138     LayoutUnit borderRight() const;
139
140     LayoutUnit paddingTop() const;
141     LayoutUnit paddingLeft() const;
142     LayoutUnit paddingBottom() const;
143     LayoutUnit paddingRight() const;
144
145     LayoutUnit contentBoxTop() const { return borderTop() + paddingTop(); }
146     LayoutUnit contentBoxLeft() const { return borderLeft() + paddingLeft(); }
147     LayoutUnit contentBoxBottom() const { return contentBoxTop() + contentBoxHeight(); }
148     LayoutUnit contentBoxRight() const { return contentBoxLeft() + contentBoxWidth(); }
149     LayoutUnit contentBoxHeight() const;
150     LayoutUnit contentBoxWidth() const;
151
152     Rect marginBox() const;
153     Rect nonCollapsedMarginBox() const;
154
155     Rect borderBox() const;
156     Rect paddingBox() const;
157     Rect contentBox() const;
158
159 private:
160     Box(const RenderStyle&);
161
162     struct Style {
163         Style(const RenderStyle&);
164
165         BoxSizing boxSizing { BoxSizing::ContentBox };
166     };
167
168     void setTopLeft(const LayoutPoint& topLeft) { m_topLeft = topLeft; }
169     void setTop(LayoutUnit top) { m_topLeft.setY(top); }
170     void setLeft(LayoutUnit left) { m_topLeft.setX(left); }
171     void moveHorizontally(LayoutUnit offset) { m_topLeft.move(offset, { }); }
172     void moveVertically(LayoutUnit offset) { m_topLeft.move({ }, offset); }
173
174     void setContentBoxHeight(LayoutUnit);
175     void setContentBoxWidth(LayoutUnit);
176
177     void setHorizontalMargin(Layout::HorizontalEdges);
178     void setVerticalMargin(Layout::VerticalEdges);
179     void setVerticalNonCollapsedMargin(Layout::VerticalEdges);
180
181     void setBorder(Layout::Edges);
182     void setPadding(Layout::Edges);
183
184 #if !ASSERT_DISABLED
185     void invalidateMargin();
186     void invalidateBorder() { m_hasValidBorder = false; }
187     void invalidatePadding() { m_hasValidPadding = false; }
188
189     void setHasValidVerticalMargin() { m_hasValidVerticalMargin = true; }
190     void setHasValidVerticalNonCollapsedMargin() { m_hasValidVerticalNonCollapsedMargin = true; }
191     void setHasValidHorizontalMargin() { m_hasValidHorizontalMargin = true; }
192
193     void setHasValidBorder() { m_hasValidBorder = true; }
194     void setHasValidPadding() { m_hasValidPadding = true; }
195
196     void setHasValidContentHeight() { m_hasValidContentHeight = true; }
197     void setHasValidContentWidth() { m_hasValidContentWidth = true; }
198 #endif
199
200     const Style m_style;
201
202     LayoutPoint m_topLeft;
203     LayoutUnit m_contentWidth;
204     LayoutUnit m_contentHeight;
205
206     Layout::Edges m_margin;
207     Layout::VerticalEdges m_verticalNonCollapsedMargin;
208
209     Layout::Edges m_border;
210     Layout::Edges m_padding;
211
212 #if !ASSERT_DISABLED
213     bool m_hasValidHorizontalMargin { false };
214     bool m_hasValidVerticalMargin { false };
215     bool m_hasValidVerticalNonCollapsedMargin { false };
216     bool m_hasValidBorder { false };
217     bool m_hasValidPadding { false };
218     bool m_hasValidContentHeight { false };
219     bool m_hasValidContentWidth { false };
220 #endif
221 };
222
223 #if !ASSERT_DISABLED
224 inline void Box::Rect::invalidatePosition()
225 {
226     invalidateTop();
227     invalidateLeft();
228 }
229
230 inline void Box::Rect::setHasValidPosition()
231 {
232     m_hasValidTop = true;
233     m_hasValidLeft = true;
234 }
235
236 inline void Box::Rect::setHasValidSize()
237 {
238     m_hasValidWidth = true;
239     m_hasValidHeight = true;
240 }
241
242 inline void Box::invalidateMargin()
243 {
244     m_hasValidHorizontalMargin = false;
245     m_hasValidVerticalMargin = false;
246 }
247 #endif
248
249 inline LayoutUnit Box::Rect::top() const
250 {
251     ASSERT(m_hasValidTop);
252     return m_rect.y();
253 }
254
255 inline LayoutUnit Box::Rect::left() const
256 {
257     ASSERT(m_hasValidLeft);
258     return m_rect.x();
259 }
260
261 inline LayoutUnit Box::Rect::bottom() const
262 {
263     ASSERT(m_hasValidTop && m_hasValidHeight);
264     return m_rect.maxY();
265 }
266
267 inline LayoutUnit Box::Rect::right() const
268 {
269     ASSERT(m_hasValidLeft && m_hasValidWidth);
270     return m_rect.maxX();
271 }
272
273 inline LayoutPoint Box::Rect::topLeft() const
274 {
275     ASSERT(hasValidPosition());
276     return m_rect.minXMinYCorner();
277 }
278
279 inline LayoutPoint Box::Rect::bottomRight() const
280 {
281     ASSERT(hasValidGeometry());
282     return m_rect.maxXMaxYCorner();
283 }
284
285 inline LayoutSize Box::Rect::size() const
286 {
287     ASSERT(hasValidSize());
288     return m_rect.size();
289 }
290
291 inline LayoutUnit Box::Rect::width() const
292 {
293     ASSERT(m_hasValidWidth);
294     return m_rect.width();
295 }
296
297 inline LayoutUnit Box::Rect::height() const
298 {
299     ASSERT(m_hasValidHeight);
300     return m_rect.height();
301 }
302
303 inline void Box::Rect::setTopLeft(const LayoutPoint& topLeft)
304 {
305 #if !ASSERT_DISABLED
306     setHasValidPosition();
307 #endif
308     m_rect.setLocation(topLeft);
309 }
310
311 inline void Box::Rect::setTop(LayoutUnit top)
312 {
313 #if !ASSERT_DISABLED
314     m_hasValidTop = true;
315 #endif
316     m_rect.setY(top);
317 }
318
319 inline void Box::Rect::setLeft(LayoutUnit left)
320 {
321 #if !ASSERT_DISABLED
322     m_hasValidLeft = true;
323 #endif
324     m_rect.setX(left);
325 }
326
327 inline void Box::Rect::setWidth(LayoutUnit width)
328 {
329 #if !ASSERT_DISABLED
330     m_hasValidWidth = true;
331 #endif
332     m_rect.setWidth(width);
333 }
334
335 inline void Box::Rect::setHeight(LayoutUnit height)
336 {
337 #if !ASSERT_DISABLED
338     m_hasValidHeight = true;
339 #endif
340     m_rect.setHeight(height);
341 }
342
343 inline void Box::Rect::setSize(const LayoutSize& size)
344 {
345 #if !ASSERT_DISABLED
346     setHasValidSize();
347 #endif
348     m_rect.setSize(size);
349 }
350
351 inline void Box::Rect::shiftLeftTo(LayoutUnit left)
352 {
353     ASSERT(m_hasValidLeft);
354     m_rect.shiftXEdgeTo(left);
355 }
356
357 inline void Box::Rect::shiftRightTo(LayoutUnit right)
358 {
359     ASSERT(m_hasValidLeft && m_hasValidWidth);
360     m_rect.shiftMaxXEdgeTo(right);
361 }
362
363 inline void Box::Rect::shiftTopTo(LayoutUnit top)
364 {
365     ASSERT(m_hasValidTop);
366     m_rect.shiftYEdgeTo(top);
367 }
368
369 inline void Box::Rect::shiftBottomTo(LayoutUnit bottom)
370 {
371     ASSERT(m_hasValidTop && m_hasValidHeight);
372     m_rect.shiftMaxYEdgeTo(bottom);
373 }
374
375 inline void Box::Rect::moveHorizontally(LayoutUnit offset)
376 {
377     ASSERT(m_hasValidLeft);
378     m_rect.move(offset, { });
379 }
380
381 inline void Box::Rect::moveVertically(LayoutUnit offset)
382 {
383     ASSERT(m_hasValidTop);
384     m_rect.move({ }, offset);
385 }
386
387 inline void Box::Rect::expand(LayoutUnit width, LayoutUnit height)
388 {
389     ASSERT(hasValidGeometry());
390     m_rect.expand(width, height);
391 }
392
393 inline Box::Rect Box::Rect::clone() const
394 {
395     Rect rect;
396 #if !ASSERT_DISABLED
397     rect.m_hasValidTop = m_hasValidTop;
398     rect.m_hasValidLeft = m_hasValidLeft;
399     rect.m_hasValidWidth = m_hasValidWidth;
400     rect.m_hasValidHeight  = m_hasValidHeight;
401 #endif 
402     rect.m_rect = m_rect;
403     return rect;
404 }
405
406 inline Box::Rect::operator LayoutRect() const
407 {
408     ASSERT(hasValidGeometry()); 
409     return m_rect;
410 }
411
412 inline void Box::setContentBoxHeight(LayoutUnit height)
413
414 #if !ASSERT_DISABLED
415     setHasValidContentHeight();
416 #endif
417     m_contentHeight = height;
418 }
419
420 inline void Box::setContentBoxWidth(LayoutUnit width)
421
422 #if !ASSERT_DISABLED
423     setHasValidContentWidth();
424 #endif
425     m_contentWidth = width;
426 }
427
428 inline LayoutUnit Box::contentBoxHeight() const
429 {
430     ASSERT(m_hasValidContentHeight);
431     return m_contentHeight;
432 }
433
434 inline LayoutUnit Box::contentBoxWidth() const
435 {
436     ASSERT(m_hasValidContentWidth);
437     return m_contentWidth;
438 }
439
440 inline void Box::setHorizontalMargin(Layout::HorizontalEdges margin)
441 {
442 #if !ASSERT_DISABLED
443     setHasValidHorizontalMargin();
444 #endif
445     m_margin.horizontal = margin;
446 }
447
448 inline void Box::setVerticalMargin(Layout::VerticalEdges margin)
449 {
450 #if !ASSERT_DISABLED
451     setHasValidVerticalMargin();
452 #endif
453     m_margin.vertical = margin;
454 }
455
456 inline void Box::setVerticalNonCollapsedMargin(Layout::VerticalEdges margin)
457 {
458 #if !ASSERT_DISABLED
459     setHasValidVerticalNonCollapsedMargin();
460 #endif
461     m_verticalNonCollapsedMargin = margin;
462 }
463
464 inline void Box::setBorder(Layout::Edges border)
465 {
466 #if !ASSERT_DISABLED
467     setHasValidBorder();
468 #endif
469     m_border = border;
470 }
471
472 inline void Box::setPadding(Layout::Edges padding)
473 {
474 #if !ASSERT_DISABLED
475     setHasValidPadding();
476 #endif
477     m_padding = padding;
478 }
479
480 inline LayoutUnit Box::marginTop() const
481 {
482     ASSERT(m_hasValidVerticalMargin);
483     return m_margin.vertical.top;
484 }
485
486 inline LayoutUnit Box::marginLeft() const
487 {
488     ASSERT(m_hasValidHorizontalMargin);
489     return m_margin.horizontal.left;
490 }
491
492 inline LayoutUnit Box::marginBottom() const
493 {
494     ASSERT(m_hasValidVerticalMargin);
495     return m_margin.vertical.bottom;
496 }
497
498 inline LayoutUnit Box::marginRight() const
499 {
500     ASSERT(m_hasValidHorizontalMargin);
501     return m_margin.horizontal.right;
502 }
503
504 inline LayoutUnit Box::nonCollapsedMarginTop() const
505 {
506     ASSERT(m_hasValidVerticalNonCollapsedMargin);
507     return m_verticalNonCollapsedMargin.top;
508 }
509
510 inline LayoutUnit Box::nonCollapsedMarginBottom() const
511 {
512     ASSERT(m_hasValidVerticalNonCollapsedMargin);
513     return m_verticalNonCollapsedMargin.bottom;
514 }
515
516 inline LayoutUnit Box::paddingTop() const
517 {
518     ASSERT(m_hasValidPadding);
519     return m_padding.vertical.top;
520 }
521
522 inline LayoutUnit Box::paddingLeft() const
523 {
524     ASSERT(m_hasValidPadding);
525     return m_padding.horizontal.left;
526 }
527
528 inline LayoutUnit Box::paddingBottom() const
529 {
530     ASSERT(m_hasValidPadding);
531     return m_padding.vertical.bottom;
532 }
533
534 inline LayoutUnit Box::paddingRight() const
535 {
536     ASSERT(m_hasValidPadding);
537     return m_padding.horizontal.right;
538 }
539
540 inline LayoutUnit Box::borderTop() const
541 {
542     ASSERT(m_hasValidBorder);
543     return m_border.vertical.top;
544 }
545
546 inline LayoutUnit Box::borderLeft() const
547 {
548     ASSERT(m_hasValidBorder);
549     return m_border.horizontal.left;
550 }
551
552 inline LayoutUnit Box::borderBottom() const
553 {
554     ASSERT(m_hasValidBorder);
555     return m_border.vertical.bottom;
556 }
557
558 inline LayoutUnit Box::borderRight() const
559 {
560     ASSERT(m_hasValidBorder);
561     return m_border.horizontal.right;
562 }
563
564 }
565 }
566 #endif