Display.h 7.0 KB

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