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"
33 /*========================================================*/
34 /* Private macros and constants. */
35 /*========================================================*/
37 #define FONT_SCALE (72.0/96.0)
40 /*========================================================*/
42 /*========================================================*/
44 struct _glLabelBarcodePrivate {
45 glTextNode *text_node;
47 glColorNode *color_node;
49 gboolean checksum_flag;
54 /*========================================================*/
55 /* Private globals. */
56 /*========================================================*/
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,
76 static glColorNode *get_line_color (glLabelObject *object);
78 static void draw_object (glLabelObject *object,
81 glMergeRecord *record);
83 static gboolean object_at (glLabelObject *object,
89 /*****************************************************************************/
90 /* Boilerplate object stuff. */
91 /*****************************************************************************/
92 G_DEFINE_TYPE (glLabelBarcode, gl_label_barcode, GL_TYPE_LABEL_OBJECT);
96 gl_label_barcode_class_init (glLabelBarcodeClass *class)
98 GObjectClass *object_class = G_OBJECT_CLASS (class);
99 glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
101 gl_label_barcode_parent_class = g_type_class_peek_parent (class);
103 label_object_class->copy = copy;
104 label_object_class->get_size = get_size;
105 label_object_class->set_line_color = set_line_color;
106 label_object_class->get_line_color = get_line_color;
107 label_object_class->draw_object = draw_object;
108 label_object_class->draw_shadow = NULL;
109 label_object_class->object_at = object_at;
111 object_class->finalize = gl_label_barcode_finalize;
116 gl_label_barcode_init (glLabelBarcode *lbc)
118 lbc->priv = g_new0 (glLabelBarcodePrivate, 1);
119 lbc->priv->text_node = gl_text_node_new_from_text ("");
124 gl_label_barcode_finalize (GObject *object)
126 glLabelBarcode *lbc = GL_LABEL_BARCODE (object);
128 g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
130 gl_text_node_free (&lbc->priv->text_node);
131 g_free (lbc->priv->id);
132 gl_color_node_free (&(lbc->priv->color_node));
135 G_OBJECT_CLASS (gl_label_barcode_parent_class)->finalize (object);
139 /*****************************************************************************/
140 /* NEW label "barcode" object. */
141 /*****************************************************************************/
143 gl_label_barcode_new (glLabel *label,
147 glColorNode *line_color_node;
149 lbc = g_object_new (gl_label_barcode_get_type(), NULL);
155 gl_label_checkpoint (label, _("Create barcode object"));
158 line_color_node = gl_color_node_new_default ();
160 line_color_node->color = gl_label_get_default_line_color(label);
162 lbc->priv->color_node = line_color_node;
164 gl_label_add_object (label, GL_LABEL_OBJECT (lbc));
165 gl_label_object_set_parent (GL_LABEL_OBJECT (lbc), label);
168 return G_OBJECT (lbc);
172 /*****************************************************************************/
173 /* Copy object contents. */
174 /*****************************************************************************/
176 copy (glLabelObject *dst_object,
177 glLabelObject *src_object)
179 glLabelBarcode *lbc = (glLabelBarcode *)src_object;
180 glLabelBarcode *new_lbc = (glLabelBarcode *)dst_object;
181 glTextNode *text_node;
184 gboolean checksum_flag;
185 glColorNode *color_node;
188 gl_debug (DEBUG_LABEL, "START");
190 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
191 g_return_if_fail (new_lbc && GL_IS_LABEL_BARCODE (new_lbc));
193 text_node = gl_label_barcode_get_data (lbc);
194 gl_label_barcode_get_props (lbc, &id, &text_flag, &checksum_flag, &format_digits);
195 color_node = get_line_color (src_object);
197 gl_label_barcode_set_data (new_lbc, text_node, FALSE);
198 gl_label_barcode_set_props (new_lbc, id, text_flag, checksum_flag, format_digits, FALSE);
199 set_line_color (dst_object, color_node, FALSE);
201 gl_color_node_free (&color_node);
202 gl_text_node_free (&text_node);
205 gl_debug (DEBUG_LABEL, "END");
209 /*****************************************************************************/
210 /* Set object params. */
211 /*****************************************************************************/
213 gl_label_barcode_set_data (glLabelBarcode *lbc,
214 glTextNode *text_node,
219 gl_debug (DEBUG_LABEL, "START");
221 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
223 if (!gl_text_node_equal (lbc->priv->text_node, text_node))
227 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbc));
228 gl_label_checkpoint (label, _("Barcode data"));
231 gl_text_node_free (&lbc->priv->text_node);
232 lbc->priv->text_node = gl_text_node_dup (text_node);
234 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
237 gl_debug (DEBUG_LABEL, "END");
242 gl_label_barcode_set_props (glLabelBarcode *lbc,
245 gboolean checksum_flag,
251 gl_debug (DEBUG_LABEL, "START");
253 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
255 if ( ((lbc->priv->id == NULL) && (id != NULL))
256 || ((lbc->priv->id != NULL) && (id != NULL) && (g_ascii_strcasecmp (lbc->priv->id, id) != 0))
257 || (lbc->priv->text_flag != text_flag)
258 || (lbc->priv->checksum_flag != checksum_flag)
259 || (lbc->priv->format_digits != format_digits))
263 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbc));
264 gl_label_checkpoint (label, _("Barcode property"));
267 lbc->priv->id = g_strdup (id);
268 lbc->priv->text_flag = text_flag;
269 lbc->priv->checksum_flag = checksum_flag;
270 lbc->priv->format_digits = format_digits;
272 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
275 gl_debug (DEBUG_LABEL, "END");
279 /*****************************************************************************/
280 /* Get object params. */
281 /*****************************************************************************/
283 gl_label_barcode_get_data (glLabelBarcode *lbc)
285 g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
287 return gl_text_node_dup (lbc->priv->text_node);
292 gl_label_barcode_get_props (glLabelBarcode *lbc,
295 gboolean *checksum_flag,
296 guint *format_digits)
298 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
300 *id = g_strdup (lbc->priv->id);
301 *text_flag = lbc->priv->text_flag;
302 *checksum_flag = lbc->priv->checksum_flag;
303 *format_digits = lbc->priv->format_digits;
307 /*---------------------------------------------------------------------------*/
308 /* PRIVATE. Get object size method. */
309 /*---------------------------------------------------------------------------*/
311 get_size (glLabelObject *object,
315 glLabelBarcode *lbc = (glLabelBarcode *)object;
317 gdouble w_parent, h_parent;
320 gl_debug (DEBUG_LABEL, "START");
322 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
324 gl_label_object_get_raw_size (object, &w_parent, &h_parent);
326 if (lbc->priv->text_node->field_flag) {
327 data = gl_barcode_backends_default_digits (lbc->priv->id,
328 lbc->priv->format_digits);
330 data = gl_text_node_expand (lbc->priv->text_node, NULL);
333 gbc = gl_barcode_backends_new_barcode (lbc->priv->id,
334 lbc->priv->text_flag,
335 lbc->priv->checksum_flag,
342 /* Try again with default digits. */
343 data = gl_barcode_backends_default_digits (lbc->priv->id,
344 lbc->priv->format_digits);
345 gbc = gl_barcode_backends_new_barcode (lbc->priv->id,
346 lbc->priv->text_flag,
347 lbc->priv->checksum_flag,
361 /* If we still can't render, just set a default size. */
366 gl_barcode_free (&gbc);
368 gl_debug (DEBUG_LABEL, "END");
372 /*---------------------------------------------------------------------------*/
373 /* PRIVATE. Set line color method. */
374 /*---------------------------------------------------------------------------*/
376 set_line_color (glLabelObject *object,
377 glColorNode *line_color_node,
380 glLabelBarcode *lbarcode = (glLabelBarcode *)object;
383 g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
385 if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) )
389 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbarcode));
390 gl_label_checkpoint (label, _("Barcode data"));
393 gl_color_node_free (&(lbarcode->priv->color_node));
394 lbarcode->priv->color_node = gl_color_node_dup (line_color_node);
395 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbarcode));
400 /*---------------------------------------------------------------------------*/
401 /* PRIVATE. Get line color method. */
402 /*---------------------------------------------------------------------------*/
404 get_line_color (glLabelObject *object)
406 glLabelBarcode *lbarcode = (glLabelBarcode *)object;
408 g_return_val_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode), NULL);
410 return gl_color_node_dup (lbarcode->priv->color_node);
414 /*****************************************************************************/
415 /* Draw object method. */
416 /*****************************************************************************/
418 draw_object (glLabelObject *object,
420 gboolean screen_flag,
421 glMergeRecord *record)
424 cairo_matrix_t matrix;
426 glBarcodeShape *shape;
427 glBarcodeShapeLine *line;
428 glBarcodeShapeBox *box;
429 glBarcodeShapeChar *bchar;
430 glBarcodeShapeString *bstring;
432 gdouble x_offset, y_offset;
434 PangoFontDescription *desc;
435 gchar *text, *cstring;
436 glTextNode *text_node;
439 gboolean checksum_flag;
441 glColorNode *color_node;
445 gdouble layout_width;
447 gl_debug (DEBUG_LABEL, "START");
449 gl_label_object_get_position (object, &x0, &y0);
450 gl_label_object_get_matrix (object, &matrix);
452 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE (object));
453 gl_label_barcode_get_props (GL_LABEL_BARCODE (object),
454 &id, &text_flag, &checksum_flag, &format_digits);
456 color_node = gl_label_object_get_line_color (object);
457 color = gl_color_node_expand (color_node, record);
458 if (color_node->field_flag && screen_flag)
460 color = GL_COLOR_MERGE_DEFAULT;
462 gl_color_node_free (&color_node);
464 gl_label_object_get_size (object, &w, &h);
466 text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
467 text = gl_text_node_expand (text_node, record);
468 if (text_node->field_flag && screen_flag) {
469 text = gl_barcode_backends_default_digits (id, format_digits);
472 gbc = gl_barcode_backends_new_barcode (id, text_flag, checksum_flag, w, h, text);
474 cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
478 layout = pango_cairo_create_layout (cr);
480 desc = pango_font_description_new ();
481 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
482 pango_font_description_set_size (desc, 12 * PANGO_SCALE * FONT_SCALE);
483 pango_layout_set_font_description (layout, desc);
484 pango_font_description_free (desc);
486 if (text == NULL || *text == '\0')
488 pango_layout_set_text (layout, _("Barcode data empty"), -1);
492 pango_layout_set_text (layout, _("Invalid barcode data"), -1);
495 cairo_move_to (cr, 0, 0);
496 pango_cairo_show_layout (cr, layout);
498 g_object_unref (layout);
502 for (p = gbc->shapes; p != NULL; p = p->next) {
503 shape = (glBarcodeShape *)p->data;
507 case GL_BARCODE_SHAPE_LINE:
508 line = (glBarcodeShapeLine *) shape;
510 cairo_move_to (cr, line->x, line->y);
511 cairo_line_to (cr, line->x, line->y + line->length);
512 cairo_set_line_width (cr, line->width);
517 case GL_BARCODE_SHAPE_BOX:
518 box = (glBarcodeShapeBox *) shape;
520 cairo_rectangle (cr, box->x, box->y, box->width, box->height);
525 case GL_BARCODE_SHAPE_CHAR:
526 bchar = (glBarcodeShapeChar *) shape;
528 layout = pango_cairo_create_layout (cr);
530 desc = pango_font_description_new ();
531 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
532 pango_font_description_set_size (desc, bchar->fsize * PANGO_SCALE * FONT_SCALE);
533 pango_layout_set_font_description (layout, desc);
534 pango_font_description_free (desc);
536 cstring = g_strdup_printf ("%c", bchar->c);
537 pango_layout_set_text (layout, cstring, -1);
540 y_offset = 0.2 * bchar->fsize;
542 cairo_move_to (cr, bchar->x, bchar->y-y_offset);
543 pango_cairo_show_layout (cr, layout);
545 g_object_unref (layout);
549 case GL_BARCODE_SHAPE_STRING:
550 bstring = (glBarcodeShapeString *) shape;
552 layout = pango_cairo_create_layout (cr);
554 desc = pango_font_description_new ();
555 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
556 pango_font_description_set_size (desc, bstring->fsize * PANGO_SCALE * FONT_SCALE);
557 pango_layout_set_font_description (layout, desc);
558 pango_font_description_free (desc);
560 pango_layout_set_text (layout, bstring->string, -1);
562 pango_layout_get_size (layout, &iw, &ih);
563 layout_width = (gdouble)iw / (gdouble)PANGO_SCALE;
565 x_offset = layout_width / 2.0;
566 y_offset = 0.2 * bstring->fsize;
568 cairo_move_to (cr, (bstring->x - x_offset), (bstring->y - y_offset));
569 pango_cairo_show_layout (cr, layout);
571 g_object_unref (layout);
576 g_assert_not_reached ();
583 gl_barcode_free (&gbc);
588 gl_text_node_free (&text_node);
591 gl_debug (DEBUG_LABEL, "END");
595 /*****************************************************************************/
596 /* Is object at coordinates? */
597 /*****************************************************************************/
599 object_at (glLabelObject *object,
606 gl_label_object_get_size (object, &w, &h);
609 cairo_rectangle (cr, 0.0, 0.0, w, h);
611 if (cairo_in_fill (cr, x, y))
623 * Local Variables: -- emacs
625 * c-basic-offset: 8 -- emacs
626 * tab-width: 8 -- emacs
627 * indent-tabs-mode: nil -- emacs