]> git.sur5r.net Git - glabels/blobdiff - src/label-barcode.c
Added support for Maxicode barcodes using the libzint backend.
[glabels] / src / label-barcode.c
index efc5bc9e0abc4accf09716b7c5bd0ae6a67c1f9a..a57721f1bd486e1082a424c99ed984e57c08f53d 100644 (file)
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <pango/pangocairo.h>
+#include "bc-backends.h"
 
 #include "debug.h"
 
-
 /*========================================================*/
 /* Private macros and constants.                          */
 /*========================================================*/
 
 #define FONT_SCALE (72.0/96.0)
+#define PI 3.141592654
 
 
 /*========================================================*/
 /*========================================================*/
 
 struct _glLabelBarcodePrivate {
-       glTextNode     *text_node;
-       gchar          *id;
-       glColorNode    *color_node;
-       gboolean        text_flag;
-       gboolean        checksum_flag;
-       guint           format_digits;
+        glTextNode     *text_node;
+        gchar          *id;
+        glColorNode    *color_node;
+        gboolean        text_flag;
+        gboolean        checksum_flag;
+        guint           format_digits;
 };
 
 
@@ -62,14 +63,14 @@ struct _glLabelBarcodePrivate {
 static void  gl_label_barcode_finalize      (GObject             *object);
 
 static void  copy                           (glLabelObject       *dst_object,
-                                            glLabelObject       *src_object);
+                                             glLabelObject       *src_object);
 
 static void  get_size                       (glLabelObject       *object,
-                                            gdouble             *w,
-                                            gdouble             *h);
+                                             gdouble             *w,
+                                             gdouble             *h);
 
 static void  set_line_color                 (glLabelObject       *object,
-                                            glColorNode         *line_color,
+                                             glColorNode         *line_color,
                                              gboolean             checkpoint);
 
 static glColorNode *get_line_color          (glLabelObject       *object);
@@ -94,44 +95,44 @@ G_DEFINE_TYPE (glLabelBarcode, gl_label_barcode, GL_TYPE_LABEL_OBJECT);
 static void
 gl_label_barcode_class_init (glLabelBarcodeClass *class)
 {
-       GObjectClass       *object_class       = G_OBJECT_CLASS (class);
-       glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
+        GObjectClass       *object_class       = G_OBJECT_CLASS (class);
+        glLabelObjectClass *label_object_class = GL_LABEL_OBJECT_CLASS (class);
 
-       gl_label_barcode_parent_class = g_type_class_peek_parent (class);
+        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->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;
         label_object_class->object_at      = object_at;
 
-       object_class->finalize = gl_label_barcode_finalize;
+        object_class->finalize = gl_label_barcode_finalize;
 }
 
 
 static void
 gl_label_barcode_init (glLabelBarcode *lbc)
 {
-       lbc->priv = g_new0 (glLabelBarcodePrivate, 1);
-       lbc->priv->text_node  = gl_text_node_new_from_text ("");
+        lbc->priv = g_new0 (glLabelBarcodePrivate, 1);
+        lbc->priv->text_node  = gl_text_node_new_from_text ("");
 }
 
 
 static void
 gl_label_barcode_finalize (GObject *object)
 {
-       glLabelBarcode *lbc = GL_LABEL_BARCODE (object);
+        glLabelBarcode *lbc = GL_LABEL_BARCODE (object);
 
-       g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
+        g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
 
-       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);
+        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 (gl_label_barcode_parent_class)->finalize (object);
+        G_OBJECT_CLASS (gl_label_barcode_parent_class)->finalize (object);
 }
 
 
