mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:47:44 +00:00
LibWeb: Add SVGFormattingContext to handle SVG box trees
Instead of trying to layout SVG boxes as if they are regular CSS boxes, let's invent an "SVG formatting context" and let it manage SVG boxes. To facilitate this, Layout::SVGBox no longer inherits from ReplacedBox, and is instead a simple, "inline-block" style BlockBox.
This commit is contained in:
parent
4417f26d7c
commit
92c08ad4ac
11 changed files with 65 additions and 26 deletions
|
@ -193,6 +193,7 @@ set(SOURCES
|
||||||
Layout/RadioButton.cpp
|
Layout/RadioButton.cpp
|
||||||
Layout/ReplacedBox.cpp
|
Layout/ReplacedBox.cpp
|
||||||
Layout/SVGBox.cpp
|
Layout/SVGBox.cpp
|
||||||
|
Layout/SVGFormattingContext.cpp
|
||||||
Layout/SVGGraphicsBox.cpp
|
Layout/SVGGraphicsBox.cpp
|
||||||
Layout/SVGPathBox.cpp
|
Layout/SVGPathBox.cpp
|
||||||
Layout/SVGSVGBox.cpp
|
Layout/SVGSVGBox.cpp
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include <LibWeb/Layout/FormattingContext.h>
|
#include <LibWeb/Layout/FormattingContext.h>
|
||||||
#include <LibWeb/Layout/InlineFormattingContext.h>
|
#include <LibWeb/Layout/InlineFormattingContext.h>
|
||||||
#include <LibWeb/Layout/ReplacedBox.h>
|
#include <LibWeb/Layout/ReplacedBox.h>
|
||||||
|
#include <LibWeb/Layout/SVGFormattingContext.h>
|
||||||
|
#include <LibWeb/Layout/SVGSVGBox.h>
|
||||||
#include <LibWeb/Layout/TableBox.h>
|
#include <LibWeb/Layout/TableBox.h>
|
||||||
#include <LibWeb/Layout/TableCellBox.h>
|
#include <LibWeb/Layout/TableCellBox.h>
|
||||||
#include <LibWeb/Layout/TableFormattingContext.h>
|
#include <LibWeb/Layout/TableFormattingContext.h>
|
||||||
|
@ -67,6 +69,12 @@ bool FormattingContext::creates_block_formatting_context(const Box& box)
|
||||||
|
|
||||||
void FormattingContext::layout_inside(Box& box, LayoutMode layout_mode)
|
void FormattingContext::layout_inside(Box& box, LayoutMode layout_mode)
|
||||||
{
|
{
|
||||||
|
if (is<SVGSVGBox>(box)) {
|
||||||
|
SVGFormattingContext context(box, this);
|
||||||
|
context.run(box, layout_mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (creates_block_formatting_context(box)) {
|
if (creates_block_formatting_context(box)) {
|
||||||
BlockFormattingContext context(box, this);
|
BlockFormattingContext context(box, this);
|
||||||
context.run(box, layout_mode);
|
context.run(box, layout_mode);
|
||||||
|
|
|
@ -10,8 +10,9 @@
|
||||||
namespace Web::Layout {
|
namespace Web::Layout {
|
||||||
|
|
||||||
SVGBox::SVGBox(DOM::Document& document, SVG::SVGElement& element, NonnullRefPtr<CSS::StyleProperties> style)
|
SVGBox::SVGBox(DOM::Document& document, SVG::SVGElement& element, NonnullRefPtr<CSS::StyleProperties> style)
|
||||||
: ReplacedBox(document, element, move(style))
|
: BlockBox(document, &element, move(style))
|
||||||
{
|
{
|
||||||
|
set_inline(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SVGBox::before_children_paint(PaintContext& context, PaintPhase phase)
|
void SVGBox::before_children_paint(PaintContext& context, PaintPhase phase)
|
||||||
|
|
|
@ -6,17 +6,19 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <LibWeb/Layout/ReplacedBox.h>
|
#include <LibWeb/Layout/BlockBox.h>
|
||||||
#include <LibWeb/SVG/SVGElement.h>
|
#include <LibWeb/SVG/SVGElement.h>
|
||||||
#include <LibWeb/SVG/SVGGraphicsElement.h>
|
#include <LibWeb/SVG/SVGGraphicsElement.h>
|
||||||
|
|
||||||
namespace Web::Layout {
|
namespace Web::Layout {
|
||||||
|
|
||||||
class SVGBox : public ReplacedBox {
|
class SVGBox : public BlockBox {
|
||||||
public:
|
public:
|
||||||
SVGBox(DOM::Document&, SVG::SVGElement&, NonnullRefPtr<CSS::StyleProperties>);
|
SVGBox(DOM::Document&, SVG::SVGElement&, NonnullRefPtr<CSS::StyleProperties>);
|
||||||
virtual ~SVGBox() override = default;
|
virtual ~SVGBox() override = default;
|
||||||
|
|
||||||
|
SVG::SVGElement& dom_node() { return verify_cast<SVG::SVGElement>(*Box::dom_node()); }
|
||||||
|
|
||||||
virtual void before_children_paint(PaintContext& context, PaintPhase phase) override;
|
virtual void before_children_paint(PaintContext& context, PaintPhase phase) override;
|
||||||
virtual void after_children_paint(PaintContext& context, PaintPhase phase) override;
|
virtual void after_children_paint(PaintContext& context, PaintPhase phase) override;
|
||||||
};
|
};
|
||||||
|
|
26
Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp
Normal file
26
Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AK/Format.h>
|
||||||
|
#include <LibWeb/Layout/SVGFormattingContext.h>
|
||||||
|
#include <LibWeb/Layout/SVGSVGBox.h>
|
||||||
|
|
||||||
|
namespace Web::Layout {
|
||||||
|
|
||||||
|
SVGFormattingContext::SVGFormattingContext(Box& box, FormattingContext* parent)
|
||||||
|
: FormattingContext(box, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SVGFormattingContext::~SVGFormattingContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SVGFormattingContext::run(Box&, LayoutMode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h
Normal file
22
Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibWeb/Forward.h>
|
||||||
|
#include <LibWeb/Layout/FormattingContext.h>
|
||||||
|
|
||||||
|
namespace Web::Layout {
|
||||||
|
|
||||||
|
class SVGFormattingContext : public FormattingContext {
|
||||||
|
public:
|
||||||
|
explicit SVGFormattingContext(Box&, FormattingContext* parent);
|
||||||
|
~SVGFormattingContext();
|
||||||
|
|
||||||
|
virtual void run(Box&, LayoutMode) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -17,6 +17,8 @@ public:
|
||||||
SVGGraphicsBox(DOM::Document&, SVG::SVGGraphicsElement&, NonnullRefPtr<CSS::StyleProperties>);
|
SVGGraphicsBox(DOM::Document&, SVG::SVGGraphicsElement&, NonnullRefPtr<CSS::StyleProperties>);
|
||||||
virtual ~SVGGraphicsBox() override = default;
|
virtual ~SVGGraphicsBox() override = default;
|
||||||
|
|
||||||
|
SVG::SVGGraphicsElement& dom_node() { return verify_cast<SVG::SVGGraphicsElement>(SVGBox::dom_node()); }
|
||||||
|
|
||||||
virtual void before_children_paint(PaintContext& context, PaintPhase phase) override;
|
virtual void before_children_paint(PaintContext& context, PaintPhase phase) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,18 +16,6 @@ SVGPathBox::SVGPathBox(DOM::Document& document, SVG::SVGPathElement& element, No
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SVGPathBox::prepare_for_replaced_layout()
|
|
||||||
{
|
|
||||||
auto& bounding_box = dom_node().get_path().bounding_box();
|
|
||||||
set_has_intrinsic_width(true);
|
|
||||||
set_has_intrinsic_height(true);
|
|
||||||
set_intrinsic_width(bounding_box.width());
|
|
||||||
set_intrinsic_height(bounding_box.height());
|
|
||||||
|
|
||||||
// FIXME: This does not belong here! Someone at a higher level should place this box.
|
|
||||||
set_offset(bounding_box.top_left());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVGPathBox::paint(PaintContext& context, PaintPhase phase)
|
void SVGPathBox::paint(PaintContext& context, PaintPhase phase)
|
||||||
{
|
{
|
||||||
if (!is_visible())
|
if (!is_visible())
|
||||||
|
|
|
@ -18,7 +18,6 @@ public:
|
||||||
|
|
||||||
SVG::SVGPathElement& dom_node() { return verify_cast<SVG::SVGPathElement>(SVGGraphicsBox::dom_node()); }
|
SVG::SVGPathElement& dom_node() { return verify_cast<SVG::SVGPathElement>(SVGGraphicsBox::dom_node()); }
|
||||||
|
|
||||||
virtual void prepare_for_replaced_layout() override;
|
|
||||||
virtual void paint(PaintContext& context, PaintPhase phase) override;
|
virtual void paint(PaintContext& context, PaintPhase phase) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,6 @@ SVGSVGBox::SVGSVGBox(DOM::Document& document, SVG::SVGSVGElement& element, Nonnu
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SVGSVGBox::prepare_for_replaced_layout()
|
|
||||||
{
|
|
||||||
set_has_intrinsic_width(true);
|
|
||||||
set_has_intrinsic_height(true);
|
|
||||||
set_intrinsic_width(dom_node().width());
|
|
||||||
set_intrinsic_height(dom_node().height());
|
|
||||||
}
|
|
||||||
|
|
||||||
void SVGSVGBox::before_children_paint(PaintContext& context, PaintPhase phase)
|
void SVGSVGBox::before_children_paint(PaintContext& context, PaintPhase phase)
|
||||||
{
|
{
|
||||||
if (phase != PaintPhase::Foreground)
|
if (phase != PaintPhase::Foreground)
|
||||||
|
|
|
@ -18,8 +18,6 @@ public:
|
||||||
|
|
||||||
SVG::SVGSVGElement& dom_node() { return verify_cast<SVG::SVGSVGElement>(SVGGraphicsBox::dom_node()); }
|
SVG::SVGSVGElement& dom_node() { return verify_cast<SVG::SVGSVGElement>(SVGGraphicsBox::dom_node()); }
|
||||||
|
|
||||||
virtual void prepare_for_replaced_layout() override;
|
|
||||||
|
|
||||||
virtual void before_children_paint(PaintContext& context, PaintPhase phase) override;
|
virtual void before_children_paint(PaintContext& context, PaintPhase phase) override;
|
||||||
virtual void after_children_paint(PaintContext& context, PaintPhase phase) override;
|
virtual void after_children_paint(PaintContext& context, PaintPhase phase) override;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue