eacd26f4f044ceb6a317667e0993332ce1251dae
[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 moveHorizontally(LayoutUnit);
84         void moveVertically(LayoutUnit);
85
86         void expand(LayoutUnit, LayoutUnit);
87
88         Rect clone() const;
89         operator LayoutRect() const;
90
91     private:
92 #if !ASSERT_DISABLED
93         void invalidateTop() { m_hasValidTop = false; }
94         void invalidateLeft() { m_hasValidLeft = false; }
95         void invalidateWidth() { m_hasValidWidth = false; }
96         void invalidateHeight() { m_hasValidHeight = false; }
97         void invalidatePosition();
98
99         bool hasValidPosition() const { return m_hasValidTop && m_hasValidLeft; }
100         bool hasValidSize() const { return m_hasValidWidth && m_hasValidHeight; }
101         bool hasValidGeometry() const { return hasValidPosition() && hasValidSize(); }
102     
103         void setHasValidPosition();
104         void setHasValidSize();
105
106         bool m_hasValidTop { false };
107         bool m_hasValidLeft { false };
108         bool m_hasValidWidth { false };
109         bool m_hasValidHeight { false };
110 #endif
111         LayoutRect m_rect;
112     };
113
114     ~Box();
115
116     Rect rect() const { return m_rect; }
117
118     LayoutUnit top() const { return m_rect.top(); }
119     LayoutUnit left() const { return m_rect.left(); }
120     LayoutUnit bottom() const { return m_rect.bottom(); }
121     LayoutUnit right() const { return m_rect.right(); }
122
123     LayoutPoint topLeft() const { return m_rect.topLeft(); }
124     LayoutPoint bottomRight() const { return m_rect.bottomRight(); }
125
126     LayoutSize size() const { return m_rect.size(); }
127     LayoutUnit width() const { return m_rect.width(); }
128     LayoutUnit height() const { return m_rect.height(); }
129
130     LayoutUnit marginTop() const;
131     LayoutUnit marginLeft() const;
132     LayoutUnit marginBottom() const;
133     LayoutUnit marginRight() 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     Rect marginBox() const;
146     Rect borderBox() const;
147     Rect paddingBox() const;
148     Rect contentBox() const;
149
150 private:
151     Box(const RenderStyle&);
152
153     struct Style {
154         Style(const RenderStyle&);
155
156         BoxSizing boxSizing { BoxSizing::ContentBox };
157     };
158
159     void setTopLeft(const LayoutPoint& topLeft) { m_rect.setTopLeft(topLeft); }
160     void setTop(LayoutUnit top) { m_rect.setTop(top); }
161     void setLeft(LayoutUnit left) { m_rect.setLeft(left); }
162     void moveHorizontally(LayoutUnit offset) { m_rect.moveHorizontally(offset); }
163     void moveVertically(LayoutUnit offset) { m_rect.moveVertically(offset); }
164     void setWidth(LayoutUnit width) { m_rect.setWidth(width); }
165     void setHeight(LayoutUnit height) { m_rect.setHeight(height); }
166     void setSize(const LayoutSize& size) { m_rect.setSize(size); }
167
168     struct HorizontalEdges {
169         LayoutUnit left;
170         LayoutUnit right;
171     };
172
173     struct VerticalEdges {
174         LayoutUnit top;
175         LayoutUnit bottom;
176     };
177
178     struct Edges {
179         HorizontalEdges horizontal;
180         VerticalEdges vertical;
181     };
182
183     void setHorizontalMargin(HorizontalEdges);
184     void setVerticalMargin(VerticalEdges);
185     void setBorder(Edges);
186     void setPadding(Edges);
187
188 #if !ASSERT_DISABLED
189     void invalidateMargin();
190     void invalidateBorder() { m_hasValidBorder = false; }
191     void invalidatePadding() { m_hasValidPadding = false; }
192
193     void setHasValidVerticalMargin() { m_hasValidVerticalMargin = true; }
194     void setHasValidHorizontalMargin() { m_hasValidHorizontalMargin = true; }
195
196     void setHasValidBorder() { m_hasValidBorder = true; }
197     void setHasValidPadding() { m_hasValidPadding = true; }
198 #endif
199
200     const Style m_style;
201
202     Rect m_rect;
203
204     Edges m_margin;
205     Edges m_border;
206     Edges m_padding;
207
208 #if !ASSERT_DISABLED
209     bool m_hasValidHorizontalMargin { false };
210     bool m_hasValidVerticalMargin { false };
211     bool m_hasValidBorder { false };
212     bool m_hasValidPadding { false };
213 #endif
214 };
215
216 #if !ASSERT_DISABLED
217 inline void Box::Rect::invalidatePosition()
218 {
219     invalidateTop();
220     invalidateLeft();
221 }
222
223 inline void Box::Rect::setHasValidPosition()
224 {
225     m_hasValidTop = true;
226     m_hasValidLeft = true;
227 }
228
229 inline void Box::Rect::setHasValidSize()
230 {
231     m_hasValidWidth = true;
232     m_hasValidHeight = true;
233 }
234
235 inline void Box::invalidateMargin()
236 {
237     m_hasValidHorizontalMargin = false;
238     m_hasValidVerticalMargin = false;
239 }
240 #endif
241
242 inline LayoutUnit Box::Rect::top() const
243 {
244     ASSERT(m_hasValidTop);
245     return m_rect.y();
246 }
247
248 inline LayoutUnit Box::Rect::left() const
249 {
250     ASSERT(m_hasValidLeft);
251     return m_rect.x();
252 }
253
254 inline LayoutUnit Box::Rect::bottom() const
255 {
256     ASSERT(m_hasValidTop && m_hasValidHeight);
257     return m_rect.maxY();
258 }
259
260 inline LayoutUnit Box::Rect::right() const
261 {
262     ASSERT(m_hasValidLeft && m_hasValidWidth);
263     return m_rect.maxX();
264 }
265
266 inline LayoutPoint Box::Rect::topLeft() const
267 {
268     ASSERT(hasValidPosition());
269     return m_rect.minXMinYCorner();
270 }
271
272 inline LayoutPoint Box::Rect::bottomRight() const
273 {
274     ASSERT(hasValidGeometry());
275     return m_rect.maxXMaxYCorner();
276 }
277
278 inline LayoutSize Box::Rect::size() const
279 {
280     ASSERT(hasValidSize());
281     return m_rect.size();
282 }
283
284 inline LayoutUnit Box::Rect::width() const
285 {
286     ASSERT(m_hasValidWidth);
287     return m_rect.width();
288 }
289
290 inline LayoutUnit Box::Rect::height() const
291 {
292     ASSERT(m_hasValidHeight);
293     return m_rect.height();
294 }
295
296 inline void Box::Rect::setTopLeft(const LayoutPoint& topLeft)
297 {
298 #if !ASSERT_DISABLED
299     setHasValidPosition();
300 #endif
301     m_rect.setLocation(topLeft);
302 }
303
304 inline void Box::Rect::setTop(LayoutUnit top)
305 {
306 #if !ASSERT_DISABLED
307     m_hasValidTop = true;
308 #endif
309     m_rect.setY(top);
310 }
311
312 inline void Box::Rect::setLeft(LayoutUnit left)
313 {
314 #if !ASSERT_DISABLED
315     m_hasValidLeft = true;
316 #endif
317     m_rect.setX(left);
318 }
319
320 inline void Box::Rect::setWidth(LayoutUnit width)
321 {
322 #if !ASSERT_DISABLED
323     m_hasValidWidth = true;
324 #endif
325     m_rect.setWidth(width);
326 }
327
328 inline void Box::Rect::setHeight(LayoutUnit height)
329 {
330 #if !ASSERT_DISABLED
331     m_hasValidHeight = true;
332 #endif
333     m_rect.setHeight(height);
334 }
335
336 inline void Box::Rect::setSize(const LayoutSize& size)
337 {
338 #if !ASSERT_DISABLED
339     setHasValidSize();
340 #endif
341     m_rect.setSize(size);
342 }
343
344 inline void Box::Rect::shiftLeftTo(LayoutUnit left)
345 {
346     ASSERT(m_hasValidLeft);
347     m_rect.shiftXEdgeTo(left);
348 }
349
350 inline void Box::Rect::shiftRightTo(LayoutUnit right)
351 {
352     ASSERT(m_hasValidLeft && m_hasValidWidth);
353     m_rect.shiftMaxXEdgeTo(right);
354 }
355
356 inline void Box::Rect::shiftTopTo(LayoutUnit top)
357 {
358     ASSERT(m_hasValidTop);
359     m_rect.shiftYEdgeTo(top);
360 }
361
362 inline void Box::Rect::shiftBottomTo(LayoutUnit bottom)
363 {
364     ASSERT(m_hasValidTop && m_hasValidHeight);
365     m_rect.shiftMaxYEdgeTo(bottom);
366 }
367
368 inline void Box::Rect::moveHorizontally(LayoutUnit offset)
369 {
370     ASSERT(m_hasValidLeft);
371     m_rect.move(offset, { });
372 }
373
374 inline void Box::Rect::moveVertically(LayoutUnit offset)
375 {
376     ASSERT(m_hasValidTop);
377     m_rect.move({ }, offset);
378 }
379
380 inline void Box::Rect::expand(LayoutUnit width, LayoutUnit height)
381 {
382     ASSERT(hasValidGeometry());
383     m_rect.expand(width, height);
384 }
385
386 inline Box::Rect Box::Rect::clone() const
387 {
388     Rect rect;
389 #if !ASSERT_DISABLED
390     rect.m_hasValidTop = m_hasValidTop;
391     rect.m_hasValidLeft = m_hasValidLeft;
392     rect.m_hasValidWidth = m_hasValidWidth;
393     rect.m_hasValidHeight  = m_hasValidHeight;
394 #endif 
395     rect.m_rect = m_rect;
396     return rect;
397 }
398
399 inline Box::Rect::operator LayoutRect() const
400 {
401     ASSERT(hasValidGeometry()); 
402     return m_rect;
403 }
404
405 inline void Box::setHorizontalMargin(HorizontalEdges margin)
406 {
407 #if !ASSERT_DISABLED
408     setHasValidHorizontalMargin();
409 #endif
410     m_margin.horizontal = margin;
411 }
412
413 inline void Box::setVerticalMargin(VerticalEdges margin)
414 {
415 #if !ASSERT_DISABLED
416     setHasValidVerticalMargin();
417 #endif
418     m_margin.vertical = margin;
419 }
420
421 inline void Box::setBorder(Edges border)
422 {
423 #if !ASSERT_DISABLED
424     setHasValidBorder();
425 #endif
426     m_border = border;
427 }
428
429 inline void Box::setPadding(Edges padding)
430 {
431 #if !ASSERT_DISABLED
432     setHasValidPadding();
433 #endif
434     m_padding = padding;
435 }
436
437 inline LayoutUnit Box::marginTop() const
438 {
439     ASSERT(m_hasValidVerticalMargin);
440     return m_margin.vertical.top;
441 }
442
443 inline LayoutUnit Box::marginLeft() const
444 {
445     ASSERT(m_hasValidHorizontalMargin);
446     return m_margin.horizontal.left;
447 }
448
449 inline LayoutUnit Box::marginBottom() const
450 {
451     ASSERT(m_hasValidVerticalMargin);
452     return m_margin.vertical.bottom;
453 }
454
455 inline LayoutUnit Box::marginRight() const
456 {
457     ASSERT(m_hasValidHorizontalMargin);
458     return m_margin.horizontal.right;
459 }
460
461 inline LayoutUnit Box::paddingTop() const
462 {
463     ASSERT(m_hasValidPadding);
464     return m_padding.vertical.top;
465 }
466
467 inline LayoutUnit Box::paddingLeft() const
468 {
469     ASSERT(m_hasValidPadding);
470     return m_padding.horizontal.left;
471 }
472
473 inline LayoutUnit Box::paddingBottom() const
474 {
475     ASSERT(m_hasValidPadding);
476     return m_padding.vertical.bottom;
477 }
478
479 inline LayoutUnit Box::paddingRight() const
480 {
481     ASSERT(m_hasValidPadding);
482     return m_padding.horizontal.right;
483 }
484
485 inline LayoutUnit Box::borderTop() const
486 {
487     ASSERT(m_hasValidBorder);
488     return m_border.vertical.top;
489 }
490
491 inline LayoutUnit Box::borderLeft() const
492 {
493     ASSERT(m_hasValidBorder);
494     return m_border.horizontal.left;
495 }
496
497 inline LayoutUnit Box::borderBottom() const
498 {
499     ASSERT(m_hasValidBorder);
500     return m_border.vertical.bottom;
501 }
502
503 inline LayoutUnit Box::borderRight() const
504 {
505     ASSERT(m_hasValidBorder);
506     return m_border.horizontal.right;
507 }
508
509 }
510 }
511 #endif