@@ -142,10 +143,10 @@ GObject *
 gl_label_barcode_new (glLabel *label,
                       gboolean checkpoint)
 {
-       glLabelBarcode      *lbc;
-       glColorNode         *line_color_node;
+        glLabelBarcode      *lbc;
+        glColorNode         *line_color_node;
 
-       lbc = g_object_new (gl_label_barcode_get_type(), NULL);
+        lbc = g_object_new (gl_label_barcode_get_type(), NULL);
 
         if (label != NULL)
         {
@@ -164,7 +165,7 @@ gl_label_barcode_new (glLabel *label,
                 gl_label_object_set_parent (GL_LABEL_OBJECT (lbc), label);
         }
 
-       return G_OBJECT (lbc);
+        return G_OBJECT (lbc);
 }
 
 
@@ -175,33 +176,33 @@ static void
 copy (glLabelObject *dst_object,
       glLabelObject *src_object)
 {
-       glLabelBarcode      *lbc     = (glLabelBarcode *)src_object;
-       glLabelBarcode      *new_lbc = (glLabelBarcode *)dst_object;
-       glTextNode          *text_node;
-       gchar               *id;
-       gboolean             text_flag;
-       gboolean             checksum_flag;
-       glColorNode         *color_node;
-       guint                format_digits;
+        glLabelBarcode      *lbc     = (glLabelBarcode *)src_object;
+        glLabelBarcode      *new_lbc = (glLabelBarcode *)dst_object;
+        glTextNode          *text_node;
+        gchar               *id;
+        gboolean             text_flag;
+        gboolean             checksum_flag;
+        glColorNode         *color_node;
+        guint                format_digits;
 
-       gl_debug (DEBUG_LABEL, "START");
+        gl_debug (DEBUG_LABEL, "START");
 
-       g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
-       g_return_if_fail (new_lbc && GL_IS_LABEL_BARCODE (new_lbc));
+        g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
+        g_return_if_fail (new_lbc && GL_IS_LABEL_BARCODE (new_lbc));
 
-       text_node = gl_label_barcode_get_data (lbc);
-       gl_label_barcode_get_props (lbc, &id, &text_flag, &checksum_flag, &format_digits);
-       color_node = get_line_color (src_object);
+        text_node = gl_label_barcode_get_data (lbc);
+        gl_label_barcode_get_props (lbc, &id, &text_flag, &checksum_flag, &format_digits);
+        color_node = get_line_color (src_object);
 
-       gl_label_barcode_set_data (new_lbc, text_node, FALSE);
-       gl_label_barcode_set_props (new_lbc, id, text_flag, checksum_flag, format_digits, FALSE);
-       set_line_color (dst_object, color_node, FALSE);
+        gl_label_barcode_set_data (new_lbc, text_node, FALSE);
+        gl_label_barcode_set_props (new_lbc, id, text_flag, checksum_flag, format_digits, FALSE);
+        set_line_color (dst_object, color_node, FALSE);
 
-       gl_color_node_free (&color_node);
-       gl_text_node_free (&text_node);
-       g_free (id);
+        gl_color_node_free (&color_node);
+        gl_text_node_free (&text_node);
+        g_free (id);
 
-       gl_debug (DEBUG_LABEL, "END");
+        gl_debug (DEBUG_LABEL, "END");
 }
 
 
@@ -210,16 +211,16 @@ copy (glLabelObject *dst_object,
 /*****************************************************************************/
 void
 gl_label_barcode_set_data (glLabelBarcode *lbc,
-                          glTextNode     *text_node,
+                           glTextNode     *text_node,
                            gboolean        checkpoint)
 {
         glLabel *label;
 
-       gl_debug (DEBUG_LABEL, "START");
+        gl_debug (DEBUG_LABEL, "START");
 
-       g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
+        g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
 
-       if (!gl_text_node_equal (lbc->priv->text_node, text_node))
+        if (!gl_text_node_equal (lbc->priv->text_node, text_node))
         {
                 if ( checkpoint )
                 {
@@ -227,35 +228,35 @@ gl_label_barcode_set_data (glLabelBarcode *lbc,
                         gl_label_checkpoint (label, _("Barcode data"));
                 }
                 
-               gl_text_node_free (&lbc->priv->text_node);
-               lbc->priv->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));
-       }
+                gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
+        }
 
-       gl_debug (DEBUG_LABEL, "END");
+        gl_debug (DEBUG_LABEL, "END");
 }
 
 
 void
 gl_label_barcode_set_props (glLabelBarcode *lbc,
-                           gchar          *id,
-                           gboolean        text_flag,
-                           gboolean        checksum_flag,
-                           guint           format_digits,
+                            gchar          *id,
+                            gboolean        text_flag,
+                            gboolean        checksum_flag,
+                            guint           format_digits,
                             gboolean        checkpoint)
 {
         glLabel *label;
 
-       gl_debug (DEBUG_LABEL, "START");
+        gl_debug (DEBUG_LABEL, "START");
 
-       g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
+        g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
 
-       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))
+        if ( ((lbc->priv->id == NULL) && (id != NULL))
+             || ((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))
         {
                 if ( checkpoint )
                 {
@@ -263,15 +264,15 @@ gl_label_barcode_set_props (glLabelBarcode *lbc,
                         gl_label_checkpoint (label, _("Barcode property"));
                 }
 
-               lbc->priv->id               = g_strdup (id);
-               lbc->priv->text_flag        = text_flag;
-               lbc->priv->checksum_flag    = checksum_flag;
-               lbc->priv->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));
-       }
+                gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
+        }
 
