]> git.sur5r.net Git - glabels/blob - src/label-barcode.c
Imported Upstream version 2.2.8
[glabels] / src / label-barcode.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  label_barcode.c:  GLabels label text object
7  *
8  *  Copyright (C) 2001-2007  Jim Evins <evins@snaught.com>.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24
25 #include "label-barcode.h"
26
27 #include <glib/gi18n.h>
28 #include <glib/gmem.h>
29 #include <glib/gstrfuncs.h>
30 #include <glib/gmessages.h>
31 #include <cairo.h>
32 #include <pango/pangocairo.h>
33
34 #include "debug.h"
35
36 /*========================================================*/
37 /* Private macros and constants.                          */
38 /*========================================================*/
39
40 #define FONT_SCALE (72.0/96.0)
41
42 /*========================================================*/
43 /* Private types.                                         */
44 /*========================================================*/
45
46 struct _glLabelBarcodePrivate {
47         glTextNode     *text_node;
48         gchar          *id;
49         glColorNode    *color_node;
50         gboolean        text_flag;
51         gboolean        checksum_flag;
52         guint           format_digits;
53 };
54
55 /*========================================================*/
56 /* Private globals.                                       */
57 /*========================================================*/
58
59 /*========================================================*/
60 /* Private function prototypes.                           */
61 /*========================================================*/
62
63 static void  gl_label_barcode_finalize      (GObject             *object);
64
65 static void  copy                           (glLabelObject       *dst_object,
66                                              glLabelObject       *src_object);
67
68 static void  get_size                       (glLabelObject       *object,
69                                              gdouble             *w,
70                                              gdouble             *h);
71
72 static void  set_line_color                 (glLabelObject       *object,
73                                              glColorNode         *line_color);
74
75 static glColorNode *get_line_color          (glLabelObject       *object);
76
77 static void    draw_object                (glLabelObject     *object,
78                                            cairo_t           *cr,
79                                            gboolean           screen_flag,
80                                            glMergeRecord     *record);
81
82
83 \f
84 /*****************************************************************************/
85 /* Boilerplate object stuff.                                                 */
86 /*****************************************************************************/
87 G_DEFINE_TYPE (glLabelBarcode, gl_label_barcode, GL_TYPE_LABEL_OBJECT);
88
89 static void
90 gl_label_barcode_class_init (glLabelBarcodeClass *class)
91 {
92         GObjectClass       *object_class       = G_OBJECT_CLASS (class);
93         glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
94
95         gl_label_barcode_parent_class = g_type_class_peek_parent (class);
96
97         label_object_class->copy           = copy;
98         label_object_class->get_size       = get_size;
99         label_object_class->set_line_color = set_line_color;
100         label_object_class->get_line_color = get_line_color;
101         label_object_class->draw_object    = draw_object;
102         label_object_class->draw_shadow    = NULL;
103
104         object_class->finalize = gl_label_barcode_finalize;
105 }
106
107 static void
108 gl_label_barcode_init (glLabelBarcode *lbc)
109 {
110         lbc->priv = g_new0 (glLabelBarcodePrivate, 1);
111         lbc->priv->color_node = gl_color_node_new_default ();
112         lbc->priv->text_node  = gl_text_node_new_from_text ("");
113 }
114
115 static void
116 gl_label_barcode_finalize (GObject *object)
117 {
118         glLabelBarcode *lbc = GL_LABEL_BARCODE (object);
119
120         g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
121
122         gl_text_node_free (&lbc->priv->text_node);
123         g_free (lbc->priv->id);
124         gl_color_node_free (&(lbc->priv->color_node));
125         g_free (lbc->priv);
126
127         G_OBJECT_CLASS (gl_label_barcode_parent_class)->finalize (object);
128 }
129
130 /*****************************************************************************/
131 /* NEW label "barcode" object.                                               */
132 /*****************************************************************************/
133 GObject *
134 gl_label_barcode_new (glLabel *label)
135 {
136         glLabelBarcode *lbc;
137
138         lbc = g_object_new (gl_label_barcode_get_type(), NULL);
139
140         gl_label_object_set_parent (GL_LABEL_OBJECT(lbc), label);
141
142         return G_OBJECT (lbc);
143 }
144
145 /*****************************************************************************/
146 /* Copy object contents.                                                     */
147 /*****************************************************************************/
148 static void
149 copy (glLabelObject *dst_object,
150       glLabelObject *src_object)
151 {
152         glLabelBarcode      *lbc     = (glLabelBarcode *)src_object;
153         glLabelBarcode      *new_lbc = (glLabelBarcode *)dst_object;
154         glTextNode          *text_node;
155         gchar               *id;
156         gboolean             text_flag;
157         gboolean             checksum_flag;
158         glColorNode         *color_node;
159         guint                format_digits;
160
161         gl_debug (DEBUG_LABEL, "START");
162
163         g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
164         g_return_if_fail (new_lbc && GL_IS_LABEL_BARCODE (new_lbc));
165
166         text_node = gl_label_barcode_get_data (lbc);
167         gl_label_barcode_get_props (lbc, &id, &text_flag, &checksum_flag, &format_digits);
168         color_node = get_line_color (src_object);
169
170         gl_label_barcode_set_data (new_lbc, text_node);
171         gl_label_barcode_set_props (new_lbc, id, text_flag, checksum_flag, format_digits);
172         set_line_color (dst_object, color_node);
173
174         gl_color_node_free (&color_node);
175         gl_text_node_free (&text_node);
176         g_free (id);
177
178         gl_debug (DEBUG_LABEL, "END");
179 }
180
181
182 /*****************************************************************************/
183 /* Set object params.                                                        */
184 /*****************************************************************************/
185 void
186 gl_label_barcode_set_data (glLabelBarcode *lbc,
187                            glTextNode     *text_node)
188 {
189         gl_debug (DEBUG_LABEL, "START");
190
191         g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
192
193         if (!gl_text_node_equal (lbc->priv->text_node, text_node)) {
194
195                 gl_text_node_free (&lbc->priv->text_node);
196                 lbc->priv->text_node = gl_text_node_dup (text_node);
197
198                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
199
200         }
201
202         gl_debug (DEBUG_LABEL, "END");
203 }
204
205 void
206 gl_label_barcode_set_props (glLabelBarcode *lbc,
207                             gchar          *id,
208                             gboolean        text_flag,
209                             gboolean        checksum_flag,
210                             guint           format_digits)
211 {
212         gl_debug (DEBUG_LABEL, "START");
213
214         g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
215
216         if ( ((lbc->priv->id == NULL) && (id != NULL))
217              || (g_strcasecmp (lbc->priv->id, id) != 0)
218              || (lbc->priv->text_flag != text_flag)
219              || (lbc->priv->checksum_flag != checksum_flag)
220              || (lbc->priv->format_digits != format_digits)) {
221
222                 lbc->priv->id               = g_strdup (id);
223                 lbc->priv->text_flag        = text_flag;
224                 lbc->priv->checksum_flag    = checksum_flag;
225                 lbc->priv->format_digits    = format_digits;
226
227                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
228
229         }
230
231         gl_debug (DEBUG_LABEL, "END");
232 }
233
234
235 /*****************************************************************************/
236 /* Get object params.                                                        */
237 /*****************************************************************************/
238 glTextNode *
239 gl_label_barcode_get_data (glLabelBarcode *lbc)
240 {
241         g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
242
243         return gl_text_node_dup (lbc->priv->text_node);
244 }
245
246 void
247 gl_label_barcode_get_props (glLabelBarcode *lbc,
248                             gchar          **id,
249                             gboolean       *text_flag,
250                             gboolean       *checksum_flag,
251                             guint          *format_digits)
252 {
253         g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
254
255         *id               = g_strdup (lbc->priv->id);
256         *text_flag        = lbc->priv->text_flag;
257         *checksum_flag    = lbc->priv->checksum_flag;
258         *format_digits    = lbc->priv->format_digits;
259 }
260
261 /*---------------------------------------------------------------------------*/
262 /* PRIVATE.  Get object size method.                                         */
263 /*---------------------------------------------------------------------------*/
264 static void
265 get_size (glLabelObject *object,
266           gdouble       *w,
267           gdouble       *h)
268 {
269         glLabelBarcode      *lbc = (glLabelBarcode *)object;
270         gchar               *data;
271         gdouble              w_parent, h_parent;
272         glBarcode           *gbc;
273
274         gl_debug (DEBUG_LABEL, "START");
275
276         g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
277
278         gl_label_object_get_raw_size (object, &w_parent, &h_parent);
279
280         if (lbc->priv->text_node->field_flag) {
281                 data = gl_barcode_default_digits (lbc->priv->id,
282                                                   lbc->priv->format_digits);
283         } else {
284                 data = gl_text_node_expand (lbc->priv->text_node, NULL);
285         }
286
287         gbc = gl_barcode_new (lbc->priv->id,
288                               lbc->priv->text_flag,
289                               lbc->priv->checksum_flag,
290                               w_parent,
291                               h_parent,
292                               data);
293         g_free (data);
294
295         if ( gbc == NULL ) {
296                 /* Try again with default digits. */
297                 data = gl_barcode_default_digits (lbc->priv->id,
298                                                   lbc->priv->format_digits);
299                 gbc = gl_barcode_new (lbc->priv->id,
300                                       lbc->priv->text_flag,
301                                       lbc->priv->checksum_flag,
302                                       w_parent,
303                                       h_parent,
304                                       data);
305                 g_free (data);
306         }
307
308         if ( gbc != NULL )
309         {
310                 *w = gbc->width;
311                 *h = gbc->height;
312         }
313         else
314         {
315                 /* If we still can't render, just set a default size. */
316                 *w = 144;
317                 *h = 72;
318         }
319
320         gl_barcode_free (&gbc);
321
322         gl_debug (DEBUG_LABEL, "END");
323 }
324
325 /*---------------------------------------------------------------------------*/
326 /* PRIVATE.  Set line color method.                                          */
327 /*---------------------------------------------------------------------------*/
328 static void
329 set_line_color (glLabelObject *object,
330                 glColorNode   *line_color_node)
331 {
332         glLabelBarcode *lbarcode = (glLabelBarcode *)object;
333
334         g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
335
336         if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) ) {
337                 
338                 gl_color_node_free (&(lbarcode->priv->color_node));
339                 lbarcode->priv->color_node = gl_color_node_dup (line_color_node);
340                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbarcode));
341         }
342 }
343
344 /*---------------------------------------------------------------------------*/
345 /* PRIVATE.  Get line color method.                                          */
346 /*---------------------------------------------------------------------------*/
347 static glColorNode*
348 get_line_color (glLabelObject *object)
349 {
350         glLabelBarcode *lbarcode = (glLabelBarcode *)object;
351
352         g_return_val_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode), NULL);
353
354         return gl_color_node_dup (lbarcode->priv->color_node);
355 }
356
357 /*****************************************************************************/
358 /* Draw object method.                                                       */
359 /*****************************************************************************/
360 static void
361 draw_object (glLabelObject *object,
362              cairo_t       *cr,
363              gboolean       screen_flag,
364              glMergeRecord *record)
365 {
366         gdouble             x0, y0;
367         cairo_matrix_t      matrix;
368         glBarcode          *gbc;
369         glBarcodeLine      *line;
370         glBarcodeChar      *bchar;
371         GList              *li;
372         gdouble             y_offset;
373         PangoLayout        *layout;
374         PangoFontDescription *desc;
375         gchar              *text, *cstring;
376         glTextNode         *text_node;
377         gchar              *id;
378         gboolean            text_flag;
379         gboolean            checksum_flag;
380         guint               color;
381         glColorNode        *color_node;
382         guint               format_digits;
383         gdouble             w, h;
384
385         gl_debug (DEBUG_LABEL, "START");
386
387         gl_label_object_get_position (object, &x0, &y0);
388         gl_label_object_get_matrix (object, &matrix);
389
390         text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE (object));
391         gl_label_barcode_get_props (GL_LABEL_BARCODE (object),
392                                     &id, &text_flag, &checksum_flag, &format_digits);
393                                         
394         color_node = gl_label_object_get_line_color (object);
395         color = gl_color_node_expand (color_node, record);
396         if (color_node->field_flag && screen_flag)
397         {
398                 color = GL_COLOR_MERGE_DEFAULT;
399         }
400         gl_color_node_free (&color_node);
401         
402         gl_label_object_get_size (object, &w, &h);
403
404         text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
405         text = gl_text_node_expand (text_node, record);
406         if (text_node->field_flag && screen_flag) {
407                 text = gl_barcode_default_digits (id, format_digits);
408         }
409
410         gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
411
412         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
413
414         if (gbc == NULL) {
415
416                 layout = pango_cairo_create_layout (cr);
417
418                 desc = pango_font_description_new ();
419                 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
420                 pango_font_description_set_size   (desc, 12 * PANGO_SCALE * FONT_SCALE);
421                 pango_layout_set_font_description (layout, desc);
422                 pango_font_description_free       (desc);
423
424                 if (text == NULL || *text == '\0')
425                 {
426                         pango_layout_set_text (layout, _("Barcode data empty"), -1);
427                 }
428                 else
429                 {
430                         pango_layout_set_text (layout, _("Invalid barcode data"), -1);
431                 }
432
433                 cairo_move_to (cr, 0, 0);
434                 pango_cairo_show_layout (cr, layout);
435
436                 g_object_unref (layout);
437
438         } else {
439
440                 for (li = gbc->lines; li != NULL; li = li->next) {
441                         line = (glBarcodeLine *) li->data;
442
443                         cairo_move_to (cr, line->x, line->y);
444                         cairo_line_to (cr, line->x, line->y + line->length);
445                         cairo_set_line_width (cr, line->width);
446                         cairo_stroke (cr);
447                 }
448
449                 for (li = gbc->chars; li != NULL; li = li->next) {
450                         bchar = (glBarcodeChar *) li->data;
451
452                         layout = pango_cairo_create_layout (cr);
453
454                         desc = pango_font_description_new ();
455                         pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
456                         pango_font_description_set_size   (desc, bchar->fsize * PANGO_SCALE * FONT_SCALE);
457                         pango_layout_set_font_description (layout, desc);
458                         pango_font_description_free       (desc);
459
460                         cstring = g_strdup_printf ("%c", bchar->c);
461                         pango_layout_set_text (layout, cstring, -1);
462                         g_free (cstring);
463
464                         y_offset = 0.2 * bchar->fsize;
465
466                         cairo_move_to (cr, bchar->x, bchar->y-y_offset);
467                         pango_cairo_show_layout (cr, layout);
468
469                         g_object_unref (layout);
470
471                 }
472
473                 gl_barcode_free (&gbc);
474
475         }
476
477         g_free (text);
478         gl_text_node_free (&text_node);
479         g_free (id);
480
481         gl_debug (DEBUG_LABEL, "END");
482 }
483