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
39 #define GL_BARCODE_FONT_FAMILY "Sans"
42 /*========================================================*/
44 /*========================================================*/
46 struct _glLabelBarcodePrivate {
48 glTextNode *text_node;
49 glLabelBarcodeStyle *style;
50 glColorNode *color_node;
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 gl_label_barcode_style_free (lbc->priv->style);
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 glLabelBarcodeStyle *style;
149 glColorNode *line_color_node;
151 lbc = g_object_new (gl_label_barcode_get_type(), NULL);
157 gl_label_checkpoint (label, _("Create barcode object"));
160 /* Default barcode style and properties. */
161 style = gl_label_barcode_style_new ();
162 gl_label_barcode_style_set_backend_id (style, gl_barcode_backends_backend_name_to_id (NULL));
163 gl_label_barcode_style_set_style_id (style, gl_barcode_backends_style_name_to_id (style->backend_id, NULL));
164 style->text_flag = gl_barcode_backends_style_can_text (style->backend_id, style->id);
165 style->checksum_flag = gl_barcode_backends_style_can_csum (style->backend_id, style->id);
166 style->format_digits = gl_barcode_backends_style_get_prefered_n (style->backend_id, style->id);
167 lbc->priv->style = style;
169 line_color_node = gl_color_node_new_default ();
170 line_color_node->color = gl_label_get_default_line_color(label);
171 lbc->priv->color_node = line_color_node;
173 gl_label_add_object (label, GL_LABEL_OBJECT (lbc));
174 gl_label_object_set_parent (GL_LABEL_OBJECT (lbc), label);
177 return G_OBJECT (lbc);
181 /*****************************************************************************/
182 /* Copy object contents. */
183 /*****************************************************************************/
185 copy (glLabelObject *dst_object,
186 glLabelObject *src_object)
188 glLabelBarcode *lbc = (glLabelBarcode *)src_object;
189 glLabelBarcode *new_lbc = (glLabelBarcode *)dst_object;
190 glTextNode *text_node;
191 glLabelBarcodeStyle *style;
192 glColorNode *color_node;
194 gl_debug (DEBUG_LABEL, "START");
196 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
197 g_return_if_fail (new_lbc && GL_IS_LABEL_BARCODE (new_lbc));
199 text_node = gl_label_barcode_get_data (lbc);
200 style = gl_label_barcode_get_style (lbc);
201 color_node = get_line_color (src_object);
203 gl_label_barcode_set_data (new_lbc, text_node, FALSE);
204 gl_label_barcode_set_style (new_lbc, style, FALSE);
205 set_line_color (dst_object, color_node, FALSE);
207 gl_color_node_free (&color_node);
208 gl_text_node_free (&text_node);
210 gl_debug (DEBUG_LABEL, "END");
214 /*****************************************************************************/
215 /* Set object params. */
216 /*****************************************************************************/
218 gl_label_barcode_set_data (glLabelBarcode *lbc,
219 const glTextNode *text_node,
224 gl_debug (DEBUG_LABEL, "START");
226 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
228 if (!gl_text_node_equal (lbc->priv->text_node, text_node))
232 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbc));
233 gl_label_checkpoint (label, _("Barcode data"));
236 gl_text_node_free (&lbc->priv->text_node);
237 lbc->priv->text_node = gl_text_node_dup (text_node);
239 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
242 gl_debug (DEBUG_LABEL, "END");
247 gl_label_barcode_set_style (glLabelBarcode *lbc,
248 const glLabelBarcodeStyle *style,
253 gl_debug (DEBUG_LABEL, "START");
255 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
257 if ( !gl_label_barcode_style_is_equal (style, lbc->priv->style) )
261 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbc));
262 gl_label_checkpoint (label, _("Barcode property"));
265 gl_label_barcode_style_free (lbc->priv->style);
266 lbc->priv->style = gl_label_barcode_style_dup (style);
268 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
271 gl_debug (DEBUG_LABEL, "END");
275 /*****************************************************************************/
276 /* Get object params. */
277 /*****************************************************************************/
279 gl_label_barcode_get_data (glLabelBarcode *lbc)
281 g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
283 return gl_text_node_dup (lbc->priv->text_node);
287 glLabelBarcodeStyle *
288 gl_label_barcode_get_style (glLabelBarcode *lbc)
290 g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
292 return gl_label_barcode_style_dup (lbc->priv->style);
296 /*---------------------------------------------------------------------------*/
297 /* PRIVATE. Get object size method. */
298 /*---------------------------------------------------------------------------*/
300 get_size (glLabelObject *object,
304 glLabelBarcode *lbc = (glLabelBarcode *)object;
306 gdouble w_parent, h_parent;
309 gl_debug (DEBUG_LABEL, "START");
311 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
313 gl_label_object_get_raw_size (object, &w_parent, &h_parent);
315 if (lbc->priv->text_node->field_flag) {
316 data = gl_barcode_backends_style_default_digits (lbc->priv->style->backend_id,
317 lbc->priv->style->id,
318 lbc->priv->style->format_digits);
320 data = gl_text_node_expand (lbc->priv->text_node, NULL);
323 gbc = gl_barcode_backends_new_barcode (lbc->priv->style->backend_id,
324 lbc->priv->style->id,
325 lbc->priv->style->text_flag,
326 lbc->priv->style->checksum_flag,
333 /* Try again with default digits. */
334 data = gl_barcode_backends_style_default_digits (lbc->priv->style->backend_id,
335 lbc->priv->style->id,
336 lbc->priv->style->format_digits);
337 gbc = gl_barcode_backends_new_barcode (lbc->priv->style->backend_id,
338 lbc->priv->style->id,
339 lbc->priv->style->text_flag,
340 lbc->priv->style->checksum_flag,
354 /* If we still can't render, just set a default size. */
359 lgl_barcode_free (gbc);
361 gl_debug (DEBUG_LABEL, "END");
365 /*---------------------------------------------------------------------------*/
366 /* PRIVATE. Set line color method. */
367 /*---------------------------------------------------------------------------*/
369 set_line_color (glLabelObject *object,
370 glColorNode *line_color_node,
373 glLabelBarcode *lbarcode = (glLabelBarcode *)object;
376 g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
378 if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) )
382 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbarcode));
383 gl_label_checkpoint (label, _("Barcode data"));
386 gl_color_node_free (&(lbarcode->priv->color_node));
387 lbarcode->priv->color_node = gl_color_node_dup (line_color_node);
388 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbarcode));
393 /*---------------------------------------------------------------------------*/
394 /* PRIVATE. Get line color method. */
395 /*---------------------------------------------------------------------------*/
397 get_line_color (glLabelObject *object)
399 glLabelBarcode *lbarcode = (glLabelBarcode *)object;
401 g_return_val_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode), NULL);
403 return gl_color_node_dup (lbarcode->priv->color_node);
407 /*****************************************************************************/
408 /* Draw object method. */
409 /*****************************************************************************/
411 draw_object (glLabelObject *object,
413 gboolean screen_flag,
414 glMergeRecord *record)
417 cairo_matrix_t matrix;
420 PangoFontDescription *desc;
422 glTextNode *text_node;
423 glLabelBarcodeStyle *style;
425 glColorNode *color_node;
428 gl_debug (DEBUG_LABEL, "START");
430 gl_label_object_get_position (object, &x0, &y0);
431 gl_label_object_get_matrix (object, &matrix);
433 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE (object));
434 style = gl_label_barcode_get_style (GL_LABEL_BARCODE (object));
436 color_node = gl_label_object_get_line_color (object);
437 color = gl_color_node_expand (color_node, record);
438 if (color_node->field_flag && screen_flag)
440 color = GL_COLOR_MERGE_DEFAULT;
443 gl_label_object_get_size (object, &w, &h);
445 text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
446 text = gl_text_node_expand (text_node, record);
447 if (text_node->field_flag && screen_flag) {
448 text = gl_barcode_backends_style_default_digits (style->backend_id, style->id, style->format_digits);
451 gbc = gl_barcode_backends_new_barcode (style->backend_id, style->id, style->text_flag, style->checksum_flag, w, h, text);
453 cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
457 layout = pango_cairo_create_layout (cr);
459 desc = pango_font_description_new ();
460 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
461 pango_font_description_set_size (desc, 12 * PANGO_SCALE * FONT_SCALE);
462 pango_layout_set_font_description (layout, desc);
463 pango_font_description_free (desc);
465 if (text == NULL || *text == '\0')
467 pango_layout_set_text (layout, _("Barcode data empty"), -1);
471 pango_layout_set_text (layout, _("Invalid barcode data"), -1);
474 cairo_move_to (cr, 0, 0);
475 pango_cairo_show_layout (cr, layout);
477 g_object_unref (layout);
481 lgl_barcode_render_to_cairo (gbc, cr);
483 lgl_barcode_free (gbc);
488 gl_text_node_free (&text_node);
489 gl_label_barcode_style_free (style);
490 gl_color_node_free (&color_node);
492 gl_debug (DEBUG_LABEL, "END");
496 /*****************************************************************************/
497 /* Is object at coordinates? */
498 /*****************************************************************************/
500 object_at (glLabelObject *object,
507 gl_label_object_get_size (object, &w, &h);
510 cairo_rectangle (cr, 0.0, 0.0, w, h);
512 if (cairo_in_fill (cr, x, y))
521 /*****************************************************************************/
522 /* Barcode style utilities. */
523 /*****************************************************************************/
524 glLabelBarcodeStyle *
525 gl_label_barcode_style_new (void)
527 return g_new0 (glLabelBarcodeStyle, 1);
531 glLabelBarcodeStyle *
532 gl_label_barcode_style_dup (const glLabelBarcodeStyle *style)
534 glLabelBarcodeStyle *style2;
536 style2 = gl_label_barcode_style_new ();
538 /* Shallow copy first. */
542 style2->backend_id = g_strdup (style->backend_id);
543 style2->id = g_strdup (style->id);
550 gl_label_barcode_style_free (glLabelBarcodeStyle *style)
554 g_free (style->backend_id);
563 gl_label_barcode_style_is_equal (const glLabelBarcodeStyle *style1,
564 const glLabelBarcodeStyle *style2)
567 /* First take care of the case of either or both being NULL. */
568 if ( style1 == NULL )
570 return ( style2 == NULL );
574 if ( style2 == NULL )
580 /* Compare field by field, bail on first difference. */
581 if ( style1->text_flag != style2->text_flag )
585 if ( style1->checksum_flag != style2->checksum_flag )
589 if ( style1->format_digits != style2->format_digits )
593 if ( style1->backend_id && style2->backend_id )
595 if ( strcmp (style1->backend_id, style2->backend_id) != 0 )
602 if ( style1->backend_id != style2->backend_id )
607 if ( style1->id && style2->id )
609 if ( strcmp (style1->id, style2->id) != 0 )
616 if ( style1->id != style2->id )
622 /* Passed all tests. */
628 gl_label_barcode_style_set_backend_id (glLabelBarcodeStyle *style,
629 const gchar *backend_id)
631 style->backend_id = g_strdup (backend_id);
636 gl_label_barcode_style_set_style_id (glLabelBarcodeStyle *style,
639 style->id = g_strdup (id);
647 * Local Variables: -- emacs
649 * c-basic-offset: 8 -- emacs
650 * tab-width: 8 -- emacs
651 * indent-tabs-mode: nil -- emacs