mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 10:18:11 +00:00
LibHTML: LayoutText should always use parent's style properties
This patch makes StyleProperties heap-allocated and ref-counted so that a LayoutNode can be without one. The ref-counting also allows anonymous blocks to share style with their parent block. LayoutText never needs a StyleProperties, since text always inherits style from its parent element. This is handled by style_properties().
This commit is contained in:
parent
79d8b9ae75
commit
4e35bbffdd
14 changed files with 45 additions and 39 deletions
|
@ -6,8 +6,10 @@
|
||||||
|
|
||||||
class Color;
|
class Color;
|
||||||
|
|
||||||
class StyleProperties {
|
class StyleProperties : public RefCounted<StyleProperties> {
|
||||||
public:
|
public:
|
||||||
|
static NonnullRefPtr<StyleProperties> create() { return adopt(*new StyleProperties); }
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
inline void for_each_property(Callback callback) const
|
inline void for_each_property(Callback callback) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -57,22 +57,22 @@ NonnullRefPtrVector<StyleRule> StyleResolver::collect_matching_rules(const Eleme
|
||||||
return matching_rules;
|
return matching_rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
StyleProperties StyleResolver::resolve_style(const Element& element, const StyleProperties* parent_properties) const
|
NonnullRefPtr<StyleProperties> StyleResolver::resolve_style(const Element& element, const StyleProperties* parent_properties) const
|
||||||
{
|
{
|
||||||
StyleProperties style_properties;
|
auto style_properties = StyleProperties::create();
|
||||||
|
|
||||||
if (parent_properties) {
|
if (parent_properties) {
|
||||||
parent_properties->for_each_property([&](const StringView& name, auto& value) {
|
parent_properties->for_each_property([&](const StringView& name, auto& value) {
|
||||||
// TODO: proper inheritance
|
// TODO: proper inheritance
|
||||||
if (name.starts_with("font") || name == "white-space" || name == "color" || name == "text-decoration")
|
if (name.starts_with("font") || name == "white-space" || name == "color" || name == "text-decoration")
|
||||||
style_properties.set_property(name, value);
|
style_properties->set_property(name, value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto matching_rules = collect_matching_rules(element);
|
auto matching_rules = collect_matching_rules(element);
|
||||||
for (auto& rule : matching_rules) {
|
for (auto& rule : matching_rules) {
|
||||||
for (auto& property : rule.declaration().properties()) {
|
for (auto& property : rule.declaration().properties()) {
|
||||||
style_properties.set_property(property.name, property.value);
|
style_properties->set_property(property.name, property.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ StyleProperties StyleResolver::resolve_style(const Element& element, const Style
|
||||||
if (!style_attribute.is_null()) {
|
if (!style_attribute.is_null()) {
|
||||||
if (auto declaration = parse_css_declaration(style_attribute)) {
|
if (auto declaration = parse_css_declaration(style_attribute)) {
|
||||||
for (auto& property : declaration->properties()) {
|
for (auto& property : declaration->properties()) {
|
||||||
style_properties.set_property(property.name, property.value);
|
style_properties->set_property(property.name, property.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ public:
|
||||||
Document& document() { return m_document; }
|
Document& document() { return m_document; }
|
||||||
const Document& document() const { return m_document; }
|
const Document& document() const { return m_document; }
|
||||||
|
|
||||||
StyleProperties resolve_style(const Element&, const StyleProperties* parent_properties) const;
|
NonnullRefPtr<StyleProperties> resolve_style(const Element&, const StyleProperties* parent_properties) const;
|
||||||
|
|
||||||
NonnullRefPtrVector<StyleRule> collect_matching_rules(const Element&) const;
|
NonnullRefPtrVector<StyleRule> collect_matching_rules(const Element&) const;
|
||||||
|
|
||||||
|
|
|
@ -22,19 +22,16 @@ Node::~Node()
|
||||||
RefPtr<LayoutNode> Node::create_layout_node(const StyleResolver& resolver, const StyleProperties* parent_properties) const
|
RefPtr<LayoutNode> Node::create_layout_node(const StyleResolver& resolver, const StyleProperties* parent_properties) const
|
||||||
{
|
{
|
||||||
if (is_document())
|
if (is_document())
|
||||||
return adopt(*new LayoutDocument(static_cast<const Document&>(*this), {}));
|
return adopt(*new LayoutDocument(static_cast<const Document&>(*this), StyleProperties::create()));
|
||||||
|
|
||||||
StyleProperties style_properties;
|
|
||||||
if (is_element())
|
|
||||||
style_properties = resolver.resolve_style(static_cast<const Element&>(*this), parent_properties);
|
|
||||||
else
|
|
||||||
style_properties = *parent_properties;
|
|
||||||
|
|
||||||
auto display_property = style_properties.property("display");
|
|
||||||
String display = display_property.has_value() ? display_property.release_value()->to_string() : "inline";
|
|
||||||
|
|
||||||
if (is_text())
|
if (is_text())
|
||||||
return adopt(*new LayoutText(static_cast<const Text&>(*this), move(style_properties)));
|
return adopt(*new LayoutText(static_cast<const Text&>(*this)));
|
||||||
|
|
||||||
|
auto style_properties = resolver.resolve_style(static_cast<const Element&>(*this), parent_properties);
|
||||||
|
|
||||||
|
auto display_property = style_properties->property("display");
|
||||||
|
String display = display_property.has_value() ? display_property.release_value()->to_string() : "inline";
|
||||||
|
|
||||||
if (display == "none")
|
if (display == "none")
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (display == "block" || display == "list-item")
|
if (display == "block" || display == "list-item")
|
||||||
|
@ -71,7 +68,7 @@ RefPtr<LayoutNode> Node::create_layout_tree(const StyleResolver& resolver, const
|
||||||
|
|
||||||
for (auto layout_child : layout_children)
|
for (auto layout_child : layout_children)
|
||||||
if (have_block_children && have_inline_children && !layout_child->is_block()) {
|
if (have_block_children && have_inline_children && !layout_child->is_block()) {
|
||||||
if (layout_child->is_text() && static_cast<const LayoutText&>(*layout_child).text() == " ")
|
if (layout_child->is_text() && static_cast<const LayoutText&>(*layout_child).text_for_style(*parent_properties) == " ")
|
||||||
continue;
|
continue;
|
||||||
layout_node->inline_wrapper().append_child(*layout_child);
|
layout_node->inline_wrapper().append_child(*layout_child);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <LibHTML/Layout/LayoutBlock.h>
|
#include <LibHTML/Layout/LayoutBlock.h>
|
||||||
#include <LibHTML/Layout/LayoutInline.h>
|
#include <LibHTML/Layout/LayoutInline.h>
|
||||||
|
|
||||||
LayoutBlock::LayoutBlock(const Node* node, StyleProperties&& style_properties)
|
LayoutBlock::LayoutBlock(const Node* node, NonnullRefPtr<StyleProperties> style_properties)
|
||||||
: LayoutNode(node, move(style_properties))
|
: LayoutNode(node, move(style_properties))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ LayoutBlock::~LayoutBlock()
|
||||||
LayoutNode& LayoutBlock::inline_wrapper()
|
LayoutNode& LayoutBlock::inline_wrapper()
|
||||||
{
|
{
|
||||||
if (!last_child() || !last_child()->is_block() || last_child()->node() != nullptr) {
|
if (!last_child() || !last_child()->is_block() || last_child()->node() != nullptr) {
|
||||||
append_child(adopt(*new LayoutBlock(nullptr, {})));
|
append_child(adopt(*new LayoutBlock(nullptr, style_properties())));
|
||||||
}
|
}
|
||||||
return *last_child();
|
return *last_child();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ class Element;
|
||||||
|
|
||||||
class LayoutBlock : public LayoutNode {
|
class LayoutBlock : public LayoutNode {
|
||||||
public:
|
public:
|
||||||
LayoutBlock(const Node*, StyleProperties&&);
|
LayoutBlock(const Node*, NonnullRefPtr<StyleProperties>);
|
||||||
virtual ~LayoutBlock() override;
|
virtual ~LayoutBlock() override;
|
||||||
|
|
||||||
virtual const char* class_name() const override { return "LayoutBlock"; }
|
virtual const char* class_name() const override { return "LayoutBlock"; }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include <LibHTML/Layout/LayoutDocument.h>
|
#include <LibHTML/Layout/LayoutDocument.h>
|
||||||
|
|
||||||
LayoutDocument::LayoutDocument(const Document& document, StyleProperties&& style_properties)
|
LayoutDocument::LayoutDocument(const Document& document, NonnullRefPtr<StyleProperties> style_properties)
|
||||||
: LayoutBlock(&document, move(style_properties))
|
: LayoutBlock(&document, move(style_properties))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
class LayoutDocument final : public LayoutBlock {
|
class LayoutDocument final : public LayoutBlock {
|
||||||
public:
|
public:
|
||||||
LayoutDocument(const Document&, StyleProperties&&);
|
explicit LayoutDocument(const Document&, NonnullRefPtr<StyleProperties>);
|
||||||
virtual ~LayoutDocument() override;
|
virtual ~LayoutDocument() override;
|
||||||
|
|
||||||
const Document& node() const { return static_cast<const Document&>(*LayoutNode::node()); }
|
const Document& node() const { return static_cast<const Document&>(*LayoutNode::node()); }
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include <LibHTML/Layout/LayoutBlock.h>
|
#include <LibHTML/Layout/LayoutBlock.h>
|
||||||
#include <LibHTML/Layout/LayoutInline.h>
|
#include <LibHTML/Layout/LayoutInline.h>
|
||||||
|
|
||||||
LayoutInline::LayoutInline(const Node& node, StyleProperties&& style_properties)
|
LayoutInline::LayoutInline(const Node& node, RefPtr<StyleProperties> style_properties)
|
||||||
: LayoutNode(&node, move(style_properties))
|
: LayoutNode(&node, move(style_properties))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ class LayoutBlock;
|
||||||
|
|
||||||
class LayoutInline : public LayoutNode {
|
class LayoutInline : public LayoutNode {
|
||||||
public:
|
public:
|
||||||
LayoutInline(const Node&, StyleProperties&&);
|
LayoutInline(const Node&, RefPtr<StyleProperties>);
|
||||||
virtual ~LayoutInline() override;
|
virtual ~LayoutInline() override;
|
||||||
|
|
||||||
virtual const char* class_name() const override { return "LayoutInline"; }
|
virtual const char* class_name() const override { return "LayoutInline"; }
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
//#define DRAW_BOXES_AROUND_LAYOUT_NODES
|
//#define DRAW_BOXES_AROUND_LAYOUT_NODES
|
||||||
//#define DRAW_BOXES_AROUND_HOVERED_NODES
|
//#define DRAW_BOXES_AROUND_HOVERED_NODES
|
||||||
|
|
||||||
LayoutNode::LayoutNode(const Node* node, StyleProperties&& style_properties)
|
LayoutNode::LayoutNode(const Node* node, RefPtr<StyleProperties> style_properties)
|
||||||
: m_node(node)
|
: m_node(node)
|
||||||
, m_style_properties(style_properties)
|
, m_style_properties(move(style_properties))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,18 +62,23 @@ public:
|
||||||
|
|
||||||
virtual LayoutNode& inline_wrapper() { return *this; }
|
virtual LayoutNode& inline_wrapper() { return *this; }
|
||||||
|
|
||||||
const StyleProperties& style_properties() const { return m_style_properties; }
|
const StyleProperties& style_properties() const
|
||||||
|
{
|
||||||
|
if (m_style_properties)
|
||||||
|
return *m_style_properties;
|
||||||
|
return parent()->style_properties();
|
||||||
|
}
|
||||||
|
|
||||||
void inserted_into(LayoutNode&) {}
|
void inserted_into(LayoutNode&) {}
|
||||||
void removed_from(LayoutNode&) {}
|
void removed_from(LayoutNode&) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit LayoutNode(const Node*, StyleProperties&&);
|
explicit LayoutNode(const Node*, RefPtr<StyleProperties>);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Node* m_node { nullptr };
|
const Node* m_node { nullptr };
|
||||||
|
|
||||||
StyleProperties m_style_properties;
|
RefPtr<StyleProperties> m_style_properties;
|
||||||
ComputedStyle m_style;
|
ComputedStyle m_style;
|
||||||
Rect m_rect;
|
Rect m_rect;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
#include <LibHTML/Layout/LayoutText.h>
|
#include <LibHTML/Layout/LayoutText.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
LayoutText::LayoutText(const Text& text, StyleProperties&& style_properties)
|
LayoutText::LayoutText(const Text& text)
|
||||||
: LayoutInline(text, move(style_properties))
|
: LayoutInline(text, {})
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,12 +78,13 @@ static bool is_all_whitespace(const String& string)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const String& LayoutText::text() const
|
const String& LayoutText::text_for_style(const StyleProperties& style_properties) const
|
||||||
{
|
{
|
||||||
static String one_space = " ";
|
static String one_space = " ";
|
||||||
if (is_all_whitespace(node().data()))
|
if (is_all_whitespace(node().data())) {
|
||||||
if (style_properties().string_or_fallback("white-space", "normal") == "normal")
|
if (style_properties.string_or_fallback("white-space", "normal") == "normal")
|
||||||
return one_space;
|
return one_space;
|
||||||
|
}
|
||||||
return node().data();
|
return node().data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,12 @@ class LineBoxFragment;
|
||||||
|
|
||||||
class LayoutText : public LayoutInline {
|
class LayoutText : public LayoutInline {
|
||||||
public:
|
public:
|
||||||
LayoutText(const Text&, StyleProperties&&);
|
explicit LayoutText(const Text&);
|
||||||
virtual ~LayoutText() override;
|
virtual ~LayoutText() override;
|
||||||
|
|
||||||
const Text& node() const { return static_cast<const Text&>(*LayoutNode::node()); }
|
const Text& node() const { return static_cast<const Text&>(*LayoutNode::node()); }
|
||||||
|
|
||||||
const String& text() const;
|
const String& text_for_style(const StyleProperties&) const;
|
||||||
|
|
||||||
virtual const char* class_name() const override { return "LayoutText"; }
|
virtual const char* class_name() const override { return "LayoutText"; }
|
||||||
virtual bool is_text() const final { return true; }
|
virtual bool is_text() const final { return true; }
|
||||||
|
@ -22,6 +22,8 @@ public:
|
||||||
|
|
||||||
virtual void split_into_lines(LayoutBlock& container) override;
|
virtual void split_into_lines(LayoutBlock& container) override;
|
||||||
|
|
||||||
|
const StyleProperties& style_properties() const { return parent()->style_properties(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
void for_each_word(Callback) const;
|
void for_each_word(Callback) const;
|
||||||
|
@ -29,7 +31,6 @@ private:
|
||||||
void for_each_source_line(Callback) const;
|
void for_each_source_line(Callback) const;
|
||||||
|
|
||||||
void load_font();
|
void load_font();
|
||||||
void compute_runs();
|
|
||||||
|
|
||||||
RefPtr<Font> m_font;
|
RefPtr<Font> m_font;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue