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"
40 #include "xml-label.h"
41 #include "xml-label-04.h"
42 #include "xml-label-191.h"
43 #include <libglabels/template.h>
44 #include <libglabels/xml-template.h>
45 #include <libglabels/xml.h>
50 /*========================================================*/
51 /* Private macros and constants. */
52 /*========================================================*/
53 #define COMPAT01_NAME_SPACE "http://snaught.com/glabels/0.1/"
54 #define COMPAT04_NAME_SPACE "http://snaught.com/glabels/0.4/"
55 #define COMPAT191_NAME_SPACE "http://snaught.com/glabels/1.92/"
57 /*========================================================*/
59 /*========================================================*/
61 /*========================================================*/
62 /* Private globals. */
63 /*========================================================*/
65 /*========================================================*/
66 /* Private function prototypes. */
67 /*========================================================*/
69 static glLabel *xml_doc_to_label (xmlDocPtr doc,
70 glXMLLabelStatus *status);
72 static glLabel *xml_parse_label (xmlNodePtr root,
73 glXMLLabelStatus *status);
75 static void xml_parse_objects (xmlNodePtr node,
78 static void xml_parse_object_text (xmlNodePtr node,
81 static void xml_parse_object_box (xmlNodePtr node,
84 static void xml_parse_object_ellipse (xmlNodePtr node,
87 static void xml_parse_object_line (xmlNodePtr node,
90 static void xml_parse_object_image (xmlNodePtr node,
93 static void xml_parse_object_barcode (xmlNodePtr node,
96 static void xml_parse_merge_fields (xmlNodePtr node,
99 static void xml_parse_data (xmlNodePtr node,
102 static void xml_parse_pixdata (xmlNodePtr node,
105 static void xml_parse_toplevel_span (xmlNodePtr node,
106 glLabelObject *object);
109 static xmlDocPtr xml_label_to_doc (glLabel *label,
110 glXMLLabelStatus *status);
112 static void xml_create_objects (xmlNodePtr root,
116 static void xml_create_object_text (xmlNodePtr root,
118 glLabelObject *object);
120 static void xml_create_object_box (xmlNodePtr root,
122 glLabelObject *object);
124 static void xml_create_object_line (xmlNodePtr root,
126 glLabelObject *object);
128 static void xml_create_object_ellipse(xmlNodePtr root,
130 glLabelObject *object);
132 static void xml_create_object_image (xmlNodePtr root,
134 glLabelObject *object);
136 static void xml_create_object_barcode(xmlNodePtr root,
138 glLabelObject *object);
140 static void xml_create_merge_fields (xmlNodePtr root,
144 static void xml_create_data (xmlNodePtr root,
148 static void xml_create_pixdata (xmlNodePtr root,
153 static void xml_create_toplevel_span (xmlNodePtr node,
155 glLabelText *object_text);
158 /****************************************************************************/
159 /* Open and read label from xml file. */
160 /****************************************************************************/
162 gl_xml_label_open (const gchar *utf8_filename,
163 glXMLLabelStatus *status)
169 gl_debug (DEBUG_XML, "START");
171 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
172 g_return_val_if_fail (filename, NULL);
174 doc = xmlParseFile (filename);
176 g_warning (_("xmlParseFile error"));
177 *status = XML_LABEL_ERROR_OPEN_PARSE;
181 xmlXIncludeProcess (doc);
182 xmlReconciliateNs (doc, xmlDocGetRootElement (doc));
184 label = xml_doc_to_label (doc, status);
189 gl_label_set_filename (label, utf8_filename);
190 gl_label_clear_modified (label);
194 gl_debug (DEBUG_XML, "END");
199 /****************************************************************************/
200 /* Read label from xml buffer. */
201 /****************************************************************************/
203 gl_xml_label_open_buffer (const gchar *buffer,
204 glXMLLabelStatus *status)
209 gl_debug (DEBUG_XML, "START");
211 doc = xmlParseDoc ((xmlChar *) buffer);
213 g_warning (_("xmlParseFile error"));
214 *status = XML_LABEL_ERROR_OPEN_PARSE;
218 label = xml_doc_to_label (doc, status);
223 gl_label_clear_modified (label);
226 gl_debug (DEBUG_XML, "END");
231 /*--------------------------------------------------------------------------*/
232 /* PRIVATE. Parse xml doc structure and create label. */
233 /*--------------------------------------------------------------------------*/
235 xml_doc_to_label (xmlDocPtr doc,
236 glXMLLabelStatus *status)
238 xmlNodePtr root, node;
242 gl_debug (DEBUG_XML, "START");
246 *status = XML_LABEL_OK;
248 root = xmlDocGetRootElement (doc);
249 if (!root || !root->name) {
250 g_warning (_("No document root"));
251 *status = XML_LABEL_ERROR_OPEN_PARSE;
255 ns = xmlSearchNsByHref (doc, root, GL_XML_NAME_SPACE);
257 label = xml_parse_label (root, status);
259 gl_label_set_compression (label, xmlGetDocCompressMode (doc));
261 /* Try compatability mode 0.1 */
262 ns = xmlSearchNsByHref (doc, root, COMPAT01_NAME_SPACE);
264 g_warning (_("Importing from glabels 0.1 format"));
266 label = NULL; /* TODO */
268 /* Try compatability mode 0.4 */
269 ns = xmlSearchNsByHref (doc, root,
270 COMPAT04_NAME_SPACE);
272 g_warning (_("Importing from glabels 0.4 format"));
273 label = gl_xml_label_04_parse (root, status);
275 /* Try compatability mode 1.91 */
276 ns = xmlSearchNsByHref (doc, root,
277 COMPAT191_NAME_SPACE);
279 g_warning (_("Importing from glabels 1.91 format"));
280 label = gl_xml_label_191_parse (root, status);
282 g_warning (_("bad document, unknown glabels Namespace"));
283 *status = XML_LABEL_ERROR_OPEN_PARSE;
290 gl_debug (DEBUG_XML, "END");
295 /*--------------------------------------------------------------------------*/
296 /* PRIVATE. Parse xml root node and create label. */
297 /*--------------------------------------------------------------------------*/
299 xml_parse_label (xmlNodePtr root,
300 glXMLLabelStatus *status)
302 xmlNodePtr child_node;
304 glTemplate *template;
306 gl_debug (DEBUG_XML, "START");
308 *status = XML_LABEL_OK;
310 if (!xmlStrEqual (root->name, "Glabels-document")) {
311 g_warning (_("Bad root node = \"%s\""), root->name);
312 *status = XML_LABEL_ERROR_OPEN_PARSE;
316 label = GL_LABEL(gl_label_new ());
318 /* Pass 1, extract data nodes to pre-load cache. */
319 for (child_node = root->xmlChildrenNode; child_node != NULL; child_node = child_node->next) {
320 if (xmlStrEqual (child_node->name, "Data")) {
321 xml_parse_data (child_node, label);
325 /* Pass 2, now extract everything else. */
326 for (child_node = root->xmlChildrenNode;
328 child_node = child_node->next) {
330 if (xmlStrEqual (child_node->name, "Template")) {
331 template = gl_xml_template_parse_template_node (child_node);
333 g_object_unref (label);
334 *status = XML_LABEL_UNKNOWN_MEDIA;
337 gl_template_register (template);
338 gl_label_set_template (label, template);
339 gl_template_free (template);
340 } else if (xmlStrEqual (child_node->name, "Objects")) {
341 xml_parse_objects (child_node, label);
342 } else if (xmlStrEqual (child_node->name, "Merge")) {
343 xml_parse_merge_fields (child_node, label);
344 } else if (xmlStrEqual (child_node->name, "Data")) {
345 /* Handled in pass 1. */
347 if (!xmlNodeIsText (child_node)) {
348 g_warning (_("bad node in Document node = \"%s\""),
350 g_object_unref (label);
351 *status = XML_LABEL_ERROR_OPEN_PARSE;
357 gl_debug (DEBUG_XML, "END");
362 /*--------------------------------------------------------------------------*/
363 /* PRIVATE. Parse Objects node. */
364 /*--------------------------------------------------------------------------*/
366 xml_parse_objects (xmlNodePtr node,
369 gboolean rotate_flag;
372 gl_debug (DEBUG_XML, "START");
374 rotate_flag = gl_xml_get_prop_boolean (node, "rotate", FALSE);
375 gl_label_set_rotate_flag (label, rotate_flag);
377 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
379 if (xmlStrEqual (child->name, "Object-text")) {
380 xml_parse_object_text (child, label);
381 } else if (xmlStrEqual (child->name, "Object-box")) {
382 xml_parse_object_box (child, label);
383 } else if (xmlStrEqual (child->name, "Object-ellipse")) {
384 xml_parse_object_ellipse (child, label);
385 } else if (xmlStrEqual (child->name, "Object-line")) {
386 xml_parse_object_line (child, label);
387 } else if (xmlStrEqual (child->name, "Object-image")) {
388 xml_parse_object_image (child, label);
389 } else if (xmlStrEqual (child->name, "Object-barcode")) {
390 xml_parse_object_barcode (child, label);
392 if (!xmlNodeIsText (child)) {
393 g_warning (_("bad node = \"%s\""), child->name);
399 gl_debug (DEBUG_XML, "END");
402 /*--------------------------------------------------------------------------*/
403 /* PRIVATE. Parse XML Objects->Object-text Node */
404 /*--------------------------------------------------------------------------*/
406 xml_parse_object_text (xmlNodePtr node,
413 GtkJustification just;
414 gboolean auto_shrink;
418 gl_debug (DEBUG_XML, "START");
420 object = gl_label_text_new (label);
423 x = gl_xml_get_prop_length (node, "x", 0.0);
424 y = gl_xml_get_prop_length (node, "y", 0.0);
425 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
427 /* implied size attrs */
428 w = gl_xml_get_prop_length (node, "w", 0);
429 h = gl_xml_get_prop_length (node, "h", 0);
430 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
433 string = xmlGetProp (node, "justify");
434 just = gl_util_string_to_just (string);
436 gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), just);
438 /* auto_shrink attr */
439 auto_shrink = gl_xml_get_prop_boolean (node, "auto_shrink", FALSE);
440 gl_label_text_set_auto_shrink (GL_LABEL_TEXT(object), auto_shrink);
443 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
444 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
445 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
446 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
447 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
448 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
449 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
451 /* Process children */
452 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
453 if (xmlStrEqual (child->name, "Span")) {
454 xml_parse_toplevel_span (child, GL_LABEL_OBJECT(object));
457 if (!xmlNodeIsText (child)) {
458 g_warning ("Unexpected Object-text child: \"%s\"",
464 gl_debug (DEBUG_XML, "END");
467 /*--------------------------------------------------------------------------*/
468 /* PRIVATE. Parse XML Objects->Object-box Node */
469 /*--------------------------------------------------------------------------*/
471 xml_parse_object_box (xmlNodePtr node,
478 guint line_color, fill_color;
481 gl_debug (DEBUG_XML, "START");
483 object = gl_label_box_new (label);
486 x = gl_xml_get_prop_length (node, "x", 0.0);
487 y = gl_xml_get_prop_length (node, "y", 0.0);
488 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
491 w = gl_xml_get_prop_length (node, "w", 0);
492 h = gl_xml_get_prop_length (node, "h", 0);
493 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
496 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
497 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
498 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
499 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
502 fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
503 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color);
506 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
507 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
508 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
509 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
510 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
511 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
512 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
514 gl_debug (DEBUG_XML, "END");
517 /*--------------------------------------------------------------------------*/
518 /* PRIVATE. Parse XML Objects->Object-ellipse Node */
519 /*--------------------------------------------------------------------------*/
521 xml_parse_object_ellipse (xmlNodePtr node,
528 guint line_color, fill_color;
531 gl_debug (DEBUG_XML, "START");
533 object = gl_label_ellipse_new (label);
536 x = gl_xml_get_prop_length (node, "x", 0.0);
537 y = gl_xml_get_prop_length (node, "y", 0.0);
538 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
541 w = gl_xml_get_prop_length (node, "w", 0);
542 h = gl_xml_get_prop_length (node, "h", 0);
543 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
546 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
547 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
548 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
549 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
552 fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
553 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color);
556 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
557 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
558 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
559 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
560 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
561 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
562 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
564 gl_debug (DEBUG_XML, "END");
567 /*--------------------------------------------------------------------------*/
568 /* PRIVATE. Parse XML Objects->Object-line Node */
569 /*--------------------------------------------------------------------------*/
571 xml_parse_object_line (xmlNodePtr node,
581 gl_debug (DEBUG_XML, "START");
583 object = gl_label_line_new (label);
586 x = gl_xml_get_prop_length (node, "x", 0.0);
587 y = gl_xml_get_prop_length (node, "y", 0.0);
588 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
591 dx = gl_xml_get_prop_length (node, "dx", 0);
592 dy = gl_xml_get_prop_length (node, "dy", 0);
593 gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy);
596 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
597 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
598 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
599 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
602 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
603 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
604 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
605 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
606 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
607 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
608 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
610 gl_debug (DEBUG_XML, "END");
613 /*--------------------------------------------------------------------------*/
614 /* PRIVATE. Parse XML Objects->Object-image Node */
615 /*--------------------------------------------------------------------------*/
617 xml_parse_object_image (xmlNodePtr node,
624 glTextNode *filename;
627 gl_debug (DEBUG_XML, "START");
629 object = gl_label_image_new (label);
632 x = gl_xml_get_prop_length (node, "x", 0.0);
633 y = gl_xml_get_prop_length (node, "y", 0.0);
634 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
636 /* src or field attr */
637 string = xmlGetProp (node, "src");
639 filename = g_new0 (glTextNode, 1);
640 filename->field_flag = FALSE;
641 filename->data = string;
642 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
643 gl_text_node_free (&filename);
645 string = xmlGetProp (node, "field");
647 filename = g_new0 (glTextNode, 1);
648 filename->field_flag = TRUE;
649 filename->data = string;
650 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
651 gl_text_node_free (&filename);
653 g_warning ("Missing Object-image src or field attr");
658 w = gl_xml_get_prop_length (node, "w", 0);
659 h = gl_xml_get_prop_length (node, "h", 0);
660 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
663 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
664 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
665 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
666 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
667 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
668 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
669 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
671 gl_debug (DEBUG_XML, "END");
674 /*--------------------------------------------------------------------------*/
675 /* PRIVATE. Parse XML Objects->Object-barcode Node */
676 /*--------------------------------------------------------------------------*/
678 xml_parse_object_barcode (xmlNodePtr node,
685 glTextNode *text_node;
688 gboolean checksum_flag;
693 gl_debug (DEBUG_XML, "START");
695 object = gl_label_barcode_new (label);
698 x = gl_xml_get_prop_length (node, "x", 0.0);
699 y = gl_xml_get_prop_length (node, "y", 0.0);
700 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
703 w = gl_xml_get_prop_length (node, "w", 0);
704 h = gl_xml_get_prop_length (node, "h", 0);
705 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
708 id = xmlGetProp (node, "style");
709 text_flag = gl_xml_get_prop_boolean (node, "text", FALSE);
710 checksum_flag = gl_xml_get_prop_boolean (node, "checksum", TRUE);
711 color = gl_xml_get_prop_uint (node, "color", 0);
712 format_digits = gl_xml_get_prop_uint (node, "format", 0);
713 gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
714 id, text_flag, checksum_flag, format_digits);
715 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color);
718 /* data or field attr */
719 string = xmlGetProp (node, "data");
721 text_node = g_new0 (glTextNode, 1);
722 text_node->field_flag = FALSE;
723 text_node->data = string;
724 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
725 gl_text_node_free (&text_node);
727 string = xmlGetProp (node, "field");
729 text_node = g_new0 (glTextNode, 1);
730 text_node->field_flag = TRUE;
731 text_node->data = string;
732 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
733 gl_text_node_free (&text_node);
735 g_warning ("Missing Object-barcode data or field attr");
740 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
741 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
742 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
743 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
744 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
745 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
746 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
748 gl_debug (DEBUG_XML, "END");
751 /*--------------------------------------------------------------------------*/
752 /* PRIVATE. Parse XML merge fields tag. */
753 /*--------------------------------------------------------------------------*/
755 xml_parse_merge_fields (xmlNodePtr node,
762 gl_debug (DEBUG_XML, "START");
764 string = xmlGetProp (node, "type");
765 merge = gl_merge_new (string);
768 string = xmlGetProp (node, "src");
769 gl_merge_set_src (merge, string);
772 gl_label_set_merge (label, merge);
774 g_object_unref (G_OBJECT(merge));
776 gl_debug (DEBUG_XML, "END");
779 /*--------------------------------------------------------------------------*/
780 /* PRIVATE. Parse XML data tag. */
781 /*--------------------------------------------------------------------------*/
783 xml_parse_data (xmlNodePtr node,
788 gl_debug (DEBUG_XML, "START");
790 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
792 if (xmlStrEqual (child->name, "Pixdata")) {
793 xml_parse_pixdata (child, label);
795 if (!xmlNodeIsText (child)) {
796 g_warning (_("bad node in Data node = \"%s\""),
802 gl_debug (DEBUG_XML, "END");
805 /*--------------------------------------------------------------------------*/
806 /* PRIVATE. Parse XML pixbuf data tag. */
807 /*--------------------------------------------------------------------------*/
809 xml_parse_pixdata (xmlNodePtr node,
812 gchar *name, *base64;
818 GHashTable *pixbuf_cache;
820 gl_debug (DEBUG_XML, "START");
822 name = xmlGetProp (node, "name");
823 base64 = xmlNodeGetContent (node);
825 stream = gl_base64_decode (base64, &stream_length);
826 pixdata = g_new0 (GdkPixdata, 1);
827 ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
830 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
832 pixbuf_cache = gl_label_get_pixbuf_cache (label);
833 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
841 gl_debug (DEBUG_XML, "END");
844 /*--------------------------------------------------------------------------*/
845 /* PRIVATE. Parse top-level Span tag. */
846 /*--------------------------------------------------------------------------*/
848 xml_parse_toplevel_span (xmlNodePtr node,
849 glLabelObject *object)
853 GnomeFontWeight font_weight;
854 gboolean font_italic_flag;
856 gdouble text_line_spacing;
858 GList *lines, *text_nodes;
860 glTextNode *text_node;
862 gl_debug (DEBUG_XML, "START");
864 /* Font family attr */
865 font_family = xmlGetProp (node, "font_family");
866 gl_label_object_set_font_family (object, font_family);
867 g_free (font_family);
870 font_size = gl_xml_get_prop_double (node, "font_size", 0.0);
871 gl_label_object_set_font_size (object, font_size);
873 /* Font weight attr */
874 string = xmlGetProp (node, "font_weight");
875 font_weight = gl_util_string_to_weight (string);
877 gl_label_object_set_font_weight (object, font_weight);
879 /* Font italic flag attr */
880 font_italic_flag = gl_xml_get_prop_boolean (node, "font_italic", FALSE);
881 gl_label_object_set_font_italic_flag (object, font_italic_flag);
883 /* Text color attr */
884 color = gl_xml_get_prop_uint (node, "color", 0);
885 gl_label_object_set_text_color (object, color);
887 /* Text line spacing attr */
888 text_line_spacing = gl_xml_get_prop_double (node, "line_spacing", 1.0);
889 gl_label_object_set_text_line_spacing (object, text_line_spacing);
891 /* Now descend children, and build lines of text nodes */
894 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
896 if (xmlNodeIsText (child)) {
897 gchar *data = xmlNodeGetContent (child);
899 /* Hack: if the first char is LF, it's a xml formatting string */
900 if (data[0] != '\n') {
902 text_node = g_new0 (glTextNode, 1);
903 text_node->field_flag = FALSE;
904 text_node->data = data;
905 text_nodes = g_list_append (text_nodes, text_node);
910 } else if (xmlStrEqual (child->name, "Span")) {
912 g_warning ("Unexpected rich text (not supported, yet!)");
914 } else if (xmlStrEqual (child->name, "Field")) {
917 text_node = g_new0 (glTextNode, 1);
918 text_node->field_flag = TRUE;
919 text_node->data = xmlGetProp (child, "name");
920 text_nodes = g_list_append (text_nodes, text_node);
922 } else if (xmlStrEqual (child->name, "NL")) {
925 lines = g_list_append (lines, text_nodes);
929 g_warning ("Unexpected Span child: \"%s\"", child->name);
934 /* Store last line. */
935 lines = g_list_append (lines, text_nodes);
938 gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
939 gl_text_node_lines_free (&lines);
941 gl_debug (DEBUG_XML, "END");
944 /****************************************************************************/
945 /* Save label to xml label file. */
946 /****************************************************************************/
948 gl_xml_label_save (glLabel *label,
949 const gchar *utf8_filename,
950 glXMLLabelStatus *status)
956 gl_debug (DEBUG_XML, "START");
958 doc = xml_label_to_doc (label, status);
960 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
962 g_warning (_("Utf8 conversion error."));
964 xmlSetDocCompressMode (doc, gl_label_get_compression (label));
965 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
969 g_warning (_("Problem saving xml file."));
970 *status = XML_LABEL_ERROR_SAVE_FILE;
974 gl_label_set_filename (label, utf8_filename);
975 gl_label_clear_modified (label);
981 gl_debug (DEBUG_XML, "END");
984 /****************************************************************************/
985 /* Save label to xml buffer. */
986 /****************************************************************************/
988 gl_xml_label_save_buffer (glLabel *label,
989 glXMLLabelStatus *status)
995 gl_debug (DEBUG_XML, "START");
997 doc = xml_label_to_doc (label, status);
999 xmlDocDumpMemory (doc, (xmlChar **)&buffer, &size);
1002 gl_label_clear_modified (label);
1004 gl_debug (DEBUG_XML, "END");
1009 /*--------------------------------------------------------------------------*/
1010 /* PRIVATE. Convert label to xml doc structure. */
1011 /*--------------------------------------------------------------------------*/
1013 xml_label_to_doc (glLabel *label,
1014 glXMLLabelStatus *status)
1018 glTemplate *template;
1021 gl_debug (DEBUG_XML, "START");
1023 LIBXML_TEST_VERSION;
1025 doc = xmlNewDoc ("1.0");
1026 doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Glabels-document", NULL);
1028 ns = xmlNewNs (doc->xmlRootNode, GL_XML_NAME_SPACE, NULL);
1029 xmlSetNs (doc->xmlRootNode, ns);
1031 template = gl_label_get_template (label);
1032 gl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
1034 xml_create_objects (doc->xmlRootNode, ns, label);
1036 merge = gl_label_get_merge (label);
1037 gl_debug (DEBUG_XML, "merge=%p", merge);
1038 if (merge != NULL) {
1039 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1040 g_object_unref (G_OBJECT(merge));
1043 xml_create_data (doc->xmlRootNode, ns, label);
1045 gl_debug (DEBUG_XML, "END");
1047 *status = XML_LABEL_OK;
1051 /*--------------------------------------------------------------------------*/
1052 /* PRIVATE. Add XML Objects Node */
1053 /*--------------------------------------------------------------------------*/
1055 xml_create_objects (xmlNodePtr root,
1060 gboolean rotate_flag;
1062 glLabelObject *object;
1064 gl_debug (DEBUG_XML, "START");
1066 rotate_flag = gl_label_get_rotate_flag (label);
1068 node = xmlNewChild (root, ns, "Objects", NULL);
1069 xmlSetProp (node, "id", "0");
1070 gl_xml_set_prop_boolean (node, "rotate", rotate_flag);
1072 for (p = label->objects; p != NULL; p = p->next) {
1074 object = GL_LABEL_OBJECT(p->data);
1076 if ( GL_IS_LABEL_TEXT(object) ) {
1077 xml_create_object_text (node, ns, object);
1078 } else if ( GL_IS_LABEL_BOX(object) ) {
1079 xml_create_object_box (node, ns, object);
1080 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1081 xml_create_object_ellipse (node, ns, object);
1082 } else if ( GL_IS_LABEL_LINE(object) ) {
1083 xml_create_object_line (node, ns, object);
1084 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1085 xml_create_object_image (node, ns, object);
1086 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1087 xml_create_object_barcode (node, ns, object);
1089 g_warning ("Unknown label object");
1094 gl_debug (DEBUG_XML, "END");
1097 /*--------------------------------------------------------------------------*/
1098 /* PRIVATE. Add XML Objects->Object-text Node */
1099 /*--------------------------------------------------------------------------*/
1101 xml_create_object_text (xmlNodePtr root,
1103 glLabelObject *object)
1108 GtkJustification just;
1109 gboolean auto_shrink;
1112 gl_debug (DEBUG_XML, "START");
1114 node = xmlNewChild (root, ns, "Object-text", NULL);
1116 /* position attrs */
1117 gl_label_object_get_position (object, &x, &y);
1118 gl_xml_set_prop_length (node, "x", x);
1119 gl_xml_set_prop_length (node, "y", y);
1122 gl_label_text_get_box ( GL_LABEL_TEXT(object), &w, &h);
1123 gl_xml_set_prop_length (node, "w", w);
1124 gl_xml_set_prop_length (node, "h", h);
1127 just = gl_label_object_get_text_alignment (object);
1128 xmlSetProp (node, "justify", gl_util_just_to_string (just));
1130 /* auto_shrink attr */
1131 auto_shrink = gl_label_text_get_auto_shrink (GL_LABEL_TEXT (object));
1132 gl_xml_set_prop_boolean (node, "auto_shrink", auto_shrink);
1135 gl_label_object_get_affine (object, affine);
1136 gl_xml_set_prop_double (node, "a0", affine[0]);
1137 gl_xml_set_prop_double (node, "a1", affine[1]);
1138 gl_xml_set_prop_double (node, "a2", affine[2]);
1139 gl_xml_set_prop_double (node, "a3", affine[3]);
1140 gl_xml_set_prop_double (node, "a4", affine[4]);
1141 gl_xml_set_prop_double (node, "a5", affine[5]);
1144 xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1146 gl_debug (DEBUG_XML, "END");
1149 /*--------------------------------------------------------------------------*/
1150 /* PRIVATE. Add XML Objects->Object-box Node */
1151 /*--------------------------------------------------------------------------*/
1153 xml_create_object_box (xmlNodePtr root,
1155 glLabelObject *object)
1161 guint line_color, fill_color;
1164 gl_debug (DEBUG_XML, "START");
1166 node = xmlNewChild (root, ns, "Object-box", NULL);
1168 /* position attrs */
1169 gl_label_object_get_position (object, &x, &y);
1170 gl_xml_set_prop_length (node, "x", x);
1171 gl_xml_set_prop_length (node, "y", y);
1174 gl_label_object_get_size (object, &w, &h);
1175 gl_xml_set_prop_length (node, "w", w);
1176 gl_xml_set_prop_length (node, "h", h);
1179 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1180 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1181 gl_xml_set_prop_length (node, "line_width", line_width);
1182 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1185 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1186 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1189 gl_label_object_get_affine (object, affine);
1190 gl_xml_set_prop_double (node, "a0", affine[0]);
1191 gl_xml_set_prop_double (node, "a1", affine[1]);
1192 gl_xml_set_prop_double (node, "a2", affine[2]);
1193 gl_xml_set_prop_double (node, "a3", affine[3]);
1194 gl_xml_set_prop_double (node, "a4", affine[4]);
1195 gl_xml_set_prop_double (node, "a5", affine[5]);
1197 gl_debug (DEBUG_XML, "END");
1200 /*--------------------------------------------------------------------------*/
1201 /* PRIVATE. Add XML Objects->Object-ellipse Node */
1202 /*--------------------------------------------------------------------------*/
1204 xml_create_object_ellipse (xmlNodePtr root,
1206 glLabelObject *object)
1212 guint line_color, fill_color;
1215 gl_debug (DEBUG_XML, "START");
1217 node = xmlNewChild (root, ns, "Object-ellipse", NULL);
1219 /* position attrs */
1220 gl_label_object_get_position (object, &x, &y);
1221 gl_xml_set_prop_length (node, "x", x);
1222 gl_xml_set_prop_length (node, "y", y);
1225 gl_label_object_get_size (object, &w, &h);
1226 gl_xml_set_prop_length (node, "w", w);
1227 gl_xml_set_prop_length (node, "h", h);
1230 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1231 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1232 gl_xml_set_prop_length (node, "line_width", line_width);
1233 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1236 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1237 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1240 gl_label_object_get_affine (object, affine);
1241 gl_xml_set_prop_double (node, "a0", affine[0]);
1242 gl_xml_set_prop_double (node, "a1", affine[1]);
1243 gl_xml_set_prop_double (node, "a2", affine[2]);
1244 gl_xml_set_prop_double (node, "a3", affine[3]);
1245 gl_xml_set_prop_double (node, "a4", affine[4]);
1246 gl_xml_set_prop_double (node, "a5", affine[5]);
1248 gl_debug (DEBUG_XML, "END");
1251 /*--------------------------------------------------------------------------*/
1252 /* PRIVATE. Add XML Objects->Object-line Node */
1253 /*--------------------------------------------------------------------------*/
1255 xml_create_object_line (xmlNodePtr root,
1257 glLabelObject *object)
1266 gl_debug (DEBUG_XML, "START");
1268 node = xmlNewChild (root, ns, "Object-line", NULL);
1270 /* position attrs */
1271 gl_label_object_get_position (object, &x, &y);
1272 gl_xml_set_prop_length (node, "x", x);
1273 gl_xml_set_prop_length (node, "y", y);
1276 gl_label_object_get_size (object, &dx, &dy);
1277 gl_xml_set_prop_length (node, "dx", dx);
1278 gl_xml_set_prop_length (node, "dy", dy);
1281 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1282 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1283 gl_xml_set_prop_length (node, "line_width", line_width);
1284 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1287 gl_label_object_get_affine (object, affine);
1288 gl_xml_set_prop_double (node, "a0", affine[0]);
1289 gl_xml_set_prop_double (node, "a1", affine[1]);
1290 gl_xml_set_prop_double (node, "a2", affine[2]);
1291 gl_xml_set_prop_double (node, "a3", affine[3]);
1292 gl_xml_set_prop_double (node, "a4", affine[4]);
1293 gl_xml_set_prop_double (node, "a5", affine[5]);
1295 gl_debug (DEBUG_XML, "END");
1298 /*--------------------------------------------------------------------------*/
1299 /* PRIVATE. Add XML Objects->Object-image Node */
1300 /*--------------------------------------------------------------------------*/
1302 xml_create_object_image (xmlNodePtr root,
1304 glLabelObject *object)
1309 glTextNode *filename;
1312 gl_debug (DEBUG_XML, "START");
1314 node = xmlNewChild (root, ns, "Object-image", NULL);
1316 /* position attrs */
1317 gl_label_object_get_position (object, &x, &y);
1318 gl_xml_set_prop_length (node, "x", x);
1319 gl_xml_set_prop_length (node, "y", y);
1322 gl_label_object_get_size (object, &w, &h);
1323 gl_xml_set_prop_length (node, "w", w);
1324 gl_xml_set_prop_length (node, "h", h);
1326 /* src OR field attr */
1327 filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1328 if (filename->field_flag) {
1329 xmlSetProp (node, "field", filename->data);
1331 xmlSetProp (node, "src", filename->data);
1333 gl_text_node_free (&filename);
1336 gl_label_object_get_affine (object, affine);
1337 gl_xml_set_prop_double (node, "a0", affine[0]);
1338 gl_xml_set_prop_double (node, "a1", affine[1]);
1339 gl_xml_set_prop_double (node, "a2", affine[2]);
1340 gl_xml_set_prop_double (node, "a3", affine[3]);
1341 gl_xml_set_prop_double (node, "a4", affine[4]);
1342 gl_xml_set_prop_double (node, "a5", affine[5]);
1344 gl_debug (DEBUG_XML, "END");
1347 /*--------------------------------------------------------------------------*/
1348 /* PRIVATE. Add XML Objects->Object-barcode Node */
1349 /*--------------------------------------------------------------------------*/
1351 xml_create_object_barcode (xmlNodePtr root,
1353 glLabelObject *object)
1358 glTextNode *text_node;
1361 gboolean checksum_flag;
1363 guint format_digits;
1366 gl_debug (DEBUG_XML, "START");
1368 node = xmlNewChild (root, ns, "Object-barcode", NULL);
1370 /* position attrs */
1371 gl_label_object_get_position (object, &x, &y);
1372 gl_xml_set_prop_length (node, "x", x);
1373 gl_xml_set_prop_length (node, "y", y);
1376 gl_label_object_get_size (object, &w, &h);
1377 gl_xml_set_prop_length (node, "w", w);
1378 gl_xml_set_prop_length (node, "h", h);
1380 /* Barcode properties attrs */
1381 gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1382 &id, &text_flag, &checksum_flag, &format_digits);
1383 color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1384 xmlSetProp (node, "style", id);
1385 gl_xml_set_prop_boolean (node, "text", text_flag);
1386 gl_xml_set_prop_boolean (node, "checksum", checksum_flag);
1387 gl_xml_set_prop_uint_hex (node, "color", color);
1390 /* data OR field attr */
1391 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1392 if (text_node->field_flag) {
1393 xmlSetProp (node, "field", text_node->data);
1394 gl_xml_set_prop_int (node, "format", format_digits);
1396 xmlSetProp (node, "data", text_node->data);
1398 gl_text_node_free (&text_node);
1401 gl_label_object_get_affine (object, affine);
1402 gl_xml_set_prop_double (node, "a0", affine[0]);
1403 gl_xml_set_prop_double (node, "a1", affine[1]);
1404 gl_xml_set_prop_double (node, "a2", affine[2]);
1405 gl_xml_set_prop_double (node, "a3", affine[3]);
1406 gl_xml_set_prop_double (node, "a4", affine[4]);
1407 gl_xml_set_prop_double (node, "a5", affine[5]);
1409 gl_debug (DEBUG_XML, "END");
1412 /*--------------------------------------------------------------------------*/
1413 /* PRIVATE. Add XML Label Merge Fields Node */
1414 /*--------------------------------------------------------------------------*/
1416 xml_create_merge_fields (xmlNodePtr root,
1420 xmlNodePtr node, child;
1425 gl_debug (DEBUG_XML, "START");
1427 merge = gl_label_get_merge (label);
1429 node = xmlNewChild (root, ns, "Merge", NULL);
1431 string = gl_merge_get_name (merge);
1432 xmlSetProp (node, "type", string);
1435 string = gl_merge_get_src (merge);
1436 xmlSetProp (node, "src", string);
1439 g_object_unref (G_OBJECT(merge));
1441 gl_debug (DEBUG_XML, "END");
1444 /*--------------------------------------------------------------------------*/
1445 /* PRIVATE. Add XML Label Data Node */
1446 /*--------------------------------------------------------------------------*/
1448 xml_create_data (xmlNodePtr root,
1453 GList *name_list, *p;
1454 GHashTable *pixbuf_cache;
1456 gl_debug (DEBUG_XML, "START");
1458 node = xmlNewChild (root, ns, "Data", NULL);
1460 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1461 name_list = gl_pixbuf_cache_get_name_list (pixbuf_cache);
1463 for (p = name_list; p != NULL; p=p->next) {
1464 xml_create_pixdata (node, ns, label, p->data);
1467 gl_pixbuf_cache_free_name_list (name_list);
1470 gl_debug (DEBUG_XML, "END");
1473 /*--------------------------------------------------------------------------*/
1474 /* PRIVATE. Add XML Label Data Pixbuf Node */
1475 /*--------------------------------------------------------------------------*/
1477 xml_create_pixdata (xmlNodePtr root,
1483 GHashTable *pixbuf_cache;
1485 GdkPixdata *pixdata;
1487 guint stream_length;
1490 gl_debug (DEBUG_XML, "START");
1492 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1494 pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, name);
1495 if ( pixbuf != NULL ) {
1497 pixdata = g_new0 (GdkPixdata, 1);
1498 gdk_pixdata_from_pixbuf (pixdata, pixbuf, FALSE);
1499 stream = gdk_pixdata_serialize (pixdata, &stream_length);
1500 base64 = gl_base64_encode (stream, stream_length);
1502 node = xmlNewChild (root, ns, "Pixdata", base64);
1503 xmlSetProp (node, "name", name);
1504 xmlSetProp (node, "encoding", "Base64");
1506 gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, name);
1514 gl_debug (DEBUG_XML, "END");
1517 /*--------------------------------------------------------------------------*/
1518 /* PRIVATE. Create top-level Span node. */
1519 /*--------------------------------------------------------------------------*/
1521 xml_create_toplevel_span (xmlNodePtr root,
1523 glLabelText *object_text)
1528 GnomeFontWeight font_weight;
1529 gboolean font_italic_flag;
1531 GtkJustification just;
1532 gdouble text_line_spacing;
1533 GList *lines, *p_line, *p_node;
1534 glTextNode *text_node;
1537 node = xmlNewChild (root, ns, "Span", NULL);
1539 /* All span attrs at top level. */
1540 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object_text));
1541 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object_text));
1542 text_line_spacing = gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object_text));
1543 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object_text));
1544 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object_text));
1545 color = gl_label_object_get_text_color (GL_LABEL_OBJECT(object_text));
1546 just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object_text));
1547 xmlSetProp (node, "font_family", font_family);
1548 gl_xml_set_prop_double (node, "font_size", font_size);
1549 xmlSetProp (node, "font_weight", gl_util_weight_to_string (font_weight));
1550 gl_xml_set_prop_boolean (node, "font_italic", font_italic_flag);
1551 gl_xml_set_prop_uint_hex (node, "color", color);
1552 gl_xml_set_prop_double (node, "line_spacing", text_line_spacing);
1554 /* Build children. */
1555 lines = gl_label_text_get_lines (GL_LABEL_TEXT(object_text));
1556 for (p_line = lines; p_line != NULL; p_line = p_line->next) {
1558 for (p_node = (GList *) p_line->data; p_node != NULL;
1559 p_node = p_node->next) {
1560 text_node = (glTextNode *) p_node->data;
1562 if (text_node->field_flag) {
1563 child = xmlNewChild (node, ns, "Field", NULL);
1564 xmlSetProp (child, "name", text_node->data);
1566 xmlNodeAddContent (node, text_node->data);
1571 if ( p_line->next ) {
1572 child = xmlNewChild (node, ns, "NL", NULL);
1577 gl_text_node_lines_free (&lines);
1578 g_free (font_family);