]> git.sur5r.net Git - glabels/blob - glabels2/src/xml-label.c
2003-12-30 Wayne Schuller <k_wayne@linuxpower.org>
[glabels] / glabels2 / src / xml-label.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  label.c:  GLabels xml label module
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22
23 #include <config.h>
24
25 #include <gnome.h>
26
27 #include <libxml/tree.h>
28 #include <libxml/parser.h>
29 #include <gdk-pixbuf/gdk-pixdata.h>
30
31 #include "label.h"
32 #include "label-object.h"
33 #include "label-text.h"
34 #include "label-box.h"
35 #include "label-line.h"
36 #include "label-ellipse.h"
37 #include "label-image.h"
38 #include "label-barcode.h"
39 #include "template.h"
40 #include "base64.h"
41 #include "xml-label.h"
42 #include "xml-label-04.h"
43 #include "xml-label-191.h"
44 #include "xml-template.h"
45 #include "xml.h"
46 #include "util.h"
47
48 #include "debug.h"
49
50 /*========================================================*/
51 /* Private macros and constants.                          */
52 /*========================================================*/
53 #define 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, 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 (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         glBarcodeStyle      style;
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         string = xmlGetProp (node, "style");
701         style = gl_barcode_text_to_style (string);
702         g_free (string);
703         text_flag = gl_xml_get_prop_boolean (node, "text", FALSE);
704         checksum_flag = gl_xml_get_prop_boolean (node, "checksum", TRUE);
705         color = gl_xml_get_prop_uint (node, "color", 0);
706         gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
707                                     style, text_flag, checksum_flag);
708         gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color);
709
710         /* data or field attr */
711         string = xmlGetProp (node, "data");
712         if ( string ) {
713                 text_node = g_new0 (glTextNode, 1);
714                 text_node->field_flag = FALSE;
715                 text_node->data = string;
716                 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
717                 gl_text_node_free (&text_node);
718         } else {
719                 string = xmlGetProp (node, "field");
720                 if ( string ) {
721                         text_node = g_new0 (glTextNode, 1);
722                         text_node->field_flag = TRUE;
723                         text_node->data = string;
724                         gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
725                         gl_text_node_free (&text_node);
726                 } else {
727                         g_warning ("Missing Object-barcode data or field attr");
728                 }
729         }
730
731         /* affine attrs */
732         affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
733         affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
734         affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
735         affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
736         affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
737         affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
738         gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
739
740         gl_debug (DEBUG_XML, "END");
741 }
742
743 /*--------------------------------------------------------------------------*/
744 /* PRIVATE.  Parse XML merge fields tag.                                    */
745 /*--------------------------------------------------------------------------*/
746 static void
747 xml_parse_merge_fields (xmlNodePtr  node,
748                         glLabel    *label)
749 {
750         xmlNodePtr  child;
751         gchar      *string;
752         glMerge    *merge;
753
754         gl_debug (DEBUG_XML, "START");
755
756         string = xmlGetProp (node, "type");
757         merge = gl_merge_new (string);
758         g_free (string);
759
760         string = xmlGetProp (node, "src");
761         gl_merge_set_src (merge, string);
762         g_free (string);
763
764         gl_label_set_merge (label, merge);
765
766         g_object_unref (G_OBJECT(merge));
767
768         gl_debug (DEBUG_XML, "END");
769 }
770
771 /*--------------------------------------------------------------------------*/
772 /* PRIVATE.  Parse XML data tag.                                            */
773 /*--------------------------------------------------------------------------*/
774 static void
775 xml_parse_data (xmlNodePtr  node,
776                 glLabel    *label)
777 {
778         xmlNodePtr  child;
779
780         gl_debug (DEBUG_XML, "START");
781
782         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
783
784                 if (xmlStrEqual (child->name, "Pixdata")) {
785                         xml_parse_pixdata (child, label);
786                 } else {
787                         if (!xmlNodeIsText (child)) {
788                                 g_warning (_("bad node in Data node =  \"%s\""),
789                                            child->name);
790                         }
791                 }
792         }
793
794         gl_debug (DEBUG_XML, "END");
795 }
796
797 /*--------------------------------------------------------------------------*/
798 /* PRIVATE.  Parse XML pixbuf data tag.                                     */
799 /*--------------------------------------------------------------------------*/
800 static void
801 xml_parse_pixdata (xmlNodePtr  node,
802                    glLabel    *label)
803 {
804         gchar      *name, *base64;
805         guchar     *stream;
806         guint       stream_length;
807         gboolean    ret;
808         GdkPixdata *pixdata;
809         GdkPixbuf  *pixbuf;
810         GHashTable *pixbuf_cache;
811
812         gl_debug (DEBUG_XML, "START");
813
814         name = xmlGetProp (node, "name");
815         base64 = xmlNodeGetContent (node);
816
817         stream = gl_base64_decode (base64, &stream_length);
818         pixdata = g_new0 (GdkPixdata, 1);
819         ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
820
821         if (ret) {
822                 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
823
824                 pixbuf_cache = gl_label_get_pixbuf_cache (label);
825                 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
826         }
827
828         g_free (name);
829         g_free (base64);
830         g_free (stream);
831         g_free (pixdata);
832
833         gl_debug (DEBUG_XML, "END");
834 }
835
836 /*--------------------------------------------------------------------------*/
837 /* PRIVATE.  Parse top-level Span tag.                                      */
838 /*--------------------------------------------------------------------------*/
839 static void
840 xml_parse_toplevel_span  (xmlNodePtr        node,
841                           glLabelObject    *object)
842 {
843         gchar            *font_family;
844         gdouble           font_size;
845         GnomeFontWeight   font_weight;
846         gboolean          font_italic_flag;
847         guint             color;
848         gdouble           text_line_spacing;
849         gchar            *string;
850         GList            *lines, *text_nodes;
851         xmlNodePtr        child;
852         glTextNode       *text_node;
853
854         gl_debug (DEBUG_XML, "START");
855
856         /* Font family attr */
857         font_family = xmlGetProp (node, "font_family");
858         gl_label_object_set_font_family (object, font_family);
859         g_free (font_family);
860
861         /* Font size attr */
862         font_size = gl_xml_get_prop_double (node, "font_size", 0.0);
863         gl_label_object_set_font_size (object, font_size);
864
865         /* Font weight attr */
866         string = xmlGetProp (node, "font_weight");
867         font_weight = gl_util_string_to_weight (string);
868         g_free (string);
869         gl_label_object_set_font_weight (object, font_weight);
870
871         /* Font italic flag attr */
872         font_italic_flag = gl_xml_get_prop_boolean (node, "font_italic", FALSE);
873         gl_label_object_set_font_italic_flag (object, font_italic_flag);
874
875         /* Text color attr */
876         color = gl_xml_get_prop_uint (node, "color", 0);
877         gl_label_object_set_text_color (object, color);
878
879         /* Text line spacing attr  */
880         text_line_spacing = gl_xml_get_prop_double (node, "line_spacing", 1.0);
881         gl_label_object_set_text_line_spacing (object, text_line_spacing); 
882
883         /* Now descend children, and build lines of text nodes */
884         lines = NULL;
885         text_nodes = NULL;
886         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
887
888                 if (xmlNodeIsText (child)) {
889                         gchar *data = xmlNodeGetContent (child); 
890
891                         /* Hack: if the first char is LF, it's a xml formatting string */
892                         if (data[0] != '\n') { 
893                                 /* Literal text */
894                                 text_node = g_new0 (glTextNode, 1);
895                                 text_node->field_flag = FALSE;
896                                 text_node->data = data;
897                                 text_nodes = g_list_append (text_nodes, text_node);
898                         }
899                         else 
900                                 g_free (data);
901
902                 } else if (xmlStrEqual (child->name, "Span")) {
903
904                         g_warning ("Unexpected rich text (not supported, yet!)");
905
906                 } else if (xmlStrEqual (child->name, "Field")) {
907
908                         /* Field node */
909                         text_node = g_new0 (glTextNode, 1);
910                         text_node->field_flag = TRUE;
911                         text_node->data = xmlGetProp (child, "name");
912                         text_nodes = g_list_append (text_nodes, text_node);
913
914                 } else if (xmlStrEqual (child->name, "NL")) {
915
916                         /* Store line. */
917                         lines = g_list_append (lines, text_nodes);
918                         text_nodes = NULL;
919
920                 } else {
921                         g_warning ("Unexpected Span child: \"%s\"", child->name);
922                 }
923
924         }
925         if ( text_nodes ) {
926                 /* Store last line. */
927                 lines = g_list_append (lines, text_nodes);
928                 text_nodes = NULL;
929         }
930         gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
931         gl_text_node_lines_free (&lines);
932
933         gl_debug (DEBUG_XML, "END");
934 }
935
936 /****************************************************************************/
937 /* Save label to xml label file.                                            */
938 /****************************************************************************/
939 void
940 gl_xml_label_save (glLabel          *label,
941                    const gchar      *utf8_filename,
942                    glXMLLabelStatus *status)
943 {
944         xmlDocPtr doc;
945         gint      xml_ret;
946         gchar     *filename;
947
948         gl_debug (DEBUG_XML, "START");
949
950         doc = xml_label_to_doc (label, status);
951
952         filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
953         if (!filename)
954                 g_warning (_("Utf8 conversion error."));
955         else {
956                 xmlSetDocCompressMode (doc, 9);
957                 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
958                 xmlFreeDoc (doc);
959                 if (xml_ret == -1) {
960
961                         g_warning (_("Problem saving xml file."));
962                         *status = XML_LABEL_ERROR_SAVE_FILE;
963
964                 } else {
965
966                         gl_label_set_filename (label, utf8_filename);
967                         gl_label_clear_modified (label);
968
969                 }
970                 g_free (filename);
971         }
972
973         gl_debug (DEBUG_XML, "END");
974 }
975
976 /****************************************************************************/
977 /* Save label to xml buffer.                                                */
978 /****************************************************************************/
979 gchar *
980 gl_xml_label_save_buffer (glLabel          *label,
981                           glXMLLabelStatus *status)
982 {
983         xmlDocPtr  doc;
984         gint       size;
985         gchar     *buffer;
986
987         gl_debug (DEBUG_XML, "START");
988
989         doc = xml_label_to_doc (label, status);
990
991         xmlDocDumpMemory (doc, (xmlChar **)&buffer, &size);
992         xmlFreeDoc (doc);
993
994         gl_label_clear_modified (label);
995
996         gl_debug (DEBUG_XML, "END");
997
998         return buffer;
999 }
1000
1001 /*--------------------------------------------------------------------------*/
1002 /* PRIVATE.  Convert label to xml doc structure.                            */
1003 /*--------------------------------------------------------------------------*/
1004 static xmlDocPtr
1005 xml_label_to_doc (glLabel          *label,
1006                   glXMLLabelStatus *status)
1007 {
1008         xmlDocPtr   doc;
1009         xmlNsPtr    ns;
1010         glTemplate *template;
1011         glMerge    *merge;
1012
1013         gl_debug (DEBUG_XML, "START");
1014
1015         LIBXML_TEST_VERSION;
1016
1017         doc = xmlNewDoc ("1.0");
1018         doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Glabels-document", NULL);
1019
1020         ns = xmlNewNs (doc->xmlRootNode, XML_NAME_SPACE, NULL);
1021         xmlSetNs (doc->xmlRootNode, ns);
1022
1023         template = gl_label_get_template (label);
1024         gl_xml_template_add_template (template, doc->xmlRootNode, ns);
1025
1026         xml_create_objects (doc->xmlRootNode, ns, label);
1027
1028         merge = gl_label_get_merge (label);
1029         gl_debug (DEBUG_XML, "merge=%p", merge);
1030         if (merge != NULL) {
1031                 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1032                 g_object_unref (G_OBJECT(merge));
1033         }
1034
1035         xml_create_data (doc->xmlRootNode, ns, label);
1036
1037         gl_debug (DEBUG_XML, "END");
1038
1039         *status = XML_LABEL_OK;
1040         return doc;
1041 }
1042
1043 /*--------------------------------------------------------------------------*/
1044 /* PRIVATE.  Add XML Objects Node                                           */
1045 /*--------------------------------------------------------------------------*/
1046 static void
1047 xml_create_objects (xmlNodePtr  root,
1048                     xmlNsPtr    ns,
1049                     glLabel    *label)
1050 {
1051         xmlNodePtr     node;
1052         gboolean       rotate_flag;
1053         GList         *p;
1054         glLabelObject *object;
1055
1056         gl_debug (DEBUG_XML, "START");
1057
1058         rotate_flag = gl_label_get_rotate_flag (label);
1059
1060         node = xmlNewChild (root, ns, "Objects", NULL);
1061         xmlSetProp (node, "id", "0");
1062         gl_xml_set_prop_boolean (node, "rotate", rotate_flag);
1063
1064         for (p = label->objects; p != NULL; p = p->next) {
1065
1066                 object = GL_LABEL_OBJECT(p->data);
1067
1068                 if ( GL_IS_LABEL_TEXT(object) ) {
1069                         xml_create_object_text (node, ns, object);
1070                 } else if ( GL_IS_LABEL_BOX(object) ) {
1071                         xml_create_object_box (node, ns, object);
1072                 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1073                         xml_create_object_ellipse (node, ns, object);
1074                 } else if ( GL_IS_LABEL_LINE(object) ) {
1075                         xml_create_object_line (node, ns, object);
1076                 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1077                         xml_create_object_image (node, ns, object);
1078                 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1079                         xml_create_object_barcode (node, ns, object);
1080                 } else {
1081                         g_warning ("Unknown label object");
1082                 }
1083
1084         }
1085
1086         gl_debug (DEBUG_XML, "END");
1087 }
1088
1089 /*--------------------------------------------------------------------------*/
1090 /* PRIVATE.  Add XML Objects->Object-text Node                              */
1091 /*--------------------------------------------------------------------------*/
1092 static void
1093 xml_create_object_text (xmlNodePtr     root,
1094                         xmlNsPtr       ns,
1095                         glLabelObject *object)
1096 {
1097         xmlNodePtr        node;
1098         gdouble           x, y;
1099         gdouble           w, h;
1100         GtkJustification  just;
1101         gdouble           affine[6];
1102
1103         gl_debug (DEBUG_XML, "START");
1104
1105         node = xmlNewChild (root, ns, "Object-text", NULL);
1106
1107         /* position attrs */
1108         gl_label_object_get_position (object, &x, &y);
1109         gl_xml_set_prop_length (node, "x", x);
1110         gl_xml_set_prop_length (node, "y", y);
1111
1112         /* size attrs */
1113         gl_label_text_get_box ( GL_LABEL_TEXT(object), &w, &h);
1114         gl_xml_set_prop_length (node, "w", w);
1115         gl_xml_set_prop_length (node, "h", h);
1116
1117         /* justify attr */
1118         just = gl_label_object_get_text_alignment (object);
1119         xmlSetProp (node, "justify", gl_util_just_to_string (just));
1120
1121         /* affine attrs */
1122         gl_label_object_get_affine (object, affine);
1123         gl_xml_set_prop_double (node, "a0", affine[0]);
1124         gl_xml_set_prop_double (node, "a1", affine[1]);
1125         gl_xml_set_prop_double (node, "a2", affine[2]);
1126         gl_xml_set_prop_double (node, "a3", affine[3]);
1127         gl_xml_set_prop_double (node, "a4", affine[4]);
1128         gl_xml_set_prop_double (node, "a5", affine[5]);
1129
1130         /* Add children */
1131         xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1132
1133         gl_debug (DEBUG_XML, "END");
1134 }
1135
1136 /*--------------------------------------------------------------------------*/
1137 /* PRIVATE.  Add XML Objects->Object-box Node                               */
1138 /*--------------------------------------------------------------------------*/
1139 static void
1140 xml_create_object_box (xmlNodePtr     root,
1141                        xmlNsPtr       ns,
1142                        glLabelObject *object)
1143 {
1144         xmlNodePtr        node;
1145         gdouble           x, y;
1146         gdouble           w, h;
1147         gdouble           line_width;
1148         guint             line_color, fill_color;
1149         gdouble           affine[6];
1150
1151         gl_debug (DEBUG_XML, "START");
1152
1153         node = xmlNewChild (root, ns, "Object-box", NULL);
1154
1155         /* position attrs */
1156         gl_label_object_get_position (object, &x, &y);
1157         gl_xml_set_prop_length (node, "x", x);
1158         gl_xml_set_prop_length (node, "y", y);
1159
1160         /* size attrs */
1161         gl_label_object_get_size (object, &w, &h);
1162         gl_xml_set_prop_length (node, "w", w);
1163         gl_xml_set_prop_length (node, "h", h);
1164
1165         /* line attrs */
1166         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1167         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1168         gl_xml_set_prop_length (node, "line_width", line_width);
1169         gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1170
1171         /* fill attrs */
1172         fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1173         gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1174
1175         /* affine attrs */
1176         gl_label_object_get_affine (object, affine);
1177         gl_xml_set_prop_double (node, "a0", affine[0]);
1178         gl_xml_set_prop_double (node, "a1", affine[1]);
1179         gl_xml_set_prop_double (node, "a2", affine[2]);
1180         gl_xml_set_prop_double (node, "a3", affine[3]);
1181         gl_xml_set_prop_double (node, "a4", affine[4]);
1182         gl_xml_set_prop_double (node, "a5", affine[5]);
1183
1184         gl_debug (DEBUG_XML, "END");
1185 }
1186
1187 /*--------------------------------------------------------------------------*/
1188 /* PRIVATE.  Add XML Objects->Object-ellipse Node                           */
1189 /*--------------------------------------------------------------------------*/
1190 static void
1191 xml_create_object_ellipse (xmlNodePtr     root,
1192                            xmlNsPtr       ns,
1193                            glLabelObject *object)
1194 {
1195         xmlNodePtr        node;
1196         gdouble           x, y;
1197         gdouble           w, h;
1198         gdouble           line_width;
1199         guint             line_color, fill_color;
1200         gdouble           affine[6];
1201
1202         gl_debug (DEBUG_XML, "START");
1203
1204         node = xmlNewChild (root, ns, "Object-ellipse", NULL);
1205
1206         /* position attrs */
1207         gl_label_object_get_position (object, &x, &y);
1208         gl_xml_set_prop_length (node, "x", x);
1209         gl_xml_set_prop_length (node, "y", y);
1210
1211         /* size attrs */
1212         gl_label_object_get_size (object, &w, &h);
1213         gl_xml_set_prop_length (node, "w", w);
1214         gl_xml_set_prop_length (node, "h", h);
1215
1216         /* line attrs */
1217         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1218         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1219         gl_xml_set_prop_length (node, "line_width", line_width);
1220         gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1221
1222         /* fill attrs */
1223         fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1224         gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1225
1226         /* affine attrs */
1227         gl_label_object_get_affine (object, affine);
1228         gl_xml_set_prop_double (node, "a0", affine[0]);
1229         gl_xml_set_prop_double (node, "a1", affine[1]);
1230         gl_xml_set_prop_double (node, "a2", affine[2]);
1231         gl_xml_set_prop_double (node, "a3", affine[3]);
1232         gl_xml_set_prop_double (node, "a4", affine[4]);
1233         gl_xml_set_prop_double (node, "a5", affine[5]);
1234
1235         gl_debug (DEBUG_XML, "END");
1236 }
1237
1238 /*--------------------------------------------------------------------------*/
1239 /* PRIVATE.  Add XML Objects->Object-line Node                              */
1240 /*--------------------------------------------------------------------------*/
1241 static void
1242 xml_create_object_line (xmlNodePtr     root,
1243                         xmlNsPtr       ns,
1244                         glLabelObject *object)
1245 {
1246         xmlNodePtr        node;
1247         gdouble           x, y;
1248         gdouble           dx, dy;
1249         gdouble           line_width;
1250         guint             line_color;
1251         gdouble           affine[6];
1252
1253         gl_debug (DEBUG_XML, "START");
1254
1255         node = xmlNewChild (root, ns, "Object-line", NULL);
1256
1257         /* position attrs */
1258         gl_label_object_get_position (object, &x, &y);
1259         gl_xml_set_prop_length (node, "x", x);
1260         gl_xml_set_prop_length (node, "y", y);
1261
1262         /* length attrs */
1263         gl_label_object_get_size (object, &dx, &dy);
1264         gl_xml_set_prop_length (node, "dx", dx);
1265         gl_xml_set_prop_length (node, "dy", dy);
1266
1267         /* line attrs */
1268         line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1269         line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1270         gl_xml_set_prop_length (node, "line_width", line_width);
1271         gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1272
1273         /* affine attrs */
1274         gl_label_object_get_affine (object, affine);
1275         gl_xml_set_prop_double (node, "a0", affine[0]);
1276         gl_xml_set_prop_double (node, "a1", affine[1]);
1277         gl_xml_set_prop_double (node, "a2", affine[2]);
1278         gl_xml_set_prop_double (node, "a3", affine[3]);
1279         gl_xml_set_prop_double (node, "a4", affine[4]);
1280         gl_xml_set_prop_double (node, "a5", affine[5]);
1281
1282         gl_debug (DEBUG_XML, "END");
1283 }
1284
1285 /*--------------------------------------------------------------------------*/
1286 /* PRIVATE.  Add XML Objects->Object-image Node                             */
1287 /*--------------------------------------------------------------------------*/
1288 static void
1289 xml_create_object_image (xmlNodePtr     root,
1290                          xmlNsPtr       ns,
1291                          glLabelObject *object)
1292 {
1293         xmlNodePtr        node;
1294         gdouble           x, y;
1295         gdouble           w, h;
1296         glTextNode       *filename;
1297         gdouble           affine[6];
1298
1299         gl_debug (DEBUG_XML, "START");
1300
1301         node = xmlNewChild (root, ns, "Object-image", NULL);
1302
1303         /* position attrs */
1304         gl_label_object_get_position (object, &x, &y);
1305         gl_xml_set_prop_length (node, "x", x);
1306         gl_xml_set_prop_length (node, "y", y);
1307
1308         /* size attrs */
1309         gl_label_object_get_size (object, &w, &h);
1310         gl_xml_set_prop_length (node, "w", w);
1311         gl_xml_set_prop_length (node, "h", h);
1312
1313         /* src OR field attr */
1314         filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1315         if (filename->field_flag) {
1316                 xmlSetProp (node, "field", filename->data);
1317         } else {
1318                 xmlSetProp (node, "src", filename->data);
1319         }
1320         gl_text_node_free (&filename);
1321
1322         /* affine attrs */
1323         gl_label_object_get_affine (object, affine);
1324         gl_xml_set_prop_double (node, "a0", affine[0]);
1325         gl_xml_set_prop_double (node, "a1", affine[1]);
1326         gl_xml_set_prop_double (node, "a2", affine[2]);
1327         gl_xml_set_prop_double (node, "a3", affine[3]);
1328         gl_xml_set_prop_double (node, "a4", affine[4]);
1329         gl_xml_set_prop_double (node, "a5", affine[5]);
1330
1331         gl_debug (DEBUG_XML, "END");
1332 }
1333
1334 /*--------------------------------------------------------------------------*/
1335 /* PRIVATE.  Add XML Objects->Object-barcode Node                           */
1336 /*--------------------------------------------------------------------------*/
1337 static void
1338 xml_create_object_barcode (xmlNodePtr     root,
1339                            xmlNsPtr       ns,
1340                            glLabelObject *object)
1341 {
1342         xmlNodePtr        node;
1343         gdouble           x, y;
1344         gdouble           w, h;
1345         glTextNode       *text_node;
1346         glBarcodeStyle    style;
1347         gboolean          text_flag;
1348         gboolean          checksum_flag;
1349         guint             color;
1350         gdouble           affine[6];
1351
1352         gl_debug (DEBUG_XML, "START");
1353
1354         node = xmlNewChild (root, ns, "Object-barcode", NULL);
1355
1356         /* position attrs */
1357         gl_label_object_get_position (object, &x, &y);
1358         gl_xml_set_prop_length (node, "x", x);
1359         gl_xml_set_prop_length (node, "y", y);
1360
1361         /* size attrs */
1362         gl_label_object_get_size (object, &w, &h);
1363         gl_xml_set_prop_length (node, "w", w);
1364         gl_xml_set_prop_length (node, "h", h);
1365
1366         /* Barcode properties attrs */
1367         gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1368                                     &style, &text_flag, &checksum_flag);
1369         color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1370         xmlSetProp (node, "style", gl_barcode_style_to_text (style));
1371         gl_xml_set_prop_boolean (node, "text", text_flag);
1372         gl_xml_set_prop_boolean (node, "checksum", checksum_flag);
1373         gl_xml_set_prop_uint_hex (node, "color", color);
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 }