mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 03:17:35 +00:00
LibWeb: Implement painting for svg text
The implementation of painting for SVG text follows the same pattern as the implementation of painting for SVG geometries. However, instead of reusing the existing PaintableWithLines to draw text, a new class called SVGTextPaintable is introduced. because everything that is painted inside an SVG is expected to inherit from SVGGraphicsPaintable. Therefore reusing the text painting from regular text nodes would require significant refactoring.
This commit is contained in:
parent
81a6976e90
commit
0d8d7ae94e
9 changed files with 216 additions and 0 deletions
|
@ -12,6 +12,7 @@
|
|||
#include <LibWeb/Layout/SVGFormattingContext.h>
|
||||
#include <LibWeb/Layout/SVGGeometryBox.h>
|
||||
#include <LibWeb/Layout/SVGSVGBox.h>
|
||||
#include <LibWeb/Layout/SVGTextBox.h>
|
||||
#include <LibWeb/SVG/SVGForeignObjectElement.h>
|
||||
#include <LibWeb/SVG/SVGSVGElement.h>
|
||||
|
||||
|
@ -187,6 +188,10 @@ void SVGFormattingContext::run(Box const& box, LayoutMode layout_mode, Available
|
|||
} else if (is<SVGSVGBox>(descendant)) {
|
||||
SVGFormattingContext nested_context(m_state, descendant, this);
|
||||
nested_context.run(descendant, layout_mode, available_space);
|
||||
} else if (is<SVGTextBox>(descendant)) {
|
||||
auto const& svg_text_box = static_cast<SVGTextBox const&>(descendant);
|
||||
// NOTE: This hack creates a layout state to ensure the existence of a paintable box node in LayoutState::commit(), even when none of the values from UsedValues impact the SVG text.
|
||||
m_state.get_mutable(svg_text_box);
|
||||
}
|
||||
|
||||
return IterationDecision::Continue;
|
||||
|
|
43
Userland/Libraries/LibWeb/Layout/SVGTextBox.cpp
Normal file
43
Userland/Libraries/LibWeb/Layout/SVGTextBox.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibWeb/Layout/SVGTextBox.h>
|
||||
#include <LibWeb/Painting/SVGTextPaintable.h>
|
||||
#include <LibWeb/SVG/SVGSVGElement.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
SVGTextBox::SVGTextBox(DOM::Document& document, SVG::SVGTextContentElement& element, NonnullRefPtr<CSS::StyleProperties> properties)
|
||||
: SVGGraphicsBox(document, element, properties)
|
||||
{
|
||||
}
|
||||
|
||||
CSSPixelPoint SVGTextBox::viewbox_origin() const
|
||||
{
|
||||
auto* svg_box = dom_node().first_ancestor_of_type<SVG::SVGSVGElement>();
|
||||
if (!svg_box || !svg_box->view_box().has_value())
|
||||
return { 0, 0 };
|
||||
return { svg_box->view_box().value().min_x, svg_box->view_box().value().min_y };
|
||||
}
|
||||
|
||||
Optional<Gfx::AffineTransform> SVGTextBox::layout_transform() const
|
||||
{
|
||||
auto& geometry_element = dom_node();
|
||||
auto transform = geometry_element.get_transform();
|
||||
auto* svg_box = geometry_element.first_ancestor_of_type<SVG::SVGSVGElement>();
|
||||
auto origin = viewbox_origin().to_type<double>().to_type<float>();
|
||||
Gfx::FloatPoint paint_offset = {};
|
||||
if (svg_box && svg_box->view_box().has_value())
|
||||
paint_offset = svg_box->paintable_box()->absolute_rect().location().to_type<double>().to_type<float>();
|
||||
return Gfx::AffineTransform {}.translate(paint_offset).translate(-origin).multiply(transform);
|
||||
}
|
||||
|
||||
JS::GCPtr<Painting::Paintable> SVGTextBox::create_paintable() const
|
||||
{
|
||||
return Painting::SVGTextPaintable::create(*this);
|
||||
}
|
||||
|
||||
}
|
33
Userland/Libraries/LibWeb/Layout/SVGTextBox.h
Normal file
33
Userland/Libraries/LibWeb/Layout/SVGTextBox.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Optional.h>
|
||||
#include <LibWeb/Layout/SVGGraphicsBox.h>
|
||||
#include <LibWeb/SVG/SVGTextContentElement.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
class SVGTextBox final : public SVGGraphicsBox {
|
||||
JS_CELL(SVGTextBox, SVGGraphicsBox);
|
||||
|
||||
public:
|
||||
SVGTextBox(DOM::Document&, SVG::SVGTextContentElement&, NonnullRefPtr<CSS::StyleProperties>);
|
||||
virtual ~SVGTextBox() override = default;
|
||||
|
||||
SVG::SVGTextContentElement& dom_node() { return static_cast<SVG::SVGTextContentElement&>(SVGGraphicsBox::dom_node()); }
|
||||
SVG::SVGTextContentElement const& dom_node() const { return static_cast<SVG::SVGTextContentElement const&>(SVGGraphicsBox::dom_node()); }
|
||||
|
||||
Optional<Gfx::AffineTransform> layout_transform() const;
|
||||
|
||||
virtual JS::GCPtr<Painting::Paintable> create_paintable() const override;
|
||||
|
||||
private:
|
||||
CSSPixelPoint viewbox_origin() const;
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue