diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index eae666b646d..0579c1e14d4 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -593,7 +593,7 @@ JS::NonnullGCPtr Element::get_bounding_client_rect() const VERIFY(document().browsing_context()); auto viewport_offset = document().browsing_context()->viewport_scroll_offset(); - return Geometry::DOMRect::create(realm(), paint_box->absolute_rect().translated(-viewport_offset.x(), -viewport_offset.y())); + return Geometry::DOMRect::create(realm(), paint_box->absolute_rect().translated(-viewport_offset.x(), -viewport_offset.y()).to_type()); } // https://drafts.csswg.org/cssom-view/#dom-element-getclientrects @@ -676,7 +676,7 @@ int Element::client_width() const // 3. Return the width of the padding edge excluding the width of any rendered scrollbar between the padding edge and the border edge, // ignoring any transforms that apply to the element and its ancestors. - return paint_box()->absolute_padding_box_rect().width(); + return paint_box()->absolute_padding_box_rect().width().value(); } // https://drafts.csswg.org/cssom-view/#dom-element-clientheight @@ -701,7 +701,7 @@ int Element::client_height() const // 3. Return the height of the padding edge excluding the height of any rendered scrollbar between the padding edge and the border edge, // ignoring any transforms that apply to the element and its ancestors. - return paint_box()->absolute_padding_box_rect().height(); + return paint_box()->absolute_padding_box_rect().height().value(); } void Element::children_changed() @@ -1212,7 +1212,7 @@ static void scroll_an_element_into_view(DOM::Element& element, Bindings::ScrollB if (!layout_node) return; - page->client().page_did_request_scroll_into_view(verify_cast(*layout_node).paint_box()->absolute_padding_box_rect().to_type()); + page->client().page_did_request_scroll_into_view(verify_cast(*layout_node).paint_box()->absolute_padding_box_rect()); } // https://w3c.github.io/csswg-drafts/cssom-view-1/#dom-element-scrollintoview diff --git a/Userland/Libraries/LibWeb/Dump.cpp b/Userland/Libraries/LibWeb/Dump.cpp index a9aef46eda7..f00bd724508 100644 --- a/Userland/Libraries/LibWeb/Dump.cpp +++ b/Userland/Libraries/LibWeb/Dump.cpp @@ -264,7 +264,7 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho builder.appendff("start: {}, length: {}, rect: {}\n", fragment.start(), fragment.length(), - fragment.absolute_rect().to_deprecated_string()); + fragment.absolute_rect()); if (is(fragment.layout_node())) { for (size_t i = 0; i < indent; ++i) builder.append(" "sv); diff --git a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp index cd281a7ea30..30df1d02563 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -199,7 +199,7 @@ int HTMLElement::offset_width() const // 2. Return the width of the axis-aligned bounding box of the border boxes of all fragments generated by the element’s principal box, // ignoring any transforms that apply to the element and its ancestors. // FIXME: Account for inline boxes. - return paint_box()->border_box_width(); + return paint_box()->border_box_width().value(); } // https://drafts.csswg.org/cssom-view/#dom-htmlelement-offsetheight @@ -215,7 +215,7 @@ int HTMLElement::offset_height() const // 2. Return the height of the axis-aligned bounding box of the border boxes of all fragments generated by the element’s principal box, // ignoring any transforms that apply to the element and its ancestors. // FIXME: Account for inline boxes. - return paint_box()->border_box_height(); + return paint_box()->border_box_height().value(); } // https://html.spec.whatwg.org/multipage/links.html#cannot-navigate diff --git a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp index 129a0a123a8..a74bc35d4f4 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -102,7 +102,7 @@ unsigned HTMLImageElement::width() const // Return the rendered width of the image, in CSS pixels, if the image is being rendered. if (auto* paint_box = this->paint_box()) - return paint_box->content_width(); + return paint_box->content_width().value(); // NOTE: This step seems to not be in the spec, but all browsers do it. auto width_attr = get_attribute(HTML::AttributeNames::width); @@ -130,7 +130,7 @@ unsigned HTMLImageElement::height() const // Return the rendered height of the image, in CSS pixels, if the image is being rendered. if (auto* paint_box = this->paint_box()) - return paint_box->content_height(); + return paint_box->content_height().value(); // NOTE: This step seems to not be in the spec, but all browsers do it. auto height_attr = get_attribute(HTML::AttributeNames::height); diff --git a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp index 0ad28aad66c..e927713f50f 100644 --- a/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/BlockFormattingContext.cpp @@ -539,7 +539,7 @@ void BlockFormattingContext::layout_initial_containing_block(LayoutMode layout_m if (bottom_edge >= viewport_rect.height() || right_edge >= viewport_rect.width()) { // FIXME: Move overflow data to LayoutState! auto& overflow_data = icb_state.ensure_overflow_data(); - overflow_data.scrollable_overflow_rect = viewport_rect.to_type(); + overflow_data.scrollable_overflow_rect = viewport_rect.to_type(); // NOTE: The edges are *within* the rectangle, so we add 1 to get the width and height. overflow_data.scrollable_overflow_rect.set_size(right_edge + 1, bottom_edge + 1); } diff --git a/Userland/Libraries/LibWeb/Layout/Box.cpp b/Userland/Libraries/LibWeb/Layout/Box.cpp index 73d770968da..1583ff0fd10 100644 --- a/Userland/Libraries/LibWeb/Layout/Box.cpp +++ b/Userland/Libraries/LibWeb/Layout/Box.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling - * Copyright (c) 2021, Sam Atkins + * Copyright (c) 2021-2022, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -31,8 +31,9 @@ Box::~Box() void Box::set_needs_display() { + // FIXME: Make `set_needs_display` take CSSPixels if (paint_box()) - browsing_context().set_needs_display(enclosing_int_rect(paint_box()->absolute_rect())); + browsing_context().set_needs_display(enclosing_int_rect(paint_box()->absolute_rect().to_type())); } bool Box::is_body() const diff --git a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp index a85121caf14..54343724618 100644 --- a/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/FormattingContext.cpp @@ -919,7 +919,7 @@ Gfx::FloatPoint FormattingContext::calculate_static_position(Box const& box) con } } if (last_fragment) { - y = last_fragment->offset().y() + last_fragment->height(); + y = (last_fragment->offset().y() + last_fragment->height()).value(); } } else { // Easy case: no previous sibling, we're at the top of the containing block. diff --git a/Userland/Libraries/LibWeb/Layout/FrameBox.cpp b/Userland/Libraries/LibWeb/Layout/FrameBox.cpp index 73d47dc022c..a761ff29745 100644 --- a/Userland/Libraries/LibWeb/Layout/FrameBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/FrameBox.cpp @@ -33,7 +33,8 @@ void FrameBox::did_set_rect() ReplacedBox::did_set_rect(); VERIFY(dom_node().nested_browsing_context()); - dom_node().nested_browsing_context()->set_size(paint_box()->content_size().to_type()); + // FIXME: Pass CSSPixels here instead of int. + dom_node().nested_browsing_context()->set_size(paint_box()->content_size().to_type().to_type()); } RefPtr FrameBox::create_paintable() const diff --git a/Userland/Libraries/LibWeb/Layout/ImageBox.cpp b/Userland/Libraries/LibWeb/Layout/ImageBox.cpp index 752d367177a..dcf195015ff 100644 --- a/Userland/Libraries/LibWeb/Layout/ImageBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/ImageBox.cpp @@ -94,7 +94,7 @@ bool ImageBox::renders_as_alt_text() const void ImageBox::browsing_context_did_set_viewport_rect(Gfx::IntRect const& viewport_rect) { - m_image_loader.set_visible_in_viewport(paint_box() && viewport_rect.to_type().intersects(paint_box()->absolute_rect())); + m_image_loader.set_visible_in_viewport(paint_box() && viewport_rect.to_type().intersects(paint_box()->absolute_rect())); } RefPtr ImageBox::create_paintable() const diff --git a/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.cpp b/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.cpp index ce92931b24f..4d56d16cde4 100644 --- a/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.cpp +++ b/Userland/Libraries/LibWeb/Layout/InitialContainingBlock.cpp @@ -49,7 +49,7 @@ void InitialContainingBlock::build_stacking_context_tree() void InitialContainingBlock::paint_all_phases(PaintContext& context) { build_stacking_context_tree_if_needed(); - context.painter().fill_rect(enclosing_int_rect(paint_box()->absolute_rect()), document().background_color(context.palette())); + context.painter().fill_rect(context.enclosing_device_rect(paint_box()->absolute_rect()).to_type(), document().background_color(context.palette())); context.painter().translate(-context.device_viewport_rect().location().to_type()); paint_box()->stacking_context()->paint(context); } diff --git a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp index ee16b26964e..38a1d70a1b0 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/InlineFormattingContext.cpp @@ -202,7 +202,7 @@ void InlineFormattingContext::apply_justification_to_fragments(CSS::TextJustify for (auto& fragment : line_box.fragments()) { if (fragment.is_justifiable_whitespace()) { ++whitespace_count; - excess_horizontal_space_including_whitespace += fragment.width(); + excess_horizontal_space_including_whitespace += fragment.width().value(); } } @@ -221,7 +221,7 @@ void InlineFormattingContext::apply_justification_to_fragments(CSS::TextJustify if (fragment.is_justifiable_whitespace() && fragment.width() != justified_space_width) { - running_diff += justified_space_width - fragment.width(); + running_diff += justified_space_width - fragment.width().value(); fragment.set_width(justified_space_width); } } diff --git a/Userland/Libraries/LibWeb/Layout/Label.cpp b/Userland/Libraries/LibWeb/Layout/Label.cpp index cdf0d7ac175..394589ea7c7 100644 --- a/Userland/Libraries/LibWeb/Layout/Label.cpp +++ b/Userland/Libraries/LibWeb/Layout/Label.cpp @@ -39,8 +39,8 @@ void Label::handle_mouseup_on_label(Badge, CSSPixelPoin return; if (auto* control = labeled_control(); control) { - bool is_inside_control = enclosing_int_rect(control->paint_box()->absolute_rect()).to_type().contains(position); - bool is_inside_label = enclosing_int_rect(paint_box()->absolute_rect()).to_type().contains(position); + bool is_inside_control = control->paint_box()->absolute_rect().contains(position); + bool is_inside_label = paint_box()->absolute_rect().contains(position); if (is_inside_control || is_inside_label) control->paintable()->handle_associated_label_mouseup({}); @@ -55,8 +55,8 @@ void Label::handle_mousemove_on_label(Badge, CSSPixelPo return; if (auto* control = labeled_control(); control) { - bool is_inside_control = enclosing_int_rect(control->paint_box()->absolute_rect()).to_type().contains(position); - bool is_inside_label = enclosing_int_rect(paint_box()->absolute_rect()).to_type().contains(position); + bool is_inside_control = control->paint_box()->absolute_rect().contains(position); + bool is_inside_label = paint_box()->absolute_rect().contains(position); control->paintable()->handle_associated_label_mousemove({}, is_inside_control || is_inside_label); } @@ -65,7 +65,7 @@ void Label::handle_mousemove_on_label(Badge, CSSPixelPo bool Label::is_inside_associated_label(LabelableNode const& control, CSSPixelPoint position) { if (auto* label = label_for_control_node(control); label) - return enclosing_int_rect(label->paint_box()->absolute_rect()).to_type().contains(position); + return label->paint_box()->absolute_rect().contains(position); return false; } diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp index 994957ae826..a5245b8275d 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.cpp @@ -76,7 +76,7 @@ void LayoutState::commit() if (is(node)) { auto& box = static_cast(node); auto& paint_box = const_cast(*box.paint_box()); - paint_box.set_offset(used_values.offset); + paint_box.set_offset(used_values.offset.to_type()); paint_box.set_content_size(used_values.content_width(), used_values.content_height()); paint_box.set_overflow_data(move(used_values.overflow_data)); paint_box.set_containing_line_box_fragment(used_values.containing_line_box_fragment); diff --git a/Userland/Libraries/LibWeb/Layout/LineBox.cpp b/Userland/Libraries/LibWeb/Layout/LineBox.cpp index 1e795ddcdd6..cbc0d68a20b 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/LineBox.cpp @@ -26,7 +26,7 @@ void LineBox::add_fragment(Node const& layout_node, int start, int length, float } else { float x_offset = leading_margin + leading_size + m_width; float y_offset = 0.0f; - m_fragments.append(LineBoxFragment { layout_node, start, length, Gfx::FloatPoint(x_offset, y_offset), Gfx::FloatSize(content_width, content_height), border_box_top, border_box_bottom, fragment_type }); + m_fragments.append(LineBoxFragment { layout_node, start, length, CSSPixelPoint(x_offset, y_offset), CSSPixelSize(content_width, content_height), border_box_top, border_box_bottom, fragment_type }); } m_width += leading_margin + leading_size + content_width + trailing_size + trailing_margin; } @@ -35,7 +35,7 @@ void LineBox::trim_trailing_whitespace() { while (!m_fragments.is_empty() && m_fragments.last().is_justifiable_whitespace()) { auto fragment = m_fragments.take_last(); - m_width -= fragment.width(); + m_width -= fragment.width().value(); } if (m_fragments.is_empty()) diff --git a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp index 17c83f96f49..4e8b9d5ffe5 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp +++ b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.cpp @@ -33,15 +33,15 @@ StringView LineBoxFragment::text() const return verify_cast(layout_node()).text_for_rendering().substring_view(m_start, m_length); } -const Gfx::FloatRect LineBoxFragment::absolute_rect() const +CSSPixelRect const LineBoxFragment::absolute_rect() const { - Gfx::FloatRect rect { {}, size() }; + CSSPixelRect rect { {}, size() }; rect.set_location(m_layout_node.containing_block()->paint_box()->absolute_position()); rect.translate_by(offset()); return rect; } -int LineBoxFragment::text_index_at(float x) const +int LineBoxFragment::text_index_at(CSSPixels x) const { if (!is(layout_node())) return 0; @@ -49,15 +49,15 @@ int LineBoxFragment::text_index_at(float x) const auto& font = layout_text.font(); Utf8View view(text()); - float relative_x = x - absolute_x(); + CSSPixels relative_x = x - absolute_x(); float glyph_spacing = font.glyph_spacing(); if (relative_x < 0) return 0; - float width_so_far = 0; + CSSPixels width_so_far = 0; for (auto it = view.begin(); it != view.end(); ++it) { - float glyph_width = font.glyph_or_emoji_width(*it); + CSSPixels glyph_width = font.glyph_or_emoji_width(*it); if ((width_so_far + (glyph_width + glyph_spacing) / 2) > relative_x) return m_start + view.byte_offset_of(it); width_so_far += glyph_width + glyph_spacing; @@ -65,7 +65,7 @@ int LineBoxFragment::text_index_at(float x) const return m_start + m_length; } -Gfx::FloatRect LineBoxFragment::selection_rect(Gfx::Font const& font) const +CSSPixelRect LineBoxFragment::selection_rect(Gfx::Font const& font) const { if (layout_node().selection_state() == Node::SelectionState::None) return {}; diff --git a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h index 4d938ab1d01..b8566b57f5b 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h +++ b/Userland/Libraries/LibWeb/Layout/LineBoxFragment.h @@ -6,9 +6,9 @@ #pragma once -#include #include #include +#include namespace Web::Layout { @@ -22,7 +22,7 @@ public: Trailing, }; - LineBoxFragment(Node const& layout_node, int start, int length, Gfx::FloatPoint offset, Gfx::FloatSize size, float border_box_top, float border_box_bottom, Type type) + LineBoxFragment(Node const& layout_node, int start, int length, CSSPixelPoint offset, CSSPixelSize size, CSSPixels border_box_top, CSSPixels border_box_bottom, Type type) : m_layout_node(layout_node) , m_start(start) , m_length(length) @@ -37,45 +37,54 @@ public: Node const& layout_node() const { return m_layout_node; } int start() const { return m_start; } int length() const { return m_length; } - const Gfx::FloatRect absolute_rect() const; + CSSPixelRect const absolute_rect() const; Type type() const { return m_type; } - Gfx::FloatPoint offset() const { return m_offset; } - void set_offset(Gfx::FloatPoint offset) { m_offset = offset; } + CSSPixelPoint offset() const + { + return m_offset; + } + void set_offset(CSSPixelPoint offset) { m_offset = offset; } // The baseline of a fragment is the number of pixels from the top to the text baseline. - void set_baseline(float y) { m_baseline = y; } - float baseline() const { return m_baseline; } + void set_baseline(CSSPixels y) { m_baseline = y; } + CSSPixels baseline() const { return m_baseline; } - Gfx::FloatSize size() const { return m_size; } - void set_width(float width) { m_size.set_width(width); } - void set_height(float height) { m_size.set_height(height); } - float width() const { return m_size.width(); } - float height() const { return m_size.height(); } + CSSPixelSize size() const + { + return m_size; + } + void set_width(CSSPixels width) { m_size.set_width(width); } + void set_height(CSSPixels height) { m_size.set_height(height); } + CSSPixels width() const { return m_size.width(); } + CSSPixels height() const { return m_size.height(); } - float border_box_height() const { return m_border_box_top + height() + m_border_box_bottom; } - float border_box_top() const { return m_border_box_top; } - float border_box_bottom() const { return m_border_box_bottom; } + CSSPixels border_box_height() const + { + return m_border_box_top + height() + m_border_box_bottom; + } + CSSPixels border_box_top() const { return m_border_box_top; } + CSSPixels border_box_bottom() const { return m_border_box_bottom; } - float absolute_x() const { return absolute_rect().x(); } + CSSPixels absolute_x() const { return absolute_rect().x(); } bool ends_in_whitespace() const; bool is_justifiable_whitespace() const; StringView text() const; - int text_index_at(float x) const; + int text_index_at(CSSPixels x) const; - Gfx::FloatRect selection_rect(Gfx::Font const&) const; + CSSPixelRect selection_rect(Gfx::Font const&) const; private: Node const& m_layout_node; int m_start { 0 }; int m_length { 0 }; - Gfx::FloatPoint m_offset; - Gfx::FloatSize m_size; - float m_border_box_top { 0 }; - float m_border_box_bottom { 0 }; - float m_baseline { 0 }; + CSSPixelPoint m_offset; + CSSPixelSize m_size; + CSSPixels m_border_box_top { 0 }; + CSSPixels m_border_box_bottom { 0 }; + CSSPixels m_baseline { 0 }; Type m_type { Type::Normal }; }; diff --git a/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp b/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp index 13fc619b4cf..bee5cc65947 100644 --- a/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp +++ b/Userland/Libraries/LibWeb/Layout/LineBuilder.cpp @@ -227,15 +227,15 @@ void LineBuilder::update_last_line() for (size_t i = 0; i < line_box.fragments().size(); ++i) { auto& fragment = line_box.fragments()[i]; - float new_fragment_x = roundf(x_offset + fragment.offset().x()); + float new_fragment_x = roundf(x_offset + fragment.offset().x().value()); float new_fragment_y = 0; auto y_value_for_alignment = [&](CSS::VerticalAlign vertical_align) { switch (vertical_align) { case CSS::VerticalAlign::Baseline: - return m_current_y + line_box_baseline - fragment.baseline() + fragment.border_box_top(); + return m_current_y + line_box_baseline - fragment.baseline().value() + fragment.border_box_top().value(); case CSS::VerticalAlign::Top: - return m_current_y + fragment.border_box_top(); + return m_current_y + fragment.border_box_top().value(); case CSS::VerticalAlign::Middle: case CSS::VerticalAlign::Bottom: case CSS::VerticalAlign::Sub: @@ -243,7 +243,7 @@ void LineBuilder::update_last_line() case CSS::VerticalAlign::TextBottom: case CSS::VerticalAlign::TextTop: // FIXME: These are all 'baseline' - return m_current_y + line_box_baseline - fragment.baseline() + fragment.border_box_top(); + return m_current_y + line_box_baseline - fragment.baseline().value() + fragment.border_box_top().value(); } VERIFY_NOT_REACHED(); }; @@ -266,15 +266,15 @@ void LineBuilder::update_last_line() // FIXME: Support inline-table elements. if (fragment.layout_node().is_replaced_box() || (fragment.layout_node().display().is_inline_outside() && !fragment.layout_node().display().is_flow_inside())) { auto const& fragment_box_state = m_layout_state.get(static_cast(fragment.layout_node())); - top_of_inline_box = fragment.offset().y() - fragment_box_state.margin_box_top(); - bottom_of_inline_box = fragment.offset().y() + fragment_box_state.content_height() + fragment_box_state.margin_box_bottom(); + top_of_inline_box = (fragment.offset().y() - fragment_box_state.margin_box_top()).value(); + bottom_of_inline_box = (fragment.offset().y() + fragment_box_state.content_height() + fragment_box_state.margin_box_bottom()).value(); } else { auto font_metrics = fragment.layout_node().font().pixel_metrics(); auto typographic_height = font_metrics.ascent + font_metrics.descent; auto leading = fragment.layout_node().line_height() - typographic_height; auto half_leading = leading / 2; - top_of_inline_box = fragment.offset().y() + fragment.baseline() - font_metrics.ascent - half_leading; - bottom_of_inline_box = fragment.offset().y() + fragment.baseline() + font_metrics.descent + half_leading; + top_of_inline_box = (fragment.offset().y() + fragment.baseline() - font_metrics.ascent - half_leading).value(); + bottom_of_inline_box = (fragment.offset().y() + fragment.baseline() + font_metrics.descent + half_leading).value(); } if (auto length_percentage = fragment.layout_node().computed_values().vertical_align().template get_pointer(); length_percentage && length_percentage->is_length()) bottom_of_inline_box += length_percentage->length().to_px(fragment.layout_node()); diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 65643c1e57d..86f2e02b0c7 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -158,7 +158,7 @@ void Node::set_needs_display() return; containing_block->paint_box()->for_each_fragment([&](auto& fragment) { if (&fragment.layout_node() == this || is_ancestor_of(fragment.layout_node())) { - browsing_context().set_needs_display(enclosing_int_rect(fragment.absolute_rect())); + browsing_context().set_needs_display(fragment.absolute_rect().template to_type().template to_type()); } return IterationDecision::Continue; }); @@ -167,13 +167,13 @@ void Node::set_needs_display() Gfx::FloatPoint Node::box_type_agnostic_position() const { if (is(*this)) - return verify_cast(*this).paint_box()->absolute_position(); + return verify_cast(*this).paint_box()->absolute_position().to_type(); VERIFY(is_inline()); Gfx::FloatPoint position; if (auto* block = containing_block()) { block->paint_box()->for_each_fragment([&](auto& fragment) { if (&fragment.layout_node() == this || is_ancestor_of(fragment.layout_node())) { - position = fragment.absolute_rect().location(); + position = fragment.absolute_rect().location().template to_type(); return IterationDecision::Break; } return IterationDecision::Continue; diff --git a/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.cpp b/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.cpp index 9b1a82e9dc8..cfc0add2880 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/SVGGeometryBox.cpp @@ -27,10 +27,10 @@ float SVGGeometryBox::viewbox_scaling() const auto view_box = svg_box->view_box().value(); bool has_specified_width = svg_box->has_attribute(HTML::AttributeNames::width); - auto specified_width = paint_box()->content_width(); + auto specified_width = paint_box()->content_width().value(); bool has_specified_height = svg_box->has_attribute(HTML::AttributeNames::height); - auto specified_height = paint_box()->content_height(); + auto specified_height = paint_box()->content_height().value(); auto scale_width = has_specified_width ? specified_width / view_box.width : 1; auto scale_height = has_specified_height ? specified_height / view_box.height : 1; diff --git a/Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp b/Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp index 63c1f33c40c..04ce0b3d1dc 100644 --- a/Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ButtonPaintable.cpp @@ -42,10 +42,12 @@ void ButtonPaintable::paint(PaintContext& context, PaintPhase phase) const auto const& dom_node = layout_box().dom_node(); if (is(dom_node) && phase == PaintPhase::Foreground) { - auto text_rect = enclosing_int_rect(absolute_rect()); - if (being_pressed()) - text_rect.translate_by(1, 1); - context.painter().draw_text(text_rect, static_cast(dom_node).value(), layout_box().font(), Gfx::TextAlignment::Center, computed_values().color()); + auto text_rect = context.enclosing_device_rect(absolute_rect()); + if (being_pressed()) { + auto offset = context.rounded_device_pixels(1); + text_rect.translate_by(offset, offset); + } + context.painter().draw_text(text_rect.to_type(), static_cast(dom_node).value(), layout_box().font(), Gfx::TextAlignment::Center, computed_values().color()); } } diff --git a/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp b/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp index ff584c6cb07..f472d41dab3 100644 --- a/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/CanvasPaintable.cpp @@ -31,7 +31,7 @@ void CanvasPaintable::paint(PaintContext& context, PaintPhase phase) const PaintableBox::paint(context, phase); if (phase == PaintPhase::Foreground) { - auto canvas_rect = context.rounded_device_rect(absolute_rect().to_type()); + auto canvas_rect = context.rounded_device_rect(absolute_rect()); ScopedCornerRadiusClip corner_clip { context, context.painter(), canvas_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) }; // FIXME: This should be done at a different level. diff --git a/Userland/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp b/Userland/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp index 26203547003..b2a479bf8a1 100644 --- a/Userland/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp @@ -43,7 +43,7 @@ void CheckBoxPaintable::paint(PaintContext& context, PaintPhase phase) const auto const& checkbox = static_cast(layout_box().dom_node()); if (phase == PaintPhase::Foreground) - Gfx::StylePainter::paint_check_box(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), layout_box().dom_node().enabled(), checkbox.checked(), being_pressed()); + Gfx::StylePainter::paint_check_box(context.painter(), context.enclosing_device_rect(absolute_rect()).to_type(), context.palette(), layout_box().dom_node().enabled(), checkbox.checked(), being_pressed()); } } diff --git a/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp b/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp index 2fdfb30dc79..f572a41bfe1 100644 --- a/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ImagePaintable.cpp @@ -42,14 +42,15 @@ void ImagePaintable::paint(PaintContext& context, PaintPhase phase) const if (phase == PaintPhase::Foreground) { if (layout_box().renders_as_alt_text()) { auto& image_element = verify_cast(*dom_node()); + auto enclosing_rect = context.enclosing_device_rect(absolute_rect()).to_type(); context.painter().set_font(Platform::FontPlugin::the().default_font()); - Gfx::StylePainter::paint_frame(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), Gfx::FrameShape::Container, Gfx::FrameShadow::Sunken, 2); + Gfx::StylePainter::paint_frame(context.painter(), enclosing_rect, context.palette(), Gfx::FrameShape::Container, Gfx::FrameShadow::Sunken, 2); auto alt = image_element.alt(); if (alt.is_empty()) alt = image_element.src(); - context.painter().draw_text(enclosing_int_rect(absolute_rect()), alt, Gfx::TextAlignment::Center, computed_values().color(), Gfx::TextElision::Right); + context.painter().draw_text(enclosing_rect, alt, Gfx::TextAlignment::Center, computed_values().color(), Gfx::TextElision::Right); } else if (auto bitmap = layout_box().image_loader().bitmap(layout_box().image_loader().current_frame_index())) { - auto image_rect = context.rounded_device_rect(absolute_rect().to_type()); + auto image_rect = context.rounded_device_rect(absolute_rect()); ScopedCornerRadiusClip corner_clip { context, context.painter(), image_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) }; context.painter().draw_scaled_bitmap(image_rect.to_type(), *bitmap, bitmap->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering())); } diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp index fddf2b144ef..615e82d1add 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp @@ -41,7 +41,7 @@ void InlinePaintable::paint(PaintContext& context, Painting::PaintPhase phase) c auto containing_block_position_in_absolute_coordinates = containing_block()->paint_box()->absolute_position(); for_each_fragment([&](auto const& fragment, bool is_first_fragment, bool is_last_fragment) { - Gfx::FloatRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() }; + CSSPixelRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() }; if (is_first_fragment) { float extra_start_width = box_model().padding.left; @@ -54,8 +54,8 @@ void InlinePaintable::paint(PaintContext& context, Painting::PaintPhase phase) c absolute_fragment_rect.set_width(absolute_fragment_rect.width() + extra_end_width); } - auto border_radii_data = Painting::normalized_border_radii_data(layout_node(), absolute_fragment_rect.to_type(), top_left_border_radius, top_right_border_radius, bottom_right_border_radius, bottom_left_border_radius); - Painting::paint_background(context, layout_node(), absolute_fragment_rect.to_type(), computed_values().background_color(), computed_values().image_rendering(), &computed_values().background_layers(), border_radii_data); + auto border_radii_data = Painting::normalized_border_radii_data(layout_node(), absolute_fragment_rect, top_left_border_radius, top_right_border_radius, bottom_right_border_radius, bottom_left_border_radius); + Painting::paint_background(context, layout_node(), absolute_fragment_rect, computed_values().background_color(), computed_values().image_rendering(), &computed_values().background_layers(), border_radii_data); if (auto computed_box_shadow = computed_values().box_shadow(); !computed_box_shadow.is_empty()) { Vector resolved_box_shadow_data; @@ -69,7 +69,7 @@ void InlinePaintable::paint(PaintContext& context, Painting::PaintPhase phase) c layer.spread_distance.to_px(layout_node()), layer.placement == CSS::ShadowPlacement::Outer ? Painting::ShadowPlacement::Outer : Painting::ShadowPlacement::Inner); } - Painting::paint_box_shadow(context, absolute_fragment_rect.to_type(), border_radii_data, resolved_box_shadow_data); + Painting::paint_box_shadow(context, absolute_fragment_rect, border_radii_data, resolved_box_shadow_data); } return IterationDecision::Continue; @@ -121,7 +121,7 @@ void InlinePaintable::paint(PaintContext& context, Painting::PaintPhase phase) c // would be none. Once we implement non-rectangular outlines for the `outline` CSS // property, we can use that here instead. for_each_fragment([&](auto const& fragment, bool, bool) { - painter.draw_rect(enclosing_int_rect(fragment.absolute_rect()), Color::Magenta); + painter.draw_rect(context.enclosing_device_rect(fragment.absolute_rect()).template to_type(), Color::Magenta); return IterationDecision::Continue; }); } diff --git a/Userland/Libraries/LibWeb/Painting/LabelablePaintable.cpp b/Userland/Libraries/LibWeb/Painting/LabelablePaintable.cpp index ebedfdf9672..8becfa08122 100644 --- a/Userland/Libraries/LibWeb/Painting/LabelablePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/LabelablePaintable.cpp @@ -51,7 +51,7 @@ LabelablePaintable::DispatchEventOfSameName LabelablePaintable::handle_mouseup(B if (!m_tracking_mouse || button != GUI::MouseButton::Primary || !layout_box().dom_node().enabled()) return DispatchEventOfSameName::No; - bool is_inside_node_or_label = absolute_rect().to_type().contains(position); + bool is_inside_node_or_label = absolute_rect().contains(position); if (!is_inside_node_or_label) is_inside_node_or_label = Layout::Label::is_inside_associated_label(layout_box(), position); @@ -66,7 +66,7 @@ LabelablePaintable::DispatchEventOfSameName LabelablePaintable::handle_mousemove if (!m_tracking_mouse || !layout_box().dom_node().enabled()) return DispatchEventOfSameName::No; - bool is_inside_node_or_label = absolute_rect().to_type().contains(position); + bool is_inside_node_or_label = absolute_rect().contains(position); if (!is_inside_node_or_label) is_inside_node_or_label = Layout::Label::is_inside_associated_label(layout_box(), position); diff --git a/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp b/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp index 6911166c847..8227a1c755a 100644 --- a/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp @@ -31,7 +31,8 @@ void MarkerPaintable::paint(PaintContext& context, PaintPhase phase) const if (phase != PaintPhase::Foreground) return; - CSSPixelRect enclosing = absolute_rect().to_rounded().to_type(); + // FIXME: All this does is round to the nearest whole CSS pixel, but it's goofy. + CSSPixelRect enclosing = absolute_rect().to_type().to_rounded().to_type(); auto device_enclosing = context.enclosing_device_rect(enclosing); CSSPixels marker_width = enclosing.height() / 2.0f; diff --git a/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp b/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp index 5fd754859a2..3c19b5a2a37 100644 --- a/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp @@ -36,7 +36,8 @@ void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase pha PaintableBox::paint(context, phase); if (phase == PaintPhase::Foreground) { - auto clip_rect = context.rounded_device_rect(absolute_rect().to_type()); + auto absolute_rect = this->absolute_rect(); + auto clip_rect = context.rounded_device_rect(absolute_rect); ScopedCornerRadiusClip corner_clip { context, context.painter(), clip_rect, normalized_border_radii_data(ShrinkRadiiForBorders::Yes) }; auto* hosted_document = layout_box().dom_node().content_document_without_origin_check(); @@ -50,7 +51,7 @@ void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase pha auto old_viewport_rect = context.device_viewport_rect(); context.painter().add_clip_rect(clip_rect.to_type()); - context.painter().translate(absolute_x(), absolute_y()); + context.painter().translate(absolute_rect.x().value(), absolute_rect.y().value()); context.set_device_viewport_rect({ {}, layout_box().dom_node().nested_browsing_context()->size() }); const_cast(hosted_layout_tree)->paint_all_phases(context); @@ -60,7 +61,7 @@ void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase pha if constexpr (HIGHLIGHT_FOCUSED_FRAME_DEBUG) { if (layout_box().dom_node().nested_browsing_context()->is_focused_context()) { - context.painter().draw_rect(absolute_rect().to_type(), Color::Cyan); + context.painter().draw_rect(clip_rect.to_type(), Color::Cyan); } } } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index 477af9a7565..d09f20dc194 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Andreas Kling + * Copyright (c) 2022, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -39,7 +40,8 @@ void PaintableBox::invalidate_stacking_context() bool PaintableBox::is_out_of_view(PaintContext& context) const { - return !enclosing_int_rect(absolute_paint_rect()) + return !context.enclosing_device_rect(absolute_paint_rect()) + .to_type() .translated(context.painter().translation()) .intersects(context.painter().clip_rect()); } @@ -53,23 +55,23 @@ PaintableWithLines::~PaintableWithLines() { } -void PaintableBox::set_offset(Gfx::FloatPoint offset) +void PaintableBox::set_offset(CSSPixelPoint offset) { m_offset = offset; // FIXME: This const_cast is gross. const_cast(layout_box()).did_set_rect(); } -void PaintableBox::set_content_size(Gfx::FloatSize size) +void PaintableBox::set_content_size(CSSPixelSize size) { m_content_size = size; // FIXME: This const_cast is gross. const_cast(layout_box()).did_set_rect(); } -Gfx::FloatPoint PaintableBox::effective_offset() const +CSSPixelPoint PaintableBox::effective_offset() const { - Gfx::FloatPoint offset; + CSSPixelPoint offset; if (m_containing_line_box_fragment.has_value()) { // FIXME: This is a hack to deal with situations where the layout tree has been garbage collected. @@ -89,22 +91,22 @@ Gfx::FloatPoint PaintableBox::effective_offset() const return offset; } -Gfx::FloatRect PaintableBox::compute_absolute_rect() const +CSSPixelRect PaintableBox::compute_absolute_rect() const { - Gfx::FloatRect rect { effective_offset(), content_size() }; + CSSPixelRect rect { effective_offset(), content_size() }; for (auto const* block = containing_block(); block && block->paintable(); block = block->paintable()->containing_block()) rect.translate_by(block->paint_box()->effective_offset()); return rect; } -Gfx::FloatRect PaintableBox::absolute_rect() const +CSSPixelRect PaintableBox::absolute_rect() const { if (!m_absolute_rect.has_value()) m_absolute_rect = compute_absolute_rect(); return *m_absolute_rect; } -Gfx::FloatRect PaintableBox::compute_absolute_paint_rect() const +CSSPixelRect PaintableBox::compute_absolute_paint_rect() const { // FIXME: This likely incomplete: auto rect = absolute_border_box_rect(); @@ -112,14 +114,14 @@ Gfx::FloatRect PaintableBox::compute_absolute_paint_rect() const for (auto const& shadow : resolved_box_shadow_data) { if (shadow.placement == ShadowPlacement::Inner) continue; - auto inflate = shadow.spread_distance.value() + shadow.blur_radius.value(); - auto shadow_rect = rect.inflated(inflate, inflate, inflate, inflate).translated(shadow.offset_x.value(), shadow.offset_y.value()); + auto inflate = shadow.spread_distance + shadow.blur_radius; + auto shadow_rect = rect.inflated(inflate, inflate, inflate, inflate).translated(shadow.offset_x, shadow.offset_y); rect = rect.united(shadow_rect); } return rect; } -Gfx::FloatRect PaintableBox::absolute_paint_rect() const +CSSPixelRect PaintableBox::absolute_paint_rect() const { if (!m_absolute_paint_rect.has_value()) m_absolute_paint_rect = compute_absolute_paint_rect(); @@ -156,7 +158,7 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const if (should_clip_rect) { context.painter().save(); auto border_box = absolute_border_box_rect(); - context.painter().add_clip_rect(context.rounded_device_rect(clip_rect.to_rect().resolved(Paintable::layout_node(), border_box).to_type()).to_type()); + context.painter().add_clip_rect(context.rounded_device_rect(clip_rect.to_rect().resolved(Paintable::layout_node(), border_box.to_type()).to_type()).to_type()); } paint_backdrop_filter(context); paint_background(context); @@ -171,7 +173,7 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const context.painter().restore(); if (phase == PaintPhase::Overlay && layout_box().dom_node() && layout_box().document().inspected_node() == layout_box().dom_node()) { - auto content_rect = absolute_rect().to_type(); + auto content_rect = absolute_rect(); auto margin_box = box_model().margin_box(); CSSPixelRect margin_rect; @@ -180,8 +182,8 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const margin_rect.set_y(absolute_y() - margin_box.top); margin_rect.set_height(content_height() + margin_box.top + margin_box.bottom); - auto border_rect = absolute_border_box_rect().to_type(); - auto padding_rect = absolute_padding_box_rect().to_type(); + auto border_rect = absolute_border_box_rect(); + auto padding_rect = absolute_padding_box_rect(); auto paint_inspector_rect = [&](CSSPixelRect const& rect, Color color) { auto device_rect = context.enclosing_device_rect(rect).to_type(); @@ -216,7 +218,7 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const if (phase == PaintPhase::FocusOutline && layout_box().dom_node() && layout_box().dom_node()->is_element() && verify_cast(*layout_box().dom_node()).is_focused()) { // FIXME: Implement this as `outline` using :focus-visible in the default UA stylesheet to make it possible to override/disable. - auto focus_outline_rect = context.enclosing_device_rect(absolute_border_box_rect().to_type()).inflated(4, 4); + auto focus_outline_rect = context.enclosing_device_rect(absolute_border_box_rect()).inflated(4, 4); context.painter().draw_focus_rect(focus_outline_rect.to_type(), context.palette().focus_outline()); } } @@ -229,14 +231,14 @@ void PaintableBox::paint_border(PaintContext& context) const .bottom = computed_values().border_bottom(), .left = computed_values().border_left(), }; - paint_all_borders(context, absolute_border_box_rect().to_type(), normalized_border_radii_data(), borders_data); + paint_all_borders(context, absolute_border_box_rect(), normalized_border_radii_data(), borders_data); } void PaintableBox::paint_backdrop_filter(PaintContext& context) const { auto& backdrop_filter = computed_values().backdrop_filter(); if (!backdrop_filter.is_none()) - Painting::apply_backdrop_filter(context, layout_node(), absolute_border_box_rect().to_type(), normalized_border_radii_data(), backdrop_filter); + Painting::apply_backdrop_filter(context, layout_node(), absolute_border_box_rect(), normalized_border_radii_data(), backdrop_filter); } void PaintableBox::paint_background(PaintContext& context) const @@ -260,13 +262,13 @@ void PaintableBox::paint_background(PaintContext& context) const background_color = document().background_color(context.palette()); } } else { - background_rect = absolute_padding_box_rect().to_type(); + background_rect = absolute_padding_box_rect(); } // HACK: If the Box has a border, use the bordered_rect to paint the background. // This way if we have a border-radius there will be no gap between the filling and actual border. if (computed_values().border_top().width || computed_values().border_right().width || computed_values().border_bottom().width || computed_values().border_left().width) - background_rect = absolute_border_box_rect().to_type(); + background_rect = absolute_border_box_rect(); Painting::paint_background(context, layout_box(), background_rect, background_color, computed_values().image_rendering(), background_layers, normalized_border_radii_data()); } @@ -297,13 +299,13 @@ void PaintableBox::paint_box_shadow(PaintContext& context) const auto resolved_box_shadow_data = resolve_box_shadow_data(); if (resolved_box_shadow_data.is_empty()) return; - Painting::paint_box_shadow(context, absolute_border_box_rect().to_type(), normalized_border_radii_data(), resolved_box_shadow_data); + Painting::paint_box_shadow(context, absolute_border_box_rect(), normalized_border_radii_data(), resolved_box_shadow_data); } BorderRadiiData PaintableBox::normalized_border_radii_data(ShrinkRadiiForBorders shrink) const { auto border_radius_data = Painting::normalized_border_radii_data(layout_box(), - absolute_border_box_rect().to_type(), + absolute_border_box_rect(), computed_values().border_top_left_radius(), computed_values().border_top_right_radius(), computed_values().border_bottom_right_radius(), @@ -324,9 +326,9 @@ Optional PaintableBox::clip_rect() const if (overflow_x == CSS::Overflow::Hidden && overflow_y == CSS::Overflow::Hidden) { if (m_clip_rect.has_value()) { - m_clip_rect->intersect(absolute_padding_box_rect().to_rounded()); + m_clip_rect->intersect(absolute_padding_box_rect().to_type().to_rounded()); } else { - m_clip_rect = absolute_padding_box_rect().to_rounded(); + m_clip_rect = absolute_padding_box_rect().to_type().to_rounded(); } } } @@ -407,7 +409,7 @@ static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const if (!fragment.layout_node().dom_node() || !fragment.layout_node().dom_node()->is_editable()) return; - auto fragment_rect = fragment.absolute_rect().to_type(); + auto fragment_rect = fragment.absolute_rect(); CSSPixelRect cursor_rect { fragment_rect.x() + text_node.font().width(fragment.text().substring_view(0, text_node.browsing_context().cursor_position().offset() - fragment.start())), @@ -424,7 +426,7 @@ static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const static void paint_text_decoration(PaintContext& context, Gfx::Painter& painter, Layout::Node const& text_node, Layout::LineBoxFragment const& fragment) { auto& font = fragment.layout_node().font(); - auto fragment_box = fragment.absolute_rect().to_type(); + auto fragment_box = fragment.absolute_rect(); CSSPixels glyph_height = font.pixel_size(); auto baseline = fragment_box.height() / 2 - (glyph_height + 4) / 2 + glyph_height; @@ -507,7 +509,7 @@ static void paint_text_fragment(PaintContext& context, Layout::TextNode const& t auto& painter = context.painter(); if (phase == Painting::PaintPhase::Foreground) { - auto fragment_absolute_rect = fragment.absolute_rect().to_type(); + auto fragment_absolute_rect = fragment.absolute_rect(); auto fragment_absolute_device_rect = context.enclosing_device_rect(fragment_absolute_rect); if (text_node.document().inspected_node() == &text_node.dom_node()) @@ -521,16 +523,16 @@ static void paint_text_fragment(PaintContext& context, Layout::TextNode const& t if (text_transform == CSS::TextTransform::Lowercase) text = Unicode::to_unicode_lowercase_full(text_node.text_for_rendering()); - DevicePixelPoint baseline_start { fragment_absolute_device_rect.x(), fragment_absolute_device_rect.y() + fragment.baseline() }; + DevicePixelPoint baseline_start { fragment_absolute_device_rect.x(), fragment_absolute_device_rect.y() + context.rounded_device_pixels(fragment.baseline()) }; Utf8View view { text.substring_view(fragment.start(), fragment.length()) }; painter.draw_text_run(baseline_start.to_type(), view, fragment.layout_node().font(), text_node.computed_values().color()); - auto selection_rect = fragment.selection_rect(text_node.font()); + auto selection_rect = context.enclosing_device_rect(fragment.selection_rect(text_node.font())).to_type(); if (!selection_rect.is_empty()) { - painter.fill_rect(enclosing_int_rect(selection_rect), context.palette().selection()); + painter.fill_rect(selection_rect, context.palette().selection()); Gfx::PainterStateSaver saver(painter); - painter.add_clip_rect(enclosing_int_rect(selection_rect)); + painter.add_clip_rect(selection_rect); painter.draw_text_run(baseline_start.to_type(), view, fragment.layout_node().font(), context.palette().selection_text()); } @@ -555,7 +557,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const if (should_clip_overflow) { context.painter().save(); // FIXME: Handle overflow-x and overflow-y being different values. - auto clip_box = context.rounded_device_rect(absolute_padding_box_rect().to_type()); + auto clip_box = context.rounded_device_rect(absolute_padding_box_rect()); context.painter().add_clip_rect(clip_box.to_type()); auto scroll_offset = static_cast(layout_box()).scroll_offset(); context.painter().translate(-scroll_offset.to_type()); @@ -603,10 +605,10 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const for (auto& fragment : line_box.fragments()) { if (context.should_show_line_box_borders()) { auto fragment_absolute_rect = fragment.absolute_rect(); - context.painter().draw_rect(enclosing_int_rect(fragment_absolute_rect), Color::Green); + context.painter().draw_rect(context.enclosing_device_rect(fragment_absolute_rect).to_type(), Color::Green); context.painter().draw_line( - fragment_absolute_rect.top_left().translated(0, fragment.baseline()).to_rounded(), - fragment_absolute_rect.top_right().translated(0, fragment.baseline()).to_rounded(), Color::Red); + context.rounded_device_point(fragment_absolute_rect.top_left().translated(0, fragment.baseline())).to_type(), + context.rounded_device_point(fragment_absolute_rect.top_right().translated(0, fragment.baseline())).to_type(), Color::Red); } if (is(fragment.layout_node())) paint_text_fragment(context, static_cast(fragment.layout_node()), fragment, phase); @@ -631,7 +633,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const continue; if (parent->is_focused()) { // FIXME: Implement this as `outline` using :focus-visible in the default UA stylesheet to make it possible to override/disable. - auto focus_outline_rect = enclosing_int_rect(fragment.absolute_rect()).inflated(4, 4); + auto focus_outline_rect = context.enclosing_device_rect(fragment.absolute_rect()).to_type().inflated(4, 4); context.painter().draw_focus_rect(focus_outline_rect, context.palette().focus_outline()); } } @@ -674,7 +676,7 @@ Optional PaintableBox::hit_test(CSSPixelPoint position, HitTestTy return stacking_context()->hit_test(position, type); } - if (!absolute_border_box_rect().contains(position.x().value(), position.y().value())) + if (!absolute_border_box_rect().contains(position.x(), position.y())) return {}; for (auto* child = first_child(); child; child = child->next_sibling()) { @@ -702,11 +704,11 @@ Optional PaintableWithLines::hit_test(CSSPixelPoint position, Hit dbgln("FIXME: PaintableWithLines::hit_test(): Missing containing block on {}", fragment.layout_node().debug_description()); continue; } - auto fragment_absolute_rect = fragment.absolute_rect().to_type(); + auto fragment_absolute_rect = fragment.absolute_rect(); if (fragment_absolute_rect.contains(position)) { if (is(fragment.layout_node()) && fragment.layout_node().paintable()) return fragment.layout_node().paintable()->hit_test(position, type); - return HitTestResult { *fragment.layout_node().paintable(), fragment.text_index_at(position.x().value()) }; + return HitTestResult { *fragment.layout_node().paintable(), fragment.text_index_at(position.x()) }; } // If we reached this point, the position is not within the fragment. However, the fragment start or end might be the place to place the cursor. @@ -730,7 +732,7 @@ Optional PaintableWithLines::hit_test(CSSPixelPoint position, Hit if (type == HitTestType::TextCursor && last_good_candidate.has_value()) return last_good_candidate; - if (is_visible() && absolute_border_box_rect().contains(position.x().value(), position.y().value())) + if (is_visible() && absolute_border_box_rect().contains(position.x(), position.y())) return HitTestResult { *this }; return {}; } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index a509c1d8860..e2f140f3940 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -28,29 +28,29 @@ public: auto const& box_model() const { return layout_box().box_model(); } struct OverflowData { - Gfx::FloatRect scrollable_overflow_rect; - Gfx::FloatPoint scroll_offset; + CSSPixelRect scrollable_overflow_rect; + CSSPixelPoint scroll_offset; }; - Gfx::FloatRect absolute_rect() const; - Gfx::FloatPoint effective_offset() const; + CSSPixelRect absolute_rect() const; + CSSPixelPoint effective_offset() const; - void set_offset(Gfx::FloatPoint); + void set_offset(CSSPixelPoint); void set_offset(float x, float y) { set_offset({ x, y }); } - Gfx::FloatSize content_size() const { return m_content_size; } - void set_content_size(Gfx::FloatSize); - void set_content_size(float width, float height) { set_content_size({ width, height }); } + CSSPixelSize const& content_size() const { return m_content_size; } + void set_content_size(CSSPixelSize); + void set_content_size(CSSPixels width, CSSPixels height) { set_content_size({ width, height }); } - void set_content_width(float width) { set_content_size(width, content_height()); } - void set_content_height(float height) { set_content_size(content_width(), height); } - float content_width() const { return m_content_size.width(); } - float content_height() const { return m_content_size.height(); } + void set_content_width(CSSPixels width) { set_content_size(width, content_height()); } + void set_content_height(CSSPixels height) { set_content_size(content_width(), height); } + CSSPixels content_width() const { return m_content_size.width(); } + CSSPixels content_height() const { return m_content_size.height(); } - Gfx::FloatRect absolute_padding_box_rect() const + CSSPixelRect absolute_padding_box_rect() const { auto absolute_rect = this->absolute_rect(); - Gfx::FloatRect rect; + CSSPixelRect rect; rect.set_x(absolute_rect.x() - box_model().padding.left); rect.set_width(content_width() + box_model().padding.left + box_model().padding.right); rect.set_y(absolute_rect.y() - box_model().padding.top); @@ -58,10 +58,10 @@ public: return rect; } - Gfx::FloatRect absolute_border_box_rect() const + CSSPixelRect absolute_border_box_rect() const { auto padded_rect = this->absolute_padding_box_rect(); - Gfx::FloatRect rect; + CSSPixelRect rect; rect.set_x(padded_rect.x() - box_model().border.left); rect.set_width(padded_rect.width() + box_model().border.left + box_model().border.right); rect.set_y(padded_rect.y() - box_model().border.top); @@ -69,27 +69,27 @@ public: return rect; } - Gfx::FloatRect absolute_paint_rect() const; + CSSPixelRect absolute_paint_rect() const; - float border_box_width() const + CSSPixels border_box_width() const { auto border_box = box_model().border_box(); return content_width() + border_box.left + border_box.right; } - float border_box_height() const + CSSPixels border_box_height() const { auto border_box = box_model().border_box(); return content_height() + border_box.top + border_box.bottom; } - float absolute_x() const { return absolute_rect().x(); } - float absolute_y() const { return absolute_rect().y(); } - Gfx::FloatPoint absolute_position() const { return absolute_rect().location(); } + CSSPixels absolute_x() const { return absolute_rect().x(); } + CSSPixels absolute_y() const { return absolute_rect().y(); } + CSSPixelPoint absolute_position() const { return absolute_rect().location(); } bool has_overflow() const { return m_overflow_data.has_value(); } - Optional scrollable_overflow_rect() const + Optional scrollable_overflow_rect() const { if (!m_overflow_data.has_value()) return {}; @@ -129,8 +129,8 @@ protected: virtual void paint_background(PaintContext&) const; virtual void paint_box_shadow(PaintContext&) const; - virtual Gfx::FloatRect compute_absolute_rect() const; - virtual Gfx::FloatRect compute_absolute_paint_rect() const; + virtual CSSPixelRect compute_absolute_rect() const; + virtual CSSPixelRect compute_absolute_paint_rect() const; enum class ShrinkRadiiForBorders { Yes, @@ -144,16 +144,16 @@ protected: private: Optional m_overflow_data; - Gfx::FloatPoint m_offset; - Gfx::FloatSize m_content_size; + CSSPixelPoint m_offset; + CSSPixelSize m_content_size; // Some boxes hang off of line box fragments. (inline-block, inline-table, replaced, etc) Optional m_containing_line_box_fragment; OwnPtr m_stacking_context; - Optional mutable m_absolute_rect; - Optional mutable m_absolute_paint_rect; + Optional mutable m_absolute_rect; + Optional mutable m_absolute_paint_rect; Optional mutable m_clip_rect; diff --git a/Userland/Libraries/LibWeb/Painting/ProgressPaintable.cpp b/Userland/Libraries/LibWeb/Painting/ProgressPaintable.cpp index 785fc34e814..58db36fd33c 100644 --- a/Userland/Libraries/LibWeb/Painting/ProgressPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ProgressPaintable.cpp @@ -30,10 +30,13 @@ void ProgressPaintable::paint(PaintContext& context, PaintPhase phase) const return; if (phase == PaintPhase::Foreground) { - auto progress_rect = absolute_rect().to_rounded(); - auto frame_thickness = min(min(progress_rect.width(), progress_rect.height()) / 6, 3); - Gfx::StylePainter::paint_progressbar(context.painter(), progress_rect.shrunken(frame_thickness, frame_thickness), context.palette(), 0, round_to(layout_box().dom_node().max()), round_to(layout_box().dom_node().value()), ""sv); - Gfx::StylePainter::paint_frame(context.painter(), progress_rect, context.palette(), Gfx::FrameShape::Box, Gfx::FrameShadow::Raised, frame_thickness); + auto progress_rect = context.rounded_device_rect(absolute_rect()); + auto min_frame_thickness = context.rounded_device_pixels(3); + auto frame_thickness = min(min(progress_rect.width(), progress_rect.height()) / 6, min_frame_thickness); + + Gfx::StylePainter::paint_progressbar(context.painter(), progress_rect.shrunken(frame_thickness, frame_thickness).to_type(), context.palette(), 0, round_to(layout_box().dom_node().max()), round_to(layout_box().dom_node().value()), ""sv); + + Gfx::StylePainter::paint_frame(context.painter(), progress_rect.to_type(), context.palette(), Gfx::FrameShape::Box, Gfx::FrameShadow::Raised, frame_thickness.value()); } } diff --git a/Userland/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp b/Userland/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp index a4b3abfd922..8534e3fe73e 100644 --- a/Userland/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp @@ -34,7 +34,7 @@ void RadioButtonPaintable::paint(PaintContext& context, PaintPhase phase) const auto const& radio_box = static_cast(layout_box().dom_node()); if (phase == PaintPhase::Foreground) - Gfx::StylePainter::paint_radio_button(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), radio_box.checked(), being_pressed()); + Gfx::StylePainter::paint_radio_button(context.painter(), context.enclosing_device_rect(absolute_rect()).to_type(), context.palette(), radio_box.checked(), being_pressed()); } } diff --git a/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp index ab124398d37..c8f20d5fa95 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGGeometryPaintable.cpp @@ -47,7 +47,7 @@ void SVGGeometryPaintable::paint(PaintContext& context, PaintPhase phase) const auto const* svg_element = geometry_element.first_ancestor_of_type(); auto maybe_view_box = svg_element->view_box(); - context.painter().add_clip_rect(enclosing_int_rect(absolute_rect())); + context.painter().add_clip_rect(context.enclosing_device_rect(absolute_rect()).to_type()); Gfx::Path path = const_cast(geometry_element).get_path(); diff --git a/Userland/Libraries/LibWeb/Painting/SVGPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGPaintable.cpp index e1dae922978..2d202fc9cfe 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGPaintable.cpp @@ -36,10 +36,10 @@ void SVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase) context.svg_context().restore(); } -Gfx::FloatRect SVGPaintable::compute_absolute_rect() const +CSSPixelRect SVGPaintable::compute_absolute_rect() const { if (auto* svg_svg_box = layout_box().first_ancestor_of_type()) { - Gfx::FloatRect rect { effective_offset(), content_size() }; + CSSPixelRect rect { effective_offset(), content_size() }; for (Layout::Box const* ancestor = svg_svg_box; ancestor && ancestor->paintable(); ancestor = ancestor->paintable()->containing_block()) rect.translate_by(ancestor->paint_box()->effective_offset()); return rect; diff --git a/Userland/Libraries/LibWeb/Painting/SVGPaintable.h b/Userland/Libraries/LibWeb/Painting/SVGPaintable.h index b1783e16eb3..0369ea12e02 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGPaintable.h +++ b/Userland/Libraries/LibWeb/Painting/SVGPaintable.h @@ -21,7 +21,7 @@ public: protected: SVGPaintable(Layout::SVGBox const&); - virtual Gfx::FloatRect compute_absolute_rect() const override; + virtual CSSPixelRect compute_absolute_rect() const override; }; } diff --git a/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp index b5216b14182..d428af681ae 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp @@ -30,7 +30,7 @@ void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase ph return; if (!context.has_svg_context()) - context.set_svg_context(SVGContext(absolute_rect())); + context.set_svg_context(SVGContext(absolute_rect().to_type())); PaintableBox::before_children_paint(context, phase); } diff --git a/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp b/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp index 12236760646..e938b468b07 100644 --- a/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp @@ -371,14 +371,14 @@ void paint_text_shadow(PaintContext& context, Layout::LineBoxFragment const& fra Gfx::Painter shadow_painter { *shadow_bitmap }; shadow_painter.set_font(context.painter().font()); // FIXME: "Spread" the shadow somehow. - DevicePixelPoint baseline_start(text_rect.x(), text_rect.y() + fragment.baseline()); + DevicePixelPoint baseline_start(text_rect.x(), text_rect.y() + context.rounded_device_pixels(fragment.baseline())); shadow_painter.draw_text_run(baseline_start.to_type(), Utf8View(fragment.text()), context.painter().font(), layer.color); // Blur Gfx::StackBlurFilter filter(*shadow_bitmap); filter.process_rgba(blur_radius.value(), layer.color); - auto draw_rect = context.enclosing_device_rect(fragment.absolute_rect().to_type()); + auto draw_rect = context.enclosing_device_rect(fragment.absolute_rect()); DevicePixelPoint draw_location { draw_rect.x() + offset_x - margin, draw_rect.y() + offset_y - margin diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index cfdff679f7c..7cc03b56415 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -357,7 +357,7 @@ void StackingContext::paint(PaintContext& context) const if (opacity < 1.0f || !affine_transform.is_identity_or_translation()) { auto transform_origin = this->transform_origin(); - auto source_rect = paintable().absolute_paint_rect().translated(-transform_origin); + auto source_rect = paintable().absolute_paint_rect().to_type().translated(-transform_origin); auto transformed_destination_rect = affine_transform.map(source_rect).translated(transform_origin); auto destination_rect = transformed_destination_rect.to_rounded(); @@ -366,12 +366,12 @@ void StackingContext::paint(PaintContext& context) const // to the size of the source (which could add some artefacts, though just scaling the bitmap already does that). // We need to copy the background at the destination because a bunch of our rendering effects now rely on // being able to sample the painter (see border radii, shadows, filters, etc). - Gfx::FloatPoint destination_clipped_fixup {}; + CSSPixelPoint destination_clipped_fixup {}; auto try_get_scaled_destination_bitmap = [&]() -> ErrorOr> { Gfx::IntRect actual_destination_rect; auto bitmap = TRY(context.painter().get_region_bitmap(destination_rect, Gfx::BitmapFormat::BGRA8888, actual_destination_rect)); // get_region_bitmap() may clip to a smaller region if the requested rect goes outside the painter, so we need to account for that. - destination_clipped_fixup = Gfx::FloatPoint { destination_rect.location() - actual_destination_rect.location() }; + destination_clipped_fixup = CSSPixelPoint { destination_rect.location() - actual_destination_rect.location() }; destination_rect = actual_destination_rect; if (source_rect.size() != transformed_destination_rect.size()) { auto sx = static_cast(source_rect.width()) / transformed_destination_rect.width(); @@ -387,7 +387,7 @@ void StackingContext::paint(PaintContext& context) const return; auto bitmap = bitmap_or_error.release_value_but_fixme_should_propagate_errors(); Gfx::Painter painter(bitmap); - painter.translate((-paintable().absolute_paint_rect().location() + destination_clipped_fixup).to_rounded()); + painter.translate(context.rounded_device_point(-paintable().absolute_paint_rect().location() + destination_clipped_fixup).to_type()); auto paint_context = context.clone(painter); paint_internal(paint_context); diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index a899b5db95c..8032dd58d96 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -355,8 +355,8 @@ Messages::WebContentServer::InspectDomNodeResponse ConnectionFromClient::inspect MUST(serializer.add("border_bottom"sv, box_model.border.bottom)); MUST(serializer.add("border_left"sv, box_model.border.left)); if (auto* paint_box = box->paint_box()) { - MUST(serializer.add("content_width"sv, paint_box->content_width())); - MUST(serializer.add("content_height"sv, paint_box->content_height())); + MUST(serializer.add("content_width"sv, paint_box->content_width().value())); + MUST(serializer.add("content_height"sv, paint_box->content_height().value())); } else { MUST(serializer.add("content_width"sv, 0)); MUST(serializer.add("content_height"sv, 0)); diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp index c1b6f4c6bcb..3134ece2473 100644 --- a/Userland/Services/WebContent/PageHost.cpp +++ b/Userland/Services/WebContent/PageHost.cpp @@ -152,9 +152,9 @@ void PageHost::page_did_layout() auto* layout_root = this->layout_root(); VERIFY(layout_root); if (layout_root->paint_box()->has_overflow()) - m_content_size = page().enclosing_device_rect(layout_root->paint_box()->scrollable_overflow_rect().value().to_type()).size(); + m_content_size = page().enclosing_device_rect(layout_root->paint_box()->scrollable_overflow_rect().value()).size(); else - m_content_size = page().enclosing_device_rect(layout_root->paint_box()->absolute_rect().to_type()).size(); + m_content_size = page().enclosing_device_rect(layout_root->paint_box()->absolute_rect()).size(); m_client.async_did_layout(m_content_size.to_type()); }