]> git.sur5r.net Git - glabels/blob - glabels2/src/xml-label.c
2004-07-18 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / xml-label.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  label.c:  GLabels xml label module
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22
23 #include <config.h>
24
25 #include <gnome.h>
26
27 #include <libxml/tree.h>
28 #include <libxml/parser.h>
29 #include <gdk-pixbuf/gdk-pixdata.h>
30
31 #include "label.h"
32 #include "label-object.h"
33 #include "label-text.h"
34 #include "label-box.h"
35 #include "label-line.h"
36 #include "label-ellipse.h"
37 #include "label-image.h"
38 #include "label-barcode.h"
39 #include "base64.h"
40 #include "xml-label.h"
41 #include "xml-label-04.h"
42 #include "xml-label-191.h"
43 #include <libglabels/template.h>
44 #include <libglabels/xml-template.h>
45 #include <libglabels/xml.h>
46 #include "util.h"
47
48 #include "debug.h"
49
50 /*========================================================*/
51 /* Private macros and constants.                          */
52 /*========================================================*/
53 #define COMPAT01_NAME_SPACE "http://snaught.com/glabels/0.1/"
54 #define COMPAT04_NAME_SPACE "http://snaught.com/glabels/0.4/"
55 #define COMPAT191_NAME_SPACE "http://snaught.com/glabels/1.92/"
56
57 /*========================================================*/
58 /* Private types.                                         */
59 /*========================================================*/
60
61 /*========================================================*/
62 /* Private globals.                                       */
63 /*========================================================*/
64
65 /*========================================================*/
66 /* Private function prototypes.                           */
67 /*========================================================*/
68
69 static glLabel       *xml_doc_to_label         (xmlDocPtr         doc,
70                                                 glXMLLabelStatus *status);
71
72 static glLabel       *xml_parse_label          (xmlNodePtr        root,
73                                                 glXMLLabelStatus *status);
74
75 static void           xml_parse_objects        (xmlNodePtr        node,
76                                                 glLabel          *label);
77
78 static void           xml_parse_object_text    (xmlNodePtr        node,
79                                                 glLabel          *label);
80
81 static void           xml_parse_object_box     (xmlNodePtr        node,
82                                                 glLabel          *label);
83
84 static void           xml_parse_object_ellipse (xmlNodePtr        node,
85                                                 glLabel          *label);
86
87 static void           xml_parse_object_line    (xmlNodePtr        node,
88                                                 glLabel          *label);
89
90 static void           xml_parse_object_image   (xmlNodePtr        node,
91                                                 glLabel          *label);
92
93 static void           xml_parse_object_barcode (xmlNodePtr        node,
94                                                 glLabel          *label);
95
96 static void           xml_parse_merge_fields   (xmlNodePtr        node,
97                                                 glLabel          *label);
98
99 static void           xml_parse_data           (xmlNodePtr        node,
100                                                 glLabel          *label);
101
102 static void           xml_parse_pixdata        (xmlNodePtr        node,
103                                                 glLabel          *label);
104
105 static void           xml_parse_toplevel_span  (xmlNodePtr        node,
106                                                 glLabelObject    *object);
107
108
109 static xmlDocPtr      xml_label_to_doc         (glLabel          *label,
110                                                 glXMLLabelStatus *status);
111
112 static void           xml_create_objects       (xmlNodePtr        root,
113                                                 xmlNsPtr          ns,
114                                                 glLabel          *label);
115
116 static void           xml_create_object_text   (xmlNodePtr        root,
117                                                 xmlNsPtr          ns,
118                                                 glLabelObject    *object);
119
120 static void           xml_create_object_box    (xmlNodePtr        root,
121                                                 xmlNsPtr          ns,
122                                                 glLabelObject    *object);
123
124 static void           xml_create_object_line   (xmlNodePtr        root,
125                                                 xmlNsPtr          ns,
126                                                 glLabelObject    *object);
127
128 static void           xml_create_object_ellipse(xmlNodePtr        root,
129                                                 xmlNsPtr          ns,
130                                                 glLabelObject    *object);
131
132 static void           xml_create_object_image  (xmlNodePtr        root,
133                                                 xmlNsPtr          ns,
134                                                 glLabelObject    *object);
135
136 static void           xml_create_object_barcode(xmlNodePtr        root,
137                                                 xmlNsPtr          ns,
138                                                 glLabelObject    *object);
139
140 static void           xml_create_merge_fields  (xmlNodePtr        root,
141                                                 xmlNsPtr          ns,
142                                                 glLabel          *label);
143
144 static void           xml_create_data          (xmlNodePtr        root,
145                                                 xmlNsPtr          ns,
146                                                 glLabel          *label);
147
148 static void           xml_create_pixdata       (xmlNodePtr        root,
149                                                 xmlNsPtr          ns,
150                                                 glLabel          *label,
151                                                 gchar            *name);
152
153 static void           xml_create_toplevel_span (xmlNodePtr        node,
154                                                 xmlNsPtr          ns,
155                                                 glLabelText      *object_text);
156
157
158 /****************************************************************************/
159 /* Open and read label from xml file.                                       */
160 /****************************************************************************/
161 glLabel *
162 gl_xml_label_open (const gchar      *utf8_filename,
163                    glXMLLabelStatus *status)
164 {
165         xmlDocPtr  doc;
166         glLabel   *label;
167         gchar     *filename;
168
169         gl_debug (DEBUG_XML, "START");
170
171         filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
172         g_return_val_if_fail (filename, NULL);
173
174         doc = xmlParseFile (filename);
175         if (!doc) {
176                 g_warning (_("xmlParseFile error"));
177                 *status = XML_LABEL_ERROR_OPEN_PARSE;
178                 return NULL;
179         }
180
181         xmlXIncludeProcess (doc);
182         xmlReconciliateNs (doc, xmlDocGetRootElement (doc));
183
184         label = xml_doc_to_label (doc, status);
185
186         xmlFreeDoc (doc);
187
188         if (label) {
189                 gl_label_set_filename (label, utf8_filename);
190                 gl_label_clear_modified (label);
191         }
192
193         g_free (filename);
194         gl_debug (DEBUG_XML, "END");
195
196         return label;
197 }
198
199 /****************************************************************************/
200 /* Read label from xml buffer.                                              */
201 /****************************************************************************/
202 glLabel *
203 gl_xml_label_open_buffer (const gchar      *buffer,
204                           glXMLLabelStatus *status)
205 {
206         xmlDocPtr  doc;
207         glLabel   *label;
208
209         gl_debug (DEBUG_XML, "START");
210
211         doc = xmlParseDoc ((xmlChar *) buffer);
212         if (!doc) {
213                 g_warning (_("xmlParseFile error"));
214                 *status = XML_LABEL_ERROR_OPEN_PARSE;
215                 return NULL;
216         }
217
218         label = xml_doc_to_label (doc, status);
219
220         xmlFreeDoc (doc);
221
222         if (label) {
223                 gl_label_clear_modified (label);
224         }
225
226         gl_debug (DEBUG_XML, "END");
227
228         return label;
229 }
230
231 /*--------------------------------------------------------------------------*/
232 /* PRIVATE.  Parse xml doc structure and create label.                      */
233 /*--------------------------------------------------------------------------*/
234 static glLabel *
235 xml_doc_to_label (xmlDocPtr         doc,
236                   glXMLLabelStatus *status)
237 {
238         xmlNodePtr  root, node;
239         xmlNsPtr    ns;
240         glLabel    *label;
241
242         gl_debug (DEBUG_XML, "START");
243
244         LIBXML_TEST_VERSION;
245
246         *status = XML_LABEL_OK;
247
248         root = xmlDocGetRootElement (doc);
249         if (!root || !root->name) {
250                 g_warning (_("No document root"));
251                 *status = XML_LABEL_ERROR_OPEN_PARSE;
252                 return NULL;
253         }
254
255         ns = xmlSearchNsByHref (doc, root, GL_XML_NAME_SPACE);
256         if (ns != NULL) {
257                 label = xml_parse_label (root, status);
258                 if (label)
259                         gl_label_set_compression (label, xmlGetDocCompressMode (doc));
260         } else {
261                 /* Try compatability mode 0.1 */
262                 ns = xmlSearchNsByHref (doc, root, COMPAT01_NAME_SPACE);
263                 if (ns != NULL) {
264                         g_warning (_("Importing from glabels 0.1 format"));
265                         g_warning ("TODO");
266                         label = NULL; /* TODO */
267                 } else {
268                         /* Try compatability mode 0.4 */
269                         ns = xmlSearchNsByHref (doc, root,
270                                                 COMPAT04_NAME_SPACE);
271                         if (ns != NULL) {
272                                 g_warning (_("Importing from glabels 0.4 format"));
273                                 label = gl_xml_label_04_parse (root, status);
274                         } else {
275                                 /* Try compatability mode 1.91 */
276                                 ns = xmlSearchNsByHref (doc, root,
277                                                         COMPAT191_NAME_SPACE);
278                                 if (ns != NULL) {
279                                         g_warning (_("Importing from glabels 1.91 format"));
280                                         label = gl_xml_label_191_parse (root, status);
281                                 } else {
282                                         g_warning (_("bad document, unknown glabels Namespace"));
283                                         *status = XML_LABEL_ERROR_OPEN_PARSE;
284                                         return NULL;
285                                 }
286                         }
287                 }
288         }
289
290         gl_debug (DEBUG_XML, "END");
291
292         return label;
293 }
294
295 /*--------------------------------------------------------------------------*/
296 /* PRIVATE.  Parse xml root node and create label.                          */
297 /*--------------------------------------------------------------------------*/
298 static glLabel *
299 xml_parse_label (xmlNodePtr        root,
300                  glXMLLabelStatus *status)
301 {
302         xmlNodePtr  child_node;
303         glLabel    *label;
304         glTemplate *template;
305
306         gl_debug (DEBUG_XML, "START");
307
308         *status = XML_LABEL_OK;
309
310         if (!xmlStrEqual (root->name, "Glabels-document")) {
311                 g_warning (_("Bad root node = \"%s\""), root->name);
312                 *status = XML_LABEL_ERROR_OPEN_PARSE;
313                 return NULL;
314         }
315
316         label = GL_LABEL(gl_label_new ());
317
318         /* Pass 1, extract data nodes to pre-load cache. */
319         for (child_node = root->xmlChildrenNode; child_node != NULL; child_node = child_node->next) {
320                 if (xmlStrEqual (child_node->name, "Data")) {
321                         xml_parse_data (child_node, label);
322                 }
323         }
324
325         /* Pass 2, now extract everything else. */
326         for (child_node = root->xmlChildrenNode;
327              child_node != NULL;
328              child_node = child_node->next) {
329
330                 if (xmlStrEqual (child_node->name, "Template")) {
331                         template = gl_xml_template_parse_template_node (child_node);
332                         if (!template) {
333                                 g_object_unref (label);
334                                 *status = XML_LABEL_UNKNOWN_MEDIA;
335                                 return NULL;
336                         }
337                         gl_template_register (template);
338                         gl_label_set_template (label, template);
339                         gl_template_free (template);
340                 } else if (xmlStrEqual (child_node->name, "Objects")) {
341                         xml_parse_objects (child_node, label);
342                 } else if (xmlStrEqual (child_node->name, "Merge")) {
343                         xml_parse_merge_fields (child_node, label);
344                 } else if (xmlStrEqual (child_node->name, "Data")) {
345                         /* Handled in pass 1. */
346                 } else {
347                         if (!xmlNodeIsText (child_node)) {
348                                 g_warning (_("bad node in Document node =  \"%s\""),
349                                            child_node->name);
350                                 g_object_unref (label);
351                                 *status = XML_LABEL_ERROR_OPEN_PARSE;
352                                 return NULL;
353                         }
354                 }
355         }
356
357         gl_debug (DEBUG_XML, "END");
358
359         return label;
360 }
361
362 /*--------------------------------------------------------------------------*/
363 /* PRIVATE.  Parse Objects node.                                            */
364 /*--------------------------------------------------------------------------*/
365 static void
366 xml_parse_objects (xmlNodePtr  node,
367                    glLabel    *label)
368 {
369         gboolean    rotate_flag;
370         xmlNodePtr  child;
371
372         gl_debug (DEBUG_XML, "START");
373
374         rotate_flag = gl_xml_get_prop_boolean (node, "rotate", FALSE);
375         gl_label_set_rotate_flag (label, rotate_flag);
376
377         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
378
379                 if (xmlStrEqual (child->name, "Object-text")) {
380                         xml_parse_object_text (child, label);
381                 } else if (xmlStrEqual (child->name, "Object-box")) {
382                         xml_parse_object_box (child, label);
383                 } else if (xmlStrEqual (child->name, "Object-ellipse")) {
384                         xml_parse_object_ellipse (child, label);
385                 } else if (xmlStrEqual (child->name, "Object-line")) {
386                         xml_parse_object_line (child, label);
387                 } else if (xmlStrEqual (child->name, "Object-image")) {
388                         xml_parse_object_image (child, label);
389                 } else if (xmlStrEqual (child->name, "Object-barcode")) {
390                         xml_parse_object_barcode (child, label);
391                 } else {
392                         if (!xmlNodeIsText (child)) {
393                                 g_warning (_("bad node =  \"%s\""), child->name);
394                                 break;
395                         }
396                 }
397         }
398
399         gl_debug (DEBUG_XML, "END");
400 }
401
402 /*--------------------------------------------------------------------------*/
403 /* PRIVATE.  Parse XML Objects->Object-text Node                            */
404 /*--------------------------------------------------------------------------*/
405 static void
406 xml_parse_object_text (xmlNodePtr  node,
407                        glLabel    *label)
408 {
409         GObject          *object;
410         gdouble           x, y;
411         gdouble           w, h;
412         gchar            *string;
413         GtkJustification  just;
414         gboolean          auto_shrink;
415         gdouble           affine[6];
416         xmlNodePtr        child;
417
418         gl_debug (DEBUG_XML, "START");
419
420         object = gl_label_text_new (label);
421
422         /* position attrs */
423         x = gl_xml_get_prop_length (node, "x", 0.0);
424         y = gl_xml_get_prop_length (node, "y", 0.0);
425         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
426
427         /* implied size attrs */
428         w = gl_xml_get_prop_length (node, "w", 0);
429         h = gl_xml_get_prop_length (node, "h", 0);
430         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
431
432         /* justify attr */
433         string = xmlGetProp (node, "justify");
434         just = gl_util_string_to_just (string);
435         g_free (string);
436         gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), just);
437
438         /* auto_shrink attr */
439         auto_shrink = gl_xml_get_prop_boolean (node, "auto_shrink", FALSE);
440         gl_label_text_set_auto_shrink (GL_LABEL_TEXT(object), auto_shrink);
441
442         /* affine attrs */
443         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
444         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
445         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
446         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
447         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
448         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
449         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
450
451         /* Process children */
452         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
453                 if (xmlStrEqual (child->name, "Span")) {
454                         xml_parse_toplevel_span (child, GL_LABEL_OBJECT(object));
455                         break;
456                 } else {
457                         if (!xmlNodeIsText (child)) {
458                                 g_warning ("Unexpected Object-text child: \"%s\"",
459                                            child->name);
460                         }
461                 }
462         }
463
464         gl_debug (DEBUG_XML, "END");
465 }
466
467 /*--------------------------------------------------------------------------*/
468 /* PRIVATE.  Parse XML Objects->Object-box Node                             */
469 /*--------------------------------------------------------------------------*/
470 static void
471 xml_parse_object_box (xmlNodePtr  node,
472                       glLabel    *label)
473 {
474         GObject *object;
475         gdouble  x, y;
476         gdouble  w, h;
477         gdouble  line_width;
478         guint    line_color, fill_color;
479         gdouble  affine[6];
480
481         gl_debug (DEBUG_XML, "START");
482
483         object = gl_label_box_new (label);
484
485         /* position attrs */
486         x = gl_xml_get_prop_length (node, "x", 0.0);
487         y = gl_xml_get_prop_length (node, "y", 0.0);
488         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
489
490         /* size attrs */
491         w = gl_xml_get_prop_length (node, "w", 0);
492         h = gl_xml_get_prop_length (node, "h", 0);
493         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
494
495         /* line attrs */
496         line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
497         line_color = gl_xml_get_prop_uint (node, "line_color", 0);
498         gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
499         gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
500
501         /* fill attrs */
502         fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
503         gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color);
504
505         /* affine attrs */
506         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
507         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
508         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
509         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
510         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
511         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
512         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
513
514         gl_debug (DEBUG_XML, "END");
515 }
516
517 /*--------------------------------------------------------------------------*/
518 /* PRIVATE.  Parse XML Objects->Object-ellipse Node                         */
519 /*--------------------------------------------------------------------------*/
520 static void
521 xml_parse_object_ellipse (xmlNodePtr  node,
522                           glLabel    *label)
523 {
524         GObject *object;
525         gdouble  x, y;
526         gdouble  w, h;
527         gdouble  line_width;
528         guint    line_color, fill_color;
529         gdouble  affine[6];
530
531         gl_debug (DEBUG_XML, "START");
532
533         object = gl_label_ellipse_new (label);
534
535         /* position attrs */
536         x = gl_xml_get_prop_length (node, "x", 0.0);
537         y = gl_xml_get_prop_length (node, "y", 0.0);
538         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
539
540         /* size attrs */
541         w = gl_xml_get_prop_length (node, "w", 0);
542         h = gl_xml_get_prop_length (node, "h", 0);
543         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
544
545         /* line attrs */
546         line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
547         line_color = gl_xml_get_prop_uint (node, "line_color", 0);
548         gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
549         gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
550
551         /* fill attrs */
552         fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
553         gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color);
554
555         /* affine attrs */
556         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
557         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
558         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
559         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
560         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
561         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
562         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
563
564         gl_debug (DEBUG_XML, "END");
565 }
566
567 /*--------------------------------------------------------------------------*/
568 /* PRIVATE.  Parse XML Objects->Object-line Node                            */
569 /*--------------------------------------------------------------------------*/
570 static void
571 xml_parse_object_line (xmlNodePtr  node,
572                        glLabel    *label)
573 {
574         GObject *object;
575         gdouble  x, y;
576         gdouble  dx, dy;
577         gdouble  line_width;
578         guint    line_color;
579         gdouble  affine[6];
580
581         gl_debug (DEBUG_XML, "START");
582
583         object = gl_label_line_new (label);
584
585         /* position attrs */
586         x = gl_xml_get_prop_length (node, "x", 0.0);
587         y = gl_xml_get_prop_length (node, "y", 0.0);
588         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
589
590         /* length attrs */
591         dx = gl_xml_get_prop_length (node, "dx", 0);
592         dy = gl_xml_get_prop_length (node, "dy", 0);
593         gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy);
594
595         /* line attrs */
596         line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
597         line_color = gl_xml_get_prop_uint (node, "line_color", 0);
598         gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
599         gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
600
601         /* affine attrs */
602         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
603         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
604         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
605         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
606         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
607         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
608         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
609
610         gl_debug (DEBUG_XML, "END");
611 }
612
613 /*--------------------------------------------------------------------------*/
614 /* PRIVATE.  Parse XML Objects->Object-image Node                           */
615 /*--------------------------------------------------------------------------*/
616 static void
617 xml_parse_object_image (xmlNodePtr  node,
618                         glLabel    *label)
619 {
620         GObject      *object;
621         gdouble       x, y;
622         gdouble       w, h;
623         gchar        *string;
624         glTextNode   *filename;
625         gdouble       affine[6];
626
627         gl_debug (DEBUG_XML, "START");
628
629         object = gl_label_image_new (label);
630
631         /* position attrs */
632         x = gl_xml_get_prop_length (node, "x", 0.0);
633         y = gl_xml_get_prop_length (node, "y", 0.0);
634         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
635
636         /* src or field attr */
637         string = xmlGetProp (node, "src");
638         if ( string ) {
639                 filename = g_new0 (glTextNode, 1);
640                 filename->field_flag = FALSE;
641                 filename->data = string;
642                 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
643                 gl_text_node_free (&filename);
644         } else {
645                 string = xmlGetProp (node, "field");
646                 if ( string ) {
647                         filename = g_new0 (glTextNode, 1);
648                         filename->field_flag = TRUE;
649                         filename->data = string;
650                         gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
651                         gl_text_node_free (&filename);
652                 } else {
653                         g_warning ("Missing Object-image src or field attr");
654                 }
655         }
656
657         /* size attrs */
658         w = gl_xml_get_prop_length (node, "w", 0);
659         h = gl_xml_get_prop_length (node, "h", 0);
660         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
661
662         /* affine attrs */
663         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
664         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
665         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
666         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
667         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
668         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
669         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
670
671         gl_debug (DEBUG_XML, "END");
672 }
673
674 /*--------------------------------------------------------------------------*/
675 /* PRIVATE.  Parse XML Objects->Object-barcode Node                         */
676 /*--------------------------------------------------------------------------*/
677 static void
678 xml_parse_object_barcode (xmlNodePtr  node,
679                           glLabel    *label)
680 {
681         GObject            *object;
682         gdouble             x, y;
683         gdouble             w, h;
684         gchar              *string;
685         glTextNode         *text_node;
686         gchar              *id;
687         gboolean            text_flag;
688         gboolean            checksum_flag;
689         guint               color;
690         guint               format_digits;
691         gdouble             affine[6];
692
693         gl_debug (DEBUG_XML, "START");
694
695         object = gl_label_barcode_new (label);
696
697         /* position attrs */
698         x = gl_xml_get_prop_length (node, "x", 0.0);
699         y = gl_xml_get_prop_length (node, "y", 0.0);
700         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
701
702         /* size attrs */
703         w = gl_xml_get_prop_length (node, "w", 0);
704         h = gl_xml_get_prop_length (node, "h", 0);
705         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
706
707         /* prop attrs */
708         id = xmlGetProp (node, "style");
709         text_flag = gl_xml_get_prop_boolean (node, "text", FALSE);
710         checksum_flag = gl_xml_get_prop_boolean (node, "checksum", TRUE);
711         color = gl_xml_get_prop_uint (node, "color", 0);
712         format_digits = gl_xml_get_prop_uint (node, "format", 0);
713         gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
714                                     id, text_flag, checksum_flag, format_digits);
715         gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color);
716         g_free (id);
717
718         /* data or field attr */
719         string = xmlGetProp (node, "data");
720         if ( string ) {
721                 text_node = g_new0 (glTextNode, 1);
722                 text_node->field_flag = FALSE;
723                 text_node->data = string;
724                 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
725                 gl_text_node_free (&text_node);
726         } else {
727                 string = xmlGetProp (node, "field");
728                 if ( string ) {
729                         text_node = g_new0 (glTextNode, 1);
730                         text_node->field_flag = TRUE;
731                         text_node->data = string;
732                         gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
733                         gl_text_node_free (&text_node);
734                 } else {
735                         g_warning ("Missing Object-barcode data or field attr");
736                 }
737         }
738
739         /* affine attrs */
740         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
741         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
742         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
743         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
744         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
745         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
746         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
747
748         gl_debug (DEBUG_XML, "END");
749 }
750
751 /*--------------------------------------------------------------------------*/
752 /* PRIVATE.  Parse XML merge fields tag.                                    */
753 /*--------------------------------------------------------------------------*/
754 static void
755 xml_parse_merge_fields (xmlNodePtr  node,
756                         glLabel    *label)
757 {
758         xmlNodePtr  child;
759         gchar      *string;
760         glMerge    *merge;
761
762         gl_debug (DEBUG_XML, "START");
763
764         string = xmlGetProp (node, "type");
765         merge = gl_merge_new (string);
766         g_free (string);
767
768         string = xmlGetProp (node, "src");
769         gl_merge_set_src (merge, string);
770         g_free (string);
771
772         gl_label_set_merge (label, merge);
773
774         g_object_unref (G_OBJECT(merge));
775
776         gl_debug (DEBUG_XML, "END");
777 }
778
779 /*--------------------------------------------------------------------------*/
780 /* PRIVATE.  Parse XML data tag.                                            */
781 /*--------------------------------------------------------------------------*/
782 static void
783 xml_parse_data (xmlNodePtr  node,
784                 glLabel    *label)
785 {
786         xmlNodePtr  child;
787
788         gl_debug (DEBUG_XML, "START");
789
790         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
791
792                 if (xmlStrEqual (child->name, "Pixdata")) {
793                         xml_parse_pixdata (child, label);
794                 } else {
795                         if (!xmlNodeIsText (child)) {
796                                 g_warning (_("bad node in Data node =  \"%s\""),
797                                            child->name);
798                         }
799                 }
800         }
801
802         gl_debug (DEBUG_XML, "END");
803 }
804
805 /*--------------------------------------------------------------------------*/
806 /* PRIVATE.  Parse XML pixbuf data tag.                                     */
807 /*--------------------------------------------------------------------------*/
808 static void
809 xml_parse_pixdata (xmlNodePtr  node,
810                    glLabel    *label)
811 {
812         gchar      *name, *base64;
813         guchar     *stream;
814         guint       stream_length;
815         gboolean    ret;
816         GdkPixdata *pixdata;
817         GdkPixbuf  *pixbuf;
818         GHashTable *pixbuf_cache;
819
820         gl_debug (DEBUG_XML, "START");
821
822         name = xmlGetProp (node, "name");
823         base64 = xmlNodeGetContent (node);
824
825         stream = gl_base64_decode (base64, &stream_length);
826         pixdata = g_new0 (GdkPixdata, 1);
827         ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
828
829         if (ret) {
830                 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
831
832                 pixbuf_cache = gl_label_get_pixbuf_cache (label);
833                 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
834         }
835
836         g_free (name);
837         g_free (base64);
838         g_free (stream);
839         g_free (pixdata);
840
841         gl_debug (DEBUG_XML, "END");
842 }
843
844 /*--------------------------------------------------------------------------*/
845 /* PRIVATE.  Parse top-level Span tag.                                      */
846 /*--------------------------------------------------------------------------*/
847 static void
848 xml_parse_toplevel_span  (xmlNodePtr        node,
849                           glLabelObject    *object)
850 {
851         gchar            *font_family;
852         gdouble           font_size;
853         GnomeFontWeight   font_weight;
854         gboolean          font_italic_flag;
855         guint             color;
856         gdouble           text_line_spacing;
857         gchar            *string;
858         GList            *lines, *text_nodes;
859         xmlNodePtr        child;
860         glTextNode       *text_node;
861
862         gl_debug (DEBUG_XML, "START");
863
864         /* Font family attr */
865         font_family = xmlGetProp (node, "font_family");
866         gl_label_object_set_font_family (object, font_family);
867         g_free (font_family);
868
869         /* Font size attr */
870         font_size = gl_xml_get_prop_double (node, "font_size", 0.0);
871         gl_label_object_set_font_size (object, font_size);
872
873         /* Font weight attr */
874         string = xmlGetProp (node, "font_weight");
875         font_weight = gl_util_string_to_weight (string);
876         g_free (string);
877         gl_label_object_set_font_weight (object, font_weight);
878
879         /* Font italic flag attr */
880         font_italic_flag = gl_xml_get_prop_boolean (node, "font_italic", FALSE);
881         gl_label_object_set_font_italic_flag (object, font_italic_flag);
882
883         /* Text color attr */
884         color = gl_xml_get_prop_uint (node, "color", 0);
885         gl_label_object_set_text_color (object, color);
886
887         /* Text line spacing attr  */
888         text_line_spacing = gl_xml_get_prop_double (node, "line_spacing", 1.0);
889         gl_label_object_set_text_line_spacing (object, text_line_spacing); 
890
891         /* Now descend children, and build lines of text nodes */
892         lines = NULL;
893         text_nodes = NULL;
894         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
895
896                 if (xmlNodeIsText (child)) {
897                         gchar *data = xmlNodeGetContent (child); 
898
899                         /* Hack: if the first char is LF, it's a xml formatting string */
900                         if (data[0] != '\n') { 
901                                 /* Literal text */
902                                 text_node = g_new0 (glTextNode, 1);
903                                 text_node->field_flag = FALSE;
904                                 text_node->data = data;
905                                 text_nodes = g_list_append (text_nodes, text_node);
906                         }
907                         else 
908                                 g_free (data);
909
910                 } else if (xmlStrEqual (child->name, "Span")) {
911
912                         g_warning ("Unexpected rich text (not supported, yet!)");
913
914                 } else if (xmlStrEqual (child->name, "Field")) {
915
916                         /* Field node */
917                         text_node = g_new0 (glTextNode, 1);
918                         text_node->field_flag = TRUE;
919                         text_node->data = xmlGetProp (child, "name");
920                         text_nodes = g_list_append (text_nodes, text_node);
921
922                 } else if (xmlStrEqual (child->name, "NL")) {
923
924                         /* Store line. */
925                         lines = g_list_append (lines, text_nodes);
926                         text_nodes = NULL;
927
928                 } else {
929                         g_warning ("Unexpected Span child: \"%s\"", child->name);
930                 }
931
932         }
933         if ( text_nodes ) {
934                 /* Store last line. */
935                 lines = g_list_append (lines, text_nodes);
936                 text_nodes = NULL;
937         }
938         gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
939         gl_text_node_lines_free (&lines);
940
941         gl_debug (DEBUG_XML, "END");
942 }
943
944 /****************************************************************************/
945 /* Save label to xml label file.                                            */
946 /****************************************************************************/
947 void
948 gl_xml_label_save (glLabel          *label,
949                    const gchar      *utf8_filename,
950                    glXMLLabelStatus *status)
951 {
952         xmlDocPtr doc;
953         gint      xml_ret;
954         gchar     *filename;
955
956         gl_debug (DEBUG_XML, "START");
957
958         doc = xml_label_to_doc (label, status);
959
960         filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
961         if (!filename)
962                 g_warning (_("Utf8 conversion error."));
963         else {
964                 xmlSetDocCompressMode (doc, gl_label_get_compression (label));
965                 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
966                 xmlFreeDoc (doc);
967                 if (xml_ret == -1) {
968
969                         g_warning (_("Problem saving xml file."));
970                         *status = XML_LABEL_ERROR_SAVE_FILE;
971
972                 } else {
973
974                         gl_label_set_filename (label, utf8_filename);
975                         gl_label_clear_modified (label);
976
977                 }
978                 g_free (filename);
979         }
980
981         gl_debug (DEBUG_XML, "END");
982 }
983
984 /****************************************************************************/
985 /* Save label to xml buffer.                                                */
986 /****************************************************************************/
987 gchar *
988 gl_xml_label_save_buffer (glLabel          *label,
989                           glXMLLabelStatus *status)
990 {
991         xmlDocPtr  doc;
992         gint       size;
993         gchar     *buffer;
994
995         gl_debug (DEBUG_XML, "START");
996
997         doc = xml_label_to_doc (label, status);
998
999         xmlDocDumpMemory (doc, (xmlChar **)&buffer, &size);
1000         xmlFreeDoc (doc);
1001
1002         gl_label_clear_modified (label);
1003
1004         gl_debug (DEBUG_XML, "END");
1005
1006         return buffer;
1007 }
1008
1009 /*--------------------------------------------------------------------------*/
1010 /* PRIVATE.  Convert label to xml doc structure.                            */
1011 /*--------------------------------------------------------------------------*/
1012 static xmlDocPtr
1013 xml_label_to_doc (glLabel          *label,
1014                   glXMLLabelStatus *status)
1015 {
1016         xmlDocPtr   doc;
1017         xmlNsPtr    ns;
1018         glTemplate *template;
1019         glMerge    *merge;
1020
1021         gl_debug (DEBUG_XML, "START");
1022
1023         LIBXML_TEST_VERSION;
1024
1025         doc = xmlNewDoc ("1.0");
1026         doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Glabels-document", NULL);
1027
1028         ns = xmlNewNs (doc->xmlRootNode, GL_XML_NAME_SPACE, NULL);
1029         xmlSetNs (doc->xmlRootNode, ns);
1030
1031         template = gl_label_get_template (label);
1032         gl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
1033
1034         xml_create_objects (doc->xmlRootNode, ns, label);
1035
1036         merge = gl_label_get_merge (label);
1037         gl_debug (DEBUG_XML, "merge=%p", merge);
1038         if (merge != NULL) {
1039                 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1040                 g_object_unref (G_OBJECT(merge));
1041         }
1042
1043         xml_create_data (doc->xmlRootNode, ns, label);
1044
1045         gl_debug (DEBUG_XML, "END");
1046
1047         *status = XML_LABEL_OK;
1048         return doc;
1049 }
1050
1051 /*--------------------------------------------------------------------------*/
1052 /* PRIVATE.  Add XML Objects Node                                           */
1053 /*--------------------------------------------------------------------------*/
1054 static void
1055 xml_create_objects (xmlNodePtr  root,
1056                     xmlNsPtr    ns,
1057                     glLabel    *label)
1058 {
1059         xmlNodePtr     node;
1060         gboolean       rotate_flag;
1061         GList         *p;
1062         glLabelObject *object;
1063
1064         gl_debug (DEBUG_XML, "START");
1065
1066         rotate_flag = gl_label_get_rotate_flag (label);
1067
1068         node = xmlNewChild (root, ns, "Objects", NULL);
1069         xmlSetProp (node, "id", "0");
1070         gl_xml_set_prop_boolean (node, "rotate", rotate_flag);
1071
1072         for (p = label->objects; p != NULL; p = p->next) {
1073
1074                 object = GL_LABEL_OBJECT(p->data);
1075
1076                 if ( GL_IS_LABEL_TEXT(object) ) {
1077                         xml_create_object_text (node, ns, object);
1078                 } else if ( GL_IS_LABEL_BOX(object) ) {
1079                         xml_create_object_box (node, ns, object);
1080                 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1081                         xml_create_object_ellipse (node, ns, object);
1082                 } else if ( GL_IS_LABEL_LINE(object) ) {
1083                         xml_create_object_line (node, ns, object);
1084                 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1085                         xml_create_object_image (node, ns, object);
1086                 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1087                         xml_create_object_barcode (node, ns, object);
1088                 } else {
1089                         g_warning ("Unknown label object");
1090                 }
1091
1092         }
1093
1094         gl_debug (DEBUG_XML, "END");
1095 }
1096
1097 /*--------------------------------------------------------------------------*/
1098 /* PRIVATE.  Add XML Objects->Object-text Node                              */
1099 /*--------------------------------------------------------------------------*/
1100 static void
1101 xml_create_object_text (xmlNodePtr     root,
1102                         xmlNsPtr       ns,
1103                         glLabelObject *object)
1104 {
1105         xmlNodePtr        node;
1106         gdouble           x, y;
1107         gdouble           w, h;
1108         GtkJustification  just;
1109         gboolean          auto_shrink;
1110         gdouble           affine[6];
1111
1112         gl_debug (DEBUG_XML, "START");
1113
1114         node = xmlNewChild (root, ns, "Object-text", NULL);
1115
1116         /* position attrs */
1117         gl_label_object_get_position (object, &x, &y);
1118         gl_xml_set_prop_length (node, "x", x);
1119         gl_xml_set_prop_length (node, "y", y);
1120
1121         /* size attrs */
1122         gl_label_text_get_box ( GL_LABEL_TEXT(object), &w, &h);
1123         gl_xml_set_prop_length (node, "w", w);
1124         gl_xml_set_prop_length (node, "h", h);
1125
1126         /* justify attr */
1127         just = gl_label_object_get_text_alignment (object);
1128         xmlSetProp (node, "justify", gl_util_just_to_string (just));
1129
1130         /* auto_shrink attr */
1131         auto_shrink = gl_label_text_get_auto_shrink (GL_LABEL_TEXT (object));
1132         gl_xml_set_prop_boolean (node, "auto_shrink", auto_shrink);
1133
1134         /* affine attrs */
1135         gl_label_object_get_affine (object, affine);
1136         gl_xml_set_prop_double (node, "a0", affine[0]);
1137         gl_xml_set_prop_double (node, "a1", affine[1]);
1138         gl_xml_set_prop_double (node, "a2", affine[2]);
1139         gl_xml_set_prop_double (node, "a3", affine[3]);
1140         gl_xml_set_prop_double (node, "a4", affine[4]);
1141         gl_xml_set_prop_double (node, "a5", affine[5]);
1142
1143         /* Add children */
1144         xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1145
1146         gl_debug (DEBUG_XML, "END");
1147 }
1148
1149 /*--------------------------------------------------------------------------*/
1150 /* PRIVATE.  Add XML Objects->Object-box Node                               */
1151 /*--------------------------------------------------------------------------*/
1152 static void
1153 xml_create_object_box (xmlNodePtr     root,
1154                        xmlNsPtr       ns,
1155                        glLabelObject *object)
1156 {
1157         xmlNodePtr        node;
1158         gdouble           x, y;
1159         gdouble           w, h;
1160         gdouble           line_width;
1161         guint             line_color, fill_color;
1162         gdouble           affine[6];
1163
1164         gl_debug (DEBUG_XML, "START");
1165
1166         node = xmlNewChild (root, ns, "Object-box", NULL);
1167
1168         /* position attrs */
1169         gl_label_object_get_position (object, &x, &y);
1170         gl_xml_set_prop_length (node, "x", x);
1171         gl_xml_set_prop_length (node, "y", y);
1172
1173         /* size attrs */
1174         gl_label_object_get_size (object, &w, &h);
1175         gl_xml_set_prop_length (node, "w", w);
1176         gl_xml_set_prop_length (node, "h", h);
1177
1178         /* line attrs */
1179         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1180         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1181         gl_xml_set_prop_length (node, "line_width", line_width);
1182         gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1183
1184         /* fill attrs */
1185         fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1186         gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1187
1188         /* affine attrs */
1189         gl_label_object_get_affine (object, affine);
1190         gl_xml_set_prop_double (node, "a0", affine[0]);
1191         gl_xml_set_prop_double (node, "a1", affine[1]);
1192         gl_xml_set_prop_double (node, "a2", affine[2]);
1193         gl_xml_set_prop_double (node, "a3", affine[3]);
1194         gl_xml_set_prop_double (node, "a4", affine[4]);
1195         gl_xml_set_prop_double (node, "a5", affine[5]);
1196
1197         gl_debug (DEBUG_XML, "END");
1198 }
1199
1200 /*--------------------------------------------------------------------------*/
1201 /* PRIVATE.  Add XML Objects->Object-ellipse Node                           */
1202 /*--------------------------------------------------------------------------*/
1203 static void
1204 xml_create_object_ellipse (xmlNodePtr     root,
1205                            xmlNsPtr       ns,
1206                            glLabelObject *object)
1207 {
1208         xmlNodePtr        node;
1209         gdouble           x, y;
1210         gdouble           w, h;
1211         gdouble           line_width;
1212         guint             line_color, fill_color;
1213         gdouble           affine[6];
1214
1215         gl_debug (DEBUG_XML, "START");
1216
1217         node = xmlNewChild (root, ns, "Object-ellipse", NULL);
1218
1219         /* position attrs */
1220         gl_label_object_get_position (object, &x, &y);
1221         gl_xml_set_prop_length (node, "x", x);
1222         gl_xml_set_prop_length (node, "y", y);
1223
1224         /* size attrs */
1225         gl_label_object_get_size (object, &w, &h);
1226         gl_xml_set_prop_length (node, "w", w);
1227         gl_xml_set_prop_length (node, "h", h);
1228
1229         /* line attrs */
1230         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1231         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1232         gl_xml_set_prop_length (node, "line_width", line_width);
1233         gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1234
1235         /* fill attrs */
1236         fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1237         gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1238
1239         /* affine attrs */
1240         gl_label_object_get_affine (object, affine);
1241         gl_xml_set_prop_double (node, "a0", affine[0]);
1242         gl_xml_set_prop_double (node, "a1", affine[1]);
1243         gl_xml_set_prop_double (node, "a2", affine[2]);
1244         gl_xml_set_prop_double (node, "a3", affine[3]);
1245         gl_xml_set_prop_double (node, "a4", affine[4]);
1246         gl_xml_set_prop_double (node, "a5", affine[5]);
1247
1248         gl_debug (DEBUG_XML, "END");
1249 }
1250
1251 /*--------------------------------------------------------------------------*/
1252 /* PRIVATE.  Add XML Objects->Object-line Node                              */
1253 /*--------------------------------------------------------------------------*/
1254 static void
1255 xml_create_object_line (xmlNodePtr     root,
1256                         xmlNsPtr       ns,
1257                         glLabelObject *object)
1258 {
1259         xmlNodePtr        node;
1260         gdouble           x, y;
1261         gdouble           dx, dy;
1262         gdouble           line_width;
1263         guint             line_color;
1264         gdouble           affine[6];
1265
1266         gl_debug (DEBUG_XML, "START");
1267
1268         node = xmlNewChild (root, ns, "Object-line", NULL);
1269
1270         /* position attrs */
1271         gl_label_object_get_position (object, &x, &y);
1272         gl_xml_set_prop_length (node, "x", x);
1273         gl_xml_set_prop_length (node, "y", y);
1274
1275         /* length attrs */
1276         gl_label_object_get_size (object, &dx, &dy);
1277         gl_xml_set_prop_length (node, "dx", dx);
1278         gl_xml_set_prop_length (node, "dy", dy);
1279
1280         /* line attrs */
1281         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1282         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1283         gl_xml_set_prop_length (node, "line_width", line_width);
1284         gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1285
1286         /* affine attrs */
1287         gl_label_object_get_affine (object, affine);
1288         gl_xml_set_prop_double (node, "a0", affine[0]);
1289         gl_xml_set_prop_double (node, "a1", affine[1]);
1290         gl_xml_set_prop_double (node, "a2", affine[2]);
1291         gl_xml_set_prop_double (node, "a3", affine[3]);
1292         gl_xml_set_prop_double (node, "a4", affine[4]);
1293         gl_xml_set_prop_double (node, "a5", affine[5]);
1294
1295         gl_debug (DEBUG_XML, "END");
1296 }
1297
1298 /*--------------------------------------------------------------------------*/
1299 /* PRIVATE.  Add XML Objects->Object-image Node                             */
1300 /*--------------------------------------------------------------------------*/
1301 static void
1302 xml_create_object_image (xmlNodePtr     root,
1303                          xmlNsPtr       ns,
1304                          glLabelObject *object)
1305 {
1306         xmlNodePtr        node;
1307         gdouble           x, y;
1308         gdouble           w, h;
1309         glTextNode       *filename;
1310         gdouble           affine[6];
1311
1312         gl_debug (DEBUG_XML, "START");
1313
1314         node = xmlNewChild (root, ns, "Object-image", NULL);
1315
1316         /* position attrs */
1317         gl_label_object_get_position (object, &x, &y);
1318         gl_xml_set_prop_length (node, "x", x);
1319         gl_xml_set_prop_length (node, "y", y);
1320
1321         /* size attrs */
1322         gl_label_object_get_size (object, &w, &h);
1323         gl_xml_set_prop_length (node, "w", w);
1324         gl_xml_set_prop_length (node, "h", h);
1325
1326         /* src OR field attr */
1327         filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1328         if (filename->field_flag) {
1329                 xmlSetProp (node, "field", filename->data);
1330         } else {
1331                 xmlSetProp (node, "src", filename->data);
1332         }
1333         gl_text_node_free (&filename);
1334
1335         /* affine attrs */
1336         gl_label_object_get_affine (object, affine);
1337         gl_xml_set_prop_double (node, "a0", affine[0]);
1338         gl_xml_set_prop_double (node, "a1", affine[1]);
1339         gl_xml_set_prop_double (node, "a2", affine[2]);
1340         gl_xml_set_prop_double (node, "a3", affine[3]);
1341         gl_xml_set_prop_double (node, "a4", affine[4]);
1342         gl_xml_set_prop_double (node, "a5", affine[5]);
1343
1344         gl_debug (DEBUG_XML, "END");
1345 }
1346
1347 /*--------------------------------------------------------------------------*/
1348 /* PRIVATE.  Add XML Objects->Object-barcode Node                           */
1349 /*--------------------------------------------------------------------------*/
1350 static void
1351 xml_create_object_barcode (xmlNodePtr     root,
1352                            xmlNsPtr       ns,
1353                            glLabelObject *object)
1354 {
1355         xmlNodePtr        node;
1356         gdouble           x, y;
1357         gdouble           w, h;
1358         glTextNode       *text_node;
1359         gchar            *id;
1360         gboolean          text_flag;
1361         gboolean          checksum_flag;
1362         guint             color;
1363         guint             format_digits;
1364         gdouble           affine[6];
1365
1366         gl_debug (DEBUG_XML, "START");
1367
1368         node = xmlNewChild (root, ns, "Object-barcode", NULL);
1369
1370         /* position attrs */
1371         gl_label_object_get_position (object, &x, &y);
1372         gl_xml_set_prop_length (node, "x", x);
1373         gl_xml_set_prop_length (node, "y", y);
1374
1375         /* size attrs */
1376         gl_label_object_get_size (object, &w, &h);
1377         gl_xml_set_prop_length (node, "w", w);
1378         gl_xml_set_prop_length (node, "h", h);
1379
1380         /* Barcode properties attrs */
1381         gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1382                                     &id, &text_flag, &checksum_flag, &format_digits);
1383         color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1384         xmlSetProp (node, "style", id);
1385         gl_xml_set_prop_boolean (node, "text", text_flag);
1386         gl_xml_set_prop_boolean (node, "checksum", checksum_flag);
1387         gl_xml_set_prop_uint_hex (node, "color", color);
1388         g_free (id);
1389
1390         /* data OR field attr */
1391         text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1392         if (text_node->field_flag) {
1393                 xmlSetProp (node, "field", text_node->data);
1394                 gl_xml_set_prop_int (node, "format", format_digits);
1395         } else {
1396                 xmlSetProp (node, "data", text_node->data);
1397         }
1398         gl_text_node_free (&text_node);
1399
1400         /* affine attrs */
1401         gl_label_object_get_affine (object, affine);
1402         gl_xml_set_prop_double (node, "a0", affine[0]);
1403         gl_xml_set_prop_double (node, "a1", affine[1]);
1404         gl_xml_set_prop_double (node, "a2", affine[2]);
1405         gl_xml_set_prop_double (node, "a3", affine[3]);
1406         gl_xml_set_prop_double (node, "a4", affine[4]);
1407         gl_xml_set_prop_double (node, "a5", affine[5]);
1408
1409         gl_debug (DEBUG_XML, "END");
1410 }
1411
1412 /*--------------------------------------------------------------------------*/
1413 /* PRIVATE.  Add XML Label Merge Fields Node                                */
1414 /*--------------------------------------------------------------------------*/
1415 static void
1416 xml_create_merge_fields (xmlNodePtr  root,
1417                          xmlNsPtr    ns,
1418                          glLabel    *label)
1419 {
1420         xmlNodePtr  node, child;
1421         gchar      *string;
1422         GList      *p;
1423         glMerge    *merge;
1424
1425         gl_debug (DEBUG_XML, "START");
1426
1427         merge = gl_label_get_merge (label);
1428
1429         node = xmlNewChild (root, ns, "Merge", NULL);
1430
1431         string = gl_merge_get_name (merge);
1432         xmlSetProp (node, "type", string);
1433         g_free (string);
1434
1435         string = gl_merge_get_src (merge);
1436         xmlSetProp (node, "src", string);
1437         g_free (string);
1438
1439         g_object_unref (G_OBJECT(merge));
1440
1441         gl_debug (DEBUG_XML, "END");
1442 }
1443
1444 /*--------------------------------------------------------------------------*/
1445 /* PRIVATE.  Add XML Label Data Node                                        */
1446 /*--------------------------------------------------------------------------*/
1447 static void
1448 xml_create_data (xmlNodePtr  root,
1449                  xmlNsPtr    ns,
1450                  glLabel    *label)
1451 {
1452         xmlNodePtr  node;
1453         GList      *name_list, *p;
1454         GHashTable *pixbuf_cache;
1455
1456         gl_debug (DEBUG_XML, "START");
1457
1458         node = xmlNewChild (root, ns, "Data", NULL);
1459
1460         pixbuf_cache = gl_label_get_pixbuf_cache (label);
1461         name_list = gl_pixbuf_cache_get_name_list (pixbuf_cache);
1462
1463         for (p = name_list; p != NULL; p=p->next) {
1464                 xml_create_pixdata (node, ns, label, p->data);
1465         }
1466
1467         gl_pixbuf_cache_free_name_list (name_list);
1468
1469
1470         gl_debug (DEBUG_XML, "END");
1471 }
1472
1473 /*--------------------------------------------------------------------------*/
1474 /* PRIVATE.  Add XML Label Data Pixbuf Node                                 */
1475 /*--------------------------------------------------------------------------*/
1476 static void
1477 xml_create_pixdata (xmlNodePtr  root,
1478                     xmlNsPtr    ns,
1479                     glLabel    *label,
1480                     gchar      *name)
1481 {
1482         xmlNodePtr  node;
1483         GHashTable *pixbuf_cache;
1484         GdkPixbuf  *pixbuf;
1485         GdkPixdata *pixdata;
1486         guchar     *stream;
1487         guint       stream_length;
1488         gchar      *base64;
1489
1490         gl_debug (DEBUG_XML, "START");
1491
1492         pixbuf_cache = gl_label_get_pixbuf_cache (label);
1493
1494         pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, name);
1495         if ( pixbuf != NULL ) {
1496
1497                 pixdata = g_new0 (GdkPixdata, 1);
1498                 gdk_pixdata_from_pixbuf (pixdata, pixbuf, FALSE);
1499                 stream = gdk_pixdata_serialize (pixdata, &stream_length);
1500                 base64 = gl_base64_encode (stream, stream_length);
1501
1502                 node = xmlNewChild (root, ns, "Pixdata", base64);
1503                 xmlSetProp (node, "name", name);
1504                 xmlSetProp (node, "encoding", "Base64");
1505
1506                 gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, name);
1507
1508                 g_free (pixdata);
1509                 g_free (stream);
1510                 g_free (base64);
1511         }
1512
1513
1514         gl_debug (DEBUG_XML, "END");
1515 }
1516
1517 /*--------------------------------------------------------------------------*/
1518 /* PRIVATE.  Create top-level Span node.                                    */
1519 /*--------------------------------------------------------------------------*/
1520 static void
1521 xml_create_toplevel_span (xmlNodePtr        root,
1522                           xmlNsPtr          ns,
1523                           glLabelText      *object_text)
1524 {
1525         xmlNodePtr        node;
1526         gchar            *font_family;
1527         gdouble           font_size;
1528         GnomeFontWeight   font_weight;
1529         gboolean          font_italic_flag;
1530         guint             color;
1531         GtkJustification  just;
1532         gdouble           text_line_spacing;
1533         GList            *lines, *p_line, *p_node;
1534         glTextNode       *text_node;
1535         xmlNodePtr        child;
1536
1537         node = xmlNewChild (root, ns, "Span", NULL);
1538
1539         /* All span attrs at top level. */
1540         font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object_text));
1541         font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object_text));
1542         text_line_spacing = gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object_text));
1543         font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object_text));
1544         font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object_text));
1545         color = gl_label_object_get_text_color (GL_LABEL_OBJECT(object_text));
1546         just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object_text));
1547         xmlSetProp (node, "font_family", font_family);
1548         gl_xml_set_prop_double (node, "font_size", font_size);
1549         xmlSetProp (node, "font_weight", gl_util_weight_to_string (font_weight));
1550         gl_xml_set_prop_boolean (node, "font_italic", font_italic_flag);
1551         gl_xml_set_prop_uint_hex (node, "color", color);
1552         gl_xml_set_prop_double (node, "line_spacing", text_line_spacing);
1553
1554         /* Build children. */
1555         lines = gl_label_text_get_lines (GL_LABEL_TEXT(object_text));
1556         for (p_line = lines; p_line != NULL; p_line = p_line->next) {
1557
1558                 for (p_node = (GList *) p_line->data; p_node != NULL;
1559                      p_node = p_node->next) {
1560                         text_node = (glTextNode *) p_node->data;
1561
1562                         if (text_node->field_flag) {
1563                                 child = xmlNewChild (node, ns, "Field", NULL);
1564                                 xmlSetProp (child, "name", text_node->data);
1565                         } else {
1566                                 xmlNodeAddContent (node, text_node->data);
1567                         }
1568
1569                 }
1570
1571                 if ( p_line->next ) {
1572                         child = xmlNewChild (node, ns, "NL", NULL);
1573                 }
1574
1575         }
1576
1577         gl_text_node_lines_free (&lines);
1578         g_free (font_family);
1579
1580 }