LibWeb: Refactor SVG files into their own directory; follow spec layout

This commit is contained in:
Matthew Olsson 2020-07-23 09:44:42 -07:00 committed by Andreas Kling
parent 2e73082203
commit b1299f972c
Notes: sideshowbarker 2024-07-19 04:36:46 +09:00
17 changed files with 386 additions and 172 deletions

View file

@ -46,10 +46,8 @@ set(SOURCES
DOM/HTMLInputElement.cpp
DOM/HTMLObjectElement.cpp
DOM/HTMLLinkElement.cpp
DOM/HTMLPathElement.cpp
DOM/HTMLScriptElement.cpp
DOM/HTMLStyleElement.cpp
DOM/HTMLSvgElement.cpp
DOM/HTMLTableElement.cpp
DOM/HTMLTableCellElement.cpp
DOM/HTMLTableRowElement.cpp
@ -57,7 +55,6 @@ set(SOURCES
DOM/ImageData.cpp
DOM/Node.cpp
DOM/ParentNode.cpp
DOM/SvgContext.cpp
DOM/TagNames.cpp
DOM/Text.cpp
DOM/Timer.cpp
@ -82,7 +79,7 @@ set(SOURCES
Layout/LayoutNode.cpp
Layout/LayoutPosition.cpp
Layout/LayoutReplaced.cpp
Layout/LayoutSvg.cpp
Layout/LayoutSVG.cpp
Layout/LayoutTable.cpp
Layout/LayoutTableCell.cpp
Layout/LayoutTableRow.cpp
@ -109,6 +106,12 @@ set(SOURCES
Parser/ListOfActiveFormattingElements.cpp
Parser/StackOfOpenElements.cpp
StylePropertiesModel.cpp
SVG/SVGElement.cpp
SVG/SVGGeometryElement.cpp
SVG/SVGGraphicsElement.cpp
SVG/SVGPathElement.cpp
SVG/SVGSVGElement.cpp
SVG/TagNames.cpp
URLEncoder.cpp
CSS/PropertyID.h
CSS/PropertyID.cpp

View file

@ -56,6 +56,7 @@
#include <LibWeb/Origin.h>
#include <LibWeb/PageView.h>
#include <LibWeb/Parser/CSSParser.h>
#include <LibWeb/SVG/TagNames.h>
#include <stdio.h>
namespace Web {
@ -69,6 +70,7 @@ Document::Document(const URL& url)
{
HTML::AttributeNames::initialize();
HTML::TagNames::initialize();
SVG::TagNames::initialize();
m_style_update_timer = Core::Timer::create_single_shot(0, [this] {
update_style();

View file

@ -41,14 +41,15 @@
#include <LibWeb/DOM/HTMLInputElement.h>
#include <LibWeb/DOM/HTMLLinkElement.h>
#include <LibWeb/DOM/HTMLObjectElement.h>
#include <LibWeb/DOM/HTMLPathElement.h>
#include <LibWeb/DOM/HTMLScriptElement.h>
#include <LibWeb/DOM/HTMLStyleElement.h>
#include <LibWeb/DOM/HTMLSvgElement.h>
#include <LibWeb/DOM/HTMLTableCellElement.h>
#include <LibWeb/DOM/HTMLTableElement.h>
#include <LibWeb/DOM/HTMLTableRowElement.h>
#include <LibWeb/DOM/HTMLTitleElement.h>
#include <LibWeb/SVG/SVGPathElement.h>
#include <LibWeb/SVG/SVGSVGElement.h>
#include <LibWeb/SVG/TagNames.h>
namespace Web {
@ -99,10 +100,10 @@ NonnullRefPtr<Element> create_element(Document& document, const FlyString& tag_n
return adopt(*new HTMLCanvasElement(document, lowercase_tag_name));
if (lowercase_tag_name == HTML::TagNames::object)
return adopt(*new HTMLObjectElement(document, lowercase_tag_name));
if (lowercase_tag_name == HTML::TagNames::svg)
return adopt(*new HTMLSvgElement(document, lowercase_tag_name));
if (lowercase_tag_name == HTML::TagNames::path)
return adopt(*new HTMLPathElement(document, lowercase_tag_name));
if (lowercase_tag_name == SVG::TagNames::svg)
return adopt(*new SVG::SVGSVGElement(document, lowercase_tag_name));
if (lowercase_tag_name == SVG::TagNames::path)
return adopt(*new SVG::SVGPathElement(document, lowercase_tag_name));
return adopt(*new Element(document, lowercase_tag_name));
}

View file

@ -27,16 +27,16 @@
#include <LibGUI/Painter.h>
#include <LibGfx/Font.h>
#include <LibGfx/StylePainter.h>
#include <LibWeb/Layout/LayoutSvg.h>
#include <LibWeb/Layout/LayoutSVG.h>
namespace Web {
LayoutSvg::LayoutSvg(Document& document, const HTMLSvgElement& element, NonnullRefPtr<StyleProperties> style)
LayoutSVG::LayoutSVG(Document& document, const SVG::SVGSVGElement& element, NonnullRefPtr<StyleProperties> style)
: LayoutReplaced(document, element, move(style))
{
}
void LayoutSvg::layout(LayoutMode layout_mode)
void LayoutSVG::layout(LayoutMode layout_mode)
{
set_has_intrinsic_width(true);
set_has_intrinsic_height(true);
@ -45,7 +45,7 @@ void LayoutSvg::layout(LayoutMode layout_mode)
LayoutReplaced::layout(layout_mode);
}
void LayoutSvg::paint(PaintContext& context, PaintPhase phase)
void LayoutSVG::paint(PaintContext& context, PaintPhase phase)
{
if (!is_visible())
return;
@ -57,7 +57,7 @@ void LayoutSvg::paint(PaintContext& context, PaintPhase phase)
return;
if (!node().bitmap())
node().create_bitmap();
node().create_bitmap_as_top_level_svg_element();
ASSERT(node().bitmap());
context.painter().draw_scaled_bitmap(enclosing_int_rect(absolute_rect()), *node().bitmap(), node().bitmap()->rect());

View file

@ -26,21 +26,22 @@
#pragma once
#include <LibWeb/DOM/HTMLSvgElement.h>
#include <LibWeb/SVG/SVGSVGElement.h>
#include <LibWeb/Layout/LayoutReplaced.h>
#include <LibWeb/SVG/SVGSVGElement.h>
namespace Web {
class HTMLSvgElement;
class SVGSVGElement;
class LayoutSvg : public LayoutReplaced {
class LayoutSVG : public LayoutReplaced {
public:
LayoutSvg(Document&, const HTMLSvgElement&, NonnullRefPtr<StyleProperties>);
virtual ~LayoutSvg() override = default;
LayoutSVG(Document&, const SVG::SVGSVGElement&, NonnullRefPtr<StyleProperties>);
virtual ~LayoutSVG() override = default;
virtual void layout(LayoutMode = LayoutMode::Default) override;
virtual void paint(PaintContext&, PaintPhase) override;
HTMLSvgElement& node() { return static_cast<HTMLSvgElement&>(LayoutReplaced::node()); }
SVG::SVGSVGElement& node() { return static_cast<SVG::SVGSVGElement&>(LayoutReplaced::node()); }
private:
virtual const char* class_name() const override { return "LayoutSvg"; }

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2020, Matthew Olsson <matthewcolsson@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <LibWeb/SVG/SVGElement.h>
namespace Web::SVG {
SVGElement::SVGElement(Document& document, const FlyString& tag_name)
: Element(document, tag_name)
{
}
}

View file

@ -26,30 +26,13 @@
#pragma once
#include <LibGfx/Color.h>
#include <LibGfx/Painter.h>
#include <LibWeb/DOM/Element.h>
namespace Web {
namespace Web::SVG {
struct SvgPaintingContext {
Gfx::Color fill_color { Gfx::Color::Black };
Gfx::Color stroke_color { Gfx::Color::Black };
float stroke_width { 1 };
};
class SvgGraphicElement {
class SVGElement : public Element {
public:
virtual void paint(const SvgPaintingContext&, Gfx::Painter& painter) = 0;
void parse_attribute(const FlyString& name, const String& value);
protected:
Gfx::Color fill_color(const SvgPaintingContext&) const;
Gfx::Color stroke_color(const SvgPaintingContext&) const;
float stroke_width(const SvgPaintingContext&) const;
Optional<Gfx::Color> m_fill_color;
Optional<Gfx::Color> m_stroke_color;
Optional<float> m_stroke_width;
SVGElement(Document&, const FlyString& tag_name);
};
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2020, Matthew Olsson <matthewcolsson@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <LibWeb/SVG/SVGGeometryElement.h>
namespace Web::SVG {
SVGGeometryElement::SVGGeometryElement(Document& document, const FlyString& tag_name)
: SVGGraphicsElement(document, tag_name)
{
}
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2020, Matthew Olsson <matthewcolsson@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <LibWeb/SVG/SVGGraphicsElement.h>
namespace Web::SVG {
class SVGGeometryElement : public SVGGraphicsElement {
public:
SVGGeometryElement(Document& document, const FlyString& tag_name);
};
}

View file

@ -24,37 +24,37 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <AK/FlyString.h>
#include <LibWeb/DOM/SvgContext.h>
#include <LibWeb/SVG/SVGGraphicsElement.h>
namespace Web {
namespace Web::SVG {
void SvgGraphicElement::parse_attribute(const FlyString& name, const String& value)
SVGGraphicsElement::SVGGraphicsElement(Document& document, const FlyString& tag_name)
: SVGElement(document, tag_name)
{
if (name == "stroke-width") {
m_stroke_width = strtof(value.characters(), nullptr);
}
void SVGGraphicsElement::parse_attribute(const FlyString& name, const String& value)
{
SVGElement::parse_attribute(name, value);
if (name == "fill") {
m_fill_color = Gfx::Color::from_string(value).value_or(Color::Transparent);
} else if (name == "stroke") {
auto result = Gfx::Color::from_string(value);
m_stroke_color = result.value_or(Gfx::Color::Transparent);
} else if (name == "fill") {
auto result = Gfx::Color::from_string(value);
m_fill_color = result.value_or(Gfx::Color::Transparent);
m_stroke_color = Gfx::Color::from_string(value).value_or(Color::Transparent);
} else if (name == "stroke-width") {
auto result = value.to_int();
if (result.has_value())
m_stroke_width = result.value();
}
}
Gfx::Color SvgGraphicElement::fill_color(const SvgPaintingContext& context) const
SVGPaintingContext SVGGraphicsElement::make_painting_context_from(const SVGPaintingContext& context)
{
return m_fill_color.value_or(context.fill_color);
}
Gfx::Color SvgGraphicElement::stroke_color(const SvgPaintingContext& context) const
{
return m_stroke_color.value_or(context.stroke_color);
}
float SvgGraphicElement::stroke_width(const SvgPaintingContext& context) const
{
return m_stroke_width.value_or(context.stroke_width);
return SVGPaintingContext {
m_fill_color.value_or(context.fill_color),
m_stroke_color.value_or(context.stroke_color),
m_stroke_width.value_or(context.stroke_width),
};
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright (c) 2020, Matthew Olsson <matthewcolsson@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <LibGfx/Path.h>
#include <LibWeb/DOM/Node.h>
#include <LibWeb/SVG/SVGElement.h>
#include <LibWeb/SVG/TagNames.h>
namespace Web::SVG {
struct SVGPaintingContext {
Gfx::Color fill_color;
Gfx::Color stroke_color;
float stroke_width;
};
static const SVGPaintingContext default_painting_context = {
Gfx::Color::Black,
Gfx::Color::Black,
1.0f
};
class SVGGraphicsElement : public SVGElement {
public:
SVGGraphicsElement(Document&, const FlyString& tag_name);
virtual void parse_attribute(const FlyString& name, const String& value) override;
virtual void paint(Gfx::Painter& painter, const SVGPaintingContext& context) = 0;
SVGPaintingContext make_painting_context_from(const SVGPaintingContext& context);
protected:
Optional<Gfx::Color> m_fill_color;
Optional<Gfx::Color> m_stroke_color;
Optional<float> m_stroke_width;
};
}
namespace Web {
template<>
inline bool is<SVG::SVGGraphicsElement>(const Node& node)
{
if (!is<Element>(node))
return false;
auto tag_name = to<Element>(node).tag_name();
#define __ENUMERATE_SVG_TAG(name) \
if (tag_name == #name) \
return true;
ENUMERATE_SVG_TAGS
#undef ENUMERATE_SVG_TAG
return false;
}
}

View file

@ -25,15 +25,16 @@
*/
#include <AK/StringBuilder.h>
#include <LibGfx/Painter.h>
#include <LibGfx/Path.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Event.h>
#include <LibWeb/DOM/HTMLPathElement.h>
#include <LibWeb/SVG/SVGPathElement.h>
#include <ctype.h>
//#define PATH_DEBUG
namespace Web {
namespace Web::SVG {
PathDataParser::PathDataParser(const String& source)
: m_source(source)
@ -269,7 +270,7 @@ void PathDataParser::parse_whitespace(bool must_match_once)
matched = true;
}
ASSERT(!must_match_once || matched);
ASSERT(!must_match_once || matched);
}
void PathDataParser::parse_comma_whitespace()
@ -326,7 +327,7 @@ float PathDataParser::parse_number()
float PathDataParser::parse_flag()
{
auto number = parse_number();
ASSERT(number == 0 || number == 1);
ASSERT(number == 0 || number == 1);
return number;
}
@ -348,8 +349,8 @@ bool PathDataParser::match_number() const
return !done() && (isdigit(ch()) || ch() == '-' || ch() == '+');
}
HTMLPathElement::HTMLPathElement(Document& document, const FlyString& tag_name)
: HTMLElement(document, tag_name)
SVGPathElement::SVGPathElement(Document& document, const FlyString& tag_name)
: SVGGeometryElement(document, tag_name)
{
}
@ -414,16 +415,15 @@ static void print_instruction(const PathInstruction& instruction)
}
#endif
void HTMLPathElement::parse_attribute(const FlyString& name, const String& value)
void SVGPathElement::parse_attribute(const FlyString& name, const String& value)
{
HTMLElement::parse_attribute(name, value);
SvgGraphicElement::parse_attribute(name, value);
SVGGeometryElement::parse_attribute(name, value);
if (name == "d")
m_instructions = PathDataParser(value).parse();
}
void HTMLPathElement::paint(const SvgPaintingContext& context, Gfx::Painter& painter)
void SVGPathElement::paint(Gfx::Painter& painter, const SVGPaintingContext& context)
{
Gfx::Path path;
@ -595,9 +595,8 @@ void HTMLPathElement::paint(const SvgPaintingContext& context, Gfx::Painter& pai
closed_path.close();
// Fills are computed as though all paths are closed (https://svgwg.org/svg2-draft/painting.html#FillProperties)
painter.fill_path(closed_path, fill_color(context), Gfx::Painter::WindingRule::EvenOdd);
painter.stroke_path(path, stroke_color(context), stroke_width(context));
painter.fill_path(closed_path, m_fill_color.value_or(context.fill_color), Gfx::Painter::WindingRule::EvenOdd);
painter.stroke_path(path, m_stroke_color.value_or(context.stroke_color), m_stroke_width.value_or(context.stroke_width));
}
}

View file

@ -28,9 +28,9 @@
#include <LibGfx/Bitmap.h>
#include <LibWeb/DOM/HTMLElement.h>
#include <LibWeb/DOM/SvgContext.h>
#include <LibWeb/SVG/SVGGeometryElement.h>
namespace Web {
namespace Web::SVG {
enum class PathInstructionType {
Move,
@ -100,24 +100,16 @@ private:
Vector<PathInstruction> m_instructions;
};
class HTMLPathElement final
: public HTMLElement
, public SvgGraphicElement {
class SVGPathElement final : public SVGGeometryElement {
public:
HTMLPathElement(Document&, const FlyString& tag_name);
virtual ~HTMLPathElement() override = default;
SVGPathElement(Document&, const FlyString& tag_name);
virtual ~SVGPathElement() override = default;
virtual void parse_attribute(const FlyString& name, const String& value) override;
virtual void paint(const SvgPaintingContext&, Gfx::Painter& painter) override;
virtual void paint(Gfx::Painter& painter, const SVGPaintingContext& context) override;
private:
Vector<PathInstruction> m_instructions;
};
template<>
inline bool is<HTMLPathElement>(const Node& node)
{
return is<Element>(node) && to<Element>(node).tag_name() == HTML::TagNames::path;
}
}

View file

@ -24,47 +24,34 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <LibGfx/Painter.h>
#include <LibGfx/Path.h>
#include <LibWeb/CSS/StyleResolver.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Event.h>
#include <LibWeb/DOM/HTMLPathElement.h>
#include <LibWeb/DOM/HTMLSvgElement.h>
#include <LibWeb/Layout/LayoutSvg.h>
#include <LibWeb/SVG/SVGPathElement.h>
#include <LibWeb/SVG/SVGSVGElement.h>
#include <LibWeb/Layout/LayoutSVG.h>
#include <ctype.h>
namespace Web {
namespace Web::SVG {
static constexpr auto max_svg_area = 16384 * 16384;
HTMLSvgElement::HTMLSvgElement(Document& document, const FlyString& tag_name)
: HTMLElement(document, tag_name)
SVGSVGElement::SVGSVGElement(Document& document, const FlyString& tag_name)
: SVGGraphicsElement(document, tag_name)
{
}
void HTMLSvgElement::parse_attribute(const FlyString& name, const String& value)
{
HTMLElement::parse_attribute(name, value);
if (name == "stroke") {
m_stroke_color = Gfx::Color::from_string(value);
} else if (name == "stroke-width") {
auto result = value.to_int();
if (result.has_value())
m_stroke_width = result.value();
} else if (name == "fill") {
m_fill_color = Gfx::Color::from_string(value);
}
}
RefPtr<LayoutNode> HTMLSvgElement::create_layout_node(const StyleProperties* parent_style)
RefPtr<LayoutNode> SVGSVGElement::create_layout_node(const StyleProperties* parent_style)
{
auto style = document().style_resolver().resolve_style(*this, parent_style);
if (style->display() == CSS::Display::None)
return nullptr;
return adopt(*new LayoutSvg(document(), *this, move(style)));
return adopt(*new LayoutSVG(document(), *this, move(style)));
}
static Gfx::IntSize bitmap_size_for_canvas(const HTMLSvgElement& canvas)
static Gfx::IntSize bitmap_size_for_canvas(const SVGSVGElement& canvas)
{
auto width = canvas.width();
auto height = canvas.height();
@ -83,7 +70,7 @@ static Gfx::IntSize bitmap_size_for_canvas(const HTMLSvgElement& canvas)
return Gfx::IntSize(width, height);
}
bool HTMLSvgElement::create_bitmap()
bool SVGSVGElement::create_bitmap_as_top_level_svg_element()
{
auto size = bitmap_size_for_canvas(*this);
if (size.is_empty()) {
@ -95,55 +82,26 @@ bool HTMLSvgElement::create_bitmap()
m_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA32, size);
Gfx::Painter painter(*m_bitmap);
paint(painter);
paint(painter, make_painting_context_from(default_painting_context));
return m_bitmap;
}
SvgPaintingContext HTMLSvgElement::make_context() const
{
SvgPaintingContext context;
if (m_stroke_width.has_value())
context.stroke_width = m_stroke_width.value();
if (m_stroke_color.has_value())
context.stroke_color = m_stroke_color.value();
if (m_fill_color.has_value())
context.fill_color = m_fill_color.value();
return context;
}
unsigned HTMLSvgElement::width() const
unsigned SVGSVGElement::width() const
{
return attribute(HTML::AttributeNames::width).to_uint().value_or(300);
}
unsigned HTMLSvgElement::height() const
unsigned SVGSVGElement::height() const
{
return attribute(HTML::AttributeNames::height).to_uint().value_or(150);
}
static bool is_svg_graphic_element(const HTMLElement& element)
{
return is<HTMLPathElement>(element);
}
static SvgGraphicElement& as_svg_graphic_element(HTMLElement& element)
{
if (is<HTMLPathElement>(element))
return to<HTMLPathElement>(element);
ASSERT_NOT_REACHED();
}
void HTMLSvgElement::paint(Gfx::Painter& painter)
void SVGSVGElement::paint(Gfx::Painter& painter, const SVGPaintingContext& context)
{
for_each_child([&](Node& child) {
if (is<HTMLElement>(child)) {
auto& element = to<HTMLElement>(child);
if (is_svg_graphic_element(element)) {
as_svg_graphic_element(element).paint(make_context(), painter);
}
if (is<SVGGraphicsElement>(child)) {
to<SVGGraphicsElement>(child).paint(painter, make_painting_context_from(context));
}
});
}

View file

@ -27,40 +27,26 @@
#pragma once
#include <LibGfx/Bitmap.h>
#include <LibWeb/DOM/HTMLElement.h>
#include <LibWeb/DOM/SvgContext.h>
#include <LibWeb/SVG/SVGGraphicsElement.h>
namespace Web {
namespace Web::SVG {
class HTMLSvgElement final : public HTMLElement {
class SVGSVGElement final : public SVGGraphicsElement {
public:
HTMLSvgElement(Document&, const FlyString& tag_name);
virtual ~HTMLSvgElement() override = default;
SVGSVGElement(Document&, const FlyString& tag_name);
virtual void parse_attribute(const FlyString& name, const String& value) override;
virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) override;
const RefPtr<Gfx::Bitmap> bitmap() const { return m_bitmap; }
bool create_bitmap();
SvgPaintingContext make_context() const;
bool create_bitmap_as_top_level_svg_element();
virtual void paint(Gfx::Painter& painter, const SVGPaintingContext& context) override;
unsigned width() const;
unsigned height() const;
private:
void paint(Gfx::Painter&);
RefPtr<Gfx::Bitmap> m_bitmap;
Optional<float> m_stroke_width;
Optional<Color> m_stroke_color;
Optional<Color> m_fill_color;
};
template<>
inline bool is<HTMLSvgElement>(const Node& node)
{
return is<Element>(node) && to<Element>(node).tag_name() == HTML::TagNames::svg;
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2020, Matthew Olsson <matthewcolsson@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <LibWeb/SVG/TagNames.h>
namespace Web::SVG::TagNames {
#define __ENUMERATE_SVG_TAG(name) FlyString name;
ENUMERATE_SVG_TAGS
#undef __ENUMERATE_SVG_TAG
void initialize()
{
static bool s_initialized = false;
if (s_initialized)
return;
#define __ENUMERATE_SVG_TAG(name) name = #name;
ENUMERATE_SVG_TAGS
#undef __ENUMERATE_SVG_TAG
s_initialized = true;
}
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (c) 2020, Matthew Olsson <matthewcolsson@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <AK/FlyString.h>
namespace Web::SVG::TagNames {
void initialize();
#define ENUMERATE_SVG_GRAPHICS_TAGS \
__ENUMERATE_SVG_TAG(svg) \
__ENUMERATE_SVG_TAG(path) \
#define ENUMERATE_SVG_TAGS \
ENUMERATE_SVG_GRAPHICS_TAGS
#define __ENUMERATE_SVG_TAG(name) extern FlyString name;
ENUMERATE_SVG_TAGS
#undef __ENUMERATE_SVG_TAG
}