Переглянути джерело

LibWeb: Move border width and color into LayoutStyle

To make this possible, I also had to give each LayoutNode a Document&
so it can resolve document-specific colors correctly. There's probably
ways to avoid having this extra member by resolving colors later, but
this works for now.
Andreas Kling 5 роки тому
батько
коміт
440b4ece22
57 змінених файлів з 173 додано та 190 видалено
  1. 1 1
      Libraries/LibWeb/DOM/Document.cpp
  2. 1 1
      Libraries/LibWeb/DOM/Document.h
  3. 9 9
      Libraries/LibWeb/DOM/Element.cpp
  4. 1 1
      Libraries/LibWeb/DOM/Element.h
  5. 2 2
      Libraries/LibWeb/DOM/HTMLBRElement.cpp
  6. 1 1
      Libraries/LibWeb/DOM/HTMLBRElement.h
  7. 2 2
      Libraries/LibWeb/DOM/HTMLCanvasElement.cpp
  8. 1 1
      Libraries/LibWeb/DOM/HTMLCanvasElement.h
  9. 2 2
      Libraries/LibWeb/DOM/HTMLIFrameElement.cpp
  10. 1 1
      Libraries/LibWeb/DOM/HTMLIFrameElement.h
  11. 2 2
      Libraries/LibWeb/DOM/HTMLImageElement.cpp
  12. 1 1
      Libraries/LibWeb/DOM/HTMLImageElement.h
  13. 2 2
      Libraries/LibWeb/DOM/HTMLInputElement.cpp
  14. 1 1
      Libraries/LibWeb/DOM/HTMLInputElement.h
  15. 2 2
      Libraries/LibWeb/DOM/HTMLObjectElement.cpp
  16. 1 1
      Libraries/LibWeb/DOM/HTMLObjectElement.h
  17. 1 1
      Libraries/LibWeb/DOM/Node.cpp
  18. 1 1
      Libraries/LibWeb/DOM/Node.h
  19. 2 2
      Libraries/LibWeb/DOM/Text.cpp
  20. 1 1
      Libraries/LibWeb/DOM/Text.h
  21. 27 37
      Libraries/LibWeb/Layout/LayoutBlock.cpp
  22. 1 1
      Libraries/LibWeb/Layout/LayoutBlock.h
  23. 16 40
      Libraries/LibWeb/Layout/LayoutBox.cpp
  24. 3 3
      Libraries/LibWeb/Layout/LayoutBox.h
  25. 2 2
      Libraries/LibWeb/Layout/LayoutBreak.cpp
  26. 1 1
      Libraries/LibWeb/Layout/LayoutBreak.h
  27. 2 2
      Libraries/LibWeb/Layout/LayoutCanvas.cpp
  28. 1 1
      Libraries/LibWeb/Layout/LayoutCanvas.h
  29. 2 2
      Libraries/LibWeb/Layout/LayoutDocument.cpp
  30. 1 1
      Libraries/LibWeb/Layout/LayoutDocument.h
  31. 2 2
      Libraries/LibWeb/Layout/LayoutFrame.cpp
  32. 1 1
      Libraries/LibWeb/Layout/LayoutFrame.h
  33. 2 2
      Libraries/LibWeb/Layout/LayoutImage.cpp
  34. 1 1
      Libraries/LibWeb/Layout/LayoutImage.h
  35. 2 2
      Libraries/LibWeb/Layout/LayoutInline.cpp
  36. 1 1
      Libraries/LibWeb/Layout/LayoutInline.h
  37. 3 3
      Libraries/LibWeb/Layout/LayoutListItem.cpp
  38. 1 1
      Libraries/LibWeb/Layout/LayoutListItem.h
  39. 2 2
      Libraries/LibWeb/Layout/LayoutListItemMarker.cpp
  40. 1 1
      Libraries/LibWeb/Layout/LayoutListItemMarker.h
  41. 17 21
      Libraries/LibWeb/Layout/LayoutNode.cpp
  42. 9 7
      Libraries/LibWeb/Layout/LayoutNode.h
  43. 2 2
      Libraries/LibWeb/Layout/LayoutReplaced.cpp
  44. 1 1
      Libraries/LibWeb/Layout/LayoutReplaced.h
  45. 19 0
      Libraries/LibWeb/Layout/LayoutStyle.h
  46. 2 2
      Libraries/LibWeb/Layout/LayoutTable.cpp
  47. 1 1
      Libraries/LibWeb/Layout/LayoutTable.h
  48. 2 2
      Libraries/LibWeb/Layout/LayoutTableCell.cpp
  49. 1 1
      Libraries/LibWeb/Layout/LayoutTableCell.h
  50. 2 2
      Libraries/LibWeb/Layout/LayoutTableRow.cpp
  51. 1 1
      Libraries/LibWeb/Layout/LayoutTableRow.h
  52. 2 2
      Libraries/LibWeb/Layout/LayoutTableRowGroup.cpp
  53. 1 1
      Libraries/LibWeb/Layout/LayoutTableRowGroup.h
  54. 2 2
      Libraries/LibWeb/Layout/LayoutText.cpp
  55. 1 1
      Libraries/LibWeb/Layout/LayoutText.h
  56. 2 2
      Libraries/LibWeb/Layout/LayoutWidget.cpp
  57. 1 1
      Libraries/LibWeb/Layout/LayoutWidget.h

+ 1 - 1
Libraries/LibWeb/DOM/Document.cpp

@@ -267,7 +267,7 @@ void Document::update_layout()
     layout();
 }
 
-RefPtr<LayoutNode> Document::create_layout_node(const StyleProperties*) const
+RefPtr<LayoutNode> Document::create_layout_node(const StyleProperties*)
 {
     return adopt(*new LayoutDocument(*this, StyleProperties::create()));
 }

+ 1 - 1
Libraries/LibWeb/DOM/Document.h

@@ -145,7 +145,7 @@ public:
     void set_quirks_mode(bool mode) { m_quirks_mode = mode; }
 
 private:
-    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 
     OwnPtr<StyleResolver> m_style_resolver;
     RefPtr<CSS::StyleSheetList> m_style_sheets;

+ 9 - 9
Libraries/LibWeb/DOM/Element.cpp

@@ -107,7 +107,7 @@ bool Element::has_class(const FlyString& class_name) const
     return false;
 }
 
