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"
41 #define HANDLE_OUTLINE_RGBA_ARGS 0.5, 0.5, 0.5, 0.75
42 #define HANDLE_OUTLINE_WIDTH_PIXELS 2.0
45 /*========================================================*/
47 /*========================================================*/
49 struct _glLabelBarcodePrivate {
51 glTextNode *text_node;
52 glLabelBarcodeStyle *style;
53 glColorNode *color_node;
58 /*========================================================*/
59 /* Private globals. */
60 /*========================================================*/
63 /*========================================================*/
64 /* Private function prototypes. */
65 /*========================================================*/
67 static void gl_label_barcode_finalize (GObject *object);
69 static void copy (glLabelObject *dst_object,
70 glLabelObject *src_object);
72 static void get_size (glLabelObject *object,
76 static void set_line_color (glLabelObject *object,
77 glColorNode *line_color,
80 static glColorNode *get_line_color (glLabelObject *object);
82 static void draw_object (glLabelObject *object,
85 glMergeRecord *record);
87 static gboolean object_at (glLabelObject *object,
92 static void draw_handles (glLabelObject *object,
96 /*****************************************************************************/
97 /* Boilerplate object stuff. */
98 /*****************************************************************************/
99 G_DEFINE_TYPE (glLabelBarcode, gl_label_barcode, GL_TYPE_LABEL_OBJECT);
103 gl_label_barcode_class_init (glLabelBarcodeClass *class)
105 GObjectClass *object_class = G_OBJECT_CLASS (class);
106 glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
108 gl_label_barcode_parent_class = g_type_class_peek_parent (class);
110 label_object_class->copy = copy;
111 label_object_class->get_size = get_size;
112 label_object_class->set_line_color = set_line_color;
113 label_object_class->get_line_color = get_line_color;
114 label_object_class->draw_object = draw_object;
115 label_object_class->draw_shadow = NULL;
116 label_object_class->object_at = object_at;
117 label_object_class->draw_handles = draw_handles;
119 object_class->finalize = gl_label_barcode_finalize;
124 gl_label_barcode_init (glLabelBarcode *lbc)
126 lbc->priv = g_new0 (glLabelBarcodePrivate, 1);
127 lbc->priv->text_node = gl_text_node_new_from_text ("");
132 gl_label_barcode_finalize (GObject *object)
134 glLabelBarcode *lbc = GL_LABEL_BARCODE (object);
136 g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
138 gl_text_node_free (&lbc->priv->text_node);
139 gl_label_barcode_style_free (lbc->priv->style);
140 gl_color_node_free (&(lbc->priv->color_node));
143 G_OBJECT_CLASS (gl_label_barcode_parent_class)->finalize (object);
147 /*****************************************************************************/
148 /* NEW label "barcode" object. */
149 /*****************************************************************************/
151 gl_label_barcode_new (glLabel *label,
155 glLabelBarcodeStyle *style;
156 glColorNode *line_color_node;
158 lbc = g_object_new (gl_label_barcode_get_type(), NULL);
164 gl_label_checkpoint (label, _("Create barcode object"));
167 /* Default barcode style and properties. */
168 style = gl_label_barcode_style_new ();
169 gl_label_barcode_style_set_backend_id (style, gl_barcode_backends_backend_name_to_id (NULL));
170 gl_label_barcode_style_set_style_id (style, gl_barcode_backends_style_name_to_id (style->backend_id, NULL));
171 style->text_flag = gl_barcode_backends_style_can_text (style->backend_id, style->id);
172 style->checksum_flag = gl_barcode_backends_style_can_csum (style->backend_id, style->id);
173 style->format_digits = gl_barcode_backends_style_get_prefered_n (style->backend_id, style->id);
174 lbc->priv->style = style;
176 line_color_node = gl_color_node_new_default ();
177 line_color_node->color = gl_label_get_default_line_color(label);
178 lbc->priv->color_node = line_color_node;
180 gl_label_add_object (label, GL_LABEL_OBJECT (lbc));
181 gl_label_object_set_parent (GL_LABEL_OBJECT (lbc), label);
184 return G_OBJECT (lbc);
188 /*****************************************************************************/
189 /* Copy object contents. */
190 /*****************************************************************************/
192 copy (glLabelObject *dst_object,
193 glLabelObject *src_object)
195 glLabelBarcode *lbc = (glLabelBarcode *)src_object;
196 glLabelBarcode *new_lbc = (glLabelBarcode *)dst_object;
197 glTextNode *text_node;
198 glLabelBarcodeStyle *style;
199 glColorNode *color_node;
201 gl_debug (DEBUG_LABEL, "START");
203 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
204 g_return_if_fail (new_lbc && GL_IS_LABEL_BARCODE (new_lbc));
206 text_node = gl_label_barcode_get_data (lbc);
207 style = gl_label_barcode_get_style (lbc);
208 color_node = get_line_color (src_object);
210 gl_label_barcode_set_data (new_lbc, text_node, FALSE);
211 gl_label_barcode_set_style (new_lbc, style, FALSE);
212 set_line_color (dst_object, color_node, FALSE);
214 gl_color_node_free (&color_node);
215 gl_text_node_free (&text_node);
217 gl_debug (DEBUG_LABEL, "END");
221 /*****************************************************************************/
222 /* Set object params. */
223 /*****************************************************************************/
225 gl_label_barcode_set_data (glLabelBarcode *lbc,
226 const glTextNode *text_node,
231 gl_debug (DEBUG_LABEL, "START");
233 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
235 if (!gl_text_node_equal (lbc->priv->text_node, text_node))
239 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbc));
240 gl_label_checkpoint (label, _("Barcode data"));
243 gl_text_node_free (&lbc->priv->text_node);
244 lbc->priv->text_node = gl_text_node_dup (text_node);
246 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
249 gl_debug (DEBUG_LABEL, "END");
254 gl_label_barcode_set_style (glLabelBarcode *lbc,
255 const glLabelBarcodeStyle *style,
260 gl_debug (DEBUG_LABEL, "START");
262 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
264 if ( !gl_label_barcode_style_is_equal (style, lbc->priv->style) )
268 label = gl_label_object_get_parent (GL_LABEL_OBJECT (lbc));
269 gl_label_checkpoint (label, _("Barcode property"));
272 gl_label_barcode_style_free (lbc->priv->style);
273 lbc->priv->style = gl_label_barcode_style_dup (style);
275 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
278 gl_debug (DEBUG_LABEL, "END");
282 /*****************************************************************************/
283 /* Get object params. */
284 /*****************************************************************************/
286 gl_label_barcode_get_data (glLabelBarcode *lbc)
288 g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
290 return gl_text_node_dup (lbc->priv->text_node);
294 glLabelBarcodeStyle *
295 gl_label_barcode_get_style (glLabelBarcode *lbc)
297 g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
299 return gl_label_barcode_style_dup (lbc->priv->style);
303 /*---------------------------------------------------------------------------*/
304 /* PRIVATE. Get object size method. */
305 /*---------------------------------------------------------------------------*/
307 get_size (glLabelObject *object,
311 glLabelBarcode *lbc = (glLabelBarcode *)object;
313 gdouble w_parent, h_parent;
316 gl_debug (DEBUG_LABEL, "START");
318 g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
320 gl_label_object_get_raw_size (object, &w_parent, &h_parent);
322 if (lbc->priv->text_node->field_flag) {
323 data = gl_barcode_backends_style_default_digits (lbc->priv->style->backend_id,
324 lbc->priv->style->id,
325 lbc->priv->style->format_digits);
327 data = gl_text_node_expand (lbc->priv->text_node, NULL);
330 gbc = gl_barcode_backends_new_barcode (lbc->priv->style->backend_id,
331 lbc->priv->style->id,
332 lbc->priv->style->text_flag,
333 lbc->priv->style->checksum_flag,
340 /* Try again with default digits. */
341 data = gl_barcode_backends_style_default_digits (lbc->priv->style->backend_id,
342 lbc->priv->style->id,
343 lbc->priv->style->format_digits);
344 gbc = gl_barcode_backends_new_barcode (lbc->priv->style->backend_id,
345 lbc->priv->style->id,
346 lbc->priv->style->text_flag,
347 lbc->priv->style->checksum_flag,
361 /* If we still can't render, just set a default size. */
366 lgl_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;
427 PangoFontDescription *desc;
429 glTextNode *text_node;
430 glLabelBarcodeStyle *style;
432 glColorNode *color_node;
435 gl_debug (DEBUG_LABEL, "START");
437 gl_label_object_get_position (object, &x0, &y0);
438 gl_label_object_get_matrix (object, &matrix);
440 text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE (object));
441 style = gl_label_barcode_get_style (GL_LABEL_BARCODE (object));
443 color_node = gl_label_object_get_line_color (object);
444 color = gl_color_node_expand (color_node, record);
445 if (color_node->field_flag && screen_flag)
447 color = GL_COLOR_MERGE_DEFAULT;
450 gl_label_object_get_size (object, &w, &h);
452 text = gl_text_node_expand (text_node, record);
453 if (text_node->field_flag && screen_flag) {
454 text = gl_barcode_backends_style_default_digits (style->backend_id, style->id, style->format_digits);
457 gbc = gl_barcode_backends_new_barcode (style->backend_id, style->id, style->text_flag, style->checksum_flag, w, h, text);
459 cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
463 layout = pango_cairo_create_layout (cr);
465 desc = pango_font_description_new ();
466 pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
467 pango_font_description_set_size (desc, 12 * PANGO_SCALE * FONT_SCALE);
468 pango_layout_set_font_description (layout, desc);
469 pango_font_description_free (desc);
471 if (text == NULL || *text == '\0')
473 pango_layout_set_text (layout, _("Barcode data empty"), -1);
477 pango_layout_set_text (layout, _("Invalid barcode data"), -1);
480 cairo_move_to (cr, 0, 0);
481 pango_cairo_show_layout (cr, layout);
483 g_object_unref (layout);
487 lgl_barcode_render_to_cairo (gbc, cr);
489 lgl_barcode_free (gbc);
494 gl_text_node_free (&text_node);
495 gl_label_barcode_style_free (style);
496 gl_color_node_free (&color_node);
498 gl_debug (DEBUG_LABEL, "END");
502 /*****************************************************************************/
503 /* Is object at coordinates? */
504 /*****************************************************************************/
506 object_at (glLabelObject *object,
513 glLabelBarcodeStyle *style;
514 glTextNode *text_node;
517 gl_label_object_get_size (object, &w, &h);
519 if ( (x >= 0) && (x <= w) && (y >= 0) && (y <= h) )
522 style = gl_label_barcode_get_style (GL_LABEL_BARCODE (object));
523 text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
524 text = gl_text_node_expand (text_node, NULL);
525 if (text_node->field_flag) {
526 text = gl_barcode_backends_style_default_digits (style->backend_id, style->id, style->format_digits);
528 gbc = gl_barcode_backends_new_barcode (style->backend_id,
531 style->checksum_flag,
536 lgl_barcode_render_to_cairo_path (gbc, cr);
537 lgl_barcode_free (gbc);
540 if (cairo_in_fill (cr, x, y))
547 if (gl_label_object_is_selected (object))
550 cairo_rectangle (cr, 0, 0, w, h);
551 if (cairo_in_stroke (cr, x, y))
561 /*****************************************************************************/
562 /* Draw barcode style handles. */
563 /*****************************************************************************/
565 draw_handles (glLabelObject *object,
569 gdouble scale_x, scale_y;
570 gdouble dashes[2] = { 2, 2 };
572 gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
576 cairo_rectangle (cr, 0, 0, w, h);
580 cairo_device_to_user_distance (cr, &scale_x, &scale_y);
581 cairo_scale (cr, scale_x, scale_y);
583 cairo_set_dash (cr, dashes, 2, 0);
584 cairo_set_line_width (cr, HANDLE_OUTLINE_WIDTH_PIXELS);
585 cairo_set_source_rgba (cr, HANDLE_OUTLINE_RGBA_ARGS);
590 gl_label_object_draw_handles_box (object, cr);
594 /*****************************************************************************/
595 /* Barcode style utilities. */
596 /*****************************************************************************/
597 glLabelBarcodeStyle *
598 gl_label_barcode_style_new (void)
600 return g_new0 (glLabelBarcodeStyle, 1);
604 glLabelBarcodeStyle *
605 gl_label_barcode_style_dup (const glLabelBarcodeStyle *style)
607 glLabelBarcodeStyle *style2;
609 style2 = gl_label_barcode_style_new ();
611 /* Shallow copy first. */
615 style2->backend_id = g_strdup (style->backend_id);
616 style2->id = g_strdup (style->id);
623 gl_label_barcode_style_free (glLabelBarcodeStyle *style)
627 g_free (style->backend_id);
636 gl_label_barcode_style_is_equal (const glLabelBarcodeStyle *style1,
637 const glLabelBarcodeStyle *style2)
640 /* First take care of the case of either or both being NULL. */
641 if ( style1 == NULL )
643 return ( style2 == NULL );
647 if ( style2 == NULL )
653 /* Compare field by field, bail on first difference. */
654 if ( style1->text_flag != style2->text_flag )
658 if ( style1->checksum_flag != style2->checksum_flag )
662 if ( style1->format_digits != style2->format_digits )
666 if ( style1->backend_id && style2->backend_id )
668 if ( strcmp (style1->backend_id, style2->backend_id) != 0 )
675 if ( style1->backend_id != style2->backend_id )
680 if ( style1->id && style2->id )
682 if ( strcmp (style1->id, style2->id) != 0 )
689 if ( style1->id != style2->id )
695 /* Passed all tests. */
701 gl_label_barcode_style_set_backend_id (glLabelBarcodeStyle *style,
702 const gchar *backend_id)
704 style->backend_id = g_strdup (backend_id);
709 gl_label_barcode_style_set_style_id (glLabelBarcodeStyle *style,
712 style->id = g_strdup (id);
720 * Local Variables: -- emacs
722 * c-basic-offset: 8 -- emacs
723 * tab-width: 8 -- emacs
724 * indent-tabs-mode: nil -- emacs