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;
679 glBarcodeStyle style;
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 string = xmlGetProp (node, "style");
701 style = gl_barcode_text_to_style (string);
703 text_flag = gl_xml_get_prop_boolean (node, "text", FALSE);
704 checksum_flag = gl_xml_get_prop_boolean (node, "checksum", TRUE);
705 color = gl_xml_get_prop_uint (node, "color", 0);
706 gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
707 style, text_flag, checksum_flag);
708 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color);
710 /* data or field attr */
711 string = xmlGetProp (node, "data");
713 text_node = g_new0 (glTextNode, 1);
714 text_node->field_flag = FALSE;
715 text_node->data = string;
716 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
717 gl_text_node_free (&text_node);
719 string = xmlGetProp (node, "field");
721 text_node = g_new0 (glTextNode, 1);
722 text_node->field_flag = TRUE;
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 g_warning ("Missing Object-barcode data or field attr");
732 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
733 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
734 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
735 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
736 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
737 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
738 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
740 gl_debug (DEBUG_XML, "END");
743 /*--------------------------------------------------------------------------*/
744 /* PRIVATE. Parse XML merge fields tag. */
745 /*--------------------------------------------------------------------------*/
747 xml_parse_merge_fields (xmlNodePtr node,
754 gl_debug (DEBUG_XML, "START");
756 string = xmlGetProp (node, "type");
757 merge = gl_merge_new (string);
760 string = xmlGetProp (node, "src");
761 gl_merge_set_src (merge, string);
764 gl_label_set_merge (label, merge);
766 g_object_unref (G_OBJECT(merge));
768 gl_debug (DEBUG_XML, "END");
771 /*--------------------------------------------------------------------------*/
772 /* PRIVATE. Parse XML data tag. */
773 /*--------------------------------------------------------------------------*/
775 xml_parse_data (xmlNodePtr node,
780 gl_debug (DEBUG_XML, "START");
782 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
784 if (xmlStrEqual (child->name, "Pixdata")) {
785 xml_parse_pixdata (child, label);
787 if (!xmlNodeIsText (child)) {
788 g_warning (_("bad node in Data node = \"%s\""),
794 gl_debug (DEBUG_XML, "END");
797 /*--------------------------------------------------------------------------*/
798 /* PRIVATE. Parse XML pixbuf data tag. */
799 /*--------------------------------------------------------------------------*/
801 xml_parse_pixdata (xmlNodePtr node,
804 gchar *name, *base64;
810 GHashTable *pixbuf_cache;
812 gl_debug (DEBUG_XML, "START");
814 name = xmlGetProp (node, "name");
815 base64 = xmlNodeGetContent (node);
817 stream = gl_base64_decode (base64, &stream_length);
818 pixdata = g_new0 (GdkPixdata, 1);
819 ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
822 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
824 pixbuf_cache = gl_label_get_pixbuf_cache (label);
825 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
833 gl_debug (DEBUG_XML, "END");
836 /*--------------------------------------------------------------------------*/
837 /* PRIVATE. Parse top-level Span tag. */
838 /*--------------------------------------------------------------------------*/
840 xml_parse_toplevel_span (xmlNodePtr node,
841 glLabelObject *object)
845 GnomeFontWeight font_weight;
846 gboolean font_italic_flag;
848 gdouble text_line_spacing;
850 GList *lines, *text_nodes;
852 glTextNode *text_node;
854 gl_debug (DEBUG_XML, "START");
856 /* Font family attr */
857 font_family = xmlGetProp (node, "font_family");
858 gl_label_object_set_font_family (object, font_family);
859 g_free (font_family);
862 font_size = gl_xml_get_prop_double (node, "font_size", 0.0);
863 gl_label_object_set_font_size (object, font_size);
865 /* Font weight attr */
866 string = xmlGetProp (node, "font_weight");
867 font_weight = gl_util_string_to_weight (string);
869 gl_label_object_set_font_weight (object, font_weight);
871 /* Font italic flag attr */
872 font_italic_flag = gl_xml_get_prop_boolean (node, "font_italic", FALSE);
873 gl_label_object_set_font_italic_flag (object, font_italic_flag);
875 /* Text color attr */
876 color = gl_xml_get_prop_uint (node, "color", 0);
877 gl_label_object_set_text_color (object, color);
879 /* Text line spacing attr */
880 text_line_spacing = gl_xml_get_prop_double (node, "line_spacing", 1.0);
881 gl_label_object_set_text_line_spacing (object, text_line_spacing);
883 /* Now descend children, and build lines of text nodes */
886 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
888 if (xmlNodeIsText (child)) {
889 gchar *data = xmlNodeGetContent (child);
891 /* Hack: if the first char is LF, it's a xml formatting string */
892 if (data[0] != '\n') {
894 text_node = g_new0 (glTextNode, 1);
895 text_node->field_flag = FALSE;
896 text_node->data = data;
897 text_nodes = g_list_append (text_nodes, text_node);
902 } else if (xmlStrEqual (child->name, "Span")) {
904 g_warning ("Unexpected rich text (not supported, yet!)");
906 } else if (xmlStrEqual (child->name, "Field")) {
909 text_node = g_new0 (glTextNode, 1);
910 text_node->field_flag = TRUE;
911 text_node->data = xmlGetProp (child, "name");
912 text_nodes = g_list_append (text_nodes, text_node);
914 } else if (xmlStrEqual (child->name, "NL")) {
917 lines = g_list_append (lines, text_nodes);
921 g_warning ("Unexpected Span child: \"%s\"", child->name);
926 /* Store last line. */
927 lines = g_list_append (lines, text_nodes);
930 gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
931 gl_text_node_lines_free (&lines);
933 gl_debug (DEBUG_XML, "END");
936 /****************************************************************************/
937 /* Save label to xml label file. */
938 /****************************************************************************/
940 gl_xml_label_save (glLabel *label,
941 const gchar *utf8_filename,
942 glXMLLabelStatus *status)
948 gl_debug (DEBUG_XML, "START");
950 doc = xml_label_to_doc (label, status);
952 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
954 g_warning (_("Utf8 conversion error."));
956 xmlSetDocCompressMode (doc, 9);
957 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
961 g_warning (_("Problem saving xml file."));
962 *status = XML_LABEL_ERROR_SAVE_FILE;
966 gl_label_set_filename (label, utf8_filename);
967 gl_label_clear_modified (label);
973 gl_debug (DEBUG_XML, "END");
976 /****************************************************************************/
977 /* Save label to xml buffer. */
978 /****************************************************************************/
980 gl_xml_label_save_buffer (glLabel *label,
981 glXMLLabelStatus *status)
987 gl_debug (DEBUG_XML, "START");
989 doc = xml_label_to_doc (label, status);
991 xmlDocDumpMemory (doc, (xmlChar **)&buffer, &size);
994 gl_label_clear_modified (label);
996 gl_debug (DEBUG_XML, "END");
1001 /*--------------------------------------------------------------------------*/
1002 /* PRIVATE. Convert label to xml doc structure. */
1003 /*--------------------------------------------------------------------------*/
1005 xml_label_to_doc (glLabel *label,
1006 glXMLLabelStatus *status)
1010 glTemplate *template;
1013 gl_debug (DEBUG_XML, "START");
1015 LIBXML_TEST_VERSION;
1017 doc = xmlNewDoc ("1.0");
1018 doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Glabels-document", NULL);
1020 ns = xmlNewNs (doc->xmlRootNode, GL_XML_NAME_SPACE, NULL);
1021 xmlSetNs (doc->xmlRootNode, ns);
1023 template = gl_label_get_template (label);
1024 gl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
1026 xml_create_objects (doc->xmlRootNode, ns, label);
1028 merge = gl_label_get_merge (label);
1029 gl_debug (DEBUG_XML, "merge=%p", merge);
1030 if (merge != NULL) {
1031 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1032 g_object_unref (G_OBJECT(merge));
1035 xml_create_data (doc->xmlRootNode, ns, label);
1037 gl_debug (DEBUG_XML, "END");
1039 *status = XML_LABEL_OK;
1043 /*--------------------------------------------------------------------------*/
1044 /* PRIVATE. Add XML Objects Node */
1045 /*--------------------------------------------------------------------------*/
1047 xml_create_objects (xmlNodePtr root,
1052 gboolean rotate_flag;
1054 glLabelObject *object;
1056 gl_debug (DEBUG_XML, "START");
1058 rotate_flag = gl_label_get_rotate_flag (label);
1060 node = xmlNewChild (root, ns, "Objects", NULL);
1061 xmlSetProp (node, "id", "0");
1062 gl_xml_set_prop_boolean (node, "rotate", rotate_flag);
1064 for (p = label->objects; p != NULL; p = p->next) {
1066 object = GL_LABEL_OBJECT(p->data);
1068 if ( GL_IS_LABEL_TEXT(object) ) {
1069 xml_create_object_text (node, ns, object);
1070 } else if ( GL_IS_LABEL_BOX(object) ) {
1071 xml_create_object_box (node, ns, object);
1072 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1073 xml_create_object_ellipse (node, ns, object);
1074 } else if ( GL_IS_LABEL_LINE(object) ) {
1075 xml_create_object_line (node, ns, object);
1076 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1077 xml_create_object_image (node, ns, object);
1078 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1079 xml_create_object_barcode (node, ns, object);
1081 g_warning ("Unknown label object");
1086 gl_debug (DEBUG_XML, "END");
1089 /*--------------------------------------------------------------------------*/
1090 /* PRIVATE. Add XML Objects->Object-text Node */
1091 /*--------------------------------------------------------------------------*/
1093 xml_create_object_text (xmlNodePtr root,
1095 glLabelObject *object)
1100 GtkJustification just;
1103 gl_debug (DEBUG_XML, "START");
1105 node = xmlNewChild (root, ns, "Object-text", NULL);
1107 /* position attrs */
1108 gl_label_object_get_position (object, &x, &y);
1109 gl_xml_set_prop_length (node, "x", x);
1110 gl_xml_set_prop_length (node, "y", y);
1113 gl_label_text_get_box ( GL_LABEL_TEXT(object), &w, &h);
1114 gl_xml_set_prop_length (node, "w", w);
1115 gl_xml_set_prop_length (node, "h", h);
1118 just = gl_label_object_get_text_alignment (object);
1119 xmlSetProp (node, "justify", gl_util_just_to_string (just));
1122 gl_label_object_get_affine (object, affine);
1123 gl_xml_set_prop_double (node, "a0", affine[0]);
1124 gl_xml_set_prop_double (node, "a1", affine[1]);
1125 gl_xml_set_prop_double (node, "a2", affine[2]);
1126 gl_xml_set_prop_double (node, "a3", affine[3]);
1127 gl_xml_set_prop_double (node, "a4", affine[4]);
1128 gl_xml_set_prop_double (node, "a5", affine[5]);
1131 xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1133 gl_debug (DEBUG_XML, "END");
1136 /*--------------------------------------------------------------------------*/
1137 /* PRIVATE. Add XML Objects->Object-box Node */
1138 /*--------------------------------------------------------------------------*/
1140 xml_create_object_box (xmlNodePtr root,
1142 glLabelObject *object)
1148 guint line_color, fill_color;
1151 gl_debug (DEBUG_XML, "START");
1153 node = xmlNewChild (root, ns, "Object-box", NULL);
1155 /* position attrs */
1156 gl_label_object_get_position (object, &x, &y);
1157 gl_xml_set_prop_length (node, "x", x);
1158 gl_xml_set_prop_length (node, "y", y);
1161 gl_label_object_get_size (object, &w, &h);
1162 gl_xml_set_prop_length (node, "w", w);
1163 gl_xml_set_prop_length (node, "h", h);
1166 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1167 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1168 gl_xml_set_prop_length (node, "line_width", line_width);
1169 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1172 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1173 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1176 gl_label_object_get_affine (object, affine);
1177 gl_xml_set_prop_double (node, "a0", affine[0]);
1178 gl_xml_set_prop_double (node, "a1", affine[1]);
1179 gl_xml_set_prop_double (node, "a2", affine[2]);
1180 gl_xml_set_prop_double (node, "a3", affine[3]);
1181 gl_xml_set_prop_double (node, "a4", affine[4]);
1182 gl_xml_set_prop_double (node, "a5", affine[5]);
1184 gl_debug (DEBUG_XML, "END");
1187 /*--------------------------------------------------------------------------*/
1188 /* PRIVATE. Add XML Objects->Object-ellipse Node */
1189 /*--------------------------------------------------------------------------*/
1191 xml_create_object_ellipse (xmlNodePtr root,
1193 glLabelObject *object)
1199 guint line_color, fill_color;
1202 gl_debug (DEBUG_XML, "START");
1204 node = xmlNewChild (root, ns, "Object-ellipse", NULL);
1206 /* position attrs */
1207 gl_label_object_get_position (object, &x, &y);
1208 gl_xml_set_prop_length (node, "x", x);
1209 gl_xml_set_prop_length (node, "y", y);
1212 gl_label_object_get_size (object, &w, &h);
1213 gl_xml_set_prop_length (node, "w", w);
1214 gl_xml_set_prop_length (node, "h", h);
1217 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1218 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1219 gl_xml_set_prop_length (node, "line_width", line_width);
1220 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1223 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1224 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1227 gl_label_object_get_affine (object, affine);
1228 gl_xml_set_prop_double (node, "a0", affine[0]);
1229 gl_xml_set_prop_double (node, "a1", affine[1]);
1230 gl_xml_set_prop_double (node, "a2", affine[2]);
1231 gl_xml_set_prop_double (node, "a3", affine[3]);
1232 gl_xml_set_prop_double (node, "a4", affine[4]);
1233 gl_xml_set_prop_double (node, "a5", affine[5]);
1235 gl_debug (DEBUG_XML, "END");
1238 /*--------------------------------------------------------------------------*/
1239 /* PRIVATE. Add XML Objects->Object-line Node */
1240 /*--------------------------------------------------------------------------*/
1242 xml_create_object_line (xmlNodePtr root,
1244 glLabelObject *object)
1253 gl_debug (DEBUG_XML, "START");
1255 node = xmlNewChild (root, ns, "Object-line", NULL);
1257 /* position attrs */
1258 gl_label_object_get_position (object, &x, &y);
1259 gl_xml_set_prop_length (node, "x", x);
1260 gl_xml_set_prop_length (node, "y", y);
1263 gl_label_object_get_size (object, &dx, &dy);
1264 gl_xml_set_prop_length (node, "dx", dx);
1265 gl_xml_set_prop_length (node, "dy", dy);
1268 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1269 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1270 gl_xml_set_prop_length (node, "line_width", line_width);
1271 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1274 gl_label_object_get_affine (object, affine);
1275 gl_xml_set_prop_double (node, "a0", affine[0]);
1276 gl_xml_set_prop_double (node, "a1", affine[1]);
1277 gl_xml_set_prop_double (node, "a2", affine[2]);
1278 gl_xml_set_prop_double (node, "a3", affine[3]);
1279 gl_xml_set_prop_double (node, "a4", affine[4]);
1280 gl_xml_set_prop_double (node, "a5", affine[5]);
1282 gl_debug (DEBUG_XML, "END");
1285 /*--------------------------------------------------------------------------*/
1286 /* PRIVATE. Add XML Objects->Object-image Node */
1287 /*--------------------------------------------------------------------------*/
1289 xml_create_object_image (xmlNodePtr root,
1291 glLabelObject *object)
1296 glTextNode *filename;
1299 gl_debug (DEBUG_XML, "START");
1301 node = xmlNewChild (root, ns, "Object-image", NULL);
1303 /* position attrs */
1304 gl_label_object_get_position (object, &x, &y);
1305 gl_xml_set_prop_length (node, "x", x);
1306 gl_xml_set_prop_length (node, "y", y);
1309 gl_label_object_get_size (object, &w, &h);
1310 gl_xml_set_prop_length (node, "w", w);
1311 gl_xml_set_prop_length (node, "h", h);
1313 /* src OR field attr */
1314 filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1315 if (filename->field_flag) {
1316 xmlSetProp (node, "field", filename->data);
1318 xmlSetProp (node, "src", filename->data);
1320 gl_text_node_free (&filename);
1323 gl_label_object_get_affine (object, affine);
1324 gl_xml_set_prop_double (node, "a0", affine[0]);
1325 gl_xml_set_prop_double (node, "a1", affine[1]);
1326 gl_xml_set_prop_double (node, "a2", affine[2]);
1327 gl_xml_set_prop_double (node, "a3", affine[3]);
1328 gl_xml_set_prop_double (node, "a4", affine[4]);
1329 gl_xml_set_prop_double (node, "a5", affine[5]);
1331 gl_debug (DEBUG_XML, "END");
1334 /*--------------------------------------------------------------------------*/
1335 /* PRIVATE. Add XML Objects->Object-barcode Node */
1336 /*--------------------------------------------------------------------------*/
1338 xml_create_object_barcode (xmlNodePtr root,
1340 glLabelObject *object)
1345 glTextNode *text_node;
1346 glBarcodeStyle style;
1348 gboolean checksum_flag;
1352 gl_debug (DEBUG_XML, "START");
1354 node = xmlNewChild (root, ns, "Object-barcode", NULL);
1356 /* position attrs */
1357 gl_label_object_get_position (object, &x, &y);
1358 gl_xml_set_prop_length (node, "x", x);
1359 gl_xml_set_prop_length (node, "y", y);
1362 gl_label_object_get_size (object, &w, &h);
1363 gl_xml_set_prop_length (node, "w", w);
1364 gl_xml_set_prop_length (node, "h", h);
1366 /* Barcode properties attrs */
1367 gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1368 &style, &text_flag, &checksum_flag);
1369 color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1370 xmlSetProp (node, "style", gl_barcode_style_to_text (style));
1371 gl_xml_set_prop_boolean (node, "text", text_flag);
1372 gl_xml_set_prop_boolean (node, "checksum", checksum_flag);
1373 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);