1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * label_barcode.c: GLabels label text object
8 * Copyright (C) 2001-2007 Jim Evins <evins@snaught.com>.
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.
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.
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
25 #include "label-barcode.h"
27 #include <glib/gi18n.h>
28 #include <glib/gmem.h>
29 #include <glib/gstrfuncs.h>
30 #include <glib/gmessages.h>
32 #include <pango/pangocairo.h>
36 /*========================================================*/
37 /* Private macros and constants. */
38 /*========================================================*/
40 #define FONT_SCALE (72.0/96.0)
42 /*========================================================*/
44 /*========================================================*/
46 struct _glLabelBarcodePrivate {
47 glTextNode *text_node;
49 glColorNode *color_node;
51 gboolean checksum_flag;
55 /*========================================================*/
56 /* Private globals. */
57 /*========================================================*/
59 /*========================================================*/
60 /* Private function prototypes. */
61 /*========================================================*/
63 static void gl_label_barcode_finalize (GObject *object);
65 static void copy (glLabelObject *dst_object,
66 glLabelObject *src_object);
68 static void get_size (glLabelObject *object,
72 static void set_line_color (glLabelObject *object,
73 glColorNode *line_color);
75 static glColorNode *get_line_color (glLabelObject *object);
77 static void draw_object (glLabelObject *object,
80 glMergeRecord *record);
84 /*****************************************************************************/
85 /* Boilerplate object stuff. */
86 /*****************************************************************************/
87 G_DEFINE_TYPE (glLabelBarcode, gl_label_barcode, GL_TYPE_LABEL_OBJECT);
90 gl_label_barcode_class_init (glLabelBarcodeClass *class)
92 GObjectClass *object_class = G_OBJECT_CLASS (class);
93 glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
95 gl_label_barcode_parent_class = g_type_class_peek_parent (class);
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;
104 object_class->finalize = gl_label_barcode_finalize;
108 gl_label_barcode_init (glLabelBarcode *lbc)
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 ("");
116 gl_label_barcode_finalize (GObject *object)
118 glLabelBarcode *lbc = GL_LABEL_BARCODE (object);
120 g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
122 gl_text_node_free (&lbc->priv->text_node);
123 g_free (lbc->priv->id);
124 gl_color_node_free (&(lbc->priv->color_node));
127 G_OBJECT_CLASS (gl_label_barcode_parent_class)->finalize (object);
130 /*****************************************************************************/
131 /* NEW label "barcode" object. */
132 /*****************************************************************************/
134 gl_label_barcode_new (glLabel *label)
138 lbc = g_object_new (gl_label_barcode_get_type(), NULL);
140 gl_label_object_set_parent (GL_LABEL_OBJECT(lbc), label);
142 return G_OBJECT (lbc);
145 /*****************************************************************************/
146 /* Copy object contents. */
147 /*****************************************************************************/
149 copy (glLabelObject *dst_object,
150 glLabelObject *src_object)
152 glLabelBarcode *lbc = (glLabelBarcode *)src_object;
153 glLabelBarcode *new_lbc = (glLabelBarcode *)dst_object;
154 glTextNode *text_node;
157 gboolean checksum_flag;
158 glColorNode *color_node;
161 gl_debug (DEBUG_LABEL, "START");
163 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
164 g_return_if_fail (new_lbc && GL_IS_LABEL_BARCODE (new_lbc));
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);
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);
174 gl_color_node_free (&color_node);
175 gl_text_node_free (&text_node);
178 gl_debug (DEBUG_LABEL, "END");
182 /*****************************************************************************/
183 /* Set object params. */
184 /*****************************************************************************/
186 gl_label_barcode_set_data (glLabelBarcode *lbc,
187 glTextNode *text_node)
189 gl_debug (DEBUG_LABEL, "START");
191 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
193 if (!gl_text_node_equal (lbc->priv->text_node, text_node)) {
195 gl_text_node_free (&lbc->priv->text_node);
196 lbc->priv->text_node = gl_text_node_dup (text_node);
198 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
202 gl_debug (DEBUG_LABEL, "END");
206 gl_label_barcode_set_props (glLabelBarcode *lbc,
209 gboolean checksum_flag,
212 gl_debug (DEBUG_LABEL, "START");
214 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
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)) {
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;
227 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
231 gl_debug (DEBUG_LABEL, "END");
235 /*****************************************************************************/
236 /* Get object params. */
237 /*****************************************************************************/
239 gl_label_barcode_get_data (glLabelBarcode *lbc)
241 g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
243 return gl_text_node_dup (lbc->priv->text_node);
247 gl_label_barcode_get_props (glLabelBarcode *lbc,
250 gboolean *checksum_flag,
251 guint *format_digits)
253 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
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;
261 /*---------------------------------------------------------------------------*/
262 /* PRIVATE. Get object size method. */
263 /*---------------------------------------------------------------------------*/
265 get_size (glLabelObject *object,
269 glLabelBarcode *lbc = (glLabelBarcode *)object;
271 gdouble w_parent, h_parent;
274 gl_debug (DEBUG_LABEL, "START");
276 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
278 gl_label_object_get_raw_size (object, &w_parent, &h_parent);
280 if (lbc->priv->text_node->field_flag) {
281 data = gl_barcode_default_digits (lbc->priv->id,
282 lbc->priv->format_digits);
284 data = gl_text_node_expand (lbc->priv->text_node, NULL);
287 gbc = gl_barcode_new (lbc->priv->id,
288 lbc->priv->text_flag,
289 lbc->priv->checksum_flag,
295 /* Try again with default digits. */
296 data = gl_barcode_default_digits (lbc->priv->id,
297 lbc->priv->format_digits);
298 gbc = gl_barcode_new (lbc->priv->id,
299 lbc->priv->text_flag,
300 lbc->priv->checksum_flag,
309 gl_barcode_free (&gbc);
312 gl_debug (DEBUG_LABEL, "END");
315 /*---------------------------------------------------------------------------*/
316 /* PRIVATE. Set line color method. */
317 /*---------------------------------------------------------------------------*/
319 set_line_color (glLabelObject *object,
320 glColorNode *line_color_node)
322 glLabelBarcode *lbarcode = (glLabelBarcode *)object;
324 g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
326 if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) ) {
328 gl_color_node_free (&(lbarcode->priv->color_node));
329 lbarcode->priv->color_node = gl_color_node_dup (line_color_node);
330 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbarcode));
334 /*---------------------------------------------------------------------------*/
335 /* PRIVATE. Get line color method. */
336 /*---------------------------------------------------------------------------*/
338 get_line_color (glLabelObject *object)
340 glLabelBarcode *lbarcode = (glLabelBarcode *)object;
342 g_return_val_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode), NULL);
344 return gl_color_node_dup (lbarcode->priv->color_node);
347 /*****************************************************************************/
348 /* Draw object method. */
349 /*****************************************************************************/
351 draw_object (glLabelObject *object,
353 gboolean screen_flag,
354 glMergeRecord *record)
357 cairo_matrix_t matrix;
360 glBarcodeChar *bchar;
364 PangoFontDescription *desc;
365 gchar *text, *cstring;
366 glTextNode *text_node;
369 gboolean checksum_flag;
371 glColorNode *color_node;
375 gl_debug (DEBUG_LABEL, "START");
377 gl_label_object_get_position (object, &x0, &y0);
378 gl_label_object_get_matrix (object, &matrix);
380 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE (object));
381 gl_label_barcode_get_props (GL_LABEL_BARCODE (object),
382 &id, &text_flag, &checksum_flag, &format_digits);
384 color_node = gl_label_object_get_line_color (object);
385 color = gl_color_node_expand (color_node, record);
386 if (color_node->field_flag && screen_flag)
388 color = GL_COLOR_MERGE_DEFAULT;
390 gl_color_node_free (&color_node);
392 gl_label_object_get_size (object, &w, &h);
394 text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
395 text = gl_text_node_expand (text_node, record);
396 if (text_node->field_flag && screen_flag) {
397 text = gl_barcode_default_digits (id, format_digits);
400 gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
402 cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
406 layout = pango_cairo_create_layout (cr);
408 desc = pango_font_description_new ();
409 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
410 pango_font_description_set_size (desc, 12 * PANGO_SCALE * FONT_SCALE);
411 pango_layout_set_font_description (layout, desc);
412 pango_font_description_free (desc);
414 if (text == NULL || *text == '\0')
416 pango_layout_set_text (layout, _("Barcode data empty"), -1);
420 pango_layout_set_text (layout, _("Invalid barcode data"), -1);
423 pango_cairo_show_layout (cr, layout);
425 g_object_unref (layout);
429 for (li = gbc->lines; li != NULL; li = li->next) {
430 line = (glBarcodeLine *) li->data;
432 cairo_move_to (cr, line->x, line->y);
433 cairo_line_to (cr, line->x, line->y + line->length);
434 cairo_set_line_width (cr, line->width);
438 for (li = gbc->chars; li != NULL; li = li->next) {
439 bchar = (glBarcodeChar *) li->data;
441 layout = pango_cairo_create_layout (cr);
443 desc = pango_font_description_new ();
444 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
445 pango_font_description_set_size (desc, bchar->fsize * PANGO_SCALE * FONT_SCALE);
446 pango_layout_set_font_description (layout, desc);
447 pango_font_description_free (desc);
449 cstring = g_strdup_printf ("%c", bchar->c);
450 pango_layout_set_text (layout, cstring, -1);
453 y_offset = 0.2 * bchar->fsize;
455 cairo_move_to (cr, bchar->x, bchar->y-y_offset);
456 pango_cairo_show_layout (cr, layout);
458 g_object_unref (layout);
462 gl_barcode_free (&gbc);
467 gl_text_node_free (&text_node);
470 gl_debug (DEBUG_LABEL, "END");