Skip to content

Commit

Permalink
move fragments into inline paintable wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kalenikaliaksandr committed Jan 12, 2024
1 parent c566ef2 commit 1962604
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 15 deletions.
53 changes: 47 additions & 6 deletions Userland/Libraries/LibWeb/Layout/LayoutState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,25 +298,29 @@ void LayoutState::resolve_border_radii()
}

for (auto& inline_paintable : inline_paintables) {
Vector<Layout::LineBoxFragment&> fragments;
verify_cast<Painting::PaintableWithLines>(*inline_paintable.containing_block()->paintable_box()).for_each_fragment([&](auto& fragment) {
if (inline_paintable.layout_node().is_inclusive_ancestor_of(fragment.layout_node()))
fragments.append(const_cast<Layout::LineBoxFragment&>(fragment));
return IterationDecision::Continue;
});
// Vector<Layout::LineBoxFragment&> fragments;
// verify_cast<Painting::PaintableWithLines>(*inline_paintable.containing_block()->paintable_box()).for_each_fragment([&](auto& fragment) {
// if (inline_paintable.layout_node().is_inclusive_ancestor_of(fragment.layout_node()))
// fragments.append(const_cast<Layout::LineBoxFragment&>(fragment));
// return IterationDecision::Continue;
// });

auto& fragments = inline_paintable.m_fragments;

auto const& top_left_border_radius = inline_paintable.computed_values().border_top_left_radius();
auto const& top_right_border_radius = inline_paintable.computed_values().border_top_right_radius();
auto const& bottom_right_border_radius = inline_paintable.computed_values().border_bottom_right_radius();
auto const& bottom_left_border_radius = inline_paintable.computed_values().border_bottom_left_radius();

auto containing_block_position_in_absolute_coordinates = inline_paintable.containing_block()->paintable_box()->absolute_position();
// dbgln(">contatining block of ({}) is ({})", inline_paintable.layout_node().debug_description(), inline_paintable.containing_block()->debug_description());
for (size_t i = 0; i < fragments.size(); ++i) {
auto is_first_fragment = i == 0;
auto is_last_fragment = i == fragments.size() - 1;
auto& fragment = fragments[i];

CSSPixelRect absolute_fragment_rect { containing_block_position_in_absolute_coordinates.translated(fragment.offset()), fragment.size() };
// dbgln(">absolute_fragment_rect=({})", absolute_fragment_rect);

if (is_first_fragment) {
auto extra_start_width = inline_paintable.box_model().padding.left;
Expand Down Expand Up @@ -364,6 +368,8 @@ void LayoutState::resolve_box_shadow_data()

void LayoutState::commit(Box& root)
{
dbgln(">>>LayoutState::commit START");

// Only the top-level LayoutState should ever be committed.
VERIFY(!m_parent);

Expand Down Expand Up @@ -428,6 +434,39 @@ void LayoutState::commit(Box& root)

resolve_relative_positions(paintables_with_lines);

for (auto& paintable_with_lines : paintables_with_lines) {
for (auto& line_box : paintable_with_lines.line_boxes()) {
Vector<LineBoxFragment> new_fragments;
for (auto& fragment : line_box.fragments()) {
auto find_optional_closest_inline_paintable_of_fragment = [&](LineBoxFragment& fragment) -> Painting::InlinePaintable const* {
auto const* parent = fragment.layout_node().parent();
while (parent) {
if (is<InlineNode>(*parent)) {
VERIFY(is<Painting::InlinePaintable>(*parent->paintable()));
return static_cast<Painting::InlinePaintable const*>(parent->paintable());
}
parent = parent->parent();
}
return nullptr;
};

if (fragment.layout_node().is_text_node())
text_nodes.set(static_cast<Layout::TextNode*>(const_cast<Layout::Node*>(&fragment.layout_node())));

auto* closest_inline_paintable = find_optional_closest_inline_paintable_of_fragment(fragment);
if (closest_inline_paintable) {
// dbgln(">>>closest_inline_paintable of ({}) is ({}) text=({})", fragment.layout_node().debug_description(), closest_inline_paintable->layout_node().debug_description(), fragment.text());
const_cast<Painting::InlinePaintable*>(closest_inline_paintable)->m_fragments.append(fragment);
} else {
new_fragments.append(fragment);
// dbgln(">>>closest_inline_paintable of ({}) is null text=({})", fragment.layout_node().debug_description(), fragment.text());
}
}

line_box.set_fragments(move(new_fragments));
}
}

// Make a pass over all the line boxes to:
// - Measure absolute rect of each line box.
// - Collect all text nodes, so we can create paintables for them later.
Expand Down Expand Up @@ -471,6 +510,8 @@ void LayoutState::commit(Box& root)
inline_paintable.mark_contained_fragments();
}
}

dbgln(">>>LayoutState::commit END");
}

void LayoutState::UsedValues::set_node(NodeWithStyle& node, UsedValues const* containing_block_used_values)
Expand Down
2 changes: 2 additions & 0 deletions Userland/Libraries/LibWeb/Layout/LineBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class LineBox {

void add_fragment(Node const& layout_node, int start, int length, CSSPixels leading_size, CSSPixels trailing_size, CSSPixels leading_margin, CSSPixels trailing_margin, CSSPixels content_width, CSSPixels content_height, CSSPixels border_box_top, CSSPixels border_box_bottom, Span<Gfx::DrawGlyphOrEmoji const> = {});

void set_fragments(Vector<LineBoxFragment>&& fragments) { m_fragments = fragments; }

Vector<LineBoxFragment> const& fragments() const { return m_fragments; }
Vector<LineBoxFragment>& fragments() { return m_fragments; }

Expand Down
44 changes: 35 additions & 9 deletions Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,19 @@ template<typename Callback>
void InlinePaintable::for_each_fragment(Callback callback) const
{
// FIXME: This will be slow if the containing block has a lot of fragments!
Vector<Layout::LineBoxFragment const&> fragments;
verify_cast<PaintableWithLines>(*containing_block()->paintable_box()).for_each_fragment([&](auto& fragment) {
if (layout_node().is_inclusive_ancestor_of(fragment.layout_node()))
fragments.append(fragment);
return IterationDecision::Continue;
});
for (size_t i = 0; i < fragments.size(); ++i) {
auto const& fragment = fragments[i];
callback(fragment, i == 0, i == fragments.size() - 1);
// Vector<Layout::LineBoxFragment const&> fragments;
// verify_cast<PaintableWithLines>(*containing_block()->paintable_box()).for_each_fragment([&](auto& fragment) {
// if (layout_node().is_inclusive_ancestor_of(fragment.layout_node()))
// fragments.append(fragment);
// return IterationDecision::Continue;
// });
// for (size_t i = 0; i < fragments.size(); ++i) {
// auto const& fragment = fragments[i];
// callback(fragment, i == 0, i == fragments.size() - 1);
// }
for (size_t i = 0; i < m_fragments.size(); ++i) {
auto const& fragment = m_fragments[i];
callback(fragment, i == 0, i == m_fragments.size() - 1);
}
}

Expand All @@ -189,6 +193,28 @@ void InlinePaintable::mark_contained_fragments()
});
}

