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