]> git.sur5r.net Git - glabels/blob - glabels2/src/bc-gnubarcode.c
Initial revision
[glabels] / glabels2 / src / bc-gnubarcode.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  bc-gnubarcode.c:  front-end to GNU-barcode-library module
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
8  *  Some of this code is borrowed from the postscript renderer (ps.c)
9  *  from the GNU barcode library:
10  *
11  *     Copyright (C) 1999 Alessaandro Rubini (rubini@gnu.org)
12  *     Copyright (C) 1999 Prosa Srl. (prosa@prosa.it)
13  *
14  *  This program is free software; you can redistribute it and/or modify
15  *  it under the terms of the GNU General Public License as published by
16  *  the Free Software Foundation; either version 2 of the License, or
17  *  (at your option) any later version.
18  *
19  *  This program is distributed in the hope that it will be useful,
20  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *  GNU General Public License for more details.
23  *
24  *  You should have received a copy of the GNU General Public License
25  *  along with this program; if not, write to the Free Software
26  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
27  */
28
29 #include <config.h>
30
31 #include <ctype.h>
32 #include <string.h>
33
34 #include "bc.h"
35 #include "bc-gnubarcode.h"
36
37 #include "barcode.h"
38
39 #include "debug.h"
40
41 #define SHRINK_AMOUNT 0.15      /* shrink bars to account for ink spreading */
42 #define FONT_SCALE    0.95      /* Shrink fonts just a hair */
43
44 static glBarcode *render_pass1 (struct Barcode_Item *bci,
45                                 gboolean text_flag,
46                                 gdouble scale);
47 \f
48 /*****************************************************************************/
49 /* Generate intermediate representation of barcode.                          */
50 /*****************************************************************************/
51 glBarcode *
52 gl_barcode_gnubarcode_new (glBarcodeStyle style,
53                            gboolean text_flag,
54                            gdouble scale,
55                            gchar * digits)
56 {
57         glBarcode *gbc;
58         struct Barcode_Item *bci;
59         gint flags;
60
61         bci = Barcode_Create (digits);
62
63         /* First encode using GNU Barcode library */
64         switch (style) {
65         case GL_BARCODE_STYLE_EAN:
66                 flags = BARCODE_EAN;
67                 break;
68         case GL_BARCODE_STYLE_UPC:
69                 flags = BARCODE_UPC;
70                 break;
71         case GL_BARCODE_STYLE_ISBN:
72                 flags = BARCODE_ISBN;
73                 break;
74         case GL_BARCODE_STYLE_39:
75                 flags = BARCODE_39;
76                 break;
77         case GL_BARCODE_STYLE_128:
78                 flags = BARCODE_128;
79                 break;
80         case GL_BARCODE_STYLE_128C:
81                 flags = BARCODE_128C;
82                 break;
83         case GL_BARCODE_STYLE_128B:
84                 flags = BARCODE_128B;
85                 break;
86         case GL_BARCODE_STYLE_I25:
87                 flags = BARCODE_I25;
88                 break;
89         case GL_BARCODE_STYLE_CBR:
90                 flags = BARCODE_CBR;
91                 break;
92         case GL_BARCODE_STYLE_MSI:
93                 flags = BARCODE_MSI;
94                 break;
95         case GL_BARCODE_STYLE_PLS:
96                 flags = BARCODE_PLS;
97                 break;
98         default:
99                 g_warning( "Illegal barcode style %d", style );
100                 flags = BARCODE_ANY;
101                 break;
102         }
103         Barcode_Encode (bci, flags);
104         if (!bci->partial || !bci->textinfo) {
105                 g_warning ("Barcode Data Invalid");
106                 Barcode_Delete (bci);
107                 return NULL;
108         }
109
110         /* now render with our custom back-end,
111            to create appropriate intermdediate format */
112         gbc = render_pass1 (bci, text_flag, scale);
113
114         Barcode_Delete (bci);
115         return gbc;
116 }
117
118 /*--------------------------------------------------------------------------
119  * PRIVATE.  Render to glBarcode intermediate representation of barcode.
120  *
121  *  Some of this code is borrowed from the postscript renderer (ps.c)
122  *  from the GNU barcode library:
123  *
124  *     Copyright (C) 1999 Alessaandro Rubini (rubini@gnu.org)
125  *     Copyright (C) 1999 Prosa Srl. (prosa@prosa.it)
126  *
127  *--------------------------------------------------------------------------*/
128 static glBarcode *
129 render_pass1 (struct Barcode_Item *bci,
130               gboolean text_flag,
131               gdouble scale)
132 {
133         glBarcode *gbc;
134         glBarcodeLine *line;
135         glBarcodeChar *bchar;
136         gdouble x;
137         gint i, j, barlen;
138         gdouble f1, f2;
139         gint mode = '-';        /* text below bars */
140         gdouble x0, y0, yr;
141         guchar *p, c;
142
143         /* First calculate barlen */
144         barlen = bci->partial[0] - '0';
145         for (p = bci->partial + 1; *p != 0; p++) {
146                 if (isdigit (*p)) {
147                         barlen += *p - '0';
148                 } else {
149                         if ((*p != '+') && (*p != '-')) {
150                                 barlen += *p - 'a' + 1;
151                         }
152                 }
153         }
154
155         /* The width defaults to "just enough" */
156         bci->width = barlen * scale + 1;
157
158         /* The height defaults to 80 points (rescaled) */
159         if (!bci->height)
160                 bci->height = 80 * scale;
161
162         gbc = g_new0 (glBarcode, 1);
163
164         /* Now traverse the code string and create a list of lines */
165         x = bci->margin + (bci->partial[0] - '0') * scale;
166         for (p = bci->partial + 1, i = 1; *p != 0; p++, i++) {
167                 /* special cases: '+' and '-' */
168                 if (*p == '+' || *p == '-') {
169                         mode = *p;      /* don't count it */
170                         i++;
171                         continue;
172                 }
173                 /* j is the width of this bar/space */
174                 if (isdigit (*p))
175                         j = *p - '0';
176                 else
177                         j = *p - 'a' + 1;
178                 if (i % 2) {    /* bar */
179                         x0 = x + (j * scale) / 2;
180                         y0 = bci->margin;
181                         yr = bci->height;
182                         if (text_flag) {        /* leave space for text */
183                                 if (mode == '-') {
184                                         /* text below bars: 10 or 5 points */
185                                         yr -= (isdigit (*p) ? 10 : 5) * scale;
186                                 } else {        /* '+' */
187                                         /* above bars: 10 or 0 from bottom,
188                                            and 10 from top */
189                                         y0 += 10 * scale;
190                                         yr -= (isdigit (*p) ? 20 : 10) * scale;
191                                 }
192                         }
193                         line = g_new0 (glBarcodeLine, 1);
194                         line->x = x0;
195                         line->y = y0;
196                         line->length = yr;
197                         line->width = (j * scale) - SHRINK_AMOUNT;
198                         gbc->lines = g_list_append (gbc->lines, line);
199                 }
200                 x += j * scale;
201
202         }
203
204         /* Now the text */
205         mode = '-';             /* reinstantiate default */
206         if (text_flag) {
207                 for (p = bci->textinfo; p; p = strchr (p, ' ')) {
208                         while (*p == ' ')
209                                 p++;
210                         if (!*p)
211                                 break;
212                         if (*p == '+' || *p == '-') {
213                                 mode = *p;
214                                 continue;
215                         }
216                         if (sscanf (p, "%lf:%lf:%c", &f1, &f2, &c) != 3) {
217                                 g_warning ("impossible data: %s", p);
218                                 continue;
219                         }
220                         bchar = g_new0 (glBarcodeChar, 1);
221                         bchar->x = f1 * scale + bci->margin;
222                         if (mode == '-') {
223                                 bchar->y =
224                                     bci->margin + bci->height - 8 * scale;
225                         } else {
226                                 bchar->y = bci->margin;
227                         }
228                         bchar->fsize = f2 * FONT_SCALE * scale;
229                         bchar->c = c;
230                         gbc->chars = g_list_append (gbc->chars, bchar);
231                 }
232         }
233
234         /* Fill in other info */
235         gbc->height = bci->height + 2.0 * bci->margin;
236         gbc->width = bci->width + 2.0 * bci->margin;
237
238         return gbc;
239 }