///|
/// Cascade styles for an element with forced pseudo-class states.
/// This evaluates CSS rules as if the specified pseudo-class states
/// (:hover, :focus, :active) were active on the element.
pub fn cascade_element_with_forced_states(
element : @selector.Element,
stylesheets : Array[Stylesheet],
inline_style : Array[Declaration],
media_env : @media.MediaEnvironment?,
forced : @selector.ForcedPseudoStates,
) -> CascadedValues {
let result = CascadedValues::new()
let mut source_order_offset = 0
for stylesheet in stylesheets {
let max_source_order = cascade_stylesheet_forced_into(
result, stylesheet, element, media_env, forced, source_order_offset,
)
if max_source_order >= source_order_offset {
source_order_offset = max_source_order + 1
}
}
for decl in inline_style {
accumulate_inline_declaration(result, decl)
}
result
}
///|
fn cascade_stylesheet_forced_into(
result : CascadedValues,
stylesheet : Stylesheet,
element : @selector.Element,
media_env : @media.MediaEnvironment?,
forced : @selector.ForcedPseudoStates,
source_order_offset : Int,
) -> Int {
let mut max_source_order_in_sheet = source_order_offset - 1
for rule in stylesheet.rules {
let media_matches = match (rule.media_query, media_env) {
(Some(mq), Some(env)) => mq.evaluate(env)
(Some(_), None) => true
(None, _) => true
}
if !media_matches {
continue
}
if @selector.matches_complex_with_forced_states(
element,
rule.selector,
forced,
) {
let specificity = @selector.complex_specificity(rule.selector)
for decl in rule.declarations {
let adjusted_source_order = source_order_offset +
rule.source_order * 10000 +
decl.source_order
if adjusted_source_order > max_source_order_in_sheet {
max_source_order_in_sheet = adjusted_source_order
}
accumulate_cascaded_declaration(result, {
property: decl.property,
value: decl.value,
origin: stylesheet.origin,
importance: decl.importance,
specificity,
source_order: adjusted_source_order,
})
}
}
}
max_source_order_in_sheet
}