2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * template.c: template 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
26 #include <libgnomeprint/gnome-print-paper.h>
34 #define GL_DATA_DIR gnome_program_locate_file (NULL,\
35 GNOME_FILE_DOMAIN_APP_DATADIR,\
39 #define FULL_PAGE "Full-page"
41 /*===========================================*/
43 /*===========================================*/
45 /*===========================================*/
47 /*===========================================*/
49 static GList *templates = NULL;
51 /*===========================================*/
52 /* Local function prototypes */
53 /*===========================================*/
54 static glTemplate *template_full_page (const gchar *page_size);
56 static GList *read_templates (void);
58 static gchar *get_home_data_dir (void);
59 static GList *read_template_files_from_dir (GList *templates,
60 const gchar *dirname);
61 static GList *read_templates_from_file (GList *templates,
64 static void xml_parse_label (xmlNodePtr label_node,
65 glTemplate *template);
66 static void xml_parse_layout (xmlNodePtr layout_node,
67 glTemplate *template);
68 static void xml_parse_markup (xmlNodePtr markup_node,
69 glTemplate *template);
70 static void xml_parse_alias (xmlNodePtr alias_node,
71 glTemplate *template);
73 static void xml_add_label (const glTemplate *template,
76 static void xml_add_layout (glTemplateLayout *layout,
79 static void xml_add_markup_margin (glTemplateMarkupMargin *margin,
82 static void xml_add_alias (gchar *name,
86 static gint compare_origins (gconstpointer a,
90 static glTemplateLayout *layout_new (gdouble nx,
96 static glTemplateLayout *layout_dup (glTemplateLayout *orig_layout);
97 static void layout_free (glTemplateLayout **layout);
99 static glTemplateMarkup *markup_margin_new (gdouble size);
100 static glTemplateMarkup *markup_dup (glTemplateMarkup *orig_markup);
101 static void markup_free (glTemplateMarkup **markup);
103 /*****************************************************************************/
104 /* Initialize module. */
105 /*****************************************************************************/
107 gl_template_init (void)
109 GList *page_sizes, *p;
111 gl_debug (DEBUG_TEMPLATE, "START");
113 templates = read_templates ();
115 page_sizes = gl_template_get_page_size_list ();
116 for ( p=page_sizes; p != NULL; p=p->next ) {
117 templates = g_list_append (templates,
118 template_full_page (p->data));
120 gl_template_free_page_size_list (&page_sizes);
122 gl_debug (DEBUG_TEMPLATE, "END");
125 /*****************************************************************************/
126 /* Get a list of valid page size names */
127 /*****************************************************************************/
129 gl_template_get_page_size_list (void)
132 GList *p, *paper_list;
133 GnomePrintPaper *paper;
135 gl_debug (DEBUG_TEMPLATE, "START");
137 paper_list = gnome_print_paper_get_list();
138 for ( p=paper_list; p != NULL; p=p->next ) {
139 paper = (GnomePrintPaper *)p->data;
140 if ( g_strcasecmp(paper->name, "custom") != 0 ) {
141 names = g_list_append (names, g_strdup (paper->name));
145 gl_debug (DEBUG_TEMPLATE, "END");
149 /*****************************************************************************/
150 /* Free a list of page size names. */
151 /*****************************************************************************/
153 gl_template_free_page_size_list (GList ** names)
157 gl_debug (DEBUG_TEMPLATE, "START");
159 for (p_name = *names; p_name != NULL; p_name = p_name->next) {
160 g_free (p_name->data);
164 g_list_free (*names);
167 gl_debug (DEBUG_TEMPLATE, "END");
170 /*****************************************************************************/
171 /* Get a list of valid template names for given page size */
172 /*****************************************************************************/
174 gl_template_get_name_list (const gchar * page_size)
176 GList *p_tmplt, *p_name;
177 glTemplate *template;
181 gl_debug (DEBUG_TEMPLATE, "START");
183 for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next) {
184 template = (glTemplate *) p_tmplt->data;
185 if (g_strcasecmp (page_size, template->page_size) == 0) {
186 for (p_name = template->name; p_name != NULL;
187 p_name = p_name->next) {
188 str = g_strdup_printf("%s: %s",
189 (gchar *) p_name->data,
190 template->description);
191 names = g_list_insert_sorted (names, str,
192 (GCompareFunc)g_strcasecmp);
197 gl_debug (DEBUG_TEMPLATE, "templates = %p", templates);
198 gl_debug (DEBUG_TEMPLATE, "names = %p", names);
200 gl_debug (DEBUG_TEMPLATE, "END");
204 /*****************************************************************************/
205 /* Free a list of template names. */
206 /*****************************************************************************/
208 gl_template_free_name_list (GList ** names)
212 gl_debug (DEBUG_TEMPLATE, "START");
214 for (p_name = *names; p_name != NULL; p_name = p_name->next) {
215 g_free (p_name->data);
219 g_list_free (*names);
222 gl_debug (DEBUG_TEMPLATE, "END");
225 /*****************************************************************************/
226 /* Return a template structure from a name. */
227 /*****************************************************************************/
229 gl_template_from_name (const gchar * name)
231 GList *p_tmplt, *p_name;
232 glTemplate *template;
235 gl_debug (DEBUG_TEMPLATE, "START");
238 /* If no name, return first template as a default */
239 return (glTemplate *) templates->data;
242 split_name = g_strsplit (name, ":", 2);
244 for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next) {
245 template = (glTemplate *) p_tmplt->data;
246 for (p_name = template->name; p_name != NULL;
247 p_name = p_name->next) {
248 if (g_strcasecmp (p_name->data, split_name[0]) == 0) {
249 g_strfreev (split_name);
250 gl_debug (DEBUG_TEMPLATE, "END");
251 return gl_template_dup (template);
256 g_strfreev (split_name);
258 gl_debug (DEBUG_TEMPLATE, "END");
262 /*****************************************************************************/
263 /* Copy a template. */
264 /*****************************************************************************/
265 glTemplate *gl_template_dup (const glTemplate *orig_template)
267 glTemplate *template;
269 glTemplateLayout *layout;
270 glTemplateMarkup *markup;
272 gl_debug (DEBUG_TEMPLATE, "START");
274 template = g_new0 (glTemplate,1);
276 template->name = NULL;
277 for ( p=orig_template->name; p != NULL; p=p->next ) {
278 template->name = g_list_append (template->name,
281 template->description = g_strdup (orig_template->description);
282 template->page_size = g_strdup (orig_template->page_size);
284 template->label = orig_template->label;
286 template->label.any.layouts = NULL;
287 for ( p=orig_template->label.any.layouts; p != NULL; p=p->next ) {
288 layout = (glTemplateLayout *)p->data;
289 template->label.any.layouts =
290 g_list_append (template->label.any.layouts,
291 layout_dup (layout));
294 template->label.any.markups = NULL;
295 for ( p=orig_template->label.any.markups; p != NULL; p=p->next ) {
296 markup = (glTemplateMarkup *)p->data;
297 template->label.any.markups =
298 g_list_append (template->label.any.markups,
299 markup_dup (markup));
302 gl_debug (DEBUG_TEMPLATE, "END");
306 /*****************************************************************************/
307 /* Free up a template. */
308 /*****************************************************************************/
309 void gl_template_free (glTemplate **template)
313 gl_debug (DEBUG_TEMPLATE, "START");
315 if ( *template != NULL ) {
317 for ( p=(*template)->name; p != NULL; p=p->next ) {
321 g_list_free ((*template)->name);
322 (*template)->name = NULL;
324 g_free ((*template)->description);
325 (*template)->description = NULL;
327 g_free ((*template)->page_size);
328 (*template)->page_size = NULL;
330 for ( p=(*template)->label.any.layouts; p != NULL; p=p->next ) {
331 layout_free ((glTemplateLayout **)&p->data);
333 g_list_free ((*template)->label.any.layouts);
334 (*template)->label.any.layouts = NULL;
336 for ( p=(*template)->label.any.markups; p != NULL; p=p->next ) {
337 markup_free ((glTemplateMarkup **)&p->data);
339 g_list_free ((*template)->label.any.markups);
340 (*template)->label.any.markups = NULL;
347 gl_debug (DEBUG_TEMPLATE, "END");
350 /*--------------------------------------------------------------------------*/
351 /* PRIVATE. Make a template for a full page of the given page size. */
352 /*--------------------------------------------------------------------------*/
354 template_full_page (const gchar *page_size)
356 const GnomePrintPaper *paper;
357 glTemplate *template;
359 paper = gnome_print_paper_get_by_name (page_size);
360 if ( paper == NULL ) {
364 template = g_new0 (glTemplate, 1);
366 template->name = g_list_append (template->name,
367 g_strdup_printf("*%s", page_size));
368 template->page_size = g_strdup(page_size);
369 template->description = g_strdup(FULL_PAGE);
371 template->label.style = GL_TEMPLATE_STYLE_RECT;
372 template->label.rect.w = paper->width;
373 template->label.rect.h = paper->height;
374 template->label.rect.r = 0.0;
376 template->label.any.layouts =
377 g_list_append (template->label.any.layouts,
378 layout_new (1, 1, 0., 0., 0., 0.));
380 template->label.any.markups =
381 g_list_append (template->label.any.markups,
382 markup_margin_new (5.0));
387 /*--------------------------------------------------------------------------*/
388 /* PRIVATE. Read templates from various files. */
389 /*--------------------------------------------------------------------------*/
391 read_templates (void)
393 gchar *home_data_dir = get_home_data_dir ();
394 GList *templates = NULL;
396 gl_debug (DEBUG_TEMPLATE, "START");
400 templates = read_template_files_from_dir (templates, GL_DATA_DIR);
401 templates = read_template_files_from_dir (templates, home_data_dir);
403 g_free (home_data_dir);
405 if (templates == NULL) {
406 g_warning (_("No template files found!"));
409 gl_debug (DEBUG_TEMPLATE, "END");
413 /*--------------------------------------------------------------------------*/
414 /* PRIVATE. get '~/.glabels' directory path. */
415 /*--------------------------------------------------------------------------*/
417 get_home_data_dir (void)
419 gchar *dir = gnome_util_prepend_user_home (".glabels");
421 gl_debug (DEBUG_TEMPLATE, "START");
423 /* Try to create ~/.glabels directory. If it exists, no problem. */
426 gl_debug (DEBUG_TEMPLATE, "END");
430 /*--------------------------------------------------------------------------*/
431 /* PRIVATE. Read all template files from given directory. Append to list. */
432 /*--------------------------------------------------------------------------*/
434 read_template_files_from_dir (GList * templates,
435 const gchar * dirname)
438 const gchar *filename, *extension;
439 gchar *full_filename = NULL;
440 GError *gerror = NULL;
442 gl_debug (DEBUG_TEMPLATE, "START");
447 dp = g_dir_open (dirname, 0, &gerror);
448 if (gerror != NULL) {
449 g_warning ("cannot open data directory: %s", gerror->message );
450 gl_debug (DEBUG_TEMPLATE, "END");
454 while ((filename = g_dir_read_name (dp)) != NULL) {
456 extension = strrchr (filename, '.');
458 if (extension != NULL) {
460 if (strcasecmp (extension, ".template") == 0) {
463 g_build_filename (dirname, filename, NULL);
465 read_templates_from_file (templates,
467 g_free (full_filename);
477 gl_debug (DEBUG_TEMPLATE, "END");
481 /*--------------------------------------------------------------------------*/
482 /* PRIVATE. Read templates from template file. */
483 /*--------------------------------------------------------------------------*/
485 read_templates_from_file (GList * templates,
486 gchar * xml_filename)
489 xmlNodePtr root, node;
490 glTemplate *template;
492 gl_debug (DEBUG_TEMPLATE, "START");
494 doc = xmlParseFile (xml_filename);
496 g_warning ("\"%s\" is not a glabels template file (not XML)",
501 root = xmlDocGetRootElement (doc);
502 if (!root || !root->name) {
503 g_warning ("\"%s\" is not a glabels template file (no root node)",
508 if (g_strcasecmp (root->name, "glabels-templates") != 0) {
509 g_warning ("\"%s\" is not a glabels template file (wrong root node)",
515 for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
517 if (g_strcasecmp (node->name, "Sheet") == 0) {
518 template = gl_template_xml_parse_sheet (node);
519 templates = g_list_append (templates, template);
521 if ( !xmlNodeIsText(node) ) {
522 if (g_strcasecmp (node->name,"comment") != 0) {
523 g_warning ("bad node = \"%s\"",node->name);
531 gl_debug (DEBUG_TEMPLATE, "END");
535 /*****************************************************************************/
536 /* Parse XML template Node. */
537 /*****************************************************************************/
539 gl_template_xml_parse_sheet (xmlNodePtr sheet_node)
541 glTemplate *template;
544 gl_debug (DEBUG_TEMPLATE, "START");
546 template = g_new0 (glTemplate, 1);
548 template->name = g_list_append (template->name,
549 xmlGetProp (sheet_node, "name"));
550 template->page_size = xmlGetProp (sheet_node, "size");
551 if ( strcmp (template->page_size,"US-Letter") == 0 ) {
552 /* Compatibility with old pre-1.0 template files.*/
553 template->page_size = "US Letter";
555 template->description = xmlGetProp (sheet_node, "description");
557 for (node = sheet_node->xmlChildrenNode; node != NULL;
559 if (g_strcasecmp (node->name, "Label") == 0) {
560 xml_parse_label (node, template);
561 } else if (g_strcasecmp (node->name, "Alias") == 0) {
562 xml_parse_alias (node, template);
564 if (g_strcasecmp (node->name, "text") != 0) {
565 g_warning ("bad node = \"%s\"", node->name);
570 gl_debug (DEBUG_TEMPLATE, "END");
575 /*--------------------------------------------------------------------------*/
576 /* PRIVATE. Parse XML Sheet->Label Node. */
577 /*--------------------------------------------------------------------------*/
579 xml_parse_label (xmlNodePtr label_node,
580 glTemplate * template)
585 gl_debug (DEBUG_TEMPLATE, "START");
587 style = xmlGetProp (label_node, "style");
588 if (g_strcasecmp (style, "rectangle") == 0) {
589 template->label.style = GL_TEMPLATE_STYLE_RECT;
590 } else if (g_strcasecmp (style, "round") == 0) {
591 template->label.style = GL_TEMPLATE_STYLE_ROUND;
592 } else if (g_strcasecmp (style, "cd") == 0) {
593 template->label.style = GL_TEMPLATE_STYLE_CD;
595 template->label.style = GL_TEMPLATE_STYLE_RECT;
596 g_warning ("Unknown label style in template");
599 switch (template->label.style) {
600 case GL_TEMPLATE_STYLE_RECT:
601 template->label.rect.w =
602 g_strtod (xmlGetProp (label_node, "width"), NULL);
603 template->label.rect.h =
604 g_strtod (xmlGetProp (label_node, "height"), NULL);
605 template->label.rect.r =
606 g_strtod (xmlGetProp (label_node, "round"), NULL);
608 case GL_TEMPLATE_STYLE_ROUND:
609 template->label.round.r =
610 g_strtod (xmlGetProp (label_node, "radius"), NULL);
612 case GL_TEMPLATE_STYLE_CD:
613 template->label.cd.r1 =
614 g_strtod (xmlGetProp (label_node, "radius"), NULL);
615 template->label.cd.r2 =
616 g_strtod (xmlGetProp (label_node, "hole"), NULL);
622 for (node = label_node->xmlChildrenNode; node != NULL;
624 if (g_strcasecmp (node->name, "Layout") == 0) {
625 xml_parse_layout (node, template);
626 } else if (g_strcasecmp (node->name, "Markup") == 0) {
627 xml_parse_markup (node, template);
628 } else if (g_strcasecmp (node->name, "text") != 0) {
629 g_warning ("bad node = \"%s\"", node->name);
633 gl_debug (DEBUG_TEMPLATE, "END");
636 /*--------------------------------------------------------------------------*/
637 /* PRIVATE. Parse XML Sheet->Label->Layout Node. */
638 /*--------------------------------------------------------------------------*/
640 xml_parse_layout (xmlNodePtr layout_node,
641 glTemplate * template)
644 gdouble x0, y0, dx, dy;
647 gl_debug (DEBUG_TEMPLATE, "START");
649 sscanf (xmlGetProp (layout_node, "nx"), "%d", &nx);
650 sscanf (xmlGetProp (layout_node, "ny"), "%d", &ny);
651 x0 = g_strtod (xmlGetProp (layout_node, "x0"), NULL);
652 y0 = g_strtod (xmlGetProp (layout_node, "y0"), NULL);
653 dx = g_strtod (xmlGetProp (layout_node, "dx"), NULL);
654 dy = g_strtod (xmlGetProp (layout_node, "dy"), NULL);
656 for (node = layout_node->xmlChildrenNode; node != NULL;
658 if (g_strcasecmp (node->name, "text") != 0) {
659 g_warning ("bad node = \"%s\"", node->name);
663 template->label.any.layouts =
664 g_list_append (template->label.any.layouts,
665 layout_new (nx, ny, x0, y0, dx, dy));
667 gl_debug (DEBUG_TEMPLATE, "END");
670 /*--------------------------------------------------------------------------*/
671 /* PRIVATE. Parse XML Sheet->Label->Markup Node. */
672 /*--------------------------------------------------------------------------*/
674 xml_parse_markup (xmlNodePtr markup_node,
675 glTemplate * template)
681 gl_debug (DEBUG_TEMPLATE, "START");
683 type = xmlGetProp (markup_node, "type");
684 if (g_strcasecmp (type, "margin") == 0) {
685 size = g_strtod (xmlGetProp (markup_node, "size"), NULL);
686 template->label.any.markups =
687 g_list_append (template->label.any.markups,
688 markup_margin_new (size));
691 for (node = markup_node->xmlChildrenNode; node != NULL;
693 if (g_strcasecmp (node->name, "text") != 0) {
694 g_warning ("bad node = \"%s\"", node->name);
698 gl_debug (DEBUG_TEMPLATE, "END");
701 /*--------------------------------------------------------------------------*/
702 /* PRIVATE. Parse XML Sheet->Alias Node. */
703 /*--------------------------------------------------------------------------*/
705 xml_parse_alias (xmlNodePtr alias_node,
706 glTemplate * template)
708 gl_debug (DEBUG_TEMPLATE, "START");
710 template->name = g_list_append (template->name,
711 xmlGetProp (alias_node, "name"));
713 gl_debug (DEBUG_TEMPLATE, "END");
716 /****************************************************************************/
717 /* Add XML Template Node */
718 /****************************************************************************/
720 gl_template_xml_add_sheet (const glTemplate * template,
727 gl_debug (DEBUG_TEMPLATE, "START");
729 node = xmlNewChild (root, ns, "Sheet", NULL);
731 xmlSetProp (node, "name", template->name->data);
732 xmlSetProp (node, "size", template->page_size);
733 xmlSetProp (node, "description", template->description);
735 xml_add_label (template, node, ns);
737 for ( p=template->name->next; p != NULL; p=p->next ) {
738 xml_add_alias( p->data, node, ns );
741 gl_debug (DEBUG_TEMPLATE, "END");
744 /*--------------------------------------------------------------------------*/
745 /* PRIVATE. Add XML Sheet->Label Node. */
746 /*--------------------------------------------------------------------------*/
748 xml_add_label (const glTemplate *template,
755 glTemplateMarkup *markup;
756 glTemplateLayout *layout;
758 gl_debug (DEBUG_TEMPLATE, "START");
760 node = xmlNewChild(root, ns, "Label", NULL);
762 xmlSetProp (node, "id", "0");
764 switch (template->label.style) {
765 case GL_TEMPLATE_STYLE_RECT:
766 xmlSetProp (node, "style", "rectangle");
767 string = g_strdup_printf ("%g", template->label.rect.w);
768 xmlSetProp (node, "width", string);
770 string = g_strdup_printf ("%g", template->label.rect.h);
771 xmlSetProp (node, "height", string);
773 string = g_strdup_printf ("%g", template->label.rect.r);
774 xmlSetProp (node, "round", string);
777 case GL_TEMPLATE_STYLE_ROUND:
778 xmlSetProp (node, "style", "round");
779 string = g_strdup_printf ("%g", template->label.round.r);
780 xmlSetProp (node, "radius", string);
783 case GL_TEMPLATE_STYLE_CD:
784 xmlSetProp (node, "style", "cd");
785 string = g_strdup_printf ("%g", template->label.cd.r1);
786 xmlSetProp (node, "radius", string);
788 string = g_strdup_printf ("%g", template->label.cd.r2);
789 xmlSetProp (node, "hole", string);
793 g_warning ("Unknown label style");
797 for ( p=template->label.any.markups; p != NULL; p=p->next ) {
798 markup = (glTemplateMarkup *)p->data;
799 switch (markup->type) {
800 case GL_TEMPLATE_MARKUP_MARGIN:
801 xml_add_markup_margin ((glTemplateMarkupMargin *)markup,
805 g_warning ("Unknown markup type");
810 for ( p=template->label.any.layouts; p != NULL; p=p->next ) {
811 layout = (glTemplateLayout *)p->data;
812 xml_add_layout (layout, node, ns);
815 gl_debug (DEBUG_TEMPLATE, "END");
818 /*--------------------------------------------------------------------------*/
819 /* PRIVATE. Add XML Sheet->Label->Layout Node. */
820 /*--------------------------------------------------------------------------*/
822 xml_add_layout (glTemplateLayout *layout,
829 gl_debug (DEBUG_TEMPLATE, "START");
831 node = xmlNewChild(root, ns, "Layout", NULL);
832 string = g_strdup_printf ("%d", layout->nx);
833 xmlSetProp (node, "nx", string);
835 string = g_strdup_printf ("%d", layout->ny);
836 xmlSetProp (node, "ny", string);
838 string = g_strdup_printf ("%g", layout->x0);
839 xmlSetProp (node, "x0", string);
841 string = g_strdup_printf ("%g", layout->y0);
842 xmlSetProp (node, "y0", string);
844 string = g_strdup_printf ("%g", layout->dx);
845 xmlSetProp (node, "dx", string);
847 string = g_strdup_printf ("%g", layout->dy);
848 xmlSetProp (node, "dy", string);
851 gl_debug (DEBUG_TEMPLATE, "END");
854 /*--------------------------------------------------------------------------*/
855 /* PRIVATE. Add XML Sheet->Label->Markup Node. */
856 /*--------------------------------------------------------------------------*/
858 xml_add_markup_margin (glTemplateMarkupMargin *margin,
865 gl_debug (DEBUG_TEMPLATE, "START");
867 node = xmlNewChild(root, ns, "Markup", NULL);
868 xmlSetProp (node, "type", "margin");
870 string = g_strdup_printf ("%g", margin->size);
871 xmlSetProp (node, "size", string);
874 gl_debug (DEBUG_TEMPLATE, "END");
877 /*--------------------------------------------------------------------------*/
878 /* PRIVATE. Add XML Sheet->Alias Node. */
879 /*--------------------------------------------------------------------------*/
881 xml_add_alias (gchar *name,
887 gl_debug (DEBUG_TEMPLATE, "START");
889 node = xmlNewChild (root, ns, "Alias", NULL);
890 xmlSetProp (node, "name", name);
892 gl_debug (DEBUG_TEMPLATE, "END");
895 /****************************************************************************/
896 /* Get label size description. */
897 /****************************************************************************/
899 gl_template_get_label_size_desc (const glTemplate *template)
902 const gchar *units_string;
903 gdouble units_per_point;
904 gchar *string = NULL;
906 units = gl_prefs_get_units ();
907 units_string = gl_prefs_get_units_string ();
908 units_per_point = gl_prefs_get_units_per_point ();
910 switch (template->label.style) {
911 case GL_TEMPLATE_STYLE_RECT:
912 if ( units == GL_PREFS_UNITS_INCHES ) {
915 xstr = gl_util_fraction (template->label.rect.w * units_per_point);
916 ystr = gl_util_fraction (template->label.rect.h * units_per_point);
917 string = g_strdup_printf (_("%s x %s %s"),
918 xstr, ystr, units_string);
922 string = g_strdup_printf (_("%.5g x %.5g %s"),
923 template->label.rect.w * units_per_point,
924 template->label.rect.h * units_per_point,
928 case GL_TEMPLATE_STYLE_ROUND:
929 if ( units == GL_PREFS_UNITS_INCHES ) {
932 dstr = gl_util_fraction (2.0 * template->label.round.r * units_per_point);
933 string = g_strdup_printf (_("%s %s diameter"),
937 string = g_strdup_printf (_("%.5g %s diameter"),
938 2.0 * template->label.round.r * units_per_point,
942 case GL_TEMPLATE_STYLE_CD:
943 if ( units == GL_PREFS_UNITS_INCHES ) {
946 dstr = gl_util_fraction (2.0 * template->label.cd.r1 * units_per_point);
947 string = g_strdup_printf (_("%s %s diameter"),
951 string = g_strdup_printf (_("%.5g %s diameter"),
952 2.0 * template->label.cd.r1 * units_per_point,
963 /****************************************************************************/
964 /* Get raw label size (width and height). */
965 /****************************************************************************/
967 gl_template_get_label_size (const glTemplate *template,
971 switch (template->label.style) {
972 case GL_TEMPLATE_STYLE_RECT:
973 *w = template->label.rect.w;
974 *h = template->label.rect.h;
976 case GL_TEMPLATE_STYLE_ROUND:
977 *w = 2.0 * template->label.round.r;
978 *h = 2.0 * template->label.round.r;
980 case GL_TEMPLATE_STYLE_CD:
981 *w = 2.0 * template->label.cd.r1;
982 *h = 2.0 * template->label.cd.r1;
991 /****************************************************************************/
992 /* Get total number of labels per sheet. */
993 /****************************************************************************/
995 gl_template_get_n_labels (const glTemplate *template)
999 glTemplateLayout *layout;
1001 for ( p=template->label.any.layouts; p != NULL; p=p->next ) {
1002 layout = (glTemplateLayout *)p->data;
1004 n_labels += layout->nx * layout->ny;
1010 /****************************************************************************/
1011 /* Get array of origins of individual labels. */
1012 /****************************************************************************/
1014 gl_template_get_origins (const glTemplate *template)
1016 gint i_label, n_labels, ix, iy;
1017 glTemplateOrigin *origins;
1019 glTemplateLayout *layout;
1021 n_labels = gl_template_get_n_labels (template);
1022 origins = g_new0 (glTemplateOrigin, n_labels);
1025 for ( p=template->label.any.layouts; p != NULL; p=p->next ) {
1026 layout = (glTemplateLayout *)p->data;
1028 for (iy = 0; iy < layout->ny; iy++) {
1029 for (ix = 0; ix < layout->nx; ix++, i_label++) {
1030 origins[i_label].x = ix*layout->dx + layout->x0;
1031 origins[i_label].y = iy*layout->dy + layout->y0;
1036 g_qsort_with_data (origins, n_labels, sizeof(glTemplateOrigin),
1037 compare_origins, NULL);
1042 /*--------------------------------------------------------------------------*/
1043 /* PRIVATE. Sort origins comparison function, first by y then by x. */
1044 /*--------------------------------------------------------------------------*/
1046 compare_origins (gconstpointer a,
1050 const glTemplateOrigin *a_origin = a, *b_origin = b;
1052 if ( a_origin->y < b_origin->y ) {
1054 } else if ( a_origin->y > b_origin->y ) {
1057 if ( a_origin->x < b_origin->x ) {
1059 } else if ( a_origin->x > b_origin->x ) {
1062 return 0; /* hopefully 2 labels won't have the same origin */
1067 /****************************************************************************/
1068 /* Get a description of the layout and number of labels. */
1069 /****************************************************************************/
1071 gl_template_get_layout_desc (const glTemplate *template)
1074 glTemplateLayout *layout;
1077 n_labels = gl_template_get_n_labels (template);
1079 if ( template->label.any.layouts->next == NULL ) {
1080 layout = (glTemplateLayout *)template->label.any.layouts->data;
1081 string = g_strdup_printf (_("%d x %d (%d per sheet)"),
1082 layout->nx, layout->ny,
1085 string = g_strdup_printf (_("%d per sheet"),
1092 /*--------------------------------------------------------------------------*/
1093 /* PRIVATE. Create new layout structure. */
1094 /*--------------------------------------------------------------------------*/
1095 static glTemplateLayout *
1096 layout_new (gdouble nx,
1103 glTemplateLayout *layout;
1105 layout = g_new0 (glTemplateLayout, 1);
1117 /*--------------------------------------------------------------------------*/
1118 /* PRIVATE. Duplicate layout structure. */
1119 /*--------------------------------------------------------------------------*/
1120 static glTemplateLayout *
1121 layout_dup (glTemplateLayout *orig_layout)
1123 glTemplateLayout *layout;
1125 layout = g_new0 (glTemplateLayout, 1);
1128 *layout = *orig_layout;
1133 /*--------------------------------------------------------------------------*/
1134 /* PRIVATE. Free layout structure. */
1135 /*--------------------------------------------------------------------------*/
1137 layout_free (glTemplateLayout **layout)
1143 /*--------------------------------------------------------------------------*/
1144 /* PRIVATE. Create new margin markup structure. */
1145 /*--------------------------------------------------------------------------*/
1146 static glTemplateMarkup *
1147 markup_margin_new (gdouble size)
1149 glTemplateMarkup *markup;
1151 markup = g_new0 (glTemplateMarkup, 1);
1153 markup->type = GL_TEMPLATE_MARKUP_MARGIN;
1154 markup->margin.size = size;
1159 /*--------------------------------------------------------------------------*/
1160 /* PRIVATE. Duplicate markup structure. */
1161 /*--------------------------------------------------------------------------*/
1162 static glTemplateMarkup *
1163 markup_dup (glTemplateMarkup *orig_markup)
1165 glTemplateMarkup *markup;
1167 markup = g_new0 (glTemplateMarkup, 1);
1169 *markup = *orig_markup;
1174 /*--------------------------------------------------------------------------*/
1175 /* PRIVATE. Free markup structure. */
1176 /*--------------------------------------------------------------------------*/
1178 markup_free (glTemplateMarkup **markup)