-       gl_debug (DEBUG_LABEL, "END");
+        gl_debug (DEBUG_LABEL, "END");
 }
 
 
@@ -281,25 +282,25 @@ gl_label_barcode_set_props (glLabelBarcode *lbc,
 glTextNode *
 gl_label_barcode_get_data (glLabelBarcode *lbc)
 {
-       g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
+        g_return_val_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc), NULL);
 
-       return gl_text_node_dup (lbc->priv->text_node);
+        return gl_text_node_dup (lbc->priv->text_node);
 }
 
 
 void
 gl_label_barcode_get_props (glLabelBarcode *lbc,
-                           gchar          **id,
-                           gboolean       *text_flag,
-                           gboolean       *checksum_flag,
-                           guint          *format_digits)
+                            gchar          **id,
+                            gboolean       *text_flag,
+                            gboolean       *checksum_flag,
+                            guint          *format_digits)
 {
-       g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
+        g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
 
-       *id               = g_strdup (lbc->priv->id);
-       *text_flag        = lbc->priv->text_flag;
-       *checksum_flag    = lbc->priv->checksum_flag;
-       *format_digits    = lbc->priv->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;
 }
 
 
@@ -308,47 +309,47 @@ gl_label_barcode_get_props (glLabelBarcode *lbc,
 /*---------------------------------------------------------------------------*/
 static void
 get_size (glLabelObject *object,
-         gdouble       *w,
-         gdouble       *h)
+          gdouble       *w,
+          gdouble       *h)
 {
-       glLabelBarcode      *lbc = (glLabelBarcode *)object;
-       gchar               *data;
-       gdouble              w_parent, h_parent;
-       glBarcode           *gbc;
-
-       gl_debug (DEBUG_LABEL, "START");
-
-       g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
-
-       gl_label_object_get_raw_size (object, &w_parent, &h_parent);
-
-       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->priv->text_node, NULL);
-       }
-
-       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->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);
+        glLabelBarcode      *lbc = (glLabelBarcode *)object;
+        gchar               *data;
+        gdouble              w_parent, h_parent;
+        glBarcode           *gbc;
+
+        gl_debug (DEBUG_LABEL, "START");
+
+        g_return_if_fail (lbc && GL_IS_LABEL_BARCODE (lbc));
+
+        gl_label_object_get_raw_size (object, &w_parent, &h_parent);
+
+        if (lbc->priv->text_node->field_flag) {
+                data = gl_barcode_backends_default_digits (lbc->priv->id,
+                                                           lbc->priv->format_digits);
+        } else {
+                data = gl_text_node_expand (lbc->priv->text_node, NULL);
+        }
+
+        gbc = gl_barcode_backends_new_barcode (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_backends_default_digits (lbc->priv->id,
+                                                  lbc->priv->format_digits);
+                gbc = gl_barcode_backends_new_barcode (lbc->priv->id,
+                                                       lbc->priv->text_flag,
+                                                       lbc->priv->checksum_flag,
+                                                       w_parent,
+                                                       h_parent,
+                                                       data);
                 g_free (data);
-       }
+        }
 
         if ( gbc != NULL )
         {
@@ -362,9 +363,9 @@ get_size (glLabelObject *object,
                 *h = 72;
         }
 
-       gl_barcode_free (&gbc);
+        gl_barcode_free (&gbc);
 
-       gl_debug (DEBUG_LABEL, "END");
+        gl_debug (DEBUG_LABEL, "END");
 }
 
 
