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