Display.h 6.9 KB

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