]> git.sur5r.net Git - glabels/blobdiff - glabels2/src/label-barcode.c
2009-09-01 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / label-barcode.c
index 9ec54c970480041f84f1050f530c9b63223f77be..7c4506483238e681b6fbdcff9311073749e2f2b2 100644 (file)
@@ -1,9 +1,11 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+
 /*
  *  (GLABELS) Label and Business Card Creation program for GNOME
  *
  *  label_barcode.c:  GLabels label text object
  *
- *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
+ *  Copyright (C) 2001-2007  Jim Evins <evins@snaught.com>.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
 
 #include "label-barcode.h"
 
+#include <glib/gi18n.h>
 #include <glib/gmem.h>
 #include <glib/gstrfuncs.h>
 #include <glib/gmessages.h>
-
-#include "pixmaps/checkerboard.xpm"
+#include <cairo.h>
+#include <pango/pangocairo.h>
 
 #include "debug.h"
 
@@ -34,6 +37,8 @@
 /* Private macros and constants.                          */
 /*========================================================*/
 
+#define FONT_SCALE (72.0/96.0)
+
 /*========================================================*/
 /* Private types.                                         */
 /*========================================================*/
@@ -51,16 +56,10 @@ struct _glLabelBarcodePrivate {
 /* Private globals.                                       */
 /*========================================================*/
 
-static glLabelObjectClass *parent_class = NULL;
-
-static guint instance = 0;
-
 /*========================================================*/
 /* Private function prototypes.                           */
 /*========================================================*/
 
-static void  gl_label_barcode_class_init    (glLabelBarcodeClass *klass);
-static void  gl_label_barcode_instance_init (glLabelBarcode      *lbc);
 static void  gl_label_barcode_finalize      (GObject             *object);
 
 static void  copy                           (glLabelObject       *dst_object,
@@ -73,80 +72,63 @@ static void  get_size                       (glLabelObject       *object,
 static void  set_line_color                 (glLabelObject       *object,
                                             glColorNode         *line_color);
 
-static glColorNode *get_line_color           (glLabelObject       *object);
+static glColorNode *get_line_color          (glLabelObject       *object);
+
+static void    draw_object                (glLabelObject     *object,
+                                           cairo_t           *cr,
+                                           gboolean           screen_flag,
+                                           glMergeRecord     *record);
 
 
 \f
 /*****************************************************************************/
 /* Boilerplate object stuff.                                                 */
 /*****************************************************************************/
-GType
-gl_label_barcode_get_type (void)
-{
-       static GType type = 0;
-
-       if (!type) {
-               static const GTypeInfo info = {
-                       sizeof (glLabelBarcodeClass),
-                       NULL,
-                       NULL,
-                       (GClassInitFunc) gl_label_barcode_class_init,
-                       NULL,
-                       NULL,
-                       sizeof (glLabelBarcode),
-                       0,
-                       (GInstanceInitFunc) gl_label_barcode_instance_init,
-                       NULL
-               };
-
-               type = g_type_register_static (GL_TYPE_LABEL_OBJECT,
-                                              "glLabelBarcode", &info, 0);
-       }
-
-       return type;
-}
+G_DEFINE_TYPE (glLabelBarcode, gl_label_barcode, GL_TYPE_LABEL_OBJECT);
 
 static void
-gl_label_barcode_class_init (glLabelBarcodeClass *klass)
+gl_label_barcode_class_init (glLabelBarcodeClass *class)
 {
-       GObjectClass       *object_class       = (GObjectClass *) klass;
-       glLabelObjectClass *label_object_class = (glLabelObjectClass *) klass;
+       GObjectClass       *object_class       = G_OBJECT_CLASS (class);
+       glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
 
-       parent_class = g_type_class_peek_parent (klass);
+       gl_label_barcode_parent_class = g_type_class_peek_parent (class);
 
        label_object_class->copy           = copy;
        label_object_class->get_size       = get_size;
        label_object_class->set_line_color = set_line_color;
        label_object_class->get_line_color = get_line_color;
+        label_object_class->draw_object    = draw_object;
+        label_object_class->draw_shadow    = NULL;
 
        object_class->finalize = gl_label_barcode_finalize;
 }
 
 static void
-gl_label_barcode_instance_init (glLabelBarcode *lbc)
+gl_label_barcode_init (glLabelBarcode *lbc)
 {
-       lbc->private = g_new0 (glLabelBarcodePrivate, 1);
-       lbc->private->color_node = gl_color_node_new_default ();
+       lbc->priv = g_new0 (glLabelBarcodePrivate, 1);
+       lbc->priv->color_node = gl_color_node_new_default ();
+       lbc->priv->text_node  = gl_text_node_new_from_text ("");
 }
 
 static void
 gl_label_barcode_finalize (GObject *object)
 {
-       glLabelBarcode *lbc;
+       glLabelBarcode *lbc = GL_LABEL_BARCODE (object);
 
        g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
 
-       lbc = GL_LABEL_BARCODE (object);
-
-       gl_color_node_free (&(lbc->private->color_node));
-       gl_text_node_free (&lbc->private->text_node);
-       g_free (lbc->private);
+       gl_text_node_free (&lbc->priv->text_node);
+       g_free (lbc->priv->id);
+       gl_color_node_free (&(lbc->priv->color_node));
+       g_free (lbc->priv);
 
-       G_OBJECT_CLASS (parent_class)->finalize (object);
+       G_OBJECT_CLASS (gl_label_barcode_parent_class)->finalize (object);
 }
 
 /*****************************************************************************/
-/* NEW label "text" object.                                               */
+/* NEW label "barcode" object.                                               */
 /*****************************************************************************/
 GObject *
 gl_label_barcode_new (glLabel *label)
@@ -208,10 +190,10 @@ gl_label_barcode_set_data (glLabelBarcode *lbc,
 
        g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
 
-       if (!gl_text_node_equal (lbc->private->text_node, text_node)) {
+       if (!gl_text_node_equal (lbc->priv->text_node, text_node)) {
 
-               gl_text_node_free (&lbc->private->text_node);
-               lbc->private->text_node = gl_text_node_dup (text_node);
+               gl_text_node_free (&lbc->priv->text_node);
+               lbc->priv->text_node = gl_text_node_dup (text_node);
 
                gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
 
@@ -231,16 +213,16 @@ gl_label_barcode_set_props (glLabelBarcode *lbc,
 
        g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
 
-       if ( ((lbc->private->id == NULL) && (id != NULL))
-            || (g_strcasecmp (lbc->private->id, id) != 0)
-            || (lbc->private->text_flag != text_flag)
-            || (lbc->private->checksum_flag != checksum_flag)
-            || (lbc->private->format_digits != format_digits)) {
+       if ( ((lbc->priv->id == NULL) && (id != NULL))
+            || (g_ascii_strcasecmp (lbc->priv->id, id) != 0)
+            || (lbc->priv->text_flag != text_flag)
+            || (lbc->priv->checksum_flag != checksum_flag)
+            || (lbc->priv->format_digits != format_digits)) {
 
-               lbc->private->id               = g_strdup (id);
-               lbc->private->text_flag        = text_flag;
-               lbc->private->checksum_flag    = checksum_flag;
-               lbc->private->format_digits    = format_digits;
+               lbc->priv->id               = g_strdup (id);
+               lbc->priv->text_flag        = text_flag;
+               lbc->priv->checksum_flag    = checksum_flag;
+               lbc->priv->format_digits    = format_digits;
 
                gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
 
@@ -258,7 +240,7 @@ gl_label_barcode_get_data (glLabelBarcode *lbc)
 {
        g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
 
-       return gl_text_node_dup (lbc->private->text_node);
+       return gl_text_node_dup (lbc->priv->text_node);
 }
 
 void
@@ -270,10 +252,10 @@ gl_label_barcode_get_props (glLabelBarcode *lbc,
 {
        g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
 
-       *id               = g_strdup (lbc->private->id);
-       *text_flag        = lbc->private->text_flag;
-       *checksum_flag    = lbc->private->checksum_flag;
-       *format_digits    = lbc->private->format_digits;
+       *id               = g_strdup (lbc->priv->id);
+       *text_flag        = lbc->priv->text_flag;
+       *checksum_flag    = lbc->priv->checksum_flag;
+       *format_digits    = lbc->priv->format_digits;
 }
 
 /*---------------------------------------------------------------------------*/
@@ -293,40 +275,49 @@ get_size (glLabelObject *object,
 
        g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
 
-       (* parent_class->get_size) (object, &w_parent, &h_parent);
+       gl_label_object_get_raw_size (object, &w_parent, &h_parent);
 
-
-       if (lbc->private->text_node->field_flag) {
-               data = gl_barcode_default_digits (lbc->private->id,
-                                                 lbc->private->format_digits);
+       if (lbc->priv->text_node->field_flag) {
+               data = gl_barcode_default_digits (lbc->priv->id,
+                                                 lbc->priv->format_digits);
        } else {
-               data = gl_text_node_expand (lbc->private->text_node, NULL);
+               data = gl_text_node_expand (lbc->priv->text_node, NULL);
        }
 
-       gbc = gl_barcode_new (lbc->private->id,
-                             lbc->private->text_flag,
-                             lbc->private->checksum_flag,
+       gbc = gl_barcode_new (lbc->priv->id,
+                             lbc->priv->text_flag,
+                             lbc->priv->checksum_flag,
                              w_parent,
                              h_parent,
                              data);
+       g_free (data);
 
        if ( gbc == NULL ) {
                /* Try again with default digits. */
-               data = gl_barcode_default_digits (lbc->private->id,
-                                                 lbc->private->format_digits);
-               gbc = gl_barcode_new (lbc->private->id,
-                                     lbc->private->text_flag,
-                                     lbc->private->checksum_flag,
+               data = gl_barcode_default_digits (lbc->priv->id,
+                                                 lbc->priv->format_digits);
+               gbc = gl_barcode_new (lbc->priv->id,
+                                     lbc->priv->text_flag,
+                                     lbc->priv->checksum_flag,
                                      w_parent,
                                      h_parent,
                                      data);
+                g_free (data);
        }
 
-       *w = gbc->width;
-       *h = gbc->height;
+        if ( gbc != NULL )
+        {
+                *w = gbc->width;
+                *h = gbc->height;
+        }
+        else
+        {
+                /* If we still can't render, just set a default size. */
+                *w = 144;
+                *h = 72;
+        }
 
        gl_barcode_free (&gbc);
-       g_free (data);
 
        gl_debug (DEBUG_LABEL, "END");
 }
@@ -342,10 +333,10 @@ set_line_color (glLabelObject *object,
 
        g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
 
-       if ( !gl_color_node_equal(lbarcode->private->color_node, line_color_node) ) {
+       if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) ) {
                
-               gl_color_node_free (&(lbarcode->private->color_node));
-               lbarcode->private->color_node = gl_color_node_dup (line_color_node);
+               gl_color_node_free (&(lbarcode->priv->color_node));
+               lbarcode->priv->color_node = gl_color_node_dup (line_color_node);
                gl_label_object_emit_changed (GL_LABEL_OBJECT(lbarcode));
        }
 }
@@ -358,7 +349,135 @@ get_line_color (glLabelObject *object)
 {
        glLabelBarcode *lbarcode = (glLabelBarcode *)object;
 
-       g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
+       g_return_val_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode), NULL);
 
-       return gl_color_node_dup (lbarcode->private->color_node);
+       return gl_color_node_dup (lbarcode->priv->color_node);
 }
+
+/*****************************************************************************/
+/* Draw object method.                                                       */
+/*****************************************************************************/
+static void
+draw_object (glLabelObject *object,
+             cairo_t       *cr,
+             gboolean       screen_flag,
+             glMergeRecord *record)
+{
+        gdouble             x0, y0;
+        cairo_matrix_t      matrix;
+       glBarcode          *gbc;
+       glBarcodeLine      *line;
+       glBarcodeChar      *bchar;
+       GList              *li;
+       gdouble             y_offset;
+        PangoLayout        *layout;
+        PangoFontDescription *desc;
+       gchar              *text, *cstring;
+       glTextNode         *text_node;
+       gchar              *id;
+       gboolean            text_flag;
+       gboolean            checksum_flag;
+       guint               color;
+       glColorNode        *color_node;
+       guint               format_digits;
+       gdouble             w, h;
+
+       gl_debug (DEBUG_LABEL, "START");
+
+        gl_label_object_get_position (object, &x0, &y0);
+        gl_label_object_get_matrix (object, &matrix);
+
+       text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE (object));
+       gl_label_barcode_get_props (GL_LABEL_BARCODE (object),
+                                   &id, &text_flag, &checksum_flag, &format_digits);
+                                       
+       color_node = gl_label_object_get_line_color (object);
+       color = gl_color_node_expand (color_node, record);
+        if (color_node->field_flag && screen_flag)
+        {
+                color = GL_COLOR_MERGE_DEFAULT;
+        }
+       gl_color_node_free (&color_node);
+       
+       gl_label_object_get_size (object, &w, &h);
+
+       text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
+        text = gl_text_node_expand (text_node, record);
+       if (text_node->field_flag && screen_flag) {
+               text = gl_barcode_default_digits (id, format_digits);
+       }
+
+       gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
+
+        cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
+
+       if (gbc == NULL) {
+
+                layout = pango_cairo_create_layout (cr);
+
+                desc = pango_font_description_new ();
+                pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
+                pango_font_description_set_size   (desc, 12 * PANGO_SCALE * FONT_SCALE);
+                pango_layout_set_font_description (layout, desc);
+                pango_font_description_free       (desc);
+
+                if (text == NULL || *text == '\0')
+                {
+                        pango_layout_set_text (layout, _("Barcode data empty"), -1);
+                }
+                else
+                {
+                        pango_layout_set_text (layout, _("Invalid barcode data"), -1);
+                }
+
+                cairo_move_to (cr, 0, 0);
+                pango_cairo_show_layout (cr, layout);
+
+                g_object_unref (layout);
+
+       } else {
+
+               for (li = gbc->lines; li != NULL; li = li->next) {
+                       line = (glBarcodeLine *) li->data;
+
+                       cairo_move_to (cr, line->x, line->y);
+                       cairo_line_to (cr, line->x, line->y + line->length);
+                       cairo_set_line_width (cr, line->width);
+                       cairo_stroke (cr);
+               }
+
+               for (li = gbc->chars; li != NULL; li = li->next) {
+                       bchar = (glBarcodeChar *) li->data;
+
+                        layout = pango_cairo_create_layout (cr);
+
+                        desc = pango_font_description_new ();
+                        pango_font_description_set_family (desc, GL_BARCODE_FONT_FAMILY);
+                        pango_font_description_set_size   (desc, bchar->fsize * PANGO_SCALE * FONT_SCALE);
+                        pango_layout_set_font_description (layout, desc);
+                        pango_font_description_free       (desc);
+
+                       cstring = g_strdup_printf ("%c", bchar->c);
+                        pango_layout_set_text (layout, cstring, -1);
+                       g_free (cstring);
+
+                        y_offset = 0.2 * bchar->fsize;
+
+                       cairo_move_to (cr, bchar->x, bchar->y-y_offset);
+                        pango_cairo_show_layout (cr, layout);
+
+                        g_object_unref (layout);
+
+               }
+
+               gl_barcode_free (&gbc);
+
+       }
+
+       g_free (text);
+       gl_text_node_free (&text_node);
+       g_free (id);
+
+       gl_debug (DEBUG_LABEL, "END");
+}
+