3 * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
5 * This file is part of libglabels.
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.
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.
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/>.
25 #include <glib/gi18n.h>
29 #include <sys/types.h>
31 #include "libglabels-private.h"
35 /*===========================================*/
37 /*===========================================*/
40 /*===========================================*/
42 /*===========================================*/
45 /*===========================================*/
46 /* Local function prototypes */
47 /*===========================================*/
49 static gint compare_origins (gconstpointer a,
53 /*===========================================*/
55 /*===========================================*/
59 * @brand: Template brand
60 * @part: Template part name/number
61 * @description: Template descriptions
62 * @paper_id: Page size id
63 * @page_width: Page width in points, set to zero unless paper_id="Other"
64 * @page_height: Page height in points, set to zero unless paper_id="Other"
66 * Create a new template structure, with the given top-level attributes. The
67 * created template will have no initial aliases, categories, or frames
68 * associated with it. See lgl_template_add_alias(), lgl_template_add_category(),
69 * and lgl_template_add_frame() to add these.
71 * Returns: pointer to a newly allocated #lglTemplate structure.
75 lgl_template_new (const gchar *brand,
77 const gchar *description,
78 const gchar *paper_id,
82 lglTemplate *template;
83 lglTemplateAlias *alias;
85 template = g_new0 (lglTemplate,1);
87 template->brand = g_strdup (brand);
88 template->part = g_strdup (part);
89 template->description = g_strdup (description);
90 template->paper_id = g_strdup (paper_id);
91 template->page_width = page_width;
92 template->page_height = page_height;
94 /* Always include primary name in alias list. */
95 template->aliases = NULL;
96 alias = lgl_template_alias_new (brand, part);
97 lgl_template_add_alias (template, alias);
104 * lgl_template_get_name:
105 * @template: Pointer to template structure to test
107 * This function returns the name of the given template. The name is the concetenation
108 * of the brand and part name/number.
110 * Returns: A pointer to a newly allocated name string. Should be freed with g_free().
114 lgl_template_get_name (const lglTemplate *template)
116 g_return_val_if_fail (template, NULL);
118 return g_strdup_printf ("%s %s", template->brand, template->part);
123 * lgl_template_do_templates_match:
124 * @template1: Pointer to 1st template structure to test
125 * @template2: Pointer to 2nd template structure to test
127 * This function tests if the given templates match. This is a simple test that only tests
128 * the brand and part name/number. It does not test if they are actually identical.
130 * Returns: TRUE if the two template matche.
134 lgl_template_do_templates_match (const lglTemplate *template1,
135 const lglTemplate *template2)
137 g_return_val_if_fail (template1, FALSE);
138 g_return_val_if_fail (template2, FALSE);
140 return (UTF8_EQUAL (template1->brand, template2->brand) &&
141 UTF8_EQUAL (template1->part, template2->part));
146 * lgl_template_does_brand_match:
147 * @template: Pointer to template structure to test
148 * @brand: Brand string
150 * This function tests if the brand of the template matches the given brand.
152 * Returns: TRUE if the template matches the given brand.
156 lgl_template_does_brand_match (const lglTemplate *template,
159 g_return_val_if_fail (template, FALSE);
161 /* NULL matches everything. */
167 return UTF8_EQUAL (template->brand, brand);
172 * lgl_template_does_page_size_match:
173 * @template: Pointer to template structure to test
174 * @paper_id: Page size ID string
176 * This function tests if the page size of the template matches the given ID.
178 * Returns: TRUE if the template matches the given page size ID.
182 lgl_template_does_page_size_match (const lglTemplate *template,
183 const gchar *paper_id)
185 g_return_val_if_fail (template, FALSE);
187 /* NULL matches everything. */
188 if (paper_id == NULL)
193 return ASCII_EQUAL(paper_id, template->paper_id);
198 * lgl_template_does_category_match:
199 * @template: Pointer to template structure to test
200 * @category_id: Category ID string
202 * This function tests if the given template belongs to the given category ID.
204 * Returns: TRUE if the template matches the given category ID.
208 lgl_template_does_category_match (const lglTemplate *template,
209 const gchar *category_id)
213 g_return_val_if_fail (template, FALSE);
215 /* NULL matches everything. */
216 if (category_id == NULL)
221 for ( p=template->category_ids; p != NULL; p=p->next )
223 if (ASCII_EQUAL(category_id, p->data))
234 * lgl_template_alias_new:
235 * @brand: Alias brand
236 * @part: Alias part name/number
238 * Create a new template alias structure, with the given brand and part number.
240 * Returns: pointer to a newly allocated #lglTemplateAlias structure.
244 lgl_template_alias_new (const gchar *brand,
247 lglTemplateAlias *alias;
249 alias = g_new0 (lglTemplateAlias,1);
251 alias->brand = g_strdup (brand);
252 alias->part = g_strdup (part);
259 * lgl_template_add_alias:
260 * @template: Pointer to template structure
261 * @alias: Alias string
263 * This function adds the given alias to a templates list of aliases.
267 lgl_template_add_alias (lglTemplate *template,
268 lglTemplateAlias *alias)
270 g_return_if_fail (template);
271 g_return_if_fail (alias);
273 template->aliases = g_list_append (template->aliases, alias);
278 * lgl_template_add_frame:
279 * @template: Pointer to template structure
280 * @frame: Pointer to frame structure
282 * This function adds the given frame structure to the template. Once added,
283 * the frame structure belongs to the given template; do not attempt to free
286 * Note: Currently glabels only supports a single frame per template.
290 lgl_template_add_frame (lglTemplate *template,
291 lglTemplateFrame *frame)
293 g_return_if_fail (template);
294 g_return_if_fail (frame);
296 template->frames = g_list_append (template->frames, frame);
301 * lgl_template_add_category:
302 * @template: Pointer to template structure
303 * @category_id: Category ID string
305 * This function adds the given category ID to a templates category list.
309 lgl_template_add_category (lglTemplate *template,
310 const gchar *category_id)
312 g_return_if_fail (template);
313 g_return_if_fail (category_id);
315 template->category_ids = g_list_append (template->category_ids,
316 g_strdup (category_id));
321 * lgl_template_frame_rect_new:
322 * @id: ID of frame. (This should currently always be "0").
323 * @w: width of frame in points.
324 * @h: height of frame in points.
325 * @r: radius of rounded corners in points. (Should be 0 for square corners.)
326 * @x_waste: Amount of overprint to allow in the horizontal direction.
327 * @y_waste: Amount of overprint to allow in the vertical direction.
329 * This function creates a new template frame for a rectangular label or card.
331 * Returns: Pointer to newly allocated #lglTemplateFrame structure.
335 lgl_template_frame_rect_new (const gchar *id,
342 lglTemplateFrame *frame;
344 frame = g_new0 (lglTemplateFrame, 1);
346 frame->shape = LGL_TEMPLATE_FRAME_SHAPE_RECT;
347 frame->rect.id = g_strdup (id);
352 frame->rect.x_waste = x_waste;
353 frame->rect.y_waste = y_waste;
360 * lgl_template_frame_round_new:
361 * @id: ID of frame. (This should currently always be "0").
362 * @r: radius of label in points.
363 * @waste: Amount of overprint to allow.
365 * This function creates a new template frame for a round label.
367 * Returns: Pointer to newly allocated #lglTemplateFrame structure.
371 lgl_template_frame_round_new (const gchar *id,
375 lglTemplateFrame *frame;
377 frame = g_new0 (lglTemplateFrame, 1);
379 frame->shape = LGL_TEMPLATE_FRAME_SHAPE_ROUND;
380 frame->round.id = g_strdup (id);
383 frame->round.waste = waste;
390 * lgl_template_frame_cd_new:
391 * @id: ID of frame. (This should currently always be "0").
392 * @r1: outer radius of label in points.
393 * @r2: radius of center hole in points.
394 * @w: clip width of frame in points for business card CDs. Should be 0 for no clipping.
395 * @h: clip height of frame in points for business card CDs. Should be 0 for no clipping.
396 * @waste: Amount of overprint to allow.
398 * This function creates a new template frame for a CD/DVD label.
400 * Returns: Pointer to newly allocated #lglTemplateFrame structure.
404 lgl_template_frame_cd_new (const gchar *id,
411 lglTemplateFrame *frame;
413 frame = g_new0 (lglTemplateFrame, 1);
415 frame->shape = LGL_TEMPLATE_FRAME_SHAPE_CD;
416 frame->cd.id = g_strdup (id);
422 frame->cd.waste = waste;
429 * lgl_template_frame_get_size:
430 * @frame: #lglTemplateFrame structure to query
431 * @w: pointer to location to receive width of frame
432 * @h: pointer to location to receive height of frame
434 * Get size (width and height) of given #lglTemplateFrame in points.
438 lgl_template_frame_get_size (const lglTemplateFrame *frame,
442 g_return_if_fail (frame);
444 switch (frame->shape) {
445 case LGL_TEMPLATE_FRAME_SHAPE_RECT:
449 case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
450 *w = 2.0 * frame->round.r;
451 *h = 2.0 * frame->round.r;
453 case LGL_TEMPLATE_FRAME_SHAPE_CD:
454 if (frame->cd.w == 0.0) {
455 *w = 2.0 * frame->cd.r1;
459 if (frame->cd.h == 0.0) {
460 *h = 2.0 * frame->cd.r1;
474 * lgl_template_frame_get_n_labels:
475 * @frame: #lglTemplateFrame structure to query
477 * Get total number of labels per sheet corresponding to the given frame.
479 * Returns: number of labels per sheet.
483 lgl_template_frame_get_n_labels (const lglTemplateFrame *frame)
487 lglTemplateLayout *layout;
489 g_return_val_if_fail (frame, 0);
491 for ( p=frame->all.layouts; p != NULL; p=p->next ) {
492 layout = (lglTemplateLayout *)p->data;
494 n_labels += layout->nx * layout->ny;
502 * lgl_template_frame_get_origins:
503 * @frame: #lglTemplateFrame structure to query
505 * Get an array of label origins for the given frame. These origins represent the
506 * upper left hand corner of each label on a page corresponding to the given frame.
507 * The origins will be ordered geometrically left to right and then top to bottom.
508 * The array should be freed using g_free().
510 * Returns: A newly allocated array of #lglTemplateOrigin structures.
514 lgl_template_frame_get_origins (const lglTemplateFrame *frame)
516 gint i_label, n_labels, ix, iy;
517 lglTemplateOrigin *origins;
519 lglTemplateLayout *layout;
521 g_return_val_if_fail (frame, NULL);
523 n_labels = lgl_template_frame_get_n_labels (frame);
524 origins = g_new0 (lglTemplateOrigin, n_labels);
527 for ( p=frame->all.layouts; p != NULL; p=p->next ) {
528 layout = (lglTemplateLayout *)p->data;
530 for (iy = 0; iy < layout->ny; iy++) {
531 for (ix = 0; ix < layout->nx; ix++, i_label++) {
532 origins[i_label].x = ix*layout->dx + layout->x0;
533 origins[i_label].y = iy*layout->dy + layout->y0;
538 g_qsort_with_data (origins, n_labels, sizeof(lglTemplateOrigin),
539 compare_origins, NULL);
546 * lgl_template_frame_add_layout:
547 * @frame: Pointer to template frame to add layout to.
548 * @layout: Pointer to layout structure to add to frame.
550 * This function adds a layout structure to the given template frame.
554 lgl_template_frame_add_layout (lglTemplateFrame *frame,
555 lglTemplateLayout *layout)
557 g_return_if_fail (frame);
558 g_return_if_fail (layout);
560 frame->all.layouts = g_list_append (frame->all.layouts, layout);
565 * lgl_template_frame_add_markup:
566 * @frame: Pointer to template frame to add markup to.
567 * @markup: Pointer to markup structure to add to frame.
569 * This function adds a markup structure to the given template frame.
573 lgl_template_frame_add_markup (lglTemplateFrame *frame,
574 lglTemplateMarkup *markup)
576 g_return_if_fail (frame);
577 g_return_if_fail (markup);
579 frame->all.markups = g_list_append (frame->all.markups, markup);
584 * lgl_template_layout_new:
585 * @nx: Number of labels across.
586 * @ny: Number of labels down.
587 * @x0: X coordinate of the top-left corner of the top-left label in the layout in points.
588 * @y0: Y coordinate of the top-left corner of the top-left label in the layout in points.
589 * @dx: Horizontal pitch in points. This is the distance from left-edge to left-edge.
590 * @dy: Vertical pitch in points. This is the distance from top-edge to top-edge.
592 * This function creates a new layout structure with the given parameters.
594 * Returns: a newly allocated #lglTemplateLayout structure.
598 lgl_template_layout_new (gint nx,
605 lglTemplateLayout *layout;
607 layout = g_new0 (lglTemplateLayout, 1);
621 * lgl_template_markup_margin_new:
622 * @size: margin size in points.
624 * This function creates a new margin markup structure.
626 * Returns: a newly allocated #lglTemplateMarkup structure.
630 lgl_template_markup_margin_new (gdouble size)
632 lglTemplateMarkup *markup;
634 markup = g_new0 (lglTemplateMarkup, 1);
636 markup->type = LGL_TEMPLATE_MARKUP_MARGIN;
637 markup->margin.size = size;
644 * lgl_template_markup_line_new:
645 * @x1: x coordinate of first endpoint.
646 * @y1: y coordinate of first endpoint.
647 * @x2: x coordinate of second endpoint.
648 * @y2: y coordinate of second endpoint.
650 * This function creates a new line markup structure.
652 * Returns: a newly allocated #lglTemplateMarkup structure.
656 lgl_template_markup_line_new (gdouble x1,
661 lglTemplateMarkup *markup;
663 markup = g_new0 (lglTemplateMarkup, 1);
665 markup->type = LGL_TEMPLATE_MARKUP_LINE;
666 markup->line.x1 = x1;
667 markup->line.y1 = y1;
668 markup->line.x2 = x2;
669 markup->line.y2 = y2;
676 * lgl_template_markup_circle_new:
677 * @x0: x coordinate of center of circle.
678 * @y0: y coordinate of center of circle.
679 * @r: radius of circle.
681 * This function creates a new circle markup structure.
683 * Returns: a newly allocated #lglTemplateMarkup structure.
687 lgl_template_markup_circle_new (gdouble x0,
691 lglTemplateMarkup *markup;
693 markup = g_new0 (lglTemplateMarkup, 1);
695 markup->type = LGL_TEMPLATE_MARKUP_CIRCLE;
696 markup->circle.x0 = x0;
697 markup->circle.y0 = y0;
698 markup->circle.r = r;
705 * lgl_template_markup_rect_new:
706 * @x1: x coordinate of top-left corner of rectangle.
707 * @y1: y coordinate of top-left corner of rectangle.
708 * @w: width of rectangle.
709 * @h: height of rectangle.
710 * @r: radius of rounded corner.
712 * This function creates a new rectangle markup structure.
714 * Returns: a newly allocated #lglTemplateMarkup structure.
718 lgl_template_markup_rect_new (gdouble x1,
724 lglTemplateMarkup *markup;
726 markup = g_new0 (lglTemplateMarkup, 1);
728 markup->type = LGL_TEMPLATE_MARKUP_RECT;
729 markup->rect.x1 = x1;
730 markup->rect.y1 = y1;
741 * @orig_template: Template to duplicate.
743 * This function duplicates a template structure.
745 * Returns: a newly allocated #lglTemplate structure.
749 lgl_template_dup (const lglTemplate *orig_template)
751 lglTemplate *template;
752 lglTemplateAlias *alias;
754 lglTemplateFrame *frame;
756 g_return_val_if_fail (orig_template, NULL);
758 template = lgl_template_new (orig_template->brand,
760 orig_template->description,
761 orig_template->paper_id,
762 orig_template->page_width,
763 orig_template->page_height);
765 for ( p=orig_template->aliases; p != NULL; p=p->next )
767 alias = (lglTemplateAlias *)p->data;
769 if ( !(UTF8_EQUAL (template->brand, alias->brand) &&
770 UTF8_EQUAL (template->part, alias->part)) )
772 lgl_template_add_alias (template, lgl_template_alias_dup (alias));
777 for ( p=orig_template->category_ids; p != NULL; p=p->next )
779 lgl_template_add_category (template, p->data);
782 for ( p=orig_template->frames; p != NULL; p=p->next )
784 frame = (lglTemplateFrame *)p->data;
786 lgl_template_add_frame (template, lgl_template_frame_dup (frame));
795 * @template: Template to free.
797 * This function frees all memory associated with given template structure.
801 lgl_template_free (lglTemplate *template)
804 lglTemplateFrame *frame;
806 if ( template != NULL ) {
808 g_free (template->brand);
809 template->brand = NULL;
811 g_free (template->part);
812 template->part = NULL;
814 g_free (template->description);
815 template->description = NULL;
817 g_free (template->paper_id);
818 template->paper_id = NULL;
820 for ( p=template->aliases; p != NULL; p=p->next ) {
822 lgl_template_alias_free (p->data);
826 g_list_free (template->aliases);
827 template->aliases = NULL;
829 for ( p=template->category_ids; p != NULL; p=p->next ) {
835 g_list_free (template->category_ids);
836 template->category_ids = NULL;
838 for ( p=template->frames; p != NULL; p=p->next ) {
840 frame = (lglTemplateFrame *)p->data;
842 lgl_template_frame_free (frame);
845 g_list_free (template->frames);
846 template->frames = NULL;
856 * lgl_template_alias_dup:
857 * @orig_alias: Alias to duplicate.
859 * This function duplicates a template alias structure.
861 * Returns: a newly allocated #lglTemplateAlias structure.
865 lgl_template_alias_dup (const lglTemplateAlias *orig_alias)
867 g_return_val_if_fail (orig_alias, NULL);
869 return lgl_template_alias_new (orig_alias->brand, orig_alias->part);
874 * lgl_template_alias_free:
875 * @alias: Alias to free.
877 * This function frees all memory associated with given template alias structure.
881 lgl_template_alias_free (lglTemplateAlias *alias)
886 g_free (alias->brand);
889 g_free (alias->part);
898 * lgl_template_frame_dup:
899 * @orig_frame: Frame to duplicate.
901 * This function duplicates a template frame structure.
903 * Returns: a newly allocated #lglTemplateFrame structure.
907 lgl_template_frame_dup (const lglTemplateFrame *orig_frame)
909 lglTemplateFrame *frame;
911 lglTemplateLayout *layout;
912 lglTemplateMarkup *markup;
914 g_return_val_if_fail (orig_frame, NULL);
916 switch (orig_frame->shape) {
918 case LGL_TEMPLATE_FRAME_SHAPE_RECT:
920 lgl_template_frame_rect_new (orig_frame->all.id,
924 orig_frame->rect.x_waste,
925 orig_frame->rect.y_waste);
928 case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
930 lgl_template_frame_round_new (orig_frame->all.id,
932 orig_frame->round.waste);
935 case LGL_TEMPLATE_FRAME_SHAPE_CD:
937 lgl_template_frame_cd_new (orig_frame->all.id,
942 orig_frame->cd.waste);
950 for ( p=orig_frame->all.layouts; p != NULL; p=p->next ) {
952 layout = (lglTemplateLayout *)p->data;
954 lgl_template_frame_add_layout (frame, lgl_template_layout_dup (layout));
957 for ( p=orig_frame->all.markups; p != NULL; p=p->next ) {
959 markup = (lglTemplateMarkup *)p->data;
961 lgl_template_frame_add_markup (frame, lgl_template_markup_dup (markup));
969 * lgl_template_frame_free:
970 * @frame: Frame to free.
972 * This function frees all memory associated with given template frame structure.
976 lgl_template_frame_free (lglTemplateFrame *frame)
979 lglTemplateLayout *layout;
980 lglTemplateMarkup *markup;
982 if ( frame != NULL ) {
984 g_free (frame->all.id);
985 frame->all.id = NULL;
987 for ( p=frame->all.layouts; p != NULL; p=p->next ) {
989 layout = (lglTemplateLayout *)p->data;
991 lgl_template_layout_free (layout);
994 g_list_free (frame->all.layouts);
995 frame->all.layouts = NULL;
997 for ( p=frame->all.markups; p != NULL; p=p->next ) {
999 markup = (lglTemplateMarkup *)p->data;
1001 lgl_template_markup_free (markup);
1004 g_list_free (frame->all.markups);
1005 frame->all.markups = NULL;
1015 * lgl_template_layout_dup:
1016 * @orig_layout: Layout to duplicate.
1018 * This function duplicates a template layout structure.
1020 * Returns: a newly allocated #lglTemplateLayout structure.
1024 lgl_template_layout_dup (const lglTemplateLayout *orig_layout)
1026 lglTemplateLayout *layout;
1028 g_return_val_if_fail (orig_layout, NULL);
1030 layout = g_new0 (lglTemplateLayout, 1);
1033 *layout = *orig_layout;
1040 * lgl_template_layout_free:
1041 * @layout: Layout to free.
1043 * This function frees all memory associated with given template layout structure.
1047 lgl_template_layout_free (lglTemplateLayout *layout)
1054 * lgl_template_markup_dup:
1055 * @orig_markup: Markup to duplicate.
1057 * This function duplicates a template markup structure.
1059 * Returns: a newly allocated #lglTemplateMarkup structure.
1063 lgl_template_markup_dup (const lglTemplateMarkup *orig_markup)
1065 lglTemplateMarkup *markup;
1067 g_return_val_if_fail (orig_markup, NULL);
1069 markup = g_new0 (lglTemplateMarkup, 1);
1071 *markup = *orig_markup;
1078 * lgl_template_markup_free:
1079 * @markup: Markup to free.
1081 * This function frees all memory associated with given template markup structure.
1085 lgl_template_markup_free (lglTemplateMarkup *markup)
1092 compare_origins (gconstpointer a,
1096 const lglTemplateOrigin *a_origin = a, *b_origin = b;
1098 if ( a_origin->y < b_origin->y ) {
1100 } else if ( a_origin->y > b_origin->y ) {
1103 if ( a_origin->x < b_origin->x ) {
1105 } else if ( a_origin->x > b_origin->x ) {
1108 return 0; /* hopefully 2 labels won't have the same origin */
1116 * Local Variables: -- emacs
1118 * c-basic-offset: 8 -- emacs
1119 * tab-width: 8 -- emacs
1120 * indent-tabs-mode: nil -- emacs