-RefPtr<LayoutNode> Element::create_layout_node(const StyleProperties* parent_style) const
+RefPtr<LayoutNode> Element::create_layout_node(const StyleProperties* parent_style)
 {
     auto style = document().style_resolver().resolve_style(*this, parent_style);
     const_cast<Element&>(*this).m_resolved_style = style;
@@ -120,21 +120,21 @@ RefPtr<LayoutNode> Element::create_layout_node(const StyleProperties* parent_sty
         return nullptr;
 
     if (display == CSS::Display::Block)
-        return adopt(*new LayoutBlock(this, move(style)));
+        return adopt(*new LayoutBlock(document(), this, move(style)));
     if (display == CSS::Display::Inline)
-        return adopt(*new LayoutInline(*this, move(style)));
+        return adopt(*new LayoutInline(document(), *this, move(style)));
     if (display == CSS::Display::ListItem)
-        return adopt(*new LayoutListItem(*this, move(style)));
+        return adopt(*new LayoutListItem(document(), *this, move(style)));
     if (display == CSS::Display::Table)
-        return adopt(*new LayoutTable(*this, move(style)));
+        return adopt(*new LayoutTable(document(), *this, move(style)));
     if (display == CSS::Display::TableRow)
-        return adopt(*new LayoutTableRow(*this, move(style)));
+        return adopt(*new LayoutTableRow(document(), *this, move(style)));
     if (display == CSS::Display::TableCell)
-        return adopt(*new LayoutTableCell(*this, move(style)));
+        return adopt(*new LayoutTableCell(document(), *this, move(style)));
     if (display == CSS::Display::TableRowGroup)
-        return adopt(*new LayoutTableRowGroup(*this, move(style)));
+        return adopt(*new LayoutTableRowGroup(document(), *this, move(style)));
     if (display == CSS::Display::InlineBlock) {
-        auto inline_block = adopt(*new LayoutBlock(this, move(style)));
+        auto inline_block = adopt(*new LayoutBlock(document(), this, move(style)));
         inline_block->set_inline(true);
         return inline_block;
     }

+ 1 - 1
Libraries/LibWeb/DOM/Element.h

@@ -88,7 +88,7 @@ public:
     void set_class_name(const String& value) { set_attribute(HTML::AttributeNames::class_, value); }
 
 protected:
-    RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+    RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 
 private:
     Attribute* find_attribute(const FlyString& name);

+ 2 - 2
Libraries/LibWeb/DOM/HTMLBRElement.cpp

@@ -38,9 +38,9 @@ HTMLBRElement::~HTMLBRElement()
 {
 }
 
-RefPtr<LayoutNode> HTMLBRElement::create_layout_node(const StyleProperties*) const
+RefPtr<LayoutNode> HTMLBRElement::create_layout_node(const StyleProperties*)
 {
-    return adopt(*new LayoutBreak(*this));
+    return adopt(*new LayoutBreak(document(), *this));
 }
 
 }

+ 1 - 1
Libraries/LibWeb/DOM/HTMLBRElement.h

@@ -35,7 +35,7 @@ public:
     HTMLBRElement(Document&, const FlyString& tag_name);
     virtual ~HTMLBRElement() override;
 
-    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 };
 
 template<>

+ 2 - 2
Libraries/LibWeb/DOM/HTMLCanvasElement.cpp

@@ -55,12 +55,12 @@ unsigned HTMLCanvasElement::height() const
     return attribute(HTML::AttributeNames::height).to_uint().value_or(150);
 }
 
-RefPtr<LayoutNode> HTMLCanvasElement::create_layout_node(const StyleProperties* parent_style) const
+RefPtr<LayoutNode> HTMLCanvasElement::create_layout_node(const StyleProperties* parent_style)
 {
     auto style = document().style_resolver().resolve_style(*this, parent_style);
     if (style->display() == CSS::Display::None)
         return nullptr;
-    return adopt(*new LayoutCanvas(*this, move(style)));
+    return adopt(*new LayoutCanvas(document(), *this, move(style)));
 }
 
 CanvasRenderingContext2D* HTMLCanvasElement::get_context(String type)

+ 1 - 1
Libraries/LibWeb/DOM/HTMLCanvasElement.h

@@ -51,7 +51,7 @@ public:
     unsigned height() const;
 
 private:
-    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 
     RefPtr<Gfx::Bitmap> m_bitmap;
     RefPtr<CanvasRenderingContext2D> m_context;

+ 2 - 2
Libraries/LibWeb/DOM/HTMLIFrameElement.cpp

@@ -50,10 +50,10 @@ HTMLIFrameElement::~HTMLIFrameElement()
 {
 }
 
-RefPtr<LayoutNode> HTMLIFrameElement::create_layout_node(const StyleProperties* parent_style) const
+RefPtr<LayoutNode> HTMLIFrameElement::create_layout_node(const StyleProperties* parent_style)
 {
     auto style = document().style_resolver().resolve_style(*this, parent_style);
-    return adopt(*new LayoutFrame(*this, move(style)));
+    return adopt(*new LayoutFrame(document(), *this, move(style)));
 }
 
 void HTMLIFrameElement::document_did_attach_to_frame(Frame& frame)

+ 1 - 1
Libraries/LibWeb/DOM/HTMLIFrameElement.h

@@ -35,7 +35,7 @@ public:
     HTMLIFrameElement(Document&, const FlyString& tag_name);
     virtual ~HTMLIFrameElement() override;
 
-    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 
     Frame* hosted_frame() { return m_hosted_frame; }
     const Frame* hosted_frame() const { return m_hosted_frame; }

+ 2 - 2
Libraries/LibWeb/DOM/HTMLImageElement.cpp

@@ -68,12 +68,12 @@ void HTMLImageElement::parse_attribute(const FlyString& name, const String& valu
         m_image_loader.load(document().complete_url(value));
 }
 
-RefPtr<LayoutNode> HTMLImageElement::create_layout_node(const StyleProperties* parent_style) const
+RefPtr<LayoutNode> HTMLImageElement::create_layout_node(const StyleProperties* parent_style)
 {
     auto style = document().style_resolver().resolve_style(*this, parent_style);
     if (style->display() == CSS::Display::None)
         return nullptr;
-    return adopt(*new LayoutImage(*this, move(style), m_image_loader));
+    return adopt(*new LayoutImage(document(), *this, move(style), m_image_loader));
 }
 
 const Gfx::Bitmap* HTMLImageElement::bitmap() const

+ 1 - 1
Libraries/LibWeb/DOM/HTMLImageElement.h

@@ -53,7 +53,7 @@ public:
 private:
     void animate();
 
-    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 
     ImageLoader m_image_loader;
 };

+ 2 - 2
Libraries/LibWeb/DOM/HTMLInputElement.cpp

@@ -46,7 +46,7 @@ HTMLInputElement::~HTMLInputElement()
 {
 }
 
-RefPtr<LayoutNode> HTMLInputElement::create_layout_node(const StyleProperties* parent_style) const
+RefPtr<LayoutNode> HTMLInputElement::create_layout_node(const StyleProperties* parent_style)
 {
     ASSERT(document().frame());
     auto& frame = *document().frame();
@@ -97,7 +97,7 @@ RefPtr<LayoutNode> HTMLInputElement::create_layout_node(const StyleProperties* p
         widget = text_box;
     }
 
-    return adopt(*new LayoutWidget(*this, *widget));
+    return adopt(*new LayoutWidget(document(), *this, *widget));
 }
 
 }

+ 1 - 1
Libraries/LibWeb/DOM/HTMLInputElement.h

@@ -35,7 +35,7 @@ public:
     HTMLInputElement(Document&, const FlyString& tag_name);
     virtual ~HTMLInputElement() override;
 
-    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 
     String type() const { return attribute(HTML::AttributeNames::type); }
     String value() const { return attribute(HTML::AttributeNames::value); }

+ 2 - 2
Libraries/LibWeb/DOM/HTMLObjectElement.cpp

@@ -61,7 +61,7 @@ void HTMLObjectElement::parse_attribute(const FlyString& name, const String& val
         m_image_loader.load(document().complete_url(value));
 }
 
