summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2018-12-04 12:40:43 +0000
committerTavmjong Bah <tavmjong@free.fr>2018-12-04 12:40:43 +0000
commitb0be54c82565f7e476187365ccb6c65d0729810d (patch)
treec0b8133fa3a57934f4b57a5e5aaa5da0697864b0 /src
parentMinor comment/alignment changes. (diff)
downloadinkscape-b0be54c82565f7e476187365ccb6c65d0729810d.tar.gz
inkscape-b0be54c82565f7e476187365ccb6c65d0729810d.zip
Add a few useful lookup functions.
Diffstat (limited to 'src')
-rw-r--r--src/xml/repr-css.cpp29
-rw-r--r--src/xml/repr-io.cpp6
-rw-r--r--src/xml/repr-util.cpp60
-rw-r--r--src/xml/repr.h20
4 files changed, 104 insertions, 11 deletions
diff --git a/src/xml/repr-css.cpp b/src/xml/repr-css.cpp
index 5db698406..d035b9a4b 100644
--- a/src/xml/repr-css.cpp
+++ b/src/xml/repr-css.cpp
@@ -61,7 +61,7 @@ protected:
SimpleNode *_duplicate(Document* doc) const override { return new SPCSSAttrImpl(*this, doc); }
};
-static void sp_repr_css_add_components(SPCSSAttr *css, Node *repr, gchar const *attr);
+static void sp_repr_css_add_components(SPCSSAttr *css, Node const *repr, gchar const *attr);
/**
* Creates an empty SPCSSAttr (a class for manipulating CSS style properties).
@@ -90,7 +90,7 @@ void sp_repr_css_attr_unref(SPCSSAttr *css)
* string is parsed by libcroco which returns a CRDeclaration list (a typical C linked list) of
* properties and values. This list is then used to fill the attributes of the new SPCSSAttr.
*/
-SPCSSAttr *sp_repr_css_attr(Node *repr, gchar const *attr)
+SPCSSAttr *sp_repr_css_attr(Node const *repr, gchar const *attr)
{
g_assert(repr != nullptr);
g_assert(attr != nullptr);
@@ -174,9 +174,9 @@ SPCSSAttr *sp_repr_css_attr_parse_color_to_fill(const Glib::ustring &text)
/**
* Adds an attribute to an existing SPCSAttr with the cascaded value including all parents.
*/
-static void sp_repr_css_attr_inherited_recursive(SPCSSAttr *css, Node *repr, gchar const *attr)
+static void sp_repr_css_attr_inherited_recursive(SPCSSAttr *css, Node const *repr, gchar const *attr)
{
- Node *parent = repr->parent();
+ const Node *parent = repr->parent();
// read the ancestors from root down, using head recursion, so that children override parents
if (parent) {
@@ -188,7 +188,7 @@ static void sp_repr_css_attr_inherited_recursive(SPCSSAttr *css, Node *repr, gch
/**
* Creates a new SPCSSAttr with one attribute whose value is determined by cascading.
*/
-SPCSSAttr *sp_repr_css_attr_inherited(Node *repr, gchar const *attr)
+SPCSSAttr *sp_repr_css_attr_inherited(Node const *repr, gchar const *attr)
{
g_assert(repr != nullptr);
g_assert(attr != nullptr);
@@ -205,7 +205,7 @@ SPCSSAttr *sp_repr_css_attr_inherited(Node *repr, gchar const *attr)
* (nominally a style attribute).
*
*/
-static void sp_repr_css_add_components(SPCSSAttr *css, Node *repr, gchar const *attr)
+static void sp_repr_css_add_components(SPCSSAttr *css, Node const *repr, gchar const *attr)
{
g_assert(css != nullptr);
g_assert(repr != nullptr);
@@ -231,6 +231,23 @@ char const *sp_repr_css_property(SPCSSAttr *css, gchar const *name, gchar const
}
/**
+ * Returns a character string of the value of a given style property or a default value if the
+ * attribute is not found.
+ */
+Glib::ustring sp_repr_css_property(SPCSSAttr *css, Glib::ustring const &name, Glib::ustring const &defval)
+{
+ g_assert(css != nullptr);
+
+ Glib::ustring retval = defval;
+ char const *attr = ((Node *)css)->attribute(name.c_str());
+ if (attr) {
+ retval = attr;
+ }
+
+ return retval;
+}
+
+/**
* Returns true if a style property is present and its value is unset.
*/
bool sp_repr_css_property_is_unset(SPCSSAttr *css, gchar const *name)
diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp
index b1bf26118..c0ebfa12c 100644
--- a/src/xml/repr-io.cpp
+++ b/src/xml/repr-io.cpp
@@ -981,10 +981,9 @@ void sp_repr_write_stream_element( Node * repr, Writer & out,
}
out.printf( "<%s", element_name );
- // if this is a <text> element, suppress formatting whitespace
+ // If this is a <text> element, suppress formatting whitespace
// for its content and children:
- gchar const *xml_space_attr = repr->attribute("xml:space");
- if (xml_space_attr != nullptr && !strcmp(xml_space_attr, "preserve")) {
+ if (strcmp(repr->name(),"svg:text") == 0) {
add_whitespace = false;
}
@@ -1014,6 +1013,7 @@ void sp_repr_write_stream_element( Node * repr, Writer & out,
break;
}
}
+
if (repr->firstChild()) {
out.writeChar('>');
if (loose && add_whitespace) {
diff --git a/src/xml/repr-util.cpp b/src/xml/repr-util.cpp
index a5dea02a2..a02997105 100644
--- a/src/xml/repr-util.cpp
+++ b/src/xml/repr-util.cpp
@@ -21,6 +21,8 @@
#include <glib.h>
+#include <glibmm.h>
+
#include <2geom/point.h>
#include "svg/stringstream.h"
#include "svg/css-ostringstream.h"
@@ -334,6 +336,36 @@ Inkscape::XML::Node *sp_repr_lookup_child(Inkscape::XML::Node *repr,
return nullptr;
}
+/**
+ * Recursive version of sp_repr_lookup_child().
+ */
+Inkscape::XML::Node const *sp_repr_lookup_descendant(Inkscape::XML::Node const *repr,
+ gchar const *key,
+ gchar const *value)
+{
+ Inkscape::XML::Node const *found = nullptr;
+ g_return_val_if_fail(repr != nullptr, NULL);
+ gchar const *repr_value = repr->attribute(key);
+ if ( (repr_value == value) ||
+ (repr_value && value && strcmp(repr_value, value) == 0) ) {
+ found = repr;
+ } else {
+ for (Inkscape::XML::Node const *child = repr->firstChild() ; child && !found; child = child->next() ) {
+ found = sp_repr_lookup_descendant( child, key, value );
+ }
+ }
+ return found;
+}
+
+
+Inkscape::XML::Node *sp_repr_lookup_descendant(Inkscape::XML::Node *repr,
+ gchar const *key,
+ gchar const *value)
+{
+ Inkscape::XML::Node const *found = sp_repr_lookup_descendant( const_cast<Inkscape::XML::Node const *>(repr), key, value );
+ return const_cast<Inkscape::XML::Node *>(found);
+}
+
Inkscape::XML::Node const *sp_repr_lookup_name( Inkscape::XML::Node const *repr, gchar const *name, gint maxdepth )
{
Inkscape::XML::Node const *found = nullptr;
@@ -391,6 +423,34 @@ std::vector<Inkscape::XML::Node const *> sp_repr_lookup_name_many( Inkscape::XML
return nodes;
}
+std::vector<Inkscape::XML::Node *>
+sp_repr_lookup_property_many( Inkscape::XML::Node *repr, Glib::ustring const& property,
+ Glib::ustring const &value, int maxdepth )
+{
+ std::vector<Inkscape::XML::Node *> nodes;
+ std::vector<Inkscape::XML::Node *> found;
+ g_return_val_if_fail(repr != nullptr, nodes);
+
+ SPCSSAttr* css = sp_repr_css_attr (repr, "style");
+ if (value == sp_repr_css_property (css, property, "")) {
+ nodes.push_back(repr);
+ }
+
+ if ( maxdepth != 0 ) {
+ // maxdepth == -1 means unlimited
+ if ( maxdepth == -1 ) {
+ maxdepth = 0;
+ }
+
+ for (Inkscape::XML::Node *child = repr->firstChild() ; child; child = child->next() ) {
+ found = sp_repr_lookup_property_many( child, property, value, maxdepth - 1);
+ nodes.insert(nodes.end(), found.begin(), found.end());
+ }
+ }
+
+ return nodes;
+}
+
/**
* Determine if the node is a 'title', 'desc' or 'metadata' element.
*/
diff --git a/src/xml/repr.h b/src/xml/repr.h
index 1c3bf1193..e9f01c5d4 100644
--- a/src/xml/repr.h
+++ b/src/xml/repr.h
@@ -78,12 +78,13 @@ bool sp_repr_save_rebased_file(Inkscape::XML::Document *doc, char const *filenam
SPCSSAttr *sp_repr_css_attr_new();
void sp_repr_css_attr_unref(SPCSSAttr *css);
-SPCSSAttr *sp_repr_css_attr(Inkscape::XML::Node *repr, char const *attr);
+SPCSSAttr *sp_repr_css_attr(Inkscape::XML::Node const *repr, char const *attr);
SPCSSAttr *sp_repr_css_attr_parse_color_to_fill(const Glib::ustring &text);
-SPCSSAttr *sp_repr_css_attr_inherited(Inkscape::XML::Node *repr, char const *attr);
+SPCSSAttr *sp_repr_css_attr_inherited(Inkscape::XML::Node const *repr, char const *attr);
SPCSSAttr *sp_repr_css_attr_unset_all(SPCSSAttr *css);
char const *sp_repr_css_property(SPCSSAttr *css, char const *name, char const *defval);
+Glib::ustring sp_repr_css_property(SPCSSAttr *css, Glib::ustring const &name, Glib::ustring const &defval);
void sp_repr_css_set_property(SPCSSAttr *css, char const *name, char const *value);
void sp_repr_css_unset_property(SPCSSAttr *css, char const *name);
bool sp_repr_css_property_is_unset(SPCSSAttr *css, char const *name);
@@ -151,10 +152,25 @@ std::vector<Inkscape::XML::Node const *> sp_repr_lookup_name_many(Inkscape::XML:
char const *name,
int maxdepth = -1);
+// Find an element node using an unique attribute.
Inkscape::XML::Node *sp_repr_lookup_child(Inkscape::XML::Node *repr,
char const *key,
char const *value);
+// Find an element node using an unique attribute recursively.
+Inkscape::XML::Node *sp_repr_lookup_descendant(Inkscape::XML::Node *repr,
+ char const *key,
+ char const *value);
+
+Inkscape::XML::Node const *sp_repr_lookup_descendant(Inkscape::XML::Node const *repr,
+ char const *key,
+ char const *value);
+
+// Find element nodes using a property value.
+std::vector<Inkscape::XML::Node *> sp_repr_lookup_property_many(Inkscape::XML::Node *repr,
+ Glib::ustring const &property,
+ Glib::ustring const &value,
+ int maxdepth = -1);
inline Inkscape::XML::Node *sp_repr_document_first_child(Inkscape::XML::Document const *doc) {
return const_cast<Inkscape::XML::Node *>(doc->firstChild());