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