]> git.sur5r.net Git - glabels/blobdiff - src/label-barcode.c
Some coding style cleanup.
[glabels] / src / label-barcode.c
index d5704df8c5f0504d612bf30a1db7e5b807a81042..9a98187ea3e57427e34356454d46418335c332ae 100644 (file)
@@ -41,6 +41,8 @@
 #define HANDLE_OUTLINE_RGBA_ARGS   0.5,   0.5,   0.5,   0.75
 #define HANDLE_OUTLINE_WIDTH_PIXELS   2.0
 
+#define SELECTION_SLOP_PIXELS 4.0
+
 
 /*========================================================*/
 /* Private types.                                         */
@@ -52,6 +54,11 @@ struct _glLabelBarcodePrivate {
         glLabelBarcodeStyle *style;
         glColorNode         *color_node;
 
+        /* Cached info.  Only regenerate when text_node,
+         * style, or raw size changed */
+        lglBarcode          *display_gbc;
+        gdouble              w, h;
+
 };
 
 
@@ -69,6 +76,13 @@ static void  gl_label_barcode_finalize      (GObject             *object);
 static void  copy                           (glLabelObject       *dst_object,
                                              glLabelObject       *src_object);
 
+static void  update_barcode                 (glLabelBarcode      *lbc);
+
+static void  set_size                       (glLabelObject       *object,
+                                             gdouble              w,
+                                             gdouble              h,
+                                             gboolean             checkpoint);
+
 static void  get_size                       (glLabelObject       *object,
                                              gdouble             *w,
                                              gdouble             *h);
