cppfw / svgdom Goto Github PK
View Code? Open in Web Editor NEW:house: SVG document object model in C++
License: MIT License
:house: SVG document object model in C++
License: MIT License
Missing elements:
switch,
style,
text,
tspan,
tref,
textPath,
altGlyph,
altGlyphDef,
altGlyphItem,
glyphRef,
marker,
color-profile,
clipPath,
feDistantLight,
fePointLight,
feSpotLight,
feComponentTransfer,
feConvolveMatrix,
feDiffuseLighting,
feDisplacementMap,
feFlood,
feImage,
feMerge,
feMorphology,
feOffset,
feSpecularLighting,
feTile,
feTurbulence,
cursor,
a,
view,
script,
animate,
set,
animateMotion,
animateColor,
animateTransform,
font,
glyph,
missing-glyph,
hkern,
vkern,
font-face,
font-face-src,
font-face-uri,
font-face-format,
font-face-name,
metadata,
foreignObject
Add solidColor
element.
Implement parsing from XML and writing to XML.
Add test.
This element was introduced in SVG spec version 2. While this library aims to support SVG 1 for now, this element might be useful.
https://www.w3.org/TR/2013/WD-SVG2-20130409/pservers.html#SolidColors
Potential use case is to be able to change colors in SVG dynamically.
Just a quick suggestion: I have been using Finder
and StyleStack
from svgren
quite often and I think that these two classes belong to svgdom
and not svgren
, since their functionality is useful outside of the scope of rendering.
@Papirosnik FYI
Hi Ivan!
I've attached zip containing an original svg and result of dom->toString() saved to svg again and rendered by google chrome.
There are some ugly black lines on the car's hood and doors .
Could you please investigate this problem and give us small fix for this nice car?
Thanks a lot.
car.zip
I'm working on a class that takes an Element as input and is doing constant modifications to such Element. I would like to make a deep copy of this Element in order to keep the original intact though, but the nature of unique_ptrs doesn't allow it though. Is there any way of doing a deep copy of an Element? Maybe a cloning option?
I'm trying to use Finder
to get a reference to an Element, and then accept a Visitor from this element, but I'm getting the following error:
candidate function not viable: 'this' argument has type 'const svgdom::Element', but method is not marked const
The problem is that Finder
returns ElementInfo
with const svgdom::Element& e
instead of svgdom::Element& e
, so the Element can't be modified.
Here's the code that is causing the error:
auto ref = finder.findById(e.getLocalIdFromIri());
if (!ref) {
return;
}
class MyVisitor : public Visitor {
public:
virtual void defaultVisit(Element& e) override {
// Modify Element here
}
} myVisitor;
ref->e.accept(myVisitor);
Using Finder
to modify Elements seems like a useful pattern to me, otherwise I would have to write my own implementation of Finder with non-constant Element, what do you think?
like libexpat.
It should increase performance.
Hi
I am on vacation so working with my games again ;)
After updating svgren, svgdom and all of the dependencies from NuGet, it seems svgdom can't load any svg file from an istream. This code always produces exception mikroxml::malformed_xml with message "Unexpected '/' character in attribute list encountered. line: 1"
std::ifstream ist; ist.open(filename); auto dom = svgdom::load(ist);
Not a big issue for me right now as it seems to work if I use papki::fs_file instead, but thought I would report it anyway. :)
After Update to latest version of svgren I permanently get an assertion in svgdom while loading simple images:
menue-new.zip
Release version runs fine and alle the images still look good ..... so I don't see a reason for an assertion.
Visitors are used to traverse the dom, since derived Element classes are not homogeneous. It would be convenient, however, to have a custom iterator to access all Elements and their members.
It would be great to access the IDs of all the elements with a simple loop, for example, instead of having to create a new Visitor:
for (auto element : dom)
cout<<element.id<<endl;
This would be helpful to do simple operations like counting the number of elements, or searching for an element with certain ID.
Edit: Looking at the problem, it seems like the Container's children
member would have to be moved to Element in order for this to work.
Add a new element whose sole purpose is to insert custom strings when generating XMLs. This new element could be called StringElement
.
Is there a way to include namespaces when writing the root <svg>
? Here's the code and the generated string to illustrate what I'm talking about:
auto dom = utki::makeUnique<svgdom::SvgElement>();
svgdom::PathElement path;
svgdom::PathElement::Step step;
step.type = svgdom::PathElement::Step::Type_e::MOVE_ABS;
step.x = 0;
step.y = 0;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS
step.x = 0;
step.y = 300;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS;
step.x = 300;
step.y = 300;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS;
step.x = 300;
step.y = 0;
path.path.push_back(step);
dom->children.push_back(utki::makeUnique<svgdom::PathElement>(path));
cout<<dom->toString()<<std::endl;
And here's the string result:
<svg>
<path d="M0,0L0,300 300,300 300,0"/>
</svg>
Notice that the xmlns
namespace is missing, and therefore the result can't be properly rendered.
I am using svgdom
to generate and update a DOM dynamically from code (instead of loading the svg file) and then generate the corresponding XML string. I have some questions and suggestions:
Adding namespaces to the root <svg>
element
Is there a way to include namespaces when writing the root <svg>
? Here's the code and the generated string to illustrate what I'm talking about:
auto dom = utki::makeUnique<svgdom::SvgElement>();
svgdom::PathElement path;
svgdom::PathElement::Step step;
step.type = svgdom::PathElement::Step::Type_e::MOVE_ABS;
step.x = 0;
step.y = 0;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS
step.x = 0;
step.y = 300;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS;
step.x = 300;
step.y = 300;
path.path.push_back(step);
step.type = svgdom::PathElement::Step::Type_e::LINE_ABS;
step.x = 300;
step.y = 0;
path.path.push_back(step);
dom->children.push_back(utki::makeUnique<svgdom::PathElement>(path));
cout<<dom->toString()<<std::endl;
And here's the string result:
<svg>
<path d="M0,0L0,300 300,300 300,0"/>
</svg>
Notice that the xmlns
namespace is missing, and therefore the result can't be properly rendered.
Streams for custom strings (to write unsupported elements)
Let's say that I am generating an XML string, and I want to write an element that is unsupported by svgdom (eg: <filter>
or <pattern>
). Would it be possible to write a custom string in order to add any element that might be unsupported or maybe even to just add some comments?
I am actually planning to add a new element called StringElement
whose sole purpose is add any extra text to the XML string. What do you think?
Unique pointers
Using unique_ptr
and utki::Unique
makes the construction of DOMs a bit convoluted, and it can be confusing for users that don't understand the concept of unique pointers. It would be much easier to write something dom.push_back(path)
instead of dom->children.push_back(utki::makeUnique<svgdom::PathElement>(path))
. Is it really necessary to force the unique pointers? Why are unique pointers needed?
Constructors and structs
I am considering adding constructors to some elements to allow the initialization of some attributes. It would be great to initialize the vector of steps right on the constructor for the PathElement
for example. What do you think?
And finally, just out of curiosity: why do you use structs for the elements instead of classes?
@igagis you mentioned that writing SVGs to XML is not critical, but I believe that it's a really useful feature and it's almost ready ;). Supporting symmetric reading/writing operations is what I like about svgdom
since I can modify the DOM dynamically and generate the XML strings on the fly. I can help, but first I am trying to understand some of your architecture decisions.
What do you think about adding cmake support?
We're really interested in incorporating a svg dom type library into our library, but we use cmake, and support Mac, Linux and Windows. So, best way is if svgdom were all packaged into a single git repo, and we could just add it as a git submodule.
I'd be willing to write the CMake build system.
Please add support for the latest msvs v143 build tools.
callgrind shows that a lot of dynamic_casts
are used inside of the istream
, perhaps it is istringstream
investigate if it is possible to avoid using it.
Using unique_ptr
and utki::Unique
makes the construction of DOMs a bit convoluted, and it can be confusing for users that don't understand the concept of unique pointers. It would be much easier to write something dom.push_back(path)
instead of dom->children.push_back(utki::makeUnique<svgdom::PathElement>(path))
. Maybe it would be a good idea to add convenience methods to create DOMs and hide the management of unique pointers.
It would be nice to have elements in parsed DOM even if they are not supported by svgren, so their presence can at least be checked after parsing.
Hi @igagis, here is a suggestion for 2 new features that would be somewhat easy to implement, but would go a long way for your developers:
Implement class attribute: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/class
Implement a method to return the Element type (eg: Element::Type getType()
). Eg, for the PathElement
this method would return Element::Type::Path
.
This information would be helpful if your developers need to access an Element by class
or type
(or already supported id
), through Javascript or through a CSS selector.
I don't know for sure, but depending on my schedule, I might be able to help out ;).
I'm working on a function that groups together svg elements that area selected in an svg editor. To do this, I created a class called SelectionVisitor
that contains a vector of selected elements called selectedElements
.
I'm having a lot of problems with unique pointers though, since I have to store a reference to the selected Elements and then I have to move these Elements to a new group and delete them from the current Container. Here's the code to group the selected Elements in a new group (it's failing to compile):
int DomOperations::groupActiveSelection(std::string id) {
auto ge = utki::makeUnique<GElement>();
ge->id = id;
for (auto e : selectionVisitor.selectedElements) {
ge->children.push_back(std::move(e));
root.children.erase(e);
}
if (!ge->children.size() == 0)
root.children.push_back(std::move(ge));
selectionVisitor.selectedElements.clear();
return 0;
}
And here's the code for the SelectionVisitor
class:
class SelectionVisitor : virtual public svgdom::Visitor {
public:
std::vector<svgdom::Element*> selectedElements;
polygon_2f selectionPolygon;
void setSelectionPolygon(const polygon_2f selectionPolygon);
void visit(const svgdom::PathElement& e)override;
void visit(const svgdom::RectElement& e)override;
void visit(const svgdom::CircleElement& e)override;
void visit(const svgdom::EllipseElement& e)override;
void visit(const svgdom::LineElement& e)override;
void visit(const svgdom::PolylineElement& e)override;
void visit(const svgdom::PolygonElement& e)override;
void visit(const svgdom::GElement& e)override;
void visit(const svgdom::SvgElement& e)override;
void visit(const svgdom::SymbolElement& e)override;
void visit(const svgdom::UseElement& e)override;
void visit(const svgdom::DefsElement& e)override;
void visit(const svgdom::Gradient::StopElement& e)override;
void visit(const svgdom::LinearGradientElement& e)override;
void visit(const svgdom::RadialGradientElement& e)override;
void visit(const svgdom::FilterElement& e)override;
void visit(const svgdom::FeGaussianBlurElement& e)override;
};
Do you have any suggestion on how to do this? I understand that a unique_ptr can't be copied, only moved, but this makes the problem of having references to selected Elements, and rearranging these elements into groups very difficult.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.