
The 'C' in "CSS" is for Cascade, so let's actually implement the cascade in LibWeb. :^) StyleResolver::resolve_style() now begins by collecting all the matching CSS rules for the given DOM::Element. Rules are then processed in the spec's cascade order (instead of in the order we encounter them.) With this, "!important" is now honored on CSS properties. After performing the cascade, we do another pass of what the spec calls "defaulting" where we resolve "inherit" and "initial" values. I've left a FIXME about supporting correct "initial" values for every property, since we're currently lacking some coverage there. Note that this mechanism now resolves every known CSS property. This is *not* space-efficient and we'll eventually need to come up with some strategies to reduce memory usage around this. However, this will do fine until we have more of the engine working correctly. :^)
71 lines
2 KiB
C++
71 lines
2 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/NonnullRefPtrVector.h>
|
|
#include <AK/OwnPtr.h>
|
|
#include <LibWeb/CSS/CSSStyleDeclaration.h>
|
|
#include <LibWeb/CSS/StyleProperties.h>
|
|
#include <LibWeb/Forward.h>
|
|
|
|
namespace Web::CSS {
|
|
|
|
struct MatchingRule {
|
|
RefPtr<CSSStyleRule> rule;
|
|
size_t style_sheet_index { 0 };
|
|
size_t rule_index { 0 };
|
|
size_t selector_index { 0 };
|
|
u32 specificity { 0 };
|
|
};
|
|
|
|
class StyleResolver {
|
|
public:
|
|
explicit StyleResolver(DOM::Document&);
|
|
~StyleResolver();
|
|
|
|
DOM::Document& document() { return m_document; }
|
|
DOM::Document const& document() const { return m_document; }
|
|
|
|
NonnullRefPtr<StyleProperties> resolve_style(DOM::Element&) const;
|
|
|
|
// https://www.w3.org/TR/css-cascade/#origin
|
|
enum class CascadeOrigin {
|
|
Any, // FIXME: This is not part of the spec. Get rid of it.
|
|
Author,
|
|
User,
|
|
UserAgent,
|
|
Animation,
|
|
Transition,
|
|
};
|
|
|
|
Vector<MatchingRule> collect_matching_rules(DOM::Element const&, CascadeOrigin = CascadeOrigin::Any) const;
|
|
void sort_matching_rules(Vector<MatchingRule>&) const;
|
|
struct CustomPropertyResolutionTuple {
|
|
Optional<StyleProperty> style {};
|
|
u32 specificity { 0 };
|
|
};
|
|
CustomPropertyResolutionTuple resolve_custom_property_with_specificity(DOM::Element&, String const&) const;
|
|
Optional<StyleProperty> resolve_custom_property(DOM::Element&, String const&) const;
|
|
|
|
private:
|
|
void compute_cascaded_values(StyleProperties&, DOM::Element&) const;
|
|
void compute_defaulted_values(StyleProperties&, DOM::Element const&) const;
|
|
|
|
template<typename Callback>
|
|
void for_each_stylesheet(CascadeOrigin, Callback) const;
|
|
|
|
struct MatchingRuleSet {
|
|
Vector<MatchingRule> user_agent_rules;
|
|
Vector<MatchingRule> author_rules;
|
|
};
|
|
|
|
void cascade_declarations(StyleProperties&, DOM::Element&, Vector<MatchingRule> const&, CascadeOrigin, bool important) const;
|
|
|
|
DOM::Document& m_document;
|
|
};
|
|
|
|
}
|