mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 21:27:45 +00:00
LibWeb: Add Painting::Box and move things from Layout::Box into it
The "paintable" state in Layout::Box was actually not safe to access until after layout had been performed. As a first step towards making this harder to mess up accidentally, this patch moves painting information from Layout::Box to a new class: Painting::Box. Every layout can have a corresponding paint box, and it holds the final used metrics determined by layout. The paint box is created and populated by FormattingState::commit(). I've also added DOM::Node::paint_box() as a convenient way to access the paint box (if available) of a given DOM node. Going forward, I believe this will allow us to better separate data that belongs to layout vs painting, and also open up opportunities for naturally invalidating caches in the paint box (since it's reconstituted by every layout.)
This commit is contained in:
parent
db404af6df
commit
a4d51b3dc2
35 changed files with 365 additions and 293 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -11,6 +11,7 @@
|
|||
#include <LibWeb/Layout/InlineFormattingContext.h>
|
||||
#include <LibWeb/Layout/ReplacedBox.h>
|
||||
#include <LibWeb/Layout/TextNode.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -46,11 +47,11 @@ void BlockContainer::paint(PaintContext& context, PaintPhase phase)
|
|||
if (should_clip_overflow()) {
|
||||
context.painter().save();
|
||||
// FIXME: Handle overflow-x and overflow-y being different values.
|
||||
context.painter().add_clip_rect(enclosing_int_rect(absolute_padding_box_rect()));
|
||||
context.painter().add_clip_rect(enclosing_int_rect(m_paint_box->absolute_padding_box_rect()));
|
||||
context.painter().translate(-m_scroll_offset.to_type<int>());
|
||||
}
|
||||
|
||||
for (auto& line_box : m_line_boxes) {
|
||||
for (auto& line_box : m_paint_box->m_line_boxes) {
|
||||
for (auto& fragment : line_box.fragments()) {
|
||||
if (context.should_show_line_box_borders())
|
||||
context.painter().draw_rect(enclosing_int_rect(fragment.absolute_rect()), Color::Green);
|
||||
|
@ -64,7 +65,7 @@ void BlockContainer::paint(PaintContext& context, PaintPhase phase)
|
|||
|
||||
// FIXME: Merge this loop with the above somehow..
|
||||
if (phase == PaintPhase::FocusOutline) {
|
||||
for (auto& line_box : m_line_boxes) {
|
||||
for (auto& line_box : m_paint_box->m_line_boxes) {
|
||||
for (auto& fragment : line_box.fragments()) {
|
||||
auto* node = fragment.layout_node().dom_node();
|
||||
if (!node)
|
||||
|
@ -85,7 +86,7 @@ HitTestResult BlockContainer::hit_test(const Gfx::IntPoint& position, HitTestTyp
|
|||
return Box::hit_test(position, type);
|
||||
|
||||
HitTestResult last_good_candidate;
|
||||
for (auto& line_box : m_line_boxes) {
|
||||
for (auto& line_box : m_paint_box->m_line_boxes) {
|
||||
for (auto& fragment : line_box.fragments()) {
|
||||
if (is<Box>(fragment.layout_node()) && verify_cast<Box>(fragment.layout_node()).stacking_context())
|
||||
continue;
|
||||
|
@ -101,7 +102,7 @@ HitTestResult BlockContainer::hit_test(const Gfx::IntPoint& position, HitTestTyp
|
|||
|
||||
if (type == HitTestType::TextCursor && last_good_candidate.layout_node)
|
||||
return last_good_candidate;
|
||||
return { absolute_border_box_rect().contains(position.x(), position.y()) ? this : nullptr };
|
||||
return { m_paint_box->absolute_border_box_rect().contains(position.x(), position.y()) ? this : nullptr };
|
||||
}
|
||||
|
||||
bool BlockContainer::is_scrollable() const
|
||||
|
|
|
@ -27,22 +27,10 @@ public:
|
|||
BlockContainer* next_sibling() { return verify_cast<BlockContainer>(Node::next_sibling()); }
|
||||
const BlockContainer* next_sibling() const { return verify_cast<BlockContainer>(Node::next_sibling()); }
|
||||
|
||||
template<typename Callback>
|
||||
void for_each_fragment(Callback);
|
||||
template<typename Callback>
|
||||
void for_each_fragment(Callback) const;
|
||||
|
||||
bool is_scrollable() const;
|
||||
const Gfx::FloatPoint& scroll_offset() const { return m_scroll_offset; }
|
||||
void set_scroll_offset(const Gfx::FloatPoint&);
|
||||
|
||||
const Vector<LineBox>& line_boxes() const { return m_line_boxes; }
|
||||
|
||||
void set_line_boxes(Vector<LineBox>&& line_boxes) { m_line_boxes = move(line_boxes); }
|
||||
|
||||
protected:
|
||||
Vector<LineBox> m_line_boxes;
|
||||
|
||||
private:
|
||||
virtual bool is_block_container() const final { return true; }
|
||||
virtual bool wants_mouse_events() const override { return false; }
|
||||
|
@ -56,26 +44,4 @@ private:
|
|||
template<>
|
||||
inline bool Node::fast_is<BlockContainer>() const { return is_block_container(); }
|
||||
|
||||
template<typename Callback>
|
||||
void BlockContainer::for_each_fragment(Callback callback)
|
||||
{
|
||||
for (auto& line_box : line_boxes()) {
|
||||
for (auto& fragment : line_box.fragments()) {
|
||||
if (callback(fragment) == IterationDecision::Break)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Callback>
|
||||
void BlockContainer::for_each_fragment(Callback callback) const
|
||||
{
|
||||
for (auto& line_box : line_boxes()) {
|
||||
for (auto& fragment : line_box.fragments()) {
|
||||
if (callback(fragment) == IterationDecision::Break)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,10 +15,25 @@
|
|||
#include <LibWeb/Layout/FormattingContext.h>
|
||||
#include <LibWeb/Painting/BackgroundPainting.h>
|
||||
#include <LibWeb/Painting/BorderPainting.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
#include <LibWeb/Painting/ShadowPainting.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
Box::Box(DOM::Document& document, DOM::Node* node, NonnullRefPtr<CSS::StyleProperties> style)
|
||||
: NodeWithStyleAndBoxModelMetrics(document, node, move(style))
|
||||
{
|
||||
}
|
||||
|
||||
Box::Box(DOM::Document& document, DOM::Node* node, CSS::ComputedValues computed_values)
|
||||
: NodeWithStyleAndBoxModelMetrics(document, node, move(computed_values))
|
||||
{
|
||||
}
|
||||
|
||||
Box::~Box()
|
||||
{
|
||||
}
|
||||
|
||||
void Box::paint(PaintContext& context, PaintPhase phase)
|
||||
{
|
||||
if (!is_visible())
|
||||
|
@ -34,17 +49,17 @@ void Box::paint(PaintContext& context, PaintPhase phase)
|
|||
}
|
||||
|
||||
if (phase == PaintPhase::Overlay && dom_node() && document().inspected_node() == dom_node()) {
|
||||
auto content_rect = absolute_rect();
|
||||
auto content_rect = m_paint_box->absolute_rect();
|
||||
|
||||
auto margin_box = box_model().margin_box();
|
||||
Gfx::FloatRect margin_rect;
|
||||
margin_rect.set_x(absolute_x() - margin_box.left);
|
||||
margin_rect.set_width(content_width() + margin_box.left + margin_box.right);
|
||||
margin_rect.set_y(absolute_y() - margin_box.top);
|
||||
margin_rect.set_height(content_height() + margin_box.top + margin_box.bottom);
|
||||
margin_rect.set_x(m_paint_box->absolute_x() - margin_box.left);
|
||||
margin_rect.set_width(m_paint_box->content_width() + margin_box.left + margin_box.right);
|
||||
margin_rect.set_y(m_paint_box->absolute_y() - margin_box.top);
|
||||
margin_rect.set_height(m_paint_box->content_height() + margin_box.top + margin_box.bottom);
|
||||
|
||||
auto border_rect = absolute_border_box_rect();
|
||||
auto padding_rect = absolute_padding_box_rect();
|
||||
auto border_rect = m_paint_box->absolute_border_box_rect();
|
||||
auto padding_rect = m_paint_box->absolute_padding_box_rect();
|
||||
|
||||
auto paint_inspector_rect = [&](Gfx::FloatRect const& rect, Color color) {
|
||||
context.painter().fill_rect(enclosing_int_rect(rect), Color(color).with_alpha(100));
|
||||
|
@ -74,7 +89,7 @@ void Box::paint(PaintContext& context, PaintPhase phase)
|
|||
}
|
||||
|
||||
if (phase == PaintPhase::FocusOutline && dom_node() && dom_node()->is_element() && verify_cast<DOM::Element>(*dom_node()).is_focused()) {
|
||||
context.painter().draw_rect(enclosing_int_rect(absolute_rect()), context.palette().focus_outline());
|
||||
context.painter().draw_rect(enclosing_int_rect(m_paint_box->absolute_rect()), context.palette().focus_outline());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +101,7 @@ void Box::paint_border(PaintContext& context)
|
|||
.bottom = computed_values().border_bottom(),
|
||||
.left = computed_values().border_left(),
|
||||
};
|
||||
Painting::paint_all_borders(context, absolute_border_box_rect(), normalized_border_radius_data(), borders_data);
|
||||
Painting::paint_all_borders(context, m_paint_box->absolute_border_box_rect(), normalized_border_radius_data(), borders_data);
|
||||
}
|
||||
|
||||
void Box::paint_background(PaintContext& context)
|
||||
|
@ -110,13 +125,13 @@ void Box::paint_background(PaintContext& context)
|
|||
background_color = document().background_color(context.palette());
|
||||
}
|
||||
} else {
|
||||
background_rect = enclosing_int_rect(absolute_padding_box_rect());
|
||||
background_rect = enclosing_int_rect(m_paint_box->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 = enclosing_int_rect(absolute_border_box_rect());
|
||||
background_rect = enclosing_int_rect(m_paint_box->absolute_border_box_rect());
|
||||
|
||||
Painting::paint_background(context, *this, background_rect, background_color, background_layers, normalized_border_radius_data());
|
||||
}
|
||||
|
@ -138,12 +153,12 @@ void Box::paint_box_shadow(PaintContext& context)
|
|||
static_cast<int>(layer.spread_distance.to_px(*this)),
|
||||
layer.placement == CSS::BoxShadowPlacement::Outer ? Painting::BoxShadowPlacement::Outer : Painting::BoxShadowPlacement::Inner);
|
||||
}
|
||||
Painting::paint_box_shadow(context, enclosing_int_rect(absolute_border_box_rect()), resolved_box_shadow_data);
|
||||
Painting::paint_box_shadow(context, enclosing_int_rect(m_paint_box->absolute_border_box_rect()), resolved_box_shadow_data);
|
||||
}
|
||||
|
||||
Painting::BorderRadiusData Box::normalized_border_radius_data()
|
||||
{
|
||||
return Painting::normalized_border_radius_data(*this, absolute_border_box_rect(),
|
||||
return Painting::normalized_border_radius_data(*this, m_paint_box->absolute_border_box_rect(),
|
||||
computed_values().border_top_left_radius(),
|
||||
computed_values().border_top_right_radius(),
|
||||
computed_values().border_bottom_right_radius(),
|
||||
|
@ -178,7 +193,7 @@ HitTestResult Box::hit_test(const Gfx::IntPoint& position, HitTestType type) con
|
|||
// FIXME: It would be nice if we could confidently skip over hit testing
|
||||
// parts of the layout tree, but currently we can't just check
|
||||
// m_rect.contains() since inline text rects can't be trusted..
|
||||
HitTestResult result { absolute_border_box_rect().contains(position.x(), position.y()) ? this : nullptr };
|
||||
HitTestResult result { m_paint_box->absolute_border_box_rect().contains(position.x(), position.y()) ? this : nullptr };
|
||||
for_each_child_in_paint_order([&](auto& child) {
|
||||
auto child_result = child.hit_test(position, type);
|
||||
if (child_result.layout_node)
|
||||
|
@ -190,7 +205,7 @@ HitTestResult Box::hit_test(const Gfx::IntPoint& position, HitTestType type) con
|
|||
void Box::set_needs_display()
|
||||
{
|
||||
if (!is_inline()) {
|
||||
browsing_context().set_needs_display(enclosing_int_rect(absolute_rect()));
|
||||
browsing_context().set_needs_display(enclosing_int_rect(m_paint_box->absolute_rect()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -202,45 +217,6 @@ bool Box::is_body() const
|
|||
return dom_node() && dom_node() == document().body();
|
||||
}
|
||||
|
||||
void Box::set_offset(const Gfx::FloatPoint& offset)
|
||||
{
|
||||
if (m_offset == offset)
|
||||
return;
|
||||
m_offset = offset;
|
||||
did_set_rect();
|
||||
}
|
||||
|
||||
void Box::set_content_size(Gfx::FloatSize const& size)
|
||||
{
|
||||
if (m_content_size == size)
|
||||
return;
|
||||
m_content_size = size;
|
||||
did_set_rect();
|
||||
}
|
||||
|
||||
Gfx::FloatPoint Box::effective_offset() const
|
||||
{
|
||||
if (m_containing_line_box_fragment.has_value()) {
|
||||
auto const& fragment = containing_block()->line_boxes()[m_containing_line_box_fragment->line_box_index].fragments()[m_containing_line_box_fragment->fragment_index];
|
||||
return fragment.offset();
|
||||
}
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
const Gfx::FloatRect Box::absolute_rect() const
|
||||
{
|
||||
Gfx::FloatRect rect { effective_offset(), content_size() };
|
||||
for (auto* block = containing_block(); block; block = block->containing_block()) {
|
||||
rect.translate_by(block->effective_offset());
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
void Box::set_containing_line_box_fragment(Optional<LineBoxFragmentCoordinate> fragment_coordinate)
|
||||
{
|
||||
m_containing_line_box_fragment = fragment_coordinate;
|
||||
}
|
||||
|
||||
StackingContext* Box::enclosing_stacking_context()
|
||||
{
|
||||
for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
|
||||
|
@ -262,7 +238,7 @@ void Box::before_children_paint(PaintContext& context, PaintPhase phase)
|
|||
// FIXME: Support more overflow variations.
|
||||
if (computed_values().overflow_x() == CSS::Overflow::Hidden && computed_values().overflow_y() == CSS::Overflow::Hidden) {
|
||||
context.painter().save();
|
||||
context.painter().add_clip_rect(enclosing_int_rect(absolute_border_box_rect()));
|
||||
context.painter().add_clip_rect(enclosing_int_rect(m_paint_box->absolute_border_box_rect()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -21,64 +21,7 @@ struct LineBoxFragmentCoordinate {
|
|||
|
||||
class Box : public NodeWithStyleAndBoxModelMetrics {
|
||||
public:
|
||||
struct OverflowData {
|
||||
Gfx::FloatRect scrollable_overflow_rect;
|
||||
Gfx::FloatPoint scroll_offset;
|
||||
};
|
||||
|
||||
const Gfx::FloatRect absolute_rect() const;
|
||||
|
||||
Gfx::FloatPoint effective_offset() const;
|
||||
|
||||
void set_offset(const Gfx::FloatPoint& offset);
|
||||
void set_offset(float x, float y) { set_offset({ x, y }); }
|
||||
|
||||
Gfx::FloatSize const& content_size() const { return m_content_size; }
|
||||
void set_content_size(Gfx::FloatSize const&);
|
||||
void set_content_size(float width, float 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(); }
|
||||
|
||||
Gfx::FloatRect absolute_padding_box_rect() const
|
||||
{
|
||||
auto absolute_rect = this->absolute_rect();
|
||||
Gfx::FloatRect 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);
|
||||
rect.set_height(content_height() + box_model().padding.top + box_model().padding.bottom);
|
||||
return rect;
|
||||
}
|
||||
|
||||
Gfx::FloatRect absolute_border_box_rect() const
|
||||
{
|
||||
auto padded_rect = this->absolute_padding_box_rect();
|
||||
Gfx::FloatRect 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);
|
||||
rect.set_height(padded_rect.height() + box_model().border.top + box_model().border.bottom);
|
||||
return rect;
|
||||
}
|
||||
|
||||
float 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
|
||||
{
|
||||
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(); }
|
||||
OwnPtr<Painting::Box> m_paint_box;
|
||||
|
||||
bool is_out_of_flow(FormattingContext const&) const;
|
||||
|
||||
|
@ -87,8 +30,6 @@ public:
|
|||
|
||||
bool is_body() const;
|
||||
|
||||
void set_containing_line_box_fragment(Optional<LineBoxFragmentCoordinate>);
|
||||
|
||||
StackingContext* stacking_context() { return m_stacking_context; }
|
||||
const StackingContext* stacking_context() const { return m_stacking_context; }
|
||||
void set_stacking_context(NonnullOwnPtr<StackingContext> context) { m_stacking_context = move(context); }
|
||||
|
@ -109,45 +50,21 @@ public:
|
|||
bool has_intrinsic_height() const { return intrinsic_height().has_value(); }
|
||||
bool has_intrinsic_aspect_ratio() const { return intrinsic_aspect_ratio().has_value(); }
|
||||
|
||||
bool has_overflow() const { return m_overflow_data.has_value(); }
|
||||
|
||||
Optional<Gfx::FloatRect> scrollable_overflow_rect() const
|
||||
{
|
||||
if (!m_overflow_data.has_value())
|
||||
return {};
|
||||
return m_overflow_data->scrollable_overflow_rect;
|
||||
}
|
||||
|
||||
void set_overflow_data(Optional<OverflowData> data) { m_overflow_data = move(data); }
|
||||
|
||||
virtual void before_children_paint(PaintContext&, PaintPhase) override;
|
||||
virtual void after_children_paint(PaintContext&, PaintPhase) override;
|
||||
|
||||
protected:
|
||||
Box(DOM::Document& document, DOM::Node* node, NonnullRefPtr<CSS::StyleProperties> style)
|
||||
: NodeWithStyleAndBoxModelMetrics(document, node, move(style))
|
||||
{
|
||||
}
|
||||
|
||||
Box(DOM::Document& document, DOM::Node* node, CSS::ComputedValues computed_values)
|
||||
: NodeWithStyleAndBoxModelMetrics(document, node, move(computed_values))
|
||||
{
|
||||
}
|
||||
virtual ~Box() override;
|
||||
|
||||
virtual void did_set_rect() { }
|
||||
|
||||
protected:
|
||||
Box(DOM::Document&, DOM::Node*, NonnullRefPtr<CSS::StyleProperties>);
|
||||
Box(DOM::Document&, DOM::Node*, CSS::ComputedValues);
|
||||
|
||||
private:
|
||||
virtual bool is_box() const final { return true; }
|
||||
|
||||
Gfx::FloatPoint m_offset;
|
||||
Gfx::FloatSize m_content_size;
|
||||
|
||||
// Some boxes hang off of line box fragments. (inline-block, inline-table, replaced, etc)
|
||||
Optional<LineBoxFragmentCoordinate> m_containing_line_box_fragment;
|
||||
|
||||
OwnPtr<StackingContext> m_stacking_context;
|
||||
|
||||
Optional<OverflowData> m_overflow_data;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/Layout/ButtonBox.h>
|
||||
#include <LibWeb/Layout/Label.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -38,7 +39,7 @@ void ButtonBox::paint(PaintContext& context, PaintPhase phase)
|
|||
LabelableNode::paint(context, phase);
|
||||
|
||||
if (phase == PaintPhase::Foreground) {
|
||||
auto text_rect = enclosing_int_rect(absolute_rect());
|
||||
auto text_rect = enclosing_int_rect(m_paint_box->absolute_rect());
|
||||
if (m_being_pressed)
|
||||
text_rect.translate_by(1, 1);
|
||||
context.painter().draw_text(text_rect, dom_node().value(), font(), Gfx::TextAlignment::Center, computed_values().color());
|
||||
|
@ -66,7 +67,7 @@ void ButtonBox::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint& positio
|
|||
NonnullRefPtr protected_this = *this;
|
||||
NonnullRefPtr protected_browsing_context = browsing_context();
|
||||
|
||||
bool is_inside_node_or_label = enclosing_int_rect(absolute_rect()).contains(position);
|
||||
bool is_inside_node_or_label = enclosing_int_rect(m_paint_box->absolute_rect()).contains(position);
|
||||
if (!is_inside_node_or_label)
|
||||
is_inside_node_or_label = Label::is_inside_associated_label(*this, position);
|
||||
|
||||
|
@ -84,7 +85,7 @@ void ButtonBox::handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint& posit
|
|||
if (!m_tracking_mouse || !dom_node().enabled())
|
||||
return;
|
||||
|
||||
bool is_inside_node_or_label = enclosing_int_rect(absolute_rect()).contains(position);
|
||||
bool is_inside_node_or_label = enclosing_int_rect(m_paint_box->absolute_rect()).contains(position);
|
||||
if (!is_inside_node_or_label)
|
||||
is_inside_node_or_label = Label::is_inside_associated_label(*this, position);
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibGfx/Painter.h>
|
||||
#include <LibWeb/Layout/CanvasBox.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -33,11 +34,11 @@ void CanvasBox::paint(PaintContext& context, PaintPhase phase)
|
|||
|
||||
if (phase == PaintPhase::Foreground) {
|
||||
// FIXME: This should be done at a different level. Also rect() does not include padding etc!
|
||||
if (!context.viewport_rect().intersects(enclosing_int_rect(absolute_rect())))
|
||||
if (!context.viewport_rect().intersects(enclosing_int_rect(m_paint_box->absolute_rect())))
|
||||
return;
|
||||
|
||||
if (dom_node().bitmap())
|
||||
context.painter().draw_scaled_bitmap(rounded_int_rect(absolute_rect()), *dom_node().bitmap(), dom_node().bitmap()->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering()));
|
||||
context.painter().draw_scaled_bitmap(rounded_int_rect(m_paint_box->absolute_rect()), *dom_node().bitmap(), dom_node().bitmap()->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <LibWeb/HTML/HTMLInputElement.h>
|
||||
#include <LibWeb/Layout/CheckBox.h>
|
||||
#include <LibWeb/Layout/Label.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -34,7 +35,7 @@ void CheckBox::paint(PaintContext& context, PaintPhase phase)
|
|||
LabelableNode::paint(context, phase);
|
||||
|
||||
if (phase == PaintPhase::Foreground) {
|
||||
Gfx::StylePainter::paint_check_box(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), dom_node().enabled(), dom_node().checked(), m_being_pressed);
|
||||
Gfx::StylePainter::paint_check_box(context.painter(), enclosing_int_rect(m_paint_box->absolute_rect()), context.palette(), dom_node().enabled(), dom_node().checked(), m_being_pressed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +59,7 @@ void CheckBox::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint& position
|
|||
// NOTE: Changing the checked state of the DOM node may run arbitrary JS, which could disappear this node.
|
||||
NonnullRefPtr protect = *this;
|
||||
|
||||
bool is_inside_node_or_label = enclosing_int_rect(absolute_rect()).contains(position);
|
||||
bool is_inside_node_or_label = enclosing_int_rect(m_paint_box->absolute_rect()).contains(position);
|
||||
if (!is_inside_node_or_label)
|
||||
is_inside_node_or_label = Label::is_inside_associated_label(*this, position);
|
||||
|
||||
|
@ -77,7 +78,7 @@ void CheckBox::handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint& positi
|
|||
if (!m_tracking_mouse || !dom_node().enabled())
|
||||
return;
|
||||
|
||||
bool is_inside_node_or_label = enclosing_int_rect(absolute_rect()).contains(position);
|
||||
bool is_inside_node_or_label = enclosing_int_rect(m_paint_box->absolute_rect()).contains(position);
|
||||
if (!is_inside_node_or_label)
|
||||
is_inside_node_or_label = Label::is_inside_associated_label(*this, position);
|
||||
|
||||
|
|
|
@ -38,19 +38,15 @@ void FormattingState::commit()
|
|||
node.box_model().border = { node_state.border_top, node_state.border_right, node_state.border_bottom, node_state.border_left };
|
||||
node.box_model().margin = { node_state.margin_top, node_state.margin_right, node_state.margin_bottom, node_state.margin_left };
|
||||
|
||||
// For boxes, transfer relative offset, size, and overflow data.
|
||||
// For boxes, transfer all the state needed for painting.
|
||||
if (is<Layout::Box>(node)) {
|
||||
auto& box = static_cast<Layout::Box&>(node);
|
||||
box.set_offset(node_state.offset);
|
||||
box.set_content_size(node_state.content_width, node_state.content_height);
|
||||
box.set_overflow_data(move(node_state.overflow_data));
|
||||
box.set_containing_line_box_fragment(node_state.containing_line_box_fragment);
|
||||
}
|
||||
|
||||
// For block containers, transfer line boxes.
|
||||
if (is<Layout::BlockContainer>(node)) {
|
||||
auto& block_container = static_cast<Layout::BlockContainer&>(node);
|
||||
block_container.set_line_boxes(move(node_state.line_boxes));
|
||||
box.m_paint_box = Painting::Box::create(box);
|
||||
box.m_paint_box->set_offset(node_state.offset);
|
||||
box.m_paint_box->set_content_size(node_state.content_width, node_state.content_height);
|
||||
box.m_paint_box->set_overflow_data(move(node_state.overflow_data));
|
||||
box.m_paint_box->set_containing_line_box_fragment(node_state.containing_line_box_fragment);
|
||||
box.m_paint_box->set_line_boxes(move(node_state.line_boxes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <LibGfx/Point.h>
|
||||
#include <LibWeb/Layout/Box.h>
|
||||
#include <LibWeb/Layout/LineBox.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -54,12 +55,12 @@ struct FormattingState {
|
|||
float border_box_width() const { return border_box_left() + content_width + border_box_right(); }
|
||||
float border_box_height() const { return border_box_top() + content_height + border_box_bottom(); }
|
||||
|
||||
Optional<Layout::Box::OverflowData> overflow_data;
|
||||
Optional<Painting::Box::OverflowData> overflow_data;
|
||||
|
||||
Layout::Box::OverflowData& ensure_overflow_data()
|
||||
Painting::Box::OverflowData& ensure_overflow_data()
|
||||
{
|
||||
if (!overflow_data.has_value())
|
||||
overflow_data = Layout::Box::OverflowData {};
|
||||
overflow_data = Painting::Box::OverflowData {};
|
||||
return *overflow_data;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/Layout/FrameBox.h>
|
||||
#include <LibWeb/Layout/InitialContainingBlock.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -46,8 +47,8 @@ void FrameBox::paint(PaintContext& context, PaintPhase phase)
|
|||
context.painter().save();
|
||||
auto old_viewport_rect = context.viewport_rect();
|
||||
|
||||
context.painter().add_clip_rect(enclosing_int_rect(absolute_rect()));
|
||||
context.painter().translate(absolute_x(), absolute_y());
|
||||
context.painter().add_clip_rect(enclosing_int_rect(m_paint_box->absolute_rect()));
|
||||
context.painter().translate(m_paint_box->absolute_x(), m_paint_box->absolute_y());
|
||||
|
||||
context.set_viewport_rect({ {}, dom_node().nested_browsing_context()->size() });
|
||||
const_cast<Layout::InitialContainingBlock*>(hosted_layout_tree)->paint_all_phases(context);
|
||||
|
@ -57,7 +58,7 @@ void FrameBox::paint(PaintContext& context, PaintPhase phase)
|
|||
|
||||
if constexpr (HIGHLIGHT_FOCUSED_FRAME_DEBUG) {
|
||||
if (dom_node().nested_browsing_context()->is_focused_context()) {
|
||||
context.painter().draw_rect(absolute_rect().to_type<int>(), Color::Cyan);
|
||||
context.painter().draw_rect(m_paint_box->absolute_rect().to_type<int>(), Color::Cyan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,7 +69,7 @@ void FrameBox::did_set_rect()
|
|||
ReplacedBox::did_set_rect();
|
||||
|
||||
VERIFY(dom_node().nested_browsing_context());
|
||||
dom_node().nested_browsing_context()->set_size(content_size().to_type<int>());
|
||||
dom_node().nested_browsing_context()->set_size(m_paint_box->content_size().to_type<int>());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <LibWeb/CSS/ValueID.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/Layout/ImageBox.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -67,8 +68,7 @@ void ImageBox::prepare_for_replaced_layout()
|
|||
}
|
||||
|
||||
if (!has_intrinsic_width() && !has_intrinsic_height()) {
|
||||
set_content_width(16);
|
||||
set_content_height(16);
|
||||
// FIXME: Do something.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ void ImageBox::paint(PaintContext& context, PaintPhase phase)
|
|||
return;
|
||||
|
||||
// FIXME: This should be done at a different level. Also rect() does not include padding etc!
|
||||
if (!context.viewport_rect().intersects(enclosing_int_rect(absolute_rect())))
|
||||
if (!context.viewport_rect().intersects(enclosing_int_rect(m_paint_box->absolute_rect())))
|
||||
return;
|
||||
|
||||
ReplacedBox::paint(context, phase);
|
||||
|
@ -87,13 +87,13 @@ void ImageBox::paint(PaintContext& context, PaintPhase phase)
|
|||
if (renders_as_alt_text()) {
|
||||
auto& image_element = verify_cast<HTML::HTMLImageElement>(dom_node());
|
||||
context.painter().set_font(Gfx::FontDatabase::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_int_rect(m_paint_box->absolute_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_int_rect(m_paint_box->absolute_rect()), alt, Gfx::TextAlignment::Center, computed_values().color(), Gfx::TextElision::Right);
|
||||
} else if (auto bitmap = m_image_loader.bitmap(m_image_loader.current_frame_index())) {
|
||||
context.painter().draw_scaled_bitmap(rounded_int_rect(absolute_rect()), *bitmap, bitmap->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering()));
|
||||
context.painter().draw_scaled_bitmap(rounded_int_rect(m_paint_box->absolute_rect()), *bitmap, bitmap->rect(), 1.0f, to_gfx_scaling_mode(computed_values().image_rendering()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,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(viewport_rect.to_type<float>().intersects(absolute_rect()));
|
||||
m_image_loader.set_visible_in_viewport(viewport_rect.to_type<float>().intersects(m_paint_box->absolute_rect()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -8,6 +8,7 @@
|
|||
#include <LibWeb/Dump.h>
|
||||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/Layout/InitialContainingBlock.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
#include <LibWeb/Painting/StackingContext.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
@ -41,7 +42,7 @@ void InitialContainingBlock::build_stacking_context_tree()
|
|||
|
||||
void InitialContainingBlock::paint_all_phases(PaintContext& context)
|
||||
{
|
||||
context.painter().fill_rect(enclosing_int_rect(absolute_rect()), context.palette().base());
|
||||
context.painter().fill_rect(enclosing_int_rect(m_paint_box->absolute_rect()), context.palette().base());
|
||||
context.painter().translate(-context.viewport_rect().location());
|
||||
stacking_context()->paint(context);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ void InlineNode::paint(PaintContext& context, PaintPhase phase)
|
|||
auto top_right_border_radius = computed_values().border_top_right_radius();
|
||||
auto bottom_right_border_radius = computed_values().border_bottom_right_radius();
|
||||
auto bottom_left_border_radius = computed_values().border_bottom_left_radius();
|
||||
auto containing_block_position_in_absolute_coordinates = containing_block()->absolute_position();
|
||||
auto containing_block_position_in_absolute_coordinates = containing_block()->m_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() };
|
||||
|
@ -87,7 +87,7 @@ void InlineNode::paint(PaintContext& context, PaintPhase phase)
|
|||
.left = computed_values().border_left(),
|
||||
};
|
||||
|
||||
auto containing_block_position_in_absolute_coordinates = containing_block()->absolute_position();
|
||||
auto containing_block_position_in_absolute_coordinates = containing_block()->m_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() };
|
||||
|
@ -130,7 +130,7 @@ void InlineNode::for_each_fragment(Callback callback)
|
|||
{
|
||||
// FIXME: This will be slow if the containing block has a lot of fragments!
|
||||
Vector<LineBoxFragment const&> fragments;
|
||||
containing_block()->for_each_fragment([&](auto& fragment) {
|
||||
containing_block()->m_paint_box->for_each_fragment([&](auto& fragment) {
|
||||
if (is_inclusive_ancestor_of(fragment.layout_node()))
|
||||
fragments.append(fragment);
|
||||
return IterationDecision::Continue;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <LibWeb/Layout/Label.h>
|
||||
#include <LibWeb/Layout/LabelableNode.h>
|
||||
#include <LibWeb/Layout/TextNode.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -46,8 +47,8 @@ void Label::handle_mouseup_on_label(Badge<TextNode>, const Gfx::IntPoint& positi
|
|||
NonnullRefPtr protect = *this;
|
||||
|
||||
if (auto* control = labeled_control(); control) {
|
||||
bool is_inside_control = enclosing_int_rect(control->absolute_rect()).contains(position);
|
||||
bool is_inside_label = enclosing_int_rect(absolute_rect()).contains(position);
|
||||
bool is_inside_control = enclosing_int_rect(control->m_paint_box->absolute_rect()).contains(position);
|
||||
bool is_inside_label = enclosing_int_rect(m_paint_box->absolute_rect()).contains(position);
|
||||
|
||||
if (is_inside_control || is_inside_label)
|
||||
control->handle_associated_label_mouseup({});
|
||||
|
@ -62,8 +63,8 @@ void Label::handle_mousemove_on_label(Badge<TextNode>, const Gfx::IntPoint& posi
|
|||
return;
|
||||
|
||||
if (auto* control = labeled_control(); control) {
|
||||
bool is_inside_control = enclosing_int_rect(control->absolute_rect()).contains(position);
|
||||
bool is_inside_label = enclosing_int_rect(absolute_rect()).contains(position);
|
||||
bool is_inside_control = enclosing_int_rect(control->m_paint_box->absolute_rect()).contains(position);
|
||||
bool is_inside_label = enclosing_int_rect(m_paint_box->absolute_rect()).contains(position);
|
||||
|
||||
control->handle_associated_label_mousemove({}, is_inside_control || is_inside_label);
|
||||
}
|
||||
|
@ -72,7 +73,7 @@ void Label::handle_mousemove_on_label(Badge<TextNode>, const Gfx::IntPoint& posi
|
|||
bool Label::is_inside_associated_label(LabelableNode& control, const Gfx::IntPoint& position)
|
||||
{
|
||||
if (auto* label = label_for_control_node(control); label)
|
||||
return enclosing_int_rect(label->absolute_rect()).contains(position);
|
||||
return enclosing_int_rect(label->m_paint_box->absolute_rect()).contains(position);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ StringView LineBoxFragment::text() const
|
|||
const Gfx::FloatRect LineBoxFragment::absolute_rect() const
|
||||
{
|
||||
Gfx::FloatRect rect { {}, size() };
|
||||
rect.set_location(m_layout_node.containing_block()->absolute_position());
|
||||
rect.set_location(m_layout_node.containing_block()->m_paint_box->absolute_position());
|
||||
rect.translate_by(offset());
|
||||
return rect;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <AK/StringBuilder.h>
|
||||
#include <LibGfx/Painter.h>
|
||||
#include <LibWeb/Layout/ListItemMarkerBox.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -59,7 +60,7 @@ void ListItemMarkerBox::paint(PaintContext& context, PaintPhase phase)
|
|||
if (phase != PaintPhase::Foreground)
|
||||
return;
|
||||
|
||||
auto enclosing = enclosing_int_rect(absolute_rect());
|
||||
auto enclosing = enclosing_int_rect(m_paint_box->absolute_rect());
|
||||
|
||||
if (auto const* list_style_image = list_style_image_bitmap()) {
|
||||
context.painter().blit(enclosing.location(), *list_style_image, list_style_image->rect());
|
||||
|
|
|
@ -112,7 +112,7 @@ InitialContainingBlock& Node::root()
|
|||
void Node::set_needs_display()
|
||||
{
|
||||
if (auto* block = containing_block()) {
|
||||
block->for_each_fragment([&](auto& fragment) {
|
||||
block->m_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()));
|
||||
}
|
||||
|
@ -124,11 +124,11 @@ void Node::set_needs_display()
|
|||
Gfx::FloatPoint Node::box_type_agnostic_position() const
|
||||
{
|
||||
if (is<Box>(*this))
|
||||
return verify_cast<Box>(*this).absolute_position();
|
||||
return verify_cast<Box>(*this).m_paint_box->absolute_position();
|
||||
VERIFY(is_inline());
|
||||
Gfx::FloatPoint position;
|
||||
if (auto* block = containing_block()) {
|
||||
block->for_each_fragment([&](auto& fragment) {
|
||||
block->m_paint_box->for_each_fragment([&](auto& fragment) {
|
||||
if (&fragment.layout_node() == this || is_ancestor_of(fragment.layout_node())) {
|
||||
position = fragment.absolute_rect().location();
|
||||
return IterationDecision::Break;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <LibGfx/Painter.h>
|
||||
#include <LibGfx/StylePainter.h>
|
||||
#include <LibWeb/Layout/Progress.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -27,7 +28,7 @@ void Progress::paint(PaintContext& context, PaintPhase phase)
|
|||
|
||||
if (phase == PaintPhase::Foreground) {
|
||||
// FIXME: This does not support floating point value() and max()
|
||||
Gfx::StylePainter::paint_progressbar(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), 0, dom_node().max(), dom_node().value(), "");
|
||||
Gfx::StylePainter::paint_progressbar(context.painter(), enclosing_int_rect(m_paint_box->absolute_rect()), context.palette(), 0, dom_node().max(), dom_node().value(), "");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <LibWeb/HTML/BrowsingContext.h>
|
||||
#include <LibWeb/Layout/Label.h>
|
||||
#include <LibWeb/Layout/RadioButton.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -33,7 +34,7 @@ void RadioButton::paint(PaintContext& context, PaintPhase phase)
|
|||
LabelableNode::paint(context, phase);
|
||||
|
||||
if (phase == PaintPhase::Foreground) {
|
||||
Gfx::StylePainter::paint_radio_button(context.painter(), enclosing_int_rect(absolute_rect()), context.palette(), dom_node().checked(), m_being_pressed);
|
||||
Gfx::StylePainter::paint_radio_button(context.painter(), enclosing_int_rect(m_paint_box->absolute_rect()), context.palette(), dom_node().checked(), m_being_pressed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +58,7 @@ void RadioButton::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint& posit
|
|||
// NOTE: Changing the checked state of the DOM node may run arbitrary JS, which could disappear this node.
|
||||
NonnullRefPtr protect = *this;
|
||||
|
||||
bool is_inside_node_or_label = enclosing_int_rect(absolute_rect()).contains(position);
|
||||
bool is_inside_node_or_label = enclosing_int_rect(m_paint_box->absolute_rect()).contains(position);
|
||||
if (!is_inside_node_or_label)
|
||||
is_inside_node_or_label = Label::is_inside_associated_label(*this, position);
|
||||
|
||||
|
@ -74,7 +75,7 @@ void RadioButton::handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint& pos
|
|||
if (!m_tracking_mouse || !dom_node().enabled())
|
||||
return;
|
||||
|
||||
bool is_inside_node_or_label = enclosing_int_rect(absolute_rect()).contains(position);
|
||||
bool is_inside_node_or_label = enclosing_int_rect(m_paint_box->absolute_rect()).contains(position);
|
||||
if (!is_inside_node_or_label)
|
||||
is_inside_node_or_label = Label::is_inside_associated_label(*this, position);
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <LibGfx/AntiAliasingPainter.h>
|
||||
#include <LibGfx/Painter.h>
|
||||
#include <LibWeb/Layout/SVGGeometryBox.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
#include <LibWeb/SVG/SVGPathElement.h>
|
||||
#include <LibWeb/SVG/SVGSVGElement.h>
|
||||
|
||||
|
@ -39,7 +40,7 @@ void SVGGeometryBox::paint(PaintContext& context, PaintPhase phase)
|
|||
SVG::SVGSVGElement* svg_element = geometry_element.first_ancestor_of_type<SVG::SVGSVGElement>();
|
||||
auto maybe_view_box = svg_element->view_box();
|
||||
|
||||
context.painter().add_clip_rect((Gfx::Rect<int>)absolute_rect());
|
||||
context.painter().add_clip_rect(enclosing_int_rect(m_paint_box->absolute_rect()));
|
||||
|
||||
Gfx::Path path = geometry_element.get_path();
|
||||
|
||||
|
@ -121,10 +122,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 = content_width();
|
||||
auto specified_width = m_paint_box->content_width();
|
||||
|
||||
bool has_specified_height = svg_box->has_attribute(HTML::AttributeNames::height);
|
||||
auto specified_height = content_height();
|
||||
auto specified_height = m_paint_box->content_height();
|
||||
|
||||
auto scale_width = has_specified_width ? specified_width / view_box.width : 1;
|
||||
auto scale_height = has_specified_height ? specified_height / view_box.height : 1;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <LibWeb/Layout/SVGSVGBox.h>
|
||||
#include <LibWeb/Painting/Box.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -19,7 +20,7 @@ void SVGSVGBox::before_children_paint(PaintContext& context, PaintPhase phase)
|
|||
return;
|
||||
|
||||
if (!context.has_svg_context())
|
||||
context.set_svg_context(SVGContext(absolute_rect()));
|
||||
context.set_svg_context(SVGContext(m_paint_box->absolute_rect()));
|
||||
|
||||
SVGGraphicsBox::before_children_paint(context, phase);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue