From e43f6397f295172646ed67456799c1fe6cbfb94a Mon Sep 17 00:00:00 2001 From: Jim Evins Date: Fri, 9 Jul 2010 23:20:11 -0400 Subject: [PATCH] Added new barcode drawing primitives. Added a "Box" and a "String" barcode drawing primitives. The box primitive should be more natural for drawing actual boxes instead of lines. The string primitive allows an entire string to be rendered with a single interaction with pango and cairo, rather than an interaction for each character. There is no need to try to implement kerning since pango will take care of the string as a single layout. --- src/bc-zint.c | 81 ++++++++++++++---------------- src/bc.c | 49 +++++++++++++++++- src/bc.h | 118 ++++++++++++++++++++++++++++++++++++-------- src/label-barcode.c | 32 ++++++++++++ 4 files changed, 214 insertions(+), 66 deletions(-) diff --git a/src/bc-zint.c b/src/bc-zint.c index 3ee26acb..fb02b514 100644 --- a/src/bc-zint.c +++ b/src/bc-zint.c @@ -179,62 +179,55 @@ gl_barcode_zint_new (const gchar *id, * internal Zint code to convert directly to glBarcode representation. * *--------------------------------------------------------------------------*/ -static glBarcode *render_zint(struct zint_symbol *symbol, gboolean text_flag) { +static glBarcode *render_zint(struct zint_symbol *symbol, gboolean text_flag) +{ + glBarcode *gbc; + glBarcodeShapeBox *box; + glBarcodeShapeString *bstring; - int i; - double string_offset, x; + struct zint_render *render; + struct zint_render_line *zline; + struct zint_render_string *zstring; - glBarcode *gbc; - glBarcodeShapeLine *line; - glBarcodeShapeAlpha *bchar; - - struct zint_render *render; - struct zint_render_line *zline; - struct zint_render_string *zstring; - render = symbol->rendered; - gbc = g_new0(glBarcode, 1); - + render = symbol->rendered; + gbc = g_new0(glBarcode, 1); - for ( zline = render->lines; zline != NULL; zline = zline->next ) { - line = gl_barcode_shape_line_new (); + for ( zline = render->lines; zline != NULL; zline = zline->next ) + { + box = gl_barcode_shape_box_new (); - line->width = (double) zline->width; - line->length = (double) zline->length; - /* glBarcodeLine centers based on width, counter-act!!! */ - line->x = (double) (zline->x + (zline->width / 2.0)); - line->y = (double) zline->y; + box->x = (gdouble) zline->x; + box->y = (gdouble) zline->y; + box->width = (gdouble) zline->width; + box->height = (gdouble) zline->length; - gl_barcode_add_shape (gbc, (glBarcodeShape *)line); - } + gl_barcode_add_shape (gbc, (glBarcodeShape *)box); + } /* * Repeat loop for characters */ - if(text_flag) { - for ( zstring = render->strings; zstring != NULL; zstring = zstring->next ) { - string_offset = (double) zstring->x - (((6.0 / 9.0) * zstring->length * zstring->fsize) / 2); - for(i = 0; i < zstring->length; i++) { - x = 0.0; - // Poor man's kerning - if (zstring->text[i] == '(') { x = 0.18; } - bchar = gl_barcode_shape_alpha_new(); - bchar->x = (double) string_offset + ((((6.0 / 9.0) * i) + x) * zstring->fsize); - bchar->y = (double) zstring->y; - bchar->fsize = (double) zstring->fsize; - bchar->c = (char) zstring->text[i]; - gl_barcode_add_shape (gbc, (glBarcodeShape *)bchar); - } - } - } + if(text_flag) + { + for ( zstring = render->strings; zstring != NULL; zstring = zstring->next ) + { + bstring = gl_barcode_shape_string_new(); + bstring->x = (double) zstring->x - (((6.0 / 9.0) * zstring->length * zstring->fsize) / 2); + bstring->y = (double) zstring->y; + bstring->fsize = (double) zstring->fsize; + bstring->str = g_strndup (zstring->text, zstring->length); + gl_barcode_add_shape (gbc, (glBarcodeShape *)bstring); + } + } - /* - * Finally add complete sizes - */ - gbc->width = (gdouble) render->width; - gbc->height = (gdouble) render->height; + /* + * Finally add complete sizes + */ + gbc->width = (gdouble) render->width; + gbc->height = (gdouble) render->height; - return gbc; + return gbc; } #endif /* HAVE_LIBZINT */ diff --git a/src/bc.c b/src/bc.c index 35a2bc4b..247b5065 100644 --- a/src/bc.c +++ b/src/bc.c @@ -440,6 +440,19 @@ gl_barcode_shape_line_new (void) } +/*****************************************************************************/ +/* Allocate new Box shape. */ +/*****************************************************************************/ +glBarcodeShapeBox * +gl_barcode_shape_box_new (void) +{ + glBarcodeShapeBox *box_shape = g_new0 (glBarcodeShapeBox, 1); + box_shape->type = GL_BARCODE_SHAPE_BOX; + + return box_shape; +} + + /*****************************************************************************/ /* Allocate new Alpha shape. */ /*****************************************************************************/ @@ -453,6 +466,40 @@ gl_barcode_shape_alpha_new (void) } +/*****************************************************************************/ +/* Allocate new String shape. */ +/*****************************************************************************/ +glBarcodeShapeString * +gl_barcode_shape_string_new (void) +{ + glBarcodeShapeString *string_shape = g_new0 (glBarcodeShapeString, 1); + string_shape->type = GL_BARCODE_SHAPE_STRING; + + return string_shape; +} + + +/*****************************************************************************/ +/* Free a shape primitive. */ +/*****************************************************************************/ +void +gl_barcode_shape_free (glBarcodeShape *shape) +{ + switch (shape->type) + { + + case GL_BARCODE_SHAPE_STRING: + g_free (shape->string.str); + break; + + default: + break; + } + + g_free (shape); +} + + /*****************************************************************************/ /* Call appropriate barcode backend to create barcode in intermediate format.*/ /*****************************************************************************/ @@ -492,7 +539,7 @@ gl_barcode_free (glBarcode **gbc) if (*gbc != NULL) { for (p = (*gbc)->shapes; p != NULL; p = p->next) { - g_free (p->data); + gl_barcode_shape_free ((glBarcodeShape *)p->data); p->data = NULL; } g_list_free ((*gbc)->shapes); diff --git a/src/bc.h b/src/bc.h index 909f74f2..5a0374f0 100644 --- a/src/bc.h +++ b/src/bc.h @@ -1,6 +1,6 @@ /* * bc.h - * Copyright (C) 2001-2009 Jim Evins . + * Copyright (C) 2001-2010 Jim Evins . * * This file is part of gLabels. * @@ -26,9 +26,20 @@ G_BEGIN_DECLS + +#define GL_BARCODE_FONT_FAMILY "Sans" +#define GL_BARCODE_FONT_WEIGHT PANGO_WEIGHT_NORMAL + + +/*******************************/ +/* Barcode Drawing Primitives. */ +/*******************************/ + typedef enum { GL_BARCODE_SHAPE_LINE, + GL_BARCODE_SHAPE_BOX, GL_BARCODE_SHAPE_ALPHA, + GL_BARCODE_SHAPE_STRING, } glBarcodeShapeType; typedef struct { @@ -70,6 +81,35 @@ typedef struct { } glBarcodeShapeLine; +/* + * glBarcodeShapeBox: + * + * @ = origin (x,y) from top left corner of barcode + * + * @---------+ + * | | + * | | + * | | + * | | height + * | | + * | | + * | | + * +---------+ + * width + */ +typedef struct { + + /* Begin Common Fields */ + glBarcodeShapeType type; /* Always GL_BARCODE_SHAPE_LINE. */ + gdouble x; + gdouble y; + /* End Common Fields */ + + gdouble width; + gdouble height; + +} glBarcodeShapeBox; + /* * glBarcodeShapeAlpha: * @@ -98,42 +138,77 @@ typedef struct { } glBarcodeShapeAlpha; +/* + * glBarcodeShapeString: + * + * @ = origin (x,y) from top left corner of barcode + * + * ____ _ ------------------ + * / \ | | ^ + * / /\ \ | | | + * / /__\ \ | |___ ____ | + * / ______ \ | ._ \ / __| | ~fsize + * / / \ \ | |_) | | (__ | + * /__/ \__\ |_.___/ \____| | + * v + * @ -------------------------------------- + */ +typedef struct { + + /* Begin Common Fields */ + glBarcodeShapeType type; /* Always GL_BARCODE_SHAPE_ALPHA. */ + gdouble x; + gdouble y; + /* End Common Fields */ + + gdouble fsize; + gchar *str; + +} glBarcodeShapeString; + typedef union { glBarcodeShapeType type; glBarcodeShapeAny any; glBarcodeShapeLine line; + glBarcodeShapeBox box; glBarcodeShapeAlpha alpha; + glBarcodeShapeString string; } glBarcodeShape; -typedef struct { - gdouble width, height; - GList *shapes; /* List of glBarcodeShape */ -} glBarcode; +glBarcodeShapeLine *gl_barcode_shape_line_new (void); +glBarcodeShapeBox *gl_barcode_shape_box_new (void); +glBarcodeShapeAlpha *gl_barcode_shape_alpha_new (void); +glBarcodeShapeString *gl_barcode_shape_string_new (void); -typedef glBarcode *(*glBarcodeNewFunc) (const gchar *id, - gboolean text_flag, - gboolean checksum_flag, - gdouble w, - gdouble h, - const gchar *digits); +void gl_barcode_shape_free (glBarcodeShape *shape); -#define GL_BARCODE_FONT_FAMILY "Sans" -#define GL_BARCODE_FONT_WEIGHT PANGO_WEIGHT_NORMAL +/********************************/ +/* Barcode Intermediate Format. */ +/********************************/ +typedef struct { + gdouble width, height; + GList *shapes; /* List of glBarcodeShape */ +} glBarcode; + +typedef glBarcode *(*glBarcodeNewFunc) (const gchar *id, + gboolean text_flag, + gboolean checksum_flag, + gdouble w, + gdouble h, + const gchar *digits); -glBarcodeShapeLine *gl_barcode_shape_line_new (void); -glBarcodeShapeAlpha *gl_barcode_shape_alpha_new (void); glBarcode *gl_barcode_new (const gchar *id, - gboolean text_flag, - gboolean checksum_flag, - gdouble w, - gdouble h, - const gchar *digits); + gboolean text_flag, + gboolean checksum_flag, + gdouble w, + gdouble h, + const gchar *digits); void gl_barcode_free (glBarcode **bc); @@ -144,7 +219,7 @@ GList *gl_barcode_get_styles_list (void); void gl_barcode_free_styles_list (GList *styles_list); gchar *gl_barcode_default_digits (const gchar *id, - guint n); + guint n); gboolean gl_barcode_can_text (const gchar *id); gboolean gl_barcode_text_optional (const gchar *id); @@ -158,6 +233,7 @@ guint gl_barcode_get_prefered_n (const gchar *id); const gchar *gl_barcode_id_to_name (const gchar *id); const gchar *gl_barcode_name_to_id (const gchar *name); + G_END_DECLS #endif /* __BC_H__ */ diff --git a/src/label-barcode.c b/src/label-barcode.c index fe108fd0..6f538189 100644 --- a/src/label-barcode.c +++ b/src/label-barcode.c @@ -424,7 +424,9 @@ draw_object (glLabelObject *object, glBarcode *gbc; glBarcodeShape *shape; glBarcodeShapeLine *line; + glBarcodeShapeBox *box; glBarcodeShapeAlpha *bchar; + glBarcodeShapeString *bstring; GList *p; gdouble y_offset; PangoLayout *layout; @@ -509,6 +511,14 @@ draw_object (glLabelObject *object, break; + case GL_BARCODE_SHAPE_BOX: + box = (glBarcodeShapeBox *) shape; + + cairo_rectangle (cr, box->x, box->y, box->width, box->height); + cairo_fill (cr); + + break; + case GL_BARCODE_SHAPE_ALPHA: bchar = (glBarcodeShapeAlpha *) shape; @@ -533,6 +543,28 @@ draw_object (glLabelObject *object, break; + 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->str, -1); + + y_offset = 0.2 * bstring->fsize; + + cairo_move_to (cr, bstring->x, bstring->y-y_offset); + pango_cairo_show_layout (cr, layout); + + g_object_unref (layout); + + break; + default: g_assert_not_reached (); break; -- 2.39.5