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;
};