diff --git a/Libraries/LibHTML/DOM/HTMLImageElement.cpp b/Libraries/LibHTML/DOM/HTMLImageElement.cpp index 864cc2b91e..97bec0b402 100644 --- a/Libraries/LibHTML/DOM/HTMLImageElement.cpp +++ b/Libraries/LibHTML/DOM/HTMLImageElement.cpp @@ -1,4 +1,6 @@ +#include #include +#include HTMLImageElement::HTMLImageElement(Document& document, const String& tag_name) : HTMLElement(document, tag_name) @@ -8,3 +10,15 @@ HTMLImageElement::HTMLImageElement(Document& document, const String& tag_name) HTMLImageElement::~HTMLImageElement() { } + +RefPtr HTMLImageElement::create_layout_node(const StyleResolver& resolver, const StyleProperties* parent_style) const +{ + auto style = resolver.resolve_style(*this, parent_style); + + auto display_property = style->property("display"); + String display = display_property.has_value() ? display_property.release_value()->to_string() : "inline"; + + if (display == "none") + return nullptr; + return adopt(*new LayoutImage(*this, move(style))); +} diff --git a/Libraries/LibHTML/DOM/HTMLImageElement.h b/Libraries/LibHTML/DOM/HTMLImageElement.h index 0bb37bd2ed..69d3513c5d 100644 --- a/Libraries/LibHTML/DOM/HTMLImageElement.h +++ b/Libraries/LibHTML/DOM/HTMLImageElement.h @@ -9,4 +9,7 @@ public: String alt() const { return attribute("alt"); } String src() const { return attribute("src"); } + +private: + virtual RefPtr create_layout_node(const StyleResolver&, const StyleProperties* parent_style) const override; }; diff --git a/Libraries/LibHTML/Layout/LayoutBlock.cpp b/Libraries/LibHTML/Layout/LayoutBlock.cpp index 6b22135333..ac30819946 100644 --- a/Libraries/LibHTML/Layout/LayoutBlock.cpp +++ b/Libraries/LibHTML/Layout/LayoutBlock.cpp @@ -50,7 +50,7 @@ void LayoutBlock::layout_inline_children() m_line_boxes.clear(); for_each_child([&](auto& child) { ASSERT(child.is_inline()); - static_cast(child).split_into_lines(*this); + child.split_into_lines(*this); }); int content_height = 0; @@ -65,6 +65,9 @@ void LayoutBlock::layout_inline_children() // FIXME: Support other kinds of vertical alignment. fragment.rect().set_x(rect().x() + fragment.rect().x()); fragment.rect().set_y(rect().y() + content_height + (max_height - fragment.rect().height())); + + if (fragment.layout_node().is_replaced()) + const_cast(fragment.layout_node()).set_rect(fragment.rect()); } content_height += max_height; diff --git a/Libraries/LibHTML/Layout/LayoutImage.cpp b/Libraries/LibHTML/Layout/LayoutImage.cpp index 36dcafafaf..68c4a8a7c7 100644 --- a/Libraries/LibHTML/Layout/LayoutImage.cpp +++ b/Libraries/LibHTML/Layout/LayoutImage.cpp @@ -1,3 +1,6 @@ +#include +#include +#include #include LayoutImage::LayoutImage(const HTMLImageElement& element, NonnullRefPtr style) @@ -11,10 +14,26 @@ LayoutImage::~LayoutImage() void LayoutImage::layout() { + if (renders_as_alt_text()) { + auto& font = Font::default_font(); + rect().set_width(font.width(node().alt()) + 16); + rect().set_height(font.glyph_height() + 16); + } + LayoutReplaced::layout(); } void LayoutImage::render(RenderingContext& context) { + if (renders_as_alt_text()) { + context.painter().set_font(Font::default_font()); + StylePainter::paint_frame(context.painter(), rect(), FrameShape::Container, FrameShadow::Sunken, 2); + context.painter().draw_text(rect(), node().alt(), TextAlignment::Center, Color::White); + } LayoutReplaced::render(context); } + +bool LayoutImage::renders_as_alt_text() const +{ + return true; +} diff --git a/Libraries/LibHTML/Layout/LayoutImage.h b/Libraries/LibHTML/Layout/LayoutImage.h index 0a6105a891..344797769c 100644 --- a/Libraries/LibHTML/Layout/LayoutImage.h +++ b/Libraries/LibHTML/Layout/LayoutImage.h @@ -14,5 +14,9 @@ public: virtual void render(RenderingContext&) override; const HTMLImageElement& node() const { return static_cast(LayoutReplaced::node()); } + + bool renders_as_alt_text() const; + private: + virtual const char* class_name() const override { return "LayoutImage"; } }; diff --git a/Libraries/LibHTML/Layout/LayoutInline.cpp b/Libraries/LibHTML/Layout/LayoutInline.cpp index 60f195faf5..41133cbd2d 100644 --- a/Libraries/LibHTML/Layout/LayoutInline.cpp +++ b/Libraries/LibHTML/Layout/LayoutInline.cpp @@ -10,14 +10,3 @@ LayoutInline::LayoutInline(const Node& node, RefPtr style_prope LayoutInline::~LayoutInline() { } - -void LayoutInline::split_into_lines(LayoutBlock& container) -{ - for_each_child([&](auto& child) { - if (child.is_inline()) { - static_cast(child).split_into_lines(container); - } else { - // FIXME: Support block children of inlines. - } - }); -} diff --git a/Libraries/LibHTML/Layout/LayoutInline.h b/Libraries/LibHTML/Layout/LayoutInline.h index 8eecf9fc49..3f9f6e019a 100644 --- a/Libraries/LibHTML/Layout/LayoutInline.h +++ b/Libraries/LibHTML/Layout/LayoutInline.h @@ -11,7 +11,5 @@ public: virtual const char* class_name() const override { return "LayoutInline"; } - virtual void split_into_lines(LayoutBlock& container); - private: }; diff --git a/Libraries/LibHTML/Layout/LayoutNode.cpp b/Libraries/LibHTML/Layout/LayoutNode.cpp index 21f9995421..704946bdcd 100644 --- a/Libraries/LibHTML/Layout/LayoutNode.cpp +++ b/Libraries/LibHTML/Layout/LayoutNode.cpp @@ -116,3 +116,14 @@ const Document& LayoutNode::document() const return parent()->document(); return node()->document(); } + +void LayoutNode::split_into_lines(LayoutBlock& container) +{ + for_each_child([&](auto& child) { + if (child.is_inline()) { + child.split_into_lines(container); + } else { + // FIXME: Support block children of inlines. + } + }); +} diff --git a/Libraries/LibHTML/Layout/LayoutNode.h b/Libraries/LibHTML/Layout/LayoutNode.h index f75da03d6c..f8a19d3eda 100644 --- a/Libraries/LibHTML/Layout/LayoutNode.h +++ b/Libraries/LibHTML/Layout/LayoutNode.h @@ -12,6 +12,7 @@ class Document; class Element; class LayoutBlock; class LayoutNode; +class LineBoxFragment; class Node; struct HitTestResult { @@ -53,6 +54,7 @@ public: virtual const char* class_name() const { return "LayoutNode"; } virtual bool is_text() const { return false; } virtual bool is_block() const { return false; } + virtual bool is_replaced() const { return false; } bool is_inline() const { return m_inline; } void set_inline(bool b) { m_inline = b; } @@ -74,6 +76,8 @@ public: void inserted_into(LayoutNode&) {} void removed_from(LayoutNode&) {} + virtual void split_into_lines(LayoutBlock& container); + protected: explicit LayoutNode(const Node*, RefPtr); diff --git a/Libraries/LibHTML/Layout/LayoutReplaced.cpp b/Libraries/LibHTML/Layout/LayoutReplaced.cpp index 2634be9b09..6d0f8695db 100644 --- a/Libraries/LibHTML/Layout/LayoutReplaced.cpp +++ b/Libraries/LibHTML/Layout/LayoutReplaced.cpp @@ -1,4 +1,5 @@ #include +#include #include LayoutReplaced::LayoutReplaced(const Element& element, NonnullRefPtr style) @@ -11,3 +12,12 @@ LayoutReplaced::LayoutReplaced(const Element& element, NonnullRefPtr); - virtual ~LayoutReplaced(); + virtual ~LayoutReplaced() override; const Element& node() const { return static_cast(*LayoutNode::node()); } + virtual bool is_replaced() const final { return true; } + private: + virtual const char* class_name() const override { return "LayoutReplaced"; } + + virtual void split_into_lines(LayoutBlock& container) override; };