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 /* Try compatability mode 0.1 */
260 ns = xmlSearchNsByHref (doc, root, COMPAT01_NAME_SPACE);
262 g_warning (_("Importing from glabels 0.1 format"));
264 label = NULL; /* TODO */
266 /* Try compatability mode 0.4 */
267 ns = xmlSearchNsByHref (doc, root,
268 COMPAT04_NAME_SPACE);
270 g_warning (_("Importing from glabels 0.4 format"));
271 label = gl_xml_label_04_parse (root, status);
273 /* Try compatability mode 1.91 */
274 ns = xmlSearchNsByHref (doc, root,
275 COMPAT191_NAME_SPACE);
277 g_warning (_("Importing from glabels 1.91 format"));
278 label = gl_xml_label_191_parse (root, status);
280 g_warning (_("bad document, unknown glabels Namespace"));
281 *status = XML_LABEL_ERROR_OPEN_PARSE;
288 gl_debug (DEBUG_XML, "END");
293 /*--------------------------------------------------------------------------*/
294 /* PRIVATE. Parse xml root node and create label. */
295 /*--------------------------------------------------------------------------*/
297 xml_parse_label (xmlNodePtr root,
298 glXMLLabelStatus *status)
300 xmlNodePtr child_node;
302 glTemplate *template;
304 gl_debug (DEBUG_XML, "START");
306 *status = XML_LABEL_OK;
308 if (!xmlStrEqual (root->name, "Glabels-document")) {
309 g_warning (_("Bad root node = \"%s\""), root->name);
310 *status = XML_LABEL_ERROR_OPEN_PARSE;
314 label = GL_LABEL(gl_label_new ());
316 /* Pass 1, extract data nodes to pre-load cache. */
317 for (child_node = root->xmlChildrenNode; child_node != NULL; child_node = child_node->next) {
318 if (xmlStrEqual (child_node->name, "Data")) {
319 xml_parse_data (child_node, label);
323 /* Pass 2, now extract everything else. */
324 for (child_node = root->xmlChildrenNode;
326 child_node = child_node->next) {
328 if (xmlStrEqual (child_node->name, "Template")) {
329 template = gl_xml_template_parse_template_node (child_node);
331 g_object_unref (label);
332 *status = XML_LABEL_UNKNOWN_MEDIA;
335 gl_template_register (template);
336 gl_label_set_template (label, template);
337 gl_template_free (template);
338 } else if (xmlStrEqual (child_node->name, "Objects")) {
339 xml_parse_objects (child_node, label);
340 } else if (xmlStrEqual (child_node->name, "Merge")) {
341 xml_parse_merge_fields (child_node, label);
342 } else if (xmlStrEqual (child_node->name, "Data")) {
343 /* Handled in pass 1. */
345 if (!xmlNodeIsText (child_node)) {
346 g_warning (_("bad node in Document node = \"%s\""),
348 g_object_unref (label);
349 *status = XML_LABEL_ERROR_OPEN_PARSE;
355 gl_debug (DEBUG_XML, "END");
360 /*--------------------------------------------------------------------------*/
361 /* PRIVATE. Parse Objects node. */
362 /*--------------------------------------------------------------------------*/
364 xml_parse_objects (xmlNodePtr node,
367 gboolean rotate_flag;
370 gl_debug (DEBUG_XML, "START");
372 rotate_flag = gl_xml_get_prop_boolean (node, "rotate", FALSE);
373 gl_label_set_rotate_flag (label, rotate_flag);
375 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
377 if (xmlStrEqual (child->name, "Object-text")) {
378 xml_parse_object_text (child, label);
379 } else if (xmlStrEqual (child->name, "Object-box")) {
380 xml_parse_object_box (child, label);
381 } else if (xmlStrEqual (child->name, "Object-ellipse")) {
382 xml_parse_object_ellipse (child, label);
383 } else if (xmlStrEqual (child->name, "Object-line")) {
384 xml_parse_object_line (child, label);
385 } else if (xmlStrEqual (child->name, "Object-image")) {
386 xml_parse_object_image (child, label);
387 } else if (xmlStrEqual (child->name, "Object-barcode")) {
388 xml_parse_object_barcode (child, label);
390 if (!xmlNodeIsText (child)) {
391 g_warning (_("bad node = \"%s\""), child->name);
397 gl_debug (DEBUG_XML, "END");
400 /*--------------------------------------------------------------------------*/
401 /* PRIVATE. Parse XML Objects->Object-text Node */
402 /*--------------------------------------------------------------------------*/
404 xml_parse_object_text (xmlNodePtr node,
411 GtkJustification just;
415 gl_debug (DEBUG_XML, "START");
417 object = gl_label_text_new (label);
420 x = gl_xml_get_prop_length (node, "x", 0.0);
421 y = gl_xml_get_prop_length (node, "y", 0.0);
422 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
424 /* implied size attrs */
425 w = gl_xml_get_prop_length (node, "w", 0);
426 h = gl_xml_get_prop_length (node, "h", 0);
427 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
430 string = xmlGetProp (node, "justify");
431 just = gl_util_string_to_just (string);
433 gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), just);
436 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
437 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
438 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
439 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
440 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
441 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
442 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
444 /* Process children */
445 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
446 if (xmlStrEqual (child->name, "Span")) {
447 xml_parse_toplevel_span (child, GL_LABEL_OBJECT(object));
450 if (!xmlNodeIsText (child)) {
451 g_warning ("Unexpected Object-text child: \"%s\"",
457 gl_debug (DEBUG_XML, "END");
460 /*--------------------------------------------------------------------------*/
461 /* PRIVATE. Parse XML Objects->Object-box Node */
462 /*--------------------------------------------------------------------------*/
464 xml_parse_object_box (xmlNodePtr node,
471 guint line_color, fill_color;
474 gl_debug (DEBUG_XML, "START");
476 object = gl_label_box_new (label);
479 x = gl_xml_get_prop_length (node, "x", 0.0);
480 y = gl_xml_get_prop_length (node, "y", 0.0);
481 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
484 w = gl_xml_get_prop_length (node, "w", 0);
485 h = gl_xml_get_prop_length (node, "h", 0);
486 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
489 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
490 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
491 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
492 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
495 fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
496 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color);
499 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
500 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
501 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
502 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
503 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
504 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
505 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
507 gl_debug (DEBUG_XML, "END");
510 /*--------------------------------------------------------------------------*/
511 /* PRIVATE. Parse XML Objects->Object-ellipse Node */
512 /*--------------------------------------------------------------------------*/
514 xml_parse_object_ellipse (xmlNodePtr node,
521 guint line_color, fill_color;
524 gl_debug (DEBUG_XML, "START");
526 object = gl_label_ellipse_new (label);
529 x = gl_xml_get_prop_length (node, "x", 0.0);
530 y = gl_xml_get_prop_length (node, "y", 0.0);
531 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
534 w = gl_xml_get_prop_length (node, "w", 0);
535 h = gl_xml_get_prop_length (node, "h", 0);
536 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
539 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
540 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
541 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
542 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
545 fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
546 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color);
549 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
550 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
551 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
552 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
553 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
554 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
555 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
557 gl_debug (DEBUG_XML, "END");
560 /*--------------------------------------------------------------------------*/
561 /* PRIVATE. Parse XML Objects->Object-line Node */
562 /*--------------------------------------------------------------------------*/
564 xml_parse_object_line (xmlNodePtr node,
574 gl_debug (DEBUG_XML, "START");
576 object = gl_label_line_new (label);
579 x = gl_xml_get_prop_length (node, "x", 0.0);
580 y = gl_xml_get_prop_length (node, "y", 0.0);
581 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
584 dx = gl_xml_get_prop_length (node, "dx", 0);
585 dy = gl_xml_get_prop_length (node, "dy", 0);
586 gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy);
589 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
590 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
591 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
592 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
595 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
596 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
597 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
598 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
599 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
600 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
601 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
603 gl_debug (DEBUG_XML, "END");
606 /*--------------------------------------------------------------------------*/
607 /* PRIVATE. Parse XML Objects->Object-image Node */
608 /*--------------------------------------------------------------------------*/
610 xml_parse_object_image (xmlNodePtr node,
617 glTextNode *filename;
620 gl_debug (DEBUG_XML, "START");
622 object = gl_label_image_new (label);
625 x = gl_xml_get_prop_length (node, "x", 0.0);
626 y = gl_xml_get_prop_length (node, "y", 0.0);
627 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
630 w = gl_xml_get_prop_length (node, "w", 0);
631 h = gl_xml_get_prop_length (node, "h", 0);
632 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
634 /* src or field attr */
635 string = xmlGetProp (node, "src");
637 filename = g_new0 (glTextNode, 1);
638 filename->field_flag = FALSE;
639 filename->data = string;
640 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
641 gl_text_node_free (&filename);
643 string = xmlGetProp (node, "field");
645 filename = g_new0 (glTextNode, 1);
646 filename->field_flag = TRUE;
647 filename->data = string;
648 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
649 gl_text_node_free (&filename);
651 g_warning ("Missing Object-image src or field attr");
656 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
657 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
658 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
659 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
660 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
661 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
662 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
664 gl_debug (DEBUG_XML, "END");
667 /*--------------------------------------------------------------------------*/
668 /* PRIVATE. Parse XML Objects->Object-barcode Node */
669 /*--------------------------------------------------------------------------*/
671 xml_parse_object_barcode (xmlNodePtr node,
678 glTextNode *text_node;
681 gboolean checksum_flag;
685 gl_debug (DEBUG_XML, "START");
687 object = gl_label_barcode_new (label);
690 x = gl_xml_get_prop_length (node, "x", 0.0);
691 y = gl_xml_get_prop_length (node, "y", 0.0);
692 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
695 w = gl_xml_get_prop_length (node, "w", 0);
696 h = gl_xml_get_prop_length (node, "h", 0);
697 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
700 id = xmlGetProp (node, "style");
701 text_flag = gl_xml_get_prop_boolean (node, "text", FALSE);
702 checksum_flag = gl_xml_get_prop_boolean (node, "checksum", TRUE);
703 color = gl_xml_get_prop_uint (node, "color", 0);
704 gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
705 id, text_flag, checksum_flag);
706 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color);
709 /* data or field attr */
710 string = xmlGetProp (node, "data");
712 text_node = g_new0 (glTextNode, 1);
713 text_node->field_flag = FALSE;
714 text_node->data = string;
715 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
716 gl_text_node_free (&text_node);
718 string = xmlGetProp (node, "field");
720 text_node = g_new0 (glTextNode, 1);
721 text_node->field_flag = TRUE;
722 text_node->data = string;
723 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
724 gl_text_node_free (&text_node);
726 g_warning ("Missing Object-barcode data or field attr");
731 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
732 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
733 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
734 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
735 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
736 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
737 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
739 gl_debug (DEBUG_XML, "END");
742 /*--------------------------------------------------------------------------*/
743 /* PRIVATE. Parse XML merge fields tag. */
744 /*--------------------------------------------------------------------------*/
746 xml_parse_merge_fields (xmlNodePtr node,
753 gl_debug (DEBUG_XML, "START");
755 string = xmlGetProp (node, "type");
756 merge = gl_merge_new (string);
759 string = xmlGetProp (node, "src");
760 gl_merge_set_src (merge, string);
763 gl_label_set_merge (label, merge);
765 g_object_unref (G_OBJECT(merge));
767 gl_debug (DEBUG_XML, "END");
770 /*--------------------------------------------------------------------------*/
771 /* PRIVATE. Parse XML data tag. */
772 /*--------------------------------------------------------------------------*/
774 xml_parse_data (xmlNodePtr node,
779 gl_debug (DEBUG_XML, "START");
781 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
783 if (xmlStrEqual (child->name, "Pixdata")) {
784 xml_parse_pixdata (child, label);
786 if (!xmlNodeIsText (child)) {
787 g_warning (_("bad node in Data node = \"%s\""),
793 gl_debug (DEBUG_XML, "END");
796 /*--------------------------------------------------------------------------*/
797 /* PRIVATE. Parse XML pixbuf data tag. */
798 /*--------------------------------------------------------------------------*/
800 xml_parse_pixdata (xmlNodePtr node,
803 gchar *name, *base64;
809 GHashTable *pixbuf_cache;
811 gl_debug (DEBUG_XML, "START");
813 name = xmlGetProp (node, "name");
814 base64 = xmlNodeGetContent (node);
816 stream = gl_base64_decode (base64, &stream_length);
817 pixdata = g_new0 (GdkPixdata, 1);
818 ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
821 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
823 pixbuf_cache = gl_label_get_pixbuf_cache (label);
824 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
832 gl_debug (DEBUG_XML, "END");
835 /*--------------------------------------------------------------------------*/
836 /* PRIVATE. Parse top-level Span tag. */
837 /*--------------------------------------------------------------------------*/
839 xml_parse_toplevel_span (xmlNodePtr node,
840 glLabelObject *object)
844 GnomeFontWeight font_weight;
845 gboolean font_italic_flag;
847 gdouble text_line_spacing;
849 GList *lines, *text_nodes;
851 glTextNode *text_node;
853 gl_debug (DEBUG_XML, "START");
855 /* Font family attr */
856 font_family = xmlGetProp (node, "font_family");
857 gl_label_object_set_font_family (object, font_family);
858 g_free (font_family);
861 font_size = gl_xml_get_prop_double (node, "font_size", 0.0);
862 gl_label_object_set_font_size (object, font_size);
864 /* Font weight attr */
865 string = xmlGetProp (node, "font_weight");
866 font_weight = gl_util_string_to_weight (string);
868 gl_label_object_set_font_weight (object, font_weight);
870 /* Font italic flag attr */
871 font_italic_flag = gl_xml_get_prop_boolean (node, "font_italic", FALSE);
872 gl_label_object_set_font_italic_flag (object, font_italic_flag);
874 /* Text color attr */
875 color = gl_xml_get_prop_uint (node, "color", 0);
876 gl_label_object_set_text_color (object, color);
878 /* Text line spacing attr */
879 text_line_spacing = gl_xml_get_prop_double (node, "line_spacing", 1.0);
880 gl_label_object_set_text_line_spacing (object, text_line_spacing);
882 /* Now descend children, and build lines of text nodes */
885 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
887 if (xmlNodeIsText (child)) {
888 gchar *data = xmlNodeGetContent (child);
890 /* Hack: if the first char is LF, it's a xml formatting string */
891 if (data[0] != '\n') {
893 text_node = g_new0 (glTextNode, 1);
894 text_node->field_flag = FALSE;
895 text_node->data = data;
896 text_nodes = g_list_append (text_nodes, text_node);
901 } else if (xmlStrEqual (child->name, "Span")) {
903 g_warning ("Unexpected rich text (not supported, yet!)");
905 } else if (xmlStrEqual (child->name, "Field")) {
908 text_node = g_new0 (glTextNode, 1);
909 text_node->field_flag = TRUE;
910 text_node->data = xmlGetProp (child, "name");
911 text_nodes = g_list_append (text_nodes, text_node);
913 } else if (xmlStrEqual (child->name, "NL")) {
916 lines = g_list_append (lines, text_nodes);
920 g_warning ("Unexpected Span child: \"%s\"", child->name);
925 /* Store last line. */
926 lines = g_list_append (lines, text_nodes);
929 gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
930 gl_text_node_lines_free (&lines);
932 gl_debug (DEBUG_XML, "END");
935 /****************************************************************************/
936 /* Save label to xml label file. */
937 /****************************************************************************/
939 gl_xml_label_save (glLabel *label,
940 const gchar *utf8_filename,
941 glXMLLabelStatus *status)
947 gl_debug (DEBUG_XML, "START");
949 doc = xml_label_to_doc (label, status);
951 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
953 g_warning (_("Utf8 conversion error."));
955 xmlSetDocCompressMode (doc, 9);
956 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
960 g_warning (_("Problem saving xml file."));
961 *status = XML_LABEL_ERROR_SAVE_FILE;
965 gl_label_set_filename (label, utf8_filename);
966 gl_label_clear_modified (label);
972 gl_debug (DEBUG_XML, "END");
975 /****************************************************************************/
976 /* Save label to xml buffer. */
977 /****************************************************************************/
979 gl_xml_label_save_buffer (glLabel *label,
980 glXMLLabelStatus *status)
986 gl_debug (DEBUG_XML, "START");
988 doc = xml_label_to_doc (label, status);
990 xmlDocDumpMemory (doc, (xmlChar **)&buffer, &size);
993 gl_label_clear_modified (label);
995 gl_debug (DEBUG_XML, "END");
1000 /*--------------------------------------------------------------------------*/
1001 /* PRIVATE. Convert label to xml doc structure. */
1002 /*--------------------------------------------------------------------------*/
1004 xml_label_to_doc (glLabel *label,
1005 glXMLLabelStatus *status)
1009 glTemplate *template;
1012 gl_debug (DEBUG_XML, "START");
1014 LIBXML_TEST_VERSION;
1016 doc = xmlNewDoc ("1.0");
1017 doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Glabels-document", NULL);
1019 ns = xmlNewNs (doc->xmlRootNode, GL_XML_NAME_SPACE, NULL);
1020 xmlSetNs (doc->xmlRootNode, ns);
1022 template = gl_label_get_template (label);
1023 gl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
1025 xml_create_objects (doc->xmlRootNode, ns, label);
1027 merge = gl_label_get_merge (label);
1028 gl_debug (DEBUG_XML, "merge=%p", merge);
1029 if (merge != NULL) {
1030 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1031 g_object_unref (G_OBJECT(merge));
1034 xml_create_data (doc->xmlRootNode, ns, label);
1036 gl_debug (DEBUG_XML, "END");
1038 *status = XML_LABEL_OK;
1042 /*--------------------------------------------------------------------------*/
1043 /* PRIVATE. Add XML Objects Node */
1044 /*--------------------------------------------------------------------------*/
1046 xml_create_objects (xmlNodePtr root,
1051 gboolean rotate_flag;
1053 glLabelObject *object;
1055 gl_debug (DEBUG_XML, "START");
1057 rotate_flag = gl_label_get_rotate_flag (label);
1059 node = xmlNewChild (root, ns, "Objects", NULL);
1060 xmlSetProp (node, "id", "0");
1061 gl_xml_set_prop_boolean (node, "rotate", rotate_flag);
1063 for (p = label->objects; p != NULL; p = p->next) {
1065 object = GL_LABEL_OBJECT(p->data);
1067 if ( GL_IS_LABEL_TEXT(object) ) {
1068 xml_create_object_text (node, ns, object);
1069 } else if ( GL_IS_LABEL_BOX(object) ) {
1070 xml_create_object_box (node, ns, object);
1071 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1072 xml_create_object_ellipse (node, ns, object);
1073 } else if ( GL_IS_LABEL_LINE(object) ) {
1074 xml_create_object_line (node, ns, object);
1075 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1076 xml_create_object_image (node, ns, object);
1077 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1078 xml_create_object_barcode (node, ns, object);
1080 g_warning ("Unknown label object");
1085 gl_debug (DEBUG_XML, "END");
1088 /*--------------------------------------------------------------------------*/
1089 /* PRIVATE. Add XML Objects->Object-text Node */
1090 /*--------------------------------------------------------------------------*/
1092 xml_create_object_text (xmlNodePtr root,
1094 glLabelObject *object)
1099 GtkJustification just;
1102 gl_debug (DEBUG_XML, "START");
1104 node = xmlNewChild (root, ns, "Object-text", NULL);
1106 /* position attrs */
1107 gl_label_object_get_position (object, &x, &y);
1108 gl_xml_set_prop_length (node, "x", x);
1109 gl_xml_set_prop_length (node, "y", y);
1112 gl_label_text_get_box ( GL_LABEL_TEXT(object), &w, &h);
1113 gl_xml_set_prop_length (node, "w", w);
1114 gl_xml_set_prop_length (node, "h", h);
1117 just = gl_label_object_get_text_alignment (object);
1118 xmlSetProp (node, "justify", gl_util_just_to_string (just));
1121 gl_label_object_get_affine (object, affine);
1122 gl_xml_set_prop_double (node, "a0", affine[0]);
1123 gl_xml_set_prop_double (node, "a1", affine[1]);
1124 gl_xml_set_prop_double (node, "a2", affine[2]);
1125 gl_xml_set_prop_double (node, "a3", affine[3]);
1126 gl_xml_set_prop_double (node, "a4", affine[4]);
1127 gl_xml_set_prop_double (node, "a5", affine[5]);
1130 xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1132 gl_debug (DEBUG_XML, "END");
1135 /*--------------------------------------------------------------------------*/
1136 /* PRIVATE. Add XML Objects->Object-box Node */
1137 /*--------------------------------------------------------------------------*/
1139 xml_create_object_box (xmlNodePtr root,
1141 glLabelObject *object)
1147 guint line_color, fill_color;
1150 gl_debug (DEBUG_XML, "START");
1152 node = xmlNewChild (root, ns, "Object-box", NULL);
1154 /* position attrs */
1155 gl_label_object_get_position (object, &x, &y);
1156 gl_xml_set_prop_length (node, "x", x);
1157 gl_xml_set_prop_length (node, "y", y);
1160 gl_label_object_get_size (object, &w, &h);
1161 gl_xml_set_prop_length (node, "w", w);
1162 gl_xml_set_prop_length (node, "h", h);
1165 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1166 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1167 gl_xml_set_prop_length (node, "line_width", line_width);
1168 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1171 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1172 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1175 gl_label_object_get_affine (object, affine);
1176 gl_xml_set_prop_double (node, "a0", affine[0]);
1177 gl_xml_set_prop_double (node, "a1", affine[1]);
1178 gl_xml_set_prop_double (node, "a2", affine[2]);
1179 gl_xml_set_prop_double (node, "a3", affine[3]);
1180 gl_xml_set_prop_double (node, "a4", affine[4]);
1181 gl_xml_set_prop_double (node, "a5", affine[5]);
1183 gl_debug (DEBUG_XML, "END");
1186 /*--------------------------------------------------------------------------*/
1187 /* PRIVATE. Add XML Objects->Object-ellipse Node */
1188 /*--------------------------------------------------------------------------*/
1190 xml_create_object_ellipse (xmlNodePtr root,
1192 glLabelObject *object)
1198 guint line_color, fill_color;
1201 gl_debug (DEBUG_XML, "START");
1203 node = xmlNewChild (root, ns, "Object-ellipse", NULL);
1205 /* position attrs */
1206 gl_label_object_get_position (object, &x, &y);
1207 gl_xml_set_prop_length (node, "x", x);
1208 gl_xml_set_prop_length (node, "y", y);
1211 gl_label_object_get_size (object, &w, &h);
1212 gl_xml_set_prop_length (node, "w", w);
1213 gl_xml_set_prop_length (node, "h", h);
1216 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1217 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1218 gl_xml_set_prop_length (node, "line_width", line_width);
1219 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1222 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1223 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1226 gl_label_object_get_affine (object, affine);
1227 gl_xml_set_prop_double (node, "a0", affine[0]);
1228 gl_xml_set_prop_double (node, "a1", affine[1]);
1229 gl_xml_set_prop_double (node, "a2", affine[2]);
1230 gl_xml_set_prop_double (node, "a3", affine[3]);
1231 gl_xml_set_prop_double (node, "a4", affine[4]);
1232 gl_xml_set_prop_double (node, "a5", affine[5]);
1234 gl_debug (DEBUG_XML, "END");
1237 /*--------------------------------------------------------------------------*/
1238 /* PRIVATE. Add XML Objects->Object-line Node */
1239 /*--------------------------------------------------------------------------*/
1241 xml_create_object_line (xmlNodePtr root,
1243 glLabelObject *object)
1252 gl_debug (DEBUG_XML, "START");
1254 node = xmlNewChild (root, ns, "Object-line", NULL);
1256 /* position attrs */
1257 gl_label_object_get_position (object, &x, &y);
1258 gl_xml_set_prop_length (node, "x", x);
1259 gl_xml_set_prop_length (node, "y", y);
1262 gl_label_object_get_size (object, &dx, &dy);
1263 gl_xml_set_prop_length (node, "dx", dx);
1264 gl_xml_set_prop_length (node, "dy", dy);
1267 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1268 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1269 gl_xml_set_prop_length (node, "line_width", line_width);
1270 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1273 gl_label_object_get_affine (object, affine);
1274 gl_xml_set_prop_double (node, "a0", affine[0]);
1275 gl_xml_set_prop_double (node, "a1", affine[1]);
1276 gl_xml_set_prop_double (node, "a2", affine[2]);
1277 gl_xml_set_prop_double (node, "a3", affine[3]);
1278 gl_xml_set_prop_double (node, "a4", affine[4]);
1279 gl_xml_set_prop_double (node, "a5", affine[5]);
1281 gl_debug (DEBUG_XML, "END");
1284 /*--------------------------------------------------------------------------*/
1285 /* PRIVATE. Add XML Objects->Object-image Node */
1286 /*--------------------------------------------------------------------------*/
1288 xml_create_object_image (xmlNodePtr root,
1290 glLabelObject *object)
1295 glTextNode *filename;
1298 gl_debug (DEBUG_XML, "START");
1300 node = xmlNewChild (root, ns, "Object-image", NULL);
1302 /* position attrs */
1303 gl_label_object_get_position (object, &x, &y);
1304 gl_xml_set_prop_length (node, "x", x);
1305 gl_xml_set_prop_length (node, "y", y);
1308 gl_label_object_get_size (object, &w, &h);
1309 gl_xml_set_prop_length (node, "w", w);
1310 gl_xml_set_prop_length (node, "h", h);
1312 /* src OR field attr */
1313 filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1314 if (filename->field_flag) {
1315 xmlSetProp (node, "field", filename->data);
1317 xmlSetProp (node, "src", filename->data);
1319 gl_text_node_free (&filename);
1322 gl_label_object_get_affine (object, affine);
1323 gl_xml_set_prop_double (node, "a0", affine[0]);
1324 gl_xml_set_prop_double (node, "a1", affine[1]);
1325 gl_xml_set_prop_double (node, "a2", affine[2]);
1326 gl_xml_set_prop_double (node, "a3", affine[3]);
1327 gl_xml_set_prop_double (node, "a4", affine[4]);
1328 gl_xml_set_prop_double (node, "a5", affine[5]);
1330 gl_debug (DEBUG_XML, "END");
1333 /*--------------------------------------------------------------------------*/
1334 /* PRIVATE. Add XML Objects->Object-barcode Node */
1335 /*--------------------------------------------------------------------------*/
1337 xml_create_object_barcode (xmlNodePtr root,
1339 glLabelObject *object)
1344 glTextNode *text_node;
1347 gboolean checksum_flag;
1351 gl_debug (DEBUG_XML, "START");
1353 node = xmlNewChild (root, ns, "Object-barcode", NULL);
1355 /* position attrs */
1356 gl_label_object_get_position (object, &x, &y);
1357 gl_xml_set_prop_length (node, "x", x);
1358 gl_xml_set_prop_length (node, "y", y);
1361 gl_label_object_get_size (object, &w, &h);
1362 gl_xml_set_prop_length (node, "w", w);
1363 gl_xml_set_prop_length (node, "h", h);
1365 /* Barcode properties attrs */
1366 gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1367 &id, &text_flag, &checksum_flag);
1368 color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1369 xmlSetProp (node, "style", id);
1370 gl_xml_set_prop_boolean (node, "text", text_flag);
1371 gl_xml_set_prop_boolean (node, "checksum", checksum_flag);
1372 gl_xml_set_prop_uint_hex (node, "color", color);
1375 /* data OR field attr */
1376 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1377 if (text_node->field_flag) {
1378 xmlSetProp (node, "field", text_node->data);
1380 xmlSetProp (node, "data", text_node->data);
1382 gl_text_node_free (&text_node);
1385 gl_label_object_get_affine (object, affine);
1386 gl_xml_set_prop_double (node, "a0", affine[0]);
1387 gl_xml_set_prop_double (node, "a1", affine[1]);
1388 gl_xml_set_prop_double (node, "a2", affine[2]);
1389 gl_xml_set_prop_double (node, "a3", affine[3]);
1390 gl_xml_set_prop_double (node, "a4", affine[4]);
1391 gl_xml_set_prop_double (node, "a5", affine[5]);
1393 gl_debug (DEBUG_XML, "END");
1396 /*--------------------------------------------------------------------------*/
1397 /* PRIVATE. Add XML Label Merge Fields Node */
1398 /*--------------------------------------------------------------------------*/
1400 xml_create_merge_fields (xmlNodePtr root,
1404 xmlNodePtr node, child;
1409 gl_debug (DEBUG_XML, "START");
1411 merge = gl_label_get_merge (label);
1413 node = xmlNewChild (root, ns, "Merge", NULL);
1415 string = gl_merge_get_name (merge);
1416 xmlSetProp (node, "type", string);
1419 string = gl_merge_get_src (merge);
1420 xmlSetProp (node, "src", string);
1423 g_object_unref (G_OBJECT(merge));
1425 gl_debug (DEBUG_XML, "END");
1428 /*--------------------------------------------------------------------------*/
1429 /* PRIVATE. Add XML Label Data Node */
1430 /*--------------------------------------------------------------------------*/
1432 xml_create_data (xmlNodePtr root,
1437 GList *name_list, *p;
1438 GHashTable *pixbuf_cache;
1440 gl_debug (DEBUG_XML, "START");
1442 node = xmlNewChild (root, ns, "Data", NULL);
1444 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1445 name_list = gl_pixbuf_cache_get_name_list (pixbuf_cache);
1447 for (p = name_list; p != NULL; p=p->next) {
1448 xml_create_pixdata (node, ns, label, p->data);
1451 gl_pixbuf_cache_free_name_list (name_list);
1454 gl_debug (DEBUG_XML, "END");
1457 /*--------------------------------------------------------------------------*/
1458 /* PRIVATE. Add XML Label Data Pixbuf Node */
1459 /*--------------------------------------------------------------------------*/
1461 xml_create_pixdata (xmlNodePtr root,
1467 GHashTable *pixbuf_cache;
1469 GdkPixdata *pixdata;
1471 guint stream_length;
1474 gl_debug (DEBUG_XML, "START");
1476 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1478 pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, name);
1479 if ( pixbuf != NULL ) {
1481 pixdata = g_new0 (GdkPixdata, 1);
1482 gdk_pixdata_from_pixbuf (pixdata, pixbuf, FALSE);
1483 stream = gdk_pixdata_serialize (pixdata, &stream_length);
1484 base64 = gl_base64_encode (stream, stream_length);
1486 node = xmlNewChild (root, ns, "Pixdata", base64);
1487 xmlSetProp (node, "name", name);
1488 xmlSetProp (node, "encoding", "Base64");
1490 gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, name);
1498 gl_debug (DEBUG_XML, "END");
1501 /*--------------------------------------------------------------------------*/
1502 /* PRIVATE. Create top-level Span node. */
1503 /*--------------------------------------------------------------------------*/
1505 xml_create_toplevel_span (xmlNodePtr root,
1507 glLabelText *object_text)
1512 GnomeFontWeight font_weight;
1513 gboolean font_italic_flag;
1515 GtkJustification just;
1516 gdouble text_line_spacing;
1517 GList *lines, *p_line, *p_node;
1518 glTextNode *text_node;
1521 node = xmlNewChild (root, ns, "Span", NULL);
1523 /* All span attrs at top level. */
1524 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object_text));
1525 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object_text));
1526 text_line_spacing = gl_label_object_get_text_line_spacing (GL_LABEL_OBJECT(object_text));
1527 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object_text));
1528 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object_text));
1529 color = gl_label_object_get_text_color (GL_LABEL_OBJECT(object_text));
1530 just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object_text));
1531 xmlSetProp (node, "font_family", font_family);
1532 gl_xml_set_prop_double (node, "font_size", font_size);
1533 xmlSetProp (node, "font_weight", gl_util_weight_to_string (font_weight));
1534 gl_xml_set_prop_boolean (node, "font_italic", font_italic_flag);
1535 gl_xml_set_prop_uint_hex (node, "color", color);
1536 gl_xml_set_prop_double (node, "line_spacing", text_line_spacing);
1538 /* Build children. */
1539 lines = gl_label_text_get_lines (GL_LABEL_TEXT(object_text));
1540 for (p_line = lines; p_line != NULL; p_line = p_line->next) {
1542 for (p_node = (GList *) p_line->data; p_node != NULL;
1543 p_node = p_node->next) {
1544 text_node = (glTextNode *) p_node->data;
1546 if (text_node->field_flag) {
1547 child = xmlNewChild (node, ns, "Field", NULL);
1548 xmlSetProp (child, "name", text_node->data);
1550 xmlNodeAddContent (node, text_node->data);
1555 if ( p_line->next ) {
1556 child = xmlNewChild (node, ns, "NL", NULL);
1561 gl_text_node_lines_free (&lines);
1562 g_free (font_family);