]> git.sur5r.net Git - glabels/blob - glabels2/src/bc-postnet.c
Initial revision
[glabels] / glabels2 / src / bc-postnet.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  bc_postnet.c:  GLabels POSTNET barcode module
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
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.
12  *
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.
17  *
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
21  */
22
23 /*
24  * This module implements the POSTNET barcode specified in the USPS
25  * publication 25, Mar 2001.
26  */
27
28 #include <config.h>
29
30 #include <ctype.h>
31
32 #include "bc.h"
33 #include "bc-postnet.h"
34
35 #include "debug.h"
36
37 static gchar *symbols[] = {
38         /* 0 */ "11000",
39         /* 1 */ "00011",
40         /* 2 */ "00101",
41         /* 3 */ "00110",
42         /* 4 */ "01001",
43         /* 5 */ "01010",
44         /* 6 */ "01100",
45         /* 7 */ "10001",
46         /* 8 */ "10010",
47         /* 9 */ "10100",
48 };
49
50 static gchar *frame_symbol = "1";
51
52 #define POSTNET_BAR_WIDTH      1.25
53 #define POSTNET_FULLBAR_HEIGHT 9.00
54 #define POSTNET_HALFBAR_HEIGHT 3.50
55 #define POSTNET_BAR_PITCH      3.25
56 #define POSTNET_HORIZ_MARGIN   9.00
57 #define POSTNET_VERT_MARGIN    3.00
58
59 static gchar *postnet_code (gchar * digits);
60 \f
61 /****************************************************************************/
62 /* Generate list of lines that form the barcode for the given digits.       */
63 /****************************************************************************/
64 glBarcode *
65 gl_barcode_postnet_new (gchar * digits)
66 {
67         gchar *code, *p;
68         glBarcode *gbc;
69         glBarcodeLine *line;
70         gdouble x;
71
72         gbc = g_new0 (glBarcode, 1);
73
74         /* First get code string */
75         code = postnet_code (digits);
76         if (code == NULL) {
77                 return NULL;
78         }
79
80         /* Now traverse the code string and create a list of lines */
81         x = POSTNET_HORIZ_MARGIN;
82         for (p = code; *p != 0; p++) {
83                 line = g_new0 (glBarcodeLine, 1);
84                 line->x = x;
85                 line->y = POSTNET_VERT_MARGIN;
86                 if (*p == '0') {
87                         line->y +=
88                             POSTNET_FULLBAR_HEIGHT - POSTNET_HALFBAR_HEIGHT;
89                         line->length = POSTNET_HALFBAR_HEIGHT;
90                 } else {
91                         line->length = POSTNET_FULLBAR_HEIGHT;
92                 }
93                 line->width = POSTNET_BAR_WIDTH;
94
95                 gbc->lines = g_list_append (gbc->lines, line);
96
97                 x += POSTNET_BAR_PITCH;
98         }
99
100         g_free (code);
101
102         gbc->width = x + POSTNET_HORIZ_MARGIN;
103         gbc->height = POSTNET_FULLBAR_HEIGHT + 2 * POSTNET_VERT_MARGIN;
104
105         gbc->chars = NULL;
106
107         return gbc;
108 }
109
110 /*--------------------------------------------------------------------------*/
111 /* PRIVATE.  Generate string of symbols, representing barcode.              */
112 /*--------------------------------------------------------------------------*/
113 static gchar *
114 postnet_code (gchar * digits)
115 {
116         gchar *p;
117         gint len;
118         gint d, sum;
119         GString *code;
120         gchar *ret;
121
122         /* Left frame bar */
123         code = g_string_new (frame_symbol);
124
125         sum = 0;
126         for (p = digits, len = 0; (*p != 0) && (len < 11); p++) {
127                 if (isdigit (*p)) {
128                         /* Only translate valid characters (0-9) */
129                         d = (*p) - '0';
130                         sum += d;
131                         code = g_string_append (code, symbols[d]);
132                         len++;
133                 }
134         }
135         if ((len != 5) && (len != 9) && (len != 11)) {
136                 g_warning ("Invalid POSTNET length %d, should be 5(ZIP), 9(ZIP+4), or 11(DPBC)", len);
137         }
138
139         /* Create correction character */
140         d = (10 - (sum % 10)) % 10;
141         code = g_string_append (code, symbols[d]);
142
143         /* Right frame bar */
144         code = g_string_append (code, frame_symbol);
145
146         ret = g_strdup (code->str);
147         g_string_free (code, TRUE);
148
149         return ret;
150 }