]> git.sur5r.net Git - glabels/blob - libglabels/lgl-xml-template.c
Imported Upstream version 3.0.0
[glabels] / libglabels / lgl-xml-template.c
1 /*
2  *  lgl-xml-template.c
3  *  Copyright (C) 2001-2010  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of libglabels.
6  *
7  *  libglabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU Lesser General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  libglabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License
18  *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "lgl-xml-template.h"
24
25 #include <glib/gi18n.h>
26 #include <glib.h>
27 #include <string.h>
28 #include <libintl.h>
29
30 #include "libglabels-private.h"
31
32 #include "lgl-db.h"
33 #include "lgl-xml.h"
34
35 /*===========================================*/
36 /* Private types                             */
37 /*===========================================*/
38
39 /*===========================================*/
40 /* Private globals                           */
41 /*===========================================*/
42
43 /*===========================================*/
44 /* Local function prototypes                 */
45 /*===========================================*/
46 static void  xml_parse_meta_node            (xmlNodePtr              label_node,
47                                              lglTemplate            *template);
48 static void  xml_parse_label_rectangle_node (xmlNodePtr              label_node,
49                                              lglTemplate            *template);
50 static void  xml_parse_label_ellipse_node   (xmlNodePtr              label_node,
51                                              lglTemplate            *template);
52 static void  xml_parse_label_round_node     (xmlNodePtr              label_node,
53                                              lglTemplate            *template);
54 static void  xml_parse_label_cd_node        (xmlNodePtr              label_node,
55                                              lglTemplate            *template);
56 static void  xml_parse_layout_node          (xmlNodePtr              layout_node,
57                                              lglTemplateFrame       *frame);
58 static void  xml_parse_markup_margin_node   (xmlNodePtr              markup_node,
59                                              lglTemplateFrame       *frame);
60 static void  xml_parse_markup_line_node     (xmlNodePtr              markup_node,
61                                              lglTemplateFrame       *frame);
62 static void  xml_parse_markup_circle_node   (xmlNodePtr              markup_node,
63                                              lglTemplateFrame       *frame);
64 static void  xml_parse_markup_rect_node     (xmlNodePtr              markup_node,
65                                              lglTemplateFrame       *frame);
66 static void  xml_parse_markup_ellipse_node  (xmlNodePtr              markup_node,
67                                              lglTemplateFrame       *frame);
68 static void  xml_parse_alias_node           (xmlNodePtr              alias_node,
69                                              lglTemplate            *template);
70
71 static void  xml_create_meta_node           (const gchar                  *attr,
72                                              const gchar                  *value,
73                                              xmlNodePtr                    root,
74                                              const xmlNsPtr                ns);
75 static void  xml_create_label_node          (const lglTemplateFrame       *frame,
76                                              xmlNodePtr                    root,
77                                              const xmlNsPtr                ns);
78 static void  xml_create_layout_node         (const lglTemplateLayout      *layout,
79                                              xmlNodePtr                    root,
80                                              const xmlNsPtr                ns);
81 static void  xml_create_markup_margin_node  (const lglTemplateMarkup      *margin,
82                                              xmlNodePtr                    root,
83                                              const xmlNsPtr                ns);
84 static void  xml_create_markup_line_node    (const lglTemplateMarkup      *line,
85                                              xmlNodePtr                    root,
86                                              const xmlNsPtr                ns);
87 static void  xml_create_markup_circle_node  (const lglTemplateMarkup      *circle,
88                                              xmlNodePtr                    root,
89                                              const xmlNsPtr                ns);
90 static void  xml_create_markup_rect_node    (const lglTemplateMarkup      *circle,
91                                              xmlNodePtr                    root,
92                                              const xmlNsPtr                ns);
93 static void  xml_create_markup_ellipse_node (const lglTemplateMarkup      *circle,
94                                              xmlNodePtr                    root,
95                                              const xmlNsPtr                ns);
96
97
98 /**
99  * lgl_xml_template_read_templates_from_file:
100  * @utf8_filename:       Filename of papers file (name encoded as UTF-8)
101  *
102  * Read glabels templates from template file.
103  *
104  */
105 void
106 lgl_xml_template_read_templates_from_file (const gchar *utf8_filename)
107 {
108         gchar      *filename;
109         xmlDocPtr   templates_doc;
110
111         LIBXML_TEST_VERSION;
112
113         filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
114         if (!filename)
115         {
116                 g_message ("Utf8 filename conversion error");
117                 return;
118         }
119
120         templates_doc = xmlParseFile (filename);
121         if (!templates_doc)
122         {
123                 g_message ("\"%s\" is not a glabels template file (not XML)",
124                       filename);
125                 return;
126         }
127
128         lgl_xml_template_parse_templates_doc (templates_doc);
129
130         g_free (filename);
131         xmlFreeDoc (templates_doc);
132 }
133
134
135 /**
136  * lgl_xml_template_parse_templates_doc:
137  * @templates_doc:  libxml #xmlDocPtr tree, representing template file.
138  *
139  * Read glabels templates from a libxml #xmlDocPtr tree.
140  *
141  */
142 void
143 lgl_xml_template_parse_templates_doc (const xmlDocPtr templates_doc)
144 {
145         
146         xmlNodePtr   root, node;
147         lglTemplate *template;
148
149         LIBXML_TEST_VERSION;
150
151         root = xmlDocGetRootElement (templates_doc);
152         if (!root || !root->name)
153         {
154                 g_message ("\"%s\" is not a glabels template file (no root node)",
155                            templates_doc->URL);
156                 return;
157         }
158         if (!lgl_xml_is_node (root, "Glabels-templates"))
159         {
160                 g_message ("\"%s\" is not a glabels template file (wrong root node)",
161                       templates_doc->URL);
162                 return;
163         }
164
165         for (node = root->xmlChildrenNode; node != NULL; node = node->next)
166         {
167
168                 if (lgl_xml_is_node (node, "Template"))
169                 {
170                         template = lgl_xml_template_parse_template_node (node);
171                         if (template)
172                         {
173                                 _lgl_db_register_template_internal (template);
174                                 lgl_template_free (template);
175                         }
176                 }
177                 else
178                 {
179                         if ( !xmlNodeIsText(node) )
180                         {
181                                 if (!lgl_xml_is_node (node,"comment"))
182                                 {
183                                         g_message ("bad node =  \"%s\"",node->name);
184                                 }
185                         }
186                 }
187         }
188 }
189
190
191 /**
192  * lgl_xml_template_parse_template_node:
193  * @template_node:  libxml #xmlNodePtr template node from a #xmlDocPtr tree.
194  *
195  * Read a single glabels template from a libxml #xmlNodePtr node.
196  *
197  * Returns: a pointer to a newly created #lglTemplate structure.
198  *
199  */
200 lglTemplate *
201 lgl_xml_template_parse_template_node (const xmlNodePtr template_node)
202 {
203         gchar                 *brand;
204         gchar                 *part;
205         gchar                 *name;
206         gchar                 *equiv_part;
207         gchar                 *description;
208         gchar                 *paper_id;
209         gdouble                page_width, page_height;
210         lglPaper              *paper = NULL;
211         lglTemplate           *template;
212         xmlNodePtr             node;
213         gchar                **v;
214         lglTemplateFrame      *frame;
215
216
217         brand = lgl_xml_get_prop_string (template_node, "brand", NULL);
218         part  = lgl_xml_get_prop_string (template_node, "part", NULL);
219         if (!brand || !part)
220         {
221                 name = lgl_xml_get_prop_string (template_node, "name", NULL);
222                 if (name)
223                 {
224                         v = g_strsplit (name, " ", 2);
225                         brand = g_strdup (v[0]);
226                         part  = g_strchug (g_strdup (v[1]));
227                         g_free (name);
228                         g_strfreev (v);
229                         
230                 }
231                 else
232                 {
233                         g_message ("Missing name or brand/part attributes.");
234                 }
235         }
236
237
238         equiv_part = lgl_xml_get_prop_string (template_node, "equiv", NULL);
239
240
241         description = lgl_xml_get_prop_i18n_string (template_node, "description", NULL);
242         paper_id = lgl_xml_get_prop_string (template_node, "size", NULL);
243
244         if (lgl_db_is_paper_id_other (paper_id))
245         {
246
247                 page_width = lgl_xml_get_prop_length (template_node, "width", 0);
248                 page_height = lgl_xml_get_prop_length (template_node, "height", 0);
249
250         }
251         else
252         {
253                 paper = lgl_db_lookup_paper_from_id (paper_id);
254                 if (paper == NULL)
255                 {
256                         /* This should always be an id, but just in case a name
257                            slips by! */
258                         g_message ("Unknown page size id \"%s\", trying as name",
259                                    paper_id);
260                         paper = lgl_db_lookup_paper_from_name (paper_id);
261                         g_free (paper_id);
262                         paper_id = g_strdup (paper->id);
263                 }
264                 if (paper != NULL)
265                 {
266                         page_width  = paper->width;
267                         page_height = paper->height;
268                 }
269                 else
270                 {
271                         page_width  = 612;
272                         page_height = 792;
273                         g_message ("Unknown page size id or name \"%s\"",
274                                    paper_id);
275                 }
276                 lgl_paper_free (paper);
277                 paper = NULL;
278         }
279
280
281         if (!equiv_part)
282         {
283                 template = lgl_template_new (brand, part, description,
284                                              paper_id, page_width, page_height);
285         }
286         else
287         {
288                 template = lgl_template_new_from_equiv (brand, part, equiv_part);
289
290                 if (!template)
291                 {
292                         g_message ("Forward references not supported.");
293                         return NULL;
294                 }
295         }
296
297
298         for (node = template_node->xmlChildrenNode; node != NULL; node = node->next)
299         {
300                 if (lgl_xml_is_node (node, "Meta"))
301                 {
302                         xml_parse_meta_node (node, template);
303                 }
304                 else if (lgl_xml_is_node (node, "Label-rectangle"))
305                 {
306                         xml_parse_label_rectangle_node (node, template);
307                 }
308                 else if (lgl_xml_is_node (node, "Label-ellipse"))
309                 {
310                         xml_parse_label_ellipse_node (node, template);
311                 }
312                 else if (lgl_xml_is_node (node, "Label-round"))
313                 {
314                         xml_parse_label_round_node (node, template);
315                 }
316                 else if (lgl_xml_is_node (node, "Label-cd"))
317                 {
318                         xml_parse_label_cd_node (node, template);
319                 }
320                 else if (lgl_xml_is_node (node, "Alias"))
321                 {
322                         xml_parse_alias_node (node, template);
323                 }
324                 else
325                 {
326                         if (!xmlNodeIsText (node))
327                         {
328                                 if (!lgl_xml_is_node (node,"comment"))
329                                 {
330                                         g_message ("bad node =  \"%s\"",node->name);
331                                 }
332                         }
333                 }
334         }
335
336         g_free (brand);
337         g_free (part);
338         g_free (equiv_part);
339         g_free (description);
340         g_free (paper_id);
341
342         /*
343          * Create a default full-page frame, if a known frame type was not found.
344          */
345         if ( template->frames == NULL )
346         {
347                 g_message ("%s %s: missing valid frame node", template->brand, template->part);
348                 frame = lgl_template_frame_rect_new ("0", page_width, page_height, 0, 0, 0);
349                 lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0, 0, 0, 0));
350                 lgl_template_add_frame (template, frame);
351         }
352
353         /*
354          * Create a default 1x1 layout, if layout is missing.
355          */
356         frame = (lglTemplateFrame *)template->frames->data;
357         if ( frame->all.layouts == NULL )
358         {
359                 g_message ("%s %s: missing layout node", template->brand, template->part);
360                 lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0, 0, 0, 0));
361         }
362
363         return template;
364 }
365
366 /*--------------------------------------------------------------------------*/
367 /* PRIVATE.  Parse XML Template->Meta Node.                                 */
368 /*--------------------------------------------------------------------------*/
369 static void
370 xml_parse_meta_node (xmlNodePtr   meta_node,
371                      lglTemplate *template)
372 {
373         gchar               *product_url;
374         gchar               *category;
375
376         product_url = lgl_xml_get_prop_string (meta_node, "product_url", NULL);
377         if ( product_url != NULL )
378         {
379                 g_free (template->product_url);
380                 template->product_url = product_url;
381         }
382
383         category = lgl_xml_get_prop_string (meta_node, "category", NULL);
384         if ( category != NULL )
385         {
386                 lgl_template_add_category (template, category);
387                 g_free (category);
388         }
389 }
390
391
392 /*--------------------------------------------------------------------------*/
393 /* PRIVATE.  Parse XML Template->Label-rectangle Node.                      */
394 /*--------------------------------------------------------------------------*/
395 static void
396 xml_parse_label_rectangle_node (xmlNodePtr   label_node,
397                                 lglTemplate *template)
398 {
399         gchar               *id;
400         gchar               *tmp;
401         gdouble              x_waste, y_waste;
402         gdouble              w, h, r;
403         lglTemplateFrame    *frame;
404         xmlNodePtr           node;
405
406         id      = lgl_xml_get_prop_string (label_node, "id", NULL);
407
408         if ((tmp = lgl_xml_get_prop_string (label_node, "waste", NULL)))
409         {
410                 /* Handle single "waste" property. */
411                 x_waste = y_waste = lgl_xml_get_prop_length (label_node, "waste", 0);
412                 g_free (tmp);
413         }
414         else
415         {
416                 x_waste = lgl_xml_get_prop_length (label_node, "x_waste", 0);
417                 y_waste = lgl_xml_get_prop_length (label_node, "y_waste", 0);
418         }
419
420         w       = lgl_xml_get_prop_length (label_node, "width", 0);
421         h       = lgl_xml_get_prop_length (label_node, "height", 0);
422         r       = lgl_xml_get_prop_length (label_node, "round", 0);
423
424         frame = lgl_template_frame_rect_new ((gchar *)id, w, h, r, x_waste, y_waste);
425         lgl_template_add_frame (template, frame);
426
427         for (node = label_node->xmlChildrenNode; node != NULL; node = node->next)
428         {
429                 if (lgl_xml_is_node (node, "Layout"))
430                 {
431                         xml_parse_layout_node (node, frame);
432                 }
433                 else if (lgl_xml_is_node (node, "Markup-margin"))
434                 {
435                         xml_parse_markup_margin_node (node, frame);
436                 }
437                 else if (lgl_xml_is_node (node, "Markup-line"))
438                 {
439                         xml_parse_markup_line_node (node, frame);
440                 }
441                 else if (lgl_xml_is_node (node, "Markup-circle"))
442                 {
443                         xml_parse_markup_circle_node (node, frame);
444                 }
445                 else if (lgl_xml_is_node (node, "Markup-rect"))
446                 {
447                         xml_parse_markup_rect_node (node, frame);
448                 }
449                 else if (lgl_xml_is_node (node, "Markup-ellipse"))
450                 {
451                         xml_parse_markup_ellipse_node (node, frame);
452                 }
453                 else if (!xmlNodeIsText (node))
454                 {
455                         if (!lgl_xml_is_node (node, "comment"))
456                         {
457                                 g_message ("bad node =  \"%s\"",node->name);
458                         }
459                 }
460         }
461
462         g_free (id);
463 }
464
465
466 /*--------------------------------------------------------------------------*/
467 /* PRIVATE.  Parse XML Template->Label-ellipse Node.                        */
468 /*--------------------------------------------------------------------------*/
469 static void
470 xml_parse_label_ellipse_node (xmlNodePtr   label_node,
471                               lglTemplate *template)
472 {
473         gchar               *id;
474         gdouble              waste;
475         gdouble              w, h;
476         lglTemplateFrame    *frame;
477         xmlNodePtr           node;
478
479         id      = lgl_xml_get_prop_string (label_node, "id", NULL);
480
481         w       = lgl_xml_get_prop_length (label_node, "width", 0);
482         h       = lgl_xml_get_prop_length (label_node, "height", 0);
483         waste   = lgl_xml_get_prop_length (label_node, "waste", 0);
484
485         frame = lgl_template_frame_ellipse_new ((gchar *)id, w, h, waste);
486         lgl_template_add_frame (template, frame);
487
488         for (node = label_node->xmlChildrenNode; node != NULL; node = node->next)
489         {
490                 if (lgl_xml_is_node (node, "Layout"))
491                 {
492                         xml_parse_layout_node (node, frame);
493                 }
494                 else if (lgl_xml_is_node (node, "Markup-margin"))
495                 {
496                         xml_parse_markup_margin_node (node, frame);
497                 }
498                 else if (lgl_xml_is_node (node, "Markup-line"))
499                 {
500                         xml_parse_markup_line_node (node, frame);
501                 }
502                 else if (lgl_xml_is_node (node, "Markup-circle"))
503                 {
504                         xml_parse_markup_circle_node (node, frame);
505                 }
506                 else if (lgl_xml_is_node (node, "Markup-rect"))
507                 {
508                         xml_parse_markup_rect_node (node, frame);
509                 }
510                 else if (lgl_xml_is_node (node, "Markup-ellipse"))
511                 {
512                         xml_parse_markup_ellipse_node (node, frame);
513                 }
514                 else if (!xmlNodeIsText (node))
515                 {
516                         if (!lgl_xml_is_node (node, "comment"))
517                         {
518                                 g_message ("bad node =  \"%s\"",node->name);
519                         }
520                 }
521         }
522
523         g_free (id);
524 }
525
526
527 /*--------------------------------------------------------------------------*/
528 /* PRIVATE.  Parse XML Template->Label-round Node.                          */
529 /*--------------------------------------------------------------------------*/
530 static void
531 xml_parse_label_round_node (xmlNodePtr   label_node,
532                             lglTemplate *template)
533 {
534         gchar               *id;
535         gdouble              waste;
536         gdouble              r;
537         lglTemplateFrame    *frame;
538         xmlNodePtr           node;
539
540         id    = lgl_xml_get_prop_string (label_node, "id", NULL);
541         waste = lgl_xml_get_prop_length (label_node, "waste", 0);
542         r     = lgl_xml_get_prop_length (label_node, "radius", 0);
543
544         frame = lgl_template_frame_round_new ((gchar *)id, r, waste);
545         lgl_template_add_frame (template, frame);
546
547         for (node = label_node->xmlChildrenNode; node != NULL; node = node->next)
548         {
549                 if (lgl_xml_is_node (node, "Layout"))
550                 {
551                         xml_parse_layout_node (node, frame);
552                 }
553                 else if (lgl_xml_is_node (node, "Markup-margin"))
554                 {
555                         xml_parse_markup_margin_node (node, frame);
556                 }
557                 else if (lgl_xml_is_node (node, "Markup-line"))
558                 {
559                         xml_parse_markup_line_node (node, frame);
560                 }
561                 else if (lgl_xml_is_node (node, "Markup-circle"))
562                 {
563                         xml_parse_markup_circle_node (node, frame);
564                 }
565                 else if (lgl_xml_is_node (node, "Markup-rect"))
566                 {
567                         xml_parse_markup_rect_node (node, frame);
568                 }
569                 else if (lgl_xml_is_node (node, "Markup-ellipse"))
570                 {
571                         xml_parse_markup_ellipse_node (node, frame);
572                 }
573                 else if (!xmlNodeIsText (node))
574                 {
575                         if (!lgl_xml_is_node (node, "comment"))
576                         {
577                                 g_message ("bad node =  \"%s\"",node->name);
578                         }
579                 }
580         }
581
582         g_free (id);
583 }
584
585 /*--------------------------------------------------------------------------*/
586 /* PRIVATE.  Parse XML Template->Label-cd Node.                             */
587 /*--------------------------------------------------------------------------*/
588 static void
589 xml_parse_label_cd_node (xmlNodePtr   label_node,
590                          lglTemplate *template)
591 {
592         gchar               *id;
593         gdouble              waste;
594         gdouble              r1, r2, w, h;
595         lglTemplateFrame    *frame;
596         xmlNodePtr           node;
597
598         id    = lgl_xml_get_prop_string (label_node, "id", NULL);
599         waste = lgl_xml_get_prop_length (label_node, "waste", 0);
600         r1    = lgl_xml_get_prop_length (label_node, "radius", 0);
601         r2    = lgl_xml_get_prop_length (label_node, "hole", 0);
602         w     = lgl_xml_get_prop_length (label_node, "width", 0);
603         h     = lgl_xml_get_prop_length (label_node, "height", 0);
604
605         frame = lgl_template_frame_cd_new ((gchar *)id, r1, r2, w, h, waste);
606         lgl_template_add_frame (template, frame);
607
608         for (node = label_node->xmlChildrenNode; node != NULL; node = node->next)
609         {
610                 if (lgl_xml_is_node (node, "Layout"))
611                 {
612                         xml_parse_layout_node (node, frame);
613                 }
614                 else if (lgl_xml_is_node (node, "Markup-margin"))
615                 {
616                         xml_parse_markup_margin_node (node, frame);
617                 }
618                 else if (lgl_xml_is_node (node, "Markup-line"))
619                 {
620                         xml_parse_markup_line_node (node, frame);
621                 }
622                 else if (lgl_xml_is_node (node, "Markup-circle"))
623                 {
624                         xml_parse_markup_circle_node (node, frame);
625                 }
626                 else if (lgl_xml_is_node (node, "Markup-rect"))
627                 {
628                         xml_parse_markup_rect_node (node, frame);
629                 }
630                 else if (lgl_xml_is_node (node, "Markup-ellipse"))
631                 {
632                         xml_parse_markup_ellipse_node (node, frame);
633                 }
634                 else if (!xmlNodeIsText (node))
635                 {
636                         if (!lgl_xml_is_node (node, "comment"))
637                         {
638                                 g_message ("bad node =  \"%s\"",node->name);
639                         }
640                 }
641         }
642
643         g_free (id);
644 }
645
646 /*--------------------------------------------------------------------------*/
647 /* PRIVATE.  Parse XML Template->Label->Layout Node.                        */
648 /*--------------------------------------------------------------------------*/
649 static void
650 xml_parse_layout_node (xmlNodePtr          layout_node,
651                        lglTemplateFrame   *frame)
652 {
653         gint        nx, ny;
654         gdouble     x0, y0, dx, dy;
655         xmlNodePtr  node;
656
657         nx = lgl_xml_get_prop_int (layout_node, "nx", 1);
658         ny = lgl_xml_get_prop_int (layout_node, "ny", 1);
659
660         x0 = lgl_xml_get_prop_length (layout_node, "x0", 0);
661         y0 = lgl_xml_get_prop_length (layout_node, "y0", 0);
662
663         dx = lgl_xml_get_prop_length (layout_node, "dx", 0);
664         dy = lgl_xml_get_prop_length (layout_node, "dy", 0);
665
666         lgl_template_frame_add_layout (frame, lgl_template_layout_new (nx, ny, x0, y0, dx, dy));
667
668         for (node = layout_node->xmlChildrenNode; node != NULL; node = node->next)
669         {
670                 if (!xmlNodeIsText (node))
671                 {
672                         if (!lgl_xml_is_node (node, "comment"))
673                         {
674                                 g_message ("bad node =  \"%s\"",node->name);
675                         }
676                 }
677         }
678
679 }
680
681 /*--------------------------------------------------------------------------*/
682 /* PRIVATE.  Parse XML Template->Label->Markup-margin Node.                 */
683 /*--------------------------------------------------------------------------*/
684 static void
685 xml_parse_markup_margin_node (xmlNodePtr          markup_node,
686                               lglTemplateFrame   *frame)
687 {
688         gdouble     size;
689         xmlNodePtr  node;
690
691         size = lgl_xml_get_prop_length (markup_node, "size", 0);
692
693         lgl_template_frame_add_markup (frame, lgl_template_markup_margin_new (size));
694
695         for (node = markup_node->xmlChildrenNode; node != NULL; node = node->next)
696         {
697                 if (!xmlNodeIsText (node))
698                 {
699                         if (!lgl_xml_is_node (node, "comment"))
700                         {
701                                 g_message ("bad node =  \"%s\"",node->name);
702                         }
703                 }
704         }
705
706 }
707
708 /*--------------------------------------------------------------------------*/
709 /* PRIVATE.  Parse XML Template->Label->Markup-line Node.                   */
710 /*--------------------------------------------------------------------------*/
711 static void
712 xml_parse_markup_line_node (xmlNodePtr          markup_node,
713                             lglTemplateFrame   *frame)
714 {
715         gdouble     x1, y1, x2, y2;
716         xmlNodePtr  node;
717
718         x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
719         y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
720         x2 = lgl_xml_get_prop_length (markup_node, "x2", 0);
721         y2 = lgl_xml_get_prop_length (markup_node, "y2", 0);
722
723         lgl_template_frame_add_markup (frame, lgl_template_markup_line_new (x1, y1, x2, y2));
724
725         for (node = markup_node->xmlChildrenNode; node != NULL; node = node->next)
726         {
727                 if (!xmlNodeIsText (node))
728                 {
729                         if (!lgl_xml_is_node (node, "comment"))
730                         {
731                                 g_message ("bad node =  \"%s\"",node->name);
732                         }
733                 }
734         }
735
736 }
737
738 /*--------------------------------------------------------------------------*/
739 /* PRIVATE.  Parse XML Template->Label->Markup-circle Node.                 */
740 /*--------------------------------------------------------------------------*/
741 static void
742 xml_parse_markup_circle_node (xmlNodePtr          markup_node,
743                               lglTemplateFrame   *frame)
744 {
745         gdouble     x0, y0, r;
746         xmlNodePtr  node;
747
748         x0 = lgl_xml_get_prop_length (markup_node, "x0", 0);
749         y0 = lgl_xml_get_prop_length (markup_node, "y0", 0);
750         r  = lgl_xml_get_prop_length (markup_node, "radius", 0);
751
752         lgl_template_frame_add_markup (frame, lgl_template_markup_circle_new (x0, y0, r));
753
754         for (node = markup_node->xmlChildrenNode; node != NULL; node = node->next)
755         {
756                 if (!xmlNodeIsText (node))
757                 {
758                         if (!lgl_xml_is_node (node, "comment"))
759                         {
760                                 g_message ("bad node =  \"%s\"",node->name);
761                         }
762                 }
763         }
764
765 }
766
767
768 /*--------------------------------------------------------------------------*/
769 /* PRIVATE.  Parse XML Template->Label->Markup-rect Node.                   */
770 /*--------------------------------------------------------------------------*/
771 static void
772 xml_parse_markup_rect_node (xmlNodePtr          markup_node,
773                             lglTemplateFrame   *frame)
774 {
775         gdouble     x1, y1, w, h, r;
776         xmlNodePtr  node;
777
778         x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
779         y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
780         w  = lgl_xml_get_prop_length (markup_node, "w", 0);
781         h  = lgl_xml_get_prop_length (markup_node, "h", 0);
782         r  = lgl_xml_get_prop_length (markup_node, "r", 0);
783
784         lgl_template_frame_add_markup (frame, lgl_template_markup_rect_new (x1, y1, w, h, r));
785
786         for (node = markup_node->xmlChildrenNode; node != NULL; node = node->next)
787         {
788                 if (!xmlNodeIsText (node))
789                 {
790                         if (!lgl_xml_is_node (node, "comment"))
791                         {
792                                 g_message ("bad node =  \"%s\"",node->name);
793                         }
794                 }
795         }
796
797 }
798
799
800 /*--------------------------------------------------------------------------*/
801 /* PRIVATE.  Parse XML Template->Label->Markup-ellipse Node.                */
802 /*--------------------------------------------------------------------------*/
803 static void
804 xml_parse_markup_ellipse_node (xmlNodePtr          markup_node,
805                                lglTemplateFrame   *frame)
806 {
807         gdouble     x1, y1, w, h;
808         xmlNodePtr  node;
809
810         x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
811         y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
812         w  = lgl_xml_get_prop_length (markup_node, "w", 0);
813         h  = lgl_xml_get_prop_length (markup_node, "h", 0);
814
815         lgl_template_frame_add_markup (frame, lgl_template_markup_ellipse_new (x1, y1, w, h));
816
817         for (node = markup_node->xmlChildrenNode; node != NULL; node = node->next)
818         {
819                 if (!xmlNodeIsText (node))
820                 {
821                         if (!lgl_xml_is_node (node, "comment"))
822                         {
823                                 g_message ("bad node =  \"%s\"",node->name);
824                         }
825                 }
826         }
827
828 }
829
830
831 /*--------------------------------------------------------------------------*/
832 /* PRIVATE.  Parse deprecated XML Template->Alias Node.                     */
833 /*--------------------------------------------------------------------------*/
834 static void
835 xml_parse_alias_node (xmlNodePtr   alias_node,
836                       lglTemplate *template)
837 {
838         g_message ("Skipping deprecated \"Alias\" node.");
839 }
840
841
842 /**
843  * lgl_xml_template_write_templates_to_file:
844  * @templates:      List of #lglTemplate structures
845  * @utf8_filename:  Filename of templates file (name encoded as UTF-8)
846  *
847  * Write a list of #lglTemplate structures to a glabels XML template file.
848  *
849  * Returns: the number of bytes written or -1 in case of failure
850  *
851  */
852 gint
853 lgl_xml_template_write_templates_to_file (GList       *templates,
854                                           const gchar *utf8_filename)
855 {
856         xmlDocPtr    doc;
857         xmlNsPtr     ns;
858         gint         bytes_written;
859         GList       *p;
860         lglTemplate *template;
861         gchar       *filename;
862
863         doc = xmlNewDoc ((xmlChar *)"1.0");
864         doc->xmlRootNode = xmlNewDocNode (doc, NULL, (xmlChar *)"Glabels-templates", NULL);
865
866         ns = xmlNewNs (doc->xmlRootNode, (xmlChar *)LGL_XML_NAME_SPACE, NULL);
867         xmlSetNs (doc->xmlRootNode, ns);
868
869         for (p=templates; p!=NULL; p=p->next)
870         {
871                 template = (lglTemplate *)p->data;
872                 lgl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
873         }
874
875         filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
876         if (!filename)
877         {
878                 g_message ("Utf8 conversion error.");
879                 return -1;
880         }
881         else
882         {
883                 xmlSetDocCompressMode (doc, 0);
884                 bytes_written = xmlSaveFormatFile (filename, doc, TRUE);
885                 xmlFreeDoc (doc);
886                 g_free (filename);
887                 return bytes_written;
888         }
889
890 }
891
892
893 /**
894  * lgl_xml_template_write_template_to_file:
895  * @template:       #lglTemplate structure to be written
896  * @utf8_filename:  Filename of templates file (name encoded as UTF-8)
897  *
898  * Write a single #lglTemplate structures to a glabels XML template file.
899  *
900  * Returns: the number of bytes written or -1 in case of failure
901  *
902  */
903 gint
904 lgl_xml_template_write_template_to_file (const lglTemplate  *template,
905                                          const gchar        *utf8_filename)
906 {
907         GList     *templates = NULL;
908         gint       bytes_written;
909
910         templates = g_list_append (templates, (gpointer)template);
911
912         bytes_written = lgl_xml_template_write_templates_to_file (templates, utf8_filename);
913
914         g_list_free (templates);
915
916         return bytes_written;
917 }
918
919
920 /**
921  * lgl_xml_template_create_template_node:
922  * @template:       #lglTemplate structure to be written
923  * @root:           parent node to receive new child node
924  * @ns:             a libxml #xmlNsPtr
925  *
926  * Add a single #lglTemplate child node to given #xmlNodePtr.
927  *
928  */
929 void
930 lgl_xml_template_create_template_node (const lglTemplate *template,
931                                        xmlNodePtr         root,
932                                        const xmlNsPtr     ns)
933 {
934         xmlNodePtr          node;
935         GList              *p;
936         lglTemplateFrame   *frame;
937
938         node = xmlNewChild (root, ns, (xmlChar *)"Template", NULL);
939
940         lgl_xml_set_prop_string (node, "brand", template->brand);
941         lgl_xml_set_prop_string (node, "part", template->part);
942
943         lgl_xml_set_prop_string (node, "size", template->paper_id);
944         if (xmlStrEqual ((xmlChar *)template->paper_id, (xmlChar *)"Other"))
945         {
946
947                 lgl_xml_set_prop_length (node, "width", template->page_width);
948                 lgl_xml_set_prop_length (node, "height", template->page_height);
949
950         }
951
952         lgl_xml_set_prop_string (node, "description", template->description);
953
954         xml_create_meta_node ("product_url", template->product_url, node, ns );
955         for ( p=template->category_ids; p != NULL; p=p->next )
956         {
957                 xml_create_meta_node ( "category", p->data, node, ns );
958         }
959         for ( p=template->frames; p != NULL; p=p->next )
960         {
961                 frame = (lglTemplateFrame *)p->data;
962                 xml_create_label_node (frame, node, ns);
963         }
964
965 }
966
967 /*--------------------------------------------------------------------------*/
968 /* PRIVATE.  Add XML Template->Meta Node with category.                     */
969 /*--------------------------------------------------------------------------*/
970 static void
971 xml_create_meta_node (const gchar      *attr,
972                       const gchar      *value,
973                       xmlNodePtr        root,
974                       const xmlNsPtr    ns)
975 {
976         xmlNodePtr node;
977
978         if ( value != NULL )
979         {
980                 node = xmlNewChild (root, ns, (xmlChar *)"Meta", NULL);
981                 lgl_xml_set_prop_string (node, attr, value);
982         }
983
984 }
985
986 /*--------------------------------------------------------------------------*/
987 /* PRIVATE.  Add XML Template->Label Node.                                  */
988 /*--------------------------------------------------------------------------*/
989 static void
990 xml_create_label_node (const lglTemplateFrame  *frame,
991                        xmlNodePtr               root,
992                        const xmlNsPtr           ns)
993 {
994         xmlNodePtr        node;
995         GList            *p;
996         lglTemplateMarkup *markup;
997         lglTemplateLayout *layout;
998
999         switch (frame->shape)
1000         {
1001
1002         case LGL_TEMPLATE_FRAME_SHAPE_RECT:
1003                 node = xmlNewChild(root, ns, (xmlChar *)"Label-rectangle", NULL);
1004                 lgl_xml_set_prop_string (node, "id",      frame->all.id);
1005                 lgl_xml_set_prop_length (node, "width",   frame->rect.w);
1006                 lgl_xml_set_prop_length (node, "height",  frame->rect.h);
1007                 lgl_xml_set_prop_length (node, "round",   frame->rect.r);
1008                 lgl_xml_set_prop_length (node, "x_waste", frame->rect.x_waste);
1009                 lgl_xml_set_prop_length (node, "y_waste", frame->rect.y_waste);
1010                 break;
1011
1012         case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
1013                 node = xmlNewChild(root, ns, (xmlChar *)"Label-ellipse", NULL);
1014                 lgl_xml_set_prop_string (node, "id",     frame->all.id);
1015                 lgl_xml_set_prop_length (node, "width",  frame->ellipse.w);
1016                 lgl_xml_set_prop_length (node, "height", frame->ellipse.h);
1017                 lgl_xml_set_prop_length (node, "waste",  frame->ellipse.waste);
1018                 break;
1019
1020         case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
1021                 node = xmlNewChild(root, ns, (xmlChar *)"Label-round", NULL);
1022                 lgl_xml_set_prop_string (node, "id",      frame->all.id);
1023                 lgl_xml_set_prop_length (node, "radius",  frame->round.r);
1024                 lgl_xml_set_prop_length (node, "waste",   frame->round.waste);
1025                 break;
1026
1027         case LGL_TEMPLATE_FRAME_SHAPE_CD:
1028                 node = xmlNewChild(root, ns, (xmlChar *)"Label-cd", NULL);
1029                 lgl_xml_set_prop_string (node, "id",     frame->all.id);
1030                 lgl_xml_set_prop_length (node, "radius", frame->cd.r1);
1031                 lgl_xml_set_prop_length (node, "hole",   frame->cd.r2);
1032                 if (frame->cd.w != 0.0)
1033                 {
1034                         lgl_xml_set_prop_length (node, "width",  frame->cd.w);
1035                 }
1036                 if (frame->cd.h != 0.0)
1037                 {
1038                         lgl_xml_set_prop_length (node, "height", frame->cd.h);
1039                 }
1040                 lgl_xml_set_prop_length (node, "waste",  frame->cd.waste);
1041                 break;
1042
1043         default:
1044                 g_message ("Unknown label style");
1045                 return;
1046                 break;
1047
1048         }
1049
1050         for ( p=frame->all.markups; p != NULL; p=p->next )
1051         {
1052                 markup = (lglTemplateMarkup *)p->data;
1053                 switch (markup->type)
1054                 {
1055                 case LGL_TEMPLATE_MARKUP_MARGIN:
1056                         xml_create_markup_margin_node (markup, node, ns);
1057                         break;
1058                 case LGL_TEMPLATE_MARKUP_LINE:
1059                         xml_create_markup_line_node (markup, node, ns);
1060                         break;
1061                 case LGL_TEMPLATE_MARKUP_CIRCLE:
1062                         xml_create_markup_circle_node (markup, node, ns);
1063                         break;
1064                 case LGL_TEMPLATE_MARKUP_RECT:
1065                         xml_create_markup_rect_node (markup, node, ns);
1066                         break;
1067                 case LGL_TEMPLATE_MARKUP_ELLIPSE:
1068                         xml_create_markup_ellipse_node (markup, node, ns);
1069                         break;
1070                 default:
1071                         g_message ("Unknown markup type");
1072                         break;
1073                 }
1074         }
1075
1076         for ( p=frame->all.layouts; p != NULL; p=p->next )
1077         {
1078                 layout = (lglTemplateLayout *)p->data;
1079                 xml_create_layout_node (layout, node, ns);
1080         }
1081
1082 }
1083
1084 /*--------------------------------------------------------------------------*/
1085 /* PRIVATE.  Add XML Template->Label->Layout Node.                          */
1086 /*--------------------------------------------------------------------------*/
1087 static void
1088 xml_create_layout_node (const lglTemplateLayout *layout,
1089                         xmlNodePtr               root,
1090                         const xmlNsPtr           ns)
1091 {
1092         xmlNodePtr  node;
1093
1094         node = xmlNewChild(root, ns, (xmlChar *)"Layout", NULL);
1095         lgl_xml_set_prop_int (node, "nx", layout->nx);
1096         lgl_xml_set_prop_int (node, "ny", layout->ny);
1097         lgl_xml_set_prop_length (node, "x0", layout->x0);
1098         lgl_xml_set_prop_length (node, "y0", layout->y0);
1099         lgl_xml_set_prop_length (node, "dx", layout->dx);
1100         lgl_xml_set_prop_length (node, "dy", layout->dy);
1101
1102 }
1103
1104 /*--------------------------------------------------------------------------*/
1105 /* PRIVATE.  Add XML Template->Label->Markup-margin Node.                   */
1106 /*--------------------------------------------------------------------------*/
1107 static void
1108 xml_create_markup_margin_node (const lglTemplateMarkup  *markup,
1109                                xmlNodePtr                root,
1110                                const xmlNsPtr            ns)
1111 {
1112         xmlNodePtr  node;
1113
1114         node = xmlNewChild(root, ns, (xmlChar *)"Markup-margin", NULL);
1115
1116         lgl_xml_set_prop_length (node, "size", markup->margin.size);
1117
1118 }
1119
1120 /*--------------------------------------------------------------------------*/
1121 /* PRIVATE.  Add XML Template->Label->Markup-line Node.                     */
1122 /*--------------------------------------------------------------------------*/
1123 static void
1124 xml_create_markup_line_node (const lglTemplateMarkup *markup,
1125                              xmlNodePtr               root,
1126                              const xmlNsPtr           ns)
1127 {
1128         xmlNodePtr  node;
1129
1130         node = xmlNewChild(root, ns, (xmlChar *)"Markup-line", NULL);
1131
1132         lgl_xml_set_prop_length (node, "x1", markup->line.x1);
1133         lgl_xml_set_prop_length (node, "y1", markup->line.y1);
1134         lgl_xml_set_prop_length (node, "x2", markup->line.x2);
1135         lgl_xml_set_prop_length (node, "y2", markup->line.y2);
1136
1137 }
1138
1139 /*--------------------------------------------------------------------------*/
1140 /* PRIVATE.  Add XML Template->Label->Markup-circle Node.                   */
1141 /*--------------------------------------------------------------------------*/
1142 static void
1143 xml_create_markup_circle_node (const lglTemplateMarkup *markup,
1144                                xmlNodePtr               root,
1145                                const xmlNsPtr           ns)
1146 {
1147         xmlNodePtr  node;
1148
1149         node = xmlNewChild(root, ns, (xmlChar *)"Markup-circle", NULL);
1150
1151         lgl_xml_set_prop_length (node, "x0",     markup->circle.x0);
1152         lgl_xml_set_prop_length (node, "y0",     markup->circle.y0);
1153         lgl_xml_set_prop_length (node, "radius", markup->circle.r);
1154
1155 }
1156
1157
1158 /*--------------------------------------------------------------------------*/
1159 /* PRIVATE.  Add XML Template->Label->Markup-rect Node.                     */
1160 /*--------------------------------------------------------------------------*/
1161 static void
1162 xml_create_markup_rect_node (const lglTemplateMarkup *markup,
1163                              xmlNodePtr               root,
1164                              const xmlNsPtr           ns)
1165 {
1166         xmlNodePtr  node;
1167
1168         node = xmlNewChild(root, ns, (xmlChar *)"Markup-rect", NULL);
1169
1170         lgl_xml_set_prop_length (node, "x1", markup->rect.x1);
1171         lgl_xml_set_prop_length (node, "y1", markup->rect.y1);
1172         lgl_xml_set_prop_length (node, "w",  markup->rect.w);
1173         lgl_xml_set_prop_length (node, "h",  markup->rect.h);
1174         lgl_xml_set_prop_length (node, "r",  markup->rect.r);
1175
1176 }
1177
1178
1179 /*--------------------------------------------------------------------------*/
1180 /* PRIVATE.  Add XML Template->Label->Markup-ellipse Node.                  */
1181 /*--------------------------------------------------------------------------*/
1182 static void
1183 xml_create_markup_ellipse_node (const lglTemplateMarkup *markup,
1184                                 xmlNodePtr               root,
1185                                 const xmlNsPtr           ns)
1186 {
1187         xmlNodePtr  node;
1188
1189         node = xmlNewChild(root, ns, (xmlChar *)"Markup-ellipse", NULL);
1190
1191         lgl_xml_set_prop_length (node, "x1", markup->ellipse.x1);
1192         lgl_xml_set_prop_length (node, "y1", markup->ellipse.y1);
1193         lgl_xml_set_prop_length (node, "w",  markup->ellipse.w);
1194         lgl_xml_set_prop_length (node, "h",  markup->ellipse.h);
1195
1196 }
1197
1198
1199
1200 /*
1201  * Local Variables:       -- emacs
1202  * mode: C                -- emacs
1203  * c-basic-offset: 8      -- emacs
1204  * tab-width: 8           -- emacs
1205  * indent-tabs-mode: nil  -- emacs
1206  * End:                   -- emacs
1207  */