123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- /*
- * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
- * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #pragma once
- #include <AK/Assertions.h>
- #include <AK/String.h>
- #include <LibWeb/CSS/Enums.h>
- namespace Web::CSS {
- class Display {
- public:
- Display() = default;
- ~Display() = default;
- String to_string() const;
- bool operator==(Display const& other) const
- {
- if (m_type != other.m_type)
- return false;
- switch (m_type) {
- case Type::Box:
- return m_value.box == other.m_value.box;
- case Type::Internal:
- return m_value.internal == other.m_value.internal;
- case Type::OutsideAndInside:
- return m_value.outside_inside.outside == other.m_value.outside_inside.outside
- && m_value.outside_inside.inside == other.m_value.outside_inside.inside
- && m_value.outside_inside.list_item == other.m_value.outside_inside.list_item;
- }
- VERIFY_NOT_REACHED();
- }
- enum class ListItem {
- No,
- Yes,
- };
- enum class Type {
- OutsideAndInside,
- Internal,
- Box,
- };
- bool is_internal() const { return m_type == Type::Internal; }
- DisplayInternal internal() const
- {
- VERIFY(is_internal());
- return m_value.internal;
- }
- bool is_table_column() const { return is_internal() && internal() == DisplayInternal::TableColumn; }
- bool is_table_row_group() const { return is_internal() && internal() == DisplayInternal::TableRowGroup; }
- bool is_table_header_group() const { return is_internal() && internal() == DisplayInternal::TableHeaderGroup; }
- bool is_table_footer_group() const { return is_internal() && internal() == DisplayInternal::TableFooterGroup; }
- bool is_table_row() const { return is_internal() && internal() == DisplayInternal::TableRow; }
- bool is_table_cell() const { return is_internal() && internal() == DisplayInternal::TableCell; }
- bool is_table_column_group() const { return is_internal() && internal() == DisplayInternal::TableColumnGroup; }
- bool is_table_caption() const { return is_internal() && internal() == DisplayInternal::TableCaption; }
- bool is_none() const { return m_type == Type::Box && m_value.box == DisplayBox::None; }
- bool is_contents() const { return m_type == Type::Box && m_value.box == DisplayBox::Contents; }
- Type type() const { return m_type; }
- bool is_outside_and_inside() const { return m_type == Type::OutsideAndInside; }
- DisplayOutside outside() const
- {
- VERIFY(is_outside_and_inside());
- return m_value.outside_inside.outside;
- }
- bool is_block_outside() const { return is_outside_and_inside() && outside() == DisplayOutside::Block; }
- bool is_inline_outside() const { return is_outside_and_inside() && outside() == DisplayOutside::Inline; }
- bool is_inline_block() const { return is_inline_outside() && is_flow_root_inside(); }
- ListItem list_item() const
- {
- VERIFY(is_outside_and_inside());
- return m_value.outside_inside.list_item;
- }
- bool is_list_item() const { return is_outside_and_inside() && list_item() == ListItem::Yes; }
- DisplayInside inside() const
- {
- VERIFY(is_outside_and_inside());
- return m_value.outside_inside.inside;
- }
- bool is_flow_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Flow; }
- bool is_flow_root_inside() const { return is_outside_and_inside() && inside() == DisplayInside::FlowRoot; }
- bool is_table_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Table; }
- bool is_flex_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Flex; }
- bool is_grid_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Grid; }
- bool is_ruby_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Ruby; }
- bool is_math_inside() const { return is_outside_and_inside() && inside() == DisplayInside::Math; }
- enum class Short {
- None,
- Contents,
- Block,
- Flow,
- FlowRoot,
- Inline,
- InlineBlock,
- RunIn,
- ListItem,
- InlineListItem,
- Flex,
- InlineFlex,
- Grid,
- InlineGrid,
- Ruby,
- Table,
- InlineTable,
- Math,
- };
- static Display from_short(Short short_)
- {
- switch (short_) {
- case Short::None:
- return Display { DisplayBox::None };
- case Short::Contents:
- return Display { DisplayBox::Contents };
- case Short::Block:
- return Display { DisplayOutside::Block, DisplayInside::Flow };
- case Short::Inline:
- return Display { DisplayOutside::Inline, DisplayInside::Flow };
- case Short::Flow:
- return Display { DisplayOutside::Block, DisplayInside::Flow };
- case Short::FlowRoot:
- return Display { DisplayOutside::Block, DisplayInside::FlowRoot };
- case Short::InlineBlock:
- return Display { DisplayOutside::Inline, DisplayInside::FlowRoot };
- case Short::RunIn:
- return Display { DisplayOutside::RunIn, DisplayInside::Flow };
- case Short::ListItem:
- return Display { DisplayOutside::Block, DisplayInside::Flow, ListItem::Yes };
- case Short::InlineListItem:
- return Display { DisplayOutside::Inline, DisplayInside::Flow, ListItem::Yes };
- case Short::Flex:
- return Display { DisplayOutside::Block, DisplayInside::Flex };
- case Short::InlineFlex:
- return Display { DisplayOutside::Inline, DisplayInside::Flex };
- case Short::Grid:
- return Display { DisplayOutside::Block, DisplayInside::Grid };
- case Short::InlineGrid:
- return Display { DisplayOutside::Inline, DisplayInside::Grid };
- case Short::Ruby:
- return Display { DisplayOutside::Inline, DisplayInside::Ruby };
- case Short::Table:
- return Display { DisplayOutside::Block, DisplayInside::Table };
- case Short::InlineTable:
- return Display { DisplayOutside::Inline, DisplayInside::Table };
- case Short::Math:
- // NOTE: The spec ( https://w3c.github.io/mathml-core/#new-display-math-value ) does not
- // mention what the outside value for `display: math` should be.
- // The UA stylesheet does `* { display: block math; }` so let's go with that.
- return Display { DisplayOutside::Block, DisplayInside::Math };
- }
- VERIFY_NOT_REACHED();
- }
- Display(DisplayOutside outside, DisplayInside inside)
- : m_type(Type::OutsideAndInside)
- {
- m_value.outside_inside = {
- .outside = outside,
- .inside = inside,
- .list_item = ListItem::No,
- };
- }
- Display(DisplayOutside outside, DisplayInside inside, ListItem list_item)
- : m_type(Type::OutsideAndInside)
- {
- m_value.outside_inside = {
- .outside = outside,
- .inside = inside,
- .list_item = list_item,
- };
- }
- explicit Display(DisplayInternal internal)
- : m_type(Type::Internal)
- {
- m_value.internal = internal;
- }
- explicit Display(DisplayBox box)
- : m_type(Type::Box)
- {
- m_value.box = box;
- }
- private:
- Type m_type {};
- union {
- struct {
- DisplayOutside outside;
- DisplayInside inside;
- ListItem list_item;
- } outside_inside;
- DisplayInternal internal;
- DisplayBox box;
- } m_value {};
- };
- }
|