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>
28 #include "bc-backends.h"
32 /*========================================================*/
33 /* Private macros and constants. */
34 /*========================================================*/
36 #define FONT_SCALE (72.0/96.0)
37 #define PI 3.141592654
40 /*========================================================*/
42 /*========================================================*/
44 struct _glLabelBarcodePrivate {
45 glTextNode *text_node;
48 glColorNode *color_node;
50 gboolean checksum_flag;
55 /*========================================================*/
56 /* Private globals. */
57 /*========================================================*/
60 /*========================================================*/
61 /* Private function prototypes. */
62 /*========================================================*/
64 static void gl_label_barcode_finalize (GObject *object);
66 static void copy (glLabelObject *dst_object,
67 glLabelObject *src_object);
69 static void get_size (glLabelObject *object,
73 static void set_line_color (glLabelObject *object,
74 glColorNode *line_color,
77 static glColorNode *get_line_color (glLabelObject *object);
79 static void draw_object (glLabelObject *object,
82 glMergeRecord *record);
84 static gboolean object_at (glLabelObject *object,
90 /*****************************************************************************/
91 /* Boilerplate object stuff. */
92 /*****************************************************************************/
93 G_DEFINE_TYPE (glLabelBarcode, gl_label_barcode, GL_TYPE_LABEL_OBJECT);
97 gl_label_barcode_class_init (glLabelBarcodeClass *class)
99 GObjectClass *object_class = G_OBJECT_CLASS (class);
100 glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
102 gl_label_barcode_parent_class = g_type_class_peek_parent (class);
104 label_object_class->copy = copy;
105 label_object_class->get_size = get_size;
106 label_object_class->set_line_color = set_line_color;
107 label_object_class->get_line_color = get_line_color;
108 label_object_class->draw_object = draw_object;
109 label_object_class->draw_shadow = NULL;
110 label_object_class->object_at = object_at;
112 object_class->finalize = gl_label_barcode_finalize;
117 gl_label_barcode_init (glLabelBarcode *lbc)
119 lbc->priv = g_new0 (glLabelBarcodePrivate, 1);
120 lbc->priv->text_node = gl_text_node_new_from_text ("");
125 gl_label_barcode_finalize (GObject *object)
127 glLabelBarcode *lbc = GL_LABEL_BARCODE (object);
129 g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
131 gl_text_node_free (&lbc->priv->text_node);
132 g_free (lbc->priv->id);
133 gl_color_node_free (&(lbc->priv->color_node));
136 G_OBJECT_CLASS (gl_label_barcode_parent_class)->finalize (object);
140 /*****************************************************************************/
141 /* NEW label "barcode" object. */
142 /*****************************************************************************/
144 gl_label_barcode_new (glLabel *label,
148 glColorNode *line_color_node;
150 lbc = g_object_new (gl_label_barcode_get_type(), NULL);
156 gl_label_checkpoint (label, _("Create barcode object"));
159 /* Default barcode style and properties. */
160 lbc->priv->backend_id = g_strdup (gl_barcode_backends_backend_name_to_id (NULL));
161 lbc->priv->id = g_strdup (gl_barcode_backends_style_name_to_id (lbc->priv->backend_id,
163 lbc->priv->text_flag = gl_barcode_backends_style_can_text (lbc->priv->backend_id,
165 lbc->priv->checksum_flag = gl_barcode_backends_style_can_csum (lbc->priv->backend_id,
167 lbc->priv->format_digits = gl_barcode_backends_style_get_prefered_n (lbc->priv->backend_id,
170 line_color_node = gl_color_node_new_default ();
171 line_color_node->color = gl_label_get_default_line_color(label);
173 lbc->priv->color_node = line_color_node;
175 gl_label_add_object (label, GL_LABEL_OBJECT (lbc));
176 gl_label_object_set_parent (GL_LABEL_OBJECT (lbc), label);
179 return G_OBJECT (lbc);
183 /*****************************************************************************/
184 /* Copy object contents. */
185 /*****************************************************************************/
187 copy (glLabelObject *dst_object,
188 glLabelObject *src_object)
190 glLabelBarcode *lbc = (glLabelBarcode *)src_object;
191 glLabelBarcode *new_lbc = (glLabelBarcode *)dst_object;
192 glTextNode *text_node;
196 gboolean checksum_flag;
197 glColorNode *color_node;
200 gl_debug (DEBUG_LABEL, "START");
202 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
203 g_return_if_fail (new_lbc && GL_IS_LABEL_BARCODE (new_lbc));
205 text_node = gl_label_barcode_get_data (lbc);
206 gl_label_barcode_get_props (lbc, &backend_id, &id, &text_flag, &checksum_flag, &format_digits);
207 color_node = get_line_color (src_object);
209 gl_label_barcode_set_data (new_lbc, text_node, FALSE);
210 gl_label_barcode_set_props (new_lbc, backend_id, id, text_flag, checksum_flag, format_digits, FALSE);
211 set_line_color (dst_object, color_node, FALSE);
213 gl_color_node_free (&color_node);
214 gl_text_node_free (&text_node);
218 gl_debug (DEBUG_LABEL, "END");
222 /*****************************************************************************/
223 /* Set object params. */
224 /*****************************************************************************/
226 gl_label_barcode_set_data (glLabelBarcode *lbc,
227 glTextNode *text_node,
232 gl_debug (DEBUG_LABEL, "START");
234 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
236 if (!gl_text_node_equal (lbc->priv->text_node, text_node))
240 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbc));
241 gl_label_checkpoint (label, _("Barcode data"));
244 gl_text_node_free (&lbc->priv->text_node);
245 lbc->priv->text_node = gl_text_node_dup (text_node);
247 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
250 gl_debug (DEBUG_LABEL, "END");
255 gl_label_barcode_set_props (glLabelBarcode *lbc,
259 gboolean checksum_flag,
265 gl_debug (DEBUG_LABEL, "START");
267 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
269 if ( ((lbc->priv->backend_id == NULL) && (backend_id != NULL))
270 || ((lbc->priv->id == NULL) && (id != NULL))
271 || ((lbc->priv->backend_id != NULL) && (backend_id != NULL) && (g_ascii_strcasecmp (lbc->priv->backend_id, backend_id) != 0))
272 || ((lbc->priv->id != NULL) && (id != NULL) && (g_ascii_strcasecmp (lbc->priv->id, id) != 0))
273 || (lbc->priv->text_flag != text_flag)
274 || (lbc->priv->checksum_flag != checksum_flag)
275 || (lbc->priv->format_digits != format_digits))
279 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbc));
280 gl_label_checkpoint (label, _("Barcode property"));
283 lbc->priv->backend_id = g_strdup (backend_id);
284 lbc->priv->id = g_strdup (id);
285 lbc->priv->text_flag = text_flag;
286 lbc->priv->checksum_flag = checksum_flag;
287 lbc->priv->format_digits = format_digits;
289 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
292 gl_debug (DEBUG_LABEL, "END");
296 /*****************************************************************************/
297 /* Get object params. */
298 /*****************************************************************************/
300 gl_label_barcode_get_data (glLabelBarcode *lbc)
302 g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
304 return gl_text_node_dup (lbc->priv->text_node);
309 gl_label_barcode_get_props (glLabelBarcode *lbc,
313 gboolean *checksum_flag,
314 guint *format_digits)
316 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
318 *backend_id = g_strdup (lbc->priv->backend_id);
319 *id = g_strdup (lbc->priv->id);
320 *text_flag = lbc->priv->text_flag;
321 *checksum_flag = lbc->priv->checksum_flag;
322 *format_digits = lbc->priv->format_digits;
326 /*---------------------------------------------------------------------------*/
327 /* PRIVATE. Get object size method. */
328 /*---------------------------------------------------------------------------*/
330 get_size (glLabelObject *object,
334 glLabelBarcode *lbc = (glLabelBarcode *)object;
336 gdouble w_parent, h_parent;
339 gl_debug (DEBUG_LABEL, "START");
341 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
343 gl_label_object_get_raw_size (object, &w_parent, &h_parent);
345 if (lbc->priv->text_node->field_flag) {
346 data = gl_barcode_backends_style_default_digits (lbc->priv->backend_id,
348 lbc->priv->format_digits);
350 data = gl_text_node_expand (lbc->priv->text_node, NULL);
353 gbc = gl_barcode_backends_new_barcode (lbc->priv->backend_id,
355 lbc->priv->text_flag,
356 lbc->priv->checksum_flag,
363 /* Try again with default digits. */
364 data = gl_barcode_backends_style_default_digits (lbc->priv->backend_id,
366 lbc->priv->format_digits);
367 gbc = gl_barcode_backends_new_barcode (lbc->priv->backend_id,
369 lbc->priv->text_flag,
370 lbc->priv->checksum_flag,
384 /* If we still can't render, just set a default size. */
389 gl_barcode_free (&gbc);
391 gl_debug (DEBUG_LABEL, "END");
395 /*---------------------------------------------------------------------------*/
396 /* PRIVATE. Set line color method. */
397 /*---------------------------------------------------------------------------*/
399 set_line_color (glLabelObject *object,
400 glColorNode *line_color_node,
403 glLabelBarcode *lbarcode = (glLabelBarcode *)object;
406 g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
408 if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) )
412 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbarcode));
413 gl_label_checkpoint (label, _("Barcode data"));
416 gl_color_node_free (&(lbarcode->priv->color_node));
417 lbarcode->priv->color_node = gl_color_node_dup (line_color_node);
418 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbarcode));
423 /*---------------------------------------------------------------------------*/
424 /* PRIVATE. Get line color method. */
425 /*---------------------------------------------------------------------------*/
427 get_line_color (glLabelObject *object)
429 glLabelBarcode *lbarcode = (glLabelBarcode *)object;
431 g_return_val_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode), NULL);
433 return gl_color_node_dup (lbarcode->priv->color_node);
437 /*****************************************************************************/
438 /* Draw object method. */
439 /*****************************************************************************/
441 draw_object (glLabelObject *object,
443 gboolean screen_flag,
444 glMergeRecord *record)
447 cairo_matrix_t matrix;
449 glBarcodeShape *shape;
450 glBarcodeShapeLine *line;
451 glBarcodeShapeBox *box;
452 glBarcodeShapeRing *ring;
453 glBarcodeShapeHexagon *hexagon;
454 glBarcodeShapeChar *bchar;
455 glBarcodeShapeString *bstring;
457 gdouble x_offset, y_offset;
459 PangoFontDescription *desc;
460 gchar *text, *cstring;
461 glTextNode *text_node;
465 gboolean checksum_flag;
467 glColorNode *color_node;
471 gdouble layout_width;
473 gl_debug (DEBUG_LABEL, "START");
475 gl_label_object_get_position (object, &x0, &y0);
476 gl_label_object_get_matrix (object, &matrix);
478 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE (object));
479 gl_label_barcode_get_props (GL_LABEL_BARCODE (object),
480 &backend_id, &id, &text_flag, &checksum_flag, &format_digits);
482 color_node = gl_label_object_get_line_color (object);
483 color = gl_color_node_expand (color_node, record);
484 if (color_node->field_flag && screen_flag)
486 color = GL_COLOR_MERGE_DEFAULT;
488 gl_color_node_free (&color_node);
490 gl_label_object_get_size (object, &w, &h);
492 text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
493 text = gl_text_node_expand (text_node, record);
494 if (text_node->field_flag && screen_flag) {
495 text = gl_barcode_backends_style_default_digits (backend_id, id, format_digits);
498 gbc = gl_barcode_backends_new_barcode (backend_id, id, text_flag, checksum_flag, w, h, text);
500 cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
504 layout = pango_cairo_create_layout (cr);
506 desc = pango_font_description_new ();
507 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
508 pango_font_description_set_size (desc, 12 * PANGO_SCALE * FONT_SCALE);
509 pango_layout_set_font_description (layout, desc);
510 pango_font_description_free (desc);
512 if (text == NULL || *text == '\0')
514 pango_layout_set_text (layout, _("Barcode data empty"), -1);
518 pango_layout_set_text (layout, _("Invalid barcode data"), -1);
521 cairo_move_to (cr, 0, 0);
522 pango_cairo_show_layout (cr, layout);
524 g_object_unref (layout);
528 for (p = gbc->shapes; p != NULL; p = p->next) {
529 shape = (glBarcodeShape *)p->data;
533 case GL_BARCODE_SHAPE_LINE:
534 line = (glBarcodeShapeLine *) shape;
536 cairo_move_to (cr, line->x, line->y);
537 cairo_line_to (cr, line->x, line->y + line->length);
538 cairo_set_line_width (cr, line->width);
543 case GL_BARCODE_SHAPE_BOX:
544 box = (glBarcodeShapeBox *) shape;
546 cairo_rectangle (cr, box->x, box->y, box->width, box->height);
551 case GL_BARCODE_SHAPE_CHAR:
552 bchar = (glBarcodeShapeChar *) shape;
554 layout = pango_cairo_create_layout (cr);
556 desc = pango_font_description_new ();
557 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
558 pango_font_description_set_size (desc, bchar->fsize * PANGO_SCALE * FONT_SCALE);
559 pango_layout_set_font_description (layout, desc);
560 pango_font_description_free (desc);
562 cstring = g_strdup_printf ("%c", bchar->c);
563 pango_layout_set_text (layout, cstring, -1);
566 y_offset = 0.2 * bchar->fsize;
568 cairo_move_to (cr, bchar->x, bchar->y-y_offset);
569 pango_cairo_show_layout (cr, layout);
571 g_object_unref (layout);
575 case GL_BARCODE_SHAPE_STRING:
576 bstring = (glBarcodeShapeString *) shape;
578 layout = pango_cairo_create_layout (cr);
580 desc = pango_font_description_new ();
581 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
582 pango_font_description_set_size (desc, bstring->fsize * PANGO_SCALE * FONT_SCALE);
583 pango_layout_set_font_description (layout, desc);
584 pango_font_description_free (desc);
586 pango_layout_set_text (layout, bstring->string, -1);
588 pango_layout_get_size (layout, &iw, &ih);
589 layout_width = (gdouble)iw / (gdouble)PANGO_SCALE;
591 x_offset = layout_width / 2.0;
592 y_offset = 0.2 * bstring->fsize;
594 cairo_move_to (cr, (bstring->x - x_offset), (bstring->y - y_offset));
595 pango_cairo_show_layout (cr, layout);
597 g_object_unref (layout);
601 case GL_BARCODE_SHAPE_RING:
602 ring = (glBarcodeShapeRing *) shape;
604 cairo_arc (cr, ring->x, ring->y, ring->radius, 0.0, 2 * PI);
605 cairo_set_line_width (cr, ring->line_width);
610 case GL_BARCODE_SHAPE_HEXAGON:
611 hexagon = (glBarcodeShapeHexagon *) shape;
613 cairo_move_to (cr, hexagon->x, hexagon->y);
614 cairo_line_to (cr, hexagon->x + 1.25, hexagon->y + 0.70);
615 cairo_line_to (cr, hexagon->x + 1.25, hexagon->y + 2.18);
616 cairo_line_to (cr, hexagon->x, hexagon->y + 2.89);
617 cairo_line_to (cr, hexagon->x - 1.25, hexagon->y + 2.18);
618 cairo_line_to (cr, hexagon->x - 1.25, hexagon->y + 0.70);
619 cairo_close_path (cr);
625 g_assert_not_reached ();
632 gl_barcode_free (&gbc);
637 gl_text_node_free (&text_node);
641 gl_debug (DEBUG_LABEL, "END");
645 /*****************************************************************************/
646 /* Is object at coordinates? */
647 /*****************************************************************************/
649 object_at (glLabelObject *object,
656 gl_label_object_get_size (object, &w, &h);
659 cairo_rectangle (cr, 0.0, 0.0, w, h);
661 if (cairo_in_fill (cr, x, y))
673 * Local Variables: -- emacs
675 * c-basic-offset: 8 -- emacs
676 * tab-width: 8 -- emacs
677 * indent-tabs-mode: nil -- emacs