@@ -92,11 +106,14 @@ static gboolean object_at                   (glLabelObject       *object,
 static void     draw_handles                (glLabelObject       *object,
                                              cairo_t             *cr);
 
+static void     create_alt_msg_path         (cairo_t             *cr,
+                                             gchar               *text);
+
 
 /*****************************************************************************/
 /* Boilerplate object stuff.                                                 */
 /*****************************************************************************/
-G_DEFINE_TYPE (glLabelBarcode, gl_label_barcode, GL_TYPE_LABEL_OBJECT);
+G_DEFINE_TYPE (glLabelBarcode, gl_label_barcode, GL_TYPE_LABEL_OBJECT)
 
 
 static void
@@ -108,6 +125,7 @@ gl_label_barcode_class_init (glLabelBarcodeClass *class)
         gl_label_barcode_parent_class = g_type_class_peek_parent (class);
 
         label_object_class->copy           = copy;
+        label_object_class->set_size       = set_size;
         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;
@@ -138,6 +156,7 @@ gl_label_barcode_finalize (GObject *object)
         gl_text_node_free (&lbc->priv->text_node);
         gl_label_barcode_style_free (lbc->priv->style);
         gl_color_node_free (&(lbc->priv->color_node));
+        lgl_barcode_free (lbc->priv->display_gbc);
         g_free (lbc->priv);
 
         G_OBJECT_CLASS (gl_label_barcode_parent_class)->finalize (object);
@@ -172,6 +191,7 @@ gl_label_barcode_new (glLabel *label,
                 style->checksum_flag = gl_barcode_backends_style_can_csum (style->backend_id, style->id);
                 style->format_digits = gl_barcode_backends_style_get_prefered_n (style->backend_id, style->id);
                 lbc->priv->style = style;
+                update_barcode (lbc);
 
                 line_color_node = gl_color_node_new_default ();
                 line_color_node->color = gl_label_get_default_line_color(label);
@@ -207,12 +227,11 @@ copy (glLabelObject *dst_object,
         style = gl_label_barcode_get_style (lbc);
         color_node = get_line_color (src_object);
 
-        gl_label_barcode_set_data (new_lbc, text_node, FALSE);
-        gl_label_barcode_set_style (new_lbc, style, FALSE);
-        set_line_color (dst_object, color_node, FALSE);
+        new_lbc->priv->text_node  = text_node;
+        new_lbc->priv->style      = style;
+        new_lbc->priv->color_node = color_node;
 
-        gl_color_node_free (&color_node);
-        gl_text_node_free (&text_node);
+        update_barcode (new_lbc);
 
         gl_debug (DEBUG_LABEL, "END");
 }
@@ -243,6 +262,8 @@ gl_label_barcode_set_data (glLabelBarcode   *lbc,
                 gl_text_node_free (&lbc->priv->text_node);
                 lbc->priv->text_node = gl_text_node_dup (text_node);
 
+                update_barcode (lbc);
+
                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
         }
 
@@ -272,6 +293,8 @@ gl_label_barcode_set_style (glLabelBarcode            *lbc,
                 gl_label_barcode_style_free (lbc->priv->style);
                 lbc->priv->style = gl_label_barcode_style_dup (style);
 
+                update_barcode (lbc);
+
                 gl_label_object_emit_changed (GL_LABEL_OBJECT(lbc));
         }
 
@@ -301,43 +324,47 @@ gl_label_barcode_get_style (glLabelBarcode *lbc)
 
 
 /*---------------------------------------------------------------------------*/
-/* PRIVATE.  Get object size method.                                         */
+/* PRIVATE.  Update cached lglBarcode.                                       */
 /*---------------------------------------------------------------------------*/
 static void
-get_size (glLabelObject *object,
-          gdouble       *w,
-          gdouble       *h)
+update_barcode (glLabelBarcode *lbc)
 {
-        glLabelBarcode      *lbc = (glLabelBarcode *)object;
+        gdouble              w_raw, h_raw;
         gchar               *data;
-        gdouble              w_parent, h_parent;
-        lglBarcode          *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);
+        gl_label_object_get_raw_size (GL_LABEL_OBJECT (lbc), &w_raw, &h_raw);
+
+        lgl_barcode_free (lbc->priv->display_gbc);
 
-        if (lbc->priv->text_node->field_flag) {
+        if (lbc->priv->text_node->field_flag)
+        {
                 data = gl_barcode_backends_style_default_digits (lbc->priv->style->backend_id,
                                                                  lbc->priv->style->id,
                                                                  lbc->priv->style->format_digits);
-        } else {
+        }
+        else
+        {
                 data = gl_text_node_expand (lbc->priv->text_node, NULL);
         }
 
-        gbc = gl_barcode_backends_new_barcode (lbc->priv->style->backend_id,
-                                               lbc->priv->style->id,
-                                               lbc->priv->style->text_flag,
-                                               lbc->priv->style->checksum_flag,
-                                               w_parent,
-                                               h_parent,
-                                               data);
+        lbc->priv->display_gbc = gl_barcode_backends_new_barcode (lbc->priv->style->backend_id,
+                                                                  lbc->priv->style->id,
+                                                                  lbc->priv->style->text_flag,
+                                                                  lbc->priv->style->checksum_flag,
+                                                                  w_raw,
+                                                                  h_raw,
+                                                                  data);
         g_free (data);
 
-        if ( gbc == NULL ) {
-                /* Try again with default digits. */
+        if ( lbc->priv->display_gbc == NULL )
+        {
+                lglBarcode *gbc;
+
+                /* Try again with default digits, but don't save -- just extract size. */
                 data = gl_barcode_backends_style_default_digits (lbc->priv->style->backend_id,
                                                                  lbc->priv->style->id,
                                                                  lbc->priv->style->format_digits);
@@ -345,25 +372,69 @@ get_size (glLabelObject *object,
                                                        lbc->priv->style->id,
                                                        lbc->priv->style->text_flag,
                                                        lbc->priv->style->checksum_flag,
-                                                       w_parent,
-                                                       h_parent,
+                                                       w_raw,
+                                                       h_raw,
                                                        data);
                 g_free (data);
-        }
 
-        if ( gbc != NULL )
-        {
-                *w = gbc->width;
-                *h = gbc->height;
+                if ( gbc != NULL )
+                {
+                        lbc->priv->w = gbc->width;
+                        lbc->priv->h = gbc->height;
+                }
+                else
+                {
+                        /* If we still can't render, just set a default size. */
+                        lbc->priv->w = 144;
+                        lbc->priv->h = 72;
+                }
+
+                lgl_barcode_free (gbc);
         }
         else
         {
-                /* If we still can't render, just set a default size. */
-                *w = 144;
-                *h = 72;
+                lbc->priv->w = lbc->priv->display_gbc->width;
+                lbc->priv->h = lbc->priv->display_gbc->height;
         }
 
-        lgl_barcode_free (gbc);
+        gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE.  Set object size method.                                         */
+/*---------------------------------------------------------------------------*/
+static void
+set_size (glLabelObject       *object,
+          gdouble              w,
+          gdouble              h,
+          gboolean             checkpoint)
+{
+        gl_debug (DEBUG_LABEL, "START");
+
+        g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
+
+        gl_label_object_set_raw_size (object, w, h, checkpoint);
+        update_barcode (GL_LABEL_BARCODE (object));
+
+        gl_debug (DEBUG_LABEL, "END");
+}
+
+
+/*---------------------------------------------------------------------------*/
+/* PRIVATE.  Get object size method.                                         */
+/*---------------------------------------------------------------------------*/
+static void
+get_size (glLabelObject *object,
+          gdouble       *w,
+          gdouble       *h)
+{
+        gl_debug (DEBUG_LABEL, "START");
+
+        g_return_if_fail (object && GL_IS_LABEL_BARCODE (object));
+
+        *w = GL_LABEL_BARCODE (object)->priv->w;
+        *h = GL_LABEL_BARCODE (object)->priv->h;
 
         gl_debug (DEBUG_LABEL, "END");
 }
@@ -420,11 +491,10 @@ draw_object (glLabelObject *object,
              gboolean       screen_flag,
              glMergeRecord *record)
 {
+        glLabelBarcode       *lbc     = (glLabelBarcode *)object;
         gdouble               x0, y0;
         cairo_matrix_t        matrix;
         lglBarcode           *gbc;
-        PangoLayout          *layout;
-        PangoFontDescription *desc;
         gchar                *text;
         glTextNode           *text_node;
         glLabelBarcodeStyle  *style;
@@ -447,50 +517,38 @@ draw_object (glLabelObject *object,
                 color = GL_COLOR_MERGE_DEFAULT;
         }
 
-        gl_label_object_get_size (object, &w, &h);
-
-        text = gl_text_node_expand (text_node, record);
-        if (text_node->field_flag && screen_flag) {
-                text = gl_barcode_backends_style_default_digits (style->backend_id, style->id, style->format_digits);
-        }
+        cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
 
-        gbc = gl_barcode_backends_new_barcode (style->backend_id, style->id, style->text_flag, style->checksum_flag, w, h, text);
+        if (text_node->field_flag && !screen_flag) {
 
-        cairo_set_source_rgba (cr, GL_COLOR_RGBA_ARGS (color));
+                gl_label_object_get_raw_size (object, &w, &h);
 
-        if (gbc == NULL) {
+                text = gl_text_node_expand (text_node, record);
+                gbc = gl_barcode_backends_new_barcode (style->backend_id, style->id, style->text_flag, style->checksum_flag, w, h, text);
+                g_free (text);
 
-                layout = pango_cairo_create_layout (cr);
+                if ( gbc != NULL )
+                {
+                        lgl_barcode_render_to_cairo (gbc, cr);
+                        lgl_barcode_free (gbc);
+                }
 
-                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);
+        }
+        else
+        {
 
-                if (text == NULL || *text == '\0')
+                if (lbc->priv->display_gbc == NULL)
                 {
-                        pango_layout_set_text (layout, _("Barcode data empty"), -1);
+                        create_alt_msg_path (cr, text_node->data);
+                        cairo_fill (cr);
                 }
                 else
                 {
-                        pango_layout_set_text (layout, _("Invalid barcode data"), -1);
+                        lgl_barcode_render_to_cairo (lbc->priv->display_gbc, cr);
                 }
 
-                cairo_move_to (cr, 0, 0);
-                pango_cairo_show_layout (cr, layout);
-
-                g_object_unref (layout);
-
-        } else {
-
-                lgl_barcode_render_to_cairo (gbc, cr);
-
-                lgl_barcode_free (gbc);
-
         }
 
-        g_free (text);
         gl_text_node_free (&text_node);
         gl_label_barcode_style_free (style);
         gl_color_node_free (&color_node);
@@ -508,33 +566,25 @@ object_at (glLabelObject *object,
            gdouble        x,
            gdouble        y)
 {
+        glLabelBarcode       *lbc     = (glLabelBarcode *)object;
         gdouble               w, h;
-        lglBarcode           *gbc;
-        glLabelBarcodeStyle  *style;
         glTextNode           *text_node;
-        gchar                *text;
+        gdouble               scale_x, scale_y;
 
         gl_label_object_get_size (object, &w, &h);
 
         if ( (x >= 0) && (x <= w) && (y >= 0) && (y <= h) )
         {
 
-                style = gl_label_barcode_get_style (GL_LABEL_BARCODE (object));
                 text_node = gl_label_barcode_get_data(GL_LABEL_BARCODE(object));
-                text = gl_text_node_expand (text_node, NULL);
-                if (text_node->field_flag) {
-                        text = gl_barcode_backends_style_default_digits (style->backend_id, style->id, style->format_digits);
+
+                if ( lbc->priv->display_gbc == NULL )
+                {
+                        create_alt_msg_path (cr, text_node->data);
                 }
-                gbc = gl_barcode_backends_new_barcode (style->backend_id,
-                                                       style->id,
-                                                       style->text_flag,
-                                                       style->checksum_flag,
-                                                       w, h,
-                                                       text);
-                if ( gbc )
+                else
                 {
-                        lgl_barcode_render_to_cairo_path (gbc, cr);
-                        lgl_barcode_free (gbc);
+                        lgl_barcode_render_to_cairo_path (lbc->priv->display_gbc, cr);
                 }
 
                 if (cairo_in_fill (cr, x, y))
@@ -542,16 +592,36 @@ object_at (glLabelObject *object,
                         return TRUE;
                 }
 
-        }
 
-        if (gl_label_object_is_selected (object))
-        {
-                cairo_new_path (cr);
-                cairo_rectangle (cr, 0, 0, w, h);
+                scale_x = 1.0;
+                scale_y = 1.0;
+                cairo_device_to_user_distance (cr, &scale_x, &scale_y);
+
+                cairo_set_line_width (cr, 2*SELECTION_SLOP_PIXELS*scale_x);
+
                 if (cairo_in_stroke (cr, x, y))
                 {
                         return TRUE;
                 }
+
+
+                if (gl_label_object_is_selected (object))
+                {
+                        cairo_new_path (cr);
+                        cairo_rectangle (cr, 0, 0, w, h);
+
+                        scale_x = 1.0;
+                        scale_y = 1.0;
+                        cairo_device_to_user_distance (cr, &scale_x, &scale_y);
+
+                        cairo_set_line_width (cr, (HANDLE_OUTLINE_WIDTH_PIXELS + 2*SELECTION_SLOP_PIXELS)*scale_x);
+
+                        if (cairo_in_stroke (cr, x, y))
+                        {
+                                return TRUE;
+                        }
+                }
+
         }
 
         return FALSE;
@@ -591,6 +661,40 @@ draw_handles (glLabelObject     *object,
 }
 
 
+/*****************************************************************************/
+/* Create a cairo path with apropos message.                                 */
+/*****************************************************************************/
+static void
+create_alt_msg_path (cairo_t *cr,
+                     gchar   *text)
+{
+        PangoLayout          *layout;
+        PangoFontDescription *desc;
+
+        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_layout_path (cr, layout);
+
+        g_object_unref (layout);
+}
+
+
 /*****************************************************************************/
 /* Barcode style utilities.                                                  */
 /*****************************************************************************/