| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590 |
- /* composite.c - Handles GS1 Composite Symbols */
- /*
- libzint - the open source barcode library
- Copyright (C) 2008-2024 Robin Stuart <rstuart114@gmail.com>
- 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.
- */
- /* SPDX-License-Identifier: BSD-3-Clause */
- /* The functions "getBit", "init928" and "encode928" are copyright BSI and are
- released with permission under the following terms:
- "Copyright subsists in all BSI publications. BSI also holds the copyright, in the
- UK, of the international standardisation bodies. Except as
- permitted under the Copyright, Designs and Patents Act 1988 no extract may be
- reproduced, stored in a retrieval system or transmitted in any form or by any
- means - electronic, photocopying, recording or otherwise - without prior written
- permission from BSI.
- "This does not preclude the free use, in the course of implementing the standard,
- of necessary details such as symbols, and size, type or grade designations. If these
- details are to be used for any other purpose than implementation then the prior
- written permission of BSI must be obtained."
- The date of publication for these functions is 31 May 2006
- */
- #include <assert.h>
- #include <math.h>
- #include <stdio.h>
- #include "common.h"
- #include "pdf417.h"
- #include "gs1.h"
- #include "general_field.h"
- #include "composite.h"
- INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_mode,
- const int cc_rows);
- INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows);
- INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[],
- unsigned char local_source[], int *p_with_addon, unsigned char *zfirst_part,
- unsigned char *zsecond_part);
- INTERNAL int dbar_omnstk_set_height(struct zint_symbol *symbol, const int first_row);
- INTERNAL int dbar_omn_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows);
- INTERNAL int dbar_ltd_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows);
- INTERNAL int dbar_exp_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows);
- INTERNAL int dbar_date(const unsigned char source[], const int length, const int src_posn);
- static int cc_min(const int first, const int second) {
- if (first <= second)
- return first;
- else
- return second;
- }
- /* gets bit in bitString at bitPos */
- static int cc_getBit(const unsigned short *bitStr, const int bitPos) {
- return !!(bitStr[bitPos >> 4] & (0x8000 >> (bitPos & 15)));
- }
- /* converts bit string to base 928 values, codeWords[0] is highest order */
- static int cc_encode928(const unsigned short bitString[], unsigned short codeWords[], const int bitLng) {
- int i, j, b, cwNdx, cwLng;
- for (cwNdx = cwLng = b = 0; b < bitLng; b += 69, cwNdx += 7) {
- const int bitCnt = cc_min(bitLng - b, 69);
- int cwCnt;
- cwLng += cwCnt = bitCnt / 10 + 1;
- for (i = 0; i < cwCnt; i++)
- codeWords[cwNdx + i] = 0; /* init 0 */
- for (i = 0; i < bitCnt; i++) {
- if (cc_getBit(bitString, b + bitCnt - i - 1)) {
- for (j = 0; j < cwCnt; j++)
- codeWords[cwNdx + j] += cc_pwr928[i][j + 7 - cwCnt];
- }
- }
- for (i = cwCnt - 1; i > 0; i--) {
- /* add "carries" */
- codeWords[cwNdx + i - 1] += codeWords[cwNdx + i] / 928;
- codeWords[cwNdx + i] %= 928;
- }
- }
- return (cwLng);
- }
- /* CC-A 2D component */
- static void cc_a(struct zint_symbol *symbol, const char source[], const int cc_width) {
- int i, segment, bitlen, cwCnt, variant, rows;
- int k, offset, j, total, rsCodeWords[8] = {0};
- int LeftRAPStart, RightRAPStart, CentreRAPStart, StartCluster;
- int LeftRAP, RightRAP, CentreRAP, Cluster;
- int loop;
- unsigned short codeWords[28] = {0};
- unsigned short bitStr[13] = {0};
- char pattern[580];
- int bp = 0;
- const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
- variant = 0;
- bitlen = (int) strlen(source);
- for (segment = 0; segment < 13; segment++) {
- const int strpos = segment * 16;
- if (strpos >= bitlen) {
- break;
- }
- for (i = 0; i < 16 && strpos + i < bitlen; i++) {
- if (source[strpos + i] == '1') {
- bitStr[segment] |= (0x8000 >> i);
- }
- }
- }
- /* encode codeWords from bitStr */
- cwCnt = cc_encode928(bitStr, codeWords, bitlen);
- switch (cc_width) {
- case 2:
- switch (cwCnt) {
- case 6: variant = 0;
- break;
- case 8: variant = 1;
- break;
- case 9: variant = 2;
- break;
- case 11: variant = 3;
- break;
- case 12: variant = 4;
- break;
- case 14: variant = 5;
- break;
- case 17: variant = 6;
- break;
- }
- break;
- case 3:
- switch (cwCnt) {
- case 8: variant = 7;
- break;
- case 10: variant = 8;
- break;
- case 12: variant = 9;
- break;
- case 14: variant = 10;
- break;
- case 17: variant = 11;
- break;
- }
- break;
- case 4:
- switch (cwCnt) {
- case 8: variant = 12;
- break;
- case 11: variant = 13;
- break;
- case 14: variant = 14;
- break;
- case 17: variant = 15;
- break;
- case 20: variant = 16;
- break;
- }
- break;
- }
- rows = cc_aVariants[variant];
- k = cc_aVariants[17 + variant];
- offset = cc_aVariants[34 + variant];
- /* Reed-Solomon error correction */
- for (i = 0; i < cwCnt; i++) {
- total = (codeWords[i] + rsCodeWords[k - 1]) % 929;
- for (j = k - 1; j >= 0; j--) {
- if (j == 0) {
- rsCodeWords[j] = (929 - (total * cc_aCoeffs[offset + j]) % 929) % 929;
- } else {
- rsCodeWords[j] = (rsCodeWords[j - 1] + 929 - (total * cc_aCoeffs[offset + j]) % 929) % 929;
- }
- }
- }
- for (j = 0; j < k; j++) {
- if (rsCodeWords[j] != 0) {
- rsCodeWords[j] = 929 - rsCodeWords[j];
- }
- }
- for (i = k - 1; i >= 0; i--) {
- codeWords[cwCnt] = rsCodeWords[i];
- cwCnt++;
- }
- /* Place data into table */
- LeftRAPStart = cc_aRAPTable[variant];
- CentreRAPStart = cc_aRAPTable[variant + 17];
- RightRAPStart = cc_aRAPTable[variant + 34];
- StartCluster = cc_aRAPTable[variant + 51] / 3;
- LeftRAP = LeftRAPStart;
- CentreRAP = CentreRAPStart;
- RightRAP = RightRAPStart;
- Cluster = StartCluster; /* Cluster can be 0, 1 or 2 for Cluster(0), Cluster(3) and Cluster(6) */
- for (i = 0; i < rows; i++) {
- bp = 0;
- offset = 929 * Cluster;
- k = i * cc_width;
- /* Copy the data into codebarre */
- if (cc_width != 3) {
- bp = bin_append_posn(pdf_rap_side[LeftRAP - 1], 10, pattern, bp);
- }
- bp = bin_append_posn(pdf_bitpattern[offset + codeWords[k]], 16, pattern, bp);
- pattern[bp++] = '0';
- if (cc_width >= 2) {
- if (cc_width == 3) {
- bp = bin_append_posn(pdf_rap_centre[CentreRAP - 1], 10, pattern, bp);
- }
- bp = bin_append_posn(pdf_bitpattern[offset + codeWords[k + 1]], 16, pattern, bp);
- pattern[bp++] = '0';
- if (cc_width >= 3) {
- if (cc_width == 4) {
- bp = bin_append_posn(pdf_rap_centre[CentreRAP - 1], 10, pattern, bp);
- }
- bp = bin_append_posn(pdf_bitpattern[offset + codeWords[k + 2]], 16, pattern, bp);
- pattern[bp++] = '0';
- if (cc_width == 4) {
- bp = bin_append_posn(pdf_bitpattern[offset + codeWords[k + 3]], 16, pattern, bp);
- pattern[bp++] = '0';
- }
- }
- }
- bp = bin_append_posn(pdf_rap_side[RightRAP - 1], 10, pattern, bp);
- pattern[bp++] = '1'; /* stop */
- /* so now pattern[] holds the string of '1's and '0's. - copy this to the symbol */
- for (loop = 0; loop < bp; loop++) {
- if (pattern[loop] == '1') {
- set_module(symbol, i, loop);
- }
- }
- symbol->row_height[i] = 2;
- symbol->rows++;
- /* Set up RAPs and Cluster for next row */
- LeftRAP++;
- CentreRAP++;
- RightRAP++;
- Cluster++;
- if (LeftRAP == 53) {
- LeftRAP = 1;
- }
- if (CentreRAP == 53) {
- CentreRAP = 1;
- }
- if (RightRAP == 53) {
- RightRAP = 1;
- }
- if (Cluster == 3) {
- Cluster = 0;
- }
- }
- symbol->width = bp;
- if (debug_print) {
- printf("CC-A Columns: %d, Rows: %d, Variant: %d, CodeWords: %d\n", cc_width, symbol->rows, variant, cwCnt);
- }
- }
- /* CC-B 2D component */
- static void cc_b(struct zint_symbol *symbol, const char source[], const int cc_width) {
- const int length = (int) strlen(source) / 8;
- int i;
- unsigned char *data_string = (unsigned char *) z_alloca(length + 3);
- short chainemc[180];
- int mclength = 0;
- int k, j, p, longueur, mccorrection[50] = {0}, offset;
- int total;
- char pattern[580];
- int variant, LeftRAPStart, CentreRAPStart, RightRAPStart, StartCluster;
- int LeftRAP, CentreRAP, RightRAP, Cluster, loop;
- int columns;
- int bp = 0;
- const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
- for (i = 0; i < length; i++) {
- const int binloc = i * 8;
- data_string[i] = 0;
- for (p = 0; p < 8; p++) {
- if (source[binloc + p] == '1') {
- data_string[i] |= (0x80 >> p);
- }
- }
- }
- /* "the CC-B component shall have codeword 920 in the first symbol character position" (section 9a) */
- chainemc[mclength++] = 920;
- pdf_byteprocess(chainemc, &mclength, data_string, 0, length, 0);
- /* Now figure out which variant of the symbol to use and load values accordingly */
- variant = 0;
- if (cc_width == 2) {
- if (mclength <= 8) {
- variant = 7;
- } else if (mclength <= 13) {
- variant = 8;
- } else if (mclength <= 19) {
- variant = 9;
- } else if (mclength <= 24) {
- variant = 10;
- } else if (mclength <= 29) {
- variant = 11;
- } else if (mclength <= 33) {
- variant = 12;
- } else {
- variant = 13;
- }
- } else if (cc_width == 3) {
- if (mclength <= 6) {
- variant = 14;
- } else if (mclength <= 10) {
- variant = 15;
- } else if (mclength <= 14) {
- variant = 16;
- } else if (mclength <= 18) {
- variant = 17;
- } else if (mclength <= 24) {
- variant = 18;
- } else if (mclength <= 34) {
- variant = 19;
- } else if (mclength <= 46) {
- variant = 20;
- } else if (mclength <= 58) {
- variant = 21;
- } else if (mclength <= 70) {
- variant = 22;
- } else {
- variant = 23;
- }
- } else if (cc_width == 4) {
- if (mclength <= 8) {
- variant = 24;
- } else if (mclength <= 12) {
- variant = 25;
- } else if (mclength <= 18) {
- variant = 26;
- } else if (mclength <= 24) {
- variant = 27;
- } else if (mclength <= 30) {
- variant = 28;
- } else if (mclength <= 39) {
- variant = 29;
- } else if (mclength <= 54) {
- variant = 30;
- } else if (mclength <= 72) {
- variant = 31;
- } else if (mclength <= 90) {
- variant = 32;
- } else if (mclength <= 108) {
- variant = 33;
- } else {
- variant = 34;
- }
- }
- /* Now we have the variant we can load the data - from here on the same as MicroPDF417 code */
- variant--;
- assert(variant >= 0);
- columns = pdf_MicroVariants[variant]; /* columns */
- symbol->rows = pdf_MicroVariants[variant + 34]; /* rows */
- k = pdf_MicroVariants[variant + 68]; /* number of EC CWs */
- longueur = (columns * symbol->rows) - k; /* number of non-EC CWs */
- i = longueur - mclength; /* amount of padding required */
- offset = pdf_MicroVariants[variant + 102]; /* coefficient offset */
- /* Binary input padded to target length so no padding should be necessary */
- while (i > 0) {
- chainemc[mclength++] = 900; /* Not reached */
- i--;
- }
- /* Reed-Solomon error correction */
- longueur = mclength;
- for (i = 0; i < longueur; i++) {
- total = (chainemc[i] + mccorrection[k - 1]) % 929;
- for (j = k - 1; j >= 0; j--) {
- if (j == 0) {
- mccorrection[j] = (929 - (total * pdf_Microcoeffs[offset + j]) % 929) % 929;
- } else {
- mccorrection[j] = (mccorrection[j - 1] + 929 - (total * pdf_Microcoeffs[offset + j]) % 929) % 929;
- }
- }
- }
- for (j = 0; j < k; j++) {
- if (mccorrection[j] != 0) {
- mccorrection[j] = 929 - mccorrection[j];
- }
- }
- /* we add these codes to the string */
- for (i = k - 1; i >= 0; i--) {
- chainemc[mclength++] = mccorrection[i];
- }
- /* Now get the RAP (Row Address Pattern) start values */
- LeftRAPStart = pdf_RAPTable[variant];
- CentreRAPStart = pdf_RAPTable[variant + 34];
- RightRAPStart = pdf_RAPTable[variant + 68];
- StartCluster = pdf_RAPTable[variant + 102] / 3;
- /* That's all values loaded, get on with the encoding */
- LeftRAP = LeftRAPStart;
- CentreRAP = CentreRAPStart;
- RightRAP = RightRAPStart;
- Cluster = StartCluster;
- /* Cluster can be 0, 1 or 2 for Cluster(0), Cluster(3) and Cluster(6) */
- for (i = 0; i < symbol->rows; i++) {
- bp = 0;
- offset = 929 * Cluster;
- k = i * columns;
- /* Copy the data into codebarre */
- bp = bin_append_posn(pdf_rap_side[LeftRAP - 1], 10, pattern, bp);
- bp = bin_append_posn(pdf_bitpattern[offset + chainemc[k]], 16, pattern, bp);
- pattern[bp++] = '0';
- if (cc_width >= 2) {
- if (cc_width == 3) {
- bp = bin_append_posn(pdf_rap_centre[CentreRAP - 1], 10, pattern, bp);
- }
- bp = bin_append_posn(pdf_bitpattern[offset + chainemc[k + 1]], 16, pattern, bp);
- pattern[bp++] = '0';
- if (cc_width >= 3) {
- if (cc_width == 4) {
- bp = bin_append_posn(pdf_rap_centre[CentreRAP - 1], 10, pattern, bp);
- }
- bp = bin_append_posn(pdf_bitpattern[offset + chainemc[k + 2]], 16, pattern, bp);
- pattern[bp++] = '0';
- if (cc_width == 4) {
- bp = bin_append_posn(pdf_bitpattern[offset + chainemc[k + 3]], 16, pattern, bp);
- pattern[bp++] = '0';
- }
- }
- }
- bp = bin_append_posn(pdf_rap_side[RightRAP - 1], 10, pattern, bp);
- pattern[bp++] = '1'; /* stop */
- /* so now pattern[] holds the string of '1's and '0's. - copy this to the symbol */
- for (loop = 0; loop < bp; loop++) {
- if (pattern[loop] == '1') {
- set_module(symbol, i, loop);
- }
- }
- symbol->row_height[i] = 2;
- /* Set up RAPs and Cluster for next row */
- LeftRAP++;
- CentreRAP++;
- RightRAP++;
- Cluster++;
- if (LeftRAP == 53) {
- LeftRAP = 1;
- }
- if (CentreRAP == 53) {
- CentreRAP = 1;
- }
- if (RightRAP == 53) {
- RightRAP = 1;
- }
- if (Cluster == 3) {
- Cluster = 0;
- }
- }
- symbol->width = bp;
- if (debug_print) {
- printf("CC-B Columns: %d, Rows: %d, Variant: %d, CodeWords: %d\n",
- cc_width, symbol->rows, variant + 1, mclength);
- }
- }
- /* CC-C 2D component - byte compressed PDF417 */
- static void cc_c(struct zint_symbol *symbol, const char source[], const int cc_width, const int ecc_level) {
- const int length = (int) strlen(source) / 8;
- int i, p;
- unsigned char *data_string = (unsigned char *) z_alloca(length + 4);
- short chainemc[1000];
- int mclength = 0, k;
- int offset, longueur, loop, total, j, mccorrection[520] = {0};
- int c1, c2, c3, dummy[35];
- char pattern[580];
- int bp = 0;
- const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
- for (i = 0; i < length; i++) {
- const int binloc = i * 8;
- data_string[i] = 0;
- for (p = 0; p < 8; p++) {
- if (source[binloc + p] == '1') {
- data_string[i] |= (0x80 >> p);
- }
- }
- }
- chainemc[mclength++] = 0; /* space for length descriptor */
- chainemc[mclength++] = 920; /* CC-C identifier */
- pdf_byteprocess(chainemc, &mclength, data_string, 0, length, 0);
- chainemc[0] = mclength;
- if (debug_print) {
- printf("CC-C Codewords (%d):", mclength);
- for (i = 0; i < mclength; i++) printf(" %d", chainemc[i]);
- fputc('\n', stdout);
- }
- k = 1;
- for (i = 1; i <= (ecc_level + 1); i++) {
- k *= 2;
- }
- /* 796 - we now take care of the Reed Solomon codes */
- switch (ecc_level) {
- case 1: offset = 2; /* Not reached */
- break;
- case 2: offset = 6; /* Min ECC currently used is 2 */
- break;
- case 3: offset = 14;
- break;
- case 4: offset = 30;
- break;
- case 5: offset = 62; /* Max ECC currently used is 5 */
- break;
- case 6: offset = 126; /* Not reached */
- break;
- case 7: offset = 254; /* Not reached */
- break;
- case 8: offset = 510; /* Not reached */
- break;
- default: offset = 0; /* Not reached */
- break;
- }
- longueur = mclength;
- for (i = 0; i < longueur; i++) {
- total = (chainemc[i] + mccorrection[k - 1]) % 929;
- for (j = k - 1; j >= 0; j--) {
- if (j == 0) {
- mccorrection[j] = (929 - (total * pdf_coefrs[offset + j]) % 929) % 929;
- } else {
- mccorrection[j] = (mccorrection[j - 1] + 929 - (total * pdf_coefrs[offset + j]) % 929) % 929;
- }
- }
- }
- for (j = 0; j < k; j++) {
- if (mccorrection[j] != 0) {
- mccorrection[j] = 929 - mccorrection[j];
- }
- }
- /* we add these codes to the string */
- for (i = k - 1; i >= 0; i--) {
- chainemc[mclength++] = mccorrection[i];
- }
- /* 818 - The CW string is finished */
- symbol->rows = mclength / cc_width;
- c1 = (symbol->rows - 1) / 3;
- c2 = ecc_level * 3 + (symbol->rows - 1) % 3;
- c3 = cc_width - 1;
- /* we now encode each row */
- for (i = 0; i <= symbol->rows - 1; i++) {
- for (j = 0; j < cc_width; j++) {
- dummy[j + 1] = chainemc[i * cc_width + j];
- }
- k = (i / 3) * 30;
- switch (i % 3) {
- case 0:
- dummy[0] = k + c1;
- dummy[cc_width + 1] = k + c3;
- offset = 0; /* cluster(0) */
- break;
- case 1:
- dummy[0] = k + c2;
- dummy[cc_width + 1] = k + c1;
- offset = 929; /* cluster(3) */
- break;
- case 2:
- dummy[0] = k + c3;
- dummy[cc_width + 1] = k + c2;
- offset = 1858; /* cluster(6) */
- break;
- }
- bp = 0;
- bp = bin_append_posn(0x1FEA8, 17, pattern, bp); /* Row start */
- for (j = 0; j <= cc_width + 1; j++) {
- bp = bin_append_posn(pdf_bitpattern[offset + dummy[j]], 16, pattern, bp);
- pattern[bp++] = '0';
- }
- bp = bin_append_posn(0x3FA29, 18, pattern, bp); /* Row Stop */
- for (loop = 0; loop < bp; loop++) {
- if (pattern[loop] == '1') {
- set_module(symbol, i, loop);
- }
- }
- symbol->row_height[i] = 3;
- }
- symbol->width = bp;
- if (debug_print) {
- printf("CC-C Columns: %d, Rows: %d, CodeWords: %d, ECC Level: %d\n",
- cc_width, symbol->rows, mclength, ecc_level);
- }
- }
- static int cc_a_calc_padding(const int binary_length, const int cc_width) {
- int target_bitsize = 0;
- switch (cc_width) {
- case 2:
- if (binary_length <= 59) {
- target_bitsize = 59;
- } else if (binary_length <= 78) {
- target_bitsize = 78;
- } else if (binary_length <= 88) {
- target_bitsize = 88;
- } else if (binary_length <= 108) {
- target_bitsize = 108;
- } else if (binary_length <= 118) {
- target_bitsize = 118;
- } else if (binary_length <= 138) {
- target_bitsize = 138;
- } else if (binary_length <= 167) {
- target_bitsize = 167;
- }
- break;
- case 3:
- if (binary_length <= 78) {
- target_bitsize = 78;
- } else if (binary_length <= 98) {
- target_bitsize = 98;
- } else if (binary_length <= 118) {
- target_bitsize = 118;
- } else if (binary_length <= 138) {
- target_bitsize = 138;
- } else if (binary_length <= 167) {
- target_bitsize = 167;
- }
- break;
- case 4:
- if (binary_length <= 78) {
- target_bitsize = 78;
- } else if (binary_length <= 108) {
- target_bitsize = 108;
- } else if (binary_length <= 138) {
- target_bitsize = 138;
- } else if (binary_length <= 167) {
- target_bitsize = 167;
- } else if (binary_length <= 197) {
- target_bitsize = 197;
- }
- break;
- }
- return target_bitsize;
- }
- static int cc_b_calc_padding(const int binary_length, const int cc_width) {
- int target_bitsize = 0;
- switch (cc_width) {
- case 2:
- if (binary_length <= 56) {
- target_bitsize = 56;
- } else if (binary_length <= 104) {
- target_bitsize = 104;
- } else if (binary_length <= 160) {
- target_bitsize = 160;
- } else if (binary_length <= 208) {
- target_bitsize = 208;
- } else if (binary_length <= 256) {
- target_bitsize = 256;
- } else if (binary_length <= 296) {
- target_bitsize = 296;
- } else if (binary_length <= 336) {
- target_bitsize = 336;
- }
- break;
- case 3:
- if (binary_length <= 32) {
- target_bitsize = 32;
- } else if (binary_length <= 72) {
- target_bitsize = 72;
- } else if (binary_length <= 112) {
- target_bitsize = 112;
- } else if (binary_length <= 152) {
- target_bitsize = 152;
- } else if (binary_length <= 208) {
- target_bitsize = 208;
- } else if (binary_length <= 304) {
- target_bitsize = 304;
- } else if (binary_length <= 416) {
- target_bitsize = 416;
- } else if (binary_length <= 536) {
- target_bitsize = 536;
- } else if (binary_length <= 648) {
- target_bitsize = 648;
- } else if (binary_length <= 768) {
- target_bitsize = 768;
- }
- break;
- case 4:
- if (binary_length <= 56) {
- target_bitsize = 56;
- } else if (binary_length <= 96) {
- target_bitsize = 96;
- } else if (binary_length <= 152) {
- target_bitsize = 152;
- } else if (binary_length <= 208) {
- target_bitsize = 208;
- } else if (binary_length <= 264) {
- target_bitsize = 264;
- } else if (binary_length <= 352) {
- target_bitsize = 352;
- } else if (binary_length <= 496) {
- target_bitsize = 496;
- } else if (binary_length <= 672) {
- target_bitsize = 672;
- } else if (binary_length <= 840) {
- target_bitsize = 840;
- } else if (binary_length <= 1016) {
- target_bitsize = 1016;
- } else if (binary_length <= 1184) {
- target_bitsize = 1184;
- }
- break;
- }
- return target_bitsize;
- }
- static int cc_c_calc_padding(const int binary_length, int *p_cc_width, const int linear_width, int *p_ecc_level) {
- int target_bitsize = 0;
- int byte_length, codewords_used, ecc_level, ecc_codewords, rows;
- int codewords_total, target_codewords, target_bytesize;
- byte_length = binary_length / 8;
- if (binary_length % 8 != 0) {
- byte_length++;
- }
- codewords_used = (byte_length / 6) * 5;
- codewords_used += byte_length % 6;
- /* Recommended minimum ecc levels ISO/IEC 1543:2015 (PDF417) Annex E Table E.1,
- restricted by CC-C codeword max 900 (30 cols * 30 rows), GS1 General Specifications 19.1 5.9.2.3 */
- if (codewords_used <= 40) {
- ecc_level = 2;
- } else if (codewords_used <= 160) {
- ecc_level = 3;
- } else if (codewords_used <= 320) {
- ecc_level = 4;
- } else if (codewords_used <= 833) { /* 900 - 3 - 64 */
- ecc_level = 5;
- } else if (codewords_used <= 865) { /* 900 - 3 - 32 */
- ecc_level = 4; /* Not recommended but allow to meet advertised "up to 2361 digits" (allows max 2372) */
- } else {
- return 0;
- }
- *p_ecc_level = ecc_level;
- ecc_codewords = 1 << (ecc_level + 1);
- codewords_used += ecc_codewords;
- codewords_used += 3;
- /* Minimum possible linear width (with GS1_NO_CHECK) is 11*5 (start, FNC1, linkage, data, check) + 13 stop */
- assert(linear_width >= 68);
- /* -52 = 7 left shift (section 12.3 f) + 10 right quiet zone - 17 start + 2x17 row indicators + 18 stop */
- *p_cc_width = linear_width == 68 ? 1 : (linear_width - 52) / 17; /* Ensure > 0 */
- if (*p_cc_width > 30) {
- *p_cc_width = 30;
- }
- assert(*p_cc_width > 0);
- rows = (int) ceil((double) codewords_used / *p_cc_width);
- /* stop the symbol from becoming too high */
- while (rows > 30 && *p_cc_width < 30) {
- (*p_cc_width)++;
- rows = (int) ceil((double) codewords_used / *p_cc_width);
- }
- if (rows > 30) { /* Should never happen given `codewords_used` check above (865 / 30 ~ 28.83) */
- return 0; /* Not reached */
- }
- if (rows < 3) {
- rows = 3;
- }
- codewords_total = *p_cc_width * rows;
- target_codewords = codewords_total - ecc_codewords;
- target_codewords -= 3;
- target_bytesize = 6 * (target_codewords / 5);
- target_bytesize += target_codewords % 5;
- target_bitsize = 8 * target_bytesize;
- return target_bitsize;
- }
- /* Handles all data encodation from section 5 of ISO/IEC 24723 */
- static int cc_binary_string(struct zint_symbol *symbol, const unsigned char source[], const int length,
- char binary_string[], const int cc_mode, int *p_cc_width, int *p_ecc_level, const int linear_width) {
- int encoding_method, read_posn, alpha_pad;
- int i, j, ai_crop, ai_crop_posn, fnc1_latch;
- int ai90_mode, remainder;
- char last_digit = '\0';
- int mode;
- char *general_field = (char *) z_alloca(length + 1);
- int target_bitsize;
- int bp = 0;
- const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
- encoding_method = 1;
- read_posn = 0;
- ai_crop = 0;
- ai_crop_posn = -1;
- fnc1_latch = 0;
- alpha_pad = 0;
- *p_ecc_level = 0;
- target_bitsize = 0;
- mode = NUMERIC;
- if (length > 1 && (source[0] == '1') && ((source[1] == '0') || (source[1] == '1') || (source[1] == '7'))) {
- /* Source starts (10), (11) or (17) */
- if (source[1] == '0' || dbar_date(source, length, 2) >= 0) { /* Check date valid if (11) or (17) */
- encoding_method = 2;
- }
- } else if (length > 1 && (source[0] == '9') && (source[1] == '0')) {
- /* Source starts (90) */
- encoding_method = 3;
- }
- if (encoding_method == 1) {
- binary_string[bp++] = '0';
- if (debug_print) printf("CC-%c Encodation Method: 0\n", 'A' + (cc_mode - 1));
- } else if (encoding_method == 2) {
- /* Encoding Method field "10" - date and lot number */
- bp = bin_append_posn(2, 2, binary_string, bp); /* "10" */
- if (source[1] == '0') {
- /* No date data */
- bp = bin_append_posn(3, 2, binary_string, bp); /* "11" */
- read_posn = 2;
- } else {
- /* Production Date (11) or Expiration Date (17) */
- assert(length >= 8); /* Due to `dbar_date()` check above */
- bp = bin_append_posn(dbar_date(source, length, 2), 16, binary_string, bp);
- if (source[1] == '1') {
- /* Production Date AI 11 */
- binary_string[bp++] = '0';
- } else {
- /* Expiration Date AI 17 */
- binary_string[bp++] = '1';
- }
- read_posn = 8;
- if (read_posn + 1 < length && (source[read_posn] == '1') && (source[read_posn + 1] == '0')) {
- /* Followed by AI 10 - strip this from general field */
- read_posn += 2;
- } else if (source[read_posn]) {
- /* ISO/IEC 24723:2010 5.3.1 "If a lot number does not directly follow the date element string,
- a FNC1 is encoded following the date element string ..." */
- fnc1_latch = 1;
- } else {
- /* "... even if no more data follows the date element string" */
- /* So still need FNC1 character but can't do single FNC1 in numeric mode, so insert alphanumeric latch
- "0000" and alphanumeric FNC1 "01111" (this implementation detail taken from BWIPP
- https://github.com/bwipp/postscriptbarcode Copyright (c) 2004-2019 Terry Burton) */
- bp = bin_append_posn(15, 9, binary_string, bp); /* "000001111" */
- /* Note an alphanumeric FNC1 is also a numeric latch, so now in numeric mode */
- }
- }
- if (debug_print) {
- printf("CC-%c Encodation Method: 10, Compaction Field: %.*s\n", 'A' + (cc_mode - 1), read_posn, source);
- }
- } else if (encoding_method == 3) {
- /* Encodation Method field of "11" - AI 90 */
- unsigned char *ninety = (unsigned char *) z_alloca(length + 1);
- int ninety_len, alpha, alphanum, numeric, alpha_posn;
- /* "This encodation method may be used if an element string with an AI
- 90 occurs at the start of the data message, and if the data field
- following the two-digit AI 90 starts with an alphanumeric string which
- complies with a specific format." (para 5.3.2) */
- i = 0;
- if (length > 2) {
- do {
- ninety[i] = source[i + 2];
- i++;
- } while (i + 2 < length && source[i + 2] != '\x1D');
- }
- ninety[i] = '\0';
- ninety_len = i;
- /* Find out if the AI 90 data is alphabetic or numeric or both */
- alpha = 0;
- alphanum = 0;
- numeric = 0;
- for (i = 0; i < ninety_len; i++) {
- if (z_isupper(ninety[i])) {
- /* Character is alphabetic */
- alpha += 1;
- } else if (z_isdigit(ninety[i])) {
- /* Character is numeric */
- numeric += 1;
- } else {
- alphanum += 1;
- }
- }
- /* must start with 0, 1, 2 or 3 digits followed by an uppercase character */
- alpha_posn = -1;
- if (ninety_len && ninety[0] != '0') { /* Leading zeros are not permitted */
- for (i = 0; i < ninety_len && i < 4; i++) {
- if (z_isupper(ninety[i])) {
- alpha_posn = i;
- break;
- }
- if (!z_isdigit(ninety[i])) {
- break;
- }
- }
- }
- if (alpha_posn != -1) {
- int next_ai_posn;
- int numeric_value;
- int table3_letter;
- /* Encodation method "11" can be used */
- bp = bin_append_posn(3, 2, binary_string, bp); /* "11" */
- numeric -= alpha_posn;
- alpha--;
- /* Decide on numeric, alpha or alphanumeric mode */
- /* Alpha mode is a special mode for AI 90 */
- if (alphanum == 0 && alpha > numeric) {
- /* Alpha mode */
- bp = bin_append_posn(3, 2, binary_string, bp); /* "11" */
- ai90_mode = 2;
- } else if (alphanum == 0 && alpha == 0) {
- /* Numeric mode */
- bp = bin_append_posn(2, 2, binary_string, bp); /* "10" */
- ai90_mode = 3;
- } else {
- /* Note if first 4 are digits then it would be shorter to go into NUMERIC mode first; not
- implemented */
- /* Alphanumeric mode */
- binary_string[bp++] = '0';
- ai90_mode = 1;
- mode = ALPHANUMERIC;
- }
- next_ai_posn = 2 + ninety_len;
- if (next_ai_posn < length && source[next_ai_posn] == '\x1D') {
- /* There are more AIs afterwards */
- if (next_ai_posn + 2 < length
- && (source[next_ai_posn + 1] == '2') && (source[next_ai_posn + 2] == '1')) {
- /* AI 21 follows */
- ai_crop = 1;
- } else if (next_ai_posn + 4 < length
- && (source[next_ai_posn + 1] == '8') && (source[next_ai_posn + 2] == '0')
- && (source[next_ai_posn + 3] == '0') && (source[next_ai_posn + 4] == '4')) {
- /* AI 8004 follows */
- ai_crop = 3;
- }
- }
- switch (ai_crop) {
- case 0: binary_string[bp++] = '0';
- break;
- case 1: bp = bin_append_posn(2, 2, binary_string, bp); /* "10" */
- ai_crop_posn = next_ai_posn + 1;
- break;
- case 3: bp = bin_append_posn(3, 2, binary_string, bp); /* "11" */
- ai_crop_posn = next_ai_posn + 1;
- break;
- }
- numeric_value = alpha_posn ? to_int(ninety, alpha_posn) : 0;
- table3_letter = -1;
- if (numeric_value < 31) {
- table3_letter = posn("BDHIJKLNPQRSTVWZ", ninety[alpha_posn]);
- }
- if (table3_letter != -1) {
- /* Encoding can be done according to 5.3.2 c) 2) */
- /* five bit binary string representing value before letter */
- bp = bin_append_posn(numeric_value, 5, binary_string, bp);
- /* followed by four bit representation of letter from Table 3 */
- bp = bin_append_posn(table3_letter, 4, binary_string, bp);
- } else {
- /* Encoding is done according to 5.3.2 c) 3) */
- bp = bin_append_posn(31, 5, binary_string, bp);
- /* ten bit representation of number */
- bp = bin_append_posn(numeric_value, 10, binary_string, bp);
- /* five bit representation of ASCII character */
- bp = bin_append_posn(ninety[alpha_posn] - 65, 5, binary_string, bp);
- }
- read_posn = alpha_posn + 3; /* +2 for 90 and +1 to go beyond alpha position */
- /* Do Alpha mode encoding of the rest of the AI 90 data field here */
- if (ai90_mode == 2) {
- /* Alpha encodation (section 5.3.3) */
- do {
- if (z_isupper(source[read_posn])) {
- bp = bin_append_posn(source[read_posn] - 65, 5, binary_string, bp);
- } else if (z_isdigit(source[read_posn])) {
- bp = bin_append_posn(source[read_posn] + 4, 6, binary_string, bp);
- } else if (source[read_posn] == '\x1D') {
- bp = bin_append_posn(31, 5, binary_string, bp);
- }
- read_posn++;
- } while (source[read_posn - 1] != '\x1D' && source[read_posn - 1] != '\0');
- alpha_pad = 1; /* This is overwritten if a general field is encoded */
- }
- if (debug_print) {
- printf("CC-%c Encodation Method: 11, Compaction Field: %.*s, Binary: %.*s (%d)\n",
- 'A' + (cc_mode - 1), read_posn, source, bp, binary_string, bp);
- }
- } else {
- /* Use general field encodation instead */
- binary_string[bp++] = '0';
- read_posn = 0;
- if (debug_print) printf("CC-%c Encodation Method: 0\n", 'A' + (cc_mode - 1));
- }
- }
- /* The compressed data field has been processed if appropriate - the
- rest of the data (if any) goes into a general-purpose data compaction field */
- j = 0;
- if (fnc1_latch == 1) {
- /* Encodation method "10" has been used but it is not followed by
- AI 10, so a FNC1 character needs to be added */
- general_field[j] = '\x1D';
- j++;
- }
- for (i = read_posn; i < length; i++) {
- /* Skip "[21" or "[8004" AIs if encodation method "11" used */
- if (i == ai_crop_posn) {
- i += ai_crop;
- } else {
- general_field[j] = source[i];
- j++;
- }
- }
- general_field[j] = '\0';
- if (debug_print) {
- printf("Mode %s, General Field: %.40s%s\n",
- mode == NUMERIC ? "NUMERIC" : mode == ALPHANUMERIC ? "ALPHANUMERIC" : "ISO646",
- general_field, j > 40 ? "..." : "");
- }
- if (j != 0) { /* If general field not empty */
- alpha_pad = 0;
- if (!general_field_encode(general_field, j, &mode, &last_digit, binary_string, &bp)) {
- /* Invalid character in input data */
- return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 441, "Invalid character in input (2D component)");
- }
- }
- switch (cc_mode) {
- case 1:
- target_bitsize = cc_a_calc_padding(bp, *p_cc_width);
- break;
- case 2:
- target_bitsize = cc_b_calc_padding(bp, *p_cc_width);
- break;
- case 3:
- target_bitsize = cc_c_calc_padding(bp, p_cc_width, linear_width, p_ecc_level);
- break;
- }
- if (target_bitsize == 0) {
- return errtxt(ZINT_ERROR_TOO_LONG, symbol, 442, "Input too long (2D component)");
- }
- remainder = target_bitsize - bp;
- if (last_digit) {
- /* There is still one more numeric digit to encode */
- if ((remainder >= 4) && (remainder <= 6)) {
- /* ISO/IEC 24723:2010 5.4.1 c) 2) "If four to six bits remain, add 1 to the digit value and encode the
- result in the next four bits. ..." */
- bp = bin_append_posn(ctoi(last_digit) + 1, 4, binary_string, bp);
- if (remainder > 4) {
- /* "... The fifth and sixth bits, if present, shall be “0”s." (Covered by adding truncated
- alphanumeric latch below but do explicitly anyway) */
- bp = bin_append_posn(0, remainder - 4, binary_string, bp);
- }
- } else {
- bp = bin_append_posn((11 * ctoi(last_digit)) + 18, 7, binary_string, bp);
- /* This may push the symbol up to the next size */
- }
- }
- switch (cc_mode) {
- case 1:
- target_bitsize = cc_a_calc_padding(bp, *p_cc_width);
- break;
- case 2:
- target_bitsize = cc_b_calc_padding(bp, *p_cc_width);
- break;
- case 3:
- target_bitsize = cc_c_calc_padding(bp, p_cc_width, linear_width, p_ecc_level);
- break;
- }
- if (target_bitsize == 0) {
- return errtxt(ZINT_ERROR_TOO_LONG, symbol, 444, "Input too long (2D component)");
- }
- if (bp < target_bitsize) {
- /* Now add padding to binary string */
- if (alpha_pad == 1) {
- bp = bin_append_posn(31, 5, binary_string, bp); /* "11111" */
- /* Extra FNC1 character required after Alpha encodation (section 5.3.3) */
- }
- if (mode == NUMERIC) {
- bp = bin_append_posn(0, 4, binary_string, bp); /* "0000" */
- }
- while (bp < target_bitsize) {
- bp = bin_append_posn(4, 5, binary_string, bp); /* "00100" */
- }
- }
- binary_string[target_bitsize] = '\0';
- if (debug_print) {
- printf("ECC: %d, CC width %d\n", *p_ecc_level, *p_cc_width);
- printf("Binary: %s (%d)\n", binary_string, target_bitsize);
- }
- return 0;
- }
- /* Calculate the width of the linear part (primary) */
- static int cc_linear_dummy_run(int input_mode, unsigned char *source, const int length, const int debug,
- char *errtxt) {
- struct zint_symbol dummy = {0};
- int error_number;
- int linear_width;
- dummy.symbology = BARCODE_GS1_128_CC;
- dummy.option_1 = -1;
- dummy.input_mode = input_mode;
- dummy.debug = debug;
- error_number = gs1_128_cc(&dummy, source, length, 3 /*cc_mode*/, 0 /*cc_rows*/);
- linear_width = dummy.width;
- if (error_number >= ZINT_ERROR || (debug & ZINT_DEBUG_TEST)) {
- strcpy(errtxt, dummy.errtxt);
- }
- if (error_number >= ZINT_ERROR) {
- return 0;
- }
- return linear_width;
- }
- INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int length) {
- int error_number, cc_mode, cc_width = 0, ecc_level = 0;
- int j, i, k;
- /* Allow for 8 bits + 5-bit latch per char + 1000 bits overhead/padding */
- const unsigned int bs = 13 * length + 1000 + 1;
- char *binary_string = (char *) z_alloca(bs);
- unsigned int pri_len;
- struct zint_symbol *linear;
- int top_shift, bottom_shift;
- int linear_width = 0;
- const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
- if (debug_print) printf("Reduced length: %d\n", length);
- /* Perform sanity checks on input options first */
- error_number = 0;
- pri_len = (int) strlen(symbol->primary);
- if (pri_len == 0) {
- /* TODO: change to more appropiate ZINT_ERROR_INVALID_DATA */
- return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 445, "No primary (linear) message");
- }
- if (length > 2990) {
- return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 446,
- "2D component input too long, requires %d characters (maximum 2990)", length);
- }
- cc_mode = symbol->option_1;
- if ((cc_mode == 3) && (symbol->symbology != BARCODE_GS1_128_CC)) {
- /* CC-C can only be used with a GS1-128 linear part */
- return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 447,
- "Invalid mode (CC-C only valid with GS1-128 linear component)");
- }
- if (symbol->symbology == BARCODE_GS1_128_CC) {
- /* Do a test run of encoding the linear component to establish its width */
- linear_width = cc_linear_dummy_run(symbol->input_mode, (unsigned char *) symbol->primary, pri_len,
- symbol->debug, symbol->errtxt);
- if (linear_width == 0) {
- return errtxt_adj(ZINT_ERROR_INVALID_DATA, symbol, "%1$s%2$s", " (linear component)");
- }
- if (debug_print) {
- printf("GS1-128 linear width: %d\n", linear_width);
- }
- }
- switch (symbol->symbology) {
- /* Determine width of 2D component according to ISO/IEC 24723 Table 1 */
- case BARCODE_EANX_CC:
- if (pri_len < 20) {
- int padded_pri_len;
- int with_addon;
- unsigned char padded_pri[21];
- if (!ean_leading_zeroes(symbol, (unsigned char *) symbol->primary, padded_pri, &with_addon, NULL,
- NULL)) {
- return errtxt_adj(ZINT_ERROR_TOO_LONG, symbol, "%1$s%2$s", " (linear component)");
- }
- padded_pri_len = (int) ustrlen(padded_pri);
- if (padded_pri_len <= 7) { /* EAN-8 */
- cc_width = 3;
- } else {
- switch (padded_pri_len) {
- case 10: /* EAN-8 + 2 */
- cc_width = 3;
- break;
- case 13: /* EAN-13 CHK or EAN-8 + 5 */
- cc_width = with_addon ? 3 : 4;
- break;
- case 12: /* EAN-13 */
- case 15: /* EAN-13 + 2 */
- case 16: /* EAN-13 CHK + 2 */
- case 18: /* EAN-13 + 5 */
- case 19: /* EAN-13 CHK + 5 */
- cc_width = 4;
- break;
- }
- }
- }
- if (cc_width == 0) {
- return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 449, "Input length %d wrong (linear component)", pri_len);
- }
- break;
- case BARCODE_GS1_128_CC: cc_width = 4;
- break;
- case BARCODE_DBAR_OMN_CC: cc_width = 4;
- break;
- case BARCODE_DBAR_LTD_CC: cc_width = 3;
- break;
- case BARCODE_DBAR_EXP_CC: cc_width = 4;
- break;
- case BARCODE_UPCA_CC: cc_width = 4;
- break;
- case BARCODE_UPCE_CC: cc_width = 2;
- break;
- case BARCODE_DBAR_STK_CC: cc_width = 2;
- break;
- case BARCODE_DBAR_OMNSTK_CC: cc_width = 2;
- break;
- case BARCODE_DBAR_EXPSTK_CC: cc_width = 4;
- break;
- }
- if (cc_mode < 1 || cc_mode > 3) {
- cc_mode = 1;
- }
- if (cc_mode == 1) {
- i = cc_binary_string(symbol, source, length, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
- if (i == ZINT_ERROR_TOO_LONG) {
- symbol->errtxt[0] = '\0'; /* Unset error text */
- cc_mode = 2;
- } else if (i != 0) {
- return i;
- }
- }
- if (cc_mode == 2) {
- /* If the data didn't fit into CC-A it is recalculated for CC-B */
- i = cc_binary_string(symbol, source, length, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
- if (i == ZINT_ERROR_TOO_LONG) {
- if (symbol->symbology != BARCODE_GS1_128_CC) {
- return ZINT_ERROR_TOO_LONG;
- }
- symbol->errtxt[0] = '\0'; /* Unset error text */
- cc_mode = 3;
- } else if (i != 0) {
- return i;
- }
- }
- if (cc_mode == 3) {
- /* If the data didn't fit in CC-B (and linear part is GS1-128) it is recalculated for CC-C */
- i = cc_binary_string(symbol, source, length, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
- if (i != 0) {
- return i;
- }
- }
- switch (cc_mode) {
- /* Note that ecc_level is only relevant to CC-C */
- case 1: cc_a(symbol, binary_string, cc_width);
- break;
- case 2: cc_b(symbol, binary_string, cc_width);
- break;
- case 3: cc_c(symbol, binary_string, cc_width, ecc_level);
- break;
- }
- /* 2D component done, now calculate linear component */
- linear = ZBarcode_Create(); /* Symbol contains the 2D component and Linear contains the rest */
- linear->symbology = symbol->symbology;
- linear->input_mode = symbol->input_mode;
- linear->output_options = symbol->output_options;
- linear->show_hrt = symbol->show_hrt;
- linear->option_2 = symbol->option_2;
- linear->option_3 = symbol->option_3;
- /* If symbol->height given minimum row height will be returned, else default height */
- linear->height = symbol->height;
- linear->debug = symbol->debug;
- if (linear->symbology != BARCODE_GS1_128_CC) {
- /* Set the "component linkage" flag in the linear component */
- linear->option_1 = 2;
- }
- switch (symbol->symbology) {
- case BARCODE_EANX_CC:
- error_number = eanx_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows);
- break;
- case BARCODE_GS1_128_CC:
- /* GS1-128 needs to know which type of 2D component is used */
- error_number = gs1_128_cc(linear, (unsigned char *) symbol->primary, pri_len, cc_mode, symbol->rows);
- break;
- case BARCODE_DBAR_OMN_CC:
- error_number = dbar_omn_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows);
- break;
- case BARCODE_DBAR_LTD_CC:
- error_number = dbar_ltd_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows);
- break;
- case BARCODE_DBAR_EXP_CC:
- error_number = dbar_exp_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows);
- break;
- case BARCODE_UPCA_CC:
- error_number = eanx_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows);
- break;
- case BARCODE_UPCE_CC:
- error_number = eanx_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows);
- break;
- case BARCODE_DBAR_STK_CC:
- error_number = dbar_omn_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows);
- break;
- case BARCODE_DBAR_OMNSTK_CC:
- error_number = dbar_omn_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows);
- break;
- case BARCODE_DBAR_EXPSTK_CC:
- error_number = dbar_exp_cc(linear, (unsigned char *) symbol->primary, pri_len, symbol->rows);
- break;
- }
- if (error_number) {
- errtxtf(0, symbol, -1, "%1$s%2$s", linear->errtxt, " (linear component)");
- if (error_number >= ZINT_ERROR) {
- ZBarcode_Delete(linear);
- return error_number;
- }
- }
- /* Merge the linear component with the 2D component */
- top_shift = 0;
- bottom_shift = 0;
- switch (symbol->symbology) {
- /* Determine horizontal alignment (according to section 12.3) */
- case BARCODE_EANX_CC:
- switch (ustrlen(linear->text)) { /* Use zero-padded length */
- case 8: /* EAN-8 */
- case 11: /* EAN-8 + 2 */
- case 14: /* EAN-8 + 5 */
- if (cc_mode == 1) {
- bottom_shift = 3;
- } else {
- bottom_shift = 13;
- }
- break;
- case 13: /* EAN-13 */
- case 16: /* EAN-13 + 2 */
- case 19: /* EAN-13 + 5 */
- bottom_shift = 2;
- break;
- }
- break;
- case BARCODE_GS1_128_CC:
- if (cc_mode == 3) {
- bottom_shift = 7; /* ISO/IEC 24723:2010 12.3 f) */
- } else {
- /* ISO/IEC 24723:2010 12.3 g) "GS1-128 components linked to the right quiet zone of the CC-A or CC-B:
- the CC-A or CC-B component is aligned with the last space module of one of the rightmost symbol
- characters of the linear component. To calculate the target Code 128 symbol character position for
- alignment, number the positions from right to left (0 is the Stop character, 1 is the Check
- character, etc.), and then Position = (total number of Code 128 symbol characters – 9) div 2"
- */
- const int num_symbols = (linear_width - 2) / 11;
- const int position = (num_symbols - 9) / 2;
- /* Less 1 to align with last space module */
- int calc_shift = linear->width - position * 11 - 1 - symbol->width;
- if (position) {
- calc_shift -= 2; /* Less additional stop modules */
- }
- if (calc_shift > 0) {
- top_shift = calc_shift;
- } else if (calc_shift < 0) {
- bottom_shift = -calc_shift;
- }
- }
- break;
- case BARCODE_DBAR_OMN_CC: bottom_shift = 4;
- break;
- case BARCODE_DBAR_LTD_CC:
- if (cc_mode == 1) {
- top_shift = 1;
- } else {
- bottom_shift = 9;
- }
- break;
- case BARCODE_DBAR_EXP_CC:
- for (k = 1; !module_is_set(linear, 1, k - 1) && module_is_set(linear, 1, k); k++);
- top_shift = k;
- break;
- case BARCODE_UPCA_CC: bottom_shift = 2;
- break;
- case BARCODE_UPCE_CC: bottom_shift = 2;
- break;
- case BARCODE_DBAR_STK_CC: top_shift = 1;
- break;
- case BARCODE_DBAR_OMNSTK_CC: top_shift = 1;
- break;
- case BARCODE_DBAR_EXPSTK_CC:
- for (k = 1; !module_is_set(linear, 1, k - 1) && module_is_set(linear, 1, k); k++);
- top_shift = k;
- break;
- }
- if (debug_print) {
- printf("Top shift: %d, Bottom shift: %d\n", top_shift, bottom_shift);
- }
- if (top_shift != 0) {
- /* Move the 2D component of the symbol horizontally */
- for (i = 0; i <= symbol->rows; i++) {
- for (j = (symbol->width + top_shift); j >= top_shift; j--) {
- if (module_is_set(symbol, i, j - top_shift)) {
- set_module(symbol, i, j);
- } else {
- unset_module(symbol, i, j);
- }
- }
- for (j = 0; j < top_shift; j++) {
- unset_module(symbol, i, j);
- }
- }
- }
- /* Merge linear and 2D components into one structure */
- for (i = 0; i <= linear->rows; i++) {
- symbol->row_height[symbol->rows + i] = linear->row_height[i];
- for (j = 0; j <= linear->width; j++) {
- if (module_is_set(linear, i, j)) {
- set_module(symbol, i + symbol->rows, j + bottom_shift);
- } else {
- unset_module(symbol, i + symbol->rows, j + bottom_shift);
- }
- }
- }
- if ((linear->width + bottom_shift) > symbol->width + top_shift) {
- symbol->width = linear->width + bottom_shift;
- } else if ((symbol->width + top_shift) > linear->width + bottom_shift) {
- symbol->width += top_shift;
- }
- symbol->rows += linear->rows;
- if (symbol->output_options & COMPLIANT_HEIGHT) {
- if (symbol->symbology == BARCODE_DBAR_STK_CC) {
- /* Databar Stacked needs special treatment due to asymmetric rows */
- error_number = dbar_omnstk_set_height(symbol, symbol->rows - linear->rows + 1 /*first_row*/);
- } else if (symbol->symbology == BARCODE_DBAR_EXP_CC || symbol->symbology == BARCODE_DBAR_EXPSTK_CC) {
- /* If symbol->height given then min row height was returned, else default height */
- if (error_number == 0) { /* Avoid overwriting any `gs1_verify()` warning */
- error_number = set_height(symbol, symbol->height ? linear->height : 0.0f,
- symbol->height ? 0.0f : linear->height, 0.0f, 0 /*no_errtxt*/);
- } else {
- (void) set_height(symbol, symbol->height ? linear->height : 0.0f,
- symbol->height ? 0.0f : linear->height, 0.0f, 1 /*no_errtxt*/);
- }
- } else {
- /* If symbol->height given then min row height was returned, else default height */
- error_number = set_height(symbol, symbol->height ? linear->height : 0.0f,
- symbol->height ? 0.0f : linear->height, 0.0f, 0 /*no_errtxt*/);
- }
- } else {
- if (symbol->symbology == BARCODE_DBAR_STK_CC) {
- (void) dbar_omnstk_set_height(symbol, symbol->rows - linear->rows + 1 /*first_row*/);
- } else {
- (void) set_height(symbol, symbol->height ? linear->height : 0.0f, symbol->height ? 0.0f : linear->height,
- 0.0f, 1 /*no_errtxt*/);
- }
- }
- ustrcpy(symbol->text, linear->text);
- ZBarcode_Delete(linear);
- return error_number;
- }
- /* vim: set ts=4 sw=4 et : */
|