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 <glib/gbase64.h>
31 #include <libxml/tree.h>
32 #include <libxml/parser.h>
33 #include <libxml/xinclude.h>
34 #include <gdk-pixbuf/gdk-pixdata.h>
37 #include "label-object.h"
38 #include "label-text.h"
39 #include "label-box.h"
40 #include "label-line.h"
41 #include "label-ellipse.h"
42 #include "label-image.h"
43 #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 doc = xmlReadFile (filename, NULL, XML_PARSE_HUGE);
189 g_message (_("xmlParseFile error"));
190 *status = XML_LABEL_ERROR_OPEN_PARSE;
194 xmlXIncludeProcess (doc);
195 xmlReconciliateNs (doc, xmlDocGetRootElement (doc));
197 label = xml_doc_to_label (doc, status);
202 gl_label_set_filename (label, utf8_filename);
203 gl_label_clear_modified (label);
207 gl_debug (DEBUG_XML, "END");
212 /****************************************************************************/
213 /* Read label from xml buffer. */
214 /****************************************************************************/
216 gl_xml_label_open_buffer (const gchar *buffer,
217 glXMLLabelStatus *status)
222 gl_debug (DEBUG_XML, "START");
224 doc = xmlReadDoc ((xmlChar *) buffer, NULL, NULL, XML_PARSE_HUGE);
226 g_message (_("xmlParseFile error"));
227 *status = XML_LABEL_ERROR_OPEN_PARSE;
231 label = xml_doc_to_label (doc, status);
236 gl_label_clear_modified (label);
239 gl_debug (DEBUG_XML, "END");
244 /*--------------------------------------------------------------------------*/
245 /* PRIVATE. Parse xml doc structure and create label. */
246 /*--------------------------------------------------------------------------*/
248 xml_doc_to_label (xmlDocPtr doc,
249 glXMLLabelStatus *status)
254 gl_debug (DEBUG_XML, "START");
258 *status = XML_LABEL_OK;
260 root = xmlDocGetRootElement (doc);
261 if (!root || !root->name) {
262 g_message (_("No document root"));
263 *status = XML_LABEL_ERROR_OPEN_PARSE;
267 /* Try compatability mode 0.1 */
268 if (xmlSearchNsByHref (doc, root, (xmlChar *)COMPAT01_NAME_SPACE))
270 g_message (_("Importing from glabels 0.1 format"));
272 label = NULL; /* TODO */
276 /* Try compatability mode 0.4 */
277 if (xmlSearchNsByHref (doc, root, (xmlChar *)COMPAT04_NAME_SPACE))
279 g_message (_("Importing from glabels 0.4 format"));
280 label = gl_xml_label_04_parse (root, status);
284 /* Test for current namespaces. */
285 if ( !xmlSearchNsByHref (doc, root, (xmlChar *)COMPAT20_NAME_SPACE) &&
286 !xmlSearchNsByHref (doc, root, (xmlChar *)LGL_XML_NAME_SPACE) )
288 g_message (_("Unknown glabels Namespace -- Using %s"),
292 label = xml_parse_label (root, status);
295 gl_label_set_compression (label, xmlGetDocCompressMode (doc));
298 gl_debug (DEBUG_XML, "END");
303 /*--------------------------------------------------------------------------*/
304 /* PRIVATE. Parse xml root node and create label. */
305 /*--------------------------------------------------------------------------*/
307 xml_parse_label (xmlNodePtr root,
308 glXMLLabelStatus *status)
310 xmlNodePtr child_node;
312 lglTemplate *template;
314 gl_debug (DEBUG_XML, "START");
316 *status = XML_LABEL_OK;
318 if (!lgl_xml_is_node (root, "Glabels-document")) {
319 g_message (_("Bad root node = \"%s\""), root->name);
320 *status = XML_LABEL_ERROR_OPEN_PARSE;
324 label = GL_LABEL(gl_label_new ());
326 /* Pass 1, extract data nodes to pre-load cache. */
327 for (child_node = root->xmlChildrenNode; child_node != NULL; child_node = child_node->next) {
328 if (lgl_xml_is_node (child_node, "Data")) {
329 xml_parse_data (child_node, label);
333 /* Pass 2, now extract everything else. */
334 for (child_node = root->xmlChildrenNode;
336 child_node = child_node->next) {
338 if (lgl_xml_is_node (child_node, "Template")) {
339 template = lgl_xml_template_parse_template_node (child_node);
341 g_object_unref (label);
342 *status = XML_LABEL_UNKNOWN_MEDIA;
345 lgl_db_register_template (template);
346 gl_label_set_template (label, template);
347 lgl_template_free (template);
348 } else if (lgl_xml_is_node (child_node, "Objects")) {
349 xml_parse_objects (child_node, label);
350 } else if (lgl_xml_is_node (child_node, "Merge")) {
351 xml_parse_merge_fields (child_node, label);
352 } else if (lgl_xml_is_node (child_node, "Data")) {
353 /* Handled in pass 1. */
355 if (!xmlNodeIsText (child_node)) {
356 g_message (_("bad node in Document node = \"%s\""),
358 g_object_unref (label);
359 *status = XML_LABEL_ERROR_OPEN_PARSE;
365 gl_debug (DEBUG_XML, "END");
370 /*--------------------------------------------------------------------------*/
371 /* PRIVATE. Parse Objects node. */
372 /*--------------------------------------------------------------------------*/
374 xml_parse_objects (xmlNodePtr node,
377 gboolean rotate_flag;
380 gl_debug (DEBUG_XML, "START");
382 rotate_flag = lgl_xml_get_prop_boolean (node, "rotate", FALSE);
383 gl_label_set_rotate_flag (label, rotate_flag);
385 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
387 if (lgl_xml_is_node (child, "Object-text")) {
388 xml_parse_object_text (child, label);
389 } else if (lgl_xml_is_node (child, "Object-box")) {
390 xml_parse_object_box (child, label);
391 } else if (lgl_xml_is_node (child, "Object-ellipse")) {
392 xml_parse_object_ellipse (child, label);
393 } else if (lgl_xml_is_node (child, "Object-line")) {
394 xml_parse_object_line (child, label);
395 } else if (lgl_xml_is_node (child, "Object-image")) {
396 xml_parse_object_image (child, label);
397 } else if (lgl_xml_is_node (child, "Object-barcode")) {
398 xml_parse_object_barcode (child, label);
400 if (!xmlNodeIsText (child)) {
401 g_message (_("bad node = \"%s\""), child->name);
407 gl_debug (DEBUG_XML, "END");
410 /*--------------------------------------------------------------------------*/
411 /* PRIVATE. Parse XML Objects->Object-text Node */
412 /*--------------------------------------------------------------------------*/
414 xml_parse_object_text (xmlNodePtr node,
421 PangoAlignment align;
422 gboolean auto_shrink;
425 gl_debug (DEBUG_XML, "START");
427 object = gl_label_text_new (label);
430 x = lgl_xml_get_prop_length (node, "x", 0.0);
431 y = lgl_xml_get_prop_length (node, "y", 0.0);
432 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
434 /* implied size attrs */
435 w = lgl_xml_get_prop_length (node, "w", 0);
436 h = lgl_xml_get_prop_length (node, "h", 0);
437 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
440 string = lgl_xml_get_prop_string (node, "justify", NULL);
441 align = gl_util_string_to_align (string);
443 gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), align);
445 /* auto_shrink attr */
446 auto_shrink = lgl_xml_get_prop_boolean (node, "auto_shrink", FALSE);
447 gl_label_text_set_auto_shrink (GL_LABEL_TEXT(object), auto_shrink);
450 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
453 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
455 /* Process children */
456 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
457 if (lgl_xml_is_node (child, "Span")) {
458 xml_parse_toplevel_span (child, GL_LABEL_OBJECT(object));
461 if (!xmlNodeIsText (child)) {
462 g_message ("Unexpected Object-text child: \"%s\"",
468 gl_debug (DEBUG_XML, "END");
471 /*--------------------------------------------------------------------------*/
472 /* PRIVATE. Parse XML Objects->Object-box Node */
473 /*--------------------------------------------------------------------------*/
475 xml_parse_object_box (xmlNodePtr node,
482 glColorNode *line_color_node;
484 glColorNode *fill_color_node;
486 gl_debug (DEBUG_XML, "START");
488 object = gl_label_box_new (label);
491 x = lgl_xml_get_prop_length (node, "x", 0.0);
492 y = lgl_xml_get_prop_length (node, "y", 0.0);
493 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
496 w = lgl_xml_get_prop_length (node, "w", 0);
497 h = lgl_xml_get_prop_length (node, "h", 0);
498 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
501 line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
502 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
504 line_color_node = gl_color_node_new_default ();
505 string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
507 line_color_node->field_flag = TRUE;
508 line_color_node->key = string;
510 line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
512 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
513 gl_color_node_free (&line_color_node);
517 fill_color_node = gl_color_node_new_default ();
518 string = lgl_xml_get_prop_string (node, "fill_color_field", NULL);
520 fill_color_node->field_flag = TRUE;
521 fill_color_node->key = string;
523 fill_color_node->color = lgl_xml_get_prop_uint (node, "fill_color", 0);
525 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node);
526 gl_color_node_free (&fill_color_node);
529 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
532 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
534 gl_debug (DEBUG_XML, "END");
537 /*--------------------------------------------------------------------------*/
538 /* PRIVATE. Parse XML Objects->Object-ellipse Node */
539 /*--------------------------------------------------------------------------*/
541 xml_parse_object_ellipse (xmlNodePtr node,
548 glColorNode *line_color_node;
550 glColorNode *fill_color_node;
552 gl_debug (DEBUG_XML, "START");
554 object = gl_label_ellipse_new (label);
557 x = lgl_xml_get_prop_length (node, "x", 0.0);
558 y = lgl_xml_get_prop_length (node, "y", 0.0);
559 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
562 w = lgl_xml_get_prop_length (node, "w", 0);
563 h = lgl_xml_get_prop_length (node, "h", 0);
564 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
567 line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
568 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
570 line_color_node = gl_color_node_new_default ();
571 string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
573 line_color_node->field_flag = TRUE;
574 line_color_node->key = string;
576 line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
578 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
579 gl_color_node_free (&line_color_node);
583 fill_color_node = gl_color_node_new_default ();
584 string = lgl_xml_get_prop_string (node, "fill_color_field", NULL);
586 fill_color_node->field_flag = TRUE;
587 fill_color_node->key = string;
589 fill_color_node->color = lgl_xml_get_prop_uint (node, "fill_color", 0);
591 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node);
592 gl_color_node_free (&fill_color_node);
595 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
598 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
600 gl_debug (DEBUG_XML, "END");
603 /*--------------------------------------------------------------------------*/
604 /* PRIVATE. Parse XML Objects->Object-line Node */
605 /*--------------------------------------------------------------------------*/
607 xml_parse_object_line (xmlNodePtr node,
614 glColorNode *line_color_node;
617 gl_debug (DEBUG_XML, "START");
619 object = gl_label_line_new (label);
622 x = lgl_xml_get_prop_length (node, "x", 0.0);
623 y = lgl_xml_get_prop_length (node, "y", 0.0);
624 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
627 dx = lgl_xml_get_prop_length (node, "dx", 0);
628 dy = lgl_xml_get_prop_length (node, "dy", 0);
629 gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy);
632 line_width = lgl_xml_get_prop_length (node, "line_width", 1.0);
633 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
635 line_color_node = gl_color_node_new_default ();
636 string = lgl_xml_get_prop_string (node, "line_color_field", NULL);
638 line_color_node->field_flag = TRUE;
639 line_color_node->key = string;
641 line_color_node->color = lgl_xml_get_prop_uint (node, "line_color", 0);
643 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
644 gl_color_node_free (&line_color_node);
647 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
650 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
652 gl_debug (DEBUG_XML, "END");
655 /*--------------------------------------------------------------------------*/
656 /* PRIVATE. Parse XML Objects->Object-image Node */
657 /*--------------------------------------------------------------------------*/
659 xml_parse_object_image (xmlNodePtr node,
666 glTextNode *filename;
668 gl_debug (DEBUG_XML, "START");
670 object = gl_label_image_new (label);
673 x = lgl_xml_get_prop_length (node, "x", 0.0);
674 y = lgl_xml_get_prop_length (node, "y", 0.0);
675 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
677 /* src or field attr */
678 string = lgl_xml_get_prop_string (node, "src", NULL);
680 filename = g_new0 (glTextNode, 1);
681 filename->field_flag = FALSE;
682 filename->data = g_strdup ((gchar *)string);
683 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
684 gl_text_node_free (&filename);
687 string = lgl_xml_get_prop_string (node, "field", NULL);
689 filename = g_new0 (glTextNode, 1);
690 filename->field_flag = TRUE;
691 filename->data = g_strdup ((gchar *)string);
692 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
693 gl_text_node_free (&filename);
696 g_message ("Missing Object-image src or field attr");
701 w = lgl_xml_get_prop_length (node, "w", 0);
702 h = lgl_xml_get_prop_length (node, "h", 0);
703 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
706 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
709 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
711 gl_debug (DEBUG_XML, "END");
714 /*--------------------------------------------------------------------------*/
715 /* PRIVATE. Parse XML Objects->Object-barcode Node */
716 /*--------------------------------------------------------------------------*/
718 xml_parse_object_barcode (xmlNodePtr node,
725 glTextNode *text_node;
728 gboolean checksum_flag;
729 glColorNode *color_node;
732 gl_debug (DEBUG_XML, "START");
734 object = gl_label_barcode_new (label);
737 x = lgl_xml_get_prop_length (node, "x", 0.0);
738 y = lgl_xml_get_prop_length (node, "y", 0.0);
739 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
742 w = lgl_xml_get_prop_length (node, "w", 0);
743 h = lgl_xml_get_prop_length (node, "h", 0);
744 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
747 id = lgl_xml_get_prop_string (node, "style", NULL);
748 text_flag = lgl_xml_get_prop_boolean (node, "text", FALSE);
749 checksum_flag = lgl_xml_get_prop_boolean (node, "checksum", TRUE);
750 format_digits = lgl_xml_get_prop_uint (node, "format", 10);
751 gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
752 (gchar *)id, text_flag, checksum_flag, format_digits);
755 color_node = gl_color_node_new_default ();
756 string = lgl_xml_get_prop_string (node, "color_field", NULL);
758 color_node->field_flag = TRUE;
759 color_node->key = string;
761 color_node->color = lgl_xml_get_prop_uint (node, "color", 0);
763 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color_node);
764 gl_color_node_free (&color_node);
766 /* data or field attr */
767 string = lgl_xml_get_prop_string (node, "data", NULL);
769 text_node = g_new0 (glTextNode, 1);
770 text_node->field_flag = FALSE;
771 text_node->data = string;
772 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
773 gl_text_node_free (&text_node);
775 string = lgl_xml_get_prop_string (node, "field", NULL);
777 text_node = g_new0 (glTextNode, 1);
778 text_node->field_flag = TRUE;
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 g_message ("Missing Object-barcode data or field attr");
788 xml_parse_affine_attrs (node, GL_LABEL_OBJECT(object));
791 xml_parse_shadow_attrs (node, GL_LABEL_OBJECT(object));
793 gl_debug (DEBUG_XML, "END");
796 /*--------------------------------------------------------------------------*/
797 /* PRIVATE. Parse XML merge fields tag. */
798 /*--------------------------------------------------------------------------*/
800 xml_parse_merge_fields (xmlNodePtr node,
806 gl_debug (DEBUG_XML, "START");
808 string = lgl_xml_get_prop_string (node, "type", NULL);
809 merge = gl_merge_new (string);
812 string = lgl_xml_get_prop_string (node, "src", NULL);
813 gl_merge_set_src (merge, string);
816 gl_label_set_merge (label, merge);
818 g_object_unref (G_OBJECT(merge));
820 gl_debug (DEBUG_XML, "END");
823 /*--------------------------------------------------------------------------*/
824 /* PRIVATE. Parse XML data tag. */
825 /*--------------------------------------------------------------------------*/
827 xml_parse_data (xmlNodePtr node,
832 gl_debug (DEBUG_XML, "START");
834 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
836 if (lgl_xml_is_node (child, "Pixdata")) {
837 xml_parse_pixdata (child, label);
839 if (!xmlNodeIsText (child)) {
840 g_message (_("bad node in Data node = \"%s\""),
846 gl_debug (DEBUG_XML, "END");
849 /*--------------------------------------------------------------------------*/
850 /* PRIVATE. Parse XML pixbuf data tag. */
851 /*--------------------------------------------------------------------------*/
853 xml_parse_pixdata (xmlNodePtr node,
856 gchar *name, *base64;
862 GHashTable *pixbuf_cache;
864 gl_debug (DEBUG_XML, "START");
866 name = lgl_xml_get_prop_string (node, "name", NULL);
867 base64 = lgl_xml_get_node_content (node);
869 stream = g_base64_decode ((gchar *)base64, &stream_length);
870 pixdata = g_new0 (GdkPixdata, 1);
871 ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
874 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
876 pixbuf_cache = gl_label_get_pixbuf_cache (label);
877 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, (gchar *)name, pixbuf);
886 gl_debug (DEBUG_XML, "END");
889 /*--------------------------------------------------------------------------*/
890 /* PRIVATE. Parse top-level Span tag. */
891 /*--------------------------------------------------------------------------*/
893 xml_parse_toplevel_span (xmlNodePtr node,
894 glLabelObject *object)
898 PangoWeight font_weight;
899 gboolean font_italic_flag;
900 glColorNode *color_node;
901 gdouble text_line_spacing;
903 GList *lines, *text_nodes;
905 glTextNode *text_node;
907 gl_debug (DEBUG_XML, "START");
909 /* Font family attr */
910 font_family = lgl_xml_get_prop_string (node, "font_family", "Sans");
911 gl_label_object_set_font_family (object, font_family);
912 g_free (font_family);
915 font_size = lgl_xml_get_prop_double (node, "font_size", 0.0);
916 gl_label_object_set_font_size (object, font_size);
918 /* Font weight attr */
919 string = lgl_xml_get_prop_string (node, "font_weight", NULL);
920 font_weight = gl_util_string_to_weight (string);
922 gl_label_object_set_font_weight (object, font_weight);
924 /* Font italic flag attr */
925 font_italic_flag = lgl_xml_get_prop_boolean (node, "font_italic", FALSE);
926 gl_label_object_set_font_italic_flag (object, font_italic_flag);
928 /* Text color attr */
929 color_node = gl_color_node_new_default ();
930 string = lgl_xml_get_prop_string (node, "color_field", NULL);
932 color_node->field_flag = TRUE;
933 color_node->key = string;
935 color_node->color = lgl_xml_get_prop_uint (node, "color", 0);
937 gl_label_object_set_text_color (object, color_node);
938 gl_color_node_free (&color_node);
941 /* Text line spacing attr */
942 text_line_spacing = lgl_xml_get_prop_double (node, "line_spacing", 1.0);
943 gl_label_object_set_text_line_spacing (object, text_line_spacing);
945 /* Now descend children, and build lines of text nodes */
948 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
950 if (xmlNodeIsText (child)) {
951 gchar *data = lgl_xml_get_node_content (child);
953 /* Hack: if the first char is LF, it's an xml formatting string */
954 if (data[0] != '\n') {
956 text_node = g_new0 (glTextNode, 1);
957 text_node->field_flag = FALSE;
958 text_node->data = g_strdup ((gchar *)data);
959 text_nodes = g_list_append (text_nodes, text_node);
963 } else if (lgl_xml_is_node (child, "Span")) {
965 g_message ("Unexpected rich text (not supported, yet!)");
967 } else if (lgl_xml_is_node (child, "Field")) {
970 string = lgl_xml_get_prop_string (child, "name", NULL);
971 text_node = g_new0 (glTextNode, 1);
972 text_node->field_flag = TRUE;
973 text_node->data = string;
974 text_nodes = g_list_append (text_nodes, text_node);
976 } else if (lgl_xml_is_node (child, "NL")) {
979 lines = g_list_append (lines, text_nodes);
983 g_message ("Unexpected Span child: \"%s\"", child->name);
988 /* Store last line. */
989 lines = g_list_append (lines, text_nodes);
992 gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
993 gl_text_node_lines_free (&lines);
995 gl_debug (DEBUG_XML, "END");
998 /*--------------------------------------------------------------------------*/
999 /* PRIVATE. Parse affine attributes. */
1000 /*--------------------------------------------------------------------------*/
1002 xml_parse_affine_attrs (xmlNodePtr node,
1003 glLabelObject *object)
1006 cairo_matrix_t matrix;
1008 a[0] = lgl_xml_get_prop_double (node, "a0", 0.0);
1009 a[1] = lgl_xml_get_prop_double (node, "a1", 0.0);
1010 a[2] = lgl_xml_get_prop_double (node, "a2", 0.0);
1011 a[3] = lgl_xml_get_prop_double (node, "a3", 0.0);
1012 a[4] = lgl_xml_get_prop_double (node, "a4", 0.0);
1013 a[5] = lgl_xml_get_prop_double (node, "a5", 0.0);
1015 cairo_matrix_init (&matrix, a[0], a[1], a[2], a[3], a[4], a[5]);
1017 gl_label_object_set_matrix (object, &matrix);
1020 /*--------------------------------------------------------------------------*/
1021 /* PRIVATE. Parse shadow attributes. */
1022 /*--------------------------------------------------------------------------*/
1024 xml_parse_shadow_attrs (xmlNodePtr node,
1025 glLabelObject *object)
1027 gboolean shadow_state;
1030 glColorNode *shadow_color_node;
1031 gdouble shadow_opacity;
1034 shadow_state = lgl_xml_get_prop_boolean (node, "shadow", FALSE);
1035 gl_label_object_set_shadow_state (object, shadow_state);
1039 shadow_x = lgl_xml_get_prop_length (node, "shadow_x", 0.0);
1040 shadow_y = lgl_xml_get_prop_length (node, "shadow_y", 0.0);
1041 gl_label_object_set_shadow_offset (object, shadow_x, shadow_y);
1043 shadow_color_node = gl_color_node_new_default ();
1044 string = lgl_xml_get_prop_string (node, "shadow_color_field", NULL);
1046 shadow_color_node->field_flag = TRUE;
1047 shadow_color_node->key = string;
1049 shadow_color_node->color = lgl_xml_get_prop_uint (node, "shadow_color", 0);
1051 gl_label_object_set_shadow_color (object, shadow_color_node);
1052 gl_color_node_free (&shadow_color_node);
1054 shadow_opacity = lgl_xml_get_prop_double (node, "shadow_opacity", 1.0);
1055 gl_label_object_set_shadow_opacity (object, shadow_opacity);
1059 /****************************************************************************/
1060 /* Save label to xml label file. */
1061 /****************************************************************************/
1063 gl_xml_label_save (glLabel *label,
1064 const gchar *utf8_filename,
1065 glXMLLabelStatus *status)
1071 gl_debug (DEBUG_XML, "START");
1073 doc = xml_label_to_doc (label, status);
1075 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
1077 g_message (_("Utf8 conversion error."));
1079 xmlSetDocCompressMode (doc, gl_label_get_compression (label));
1080 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
1082 if (xml_ret == -1) {
1084 g_message (_("Problem saving xml file."));
1085 *status = XML_LABEL_ERROR_SAVE_FILE;
1089 gl_label_set_filename (label, utf8_filename);
1090 gl_label_clear_modified (label);
1096 gl_debug (DEBUG_XML, "END");
1099 /****************************************************************************/
1100 /* Save label to xml buffer. */
1101 /****************************************************************************/
1103 gl_xml_label_save_buffer (glLabel *label,
1104 glXMLLabelStatus *status)
1110 gl_debug (DEBUG_XML, "START");
1112 doc = xml_label_to_doc (label, status);
1114 xmlDocDumpMemory (doc, &buffer, &size);
1117 gl_label_clear_modified (label);
1119 gl_debug (DEBUG_XML, "END");
1121 return (gchar *)buffer;
1124 /*--------------------------------------------------------------------------*/
1125 /* PRIVATE. Convert label to xml doc structure. */
1126 /*--------------------------------------------------------------------------*/
1128 xml_label_to_doc (glLabel *label,
1129 glXMLLabelStatus *status)
1135 gl_debug (DEBUG_XML, "START");
1137 LIBXML_TEST_VERSION;
1139 doc = xmlNewDoc ((xmlChar *)"1.0");
1140 doc->xmlRootNode = xmlNewDocNode (doc, NULL, (xmlChar *)"Glabels-document", NULL);
1142 ns = xmlNewNs (doc->xmlRootNode, (xmlChar *)LGL_XML_NAME_SPACE, NULL);
1143 xmlSetNs (doc->xmlRootNode, ns);
1145 lgl_xml_template_create_template_node (label->template, doc->xmlRootNode, ns);
1147 xml_create_objects (doc->xmlRootNode, ns, label);
1149 merge = gl_label_get_merge (label);
1150 gl_debug (DEBUG_XML, "merge=%p", merge);
1151 if (merge != NULL) {
1152 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1153 g_object_unref (G_OBJECT(merge));
1156 xml_create_data (doc->xmlRootNode, ns, label);
1158 gl_debug (DEBUG_XML, "END");
1160 *status = XML_LABEL_OK;
1164 /*--------------------------------------------------------------------------*/
1165 /* PRIVATE. Add XML Objects Node */
1166 /*--------------------------------------------------------------------------*/
1168 xml_create_objects (xmlNodePtr root,
1174 glLabelObject *object;
1176 gl_debug (DEBUG_XML, "START");
1178 node = xmlNewChild (root, ns, (xmlChar *)"Objects", NULL);
1179 lgl_xml_set_prop_string (node, "id", "0");
1180 lgl_xml_set_prop_boolean (node, "rotate", label->rotate_flag);
1182 for (p = label->objects; p != NULL; p = p->next) {
1184 object = GL_LABEL_OBJECT(p->data);
1186 if ( GL_IS_LABEL_TEXT(object) ) {
1187 xml_create_object_text (node, ns, object);
1188 } else if ( GL_IS_LABEL_BOX(object) ) {
1189 xml_create_object_box (node, ns, object);
1190 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1191 xml_create_object_ellipse (node, ns, object);
1192 } else if ( GL_IS_LABEL_LINE(object) ) {
1193 xml_create_object_line (node, ns, object);
1194 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1195 xml_create_object_image (node, ns, object);
1196 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1197 xml_create_object_barcode (node, ns, object);
1199 g_message ("Unknown label object");
1204 gl_debug (DEBUG_XML, "END");
1207 /*--------------------------------------------------------------------------*/
1208 /* PRIVATE. Add XML Objects->Object-text Node */
1209 /*--------------------------------------------------------------------------*/
1211 xml_create_object_text (xmlNodePtr root,
1213 glLabelObject *object)
1218 PangoAlignment align;
1219 gboolean auto_shrink;
1221 gl_debug (DEBUG_XML, "START");
1223 node = xmlNewChild (root, ns, (xmlChar *)"Object-text", NULL);
1225 /* position attrs */
1226 gl_label_object_get_position (object, &x, &y);
1227 lgl_xml_set_prop_length (node, "x", x);
1228 lgl_xml_set_prop_length (node, "y", y);
1231 gl_label_object_get_raw_size ( object, &w, &h);
1232 lgl_xml_set_prop_length (node, "w", w);
1233 lgl_xml_set_prop_length (node, "h", h);
1236 align = gl_label_object_get_text_alignment (object);
1237 lgl_xml_set_prop_string (node, "justify", gl_util_align_to_string (align));
1239 /* auto_shrink attr */
1240 auto_shrink = gl_label_text_get_auto_shrink (GL_LABEL_TEXT (object));
1241 lgl_xml_set_prop_boolean (node, "auto_shrink", auto_shrink);
1244 xml_create_affine_attrs (node, object);
1247 xml_create_shadow_attrs (node, object);
1250 xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1252 gl_debug (DEBUG_XML, "END");
1255 /*--------------------------------------------------------------------------*/
1256 /* PRIVATE. Add XML Objects->Object-box Node */
1257 /*--------------------------------------------------------------------------*/
1259 xml_create_object_box (xmlNodePtr root,
1261 glLabelObject *object)
1267 glColorNode *line_color_node;
1268 glColorNode *fill_color_node;
1270 gl_debug (DEBUG_XML, "START");
1272 node = xmlNewChild (root, ns, (xmlChar *)"Object-box", NULL);
1274 /* position attrs */
1275 gl_label_object_get_position (object, &x, &y);
1276 lgl_xml_set_prop_length (node, "x", x);
1277 lgl_xml_set_prop_length (node, "y", y);
1280 gl_label_object_get_size (object, &w, &h);
1281 lgl_xml_set_prop_length (node, "w", w);
1282 lgl_xml_set_prop_length (node, "h", h);
1285 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1286 lgl_xml_set_prop_length (node, "line_width", line_width);
1288 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1289 if (line_color_node->field_flag)
1291 lgl_xml_set_prop_string (node, "line_color_field", line_color_node->key);
1295 lgl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1297 gl_color_node_free (&line_color_node);
1299 /* fill attrs (color or field) */
1300 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1301 if (fill_color_node->field_flag)
1303 lgl_xml_set_prop_string (node, "fill_color_field", fill_color_node->key);
1307 lgl_xml_set_prop_uint_hex (node, "fill_color", fill_color_node->color);
1309 gl_color_node_free (&fill_color_node);
1312 xml_create_affine_attrs (node, object);
1315 xml_create_shadow_attrs (node, object);
1317 gl_debug (DEBUG_XML, "END");
1320 /*--------------------------------------------------------------------------*/
1321 /* PRIVATE. Add XML Objects->Object-ellipse Node */
1322 /*--------------------------------------------------------------------------*/
1324 xml_create_object_ellipse (xmlNodePtr root,
1326 glLabelObject *object)
1332 glColorNode *line_color_node;
1333 glColorNode *fill_color_node;
1335 gl_debug (DEBUG_XML, "START");
1337 node = xmlNewChild (root, ns, (xmlChar *)"Object-ellipse", NULL);
1339 /* position attrs */
1340 gl_label_object_get_position (object, &x, &y);
1341 lgl_xml_set_prop_length (node, "x", x);
1342 lgl_xml_set_prop_length (node, "y", y);
1345 gl_label_object_get_size (object, &w, &h);
1346 lgl_xml_set_prop_length (node, "w", w);
1347 lgl_xml_set_prop_length (node, "h", h);
1350 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1351 lgl_xml_set_prop_length (node, "line_width", line_width);
1353 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1354 if (line_color_node->field_flag)
1356 lgl_xml_set_prop_string (node, "line_color_field", line_color_node->key);
1360 lgl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1362 gl_color_node_free (&line_color_node);
1365 /* fill attrs (color or field) */
1366 fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1367 if (fill_color_node->field_flag)
1369 lgl_xml_set_prop_string (node, "fill_color_field", fill_color_node->key);
1373 lgl_xml_set_prop_uint_hex (node, "fill_color", fill_color_node->color);
1375 gl_color_node_free (&fill_color_node);
1378 xml_create_affine_attrs (node, object);
1381 xml_create_shadow_attrs (node, object);
1383 gl_debug (DEBUG_XML, "END");
1386 /*--------------------------------------------------------------------------*/
1387 /* PRIVATE. Add XML Objects->Object-line Node */
1388 /*--------------------------------------------------------------------------*/
1390 xml_create_object_line (xmlNodePtr root,
1392 glLabelObject *object)
1398 glColorNode *line_color_node;
1400 gl_debug (DEBUG_XML, "START");
1402 node = xmlNewChild (root, ns, (xmlChar *)"Object-line", NULL);
1404 /* position attrs */
1405 gl_label_object_get_position (object, &x, &y);
1406 lgl_xml_set_prop_length (node, "x", x);
1407 lgl_xml_set_prop_length (node, "y", y);
1410 gl_label_object_get_size (object, &dx, &dy);
1411 lgl_xml_set_prop_length (node, "dx", dx);
1412 lgl_xml_set_prop_length (node, "dy", dy);
1415 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1416 lgl_xml_set_prop_length (node, "line_width", line_width);
1418 line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1419 if (line_color_node->field_flag)
1421 lgl_xml_set_prop_string (node, "line_color_field", line_color_node->key);
1425 lgl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1427 gl_color_node_free (&line_color_node);
1431 xml_create_affine_attrs (node, object);
1434 xml_create_shadow_attrs (node, object);
1436 gl_debug (DEBUG_XML, "END");
1439 /*--------------------------------------------------------------------------*/
1440 /* PRIVATE. Add XML Objects->Object-image Node */
1441 /*--------------------------------------------------------------------------*/
1443 xml_create_object_image (xmlNodePtr root,
1445 glLabelObject *object)
1450 glTextNode *filename;
1452 gl_debug (DEBUG_XML, "START");
1454 node = xmlNewChild (root, ns, (xmlChar *)"Object-image", NULL);
1456 /* position attrs */
1457 gl_label_object_get_position (object, &x, &y);
1458 lgl_xml_set_prop_length (node, "x", x);
1459 lgl_xml_set_prop_length (node, "y", y);
1462 gl_label_object_get_size (object, &w, &h);
1463 lgl_xml_set_prop_length (node, "w", w);
1464 lgl_xml_set_prop_length (node, "h", h);
1466 /* src OR field attr */
1467 filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1468 if (filename->field_flag) {
1469 lgl_xml_set_prop_string (node, "field", filename->data);
1471 lgl_xml_set_prop_string (node, "src", filename->data);
1473 gl_text_node_free (&filename);
1476 xml_create_affine_attrs (node, object);
1479 xml_create_shadow_attrs (node, object);
1481 gl_debug (DEBUG_XML, "END");
1484 /*--------------------------------------------------------------------------*/
1485 /* PRIVATE. Add XML Objects->Object-barcode Node */
1486 /*--------------------------------------------------------------------------*/
1488 xml_create_object_barcode (xmlNodePtr root,
1490 glLabelObject *object)
1495 glTextNode *text_node;
1498 gboolean checksum_flag;
1499 glColorNode *color_node;
1500 guint format_digits;
1502 gl_debug (DEBUG_XML, "START");
1504 node = xmlNewChild (root, ns, (xmlChar *)"Object-barcode", NULL);
1506 /* position attrs */
1507 gl_label_object_get_position (object, &x, &y);
1508 lgl_xml_set_prop_length (node, "x", x);
1509 lgl_xml_set_prop_length (node, "y", y);
1512 gl_label_object_get_raw_size (object, &w, &h);
1513 lgl_xml_set_prop_length (node, "w", w);
1514 lgl_xml_set_prop_length (node, "h", h);
1516 /* Barcode properties attrs */
1517 gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1518 &id, &text_flag, &checksum_flag, &format_digits);
1519 lgl_xml_set_prop_string (node, "style", id);
1520 lgl_xml_set_prop_boolean (node, "text", text_flag);
1521 lgl_xml_set_prop_boolean (node, "checksum", checksum_flag);
1525 color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1526 if (color_node->field_flag)
1528 lgl_xml_set_prop_string (node, "color_field", color_node->key);
1532 lgl_xml_set_prop_uint_hex (node, "color", color_node->color);
1534 gl_color_node_free (&color_node);
1537 /* data OR field attr */
1538 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1539 if (text_node->field_flag) {
1540 lgl_xml_set_prop_string (node, "field", text_node->data);
1541 lgl_xml_set_prop_int (node, "format", format_digits);
1543 lgl_xml_set_prop_string (node, "data", text_node->data);
1545 gl_text_node_free (&text_node);
1548 xml_create_affine_attrs (node, object);
1551 xml_create_shadow_attrs (node, object);
1553 gl_debug (DEBUG_XML, "END");
1556 /*--------------------------------------------------------------------------*/
1557 /* PRIVATE. Add XML Label Merge Fields Node */
1558 /*--------------------------------------------------------------------------*/
1560 xml_create_merge_fields (xmlNodePtr root,
1568 gl_debug (DEBUG_XML, "START");
1570 merge = gl_label_get_merge (label);
1572 node = xmlNewChild (root, ns, (xmlChar *)"Merge", NULL);
1574 string = gl_merge_get_name (merge);
1575 lgl_xml_set_prop_string (node, "type", string);
1578 string = gl_merge_get_src (merge);
1579 lgl_xml_set_prop_string (node, "src", string);
1582 g_object_unref (G_OBJECT(merge));
1584 gl_debug (DEBUG_XML, "END");
1587 /*--------------------------------------------------------------------------*/
1588 /* PRIVATE. Add XML Label Data Node */
1589 /*--------------------------------------------------------------------------*/
1591 xml_create_data (xmlNodePtr root,
1596 GList *name_list, *p;
1597 GHashTable *pixbuf_cache;
1599 gl_debug (DEBUG_XML, "START");
1601 node = xmlNewChild (root, ns, (xmlChar *)"Data", NULL);
1603 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1604 name_list = gl_pixbuf_cache_get_name_list (pixbuf_cache);
1606 for (p = name_list; p != NULL; p=p->next) {
1607 xml_create_pixdata (node, ns, label, p->data);
1610 gl_pixbuf_cache_free_name_list (name_list);
1613 gl_debug (DEBUG_XML, "END");
1616 /*--------------------------------------------------------------------------*/
1617 /* PRIVATE. Add XML Label Data Pixbuf Node */
1618 /*--------------------------------------------------------------------------*/
1620 xml_create_pixdata (xmlNodePtr root,
1626 GHashTable *pixbuf_cache;
1628 GdkPixdata *pixdata;
1630 guint stream_length;
1633 gl_debug (DEBUG_XML, "START");
1635 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1637 pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, name);
1638 if ( pixbuf != NULL ) {
1640 pixdata = g_new0 (GdkPixdata, 1);
1641 gdk_pixdata_from_pixbuf (pixdata, pixbuf, FALSE);
1642 stream = gdk_pixdata_serialize (pixdata, &stream_length);
1643 base64 = g_base64_encode (stream, stream_length);
1645 node = xmlNewChild (root, ns, (xmlChar *)"Pixdata", (xmlChar *)base64);
1646 lgl_xml_set_prop_string (node, "name", name);
1647 lgl_xml_set_prop_string (node, "encoding", "Base64");
1649 gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, name);
1657 gl_debug (DEBUG_XML, "END");
1660 /*--------------------------------------------------------------------------*/
1661 /* PRIVATE. Create top-level Span node. */
1662 /*--------------------------------------------------------------------------*/
1664 xml_create_toplevel_span (xmlNodePtr root,
1666 glLabelText *object_text)
1671 PangoWeight font_weight;
1672 gboolean font_italic_flag;
1673 glColorNode *color_node;
1674 PangoAlignment align;
1675 gdouble text_line_spacing;
1676 GList *lines, *p_line, *p_node;
1677 glTextNode *text_node;
1680 node = xmlNewChild (root, ns, (xmlChar *)"Span", NULL);
1682 /* All span attrs at top level. */
1683 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object_text));
1684 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object_text));
1685 text_line_spacing = gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object_text));
1686 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object_text));
1687 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object_text));
1689 color_node = gl_label_object_get_text_color (GL_LABEL_OBJECT(object_text));
1690 if (color_node->field_flag)
1692 lgl_xml_set_prop_string (node, "color_field", color_node->key);
1696 lgl_xml_set_prop_uint_hex (node, "color", color_node->color);
1698 gl_color_node_free (&color_node);
1700 align = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object_text));
1701 lgl_xml_set_prop_string (node, "font_family", font_family);
1702 lgl_xml_set_prop_double (node, "font_size", font_size);
1703 lgl_xml_set_prop_string (node, "font_weight", gl_util_weight_to_string (font_weight));
1704 lgl_xml_set_prop_boolean (node, "font_italic", font_italic_flag);
1706 lgl_xml_set_prop_double (node, "line_spacing", text_line_spacing);
1708 /* Build children. */
1709 lines = gl_label_text_get_lines (GL_LABEL_TEXT(object_text));
1710 for (p_line = lines; p_line != NULL; p_line = p_line->next) {
1712 for (p_node = (GList *) p_line->data; p_node != NULL;
1713 p_node = p_node->next) {
1714 text_node = (glTextNode *) p_node->data;
1716 if (text_node->field_flag) {
1717 child = xmlNewChild (node, ns, (xmlChar *)"Field", NULL);
1718 lgl_xml_set_prop_string (child, "name", text_node->data);
1720 xmlNodeAddContent (node, (xmlChar *)text_node->data);
1725 if ( p_line->next ) {
1726 child = xmlNewChild (node, ns, (xmlChar *)"NL", NULL);
1731 gl_text_node_lines_free (&lines);
1732 g_free (font_family);
1736 /*--------------------------------------------------------------------------*/
1737 /* PRIVATE. Create affine attributes. */
1738 /*--------------------------------------------------------------------------*/
1740 xml_create_affine_attrs (xmlNodePtr node,
1741 glLabelObject *object)
1743 cairo_matrix_t matrix;
1745 gl_label_object_get_matrix (object, &matrix);
1747 lgl_xml_set_prop_double (node, "a0", matrix.xx);
1748 lgl_xml_set_prop_double (node, "a1", matrix.yx);
1749 lgl_xml_set_prop_double (node, "a2", matrix.xy);
1750 lgl_xml_set_prop_double (node, "a3", matrix.yy);
1751 lgl_xml_set_prop_double (node, "a4", matrix.x0);
1752 lgl_xml_set_prop_double (node, "a5", matrix.y0);
1755 /*--------------------------------------------------------------------------*/
1756 /* PRIVATE. Create shadow attributes. */
1757 /*--------------------------------------------------------------------------*/
1759 xml_create_shadow_attrs (xmlNodePtr node,
1760 glLabelObject *object)
1762 gboolean shadow_state;
1765 glColorNode *shadow_color_node;
1766 gdouble shadow_opacity;
1768 shadow_state = gl_label_object_get_shadow_state (object);
1772 lgl_xml_set_prop_boolean (node, "shadow", shadow_state);
1774 gl_label_object_get_shadow_offset (object, &shadow_x, &shadow_y);
1775 lgl_xml_set_prop_length (node, "shadow_x", shadow_x);
1776 lgl_xml_set_prop_length (node, "shadow_y", shadow_y);
1778 shadow_color_node = gl_label_object_get_shadow_color (object);
1779 if (shadow_color_node->field_flag)
1781 lgl_xml_set_prop_string (node, "shadow_color_field", shadow_color_node->key);
1785 lgl_xml_set_prop_uint_hex (node, "shadow_color", shadow_color_node->color);
1787 gl_color_node_free (&shadow_color_node);
1789 shadow_opacity = gl_label_object_get_shadow_opacity (object);
1790 lgl_xml_set_prop_double (node, "shadow_opacity", shadow_opacity);