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