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