Optional<HitTestResult> InlinePaintable::hit_test(CSSPixelPoint position, HitTestType type) const
{
for (auto& fragment : m_fragments) {
if (is<Layout::Box>(fragment.layout_node()) && static_cast<Layout::Box const&>(fragment.layout_node()).paintable_box()->stacking_context())
continue;
if (!fragment.layout_node().containing_block()) {
dbgln("FIXME: PaintableWithLines::hit_test(): Missing containing block on {}",
fragment.layout_node().debug_description());
continue;
}
auto fragment_absolute_rect = fragment.absolute_rect();
if (fragment_absolute_rect.contains(position)) {
if (is<Layout::BlockContainer>(fragment.layout_node()) && fragment.layout_node().paintable())
return fragment.layout_node().paintable()->hit_test(position, type);
return HitTestResult { const_cast<Paintable&>(const_cast<Paintable&>(*fragment.layout_node().paintable())),
fragment.text_index_at(position.x()) };
}
}

return {};
}

CSSPixelRect InlinePaintable::bounding_rect() const
{
auto top = CSSPixels::max();
Expand Down
4 changes: 4 additions & 0 deletions Userland/Libraries/LibWeb/Painting/InlinePaintable.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ class InlinePaintable final : public Paintable {

void mark_contained_fragments();

virtual Optional<HitTestResult> hit_test(CSSPixelPoint, HitTestType) const override;

Vector<Layout::LineBoxFragment> m_fragments;

private:
InlinePaintable(Layout::InlineNode const&);

Expand Down
9 changes: 9 additions & 0 deletions Userland/Libraries/LibWeb/Painting/PaintableBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,15 @@ Optional<HitTestResult> PaintableWithLines::hit_test(CSSPixelPoint position, Hit
if (!layout_box().children_are_inline() || m_line_boxes.is_empty())
return PaintableBox::hit_test(position, type);

for (auto* child = first_child(); child; child = child->next_sibling()) {
auto result = child->hit_test(position, type);
if (!result.has_value())
continue;
if (!result->paintable->visible_for_hit_testing())
continue;
return result;
}

Optional<HitTestResult> last_good_candidate;
for (auto& line_box : m_line_boxes) {
for (auto& fragment : line_box.fragments()) {
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibWeb/Painting/PaintableBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ class PaintableWithLines : public PaintableBox {
Layout::BlockContainer& layout_box();

Vector<Layout::LineBox> const& line_boxes() const { return m_line_boxes; }
Vector<Layout::LineBox>& line_boxes() { return m_line_boxes; }
void set_line_boxes(Vector<Layout::LineBox>&& line_boxes) { m_line_boxes = move(line_boxes); }

template<typename Callback>
Expand Down

0 comments on commit 1962604

Please sign in to comment.