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