@@ -373,15 +374,15 @@ get_size (glLabelObject *object,
 /*---------------------------------------------------------------------------*/
 static void
 set_line_color (glLabelObject *object,
-               glColorNode   *line_color_node,
+                glColorNode   *line_color_node,
                 gboolean       checkpoint)
 {
-       glLabelBarcode *lbarcode = (glLabelBarcode *)object;
+        glLabelBarcode *lbarcode = (glLabelBarcode *)object;
         glLabel        *label;
 
-       g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
+        g_return_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode));
 
-       if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) )
+        if ( !gl_color_node_equal(lbarcode->priv->color_node, line_color_node) )
         {
                 if ( checkpoint )
                 {
@@ -389,10 +390,10 @@ set_line_color (glLabelObject *object,
                         gl_label_checkpoint (label, _("Barcode data"));
                 }
 
-               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));
-       }
+                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));
+        }
 }
 
 
@@ -402,11 +403,11 @@ set_line_color (glLabelObject *object,
 static glColorNode*
 get_line_color (glLabelObject *object)
 {
-       glLabelBarcode *lbarcode = (glLabelBarcode *)object;
+        glLabelBarcode *lbarcode = (glLabelBarcode *)object;
 
-       g_return_val_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode), NULL);
+        g_return_val_if_fail (lbarcode && GL_IS_LABEL_BARCODE (lbarcode), NULL);
 
-       return gl_color_node_dup (lbarcode->priv->color_node);
+        return gl_color_node_dup (lbarcode->priv->color_node);
 }
 
 
@@ -419,55 +420,62 @@ draw_object (glLabelObject *object,
              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;
+        gdouble               x0, y0;
+        cairo_matrix_t        matrix;
+        glBarcode            *gbc;
+        glBarcodeShape       *shape;
+        glBarcodeShapeLine   *line;
+        glBarcodeShapeBox    *box;
+        glBarcodeShapeRing   *ring;
+        glBarcodeShapeHexagon *hexagon;
+        glBarcodeShapeChar   *bchar;
+        glBarcodeShapeString *bstring;
+        GList                *p;
+        gdouble               x_offset, 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");
+        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;
+        gint                  iw, ih;
+        gdouble               layout_width;
+
+        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);
+        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);
+        gl_color_node_free (&color_node);
 
-       text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
+        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);
-       }
+        if (text_node->field_flag && screen_flag) {
+                text = gl_barcode_backends_default_digits (id, format_digits);
+        }
 
-       gbc = gl_barcode_new (id, text_flag, checksum_flag, w, h, text);
+        gbc = gl_barcode_backends_new_barcode (id, text_flag, checksum_flag, w, h, text);
 
         cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
 
