3 * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
5 * This file is part of gLabels.
7 * gLabels is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * gLabels is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with gLabels. If not, see <http://www.gnu.org/licenses/>.
23 #include "xml-label.h"
25 #include <glib/gi18n.h>
27 #include <libxml/tree.h>
28 #include <libxml/parser.h>
29 #include <libxml/xinclude.h>
30 #include <gdk-pixbuf/gdk-pixdata.h>
32 #include <libglabels.h>
34 #include "label-object.h"
35 #include "label-text.h"
36 #include "label-box.h"
37 #include "label-line.h"
38 #include "label-ellipse.h"
39 #include "label-image.h"
40 #include "label-barcode.h"
41 #include "bc-backends.h"
42 #include "xml-label-04.h"
49 /*========================================================*/
50 /* Private macros and constants. */
51 /*========================================================*/
52 #define COMPAT01_NAME_SPACE "http://snaught.com/glabels/0.1/"
53 #define COMPAT04_NAME_SPACE "http://snaught.com/glabels/0.4/"
54 #define COMPAT20_NAME_SPACE "http://snaught.com/glabels/2.0/"
55 #define COMPAT22_NAME_SPACE "http://snaught.com/glabels/2.2/"
58 /*========================================================*/
60 /*========================================================*/
63 /*========================================================*/
64 /* Private globals. */
65 /*========================================================*/
68 /*========================================================*/
69 /* Private function prototypes. */
70 /*========================================================*/
72 static glLabel *xml_doc_to_label (xmlDocPtr doc,
73 glXMLLabelStatus *status);
75 static glLabel *xml_parse_label (xmlNodePtr root,
76 glXMLLabelStatus *status);
78 static void xml_parse_objects (xmlNodePtr node,
81 static void xml_parse_object_text (xmlNodePtr node,
84 static void xml_parse_object_box (xmlNodePtr node,
87 static void xml_parse_object_ellipse (xmlNodePtr node,
90 static void xml_parse_object_line (xmlNodePtr node,
93 static void xml_parse_object_image (xmlNodePtr node,
96 static void xml_parse_object_barcode (xmlNodePtr node,
99 static void xml_parse_merge_fields (xmlNodePtr node,
102 static void xml_parse_data (xmlNodePtr node,
105 static void xml_parse_pixdata (xmlNodePtr node,
108 static void xml_parse_file_node (xmlNodePtr node,
111 static void xml_parse_toplevel_span (xmlNodePtr node,
112 glLabelObject *object);
114 static void xml_parse_affine_attrs (xmlNodePtr node,
115 glLabelObject *object);
117 static void xml_parse_shadow_attrs (xmlNodePtr node,
118 glLabelObject *object);
120 static xmlDocPtr xml_label_to_doc (glLabel *label,
121 glXMLLabelStatus *status);
123 static void xml_create_objects (xmlNodePtr parent,
127 static void xml_create_object_text (xmlNodePtr parent,
129 glLabelObject *object);
131 static void xml_create_object_box (xmlNodePtr parent,
133 glLabelObject *object);
135 static void xml_create_object_line (xmlNodePtr parent,
137 glLabelObject *object);
139 static void xml_create_object_ellipse(xmlNodePtr parent,
141 glLabelObject *object);
143 static void xml_create_object_image (xmlNodePtr parent,
145 glLabelObject *object);
147 static void xml_create_object_barcode(xmlNodePtr parent,
149 glLabelObject *object);
151 static void xml_create_merge_fields (xmlNodePtr parent,
155 static void xml_create_data (xmlDocPtr doc,
160 static void xml_create_pixdata (xmlNodePtr parent,
165 static void xml_create_file_svg (xmlDocPtr doc,
171 static void xml_create_toplevel_span (xmlNodePtr node,
173 glLabelText *object_text);
175 static void xml_create_affine_attrs (xmlNodePtr node,
176 glLabelObject *object);
178 static void xml_create_shadow_attrs (xmlNodePtr node,
179 glLabelObject *object);
182 /****************************************************************************/
183 /* Open and read label from xml file. */
184 /****************************************************************************/
186 gl_xml_label_open (const gchar *utf8_filename,
187 glXMLLabelStatus *status)
193 gl_debug (DEBUG_XML, "START");
195 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
196 g_return_val_if_fail (filename, NULL);
198 doc = xmlReadFile (filename, NULL, XML_PARSE_HUGE);
200 g_message ("xmlParseFile error");
201 *status = XML_LABEL_ERROR_OPEN_PARSE;
205 xmlXIncludeProcess (doc);
206 xmlReconciliateNs (doc, xmlDocGetRootElement (doc));
208 label = xml_doc_to_label (doc, status);
213 gl_label_set_filename (label, utf8_filename);
214 gl_label_clear_modified (label);
218 gl_debug (DEBUG_XML, "END");
224 /****************************************************************************/
225 /* Read label from xml buffer. */
226 /****************************************************************************/
228 gl_xml_label_open_buffer (const gchar *buffer,
229 glXMLLabelStatus *status)
234 gl_debug (DEBUG_XML, "START");
236 doc = xmlReadDoc ((xmlChar *) buffer, NULL, NULL, XML_PARSE_HUGE);
238 g_message ("xmlParseFile error");
239 *status = XML_LABEL_ERROR_OPEN_PARSE;
243 label = xml_doc_to_label (doc, status);
248 gl_label_clear_modified (label);
251 gl_debug (DEBUG_XML, "END");
257 /*--------------------------------------------------------------------------*/
258 /* PRIVATE. Parse xml doc structure and create label. */
259 /*--------------------------------------------------------------------------*/
261 xml_doc_to_label (xmlDocPtr doc,
262 glXMLLabelStatus *status)
267 gl_debug (DEBUG_XML, "START");
271 *status = XML_LABEL_OK;
273 root = xmlDocGetRootElement (doc);
274 if (!root || !root->name) {
275 g_message ("No document root");
276 *status = XML_LABEL_ERROR_OPEN_PARSE;
280 /* Try compatability mode 0.1 */
281 if (xmlSearchNsByHref (doc, root, (xmlChar *)COMPAT01_NAME_SPACE))
283 g_message ("Importing from glabels 0.1 format");
285 label = NULL; /* TODO */
289 /* Try compatability mode 0.4 */
290 if (xmlSearchNsByHref (doc, root, (xmlChar *)COMPAT04_NAME_SPACE))
292 g_message ("Importing from glabels 0.4 format");
293 label = gl_xml_label_04_parse (root, status);
297 /* Test for current namespaces. */
298 if ( !xmlSearchNsByHref (doc, root, (xmlChar *)COMPAT20_NAME_SPACE) &&
299 !xmlSearchNsByHref (doc, root, (xmlChar *)COMPAT22_NAME_SPACE) &&
300 !xmlSearchNsByHref (doc, root, (xmlChar *)LGL_XML_NAME_SPACE) )
302 g_message ("Unknown glabels Namespace -- Using %s",
306 label = xml_parse_label (root, status);
309 gl_label_set_compression (label, xmlGetDocCompressMode (doc));
312 gl_debug (DEBUG_XML, "END");
318 /*--------------------------------------------------------------------------*/
319 /* PRIVATE. Parse xml root node and create label. */
320 /*--------------------------------------------------------------------------*/
322 xml_parse_label (xmlNodePtr root,
323 glXMLLabelStatus *status)
325 xmlNodePtr child_node;
327 lglTemplate *template;
329 gl_debug (DEBUG_XML, "START");
331 *status = XML_LABEL_OK;
333 if (!lgl_xml_is_node (root, "Glabels-document")) {
334 g_message ("Bad root node = \"%s\"", root->name);
335 *status = XML_LABEL_ERROR_OPEN_PARSE;
339 label = GL_LABEL(gl_label_new ());
341 /* Pass 1, extract data nodes to pre-load cache. */
342 for (child_node = root->xmlChildrenNode; child_node != NULL; child_node = child_node->next) {
343 if (lgl_xml_is_node (child_node, "Data")) {
344 xml_parse_data (child_node, label);
348 /* Pass 2, now extract everything else. */
349 for (child_node = root->xmlChildrenNode;
351 child_node = child_node->next) {
353 if (lgl_xml_is_node (child_node, "Template")) {
354 template = lgl_xml_template_parse_template_node (child_node);
356 g_object_unref (label);
357 *status = XML_LABEL_UNKNOWN_MEDIA;
360 lgl_db_register_template (template);
361 gl_label_set_template (label, template, FALSE);
362 lgl_template_free (template);
363 } else if (lgl_xml_is_node (child_node, "Objects")) {
364 xml_parse_objects (child_node, label);
365 } else if (lgl_xml_is_node (child_node, "Merge")) {
366 xml_parse_merge_fields (child_node, label);
367 } else if (lgl_xml_is_node (child_node, "Data")) {
368 /* Handled in pass 1. */
370 if (!xmlNodeIsText (child_node)) {
371 g_message ("bad node in Document node = \"%s\"",
373 g_object_unref (label);
374 *status = XML_LABEL_ERROR_OPEN_PARSE;
380 gl_debug (DEBUG_XML, "END");
386 /*--------------------------------------------------------------------------*/
387 /* PRIVATE. Parse Objects node. */
388 /*--------------------------------------------------------------------------*/
390 xml_parse_objects (xmlNodePtr node,
393 gboolean rotate_flag;
396 gl_debug (DEBUG_XML, "START");
398 rotate_flag = lgl_xml_get_prop_boolean (node, "rotate", FALSE);
399 gl_label_set_rotate_flag (label, rotate_flag, FALSE);
401 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
403 if (lgl_xml_is_node (child, "Object-text")) {
404 xml_parse_object_text (child, label);
405 } else if (lgl_xml_is_node (child, "Object-box")) {
406 xml_parse_object_box (child, label);
407 } else if (lgl_xml_is_node (child, "Object-ellipse")) {
408 xml_parse_object_ellipse (child, label);
409 } else if (lgl_xml_is_node (child, "Object-line")) {
410 xml_parse_object_line (child, label);
411 } else if (lgl_xml_is_node (child, "Object-image")) {
412 xml_parse_object_image (child, label);
413 } else if (lgl_xml_is_node (child, "Object-barcode")) {
414 xml_parse_object_barcode (child, label);
416 if (!xmlNodeIsText (child)) {
417 g_message ("bad node = \"%s\"", child->name);
423 gl_debug (DEBUG_XML, "END");
427 /*--------------------------------------------------------------------------*/
428 /* PRIVATE. Parse XML Objects->Object-text Node */
429 /*--------------------------------------------------------------------------*/
431 xml_parse_object_text (xmlNodePtr node,
438 PangoAlignment align;
440 gboolean auto_shrink;
443 gl_debug (DEBUG_XML, "START");
445 object = gl_label_text_new (label, FALSE);
448 x = lgl_xml_get_prop_length (node, "x", 0.0);
449 y = lgl_xml_get_prop_length (node, "y", 0.0);
450 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
452 /* implied size attrs */
453 w = lgl_xml_get_prop_length (node, "w", 0);
454 h = lgl_xml_get_prop_length (node, "h", 0);
455 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
458 string = lgl_xml_get_prop_string (node, "justify", NULL);
459 align = gl_str_util_string_to_align (string);
461 gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), align, FALSE);
464 string = lgl_xml_get_prop_string (node, "valign", NULL);
465 valign = gl_str_util_string_to_valign (string);
467 gl_label_object_set_text_valignment (GL_LABEL_OBJECT(object), valign, FALSE);
469 /* auto_shrink attr */
470 auto_shrink = lgl_xml_get_prop_boolean (node, "auto_shrink", FALSE);
471 gl_label_text_set_auto_shrink (GL_LABEL_TEXT(object), auto_shrink, FALSE);
474 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
477 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
479 /* Process children */
480 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
481 if (lgl_xml_is_node (child, "Span")) {
482 xml_parse_toplevel_span (child, GL_LABEL_OBJECT(object));
485 if (!xmlNodeIsText (child)) {
486 g_message ("Unexpected Object-text child: \"%s\"",
492 gl_debug (DEBUG_XML, "END");
496 /*--------------------------------------------------------------------------*/
497 /* PRIVATE. Parse XML Objects->Object-box Node */
498 /*--------------------------------------------------------------------------*/
500 xml_parse_object_box (xmlNodePtr node,
507 glColorNode *line_color_node;
509 glColorNode *fill_color_node;
511 gl_debug (DEBUG_XML, "START");
513 object = gl_label_box_new (label, FALSE);
516 x = lgl_xml_get_prop_length (node, "x", 0.0);
517 y = lgl_xml_get_prop_length (node, "y", 0.0);
518 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
521 w = lgl_xml_get_prop_length (node, "w", 0);
522 h = lgl_xml_get_prop_length (node, "h", 0);
523 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
526 line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
527 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width, FALSE);
529 line_color_node = gl_color_node_new_default ();
530 string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
532 line_color_node->field_flag = TRUE;
533 line_color_node->key = string;
535 line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
537 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node, FALSE);
538 gl_color_node_free (&line_color_node);
542 fill_color_node = gl_color_node_new_default ();
543 string = lgl_xml_get_prop_string (node, "fill_color_field", NULL);
545 fill_color_node->field_flag = TRUE;
546 fill_color_node->key = string;
548 fill_color_node->color = lgl_xml_get_prop_uint (node, "fill_color", 0);
550 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node, FALSE);
551 gl_color_node_free (&fill_color_node);
554 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
557 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
559 gl_debug (DEBUG_XML, "END");
563 /*--------------------------------------------------------------------------*/
564 /* PRIVATE. Parse XML Objects->Object-ellipse Node */
565 /*--------------------------------------------------------------------------*/
567 xml_parse_object_ellipse (xmlNodePtr node,
574 glColorNode *line_color_node;
576 glColorNode *fill_color_node;
578 gl_debug (DEBUG_XML, "START");
580 object = gl_label_ellipse_new (label, FALSE);
583 x = lgl_xml_get_prop_length (node, "x", 0.0);
584 y = lgl_xml_get_prop_length (node, "y", 0.0);
585 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
588 w = lgl_xml_get_prop_length (node, "w", 0);
589 h = lgl_xml_get_prop_length (node, "h", 0);
590 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
593 line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
594 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width, FALSE);
596 line_color_node = gl_color_node_new_default ();
597 string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
599 line_color_node->field_flag = TRUE;
600 line_color_node->key = string;
602 line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
604 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node, FALSE);
605 gl_color_node_free (&line_color_node);
609 fill_color_node = gl_color_node_new_default ();
610 string = lgl_xml_get_prop_string (node, "fill_color_field", NULL);
612 fill_color_node->field_flag = TRUE;
613 fill_color_node->key = string;
615 fill_color_node->color = lgl_xml_get_prop_uint (node, "fill_color", 0);
617 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node, FALSE);
618 gl_color_node_free (&fill_color_node);
621 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
624 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
626 gl_debug (DEBUG_XML, "END");
630 /*--------------------------------------------------------------------------*/
631 /* PRIVATE. Parse XML Objects->Object-line Node */
632 /*--------------------------------------------------------------------------*/
634 xml_parse_object_line (xmlNodePtr node,
641 glColorNode *line_color_node;
644 gl_debug (DEBUG_XML, "START");
646 object = gl_label_line_new (label, FALSE);
649 x = lgl_xml_get_prop_length (node, "x", 0.0);
650 y = lgl_xml_get_prop_length (node, "y", 0.0);
651 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
654 dx = lgl_xml_get_prop_length (node, "dx", 0);
655 dy = lgl_xml_get_prop_length (node, "dy", 0);
656 gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy, FALSE);
659 line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
660 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width, FALSE);
662 line_color_node = gl_color_node_new_default ();
663 string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
665 line_color_node->field_flag = TRUE;
666 line_color_node->key = string;
668 line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
670 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node, FALSE);
671 gl_color_node_free (&line_color_node);
674 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
677 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
679 gl_debug (DEBUG_XML, "END");
683 /*--------------------------------------------------------------------------*/
684 /* PRIVATE. Parse XML Objects->Object-image Node */
685 /*--------------------------------------------------------------------------*/
687 xml_parse_object_image (xmlNodePtr node,
694 glTextNode *filename;
696 gl_debug (DEBUG_XML, "START");
698 object = gl_label_image_new (label, FALSE);
701 x = lgl_xml_get_prop_length (node, "x", 0.0);
702 y = lgl_xml_get_prop_length (node, "y", 0.0);
703 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
705 /* src or field attr */
706 string = lgl_xml_get_prop_string (node, "src", NULL);
708 filename = g_new0 (glTextNode, 1);
709 filename->field_flag = FALSE;
710 filename->data = g_strdup ((gchar *)string);
711 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename, FALSE);
712 gl_text_node_free (&filename);
715 string = lgl_xml_get_prop_string (node, "field", NULL);
717 filename = g_new0 (glTextNode, 1);
718 filename->field_flag = TRUE;
719 filename->data = g_strdup ((gchar *)string);
720 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename, FALSE);
721 gl_text_node_free (&filename);
724 g_message ("Missing Object-image src or field attr");
729 w = lgl_xml_get_prop_length (node, "w", 0);
730 h = lgl_xml_get_prop_length (node, "h", 0);
731 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
734 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
737 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
739 gl_debug (DEBUG_XML, "END");
743 /*--------------------------------------------------------------------------*/
744 /* PRIVATE. Parse XML Objects->Object-barcode Node */
745 /*--------------------------------------------------------------------------*/
747 xml_parse_object_barcode (xmlNodePtr node,
754 glTextNode *text_node;
757 glLabelBarcodeStyle *style;
758 glColorNode *color_node;
760 gl_debug (DEBUG_XML, "START");
762 object = gl_label_barcode_new (label, FALSE);
765 x = lgl_xml_get_prop_length (node, "x", 0.0);
766 y = lgl_xml_get_prop_length (node, "y", 0.0);
767 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y, FALSE);
770 w = lgl_xml_get_prop_length (node, "w", 0);
771 h = lgl_xml_get_prop_length (node, "h", 0);
772 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h, FALSE);
775 style = gl_label_barcode_style_new ();
776 backend_id = lgl_xml_get_prop_string (node, "backend", NULL);
777 id = lgl_xml_get_prop_string (node, "style", NULL);
778 if ( !gl_barcode_backends_is_backend_id_valid (backend_id) )
780 if ( backend_id == NULL )
782 backend_id = g_strdup (gl_barcode_backends_guess_backend_id (id));
787 backend_id = g_strdup ("built-in");
790 gl_label_barcode_style_set_backend_id (style, backend_id);
791 gl_label_barcode_style_set_style_id (style, id);
792 style->text_flag = lgl_xml_get_prop_boolean (node, "text", FALSE);
793 style->checksum_flag = lgl_xml_get_prop_boolean (node, "checksum", TRUE);
794 style->format_digits = lgl_xml_get_prop_uint (node, "format", 10);
795 gl_label_barcode_set_style (GL_LABEL_BARCODE(object), style, FALSE);
798 gl_label_barcode_style_free (style);
800 color_node = gl_color_node_new_default ();
801 string = lgl_xml_get_prop_string (node, "color_field", NULL);
803 color_node->field_flag = TRUE;
804 color_node->key = string;
806 color_node->color = lgl_xml_get_prop_uint (node, "color", 0);
808 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color_node, FALSE);
809 gl_color_node_free (&color_node);
811 /* data or field attr */
812 string = lgl_xml_get_prop_string (node, "data", NULL);
814 text_node = g_new0 (glTextNode, 1);
815 text_node->field_flag = FALSE;
816 text_node->data = string;
817 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node, FALSE);
818 gl_text_node_free (&text_node);
820 string = lgl_xml_get_prop_string (node, "field", NULL);
822 text_node = g_new0 (glTextNode, 1);
823 text_node->field_flag = TRUE;
824 text_node->data = string;
825 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node, FALSE);
826 gl_text_node_free (&text_node);
828 g_message ("Missing Object-barcode data or field attr");
833 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
836 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
838 gl_debug (DEBUG_XML, "END");
842 /*--------------------------------------------------------------------------*/
843 /* PRIVATE. Parse XML merge fields tag. */
844 /*--------------------------------------------------------------------------*/
846 xml_parse_merge_fields (xmlNodePtr node,
852 gl_debug (DEBUG_XML, "START");
854 string = lgl_xml_get_prop_string (node, "type", NULL);
855 merge = gl_merge_new (string);
860 string = lgl_xml_get_prop_string (node, "src", NULL);
861 gl_merge_set_src (merge, string);
864 gl_label_set_merge (label, merge, FALSE);
866 g_object_unref (G_OBJECT(merge));
869 gl_debug (DEBUG_XML, "END");
873 /*--------------------------------------------------------------------------*/
874 /* PRIVATE. Parse XML data tag. */
875 /*--------------------------------------------------------------------------*/
877 xml_parse_data (xmlNodePtr node,
882 gl_debug (DEBUG_XML, "START");
884 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
886 if (lgl_xml_is_node (child, "Pixdata")) {
887 xml_parse_pixdata (child, label);
888 } else if (lgl_xml_is_node (child, "File")) {
889 xml_parse_file_node (child, label);
891 if (!xmlNodeIsText (child)) {
892 g_message ("bad node in Data node = \"%s\"",
898 gl_debug (DEBUG_XML, "END");
902 /*--------------------------------------------------------------------------*/
903 /* PRIVATE. Parse XML embedded Pixdata node. */
904 /*--------------------------------------------------------------------------*/
906 xml_parse_pixdata (xmlNodePtr node,
909 gchar *name, *base64;
915 GHashTable *pixbuf_cache;
917 gl_debug (DEBUG_XML, "START");
919 name = lgl_xml_get_prop_string (node, "name", NULL);
920 base64 = lgl_xml_get_node_content (node);
922 stream = g_base64_decode ((gchar *)base64, &stream_length);
923 pixdata = g_new0 (GdkPixdata, 1);
924 ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
927 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
929 pixbuf_cache = gl_label_get_pixbuf_cache (label);
930 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, (gchar *)name, pixbuf);
939 gl_debug (DEBUG_XML, "END");
943 /*--------------------------------------------------------------------------*/
944 /* PRIVATE. Parse XML embedded File node. */
945 /*--------------------------------------------------------------------------*/
947 xml_parse_file_node (xmlNodePtr node,
950 gchar *name, *format;
952 GHashTable *svg_cache;
954 name = lgl_xml_get_prop_string (node, "name", NULL);
955 format = lgl_xml_get_prop_string (node, "format", NULL);
957 if ( format && (lgl_str_utf8_casecmp (format, "SVG") == 0) )
959 content = lgl_xml_get_node_content (node);
961 svg_cache = gl_label_get_svg_cache (label);
962 gl_svg_cache_add_svg (svg_cache, name, content);
968 g_message ("Unknown embedded file format: \"%s\"", format);
977 /*--------------------------------------------------------------------------*/
978 /* PRIVATE. Parse top-level Span tag. */
979 /*--------------------------------------------------------------------------*/
981 xml_parse_toplevel_span (xmlNodePtr node,
982 glLabelObject *object)
986 PangoWeight font_weight;
987 gboolean font_italic_flag;
988 glColorNode *color_node;
989 gdouble text_line_spacing;
991 GList *lines, *text_nodes;
993 glTextNode *text_node;
996 gl_debug (DEBUG_XML, "START");
998 /* Font family attr */
999 font_family = lgl_xml_get_prop_string (node, "font_family", "Sans");
1000 gl_label_object_set_font_family (object, font_family, FALSE);
1001 g_free (font_family);
1003 /* Font size attr */
1004 font_size = lgl_xml_get_prop_double (node, "font_size", 0.0);
1005 gl_label_object_set_font_size (object, font_size, FALSE);
1007 /* Font weight attr */
1008 string = lgl_xml_get_prop_string (node, "font_weight", NULL);
1009 font_weight = gl_str_util_string_to_weight (string);
1011 gl_label_object_set_font_weight (object, font_weight, FALSE);
1013 /* Font italic flag attr */
1014 font_italic_flag = lgl_xml_get_prop_boolean (node, "font_italic", FALSE);
1015 gl_label_object_set_font_italic_flag (object, font_italic_flag, FALSE);
1017 /* Text color attr */
1018 color_node = gl_color_node_new_default ();
1019 string = lgl_xml_get_prop_string (node, "color_field", NULL);
1021 color_node->field_flag = TRUE;
1022 color_node->key = string;
1024 color_node->color = lgl_xml_get_prop_uint (node, "color", 0);
1026 gl_label_object_set_text_color (object, color_node, FALSE);
1027 gl_color_node_free (&color_node);
1029 /* Text line spacing attr */
1030 text_line_spacing = lgl_xml_get_prop_double (node, "line_spacing", 1.0);
1031 gl_label_object_set_text_line_spacing (object, text_line_spacing, FALSE);
1033 /* Now descend children, and build lines of text nodes */
1036 strip_regex = g_regex_new("\\A\\n\\s*|\\n\\s*\\Z", 0, 0, NULL);
1037 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
1039 if (lgl_xml_is_node (child, "Span")) {
1041 g_message ("Unexpected rich text (not supported, yet!)");
1043 } else if (lgl_xml_is_node (child, "Field")) {
1046 string = lgl_xml_get_prop_string (child, "name", NULL);
1047 text_node = g_new0 (glTextNode, 1);
1048 text_node->field_flag = TRUE;
1049 text_node->data = string;
1050 text_nodes = g_list_append (text_nodes, text_node);
1052 } else if (lgl_xml_is_node (child, "NL")) {
1055 lines = g_list_append (lines, text_nodes);
1058 } else if (xmlNodeIsText (child)) {
1059 gchar *orig_data = lgl_xml_get_node_content (child);
1064 /* Stip out white space before and after */
1065 data = g_regex_replace(strip_regex, orig_data, -1, 0, "", 0, NULL);
1068 text_node = g_new0 (glTextNode, 1);
1069 text_node->field_flag = FALSE;
1070 text_node->data = g_strdup ((gchar *)data);
1071 text_nodes = g_list_append (text_nodes, text_node);
1076 g_message ("Unexpected Span child: \"%s\"", child->name);
1080 g_free (strip_regex);
1082 /* Store last line. */
1083 lines = g_list_append (lines, text_nodes);
1086 gl_label_text_set_lines (GL_LABEL_TEXT(object), lines, FALSE);
1087 gl_text_node_lines_free (&lines);
1089 gl_debug (DEBUG_XML, "END");
1093 /*--------------------------------------------------------------------------*/
1094 /* PRIVATE. Parse affine attributes. */
1095 /*--------------------------------------------------------------------------*/
1097 xml_parse_affine_attrs (xmlNodePtr node,
1098 glLabelObject *object)
1101 cairo_matrix_t matrix;
1103 a[0] = lgl_xml_get_prop_double (node, "a0", 0.0);
1104 a[1] = lgl_xml_get_prop_double (node, "a1", 0.0);
1105 a[2] = lgl_xml_get_prop_double (node, "a2", 0.0);
1106 a[3] = lgl_xml_get_prop_double (node, "a3", 0.0);
1107 a[4] = lgl_xml_get_prop_double (node, "a4", 0.0);
1108 a[5] = lgl_xml_get_prop_double (node, "a5", 0.0);
1110 cairo_matrix_init (&matrix, a[0], a[1], a[2], a[3], a[4], a[5]);
1112 gl_label_object_set_matrix (object, &matrix);
1116 /*--------------------------------------------------------------------------*/
1117 /* PRIVATE. Parse shadow attributes. */
1118 /*--------------------------------------------------------------------------*/
1120 xml_parse_shadow_attrs (xmlNodePtr node,
1121 glLabelObject *object)
1123 gboolean shadow_state;
1126 glColorNode *shadow_color_node;
1127 gdouble shadow_opacity;
1130 shadow_state = lgl_xml_get_prop_boolean (node, "shadow", FALSE);
1131 gl_label_object_set_shadow_state (object, shadow_state, FALSE);
1135 shadow_x = lgl_xml_get_prop_length (node, "shadow_x", 0.0);
1136 shadow_y = lgl_xml_get_prop_length (node, "shadow_y", 0.0);
1137 gl_label_object_set_shadow_offset (object, shadow_x, shadow_y, FALSE);
1139 shadow_color_node = gl_color_node_new_default ();
1140 string = lgl_xml_get_prop_string (node, "shadow_color_field", NULL);
1142 shadow_color_node->field_flag = TRUE;
1143 shadow_color_node->key = string;
1145 shadow_color_node->color = lgl_xml_get_prop_uint (node, "shadow_color", 0);
1147 gl_label_object_set_shadow_color (object, shadow_color_node, FALSE);
1148 gl_color_node_free (&shadow_color_node);
1150 shadow_opacity = lgl_xml_get_prop_double (node, "shadow_opacity", 1.0);
1151 gl_label_object_set_shadow_opacity (object, shadow_opacity, FALSE);
1156 /****************************************************************************/
1157 /* Save label to xml label file. */
1158 /****************************************************************************/
1160 gl_xml_label_save (glLabel *label,
1161 const gchar *utf8_filename,
1162 glXMLLabelStatus *status)
1168 gl_debug (DEBUG_XML, "START");
1170 doc = xml_label_to_doc (label, status);
1172 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
1174 g_message ("Utf8 conversion error.");
1176 xmlSetDocCompressMode (doc, gl_label_get_compression (label));
1177 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
1179 if (xml_ret == -1) {
1181 g_message ("Problem saving xml file.");
1182 *status = XML_LABEL_ERROR_SAVE_FILE;
1186 gl_label_set_filename (label, utf8_filename);
1187 gl_label_clear_modified (label);
1193 gl_debug (DEBUG_XML, "END");
1197 /****************************************************************************/
1198 /* Save label to xml buffer. */
1199 /****************************************************************************/
1201 gl_xml_label_save_buffer (glLabel *label,
1202 glXMLLabelStatus *status)
1208 gl_debug (DEBUG_XML, "START");
1210 doc = xml_label_to_doc (label, status);
1212 xmlDocDumpMemory (doc, &buffer, &size);
1215 gl_label_clear_modified (label);
1217 gl_debug (DEBUG_XML, "END");
1219 return (gchar *)buffer;
1223 /*--------------------------------------------------------------------------*/
1224 /* PRIVATE. Convert label to xml doc structure. */
1225 /*--------------------------------------------------------------------------*/
1227 xml_label_to_doc (glLabel *label,
1228 glXMLLabelStatus *status)
1233 const lglTemplate *template;
1236 gl_debug (DEBUG_XML, "START");
1238 LIBXML_TEST_VERSION;
1240 units = gl_prefs_model_get_units (gl_prefs);
1241 lgl_xml_set_default_units (units);
1243 doc = xmlNewDoc ((xmlChar *)"1.0");
1244 doc->xmlRootNode = xmlNewDocNode (doc, NULL, (xmlChar *)"Glabels-document", NULL);
1246 ns = xmlNewNs (doc->xmlRootNode, (xmlChar *)LGL_XML_NAME_SPACE, NULL);
1247 xmlSetNs (doc->xmlRootNode, ns);
1249 template = gl_label_get_template (label);
1250 lgl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
1252 xml_create_objects (doc->xmlRootNode, ns, label);
1254 merge = gl_label_get_merge (label);
1255 gl_debug (DEBUG_XML, "merge=%p", merge);
1256 if (merge != NULL) {
1257 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1258 g_object_unref (G_OBJECT(merge));
1261 xml_create_data (doc, doc->xmlRootNode, ns, label);
1263 gl_debug (DEBUG_XML, "END");
1265 *status = XML_LABEL_OK;
1270 /*--------------------------------------------------------------------------*/
1271 /* PRIVATE. Add XML Objects Node */
1272 /*--------------------------------------------------------------------------*/
1274 xml_create_objects (xmlNodePtr parent,
1279 gboolean rotate_flag;
1280 const GList *object_list;
1282 glLabelObject *object;
1284 gl_debug (DEBUG_XML, "START");
1286 rotate_flag = gl_label_get_rotate_flag (label);
1287 object_list = gl_label_get_object_list (label);
1289 node = xmlNewChild (parent, ns, (xmlChar *)"Objects", NULL);
1290 lgl_xml_set_prop_string (node, "id", "0");
1291 lgl_xml_set_prop_boolean (node, "rotate", rotate_flag);
1293 for (p = (GList *)object_list; p != NULL; p = p->next) {
1295 object = GL_LABEL_OBJECT(p->data);
1297 if ( GL_IS_LABEL_TEXT(object) ) {
1298 xml_create_object_text (node, ns, object);
1299 } else if ( GL_IS_LABEL_BOX(object) ) {
1300 xml_create_object_box (node, ns, object);
1301 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1302 xml_create_object_ellipse (node, ns, object);
1303 } else if ( GL_IS_LABEL_LINE(object) ) {
1304 xml_create_object_line (node, ns, object);
1305 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1306 xml_create_object_image (node, ns, object);
1307 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1308 xml_create_object_barcode (node, ns, object);
1310 g_message ("Unknown label object");
1315 gl_debug (DEBUG_XML, "END");
1319 /*--------------------------------------------------------------------------*/
1320 /* PRIVATE. Add XML Objects->Object-text Node */
1321 /*--------------------------------------------------------------------------*/
1323 xml_create_object_text (xmlNodePtr parent,
1325 glLabelObject *object)
1330 PangoAlignment align;
1331 glValignment valign;
1332 gboolean auto_shrink;
1334 gl_debug (DEBUG_XML, "START");
1336 node = xmlNewChild (parent, ns, (xmlChar *)"Object-text", NULL);
1338 /* position attrs */
1339 gl_label_object_get_position (object, &x, &y);
1340 lgl_xml_set_prop_length (node, "x", x);
1341 lgl_xml_set_prop_length (node, "y", y);
1344 gl_label_object_get_raw_size ( object, &w, &h);
1345 lgl_xml_set_prop_length (node, "w", w);
1346 lgl_xml_set_prop_length (node, "h", h);
1349 align = gl_label_object_get_text_alignment (object);
1350 lgl_xml_set_prop_string (node, "justify", gl_str_util_align_to_string (align));
1353 valign = gl_label_object_get_text_valignment (object);
1354 lgl_xml_set_prop_string (node, "valign", gl_str_util_valign_to_string (valign));
1356 /* auto_shrink attr */
1357 auto_shrink = gl_label_text_get_auto_shrink (GL_LABEL_TEXT (object));
1358 lgl_xml_set_prop_boolean (node, "auto_shrink", auto_shrink);
1361 xml_create_affine_attrs (node, object);
1364 xml_create_shadow_attrs (node, object);
1367 xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1369 gl_debug (DEBUG_XML, "END");
1373 /*--------------------------------------------------------------------------*/
1374 /* PRIVATE. Add XML Objects->Object-box Node */
1375 /*--------------------------------------------------------------------------*/
1377 xml_create_object_box (xmlNodePtr parent,
1379 glLabelObject *object)
1385 glColorNode *line_color_node;
1386 glColorNode *fill_color_node;
1388 gl_debug (DEBUG_XML, "START");
1390 node = xmlNewChild (parent, ns, (xmlChar *)"Object-box", NULL);
1392 /* position attrs */
1393 gl_label_object_get_position (object, &x, &y);
1394 lgl_xml_set_prop_length (node, "x", x);
1395 lgl_xml_set_prop_length (node, "y", y);
1398 gl_label_object_get_size (object, &w, &h);
1399 lgl_xml_set_prop_length (node, "w", w);
1400 lgl_xml_set_prop_length (node, "h", h);
1403 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1404 lgl_xml_set_prop_length (node, "line_width", line_width);
1406 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1407 if (line_color_node->field_flag)
1409 lgl_xml_set_prop_string (node, "line_color_field", line_color_node->key);
1413 lgl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1415 gl_color_node_free (&line_color_node);
1417 /* fill attrs (color or field) */
1418 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1419 if (fill_color_node->field_flag)
1421 lgl_xml_set_prop_string (node, "fill_color_field", fill_color_node->key);
1425 lgl_xml_set_prop_uint_hex (node, "fill_color", fill_color_node->color);
1427 gl_color_node_free (&fill_color_node);
1430 xml_create_affine_attrs (node, object);
1433 xml_create_shadow_attrs (node, object);
1435 gl_debug (DEBUG_XML, "END");
1439 /*--------------------------------------------------------------------------*/
1440 /* PRIVATE. Add XML Objects->Object-ellipse Node */
1441 /*--------------------------------------------------------------------------*/
1443 xml_create_object_ellipse (xmlNodePtr parent,
1445 glLabelObject *object)
1451 glColorNode *line_color_node;
1452 glColorNode *fill_color_node;
1454 gl_debug (DEBUG_XML, "START");
1456 node = xmlNewChild (parent, ns, (xmlChar *)"Object-ellipse", NULL);
1458 /* position attrs */
1459 gl_label_object_get_position (object, &x, &y);
1460 lgl_xml_set_prop_length (node, "x", x);
1461 lgl_xml_set_prop_length (node, "y", y);
1464 gl_label_object_get_size (object, &w, &h);
1465 lgl_xml_set_prop_length (node, "w", w);
1466 lgl_xml_set_prop_length (node, "h", h);
1469 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1470 lgl_xml_set_prop_length (node, "line_width", line_width);
1472 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1473 if (line_color_node->field_flag)
1475 lgl_xml_set_prop_string (node, "line_color_field", line_color_node->key);
1479 lgl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1481 gl_color_node_free (&line_color_node);
1484 /* fill attrs (color or field) */
1485 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1486 if (fill_color_node->field_flag)
1488 lgl_xml_set_prop_string (node, "fill_color_field", fill_color_node->key);
1492 lgl_xml_set_prop_uint_hex (node, "fill_color", fill_color_node->color);
1494 gl_color_node_free (&fill_color_node);
1497 xml_create_affine_attrs (node, object);
1500 xml_create_shadow_attrs (node, object);
1502 gl_debug (DEBUG_XML, "END");
1506 /*--------------------------------------------------------------------------*/
1507 /* PRIVATE. Add XML Objects->Object-line Node */
1508 /*--------------------------------------------------------------------------*/
1510 xml_create_object_line (xmlNodePtr parent,
1512 glLabelObject *object)
1518 glColorNode *line_color_node;
1520 gl_debug (DEBUG_XML, "START");
1522 node = xmlNewChild (parent, ns, (xmlChar *)"Object-line", NULL);
1524 /* position attrs */
1525 gl_label_object_get_position (object, &x, &y);
1526 lgl_xml_set_prop_length (node, "x", x);
1527 lgl_xml_set_prop_length (node, "y", y);
1530 gl_label_object_get_size (object, &dx, &dy);
1531 lgl_xml_set_prop_length (node, "dx", dx);
1532 lgl_xml_set_prop_length (node, "dy", dy);
1535 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1536 lgl_xml_set_prop_length (node, "line_width", line_width);
1538 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1539 if (line_color_node->field_flag)
1541 lgl_xml_set_prop_string (node, "line_color_field", line_color_node->key);
1545 lgl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1547 gl_color_node_free (&line_color_node);
1551 xml_create_affine_attrs (node, object);
1554 xml_create_shadow_attrs (node, object);
1556 gl_debug (DEBUG_XML, "END");
1560 /*--------------------------------------------------------------------------*/
1561 /* PRIVATE. Add XML Objects->Object-image Node */
1562 /*--------------------------------------------------------------------------*/
1564 xml_create_object_image (xmlNodePtr parent,
1566 glLabelObject *object)
1571 glTextNode *filename;
1573 gl_debug (DEBUG_XML, "START");
1575 node = xmlNewChild (parent, ns, (xmlChar *)"Object-image", NULL);
1577 /* position attrs */
1578 gl_label_object_get_position (object, &x, &y);
1579 lgl_xml_set_prop_length (node, "x", x);
1580 lgl_xml_set_prop_length (node, "y", y);
1583 gl_label_object_get_size (object, &w, &h);
1584 lgl_xml_set_prop_length (node, "w", w);
1585 lgl_xml_set_prop_length (node, "h", h);
1587 /* src OR field attr */
1588 filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1589 if (filename->field_flag) {
1590 lgl_xml_set_prop_string (node, "field", filename->data);
1592 lgl_xml_set_prop_string (node, "src", filename->data);
1594 gl_text_node_free (&filename);
1597 xml_create_affine_attrs (node, object);
1600 xml_create_shadow_attrs (node, object);
1602 gl_debug (DEBUG_XML, "END");
1606 /*--------------------------------------------------------------------------*/
1607 /* PRIVATE. Add XML Objects->Object-barcode Node */
1608 /*--------------------------------------------------------------------------*/
1610 xml_create_object_barcode (xmlNodePtr parent,
1612 glLabelObject *object)
1617 glTextNode *text_node;
1618 glLabelBarcodeStyle *style;
1619 glColorNode *color_node;
1621 gl_debug (DEBUG_XML, "START");
1623 node = xmlNewChild (parent, ns, (xmlChar *)"Object-barcode", NULL);
1625 /* position attrs */
1626 gl_label_object_get_position (object, &x, &y);
1627 lgl_xml_set_prop_length (node, "x", x);
1628 lgl_xml_set_prop_length (node, "y", y);
1631 gl_label_object_get_raw_size (object, &w, &h);
1632 lgl_xml_set_prop_length (node, "w", w);
1633 lgl_xml_set_prop_length (node, "h", h);
1635 /* Barcode properties attrs */
1636 style = gl_label_barcode_get_style (GL_LABEL_BARCODE(object));
1637 lgl_xml_set_prop_string (node, "backend", style->backend_id);
1638 lgl_xml_set_prop_string (node, "style", style->id);
1639 lgl_xml_set_prop_boolean (node, "text", style->text_flag);
1640 lgl_xml_set_prop_boolean (node, "checksum", style->checksum_flag);
1642 color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1643 if (color_node->field_flag)
1645 lgl_xml_set_prop_string (node, "color_field", color_node->key);
1649 lgl_xml_set_prop_uint_hex (node, "color", color_node->color);
1651 gl_color_node_free (&color_node);
1654 /* data OR field attr */
1655 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1656 if (text_node->field_flag) {
1657 lgl_xml_set_prop_string (node, "field", text_node->data);
1658 lgl_xml_set_prop_int (node, "format", style->format_digits);
1660 lgl_xml_set_prop_string (node, "data", text_node->data);
1662 gl_text_node_free (&text_node);
1665 xml_create_affine_attrs (node, object);
1668 xml_create_shadow_attrs (node, object);
1670 gl_label_barcode_style_free (style);
1672 gl_debug (DEBUG_XML, "END");
1676 /*--------------------------------------------------------------------------*/
1677 /* PRIVATE. Add XML Label Merge Fields Node */
1678 /*--------------------------------------------------------------------------*/
1680 xml_create_merge_fields (xmlNodePtr parent,
1688 gl_debug (DEBUG_XML, "START");
1690 merge = gl_label_get_merge (label);
1692 node = xmlNewChild (parent, ns, (xmlChar *)"Merge", NULL);
1694 string = gl_merge_get_name (merge);
1695 lgl_xml_set_prop_string (node, "type", string);
1698 string = gl_merge_get_src (merge);
1699 lgl_xml_set_prop_string (node, "src", string);
1702 g_object_unref (G_OBJECT(merge));
1704 gl_debug (DEBUG_XML, "END");
1708 /*--------------------------------------------------------------------------*/
1709 /* PRIVATE. Add XML Label Data Node */
1710 /*--------------------------------------------------------------------------*/
1712 xml_create_data (xmlDocPtr doc,
1719 GList *name_list, *p;
1721 gl_debug (DEBUG_XML, "START");
1723 node = xmlNewChild (parent, ns, (xmlChar *)"Data", NULL);
1725 cache = gl_label_get_pixbuf_cache (label);
1726 name_list = gl_pixbuf_cache_get_name_list (cache);
1728 for (p = name_list; p != NULL; p=p->next) {
1729 xml_create_pixdata (node, ns, label, p->data);
1732 gl_pixbuf_cache_free_name_list (name_list);
1735 cache = gl_label_get_svg_cache (label);
1736 name_list = gl_svg_cache_get_name_list (cache);
1738 for (p = name_list; p != NULL; p=p->next) {
1739 xml_create_file_svg (doc, node, ns, label, p->data);
1742 gl_pixbuf_cache_free_name_list (name_list);
1745 gl_debug (DEBUG_XML, "END");
1749 /*--------------------------------------------------------------------------*/
1750 /* PRIVATE. Add XML Label Data embedded Pixdata Node */
1751 /*--------------------------------------------------------------------------*/
1753 xml_create_pixdata (xmlNodePtr parent,
1759 GHashTable *pixbuf_cache;
1761 GdkPixdata *pixdata;
1763 guint stream_length;
1766 gl_debug (DEBUG_XML, "START");
1768 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1770 pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, name);
1771 if ( pixbuf != NULL ) {
1773 pixdata = g_new0 (GdkPixdata, 1);
1774 gdk_pixdata_from_pixbuf (pixdata, pixbuf, FALSE);
1775 stream = gdk_pixdata_serialize (pixdata, &stream_length);
1776 base64 = g_base64_encode (stream, stream_length);
1778 node = xmlNewChild (parent, ns, (xmlChar *)"Pixdata", (xmlChar *)base64);
1779 lgl_xml_set_prop_string (node, "name", name);
1780 lgl_xml_set_prop_string (node, "encoding", "Base64");
1782 gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, name);
1790 gl_debug (DEBUG_XML, "END");
1794 /*--------------------------------------------------------------------------*/
1795 /* PRIVATE. Add XML Label Data embedded SVG file Node */
1796 /*--------------------------------------------------------------------------*/
1798 xml_create_file_svg (xmlDocPtr doc,
1805 xmlNodePtr cdata_section_node;
1806 GHashTable *svg_cache;
1809 gl_debug (DEBUG_XML, "START");
1811 svg_cache = gl_label_get_svg_cache (label);
1813 svg_data = gl_svg_cache_get_contents (svg_cache, name);
1814 if ( svg_data != NULL ) {
1816 node = xmlNewChild (parent, ns, (xmlChar *)"File", NULL);
1817 lgl_xml_set_prop_string (node, "name", name);
1818 lgl_xml_set_prop_string (node, "format", "SVG");
1820 cdata_section_node = xmlNewCDataBlock (doc, (xmlChar *)svg_data, strlen (svg_data));
1821 xmlAddChild (node, cdata_section_node);
1827 gl_debug (DEBUG_XML, "END");
1831 /*--------------------------------------------------------------------------*/
1832 /* PRIVATE. Create top-level Span node. */
1833 /*--------------------------------------------------------------------------*/
1835 xml_create_toplevel_span (xmlNodePtr parent,
1837 glLabelText *object_text)
1842 PangoWeight font_weight;
1843 gboolean font_italic_flag;
1844 glColorNode *color_node;
1845 gdouble text_line_spacing;
1846 GList *lines, *p_line, *p_node;
1847 glTextNode *text_node;
1850 node = xmlNewChild (parent, ns, (xmlChar *)"Span", NULL);
1852 /* All span attrs at top level. */
1853 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object_text));
1854 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object_text));
1855 text_line_spacing = gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object_text));
1856 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object_text));
1857 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object_text));
1859 color_node = gl_label_object_get_text_color (GL_LABEL_OBJECT(object_text));
1860 if (color_node->field_flag)
1862 lgl_xml_set_prop_string (node, "color_field", color_node->key);
1866 lgl_xml_set_prop_uint_hex (node, "color", color_node->color);
1868 gl_color_node_free (&color_node);
1870 lgl_xml_set_prop_string (node, "font_family", font_family);
1871 lgl_xml_set_prop_double (node, "font_size", font_size);
1872 lgl_xml_set_prop_string (node, "font_weight", gl_str_util_weight_to_string (font_weight));
1873 lgl_xml_set_prop_boolean (node, "font_italic", font_italic_flag);
1875 lgl_xml_set_prop_double (node, "line_spacing", text_line_spacing);
1877 /* Build children. */
1878 lines = gl_label_text_get_lines (GL_LABEL_TEXT(object_text));
1879 for (p_line = lines; p_line != NULL; p_line = p_line->next) {
1881 for (p_node = (GList *) p_line->data; p_node != NULL;
1882 p_node = p_node->next) {
1883 text_node = (glTextNode *) p_node->data;
1885 if (text_node->field_flag) {
1886 child = xmlNewChild (node, ns, (xmlChar *)"Field", NULL);
1887 lgl_xml_set_prop_string (child, "name", text_node->data);
1889 xmlNodeAddContent (node, (xmlChar *)text_node->data);
1894 if ( p_line->next ) {
1895 child = xmlNewChild (node, ns, (xmlChar *)"NL", NULL);
1900 gl_text_node_lines_free (&lines);
1901 g_free (font_family);
1906 /*--------------------------------------------------------------------------*/
1907 /* PRIVATE. Create affine attributes. */
1908 /*--------------------------------------------------------------------------*/
1910 xml_create_affine_attrs (xmlNodePtr node,
1911 glLabelObject *object)
1913 cairo_matrix_t matrix;
1915 gl_label_object_get_matrix (object, &matrix);
1917 lgl_xml_set_prop_double (node, "a0", matrix.xx);
1918 lgl_xml_set_prop_double (node, "a1", matrix.yx);
1919 lgl_xml_set_prop_double (node, "a2", matrix.xy);
1920 lgl_xml_set_prop_double (node, "a3", matrix.yy);
1921 lgl_xml_set_prop_double (node, "a4", matrix.x0);
1922 lgl_xml_set_prop_double (node, "a5", matrix.y0);
1926 /*--------------------------------------------------------------------------*/
1927 /* PRIVATE. Create shadow attributes. */
1928 /*--------------------------------------------------------------------------*/
1930 xml_create_shadow_attrs (xmlNodePtr node,
1931 glLabelObject *object)
1933 gboolean shadow_state;
1936 glColorNode *shadow_color_node;
1937 gdouble shadow_opacity;
1939 shadow_state = gl_label_object_get_shadow_state (object);
1943 lgl_xml_set_prop_boolean (node, "shadow", shadow_state);
1945 gl_label_object_get_shadow_offset (object, &shadow_x, &shadow_y);
1946 lgl_xml_set_prop_length (node, "shadow_x", shadow_x);
1947 lgl_xml_set_prop_length (node, "shadow_y", shadow_y);
1949 shadow_color_node = gl_label_object_get_shadow_color (object);
1950 if (shadow_color_node->field_flag)
1952 lgl_xml_set_prop_string (node, "shadow_color_field", shadow_color_node->key);
1956 lgl_xml_set_prop_uint_hex (node, "shadow_color", shadow_color_node->color);
1958 gl_color_node_free (&shadow_color_node);
1960 shadow_opacity = gl_label_object_get_shadow_opacity (object);
1961 lgl_xml_set_prop_double (node, "shadow_opacity", shadow_opacity);
1968 * Local Variables: -- emacs
1970 * c-basic-offset: 8 -- emacs
1971 * tab-width: 8 -- emacs
1972 * indent-tabs-mode: nil -- emacs