X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Flabel-barcode.c;h=9a98187ea3e57427e34356454d46418335c332ae;hb=4f37ea189b9cc80ef25d608c024273a345970722;hp=d5704df8c5f0504d612bf30a1db7e5b807a81042;hpb=81941432d20338b56011444017b01799320a6e97;p=glabels diff --git a/src/label-barcode.c b/src/label-barcode.c index d5704df8..9a98187e 100644 --- a/src/label-barcode.c +++ b/src/label-barcode.c @@ -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. */ /*****************************************************************************/