2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * label.c: GLabels xml label module
6 * Copyright (C) 2001-2002 Jim Evins <evins@snaught.com>.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <libxml/tree.h>
28 #include <libxml/parser.h>
29 #include <gdk-pixbuf/gdk-pixdata.h>
32 #include "label-object.h"
33 #include "label-text.h"
34 #include "label-box.h"
35 #include "label-line.h"
36 #include "label-ellipse.h"
37 #include "label-image.h"
38 #include "label-barcode.h"
41 #include "xml-label.h"
42 #include "xml-label-04.h"
43 #include "xml-label-191.h"
44 #include "xml-template.h"
50 /*========================================================*/
51 /* Private macros and constants. */
52 /*========================================================*/
53 #define NAME_SPACE "http://snaught.com/glabels/2.0/"
54 #define COMPAT01_NAME_SPACE "http://snaught.com/glabels/0.1/"
55 #define COMPAT04_NAME_SPACE "http://snaught.com/glabels/0.4/"
56 #define COMPAT191_NAME_SPACE "http://snaught.com/glabels/1.92/"
58 /*========================================================*/
60 /*========================================================*/
62 /*========================================================*/
63 /* Private globals. */
64 /*========================================================*/
66 /*========================================================*/
67 /* Private function prototypes. */
68 /*========================================================*/
70 static glLabel *xml_doc_to_label (xmlDocPtr doc,
71 glXMLLabelStatus *status);
73 static glLabel *xml_parse_label (xmlNodePtr root,
74 glXMLLabelStatus *status);
76 static void xml_parse_objects (xmlNodePtr node,
79 static void xml_parse_object_text (xmlNodePtr node,
82 static void xml_parse_object_box (xmlNodePtr node,
85 static void xml_parse_object_ellipse (xmlNodePtr node,
88 static void xml_parse_object_line (xmlNodePtr node,
91 static void xml_parse_object_image (xmlNodePtr node,
94 static void xml_parse_object_barcode (xmlNodePtr node,
97 static void xml_parse_merge_fields (xmlNodePtr node,
100 static void xml_parse_data (xmlNodePtr node,
103 static void xml_parse_pixdata (xmlNodePtr node,
106 static void xml_parse_toplevel_span (xmlNodePtr node,
107 glLabelObject *object);
110 static xmlDocPtr xml_label_to_doc (glLabel *label,
111 glXMLLabelStatus *status);
113 static void xml_create_objects (xmlNodePtr root,
117 static void xml_create_object_text (xmlNodePtr root,
119 glLabelObject *object);
121 static void xml_create_object_box (xmlNodePtr root,
123 glLabelObject *object);
125 static void xml_create_object_line (xmlNodePtr root,
127 glLabelObject *object);
129 static void xml_create_object_ellipse(xmlNodePtr root,
131 glLabelObject *object);
133 static void xml_create_object_image (xmlNodePtr root,
135 glLabelObject *object);
137 static void xml_create_object_barcode(xmlNodePtr root,
139 glLabelObject *object);
141 static void xml_create_merge_fields (xmlNodePtr root,
145 static void xml_create_data (xmlNodePtr root,
149 static void xml_create_pixdata (xmlNodePtr root,
154 static void xml_create_toplevel_span (xmlNodePtr node,
156 glLabelText *object_text);
159 /****************************************************************************/
160 /* Open and read label from xml file. */
161 /****************************************************************************/
163 gl_xml_label_open (const gchar *utf8_filename,
164 glXMLLabelStatus *status)
170 gl_debug (DEBUG_XML, "START");
172 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
173 g_return_val_if_fail (filename, NULL);
175 doc = xmlParseFile (filename);
177 g_warning (_("xmlParseFile error"));
178 *status = XML_LABEL_ERROR_OPEN_PARSE;
182 xmlXIncludeProcess (doc);
183 xmlReconciliateNs (doc, xmlDocGetRootElement (doc));
185 label = xml_doc_to_label (doc, status);
190 gl_label_set_filename (label, utf8_filename);
191 gl_label_clear_modified (label);
195 gl_debug (DEBUG_XML, "END");
200 /****************************************************************************/
201 /* Read label from xml buffer. */
202 /****************************************************************************/
204 gl_xml_label_open_buffer (const gchar *buffer,
205 glXMLLabelStatus *status)
210 gl_debug (DEBUG_XML, "START");
212 doc = xmlParseDoc ((xmlChar *) buffer);
214 g_warning (_("xmlParseFile error"));
215 *status = XML_LABEL_ERROR_OPEN_PARSE;
219 label = xml_doc_to_label (doc, status);
224 gl_label_clear_modified (label);
227 gl_debug (DEBUG_XML, "END");
232 /*--------------------------------------------------------------------------*/
233 /* PRIVATE. Parse xml doc structure and create label. */
234 /*--------------------------------------------------------------------------*/
236 xml_doc_to_label (xmlDocPtr doc,
237 glXMLLabelStatus *status)
239 xmlNodePtr root, node;
243 gl_debug (DEBUG_XML, "START");
247 *status = XML_LABEL_OK;
249 root = xmlDocGetRootElement (doc);
250 if (!root || !root->name) {
251 g_warning (_("No document root"));
252 *status = XML_LABEL_ERROR_OPEN_PARSE;
256 ns = xmlSearchNsByHref (doc, root, NAME_SPACE);
258 label = xml_parse_label (root, status);
260 /* Try compatability mode 0.1 */
261 ns = xmlSearchNsByHref (doc, root, COMPAT01_NAME_SPACE);
263 g_warning (_("Importing from glabels 0.1 format"));
265 label = NULL; /* TODO */
267 /* Try compatability mode 0.4 */
268 ns = xmlSearchNsByHref (doc, root,
269 COMPAT04_NAME_SPACE);
271 g_warning (_("Importing from glabels 0.4 format"));
272 label = gl_xml_label_04_parse (root, status);
274 /* Try compatability mode 1.91 */
275 ns = xmlSearchNsByHref (doc, root,
276 COMPAT191_NAME_SPACE);
278 g_warning (_("Importing from glabels 1.91 format"));
279 label = gl_xml_label_191_parse (root, status);
281 g_warning (_("bad document, unknown glabels Namespace"));
282 *status = XML_LABEL_ERROR_OPEN_PARSE;
289 gl_debug (DEBUG_XML, "END");
294 /*--------------------------------------------------------------------------*/
295 /* PRIVATE. Parse xml root node and create label. */
296 /*--------------------------------------------------------------------------*/
298 xml_parse_label (xmlNodePtr root,
299 glXMLLabelStatus *status)
301 xmlNodePtr child_node;
303 glTemplate *template;
305 gl_debug (DEBUG_XML, "START");
307 *status = XML_LABEL_OK;
309 if (!xmlStrEqual (root->name, "Glabels-document")) {
310 g_warning (_("Bad root node = \"%s\""), root->name);
311 *status = XML_LABEL_ERROR_OPEN_PARSE;
315 label = GL_LABEL(gl_label_new ());
317 /* Pass 1, extract data nodes to pre-load cache. */
318 for (child_node = root->xmlChildrenNode; child_node != NULL; child_node = child_node->next) {
319 if (xmlStrEqual (child_node->name, "Data")) {
320 xml_parse_data (child_node, label);
324 /* Pass 2, now extract everything else. */
325 for (child_node = root->xmlChildrenNode;
327 child_node = child_node->next) {
329 if (xmlStrEqual (child_node->name, "Template")) {
330 template = gl_xml_template_parse_template (child_node);
332 *status = XML_LABEL_UNKNOWN_MEDIA;
335 gl_label_set_template (label, template);
336 gl_template_free (&template);
337 } else if (xmlStrEqual (child_node->name, "Objects")) {
338 xml_parse_objects (child_node, label);
339 } else if (xmlStrEqual (child_node->name, "Merge")) {
340 xml_parse_merge_fields (child_node, label);
341 } else if (xmlStrEqual (child_node->name, "Data")) {
342 /* Handled in pass 1. */
344 if (!xmlNodeIsText (child_node)) {
345 g_warning (_("bad node in Document node = \"%s\""),
351 gl_debug (DEBUG_XML, "END");
356 /*--------------------------------------------------------------------------*/
357 /* PRIVATE. Parse Objects node. */
358 /*--------------------------------------------------------------------------*/
360 xml_parse_objects (xmlNodePtr node,
363 gboolean rotate_flag;
366 gl_debug (DEBUG_XML, "START");
368 rotate_flag = gl_xml_get_prop_boolean (node, "rotate", FALSE);
369 gl_label_set_rotate_flag (label, rotate_flag);
371 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
373 if (xmlStrEqual (child->name, "Object-text")) {
374 xml_parse_object_text (child, label);
375 } else if (xmlStrEqual (child->name, "Object-box")) {
376 xml_parse_object_box (child, label);
377 } else if (xmlStrEqual (child->name, "Object-ellipse")) {
378 xml_parse_object_ellipse (child, label);
379 } else if (xmlStrEqual (child->name, "Object-line")) {
380 xml_parse_object_line (child, label);
381 } else if (xmlStrEqual (child->name, "Object-image")) {
382 xml_parse_object_image (child, label);
383 } else if (xmlStrEqual (child->name, "Object-barcode")) {
384 xml_parse_object_barcode (child, label);
386 if (!xmlNodeIsText (child)) {
387 g_warning (_("bad node = \"%s\""), child->name);
393 gl_debug (DEBUG_XML, "END");
396 /*--------------------------------------------------------------------------*/
397 /* PRIVATE. Parse XML Objects->Object-text Node */
398 /*--------------------------------------------------------------------------*/
400 xml_parse_object_text (xmlNodePtr node,
407 GtkJustification just;
411 gl_debug (DEBUG_XML, "START");
413 object = gl_label_text_new (label);
416 x = gl_xml_get_prop_length (node, "x", 0.0);
417 y = gl_xml_get_prop_length (node, "y", 0.0);
418 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
420 /* implied size attrs */
421 w = gl_xml_get_prop_length (node, "w", 0);
422 h = gl_xml_get_prop_length (node, "h", 0);
423 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
426 string = xmlGetProp (node, "justify");
427 just = gl_util_string_to_just (string);
429 gl_label_object_set_text_alignment (GL_LABEL_OBJECT(object), just);
432 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
433 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
434 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
435 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
436 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
437 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
438 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
440 /* Process children */
441 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
442 if (xmlStrEqual (child->name, "Span")) {
443 xml_parse_toplevel_span (child, GL_LABEL_OBJECT(object));
446 if (!xmlNodeIsText (child)) {
447 g_warning ("Unexpected Object-text child: \"%s\"",
453 gl_debug (DEBUG_XML, "END");
456 /*--------------------------------------------------------------------------*/
457 /* PRIVATE. Parse XML Objects->Object-box Node */
458 /*--------------------------------------------------------------------------*/
460 xml_parse_object_box (xmlNodePtr node,
467 guint line_color, fill_color;
470 gl_debug (DEBUG_XML, "START");
472 object = gl_label_box_new (label);
475 x = gl_xml_get_prop_length (node, "x", 0.0);
476 y = gl_xml_get_prop_length (node, "y", 0.0);
477 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
480 w = gl_xml_get_prop_length (node, "w", 0);
481 h = gl_xml_get_prop_length (node, "h", 0);
482 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
485 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
486 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
487 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
488 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
491 fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
492 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color);
495 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
496 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
497 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
498 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
499 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
500 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
501 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
503 gl_debug (DEBUG_XML, "END");
506 /*--------------------------------------------------------------------------*/
507 /* PRIVATE. Parse XML Objects->Object-ellipse Node */
508 /*--------------------------------------------------------------------------*/
510 xml_parse_object_ellipse (xmlNodePtr node,
517 guint line_color, fill_color;
520 gl_debug (DEBUG_XML, "START");
522 object = gl_label_ellipse_new (label);
525 x = gl_xml_get_prop_length (node, "x", 0.0);
526 y = gl_xml_get_prop_length (node, "y", 0.0);
527 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
530 w = gl_xml_get_prop_length (node, "w", 0);
531 h = gl_xml_get_prop_length (node, "h", 0);
532 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
535 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
536 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
537 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
538 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
541 fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
542 gl_label_object_set_fill_color (GL_LABEL_OBJECT(object), fill_color);
545 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
546 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
547 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
548 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
549 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
550 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
551 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
553 gl_debug (DEBUG_XML, "END");
556 /*--------------------------------------------------------------------------*/
557 /* PRIVATE. Parse XML Objects->Object-line Node */
558 /*--------------------------------------------------------------------------*/
560 xml_parse_object_line (xmlNodePtr node,
570 gl_debug (DEBUG_XML, "START");
572 object = gl_label_line_new (label);
575 x = gl_xml_get_prop_length (node, "x", 0.0);
576 y = gl_xml_get_prop_length (node, "y", 0.0);
577 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
580 dx = gl_xml_get_prop_length (node, "dx", 0);
581 dy = gl_xml_get_prop_length (node, "dy", 0);
582 gl_label_object_set_size (GL_LABEL_OBJECT(object), dx, dy);
585 line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
586 line_color = gl_xml_get_prop_uint (node, "line_color", 0);
587 gl_label_object_set_line_width (GL_LABEL_OBJECT(object), line_width);
588 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), line_color);
591 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
592 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
593 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
594 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
595 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
596 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
597 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
599 gl_debug (DEBUG_XML, "END");
602 /*--------------------------------------------------------------------------*/
603 /* PRIVATE. Parse XML Objects->Object-image Node */
604 /*--------------------------------------------------------------------------*/
606 xml_parse_object_image (xmlNodePtr node,
613 glTextNode *filename;
616 gl_debug (DEBUG_XML, "START");
618 object = gl_label_image_new (label);
621 x = gl_xml_get_prop_length (node, "x", 0.0);
622 y = gl_xml_get_prop_length (node, "y", 0.0);
623 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
626 w = gl_xml_get_prop_length (node, "w", 0);
627 h = gl_xml_get_prop_length (node, "h", 0);
628 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
630 /* src or field attr */
631 string = xmlGetProp (node, "src");
633 filename = g_new0 (glTextNode, 1);
634 filename->field_flag = FALSE;
635 filename->data = string;
636 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
637 gl_text_node_free (&filename);
639 string = xmlGetProp (node, "field");
641 filename = g_new0 (glTextNode, 1);
642 filename->field_flag = TRUE;
643 filename->data = string;
644 gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
645 gl_text_node_free (&filename);
647 g_warning ("Missing Object-image src or field attr");
652 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
653 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
654 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
655 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
656 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
657 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
658 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
660 gl_debug (DEBUG_XML, "END");
663 /*--------------------------------------------------------------------------*/
664 /* PRIVATE. Parse XML Objects->Object-barcode Node */
665 /*--------------------------------------------------------------------------*/
667 xml_parse_object_barcode (xmlNodePtr node,
674 glTextNode *text_node;
675 glBarcodeStyle style;
677 gboolean checksum_flag;
681 gl_debug (DEBUG_XML, "START");
683 object = gl_label_barcode_new (label);
686 x = gl_xml_get_prop_length (node, "x", 0.0);
687 y = gl_xml_get_prop_length (node, "y", 0.0);
688 gl_label_object_set_position (GL_LABEL_OBJECT(object), x, y);
691 w = gl_xml_get_prop_length (node, "w", 0);
692 h = gl_xml_get_prop_length (node, "h", 0);
693 gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
696 string = xmlGetProp (node, "style");
697 style = gl_barcode_text_to_style (string);
699 text_flag = gl_xml_get_prop_boolean (node, "text", FALSE);
700 checksum_flag = gl_xml_get_prop_boolean (node, "checksum", TRUE);
701 color = gl_xml_get_prop_uint (node, "color", 0);
702 gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
703 style, text_flag, checksum_flag);
704 gl_label_object_set_line_color (GL_LABEL_OBJECT(object), color);
706 /* data or field attr */
707 string = xmlGetProp (node, "data");
709 text_node = g_new0 (glTextNode, 1);
710 text_node->field_flag = FALSE;
711 text_node->data = string;
712 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
713 gl_text_node_free (&text_node);
715 string = xmlGetProp (node, "field");
717 text_node = g_new0 (glTextNode, 1);
718 text_node->field_flag = TRUE;
719 text_node->data = string;
720 gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
721 gl_text_node_free (&text_node);
723 g_warning ("Missing Object-barcode data or field attr");
728 affine[0] = gl_xml_get_prop_double (node, "a0", 0.0);
729 affine[1] = gl_xml_get_prop_double (node, "a1", 0.0);
730 affine[2] = gl_xml_get_prop_double (node, "a2", 0.0);
731 affine[3] = gl_xml_get_prop_double (node, "a3", 0.0);
732 affine[4] = gl_xml_get_prop_double (node, "a4", 0.0);
733 affine[5] = gl_xml_get_prop_double (node, "a5", 0.0);
734 gl_label_object_set_affine (GL_LABEL_OBJECT(object), affine);
736 gl_debug (DEBUG_XML, "END");
739 /*--------------------------------------------------------------------------*/
740 /* PRIVATE. Parse XML merge fields tag. */
741 /*--------------------------------------------------------------------------*/
743 xml_parse_merge_fields (xmlNodePtr node,
750 gl_debug (DEBUG_XML, "START");
752 string = xmlGetProp (node, "type");
753 merge = gl_merge_new (string);
756 string = xmlGetProp (node, "src");
757 gl_merge_set_src (merge, string);
760 gl_label_set_merge (label, merge);
762 g_object_unref (G_OBJECT(merge));
764 gl_debug (DEBUG_XML, "END");
767 /*--------------------------------------------------------------------------*/
768 /* PRIVATE. Parse XML data tag. */
769 /*--------------------------------------------------------------------------*/
771 xml_parse_data (xmlNodePtr node,
776 gl_debug (DEBUG_XML, "START");
778 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
780 if (xmlStrEqual (child->name, "Pixdata")) {
781 xml_parse_pixdata (child, label);
783 if (!xmlNodeIsText (child)) {
784 g_warning (_("bad node in Data node = \"%s\""),
790 gl_debug (DEBUG_XML, "END");
793 /*--------------------------------------------------------------------------*/
794 /* PRIVATE. Parse XML pixbuf data tag. */
795 /*--------------------------------------------------------------------------*/
797 xml_parse_pixdata (xmlNodePtr node,
800 gchar *name, *base64;
806 GHashTable *pixbuf_cache;
808 gl_debug (DEBUG_XML, "START");
810 name = xmlGetProp (node, "name");
811 base64 = xmlNodeGetContent (node);
813 stream = gl_base64_decode (base64, &stream_length);
814 pixdata = g_new0 (GdkPixdata, 1);
815 ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
818 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
820 pixbuf_cache = gl_label_get_pixbuf_cache (label);
821 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
829 gl_debug (DEBUG_XML, "END");
832 /*--------------------------------------------------------------------------*/
833 /* PRIVATE. Parse top-level Span tag. */
834 /*--------------------------------------------------------------------------*/
836 xml_parse_toplevel_span (xmlNodePtr node,
837 glLabelObject *object)
841 GnomeFontWeight font_weight;
842 gboolean font_italic_flag;
845 GList *lines, *text_nodes;
847 glTextNode *text_node;
849 gl_debug (DEBUG_XML, "START");
851 /* Font family attr */
852 font_family = xmlGetProp (node, "font_family");
853 gl_label_object_set_font_family (object, font_family);
854 g_free (font_family);
857 font_size = gl_xml_get_prop_double (node, "font_size", 0.0);
858 gl_label_object_set_font_size (object, font_size);
860 /* Font weight attr */
861 string = xmlGetProp (node, "font_weight");
862 font_weight = gl_util_string_to_weight (string);
864 gl_label_object_set_font_weight (object, font_weight);
866 /* Font italic flag attr */
867 font_italic_flag = gl_xml_get_prop_boolean (node, "font_italic", FALSE);
868 gl_label_object_set_font_italic_flag (object, font_italic_flag);
870 /* Text color attr */
871 color = gl_xml_get_prop_uint (node, "color", 0);
872 gl_label_object_set_text_color (object, color);
874 /* Now descend children, and build lines of text nodes */
877 for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
879 if (xmlNodeIsText (child)) {
880 gchar *data = xmlNodeGetContent (child);
882 /* Hack: if the first char is LF, it's a xml formatting string */
883 if (data[0] != '\n') {
885 text_node = g_new0 (glTextNode, 1);
886 text_node->field_flag = FALSE;
887 text_node->data = data;
888 text_nodes = g_list_append (text_nodes, text_node);
893 } else if (xmlStrEqual (child->name, "Span")) {
895 g_warning ("Unexpected rich text (not supported, yet!)");
897 } else if (xmlStrEqual (child->name, "Field")) {
900 text_node = g_new0 (glTextNode, 1);
901 text_node->field_flag = TRUE;
902 text_node->data = xmlGetProp (child, "name");
903 text_nodes = g_list_append (text_nodes, text_node);
905 } else if (xmlStrEqual (child->name, "NL")) {
908 lines = g_list_append (lines, text_nodes);
912 g_warning ("Unexpected Span child: \"%s\"", child->name);
917 /* Store last line. */
918 lines = g_list_append (lines, text_nodes);
921 gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
922 gl_text_node_lines_free (&lines);
924 gl_debug (DEBUG_XML, "END");
927 /****************************************************************************/
928 /* Save label to xml label file. */
929 /****************************************************************************/
931 gl_xml_label_save (glLabel *label,
932 const gchar *utf8_filename,
933 glXMLLabelStatus *status)
939 gl_debug (DEBUG_XML, "START");
941 doc = xml_label_to_doc (label, status);
943 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
945 g_warning (_("Utf8 conversion error."));
947 xmlSetDocCompressMode (doc, 9);
948 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
952 g_warning (_("Problem saving xml file."));
953 *status = XML_LABEL_ERROR_SAVE_FILE;
957 gl_label_set_filename (label, utf8_filename);
958 gl_label_clear_modified (label);
964 gl_debug (DEBUG_XML, "END");
967 /****************************************************************************/
968 /* Save label to xml buffer. */
969 /****************************************************************************/
971 gl_xml_label_save_buffer (glLabel *label,
972 glXMLLabelStatus *status)
978 gl_debug (DEBUG_XML, "START");
980 doc = xml_label_to_doc (label, status);
982 xmlDocDumpMemory (doc, (xmlChar **)&buffer, &size);
985 gl_label_clear_modified (label);
987 gl_debug (DEBUG_XML, "END");
992 /*--------------------------------------------------------------------------*/
993 /* PRIVATE. Convert label to xml doc structure. */
994 /*--------------------------------------------------------------------------*/
996 xml_label_to_doc (glLabel *label,
997 glXMLLabelStatus *status)
1001 glTemplate *template;
1004 gl_debug (DEBUG_XML, "START");
1006 LIBXML_TEST_VERSION;
1008 doc = xmlNewDoc ("1.0");
1009 doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Glabels-document", NULL);
1011 ns = xmlNewNs (doc->xmlRootNode, NAME_SPACE, NULL);
1012 xmlSetNs (doc->xmlRootNode, ns);
1014 template = gl_label_get_template (label);
1015 gl_xml_template_add_template (template, doc->xmlRootNode, ns);
1017 xml_create_objects (doc->xmlRootNode, ns, label);
1019 merge = gl_label_get_merge (label);
1020 gl_debug (DEBUG_XML, "merge=%p", merge);
1021 if (merge != NULL) {
1022 xml_create_merge_fields (doc->xmlRootNode, ns, label);
1023 g_object_unref (G_OBJECT(merge));
1026 xml_create_data (doc->xmlRootNode, ns, label);
1028 gl_debug (DEBUG_XML, "END");
1030 *status = XML_LABEL_OK;
1034 /*--------------------------------------------------------------------------*/
1035 /* PRIVATE. Add XML Objects Node */
1036 /*--------------------------------------------------------------------------*/
1038 xml_create_objects (xmlNodePtr root,
1043 gboolean rotate_flag;
1045 glLabelObject *object;
1047 gl_debug (DEBUG_XML, "START");
1049 rotate_flag = gl_label_get_rotate_flag (label);
1051 node = xmlNewChild (root, ns, "Objects", NULL);
1052 xmlSetProp (node, "id", "0");
1053 gl_xml_set_prop_boolean (node, "rotate", rotate_flag);
1055 for (p = label->objects; p != NULL; p = p->next) {
1057 object = GL_LABEL_OBJECT(p->data);
1059 if ( GL_IS_LABEL_TEXT(object) ) {
1060 xml_create_object_text (node, ns, object);
1061 } else if ( GL_IS_LABEL_BOX(object) ) {
1062 xml_create_object_box (node, ns, object);
1063 } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
1064 xml_create_object_ellipse (node, ns, object);
1065 } else if ( GL_IS_LABEL_LINE(object) ) {
1066 xml_create_object_line (node, ns, object);
1067 } else if ( GL_IS_LABEL_IMAGE(object) ) {
1068 xml_create_object_image (node, ns, object);
1069 } else if ( GL_IS_LABEL_BARCODE(object) ) {
1070 xml_create_object_barcode (node, ns, object);
1072 g_warning ("Unknown label object");
1077 gl_debug (DEBUG_XML, "END");
1080 /*--------------------------------------------------------------------------*/
1081 /* PRIVATE. Add XML Objects->Object-text Node */
1082 /*--------------------------------------------------------------------------*/
1084 xml_create_object_text (xmlNodePtr root,
1086 glLabelObject *object)
1091 GtkJustification just;
1094 gl_debug (DEBUG_XML, "START");
1096 node = xmlNewChild (root, ns, "Object-text", NULL);
1098 /* position attrs */
1099 gl_label_object_get_position (object, &x, &y);
1100 gl_xml_set_prop_length (node, "x", x);
1101 gl_xml_set_prop_length (node, "y", y);
1104 gl_label_text_get_box ( GL_LABEL_TEXT(object), &w, &h);
1105 gl_xml_set_prop_length (node, "w", w);
1106 gl_xml_set_prop_length (node, "h", h);
1109 just = gl_label_object_get_text_alignment (object);
1110 xmlSetProp (node, "justify", gl_util_just_to_string (just));
1113 gl_label_object_get_affine (object, affine);
1114 gl_xml_set_prop_double (node, "a0", affine[0]);
1115 gl_xml_set_prop_double (node, "a1", affine[1]);
1116 gl_xml_set_prop_double (node, "a2", affine[2]);
1117 gl_xml_set_prop_double (node, "a3", affine[3]);
1118 gl_xml_set_prop_double (node, "a4", affine[4]);
1119 gl_xml_set_prop_double (node, "a5", affine[5]);
1122 xml_create_toplevel_span (node, ns, GL_LABEL_TEXT(object));
1124 gl_debug (DEBUG_XML, "END");
1127 /*--------------------------------------------------------------------------*/
1128 /* PRIVATE. Add XML Objects->Object-box Node */
1129 /*--------------------------------------------------------------------------*/
1131 xml_create_object_box (xmlNodePtr root,
1133 glLabelObject *object)
1139 guint line_color, fill_color;
1142 gl_debug (DEBUG_XML, "START");
1144 node = xmlNewChild (root, ns, "Object-box", NULL);
1146 /* position attrs */
1147 gl_label_object_get_position (object, &x, &y);
1148 gl_xml_set_prop_length (node, "x", x);
1149 gl_xml_set_prop_length (node, "y", y);
1152 gl_label_object_get_size (object, &w, &h);
1153 gl_xml_set_prop_length (node, "w", w);
1154 gl_xml_set_prop_length (node, "h", h);
1157 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1158 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1159 gl_xml_set_prop_length (node, "line_width", line_width);
1160 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1163 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1164 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1167 gl_label_object_get_affine (object, affine);
1168 gl_xml_set_prop_double (node, "a0", affine[0]);
1169 gl_xml_set_prop_double (node, "a1", affine[1]);
1170 gl_xml_set_prop_double (node, "a2", affine[2]);
1171 gl_xml_set_prop_double (node, "a3", affine[3]);
1172 gl_xml_set_prop_double (node, "a4", affine[4]);
1173 gl_xml_set_prop_double (node, "a5", affine[5]);
1175 gl_debug (DEBUG_XML, "END");
1178 /*--------------------------------------------------------------------------*/
1179 /* PRIVATE. Add XML Objects->Object-ellipse Node */
1180 /*--------------------------------------------------------------------------*/
1182 xml_create_object_ellipse (xmlNodePtr root,
1184 glLabelObject *object)
1190 guint line_color, fill_color;
1193 gl_debug (DEBUG_XML, "START");
1195 node = xmlNewChild (root, ns, "Object-ellipse", NULL);
1197 /* position attrs */
1198 gl_label_object_get_position (object, &x, &y);
1199 gl_xml_set_prop_length (node, "x", x);
1200 gl_xml_set_prop_length (node, "y", y);
1203 gl_label_object_get_size (object, &w, &h);
1204 gl_xml_set_prop_length (node, "w", w);
1205 gl_xml_set_prop_length (node, "h", h);
1208 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1209 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1210 gl_xml_set_prop_length (node, "line_width", line_width);
1211 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1214 fill_color = gl_label_object_get_fill_color (GL_LABEL_OBJECT(object));
1215 gl_xml_set_prop_uint_hex (node, "fill_color", fill_color);
1218 gl_label_object_get_affine (object, affine);
1219 gl_xml_set_prop_double (node, "a0", affine[0]);
1220 gl_xml_set_prop_double (node, "a1", affine[1]);
1221 gl_xml_set_prop_double (node, "a2", affine[2]);
1222 gl_xml_set_prop_double (node, "a3", affine[3]);
1223 gl_xml_set_prop_double (node, "a4", affine[4]);
1224 gl_xml_set_prop_double (node, "a5", affine[5]);
1226 gl_debug (DEBUG_XML, "END");
1229 /*--------------------------------------------------------------------------*/
1230 /* PRIVATE. Add XML Objects->Object-line Node */
1231 /*--------------------------------------------------------------------------*/
1233 xml_create_object_line (xmlNodePtr root,
1235 glLabelObject *object)
1244 gl_debug (DEBUG_XML, "START");
1246 node = xmlNewChild (root, ns, "Object-line", NULL);
1248 /* position attrs */
1249 gl_label_object_get_position (object, &x, &y);
1250 gl_xml_set_prop_length (node, "x", x);
1251 gl_xml_set_prop_length (node, "y", y);
1254 gl_label_object_get_size (object, &dx, &dy);
1255 gl_xml_set_prop_length (node, "dx", dx);
1256 gl_xml_set_prop_length (node, "dy", dy);
1259 line_width = gl_label_object_get_line_width (GL_LABEL_OBJECT(object));
1260 line_color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1261 gl_xml_set_prop_length (node, "line_width", line_width);
1262 gl_xml_set_prop_uint_hex (node, "line_color", line_color);
1265 gl_label_object_get_affine (object, affine);
1266 gl_xml_set_prop_double (node, "a0", affine[0]);
1267 gl_xml_set_prop_double (node, "a1", affine[1]);
1268 gl_xml_set_prop_double (node, "a2", affine[2]);
1269 gl_xml_set_prop_double (node, "a3", affine[3]);
1270 gl_xml_set_prop_double (node, "a4", affine[4]);
1271 gl_xml_set_prop_double (node, "a5", affine[5]);
1273 gl_debug (DEBUG_XML, "END");
1276 /*--------------------------------------------------------------------------*/
1277 /* PRIVATE. Add XML Objects->Object-image Node */
1278 /*--------------------------------------------------------------------------*/
1280 xml_create_object_image (xmlNodePtr root,
1282 glLabelObject *object)
1287 glTextNode *filename;
1290 gl_debug (DEBUG_XML, "START");
1292 node = xmlNewChild (root, ns, "Object-image", NULL);
1294 /* position attrs */
1295 gl_label_object_get_position (object, &x, &y);
1296 gl_xml_set_prop_length (node, "x", x);
1297 gl_xml_set_prop_length (node, "y", y);
1300 gl_label_object_get_size (object, &w, &h);
1301 gl_xml_set_prop_length (node, "w", w);
1302 gl_xml_set_prop_length (node, "h", h);
1304 /* src OR field attr */
1305 filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1306 if (filename->field_flag) {
1307 xmlSetProp (node, "field", filename->data);
1309 xmlSetProp (node, "src", filename->data);
1311 gl_text_node_free (&filename);
1314 gl_label_object_get_affine (object, affine);
1315 gl_xml_set_prop_double (node, "a0", affine[0]);
1316 gl_xml_set_prop_double (node, "a1", affine[1]);
1317 gl_xml_set_prop_double (node, "a2", affine[2]);
1318 gl_xml_set_prop_double (node, "a3", affine[3]);
1319 gl_xml_set_prop_double (node, "a4", affine[4]);
1320 gl_xml_set_prop_double (node, "a5", affine[5]);
1322 gl_debug (DEBUG_XML, "END");
1325 /*--------------------------------------------------------------------------*/
1326 /* PRIVATE. Add XML Objects->Object-barcode Node */
1327 /*--------------------------------------------------------------------------*/
1329 xml_create_object_barcode (xmlNodePtr root,
1331 glLabelObject *object)
1336 glTextNode *text_node;
1337 glBarcodeStyle style;
1339 gboolean checksum_flag;
1343 gl_debug (DEBUG_XML, "START");
1345 node = xmlNewChild (root, ns, "Object-barcode", NULL);
1347 /* position attrs */
1348 gl_label_object_get_position (object, &x, &y);
1349 gl_xml_set_prop_length (node, "x", x);
1350 gl_xml_set_prop_length (node, "y", y);
1353 gl_label_object_get_size (object, &w, &h);
1354 gl_xml_set_prop_length (node, "w", w);
1355 gl_xml_set_prop_length (node, "h", h);
1357 /* Barcode properties attrs */
1358 gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1359 &style, &text_flag, &checksum_flag);
1360 color = gl_label_object_get_line_color (GL_LABEL_OBJECT(object));
1361 xmlSetProp (node, "style", gl_barcode_style_to_text (style));
1362 gl_xml_set_prop_boolean (node, "text", text_flag);
1363 gl_xml_set_prop_boolean (node, "checksum", checksum_flag);
1364 gl_xml_set_prop_uint_hex (node, "color", color);
1366 /* data OR field attr */
1367 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1368 if (text_node->field_flag) {
1369 xmlSetProp (node, "field", text_node->data);
1371 xmlSetProp (node, "data", text_node->data);
1373 gl_text_node_free (&text_node);
1376 gl_label_object_get_affine (object, affine);
1377 gl_xml_set_prop_double (node, "a0", affine[0]);
1378 gl_xml_set_prop_double (node, "a1", affine[1]);
1379 gl_xml_set_prop_double (node, "a2", affine[2]);
1380 gl_xml_set_prop_double (node, "a3", affine[3]);
1381 gl_xml_set_prop_double (node, "a4", affine[4]);
1382 gl_xml_set_prop_double (node, "a5", affine[5]);
1384 gl_debug (DEBUG_XML, "END");
1387 /*--------------------------------------------------------------------------*/
1388 /* PRIVATE. Add XML Label Merge Fields Node */
1389 /*--------------------------------------------------------------------------*/
1391 xml_create_merge_fields (xmlNodePtr root,
1395 xmlNodePtr node, child;
1400 gl_debug (DEBUG_XML, "START");
1402 merge = gl_label_get_merge (label);
1404 node = xmlNewChild (root, ns, "Merge", NULL);
1406 string = gl_merge_get_name (merge);
1407 xmlSetProp (node, "type", string);
1410 string = gl_merge_get_src (merge);
1411 xmlSetProp (node, "src", string);
1414 g_object_unref (G_OBJECT(merge));
1416 gl_debug (DEBUG_XML, "END");
1419 /*--------------------------------------------------------------------------*/
1420 /* PRIVATE. Add XML Label Data Node */
1421 /*--------------------------------------------------------------------------*/
1423 xml_create_data (xmlNodePtr root,
1428 GList *name_list, *p;
1429 GHashTable *pixbuf_cache;
1431 gl_debug (DEBUG_XML, "START");
1433 node = xmlNewChild (root, ns, "Data", NULL);
1435 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1436 name_list = gl_pixbuf_cache_get_name_list (pixbuf_cache);
1438 for (p = name_list; p != NULL; p=p->next) {
1439 xml_create_pixdata (node, ns, label, p->data);
1442 gl_pixbuf_cache_free_name_list (name_list);
1445 gl_debug (DEBUG_XML, "END");
1448 /*--------------------------------------------------------------------------*/
1449 /* PRIVATE. Add XML Label Data Pixbuf Node */
1450 /*--------------------------------------------------------------------------*/
1452 xml_create_pixdata (xmlNodePtr root,
1458 GHashTable *pixbuf_cache;
1460 GdkPixdata *pixdata;
1462 guint stream_length;
1465 gl_debug (DEBUG_XML, "START");
1467 pixbuf_cache = gl_label_get_pixbuf_cache (label);
1469 pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, name);
1470 if ( pixbuf != NULL ) {
1472 pixdata = g_new0 (GdkPixdata, 1);
1473 gdk_pixdata_from_pixbuf (pixdata, pixbuf, FALSE);
1474 stream = gdk_pixdata_serialize (pixdata, &stream_length);
1475 base64 = gl_base64_encode (stream, stream_length);
1477 node = xmlNewChild (root, ns, "Pixdata", base64);
1478 xmlSetProp (node, "name", name);
1479 xmlSetProp (node, "encoding", "Base64");
1481 gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, name);
1489 gl_debug (DEBUG_XML, "END");
1492 /*--------------------------------------------------------------------------*/
1493 /* PRIVATE. Create top-level Span node. */
1494 /*--------------------------------------------------------------------------*/
1496 xml_create_toplevel_span (xmlNodePtr root,
1498 glLabelText *object_text)
1503 GnomeFontWeight font_weight;
1504 gboolean font_italic_flag;
1506 GtkJustification just;
1507 GList *lines, *p_line, *p_node;
1508 glTextNode *text_node;
1511 node = xmlNewChild (root, ns, "Span", NULL);
1513 /* All span attrs at top level. */
1514 font_family = gl_label_object_get_font_family (GL_LABEL_OBJECT(object_text));
1515 font_size = gl_label_object_get_font_size (GL_LABEL_OBJECT(object_text));
1516 font_weight = gl_label_object_get_font_weight (GL_LABEL_OBJECT(object_text));
1517 font_italic_flag = gl_label_object_get_font_italic_flag (GL_LABEL_OBJECT(object_text));
1518 color = gl_label_object_get_text_color (GL_LABEL_OBJECT(object_text));
1519 just = gl_label_object_get_text_alignment (GL_LABEL_OBJECT(object_text));
1520 xmlSetProp (node, "font_family", font_family);
1521 gl_xml_set_prop_double (node, "font_size", font_size);
1522 xmlSetProp (node, "font_weight", gl_util_weight_to_string (font_weight));
1523 gl_xml_set_prop_boolean (node, "font_italic", font_italic_flag);
1524 gl_xml_set_prop_uint_hex (node, "color", color);
1526 /* Build children. */
1527 lines = gl_label_text_get_lines (GL_LABEL_TEXT(object_text));
1528 for (p_line = lines; p_line != NULL; p_line = p_line->next) {
1530 for (p_node = (GList *) p_line->data; p_node != NULL;
1531 p_node = p_node->next) {
1532 text_node = (glTextNode *) p_node->data;
1534 if (text_node->field_flag) {
1535 child = xmlNewChild (node, ns, "Field", NULL);
1536 xmlSetProp (child, "name", text_node->data);
1538 xmlNodeAddContent (node, text_node->data);
1543 if ( p_line->next ) {
1544 child = xmlNewChild (node, ns, "NL", NULL);
1549 gl_text_node_lines_free (&lines);
1550 g_free (font_family);