1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

//! Misc information about a given computed style.

/// Misc information about a given computed style.
///
/// All flags are currently inherited for text, pseudo elements, and
/// anonymous boxes, see StyleBuilder::for_inheritance and its callsites.
/// If we ever want to add some flags that shouldn't inherit for them,
/// we might want to add a function to handle this.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
pub struct ComputedValueFlags(u32);

bitflags! {
    impl ComputedValueFlags: u32 {
        /// Whether the style or any of the ancestors has a text-decoration-line
        /// property that should get propagated to descendants.
        ///
        /// text-decoration-line is a reset property, but gets propagated in the
        /// frame/box tree.
        const HAS_TEXT_DECORATION_LINES = 1 << 0;

        /// Whether line break inside should be suppressed.
        ///
        /// If this flag is set, the line should not be broken inside,
        /// which means inlines act as if nowrap is set, <br> element is
        /// suppressed, and blocks are inlinized.
        ///
        /// This bit is propagated to all children of line participants.
        /// It is currently used by ruby to make its content unbreakable.
        const SHOULD_SUPPRESS_LINEBREAK = 1 << 1;

        /// A flag used to mark text that that has text-combine-upright.
        ///
        /// This is used from Gecko's layout engine.
        const IS_TEXT_COMBINED = 1 << 2;

        /// A flag used to mark styles under a relevant link that is also
        /// visited.
        const IS_RELEVANT_LINK_VISITED = 1 << 3;

        /// A flag used to mark styles which are a pseudo-element or under one.
        const IS_IN_PSEUDO_ELEMENT_SUBTREE = 1 << 4;

        /// A flag used to mark styles which have contain:style or under one.
        const SELF_OR_ANCESTOR_HAS_CONTAIN_STYLE = 1 << 5;

        /// Whether this style's `display` property depends on our parent style.
        ///
        /// This is important because it may affect our optimizations to avoid
        /// computing the style of pseudo-elements, given whether the
        /// pseudo-element is generated depends on the `display` value.
        const DISPLAY_DEPENDS_ON_INHERITED_STYLE = 1 << 6;

        /// Whether this style's `content` depends on our parent style.
        ///
        /// Important because of the same reason.
        const CONTENT_DEPENDS_ON_INHERITED_STYLE = 1 << 7;

        /// Whether the child explicitly inherits any reset property.
        const INHERITS_RESET_STYLE = 1 << 8;

        /// Whether any value on our style is font-metric-dependent on our
        /// primary font.
        const DEPENDS_ON_SELF_FONT_METRICS = 1 << 9;

        /// Whether any value on our style is font-metric-dependent on the
        /// primary font of our parent.
        const DEPENDS_ON_INHERITED_FONT_METRICS = 1 << 10;

        /// Whether the style or any of the ancestors has a multicol style.
        ///
        /// Only used in Servo.
        const CAN_BE_FRAGMENTED = 1 << 11;

        /// Whether this style is the style of the document element.
        const IS_ROOT_ELEMENT_STYLE = 1 << 12;

        /// Whether this element is inside an `opacity: 0` subtree.
        const IS_IN_OPACITY_ZERO_SUBTREE = 1 << 13;

        /// Whether there are author-specified rules for border-* properties
        /// (except border-image-*), background-color, or background-image.
        ///
        /// TODO(emilio): Maybe do include border-image, see:
        ///
        /// https://github.com/w3c/csswg-drafts/issues/4777#issuecomment-604424845
        const HAS_AUTHOR_SPECIFIED_BORDER_BACKGROUND = 1 << 14;

        /// Whether there are author-specified rules for `font-family`.
        const HAS_AUTHOR_SPECIFIED_FONT_FAMILY = 1 << 16;

        /// Whether there are author-specified rules for `font-synthesis-weight`.
        const HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS_WEIGHT = 1 << 17;

        /// Whether there are author-specified rules for `font-synthesis-style`.
        const HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS_STYLE = 1 << 18;

        // (There's also font-synthesis-small-caps and font-synthesis-position,
        // but we don't currently need to keep track of those.)

        /// Whether there are author-specified rules for `letter-spacing`.
        const HAS_AUTHOR_SPECIFIED_LETTER_SPACING = 1 << 19;

        /// Whether there are author-specified rules for `word-spacing`.
        const HAS_AUTHOR_SPECIFIED_WORD_SPACING = 1 << 20;

        /// Whether the style depends on viewport units.
        const USES_VIEWPORT_UNITS = 1 << 21;

        /// Whether the style depends on viewport units on container queries.
        ///
        /// This needs to be a separate flag from `USES_VIEWPORT_UNITS` because
        /// it causes us to re-match the style (rather than re-cascascading it,
        /// which is enough for other uses of viewport units).
        const USES_VIEWPORT_UNITS_ON_CONTAINER_QUERIES = 1 << 22;

        /// A flag used to mark styles which have `container-type` of `size` or
        /// `inline-size`, or under one.
        const SELF_OR_ANCESTOR_HAS_SIZE_CONTAINER_TYPE = 1 << 23;
        /// Whether the style uses container query units, in which case the style depends on the
        /// container's size and we can't reuse it across cousins (without double-checking the
        /// container at least).
        const USES_CONTAINER_UNITS = 1 << 24;

        /// Whether there are author-specific rules for text `color`.
        const HAS_AUTHOR_SPECIFIED_TEXT_COLOR = 1 << 25;

        /// Whether this style considered a scope style rule.
        const CONSIDERED_NONTRIVIAL_SCOPED_STYLE = 1 << 26;
    }
}

impl Default for ComputedValueFlags {
    #[inline]
    fn default() -> Self {
        Self::empty()
    }
}

impl ComputedValueFlags {
    /// Flags that are unconditionally propagated to descendants.
    #[inline]
    fn inherited_flags() -> Self {
        Self::IS_RELEVANT_LINK_VISITED |
            Self::CAN_BE_FRAGMENTED |
            Self::IS_IN_PSEUDO_ELEMENT_SUBTREE |
            Self::HAS_TEXT_DECORATION_LINES |
            Self::IS_IN_OPACITY_ZERO_SUBTREE |
            Self::SELF_OR_ANCESTOR_HAS_CONTAIN_STYLE |
            Self::SELF_OR_ANCESTOR_HAS_SIZE_CONTAINER_TYPE
    }

    /// Flags that may be propagated to descendants.
    #[inline]
    fn maybe_inherited_flags() -> Self {
        Self::inherited_flags() | Self::SHOULD_SUPPRESS_LINEBREAK
    }

    /// Flags that are an input to the cascade.
    #[inline]
    fn cascade_input_flags() -> Self {
        Self::USES_VIEWPORT_UNITS_ON_CONTAINER_QUERIES |
        Self::CONSIDERED_NONTRIVIAL_SCOPED_STYLE
    }

    /// Returns the flags that are always propagated to descendants.
    ///
    /// See StyleAdjuster::set_bits and StyleBuilder.
    #[inline]
    pub fn inherited(self) -> Self {
        self & Self::inherited_flags()
    }

    /// Flags that are conditionally propagated to descendants, just to handle
    /// properly style invalidation.
    #[inline]
    pub fn maybe_inherited(self) -> Self {
        self & Self::maybe_inherited_flags()
    }

    /// Flags that are an input to the cascade.
    #[inline]
    pub fn for_cascade_inputs(self) -> Self {
        self & Self::cascade_input_flags()
    }
}