
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. :^)
96 lines
3.3 KiB
C++
96 lines
3.3 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/HashMap.h>
|
|
#include <AK/NonnullRefPtr.h>
|
|
#include <LibGfx/Font.h>
|
|
#include <LibGfx/Forward.h>
|
|
#include <LibWeb/CSS/ComputedValues.h>
|
|
#include <LibWeb/CSS/LengthBox.h>
|
|
#include <LibWeb/CSS/StyleValue.h>
|
|
|
|
namespace Web::CSS {
|
|
|
|
class StyleProperties : public RefCounted<StyleProperties> {
|
|
public:
|
|
StyleProperties();
|
|
|
|
explicit StyleProperties(const StyleProperties&);
|
|
|
|
static NonnullRefPtr<StyleProperties> create() { return adopt_ref(*new StyleProperties); }
|
|
|
|
NonnullRefPtr<StyleProperties> clone() const;
|
|
|
|
template<typename Callback>
|
|
inline void for_each_property(Callback callback) const
|
|
{
|
|
for (auto& it : m_property_values)
|
|
callback((CSS::PropertyID)it.key, *it.value);
|
|
}
|
|
|
|
void set_property(CSS::PropertyID, NonnullRefPtr<StyleValue> value);
|
|
void set_property(CSS::PropertyID, const StringView&);
|
|
Optional<NonnullRefPtr<StyleValue>> property(CSS::PropertyID) const;
|
|
|
|
Length length_or_fallback(CSS::PropertyID, const Length& fallback) const;
|
|
LengthBox length_box(CSS::PropertyID left_id, CSS::PropertyID top_id, CSS::PropertyID right_id, CSS::PropertyID bottom_id, const CSS::Length& default_value) const;
|
|
Color color_or_fallback(CSS::PropertyID, Layout::NodeWithStyle const&, Color fallback) const;
|
|
Optional<CSS::TextAlign> text_align() const;
|
|
CSS::Display display() const;
|
|
Optional<CSS::Float> float_() const;
|
|
Optional<CSS::Clear> clear() const;
|
|
Optional<CSS::Cursor> cursor() const;
|
|
Optional<CSS::WhiteSpace> white_space() const;
|
|
Optional<CSS::LineStyle> line_style(CSS::PropertyID) const;
|
|
Optional<CSS::TextDecorationLine> text_decoration_line() const;
|
|
Optional<CSS::TextTransform> text_transform() const;
|
|
Optional<CSS::ListStyleType> list_style_type() const;
|
|
Optional<CSS::FlexDirection> flex_direction() const;
|
|
Optional<CSS::FlexWrap> flex_wrap() const;
|
|
Optional<CSS::FlexBasisData> flex_basis() const;
|
|
Optional<float> flex_grow_factor() const;
|
|
Optional<float> flex_shrink_factor() const;
|
|
Optional<CSS::AlignItems> align_items() const;
|
|
Optional<float> opacity() const;
|
|
Optional<CSS::JustifyContent> justify_content() const;
|
|
Optional<CSS::Overflow> overflow_x() const;
|
|
Optional<CSS::Overflow> overflow_y() const;
|
|
Optional<CSS::Repeat> background_repeat_x() const;
|
|
Optional<CSS::Repeat> background_repeat_y() const;
|
|
Optional<CSS::BoxShadowData> box_shadow() const;
|
|
|
|
Vector<CSS::Transformation> transformations() const;
|
|
|
|
const Gfx::Font& font(Layout::Node const& node) const
|
|
{
|
|
if (!m_font)
|
|
load_font(node);
|
|
return *m_font;
|
|
}
|
|
|
|
float line_height(const Layout::Node&) const;
|
|
|
|
bool operator==(const StyleProperties&) const;
|
|
bool operator!=(const StyleProperties& other) const { return !(*this == other); }
|
|
|
|
Optional<CSS::Position> position() const;
|
|
Optional<int> z_index() const;
|
|
|
|
private:
|
|
friend class StyleResolver;
|
|
|
|
HashMap<CSS::PropertyID, NonnullRefPtr<StyleValue>> m_property_values;
|
|
Optional<CSS::Overflow> overflow(CSS::PropertyID) const;
|
|
|
|
void load_font(Layout::Node const&) const;
|
|
RefPtr<Gfx::Font> font_fallback(bool monospace, bool bold) const;
|
|
|
|
mutable RefPtr<Gfx::Font> m_font;
|
|
};
|
|
|
|
}
|