]> git.sur5r.net Git - glabels/blob - glabels2/src/xml-label.c
2005-10-22 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 "xml-label.h"
26
27 #include <glib/gi18n.h>
28 #include <libxml/tree.h>
29 #include <libxml/parser.h>
30 #include <gdk-pixbuf/gdk-pixdata.h>
31
32 #include "label.h"
33 #include "label-object.h"
34 #include "label-text.h"
35 #include "label-box.h"
36 #include "label-line.h"
37 #include "label-ellipse.h"
38 #include "label-image.h"
39 #include "label-barcode.h"
40 #include "base64.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, (xmlChar *)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, (xmlChar *)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                                                 (xmlChar *)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                                                         (xmlChar *)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, (xmlChar *)"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, (xmlChar *)"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, (xmlChar *)"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, (xmlChar *)"Objects")) {
341                         xml_parse_objects (child_node, label);
342                 } else if (xmlStrEqual (child_node->name, (xmlChar *)"Merge")) {
343                         xml_parse_merge_fields (child_node, label);
344                 } else if (xmlStrEqual (child_node->name, (xmlChar *)"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, (xmlChar *)"Object-text")) {
380                         xml_parse_object_text (child, label);
381                 } else if (xmlStrEqual (child->name, (xmlChar *)"Object-box")) {
382                         xml_parse_object_box (child, label);
383                 } else if (xmlStrEqual (child->name, (xmlChar *)"Object-ellipse")) {
384                         xml_parse_object_ellipse (child, label);
385                 } else if (xmlStrEqual (child->name, (xmlChar *)"Object-line")) {
386                         xml_parse_object_line (child, label);
387                 } else if (xmlStrEqual (child->name, (xmlChar *)"Object-image")) {
388                         xml_parse_object_image (child, label);
389                 } else if (xmlStrEqual (child->name, (xmlChar *)"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         xmlChar          *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, (xmlChar *)"justify");
434         just = gl_util_string_to_just ((gchar *)string);
435         xmlFree (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,(xmlChar *) "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         glColorNode  *line_color_node;
479         gdouble       affine[6];
480         xmlChar      *string;
481         glColorNode  *fill_color_node;
482
483         gl_debug (DEBUG_XML, "START");
484
485         object = gl_label_box_new (label);
486
487         /* position attrs */
488         x = gl_xml_get_prop_length (node, "x", 0.0);
489         y = gl_xml_get_prop_length (node, "y", 0.0);
490         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
491
492         /* size attrs */
493         w = gl_xml_get_prop_length (node, "w", 0);
494         h = gl_xml_get_prop_length (node, "h", 0);
495         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
496
497         /* line attrs */
498         line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
499         gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
500         
501         line_color_node = gl_color_node_new_default ();
502         string = xmlGetProp (node, (xmlChar *)"line_color_field");
503         if ( string ) {
504                 line_color_node->field_flag = TRUE;
505                 line_color_node->key = g_strdup ((gchar *)string);
506                 xmlFree (string);
507         } else {
508                 line_color_node->color = gl_xml_get_prop_uint (node, "line_color", 0);
509         }
510         gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
511         gl_color_node_free (&line_color_node);
512
513
514         /* fill attrs */
515         fill_color_node = gl_color_node_new_default ();
516         string = xmlGetProp (node, (xmlChar *)"fill_color_field");
517         if ( string ) {
518                 fill_color_node->field_flag = TRUE;
519                 fill_color_node->key = g_strdup ((gchar *)string);
520         } else {
521                 fill_color_node->color = gl_xml_get_prop_uint (node, "fill_color", 0);
522         }
523         gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node);
524         gl_color_node_free (&fill_color_node);
525         
526         /* affine attrs */
527         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
528         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
529         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
530         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
531         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
532         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
533         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
534
535         gl_debug (DEBUG_XML, "END");
536 }
537
538 /*--------------------------------------------------------------------------*/
539 /* PRIVATE.  Parse XML Objects->Object-ellipse Node                         */
540 /*--------------------------------------------------------------------------*/
541 static void
542 xml_parse_object_ellipse (xmlNodePtr  node,
543                           glLabel    *label)
544 {
545         GObject     *object;
546         gdouble      x, y;
547         gdouble      w, h;
548         gdouble      line_width;
549         glColorNode *line_color_node;
550         gdouble      affine[6];
551         xmlChar     *string;
552         glColorNode *fill_color_node;
553
554         gl_debug (DEBUG_XML, "START");
555
556         object = gl_label_ellipse_new (label);
557
558         /* position attrs */
559         x = gl_xml_get_prop_length (node, "x", 0.0);
560         y = gl_xml_get_prop_length (node, "y", 0.0);
561         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
562
563         /* size attrs */
564         w = gl_xml_get_prop_length (node, "w", 0);
565         h = gl_xml_get_prop_length (node, "h", 0);
566         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
567
568         /* line attrs */
569         line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
570         gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
571
572         line_color_node = gl_color_node_new_default ();
573         string = xmlGetProp (node, (xmlChar *)"line_color_field");
574         if ( string ) {
575                 line_color_node->field_flag = TRUE;
576                 line_color_node->key = g_strdup ((gchar *)string);
577                 xmlFree (string);
578         } else {
579                 line_color_node->color = gl_xml_get_prop_uint (node, "line_color", 0);          
580         }
581         gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
582         gl_color_node_free (&line_color_node);
583
584
585         /* fill attrs */
586         fill_color_node = gl_color_node_new_default ();
587         string = xmlGetProp (node, (xmlChar *)"fill_color_field");
588         if ( string ) {
589                 fill_color_node->field_flag = TRUE;
590                 fill_color_node->key = g_strdup ((gchar *)string);
591                 xmlFree (string);
592         } else {
593                 fill_color_node->color = gl_xml_get_prop_uint (node, "fill_color", 0);
594         }
595         gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color_node);
596         gl_color_node_free (&fill_color_node);
597
598         /* affine attrs */
599         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
600         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
601         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
602         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
603         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
604         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
605         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
606
607         gl_debug (DEBUG_XML, "END");
608 }
609
610 /*--------------------------------------------------------------------------*/
611 /* PRIVATE.  Parse XML Objects->Object-line Node                            */
612 /*--------------------------------------------------------------------------*/
613 static void
614 xml_parse_object_line (xmlNodePtr  node,
615                        glLabel    *label)
616 {
617         GObject     *object;
618         gdouble      x, y;
619         gdouble      dx, dy;
620         gdouble      line_width;
621         glColorNode *line_color_node;
622         gdouble      affine[6];
623         xmlChar     *string;
624
625         gl_debug (DEBUG_XML, "START");
626
627         object = gl_label_line_new (label);
628
629         /* position attrs */
630         x = gl_xml_get_prop_length (node, "x", 0.0);
631         y = gl_xml_get_prop_length (node, "y", 0.0);
632         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
633
634         /* length attrs */
635         dx = gl_xml_get_prop_length (node, "dx", 0);
636         dy = gl_xml_get_prop_length (node, "dy", 0);
637         gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy);
638
639         /* line attrs */
640         line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
641         gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
642         
643         line_color_node = gl_color_node_new_default ();
644         string = xmlGetProp (node, (xmlChar *)"line_color_field");
645         if ( string ) {
646                 line_color_node->field_flag = TRUE;
647                 line_color_node->key = g_strdup ((gchar *)string);
648                 xmlFree (string);
649         } else {
650                 line_color_node->color = gl_xml_get_prop_uint (node, "line_color", 0);          
651         }
652         gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color_node);
653         gl_color_node_free (&line_color_node);
654
655         /* affine attrs */
656         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
657         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
658         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
659         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
660         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
661         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
662         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
663
664         gl_debug (DEBUG_XML, "END");
665 }
666
667 /*--------------------------------------------------------------------------*/
668 /* PRIVATE.  Parse XML Objects->Object-image Node                           */
669 /*--------------------------------------------------------------------------*/
670 static void
671 xml_parse_object_image (xmlNodePtr  node,
672                         glLabel    *label)
673 {
674         GObject      *object;
675         gdouble       x, y;
676         gdouble       w, h;
677         xmlChar      *string;
678         glTextNode   *filename;
679         gdouble       affine[6];
680
681         gl_debug (DEBUG_XML, "START");
682
683         object = gl_label_image_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         /* src or field attr */
691         string = xmlGetProp (node, (xmlChar *)"src");
692         if ( string ) {
693                 filename = g_new0 (glTextNode, 1);
694                 filename->field_flag = FALSE;
695                 filename->data = g_strdup ((gchar *)string);
696                 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
697                 gl_text_node_free (&filename);
698                 xmlFree (string);
699         } else {
700                 string = xmlGetProp (node, (xmlChar *)"field");
701                 if ( string ) {
702                         filename = g_new0 (glTextNode, 1);
703                         filename->field_flag = TRUE;
704                         filename->data = g_strdup ((gchar *)string);
705                         gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
706                         gl_text_node_free (&filename);
707                         xmlFree (string);
708                 } else {
709                         g_warning ("Missing Object-image src or field attr");
710                 }
711         }
712
713         /* size attrs */
714         w = gl_xml_get_prop_length (node, "w", 0);
715         h = gl_xml_get_prop_length (node, "h", 0);
716         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
717
718         /* affine attrs */
719         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
720         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
721         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
722         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
723         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
724         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
725         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
726
727         gl_debug (DEBUG_XML, "END");
728 }
729
730 /*--------------------------------------------------------------------------*/
731 /* PRIVATE.  Parse XML Objects->Object-barcode Node                         */
732 /*--------------------------------------------------------------------------*/
733 static void
734 xml_parse_object_barcode (xmlNodePtr  node,
735                           glLabel    *label)
736 {
737         GObject            *object;
738         gdouble             x, y;
739         gdouble             w, h;
740         xmlChar            *string;
741         glTextNode         *text_node;
742         xmlChar            *id;
743         gboolean            text_flag;
744         gboolean            checksum_flag;
745         glColorNode        *color_node;
746         guint               format_digits;
747         gdouble             affine[6];
748
749         gl_debug (DEBUG_XML, "START");
750
751         object = gl_label_barcode_new (label);
752
753         /* position attrs */
754         x = gl_xml_get_prop_length (node, "x", 0.0);
755         y = gl_xml_get_prop_length (node, "y", 0.0);
756         gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
757
758         /* size attrs */
759         w = gl_xml_get_prop_length (node, "w", 0);
760         h = gl_xml_get_prop_length (node, "h", 0);
761         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
762
763         /* prop attrs */
764         id = xmlGetProp (node, (xmlChar *)"style");
765         text_flag = gl_xml_get_prop_boolean (node, "text", FALSE);
766         checksum_flag = gl_xml_get_prop_boolean (node, "checksum", TRUE);
767         format_digits = gl_xml_get_prop_uint (node, "format", 10);
768         gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
769                                     (gchar *)id, text_flag, checksum_flag, format_digits);
770         xmlFree (id);
771         
772         color_node = gl_color_node_new_default ();
773         string = xmlGetProp (node, (xmlChar *)"color_field");
774         if ( string ) {
775                 color_node->field_flag = TRUE;
776                 color_node->key = g_strdup ((gchar *)string);
777                 xmlFree (string);
778         } else {
779                 color_node->color = gl_xml_get_prop_uint (node, "color", 0);            
780         }
781         gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color_node);
782         gl_color_node_free (&color_node);
783
784         /* data or field attr */
785         string = xmlGetProp (node, (xmlChar *)"data");
786         if ( string ) {
787                 text_node = g_new0 (glTextNode, 1);
788                 text_node->field_flag = FALSE;
789                 text_node->data = g_strdup ((gchar *)string);
790                 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
791                 gl_text_node_free (&text_node);
792                 xmlFree (string);
793         } else {
794                 string = xmlGetProp (node, (xmlChar *)"field");
795                 if ( string ) {
796                         text_node = g_new0 (glTextNode, 1);
797                         text_node->field_flag = TRUE;
798                         text_node->data = g_strdup ((gchar *)string);
799                         gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
800                         gl_text_node_free (&text_node);
801                         xmlFree (string);
802                 } else {
803                         g_warning ("Missing Object-barcode data or field attr");
804                 }
805         }
806
807         /* affine attrs */
808         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
809         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
810         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
811         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
812         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
813         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
814         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
815
816         gl_debug (DEBUG_XML, "END");
817 }
818
819 /*--------------------------------------------------------------------------*/
820 /* PRIVATE.  Parse XML merge fields tag.                                    */
821 /*--------------------------------------------------------------------------*/
822 static void
823 xml_parse_merge_fields (xmlNodePtr  node,
824                         glLabel    *label)
825 {
826         xmlNodePtr  child;
827         xmlChar    *string;
828         glMerge    *merge;
829
830         gl_debug (DEBUG_XML, "START");
831
832         string = xmlGetProp (node, (xmlChar *)"type");
833         merge = gl_merge_new ((gchar *)string);
834         xmlFree (string);
835
836         string = xmlGetProp (node, (xmlChar *)"src");
837         gl_merge_set_src (merge, (gchar *)string);
838         xmlFree (string);
839
840         gl_label_set_merge (label, merge);
841
842         g_object_unref (G_OBJECT(merge));
843
844         gl_debug (DEBUG_XML, "END");
845 }
846
847 /*--------------------------------------------------------------------------*/
848 /* PRIVATE.  Parse XML data tag.                                            */
849 /*--------------------------------------------------------------------------*/
850 static void
851 xml_parse_data (xmlNodePtr  node,
852                 glLabel    *label)
853 {
854         xmlNodePtr  child;
855
856         gl_debug (DEBUG_XML, "START");
857
858         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
859
860                 if (xmlStrEqual (child->name, (xmlChar *)"Pixdata")) {
861                         xml_parse_pixdata (child, label);
862                 } else {
863                         if (!xmlNodeIsText (child)) {
864                                 g_warning (_("bad node in Data node =  \"%s\""),
865                                            child->name);
866                         }
867                 }
868         }
869
870         gl_debug (DEBUG_XML, "END");
871 }
872
873 /*--------------------------------------------------------------------------*/
874 /* PRIVATE.  Parse XML pixbuf data tag.                                     */
875 /*--------------------------------------------------------------------------*/
876 static void
877 xml_parse_pixdata (xmlNodePtr  node,
878                    glLabel    *label)
879 {
880         xmlChar    *name, *base64;
881         guchar     *stream;
882         guint       stream_length;
883         gboolean    ret;
884         GdkPixdata *pixdata;
885         GdkPixbuf  *pixbuf;
886         GHashTable *pixbuf_cache;
887
888         gl_debug (DEBUG_XML, "START");
889
890         name = xmlGetProp (node, (xmlChar *)"name");
891         base64 = xmlNodeGetContent (node);
892
893         stream = gl_base64_decode ((gchar *)base64, &stream_length);
894         pixdata = g_new0 (GdkPixdata, 1);
895         ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
896
897         if (ret) {
898                 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
899
900                 pixbuf_cache = gl_label_get_pixbuf_cache (label);
901                 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, (gchar *)name, pixbuf);
902         }
903
904         xmlFree (name);
905         xmlFree (base64);
906
907         g_free (stream);
908         g_free (pixdata);
909
910         gl_debug (DEBUG_XML, "END");
911 }
912
913 /*--------------------------------------------------------------------------*/
914 /* PRIVATE.  Parse top-level Span tag.                                      */
915 /*--------------------------------------------------------------------------*/
916 static void
917 xml_parse_toplevel_span  (xmlNodePtr        node,
918                           glLabelObject    *object)
919 {
920         xmlChar          *font_family;
921         gdouble           font_size;
922         GnomeFontWeight   font_weight;
923         gboolean          font_italic_flag;
924         glColorNode      *color_node;
925         gdouble           text_line_spacing;
926         xmlChar          *string;
927         GList            *lines, *text_nodes;
928         xmlNodePtr        child;
929         glTextNode       *text_node;
930
931         gl_debug (DEBUG_XML, "START");
932
933         /* Font family attr */
934         font_family = xmlGetProp (node, (xmlChar *)"font_family");
935         gl_label_object_set_font_family (object, (gchar *)font_family);
936         xmlFree (font_family);
937
938         /* Font size attr */
939         font_size = gl_xml_get_prop_double (node, "font_size", 0.0);
940         gl_label_object_set_font_size (object, font_size);
941
942         /* Font weight attr */
943         string = xmlGetProp (node, (xmlChar *)"font_weight");
944         font_weight = gl_util_string_to_weight ((gchar *)string);
945         xmlFree (string);
946         gl_label_object_set_font_weight (object, font_weight);
947
948         /* Font italic flag attr */
949         font_italic_flag = gl_xml_get_prop_boolean (node, "font_italic", FALSE);
950         gl_label_object_set_font_italic_flag (object, font_italic_flag);
951
952         /* Text color attr */
953         color_node = gl_color_node_new_default ();
954         string = xmlGetProp (node, (xmlChar *)"color_field");
955         if ( string ) {
956                 color_node->field_flag = TRUE;
957                 color_node->key = g_strdup ((gchar *)string);
958                 xmlFree (string);
959         } else {
960                 color_node->color = gl_xml_get_prop_uint (node, "color", 0);            
961         }
962         gl_label_object_set_text_color (object, color_node);
963         gl_color_node_free (&color_node);
964         
965
966         /* Text line spacing attr  */
967         text_line_spacing = gl_xml_get_prop_double (node, "line_spacing", 1.0);
968         gl_label_object_set_text_line_spacing (object, text_line_spacing); 
969
970         /* Now descend children, and build lines of text nodes */
971         lines = NULL;
972         text_nodes = NULL;
973         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
974
975                 if (xmlNodeIsText (child)) {
976                         xmlChar *data = xmlNodeGetContent (child); 
977
978                         /* Hack: if the first char is LF, it's a xml formatting string */
979                         if (data[0] != '\n') { 
980                                 /* Literal text */
981                                 text_node = g_new0 (glTextNode, 1);
982                                 text_node->field_flag = FALSE;
983                                 text_node->data = g_strdup ((gchar *)data);
984                                 text_nodes = g_list_append (text_nodes, text_node);
985                         }
986                         xmlFree (data);
987
988                 } else if (xmlStrEqual (child->name, (xmlChar *)"Span")) {
989
990                         g_warning ("Unexpected rich text (not supported, yet!)");
991
992                 } else if (xmlStrEqual (child->name, (xmlChar *)"Field")) {
993
994                         /* Field node */
995                         string = xmlGetProp (child, (xmlChar *)"name");
996                         text_node = g_new0 (glTextNode, 1);
997                         text_node->field_flag = TRUE;
998                         text_node->data = g_strdup ((gchar *)string);
999                         text_nodes = g_list_append (text_nodes, text_node);
1000                         xmlFree (string);
1001
1002                 } else if (xmlStrEqual (child->name, (xmlChar *)"NL")) {
1003
1004                         /* Store line. */
1005                         lines = g_list_append (lines, text_nodes);
1006                         text_nodes = NULL;
1007
1008                 } else {
1009                         g_warning ("Unexpected Span child: \"%s\"", child->name);
1010                 }
1011
1012         }
1013         if ( text_nodes ) {
1014                 /* Store last line. */
1015                 lines = g_list_append (lines, text_nodes);
1016                 text_nodes = NULL;
1017         }
1018         gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
1019         gl_text_node_lines_free (&lines);
1020
1021         gl_debug (DEBUG_XML, "END");
1022 }
1023
1024 /****************************************************************************/
1025 /* Save label to xml label file.                                            */
1026 /****************************************************************************/
1027 void
1028 gl_xml_label_save (glLabel          *label,
1029                    const gchar      *utf8_filename,
1030                    glXMLLabelStatus *status)
1031 {
1032         xmlDocPtr doc;
1033         gint      xml_ret;
1034         gchar     *filename;
1035
1036         gl_debug (DEBUG_XML, "START");
1037
1038         doc = xml_label_to_doc (label, status);
1039
1040         filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
1041         if (!filename)
1042                 g_warning (_("Utf8 conversion error."));
1043         else {
1044                 xmlSetDocCompressMode (doc, gl_label_get_compression (label));
1045                 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
1046                 xmlFreeDoc (doc);
1047                 if (xml_ret == -1) {
1048
1049                         g_warning (_("Problem saving xml file."));
1050                         *status = XML_LABEL_ERROR_SAVE_FILE;
1051
1052                 } else {
1053
1054                         gl_label_set_filename (label, utf8_filename);
1055                         gl_label_clear_modified (label);
1056
1057                 }
1058                 g_free (filename);
1059         }
1060
1061         gl_debug (DEBUG_XML, "END");
1062 }
1063
1064 /****************************************************************************/
1065 /* Save label to xml buffer.                                                */
1066 /****************************************************************************/
1067 gchar *
1068 gl_xml_label_save_buffer (glLabel          *label,
1069                           glXMLLabelStatus *status)
1070 {
1071         xmlDocPtr  doc;
1072         gint       size;
1073         gchar     *buffer;
1074
1075         gl_debug (DEBUG_XML, "START");
1076
1077         doc = xml_label_to_doc (label, status);
1078
1079         xmlDocDumpMemory (doc, (xmlChar **)&buffer, &size);
1080         xmlFreeDoc (doc);
1081
1082         gl_label_clear_modified (label);
1083
1084         gl_debug (DEBUG_XML, "END");
1085
1086         return buffer;
1087 }
1088
1089 /*--------------------------------------------------------------------------*/
1090 /* PRIVATE.  Convert label to xml doc structure.                            */
1091 /*--------------------------------------------------------------------------*/
1092 static xmlDocPtr
1093 xml_label_to_doc (glLabel          *label,
1094                   glXMLLabelStatus *status)
1095 {
1096         xmlDocPtr   doc;
1097         xmlNsPtr    ns;
1098         glTemplate *template;
1099         glMerge    *merge;
1100
1101         gl_debug (DEBUG_XML, "START");
1102
1103         LIBXML_TEST_VERSION;
1104
1105         doc = xmlNewDoc ((xmlChar *)"1.0");
1106         doc->xmlRootNode = xmlNewDocNode (doc, NULL, (xmlChar *)"Glabels-document", NULL);
1107
1108         ns = xmlNewNs (doc->xmlRootNode, (xmlChar *)GL_XML_NAME_SPACE, NULL);
1109         xmlSetNs (doc->xmlRootNode, ns);
1110
1111         template = gl_label_get_template (label);
1112         gl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
1113
1114         xml_create_objects (doc->xmlRootNode, ns, label);
1115
1116         merge = gl_label_get_merge (label);
1117         gl_debug (DEBUG_XML, "merge=%p", merge);
1118         if (merge != NULL) {
1119                 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1120                 g_object_unref (G_OBJECT(merge));
1121         }
1122
1123         xml_create_data (doc->xmlRootNode, ns, label);
1124
1125         gl_debug (DEBUG_XML, "END");
1126
1127         *status = XML_LABEL_OK;
1128         return doc;
1129 }
1130
1131 /*--------------------------------------------------------------------------*/
1132 /* PRIVATE.  Add XML Objects Node                                           */
1133 /*--------------------------------------------------------------------------*/
1134 static void
1135 xml_create_objects (xmlNodePtr  root,
1136                     xmlNsPtr    ns,
1137                     glLabel    *label)
1138 {
1139         xmlNodePtr     node;
1140         gboolean       rotate_flag;
1141         GList         *p;
1142         glLabelObject *object;
1143
1144         gl_debug (DEBUG_XML, "START");
1145
1146         rotate_flag = gl_label_get_rotate_flag (label);
1147
1148         node = xmlNewChild (root, ns, (xmlChar *)"Objects", NULL);
1149         xmlSetProp (node, (xmlChar *)"id", (xmlChar *)"0");
1150         gl_xml_set_prop_boolean (node, "rotate", rotate_flag);
1151
1152         for (p = label->objects; p != NULL; p = p->next) {
1153
1154                 object = GL_LABEL_OBJECT(p->data);
1155
1156                 if ( GL_IS_LABEL_TEXT(object) ) {
1157                         xml_create_object_text (node, ns, object);
1158                 } else if ( GL_IS_LABEL_BOX(object) ) {
1159                         xml_create_object_box (node, ns, object);
1160                 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1161                         xml_create_object_ellipse (node, ns, object);
1162                 } else if ( GL_IS_LABEL_LINE(object) ) {
1163                         xml_create_object_line (node, ns, object);
1164                 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1165                         xml_create_object_image (node, ns, object);
1166                 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1167                         xml_create_object_barcode (node, ns, object);
1168                 } else {
1169                         g_warning ("Unknown label object");
1170                 }
1171
1172         }
1173
1174         gl_debug (DEBUG_XML, "END");
1175 }
1176
1177 /*--------------------------------------------------------------------------*/
1178 /* PRIVATE.  Add XML Objects->Object-text Node                              */
1179 /*--------------------------------------------------------------------------*/
1180 static void
1181 xml_create_object_text (xmlNodePtr     root,
1182                         xmlNsPtr       ns,
1183                         glLabelObject *object)
1184 {
1185         xmlNodePtr        node;
1186         gdouble           x, y;
1187         gdouble           w, h;
1188         GtkJustification  just;
1189         gboolean          auto_shrink;
1190         gdouble           affine[6];
1191
1192         gl_debug (DEBUG_XML, "START");
1193
1194         node = xmlNewChild (root, ns, (xmlChar *)"Object-text", NULL);
1195
1196         /* position attrs */
1197         gl_label_object_get_position (object, &x, &y);
1198         gl_xml_set_prop_length (node, "x", x);
1199         gl_xml_set_prop_length (node, "y", y);
1200
1201         /* size attrs */
1202         gl_label_text_get_box ( GL_LABEL_TEXT(object), &w, &h);
1203         gl_xml_set_prop_length (node, "w", w);
1204         gl_xml_set_prop_length (node, "h", h);
1205
1206         /* justify attr */
1207         just = gl_label_object_get_text_alignment (object);
1208         xmlSetProp (node, (xmlChar *)"justify", (xmlChar *)gl_util_just_to_string (just));
1209
1210         /* auto_shrink attr */
1211         auto_shrink = gl_label_text_get_auto_shrink (GL_LABEL_TEXT (object));
1212         gl_xml_set_prop_boolean (node, "auto_shrink", auto_shrink);
1213
1214         /* affine attrs */
1215         gl_label_object_get_affine (object, affine);
1216         gl_xml_set_prop_double (node, "a0", affine[0]);
1217         gl_xml_set_prop_double (node, "a1", affine[1]);
1218         gl_xml_set_prop_double (node, "a2", affine[2]);
1219         gl_xml_set_prop_double (node, "a3", affine[3]);
1220         gl_xml_set_prop_double (node, "a4", affine[4]);
1221         gl_xml_set_prop_double (node, "a5", affine[5]);
1222
1223         /* Add children */
1224         xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1225
1226         gl_debug (DEBUG_XML, "END");
1227 }
1228
1229 /*--------------------------------------------------------------------------*/
1230 /* PRIVATE.  Add XML Objects->Object-box Node                               */
1231 /*--------------------------------------------------------------------------*/
1232 static void
1233 xml_create_object_box (xmlNodePtr     root,
1234                        xmlNsPtr       ns,
1235                        glLabelObject *object)
1236 {
1237         xmlNodePtr        node;
1238         gdouble           x, y;
1239         gdouble           w, h;
1240         gdouble           line_width;
1241         glColorNode      *line_color_node;
1242         gdouble           affine[6];
1243         glColorNode *fill_color_node;
1244
1245         gl_debug (DEBUG_XML, "START");
1246
1247         node = xmlNewChild (root, ns, (xmlChar *)"Object-box", NULL);
1248
1249         /* position attrs */
1250         gl_label_object_get_position (object, &x, &y);
1251         gl_xml_set_prop_length (node, "x", x);
1252         gl_xml_set_prop_length (node, "y", y);
1253
1254         /* size attrs */
1255         gl_label_object_get_size (object, &w, &h);
1256         gl_xml_set_prop_length (node, "w", w);
1257         gl_xml_set_prop_length (node, "h", h);
1258
1259         /* line attrs */
1260         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1261         gl_xml_set_prop_length (node, "line_width", line_width);
1262         
1263         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1264         if (line_color_node->field_flag)
1265         {
1266                 xmlSetProp (node, (xmlChar *)"line_color_field", (xmlChar *)line_color_node->key);
1267         }
1268         else
1269         {
1270                 gl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1271         }
1272         gl_color_node_free (&line_color_node);
1273
1274         /* fill attrs (color or field) */
1275         fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1276         if (fill_color_node->field_flag)
1277         {
1278                 xmlSetProp (node, (xmlChar *)"fill_color_field", (xmlChar *)fill_color_node->key);
1279         }
1280         else
1281         {
1282                 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color_node->color);
1283         }
1284         gl_color_node_free (&fill_color_node);
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-ellipse Node                           */
1300 /*--------------------------------------------------------------------------*/
1301 static void
1302 xml_create_object_ellipse (xmlNodePtr     root,
1303                            xmlNsPtr       ns,
1304                            glLabelObject *object)
1305 {
1306         xmlNodePtr        node;
1307         gdouble           x, y;
1308         gdouble           w, h;
1309         gdouble           line_width;
1310         glColorNode      *line_color_node;
1311         gdouble           affine[6];
1312         glColorNode *fill_color_node;
1313
1314         gl_debug (DEBUG_XML, "START");
1315
1316         node = xmlNewChild (root, ns, (xmlChar *)"Object-ellipse", NULL);
1317
1318         /* position attrs */
1319         gl_label_object_get_position (object, &x, &y);
1320         gl_xml_set_prop_length (node, "x", x);
1321         gl_xml_set_prop_length (node, "y", y);
1322
1323         /* size attrs */
1324         gl_label_object_get_size (object, &w, &h);
1325         gl_xml_set_prop_length (node, "w", w);
1326         gl_xml_set_prop_length (node, "h", h);
1327
1328         /* line attrs */
1329         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1330         gl_xml_set_prop_length (node, "line_width", line_width);
1331         
1332         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1333         if (line_color_node->field_flag)
1334         {
1335                 xmlSetProp (node, (xmlChar *)"line_color_field", (xmlChar *)line_color_node->key);
1336         }
1337         else
1338         {
1339                 gl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1340         }
1341         gl_color_node_free (&line_color_node);
1342
1343
1344         /* fill attrs (color or field) */
1345         fill_color_node = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1346         if (fill_color_node->field_flag)
1347         {
1348                 xmlSetProp (node, (xmlChar *)"fill_color_field", (xmlChar *)fill_color_node->key);
1349         }
1350         else
1351         {
1352                 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color_node->color);
1353         }
1354         gl_color_node_free (&fill_color_node);
1355
1356         /* affine attrs */
1357         gl_label_object_get_affine (object, affine);
1358         gl_xml_set_prop_double (node, "a0", affine[0]);
1359         gl_xml_set_prop_double (node, "a1", affine[1]);
1360         gl_xml_set_prop_double (node, "a2", affine[2]);
1361         gl_xml_set_prop_double (node, "a3", affine[3]);
1362         gl_xml_set_prop_double (node, "a4", affine[4]);
1363         gl_xml_set_prop_double (node, "a5", affine[5]);
1364
1365         gl_debug (DEBUG_XML, "END");
1366 }
1367
1368 /*--------------------------------------------------------------------------*/
1369 /* PRIVATE.  Add XML Objects->Object-line Node                              */
1370 /*--------------------------------------------------------------------------*/
1371 static void
1372 xml_create_object_line (xmlNodePtr     root,
1373                         xmlNsPtr       ns,
1374                         glLabelObject *object)
1375 {
1376         xmlNodePtr        node;
1377         gdouble           x, y;
1378         gdouble           dx, dy;
1379         gdouble           line_width;
1380         glColorNode      *line_color_node;
1381         gdouble           affine[6];
1382
1383         gl_debug (DEBUG_XML, "START");
1384
1385         node = xmlNewChild (root, ns, (xmlChar *)"Object-line", NULL);
1386
1387         /* position attrs */
1388         gl_label_object_get_position (object, &x, &y);
1389         gl_xml_set_prop_length (node, "x", x);
1390         gl_xml_set_prop_length (node, "y", y);
1391
1392         /* length attrs */
1393         gl_label_object_get_size (object, &dx, &dy);
1394         gl_xml_set_prop_length (node, "dx", dx);
1395         gl_xml_set_prop_length (node, "dy", dy);
1396
1397         /* line attrs */
1398         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1399         gl_xml_set_prop_length (node, "line_width", line_width);
1400         
1401         line_color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1402         if (line_color_node->field_flag)
1403         {
1404                 xmlSetProp (node, (xmlChar *)"line_color_field", (xmlChar *)line_color_node->key);
1405         }
1406         else
1407         {
1408                 gl_xml_set_prop_uint_hex (node, "line_color", line_color_node->color);
1409         }
1410         gl_color_node_free (&line_color_node);
1411
1412
1413         /* affine attrs */
1414         gl_label_object_get_affine (object, affine);
1415         gl_xml_set_prop_double (node, "a0", affine[0]);
1416         gl_xml_set_prop_double (node, "a1", affine[1]);
1417         gl_xml_set_prop_double (node, "a2", affine[2]);
1418         gl_xml_set_prop_double (node, "a3", affine[3]);
1419         gl_xml_set_prop_double (node, "a4", affine[4]);
1420         gl_xml_set_prop_double (node, "a5", affine[5]);
1421
1422         gl_debug (DEBUG_XML, "END");
1423 }
1424
1425 /*--------------------------------------------------------------------------*/
1426 /* PRIVATE.  Add XML Objects->Object-image Node                             */
1427 /*--------------------------------------------------------------------------*/
1428 static void
1429 xml_create_object_image (xmlNodePtr     root,
1430                          xmlNsPtr       ns,
1431                          glLabelObject *object)
1432 {
1433         xmlNodePtr        node;
1434         gdouble           x, y;
1435         gdouble           w, h;
1436         glTextNode       *filename;
1437         gdouble           affine[6];
1438
1439         gl_debug (DEBUG_XML, "START");
1440
1441         node = xmlNewChild (root, ns, (xmlChar *)"Object-image", NULL);
1442
1443         /* position attrs */
1444         gl_label_object_get_position (object, &x, &y);
1445         gl_xml_set_prop_length (node, "x", x);
1446         gl_xml_set_prop_length (node, "y", y);
1447
1448         /* size attrs */
1449         gl_label_object_get_size (object, &w, &h);
1450         gl_xml_set_prop_length (node, "w", w);
1451         gl_xml_set_prop_length (node, "h", h);
1452
1453         /* src OR field attr */
1454         filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1455         if (filename->field_flag) {
1456                 xmlSetProp (node, (xmlChar *)"field", (xmlChar *)filename->data);
1457         } else {
1458                 xmlSetProp (node, (xmlChar *)"src", (xmlChar *)filename->data);
1459         }
1460         gl_text_node_free (&filename);
1461
1462         /* affine attrs */
1463         gl_label_object_get_affine (object, affine);
1464         gl_xml_set_prop_double (node, "a0", affine[0]);
1465         gl_xml_set_prop_double (node, "a1", affine[1]);
1466         gl_xml_set_prop_double (node, "a2", affine[2]);
1467         gl_xml_set_prop_double (node, "a3", affine[3]);
1468         gl_xml_set_prop_double (node, "a4", affine[4]);
1469         gl_xml_set_prop_double (node, "a5", affine[5]);
1470
1471         gl_debug (DEBUG_XML, "END");
1472 }
1473
1474 /*--------------------------------------------------------------------------*/
1475 /* PRIVATE.  Add XML Objects->Object-barcode Node                           */
1476 /*--------------------------------------------------------------------------*/
1477 static void
1478 xml_create_object_barcode (xmlNodePtr     root,
1479                            xmlNsPtr       ns,
1480                            glLabelObject *object)
1481 {
1482         xmlNodePtr        node;
1483         gdouble           x, y;
1484         gdouble           w, h;
1485         glTextNode       *text_node;
1486         gchar            *id;
1487         gboolean          text_flag;
1488         gboolean          checksum_flag;
1489         glColorNode      *color_node;
1490         guint             format_digits;
1491         gdouble           affine[6];
1492
1493         gl_debug (DEBUG_XML, "START");
1494
1495         node = xmlNewChild (root, ns, (xmlChar *)"Object-barcode", NULL);
1496
1497         /* position attrs */
1498         gl_label_object_get_position (object, &x, &y);
1499         gl_xml_set_prop_length (node, "x", x);
1500         gl_xml_set_prop_length (node, "y", y);
1501
1502         /* size attrs */
1503         gl_label_object_get_size (object, &w, &h);
1504         gl_xml_set_prop_length (node, "w", w);
1505         gl_xml_set_prop_length (node, "h", h);
1506
1507         /* Barcode properties attrs */
1508         gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1509                                     &id, &text_flag, &checksum_flag, &format_digits);
1510         xmlSetProp (node, (xmlChar *)"style", (xmlChar *)id);
1511         gl_xml_set_prop_boolean (node, "text", text_flag);
1512         gl_xml_set_prop_boolean (node, "checksum", checksum_flag);
1513         
1514         g_free (id);
1515         
1516         color_node = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1517         if (color_node->field_flag)
1518         {
1519                 xmlSetProp (node, (xmlChar *)"color_field", (xmlChar *)color_node->key);
1520         }
1521         else
1522         {
1523                 gl_xml_set_prop_uint_hex (node, "color", color_node->color);
1524         }
1525         gl_color_node_free (&color_node);
1526
1527
1528         /* data OR field attr */
1529         text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1530         if (text_node->field_flag) {
1531                 xmlSetProp (node, (xmlChar *)"field", (xmlChar *)text_node->data);
1532                 gl_xml_set_prop_int (node, "format", format_digits);
1533         } else {
1534                 xmlSetProp (node, (xmlChar *)"data", (xmlChar *)text_node->data);
1535         }
1536         gl_text_node_free (&text_node);
1537
1538         /* affine attrs */
1539         gl_label_object_get_affine (object, affine);
1540         gl_xml_set_prop_double (node, "a0", affine[0]);
1541         gl_xml_set_prop_double (node, "a1", affine[1]);
1542         gl_xml_set_prop_double (node, "a2", affine[2]);
1543         gl_xml_set_prop_double (node, "a3", affine[3]);
1544         gl_xml_set_prop_double (node, "a4", affine[4]);
1545         gl_xml_set_prop_double (node, "a5", affine[5]);
1546
1547         gl_debug (DEBUG_XML, "END");
1548 }
1549
1550 /*--------------------------------------------------------------------------*/
1551 /* PRIVATE.  Add XML Label Merge Fields Node                                */
1552 /*--------------------------------------------------------------------------*/
1553 static void
1554 xml_create_merge_fields (xmlNodePtr  root,
1555                          xmlNsPtr    ns,
1556                          glLabel    *label)
1557 {
1558         xmlNodePtr  node, child;
1559         gchar      *string;
1560         GList      *p;
1561         glMerge    *merge;
1562
1563         gl_debug (DEBUG_XML, "START");
1564
1565         merge = gl_label_get_merge (label);
1566
1567         node = xmlNewChild (root, ns, (xmlChar *)"Merge", NULL);
1568
1569         string = gl_merge_get_name (merge);
1570         xmlSetProp (node, (xmlChar *)"type", (xmlChar *)string);
1571         g_free (string);
1572
1573         string = gl_merge_get_src (merge);
1574         xmlSetProp (node, (xmlChar *)"src", (xmlChar *)string);
1575         g_free (string);
1576
1577         g_object_unref (G_OBJECT(merge));
1578
1579         gl_debug (DEBUG_XML, "END");
1580 }
1581
1582 /*--------------------------------------------------------------------------*/
1583 /* PRIVATE.  Add XML Label Data Node                                        */
1584 /*--------------------------------------------------------------------------*/
1585 static void
1586 xml_create_data (xmlNodePtr  root,
1587                  xmlNsPtr    ns,
1588                  glLabel    *label)
1589 {
1590         xmlNodePtr  node;
1591         GList      *name_list, *p;
1592         GHashTable *pixbuf_cache;
1593
1594         gl_debug (DEBUG_XML, "START");
1595
1596         node = xmlNewChild (root, ns, (xmlChar *)"Data", NULL);
1597
1598         pixbuf_cache = gl_label_get_pixbuf_cache (label);
1599         name_list = gl_pixbuf_cache_get_name_list (pixbuf_cache);
1600
1601         for (p = name_list; p != NULL; p=p->next) {
1602                 xml_create_pixdata (node, ns, label, p->data);
1603         }
1604
1605         gl_pixbuf_cache_free_name_list (name_list);
1606
1607
1608         gl_debug (DEBUG_XML, "END");
1609 }
1610
1611 /*--------------------------------------------------------------------------*/
1612 /* PRIVATE.  Add XML Label Data Pixbuf Node                                 */
1613 /*--------------------------------------------------------------------------*/
1614 static void
1615 xml_create_pixdata (xmlNodePtr  root,
1616                     xmlNsPtr    ns,
1617                     glLabel    *label,
1618                     gchar      *name)
1619 {
1620         xmlNodePtr  node;
1621         GHashTable *pixbuf_cache;
1622         GdkPixbuf  *pixbuf;
1623         GdkPixdata *pixdata;
1624         guchar     *stream;
1625         guint       stream_length;
1626         gchar      *base64;
1627
1628         gl_debug (DEBUG_XML, "START");
1629
1630         pixbuf_cache = gl_label_get_pixbuf_cache (label);
1631
1632         pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, name);
1633         if ( pixbuf != NULL ) {
1634
1635                 pixdata = g_new0 (GdkPixdata, 1);
1636                 gdk_pixdata_from_pixbuf (pixdata, pixbuf, FALSE);
1637                 stream = gdk_pixdata_serialize (pixdata, &stream_length);
1638                 base64 = gl_base64_encode (stream, stream_length);
1639
1640                 node = xmlNewChild (root, ns, (xmlChar *)"Pixdata", (xmlChar *)base64);
1641                 xmlSetProp (node, (xmlChar *)"name", (xmlChar *)name);
1642                 xmlSetProp (node, (xmlChar *)"encoding", (xmlChar *)"Base64");
1643
1644                 gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, name);
1645
1646                 g_free (pixdata);
1647                 g_free (stream);
1648                 g_free (base64);
1649         }
1650
1651
1652         gl_debug (DEBUG_XML, "END");
1653 }
1654
1655 /*--------------------------------------------------------------------------*/
1656 /* PRIVATE.  Create top-level Span node.                                    */
1657 /*--------------------------------------------------------------------------*/
1658 static void
1659 xml_create_toplevel_span (xmlNodePtr        root,
1660                           xmlNsPtr          ns,
1661                           glLabelText      *object_text)
1662 {
1663         xmlNodePtr        node;
1664         gchar            *font_family;
1665         gdouble           font_size;
1666         GnomeFontWeight   font_weight;
1667         gboolean          font_italic_flag;
1668         glColorNode      *color_node;
1669         GtkJustification  just;
1670         gdouble           text_line_spacing;
1671         GList            *lines, *p_line, *p_node;
1672         glTextNode       *text_node;
1673         xmlNodePtr        child;
1674
1675         node = xmlNewChild (root, ns, (xmlChar *)"Span", NULL);
1676
1677         /* All span attrs at top level. */
1678         font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object_text));
1679         font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object_text));
1680         text_line_spacing = gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object_text));
1681         font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object_text));
1682         font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object_text));
1683         
1684         color_node = gl_label_object_get_text_color (GL_LABEL_OBJECT(object_text));
1685         if (color_node->field_flag)
1686         {
1687                 xmlSetProp (node, (xmlChar *)"color_field", (xmlChar *)color_node->key);
1688         }
1689         else
1690         {
1691                 gl_xml_set_prop_uint_hex (node, "color", color_node->color);
1692         }
1693         gl_color_node_free (&color_node);
1694         
1695         just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object_text));
1696         xmlSetProp (node, (xmlChar *)"font_family", (xmlChar *)font_family);
1697         gl_xml_set_prop_double (node, "font_size", font_size);
1698         xmlSetProp (node, (xmlChar *)"font_weight", (xmlChar *)gl_util_weight_to_string (font_weight));
1699         gl_xml_set_prop_boolean (node, "font_italic", font_italic_flag);
1700         
1701         gl_xml_set_prop_double (node, "line_spacing", text_line_spacing);
1702
1703         /* Build children. */
1704         lines = gl_label_text_get_lines (GL_LABEL_TEXT(object_text));
1705         for (p_line = lines; p_line != NULL; p_line = p_line->next) {
1706
1707                 for (p_node = (GList *) p_line->data; p_node != NULL;
1708                      p_node = p_node->next) {
1709                         text_node = (glTextNode *) p_node->data;
1710
1711                         if (text_node->field_flag) {
1712                                 child = xmlNewChild (node, ns, (xmlChar *)"Field", NULL);
1713                                 xmlSetProp (child, (xmlChar *)"name", (xmlChar *)text_node->data);
1714                         } else {
1715                                 xmlNodeAddContent (node, (xmlChar *)text_node->data);
1716                         }
1717
1718                 }
1719
1720                 if ( p_line->next ) {
1721                         child = xmlNewChild (node, ns, (xmlChar *)"NL", NULL);
1722                 }
1723
1724         }
1725
1726         gl_text_node_lines_free (&lines);
1727         g_free (font_family);
1728
1729 }