diff --git a/backend/bmp.c b/backend/bmp.c index a351dc36..c74e8d5b 100644 --- a/backend/bmp.c +++ b/backend/bmp.c @@ -74,6 +74,46 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { for (column = 0; column < symbol->bitmap_width; column++) { i = (3 * column) + (row * row_size); switch (*(pixelbuf + (symbol->bitmap_width * (symbol->bitmap_height - row - 1)) + column)) { + case 'W': // White + bitmap[i] = 255; + bitmap[i + 1] = 255; + bitmap[i + 2] = 255; + break; + case 'C': // Cyan + bitmap[i] = 255; + bitmap[i + 1] = 255; + bitmap[i + 2] = 0; + break; + case 'B': // Blue + bitmap[i] = 255; + bitmap[i + 1] = 0; + bitmap[i + 2] = 0; + break; + case 'M': // Magenta + bitmap[i] = 255; + bitmap[i + 1] = 0; + bitmap[i + 2] = 255; + break; + case 'R': // Red + bitmap[i] = 0; + bitmap[i + 1] = 0; + bitmap[i + 2] = 255; + break; + case 'Y': // Yellow + bitmap[i] = 0; + bitmap[i + 1] = 255; + bitmap[i + 2] = 255; + break; + case 'G': // Green + bitmap[i] = 0; + bitmap[i + 1] = 255; + bitmap[i + 2] = 0; + break; + case 'K': // Black + bitmap[i] = 0; + bitmap[i + 1] = 0; + bitmap[i + 2] = 0; + break; case '1': bitmap[i] = fgblu; bitmap[i + 1] = fggrn; diff --git a/backend/common.c b/backend/common.c index 6ed92fe1..9140ea10 100644 --- a/backend/common.c +++ b/backend/common.c @@ -152,7 +152,11 @@ INTERNAL int ustrchr_cnt(const unsigned char string[], const size_t length, cons /* Return true (1) if a module is dark/black, otherwise false (0) */ INTERNAL int module_is_set(const struct zint_symbol *symbol, const int y_coord, const int x_coord) { - return (symbol->encoded_data[y_coord][x_coord / 7] >> (x_coord % 7)) & 1; + if (symbol->symbology == BARCODE_ULTRA) { + return symbol->encoded_data[y_coord][x_coord]; + } else { + return (symbol->encoded_data[y_coord][x_coord / 7] >> (x_coord % 7)) & 1; + } } /* Set a module to dark/black */ diff --git a/backend/emf.c b/backend/emf.c index 50aa9e66..27c84f93 100644 --- a/backend/emf.c +++ b/backend/emf.c @@ -42,6 +42,51 @@ #include "common.h" #include "emf.h" +int colour_to_red(int colour) { + int return_val = 0; + + switch(colour) { + case 0: // White + case 3: // Magenta + case 4: // Red + case 5: // Yellow + return_val = 255; + break; + } + + return return_val; +} + +int colour_to_green(int colour) { + int return_val = 0; + + switch(colour) { + case 0: // White + case 1: // Cyan + case 5: // Yellow + case 6: // Green + return_val = 255; + break; + } + + return return_val; +} + +int colour_to_blue(int colour) { + int return_val = 0; + + switch(colour) { + case 0: // White + case 1: // Cyan + case 2: // Blue + case 3: // Magenta + return_val = 255; + break; + } + + return return_val; +} + static int count_rectangles(struct zint_symbol *symbol) { int rectangles = 0; struct zint_vector_rect *rect; @@ -137,6 +182,8 @@ INTERNAL int emf_plot(struct zint_symbol *symbol) { int string_count, this_text; int bytecount, recordcount; float radius; + int colours_used = 0; + int rectangle_count_bycolour[8]; unsigned char *this_string[6]; uint32_t spacing; @@ -151,8 +198,10 @@ INTERNAL int emf_plot(struct zint_symbol *symbol) { emr_eof_t emr_eof; emr_createbrushindirect_t emr_createbrushindirect_fg; emr_createbrushindirect_t emr_createbrushindirect_bg; + emr_createbrushindirect_t emr_createbrushindirect_colour[8]; // Used for colour symbols only emr_selectobject_t emr_selectobject_fgbrush; emr_selectobject_t emr_selectobject_bgbrush; + emr_selectobject_t emr_selectobject_colour[8]; // Used for colour symbols only emr_createpen_t emr_createpen; emr_selectobject_t emr_selectobject_pen; emr_rectangle_t background; @@ -191,7 +240,24 @@ INTERNAL int emf_plot(struct zint_symbol *symbol) { hexagon = (emr_polygon_t*) _alloca(hexagon_count * sizeof (emr_polygon_t)); text = (emr_exttextoutw_t*) _alloca(string_count * sizeof (emr_exttextoutw_t)); #endif - + + //Calculate how many coloured rectangles + if (symbol->symbology == BARCODE_ULTRA) { + for (i = 0; i < 8; i++) { + rectangle_count_bycolour[i] = 0; + } + + rect = symbol->vector->rectangles; + this_rectangle = 0; + while (rect) { + if (rectangle_count_bycolour[rect->colour] == 0) { + colours_used++; + } + rectangle_count_bycolour[rect->colour]++; + rect = rect->next; + } + } + /* Header */ emr_header.type = 0x00000001; // EMR_HEADER emr_header.size = 88; // Assuming no additional data in header @@ -218,21 +284,9 @@ INTERNAL int emf_plot(struct zint_symbol *symbol) { recordcount = 1; /* Create Brushes */ - emr_createbrushindirect_fg.type = 0x00000027; // EMR_CREATEBRUSHINDIRECT - emr_createbrushindirect_fg.size = 24; - emr_createbrushindirect_fg.ih_brush = 1; - emr_createbrushindirect_fg.log_brush.brush_style = 0x0000; // BS_SOLID - emr_createbrushindirect_fg.log_brush.color.red = fgred; - emr_createbrushindirect_fg.log_brush.color.green = fggrn; - emr_createbrushindirect_fg.log_brush.color.blue = fgblu; - emr_createbrushindirect_fg.log_brush.color.reserved = 0; - emr_createbrushindirect_fg.log_brush.brush_hatch = 0x0006; // HS_SOLIDCLR - bytecount += 24; - recordcount++; - emr_createbrushindirect_bg.type = 0x00000027; // EMR_CREATEBRUSHINDIRECT emr_createbrushindirect_bg.size = 24; - emr_createbrushindirect_bg.ih_brush = 2; + emr_createbrushindirect_bg.ih_brush = 1; emr_createbrushindirect_bg.log_brush.brush_style = 0x0000; // BS_SOLID emr_createbrushindirect_bg.log_brush.color.red = bgred; emr_createbrushindirect_bg.log_brush.color.green = bggrn; @@ -242,22 +296,60 @@ INTERNAL int emf_plot(struct zint_symbol *symbol) { bytecount += 24; recordcount++; - emr_selectobject_fgbrush.type = 0x00000025; // EMR_SELECTOBJECT - emr_selectobject_fgbrush.size = 12; - emr_selectobject_fgbrush.ih_object = 1; - bytecount += 12; - recordcount++; + if (symbol->symbology == BARCODE_ULTRA) { + for (i = 0; i < 8; i++) { + emr_createbrushindirect_colour[i].type = 0x00000027; // EMR_CREATEBRUSHINDIRECT + emr_createbrushindirect_colour[i].size = 24; + emr_createbrushindirect_colour[i].ih_brush = 2 + i; + emr_createbrushindirect_colour[i].log_brush.brush_style = 0x0000; // BS_SOLID + emr_createbrushindirect_colour[i].log_brush.color.red = colour_to_red(i); + emr_createbrushindirect_colour[i].log_brush.color.green = colour_to_green(i); + emr_createbrushindirect_colour[i].log_brush.color.blue = colour_to_blue(i); + emr_createbrushindirect_colour[i].log_brush.color.reserved = 0; + emr_createbrushindirect_colour[i].log_brush.brush_hatch = 0x0006; // HS_SOLIDCLR + } + bytecount += colours_used * 24; + recordcount += colours_used; + } else { + emr_createbrushindirect_fg.type = 0x00000027; // EMR_CREATEBRUSHINDIRECT + emr_createbrushindirect_fg.size = 24; + emr_createbrushindirect_fg.ih_brush = 2; + emr_createbrushindirect_fg.log_brush.brush_style = 0x0000; // BS_SOLID + emr_createbrushindirect_fg.log_brush.color.red = fgred; + emr_createbrushindirect_fg.log_brush.color.green = fggrn; + emr_createbrushindirect_fg.log_brush.color.blue = fgblu; + emr_createbrushindirect_fg.log_brush.color.reserved = 0; + emr_createbrushindirect_fg.log_brush.brush_hatch = 0x0006; // HS_SOLIDCLR + bytecount += 24; + recordcount++; + } emr_selectobject_bgbrush.type = 0x00000025; // EMR_SELECTOBJECT emr_selectobject_bgbrush.size = 12; - emr_selectobject_bgbrush.ih_object = 2; + emr_selectobject_bgbrush.ih_object = 1; bytecount += 12; recordcount++; + if (symbol->symbology == BARCODE_ULTRA) { + for (i = 0; i < 8; i++) { + emr_selectobject_colour[i].type = 0x00000025; // EMR_SELECTOBJECT + emr_selectobject_colour[i].size = 12; + emr_selectobject_colour[i].ih_object = 2 + i; + } + bytecount += colours_used * 12; + recordcount += colours_used; + } else { + emr_selectobject_fgbrush.type = 0x00000025; // EMR_SELECTOBJECT + emr_selectobject_fgbrush.size = 12; + emr_selectobject_fgbrush.ih_object = 2; + bytecount += 12; + recordcount++; + } + /* Create Pens */ emr_createpen.type = 0x00000026; // EMR_CREATEPEN emr_createpen.size = 28; - emr_createpen.ih_pen = 3; + emr_createpen.ih_pen = 10; emr_createpen.log_pen.pen_style = 0x00000005; // PS_NULL emr_createpen.log_pen.width.x = 1; emr_createpen.log_pen.width.y = 0; // ignored @@ -270,7 +362,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol) { emr_selectobject_pen.type = 0x00000025; // EMR_SELECTOBJECT emr_selectobject_pen.size = 12; - emr_selectobject_pen.ih_object = 3; + emr_selectobject_pen.ih_object = 10; bytecount += 12; recordcount++; @@ -460,8 +552,18 @@ INTERNAL int emf_plot(struct zint_symbol *symbol) { fwrite(&emr_header, sizeof (emr_header_t), 1, emf_file); - fwrite(&emr_createbrushindirect_fg, sizeof (emr_createbrushindirect_t), 1, emf_file); fwrite(&emr_createbrushindirect_bg, sizeof (emr_createbrushindirect_t), 1, emf_file); + + if (symbol->symbology == BARCODE_ULTRA) { + for (i = 0; i < 8; i++) { + if (rectangle_count_bycolour[i]) { + fwrite(&emr_createbrushindirect_colour[i], sizeof (emr_createbrushindirect_t), 1, emf_file); + } + } + } else { + fwrite(&emr_createbrushindirect_fg, sizeof (emr_createbrushindirect_t), 1, emf_file); + } + fwrite(&emr_createpen, sizeof (emr_createpen_t), 1, emf_file); if (symbol->vector->strings) { @@ -472,11 +574,29 @@ INTERNAL int emf_plot(struct zint_symbol *symbol) { fwrite(&emr_selectobject_pen, sizeof (emr_selectobject_t), 1, emf_file); fwrite(&background, sizeof (emr_rectangle_t), 1, emf_file); - fwrite(&emr_selectobject_fgbrush, sizeof (emr_selectobject_t), 1, emf_file); + if (symbol->symbology == BARCODE_ULTRA) { + for(i = 0; i < 8; i++) { + if (rectangle_count_bycolour[i]) { + fwrite(&emr_selectobject_colour[i], sizeof (emr_selectobject_t), 1, emf_file); - // Rectangles - for (i = 0; i < rectangle_count; i++) { - fwrite(&rectangle[i], sizeof (emr_rectangle_t), 1, emf_file); + rect = symbol->vector->rectangles; + this_rectangle = 0; + while (rect) { + if (rect->colour == i) { + fwrite(&rectangle[this_rectangle], sizeof (emr_rectangle_t), 1, emf_file); + } + this_rectangle++; + rect = rect->next; + } + } + } + } else { + fwrite(&emr_selectobject_fgbrush, sizeof (emr_selectobject_t), 1, emf_file); + + // Rectangles + for (i = 0; i < rectangle_count; i++) { + fwrite(&rectangle[i], sizeof (emr_rectangle_t), 1, emf_file); + } } // Hexagons diff --git a/backend/pcx.c b/backend/pcx.c index 111c78f6..e7b91d2d 100644 --- a/backend/pcx.c +++ b/backend/pcx.c @@ -124,24 +124,69 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { for (column = 0; column < symbol->bitmap_width; column++) { switch (colour) { case 0: - if (pixelbuf[(row * symbol->bitmap_width) + column] == '1') { - rle_row[column] = fgred; - } else { - rle_row[column] = bgred; + switch(pixelbuf[(row * symbol->bitmap_width) + column]) { + case 'W': // White + case 'M': // Magenta + case 'R': // Red + case 'Y': // Yellow + rle_row[column] = 255; + break; + case 'C': // Cyan + case 'B': // Blue + case 'G': // Green + case 'K': // Black + rle_row[column] = 0; + break; + case '1': + rle_row[column] = fgred; + break; + default: + rle_row[column] = bgred; + break; } break; case 1: - if (pixelbuf[(row * symbol->bitmap_width) + column] == '1') { - rle_row[column] = fggrn; - } else { - rle_row[column] = bggrn; + switch(pixelbuf[(row * symbol->bitmap_width) + column]) { + case 'W': // White + case 'C': // Cyan + case 'Y': // Yellow + case 'G': // Green + rle_row[column] = 255; + break; + case 'B': // Blue + case 'M': // Magenta + case 'R': // Red + case 'K': // Black + rle_row[column] = 0; + break; + case '1': + rle_row[column] = fggrn; + break; + default: + rle_row[column] = bggrn; + break; } break; case 2: - if (pixelbuf[(row * symbol->bitmap_width) + column] == '1') { - rle_row[column] = fgblu; - } else { - rle_row[column] = bgblu; + switch(pixelbuf[(row * symbol->bitmap_width) + column]) { + case 'W': // White + case 'C': // Cyan + case 'B': // Blue + case 'M': // Magenta + rle_row[column] = 255; + break; + case 'R': // Red + case 'Y': // Yellow + case 'G': // Green + case 'K': // Black + rle_row[column] = 0; + break; + case '1': + rle_row[column] = fgblu; + break; + default: + rle_row[column] = bgblu; + break; } break; } diff --git a/backend/png.c b/backend/png.c index d92c6d70..f2e41f14 100644 --- a/backend/png.c +++ b/backend/png.c @@ -159,6 +159,46 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { for (column = 0; column < symbol->bitmap_width; column++) { i = column * 3; switch (*(pixelbuf + (symbol->bitmap_width * row) + column)) { + case 'W': // White + outdata[i] = 255; + outdata[i + 1] = 255; + outdata[i + 2] = 255; + break; + case 'C': // Cyan + outdata[i] = 0; + outdata[i + 1] = 255; + outdata[i + 2] = 255; + break; + case 'B': // Blue + outdata[i] = 0; + outdata[i + 1] = 0; + outdata[i + 2] = 255; + break; + case 'M': // Magenta + outdata[i] = 255; + outdata[i + 1] = 0; + outdata[i + 2] = 255; + break; + case 'R': // Red + outdata[i] = 255; + outdata[i + 1] = 0; + outdata[i + 2] = 0; + break; + case 'Y': // Yellow + outdata[i] = 255; + outdata[i + 1] = 255; + outdata[i + 2] = 0; + break; + case 'G': // Green + outdata[i] = 0; + outdata[i + 1] = 255; + outdata[i + 2] = 0; + break; + case 'K': // Black + outdata[i] = 0; + outdata[i + 1] = 0; + outdata[i + 2] = 0; + break; case '1': outdata[i] = fgred; outdata[i + 1] = fggrn; diff --git a/backend/ps.c b/backend/ps.c index 0839fc42..31a2f39d 100644 --- a/backend/ps.c +++ b/backend/ps.c @@ -38,6 +38,69 @@ #include #include "common.h" +void colour_to_pscolor(int option, int colour, char* output) { + strcpy(output, ""); + if ((option & CMYK_COLOUR) == 0) { + // Use RGB colour space + switch(colour) { + case 0: // White + strcat(output, "1.00 1.00 1.00"); + break; + case 1: // Cyan + strcat(output, "0.00 1.00 1.00"); + break; + case 2: // Blue + strcat(output, "0.00 0.00 1.00"); + break; + case 3: // Magenta + strcat(output, "1.00 0.00 1.00"); + break; + case 4: // Red + strcat(output, "1.00 0.00 0.00"); + break; + case 5: // Yellow + strcat(output, "1.00 1.00 0.00"); + break; + case 6: // Green + strcat(output, "0.00 1.00 0.00"); + break; + default: // Black + strcat(output, "0.00 0.00 0.00"); + break; + } + strcat(output, " setrgbcolor"); + } else { + // Use CMYK colour space + switch(colour) { + case 0: // White + strcat(output, "0.00 0.00 0.00 0.00"); + break; + case 1: // Cyan + strcat(output, "1.00 0.00 0.00 0.00"); + break; + case 2: // Blue + strcat(output, "1.00 1.00 0.00 0.00"); + break; + case 3: // Magenta + strcat(output, "0.00 1.00 0.00 0.00"); + break; + case 4: // Red + strcat(output, "0.00 1.00 1.00 0.00"); + break; + case 5: // Yellow + strcat(output, "0.00 0.00 1.00 0.00"); + break; + case 6: // Green + strcat(output, "1.00 0.00 1.00 0.00"); + break; + default: // Black + strcat(output, "0.00 0.00 0.00 1.00"); + break; + } + strcat(output, " setcmykcolor"); + } +} + INTERNAL int ps_plot(struct zint_symbol *symbol) { FILE *feps; int fgred, fggrn, fgblu, bgred, bggrn, bgblu; @@ -47,6 +110,8 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { int error_number = 0; float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy; float radius; + int colour_index, colour_rect_counter; + char ps_color[30]; struct zint_vector_rect *rect; struct zint_vector_hexagon *hex; @@ -153,18 +218,40 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { fprintf(feps, "%.2f 0.00 TB 0.00 %.2f TR\n", symbol->vector->height, symbol->vector->width); fprintf(feps, "TE\n"); - if ((symbol->output_options & CMYK_COLOUR) == 0) { - fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); - } else { - fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink); + if (symbol->symbology != BARCODE_ULTRA) { + if ((symbol->output_options & CMYK_COLOUR) == 0) { + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + } else { + fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink); + } } // Rectangles - rect = symbol->vector->rectangles; - while (rect) { - fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", rect->height, (symbol->vector->height - rect->y) - rect->height, rect->x, rect->width); - fprintf(feps, "TE\n"); - rect = rect->next; + if (symbol->symbology == BARCODE_ULTRA) { + for (colour_index = 0; colour_index <= 7; colour_index++) { + colour_rect_counter = 0; + rect = symbol->vector->rectangles; + while (rect) { + if (rect->colour == colour_index) { + if (colour_rect_counter == 0) { + //Set new colour + colour_to_pscolor(symbol->output_options, colour_index, ps_color); + fprintf(feps, "%s\n", ps_color); + } + colour_rect_counter++; + fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", rect->height, (symbol->vector->height - rect->y) - rect->height, rect->x, rect->width); + fprintf(feps, "TE\n"); + } + rect = rect->next; + } + } + } else { + rect = symbol->vector->rectangles; + while (rect) { + fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", rect->height, (symbol->vector->height - rect->y) - rect->height, rect->x, rect->width); + fprintf(feps, "TE\n"); + rect = rect->next; + } } // Hexagons diff --git a/backend/raster.c b/backend/raster.c index 5cf24c1a..5705ed91 100644 --- a/backend/raster.c +++ b/backend/raster.c @@ -47,6 +47,9 @@ #define SSET "0123456789ABCDEF" +#define DEFAULT_INK '1' +#define DEFAULT_PAPER '0' + #ifndef NO_PNG INTERNAL int png_pixel_plot(struct zint_symbol *symbol, char *pixelbuf); #endif /* NO_PNG */ @@ -55,6 +58,8 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, char *pixelbuf); INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf); INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf); +static const char ultra_colour[] = "WCBMRYGK"; + static void buffer_plot(struct zint_symbol *symbol, char *pixelbuf) { /* Place pixelbuffer into symbol */ int fgred, fggrn, fgblu, bgred, bggrn, bgblu; @@ -73,12 +78,52 @@ static void buffer_plot(struct zint_symbol *symbol, char *pixelbuf) { for (column = 0; column < symbol->bitmap_width; column++) { i = ((row * symbol->bitmap_width) + column) * 3; switch (*(pixelbuf + (symbol->bitmap_width * row) + column)) { - case '1': + case 'W': // White + symbol->bitmap[i] = 255; + symbol->bitmap[i + 1] = 255; + symbol->bitmap[i + 2] = 255; + break; + case 'C': // Cyan + symbol->bitmap[i] = 0; + symbol->bitmap[i + 1] = 255; + symbol->bitmap[i + 2] = 255; + break; + case 'B': // Blue + symbol->bitmap[i] = 0; + symbol->bitmap[i + 1] = 0; + symbol->bitmap[i + 2] = 255; + break; + case 'M': // Magenta + symbol->bitmap[i] = 255; + symbol->bitmap[i + 1] = 0; + symbol->bitmap[i + 2] = 255; + break; + case 'R': // Red + symbol->bitmap[i] = 255; + symbol->bitmap[i + 1] = 0; + symbol->bitmap[i + 2] = 0; + break; + case 'Y': // Yellow + symbol->bitmap[i] = 255; + symbol->bitmap[i + 1] = 255; + symbol->bitmap[i + 2] = 0; + break; + case 'G': // Green + symbol->bitmap[i] = 0; + symbol->bitmap[i + 1] = 255; + symbol->bitmap[i + 2] = 0; + break; + case 'K': // Black + symbol->bitmap[i] = 0; + symbol->bitmap[i + 1] = 0; + symbol->bitmap[i + 2] = 0; + break; + case DEFAULT_INK: symbol->bitmap[i] = fgred; symbol->bitmap[i + 1] = fggrn; symbol->bitmap[i + 2] = fgblu; break; - default: + default: // DEFAULT_PAPER symbol->bitmap[i] = bgred; symbol->bitmap[i + 1] = bggrn; symbol->bitmap[i + 2] = bgblu; @@ -207,7 +252,7 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, int image_heigh return error_number; } -static void draw_bar(char *pixelbuf, int xpos, int xlen, int ypos, int ylen, int image_width, int image_height) { +static void draw_bar(char *pixelbuf, int xpos, int xlen, int ypos, int ylen, int image_width, int image_height, char fill) { /* Draw a rectangle */ int i, j, png_ypos; @@ -217,7 +262,7 @@ static void draw_bar(char *pixelbuf, int xpos, int xlen, int ypos, int ylen, int for (i = (xpos); i < (xpos + xlen); i++) { for (j = (png_ypos); j < (png_ypos + ylen); j++) { - *(pixelbuf + (image_width * j) + i) = '1'; + *(pixelbuf + (image_width * j) + i) = fill; } } } @@ -246,13 +291,13 @@ static void draw_bullseye(char *pixelbuf, int image_width, int image_height, int x = 16.0 * scaler; y = 16.5 * scaler; } - - draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (4.571 * scaler) + 1, '1'); - draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (3.779 * scaler) + 1, '0'); - draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (2.988 * scaler) + 1, '1'); - draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (2.196 * scaler) + 1, '0'); - draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (1.394 * scaler) + 1, '1'); - draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (0.602 * scaler) + 1, '0'); + + draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (4.571 * scaler) + 1, DEFAULT_INK); + draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (3.779 * scaler) + 1, DEFAULT_PAPER); + draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (2.988 * scaler) + 1, DEFAULT_INK); + draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (2.196 * scaler) + 1, DEFAULT_PAPER); + draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (1.394 * scaler) + 1, DEFAULT_INK); + draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (0.602 * scaler) + 1, DEFAULT_PAPER); } static void draw_hexagon(char *pixelbuf, int image_width, char *scaled_hexagon, int hexagon_size, int xposn, int yposn) { @@ -261,8 +306,8 @@ static void draw_hexagon(char *pixelbuf, int image_width, char *scaled_hexagon, for (i = 0; i < hexagon_size; i++) { for (j = 0; j < hexagon_size; j++) { - if (scaled_hexagon[(i * hexagon_size) + j] == '1') { - *(pixelbuf + (image_width * i) + (image_width * yposn) + xposn + j) = '1'; + if (scaled_hexagon[(i * hexagon_size) + j] == DEFAULT_INK) { + *(pixelbuf + (image_width * i) + (image_width * yposn) + xposn + j) = DEFAULT_INK; } } } @@ -313,7 +358,7 @@ static void draw_letter(char *pixelbuf, unsigned char letter, int xposn, int ypo for (y = 0; y < max_y; y++) { for (x = 0; x < max_x; x++) { if (small_font[(glyph_no * 9) + y] & (0x10 >> x)) { - *(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = '1'; + *(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = DEFAULT_INK; } } } @@ -339,11 +384,11 @@ static void draw_letter(char *pixelbuf, unsigned char letter, int xposn, int ypo int extra_dot = 0; for (x = 0; x < 7; x++) { if (ascii_font[(glyph_no * 14) + y] & (0x40 >> x)) { - *pixelPtr = '1'; + *pixelPtr = DEFAULT_INK; extra_dot = 1; } else { if (extra_dot) { - *pixelPtr = '1'; + *pixelPtr = DEFAULT_INK; } extra_dot = 0; @@ -353,7 +398,7 @@ static void draw_letter(char *pixelbuf, unsigned char letter, int xposn, int ypo } if (extra_dot) { - *pixelPtr = '1'; + *pixelPtr = DEFAULT_INK; } linePtr += image_width; @@ -376,7 +421,7 @@ static void draw_letter(char *pixelbuf, unsigned char letter, int xposn, int ypo for (y = 0; y < max_y; y++) { for (x = 0; x < 7; x++) { if (ascii_font[(glyph_no * 14) + y] & (0x40 >> x)) { - *(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = '1'; + *(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = DEFAULT_INK; } } } @@ -424,7 +469,7 @@ static void plot_hexline(char *scaled_hexagon, int hexagon_size, float start_x, float this_x = start_x + ((float)i * inc_x); float this_y = start_y + ((float)i * inc_y); if (((this_x >= 0) && (this_x < hexagon_size)) && ((this_y >= 0) && (this_y < hexagon_size))) { - scaled_hexagon[(hexagon_size * (int)this_y) + (int)this_x] = '1'; + scaled_hexagon[(hexagon_size * (int)this_y) + (int)this_x] = DEFAULT_INK; } } } @@ -468,17 +513,17 @@ static void plot_hexagon(char *scaled_hexagon, int hexagon_size) { /* Fill hexagon */ for (line = 0; line < hexagon_size; line++) { - char ink = '0'; + char ink = DEFAULT_PAPER; for (i = 0; i < hexagon_size; i++) { - if (scaled_hexagon[(hexagon_size * line) + i] == '1') { + if (scaled_hexagon[(hexagon_size * line) + i] == DEFAULT_INK) { if (i < (hexagon_size / 2)) { - ink = '1'; + ink = DEFAULT_INK; } else { - ink = '0'; + ink = DEFAULT_PAPER; } } - if (ink == '1') { + if (ink == DEFAULT_INK) { scaled_hexagon[(hexagon_size * line) + i] = ink; } } @@ -506,7 +551,7 @@ static int plot_raster_maxicode(struct zint_symbol *symbol, int rotate_angle, in return ZINT_ERROR_ENCODING_PROBLEM; } else { for (i = 0; i < (image_width * image_height); i++) { - *(pixelbuf + i) = '0'; + *(pixelbuf + i) = DEFAULT_PAPER; } } @@ -518,7 +563,7 @@ static int plot_raster_maxicode(struct zint_symbol *symbol, int rotate_angle, in return ZINT_ERROR_ENCODING_PROBLEM; } else { for (i = 0; i < (hexagon_size * hexagon_size); i++) { - *(scaled_hexagon + i) = '0'; + *(scaled_hexagon + i) = DEFAULT_PAPER; } } @@ -548,14 +593,14 @@ static int plot_raster_maxicode(struct zint_symbol *symbol, int rotate_angle, in if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) { /* boundary bars */ - draw_bar(pixelbuf, 0, image_width, 0, symbol->border_width * 2, image_width, image_height); - draw_bar(pixelbuf, 0, image_width, 300 + (symbol->border_width * 2), symbol->border_width * 2, image_width, image_height); + draw_bar(pixelbuf, 0, image_width, 0, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, 0, image_width, 300 + (symbol->border_width * 2), symbol->border_width * 2, image_width, image_height, DEFAULT_INK); } if (symbol->output_options & BARCODE_BOX) { /* side bars */ - draw_bar(pixelbuf, 0, symbol->border_width * 2, 0, image_height, image_width, image_height); - draw_bar(pixelbuf, 300 + ((symbol->border_width + symbol->whitespace_width + symbol->whitespace_width) * 2), symbol->border_width * 2, 0, image_height, image_width, image_height); + draw_bar(pixelbuf, 0, symbol->border_width * 2, 0, image_height, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, 300 + ((symbol->border_width + symbol->whitespace_width + symbol->whitespace_width) * 2), symbol->border_width * 2, 0, image_height, image_width, image_height, DEFAULT_INK); } error_number = save_raster_image_to_file(symbol, image_height, image_width, pixelbuf, rotate_angle, data_type); @@ -630,7 +675,7 @@ static int plot_raster_dotty(struct zint_symbol *symbol, int rotate_angle, int d return ZINT_ERROR_ENCODING_PROBLEM; } else { for (i = 0; i < (scale_width * scale_height); i++) { - *(scaled_pixelbuf + i) = '0'; + *(scaled_pixelbuf + i) = DEFAULT_PAPER; } } @@ -642,7 +687,7 @@ static int plot_raster_dotty(struct zint_symbol *symbol, int rotate_angle, int d (int) ((i + xoffset) * scaler) + (scaler / 2.0), (int) ((r + yoffset) * scaler) + (scaler / 2.0), (symbol->dot_size / 2.0) * scaler, - '1'); + DEFAULT_INK); } } } @@ -796,7 +841,7 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int return ZINT_ERROR_ENCODING_PROBLEM; } else { for (i = 0; i < (image_width * image_height); i++) { - *(pixelbuf + i) = '0'; + *(pixelbuf + i) = DEFAULT_PAPER; } } @@ -815,6 +860,7 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int int plot_yposn; int plot_height; int this_row = symbol->rows - r - 1; /* invert r otherwise plots upside down */ + int module_fill; row_posn += row_height; plot_yposn = next_yposn; if (symbol->row_height[this_row] == 0) { @@ -826,30 +872,27 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int plot_height = next_yposn - plot_yposn; i = 0; - if (module_is_set(symbol, this_row, 0)) { - latch = 1; - } else { - latch = 0; - } do { + module_fill = module_is_set(symbol, this_row, i); block_width = 0; do { block_width++; } while ((i + block_width < symbol->width) && module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i)); + if ((addon_latch == 0) && (r == 0) && (i > main_width)) { plot_height = (int) (row_height - 5.0); plot_yposn = (int) (row_posn - 5.0); addon_text_posn = row_posn + row_height - 8.0; addon_latch = 1; } - if (latch == 1) { + if (module_fill) { /* a bar */ - draw_bar(pixelbuf, (i + xoffset) * 2, block_width * 2, plot_yposn * 2, plot_height * 2, image_width, image_height); - latch = 0; - } else { - /* a space */ - latch = 1; + if (symbol->symbology == BARCODE_ULTRA) { + draw_bar(pixelbuf, (i + xoffset) * 2, block_width * 2, plot_yposn * 2, plot_height * 2, image_width, image_height, ultra_colour[module_fill]); + } else { + draw_bar(pixelbuf, (i + xoffset) * 2, block_width * 2, plot_yposn * 2, plot_height * 2, image_width, image_height, DEFAULT_INK); + } } i += block_width; @@ -865,12 +908,12 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int case 8: /* EAN-8 */ case 11: case 14: - draw_bar(pixelbuf, (0 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (2 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (32 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (34 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (64 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (66 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); + draw_bar(pixelbuf, (0 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (2 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (32 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (34 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (64 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (66 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); for (i = 0; i < 4; i++) { textpart[i] = local_text[i]; } @@ -900,12 +943,12 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int case 13: /* EAN 13 */ case 16: case 19: - draw_bar(pixelbuf, (0 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (2 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (46 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (48 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (92 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (94 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); + draw_bar(pixelbuf, (0 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (2 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (46 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (48 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (92 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (94 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); textpart[0] = local_text[0]; textpart[1] = '\0'; @@ -951,7 +994,7 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int } while ((i + block_width < symbol->width) && module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i)); if (latch == 1) { /* a bar */ - draw_bar(pixelbuf, (i + xoffset - comp_offset) * 2, block_width * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); + draw_bar(pixelbuf, (i + xoffset - comp_offset) * 2, block_width * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); latch = 0; } else { /* a space */ @@ -959,8 +1002,8 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int } i += block_width; } while (i < 11 + comp_offset); - draw_bar(pixelbuf, (46 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (48 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); + draw_bar(pixelbuf, (46 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (48 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); latch = 1; i = 85 + comp_offset; do { @@ -970,7 +1013,7 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int } while ((i + block_width < symbol->width) && module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i)); if (latch == 1) { /* a bar */ - draw_bar(pixelbuf, (i + xoffset - comp_offset) * 2, block_width * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); + draw_bar(pixelbuf, (i + xoffset - comp_offset) * 2, block_width * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); latch = 0; } else { /* a space */ @@ -1013,11 +1056,11 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int } else if ((symbol->symbology == BARCODE_UPCE) || (symbol->symbology == BARCODE_UPCE_CHK) || (symbol->symbology == BARCODE_UPCE_CC)) { /* guard bar extensions and text formatting for UPCE */ - draw_bar(pixelbuf, (0 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (2 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (46 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (48 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); - draw_bar(pixelbuf, (50 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height); + draw_bar(pixelbuf, (0 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (2 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (46 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (48 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (50 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height, DEFAULT_INK); textpart[0] = local_text[0]; textpart[1] = '\0'; @@ -1053,23 +1096,23 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) { /* boundary bars */ if (symbol->symbology != BARCODE_CODABLOCKF) { - draw_bar(pixelbuf, 0, (symbol->width + xoffset + xoffset) * 2, textoffset * 2, symbol->border_width * 2, image_width, image_height); - draw_bar(pixelbuf, 0, (symbol->width + xoffset + xoffset) * 2, (textoffset + symbol->height + symbol->border_width) * 2, symbol->border_width * 2, image_width, image_height); + draw_bar(pixelbuf, 0, (symbol->width + xoffset + xoffset) * 2, textoffset * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, 0, (symbol->width + xoffset + xoffset) * 2, (textoffset + symbol->height + symbol->border_width) * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); } else { - draw_bar(pixelbuf, xoffset * 2, symbol->width * 2, textoffset * 2, symbol->border_width * 2, image_width, image_height); - draw_bar(pixelbuf, xoffset * 2, symbol->width * 2, (textoffset + symbol->height + symbol->border_width) * 2, symbol->border_width * 2, image_width, image_height); + draw_bar(pixelbuf, xoffset * 2, symbol->width * 2, textoffset * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, xoffset * 2, symbol->width * 2, (textoffset + symbol->height + symbol->border_width) * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); } if ((symbol->output_options & BARCODE_BIND) != 0) { if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) { /* row binding */ if (symbol->symbology != BARCODE_CODABLOCKF) { for (r = 1; r < symbol->rows; r++) { - draw_bar(pixelbuf, xoffset * 2, symbol->width * 2, ((r * row_height) + textoffset + yoffset - 1) * 2, 2 * 2, image_width, image_height); + draw_bar(pixelbuf, xoffset * 2, symbol->width * 2, ((r * row_height) + textoffset + yoffset - 1) * 2, 2 * 2, image_width, image_height, DEFAULT_INK); } } else { for (r = 1; r < symbol->rows; r++) { /* Avoid 11-module start and stop chars */ - draw_bar(pixelbuf, (xoffset + 11) * 2 , (symbol->width - 22) * 2, ((r * row_height) + textoffset + yoffset - 1) * 2, 2 * 2, image_width, image_height); + draw_bar(pixelbuf, (xoffset + 11) * 2 , (symbol->width - 22) * 2, ((r * row_height) + textoffset + yoffset - 1) * 2, 2 * 2, image_width, image_height, DEFAULT_INK); } } } @@ -1078,8 +1121,8 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int if (symbol->output_options & BARCODE_BOX) { /* side bars */ - draw_bar(pixelbuf, 0, symbol->border_width * 2, textoffset * 2, (symbol->height + (2 * symbol->border_width)) * 2, image_width, image_height); - draw_bar(pixelbuf, (symbol->width + xoffset + xoffset - symbol->border_width) * 2, symbol->border_width * 2, textoffset * 2, (symbol->height + (2 * symbol->border_width)) * 2, image_width, image_height); + draw_bar(pixelbuf, 0, symbol->border_width * 2, textoffset * 2, (symbol->height + (2 * symbol->border_width)) * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (symbol->width + xoffset + xoffset - symbol->border_width) * 2, symbol->border_width * 2, textoffset * 2, (symbol->height + (2 * symbol->border_width)) * 2, image_width, image_height, DEFAULT_INK); } /* Put the human readable text at the bottom */ @@ -1102,7 +1145,7 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int return ZINT_ERROR_ENCODING_PROBLEM; } else { for (i = 0; i < (scale_width * scale_height); i++) { - *(scaled_pixelbuf + i) = '0'; + *(scaled_pixelbuf + i) = DEFAULT_PAPER; } } diff --git a/backend/svg.c b/backend/svg.c index 35d5b526..98cca3d9 100644 --- a/backend/svg.c +++ b/backend/svg.c @@ -41,6 +41,35 @@ #include "common.h" +void pick_colour(int colour, char colour_code[]) { + switch(colour) { + case 0: // White + strcpy(colour_code, "ffffff"); + break; + case 1: // Cyan + strcpy(colour_code, "00ffff"); + break; + case 2: // Blue + strcpy(colour_code, "0000ff"); + break; + case 3: // Magenta + strcpy(colour_code, "ff00ff"); + break; + case 4: // Red + strcpy(colour_code, "ff0000"); + break; + case 5: // Yellow + strcpy(colour_code, "ffff00"); + break; + case 6: // Green + strcpy(colour_code, "00ff00"); + break; + default: // Black + strcpy(colour_code, "000000"); + break; + } +} + static void make_html_friendly(unsigned char * string, char * html_version) { /* Converts text to use HTML entity codes */ @@ -98,6 +127,8 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { struct zint_vector_circle *circle; struct zint_vector_string *string; + char colour_code[7]; + #ifdef _MSC_VER char* html_string; #endif @@ -153,7 +184,12 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { rect = symbol->vector->rectangles; while (rect) { - fprintf(fsvg, " \n", rect->x, rect->y, rect->width, rect->height); + if (rect->colour == -1) { + fprintf(fsvg, " \n", rect->x, rect->y, rect->width, rect->height); + } else { + pick_colour(rect->colour, colour_code); + fprintf(fsvg, " \n", rect->x, rect->y, rect->width, rect->height, colour_code); + } rect = rect->next; } diff --git a/backend/tif.c b/backend/tif.c index 9c9afe36..30caf4d8 100644 --- a/backend/tif.c +++ b/backend/tif.c @@ -76,16 +76,16 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { if ((symbol->bitmap_height % rows_per_strip) != 0) { strip_count++; } - + if (rows_per_strip > symbol->bitmap_height) { rows_per_strip = symbol->bitmap_height; } - + if (strip_count == 1) { rows_per_strip = (rows_per_strip / 2) + 1; strip_count++; } - + #ifndef _MSC_VER uint32_t strip_offset[strip_count]; uint32_t strip_bytes[strip_count]; @@ -140,24 +140,67 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { fwrite(&header, sizeof(tiff_header_t), 1, tif_file); free_memory += sizeof(tiff_ifd_t); - + /* Pixel data */ strip = 0; bytes_put = 0; for (row = 0; row < symbol->bitmap_height; row++) { for (column = 0; column < symbol->bitmap_width; column++) { - if (pixelbuf[(row * symbol->bitmap_width) + column] == '1') { - putc(fgred, tif_file); - putc(fggrn, tif_file); - putc(fgblu, tif_file); - } else { - putc(bgred, tif_file); - putc(bggrn, tif_file); - putc(bgblu, tif_file); + switch(pixelbuf[(row * symbol->bitmap_width) + column]) { + case 'W': // White + putc(255, tif_file); + putc(255, tif_file); + putc(255, tif_file); + break; + case 'C': // Cyan + putc(0, tif_file); + putc(255, tif_file); + putc(255, tif_file); + break; + case 'B': // Blue + putc(0, tif_file); + putc(0, tif_file); + putc(255, tif_file); + break; + case 'M': // Magenta + putc(255, tif_file); + putc(0, tif_file); + putc(255, tif_file); + break; + case 'R': // Red + putc(255, tif_file); + putc(0, tif_file); + putc(0, tif_file); + break; + case 'Y': // Yellow + putc(255, tif_file); + putc(255, tif_file); + putc(0, tif_file); + break; + case 'G': // Green + putc(0, tif_file); + putc(255, tif_file); + putc(0, tif_file); + break; + case 'K': // Black + putc(0, tif_file); + putc(0, tif_file); + putc(0, tif_file); + break; + case '1': + putc(fgred, tif_file); + putc(fggrn, tif_file); + putc(fgblu, tif_file); + break; + default: + putc(bgred, tif_file); + putc(bggrn, tif_file); + putc(bgblu, tif_file); + break; } bytes_put += 3; } - + if ((bytes_put + 3) >= strip_bytes[strip]) { // End of strip, pad if strip length is odd if (strip_bytes[strip] % 2 == 1) { diff --git a/backend/ultra.c b/backend/ultra.c index 29f807e8..bd022966 100644 --- a/backend/ultra.c +++ b/backend/ultra.c @@ -1,7 +1,7 @@ /* ultra.c - Ultracode libzint - the open source barcode library - Copyright (C) 2019 Robin Stuart + Copyright (C) 2020 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,13 +29,1002 @@ SUCH DAMAGE. */ + /* This version was developed using AIMD/TSC15032-43 v0.99c Edit 60, dated 4th Nov 2015 */ + +#ifdef _MSC_VER +#include +#endif #include #include #include "common.h" -INTERNAL int ultracode(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length) { +#define EIGHTBIT_MODE 10 +#define ASCII_MODE 20 +#define C43_MODE 30 +#define PREDICT_WINDOW 12 - strcpy(symbol->errtxt, "1000: Ultracode has not been implemented - yet!"); - return ZINT_ERROR_INVALID_OPTION; +#define GFMUL(i, j) ((((i) == 0)||((j) == 0)) ? 0 : gfPwr[(gfLog[i] + gfLog[j])]) + +static const char fragment[27][14] = {"http://", "https://", "http://www.", "https://www.", + "ftp://", "www.", ".com", ".edu", ".gov", ".int", ".mil", ".net", ".org", + ".mobi", ".coop", ".biz", ".info", "mailto:", "tel:", ".cgi", ".asp", + ".aspx", ".php", ".htm", ".html", ".shtml", "file:"}; + +static const char ultra_c43_set1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 .,%"; +static const char ultra_c43_set2[] = "abcdefghijklmnopqrstuvwxyz:/?#[]@=_~!.,-"; +static const char ultra_c43_set3[] = "{}`()\"+'<>|$;&\\^*"; +static const char ultra_digit[] = "0123456789,/"; +static const char ultra_colour[] = "WCBMRYGK"; + +//static const int ultra_maxsize[] = {34, 78, 158, 282}; // According to Table 1 +//static const int ultra_maxsize[] = {34, 82, 158, 282}; // Adjusted to allow 79-82 codeword range in 3-row symbols +static const int ultra_maxsize[] = {38, 91, 158, 282}; // Adjusted again to ensure DCC is never negative + +static const int ultra_mincols[] = {5, 13, 23, 30}; // # Total Tile Columns from Table 1 + +static const int kec[] = {0, 1, 2, 4, 6, 8}; // Value K(EC) from Table 12 + +static const int dccu[] = { + 051363, 051563, 051653, 053153, 053163, 053513, 053563, 053613, // 0-7 + 053653, 056153, 056163, 056313, 056353, 056363, 056513, 056563, // 8-15 + 051316, 051356, 051536, 051616, 053156, 053516, 053536, 053616, // 16-23 + 053636, 053656, 056136, 056156, 056316, 056356, 056516, 056536 // 24-31 +}; + +static const int dccl[] = { + 061351, 061361, 061531, 061561, 061631, 061651, 063131, 063151, // 0-7 + 063161, 063531, 063561, 063631, 065131, 065161, 065351, 065631, // 8-15 + 031351, 031361, 031531, 031561, 031631, 031651, 035131, 035151, // 16-23 + 035161, 035361, 035631, 035651, 036131, 036151, 036351, 036531 // 24-31 +}; + +static const int tiles[] = { + 013135, 013136, 013153, 013156, 013163, 013165, 013513, 013515, 013516, 013531, // 0-9 + 013535, 013536, 013561, 013563, 013565, 013613, 013615, 013616, 013631, 013635, // 10-19 + 013636, 013651, 013653, 013656, 015135, 015136, 015153, 015163, 015165, 015313, // 20-29 + 015315, 015316, 015351, 015353, 015356, 015361, 015363, 015365, 015613, 015615, // 30-39 + 015616, 015631, 015635, 015636, 015651, 015653, 015656, 016135, 016136, 016153, // 40-49 + 016156, 016165, 016313, 016315, 016316, 016351, 016353, 016356, 016361, 016363, // 50-59 + 016365, 016513, 016515, 016516, 016531, 016535, 016536, 016561, 016563, 016565, // 60-69 + 031315, 031316, 031351, 031356, 031361, 031365, 031513, 031515, 031516, 031531, // 70-79 + 031535, 031536, 031561, 031563, 031565, 031613, 031615, 031631, 031635, 031636, // 80-89 + 031651, 031653, 031656, 035131, 035135, 035136, 035151, 035153, 035156, 035161, // 90-99 + 035163, 035165, 035315, 035316, 035351, 035356, 035361, 035365, 035613, 035615, // 100-109 + 035616, 035631, 035635, 035636, 035651, 035653, 035656, 036131, 036135, 036136, // 110-119 + 036151, 036153, 036156, 036163, 036165, 036315, 036316, 036351, 036356, 036361, // 120-129 + 036365, 036513, 036515, 036516, 036531, 036535, 036536, 036561, 036563, 036565, // 130-139 + 051313, 051315, 051316, 051351, 051353, 051356, 051361, 051363, 051365, 051513, // 140-149 + 051516, 051531, 051536, 051561, 051563, 051613, 051615, 051616, 051631, 051635, // 150-159 + 051636, 051651, 051653, 051656, 053131, 053135, 053136, 053151, 053153, 053156, // 160-169 + 053161, 053163, 053165, 053513, 053516, 053531, 053536, 053561, 053563, 053613, // 170-179 + 053615, 053616, 053631, 053635, 053636, 053651, 053653, 053656, 056131, 056135, // 180-189 + 056136, 056151, 056153, 056156, 056161, 056163, 056165, 056313, 056315, 056316, // 190-199 + 056351, 056353, 056356, 056361, 056363, 056365, 056513, 056516, 056531, 056536, // 200-209 + 056561, 056563, 061313, 061315, 061316, 061351, 061353, 061356, 061361, 061363, // 210-219 + 061365, 061513, 061515, 061516, 061531, 061535, 061536, 061561, 061563, 061565, // 220-229 + 061615, 061631, 061635, 061651, 061653, 063131, 063135, 063136, 063151, 063153, // 230-239 + 063156, 063161, 063163, 063165, 063513, 063515, 063516, 063531, 063535, 063536, // 240-249 + 063561, 063563, 063565, 063613, 063615, 063631, 063635, 063651, 063653, 065131, // 250-259 + 065135, 065136, 065151, 065153, 065156, 065161, 065163, 065165, 065313, 065315, // 260-269 + 065316, 065351, 065353, 065356, 065361, 065363, 065365, 065613, 065615, 065631, // 270-279 + 065635, 065651, 065653, 056565, 051515 // 280-284 +}; + +/* The following adapted from ECC283.C "RSEC codeword generator" + * from Annex B of Ultracode draft + * originally written by Ted Williams of Symbol Vision Corp. + * Dated 2001-03-09 + * Corrected thanks to input from Terry Burton */ + +/* + * NOTE: Included here is an attempt to allow code compression within Ultracode. Unfortunately + * the copy of the standard this was written from was an early draft which includes self + * contradictions, so this is a "best guess" implementation. Because it is not guaranteed + * to be correct this compression is not applied by default. To enable compression set + * + * symbol->option_1 = ULTRA_COMPRESSION; + * + * Code compression should be enabled by default when it has been implemented according to + * a more reliable version of the specification. + */ + +/* Generate divisor polynomial gQ(x) for GF283() given the required ECC size, 3 to 101 */ +void ultra_genPoly(short EccSize, unsigned short gPoly[], unsigned short gfPwr[], unsigned short gfLog[]) { + int i, j; + + gPoly[0] = 1; + for (i = 1; i < (EccSize + 1); i++) gPoly[i] = 0; + + for (i = 0; i < EccSize; i++) { + for (j = i; j >= 0; j--) + gPoly[j + 1] = (gPoly[j] + GFMUL(gPoly[j + 1], gfPwr[i + 1])) % 283; + gPoly[0] = GFMUL(gPoly[0], gfPwr[i + 1]); + } + for (i = EccSize - 1; i >= 0; i -= 2) gPoly[i] = 283 - gPoly[i]; + + /* gPoly[i] is > 0 so modulo operation not needed */ +} + +/* Generate the log and antilog tables for GF283() multiplication & division */ +void ultra_initLogTables(unsigned short gfPwr[], unsigned short gfLog[]) { + int i, j; + + for (j = 0; j < 283; j++) gfLog[j] = 0; + i = 1; + for (j = 0; j < 282; j++) { + /* j + 282 indicies save doing the modulo operation in GFMUL */ + gfPwr[j + 282] = gfPwr[j] = (short) i; + gfLog[i] = (short) j; + i = (i * 3) % 283; + } +} + +void ultra_gf283(short DataSize, short EccSize, int Message[]) { + /* Input is complete message codewords in array Message[282] + * DataSize is number of message codewords + * EccSize is number of Reed-Solomon GF(283) check codewords to generate + * + * Upon exit, Message[282] contains complete 282 codeword Symbol Message + * including leading zeroes corresponding to each truncated codeword */ + + unsigned short gPoly[283], gfPwr[(282 * 2)], gfLog[283]; + int i, j, n; + unsigned short t; + + /* first build the log & antilog tables used in multiplication & division */ + ultra_initLogTables(gfPwr, gfLog); + + /* then generate the division polynomial of length EccSize */ + ultra_genPoly(EccSize, gPoly, gfPwr, gfLog); + + /* zero all EccSize codeword values */ + for (j = 281; (j > (281 - EccSize)); j--) Message[j] = 0; + + /* shift message codewords to the right, leave space for ECC checkwords */ + for (i = DataSize - 1; (i >= 0); j--, i--) Message[j] = Message[i]; + + /* add zeroes to pad left end Message[] for truncated codewords */ + j++; + for (i = 0; i < j; i++) Message[i] = 0; + + /* generate (EccSize) Reed-Solomon checkwords */ + for (n = j; n < (j + DataSize); n++) { + t = (Message[j + DataSize] + Message[n]) % 283; + for (i = 0; i < (EccSize - 1); i++) { + Message[j + DataSize + i] = (Message[j + DataSize + i + 1] + 283 + - GFMUL(t, gPoly[EccSize - 1 - i])) % 283; + } + Message[j + DataSize + EccSize - 1] = (283 - GFMUL(t, gPoly[0])) % 283; + } + for (i = j + DataSize; i < (j + DataSize + EccSize); i++) + Message[i] = (283 - Message[i]) % 283; +} + +/* End of Ted Williams code */ + +int ultra_find_fragment(unsigned char source[], int source_length, int position) { + int retval = -1; + int j, k, latch; + + for (j = 0; j < 27; j++) { + latch = 0; + if ((position + strlen(fragment[j])) <= source_length) { + latch = 1; + for (k = 0; k < strlen(fragment[j]); k++) { + if (source[position + k] != fragment[j][k]) { + latch = 0; + } + } + } + + if (latch) { + retval = j; + } + } + + return retval; +} + +/* Encode characters in 8-bit mode */ +float look_ahead_eightbit(unsigned char source[], int in_length, int in_locn, char current_mode, int end_char, int cw[], int* cw_len, int gs1) +{ + int codeword_count = 0; + int i; + int letters_encoded = 0; + + if (current_mode != EIGHTBIT_MODE) { + cw[codeword_count] = 282; // Unlatch + codeword_count += 1; + } + + i = in_locn; + do { + if ((source[i] == '[') && gs1) { + cw[codeword_count] = 268; // FNC1 + } else { + cw[codeword_count] = source[i]; + } + i++; + codeword_count++; + } while ((i < in_length) && (i < end_char)); + + letters_encoded = i - in_locn; + + *cw_len = codeword_count; + + if (codeword_count == 0) { + return 0.0; + } else { + return (float)letters_encoded / (float)codeword_count; + } +} + +/* Encode character in the ASCII mode/submode (including numeric compression) */ +float look_ahead_ascii(unsigned char source[], int in_length, int in_locn, char current_mode, int symbol_mode, int end_char, int cw[], int* cw_len, int gs1){ + int codeword_count = 0; + int i; + int first_digit, second_digit; + int letters_encoded = 0; + + if (current_mode == EIGHTBIT_MODE) { + cw[codeword_count] = 267; // Latch ASCII Submode + codeword_count++; + } + + if (current_mode == C43_MODE) { + cw[codeword_count] = 282; // Unlatch + codeword_count++; + if (symbol_mode == EIGHTBIT_MODE) { + cw[codeword_count] = 267; // Latch ASCII Submode + codeword_count++; + } + } + + i = in_locn; + do { + /* Check for double digits */ + if (in_locn != (in_length - 1)) { + first_digit = posn(ultra_digit, source[i]); + second_digit = posn(ultra_digit, source[i + 1]); + if ((first_digit != -1) && (second_digit != -1)) { + /* Double digit can be encoded */ + if ((first_digit >= 0) && (first_digit <= 9) && (second_digit >= 0) && (second_digit <= 9)) { + /* Double digit numerics */ + cw[codeword_count] = (10 * first_digit) + second_digit + 128; + codeword_count++; + i += 2; + } else if ((first_digit >= 0) && (first_digit <= 9) && (second_digit == 10)) { + /* Single digit followed by selected decimal point character */ + cw[codeword_count] = first_digit + 228; + codeword_count++; + i += 2; + } else if ((first_digit == 10) && (second_digit >= 0) && (second_digit <= 9)) { + /* Selected decimal point character followed by single digit */ + cw[codeword_count] = second_digit + 238; + codeword_count++; + i += 2; + } else if ((first_digit >= 0) && (first_digit <= 10) && (second_digit == 11)) { + /* Single digit or decimal point followed by field deliminator */ + cw[codeword_count] = first_digit + 248; + codeword_count++; + i += 2; + } else if ((first_digit == 11) && (second_digit >= 0) && (second_digit <= 10)) { + /* Field deliminator followed by single digit or decimal point */ + cw[codeword_count] = second_digit + 259; + codeword_count++; + i += 2; + } + } + } + + if (source[i] < 0x7F) { + if ((source[i] == '[') && gs1) { + cw[codeword_count] = 272; // FNC1 + } else { + cw[codeword_count] = source[i]; + } + codeword_count++; + i++; + } + } while ((i < in_length) && (i < end_char) && (source[i] < 0x80)); + + letters_encoded = i - in_locn; + + *cw_len = codeword_count; + + if (codeword_count == 0) { + return 0.0; + } else { + return (float)letters_encoded / (float)codeword_count; + } +} + +int get_subset(unsigned char source[], int in_length, int in_locn) { + int fragno; + int subset = 0; + + if (posn(ultra_c43_set1, source[in_locn]) != -1) { + subset = 1; + } + + if (posn(ultra_c43_set2, source[in_locn]) != -1) { + subset = 2; + } + + if (posn(ultra_c43_set3, source[in_locn]) != -1) { + subset = 3; + } + + fragno = ultra_find_fragment(source, in_length, in_locn); + if ((fragno != -1) && (fragno != 26)) { + subset = 3; + } + + return subset; +} + +/* Encode characters in the C43 compaction submode */ +float look_ahead_c43(unsigned char source[], int in_length, int in_locn, char current_mode, int end_char, int cw[], int* cw_len, int gs1){ + int codeword_count = 0; + int subcodeword_count = 0; + int i; + int subset = 0; + int fragno; + int sublocn = in_locn; + int new_subset; + int unshift_set; + int base43_value; + int letters_encoded = 0; + int pad; + int gs1_latch = 0; + +#ifndef _MSC_VER + int subcw[(in_length + 3) * 2]; +#else + int * subcw = (int *) _alloca((in_length + 3) * 2 * sizeof (int)); +#endif /* _MSC_VER */ + + subset = get_subset(source, in_length, sublocn); + + if (subset == 0) { + return 0.0; + } + + if (current_mode == EIGHTBIT_MODE) { + /* Check for permissable URL C43 macro sequences, otherwise encode directly */ + fragno = ultra_find_fragment(source, in_length, sublocn); + + if ((fragno == 2) || (fragno == 3)) { + // http://www. > http:// + // https://www. > https:// + fragno -= 2; + } + + switch(fragno) { + case 17: // mailto: + cw[codeword_count] = 276; + sublocn += strlen(fragment[fragno]); + codeword_count++; + break; + case 18: // tel: + cw[codeword_count] = 277; + sublocn += strlen(fragment[fragno]); + codeword_count++; + break; + case 26: // file: + cw[codeword_count] = 278; + sublocn += strlen(fragment[fragno]); + codeword_count++; + break; + case 0: // http:// + cw[codeword_count] = 279; + sublocn += strlen(fragment[fragno]); + codeword_count++; + break; + case 1: // https:// + cw[codeword_count] = 280; + sublocn += strlen(fragment[fragno]); + codeword_count++; + break; + case 4: // ftp:// + cw[codeword_count] = 281; + sublocn += strlen(fragment[fragno]); + codeword_count++; + break; + default: + if (subset == 1) { + cw[codeword_count] = 260; // C43 Compaction Submode C1 + codeword_count++; + } + + if ((subset == 2) || (subset == 3)) { + cw[codeword_count] = 266; // C43 Compaction Submode C2 + codeword_count++; + } + break; + } + } + + if (current_mode == ASCII_MODE) { + if (subset == 1) { + cw[codeword_count] = 278; // C43 Compaction Submode C1 + codeword_count++; + } + + if ((subset == 2) || (subset == 3)) { + cw[codeword_count] = 280; // C43 Compaction Submode C2 + codeword_count++; + } + } + unshift_set = subset; + + do { + if (subset == 1) { + subcw[subcodeword_count] = posn(ultra_c43_set1, source[sublocn]); + subcodeword_count++; + sublocn++; + } + + if (subset == 2) { + subcw[subcodeword_count] = posn(ultra_c43_set2, source[sublocn]); + subcodeword_count++; + sublocn++; + } + + if (subset == 3) { + subcw[subcodeword_count] = 41; // Shift to set 3 + subcodeword_count++; + + fragno = ultra_find_fragment(source, in_length, sublocn); + if (fragno == 26) { + fragno = -1; + } + if ((fragno >= 0) && (fragno <= 18)) { + subcw[subcodeword_count] = fragno; + subcodeword_count++; + sublocn += strlen(fragment[fragno]); + } + if ((fragno >= 18) && (fragno <= 25)) { + subcw[subcodeword_count] = fragno + 17; + subcodeword_count++; + sublocn += strlen(fragment[fragno]); + } + if (fragno == -1) { + subcw[subcodeword_count] = posn(ultra_c43_set3, source[sublocn]); + subcodeword_count++; + sublocn++; + } + subset = unshift_set; + } + + if (sublocn < in_length) { + new_subset = get_subset(source, in_length, sublocn); + + if (((subset == 1) && (new_subset == 2)) && ((source[sublocn] == '.') || (source[sublocn] == ','))) { + /* and characters available in both subsets */ + new_subset = 1; + } + + if ((new_subset != subset) && ((new_subset == 1) || (new_subset == 2))) { + subcw[subcodeword_count] = 42; // Latch to other C43 set + subcodeword_count++; + unshift_set = new_subset; + } + + subset = new_subset; + } + + /* Check for FNC1 */ + if (sublocn < (in_length - 1)) { + if ((source[sublocn + 1] == '[') && gs1) { + gs1_latch = 1; + } + } + } while ((sublocn < in_length) && (sublocn < end_char) && (subset != 0) && (gs1_latch == 0)); + + pad = 3 - (subcodeword_count % 3); + if (pad == 3) { + pad = 0; + } + + for (i = 0; i < pad; i++) { + subcw[subcodeword_count] = 42; // Latch to other C43 set used as pad + subcodeword_count++; + } + + letters_encoded = sublocn - in_locn; + + for (i = 0; i < subcodeword_count; i += 3) { + base43_value = (43 * 43 * subcw[i]) + (43 * subcw[i + 1]) + subcw[i + 2]; + cw[codeword_count] = base43_value / 282; + codeword_count++; + cw[codeword_count] = base43_value % 282; + codeword_count++; + } + + *cw_len = codeword_count; + + if (codeword_count == 0) { + return 0.0; + } else { + return (float)letters_encoded / (float)codeword_count; + } +} + +/* Produces a set of codewords which are "somewhat" optimised - this could be improved on */ +int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length, int codewords[]) { + int i; + int crop_length; + int codeword_count = 0; + int input_locn = 0; + char symbol_mode; + char current_mode; + float eightbit_score; + float ascii_score; + float c43_score; + int end_char; + int block_length; + int fragment_length; + int fragno; + int gs1 = 0; + +#ifndef _MSC_VER + unsigned char crop_source[in_length + 1]; + char mode[in_length + 1]; + int cw_fragment[in_length + 1]; +#else + unsigned char * crop_source = (unsigned char *) _alloca((in_length + 1) * sizeof (unsigned char)); + char * mode = (char *) _alloca(in_length + 1 * sizeof (char)); + int * cw_fragment = (int *) _alloca(in_length + 1 * sizeof (int)); +#endif /* _MSC_VER */ + + /* Section 7.6.2 indicates that ECI \000003 to \811799 are supported */ + /* but this seems to contradict Table 5 which only shows up to \000898 */ + if (symbol->eci > 898) { + strcpy(symbol->errtxt, "ECI value out of range"); + return ZINT_ERROR_INVALID_OPTION; + } + + // Decide start character codeword (from Table 5) + symbol_mode = ASCII_MODE; + for (i = 0; i < in_length; i++) { + if (source[i] >= 0x80) { + symbol_mode = EIGHTBIT_MODE; + } + } + + if (symbol->option_1 != ULTRA_COMPRESSION) { + // Force eight-bit mode by default as other modes are poorly documented + symbol_mode = EIGHTBIT_MODE; + } + + if (symbol->output_options & READER_INIT) { + /* Reader Initialisation mode */ + if (symbol_mode == ASCII_MODE) { + codewords[0] = 272; // 7-bit ASCII mode + codewords[1] = 271; // FNC3 + } else { + codewords[0] = 257; // 8859-1 + codewords[1] = 269; // FNC3 + } + codeword_count = 2; + } else { + /* Calculate start character codeword */ + if (symbol_mode == ASCII_MODE) { + if (symbol->input_mode == GS1_MODE) { + codewords[0] = 273; + } else { + codewords[0] = 272; + } + } else { + if ((symbol->eci >= 3) && (symbol->eci <= 18) && (symbol->eci != 14)) { + // ECI indicate use of character set within ISO/IEC 8859 + codewords[0] = 257 + (symbol->eci - 3); + if (codewords[0] > 267) { + // Avoids ECI 14 for non-existant ISO/IEC 8859-12 + codewords[0]--; + } + } else if ((symbol->eci > 18) && (symbol->eci <= 898)) { + // ECI indicates use of character set outside ISO/IEC 8859 + codewords[0] = 273 + (symbol->eci / 256); + codewords[1] = symbol->eci % 256; + codeword_count++; + } else if ((symbol->eci > 898) && (symbol->eci <= 9999)) { + // ECI beyond 898 needs to use fixed length encodable ECI invocation (section 7.6.2) + // Encode as 3 codewords + codewords[0] = 257; // ISO/IEC 8859-1 used to enter 8-bit mode + codewords[1] = 274; // Encode ECI as 3 codewords + codewords[2] = (symbol->eci / 100) + 128; + codewords[3] = (symbol->eci % 100) + 128; + codeword_count += 3; + } else if (symbol->eci >= 10000) { + // Encode as 4 codewords + codewords[0] = 257; // ISO/IEC 8859-1 used to enter 8-bit mode + codewords[1] = 275; // Encode ECI as 4 codewords + codewords[2] = (symbol->eci / 10000) + 128; + codewords[3] = ((symbol->eci % 10000) / 100) + 128; + codewords[4] = (symbol->eci % 100) + 128; + codeword_count += 4; + } else { + codewords[0] = 257; // Default is assumed to be ISO/IEC 8859-1 (ECI 3) + } + } + + if ((codewords[0] == 257) || (codewords[0] == 272)) { + fragno = ultra_find_fragment((unsigned char *)source, in_length, 0); + + // Check for http:// at start of input + if ((fragno == 0) || (fragno == 2)) { + codewords[0] = 281; + input_locn = 7; + symbol_mode = EIGHTBIT_MODE; + } + + + // Check for https:// at start of input + if ((fragno == 1) || (fragno == 3)) { + codewords[0] = 282; + input_locn = 8; + symbol_mode = EIGHTBIT_MODE; + } + } + } + + codeword_count++; + + /* Check for 06 Macro Sequence and crop accordingly */ + if (in_length >= 9 + && source[0] == '[' && source[1] == ')' && source[2] == '>' && source[3] == '\x1e' + && source[4] == '0' && source[5] == '6' && source[6] == '\x1d' + && source[in_length - 2] == '\x1e' && source[in_length - 1] == '\x04') { + + if (symbol_mode == EIGHTBIT_MODE) { + codewords[codeword_count] = 271; // 06 Macro + } else { + codewords[codeword_count] = 273; // 06 Macro + } + codeword_count++; + + for (i = 7; i < (in_length - 2); i++) { + crop_source[i - 7] = source[i]; + } + crop_length = in_length - 9; + crop_source[crop_length] = '\0'; + } else { + /* Make a cropped version of input data - removes http:// and https:// if needed */ + for (i = input_locn; i < in_length; i++) { + crop_source[i - input_locn] = source[i]; + } + crop_length = in_length - input_locn; + crop_source[crop_length] = '\0'; + } + + if ((symbol->input_mode & 0x07) == GS1_MODE) { + gs1 = 1; + } + + /* Attempt encoding in all three modes to see which offers best compaction and store results */ + if (symbol->option_1 == ULTRA_COMPRESSION) { + current_mode = symbol_mode; + input_locn = 0; + do { + end_char = input_locn + PREDICT_WINDOW; + eightbit_score = look_ahead_eightbit(crop_source, crop_length, input_locn, current_mode, end_char, cw_fragment, &fragment_length, gs1); + ascii_score = look_ahead_ascii(crop_source, crop_length, input_locn, current_mode, symbol_mode, end_char, cw_fragment, &fragment_length, gs1); + c43_score = look_ahead_c43(crop_source, crop_length, input_locn, current_mode, end_char, cw_fragment, &fragment_length, gs1); + + mode[input_locn] = 'a'; + current_mode = ASCII_MODE; + + if ((c43_score > ascii_score) && (c43_score > eightbit_score)) { + mode[input_locn] = 'c'; + current_mode = C43_MODE; + } + + if ((eightbit_score > ascii_score) && (eightbit_score > c43_score)) { + mode[input_locn] = '8'; + current_mode = EIGHTBIT_MODE; + } + input_locn++; + } while (input_locn < crop_length); + } else { + // Force eight-bit mode + for (input_locn = 0; input_locn < crop_length; input_locn++) { + mode[input_locn] = '8'; + } + } + mode[input_locn] = '\0'; + + /* Use results from test to perform actual mode switching */ + current_mode = symbol_mode; + input_locn = 0; + do { + block_length = 0; + do { + block_length++; + } while (mode[input_locn + block_length] == mode[input_locn]); + + switch(mode[input_locn]) { + case 'a': + ascii_score = look_ahead_ascii(crop_source, crop_length, input_locn, current_mode, symbol_mode, input_locn + block_length, cw_fragment, &fragment_length, gs1); + current_mode = ASCII_MODE; + break; + case 'c': + c43_score = look_ahead_c43(crop_source, crop_length, input_locn, current_mode, input_locn + block_length, cw_fragment, &fragment_length, gs1); + + /* Substitute temporary latch if possible */ + if ((current_mode == EIGHTBIT_MODE) && (cw_fragment[0] == 261) && (fragment_length >= 5) && (fragment_length <= 11)) { + /* Temporary latch to submode 1 from Table 11 */ + cw_fragment[0] = 256 + ((fragment_length - 5) / 2); + } else if ((current_mode == EIGHTBIT_MODE) && (cw_fragment[0] == 266) && (fragment_length >= 5) && (fragment_length <= 11)) { + /* Temporary latch to submode 2 from Table 11 */ + cw_fragment[0] = 262 + ((fragment_length - 5) / 2); + } else if ((current_mode == ASCII_MODE) && (cw_fragment[0] == 278) && (fragment_length >= 5) && (fragment_length <= 11)) { + /* Temporary latch to submode 1 from Table 9 */ + cw_fragment[0] = 274 + ((fragment_length - 5) / 2); + } else { + current_mode = C43_MODE; + } + break; + case '8': + eightbit_score = look_ahead_eightbit(crop_source, crop_length, input_locn, current_mode, input_locn + block_length, cw_fragment, &fragment_length, gs1); + current_mode = EIGHTBIT_MODE; + break; + } + + for (i = 0; i < fragment_length; i++) { + codewords[codeword_count + i] = cw_fragment[i]; + } + codeword_count += fragment_length; + + input_locn += block_length; + } while (input_locn < crop_length); + + return codeword_count; +} + +INTERNAL int ultracode(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length) { + int data_cw_count = 0; + int acc, qcc; + int ecc_level; + int rows, columns; + int total_cws; + int pads; + int cw_memalloc; + int codeword[283]; + int i, j, locn; + int total_height, total_width; + char tilepat[6]; + int tilex, tiley; + int dcc; + + cw_memalloc = in_length * 2; + if (cw_memalloc < 283) { + cw_memalloc = 283; + } + + if (symbol->eci > 811799) { + strcpy(symbol->errtxt, "ECI value not supported by Ultracode"); + return ZINT_ERROR_INVALID_OPTION; + } + +#ifndef _MSC_VER + int data_codewords[cw_memalloc]; +#else + int* data_codewords = (int *) _alloca(cw_memalloc * sizeof (int)); +#endif /* _MSC_VER */ + + data_cw_count = ultra_generate_codewords(symbol, source, in_length, data_codewords); + + if (symbol->debug) { + printf("Codewords returned = %d\n", data_cw_count); + } + + /* Default ECC level is EC2 */ + if ((symbol->option_1 <= 0) || (symbol->option_1 > 6)) { + ecc_level = 2; + } else { + ecc_level = symbol->option_1 - 1; + } + + /* ECC calculation from section 7.7.2 */ + if (ecc_level == 0) { + qcc = 3; + } else { + if ((data_cw_count % 25) == 0) { + qcc = (kec[ecc_level] * (data_cw_count / 25)) + 3 + 2; + } else { + qcc = (kec[ecc_level] * ((data_cw_count / 25) + 1)) + 3 + 2; + } + + } + acc = qcc - 3; + + if (symbol->debug) { + printf("ECC codewords: %d\n", qcc); + } + + /* Maximum capacity is 282 codewords */ + total_cws = data_cw_count + qcc + 5; + if (total_cws > 282) { + strcpy(symbol->errtxt, "Data too long for selected error correction capacity"); + return ZINT_ERROR_TOO_LONG; + } + + rows = 5; + for (i = 2; i >= 0; i--) { + if (total_cws < ultra_maxsize[i]) { + rows--; + } + } + + if ((total_cws % rows) == 0) { + pads = 0; + columns = total_cws / rows; + } else { + pads = rows - (total_cws % rows); + columns = (total_cws / rows) + 1; + } + + if (symbol->debug) { + printf("Calculated size is %d rows by %d columns\n", rows, columns); + } + + /* Insert MCC and ACC into data codewords */ + for (i = 282; i > 2; i--) { + data_codewords[i] = data_codewords[i - 2]; + } + data_codewords[1] = data_cw_count += 2; // MCC + data_codewords[2] = acc; // ACC + + locn = 0; + /* Calculate error correction codewords (RSEC) */ + ultra_gf283((short) data_cw_count, (short) qcc, data_codewords); + + /* Rearrange to make final codeword sequence */ + codeword[locn++] = data_codewords[282 - (data_cw_count + qcc)]; // Start Character + codeword[locn++] = data_cw_count; // MCC + for (i = 0; i < qcc; i++) { + codeword[locn++] = data_codewords[(282 - qcc) + i]; // RSEC Region + } + codeword[locn++] = data_cw_count + qcc; // TCC = C + Q - section 6.11.4 + codeword[locn++] = 283; // Separator + codeword[locn++] = acc; // ACC + for (i = 0; i < (data_cw_count - 3); i++) { + codeword[locn++] = data_codewords[(282 - ((data_cw_count - 3) + qcc)) + i]; // Data Region + } + for (i = 0; i < pads; i++) { + codeword[locn++] = 284; // Pad pattern + } + codeword[locn++] = qcc; // QCC + + if (symbol->debug) { + printf("Rearranged codewords with ECC:\n"); + for (i = 0; i < locn; i++) { + printf("%d ", codeword[i]); + } + printf("\n"); + } + + total_height = (rows * 6) + 1; + total_width = columns + 6 + (columns / 15); + + /* Build symbol */ +#ifndef _MSC_VER + char pattern[total_height * total_width]; +#else + char* pattern = (char *) _alloca(total_height * toal_width * sizeof (char)); +#endif /* _MSC_VER */ + + for (i = 0; i < (total_height * total_width); i++) { + pattern[i] = 'W'; + } + + /* Border */ + for (i = 0; i < total_width; i++) { + pattern[i] = 'K'; // Top + pattern[(total_height * total_width) - i - 1] = 'K'; // Bottom + } + for (i = 0; i < total_height; i++) { + pattern[total_width * i] = 'K'; // Left + pattern[(total_width * i) + 3] = 'K'; + pattern[(total_width * i) + (total_width - 1)] = 'K'; // Right + } + + /* Clock tracks */ + for (i = 0; i < total_height; i += 2) { + pattern[(total_width * i) + 1] = 'K'; // Primary vertical clock track + if (total_width > 20) { + pattern[(total_width * i) + 19] = 'K'; // Secondary vertical clock track + } + if (total_width > 36) { + pattern[(total_width * i) + 35] = 'K'; // Secondary vertical clock track + } + if (total_width > 52) { + pattern[(total_width * i) + 51] = 'K'; // Secondary vertical clock track + } + } + for (i = 6; i < total_height; i += 6) { + for (j = 5; j < total_width; j += 2) { + pattern[(total_width * i) + j] = 'K'; // Horizontal clock track + } + } + + /* Place tiles */ + tilepat[5] = '\0'; + tilex = 0; + tiley = 0; + for (i = 0; i < locn; i++) { + for (j = 0; j < 5; j++) { + tilepat[4 - j] = ultra_colour[(tiles[codeword[i]] >> (3 * j)) & 0x07]; + } + if ((tiley + 1) >= total_height) { + tiley = 0; + tilex++; + + if (tilex == 14) { + tilex++; + } + if (tilex == 30) { + tilex++; + } + if (tilex == 46) { + tilex++; + } + } + + for (j = 0; j < 5; j++) { + pattern[((tiley + j + 1) * total_width) + (tilex + 5)] = tilepat[j]; + } + tiley += 6; + } + + /* Add data column count */ + dcc = columns - ultra_mincols[rows - 2]; + tilex = 2; + tiley = (total_height - 11) / 2; + /* DCCU */ + for (j = 0; j < 5; j++) { + tilepat[4 - j] = ultra_colour[(dccu[dcc] >> (3 * j)) & 0x07]; + } + for (j = 0; j < 5; j++) { + pattern[((tiley + j) * total_width) + tilex] = tilepat[j]; + } + /* DCCL */ + tiley += 6; + for (j = 0; j < 5; j++) { + tilepat[4 - j] = ultra_colour[(dccl[dcc] >> (3 * j)) & 0x07]; + } + for (j = 0; j < 5; j++) { + pattern[((tiley + j) * total_width) + tilex] = tilepat[j]; + } + + if (symbol->debug) { + printf("DCC: %d\n", dcc); + + for (i = 0; i < (total_height * total_width); i++) { + printf("%c", pattern[i]); + if ((i + 1) % total_width == 0) { + printf("\n"); + } + } + } + + /* Put pattern into symbol */ + symbol->rows = total_height; + symbol->width = total_width; + + for (i = 0; i < total_height; i++) { + symbol->row_height[i] = 1; + for(j = 0; j < total_width; j++) { + symbol->encoded_data[i][j] = posn(ultra_colour, pattern[(i * total_width) + j]); + } + } + + /* Override any user selected colours */ + strcpy(symbol->fgcolour, "000000"); + strcpy(symbol->bgcolour, "ffffff"); + + return 0; } diff --git a/backend/vector.c b/backend/vector.c index 92c64dee..b9360be4 100644 --- a/backend/vector.c +++ b/backend/vector.c @@ -251,10 +251,9 @@ static void vector_reduce_rectangles(struct zint_symbol *symbol) { while (rect) { prev = rect; target = prev->next; - + while (target) { - - if ((rect->x == target->x) && (rect->width == target->width) && ((rect->y + rect->height) == target->y)) { + if ((rect->x == target->x) && (rect->width == target->width) && ((rect->y + rect->height) == target->y) && (rect->colour == target->colour)) { rect->height += target->height; prev->next = target->next; free(target); @@ -338,7 +337,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ addon_text_posn = 0.0; rect_count = 0; last_row_start = 0; - + /* * Determine if there will be any addon texts and text height */ @@ -483,20 +482,18 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ addon_text_posn = row_posn + 8.0f; addon_latch = 1; } - if (latch == 1) { - /* a bar */ + if (module_is_set(symbol, this_row, i)) { + /* a bar or colour block */ if (addon_latch == 0) { rectangle = vector_plot_create_rect((float)(i + xoffset), row_posn, (float)block_width, row_height); + if (symbol->symbology == BARCODE_ULTRA) { + rectangle->colour = module_is_set(symbol, this_row, i); + } } else { rectangle = vector_plot_create_rect((float)(i + xoffset), row_posn + 10.0f, (float)block_width, row_height - 5.0f); } - latch = 0; - vector_plot_add_rect(symbol, rectangle, &last_rectangle); rect_count++; - } else { - /* a space */ - latch = 1; } i += block_width; @@ -529,7 +526,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ for (i = 0; i < symbol->width; i++) { if (module_is_set(symbol, r, i)) { //struct zint_vector_hexagon *hexagon = vector_plot_create_hexagon(((i * 0.88) + ((r & 1) ? 1.76 : 1.32)), ((r * 0.76) + 0.76), symbol->dot_size); - struct zint_vector_hexagon *hexagon = vector_plot_create_hexagon(((i * 1.23f) + 0.615f + ((r & 1) ? 0.615f : 0.0f)) + xoffset, + struct zint_vector_hexagon *hexagon = vector_plot_create_hexagon(((i * 1.23f) + 0.615f + ((r & 1) ? 0.615f : 0.0f)) + xoffset, ((r * 1.067f) + 0.715f) + yoffset, symbol->dot_size); vector_plot_add_hexagon(symbol, hexagon, &last_hexagon); } @@ -565,7 +562,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ i++; } } - + if (upceanflag == 8) { i = 0; for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) { @@ -582,7 +579,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ i++; } } - + if (upceanflag == 12) { i = 0; for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) { @@ -603,7 +600,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ i++; } } - + if (upceanflag == 13) { i = 0; for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) { @@ -620,7 +617,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ i++; } } - + /* Add the text */ if (!hide_text) { diff --git a/backend/zint.h b/backend/zint.h index de498d48..96f65f76 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -270,6 +270,9 @@ extern "C" { // QR, Han Xin, Grid Matrix specific options (option_3) #define ZINT_FULL_MULTIBYTE 200 +// Ultracode specific option +#define ULTRA_COMPRESSION 128 + // Warning and error conditions #define ZINT_WARN_INVALID_OPTION 2 #define ZINT_WARN_USES_ECI 3 diff --git a/backend_qt/qzint.cpp b/backend_qt/qzint.cpp index 1d3fbd5c..01b0cc9f 100644 --- a/backend_qt/qzint.cpp +++ b/backend_qt/qzint.cpp @@ -1,7 +1,7 @@ /*************************************************************************** * Copyright (C) 2008 by BogDan Vatra * * bogdan@licentia.eu * - * Copyright (C) 2010-2017 Robin Stuart * + * Copyright (C) 2010-2020 Robin Stuart * * * * 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 * @@ -316,7 +316,36 @@ namespace Zint { // Plot rectangles rect = m_zintSymbol->vector->rectangles; while (rect) { - painter.fillRect(rect->x, rect->y, rect->width, rect->height, QBrush(m_fgColor)); + if (rect->colour == -1) { + painter.fillRect(rect->x, rect->y, rect->width, rect->height, QBrush(m_fgColor)); + } else { + switch(rect->colour) { + case 0: // White + painter.fillRect(rect->x, rect->y, rect->width, rect->height, QBrush(Qt::white)); + break; + case 1: // Cyan + painter.fillRect(rect->x, rect->y, rect->width, rect->height, QBrush(Qt::cyan)); + break; + case 2: // Blue + painter.fillRect(rect->x, rect->y, rect->width, rect->height, QBrush(Qt::blue)); + break; + case 3: // Magenta + painter.fillRect(rect->x, rect->y, rect->width, rect->height, QBrush(Qt::magenta)); + break; + case 4: // Red + painter.fillRect(rect->x, rect->y, rect->width, rect->height, QBrush(Qt::red)); + break; + case 5: // Yellow + painter.fillRect(rect->x, rect->y, rect->width, rect->height, QBrush(Qt::yellow)); + break; + case 6: // Green + painter.fillRect(rect->x, rect->y, rect->width, rect->height, QBrush(Qt::green)); + break; + default: + painter.fillRect(rect->x, rect->y, rect->width, rect->height, QBrush(Qt::black)); + break; + } + } rect = rect->next; } diff --git a/frontend/main.c b/frontend/main.c index 53746855..5c07782a 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -37,37 +37,38 @@ /* Print list of supported symbologies */ void types(void) { - printf( " 1: Code 11 51: Pharma One-Track 92: Aztec Code\n" - " 2: Standard 2of5 52: PZN 93: DAFT Code\n" - " 3: Interleaved 2of5 53: Pharma Two-Track 97: Micro QR Code\n" - " 4: IATA 2of5 55: PDF417 98: HIBC Code 128\n" - " 6: Data Logic 56: PDF417 Trunc 99: HIBC Code 39\n" - " 7: Industrial 2of5 57: Maxicode 102: HIBC Data Matrix\n" - " 8: Code 39 58: QR Code 104: HIBC QR Code\n" - " 9: Extended Code 39 60: Code 128-B 106: HIBC PDF417\n" - "13: EAN 63: AP Standard Customer 108: HIBC MicroPDF417\n" - "14: EAN + Check 66: AP Reply Paid 110: HIBC Codablock-F\n" - "16: GS1-128 67: AP Routing 112: HIBC Aztec Code\n" - "18: Codabar 68: AP Redirection 115: DotCode\n" - "20: Code 128 69: ISBN 116: Han Xin Code\n" - "21: Leitcode 70: RM4SCC 121: RM Mailmark\n" - "22: Identcode 71: Data Matrix 128: Aztec Runes\n" - "23: Code 16k 72: EAN-14 129: Code 32\n" - "24: Code 49 73: VIN (North America) 130: Comp EAN\n" - "25: Code 93 74: Codablock-F 131: Comp GS1-128\n" - "28: Flattermarken 75: NVE-18 132: Comp DataBar Omni\n" - "29: GS1 DataBar Omni 76: Japanese Post 133: Comp DataBar Ltd\n" - "30: GS1 DataBar Ltd 77: Korea Post 134: Comp DataBar ExpOm\n" - "31: GS1 DataBar ExpOm 79: GS1 DataBar Stack 135: Comp UPC-A\n" - "32: Telepen Alpha 80: GS1 DataBar Stack Omni 136: Comp UPC-E\n" - "34: UPC-A 81: GS1 DataBar ESO 137: Comp DataBar Stack\n" - "35: UPC-A + Check 82: Planet 138: Comp DataBar Stack Omni\n" - "37: UPC-E 84: MicroPDF 139: Comp DataBar ESO\n" - "38: UPC-E + Check 85: USPS OneCode 140: Channel Code\n" - "40: Postnet 86: UK Plessey 141: Code One\n" - "47: MSI Plessey 87: Telepen Numeric 142: Grid Matrix\n" - "49: FIM 89: ITF-14 143: UPNQR\n" - "50: Logmars 90: KIX Code 145: rMQR\n" + printf( " 1: Code 11 52: PZN 97: Micro QR Code\n" + " 2: Standard 2of5 53: Pharma Two-Track 98: HIBC Code 128\n" + " 3: Interleaved 2of5 55: PDF417 99: HIBC Code 39\n" + " 4: IATA 2of5 56: PDF417 Trunc 102: HIBC Data Matrix\n" + " 6: Data Logic 57: Maxicode 104: HIBC QR Code\n" + " 7: Industrial 2of5 58: QR Code 106: HIBC PDF417\n" + " 8: Code 39 60: Code 128-B 108: HIBC MicroPDF417\n" + " 9: Extended Code 39 63: AP Standard Customer 110: HIBC Codablock-F\n" + "13: EAN 66: AP Reply Paid 112: HIBC Aztec Code\n" + "14: EAN + Check 67: AP Routing 115: DotCode\n" + "16: GS1-128 68: AP Redirection 116: Han Xin Code\n" + "18: Codabar 69: ISBN 121: RM Mailmark\n" + "20: Code 128 70: RM4SCC 128: Aztec Runes\n" + "21: Leitcode 71: Data Matrix 129: Code 32\n" + "22: Identcode 72: EAN-14 130: Comp EAN\n" + "23: Code 16k 73: VIN (North America) 131: Comp GS1-128\n" + "24: Code 49 74: Codablock-F 132: Comp DataBar Omni\n" + "25: Code 93 75: NVE-18 133: Comp DataBar Ltd\n" + "28: Flattermarken 76: Japanese Post 134: Comp DataBar ExpOm\n" + "29: GS1 DataBar Omni 77: Korea Post 135: Comp UPC-A\n" + "30: GS1 DataBar Ltd 79: GS1 DataBar Stack 136: Comp UPC-E\n" + "31: GS1 DataBar ExpOm 80: GS1 DataBar Stack Omni 137: Comp DataBar Stack\n" + "32: Telepen Alpha 81: GS1 DataBar ESO 138: Comp DataBar Stack Omni\n" + "34: UPC-A 82: Planet 1139: Comp DataBar ESO\n" + "35: UPC-A + Check 84: MicroPDF 140: Channel Code\n" + "37: UPC-E 85: USPS OneCode 141: Code One\n" + "38: UPC-E + Check 86: UK Plessey 142: Grid Matrix\n" + "40: Postnet 87: Telepen Numeric 143: UPNQR\n" + "47: MSI Plessey 89: ITF-14 144: Ultracode\n" + "49: FIM 90: KIX Code 145: rMQR\n" + "50: Logmars 92: Aztec Code\n" + "51: Pharma One-Track 93: DAFT Code\n" ); } diff --git a/frontend_qt/mainwindow.cpp b/frontend_qt/mainwindow.cpp index c91f3509..b23226be 100644 --- a/frontend_qt/mainwindow.cpp +++ b/frontend_qt/mainwindow.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (C) 2008 by BogDan Vatra * - * Copyright (C) 2009-2019 by Robin Stuart * + * Copyright (C) 2009-2020 by Robin Stuart * * * * 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 * @@ -107,6 +107,7 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags fl) "Telepen", "Telepen Numeric", "UK Plessey", + "Ultracode", "UPNQR", "Universal Product Code (UPC-A)", "Universal Product Code (UPC-E)", diff --git a/frontend_qt/mainwindow.h b/frontend_qt/mainwindow.h index 0da976d4..f1c67601 100644 --- a/frontend_qt/mainwindow.h +++ b/frontend_qt/mainwindow.h @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (C) 2008 by BogDan Vatra * - * Copyright (C) 2009-2019 by Robin Stuart * + * Copyright (C) 2009-2020 by Robin Stuart * * * * 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 * @@ -102,6 +102,7 @@ public: TELEPEN = 32, TELEPEN_NUM = 87, PLESSEY = 86, + ULTRA = 144, UPNQR = 143, UPCA = 34, UPCE = 37,