diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-10-04 21:05:52 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-10-04 21:05:52 +0200 |
commit | 9808d3555484d0c60f952a0424ccaae9be61ebe3 (patch) | |
tree | e89992729698cae83186d706c5b80d79c194e455 /Libraries | |
parent | a7ca719c4e0d1749ccdaff6ac3eeaca66305614f (diff) | |
download | serenity-9808d3555484d0c60f952a0424ccaae9be61ebe3.zip |
LibHTML: Add support for <body bgcolor="#rrggbb" text="#rrggbb">
This patch implements basic support for presentational hints, which are
old-school HTML attributes that affect style.
You add support for a presentational hint attribute by overriding
Element::apply_presentational_hints(StyleProperties&) and setting all
of the corresponding CSS properties as appropriate.
To make the background color fill the entire document, not just the
bounds of the <body> element's LayoutNode, we special-case it in the
HtmlView::paint_event() code for now. I'm not entirely sure what the
nicest solution would be, but I'm sure we'll discover it eventually.
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibHTML/CSS/StyleResolver.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibHTML/DOM/Document.cpp | 26 | ||||
-rw-r--r-- | Libraries/LibHTML/DOM/Document.h | 4 | ||||
-rw-r--r-- | Libraries/LibHTML/DOM/Element.h | 5 | ||||
-rw-r--r-- | Libraries/LibHTML/DOM/HTMLBodyElement.cpp | 27 | ||||
-rw-r--r-- | Libraries/LibHTML/DOM/HTMLBodyElement.h | 11 | ||||
-rw-r--r-- | Libraries/LibHTML/DOM/Node.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibHTML/DOM/Node.h | 6 | ||||
-rw-r--r-- | Libraries/LibHTML/HtmlView.cpp | 8 | ||||
-rw-r--r-- | Libraries/LibHTML/Layout/LayoutNode.cpp | 4 | ||||
-rw-r--r-- | Libraries/LibHTML/Makefile.shared | 1 | ||||
-rw-r--r-- | Libraries/LibHTML/Parser/HTMLParser.cpp | 3 |
12 files changed, 94 insertions, 5 deletions
diff --git a/Libraries/LibHTML/CSS/StyleResolver.cpp b/Libraries/LibHTML/CSS/StyleResolver.cpp index 4a58de33e2..2d1119d9ea 100644 --- a/Libraries/LibHTML/CSS/StyleResolver.cpp +++ b/Libraries/LibHTML/CSS/StyleResolver.cpp @@ -69,6 +69,8 @@ NonnullRefPtr<StyleProperties> StyleResolver::resolve_style(const Element& eleme }); } + element.apply_presentational_hints(*style_properties); + auto matching_rules = collect_matching_rules(element); for (auto& rule : matching_rules) { for (auto& property : rule.declaration().properties()) { diff --git a/Libraries/LibHTML/DOM/Document.cpp b/Libraries/LibHTML/DOM/Document.cpp index 45482fd91d..97e5873c4f 100644 --- a/Libraries/LibHTML/DOM/Document.cpp +++ b/Libraries/LibHTML/DOM/Document.cpp @@ -1,6 +1,7 @@ #include <LibHTML/CSS/StyleResolver.h> #include <LibHTML/DOM/Document.h> #include <LibHTML/DOM/Element.h> +#include <LibHTML/DOM/HTMLBodyElement.h> #include <LibHTML/DOM/HTMLHeadElement.h> #include <LibHTML/DOM/HTMLHtmlElement.h> #include <LibHTML/DOM/HTMLTitleElement.h> @@ -52,6 +53,14 @@ const HTMLHeadElement* Document::head() const return static_cast<const HTMLHeadElement*>(html->first_child_with_tag_name("head")); } +const HTMLBodyElement* Document::body() const +{ + auto* html = document_element(); + if (!html) + return nullptr; + return static_cast<const HTMLBodyElement*>(html->first_child_with_tag_name("body")); +} + String Document::title() const { auto* head_element = head(); @@ -73,3 +82,20 @@ void Document::attach_to_frame(Badge<Frame>, Frame& frame) void Document::detach_from_frame(Badge<Frame>, Frame&) { } + +Color Document::background_color() const +{ + auto* body_element = body(); + if (!body_element) + return Color::White; + + auto* body_layout_node = body_element->layout_node(); + if (!body_layout_node) + return Color::White; + + auto background_color = body_layout_node->style().property("background-color"); + if (!background_color.has_value() || !background_color.value()->is_color()) + return Color::White; + + return background_color.value()->to_color(); +} diff --git a/Libraries/LibHTML/DOM/Document.h b/Libraries/LibHTML/DOM/Document.h index 46d8fe1581..07ea5454b2 100644 --- a/Libraries/LibHTML/DOM/Document.h +++ b/Libraries/LibHTML/DOM/Document.h @@ -9,6 +9,7 @@ #include <LibHTML/DOM/ParentNode.h> class Frame; +class HTMLBodyElement; class HTMLHtmlElement; class HTMLHeadElement; class LayoutNode; @@ -35,6 +36,7 @@ public: const HTMLHtmlElement* document_element() const; const HTMLHeadElement* head() const; + const HTMLBodyElement* body() const; String title() const; @@ -44,6 +46,8 @@ public: Frame* frame() { return m_frame.ptr(); } const Frame* frame() const { return m_frame.ptr(); } + Color background_color() const; + private: OwnPtr<StyleResolver> m_style_resolver; NonnullRefPtrVector<StyleSheet> m_sheets; diff --git a/Libraries/LibHTML/DOM/Element.h b/Libraries/LibHTML/DOM/Element.h index 42e564ef2e..c01b44d29c 100644 --- a/Libraries/LibHTML/DOM/Element.h +++ b/Libraries/LibHTML/DOM/Element.h @@ -1,7 +1,7 @@ #pragma once -#include <LibHTML/DOM/ParentNode.h> #include <AK/String.h> +#include <LibHTML/DOM/ParentNode.h> class Attribute { public: @@ -42,6 +42,8 @@ public: bool has_class(const StringView&) const; + virtual void apply_presentational_hints(StyleProperties&) const {} + private: Attribute* find_attribute(const String& name); const Attribute* find_attribute(const String& name) const; @@ -49,4 +51,3 @@ private: String m_tag_name; Vector<Attribute> m_attributes; }; - diff --git a/Libraries/LibHTML/DOM/HTMLBodyElement.cpp b/Libraries/LibHTML/DOM/HTMLBodyElement.cpp new file mode 100644 index 0000000000..e993ce470e --- /dev/null +++ b/Libraries/LibHTML/DOM/HTMLBodyElement.cpp @@ -0,0 +1,27 @@ +#include <LibHTML/CSS/StyleProperties.h> +#include <LibHTML/CSS/StyleValue.h> +#include <LibHTML/DOM/HTMLBodyElement.h> + +HTMLBodyElement::HTMLBodyElement(Document& document, const String& tag_name) + : HTMLElement(document, tag_name) +{ +} + +HTMLBodyElement::~HTMLBodyElement() +{ +} + +void HTMLBodyElement::apply_presentational_hints(StyleProperties& style) const +{ + for_each_attribute([&](auto& name, auto& value) { + if (name == "bgcolor") { + auto color = Color::from_string(value); + if (color.has_value()) + style.set_property("background-color", ColorStyleValue::create(color.value())); + } else if (name == "text") { + auto color = Color::from_string(value); + if (color.has_value()) + style.set_property("color", ColorStyleValue::create(color.value())); + } + }); +} diff --git a/Libraries/LibHTML/DOM/HTMLBodyElement.h b/Libraries/LibHTML/DOM/HTMLBodyElement.h new file mode 100644 index 0000000000..2c3a5b3f62 --- /dev/null +++ b/Libraries/LibHTML/DOM/HTMLBodyElement.h @@ -0,0 +1,11 @@ +#pragma once + +#include <LibHTML/DOM/HTMLElement.h> + +class HTMLBodyElement : public HTMLElement { +public: + HTMLBodyElement(Document&, const String& tag_name); + virtual ~HTMLBodyElement() override; + + virtual void apply_presentational_hints(StyleProperties&) const override; +}; diff --git a/Libraries/LibHTML/DOM/Node.cpp b/Libraries/LibHTML/DOM/Node.cpp index b4203cc594..5bfa99895f 100644 --- a/Libraries/LibHTML/DOM/Node.cpp +++ b/Libraries/LibHTML/DOM/Node.cpp @@ -27,6 +27,8 @@ RefPtr<LayoutNode> Node::create_layout_node(const StyleResolver& resolver, const if (is_text()) return adopt(*new LayoutText(static_cast<const Text&>(*this))); + ASSERT(is_element()); + auto style_properties = resolver.resolve_style(static_cast<const Element&>(*this), parent_properties); auto display_property = style_properties->property("display"); diff --git a/Libraries/LibHTML/DOM/Node.h b/Libraries/LibHTML/DOM/Node.h index 2e53fe937a..6c60717670 100644 --- a/Libraries/LibHTML/DOM/Node.h +++ b/Libraries/LibHTML/DOM/Node.h @@ -58,9 +58,15 @@ public: virtual void inserted_into(Node&) {} virtual void removed_from(Node&) {} + const LayoutNode* layout_node() const { return m_layout_node; } + LayoutNode* layout_node() { return m_layout_node; } + + void set_layout_node(Badge<LayoutNode>, LayoutNode* layout_node) const { m_layout_node = layout_node; } + protected: Node(Document&, NodeType); Document& m_document; + mutable LayoutNode* m_layout_node { nullptr }; NodeType m_type { NodeType::INVALID }; }; diff --git a/Libraries/LibHTML/HtmlView.cpp b/Libraries/LibHTML/HtmlView.cpp index fe4c97b4ec..89d4cb8df2 100644 --- a/Libraries/LibHTML/HtmlView.cpp +++ b/Libraries/LibHTML/HtmlView.cpp @@ -78,13 +78,15 @@ void HtmlView::paint_event(GPaintEvent& event) painter.add_clip_rect(widget_inner_rect()); painter.add_clip_rect(event.rect()); - painter.fill_rect(event.rect(), background_color()); + if (!m_layout_root) { + painter.fill_rect(event.rect(), background_color()); + return; + } painter.translate(frame_thickness(), frame_thickness()); painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value()); - if (!m_layout_root) - return; + painter.fill_rect(rect(), m_document->background_color()); RenderingContext context { painter }; m_layout_root->render(context); diff --git a/Libraries/LibHTML/Layout/LayoutNode.cpp b/Libraries/LibHTML/Layout/LayoutNode.cpp index e1d3ebd5be..21f9995421 100644 --- a/Libraries/LibHTML/Layout/LayoutNode.cpp +++ b/Libraries/LibHTML/Layout/LayoutNode.cpp @@ -11,10 +11,14 @@ LayoutNode::LayoutNode(const Node* node, RefPtr<StyleProperties> style_propertie : m_node(node) , m_style_properties(move(style_properties)) { + if (m_node) + m_node->set_layout_node({}, this); } LayoutNode::~LayoutNode() { + if (m_node) + m_node->set_layout_node({}, nullptr); } void LayoutNode::layout() diff --git a/Libraries/LibHTML/Makefile.shared b/Libraries/LibHTML/Makefile.shared index ebbaf69398..3dc2a55276 100644 --- a/Libraries/LibHTML/Makefile.shared +++ b/Libraries/LibHTML/Makefile.shared @@ -10,6 +10,7 @@ LIBHTML_OBJS = \ DOM/HTMLHtmlElement.o \ DOM/HTMLStyleElement.o \ DOM/HTMLTitleElement.o \ + DOM/HTMLBodyElement.o \ DOM/Document.o \ DOM/Text.o \ CSS/Selector.o \ diff --git a/Libraries/LibHTML/Parser/HTMLParser.cpp b/Libraries/LibHTML/Parser/HTMLParser.cpp index afb83e0e67..7c5e568fd8 100644 --- a/Libraries/LibHTML/Parser/HTMLParser.cpp +++ b/Libraries/LibHTML/Parser/HTMLParser.cpp @@ -4,6 +4,7 @@ #include <LibHTML/DOM/Element.h> #include <LibHTML/DOM/HTMLAnchorElement.h> #include <LibHTML/DOM/HTMLHRElement.h> +#include <LibHTML/DOM/HTMLBodyElement.h> #include <LibHTML/DOM/HTMLHeadElement.h> #include <LibHTML/DOM/HTMLHeadingElement.h> #include <LibHTML/DOM/HTMLHtmlElement.h> @@ -23,6 +24,8 @@ static NonnullRefPtr<Element> create_element(Document& document, const String& t return adopt(*new HTMLHtmlElement(document, tag_name)); if (lowercase_tag_name == "head") return adopt(*new HTMLHeadElement(document, tag_name)); + if (lowercase_tag_name == "body") + return adopt(*new HTMLBodyElement(document, tag_name)); if (lowercase_tag_name == "hr") return adopt(*new HTMLHRElement(document, tag_name)); if (lowercase_tag_name == "style") |