-RefPtr<LayoutNode> HTMLObjectElement::create_layout_node(const StyleProperties* parent_style) const
+RefPtr<LayoutNode> HTMLObjectElement::create_layout_node(const StyleProperties* parent_style)
 {
     if (m_should_show_fallback_content)
         return HTMLElement::create_layout_node(parent_style);
@@ -70,7 +70,7 @@ RefPtr<LayoutNode> HTMLObjectElement::create_layout_node(const StyleProperties*
     if (style->display() == CSS::Display::None)
         return nullptr;
     if (m_image_loader.has_image())
-        return adopt(*new LayoutImage(*this, move(style), m_image_loader));
+        return adopt(*new LayoutImage(document(), *this, move(style), m_image_loader));
     return nullptr;
 }
 

+ 1 - 1
Libraries/LibWeb/DOM/HTMLObjectElement.h

@@ -46,7 +46,7 @@ public:
     String type() const { return attribute(HTML::AttributeNames::type); }
 
 private:
-    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 
     ImageLoader m_image_loader;
     bool m_should_show_fallback_content { false };

+ 1 - 1
Libraries/LibWeb/DOM/Node.cpp

@@ -110,7 +110,7 @@ const Element* Node::previous_element_sibling() const
     return nullptr;
 }
 
-RefPtr<LayoutNode> Node::create_layout_node(const StyleProperties*) const
+RefPtr<LayoutNode> Node::create_layout_node(const StyleProperties*)
 {
     return nullptr;
 }

+ 1 - 1
Libraries/LibWeb/DOM/Node.h

@@ -85,7 +85,7 @@ public:
     RefPtr<Node> append_child(NonnullRefPtr<Node>, bool notify = true);
     RefPtr<Node> insert_before(NonnullRefPtr<Node> node, RefPtr<Node> child, bool notify = true);
 
-    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const;
+    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style);
 
     virtual FlyString node_name() const = 0;
 

+ 2 - 2
Libraries/LibWeb/DOM/Text.cpp

@@ -38,9 +38,9 @@ Text::~Text()
 {
 }
 
-RefPtr<LayoutNode> Text::create_layout_node(const StyleProperties*) const
+RefPtr<LayoutNode> Text::create_layout_node(const StyleProperties*)
 {
-    return adopt(*new LayoutText(*this));
+    return adopt(*new LayoutText(document(), *this));
 }
 
 }

+ 1 - 1
Libraries/LibWeb/DOM/Text.h

@@ -40,7 +40,7 @@ public:
     virtual FlyString node_name() const override { return "#text"; }
 
 private:
-    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+    virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
 };
 
 template<>

+ 27 - 37
Libraries/LibWeb/Layout/LayoutBlock.cpp

