3 * Copyright (C) 2001-2009 Jim Evins <evins@snaught.com>.
5 * This file is part of gLabels.
7 * gLabels is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU 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 * gLabels 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 General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with gLabels. If not, see <http://www.gnu.org/licenses/>.
23 #include "label-barcode.h"
26 #include <glib/gi18n.h>
27 #include <pango/pangocairo.h>
32 /*========================================================*/
33 /* Private macros and constants. */
34 /*========================================================*/
36 #define FONT_SCALE (72.0/96.0)
39 /*========================================================*/
41 /*========================================================*/
43 struct _glLabelBarcodePrivate {
44 glTextNode *text_node;
46 glColorNode *color_node;
48 gboolean checksum_flag;
53 /*========================================================*/
54 /* Private globals. */
55 /*========================================================*/
58 /*========================================================*/
59 /* Private function prototypes. */
60 /*========================================================*/
62 static void gl_label_barcode_finalize (GObject *object);
64 static void copy (glLabelObject *dst_object,
65 glLabelObject *src_object);
67 static void get_size (glLabelObject *object,
71 static void set_line_color (glLabelObject *object,
72 glColorNode *line_color);
74 static glColorNode *get_line_color (glLabelObject *object);
76 static void draw_object (glLabelObject *object,
79 glMergeRecord *record);
82 /*****************************************************************************/
83 /* Boilerplate object stuff. */
84 /*****************************************************************************/
85 G_DEFINE_TYPE (glLabelBarcode, gl_label_barcode, GL_TYPE_LABEL_OBJECT);
89 gl_label_barcode_class_init (glLabelBarcodeClass *class)
91 GObjectClass *object_class = G_OBJECT_CLASS (class);
92 glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
94 gl_label_barcode_parent_class = g_type_class_peek_parent (class);
96 label_object_class->copy = copy;
97 label_object_class->get_size = get_size;
98 label_object_class->set_line_color = set_line_color;
99 label_object_class->get_line_color = get_line_color;
100 label_object_class->draw_object = draw_object;
101 label_object_class->draw_shadow = NULL;
103 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 ("");
117 gl_label_barcode_finalize (GObject *object)
119 glLabelBarcode *lbc = GL_LABEL_BARCODE (object);
121 g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
123 gl_text_node_free (&lbc->priv->text_node);
124 g_free (lbc->priv->id);
125 gl_color_node_free (&(lbc->priv->color_node));
128 G_OBJECT_CLASS (gl_label_barcode_parent_class)->finalize (object);
132 /*****************************************************************************/
133 /* NEW label "barcode" object. */
134 /*****************************************************************************/
136 gl_label_barcode_new (glLabel *label)
140 lbc = g_object_new (gl_label_barcode_get_type(), NULL);
142 gl_label_object_set_parent (GL_LABEL_OBJECT(lbc), label);
144 return G_OBJECT (lbc);
148 /*****************************************************************************/
149 /* Copy object contents. */
150 /*****************************************************************************/
152 copy (glLabelObject *dst_object,
153 glLabelObject *src_object)
155 glLabelBarcode *lbc = (glLabelBarcode *)src_object;
156 glLabelBarcode *new_lbc = (glLabelBarcode *)dst_object;
157 glTextNode *text_node;
160 gboolean checksum_flag;
161 glColorNode *color_node;
164 gl_debug (DEBUG_LABEL, "START");
166 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
167 g_return_if_fail (new_lbc && GL_IS_LABEL_BARCODE (new_lbc));
169 text_node = gl_label_barcode_get_data (lbc);
170 gl_label_barcode_get_props (lbc, &id, &text_flag, &checksum_flag, &format_digits);
171 color_node = get_line_color (src_object);
173 gl_label_barcode_set_data (new_lbc, text_node);
174 gl_label_barcode_set_props (new_lbc, id, text_flag, checksum_flag, format_digits);
175 set_line_color (dst_object, color_node);
177 gl_color_node_free (&color_node);
178 gl_text_node_free (&text_node);
181 gl_debug (DEBUG_LABEL, "END");
185 /*****************************************************************************/
186 /* Set object params. */
187 /*****************************************************************************/
189 gl_label_barcode_set_data (glLabelBarcode *lbc,
190 glTextNode *text_node)
192 gl_debug (DEBUG_LABEL, "START");
194 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
196 if (!gl_text_node_equal (lbc->priv->text_node, text_node)) {
198 gl_text_node_free (&lbc->priv->text_node);
199 lbc->priv->text_node = gl_text_node_dup (text_node);
201 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
205 gl_debug (DEBUG_LABEL, "END");
210 gl_label_barcode_set_props (glLabelBarcode *lbc,
213 gboolean checksum_flag,
216 gl_debug (DEBUG_LABEL, "START");
218 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
220 if ( ((lbc->priv->id == NULL) && (id != NULL))
221 || (g_ascii_strcasecmp (lbc->priv->id, id) != 0)
222 || (lbc->priv->text_flag != text_flag)
223 || (lbc->priv->checksum_flag != checksum_flag)
224 || (lbc->priv->format_digits != format_digits)) {
226 lbc->priv->id = g_strdup (id);
227 lbc->priv->text_flag = text_flag;
228 lbc->priv->checksum_flag = checksum_flag;
229 lbc->priv->format_digits = format_digits;
231 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
235 gl_debug (DEBUG_LABEL, "END");
239 /*****************************************************************************/
240 /* Get object params. */
241 /*****************************************************************************/
243 gl_label_barcode_get_data (glLabelBarcode *lbc)
245 g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
247 return gl_text_node_dup (lbc->priv->text_node);
252 gl_label_barcode_get_props (glLabelBarcode *lbc,
255 gboolean *checksum_flag,
256 guint *format_digits)
258 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
260 *id = g_strdup (lbc->priv->id);
261 *text_flag = lbc->priv->text_flag;
262 *checksum_flag = lbc->priv->checksum_flag;
263 *format_digits = lbc->priv->format_digits;
267 /*---------------------------------------------------------------------------*/
268 /* PRIVATE. Get object size method. */
269 /*---------------------------------------------------------------------------*/
271 get_size (glLabelObject *object,
275 glLabelBarcode *lbc = (glLabelBarcode *)object;
277 gdouble w_parent, h_parent;
280 gl_debug (DEBUG_LABEL, "START");
282 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
284 gl_label_object_get_raw_size (object, &w_parent, &h_parent);
286 if (lbc->priv->text_node->field_flag) {
287 data = gl_barcode_default_digits (lbc->priv->id,
288 lbc->priv->format_digits);
290 data = gl_text_node_expand (lbc->priv->text_node, NULL);
293 gbc = gl_barcode_new (lbc->priv->id,
294 lbc->priv->text_flag,
295 lbc->priv->checksum_flag,
302 /* Try again with default digits. */
303 data = gl_barcode_default_digits (lbc->priv->id,
304 lbc->priv->format_digits);
305 gbc = gl_barcode_new (lbc->priv->id,
306 lbc->priv->text_flag,
307 lbc->priv->checksum_flag,
321 /* If we still can't render, just set a default size. */
326 gl_barcode_free (&gbc);
328 gl_debug (DEBUG_LABEL, "END");
332 /*---------------------------------------------------------------------------*/
333 /* PRIVATE. Set line color method. */
334 /*---------------------------------------------------------------------------*/
336 set_line_color (glLabelObject *object,
337 glColorNode *line_color_node)
339 glLabelBarcode *lbarcode = (glLabelBarcode *)object;
341 g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
343 if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) ) {
345 gl_color_node_free (&(lbarcode->priv->color_node));
346 lbarcode->priv->color_node = gl_color_node_dup (line_color_node);
347 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbarcode));
352 /*---------------------------------------------------------------------------*/
353 /* PRIVATE. Get line color method. */
354 /*---------------------------------------------------------------------------*/
356 get_line_color (glLabelObject *object)
358 glLabelBarcode *lbarcode = (glLabelBarcode *)object;
360 g_return_val_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode), NULL);
362 return gl_color_node_dup (lbarcode->priv->color_node);
366 /*****************************************************************************/
367 /* Draw object method. */
368 /*****************************************************************************/
370 draw_object (glLabelObject *object,
372 gboolean screen_flag,
373 glMergeRecord *record)
376 cairo_matrix_t matrix;
379 glBarcodeChar *bchar;
383 PangoFontDescription *desc;
384 gchar *text, *cstring;
385 glTextNode *text_node;
388 gboolean checksum_flag;
390 glColorNode *color_node;
394 gl_debug (DEBUG_LABEL, "START");
396 gl_label_object_get_position (object, &x0, &y0);
397 gl_label_object_get_matrix (object, &matrix);
399 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE (object));
400 gl_label_barcode_get_props (GL_LABEL_BARCODE (object),
401 &id, &text_flag, &checksum_flag, &format_digits);
403 color_node = gl_label_object_get_line_color (object);
404 color = gl_color_node_expand (color_node, record);
405 if (color_node->field_flag && screen_flag)
407 color = GL_COLOR_MERGE_DEFAULT;
409 gl_color_node_free (&color_node);
411 gl_label_object_get_size (object, &w, &h);
413 text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
414 text = gl_text_node_expand (text_node, record);
415 if (text_node->field_flag && screen_flag) {
416 text = gl_barcode_default_digits (id, format_digits);
419 gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
421 cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
425 layout = pango_cairo_create_layout (cr);
427 desc = pango_font_description_new ();
428 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
429 pango_font_description_set_size (desc, 12 * PANGO_SCALE * FONT_SCALE);
430 pango_layout_set_font_description (layout, desc);
431 pango_font_description_free (desc);
433 if (text == NULL || *text == '\0')
435 pango_layout_set_text (layout, _("Barcode data empty"), -1);
439 pango_layout_set_text (layout, _("Invalid barcode data"), -1);
442 cairo_move_to (cr, 0, 0);
443 pango_cairo_show_layout (cr, layout);
445 g_object_unref (layout);
449 for (li = gbc->lines; li != NULL; li = li->next) {
450 line = (glBarcodeLine *) li->data;
452 cairo_move_to (cr, line->x, line->y);
453 cairo_line_to (cr, line->x, line->y + line->length);
454 cairo_set_line_width (cr, line->width);
458 for (li = gbc->chars; li != NULL; li = li->next) {
459 bchar = (glBarcodeChar *) li->data;
461 layout = pango_cairo_create_layout (cr);
463 desc = pango_font_description_new ();
464 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
465 pango_font_description_set_size (desc, bchar->fsize * PANGO_SCALE * FONT_SCALE);
466 pango_layout_set_font_description (layout, desc);
467 pango_font_description_free (desc);
469 cstring = g_strdup_printf ("%c", bchar->c);
470 pango_layout_set_text (layout, cstring, -1);
473 y_offset = 0.2 * bchar->fsize;
475 cairo_move_to (cr, bchar->x, bchar->y-y_offset);
476 pango_cairo_show_layout (cr, layout);
478 g_object_unref (layout);
482 gl_barcode_free (&gbc);
487 gl_text_node_free (&text_node);
490 gl_debug (DEBUG_LABEL, "END");
497 * Local Variables: -- emacs
499 * c-basic-offset: 8 -- emacs
500 * tab-width: 8 -- emacs
501 * indent-tabs-mode: nil -- emacs