#include "element.h" #include "parser.h" #include "svgelement.h" namespace lunasvg { void PropertyList::set(PropertyId id, const std::string& value, int specificity) { auto property = get(id); if(property == nullptr) { Property property{id, value, specificity}; m_properties.push_back(std::move(property)); return; } if(property->specificity > specificity) return; property->specificity = specificity; property->value = value; } Property* PropertyList::get(PropertyId id) const { auto data = m_properties.data(); auto end = data + m_properties.size(); while(data < end) { if(data->id == id) return const_cast(data); ++data; } return nullptr; } void PropertyList::add(const Property& property) { set(property.id, property.value, property.specificity); } void PropertyList::add(const PropertyList& properties) { auto it = properties.m_properties.begin(); auto end = properties.m_properties.end(); for(;it != end;++it) add(*it); } void Node::layout(LayoutContext*, LayoutContainer*) const { } std::unique_ptr TextNode::clone() const { auto node = std::make_unique(); node->text = text; return std::move(node); } Element::Element(ElementId id) : id(id) { } void Element::set(PropertyId id, const std::string& value, int specificity) { properties.set(id, value, specificity); } static const std::string EmptyString; const std::string& Element::get(PropertyId id) const { auto property = properties.get(id); if(property == nullptr) return EmptyString; return property->value; } static const std::string InheritString{"inherit"}; const std::string& Element::find(PropertyId id) const { auto element = this; do { auto& value = element->get(id); if(!value.empty() && value != InheritString) return value; element = element->parent; } while(element); return EmptyString; } bool Element::has(PropertyId id) const { return properties.get(id); } Element* Element::previousSibling() const { if(parent == nullptr) return nullptr; Element* element = nullptr; auto it = parent->children.begin(); auto end = parent->children.end(); for(;it != end;++it) { auto node = it->get(); if(node->isText()) continue; if(node == this) return element; element = static_cast(node); } return nullptr; } Element* Element::nextSibling() const { if(parent == nullptr) return nullptr; Element* element = nullptr; auto it = parent->children.rbegin(); auto end = parent->children.rend(); for(;it != end;++it) { auto node = it->get(); if(node->isText()) continue; if(node == this) return element; element = static_cast(node); } return nullptr; } Node* Element::addChild(std::unique_ptr child) { child->parent = this; children.push_back(std::move(child)); return &*children.back(); } void Element::layoutChildren(LayoutContext* context, LayoutContainer* current) const { for(auto& child : children) child->layout(context, current); } Rect Element::currentViewport() const { if(parent == nullptr) { auto element = static_cast(this); if(element->has(PropertyId::ViewBox)) return element->viewBox(); return Rect{0, 0, 300, 150}; } if(parent->id == ElementId::Svg) { auto element = static_cast(parent); if(element->has(PropertyId::ViewBox)) return element->viewBox(); LengthContext lengthContext(element); auto _x = lengthContext.valueForLength(element->x(), LengthMode::Width); auto _y = lengthContext.valueForLength(element->y(), LengthMode::Height); auto _w = lengthContext.valueForLength(element->width(), LengthMode::Width); auto _h = lengthContext.valueForLength(element->height(), LengthMode::Height); return Rect{_x, _y, _w, _h}; } return parent->currentViewport(); } } // namespace lunasvg