@@ -38,8 +38,8 @@
 
 namespace Web {
 
-LayoutBlock::LayoutBlock(const Node* node, NonnullRefPtr<StyleProperties> style)
-    : LayoutBox(node, move(style))
+LayoutBlock::LayoutBlock(Document& document, const Node* node, NonnullRefPtr<StyleProperties> style)
+    : LayoutBox(document, node, move(style))
 {
 }
 
@@ -50,7 +50,7 @@ LayoutBlock::~LayoutBlock()
 LayoutNode& LayoutBlock::inline_wrapper()
 {
     if (!last_child() || !last_child()->is_block() || last_child()->node() != nullptr) {
-        append_child(adopt(*new LayoutBlock(nullptr, style_for_anonymous_block())));
+        append_child(adopt(*new LayoutBlock(document(), nullptr, style_for_anonymous_block())));
         last_child()->set_children_are_inline(true);
     }
     return *last_child();
@@ -275,22 +275,20 @@ void LayoutBlock::layout_inline_children(LayoutMode layout_mode)
 
 void LayoutBlock::compute_width_for_absolutely_positioned_block()
 {
-    auto& specified_style = this->specified_style();
     auto& containing_block = *this->containing_block();
     auto zero_value = Length::make_px(0);
 
     Length margin_left = Length::make_auto();
     Length margin_right = Length::make_auto();
-    Length border_left = Length::make_auto();
-    Length border_right = Length::make_auto();
+    const auto border_left = style().border_left().width;
+    const auto border_right = style().border_right().width;
     Length padding_left = Length::make_auto();
     Length padding_right = Length::make_auto();
 
     auto try_compute_width = [&](const auto& a_width) {
         margin_left = style().margin().left.resolved(zero_value, *this, containing_block.width());
         margin_right = style().margin().right.resolved(zero_value, *this, containing_block.width());
-        border_left = specified_style.length_or_fallback(CSS::PropertyID::BorderLeftWidth, zero_value);
-        border_right = specified_style.length_or_fallback(CSS::PropertyID::BorderRightWidth, zero_value);
+
         padding_left = style().padding().left.resolved(zero_value, *this, containing_block.width());
         padding_right = style().padding().right.resolved(zero_value, *this, containing_block.width());
 
@@ -299,15 +297,15 @@ void LayoutBlock::compute_width_for_absolutely_positioned_block()
         auto width = a_width;
 
         auto solve_for_left = [&] {
-            return Length(containing_block.width() - margin_left.to_px(*this) - border_left.to_px(*this) - padding_left.to_px(*this) - width.to_px(*this) - padding_right.to_px(*this) - border_right.to_px(*this) - margin_right.to_px(*this) - right.to_px(*this), Length::Type::Px);
+            return Length(containing_block.width() - margin_left.to_px(*this) - border_left - padding_left.to_px(*this) - width.to_px(*this) - padding_right.to_px(*this) - border_right - margin_right.to_px(*this) - right.to_px(*this), Length::Type::Px);
         };
 
         auto solve_for_width = [&] {
-            return Length(containing_block.width() - left.to_px(*this) - margin_left.to_px(*this) - border_left.to_px(*this) - padding_left.to_px(*this) - padding_right.to_px(*this) - border_right.to_px(*this) - margin_right.to_px(*this) - right.to_px(*this), Length::Type::Px);
+            return Length(containing_block.width() - left.to_px(*this) - margin_left.to_px(*this) - border_left - padding_left.to_px(*this) - padding_right.to_px(*this) - border_right - margin_right.to_px(*this) - right.to_px(*this), Length::Type::Px);
         };
 
         auto solve_for_right = [&] {
-            return Length(containing_block.width() - left.to_px(*this) - margin_left.to_px(*this) - border_left.to_px(*this) - padding_left.to_px(*this) - width.to_px(*this) - padding_right.to_px(*this) - border_right.to_px(*this) - margin_right.to_px(*this), Length::Type::Px);
+            return Length(containing_block.width() - left.to_px(*this) - margin_left.to_px(*this) - border_left - padding_left.to_px(*this) - width.to_px(*this) - padding_right.to_px(*this) - border_right - margin_right.to_px(*this), Length::Type::Px);
         };
 
         // If all three of 'left', 'width', and 'right' are 'auto':
@@ -411,8 +409,8 @@ void LayoutBlock::compute_width_for_absolutely_positioned_block()
 
     box_model().margin.left = margin_left;
     box_model().margin.right = margin_right;
-    box_model().border.left = border_left;
-    box_model().border.right = border_right;
+    box_model().border.left = Length::make_px(border_left);
+    box_model().border.right = Length::make_px(border_right);
     box_model().padding.left = padding_left;
     box_model().padding.right = padding_right;
 }
@@ -422,13 +420,10 @@ void LayoutBlock::compute_width()
     if (is_absolutely_positioned())
         return compute_width_for_absolutely_positioned_block();
 
-    auto& specified_style = this->specified_style();
     auto zero_value = Length::make_px(0);
 
     Length margin_left = Length::make_auto();
     Length margin_right = Length::make_auto();
-    Length border_left = Length::make_auto();
-    Length border_right = Length::make_auto();
     Length padding_left = Length::make_auto();
     Length padding_right = Length::make_auto();
 
@@ -438,13 +433,11 @@ void LayoutBlock::compute_width()
         Length width = a_width;
         margin_left = style().margin().left.resolved_or_zero(*this, containing_block.width());
         margin_right = style().margin().right.resolved_or_zero(*this, containing_block.width());
-        border_left = specified_style.length_or_fallback(CSS::PropertyID::BorderLeftWidth, zero_value);
-        border_right = specified_style.length_or_fallback(CSS::PropertyID::BorderRightWidth, zero_value);
         padding_left = style().padding().left.resolved_or_zero(*this, containing_block.width());
         padding_right = style().padding().right.resolved_or_zero(*this, containing_block.width());
 
-        float total_px = 0;
-        for (auto& value : { margin_left, border_left, padding_left, width, padding_right, border_right, margin_right }) {
+        float total_px = style().border_left().width + style().border_right().width;
+        for (auto& value : { margin_left, padding_left, width, padding_right, margin_right }) {
             total_px += value.to_px(*this);
         }
 
@@ -506,8 +499,8 @@ void LayoutBlock::compute_width()
                 // block minus the used values of 'margin-left', 'border-left-width', 'padding-left',
                 // 'padding-right', 'border-right-width', 'margin-right', and the widths of any relevant scroll bars.
                 float available_width = containing_block.width()
-                    - margin_left.to_px(*this) - border_left.to_px(*this) - padding_left.to_px(*this)
-                    - padding_right.to_px(*this) - border_right.to_px(*this) - margin_right.to_px(*this);
+                    - margin_left.to_px(*this) - style().border_left().width - padding_left.to_px(*this)
+                    - padding_right.to_px(*this) - style().border_right().width - margin_right.to_px(*this);
 
                 auto result = calculate_shrink_to_fit_width();
 
@@ -545,8 +538,8 @@ void LayoutBlock::compute_width()
     set_width(used_width.to_px(*this));
     box_model().margin.left = margin_left;
     box_model().margin.right = margin_right;
-    box_model().border.left = border_left;
-    box_model().border.right = border_right;
+    box_model().border.left = Length::make_px(style().border_left().width);
+    box_model().border.right = Length::make_px(style().border_right().width);
     box_model().padding.left = padding_left;
     box_model().padding.right = padding_right;
 }
@@ -554,16 +547,15 @@ void LayoutBlock::compute_width()
 void LayoutBlock::place_block_level_replaced_element_in_normal_flow(LayoutReplaced& box)
 {
     ASSERT(!is_absolutely_positioned());
-    auto& specified_style = box.specified_style();
     auto& containing_block = *this;
     auto& replaced_element_box_model = box.box_model();
 
-    replaced_element_box_model.margin.top = style().margin().top.resolved_or_zero(*this, containing_block.width());
-    replaced_element_box_model.margin.bottom = style().margin().bottom.resolved_or_zero(*this, containing_block.width());
-    replaced_element_box_model.border.top = specified_style.length_or_fallback(CSS::PropertyID::BorderTopWidth, Length::make_px(0));
-    replaced_element_box_model.border.bottom = specified_style.length_or_fallback(CSS::PropertyID::BorderBottomWidth, Length::make_px(0));
-    replaced_element_box_model.padding.top = style().padding().top.resolved_or_zero(*this, containing_block.width());
-    replaced_element_box_model.padding.bottom = style().padding().bottom.resolved_or_zero(*this, containing_block.width());
+    replaced_element_box_model.margin.top = box.style().margin().top.resolved_or_zero(*this, containing_block.width());
+    replaced_element_box_model.margin.bottom = box.style().margin().bottom.resolved_or_zero(*this, containing_block.width());
+    replaced_element_box_model.border.top = Length::make_px(box.style().border_top().width);
+    replaced_element_box_model.border.bottom = Length::make_px(box.style().border_bottom().width);
+    replaced_element_box_model.padding.top = box.style().padding().top.resolved_or_zero(*this, containing_block.width());
+    replaced_element_box_model.padding.bottom = box.style().padding().bottom.resolved_or_zero(*this, containing_block.width());
 
     float x = replaced_element_box_model.margin.left.to_px(*this)
         + replaced_element_box_model.border.left.to_px(*this)
@@ -608,7 +600,6 @@ LayoutBlock::ShrinkToFitResult LayoutBlock::calculate_shrink_to_fit_width()
 
 void LayoutBlock::place_block_level_non_replaced_element_in_normal_flow(LayoutBlock& block)
 {
-    auto& specified_style = block.specified_style();
     auto zero_value = Length::make_px(0);
     auto& containing_block = *this;
     auto& box = block.box_model();
@@ -616,8 +607,8 @@ void LayoutBlock::place_block_level_non_replaced_element_in_normal_flow(LayoutBl
 
     box.margin.top = style.margin().top.resolved(zero_value, *this, containing_block.width());
     box.margin.bottom = style.margin().bottom.resolved(zero_value, *this, containing_block.width());
-    box.border.top = specified_style.length_or_fallback(CSS::PropertyID::BorderTopWidth, zero_value);
-    box.border.bottom = specified_style.length_or_fallback(CSS::PropertyID::BorderBottomWidth, zero_value);
+    box.border.top = Length::make_px(style.border_top().width);
+    box.border.bottom = Length::make_px(style.border_bottom().width);
     box.padding.top = style.padding().top.resolved(zero_value, *this, containing_block.width());
     box.padding.bottom = style.padding().bottom.resolved(zero_value, *this, containing_block.width());
 
@@ -665,7 +656,6 @@ void LayoutBlock::place_block_level_non_replaced_element_in_normal_flow(LayoutBl
 
 void LayoutBlock::compute_height()
 {
-    auto& specified_style = this->specified_style();
     auto& containing_block = *this->containing_block();
 
     auto specified_height = style().height().resolved_or_auto(*this, containing_block.height());
@@ -673,8 +663,8 @@ void LayoutBlock::compute_height()
 
     box_model().margin.top = style().margin().top.resolved_or_zero(*this, containing_block.width());
     box_model().margin.bottom = style().margin().bottom.resolved_or_zero(*this, containing_block.width());
-    box_model().border.top = specified_style.length_or_fallback(CSS::PropertyID::BorderTopWidth, Length::make_px(0));
-    box_model().border.bottom = specified_style.length_or_fallback(CSS::PropertyID::BorderBottomWidth, Length::make_px(0));
+    box_model().border.top = Length::make_px(style().border_top().width);
+    box_model().border.bottom = Length::make_px(style().border_bottom().width);
     box_model().padding.top = style().padding().top.resolved_or_zero(*this, containing_block.width());
     box_model().padding.bottom = style().padding().bottom.resolved_or_zero(*this, containing_block.width());
 

+ 1 - 1
Libraries/LibWeb/Layout/LayoutBlock.h

@@ -35,7 +35,7 @@ class Element;
 
 class LayoutBlock : public LayoutBox {
 public:
-    LayoutBlock(const Node*, NonnullRefPtr<StyleProperties>);
+    LayoutBlock(Document&, const Node*, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutBlock() override;
 
     virtual const char* class_name() const override { return "LayoutBlock"; }

+ 16 - 40
Libraries/LibWeb/Layout/LayoutBox.cpp

@@ -33,33 +33,16 @@
 
 namespace Web {
 
-void LayoutBox::paint_border(PaintContext& context, Edge edge, const Gfx::FloatRect& rect, CSS::PropertyID style_property_id, CSS::PropertyID color_property_id, CSS::PropertyID width_property_id)
+void LayoutBox::paint_border(PaintContext& context, Edge edge, const Gfx::FloatRect& rect, CSS::PropertyID style_property_id, const BorderData& border_data)
 {
-    auto border_width = specified_style().property(width_property_id);
-    if (!border_width.has_value())
-        return;
-
-    auto border_style = specified_style().property(style_property_id);
-    float width = border_width.value()->to_length().to_px(*this);
+    float width = border_data.width;
     if (width <= 0)
         return;
 
+    auto color = border_data.color;
+    auto border_style = specified_style().property(style_property_id);
     int int_width = max((int)width, 1);
 
-    Color color;
-    auto border_color = specified_style().property(color_property_id);
-    if (border_color.has_value()) {
-        color = border_color.value()->to_color(document());
-    } else {
-        // FIXME: This is basically CSS "currentColor" which should be handled elsewhere
-        //        in a much more reusable way.
-        auto current_color = specified_style().property(CSS::PropertyID::Color);
-        if (current_color.has_value())
-            color = current_color.value()->to_color(document());
-        else
-            color = Color::Black;
-    }
-
     auto first_point_for_edge = [](Edge edge, const Gfx::FloatRect& rect) {
         switch (edge) {
         case Edge::Top:
@@ -136,20 +119,13 @@ void LayoutBox::paint_border(PaintContext& context, Edge edge, const Gfx::FloatR
         context.painter().draw_line({ (int)p1.x(), (int)p1.y() }, { (int)p2.x(), (int)p2.y() }, color, 1, line_style);
     };
 
-    auto width_for = [&](CSS::PropertyID property_id) -> float {
-        auto width = specified_style().property(property_id);
-        if (!width.has_value())
-            return 0;
-        return width.value()->to_length().to_px(*this);
-    };
-
     float p1_step = 0;
     float p2_step = 0;
 
     switch (edge) {
     case Edge::Top:
-        p1_step = width_for(CSS::PropertyID::BorderLeftWidth) / (float)int_width;
-        p2_step = width_for(CSS::PropertyID::BorderRightWidth) / (float)int_width;
+        p1_step = style().border_left().width / (float)int_width;
+        p2_step = style().border_right().width / (float)int_width;
         for (int i = 0; i < int_width; ++i) {
             draw_line(p1, p2);
             p1.move_by(p1_step, 1);
@@ -157,8 +133,8 @@ void LayoutBox::paint_border(PaintContext& context, Edge edge, const Gfx::FloatR
         }
         break;
     case Edge::Right:
-        p1_step = width_for(CSS::PropertyID::BorderTopWidth) / (float)int_width;
-        p2_step = width_for(CSS::PropertyID::BorderBottomWidth) / (float)int_width;
+        p1_step = style().border_top().width / (float)int_width;
+        p2_step = style().border_bottom().width / (float)int_width;
         for (int i = int_width - 1; i >= 0; --i) {
             draw_line(p1, p2);
             p1.move_by(-1, p1_step);
@@ -166,8 +142,8 @@ void LayoutBox::paint_border(PaintContext& context, Edge edge, const Gfx::FloatR
         }
         break;
     case Edge::Bottom:
-        p1_step = width_for(CSS::PropertyID::BorderLeftWidth) / (float)int_width;
-        p2_step = width_for(CSS::PropertyID::BorderRightWidth) / (float)int_width;
+        p1_step = style().border_left().width / (float)int_width;
+        p2_step = style().border_right().width / (float)int_width;
         for (int i = int_width - 1; i >= 0; --i) {
             draw_line(p1, p2);
             p1.move_by(p1_step, -1);
@@ -175,8 +151,8 @@ void LayoutBox::paint_border(PaintContext& context, Edge edge, const Gfx::FloatR
         }
         break;
     case Edge::Left:
-        p1_step = width_for(CSS::PropertyID::BorderTopWidth) / (float)int_width;
-        p2_step = width_for(CSS::PropertyID::BorderBottomWidth) / (float)int_width;
+        p1_step = style().border_top().width / (float)int_width;
+        p2_step = style().border_bottom().width / (float)int_width;
         for (int i = 0; i < int_width; ++i) {
             draw_line(p1, p2);
             p1.move_by(1, p1_step);
@@ -224,10 +200,10 @@ void LayoutBox::paint(PaintContext& context, PaintPhase phase)
         bordered_rect.set_y(padded_rect.y() - box_model().border.top.to_px(*this));
         bordered_rect.set_height(padded_rect.height() + box_model().border.top.to_px(*this) + box_model().border.bottom.to_px(*this));
 
-        paint_border(context, Edge::Left, bordered_rect, CSS::PropertyID::BorderLeftStyle, CSS::PropertyID::BorderLeftColor, CSS::PropertyID::BorderLeftWidth);
-        paint_border(context, Edge::Right, bordered_rect, CSS::PropertyID::BorderRightStyle, CSS::PropertyID::BorderRightColor, CSS::PropertyID::BorderRightWidth);
-        paint_border(context, Edge::Top, bordered_rect, CSS::PropertyID::BorderTopStyle, CSS::PropertyID::BorderTopColor, CSS::PropertyID::BorderTopWidth);
-        paint_border(context, Edge::Bottom, bordered_rect, CSS::PropertyID::BorderBottomStyle, CSS::PropertyID::BorderBottomColor, CSS::PropertyID::BorderBottomWidth);
+        paint_border(context, Edge::Left, bordered_rect, CSS::PropertyID::BorderLeftStyle, style().border_left());
+        paint_border(context, Edge::Right, bordered_rect, CSS::PropertyID::BorderRightStyle, style().border_right());
+        paint_border(context, Edge::Top, bordered_rect, CSS::PropertyID::BorderTopStyle, style().border_top());
+        paint_border(context, Edge::Bottom, bordered_rect, CSS::PropertyID::BorderBottomStyle, style().border_bottom());
     }
 
     LayoutNodeWithStyleAndBoxModelMetrics::paint(context, phase);

+ 3 - 3
Libraries/LibWeb/Layout/LayoutBox.h

@@ -70,8 +70,8 @@ public:
     virtual void paint(PaintContext&, PaintPhase) override;
 
 protected:
-    LayoutBox(const Node* node, NonnullRefPtr<StyleProperties> style)
-        : LayoutNodeWithStyleAndBoxModelMetrics(node, move(style))
+    LayoutBox(Document& document, const Node* node, NonnullRefPtr<StyleProperties> style)
+        : LayoutNodeWithStyleAndBoxModelMetrics(document, node, move(style))
     {
     }
 
@@ -86,7 +86,7 @@ private:
         Bottom,
         Left,
     };
-    void paint_border(PaintContext&, Edge, const Gfx::FloatRect&, CSS::PropertyID style_property_id, CSS::PropertyID color_property_id, CSS::PropertyID width_property_id);
+    void paint_border(PaintContext&, Edge, const Gfx::FloatRect&, CSS::PropertyID style_property_id, const BorderData&);
 
     Gfx::FloatPoint m_offset;
     Gfx::FloatSize m_size;

+ 2 - 2
Libraries/LibWeb/Layout/LayoutBreak.cpp

@@ -29,8 +29,8 @@
 
 namespace Web {
 
-LayoutBreak::LayoutBreak(const HTMLBRElement& element)
-    : LayoutNodeWithStyleAndBoxModelMetrics(&element, StyleProperties::create())
+LayoutBreak::LayoutBreak(Document& document, const HTMLBRElement& element)
+    : LayoutNodeWithStyleAndBoxModelMetrics(document, &element, StyleProperties::create())
 {
     set_inline(true);
 }

+ 1 - 1
Libraries/LibWeb/Layout/LayoutBreak.h

@@ -33,7 +33,7 @@ namespace Web {
 
 class LayoutBreak final : public LayoutNodeWithStyleAndBoxModelMetrics {
 public:
-    explicit LayoutBreak(const HTMLBRElement&);
+    LayoutBreak(Document&, const HTMLBRElement&);
     virtual ~LayoutBreak() override;
 
     const HTMLBRElement& node() const { return to<HTMLBRElement>(*LayoutNode::node()); }

+ 2 - 2
Libraries/LibWeb/Layout/LayoutCanvas.cpp

@@ -31,8 +31,8 @@
 
 namespace Web {
 
-LayoutCanvas::LayoutCanvas(const HTMLCanvasElement& element, NonnullRefPtr<StyleProperties> style)
-    : LayoutReplaced(element, move(style))
+LayoutCanvas::LayoutCanvas(Document& document, const HTMLCanvasElement& element, NonnullRefPtr<StyleProperties> style)
+    : LayoutReplaced(document, element, move(style))
 {
 }
 

+ 1 - 1
Libraries/LibWeb/Layout/LayoutCanvas.h

@@ -35,7 +35,7 @@ class HTMLCanvasElement;
 
 class LayoutCanvas : public LayoutReplaced {
 public:
-    LayoutCanvas(const HTMLCanvasElement&, NonnullRefPtr<StyleProperties>);
+    LayoutCanvas(Document&, const HTMLCanvasElement&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutCanvas() override;
 
     virtual void layout(LayoutMode = LayoutMode::Default) override;

+ 2 - 2
Libraries/LibWeb/Layout/LayoutDocument.cpp

@@ -33,8 +33,8 @@
 
 namespace Web {
 
-LayoutDocument::LayoutDocument(const Document& document, NonnullRefPtr<StyleProperties> style)
-    : LayoutBlock(&document, move(style))
+LayoutDocument::LayoutDocument(Document& document, NonnullRefPtr<StyleProperties> style)
+    : LayoutBlock(document, &document, move(style))
 {
 }
 

+ 1 - 1
Libraries/LibWeb/Layout/LayoutDocument.h

@@ -33,7 +33,7 @@ namespace Web {
 
 class LayoutDocument final : public LayoutBlock {
 public:
-    explicit LayoutDocument(const Document&, NonnullRefPtr<StyleProperties>);
+    explicit LayoutDocument(Document&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutDocument() override;
 
     const Document& node() const { return static_cast<const Document&>(*LayoutNode::node()); }

+ 2 - 2
Libraries/LibWeb/Layout/LayoutFrame.cpp

@@ -37,8 +37,8 @@
 
 namespace Web {
 
-LayoutFrame::LayoutFrame(const Element& element, NonnullRefPtr<StyleProperties> style)
-    : LayoutReplaced(element, move(style))
+LayoutFrame::LayoutFrame(Document& document, const Element& element, NonnullRefPtr<StyleProperties> style)
+    : LayoutReplaced(document, element, move(style))
 {
 }
 

+ 1 - 1
Libraries/LibWeb/Layout/LayoutFrame.h

@@ -33,7 +33,7 @@ namespace Web {
 
 class LayoutFrame final : public LayoutReplaced {
 public:
-    LayoutFrame(const Element&, NonnullRefPtr<StyleProperties>);
+    LayoutFrame(Document&, const Element&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutFrame() override;
 
     virtual void paint(PaintContext&, PaintPhase) override;

+ 2 - 2
Libraries/LibWeb/Layout/LayoutImage.cpp

@@ -32,8 +32,8 @@
 
 namespace Web {
 
-LayoutImage::LayoutImage(const Element& element, NonnullRefPtr<StyleProperties> style, const ImageLoader& image_loader)
-    : LayoutReplaced(element, move(style))
+LayoutImage::LayoutImage(Document& document, const Element& element, NonnullRefPtr<StyleProperties> style, const ImageLoader& image_loader)
+    : LayoutReplaced(document, element, move(style))
     , m_image_loader(image_loader)
 {
 }

+ 1 - 1
Libraries/LibWeb/Layout/LayoutImage.h

@@ -35,7 +35,7 @@ class HTMLImageElement;
 
 class LayoutImage : public LayoutReplaced {
 public:
-    LayoutImage(const Element&, NonnullRefPtr<StyleProperties>, const ImageLoader&);
+    LayoutImage(Document&, const Element&, NonnullRefPtr<StyleProperties>, const ImageLoader&);
     virtual ~LayoutImage() override;
 
     virtual void layout(LayoutMode = LayoutMode::Default) override;

+ 2 - 2
Libraries/LibWeb/Layout/LayoutInline.cpp

@@ -30,8 +30,8 @@
 
 namespace Web {
 
-LayoutInline::LayoutInline(const Element& element, NonnullRefPtr<StyleProperties> style)
-    : LayoutNodeWithStyleAndBoxModelMetrics(&element, move(style))
+LayoutInline::LayoutInline(Document& document, const Element& element, NonnullRefPtr<StyleProperties> style)
+    : LayoutNodeWithStyleAndBoxModelMetrics(document, &element, move(style))
 {
     set_inline(true);
 }

+ 1 - 1
Libraries/LibWeb/Layout/LayoutInline.h

@@ -34,7 +34,7 @@ class LayoutBlock;
 
 class LayoutInline : public LayoutNodeWithStyleAndBoxModelMetrics {
 public:
-    LayoutInline(const Element&, NonnullRefPtr<StyleProperties>);
+    LayoutInline(Document&, const Element&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutInline() override;
     virtual const char* class_name() const override { return "LayoutInline"; }
 };

+ 3 - 3
Libraries/LibWeb/Layout/LayoutListItem.cpp

@@ -29,8 +29,8 @@
 
 namespace Web {
 
-LayoutListItem::LayoutListItem(const Element& element, NonnullRefPtr<StyleProperties> style)
-    : LayoutBlock(&element, move(style))
+LayoutListItem::LayoutListItem(Document& document, const Element& element, NonnullRefPtr<StyleProperties> style)
+    : LayoutBlock(document, &element, move(style))
 {
 }
 
@@ -52,7 +52,7 @@ void LayoutListItem::layout(LayoutMode layout_mode)
     }
 
     if (!m_marker) {
-        m_marker = adopt(*new LayoutListItemMarker);
+        m_marker = adopt(*new LayoutListItemMarker(document()));
         if (first_child())
             m_marker->set_inline(first_child()->is_inline());
         append_child(*m_marker);

+ 1 - 1
Libraries/LibWeb/Layout/LayoutListItem.h

@@ -35,7 +35,7 @@ class LayoutListItemMarker;
 
 class LayoutListItem final : public LayoutBlock {
 public:
-    LayoutListItem(const Element&, NonnullRefPtr<StyleProperties>);
+    LayoutListItem(Document&, const Element&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutListItem() override;
 
     virtual void layout(LayoutMode = LayoutMode::Default) override;

+ 2 - 2
Libraries/LibWeb/Layout/LayoutListItemMarker.cpp

@@ -29,8 +29,8 @@
 
 namespace Web {
 
-LayoutListItemMarker::LayoutListItemMarker()
-    : LayoutBox(nullptr, StyleProperties::create())
+LayoutListItemMarker::LayoutListItemMarker(Document& document)
+    : LayoutBox(document, nullptr, StyleProperties::create())
 {
 }
 

+ 1 - 1
Libraries/LibWeb/Layout/LayoutListItemMarker.h

@@ -32,7 +32,7 @@ namespace Web {
 
 class LayoutListItemMarker final : public LayoutBox {
 public:
-    LayoutListItemMarker();
+    explicit LayoutListItemMarker(Document&);
     virtual ~LayoutListItemMarker() override;
 
     virtual void paint(PaintContext&, PaintPhase) override;

+ 17 - 21
Libraries/LibWeb/Layout/LayoutNode.cpp

@@ -35,8 +35,9 @@
 
 namespace Web {
 
-LayoutNode::LayoutNode(const Node* node)
-    : m_node(node)
+LayoutNode::LayoutNode(Document& document, const Node* node)
+    : m_document(document)
+    , m_node(node)
 {
     if (m_node)
         m_node->set_layout_node({}, this);
@@ -124,21 +125,6 @@ Frame& LayoutNode::frame()
     return *document().frame();
 }
 
-const Document& LayoutNode::document() const
-{
-    if (is_anonymous())
-        return parent()->document();
-    return node()->document();
-}
-
-Document& LayoutNode::document()
-{
-    if (is_anonymous())
-        return parent()->document();
-    // FIXME: Remove this const_cast once we give up on the idea of a const link from layout tree to DOM tree.
-    return const_cast<Node*>(node())->document();
-}
-
 const LayoutDocument& LayoutNode::root() const
 {
     ASSERT(document().layout_node());
@@ -211,12 +197,12 @@ bool LayoutNode::is_fixed_position() const
     return position == CSS::Position::Fixed;
 }
 
-LayoutNodeWithStyle::LayoutNodeWithStyle(const Node* node, NonnullRefPtr<StyleProperties> style)
-    : LayoutNode(node)
-    , m_specified_style(move(style))
+LayoutNodeWithStyle::LayoutNodeWithStyle(Document& document, const Node* node, NonnullRefPtr<StyleProperties> specified_style)
+    : LayoutNode(document, node)
+    , m_specified_style(move(specified_style))
 {
     m_has_style = true;
-    apply_style(this->specified_style());
+    apply_style(*m_specified_style);
 }
 
 void LayoutNodeWithStyle::apply_style(const StyleProperties& specified_style)
@@ -241,6 +227,16 @@ void LayoutNodeWithStyle::apply_style(const StyleProperties& specified_style)
     style.set_offset(specified_style.length_box(CSS::PropertyID::Left, CSS::PropertyID::Top, CSS::PropertyID::Right, CSS::PropertyID::Bottom));
     style.set_margin(specified_style.length_box(CSS::PropertyID::MarginLeft, CSS::PropertyID::MarginTop, CSS::PropertyID::MarginRight, CSS::PropertyID::MarginBottom));
     style.set_padding(specified_style.length_box(CSS::PropertyID::PaddingLeft, CSS::PropertyID::PaddingTop, CSS::PropertyID::PaddingRight, CSS::PropertyID::PaddingBottom));
+
+    style.border_left().width = specified_style.length_or_fallback(CSS::PropertyID::BorderLeftWidth, {}).resolved_or_zero(*this, 0).to_px(*this);
+    style.border_top().width = specified_style.length_or_fallback(CSS::PropertyID::BorderTopWidth, {}).resolved_or_zero(*this, 0).to_px(*this);
+    style.border_right().width = specified_style.length_or_fallback(CSS::PropertyID::BorderRightWidth, {}).resolved_or_zero(*this, 0).to_px(*this);
+    style.border_bottom().width = specified_style.length_or_fallback(CSS::PropertyID::BorderBottomWidth, {}).resolved_or_zero(*this, 0).to_px(*this);
+
+    style.border_left().color = specified_style.color_or_fallback(CSS::PropertyID::BorderLeftColor, document(), Color::Transparent);
+    style.border_top().color = specified_style.color_or_fallback(CSS::PropertyID::BorderTopColor, document(), Color::Transparent);
+    style.border_right().color = specified_style.color_or_fallback(CSS::PropertyID::BorderRightColor, document(), Color::Transparent);
+    style.border_bottom().color = specified_style.color_or_fallback(CSS::PropertyID::BorderBottomColor, document(), Color::Transparent);
 }
 
 }

+ 9 - 7
Libraries/LibWeb/Layout/LayoutNode.h

@@ -101,8 +101,8 @@ public:
     const Node* node() const { return m_node; }
     Node* node() { return const_cast<Node*>(m_node); }
 
-    Document& document();
-    const Document& document() const;
+    Document& document() { return m_document; }
+    const Document& document() const { return m_document; }
 
     const Frame& frame() const;
     Frame& frame();
@@ -239,11 +239,12 @@ public:
     float font_size() const;
 
 protected:
-    explicit LayoutNode(const Node*);
+    LayoutNode(Document&, const Node*);
 
 private:
     friend class LayoutNodeWithStyle;
 
+    Document& m_document;
     const Node* m_node { nullptr };
 
     bool m_inline { false };
@@ -261,11 +262,12 @@ public:
 
     const ImmutableLayoutStyle& style() const { return static_cast<const ImmutableLayoutStyle&>(m_style); }
 
+    void apply_style(const StyleProperties&);
+
 protected:
-    explicit LayoutNodeWithStyle(const Node*, NonnullRefPtr<StyleProperties>);
+    LayoutNodeWithStyle(Document&, const Node*, NonnullRefPtr<StyleProperties>);
 
 private:
-    void apply_style(const StyleProperties&);
 
     LayoutStyle m_style;
 
@@ -280,8 +282,8 @@ public:
     const BoxModelMetrics& box_model() const { return m_box_model; }
 
 protected:
-    LayoutNodeWithStyleAndBoxModelMetrics(const Node* node, NonnullRefPtr<StyleProperties> style)
-        : LayoutNodeWithStyle(node, move(style))
+    LayoutNodeWithStyleAndBoxModelMetrics(Document& document, const Node* node, NonnullRefPtr<StyleProperties> style)
+        : LayoutNodeWithStyle(document, node, move(style))
     {
     }
 

+ 2 - 2
Libraries/LibWeb/Layout/LayoutReplaced.cpp

@@ -30,8 +30,8 @@
 
 namespace Web {
 
-LayoutReplaced::LayoutReplaced(const Element& element, NonnullRefPtr<StyleProperties> style)
-    : LayoutBox(&element, move(style))
+LayoutReplaced::LayoutReplaced(Document& document, const Element& element, NonnullRefPtr<StyleProperties> style)
+    : LayoutBox(document, &element, move(style))
 {
     // FIXME: Allow non-inline replaced elements.
     set_inline(true);

+ 1 - 1
Libraries/LibWeb/Layout/LayoutReplaced.h

@@ -33,7 +33,7 @@ namespace Web {
 
 class LayoutReplaced : public LayoutBox {
 public:
-    LayoutReplaced(const Element&, NonnullRefPtr<StyleProperties>);
+    LayoutReplaced(Document&, const Element&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutReplaced() override;
 
     const Element& node() const { return to<Element>(*LayoutNode::node()); }

+ 19 - 0
Libraries/LibWeb/Layout/LayoutStyle.h

@@ -37,6 +37,12 @@ public:
     static CSS::WhiteSpace white_space() { return CSS::WhiteSpace::Normal; }
 };
 
+struct BorderData {
+public:
+    Color color { Color::Transparent };
+    float width { 0 };
+};
+
 class LayoutStyle {
 public:
     Optional<int> z_index() const { return m_z_index; }
@@ -54,6 +60,11 @@ public:
     const LengthBox& margin() const { return m_margin; }
     const LengthBox& padding() const { return m_padding; }
 
+    const BorderData& border_left() const { return m_border_left; }
+    const BorderData& border_top() const { return m_border_top; }
+    const BorderData& border_right() const { return m_border_right; }
+    const BorderData& border_bottom() const { return m_border_bottom; }
+
 protected:
     Optional<int> m_z_index;
     CSS::TextAlign m_text_align;
@@ -68,6 +79,10 @@ protected:
     LengthBox m_offset;
     LengthBox m_margin;
     LengthBox m_padding;
+    BorderData m_border_left;
+    BorderData m_border_top;
+    BorderData m_border_right;
+    BorderData m_border_bottom;
 };
 
 class ImmutableLayoutStyle final : public LayoutStyle {
@@ -88,6 +103,10 @@ public:
     void set_offset(const LengthBox& offset) { m_offset = offset; }
     void set_margin(const LengthBox& margin) { m_margin = margin; }
     void set_padding(const LengthBox& padding) { m_padding = padding; }
+    BorderData& border_left() { return m_border_left; }
+    BorderData& border_top() { return m_border_top; }
+    BorderData& border_right() { return m_border_right; }
+    BorderData& border_bottom() { return m_border_bottom; }
 };
 
 }

+ 2 - 2
Libraries/LibWeb/Layout/LayoutTable.cpp

@@ -30,8 +30,8 @@
 
 namespace Web {
 
-LayoutTable::LayoutTable(const Element& element, NonnullRefPtr<StyleProperties> style)
-    : LayoutBlock(&element, move(style))
+LayoutTable::LayoutTable(Document& document, const Element& element, NonnullRefPtr<StyleProperties> style)
+    : LayoutBlock(document, &element, move(style))
 {
 }
 

+ 1 - 1
Libraries/LibWeb/Layout/LayoutTable.h

@@ -34,7 +34,7 @@ class LayoutTableRow;
 
 class LayoutTable final : public LayoutBlock {
 public:
-    LayoutTable(const Element&, NonnullRefPtr<StyleProperties>);
+    LayoutTable(Document&, const Element&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutTable() override;
 
     virtual void layout(LayoutMode = LayoutMode::Default) override;

+ 2 - 2
Libraries/LibWeb/Layout/LayoutTableCell.cpp

@@ -29,8 +29,8 @@
 
 namespace Web {
 
-LayoutTableCell::LayoutTableCell(const Element& element, NonnullRefPtr<StyleProperties> style)
-    : LayoutBlock(&element, move(style))
+LayoutTableCell::LayoutTableCell(Document& document, const Element& element, NonnullRefPtr<StyleProperties> style)
+    : LayoutBlock(document, &element, move(style))
 {
 }
 

+ 1 - 1
Libraries/LibWeb/Layout/LayoutTableCell.h

@@ -32,7 +32,7 @@ namespace Web {
 
 class LayoutTableCell final : public LayoutBlock {
 public:
-    LayoutTableCell(const Element&, NonnullRefPtr<StyleProperties>);
+    LayoutTableCell(Document&, const Element&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutTableCell() override;
 
     LayoutTableCell* next_cell() { return next_sibling_of_type<LayoutTableCell>(); }

+ 2 - 2
Libraries/LibWeb/Layout/LayoutTableRow.cpp

@@ -30,8 +30,8 @@
 
 namespace Web {
 
-LayoutTableRow::LayoutTableRow(const Element& element, NonnullRefPtr<StyleProperties> style)
-    : LayoutBox(&element, move(style))
+LayoutTableRow::LayoutTableRow(Document& document, const Element& element, NonnullRefPtr<StyleProperties> style)
+    : LayoutBox(document, &element, move(style))
 {
 }
 

+ 1 - 1
Libraries/LibWeb/Layout/LayoutTableRow.h

@@ -34,7 +34,7 @@ class LayoutTableCell;
 
 class LayoutTableRow final : public LayoutBox {
 public:
-    LayoutTableRow(const Element&, NonnullRefPtr<StyleProperties>);
+    LayoutTableRow(Document&, const Element&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutTableRow() override;
 
     void layout_row(const Vector<float>& column_widths);

+ 2 - 2
Libraries/LibWeb/Layout/LayoutTableRowGroup.cpp

@@ -31,8 +31,8 @@
 
 namespace Web {
 
-LayoutTableRowGroup::LayoutTableRowGroup(const Element& element, NonnullRefPtr<StyleProperties> style)
-    : LayoutBlock(&element, move(style))
+LayoutTableRowGroup::LayoutTableRowGroup(Document& document, const Element& element, NonnullRefPtr<StyleProperties> style)
+    : LayoutBlock(document, &element, move(style))
 {
 }
 

+ 1 - 1
Libraries/LibWeb/Layout/LayoutTableRowGroup.h

@@ -32,7 +32,7 @@ namespace Web {
 
 class LayoutTableRowGroup final : public LayoutBlock {
 public:
-    LayoutTableRowGroup(const Element&, NonnullRefPtr<StyleProperties>);
+    LayoutTableRowGroup(Document&, const Element&, NonnullRefPtr<StyleProperties>);
     virtual ~LayoutTableRowGroup() override;
 
     virtual void layout(LayoutMode = LayoutMode::Default) override;

+ 2 - 2
Libraries/LibWeb/Layout/LayoutText.cpp

@@ -36,8 +36,8 @@
 
 namespace Web {
 
-LayoutText::LayoutText(const Text& text)
-    : LayoutNode(&text)
+LayoutText::LayoutText(Document& document, const Text& text)
+    : LayoutNode(document, &text)
 {
     set_inline(true);
 }

+ 1 - 1
Libraries/LibWeb/Layout/LayoutText.h

@@ -35,7 +35,7 @@ class LineBoxFragment;
 
 class LayoutText : public LayoutNode {
 public:
-    explicit LayoutText(const Text&);
+    LayoutText(Document&, const Text&);
     virtual ~LayoutText() override;
 
     const Text& node() const { return static_cast<const Text&>(*LayoutNode::node()); }

+ 2 - 2
Libraries/LibWeb/Layout/LayoutWidget.cpp

@@ -36,8 +36,8 @@
 
 namespace Web {
 
-LayoutWidget::LayoutWidget(const Element& element, GUI::Widget& widget)
-    : LayoutReplaced(element, StyleProperties::create())
+LayoutWidget::LayoutWidget(Document& document, const Element& element, GUI::Widget& widget)
+    : LayoutReplaced(document, element, StyleProperties::create())
     , m_widget(widget)
 {
     set_has_intrinsic_width(true);

+ 1 - 1
Libraries/LibWeb/Layout/LayoutWidget.h

@@ -32,7 +32,7 @@ namespace Web {
 
 class LayoutWidget final : public LayoutReplaced {
 public:
-    LayoutWidget(const Element&, GUI::Widget&);
+    LayoutWidget(Document&, const Element&, GUI::Widget&);
     virtual ~LayoutWidget() override;
 
     GUI::Widget& widget() { return m_widget; }