1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * label.c: GLabels xml label module
8 * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "xml-label.h"
29 #include <glib/gi18n.h>
30 #include <libxml/tree.h>
31 #include <libxml/parser.h>
32 #include <libxml/xinclude.h>
33 #include <gdk-pixbuf/gdk-pixdata.h>
36 #include "label-object.h"
37 #include "label-text.h"
38 #include "label-box.h"
39 #include "label-line.h"
40 #include "label-ellipse.h"
41 #include "label-image.h"
42 #include "label-barcode.h"
44 #include "xml-label-04.h"
45 #include <libglabels/db.h>
46 #include <libglabels/xml-template.h>
47 #include <libglabels/xml.h>
52 /*========================================================*/
53 /* Private macros and constants. */
54 /*========================================================*/
55 #define COMPAT01_NAME_SPACE "http://snaught.com/glabels/0.1/"
56 #define COMPAT04_NAME_SPACE "http://snaught.com/glabels/0.4/"
57 #define COMPAT20_NAME_SPACE "http://snaught.com/glabels/2.0/"
59 /*========================================================*/
61 /*========================================================*/
63 /*========================================================*/
64 /* Private globals. */
65 /*========================================================*/
67 /*========================================================*/
68 /* Private function prototypes. */
69 /*========================================================*/
71 static glLabel *xml_doc_to_label (xmlDocPtr doc,
72 glXMLLabelStatus *status);
74 static glLabel *xml_parse_label (xmlNodePtr root,
75 glXMLLabelStatus *status);
77 static void xml_parse_objects (xmlNodePtr node,
80 static void xml_parse_object_text (xmlNodePtr node,
83 static void xml_parse_object_box (xmlNodePtr node,
86 static void xml_parse_object_ellipse (xmlNodePtr node,
89 static void xml_parse_object_line (xmlNodePtr node,
92 static void xml_parse_object_image (xmlNodePtr node,
95 static void xml_parse_object_barcode (xmlNodePtr node,
98 static void xml_parse_merge_fields (xmlNodePtr node,
101 static void xml_parse_data (xmlNodePtr node,
104 static void xml_parse_pixdata (xmlNodePtr node,
107 static void xml_parse_toplevel_span (xmlNodePtr node,
108 glLabelObject *object);
110 static void xml_parse_affine_attrs (xmlNodePtr node,
111 glLabelObject *object);
113 static void xml_parse_shadow_attrs (xmlNodePtr node,
114 glLabelObject *object);
116 static xmlDocPtr xml_label_to_doc (glLabel *label,
117 glXMLLabelStatus *status);
119 static void xml_create_objects (xmlNodePtr root,
123 static void xml_create_object_text (xmlNodePtr root,
125 glLabelObject *object);
127 static void xml_create_object_box (xmlNodePtr root,
129 glLabelObject *object);
131 static void xml_create_object_line (xmlNodePtr root,
133 glLabelObject *object);
135 static void xml_create_object_ellipse(xmlNodePtr root,
137 glLabelObject *object);
139 static void xml_create_object_image (xmlNodePtr root,
141 glLabelObject *object);
143 static void xml_create_object_barcode(xmlNodePtr root,
145 glLabelObject *object);
147 static void xml_create_merge_fields (xmlNodePtr root,
151 static void xml_create_data (xmlNodePtr root,
155 static void xml_create_pixdata (xmlNodePtr root,
160 static void xml_create_toplevel_span (xmlNodePtr node,
162 glLabelText *object_text);
164 static void xml_create_affine_attrs (xmlNodePtr node,
165 glLabelObject *object);
167 static void xml_create_shadow_attrs (xmlNodePtr node,
168 glLabelObject *object);
171 /****************************************************************************/
172 /* Open and read label from xml file. */
173 /****************************************************************************/
175 gl_xml_label_open (const gchar *utf8_filename,
176 glXMLLabelStatus *status)
182 gl_debug (DEBUG_XML, "START");
184 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
185 g_return_val_if_fail (filename, NULL);
187 #ifndef HAVE_XML_PARSE_HUGE
188 doc = xmlParseFile (filename);
190 doc = xmlReadFile (filename, NULL, XML_PARSE_HUGE);
193 g_message (_("xmlParseFile error"));
194 *status = XML_LABEL_ERROR_OPEN_PARSE;
198 xmlXIncludeProcess (doc);
199 xmlReconciliateNs (doc, xmlDocGetRootElement (doc));
201 label = xml_doc_to_label (doc, status);
206 gl_label_set_filename (label, utf8_filename);
207 gl_label_clear_modified (label);
211 gl_debug (DEBUG_XML, "END");
216 /****************************************************************************/
217 /* Read label from xml buffer. */
218 /****************************************************************************/
220 gl_xml_label_open_buffer (const gchar *buffer,
221 glXMLLabelStatus *status)
226 gl_debug (DEBUG_XML, "START");
228 #ifndef HAVE_XML_PARSE_HUGE
229 doc = xmlParseDoc ((xmlChar *) buffer);
231 doc = xmlReadDoc ((xmlChar *) buffer, NULL, NULL, XML_PARSE_HUGE);
234 g_message (_("xmlParseDoc error"));
235 *status = XML_LABEL_ERROR_OPEN_PARSE;
239 label = xml_doc_to_label (doc, status);
244 gl_label_clear_modified (label);
247 gl_debug (DEBUG_XML, "END");
252 /*--------------------------------------------------------------------------*/
253 /* PRIVATE. Parse xml doc structure and create label. */
254 /*--------------------------------------------------------------------------*/
256 xml_doc_to_label (xmlDocPtr doc,
257 glXMLLabelStatus *status)
262 gl_debug (DEBUG_XML, "START");
266 *status = XML_LABEL_OK;
268 root = xmlDocGetRootElement (doc);
269 if (!root || !root->name) {
270 g_message (_("No document root"));
271 *status = XML_LABEL_ERROR_OPEN_PARSE;
275 /* Try compatability mode 0.1 */
276 if (xmlSearchNsByHref (doc, root, (xmlChar *)COMPAT01_NAME_SPACE))
278 g_message (_("Importing from glabels 0.1 format"));
280 label = NULL; /* TODO */
284 /* Try compatability mode 0.4 */
285 if (xmlSearchNsByHref (doc, root, (xmlChar *)COMPAT04_NAME_SPACE))
287 g_message (_("Importing from glabels 0.4 format"));
288 label = gl_xml_label_04_parse (root, status);
292 /* Test for current namespaces. */
293 if ( !xmlSearchNsByHref (doc, root, (xmlChar *)COMPAT20_NAME_SPACE) &&
294 !xmlSearchNsByHref (doc, root, (xmlChar *)LGL_XML_NAME_SPACE) )
296 g_message (_("Unknown glabels Namespace -- Using %s"),
300 label = xml_parse_label (root, status);
303 gl_label_set_compression (label, xmlGetDocCompressMode (doc));
306 gl_debug (DEBUG_XML, "END");
311 /*--------------------------------------------------------------------------*/
312 /* PRIVATE. Parse xml root node and create label. */
313 /*--------------------------------------------------------------------------*/
315 xml_parse_label (xmlNodePtr root,
316 glXMLLabelStatus *status)
318 xmlNodePtr child_node;
320 lglTemplate *template;
322 gl_debug (DEBUG_XML, "START");
324 *status = XML_LABEL_OK;
326 if (!lgl_xml_is_node (root, "Glabels-document")) {
327 g_message (_("Bad root node = \"%s\""), root->name);
328 *status = XML_LABEL_ERROR_OPEN_PARSE;
332 label = GL_LABEL(gl_label_new ());
334 /* Pass 1, extract data nodes to pre-load cache. */
335 for (child_node = root->xmlChildrenNode; child_node != NULL; child_node = child_node->next) {
336 if (lgl_xml_is_node (child_node, "Data")) {
337 xml_parse_data (child_node, label);
341 /* Pass 2, now extract everything else. */
342 for (child_node = root->xmlChildrenNode;
344 child_node = child_node->next) {
346 if (lgl_xml_is_node (child_node, "Template")) {
347 template = lgl_xml_template_parse_template_node (child_node);
349 g_object_unref (label);
350 *status = XML_LABEL_UNKNOWN_MEDIA;
353 lgl_db_register_template (template);
354 gl_label_set_template (label, template);
355 lgl_template_free (template);
356 } else if (lgl_xml_is_node (child_node, "Objects")) {
357 xml_parse_objects (child_node, label);
358 } else if (lgl_xml_is_node (child_node, "Merge")) {
359 xml_parse_merge_fields (child_node, label);
360 } else if (lgl_xml_is_node (child_node, "Data")) {
361 /* Handled in pass 1. */
363 if (!xmlNodeIsText (child_node)) {
364 g_message (_("bad node in Document node = \"%s\""),
366 g_object_unref (label);
367 *status = XML_LABEL_ERROR_OPEN_PARSE;
373 gl_debug (DEBUG_XML, "END");
378 /*--------------------------------------------------------------------------*/
379 /* PRIVATE. Parse Objects node. */
380 /*--------------------------------------------------------------------------*/
382 xml_parse_objects (xmlNodePtr node,
385 gboolean rotate_flag;
388 gl_debug (DEBUG_XML, "START");
390 rotate_flag = lgl_xml_get_prop_boolean (node, "rotate", FALSE);
391 gl_label_set_rotate_flag (label, rotate_flag);
393 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
395 if (lgl_xml_is_node (child, "Object-text")) {
396 xml_parse_object_text (child, label);
397 } else if (lgl_xml_is_node (child, "Object-box")) {
398 xml_parse_object_box (child, label);
399 } else if (lgl_xml_is_node (child, "Object-ellipse")) {
400 xml_parse_object_ellipse (child, label);
401 } else if (lgl_xml_is_node (child, "Object-line")) {
402 xml_parse_object_line (child, label);
403 } else if (lgl_xml_is_node (child, "Object-image")) {
404 xml_parse_object_image (child, label);
405 } else if (lgl_xml_is_node (child, "Object-barcode")) {
406 xml_parse_object_barcode (child, label);
408 if (!xmlNodeIsText (child)) {
409 g_message (_("bad node = \"%s\""), child->name);
415 gl_debug (DEBUG_XML, "END");
418 /*--------------------------------------------------------------------------*/
419 /* PRIVATE. Parse XML Objects->Object-text Node */
420 /*--------------------------------------------------------------------------*/
422 xml_parse_object_text (xmlNodePtr node,
429 PangoAlignment align;
430 gboolean auto_shrink;
433 gl_debug (DEBUG_XML, "START");
435 object = gl_label_text_new (label);
438 x = lgl_xml_get_prop_length (node, "x", 0.0);
439 y = lgl_xml_get_prop_length (node, "y", 0.0);
440 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
442 /* implied size attrs */
443 w = lgl_xml_get_prop_length (node, "w", 0);
444 h = lgl_xml_get_prop_length (node, "h", 0);
445 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
448 string = lgl_xml_get_prop_string (node, "justify", NULL);
449 align = gl_util_string_to_align (string);
451 gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), align);
453 /* auto_shrink attr */
454 auto_shrink = lgl_xml_get_prop_boolean (node, "auto_shrink", FALSE);
455 gl_label_text_set_auto_shrink (GL_LABEL_TEXT(object), auto_shrink);
458 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
461 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
463 /* Process children */
464 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
465 if (lgl_xml_is_node (child, "Span")) {
466 xml_parse_toplevel_span (child, GL_LABEL_OBJECT(object));
469 if (!xmlNodeIsText (child)) {
470 g_message ("Unexpected Object-text child: \"%s\"",
476 gl_debug (DEBUG_XML, "END");
479 /*--------------------------------------------------------------------------*/
480 /* PRIVATE. Parse XML Objects->Object-box Node */
481 /*--------------------------------------------------------------------------*/
483 xml_parse_object_box (xmlNodePtr node,
490 glColorNode *line_color_node;
492 glColorNode *fill_color_node;
494 gl_debug (DEBUG_XML, "START");
496 object = gl_label_box_new (label);
499 x = lgl_xml_get_prop_length (node, "x", 0.0);
500 y = lgl_xml_get_prop_length (node, "y", 0.0);
501 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
504 w = lgl_xml_get_prop_length (node, "w", 0);
505 h = lgl_xml_get_prop_length (node, "h", 0);
506 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
509 line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
510 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
512 line_color_node = gl_color_node_new_default ();
513 string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
515 line_color_node->field_flag = TRUE;
516 line_color_node->key = string;
518 line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
520 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
521 gl_color_node_free (&line_color_node);
525 fill_color_node = gl_color_node_new_default ();
526 string = lgl_xml_get_prop_string (node, "fill_color_field", NULL);
528 fill_color_node->field_flag = TRUE;
529 fill_color_node->key = string;
531 fill_color_node->color = lgl_xml_get_prop_uint (node, "fill_color", 0);
533 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node);
534 gl_color_node_free (&fill_color_node);
537 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
540 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
542 gl_debug (DEBUG_XML, "END");
545 /*--------------------------------------------------------------------------*/
546 /* PRIVATE. Parse XML Objects->Object-ellipse Node */
547 /*--------------------------------------------------------------------------*/
549 xml_parse_object_ellipse (xmlNodePtr node,
556 glColorNode *line_color_node;
558 glColorNode *fill_color_node;
560 gl_debug (DEBUG_XML, "START");
562 object = gl_label_ellipse_new (label);
565 x = lgl_xml_get_prop_length (node, "x", 0.0);
566 y = lgl_xml_get_prop_length (node, "y", 0.0);
567 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
570 w = lgl_xml_get_prop_length (node, "w", 0);
571 h = lgl_xml_get_prop_length (node, "h", 0);
572 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
575 line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
576 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
578 line_color_node = gl_color_node_new_default ();
579 string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
581 line_color_node->field_flag = TRUE;
582 line_color_node->key = string;
584 line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
586 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
587 gl_color_node_free (&line_color_node);
591 fill_color_node = gl_color_node_new_default ();
592 string = lgl_xml_get_prop_string (node, "fill_color_field", NULL);
594 fill_color_node->field_flag = TRUE;
595 fill_color_node->key = string;
597 fill_color_node->color = lgl_xml_get_prop_uint (node, "fill_color", 0);
599 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node);
600 gl_color_node_free (&fill_color_node);
603 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
606 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
608 gl_debug (DEBUG_XML, "END");
611 /*--------------------------------------------------------------------------*/
612 /* PRIVATE. Parse XML Objects->Object-line Node */
613 /*--------------------------------------------------------------------------*/
615 xml_parse_object_line (xmlNodePtr node,
622 glColorNode *line_color_node;
625 gl_debug (DEBUG_XML, "START");
627 object = gl_label_line_new (label);
630 x = lgl_xml_get_prop_length (node, "x", 0.0);
631 y = lgl_xml_get_prop_length (node, "y", 0.0);
632 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
635 dx = lgl_xml_get_prop_length (node, "dx", 0);
636 dy = lgl_xml_get_prop_length (node, "dy", 0);
637 gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy);
640 line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
641 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
643 line_color_node = gl_color_node_new_default ();
644 string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
646 line_color_node->field_flag = TRUE;
647 line_color_node->key = string;
649 line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
651 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
652 gl_color_node_free (&line_color_node);
655 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
658 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
660 gl_debug (DEBUG_XML, "END");
663 /*--------------------------------------------------------------------------*/
664 /* PRIVATE. Parse XML Objects->Object-image Node */
665 /*--------------------------------------------------------------------------*/
667 xml_parse_object_image (xmlNodePtr node,
674 glTextNode *filename;
676 gl_debug (DEBUG_XML, "START");
678 object = gl_label_image_new (label);
681 x = lgl_xml_get_prop_length (node, "x", 0.0);
682 y = lgl_xml_get_prop_length (node, "y", 0.0);
683 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
685 /* src or field attr */
686 string = lgl_xml_get_prop_string (node, "src", NULL);
688 filename = g_new0 (glTextNode, 1);
689 filename->field_flag = FALSE;
690 filename->data = g_strdup ((gchar *)string);
691 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
692 gl_text_node_free (&filename);
695 string = lgl_xml_get_prop_string (node, "field", NULL);
697 filename = g_new0 (glTextNode, 1);
698 filename->field_flag = TRUE;
699 filename->data = g_strdup ((gchar *)string);
700 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
701 gl_text_node_free (&filename);
704 g_message ("Missing Object-image src or field attr");
709 w = lgl_xml_get_prop_length (node, "w", 0);
710 h = lgl_xml_get_prop_length (node, "h", 0);
711 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
714 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
717 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
719 gl_debug (DEBUG_XML, "END");
722 /*--------------------------------------------------------------------------*/
723 /* PRIVATE. Parse XML Objects->Object-barcode Node */
724 /*--------------------------------------------------------------------------*/
726 xml_parse_object_barcode (xmlNodePtr node,
733 glTextNode *text_node;
736 gboolean checksum_flag;
737 glColorNode *color_node;
740 gl_debug (DEBUG_XML, "START");
742 object = gl_label_barcode_new (label);
745 x = lgl_xml_get_prop_length (node, "x", 0.0);
746 y = lgl_xml_get_prop_length (node, "y", 0.0);
747 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
750 w = lgl_xml_get_prop_length (node, "w", 0);
751 h = lgl_xml_get_prop_length (node, "h", 0);
752 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
755 id = lgl_xml_get_prop_string (node, "style", NULL);
756 text_flag = lgl_xml_get_prop_boolean (node, "text", FALSE);
757 checksum_flag = lgl_xml_get_prop_boolean (node, "checksum", TRUE);
758 format_digits = lgl_xml_get_prop_uint (node, "format", 10);
759 gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
760 (gchar *)id, text_flag, checksum_flag, format_digits);
763 color_node = gl_color_node_new_default ();
764 string = lgl_xml_get_prop_string (node, "color_field", NULL);
766 color_node->field_flag = TRUE;
767 color_node->key = string;
769 color_node->color = lgl_xml_get_prop_uint (node, "color", 0);
771 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color_node);
772 gl_color_node_free (&color_node);
774 /* data or field attr */
775 string = lgl_xml_get_prop_string (node, "data", NULL);
777 text_node = g_new0 (glTextNode, 1);
778 text_node->field_flag = FALSE;
779 text_node->data = string;
780 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
781 gl_text_node_free (&text_node);
783 string = lgl_xml_get_prop_string (node, "field", NULL);
785 text_node = g_new0 (glTextNode, 1);
786 text_node->field_flag = TRUE;
787 text_node->data = string;
788 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
789 gl_text_node_free (&text_node);
791 g_message ("Missing Object-barcode data or field attr");
796 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
799 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
801 gl_debug (DEBUG_XML, "END");
804 /*--------------------------------------------------------------------------*/
805 /* PRIVATE. Parse XML merge fields tag. */
806 /*--------------------------------------------------------------------------*/
808 xml_parse_merge_fields (xmlNodePtr node,
814 gl_debug (DEBUG_XML, "START");
816 string = lgl_xml_get_prop_string (node, "type", NULL);
817 merge = gl_merge_new (string);
822 string = lgl_xml_get_prop_string (node, "src", NULL);
823 gl_merge_set_src (merge, string);
826 gl_label_set_merge (label, merge);
828 g_object_unref (G_OBJECT(merge));
831 gl_debug (DEBUG_XML, "END");
834 /*--------------------------------------------------------------------------*/
835 /* PRIVATE. Parse XML data tag. */
836 /*--------------------------------------------------------------------------*/
838 xml_parse_data (xmlNodePtr node,
843 gl_debug (DEBUG_XML, "START");
845 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
847 if (lgl_xml_is_node (child, "Pixdata")) {
848 xml_parse_pixdata (child, label);
850 if (!xmlNodeIsText (child)) {
851 g_message (_("bad node in Data node = \"%s\""),
857 gl_debug (DEBUG_XML, "END");
860 /*--------------------------------------------------------------------------*/
861 /* PRIVATE. Parse XML pixbuf data tag. */
862 /*--------------------------------------------------------------------------*/
864 xml_parse_pixdata (xmlNodePtr node,
867 gchar *name, *base64;
873 GHashTable *pixbuf_cache;
875 gl_debug (DEBUG_XML, "START");
877 name = lgl_xml_get_prop_string (node, "name", NULL);
878 base64 = lgl_xml_get_node_content (node);
880 stream = gl_base64_decode ((gchar *)base64, &stream_length);
881 pixdata = g_new0 (GdkPixdata, 1);
882 ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
885 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
887 pixbuf_cache = gl_label_get_pixbuf_cache (label);
888 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, (gchar *)name, pixbuf);
897 gl_debug (DEBUG_XML, "END");
900 /*--------------------------------------------------------------------------*/
901 /* PRIVATE. Parse top-level Span tag. */
902 /*--------------------------------------------------------------------------*/
904 xml_parse_toplevel_span (xmlNodePtr node,
905 glLabelObject *object)
909 PangoWeight font_weight;
910 gboolean font_italic_flag;
911 glColorNode *color_node;
912 gdouble text_line_spacing;
914 GList *lines, *text_nodes;
916 glTextNode *text_node;
918 gl_debug (DEBUG_XML, "START");
920 /* Font family attr */
921 font_family = lgl_xml_get_prop_string (node, "font_family", "Sans");
922 gl_label_object_set_font_family (object, font_family);
923 g_free (font_family);
926 font_size = lgl_xml_get_prop_double (node, "font_size", 0.0);
927 gl_label_object_set_font_size (object, font_size);
929 /* Font weight attr */
930 string = lgl_xml_get_prop_string (node, "font_weight", NULL);
931 font_weight = gl_util_string_to_weight (string);
933 gl_label_object_set_font_weight (object, font_weight);
935 /* Font italic flag attr */
936 font_italic_flag = lgl_xml_get_prop_boolean (node, "font_italic", FALSE);
937 gl_label_object_set_font_italic_flag (object, font_italic_flag);
939 /* Text color attr */
940 color_node = gl_color_node_new_default ();
941 string = lgl_xml_get_prop_string (node, "color_field", NULL);
943 color_node->field_flag = TRUE;
944 color_node->key = string;
946 color_node->color = lgl_xml_get_prop_uint (node, "color", 0);
948 gl_label_object_set_text_color (object, color_node);
949 gl_color_node_free (&color_node);
952 /* Text line spacing attr */
953 text_line_spacing = lgl_xml_get_prop_double (node, "line_spacing", 1.0);
954 gl_label_object_set_text_line_spacing (object, text_line_spacing);
956 /* Now descend children, and build lines of text nodes */
959 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
961 if (xmlNodeIsText (child)) {
962 gchar *data = lgl_xml_get_node_content (child);
964 /* Hack: if the first char is LF, it's an xml formatting string */
965 if (data[0] != '\n') {
967 text_node = g_new0 (glTextNode, 1);
968 text_node->field_flag = FALSE;
969 text_node->data = g_strdup ((gchar *)data);
970 text_nodes = g_list_append (text_nodes, text_node);
974 } else if (lgl_xml_is_node (child, "Span")) {
976 g_message ("Unexpected rich text (not supported, yet!)");
978 } else if (lgl_xml_is_node (child, "Field")) {
981 string = lgl_xml_get_prop_string (child, "name", NULL);
982 text_node = g_new0 (glTextNode, 1);
983 text_node->field_flag = TRUE;
984 text_node->data = string;
985 text_nodes = g_list_append (text_nodes, text_node);
987 } else if (lgl_xml_is_node (child, "NL")) {
990 lines = g_list_append (lines, text_nodes);
994 g_message ("Unexpected Span child: \"%s\"", child->name);
999 /* Store last line. */
1000 lines = g_list_append (lines, text_nodes);
1003 gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
1004 gl_text_node_lines_free (&lines);
1006 gl_debug (DEBUG_XML, "END");
1009 /*--------------------------------------------------------------------------*/
1010 /* PRIVATE. Parse affine attributes. */
1011 /*--------------------------------------------------------------------------*/
1013 xml_parse_affine_attrs (xmlNodePtr node,
1014 glLabelObject *object)
1017 cairo_matrix_t matrix;
1019 a[0] = lgl_xml_get_prop_double (node, "a0", 0.0);
1020 a[1] = lgl_xml_get_prop_double (node, "a1", 0.0);
1021 a[2] = lgl_xml_get_prop_double (node, "a2", 0.0);
1022 a[3] = lgl_xml_get_prop_double (node, "a3", 0.0);
1023 a[4] = lgl_xml_get_prop_double (node, "a4", 0.0);
1024 a[5] = lgl_xml_get_prop_double (node, "a5", 0.0);
1026 cairo_matrix_init (&matrix, a[0], a[1], a[2], a[3], a[4], a[5]);
1028 gl_label_object_set_matrix (object, &matrix);
1031 /*--------------------------------------------------------------------------*/
1032 /* PRIVATE. Parse shadow attributes. */
1033 /*--------------------------------------------------------------------------*/
1035 xml_parse_shadow_attrs (xmlNodePtr node,
1036 glLabelObject *object)
1038 gboolean shadow_state;
1041 glColorNode *shadow_color_node;
1042 gdouble shadow_opacity;
1045 shadow_state = lgl_xml_get_prop_boolean (node, "shadow", FALSE);
1046 gl_label_object_set_shadow_state (object, shadow_state);
1050 shadow_x = lgl_xml_get_prop_length (node, "shadow_x", 0.0);
1051 shadow_y = lgl_xml_get_prop_length (node, "shadow_y", 0.0);
1052 gl_label_object_set_shadow_offset (object, shadow_x, shadow_y);
1054 shadow_color_node = gl_color_node_new_default ();
1055 string = lgl_xml_get_prop_string (node, "shadow_color_field", NULL);
1057 shadow_color_node->field_flag = TRUE;
1058 shadow_color_node->key = string;
1060 shadow_color_node->color = lgl_xml_get_prop_uint (node, "shadow_color", 0);
1062 gl_label_object_set_shadow_color (object, shadow_color_node);
1063 gl_color_node_free (&shadow_color_node);
1065 shadow_opacity = lgl_xml_get_prop_double (node, "shadow_opacity", 1.0);
1066 gl_label_object_set_shadow_opacity (object, shadow_opacity);
1070 /****************************************************************************/
1071 /* Save label to xml label file. */
1072 /****************************************************************************/
1074 gl_xml_label_save (glLabel *label,
1075 const gchar *utf8_filename,
1076 glXMLLabelStatus *status)
1082 gl_debug (DEBUG_XML, "START");
1084 doc = xml_label_to_doc (label, status);
1086 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
1088 g_message (_("Utf8 conversion error."));
1090 xmlSetDocCompressMode (doc, gl_label_get_compression (label));
1091 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
1093 if (xml_ret == -1) {
1095 g_message (_("Problem saving xml file."));
1096 *status = XML_LABEL_ERROR_SAVE_FILE;
1100 gl_label_set_filename (label, utf8_filename);
1101 gl_label_clear_modified (label);
1107 gl_debug (DEBUG_XML, "END");
1110 /****************************************************************************/
1111 /* Save label to xml buffer. */
1112 /****************************************************************************/
1114 gl_xml_label_save_buffer (glLabel *label,
1115 glXMLLabelStatus *status)
1121 gl_debug (DEBUG_XML, "START");
1123 doc = xml_label_to_doc (label, status);
1125 xmlDocDumpMemory (doc, &buffer, &size);
1128 gl_label_clear_modified (label);
1130 gl_debug (DEBUG_XML, "END");
1132 return (gchar *)buffer;
1135 /*--------------------------------------------------------------------------*/
1136 /* PRIVATE. Convert label to xml doc structure. */
1137 /*--------------------------------------------------------------------------*/
1139 xml_label_to_doc (glLabel *label,
1140 glXMLLabelStatus *status)
1146 gl_debug (DEBUG_XML, "START");
1148 LIBXML_TEST_VERSION;
1150 doc = xmlNewDoc ((xmlChar *)"1.0");
1151 doc->xmlRootNode = xmlNewDocNode (doc, NULL, (xmlChar *)"Glabels-document", NULL);
1153 ns = xmlNewNs (doc->xmlRootNode, (xmlChar *)LGL_XML_NAME_SPACE, NULL);
1154 xmlSetNs (doc->xmlRootNode, ns);
1156 lgl_xml_template_create_template_node (label->template, doc->xmlRootNode, ns);
1158 xml_create_objects (doc->xmlRootNode, ns, label);
1160 merge = gl_label_get_merge (label);
1161 gl_debug (DEBUG_XML, "merge=%p", merge);
1162 if (merge != NULL) {
1163 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1164 g_object_unref (G_OBJECT(merge));
1167 xml_create_data (doc->xmlRootNode, ns, label);
1169 gl_debug (DEBUG_XML, "END");
1171 *status = XML_LABEL_OK;
1175 /*--------------------------------------------------------------------------*/
1176 /* PRIVATE. Add XML Objects Node */
1177 /*--------------------------------------------------------------------------*/
1179 xml_create_objects (xmlNodePtr root,
1185 glLabelObject *object;
1187 gl_debug (DEBUG_XML, "START");
1189 node = xmlNewChild (root, ns, (xmlChar *)"Objects", NULL);
1190 lgl_xml_set_prop_string (node, "id", "0");
1191 lgl_xml_set_prop_boolean (node, "rotate", label->rotate_flag);
1193 for (p = label->objects; p != NULL; p = p->next) {
1195 object = GL_LABEL_OBJECT(p->data);
1197 if ( GL_IS_LABEL_TEXT(object) ) {
1198 xml_create_object_text (node, ns, object);
1199 } else if ( GL_IS_LABEL_BOX(object) ) {
1200 xml_create_object_box (node, ns, object);
1201 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1202 xml_create_object_ellipse (node, ns, object);
1203 } else if ( GL_IS_LABEL_LINE(object) ) {
1204 xml_create_object_line (node, ns, object);
1205 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1206 xml_create_object_image (node, ns, object);
1207 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1208 xml_create_object_barcode (node, ns, object);
1210 g_message ("Unknown label object");
1215 gl_debug (DEBUG_XML, "END");
1218 /*--------------------------------------------------------------------------*/
1219 /* PRIVATE. Add XML Objects->Object-text Node */
1220 /*--------------------------------------------------------------------------*/
1222 xml_create_object_text (xmlNodePtr root,
1224 glLabelObject *object)
1229 PangoAlignment align;
1230 gboolean auto_shrink;
1232 gl_debug (DEBUG_XML, "START");
1234 node = xmlNewChild (root, ns, (xmlChar *)"Object-text", NULL);
1236 /* position attrs */
1237 gl_label_object_get_position (object, &x, &y);
1238 lgl_xml_set_prop_length (node, "x", x);
1239 lgl_xml_set_prop_length (node, "y", y);
1242 gl_label_object_get_raw_size ( object, &w, &h);
1243 lgl_xml_set_prop_length (node, "w", w);
1244 lgl_xml_set_prop_length (node, "h", h);
1247 align = gl_label_object_get_text_alignment (object);
1248 lgl_xml_set_prop_string (node, "justify", gl_util_align_to_string (align));
1250 /* auto_shrink attr */
1251 auto_shrink = gl_label_text_get_auto_shrink (GL_LABEL_TEXT (object));
1252 lgl_xml_set_prop_boolean (node, "auto_shrink", auto_shrink);
1255 xml_create_affine_attrs (node, object);
1258 xml_create_shadow_attrs (node, object);
1261 xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1263 gl_debug (DEBUG_XML, "END");
1266 /*--------------------------------------------------------------------------*/
1267 /* PRIVATE. Add XML Objects->Object-box Node */
1268 /*--------------------------------------------------------------------------*/
1270 xml_create_object_box (xmlNodePtr root,
1272 glLabelObject *object)
1278 glColorNode *line_color_node;
1279 glColorNode *fill_color_node;
1281 gl_debug (DEBUG_XML, "START");
1283 node = xmlNewChild (root, ns, (xmlChar *)"Object-box", NULL);
1285 /* position attrs */
1286 gl_label_object_get_position (object, &x, &y);
1287 lgl_xml_set_prop_length (node, "x", x);
1288 lgl_xml_set_prop_length (node, "y", y);
1291 gl_label_object_get_size (object, &w, &h);
1292 lgl_xml_set_prop_length (node, "w", w);
1293 lgl_xml_set_prop_length (node, "h", h);
1296 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1297 lgl_xml_set_prop_length (node, "line_width", line_width);
1299 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1300 if (line_color_node->field_flag)
1302 lgl_xml_set_prop_string (node, "line_color_field", line_color_node->key);
1306 lgl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1308 gl_color_node_free (&line_color_node);
1310 /* fill attrs (color or field) */
1311 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1312 if (fill_color_node->field_flag)
1314 lgl_xml_set_prop_string (node, "fill_color_field", fill_color_node->key);
1318 lgl_xml_set_prop_uint_hex (node, "fill_color", fill_color_node->color);
1320 gl_color_node_free (&fill_color_node);
1323 xml_create_affine_attrs (node, object);
1326 xml_create_shadow_attrs (node, object);
1328 gl_debug (DEBUG_XML, "END");
1331 /*--------------------------------------------------------------------------*/
1332 /* PRIVATE. Add XML Objects->Object-ellipse Node */
1333 /*--------------------------------------------------------------------------*/
1335 xml_create_object_ellipse (xmlNodePtr root,
1337 glLabelObject *object)
1343 glColorNode *line_color_node;
1344 glColorNode *fill_color_node;
1346 gl_debug (DEBUG_XML, "START");
1348 node = xmlNewChild (root, ns, (xmlChar *)"Object-ellipse", NULL);
1350 /* position attrs */
1351 gl_label_object_get_position (object, &x, &y);
1352 lgl_xml_set_prop_length (node, "x", x);
1353 lgl_xml_set_prop_length (node, "y", y);
1356 gl_label_object_get_size (object, &w, &h);
1357 lgl_xml_set_prop_length (node, "w", w);
1358 lgl_xml_set_prop_length (node, "h", h);
1361 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1362 lgl_xml_set_prop_length (node, "line_width", line_width);
1364 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1365 if (line_color_node->field_flag)
1367 lgl_xml_set_prop_string (node, "line_color_field", line_color_node->key);
1371 lgl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1373 gl_color_node_free (&line_color_node);
1376 /* fill attrs (color or field) */
1377 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1378 if (fill_color_node->field_flag)
1380 lgl_xml_set_prop_string (node, "fill_color_field", fill_color_node->key);
1384 lgl_xml_set_prop_uint_hex (node, "fill_color", fill_color_node->color);
1386 gl_color_node_free (&fill_color_node);
1389 xml_create_affine_attrs (node, object);
1392 xml_create_shadow_attrs (node, object);
1394 gl_debug (DEBUG_XML, "END");
1397 /*--------------------------------------------------------------------------*/
1398 /* PRIVATE. Add XML Objects->Object-line Node */
1399 /*--------------------------------------------------------------------------*/
1401 xml_create_object_line (xmlNodePtr root,
1403 glLabelObject *object)
1409 glColorNode *line_color_node;
1411 gl_debug (DEBUG_XML, "START");
1413 node = xmlNewChild (root, ns, (xmlChar *)"Object-line", NULL);
1415 /* position attrs */
1416 gl_label_object_get_position (object, &x, &y);
1417 lgl_xml_set_prop_length (node, "x", x);
1418 lgl_xml_set_prop_length (node, "y", y);
1421 gl_label_object_get_size (object, &dx, &dy);
1422 lgl_xml_set_prop_length (node, "dx", dx);
1423 lgl_xml_set_prop_length (node, "dy", dy);
1426 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1427 lgl_xml_set_prop_length (node, "line_width", line_width);
1429 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1430 if (line_color_node->field_flag)
1432 lgl_xml_set_prop_string (node, "line_color_field", line_color_node->key);
1436 lgl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1438 gl_color_node_free (&line_color_node);
1442 xml_create_affine_attrs (node, object);
1445 xml_create_shadow_attrs (node, object);
1447 gl_debug (DEBUG_XML, "END");
1450 /*--------------------------------------------------------------------------*/
1451 /* PRIVATE. Add XML Objects->Object-image Node */
1452 /*--------------------------------------------------------------------------*/
1454 xml_create_object_image (xmlNodePtr root,
1456 glLabelObject *object)
1461 glTextNode *filename;
1463 gl_debug (DEBUG_XML, "START");
1465 node = xmlNewChild (root, ns, (xmlChar *)"Object-image", NULL);
1467 /* position attrs */
1468 gl_label_object_get_position (object, &x, &y);
1469 lgl_xml_set_prop_length (node, "x", x);
1470 lgl_xml_set_prop_length (node, "y", y);
1473 gl_label_object_get_size (object, &w, &h);
1474 lgl_xml_set_prop_length (node, "w", w);
1475 lgl_xml_set_prop_length (node, "h", h);
1477 /* src OR field attr */
1478 filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1479 if (filename->field_flag) {
1480 lgl_xml_set_prop_string (node, "field", filename->data);
1482 lgl_xml_set_prop_string (node, "src", filename->data);
1484 gl_text_node_free (&filename);
1487 xml_create_affine_attrs (node, object);
1490 xml_create_shadow_attrs (node, object);
1492 gl_debug (DEBUG_XML, "END");
1495 /*--------------------------------------------------------------------------*/
1496 /* PRIVATE. Add XML Objects->Object-barcode Node */
1497 /*--------------------------------------------------------------------------*/
1499 xml_create_object_barcode (xmlNodePtr root,
1501 glLabelObject *object)
1506 glTextNode *text_node;
1509 gboolean checksum_flag;
1510 glColorNode *color_node;
1511 guint format_digits;
1513 gl_debug (DEBUG_XML, "START");
1515 node = xmlNewChild (root, ns, (xmlChar *)"Object-barcode", NULL);
1517 /* position attrs */
1518 gl_label_object_get_position (object, &x, &y);
1519 lgl_xml_set_prop_length (node, "x", x);
1520 lgl_xml_set_prop_length (node, "y", y);
1523 gl_label_object_get_raw_size (object, &w, &h);
1524 lgl_xml_set_prop_length (node, "w", w);
1525 lgl_xml_set_prop_length (node, "h", h);
1527 /* Barcode properties attrs */
1528 gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1529 &id, &text_flag, &checksum_flag, &format_digits);
1530 lgl_xml_set_prop_string (node, "style", id);
1531 lgl_xml_set_prop_boolean (node, "text", text_flag);
1532 lgl_xml_set_prop_boolean (node, "checksum", checksum_flag);
1536 color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1537 if (color_node->field_flag)
1539 lgl_xml_set_prop_string (node, "color_field", color_node->key);
1543 lgl_xml_set_prop_uint_hex (node, "color", color_node->color);
1545 gl_color_node_free (&color_node);
1548 /* data OR field attr */
1549 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1550 if (text_node->field_flag) {
1551 lgl_xml_set_prop_string (node, "field", text_node->data);
1552 lgl_xml_set_prop_int (node, "format", format_digits);
1554 lgl_xml_set_prop_string (node, "data", text_node->data);
1556 gl_text_node_free (&text_node);
1559 xml_create_affine_attrs (node, object);
1562 xml_create_shadow_attrs (node, object);
1564 gl_debug (DEBUG_XML, "END");
1567 /*--------------------------------------------------------------------------*/
1568 /* PRIVATE. Add XML Label Merge Fields Node */
1569 /*--------------------------------------------------------------------------*/
1571 xml_create_merge_fields (xmlNodePtr root,
1579 gl_debug (DEBUG_XML, "START");
1581 merge = gl_label_get_merge (label);
1583 node = xmlNewChild (root, ns, (xmlChar *)"Merge", NULL);
1585 string = gl_merge_get_name (merge);
1586 lgl_xml_set_prop_string (node, "type", string);
1589 string = gl_merge_get_src (merge);
1590 lgl_xml_set_prop_string (node, "src", string);
1593 g_object_unref (G_OBJECT(merge));
1595 gl_debug (DEBUG_XML, "END");
1598 /*--------------------------------------------------------------------------*/
1599 /* PRIVATE. Add XML Label Data Node */
1600 /*--------------------------------------------------------------------------*/
1602 xml_create_data (xmlNodePtr root,
1607 GList *name_list, *p;
1608 GHashTable *pixbuf_cache;
1610 gl_debug (DEBUG_XML, "START");
1612 node = xmlNewChild (root, ns, (xmlChar *)"Data", NULL);
1614 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1615 name_list = gl_pixbuf_cache_get_name_list (pixbuf_cache);
1617 for (p = name_list; p != NULL; p=p->next) {
1618 xml_create_pixdata (node, ns, label, p->data);
1621 gl_pixbuf_cache_free_name_list (name_list);
1624 gl_debug (DEBUG_XML, "END");
1627 /*--------------------------------------------------------------------------*/
1628 /* PRIVATE. Add XML Label Data Pixbuf Node */
1629 /*--------------------------------------------------------------------------*/
1631 xml_create_pixdata (xmlNodePtr root,
1637 GHashTable *pixbuf_cache;
1639 GdkPixdata *pixdata;
1641 guint stream_length;
1644 gl_debug (DEBUG_XML, "START");
1646 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1648 pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, name);
1649 if ( pixbuf != NULL ) {
1651 pixdata = g_new0 (GdkPixdata, 1);
1652 gdk_pixdata_from_pixbuf (pixdata, pixbuf, FALSE);
1653 stream = gdk_pixdata_serialize (pixdata, &stream_length);
1654 base64 = gl_base64_encode (stream, stream_length);
1656 node = xmlNewChild (root, ns, (xmlChar *)"Pixdata", (xmlChar *)base64);
1657 lgl_xml_set_prop_string (node, "name", name);
1658 lgl_xml_set_prop_string (node, "encoding", "Base64");
1660 gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, name);
1668 gl_debug (DEBUG_XML, "END");
1671 /*--------------------------------------------------------------------------*/
1672 /* PRIVATE. Create top-level Span node. */
1673 /*--------------------------------------------------------------------------*/
1675 xml_create_toplevel_span (xmlNodePtr root,
1677 glLabelText *object_text)
1682 PangoWeight font_weight;
1683 gboolean font_italic_flag;
1684 glColorNode *color_node;
1685 PangoAlignment align;
1686 gdouble text_line_spacing;
1687 GList *lines, *p_line, *p_node;
1688 glTextNode *text_node;
1691 node = xmlNewChild (root, ns, (xmlChar *)"Span", NULL);
1693 /* All span attrs at top level. */
1694 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object_text));
1695 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object_text));
1696 text_line_spacing = gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object_text));
1697 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object_text));
1698 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object_text));
1700 color_node = gl_label_object_get_text_color (GL_LABEL_OBJECT(object_text));
1701 if (color_node->field_flag)
1703 lgl_xml_set_prop_string (node, "color_field", color_node->key);
1707 lgl_xml_set_prop_uint_hex (node, "color", color_node->color);
1709 gl_color_node_free (&color_node);
1711 align = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object_text));
1712 lgl_xml_set_prop_string (node, "font_family", font_family);
1713 lgl_xml_set_prop_double (node, "font_size", font_size);
1714 lgl_xml_set_prop_string (node, "font_weight", gl_util_weight_to_string (font_weight));
1715 lgl_xml_set_prop_boolean (node, "font_italic", font_italic_flag);
1717 lgl_xml_set_prop_double (node, "line_spacing", text_line_spacing);
1719 /* Build children. */
1720 lines = gl_label_text_get_lines (GL_LABEL_TEXT(object_text));
1721 for (p_line = lines; p_line != NULL; p_line = p_line->next) {
1723 for (p_node = (GList *) p_line->data; p_node != NULL;
1724 p_node = p_node->next) {
1725 text_node = (glTextNode *) p_node->data;
1727 if (text_node->field_flag) {
1728 child = xmlNewChild (node, ns, (xmlChar *)"Field", NULL);
1729 lgl_xml_set_prop_string (child, "name", text_node->data);
1731 xmlNodeAddContent (node, (xmlChar *)text_node->data);
1736 if ( p_line->next ) {
1737 child = xmlNewChild (node, ns, (xmlChar *)"NL", NULL);
1742 gl_text_node_lines_free (&lines);
1743 g_free (font_family);
1747 /*--------------------------------------------------------------------------*/
1748 /* PRIVATE. Create affine attributes. */
1749 /*--------------------------------------------------------------------------*/
1751 xml_create_affine_attrs (xmlNodePtr node,
1752 glLabelObject *object)
1754 cairo_matrix_t matrix;
1756 gl_label_object_get_matrix (object, &matrix);
1758 lgl_xml_set_prop_double (node, "a0", matrix.xx);
1759 lgl_xml_set_prop_double (node, "a1", matrix.yx);
1760 lgl_xml_set_prop_double (node, "a2", matrix.xy);
1761 lgl_xml_set_prop_double (node, "a3", matrix.yy);
1762 lgl_xml_set_prop_double (node, "a4", matrix.x0);
1763 lgl_xml_set_prop_double (node, "a5", matrix.y0);
1766 /*--------------------------------------------------------------------------*/
1767 /* PRIVATE. Create shadow attributes. */
1768 /*--------------------------------------------------------------------------*/
1770 xml_create_shadow_attrs (xmlNodePtr node,
1771 glLabelObject *object)
1773 gboolean shadow_state;
1776 glColorNode *shadow_color_node;
1777 gdouble shadow_opacity;
1779 shadow_state = gl_label_object_get_shadow_state (object);
1783 lgl_xml_set_prop_boolean (node, "shadow", shadow_state);
1785 gl_label_object_get_shadow_offset (object, &shadow_x, &shadow_y);
1786 lgl_xml_set_prop_length (node, "shadow_x", shadow_x);
1787 lgl_xml_set_prop_length (node, "shadow_y", shadow_y);
1789 shadow_color_node = gl_label_object_get_shadow_color (object);
1790 if (shadow_color_node->field_flag)
1792 lgl_xml_set_prop_string (node, "shadow_color_field", shadow_color_node->key);
1796 lgl_xml_set_prop_uint_hex (node, "shadow_color", shadow_color_node->color);
1798 gl_color_node_free (&shadow_color_node);
1800 shadow_opacity = gl_label_object_get_shadow_opacity (object);
1801 lgl_xml_set_prop_double (node, "shadow_opacity", shadow_opacity);