-       if (gbc == NULL) {
+        if (gbc == NULL) {
 
                 layout = pango_cairo_create_layout (cr);
 
@@ -491,50 +499,121 @@ draw_object (glLabelObject *object,
 
                 g_object_unref (layout);
 
-       } else {
+        } else {
+
+                for (p = gbc->shapes; p != NULL; p = p->next) {
+                        shape = (glBarcodeShape *)p->data;
+                        switch (shape->type)
+                        {
+
+                        case GL_BARCODE_SHAPE_LINE:
+                                line = (glBarcodeShapeLine *) shape;
+
+                                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);
+
+                                break;
+
+                        case GL_BARCODE_SHAPE_BOX:
+                                box = (glBarcodeShapeBox *) shape;
 
-               for (li = gbc->lines; li != NULL; li = li->next) {
-                       line = (glBarcodeLine *) li->data;
+                                cairo_rectangle (cr, box->x, box->y, box->width, box->height);
+                                cairo_fill (cr);
 
-                       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);
-               }
+                                break;
 
-               for (li = gbc->chars; li != NULL; li = li->next) {
-                       bchar = (glBarcodeChar *) li->data;
+                        case GL_BARCODE_SHAPE_CHAR:
+                                bchar = (glBarcodeShapeChar *) shape;
 
-                        layout = pango_cairo_create_layout (cr);
+                                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);
+                                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);
+                                cstring = g_strdup_printf ("%c", bchar->c);
+                                pango_layout_set_text (layout, cstring, -1);
+                                g_free (cstring);
 
-                        y_offset = 0.2 * bchar->fsize;
+                                y_offset = 0.2 * bchar->fsize;
 
-                       cairo_move_to (cr, bchar->x, bchar->y-y_offset);
-                        pango_cairo_show_layout (cr, layout);
+                                cairo_move_to (cr, bchar->x, bchar->y-y_offset);
+                                pango_cairo_show_layout (cr, layout);
 
-                        g_object_unref (layout);
+                                g_object_unref (layout);
 
-               }
+                                break;
 
-               gl_barcode_free (&gbc);
+                        case GL_BARCODE_SHAPE_STRING:
+                                bstring = (glBarcodeShapeString *) shape;
 
-       }
+                                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, bstring->fsize * PANGO_SCALE * FONT_SCALE);
+                                pango_layout_set_font_description (layout, desc);
+                                pango_font_description_free       (desc);
+
+                                pango_layout_set_text (layout, bstring->string, -1);
+
+                                pango_layout_get_size (layout, &iw, &ih);
+                                layout_width = (gdouble)iw / (gdouble)PANGO_SCALE;
+
+                                x_offset = layout_width / 2.0;
+                                y_offset = 0.2 * bstring->fsize;
+
+                                cairo_move_to (cr, (bstring->x - x_offset), (bstring->y - y_offset));
+                                pango_cairo_show_layout (cr, layout);
+
+                                g_object_unref (layout);
+
+                                break;
+
+                        case GL_BARCODE_SHAPE_RING:
+                                ring = (glBarcodeShapeRing *) shape;
+
+                                cairo_arc (cr, ring->x, ring->y, ring->radius, 0.0, 2 * PI);
+                                cairo_set_line_width (cr, ring->line_width);
+                                cairo_stroke (cr);
+
+                                break;
+
+                        case GL_BARCODE_SHAPE_HEXAGON:
+                                hexagon = (glBarcodeShapeHexagon *) shape;
+
+                                cairo_move_to (cr, hexagon->x, hexagon->y);
+                                cairo_line_to (cr, hexagon->x + 1.25, hexagon->y + 0.70);
+                                cairo_line_to (cr, hexagon->x + 1.25, hexagon->y + 2.18);
+                                cairo_line_to (cr, hexagon->x, hexagon->y + 2.89);
+                                cairo_line_to (cr, hexagon->x - 1.25, hexagon->y + 2.18);
+                                cairo_line_to (cr, hexagon->x - 1.25, hexagon->y + 0.70);
+                                cairo_close_path (cr);
+                                cairo_fill (cr);
+
+                                break;
+
+                        default:
+                                g_assert_not_reached ();
+                                break;
+
+                        }
+
+                }
+
+                gl_barcode_free (&gbc);
+
+        }
 
-       g_free (text);
-       gl_text_node_free (&text_node);
-       g_free (id);
+        g_free (text);
+        gl_text_node_free (&text_node);
+        g_free (id);
 
-       gl_debug (DEBUG_LABEL, "END");
+        gl_debug (DEBUG_LABEL, "END");
 }
 
 
@@ -551,6 +630,7 @@ object_at (glLabelObject *object,
 
         gl_label_object_get_size (object, &w, &h);
 
+        cairo_new_path (cr);
         cairo_rectangle (cr, 0.0, 0.0, w, h);
 
         if (cairo_in_fill (cr, x, y))