mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 04:47:35 +00:00
LibWeb: Convert Paintable coordinates to new pixel units
This fixes a few sizing issues too. The page size is now correct in most cases! \o/ We get to remove some of the `to_type<>()` shenanigans, though it reappears in some other places.
This commit is contained in:
parent
57a69f15ff
commit
ab49dbf137
39 changed files with 200 additions and 179 deletions
|
@ -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<float>();
|
||||
overflow_data.scrollable_overflow_rect = viewport_rect.to_type<CSSPixels>();
|
||||
// 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);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
|
||||
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* 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<float>()));
|
||||
}
|
||||
|
||||
bool Box::is_body() const
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<int>());
|
||||
// FIXME: Pass CSSPixels here instead of int.
|
||||
dom_node().nested_browsing_context()->set_size(paint_box()->content_size().to_type<float>().to_type<int>());
|
||||
}
|
||||
|
||||
RefPtr<Painting::Paintable> FrameBox::create_paintable() const
|
||||
|
|
|
@ -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<float>().intersects(paint_box()->absolute_rect()));
|
||||
m_image_loader.set_visible_in_viewport(paint_box() && viewport_rect.to_type<CSSPixels>().intersects(paint_box()->absolute_rect()));
|
||||
}
|
||||
|
||||
RefPtr<Painting::Paintable> ImageBox::create_paintable() const
|
||||
|
|
|
@ -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<int>(), document().background_color(context.palette()));
|
||||
context.painter().translate(-context.device_viewport_rect().location().to_type<int>());
|
||||
paint_box()->stacking_context()->paint(context);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,8 +39,8 @@ void Label::handle_mouseup_on_label(Badge<Painting::TextPaintable>, CSSPixelPoin
|
|||
return;
|
||||
|
||||
if (auto* control = labeled_control(); control) {
|
||||
bool is_inside_control = enclosing_int_rect(control->paint_box()->absolute_rect()).to_type<CSSPixels>().contains(position);
|
||||
bool is_inside_label = enclosing_int_rect(paint_box()->absolute_rect()).to_type<CSSPixels>().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<Painting::TextPaintable>, CSSPixelPo
|
|||
return;
|
||||
|
||||
if (auto* control = labeled_control(); control) {
|
||||
bool is_inside_control = enclosing_int_rect(control->paint_box()->absolute_rect()).to_type<CSSPixels>().contains(position);
|
||||
bool is_inside_label = enclosing_int_rect(paint_box()->absolute_rect()).to_type<CSSPixels>().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<Painting::TextPaintable>, 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<CSSPixels>().contains(position);
|
||||
return label->paint_box()->absolute_rect().contains(position);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ void LayoutState::commit()
|
|||
if (is<Layout::Box>(node)) {
|
||||
auto& box = static_cast<Layout::Box const&>(node);
|
||||
auto& paint_box = const_cast<Painting::PaintableBox&>(*box.paint_box());
|
||||
paint_box.set_offset(used_values.offset);
|
||||
paint_box.set_offset(used_values.offset.to_type<CSSPixels>());
|
||||
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);
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -33,15 +33,15 @@ StringView LineBoxFragment::text() const
|
|||
return verify_cast<TextNode>(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<TextNode>(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 {};
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibGfx/Forward.h>
|
||||
#include <LibGfx/Rect.h>
|
||||
#include <LibWeb/Forward.h>
|
||||
#include <LibWeb/PixelUnits.h>
|
||||
|
||||
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 };
|
||||
};
|
||||
|
||||
|
|
|
@ -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<Box const&>(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<CSS::LengthPercentage>(); length_percentage && length_percentage->is_length())
|
||||
bottom_of_inline_box += length_percentage->length().to_px(fragment.layout_node());
|
||||
|
|
|
@ -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<float>().template to_type<int>());
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
|
@ -167,13 +167,13 @@ void Node::set_needs_display()
|
|||
Gfx::FloatPoint Node::box_type_agnostic_position() const
|
||||
{
|
||||
if (is<Box>(*this))
|
||||
return verify_cast<Box>(*this).paint_box()->absolute_position();
|
||||
return verify_cast<Box>(*this).paint_box()->absolute_position().to_type<float>();
|
||||
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<float>();
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue