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