Display.h 7.0 KB

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