summaryrefslogtreecommitdiff
path: root/Libraries/LibWeb
diff options
context:
space:
mode:
Diffstat (limited to 'Libraries/LibWeb')
-rw-r--r--Libraries/LibWeb/CMakeLists.txt1
-rw-r--r--Libraries/LibWeb/CSS/Length.cpp64
-rw-r--r--Libraries/LibWeb/CSS/Length.h27
-rw-r--r--Libraries/LibWeb/CSS/StyleProperties.cpp4
-rw-r--r--Libraries/LibWeb/CSS/StyleProperties.h2
-rw-r--r--Libraries/LibWeb/CSS/StyleResolver.cpp2
-rw-r--r--Libraries/LibWeb/CSS/StyleValue.h2
-rw-r--r--Libraries/LibWeb/Dump.cpp24
-rw-r--r--Libraries/LibWeb/Layout/BoxModelMetrics.cpp10
-rw-r--r--Libraries/LibWeb/Layout/BoxModelMetrics.h2
-rw-r--r--Libraries/LibWeb/Layout/LayoutBlock.cpp53
-rw-r--r--Libraries/LibWeb/Layout/LayoutBox.cpp20
-rw-r--r--Libraries/LibWeb/Layout/LayoutNode.cpp7
-rw-r--r--Libraries/LibWeb/Layout/LayoutNode.h2
-rw-r--r--Libraries/LibWeb/Layout/LayoutReplaced.cpp25
-rw-r--r--Libraries/LibWeb/Parser/CSSParser.cpp10
16 files changed, 163 insertions, 92 deletions
diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt
index b66a84ab52..3ba2a05983 100644
--- a/Libraries/LibWeb/CMakeLists.txt
+++ b/Libraries/LibWeb/CMakeLists.txt
@@ -17,6 +17,7 @@ set(SOURCES
Bindings/XMLHttpRequestConstructor.cpp
Bindings/XMLHttpRequestPrototype.cpp
Bindings/XMLHttpRequestWrapper.cpp
+ CSS/Length.cpp
CSS/Selector.cpp
CSS/SelectorEngine.cpp
CSS/StyleDeclaration.cpp
diff --git a/Libraries/LibWeb/CSS/Length.cpp b/Libraries/LibWeb/CSS/Length.cpp
new file mode 100644
index 0000000000..698608b836
--- /dev/null
+++ b/Libraries/LibWeb/CSS/Length.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/CSS/Length.h>
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/HTMLHtmlElement.h>
+
+namespace Web {
+
+float Length::to_px(const LayoutNode& layout_node) const
+{
+ switch (m_type) {
+ case Type::Auto:
+ return 0;
+ case Type::Px:
+ return m_value;
+ case Type::Em:
+ return m_value * layout_node.font_size();
+ case Type::Rem:
+ return m_value * layout_node.document().document_element()->layout_node()->font_size();
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+const char* Length::unit_name() const
+{
+ switch (m_type) {
+ case Type::Px:
+ return "px";
+ case Type::Em:
+ return "em";
+ case Type::Rem:
+ return "rem";
+ case Type::Auto:
+ return "auto";
+ }
+ ASSERT_NOT_REACHED();
+}
+
+}
diff --git a/Libraries/LibWeb/CSS/Length.h b/Libraries/LibWeb/CSS/Length.h
index 612c1cf49f..c63bd15345 100644
--- a/Libraries/LibWeb/CSS/Length.h
+++ b/Libraries/LibWeb/CSS/Length.h
@@ -27,6 +27,7 @@
#pragma once
#include <AK/String.h>
+#include <LibWeb/Forward.h>
namespace Web {
@@ -34,10 +35,12 @@ class Length {
public:
enum class Type {
Auto,
- Absolute,
+ Px,
+ Em,
+ Rem,
};
- Length() {}
+ Length() { }
Length(int value, Type type)
: m_type(type)
, m_value(value)
@@ -48,28 +51,24 @@ public:
, m_value(value)
{
}
- ~Length() {}
bool is_auto() const { return m_type == Type::Auto; }
- bool is_absolute() const { return m_type == Type::Absolute; }
+ bool is_absolute() const { return m_type == Type::Px; }
+ bool is_relative() const { return m_type == Type::Em || m_type == Type::Rem; }
- float value() const { return m_value; }
+ float raw_value() const { return m_value; }
+ float to_px(const LayoutNode&) const;
String to_string() const
{
if (is_auto())
- return "[Length/auto]";
- return String::format("%g [Length/px]", m_value);
- }
-
- float to_px() const
- {
- if (is_auto())
- return 0;
- return m_value;
+ return "[auto]";
+ return String::format("[%g %s]", m_value, unit_name());
}
private:
+ const char* unit_name() const;
+
Type m_type { Type::Auto };
float m_value { 0 };
};
diff --git a/Libraries/LibWeb/CSS/StyleProperties.cpp b/Libraries/LibWeb/CSS/StyleProperties.cpp
index c4b307803e..b2e2a02037 100644
--- a/Libraries/LibWeb/CSS/StyleProperties.cpp
+++ b/Libraries/LibWeb/CSS/StyleProperties.cpp
@@ -172,11 +172,11 @@ void StyleProperties::load_font() const
return;
}
-float StyleProperties::line_height() const
+float StyleProperties::line_height(const LayoutNode& layout_node) const
{
auto line_height_length = length_or_fallback(CSS::PropertyID::LineHeight, {});
if (line_height_length.is_absolute())
- return (float)line_height_length.to_px();
+ return (float)line_height_length.to_px(layout_node);
return (float)font().glyph_height() * 1.4f;
}
diff --git a/Libraries/LibWeb/CSS/StyleProperties.h b/Libraries/LibWeb/CSS/StyleProperties.h
index 0b32443415..c45c2eddc2 100644
--- a/Libraries/LibWeb/CSS/StyleProperties.h
+++ b/Libraries/LibWeb/CSS/StyleProperties.h
@@ -66,7 +66,7 @@ public:
return *m_font;
}
- float line_height() const;
+ float line_height(const LayoutNode&) const;
bool operator==(const StyleProperties&) const;
bool operator!=(const StyleProperties& other) const { return !(*this == other); }
diff --git a/Libraries/LibWeb/CSS/StyleResolver.cpp b/Libraries/LibWeb/CSS/StyleResolver.cpp
index dc6bfe7ea0..28ca825e26 100644
--- a/Libraries/LibWeb/CSS/StyleResolver.cpp
+++ b/Libraries/LibWeb/CSS/StyleResolver.cpp
@@ -190,7 +190,7 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
if (auto value = parse_line_style(parts[0])) {
set_property_border_style(style, value.release_nonnull());
set_property_border_color(style, ColorStyleValue::create(Gfx::Color::Black));
- set_property_border_width(style, LengthStyleValue::create(Length(3, Length::Type::Absolute)));
+ set_property_border_width(style, LengthStyleValue::create(Length(3, Length::Type::Px)));
return;
}
}
diff --git a/Libraries/LibWeb/CSS/StyleValue.h b/Libraries/LibWeb/CSS/StyleValue.h
index 64bde2e3c5..8186eddc5b 100644
--- a/Libraries/LibWeb/CSS/StyleValue.h
+++ b/Libraries/LibWeb/CSS/StyleValue.h
@@ -212,7 +212,7 @@ public:
virtual String to_string() const override { return String::format("%g%%", m_percentage); }
- Length to_length(float reference) const { return Length((m_percentage / 100.0f) * reference, Length::Type::Absolute); }
+ Length to_length(float reference) const { return Length((m_percentage / 100.0f) * reference, Length::Type::Px); }
private:
virtual Length to_length() const override { return {}; }
diff --git a/Libraries/LibWeb/Dump.cpp b/Libraries/LibWeb/Dump.cpp
index c6173c1696..7d8f3733e8 100644
--- a/Libraries/LibWeb/Dump.cpp
+++ b/Libraries/LibWeb/Dump.cpp
@@ -117,23 +117,23 @@ void dump_tree(const LayoutNode& layout_node)
// Dump the horizontal box properties
dbgprintf(" [%g+%g+%g %g %g+%g+%g]",
- layout_box.box_model().margin().left.to_px(),
- layout_box.box_model().border().left.to_px(),
- layout_box.box_model().padding().left.to_px(),
+ layout_box.box_model().margin().left.to_px(layout_box),
+ layout_box.box_model().border().left.to_px(layout_box),
+ layout_box.box_model().padding().left.to_px(layout_box),
layout_box.width(),
- layout_box.box_model().padding().right.to_px(),
- layout_box.box_model().border().right.to_px(),
- layout_box.box_model().margin().right.to_px());
+ layout_box.box_model().padding().right.to_px(layout_box),
+ layout_box.box_model().border().right.to_px(layout_box),
+ layout_box.box_model().margin().right.to_px(layout_box));
// And the vertical box properties
dbgprintf(" [%g+%g+%g %g %g+%g+%g]",
- layout_box.box_model().margin().top.to_px(),
- layout_box.box_model().border().top.to_px(),
- layout_box.box_model().padding().top.to_px(),
+ layout_box.box_model().margin().top.to_px(layout_box),
+ layout_box.box_model().border().top.to_px(layout_box),
+ layout_box.box_model().padding().top.to_px(layout_box),
layout_box.height(),
- layout_box.box_model().padding().bottom.to_px(),
- layout_box.box_model().border().bottom.to_px(),
- layout_box.box_model().margin().bottom.to_px());
+ layout_box.box_model().padding().bottom.to_px(layout_box),
+ layout_box.box_model().border().bottom.to_px(layout_box),
+ layout_box.box_model().margin().bottom.to_px(layout_box));
dbgprintf("\n");
}
diff --git a/Libraries/LibWeb/Layout/BoxModelMetrics.cpp b/Libraries/LibWeb/Layout/BoxModelMetrics.cpp
index b218ce3c7c..c937918eaf 100644
--- a/Libraries/LibWeb/Layout/BoxModelMetrics.cpp
+++ b/Libraries/LibWeb/Layout/BoxModelMetrics.cpp
@@ -36,13 +36,13 @@ BoxModelMetrics::~BoxModelMetrics()
{
}
-BoxModelMetrics::PixelBox BoxModelMetrics::full_margin() const
+BoxModelMetrics::PixelBox BoxModelMetrics::full_margin(const LayoutNode& layout_node) const
{
return {
- m_margin.top.to_px() + m_border.top.to_px() + m_padding.top.to_px(),
- m_margin.right.to_px() + m_border.right.to_px() + m_padding.right.to_px(),
- m_margin.bottom.to_px() + m_border.bottom.to_px() + m_padding.bottom.to_px(),
- m_margin.left.to_px() + m_border.left.to_px() + m_padding.left.to_px(),
+ m_margin.top.to_px(layout_node) + m_border.top.to_px(layout_node) + m_padding.top.to_px(layout_node),
+ m_margin.right.to_px(layout_node) + m_border.right.to_px(layout_node) + m_padding.right.to_px(layout_node),
+ m_margin.bottom.to_px(layout_node) + m_border.bottom.to_px(layout_node) + m_padding.bottom.to_px(layout_node),
+ m_margin.left.to_px(layout_node) + m_border.left.to_px(layout_node) + m_padding.left.to_px(layout_node),
};
}
diff --git a/Libraries/LibWeb/Layout/BoxModelMetrics.h b/Libraries/LibWeb/Layout/BoxModelMetrics.h
index f32fbff9d7..3a699c0f4a 100644
--- a/Libraries/LibWeb/Layout/BoxModelMetrics.h
+++ b/Libraries/LibWeb/Layout/BoxModelMetrics.h
@@ -53,7 +53,7 @@ public:
float left;
};
- PixelBox full_margin() const;
+ PixelBox full_margin(const LayoutNode&) const;
private:
LengthBox m_margin;
diff --git a/Libraries/LibWeb/Layout/LayoutBlock.cpp b/Libraries/LibWeb/Layout/LayoutBlock.cpp
index 39e3fd17c9..e6422ef685 100644
--- a/Libraries/LibWeb/Layout/LayoutBlock.cpp
+++ b/Libraries/LibWeb/Layout/LayoutBlock.cpp
@@ -86,7 +86,7 @@ void LayoutBlock::layout_block_children(LayoutMode layout_mode)
child_block.layout(layout_mode);
if (!child_block.is_absolutely_positioned())
- content_height = child_block.rect().bottom() + child_block.box_model().full_margin().bottom - rect().top();
+ content_height = child_block.rect().bottom() + child_block.box_model().full_margin(*this).bottom - rect().top();
});
if (layout_mode != LayoutMode::Default) {
float max_width = 0;
@@ -112,7 +112,7 @@ void LayoutBlock::layout_inline_children(LayoutMode layout_mode)
line_box.trim_trailing_whitespace();
}
- float min_line_height = style().line_height();
+ float min_line_height = style().line_height(*this);
float line_spacing = min_line_height - style().font().glyph_height();
float content_height = 0;
@@ -221,7 +221,7 @@ void LayoutBlock::compute_width()
auto& style = this->style();
auto auto_value = Length();
- auto zero_value = Length(0, Length::Type::Absolute);
+ auto zero_value = Length(0, Length::Type::Px);
Length margin_left;
Length margin_right;
@@ -247,7 +247,7 @@ void LayoutBlock::compute_width()
float total_px = 0;
for (auto& value : { margin_left, border_left, padding_left, width, padding_right, border_right, margin_right }) {
- total_px += value.to_px();
+ total_px += value.to_px(*this);
}
#ifdef HTML_DEBUG
@@ -273,20 +273,20 @@ void LayoutBlock::compute_width()
if (margin_right.is_auto())
margin_right = zero_value;
if (underflow_px >= 0) {
- width = Length(underflow_px, Length::Type::Absolute);
+ width = Length(underflow_px, Length::Type::Px);
} else {
width = zero_value;
- margin_right = Length(margin_right.to_px() + underflow_px, Length::Type::Absolute);
+ margin_right = Length(margin_right.to_px(*this) + underflow_px, Length::Type::Px);
}
} else {
if (!margin_left.is_auto() && !margin_right.is_auto()) {
- margin_right = Length(margin_right.to_px() + underflow_px, Length::Type::Absolute);
+ margin_right = Length(margin_right.to_px(*this) + underflow_px, Length::Type::Px);
} else if (!margin_left.is_auto() && margin_right.is_auto()) {
- margin_right = Length(underflow_px, Length::Type::Absolute);
+ margin_right = Length(underflow_px, Length::Type::Px);
} else if (margin_left.is_auto() && !margin_right.is_auto()) {
- margin_left = Length(underflow_px, Length::Type::Absolute);
+ margin_left = Length(underflow_px, Length::Type::Px);
} else { // margin_left.is_auto() && margin_right.is_auto()
- auto half_of_the_underflow = Length(underflow_px / 2, Length::Type::Absolute);
+ auto half_of_the_underflow = Length(underflow_px / 2, Length::Type::Px);
margin_left = half_of_the_underflow;
margin_right = half_of_the_underflow;
}
@@ -323,8 +323,8 @@ void LayoutBlock::compute_width()
// '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() - border_left.to_px() - padding_left.to_px()
- - padding_right.to_px() - border_right.to_px() - margin_right.to_px();
+ - 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);
// Calculate the preferred width by formatting the content without breaking lines
// other than where explicit line breaks occur.
@@ -338,7 +338,7 @@ void LayoutBlock::compute_width()
float preferred_minimum_width = greatest_child_width();
// Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).
- width = Length(min(max(preferred_minimum_width, available_width), preferred_width), Length::Type::Absolute);
+ width = Length(min(max(preferred_minimum_width, available_width), preferred_width), Length::Type::Px);
}
}
@@ -354,7 +354,7 @@ void LayoutBlock::compute_width()
// but this time using the computed value of 'max-width' as the computed value for 'width'.
auto specified_max_width = style.length_or_fallback(CSS::PropertyID::MaxWidth, auto_value, containing_block.width());
if (!specified_max_width.is_auto()) {
- if (used_width.to_px() > specified_max_width.to_px()) {
+ if (used_width.to_px(*this) > specified_max_width.to_px(*this)) {
used_width = try_compute_width(specified_max_width);
}
}
@@ -363,12 +363,12 @@ void LayoutBlock::compute_width()
// but this time using the value of 'min-width' as the computed value for 'width'.
auto specified_min_width = style.length_or_fallback(CSS::PropertyID::MinWidth, auto_value, containing_block.width());
if (!specified_min_width.is_auto()) {
- if (used_width.to_px() < specified_min_width.to_px()) {
+ if (used_width.to_px(*this) < specified_min_width.to_px(*this)) {
used_width = try_compute_width(specified_min_width);
}
}
- rect().set_width(used_width.to_px());
+ rect().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;
@@ -381,13 +381,10 @@ void LayoutBlock::compute_position()
{
auto& style = this->style();
- auto auto_value = Length();
- auto zero_value = Length(0, Length::Type::Absolute);
+ auto zero_value = Length(0, Length::Type::Px);
auto& containing_block = *this->containing_block();
- auto width = style.length_or_fallback(CSS::PropertyID::Width, auto_value, containing_block.width());
-
if (style.position() == CSS::Position::Absolute) {
box_model().offset().top = style.length_or_fallback(CSS::PropertyID::Top, zero_value, containing_block.height());
box_model().offset().right = style.length_or_fallback(CSS::PropertyID::Right, zero_value, containing_block.width());
@@ -402,18 +399,18 @@ void LayoutBlock::compute_position()
box_model().padding().top = style.length_or_fallback(CSS::PropertyID::PaddingTop, zero_value, containing_block.width());
box_model().padding().bottom = style.length_or_fallback(CSS::PropertyID::PaddingBottom, zero_value, containing_block.width());
- float position_x = box_model().margin().left.to_px()
- + box_model().border().left.to_px()
- + box_model().padding().left.to_px()
- + box_model().offset().left.to_px();
+ float position_x = box_model().margin().left.to_px(*this)
+ + box_model().border().left.to_px(*this)
+ + box_model().padding().left.to_px(*this)
+ + box_model().offset().left.to_px(*this);
if (style.position() != CSS::Position::Absolute || containing_block.style().position() == CSS::Position::Absolute)
position_x += containing_block.x();
rect().set_x(position_x);
- float position_y = box_model().full_margin().top
- + box_model().offset().top.to_px();
+ float position_y = box_model().full_margin(*this).top
+ + box_model().offset().top.to_px(*this);
if (style.position() != CSS::Position::Absolute || containing_block.style().position() == CSS::Position::Absolute) {
LayoutBlock* relevant_sibling = previous_sibling();
@@ -429,7 +426,7 @@ void LayoutBlock::compute_position()
auto& previous_sibling_rect = relevant_sibling->rect();
auto& previous_sibling_style = relevant_sibling->box_model();
position_y += previous_sibling_rect.y() + previous_sibling_rect.height();
- position_y += previous_sibling_style.full_margin().bottom;
+ position_y += previous_sibling_style.full_margin(*this).bottom;
}
}
@@ -441,7 +438,7 @@ void LayoutBlock::compute_height()
auto& style = this->style();
auto height = style.length_or_fallback(CSS::PropertyID::Height, Length(), containing_block()->height());
if (height.is_absolute())
- rect().set_height(height.to_px());
+ rect().set_height(height.to_px(*this));
}
void LayoutBlock::render(RenderingContext& context)
diff --git a/Libraries/LibWeb/Layout/LayoutBox.cpp b/Libraries/LibWeb/Layout/LayoutBox.cpp
index 27add6241f..5aaefa3fee 100644
--- a/Libraries/LibWeb/Layout/LayoutBox.cpp
+++ b/Libraries/LibWeb/Layout/LayoutBox.cpp
@@ -43,7 +43,7 @@ void LayoutBox::paint_border(RenderingContext& context, Edge edge, const Gfx::Fl
return;
auto border_style = style().property(style_property_id);
- float width = border_width.value()->to_length().to_px();
+ float width = border_width.value()->to_length().to_px(*this);
if (width <= 0)
return;
@@ -143,7 +143,7 @@ void LayoutBox::paint_border(RenderingContext& context, Edge edge, const Gfx::Fl
auto width = style().property(property_id);
if (!width.has_value())
return 0;
- return width.value()->to_length().to_px();
+ return width.value()->to_length().to_px(*this);
};
float p1_step = 0;
@@ -203,10 +203,10 @@ void LayoutBox::render(RenderingContext& context)
#endif
Gfx::FloatRect padded_rect;
- padded_rect.set_x(x() - box_model().padding().left.to_px());
- padded_rect.set_width(width() + box_model().padding().left.to_px() + box_model().padding().right.to_px());
- padded_rect.set_y(y() - box_model().padding().top.to_px());
- padded_rect.set_height(height() + box_model().padding().top.to_px() + box_model().padding().bottom.to_px());
+ padded_rect.set_x(x() - box_model().padding().left.to_px(*this));
+ padded_rect.set_width(width() + box_model().padding().left.to_px(*this) + box_model().padding().right.to_px(*this));
+ padded_rect.set_y(y() - box_model().padding().top.to_px(*this));
+ padded_rect.set_height(height() + box_model().padding().top.to_px(*this) + box_model().padding().bottom.to_px(*this));
if (!is_body()) {
auto bgcolor = style().property(CSS::PropertyID::BackgroundColor);
@@ -224,10 +224,10 @@ void LayoutBox::render(RenderingContext& context)
}
Gfx::FloatRect bordered_rect;
- bordered_rect.set_x(padded_rect.x() - box_model().border().left.to_px());
- bordered_rect.set_width(padded_rect.width() + box_model().border().left.to_px() + box_model().border().right.to_px());
- bordered_rect.set_y(padded_rect.y() - box_model().border().top.to_px());
- bordered_rect.set_height(padded_rect.height() + box_model().border().top.to_px() + box_model().border().bottom.to_px());
+ bordered_rect.set_x(padded_rect.x() - box_model().border().left.to_px(*this));
+ bordered_rect.set_width(padded_rect.width() + box_model().border().left.to_px(*this) + box_model().border().right.to_px(*this));
+ 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);
diff --git a/Libraries/LibWeb/Layout/LayoutNode.cpp b/Libraries/LibWeb/Layout/LayoutNode.cpp
index a9039492fd..e4a21bb3c7 100644
--- a/Libraries/LibWeb/Layout/LayoutNode.cpp
+++ b/Libraries/LibWeb/Layout/LayoutNode.cpp
@@ -162,6 +162,13 @@ void LayoutNode::set_needs_display()
}
}
+float LayoutNode::font_size() const
+{
+ // FIXME: This doesn't work right for relative font-sizes
+ auto length = style().length_or_fallback(CSS::PropertyID::FontSize, Length(10, Length::Type::Px));
+ return length.raw_value();
+}
+
Gfx::FloatPoint LayoutNode::box_type_agnostic_position() const
{
if (is_box())
diff --git a/Libraries/LibWeb/Layout/LayoutNode.h b/Libraries/LibWeb/Layout/LayoutNode.h
index dc46e6019b..adcd160d81 100644
--- a/Libraries/LibWeb/Layout/LayoutNode.h
+++ b/Libraries/LibWeb/Layout/LayoutNode.h
@@ -158,6 +158,8 @@ public:
Gfx::FloatPoint box_type_agnostic_position() const;
+ float font_size() const;
+
protected:
explicit LayoutNode(const Node*);
diff --git a/Libraries/LibWeb/Layout/LayoutReplaced.cpp b/Libraries/LibWeb/Layout/LayoutReplaced.cpp
index 1698697b5f..4aa9b5a259 100644
--- a/Libraries/LibWeb/Layout/LayoutReplaced.cpp
+++ b/Libraries/LibWeb/Layout/LayoutReplaced.cpp
@@ -47,7 +47,7 @@ float LayoutReplaced::calculate_width() const
auto& style = this->style();
auto auto_value = Length();
- auto zero_value = Length(0, Length::Type::Absolute);
+ auto zero_value = Length(0, Length::Type::Px);
auto& containing_block = *this->containing_block();
auto margin_left = style.length_or_fallback(CSS::PropertyID::MarginLeft, zero_value, containing_block.width());
@@ -65,7 +65,7 @@ float LayoutReplaced::calculate_width() const
// FIXME: Actually compute 'width'
auto computed_width = specified_width;
- float used_width = specified_width.to_px();
+ float used_width = specified_width.to_px(*this);
// If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic width,
// then that intrinsic width is the used value of 'width'.
@@ -100,16 +100,12 @@ float LayoutReplaced::calculate_height() const
// 'inline-block' replaced elements in normal flow and floating replaced elements
auto& style = this->style();
auto auto_value = Length();
- auto zero_value = Length(0, Length::Type::Absolute);
auto& containing_block = *this->containing_block();
- auto margin_top = style.length_or_fallback(CSS::PropertyID::MarginTop, zero_value, containing_block.width());
- auto margin_bottom = style.length_or_fallback(CSS::PropertyID::MarginBottom, zero_value, containing_block.width());
-
auto specified_width = style.length_or_fallback(CSS::PropertyID::Width, auto_value, containing_block.width());
auto specified_height = style.length_or_fallback(CSS::PropertyID::Height, auto_value, containing_block.height());
- float used_height = specified_height.to_px();
+ float used_height = specified_height.to_px(*this);
// If 'height' and 'width' both have computed values of 'auto' and the element also has
// an intrinsic height, then that intrinsic height is the used value of 'height'.
@@ -128,12 +124,9 @@ float LayoutReplaced::calculate_height() const
Gfx::FloatPoint LayoutReplaced::calculate_position()
{
auto& style = this->style();
- auto auto_value = Length();
- auto zero_value = Length(0, Length::Type::Absolute);
+ auto zero_value = Length(0, Length::Type::Px);
auto& containing_block = *this->containing_block();
- auto width = style.length_or_fallback(CSS::PropertyID::Width, auto_value, containing_block.width());
-
if (style.position() == CSS::Position::Absolute) {
box_model().offset().top = style.length_or_fallback(CSS::PropertyID::Top, zero_value, containing_block.height());
box_model().offset().right = style.length_or_fallback(CSS::PropertyID::Right, zero_value, containing_block.width());
@@ -148,15 +141,15 @@ Gfx::FloatPoint LayoutReplaced::calculate_position()
box_model().padding().top = style.length_or_fallback(CSS::PropertyID::PaddingTop, zero_value, containing_block.width());
box_model().padding().bottom = style.length_or_fallback(CSS::PropertyID::PaddingBottom, zero_value, containing_block.width());
- float position_x = box_model().margin().left.to_px()
- + box_model().border().left.to_px()
- + box_model().padding().left.to_px()
- + box_model().offset().left.to_px();
+ float position_x = box_model().margin().left.to_px(*this)
+ + box_model().border().left.to_px(*this)
+ + box_model().padding().left.to_px(*this)
+ + box_model().offset().left.to_px(*this);
if (style.position() != CSS::Position::Absolute || containing_block.style().position() == CSS::Position::Absolute)
position_x += containing_block.x();
- float position_y = box_model().full_margin().top + box_model().offset().top.to_px();
+ float position_y = box_model().full_margin(*this).top + box_model().offset().top.to_px(*this);
return { position_x, position_y };
}
diff --git a/Libraries/LibWeb/Parser/CSSParser.cpp b/Libraries/LibWeb/Parser/CSSParser.cpp
index 0ba115e7e9..507ff8320d 100644
--- a/Libraries/LibWeb/Parser/CSSParser.cpp
+++ b/Libraries/LibWeb/Parser/CSSParser.cpp
@@ -253,6 +253,10 @@ static Optional<float> parse_number(const StringView& view)
// FIXME: Maybe we should have "ends_with_ignoring_case()" ?
if (view.to_string().to_lowercase().ends_with("px"))
return parse_number(view.substring_view(0, view.length() - 2));
+ if (view.to_string().to_lowercase().ends_with("rem"))
+ return parse_number(view.substring_view(0, view.length() - 3));
+ if (view.to_string().to_lowercase().ends_with("em"))
+ return parse_number(view.substring_view(0, view.length() - 2));
return try_parse_float(view);
}
@@ -263,7 +267,11 @@ NonnullRefPtr<StyleValue> parse_css_value(const StringView& string)
if (number.has_value()) {
if (string.ends_with('%'))
return PercentageStyleValue::create(number.value());
- return LengthStyleValue::create(Length(number.value(), Length::Type::Absolute));
+ if (string.ends_with("em"))
+ return LengthStyleValue::create(Length(number.value(), Length::Type::Em));
+ if (string.ends_with("rem"))
+ return LengthStyleValue::create(Length(number.value(), Length::Type::Rem));
+ return LengthStyleValue::create(Length(number.value(), Length::Type::Px));
}
if (string.equals_ignoring_case("inherit"))