2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * label.c: GLabels xml label module
6 * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
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.
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.
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
27 #include <libxml/tree.h>
28 #include <libxml/parser.h>
29 #include <gdk-pixbuf/gdk-pixdata.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"
41 #include "xml-label.h"
42 #include "xml-label-04.h"
43 #include "xml-label-191.h"
44 #include "xml-template.h"
50 /*========================================================*/
51 /* Private macros and constants. */
52 /*========================================================*/
53 #define NAME_SPACE "http://snaught.com/glabels/2.0/"
54 #define COMPAT01_NAME_SPACE "http://snaught.com/glabels/0.1/"
55 #define COMPAT04_NAME_SPACE "http://snaught.com/glabels/0.4/"
56 #define COMPAT191_NAME_SPACE "http://snaught.com/glabels/1.92/"
58 /*========================================================*/
60 /*========================================================*/
62 /*========================================================*/
63 /* Private globals. */
64 /*========================================================*/
66 /*========================================================*/
67 /* Private function prototypes. */
68 /*========================================================*/
70 static glLabel *xml_doc_to_label (xmlDocPtr doc,
71 glXMLLabelStatus *status);
73 static glLabel *xml_parse_label (xmlNodePtr root,
74 glXMLLabelStatus *status);
76 static void xml_parse_objects (xmlNodePtr node,
79 static void xml_parse_object_text (xmlNodePtr node,
82 static void xml_parse_object_box (xmlNodePtr node,
85 static void xml_parse_object_ellipse (xmlNodePtr node,
88 static void xml_parse_object_line (xmlNodePtr node,
91 static void xml_parse_object_image (xmlNodePtr node,
94 static void xml_parse_object_barcode (xmlNodePtr node,
97 static void xml_parse_merge_fields (xmlNodePtr node,
100 static void xml_parse_data (xmlNodePtr node,
103 static void xml_parse_pixdata (xmlNodePtr node,
106 static void xml_parse_toplevel_span (xmlNodePtr node,
107 glLabelObject *object);
110 static xmlDocPtr xml_label_to_doc (glLabel *label,
111 glXMLLabelStatus *status);
113 static void xml_create_objects (xmlNodePtr root,
117 static void xml_create_object_text (xmlNodePtr root,
119 glLabelObject *object);
121 static void xml_create_object_box (xmlNodePtr root,
123 glLabelObject *object);
125 static void xml_create_object_line (xmlNodePtr root,
127 glLabelObject *object);
129 static void xml_create_object_ellipse(xmlNodePtr root,
131 glLabelObject *object);
133 static void xml_create_object_image (xmlNodePtr root,
135 glLabelObject *object);
137 static void xml_create_object_barcode(xmlNodePtr root,
139 glLabelObject *object);
141 static void xml_create_merge_fields (xmlNodePtr root,
145 static void xml_create_data (xmlNodePtr root,
149 static void xml_create_pixdata (xmlNodePtr root,
154 static void xml_create_toplevel_span (xmlNodePtr node,
156 glLabelText *object_text);
159 /****************************************************************************/
160 /* Open and read label from xml file. */
161 /****************************************************************************/
163 gl_xml_label_open (const gchar *utf8_filename,
164 glXMLLabelStatus *status)
170 gl_debug (DEBUG_XML, "START");
172 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
173 g_return_val_if_fail (filename, NULL);
175 doc = xmlParseFile (filename);
177 g_warning (_("xmlParseFile error"));
178 *status = XML_LABEL_ERROR_OPEN_PARSE;
182 xmlXIncludeProcess (doc);
183 xmlReconciliateNs (doc, xmlDocGetRootElement (doc));
185 label = xml_doc_to_label (doc, status);
190 gl_label_set_filename (label, utf8_filename);
191 gl_label_clear_modified (label);
195 gl_debug (DEBUG_XML, "END");
200 /****************************************************************************/
201 /* Read label from xml buffer. */
202 /****************************************************************************/
204 gl_xml_label_open_buffer (const gchar *buffer,
205 glXMLLabelStatus *status)
210 gl_debug (DEBUG_XML, "START");
212 doc = xmlParseDoc ((xmlChar *) buffer);
214 g_warning (_("xmlParseFile error"));
215 *status = XML_LABEL_ERROR_OPEN_PARSE;
219 label = xml_doc_to_label (doc, status);
224 gl_label_clear_modified (label);
227 gl_debug (DEBUG_XML, "END");
232 /*--------------------------------------------------------------------------*/
233 /* PRIVATE. Parse xml doc structure and create label. */
234 /*--------------------------------------------------------------------------*/
236 xml_doc_to_label (xmlDocPtr doc,
237 glXMLLabelStatus *status)
239 xmlNodePtr root, node;
243 gl_debug (DEBUG_XML, "START");
247 *status = XML_LABEL_OK;
249 root = xmlDocGetRootElement (doc);
250 if (!root || !root->name) {
251 g_warning (_("No document root"));
252 *status = XML_LABEL_ERROR_OPEN_PARSE;
256 ns = xmlSearchNsByHref (doc, root, NAME_SPACE);
258 label = xml_parse_label (root, status);
260 /* Try compatability mode 0.1 */
261 ns = xmlSearchNsByHref (doc, root, COMPAT01_NAME_SPACE);
263 g_warning (_("Importing from glabels 0.1 format"));
265 label = NULL; /* TODO */
267 /* Try compatability mode 0.4 */
268 ns = xmlSearchNsByHref (doc, root,
269 COMPAT04_NAME_SPACE);
271 g_warning (_("Importing from glabels 0.4 format"));
272 label = gl_xml_label_04_parse (root, status);
274 /* Try compatability mode 1.91 */
275 ns = xmlSearchNsByHref (doc, root,
276 COMPAT191_NAME_SPACE);
278 g_warning (_("Importing from glabels 1.91 format"));
279 label = gl_xml_label_191_parse (root, status);
281 g_warning (_("bad document, unknown glabels Namespace"));
282 *status = XML_LABEL_ERROR_OPEN_PARSE;
289 gl_debug (DEBUG_XML, "END");
294 /*--------------------------------------------------------------------------*/
295 /* PRIVATE. Parse xml root node and create label. */
296 /*--------------------------------------------------------------------------*/
298 xml_parse_label (xmlNodePtr root,
299 glXMLLabelStatus *status)
301 xmlNodePtr child_node;
303 glTemplate *template;
305 gl_debug (DEBUG_XML, "START");
307 *status = XML_LABEL_OK;
309 if (!xmlStrEqual (root->name, "Glabels-document")) {
310 g_warning (_("Bad root node = \"%s\""), root->name);
311 *status = XML_LABEL_ERROR_OPEN_PARSE;
315 label = GL_LABEL(gl_label_new ());
317 /* Pass 1, extract data nodes to pre-load cache. */
318 for (child_node = root->xmlChildrenNode; child_node != NULL; child_node = child_node->next) {
319 if (xmlStrEqual (child_node->name, "Data")) {
320 xml_parse_data (child_node, label);
324 /* Pass 2, now extract everything else. */
325 for (child_node = root->xmlChildrenNode;
327 child_node = child_node->next) {
329 if (xmlStrEqual (child_node->name, "Template")) {
330 template = gl_xml_template_parse_template (child_node);
332 *status = XML_LABEL_UNKNOWN_MEDIA;
335 gl_label_set_template (label, template);
336 gl_template_free (&template);
337 } else if (xmlStrEqual (child_node->name, "Objects")) {
338 xml_parse_objects (child_node, label);
339 } else if (xmlStrEqual (child_node->name, "Merge")) {
340 xml_parse_merge_fields (child_node, label);
341 } else if (xmlStrEqual (child_node->name, "Data")) {
342 /* Handled in pass 1. */
344 if (!xmlNodeIsText (child_node)) {
345 g_warning (_("bad node in Document node = \"%s\""),
351 gl_debug (DEBUG_XML, "END");
356 /*--------------------------------------------------------------------------*/
357 /* PRIVATE. Parse Objects node. */
358 /*--------------------------------------------------------------------------*/
360 xml_parse_objects (xmlNodePtr node,
363 gboolean rotate_flag;
366 gl_debug (DEBUG_XML, "START");
368 rotate_flag = gl_xml_get_prop_boolean (node, "rotate", FALSE);
369 gl_label_set_rotate_flag (label, rotate_flag);
371 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
373 if (xmlStrEqual (child->name, "Object-text")) {
374 xml_parse_object_text (child, label);
375 } else if (xmlStrEqual (child->name, "Object-box")) {
376 xml_parse_object_box (child, label);
377 } else if (xmlStrEqual (child->name, "Object-ellipse")) {
378 xml_parse_object_ellipse (child, label);
379 } else if (xmlStrEqual (child->name, "Object-line")) {
380 xml_parse_object_line (child, label);
381 } else if (xmlStrEqual (child->name, "Object-image")) {
382 xml_parse_object_image (child, label);
383 } else if (xmlStrEqual (child->name, "Object-barcode")) {
384 xml_parse_object_barcode (child, label);
386 if (!xmlNodeIsText (child)) {
387 g_warning (_("bad node = \"%s\""), child->name);
393 gl_debug (DEBUG_XML, "END");
396 /*--------------------------------------------------------------------------*/
397 /* PRIVATE. Parse XML Objects->Object-text Node */
398 /*--------------------------------------------------------------------------*/
400 xml_parse_object_text (xmlNodePtr node,
407 GtkJustification just;
411 gl_debug (DEBUG_XML, "START");
413 object = gl_label_text_new (label);
416 x = gl_xml_get_prop_length (node, "x", 0.0);
417 y = gl_xml_get_prop_length (node, "y", 0.0);
418 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
420 /* implied size attrs */
421 w = gl_xml_get_prop_length (node, "w", 0);
422 h = gl_xml_get_prop_length (node, "h", 0);
423 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
426 string = xmlGetProp (node, "justify");
427 just = gl_util_string_to_just (string);
429 gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), just);
432 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
433 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
434 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
435 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
436 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
437 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
438 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
440 /* Process children */
441 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
442 if (xmlStrEqual (child->name, "Span")) {
443 xml_parse_toplevel_span (child, GL_LABEL_OBJECT(object));
446 if (!xmlNodeIsText (child)) {
447 g_warning ("Unexpected Object-text child: \"%s\"",
453 gl_debug (DEBUG_XML, "END");
456 /*--------------------------------------------------------------------------*/
457 /* PRIVATE. Parse XML Objects->Object-box Node */
458 /*--------------------------------------------------------------------------*/
460 xml_parse_object_box (xmlNodePtr node,
467 guint line_color, fill_color;
470 gl_debug (DEBUG_XML, "START");
472 object = gl_label_box_new (label);
475 x = gl_xml_get_prop_length (node, "x", 0.0);
476 y = gl_xml_get_prop_length (node, "y", 0.0);
477 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
480 w = gl_xml_get_prop_length (node, "w", 0);
481 h = gl_xml_get_prop_length (node, "h", 0);
482 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
485 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
486 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
487 gl_label_box_set_line_width (GL_LABEL_BOX(object), line_width);
488 gl_label_box_set_line_color (GL_LABEL_BOX(object), line_color);
491 fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
492 gl_label_box_set_fill_color (GL_LABEL_BOX(object), fill_color);
495 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
496 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
497 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
498 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
499 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
500 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
501 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
503 gl_debug (DEBUG_XML, "END");
506 /*--------------------------------------------------------------------------*/
507 /* PRIVATE. Parse XML Objects->Object-ellipse Node */
508 /*--------------------------------------------------------------------------*/
510 xml_parse_object_ellipse (xmlNodePtr node,
517 guint line_color, fill_color;
520 gl_debug (DEBUG_XML, "START");
522 object = gl_label_ellipse_new (label);
525 x = gl_xml_get_prop_length (node, "x", 0.0);
526 y = gl_xml_get_prop_length (node, "y", 0.0);
527 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
530 w = gl_xml_get_prop_length (node, "w", 0);
531 h = gl_xml_get_prop_length (node, "h", 0);
532 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
535 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
536 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
537 gl_label_ellipse_set_line_width (GL_LABEL_ELLIPSE(object), line_width);
538 gl_label_ellipse_set_line_color (GL_LABEL_ELLIPSE(object), line_color);
541 fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
542 gl_label_ellipse_set_fill_color (GL_LABEL_ELLIPSE(object), fill_color);
545 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
546 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
547 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
548 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
549 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
550 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
551 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
553 gl_debug (DEBUG_XML, "END");
556 /*--------------------------------------------------------------------------*/
557 /* PRIVATE. Parse XML Objects->Object-line Node */
558 /*--------------------------------------------------------------------------*/
560 xml_parse_object_line (xmlNodePtr node,
570 gl_debug (DEBUG_XML, "START");
572 object = gl_label_line_new (label);
575 x = gl_xml_get_prop_length (node, "x", 0.0);
576 y = gl_xml_get_prop_length (node, "y", 0.0);
577 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
580 dx = gl_xml_get_prop_length (node, "dx", 0);
581 dy = gl_xml_get_prop_length (node, "dy", 0);
582 gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy);
585 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
586 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
587 gl_label_line_set_line_width (GL_LABEL_LINE(object), line_width);
588 gl_label_line_set_line_color (GL_LABEL_LINE(object), line_color);
591 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
592 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
593 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
594 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
595 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
596 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
597 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
599 gl_debug (DEBUG_XML, "END");
602 /*--------------------------------------------------------------------------*/
603 /* PRIVATE. Parse XML Objects->Object-image Node */
604 /*--------------------------------------------------------------------------*/
606 xml_parse_object_image (xmlNodePtr node,
613 glTextNode *filename;
616 gl_debug (DEBUG_XML, "START");
618 object = gl_label_image_new (label);
621 x = gl_xml_get_prop_length (node, "x", 0.0);
622 y = gl_xml_get_prop_length (node, "y", 0.0);
623 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
626 w = gl_xml_get_prop_length (node, "w", 0);
627 h = gl_xml_get_prop_length (node, "h", 0);
628 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
630 /* src or field attr */
631 string = xmlGetProp (node, "src");
633 filename = g_new0 (glTextNode, 1);
634 filename->field_flag = FALSE;
635 filename->data = string;
636 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
637 gl_text_node_free (&filename);
639 string = xmlGetProp (node, "field");
641 filename = g_new0 (glTextNode, 1);
642 filename->field_flag = TRUE;
643 filename->data = string;
644 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
645 gl_text_node_free (&filename);
647 g_warning ("Missing Object-image src or field attr");
652 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
653 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
654 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
655 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
656 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
657 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
658 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
660 gl_debug (DEBUG_XML, "END");
663 /*--------------------------------------------------------------------------*/
664 /* PRIVATE. Parse XML Objects->Object-barcode Node */
665 /*--------------------------------------------------------------------------*/
667 xml_parse_object_barcode (xmlNodePtr node,
674 glTextNode *text_node;
675 glBarcodeStyle style;
677 gboolean checksum_flag;
681 gl_debug (DEBUG_XML, "START");
683 object = gl_label_barcode_new (label);
686 x = gl_xml_get_prop_length (node, "x", 0.0);
687 y = gl_xml_get_prop_length (node, "y", 0.0);
688 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
691 w = gl_xml_get_prop_length (node, "w", 0);
692 h = gl_xml_get_prop_length (node, "h", 0);
693 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
696 string = xmlGetProp (node, "style");
697 style = gl_barcode_text_to_style (string);
699 text_flag = gl_xml_get_prop_boolean (node, "text", FALSE);
700 checksum_flag = gl_xml_get_prop_boolean (node, "checksum", TRUE);
701 color = gl_xml_get_prop_uint (node, "color", 0);
702 gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
703 style, text_flag, checksum_flag, color);
705 /* data or field attr */
706 string = xmlGetProp (node, "data");
708 text_node = g_new0 (glTextNode, 1);
709 text_node->field_flag = FALSE;
710 text_node->data = string;
711 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
712 gl_text_node_free (&text_node);
714 string = xmlGetProp (node, "field");
716 text_node = g_new0 (glTextNode, 1);
717 text_node->field_flag = TRUE;
718 text_node->data = string;
719 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
720 gl_text_node_free (&text_node);
722 g_warning ("Missing Object-barcode data or field attr");
727 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
728 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
729 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
730 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
731 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
732 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
733 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
735 gl_debug (DEBUG_XML, "END");
738 /*--------------------------------------------------------------------------*/
739 /* PRIVATE. Parse XML merge fields tag. */
740 /*--------------------------------------------------------------------------*/
742 xml_parse_merge_fields (xmlNodePtr node,
749 gl_debug (DEBUG_XML, "START");
751 string = xmlGetProp (node, "type");
752 merge = gl_merge_new (string);
755 string = xmlGetProp (node, "src");
756 gl_merge_set_src (merge, string);
759 gl_label_set_merge (label, merge);
761 g_object_unref (G_OBJECT(merge));
763 gl_debug (DEBUG_XML, "END");
766 /*--------------------------------------------------------------------------*/
767 /* PRIVATE. Parse XML data tag. */
768 /*--------------------------------------------------------------------------*/
770 xml_parse_data (xmlNodePtr node,
775 gl_debug (DEBUG_XML, "START");
777 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
779 if (xmlStrEqual (child->name, "Pixdata")) {
780 xml_parse_pixdata (child, label);
782 if (!xmlNodeIsText (child)) {
783 g_warning (_("bad node in Data node = \"%s\""),
789 gl_debug (DEBUG_XML, "END");
792 /*--------------------------------------------------------------------------*/
793 /* PRIVATE. Parse XML pixbuf data tag. */
794 /*--------------------------------------------------------------------------*/
796 xml_parse_pixdata (xmlNodePtr node,
799 gchar *name, *base64;
805 GHashTable *pixbuf_cache;
807 gl_debug (DEBUG_XML, "START");
809 name = xmlGetProp (node, "name");
810 base64 = xmlNodeGetContent (node);
812 stream = gl_base64_decode (base64, &stream_length);
813 pixdata = g_new0 (GdkPixdata, 1);
814 ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
817 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
819 pixbuf_cache = gl_label_get_pixbuf_cache (label);
820 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
828 gl_debug (DEBUG_XML, "END");
831 /*--------------------------------------------------------------------------*/
832 /* PRIVATE. Parse top-level Span tag. */
833 /*--------------------------------------------------------------------------*/
835 xml_parse_toplevel_span (xmlNodePtr node,
836 glLabelObject *object)
840 GnomeFontWeight font_weight;
841 gboolean font_italic_flag;
844 GList *lines, *text_nodes;
846 glTextNode *text_node;
848 gl_debug (DEBUG_XML, "START");
850 /* Font family attr */
851 font_family = xmlGetProp (node, "font_family");
852 gl_label_object_set_font_family (object, font_family);
853 g_free (font_family);
856 font_size = gl_xml_get_prop_double (node, "font_size", 0.0);
857 gl_label_object_set_font_size (object, font_size);
859 /* Font weight attr */
860 string = xmlGetProp (node, "font_weight");
861 font_weight = gl_util_string_to_weight (string);
863 gl_label_object_set_font_weight (object, font_weight);
865 /* Font italic flag attr */
866 font_italic_flag = gl_xml_get_prop_boolean (node, "font_italic", FALSE);
867 gl_label_object_set_font_italic_flag (object, font_italic_flag);
869 /* Text color attr */
870 color = gl_xml_get_prop_uint (node, "color", 0);
871 gl_label_object_set_text_color (object, color);
873 /* Now descend children, and build lines of text nodes */
876 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
878 if (xmlNodeIsText (child)) {
881 text_node = g_new0 (glTextNode, 1);
882 text_node->field_flag = FALSE;
883 text_node->data = xmlNodeGetContent (child);
884 text_nodes = g_list_append (text_nodes, text_node);
886 } else if (xmlStrEqual (child->name, "Span")) {
888 g_warning ("Unexpected rich text (not supported, yet!)");
890 } else if (xmlStrEqual (child->name, "Field")) {
893 text_node = g_new0 (glTextNode, 1);
894 text_node->field_flag = TRUE;
895 text_node->data = xmlGetProp (child, "name");
896 text_nodes = g_list_append (text_nodes, text_node);
898 } else if (xmlStrEqual (child->name, "NL")) {
901 lines = g_list_append (lines, text_nodes);
905 g_warning ("Unexpected Span child: \"%s\"", child->name);
910 /* Store last line. */
911 lines = g_list_append (lines, text_nodes);
914 gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
915 gl_text_node_lines_free (&lines);
917 gl_debug (DEBUG_XML, "END");
920 /****************************************************************************/
921 /* Save label to xml label file. */
922 /****************************************************************************/
924 gl_xml_label_save (glLabel *label,
925 const gchar *utf8_filename,
926 glXMLLabelStatus *status)
932 gl_debug (DEBUG_XML, "START");
934 doc = xml_label_to_doc (label, status);
936 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
938 g_warning (_("Utf8 conversion error."));
940 xmlSetDocCompressMode (doc, 9);
941 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
945 g_warning (_("Problem saving xml file."));
946 *status = XML_LABEL_ERROR_SAVE_FILE;
950 gl_label_set_filename (label, utf8_filename);
951 gl_label_clear_modified (label);
957 gl_debug (DEBUG_XML, "END");
960 /****************************************************************************/
961 /* Save label to xml buffer. */
962 /****************************************************************************/
964 gl_xml_label_save_buffer (glLabel *label,
965 glXMLLabelStatus *status)
971 gl_debug (DEBUG_XML, "START");
973 doc = xml_label_to_doc (label, status);
975 xmlDocDumpMemory (doc, (xmlChar **)&buffer, &size);
978 gl_label_clear_modified (label);
980 gl_debug (DEBUG_XML, "END");
985 /*--------------------------------------------------------------------------*/
986 /* PRIVATE. Convert label to xml doc structure. */
987 /*--------------------------------------------------------------------------*/
989 xml_label_to_doc (glLabel *label,
990 glXMLLabelStatus *status)
994 glTemplate *template;
997 gl_debug (DEBUG_XML, "START");
1001 doc = xmlNewDoc ("1.0");
1002 doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Glabels-document", NULL);
1004 ns = xmlNewNs (doc->xmlRootNode, NAME_SPACE, NULL);
1005 xmlSetNs (doc->xmlRootNode, ns);
1007 template = gl_label_get_template (label);
1008 gl_xml_template_add_template (template, doc->xmlRootNode, ns);
1010 xml_create_objects (doc->xmlRootNode, ns, label);
1012 merge = gl_label_get_merge (label);
1013 gl_debug (DEBUG_XML, "merge=%p", merge);
1014 if (merge != NULL) {
1015 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1016 g_object_unref (G_OBJECT(merge));
1019 xml_create_data (doc->xmlRootNode, ns, label);
1021 gl_debug (DEBUG_XML, "END");
1023 *status = XML_LABEL_OK;
1027 /*--------------------------------------------------------------------------*/
1028 /* PRIVATE. Add XML Objects Node */
1029 /*--------------------------------------------------------------------------*/
1031 xml_create_objects (xmlNodePtr root,
1036 gboolean rotate_flag;
1038 glLabelObject *object;
1040 gl_debug (DEBUG_XML, "START");
1042 rotate_flag = gl_label_get_rotate_flag (label);
1044 node = xmlNewChild (root, ns, "Objects", NULL);
1045 xmlSetProp (node, "id", "0");
1046 gl_xml_set_prop_boolean (node, "rotate", rotate_flag);
1048 for (p = label->objects; p != NULL; p = p->next) {
1050 object = GL_LABEL_OBJECT(p->data);
1052 if ( GL_IS_LABEL_TEXT(object) ) {
1053 xml_create_object_text (node, ns, object);
1054 } else if ( GL_IS_LABEL_BOX(object) ) {
1055 xml_create_object_box (node, ns, object);
1056 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1057 xml_create_object_ellipse (node, ns, object);
1058 } else if ( GL_IS_LABEL_LINE(object) ) {
1059 xml_create_object_line (node, ns, object);
1060 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1061 xml_create_object_image (node, ns, object);
1062 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1063 xml_create_object_barcode (node, ns, object);
1065 g_warning ("Unknown label object");
1070 gl_debug (DEBUG_XML, "END");
1073 /*--------------------------------------------------------------------------*/
1074 /* PRIVATE. Add XML Objects->Object-text Node */
1075 /*--------------------------------------------------------------------------*/
1077 xml_create_object_text (xmlNodePtr root,
1079 glLabelObject *object)
1084 GtkJustification just;
1087 gl_debug (DEBUG_XML, "START");
1089 node = xmlNewChild (root, ns, "Object-text", NULL);
1091 /* position attrs */
1092 gl_label_object_get_position (object, &x, &y);
1093 gl_xml_set_prop_length (node, "x", x);
1094 gl_xml_set_prop_length (node, "y", y);
1097 gl_label_text_get_box ( GL_LABEL_TEXT(object), &w, &h);
1098 gl_xml_set_prop_length (node, "w", w);
1099 gl_xml_set_prop_length (node, "h", h);
1102 just = gl_label_text_get_text_alignment (GL_LABEL_TEXT(object));
1103 xmlSetProp (node, "justify", gl_util_just_to_string (just));
1106 gl_label_object_get_affine (object, affine);
1107 gl_xml_set_prop_double (node, "a0", affine[0]);
1108 gl_xml_set_prop_double (node, "a1", affine[1]);
1109 gl_xml_set_prop_double (node, "a2", affine[2]);
1110 gl_xml_set_prop_double (node, "a3", affine[3]);
1111 gl_xml_set_prop_double (node, "a4", affine[4]);
1112 gl_xml_set_prop_double (node, "a5", affine[5]);
1115 xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1117 gl_debug (DEBUG_XML, "END");
1120 /*--------------------------------------------------------------------------*/
1121 /* PRIVATE. Add XML Objects->Object-box Node */
1122 /*--------------------------------------------------------------------------*/
1124 xml_create_object_box (xmlNodePtr root,
1126 glLabelObject *object)
1132 guint line_color, fill_color;
1135 gl_debug (DEBUG_XML, "START");
1137 node = xmlNewChild (root, ns, "Object-box", NULL);
1139 /* position attrs */
1140 gl_label_object_get_position (object, &x, &y);
1141 gl_xml_set_prop_length (node, "x", x);
1142 gl_xml_set_prop_length (node, "y", y);
1145 gl_label_object_get_size (object, &w, &h);
1146 gl_xml_set_prop_length (node, "w", w);
1147 gl_xml_set_prop_length (node, "h", h);
1150 line_width = gl_label_box_get_line_width (GL_LABEL_BOX(object));
1151 line_color = gl_label_box_get_line_color (GL_LABEL_BOX(object));
1152 gl_xml_set_prop_length (node, "line_width", line_width);
1153 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1156 fill_color = gl_label_box_get_fill_color (GL_LABEL_BOX(object));
1157 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1160 gl_label_object_get_affine (object, affine);
1161 gl_xml_set_prop_double (node, "a0", affine[0]);
1162 gl_xml_set_prop_double (node, "a1", affine[1]);
1163 gl_xml_set_prop_double (node, "a2", affine[2]);
1164 gl_xml_set_prop_double (node, "a3", affine[3]);
1165 gl_xml_set_prop_double (node, "a4", affine[4]);
1166 gl_xml_set_prop_double (node, "a5", affine[5]);
1168 gl_debug (DEBUG_XML, "END");
1171 /*--------------------------------------------------------------------------*/
1172 /* PRIVATE. Add XML Objects->Object-ellipse Node */
1173 /*--------------------------------------------------------------------------*/
1175 xml_create_object_ellipse (xmlNodePtr root,
1177 glLabelObject *object)
1183 guint line_color, fill_color;
1186 gl_debug (DEBUG_XML, "START");
1188 node = xmlNewChild (root, ns, "Object-ellipse", NULL);
1190 /* position attrs */
1191 gl_label_object_get_position (object, &x, &y);
1192 gl_xml_set_prop_length (node, "x", x);
1193 gl_xml_set_prop_length (node, "y", y);
1196 gl_label_object_get_size (object, &w, &h);
1197 gl_xml_set_prop_length (node, "w", w);
1198 gl_xml_set_prop_length (node, "h", h);
1201 line_width = gl_label_ellipse_get_line_width (GL_LABEL_ELLIPSE(object));
1202 line_color = gl_label_ellipse_get_line_color (GL_LABEL_ELLIPSE(object));
1203 gl_xml_set_prop_length (node, "line_width", line_width);
1204 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1207 fill_color = gl_label_ellipse_get_fill_color (GL_LABEL_ELLIPSE(object));
1208 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1211 gl_label_object_get_affine (object, affine);
1212 gl_xml_set_prop_double (node, "a0", affine[0]);
1213 gl_xml_set_prop_double (node, "a1", affine[1]);
1214 gl_xml_set_prop_double (node, "a2", affine[2]);
1215 gl_xml_set_prop_double (node, "a3", affine[3]);
1216 gl_xml_set_prop_double (node, "a4", affine[4]);
1217 gl_xml_set_prop_double (node, "a5", affine[5]);
1219 gl_debug (DEBUG_XML, "END");
1222 /*--------------------------------------------------------------------------*/
1223 /* PRIVATE. Add XML Objects->Object-line Node */
1224 /*--------------------------------------------------------------------------*/
1226 xml_create_object_line (xmlNodePtr root,
1228 glLabelObject *object)
1237 gl_debug (DEBUG_XML, "START");
1239 node = xmlNewChild (root, ns, "Object-line", NULL);
1241 /* position attrs */
1242 gl_label_object_get_position (object, &x, &y);
1243 gl_xml_set_prop_length (node, "x", x);
1244 gl_xml_set_prop_length (node, "y", y);
1247 gl_label_object_get_size (object, &dx, &dy);
1248 gl_xml_set_prop_length (node, "dx", dx);
1249 gl_xml_set_prop_length (node, "dy", dy);
1252 line_width = gl_label_line_get_line_width (GL_LABEL_LINE(object));
1253 line_color = gl_label_line_get_line_color (GL_LABEL_LINE(object));
1254 gl_xml_set_prop_length (node, "line_width", line_width);
1255 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1258 gl_label_object_get_affine (object, affine);
1259 gl_xml_set_prop_double (node, "a0", affine[0]);
1260 gl_xml_set_prop_double (node, "a1", affine[1]);
1261 gl_xml_set_prop_double (node, "a2", affine[2]);
1262 gl_xml_set_prop_double (node, "a3", affine[3]);
1263 gl_xml_set_prop_double (node, "a4", affine[4]);
1264 gl_xml_set_prop_double (node, "a5", affine[5]);
1266 gl_debug (DEBUG_XML, "END");
1269 /*--------------------------------------------------------------------------*/
1270 /* PRIVATE. Add XML Objects->Object-image Node */
1271 /*--------------------------------------------------------------------------*/
1273 xml_create_object_image (xmlNodePtr root,
1275 glLabelObject *object)
1280 glTextNode *filename;
1283 gl_debug (DEBUG_XML, "START");
1285 node = xmlNewChild (root, ns, "Object-image", NULL);
1287 /* position attrs */
1288 gl_label_object_get_position (object, &x, &y);
1289 gl_xml_set_prop_length (node, "x", x);
1290 gl_xml_set_prop_length (node, "y", y);
1293 gl_label_object_get_size (object, &w, &h);
1294 gl_xml_set_prop_length (node, "w", w);
1295 gl_xml_set_prop_length (node, "h", h);
1297 /* src OR field attr */
1298 filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1299 if (filename->field_flag) {
1300 xmlSetProp (node, "field", filename->data);
1302 xmlSetProp (node, "src", filename->data);
1304 gl_text_node_free (&filename);
1307 gl_label_object_get_affine (object, affine);
1308 gl_xml_set_prop_double (node, "a0", affine[0]);
1309 gl_xml_set_prop_double (node, "a1", affine[1]);
1310 gl_xml_set_prop_double (node, "a2", affine[2]);
1311 gl_xml_set_prop_double (node, "a3", affine[3]);
1312 gl_xml_set_prop_double (node, "a4", affine[4]);
1313 gl_xml_set_prop_double (node, "a5", affine[5]);
1315 gl_debug (DEBUG_XML, "END");
1318 /*--------------------------------------------------------------------------*/
1319 /* PRIVATE. Add XML Objects->Object-barcode Node */
1320 /*--------------------------------------------------------------------------*/
1322 xml_create_object_barcode (xmlNodePtr root,
1324 glLabelObject *object)
1329 glTextNode *text_node;
1330 glBarcodeStyle style;
1332 gboolean checksum_flag;
1336 gl_debug (DEBUG_XML, "START");
1338 node = xmlNewChild (root, ns, "Object-barcode", NULL);
1340 /* position attrs */
1341 gl_label_object_get_position (object, &x, &y);
1342 gl_xml_set_prop_length (node, "x", x);
1343 gl_xml_set_prop_length (node, "y", y);
1346 gl_label_object_get_size (object, &w, &h);
1347 gl_xml_set_prop_length (node, "w", w);
1348 gl_xml_set_prop_length (node, "h", h);
1350 /* Barcode properties attrs */
1351 gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1352 &style, &text_flag, &checksum_flag, &color);
1353 xmlSetProp (node, "style", gl_barcode_style_to_text (style));
1354 gl_xml_set_prop_boolean (node, "text", text_flag);
1355 gl_xml_set_prop_boolean (node, "checksum", checksum_flag);
1356 gl_xml_set_prop_uint_hex (node, "color", color);
1358 /* data OR field attr */
1359 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1360 if (text_node->field_flag) {
1361 xmlSetProp (node, "field", text_node->data);
1363 xmlSetProp (node, "data", text_node->data);
1365 gl_text_node_free (&text_node);
1368 gl_label_object_get_affine (object, affine);
1369 gl_xml_set_prop_double (node, "a0", affine[0]);
1370 gl_xml_set_prop_double (node, "a1", affine[1]);
1371 gl_xml_set_prop_double (node, "a2", affine[2]);
1372 gl_xml_set_prop_double (node, "a3", affine[3]);
1373 gl_xml_set_prop_double (node, "a4", affine[4]);
1374 gl_xml_set_prop_double (node, "a5", affine[5]);
1376 gl_debug (DEBUG_XML, "END");
1379 /*--------------------------------------------------------------------------*/
1380 /* PRIVATE. Add XML Label Merge Fields Node */
1381 /*--------------------------------------------------------------------------*/
1383 xml_create_merge_fields (xmlNodePtr root,
1387 xmlNodePtr node, child;
1392 gl_debug (DEBUG_XML, "START");
1394 merge = gl_label_get_merge (label);
1396 node = xmlNewChild (root, ns, "Merge", NULL);
1398 string = gl_merge_get_name (merge);
1399 xmlSetProp (node, "type", string);
1402 string = gl_merge_get_src (merge);
1403 xmlSetProp (node, "src", string);
1406 g_object_unref (G_OBJECT(merge));
1408 gl_debug (DEBUG_XML, "END");
1411 /*--------------------------------------------------------------------------*/
1412 /* PRIVATE. Add XML Label Data Node */
1413 /*--------------------------------------------------------------------------*/
1415 xml_create_data (xmlNodePtr root,
1420 GList *name_list, *p;
1421 GHashTable *pixbuf_cache;
1423 gl_debug (DEBUG_XML, "START");
1425 node = xmlNewChild (root, ns, "Data", NULL);
1427 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1428 name_list = gl_pixbuf_cache_get_name_list (pixbuf_cache);
1430 for (p = name_list; p != NULL; p=p->next) {
1431 xml_create_pixdata (node, ns, label, p->data);
1434 gl_pixbuf_cache_free_name_list (name_list);
1437 gl_debug (DEBUG_XML, "END");
1440 /*--------------------------------------------------------------------------*/
1441 /* PRIVATE. Add XML Label Data Pixbuf Node */
1442 /*--------------------------------------------------------------------------*/
1444 xml_create_pixdata (xmlNodePtr root,
1450 GHashTable *pixbuf_cache;
1452 GdkPixdata *pixdata;
1454 guint stream_length;
1457 gl_debug (DEBUG_XML, "START");
1459 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1461 pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, name);
1462 if ( pixbuf != NULL ) {
1464 pixdata = g_new0 (GdkPixdata, 1);
1465 gdk_pixdata_from_pixbuf (pixdata, pixbuf, FALSE);
1466 stream = gdk_pixdata_serialize (pixdata, &stream_length);
1467 base64 = gl_base64_encode (stream, stream_length);
1469 node = xmlNewChild (root, ns, "Pixdata", base64);
1470 xmlSetProp (node, "name", name);
1471 xmlSetProp (node, "encoding", "Base64");
1473 gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, name);
1481 gl_debug (DEBUG_XML, "END");
1484 /*--------------------------------------------------------------------------*/
1485 /* PRIVATE. Create top-level Span node. */
1486 /*--------------------------------------------------------------------------*/
1488 xml_create_toplevel_span (xmlNodePtr root,
1490 glLabelText *object_text)
1495 GnomeFontWeight font_weight;
1496 gboolean font_italic_flag;
1498 GtkJustification just;
1499 GList *lines, *p_line, *p_node;
1500 glTextNode *text_node;
1503 node = xmlNewChild (root, ns, "Span", NULL);
1505 /* All span attrs at top level. */
1506 gl_label_text_get_props (GL_LABEL_TEXT(object_text),
1507 &font_family, &font_size, &font_weight,
1510 xmlSetProp (node, "font_family", font_family);
1511 gl_xml_set_prop_double (node, "font_size", font_size);
1512 xmlSetProp (node, "font_weight", gl_util_weight_to_string (font_weight));
1513 gl_xml_set_prop_boolean (node, "font_italic", font_italic_flag);
1514 gl_xml_set_prop_uint_hex (node, "color", color);
1516 /* Build children. */
1517 lines = gl_label_text_get_lines (GL_LABEL_TEXT(object_text));
1518 for (p_line = lines; p_line != NULL; p_line = p_line->next) {
1520 for (p_node = (GList *) p_line->data; p_node != NULL;
1521 p_node = p_node->next) {
1522 text_node = (glTextNode *) p_node->data;
1524 if (text_node->field_flag) {
1525 child = xmlNewChild (node, ns, "Field", NULL);
1526 xmlSetProp (child, "name", text_node->data);
1528 xmlNodeAddContent (node, text_node->data);
1533 if ( p_line->next ) {
1534 child = xmlNewChild (node, ns, "NL", NULL);
1539 gl_text_node_lines_free (&lines);
1540 g_free (font_family);