diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 33da7a26..5719181f 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -7,7 +7,7 @@ project(zint) configure_file(zintconfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/zintconfig.h) set(zint_COMMON_SRCS common.c library.c large.c reedsol.c gs1.c eci.c general_field.c) -set(zint_ONEDIM_SRCS code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c) +set(zint_ONEDIM_SRCS bc412.c code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c) set(zint_POSTAL_SRCS postal.c auspost.c imail.c mailmark.c) set(zint_TWODIM_SRCS code16k.c codablock.c dmatrix.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c hanxin.c dotcode.c ultra.c) set(zint_OUTPUT_SRCS vector.c ps.c svg.c emf.c bmp.c pcx.c gif.c png.c tif.c raster.c output.c) diff --git a/backend/bc412.c b/backend/bc412.c new file mode 100644 index 00000000..77314846 --- /dev/null +++ b/backend/bc412.c @@ -0,0 +1,138 @@ +/* bc412.c - Handles IBM BC412 (SEMI T1-95) symbology */ + +/* + libzint - the open source barcode library + Copyright (C) 2021 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ + +/* A little information about this symbology can be found at + * https://barcodeguide.seagullscientific.com/Content/Symbologies/BC412.htm + * + * Partial specification at + * https://www.wdfxw.net/doc80487518.htm + * + * Checked against the encoder at + * https://www.barcodesoft.com/en/semi/semi-t1-95-bc-412-code */ + +#include +#include "common.h" + +static const char BROMINE[] = "0R9GLVHA8EZ4NTS1J2Q6C7DYKBUIX3FWP5M"; + +static const char BC412Table[35][8] = { + {'1','1','1','1','1','1','1','5'}, {'1','3','1','1','1','2','1','2'}, + {'1','1','1','3','1','1','1','3'}, {'1','2','1','1','1','2','1','3'}, + {'1','2','1','2','1','3','1','1'}, {'1','3','1','3','1','1','1','1'}, + {'1','2','1','1','1','3','1','2'}, {'1','1','1','3','1','2','1','2'}, + {'1','1','1','2','1','4','1','1'}, {'1','1','1','5','1','1','1','1'}, + {'1','5','1','1','1','1','1','1'}, {'1','1','1','1','1','5','1','1'}, + {'1','2','1','3','1','2','1','1'}, {'1','3','1','2','1','1','1','2'}, + {'1','3','1','1','1','2','1','2'}, {'1','1','1','1','1','2','1','4'}, + {'1','2','1','2','1','1','1','3'}, {'1','1','1','1','1','3','1','3'}, + {'1','3','1','1','1','1','1','3'}, {'1','1','1','2','1','2','1','3'}, + {'1','1','1','4','1','1','1','2'}, {'1','1','1','2','1','3','1','2'}, + {'1','1','1','4','1','2','1','1'}, {'1','4','1','2','1','1','1','1'}, + {'1','2','1','2','1','2','1','2'}, {'1','1','1','3','1','3','1','1'}, + {'1','3','1','2','1','2','1','1'}, {'1','2','1','1','1','4','1','1'}, + {'1','4','1','1','1','2','1','1'}, {'1','1','1','1','1','4','1','2'}, + {'1','2','1','1','1','1','1','4'}, {'1','4','1','1','1','1','1','2'}, + {'1','2','1','4','1','1','1','1'}, {'1','1','1','2','1','1','1','4'}, + {'1','2','1','3','1','1','1','2'} +}; + +INTERNAL int bc412(struct zint_symbol *symbol, unsigned char source[], int length) { /* IBM BC412 */ + unsigned char padded_source[19]; + int posns[35]; + int i, counter_odd = 0, counter_even = 0, check_sum = 0; + char dest[293]; /* 2 + (36 * 8) + 3 */ + char *d = dest; + int error_number = 0; + + if ((length < 7) || (length > 18)) { + strcpy(symbol->errtxt, "nan: Input wrong length (should be between 7 and 18 characters)"); + return ZINT_ERROR_TOO_LONG; + } + to_upper(source, length); + + padded_source[0] = source[0]; + padded_source[1] = '0'; + + for (i = 2; i <= length; i++) { + padded_source[i] = source[i - 1]; + } + padded_source[length + 1] = 0; + + if (!is_sane_lookup(BROMINE, 35, padded_source, length + 1, posns)) { + strcpy(symbol->errtxt, "nan: Invalid character in data"); + return ZINT_ERROR_INVALID_DATA; + } + + for (i = 0; i <= length; i++) { + if (i % 2) { + counter_even += posns[i]; + } else { + counter_odd += posns[i]; + } + } + + counter_odd %= 35; + counter_even %= 35; + + /* Check digit */ + check_sum = counter_odd + (2 * counter_even); + check_sum %= 35; + check_sum *= 17; + check_sum %= 35; + + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("BC412 check: %c\n", BROMINE[check_sum]); + } + + padded_source[1] = BROMINE[check_sum]; + posns[1] = check_sum; + + /* Start character */ + memcpy(d, "12", 2); + d += 2; + + for (i = 0; i <= length; i++, d += 8) { + memcpy(d, BC412Table[posns[i]], 8); + } + + /* Stop character */ + memcpy(d, "111", 3); + d += 3; + + expand(symbol, dest, d - dest); + ustrcpy(symbol->text, padded_source); + + /* TODO: exact dimensions / whitespace required */ + + return error_number; +} diff --git a/backend/library.c b/backend/library.c index 6c477454..e11d27b4 100644 --- a/backend/library.c +++ b/backend/library.c @@ -198,6 +198,7 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le INTERNAL int ultra(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Ultracode */ INTERNAL int rmqr(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* rMQR */ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length); /* DPD Code */ +INTERNAL int bc412(struct zint_symbol *symbol, unsigned char source[], int length); /* BC412 */ /* Output handlers */ INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */ @@ -537,7 +538,7 @@ static const void *barcode_funcs[BARCODE_LAST + 1] = { composite, composite, composite, composite, composite, /*130-134*/ composite, composite, composite, composite, composite, /*135-139*/ channel, codeone, gridmatrix, upnqr, ultra, /*140-144*/ - rmqr, + rmqr, bc412, }; static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); @@ -1707,6 +1708,7 @@ int ZBarcode_BarcodeName(int symbol_id, char name[32]) { { "BARCODE_UPNQR", BARCODE_UPNQR, 143 }, { "BARCODE_ULTRA", BARCODE_ULTRA, 144 }, { "BARCODE_RMQR", BARCODE_RMQR, 145 }, + { "BARCODE_BC412", BARCODE_BC412, 146 }, }; name[0] = '\0'; diff --git a/backend/zint.h b/backend/zint.h index eb39d747..be58674b 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -260,7 +260,8 @@ extern "C" { #define BARCODE_UPNQR 143 /* UPNQR (Univerzalnega Plačilnega Naloga QR) */ #define BARCODE_ULTRA 144 /* Ultracode */ #define BARCODE_RMQR 145 /* Rectangular Micro QR Code (rMQR) */ -#define BARCODE_LAST 145 /* Max barcode number marker, not barcode */ +#define BARCODE_BC412 146 /* IBM BC412 */ +#define BARCODE_LAST 146 /* Max barcode number marker, not barcode */ /* Output options (`symbol->output_options`) */ #define BARCODE_NO_ASCII 0x0001 /* Legacy (no-op) */ diff --git a/frontend/main.c b/frontend/main.c index 819596c6..f4fe0be2 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -94,7 +94,7 @@ static void types(void) { "70 RM4SCC Royal Mail 4SCC 143 UPNQR UPN QR Code\n" "71 DATAMATRIX Data Matrix 144 ULTRA Ultracode\n" "72 EAN14 EAN-14 145 RMQR Rectangular Micro QR\n" - "73 VIN Vehicle Information No.\n" + "73 VIN Vehicle Information No. 146 BC412 BC412\n" ); } @@ -293,6 +293,7 @@ static int get_barcode_name(const char *barcode_name) { { BARCODE_AZTEC, "azteccode" }, /* Synonym */ { BARCODE_AZRUNE, "aztecrune" }, /* Synonym */ { BARCODE_AZRUNE, "aztecrunes" }, /* Synonym */ + { BARCODE_BC412, "bc412" }, { BARCODE_C25LOGIC, "c25datalogic" }, /* Synonym */ { BARCODE_C25IATA, "c25iata" }, { BARCODE_C25IND, "c25ind" }, diff --git a/frontend_qt/mainwindow.cpp b/frontend_qt/mainwindow.cpp index bbd75c7b..2ff13f2a 100644 --- a/frontend_qt/mainwindow.cpp +++ b/frontend_qt/mainwindow.cpp @@ -72,6 +72,7 @@ static const struct bstyle_item bstyle_items[] = { { QSL("Australia Post Standard Customer"), BARCODE_AUSPOST }, { QSL("Aztec Code (ISO 24778) (and HIBC)"), BARCODE_AZTEC }, { QSL("Aztec Runes (ISO 24778)"), BARCODE_AZRUNE }, + { QSL("BC412 (SEMI TI-95)"), BARCODE_BC412 }, { QSL("Channel Code"), BARCODE_CHANNEL }, { QSL("Codabar (EN 798)"), BARCODE_CODABAR }, { QSL("Codablock-F (and HIBC)"), BARCODE_CODABLOCKF }, @@ -258,7 +259,7 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags fl) filter_bstyle->hide(); #endif - bstyle->setCurrentIndex(settings.value(QSL("studio/symbology"), 10).toInt()); + bstyle->setCurrentIndex(settings.value(QSL("studio/symbology"), 11).toInt()); load_settings(settings);