Display.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Assertions.h>
  9. #include <AK/String.h>
  10. #include <LibWeb/CSS/Enums.h>
  11. namespace Web::CSS {
  12. class Display {
  13. public:
  14. Display() = default;
  15. ~Display() = default;
  16. String to_string() const;
  17. bool operator==(Display const& other) const
  18. {
  19. if (m_type != other.m_type)
  20. return false;
  21. switch (m_type) {
  22. case Type::Box:
  23. return m_value.box == other.m_value.box;
  24. case Type::Internal:
  25. return m_value.internal == other.m_value.internal;
  26. case Type::OutsideAndInside:
  27. return m_value.outside_inside.outside == other.m_value.outside_inside.outside
  28. && m_value.outside_inside.inside == other.m_value.outside_inside.inside
  29. && m_value.outside_inside.list_item == other.m_value.outside_inside.list_item;
  30. }
  31. VERIFY_NOT_REACHED();
  32. }
  33. enum class ListItem {
  34. No,
  35. Yes,
  36. };
  37. enum class Type {
  38. OutsideAndInside,
  39. Internal,
  40. Box,
  41. };
  42. bool is_internal() const { return m_type == Type::Internal; }
  43. DisplayInternal internal() const
  44. {
  45. VERIFY(is_internal());
  46. return m_value.internal;
  47. }
  48. bool is_table_column() const { return is_internal() && internal() == DisplayInternal::TableColumn; }
  49. bool is_table_row_group() const { return is_internal() && internal() == DisplayInternal::TableRowGroup; }
  50. bool is_table_header_group() const { return is_internal() && internal() == DisplayInternal::TableHeaderGroup; }
  51. bool is_table_footer_group() const { return is_internal() && internal() == DisplayInternal::TableFooterGroup; }
  52. bool is_table_row() const { return is_internal() && internal() == DisplayInternal::TableRow; }
  53. bool is_table_cell() const { return is_internal() && internal() == DisplayInternal::TableCell; }
  54. bool is_table_column_group() const { return is_internal() && internal() == DisplayInternal::TableColumnGroup; }
  55. bool is_table_caption() const { return is_internal() && internal() == DisplayInternal::TableCaption; }
  56. bool is_none() const { return m_type == Type::Box && m_value.box == DisplayBox::None; }
  57. bool is_contents() const { return m_type == Type::Box && m_value.box == DisplayBox::Contents; }
  58. Type type() const { return m_type; }
  59. bool is_outside_and_inside() const { return m_type == Type::OutsideAndInside; }
  60. DisplayOutside outside() const
  61. {
  62. VERIFY(is_outside_and_inside());
  63. return m_value.outside_inside.outside;
  64. }
  65. bool is_block_outside() const { return is_outside_and_inside() && outside() == DisplayOutside::Block; }
  66. bool is_inline_outside() const { return is_outside_and_inside() && outside() == DisplayOutside::Inline; }
  67. bool is_inline_block() const { return is_inline_outside() && is_flow_root_inside(); }
  68. ListItem list_item() const
  69. {
  70. VERIFY(is_outside_and_inside());
  71. return m_value.outside_inside.list_item;
  72. }
  73. bool is_list_item() const { return is_outside_and_inside() && list_item() == ListItem::Yes; }
  74. DisplayInside inside() const
  75. {
  76. VERIFY(is_outside_and_inside());
  77. return m_value.outside_inside.inside;
  78. }
  79. bool is_flow_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Flow; }
  80. bool is_flow_root_inside() const { return is_outside_and_inside() && inside() == DisplayInside::FlowRoot; }
  81. bool is_table_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Table; }
  82. bool is_flex_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Flex; }
  83. bool is_grid_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Grid; }
  84. bool is_ruby_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Ruby; }
  85. enum class Short {
  86. None,
  87. Contents,
  88. Block,
  89. Flow,
  90. FlowRoot,
  91. Inline,
  92. InlineBlock,
  93. RunIn,
  94. ListItem,
  95. InlineListItem,
  96. Flex,
  97. InlineFlex,
  98. Grid,
  99. InlineGrid,
  100. Ruby,
  101. Table,
  102. InlineTable,
  103. };
  104. static Display from_short(Short short_)
  105. {
  106. switch (short_) {
  107. case Short::None:
  108. return Display { DisplayBox::None };
  109. case Short::Contents:
  110. return Display { DisplayBox::Contents };
  111. case Short::Block:
  112. return Display { DisplayOutside::Block, DisplayInside::Flow };
  113. case Short::Inline:
  114. return Display { DisplayOutside::Inline, DisplayInside::Flow };
  115. case Short::Flow:
  116. return Display { DisplayOutside::Block, DisplayInside::Flow };
  117. case Short::FlowRoot:
  118. return Display { DisplayOutside::Block, DisplayInside::FlowRoot };
  119. case Short::InlineBlock:
  120. return Display { DisplayOutside::Inline, DisplayInside::FlowRoot };
  121. case Short::RunIn:
  122. return Display { DisplayOutside::RunIn, DisplayInside::Flow };
  123. case Short::ListItem:
  124. return Display { DisplayOutside::Block, DisplayInside::Flow, ListItem::Yes };
  125. case Short::InlineListItem:
  126. return Display { DisplayOutside::Inline, DisplayInside::Flow, ListItem::Yes };
  127. case Short::Flex:
  128. return Display { DisplayOutside::Block, DisplayInside::Flex };
  129. case Short::InlineFlex:
  130. return Display { DisplayOutside::Inline, DisplayInside::Flex };
  131. case Short::Grid:
  132. return Display { DisplayOutside::Block, DisplayInside::Grid };
  133. case Short::InlineGrid:
  134. return Display { DisplayOutside::Inline, DisplayInside::Grid };
  135. case Short::Ruby:
  136. return Display { DisplayOutside::Inline, DisplayInside::Ruby };
  137. case Short::Table:
  138. return Display { DisplayOutside::Block, DisplayInside::Table };
  139. case Short::InlineTable:
  140. return Display { DisplayOutside::Inline, DisplayInside::Table };
  141. }
  142. VERIFY_NOT_REACHED();
  143. }
  144. Display(DisplayOutside outside, DisplayInside inside)
  145. : m_type(Type::OutsideAndInside)
  146. {
  147. m_value.outside_inside = {
  148. .outside = outside,
  149. .inside = inside,
  150. .list_item = ListItem::No,
  151. };
  152. }
  153. Display(DisplayOutside outside, DisplayInside inside, ListItem list_item)
  154. : m_type(Type::OutsideAndInside)
  155. {
  156. m_value.outside_inside = {
  157. .outside = outside,
  158. .inside = inside,
  159. .list_item = list_item,
  160. };
  161. }
  162. explicit Display(DisplayInternal internal)
  163. : m_type(Type::Internal)
  164. {
  165. m_value.internal = internal;
  166. }
  167. explicit Display(DisplayBox box)
  168. : m_type(Type::Box)
  169. {
  170. m_value.box = box;
  171. }
  172. private:
  173. Type m_type {};
  174. union {
  175. struct {
  176. DisplayOutside outside;
  177. DisplayInside inside;
  178. ListItem list_item;
  179. } outside_inside;
  180. DisplayInternal internal;
  181. DisplayBox box;
  182. } m_value {};
  183. };
  184. }