Display.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. bool is_math_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Math; }
  86. enum class Short {
  87. None,
  88. Contents,
  89. Block,
  90. Flow,
  91. FlowRoot,
  92. Inline,
  93. InlineBlock,
  94. RunIn,
  95. ListItem,
  96. InlineListItem,
  97. Flex,
  98. InlineFlex,
  99. Grid,
  100. InlineGrid,
  101. Ruby,
  102. Table,
  103. InlineTable,
  104. Math,
  105. };
  106. static Display from_short(Short short_)
  107. {
  108. switch (short_) {
  109. case Short::None:
  110. return Display { DisplayBox::None };
  111. case Short::Contents:
  112. return Display { DisplayBox::Contents };
  113. case Short::Block:
  114. return Display { DisplayOutside::Block, DisplayInside::Flow };
  115. case Short::Inline:
  116. return Display { DisplayOutside::Inline, DisplayInside::Flow };
  117. case Short::Flow:
  118. return Display { DisplayOutside::Block, DisplayInside::Flow };
  119. case Short::FlowRoot:
  120. return Display { DisplayOutside::Block, DisplayInside::FlowRoot };
  121. case Short::InlineBlock:
  122. return Display { DisplayOutside::Inline, DisplayInside::FlowRoot };
  123. case Short::RunIn:
  124. return Display { DisplayOutside::RunIn, DisplayInside::Flow };
  125. case Short::ListItem:
  126. return Display { DisplayOutside::Block, DisplayInside::Flow, ListItem::Yes };
  127. case Short::InlineListItem:
  128. return Display { DisplayOutside::Inline, DisplayInside::Flow, ListItem::Yes };
  129. case Short::Flex:
  130. return Display { DisplayOutside::Block, DisplayInside::Flex };
  131. case Short::InlineFlex:
  132. return Display { DisplayOutside::Inline, DisplayInside::Flex };
  133. case Short::Grid:
  134. return Display { DisplayOutside::Block, DisplayInside::Grid };
  135. case Short::InlineGrid:
  136. return Display { DisplayOutside::Inline, DisplayInside::Grid };
  137. case Short::Ruby:
  138. return Display { DisplayOutside::Inline, DisplayInside::Ruby };
  139. case Short::Table:
  140. return Display { DisplayOutside::Block, DisplayInside::Table };
  141. case Short::InlineTable:
  142. return Display { DisplayOutside::Inline, DisplayInside::Table };
  143. case Short::Math:
  144. // NOTE: The spec ( https://w3c.github.io/mathml-core/#new-display-math-value ) does not
  145. // mention what the outside value for `display: math` should be.
  146. // The UA stylesheet does `* { display: block math; }` so let's go with that.
  147. return Display { DisplayOutside::Block, DisplayInside::Math };
  148. }
  149. VERIFY_NOT_REACHED();
  150. }
  151. Display(DisplayOutside outside, DisplayInside inside)
  152. : m_type(Type::OutsideAndInside)
  153. {
  154. m_value.outside_inside = {
  155. .outside = outside,
  156. .inside = inside,
  157. .list_item = ListItem::No,
  158. };
  159. }
  160. Display(DisplayOutside outside, DisplayInside inside, ListItem list_item)
  161. : m_type(Type::OutsideAndInside)
  162. {
  163. m_value.outside_inside = {
  164. .outside = outside,
  165. .inside = inside,
  166. .list_item = list_item,
  167. };
  168. }
  169. explicit Display(DisplayInternal internal)
  170. : m_type(Type::Internal)
  171. {
  172. m_value.internal = internal;
  173. }
  174. explicit Display(DisplayBox box)
  175. : m_type(Type::Box)
  176. {
  177. m_value.box = box;
  178. }
  179. private:
  180. Type m_type {};
  181. union {
  182. struct {
  183. DisplayOutside outside;
  184. DisplayInside inside;
  185. ListItem list_item;
  186. } outside_inside;
  187. DisplayInternal internal;
  188. DisplayBox box;
  189. } m_value {};
  190. };
  191. }