mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:07:35 +00:00
LibWeb: Paint fragments contained by inline node as part of this node
Fragments contained by the inline node should be painted in the foreground phase for this node, instead of being painted as a part of the containing PaintableWithLines. This change implements that by marking all fragments contained by inline nodes so they can be skipped while painting the content of PaintableWithLines. This is an ugly way, and instead, we should make InlinePaintables own all fragments contained by them.
This commit is contained in:
parent
c5187c6bb3
commit
6c645f3a9f
6 changed files with 45 additions and 3 deletions
|
@ -460,6 +460,18 @@ void LayoutState::commit(Box& root)
|
|||
|
||||
resolve_border_radii();
|
||||
resolve_box_shadow_data();
|
||||
|
||||
for (auto& it : used_values_per_layout_node) {
|
||||
auto& used_values = *it.value;
|
||||
auto& node = const_cast<NodeWithStyle&>(used_values.node());
|
||||
auto* paintable = node.paintable();
|
||||
if (paintable && is<Painting::InlinePaintable>(*paintable)) {
|
||||
auto& inline_paintable = static_cast<Painting::InlinePaintable&>(*paintable);
|
||||
// FIXME: Marking fragments contained by inline node is a hack required to skip them while painting
|
||||
// PaintableWithLines content.
|
||||
inline_paintable.mark_contained_fragments();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutState::UsedValues::set_node(NodeWithStyle& node, UsedValues const* containing_block_used_values)
|
||||
|
|
|
@ -79,6 +79,9 @@ public:
|
|||
Painting::BorderRadiiData const& border_radii_data() const { return m_border_radii_data; }
|
||||
void set_border_radii_data(Painting::BorderRadiiData const& border_radii_data) { m_border_radii_data = border_radii_data; }
|
||||
|
||||
bool contained_by_inline_node() const { return m_contained_by_inline_node; }
|
||||
void set_contained_by_inline_node() { m_contained_by_inline_node = true; }
|
||||
|
||||
private:
|
||||
JS::NonnullGCPtr<Node const> m_layout_node;
|
||||
int m_start { 0 };
|
||||
|
@ -90,6 +93,7 @@ private:
|
|||
CSSPixels m_baseline { 0 };
|
||||
Vector<Gfx::DrawGlyphOrEmoji> m_glyph_run;
|
||||
Painting::BorderRadiiData m_border_radii_data;
|
||||
bool m_contained_by_inline_node { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -146,6 +146,13 @@ void InlinePaintable::paint(PaintContext& context, PaintPhase phase) const
|
|||
}
|
||||
}
|
||||
|
||||
if (phase == PaintPhase::Foreground) {
|
||||
for_each_fragment([&](auto const& fragment, bool, bool) {
|
||||
if (is<Layout::TextNode>(fragment.layout_node()))
|
||||
paint_text_fragment(context, static_cast<Layout::TextNode const&>(fragment.layout_node()), fragment, phase);
|
||||
});
|
||||
}
|
||||
|
||||
if (phase == PaintPhase::Overlay && layout_node().document().inspected_layout_node() == &layout_node()) {
|
||||
// FIXME: This paints a double-thick border between adjacent fragments, where ideally there
|
||||
// would be none. Once we implement non-rectangular outlines for the `outline` CSS
|
||||
|
@ -173,6 +180,15 @@ void InlinePaintable::for_each_fragment(Callback callback) const
|
|||
}
|
||||
}
|
||||
|
||||
void InlinePaintable::mark_contained_fragments()
|
||||
{
|
||||
verify_cast<PaintableWithLines>(*containing_block()->paintable_box()).for_each_fragment([&](auto& fragment) {
|
||||
if (layout_node().is_inclusive_ancestor_of(fragment.layout_node()))
|
||||
const_cast<Layout::LineBoxFragment&>(fragment).set_contained_by_inline_node();
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
CSSPixelRect InlinePaintable::bounding_rect() const
|
||||
{
|
||||
auto top = CSSPixels::max();
|
||||
|
|
|
@ -24,6 +24,8 @@ public:
|
|||
|
||||
CSSPixelRect bounding_rect() const;
|
||||
|
||||
void mark_contained_fragments();
|
||||
|
||||
private:
|
||||
InlinePaintable(Layout::InlineNode const&);
|
||||
|
||||
|
|
|
@ -484,7 +484,7 @@ void PaintableBox::clear_clip_overflow_rect(PaintContext& context, PaintPhase ph
|
|||
}
|
||||
}
|
||||
|
||||
static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment)
|
||||
void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment)
|
||||
{
|
||||
auto const& browsing_context = text_node.browsing_context();
|
||||
|
||||
|
@ -518,7 +518,7 @@ static void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const
|
|||
context.recording_painter().draw_rect(cursor_device_rect, text_node.computed_values().color());
|
||||
}
|
||||
|
||||
static void paint_text_decoration(PaintContext& context, Layout::Node const& text_node, Layout::LineBoxFragment const& fragment)
|
||||
void paint_text_decoration(PaintContext& context, Layout::Node const& text_node, Layout::LineBoxFragment const& fragment)
|
||||
{
|
||||
auto& painter = context.recording_painter();
|
||||
auto& font = fragment.layout_node().first_available_font();
|
||||
|
@ -600,7 +600,7 @@ static void paint_text_decoration(PaintContext& context, Layout::Node const& tex
|
|||
}
|
||||
}
|
||||
|
||||
static void paint_text_fragment(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment, PaintPhase phase)
|
||||
void paint_text_fragment(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment, PaintPhase phase)
|
||||
{
|
||||
auto& painter = context.recording_painter();
|
||||
|
||||
|
@ -680,6 +680,8 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
|
|||
if (phase == PaintPhase::Foreground) {
|
||||
for (auto& line_box : m_line_boxes) {
|
||||
for (auto& fragment : line_box.fragments()) {
|
||||
if (fragment.contained_by_inline_node())
|
||||
continue;
|
||||
if (is<Layout::TextNode>(fragment.layout_node())) {
|
||||
auto& text_shadow = fragment.layout_node().computed_values().text_shadow();
|
||||
if (!text_shadow.is_empty()) {
|
||||
|
@ -704,6 +706,8 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
|
|||
|
||||
for (auto& line_box : m_line_boxes) {
|
||||
for (auto& fragment : line_box.fragments()) {
|
||||
if (fragment.contained_by_inline_node())
|
||||
continue;
|
||||
auto fragment_absolute_rect = fragment.absolute_rect();
|
||||
auto fragment_absolute_device_rect = context.enclosing_device_rect(fragment_absolute_rect);
|
||||
if (context.should_show_line_box_borders()) {
|
||||
|
|
|
@ -272,4 +272,8 @@ private:
|
|||
Vector<Layout::LineBox> m_line_boxes;
|
||||
};
|
||||
|
||||
void paint_text_decoration(PaintContext& context, Layout::Node const& text_node, Layout::LineBoxFragment const& fragment);
|
||||
void paint_cursor_if_needed(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment);
|
||||
void paint_text_fragment(PaintContext& context, Layout::TextNode const& text_node, Layout::LineBoxFragment const& fragment, PaintPhase phase);
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue