summaryrefslogtreecommitdiff
path: root/Libraries/LibHTML/Layout/LayoutBox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Libraries/LibHTML/Layout/LayoutBox.cpp')
-rw-r--r--Libraries/LibHTML/Layout/LayoutBox.cpp95
1 files changed, 95 insertions, 0 deletions
diff --git a/Libraries/LibHTML/Layout/LayoutBox.cpp b/Libraries/LibHTML/Layout/LayoutBox.cpp
new file mode 100644
index 0000000000..0e7d69afc9
--- /dev/null
+++ b/Libraries/LibHTML/Layout/LayoutBox.cpp
@@ -0,0 +1,95 @@
+#include <LibGUI/GPainter.h>
+#include <LibHTML/DOM/Document.h>
+#include <LibHTML/Frame.h>
+#include <LibHTML/Layout/LayoutBlock.h>
+#include <LibHTML/Layout/LayoutBox.h>
+
+//#define DRAW_BOXES_AROUND_LAYOUT_NODES
+//#define DRAW_BOXES_AROUND_HOVERED_NODES
+
+void LayoutBox::render(RenderingContext& context)
+{
+#ifdef DRAW_BOXES_AROUND_LAYOUT_NODES
+ context.painter().draw_rect(m_rect, Color::Blue);
+#endif
+#ifdef DRAW_BOXES_AROUND_HOVERED_NODES
+ if (!is_anonymous() && node() == document().hovered_node())
+ context.painter().draw_rect(m_rect, Color::Red);
+#endif
+
+ Rect 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());
+
+ auto bgcolor = style().property(CSS::PropertyID::BackgroundColor);
+ if (bgcolor.has_value() && bgcolor.value()->is_color()) {
+ context.painter().fill_rect(padded_rect, bgcolor.value()->to_color(document()));
+ }
+
+ // FIXME: Respect all individual border sides
+ auto border_width_value = style().property(CSS::PropertyID::BorderTopWidth);
+ auto border_color_value = style().property(CSS::PropertyID::BorderTopColor);
+ auto border_style_value = style().property(CSS::PropertyID::BorderTopStyle);
+ if (border_width_value.has_value() && border_color_value.has_value()) {
+ int border_width = border_width_value.value()->to_length().to_px();
+ Color border_color = border_color_value.value()->to_color(document());
+
+ if (border_style_value.has_value() && border_style_value.value()->to_string() == "inset") {
+ // border-style: inset
+ auto shadow_color = Color::from_rgb(0x888888);
+ auto highlight_color = Color::from_rgb(0x5a5a5a);
+ context.painter().draw_line(padded_rect.top_left(), padded_rect.top_right(), highlight_color, border_width);
+ context.painter().draw_line(padded_rect.top_right(), padded_rect.bottom_right(), shadow_color, border_width);
+ context.painter().draw_line(padded_rect.bottom_right(), padded_rect.bottom_left(), shadow_color, border_width);
+ context.painter().draw_line(padded_rect.bottom_left(), padded_rect.top_left(), highlight_color, border_width);
+ } else if (border_style_value.has_value() && border_style_value.value()->to_string() == "outset") {
+ // border-style: outset
+ auto highlight_color = Color::from_rgb(0x888888);
+ auto shadow_color = Color::from_rgb(0x5a5a5a);
+ context.painter().draw_line(padded_rect.top_left(), padded_rect.top_right(), highlight_color, border_width);
+ context.painter().draw_line(padded_rect.top_right(), padded_rect.bottom_right(), shadow_color, border_width);
+ context.painter().draw_line(padded_rect.bottom_right(), padded_rect.bottom_left(), shadow_color, border_width);
+ context.painter().draw_line(padded_rect.bottom_left(), padded_rect.top_left(), highlight_color, border_width);
+ } else {
+ // border-style: solid
+ context.painter().draw_line(padded_rect.top_left(), padded_rect.top_right(), border_color, border_width);
+ context.painter().draw_line(padded_rect.top_right(), padded_rect.bottom_right(), border_color, border_width);
+ context.painter().draw_line(padded_rect.bottom_right(), padded_rect.bottom_left(), border_color, border_width);
+ context.painter().draw_line(padded_rect.bottom_left(), padded_rect.top_left(), border_color, border_width);
+ }
+ }
+}
+
+HitTestResult LayoutBox::hit_test(const Point& position) const
+{
+ // FIXME: It would be nice if we could confidently skip over hit testing
+ // parts of the layout tree, but currently we can't just check
+ // m_rect.contains() since inline text rects can't be trusted..
+ HitTestResult result { m_rect.contains(position) ? this : nullptr };
+ for_each_child([&](auto& child) {
+ auto child_result = child.hit_test(position);
+ if (child_result.layout_node)
+ result = child_result;
+ });
+ return result;
+}
+
+void LayoutBox::set_needs_display()
+{
+ auto* frame = document().frame();
+ ASSERT(frame);
+
+ if (!is_inline()) {
+ const_cast<Frame*>(frame)->set_needs_display(rect());
+ return;
+ }
+
+ for_each_fragment_of_this([&](auto& fragment) {
+ if (&fragment.layout_node() == this || is_ancestor_of(fragment.layout_node())) {
+ const_cast<Frame*>(frame)->set_needs_display(fragment.rect());
+ }
+ return IterationDecision::Continue;
+ });
+}