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