From 231f95510aef965f672f48475d55c6f15d8ad647 Mon Sep 17 00:00:00 2001 From: sammycage Date: Sun, 7 Jan 2024 16:25:57 +0100 Subject: [PATCH] Support simple DOM manipulation #98 --- include/lunasvg.h | 76 ++++++++- source/element.cpp | 71 +++++++- source/element.h | 12 +- source/layoutcontext.cpp | 9 +- source/layoutcontext.h | 6 +- source/lunasvg.cpp | 342 +++++++++++++++++++++++---------------- source/parser.cpp | 91 +---------- source/parser.h | 22 --- source/svgelement.cpp | 4 +- source/svgelement.h | 4 +- source/useelement.cpp | 11 +- source/useelement.h | 2 +- 12 files changed, 378 insertions(+), 272 deletions(-) diff --git a/include/lunasvg.h b/include/lunasvg.h index 43308c8..7553d28 100644 --- a/include/lunasvg.h +++ b/include/lunasvg.h @@ -23,9 +23,10 @@ #ifndef LUNASVG_H #define LUNASVG_H +#include #include #include -#include +#include #if defined(_MSC_VER) && defined(LUNASVG_SHARED) #ifdef LUNASVG_EXPORT @@ -125,7 +126,66 @@ class LUNASVG_API Bitmap { std::shared_ptr m_impl; }; +class Element; + +class LUNASVG_API DomElement { +public: + /** + * @brief DomElement + */ + DomElement() = default; + + /** + * @brief DomElement + * @param element + */ + DomElement(Element* element); + + /** + * @brief setAttribute + * @param name + * @param value + */ + void setAttribute(const std::string& name, const std::string& value); + + /** + * @brief getAttribute + * @param name + * @return + */ + std::string getAttribute(const std::string& name) const; + + /** + * @brief removeAttribute + * @param name + */ + void removeAttribute(const std::string& name); + + /** + * @brief hasAttribute + * @param name + * @return + */ + bool hasAttribute(const std::string& name) const; + + /** + * @brief isNull + * @return + */ + bool isNull() const { return m_element == nullptr; } + + /** + * @brief get + * @return + */ + Element* get() { return m_element; } + +private: + Element* m_element = nullptr; +}; + class LayoutSymbol; +class SVGElement; class LUNASVG_API Document { public: @@ -204,13 +264,23 @@ class LUNASVG_API Document { */ Bitmap renderToBitmap(std::uint32_t width = 0, std::uint32_t height = 0, std::uint32_t backgroundColor = 0x00000000) const; + /** + * @brief updateLayout + */ + void updateLayout(); + Document(Document&&); ~Document(); + DomElement getElementById(const std::string& id) const; + DomElement rootElement() const; + private: Document(); - - std::unique_ptr root; + bool parse(const char* data, size_t size); + std::unique_ptr m_rootElement; + std::map m_idCache; + std::unique_ptr m_rootBox; }; } //namespace lunasvg diff --git a/source/element.cpp b/source/element.cpp index 7b85df1..3a9a965 100644 --- a/source/element.cpp +++ b/source/element.cpp @@ -1,5 +1,16 @@ #include "element.h" +#include "clippathelement.h" +#include "defselement.h" +#include "gelement.h" +#include "geometryelement.h" +#include "markerelement.h" +#include "maskelement.h" +#include "paintelement.h" +#include "stopelement.h" #include "svgelement.h" +#include "symbolelement.h" +#include "useelement.h" +#include "styleelement.h" #include "parser.h" namespace lunasvg { @@ -20,6 +31,58 @@ Element::Element(ElementID id) { } +std::unique_ptr Element::create(ElementID id) +{ + switch(id) { + case ElementID::Svg: + return makeUnique(); + case ElementID::Path: + return makeUnique(); + case ElementID::G: + return makeUnique(); + case ElementID::Rect: + return makeUnique(); + case ElementID::Circle: + return makeUnique(); + case ElementID::Ellipse: + return makeUnique(); + case ElementID::Line: + return makeUnique(); + case ElementID::Defs: + return makeUnique(); + case ElementID::Polygon: + return makeUnique(); + case ElementID::Polyline: + return makeUnique(); + case ElementID::Stop: + return makeUnique(); + case ElementID::LinearGradient: + return makeUnique(); + case ElementID::RadialGradient: + return makeUnique(); + case ElementID::Symbol: + return makeUnique(); + case ElementID::Use: + return makeUnique(); + case ElementID::Pattern: + return makeUnique(); + case ElementID::Mask: + return makeUnique(); + case ElementID::ClipPath: + return makeUnique(); + case ElementID::SolidColor: + return makeUnique(); + case ElementID::Marker: + return makeUnique(); + case ElementID::Style: + return makeUnique(); + default: + break; + } + + return nullptr; +} + void Element::set(PropertyID id, const std::string& value, int specificity) { for(auto& property : properties) { @@ -79,7 +142,6 @@ Element* Element::previousElement() const { if(parent == nullptr) return nullptr; - Element* element = nullptr; auto it = parent->children.begin(); auto end = parent->children.end(); @@ -99,7 +161,6 @@ Element* Element::nextElement() const { if(parent == nullptr) return nullptr; - Element* element = nullptr; auto it = parent->children.rbegin(); auto end = parent->children.rend(); @@ -154,19 +215,19 @@ Rect Element::currentViewport() const return parent->currentViewport(); } -void Element::build(const TreeBuilder* builder) +void Element::build(const Document* document) { for(auto& child : children) { if(child->isText()) continue; auto element = static_cast(child.get()); - element->build(builder); + element->build(document); } } std::unique_ptr Element::clone() const { - auto element = TreeBuilder::createElement(id); + auto element = Element::create(id); element->properties = properties; for(auto& child : children) element->addChild(child->clone()); diff --git a/source/element.h b/source/element.h index 7f6d074..c628522 100644 --- a/source/element.h +++ b/source/element.h @@ -5,6 +5,7 @@ #include #include "property.h" +#include "lunasvg.h" namespace lunasvg { @@ -107,6 +108,10 @@ enum class PropertyID { Y2 }; +ElementID elementid(const std::string& name); +PropertyID csspropertyid(const std::string& name); +PropertyID propertyid(const std::string& name); + struct Property { int specificity; PropertyID id; @@ -153,11 +158,9 @@ class TextNode : public Node { using NodeList = std::list>; -class TreeBuilder; - class Element : public Node { public: - Element(ElementID id); + static std::unique_ptr create(ElementID id); void set(PropertyID id, const std::string& value, int specificity); const std::string& get(PropertyID id) const; @@ -170,7 +173,7 @@ class Element : public Node { void layoutChildren(LayoutContext* context, LayoutContainer* current) const; Rect currentViewport() const; - virtual void build(const TreeBuilder* builder); + virtual void build(const Document* document); template void transverse(T callback) { @@ -191,6 +194,7 @@ class Element : public Node { std::unique_ptr clone() const final; public: + Element(ElementID id); ElementID id; NodeList children; PropertyList properties; diff --git a/source/layoutcontext.cpp b/source/layoutcontext.cpp index 526f5d1..20dd6df 100644 --- a/source/layoutcontext.cpp +++ b/source/layoutcontext.cpp @@ -467,14 +467,17 @@ void RenderState::endGroup(RenderState& state, const BlendInfo& info) state.canvas->blend(canvas.get(), BlendMode::Src_Over, m_mode == RenderMode::Display ? info.opacity : 1.0); } -LayoutContext::LayoutContext(const TreeBuilder* builder, LayoutSymbol* root) - : m_builder(builder), m_root(root) +LayoutContext::LayoutContext(const Document* document, LayoutSymbol* root) + : m_document(document), m_root(root) { } Element* LayoutContext::getElementById(const std::string& id) const { - return m_builder->getElementById(id); + auto element = m_document->getElementById(id); + if(element.isNull()) + return nullptr; + return element.get(); } LayoutObject* LayoutContext::getResourcesById(const std::string& id) const diff --git a/source/layoutcontext.h b/source/layoutcontext.h index 4c0e1ce..d38739c 100644 --- a/source/layoutcontext.h +++ b/source/layoutcontext.h @@ -325,13 +325,13 @@ class RenderState { RenderMode m_mode; }; -class TreeBuilder; +class Document; class StyledElement; class GeometryElement; class LayoutContext { public: - LayoutContext(const TreeBuilder* builder, LayoutSymbol* root); + LayoutContext(const Document* document, LayoutSymbol* root); Element* getElementById(const std::string& id) const; LayoutObject* getResourcesById(const std::string& id) const; @@ -351,7 +351,7 @@ class LayoutContext { bool hasReference(const Element* element) const; private: - const TreeBuilder* m_builder; + const Document* m_document; LayoutSymbol* m_root; std::map m_resourcesCache; std::set m_references; diff --git a/source/lunasvg.cpp b/source/lunasvg.cpp index 956b6b4..5018c17 100644 --- a/source/lunasvg.cpp +++ b/source/lunasvg.cpp @@ -1,6 +1,7 @@ #include "lunasvg.h" #include "layoutcontext.h" #include "parser.h" +#include "svgelement.h" #include #include @@ -8,6 +9,138 @@ namespace lunasvg { +Box::Box(double x, double y, double w, double h) + : x(x), y(y), w(w), h(h) +{ +} + +Box::Box(const Rect& rect) + : x(rect.x), y(rect.y), w(rect.w), h(rect.h) +{ +} + +Box& Box::transform(const Matrix &matrix) +{ + *this = transformed(matrix); + return *this; +} + +Box Box::transformed(const Matrix& matrix) const +{ + return Transform(matrix).map(*this); +} + +Matrix::Matrix(double a, double b, double c, double d, double e, double f) + : a(a), b(b), c(c), d(d), e(e), f(f) +{ +} + +Matrix::Matrix(const Transform& transform) + : a(transform.m00), b(transform.m10), c(transform.m01), d(transform.m11), e(transform.m02), f(transform.m12) +{ +} + +Matrix& Matrix::rotate(double angle) +{ + *this = rotated(angle) * *this; + return *this; +} + +Matrix& Matrix::rotate(double angle, double cx, double cy) +{ + *this = rotated(angle, cx, cy) * *this; + return *this; +} + +Matrix& Matrix::scale(double sx, double sy) +{ + *this = scaled(sx, sy) * *this; + return *this; +} + +Matrix& Matrix::shear(double shx, double shy) +{ + *this = sheared(shx, shy) * *this; + return *this; +} + +Matrix& Matrix::translate(double tx, double ty) +{ + *this = translated(tx, ty) * *this; + return *this; +} + +Matrix& Matrix::transform(double a, double b, double c, double d, double e, double f) +{ + *this = Matrix{a, b, c, d, e, f} * *this; + return *this; +} + +Matrix& Matrix::identity() +{ + *this = Matrix{1, 0, 0, 1, 0, 0}; + return *this; +} + +Matrix& Matrix::invert() +{ + *this = inverted(); + return *this; +} + +Matrix& Matrix::operator*=(const Matrix& matrix) +{ + *this = *this * matrix; + return *this; +} + +Matrix& Matrix::premultiply(const Matrix& matrix) +{ + *this = matrix * *this; + return *this; +} + +Matrix& Matrix::postmultiply(const Matrix& matrix) +{ + *this = *this * matrix; + return *this; +} + +Matrix Matrix::inverted() const +{ + return Transform(*this).inverted(); +} + +Matrix Matrix::operator*(const Matrix& matrix) const +{ + return Transform(*this) * Transform(matrix); +} + +Matrix Matrix::rotated(double angle) +{ + return Transform::rotated(angle); +} + +Matrix Matrix::rotated(double angle, double cx, double cy) +{ + return Transform::rotated(angle, cx, cy); +} + +Matrix Matrix::scaled(double sx, double sy) +{ + return Transform::scaled(sx, sy); +} + +Matrix Matrix::sheared(double shx, double shy) +{ + return Transform::sheared(shx, shy); +} + +Matrix Matrix::translated(double tx, double ty) +{ + return Transform::translated(tx, ty); +} + struct Bitmap::Impl { Impl(std::uint8_t* data, std::uint32_t width, std::uint32_t height, std::uint32_t stride); Impl(std::uint32_t width, std::uint32_t height); @@ -139,136 +272,48 @@ void Bitmap::convert(int ri, int gi, int bi, int ai, bool unpremultiply) } } -Box::Box(double x, double y, double w, double h) - : x(x), y(y), w(w), h(h) -{ -} - -Box::Box(const Rect& rect) - : x(rect.x), y(rect.y), w(rect.w), h(rect.h) -{ -} - -Box& Box::transform(const Matrix &matrix) -{ - *this = transformed(matrix); - return *this; -} - -Box Box::transformed(const Matrix& matrix) const -{ - return Transform(matrix).map(*this); -} - -Matrix::Matrix(double a, double b, double c, double d, double e, double f) - : a(a), b(b), c(c), d(d), e(e), f(f) -{ -} - -Matrix::Matrix(const Transform& transform) - : a(transform.m00), b(transform.m10), c(transform.m01), d(transform.m11), e(transform.m02), f(transform.m12) -{ -} - -Matrix& Matrix::rotate(double angle) -{ - *this = rotated(angle) * *this; - return *this; -} - -Matrix& Matrix::rotate(double angle, double cx, double cy) -{ - *this = rotated(angle, cx, cy) * *this; - return *this; -} - -Matrix& Matrix::scale(double sx, double sy) -{ - *this = scaled(sx, sy) * *this; - return *this; -} - -Matrix& Matrix::shear(double shx, double shy) -{ - *this = sheared(shx, shy) * *this; - return *this; -} - -Matrix& Matrix::translate(double tx, double ty) -{ - *this = translated(tx, ty) * *this; - return *this; -} - -Matrix& Matrix::transform(double a, double b, double c, double d, double e, double f) -{ - *this = Matrix{a, b, c, d, e, f} * *this; - return *this; -} - -Matrix& Matrix::identity() -{ - *this = Matrix{1, 0, 0, 1, 0, 0}; - return *this; -} - -Matrix& Matrix::invert() -{ - *this = inverted(); - return *this; -} - -Matrix& Matrix::operator*=(const Matrix& matrix) -{ - *this = *this * matrix; - return *this; -} - -Matrix& Matrix::premultiply(const Matrix& matrix) -{ - *this = matrix * *this; - return *this; -} - -Matrix& Matrix::postmultiply(const Matrix& matrix) +DomElement::DomElement(Element* element) + : m_element(element) { - *this = *this * matrix; - return *this; } -Matrix Matrix::inverted() const +void DomElement::setAttribute(const std::string& name, const std::string& value) { - return Transform(*this).inverted(); + if(m_element) { + auto id = propertyid(name); + if(id != PropertyID::Unknown) { + m_element->set(id, value, 0x1000); + } + } } -Matrix Matrix::operator*(const Matrix& matrix) const +std::string DomElement::getAttribute(const std::string& name) const { - return Transform(*this) * Transform(matrix); -} - -Matrix Matrix::rotated(double angle) -{ - return Transform::rotated(angle); -} + if(m_element) { + auto id = propertyid(name); + if(id != PropertyID::Unknown) { + return m_element->get(id); + } + } -Matrix Matrix::rotated(double angle, double cx, double cy) -{ - return Transform::rotated(angle, cx, cy); + return std::string(); } -Matrix Matrix::scaled(double sx, double sy) +void DomElement::removeAttribute(const std::string& name) { - return Transform::scaled(sx, sy); + setAttribute(name, std::string()); } -Matrix Matrix::sheared(double shx, double shy) +bool DomElement::hasAttribute(const std::string& name) const { - return Transform::sheared(shx, shy); -} + if(m_element) { + auto id = propertyid(name); + if(id != PropertyID::Unknown) { + return m_element->has(id); + } + } -Matrix Matrix::translated(double tx, double ty) -{ - return Transform::translated(tx, ty); + return false; } std::unique_ptr Document::loadFromFile(const std::string& filename) @@ -292,14 +337,10 @@ std::unique_ptr Document::loadFromData(const std::string& string) std::unique_ptr Document::loadFromData(const char* data, std::size_t size) { - TreeBuilder builder; - if(!builder.parse(data, size)) - return nullptr; - auto root = builder.layout(); - if(root == nullptr) - return nullptr; std::unique_ptr document(new Document); - document->root = std::move(root); + if(!document->parse(data, size)) + return nullptr; + document->updateLayout(); return document; } @@ -310,58 +351,87 @@ std::unique_ptr Document::loadFromData(const char* data) void Document::setMatrix(const Matrix& matrix) { - root->transform = Transform(matrix); + if(m_rootBox) { + m_rootBox->transform = Transform(matrix); + } } Matrix Document::matrix() const { - return root->transform; + if(m_rootBox == nullptr) + return Matrix(); + return m_rootBox->transform; } Box Document::box() const { - return root->map(root->strokeBoundingBox()); + if(m_rootBox == nullptr) + return Box(); + return m_rootBox->map(m_rootBox->strokeBoundingBox()); } double Document::width() const { - return root->width; + if(m_rootBox == nullptr) + return 0.0; + return m_rootBox->width; } double Document::height() const { - return root->height; + if(m_rootBox == nullptr) + return 0.0; + return m_rootBox->height; } void Document::render(Bitmap bitmap, const Matrix& matrix) const { + if(m_rootBox == nullptr) + return; RenderState state(nullptr, RenderMode::Display); state.canvas = Canvas::create(bitmap.data(), bitmap.width(), bitmap.height(), bitmap.stride()); state.transform = Transform(matrix); - root->render(state); + m_rootBox->render(state); } Bitmap Document::renderToBitmap(std::uint32_t width, std::uint32_t height, std::uint32_t backgroundColor) const { - if(root->width == 0.0 || root->height == 0.0) - return Bitmap{}; - + if(m_rootBox == nullptr || m_rootBox->width == 0.0 || m_rootBox->height == 0.0) + return Bitmap(); if(width == 0 && height == 0) { - width = static_cast(std::ceil(root->width)); - height = static_cast(std::ceil(root->height)); + width = static_cast(std::ceil(m_rootBox->width)); + height = static_cast(std::ceil(m_rootBox->height)); } else if(width != 0 && height == 0) { - height = static_cast(std::ceil(width * root->height / root->width)); + height = static_cast(std::ceil(width * m_rootBox->height / m_rootBox->width)); } else if(height != 0 && width == 0) { - width = static_cast(std::ceil(height * root->width / root->height)); + width = static_cast(std::ceil(height * m_rootBox->width / m_rootBox->height)); } - Matrix matrix(width / root->width, 0, 0, height / root->height, 0, 0); + Matrix matrix(width / m_rootBox->width, 0, 0, height / m_rootBox->height, 0, 0); Bitmap bitmap(width, height); bitmap.clear(backgroundColor); render(bitmap, matrix); return bitmap; } +void Document::updateLayout() +{ + m_rootBox = m_rootElement->layoutTree(this); +} + +DomElement Document::getElementById(const std::string& id) const +{ + auto it = m_idCache.find(id); + if(it == m_idCache.end()) + return nullptr; + return it->second; +} + +DomElement Document::rootElement() const +{ + return m_rootElement.get(); +} + Document::Document(Document&&) = default; Document::~Document() = default; Document::Document() = default; diff --git a/source/parser.cpp b/source/parser.cpp index 96f5d69..98c120a 100644 --- a/source/parser.cpp +++ b/source/parser.cpp @@ -1,19 +1,7 @@ #include "parser.h" #include "parserutils.h" #include "layoutcontext.h" - -#include "clippathelement.h" -#include "defselement.h" -#include "gelement.h" -#include "geometryelement.h" -#include "markerelement.h" -#include "maskelement.h" -#include "paintelement.h" -#include "stopelement.h" #include "svgelement.h" -#include "symbolelement.h" -#include "useelement.h" -#include "styleelement.h" namespace lunasvg { @@ -979,7 +967,7 @@ bool Parser::parseTransform(const char*& ptr, const char* end, TransformType& ty return true; } -static inline ElementID elementid(const std::string& name) +ElementID elementid(const std::string& name) { static const std::map elementmap = { {"circle", ElementID::Circle}, @@ -1011,7 +999,7 @@ static inline ElementID elementid(const std::string& name) return it->second; } -static inline PropertyID csspropertyid(const std::string& name) +PropertyID csspropertyid(const std::string& name) { static const std::map csspropertymap = { {"clip-path", PropertyID::Clip_Path}, @@ -1048,7 +1036,7 @@ static inline PropertyID csspropertyid(const std::string& name) return it->second; } -static inline PropertyID propertyid(const std::string& name) +PropertyID propertyid(const std::string& name) { static const std::map propertymap = { {"class", PropertyID::Class}, @@ -1680,11 +1668,7 @@ static inline void removeComments(std::string& value) } } -TreeBuilder::TreeBuilder() = default; - -TreeBuilder::~TreeBuilder() = default; - -bool TreeBuilder::parse(const char* data, std::size_t size) +bool Document::parse(const char* data, std::size_t size) { auto ptr = data; auto end = ptr + size; @@ -1815,7 +1799,7 @@ bool TreeBuilder::parse(const char* data, std::size_t size) m_rootElement = makeUnique(); element = m_rootElement.get(); } else { - auto child = createElement(id); + auto child = Element::create(id); element = child.get(); current->addChild(std::move(child)); } @@ -1908,69 +1892,4 @@ bool TreeBuilder::parse(const char* data, std::size_t size) return true; } -Element* TreeBuilder::getElementById(const std::string& id) const -{ - auto it = m_idCache.find(id); - if(it == m_idCache.end()) - return nullptr; - return it->second; -} - -std::unique_ptr TreeBuilder::createElement(ElementID id) -{ - switch(id) { - case ElementID::Svg: - return makeUnique(); - case ElementID::Path: - return makeUnique(); - case ElementID::G: - return makeUnique(); - case ElementID::Rect: - return makeUnique(); - case ElementID::Circle: - return makeUnique(); - case ElementID::Ellipse: - return makeUnique(); - case ElementID::Line: - return makeUnique(); - case ElementID::Defs: - return makeUnique(); - case ElementID::Polygon: - return makeUnique(); - case ElementID::Polyline: - return makeUnique(); - case ElementID::Stop: - return makeUnique(); - case ElementID::LinearGradient: - return makeUnique(); - case ElementID::RadialGradient: - return makeUnique(); - case ElementID::Symbol: - return makeUnique(); - case ElementID::Use: - return makeUnique(); - case ElementID::Pattern: - return makeUnique(); - case ElementID::Mask: - return makeUnique(); - case ElementID::ClipPath: - return makeUnique(); - case ElementID::SolidColor: - return makeUnique(); - case ElementID::Marker: - return makeUnique(); - case ElementID::Style: - return makeUnique(); - default: - break; - } - - return nullptr; -} - -std::unique_ptr TreeBuilder::layout() const -{ - return m_rootElement->layoutTree(this); -} - } // namespace lunasvg diff --git a/source/parser.h b/source/parser.h index fbab16b..d3e1ab5 100644 --- a/source/parser.h +++ b/source/parser.h @@ -146,7 +146,6 @@ class RuleData { static bool matchAttributeSelector(const AttributeSelector& selector, const Element* element); static bool matchPseudoClassSelector(const PseudoClassSelector& selector, const Element* element); -private: Selector m_selector; DeclarationList m_declarations; uint32_t m_specificity; @@ -174,31 +173,10 @@ class StyleSheet { static bool parseSelector(const char*& ptr, const char* end, Selector& selector); static bool parseSimpleSelector(const char*& ptr, const char* end, SimpleSelector& simpleSelector); -private: std::multiset m_rules; uint32_t m_position{0}; }; -class LayoutSymbol; - -class TreeBuilder { -public: - TreeBuilder(); - ~TreeBuilder(); - - bool parse(const char* data, std::size_t size); - - SVGElement* rootElement() const { return m_rootElement.get(); } - Element* getElementById(const std::string& id) const; - std::unique_ptr layout() const; - - static std::unique_ptr createElement(ElementID id); - -private: - std::unique_ptr m_rootElement; - std::map m_idCache; -}; - } // namespace lunasvg #endif // PARSER_H diff --git a/source/svgelement.cpp b/source/svgelement.cpp index 74c6293..c072556 100644 --- a/source/svgelement.cpp +++ b/source/svgelement.cpp @@ -45,7 +45,7 @@ PreserveAspectRatio SVGElement::preserveAspectRatio() const return Parser::parsePreserveAspectRatio(value); } -std::unique_ptr SVGElement::layoutTree(const TreeBuilder* builder) const +std::unique_ptr SVGElement::layoutTree(const Document* document) const { if(isDisplayNone()) return nullptr; @@ -76,7 +76,7 @@ std::unique_ptr SVGElement::layoutTree(const TreeBuilder* builder) root->clip = isOverflowHidden() ? preserveAspectRatio.getClip(_w, _h, viewBox) : Rect::Invalid; root->opacity = opacity(); - LayoutContext context(builder, root.get()); + LayoutContext context(document, root.get()); root->masker = context.getMasker(mask()); root->clipper = context.getClipper(clip_path()); layoutChildren(&context, root.get()); diff --git a/source/svgelement.h b/source/svgelement.h index 83657e6..5569781 100644 --- a/source/svgelement.h +++ b/source/svgelement.h @@ -5,7 +5,7 @@ namespace lunasvg { -class TreeBuilder; +class Document; class LayoutSymbol; class SVGElement final : public GraphicsElement { @@ -19,7 +19,7 @@ class SVGElement final : public GraphicsElement { Rect viewBox() const; PreserveAspectRatio preserveAspectRatio() const; - std::unique_ptr layoutTree(const TreeBuilder* builder) const; + std::unique_ptr layoutTree(const Document* document) const; void layout(LayoutContext* context, LayoutContainer* current) const final; }; diff --git a/source/useelement.cpp b/source/useelement.cpp index 06c1aae..8298ad7 100644 --- a/source/useelement.cpp +++ b/source/useelement.cpp @@ -95,7 +95,7 @@ std::unique_ptr UseElement::cloneTargetElement(const Element* targetEle tagId = ElementID::Svg; } - auto newElement = TreeBuilder::createElement(tagId); + auto newElement = Element::create(tagId); newElement->properties = targetElement->properties; if(newElement->id == ElementID::Svg) { for(const auto& property : properties) { @@ -112,15 +112,16 @@ std::unique_ptr UseElement::cloneTargetElement(const Element* targetEle return newElement; } -void UseElement::build(const TreeBuilder* builder) +void UseElement::build(const Document* document) { - if(auto targetElement = builder->getElementById(href())) { - if(auto newElement = cloneTargetElement(targetElement)) { + auto targetElement = document->getElementById(href()); + if(!targetElement.isNull()) { + if(auto newElement = cloneTargetElement(targetElement.get())) { addChild(std::move(newElement)); } } - Element::build(builder); + Element::build(document); } } // namespace lunasvg diff --git a/source/useelement.h b/source/useelement.h index 95dff08..b7dd1f4 100644 --- a/source/useelement.h +++ b/source/useelement.h @@ -18,7 +18,7 @@ class UseElement final : public GraphicsElement { void layout(LayoutContext* context, LayoutContainer* current) const final; std::unique_ptr cloneTargetElement(const Element* targetElement) const; - void build(const TreeBuilder* builder) final; + void build(const Document* document) final; }; } // namespace lunasvg