| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2024-10-04 13:19:50 +02:00
										 |  |  |  * Copyright (c) 2021, Andreas Kling <andreas@ladybird.org> | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |  * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-10 15:56:29 +02:00
										 |  |  | #include <AK/Assertions.h>
 | 
					
						
							| 
									
										
										
										
											2023-02-15 11:36:09 +00:00
										 |  |  | #include <AK/String.h>
 | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  | #include <LibWeb/CSS/Enums.h>
 | 
					
						
							| 
									
										
										
										
											2021-10-10 15:56:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  | namespace Web::CSS { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Display { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     Display() = default; | 
					
						
							|  |  |  |     ~Display() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-22 12:25:30 +01:00
										 |  |  |     String to_string() const; | 
					
						
							| 
									
										
										
										
											2022-02-13 01:02:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |     bool operator==(Display const& other) const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (m_type != other.m_type) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         switch (m_type) { | 
					
						
							|  |  |  |         case Type::Box: | 
					
						
							|  |  |  |             return m_value.box == other.m_value.box; | 
					
						
							|  |  |  |         case Type::Internal: | 
					
						
							|  |  |  |             return m_value.internal == other.m_value.internal; | 
					
						
							|  |  |  |         case Type::OutsideAndInside: | 
					
						
							|  |  |  |             return m_value.outside_inside.outside == other.m_value.outside_inside.outside | 
					
						
							|  |  |  |                 && m_value.outside_inside.inside == other.m_value.outside_inside.inside | 
					
						
							|  |  |  |                 && m_value.outside_inside.list_item == other.m_value.outside_inside.list_item; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-26 20:28:01 +02:00
										 |  |  |     enum class ListItem { | 
					
						
							|  |  |  |         No, | 
					
						
							|  |  |  |         Yes, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |     enum class Type { | 
					
						
							|  |  |  |         OutsideAndInside, | 
					
						
							|  |  |  |         Internal, | 
					
						
							|  |  |  |         Box, | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool is_internal() const { return m_type == Type::Internal; } | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |     DisplayInternal internal() const | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         VERIFY(is_internal()); | 
					
						
							|  |  |  |         return m_value.internal; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |     bool is_table_column() const { return is_internal() && internal() == DisplayInternal::TableColumn; } | 
					
						
							|  |  |  |     bool is_table_row_group() const { return is_internal() && internal() == DisplayInternal::TableRowGroup; } | 
					
						
							|  |  |  |     bool is_table_header_group() const { return is_internal() && internal() == DisplayInternal::TableHeaderGroup; } | 
					
						
							|  |  |  |     bool is_table_footer_group() const { return is_internal() && internal() == DisplayInternal::TableFooterGroup; } | 
					
						
							|  |  |  |     bool is_table_row() const { return is_internal() && internal() == DisplayInternal::TableRow; } | 
					
						
							|  |  |  |     bool is_table_cell() const { return is_internal() && internal() == DisplayInternal::TableCell; } | 
					
						
							|  |  |  |     bool is_table_column_group() const { return is_internal() && internal() == DisplayInternal::TableColumnGroup; } | 
					
						
							|  |  |  |     bool is_table_caption() const { return is_internal() && internal() == DisplayInternal::TableCaption; } | 
					
						
							| 
									
										
										
										
											2025-01-18 20:39:26 +01:00
										 |  |  |     // https://drafts.csswg.org/css-display-3/#internal-table-element
 | 
					
						
							|  |  |  |     bool is_internal_table() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return is_internal() && (internal() == DisplayInternal::TableRowGroup || internal() == DisplayInternal::TableHeaderGroup || internal() == DisplayInternal::TableFooterGroup || internal() == DisplayInternal::TableRow || internal() == DisplayInternal::TableCell || internal() == DisplayInternal::TableColumnGroup || internal() == DisplayInternal::TableColumn); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     bool is_none() const { return m_type == Type::Box && m_value.box == DisplayBox::None; } | 
					
						
							|  |  |  |     bool is_contents() const { return m_type == Type::Box && m_value.box == DisplayBox::Contents; } | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Type type() const { return m_type; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-13 01:03:40 +02:00
										 |  |  |     bool is_outside_and_inside() const { return m_type == Type::OutsideAndInside; } | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |     DisplayOutside outside() const | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-04-13 01:03:40 +02:00
										 |  |  |         VERIFY(is_outside_and_inside()); | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         return m_value.outside_inside.outside; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |     bool is_block_outside() const { return is_outside_and_inside() && outside() == DisplayOutside::Block; } | 
					
						
							|  |  |  |     bool is_inline_outside() const { return is_outside_and_inside() && outside() == DisplayOutside::Inline; } | 
					
						
							| 
									
										
										
										
											2022-10-06 16:51:53 +02:00
										 |  |  |     bool is_inline_block() const { return is_inline_outside() && is_flow_root_inside(); } | 
					
						
							| 
									
										
										
										
											2023-04-26 20:28:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ListItem list_item() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         VERIFY(is_outside_and_inside()); | 
					
						
							|  |  |  |         return m_value.outside_inside.list_item; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool is_list_item() const { return is_outside_and_inside() && list_item() == ListItem::Yes; } | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |     DisplayInside inside() const | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2022-04-13 01:03:40 +02:00
										 |  |  |         VERIFY(is_outside_and_inside()); | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         return m_value.outside_inside.inside; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |     bool is_flow_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Flow; } | 
					
						
							|  |  |  |     bool is_flow_root_inside() const { return is_outside_and_inside() && inside() == DisplayInside::FlowRoot; } | 
					
						
							|  |  |  |     bool is_table_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Table; } | 
					
						
							|  |  |  |     bool is_flex_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Flex; } | 
					
						
							|  |  |  |     bool is_grid_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Grid; } | 
					
						
							|  |  |  |     bool is_ruby_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Ruby; } | 
					
						
							| 
									
										
										
										
											2023-09-07 16:03:20 +01:00
										 |  |  |     bool is_math_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Math; } | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     enum class Short { | 
					
						
							|  |  |  |         None, | 
					
						
							|  |  |  |         Contents, | 
					
						
							|  |  |  |         Block, | 
					
						
							| 
									
										
										
										
											2023-04-26 21:05:38 +02:00
										 |  |  |         Flow, | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         FlowRoot, | 
					
						
							|  |  |  |         Inline, | 
					
						
							|  |  |  |         InlineBlock, | 
					
						
							|  |  |  |         RunIn, | 
					
						
							|  |  |  |         ListItem, | 
					
						
							|  |  |  |         InlineListItem, | 
					
						
							|  |  |  |         Flex, | 
					
						
							|  |  |  |         InlineFlex, | 
					
						
							|  |  |  |         Grid, | 
					
						
							|  |  |  |         InlineGrid, | 
					
						
							|  |  |  |         Ruby, | 
					
						
							|  |  |  |         Table, | 
					
						
							|  |  |  |         InlineTable, | 
					
						
							| 
									
										
										
										
											2023-09-07 16:03:20 +01:00
										 |  |  |         Math, | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static Display from_short(Short short_) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (short_) { | 
					
						
							|  |  |  |         case Short::None: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayBox::None }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::Contents: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayBox::Contents }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::Block: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Block, DisplayInside::Flow }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::Inline: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Inline, DisplayInside::Flow }; | 
					
						
							| 
									
										
										
										
											2023-04-26 21:05:38 +02:00
										 |  |  |         case Short::Flow: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Block, DisplayInside::Flow }; | 
					
						
							| 
									
										
										
										
											2023-04-26 21:05:38 +02:00
										 |  |  |         case Short::FlowRoot: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Block, DisplayInside::FlowRoot }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::InlineBlock: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Inline, DisplayInside::FlowRoot }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::RunIn: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::RunIn, DisplayInside::Flow }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::ListItem: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Block, DisplayInside::Flow, ListItem::Yes }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::InlineListItem: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Inline, DisplayInside::Flow, ListItem::Yes }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::Flex: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Block, DisplayInside::Flex }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::InlineFlex: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Inline, DisplayInside::Flex }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::Grid: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Block, DisplayInside::Grid }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::InlineGrid: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Inline, DisplayInside::Grid }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::Ruby: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Inline, DisplayInside::Ruby }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::Table: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Block, DisplayInside::Table }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         case Short::InlineTable: | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             return Display { DisplayOutside::Inline, DisplayInside::Table }; | 
					
						
							| 
									
										
										
										
											2023-09-07 16:03:20 +01:00
										 |  |  |         case Short::Math: | 
					
						
							|  |  |  |             // NOTE: The spec ( https://w3c.github.io/mathml-core/#new-display-math-value ) does not
 | 
					
						
							|  |  |  |             //       mention what the outside value for `display: math` should be.
 | 
					
						
							|  |  |  |             //       The UA stylesheet does `* { display: block math; }` so let's go with that.
 | 
					
						
							|  |  |  |             return Display { DisplayOutside::Block, DisplayInside::Math }; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |     Display(DisplayOutside outside, DisplayInside inside) | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         : m_type(Type::OutsideAndInside) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_value.outside_inside = { | 
					
						
							|  |  |  |             .outside = outside, | 
					
						
							|  |  |  |             .inside = inside, | 
					
						
							|  |  |  |             .list_item = ListItem::No, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |     Display(DisplayOutside outside, DisplayInside inside, ListItem list_item) | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         : m_type(Type::OutsideAndInside) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_value.outside_inside = { | 
					
						
							|  |  |  |             .outside = outside, | 
					
						
							|  |  |  |             .inside = inside, | 
					
						
							|  |  |  |             .list_item = list_item, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |     explicit Display(DisplayInternal internal) | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         : m_type(Type::Internal) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_value.internal = internal; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |     explicit Display(DisplayBox box) | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |         : m_type(Type::Box) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_value.box = box; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Type m_type {}; | 
					
						
							|  |  |  |     union { | 
					
						
							|  |  |  |         struct { | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |             DisplayOutside outside; | 
					
						
							|  |  |  |             DisplayInside inside; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |             ListItem list_item; | 
					
						
							|  |  |  |         } outside_inside; | 
					
						
							| 
									
										
										
										
											2023-09-04 17:39:15 +01:00
										 |  |  |         DisplayInternal internal; | 
					
						
							|  |  |  |         DisplayBox box; | 
					
						
							| 
									
										
										
										
											2021-10-06 19:30:14 +02:00
										 |  |  |     } m_value {}; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |