[lasem/properties] [SVG] Property list WIP.
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [lasem/properties] [SVG] Property list WIP.
- Date: Fri, 7 Aug 2009 09:29:25 +0000 (UTC)
commit b83bf9fdba6550feeb43c3d79361aa9e9d32f543
Author: Emmanuel Pacaud <emmanuel pacaud lapp in2p3 fr>
Date: Thu Aug 6 22:07:29 2009 +0200
[SVG] Property list WIP.
.gitignore | 1 +
src/lasemrender.c | 150 ++++++++-------------
src/lasemtest.c | 7 +-
src/lsmdomdocument.c | 75 +++++++++++
src/lsmdomdocument.h | 12 ++-
src/lsmdomnode.h | 24 ++--
src/lsmdomparser.c | 134 ++++++++++++++++---
src/lsmdomparser.h | 9 +-
src/lsmmathmldocument.c | 40 +++---
src/lsmmathmldocument.h | 2 +-
src/lsmstr.c | 59 ++++++++
src/lsmstr.h | 3 +
src/lsmsvgcircleelement.c | 7 +-
src/lsmsvgclippathelement.c | 22 +++-
src/lsmsvgclippathelement.h | 2 +
src/lsmsvgelement.c | 15 +--
src/lsmsvgelement.h | 3 +-
src/lsmsvgellipseelement.c | 8 +-
src/lsmsvgimageelement.c | 63 ++++++++-
src/lsmsvgmaskelement.c | 43 +++++--
src/lsmsvgmaskelement.h | 2 +
src/lsmsvgpatternelement.c | 10 +-
src/lsmsvgradialgradientelement.c | 12 ++-
src/lsmsvgrectelement.c | 19 ++--
src/lsmsvgsvgelement.c | 33 ++++--
src/lsmsvgtraits.c | 64 ++++++----
src/lsmsvgview.c | 200 ++++++++++++++++------------
test/.gitignore | 1 -
test/svg/svg1.1/color/images/colorprof.png | Bin 0 -> 705 bytes
29 files changed, 697 insertions(+), 323 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index ba0eeca..1832f85 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,4 +24,5 @@ tags
*.swp
lasem.svg
lasem.pc
+lasemtest.xml
manugen
diff --git a/src/lasemrender.c b/src/lasemrender.c
index 32c89ab..b93cc01 100644
--- a/src/lasemrender.c
+++ b/src/lasemrender.c
@@ -85,16 +85,11 @@ int main(int argc, char **argv)
cairo_surface_t *surface;
GError *error = NULL;
GOptionContext *context;
- GFile *file;
FileFormat format;
char *output_filename;
char *input_filename;
- char *mime;
- char *buffer = NULL;
- size_t size;
double height_pt, width_pt;
unsigned int height, width;
- gboolean success;
g_type_init ();
@@ -164,102 +159,69 @@ int main(int argc, char **argv)
g_free (directory);
}
- mime = g_content_type_guess (input_filename, NULL, 0, NULL);
- file = g_file_new_for_path (input_filename);
+ document = lsm_dom_document_new_from_path (input_filename, NULL);
+ if (document == NULL)
+ document = lsm_dom_document_new_from_url (input_filename, NULL);
- success = g_file_load_contents (file, NULL, &buffer, &size, NULL, NULL);
- if (!success) {
- g_object_unref (file);
- file = g_file_new_for_uri (input_filename);
- success = g_file_load_contents (file, NULL, &buffer, &size, NULL, NULL);
- }
+ if (document != NULL) {
+ lsm_dom_document_set_resolution (document, option_ppi);
+
+ view = lsm_dom_document_create_view (document);
+
+ lsm_dom_view_set_debug (view, option_debug);
- if (success) {
- char *mathml;
+ width_pt = 2.0;
+ height_pt = 2.0;
- if (strcmp (mime, "text/mathml") == 0 ||
- strcmp (mime, "image/svg+xml") == 0)
- mathml = buffer;
- else {
- mathml = itex2MML_parse (buffer, size);
- g_free (buffer);
- buffer = NULL;
+ lsm_dom_view_get_size (view, &width_pt, &height_pt);
+ lsm_dom_view_get_size_pixels (view, &width, &height);
+
+ switch (format) {
+ case FORMAT_PDF:
+ surface = cairo_pdf_surface_create (output_filename,
+ width_pt, height_pt);
+ break;
+ case FORMAT_PS:
+ surface = cairo_ps_surface_create (output_filename,
+ width_pt, height_pt);
+ break;
+ case FORMAT_PNG:
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ width,
+ height);
+ break;
+ case FORMAT_SVG:
+ default:
+ surface = cairo_svg_surface_create (output_filename,
+ width_pt, height_pt);
+ break;
}
- if (mathml != NULL) {
- document = lsm_dom_document_new_from_memory (mathml);
- lsm_dom_document_set_resolution (document, option_ppi);
-
- if (document != NULL) {
- view = lsm_dom_document_create_view (document);
-
- lsm_dom_view_set_debug (view, option_debug);
-
- width_pt = 2.0;
- height_pt = 2.0;
-
- lsm_dom_view_get_size (view, &width_pt, &height_pt);
- lsm_dom_view_get_size_pixels (view, &width, &height);
-
- switch (format) {
- case FORMAT_PDF:
- surface = cairo_pdf_surface_create (output_filename,
- width_pt, height_pt);
- break;
- case FORMAT_PS:
- surface = cairo_ps_surface_create (output_filename,
- width_pt, height_pt);
- break;
- case FORMAT_PNG:
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- width,
- height);
- break;
- case FORMAT_SVG:
- default:
- surface = cairo_svg_surface_create (output_filename,
- width_pt, height_pt);
- break;
- }
-
- cairo = cairo_create (surface);
- cairo_surface_destroy (surface);
-
- lsm_dom_view_set_cairo (view, cairo);
-
- lsm_dom_view_render (view, 0, 0);
-
- switch (format) {
- case FORMAT_PNG:
- cairo_surface_write_to_png (cairo_get_target (cairo),
- output_filename);
- break;
- default:
- break;
- }
-
- cairo_destroy (cairo);
-
- g_object_unref (view);
-
- g_object_unref (document);
-
- lsm_debug ("width = %g pt, height = %g pt", width_pt, height_pt);
- } else
- g_warning ("Can't load %s", input_filename);
- } else
- g_warning ("Invalid document");
-
- if (mathml == buffer)
- g_free (mathml);
- else
- itex2MML_free_string (mathml);
-
- g_object_unref (file);
+ cairo = cairo_create (surface);
+ cairo_surface_destroy (surface);
+
+ lsm_dom_view_set_cairo (view, cairo);
+
+ lsm_dom_view_render (view, 0, 0);
+
+ switch (format) {
+ case FORMAT_PNG:
+ cairo_surface_write_to_png (cairo_get_target (cairo),
+ output_filename);
+ break;
+ default:
+ break;
+ }
+
+ cairo_destroy (cairo);
+
+ g_object_unref (view);
+
+ g_object_unref (document);
+
+ lsm_debug ("width = %g pt, height = %g pt", width_pt, height_pt);
} else
g_warning ("Can't load %s", input_filename);
- g_free (mime);
-
return (0);
}
diff --git a/src/lasemtest.c b/src/lasemtest.c
index 4a3a16e..bf385f6 100644
--- a/src/lasemtest.c
+++ b/src/lasemtest.c
@@ -115,10 +115,13 @@ lasem_test_render (char const *filename)
if (is_xml)
xml = buffer;
- else
+ else {
xml = itex2MML_parse (buffer, size);
+ size = 0;
+ }
- document = lsm_dom_document_new_from_memory (xml);
+ document = lsm_dom_document_new_from_memory (xml, size, NULL);
+ lsm_dom_document_set_path (document, filename);
view = lsm_dom_document_create_view (document);
diff --git a/src/lsmdomdocument.c b/src/lsmdomdocument.c
index 7d41bb8..c8062f1 100644
--- a/src/lsmdomdocument.c
+++ b/src/lsmdomdocument.c
@@ -21,8 +21,11 @@
#include <lsmdomdocument.h>
#include <lsmdomelement.h>
+#include <lsmstr.h>
#include <lsmdebug.h>
#include <lsmdomtext.h>
+#include <gio/gio.h>
+#include <string.h>
static GObjectClass *parent_class;
@@ -187,6 +190,76 @@ lsm_dom_document_register_element (LsmDomDocument *self, LsmDomElement *element,
}
}
+const char *
+lsm_dom_document_get_url (LsmDomDocument *self)
+{
+ g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (self), NULL);
+
+ return self->url;
+}
+
+void
+lsm_dom_document_set_path (LsmDomDocument *self, const char *path)
+{
+ g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+
+ g_free (self->url);
+
+ if (path == NULL) {
+ self->url = NULL;
+ return;
+ }
+
+ self->url = lsm_str_to_uri (path);
+}
+
+void
+lsm_dom_document_set_url (LsmDomDocument *self, const char *url)
+{
+ g_return_if_fail (LSM_IS_DOM_DOCUMENT (self));
+ g_return_if_fail (url == NULL || lsm_str_is_uri (url));
+
+ g_free (self->url);
+ self->url = g_strdup (url);
+}
+
+void *
+lsm_dom_document_get_href_data (LsmDomDocument *self, const char *href, gsize *size)
+{
+ GFile *file;
+ char *data = NULL;
+
+ g_return_val_if_fail (LSM_IS_DOM_DOCUMENT (self), NULL);
+ g_return_val_if_fail (href != NULL, NULL);
+
+ if (strncmp (href, "data:", 5) == 0) {
+ while (*href != '\0' && *href != ',')
+ href++;
+ return g_base64_decode (href, size);
+ }
+
+ file = g_file_new_for_uri (href);
+
+ if (!g_file_load_contents (file, NULL, &data, size, NULL, NULL) && self->url != NULL) {
+ GFile *document_file;
+ GFile *parent_file;
+
+ g_object_unref (file);
+
+ document_file = g_file_new_for_uri (self->url);
+ parent_file = g_file_get_parent (document_file);
+ file = g_file_resolve_relative_path (parent_file, href);
+ g_object_unref (document_file);
+ g_object_unref (parent_file);
+
+ g_file_load_contents (file, NULL, &data, size, NULL, NULL);
+ }
+
+ g_object_unref (file);
+
+ return data;
+}
+
static void
lsm_dom_document_init (LsmDomDocument *document)
{
@@ -208,6 +281,8 @@ lsm_dom_document_finalize (GObject *object)
g_hash_table_unref (document->elements);
g_hash_table_unref (document->ids);
+ g_free (document->url);
+
parent_class->finalize (object);
}
diff --git a/src/lsmdomdocument.h b/src/lsmdomdocument.h
index 3321d36..78697ec 100644
--- a/src/lsmdomdocument.h
+++ b/src/lsmdomdocument.h
@@ -45,8 +45,10 @@ typedef struct _LsmDomDocumentClass LsmDomDocumentClass;
struct _LsmDomDocument {
LsmDomNode node;
- GHashTable * ids;
- GHashTable * elements;
+ GHashTable * ids;
+ GHashTable * elements;
+
+ char * url;
/* Not really a document property, but that simplifies things greatly */
double resolution_ppi;
@@ -82,6 +84,12 @@ void lsm_dom_document_set_viewport_px (LsmDomDocument *self, const LsmBox *vi
LsmBox lsm_dom_document_get_viewport (LsmDomDocument *self);
LsmBox lsm_dom_document_get_viewport_px (LsmDomDocument *self);
+const char * lsm_dom_document_get_url (LsmDomDocument *self);
+void lsm_dom_document_set_url (LsmDomDocument *self, const char *url);
+void lsm_dom_document_set_path (LsmDomDocument *self, const char *path);
+
+void * lsm_dom_document_get_href_data (LsmDomDocument *self, const char *href, gsize *size);
+
G_END_DECLS
#endif
diff --git a/src/lsmdomnode.h b/src/lsmdomnode.h
index 86cae17..8305525 100644
--- a/src/lsmdomnode.h
+++ b/src/lsmdomnode.h
@@ -89,30 +89,30 @@ struct _LsmDomNodeClass {
GType lsm_dom_node_get_type (void);
-const char* lsm_dom_node_get_node_name (LsmDomNode* self);
-const char* lsm_dom_node_get_node_value (LsmDomNode* self);
-void lsm_dom_node_set_node_value (LsmDomNode* self, const char* new_value);
-LsmDomNodeType lsm_dom_node_get_node_type (LsmDomNode* self);
-LsmDomNode* lsm_dom_node_get_parent_node (LsmDomNode* self);
+const char* lsm_dom_node_get_node_name (LsmDomNode* self);
+const char* lsm_dom_node_get_node_value (LsmDomNode* self);
+void lsm_dom_node_set_node_value (LsmDomNode* self, const char* new_value);
+LsmDomNodeType lsm_dom_node_get_node_type (LsmDomNode* self);
+LsmDomNode* lsm_dom_node_get_parent_node (LsmDomNode* self);
#if 0
LsmDomNodeList* lsm_dom_node_get_child_nodes (LsmDomNode* self);
#endif
-LsmDomNode* lsm_dom_node_get_first_child (LsmDomNode* self);
-LsmDomNode* lsm_dom_node_get_last_child (LsmDomNode* self);
+LsmDomNode* lsm_dom_node_get_first_child (LsmDomNode* self);
+LsmDomNode* lsm_dom_node_get_last_child (LsmDomNode* self);
LsmDomNode* lsm_dom_node_get_previous_sibling (LsmDomNode* self);
-LsmDomNode* lsm_dom_node_get_next_sibling (LsmDomNode* self);
+LsmDomNode* lsm_dom_node_get_next_sibling (LsmDomNode* self);
#if 0
LsmDomNamedNodeMap* lsm_dom_node_get_attributes (LsmDomNode* self);
#endif
LsmDomNode* lsm_dom_node_insert_before (LsmDomNode* self, LsmDomNode* new_child, LsmDomNode* ref_child);
-LsmDomNode* lsm_dom_node_replace_child (LsmDomNode* self, LsmDomNode* new_child, LsmDomNode* old_child);
+LsmDomNode* lsm_dom_node_replace_child (LsmDomNode* self, LsmDomNode* new_child, LsmDomNode* old_child);
LsmDomNode* lsm_dom_node_append_child (LsmDomNode* self, LsmDomNode* new_child);
LsmDomNode* lsm_dom_node_remove_child (LsmDomNode* self, LsmDomNode* old_child);
-gboolean lsm_dom_node_has_child_nodes (LsmDomNode* self);
+gboolean lsm_dom_node_has_child_nodes (LsmDomNode* self);
-void lsm_dom_node_changed (LsmDomNode *self);
+void lsm_dom_node_changed (LsmDomNode *self);
-LsmDomDocument* lsm_dom_node_get_owner_document (LsmDomNode* self);
+LsmDomDocument* lsm_dom_node_get_owner_document (LsmDomNode* self);
void lsm_dom_node_dump (LsmDomNode *self);
diff --git a/src/lsmdomparser.c b/src/lsmdomparser.c
index 8d3bbef..66024f4 100644
--- a/src/lsmdomparser.c
+++ b/src/lsmdomparser.c
@@ -24,8 +24,11 @@
#include <lsmmathmlpresentationtoken.h>
#include <lsmmathmlentitydictionary.h>
#include <lsmsvgtextelement.h>
+#include <lsmstr.h>
#include <libxml/parser.h>
+#include <gio/gio.h>
#include <string.h>
+#include <../itex2mml/itex2MML.h>
typedef enum {
STATE
@@ -256,37 +259,134 @@ static xmlSAXHandler sax_handler = {
.entityDecl = lsm_dom_parser_declare_entity
};
-LsmDomDocument *
-lsm_dom_document_new_from_file (const char *filename)
+static GQuark
+lsm_dom_document_error_quark (void)
+{
+ static GQuark q = 0;
+
+ if (q == 0) {
+ q = g_quark_from_static_string ("mrp-error-quark");
+ }
+
+ return q;
+}
+
+#define LSM_DOM_DOCUMENT_ERROR lsm_dom_document_error_quark ()
+
+typedef enum {
+ LSM_DOM_DOCUMENT_ERROR_INVALID_XML
+} LsmDomDocumentError;
+
+static void
+_dummy_error (const char *msg)
+{
+}
+
+static LsmDomDocument *
+lsm_dom_document_new_from_contents (const char *contents, gsize size, GError **error)
{
static LsmDomSaxParserState state;
+ char *mime;
+ char *xml;
+
+ state.document = NULL;
- if (xmlSAXUserParseFile (&sax_handler, &state, filename) < 0) {
+ mime = g_content_type_guess (NULL, (guchar *) contents, size, NULL);
+ lsm_debug ("[LsmDomDocument::new_from_contents] mime = '%s'", mime);
+ if (g_strcmp0 (mime, "image/svg+xml") == 0 ||
+ g_strcmp0 (mime, "text/mathml") == 0 ||
+ g_strcmp0 (mime, "application/xml") == 0) {
+ xml = (char *) contents;
+ } else {
+ itex2MML_error = _dummy_error;
+
+ xml = itex2MML_parse (contents, size);
+ size = strlen (contents);
+ }
+
+ if (xmlSAXUserParseMemory (&sax_handler, &state, xml, size) < 0) {
if (state.document != NULL)
g_object_unref (state.document);
- g_warning ("[LsmDomParser::from_file] invalid document");
- return NULL;
+ state.document = NULL;
+
+ lsm_debug ("[LsmDomParser::from_memory] invalid document");
+
+ g_set_error (error,
+ LSM_DOM_DOCUMENT_ERROR,
+ LSM_DOM_DOCUMENT_ERROR_INVALID_XML,
+ "Invalid document.");
}
- return LSM_DOM_DOCUMENT (state.document);
+ if (xml != contents)
+ itex2MML_free_string (xml);
+
+ return state.document;
}
LsmDomDocument *
-lsm_dom_document_new_from_memory (const char *buffer)
+lsm_dom_document_new_from_memory (const char *buffer, gsize size, GError **error)
{
- static LsmDomSaxParserState state;
+ g_return_val_if_fail (buffer != NULL, NULL);
- if (buffer == NULL)
- return NULL;
+ if (size < 1)
+ size = strlen (buffer);
- state.document = NULL;
+ return lsm_dom_document_new_from_contents (buffer, size, error);
+}
- if (xmlSAXUserParseMemory (&sax_handler, &state, buffer, strlen (buffer)) < 0) {
- if (state.document != NULL)
- g_object_unref (state.document);
- g_warning ("[LsmDomParser::from_memory] invalid document");
+static LsmDomDocument *
+lsm_dom_document_new_from_file (GFile *file, GError **error)
+{
+ LsmDomDocument *document;
+ gsize size = 0;
+ char *contents = NULL;
+
+ if (!g_file_load_contents (file, NULL, &contents, &size, NULL, error))
return NULL;
- }
- return LSM_DOM_DOCUMENT (state.document);
+ document = lsm_dom_document_new_from_contents (contents, size, error);
+
+ g_free (contents);
+
+ return document;
+}
+
+LsmDomDocument *
+lsm_dom_document_new_from_path (const char *path, GError **error)
+{
+ LsmDomDocument *document;
+ GFile *file;
+
+ g_return_val_if_fail (path != NULL, NULL);
+
+ file = g_file_new_for_path (path);
+
+ document = lsm_dom_document_new_from_file (file, error);
+
+ g_object_unref (file);
+
+ if (document != NULL)
+ lsm_dom_document_set_path (document, path);
+
+ return document;
+}
+
+LsmDomDocument *
+lsm_dom_document_new_from_url (const char *url, GError **error)
+{
+ LsmDomDocument *document;
+ GFile *file;
+
+ g_return_val_if_fail (url != NULL, NULL);
+
+ file = g_file_new_for_uri (url);
+
+ document = lsm_dom_document_new_from_file (file, error);
+
+ g_object_unref (file);
+
+ if (document != NULL)
+ lsm_dom_document_set_url (document, url);
+
+ return document;
}
diff --git a/src/lsmdomparser.h b/src/lsmdomparser.h
index 1af26b8..51e6a78 100644
--- a/src/lsmdomparser.h
+++ b/src/lsmdomparser.h
@@ -26,8 +26,13 @@
G_BEGIN_DECLS
-LsmDomDocument * lsm_dom_document_new_from_file (const char *filename);
-LsmDomDocument * lsm_dom_document_new_from_memory (const char *buffer);
+typedef enum {
+ LSM_DOM_DOCUMENT_ERROR_INVALID_XML
+} LsmDomDocumentError;
+
+LsmDomDocument * lsm_dom_document_new_from_memory (const char *buffer, gsize size, GError *error);
+LsmDomDocument * lsm_dom_document_new_from_path (const char *path, GError *error);
+LsmDomDocument * lsm_dom_document_new_from_url (const char *url, GError *error);
G_END_DECLS
diff --git a/src/lsmmathmldocument.c b/src/lsmmathmldocument.c
index 83d7d3a..dc516c9 100644
--- a/src/lsmmathmldocument.c
+++ b/src/lsmmathmldocument.c
@@ -168,29 +168,29 @@ lsm_mathml_document_class_init (LsmMathmlDocumentClass *m_document_class)
G_DEFINE_TYPE (LsmMathmlDocument, lsm_mathml_document, LSM_TYPE_DOM_DOCUMENT)
-static void
-_dummy_error (const char *msg)
-{
-}
+/*static void*/
+/*_dummy_error (const char *msg)*/
+/*{*/
+/*}*/
-LsmMathmlDocument *
-lsm_mathml_document_new_from_itex (const char *itex)
-{
- LsmMathmlDocument *document;
- char *mathml;
+/*LsmMathmlDocument **/
+/*lsm_mathml_document_new_from_itex (const char *itex)*/
+/*{*/
+/* LsmMathmlDocument *document;*/
+/* char *mathml;*/
- g_return_val_if_fail (itex != NULL, NULL);
+/* g_return_val_if_fail (itex != NULL, NULL);*/
- itex2MML_error = _dummy_error;
+/* itex2MML_error = _dummy_error;*/
- mathml = itex2MML_parse (itex, strlen (itex));
- document = LSM_MATHML_DOCUMENT (lsm_dom_document_new_from_memory (mathml));
- itex2MML_free_string (mathml);
+/* mathml = itex2MML_parse (itex, strlen (itex));*/
+/* document = LSM_MATHML_DOCUMENT (lsm_dom_document_new_from_memory (mathml));*/
+/* itex2MML_free_string (mathml);*/
- if (document != NULL && !LSM_IS_MATHML_DOCUMENT (document)) {
- g_object_unref (document);
- return NULL;
- }
+/* if (document != NULL && !LSM_IS_MATHML_DOCUMENT (document)) {*/
+/* g_object_unref (document);*/
+/* return NULL;*/
+/* }*/
- return document;
-}
+/* return document;*/
+/*}*/
diff --git a/src/lsmmathmldocument.h b/src/lsmmathmldocument.h
index 59a2046..48feef4 100644
--- a/src/lsmmathmldocument.h
+++ b/src/lsmmathmldocument.h
@@ -50,7 +50,7 @@ GType lsm_mathml_document_get_type (void);
LsmMathmlDocument * lsm_mathml_document_new (void);
LsmMathmlMathElement * lsm_mathml_document_get_root_element (const LsmMathmlDocument *document);
-LsmMathmlDocument * lsm_mathml_document_new_from_itex (const char *itex);
+//LsmMathmlDocument * lsm_mathml_document_new_from_itex (const char *itex);
G_END_DECLS
diff --git a/src/lsmstr.c b/src/lsmstr.c
index 486af43..d86173d 100644
--- a/src/lsmstr.c
+++ b/src/lsmstr.c
@@ -20,9 +20,68 @@
*/
#include <lsmstr.h>
+#include <glib.h>
#include <stdio.h>
+#include <string.h>
#include <math.h>
+/* http://www.ietf.org/rfc/rfc2396.txt - Implementation comes from librsvg (rsvg-base.c). */
+
+gboolean
+lsm_str_is_uri (const char *str)
+{
+ char const *p;
+
+ if (str == NULL)
+ return FALSE;
+
+ if (strlen (str) < 4)
+ return FALSE;
+
+ if ( (str[0] < 'a' || str[0] > 'z')
+ && (str[0] < 'A' || str[0] > 'Z'))
+ return FALSE;
+
+ for (p = &str[1];
+ (*p >= 'a' && *p <= 'z')
+ || (*p >= 'A' && *p <= 'Z')
+ || (*p >= '0' && *p <= '9')
+ || *p == '+'
+ || *p == '-'
+ || *p == '.';
+ p++);
+
+ if (strlen (p) < 3)
+ return FALSE;
+
+ return (p[0] == ':' && p[1] == '/' && p[2] == '/');
+}
+
+char *
+lsm_str_to_uri (const char *str)
+{
+ gchar *current_dir;
+ gchar *absolute_filename;
+ gchar *uri;
+
+ if (str == NULL)
+ return NULL;
+
+ if (lsm_str_is_uri (str))
+ return g_strdup (str);
+
+ if (g_path_is_absolute (str))
+ return g_filename_to_uri (str, NULL, NULL);
+
+ current_dir = g_get_current_dir ();
+ absolute_filename = g_build_filename (current_dir, str, NULL);
+ uri = g_filename_to_uri (absolute_filename, NULL, NULL);
+ g_free (absolute_filename);
+ g_free (current_dir);
+
+ return uri;
+}
+
gboolean
lsm_str_parse_double (char **str, double *x)
{
diff --git a/src/lsmstr.h b/src/lsmstr.h
index e091128..2f7e4c6 100644
--- a/src/lsmstr.h
+++ b/src/lsmstr.h
@@ -27,6 +27,9 @@
G_BEGIN_DECLS
+gboolean lsm_str_is_uri (const char *str);
+char * lsm_str_to_uri (const char *str);
+
gboolean lsm_str_parse_double (char **str, double *x);
gboolean lsm_str_parse_double_list (char **str, unsigned int n_values, double *values);
diff --git a/src/lsmsvgcircleelement.c b/src/lsmsvgcircleelement.c
index 7645438..c37b65e 100644
--- a/src/lsmsvgcircleelement.c
+++ b/src/lsmsvgcircleelement.c
@@ -84,9 +84,14 @@ lsm_svg_circle_element_new (void)
return g_object_new (LSM_TYPE_SVG_CIRCLE_ELEMENT, NULL);
}
+static const LsmSvgLength length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
static void
lsm_svg_circle_element_init (LsmSvgCircleElement *self)
{
+ self->cx.length = length_default;
+ self->cy.length = length_default;
+ self->r.length = length_default;
}
static void
@@ -97,8 +102,6 @@ lsm_svg_circle_element_finalize (GObject *object)
/* LsmSvgCircleElement class */
-static const LsmSvgLength length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
-
static const LsmAttributeInfos lsm_svg_circle_element_attribute_infos[] = {
{
.name = "cx",
diff --git a/src/lsmsvgclippathelement.c b/src/lsmsvgclippathelement.c
index 0f03de4..bb8079c 100644
--- a/src/lsmsvgclippathelement.c
+++ b/src/lsmsvgclippathelement.c
@@ -58,6 +58,13 @@ lsm_svg_clip_path_element_render (LsmSvgElement *self, LsmSvgView *view)
LsmSvgClipPathElement *clip = LSM_SVG_CLIP_PATH_ELEMENT (self);
gboolean is_object_bounding_box;
+ if (!clip->enable_rendering) {
+ lsm_debug ("[LsmSvgClipPathElement::render] Direct rendering not allowed");
+ return;
+ }
+
+ clip->enable_rendering = FALSE;
+
is_object_bounding_box = (clip->units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
if (is_object_bounding_box) {
@@ -79,15 +86,26 @@ lsm_svg_clip_path_element_render (LsmSvgElement *self, LsmSvgView *view)
}
}
+static void
+lsm_svg_clip_path_element_enable_rendering (LsmSvgElement *element)
+{
+ LSM_SVG_CLIP_PATH_ELEMENT (element)->enable_rendering = TRUE;
+}
+
LsmDomNode *
lsm_svg_clip_path_element_new (void)
{
return g_object_new (LSM_TYPE_SVG_CLIP_PATH_ELEMENT, NULL);
}
+static const LsmSvgPatternUnits units_default = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
+
static void
lsm_svg_clip_path_element_init (LsmSvgClipPathElement *self)
{
+ self->enable_rendering = FALSE;
+ self->units.value = units_default;
+
/* Hack - Force the creation of the attribute bags,
making sure the properties will be inherited from the
pattern element ancestor, not the referencing one. */
@@ -105,7 +123,8 @@ static const LsmAttributeInfos lsm_svg_clip_path_element_attribute_infos[] = {
{
.name = "clipPathUnits",
.trait_class = &lsm_svg_pattern_units_trait_class,
- .attribute_offset = offsetof (LsmSvgClipPathElement, units)
+ .attribute_offset = offsetof (LsmSvgClipPathElement, units),
+ .trait_default = &units_default
}
};
@@ -123,6 +142,7 @@ lsm_svg_clip_path_element_class_init (LsmSvgClipPathElementClass *klass)
/* s_element_class->render_clip = _clip_path_element_render_clip;*/
/* s_element_class->render = NULL;*/
s_element_class->render = lsm_svg_clip_path_element_render;
+ s_element_class->enable_rendering = lsm_svg_clip_path_element_enable_rendering;
s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
diff --git a/src/lsmsvgclippathelement.h b/src/lsmsvgclippathelement.h
index cadfd19..5794396 100644
--- a/src/lsmsvgclippathelement.h
+++ b/src/lsmsvgclippathelement.h
@@ -40,6 +40,8 @@ struct _LsmSvgClipPathElement {
LsmSvgElement element;
LsmSvgPatternUnitsAttribute units;
+
+ gboolean enable_rendering;
};
struct _LsmSvgClipPathElementClass {
diff --git a/src/lsmsvgelement.c b/src/lsmsvgelement.c
index 27ad1b6..2a11892 100644
--- a/src/lsmsvgelement.c
+++ b/src/lsmsvgelement.c
@@ -27,6 +27,7 @@
#include <lsmsvgpatternelement.h>
#include <lsmsvggradientelement.h>
#include <lsmsvgclippathelement.h>
+#include <lsmsvgmaskelement.h>
#include <lsmsvgview.h>
#include <string.h>
@@ -230,18 +231,12 @@ lsm_svg_element_enable_rendering (LsmSvgElement *element)
}
void
-lsm_svg_element_render_paint (LsmSvgElement *element, LsmSvgView *view)
+lsm_svg_element_force_render (LsmSvgElement *element, LsmSvgView *view)
{
g_return_if_fail (LSM_IS_SVG_PATTERN_ELEMENT (element) ||
- LSM_IS_SVG_GRADIENT_ELEMENT (element));
-
- lsm_svg_element_enable_rendering (element);
- lsm_svg_element_render (element, view);
-}
-
-void lsm_svg_element_render_clip (LsmSvgElement *element, LsmSvgView *view)
-{
- g_return_if_fail (LSM_IS_SVG_CLIP_PATH_ELEMENT (element));
+ LSM_IS_SVG_GRADIENT_ELEMENT (element) ||
+ LSM_IS_SVG_MASK_ELEMENT (element) ||
+ LSM_IS_SVG_CLIP_PATH_ELEMENT (element));
lsm_svg_element_enable_rendering (element);
lsm_svg_element_render (element, view);
diff --git a/src/lsmsvgelement.h b/src/lsmsvgelement.h
index 1bcba80..7ac867e 100644
--- a/src/lsmsvgelement.h
+++ b/src/lsmsvgelement.h
@@ -79,8 +79,7 @@ GType lsm_svg_element_get_type (void);
//void lsm_svg_element_update (LsmSvgElement *element, const LsmSvgStyle *style);
//void lsm_svg_element_enable_rendering(LsmSvgElement *self);
void lsm_svg_element_render (LsmSvgElement *element, LsmSvgView *view);
-void lsm_svg_element_render_paint (LsmSvgElement *element, LsmSvgView *view);
-void lsm_svg_element_render_clip (LsmSvgElement *element, LsmSvgView *view);
+void lsm_svg_element_force_render (LsmSvgElement *element, LsmSvgView *view);
void lsm_svg_element_get_extents (LsmSvgElement *element, LsmSvgView *view, LsmExtents *extents);
G_END_DECLS
diff --git a/src/lsmsvgellipseelement.c b/src/lsmsvgellipseelement.c
index 926fda9..5703364 100644
--- a/src/lsmsvgellipseelement.c
+++ b/src/lsmsvgellipseelement.c
@@ -85,9 +85,15 @@ lsm_svg_ellipse_element_new (void)
return g_object_new (LSM_TYPE_SVG_ELLIPSE_ELEMENT, NULL);
}
+static const LsmSvgLength length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+
static void
lsm_svg_ellipse_element_init (LsmSvgEllipseElement *self)
{
+ self->cx.length = length_default;
+ self->cy.length = length_default;
+ self->rx.length = length_default;
+ self->ry.length = length_default;
}
static void
@@ -98,8 +104,6 @@ lsm_svg_ellipse_element_finalize (GObject *object)
/* LsmSvgEllipseElement class */
-static const LsmSvgLength length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
-
static const LsmAttributeInfos lsm_svg_ellipse_element_attribute_infos[] = {
{
.name = "cx",
diff --git a/src/lsmsvgimageelement.c b/src/lsmsvgimageelement.c
index e77a832..ff27449 100644
--- a/src/lsmsvgimageelement.c
+++ b/src/lsmsvgimageelement.c
@@ -36,6 +36,19 @@ lsm_svg_image_element_get_node_name (LsmDomNode *node)
return "image";
}
+static void
+lsm_svg_image_element_set_attribute (LsmDomElement *self, const char *name, const char *value)
+{
+ LsmSvgImageElement *image_element = LSM_SVG_IMAGE_ELEMENT (self);
+
+ LSM_DOM_ELEMENT_CLASS (parent_class)->set_attribute (self, name, value);
+
+ if (g_strcmp0 (name, "xlink:href") == 0 && image_element->pixbuf != NULL) {
+ g_object_unref (image_element->pixbuf);
+ image_element->pixbuf = NULL;
+ }
+}
+
static gboolean
lsm_svg_use_can_append_child (LsmDomNode *node, LsmDomNode *child)
{
@@ -126,6 +139,34 @@ lsm_svg_image_element_render (LsmSvgElement *self, LsmSvgView *view)
LsmBox viewbox;
image = LSM_SVG_IMAGE_ELEMENT (self);
+
+ if (image->pixbuf == NULL) {
+ LsmDomDocument *document;
+ char *data;
+ gsize size;
+
+ document = lsm_dom_node_get_owner_document (LSM_DOM_NODE (self));
+ data = lsm_dom_document_get_href_data (document, image->href.value, &size);
+
+ if (data != NULL) {
+ GdkPixbufLoader *loader;
+ int result;
+
+ loader = gdk_pixbuf_loader_new ();
+
+ result = gdk_pixbuf_loader_write (loader, (guchar *) data, size, NULL);
+
+ g_free (data);
+
+ gdk_pixbuf_loader_close (loader, NULL);
+
+ image->pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+ g_object_ref (image->pixbuf);
+
+ g_object_unref (loader);
+ }
+ }
+
if (image->pixbuf == NULL)
return;
@@ -161,10 +202,22 @@ lsm_svg_image_element_new (void)
return g_object_new (LSM_TYPE_SVG_IMAGE_ELEMENT, NULL);
}
+static const LsmSvgLength length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+static const LsmSvgPreserveAspectRatio preserve_aspect_ratio_default = {
+ .defer = FALSE,
+ .align = LSM_SVG_ALIGN_X_MID_Y_MID,
+ .meet_or_slice = LSM_SVG_MEET_OR_SLICE_MEET
+};
+
static void
lsm_svg_image_element_init (LsmSvgImageElement *self)
{
self->pixbuf = NULL;
+ self->x.length = length_default;
+ self->y.length = length_default;
+ self->width.length = length_default;
+ self->height.length = length_default;
+ self->preserve_aspect_ratio.value = preserve_aspect_ratio_default;
}
static void
@@ -180,13 +233,6 @@ lsm_svg_image_element_finalize (GObject *gobject)
/* LsmSvgImageElement class */
-static const LsmSvgLength length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
-static const LsmSvgPreserveAspectRatio preserve_aspect_ratio_default = {
- .defer = FALSE,
- .align = LSM_SVG_ALIGN_X_MID_Y_MID,
- .meet_or_slice = LSM_SVG_MEET_OR_SLICE_MEET
-};
-
static const LsmAttributeInfos lsm_svg_image_element_attribute_infos[] = {
{
.name = "x",
@@ -230,6 +276,7 @@ lsm_svg_image_element_class_init (LsmSvgImageElementClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
LsmDomNodeClass *d_node_class = LSM_DOM_NODE_CLASS (klass);
+ LsmDomElementClass *d_element_class = LSM_DOM_ELEMENT_CLASS (klass);
LsmSvgElementClass *s_element_class = LSM_SVG_ELEMENT_CLASS (klass);
/* LsmSvgGraphicClass *s_graphic_class = LSM_SVG_GRAPHIC_CLASS (klass);*/
@@ -240,6 +287,8 @@ lsm_svg_image_element_class_init (LsmSvgImageElementClass *klass)
d_node_class->get_node_name = lsm_svg_image_element_get_node_name;
d_node_class->can_append_child = lsm_svg_use_can_append_child;
+ d_element_class->set_attribute = lsm_svg_image_element_set_attribute;
+
/* s_element_class->update = lsm_svg_image_element_update;*/
s_element_class->render = lsm_svg_image_element_render;
diff --git a/src/lsmsvgmaskelement.c b/src/lsmsvgmaskelement.c
index 5e1be92..dff2e23 100644
--- a/src/lsmsvgmaskelement.c
+++ b/src/lsmsvgmaskelement.c
@@ -78,6 +78,13 @@ lsm_svg_mask_element_render (LsmSvgElement *self, LsmSvgView *view)
LsmBox viewport;
const LsmBox *mask_extents;
+ if (!mask->enable_rendering) {
+ lsm_debug ("[LsmSvgMaskElement::render] Direct rendering not allowed");
+ return;
+ }
+
+ mask->enable_rendering = FALSE;
+
mask_extents = lsm_svg_view_get_pattern_extents (view);
is_object_bounding_box = (mask->units.value == LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX);
@@ -109,7 +116,7 @@ lsm_svg_mask_element_render (LsmSvgElement *self, LsmSvgView *view)
if (viewport.width <= 0.0 || viewport.height <= 0.0)
return;
- lsm_debug ("[LsmSvgMaskElement::render_paint] Create mask x = %g, y = %g, w = %g, h = %g",
+ lsm_debug ("[LsmSvgMaskElement::render] Create mask x = %g, y = %g, w = %g, h = %g",
viewport.x, viewport.y, viewport.width, viewport.height);
lsm_svg_view_create_surface_pattern (view, &viewport,
@@ -128,7 +135,7 @@ lsm_svg_mask_element_render (LsmSvgElement *self, LsmSvgView *view)
lsm_svg_view_push_viewbox (view, &viewbox);
lsm_svg_view_push_matrix (view, &matrix);
- lsm_debug ("[LsmSvgMaskElement::render_paint] object_bounding_box"
+ lsm_debug ("[LsmSvgMaskElement::render] object_bounding_box"
" x_scale = %g, y_scale = %g, x_offset = %g, y_offset = %g",
mask_extents->width, mask_extents->height,
mask_extents->x, mask_extents->y);
@@ -142,6 +149,12 @@ lsm_svg_mask_element_render (LsmSvgElement *self, LsmSvgView *view)
}
}
+static void
+lsm_svg_mask_element_enable_rendering (LsmSvgElement *element)
+{
+ LSM_SVG_MASK_ELEMENT (element)->enable_rendering = TRUE;
+}
+
/* LsmSvgMaskElement implementation */
LsmDomNode *
@@ -150,9 +163,22 @@ lsm_svg_mask_element_new (void)
return g_object_new (LSM_TYPE_SVG_MASK_ELEMENT, NULL);
}
+static const LsmSvgLength x_y_default = { .value_unit = -10.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE};
+static const LsmSvgLength width_height_default ={ .value_unit = 120.0, .type = LSM_SVG_LENGTH_TYPE_PERCENTAGE};
+static const LsmSvgPatternUnits units_default = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX;
+static const LsmSvgPatternUnits content_units_default = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
+
static void
lsm_svg_mask_element_init (LsmSvgMaskElement *self)
{
+ self->enable_rendering = FALSE;
+ self->x.length = x_y_default;
+ self->y.length = x_y_default;
+ self->width.length = width_height_default;
+ self->height.length = width_height_default;
+ self->units.value = units_default;
+ self->content_units.value = content_units_default;
+
/* Hack - Force the creation of the attribute bags,
making sure the properties will be inherited from the
mask element ancestor, not the referencing one. */
@@ -166,34 +192,30 @@ lsm_svg_mask_element_init (LsmSvgMaskElement *self)
/* LsmSvgMaskElement class */
-static const LsmSvgLength length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
-static const LsmSvgPatternUnits units_default = LSM_SVG_PATTERN_UNITS_OBJECT_BOUNDING_BOX;
-static const LsmSvgPatternUnits content_units_default = LSM_SVG_PATTERN_UNITS_USER_SPACE_ON_USE;
-
static const LsmAttributeInfos lsm_svg_mask_element_attribute_infos[] = {
{
.name = "x",
.attribute_offset = offsetof (LsmSvgMaskElement, x),
.trait_class = &lsm_svg_length_trait_class,
- .trait_default = &length_default
+ .trait_default = &x_y_default
},
{
.name = "y",
.attribute_offset = offsetof (LsmSvgMaskElement, y),
.trait_class = &lsm_svg_length_trait_class,
- .trait_default = &length_default
+ .trait_default = &x_y_default
},
{
.name = "width",
.attribute_offset = offsetof (LsmSvgMaskElement, width),
.trait_class = &lsm_svg_length_trait_class,
- .trait_default = &length_default
+ .trait_default = &width_height_default
},
{
.name = "height",
.attribute_offset = offsetof (LsmSvgMaskElement, height),
.trait_class = &lsm_svg_length_trait_class,
- .trait_default = &length_default
+ .trait_default = &width_height_default
},
{
.name = "maskUnits",
@@ -225,6 +247,7 @@ lsm_svg_mask_element_class_init (LsmSvgMaskElementClass *klass)
s_element_class->render = lsm_svg_mask_element_render;
s_element_class->attribute_manager = lsm_attribute_manager_duplicate (s_element_class->attribute_manager);
+ s_element_class->enable_rendering = lsm_svg_mask_element_enable_rendering;
lsm_attribute_manager_add_attributes (s_element_class->attribute_manager,
G_N_ELEMENTS (lsm_svg_mask_element_attribute_infos),
diff --git a/src/lsmsvgmaskelement.h b/src/lsmsvgmaskelement.h
index 63e3430..fe6a81e 100644
--- a/src/lsmsvgmaskelement.h
+++ b/src/lsmsvgmaskelement.h
@@ -45,6 +45,8 @@ struct _LsmSvgMaskElement {
LsmSvgLengthAttribute height;
LsmSvgPatternUnitsAttribute units;
LsmSvgPatternUnitsAttribute content_units;
+
+ gboolean enable_rendering;
};
struct _LsmSvgMaskElementClass {
diff --git a/src/lsmsvgpatternelement.c b/src/lsmsvgpatternelement.c
index e183d43..870ab1c 100644
--- a/src/lsmsvgpatternelement.c
+++ b/src/lsmsvgpatternelement.c
@@ -84,8 +84,10 @@ lsm_svg_pattern_element_render (LsmSvgElement *self, LsmSvgView *view)
LsmBox viewport;
const LsmBox *pattern_extents;
- if (!pattern->enable_rendering)
+ if (!pattern->enable_rendering) {
+ lsm_debug ("[LsmSvgPatternElement::render] Direct rendering not allowed");
return;
+ }
pattern->enable_rendering = FALSE;
@@ -120,7 +122,7 @@ lsm_svg_pattern_element_render (LsmSvgElement *self, LsmSvgView *view)
if (viewport.width <= 0.0 || viewport.height <= 0.0)
return;
- lsm_debug ("[LsmSvgPatternElement::render_paint] Create pattern x = %g, y = %g, w = %g, h = %g",
+ lsm_debug ("[LsmSvgPatternElement::render] Create pattern x = %g, y = %g, w = %g, h = %g",
viewport.x, viewport.y, viewport.width, viewport.height);
lsm_svg_view_create_surface_pattern (view, &viewport,
@@ -140,7 +142,7 @@ lsm_svg_pattern_element_render (LsmSvgElement *self, LsmSvgView *view)
lsm_svg_view_push_viewbox (view, &viewbox);
lsm_svg_view_push_matrix (view, &matrix);
- lsm_debug ("[LsmSvgPatternElement::render_paint] object_bounding_box"
+ lsm_debug ("[LsmSvgPatternElement::render] object_bounding_box"
" x_scale = %g, y_scale = %g, x_offset = %g, y_offset = %g",
pattern_extents->width, pattern_extents->height,
pattern_extents->x, pattern_extents->y);
@@ -203,7 +205,6 @@ lsm_svg_pattern_element_init (LsmSvgPatternElement *self)
self->content_units.value = content_units_default;
self->preserve_aspect_ratio.value = preserve_aspect_ratio_default;
-#if 0
/* Hack - Force the creation of the attribute bags,
making sure the properties will be inherited from the
pattern element ancestor, not the referencing one. */
@@ -213,7 +214,6 @@ lsm_svg_pattern_element_init (LsmSvgPatternElement *self)
lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "transform", NULL);
lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "font-family", NULL);
lsm_dom_element_set_attribute (LSM_DOM_ELEMENT (self), "stop-color", NULL);
-#endif
}
/* LsmSvgPatternElement class */
diff --git a/src/lsmsvgradialgradientelement.c b/src/lsmsvgradialgradientelement.c
index 1934687..d8a036c 100644
--- a/src/lsmsvgradialgradientelement.c
+++ b/src/lsmsvgradialgradientelement.c
@@ -86,8 +86,16 @@ lsm_svg_radial_gradient_element_create_gradient (LsmSvgElement *self, LsmSvgView
cx = lsm_svg_view_normalize_length (view, &radial->cx.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
cy = lsm_svg_view_normalize_length (view, &radial->cy.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
r = lsm_svg_view_normalize_length (view, &radial->r.length, LSM_SVG_LENGTH_DIRECTION_DIAGONAL);
- fx = lsm_svg_view_normalize_length (view, &radial->fx.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
- fy = lsm_svg_view_normalize_length (view, &radial->fy.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+
+ if (lsm_attribute_is_defined (&radial->fx.base))
+ fx = lsm_svg_view_normalize_length (view, &radial->fx.length, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+ else
+ fx = cx;
+
+ if (lsm_attribute_is_defined (&radial->fy.base))
+ fy = lsm_svg_view_normalize_length (view, &radial->fy.length, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+ else
+ fy = cy;
gradient_radius = sqrt ((fx - cx) * (fx - cx) + (fy - cy) * (fy - cy));
if (gradient_radius > r) {
diff --git a/src/lsmsvgrectelement.c b/src/lsmsvgrectelement.c
index 18b6215..807d81d 100644
--- a/src/lsmsvgrectelement.c
+++ b/src/lsmsvgrectelement.c
@@ -95,13 +95,6 @@ lsm_svg_rect_element_render (LsmSvgElement *self, LsmSvgView *view)
else if (!lsm_attribute_is_defined (&rect->ry.base))
ry = rx;
-
-/* if (rect->rx.length.type == LSM_SVG_LENGTH_TYPE_UNKNOWN) {*/
-/* rx = ry;*/
-/* } else if (rect->rx.length.type == LSM_SVG_LENGTH_TYPE_UNKNOWN) {*/
-/* ry = rx;*/
-/* }*/
-
lsm_svg_view_show_rectangle (view, x, y, w, h, rx, ry);
}
@@ -131,9 +124,18 @@ lsm_svg_rect_element_new (void)
return g_object_new (LSM_TYPE_SVG_RECT_ELEMENT, NULL);
}
+static const LsmSvgLength length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
+static const LsmSvgLength unset_length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_UNKNOWN};
+
static void
lsm_svg_rect_element_init (LsmSvgRectElement *self)
{
+ self->x.length = length_default;
+ self->y.length = length_default;
+ self->width.length = length_default;
+ self->height.length = length_default;
+ self->rx.length = unset_length_default;
+ self->ry.length = unset_length_default;
}
static void
@@ -144,9 +146,6 @@ lsm_svg_rect_element_finalize (GObject *object)
/* LsmSvgRectElement class */
-static const LsmSvgLength length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_PX};
-static const LsmSvgLength unset_length_default = { .value_unit = 0.0, .type = LSM_SVG_LENGTH_TYPE_UNKNOWN};
-
static const LsmAttributeInfos lsm_svg_rect_element_attribute_infos[] = {
{
.name = "x",
diff --git a/src/lsmsvgsvgelement.c b/src/lsmsvgsvgelement.c
index 74da14a..c8ed8d4 100644
--- a/src/lsmsvgsvgelement.c
+++ b/src/lsmsvgsvgelement.c
@@ -101,14 +101,29 @@ lsm_svg_svg_element_measure (LsmSvgSvgElement *self, double *width, double *heig
svg_viewbox = lsm_svg_viewbox_new (resolution_ppi, &viewport);
font_size = 10 * resolution_ppi / 72.0;
- svg_x = lsm_svg_length_normalize (&self->x.length, svg_viewbox,
- font_size, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
- svg_y = lsm_svg_length_normalize (&self->y.length, svg_viewbox,
- font_size, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
- svg_width = lsm_svg_length_normalize (&self->width.length, svg_viewbox,
- font_size, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
- svg_height = lsm_svg_length_normalize (&self->height.length, svg_viewbox,
- font_size, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+ if (lsm_attribute_is_defined (&self->x.base))
+ svg_x = lsm_svg_length_normalize (&self->x.length, svg_viewbox,
+ font_size, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+ else
+ svg_x = viewport.x;
+
+ if (lsm_attribute_is_defined (&self->y.base))
+ svg_y = lsm_svg_length_normalize (&self->y.length, svg_viewbox,
+ font_size, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+ else
+ svg_y = viewport.y;
+
+ if (lsm_attribute_is_defined (&self->width.base))
+ svg_width = lsm_svg_length_normalize (&self->width.length, svg_viewbox,
+ font_size, LSM_SVG_LENGTH_DIRECTION_HORIZONTAL);
+ else
+ svg_width = viewport.width;
+
+ if (lsm_attribute_is_defined (&self->height.base))
+ svg_height = lsm_svg_length_normalize (&self->height.length, svg_viewbox,
+ font_size, LSM_SVG_LENGTH_DIRECTION_VERTICAL);
+ else
+ svg_height = viewport.height;
if (width != NULL)
*width = svg_width * 72.0 / resolution_ppi;
@@ -146,7 +161,7 @@ _svg_element_render (LsmSvgElement *self, LsmSvgView *view)
svg->viewbox.value.height <= 0.0))
return;
- lsm_debug ("[LsmSvgSvgElement::graphic_render] viewport %g, %g, %g, %g",
+ lsm_debug ("[LsmSvgSvgElement::render] viewport %g, %g, %g, %g",
viewport.x, viewport.y, viewport.width, viewport.height);
lsm_svg_view_push_viewport (view, &viewport, is_viewbox_defined ? &svg->viewbox.value : NULL,
diff --git a/src/lsmsvgtraits.c b/src/lsmsvgtraits.c
index 93e4f91..8eb4c49 100644
--- a/src/lsmsvgtraits.c
+++ b/src/lsmsvgtraits.c
@@ -208,19 +208,18 @@ const LsmTraitClass lsm_svg_matrix_trait_class = {
static char *
_parse_color (char *string,
LsmSvgColor *svg_color,
- gboolean *is_color_set)
+ LsmSvgPaintType *paint_type)
{
unsigned int color = 0;
- *is_color_set = FALSE;
lsm_str_skip_spaces (&string);
if (g_strcmp0 (string, "currentColor") == 0) {
svg_color->red = -1.0;
- svg_color->green = 1.0;
- svg_color->blue = 1.0;
+ svg_color->green = -1.0;
+ svg_color->blue = -1.0;
- *is_color_set = TRUE;
+ *paint_type = LSM_SVG_PAINT_TYPE_CURRENT_COLOR;
string += 12; /* strlen ("current_color") */
@@ -251,7 +250,7 @@ _parse_color (char *string,
} else if (i != 6)
color = 0;
- *is_color_set = TRUE;
+ *paint_type = LSM_SVG_PAINT_TYPE_RGB_COLOR;
} else if (strncmp (string, "rgb(", 4) == 0) {
int i;
double value;
@@ -279,13 +278,13 @@ _parse_color (char *string,
if (*string != ')' || i != 3)
color = 0;
- *is_color_set = TRUE;
- } else if (g_strcmp0 (string, "none") == 0) {
- *is_color_set = FALSE;
- } else {
+ *paint_type = LSM_SVG_PAINT_TYPE_RGB_COLOR;
+ } else if (g_strcmp0 (string, "none") != 0) {
color = lsm_svg_color_from_string (string);
- *is_color_set = TRUE;
+ *paint_type = LSM_SVG_PAINT_TYPE_RGB_COLOR;
+ } else {
+ *paint_type = LSM_SVG_PAINT_TYPE_NONE;
}
svg_color->red = (double) ((color & 0xff0000) >> 16) / 255.0;
@@ -299,7 +298,7 @@ static void
lsm_svg_paint_trait_from_string (LsmTrait *abstract_trait, char *string)
{
LsmSvgPaint *paint = (LsmSvgPaint *) abstract_trait;
- gboolean is_color_set;
+ LsmSvgPaintType paint_type;
g_free (paint->uri);
@@ -322,16 +321,28 @@ lsm_svg_paint_trait_from_string (LsmTrait *abstract_trait, char *string)
paint->uri = NULL;
}
- string = _parse_color (string, &paint->color, &is_color_set);
+ string = _parse_color (string, &paint->color, &paint_type);
+
+ if (paint->uri != NULL)
+ switch (paint_type) {
+ case LSM_SVG_PAINT_TYPE_RGB_COLOR:
+ paint_type = LSM_SVG_PAINT_TYPE_URI_RGB_COLOR;
+ break;
+ case LSM_SVG_PAINT_TYPE_CURRENT_COLOR:
+ paint_type = LSM_SVG_PAINT_TYPE_URI_CURRENT_COLOR;
+ break;
+ case LSM_SVG_PAINT_TYPE_NONE:
+ paint_type = LSM_SVG_PAINT_TYPE_URI;
+ break;
+ case LSM_SVG_PAINT_TYPE_RGB_COLOR_ICC_COLOR:
+ paint_type = LSM_SVG_PAINT_TYPE_URI_RGB_COLOR_ICC_COLOR;
+ break;
+ default:
+ paint_type = LSM_SVG_PAINT_TYPE_URI;
+ break;
+ }
- if (is_color_set)
- paint->type = paint->uri != NULL ?
- LSM_SVG_PAINT_TYPE_URI_RGB_COLOR :
- LSM_SVG_PAINT_TYPE_RGB_COLOR;
- else
- paint->type = paint->uri != NULL ?
- LSM_SVG_PAINT_TYPE_URI :
- LSM_SVG_PAINT_TYPE_NONE;
+ paint->type = paint_type;
}
char *
@@ -339,9 +350,7 @@ lsm_svg_paint_trait_to_string (LsmTrait *abstract_trait)
{
LsmSvgPaint *paint = (LsmSvgPaint *) abstract_trait;
- if (paint->color.red < 0.0 ||
- paint->color.green < 0.0 ||
- paint->color.blue < 0.0)
+ if (paint->color.red < 0.0 || paint->color.green < 0.0 || paint->color.blue < 0.0)
return g_strdup ("currentColor");
if (paint->uri != NULL)
@@ -542,9 +551,9 @@ static void
lsm_svg_color_trait_from_string (LsmTrait *abstract_trait, char *string)
{
LsmSvgColor *color = (LsmSvgColor *) abstract_trait;
- gboolean is_color_set;
+ LsmSvgPaintType paint_type;
- _parse_color (string, color, &is_color_set);
+ _parse_color (string, color, &paint_type);
}
static char *
@@ -552,6 +561,9 @@ lsm_svg_color_trait_to_string (LsmTrait *abstract_trait)
{
LsmSvgColor *color = (LsmSvgColor *) abstract_trait;
+ if (color->red < 0.0 || color->green < 0.0 || color->blue < 0.0)
+ return g_strdup ("currentColor");
+
return g_strdup_printf ("rgb(%g%%,%g%%,%g%%)",
100.0 * color->red,
100.0 * color->green,
diff --git a/src/lsmsvgview.c b/src/lsmsvgview.c
index 87f1a23..d98a79a 100644
--- a/src/lsmsvgview.c
+++ b/src/lsmsvgview.c
@@ -152,6 +152,7 @@ lsm_svg_view_add_gradient_color_stop (LsmSvgView *view, double offset)
/* , const LsmSvgColor *color, double opacity)*/
{
const LsmSvgStyle *style;
+ const LsmSvgColor *color;
g_return_if_fail (LSM_IS_SVG_VIEW (view));
g_return_if_fail (view->pattern_data != NULL);
@@ -172,11 +173,15 @@ lsm_svg_view_add_gradient_color_stop (LsmSvgView *view, double offset)
/* color->red, color->green, color->blue, opacity);*/
lsm_debug ("[LsmSvgView::add_gradient_color_stop] opacity = %g", style->stop_opacity->value);
+ color = &style->stop_color->value;
+
+ if (color->red < 0.0 || color->blue < 0.0 || color->green < 0.0)
+ color = &style->color->value;
cairo_pattern_add_color_stop_rgba (view->pattern_data->pattern, offset,
- style->stop_color->value.red,
- style->stop_color->value.green,
- style->stop_color->value.blue,
+ color->red,
+ color->green,
+ color->blue,
style->stop_opacity->value);
/* color->red, color->green, color->blue, opacity);*/
}
@@ -720,7 +725,7 @@ _paint_uri (LsmSvgView *view, LsmSvgViewPaintOperation operation, const char *ur
_start_pattern (view, &extents);
- lsm_svg_element_render_paint (LSM_SVG_ELEMENT (element), view);
+ lsm_svg_element_force_render (LSM_SVG_ELEMENT (element), view);
cairo = view->pattern_data->old_cairo;
@@ -791,6 +796,13 @@ _set_color (LsmSvgView *view, LsmSvgViewPaintOperation operation,
paint->color.blue,
opacity);
break;
+ case LSM_SVG_PAINT_TYPE_CURRENT_COLOR:
+ cairo_set_source_rgba (cairo,
+ view->style->color->value.red,
+ view->style->color->value.green,
+ view->style->color->value.blue,
+ opacity);
+ break;
case LSM_SVG_PAINT_TYPE_URI:
case LSM_SVG_PAINT_TYPE_URI_RGB_COLOR:
case LSM_SVG_PAINT_TYPE_URI_CURRENT_COLOR:
@@ -929,6 +941,8 @@ paint (LsmSvgView *view)
static void
process_path (LsmSvgView *view)
{
+ g_return_if_fail (view->style != NULL);
+
if (view->is_clipping) {
/* LsmSvgMaskAttributeBag *mask;*/
@@ -1312,53 +1326,29 @@ lsm_svg_view_pop_matrix (LsmSvgView *view)
}
void
-lsm_svg_view_push_element (LsmSvgView *view, const LsmSvgElement *element)
-{
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
- g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
-
- view->element_stack = g_slist_prepend (view->element_stack, (void *) element);
-}
-
-void
-lsm_svg_view_pop_element (LsmSvgView *view)
+lsm_svg_view_push_group_opacity (LsmSvgView *view)
{
g_return_if_fail (LSM_IS_SVG_VIEW (view));
- g_return_if_fail (view->element_stack != NULL);
+ g_return_if_fail (view->style != NULL);
- view->element_stack = g_slist_delete_link (view->element_stack, view->element_stack);
+ if (view->style->opacity->value < 1.0)
+ cairo_push_group (view->dom_view.cairo);
}
void
-lsm_svg_view_push_style (LsmSvgView *view, const LsmSvgStyle *style)
-{
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
- g_return_if_fail (style != NULL);
-
- view->style_stack = g_slist_prepend (view->style_stack, (void *) style);
- view->style = style;
-}
-
-void lsm_svg_view_pop_style (LsmSvgView *view)
+lsm_svg_view_pop_group_opacity (LsmSvgView *view)
{
g_return_if_fail (LSM_IS_SVG_VIEW (view));
- g_return_if_fail (view->style_stack != NULL);
-
- view->style_stack = g_slist_delete_link (view->style_stack, view->style_stack);
- view->style = view->style_stack != NULL ? view->style_stack->data : NULL;
-}
-
-const LsmSvgStyle *
-lsm_svg_view_get_current_style (LsmSvgView *view)
-{
- g_return_val_if_fail (LSM_IS_SVG_VIEW (view), NULL);
+ g_return_if_fail (view->style != NULL);
- return view->style;
+ if (view->style->opacity->value < 1.0) {
+ cairo_pop_group_to_source (view->dom_view.cairo);
+ cairo_paint_with_alpha (view->dom_view.cairo, view->style->opacity->value);
+ }
}
-#if 0
static void
-lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_rule)
+lsm_svg_view_push_clip (LsmSvgView *view)
{
LsmDomElement *element;
LsmExtents extents;
@@ -1369,9 +1359,9 @@ lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_r
lsm_svg_element_get_extents (view->element_stack->data, view, &extents);
- uri = clip_path;
+ uri = view->style->clip_path->value;
- lsm_debug ("[LsmSvgView::push_clip] Using '%s'", clip_path);
+ lsm_debug ("[LsmSvgView::push_clip] Using '%s'", uri);
cairo_save (view->dom_view.cairo);
@@ -1393,7 +1383,7 @@ lsm_svg_view_push_clip (LsmSvgView *view, char *clip_path, LsmSvgFillRule clip_r
if (element != NULL && LSM_IS_SVG_CLIP_PATH_ELEMENT (element)) {
view->is_clipping = TRUE;
- lsm_svg_element_render_clip (LSM_SVG_ELEMENT (element), view);
+ lsm_svg_element_force_render (LSM_SVG_ELEMENT (element), view);
cairo_clip (view->dom_view.cairo);
view->is_clipping = FALSE;
}
@@ -1407,66 +1397,42 @@ lsm_svg_view_pop_clip (LsmSvgView *view)
cairo_restore (view->dom_view.cairo);
}
-#endif
-
-void
-lsm_svg_view_push_group_opacity (LsmSvgView *view)
-{
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
- g_return_if_fail (view->style != NULL);
-
- if (view->style->opacity->value < 1.0)
- cairo_push_group (view->dom_view.cairo);
-}
-
-void
-lsm_svg_view_pop_group_opacity (LsmSvgView *view)
-{
- g_return_if_fail (LSM_IS_SVG_VIEW (view));
- g_return_if_fail (view->style != NULL);
-
- if (view->style->opacity->value < 1.0) {
- cairo_pop_group_to_source (view->dom_view.cairo);
- cairo_paint_with_alpha (view->dom_view.cairo, view->style->opacity->value);
- }
-}
-#if 0
-void
-lsm_svg_view_push_mask_attributes (LsmSvgView *view, const LsmSvgMaskAttributeBag *mask)
+static void
+lsm_svg_view_push_mask (LsmSvgView *view)
{
g_return_if_fail (LSM_IS_SVG_VIEW (view));
- g_return_if_fail (mask != NULL);
+/* g_return_if_fail (mask != NULL);*/
- view->mask_stack = g_slist_prepend (view->mask_stack, (void *) mask);
+/* view->mask_stack = g_slist_prepend (view->mask_stack, (void *) mask);*/
- if (mask->clip_path.value != NULL)
- lsm_svg_view_push_clip (view, mask->clip_path.value, mask->clip_rule.value);
+/* if (mask->clip_path.value != NULL)*/
+/* lsm_svg_view_push_clip (view, mask->clip_path.value, mask->clip_rule.value);*/
- if (mask->mask.value != NULL)
+/* if (mask->mask.value != NULL)*/
cairo_push_group (view->dom_view.cairo);
}
-void
-lsm_svg_view_pop_mask_attributes (LsmSvgView *view)
+static void
+lsm_svg_view_pop_mask (LsmSvgView *view)
{
- LsmSvgMaskAttributeBag *mask;
+/* LsmSvgMaskAttributeBag *mask;*/
g_return_if_fail (LSM_IS_SVG_VIEW (view));
- g_return_if_fail (view->mask_stack != NULL);
+/* g_return_if_fail (view->mask_stack != NULL);*/
- mask = view->mask_stack->data;
+/* mask = view->mask_stack->data;*/
- if (mask->clip_path.value != NULL)
- lsm_svg_view_pop_clip (view);
+/* if (mask->clip_path.value != NULL)*/
+/* lsm_svg_view_pop_clip (view);*/
- if (mask->mask.value != NULL) {
- if (strncmp (mask->mask.value, "url(#", 5) == 0) {
+/* if (mask->mask.value != NULL) {*/
+ if (strncmp (view->style->mask->value, "url(#", 5) == 0) {
LsmDomElement *mask_element;
char *end;
char *uri;
- uri = g_strdup (mask->mask.value + 5);
+ uri = g_strdup (view->style->mask->value + 5);
for (end = uri; *end != '\0' && *end != ')'; end++);
*end = '\0';
@@ -1488,7 +1454,7 @@ lsm_svg_view_pop_mask_attributes (LsmSvgView *view)
_start_pattern (view, &mask_extents);
- lsm_svg_element_render_paint (LSM_SVG_ELEMENT (mask_element), view);
+ lsm_svg_element_force_render (LSM_SVG_ELEMENT (mask_element), view);
cairo_pop_group_to_source (cairo);
if (view->pattern_data->pattern != NULL) {
@@ -1533,11 +1499,12 @@ lsm_svg_view_pop_mask_attributes (LsmSvgView *view)
cairo_pop_group_to_source (view->dom_view.cairo);
cairo_paint (view->dom_view.cairo);
}
- }
+/* }*/
- view->mask_stack = g_slist_delete_link (view->mask_stack, view->mask_stack);
+/* view->mask_stack = g_slist_delete_link (view->mask_stack, view->mask_stack);*/
}
+#if 0
void
lsm_svg_view_push_fill_attributes (LsmSvgView *view, const LsmSvgFillAttributeBag *fill)
{
@@ -1594,6 +1561,67 @@ lsm_svg_view_pop_text_attributes (LsmSvgView *view)
#endif
+void
+lsm_svg_view_push_element (LsmSvgView *view, const LsmSvgElement *element)
+{
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (LSM_IS_SVG_ELEMENT (element));
+
+ view->element_stack = g_slist_prepend (view->element_stack, (void *) element);
+}
+
+void
+lsm_svg_view_pop_element (LsmSvgView *view)
+{
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (view->element_stack != NULL);
+
+ view->element_stack = g_slist_delete_link (view->element_stack, view->element_stack);
+}
+
+void
+lsm_svg_view_push_style (LsmSvgView *view, const LsmSvgStyle *style)
+{
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (style != NULL);
+
+ view->style_stack = g_slist_prepend (view->style_stack, (void *) style);
+ view->style = style;
+
+ if (g_strcmp0 (style->clip_path->value, "none") != 0) {
+ lsm_debug ("[LsmSvgView::push_style] Start clip '%s'", style->clip_path->value);
+ lsm_svg_view_push_clip (view);
+ }
+
+ if (g_strcmp0 (style->mask->value, "none") != 0) {
+ lsm_debug ("[LsmSvgView::push_style] Start mask '%s'", style->mask->value);
+ lsm_svg_view_push_mask (view);
+ }
+}
+
+void lsm_svg_view_pop_style (LsmSvgView *view)
+{
+ g_return_if_fail (LSM_IS_SVG_VIEW (view));
+ g_return_if_fail (view->style_stack != NULL);
+
+ if (g_strcmp0 (view->style->mask->value, "none") != 0)
+ lsm_svg_view_pop_mask (view);
+
+ if (g_strcmp0 (view->style->clip_path->value, "none") != 0)
+ lsm_svg_view_pop_clip (view);
+
+ view->style_stack = g_slist_delete_link (view->style_stack, view->style_stack);
+ view->style = view->style_stack != NULL ? view->style_stack->data : NULL;
+}
+
+const LsmSvgStyle *
+lsm_svg_view_get_current_style (LsmSvgView *view)
+{
+ g_return_val_if_fail (LSM_IS_SVG_VIEW (view), NULL);
+
+ return view->style;
+}
+
const LsmBox *
lsm_svg_view_get_pattern_extents (LsmSvgView *view)
{
diff --git a/test/.gitignore b/test/.gitignore
index d109f53..b4dc037 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -1,3 +1,2 @@
-lasemtest.xml
log
*-out.png
diff --git a/test/svg/svg1.1/color/images/colorprof.png b/test/svg/svg1.1/color/images/colorprof.png
new file mode 100755
index 0000000..c03ab9c
Binary files /dev/null and b/test/svg/svg1.1/color/images/colorprof.png differ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]