commit 52aa6fdb279240ad7e9e368decc79f6a6d610d7d Author: factor Date: Sun Jul 13 21:15:55 2008 +0000 Initial revision diff --git a/backend/2of5.c b/backend/2of5.c new file mode 100644 index 00000000..1b29441b --- /dev/null +++ b/backend/2of5.c @@ -0,0 +1,351 @@ +/* 2of5.c - Handles Code 2 of 5 barcodes */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include "common.h" + + +static char *C25MatrixTable[10] = {"113311", "311131", "131131", "331111", "113131", "313111", + "133111", "111331", "311311", "131311"}; + +static char *C25IndustTable[10] = {"1111313111", "3111111131", "1131111131", "3131111111", "1111311131", + "3111311111", "1131311111", "1111113131", "3111113111", "1131113111"}; + +static char *C25InterTable[10] = {"11331", "31113", "13113", "33111", "11313", "31311", "13311", "11133", + "31131", "13131"}; + + +int matrix_two_of_five(struct zint_symbol *symbol, unsigned char source[]) +{ /* Code 2 of 5 Standard (Code 2 of 5 Matrix) */ + + int i, errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 80) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* start character */ + concat (dest, "411111"); + + for(i = 0; i <= strlen(source); i++) { + lookup(NESET, C25MatrixTable, source[i], dest); + } + + /* Stop character */ + concat (dest, "41111"); + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + +int industrial_two_of_five(struct zint_symbol *symbol, unsigned char source[]) +{ /* Code 2 of 5 Industrial */ + + int i, errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 45) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid character in data"); + return errno; + } + + /* start character */ + concat (dest, "313111"); + + for(i = 0; i <= strlen(source); i++) { + lookup(NESET, C25IndustTable, source[i], dest); + } + + /* Stop character */ + concat (dest, "31113"); + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + +int iata_two_of_five(struct zint_symbol *symbol, unsigned char source[]) +{ /* Code 2 of 5 IATA */ + int i, errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 45) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* start */ + concat (dest, "1111"); + + for(i = 0; i < strlen(source); i++) { + lookup(NESET, C25IndustTable, source[i], dest); + } + + /* stop */ + concat (dest, "311"); + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + +int logic_two_of_five(struct zint_symbol *symbol, unsigned char source[]) +{ /* Code 2 of 5 Data Logic */ + + int i, errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 80) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* start character */ + concat (dest, "1111"); + + for(i = 0; i <= strlen(source); i++) { + lookup(NESET, C25MatrixTable, source[i], dest); + } + + /* Stop character */ + concat (dest, "311"); + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + +int interleaved_two_of_five(struct zint_symbol *symbol, unsigned char source[]) +{ /* Code 2 of 5 Interleaved */ + + int i, j, k, errno; + char bars[7], spaces[7], mixed[14], dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 90) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if (errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* Input must be an even number of characters for Interlaced 2 of 5 to work: + if an odd number of characters has been entered then add a leading zero */ + if ((strlen(source)%2) != 0) + { + /* there are an odd number of input characters */ + unsigned int length; + char temp[100]; + + length = strlen(source); + + strcpy(temp, source); + source[0] = '0'; + + for(i = 0; i <= length; i++) + { + source[i + 1] = temp[i]; + } + } + + /* start character */ + concat(dest, "1111"); + + for(i = 0; i < strlen(source); i+=2 ) + { + /* look up the bars and the spaces and put them in two strings */ + strcpy(bars, ""); + lookup(NESET, C25InterTable, source[i], bars); + strcpy(spaces, ""); + lookup(NESET, C25InterTable, source[i + 1], spaces); + + /* then merge (interlace) the strings together */ + k = 0; + for(j = 0; j <= 4; j++) + { + mixed[k] = bars[j]; k++; + mixed[k] = spaces[j]; k++; + } + mixed[k] = '\0'; + concat (dest, mixed); + } + + /* Stop character */ + concat (dest, "311"); + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; + +} + +int itf14(struct zint_symbol *symbol, unsigned char source[]) +{ + int i, errno, h; + unsigned int count, check_digit; + + errno = 0; + + count = 0; + h = strlen(source); + + if(h != 13) { + strcpy(symbol->errtxt, "error: input wrong length"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid character in data"); + return errno; + } + + /* Calculate the check digit - the same method used for EAN-13 */ + + for (i = h - 1; i >= 0; i--) + { + count += ctoi(source[i]); + + if (!((i%2) == 0)) + { + count += 2 * ctoi(source[i]); + } + } + check_digit = 10 - (count%10); + if (check_digit == 10) { check_digit = 0; } + source[h] = itoc(check_digit); + source[h + 1] = '\0'; + errno = interleaved_two_of_five(symbol, source); + strcpy(symbol->text, source); + return errno; +} + +int dpleit(struct zint_symbol *symbol, unsigned char source[]) +{ /* Deutshe Post Leitcode */ + int i, errno; + unsigned int h, count, check_digit; + + errno = 0; + count = 0; + h = strlen(source); + if(h != 13) { + strcpy(symbol->errtxt, "error: input wrong length"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + for (i = h - 1; i >= 0; i--) + { + count += 4 * ctoi(source[i]); + + if (!((i%2) == 0)) + { + count += 5 * ctoi(source[i]); + } + } + check_digit = 10 - (count%10); + if (check_digit == 10) { check_digit = 0; } + source[h] = itoc(check_digit); + source[h + 1] = '\0'; + errno = interleaved_two_of_five(symbol, source); + strcpy(symbol->text, source); + return errno; +} + +int dpident(struct zint_symbol *symbol, unsigned char source[]) +{ /* Deutsche Post Identcode */ + int i, errno; + unsigned int h, count, check_digit; + + count = 0; + h = strlen(source); + if(h != 11) { + strcpy(symbol->errtxt, "erro: input wrong length"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + for (i = h - 1; i >= 0; i--) + { + count += 4 * ctoi(source[i]); + + if (!((i%2) == 0)) + { + count += 5 * ctoi(source[i]); + } + } + check_digit = 10 - (count%10); + if (check_digit == 10) { check_digit = 0; } + source[h] = itoc(check_digit); + source[h + 1] = '\0'; + errno = interleaved_two_of_five(symbol, source); + strcpy(symbol->text, source); + return errno; +} diff --git a/backend/COPYING b/backend/COPYING new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/backend/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/backend/DEVELOPER b/backend/DEVELOPER new file mode 100644 index 00000000..c66e6fb4 --- /dev/null +++ b/backend/DEVELOPER @@ -0,0 +1,109 @@ +Contents +-------- + +Here is a guide to which bit of source code does what. + +2of5.c: + Matrix 2 of 5 + Industrial 2 of 5 + IATA 2 of 5 + Data Logic + Interleaved 2 of 5 + ITF-14 + Deutche Post Leitcode + Deutche Post Identcode + +auspost.c: + Australia Post Standard Customer Barcode + Australia Post Customer Barcode 2 + Australia Post Customer Barcode 3 + Australia Post Reply Paid Barcode + Australia Post Routing Barcode + Australia Post Redirect Barcode + +aztec.c: + Aztec Mesa + +code128.c: + Code 128 + Code 128 Subset B + NVE-18 + GS1-128 (UCC/EAN-128) + +code16k.c: + Code 16k + +code.c: + Code 11 + Code 39 + Pharmazentral Nummer (PZN) + Extended Code 39 (Code 39+) + Code 93 + LOGMARS + +composite.c: + CC-A Composite Symbology + CC-B Composite Symbology + CC-C Composite Symbology + +dmatrix.c: + Data Matrix (Semacode) + +imail.c: + USPS OneCode (Intelligent Mail) + +maxicode.c: + UPS Maxicode + +medical.c: + Pharma Code + Two Track Pharma Code + Codabar + +pdf417.c: + PDF417 + Truncated PDF417 + MicroPDF417 + +plessey.c: + UK Plessey Code (bidirectional) + MSI Plessey (no check) + MSI Plessey (Mod 10 check) + MSI Plessey (Mod 11 check) + MSI Plessey (Mod 10 Mod 10 check) + MSI Plessey (Mod 10 Mod 11 check) + +postal.c: + PostNet + PLANET + Facing Identification Mark (FIM) + Royal Mail 4-State Country Code (RM4SCC) + Korean Postal Authority Code (Disabled) + Flattermarken + +qr.c: + QR Code (libqrencode) + +rss.c: + GS1 DataBar (DataBar-14) (RSS-14) + GS1 DataBar Stacked (RSS-14 Stacked) + GS1 DataBar Stacked Omnidirectional (DataBar-14 Stacked Omnidirectional) + (RSS-14 Stacked Omnidirectional) + GS1 DataBar Limited (RSS Limited) + GS1 DataBar Expanded (RSS Expanded) + GS1 DataBar Expanded Stacked (RSS Expanded Stacked) + +telepen.c: + Telepen ASCII + Telepen Numeric + +upcean.c: + UPC-A + UPC-E + EAN-2 add-on + EAN-5 add-on + EAN-8 + EAN-13 + SBN (verification) + ISBN (verification) + ISBN-13 (verification) \ No newline at end of file diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 00000000..e995472c --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,51 @@ +# Linux makefile for libzint +# +# make compiles with QR Code support +# make libzint_noqr compiles without QR Code support +# make install copies to /usr/local/lib +# make uninstall removes library +# make clean cleans up a previous compilation and any object or editor files +# + +CC := gcc +INCLUDE := -I/usr/local/include +COMMON:= common.c png.c library.c ps.c large.c reedsol.c +COMMON_OBJ:= common.o png.o library.o ps.o large.o reedsol.o +ONEDIM:= code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c +ONEDIM_OBJ:= code.o code128.o 2of5.o upcean.o telepen.o medical.o plessey.o rss.o +POSTAL:= postal.c auspost.c imail.c +POSTAL_OBJ:= postal.o auspost.o imail.o +TWODIM:= code16k.c dmatrix.c dm200.c pdf417.c maxicode.c composite.c +TWODIM_OBJ:= code16k.o dmatrix.o dm200.o pdf417.o maxicode.o composite.o +LIBS:= `libpng12-config --I_opts --L_opts --ldflags` -lz -lm + +libzint: code.c code128.c 2of5.c upcean.c medical.c telepen.c plessey.c postal.c auspost.c imail.c code16k.c dmatrix.c dm200.c reedsol.c pdf417.c maxicode.c rss.c common.c png.c library.c ps.c qr.c large.c composite.c + $(CC) -fPIC -g -c $(ONEDIM) + $(CC) -fPIC -g -c $(POSTAL) + $(CC) -fPIC -g -c $(TWODIM) qr.c + $(CC) -fPIC -g -c $(COMMON) + $(CC) -g -shared -Wl,-soname,libzint.so -o libzint.so.1.6.0 $(INCLUDE) $(COMMON_OBJ) $(ONEDIM_OBJ) $(TWODIM_OBJ) qr.o $(POSTAL_OBJ) $(LIBS) -lqrencode + +libzint_noqr: code.c code128.c 2of5.c upcean.c medical.c telepen.c plessey.c postal.c auspost.c imail.c code16k.c dmatrix.c dm200.c reedsol.c pdf417.c maxicode.c rss.c common.c png.c library.c ps.c no_qr.c large.c composite.c + $(CC) -fPIC -g -c $(ONEDIM) + $(CC) -fPIC -g -c $(POSTAL) + $(CC) -fPIC -g -c $(TWODIM) no_qr.c + $(CC) -fPIC -g -c $(COMMON) + $(CC) -g -shared -Wl,-soname,libzint.so -o libzint.so.1.6.0 $(INCLUDE) $(COMMON_OBJ) $(ONEDIM_OBJ) $(TWODIM_OBJ) no_qr.o $(POSTAL_OBJ) $(LIBS) + + +.PHONY: install uninstall clean dist + +install: + ldconfig -n $(PWD) + mv libzint.* /usr/local/lib + cp zint.h /usr/local/include + +uninstall: + rm /usr/local/lib/libzint.* + rm /usr/local/include/zint.h + +clean: + rm -f libzint.* *.o *.a *~ + + diff --git a/backend/auspost.c b/backend/auspost.c new file mode 100644 index 00000000..8bded24f --- /dev/null +++ b/backend/auspost.c @@ -0,0 +1,240 @@ +/* auspost.c - Handles Australia Post 4-State Barcode */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#define GDSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" + +static char *AusNTable[10] = {"00", "01", "02", "10", "11", "12", "20", "21", "22", "30"}; + +static char *AusCTable[64] = {"222", "300", "301", "302", "310", "311", "312", "320", "321", "322", + "000", "001", "002", "010", "011", "012", "020", "021", "022", "100", "101", "102", "110", + "111", "112", "120", "121", "122", "200", "201", "202", "210", "211", "212", "220", "221", + "023", "030", "031", "032", "033", "103", "113", "123", "130", "131", "132", "133", "203", + "213", "223", "230", "231", "232", "233", "303", "313", "323", "330", "331", "332", "333", + "003", "013"}; + +static char *AusBarTable[64] = {"000", "001", "002", "003", "010", "011", "012", "013", "020", "021", + "022", "023", "030", "031", "032", "033", "100", "101", "102", "103", "110", "111", "112", + "113", "120", "121", "122", "123", "130", "131", "132", "133", "200", "201", "202", "203", + "210", "211", "212", "213", "220", "221", "222", "223", "230", "231", "232", "233", "300", + "301", "302", "303", "310", "311", "312", "313", "320", "321", "322", "323", "330", "331", + "332", "333"}; + +#include +#include +#include +#include "common.h" +#include "reedsol.h" + +void rs_error(char data_pattern[]) +{ + /* Adds Reed-Solomon error correction to auspost */ + + int reader, triple_writer; + char triple[31], inv_triple[31]; + char result[5]; + + triple_writer = 0; + + for(reader = 2; reader < strlen(data_pattern); reader+= 3) + { + triple[triple_writer] = 0; + switch(data_pattern[reader]) + { + case '1': triple[triple_writer] += 16; break; + case '2': triple[triple_writer] += 32; break; + case '3': triple[triple_writer] += 48; break; + } + switch(data_pattern[reader + 1]) + { + case '1': triple[triple_writer] += 4; break; + case '2': triple[triple_writer] += 8; break; + case '3': triple[triple_writer] += 12; break; + } + switch(data_pattern[reader + 2]) + { + case '1': triple[triple_writer] += 1; break; + case '2': triple[triple_writer] += 2; break; + case '3': triple[triple_writer] += 3; break; + } + triple_writer++; + + } + + for(reader = 0; reader < triple_writer; reader++) + { + inv_triple[reader] = triple[(triple_writer - 1) - reader]; + } + + rs_init_gf(0x43); + rs_init_code(4, 1); + rs_encode(triple_writer, inv_triple, result); + + for(reader = 4; reader > 0; reader--) + { + concat(data_pattern, AusBarTable[result[reader - 1]]); + } +} + +int australia_post(struct zint_symbol *symbol, unsigned char source[]) +{ + /* Handles Australia Posts's 4 State Codes */ + /* Customer Standard Barcode, Barcode 2 or Barcode 3 system determined automatically + (i.e. the FCC doesn't need to be specified by the user) dependent + on the length of the input string */ + + /* The contents of data_pattern conform to the following standard: + 0 = Tracker, Ascender and Descender + 1 = Tracker and Ascender + 2 = Tracker and Descender + 3 = Tracker only */ + + char data_pattern[200]; + char fcc[3], dpid[10]; + unsigned int loopey, reader; + int writer; + strcpy (data_pattern, ""); + int errno; + + errno = 0; + + /* Do all of the length checking first to avoid stack smashing */ + if(symbol->symbology == BARCODE_AUSPOST) { + /* Format control code (FCC) */ + switch(strlen(source)) + { + case 8: strcpy(fcc, "11"); break; + case 13: strcpy(fcc, "59"); break; + case 16: strcpy(fcc, "59"); errno = is_sane(NESET, source); break; + case 18: strcpy(fcc, "62"); break; + case 23: strcpy(fcc, "62"); errno = is_sane(NESET, source); break; + default: strcpy(symbol->errtxt, "error: auspost input is wrong length"); + return ERROR_TOO_LONG; + break; + } + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + } else { + if(strlen(source) != 8) { + strcpy(symbol->errtxt, "error: auspost input is wrong length"); + return ERROR_TOO_LONG; + } + switch(symbol->symbology) { + case BARCODE_AUSREPLY: strcpy(fcc, "45"); break; + case BARCODE_AUSROUTE: strcpy(fcc, "87"); break; + case BARCODE_AUSREDIRECT: strcpy(fcc, "92"); break; + } + } + + + errno = is_sane(GDSET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* Verifiy that the first 8 characters are numbers */ + for(loopey = 0; loopey < 8; loopey++) { + dpid[loopey] = source[loopey]; + } + dpid[8] = '\0'; + errno = is_sane(NESET, dpid); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in DPID"); + return errno; + } + + /* Start character */ + concat(data_pattern, "13"); + + /* Encode the FCC */ + for(reader = 0; reader < 2; reader++) + { + lookup(NESET, AusNTable, fcc[reader], data_pattern); + } + + /* printf("AUSPOST FCC: %s ", fcc); */ + + /* Delivery Point Identifier (DPID) */ + for(reader = 0; reader < 8; reader++) + { + lookup(NESET, AusNTable, dpid[reader], data_pattern); + } + + /* Customer Information */ + if(strlen(source) > 8) + { + if((strlen(source) == 13) || (strlen(source) == 18)) { + for(reader = 8; reader < strlen(source); reader++) { + lookup(GDSET, AusCTable, source[reader], data_pattern); + } + } + if((strlen(source) == 16) || (strlen(source) == 23)) { + for(reader = 8; reader < strlen(source); reader++) { + lookup(NESET, AusNTable, source[reader], data_pattern); + } + } + } + + /* Filler bar */ + if(strlen(data_pattern) == 22) { + concat(data_pattern, "3"); + } + if(strlen(data_pattern) == 37) { + concat(data_pattern, "3"); + } + if(strlen(data_pattern) == 52) { + concat(data_pattern, "3"); + } + + /* Reed Solomon error correction */ + rs_error(data_pattern); + + /* Stop character */ + concat(data_pattern, "13"); + + /* Turn the symbol into a bar pattern ready for plotting */ + writer = 0; + for(loopey = 0; loopey < strlen(data_pattern); loopey++) + { + if((data_pattern[loopey] == '1') || (data_pattern[loopey] == '0')) + { + symbol->encoded_data[0][writer] = '1'; + } + symbol->encoded_data[1][writer] = '1'; + if((data_pattern[loopey] == '2') || (data_pattern[loopey] == '0')) + { + symbol->encoded_data[2][writer] = '1'; + } + writer += 2; + } + + symbol->row_height[0] = 4; + symbol->row_height[1] = 2; + symbol->row_height[2] = 4; + + symbol->rows = 3; + symbol->width = writer - 1; + + return errno; +} + diff --git a/backend/code.c b/backend/code.c new file mode 100644 index 00000000..3b415f5c --- /dev/null +++ b/backend/code.c @@ -0,0 +1,435 @@ +/* code.c - Handles Code 11, 39, 39+ and 93 */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* In version 0.5 this file was 1,553 lines long! */ + +#include +#include +#include +#include "common.h" + + +#define NASET "0123456789-" +static char *C11Table[11] = {"111121", "211121", "121121", "221111", "112121", "212111", "122111", + "111221", "211211", "211111", "112111"}; + + +/* Code 39 tables checked against ISO/IEC 16388:2007 */ + +#define TCSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd" +/* Incorporates Table A1 */ + +static char *C39Table[43] = { "1112212111", "2112111121", "1122111121", "2122111111", "1112211121", + "2112211111", "1122211111", "1112112121", "2112112111", "1122112111", "2111121121", + "1121121121", "2121121111", "1111221121", "2111221111", "1121221111", "1111122121", + "2111122111", "1121122111", "1111222111", "2111111221", "1121111221", "2121111211", + "1111211221", "2111211211", "1121211211", "1111112221", "2111112211", "1121112211", + "1111212211", "2211111121", "1221111121", "2221111111", "1211211121", "2211211111", + "1221211111", "1211112121", "2211112111", "1221112111", "1212121111", "1212111211", + "1211121211", "1112121211"}; +/* Code 39 character assignments (Table 1) */ + +static char *EC39Ctrl[128] = {"%U", "$A", "$B", "$C", "$D", "$E", "$F", "$G", "$H", "$I", "$J", "$K", + "$L", "$M", "$N", "$O", "$P", "$Q", "$R", "$S", "$T", "$U", "$V", "$W", "$X", "$Y", "$Z", + "%A", "%B", "%C", "%D", "%E", " ", "/A", "/B", "/C", "/D", "/E", "/F", "/G", "/H", "/I", "/J", + "/K", "/L", "-", ".", "/O", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "/Z", "%F", + "%G", "%H", "%I", "%J", "%V", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", + "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "%K", "%L", "%M", "%N", "%O", + "%W", "+A", "+B", "+C", "+D", "+E", "+F", "+G", "+H", "+I", "+J", "+K", "+L", "+M", "+N", "+O", + "+P", "+Q", "+R", "+S", "+T", "+U", "+V", "+W", "+X", "+Y", "+Z", "%P", "%Q", "%R", "%S", "%T"}; +/* Encoding the full ASCII character set in Code 39 (Table A2) */ + +static char *C93Ctrl[128] = {"bU", "aA", "aB", "aC", "aD", "aE", "aF", "aG", "aH", "aI", "aJ", "aK", + "aL", "aM", "aN", "aO", "aP", "aQ", "aR", "aS", "aT", "aU", "aV", "aW", "aX", "aY", "aZ", + "bA", "bB", "bC", "bD", "bE", " ", "cA", "cB", "cC", "cD", "cE", "cF", "cG", "cH", "cI", "cJ", + "cK", "cL", "cM", "cN", "cO", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "cZ", "bF", + "bG", "bH", "bI", "bJ", "bV", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", + "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bK", "bL", "bM", "bN", "bO", + "bW", "dA", "dB", "dC", "dD", "dE", "dF", "dG", "dH", "dI", "dJ", "dK", "dL", "dM", "dN", "dO", + "dP", "dQ", "dR", "dS", "dT", "dU", "dV", "dW", "dX", "dY", "dZ", "bP", "bQ", "bR", "bS", "bT"}; + +static char *C93Table[47] = {"131112", "111213", "111312", "111411", "121113", "121212", "121311", + "111114", "131211", "141111", "211113", "211212", "211311", "221112", "221211", "231111", + "112113", "112212", "112311", "122112", "132111", "111123", "111222", "111321", "121122", + "131121", "212112", "212211", "211122", "211221", "221121", "222111", "112122", "112221", + "122121", "123111", "121131", "311112", "311211", "321111", "112131", "113121", "211131", + "121221", "312111", "311121", "122211"}; + +/* *********************** CODE 11 ******************** */ + +int code_11(struct zint_symbol *symbol, unsigned char source[]) +{ /* Code 11 */ + + unsigned int i; + int h, c_digit, c_weight, c_count, k_digit, k_weight, k_count; + int weight[1000], errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 80) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NASET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + c_weight = 1; + c_count = 0; + k_weight = 1; + k_count = 0; + + /* start character */ + concat (dest, "112211"); + + /* Draw main body of barcode */ + for(i = 0; i < strlen(source); i++) { + lookup(NASET, C11Table, source[i], dest); + weight[i] = ctoi(source[i]); + } + + /* Calculate C checksum */ + for(h = (strlen(source) - 1); h >= 0; h--) { + c_count += (c_weight * weight[h]); + c_weight++; + + if(c_weight > 10) { + c_weight = 1; + } + } + c_digit = c_count%11; + + /* Draw C checksum */ + lookup(NASET, C11Table, itoc(c_digit), dest); + weight[strlen(source)] = c_digit; + + /* Calculate K checksum */ + for(h = strlen(source); h >= 0; h--) { + k_count += (k_weight * weight[h]); + k_weight++; + + if(k_weight > 9) { + k_weight = 1; + } + } + k_digit = k_count%11; + + /* Draw K checksum */ + lookup(NASET, C11Table, itoc(k_digit), dest); + + /* Stop character */ + concat (dest, "11221"); + + h = strlen(source); + source[h] = itoc(c_digit); + source[h + 1] = itoc(k_digit); + source[h + 2] = '\0'; + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + +int c39(struct zint_symbol *symbol, unsigned char source[]) +{ /* Code 39 */ + unsigned int i; + unsigned int counter; + char check_digit; + int h, errno; + char dest[1000]; + + errno = 0; + counter = 0; + strcpy(dest, ""); + + to_upper(source); + if(strlen(source) > 45) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(TCSET , source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* Start character */ + concat(dest, "1211212111"); + + for(i = 0; i < strlen(source); i++) { + lookup(TCSET, C39Table, source[i], dest); + counter += posn(TCSET, source[i]); + } + + if(((symbol->symbology == BARCODE_LOGMARS) || (symbol->symbology == BARCODE_CODE39_43)) || (symbol->symbology == BARCODE_EXCODE39_43)) { + + counter = counter % 43; + if(counter < 10) { + check_digit = itoc(counter); + } else { + if(counter < 36) { + check_digit = (counter - 10) + 'A'; + } else { + switch(counter) { + case 36: check_digit = '-'; break; + case 37: check_digit = '.'; break; + case 38: check_digit = ' '; break; + case 39: check_digit = '$'; break; + case 40: check_digit = '/'; break; + case 41: check_digit = '+'; break; + case 42: check_digit = 37; break; + } + } + } + lookup(TCSET, C39Table, check_digit, dest); + + /* Display a space check digit as _, otherwise it looks like an error */ + if(check_digit == ' ') { + check_digit = '_'; + } + + h = strlen(source); + source[h] = check_digit; + source[h + 1] = '\0'; + } + + /* Stop character */ + concat (dest, "121121211"); + + if(symbol->symbology == BARCODE_LOGMARS) { + /* LOGMARS uses wider 'wide' bars than normal Code 39 */ + for(i = 0; i < strlen(dest); i++) { + if(dest[i] == '2') { + dest[i] = '3'; + } + } + } + + expand(symbol, dest); + + if((symbol->symbology == BARCODE_CODE39) || (symbol->symbology == BARCODE_CODE39_43)) { + strcpy(symbol->text, "*"); + concat(symbol->text, source); + concat(symbol->text, "*"); + } else { + strcpy(symbol->text, source); + } + return errno; +} + +int pharmazentral(struct zint_symbol *symbol, unsigned char source[]) +{ /* Pharmazentral Nummer (PZN) */ + + int i, errno; + unsigned int h, count, check_digit; + + errno = 0; + + count = 0; + h = strlen(source); + if(h != 6) { + strcpy(symbol->errtxt, "error: input wrong length"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + for (i = 0; i < h; i++) + { + count += (i + 2) * ctoi(source[i]); + } + + for(i = h + 1; i >= 1; i--) + { + source[i] = source[i - 1]; + } + source[0] = '-'; + + check_digit = count%11; + if (check_digit == 11) { check_digit = 0; } + source[h + 1] = itoc(check_digit); + source[h + 2] = '\0'; + errno = c39(symbol, source); + strcpy(symbol->text, source); + return errno; +} + + +/* ************** EXTENDED CODE 39 *************** */ + +int ec39(struct zint_symbol *symbol, unsigned char source[]) +{ /* Extended Code 39 - ISO/IEC 16388:2007 Annex A */ + + char buffer[100]; + unsigned int i; + strcpy(buffer, ""); + int ascii_value; + int errno; + + errno = 0; + + if(strlen(source) > 45) { + /* only stops strings which are far too long - actual length of the barcode + depends on the type of data being encoded - if it's too long it's picked up + by c39() */ + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + + for(i = 0; i < strlen(source); i++) { + if(source[i] > 127) { + /* Cannot encode extended ASCII */ + strcpy(symbol->errtxt, "error: invalid characters in input data"); + return ERROR_INVALID_DATA; + } + } + + /* Creates a buffer string and places control characters into it */ + for(i = 0; i < strlen(source); i++) { + ascii_value = source[i]; + concat(buffer, EC39Ctrl[ascii_value]); + } + + /* Then sends the buffer to the C39 function */ + errno = c39(symbol, buffer); + + strcpy(symbol->text, source); + return errno; +} + +/* ******************** CODE 93 ******************* */ + +int c93(struct zint_symbol *symbol, unsigned char source[]) +{ /* Code 93 is an advancement on Code 39 and the definition is a lot tighter */ + + /* TCSET includes the extra characters a, b, c and d to represent Code 93 specific + shift characters 1, 2, 3 and 4 respectively. These characters are never used by + c39() and ec39() */ + + unsigned int i; + int h, weight, c, k, values[100], errno; + char buffer[100], temp[2]; + char set_copy[] = TCSET; + strcpy(buffer, ""); + int ascii_value; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 45) { + /* This stops rediculously long input - the actual length of the barcode + depends on the type of data */ + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + for(i = 0; i < strlen(source); i++) { + if(source[i] > 127) { + /* Cannot encode extended ASCII */ + strcpy(symbol->errtxt, "error: invalid characters in input data"); + return ERROR_INVALID_DATA; + } + } + + /* Start character */ + concat(dest, "111141"); + + /* Message Content */ + for(i = 0; i < strlen(source); i++) { + ascii_value = source[i]; + concat(buffer, C93Ctrl[ascii_value]); + } + + /* Now we can check the true length of the barcode */ + if(strlen(buffer) > 45) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + for(i = 0; i < strlen(buffer); i++) { + values[i] = posn(TCSET, buffer[i]); + } + + /* Putting the data into dest[] is not done until after check digits are calculated */ + + /* Check digit C */ + + c = 0; + weight = 1; + for(h = strlen(buffer) - 1; h >= 0; h--) + { + c += values[h] * weight; + weight ++; + if(weight == 21) + { + weight = 1; + } + } + c = c % 47; + + /* Because concat() requires a string as its second argument the check digit is converted + to a character which is then put in temp[] before being added to buffer[] - its + a bit long winded but avoids putting yet another function into common.c */ + + values[strlen(buffer)] = c; + temp[0] = set_copy[c]; + temp[1] = '\0'; + concat(buffer, temp); + + /* Check digit K */ + k = 0; + weight = 1; + for(h = strlen(buffer) - 1; h >= 0; h--) + { + k += values[h] * weight; + weight ++; + if(weight == 16) + { + weight = 1; + } + } + k = k % 47; + temp[0] = set_copy[k]; + temp[1] = '\0'; + concat(buffer, temp); + + for(i = 0; i < strlen(buffer); i++) { + lookup(TCSET, C93Table, buffer[i], dest); + } + + /* Stop character */ + concat(dest, "1111411"); + + h = strlen(source); + source[h] = set_copy[c]; + source[h + 1] = set_copy[k]; + source[h + 2] = '\0'; + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} diff --git a/backend/code128.c b/backend/code128.c new file mode 100644 index 00000000..b947e011 --- /dev/null +++ b/backend/code128.c @@ -0,0 +1,846 @@ +/* code128.c - Handles Code 128 and derivatives */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include "common.h" + +#define TRUE 1 +#define FALSE 0 +#define SHIFTA 90 +#define LATCHA 91 +#define SHIFTB 92 +#define LATCHB 93 +#define SHIFTC 94 +#define LATCHC 95 +#define AORB 96 +#define ABORC 97 + +int list[2][170]; + +/* Code 128 tables checked against ISO/IEC 15417:2007 */ + +static char *C128Table[107] = {"212222", "222122", "222221", "121223", "121322", "131222", "122213", + "122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222", + "123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222", + "321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323", + "131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133", + "112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113", + "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111", + "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214", + "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", + "134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", + "421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311", + "411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232", + "2331112"}; +/* Code 128 character encodation - Table 1 */ + +int parunmodd(unsigned char llyth) +{ + int modd; + modd = 0; + + if(llyth <= 31) { modd = SHIFTA; } + if((llyth >= 32) && (llyth <= 95)) { modd = AORB; } + if((llyth >= 48) && (llyth <= 57)) { modd = ABORC; } + if((llyth >= 96) && (llyth <= 127)) { modd = SHIFTB; } + if((llyth >= 128) && (llyth <= 159)) { modd = SHIFTA; } + if((llyth >= 160) && (llyth <= 223)) { modd = AORB; } + if(llyth >= 224) { modd = SHIFTB; } + + return modd; +} + +void grwp(int *indexliste) +{ + int i, j; + + /* bring together same type blocks */ + if(*(indexliste) > 1) { + i = 1; + while(i < *(indexliste)) { + if(list[1][i - 1] == list[1][i]) { + /* bring together */ + list[0][i - 1] = list[0][i - 1] + list[0][i]; + j = i + 1; + + /* decreace the list */ + while(j < *(indexliste)) { + list[0][j - 1] = list[0][j]; + list[1][j - 1] = list[1][j]; + j++; + } + *(indexliste) = *(indexliste) - 1; + i--; + } + i++; + } + } +} + +void dxsmooth(int *indexliste) +{ /* Implements rules from ISO 15417 Annex E */ + int i, this, last, next, length; + + for(i = 0; i < *(indexliste); i++) { + this = list[1][i]; + length = list[0][i]; + if(i != 0) { last = list[1][i - 1]; } else { last = FALSE; } + if(i != *(indexliste) - 1) { next = list[1][i + 1]; } else { next = FALSE; } + + if(i == 0) { /* first block */ + if((*(indexliste) == 1) && ((length == 2) && (this == ABORC))) { /* Rule 1a */ list[1][i] = LATCHC; } + if(this == ABORC) { + if(length >= 4) {/* Rule 1b */ list[1][i] = LATCHC; } else { list[1][i] = AORB; this = AORB; } + } + if(this == SHIFTA) { /* Rule 1c */ list[1][i] = LATCHA; } + if((this == AORB) && (next == SHIFTA)) { /* Rule 1c */ list[1][i] = LATCHA; this = LATCHA; } + if(this == AORB) { /* Rule 1d */ list[1][i] = LATCHB; } + } else { + if((this == ABORC) && (length >= 4)) { /* Rule 3 */ list[1][i] = LATCHC; this = LATCHC; } + if(this == ABORC) { list[1][i] = AORB; this = AORB; } + if((this == AORB) && (last == LATCHA)) { list[1][i] = LATCHA; this = LATCHA; } + if((this == AORB) && (last == LATCHB)) { list[1][i] = LATCHB; this = LATCHB; } + if((this == AORB) && (next == SHIFTA)) { list[1][i] = LATCHA; this = LATCHA; } + if((this == AORB) && (next == SHIFTB)) { list[1][i] = LATCHB; this = LATCHB; } + if(this == AORB) { list[1][i] = LATCHB; this = LATCHB; } + if((this == SHIFTA) && (length > 1)) { /* Rule 4 */ list[1][i] = LATCHA; this = LATCHA; } + if((this == SHIFTB) && (length > 1)) { /* Rule 5 */ list[1][i] = LATCHB; this = LATCHB; } + if((this == SHIFTA) && (last == LATCHA)) { list[1][i] = LATCHA; this = LATCHA; } + if((this == SHIFTB) && (last == LATCHB)) { list[1][i] = LATCHB; this = LATCHB; } + } /* Rule 2 is implimented elsewhere, Rule 6 is implied */ + } + grwp(indexliste); + +} + + +void c128_set_a(unsigned char source, char dest[], int values[], int *bar_chars) +{ /* Translate Code 128 Set A characters into barcodes */ + /* This set handles all control characters NULL to US */ + + if(source > 127) { + concat(dest, C128Table[source + 64 - 128]); + values[(*bar_chars)] = source + 64 - 128; + } else { + concat(dest, C128Table[source + 64]); + values[(*bar_chars)] = source + 64; + } + (*bar_chars)++; +} + +void c128_set_b(unsigned char source, char dest[], int values[], int *bar_chars) +{ /* Translate Code 128 Set B characters into barcodes */ + /* This set handles all characters which are not part of long numbers and not control characters */ + + if(source > 127) { + concat(dest, C128Table[source - 32 - 128]); + values[(*bar_chars)] = source - 32 - 128; + } else { + concat(dest, C128Table[source - 32]); + values[(*bar_chars)] = source - 32; + } + (*bar_chars)++; +} + +void c128_set_c(unsigned char source_a, unsigned char source_b, char dest[], int values[], int *bar_chars) +{ /* Translate Code 128 Set C characters into barcodes */ + /* This set handles numbers in a compressed form */ + int weight; + + weight = (10 * ctoi(source_a)) + ctoi(source_b); + concat(dest, C128Table[weight]); + values[(*bar_chars)] = weight; + (*bar_chars)++; +} + +int code_128(struct zint_symbol *symbol, unsigned char source[]) +{ /* Handle Code 128 and NVE-18 */ + int i, j, k, e_count, values[170], bar_characters, read, total_sum, nve_check; + int errornum, indexchaine, indexliste; + char set[170], fset[170], mode, last_set, last_fset; + float glyph_count; + char dest[1000]; + + errornum = 0; + strcpy(dest, ""); + + j = 0; + e_count = 0; + bar_characters = 0; + nve_check = 0; + + for(i = 0; i < 170; i++) { + values[i] = 0; + set[i] = ' '; + fset[i] = ' '; + } + + if(strlen(source) > 160) { + /* This only blocks rediculously long input - the actual length of the + resulting barcode depends on the type of data, so this is trapped later */ + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + /* Add check digit if encoding an NVE18 symbol */ + if(symbol->symbology == BARCODE_NVE18) { + errornum = is_sane(NESET, source); + if(errornum == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errornum; + } + if(strlen(source) != 17) { + strcpy(symbol->errtxt, "error: input wrong length"); + return ERROR_TOO_LONG; + } + for(i = strlen(source) + 2; i > 1; i--) { + source[i] = source[i - 2]; + } + source[0] = '0'; + source[1] = '0'; + total_sum = 0; + for(i = 0; i < 19; i++) + { + if((i % 2) == 0) { + total_sum += 3 * ctoi(source[i]); + } else { + total_sum += ctoi(source[i]); + } + + } + nve_check = 10 - total_sum%10; + source[strlen(source) + 1] = '\0'; + source[strlen(source)] = itoc(nve_check); + } + + /* Detect extended ASCII characters */ + for(i = 0; i < strlen(source); i++) { + if(source[i] >=128) { + fset[i] = 'f'; + } + } + fset[i] = '\0'; + + /* Decide when to latch to extended mode - Annex E note 3 */ + for(i = 0; i < strlen(source); i++) { + j = 0; + if(fset[i] == 'f') { + do { + j++; + } while(source[i + j] == 'f'); + if((j >= 5) || ((j >= 3) && ((i + j) == strlen(source)))) { + for(k = 0; k <= j; k++) { + source[i + k] = 'F'; + } + } + } + } + + /* Decide on mode using same system as PDF417 and rules of ISO 15417 Annex E */ + indexliste = 0; + indexchaine = 0; + + mode = parunmodd(source[indexchaine]); + if((symbol->symbology == BARCODE_CODE128B) && (mode == ABORC)) { + mode = AORB; + } + + for(i = 0; i < 170; i++) { + list[0][i] = 0; + } + + do { + list[1][indexliste] = mode; + while ((list[1][indexliste] == mode) && (indexchaine < strlen(source))) { + list[0][indexliste]++; + indexchaine++; + mode = parunmodd(source[indexchaine]); + if((symbol->symbology == BARCODE_CODE128B) && (mode == ABORC)) { + mode = AORB; + } + } + indexliste++; + } while (indexchaine < strlen(source)); + + dxsmooth(&indexliste); + + /* Resolve odd length LATCHC blocks */ + if((list[1][0] == LATCHC) && ((list[0][0] % 2) == 1)) { + /* Rule 2 */ + list[0][1]++; + list[0][0]--; + } + if(indexliste > 1) { + for(i = 1; i < indexliste; i++) { + if((list[1][i] == LATCHC) && ((list[0][i] % 2) == 1)) { + /* Rule 3b */ + list[0][i - 1]++; + list[0][i]--; + } + } + } + + /* Put set data into set[] */ + + read = 0; + for(i = 0; i < indexliste; i++) { + for(j = 0; j < list[0][i]; j++) { + switch(list[1][i]) { + case SHIFTA: set[read] = 'a'; break; + case LATCHA: set[read] = 'A'; break; + case SHIFTB: set[read] = 'b'; break; + case LATCHB: set[read] = 'B'; break; + case LATCHC: set[read] = 'C'; break; + } + read++; + } + } + + /* Now we can calculate how long the barcode is going to be - and stop it from + being too long */ + last_set = ' '; + last_fset = ' '; + glyph_count = 0.0; + for(i = 0; i < strlen(source); i++) { + if((set[i] == 'a') || (set[i] == 'b')) { + glyph_count = glyph_count + 1.0; + } + if(fset[i] == 'f') { + glyph_count = glyph_count + 1.0; + } + if(((set[i] == 'A') || (set[i] == 'B')) || (set[i] == 'C')) { + if(set[i] != last_set) { + last_set = set[i]; + glyph_count = glyph_count + 1.0; + } + } + if(i == 0) { + if(fset[i] == 'F') { + last_fset = 'F'; + glyph_count = glyph_count + 2.0; + } + } else { + if((fset[i] == 'F') && (fset[i - 1] != 'F')) { + last_fset = 'F'; + glyph_count = glyph_count + 2.0; + } + if((fset[i] != 'F') && (fset[i - 1] == 'F')) { + last_fset = ' '; + glyph_count = glyph_count + 2.0; + } + } + + if(set[i] == 'C') { + glyph_count = glyph_count + 0.5; + } else { + glyph_count = glyph_count + 1.0; + } + } + if(glyph_count > 80.0) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + /* So now we know what start character to use - we can get on with it! */ + switch(set[0]) + { + case 'A': /* Start A */ + concat(dest, C128Table[103]); + values[0] = 103; + break; + case 'B': /* Start B */ + concat(dest, C128Table[104]); + values[0] = 104; + break; + case 'C': /* Start C */ + concat(dest, C128Table[105]); + values[0] = 105; + break; + } + bar_characters++; + + if(symbol->symbology == BARCODE_NVE18) { + concat(dest, C128Table[102]); + values[1] = 102; + bar_characters++; + } + + if(fset[0] == 'F') { + switch(set[0]) { + case 'A': + concat(dest, C128Table[101]); + concat(dest, C128Table[101]); + values[bar_characters] = 101; + values[bar_characters + 1] = 101; + break; + case 'B': + concat(dest, C128Table[100]); + concat(dest, C128Table[100]); + values[bar_characters] = 100; + values[bar_characters + 1] = 100; + break; + } + bar_characters += 2; + } + + /* Encode the data */ + read = 0; + do { + + if((read != 0) && (set[read] != set[read - 1])) + { /* Latch different code set */ + switch(set[read]) + { + case 'A': concat(dest, C128Table[101]); + values[bar_characters] = 101; + bar_characters++; + break; + case 'B': concat(dest, C128Table[100]); + values[bar_characters] = 100; + bar_characters++; + break; + case 'C': concat(dest, C128Table[99]); + values[bar_characters] = 99; + bar_characters++; + break; + } + } + + if((read != 0) && (fset[read] != fset[read - 1])) { + if(fset[read] == 'F') { + /* Latch beginning of extended mode */ + switch(set[0]) { + case 'A': + concat(dest, C128Table[101]); + concat(dest, C128Table[101]); + values[bar_characters] = 101; + values[bar_characters + 1] = 101; + break; + case 'B': + concat(dest, C128Table[100]); + concat(dest, C128Table[100]); + values[bar_characters] = 100; + values[bar_characters + 1] = 100; + break; + } + bar_characters += 2; + } + if(fset[read - 1] == 'F') { + /* Latch end of extended mode */ + switch(set[0]) { + case 'A': + concat(dest, C128Table[101]); + concat(dest, C128Table[101]); + values[bar_characters] = 101; + values[bar_characters + 1] = 101; + break; + case 'B': + concat(dest, C128Table[100]); + concat(dest, C128Table[100]); + values[bar_characters] = 100; + values[bar_characters + 1] = 100; + break; + } + bar_characters += 2; + } + } + + if(fset[i] == 'f') { + /* Shift extended mode */ + switch(set[i]) { + case 'A': + concat(dest, C128Table[101]); + values[bar_characters] = 101; + break; + case 'B': + concat(dest, C128Table[100]); + values[bar_characters] = 100; + break; + } + bar_characters++; + } + + if((set[i] == 'a') || (set[i] == 'b')) { + /* Insert shift character */ + concat(dest, C128Table[98]); + values[bar_characters] = 98; + bar_characters++; + } + + + switch(set[read]) + { /* Encode data characters */ + case 'A': c128_set_a(source[read], dest, values, &bar_characters); + read++; + break; + case 'B': c128_set_b(source[read], dest, values, &bar_characters); + read++; + break; + case 'C': c128_set_c(source[read], source[read + 1], dest, values, &bar_characters); + read += 2; + break; + } + } while (read < strlen(source)); + + /* check digit calculation */ + total_sum = 0; + for(i = 0; i < bar_characters; i++) + { + if(i > 0) + { + values[i] *= i; + + } + total_sum += values[i]; + } + concat(dest, C128Table[total_sum%103]); + + /* Stop character */ + concat(dest, C128Table[106]); + expand(symbol, dest); + strcpy(symbol->text, source); + return errornum; +} + +int ean_128(struct zint_symbol *symbol, unsigned char source[]) +{ /* Handle EAN-128 (Now known as GS1-128) */ + int i, j, k, e_count, values[170], bar_characters, read, total_sum; + int errornum, indexchaine, indexliste, ai_latch; + char set[170], mode, last_set, reduced[170], ai_string[4]; + float glyph_count; + char dest[1000]; + int last_ai, separator_row, linkage_flag; + + errornum = 0; + strcpy(dest, ""); + linkage_flag = 0; + + j = 0; + e_count = 0; + bar_characters = 0; + separator_row = 0; + + for(i = 0; i < 170; i++) { + values[i] = 0; + set[i] = ' '; + } + + if(strlen(source) > 160) { + /* This only blocks rediculously long input - the actual length of the + resulting barcode depends on the type of data, so this is trapped later */ + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + /* Detect extended ASCII characters */ + for(i = 0; i < strlen(source); i++) { + if(source[i] >=128) { + strcpy(symbol->errtxt, "error: extended ASCII characters not supported by GS1-128"); + return ERROR_INVALID_DATA; + } + } + + if(source[0] != '[') { + strcpy(symbol->errtxt, "error: input string doesn't start with AI"); + return ERROR_INVALID_DATA; + } + + /* if part of a composite symbol make room for the separator pattern */ + if(symbol->symbology == BARCODE_EAN128_CC) { + separator_row = symbol->rows; + symbol->row_height[symbol->rows] = 1; + symbol->rows += 1; + } + + /* Resolve AI data - put resulting string in 'reduced' */ + j = 0; + last_ai = 0; + ai_latch = 1; + for(i = 0; i < strlen(source); i++) { + if((source[i] != '[') && (source[i] != ']')) { + reduced[j] = source[i]; + j++; + } + if(source[i] == '[') { + /* Start of an AI string */ + if(ai_latch == 0) { + reduced[j] = '['; + j++; + } + ai_string[0] = source[i + 1]; + ai_string[1] = source[i + 2]; + ai_string[2] = '\0'; + last_ai = atoi(ai_string); + ai_latch = 0; + /* The following values from GS1 specification figure 5.3.8.2.1 - 1 + "Element Strings with Pre-Defined Length Using Application Identifiers" */ + if((last_ai >= 0) && (last_ai <= 4)) { ai_latch = 1; } + if((last_ai >= 11) && (last_ai <= 20)) { ai_latch = 1; } + if(last_ai == 23) { ai_latch = 1; } /* legacy support - see 5.3.8.2.2 */ + if((last_ai >= 31) && (last_ai <= 36)) { ai_latch = 1; } + if(last_ai == 41) { ai_latch = 1; } + } + /* The ']' character is simply dropped from the input */ + } + reduced[j] = '\0'; + + /* the character '[' in the reduced string refers to the FNC1 character */ + + /* Note that no attempt is made to verify that the data to be encoded does + actually conform to the right data length - that is required of the person or + program inputting the data */ + + /* Decide on mode using same system as PDF417 and rules of ISO 15417 Annex E */ + indexliste = 0; + indexchaine = 0; + + mode = parunmodd(reduced[indexchaine]); + if(reduced[indexchaine] == '[') { + mode = ABORC; + } + + for(i = 0; i < 170; i++) { + list[0][i] = 0; + } + + do { + list[1][indexliste] = mode; + while ((list[1][indexliste] == mode) && (indexchaine < strlen(reduced))) { + list[0][indexliste]++; + indexchaine++; + mode = parunmodd(reduced[indexchaine]); + if(reduced[indexchaine] == '[') { + if(indexchaine % 2 == 0) { + mode = ABORC; + } else { + mode = AORB; + } + } + } + indexliste++; + } while (indexchaine < strlen(reduced)); + + dxsmooth(&indexliste); + + /* Resolve odd length LATCHC blocks */ + if((list[1][0] == LATCHC) && ((list[0][0] % 2) == 1)) { + /* Rule 2 */ + list[0][1]++; + list[0][0]--; + } + if(indexliste > 1) { + for(i = 1; i < indexliste; i++) { + if((list[1][i] == LATCHC) && ((list[0][i] % 2) == 1)) { + /* Rule 3b */ + list[0][i - 1]++; + list[0][i]--; + } + } + } + + /* Put set data into set[] */ + + read = 0; + for(i = 0; i < indexliste; i++) { + for(j = 0; j < list[0][i]; j++) { + switch(list[1][i]) { + case SHIFTA: set[read] = 'a'; break; + case LATCHA: set[read] = 'A'; break; + case SHIFTB: set[read] = 'b'; break; + case LATCHB: set[read] = 'B'; break; + case LATCHC: set[read] = 'C'; break; + } + read++; + } + } + + /* Now we can calculate how long the barcode is going to be - and stop it from + being too long */ + last_set = ' '; + glyph_count = 0.0; + for(i = 0; i < strlen(reduced); i++) { + if((set[i] == 'a') || (set[i] == 'b')) { + glyph_count = glyph_count + 1.0; + } + if(((set[i] == 'A') || (set[i] == 'B')) || (set[i] == 'C')) { + if(set[i] != last_set) { + last_set = set[i]; + glyph_count = glyph_count + 1.0; + } + } + + if(set[i] == 'C') { + glyph_count = glyph_count + 0.5; + } else { + glyph_count = glyph_count + 1.0; + } + } + if(glyph_count > 80.0) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + /* So now we know what start character to use - we can get on with it! */ + switch(set[0]) + { + case 'A': /* Start A */ + concat(dest, C128Table[103]); + values[0] = 103; + break; + case 'B': /* Start B */ + concat(dest, C128Table[104]); + values[0] = 104; + break; + case 'C': /* Start C */ + concat(dest, C128Table[105]); + values[0] = 105; + break; + } + bar_characters++; + + concat(dest, C128Table[102]); + values[1] = 102; + bar_characters++; + + /* Encode the data */ + read = 0; + do { + + if((read != 0) && (set[read] != set[read - 1])) + { /* Latch different code set */ + switch(set[read]) + { + case 'A': concat(dest, C128Table[101]); + values[bar_characters] = 101; + bar_characters++; + break; + case 'B': concat(dest, C128Table[100]); + values[bar_characters] = 100; + bar_characters++; + break; + case 'C': concat(dest, C128Table[99]); + values[bar_characters] = 99; + bar_characters++; + break; + } + } + + if((set[i] == 'a') || (set[i] == 'b')) { + /* Insert shift character */ + concat(dest, C128Table[98]); + values[bar_characters] = 98; + bar_characters++; + } + + if(reduced[read] != '[') { + switch(set[read]) + { /* Encode data characters */ + case 'A': c128_set_a(reduced[read], dest, values, &bar_characters); + read++; + break; + case 'B': c128_set_b(reduced[read], dest, values, &bar_characters); + read++; + break; + case 'C': c128_set_c(reduced[read], reduced[read + 1], dest, values, &bar_characters); + read += 2; + break; + } + } else { + concat(dest, C128Table[102]); + values[bar_characters] = 102; + bar_characters++; + read++; + } + } while (read < strlen(reduced)); + + /* "...note that the linkage flag is an extra code set character between + the last data character and the Symbol Check Character" (GS1 Specification) */ + + /* Linkage flags in GS1-128 are determined by ISO/IEC 24723 section 7.4 */ + + switch(symbol->option_1) { + case 1: + case 2: + /* CC-A or CC-B 2D component */ + switch(set[strlen(reduced) - 1]) { + case 'A': linkage_flag = 100; break; + case 'B': linkage_flag = 99; break; + case 'C': linkage_flag = 101; break; + } + break; + case 3: + /* CC-C 2D component */ + switch(set[strlen(reduced) - 1]) { + case 'A': linkage_flag = 99; break; + case 'B': linkage_flag = 101; break; + case 'C': linkage_flag = 100; break; + } + break; + } + + if(linkage_flag != 0) { + concat(dest, C128Table[linkage_flag]); + values[bar_characters] = linkage_flag; + bar_characters++; + } + + /* check digit calculation */ + total_sum = 0; + for(i = 0; i < bar_characters; i++) + { + if(i > 0) + { + values[i] *= i; + + } + total_sum += values[i]; + } + concat(dest, C128Table[total_sum%103]); + + /* Stop character */ + concat(dest, C128Table[106]); + expand(symbol, dest); + + /* Add the separator pattern for composite symbols */ + if(symbol->symbology == BARCODE_EAN128_CC) { + for(i = 0; i < symbol->width; i++) { + if(symbol->encoded_data[separator_row + 1][i] != '1') { + symbol->encoded_data[separator_row][i] = '1'; + } + } + } + + for(i = 0; i <= strlen(source); i++) { + if((source[i] != '[') && (source[i] != ']')) { + symbol->text[i] = source[i]; + } + if(source[i] == '[') { + symbol->text[i] = '('; + } + if(source[i] == ']') { + symbol->text[i] = ')'; + } + } + + return errornum; +} diff --git a/backend/code16k.c b/backend/code16k.c new file mode 100644 index 00000000..4edf0d63 --- /dev/null +++ b/backend/code16k.c @@ -0,0 +1,477 @@ +/* code16k.c - Handles Code 16k stacked symbology */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* Updated to comply with BS EN 12323:2005 */ + +/* up to 77 characters or 154 numbers */ + +#include +#include +#include +#include "common.h" + +#define TRUE 1 +#define FALSE 0 +#define SHIFTA 90 +#define LATCHA 91 +#define SHIFTB 92 +#define LATCHB 93 +#define SHIFTC 94 +#define LATCHC 95 +#define AORB 96 +#define ABORC 97 +#define CANDB 98 +#define CANDBB 99 + +int list[2][170]; + +/* EN 12323 Table 1 - "Code 16K" character encodations */ +static char *C16KTable[107] = {"212222", "222122", "222221", "121223", "121322", "131222", "122213", + "122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222", + "123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222", + "321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323", + "131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133", + "112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113", + "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111", + "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214", + "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", + "134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", + "421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311", + "411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232", + "211133"}; + +/* EN 12323 Table 3 and Table 4 - Start patterns and stop patterns */ +static char *C16KStartStop[8] = {"3211", "2221", "2122", "1411", "1132", "1231", "1114", "3112"}; + +/* EN 12323 Table 5 - Start and stop values defining row numbers */ +static int C16KStartValues[16] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7}; +static int C16KStopValues[16] = {0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3}; + +int parunmodd(unsigned char llyth); +void grwp(int *indexliste); + +void reysmooth(int *indexliste) +{ /* Implements rules from EN 12323 */ + int i, this, last, next, length; + + for(i = 0; i < *(indexliste); i++) { + this = list[1][i]; + length = list[0][i]; + if(i != 0) { last = list[1][i - 1]; } else { last = FALSE; } + if(i != *(indexliste) - 1) { next = list[1][i + 1]; } else { next = FALSE; } + + if(i == 0) { /* first block */ + if((*(indexliste) == 1) && ((length == 2) && (this == ABORC))) { /* Rule 1a */ list[1][i] = LATCHC; } + if(this == ABORC) { + if(length >= 4) {/* Rule 1b */ list[1][i] = LATCHC; } else { list[1][i] = AORB; this = AORB; } + } + if(this == SHIFTA) { /* Rule 1c */ list[1][i] = LATCHA; } + if((this == AORB) && (next == SHIFTA)) { /* Rule 1c */ list[1][i] = LATCHA; this = LATCHA; } + if(this == AORB) { /* Rule 1d */ list[1][i] = LATCHB; } + } else { + if((this == ABORC) && (length >= 4)) { /* Rule 3 */ list[1][i] = LATCHC; this = LATCHC; } + if(this == ABORC) { list[1][i] = AORB; this = AORB; } + if((this == AORB) && (last == LATCHA)) { list[1][i] = LATCHA; this = LATCHA; } + if((this == AORB) && (last == LATCHB)) { list[1][i] = LATCHB; this = LATCHB; } + if((this == AORB) && (next == SHIFTA)) { list[1][i] = LATCHA; this = LATCHA; } + if((this == AORB) && (next == SHIFTB)) { list[1][i] = LATCHB; this = LATCHB; } + if(this == AORB) { list[1][i] = LATCHB; this = LATCHB; } + if((this == SHIFTA) && (length > 1)) { /* Rule 4 */ list[1][i] = LATCHA; this = LATCHA; } + if((this == SHIFTB) && (length > 1)) { /* Rule 5 */ list[1][i] = LATCHB; this = LATCHB; } + if((this == SHIFTA) && (last == LATCHA)) { list[1][i] = LATCHA; this = LATCHA; } + if((this == SHIFTB) && (last == LATCHB)) { list[1][i] = LATCHB; this = LATCHB; } + } /* Rule 2 is implimented elsewhere, Rule 6 is implied */ + } + grwp(indexliste); + +} + +void c16k_set_a(unsigned char source, int values[], int *bar_chars) +{ + if(source > 127) { + values[(*bar_chars)] = source + 64 - 128; + } else { + values[(*bar_chars)] = source + 64; + } + (*bar_chars)++; +} + +void c16k_set_b(unsigned char source, int values[], int *bar_chars) +{ + if(source > 127) { + values[(*bar_chars)] = source - 32 - 128; + } else { + values[(*bar_chars)] = source - 32; + } + (*bar_chars)++; +} + +void c16k_set_c(unsigned char source_a, unsigned char source_b, int values[], int *bar_chars) +{ + int weight; + + weight = (10 * ctoi(source_a)) + ctoi(source_b); + values[(*bar_chars)] = weight; + (*bar_chars)++; +} + +int code16k(struct zint_symbol *symbol, unsigned char source[]) +{ + char width_pattern[100]; + int current_row, rows_needed, flip_flop, looper, first_check, second_check; + int indexliste, indexchaine, pads_needed; + char set[160], fset[160], mode, last_set, last_fset; + unsigned int i, j, k, m, e_count, read, mx_reader, writer; + unsigned int values[160]; + unsigned int bar_characters; + strcpy(width_pattern, ""); + float glyph_count; + int errornum, first_sum, second_sum; + + errornum = 0; + + if(strlen(source) > 157) { + strcpy(symbol->errtxt, "error: input too long"); + return 6; + } + + e_count = 0; + bar_characters = 0; + + for(i = 0; i < 160; i++) { + values[i] = 0; + set[i] = ' '; + fset[i] = ' '; + } + + /* Detect extended ASCII characters */ + for(i = 0; i < strlen(source); i++) { + if(source[i] >=128) { + fset[i] = 'f'; + } + } + fset[i] = '\0'; + + /* Decide when to latch to extended mode */ + for(i = 0; i < strlen(source); i++) { + j = 0; + if(fset[i] == 'f') { + do { + j++; + } while(source[i + j] == 'f'); + if((j >= 5) || ((j >= 3) && ((i + j) == strlen(source)))) { + for(k = 0; k <= j; k++) { + source[i + k] = 'F'; + } + } + } + } + + /* Detect mode A, B and C characters */ + indexliste = 0; + indexchaine = 0; + + mode = parunmodd(source[indexchaine]); + + for(i = 0; i < 160; i++) { + list[0][i] = 0; + } + + do { + list[1][indexliste] = mode; + while ((list[1][indexliste] == mode) && (indexchaine < strlen(source))) { + list[0][indexliste]++; + indexchaine++; + mode = parunmodd(source[indexchaine]); + } + indexliste++; + } while (indexchaine < strlen(source)); + + reysmooth(&indexliste); + + /* Resolve odd length LATCHC blocks */ + if((list[1][0] == LATCHC) && ((list[0][0] % 2) == 1)) { + for(i = 1; i <= indexliste; i++) { + list[0][i] = list[0][i - 1]; + list[1][i] = list[1][i - 1]; + } + list[0][1]--; + list[0][0] = 1; + list[1][0] = LATCHB; + indexliste++; + } + if(indexliste > 1) { + for(i = 1; i < indexliste; i++) { + if((list[1][i] == LATCHC) && ((list[0][i] % 2) == 1)) { + list[0][i - 1]++; + list[0][i]--; + } + } + } + + /* Put set data into set[] */ + + read = 0; + for(i = 0; i < indexliste; i++) { + for(j = 0; j < list[0][i]; j++) { + switch(list[1][i]) { + case SHIFTA: set[read] = 'a'; break; + case LATCHA: set[read] = 'A'; break; + case SHIFTB: set[read] = 'b'; break; + case LATCHB: set[read] = 'B'; break; + case LATCHC: set[read] = 'C'; break; + } + read++; + } + } + + /* Make sure the data will fit in the symbol */ + last_set = ' '; + last_fset = ' '; + glyph_count = 0.0; + for(i = 0; i < strlen(source); i++) { + if((set[i] == 'a') || (set[i] == 'b')) { + glyph_count = glyph_count + 1.0; + } + if(fset[i] == 'f') { + glyph_count = glyph_count + 1.0; + } + if(((set[i] == 'A') || (set[i] == 'B')) || (set[i] == 'C')) { + if(set[i] != last_set) { + last_set = set[i]; + glyph_count = glyph_count + 1.0; + } + } + if(i == 0) { + if((set[i] == 'B') && (set[1] == 'C')) { + glyph_count = glyph_count - 1.0; + } + if((set[i] == 'B') && (set[1] == 'B')) { + if(set[2] == 'C') { + glyph_count = glyph_count - 1.0; + } + } + if(fset[i] == 'F') { + last_fset = 'F'; + glyph_count = glyph_count + 2.0; + } + } else { + if((fset[i] == 'F') && (fset[i - 1] != 'F')) { + last_fset = 'F'; + glyph_count = glyph_count + 2.0; + } + if((fset[i] != 'F') && (fset[i - 1] == 'F')) { + last_fset = ' '; + glyph_count = glyph_count + 2.0; + } + } + + if(set[i] == 'C') { + glyph_count = glyph_count + 0.5; + } else { + glyph_count = glyph_count + 1.0; + } + } + if(glyph_count > 77.0) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + /* Calculate how tall the symbol will be */ + glyph_count = glyph_count + 2.0; + i = glyph_count; + rows_needed = (i/5); + if(i%5 > 0) { rows_needed++; } + + /* start with the mode character - Table 2 */ + m = 0; + switch(set[0]) { + case 'A': m = 0; break; + case 'B': m = 1; break; + case 'C': m = 2; break; + } + if((set[0] == 'B') && (set[1] == 'C')) { m = 5; } + if(((set[0] == 'B') && (set[1] == 'B')) && (set[2] == 'C')) { m = 6; } + values[bar_characters] = (7 * (rows_needed - 2)) + m; /* see 4.3.4.2 */ + bar_characters++; + + if(fset[0] == 'F') { + switch(set[0]) { + case 'A': + values[bar_characters] = 101; + values[bar_characters + 1] = 101; + break; + case 'B': + values[bar_characters] = 100; + values[bar_characters + 1] = 100; + break; + } + bar_characters += 2; + } + + /* Encode the data */ + read = 0; + do { + + if((read != 0) && (set[read] != set[read - 1])) + { /* Latch different code set */ + switch(set[read]) + { + case 'A': + values[bar_characters] = 101; + bar_characters++; + break; + case 'B': + values[bar_characters] = 100; + bar_characters++; + break; + case 'C': + if(!((read == 1) && (set[0] == 'B'))) { /* Not Mode C/Shift B */ + if(!((read == 2) && ((set[0] == 'B') && (set[1] == 'B')))) { + /* Not Mode C/Double Shift B */ + values[bar_characters] = 99; + bar_characters++; + } + } + break; + } + } + + if((read != 0) && (fset[read] != fset[read - 1])) { + if(fset[read] == 'F') { + /* Latch beginning of extended mode */ + switch(set[0]) { + case 'A': + values[bar_characters] = 101; + values[bar_characters + 1] = 101; + break; + case 'B': + values[bar_characters] = 100; + values[bar_characters + 1] = 100; + break; + } + bar_characters += 2; + } + if(fset[read - 1] == 'F') { + /* Latch end of extended mode */ + switch(set[0]) { + case 'A': + values[bar_characters] = 101; + values[bar_characters + 1] = 101; + break; + case 'B': + values[bar_characters] = 100; + values[bar_characters + 1] = 100; + break; + } + bar_characters += 2; + } + } + + if(fset[i] == 'f') { + /* Shift extended mode */ + switch(set[i]) { + case 'A': + values[bar_characters] = 101; + break; + case 'B': + values[bar_characters] = 100; + break; + } + bar_characters++; + } + + if((set[i] == 'a') || (set[i] == 'b')) { + /* Insert shift character */ + values[bar_characters] = 98; + bar_characters++; + } + + + switch(set[read]) + { /* Encode data characters */ + case 'A': c16k_set_a(source[read], values, &bar_characters); + read++; + break; + case 'B': c16k_set_b(source[read], values, &bar_characters); + read++; + break; + case 'C': c16k_set_c(source[read], source[read + 1], values, &bar_characters); + read += 2; + break; + } + } while (read < strlen(source)); + + + pads_needed = 5 - ((bar_characters + 2) % 5); + if(pads_needed == 5) { + pads_needed = 0; + } + for(i = 0; i < pads_needed; i++) { + values[bar_characters] = 106; + bar_characters++; + } + + first_sum = 0; + second_sum = 0; + for(i = 0; i < bar_characters; i++) + { + first_sum += (i+2) * values[i]; + second_sum += (i+1) * values[i]; + } + first_check = first_sum % 107; + second_sum += first_check * (bar_characters + 1); + second_check = second_sum % 107; + values[bar_characters] = first_check; + values[bar_characters + 1] = second_check; + bar_characters += 2; + + for(current_row = 0; current_row < rows_needed; current_row++) { + + strcpy(width_pattern, ""); + concat(width_pattern, C16KStartStop[C16KStartValues[current_row]]); + concat(width_pattern, "1"); + for(i = 0; i < 5; i++) { + concat(width_pattern, C16KTable[values[(current_row * 5) + i]]); + } + concat(width_pattern, C16KStartStop[C16KStopValues[current_row]]); + + /* Write the information into the symbol */ + writer = 0; + flip_flop = 1; + for (mx_reader = 0; mx_reader < strlen(width_pattern); mx_reader++) { + for(looper = 0; looper < ctoi(width_pattern[mx_reader]); looper++) { + if(flip_flop == 1) { + symbol->encoded_data[current_row][writer] = '1'; + writer++; } + else { + symbol->encoded_data[current_row][writer] = '0'; + writer++; } + } + if(flip_flop == 0) { flip_flop = 1; } else { flip_flop = 0; } + } + symbol->row_height[current_row] = 8; + } + + symbol->rows = rows_needed; + symbol->width = 70; + return errornum; +} diff --git a/backend/common.c b/backend/common.c new file mode 100644 index 00000000..681af707 --- /dev/null +++ b/backend/common.c @@ -0,0 +1,126 @@ +/* common.c - Contains functions needed for a number of barcodes */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include "common.h" + +#define SSET "0123456789ABCDEF" + +void concat(char dest[], char source[]) +{ /* Concatinates dest[] with the contents of source[], copying /0 as well */ + unsigned int i, j; + + j = strlen(dest); + for(i = 0; i <= strlen(source); i++) { + dest[i + j] = source[i]; } +} + +int ctoi(char source) +{ /* Converts a character 0-9 to its equivalent integer value */ + if((source >= '0') && (source <= '9')) + return (source - '0'); + return(source - 'A' + 10); +} + +char itoc(int source) +{ /* Converts an integer value to its hexadecimal character */ + if ((source >= 0) && (source <= 9)) { + return ('0' + source); } + else { + return ('A' + (source - 10)); } +} + +void to_upper(unsigned char source[]) +{ /* Converts lower case characters to upper case in a string source[] */ + unsigned int i; + + for (i = 0; i < strlen(source); i++) { + if ((source[i] >= 'a') && (source[i] <= 'z')) { + source [i] = (source[i] - 'a') + 'A'; } + } +} + +int is_sane(char test_string[], unsigned char source[]) +{ /* Verifies that a string only uses valid characters */ + unsigned int i, j, latch; + + for(i = 0; i < strlen(source); i++) { + latch = FALSE; + for(j = 0; j < strlen(test_string); j++) { + if (source[i] == test_string[j]) { latch = TRUE; } } + if (!(latch)) { + return ERROR_INVALID_DATA; } + } + + return 0; +} + +int posn(char set_string[], char data) +{ /* Returns the position of data in set_string */ + unsigned int i; + + for(i = 0; i < strlen(set_string); i++) { + if (data == set_string[i]) { return i; } } + return 0; +} + +void lookup(char set_string[], char *table[], char data, char dest[]) +{ /* Replaces huge switch statements for looking up in tables */ + unsigned int i; + + for(i = 0; i < strlen(set_string); i++) { + if (data == set_string[i]) { concat(dest, table[i]); } } +} + +void expand(struct zint_symbol *symbol, char data[]) +{ /* Expands from a width pattern to a bit pattern */ + + int reader, writer, i; + char latch; + + writer = 0; + latch = '1'; + + for(reader = 0; reader < strlen(data); reader++) { + for(i = 0; i < ctoi(data[reader]); i++) { + symbol->encoded_data[symbol->rows][writer] = latch; + writer++; + } + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } + + if(symbol->symbology != BARCODE_PHARMA) { + if(writer > symbol->width) { + symbol->width = writer; + } + } else { + /* Pharmacode One ends with a space - adjust for this */ + if(writer > symbol->width + 2) { + symbol->width = writer - 2; + } + } + symbol->rows = symbol->rows + 1; +} diff --git a/backend/common.h b/backend/common.h new file mode 100644 index 00000000..40621aa2 --- /dev/null +++ b/backend/common.h @@ -0,0 +1,38 @@ +/* common.h - Header for all common functions in common.c */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 Robin Stuart (zint@hotmail.co.uk) + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* Used in some logic */ +#define FALSE 0 +#define TRUE 1 + +/* The most commonly used set */ +#define NESET "0123456789" + +#include "zint.h" + +void concat(char dest[], char source[]); +int ctoi(char source); +char itoc(int source); +void to_upper(unsigned char source[]); +int is_sane(char test_string[], unsigned char source[]); +void lookup(char set_string[], char *table[], char data, char dest[]); +int posn(char set_string[], char data); +void expand(struct zint_symbol *symbol, char data[]); diff --git a/backend/composite.c b/backend/composite.c new file mode 100644 index 00000000..a8e328ed --- /dev/null +++ b/backend/composite.c @@ -0,0 +1,1916 @@ +/* composite.c - Handles UCC.EAN Composite Symbols */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* 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 +#include +#include +#include +#include "common.h" +#include "large.h" +#include "composite.h" +#include "pdf417.h" +#define UINT unsigned short + +int general_rules(char field[], char type[]); + +static UINT pwr928[69][7]; + +int min(int first, int second) { + if(first <= second) { + return first; + } else { + return second; + } +} + +/* gets bit in bitString at bitPos */ +int getBit(UINT *bitStr, int bitPos) { + return(((bitStr[bitPos/16] & (0x8000>>(bitPos%16))) == 0) ? 0 : 1); +} + +/* initialize pwr928 encoding table */ +void init928(void) { + int i, j, v; + int cw[7]; + cw[6] = 1L; + for (i = 5; i >= 0; i--) + cw[i] = 0; + + for (i = 0; i < 7; i++) + pwr928[0][i] = cw[i]; + for (j = 1; j < 69; j++) { + for (v = 0, i = 6; i >= 1; i--) { + v = (2 * cw[i]) + (v / 928); + pwr928[j][i] = cw[i] = v % 928; + } + pwr928[j][0] = cw[0] = (2 * cw[0]) + (v / 928); + } + return; +} + +/* converts bit string to base 928 values, codeWords[0] is highest order */ +int encode928(UINT bitString[], UINT codeWords[], int bitLng) { + int i, j, b, bitCnt, cwNdx, cwCnt, cwLng; + for (cwNdx = cwLng = b = 0; b < bitLng; b += 69, cwNdx += 7) { + bitCnt = min(bitLng-b, 69); + cwLng += cwCnt = bitCnt/10 + 1; + for (i = 0; i < cwCnt; i++) + codeWords[cwNdx+i] = 0; /* init 0 */ + for (i = 0; i < bitCnt; i++) { + if (getBit(bitString, b+bitCnt-i-1)) { + for (j = 0; j < cwCnt; j++) + codeWords[cwNdx+j] += pwr928[i][j+7-cwCnt]; + } + } + for (i = cwCnt-1; i > 0; i--) { + /* add "carries" */ + codeWords[cwNdx+i-1] += codeWords[cwNdx+i]/928L; + codeWords[cwNdx+i] %= 928L; + } + } + return (cwLng); +} + +int cc_a(struct zint_symbol *symbol, unsigned char source[], int cc_width) +{ /* CC-A 2D component */ + int temp; + int i, strpos, segment, bitlen, cwCnt, variant, rows; + int k, offset, j, total, rsCodeWords[8]; + int LeftRAPStart, RightRAPStart, CentreRAPStart, StartCluster; + int LeftRAP, RightRAP, CentreRAP, Cluster, dummy[5]; + int writer, flip, loop; + UINT codeWords[28]; + UINT bitStr[13]; + char codebarre[100], pattern[580]; + + for(i = 0; i < 13; i++) { bitStr[i] = 0; } + for(i = 0; i < 28; i++) { codeWords[i] = 0; } + + bitlen = strlen(source); + + for(i = bitlen; i < 197; i++) { + source[i] = '0'; + } + source[197] = '\0'; + + for(segment = 0; segment < 13; segment++) { + strpos = segment * 16; + if(source[strpos] == '1') { bitStr[segment] += 0x8000; } + if(source[strpos + 1] == '1') { bitStr[segment] += 0x4000; } + if(source[strpos + 2] == '1') { bitStr[segment] += 0x2000; } + if(source[strpos + 3] == '1') { bitStr[segment] += 0x1000; } + if(source[strpos + 4] == '1') { bitStr[segment] += 0x800; } + if(source[strpos + 5] == '1') { bitStr[segment] += 0x400; } + if(source[strpos + 6] == '1') { bitStr[segment] += 0x200; } + if(source[strpos + 7] == '1') { bitStr[segment] += 0x100; } + if(source[strpos + 8] == '1') { bitStr[segment] += 0x80; } + if(source[strpos + 9] == '1') { bitStr[segment] += 0x40; } + if(source[strpos + 10] == '1') { bitStr[segment] += 0x20; } + if(source[strpos + 11] == '1') { bitStr[segment] += 0x10; } + if(source[strpos + 12] == '1') { bitStr[segment] += 0x08; } + if(source[strpos + 13] == '1') { bitStr[segment] += 0x04; } + if(source[strpos + 14] == '1') { bitStr[segment] += 0x02; } + if(source[strpos + 15] == '1') { bitStr[segment] += 0x01; } + } + + init928(); + /* encode codeWords from bitStr */ + cwCnt = 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 = ccaVariants[variant]; + k = ccaVariants[17 + variant]; + offset = ccaVariants[34 + variant]; + + /* Reed-Solomon error correction */ + + for(i = 0; i < 8; i++) { + rsCodeWords[i] = 0; + } + total = 0; + 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 * ccaCoeffs[offset + j]) % 929) % 929; + } else { + rsCodeWords[j] = (rsCodeWords[j - 1] + 929 - (total * ccaCoeffs[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 = aRAPTable[variant]; + CentreRAPStart = aRAPTable[variant + 17]; + RightRAPStart = aRAPTable[variant + 34]; + StartCluster = 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++) { + strcpy(codebarre, ""); + offset = 929 * Cluster; + for(j = 0; j < 5; j++) { + dummy[j] = 0; + } + for(j = 0; j < cc_width ; j++) { + dummy[j + 1] = codeWords[i * cc_width + j]; + } + /* Copy the data into codebarre */ + concat(codebarre, RAPLR[LeftRAP]); + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[1]]); + concat(codebarre, "1"); + if(dummy[2] != 0) { + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[2]]); + concat(codebarre, "1"); + } + if(CentreRAPStart != 0) { + concat(codebarre, RAPC[CentreRAP]); + } + if(dummy[3] != 0) { + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[3]]); + concat(codebarre, "1"); + } + if(dummy[4] != 0) { + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[4]]); + concat(codebarre, "1"); + } + concat(codebarre, RAPLR[RightRAP]); + concat(codebarre, "1"); /* stop */ + + /* Now codebarre is a mixture of letters and numbers */ + + writer = 0; + flip = 1; + strcpy(pattern, ""); + for(loop = 0; loop < strlen(codebarre); loop++) { + if((codebarre[loop] >= '0') && (codebarre[loop] <= '9')) { + for(k = 0; k < ctoi(codebarre[loop]); k++) { + if(flip == 0) { + pattern[writer] = '0'; + } else { + pattern[writer] = '1'; + } + writer++; + } + pattern[writer] = '\0'; + if(flip == 0) { + flip = 1; + } else { + flip = 0; + } + } else { + lookup(BRSET, PDFttf, codebarre[loop], pattern); + writer += 5; + } + } + symbol->width = writer; + + /* so now pattern[] holds the string of '1's and '0's. - copy this to the symbol */ + for(loop = 0; loop < strlen(pattern); loop++) { + symbol->encoded_data[i][loop] = pattern[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; + } + } + + return 0; +} + +int cc_b(struct zint_symbol *symbol, unsigned char source[], int cc_width) +{ /* CC-B 2D component */ + int length, i, binloc; + unsigned char data_string[(strlen(source) / 8) + 3]; + int chainemc[180], mclength; + int k, j, longueur, mccorrection[50], offset; + int total, dummy[5]; + char codebarre[100], pattern[580]; + int variant, LeftRAPStart, CentreRAPStart, RightRAPStart, StartCluster; + int LeftRAP, CentreRAP, RightRAP, Cluster, writer, flip, loop; + + length = strlen(source) / 8; + + for(i = 0; i < length; i++) { + binloc = i * 8; + + data_string[i] = 0; + if(source[binloc] == '1') { data_string[i] += 0x80; } + if(source[binloc + 1] == '1') { data_string[i] += 0x40; } + if(source[binloc + 2] == '1') { data_string[i] += 0x20; } + if(source[binloc + 3] == '1') { data_string[i] += 0x10; } + if(source[binloc + 4] == '1') { data_string[i] += 0x08; } + if(source[binloc + 5] == '1') { data_string[i] += 0x04; } + if(source[binloc + 6] == '1') { data_string[i] += 0x02; } + if(source[binloc + 7] == '1') { data_string[i] += 0x01; } + } + + + mclength = 0; + + /* "the CC-B component shall have codeword 920 in the first symbol character position" (section 9a) */ + chainemc[mclength] = 920; + mclength++; + + 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) { + variant = 13; + if(mclength <= 33) { variant = 12; } + if(mclength <= 29) { variant = 11; } + if(mclength <= 24) { variant = 10; } + if(mclength <= 19) { variant = 9; } + if(mclength <= 13) { variant = 8; } + if(mclength <= 8) { variant = 7; } + } + + if(cc_width == 3) { + variant = 23; + if(mclength <= 70) { variant = 22; } + if(mclength <= 58) { variant = 21; } + if(mclength <= 46) { variant = 20; } + if(mclength <= 34) { variant = 19; } + if(mclength <= 24) { variant = 18; } + if(mclength <= 18) { variant = 17; } + if(mclength <= 14) { variant = 16; } + if(mclength <= 10) { variant = 15; } + if(mclength <= 6) { variant = 14; } + } + + if(cc_width == 4) { + variant = 34; + if(mclength <= 108) { variant = 33; } + if(mclength <= 90) { variant = 32; } + if(mclength <= 72) { variant = 31; } + if(mclength <= 54) { variant = 30; } + if(mclength <= 39) { variant = 29; } + if(mclength <= 30) { variant = 28; } + if(mclength <= 24) { variant = 27; } + if(mclength <= 18) { variant = 26; } + if(mclength <= 12) { variant = 25; } + if(mclength <= 8) { variant = 24; } + } + + /* Now we have the variant we can load the data - from here on the same as MicroPDF417 code */ + variant --; + symbol->option_2 = MicroVariants[variant]; /* columns */ + symbol->rows = MicroVariants[variant + 34]; /* rows */ + k = MicroVariants[variant + 68]; /* number of EC CWs */ + longueur = (symbol->option_2 * symbol->rows) - k; /* number of non-EC CWs */ + i = longueur - mclength; /* amount of padding required */ + offset = MicroVariants[variant + 102]; /* coefficient offset */ + + /* We add the padding */ + while (i > 0) { + chainemc[mclength] = 900; + mclength++; + i--; + } + + /* Reed-Solomon error correction */ + longueur = mclength; + for(loop = 0; loop < 50; loop++) { + mccorrection[loop] = 0; + } + total = 0; + 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 * Microcoeffs[offset + j]) % 929) % 929; + } else { + mccorrection[j] = (mccorrection[j - 1] + 929 - (total * 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]; + mclength++; + } + + /* Now get the RAP (Row Address Pattern) start values */ + LeftRAPStart = RAPTable[variant]; + CentreRAPStart = RAPTable[variant + 34]; + RightRAPStart = RAPTable[variant + 68]; + StartCluster = 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++) { + strcpy(codebarre, ""); + offset = 929 * Cluster; + for(j = 0; j < 5; j++) { + dummy[j] = 0; + } + for(j = 0; j < symbol->option_2 ; j++) { + dummy[j + 1] = chainemc[i * symbol->option_2 + j]; + } + /* Copy the data into codebarre */ + concat(codebarre, RAPLR[LeftRAP]); + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[1]]); + concat(codebarre, "1"); + if(cc_width == 3) { + concat(codebarre, RAPC[CentreRAP]); + } + if(dummy[2] != 0) { + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[2]]); + concat(codebarre, "1"); + } + if(cc_width == 4) { + concat(codebarre, RAPC[CentreRAP]); + } + if(dummy[3] != 0) { + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[3]]); + concat(codebarre, "1"); + } + if(dummy[4] != 0) { + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[4]]); + concat(codebarre, "1"); + } + concat(codebarre, RAPLR[RightRAP]); + concat(codebarre, "1"); /* stop */ + + /* Now codebarre is a mixture of letters and numbers */ + + writer = 0; + flip = 1; + strcpy(pattern, ""); + for(loop = 0; loop < strlen(codebarre); loop++) { + if((codebarre[loop] >= '0') && (codebarre[loop] <= '9')) { + for(k = 0; k < ctoi(codebarre[loop]); k++) { + if(flip == 0) { + pattern[writer] = '0'; + } else { + pattern[writer] = '1'; + } + writer++; + } + pattern[writer] = '\0'; + if(flip == 0) { + flip = 1; + } else { + flip = 0; + } + } else { + lookup(BRSET, PDFttf, codebarre[loop], pattern); + writer += 5; + } + } + symbol->width = writer; + + /* so now pattern[] holds the string of '1's and '0's. - copy this to the symbol */ + for(loop = 0; loop < strlen(pattern); loop++) { + symbol->encoded_data[i][loop] = pattern[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; + } + } + + return 0; +} + +int cc_c(struct zint_symbol *symbol, unsigned char source[], int cc_width, int ecc_level) +{ /* CC-C 2D component - byte compressed PDF417 */ + int length, i, binloc; + unsigned char data_string[(strlen(source) / 8) + 4]; + int chainemc[1000], mclength, k; + int offset, longueur, loop, total, j, mccorrection[520]; + int c1, c2, c3, dummy[35]; + char codebarre[100], pattern[580]; + + length = strlen(source) / 8; + + for(i = 0; i < length; i++) { + binloc = i * 8; + + data_string[i] = 0; + if(source[binloc] == '1') { data_string[i] += 0x80; } + if(source[binloc + 1] == '1') { data_string[i] += 0x40; } + if(source[binloc + 2] == '1') { data_string[i] += 0x20; } + if(source[binloc + 3] == '1') { data_string[i] += 0x10; } + if(source[binloc + 4] == '1') { data_string[i] += 0x08; } + if(source[binloc + 5] == '1') { data_string[i] += 0x04; } + if(source[binloc + 6] == '1') { data_string[i] += 0x02; } + if(source[binloc + 7] == '1') { data_string[i] += 0x01; } + } + + mclength = 0; + + chainemc[mclength] = 0; /* space for length descriptor */ + mclength++; + chainemc[mclength] = 920; /* CC-C identifier */ + mclength++; + + byteprocess(chainemc, &mclength, data_string, 0, length, 0); + + chainemc[0] = mclength; + + 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; break; + case 2: offset = 6; break; + case 3: offset = 14; break; + case 4: offset = 30; break; + case 5: offset = 62; break; + case 6: offset = 126; break; + case 7: offset = 254; break; + case 8: offset = 510; break; + default: offset = 0; break; + } + + longueur = mclength; + for(loop = 0; loop < 520; loop++) { + mccorrection[loop] = 0; + } + total = 0; + 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 * coefrs[offset + j]) % 929) % 929; + } else { + mccorrection[j] = (mccorrection[j - 1] + 929 - (total * 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]; + mclength++; + } + + /* 818 - The CW string is finished */ + c1 = (mclength / cc_width - 1) / 3; + c2 = ecc_level * 3 + (mclength / cc_width - 1) % 3; + c3 = cc_width - 1; + + /* we now encode each row */ + for(i = 0; i <= (mclength / cc_width) - 1; i++) { + for(j = 0; j < cc_width ; j++) { + dummy[j + 1] = chainemc[i * cc_width + j]; + } + k = (i / 3) * 30; + switch(i % 3) { + /* follows this pattern from US Patent 5,243,655: + Row 0: L0 (row #, # of rows) R0 (row #, # of columns) + Row 1: L1 (row #, security level) R1 (row #, # of rows) + Row 2: L2 (row #, # of columns) R2 (row #, security level) + Row 3: L3 (row #, # of rows) R3 (row #, # of columns) + etc. */ + case 0: + dummy[0] = k + c1; + dummy[cc_width + 1] = k + c3; + break; + case 1: + dummy[0] = k + c2; + dummy[cc_width + 1] = k + c1; + break; + case 2: + dummy[0] = k + c3; + dummy[cc_width + 1] = k + c2; + break; + } + strcpy(codebarre, "+*"); /* Start with a start char and a separator */ + + for(j = 0; j <= cc_width + 1; j++) { + switch(i % 3) { + case 1: offset = 929; /* cluster(3) */ break; + case 2: offset = 1858; /* cluster(6) */ break; + default: offset = 0; /* cluster(0) */ break; + } + concat(codebarre, codagemc[offset + dummy[j]]); + concat(codebarre, "*"); + } + concat(codebarre, "-"); + + strcpy(pattern, ""); + for(loop = 0; loop < strlen(codebarre); loop++) { + lookup(BRSET, PDFttf, codebarre[loop], pattern); + } + for(loop = 0; loop < strlen(pattern); loop++) { + symbol->encoded_data[i][loop] = pattern[loop]; + } + symbol->row_height[i] = 3; + } + symbol->rows = (mclength / cc_width); + symbol->width = strlen(pattern); + + return 0; +} + +int cc_binary_string(struct zint_symbol *symbol, unsigned char source[], char binary_string[], int cc_mode, int *cc_width, int *ecc, int lin_width) +{ /* Handles all data encodation from section 5 of ISO/IEC 24723 */ + int encoding_method, read_posn, d1, d2, value, alpha_pad; + int group_val, i, j, mask, ai_crop, ai_crop_posn, fnc1_latch; + int ai90_mode, latch, remainder; + char date_str[4]; + char general_field[strlen(source)], general_field_type[strlen(source)]; + int target_bitsize; + + encoding_method = 1; + read_posn = 0; + ai_crop = 0; + ai_crop_posn = -1; + fnc1_latch = 0; + alpha_pad = 0; + ai90_mode = 0; + *(ecc) = 0; + + if((source[0] == '1') && ((source[1] == '0') || (source[1] == '1') || (source[1] == '7')) && (strlen(source) > 8)) { + /* Source starts (10), (11) or (17) */ + encoding_method = 2; + } + + if((source[0] == '9') && (source[1] == '0')) { + /* Source starts (90) */ + encoding_method = 3; + } + + if(encoding_method == 1) { + concat(binary_string, "0"); + } + + if(encoding_method == 2) { + /* Encoding Method field "10" - date and lot number */ + + concat(binary_string, "10"); + + if(source[1] == '0') { + /* No date data */ + concat(binary_string, "11"); + read_posn = 2; + } else { + /* Production Date (11) or Expiration Date (17) */ + date_str[0] = source[2]; + date_str[1] = source[3]; + date_str[2] = '\0'; + group_val = atoi(date_str) * 384; + + date_str[0] = source[4]; + date_str[1] = source[5]; + group_val += (atoi(date_str) - 1) * 32; + + date_str[0] = source[6]; + date_str[1] = source[7]; + group_val += atoi(date_str); + + mask = 0x8000; + for(j = 0; j < 16; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + + if(source[1] == '1') { + /* Production Date AI 11 */ + concat(binary_string, "0"); + } else { + /* Expiration Date AI 17 */ + concat(binary_string, "1"); + } + read_posn = 8; + } + + if((source[read_posn] == '1') && (source[read_posn + 1] == '0')) { + /* Followed by AI 10 - strip this from general field */ + read_posn += 2; + } else { + /* An FNC1 character needs to be inserted in the general field */ + fnc1_latch = 1; + } + } + + if (encoding_method == 3) { + /* Encodation Method field of "11" - AI 90 */ + char ninety[strlen(source)], numeric_part[4]; + int alpha, alphanum, numeric, test1, test2, test3, next_ai_posn, test4; + int numeric_value, table3_letter, mask; + + /* "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.2.2) */ + + i = 0; + do { + ninety[i] = source[i + 2]; + i++; + } while ((source[i + 2] != '[') && ((i + 2) < strlen(source))); + ninety[i] = '\0'; + + /* Find out if the AI 90 data is alphabetic or numeric or both */ + + alpha = 0; + alphanum = 0; + numeric = 0; + + for(i = 0; i < strlen(ninety); i++) { + + if ((ninety[i] >= 'A') && (ninety[i] <= 'Z')) { + /* Character is alphabetic */ + alpha += 1; + } + + if ((ninety[i] >= '0') && (ninety[i] <= '9')) { + /* Character is numeric */ + numeric += 1; + } + + switch(ninety[i]) { + case '*': + case ',': + case '-': + case '.': + case '/': alphanum += 1; break; + } + + if (!(((ninety[i] >= '0') && (ninety[i] <= '9')) || ((ninety[i] >= 'A') && (ninety[i] <= 'Z')))) { + if((ninety[i] != '*') && (ninety[i] != ',') && (ninety[i] != '-') && (ninety[i] != '.') && (ninety[i] != '/')) { + /* An Invalid AI 90 character */ + strcpy(symbol->errtxt, "error: invalid AI 90 data"); + return ERROR_INVALID_DATA; + } + } + } + + /* must start with 0, 1, 2 or 3 digits followed by an uppercase character */ + test1 = -1; + for(i = 3; i >= 0; i--) { + if ((ninety[i] >= 'A') && (ninety[i] <= 'Z')) { + test1 = i; + } + } + + test2 = 0; + for(i = 0; i < test1; i++) { + if (!((ninety[i] >= '0') && (ninety[i] <= '9'))) { + test2 = 1; + } + } + + /* leading zeros are not permitted */ + test3 = 0; + if((test1 >= 1) && (ninety[0] == '0')) { test3 = 1; } + + if((test1 != -1) && (test2 != 1) && (test3 == 0)) { + /* Encodation method "11" can be used */ + concat(binary_string, "11"); + + numeric -= test1; + alpha --; + + /* Decide on numeric, alpha or alphanumeric mode */ + /* Alpha mode is a special mode for AI 90 */ + + if(alphanum > 0) { + /* Alphanumeric mode */ + concat(binary_string, "0"); + ai90_mode = 1; + } else { + if(alpha > numeric) { + /* Alphabetic mode */ + concat(binary_string, "11"); + ai90_mode = 2; + } else { + /* Numeric mode */ + concat(binary_string, "10"); + ai90_mode = 3; + } + } + + next_ai_posn = 2 + strlen(ninety); + + if(source[next_ai_posn] == '[') { + /* There are more AIs afterwords */ + if((source[next_ai_posn + 1] == '2') && (source[next_ai_posn + 2] == '1')) { + /* AI 21 follows */ + ai_crop = 1; + ai_crop_posn = next_ai_posn + 1; + } + + if((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 = 2; + ai_crop_posn = next_ai_posn + 1; + } + } + + switch(ai_crop) { + case 0: concat(binary_string, "0"); break; + case 1: concat(binary_string, "10"); break; + case 2: concat(binary_string, "11"); break; + } + + if(test1 == 0) { + strcpy(numeric_part, "0"); + } else { + for(i = 0; i < test1; i++) { + numeric_part[i] = ninety[i]; + } + numeric_part[i] = '\0'; + } + + numeric_value = atoi(numeric_part); + + table3_letter = -1; + if(numeric_value < 31) { + switch(ninety[test1]) { + case 'B': table3_letter = 0; break; + case 'D': table3_letter = 1; break; + case 'H': table3_letter = 2; break; + case 'I': table3_letter = 3; break; + case 'J': table3_letter = 4; break; + case 'K': table3_letter = 5; break; + case 'L': table3_letter = 6; break; + case 'N': table3_letter = 7; break; + case 'P': table3_letter = 8; break; + case 'Q': table3_letter = 9; break; + case 'R': table3_letter = 10; break; + case 'S': table3_letter = 11; break; + case 'T': table3_letter = 12; break; + case 'V': table3_letter = 13; break; + case 'W': table3_letter = 14; break; + case 'Z': table3_letter = 15; break; + } + } + + if(table3_letter != -1) { + /* Encoding can be done according to 5.2.2 c) 2) */ + /* five bit binary string representing value before letter */ + mask = 0x10; + for(j = 0; j < 5; j++) { + if((numeric_value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + + /* followed by four bit representation of letter from Table 3 */ + mask = 0x08; + for(j = 0; j < 4; j++) { + if((table3_letter & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } else { + /* Encoding is done according to 5.2.2 c) 3) */ + concat(binary_string, "11111"); + /* ten bit representation of number */ + mask = 0x200; + for(j = 0; j < 10; j++) { + if((numeric_value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + + /* five bit representation of ASCII character */ + mask = 0x10; + for(j = 0; j < 5; j++) { + if(((ninety[test1] - 65) & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + read_posn = test1 + 3; + } else { + /* Use general field encodation instead */ + concat(binary_string, "0"); + read_posn = 0; + } + } + + /* Now encode the rest of the AI 90 data field */ + if(ai90_mode == 2) { + /* Alpha encodation (section 5.2.3) */ + do { + if((source[read_posn] >= '0') && (source[read_posn] <= '9')) { + mask = 0x10; + for(j = 0; j < 5; j++) { + if(((source[read_posn] + 4) & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if((source[read_posn] >= 'A') && (source[read_posn] <= 'Z')) { + mask = 0x20; + for(j = 0; j < 6; j++) { + if(((source[read_posn] - 65) & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if(source[read_posn] == '[') { + concat(binary_string, "11111"); + } + + read_posn++; + } while ((source[read_posn - 1] != '[') && (source[read_posn - 1] != '\0')); + alpha_pad = 1; /* This is overwritten if a general field is encoded */ + } + + if(ai90_mode == 1) { + /* Alphanumeric mode */ + do { + if((source[read_posn] >= '0') && (source[read_posn] <= '9')) { + mask = 0x10; + for(j = 0; j < 5; j++) { + if(((source[read_posn] - 43) & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if((source[read_posn] >= 'A') && (source[read_posn] <= 'Z')) { + mask = 0x20; + for(j = 0; j < 6; j++) { + if(((source[read_posn] - 33) & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + switch(source[read_posn]) { + case '[': concat(binary_string, "01111"); break; + case '*': concat(binary_string, "111010"); break; + case ',': concat(binary_string, "111011"); break; + case '-': concat(binary_string, "111100"); break; + case '.': concat(binary_string, "111101"); break; + case '/': concat(binary_string, "111110"); break; + } + + read_posn++; + } while ((source[read_posn - 1] != '[') && (source[read_posn - 1] != '\0')); + } + + read_posn += (2 * ai_crop); + + /* 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] = '['; + j++; + } + + for(i = read_posn; i < strlen(source); i++) { + general_field[j] = source[i]; + j++; + } + general_field[j] = '\0'; + + if(strlen(general_field) != 0) { alpha_pad = 0; } + + latch = 0; + for(i = 0; i < strlen(general_field); i++) { + /* Table 13 - ISO/IEC 646 encodation */ + if((general_field[i] < ' ') || (general_field[i] > 'z')) { + general_field_type[i] = INVALID_CHAR; latch = 1; + } else { + general_field_type[i] = ISOIEC; + } + + if(general_field[i] == '#') { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + if(general_field[i] == '$') { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + if(general_field[i] == '@') { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + if(general_field[i] == 92) { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + if(general_field[i] == '^') { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + if(general_field[i] == 96) { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + + /* Table 12 - Alphanumeric encodation */ + if((general_field[i] >= 'A') && (general_field[i] <= 'Z')) { + general_field_type[i] = ALPHA_OR_ISO; + } + if(general_field[i] == '*') { + general_field_type[i] = ALPHA_OR_ISO; + } + if(general_field[i] == ',') { + general_field_type[i] = ALPHA_OR_ISO; + } + if(general_field[i] == '-') { + general_field_type[i] = ALPHA_OR_ISO; + } + if(general_field[i] == '.') { + general_field_type[i] = ALPHA_OR_ISO; + } + if(general_field[i] == '/') { + general_field_type[i] = ALPHA_OR_ISO; + } + + /* Numeric encodation */ + if((general_field[i] >= '0') && (general_field[i] <= '9')) { + general_field_type[i] = ANY_ENC; + } + if(general_field[i] == '[') { + /* FNC1 can be encoded in any system */ + general_field_type[i] = ANY_ENC; + } + + } + + general_field_type[strlen(general_field)] = '\0'; + + if(latch == 1) { + /* Invalid characters in input data */ + strcpy(symbol->errtxt, "Invalid characters in input data"); + return ERROR_INVALID_DATA; + } + + for(i = 0; i < strlen(general_field); i++) { + if((general_field_type[i] == ISOIEC) && (general_field[i + 1] == '[')) { + general_field_type[i + 1] = ISOIEC; + } + } + + for(i = 0; i < strlen(general_field); i++) { + if((general_field_type[i] == ALPHA_OR_ISO) && (general_field[i + 1] == '[')) { + general_field_type[i + 1] = ALPHA_OR_ISO; + } + } + + latch = general_rules(general_field, general_field_type); + + i = 0; + do { + switch(general_field_type[i]) { + case NUMERIC: + + if(i != 0) { + if((general_field_type[i - 1] != NUMERIC) && (general_field[i - 1] != '[')) { + concat(binary_string, "000"); /* Numeric latch */ + } + } + + if(general_field[i] != '[') { + d1 = ctoi(general_field[i]); + } else { + d1 = 10; + } + + if(general_field[i + 1] != '[') { + d2 = ctoi(general_field[i + 1]); + } else { + d2 = 10; + } + + value = (11 * d1) + d2 + 8; + + mask = 0x40; + for(j = 0; j < 7; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + + i += 2; + break; + + case ALPHA: + + if(i != 0) { + if((general_field_type[i - 1] == NUMERIC) || (general_field[i - 1] == '[')) { + concat(binary_string, "0000"); /* Alphanumeric latch */ + } + if(general_field_type[i - 1] == ISOIEC) { + concat(binary_string, "00100"); /* ISO/IEC 646 latch */ + } + } + + if((general_field[i] >= '0') && (general_field[i] <= '9')) { + + value = general_field[i] - 43; + + mask = 0x10; + for(j = 0; j < 5; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if((general_field[i] >= 'A') && (general_field[i] <= 'Z')) { + + value = general_field[i] - 33; + + mask = 0x20; + for(j = 0; j < 6; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if(general_field[i] == '[') concat(binary_string, "01111"); /* FNC1/Numeric latch */ + if(general_field[i] == '*') concat(binary_string, "111010"); /* asterisk */ + if(general_field[i] == ',') concat(binary_string, "111011"); /* comma */ + if(general_field[i] == '-') concat(binary_string, "111100"); /* minus or hyphen */ + if(general_field[i] == '.') concat(binary_string, "111101"); /* period or full stop */ + if(general_field[i] == '/') concat(binary_string, "111110"); /* slash or solidus */ + + i++; + break; + + case ISOIEC: + + if(i != 0) { + if((general_field_type[i - 1] == NUMERIC) || (general_field[i - 1] == '[')) { + concat(binary_string, "0000"); /* Alphanumeric latch */ + concat(binary_string, "00100"); /* ISO/IEC 646 latch */ + } + if(general_field_type[i - 1] == ALPHA) { + concat(binary_string, "00100"); /* ISO/IEC 646 latch */ + } + } + + if((general_field[i] >= '0') && (general_field[i] <= '9')) { + + value = general_field[i] - 43; + + mask = 0x10; + for(j = 0; j < 5; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if((general_field[i] >= 'A') && (general_field[i] <= 'Z')) { + + value = general_field[i] - 1; + + mask = 0x40; + for(j = 0; j < 7; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if((general_field[i] >= 'a') && (general_field[i] <= 'z')) { + + value = general_field[i] - 7; + + mask = 0x40; + for(j = 0; j < 7; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if(general_field[i] == '[') concat(binary_string, "01111"); /* FNC1/Numeric latch */ + if(general_field[i] == '!') concat(binary_string, "11101000"); /* exclamation mark */ + if(general_field[i] == 34) concat(binary_string, "11101001"); /* quotation mark */ + if(general_field[i] == 37) concat(binary_string, "11101010"); /* percent sign */ + if(general_field[i] == '&') concat(binary_string, "11101011"); /* ampersand */ + if(general_field[i] == 39) concat(binary_string, "11101100"); /* apostrophe */ + if(general_field[i] == '(') concat(binary_string, "11101101"); /* left parenthesis */ + if(general_field[i] == ')') concat(binary_string, "11101110"); /* right parenthesis */ + if(general_field[i] == '*') concat(binary_string, "11101111"); /* asterisk */ + if(general_field[i] == '+') concat(binary_string, "11110000"); /* plus sign */ + if(general_field[i] == ',') concat(binary_string, "11110001"); /* comma */ + if(general_field[i] == '-') concat(binary_string, "11110010"); /* minus or hyphen */ + if(general_field[i] == '.') concat(binary_string, "11110011"); /* period or full stop */ + if(general_field[i] == '/') concat(binary_string, "11110100"); /* slash or solidus */ + if(general_field[i] == ':') concat(binary_string, "11110101"); /* colon */ + if(general_field[i] == ';') concat(binary_string, "11110110"); /* semicolon */ + if(general_field[i] == '<') concat(binary_string, "11110111"); /* less-than sign */ + if(general_field[i] == '=') concat(binary_string, "11111000"); /* equals sign */ + if(general_field[i] == '>') concat(binary_string, "11111001"); /* greater-than sign */ + if(general_field[i] == '?') concat(binary_string, "11111010"); /* question mark */ + if(general_field[i] == '_') concat(binary_string, "11111011"); /* underline or low line */ + if(general_field[i] == ' ') concat(binary_string, "11111100"); /* space */ + + i++; + break; + } + } while (i + latch < strlen(general_field)); + + if(cc_mode == 1) { + /* CC-A 2D component - calculate remaining space */ + switch(*(cc_width)) { + case 2: + if(strlen(binary_string) > 167) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 167) { target_bitsize = 167; } + if(strlen(binary_string) <= 138) { target_bitsize = 138; } + if(strlen(binary_string) <= 118) { target_bitsize = 118; } + if(strlen(binary_string) <= 108) { target_bitsize = 108; } + if(strlen(binary_string) <= 88) { target_bitsize = 88; } + if(strlen(binary_string) <= 78) { target_bitsize = 78; } + if(strlen(binary_string) <= 59) { target_bitsize = 59; } + break; + case 3: + if(strlen(binary_string) > 167) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 167) { target_bitsize = 167; } + if(strlen(binary_string) <= 138) { target_bitsize = 138; } + if(strlen(binary_string) <= 118) { target_bitsize = 118; } + if(strlen(binary_string) <= 98) { target_bitsize = 98; } + if(strlen(binary_string) <= 78) { target_bitsize = 78; } + break; + case 4: + if(strlen(binary_string) > 197) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 197) { target_bitsize = 197; } + if(strlen(binary_string) <= 167) { target_bitsize = 167; } + if(strlen(binary_string) <= 138) { target_bitsize = 138; } + if(strlen(binary_string) <= 108) { target_bitsize = 108; } + if(strlen(binary_string) <= 78) { target_bitsize = 78; } + break; + } + } + + if(cc_mode == 2) { + /* CC-B 2D component - calculated from ISO/IEC 24728 Table 1 */ + switch(*(cc_width)) { + case 2: + if(strlen(binary_string) > 336) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 336) { target_bitsize = 336; } + if(strlen(binary_string) <= 296) { target_bitsize = 296; } + if(strlen(binary_string) <= 256) { target_bitsize = 256; } + if(strlen(binary_string) <= 208) { target_bitsize = 208; } + if(strlen(binary_string) <= 160) { target_bitsize = 160; } + if(strlen(binary_string) <= 104) { target_bitsize = 104; } + if(strlen(binary_string) <= 56) { target_bitsize = 56; } + break; + case 3: + if(strlen(binary_string) > 768) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 768) { target_bitsize = 768; } + if(strlen(binary_string) <= 648) { target_bitsize = 648; } + if(strlen(binary_string) <= 536) { target_bitsize = 536; } + if(strlen(binary_string) <= 416) { target_bitsize = 416; } + if(strlen(binary_string) <= 304) { target_bitsize = 304; } + if(strlen(binary_string) <= 208) { target_bitsize = 208; } + if(strlen(binary_string) <= 152) { target_bitsize = 152; } + if(strlen(binary_string) <= 112) { target_bitsize = 112; } + if(strlen(binary_string) <= 72) { target_bitsize = 72; } + if(strlen(binary_string) <= 32) { target_bitsize = 32; } + break; + case 4: + if(strlen(binary_string) > 1184) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 1184) { target_bitsize = 1184; } + if(strlen(binary_string) <= 1016) { target_bitsize = 1016; } + if(strlen(binary_string) <= 840) { target_bitsize = 840; } + if(strlen(binary_string) <= 672) { target_bitsize = 672; } + if(strlen(binary_string) <= 496) { target_bitsize = 496; } + if(strlen(binary_string) <= 352) { target_bitsize = 352; } + if(strlen(binary_string) <= 264) { target_bitsize = 264; } + if(strlen(binary_string) <= 208) { target_bitsize = 208; } + if(strlen(binary_string) <= 152) { target_bitsize = 152; } + if(strlen(binary_string) <= 96) { target_bitsize = 96; } + if(strlen(binary_string) <= 56) { target_bitsize = 56; } + break; + } + } + + if (cc_mode == 3) { + /* CC-C 2D Component is a bit more complex! */ + int byte_length, codewords_used, ecc_level, ecc_codewords, rows; + int codewords_total, target_codewords, target_bytesize; + + byte_length = strlen(binary_string) / 8; + if(strlen(binary_string) % 8 != 0) { byte_length++; } + + codewords_used = (byte_length / 6) * 5; + codewords_used += byte_length % 6; + + ecc_level = 7; + if(codewords_used <= 1280) { ecc_level = 6; } + if(codewords_used <= 640) { ecc_level = 5; } + if(codewords_used <= 320) { ecc_level = 4; } + if(codewords_used <= 160) { ecc_level = 3; } + if(codewords_used <= 40) { ecc_level = 2; } + *(ecc) = ecc_level; + ecc_codewords = 1; + for(i = 1; i <= (ecc_level + 1); i++){ + ecc_codewords *= 2; + } + + codewords_used += ecc_codewords; + codewords_used += 3; + + if(codewords_used > PDF_MAX) { + return ERROR_TOO_LONG; + } + /* *(cc_width) = 0.5 + sqrt((codewords_used) / 3); */ + *(cc_width) = (lin_width - 62) / 17; + if((codewords_used / *(cc_width)) > 90) { + /* stop the symbol from becoming too high */ + *(cc_width) = *(cc_width) + 1; + } + + rows = codewords_used / *(cc_width); + if(codewords_used % *(cc_width) != 0) { + rows++; + } + + codewords_total = *(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; + } + + remainder = strlen(binary_string) - target_bitsize; + + if(latch == 1) { + i = 0; + /* There is still one more numeric digit to encode */ + + if((remainder >= 4) && (remainder <= 6)) { + d1 = ctoi(general_field[i]); + d1++; + + mask = 0x08; + for(j = 0; j < 4; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } else { + d1 = ctoi(general_field[i]); + d2 = 10; + + value = (11 * d1) + d2 + 8; + + mask = 0x40; + for(j = 0; j < 7; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + /* This may push the symbol up to the next size */ + } + } + + if(strlen(binary_string) > 11805) { /* (2361 * 5) */ + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + /* all the code below is repeated from above - it needs to be calculated again because the + size of the symbol may have changed when adding data in the above sequence */ + + if(cc_mode == 1) { + /* CC-A 2D component - calculate padding required */ + switch(*(cc_width)) { + case 2: + if(strlen(binary_string) > 167) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 167) { target_bitsize = 167; } + if(strlen(binary_string) <= 138) { target_bitsize = 138; } + if(strlen(binary_string) <= 118) { target_bitsize = 118; } + if(strlen(binary_string) <= 108) { target_bitsize = 108; } + if(strlen(binary_string) <= 88) { target_bitsize = 88; } + if(strlen(binary_string) <= 78) { target_bitsize = 78; } + if(strlen(binary_string) <= 59) { target_bitsize = 59; } + break; + case 3: + if(strlen(binary_string) > 167) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 167) { target_bitsize = 167; } + if(strlen(binary_string) <= 138) { target_bitsize = 138; } + if(strlen(binary_string) <= 118) { target_bitsize = 118; } + if(strlen(binary_string) <= 98) { target_bitsize = 98; } + if(strlen(binary_string) <= 78) { target_bitsize = 78; } + break; + case 4: + if(strlen(binary_string) > 197) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 197) { target_bitsize = 197; } + if(strlen(binary_string) <= 167) { target_bitsize = 167; } + if(strlen(binary_string) <= 138) { target_bitsize = 138; } + if(strlen(binary_string) <= 108) { target_bitsize = 108; } + if(strlen(binary_string) <= 78) { target_bitsize = 78; } + break; + } + } + + if(cc_mode == 2) { + /* CC-B 2D component */ + switch(*(cc_width)) { + case 2: + if(strlen(binary_string) > 336) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 336) { target_bitsize = 336; } + if(strlen(binary_string) <= 296) { target_bitsize = 296; } + if(strlen(binary_string) <= 256) { target_bitsize = 256; } + if(strlen(binary_string) <= 208) { target_bitsize = 208; } + if(strlen(binary_string) <= 160) { target_bitsize = 160; } + if(strlen(binary_string) <= 104) { target_bitsize = 104; } + if(strlen(binary_string) <= 56) { target_bitsize = 56; } + break; + case 3: + if(strlen(binary_string) > 768) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 768) { target_bitsize = 768; } + if(strlen(binary_string) <= 648) { target_bitsize = 648; } + if(strlen(binary_string) <= 536) { target_bitsize = 536; } + if(strlen(binary_string) <= 416) { target_bitsize = 416; } + if(strlen(binary_string) <= 304) { target_bitsize = 304; } + if(strlen(binary_string) <= 208) { target_bitsize = 208; } + if(strlen(binary_string) <= 152) { target_bitsize = 152; } + if(strlen(binary_string) <= 112) { target_bitsize = 112; } + if(strlen(binary_string) <= 72) { target_bitsize = 72; } + if(strlen(binary_string) <= 32) { target_bitsize = 32; } + break; + case 4: + if(strlen(binary_string) > 1184) { return ERROR_TOO_LONG; } + if(strlen(binary_string) <= 1184) { target_bitsize = 1184; } + if(strlen(binary_string) <= 1016) { target_bitsize = 1016; } + if(strlen(binary_string) <= 840) { target_bitsize = 840; } + if(strlen(binary_string) <= 672) { target_bitsize = 672; } + if(strlen(binary_string) <= 496) { target_bitsize = 496; } + if(strlen(binary_string) <= 352) { target_bitsize = 352; } + if(strlen(binary_string) <= 264) { target_bitsize = 264; } + if(strlen(binary_string) <= 208) { target_bitsize = 208; } + if(strlen(binary_string) <= 152) { target_bitsize = 152; } + if(strlen(binary_string) <= 96) { target_bitsize = 96; } + if(strlen(binary_string) <= 56) { target_bitsize = 56; } + break; + } + } + + if (cc_mode == 3) { + /* CC-C 2D Component is a bit more complex! */ + int byte_length, codewords_used, ecc_level, ecc_codewords, rows; + int codewords_total, target_codewords, target_bytesize; + + byte_length = strlen(binary_string) / 8; + if(strlen(binary_string) % 8 != 0) { byte_length++; } + + codewords_used = (byte_length / 6) * 5; + codewords_used += byte_length % 6; + + ecc_level = 7; + if(codewords_used <= 1280) { ecc_level = 6; } + if(codewords_used <= 640) { ecc_level = 5; } + if(codewords_used <= 320) { ecc_level = 4; } + if(codewords_used <= 160) { ecc_level = 3; } + if(codewords_used <= 40) { ecc_level = 2; } + *(ecc) = ecc_level; + ecc_codewords = 1; + for(i = 1; i <= (ecc_level + 1); i++){ + ecc_codewords *= 2; + } + + codewords_used += ecc_codewords; + codewords_used += 3; + + if(codewords_used > PDF_MAX) { + return ERROR_TOO_LONG; + } + /* *(cc_width) = 0.5 + sqrt((codewords_used) / 3); */ + *(cc_width) = (lin_width - 62) / 17; + if((codewords_used / *(cc_width)) > 90) { + /* stop the symbol from becoming too high */ + *(cc_width) = *(cc_width) + 1; + } + + rows = codewords_used / *(cc_width); + if(codewords_used % *(cc_width) != 0) { + rows++; + } + + codewords_total = *(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; + } + + if(strlen(binary_string) < target_bitsize) { + /* Now add padding to binary string */ + if (alpha_pad == 1) { + concat(binary_string, "11111"); + alpha_pad = 0; + /* Extra FNC1 character required after Alpha encodation (section 5.2.3) */ + } + + if ((strlen(general_field) != 0) && (general_field_type[strlen(general_field) - 1] == NUMERIC)) { + concat(binary_string, "0000"); + } + + while (strlen(binary_string) < target_bitsize) { + concat(binary_string, "00100"); + } + + if(strlen(binary_string) > target_bitsize) { + binary_string[target_bitsize] = '\0'; + } + } + + return 0; +} + +int composite(struct zint_symbol *symbol, unsigned char source[]) +{ + int errno, cc_mode, cc_width, ecc_level; + int j, last_ai, ai_latch, i, k, separator_row; + char reduced[3000], binary_string[10 * strlen(source)], ai_string[4]; + struct zint_symbol *linear; + int top_shift, bottom_shift; + + errno = 0; + separator_row = 0; + + if(strlen(symbol->primary) == 0) { + strcpy(symbol->errtxt, "error: No primary (linear) message in 2D composite"); + return ERROR_INVALID_OPTION; + } + + if(strlen(source) > 2990) { + strcpy(symbol->errtxt, "error: 2D component input data too long"); + return ERROR_TOO_LONG; + } + + if(source[0] != '[') { + strcpy(symbol->errtxt, "Data does not start with an AI"); + return ERROR_INVALID_DATA; + } + + for(i = 0; i < strlen(source) - 1; i++) { + if((source[i] == '[') && (source[i + 1] == '[')) { + /* Can't have nested brackets - Quit */ + strcpy(symbol->errtxt, "Nested AI detected (two or more open brackets)"); + return ERROR_INVALID_DATA; + } + } + + for(i = 0; i < strlen(source) - 1; i++) { + if((source[i] == ']') && (source[i + 1] == ']')) { + /* Can't have nested brackets - Quit */ + strcpy(symbol->errtxt, "Nested AI detected (two or more close brackets)"); + return ERROR_INVALID_DATA; + } + } + + linear = ZBarcode_Create(); /* Symbol contains the 2D component and Linear contains the rest */ + + /* Resolve AI data - put resulting string in 'reduced' */ + j = 0; + last_ai = 0; + ai_latch = 1; + for(i = 0; i < strlen(source); i++) { + if((source[i] != '[') && (source[i] != ']')) { + reduced[j] = source[i]; + j++; + } + if(source[i] == '[') { + /* Start of an AI string */ + if(ai_latch == 0) { + reduced[j] = '['; + j++; + } + ai_string[0] = source[i + 1]; + ai_string[1] = source[i + 2]; + ai_string[2] = '\0'; + last_ai = atoi(ai_string); + ai_latch = 0; + /* The following values from GS1 specification figure 5.3.8.2.1 - 1 + "Element Strings with Pre-Defined Length Using Application Identifiers" */ + if((last_ai >= 0) && (last_ai <= 4)) { ai_latch = 1; } + if((last_ai >= 11) && (last_ai <= 20)) { ai_latch = 1; } + if(last_ai == 23) { ai_latch = 1; } /* legacy support - see 5.3.8.2.2 */ + if((last_ai >= 31) && (last_ai <= 36)) { ai_latch = 1; } + if(last_ai == 41) { ai_latch = 1; } + } + /* The ']' character is simply dropped from the input */ + } + reduced[j] = '\0'; + + /* Note that no attempt is made to verify that the data to be encoded does + actually conform to the right data length - that is required of the person or + program inputting the data */ + + cc_mode = symbol->option_1; + + if((cc_mode == 3) && (symbol->symbology != BARCODE_EAN128_CC)) { + /* CC-C can only be used with a GS1-128 linear part */ + strcpy(symbol->errtxt, "Invalid mode (CC-C only valid with GS1-128 linear component)"); + return ERROR_INVALID_OPTION; + } + + linear->symbology = symbol->symbology; + + if(linear->symbology != BARCODE_EAN128_CC) { + /* Set the "component linkage" flag in the linear component */ + linear->option_1 = 2; + } else { + /* GS1-128 needs to know which type of 2D component is used */ + linear->option_1 = cc_mode; + } + + switch(symbol->symbology) { + case BARCODE_EANX_CC: errno = eanx(linear, symbol->primary); break; + case BARCODE_EAN128_CC: errno = ean_128(linear, symbol->primary); break; + case BARCODE_RSS14_CC: errno = rss14(linear, symbol->primary); break; + case BARCODE_RSS_LTD_CC: errno = rsslimited(linear, symbol->primary); break; + case BARCODE_RSS_EXP_CC: errno = rssexpanded(linear, symbol->primary); break; + case BARCODE_UPCA_CC: errno = eanx(linear, symbol->primary); break; + case BARCODE_UPCE_CC: errno = eanx(linear, symbol->primary); break; + case BARCODE_RSS14STACK_CC: errno = rss14(linear, symbol->primary); break; + case BARCODE_RSS14_OMNI_CC: errno = rss14(linear, symbol->primary); break; + case BARCODE_RSS_EXPSTACK_CC: errno = rssexpanded(linear, symbol->primary); break; + } + + switch(symbol->symbology) { + /* Determine width of 2D component according to ISO/IEC 24723 Table 1 */ + case BARCODE_EANX_CC: + switch(strlen(symbol->primary)) { + case 7: /* EAN-8 */ + case 10: /* EAN-8 + 2 */ + case 13: /* EAN-8 + 5 */ + cc_width = 3; + break; + case 12: /* EAN-13 */ + case 15: /* EAN-13 + 2 */ + case 18: /* EAN-13 + 5 */ + cc_width = 4; + break; + } + break; + case BARCODE_EAN128_CC: cc_width = 4; break; + case BARCODE_RSS14_CC: cc_width = 4; break; + case BARCODE_RSS_LTD_CC: cc_width = 3; break; + case BARCODE_RSS_EXP_CC: cc_width = 4; break; + case BARCODE_UPCA_CC: cc_width = 4; break; + case BARCODE_UPCE_CC: cc_width = 2; break; + case BARCODE_RSS14STACK_CC: cc_width = 2; break; + case BARCODE_RSS14_OMNI_CC: cc_width = 2; break; + case BARCODE_RSS_EXPSTACK_CC: cc_width = 4; break; + } + + strcpy(binary_string, ""); + + if(errno != 0) { + return errno; + } + + if(cc_mode == 1) { + i = cc_binary_string(symbol, reduced, binary_string, cc_mode, &cc_width, &ecc_level, linear->width); + if (i == ERROR_TOO_LONG) { + cc_mode = 2; + } + } + + if(cc_mode == 2) { /* If the data didn't fit into CC-A it is recalculated for CC-B */ + i = cc_binary_string(symbol, reduced, binary_string, cc_mode, &cc_width, &ecc_level, linear->width); + if (i == ERROR_TOO_LONG) { + if(symbol->symbology != BARCODE_EAN128_CC) { + return ERROR_TOO_LONG; + } else { + cc_mode == 3; + } + } + } + + 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, reduced, binary_string, cc_mode, &cc_width, &ecc_level, linear->width); + if (i == ERROR_TOO_LONG) { + return ERROR_TOO_LONG; + } + } + + switch(cc_mode) { /* Note that ecc_level is only relevant to CC-C */ + case 1: errno = cc_a(symbol, binary_string, cc_width); break; + case 2: errno = cc_b(symbol, binary_string, cc_width); break; + case 3: errno = cc_c(symbol, binary_string, cc_width, ecc_level); break; + } + + if(errno != 0) { + return ERROR_ENCODING_PROBLEM; + } + + /* 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(strlen(symbol->primary)) { + case 7: /* EAN-8 */ + case 10: /* EAN-8 + 2 */ + case 13: /* EAN-8 + 5 */ + bottom_shift = 13; + break; + case 12: /* EAN-13 */ + case 15: /* EAN-13 + 2 */ + case 18: /* EAN-13 + 5 */ + bottom_shift = 2; + break; + } + break; + case BARCODE_EAN128_CC: if(cc_mode == 3) { + bottom_shift = 7; + } + break; + case BARCODE_RSS14_CC: bottom_shift = 4; break; + case BARCODE_RSS_LTD_CC: bottom_shift = 9; break; + case BARCODE_RSS_EXP_CC: k = 1; + while((linear->encoded_data[1][k - 1] != '1') && (linear->encoded_data[1][k] != '0')) { + k++; + } + top_shift = k; + break; + case BARCODE_UPCA_CC: bottom_shift = 2; break; + case BARCODE_UPCE_CC: bottom_shift = 2; break; + case BARCODE_RSS14STACK_CC: top_shift = 1; break; + case BARCODE_RSS14_OMNI_CC: top_shift = 1; break; + case BARCODE_RSS_EXPSTACK_CC: k = 1; + while((linear->encoded_data[1][k - 1] != '1') && (linear->encoded_data[1][k] != '0')) { + k++; + } + top_shift = k; + break; + } + + if(top_shift != 0) { + for(i = 0; i <= symbol->rows; i++) { + for(j = (symbol->width + top_shift); j >= top_shift; j--) { + symbol->encoded_data[i][j] = symbol->encoded_data[i][j - top_shift]; + } + for(j = 0; j < top_shift; j++) { + symbol->encoded_data[i][j] = 0; + } + } + } + + for(i = 0; i <= linear->rows; i++) { + symbol->row_height[symbol->rows + i] = linear->row_height[i]; + for(j = 0; j <= linear->width; j++) { + symbol->encoded_data[i + symbol->rows][j + bottom_shift] = linear->encoded_data[i][j]; + } + } + if((linear->width + bottom_shift) > symbol->width) { + symbol->width = linear->width + bottom_shift; + } + if((symbol->width + top_shift) > symbol->width) { + symbol->width += top_shift; + } + symbol->rows += linear->rows; + strcpy(symbol->text, linear->text); + + + ZBarcode_Delete(linear); + + return errno; +} diff --git a/backend/composite.h b/backend/composite.h new file mode 100644 index 00000000..34b4d84b --- /dev/null +++ b/backend/composite.h @@ -0,0 +1,62 @@ +/* composite.c - Tables for UCC.EAN Composite Symbols */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#define NUMERIC 110 +#define ALPHA 97 +#define ISOIEC 105 +#define INVALID_CHAR 100 +#define ANY_ENC 120 +#define ALPHA_OR_ISO 121 + +/* CC-A component coefficients from ISO/IEC 24728:2006 Annex F */ +static int ccaCoeffs[30] = { + /* k = 4 */ + 522, 568, 723, 809, + + /* k = 5 */ + 427, 919, 460, 155, 566, + + /* k = 6 */ + 861, 285, 19, 803, 17, 766, + + /* k = 7 */ + 76, 925, 537, 597, 784, 691, 437, + + /* k = 8 */ + 237, 308, 436, 284, 646, 653, 428, 379 +}; + +/* rows, error codewords, k-offset of valid CC-A sizes from ISO/IEC 24723:2006 Table 9 */ +static int ccaVariants[51] = { + 5, 6, 7, 8, 9, 10, 12, 4, 5, 6, 7, 8, 3, 4, 5, 6, 7, + 4, 4, 5, 5, 6, 6, 7, 4, 5, 6, 7, 7, 4, 5, 6, 7, 8, + 0, 0, 4, 4, 9, 9, 15, 0, 4, 9, 15, 15, 0, 4, 9, 15, 22 +}; + +/* following is Left RAP, Centre RAP, Right RAP and Start Cluster from ISO/IEC 24723:2006 tables 10 and 11 */ +static int aRAPTable[68] = { + 39, 1, 32, 8, 14, 43, 20, 11, 1, 5, 15, 21, 40, 43, 46, 34, 29, + 0, 0, 0, 0, 0, 0, 0, 43, 33, 37, 47, 1, 20, 23, 2, 14, 9, + 19, 33, 12, 40, 4, 23, 52, 23, 13, 17, 27, 33, 52, 3, 6, 46, 41, + 6, 0, 3, 3, 3, 0, 3, 3, 0, 3, 6, 6, 0, 0, 0, 0, 3 +}; + +/* Row Address Patterns are as defined in pdf417.h */ diff --git a/backend/dm200.c b/backend/dm200.c new file mode 100644 index 00000000..466bfadf --- /dev/null +++ b/backend/dm200.c @@ -0,0 +1,961 @@ +/** + * + * IEC16022 bar code generation + * Adrian Kennard, Andrews & Arnold Ltd + * with help from Cliff Hones on the RS coding + * + * (c) 2004 Adrian Kennard, Andrews & Arnold Ltd + * (c) 2006 Stefan Schmidt + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include +#include "reedsol.h" +#include "dm200.h" + +static struct ecc200matrix_s { + int H, W; + int FH, FW; + int bytes; + int datablock, rsblock; +} ecc200matrix[] = { + 10, 10, 10, 10, 3, 3, 5, // + 12, 12, 12, 12, 5, 5, 7, // + 8, 18, 8, 18, 5, 5, 7, // + 14, 14, 14, 14, 8, 8, 10, // + 8, 32, 8, 16, 10, 10, 11, // + 16, 16, 16, 16, 12, 12, 12, // + 12, 26, 12, 26, 16, 16, 14, // + 18, 18, 18, 18, 18, 18, 14, // + 20, 20, 20, 20, 22, 22, 18, // + 12, 36, 12, 18, 22, 22, 18, // + 22, 22, 22, 22, 30, 30, 20, // + 16, 36, 16, 18, 32, 32, 24, // + 24, 24, 24, 24, 36, 36, 24, // + 26, 26, 26, 26, 44, 44, 28, // + 16, 48, 16, 24, 49, 49, 28, // + 32, 32, 16, 16, 62, 62, 36, // + 36, 36, 18, 18, 86, 86, 42, // + 40, 40, 20, 20, 114, 114, 48, // + 44, 44, 22, 22, 144, 144, 56, // + 48, 48, 24, 24, 174, 174, 68, // + 52, 52, 26, 26, 204, 102, 42, // + 64, 64, 16, 16, 280, 140, 56, // + 72, 72, 18, 18, 368, 92, 36, // + 80, 80, 20, 20, 456, 114, 48, // + 88, 88, 22, 22, 576, 144, 56, // + 96, 96, 24, 24, 696, 174, 68, // + 104, 104, 26, 26, 816, 136, 56, // + 120, 120, 20, 20, 1050, 175, 68, // + 132, 132, 22, 22, 1304, 163, 62, // + 144, 144, 24, 24, 1558, 156, 62, // 156*4+155*2 + 0 // terminate +}; + + // simple checked response malloc +static void *safemalloc(int n) +{ + void *p = malloc(n); + if (!p) { + fprintf(stderr, "Malloc(%d) failed\n", n); + exit(1); + } + return p; +} + +// Annex M placement alorithm low level +static void ecc200placementbit(int *array, int NR, int NC, int r, int c, + int p, char b) +{ + if (r < 0) { + r += NR; + c += 4 - ((NR + 4) % 8); + } + if (c < 0) { + c += NC; + r += 4 - ((NC + 4) % 8); + } + array[r * NC + c] = (p << 3) + b; +} + +static void ecc200placementblock(int *array, int NR, int NC, int r, + int c, int p) +{ + ecc200placementbit(array, NR, NC, r - 2, c - 2, p, 7); + ecc200placementbit(array, NR, NC, r - 2, c - 1, p, 6); + ecc200placementbit(array, NR, NC, r - 1, c - 2, p, 5); + ecc200placementbit(array, NR, NC, r - 1, c - 1, p, 4); + ecc200placementbit(array, NR, NC, r - 1, c - 0, p, 3); + ecc200placementbit(array, NR, NC, r - 0, c - 2, p, 2); + ecc200placementbit(array, NR, NC, r - 0, c - 1, p, 1); + ecc200placementbit(array, NR, NC, r - 0, c - 0, p, 0); +} + +static void ecc200placementcornerA(int *array, int NR, int NC, int p) +{ + ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7); + ecc200placementbit(array, NR, NC, NR - 1, 1, p, 6); + ecc200placementbit(array, NR, NC, NR - 1, 2, p, 5); + ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4); + ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3); + ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2); + ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1); + ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0); +} + +static void ecc200placementcornerB(int *array, int NR, int NC, int p) +{ + ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7); + ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6); + ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5); + ecc200placementbit(array, NR, NC, 0, NC - 4, p, 4); + ecc200placementbit(array, NR, NC, 0, NC - 3, p, 3); + ecc200placementbit(array, NR, NC, 0, NC - 2, p, 2); + ecc200placementbit(array, NR, NC, 0, NC - 1, p, 1); + ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0); +} + +static void ecc200placementcornerC(int *array, int NR, int NC, int p) +{ + ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7); + ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6); + ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5); + ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4); + ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3); + ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2); + ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1); + ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0); +} + +static void ecc200placementcornerD(int *array, int NR, int NC, int p) +{ + ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7); + ecc200placementbit(array, NR, NC, NR - 1, NC - 1, p, 6); + ecc200placementbit(array, NR, NC, 0, NC - 3, p, 5); + ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4); + ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3); + ecc200placementbit(array, NR, NC, 1, NC - 3, p, 2); + ecc200placementbit(array, NR, NC, 1, NC - 2, p, 1); + ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0); +} + +// Annex M placement alorithm main function +static void ecc200placement(int *array, int NR, int NC) +{ + int r, c, p; + // invalidate + for (r = 0; r < NR; r++) + for (c = 0; c < NC; c++) + array[r * NC + c] = 0; + // start + p = 1; + r = 4; + c = 0; + do { + // check corner + if (r == NR && !c) + ecc200placementcornerA(array, NR, NC, p++); + if (r == NR - 2 && !c && NC % 4) + ecc200placementcornerB(array, NR, NC, p++); + if (r == NR - 2 && !c && (NC % 8) == 4) + ecc200placementcornerC(array, NR, NC, p++); + if (r == NR + 4 && c == 2 && !(NC % 8)) + ecc200placementcornerD(array, NR, NC, p++); + // up/right + do { + if (r < NR && c >= 0 && !array[r * NC + c]) + ecc200placementblock(array, NR, NC, r, c, p++); + r -= 2; + c += 2; + } + while (r >= 0 && c < NC); + r++; + c += 3; + // down/left + do { + if (r >= 0 && c < NC && !array[r * NC + c]) + ecc200placementblock(array, NR, NC, r, c, p++); + r += 2; + c -= 2; + } + while (r < NR && c >= 0); + r += 3; + c++; + } + while (r < NR || c < NC); + // unfilled corner + if (!array[NR * NC - 1]) + array[NR * NC - 1] = array[NR * NC - NC - 2] = 1; +} + +// calculate and append ecc code, and if necessary interleave +static void ecc200(unsigned char *binary, int bytes, int datablock, int rsblock) +{ + int blocks = (bytes + 2) / datablock, b; + rs_init_gf(0x12d); + rs_init_code(rsblock, 1); + for (b = 0; b < blocks; b++) { + unsigned char buf[256], ecc[256]; + int n, p = 0; + for (n = b; n < bytes; n += blocks) + buf[p++] = binary[n]; + rs_encode(p, buf, ecc); + p = rsblock - 1; // comes back reversed + for (n = b; n < rsblock * blocks; n += blocks) + binary[bytes + n] = ecc[p--]; + } +} + +/* + * perform encoding for ecc200, source s len sl, to target t len tl, using + * optional encoding control string e return 1 if OK, 0 if failed. Does all + * necessary padding to tl + */ + +char ecc200encode(unsigned char *t, int tl, unsigned char *s, int sl, + char *encoding, int *lenp) +{ + char enc = 'a'; // start in ASCII encoding mode + int tp = 0, sp = 0; + if (strlen(encoding) < sl) { + fprintf(stderr, "Encoding string too short\n"); + return 0; + } + // do the encoding + while (sp < sl && tp < tl) { + char newenc = enc; // suggest new encoding + if (tl - tp <= 1 && (enc == 'c' || enc == 't') || tl - tp <= 2 + && enc == 'x') + enc = 'a'; // auto revert to ASCII + newenc = tolower(encoding[sp]); + switch (newenc) { // encode character + case 'c': // C40 + case 't': // Text + case 'x': // X12 + { + char out[6], p = 0; + const char *e, + *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]_", + *s3 = 0; + if (newenc == 'c') { + e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + s3 = "`abcdefghijklmnopqrstuvwxyz{|}~\177"; + } + if (newenc == 't') { + e = " 0123456789abcdefghijklmnopqrstuvwxyz"; + s3 = "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\177"; + } + if (newenc == 'x') + e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\r*>"; + do { + unsigned char c = s[sp++]; + char *w; + if (c & 0x80) { + if (newenc == 'x') { + fprintf(stderr, + "Cannot encode char 0x%02X in X12\n", + c); + return 0; + } + c &= 0x7f; + out[p++] = 1; + out[p++] = 30; + } + w = strchr(e, c); + if (w) + out[p++] = ((w - e) + 3) % 40; + else { + if (newenc == 'x') { + fprintf(stderr, + "Cannot encode char 0x%02X in X12\n", + c); + return 0; + } + if (c < 32) { // shift 1 + out[p++] = 0; + out[p++] = c; + } else { + w = strchr(s2, c); + if (w) { // shift 2 + out[p++] = 1; + out[p++] = + (w - s2); + } else { + w = strchr(s3, + c); + if (w) { + out[p++] + = 2; + out[p++] + = + (w - + s3); + } else { + fprintf + (stderr, + "Could not encode 0x%02X, should \ + not happen\n", c); + return + 0; + } + } + } + } + if (p == 2 && tp + 2 == tl && sp == sl) + out[p++] = 0; // shift 1 pad at end + while (p >= 3) { + int v = + out[0] * 1600 + + out[1] * 40 + out[2] + 1; + if (enc != newenc) { + if (enc == 'c' + || enc == 't' + || enc == 'x') + t[tp++] = 254; // escape C40/text/X12 + else if (enc == 'x') + t[tp++] = 0x7C; // escape EDIFACT + if (newenc == 'c') + t[tp++] = 230; + if (newenc == 't') + t[tp++] = 239; + if (newenc == 'x') + t[tp++] = 238; + enc = newenc; + } + t[tp++] = (v >> 8); + t[tp++] = (v & 0xFF); + p -= 3; + out[0] = out[3]; + out[1] = out[4]; + out[2] = out[5]; + } + } + while (p && sp < sl); + } + break; + case 'e': // EDIFACT + { + unsigned char out[4], p = 0; + if (enc != newenc) { // can only be from C40/Text/X12 + t[tp++] = 254; + enc = 'a'; + } + while (sp < sl && tolower(encoding[sp]) == 'e' + && p < 4) + out[p++] = s[sp++]; + if (p < 4) { + out[p++] = 0x1F; + enc = 'a'; + } // termination + t[tp] = ((s[0] & 0x3F) << 2); + t[tp++] |= ((s[1] & 0x30) >> 4); + t[tp] = ((s[1] & 0x0F) << 4); + if (p == 2) + tp++; + else { + t[tp++] |= ((s[2] & 0x3C) >> 2); + t[tp] = ((s[2] & 0x03) << 6); + t[tp++] |= (s[3] & 0x3F); + } + } + break; + case 'a': // ASCII + if (enc != newenc) { + if (enc == 'c' || enc == 't' || enc == 'x') + t[tp++] = 254; // escape C40/text/X12 + else + t[tp++] = 0x7C; // escape EDIFACT + } + enc = 'a'; + if (sl - sp >= 2 && isdigit(s[sp]) + && isdigit(s[sp + 1])) { + t[tp++] = + (s[sp] - '0') * 10 + s[sp + 1] - '0' + 130; + sp += 2; + } else if (s[sp] > 127) { + t[tp++] = 235; + t[tp++] = s[sp++] - 127; + } else + t[tp++] = s[sp++] + 1; + break; + case 'b': // Binary + { + int l = 0; // how much to encode + if (encoding) { + int p; + for (p = sp; + p < sl + && tolower(encoding[p]) == 'b'; + p++) + l++; + } + t[tp++] = 231; // base256 + if (l < 250) + t[tp++] = l; + else { + t[tp++] = 249 + (l / 250); + t[tp++] = (l % 250); + } + while (l-- && tp < tl) { + t[tp] = s[sp++] + (((tp + 1) * 149) % 255) + 1; // see annex H + tp++; + } + enc = 'a'; // reverse to ASCII at end + } + break; + default: + fprintf(stderr, "Unknown encoding %c\n", newenc); + return 0; // failed + } + } + if (lenp) + *lenp = tp; + if (tp < tl && enc != 'a') { + if (enc == 'c' || enc == 'x' || enc == 't') + t[tp++] = 254; // escape X12/C40/Text + else + t[tp++] = 0x7C; // escape EDIFACT + } + if (tp < tl) + t[tp++] = 129; // pad + while (tp < tl) { // more padding + int v = 129 + (((tp + 1) * 149) % 253) + 1; // see Annex H + if (v > 254) + v -= 254; + t[tp++] = v; + } + if (tp > tl || sp < sl) + return 0; // did not fit + /* + * for (tp = 0; tp < tl; tp++) fprintf (stderr, "%02X ", t[tp]); \ + * fprintf (stderr, "\n"); + */ + return 1; // OK +} + +// Auto encoding format functions +static char encchr[] = "ACTXEB"; + +enum { + E_ASCII, + E_C40, + E_TEXT, + E_X12, + E_EDIFACT, + E_BINARY, + E_MAX +}; + +unsigned char switchcost[E_MAX][E_MAX] = { + 0, 1, 1, 1, 1, 2, // From E_ASCII + 1, 0, 2, 2, 2, 3, // From E_C40 + 1, 2, 0, 2, 2, 3, // From E_TEXT + 1, 2, 2, 0, 2, 3, // From E_X12 + 1, 2, 2, 2, 0, 3, // From E_EDIFACT + 0, 1, 1, 1, 1, 0, // From E_BINARY +}; + +/* + * Creates a encoding list (malloc) + * returns encoding string + * if lenp not null, target len stored + * if error, null returned + * if exact specified, then assumes shortcuts applicable for exact fit + * in target + * 1. No unlatch to return to ASCII for last encoded byte after C40 or + * Text or X12 + * 2. No unlatch to return to ASCII for last 1 or 2 encoded bytes after + * EDIFACT + * 3. Final C40 or text encoding exactly in last 2 bytes can have a shift + * 0 to pad to make a tripple + * Only use the encoding from an exact request if the len matches the target, + * otherwise free the result and try again with exact=0 + */ + +static char *encmake(int l, unsigned char *s, int *lenp, char exact) +{ + char *encoding = 0; + int p = l; + char e; + struct { + // number of bytes of source that can be encoded in a row at this point + // using this encoding mode + short s; + // number of bytes of target generated encoding from this point to end if + // already in this encoding mode + short t; + } enc[MAXBARCODE][E_MAX]; + memset(&enc, 0, sizeof(enc)); + if (!l) + return ""; // no length + if (l > MAXBARCODE) + return 0; // not valid + while (p--) { + char b = 0, sub; + int sl, tl, bl, t; + // consider each encoding from this point + // ASCII + sl = tl = 1; + if (isdigit(s[p]) && p + 1 < l && isdigit(s[p + 1])) + sl = 2; // double digit + else if (s[p] & 0x80) + tl = 2; // high shifted + bl = 0; + if (p + sl < l) + for (e = 0; e < E_MAX; e++) + if (enc[p + sl][e].t && ((t = enc[p + sl][e].t + + switchcost[E_ASCII] + [e]) < bl || !bl)) { + bl = t; + b = e; + } + enc[p][E_ASCII].t = tl + bl; + enc[p][E_ASCII].s = sl; + if (bl && b == E_ASCII) + enc[p][b].s += enc[p + sl][b].s; + // C40 + sub = tl = sl = 0; + do { + unsigned char c = s[p + sl++]; + if (c & 0x80) { // shift + upper + sub += 2; + c &= 0x7F; + } + if (c != ' ' && !isdigit(c) && !isupper(c)) + sub++; // shift + sub++; + while (sub >= 3) { + sub -= 3; + tl += 2; + } + } while (sub && p + sl < l); + if (exact && sub == 2 && p + sl == l) { + // special case, can encode last block with shift 0 at end (Is this + // valid when not end of target buffer?) + sub = 0; + tl += 2; + } + if (!sub) { // can encode C40 + bl = 0; + if (p + sl < l) + for (e = 0; e < E_MAX; e++) + if (enc[p + sl][e].t + && + ((t = + enc[p + sl][e].t + + switchcost[E_C40][e]) < bl + || !bl)) { + bl = t; + b = e; + } + if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) { + // special case, switch to ASCII for last bytes + bl = 1; + b = E_ASCII; + } + enc[p][E_C40].t = tl + bl; + enc[p][E_C40].s = sl; + if (bl && b == E_C40) + enc[p][b].s += enc[p + sl][b].s; + } + // Text + sub = tl = sl = 0; + do { + unsigned char c = s[p + sl++]; + if (c & 0x80) { // shift + upper + sub += 2; + c &= 0x7F; + } + if (c != ' ' && !isdigit(c) && !islower(c)) + sub++; // shift + sub++; + while (sub >= 3) { + sub -= 3; + tl += 2; + } + } while (sub && p + sl < l); + if (exact && sub == 2 && p + sl == l) { + // special case, can encode last block with shift 0 at end (Is this + // valid when not end of target buffer?) + sub = 0; + tl += 2; + } + if (!sub && sl) { // can encode Text + bl = 0; + if (p + sl < l) + for (e = 0; e < E_MAX; e++) + if (enc[p + sl][e].t + && + ((t = + enc[p + sl][e].t + + switchcost[E_TEXT][e]) < bl + || !bl)) { + bl = t; + b = e; + } + if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) { // special case, switch to ASCII for last bytes + bl = 1; + b = E_ASCII; + } + enc[p][E_TEXT].t = tl + bl; + enc[p][E_TEXT].s = sl; + if (bl && b == E_TEXT) + enc[p][b].s += enc[p + sl][b].s; + } + // X12 + sub = tl = sl = 0; + do { + unsigned char c = s[p + sl++]; + if (c != 13 && c != '*' && c != '>' && c != ' ' + && !isdigit(c) && !isupper(c)) { + sl = 0; + break; + } + sub++; + while (sub >= 3) { + sub -= 3; + tl += 2; + } + } while (sub && p + sl < l); + if (!sub && sl) { // can encode X12 + bl = 0; + if (p + sl < l) + for (e = 0; e < E_MAX; e++) + if (enc[p + sl][e].t + && + ((t = + enc[p + sl][e].t + + switchcost[E_X12][e]) < bl + || !bl)) { + bl = t; + b = e; + } + if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) { + // special case, switch to ASCII for last bytes + bl = 1; + b = E_ASCII; + } + enc[p][E_X12].t = tl + bl; + enc[p][E_X12].s = sl; + if (bl && b == E_X12) + enc[p][b].s += enc[p + sl][b].s; + } + // EDIFACT + sl = bl = 0; + if (s[p + 0] >= 32 && s[p + 0] <= 94) { // can encode 1 + char bs = 0; + if (p + 1 == l && (!bl || bl < 2)) { + bl = 2; + bs = 1; + } else + for (e = 0; e < E_MAX; e++) + if (e != E_EDIFACT && enc[p + 1][e].t + && + ((t = + 2 + enc[p + 1][e].t + + switchcost[E_ASCII][e]) + < bl || !bl)) // E_ASCII as allowed for unlatch + { + bs = 1; + bl = t; + b = e; + } + if (p + 1 < l && s[p + 1] >= 32 && s[p + 1] <= 94) { // can encode 2 + if (p + 2 == l && (!bl || bl < 2)) { + bl = 3; + bs = 2; + } else + for (e = 0; e < E_MAX; e++) + if (e != E_EDIFACT + && enc[p + 2][e].t + && + ((t = + 3 + enc[p + 2][e].t + + switchcost[E_ASCII][e]) + < bl || !bl)) // E_ASCII as allowed for unlatch + { + bs = 2; + bl = t; + b = e; + } + if (p + 2 < l && s[p + 2] >= 32 && s[p + 2] <= 94) { // can encode 3 + if (p + 3 == l && (!bl || bl < 3)) { + bl = 3; + bs = 3; + } else + for (e = 0; e < E_MAX; e++) + if (e != E_EDIFACT + && enc[p + 3][e].t + && + ((t = + 3 + enc[p + + 3][e].t + + switchcost + [E_ASCII][e]) + < bl || !bl)) // E_ASCII as allowed for unlatch + { + bs = 3; + bl = t; + b = e; + } + if (p + 4 < l && s[p + 3] >= 32 && s[p + 3] <= 94) { // can encode 4 + if (p + 4 == l + && (!bl || bl < 3)) { + bl = 3; + bs = 4; + } else { + for (e = 0; e < E_MAX; + e++) + if (enc[p + 4] + [e].t + && + ((t = + 3 + + enc[p + + 4][e]. + t + + switchcost + [E_EDIFACT] + [e]) < bl + || !bl)) { + bs = 4; + bl = t; + b = e; + } + if (exact + && enc[p + + 4][E_ASCII].t + && enc[p + + 4][E_ASCII]. + t <= 2 + && (t = + 3 + enc[p + + 4] + [E_ASCII].t) < + bl) { + // special case, switch to ASCII for last 1 ot two bytes + bs = 4; + bl = t; + b = E_ASCII; + } + } + } + } + } + enc[p][E_EDIFACT].t = bl; + enc[p][E_EDIFACT].s = bs; + if (bl && b == E_EDIFACT) + enc[p][b].s += enc[p + bs][b].s; + } + // Binary + bl = 0; + for (e = 0; e < E_MAX; e++) + if (enc[p + 1][e].t + && + ((t = + enc[p + 1][e].t + switchcost[E_BINARY][e] + + ((e == E_BINARY + && enc[p + 1][e].t == 249) ? 1 : 0)) + < bl || !bl)) { + bl = t; + b = e; + } + enc[p][E_BINARY].t = 1 + bl; + enc[p][E_BINARY].s = 1; + if (bl && b == E_BINARY) + enc[p][b].s += enc[p + 1][b].s; + /* + * fprintf (stderr, "%d:", p); for (e = 0; e < E_MAX; e++) fprintf \ + * (stderr, " %c*%d/%d", encchr[e], enc[p][e].s, enc[p][e].t); \ + * fprintf (stderr, "\n"); + */ + } + encoding = safemalloc(l + 1); + p = 0; + { + char cur = E_ASCII; // starts ASCII + while (p < l) { + int t, m = 0; + char b = 0; + for (e = 0; e < E_MAX; e++) + if (enc[p][e].t + && ((t = enc[p][e].t + switchcost[cur][e]) < + m || t == m && e == cur || !m)) { + b = e; + m = t; + } + cur = b; + m = enc[p][b].s; + if (!p && lenp) + *lenp = enc[p][b].t; + while (p < l && m--) + encoding[p++] = encchr[b]; + } + } + encoding[p] = 0; + return encoding; +} + +/* + * Main encoding function + * Returns the grid (malloced) containing the matrix. L corner at 0,0. + * Takes suggested size in *Wptr, *Hptr, or 0,0. Fills in actual size. + * Takes barcodelen and barcode to be encoded + * Note, if *encodingptr is null, then fills with auto picked (malloced) + * encoding + * If lenp not null, then the length of encoded data before any final + * unlatch or pad is stored + * If maxp not null, then the max storage of this size code is stored + * If eccp not null, then the number of ecc bytes used in this size is + * stored + * Returns 0 on error (writes to stderr with details). + */ + +unsigned char *iec16022ecc200(int *Wptr, int *Hptr, char **encodingptr, + int barcodelen, unsigned char *barcode, + int *lenp, int *maxp, int *eccp) +{ + unsigned char binary[3000]; // encoded raw data and ecc to place in barcode + int W = 0, H = 0; + char *encoding = 0; + unsigned char *grid = 0; + struct ecc200matrix_s *matrix; + memset(binary, 0, sizeof(binary)); + if (encodingptr) + encoding = *encodingptr; + if (Wptr) + W = *Wptr; + if (Hptr) + H = *Hptr; + + // encoding + if (W) { // known size + for (matrix = ecc200matrix; matrix->W && (matrix->W != W || + matrix->H != H); + matrix++) ; + if (!matrix->W) { + fprintf(stderr, "Invalid size %dx%d\n", W, H); + return 0; + } + if (!encoding) { + int len; + char *e = encmake(barcodelen, barcode, &len, 1); + if (e && len != matrix->bytes) { // try not an exact fit + free(e); + e = encmake(barcodelen, barcode, &len, 0); + if (len > matrix->bytes) { + fprintf(stderr, + "Cannot make barcode fit %dx%d\n", + W, H); + return 0; + } + } + encoding = e; + } + } else { + // find a suitable encoding + if (encoding == NULL) + encoding = encmake(barcodelen, barcode, NULL, 1); + + if (encoding) { // find one that fits chosen encoding + for (matrix = ecc200matrix; matrix->W; matrix++) + if (ecc200encode + (binary, matrix->bytes, barcode, barcodelen, + encoding, 0)) + break; + } else { + int len; + char *e; + e = encmake(barcodelen, barcode, &len, 1); + for (matrix = ecc200matrix; + matrix->W && matrix->bytes != len; matrix++) ; + if (e && !matrix->W) { // try for non exact fit + free(e); + e = encmake(barcodelen, barcode, &len, 0); + for (matrix = ecc200matrix; + matrix->W && matrix->bytes < len; + matrix++) ; + } + encoding = e; + } + if (!matrix->W) { + fprintf(stderr, + "Cannot find suitable size, barcode too long\n"); + return 0; + } + W = matrix->W; + H = matrix->H; + } + if (!ecc200encode(binary, matrix->bytes, barcode, barcodelen, + encoding, lenp)) { + fprintf(stderr, "Barcode too long for %dx%d\n", W, H); + return 0; + } + // ecc code + ecc200(binary, matrix->bytes, matrix->datablock, matrix->rsblock); + { // placement + int x, y, NC, NR, *places; + NC = W - 2 * (W / matrix->FW); + NR = H - 2 * (H / matrix->FH); + places = safemalloc(NC * NR * sizeof(int)); + ecc200placement(places, NR, NC); + grid = safemalloc(W * H); + memset(grid, 0, W * H); + for (y = 0; y < H; y += matrix->FH) { + for (x = 0; x < W; x++) + grid[y * W + x] = 1; + for (x = 0; x < W; x += 2) + grid[(y + matrix->FH - 1) * W + x] = 1; + } + for (x = 0; x < W; x += matrix->FW) { + for (y = 0; y < H; y++) + grid[y * W + x] = 1; + for (y = 0; y < H; y += 2) + grid[y * W + x + matrix->FW - 1] = 1; + } + for (y = 0; y < NR; y++) { + for (x = 0; x < NC; x++) { + int v = places[(NR - y - 1) * NC + x]; + //fprintf (stderr, "%4d", v); + if (v == 1 || v > 7 + && (binary[(v >> 3) - 1] & (1 << (v & 7)))) + grid[(1 + y + + 2 * (y / (matrix->FH - 2))) * W + + 1 + x + + 2 * (x / (matrix->FW - 2))] = 1; + } + //fprintf (stderr, "\n"); + } + free(places); + } + if (Wptr) + *Wptr = W; + if (Hptr) + *Hptr = H; + if (encodingptr) + *encodingptr = encoding; + if (maxp) + *maxp = matrix->bytes; + if (eccp) + *eccp = + (matrix->bytes + 2) / matrix->datablock * matrix->rsblock; + return grid; +} diff --git a/backend/dm200.h b/backend/dm200.h new file mode 100644 index 00000000..08678f08 --- /dev/null +++ b/backend/dm200.h @@ -0,0 +1,47 @@ +/** + * + * IEC16022 bar code generation + * Adrian Kennard, Andrews & Arnold Ltd + * with help from Cliff Hones on the RS coding + * + * (c) 2004 Adrian Kennard, Andrews & Arnold Ltd + * (c) 2006 Stefan Schmidt + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * + * Main encoding function + * Returns the grid (malloced) containing the matrix. L corner at 0,0. + * Takes suggested size in *Wptr, *Hptr, or 0,0. Fills in actual size. + * Takes barcodelen and barcode to be encoded + * Note, if *encodingptr is null, then fills with auto picked (malloced) + * encoding. + * If lenp not null, then the length of encoded data before any final unlatch + * or pad is stored. + * If maxp not null, then the max storage of this size code is stored + * If eccp not null, then the number of ecc bytes used in this size is stored + * Returns 0 on error (writes to stderr with details). + * + */ + +#ifndef __IEC16022ECC200_H +#define __IEC16022ECC200_H + +unsigned char *iec16022ecc200(int *Wptr, int *Hptr, char **encodingptr, + int barcodelen, unsigned char *barcode, + int *lenp, int *maxp, int *eccp); +#define MAXBARCODE 3116 + +#endif /* __IEC16022ECC200_H */ diff --git a/backend/dmatrix.c b/backend/dmatrix.c new file mode 100644 index 00000000..99b7be22 --- /dev/null +++ b/backend/dmatrix.c @@ -0,0 +1,181 @@ +/* dmatrix.c - Handles Data Matrix 2-D symbology (IEC16022 ecc 200) */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 Robin Stuart + + This file is a hacked-up copy of: + * IEC16022 bar code generation by + * Adrian Kennard, Andrews & Arnold Ltd + * with help from Cliff Hones on the RS coding + * + * (c) 2004 Adrian Kennard, Andrews & Arnold Ltd + * (c) 2006 Stefan Schmidt + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* The original version of this code is available at: + http://www.datenfreihafen.org/projects/iec16022.html */ + +#define IEC16022_VERSION "0.2" + +#include +#include +#include +#include +#include +#include "dm200.h" +#include "common.h" + + + // simple checked response malloc +void *safemalloc(int n) +{ + void *p = malloc(n); + if (!p) { + fprintf(stderr, "Malloc(%d) failed\n", n); + exit(1); + } + return p; +} + +int dmatrix(struct zint_symbol *symbol, unsigned char source[]) +{ + int W = 0, H = 0; + int ecc = 0; + int barcodelen = 0; + char *encoding = 0; + int len = 0, maxlen = 0, ecclen = 0; + unsigned char *grid = 0; + char size[3], eccstr[3]; + + strcpy(size, ""); + strcpy(eccstr, "200"); + + /* if (strlen(barcode) == 0) { // read from file + FILE *f = fopen(infile, "rb"); + barcode = safemalloc(4001); + if (!f) { + strcpy(symbol->errtxt, "error: could not open file"); + return 8; + } + barcodelen = fread(barcode, 1, 4000, f); + if (barcodelen < 0) { + strcpy(symbol->errtxt, "error: could not read file"); + return 8; + } + barcode[barcodelen] = 0; // null terminate anyway + fclose(f); +} else */ + barcodelen = strlen(source); + if(barcodelen > 780) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + // check parameters + if (strlen(size) != 0) { + char *x = strchr(size, 'x'); + W = atoi(size); + if (x) + H = atoi(x + 1); + if (!H) + W = H; + } + if (eccstr) + ecc = atoi(eccstr); + if (W & 1) { // odd size + if (W != H || W < 9 || W > 49) { + strcpy(symbol->errtxt, "error: invalid Data Matrix size"); + return ERROR_INVALID_OPTION; + } + if (!eccstr) { + if (W >= 17) + ecc = 140; + else if (W >= 13) + ecc = 100; + else if (W >= 11) + ecc = 80; + else + ecc = 0; + } + if (ecc && ecc != 50 && ecc != 80 && ecc != 100 && ecc != 140 || + ecc == 50 && W < 11 || ecc == 80 && W < 13 || ecc == 100 + && W < 13 || ecc == 140 && W < 17) { + strcpy(symbol->errtxt, "error: invalid ecc value"); + return ERROR_INVALID_OPTION; + } + + } else if (W) { // even size + if (W < H) { + int t = W; + W = H; + H = t; + } + if (!eccstr) + ecc = 200; + if (ecc != 200) { + strcpy(symbol->errtxt, "error: invalid size for ecc 200"); + return ERROR_INVALID_OPTION; + } + } + + else { // auto size + if (!eccstr) + // default is even sizes only unless explicit ecc set to force odd + // sizes + ecc = 200; + } + + // processing stamps + if ((W & 1) || ecc < 200) { // odd sizes + strcpy(symbol->errtxt, "error: odd sizes not supported"); + return ERROR_INVALID_OPTION; + } else { // even sizes + grid = + iec16022ecc200(&W, &H, &encoding, barcodelen, source, &len, + &maxlen, &ecclen); + } + + // output + if (!grid || !W) { + strcpy(symbol->errtxt, "error: Data Matrix encoding error"); + return ERROR_ENCODING_PROBLEM; + } + int y; + /*for (y = H - 1; y >= 0; y--) { + int x; + for (x = 0; x < W; x++) + printf("%c", + grid[W * y + x] ? '*' : ' '); + printf("\n"); + }*/ + + symbol->rows = H; + symbol->width = W; + + for(y = H - 1; y >= 0; y--) { + int x; + for(x = 0; x < W; x++) { + if(grid[W * y + x]) { + symbol->encoded_data[(H - y) - 1][x] = '1'; } + else { + symbol->encoded_data[(H - y) - 1][x] = '0'; } + } + symbol->row_height[(H - y) - 1] = 1; + } + + return 0; +} diff --git a/backend/imail.c b/backend/imail.c new file mode 100644 index 00000000..3047f1b3 --- /dev/null +++ b/backend/imail.c @@ -0,0 +1,680 @@ +/* imail.c - Handles Intelligent Mail (aka OneCode) for USPS */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* The function "USPS_MSB_Math_CRC11GenerateFrameCheckSequence" + is Copyright (C) 2006 United States Postal Service */ + +#include +#include +#include +#include "common.h" +#include "large.h" + +#define NASET "0123456789-" + +/* The following lookup tables were generated using the code in Appendix C */ + +static unsigned short AppxD_I[1287] = { /* Appendix D Table 1 - 5 of 13 characters */ + 0x001F, 0x1F00, 0x002F, 0x1E80, 0x0037, 0x1D80, 0x003B, 0x1B80, 0x003D, 0x1780, + 0x003E, 0x0F80, 0x004F, 0x1E40, 0x0057, 0x1D40, 0x005B, 0x1B40, 0x005D, 0x1740, + 0x005E, 0x0F40, 0x0067, 0x1CC0, 0x006B, 0x1AC0, 0x006D, 0x16C0, 0x006E, 0x0EC0, + 0x0073, 0x19C0, 0x0075, 0x15C0, 0x0076, 0x0DC0, 0x0079, 0x13C0, 0x007A, 0x0BC0, + 0x007C, 0x07C0, 0x008F, 0x1E20, 0x0097, 0x1D20, 0x009B, 0x1B20, 0x009D, 0x1720, + 0x009E, 0x0F20, 0x00A7, 0x1CA0, 0x00AB, 0x1AA0, 0x00AD, 0x16A0, 0x00AE, 0x0EA0, + 0x00B3, 0x19A0, 0x00B5, 0x15A0, 0x00B6, 0x0DA0, 0x00B9, 0x13A0, 0x00BA, 0x0BA0, + 0x00BC, 0x07A0, 0x00C7, 0x1C60, 0x00CB, 0x1A60, 0x00CD, 0x1660, 0x00CE, 0x0E60, + 0x00D3, 0x1960, 0x00D5, 0x1560, 0x00D6, 0x0D60, 0x00D9, 0x1360, 0x00DA, 0x0B60, + 0x00DC, 0x0760, 0x00E3, 0x18E0, 0x00E5, 0x14E0, 0x00E6, 0x0CE0, 0x00E9, 0x12E0, + 0x00EA, 0x0AE0, 0x00EC, 0x06E0, 0x00F1, 0x11E0, 0x00F2, 0x09E0, 0x00F4, 0x05E0, + 0x00F8, 0x03E0, 0x010F, 0x1E10, 0x0117, 0x1D10, 0x011B, 0x1B10, 0x011D, 0x1710, + 0x011E, 0x0F10, 0x0127, 0x1C90, 0x012B, 0x1A90, 0x012D, 0x1690, 0x012E, 0x0E90, + 0x0133, 0x1990, 0x0135, 0x1590, 0x0136, 0x0D90, 0x0139, 0x1390, 0x013A, 0x0B90, + 0x013C, 0x0790, 0x0147, 0x1C50, 0x014B, 0x1A50, 0x014D, 0x1650, 0x014E, 0x0E50, + 0x0153, 0x1950, 0x0155, 0x1550, 0x0156, 0x0D50, 0x0159, 0x1350, 0x015A, 0x0B50, + 0x015C, 0x0750, 0x0163, 0x18D0, 0x0165, 0x14D0, 0x0166, 0x0CD0, 0x0169, 0x12D0, + 0x016A, 0x0AD0, 0x016C, 0x06D0, 0x0171, 0x11D0, 0x0172, 0x09D0, 0x0174, 0x05D0, + 0x0178, 0x03D0, 0x0187, 0x1C30, 0x018B, 0x1A30, 0x018D, 0x1630, 0x018E, 0x0E30, + 0x0193, 0x1930, 0x0195, 0x1530, 0x0196, 0x0D30, 0x0199, 0x1330, 0x019A, 0x0B30, + 0x019C, 0x0730, 0x01A3, 0x18B0, 0x01A5, 0x14B0, 0x01A6, 0x0CB0, 0x01A9, 0x12B0, + 0x01AA, 0x0AB0, 0x01AC, 0x06B0, 0x01B1, 0x11B0, 0x01B2, 0x09B0, 0x01B4, 0x05B0, + 0x01B8, 0x03B0, 0x01C3, 0x1870, 0x01C5, 0x1470, 0x01C6, 0x0C70, 0x01C9, 0x1270, + 0x01CA, 0x0A70, 0x01CC, 0x0670, 0x01D1, 0x1170, 0x01D2, 0x0970, 0x01D4, 0x0570, + 0x01D8, 0x0370, 0x01E1, 0x10F0, 0x01E2, 0x08F0, 0x01E4, 0x04F0, 0x01E8, 0x02F0, + 0x020F, 0x1E08, 0x0217, 0x1D08, 0x021B, 0x1B08, 0x021D, 0x1708, 0x021E, 0x0F08, + 0x0227, 0x1C88, 0x022B, 0x1A88, 0x022D, 0x1688, 0x022E, 0x0E88, 0x0233, 0x1988, + 0x0235, 0x1588, 0x0236, 0x0D88, 0x0239, 0x1388, 0x023A, 0x0B88, 0x023C, 0x0788, + 0x0247, 0x1C48, 0x024B, 0x1A48, 0x024D, 0x1648, 0x024E, 0x0E48, 0x0253, 0x1948, + 0x0255, 0x1548, 0x0256, 0x0D48, 0x0259, 0x1348, 0x025A, 0x0B48, 0x025C, 0x0748, + 0x0263, 0x18C8, 0x0265, 0x14C8, 0x0266, 0x0CC8, 0x0269, 0x12C8, 0x026A, 0x0AC8, + 0x026C, 0x06C8, 0x0271, 0x11C8, 0x0272, 0x09C8, 0x0274, 0x05C8, 0x0278, 0x03C8, + 0x0287, 0x1C28, 0x028B, 0x1A28, 0x028D, 0x1628, 0x028E, 0x0E28, 0x0293, 0x1928, + 0x0295, 0x1528, 0x0296, 0x0D28, 0x0299, 0x1328, 0x029A, 0x0B28, 0x029C, 0x0728, + 0x02A3, 0x18A8, 0x02A5, 0x14A8, 0x02A6, 0x0CA8, 0x02A9, 0x12A8, 0x02AA, 0x0AA8, + 0x02AC, 0x06A8, 0x02B1, 0x11A8, 0x02B2, 0x09A8, 0x02B4, 0x05A8, 0x02B8, 0x03A8, + 0x02C3, 0x1868, 0x02C5, 0x1468, 0x02C6, 0x0C68, 0x02C9, 0x1268, 0x02CA, 0x0A68, + 0x02CC, 0x0668, 0x02D1, 0x1168, 0x02D2, 0x0968, 0x02D4, 0x0568, 0x02D8, 0x0368, + 0x02E1, 0x10E8, 0x02E2, 0x08E8, 0x02E4, 0x04E8, 0x0307, 0x1C18, 0x030B, 0x1A18, + 0x030D, 0x1618, 0x030E, 0x0E18, 0x0313, 0x1918, 0x0315, 0x1518, 0x0316, 0x0D18, + 0x0319, 0x1318, 0x031A, 0x0B18, 0x031C, 0x0718, 0x0323, 0x1898, 0x0325, 0x1498, + 0x0326, 0x0C98, 0x0329, 0x1298, 0x032A, 0x0A98, 0x032C, 0x0698, 0x0331, 0x1198, + 0x0332, 0x0998, 0x0334, 0x0598, 0x0338, 0x0398, 0x0343, 0x1858, 0x0345, 0x1458, + 0x0346, 0x0C58, 0x0349, 0x1258, 0x034A, 0x0A58, 0x034C, 0x0658, 0x0351, 0x1158, + 0x0352, 0x0958, 0x0354, 0x0558, 0x0361, 0x10D8, 0x0362, 0x08D8, 0x0364, 0x04D8, + 0x0383, 0x1838, 0x0385, 0x1438, 0x0386, 0x0C38, 0x0389, 0x1238, 0x038A, 0x0A38, + 0x038C, 0x0638, 0x0391, 0x1138, 0x0392, 0x0938, 0x0394, 0x0538, 0x03A1, 0x10B8, + 0x03A2, 0x08B8, 0x03A4, 0x04B8, 0x03C1, 0x1078, 0x03C2, 0x0878, 0x03C4, 0x0478, + 0x040F, 0x1E04, 0x0417, 0x1D04, 0x041B, 0x1B04, 0x041D, 0x1704, 0x041E, 0x0F04, + 0x0427, 0x1C84, 0x042B, 0x1A84, 0x042D, 0x1684, 0x042E, 0x0E84, 0x0433, 0x1984, + 0x0435, 0x1584, 0x0436, 0x0D84, 0x0439, 0x1384, 0x043A, 0x0B84, 0x043C, 0x0784, + 0x0447, 0x1C44, 0x044B, 0x1A44, 0x044D, 0x1644, 0x044E, 0x0E44, 0x0453, 0x1944, + 0x0455, 0x1544, 0x0456, 0x0D44, 0x0459, 0x1344, 0x045A, 0x0B44, 0x045C, 0x0744, + 0x0463, 0x18C4, 0x0465, 0x14C4, 0x0466, 0x0CC4, 0x0469, 0x12C4, 0x046A, 0x0AC4, + 0x046C, 0x06C4, 0x0471, 0x11C4, 0x0472, 0x09C4, 0x0474, 0x05C4, 0x0487, 0x1C24, + 0x048B, 0x1A24, 0x048D, 0x1624, 0x048E, 0x0E24, 0x0493, 0x1924, 0x0495, 0x1524, + 0x0496, 0x0D24, 0x0499, 0x1324, 0x049A, 0x0B24, 0x049C, 0x0724, 0x04A3, 0x18A4, + 0x04A5, 0x14A4, 0x04A6, 0x0CA4, 0x04A9, 0x12A4, 0x04AA, 0x0AA4, 0x04AC, 0x06A4, + 0x04B1, 0x11A4, 0x04B2, 0x09A4, 0x04B4, 0x05A4, 0x04C3, 0x1864, 0x04C5, 0x1464, + 0x04C6, 0x0C64, 0x04C9, 0x1264, 0x04CA, 0x0A64, 0x04CC, 0x0664, 0x04D1, 0x1164, + 0x04D2, 0x0964, 0x04D4, 0x0564, 0x04E1, 0x10E4, 0x04E2, 0x08E4, 0x0507, 0x1C14, + 0x050B, 0x1A14, 0x050D, 0x1614, 0x050E, 0x0E14, 0x0513, 0x1914, 0x0515, 0x1514, + 0x0516, 0x0D14, 0x0519, 0x1314, 0x051A, 0x0B14, 0x051C, 0x0714, 0x0523, 0x1894, + 0x0525, 0x1494, 0x0526, 0x0C94, 0x0529, 0x1294, 0x052A, 0x0A94, 0x052C, 0x0694, + 0x0531, 0x1194, 0x0532, 0x0994, 0x0534, 0x0594, 0x0543, 0x1854, 0x0545, 0x1454, + 0x0546, 0x0C54, 0x0549, 0x1254, 0x054A, 0x0A54, 0x054C, 0x0654, 0x0551, 0x1154, + 0x0552, 0x0954, 0x0561, 0x10D4, 0x0562, 0x08D4, 0x0583, 0x1834, 0x0585, 0x1434, + 0x0586, 0x0C34, 0x0589, 0x1234, 0x058A, 0x0A34, 0x058C, 0x0634, 0x0591, 0x1134, + 0x0592, 0x0934, 0x05A1, 0x10B4, 0x05A2, 0x08B4, 0x05C1, 0x1074, 0x05C2, 0x0874, + 0x0607, 0x1C0C, 0x060B, 0x1A0C, 0x060D, 0x160C, 0x060E, 0x0E0C, 0x0613, 0x190C, + 0x0615, 0x150C, 0x0616, 0x0D0C, 0x0619, 0x130C, 0x061A, 0x0B0C, 0x061C, 0x070C, + 0x0623, 0x188C, 0x0625, 0x148C, 0x0626, 0x0C8C, 0x0629, 0x128C, 0x062A, 0x0A8C, + 0x062C, 0x068C, 0x0631, 0x118C, 0x0632, 0x098C, 0x0643, 0x184C, 0x0645, 0x144C, + 0x0646, 0x0C4C, 0x0649, 0x124C, 0x064A, 0x0A4C, 0x0651, 0x114C, 0x0652, 0x094C, + 0x0661, 0x10CC, 0x0662, 0x08CC, 0x0683, 0x182C, 0x0685, 0x142C, 0x0686, 0x0C2C, + 0x0689, 0x122C, 0x068A, 0x0A2C, 0x0691, 0x112C, 0x0692, 0x092C, 0x06A1, 0x10AC, + 0x06A2, 0x08AC, 0x06C1, 0x106C, 0x06C2, 0x086C, 0x0703, 0x181C, 0x0705, 0x141C, + 0x0706, 0x0C1C, 0x0709, 0x121C, 0x070A, 0x0A1C, 0x0711, 0x111C, 0x0712, 0x091C, + 0x0721, 0x109C, 0x0722, 0x089C, 0x0741, 0x105C, 0x0742, 0x085C, 0x0781, 0x103C, + 0x0782, 0x083C, 0x080F, 0x1E02, 0x0817, 0x1D02, 0x081B, 0x1B02, 0x081D, 0x1702, + 0x081E, 0x0F02, 0x0827, 0x1C82, 0x082B, 0x1A82, 0x082D, 0x1682, 0x082E, 0x0E82, + 0x0833, 0x1982, 0x0835, 0x1582, 0x0836, 0x0D82, 0x0839, 0x1382, 0x083A, 0x0B82, + 0x0847, 0x1C42, 0x084B, 0x1A42, 0x084D, 0x1642, 0x084E, 0x0E42, 0x0853, 0x1942, + 0x0855, 0x1542, 0x0856, 0x0D42, 0x0859, 0x1342, 0x085A, 0x0B42, 0x0863, 0x18C2, + 0x0865, 0x14C2, 0x0866, 0x0CC2, 0x0869, 0x12C2, 0x086A, 0x0AC2, 0x0871, 0x11C2, + 0x0872, 0x09C2, 0x0887, 0x1C22, 0x088B, 0x1A22, 0x088D, 0x1622, 0x088E, 0x0E22, + 0x0893, 0x1922, 0x0895, 0x1522, 0x0896, 0x0D22, 0x0899, 0x1322, 0x089A, 0x0B22, + 0x08A3, 0x18A2, 0x08A5, 0x14A2, 0x08A6, 0x0CA2, 0x08A9, 0x12A2, 0x08AA, 0x0AA2, + 0x08B1, 0x11A2, 0x08B2, 0x09A2, 0x08C3, 0x1862, 0x08C5, 0x1462, 0x08C6, 0x0C62, + 0x08C9, 0x1262, 0x08CA, 0x0A62, 0x08D1, 0x1162, 0x08D2, 0x0962, 0x08E1, 0x10E2, + 0x0907, 0x1C12, 0x090B, 0x1A12, 0x090D, 0x1612, 0x090E, 0x0E12, 0x0913, 0x1912, + 0x0915, 0x1512, 0x0916, 0x0D12, 0x0919, 0x1312, 0x091A, 0x0B12, 0x0923, 0x1892, + 0x0925, 0x1492, 0x0926, 0x0C92, 0x0929, 0x1292, 0x092A, 0x0A92, 0x0931, 0x1192, + 0x0932, 0x0992, 0x0943, 0x1852, 0x0945, 0x1452, 0x0946, 0x0C52, 0x0949, 0x1252, + 0x094A, 0x0A52, 0x0951, 0x1152, 0x0961, 0x10D2, 0x0983, 0x1832, 0x0985, 0x1432, + 0x0986, 0x0C32, 0x0989, 0x1232, 0x098A, 0x0A32, 0x0991, 0x1132, 0x09A1, 0x10B2, + 0x09C1, 0x1072, 0x0A07, 0x1C0A, 0x0A0B, 0x1A0A, 0x0A0D, 0x160A, 0x0A0E, 0x0E0A, + 0x0A13, 0x190A, 0x0A15, 0x150A, 0x0A16, 0x0D0A, 0x0A19, 0x130A, 0x0A1A, 0x0B0A, + 0x0A23, 0x188A, 0x0A25, 0x148A, 0x0A26, 0x0C8A, 0x0A29, 0x128A, 0x0A2A, 0x0A8A, + 0x0A31, 0x118A, 0x0A43, 0x184A, 0x0A45, 0x144A, 0x0A46, 0x0C4A, 0x0A49, 0x124A, + 0x0A51, 0x114A, 0x0A61, 0x10CA, 0x0A83, 0x182A, 0x0A85, 0x142A, 0x0A86, 0x0C2A, + 0x0A89, 0x122A, 0x0A91, 0x112A, 0x0AA1, 0x10AA, 0x0AC1, 0x106A, 0x0B03, 0x181A, + 0x0B05, 0x141A, 0x0B06, 0x0C1A, 0x0B09, 0x121A, 0x0B11, 0x111A, 0x0B21, 0x109A, + 0x0B41, 0x105A, 0x0B81, 0x103A, 0x0C07, 0x1C06, 0x0C0B, 0x1A06, 0x0C0D, 0x1606, + 0x0C0E, 0x0E06, 0x0C13, 0x1906, 0x0C15, 0x1506, 0x0C16, 0x0D06, 0x0C19, 0x1306, + 0x0C23, 0x1886, 0x0C25, 0x1486, 0x0C26, 0x0C86, 0x0C29, 0x1286, 0x0C31, 0x1186, + 0x0C43, 0x1846, 0x0C45, 0x1446, 0x0C49, 0x1246, 0x0C51, 0x1146, 0x0C61, 0x10C6, + 0x0C83, 0x1826, 0x0C85, 0x1426, 0x0C89, 0x1226, 0x0C91, 0x1126, 0x0CA1, 0x10A6, + 0x0CC1, 0x1066, 0x0D03, 0x1816, 0x0D05, 0x1416, 0x0D09, 0x1216, 0x0D11, 0x1116, + 0x0D21, 0x1096, 0x0D41, 0x1056, 0x0D81, 0x1036, 0x0E03, 0x180E, 0x0E05, 0x140E, + 0x0E09, 0x120E, 0x0E11, 0x110E, 0x0E21, 0x108E, 0x0E41, 0x104E, 0x0E81, 0x102E, + 0x0F01, 0x101E, 0x100F, 0x1E01, 0x1017, 0x1D01, 0x101B, 0x1B01, 0x101D, 0x1701, + 0x1027, 0x1C81, 0x102B, 0x1A81, 0x102D, 0x1681, 0x1033, 0x1981, 0x1035, 0x1581, + 0x1039, 0x1381, 0x1047, 0x1C41, 0x104B, 0x1A41, 0x104D, 0x1641, 0x1053, 0x1941, + 0x1055, 0x1541, 0x1059, 0x1341, 0x1063, 0x18C1, 0x1065, 0x14C1, 0x1069, 0x12C1, + 0x1071, 0x11C1, 0x1087, 0x1C21, 0x108B, 0x1A21, 0x108D, 0x1621, 0x1093, 0x1921, + 0x1095, 0x1521, 0x1099, 0x1321, 0x10A3, 0x18A1, 0x10A5, 0x14A1, 0x10A9, 0x12A1, + 0x10B1, 0x11A1, 0x10C3, 0x1861, 0x10C5, 0x1461, 0x10C9, 0x1261, 0x10D1, 0x1161, + 0x1107, 0x1C11, 0x110B, 0x1A11, 0x110D, 0x1611, 0x1113, 0x1911, 0x1115, 0x1511, + 0x1119, 0x1311, 0x1123, 0x1891, 0x1125, 0x1491, 0x1129, 0x1291, 0x1131, 0x1191, + 0x1143, 0x1851, 0x1145, 0x1451, 0x1149, 0x1251, 0x1183, 0x1831, 0x1185, 0x1431, + 0x1189, 0x1231, 0x1207, 0x1C09, 0x120B, 0x1A09, 0x120D, 0x1609, 0x1213, 0x1909, + 0x1215, 0x1509, 0x1219, 0x1309, 0x1223, 0x1889, 0x1225, 0x1489, 0x1229, 0x1289, + 0x1243, 0x1849, 0x1245, 0x1449, 0x1283, 0x1829, 0x1285, 0x1429, 0x1303, 0x1819, + 0x1305, 0x1419, 0x1407, 0x1C05, 0x140B, 0x1A05, 0x140D, 0x1605, 0x1413, 0x1905, + 0x1415, 0x1505, 0x1423, 0x1885, 0x1425, 0x1485, 0x1443, 0x1845, 0x1483, 0x1825, + 0x1503, 0x1815, 0x1603, 0x180D, 0x1807, 0x1C03, 0x180B, 0x1A03, 0x1813, 0x1903, + 0x1823, 0x1883, 0x1843, 0x1445, 0x1249, 0x1151, 0x10E1, 0x0C46, 0x0A4A, 0x0952, + 0x08E2, 0x064C, 0x0554, 0x04E4, 0x0358, 0x02E8, 0x01F0 }; + +static unsigned short AppxD_II[78] = { /* Appendix D Table II - 2 of 13 characters */ + 0x0003, 0x1800, 0x0005, 0x1400, 0x0006, 0x0C00, 0x0009, 0x1200, 0x000A, 0x0A00, + 0x000C, 0x0600, 0x0011, 0x1100, 0x0012, 0x0900, 0x0014, 0x0500, 0x0018, 0x0300, + 0x0021, 0x1080, 0x0022, 0x0880, 0x0024, 0x0480, 0x0028, 0x0280, 0x0030, 0x0180, + 0x0041, 0x1040, 0x0042, 0x0840, 0x0044, 0x0440, 0x0048, 0x0240, 0x0050, 0x0140, + 0x0060, 0x00C0, 0x0081, 0x1020, 0x0082, 0x0820, 0x0084, 0x0420, 0x0088, 0x0220, + 0x0090, 0x0120, 0x0101, 0x1010, 0x0102, 0x0810, 0x0104, 0x0410, 0x0108, 0x0210, + 0x0201, 0x1008, 0x0202, 0x0808, 0x0204, 0x0408, 0x0401, 0x1004, 0x0402, 0x0804, + 0x0801, 0x1002, 0x1001, 0x0802, 0x0404, 0x0208, 0x0110, 0x00A0 }; + +static int AppxD_IV[130] = { /* Appendix D Table IV - Bar-to-Character Mapping (reverse lookup) */ + 67, 6, 78, 16, 86, 95, 34, 40, 45, 113, 117, 121, 62, 87, 18, 104, 41, 76, 57, 119, 115, 72, 97, + 2, 127, 26, 105, 35, 122, 52, 114, 7, 24, 82, 68, 63, 94, 44, 77, 112, 70, 100, 39, 30, 107, + 15, 125, 85, 10, 65, 54, 88, 20, 106, 46, 66, 8, 116, 29, 61, 99, 80, 90, 37, 123, 51, 25, 84, + 129, 56, 4, 109, 96, 28, 36, 47, 11, 71, 33, 102, 21, 9, 17, 49, 124, 79, 64, 91, 42, 69, 53, + 60, 14, 1, 27, 103, 126, 75, 89, 50, 120, 19, 32, 110, 92, 111, 130, 59, 31, 12, 81, 43, 55, + 5, 74, 22, 101, 128, 58, 118, 48, 108, 38, 98, 93, 23, 83, 13, 73, 3 }; + +/*************************************************************************** + ** USPS_MSB_Math_CRC11GenerateFrameCheckSequence + ** + ** Inputs: + ** ByteAttayPtr is the address of a 13 byte array holding 102 bytes which + ** are right justified - ie: the leftmost 2 bits of the first byte do not + ** hold data and must be set to zero. + ** + ** Outputs: + ** return unsigned short - 11 bit Frame Check Sequence (right justified) +***************************************************************************/ +extern unsigned short + USPS_MSB_Math_CRC11GenerateFrameCheckSequence( unsigned char *ByteArrayPtr ) + +{ + unsigned short GeneratorPolynomial = 0x0F35; + unsigned short FrameCheckSequence = 0x07FF; + unsigned short Data; + int ByteIndex, Bit; + + /* Do most significant byte skipping the 2 most significant bits */ + Data = *ByteArrayPtr << 5; + ByteArrayPtr++; + for ( Bit = 2; Bit < 8; Bit++ ) + { + if ( (FrameCheckSequence ^ Data) & 0x400 ) + FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial; + else + FrameCheckSequence = (FrameCheckSequence << 1); + FrameCheckSequence &= 0x7FF; + Data <<= 1; + } + /* Do rest of the bytes */ + for ( ByteIndex = 1; ByteIndex < 13; ByteIndex++ ) + { + Data = *ByteArrayPtr << 3; + ByteArrayPtr++; + for ( Bit = 0; Bit < 8; Bit++ ) + { + if ( (FrameCheckSequence ^ Data) & 0x0400 ) { + FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial; + } else { + FrameCheckSequence = (FrameCheckSequence << 1); + } + FrameCheckSequence &= 0x7FF; + Data <<= 1; + } + } + return FrameCheckSequence; +} + +void breakup(short int fcs_bit[], unsigned short usps_crc) +{ + int i; + + for(i = 0; i < 13; i++) { + fcs_bit[i] = 0; + } + + if(usps_crc >= 4096) { + fcs_bit[12] = 1; + usps_crc -= 4096; + } + if(usps_crc >= 2048) { + fcs_bit[11] = 1; + usps_crc -= 2048; + } + if(usps_crc >= 1024) { + fcs_bit[10] = 1; + usps_crc -= 1024; + } + if(usps_crc >= 512) { + fcs_bit[9] = 1; + usps_crc -= 512; + } + if(usps_crc >= 256) { + fcs_bit[8] = 1; + usps_crc -= 256; + } + if(usps_crc >= 128) { + fcs_bit[7] = 1; + usps_crc -= 128; + } + if(usps_crc >= 64) { + fcs_bit[6] = 1; + usps_crc -= 64; + } + if(usps_crc >= 32) { + fcs_bit[5] = 1; + usps_crc -= 32; + } + if(usps_crc >= 16) { + fcs_bit[4] = 1; + usps_crc -= 16; + } + if(usps_crc >= 8) { + fcs_bit[3] = 1; + usps_crc -= 8; + } + if(usps_crc >= 4) { + fcs_bit[2] = 1; + usps_crc -= 4; + } + if(usps_crc >= 2) { + fcs_bit[1] = 1; + usps_crc -= 2; + } + if(usps_crc == 1) { + fcs_bit[0] = 1; + } +} + +int imail(struct zint_symbol *symbol, unsigned char source[]) +{ + char data_pattern[200]; + int errno; + + errno = 0; + + if(strlen(source) > 32) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NASET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + int i, j, read; + char zip[35], tracker[35], zip_adder[11], temp[2]; + short int accum[112], x_reg[112], y_reg[112]; + strcpy(zip, ""); + strcpy(tracker, ""); + unsigned char byte_array[13]; + unsigned short usps_crc; + int codeword[10]; + unsigned short characters[10]; + short int bit_pattern[13], bar_map[130]; + + /* separate the tracking code from the routing code */ + + read = 0; + j = 0; + for(i = 0; i < strlen(source); i++) { + if(source[i] == '-') { + tracker[read] = '\0'; + j = 1; + read = 0; + } else { + if(j == 0) { + /* reading tracker */ + tracker[read] = source[i]; + read++; + } else { + /* reading zip code */ + zip[read] = source[i]; + read++; + } + } + } + if(j == 0) { + tracker[read] = '\0'; + } else { + zip[read] = '\0'; + } + + if(strlen(tracker) != 20) { + strcpy(symbol->errtxt, "error: invalid length tracking code"); + return ERROR_INVALID_DATA; + } + if(strlen(zip) > 11) { + strcpy(symbol->errtxt, "error: invalid ZIP code"); + return ERROR_INVALID_DATA; + } + + /* *** Step 1 - Conversion of Data Fields into Binary Data *** */ + + /* Routing code first */ + + for(i = 0; i < 112; i++) { + accum[i] = 0; + } + + for(read = 0; read < strlen(zip); read++) { + + for(i = 0; i < 112; i++) { + x_reg[i] = accum[i]; + } + + for(i = 0; i < 9; i++) { + binary_add(accum, x_reg); + } + + x_reg[0] = BCD[ctoi(zip[read]) * 4]; + x_reg[1] = BCD[(ctoi(zip[read]) * 4) + 1]; + x_reg[2] = BCD[(ctoi(zip[read]) * 4) + 2]; + x_reg[3] = BCD[(ctoi(zip[read]) * 4) + 3]; + for(i = 4; i < 112; i++) { + x_reg[i] = 0; + } + + binary_add(accum, x_reg); + } + + /* add weight to routing code */ + + for(i = 0; i < 112; i++) { + x_reg[i] = accum[i]; + } + + if(strlen(zip) > 9) { + strcpy(zip_adder, "1000100001"); + } else { + if(strlen(zip) > 5) { + strcpy(zip_adder, "100001"); + } else { + if(strlen(zip) > 0) { + strcpy(zip_adder, "1"); + } else { + strcpy(zip_adder, "0"); + } + } + } + + for(i = 0; i < 112; i++) { + accum[i] = 0; + } + + for(read = 0; read < strlen(zip_adder); read++) { + + for(i = 0; i < 112; i++) { + y_reg[i] = accum[i]; + } + + for(i = 0; i < 9; i++) { + binary_add(accum, y_reg); + } + + y_reg[0] = BCD[ctoi(zip_adder[read]) * 4]; + y_reg[1] = BCD[(ctoi(zip_adder[read]) * 4) + 1]; + y_reg[2] = BCD[(ctoi(zip_adder[read]) * 4) + 2]; + y_reg[3] = BCD[(ctoi(zip_adder[read]) * 4) + 3]; + for(i = 4; i < 112; i++) { + y_reg[i] = 0; + } + + binary_add(accum, y_reg); + } + + binary_add(accum, x_reg); + + /* tracking code */ + + /* multiply by 10 */ + for(i = 0; i < 112; i++) { + y_reg[i] = accum[i]; + } + + for(i = 0; i < 9; i++) { + binary_add(accum, y_reg); + } + + /* add first digit of tracker */ + y_reg[0] = BCD[ctoi(tracker[0]) * 4]; + y_reg[1] = BCD[(ctoi(tracker[0]) * 4) + 1]; + y_reg[2] = BCD[(ctoi(tracker[0]) * 4) + 2]; + y_reg[3] = BCD[(ctoi(tracker[0]) * 4) + 3]; + for(i = 4; i < 112; i++) { + y_reg[i] = 0; + } + + binary_add(accum, y_reg); + + /* multiply by 5 */ + for(i = 0; i < 112; i++) { + y_reg[i] = accum[i]; + } + + for(i = 0; i < 4; i++) { + binary_add(accum, y_reg); + } + + /* add second digit */ + y_reg[0] = BCD[ctoi(tracker[1]) * 4]; + y_reg[1] = BCD[(ctoi(tracker[1]) * 4) + 1]; + y_reg[2] = BCD[(ctoi(tracker[1]) * 4) + 2]; + y_reg[3] = BCD[(ctoi(tracker[1]) * 4) + 3]; + for(i = 4; i < 112; i++) { + y_reg[i] = 0; + } + + binary_add(accum, y_reg); + + /* and then the rest */ + + for(read = 2; read < strlen(tracker); read++) { + + for(i = 0; i < 112; i++) { + y_reg[i] = accum[i]; + } + + for(i = 0; i < 9; i++) { + binary_add(accum, y_reg); + } + + y_reg[0] = BCD[ctoi(tracker[read]) * 4]; + y_reg[1] = BCD[(ctoi(tracker[read]) * 4) + 1]; + y_reg[2] = BCD[(ctoi(tracker[read]) * 4) + 2]; + y_reg[3] = BCD[(ctoi(tracker[read]) * 4) + 3]; + for(i = 4; i < 112; i++) { + y_reg[i] = 0; + } + + binary_add(accum, y_reg); + } + + /* printf("Binary data 1: "); + hex_dump(accum); */ + + /* *** Step 2 - Generation of 11-bit CRC on Binary Data *** */ + + accum[103] = 0; + accum[102] = 0; + + strcpy(byte_array, ""); + for(j = 0; j < 13; j++) { + i = 96 - (8 * j); + byte_array[j] = 0; + byte_array[j] += accum[i]; + byte_array[j] += 2 * accum[i + 1]; + byte_array[j] += 4 * accum[i + 2]; + byte_array[j] += 8 * accum[i + 3]; + byte_array[j] += 16 * accum[i + 4]; + byte_array[j] += 32 * accum[i + 5]; + byte_array[j] += 64 * accum[i + 6]; + byte_array[j] += 128 * accum[i + 7]; + } + + usps_crc = USPS_MSB_Math_CRC11GenerateFrameCheckSequence(byte_array); + /* printf("FCS 2: %4.4X\n", usps_crc); */ + + /* *** Step 3 - Conversion from Binary Data to Codewords *** */ + + /* start with codeword J which is base 636 */ + for(i = 0; i < 112; i++) { + x_reg[i] = 0; + y_reg[i] = 0; + } + + x_reg[101] = 1; + x_reg[98] = 1; + x_reg[97] = 1; + x_reg[96] = 1; + x_reg[95] = 1; + x_reg[94] = 1; + + for(i = 92; i >= 0; i--) { + y_reg[i] = islarger(accum, x_reg); + if(y_reg[i] == 1) { + binary_subtract(accum, x_reg); + } + shiftdown(x_reg); + } + + codeword[9] = (accum[9] * 512) + (accum[8] * 256) + (accum[7] * 128) + (accum[6] * 64) + + (accum[5] * 32) + (accum[4] * 16) + (accum[3] * 8) + (accum[2] * 4) + + (accum[1] * 2) + accum[0]; + + /* then codewords I to B with base 1365 */ + + for(j = 8; j > 0; j--) { + for(i = 0; i < 112; i++) { + accum[i] = y_reg[i]; + y_reg[i] = 0; + x_reg[i] = 0; + } + x_reg[101] = 1; + x_reg[99] = 1; + x_reg[97] = 1; + x_reg[95] = 1; + x_reg[93] = 1; + x_reg[91] = 1; + for(i = 91; i >= 0; i--) { + y_reg[i] = islarger(accum, x_reg); + if(y_reg[i] == 1) { + binary_subtract(accum, x_reg); + } + shiftdown(x_reg); + } + + codeword[j] = (accum[10] * 1024) + (accum[9] * 512) + (accum[8] * 256) + + (accum[7] * 128) + (accum[6] * 64) + (accum[5] * 32) + + (accum[4] * 16) + (accum[3] * 8) + (accum[2] * 4) + + (accum[1] * 2) + accum[0]; + } + + codeword[0] = (y_reg[10] * 1024) + (y_reg[9] * 512) + (y_reg[8] * 256) + + (y_reg[7] * 128) + (y_reg[6] * 64) + (y_reg[5] * 32) + + (y_reg[4] * 16) + (y_reg[3] * 8) + (y_reg[2] * 4) + + (y_reg[1] * 2) + y_reg[0]; + + /* printf("Codewords 3: "); + for(i = 0; i < 10; i++) { + printf("%d ", codeword[i]); + } + printf("\n"); */ + + /* *** Step 4 - Inserting Additional Information into Codewords *** */ + + codeword[9] = codeword[9] * 2; + + if(usps_crc >= 1024) { + codeword[0] += 659; + } + + /* printf("Codewords 4b: "); + for(i = 0; i < 10; i++) { + printf("%d ", codeword[i]); + } + printf("\n"); */ + + /* *** Step 5 - Conversion from Codewords to Characters *** */ + + for(i = 0; i < 10; i++) { + if(codeword[i] < 1287) { + characters[i] = AppxD_I[codeword[i]]; + } else { + characters[i] = AppxD_II[codeword[i] - 1287]; + } + } + + /* printf("Characters 5a: "); + for(i = 0; i < 10; i++) { + printf("%4.4X ", characters[i]); + } + printf("\n"); */ + + breakup(bit_pattern, usps_crc); + + for(i = 0; i < 10; i++) { + if(bit_pattern[i] == 1) { + characters[i] = 0x1FFF - characters[i]; + } + } + + /* printf("Characters 5b: "); + for(i = 0; i < 10; i++) { + printf("%4.4X ", characters[i]); + } + printf("\n"); */ + + /* *** Step 6 - Conversion from Characters to the Intelligent Mail Barcode *** */ + + for(i = 0; i < 10; i++) { + breakup(bit_pattern, characters[i]); + for(j = 0; j < 13; j++) { + bar_map[AppxD_IV[(13 * i) + j] - 1] = bit_pattern[j]; + } + } + + strcpy(data_pattern, ""); + temp[1] = '\0'; + for(i = 0; i < 65; i++) { + j = 0; + if(bar_map[i] == 0) + j += 1; + if(bar_map[i + 65] == 0) + j += 2; + temp[0] = itoc(j); + concat(data_pattern, temp); + } + + /* Translate 4-state data pattern to symbol */ + read = 0; + for(i = 0; i < strlen(data_pattern); i++) + { + if((data_pattern[i] == '1') || (data_pattern[i] == '0')) + { + symbol->encoded_data[0][read] = '1'; + } + symbol->encoded_data[1][read] = '1'; + if((data_pattern[i] == '2') || (data_pattern[i] == '0')) + { + symbol->encoded_data[2][read] = '1'; + } + read += 2; + } + + symbol->row_height[0] = 2; + symbol->row_height[1] = 2; + symbol->row_height[2] = 2; + + symbol->rows = 3; + symbol->width = read - 1; + return errno; +} diff --git a/backend/large.c b/backend/large.c new file mode 100644 index 00000000..ca16e10a --- /dev/null +++ b/backend/large.c @@ -0,0 +1,225 @@ +/* large.c - Handles binary manipulation of large numbers */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include + +static short int BCD[40] = { + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 1, 0, 0, + 1, 1, 0, 0, + 0, 0, 1, 0, + 1, 0, 1, 0, + 0, 1, 1, 0, + 1, 1, 1, 0, + 0, 0, 0, 1, + 1, 0, 0, 1 }; + +void binary_add(short int accumulator[], short int input_buffer[]) +{ /* Binary addition */ + int i, carry, done; + carry = 0; + + for(i = 0; i < 112; i++) { + done = 0; + if(((input_buffer[i] == 0) && (accumulator[i] == 0)) && ((carry == 0) && (done == 0))) { + accumulator[i] = 0; + carry = 0; + done = 1; + } + if(((input_buffer[i] == 0) && (accumulator[i] == 0)) && ((carry == 1) && (done == 0))) { + accumulator[i] = 1; + carry = 0; + done = 1; + } + if(((input_buffer[i] == 0) && (accumulator[i] == 1)) && ((carry == 0) && (done == 0))) { + accumulator[i] = 1; + carry = 0; + done = 1; + } + if(((input_buffer[i] == 0) && (accumulator[i] == 1)) && ((carry == 1) && (done == 0))) { + accumulator[i] = 0; + carry = 1; + done = 1; + } + if(((input_buffer[i] == 1) && (accumulator[i] == 0)) && ((carry == 0) && (done == 0))) { + accumulator[i] = 1; + carry = 0; + done = 1; + } + if(((input_buffer[i] == 1) && (accumulator[i] == 0)) && ((carry == 1) && (done == 0))) { + accumulator[i] = 0; + carry = 1; + done = 1; + } + if(((input_buffer[i] == 1) && (accumulator[i] == 1)) && ((carry == 0) && (done == 0))) { + accumulator[i] = 0; + carry = 1; + done = 1; + } + if(((input_buffer[i] == 1) && (accumulator[i] == 1)) && ((carry == 1) && (done == 0))) { + accumulator[i] = 1; + carry = 1; + done = 1; + } + } +} + +void binary_subtract(short int accumulator[], short int input_buffer[]) +{ /* 2's compliment subtraction */ + /* take input_buffer from accumulator and put answer in accumulator */ + int i; + short int sub_buffer[112]; + + for(i = 0; i < 112; i++) { + if(input_buffer[i] == 0) { + sub_buffer[i] = 1; + } else { + sub_buffer[i] = 0; + } + } + binary_add(accumulator, sub_buffer); + + sub_buffer[0] = 1; + + for(i = 1; i < 112; i++) { + sub_buffer[i] = 0; + } + binary_add(accumulator, sub_buffer); +} + +void shiftdown(short int buffer[]) +{ + int i; + + buffer[102] = 0; + buffer[103] = 0; + + for(i = 0; i < 102; i++) { + buffer[i] = buffer[i + 1]; + } +} + +void shiftup(short int buffer[]) +{ + int i; + + for(i = 102; i > 0; i--) { + buffer[i] = buffer[i - 1]; + } + + buffer[0] = 0; +} + +short int islarger(short int accum[], short int reg[]) +{ + /* Returns 1 if accum[] is larger than reg[], else 0 */ + int i, latch, larger; + latch = 0; + i = 103; + larger = 0; + + + do { + if((accum[i] == 1) && (reg[i] == 0)) { + latch = 1; + larger = 1; + } + if((accum[i] == 0) && (reg[i] == 1)) { + latch = 1; + } + i--; + } while ((latch == 0) && (i >= -1)); + + return larger; +} + +void binary_load(short int reg[], char data[]) +{ + int read, i; + short int temp[112]; + + for(i = 0; i < 112; i++) { + reg[i] = 0; + } + + for(read = 0; read < strlen(data); read++) { + + for(i = 0; i < 112; i++) { + temp[i] = reg[i]; + } + + for(i = 0; i < 9; i++) { + binary_add(reg, temp); + } + + temp[0] = BCD[ctoi(data[read]) * 4]; + temp[1] = BCD[(ctoi(data[read]) * 4) + 1]; + temp[2] = BCD[(ctoi(data[read]) * 4) + 2]; + temp[3] = BCD[(ctoi(data[read]) * 4) + 3]; + for(i = 4; i < 112; i++) { + temp[i] = 0; + } + + binary_add(reg, temp); + } +} + +void hex_dump(short int input_buffer[]) +{ + int i, digit, byte_space; + + byte_space = 1; + for(i = 100; i >= 0; i-=4) { + digit = 0; + digit += 1 * input_buffer[i]; + digit += 2 * input_buffer[i + 1]; + digit += 4 * input_buffer[i + 2]; + digit += 8 * input_buffer[i + 3]; + + switch(digit) { + case 0: printf("0"); break; + case 1: printf("1"); break; + case 2: printf("2"); break; + case 3: printf("3"); break; + case 4: printf("4"); break; + case 5: printf("5"); break; + case 6: printf("6"); break; + case 7: printf("7"); break; + case 8: printf("8"); break; + case 9: printf("9"); break; + case 10: printf("A"); break; + case 11: printf("B"); break; + case 12: printf("C"); break; + case 13: printf("D"); break; + case 14: printf("E"); break; + case 15: printf("F"); break; + } + if(byte_space == 1) { + byte_space = 0; + } else { + byte_space = 1; + printf(" "); + } + } + printf("\n"); +} diff --git a/backend/large.h b/backend/large.h new file mode 100644 index 00000000..b7b8846e --- /dev/null +++ b/backend/large.h @@ -0,0 +1,42 @@ +/* large.h - Handles binary manipulation of large numbers */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +static short int BCD[40] = { + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 1, 0, 0, + 1, 1, 0, 0, + 0, 0, 1, 0, + 1, 0, 1, 0, + 0, 1, 1, 0, + 1, 1, 1, 0, + 0, 0, 0, 1, + 1, 0, 0, 1 }; + +void binary_load(short int reg[], char data[]); +void binary_add(short int accumulator[], short int input_buffer[]); +void binary_subtract(short int accumulator[], short int input_buffer[]); +void shiftdown(short int buffer[]); +void shiftup(short int buffer[]); +short int islarger(short int accum[], short int reg[]); +void hex_dump(short int input_buffer[]); + + diff --git a/backend/library.c b/backend/library.c new file mode 100644 index 00000000..8f0d5a7e --- /dev/null +++ b/backend/library.c @@ -0,0 +1,296 @@ +/* library.c - external functions of libzint + + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include "common.h" + +struct zint_symbol *ZBarcode_Create() +{ + struct zint_symbol *symbol; + int i, j; + + symbol = malloc(sizeof(*symbol)); + if (!symbol) return NULL; + + memset(symbol, 0, sizeof(*symbol)); + symbol->symbology = BARCODE_CODE128; + symbol->height = 0; + symbol->whitespace_width = 0; + symbol->border_width = 0; + symbol->output_options = 0; + symbol->rows = 0; + symbol->width = 0; + strcpy(symbol->fgcolour, "000000"); + strcpy(symbol->bgcolour, "ffffff"); + strcpy(symbol->outfile, "out.png"); + symbol->option_1 = -1; + symbol->option_2 = 0; + strcpy(symbol->primary, ""); + for(i = 0; i < 90; i++) { + for(j = 0; j < 1000; j++) { + symbol->encoded_data[i][j] = '0'; + } + symbol->row_height[i] = 0; + } + return symbol; +} + + +int ZBarcode_Delete(struct zint_symbol *symbol) +{ + free(symbol); + return 0; +} + +extern int eanx(struct zint_symbol *symbol, unsigned char source[]); /* EAN system barcodes */ +extern int c39(struct zint_symbol *symbol, unsigned char source[]); /* Code 3 from 9 (or Code 39) */ +extern int pharmazentral(struct zint_symbol *symbol, unsigned char source[]); /* Pharmazentral Nummer (PZN) */ +extern int ec39(struct zint_symbol *symbol, unsigned char source[]); /* Extended Code 3 from 9 (or Code 39+) */ +extern int codabar(struct zint_symbol *symbol, unsigned char source[]); /* Codabar - a simple substitution cipher */ +extern int matrix_two_of_five(struct zint_symbol *symbol, unsigned char source[]); /* Code 2 of 5 Standard (& Matrix) */ +extern int industrial_two_of_five(struct zint_symbol *symbol, unsigned char source[]); /* Code 2 of 5 Industrial */ +extern int iata_two_of_five(struct zint_symbol *symbol, unsigned char source[]); /* Code 2 of 5 IATA */ +extern int interleaved_two_of_five(struct zint_symbol *symbol, unsigned char source[]); /* Code 2 of 5 Interleaved */ +extern int logic_two_of_five(struct zint_symbol *symbol, unsigned char source[]); /* Code 2 of 5 Data Logic */ +extern int itf14(struct zint_symbol *symbol, unsigned char source[]); /* ITF-14 */ +extern int dpleit(struct zint_symbol *symbol, unsigned char source[]); /* Deutsche Post Leitcode */ +extern int dpident(struct zint_symbol *symbol, unsigned char source[]); /* Deutsche Post Identcode */ +extern int c93(struct zint_symbol *symbol, unsigned char source[]); /* Code 93 - a re-working of Code 39+, generates 2 check digits */ +extern int code_128(struct zint_symbol *symbol, unsigned char source[]); /* Code 128 and NVE-18 */ +extern int ean_128(struct zint_symbol *symbol, unsigned char source[]); /* EAN-128 (GS1-128) */ +extern int code_11(struct zint_symbol *symbol, unsigned char source[]); /* Code 11 */ +extern int msi_plessey(struct zint_symbol *symbol, unsigned char source[]); /* MSI Plessey without check digit */ +extern int msi_plessey_mod10(struct zint_symbol *symbol, unsigned char source[]); /* MSI with check as on Barcode Island */ +extern int msi_plessey_mod1010(struct zint_symbol *symbol, unsigned char source[]); /* MSI with two checks as Barcode Island */ +extern int msi_plessey_mod11(struct zint_symbol *symbol, unsigned char source[]); /* MSI with Mod 11 check as Wikipedia */ +extern int msi_plessey_mod1110(struct zint_symbol *symbol, unsigned char source[]); /* MSI with Mod 11 and Mod 10 */ +extern int telepen(struct zint_symbol *symbol, unsigned char source[]); /* Telepen ASCII */ +extern int telepen_num(struct zint_symbol *symbol, unsigned char source[]); /* Telepen Numeric */ +extern int plessey(struct zint_symbol *symbol, unsigned char source[]); /* Plessey Code */ +extern int pharma_one(struct zint_symbol *symbol, unsigned char source[]); /* Pharmacode One Track */ +/* extern int korea(struct zint_symbol *symbol, unsigned char source[]); */ +extern int flattermarken(struct zint_symbol *symbol, unsigned char source[]); /* Flattermarken */ +extern int fim(struct zint_symbol *symbol, unsigned char source[]); /* Facing Identification Mark */ +extern int pharma_two(struct zint_symbol *symbol, unsigned char source[]); /* Pharmacode Two Track */ +extern int post_plot(struct zint_symbol *symbol, unsigned char source[]); /* Postnet */ +extern int planet_plot(struct zint_symbol *symbol, unsigned char source[]); /* PLANET */ +extern int imail(struct zint_symbol *symbol, unsigned char source[]); /* Intelligent Mail (aka USPS OneCode) */ +extern int royal_plot(struct zint_symbol *symbol, unsigned char source[]); /* RM4SCC */ +extern int australia_post(struct zint_symbol *symbol, unsigned char source[]); /* Australia Post 4-state */ +extern int code16k(struct zint_symbol *symbol, unsigned char source[]); /* Code 16k */ +extern int pdf417enc(struct zint_symbol *symbol, unsigned char source[]); /* PDF417 */ +extern int dmatrix(struct zint_symbol *symbol, unsigned char source[]); /* Data Matrix (IEC16022) */ +extern int qr_code(struct zint_symbol *symbol, unsigned char source[]); /* QR Code */ +extern int micro_pdf417(struct zint_symbol *symbol, unsigned char source[]); /* Micro PDF417 */ +extern int maxicode(struct zint_symbol *symbol, unsigned char source[]); /* Maxicode */ +extern int rss14(struct zint_symbol *symbol, unsigned char source[]); /* RSS-14 */ +extern int rsslimited(struct zint_symbol *symbol, unsigned char source[]); /* RSS Limited */ +extern int rssexpanded(struct zint_symbol *symbol, unsigned char source[]); /* RSS Expanded */ +extern int composite(struct zint_symbol *symbol, unsigned char source[]); /* Composite Symbology */ +/* extern int aztec_mesa(struct zint_symbol *symbol, unsigned char source[]); */ +/* extern int ultra_sample(struct zint_symbol *symbol, unsigned char source[]); */ + +extern int png_plot(struct zint_symbol *symbol); +extern int ps_plot(struct zint_symbol *symbol); + +int ZBarcode_Encode(struct zint_symbol *symbol, unsigned char *input) +{ + int errno; + errno = 0; + + /* First check the symbology field */ + + if(symbol->symbology < 1) { strcpy(symbol->errtxt, "Symbology out of range, using Code 128"); symbol->symbology = BARCODE_CODE128; errno = WARN_INVALID_OPTION; } + + /* symbol->symbologys 1 to 86 are defined by tbarcode */ + if(symbol->symbology == 5) { symbol->symbology = BARCODE_C25MATRIX; } + if((symbol->symbology >= 10) && (symbol->symbology <= 12)) { symbol->symbology = BARCODE_EANX; } + if((symbol->symbology == 14) || (symbol->symbology == 15)) { symbol->symbology = BARCODE_EANX; } + if(symbol->symbology == 17) { symbol->symbology = BARCODE_UPCA; } + if(symbol->symbology == 19) { strcpy(symbol->errtxt, "Codabar 18 not supported, using Codabar"); symbol->symbology = BARCODE_CODABAR; errno = WARN_INVALID_OPTION; } + if(symbol->symbology == 24) { strcpy(symbol->errtxt, "Code 49 not supported, using Code 93"); symbol->symbology = BARCODE_CODE93; errno = WARN_INVALID_OPTION; } + if(symbol->symbology == 26) { symbol->symbology = BARCODE_UPCA; } + if(symbol->symbology == 27) { strcpy(symbol->errtxt, "UPCD1 not supported"); errno = ERROR_INVALID_OPTION; } + if(symbol->symbology == 33) { symbol->symbology = BARCODE_EAN128; } + if((symbol->symbology == 35) || (symbol->symbology == 36)) { symbol->symbology = BARCODE_UPCA; } + if((symbol->symbology == 38) || (symbol->symbology == 39)) { symbol->symbology = BARCODE_UPCE; } + if((symbol->symbology >= 41) && (symbol->symbology <= 45)) { symbol->symbology = BARCODE_POSTNET; } + if(symbol->symbology == 46) { symbol->symbology = BARCODE_PLESSEY; } + if(symbol->symbology == 48) { symbol->symbology = BARCODE_NVE18; } + if(symbol->symbology == 54) { strcpy(symbol->errtxt, "General Parcel Code not supported, using Code 128"); symbol->symbology = BARCODE_CODE128; errno = WARN_INVALID_OPTION; } + if((symbol->symbology == 59) || (symbol->symbology == 61)) { symbol->symbology = BARCODE_CODE128; } + if(symbol->symbology == 62) { symbol->symbology = BARCODE_CODE93; } + if((symbol->symbology == 64) || (symbol->symbology == 65)) { symbol->symbology = BARCODE_AUSPOST; } + if(symbol->symbology == 73) { strcpy(symbol->errtxt, "Codablock E not supported"); errno = ERROR_INVALID_OPTION; } + if(symbol->symbology == 74) { strcpy(symbol->errtxt, "Codablock F not supported"); errno = ERROR_INVALID_OPTION; } + if(symbol->symbology == 76) { strcpy(symbol->errtxt, "Japanese Postal Code not supported"); errno = ERROR_INVALID_OPTION; } + if(symbol->symbology == 77) { strcpy(symbol->errtxt, "Korean Postal Code not supported"); errno = ERROR_INVALID_OPTION; } + if(symbol->symbology == 78) { symbol->symbology = BARCODE_RSS14; } + if(symbol->symbology == 83) { symbol->symbology = BARCODE_PLANET; } + /* leave a gap for future expansion of tbarcode */ + if((symbol->symbology >= 87) && (symbol->symbology <= 99)) { strcpy(symbol->errtxt, "Symbology out of range, using Code 128\n"); symbol->symbology = BARCODE_CODE128; errno = WARN_INVALID_OPTION; } + /* Everything from 100 up is Zint-specific */ + if(symbol->symbology == 107) { strcpy(symbol->errtxt, "Aztec Code not yet supported"); errno = ERROR_INVALID_OPTION; } + if(symbol->symbology == 108) { strcpy(symbol->errtxt, "Supercode not yet supported"); errno = ERROR_INVALID_OPTION; } + if(symbol->symbology == 109) { strcpy(symbol->errtxt, "Ultracode not yet supported"); errno = ERROR_INVALID_OPTION; } + if(symbol->symbology >= 120) { strcpy(symbol->errtxt, "Symbology out of range, using Code 128"); symbol->symbology = BARCODE_CODE128; errno = WARN_INVALID_OPTION; } + + if(errno > 4) { + return errno; + } + + if(symbol->symbology == BARCODE_CODE16K) { + symbol->whitespace_width = 16; + symbol->border_width = 2; + symbol->output_options = BARCODE_BIND; + } + + if(symbol->symbology == BARCODE_ITF14) { + symbol->whitespace_width = 20; + symbol->border_width = 8; + symbol->output_options = BARCODE_BOX; + } + + switch(symbol->symbology) { + case BARCODE_C25MATRIX: errno = matrix_two_of_five(symbol, input); break; + case BARCODE_C25IND: errno = industrial_two_of_five(symbol, input); break; + case BARCODE_C25INTER: errno = interleaved_two_of_five(symbol, input); break; + case BARCODE_C25IATA: errno = iata_two_of_five(symbol, input); break; + case BARCODE_C25LOGIC: errno = logic_two_of_five(symbol, input); break; + case BARCODE_DPLEIT: errno = dpleit(symbol, input); break; + case BARCODE_DPIDENT: errno = dpident(symbol, input); break; + case BARCODE_UPCA: errno = eanx(symbol, input); break; + case BARCODE_UPCE: errno = eanx(symbol, input); break; + case BARCODE_EANX: errno = eanx(symbol, input); break; + case BARCODE_EAN128: errno = ean_128(symbol, input); break; + case BARCODE_CODE39: errno = c39(symbol, input); break; + case BARCODE_PZN: errno = pharmazentral(symbol, input); break; + case BARCODE_EXCODE39: errno = ec39(symbol, input); break; + case BARCODE_CODABAR: errno = codabar(symbol, input); break; + case BARCODE_CODE93: errno = c93(symbol, input); break; + case BARCODE_LOGMARS: errno = c39(symbol, input); break; + case BARCODE_CODE128: errno = code_128(symbol, input); break; + case BARCODE_CODE128B: errno = code_128(symbol, input); break; + case BARCODE_NVE18: errno = code_128(symbol, input); break; + case BARCODE_CODE11: errno = code_11(symbol, input); break; + case BARCODE_MSI_PLESSEY: errno = msi_plessey(symbol, input); break; + case BARCODE_MSI_10: errno = msi_plessey_mod10(symbol, input); break; + case BARCODE_MSI_10_10: errno = msi_plessey_mod1010(symbol, input); break; + case BARCODE_MSI_11: errno = msi_plessey_mod11(symbol, input); break; + case BARCODE_MSI_11_10: errno = msi_plessey_mod1110(symbol, input); break; + case BARCODE_TELEPEN: errno = telepen(symbol, input); break; + case BARCODE_TELEPEN_NUM: errno = telepen_num(symbol, input); break; + case BARCODE_PHARMA: errno = pharma_one(symbol, input); break; + case BARCODE_PLESSEY: errno = plessey(symbol, input); break; + case BARCODE_ITF14: errno = itf14(symbol, input); break; + /* case BARCODE_KOREAPOST: errno = korea(symbol, input); break; */ + case BARCODE_FLAT: errno = flattermarken(symbol, input); break; + case BARCODE_FIM: errno = fim(symbol, input); break; + case BARCODE_POSTNET: errno = post_plot(symbol, input); break; + case BARCODE_PLANET: errno = planet_plot(symbol, input); break; + case BARCODE_RM4SCC: errno = royal_plot(symbol, input); break; + case BARCODE_AUSPOST: errno = australia_post(symbol, input); break; + case BARCODE_AUSREPLY: errno = australia_post(symbol, input); break; + case BARCODE_AUSROUTE: errno = australia_post(symbol, input); break; + case BARCODE_AUSREDIRECT: errno = australia_post(symbol, input); break; + case BARCODE_CODE16K: errno = code16k(symbol, input); break; + case BARCODE_PHARMA_TWO: errno = pharma_two(symbol, input); break; + case BARCODE_ONECODE: errno = imail(symbol, input); break; + case BARCODE_DATAMATRIX: errno = dmatrix(symbol, input); break; + case BARCODE_PDF417: errno = pdf417enc(symbol, input); break; + case BARCODE_PDF417TRUNC: errno = pdf417enc(symbol, input); break; + case BARCODE_QRCODE: errno = qr_code(symbol, input); break; + case BARCODE_MICROPDF417: errno = micro_pdf417(symbol, input); break; + case BARCODE_ISBNX: errno = eanx(symbol, input); break; + case BARCODE_CODE39_43: errno = c39(symbol, input); break; + case BARCODE_EXCODE39_43: errno = ec39(symbol, input); break; + case BARCODE_MAXICODE: errno = maxicode(symbol, input); break; + case BARCODE_RSS14: errno = rss14(symbol, input); break; + case BARCODE_RSS14STACK: errno = rss14(symbol, input); break; + case BARCODE_RSS14STACK_OMNI: errno = rss14(symbol, input); break; + case BARCODE_RSS_LTD: errno = rsslimited(symbol, input); break; + case BARCODE_RSS_EXP: errno = rssexpanded(symbol, input); break; + case BARCODE_RSS_EXPSTACK: errno = rssexpanded(symbol, input); break; + case BARCODE_EANX_CC: errno = composite(symbol, input); break; + case BARCODE_EAN128_CC: errno = composite(symbol, input); break; + case BARCODE_RSS14_CC: errno = composite(symbol, input); break; + case BARCODE_RSS_LTD_CC: errno = composite(symbol, input); break; + case BARCODE_RSS_EXP_CC: errno = composite(symbol, input); break; + case BARCODE_UPCA_CC: errno = composite(symbol, input); break; + case BARCODE_UPCE_CC: errno = composite(symbol, input); break; + case BARCODE_RSS14STACK_CC: errno = composite(symbol, input); break; + case BARCODE_RSS14_OMNI_CC: errno = composite(symbol, input); break; + case BARCODE_RSS_EXPSTACK_CC: errno = composite(symbol, input); break; + /* case BARCODE_AZTEC: errno = aztec_mesa(symbol, input); break; */ + /* case BARCODE_ULTRA: errno = ultra(symbol, input); break; */ + } + + return errno; +} + +int ZBarcode_Print(struct zint_symbol *symbol) +{ + int errno; + char output[4]; + + if(strlen(symbol->outfile) > 3) { + output[0] = symbol->outfile[strlen(symbol->outfile) - 3]; + output[1] = symbol->outfile[strlen(symbol->outfile) - 2]; + output[2] = symbol->outfile[strlen(symbol->outfile) - 1]; + output[3] = '\0'; + to_upper(output); + if(!(strcmp(output, "PNG"))) { + if(symbol->symbology == BARCODE_MAXICODE) { + errno = maxi_png_plot(symbol); + } else { + errno = png_plot(symbol); + } + } else { + if(!(strcmp(output, "EPS"))) { + errno = ps_plot(symbol); + } else { + strcpy(symbol->errtxt, "error: unknown output format"); + return ERROR_INVALID_OPTION; + } + } + } else { + strcpy(symbol->errtxt, "error: unknown output format"); + return ERROR_INVALID_OPTION; + } + + return errno; +} + +int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input) +{ + int errno; + + errno = 0; + + errno = ZBarcode_Encode(symbol, input); + if(errno != 0) { + return errno; + } + + errno = ZBarcode_Print(symbol); + return errno; +} diff --git a/backend/maxicode.c b/backend/maxicode.c new file mode 100644 index 00000000..7b446588 --- /dev/null +++ b/backend/maxicode.c @@ -0,0 +1,681 @@ +/* maxicode.c - Handles Maxicode */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* This code has been thoroughly checked against ISO/IEC 16023:2000 */ + +#include "common.h" +#include "maxicode.h" +#include "reedsol.h" +#include + +int maxi_codeword[144]; + +void maxi_do_primary_check( ) +{ + /* Handles error correction of primary message */ + char data[15]; + char results[15]; + int j; + int datalen = 10; + int ecclen = 10; + + rs_init_gf(0x43); + rs_init_code(ecclen, 1); + + for(j = 0; j < datalen; j += 1) + data[j] = maxi_codeword[j]; + + rs_encode(datalen, data, results); + + for ( j = 0; j < ecclen; j += 1) + maxi_codeword[ datalen + j] = results[j]; +} + +void maxi_do_secondary_chk_odd( int ecclen ) +{ + /* Handles error correction of odd characters in secondary */ + char data[100]; + char results[30]; + int j; + int datalen = 68; + + rs_init_gf(0x43); + rs_init_code(ecclen, 1); + + if (ecclen == 20) + datalen = 84; + + for(j = 0; j < datalen; j += 1) + if ((j % 2) == 1) // odd + data[(j-1)/2] = maxi_codeword[j + 20]; + + rs_encode(datalen/2, data, results); + + for ( j = 0; j < (ecclen); j += 1) + maxi_codeword[ datalen + (2 *j) + 1 + 20 ] = results[j]; +} + +void maxi_do_secondary_chk_even(int ecclen ) +{ + /* Handles error correction of even characters in secondary */ + char data[100]; + char results[30]; + int j; + int datalen = 68; + + if (ecclen == 20) + datalen = 84; + + rs_init_gf(0x43); + rs_init_code(ecclen, 1); + + for(j = 0; j < datalen + 1; j += 1) + if ((j % 2) == 0) // even + data[j/2] = maxi_codeword[j + 20]; + + rs_encode(datalen/2, data, results); + + for ( j = 0; j < (ecclen); j += 1) + maxi_codeword[ datalen + (2 *j) + 20] = results[j]; +} + +int maxi_bump(int set[], int character[], int bump_posn) +{ + /* Moves everything up so that a shift or latch can be inserted */ + int i; + + for(i = 143; i > bump_posn; i--) { + set[i] = set[i - 1]; + character[i] = character[i - 1]; + } +} + +int maxi_text_process(int mode, unsigned char source[]) +{ + /* Format text according to Appendix A */ + + /* This code doesn't make use of [Lock in C], [Lock in D] + and [Lock in E] and so is not always the most efficient at + compressing data, but should suffice for most applications */ + + int set[144], character[144], i, j, done, count, length, current_set; + + length = strlen(source); + + if(length > 138) { + return ERROR_TOO_LONG; + } + + for(i = 0; i < 144; i++) { + set[i] = -1; + character[i] = 0; + } + + for (i = 0; i < length; i++) { + /* Look up characters in table from Appendix A - this gives + value and code set for most characters */ + set[i] = maxiCodeSet[source[i]]; + character[i] = maxiSymbolChar[source[i]]; + } + + /* If a character can be represented in more than one code set, + pick which version to use */ + if(set[0] == 0) { + if(character[0] == 13) { + character[0] = 0; + } + set[0] = 1; + } + + for(i = 1; i < length; i++) { + if(set[i] == 0) { + done = 0; + /* Special character */ + if(character[i] == 13) { + /* Carriage Return */ + if(set[i - 1] == 5) { + character[i] = 13; + set[i] = 5; + } else { + if((i != length - 1) && (set[i + 1] == 5)) { + character[i] = 13; + set[i] = 5; + } else { + character[i] = 0; + set[i] = 1; + } + } + done = 1; + } + + if((character[i] == 28) && (done == 0)) { + /* FS */ + if(set[i - 1] == 5) { + character[i] = 32; + set[i] = 5; + } else { + set[i] = set[i - 1]; + } + done = 1; + } + + if((character[i] == 29) && (done == 0)) { + /* GS */ + if(set[i - 1] == 5) { + character[i] = 33; + set[i] = 5; + } else { + set[i] = set[i - 1]; + } + done = 1; + } + + if((character[i] == 30) && (done == 0)) { + /* RS */ + if(set[i - 1] == 5) { + character[i] = 34; + set[i] = 5; + } else { + set[i] = set[i - 1]; + } + done = 1; + } + + if((character[i] == 32) && (done == 0)) { + /* Space */ + if(set[i - 1] == 1) { + character[i] = 32; + set[i] = 1; + } + if(set[i - 1] == 2) { + character[i] = 47; + set[i] = 2; + } + if(set[i - 1] >= 3) { + if(i != length - 1) { + if(set[i + 1] == 1) { + character[i] = 32; + set[i] = 1; + } + if(set[i + 1] == 2) { + character[i] = 47; + set[i] = 2; + } + if(set[i + 1] >= 3) { + character[i] = 59; + set[i] = set[i - 1]; + } + } else { + character[i] = 59; + set[i] = set[i - 1]; + } + } + done = 1; + } + + if((character[i] == 44) && (done == 0)) { + /* Comma */ + if(set[i - 1] == 2) { + character[i] = 48; + set[i] = 2; + } else { + if((i != length - 1) && (set[i + 1] == 2)) { + character[i] = 48; + set[i] = 2; + } else { + set[i] = 1; + } + } + done = 1; + } + + if((character[i] == 46) && (done == 0)) { + /* Full Stop */ + if(set[i - 1] == 2) { + character[i] = 49; + set[i] = 2; + } else { + if((i != length - 1) && (set[i + 1] == 2)) { + character[i] = 49; + set[i] = 2; + } else { + set[i] = 1; + } + } + done = 1; + } + + if((character[i] == 47) && (done == 0)) { + /* Slash */ + if(set[i - 1] == 2) { + character[i] = 50; + set[i] = 2; + } else { + if((i != length - 1) && (set[i + 1] == 2)) { + character[i] = 50; + set[i] = 2; + } else { + set[i] = 1; + } + } + done = 1; + } + + if((character[i] == 58) && (done == 0)) { + /* Colon */ + if(set[i - 1] == 2) { + character[i] = 51; + set[i] = 2; + } else { + if((i != length - 1) && (set[i + 1] == 2)) { + character[i] = 51; + set[i] = 2; + } else { + set[i] = 1; + } + } + done = 1; + } + } + } + + for(i = strlen(source); i < 144; i++) { + /* Add the padding */ + if(set[length - 1] == 2) { + set[i] = 2; + } else { + set[i] = 1; + } + character[i] = 33; + } + + /* Find candidates for number compression */ + if((mode == 2) || (mode ==3)) { j = 0; } else { j = 9; } + /* Number compression not allowed in primary message */ + count = 0; + for(i = j; i < 143; i++) { + if((set[i] == 1) && ((character[i] >= 48) && (character[i] <= 57))) { + /* Character is a number */ + count++; + } else { + count = 0; + } + if(count == 9) { + /* Nine digits in a row can be compressed */ + set[i] = 6; + set[i - 1] = 6; + set[i - 2] = 6; + set[i - 3] = 6; + set[i - 4] = 6; + set[i - 5] = 6; + set[i - 6] = 6; + set[i - 7] = 6; + set[i - 8] = 6; + count = 0; + } + } + + /* Add shift and latch characters */ + current_set = 1; + i = 0; + do { + + if(set[i] != current_set) { + switch(set[i]) { + case 1: + if(set[i + 1] == 1) { + if(set[i + 2] == 1) { + if(set[i + 3] == 1) { + /* Latch A */ + maxi_bump(set, character, i); + character[i] = 63; + current_set = 1; + length++; + } else { + /* 3 Shift A */ + maxi_bump(set, character, i); + character[i] = 57; + length++; + i += 2; + } + } else { + /* 2 Shift A */ + maxi_bump(set, character, i); + character[i] = 56; + length++; + i++; + } + } else { + /* Shift A */ + maxi_bump(set, character, i); + character[i] = 59; + length++; + } + break; + case 2: + if(set[i + 1] == 2) { + /* Latch B */ + maxi_bump(set, character, i); + character[i] = 63; + current_set = 2; + length++; + } else { + /* Shift B */ + maxi_bump(set, character, i); + character[i] = 59; + length++; + } + break; + case 3: + /* Shift C */ + maxi_bump(set, character, i); + character[i] = 60; + length++; + break; + case 4: + /* Shift D */ + maxi_bump(set, character, i); + character[i] = 61; + length++; + break; + case 5: + /* Shift E */ + maxi_bump(set, character, i); + character[i] = 62; + length++; + break; + case 6: + /* Number Compressed */ + /* Do nothing */ + break; + } + i++; + } + i++; + } while(i < 145); + + /* Number compression has not been forgotten! - It's handled below */ + i = 0; + do { + if (set[i] == 6) { + /* Number compression */ + char substring[10]; + int value; + + for(j = 0; j < 10; j++) { + substring[j] = character[i + j]; + } + substring[10] = '\0'; + value = atoi(substring); + + character[i] = 31; /* NS */ + character[i + 1] = (value & 0x3f000000) >> 24; + character[i + 2] = (value & 0xfc0000) >> 18; + character[i + 3] = (value & 0x3f000) >> 12; + character[i + 4] = (value & 0xfc0) >> 6; + character[i + 5] = (value & 0x3f); + + i += 6; + for(j = i; j < 140; j++) { + set[j] = set[j + 3]; + character[j] = character[j + 3]; + } + length -= 3; + } else { + i++; + } + } while (i <= 143); + + if(((mode ==2) || (mode == 3)) && (length > 84)) { + return ERROR_TOO_LONG; + } + + if(((mode == 4) || (mode == 6)) && (length > 93)) { + return ERROR_TOO_LONG; + } + + if((mode == 5) && (length > 77)) { + return ERROR_TOO_LONG; + } + + + /* Copy the encoded text into the codeword array */ + if((mode == 2) || (mode == 3)) { + for(i = 0; i < 84; i++) { /* secondary only */ + maxi_codeword[i + 20] = character[i]; + } + } + + if((mode == 4) || (mode == 6)) { + for(i = 0; i < 9; i++) { /* primary */ + maxi_codeword[i + 1] = character[i]; + } + for(i = 0; i < 84; i++) { /* secondary */ + maxi_codeword[i + 20] = character[i + 9]; + } + } + + if(mode == 5) { + for(i = 0; i < 9; i++) { /* primary */ + maxi_codeword[i + 1] = character[i]; + } + for(i = 0; i < 68; i++) { /* secondary */ + maxi_codeword[i + 20] = character[i + 9]; + } + } + + return 0; +} + +void maxi_do_primary_2(char postcode[], int country, int service) +{ + /* Format structured primary for Mode 2 */ + int postcode_length, postcode_num, i; + + for(i = 0; i < 10; i++) { + if((postcode[i] <= '0') || (postcode[i] >= '9')) { + postcode[i] = '\0'; + } + } + + postcode_length = strlen(postcode); + postcode_num = atoi(postcode); + + maxi_codeword[0] = ((postcode_num & 0x03) << 4) | 2; + maxi_codeword[1] = ((postcode_num & 0xfc) >> 2); + maxi_codeword[2] = ((postcode_num & 0x3f00) >> 8); + maxi_codeword[3] = ((postcode_num & 0xfc000) >> 14); + maxi_codeword[4] = ((postcode_num & 0x3f00000) >> 20); + maxi_codeword[5] = ((postcode_num & 0x3c000000) >> 26) | ((postcode_length & 0x3) << 4); + maxi_codeword[6] = ((postcode_length & 0x3c) >> 2) | ((country & 0x3) << 4); + maxi_codeword[7] = (country & 0xfc) >> 2; + maxi_codeword[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2); + maxi_codeword[9] = ((service & 0x3f0) >> 4); +} + +void maxi_do_primary_3(char postcode[], int country, int service) +{ + /* Format structured primary for Mode 3 */ + int i; + + to_upper(postcode); + for(i = 0; i < strlen(postcode); i++) { + if((postcode[i] >= 65) && (postcode[i] <= 90)) { + /* (Capital) letters shifted to Code Set A values */ + postcode[i] = postcode[i] - 64; + } + if(((postcode[i] == 27) || (postcode[i] == 31)) || ((postcode[i] == 33) || (postcode[i] >= 59))) { + /* Not a valid postcode character */ + postcode[i] = ' '; + } + /* Input characters lower than 27 (NUL - SUB) in postcode are + interpreted as capital letters in Code Set A (e.g. LF becomes 'J') */ + } + + maxi_codeword[0] = ((postcode[5] & 0x03) << 4) | 3; + maxi_codeword[1] = ((postcode[4] & 0x03) << 4) | ((postcode[5] & 0x3c) >> 2); + maxi_codeword[2] = ((postcode[3] & 0x03) << 4) | ((postcode[4] & 0x3c) >> 2); + maxi_codeword[3] = ((postcode[2] & 0x03) << 4) | ((postcode[3] & 0x3c) >> 2); + maxi_codeword[4] = ((postcode[1] & 0x03) << 4) | ((postcode[2] & 0x3c) >> 2); + maxi_codeword[5] = ((postcode[0] & 0x03) << 4) | ((postcode[1] & 0x3c) >> 2); + maxi_codeword[6] = ((postcode[0] & 0x3c) >> 2) | ((country & 0x3) << 4); + maxi_codeword[7] = (country & 0xfc) >> 2; + maxi_codeword[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2); + maxi_codeword[9] = ((service & 0x3f0) >> 4); +} + +int maxicode(struct zint_symbol *symbol, unsigned char source[]) +{ + int i, j, block, bit, mode, countrycode = 0, service = 0; + int bit_pattern[7], internal_error = 0, eclen; + char postcode[12], countrystr[4], servicestr[4]; + mode = symbol->option_1; + strcpy(postcode, ""); + strcpy(countrystr, ""); + strcpy(servicestr, ""); + + for(i = 0; i < 145; i++) { + maxi_codeword[i] = 0; + } + + if(mode == -1) { /* If mode is unspecified */ + if(strlen(symbol->primary) == 0) { + mode = 4; + } else { + mode = 2; + for(i = 0; i < 10; i++) { + if((symbol->primary[i] < 48) || (symbol->primary[i] > 57)) { + mode = 3; + } + } + } + } + + if((mode < 2) || (mode > 6)) { /* Only codes 2 to 6 supported */ + strcpy(symbol->errtxt, "Error: Invalid Maxicode Mode"); + return ERROR_INVALID_OPTION; + } + + if((mode == 2) || (mode == 3)) { /* Modes 2 and 3 need data in symbol->primary */ + if(strlen(symbol->primary) != 15) { + strcpy(symbol->errtxt, "Error: Invalid Primary String"); + return ERROR_INVALID_DATA; + } + + for(i = 9; i < 15; i++) { /* check that country code and service are numeric */ + if((symbol->primary[i] < 48) || (symbol->primary[i] > 57)) { + strcpy(symbol->errtxt, "Error: Invalid Primary String"); + return ERROR_INVALID_DATA; + } + } + + strncpy(postcode, symbol->primary, 9); + postcode[9] = '\0'; + + if(mode == 2) { + for(i = 0; i < 10; i++) { + if(postcode[i] == ' ') { + postcode[i] = '\0'; + } + } + } + + if(mode == 3) { postcode[6] = '\0'; } + + countrystr[0] = symbol->primary[9]; + countrystr[1] = symbol->primary[10]; + countrystr[2] = symbol->primary[11]; + countrystr[3] = '\0'; + + servicestr[0] = symbol->primary[12]; + servicestr[1] = symbol->primary[13]; + servicestr[2] = symbol->primary[14]; + servicestr[3] = '\0'; + + countrycode = atoi(countrystr); + service = atoi(servicestr); + + if(mode == 2) { maxi_do_primary_2(postcode, countrycode, service); } + if(mode == 3) { maxi_do_primary_3(postcode, countrycode, service); } + } else { + maxi_codeword[0] = mode; + } + + i = maxi_text_process(mode, source); + if(i == ERROR_TOO_LONG ) { + strcpy(symbol->errtxt, "Error: Input data too long"); + return i; + } + + /* All the data is sorted - now do error correction */ + maxi_do_primary_check(); /* always EEC */ + + if ( mode == 5 ) + eclen = 56; // 68 data codewords , 56 error corrections + else + eclen = 40; // 84 data codewords, 40 error corrections + + maxi_do_secondary_chk_even(eclen/2); // do error correction of even + maxi_do_secondary_chk_odd(eclen/2); // do error correction of odd + + /* Copy data into symbol grid */ + for(i = 0; i < 33; i++) { + for(j = 0; j < 30; j++) { + symbol->encoded_data[i][j] = '0'; + block = (MaxiGrid[(i * 30) + j] + 5) / 6; + bit = (MaxiGrid[(i * 30) + j] + 5) % 6; + + if(block != 0) { + + bit_pattern[0] = (maxi_codeword[block - 1] & 0x20) >> 5; + bit_pattern[1] = (maxi_codeword[block - 1] & 0x10) >> 4; + bit_pattern[2] = (maxi_codeword[block - 1] & 0x8) >> 3; + bit_pattern[3] = (maxi_codeword[block - 1] & 0x4) >> 2; + bit_pattern[4] = (maxi_codeword[block - 1] & 0x2) >> 1; + bit_pattern[5] = (maxi_codeword[block - 1] & 0x1); + + if(bit_pattern[bit] != 0) { + symbol->encoded_data[i][j] = '1'; + } + } + } + } + + /* Add orientation markings */ + symbol->encoded_data[0][28] = '1'; // Top right filler + symbol->encoded_data[0][29] = '1'; + symbol->encoded_data[9][10] = '1'; // Top left marker + symbol->encoded_data[9][11] = '1'; + symbol->encoded_data[10][11] = '1'; + symbol->encoded_data[15][7] = '1'; // Left hand marker + symbol->encoded_data[16][8] = '1'; + symbol->encoded_data[16][20] = '1'; // Right hand marker + symbol->encoded_data[17][20] = '1'; + symbol->encoded_data[22][10] = '1'; // Bottom left marker + symbol->encoded_data[23][10] = '1'; + symbol->encoded_data[22][17] = '1'; // Bottom right marker + symbol->encoded_data[23][17] = '1'; + + symbol->width = 30; + symbol->rows = 33; + + return internal_error; +} diff --git a/backend/maxicode.h b/backend/maxicode.h new file mode 100644 index 00000000..de470136 --- /dev/null +++ b/backend/maxicode.h @@ -0,0 +1,90 @@ +/* maxicode.h - Handles Maxicode */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +static int MaxiGrid[990] = { /* ISO/IEC 16023 Figure 5 - MaxiCode Module Sequence */ + 122, 121, 128, 127, 134, 133, 140, 139, 146, 145, 152, 151, 158, 157, 164, 163, 170, 169, 176, 175, 182, 181, 188, 187, 194, 193, 200, 199, 0, 0, + 124, 123, 130, 129, 136, 135, 142, 141, 148, 147, 154, 153, 160, 159, 166, 165, 172, 171, 178, 177, 184, 183, 190, 189, 196, 195, 202, 201, 817, 0, + 126, 125, 132, 131, 138, 137, 144, 143, 150, 149, 156, 155, 162, 161, 168, 167, 174, 173, 180, 179, 186, 185, 192, 191, 198, 197, 204, 203, 819, 818, + 284, 283, 278, 277, 272, 271, 266, 265, 260, 259, 254, 253, 248, 247, 242, 241, 236, 235, 230, 229, 224, 223, 218, 217, 212, 211, 206, 205, 820, 0, + 286, 285, 280, 279, 274, 273, 268, 267, 262, 261, 256, 255, 250, 249, 244, 243, 238, 237, 232, 231, 226, 225, 220, 219, 214, 213, 208, 207, 822, 821, + 288, 287, 282, 281, 276, 275, 270, 269, 264, 263, 258, 257, 252, 251, 246, 245, 240, 239, 234, 233, 228, 227, 222, 221, 216, 215, 210, 209, 823, 0, + 290, 289, 296, 295, 302, 301, 308, 307, 314, 313, 320, 319, 326, 325, 332, 331, 338, 337, 344, 343, 350, 349, 356, 355, 362, 361, 368, 367, 825, 824, + 292, 291, 298, 297, 304, 303, 310, 309, 316, 315, 322, 321, 328, 327, 334, 333, 340, 339, 346, 345, 352, 351, 358, 357, 364, 363, 370, 369, 826, 0, + 294, 293, 300, 299, 306, 305, 312, 311, 318, 317, 324, 323, 330, 329, 336, 335, 342, 341, 348, 347, 354, 353, 360, 359, 366, 365, 372, 371, 828, 827, + 410, 409, 404, 403, 398, 397, 392, 391, 80, 79, 0, 0, 14, 13, 38, 37, 3, 0, 45, 44, 110, 109, 386, 385, 380, 379, 374, 373, 829, 0, + 412, 411, 406, 405, 400, 399, 394, 393, 82, 81, 41, 0, 16, 15, 40, 39, 4, 0, 0, 46, 112, 111, 388, 387, 382, 381, 376, 375, 831, 830, + 414, 413, 408, 407, 402, 401, 396, 395, 84, 83, 42, 0, 0, 0, 0, 0, 6, 5, 48, 47, 114, 113, 390, 389, 384, 383, 378, 377, 832, 0, + 416, 415, 422, 421, 428, 427, 104, 103, 56, 55, 17, 0, 0, 0, 0, 0, 0, 0, 21, 20, 86, 85, 434, 433, 440, 439, 446, 445, 834, 833, + 418, 417, 424, 423, 430, 429, 106, 105, 58, 57, 0, 0, 0, 0, 0, 0, 0, 0, 23, 22, 88, 87, 436, 435, 442, 441, 448, 447, 835, 0, + 420, 419, 426, 425, 432, 431, 108, 107, 60, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 90, 89, 438, 437, 444, 443, 450, 449, 837, 836, + 482, 481, 476, 475, 470, 469, 49, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 54, 53, 464, 463, 458, 457, 452, 451, 838, 0, + 484, 483, 478, 477, 472, 471, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 466, 465, 460, 459, 454, 453, 840, 839, + 486, 485, 480, 479, 474, 473, 52, 51, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 43, 468, 467, 462, 461, 456, 455, 841, 0, + 488, 487, 494, 493, 500, 499, 98, 97, 62, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 92, 91, 506, 505, 512, 511, 518, 517, 843, 842, + 490, 489, 496, 495, 502, 501, 100, 99, 64, 63, 0, 0, 0, 0, 0, 0, 0, 0, 29, 28, 94, 93, 508, 507, 514, 513, 520, 519, 844, 0, + 492, 491, 498, 497, 504, 503, 102, 101, 66, 65, 18, 0, 0, 0, 0, 0, 0, 0, 19, 30, 96, 95, 510, 509, 516, 515, 522, 521, 846, 845, + 560, 559, 554, 553, 548, 547, 542, 541, 74, 73, 33, 0, 0, 0, 0, 0, 0, 11, 68, 67, 116, 115, 536, 535, 530, 529, 524, 523, 847, 0, + 562, 561, 556, 555, 550, 549, 544, 543, 76, 75, 0, 0, 8, 7, 36, 35, 12, 0, 70, 69, 118, 117, 538, 537, 532, 531, 526, 525, 849, 848, + 564, 563, 558, 557, 552, 551, 546, 545, 78, 77, 0, 34, 10, 9, 26, 25, 0, 0, 72, 71, 120, 119, 540, 539, 534, 533, 528, 527, 850, 0, + 566, 565, 572, 571, 578, 577, 584, 583, 590, 589, 596, 595, 602, 601, 608, 607, 614, 613, 620, 619, 626, 625, 632, 631, 638, 637, 644, 643, 852, 851, + 568, 567, 574, 573, 580, 579, 586, 585, 592, 591, 598, 597, 604, 603, 610, 609, 616, 615, 622, 621, 628, 627, 634, 633, 640, 639, 646, 645, 853, 0, + 570, 569, 576, 575, 582, 581, 588, 587, 594, 593, 600, 599, 606, 605, 612, 611, 618, 617, 624, 623, 630, 629, 636, 635, 642, 641, 648, 647, 855, 854, + 728, 727, 722, 721, 716, 715, 710, 709, 704, 703, 698, 697, 692, 691, 686, 685, 680, 679, 674, 673, 668, 667, 662, 661, 656, 655, 650, 649, 856, 0, + 730, 729, 724, 723, 718, 717, 712, 711, 706, 705, 700, 699, 694, 693, 688, 687, 682, 681, 676, 675, 670, 669, 664, 663, 658, 657, 652, 651, 858, 857, + 732, 731, 726, 725, 720, 719, 714, 713, 708, 707, 702, 701, 696, 695, 690, 689, 684, 683, 678, 677, 673, 671, 666, 665, 660, 659, 654, 653, 859, 0, + 734, 733, 740, 739, 746, 745, 752, 751, 758, 757, 764, 763, 770, 769, 776, 775, 782, 781, 788, 787, 794, 793, 800, 799, 806, 805, 812, 811, 861, 860, + 736, 735, 742, 741, 748, 747, 754, 753, 760, 759, 766, 765, 772, 771, 778, 777, 784, 783, 790, 789, 796, 795, 802, 801, 808, 807, 814, 813, 862, 0, + 738, 737, 744, 743, 750, 749, 756, 755, 762, 761, 768, 767, 774, 773, 780, 779, 786, 785, 792, 791, 798, 797, 804, 803, 810, 809, 816, 815, 864, 863 +}; + +int maxiCodeSet[256] = { /* from Appendix A - ASCII character to Code Set (e.g. 2 = Set B) */ + /* set 0 refers to special characters that fit into more than one set (e.g. GS) */ + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 5, 0, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 4, 5, 5, 5, 5, 5, 5, 4, 5, 3, 4, 3, 5, 5, 4, 4, 3, 3, 3, + 4, 3, 5, 4, 4, 3, 3, 4, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 +}; + +int maxiSymbolChar[256] = { /* from Appendix A - ASCII character to symbol value */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 30, 28, 29, 30, 35, 32, 53, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 37, + 38, 39, 40, 41, 52, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 42, 43, 44, 45, 46, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 32, 54, 34, 35, 36, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 36, + 37, 37, 38, 39, 40, 41, 42, 43, 38, 44, 37, 39, 38, 45, 46, 40, 41, 39, 40, 41, + 42, 42, 47, 43, 44, 43, 44, 45, 45, 46, 47, 46, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 32, + 33, 34, 35, 36, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 32, 33, 34, 35, 36 +}; + diff --git a/backend/maxipng.h b/backend/maxipng.h new file mode 100644 index 00000000..7e33794e --- /dev/null +++ b/backend/maxipng.h @@ -0,0 +1,588 @@ +/* maxipng.h - Shapes for Maxicode output to PNG file */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* This file contains the pixel-by-pixel representation of maxicode glyphs + at a resolution of 12 pixels per millimeter. hexagon[] is taken directly + from ISO 16023 Annex J. bullseye[] was calculated by the Gimp */ + +#define SSET "0123456789ABCDEF" + +static int hexagon[120] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static char bullseye[34532] = + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````````````````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````````````````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````````````" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````````````````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!````````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````````````" + "````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````````````````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````" + "````````````````````````````````````````````````````````````````" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````" + "````````````````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" + "!!!!````````````````````````````````````````````````````````````" + "````````````````````````````````````````````````````````````````" + "````````````````````````````````````"; + + + + diff --git a/backend/medical.c b/backend/medical.c new file mode 100644 index 00000000..ce891b44 --- /dev/null +++ b/backend/medical.c @@ -0,0 +1,237 @@ +/* medical.c - Handles 1 track and 2 track pharmacode and Codabar */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include "common.h" + +/* Codabar table checked against EN 798:1995 */ + +#define CASET "0123456789-$:/.+ABCD" +static char *CodaTable[20] = {"11111221", "11112211", "11121121", "22111111", "11211211", "21111211", + "12111121", "12112111", "12211111", "21121111", "11122111", "11221111", "21112121", "21211121", + "21212111", "11212121", "11221211", "12121121", "11121221", "11122211"}; + +int pharma_one(struct zint_symbol *symbol, unsigned char source[]) +{ + /* "Pharmacode can represent only a single integer from 3 to 131070. Unlike other + commonly used one-dimensional barcode schemes, pharmacode does not store the data in a + form corresponding to the human-readable digits; the number is encoded in binary, rather + than decimal. Pharmacode is read from right to left: with n as the bar position starting + at 0 on the right, each narrow bar adds 2n to the value and each wide bar adds 2(2^n). + The minimum barcode is 2 bars and the maximum 16, so the smallest number that could + be encoded is 3 (2 narrow bars) and the biggest is 131070 (16 wide bars)." + - http://en.wikipedia.org/wiki/Pharmacode */ + + /* This code uses the One Track Pharamacode calculating algorithm as recommended by + the specification at http://www.laetus.com/laetus.php?request=file&id=69 */ + + unsigned long int tester; + int counter; + char inter[17]; + int errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 6) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + strcpy(inter, ""); + tester = atoi(source); + + if((tester < 3) || (tester > 131070)) { + strcpy(symbol->errtxt, "error: data out of range"); + return ERROR_INVALID_DATA; + } + + do + { + if(tester%2 == 0) { + concat(inter, "W"); + tester = (tester - 2) / 2; + } else { + concat(inter, "N"); + tester = (tester - 1) / 2; + } + } + while(tester != 0); + + for(counter = (strlen(inter) - 1); counter >= 0; counter--) { + if(inter[counter] == 'W') { + concat(dest, "32"); + } else { + concat(dest, "12"); + } + } + + expand(symbol, dest); + strcpy(symbol->text, ""); + return errno; +} + +int pharma_two_calc(struct zint_symbol *symbol, unsigned char source[], char dest[]) +{ + /* This code uses the Two Track Pharamacode defined in the document at + http://www.laetus.com/laetus.php?request=file&id=69 and using a modified + algorithm from the One Track system. This standard accepts integet values + from 4 to 64570080. */ + + unsigned long int tester; + int counter; + char inter[17]; + int errno; + + errno = 0; + strcpy(dest, ""); + + strcpy(inter, ""); + tester = atoi(source); + + if((tester < 4) || (tester > 64570080)) + { + strcpy(symbol->errtxt, "error: data out of range"); + return ERROR_INVALID_DATA; + } + do + { + switch(tester%3) { + case 0: + concat(inter, "3"); + tester = (tester - 3) / 3; + break; + case 1: + concat(inter, "1"); + tester = (tester - 1) / 3; + break; + case 2: + concat(inter, "2"); + tester = (tester - 2) / 3; + break; + } + } + while(tester != 0); + + for(counter = (strlen(inter) - 1); counter >= 0; counter--) + { + dest[(strlen(inter) - 1) - counter] = inter[counter]; + } + dest[strlen(inter)] = '\0'; + + return errno; +} + +int pharma_two(struct zint_symbol *symbol, unsigned char source[]) +{ + /* Draws the patterns for two track pharmacode */ + char height_pattern[200]; + unsigned int loopey; + int writer; + int errno = 0; + strcpy(height_pattern, ""); + + if(strlen(source) > 8) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + errno = pharma_two_calc(symbol, source, height_pattern); + if(errno != 0) { + return errno; + } + + writer = 0; + for(loopey = 0; loopey < strlen(height_pattern); loopey++) + { + if((height_pattern[loopey] == '2') || (height_pattern[loopey] == '3')) + { + symbol->encoded_data[0][writer] = '1'; + } + if((height_pattern[loopey] == '1') || (height_pattern[loopey] == '3')) + { + symbol->encoded_data[1][writer] = '1'; + } + writer += 2; + } + symbol->rows = 2; + symbol->width = writer - 1; + + strcpy(symbol->text, ""); + return errno; +} + +int codabar(struct zint_symbol *symbol, unsigned char source[]) +{ /* The Codabar system consisting of simple substitution */ + + int i, errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 60) { /* No stack smashing please */ + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + to_upper(source); + errno = is_sane(CASET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* Codabar must begin and end with the characters A, B, C or D */ + if(((source[0] != 'A') && (source[0] != 'B')) && + ((source[0] != 'C') && (source[0] != 'D'))) + { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return 6; + } + + if(((source[strlen(source) - 1] != 'A') && (source[strlen(source) - 1] != 'B')) && + ((source[strlen(source) - 1] != 'C') && (source[strlen(source) - 1] != 'D'))) + { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return 6; + } + + for(i = 0; i <= strlen(source); i++) + { + lookup(CASET, CodaTable, source[i], dest); + } + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} diff --git a/backend/no_qr.c b/backend/no_qr.c new file mode 100644 index 00000000..eb7ba55a --- /dev/null +++ b/backend/no_qr.c @@ -0,0 +1,29 @@ +/* no_qr.c Handlier if no QR Encode library is available */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include "common.h" + +int qr_code(struct zint_symbol *symbol, unsigned char source[]) +{ + strcpy(symbol->errtxt, "error: QR Code library not available"); + return ERROR_INVALID_OPTION; +} diff --git a/backend/pdf417.c b/backend/pdf417.c new file mode 100644 index 00000000..2379058f --- /dev/null +++ b/backend/pdf417.c @@ -0,0 +1,1039 @@ +/* pdf417.c - Handles PDF417 stacked symbology */ + +/* Zint - A barcode generating program using libpng + Copyright (C) 2008 Robin Stuart + Portions Copyright (C) 2004 Grandzebu + Bug Fixes thanks to KL Chin + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* This code is adapted from "Code barre PDF 417 / PDF 417 barcode" v2.5.0 + which is Copyright (C) 2004 (Grandzebu). + The original code can be downloaded from http://grandzebu.net/index.php */ + +/* NOTE: symbol->option_1 is used to specify the security level (i.e. control the + number of check codewords) + + symbol->option_2 is used to adjust the width of the resulting symbol (i.e. the + number of codeword columns not including row start and end data) */ + +#include +#include +#include +#include +#include "pdf417.h" +#include "common.h" +#include "large.h" + +/* + Three figure numbers in comments give the location of command equivalents in the + original Visual Basic source code file pdf417.frm + this code retains some original (French) procedure and variable names to ease conversion */ + + + +int liste[2][1000]; /* global - okay, so I got _almost_ everything local! */ + +/* 866 */ +int quelmode(char codeascii) +{ + int mode; + mode = BYT; + + if((codeascii >= ' ') && (codeascii <= '~')) { mode = TEX; } + if(codeascii == '\t') { mode = TEX; } + if(codeascii == '\n') { mode = TEX; } + if(codeascii == 13) { mode = TEX; } + if((codeascii >= '0') && (codeascii <= '9')) { mode = NUM; } + /* 876 */ + return mode; +} + +/* 844 */ +void regroupe(int *indexliste) +{ + int i, j; + + /* bring together same type blocks */ + if(*(indexliste) > 1) { + i = 1; + while(i < *(indexliste)) { + if(liste[1][i - 1] == liste[1][i]) { + /* bring together */ + liste[0][i - 1] = liste[0][i - 1] + liste[0][i]; + j = i + 1; + + /* decreace the list */ + while(j < *(indexliste)) { + liste[0][j - 1] = liste[0][j]; + liste[1][j - 1] = liste[1][j]; + j++; + } + *(indexliste) = *(indexliste) - 1; + i--; + } + i++; + } + } + /* 865 */ +} + +/* 478 */ +void pdfsmooth(int *indexliste) +{ + int i, this, last, next, length; + + for(i = 0; i < *(indexliste); i++) { + this = liste[1][i]; + length = liste[0][i]; + if(i != 0) { last = liste[1][i - 1]; } else { last = FALSE; } + if(i != *(indexliste) - 1) { next = liste[1][i + 1]; } else { next = FALSE; } + + if(this == NUM) { + if(i == 0) { /* first block */ + if(*(indexliste) > 1) { /* and there are others */ + if((next == TEX) && (length < 8)) { liste[1][i] = TEX;} + if((next == BYT) && (length == 1)) { liste[1][i] = BYT; } + } + } else { + if(i == *(indexliste) - 1) { /* last block */ + if((last == TEX) && (length < 7)) { liste[1][i] = TEX; } + if((last == BYT) && (length == 1)) { liste[1][i] = BYT; } + } else { /* not first or last block */ + if(((last == BYT) && (next == BYT)) && (length < 4)) { liste[1][i] = BYT; } + if(((last == BYT) && (next == TEX)) && (length < 4)) { liste[1][i] = TEX; } + if(((last == TEX) && (next == BYT)) && (length < 5)) { liste[1][i] = TEX; } + if(((last == TEX) && (next == TEX)) && (length < 8)) { liste[1][i] = TEX; } + } + } + } + } + regroupe(indexliste); + /* 520 */ + for(i = 0; i < *(indexliste); i++) { + this = liste[1][i]; + length = liste[0][i]; + if(i != 0) { last = liste[1][i - 1]; } else { last = FALSE; } + if(i != *(indexliste) - 1) { next = liste[1][i + 1]; } else { next = FALSE; } + + if((this == TEX) && (i > 0)) { /* not the first */ + if(i == *(indexliste) - 1) { /* the last one */ + if((last == BYT) && (length == 1)) { liste[1][i] = BYT; } + } else { /* not the last one */ + if(((last == BYT) && (next == BYT)) && (length < 5)) { liste[1][i] = BYT; } + if((((last == BYT) && (next != BYT)) || ((last != BYT) && (next == BYT))) && (length < 3)) { + liste[1][i] = BYT; + } + } + } + } + /* 540 */ + regroupe(indexliste); +} + +/* 547 */ +void textprocess(int *chainemc, int *mclength, char chaine[], int start, int length, int block) +{ + int j, indexlistet, curtable, listet[2][5000], chainet[5000], wnet; + char codeascii; + + codeascii = 0; + wnet = 0; + + for(j = 0; j < 1000; j++) { + listet[0][j] = 0; + } + /* listet will contain the table numbers and the value of each characters */ + for(indexlistet = 0; indexlistet < length; indexlistet++) { + codeascii = chaine[start + indexlistet]; + switch(codeascii) { + case '\t': listet[0][indexlistet] = 12; listet[1][indexlistet] = 12; break; + case '\n': listet[0][indexlistet] = 8; listet[1][indexlistet] = 15; break; + case 13: listet[0][indexlistet] = 12; listet[1][indexlistet] = 11; break; + default: listet[0][indexlistet] = asciix[codeascii - 32]; + listet[1][indexlistet] = asciiy[codeascii - 32]; break; + } + } + + /* 570 */ + curtable = 1; /* default table */ + for(j = 0; j < length; j++) { + if(listet[0][j] & curtable) { /* The character is in the current table */ + chainet[wnet] = listet[1][j]; + wnet++; + } else { /* Obliged to change table */ + int flag = FALSE; /* True if we change table for only one character */ + if (j == (length - 1)) { + flag = TRUE; + } else { + if(!(listet[0][j] & listet[0][j + 1])) { flag = TRUE; } + } + + if (flag) { /* we change only one character - look for temporary switch */ + if((listet[0][j] & 1) && (curtable == 2)) { /* T_UPP */ + chainet[wnet] = 27; + chainet[wnet + 1] = listet[1][j]; + wnet += 2; + } + if(listet[0][j] & 8) { /* T_PUN */ + chainet[wnet] = 29; + chainet[wnet + 1] = listet[1][j]; + wnet += 2; + } + if(!(((listet[0][j] & 1) && (curtable == 2)) || (listet[0][j] & 8))) { + /* No temporary switch available */ + flag = FALSE; + } + } + + /* 599 */ + if (!(flag)) { + int newtable; + + if(j == (length - 1)) { + newtable = listet[0][j]; + } else { + if(!(listet[0][j] & listet[0][j + 1])) { + newtable = listet[0][j]; + } else { + newtable = listet[0][j] & listet[0][j + 1]; + } + } + + /* Maintain the first if several tables are possible */ + switch (newtable) { + case 3: + case 5: + case 7: + case 9: + case 11: + case 13: + case 15: + newtable = 1; break; + case 6: + case 10: + case 14: + newtable = 2; break; + case 12: + newtable = 4; break; + } + + /* 619 - select the switch */ + switch (curtable) { + case 1: + switch (newtable) { + case 2: chainet[wnet] = 27; wnet++; break; + case 4: chainet[wnet] = 28; wnet++; break; + case 8: chainet[wnet] = 28; wnet++; chainet[wnet] = 25; wnet++; break; + } break; + case 2: + switch (newtable) { + case 1: chainet[wnet] = 28; wnet++; chainet[wnet] = 28; wnet++; break; + case 4: chainet[wnet] = 28; wnet++; break; + case 8: chainet[wnet] = 28; wnet++; chainet[wnet] = 25; wnet++; break; + } break; + case 4: + switch (newtable) { + case 1: chainet[wnet] = 28; wnet++; break; + case 2: chainet[wnet] = 27; wnet++; break; + case 8: chainet[wnet] = 25; wnet++; break; + } break; + case 8: + switch (newtable) { + case 1: chainet[wnet] = 29; wnet++; break; + case 2: chainet[wnet] = 29; wnet++; chainet[wnet] = 27; wnet++; break; + case 4: chainet[wnet] = 29; wnet++; chainet[wnet] = 28; wnet++; break; + } break; + } + curtable = newtable; + /* 659 - at last we add the character */ + chainet[wnet] = listet[1][j]; + wnet++; + } + } + } + + /* 663 */ + if ((wnet % 2) > 0) { + chainet[wnet] = 29; + wnet++; + } + + /* Now translate the string chainet into codewords */ + if (block > 0) { + chainemc[*(mclength)] = 900; + *(mclength) = *(mclength) + 1; + } + + for(j = 0; j < wnet; j+= 2) { + int cw_number; + + cw_number = (30 * chainet[j]) + chainet[j + 1]; + chainemc[*(mclength)] = cw_number; + *(mclength) = *(mclength) + 1; + + } +} + +/* 671 */ +void byteprocess(int *chainemc, int *mclength, unsigned char chaine[], int start, int length, int block) +{ + + int i, j, k, l, loop, longueur; + double multiple, total; + short int accum[112], x_reg[112], y_reg[112]; + + if(length == 1) { + chainemc[*(mclength)] = 913; + chainemc[*(mclength) + 1] = chaine[start]; + *(mclength) = *(mclength) + 2; + } else { + /* select the switch for multiple of 6 bytes */ + if (length % 6 == 0) { + chainemc[*(mclength)] = 924; + *(mclength) = *(mclength) + 1; + } else { + chainemc[*(mclength)] = 901; + *(mclength) = *(mclength) + 1; + } + + j = 0; + while(j < length) { + longueur = length - j; + + if (longueur >= 6) { /* Take groups of 6 */ + + int cw[5]; + + for(i = 0; i < 112; i++) { + accum[i] = 0; + x_reg[i] = 0; + y_reg[i] = 0; + } + + longueur = 6; + for(k = 0; k < longueur; k++) { + for(i = 0; i < 8; i++) { + shiftup(y_reg); + } + + if((chaine[start + j + k] & 0x80) != 0) { y_reg[7] = 1; } + if((chaine[start + j + k] & 0x40) != 0) { y_reg[6] = 1; } + if((chaine[start + j + k] & 0x20) != 0) { y_reg[5] = 1; } + if((chaine[start + j + k] & 0x10) != 0) { y_reg[4] = 1; } + if((chaine[start + j + k] & 0x08) != 0) { y_reg[3] = 1; } + if((chaine[start + j + k] & 0x04) != 0) { y_reg[2] = 1; } + if((chaine[start + j + k] & 0x02) != 0) { y_reg[1] = 1; } + if((chaine[start + j + k] & 0x01) != 0) { y_reg[0] = 1; } + + } + + for(l = 0; l < 4; l++) { + + for(i = 0; i < 112; i++) { + accum[i] = y_reg[i]; + y_reg[i] = 0; + x_reg[i] = 0; + } + x_reg[101] = 1; + x_reg[100] = 1; + x_reg[99] = 1; + x_reg[94] = 1; + for(i = 92; i >= 0; i--) { + y_reg[i] = islarger(accum, x_reg); + if(y_reg[i] == 1) { + binary_subtract(accum, x_reg); + } + shiftdown(x_reg); + } + + cw[l] = (accum[9] * 512) + (accum[8] * 256) + + (accum[7] * 128) + (accum[6] * 64) + (accum[5] * 32) + + (accum[4] * 16) + (accum[3] * 8) + (accum[2] * 4) + + (accum[1] * 2) + accum[0]; + + } + + cw[4] = (y_reg[9] * 512) + (y_reg[8] * 256) + + (y_reg[7] * 128) + (y_reg[6] * 64) + (y_reg[5] * 32) + + (y_reg[4] * 16) + (y_reg[3] * 8) + (y_reg[2] * 4) + + (y_reg[1] * 2) + y_reg[0]; + + for(i = 0; i < 5; i++) { + chainemc[*(mclength)] = cw[4 - i]; + *(mclength) = *(mclength) + 1; + } + + } else { + /* If there remains a group of less than 6 bytes */ + for(k = 0; k < longueur; k++) { + chainemc[*(mclength)] = chaine[start + j + k]; + *(mclength) = *(mclength) + 1; + } + } + j += longueur; + + } + } +} + +/* 712 */ +void numbprocess(int *chainemc, int *mclength, char chaine[], int start, int length, int block) +{ + int j, loop, longueur, dummy[100], dumlength, diviseur, nombre; + char chainemod[50], chainemult[100], temp; + + strcpy(chainemod, ""); + for(loop = 0; loop <= 50; loop++) { + dummy[loop] = 0; + } + + chainemc[*(mclength)] = 902; + *(mclength) = *(mclength) + 1; + + j = 0; + while(j < length) { + dumlength = 0; + strcpy(chainemod, ""); + longueur = length - j; + if(longueur > 44) { longueur = 44; } + concat(chainemod, "1"); + for(loop = 1; loop <= longueur; loop++) { + chainemod[loop] = chaine[start + loop + j - 1]; + } + chainemod[longueur + 1] = '\0'; + do { + diviseur = 900; + + /* 877 - gosub Modulo */ + strcpy(chainemult, ""); + nombre = 0; + while(strlen(chainemod) != 0) { + nombre *= 10; + nombre += ctoi(chainemod[0]); + for(loop = 0; loop < strlen(chainemod); loop++) { + chainemod[loop] = chainemod[loop + 1]; + } + if (nombre < diviseur) { + if (strlen(chainemult) != 0) { concat(chainemult, "0"); } + } else { + temp = (nombre / diviseur) + '0'; + chainemult[strlen(chainemult) + 1] = '\0'; + chainemult[strlen(chainemult)] = temp; + } + nombre = nombre % diviseur; + } + diviseur = nombre; + /* return to 723 */ + + for(loop = dumlength; loop > 0; loop--) { + dummy[loop] = dummy[loop - 1]; + } + dummy[0] = diviseur; + dumlength++; + strcpy(chainemod, chainemult); + } while(strlen(chainemult) != 0); + for(loop = 0; loop < dumlength; loop++) { + chainemc[*(mclength)] = dummy[loop]; + *(mclength) = *(mclength) + 1; + } + j += longueur; + } +} + +/* 366 */ +int pdf417(struct zint_symbol *symbol, unsigned char chaine[]) +{ + int i, k, j, indexchaine, indexliste, mode, longueur, loop, mccorrection[520], offset; + int total, chainemc[2700], mclength, c1, c2, c3, dummy[35], codeerr; + char codebarre[100], pattern[580]; + + codeerr = 0; + + /* 456 */ + indexliste = 0; + indexchaine = 0; + + mode = quelmode(chaine[indexchaine]); + + for(i = 0; i < 1000; i++) { + liste[0][i] = 0; + } + + /* 463 */ + do { + liste[1][indexliste] = mode; + while ((liste[1][indexliste] == mode) && (indexchaine < strlen(chaine))) { + liste[0][indexliste]++; + indexchaine++; + mode = quelmode(chaine[indexchaine]); + } + indexliste++; + } while (indexchaine < strlen(chaine)); + + /* 474 */ + pdfsmooth(&indexliste); + + /* 541 - now compress the data */ + indexchaine = 0; + mclength = 0; + for(i = 0; i < indexliste; i++) { + switch(liste[1][i]) { + case TEX: /* 547 - text mode */ + textprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], i); + break; + case BYT: /* 670 - octet stream mode */ + byteprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], i); + break; + case NUM: /* 712 - numeric mode */ + numbprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], i); + break; + } + indexchaine = indexchaine + liste[0][i]; + } + + /* 752 - Now take care of the number of CWs per row */ + if (symbol->option_1 < 0) { + /* note that security level 8 is never used automatically */ + symbol->option_1 = 7; + if(mclength <= 1280) { symbol->option_1 = 6; } + if(mclength <= 640) { symbol->option_1 = 5; } + if(mclength <= 320) { symbol->option_1 = 4; } + if(mclength <= 160) { symbol->option_1 = 3; } + if(mclength <= 40) { symbol->option_1 = 2; } + } + k = 1; + for(loop = 1; loop <= (symbol->option_1 + 1); loop++) + { + k *= 2; + } + + longueur = mclength; + if(symbol->option_2 > 30) { symbol->option_2 = 30; } + if(symbol->option_2 < 1) { + /* This is a much more simple formula to Grand Zebu's - + it does not try to make the symbol square */ + symbol->option_2 = 0.5 + sqrt((longueur + k) / 3); + } + if(((longueur + k) / symbol->option_2) > 90) { + /* stop the symbol from becoming too high */ + symbol->option_2 = symbol->option_2 + 1; + } + + /* Reduce the correction level if there isn't room */ + /* while((longueur + k > PDF_MAX) && (symbol->option_1 > 0)) { + symbol->option_1 = symbol->option_1 - 1; + for(loop = 0; loop <= (symbol->option_1 + 1); loop++) + { + k *= 2; + } + } */ + /* this bit of the code would allow Zint to happily encode 2698 code words with + only 2 check digits, so I have abandoned it! - Zint now insists on a proportional + amount of check data unless overruled by the user */ + + if(longueur + k > PDF_MAX) { + return 2; + } + if(((longueur + k) / symbol->option_2) > 90) { + return 4; + } + + /* 781 - Padding calculation */ + longueur = mclength + 1 + k; + i = 0; + if ((longueur / symbol->option_2) < 3) { + i = (symbol->option_2 * 3) - longueur; /* A bar code must have at least three rows */ + } else { + if((longueur % symbol->option_2) > 0) { i = symbol->option_2 - (longueur % symbol->option_2); } + } + /* We add the padding */ + while (i > 0) { + chainemc[mclength] = 900; + mclength++; + i--; + } + /* we add the length descriptor */ + for(i = mclength; i > 0; i--) { + chainemc[i] = chainemc[i - 1]; + } + chainemc[0] = mclength + 1; + mclength++; + + /* 796 - we now take care of the Reed Solomon codes */ + switch(symbol->option_1) { + case 1: offset = 2; break; + case 2: offset = 6; break; + case 3: offset = 14; break; + case 4: offset = 30; break; + case 5: offset = 62; break; + case 6: offset = 126; break; + case 7: offset = 254; break; + case 8: offset = 510; break; + default: offset = 0; break; + } + + longueur = mclength; + for(loop = 0; loop < 520; loop++) { + mccorrection[loop] = 0; + } + total = 0; + 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 * coefrs[offset + j]) % 929) % 929; + } else { + mccorrection[j] = (mccorrection[j - 1] + 929 - (total * 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]; + mclength++; + } + + /* 818 - The CW string is finished */ + c1 = (mclength / symbol->option_2 - 1) / 3; + c2 = symbol->option_1 * 3 + (mclength / symbol->option_2 - 1) % 3; + c3 = symbol->option_2 - 1; + + /* we now encode each row */ + for(i = 0; i <= (mclength / symbol->option_2) - 1; i++) { + for(j = 0; j < symbol->option_2 ; j++) { + dummy[j + 1] = chainemc[i * symbol->option_2 + j]; + } + k = (i / 3) * 30; + switch(i % 3) { + /* follows this pattern from US Patent 5,243,655: + Row 0: L0 (row #, # of rows) R0 (row #, # of columns) + Row 1: L1 (row #, security level) R1 (row #, # of rows) + Row 2: L2 (row #, # of columns) R2 (row #, security level) + Row 3: L3 (row #, # of rows) R3 (row #, # of columns) + etc. */ + case 0: + dummy[0] = k + c1; + dummy[symbol->option_2 + 1] = k + c3; + break; + case 1: + dummy[0] = k + c2; + dummy[symbol->option_2 + 1] = k + c1; + break; + case 2: + dummy[0] = k + c3; + dummy[symbol->option_2 + 1] = k + c2; + break; + } + strcpy(codebarre, "+*"); /* Start with a start char and a separator */ + if(symbol->symbology == BARCODE_PDF417TRUNC) { + /* truncated - so same as before except knock off the last 5 chars */ + for(j = 0; j <= symbol->option_2; j++) { + switch(i % 3) { + case 1: offset = 929; break; + case 2: offset = 1858; break; + default: offset = 0; break; + } + concat(codebarre, codagemc[offset + dummy[j]]); + concat(codebarre, "*"); + } + } else { + /* normal PDF417 symbol */ + for(j = 0; j <= symbol->option_2 + 1; j++) { + switch(i % 3) { + case 1: offset = 929; /* cluster(3) */ break; + case 2: offset = 1858; /* cluster(6) */ break; + default: offset = 0; /* cluster(0) */ break; + } + concat(codebarre, codagemc[offset + dummy[j]]); + concat(codebarre, "*"); + } + concat(codebarre, "-"); + } + + strcpy(pattern, ""); + for(loop = 0; loop < strlen(codebarre); loop++) { + lookup(BRSET, PDFttf, codebarre[loop], pattern); + } + for(loop = 0; loop < strlen(pattern); loop++) { + symbol->encoded_data[i][loop] = pattern[loop]; + } + symbol->row_height[i] = 3; + } + symbol->rows = (mclength / symbol->option_2); + symbol->width = strlen(pattern); + + /* 843 */ + return codeerr; +} + +/* 345 */ +int pdf417enc(struct zint_symbol *symbol, unsigned char source[]) +{ + int codeerr, errno; + + errno = 0; + + if((symbol->option_1 < -1) || (symbol->option_1 > 8)) { + strcpy(symbol->errtxt, "warning: security value out of range"); + symbol->option_1 = -1; + errno = WARN_INVALID_OPTION; + } + if((symbol->option_2 < 0) || (symbol->option_2 > 30)) { + strcpy(symbol->errtxt, "warning: number of columns out of range"); + symbol->option_2 = 0; + errno = WARN_INVALID_OPTION; + } + + /* 349 */ + codeerr = pdf417(symbol, source); + + /* 352 */ + if(codeerr != 0) { + switch(codeerr) { + case 1: + strcpy(symbol->errtxt, "error: no such file or file unreadable (PDF error 1)"); + errno = ERROR_INVALID_OPTION; + break; + case 2: + strcpy(symbol->errtxt, "error: input string too long (PDF error 2)"); + errno = ERROR_TOO_LONG; + break; + case 3: + strcpy(symbol->errtxt, "error: number of codewords per row too small (PDF error 3)"); + errno = WARN_INVALID_OPTION; + break; + case 4: + strcpy(symbol->errtxt, "error: data too long for specified number of columns (PDF error 4)"); + errno = ERROR_TOO_LONG; + break; + default: + strcpy(symbol->errtxt, "error: something strange happened"); + errno = ERROR_ENCODING_PROBLEM; + break; + } + } + + /* 364 */ + return errno; +} + + +int micro_pdf417(struct zint_symbol *symbol, unsigned char chaine[]) +{ /* like PDF417 only much smaller! */ + + int i, k, j, indexchaine, indexliste, mode, longueur, mccorrection[50], offset; + int total, chainemc[2700], mclength, dummy[5], codeerr; + char codebarre[100], pattern[580]; + int variant, LeftRAPStart, CentreRAPStart, RightRAPStart, StartCluster; + int LeftRAP, CentreRAP, RightRAP, Cluster, writer, flip, loop; + + /* Encoding starts out the same as PDF417, so use the same code */ + codeerr = 0; + + /* 456 */ + indexliste = 0; + indexchaine = 0; + + mode = quelmode(chaine[indexchaine]); + + for(i = 0; i < 1000; i++) { + liste[0][i] = 0; + } + + /* 463 */ + do { + liste[1][indexliste] = mode; + while ((liste[1][indexliste] == mode) && (indexchaine < strlen(chaine))) { + liste[0][indexliste]++; + indexchaine++; + mode = quelmode(chaine[indexchaine]); + } + indexliste++; + } while (indexchaine < strlen(chaine)); + + /* 474 */ + pdfsmooth(&indexliste); + + /* 541 - now compress the data */ + indexchaine = 0; + mclength = 0; + for(i = 0; i < indexliste; i++) { + switch(liste[1][i]) { + case TEX: /* 547 - text mode */ + textprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], i); + break; + case BYT: /* 670 - octet stream mode */ + byteprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], i); + break; + case NUM: /* 712 - numeric mode */ + numbprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], i); + break; + } + indexchaine = indexchaine + liste[0][i]; + } + + /* This is where it all changes! */ + + if(mclength > 126) { + strcpy(symbol->errtxt, "error: input data too long"); + return ERROR_TOO_LONG; + } + if(symbol->option_2 > 4) { + strcpy(symbol->errtxt, "warning: specified width out of range"); + symbol->option_2 = 0; + codeerr = WARN_INVALID_OPTION; + } + + /* Now figure out which variant of the symbol to use and load values accordingly */ + + variant = 0; + + if((symbol->option_2 == 1) && (mclength > 20)) { + /* the user specified 1 column but the data doesn't fit - go to automatic */ + symbol->option_2 = 0; + strcpy(symbol->errtxt, "warning: specified symbol size too small for data"); + codeerr = WARN_INVALID_OPTION; + } + + if((symbol->option_2 == 2) && (mclength > 37)) { + /* the user specified 2 columns but the data doesn't fit - go to automatic */ + symbol->option_2 = 0; + strcpy(symbol->errtxt, "warning: specified symbol size too small for data"); + codeerr = WARN_INVALID_OPTION; + } + + if((symbol->option_2 == 3) && (mclength > 82)) { + /* the user specified 3 columns but the data doesn't fit - go to automatic */ + symbol->option_2 = 0; + strcpy(symbol->errtxt, "warning: specified symbol size too small for data"); + codeerr = WARN_INVALID_OPTION; + } + + if(symbol->option_2 == 1) { + /* the user specified 1 column and the data does fit */ + variant = 6; + if(mclength <= 16) { variant = 5; } + if(mclength <= 12) { variant = 4; } + if(mclength <= 10) { variant = 3; } + if(mclength <= 7) { variant = 2; } + if(mclength <= 4) { variant = 1; } + } + + if(symbol->option_2 == 2) { + /* the user specified 2 columns and the data does fit */ + variant = 13; + if(mclength <= 33) { variant = 12; } + if(mclength <= 29) { variant = 11; } + if(mclength <= 24) { variant = 10; } + if(mclength <= 19) { variant = 9; } + if(mclength <= 13) { variant = 8; } + if(mclength <= 8) { variant = 7; } + } + + if(symbol->option_2 == 3) { + /* the user specified 3 columns and the data does fit */ + variant = 23; + if(mclength <= 70) { variant = 22; } + if(mclength <= 58) { variant = 21; } + if(mclength <= 46) { variant = 20; } + if(mclength <= 34) { variant = 19; } + if(mclength <= 24) { variant = 18; } + if(mclength <= 18) { variant = 17; } + if(mclength <= 14) { variant = 16; } + if(mclength <= 10) { variant = 15; } + if(mclength <= 6) { variant = 14; } + } + + if(symbol->option_2 == 4) { + /* the user specified 4 columns and the data does fit */ + variant = 34; + if(mclength <= 108) { variant = 33; } + if(mclength <= 90) { variant = 32; } + if(mclength <= 72) { variant = 31; } + if(mclength <= 54) { variant = 30; } + if(mclength <= 39) { variant = 29; } + if(mclength <= 30) { variant = 28; } + if(mclength <= 24) { variant = 27; } + if(mclength <= 18) { variant = 26; } + if(mclength <= 12) { variant = 25; } + if(mclength <= 8) { variant = 24; } + } + + if(variant == 0) { + /* Zint can choose automatically from all available variations */ + for(i = 27; i >= 0; i--) { + + if(MicroAutosize[i] >= mclength) { + variant = MicroAutosize[i + 28]; + } + } + } + + /* Now we have the variant we can load the data */ + variant --; + symbol->option_2 = MicroVariants[variant]; /* columns */ + symbol->rows = MicroVariants[variant + 34]; /* rows */ + k = MicroVariants[variant + 68]; /* number of EC CWs */ + longueur = (symbol->option_2 * symbol->rows) - k; /* number of non-EC CWs */ + i = longueur - mclength; /* amount of padding required */ + offset = MicroVariants[variant + 102]; /* coefficient offset */ + + /* We add the padding */ + while (i > 0) { + chainemc[mclength] = 900; + mclength++; + i--; + } + + /* Reed-Solomon error correction */ + longueur = mclength; + for(loop = 0; loop < 50; loop++) { + mccorrection[loop] = 0; + } + total = 0; + 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 * Microcoeffs[offset + j]) % 929) % 929; + } else { + mccorrection[j] = (mccorrection[j - 1] + 929 - (total * 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]; + mclength++; + } + + /* Now get the RAP (Row Address Pattern) start values */ + LeftRAPStart = RAPTable[variant]; + CentreRAPStart = RAPTable[variant + 34]; + RightRAPStart = RAPTable[variant + 68]; + StartCluster = 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++) { + strcpy(codebarre, ""); + offset = 929 * Cluster; + for(j = 0; j < 5; j++) { + dummy[j] = 0; + } + for(j = 0; j < symbol->option_2 ; j++) { + dummy[j + 1] = chainemc[i * symbol->option_2 + j]; + } + /* Copy the data into codebarre */ + concat(codebarre, RAPLR[LeftRAP]); + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[1]]); + concat(codebarre, "1"); + if(symbol->option_2 == 3) { + concat(codebarre, RAPC[CentreRAP]); + } + if(dummy[2] != 0) { + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[2]]); + concat(codebarre, "1"); + } + if(symbol->option_2 == 4) { + concat(codebarre, RAPC[CentreRAP]); + } + if(dummy[3] != 0) { + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[3]]); + concat(codebarre, "1"); + } + if(dummy[4] != 0) { + concat(codebarre, "1"); + concat(codebarre, codagemc[offset + dummy[4]]); + concat(codebarre, "1"); + } + concat(codebarre, RAPLR[RightRAP]); + concat(codebarre, "1"); /* stop */ + + /* Now codebarre is a mixture of letters and numbers */ + + writer = 0; + flip = 1; + strcpy(pattern, ""); + for(loop = 0; loop < strlen(codebarre); loop++) { + if((codebarre[loop] >= '0') && (codebarre[loop] <= '9')) { + for(k = 0; k < ctoi(codebarre[loop]); k++) { + if(flip == 0) { + pattern[writer] = '0'; + } else { + pattern[writer] = '1'; + } + writer++; + } + pattern[writer] = '\0'; + if(flip == 0) { + flip = 1; + } else { + flip = 0; + } + } else { + lookup(BRSET, PDFttf, codebarre[loop], pattern); + writer += 5; + } + } + symbol->width = writer; + + /* so now pattern[] holds the string of '1's and '0's. - copy this to the symbol */ + for(loop = 0; loop < strlen(pattern); loop++) { + symbol->encoded_data[i][loop] = pattern[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; + } + } + + return codeerr; +} + diff --git a/backend/pdf417.h b/backend/pdf417.h new file mode 100644 index 00000000..def9ccce --- /dev/null +++ b/backend/pdf417.h @@ -0,0 +1,454 @@ +/* pdf417.h - PDF417 tables and coefficients */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 Robin Stuart (zint@hotmail.co.uk) + Portions Copyright (C) 2004 Grandzebu + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* this file contains the character table, the pre-calculated coefficients and the + codeword patterns taken from lines 416 to 454 of pdf417.frm */ + +#define TRUE 1 +#define FALSE 0 +#define TEX 900 +#define BYT 901 +#define NUM 902 +#define PDF_MAX 928 + +#define BRSET "ABCDEFabcdefghijklmnopqrstuvwxyz*+-" + +/* text mode processing tables */ +static int asciix[95] = { 7, 8, 8, 4, 12, 4, 4, 8, 8, 8, 12, 4, 12, 12, 12, 12, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 12, 8, 8, 4, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 8, 8, 8, 4, 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 8, 8, 8, 8 }; +static int asciiy[95] = { 26, 10, 20, 15, 18, 21, 10, 28, 23, 24, 22, 20, 13, 16, 17, 19, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 14, 0, 1, 23, 2, 25, 3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 4, 5, 6, 24, 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 21, 27, 9 }; + +/* PDF417 error correction coefficients from Grand Zebu */ +static int coefrs[1022] = { + /* k = 2 */ + 27, 917, + + /* k = 4 */ + 522, 568, 723, 809, + + /* k = 8 */ + 237, 308, 436, 284, 646, 653, 428, 379, + + /* k = 16 */ + 274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65, + + /* k = 32 */ + 361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, + 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410, + + /* k = 64 */ + 539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, 877, 381, 612, + 723, 476, 462, 172, 430, 609, 858, 822, 543, 376, 511, 400, 672, 762, 283, 184, + 440, 35, 519, 31, 460, 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502, + 648, 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, 623, 264, 543, + + /* k = 128 */ + 521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, 925, 749, 415, + 822, 93, 217, 208, 928, 244, 583, 620, 246, 148, 447, 631, 292, 908, 490, 704, + 516, 258, 457, 907, 594, 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569, + 193, 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, 463, 646, 776, + 171, 491, 297, 763, 156, 732, 95, 270, 447, 90, 507, 48, 228, 821, 808, 898, + 784, 663, 627, 378, 382, 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616, + 157, 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, 587, 804, 34, + 211, 330, 539, 297, 827, 865, 37, 517, 834, 315, 550, 86, 801, 4, 108, 539, + + /* k = 256 */ + 524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, 786, 138, 720, + 858, 194, 311, 913, 275, 190, 375, 850, 438, 733, 194, 280, 201, 280, 828, 757, + 710, 814, 919, 89, 68, 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137, + 439, 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, 549, 209, 884, + 315, 70, 329, 793, 490, 274, 877, 162, 749, 812, 684, 461, 334, 376, 849, 521, + 307, 291, 803, 712, 19, 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470, + 637, 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, 538, 906, 90, + 2, 290, 743, 199, 655, 903, 329, 49, 802, 580, 355, 588, 188, 462, 10, 134, + 628, 320, 479, 130, 739, 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234, + 722, 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, 60, 732, 621, + 895, 544, 261, 852, 655, 309, 697, 755, 756, 60, 231, 773, 434, 421, 726, 528, + 503, 118, 49, 795, 32, 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550, + 73, 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, 791, 893, 754, + 605, 383, 228, 749, 760, 213, 54, 297, 134, 54, 834, 299, 922, 191, 910, 532, + 609, 829, 189, 20, 167, 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173, + 404, 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, 55, 497, 10, + + /* k = 512 */ + 352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, 380, 350, 492, + 197, 265, 920, 155, 914, 299, 229, 643, 294, 871, 306, 88, 87, 193, 352, 781, + 846, 75, 327, 520, 435, 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534, + 539, 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, 916, 552, 41, + 542, 289, 122, 272, 383, 800, 485, 98, 752, 472, 761, 107, 784, 860, 658, 741, + 290, 204, 681, 407, 855, 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142, + 808, 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, 192, 516, 258, + 240, 518, 794, 395, 768, 848, 51, 610, 384, 168, 190, 826, 328, 596, 786, 303, + 570, 381, 415, 641, 156, 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402, + 40, 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, 92, 358, 785, + 288, 357, 850, 836, 827, 736, 707, 94, 8, 494, 114, 521, 2, 499, 851, 543, + 152, 729, 771, 95, 248, 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820, + 669, 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, 591, 452, 578, + 37, 124, 298, 332, 552, 43, 427, 119, 662, 777, 475, 850, 764, 364, 578, 911, + 283, 711, 472, 420, 245, 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408, + 842, 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, 159, 672, 729, + 624, 59, 193, 417, 158, 209, 563, 564, 343, 693, 109, 608, 563, 365, 181, 772, + 677, 310, 248, 353, 708, 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777, + 618, 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, 247, 184, 45, + 787, 680, 18, 66, 407, 369, 54, 492, 228, 613, 830, 922, 437, 519, 644, 905, + 789, 420, 305, 441, 207, 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341, + 242, 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, 665, 397, 808, + 851, 309, 473, 795, 378, 31, 647, 915, 459, 806, 590, 731, 425, 216, 548, 249, + 321, 881, 699, 535, 673, 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791, + 660, 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, 336, 286, 437, + 375, 273, 610, 296, 183, 923, 116, 667, 751, 353, 62, 366, 691, 379, 687, 842, + 37, 357, 720, 742, 330, 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316, + 342, 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, 610, 46, 656, + 447, 171, 616, 464, 190, 531, 297, 321, 762, 752, 533, 175, 134, 14, 381, 433, + 717, 45, 111, 20, 596, 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780, + 407, 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, 223, 849, 647, + 63, 310, 863, 251, 366, 304, 282, 738, 675, 410, 389, 244, 31, 121, 303, 263 }; + + +static char *codagemc[2787] = { "urA", "xfs", "ypy", "unk", "xdw", "yoz", "pDA", "uls", "pBk", "eBA", + "pAs", "eAk", "prA", "uvs", "xhy", "pnk", "utw", "xgz", "fDA", "pls", "fBk", "frA", "pvs", + "uxy", "fnk", "ptw", "uwz", "fls", "psy", "fvs", "pxy", "ftw", "pwz", "fxy", "yrx", "ufk", + "xFw", "ymz", "onA", "uds", "xEy", "olk", "ucw", "dBA", "oks", "uci", "dAk", "okg", "dAc", + "ovk", "uhw", "xaz", "dnA", "ots", "ugy", "dlk", "osw", "ugj", "dks", "osi", "dvk", "oxw", + "uiz", "dts", "owy", "dsw", "owj", "dxw", "oyz", "dwy", "dwj", "ofA", "uFs", "xCy", "odk", + "uEw", "xCj", "clA", "ocs", "uEi", "ckk", "ocg", "ckc", "ckE", "cvA", "ohs", "uay", "ctk", + "ogw", "uaj", "css", "ogi", "csg", "csa", "cxs", "oiy", "cww", "oij", "cwi", "cyy", "oFk", + "uCw", "xBj", "cdA", "oEs", "uCi", "cck", "oEg", "uCb", "ccc", "oEa", "ccE", "oED", "chk", + "oaw", "uDj", "cgs", "oai", "cgg", "oab", "cga", "cgD", "obj", "cib", "cFA", "oCs", "uBi", + "cEk", "oCg", "uBb", "cEc", "oCa", "cEE", "oCD", "cEC", "cas", "cag", "caa", "cCk", "uAr", + "oBa", "oBD", "cCB", "tfk", "wpw", "yez", "mnA", "tds", "woy", "mlk", "tcw", "woj", "FBA", + "mks", "FAk", "mvk", "thw", "wqz", "FnA", "mts", "tgy", "Flk", "msw", "Fks", "Fkg", "Fvk", + "mxw", "tiz", "Fts", "mwy", "Fsw", "Fsi", "Fxw", "myz", "Fwy", "Fyz", "vfA", "xps", "yuy", + "vdk", "xow", "yuj", "qlA", "vcs", "xoi", "qkk", "vcg", "xob", "qkc", "vca", "mfA", "tFs", + "wmy", "qvA", "mdk", "tEw", "wmj", "qtk", "vgw", "xqj", "hlA", "Ekk", "mcg", "tEb", "hkk", + "qsg", "hkc", "EvA", "mhs", "tay", "hvA", "Etk", "mgw", "taj", "htk", "qww", "vij", "hss", + "Esg", "hsg", "Exs", "miy", "hxs", "Eww", "mij", "hww", "qyj", "hwi", "Eyy", "hyy", "Eyj", + "hyj", "vFk", "xmw", "ytj", "qdA", "vEs", "xmi", "qck", "vEg", "xmb", "qcc", "vEa", "qcE", + "qcC", "mFk", "tCw", "wlj", "qhk", "mEs", "tCi", "gtA", "Eck", "vai", "tCb", "gsk", "Ecc", + "mEa", "gsc", "qga", "mED", "EcC", "Ehk", "maw", "tDj", "gxk", "Egs", "mai", "gws", "qii", + "mab", "gwg", "Ega", "EgD", "Eiw", "mbj", "gyw", "Eii", "gyi", "Eib", "gyb", "gzj", "qFA", + "vCs", "xli", "qEk", "vCg", "xlb", "qEc", "vCa", "qEE", "vCD", "qEC", "qEB", "EFA", "mCs", + "tBi", "ghA", "EEk", "mCg", "tBb", "ggk", "qag", "vDb", "ggc", "EEE", "mCD", "ggE", "qaD", + "ggC", "Eas", "mDi", "gis", "Eag", "mDb", "gig", "qbb", "gia", "EaD", "giD", "gji", "gjb", + "qCk", "vBg", "xkr", "qCc", "vBa", "qCE", "vBD", "qCC", "qCB", "ECk", "mBg", "tAr", "gak", + "ECc", "mBa", "gac", "qDa", "mBD", "gaE", "ECC", "gaC", "ECB", "EDg", "gbg", "gba", "gbD", + "vAq", "vAn", "qBB", "mAq", "EBE", "gDE", "gDC", "gDB", "lfA", "sps", "wey", "ldk", "sow", + "ClA", "lcs", "soi", "Ckk", "lcg", "Ckc", "CkE", "CvA", "lhs", "sqy", "Ctk", "lgw", "sqj", + "Css", "lgi", "Csg", "Csa", "Cxs", "liy", "Cww", "lij", "Cwi", "Cyy", "Cyj", "tpk", "wuw", + "yhj", "ndA", "tos", "wui", "nck", "tog", "wub", "ncc", "toa", "ncE", "toD", "lFk", "smw", + "wdj", "nhk", "lEs", "smi", "atA", "Cck", "tqi", "smb", "ask", "ngg", "lEa", "asc", "CcE", + "asE", "Chk", "law", "snj", "axk", "Cgs", "trj", "aws", "nii", "lab", "awg", "Cga", "awa", + "Ciw", "lbj", "ayw", "Cii", "ayi", "Cib", "Cjj", "azj", "vpA", "xus", "yxi", "vok", "xug", + "yxb", "voc", "xua", "voE", "xuD", "voC", "nFA", "tms", "wti", "rhA", "nEk", "xvi", "wtb", + "rgk", "vqg", "xvb", "rgc", "nEE", "tmD", "rgE", "vqD", "nEB", "CFA", "lCs", "sli", "ahA", + "CEk", "lCg", "slb", "ixA", "agk", "nag", "tnb", "iwk", "rig", "vrb", "lCD", "iwc", "agE", + "naD", "iwE", "CEB", "Cas", "lDi", "ais", "Cag", "lDb", "iys", "aig", "nbb", "iyg", "rjb", + "CaD", "aiD", "Cbi", "aji", "Cbb", "izi", "ajb", "vmk", "xtg", "ywr", "vmc", "xta", "vmE", + "xtD", "vmC", "vmB", "nCk", "tlg", "wsr", "rak", "nCc", "xtr", "rac", "vna", "tlD", "raE", + "nCC", "raC", "nCB", "raB", "CCk", "lBg", "skr", "aak", "CCc", "lBa", "iik", "aac", "nDa", + "lBD", "iic", "rba", "CCC", "iiE", "aaC", "CCB", "aaB", "CDg", "lBr", "abg", "CDa", "ijg", + "aba", "CDD", "ija", "abD", "CDr", "ijr", "vlc", "xsq", "vlE", "xsn", "vlC", "vlB", "nBc", + "tkq", "rDc", "nBE", "tkn", "rDE", "vln", "rDC", "nBB", "rDB", "CBc", "lAq", "aDc", "CBE", + "lAn", "ibc", "aDE", "nBn", "ibE", "rDn", "CBB", "ibC", "aDB", "ibB", "aDq", "ibq", "ibn", + "xsf", "vkl", "tkf", "nAm", "nAl", "CAo", "aBo", "iDo", "CAl", "aBl", "kpk", "BdA", "kos", + "Bck", "kog", "seb", "Bcc", "koa", "BcE", "koD", "Bhk", "kqw", "sfj", "Bgs", "kqi", "Bgg", + "kqb", "Bga", "BgD", "Biw", "krj", "Bii", "Bib", "Bjj", "lpA", "sus", "whi", "lok", "sug", + "loc", "sua", "loE", "suD", "loC", "BFA", "kms", "sdi", "DhA", "BEk", "svi", "sdb", "Dgk", + "lqg", "svb", "Dgc", "BEE", "kmD", "DgE", "lqD", "BEB", "Bas", "kni", "Dis", "Bag", "knb", + "Dig", "lrb", "Dia", "BaD", "Bbi", "Dji", "Bbb", "Djb", "tuk", "wxg", "yir", "tuc", "wxa", + "tuE", "wxD", "tuC", "tuB", "lmk", "stg", "nqk", "lmc", "sta", "nqc", "tva", "stD", "nqE", + "lmC", "nqC", "lmB", "nqB", "BCk", "klg", "Dak", "BCc", "str", "bik", "Dac", "lna", "klD", + "bic", "nra", "BCC", "biE", "DaC", "BCB", "DaB", "BDg", "klr", "Dbg", "BDa", "bjg", "Dba", + "BDD", "bja", "DbD", "BDr", "Dbr", "bjr", "xxc", "yyq", "xxE", "yyn", "xxC", "xxB", "ttc", + "wwq", "vvc", "xxq", "wwn", "vvE", "xxn", "vvC", "ttB", "vvB", "llc", "ssq", "nnc", "llE", + "ssn", "rrc", "nnE", "ttn", "rrE", "vvn", "llB", "rrC", "nnB", "rrB", "BBc", "kkq", "DDc", + "BBE", "kkn", "bbc", "DDE", "lln", "jjc", "bbE", "nnn", "BBB", "jjE", "rrn", "DDB", "jjC", + "BBq", "DDq", "BBn", "bbq", "DDn", "jjq", "bbn", "jjn", "xwo", "yyf", "xwm", "xwl", "tso", + "wwf", "vto", "xwv", "vtm", "tsl", "vtl", "lko", "ssf", "nlo", "lkm", "rno", "nlm", "lkl", + "rnm", "nll", "rnl", "BAo", "kkf", "DBo", "lkv", "bDo", "DBm", "BAl", "jbo", "bDm", "DBl", + "jbm", "bDl", "jbl", "DBv", "jbv", "xwd", "vsu", "vst", "nku", "rlu", "rlt", "DAu", "bBu", + "jDu", "jDt", "ApA", "Aok", "keg", "Aoc", "AoE", "AoC", "Aqs", "Aqg", "Aqa", "AqD", "Ari", + "Arb", "kuk", "kuc", "sha", "kuE", "shD", "kuC", "kuB", "Amk", "kdg", "Bqk", "kvg", "kda", + "Bqc", "kva", "BqE", "kvD", "BqC", "AmB", "BqB", "Ang", "kdr", "Brg", "kvr", "Bra", "AnD", + "BrD", "Anr", "Brr", "sxc", "sxE", "sxC", "sxB", "ktc", "lvc", "sxq", "sgn", "lvE", "sxn", + "lvC", "ktB", "lvB", "Alc", "Bnc", "AlE", "kcn", "Drc", "BnE", "AlC", "DrE", "BnC", "AlB", + "DrC", "BnB", "Alq", "Bnq", "Aln", "Drq", "Bnn", "Drn", "wyo", "wym", "wyl", "swo", "txo", + "wyv", "txm", "swl", "txl", "kso", "sgf", "lto", "swv", "nvo", "ltm", "ksl", "nvm", "ltl", + "nvl", "Ako", "kcf", "Blo", "ksv", "Dno", "Blm", "Akl", "bro", "Dnm", "Bll", "brm", "Dnl", + "Akv", "Blv", "Dnv", "brv", "yze", "yzd", "wye", "xyu", "wyd", "xyt", "swe", "twu", "swd", + "vxu", "twt", "vxt", "kse", "lsu", "ksd", "ntu", "lst", "rvu", "ypk", "zew", "xdA", "yos", + "zei", "xck", "yog", "zeb", "xcc", "yoa", "xcE", "yoD", "xcC", "xhk", "yqw", "zfj", "utA", + "xgs", "yqi", "usk", "xgg", "yqb", "usc", "xga", "usE", "xgD", "usC", "uxk", "xiw", "yrj", + "ptA", "uws", "xii", "psk", "uwg", "xib", "psc", "uwa", "psE", "uwD", "psC", "pxk", "uyw", + "xjj", "ftA", "pws", "uyi", "fsk", "pwg", "uyb", "fsc", "pwa", "fsE", "pwD", "fxk", "pyw", + "uzj", "fws", "pyi", "fwg", "pyb", "fwa", "fyw", "pzj", "fyi", "fyb", "xFA", "yms", "zdi", + "xEk", "ymg", "zdb", "xEc", "yma", "xEE", "ymD", "xEC", "xEB", "uhA", "xas", "yni", "ugk", + "xag", "ynb", "ugc", "xaa", "ugE", "xaD", "ugC", "ugB", "oxA", "uis", "xbi", "owk", "uig", + "xbb", "owc", "uia", "owE", "uiD", "owC", "owB", "dxA", "oys", "uji", "dwk", "oyg", "ujb", + "dwc", "oya", "dwE", "oyD", "dwC", "dys", "ozi", "dyg", "ozb", "dya", "dyD", "dzi", "dzb", + "xCk", "ylg", "zcr", "xCc", "yla", "xCE", "ylD", "xCC", "xCB", "uak", "xDg", "ylr", "uac", + "xDa", "uaE", "xDD", "uaC", "uaB", "oik", "ubg", "xDr", "oic", "uba", "oiE", "ubD", "oiC", + "oiB", "cyk", "ojg", "ubr", "cyc", "oja", "cyE", "ojD", "cyC", "cyB", "czg", "ojr", "cza", + "czD", "czr", "xBc", "ykq", "xBE", "ykn", "xBC", "xBB", "uDc", "xBq", "uDE", "xBn", "uDC", + "uDB", "obc", "uDq", "obE", "uDn", "obC", "obB", "cjc", "obq", "cjE", "obn", "cjC", "cjB", + "cjq", "cjn", "xAo", "ykf", "xAm", "xAl", "uBo", "xAv", "uBm", "uBl", "oDo", "uBv", "oDm", + "oDl", "cbo", "oDv", "cbm", "cbl", "xAe", "xAd", "uAu", "uAt", "oBu", "oBt", "wpA", "yes", + "zFi", "wok", "yeg", "zFb", "woc", "yea", "woE", "yeD", "woC", "woB", "thA", "wqs", "yfi", + "tgk", "wqg", "yfb", "tgc", "wqa", "tgE", "wqD", "tgC", "tgB", "mxA", "tis", "wri", "mwk", + "tig", "wrb", "mwc", "tia", "mwE", "tiD", "mwC", "mwB", "FxA", "mys", "tji", "Fwk", "myg", + "tjb", "Fwc", "mya", "FwE", "myD", "FwC", "Fys", "mzi", "Fyg", "mzb", "Fya", "FyD", "Fzi", + "Fzb", "yuk", "zhg", "hjs", "yuc", "zha", "hbw", "yuE", "zhD", "hDy", "yuC", "yuB", "wmk", + "ydg", "zEr", "xqk", "wmc", "zhr", "xqc", "yva", "ydD", "xqE", "wmC", "xqC", "wmB", "xqB", + "tak", "wng", "ydr", "vik", "tac", "wna", "vic", "xra", "wnD", "viE", "taC", "viC", "taB", + "viB", "mik", "tbg", "wnr", "qyk", "mic", "tba", "qyc", "vja", "tbD", "qyE", "miC", "qyC", + "miB", "qyB", "Eyk", "mjg", "tbr", "hyk", "Eyc", "mja", "hyc", "qza", "mjD", "hyE", "EyC", + "hyC", "EyB", "Ezg", "mjr", "hzg", "Eza", "hza", "EzD", "hzD", "Ezr", "ytc", "zgq", "grw", + "ytE", "zgn", "gny", "ytC", "glz", "ytB", "wlc", "ycq", "xnc", "wlE", "ycn", "xnE", "ytn", + "xnC", "wlB", "xnB", "tDc", "wlq", "vbc", "tDE", "wln", "vbE", "xnn", "vbC", "tDB", "vbB", + "mbc", "tDq", "qjc", "mbE", "tDn", "qjE", "vbn", "qjC", "mbB", "qjB", "Ejc", "mbq", "gzc", + "EjE", "mbn", "gzE", "qjn", "gzC", "EjB", "gzB", "Ejq", "gzq", "Ejn", "gzn", "yso", "zgf", + "gfy", "ysm", "gdz", "ysl", "wko", "ycf", "xlo", "ysv", "xlm", "wkl", "xll", "tBo", "wkv", + "vDo", "tBm", "vDm", "tBl", "vDl", "mDo", "tBv", "qbo", "vDv", "qbm", "mDl", "qbl", "Ebo", + "mDv", "gjo", "Ebm", "gjm", "Ebl", "gjl", "Ebv", "gjv", "yse", "gFz", "ysd", "wke", "xku", + "wkd", "xkt", "tAu", "vBu", "tAt", "vBt", "mBu", "qDu", "mBt", "qDt", "EDu", "gbu", "EDt", + "gbt", "ysF", "wkF", "xkh", "tAh", "vAx", "mAx", "qBx", "wek", "yFg", "zCr", "wec", "yFa", + "weE", "yFD", "weC", "weB", "sqk", "wfg", "yFr", "sqc", "wfa", "sqE", "wfD", "sqC", "sqB", + "lik", "srg", "wfr", "lic", "sra", "liE", "srD", "liC", "liB", "Cyk", "ljg", "srr", "Cyc", + "lja", "CyE", "ljD", "CyC", "CyB", "Czg", "ljr", "Cza", "CzD", "Czr", "yhc", "zaq", "arw", + "yhE", "zan", "any", "yhC", "alz", "yhB", "wdc", "yEq", "wvc", "wdE", "yEn", "wvE", "yhn", + "wvC", "wdB", "wvB", "snc", "wdq", "trc", "snE", "wdn", "trE", "wvn", "trC", "snB", "trB", + "lbc", "snq", "njc", "lbE", "snn", "njE", "trn", "njC", "lbB", "njB", "Cjc", "lbq", "azc", + "CjE", "lbn", "azE", "njn", "azC", "CjB", "azB", "Cjq", "azq", "Cjn", "azn", "zio", "irs", + "rfy", "zim", "inw", "rdz", "zil", "ily", "ikz", "ygo", "zaf", "afy", "yxo", "ziv", "ivy", + "adz", "yxm", "ygl", "itz", "yxl", "wco", "yEf", "wto", "wcm", "xvo", "yxv", "wcl", "xvm", + "wtl", "xvl", "slo", "wcv", "tno", "slm", "vro", "tnm", "sll", "vrm", "tnl", "vrl", "lDo", + "slv", "nbo", "lDm", "rjo", "nbm", "lDl", "rjm", "nbl", "rjl", "Cbo", "lDv", "ajo", "Cbm", + "izo", "ajm", "Cbl", "izm", "ajl", "izl", "Cbv", "ajv", "zie", "ifw", "rFz", "zid", "idy", + "icz", "yge", "aFz", "ywu", "ygd", "ihz", "ywt", "wce", "wsu", "wcd", "xtu", "wst", "xtt", + "sku", "tlu", "skt", "vnu", "tlt", "vnt", "lBu", "nDu", "lBt", "rbu", "nDt", "rbt", "CDu", + "abu", "CDt", "iju", "abt", "ijt", "ziF", "iFy", "iEz", "ygF", "ywh", "wcF", "wsh", "xsx", + "skh", "tkx", "vlx", "lAx", "nBx", "rDx", "CBx", "aDx", "ibx", "iCz", "wFc", "yCq", "wFE", + "yCn", "wFC", "wFB", "sfc", "wFq", "sfE", "wFn", "sfC", "sfB", "krc", "sfq", "krE", "sfn", + "krC", "krB", "Bjc", "krq", "BjE", "krn", "BjC", "BjB", "Bjq", "Bjn", "yao", "zDf", "Dfy", + "yam", "Ddz", "yal", "wEo", "yCf", "who", "wEm", "whm", "wEl", "whl", "sdo", "wEv", "svo", + "sdm", "svm", "sdl", "svl", "kno", "sdv", "lro", "knm", "lrm", "knl", "lrl", "Bbo", "knv", + "Djo", "Bbm", "Djm", "Bbl", "Djl", "Bbv", "Djv", "zbe", "bfw", "npz", "zbd", "bdy", "bcz", + "yae", "DFz", "yiu", "yad", "bhz", "yit", "wEe", "wgu", "wEd", "wxu", "wgt", "wxt", "scu", + "stu", "sct", "tvu", "stt", "tvt", "klu", "lnu", "klt", "nru", "lnt", "nrt", "BDu", "Dbu", + "BDt", "bju", "Dbt", "bjt", "jfs", "rpy", "jdw", "roz", "jcy", "jcj", "zbF", "bFy", "zjh", + "jhy", "bEz", "jgz", "yaF", "yih", "yyx", "wEF", "wgh", "wwx", "xxx", "sch", "ssx", "ttx", + "vvx", "kkx", "llx", "nnx", "rrx", "BBx", "DDx", "bbx", "jFw", "rmz", "jEy", "jEj", "bCz", + "jaz", "jCy", "jCj", "jBj", "wCo", "wCm", "wCl", "sFo", "wCv", "sFm", "sFl", "kfo", "sFv", + "kfm", "kfl", "Aro", "kfv", "Arm", "Arl", "Arv", "yDe", "Bpz", "yDd", "wCe", "wau", "wCd", + "wat", "sEu", "shu", "sEt", "sht", "kdu", "kvu", "kdt", "kvt", "Anu", "Bru", "Ant", "Brt", + "zDp", "Dpy", "Doz", "yDF", "ybh", "wCF", "wah", "wix", "sEh", "sgx", "sxx", "kcx", "ktx", + "lvx", "Alx", "Bnx", "Drx", "bpw", "nuz", "boy", "boj", "Dmz", "bqz", "jps", "ruy", "jow", + "ruj", "joi", "job", "bmy", "jqy", "bmj", "jqj", "jmw", "rtj", "jmi", "jmb", "blj", "jnj", + "jli", "jlb", "jkr", "sCu", "sCt", "kFu", "kFt", "Afu", "Aft", "wDh", "sCh", "sax", "kEx", + "khx", "Adx", "Avx", "Buz", "Duy", "Duj", "buw", "nxj", "bui", "bub", "Dtj", "bvj", "jus", + "rxi", "jug", "rxb", "jua", "juD", "bti", "jvi", "btb", "jvb", "jtg", "rwr", "jta", "jtD", + "bsr", "jtr", "jsq", "jsn", "Bxj", "Dxi", "Dxb", "bxg", "nyr", "bxa", "bxD", "Dwr", "bxr", + "bwq", "bwn", "pjk", "urw", "ejA", "pbs", "uny", "ebk", "pDw", "ulz", "eDs", "pBy", "eBw", + "zfc", "fjk", "prw", "zfE", "fbs", "pny", "zfC", "fDw", "plz", "zfB", "fBy", "yrc", "zfq", + "frw", "yrE", "zfn", "fny", "yrC", "flz", "yrB", "xjc", "yrq", "xjE", "yrn", "xjC", "xjB", + "uzc", "xjq", "uzE", "xjn", "uzC", "uzB", "pzc", "uzq", "pzE", "uzn", "pzC", "djA", "ors", + "ufy", "dbk", "onw", "udz", "dDs", "oly", "dBw", "okz", "dAy", "zdo", "drs", "ovy", "zdm", + "dnw", "otz", "zdl", "dly", "dkz", "yno", "zdv", "dvy", "ynm", "dtz", "ynl", "xbo", "ynv", + "xbm", "xbl", "ujo", "xbv", "ujm", "ujl", "ozo", "ujv", "ozm", "ozl", "crk", "ofw", "uFz", + "cns", "ody", "clw", "ocz", "cky", "ckj", "zcu", "cvw", "ohz", "zct", "cty", "csz", "ylu", + "cxz", "ylt", "xDu", "xDt", "ubu", "ubt", "oju", "ojt", "cfs", "oFy", "cdw", "oEz", "ccy", + "ccj", "zch", "chy", "cgz", "ykx", "xBx", "uDx", "cFw", "oCz", "cEy", "cEj", "caz", "cCy", + "cCj", "FjA", "mrs", "tfy", "Fbk", "mnw", "tdz", "FDs", "mly", "FBw", "mkz", "FAy", "zFo", + "Frs", "mvy", "zFm", "Fnw", "mtz", "zFl", "Fly", "Fkz", "yfo", "zFv", "Fvy", "yfm", "Ftz", + "yfl", "wro", "yfv", "wrm", "wrl", "tjo", "wrv", "tjm", "tjl", "mzo", "tjv", "mzm", "mzl", + "qrk", "vfw", "xpz", "hbA", "qns", "vdy", "hDk", "qlw", "vcz", "hBs", "qky", "hAw", "qkj", + "hAi", "Erk", "mfw", "tFz", "hrk", "Ens", "mdy", "hns", "qty", "mcz", "hlw", "Eky", "hky", + "Ekj", "hkj", "zEu", "Evw", "mhz", "zhu", "zEt", "hvw", "Ety", "zht", "hty", "Esz", "hsz", + "ydu", "Exz", "yvu", "ydt", "hxz", "yvt", "wnu", "xru", "wnt", "xrt", "tbu", "vju", "tbt", + "vjt", "mju", "mjt", "grA", "qfs", "vFy", "gnk", "qdw", "vEz", "gls", "qcy", "gkw", "qcj", + "gki", "gkb", "Efs", "mFy", "gvs", "Edw", "mEz", "gtw", "qgz", "gsy", "Ecj", "gsj", "zEh", + "Ehy", "zgx", "gxy", "Egz", "gwz", "ycx", "ytx", "wlx", "xnx", "tDx", "vbx", "mbx", "gfk", + "qFw", "vCz", "gds", "qEy", "gcw", "qEj", "gci", "gcb", "EFw", "mCz", "ghw", "EEy", "ggy", + "EEj", "ggj", "Eaz", "giz", "gFs", "qCy", "gEw", "qCj", "gEi", "gEb", "ECy", "gay", "ECj", + "gaj", "gCw", "qBj", "gCi", "gCb", "EBj", "gDj", "gBi", "gBb", "Crk", "lfw", "spz", "Cns", + "ldy", "Clw", "lcz", "Cky", "Ckj", "zCu", "Cvw", "lhz", "zCt", "Cty", "Csz", "yFu", "Cxz", + "yFt", "wfu", "wft", "sru", "srt", "lju", "ljt", "arA", "nfs", "tpy", "ank", "ndw", "toz", + "als", "ncy", "akw", "ncj", "aki", "akb", "Cfs", "lFy", "avs", "Cdw", "lEz", "atw", "ngz", + "asy", "Ccj", "asj", "zCh", "Chy", "zax", "axy", "Cgz", "awz", "yEx", "yhx", "wdx", "wvx", + "snx", "trx", "lbx", "rfk", "vpw", "xuz", "inA", "rds", "voy", "ilk", "rcw", "voj", "iks", + "rci", "ikg", "rcb", "ika", "afk", "nFw", "tmz", "ivk", "ads", "nEy", "its", "rgy", "nEj", + "isw", "aci", "isi", "acb", "isb", "CFw", "lCz", "ahw", "CEy", "ixw", "agy", "CEj", "iwy", + "agj", "iwj", "Caz", "aiz", "iyz", "ifA", "rFs", "vmy", "idk", "rEw", "vmj", "ics", "rEi", + "icg", "rEb", "ica", "icD", "aFs", "nCy", "ihs", "aEw", "nCj", "igw", "raj", "igi", "aEb", + "igb", "CCy", "aay", "CCj", "iiy", "aaj", "iij", "iFk", "rCw", "vlj", "iEs", "rCi", "iEg", + "rCb", "iEa", "iED", "aCw", "nBj", "iaw", "aCi", "iai", "aCb", "iab", "CBj", "aDj", "ibj", + "iCs", "rBi", "iCg", "rBb", "iCa", "iCD", "aBi", "iDi", "aBb", "iDb", "iBg", "rAr", "iBa", + "iBD", "aAr", "iBr", "iAq", "iAn", "Bfs", "kpy", "Bdw", "koz", "Bcy", "Bcj", "Bhy", "Bgz", + "yCx", "wFx", "sfx", "krx", "Dfk", "lpw", "suz", "Dds", "loy", "Dcw", "loj", "Dci", "Dcb", + "BFw", "kmz", "Dhw", "BEy", "Dgy", "BEj", "Dgj", "Baz", "Diz", "bfA", "nps", "tuy", "bdk", + "now", "tuj", "bcs", "noi", "bcg", "nob", "bca", "bcD", "DFs", "lmy", "bhs", "DEw", "lmj", + "bgw", "DEi", "bgi", "DEb", "bgb", "BCy", "Day", "BCj", "biy", "Daj", "bij", "rpk", "vuw", + "xxj", "jdA", "ros", "vui", "jck", "rog", "vub", "jcc", "roa", "jcE", "roD", "jcC", "bFk", + "nmw", "ttj", "jhk", "bEs", "nmi", "jgs", "rqi", "nmb", "jgg", "bEa", "jga", "bED", "jgD", + "DCw", "llj", "baw", "DCi", "jiw", "bai", "DCb", "jii", "bab", "jib", "BBj", "DDj", "bbj", + "jjj", "jFA", "rms", "vti", "jEk", "rmg", "vtb", "jEc", "rma", "jEE", "rmD", "jEC", "jEB", + "bCs", "nli", "jas", "bCg", "nlb", "jag", "rnb", "jaa", "bCD", "jaD", "DBi", "bDi", "DBb", + "jbi", "bDb", "jbb", "jCk", "rlg", "vsr", "jCc", "rla", "jCE", "rlD", "jCC", "jCB", "bBg", + "nkr", "jDg", "bBa", "jDa", "bBD", "jDD", "DAr", "bBr", "jDr", "jBc", "rkq", "jBE", "rkn", + "jBC", "jBB", "bAq", "jBq", "bAn", "jBn", "jAo", "rkf", "jAm", "jAl", "bAf", "jAv", "Apw", + "kez", "Aoy", "Aoj", "Aqz", "Bps", "kuy", "Bow", "kuj", "Boi", "Bob", "Amy", "Bqy", "Amj", + "Bqj", "Dpk", "luw", "sxj", "Dos", "lui", "Dog", "lub", "Doa", "DoD", "Bmw", "ktj", "Dqw", + "Bmi", "Dqi", "Bmb", "Dqb", "Alj", "Bnj", "Drj", "bpA", "nus", "txi", "bok", "nug", "txb", + "boc", "nua", "boE", "nuD", "boC", "boB", "Dms", "lti", "bqs", "Dmg", "ltb", "bqg", "nvb", + "bqa", "DmD", "bqD", "Bli", "Dni", "Blb", "bri", "Dnb", "brb", "ruk", "vxg", "xyr", "ruc", + "vxa", "ruE", "vxD", "ruC", "ruB", "bmk", "ntg", "twr", "jqk", "bmc", "nta", "jqc", "rva", + "ntD", "jqE", "bmC", "jqC", "bmB", "jqB", "Dlg", "lsr", "bng", "Dla", "jrg", "bna", "DlD", + "jra", "bnD", "jrD", "Bkr", "Dlr", "bnr", "jrr", "rtc", "vwq", "rtE", "vwn", "rtC", "rtB", + "blc", "nsq", "jnc", "blE", "nsn", "jnE", "rtn", "jnC", "blB", "jnB", "Dkq", "blq", "Dkn", + "jnq", "bln", "jnn", "rso", "vwf", "rsm", "rsl", "bko", "nsf", "jlo", "bkm", "jlm", "bkl", + "jll", "Dkf", "bkv", "jlv", "rse", "rsd", "bke", "jku", "bkd", "jkt", "Aey", "Aej", "Auw", + "khj", "Aui", "Aub", "Adj", "Avj", "Bus", "kxi", "Bug", "kxb", "Bua", "BuD", "Ati", "Bvi", + "Atb", "Bvb", "Duk", "lxg", "syr", "Duc", "lxa", "DuE", "lxD", "DuC", "DuB", "Btg", "kwr", + "Dvg", "lxr", "Dva", "BtD", "DvD", "Asr", "Btr", "Dvr", "nxc", "tyq", "nxE", "tyn", "nxC", + "nxB", "Dtc", "lwq", "bvc", "nxq", "lwn", "bvE", "DtC", "bvC", "DtB", "bvB", "Bsq", "Dtq", + "Bsn", "bvq", "Dtn", "bvn", "vyo", "xzf", "vym", "vyl", "nwo", "tyf", "rxo", "nwm", "rxm", + "nwl", "rxl", "Dso", "lwf", "bto", "Dsm", "jvo", "btm", "Dsl", "jvm", "btl", "jvl", "Bsf", + "Dsv", "btv", "jvv", "vye", "vyd", "nwe", "rwu", "nwd", "rwt", "Dse", "bsu", "Dsd", "jtu", + "bst", "jtt", "vyF", "nwF", "rwh", "DsF", "bsh", "jsx", "Ahi", "Ahb", "Axg", "kir", "Axa", + "AxD", "Agr", "Axr", "Bxc", "kyq", "BxE", "kyn", "BxC", "BxB", "Awq", "Bxq", "Awn", "Bxn", + "lyo", "szf", "lym", "lyl", "Bwo", "kyf", "Dxo", "lyv", "Dxm", "Bwl", "Dxl", "Awf", "Bwv", + "Dxv", "tze", "tzd", "lye", "nyu", "lyd", "nyt", "Bwe", "Dwu", "Bwd", "bxu", "Dwt", "bxt", + "tzF", "lyF", "nyh", "BwF", "Dwh", "bwx", "Aiq", "Ain", "Ayo", "kjf", "Aym", "Ayl", "Aif", + "Ayv", "kze", "kzd", "Aye", "Byu", "Ayd", "Byt", "szp" }; + +/* converts values into bar patterns - replacing Grand Zebu's true type font */ +static char *PDFttf[35] = { "00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111", + "01000", "01001", "01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001", + "10010", "10011", "10100", "10101", "10110", "10111", "11000", "11001", "11010", + "11011", "11100", "11101", "11110", "11111", "01", "1111111101010100", "11111101000101001"}; + +/* MicroPDF417 coefficients from ISO/IEC 24728:2006 Annex F */ +static int Microcoeffs[344] = { + /* k = 7 */ + 76, 925, 537, 597, 784, 691, 437, + + /* k = 8 */ + 237, 308, 436, 284, 646, 653, 428, 379, + + /* k = 9 */ + 567, 527, 622, 257, 289, 362, 501, 441, 205, + + /* k = 10 */ + 377, 457, 64, 244, 826, 841, 818, 691, 266, 612, + + /* k = 11 */ + 462, 45, 565, 708, 825, 213, 15, 68, 327, 602, 904, + + /* k = 12 */ + 597, 864, 757, 201, 646, 684, 347, 127, 388, 7, 69, 851, + + /* k = 13 */ + 764, 713, 342, 384, 606, 583, 322, 592, 678, 204, 184, 394, 692, + + /* k = 14 */ + 669, 677, 154, 187, 241, 286, 274, 354, 478, 915, 691, 833, 105, 215, + + /* k = 15 */ + 460, 829, 476, 109, 904, 664, 230, 5, 80, 74, 550, 575, 147, 868, 642, + + /* k = 16 */ + 274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65, + + /* k = 18 */ + 279, 577, 315, 624, 37, 855, 275, 739, 120, 297, 312, 202, 560, 321, 233, 756, + 760, 573, + + /* k = 21 */ + 108, 519, 781, 534, 129, 425, 681, 553, 422, 716, 763, 693, 624, 610, 310, 691, + 347, 165, 193, 259, 568, + + /* k = 26 */ + 443, 284, 887, 544, 788, 93, 477, 760, 331, 608, 269, 121, 159, 830, 446, 893, + 699, 245, 441, 454, 325, 858, 131, 847, 764, 169, + + /* k = 32 */ + 361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, + 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410, + + /* k = 38 */ + 234, 228, 438, 848, 133, 703, 529, 721, 788, 322, 280, 159, 738, 586, 388, 684, + 445, 680, 245, 595, 614, 233, 812, 32, 284, 658, 745, 229, 95, 689, 920, 771, + 554, 289, 231, 125, 117, 518, + + /* k = 44 */ + 476, 36, 659, 848, 678, 64, 764, 840, 157, 915, 470, 876, 109, 25, 632, 405, + 417, 436, 714, 60, 376, 97, 413, 706, 446, 21, 3, 773, 569, 267, 272, 213, + 31, 560, 231, 758, 103, 271, 572, 436, 339, 730, 82, 285, + + /* k = 50 */ + 923, 797, 576, 875, 156, 706, 63, 81, 257, 874, 411, 416, 778, 50, 205, 303, + 188, 535, 909, 155, 637, 230, 534, 96, 575, 102, 264, 233, 919, 593, 865, 26, + 579, 623, 766, 146, 10, 739, 246, 127, 71, 244, 211, 477, 920, 876, 427, 820, + 718, 435 }; + +/* rows, columns, error codewords, k-offset of valid MicroPDF417 sizes from ISO/IEC 24728:2006 */ +static int MicroVariants[170] = +{ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 11, 14, 17, 20, 24, 28, 8, 11, 14, 17, 20, 23, 26, 6, 8, 10, 12, 15, 20, 26, 32, 38, 44, 4, 6, 8, 10, 12, 15, 20, 26, 32, 38, 44, + 7, 7, 7, 8, 8, 8, 8, 9, 9, 10, 11, 13, 15, 12, 14, 16, 18, 21, 26, 32, 38, 44, 50, 8, 12, 14, 16, 18, 21, 26, 32, 38, 44, 50, + 0, 0, 0, 7, 7, 7, 7, 15, 15, 24, 34, 57, 84, 45, 70, 99, 115, 133, 154, 180, 212, 250, 294, 7, 45, 70, 99, 115, 133, 154, 180, 212, 250, 294 }; +/* rows, columns, error codewords, k-offset */ + +/* Automatic sizing table */ +static int MicroAutosize[56] = +{ 4, 6, 7, 8, 10, 12, 13, 14, 16, 18, 19, 20, 24, 29, 30, 33, 34, 37, 39, 46, 54, 58, 70, 72, 82, 90, 108, 126, + 1, 14, 2, 7, 3, 25, 8, 16, 5, 17, 9, 6, 10, 11, 28, 12, 19, 13, 29, 20, 30, 21, 22, 31, 23, 32, 33, 34 +}; + +/* following is Left RAP, Centre RAP, Right RAP and Start Cluster from ISO/IEC 24728:2006 tables 10, 11 and 12 */ +static int RAPTable[136] = +{ 1, 8, 36, 19, 9, 25, 1, 1, 8, 36, 19, 9, 27, 1, 7, 15, 25, 37, 1, 1, 21, 15, 1, 47, 1, 7, 15, 25, 37, 1, 1, 21, 15, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 15, 25, 37, 17, 9, 29, 31, 25, 19, 1, 7, 15, 25, 37, 17, 9, 29, 31, 25, + 9, 8, 36, 19, 17, 33, 1, 9, 8, 36, 19, 17, 35, 1, 7, 15, 25, 37, 33, 17, 37, 47, 49, 43, 1, 7, 15, 25, 37, 33, 17, 37, 47, 49, + 0, 3, 6, 0, 6, 0, 0, 0, 3, 6, 0, 6, 6, 0, 0, 6, 0, 0, 0, 0, 6, 6, 0, 3, 0, 0, 6, 0, 0, 0, 0, 6, 6, 0 }; + +/* Left and Right Row Address Pattern from Table 2 */ +static char *RAPLR[53] = {"", "221311", "311311", "312211", "222211", "213211", "214111", "223111", + "313111", "322111", "412111", "421111", "331111", "241111", "232111", "231211", "321211", + "411211", "411121", "411112", "321112", "312112", "311212", "311221", "311131", "311122", + "311113", "221113", "221122", "221131", "221221", "222121", "312121", "321121", "231121", + "231112", "222112", "213112", "212212", "212221", "212131", "212122", "212113", "211213", + "211123", "211132", "211141", "211231", "211222", "211312", "211321", "211411", "212311" }; + +/* Centre Row Address Pattern from Table 2 */ +static char *RAPC[53] = {"", "112231", "121231", "122131", "131131", "131221", "132121", "141121", + "141211", "142111", "133111", "132211", "131311", "122311", "123211", "124111", "115111", + "114211", "114121", "123121", "123112", "122212", "122221", "121321", "121411", "112411", + "113311", "113221", "113212", "113122", "122122", "131122", "131113", "122113", "113113", + "112213", "112222", "112312", "112321", "111421", "111331", "111322", "111232", "111223", + "111133", "111124", "111214", "112114", "121114", "121123", "121132", "112132", "112141" }; + diff --git a/backend/plessey.c b/backend/plessey.c new file mode 100644 index 00000000..fafbb28a --- /dev/null +++ b/backend/plessey.c @@ -0,0 +1,583 @@ +/* plessey.c - Handles Plessey and MSI Plessey */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include "common.h" + + +#define SSET "0123456789ABCDEF" +static char *PlessTable[16] = {"13131313", "31131313", "13311313", "31311313", "13133113", "31133113", + "13313113", "31313113", "13131331", "31131331", "13311331", "31311331", "13133131", + "31133131", "13313131", "31313131"}; + +static char *MSITable[10] = {"12121212", "12121221", "12122112", "12122121", "12211212", "12211221", + "12212112", "12212121", "21121212", "21121221"}; + + +int plessey(struct zint_symbol *symbol, unsigned char source[]) +{ /* Not MSI/Plessey but the older Plessey standard */ + + unsigned int i, check; + unsigned char *checkptr; + static char grid[9] = {1,1,1,1,0,1,0,0,1}; + char dest[1000]; + int errno; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 65) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(SSET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + checkptr = calloc (1, strlen(source) * 4 + 8); + + /* Start character */ + concat(dest, "31311331"); + + /* Data area */ + for(i = 0; i <= strlen(source); i++) + { + check = posn(SSET, source[i]); + lookup(SSET, PlessTable, source[i], dest); + checkptr[4*i] = check & 1; + checkptr[4*i+1] = (check >> 1) & 1; + checkptr[4*i+2] = (check >> 2) & 1; + checkptr[4*i+3] = (check >> 3) & 1; + } + + /* CRC check digit code adapted from code by Leonid A. Broukhis + used in GNU Barcode */ + + for (i=0; i < 4*strlen(source); i++) { + int j; + if (checkptr[i]) + for (j = 0; j < 9; j++) + checkptr[i+j] ^= grid[j]; + } + + for (i = 0; i < 8; i++) { + switch(checkptr[strlen(source) * 4 + i]) + { + case 0: concat(dest, "13"); break; + case 1: concat(dest, "31"); break; + } + } + + /* Stop character */ + concat(dest, "331311313"); + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + +int msi_plessey(struct zint_symbol *symbol, unsigned char source[]) +{ /* Plain MSI Plessey - does not calculate any check character */ + + unsigned int i; + int errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 55) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* start character */ + concat (dest, "21"); + + for(i = 0; i <= strlen(source); i++) + { + lookup(NESET, MSITable, source[i], dest); + } + + /* Stop character */ + concat (dest, "121"); + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + +int msi_plessey_mod10(struct zint_symbol *symbol, unsigned char source[]) +{ /* MSI Plessey with Modulo 10 check digit - algorithm from Barcode Island + http://www.barcodeisland.com/ */ + + unsigned int i, wright, dau, pedwar, pump; + char un[200], tri[200]; + int errno, h; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 55) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* start character */ + concat (dest, "21"); + + /* draw data section */ + for(i = 0; i < strlen(source); i++) + { + lookup(NESET, MSITable, source[i], dest); + } + + /* caluculate check digit */ + wright = 0; + if((strlen(source)%2) == 0) + { + for(i = 1; i < strlen(source); i+=2) + { + un[wright] = source[i]; + wright ++; + } + } + else + { + for(i = 0; i < strlen(source); i+=2) + { + un[wright] = source[i]; + wright ++; + } + } + un[wright] = '\0'; + + dau = atoi(un); + dau *= 2; + + sprintf(tri,"%d",dau); + + pedwar = 0; + for(i = 0; i < strlen(tri); i++) + { + pedwar += ctoi(tri[i]); + } + + + if((strlen(source)%2) == 0) + { + for(i = 0; i < strlen(source); i+=2) + { + pedwar += ctoi(source[i]); + } + } + else + { + for(i = 1; i < strlen(source); i+=2) + { + pedwar += ctoi(source[i]); + } + } + + pump = (10 - pedwar%10); + if(pump == 10) + { + pump = 0; + } + + /* draw check digit */ + lookup(NESET, MSITable, itoc(pump), dest); + + /* Stop character */ + concat (dest, "121"); + + h = strlen(source); + source[h] = itoc(pump); + source[h + 1] = '\0'; + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + +int msi_plessey_mod1010(struct zint_symbol *symbol, unsigned char source[]) +{ /* MSI Plessey with two Modulo 10 check digits - algorithm from + Barcode Island http://www.barcodeisland.com/ */ + + unsigned int i, wright, dau, pedwar, pump, chwech; + char un[200], tri[200]; + int errno, h; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 55) { /* No Entry Stack Smashers! */ + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if (errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* start character */ + concat (dest, "21"); + + /* draw data section */ + for(i = 0; i < strlen(source); i++) + { + lookup(NESET, MSITable, source[i], dest); + } + + /* calculate first check digit */ + wright = 0; + if((strlen(source)%2) == 0) + { + for(i = 1; i < strlen(source); i+=2) + { + un[wright] = source[i]; + wright ++; + } + } + else + { + for(i = 0; i < strlen(source); i+=2) + { + un[wright] = source[i]; + wright ++; + } + } + un[wright] = '\0'; + + dau = atoi(un); + dau *= 2; + + sprintf(tri,"%d",dau); + + pedwar = 0; + for(i = 0; i < strlen(tri); i++) + { + pedwar += ctoi(tri[i]); + } + + + if((strlen(source)%2) == 0) + { + for(i = 0; i < strlen(source); i+=2) + { + pedwar += ctoi(source[i]); + } + } + else + { + for(i = 1; i < strlen(source); i+=2) + { + pedwar += ctoi(source[i]); + } + } + + pump = (10 - pedwar%10); + if(pump == 10) + { + pump = 0; + } + + /* calculate second check digit */ + wright = 0; + if((strlen(source)%2) == 0) + { + for(i = 0; i < strlen(source); i+=2) + { + un[wright] = source[i]; + wright ++; + } + } + else + { + for(i = 1; i < strlen(source); i+=2) + { + un[wright] = source[i]; + wright ++; + } + } + un[wright] = itoc(pump); + wright++; + un[wright] = '\0'; + + dau = atoi(un); + dau *= 2; + + sprintf(tri,"%d",dau); + + pedwar = 0; + for(i = 0; i < strlen(tri); i++) + { + pedwar += ctoi(tri[i]); + } + + + if((strlen(source)%2) == 0) + { + for(i = 1; i < strlen(source); i+=2) + { + pedwar += ctoi(source[i]); + } + } + else + { + for(i = 0; i < strlen(source); i+=2) + { + pedwar += ctoi(source[i]); + } + } + + chwech = (10 - pedwar%10); + if(chwech == 10) + { + chwech = 0; + } + + /* Draw check digits */ + lookup(NESET, MSITable, itoc(pump), dest); + lookup(NESET, MSITable, itoc(chwech), dest); + + /* Stop character */ + concat (dest, "121"); + + h = strlen(source); + source[h] = itoc(pump); + source[h + 1] = itoc(chwech); + source[h + 2] = '\0'; + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + + +int msi_plessey_mod11(struct zint_symbol *symbol, unsigned char source[]) +{ + /* Calculate a Modulo 11 check digit using the system discussed on Wikipedia - + see http://en.wikipedia.org/wiki/Talk:MSI_Barcode */ + /* uses the IBM weight system */ + + int i, weight, x, check, h; + int errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 55) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* start character */ + concat (dest, "21"); + + /* draw data section */ + for(i = 0; i < strlen(source); i++) + { + lookup(NESET, MSITable, source[i], dest); + } + + /* calculate check digit */ + x = 0; + weight = 2; + for(i = (strlen(source) - 1); i >= 0; i--) { + x += weight * ctoi(source[i]); + weight++; + if(weight > 7) { + weight = 2; + } + } + + check = (11 - (x % 11)) % 11; + if(check == 10) { + lookup(NESET, MSITable, '1', dest); + lookup(NESET, MSITable, '0', dest); + } else { + lookup(NESET, MSITable, itoc(check), dest); + } + + h = strlen(source); + if(check == 10) { + source[h] = '1'; + source[h + 1] = '0'; + source[h + 2] = '\0'; + } else { + source[h] = itoc(check); + source[h + 1] = '\0'; + } + + /* stop character */ + concat (dest, "121"); + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + +int msi_plessey_mod1110(struct zint_symbol *symbol, unsigned char source[]) +{ + /* Combining the Barcode Island and Wikipedia code */ + /* Verified against http://www.bokai.com/BarcodeJSP/applet/BarcodeSampleApplet.htm */ + /* Weighted using the IBM system */ + + int i, weight, x, check, wright, dau, pedwar, pump, h; + char un[200], tri[200]; + int errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 55) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if (errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* start character */ + concat (dest, "21"); + + /* draw data section */ + for(i = 0; i < strlen(source); i++) + { + lookup(NESET, MSITable, source[i], dest); + } + + /* calculate first (mod 11) digit */ + wright = strlen(source); + x = 0; + weight = 2; + for(i = (strlen(source) - 1); i >= 0; i--) { + x += weight * ctoi(source[i]); + weight++; + if(weight > 7) { + weight = 2; + } + } + + check = (11 - (x % 11)) % 11; + if(check == 10) { + lookup(NESET, MSITable, '1', dest); + lookup(NESET, MSITable, '0', dest); + source[wright] = '1'; + source[wright + 1] = '0'; + source[wright + 2] = '\0'; + } else { + lookup(NESET, MSITable, itoc(check), dest); + source[wright] = itoc(check); + source[wright + 1] = '\0'; + } + + /* caluculate second (mod 10) check digit */ + wright = 0; + if((strlen(source)%2) == 0) + { + for(i = 1; i < strlen(source); i+=2) + { + un[wright] = source[i]; + wright ++; + } + } + else + { + for(i = 0; i < strlen(source); i+=2) + { + un[wright] = source[i]; + wright ++; + } + } + un[wright] = '\0'; + + dau = atoi(un); + dau *= 2; + + sprintf(tri,"%d",dau); + + pedwar = 0; + for(i = 0; i < strlen(tri); i++) + { + pedwar += ctoi(tri[i]); + } + + + if((strlen(source)%2) == 0) + { + for(i = 0; i < strlen(source); i+=2) + { + pedwar += ctoi(source[i]); + } + } + else + { + for(i = 1; i < strlen(source); i+=2) + { + pedwar += ctoi(source[i]); + } + } + + pump = (10 - pedwar%10); + if(pump == 10) + { + pump = 0; + } + + /* draw check digit */ + lookup(NESET, MSITable, itoc(pump), dest); + + /* stop character */ + concat (dest, "121"); + + h = strlen(source); + source[h] = itoc(pump); + source[h + 1] = '\0'; + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} diff --git a/backend/png.c b/backend/png.c new file mode 100644 index 00000000..f24d3d24 --- /dev/null +++ b/backend/png.c @@ -0,0 +1,556 @@ +/* png.c - Handles output to PNG file */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* Any resemblance to the code used by Greg Reolofs' wpng code examples is not + coincidental. Rather odd use of mainprog_info in this file is due to gradual adaption + from that code. Read his excellent book "PNG: The Definitive Guide" online at + http://www.libpng.org/pub/png/book/ */ + +#include +#include +#include +#include "png.h" /* libpng header; includes zlib.h and setjmp.h */ +#include "common.h" +#include "maxipng.h" /* Maxicode shapes */ + +#define SSET "0123456789ABCDEF" + +struct mainprog_info_type { + long width; + long height; + FILE *outfile; + jmp_buf jmpbuf; +}; + +static void writepng_error_handler(png_structp png_ptr, png_const_charp msg) +{ + struct mainprog_info_type *graphic; + + fprintf(stderr, "writepng libpng error: %s\n", msg); + fflush(stderr); + + graphic = png_get_error_ptr(png_ptr); + if (graphic == NULL) { /* we are completely hosed now */ + fprintf(stderr, + "writepng severe error: jmpbuf not recoverable; terminating.\n"); + fflush(stderr); + exit(99); + } + longjmp(graphic->jmpbuf, 1); +} + +int png_plot(struct zint_symbol *symbol) +{ + struct mainprog_info_type wpng_info; + struct mainprog_info_type *graphic; + unsigned char outdata[6000]; + png_structp png_ptr; + png_infop info_ptr; + graphic = &wpng_info; + long j; + unsigned long rowbytes; + unsigned char *image_data; + int i, k, offset, row, row_binding, errno; + int fgred, fggrn, fgblu, bgred, bggrn, bgblu; + float large_bar_height, preset_height; + int large_bar_count; + + /* sort out colour options */ + to_upper(symbol->fgcolour); + to_upper(symbol->bgcolour); + + if(strlen(symbol->fgcolour) != 6) { + strcpy(symbol->errtxt, "error: malformed foreground colour target"); + return ERROR_INVALID_OPTION; + } + if(strlen(symbol->bgcolour) != 6) { + strcpy(symbol->errtxt, "error: malformed background colour target"); + return ERROR_INVALID_OPTION; + } + errno = is_sane(SSET, symbol->fgcolour); + if (errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: malformed foreground colour target"); + return ERROR_INVALID_OPTION; + } + errno = is_sane(SSET, symbol->bgcolour); + if (errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: malformed background colour target"); + return ERROR_INVALID_OPTION; + } + + fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]); + fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]); + fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]); + bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]); + bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]); + bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]); + + /* x-dimension is equivalent to 2 pixels so multiply everything by 2 */ + + /* calculate graphic width and height */ + graphic->width = 2 * (symbol->width + (symbol->border_width * 2) + (symbol->whitespace_width * 2)); + row_binding = 0; + + if (symbol->height == 0) { + symbol->height = 50; + } + + large_bar_count = 0; + preset_height = 0.0; + for(i = 0; i < symbol->rows; i++) { + preset_height += symbol->row_height[i]; + if(symbol->row_height[i] == 0) { + large_bar_count++; + } + } + large_bar_height = (symbol->height - preset_height) / large_bar_count; + + if (large_bar_count == 0) { + symbol->height = preset_height; + } + + graphic->height = (2 * symbol->height) + (symbol->border_width * 4); + + if((symbol->rows > 1) && ((symbol->output_options == BARCODE_BIND) || (symbol->output_options == BARCODE_BOX))) { + row_binding = 1; + } + + if(symbol->symbology == BARCODE_CODE16K) { + row_binding = 1; + } + + /* Open output file in binary mode */ + if (!(graphic->outfile = fopen(symbol->outfile, "wb"))) { + strcpy(symbol->errtxt, "error: can't open output file"); + return ERROR_FILE_ACCESS; + } + + /* Set up error handling routine as proc() above */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, graphic, + writepng_error_handler, NULL); + if (!png_ptr) { + strcpy(symbol->errtxt, "error: out of memory"); + return ERROR_MEMORY; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, NULL); + strcpy(symbol->errtxt, "error: out of memory"); + return ERROR_MEMORY; + } + + /* catch jumping here */ + if (setjmp(graphic->jmpbuf)) { + png_destroy_write_struct(&png_ptr, &info_ptr); + strcpy(symbol->errtxt, "error: libpng error occurred"); + return ERROR_MEMORY; + } + + /* open output file with libpng */ + png_init_io(png_ptr, graphic->outfile); + + /* set compression */ + png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); + + /* set Header block */ + png_set_IHDR(png_ptr, info_ptr, graphic->width, graphic->height, + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + /* write all chunks up to (but not including) first IDAT */ + png_write_info(png_ptr, info_ptr); + + /* set up the transformations: for now, just pack low-bit-depth pixels + into bytes (one, two or four pixels per byte) */ + png_set_packing(png_ptr); + + /* set rowbytes - depends on picture depth */ + rowbytes = wpng_info.width * 3; + + /* Pixel Plotting */ + offset = (2 * symbol->border_width) + (2 * symbol->whitespace_width); + for (j = 0; j < graphic->height; j++) { + + + + /* top border */ + if (j < (2 * symbol->border_width)) { + if ((symbol->output_options == BARCODE_BOX) || (symbol->output_options == BARCODE_BIND)) { + for(i = 0; i < (graphic->width * 3); i+=3) { + outdata[i] = fgred; + outdata[i + 1] = fggrn; + outdata[i + 2] = fgblu; + } + } else { + for(i = 0; i < (graphic->width * 3); i+=3) { + outdata[i] = bgred; + outdata[i + 1] = bggrn; + outdata[i + 2] = bgblu; + } + } + } + + /* middle section */ + if ((j >= (2 * symbol->border_width)) && (j < (graphic->height - (2 * symbol->border_width)))) { + for(i = 0; i < (graphic->width * 3); i+= 3) { + k = (i / 3); + + /* left hand border */ + if(k < (2 * symbol->border_width)) { + if(symbol->output_options == BARCODE_BOX) { + outdata[i] = fgred; + outdata[i + 1] = fggrn; + outdata[i + 2] = fgblu; + } else { + outdata[i] = bgred; + outdata[i + 1] = bggrn; + outdata[i + 2] = bgblu; + } + } + + /* left whitespace */ + if((k >= (2 * symbol->border_width)) && (k < ((2 * symbol->border_width) + (2 * symbol->whitespace_width)))) { + outdata[i] = bgred; + outdata[i + 1] = bggrn; + outdata[i + 2] = bgblu; + } + + /* the symbol area */ + if((k >= ((2 * symbol->border_width) + (2 * symbol->whitespace_width))) && (k < (graphic->width - ((2 * symbol->border_width) + (2 * symbol->whitespace_width))))) { + float y_position, cumul; + + y_position = ((j / 2) - symbol->border_width); + y_position += 1.0; + row = 0; + + if(symbol->row_height[row] == 0) { + cumul = large_bar_height; + } else { + cumul = symbol->row_height[row]; + } + + while(cumul < y_position) { + row++; + if(symbol->row_height[row] == 0) { + cumul += large_bar_height; + } else { + cumul += symbol->row_height[row]; + } + } + + switch(symbol->encoded_data[row][(k - offset) / 2]) + { + case '1': + outdata[i] = fgred; + outdata[i + 1] = fggrn; + outdata[i + 2] = fgblu; + break; + /* NOTE: Other preset colours will go here */ + case 'R': + outdata[i] = 0xff; + outdata[i + 1] = 0x00; + outdata[i + 2] = 0x00; + break; + case 'G': + outdata[i] = 0x00; + outdata[i + 1] = 0xff; + outdata[i + 2] = 0x00; + break; + case 'B': + outdata[i] = 0x00; + outdata[i + 1] = 0x00; + outdata[i + 2] = 0xff; + break; + case 'C': + outdata[i] = 0x00; + outdata[i + 1] = 0xff; + outdata[i + 2] = 0xff; + break; + case 'M': + outdata[i] = 0xff; + outdata[i + 1] = 0x00; + outdata[i + 2] = 0xff; + break; + case 'Y': + outdata[i] = 0xff; + outdata[i + 1] = 0xff; + outdata[i + 2] = 0x00; + break; + default: + outdata[i] = bgred; + outdata[i + 1] = bggrn; + outdata[i + 2] = bgblu; + break; + + } + + /* row binding */ + if(row_binding) { + /* Only valid if all rows are the same height */ + float total_height, equal_height; + + total_height = (graphic->height / 2) - symbol->border_width; + equal_height = total_height / symbol->rows; + + if((y_position > ((equal_height * row) - 1.0)) && (y_position < ((equal_height * row) + 1.0))) { + outdata[i] = fgred; + outdata[i + 1] = fggrn; + outdata[i + 2] = fgblu; + } + + if((y_position > ((equal_height * (row + 1)) - 1.0)) && (y_position < ((equal_height * (row + 1)) + 1.0))) { + outdata[i] = fgred; + outdata[i + 1] = fggrn; + outdata[i + 2] = fgblu; + } + } + + } + + /* right whitespace */ + if((k >= (graphic->width - ((2 *symbol->border_width) + (2 * symbol->whitespace_width)))) && (k < (graphic->width - (2 * symbol->border_width)))) { + outdata[i] = bgred; + outdata[i + 1] = bggrn; + outdata[i + 2] = bgblu; + } + + /* right hand border */ + if(k >= (graphic->width - (2 * symbol->border_width))) { + if(symbol->output_options == BARCODE_BOX) { + outdata[i] = fgred; + outdata[i + 1] = fggrn; + outdata[i + 2] = fgblu; + } else { + outdata[i] = bgred; + outdata[i + 1] = bggrn; + outdata[i + 2] = bgblu; + } + } + } + } + + /* bottom border */ + if (j >= (graphic->height - (2 * symbol->border_width))) { + if ((symbol->output_options == BARCODE_BOX) || (symbol->output_options == BARCODE_BIND)) { + for(i = 0; i < (graphic->width * 3); i+=3) { + outdata[i] = fgred; + outdata[i + 1] = fggrn; + outdata[i + 2] = fgblu; + } + } else { + for(i = 0; i < (graphic->width * 3); i+=3) { + outdata[i] = bgred; + outdata[i + 1] = bggrn; + outdata[i + 2] = bgblu; + } + } + } + + /* write row contents to file */ + image_data = outdata; + png_write_row(png_ptr, image_data); + } + + /* End the file */ + png_write_end(png_ptr, NULL); + + /* make sure we have disengaged */ + if (png_ptr && info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(wpng_info.outfile); + + return 0; +} + +int maxi_png_plot(struct zint_symbol *symbol) +{ + struct mainprog_info_type wpng_info; + struct mainprog_info_type *graphic; + unsigned char outdata[6000]; + png_structp png_ptr; + png_infop info_ptr; + graphic = &wpng_info; + long j; + unsigned long rowbytes; + unsigned char *image_data; + int i, k, row, row_binding, errno; + int fgred, fggrn, fgblu, bgred, bggrn, bgblu; + int x_posn, y_posn, w_posn, h_posn; + + /* sort out colour options */ + to_upper(symbol->fgcolour); + to_upper(symbol->bgcolour); + + if(strlen(symbol->fgcolour) != 6) { + strcpy(symbol->errtxt, "error: malformed foreground colour target"); + return ERROR_INVALID_OPTION; + } + if(strlen(symbol->bgcolour) != 6) { + strcpy(symbol->errtxt, "error: malformed background colour target"); + return ERROR_INVALID_OPTION; + } + errno = is_sane(SSET, symbol->fgcolour); + if (errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: malformed foreground colour target"); + return ERROR_INVALID_OPTION; + } + errno = is_sane(SSET, symbol->bgcolour); + if (errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: malformed background colour target"); + return ERROR_INVALID_OPTION; + } + + fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]); + fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]); + fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]); + bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]); + bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]); + bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]); + + graphic->width = 300; + graphic->height = 300; + + /* Open output file in binary mode */ + if (!(graphic->outfile = fopen(symbol->outfile, "wb"))) { + strcpy(symbol->errtxt, "error: can't open output file"); + return ERROR_FILE_ACCESS; + } + + /* Set up error handling routine as proc() above */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, graphic, + writepng_error_handler, NULL); + if (!png_ptr) { + strcpy(symbol->errtxt, "error: out of memory"); + return ERROR_MEMORY; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, NULL); + strcpy(symbol->errtxt, "error: out of memory"); + return ERROR_MEMORY; + } + + /* catch jumping here */ + if (setjmp(graphic->jmpbuf)) { + png_destroy_write_struct(&png_ptr, &info_ptr); + strcpy(symbol->errtxt, "error: libpng error occurred"); + return ERROR_MEMORY; + } + + /* open output file with libpng */ + png_init_io(png_ptr, graphic->outfile); + + /* set compression */ + png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); + + /* set Header block */ + png_set_IHDR(png_ptr, info_ptr, graphic->width, graphic->height, + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + /* write all chunks up to (but not including) first IDAT */ + png_write_info(png_ptr, info_ptr); + + /* set up the transformations: for now, just pack low-bit-depth pixels + into bytes (one, two or four pixels per byte) */ + png_set_packing(png_ptr); + + /* set rowbytes - depends on picture depth */ + rowbytes = wpng_info.width * 3; + + /* Pixel Plotting */ + for (j = 0; j < graphic->height; j++) { + for(i = 0; i < (graphic->width * 3); i += 3) { + outdata[i] = bgred; + outdata[i + 1] = bggrn; + outdata[i + 2] = bgblu; + } + + if((j % 18) < 12) { + /* We are in a 'full' row of hexagons */ + for(i = 0; i < graphic->width; i++) { + x_posn = i / 10; + y_posn = j / 18; + y_posn *= 2; + + if(symbol->encoded_data[y_posn][x_posn] == '1') { + /* A hexagon needs plotting here */ + w_posn = i % 10; + h_posn = j % 18; + if(hexagon[(h_posn * 10) + w_posn] == 1) { + outdata[i * 3] = fgred; + outdata[(i * 3) + 1] = fggrn; + outdata[(i * 3) + 2] = fgblu; + } + } + } + } + + if(((j + 9) % 18) < 12) { + int ia, ja; + ja = j - 9; + /* We are in a 'reduced' row of hexagons */ + for(i = 5; i < (graphic->width - 5); i++) { + ia = i - 5; + x_posn = ia / 10; + y_posn = ja / 18; + y_posn *= 2; + y_posn++; + + if(symbol->encoded_data[y_posn][x_posn] == '1') { + /* A hexagon needs plotting here */ + w_posn = ia % 10; + h_posn = ja % 18; + if(hexagon[(h_posn * 10) + w_posn] == 1) { + outdata[i * 3] = fgred; + outdata[(i * 3) + 1] = fggrn; + outdata[(i * 3) + 2] = fgblu; + } + } + } + } + + if((j >= 103) && (j < 196)) { + /* Central bullseye */ + for(i = 0; i < 93; i++) { + if(bullseye[(((j - 103) * 93) + i) * 4] == '!') { + outdata[i * 3 + 297] = fgred; + outdata[(i * 3) + 1 + 297] = fggrn; + outdata[(i * 3) + 2 + 297] = fgblu; + } + } + } + + /* write row contents to file */ + image_data = outdata; + png_write_row(png_ptr, image_data); + } + + /* End the file */ + png_write_end(png_ptr, NULL); + + /* make sure we have disengaged */ + if (png_ptr && info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(wpng_info.outfile); + + return 0; +} diff --git a/backend/postal.c b/backend/postal.c new file mode 100644 index 00000000..b55e67f4 --- /dev/null +++ b/backend/postal.c @@ -0,0 +1,341 @@ +/* postal.c - Handles PostNet, PLANET, FIM. RM4SCC and Flattermarken */ + +/* Zint - A barcode generating program using libpng + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include "common.h" + +#define BESET "ABCD" +#define KRSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + +/* PostNet number encoding table - In this table L is long as S is short */ +static char *PNTable[10] = {"LLSSS", "SSSLL", "SSLSL", "SSLLS", "SLSSL", "SLSLS", "SLLSS", "LSSSL", + "LSSLS", "LSLSS"}; +static char *PLTable[10] = {"SSLLL", "LLLSS", "LLSLS", "LLSSL", "LSLLS", "LSLSL", "LSSLL", "SLLLS", + "SLLSL", "SLSLL"}; + +static char *FIMTable[4] = {"12121112121", "111112111211111", "121111111111121", "13111111131"}; + +static char *RoyalValues[36] = {"11", "12", "13", "14", "15", "10", "21", "22", "23", "24", "25", + "20", "31", "32", "33", "34", "35", "30", "41", "42", "43", "44", "45", "40", "51", "52", + "53", "54", "55", "50", "01", "02", "03", "04", "05", "00"}; + +static char *RoyalTable[36] = {"3300", "3210", "3201", "2310", "2301", "2211", "3120", "3030", "3021", + "2130", "2121", "2031", "3102", "3012", "3003", "2112", "2103", "2013", "1320", "1230", + "1221", "0330", "0321", "0231", "1302", "1212", "1203", "0312", "0303", "0213", "1122", + "1032", "1023", "0132", "0123", "0033"}; + +static char *FlatTable[10] = {"0504", "18", "0117", "0216", "0315", "0414", "0513", "0612", "0711", + "0810"}; + +int postnet(struct zint_symbol *symbol, unsigned char source[], char dest[]) +{ + /* Handles the PostNet system used for Zip codes in the US */ + unsigned int i, sum, check_digit; + int errno, h; + + errno = 0; + + if(strlen(source) > 90) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + sum = 0; + + /* start character */ + concat (dest, "L"); + + for (i=0; i < strlen(source); i++) + { + lookup(NESET, PNTable, source[i], dest); + sum += ctoi(source[i]); + } + + check_digit = 10 - (sum%10); + concat(dest, PNTable[check_digit]); + + /* stop character */ + concat (dest, "L"); + + h = strlen(source); + source[h] = itoc(check_digit); + source[h + 1] = '\0'; + strcpy(symbol->text, ""); + + return errno; +} + +int post_plot(struct zint_symbol *symbol, unsigned char source[]) +{ + /* Puts PostNet barcodes into the pattern matrix */ + char height_pattern[200]; + unsigned int loopey; + int writer; + strcpy(height_pattern, ""); + int errno; + + errno = 0; + + errno = postnet(symbol, source, height_pattern); + if(errno != 0) { + return errno; + } + + writer = 0; + for(loopey = 0; loopey < strlen(height_pattern); loopey++) + { + if(height_pattern[loopey] == 'L') + { + symbol->encoded_data[0][writer] = '1'; + } + symbol->encoded_data[1][writer] = '1'; + writer += 2; + } + symbol->row_height[0] = 6; + symbol->row_height[1] = 6; + symbol->rows = 2; + symbol->width = writer - 1; + + return errno; +} + +int planet(struct zint_symbol *symbol, unsigned char source[], char dest[]) +{ + /* Handles the PLANET system used for item tracking in the US */ + unsigned int i, sum, check_digit; + int errno, h; + + errno = 0; + + if(strlen(source) > 90) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + sum = 0; + + /* start character */ + concat (dest, "L"); + + for (i=0; i < strlen(source); i++) + { + lookup(NESET, PLTable, source[i], dest); + sum += ctoi(source[i]); + } + + check_digit = 10 - (sum%10); + concat(dest, PLTable[check_digit]); + + /* stop character */ + concat (dest, "L"); + + h = strlen(source); + source[h] = itoc(check_digit); + source[h + 1] = '\0'; + strcpy(symbol->text, ""); + + return errno; +} + +int planet_plot(struct zint_symbol *symbol, unsigned char source[]) +{ + /* Puts PLANET barcodes into the pattern matrix */ + char height_pattern[200]; + unsigned int loopey; + int writer; + int errno; + strcpy(height_pattern, ""); + + errno = 0; + + errno = planet(symbol, source, height_pattern); + if(errno != 0) { + return errno; + } + + writer = 0; + for(loopey = 0; loopey < strlen(height_pattern); loopey++) + { + if(height_pattern[loopey] == 'L') + { + symbol->encoded_data[0][writer] = '1'; + } + symbol->encoded_data[1][writer] = '1'; + writer += 2; + } + symbol->row_height[0] = 6; + symbol->row_height[1] = 6; + symbol->rows = 2; + symbol->width = writer - 1; + return errno; +} + +int fim(struct zint_symbol *symbol, unsigned char source[]) +{ + /* The simplest barcode symbology ever! Supported by MS Word, so here it is! */ + /* glyphs from http://en.wikipedia.org/wiki/Facing_Identification_Mark */ + + int errno; + char dest[17]; + + errno = 0; + strcpy(dest, ""); + + to_upper(source); + if(strlen(source) > 1) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(BESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + lookup(BESET, FIMTable, source[0], dest); + + expand(symbol, dest); + strcpy(symbol->text, ""); + return errno; +} + +char rm4scc(char source[], unsigned char dest[]) +{ + /* Handles the 4 State barcodes used in the UK by Royal Mail */ + unsigned int i; + int top, bottom, row, column, check_digit; + char values[3], set_copy[38]; + strcpy(set_copy, KRSET); + + top = 0; + bottom = 0; + + /* start character */ + concat (dest, "1"); + + for (i=0; i < strlen(source); i++) { + lookup(KRSET, RoyalTable, source[i], dest); + strcpy(values, RoyalValues[posn(KRSET, source[i])]); + top += ctoi(values[0]); + bottom += ctoi(values[1]); + } + + /* Calculate the check digit */ + row = (top % 6) - 1; + column = (bottom % 6) - 1; + if(row == -1) { row = 5; } + if(column == -1) { column = 5; } + check_digit = (6 * row) + column; + concat(dest, RoyalTable[check_digit]); + + /* stop character */ + concat (dest, "0"); + + return set_copy[check_digit]; +} + +int royal_plot(struct zint_symbol *symbol, unsigned char source[]) +{ + /* Puts RM4SCC into the data matrix */ + char height_pattern[200], check; + unsigned int loopey; + int writer; + int errno, h; + strcpy(height_pattern, ""); + + errno = 0; + + to_upper(source); + if(strlen(source) > 120) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(KRSET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + check = rm4scc(source, height_pattern); + + writer = 0; + for(loopey = 0; loopey < strlen(height_pattern); loopey++) + { + if((height_pattern[loopey] == '1') || (height_pattern[loopey] == '0')) + { + symbol->encoded_data[0][writer] = '1'; + } + symbol->encoded_data[1][writer] = '1'; + if((height_pattern[loopey] == '2') || (height_pattern[loopey] == '0')) + { + symbol->encoded_data[2][writer] = '1'; + } + writer += 2; + } + + symbol->row_height[0] = 4; + symbol->row_height[1] = 2; + symbol->row_height[2] = 4; + symbol->rows = 3; + symbol->width = writer - 1; + + h = strlen(source); + source[h] = check; + source[h + 1] = '\0'; + strcpy(symbol->text, ""); + + return errno; +} + +int flattermarken(struct zint_symbol *symbol, unsigned char source[]) +{ /* Flattermarken - Not really a barcode symbology and (in my opinion) probably not much use + but it's supported by TBarCode so it's supported by Zint! */ + int loop, errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + if(strlen(source) > 90) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + for(loop = 0; loop < strlen(source); loop++) { + lookup(NESET, FlatTable, source[loop], dest); + } + + expand(symbol, dest); + strcpy(symbol->text, ""); + return errno; +} diff --git a/backend/ps.c b/backend/ps.c new file mode 100644 index 00000000..cdeb6934 --- /dev/null +++ b/backend/ps.c @@ -0,0 +1,790 @@ +/* ps.c - Post Script output */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include "common.h" + +#define SSET "0123456789ABCDEF" + +/* This file has expanded quite a bit since version 1.5 in order to accomodate + the formatting rules for EAN and UPC symbols as set out in EN 797:1995 - the + down side of this support is that the code is now vertually unreadable! */ + +int ps_plot(struct zint_symbol *symbol) +{ + int i, block_width, latch, r, this_row; + float textpos, large_bar_height, preset_height, row_height, row_posn; + FILE *feps; + int fgred, fggrn, fgblu, bgred, bggrn, bgblu; + float red_ink, green_ink, blue_ink, red_paper, green_paper, blue_paper; + int errno = 0; + int textoffset, xoffset, yoffset, textdone, main_width; + char textpart[10], addon[6]; + int large_bar_count, comp_offset; + float addon_text_posn; + + textdone = 0; + main_width = symbol->width; + strcpy(addon, ""); + comp_offset = 0; + addon_text_posn = 0.0; + + feps = fopen(symbol->outfile, "w"); + if(feps == NULL) { + strcpy(symbol->errtxt, "error: could not open output file"); + return ERROR_FILE_ACCESS; + } + + /* sort out colour options */ + to_upper(symbol->fgcolour); + to_upper(symbol->bgcolour); + + if(strlen(symbol->fgcolour) != 6) { + strcpy(symbol->errtxt, "error: malformed foreground colour target"); + return ERROR_INVALID_OPTION; + } + if(strlen(symbol->bgcolour) != 6) { + strcpy(symbol->errtxt, "error: malformed background colour target"); + return ERROR_INVALID_OPTION; + } + errno = is_sane(SSET, symbol->fgcolour); + if (errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: malformed foreground colour target"); + return ERROR_INVALID_OPTION; + } + errno = is_sane(SSET, symbol->bgcolour); + if (errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: malformed background colour target"); + return ERROR_INVALID_OPTION; + } + + fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]); + fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]); + fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]); + bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]); + bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]); + bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]); + red_ink = fgred / 256.0; + green_ink = fggrn / 256.0; + blue_ink = fgblu / 256.0; + red_paper = bgred / 256.0; + green_paper = bggrn / 256.0; + blue_paper = bgblu / 256.0; + + if (symbol->height == 0) { + symbol->height = 50; + } + + large_bar_count = 0; + preset_height = 0.0; + for(i = 0; i < symbol->rows; i++) { + preset_height += symbol->row_height[i]; + if(symbol->row_height[i] == 0) { + large_bar_count++; + } + } + large_bar_height = (symbol->height - preset_height) / large_bar_count; + + if (large_bar_count == 0) { + symbol->height = preset_height; + } + + while(symbol->encoded_data[symbol->rows - 1][comp_offset] != '1') { + comp_offset++; + } + + /* Certain symbols need whitespace otherwise characters get chopped off the sides */ + if (((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC)) { + switch(strlen(symbol->text)) { + case 13: /* EAN 13 */ + case 16: + case 19: + if(symbol->whitespace_width == 0) { + symbol->whitespace_width = 10; + } + main_width = 96 + comp_offset; + break; + default: + main_width = 68 + comp_offset; + } + } + + if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) { + if(symbol->whitespace_width == 0) { + symbol->whitespace_width = 10; + main_width = 96 + comp_offset; + } + } + + if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) { + if(symbol->whitespace_width == 0) { + symbol->whitespace_width = 10; + main_width = 51 + comp_offset; + } + } + + latch = 0; + r = 0; + /* Isolate add-on text */ + for(i = 0; i < strlen(symbol->text); i++) { + if (latch == 1) { + addon[r] = symbol->text[i]; + r++; + } + if (symbol->text[i] == '+') { + latch = 1; + } + } + addon[r] = '\0'; + + if(strcmp(symbol->text, "")) { + textoffset = 9; + } else { + textoffset = 0; + } + xoffset = symbol->border_width + symbol->whitespace_width; + yoffset = symbol->border_width; + + /* Start writing the header */ + fprintf(feps, "%!PS-Adobe-3.0 EPSF-3.0\n"); + fprintf(feps, "%%%%Creator: Zint %s\n", VERSION); + if(strlen(symbol->text) != 0) { + fprintf(feps, "%%%%Title: %s\n",symbol->text); + } else { + fprintf(feps, "%%%%Title: Zint Generated Symbol\n"); + } + fprintf(feps, "%%%%Pages: 0\n"); + if(symbol->symbology != BARCODE_MAXICODE) { + fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", (symbol->width + xoffset + xoffset), (symbol->height + textoffset + yoffset + yoffset)); + } else { + fprintf(feps, "%%%%BoundingBox: 0 0 74 72\n"); + } + fprintf(feps, "%%%%EndComments\n"); + + /* Definitions */ + fprintf(feps, "/TL { setlinewidth moveto lineto stroke } bind def\n"); + fprintf(feps, "/TC { moveto 0 360 arc 360 0 arcn fill } bind def\n"); + fprintf(feps, "/TH { 0 setlinewidth moveto lineto lineto lineto lineto lineto closepath fill } bind def\n"); + fprintf(feps, "/TB { 2 copy } bind def\n"); + fprintf(feps, "/TR { newpath 4 1 roll exch moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill } bind def\n"); + fprintf(feps, "/TE { pop pop } bind def\n"); + + fprintf(feps, "newpath\n"); + + /* Now the actual representation */ + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_paper, green_paper, blue_paper); + fprintf(feps, "%d.00 0.00 TB 0.00 %d.00 TR\n", (symbol->height + textoffset + yoffset + yoffset), symbol->width + xoffset + xoffset); + + + if(symbol->symbology == BARCODE_MAXICODE) { + /* Maxicode uses hexagons */ + float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy, mx, my; + + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "35.76 35.60 10.85 35.76 35.60 8.97 44.73 35.60 TC\n"); + fprintf(feps, "35.76 35.60 7.10 35.76 35.60 5.22 40.98 35.60 TC\n"); + fprintf(feps, "35.76 35.60 3.31 35.76 35.60 1.43 37.19 35.60 TC\n"); + for(r = 0; r < symbol->rows; r++) { + for(i = 0; i < symbol->width; i++) { + if(symbol->encoded_data[r][i] == '1') { + /* Dump a hexagon */ + my = ((symbol->rows - r - 1)) * 2.135 + 1.43; + ay = my + 1.0; + by = my + 0.5; + cy = my - 0.5; + dy = my - 1.0; + ey = my - 0.5; + fy = my + 0.5; + if(r % 2 == 1) { + mx = (2.46 * i) + 1.23 + 1.23; + } else { + mx = (2.46 * i) + 1.23; + } + ax = mx; + bx = mx + 0.86; + cx = mx + 0.86; + dx = mx; + ex = mx - 0.86; + fx = mx - 0.86; + fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TH\n", ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy); + } + } + } + } + + if(symbol->symbology == BARCODE_ULTRA) { + /* Ultracode uses a colour scheme all of its own! */ + int addon_latch = 0; + + for(r = 0; r < symbol->rows; r++) { + this_row = symbol->rows - r - 1; /* invert r otherwise plots upside down */ + if(symbol->row_height[this_row] == 0) { + row_height = large_bar_height; + } else { + row_height = symbol->row_height[this_row]; + } + row_posn = 0; + for(i = 0; i < r; i++) { + if(symbol->row_height[symbol->rows - i - 1] == 0) { + row_posn += large_bar_height; + } else { + row_posn += symbol->row_height[symbol->rows - i - 1]; + } + } + row_posn += (textoffset + yoffset); + + for(i = 0; i < symbol->width; i++) { + switch(symbol->encoded_data[this_row][i]) { + case '1': + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%.2f %.2f ", row_height, row_posn); + fprintf(feps, "TB %d.00 %d.00 TR\n", i + xoffset, 1); + break; + case 'R': + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", 1.00, 0.00, 0.00); + fprintf(feps, "%.2f %.2f ", row_height, row_posn); + fprintf(feps, "TB %d.00 %d.00 TR\n", i + xoffset, 1); + break; + case 'G': + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", 0.00, 1.00, 0.00); + fprintf(feps, "%.2f %.2f ", row_height, row_posn); + fprintf(feps, "TB %d.00 %d.00 TR\n", i + xoffset, 1); + break; + case 'B': + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", 0.00, 0.00, 1.00); + fprintf(feps, "%.2f %.2f ", row_height, row_posn); + fprintf(feps, "TB %d.00 %d.00 TR\n", i + xoffset, 1); + break; + case 'C': + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", 0.00, 1.00, 1.00); + fprintf(feps, "%.2f %.2f ", row_height, row_posn); + fprintf(feps, "TB %d.00 %d.00 TR\n", i + xoffset, 1); + break; + case 'M': + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", 1.00, 0.00, 1.00); + fprintf(feps, "%.2f %.2f ", row_height, row_posn); + fprintf(feps, "TB %d.00 %d.00 TR\n", i + xoffset, 1); + break; + case 'Y': + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", 1.00, 1.00, 0.00); + fprintf(feps, "%.2f %.2f ", row_height, row_posn); + fprintf(feps, "TB %d.00 %d.00 TR\n", i + xoffset, 1); + break; + } + } + + } + } + + + if((symbol->symbology != BARCODE_MAXICODE) && (symbol->symbology != BARCODE_ULTRA)) { + /* everything else uses rectangles (or squares) */ + /* Works from the bottom of the symbol up */ + int addon_latch = 0; + + for(r = 0; r < symbol->rows; r++) { + this_row = symbol->rows - r - 1; /* invert r otherwise plots upside down */ + if(symbol->row_height[this_row] == 0) { + row_height = large_bar_height; + } else { + row_height = symbol->row_height[this_row]; + } + row_posn = 0; + for(i = 0; i < r; i++) { + if(symbol->row_height[symbol->rows - i - 1] == 0) { + row_posn += large_bar_height; + } else { + row_posn += symbol->row_height[symbol->rows - i - 1]; + } + } + row_posn += (textoffset + yoffset); + + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%.2f %.2f ", row_height, row_posn); + i = 0; + if(symbol->encoded_data[this_row][0] == '1') { + latch = 1; + } else { + latch = 0; + } + + do { + block_width = 0; + do { + block_width++; + } while (symbol->encoded_data[this_row][i + block_width] == symbol->encoded_data[this_row][i]); + if((addon_latch == 0) && (r == 0) && (i > main_width)) { + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%.2f %.2f ", (row_height - 5.0), (row_posn - 5.0)); + addon_text_posn = row_posn + row_height - 8.0; + addon_latch = 1; + } + if(latch == 1) { + /* a bar */ + fprintf(feps, "TB %d.00 %d.00 TR\n", i + xoffset, block_width); + latch = 0; + } else { + /* a space */ + latch = 1; + } + i += block_width; + + } while (i < symbol->width); + } + } + /* That's done the actual data area, everything else is human-friendly */ + + xoffset += comp_offset; + + if (((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC)) { + /* guard bar extensions and text formatting for EAN8 and EAN13 */ + switch(strlen(symbol->text)) { + case 8: /* EAN-8 */ + case 11: + case 14: + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%.2f %.2f ", 5.0, 4.0 + yoffset); + fprintf(feps, "TB %d.00 %d.00 TR\n", 0 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 2 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 32 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 34 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 64 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 66 + xoffset, 1); + for(i = 0; i < 4; i++) { + textpart[i] = symbol->text[i]; + } + textpart[4] = '\0'; + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = 17; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + for(i = 0; i < 4; i++) { + textpart[i] = symbol->text[i + 4]; + } + textpart[4] = '\0'; + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = 50; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + textdone = 1; + switch(strlen(addon)) { + case 2: + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = symbol->width + xoffset - 10; + fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos, addon_text_posn); + fprintf(feps, " (%s) stringwidth\n", addon); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", addon); + fprintf(feps, "setmatrix\n"); + break; + case 5: + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = symbol->width + xoffset - 23; + fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos, addon_text_posn); + fprintf(feps, " (%s) stringwidth\n", addon); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", addon); + fprintf(feps, "setmatrix\n"); + break; + } + + break; + case 13: /* EAN 13 */ + case 16: + case 19: + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%.2f %.2f ", 5.0, 4.0 + yoffset); + fprintf(feps, "TB %d.00 %d.00 TR\n", 0 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 2 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 46 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 48 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 92 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 94 + xoffset, 1); + textpart[0] = symbol->text[0]; + textpart[1] = '\0'; + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = -7; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + for(i = 0; i < 6; i++) { + textpart[i] = symbol->text[i + 1]; + } + textpart[6] = '\0'; + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = 24; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + for(i = 0; i < 6; i++) { + textpart[i] = symbol->text[i + 7]; + } + textpart[6] = '\0'; + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = 71; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + textdone = 1; + switch(strlen(addon)) { + case 2: + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = symbol->width + xoffset - 10; + fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos, addon_text_posn); + fprintf(feps, " (%s) stringwidth\n", addon); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", addon); + fprintf(feps, "setmatrix\n"); + break; + case 5: + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = symbol->width + xoffset - 23; + fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos, addon_text_posn); + fprintf(feps, " (%s) stringwidth\n", addon); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", addon); + fprintf(feps, "setmatrix\n"); + break; + } + break; + + } + } + + if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) { + /* guard bar extensions and text formatting for UPCA */ + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%.2f %.2f ", 5.0, 4.0 + yoffset); + latch = 1; + + i = 0 + comp_offset; + do { + block_width = 0; + do { + block_width++; + } while (symbol->encoded_data[symbol->rows - 1][i + block_width] == symbol->encoded_data[symbol->rows - 1][i]); + if(latch == 1) { + /* a bar */ + fprintf(feps, "TB %d.00 %d.00 TR\n", i + xoffset - comp_offset, block_width); + latch = 0; + } else { + /* a space */ + latch = 1; + } + i += block_width; + } while (i < 11 + comp_offset); + fprintf(feps, "TB %d.00 %d.00 TR\n", 46 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 48 + xoffset, 1); + latch = 1; + i = 85 + comp_offset; + do { + block_width = 0; + do { + block_width++; + } while (symbol->encoded_data[symbol->rows - 1][i + block_width] == symbol->encoded_data[symbol->rows - 1][i]); + if(latch == 1) { + /* a bar */ + fprintf(feps, "TB %d.00 %d.00 TR\n", i + xoffset - comp_offset, block_width); + latch = 0; + } else { + /* a space */ + latch = 1; + } + i += block_width; + } while (i < 96 + comp_offset); + textpart[0] = symbol->text[0]; + textpart[1] = '\0'; + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "8.00 scalefont setfont\n"); + textpos = -5; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + for(i = 0; i < 5; i++) { + textpart[i] = symbol->text[i + 1]; + } + textpart[5] = '\0'; + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = 27; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + for(i = 0; i < 5; i++) { + textpart[i] = symbol->text[i + 6]; + } + textpart[6] = '\0'; + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = 68; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + textpart[0] = symbol->text[11]; + textpart[1] = '\0'; + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "8.00 scalefont setfont\n"); + textpos = 100; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + textdone = 1; + switch(strlen(addon)) { + case 2: + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = symbol->width + xoffset - 10; + fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos, addon_text_posn); + fprintf(feps, " (%s) stringwidth\n", addon); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", addon); + fprintf(feps, "setmatrix\n"); + break; + case 5: + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = symbol->width + xoffset - 23; + fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos, addon_text_posn); + fprintf(feps, " (%s) stringwidth\n", addon); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", addon); + fprintf(feps, "setmatrix\n"); + break; + } + + } + + if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) { + /* guard bar extensions and text formatting for UPCE */ + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%.2f %.2f ", 5.0, 4.0 + yoffset); + fprintf(feps, "TB %d.00 %d.00 TR\n", 0 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 2 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 46 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 48 + xoffset, 1); + fprintf(feps, "TB %d.00 %d.00 TR\n", 50 + xoffset, 1); + textpart[0] = symbol->text[0]; + textpart[1] = '\0'; + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "8.00 scalefont setfont\n"); + textpos = -5; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + for(i = 0; i < 6; i++) { + textpart[i] = symbol->text[i + 1]; + } + textpart[6] = '\0'; + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = 24; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + textpart[0] = symbol->text[7]; + textpart[1] = '\0'; + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "8.00 scalefont setfont\n"); + textpos = 55; + fprintf(feps, " 0 0 moveto %.2f 0.50 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", textpart); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", textpart); + fprintf(feps, "setmatrix\n"); + textdone = 1; + switch(strlen(addon)) { + case 2: + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = symbol->width + xoffset - 10; + fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos, addon_text_posn); + fprintf(feps, " (%s) stringwidth\n", addon); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", addon); + fprintf(feps, "setmatrix\n"); + break; + case 5: + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "11.00 scalefont setfont\n"); + textpos = symbol->width + xoffset - 23; + fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos, addon_text_posn); + fprintf(feps, " (%s) stringwidth\n", addon); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", addon); + fprintf(feps, "setmatrix\n"); + break; + } + + } + + xoffset -= comp_offset; + + + /* Put boundary bars or box around symbol */ + if ((symbol->output_options == BARCODE_BOX) || (symbol->output_options == BARCODE_BIND)) { + /* boundary bars */ + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%d.00 %d.00 TB %d.00 %d.00 TR\n", symbol->border_width, textoffset, 0, (symbol->width + xoffset + xoffset)); + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%d.00 %d.00 TB %d.00 %d.00 TR\n", symbol->border_width, textoffset + symbol->height + symbol->border_width, 0, (symbol->width + xoffset + xoffset)); + if(symbol->rows > 1) { + /* row binding */ + for(r = 1; r < symbol->rows; r++) { + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%d.00 %.2f TB %d.00 %d.00 TR\n", 2, ((r * row_height) + textoffset + yoffset - 1), xoffset, symbol->width); + } + } + } + + if (symbol->output_options == BARCODE_BOX) { + /* side bars */ + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%d.00 %d.00 TB %d.00 %d.00 TR\n", symbol->height + (2 * symbol->border_width), textoffset, 0, symbol->border_width); + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "%d.00 %d.00 TB %d.00 %d.00 TR\n", symbol->height + (2 * symbol->border_width), textoffset, (symbol->width + xoffset + xoffset - symbol->border_width), symbol->border_width); + } + + /* Put the human readable text at the bottom */ + if((textdone == 0) && (strlen(symbol->text) != 0)) { + fprintf(feps, "TE\n"); + fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink); + fprintf(feps, "matrix currentmatrix\n"); + fprintf(feps, "/Helvetica findfont\n"); + fprintf(feps, "8.00 scalefont setfont\n"); + textpos = symbol->width / 2.0; + fprintf(feps, " 0 0 moveto %.2f 1.67 translate 0.00 rotate 0 0 moveto\n", textpos + xoffset); + fprintf(feps, " (%s) stringwidth\n", symbol->text); + fprintf(feps, "pop\n"); + fprintf(feps, "-2 div 0 rmoveto\n"); + fprintf(feps, " (%s) show\n", symbol->text); + fprintf(feps, "setmatrix\n"); + } + fprintf(feps, "\nshowpage\n"); + + fclose(feps); + + return errno; +} + diff --git a/backend/qr.c b/backend/qr.c new file mode 100644 index 00000000..e1a432dd --- /dev/null +++ b/backend/qr.c @@ -0,0 +1,94 @@ +/* qr.c Handles QR Code by utilising libqrencode */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 Robin Stuart + Copyright (C) 2006 Kentaro Fukuchi + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include /* The assumption is that this is already installed */ +#include "common.h" + +static int kanji = 0; +static QRecLevel level = QR_ECLEVEL_L; + +QRcode *encode(int security, int size, const unsigned char *intext) +{ + int version; + QRecLevel level; + QRencodeMode hint; + QRcode *code; + + if(kanji) { + hint = QR_MODE_KANJI; + } else { + hint = QR_MODE_8; + } + + if((security >= 1) && (security <= 4)) { + switch (security) { + case 1: level = QR_ECLEVEL_L; break; + case 2: level = QR_ECLEVEL_M; break; + case 3: level = QR_ECLEVEL_Q; break; + case 4: level = QR_ECLEVEL_H; break; + } + } else { + level = QR_ECLEVEL_L; + } + + if((size >= 1) && (size <= 40)) { + version = size; + } else { + version = 0; + } + + code = QRcode_encodeString(intext, version, level, hint, 1); + + return code; +} + +int qr_code(struct zint_symbol *symbol, unsigned char source[]) +{ + QRcode *code; + int errno = 0; + int i, j; + + code = encode(symbol->option_1, symbol->option_2, source); + if(code == NULL) { + strcpy(symbol->errtxt, "error: libqrencode failed to encode the input data"); + return ERROR_ENCODING_PROBLEM; + } + + symbol->width = code->width; + symbol->rows = code->width; + + for(i = 0; i < code->width; i++) { + for(j = 0; j < code->width; j++) { + if((*(code->data + (i * code->width) + j) & 0x01) == 0) { + symbol->encoded_data[i][j] = '0'; + } else { + symbol->encoded_data[i][j] = '1'; + } + } + symbol->row_height[i] = 1; + } + + QRcode_free(code); + + return errno; +} diff --git a/backend/reedsol.c b/backend/reedsol.c new file mode 100644 index 00000000..a0a84dc5 --- /dev/null +++ b/backend/reedsol.c @@ -0,0 +1,170 @@ +/** + * + * This is a simple Reed-Solomon encoder + * (C) Cliff Hones 2004 + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +// It is not written with high efficiency in mind, so is probably +// not suitable for real-time encoding. The aim was to keep it +// simple, general and clear. +// +// + +// Usage: +// First call rs_init_gf(poly) to set up the Galois Field parameters. +// Then call rs_init_code(size, index) to set the encoding size +// Then call rs_encode(datasize, data, out) to encode the data. +// +// These can be called repeatedly as required - but note that +// rs_init_code must be called following any rs_init_gf call. +// +// If the parameters are fixed, some of the statics below can be +// replaced with constants in the obvious way, and additionally +// malloc/free can be avoided by using static arrays of a suitable +// size. + +#include // only needed for debug (main) +#include // only needed for malloc/free + +static int gfpoly; +static int symsize; // in bits +static int logmod; // 2**symsize - 1 +static int rlen; + +static int *log = NULL, *alog = NULL, *rspoly = NULL; + +// rs_init_gf(poly) initialises the parameters for the Galois Field. +// The symbol size is determined from the highest bit set in poly +// This implementation will support sizes up to 30 bits (though that +// will result in very large log/antilog tables) - bit sizes of +// 8 or 4 are typical +// +// The poly is the bit pattern representing the GF characteristic +// polynomial. e.g. for ECC200 (8-bit symbols) the polynomial is +// a**8 + a**5 + a**3 + a**2 + 1, which translates to 0x12d. + +void rs_init_gf(int poly) +{ + int m, b, p, v; + + // Return storage from previous setup + if (log) { + free(log); + free(alog); + free(rspoly); + rspoly = NULL; + } + // Find the top bit, and hence the symbol size + for (b = 1, m = 0; b <= poly; b <<= 1) + m++; + b >>= 1; + m--; + gfpoly = poly; + symsize = m; + + // Calculate the log/alog tables + logmod = (1 << m) - 1; + log = (int *)malloc(sizeof(int) * (logmod + 1)); + alog = (int *)malloc(sizeof(int) * logmod); + + for (p = 1, v = 0; v < logmod; v++) { + alog[v] = p; + log[p] = v; + p <<= 1; + if (p & b) + p ^= poly; + } +} + +// rs_init_code(nsym, index) initialises the Reed-Solomon encoder +// nsym is the number of symbols to be generated (to be appended +// to the input data). index is usually 1 - it is the index of +// the constant in the first term (i) of the RS generator polynomial: +// (x + 2**i)*(x + 2**(i+1))*... [nsym terms] +// For ECC200, index is 1. + +void rs_init_code(int nsym, int index) +{ + int i, k; + + if (rspoly) + free(rspoly); + rspoly = (int *)malloc(sizeof(int) * (nsym + 1)); + + rlen = nsym; + + rspoly[0] = 1; + for (i = 1; i <= nsym; i++) { + rspoly[i] = 1; + for (k = i - 1; k > 0; k--) { + if (rspoly[k]) + rspoly[k] = + alog[(log[rspoly[k]] + index) % logmod]; + rspoly[k] ^= rspoly[k - 1]; + } + rspoly[0] = alog[(log[rspoly[0]] + index) % logmod]; + index++; + } +} + +void rs_encode(int len, unsigned char *data, unsigned char *res) +{ + int i, k, m; + for (i = 0; i < rlen; i++) + res[i] = 0; + for (i = 0; i < len; i++) { + m = res[rlen - 1] ^ data[i]; + for (k = rlen - 1; k > 0; k--) { + if (m && rspoly[k]) + res[k] = + res[k - + 1] ^ alog[(log[m] + + log[rspoly[k]]) % logmod]; + else + res[k] = res[k - 1]; + } + if (m && rspoly[0]) + res[0] = alog[(log[m] + log[rspoly[0]]) % logmod]; + else + res[0] = 0; + } +} + +void rs_encode_long(int len, unsigned int *data, unsigned int *res) +{ /* The same as above but for larger bitlengths - Aztec code compatible */ + int i, k, m; + for (i = 0; i < rlen; i++) + res[i] = 0; + for (i = 0; i < len; i++) { + m = res[rlen - 1] ^ data[i]; + for (k = rlen - 1; k > 0; k--) { + if (m && rspoly[k]) + res[k] = + res[k - + 1] ^ alog[(log[m] + + log[rspoly[k]]) % logmod]; + else + res[k] = res[k - 1]; + } + if (m && rspoly[0]) + res[0] = alog[(log[m] + log[rspoly[0]]) % logmod]; + else + res[0] = 0; + } +} + diff --git a/backend/reedsol.h b/backend/reedsol.h new file mode 100644 index 00000000..9d7df4b0 --- /dev/null +++ b/backend/reedsol.h @@ -0,0 +1,30 @@ +/** + * + * This is a simple Reed-Solomon encoder + * (C) Cliff Hones 2004 + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __REEDSOL_H +#define __REEDSOL_H + +void rs_init_gf(int poly); +void rs_init_code(int nsym, int index); +void rs_encode(int len, unsigned char *data, unsigned char *res); +void rs_encode_long(int len, unsigned int *data, unsigned int *res); + +#endif /* __REEDSOL_H */ diff --git a/backend/rss.c b/backend/rss.c new file mode 100644 index 00000000..e391e2cb --- /dev/null +++ b/backend/rss.c @@ -0,0 +1,2293 @@ +/* rss.c - Handles Reduced Space Symbology (GS1 DataBar) */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* The functions "combins" and "getRSSwidths" 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 30 November 2006 +*/ + +#include +#include +#include +#include "common.h" +#include "large.h" +#include "rss.h" + +/********************************************************************** +* combins(n,r): returns the number of Combinations of r selected from n: +* Combinations = n! / ((n - r)! * r!) +**********************************************************************/ +int combins(int n, int r) { + int i, j; + int maxDenom, minDenom; + int val; + + if (n-r > r) { + minDenom = r; + maxDenom = n-r; + } + else { + minDenom = n-r; + maxDenom = r; + } + val = 1; + j = 1; + for (i = n; i > maxDenom; i--) { + val *= i; + if (j <= minDenom) { + val /= j; + j++; + } + } + for (; j <= minDenom; j++) { + val /= j; + } + return(val); +} + +/********************************************************************** +* getRSSwidths +* routine to generate widths for RSS elements for a given value.# +* +* Calling arguments: +* val = required value +* n = number of modules +* elements = elements in a set (RSS-14 & Expanded = 4; RSS Limited = 7) +* maxWidth = maximum module width of an element +* noNarrow = 0 will skip patterns without a one module wide element +* +* Return: +* static int widths[] = element widths +**********************************************************************/ +void getRSSwidths(int val, int n, int elements, int maxWidth, int noNarrow) +{ + int bar; + int elmWidth; + int i; + int mxwElement; + int subVal, lessVal; + int narrowMask = 0; + for (bar = 0; bar < elements-1; bar++) + { + for(elmWidth = 1, narrowMask |= (1<= elements-bar-1)) + { + subVal -= combins(n-elmWidth-(elements-bar), elements-bar-2); + } + /* less combinations with elements > maxVal */ + if (elements-bar-1 > 1) + { + lessVal = 0; + for (mxwElement = n-elmWidth-(elements-bar-2); + mxwElement > maxWidth; + mxwElement--) + { + lessVal += combins(n-elmWidth-mxwElement-1, elements-bar-3); + } + subVal -= lessVal * (elements-1-bar); + } + else if (n-elmWidth > maxWidth) + { + subVal--; + } + val -= subVal; + if (val < 0) break; + } + val += subVal; + n -= elmWidth; + widths[bar] = elmWidth; + } + widths[bar] = n; + return; +} + +int rss14(struct zint_symbol *symbol, unsigned char source[]) +{ /* GS1 DataBar-14 */ + int errno = 0, i, j, read, mask; + short int accum[112], left_reg[112], right_reg[112], x_reg[112], y_reg[112]; + int data_character[4], data_group[4], v_odd[4], v_even[4]; + int data_widths[8][4], checksum, c_left, c_right, total_widths[46], writer; + char latch, hrt[15]; + int check_digit, count, separator_row; + + separator_row = 0; + + if(strlen(source) > 13) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* make some room for a separator row for composite symbols */ + switch(symbol->symbology) { + case BARCODE_RSS14_CC: + case BARCODE_RSS14STACK_CC: + case BARCODE_RSS14_OMNI_CC: + separator_row = symbol->rows; + symbol->row_height[separator_row] = 1; + symbol->rows += 1; + break; + } + + for(i = 0; i < 112; i++) { + accum[i] = 0; + x_reg[i] = 0; + y_reg[i] = 0; + } + + for(i = 0; i < 4; i++) { + data_character[i] = 0; + data_group[i] = 0; + } + + binary_load(accum, source); + + if(symbol->option_1 == 2) { + /* Add symbol linkage flag */ + binary_load(y_reg, "10000000000000"); + binary_add(accum, y_reg); + for(i = 0; i < 112; i++) { + y_reg[i] = 0; + } + } + + /* Calculate left and right pair values */ + binary_load(x_reg, "4537077"); + + for(i = 0; i < 24; i++) { + shiftup(x_reg); + } + + for(i = 24; i >= 0; i--) { + y_reg[i] = islarger(accum, x_reg); + if(y_reg[i] == 1) { + binary_subtract(accum, x_reg); + } + shiftdown(x_reg); + } + + for(i = 0; i < 112; i++) { + left_reg[i] = y_reg[i]; + right_reg[i] = accum[i]; + } + + /* Calculate four data characters */ + binary_load(x_reg, "1597"); + for(i = 0; i < 112; i++) { + accum[i] = left_reg[i]; + } + + for(i = 0; i < 24; i++) { + shiftup(x_reg); + } + + for(i = 24; i >= 0; i--) { + y_reg[i] = islarger(accum, x_reg); + if(y_reg[i] == 1) { + binary_subtract(accum, x_reg); + } + shiftdown(x_reg); + } + + data_character[0] = 0; + data_character[1] = 0; + mask = 0x2000; + for(i = 13; i >= 0; i--) { + if(y_reg[i] == 1) { + data_character[0] += mask; + } + if(accum[i] == 1) { + data_character[1] += mask; + } + mask = mask >> 1; + } + + binary_load(x_reg, "1597"); + for(i = 0; i < 112; i++) { + accum[i] = right_reg[i]; + } + + for(i = 0; i < 24; i++) { + shiftup(x_reg); + } + + for(i = 24; i >= 0; i--) { + y_reg[i] = islarger(accum, x_reg); + if(y_reg[i] == 1) { + binary_subtract(accum, x_reg); + } + shiftdown(x_reg); + } + + data_character[2] = 0; + data_character[3] = 0; + mask = 0x2000; + for(i = 13; i >= 0; i--) { + if(y_reg[i] == 1) { + data_character[2] += mask; + } + if(accum[i] == 1) { + data_character[3] += mask; + } + mask = mask >> 1; + } + + /* Calculate odd and even subset values */ + + if((data_character[0] >= 0) && (data_character[0] <= 160)) { data_group[0] = 0; } + if((data_character[0] >= 161) && (data_character[0] <= 960)) { data_group[0] = 1; } + if((data_character[0] >= 961) && (data_character[0] <= 2014)) { data_group[0] = 2; } + if((data_character[0] >= 2015) && (data_character[0] <= 2714)) { data_group[0] = 3; } + if((data_character[0] >= 2715) && (data_character[0] <= 2840)) { data_group[0] = 4; } + if((data_character[1] >= 0) && (data_character[1] <= 335)) { data_group[1] = 5; } + if((data_character[1] >= 336) && (data_character[1] <= 1035)) { data_group[1] = 6; } + if((data_character[1] >= 1036) && (data_character[1] <= 1515)) { data_group[1] = 7; } + if((data_character[1] >= 1516) && (data_character[1] <= 1596)) { data_group[1] = 8; } + if((data_character[3] >= 0) && (data_character[3] <= 335)) { data_group[3] = 5; } + if((data_character[3] >= 336) && (data_character[3] <= 1035)) { data_group[3] = 6; } + if((data_character[3] >= 1036) && (data_character[3] <= 1515)) { data_group[3] = 7; } + if((data_character[3] >= 1516) && (data_character[3] <= 1596)) { data_group[3] = 8; } + if((data_character[2] >= 0) && (data_character[2] <= 160)) { data_group[2] = 0; } + if((data_character[2] >= 161) && (data_character[2] <= 960)) { data_group[2] = 1; } + if((data_character[2] >= 961) && (data_character[2] <= 2014)) { data_group[2] = 2; } + if((data_character[2] >= 2015) && (data_character[2] <= 2714)) { data_group[2] = 3; } + if((data_character[2] >= 2715) && (data_character[2] <= 2840)) { data_group[2] = 4; } + + v_odd[0] = (data_character[0] - g_sum_table[data_group[0]]) / t_table[data_group[0]]; + v_even[0] = (data_character[0] - g_sum_table[data_group[0]]) % t_table[data_group[0]]; + v_odd[1] = (data_character[1] - g_sum_table[data_group[1]]) % t_table[data_group[1]]; + v_even[1] = (data_character[1] - g_sum_table[data_group[1]]) / t_table[data_group[1]]; + v_odd[3] = (data_character[3] - g_sum_table[data_group[3]]) % t_table[data_group[3]]; + v_even[3] = (data_character[3] - g_sum_table[data_group[3]]) / t_table[data_group[3]]; + v_odd[2] = (data_character[2] - g_sum_table[data_group[2]]) / t_table[data_group[2]]; + v_even[2] = (data_character[2] - g_sum_table[data_group[2]]) % t_table[data_group[2]]; + + + /* Use RSS subset width algorithm */ + for(i = 0; i < 4; i++) { + if((i == 0)||(i == 2)) { + getRSSwidths(v_odd[i], modules_odd[data_group[i]], 4, widest_odd[data_group[i]], 1); + data_widths[0][i] = widths[0]; + data_widths[2][i] = widths[1]; + data_widths[4][i] = widths[2]; + data_widths[6][i] = widths[3]; + getRSSwidths(v_even[i], modules_even[data_group[i]], 4, widest_even[data_group[i]], 0); + data_widths[1][i] = widths[0]; + data_widths[3][i] = widths[1]; + data_widths[5][i] = widths[2]; + data_widths[7][i] = widths[3]; + } else { + getRSSwidths(v_odd[i], modules_odd[data_group[i]], 4, widest_odd[data_group[i]], 0); + data_widths[0][i] = widths[0]; + data_widths[2][i] = widths[1]; + data_widths[4][i] = widths[2]; + data_widths[6][i] = widths[3]; + getRSSwidths(v_even[i], modules_even[data_group[i]], 4, widest_even[data_group[i]], 1); + data_widths[1][i] = widths[0]; + data_widths[3][i] = widths[1]; + data_widths[5][i] = widths[2]; + data_widths[7][i] = widths[3]; + } + } + + + checksum = 0; + /* Calculate the checksum */ + for(i = 0; i < 8; i++) { + checksum += checksum_weight[i] * data_widths[i][0]; + checksum += checksum_weight[i+8] * data_widths[i][1]; + checksum += checksum_weight[i+16] * data_widths[i][2]; + checksum += checksum_weight[i+24] * data_widths[i][3]; + } + checksum %= 79; + + /* Calculate the two check characters */ + if(checksum >= 8) { checksum++; } + if(checksum >= 72) { checksum++; } + c_left = checksum / 9; + c_right = checksum % 9; + + /* Put element widths together */ + total_widths[0] = 1; + total_widths[1] = 1; + total_widths[44] = 1; + total_widths[45] = 1; + for(i = 0; i < 8; i++) { + total_widths[i + 2] = data_widths[i][0]; + total_widths[i + 15] = data_widths[7 - i][1]; + total_widths[i + 23] = data_widths[i][3]; + total_widths[i + 36] = data_widths[7 - i][2]; + } + for(i = 0; i < 5; i++) { + total_widths[i + 10] = finder_pattern[i + (5 * c_left)]; + total_widths[i + 31] = finder_pattern[(4 - i) + (5 * c_right)]; + } + + /* Put this data into the symbol */ + if((symbol->symbology == BARCODE_RSS14) || (symbol->symbology == BARCODE_RSS14_CC)) { + writer = 0; + latch = '0'; + for(i = 0; i < 46; i++) { + for(j = 0; j < total_widths[i]; j++) { + symbol->encoded_data[symbol->rows][writer] = latch; + writer++; + } + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } + if(symbol->width < writer) { symbol->width = writer; } + if(symbol->symbology == BARCODE_RSS14_CC) { + /* separator pattern for composite symbol */ + for(i = 4; i < 92; i++) { + if(symbol->encoded_data[separator_row + 1][i] != '1') { + symbol->encoded_data[separator_row][i] = '1'; + } + } + latch = '1'; + for(i = 16; i < 32; i++) { + if(symbol->encoded_data[separator_row + 1][i] != '1') { + symbol->encoded_data[separator_row][i] = latch; + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } else { + symbol->encoded_data[separator_row][i] = '0'; + latch = '1'; + } + } + latch = '1'; + for(i = 63; i < 78; i++) { + if(symbol->encoded_data[separator_row + 1][i] != '1') { + symbol->encoded_data[separator_row][i] = latch; + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } else { + symbol->encoded_data[separator_row][i] = '0'; + latch = '1'; + } + } + } + symbol->rows = symbol->rows + 1; + + count = 0; + check_digit = 0; + + /* Calculate check digit from Annex A and place human readable text */ + strcpy(symbol->text, "(01)"); + for(i = 0; i < 14; i++) { + hrt[i] = '0'; + } + for(i = 0; i < strlen(source); i++) { + hrt[12 - i] = source[strlen(source) - i - 1]; + } + hrt[14] = '\0'; + + for (i = 0; i < 13; i++) + { + count += ctoi(hrt[i]); + + if ((i%2) == 0) + { + count += 2 * (ctoi(hrt[i])); + } + } + + check_digit = 10 - (count%10); + if (check_digit == 10) { check_digit = 0; } + hrt[13] = itoc(check_digit); + + concat(symbol->text, hrt); + } + + if((symbol->symbology == BARCODE_RSS14STACK) || (symbol->symbology == BARCODE_RSS14STACK_CC)) { + /* top row */ + writer = 0; + latch = '0'; + for(i = 0; i < 23; i++) { + for(j = 0; j < total_widths[i]; j++) { + symbol->encoded_data[symbol->rows][writer] = latch; + writer++; + } + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } + symbol->encoded_data[symbol->rows][writer] = '1'; + symbol->encoded_data[symbol->rows][writer + 1] = '0'; + symbol->row_height[symbol->rows] = 5; + /* bottom row */ + symbol->rows = symbol->rows + 2; + symbol->encoded_data[symbol->rows][0] = '1'; + symbol->encoded_data[symbol->rows][1] = '0'; + writer = 0; + latch = '1'; + for(i = 23; i < 46; i++) { + for(j = 0; j < total_widths[i]; j++) { + symbol->encoded_data[symbol->rows][writer + 2] = latch; + writer++; + } + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } + symbol->row_height[symbol->rows] = 7; + /* separator pattern */ + for(i = 4; i < 46; i++) { + if(symbol->encoded_data[symbol->rows - 2][i] == symbol->encoded_data[symbol->rows][i]) { + if(symbol->encoded_data[symbol->rows - 2][i] == '0') { + symbol->encoded_data[symbol->rows - 1][i] = '1'; + } + } else { + if(symbol->encoded_data[symbol->rows - 1][i - 1] != '1') { + symbol->encoded_data[symbol->rows - 1][i] = '1'; + } + } + } + symbol->row_height[symbol->rows - 1] = 1; + if(symbol->symbology == BARCODE_RSS14STACK_CC) { + /* separator pattern for composite symbol */ + for(i = 4; i < 46; i++) { + if(symbol->encoded_data[separator_row + 1][i] != '1') { + symbol->encoded_data[separator_row][i] = '1'; + } + } + latch = '1'; + for(i = 16; i < 32; i++) { + if(symbol->encoded_data[separator_row + 1][i] != '1') { + symbol->encoded_data[separator_row][i] = latch; + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } else { + symbol->encoded_data[separator_row][i] = '0'; + latch = '1'; + } + } + } + symbol->rows = symbol->rows + 1; + if(symbol->width < 50) { symbol->width = 50; } + } + + if((symbol->symbology == BARCODE_RSS14STACK_OMNI) || (symbol->symbology == BARCODE_RSS14_OMNI_CC)) { + /* top row */ + writer = 0; + latch = '0'; + for(i = 0; i < 23; i++) { + for(j = 0; j < total_widths[i]; j++) { + symbol->encoded_data[symbol->rows][writer] = latch; + writer++; + } + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } + symbol->encoded_data[symbol->rows][writer] = '1'; + symbol->encoded_data[symbol->rows][writer + 1] = '0'; + /* bottom row */ + symbol->rows = symbol->rows + 4; + symbol->encoded_data[symbol->rows][0] = '1'; + symbol->encoded_data[symbol->rows][1] = '0'; + writer = 0; + latch = '1'; + for(i = 23; i < 46; i++) { + for(j = 0; j < total_widths[i]; j++) { + symbol->encoded_data[symbol->rows][writer + 2] = latch; + writer++; + } + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } + /* middle separator */ + for(i = 5; i < 46; i += 2) { + symbol->encoded_data[symbol->rows - 2][i] = '1'; + } + symbol->row_height[symbol->rows - 2] = 1; + /* top separator */ + for(i = 4; i < 46; i++) { + if(symbol->encoded_data[symbol->rows - 4][i] != '1') { + symbol->encoded_data[symbol->rows - 3][i] = '1'; + } + } + latch = '1'; + for(i = 17; i < 33; i++) { + if(symbol->encoded_data[symbol->rows - 4][i] != '1') { + symbol->encoded_data[symbol->rows - 3][i] = latch; + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } else { + symbol->encoded_data[symbol->rows - 3][i] = '0'; + latch = '1'; + } + } + symbol->row_height[symbol->rows - 3] = 1; + /* bottom separator */ + for(i = 4; i < 46; i++) { + if(symbol->encoded_data[symbol->rows][i] != '1') { + symbol->encoded_data[symbol->rows - 1][i] = '1'; + } + } + latch = '1'; + for(i = 16; i < 32; i++) { + if(symbol->encoded_data[symbol->rows][i] != '1') { + symbol->encoded_data[symbol->rows - 1][i] = latch; + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } else { + symbol->encoded_data[symbol->rows - 1][i] = '0'; + latch = '1'; + } + } + symbol->row_height[symbol->rows - 1] = 1; + if(symbol->width < 50) { symbol->width = 50; } + if(symbol->symbology == BARCODE_RSS14_OMNI_CC) { + /* separator pattern for composite symbol */ + for(i = 4; i < 46; i++) { + if(symbol->encoded_data[separator_row + 1][i] != '1') { + symbol->encoded_data[separator_row][i] = '1'; + } + } + latch = '1'; + for(i = 16; i < 32; i++) { + if(symbol->encoded_data[separator_row + 1][i] != '1') { + symbol->encoded_data[separator_row][i] = latch; + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } else { + symbol->encoded_data[separator_row][i] = '0'; + latch = '1'; + } + } + } + symbol->rows = symbol->rows + 1; + } + + + return errno; +} + +int rsslimited(struct zint_symbol *symbol, unsigned char source[]) +{ /* GS1 DataBar Limited */ + int errno = 0, i, mask; + short int accum[112], left_reg[112], right_reg[112], x_reg[112], y_reg[112]; + int left_group, right_group, left_odd, left_even, right_odd, right_even; + int left_character, right_character, left_widths[14], right_widths[14]; + int checksum, check_elements[14], total_widths[46], writer, j, check_digit, count; + char latch, hrt[15]; + int separator_row; + + separator_row = 0; + + if(strlen(source) > 13) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* make some room for a separator row for composite symbols */ + if(symbol->symbology == BARCODE_RSS_LTD_CC) { + separator_row = symbol->rows; + symbol->row_height[separator_row] = 1; + symbol->rows += 1; + } + + for(i = 0; i < 112; i++) { + accum[i] = 0; + x_reg[i] = 0; + y_reg[i] = 0; + } + + binary_load(accum, source); + if(symbol->option_1 == 2) { + /* Add symbol linkage flag */ + binary_load(y_reg, "2015133531096"); + binary_add(accum, y_reg); + for(i = 0; i < 112; i++) { + y_reg[i] = 0; + } + } + + /* Calculate left and right pair values */ + binary_load(x_reg, "2013571"); + + for(i = 0; i < 24; i++) { + shiftup(x_reg); + } + + for(i = 24; i >= 0; i--) { + y_reg[i] = islarger(accum, x_reg); + if(y_reg[i] == 1) { + binary_subtract(accum, x_reg); + } + shiftdown(x_reg); + } + + for(i = 0; i < 112; i++) { + left_reg[i] = y_reg[i]; + right_reg[i] = accum[i]; + } + + left_group = 0; + binary_load(accum, "183063"); + if(islarger(left_reg, accum)) { left_group = 1; } + binary_load(accum, "820063"); + if(islarger(left_reg, accum)) { left_group = 2; } + binary_load(accum, "1000775"); + if(islarger(left_reg, accum)) { left_group = 3; } + binary_load(accum, "1491020"); + if(islarger(left_reg, accum)) { left_group = 4; } + binary_load(accum, "1979844"); + if(islarger(left_reg, accum)) { left_group = 5; } + binary_load(accum, "1996938"); + if(islarger(left_reg, accum)) { left_group = 6; } + right_group = 0; + binary_load(accum, "183063"); + if(islarger(right_reg, accum)) { right_group = 1; } + binary_load(accum, "820063"); + if(islarger(right_reg, accum)) { right_group = 2; } + binary_load(accum, "1000775"); + if(islarger(right_reg, accum)) { right_group = 3; } + binary_load(accum, "1491020"); + if(islarger(right_reg, accum)) { right_group = 4; } + binary_load(accum, "1979844"); + if(islarger(right_reg, accum)) { right_group = 5; } + binary_load(accum, "1996938"); + if(islarger(right_reg, accum)) { right_group = 6; } + + switch(left_group) { + case 1: binary_load(accum, "183064"); + binary_subtract(left_reg, accum); + break; + case 2: binary_load(accum, "820064"); + binary_subtract(left_reg, accum); + break; + case 3: binary_load(accum, "1000776"); + binary_subtract(left_reg, accum); + break; + case 4: binary_load(accum, "1491021"); + binary_subtract(left_reg, accum); + break; + case 5: binary_load(accum, "1979845"); + binary_subtract(left_reg, accum); + break; + case 6: binary_load(accum, "1996939"); + binary_subtract(left_reg, accum); + break; + } + + switch(right_group) { + case 1: binary_load(accum, "183064"); + binary_subtract(right_reg, accum); + break; + case 2: binary_load(accum, "820064"); + binary_subtract(right_reg, accum); + break; + case 3: binary_load(accum, "1000776"); + binary_subtract(right_reg, accum); + break; + case 4: binary_load(accum, "1491021"); + binary_subtract(right_reg, accum); + break; + case 5: binary_load(accum, "1979845"); + binary_subtract(right_reg, accum); + break; + case 6: binary_load(accum, "1996939"); + binary_subtract(right_reg, accum); + break; + } + + left_character = 0; + right_character = 0; + mask = 0x800000; + for(i = 23; i >= 0; i--) { + if(left_reg[i] == 1) { + left_character += mask; + } + if(right_reg[i] == 1) { + right_character += mask; + } + mask = mask >> 1; + } + + left_odd = left_character / t_even_ltd[left_group]; + left_even = left_character % t_even_ltd[left_group]; + right_odd = right_character / t_even_ltd[right_group]; + right_even = right_character % t_even_ltd[right_group]; + + getRSSwidths(left_odd, modules_odd_ltd[left_group], 7, widest_odd_ltd[left_group], 1); + left_widths[0] = widths[0]; + left_widths[2] = widths[1]; + left_widths[4] = widths[2]; + left_widths[6] = widths[3]; + left_widths[8] = widths[4]; + left_widths[10] = widths[5]; + left_widths[12] = widths[6]; + getRSSwidths(left_even, modules_even_ltd[left_group], 7, widest_even_ltd[left_group], 0); + left_widths[1] = widths[0]; + left_widths[3] = widths[1]; + left_widths[5] = widths[2]; + left_widths[7] = widths[3]; + left_widths[9] = widths[4]; + left_widths[11] = widths[5]; + left_widths[13] = widths[6]; + getRSSwidths(right_odd, modules_odd_ltd[right_group], 7, widest_odd_ltd[right_group], 1); + right_widths[0] = widths[0]; + right_widths[2] = widths[1]; + right_widths[4] = widths[2]; + right_widths[6] = widths[3]; + right_widths[8] = widths[4]; + right_widths[10] = widths[5]; + right_widths[12] = widths[6]; + getRSSwidths(right_even, modules_even_ltd[right_group], 7, widest_even_ltd[right_group], 0); + right_widths[1] = widths[0]; + right_widths[3] = widths[1]; + right_widths[5] = widths[2]; + right_widths[7] = widths[3]; + right_widths[9] = widths[4]; + right_widths[11] = widths[5]; + right_widths[13] = widths[6]; + + checksum = 0; + /* Calculate the checksum */ + for(i = 0; i < 14; i++) { + checksum += checksum_weight_ltd[i] * left_widths[i]; + checksum += checksum_weight_ltd[i + 14] * right_widths[i]; + } + checksum %= 89; + + for(i = 0; i < 14; i++) { + check_elements[i] = finder_pattern_ltd[i + (checksum * 14)]; + } + + total_widths[0] = 1; + total_widths[1] = 1; + total_widths[44] = 1; + total_widths[45] = 1; + for(i = 0; i < 14; i++) { + total_widths[i + 2] = left_widths[i]; + total_widths[i + 16] = check_elements[i]; + total_widths[i + 30] = right_widths[i]; + } + + writer = 0; + latch = '0'; + for(i = 0; i < 46; i++) { + for(j = 0; j < total_widths[i]; j++) { + symbol->encoded_data[symbol->rows][writer] = latch; + writer++; + } + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } + if(symbol->width < writer) { symbol->width = writer; } + symbol->rows = symbol->rows + 1; + + /* add separator pattern if composite symbol */ + if(symbol->symbology == BARCODE_RSS_LTD_CC) { + for(i = 4; i < 70; i++) { + if(symbol->encoded_data[separator_row + 1][i] != '1') { + symbol->encoded_data[separator_row][i] = '1'; + } + } + } + + /* Calculate check digit from Annex A and place human readable text */ + + check_digit = 0; + count = 0; + + strcpy(symbol->text, "(01)"); + for(i = 0; i < 14; i++) { + hrt[i] = '0'; + } + for(i = 0; i < strlen(source); i++) { + hrt[12 - i] = source[strlen(source) - i - 1]; + } + + for (i = 0; i < 13; i++) + { + count += ctoi(hrt[i]); + + if ((i%2) == 0) + { + count += 2 * (ctoi(hrt[i])); + } + } + + check_digit = 10 - (count%10); + if (check_digit == 10) { check_digit = 0; } + + hrt[13] = itoc(check_digit); + hrt[14] = '\0'; + + concat(symbol->text, hrt); + + return errno; +} + +int general_rules(char field[], char type[]) +{ /* Attempts to apply encoding rules from secions 7.2.5.5.1 to 7.2.5.5.3 + of ISO/IEC 24724:2006 */ + int block[2][200], block_count, i, j, k; + char current, next, last; + + block_count = 0; + + block[0][block_count] = 1; + block[1][block_count] = type[0]; + + for(i = 1; i < strlen(type); i++) { + current = type[i]; + last = type[i - 1]; + + if(current == last) { + block[0][block_count] = block[0][block_count] + 1; + } else { + block_count++; + block[0][block_count] = 1; + block[1][block_count] = type[i]; + } + } + + block_count++; + + for(i = 0; i < block_count; i++) { + } + + for(i = 0; i < block_count; i++) { + current = block[1][i]; + next = block[1][i + 1]; + + if(current == ISOIEC) { + if((next == ANY_ENC) && (block[0][i + 1] >= 4)) { + block[1][i + 1] = NUMERIC; + } + if((next == ANY_ENC) && (block[0][i + 1] < 4)) { + block[1][i + 1] = ISOIEC; + } + if((next == ALPHA_OR_ISO) && (block[0][i + 1] >= 5)) { + block[1][i + 1] = ALPHA; + } + if((next == ALPHA_OR_ISO) && (block[0][i + 1] < 5)) { + block[1][i + 1] = ISOIEC; + } + } + + if(current == ALPHA_OR_ISO) { + block[1][i] = ALPHA; + } + + if(current == ALPHA) { + if((next == ANY_ENC) && (block[0][i + 1] >= 6)) { + block[1][i + 1] = NUMERIC; + } + if((next == ANY_ENC) && (block[0][i + 1] < 6)) { + if((i == block_count - 2) && (block[0][i + 1] >= 4)) { + block[1][i + 1] = NUMERIC; + } else { + block[1][i + 1] = ALPHA; + } + } + } + + if(current == ANY_ENC) { + block[1][i] = NUMERIC; + } + } + + if(block_count > 1) { + i = 1; + while(i < block_count) { + if(block[1][i - 1] == block[1][i]) { + /* bring together */ + block[0][i - 1] = block[0][i - 1] + block[0][i]; + j = i + 1; + + /* decreace the list */ + while(j < block_count) { + block[0][j - 1] = block[0][j]; + block[1][j - 1] = block[1][j]; + j++; + } + block_count--; + i--; + } + i++; + } + } + + for(i = 0; i < block_count - 1; i++) { + if((block[1][i] == NUMERIC) && (block[0][i] % 2 == 1)) { + /* Odd size numeric block */ + block[0][i] = block[0][i] - 1; + block[0][i + 1] = block[0][i + 1] + 1; + } + } + + j = 0; + for(i = 0; i < block_count; i++) { + for(k = 0; k < block[0][i]; k++) { + type[j] = block[1][i]; + j++; + } + } + + if((block[1][block_count - 1] == NUMERIC) && (block[0][block_count - 1] % 2 == 1)) { + /* If the last block is numeric and an odd size, further + processing needs to be done outside this procedure */ + return 1; + } else { + return 0; + } +} + +int rss_binary_string(struct zint_symbol *symbol, unsigned char source[], char binary_string[]) +{ /* Handles all data encodation from section 7.2.5 of ISO/IEC 24724 */ + int encoding_method, i, mask, j, read_posn, latch; + char general_field[strlen(source)], general_field_type[strlen(source)]; + int remainder, d1, d2, value; + char padstring[14]; + + + /* Decide whether a compressed data field is required and if so what + method to use - method 2 = no compressed data field */ + + if((strlen(source) >= 16) && ((source[0] == '0') && (source[1] == '1'))) { + /* (01) and other AIs */ + encoding_method = 1; + } else { + /* any AIs */ + encoding_method = 2; + } + + if(((strlen(source) >= 20) && (encoding_method == 1)) && ((source[2] == '9') && (source[16] == '3'))) { + /* Possibly encoding method > 2 */ + + if((strlen(source) >= 26) && (source[17] == '1')) { + /* Methods 3, 7, 9, 11 and 13 */ + + if(source[18] == '0') { + /* (01) and (310x) */ + char weight_str[7]; + float weight; /* In kilos */ + + for(i = 0; i < 6; i++) { + weight_str[i] = source[20 + i]; + } + weight_str[6] = '\0'; + + if (weight_str[0] == '0') { /* Maximum weight = 99999 */ + + + encoding_method = 7; + + if((source[19] == '3') && (strlen(source) == 26)) { + /* (01) and (3103) */ + weight = atof(weight_str) / 1000.0; + + if(weight <= 32.767) { encoding_method = 3; } + } + + if(strlen(source) == 34){ + if((source[26] == '1') && (source[27] == '1')) { + /* (01), (310x) and (11) - metric weight and production date */ + encoding_method = 7; + } + + if((source[26] == '1') && (source[27] == '3')) { + /* (01), (310x) and (13) - metric weight and packaging date */ + encoding_method = 9; + } + + if((source[26] == '1') && (source[27] == '5')) { + /* (01), (310x) and (15) - metric weight and "best before" date */ + encoding_method = 11; + } + + if((source[26] == '1') && (source[27] == '7')) { + /* (01), (310x) and (17) - metric weight and expiration date */ + encoding_method = 13; + } + } + } + } + } + + if((strlen(source) >= 26) && (source[17] == '2')) { + /* Methods 4, 8, 10, 12 and 14 */ + + if(source[18] == '0') { + /* (01) and (320x) */ + char weight_str[7]; + float weight; /* In pounds */ + + for(i = 0; i < 6; i++) { + weight_str[i] = source[20 + i]; + } + weight_str[6] = '\0'; + + if (weight_str[0] == '0') { /* Maximum weight = 99999 */ + + encoding_method = 8; + + if(((source[19] == '2') || (source[19] == '3')) && (strlen(source) == 26)) { + /* (01) and (3202)/(3203) */ + + if(source[19] == '3') { + weight = atof(weight_str) / 1000.0; + if(weight <= 22.767) { + encoding_method = 4; + } + } else { + weight = atof(weight_str) / 100.0; + if(weight <= 99.99) { + encoding_method = 4; + } + } + + } + + if(strlen(source) == 34){ + if((source[26] == '1') && (source[27] == '1')) { + /* (01), (320x) and (11) - English weight and production date */ + encoding_method = 8; + } + + if((source[26] == '1') && (source[27] == '3')) { + /* (01), (320x) and (13) - English weight and packaging date */ + encoding_method = 10; + } + + if((source[26] == '1') && (source[27] == '5')) { + /* (01), (320x) and (15) - English weight and "best before" date */ + encoding_method = 12; + } + + if((source[26] == '1') && (source[27] == '7')) { + /* (01), (320x) and (17) - English weight and expiration date */ + encoding_method = 14; + } + } + } + } + + } + + if(source[17] == '9') { + /* Methods 5 and 6 */ + if((source[18] == '2') && ((source[19] >= '0') && (source[19] <= '3'))) { + /* (01) and (392x) */ + encoding_method = 5; + } + if((source[18] == '3') && ((source[19] >= '0') && (source[19] <= '3'))) { + /* (01) and (393x) */ + encoding_method = 6; + } + } + } + + switch(encoding_method) { /* Encoding method - Table 10 */ + case 1: concat(binary_string, "1XX"); read_posn = 16; break; + case 2: concat(binary_string, "00XX"); read_posn = 0; break; + case 3: concat(binary_string, "0100"); read_posn = strlen(source); break; + case 4: concat(binary_string, "0101"); read_posn = strlen(source); break; + case 5: concat(binary_string, "01100XX"); read_posn = 20; break; + case 6: concat(binary_string, "01101XX"); read_posn = 23; break; + case 7: concat(binary_string, "0111000"); read_posn = strlen(source); break; + case 8: concat(binary_string, "0111001"); read_posn = strlen(source); break; + case 9: concat(binary_string, "0111010"); read_posn = strlen(source); break; + case 10: concat(binary_string, "0111011"); read_posn = strlen(source); break; + case 11: concat(binary_string, "0111100"); read_posn = strlen(source); break; + case 12: concat(binary_string, "0111101"); read_posn = strlen(source); break; + case 13: concat(binary_string, "0111110"); read_posn = strlen(source); break; + case 14: concat(binary_string, "0111111"); read_posn = strlen(source); break; + } + + /* Variable length symbol bit field is just given a place holder (XX) + for the time being */ + + /* Verify that the data to be placed in the compressed data field is all + numeric data before carrying out compression */ + for(i = 0; i < read_posn; i++) { + if((source[i] < '0') || (source[i] > '9')) { + if((source[i] != '[') && (source[i] != ']')) { + /* Something is wrong */ + strcpy(symbol->errtxt, "Invalid characters in input data"); + return ERROR_INVALID_DATA; + } + } + } + + /* Now encode the compressed data field */ + + if(encoding_method == 1) { + /* Encoding method field "1" - general item identification data */ + char group[4]; + int group_val; + + group[0] = source[2]; + group[1] = '\0'; + group_val = atoi(group); + + mask = 0x08; + for(j = 0; j < 4; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + + for(i = 1; i < 5; i++) { + group[0] = source[(i * 3)]; + group[1] = source[(i * 3) + 1]; + group[2] = source[(i * 3) + 2]; + group[3] = '\0'; + group_val = atoi(group); + + mask = 0x200; + for(j = 0; j < 10; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + + } + + + if(encoding_method == 3) { + /* Encoding method field "0100" - variable weight item + (0,001 kilogram icrements) */ + char group[4]; + int group_val; + char weight_str[7]; + + for(i = 1; i < 5; i++) { + group[0] = source[(i * 3)]; + group[1] = source[(i * 3) + 1]; + group[2] = source[(i * 3) + 2]; + group[3] = '\0'; + group_val = atoi(group); + + mask = 0x200; + for(j = 0; j < 10; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + for(i = 0; i < 6; i++) { + weight_str[i] = source[20 + i]; + } + weight_str[6] = '\0'; + group_val = atoi(weight_str); + + mask = 0x4000; + for(j = 0; j < 15; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + + + } + + if(encoding_method == 4) { + /* Encoding method field "0101" - variable weight item (0,01 or + 0,001 pound increment) */ + char group[4]; + int group_val; + char weight_str[7]; + + for(i = 1; i < 5; i++) { + group[0] = source[(i * 3)]; + group[1] = source[(i * 3) + 1]; + group[2] = source[(i * 3) + 2]; + group[3] = '\0'; + group_val = atoi(group); + + mask = 0x200; + for(j = 0; j < 10; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + for(i = 0; i < 6; i++) { + weight_str[i] = source[20 + i]; + } + weight_str[6] = '\0'; + group_val = atoi(weight_str); + + if(source[19] == '3') { + group_val = group_val + 10000; + } + + mask = 0x4000; + for(j = 0; j < 15; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + + } + + + if((encoding_method >= 7) && (encoding_method <= 14)) { + /* Encoding method fields "0111000" through "0111111" - variable + weight item plus date */ + char group[4]; + int group_val; + char weight_str[8]; + char date_str[4]; + + for(i = 1; i < 5; i++) { + group[0] = source[(i * 3)]; + group[1] = source[(i * 3) + 1]; + group[2] = source[(i * 3) + 2]; + group[3] = '\0'; + group_val = atoi(group); + + mask = 0x200; + for(j = 0; j < 10; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + weight_str[0] = source[19]; + + for(i = 0; i < 5; i++) { + weight_str[i + 1] = source[21 + i]; + } + weight_str[6] = '\0'; + group_val = atoi(weight_str); + + mask = 0x80000; + for(j = 0; j < 20; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + + if(strlen(source) == 34) { + /* Date information is included */ + date_str[0] = source[28]; + date_str[1] = source[29]; + date_str[2] = '\0'; + group_val = atoi(date_str) * 384; + + date_str[0] = source[30]; + date_str[1] = source[31]; + group_val += (atoi(date_str) - 1) * 32; + + date_str[0] = source[32]; + date_str[1] = source[33]; + group_val += atoi(date_str); + } else { + group_val = 38400; + } + + mask = 0x8000; + for(j = 0; j < 16; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + + } + + if(encoding_method == 5) { + /* Encoding method field "01100" - variable measure item and price */ + char group[4]; + int group_val; + + for(i = 1; i < 5; i++) { + group[0] = source[(i * 3)]; + group[1] = source[(i * 3) + 1]; + group[2] = source[(i * 3) + 2]; + group[3] = '\0'; + group_val = atoi(group); + + mask = 0x200; + for(j = 0; j < 10; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + switch(source[19]) { + case '0': concat(binary_string, "00"); break; + case '1': concat(binary_string, "01"); break; + case '2': concat(binary_string, "10"); break; + case '3': concat(binary_string, "11"); break; + } + } + + if(encoding_method == 6) { + /* Encoding method "01101" - variable measure item and price with ISO 4217 + Currency Code */ + + char group[4]; + int group_val; + char currency_str[5]; + + for(i = 1; i < 5; i++) { + group[0] = source[(i * 3)]; + group[1] = source[(i * 3) + 1]; + group[2] = source[(i * 3) + 2]; + group[3] = '\0'; + group_val = atoi(group); + + mask = 0x200; + for(j = 0; j < 10; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + switch(source[19]) { + case '0': concat(binary_string, "00"); break; + case '1': concat(binary_string, "01"); break; + case '2': concat(binary_string, "10"); break; + case '3': concat(binary_string, "11"); break; + } + + for(i = 0; i < 3; i++) { + currency_str[i] = source[20 + i]; + } + currency_str[3] = '\0'; + group_val = atoi(currency_str); + + mask = 0x200; + for(j = 0; j < 10; j++) { + if((group_val & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 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; + for(i = read_posn; i < strlen(source); i++) { + general_field[j] = source[i]; + j++; + } + general_field[j] = '\0'; + + latch = 0; + for(i = 0; i < strlen(general_field); i++) { + /* Table 13 - ISO/IEC 646 encodation */ + if((general_field[i] < ' ') || (general_field[i] > 'z')) { + general_field_type[i] = INVALID_CHAR; latch = 1; + } else { + general_field_type[i] = ISOIEC; + } + + if(general_field[i] == '#') { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + if(general_field[i] == '$') { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + if(general_field[i] == '@') { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + if(general_field[i] == 92) { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + if(general_field[i] == '^') { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + if(general_field[i] == 96) { + general_field_type[i] = INVALID_CHAR; latch = 1; + } + + /* Table 12 - Alphanumeric encodation */ + if((general_field[i] >= 'A') && (general_field[i] <= 'Z')) { + general_field_type[i] = ALPHA_OR_ISO; + } + if(general_field[i] == '*') { + general_field_type[i] = ALPHA_OR_ISO; + } + if(general_field[i] == ',') { + general_field_type[i] = ALPHA_OR_ISO; + } + if(general_field[i] == '-') { + general_field_type[i] = ALPHA_OR_ISO; + } + if(general_field[i] == '.') { + general_field_type[i] = ALPHA_OR_ISO; + } + if(general_field[i] == '/') { + general_field_type[i] = ALPHA_OR_ISO; + } + + /* Numeric encodation */ + if((general_field[i] >= '0') && (general_field[i] <= '9')) { + general_field_type[i] = ANY_ENC; + } + if(general_field[i] == '[') { + /* FNC1 can be encoded in any system */ + general_field_type[i] = ANY_ENC; + } + + } + + general_field_type[strlen(general_field)] = '\0'; + + if(latch == 1) { + /* Invalid characters in input data */ + strcpy(symbol->errtxt, "Invalid characters in input data"); + return ERROR_INVALID_DATA; + } + + for(i = 0; i < strlen(general_field); i++) { + if((general_field_type[i] == ISOIEC) && (general_field[i + 1] == '[')) { + general_field_type[i + 1] = ISOIEC; + } + } + + for(i = 0; i < strlen(general_field); i++) { + if((general_field_type[i] == ALPHA_OR_ISO) && (general_field[i + 1] == '[')) { + general_field_type[i + 1] = ALPHA_OR_ISO; + } + } + + latch = general_rules(general_field, general_field_type); + + i = 0; + do { + switch(general_field_type[i]) { + case NUMERIC: + + if(i != 0) { + if((general_field_type[i - 1] != NUMERIC) && (general_field[i - 1] != '[')) { + concat(binary_string, "000"); /* Numeric latch */ + } + } + + if(general_field[i] != '[') { + d1 = ctoi(general_field[i]); + } else { + d1 = 10; + } + + if(general_field[i + 1] != '[') { + d2 = ctoi(general_field[i + 1]); + } else { + d2 = 10; + } + + value = (11 * d1) + d2 + 8; + + mask = 0x40; + for(j = 0; j < 7; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + + i += 2; + break; + + case ALPHA: + + if(i != 0) { + if((general_field_type[i - 1] == NUMERIC) || (general_field[i - 1] == '[')) { + concat(binary_string, "0000"); /* Alphanumeric latch */ + } + if(general_field_type[i - 1] == ISOIEC) { + concat(binary_string, "00100"); /* ISO/IEC 646 latch */ + } + } + + if((general_field[i] >= '0') && (general_field[i] <= '9')) { + + value = general_field[i] - 43; + + mask = 0x10; + for(j = 0; j < 5; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if((general_field[i] >= 'A') && (general_field[i] <= 'Z')) { + + value = general_field[i] - 33; + + mask = 0x20; + for(j = 0; j < 6; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if(general_field[i] == '[') concat(binary_string, "01111"); /* FNC1/Numeric latch */ + if(general_field[i] == '*') concat(binary_string, "111010"); /* asterisk */ + if(general_field[i] == ',') concat(binary_string, "111011"); /* comma */ + if(general_field[i] == '-') concat(binary_string, "111100"); /* minus or hyphen */ + if(general_field[i] == '.') concat(binary_string, "111101"); /* period or full stop */ + if(general_field[i] == '/') concat(binary_string, "111110"); /* slash or solidus */ + + i++; + break; + + case ISOIEC: + + if(i != 0) { + if((general_field_type[i - 1] == NUMERIC) || (general_field[i - 1] == '[')) { + concat(binary_string, "0000"); /* Alphanumeric latch */ + concat(binary_string, "00100"); /* ISO/IEC 646 latch */ + } + if(general_field_type[i - 1] == ALPHA) { + concat(binary_string, "00100"); /* ISO/IEC 646 latch */ + } + } + + if((general_field[i] >= '0') && (general_field[i] <= '9')) { + + value = general_field[i] - 43; + + mask = 0x10; + for(j = 0; j < 5; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if((general_field[i] >= 'A') && (general_field[i] <= 'Z')) { + + value = general_field[i] - 1; + + mask = 0x40; + for(j = 0; j < 7; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if((general_field[i] >= 'a') && (general_field[i] <= 'z')) { + + value = general_field[i] - 7; + + mask = 0x40; + for(j = 0; j < 7; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + + if(general_field[i] == '[') concat(binary_string, "01111"); /* FNC1/Numeric latch */ + if(general_field[i] == '!') concat(binary_string, "11101000"); /* exclamation mark */ + if(general_field[i] == 34) concat(binary_string, "11101001"); /* quotation mark */ + if(general_field[i] == 37) concat(binary_string, "11101010"); /* percent sign */ + if(general_field[i] == '&') concat(binary_string, "11101011"); /* ampersand */ + if(general_field[i] == 39) concat(binary_string, "11101100"); /* apostrophe */ + if(general_field[i] == '(') concat(binary_string, "11101101"); /* left parenthesis */ + if(general_field[i] == ')') concat(binary_string, "11101110"); /* right parenthesis */ + if(general_field[i] == '*') concat(binary_string, "11101111"); /* asterisk */ + if(general_field[i] == '+') concat(binary_string, "11110000"); /* plus sign */ + if(general_field[i] == ',') concat(binary_string, "11110001"); /* comma */ + if(general_field[i] == '-') concat(binary_string, "11110010"); /* minus or hyphen */ + if(general_field[i] == '.') concat(binary_string, "11110011"); /* period or full stop */ + if(general_field[i] == '/') concat(binary_string, "11110100"); /* slash or solidus */ + if(general_field[i] == ':') concat(binary_string, "11110101"); /* colon */ + if(general_field[i] == ';') concat(binary_string, "11110110"); /* semicolon */ + if(general_field[i] == '<') concat(binary_string, "11110111"); /* less-than sign */ + if(general_field[i] == '=') concat(binary_string, "11111000"); /* equals sign */ + if(general_field[i] == '>') concat(binary_string, "11111001"); /* greater-than sign */ + if(general_field[i] == '?') concat(binary_string, "11111010"); /* question mark */ + if(general_field[i] == '_') concat(binary_string, "11111011"); /* underline or low line */ + if(general_field[i] == ' ') concat(binary_string, "11111100"); /* space */ + + i++; + break; + } + } while (i + latch < strlen(general_field)); + + remainder = strlen(binary_string) % 12; + if(strlen(binary_string) < 36) { remainder = 36 - strlen(binary_string); } + + if(latch == 1) { + i = 0; + /* There is still one more numeric digit to encode */ + + if((remainder >= 4) && (remainder <= 6)) { + d1 = ctoi(general_field[i]); + d1++; + + mask = 0x08; + for(j = 0; j < 4; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } else { + d1 = ctoi(general_field[i]); + d2 = 10; + + value = (11 * d1) + d2 + 8; + + mask = 0x40; + for(j = 0; j < 7; j++) { + if((value & mask) == 0x00) { + concat(binary_string, "0"); + } else { + concat(binary_string, "1"); + } + mask = mask >> 1; + } + } + remainder = strlen(binary_string) % 12; + if(strlen(binary_string) < 36) { remainder = 36 - strlen(binary_string); } + } + + if(strlen(binary_string) > 252) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + /* Now add padding to binary string */ + if (general_field_type[strlen(general_field) - 1] == NUMERIC) { + strcpy(padstring, "000000100001"); + } else { + strcpy(padstring, "001000010000"); + } + padstring[remainder] = '\0'; + concat(binary_string, padstring); + + /* Patch variable length symbol bit field */ + d1 = ((strlen(binary_string) / 12) + 1) % 2; + if(strlen(binary_string) <= 156) { d2 = 0; } else { d2 = 1; } + + if(encoding_method == 1) { + if(d1 == 0) { binary_string[2] = '0'; } else { binary_string[2] = '1'; } + if(d2 == 0) { binary_string[3] = '0'; } else { binary_string[3] = '1'; } + } + if(encoding_method == 2) { + if(d1 == 0) { binary_string[3] = '0'; } else { binary_string[3] = '1'; } + if(d2 == 0) { binary_string[4] = '0'; } else { binary_string[4] = '1'; } + } + if((encoding_method == 5) || (encoding_method == 6)) { + if(d1 == 0) { binary_string[6] = '0'; } else { binary_string[6] = '1'; } + if(d2 == 0) { binary_string[7] = '0'; } else { binary_string[7] = '1'; } + } + + return 0; +} + +int rssexpanded(struct zint_symbol *symbol, unsigned char source[]) +{ /* GS1 DataBar Expanded */ + int i, j, k, l, data_chars, vs[21], group[21], v_odd[21], v_even[21]; + char binary_string[7 * strlen(source)], substring[21][14], latch; + int char_widths[21][8], checksum, check_widths[8], c_group; + int check_char, c_odd, c_even, elements[235], pattern_width, reader, writer; + int row, elements_in_sub, special_case_row, left_to_right; + int codeblocks, sub_elements[235], stack_rows, current_row, current_block; + char reduced[170], ai_string[4]; + int last_ai, ai_latch, separator_row; + + separator_row = 0; + + if(source[0] != '[') { + strcpy(symbol->errtxt, "Data does not start with an AI"); + return ERROR_INVALID_DATA; + } + + for(i = 0; i < strlen(source) - 1; i++) { + if((source[i] == '[') && (source[i + 1] == '[')) { + /* Can't have nested brackets - Quit */ + strcpy(symbol->errtxt, "Nested AI detected (two or more open brackets)"); + return ERROR_INVALID_DATA; + } + } + + for(i = 0; i < strlen(source) - 1; i++) { + if((source[i] == ']') && (source[i + 1] == ']')) { + /* Can't have nested brackets - Quit */ + strcpy(symbol->errtxt, "Nested AI detected (two or more close brackets)"); + return ERROR_INVALID_DATA; + } + } + + if((symbol->symbology == BARCODE_RSS_EXP_CC) || (symbol->symbology == BARCODE_RSS_EXPSTACK_CC)) { + /* make space for a composite separator pattern */ + separator_row = symbol->rows; + symbol->row_height[separator_row] = 1; + symbol->rows += 1; + } + + strcpy(binary_string, ""); + + if(symbol->option_1 == 2) { + concat(binary_string, "1"); + } else { + concat(binary_string, "0"); + } + + /* Resolve AI data - put resulting string in 'reduced' */ + j = 0; + last_ai = 0; + ai_latch = 1; + for(i = 0; i < strlen(source); i++) { + if((source[i] != '[') && (source[i] != ']')) { + reduced[j] = source[i]; + j++; + } + if(source[i] == '[') { + /* Start of an AI string */ + if(ai_latch == 0) { + reduced[j] = '['; + j++; + } + ai_string[0] = source[i + 1]; + ai_string[1] = source[i + 2]; + ai_string[2] = '\0'; + last_ai = atoi(ai_string); + ai_latch = 0; + /* The following values from GS1 specification figure 5.3.8.2.1 - 1 + "Element Strings with Pre-Defined Length Using Application Identifiers" */ + if((last_ai >= 0) && (last_ai <= 4)) { ai_latch = 1; } + if((last_ai >= 11) && (last_ai <= 20)) { ai_latch = 1; } + if(last_ai == 23) { ai_latch = 1; } /* legacy support - see 5.3.8.2.2 */ + if((last_ai >= 31) && (last_ai <= 36)) { ai_latch = 1; } + if(last_ai == 41) { ai_latch = 1; } + } + /* The ']' character is simply dropped from the input */ + } + reduced[j] = '\0'; + + /* the character '[' in the reduced string refers to the FNC1 character */ + + /* Note that no attempt is made to verify that the data to be encoded does + actually conform to the right data length - that is required of the person or + program inputting the data */ + + i = rss_binary_string(symbol, reduced, binary_string); + if(i != 0) { + return i; + } + + data_chars = strlen(binary_string) / 12; + + for(i = 0; i < data_chars; i++) { + for(j = 0; j < 12; j++) { + substring[i][j] = binary_string[(i * 12) + j]; + } + substring[i][12] = '\0'; + } + + for(i = 0; i < data_chars; i++) { + vs[i] = 0; + if(substring[i][0] == '1') { vs[i] += 2048; } + if(substring[i][1] == '1') { vs[i] += 1024; } + if(substring[i][2] == '1') { vs[i] += 512; } + if(substring[i][3] == '1') { vs[i] += 256; } + if(substring[i][4] == '1') { vs[i] += 128; } + if(substring[i][5] == '1') { vs[i] += 64; } + if(substring[i][6] == '1') { vs[i] += 32; } + if(substring[i][7] == '1') { vs[i] += 16; } + if(substring[i][8] == '1') { vs[i] += 8; } + if(substring[i][9] == '1') { vs[i] += 4; } + if(substring[i][10] == '1') { vs[i] += 2; } + if(substring[i][11] == '1') { vs[i] += 1; } + } + + for(i = 0; i < data_chars; i++) { + if(vs[i] <= 347) { group[i] = 1; } + if((vs[i] >= 348) && (vs[i] <= 1387)) { group[i] = 2; } + if((vs[i] >= 1388) && (vs[i] <= 2947)) { group[i] = 3; } + if((vs[i] >= 2948) && (vs[i] <= 3987)) { group[i] = 4; } + if(vs[i] >= 3988) { group[i] = 5; } + v_odd[i] = (vs[i] - g_sum_exp[group[i] - 1]) / t_even_exp[group[i] - 1]; + v_even[i] = (vs[i] - g_sum_exp[group[i] - 1]) % t_even_exp[group[i] - 1]; + + getRSSwidths(v_odd[i], modules_odd_exp[group[i] - 1], 4, widest_odd_exp[group[i] - 1], 0); + char_widths[i][0] = widths[0]; + char_widths[i][2] = widths[1]; + char_widths[i][4] = widths[2]; + char_widths[i][6] = widths[3]; + getRSSwidths(v_even[i], modules_even_exp[group[i] - 1], 4, widest_even_exp[group[i] - 1], 1); + char_widths[i][1] = widths[0]; + char_widths[i][3] = widths[1]; + char_widths[i][5] = widths[2]; + char_widths[i][7] = widths[3]; + } + + checksum = 0; + for(i = 0; i < data_chars; i++) { + row = weight_rows[(((data_chars - 3) / 2) * 21) + i]; + for(j = 0; j < 8; j++) { + checksum += (char_widths[i][j] * checksum_weight_exp[(row * 8) + j]); + + } + } + + checksum; + check_char = (211 * ((data_chars + 1) - 4)) + (checksum % 211); + + if(check_char <= 347) { c_group = 1; } + if((check_char >= 348) && (check_char <= 1387)) { c_group = 2; } + if((check_char >= 1388) && (check_char <= 2947)) { c_group = 3; } + if((check_char >= 2948) && (check_char <= 3987)) { c_group = 4; } + if(check_char >= 3988) { c_group = 5; } + + c_odd = (check_char - g_sum_exp[c_group - 1]) / t_even_exp[c_group - 1]; + c_even = (check_char - g_sum_exp[c_group - 1]) % t_even_exp[c_group - 1]; + + getRSSwidths(c_odd, modules_odd_exp[c_group - 1], 4, widest_odd_exp[c_group - 1], 0); + check_widths[0] = widths[0]; + check_widths[2] = widths[1]; + check_widths[4] = widths[2]; + check_widths[6] = widths[3]; + getRSSwidths(c_even, modules_even_exp[c_group - 1], 4, widest_even_exp[c_group - 1], 1); + check_widths[1] = widths[0]; + check_widths[3] = widths[1]; + check_widths[5] = widths[2]; + check_widths[7] = widths[3]; + + /* Initialise element array */ + pattern_width = ((((data_chars + 1) / 2) + ((data_chars + 1) % 2)) * 5) + ((data_chars + 1) * 8) + 4; + for(i = 0; i < pattern_width; i++) { + elements[i] = 0; + } + + elements[0] = 1; + elements[1] = 1; + elements[pattern_width - 2] = 1; + elements[pattern_width - 1] = 1; + + /* Put finder patterns in element array */ + for(i = 0; i < (((data_chars + 1) / 2) + ((data_chars + 1) % 2)); i++) { + k = ((((((data_chars + 1) - 2) / 2) + ((data_chars + 1) % 2)) - 1) * 11) + i; + for(j = 0; j < 5; j++) { + elements[(21 * i) + j + 10] = finder_pattern_exp[((finder_sequence[k] - 1) * 5) + j]; + } + } + + /* Put check character in element array */ + for(i = 0; i < 8; i++) { + elements[i + 2] = check_widths[i]; + } + + /* Put forward reading data characters in element array */ + for(i = 1; i < data_chars; i += 2) { + for(j = 0; j < 8; j++) { + elements[(((i - 1) / 2) * 21) + 23 + j] = char_widths[i][j]; + } + } + + /* Put reversed data characters in element array */ + for(i = 0; i < data_chars; i += 2) { + for(j = 0; j < 8; j++) { + elements[((i / 2) * 21) + 15 + j] = char_widths[i][7 - j]; + } + } + + if((symbol->symbology == BARCODE_RSS_EXP) || (symbol->symbology == BARCODE_RSS_EXP_CC)) { + /* Copy elements into symbol */ + writer = 0; + latch = '0'; + for(i = 0; i < pattern_width; i++) { + for(j = 0; j < elements[i]; j++) { + symbol->encoded_data[symbol->rows][writer] = latch; + writer++; + } + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } + if(symbol->width < writer) { symbol->width = writer; } + symbol->rows = symbol->rows + 1; + if(symbol->symbology == BARCODE_RSS_EXP_CC) { + for(j = 4; j < (symbol->width - 4); j++) { + if(symbol->encoded_data[separator_row + 1][j] == '1') { + symbol->encoded_data[separator_row][j] = '0'; + } else { + symbol->encoded_data[separator_row][j] = '1'; + } + } + /* finder bar adjustment */ + for(j = 0; j < (writer / 49); j++) { + k = (49 * j) + 18; + for(i = 0; i < 15; i++) { + if((symbol->encoded_data[separator_row + 1][i + k - 1] == '0') && + (symbol->encoded_data[separator_row + 1][i + k] == '0') && + (symbol->encoded_data[separator_row][i + k - 1] == '1')) { + symbol->encoded_data[separator_row][i + k] = '0'; + } + } + } + } + + /* Add human readable text */ + for(i = 0; i <= strlen(source); i++) { + if((source[i] != '[') && (source[i] != ']')) { + symbol->text[i] = source[i]; + } else { + if(source[i] == '[') { + symbol->text[i] = '('; + } + if(source[i] == ']') { + symbol->text[i] = ')'; + } + } + } + + } else { + /* RSS Expanded Stacked */ + + codeblocks = (data_chars + 1) / 2; + + if((symbol->option_2 < 1) || (symbol->option_2 > 10)) { + symbol->option_2 = 2; + } + if((symbol->option_1 == 2) && (symbol->option_2 == 1)) { + /* "There shall be a minimum of four symbol characters in the + first row of an RSS Expanded Stacked symbol when it is the linear + component of an EAN.UCC Composite symbol." */ + symbol->option_2 = 2; + } + + stack_rows = codeblocks / symbol->option_2; + if(codeblocks % symbol->option_2 > 0) { + stack_rows++; + } + + current_block = 0; + for(current_row = 1; current_row <= stack_rows; current_row++) { + for(i = 0; i < 235; i++) { + sub_elements[i] = 0; + } + special_case_row = 0; + + /* Row Start */ + sub_elements[0] = 1; + sub_elements[1] = 1; + elements_in_sub = 2; + + /* Row Data */ + reader = 0; + do { + if(((symbol->option_2 % 2 == 1) || (current_row % 2 == 1)) || + ((current_row == stack_rows) && (codeblocks != (current_row * symbol->option_2)) && + ((((current_row * symbol->option_2) - codeblocks) % 2) == 1) )) { + /* left to right */ + left_to_right = 1; + i = 2 + (current_block * 21); + for(j = 0; j < 21; j++) { + sub_elements[j + (reader * 21) + 2] = elements[i + j]; + elements_in_sub++; + } + } else { + /* right to left */ + left_to_right = 0; + if((current_row * symbol->option_2) < codeblocks) { + /* a full row */ + i = 2 + (((current_row * symbol->option_2) - reader - 1) * 21); + for(j = 0; j < 21; j++) { + sub_elements[(20 - j) + (reader * 21) + 2] = elements[i + j]; + elements_in_sub++; + } + } else { + /* a partial row */ + k = ((current_row * symbol->option_2) - codeblocks); + l = (current_row * symbol->option_2) - reader - 1; + i = 2 + ((l - k) * 21); + for(j = 0; j < 21; j++) { + sub_elements[(20 - j) + (reader * 21) + 2] = elements[i + j]; + elements_in_sub++; + } + } + } + reader++; + current_block++; + } while ((reader < symbol->option_2) && (current_block < codeblocks)); + + /* Row Stop */ + sub_elements[elements_in_sub] = 1; + sub_elements[elements_in_sub + 1] = 1; + elements_in_sub += 2; + + if(current_row % 2 == 1) { + latch = '0'; + } else { + latch = '1'; + } + + if ((current_row == stack_rows) && (codeblocks != (current_row * symbol->option_2)) && + ((((current_row * symbol->option_2) - codeblocks) % 2) == 1) ) { + /* Special case bottom row */ + special_case_row = 1; + sub_elements[0] = 2; + latch = '0'; + } + + writer = 0; + for(i = 0; i < elements_in_sub; i++) { + for(j = 0; j < sub_elements[i]; j++) { + symbol->encoded_data[symbol->rows][writer] = latch; + writer++; + } + if(latch == '1') { + latch = '0'; + } else { + latch = '1'; + } + } + if(symbol->width < writer) { symbol->width = writer; } + + if(current_row != 1) { + /* middle separator pattern (above current row) */ + for(j = 5; j < (49 * symbol->option_2); j += 2) { + symbol->encoded_data[symbol->rows - 2][j] = '1'; + } + symbol->row_height[symbol->rows - 2] = 1; + /* bottom separator pattern (above current row) */ + for(j = 4; j < (writer - 4); j++) { + if(symbol->encoded_data[symbol->rows][j] == '1') { + symbol->encoded_data[symbol->rows - 1][j] = '0'; + } else { + symbol->encoded_data[symbol->rows - 1][j] = '1'; + } + } + symbol->row_height[symbol->rows - 1] = 1; + /* finder bar adjustment */ + for(j = 0; j < reader; j++) { + if(special_case_row == 0) { + k = (49 * j) + 18; + } else { + k = (49 * j) + 19; + } + if(left_to_right) { + for(i = 0; i < 15; i++) { + if((symbol->encoded_data[symbol->rows][i + k - 1] == '0') && + (symbol->encoded_data[symbol->rows][i + k] == '0') && + (symbol->encoded_data[symbol->rows - 1][i + k - 1] == '1')) { + symbol->encoded_data[symbol->rows - 1][i + k] = '0'; + } + } + } else { + for(i = 14; i >= 0; i--) { + if((symbol->encoded_data[symbol->rows][i + k + 1] == '0') && + (symbol->encoded_data[symbol->rows][i + k] == '0') && + (symbol->encoded_data[symbol->rows - 1][i + k + 1] == '1')) { + symbol->encoded_data[symbol->rows - 1][i + k] = '0'; + } + } + } + } + } + + if(current_row != stack_rows) { + /* top separator pattern (below current row) */ + for(j = 4; j < (writer - 4); j++) { + if(symbol->encoded_data[symbol->rows][j] == '1') { + symbol->encoded_data[symbol->rows + 1][j] = '0'; + } else { + symbol->encoded_data[symbol->rows + 1][j] = '1'; + } + } + symbol->row_height[symbol->rows + 1] = 1; + /* finder bar adjustment */ + for(j = 0; j < reader; j++) { + k = (49 * j) + 18; + if(left_to_right) { + for(i = 0; i < 15; i++) { + if((symbol->encoded_data[symbol->rows][i + k - 1] == '0') && + (symbol->encoded_data[symbol->rows][i + k] == '0') && + (symbol->encoded_data[symbol->rows + 1][i + k - 1] == '1')) { + symbol->encoded_data[symbol->rows + 1][i + k] = '0'; + } + } + } else{ + for(i = 14; i >= 0; i--) { + if((symbol->encoded_data[symbol->rows][i + k + 1] == '0') && + (symbol->encoded_data[symbol->rows][i + k] == '0') && + (symbol->encoded_data[symbol->rows + 1][i + k + 1] == '1')) { + symbol->encoded_data[symbol->rows + 1][i + k] = '0'; + } + } + } + } + } + + symbol->rows = symbol->rows + 4; + } + symbol->rows = symbol->rows - 3; + if(symbol->symbology == BARCODE_RSS_EXPSTACK_CC) { + for(j = 4; j < (symbol->width - 4); j++) { + if(symbol->encoded_data[separator_row + 1][j] == '1') { + symbol->encoded_data[separator_row][j] = '0'; + } else { + symbol->encoded_data[separator_row][j] = '1'; + } + } + /* finder bar adjustment */ + for(j = 0; j < reader; j++) { + k = (49 * j) + 18; + for(i = 0; i < 15; i++) { + if((symbol->encoded_data[separator_row + 1][i + k - 1] == '0') && + (symbol->encoded_data[separator_row + 1][i + k] == '0') && + (symbol->encoded_data[separator_row][i + k - 1] == '1')) { + symbol->encoded_data[separator_row][i + k] = '0'; + } + } + } + } + + } + + return 0; +} diff --git a/backend/rss.h b/backend/rss.h new file mode 100644 index 00000000..919bf53e --- /dev/null +++ b/backend/rss.h @@ -0,0 +1,225 @@ +/* rss.h - Data tables for Reduced Space Symbology */ + +/* + libzint - the open source barcode library + Copyright (C) 2007 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#define NUMERIC 110 +#define ALPHA 97 +#define ISOIEC 105 +#define INVALID_CHAR 100 +#define ANY_ENC 120 +#define ALPHA_OR_ISO 121 + +/* RSS-14 Tables */ +static int g_sum_table[9] = { 0, 161, 961, 2015, 2715, 0, 336, 1036, 1516}; +static int t_table[9] = { 1, 10, 34, 70, 126, 4, 20, 48, 81}; +static int modules_odd[9] = { 12, 10, 8, 6, 4, 5, 7, 9, 11 }; +static int modules_even[9] = { 4, 6, 8, 10, 12, 10, 8, 6, 4 }; +static int widest_odd[9] = { 8, 6, 4, 3, 1, 2, 4, 6, 8 }; +static int widest_even[9] = { 1, 3, 5, 6, 8, 7, 5, 3, 1 }; +static int widths[8]; +static int finder_pattern[45] = { + 3, 8, 2, 1, 1, + 3, 5, 5, 1, 1, + 3, 3, 7, 1, 1, + 3, 1, 9, 1, 1, + 2, 7, 4, 1, 1, + 2, 5, 6, 1, 1, + 2, 3, 8, 1, 1, + 1, 5, 7, 1, 1, + 1, 3, 9, 1, 1 +}; +static int checksum_weight[32] = { /* Table 5 */ + 1, 3, 9, 27, 2, 6, 18, 54, + 4, 12, 36, 29, 8, 24, 72, 58, + 16, 48, 65, 37, 32, 17, 51, 74, + 64, 34, 23, 69, 49, 68, 46, 59 +}; + +/* RSS Limited Tables */ +static int t_even_ltd[7] = { 28, 728, 6454, 203, 2408, 1, 16632 }; +static int modules_odd_ltd[7] = { 17, 13, 9, 15, 11, 19, 7 }; +static int modules_even_ltd[7] = { 9, 13, 17, 11, 15, 7, 19 }; +static int widest_odd_ltd[7] = { 6, 5, 3, 5, 4, 8, 1 }; +static int widest_even_ltd[7] = { 3, 4, 6, 4, 5, 1, 8 }; +static int checksum_weight_ltd[28] = { /* Table 7 */ + 1, 3, 9, 27, 81, 65, 17, 51, 64, 14, 42, 37, 22, 66, + 20, 60, 2, 6, 18, 54, 73, 41, 34, 13, 39, 28, 84, 74 +}; +static int finder_pattern_ltd[1232] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 3, 2, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 1, + 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 1, + 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, + 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 3, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, + 1, 2, 1, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1, + 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, + 1, 3, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1, + 1, 1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, + 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, + 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, + 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, 1, + 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3, 1, 1, + 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 2, 1, 1, + 1, 1, 1, 1, 2, 1, 1, 1, 1, 3, 2, 1, 1, 1, + 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 1, + 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, + 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, + 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, + 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 1, + 1, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, + 1, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, + 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, + 2, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 1, 1, 1, + 2, 1, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, + 2, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, + 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1 +}; + +/* RSS Expanded Tables */ +static int g_sum_exp[5] = { 0, 348, 1388, 2948, 3988 }; +static int t_even_exp[5] = { 4, 20, 52, 104, 204 }; +static int modules_odd_exp[5] = { 12, 10, 8, 6, 4 }; +static int modules_even_exp[5] = { 5, 7, 9, 11, 13 }; +static int widest_odd_exp[5] = { 7, 5, 4, 3, 1 }; +static int widest_even_exp[5] = { 2, 4, 5, 6, 8 }; +static int checksum_weight_exp[184] = { /* Table 14 */ + 1, 3, 9, 27, 81, 32, 96, 77, + 20, 60, 180, 118, 143, 7, 21, 63, + 189, 145, 13, 39, 117, 140, 209, 205, + 193, 157, 49, 147, 19, 57, 171, 91, + 62, 186, 136, 197, 169, 85, 44, 132, + 185, 133, 188, 142, 4, 12, 36, 108, + 113, 128, 173, 97, 80, 29, 87, 50, + 150, 28, 84, 41, 123, 158, 52, 156, + 46, 138, 203, 187, 139, 206, 196, 166, + 76, 17, 51, 153, 37, 111, 122, 155, + 43, 129, 176, 106, 107, 110, 119, 146, + 16, 48, 144, 10, 30, 90, 59, 177, + 109, 166, 137, 200, 178, 112, 125, 164, + 70, 210, 208, 202, 184, 130, 179, 115, + 134, 191, 151, 31, 93, 68, 204, 190, + 148, 22, 66, 198, 172, 94, 71, 2, + 6, 18, 54, 162, 64, 192, 154, 40, + 120, 149, 25, 75, 14, 42, 126, 167, + 79, 26, 78, 23, 69, 207, 199, 175, + 103, 98, 83, 38, 114, 131, 182, 124, + 161, 61, 183, 127, 170, 88, 53, 159, + 55, 165, 73, 8, 24, 72, 5, 15, + 45, 135, 194, 160, 58, 174, 100, 89 +}; +static int finder_pattern_exp[60] = { /* Table 15 */ + 1, 8, 4, 1, 1, + 1, 1, 4, 8, 1, + 3, 6, 4, 1, 1, + 1, 1, 4, 6, 3, + 3, 4, 6, 1, 1, + 1, 1, 6, 4, 3, + 3, 2, 8, 1, 1, + 1, 1, 8, 2, 3, + 2, 6, 5, 1, 1, + 1, 1, 5, 6, 2, + 2, 2, 9, 1, 1, + 1, 1, 9, 2, 2 +}; +static int finder_sequence[198] = { /* Table 16 */ + 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 6, 3, 8, 0, 0, 0, 0, 0, 0, 0, + 1, 10, 3, 8, 5, 0, 0, 0, 0, 0, 0, + 1, 10, 3, 8, 7, 12, 0, 0, 0, 0, 0, + 1, 10, 3, 8, 9, 12, 11, 0, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 10, 9, 0, 0, + 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 0, + 1, 2, 3, 4, 5, 8, 7, 10, 9, 12, 11 +}; +static int weight_rows[210] = { + 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5, 6, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 10, 3, 4, 13, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 18, 3, 4, 13, 14, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 18, 3, 4, 13, 14, 11, 12, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17, 18, 3, 4, 13, 14, 15, 16, 21, 22, 19, 20, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 17, 18, 15, 16, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 17, 18, 19, 20, 21, 22, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 13, 14, 11, 12, 17, 18, 15, 16, 21, 22, 19, 20 +}; diff --git a/backend/telepen.c b/backend/telepen.c new file mode 100644 index 00000000..35d0278b --- /dev/null +++ b/backend/telepen.c @@ -0,0 +1,155 @@ +/* telepen.c - Handles Telepen and Telepen numeric */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include "common.h" + +static char *TeleTable[128] = { "1111111111111111", "1131313111", "33313111", "1111313131", + "3111313111", "11333131", "13133131", "111111313111", "31333111", "1131113131", "33113131", + "1111333111", "3111113131", "1113133111", "1311133111", "111111113131", "3131113111", + "11313331", "333331", "111131113111", "31113331", "1133113111", "1313113111", "1111113331", + "31131331", "113111113111", "3311113111", "1111131331", "311111113111", "1113111331", + "1311111331", "11111111113111", "31313311", "1131311131", "33311131", "1111313311", + "3111311131", "11333311", "13133311", "111111311131", "31331131", "1131113311", "33113311", + "1111331131", "3111113311", "1113131131", "1311131131", "111111113311", "3131111131", + "1131131311", "33131311", "111131111131", "3111131311", "1133111131", "1313111131", + "111111131311", "3113111311", "113111111131", "3311111131", "111113111311", "311111111131", + "111311111311", "131111111311", "11111111111131", "3131311111", "11313133", "333133", + "111131311111", "31113133", "1133311111", "1313311111", "1111113133", "313333", + "113111311111", "3311311111", "11113333", "311111311111", "11131333", "13111333", + "11111111311111", "31311133", "1131331111", "33331111", "1111311133", "3111331111", + "11331133", "13131133", "111111331111", "3113131111", "1131111133", "33111133", + "111113131111", "3111111133", "111311131111", "131111131111", "111111111133", "31311313", + "113131111111", "3331111111", "1111311313", "311131111111", "11331313", "13131313", + "11111131111111", "3133111111", "1131111313", "33111313", "111133111111", "3111111313", + "111313111111", "131113111111", "111111111313", "313111111111", "1131131113", "33131113", + "11113111111111", "3111131113", "113311111111", "131311111111", "111111131113", "3113111113", + "11311111111111", "331111111111", "111113111113", "31111111111111", "111311111113", + "131111111113"}; + +int telepen(struct zint_symbol *symbol, unsigned char source[]) +{ + unsigned int i, count, check_digit; + int ascii_value; + int errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + count = 0; + + if(strlen(source) > 30) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + + for(i = 0; i < strlen(source); i++) { + if(source[i] > 127) { + /* Cannot encode extended ASCII */ + strcpy(symbol->errtxt, "error: invalid characters in input data"); + return ERROR_INVALID_DATA; + } + } + + /* Start character */ + concat(dest, TeleTable['_']); + + for (i=0; i < strlen(source); i++) + { + ascii_value = source[i]; + concat(dest, TeleTable[ascii_value]); + count += source[i]; + } + + check_digit = 127 - (count % 127); + concat(dest, TeleTable[check_digit]); + + /* Stop character */ + concat(dest, TeleTable['z']); + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + +int telepen_num(struct zint_symbol *symbol, unsigned char source[]) +{ + unsigned int i, count, check_digit, glyph; + int errno; + char dest[1000]; + + errno = 0; + strcpy(dest, ""); + + count = 0; + + if(strlen(source) > 60) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + errno = is_sane(NESET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + + /* Add a leading zero if required */ + if ((strlen(source)%2) != 0) + { + unsigned int length; + char temp[200]; + + length = strlen(source); + + strcpy(temp, source); + source[0] = '0'; + + for(i = 0; i <= length; i++) + { + source[i + 1] = temp[i]; + } + } + + /* Start character */ + concat(dest, TeleTable['_']); + + for (i=0; i < strlen(source); i+=2) + { + glyph = (10 * ctoi(source[i])) + ctoi(source[i + 1]); + glyph += 27; + concat(dest, TeleTable[glyph]); + count += glyph; + } + + check_digit = 127 - (count % 127); + concat(dest, TeleTable[check_digit]); + + /* Stop character */ + concat(dest, TeleTable['z']); + + expand(symbol, dest); + strcpy(symbol->text, source); + return errno; +} + diff --git a/backend/upcean.c b/backend/upcean.c new file mode 100644 index 00000000..91448c6f --- /dev/null +++ b/backend/upcean.c @@ -0,0 +1,691 @@ +/* upcean.c - Handles UPC, EAN and ISBN + + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#define NASET "0123456789+" +#define EAN2 102 +#define EAN5 105 + +#include +#include +#include +#include "common.h" + +/* UPC and EAN tables checked against EN 797:1996 */ + +static char *UPCParity0[10] = {"BBBAAA", "BBABAA", "BBAABA", "BBAAAB", "BABBAA", "BAABBA", "BAAABB", + "BABABA", "BABAAB", "BAABAB"}; /* Number set for UPC-E symbol (EN Table 4) */ +static char *UPCParity1[10] = {"AAABBB", "AABABB", "AABBAB", "AABBBA", "ABAABB", "ABBAAB", "ABBBAA", + "ABABAB", "ABABBA", "ABBABA"}; /* Not covered by BS EN 797:1995 */ +static char *EAN2Parity[4] = {"AA", "AB", "BA", "BB"}; /* Number sets for 2-digit add-on (EN Table 6) */ +static char *EAN5Parity[10] = {"BBAAA", "BABAA", "BAABA", "BAAAB", "ABBAA", "AABBA", "AAABB", "ABABA", + "ABAAB", "AABAB"}; /* Number set for 5-digit add-on (EN Table 7) */ +static char *EAN13Parity[10] = {"AAAAA", "ABABB", "ABBAB", "ABBBA", "BAABB", "BBAAB", "BBBAA", "BABAB", + "BABBA", "BBABA"}; /* Left hand of the EAN-13 symbol (EN Table 3) */ +static char *EANsetA[10] = {"3211", "2221", "2122", "1411", "1132", "1231", "1114", "1312", "1213", + "3112"}; /* Representation set A and C (EN Table 1) */ +static char *EANsetB[10] = {"1123", "1222", "2212", "1141", "2311", "1321", "4111", "2131", "3121", + "2113"}; /* Representation set B (EN Table 1) */ + +char upc_check(unsigned char source[]) +{ /* Calculate the correct check digit for a UPC barcode */ + unsigned int i, count, check_digit; + + count = 0; + + for (i = 0; i < strlen(source); i++) + { + count += ctoi(source[i]); + + if ((i%2) == 0) + { + count += 2 * (ctoi(source[i])); + } + } + + check_digit = 10 - (count%10); + if (check_digit == 10) { check_digit = 0; } + return itoc(check_digit); +} + +void upca_draw(unsigned char source[], char dest[]) +{ /* UPC A is usually used for 12 digit numbers, but this function takes a source of any length */ + unsigned int i, half_way; + + half_way = strlen(source) / 2; + + /* start character */ + concat (dest, "111"); + + for(i = 0; i <= strlen(source); i++) + { + if (i == half_way) + { + /* middle character - separates manufacturer no. from product no. */ + /* also inverts right hand characters */ + concat(dest, "11111"); + } + + lookup(NESET, EANsetA, source[i], dest); + } + + /* stop character */ + concat (dest, "111"); +} + +void upca(struct zint_symbol *symbol, unsigned char source[], char dest[]) +{ /* Make a UPC A barcode when we haven't been given the check digit */ + int length; + + length = strlen(source); + source[length] = upc_check(source); + source[length + 1] = '\0'; + upca_draw(source, dest); + strcpy(symbol->text, source); +} + +void upce(struct zint_symbol *symbol, unsigned char source[], char dest[]) +{ /* UPC E is a zero-compressed version of UPC A */ + unsigned int i, num_system; + char emode, equivalent[12], check_digit, parity[8], temp[8]; + char hrt[8]; + + /* Two number systems can be used - system 0 and system 1 */ + if(strlen(source) == 7) { + switch(source[0]) { + case '0': num_system = 0; break; + case '1': num_system = 1; break; + default: num_system = 0; source[0] = '0'; break; + } + strcpy(temp, source); + strcpy(hrt, source); + for(i = 1; i <= 7; i++) { + source[i - 1] = temp[i]; + } + } + else { + num_system = 0; + hrt[0] = '0'; + hrt[1] = '\0'; + concat(hrt, source); + } + + /* Expand the zero-compressed UPCE code to make a UPCA equivalent (EN Table 5) */ + emode = source[5]; + for(i = 0; i < 11; i++) { + equivalent[i] = '0'; + } + equivalent[1] = source[0]; + equivalent[2] = source[1]; + equivalent[11] = '\0'; + + switch(emode) + { + case '0': + case '1': + case '2': + equivalent[3] = emode; + equivalent[8] = source[2]; + equivalent[9] = source[3]; + equivalent[10] = source[4]; + break; + case '3': + equivalent[3] = source[2]; + equivalent[9] = source[3]; + equivalent[10] = source[4]; + if(((source[2] == '0') || (source[2] == '1')) || (source[2] == '2')) { + /* Note 1 - "X3 shall not be equal to 0, 1 or 2" */ + strcpy(symbol->errtxt, "warning: invalid UPC-E data"); + } + break; + case '4': + equivalent[3] = source[2]; + equivalent[4] = source[3]; + equivalent[10] = source[4]; + if(source[3] == '0') { + /* Note 2 - "X4 shall not be equal to 0" */ + strcpy(symbol->errtxt, "warning: invalid UPC-E data"); + } + break; + case '5': + case '6': + case '7': + case '8': + case '9': + equivalent[3] = source[2]; + equivalent[4] = source[3]; + equivalent[5] = source[4]; + equivalent[10] = emode; + if(source[4] == '0') { + /* Note 3 - "X5 shall not be equal to 0" */ + strcpy(symbol->errtxt, "warning: invalid UPC-E data"); + } + break; + } + + /* Get the check digit from the expanded UPCA code */ + + check_digit = upc_check(equivalent); + + /* Use the number system and check digit information to choose a parity scheme */ + if(num_system == 1) { + strcpy(parity, UPCParity1[ctoi(check_digit)]); + } else { + strcpy(parity, UPCParity0[ctoi(check_digit)]); + } + + /* Take all this information and make the barcode pattern */ + + /* start character */ + concat (dest, "111"); + + for(i = 0; i <= strlen(source); i++) { + switch(parity[i]) { + case 'A': lookup(NESET, EANsetA, source[i], dest); break; + case 'B': lookup(NESET, EANsetB, source[i], dest); break; + } + } + + /* stop character */ + concat (dest, "111111"); + + hrt[7] = check_digit; + hrt[8] = '\0'; + strcpy(symbol->text, hrt); +} + + +void add_on(unsigned char source[], char dest[], int mode) +{ /* EAN-2 and EAN-5 add-on codes */ + char parity[6]; + unsigned int i, code_type; + + /* If an add-on then append with space */ + if (mode != 0) + { + concat(dest, "9"); + } + + /* Start character */ + concat (dest, "112"); + + /* Determine EAN2 or EAN5 add-on */ + if(strlen(source) == 2) + { + code_type = EAN2; + } + else + { + code_type = EAN5; + } + + /* Calculate parity for EAN2 */ + if(code_type == EAN2) + { + int code_value, parity_bit; + + code_value = (10 * ctoi(source[0])) + ctoi(source[1]); + parity_bit = code_value%4; + strcpy(parity, EAN2Parity[parity_bit]); + } + + if(code_type == EAN5) + { + int values[6], parity_sum, parity_bit; + + for(i = 0; i < 6; i++) + { + values[i] = ctoi(source[i]); + } + + parity_sum = (3 * (values[0] + values[2] + values[4])); + parity_sum += (9 * (values[1] + values[3])); + + parity_bit = parity_sum%10; + strcpy(parity, EAN5Parity[parity_bit]); + } + + for(i = 0; i < strlen(source); i++) + { + switch(parity[i]) { + case 'A': lookup(NESET, EANsetA, source[i], dest); break; + case 'B': lookup(NESET, EANsetB, source[i], dest); break; + } + + /* Glyph separator */ + if(i != (strlen(source) - 1)) + { + concat (dest, "11"); + } + } +} + + +/* ************************ EAN-13 ****************** */ + +char ean_check(unsigned char source[]) +{ /* Calculate the correct check digit for a EAN-13 barcode */ + int i; + unsigned int h, count, check_digit; + + count = 0; + + h = strlen(source); + for (i = h - 1; i >= 0; i--) + { + count += ctoi(source[i]); + + if (!((i%2) == 0)) + { + count += 2 * ctoi(source[i]); + } + } + check_digit = 10 - (count%10); + if (check_digit == 10) { check_digit = 0; } + return itoc(check_digit); +} + +void ean13(struct zint_symbol *symbol, unsigned char source[], char dest[]) +{ + unsigned int length, i, half_way; + char parity[6]; + + strcpy(parity, ""); + + /* Add the appropriate check digit */ + length = strlen(source); + source[length] = ean_check(source); + source[length + 1] = '\0'; + + /* Get parity for first half of the symbol */ + lookup(NASET, EAN13Parity, source[0], parity); + + /* Now get on with the cipher */ + half_way = 7; + + /* start character */ + concat (dest, "111"); + + for(i = 1; i <= strlen(source); i++) + { + if (i == half_way) + { + /* middle character - separates manufacturer no. from product no. */ + /* also inverses right hand characters */ + concat (dest, "11111"); + } + + if(((i > 1) && (i < 7)) && (parity[i - 2] == 'B')) + { + lookup(NESET, EANsetB, source[i], dest); + } + else + { + lookup(NESET, EANsetA, source[i], dest); + } + } + + /* stop character */ + concat (dest, "111"); + + strcpy(symbol->text, source); +} + +void ean8(struct zint_symbol *symbol, unsigned char source[], char dest[]) +{ /* Make an EAN-8 barcode when we haven't been given the check digit */ + /* EAN-8 is basically the same as UPC-A but with fewer digits */ + int length; + + length = strlen(source); + source[length] = upc_check(source); + source[length + 1] = '\0'; + upca_draw(source, dest); + strcpy(symbol->text, source); +} + +char isbn13_check(unsigned char source[]) /* For ISBN(13) only */ +{ + unsigned int i, weight, sum, check; + + sum = 0; + weight = 1; + + for(i = 0; i < (strlen(source) - 1); i++) + { + sum += ctoi(source[i]) * weight; + if(weight == 1) weight = 3; else weight = 1; + } + + check = sum % 10; + check = 10 - check; + return itoc(check); +} + +char isbn_check(unsigned char source[]) /* For ISBN(10) and SBN only */ +{ + unsigned int i, weight, sum, check; + + sum = 0; + weight = 1; + for(i = 0; i < (strlen(source) - 1); i++) + { + sum += ctoi(source[i]) * weight; + weight++; + } + + check = sum % 11; + return itoc(check); +} + +int isbn(struct zint_symbol *symbol, unsigned char source[], char dest[]) /* Make an EAN-13 barcode from an SBN or ISBN */ +{ + int i, errno; + char check_digit; + + errno = 0; + + to_upper(source); + errno = is_sane("0123456789X", source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in input"); + return errno; + } + + /* Input must be 9, 10 or 13 characters */ + if(((strlen(source) < 9) || (strlen(source) > 13)) || ((strlen(source) > 10) && (strlen(source) < 13))) + { + strcpy(symbol->errtxt, "error: input wrong length"); + return ERROR_TOO_LONG; + } + + if(strlen(source) == 13) /* Using 13 character ISBN */ + { + if(!(((source[0] == '9') && (source[1] == '7')) && + ((source[2] == '8') || (source[2] == '9')))) + { + strcpy(symbol->errtxt, "error: invalid ISBN"); + return ERROR_INVALID_DATA; + } + + check_digit = isbn13_check(source); + if (source[strlen(source) - 1] != check_digit) + { + strcpy(symbol->errtxt, "error: incorrect ISBN check"); + return ERROR_INVALID_CHECK; + } + source[12] = '\0'; + + ean13(symbol, source, dest); + } + + if(strlen(source) == 10) /* Using 10 digit ISBN */ + { + check_digit = isbn_check(source); + if(check_digit != source[strlen(source) - 1]) + { + strcpy(symbol->errtxt, "error: incorrect ISBN check"); + return ERROR_INVALID_CHECK; + } + for(i = 13; i > 0; i--) + { + source[i] = source[i - 3]; + } + source[0] = '9'; + source[1] = '7'; + source[2] = '8'; + source[12] = '\0'; + + ean13(symbol, source, dest); + } + + if(strlen(source) == 9) /* Using 9 digit SBN */ + { + /* Add leading zero */ + for(i = 10; i > 0; i--) + { + source[i] = source[i - 1]; + } + source[0] = '0'; + + /* Verify check digit */ + check_digit = isbn_check(source); + if(check_digit != source[strlen(source) - 1]) + { + strcpy(symbol->errtxt, "error: incorrect SBN check"); + return ERROR_INVALID_CHECK; + } + + /* Convert to EAN-13 number */ + for(i = 13; i > 0; i--) + { + source[i] = source[i - 3]; + } + source[0] = '9'; + source[1] = '7'; + source[2] = '8'; + source[12] = '\0'; + + ean13(symbol, source, dest); + } + + return errno; +} + +int eanx(struct zint_symbol *symbol, unsigned char source[]) +{ + /* splits string to parts before and after '+' parts */ + char first_part[20], second_part[20], dest[1000]; + unsigned int latch, reader, writer, with_addon; + strcpy(first_part, ""); + strcpy(second_part, ""); + int errno, i; + + errno = 0; + strcpy(dest, ""); + + with_addon = FALSE; + latch = FALSE; + writer = 0; + + if(strlen(source) > 19) { + strcpy(symbol->errtxt, "error: input too long"); + return ERROR_TOO_LONG; + } + if(symbol->symbology != BARCODE_ISBNX) { + /* ISBN has it's own checking routine */ + errno = is_sane(NASET, source); + if(errno == ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "error: invalid characters in data"); + return errno; + } + } + + for(reader = 0; reader <= strlen(source); reader++) + { + if(source[reader] == '+') { with_addon = TRUE; } + } + + reader = 0; + if(with_addon) { + do { + if(source[reader] == '+') { + first_part[writer] = '\0'; + latch = TRUE; + reader++; + writer = 0; + } + + if(latch) { + second_part[writer] = source[reader]; + reader++; + writer++; + } else { + first_part[writer] = source[reader]; + reader++; + writer++; + } + } while (reader <= strlen(source)); + } else { + strcpy(first_part, source); + } + + + switch(symbol->symbology) + { + case BARCODE_EANX: + switch(strlen(first_part)) + { + case 2: add_on(first_part, dest, 0); strcpy(symbol->text, first_part); break; + case 5: add_on(first_part, dest, 0); strcpy(symbol->text, first_part); break; + case 7: ean8(symbol, first_part, dest); break; + case 12: ean13(symbol, first_part, dest); break; + default: strcpy(symbol->errtxt, "error: invalid length input"); return ERROR_TOO_LONG; break; + } + break; + case BARCODE_EANX_CC: + switch(strlen(first_part)) + { /* Adds vertical separator bars according to ISO/IEC 24723 section 11.4 */ + case 7: symbol->encoded_data[symbol->rows][1] = '1'; + symbol->encoded_data[symbol->rows][67] = '1'; + symbol->encoded_data[symbol->rows + 1][0] = '1'; + symbol->encoded_data[symbol->rows + 1][68] = '1'; + symbol->encoded_data[symbol->rows + 2][1] = '1'; + symbol->encoded_data[symbol->rows + 2][67] = '1'; + symbol->row_height[symbol->rows] = 2; + symbol->row_height[symbol->rows + 1] = 2; + symbol->row_height[symbol->rows + 2] = 2; + symbol->rows += 3; + ean8(symbol, first_part, dest); break; + case 12:symbol->encoded_data[symbol->rows][1] = '1'; + symbol->encoded_data[symbol->rows][95] = '1'; + symbol->encoded_data[symbol->rows + 1][0] = '1'; + symbol->encoded_data[symbol->rows + 1][96] = '1'; + symbol->encoded_data[symbol->rows + 2][1] = '1'; + symbol->encoded_data[symbol->rows + 2][95] = '1'; + symbol->row_height[symbol->rows] = 2; + symbol->row_height[symbol->rows + 1] = 2; + symbol->row_height[symbol->rows + 2] = 2; + symbol->rows += 3; + ean13(symbol, first_part, dest); break; + default: strcpy(symbol->errtxt, "error: invalid length EAN input"); return ERROR_TOO_LONG; break; + } + break; + case BARCODE_UPCA: + if(strlen(first_part) == 11) { + upca(symbol, first_part, dest); + } else { + strcpy(symbol->errtxt, "error: input wrong length"); + return ERROR_TOO_LONG; + } + break; + case BARCODE_UPCA_CC: + if(strlen(first_part) == 11) { + symbol->encoded_data[symbol->rows][1] = '1'; + symbol->encoded_data[symbol->rows][95] = '1'; + symbol->encoded_data[symbol->rows + 1][0] = '1'; + symbol->encoded_data[symbol->rows + 1][96] = '1'; + symbol->encoded_data[symbol->rows + 2][1] = '1'; + symbol->encoded_data[symbol->rows + 2][95] = '1'; + symbol->row_height[symbol->rows] = 2; + symbol->row_height[symbol->rows + 1] = 2; + symbol->row_height[symbol->rows + 2] = 2; + symbol->rows += 3; + upca(symbol, first_part, dest); + } else { + strcpy(symbol->errtxt, "error: UPCA input wrong length"); + return ERROR_TOO_LONG; + } + break; + case BARCODE_UPCE: + if((strlen(first_part) >= 6) && (strlen(first_part) <= 7)) { + upce(symbol, first_part, dest); + } else { + strcpy(symbol->errtxt, "error: input wrong length"); + return ERROR_TOO_LONG; + } + break; + case BARCODE_UPCE_CC: + if((strlen(first_part) >= 6) && (strlen(first_part) <= 7)) { + symbol->encoded_data[symbol->rows][1] = '1'; + symbol->encoded_data[symbol->rows][51] = '1'; + symbol->encoded_data[symbol->rows + 1][0] = '1'; + symbol->encoded_data[symbol->rows + 1][52] = '1'; + symbol->encoded_data[symbol->rows + 2][1] = '1'; + symbol->encoded_data[symbol->rows + 2][51] = '1'; + symbol->row_height[symbol->rows] = 2; + symbol->row_height[symbol->rows + 1] = 2; + symbol->row_height[symbol->rows + 2] = 2; + symbol->rows += 3; + upce(symbol, first_part, dest); + } else { + strcpy(symbol->errtxt, "error: UPCE input wrong length"); + return ERROR_TOO_LONG; + } + break; + case BARCODE_ISBNX: + errno = isbn(symbol, first_part, dest); + if(errno > 4) { + return errno; + } + break; + } + switch(strlen(second_part)) + { + case 0: break; + case 2: + add_on(second_part, dest, 1); + concat(symbol->text, "+"); + concat(symbol->text, second_part); + break; + case 5: + add_on(second_part, dest, 1); + concat(symbol->text, "+"); + concat(symbol->text, second_part); + break; + default: + strcpy(symbol->errtxt, "error: invalid length input"); + return ERROR_TOO_LONG; + break; + } + + expand(symbol, dest); + + switch(symbol->symbology) { + case BARCODE_EANX_CC: + case BARCODE_UPCA_CC: + case BARCODE_UPCE_CC: + /* shift the symbol to the right one space to allow for separator bars */ + for(i = (symbol->width + 1); i >= 1; i--) { + symbol->encoded_data[symbol->rows - 1][i] = symbol->encoded_data[symbol->rows - 1][i - 1]; + } + symbol->encoded_data[symbol->rows - 1][0] = '0'; + symbol->width += 2; + break; + } + + + if((symbol->errtxt[0] == 'w') && (errno == 0)) { + errno = 1; /* flag UPC-E warnings */ + } + return errno; +} + + + + diff --git a/backend/zint.h b/backend/zint.h new file mode 100644 index 00000000..587a26b5 --- /dev/null +++ b/backend/zint.h @@ -0,0 +1,133 @@ +/* zint.h - definitions for libzint + + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#define VERSION "1.6.0" + +struct zint_symbol { + int symbology; + int height; + int whitespace_width; + int border_width; + int output_options; + char fgcolour[10]; + char bgcolour[10]; + char outfile[256]; + int option_1; + int option_2; + char text[100]; + int rows; + int width; + char primary[100]; + char encoded_data[155][1000]; + int row_height[155]; + char errtxt[100]; +}; + +#define BARCODE_CODE11 1 +#define BARCODE_C25MATRIX 2 +#define BARCODE_C25INTER 3 +#define BARCODE_C25IATA 4 +#define BARCODE_C25LOGIC 6 +#define BARCODE_C25IND 7 +#define BARCODE_CODE39 8 +#define BARCODE_EXCODE39 9 +#define BARCODE_EANX 13 +#define BARCODE_EAN128 16 +#define BARCODE_CODABAR 18 +#define BARCODE_CODE128 20 +#define BARCODE_DPLEIT 21 +#define BARCODE_DPIDENT 22 +#define BARCODE_CODE16K 23 +#define BARCODE_CODE93 25 +#define BARCODE_FLAT 28 +#define BARCODE_RSS14 29 +#define BARCODE_RSS_LTD 30 +#define BARCODE_RSS_EXP 31 +#define BARCODE_TELEPEN 32 +#define BARCODE_UPCA 34 +#define BARCODE_UPCE 37 +#define BARCODE_POSTNET 40 +#define BARCODE_MSI_PLESSEY 47 +#define BARCODE_FIM 49 +#define BARCODE_LOGMARS 50 +#define BARCODE_PHARMA 51 +#define BARCODE_PZN 52 +#define BARCODE_PHARMA_TWO 53 +#define BARCODE_PDF417 55 +#define BARCODE_PDF417TRUNC 56 +#define BARCODE_MAXICODE 57 +#define BARCODE_QRCODE 58 +#define BARCODE_CODE128B 60 +#define BARCODE_AUSPOST 63 +#define BARCODE_AUSREPLY 66 +#define BARCODE_AUSROUTE 67 +#define BARCODE_AUSREDIRECT 68 +#define BARCODE_ISBNX 69 +#define BARCODE_RM4SCC 70 +#define BARCODE_DATAMATRIX 71 +#define BARCODE_ITF14 72 +#define BARCODE_NVE18 75 +#define BARCODE_KOREAPOST 77 +#define BARCODE_RSS14STACK 79 +#define BARCODE_RSS14STACK_OMNI 80 +#define BARCODE_RSS_EXPSTACK 81 +#define BARCODE_PLANET 82 +#define BARCODE_MICROPDF417 84 +#define BARCODE_ONECODE 85 +#define BARCODE_PLESSEY 86 +#define BARCODE_TELEPEN_NUM 100 +#define BARCODE_MSI_10 101 +#define BARCODE_MSI_10_10 102 +#define BARCODE_MSI_11 103 +#define BARCODE_MSI_11_10 104 +#define BARCODE_CODE39_43 105 +#define BARCODE_EXCODE39_43 106 +#define BARCODE_AZTEC 107 +#define BARCODE_SUPER 108 +#define BARCODE_ULTRA 109 +#define BARCODE_EANX_CC 110 +#define BARCODE_EAN128_CC 111 +#define BARCODE_RSS14_CC 112 +#define BARCODE_RSS_LTD_CC 113 +#define BARCODE_RSS_EXP_CC 114 +#define BARCODE_UPCA_CC 115 +#define BARCODE_UPCE_CC 116 +#define BARCODE_RSS14STACK_CC 117 +#define BARCODE_RSS14_OMNI_CC 118 +#define BARCODE_RSS_EXPSTACK_CC 119 + +#define BARCODE_NO_ASCII 1 +#define BARCODE_BIND 2 +#define BARCODE_BOX 4 + +#define WARN_INVALID_OPTION 2 +#define ERROR_TOO_LONG 5 +#define ERROR_INVALID_DATA 6 +#define ERROR_INVALID_CHECK 7 +#define ERROR_INVALID_OPTION 8 +#define ERROR_ENCODING_PROBLEM 9 +#define ERROR_FILE_ACCESS 10 +#define ERROR_MEMORY 11 + +extern struct zint_symbol *ZBarcode_Create(); +extern int ZBarcode_Delete(struct zint_symbol *symbol); +extern int ZBarcode_Encode(struct zint_symbol *symbol, unsigned char *input); +extern int ZBarcode_Print(struct zint_symbol *symbol); +extern int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input); diff --git a/docs/appxa.html b/docs/appxa.html new file mode 100644 index 00000000..86a6a962 --- /dev/null +++ b/docs/appxa.html @@ -0,0 +1,1125 @@ + + + + + Character Encoding + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

A. Character Encoding

+

This section is intended as a quick reference to the character +sets used by Zint. All symbologies use standard ASCII input as shown +in section A.1, but some support extended character support as shown +in the subsequent section.

+

A.1 ASCII Standard

+

The ubiquitous ASCII standard is well known to most computer +users. It's reproduced here for reference.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Hex

+
+

0

+
+

1

+
+

2

+
+

3

+
+

4

+
+

5

+
+

6

+
+

7

+
+

0

+
+

NULL

+
+

DLE

+
+

SPACE

+
+

0

+
+

@

+
+

P

+
+

`

+
+

p

+
+

1

+
+

SOH

+
+

DC1

+
+

!

+
+

1

+
+

A

+
+

Q

+
+

a

+
+

q

+
+

2

+
+

STX

+
+

DC2

+
+

"

+
+

2

+
+

B

+
+

R

+
+

b

+
+

r

+
+

3

+
+

ETX

+
+

DC3

+
+

#

+
+

3

+
+

C

+
+

S

+
+

c

+
+

s

+
+

4

+
+

EOT

+
+

DC4

+
+

$

+
+

4

+
+

D

+
+

Y

+
+

d

+
+

t

+
+

5

+
+

ENQ

+
+

NAK

+
+

%

+
+

5

+
+

E

+
+

U

+
+

e

+
+

u

+
+

6

+
+

ACK

+
+

SYN

+
+

&

+
+

6

+
+

F

+
+

V

+
+

f

+
+

v

+
+

7

+
+

BEL

+
+

ETB

+
+

'

+
+

7

+
+

G

+
+

W

+
+

g

+
+

w

+
+

8

+
+

BS

+
+

CAN

+
+

(

+
+

8

+
+

H

+
+

X

+
+

h

+
+

x

+
+

9

+
+

TAB

+
+

EM

+
+

)

+
+

9

+
+

I

+
+

Y

+
+

i

+
+

y

+
+

A

+
+

LF

+
+

SUB

+
+

*

+
+

:

+
+

J

+
+

Z

+
+

j

+
+

z

+
+

B

+
+

VT

+
+

ESC

+
+

+

+
+

;

+
+

K

+
+

[

+
+

k

+
+

{

+
+

C

+
+

FF

+
+

FS

+
+

,

+
+

<

+
+

L

+
+

\

+
+

l

+
+

|

+
+

D

+
+

CR

+
+

GS

+
+

-

+
+

=

+
+

M

+
+

]

+
+

m

+
+

}

+
+

E

+
+

SO

+
+

RS

+
+

.

+
+

>

+
+

N

+
+

^

+
+

n

+
+

~

+
+

F

+
+

SI

+
+

US

+
+

/

+
+

?

+
+

O

+
+

_

+
+

o

+
+

DEL

+
+

+

A.2 Latin Alphabet No 1 (ISO 8859-1)

+

A common extension to the ASCII +standard, Latin-1 is used to expand the range of Code 128 and PDF417 symbols.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Hex

+
+

8

+
+

9

+
+

A

+
+

B

+
+

C

+
+

D

+
+

E

+
+

F

+
+

0

+
+


+

+
+


+

+
+

NBSP

+
+

°

+
+

À

+
+

Ð

+
+

à

+
+

ð

+
+

1

+
+


+

+
+


+

+
+

¡

+
+

±

+
+

Á

+
+

Ñ

+
+

á

+
+

ñ

+
+

2

+
+


+

+
+


+

+
+

¢

+
+

²

+
+

Â

+
+

Ò

+
+

â

+
+

ò

+
+

3

+
+


+

+
+


+

+
+

£

+
+

³

+
+

Ã

+
+

Ó

+
+

ã

+
+

ó

+
+

4

+
+


+

+
+


+

+
+

¤

+
+

´

+
+

Ä

+
+

Ô

+
+

ä

+
+

ô

+
+

5

+
+


+

+
+


+

+
+

¥

+
+

µ

+
+

Å

+
+

Õ

+
+

å

+
+

õ

+
+

6

+
+


+

+
+


+

+
+

¦

+
+

+
+

Æ

+
+

Ö

+
+

æ

+
+

ö

+
+

7

+
+


+

+
+


+

+
+

§

+
+

·

+
+

Ç

+
+

×

+
+

ç

+
+

÷

+
+

8

+
+


+

+
+


+

+
+

¨

+
+

¸

+
+

È

+
+

Ø

+
+

è

+
+

ø

+
+

9

+
+


+

+
+


+

+
+

©

+
+

¹

+
+

É

+
+

Ù

+
+

é

+
+

ù

+
+

A

+
+


+

+
+


+

+
+

ª

+
+

º

+
+

Ê

+
+

Ú

+
+

ê

+
+

ú

+
+

B

+
+


+

+
+


+

+
+

«

+
+

»

+
+

Ë

+
+

Û

+
+

ë

+
+

û

+
+

C

+
+


+

+
+


+

+
+

¬

+
+

¼

+
+

Ì

+
+

Ü

+
+

ì

+
+

ü

+
+

D

+
+


+

+
+


+

+
+

SHY

+
+

½

+
+

Í

+
+

Ý

+
+

í

+
+

ý

+
+

E

+
+


+

+
+


+

+
+

®

+
+

¾

+
+

Î

+
+

Þ

+
+

î

+
+

þ

+
+

F

+
+


+

+
+


+

+
+

¯

+
+

¿

+
+

Ï

+
+

ß

+
+

ï

+
+

ÿ

+
+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Legal Information

+
+

 

+
+

Appendix B

+
+ + \ No newline at end of file diff --git a/docs/appxb.html b/docs/appxb.html new file mode 100644 index 00000000..84f077e1 --- /dev/null +++ b/docs/appxb.html @@ -0,0 +1,316 @@ + + + + + Three Digit Country Codes + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

B. Three Digit Country Codes (ISO 3166)

+

Below are some of the three digit country codes as determined by +ISO 3166 for use with Maxicode symbols.

+
+AFGHANISTAN                                     004 
+ALAND ISLANDS                                   248
+ALBANIA                                         008 
+ALGERIA                                         012 
+AMERICAN SAMOA                                  016 
+ANDORRA                                         020 
+ANGOLA                                          024 
+ANGUILLA                                        660 
+ANTARCTICA                                      010 
+ANTIGUA AND BARBUDA                             028 
+ARGENTINA                                       032 
+ARMENIA                                         051 
+ARUBA                                           533 
+AUSTRALIA                                       036 
+AUSTRIA                                         040 
+AZERBAIJAN                                      031 
+BAHAMAS                                         044 
+BAHRAIN                                         048 
+BANGLADESH                                      050 
+BARBADOS                                        052 
+BELARUS                                         112 
+BELGIUM                                         056 
+BELIZE                                          084 
+BENIN                                           204 
+BERMUDA                                         060 
+BHUTAN                                          064 
+BOLIVIA                                         068 
+BOSNIA AND HERZEGOVINA                          070 
+BOTSWANA                                        072 
+BOUVET ISLAND                                   074 
+BRAZIL                                          076 
+BRITISH INDIAN OCEAN TERRITORY                  086 
+BRUNEI DARUSSALAM                               096 
+BULGARIA                                        100 
+BURKINA FASO                                    854 
+BURUNDI                                         108 
+CAMBODIA                                        116 
+CAMEROON                                        120 
+CANADA                                          124 
+CAPE VERDE                                      132 
+CAYMAN ISLANDS                                  136 
+CENTRAL AFRICAN REPUBLIC                        140 
+CHAD                                            148 
+CHILE                                           152 
+CHINA                                           156 
+CHRISTMAS ISLAND                                162 
+COCOS (KEELING) ISLANDS                         166 
+COLOMBIA                                        170 
+COMOROS                                         174 
+CONGO                                           178 
+CONGO, THE DEMOCRATIC REPUBLIC OF THE           180 
+COOK ISLANDS                                    184 
+COSTA RICA                                      188 
+COTE D'IVOIRE                                   384 
+CROATIA                                         191 
+CUBA                                            192 
+CYPRUS                                          196 
+CZECH REPUBLIC                                  203 
+DENMARK                                         208 
+DJIBOUTI                                        262 
+DOMINICA                                        212 
+DOMINICAN REPUBLIC                              214 
+ECUADOR                                         218 
+EGYPT                                           818 
+EL SALVADOR                                     222 
+EQUATORIAL GUINEA                               226 
+ERITREA                                         232 
+ESTONIA                                         233 
+ETHIOPIA                                        231 
+FALKLAND ISLANDS (MALVINAS)                     238 
+FAROE ISLANDS                                   234 
+FIJI                                            242 
+FINLAND                                         246 
+FRANCE                                          250 
+FRENCH GUIANA                                   254 
+FRENCH POLYNESIA                                258 
+FRENCH SOUTHERN TERRITORIES                     260 
+GABON                                           266 
+GAMBIA                                          270 
+GEORGIA                                         268 
+GERMANY                                         276 
+GHANA                                           288 
+GIBRALTAR                                       292 
+GREECE                                          300 
+GREENLAND                                       304 
+GRENADA                                         308 
+GUADELOUPE                                      312 
+GUAM                                            316 
+GUATEMALA                                       320 
+GUERNSEY                                        831
+GUINEA                                          324 
+GUINEA-BISSAU                                   624 
+GUYANA                                          328 
+HAITI                                           332 
+HEARD ISLAND AND MCDONALD ISLANDS               334 
+HOLY SEE (VATICAN CITY STATE)                   336
+HONDURAS                                        340 
+HONG KONG                                       344 
+HUNGARY                                         348 
+ICELAND                                         352 
+INDIA                                           356 
+INDONESIA                                       360 
+IRAN (ISLAMIC REPUBLIC OF)                      364 
+IRAQ                                            368 
+IRELAND                                         372 
+ISLE OF MAN                                     833
+ISRAEL                                          376 
+ITALY                                           380 
+JAMAICA                                         388 
+JAPAN                                           392 
+JERSEY                                          832
+JORDAN                                          400 
+KAZAKHSTAN                                      398 
+KENYA                                           404 
+KIRIBATI                                        296 
+KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF          408 
+KOREA, REPUBLIC OF                              410 
+KUWAIT                                          414 
+KYRGYZSTAN                                      417 
+LAO PEOPLE'S DEMOCRATIC REPUBLIC                418 
+LATVIA                                          428 
+LEBANON                                         422 
+LESOTHO                                         426 
+LIBERIA                                         430 
+LIBYAN ARAB JAMAHIRIYA                          434 
+LIECHTENSTEIN                                   438 
+LITHUANIA                                       440 
+LUXEMBOURG                                      442 
+MACAO                                           446 
+MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF      807 
+MADAGASCAR                                      450 
+MALAWI                                          454 
+MALAYSIA                                        458 
+MALDIVES                                        462 
+MALI                                            466 
+MALTA                                           470 
+MARSHALL ISLANDS                                584 
+MARTINIQUE                                      474 
+MAURITANIA                                      478 
+MAURITIUS                                       480 
+MAYOTTE                                         175 
+MEXICO                                          484 
+MICRONESIA, FEDERATED STATES OF                 583 
+MOLDOVA, REPUBLIC OF                            498 
+MONACO                                          492
+MONGOLIA                                        496
+MONTENEGRO                                      499
+MONTSERRAT                                      500 
+MOROCCO                                         504 
+MOZAMBIQUE                                      508 
+MYANMAR                                         104 
+NAMIBIA                                         516 
+NAURU                                           520 
+NEPAL                                           524 
+NETHERLANDS                                     528 
+NETHERLANDS ANTILLES                            530 
+NEW CALEDONIA                                   540 
+NEW ZEALAND                                     554 
+NICARAGUA                                       558 
+NIGER                                           562 
+NIGERIA                                         566 
+NIUE                                            570 
+NORFOLK ISLAND                                  574 
+NORTHERN MARIANA ISLANDS                        580 
+NORWAY                                          578 
+OMAN                                            512 
+PAKISTAN                                        586 
+PALAU                                           585 
+PALESTINIAN TERRITORY, OCCUPIED                 275
+PANAMA                                          591 
+PAPUA NEW GUINEA                                598 
+PARAGUAY                                        600 
+PERU                                            604 
+PHILIPPINES                                     608 
+PITCAIRN                                        612 
+POLAND                                          616 
+PORTUGAL                                        620 
+PUERTO RICO                                     630 
+QATAR                                           634 
+REUNION                                         638 
+ROMANIA                                         642 
+RUSSIAN FEDERATION                              643 
+RWANDA                                          646 
+SAINT HELENA                                    654
+SAINT KITTS AND NEVIS                           659 
+SAINT LUCIA                                     662 
+SAINT PIERRE AND MIQUELON                       666
+SAINT VINCENT AND THE GRENADINES                670 
+SAMOA                                           882 
+SAN MARINO                                      674 
+SAO TOME AND PRINCIPE                           678 
+SAUDI ARABIA                                    682 
+SENEGAL                                         686 
+SERBIA                                          688
+SEYCHELLES                                      690 
+SIERRA LEONE                                    694 
+SINGAPORE                                       702 
+SLOVAKIA                                        703 
+SLOVENIA                                        705 
+SOLOMON ISLANDS                                 090 
+SOMALIA                                         706 
+SOUTH AFRICA                                    710 
+SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS    239 
+SPAIN                                           724 
+SRI LANKA                                       144 
+SUDAN                                           736 
+SURINAME                                        740
+SVALBARD AND JAN MAYEN                          744
+ST. HELENA                                      654 
+ST. PIERRE AND MIQUELON                         666 
+SWAZILAND                                       748 
+SWEDEN                                          752 
+SWITZERLAND                                     756 
+SYRIAN ARAB REPUBLIC                            760 
+TAIWAN, PROVINCE OF CHINA                       158 
+TAJIKISTAN                                      762 
+TANZANIA, UNITED REPUBLIC OF                    834 
+THAILAND                                        764
+TIMOR-LESTE                                     626
+TOGO                                            768 
+TOKELAU                                         772 
+TONGA                                           776 
+TRINIDAD AND TOBAGO                             780 
+TUNISIA                                         788 
+TURKEY                                          792 
+TURKMENISTAN                                    795 
+TURKS AND CAICOS ISLANDS                        796 
+TUVALU                                          798 
+UGANDA                                          800 
+UKRAINE                                         804 
+UNITED ARAB EMIRATES                            784 
+UNITED KINGDOM                                  826 
+UNITED STATES                                   840 
+UNITED STATES MINOR OUTLYING ISLANDS            581 
+URUGUAY                                         858 
+UZBEKISTAN                                      860 
+VANUATU                                         548 
+VATICAN CITY STATE (HOLY SEE)                   336 
+VENEZUELA                                       862 
+VIET NAM                                        704 
+VIRGIN ISLANDS (BRITISH)                        092 
+VIRGIN ISLANDS (U.S.)                           850 
+WALLIS AND FUTUNA                               876 
+WESTERN SAHARA                                  732 
+YEMEN                                           887 
+YUGOSLAVIA                                      891 
+ZAMBIA                                          894 
+ZIMBABWE                                        716
+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Appendix A

+
+

 

+
+

Appendix C

+
+ + diff --git a/docs/appxc.html b/docs/appxc.html new file mode 100644 index 00000000..290c9a6f --- /dev/null +++ b/docs/appxc.html @@ -0,0 +1,382 @@ + + + + + GS1 General Specification + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+
+

C. GS1 General Specification

+

The GS1 General Specification defines a global standard for +encoding data about products. The full specification is available +here. +Data is encoded as a series of number pairs where the first number, +usually shown in (brackets) is an application identifier (AI), and +the second is a formatted representation of the data. For example +(401)6773 can be read as "Consignment Number 6773" where +the AI (401) signifies that the data is a consignment number. Note +that when using Zint AI data is entered using [square] brackets. This +allows rounded brackets to be included in the data which is allowed +by the specification. When the barcode symbol is generated these +square brackets are replaced by rounded brackets in the text. A list +of valid AI numbers is given below.

+

C.1 Application Identifiers [1]

+
00 Serial Shipping Container Code (SSCC)
+01 Global Trade Item Number (GTIN)
+02 # of containers
+10 Batch Number
+11 Production Date
+13 Packaging Date
+15 Sell by Date (Quality Control)
+17 Expiration Date
+20 Product Variant
+21 Serial Number
+22 HIBCC Quantity, Date, Batch and Link
+23x Lot Number
+240 Additional Product Identification
+250 Second Serial Number
+30 Quantity Each
+310y Product Net Weight in kg
+311y Product Length/1st Dimension, in meters
+312y Product Width/Diameter/2nd Dimension, in meters
+313y Product Depth/Thickness/3rd Dimension, in meters
+314y Product Area, in square meters
+315y Product Volume, in liters
+316y product Volume, in cubic meters
+320y Product Net Weight, in pounds
+321y Product Length/1st Dimension, in inches
+322y Product Length/1st Dimension, in feet
+323y Product Length/1st Dimension, in yards
+324y Product Width/Diameter/2nd Dimension, in inches
+325y Product Width/Diameter/2nd Dimension, in feet
+326y Product Width/Diameter/2nd Dimension, in yards
+327y Product Depth/Thickness/3rd Dimension, in inches
+328y Product Depth/Thickness/3rd Dimension, in feet
+329y Product Depth/Thickness/3rd Dimension, in yards
+330y Container Gross Weight (kg)
+331y Container Length/1st Dimension (Meters)
+332y Container Width/Diameter/2nd Dimension (Meters)
+333y Container Depth/Thickness/3rd Dimension (Meters)
+334y Container Area (Square Meters)
+335y Container Gross Volume (Liters)
+336y Container Gross Volume (Cubic Meters)
+340y Container Gross Weight (Pounds)
+341y Container Length/1st Dimension, in inches
+342y Container Length/1st Dimension, in feet
+343y Container Length/1st Dimension in, in yards
+344y Container Width/Diameter/2nd Dimension, in inches
+345y Container Width/Diameter/2nd Dimension, in feet
+346y Container Width/Diameter/2nd Dimension, in yards
+347y Container Depth/Thickness/Height/3rd Dimension, in inches
+348y Container Depth/Thickness/Height/3rd Dimension, in feet
+349y Container Depth/Thickness/Height/3rd Dimension, in yards
+350y Product Area (Square Inches)
+351y Product Area (Square Feet)
+352y Product Area (Square Yards)
+353y Container Area (Square Inches)
+354y Container Area (Square Feet)
+355y Container Area (Suqare Yards)
+356y Net Weight (Troy Ounces)
+360y Product Volume (Quarts)
+361y Product Volume (Gallons)
+362y Container Gross Volume (Quarts)
+363y Container Gross Volume (Gallons)
+364y Product Volume (Cubic Inches)
+365y Product Volume (Cubic Feet)
+366y Product Volume (Cubic Yards)
+367y Container Gross Volume (Cubic Inches)
+368y Container Gross Volume (Cubic Feet)
+369y Container Gross Volume (Cubic Yards)
+37 Number of Units Contained
+400 Customer Purchase Order Number
+410 Ship To/Deliver To Location Code (Global Location Number)
+411 Bill To/Invoice Location Code (Global Location Number)
+412 Purchase From Location Code (Global Location Number)
+420 Ship To/Deliver To Postal Code (Single Postal Authority)
+421 Ship To/Deliver To Postal Code (Multiple Postal Authority)
+8001 Roll Products - Width/Length/Core Diameter
+8002 Electronic Serial Number (ESN) for Cellular Phone
+8003 Global Returnable Asset Identifier
+8004 Global Individual Asset Identifier
+8005 Price per Unit of Measure
+8100 Coupon Extended Code: Number System and Offer
+8101 8101 Coupon Extended Code: Number System, Offer, End of Offer
+8102 Coupon Extended Code: Number System preceded by 0
+90 Mutually Agreed Between Trading Partners
+91 Internal Company Codes
+92 Internal Company Codes
+93 Internal Company Codes
+94 Internal Company Codes
+95 Internal Company Codes
+96 Internal Company Codes
+97 Internal Company Codes
+98 Internal Company Codes
+99 Internal Company Codes

+C.2 Fixed Length Fields

+

The GS1 Specification requires that +some of the data to be encoded fits a standard length field. Zint +requires this to be true of input data in order for data to be +encoded correctly but does not check that the input data adheres to +these rules. If this system is not followed then the resulting +barcode symbol may not be readable. The following table details which +AIs have fixed length data fields and how long the data should be for +each:

+


+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Application Identifier

+
+

Number of characters
(AI and Data Field)

+
+

00

+
+

20

+
+

01

+
+

16

+
+

02

+
+

16

+
+

03

+
+

16

+
+

04

+
+

18

+
+

11

+
+

8

+
+

12

+
+

8

+
+

13

+
+

8

+
+

14

+
+

8

+
+

15

+
+

8

+
+

16

+
+

8

+
+

17

+
+

8

+
+

18

+
+

8

+
+

19

+
+

8

+
+

20

+
+

4

+
+

31

+
+

10

+
+

32

+
+

10

+
+

33

+
+

10

+
+

34

+
+

10

+
+

35

+
+

10

+
+

36

+
+

10

+
+

41

+
+

16

+
+
+


+

+

[1] This information taken from +Wikipedia and used +under the terms of the GNU +Free Documentation License.

+


+

+


+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Appendix B

+
+

 

+
+



+

+ + \ No newline at end of file diff --git a/docs/auspost.png b/docs/auspost.png new file mode 100644 index 00000000..0bca727e Binary files /dev/null and b/docs/auspost.png differ diff --git a/docs/backend.html b/docs/backend.html new file mode 100644 index 00000000..21aa31ed --- /dev/null +++ b/docs/backend.html @@ -0,0 +1,1390 @@ + + + + + Using the API + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

4. Using the API

+

The libzint API has been designed to be very similar to +that used by the GNU +Barcode package. This allows easy migration from GNU Barcode to +Zint. Zint, however, uses none of the same function +names or option names as GNU Barcode. This allows you to use +both packages in your application without conflict if you wish.

+



+

+

4.1 +Creating and Deleting Symbols

+

The symbols manipulated by Zint are +held in a zint_symbol +structure defined in zint.h. +These symbols are created with the ZBarcode_Create() +function and deleted using the ZBarcode_Delete() +function. For example the following code creates and then deletes a +symbol:

+

#include +<stdio.h>
#include <zint.h>

int +main()
{
    struct zint_symbol +*my_symbol;

    my_symbol = +ZBarcode_Create();
    if(my_symbol != NULL) +{
        printf("Symbol +successfully +created!\n");
    }
    ZBarcode_Delete(my_symbol);
    return +0;
}

+

When compiling this code it will need to be linked with the +libzint library using the -lzint option:

+

gcc -o simple +simple.c -lzint

+



+

+

4.2 Encoding and Saving to +File

+

To encode data in a barcode use the ZBarcode_Encode() +function. To write the symbol to a file use the ZBarcode_Print() +function. For example the following code takes a string from the +command line and outputs a Code 128 symbol in a PNG file named +out.png in the current working directory:

+

#include +<stdio.h>
#include <zint.h>

int main(int argc, +char **argv)
{
    struct zint_symbol +*my_symbol;

    my_symbol = +ZBarcode_Create();
    ZBarcode_Encode(my_symbol, +argv[1]);
    ZBarcode_Print(my_symbol);
    ZBarcode_Delete(my_symbol);
    return +0;
}

+

This can also be done in one stage using the +ZBarcode_Encode_and_Print() +function as shown in the next example:

+

#include +<stdio.h>
#include <zint.h>

int main(int argc, +char **argv)
{
    struct zint_symbol +*my_symbol;

    my_symbol = +ZBarcode_Create();
    ZBarcode_Encode_and_Print(my_symbol, +argv[1]);
    ZBarcode_Delete(my_symbol);
    return +0;
}

+



+

+

4.3 Setting Options

+

So far our application is not very useful unless we plan to only +make Code 128 barcodes and we don't mind that they only save to +out.png. As with the front end program, of course, these options can +be altered. The way this is done is by altering the contents of the +zint_symbol structure between +the creation and encoding stages. The zint_symbol +structure consists of the following variables:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Variable Name

+
+

Type

+
+

Meaning

+
+

Default Value

+
+

symbology

+
+

integer

+
+

Symbology to use (see section 4.5).

+
+

BARCODE_CODE128

+
+

height

+
+

integer

+
+

Symbol height. [1]

+
+

50

+
+

whitespace_width

+
+

integer

+
+

Whitespace width.

+
+

0

+
+

boder_width

+
+

integer

+
+

Border width.

+
+

0

+
+

output_options

+
+

integer

+
+

Binding or box parameters (see section 4.6). [2]

+
+

(none)

+
+

fgcolour

+
+

character string

+
+

Foreground (ink) colour as RGB hexadecimal + string. Must be 6 characters followed by terminating \0 + character.

+
+

"000000"

+
+

bgcolour

+
+

character string

+
+

Background (paper) colour as RGB hexadecimal + string. Must be 6 characters followed by terminating \0 + character.

+
+

"ffffff"

+
+

outfile

+
+

character string

+
+

Contains the name of the file to output a + resulting barcode symbol to. Must end in .PNG or .EPS

+
+

"out.png"

+
+

option_1

+
+

integer

+
+

Symbology specific options.

+
+

(automatic)

+
+

option_2

+
+

integer

+
+

Symbology specific options.

+
+

(automatic)

+
+

primary

+
+

character string

+
+

Primary message data for more complex symbols.

+
+

NULL

+
+

text

+
+

character string

+
+

Human readable text, which usually consists of + the input data plus one or more check digits.

+
+

NULL

+
+

rows

+
+

integer

+
+

Number of rows used by the symbol or, if using + barcode stacking, the row to be used by the next symbol.

+
+

(output only)

+
+

width

+
+

integer

+
+

Width of the generated symbol.

+
+

(output only)

+
+

encoding_data

+
+

array of character strings

+
+

Representation of the encoded data.

+
+

(output only)

+
+

row_height

+
+

array of integers

+
+

Representation of the height of a row.

+
+

(output only)

+
+

errtxt

+
+

character string

+
+

Error message in the event that an error + occurred.

+
+

(output only)

+
+
+



+

+

To alter these values use the syntax shown in the example below. +This code has the same result as the previous example except the +output is now taller and plotted in green.

+

#include +<stdio.h>
#include <zint.h>
#include +<string.h>

int main(int argc, char **argv)
{
    struct +zint_symbol *my_symbol;

    my_symbol = +ZBarcode_Create();
    strcpy(my_symbol->fgcolour, +"00ff00");
    my_symbol->height += 400;
    ZBarcode_Encode_and_Print(my_symbol, +argv[1]);
    ZBarcode_Delete(my_symbol);
    return +0;
}

+



+

+

4.4 Handling Errors

+

If errors occur during encoding an integer value is passed back to +the calling application. In addition the errtxt +value is used to give a message detailing the nature of the error. +The errors generated by Zint are given in the table below:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Return Value

+
+

Meaning

+
+

WARN_INVALID_OPTION

+
+

One of the values in zint_struct + was set incorrectly but Zint has made a guess at what it should + have been and generated a barcode accordingly.

+
+

ERROR_TOO_LONG

+
+

The input data is too long or too short for the + selected symbology. No symbol has been generated.

+
+

ERROR_INVALID_DATA

+
+

The data to be encoded includes characters which + are not permitted by the selected symbology (e.g. alphabetic + characters in an EAN symbol). No symbol has been generated.

+
+

ERROR_INVALID_CHECK

+
+

An ISBN with an incorrect check digit has been + entered. No symbol has been generated.

+
+

ERROR_INVALID_OPTION

+
+

One of the values in zint_struct + was set incorrectly and Zint was unable to guess what it should + have been. No symbol has been generated.

+
+

ERROR_ENCODING_PROBLEM

+
+

A problem has occurred during encoding of the + data. This should never happen. Please contact the developer if + you encounter this error.

+
+

ERROR_FILE_ACCESS

+
+

Zint was unable to open the requested output + file. This is usually a file permissions problem.

+
+

ERROR_MEMORY

+
+

Zint ran out of memory. This should only be a + problem with legacy systems.

+
+
+



+

+

To catch errors use an integer variable as shown in the code +below:

+

#include +<stdio.h>
#include <zint.h>
#include +<string.h>

int main(int argc, char **argv)
{
    struct +zint_symbol *my_symbol;
    int error = +0;

    my_symbol = +ZBarcode_Create();
    strcpy(my_symbol->fgcolour, +"nonsense");
    error = +ZBarcode_Encode_and_Print(my_symbol, argv[1]);

    if(error +!= 0) {
        /* some +error occurred */
        printf("%s\n", +my_symbol->errtxt);
    }

    if(error +> WARN_INVALID_OPTION) {
        /* +stop now */
        ZBarcode_Delete(my_symbol);
        return +1;
    }
    /* +otherwise carry on with the rest of the application +*/
    ZBarcode_Delete(my_symbol);
    return +0;
}

+

This code will exit with the appropriate message:

+

error: malformed +foreground colour target

+



+

+

4.5 Specifying a Symbology

+

Symbologies can be specified by number or by name as shown in the +following table. For example

+

symbol->symbology += BARCODE_LOGMARS;

+

means the same as

+

symbol->symbology += 50;

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Numeric Value

+
+

Name

+
+

Symbology

+
+

1

+
+

BARCODE_CODE11

+
+

Code 11

+
+

2

+
+

BARCODE_C25MATRIX

+
+

Standard Code 2 of 5

+
+

3

+
+

BARCODE_C25INTER

+
+

Interleaved 2 of 5

+
+

4

+
+

BARCODE_C25IATA

+
+

Code 2 of 5 IATA

+
+

6

+
+

BARCODE_C25LOGIC

+
+

Code 2 of 5 Data Logic

+
+

7

+
+

BARCODE_C25IND

+
+

Code 2 of 5 Industrial

+
+

8

+
+

BARCODE_CODE39

+
+

Code 3 of 9 (Code 39)

+
+

9

+
+

BARCODE_EXCODE39

+
+

Extended Code 3 of 9 (Code 39+)

+
+

13

+
+

BARCODE_EANX

+
+

EAN

+
+

16

+
+

BARCODE_EAN128

+
+

GS1-128

+
+

18

+
+

BARCODE_CODABAR

+
+

Codabar

+
+

20

+
+

BARCODE_CODE128

+
+

Code 128 (automatic subset switching)

+
+

21

+
+

BARCODE_DPLEIT

+
+

Deutshe Post Leitcode

+
+

22

+
+

BARCODE_DPIDENT

+
+

Deutshe Post Identcode

+
+

23

+
+

BARCODE_CODE16K

+
+

Code 16K

+
+

25

+
+

BARCODE_CODE93

+
+

Code 93

+
+

28

+
+

BARCODE_FLAT

+
+

Flattermarken

+
+

29

+
+

BARCODE_RSS14

+
+

GS1 DataBar-14

+
+

30

+
+

BARCODE_RSS_LTD

+
+

GS1 DataBar Limited

+
+

31

+
+

BARCODE_RSS_EXP

+
+

GS1 DataBar Expanded

+
+

32

+
+

BARCODE_TELEPEN

+
+

Telepen Alpha

+
+

34

+
+

BARCODE_UPCA

+
+

UPC A

+
+

37

+
+

BARCODE_UPCE

+
+

UPC E

+
+

40

+
+

BARCODE_POSTNET

+
+

PostNet

+
+

47

+
+

BARCODE_MSI_PLESSEY

+
+

MSI Code

+
+

49

+
+

BARCODE_FIM

+
+

FIM

+
+

50

+
+

BARCODE_LOGMARS

+
+

LOGMARS

+
+

51

+
+

BARCODE_PHARMA

+
+

Pharmacode One-Track

+
+

52

+
+

BARCODE_PZN

+
+

PZN

+
+

53

+
+

BARCODE_PHARMA_TWO

+
+

Pharmacode Two-Track

+
+

55

+
+

BARCODE_PDF417

+
+

PDF417

+
+

56

+
+

BARCODE_PDF417TRUNC

+
+

PDF417 Truncated

+
+

57

+
+

BARCODE_MAXICODE

+
+

Maxicode

+
+

58

+
+

BARCODE_QRCODE

+
+

QR Code

+
+

60

+
+

BARCODE_CODE128B

+
+

Code 128 (Subset B)

+
+

63

+
+

BARCODE_AUSPOST

+
+

Australia Post Standard Customer

+
+

66

+
+

BARCODE_AUSREPLY

+
+

Australia Post Reply Paid

+
+

67

+
+

BARCODE_AUSROUTE

+
+

Australia Post Routing

+
+

68

+
+

BARCODE_AUSREDIRECT

+
+

Australia Post Redirection

+
+

69

+
+

BARCODE_ISBNX

+
+

ISBN (EAN-13 with verification stage)

+
+

70

+
+

BARCODE_RM4SCC

+
+

Royal Mail 4 State (RM4SCC)

+
+

71

+
+

BARCODE_DATAMATRIX

+
+

Data Matrix

+
+

72

+
+

BARCODE_ITF14

+
+

ITF-14

+
+

75

+
+

BARCODE_NVE18

+
+

NVE-18

+
+

79

+
+

BARCODE_RSS14STACK

+
+

GS1 DataBar-14 Stacked

+
+

80

+
+

BARCODE_RSS14STACK_OMNI

+
+

GS1 DataBar-14 Stacked Omnidirectional

+
+

81

+
+

BARCODE_RSS_EXPSTACK

+
+

GS1 DataBar Expanded Stacked

+
+

82

+
+

BARCODE_PLANET

+
+

PLANET

+
+

84

+
+

BARCODE_MICROPDF417

+
+

MicroPDF417

+
+

85

+
+

BARCODE_ONECODE

+
+

USPS OneCode

+
+

86

+
+

BARCODE_PLESSEY

+
+

Plessey Code

+
+

100

+
+

BARCODE_TELEPEN_NUM

+
+

Telepen Numeric

+
+

101

+
+

BARCODE_MSI_10

+
+

MSI Plessey + mod 10

+
+

102

+
+

BARCODE_MSI_10_10

+
+

MSI Plessey + mod 10 + mod 10

+
+

103

+
+

BARCODE_MSI_11

+
+

MSI Plessey + mod 11

+
+

104

+
+

BARCODE_MSI_11_10

+
+

MSI Plessey + mod 11 + mod 10

+
+

105

+
+

BARCODE_CODE39_43

+
+

Code 39 + mod 43

+
+

106

+
+

BARCODE_EXCODE39_43

+
+

Extended Code 39 + mod 43

+
+

110

+
+

BARCODE_EANX_CC

+
+

Composite Symbol with EAN linear component

+
+

111

+
+

BARCODE_EAN128_CC

+
+

Composite Symbol with GS1-128 linear component

+
+

112

+
+

BARCODE_RSS14_CC

+
+

Composite Symbol with GS1 DataBar-14 linear + component

+
+

113

+
+

BARCODE_RSS_LTD_CC

+
+

Composite Symbol with GS1 DataBar Limited + component

+
+

114

+
+

BARCODE_RSS_EXP_CC

+
+

Composite Symbol with GS1 DataBar Extended + component

+
+

115

+
+

BARCODE_UPCA_CC

+
+

Composite Symbol with UPC A linear component

+
+

116

+
+

BARCODE_UPCE_CC

+
+

Composite Symbol with UPC E linear component

+
+

117

+
+

BARCODE_RSS14STACK_CC

+
+

Composite Symbol with GS1 DataBar-14 Stacked + component

+
+

118

+
+

BARCODE_RSS14_OMNI_CC

+
+

Composite Symbol with GS1 DataBar-14 Stacked + Omnidirectional component

+
+

119

+
+

BARCODE_RSS_EXPSTACK_CC

+
+

Composite Symbol with GS1 DataBar Expanded + Stacked component

+
+
+



+

+

4.6 Adding Boxes and Boundary +Bars

+

Boxes and boundary bars are handled using the output_options +variable in the zint_symbol structure. To +use this option simply assign a value to the output_options +variable from the following table [2].

+
+ + + + + + + + + + + + + + + + + + + + + + + +
+

Value

+
+

Effect

+
+

0

+
+

No box or boundary bars.

+
+

BARCODE_BIND

+
+

Boundary bars above and below the symbol and + between rows if stacking multiple symbols.

+
+

BARCODE_BOX

+
+

Add a box surrounding the symbol and whitespace.

+
+
+



+

+



+

+

[1] This value is ignored for Australia Post 4-State Barcodes, +PostNet, PLANET, USPS OneCode, RM4SCC, PDF417, Data Matrix, Maxicode, +QR Code and GS1 DataBar-14 Stacked - all of which have a fixed +height.

+

[2] This value is ignored for Code 16k and ITF-14 symbols.

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Using the Front End

+
+

 

+
+

Types of Symbol

+
+



+

+ + \ No newline at end of file diff --git a/docs/border.png b/docs/border.png new file mode 100644 index 00000000..a186b431 Binary files /dev/null and b/docs/border.png differ diff --git a/docs/box.png b/docs/box.png new file mode 100644 index 00000000..0f848061 Binary files /dev/null and b/docs/box.png differ diff --git a/docs/cca.png b/docs/cca.png new file mode 100644 index 00000000..c7743236 Binary files /dev/null and b/docs/cca.png differ diff --git a/docs/ccb.png b/docs/ccb.png new file mode 100644 index 00000000..a554e4e8 Binary files /dev/null and b/docs/ccb.png differ diff --git a/docs/ccc.png b/docs/ccc.png new file mode 100644 index 00000000..0701ab17 Binary files /dev/null and b/docs/ccc.png differ diff --git a/docs/codabar.png b/docs/codabar.png new file mode 100644 index 00000000..5e05ebfa Binary files /dev/null and b/docs/codabar.png differ diff --git a/docs/code11.png b/docs/code11.png new file mode 100644 index 00000000..be419623 Binary files /dev/null and b/docs/code11.png differ diff --git a/docs/code128.png b/docs/code128.png new file mode 100644 index 00000000..cfb244e2 Binary files /dev/null and b/docs/code128.png differ diff --git a/docs/code16k.png b/docs/code16k.png new file mode 100644 index 00000000..29b9e166 Binary files /dev/null and b/docs/code16k.png differ diff --git a/docs/code39.png b/docs/code39.png new file mode 100644 index 00000000..c38180db Binary files /dev/null and b/docs/code39.png differ diff --git a/docs/codesize.txt b/docs/codesize.txt new file mode 100644 index 00000000..04869ba1 --- /dev/null +++ b/docs/codesize.txt @@ -0,0 +1,19 @@ +0.1 97.9kB (est) +0.2 150.7kB +0.3 101.0kB +0.4 112.0kB +0.5 111.9kB +0.6 109.6kB +1.0 158.8kB +1.1 168.9kB +1.2 208.5kB +1.3 236.6kB +1.4 246.9kB +1.5 263.4kB +1.5.1a 276.2kB +1.5.1 300.2kB +1.5.2 369.4kB +1.5.3 355.3kB +1.5.4 415.3kB +1.5.5 499.9kB +1.5.6* 600.8kB \ No newline at end of file diff --git a/docs/compact417.png b/docs/compact417.png new file mode 100644 index 00000000..2eeb74b0 Binary files /dev/null and b/docs/compact417.png differ diff --git a/docs/composite.html b/docs/composite.html new file mode 100644 index 00000000..bec7c083 --- /dev/null +++ b/docs/composite.html @@ -0,0 +1,271 @@ + + + + + Composite Symbols + + + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

5.3 Composite Symbols (ISO 24723)

+

Composite symbols employ a mixture of components to give more +comprehensive information about a product. The permissible contents +of a composite symbol is determined by the terms of the GS1 +General Specification. Composite symbols consist of a linear +component which can be an EAN, UPC, GS1-128 or GS1 DataBar symbol, a +2D component which is based on PDF417 or MicroPDF417, and a separator +pattern. The type of linear component to be used is determined using +the -b or --barcode= +switch or by adjusting symbol->symbology +as with other encoding methods. Valid values are shown below.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Numeric Value

+
+

Name

+
+

Symbology

+
+

110

+
+

BARCODE_EANX_CC

+
+

Composite Symbol with EAN linear component

+
+

111

+
+

BARCODE_EAN128_CC

+
+

Composite Symbol with GS1-128 linear component

+
+

112

+
+

BARCODE_RSS14_CC

+
+

Composite Symbol with GS1 DataBar-14 linear + component

+
+

113

+
+

BARCODE_RSS_LTD_CC

+
+

Composite Symbol with GS1 DataBar Limited + component

+
+

114

+
+

BARCODE_RSS_EXP_CC

+
+

Composite Symbol with GS1 DataBar Extended + component

+
+

115

+
+

BARCODE_UPCA_CC

+
+

Composite Symbol with UPC A linear component

+
+

116

+
+

BARCODE_UPCE_CC

+
+

Composite Symbol with UPC E linear component

+
+

117

+
+

BARCODE_RSS14STACK_CC

+
+

Composite Symbol with GS1 DataBar-14 Stacked + component

+
+

118

+
+

BARCODE_RSS14_OMNI_CC

+
+

Composite Symbol with GS1 DataBar-14 Stacked + Omnidirectional component

+
+

119

+
+

BARCODE_RSS_EXPSTACK_CC

+
+

Composite Symbol with GS1 DataBar Expanded + Stacked component

+
+
+

The data to be encoded in the linear component of a +composite symbol should be entered into a primary string with the +data for the 2D component being entered in the normal way. To do this +at the command prompt use the --primary= +command. For example:

+

zint -b 110 --mode=1 +--primary=331234567890 -d "[99]1234-abcd"

+

This creates an EAN-13 linear component with the data +"331234567890" and a 2D CC-A (see below) component with the +data "(99)1234-abcd". The same results can be achieved +using the API as shown below:

+

    my_symbol->symbology += 110;
    my_symbol->option_1 = +1;
    strcpy(my_symbol->primary, +"331234567890");
    ZBarcode_Encode_and_Print(my_symbol, +"[99]1234-abcd");

+

EAN-2 and EAN-5 add-on data can be used with EAN and +UPC symbols using the + symbol as described in section 5.1.3 and +5.1.4.

+

The 2D component of a composite symbol can use one of +three systems: CC-A, CC-B and CC-C as described below. The 2D +component type can be selected automatically by Zint dependant on the +length of the input string. Alternatively the three methods can be +accessed using the --mode= prompt +followed by 1, 2 or 3 for CC-A, CC-B or CC-C respectively, or by +using the option_1 variable as shown +above.

+

NOTE: 2D +component data starting with a production (AI 11) or expiration (AI +17) date must be followed by a batch number (AI 10). In the +absence of real data this value can be entered as "0". This +is due to a known problem concerning the way the encoding is +optimised for date information. It is hoped this problem will be +resolved in a later release of Zint.

+

 

+

5.3.1 CC-A

+

This system uses a variation of MicroPDF417 which +optimised to fit into a small space. The size of the 2D component and +the amount of error correction is determined by the amount of data to +be encoded and the type of linear component which is being used. CC-A +can encode up to 56 numeric digits or an alphanumeric string of +shorter length. To select CC-A use --mode=1.

+




+

+

5.3.2 CC-B

+

This system uses MicroPDF417 to encode the 2D +component. The size of the 2D component and the amount of error +correction is determined by the amount of data to be encoded and the +type of linear component which is being used. CC-B can encode up to +338 numeric digits or an alphanumeric string of shorter length. To +select CC-B use --mode=2.

+




+

+

5.3.3 CC-C

+

This system uses PDF417 and can only be used in +conjunction with a GS1-128 linear component. CC-C can encode up to +2361 numeric digits or an alphanumeric string of shorter length. To +select CC-C use --mode=3.

+




+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Stacked Symbologies

+
+

 

+
+

Two-Track Symbols

+
+



+

+ + \ No newline at end of file diff --git a/docs/databar.png b/docs/databar.png new file mode 100644 index 00000000..218cff47 Binary files /dev/null and b/docs/databar.png differ diff --git a/docs/dbexpand.png b/docs/dbexpand.png new file mode 100644 index 00000000..98b8e0dd Binary files /dev/null and b/docs/dbexpand.png differ diff --git a/docs/dbomni.png b/docs/dbomni.png new file mode 100644 index 00000000..899e40a4 Binary files /dev/null and b/docs/dbomni.png differ diff --git a/docs/dbstack.png b/docs/dbstack.png new file mode 100644 index 00000000..86cde8ae Binary files /dev/null and b/docs/dbstack.png differ diff --git a/docs/ean13.png b/docs/ean13.png new file mode 100644 index 00000000..064b8729 Binary files /dev/null and b/docs/ean13.png differ diff --git a/docs/fim.png b/docs/fim.png new file mode 100644 index 00000000..394c003f Binary files /dev/null and b/docs/fim.png differ diff --git a/docs/fourstate.html b/docs/fourstate.html new file mode 100644 index 00000000..6f4455fe --- /dev/null +++ b/docs/fourstate.html @@ -0,0 +1,228 @@ + + + + + 4-State Codes + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

5.5 4-State Postal Codes

+

5.5.1 Australia Post 4-State +Symbols

+

5.5.1.1 Customer Barcodes

+

Australia Post Standard Customer Barcode, Customer Barcode 2 and +Customer Barcode 3 are 37-bar, 52-bar and 67-bar specifications +respectively, developed by Australia Post for printing Delivery Point +ID (DPID) and customer information on mail items. Valid data +characters are 0-9, A-Z, a-z, space and hash (#). A Format Control +Code (FCC) is added by Zint and should not be included in the input +data. Reed-Solomon error correction data is generated by Zint. +Encoding behaviour is determined by the length of the input data +according to the formula shown in the following table:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Input Length

+
+

Required Input Format

+
+

Symbol Length

+
+

FCC

+
+

Encoding Table

+
+

8

+
+

99999999

+
+

37-bar

+
+

11

+
+

None

+
+

13

+
+

99999999AAAAA

+
+

52-bar

+
+

59

+
+

C

+
+

16

+
+

9999999999999999

+
+

52-bar

+
+

59

+
+

N

+
+

18

+
+

99999999AAAAAAAAAA

+
+

67-bar

+
+

62

+
+

C

+
+

23

+
+

99999999999999999999999

+
+

67-bar

+
+

62

+
+

N

+
+
+


+

+

5.5.1.2 Reply Paid Barcode

+

A Reply Paid version of the Australia Post 4-State Barcode (FCC +45) which requires an 8-digit DPID input.

+

5.5.1.3 Routing Barcode

+

A Routing version of the Australia Post 4-State Barcode (FCC 87) +which requires an 8-digit DPID input.

+

5.5.1.4 Redirect Barcode

+

A Redirection version of the Australia Post 4-State Barcode (FCC +92) which requires an 8-digit DPID input.

+




+

+

5.5.2 Royal Mail 4-State +Country Code (RM4SCC)

+

The RM4SCC standard is used by the Royal Mail in the UK to encode +postcode and customer data on mail items. Data input can consist of +numbers 0-9 and letters A-Z and usually includes delivery postcode +followed by house number. For example "W1J0TR01" for 1 +Picadilly Circus in London. Check digit data is generated by Zint.

+




+

+

5.5.3 USPS OneCode

+

Also known as the Intelligent Mail Barcode and used in the US by +the United States Postal Service (USPS), the OneCode system is due to +replace the PostNet and PLANET symbologies by 2009. OneCode is a +fixed length (65-bar) symbol which combines routing and customer +information in a single symbol. Input data consists of a 20 digit +tracking code, followed by a dash (-), followed by a delivery point +zip-code which can be 0, 5, 9 or 11 digits in length. For example all +of the following inputs are valid data entries:

+

"01234567094987654321"
"01234567094987654321-01234"
"01234567094987654321-012345678"
"01234567094987654321-01234567891"

+





+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Two-Track Symbols

+
+

 

+
+

Two-Dimensional Symbols

+
+



+

+ + \ No newline at end of file diff --git a/docs/frontend.html b/docs/frontend.html new file mode 100644 index 00000000..ac60b9e3 --- /dev/null +++ b/docs/frontend.html @@ -0,0 +1,765 @@ + + + + + Using the Front End + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

3. Using the Front End

+

Zint can be used to generate barcodes +as PNG images or as encapsulated Post Script (EPS) files. This page +describes how to encode data using the command line front end +program.

+



+

+

3.1 Inputting data

+

The data to encode can be entered at +the command line using the -d option, for example:

+

zint +-d 'This Text'

+

This will encode the text This Text. +Zint will use the default symbology, Code 128, and output to the +default file out.png in the current directory. +

+



+

+

3.2 +Directing Output

+

Output can be directed to a file other +than the default using the -o switch. For example:

+

zint +-o here.png -d 'This Text'

+

draws a Code 128 barcode in the file +here.png. If an encapsulated Post Script file is needed simply append +the file name with .eps:

+

zint +-o there.eps -d 'This Text'

+



+

+

3.3 +Selecting barcode type

+

Selecting which type of barcode you +wish to produce (i.e. which symbology to use) can be done at the +command line using the -b or --barcode= switch followed by the +appropriate integer value in the following table.

+



+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

ID

+
+

Barcode Name

+
+

1

+
+

Code 11

+
+

2

+
+

Standard Code 2 of 5

+
+

3

+
+

Interleaved 2 of 5

+
+

4

+
+

Code 2 of 5 IATA

+
+

6

+
+

Code 2 of 5 Data Logic

+
+

7

+
+

Code 2 of 5 Industrial

+
+

8

+
+

Code 3 of 9 (Code 39)

+
+

9

+
+

Extended Code 3 of 9 (Code 39+)

+
+

13

+
+

EAN

+
+

16

+
+

GS1-128 (UCC.EAN-128)

+
+

18

+
+

Codabar

+
+

20

+
+

Code 128 (automatic subset switching)

+
+

21

+
+

Deutshe Post Leitcode

+
+

22

+
+

Deutshe Post Identcode

+
+

23

+
+

Code 16K

+
+

25

+
+

Code 93

+
+

28

+
+

Flattermarken

+
+

29

+
+

GS1 DataBar-14

+
+

30

+
+

GS1 DataBar Limited

+
+

31

+
+

GS1 DataBar Extended

+
+

32

+
+

Telepen Alpha

+
+

34

+
+

UPC A

+
+

37

+
+

UPC E

+
+

40

+
+

PostNet

+
+

47

+
+

MSI Code

+
+

49

+
+

FIM

+
+

50

+
+

LOGMARS

+
+

51

+
+

Pharmacode One-Track

+
+

52

+
+

PZN

+
+

53

+
+

Pharmacode Two-Track

+
+

55

+
+

PDF417

+
+

56

+
+

PDF417 Truncated

+
+

57

+
+

Maxicode

+
+

58

+
+

QR Code

+
+

60

+
+

Code 128 (Subset B)

+
+

63

+
+

Australia Post Standard Customer

+
+

66

+
+

Australia Post Reply Paid

+
+

67

+
+

Australia Post Routing

+
+

68

+
+

Australia Post Redirection

+
+

69

+
+

ISBN (EAN-13 with verification stage)

+
+

70

+
+

Royal Mail 4 State (RM4SCC)

+
+

71

+
+

Data Matrix

+
+

72

+
+

ITF-14

+
+

75

+
+

NVE-18

+
+

79

+
+

GS1 DataBar-14 Stacked

+
+

80

+
+

GS1 DataBar-14 Stacked Omnidirectional

+
+

81

+
+

GS1 DataBar Expanded Stacked

+
+

82

+
+

PLANET

+
+

84

+
+

MicroPDF417

+
+

85

+
+

USPS OneCode

+
+

86

+
+

Plessey Code

+
+

100

+
+

Telepen Numeric

+
+

101

+
+

MSI Plessey + mod 10

+
+

102

+
+

MSI Plessey + mod 10 + mod 10

+
+

103

+
+

MSI Plessey + mod 11

+
+

104

+
+

MSI Plessey + mod 10 + mod 11

+
+

105

+
+

Code 39 + mod 43

+
+

106

+
+

Extended Code 39 + mod 43

+
+

110

+
+

Composite Symbol with EAN linear component

+
+

111

+
+

Composite Symbol with GS1-128 linear component

+
+

112

+
+

Composite Symbol with GS1 DataBar-14 linear + component

+
+

113

+
+

Composite Symbol with GS1 DataBar Limited + component

+
+

114

+
+

Composite Symbol with GS1 DataBar Extended + component

+
+

115

+
+

Composite Symbol with UPC A linear component

+
+

116

+
+

Composite Symbol with UPC E linear component

+
+

117

+
+

Composite Symbol with GS1 DataBar-14 Stacked + component

+
+

118

+
+

Composite Symbol with GS1 DataBar-14 Stacked + Omnidirectional component

+
+

119

+
+

Composite Symbol with GS1 DataBar Expanded + Stacked component

+
+
+



+

+

3.4 Adjusting height

+

The height of the symbol can be adjusted using the --height +switch. For example:

+

zint --height=100 -d +'This Text'

+

specifies a symbol height of 100 times the x-resolution of +the symbol.

+



+

+

3.5 +Adjusting whitespace

+

The amount of whitespace to the left +and right of the generated barcode can be altered using the -w +switch. For example:

+

zint +-w 10 -d 'This Text'

+

specifies a whitespace width of 10 +times the x-resolution of the symbol.

+



+

+

3.6 +Adding boundary bars and boxes

+

Zint allows the symbol to be bound with +'boundary bars' using the option --bind. These bars help to prevent +misreading of the symbol by corrupting a scan if the scanning beam +strays off the top or bottom of the symbol. Zint can also put a +border right around the symbol and its whitespace with the --box +option. This option is automatically chosen for ITF-14 symbols.

+

The width of the boundary or box can be +specified using the --border switch. For example:

+

zint +--box --border=10 -d 'This'

+

gives a box with a width 10 times the +x-resolution of the symbol.

+ + + + + + + +
+

bound symbol

+
+

boxed symbol

+
+



+

+

3.7 +Using colour

+

The default colours of a symbol are a +black symbol on a white background. Zint allows you to change this. +The -r switch allows the default colours to be inverted so that a +white symbol is shown on a black background. For example the command

+

zint +-r -d 'This'

+

gives an inverted Code 128 symbol. This +is not practical for most symbologies but white-on-black is allowed +by the Data Matrix symbology specification.

+

For more specific needs the foreground +and background colours can be specified using the --fg= and --bg= +options followed by a number in RGB hexadecimal notation (the same +system used in HTML). For example the command +

+

zint +--fg=004700 -d 'This'

+

alters the symbol to a dark green as +shown below.

+ + + + + + + +
+

symbol with green ink

+
+

symbol with pink paper

+
+



+

+

3.8 +Other options

+

Additional options are available which +are specific to certain symbologies. These may, for example, control +the quantity of error correction data or the size of the symbol. +These options are discussed in section 5 of this guide.

+



+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Installation

+
+

 

+
+

Using the API

+
+



+

+ + \ No newline at end of file diff --git a/docs/gplv3-127x51.png b/docs/gplv3-127x51.png new file mode 100644 index 00000000..fe375326 Binary files /dev/null and b/docs/gplv3-127x51.png differ diff --git a/docs/green.png b/docs/green.png new file mode 100644 index 00000000..410d215a Binary files /dev/null and b/docs/green.png differ diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 00000000..1cfdabee --- /dev/null +++ b/docs/index.html @@ -0,0 +1,317 @@ + + + + + Zint Barcode Generator + + + + + + +

Zint Barcode Generator

+

by Robin Stuart

+

version 1.6, 22nd April 2008

+

This document is a guide to Zint, the libzint library and +the barcode symbologies supported by them.

+
+
+
Table of Contents +
+ 1. Introduction +
+ 2. Installing Zint +
+
+ 2.1 Installing the Back End +
+ 2.2 Installing the Front End +
+ 2.3 Testing the Installation +
+
+ 3. Using the Front End +
+
+ 3.1 Inputting Data +
+ 3.2 Directing Output +
+ 3.3 Selecting Barcode Type +
+ 3.4 Adjusting Height +
+ 3.5 Adjusting Whitespace +
+ 3.6 Adding Boundary Bars and Boxes +
+ 3.7 Using Colour +
+ 3.8 Other Options +
+
+ 4. Using the API +
+
+ 4.1 Creating and Deleting Symbols +
+ 4.2 Encoding and Saving to File +
+ 4.3 Setting Options +
+ 4.4 Handling Errors +
+ 4.5 Specifying a Symbology +
+ 4.6 Adding Boxes and Boundary Bars +
+
+ 5. Types of Symbol +
+
+ 5.1 One-Dimensional Symbols +
+
+ 5.1.1 Code 11 +
+ 5.1.2 Code 2 of 5 +
+
+ 5.1.2.1 Standard Code 2 of 5 +
+ 5.1.2.2 IATA Code 2 of 5 +
+ 5.1.2.3 Industrial 2 of 5 +
+ 5.1.2.4 Interleaved Code 2 of 5 +
+ 5.1.2.5 Code 2 of 5 Data Logic +
+ 5.1.2.6 ITF-14 +
+ 5.1.2.7 Deutche Post Leitcode +
+ 5.1.2.8 Deutche Post Identcode +
+
+ 5.1.3 Universal Product Code (EN 797) +
+
+ 5.1.3.1 UPC version A +
+ 5.1.3.2 UPC version E +
+
+ 5.1.4 European Article Number (EN 797) +
+
+ 5.1.4.1 EAN-2, EAN-5, EAN-8 and EAN-13 +
+ 5.1.4.2 SBN, ISBN and ISBN-13 +
+
+ 5.1.5 Plessey +
+ 5.1.6 MSI Plessey +
+ 5.1.7 Telepen +
+
+ 5.1.7.1 Telepen Alpha +
+ 5.1.7.2 Telepen Numeric +
+
+ 5.1.8 Code 39 +
+
+ 5.1.8.1 Standard Code 39 (ISO + 16388) +
+ 5.1.8.2 Extended Code 39 +
+ 5.1.8.3 Code 93 +
+ 5.1.8.4 PZN +
+ 5.1.8.5 LOGMARS +
+
+ 5.1.9 Codabar (EN 798) +
+ 5.1.10 Pharmacode +
+ 5.1.11 Code 128 +
+
+ 5.1.11.1 Standard Code 128 + (ISO 15417) +
+ 5.1.11.2 Code 128 subset B +
+ 5.1.11.3 EAN-128 +
+ 5.1.11.4 NVE-18 +
+
+ 5.1.12 GS1 DataBar (ISO 24724) +
+
+ 5.1.12.1 DataBar-14 and DataBar-14 + Truncated
+ 5.1.12.2 DataBar Limited
+ 5.1.12.3 DataBar Expanded
+
+
+ 5.2 Stacked Symbologies +
+
+ 5.2.1 Basic Symbol Stacking +
+ 5.2.2 Code 16k (EN 12323) +
+ 5.2.3 PDF417 (ISO 15438) +
+ 5.2.4 Compact PDF417 +
+ 5.2.5 MicroPDF417 (ISO 24728) +
+ 5.2.6 GS1 DataBar-14 Stacked + (ISO 24724)
+ 5.2.7 GS1 DataBar-14 Stacked + Omnidirectional (ISO 24724)
+ 5.2.8 GS1 DataBar Expanded + Stacked (ISO 24724) +
+
+ 5.3 Composite Symbols (ISO 24723) +
+
+ 5.3.1 CC-A +
+ 5.3.2 CC-B +
+ 5.3.3 CC-C +
+
+ 5.4 Two-Track Symbologies +
+
+ 5.4.1 Two-Track Pharmacode +
+ 5.4.2 PostNet +
+ 5.4.3 PLANET +
+
+ 5.5 4-State Postal Codes +
+
+ 5.5.1 Australia Post 4-State + Symbols +
+
+ 5.5.1.1 Customer Barcodes +
+ 5.5.1.2 Reply Paid Barcode +
+ 5.5.1.3 Routing Barcode +
+ 5.5.1.4 Redirect Barcode +
+
+ 5.5.2 Royal Mail 4-State Country + Code (RM4SCC) +
+ 5.5.3 USPS OneCode +
+
+ 5.6 Two-Dimensional Symbols +
+
+ 5.6.1 Data Matrix (ISO 16022) +
+ 5.6.2 QR Code (ISO 18004) +
+ 5.6.3 Maxicode (ISO 16023)
+
+ 5.7 Other Barcode-Like Markings +
+
+ 5.7.1 Facing Identification Mark (FIM) +
+ 5.7.2 Flattermarken +
+
+
+ 6 Legal and Version Information +
+
+ 6.1 License +
+ 6.2 Patent Issues +
+ 6.3 Version Information +
+ 6.4 Sources of Information +
+ 6.5 Standard Compliance +
+
+ A Appendix A: Character Encoding +
+
+ A.1 ASCII Standard +
+ A.2 Latin Alphabet No 1 (ISO 8859-1) +
+
+ B Appendix B: Three Digit Country Codes (ISO + 3166) +
+ C Appendix C: GS1 General Specification +
+
+ C.1 Application Identifiers +
+ C.2 Fixed Length Fields +
+
+
+ + + + + + + + + + + +
+

 

+
+

 

+
+

Next

+
+

 

+
+

 

+
+

Introduction

+
+ + \ No newline at end of file diff --git a/docs/installing.html b/docs/installing.html new file mode 100644 index 00000000..9c5bdaa1 --- /dev/null +++ b/docs/installing.html @@ -0,0 +1,125 @@ + + + + + Installing Zint + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

2. Installing Zint

+

These instructions relate to installing Zint on a GNU/Linux +machine but should be the same or similar for other POSIX compliant +systems (including UNIX and BSD based systems). Installation on +Windows or MacOS based system should be possible but is not covered +here.

+

Zint is currently only available as source code. First download +the source code .tar.gz file from SourceForge +and unpack it. The package consists of two distinct parts: a front +end which provides a command line interface, and a back end +which provides an API which allows developers to integrate encoding +into their own project. You will notice that the sorce code is +suitably arranged into frontend and backend folders. The front end +requires the back end to be installed, so the back end should be +installed first.

+

2.1 Installing the back end

+

The Zint back end, libzint, requires the libpng and libz +libraries. The latest version of these libraries is available from +http://www.libpng.org/pub/png/libpng.html. +Install these first before trying to install Zint. In addition, if +you require QR Code support, Zint uses libqrencode which is +available from +http://megaui.net/fukuchi/works/qrencode/index.en.html. +If you don't need QR Code support this can be disabled during +compilation.

+

To install libzint with QR Code support +follow these steps

+

cd +backend
make
make install

+

If you do not want QR Code support use +the following steps

+

cd +backend
make libzint_noqr
make install

+



+

+

2.2 +Installing the front end

+

To install the front end follow these +steps

+

cd +frontend
make
make install

+



+

+

2.3 +Testing the Installation

+

To test that the installation has been +sucessful a shell script is included in the frontend folder. To run +the test type

+

./test.sh

+

This should create numerous files +showing the many modes of operation which are available from Zint. If +you get the following message...

+

zint: +error while loading shared libraries: libzint.so: cannot open shared +object file: No such file or directory

+

try the following as root:

+

ldconfig

+



+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Introduction

+
+

 

+
+

Using the Front End

+
+



+

+ + \ No newline at end of file diff --git a/docs/introduction.html b/docs/introduction.html new file mode 100644 index 00000000..fd6c9e09 --- /dev/null +++ b/docs/introduction.html @@ -0,0 +1,97 @@ + + + + + Introduction + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

1. Introduction

+

Zint is an open source barcode generator which allows you to +encode data in over 30 types of barcode symbol. In this documentation +a barcode encoding method is termed a symbology and the +resulting barcode image is termed a symbol. The symbologies +currently supported by Zint are: [1]

+

Code 11, Standard Code 2 of 5, IATA Code 2 of 5, Industrial Code 2 +of 5, Interleaved Code 2 of 5, Code 2 of 5 Data Logic, ITF-14, +Deutche Post Leitcode, Deutche Post Identcode, UPC-A, UPC-E, EAN-2, +EAN-5, EAN-8, EAN-13, UK Plessey, MSI Plessey, Telepen Alpha, Telepen +Numeric, Code 39, Extended Code 39, Code 93, PZN, LOGMARS, Codabar, +Pharmacode, Code 128, GS1-128, NVE-18, GS1 DataBar, DataBar-14, +DataBar Limited, DataBar Extended, Code 16k, PDF417, MicroPDF417, +Two-Track Pharmacode, PostNet, PLANET, Australia Post 4-State +Symbols, RM4SCC, USPS OneCode, Data Matrix, QR Code, Maxicode, +Composite Symbols, FIM and Flattermarken.

+

In addition Zint also provides barcode stacking, colour options +and a verification stage for SBN, ISBN and ISBN-13 data. The aim of +the Zint project is to provide an open source API for encoding all +public domain barcode symbologies.

+

This document is a guide to the Zint API and front end program as +well as a guide to the barcode technologies which they make +available. Please remember that, although a great deal of care has +been taken to de-bug Zint, many of the symbologies have not been +tested with commercial barcode scanners so you are recommended to +test that symbols decode properly before you use them.

+



+

+

[1] Note that some of these symbologies have more than one name, +and that some of the names given in this list are not the official +names for the symbologies referred to.

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Zint Barcode Generator

+
+

 

+
+

Installing Zint

+
+



+

+ + \ No newline at end of file diff --git a/docs/itf14.png b/docs/itf14.png new file mode 100644 index 00000000..d39be574 Binary files /dev/null and b/docs/itf14.png differ diff --git a/docs/legal.html b/docs/legal.html new file mode 100644 index 00000000..95636201 --- /dev/null +++ b/docs/legal.html @@ -0,0 +1,265 @@ + + + + + Legal and Version Information + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

6. Legal and Version Information

+

6.1 License

+

Zint +and libzint are Copyright © 2008 Robin Stuart and are +distributed under the terms of the GNU +General Public License version 3 [1]. See the file COPYING +for more information. The following terms form part of the GPL:

+

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 the Free Software Foundation; either +version 3 of the License, or (at your option) any later version.

+

This program is distributed in the hope that +it will be useful, but WITHOUT ANY WARRANTY; without even the implied +warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +the GNU General Public License for more details.

+

Data Matrix code is Copyright © 2004 Adrian Kennard, Andrews +& Arnold Ltd and © 2006 Stefan Schmidt, used under the terms +of the GNU General Public Licence.

+

Reed-Solomon code is Copyright © 2004 Cliff Hones, used under +the terms of the GNU General Public Licence.

+

Portions of GS1 DataBar and Composite Symbology code are Copyright +© 2006 ISO/BSI Global and used with permission.

+

Portions of OneCode code is © 2006 United States Postal +Service. This is indicated where appropriate in the source code and +is used on the understanding that this code has been released to the +public domain and that such use is intended by the copyright holder.

+

libqrencode is Copyright © 2006, 2007, 2008 Kentaro +Fukuchi and is released under the terms of the GNU General Public +Licence.

+

QR Code is a registered trademark of Denso Corp. of Kariya, Japan.

+

6.2 Patent Issues

+

All of the code in Zint is developed using information in the +public domain, usually freely available on the Internet. Some of the +techniques used may be subject to patents and other intellectual +property legislation. It is my belief that any patents involved in +the technology underlying symbologies utilised by Zint are +'unadopted', that is the holder does not object to their methods +being used. If, however, you are a patent holder or hold any other +intellectual property rights on the methods used by Zint or the +symbologies which Zint generates, and do not want Zint to continue to +support your symbology then please contact me and I will update the +code to accommodate your wishes at the soonest opportunity.

+

Any methods patented or owned by third parties or trademarks or +registered trademarks used within Zint or in this document are and +remain the property of their respective owners and do not indicate +endorsement or affiliation with those owners, companies or +organisations.

+

6.3 Version Information

+

v0.1 - (as Zebar) Draws UPC-A. UPC-E, EAN-8, EAN-13, +Interlaced 2 of 5, Codabar, Code 39, Extended Code 39 and Code 93 +barcodes and Add-on codes EAN-2 and EAN-5 without parity. 13/11/2006

+

v0.2 - Added Code 128 (which is now the default), Code 11, Code 2 +of 5, Add-on codes EAN-2 and EAN-5 parity and MSI/Plessey without +check digit. 12/12/2006

+

v0.3 - Added MSI/Plessey Mod 10 check and 2 x Mod 10 check +options, Telepen ASCII and Telepen numeric, Postnet, RM4SCC. Code has +been tidied up quite a bit. Bind option added. 30/12/2006

+

v0.4 - Added barcode stacking (now stacks up to 16 barcodes) and +Code16k (stub). 15/1/2007

+

v0.5 - Added Australia Post 4-State Barcodes and Pharmacode (1 and +2 track). 4-state codes now draw with correct height/width ratio. +28/2/2007

+

v0.6 - Added Plessey and some derivative codes (EAN-128, Code 128 +subset B, Auspost Reply, Auspost Routing, Auspost Redirect, ITF-14). +Tidied up code again: separated symbologies into more files and put +all lookup tables into arrays (much reducing the amount of code, +especially for Code 39e and Code 93). Errors now output to stderr. +Added proper input verification. Distribution now packs with this +HTML page instead of separate README. Outputs to PNG. Outputs colour. +User variable whitespace and border width. Box option. Fixed EAN +add-on bug. Added whitespace and height options. Project name changed +to Zint to avoid conflict with extant trade name. Added escape +character input. 1/4/2007

+

v1.0 - Corrected problem with escape character codes. Supports +PDF417. This completes the list of features I originally wanted (plus +a few more), hence skip to version 1.0. 20/4/2007

+

v1.1 - Added more derivatives (Code 2 of 5 Matrix, IATA and Data +Logic, Truncated PDF417, Deutsche Post Leitcode and Identcode, +Pharmazentralnummer, Planet) and Flattermarken. Tidied up 2 of 5 +code. 26/4/2007

+

v1.2 - Supports Data Matrix (by absorption of IEC16022 code by +Stefan Schmidt et al). Added reverse colours, FIM, MSI/Plessey Modulo +11 and Modulo 11/10. Corrected Code 16k check digit calculation. +28/5/2007

+

v1.3 - Supports USPS OneCode and LOGMARS. Brought all usage +information into one User Manual document. 13/6/2007

+

v1.4 - Added NVE-18 support. Corrected some problems with +compilation and input verification. Added zint.1 man page. Command +line option handling now uses getopt(), and all the switches have +changed. Added --font option. 20/6/2007

+

v1.5 - Pulled everything together to make an API. Corrected errors +with EAN-13, PDF417 and LOGMARS. Added EPS output. Added QR Code +support using libqrencode. Corrected ISBN verification error. +Re-compiled documentation in HTML form. Put in place proper error +handling routines. --font option removed. Encoding is now done with a +restructured zint_symbol structure. Added make install option and +optional QR Code support to Makefile. Corrected minor problem with +4-State Codes. Restructured code into fewer source code files. Added +MicroPDF417 support. 12/8/2007

+

v1.5.1 - Added formatting code to EPS output of EAN and UPC +symbols according to EN 797:1996. Checked against and, where +appropriate, altered or corrected to comply with ISO 16388 and ISO +15417 including Latin-1 support. Altered default image settings, +added automatic ITF border. Corrected error with USPS OneCode. Tidied +up Code 39 quite a bit, added Mod 43 options. 3/9/2007

+

v1.5.2 - Added extended ASCII support to Code 16k. Corrected Code +128 error. Added Maxicode support by integrating code by John Lien. +26/9/2007

+

v1.5.3 - Made huge corrections to Maxicode support by removing and +re-writing much of John's code. Maxicode now supports extended ASCII +and modes 4, 5 and 6. 10/10/2007

+

v1.5.4 - Added GS1 DataBar (Reduced Space Symbology) support. +26/11/2007

+

v1.5.5 - Added composite symbology support. Corrected errors with +GS1-128 and PDF417/MicroPDF417 byte processing. Transferred licence +to GPL version 3. 9/3/2008

+

v1.6 – Data Matrix, Maxicode and Australia Post now use common +Reed-Solomon functions – this also fixes a bug in Maxicode error +correction and replaces the last of the Lien code. Added PNG output +for Maxicode symbols. Removed some useless code. Updated QR support +for libqrencode v2.0.0. 22/4/2008

+

6.4 Sources of Information

+

Below is a list of some of the sources used in rough chronological +order:

+

Nick +Johnson's Barcode Specifications

+

Bar Code +1 Specification Source Page

+

SB Electronic Systems +Telepen website

+

Pharmacode specifications from Laetus

+

Morovia +RM4SCC specification

+

Austalia Post's 'A Guide +to Printing the 4-State Barcode' and bcsample source code

+

Plessey algorithm from GNU-Barcode +v0.98 by Leonid A. Broukhis

+

GS1 +General Specifications v 7.0

+

PNG: The Definitive +Guide and wpng source code by Greg Reolofs

+

PDF417 specification and pdf417 source code by Grand +Zebu

+

Barcode Reference, TBarCode/X User Documentation and TBarCode/X +demonstration program from Tec-It

+

IEC16022 +source code by Stefan Schmidt et al

+

United States +Postal Service Specification USPS-B-3200

+

Adobe Systems Incorporated Encapsulated PostScript File Format +Specification

+

BSI Online Library

+

6.5 Standard Compliance

+

Zint was developed to provide compliance with the following +British and international standards: +

+

BS EN 797:1996 Bar coding – Symbology specifications - 'EAN/UPC'

+

BS EN 798:1996 Bar coding – Symbology specifications - “Codabar”

+

BS ISO/IEC 12323:2005 AIDC technologies – Symbology +specifications – Code 16K

+

BS ISO/IEC 15417:2007 Information technology – Automatic +identification and data capture techniques – Code 128 bar code +symbology specification

+

BS ISO/IEC 15438:2006 Information technology – Automatic +identification and data capture techniques – PDF417 bar code +symbology specification

+

BS ISO/IEC 16022:2006 Information technology – Automatic +identification and data capture techniques – Data Matrix bar code +symbology specification

+

BS ISO/IEC 16023:2000 Information technology – International +symbology specification - Maxicode

+

BS ISO/IEC 16388:2007 Information technology – Automatic +identification and data capture techniques – Code 39 bar code +symbology specification

+

BS ISO/IEC 18004:2006 Information technology – Automatic +identification and data capture techniques – QR Code 2005 bar code +symbology specification

+

BS ISO/IEC 24723:2006 Information technology – Automatic +identification and data capture techniques – EAN.UCC Composite bar +code symbology specification

+

BS ISO/IEC 24724:2006 Information technology – Automatic +identification and data capture techniques – Reduced Space +Symbology (RSS) bar code symbology specification

+

BS ISO/IEC 24728:2006 Information technology – Automatic +identification and data capture techniques – MicroPDF417 bar code +symbology specification

+



+

+

[1] Some of the third party code in this library was +distributed under the terms of version +2 of the GNU Public Licence with the option of using a later +version. For the purpose of Zint as a whole package I have chosen to +take this option and redistribute the code under version 3 of the +licence. This decision takes effect from version 1.5.5 of the code +and does not affect the licence of previously released versions of +the code. Some third party source code files, however, are included +in Zint as verbatim (unaltered) copies and therefore the right to +change the license terms remains exclusively with the original +copyright holder. R. Stuart 9/3/2008

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Other Markings

+
+

 

+
+

Appendix A

+
+



+

+ + \ No newline at end of file diff --git a/docs/markings.html b/docs/markings.html new file mode 100644 index 00000000..e04ed3ba --- /dev/null +++ b/docs/markings.html @@ -0,0 +1,138 @@ + + + + + Other Markings + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

5.7 Other Barcode-Like Markings

+

5.7.1. Facing Identification +Mark (FIM)

+

Used by the United States Postal Service (USPS), the +FIM symbology is used to assist automated mail processing. There are +only 4 valid symbols which can be generated using the characters A-D +as shown in the table below.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Code Letter

+
+

Usage

+
+

A

+
+

Used for courtesy reply mail and metered reply + mail with a pre-printed PostNet symbol.

+
+

B

+
+

Used for business reply mail without a + pre-printed zip code.

+
+

C

+
+

Used for business reply mail with a pre-printed + zip code.

+
+

D

+
+

Used for Information Based Indicia (IBI) + postage.

+
+
+



+

+




+

+

5.7.2 Flattermarken

+

Used for the recognition of page sequences in +print-shops, the Flattermarken is not a true barcode symbol and +requires precise knowledge of the position of the mark on the page. +The Flattermarken system can encode any length numeric data and does +not include a check digit.


+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

4-State Codes

+
+

 

+
+

Legal

+
+



+

+ + \ No newline at end of file diff --git a/docs/matrix.png b/docs/matrix.png new file mode 100644 index 00000000..f6d800c8 Binary files /dev/null and b/docs/matrix.png differ diff --git a/docs/maxicode.png b/docs/maxicode.png new file mode 100644 index 00000000..efd4c392 Binary files /dev/null and b/docs/maxicode.png differ diff --git a/docs/micropdf.png b/docs/micropdf.png new file mode 100644 index 00000000..7a2a1598 Binary files /dev/null and b/docs/micropdf.png differ diff --git a/docs/msi.png b/docs/msi.png new file mode 100644 index 00000000..90e5abc1 Binary files /dev/null and b/docs/msi.png differ diff --git a/docs/onecode.png b/docs/onecode.png new file mode 100644 index 00000000..3b4f3c8c Binary files /dev/null and b/docs/onecode.png differ diff --git a/docs/onedim.html b/docs/onedim.html new file mode 100644 index 00000000..13319c40 --- /dev/null +++ b/docs/onedim.html @@ -0,0 +1,413 @@ + + + + + One-Dimensional Symbols + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

5.1 One-Dimensional Symbols

+

One-Dimensional Symbols are what most people associate with the +term barcode. They consist of a number of bars and a number of +spaces of differing widths.

+



+

+

5.1.1 Code 11

+

Developed by Intermec in 1977, Code 11 is similar to Code 2 of 5 +Matrix and is primarily used in telecommunications. The symbol can +encode any length string consisting of the digits 0-9 and the dash +character (-). One modulo-11 check digit is calculated.

+




+

+

5.1.2 Code 2 of 5

+

Code 2 of 5 is a family of one-dimensional symbols, 8 of which are +supported by Zint.

+

5.1.2.1 Standard Code 2 +of 5

+

Also known as Code 2 of 5 Matrix is a self-checking code used in +industrial applications and photo development. Standard Code 2 of 5 +will encode any length numeric input (digits 0-9).

+

5.1.2.2 IATA Code 2 of 5

+

Used for baggage handling in the air-transport industry by the +International Air Transport Agency, this self-checking code will +encode any length numeric input (digits 0-9) and does not include a +check digit.

+

5.1.2.3 Industrial Code 2 of 5

+

Industrial Code 2 of 5 can encode any length numeric input (digits +0-9) and does not include a check digit.

+

5.1.2.4 Interleaved Code 2 +of 5

+

This self-checking symbology encodes pairs of numbers, and so can +only encode an even number of digits (0-9). If an odd number of +digits is entered a leading zero is added by Zint. No check digit is +added.

+

5.1.2.5 Code 2 of 5 Data +Logic

+

Data Logic is a proprietary variation of Standard Code 2 of 5. +Data Logic does not include a check digit and can encode any length +numeric input (digits 0-9).

+

5.1.2.6 ITF-14

+

ITF-14, also known as UPC Shipping Container Symbol, Case Code and +EAN-14, is based on Interleaved Code 2 of 5 and requires a 13 digit +numeric input (digits 0-9). One modulo-10 check digit is calculated.

+

5.1.2.7 Deutche Post Leitcode

+

Leitcode is based on Interleaved Code 2 of 5 and is used by +Deutche Post for mailing purposes. Leitcode requires a 13-digit +numerical input and includes a check digit.

+

5.1.2.8 Deutche Post +Identcode

+

Identcode is based on Interleaved Code 2 of 5 and is used by +Deutche Post for mailing purposes. Identcode requires an 11-digit +numerical input and includes a check digit.

+




+

+

5.1.3 Universal Product Code (EN +797)

+

5.1.3.1 UPC Version A

+

UPC-A is used in the United States for retail applications. The +symbol requires an 11 digit article number. The check digit is +calculated by Zint. In addition EAN-2 and EAN-5 add-on symbols can be +added using the + character. For example, to draw a UPC-A symbol with +the data 72527270270 with an EAN-5 add-on showing the data 12345 use +the command:

+

zint --barcode=34 -d +72527270270+12345

+

or encode a data string with the + character included: +

+

my_symbol->symbology += BARCODE_UPCA;
error = ZBarcode_Encode_and_Print(my_symbol, +"72527270270+12345");

+

5.1.3.2 UPC Version E

+

UPC-E is a zero-compressed version of UPC-A developed for smaller +packages. The code requires a 6 digit article number (digits 0-9). +The check digit is calculated by Zint. EAN-2 and EAN-5 add-on symbols +can be added using the + character as with UPC-A. In addition Zint +also supports Number System 1 encoding by entering a 7-digit article +number stating with the digit 1. For example:

+

zint --barcode=37 -d +1123456

+

or

+

my_symbol->symbology += BARCODE_UPCE;
error = ZBarcode_Encode_and_Print(my_symbol, +"1123456");

+




+

+

5.1.4 European Article Number +(EN 797)

+

5.1.5.1 EAN-2, EAN-5, EAN-8 and +EAN-13

+

The EAN system is used in retail across Europe and includes +standards for EAN-2 and EAN-5 add-on codes, EAN-8 and EAN-13 which +encode 2, 5, 7 or 12 digit numbers respectively. Zint will decide +which symbology to use depending on the length of the input data. In +addition EAN-2 and EAN-5 add-on symbols can be added using the + +symbol as with UPC symbols. For example

+

zint --barcode=13 -d +54321

+

will encode a stand-alone EAN-5, whereas

+

zint --barcode=13 -d +7432365+54321

+

will encode an EAN-8 symbol with an EAN-5 add-on. As before these +results can be achieved using the API:

+

my_symbol->symbology += BARCODE_EANX
error = ZBarcode_Encode_and_Print(my_symbol, +"54321");
error = ZBarcode_Encode_and_Print(my_symbol, +"7432365+54321");

+

All of the EAN symbols include check data which is added by Zint.

+

5.1.4.2 SBN, ISBN and ISBN-13

+

EAN-13 symbols (also known as Bookland EAN-13) can also be +produced from 9-digit SBN, 10-digit ISBN or 13-digit ISBN-13 data. +The relevant check digit needs to be present in the input data and +will be verified before the symbol is generated. In addition EAN-2 +and EAN-5 add-on symbols can be added using the + symbol as with UPC +symbols.

+




+

+

5.1.5 Plessey

+

Also known as Plessey Code, this symbology was developed by the +Plessey Company Ltd. in the UK. The symbol can encode any length data +consisting of digits (0-9) or letters A-F and includes a CRC check +digit.

+




+

+

5.1.6 MSI Plessey

+

Based on Plessey and developed by MSE Data Corporation, MSI +Plessey is available with a range of check digit options. Any length +numeric (digits 0-9) input can be encoded. The table below shows the +options available:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Symbology ID

+
+

Symbology Name

+
+

Check Digits

+
+

47

+
+

BARCODE_MSI_PLESSEY

+
+

None

+
+

101

+
+

BARCODE_MSI_10

+
+

Modulo-10

+
+

102

+
+

BARCODE_MSI_10_10

+
+

Modulo-10 & Modulo-10

+
+

103

+
+

BARCODE_MSI_11

+
+

Modulo-11

+
+

104

+
+

BARCODE_MSI_11_10

+
+

Modulo-11 & Modulo-10

+
+
+



+

+




+

+

5.1.7 Telepen

+

5.1.7.1 Telepen Alpha

+

Telepen Alpha was developed by SB Electronic Systems Limited and +can encode any length of ASCII text input. Telepen includes a +modulo-127 check digit.

+

5.1.7.2 Telepen Numeric

+

Telepen Numeric allows compression of purely numeric data into a +Telepen symbol and includes a modulo-127 check digit.

+




+

+

5.1.8 Code 39

+

5.1.8.1 Standard Code 39 +(ISO 16388)

+

Standard Code 39 was developed in 1974 by Intermec. Input data can +be of any length and supports the characters 0-9, A-Z, dash (-), full +stop (.), space, asterisk (*), dollar ($), slash (/), plus (+) and +percent (%). The original standard (symbology 8) does not require a +check digit but a modulo-43 check digit can be added if required +(symbology 105).

+

5.1.8.2 Extended Code 39

+

Also known as Code 39e and Code39+, this symbology expands on +Standard Code 39 to provide support to the full ASCII character set. +The original standard (symbology 9) does not require a check digit +but a modulo-43 check digit can be added if required (symbology 106).

+

5.1.8.3 Code 93

+

A variation of Extended Code 39, Code 93 also supports full ASCII +text. Two check digits are added.

+

5.1.8.4 PZN

+

PZN is a Code 39 based symbology used by the pharmaceutical +industry in Germany. PZN encodes a 6 digit number and includes a +modulo-10 check digit.

+

5.1.8.5 LOGMARS

+

LOGMARS (Logistics Applications of Automated Marking and Reading +Symbols) is a variation of the Code 39 symbology used by the US +Department of Defence. LOGMARS encodes the same character set as +Standard Code 39 and adds a modulo-43 check digit.

+




+

+

5.1.9 Codabar (EN 798)

+

Also known as NW-7, Monarch, ABC Codabar, USD-4, Ames Code and +Code 27, this symbology was developed in 1972 by Monarch Marketing +Systems for retail purposes. The American Blood Commission adopted +Codabar in 1977 as the standard symbology for blood identification. +Codabar can encode any length string starting and ending with the +letters A-D and containing between these letters the numbers 0-9, +dash (-), dollar ($), colon (:), slash (/), full stop (.) or plus +(+). No check digit is generated.

+




+

+

5.1.10 Pharmacode

+

Developed by Laetus, Pharmacode One-Track is used for the +identification of pharmaceuticals. The symbology is able to encode +whole numbers between 3 and 131070.

+




+

+

5.1.11 Code 128

+

5.1.11.1 Standard Code +128 (ISO 15417)

+

One of the most widely used one-dimensional barcode symbologies, +Code 128 was developed in 1981 by Computer Identics. This symbology +supports full ASCII text and uses a three-mode system to compress the +data into a smaller symbol. Zint automatically switches between modes +and adds a modulo-103 check digit. Code 128 is the default barcode +symbology used by Zint. In addition Zint supports the encoding of +Latin-1 (non-English) characters in Code 128 symbols. The Latin-1 +character set is shown in Appendix A.

+

5.1.11.2 Code 128 Subset B

+

It is sometimes advantageous to stop Code 128 from using subset +mode C which compresses numerical data. The BARCODE_CODE128B +option suppresses mode C in favour of mode B.

+

5.1.11.3 GS1-128

+

A variation of Code 128 also known as UCC/EAN-128, this symbology +is defined by the GS1 General Specification. +Application Identifiers (AIs) should be entered using [square +brackets] notation. These will be converted to (round brackets) for +the human readable text. This will allow (round brackets) to be used +in the data strings to be encoded. Fixed length data should be +entered at the appropriate length for correct encoding - this is not +checked by Zint and incorrect length data will result in a symbol +which does not read correctly (see Appendix C). +GS1-128 does not support extended ASCII characters. Check digits for +GTIN data (AI 01) are not generated and need to be included in input +data. The following is an example of a valid GS1-128 input:

+

zint +--barcode=16 -d "[01]98898765432106[3202]012345[15]991231"

+

5.1.11.4 NVE-18

+

A variation of Code 128 the Nummber der Versandeinheit standard +includes both modulo-10 and modulo-103 check digits. NVE-18 requires +a 17 digit numerical input.

+




+

+

5.1.12 GS1 +DataBar (ISO 24724)

+

Also known as RSS (Reduced Spaced Symbology) these +symbols are due to replace GS1-128 symbols starting in 2010 in +accordance with the GS1 +General Specification. If a GS1 DataBar symbol is to be printed +with a 2D component as specified in ISO 24723 set option_1 += 2 or use the option --mode=2 +at the command prompt. See the section Composite +Symbols to generate DataBar symbols with 2D components.

+

5.1.12.1 DataBar-14 +and DataBar-14 Truncated

+

Also known as +RSS-14 the DataBar-14 encodes a 13 digit item code. A check digit and +application identifier of (01) are added by Zint. Note that for full +standard compliance symbol height should be greater than or equal to +33 modules. For DataBar-14 Truncated set the symbol height to a +minimum of 13.

+

5.1.12.2 DataBar +Limited

+

Also known as +RSS Limited the DataBar Limited symbol also encodes 13 digit item +codes and can be used in the same way as DataBar-14 above. DataBar +Limited, however, is limited to data starting with digits 0 and 1 +(i.e. numbers in the range 0 to 1999999999999). As with DataBar-14 a +check digit and application identifier of (01) are added by Zint.

+

5.1.12.3 DataBar +Expanded

+

Also +known as RSS Expanded this is a variable length symbology capable of +encoding data from a number of AIs in a single symbol. AIs should be +encased in [square brackets] in the input data. This will be +converted to (rounded brackets) before it is included in the human +readable text attached to the symbol. This method allows the +inclusion of rounded brackets in the data to be encoded. GTIN data +(AI 01) should also include the check digit data as this is not +calculated by Zint when this symbology is encoded. Fixed +length data should be entered at the appropriate length for correct +encoding - this is not checked by Zint and incorrect length data will +result in a symbol which does not read correctly (see Appendix +C). The +following is an example of a valid DataBar Expanded input

+

zint +--barcode=31 -d "[01]98898765432106[3202]012345[15]991231"

+




+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Types of Symbol

+
+

 

+
+

Stacked Symbols

+
+



+

+ + \ No newline at end of file diff --git a/docs/pdf417.png b/docs/pdf417.png new file mode 100644 index 00000000..2e1a192d Binary files /dev/null and b/docs/pdf417.png differ diff --git a/docs/pharma.png b/docs/pharma.png new file mode 100644 index 00000000..62d9497b Binary files /dev/null and b/docs/pharma.png differ diff --git a/docs/pharma2.png b/docs/pharma2.png new file mode 100644 index 00000000..70493b04 Binary files /dev/null and b/docs/pharma2.png differ diff --git a/docs/pink.png b/docs/pink.png new file mode 100644 index 00000000..e7a619e6 Binary files /dev/null and b/docs/pink.png differ diff --git a/docs/planet.png b/docs/planet.png new file mode 100644 index 00000000..02eae72b Binary files /dev/null and b/docs/planet.png differ diff --git a/docs/plessey.png b/docs/plessey.png new file mode 100644 index 00000000..e3f4504d Binary files /dev/null and b/docs/plessey.png differ diff --git a/docs/postnet.png b/docs/postnet.png new file mode 100644 index 00000000..6c9f8143 Binary files /dev/null and b/docs/postnet.png differ diff --git a/docs/qr.png b/docs/qr.png new file mode 100644 index 00000000..f55bed96 Binary files /dev/null and b/docs/qr.png differ diff --git a/docs/rm4scc.png b/docs/rm4scc.png new file mode 100644 index 00000000..7490be09 Binary files /dev/null and b/docs/rm4scc.png differ diff --git a/docs/stacked.html b/docs/stacked.html new file mode 100644 index 00000000..77c93bb9 --- /dev/null +++ b/docs/stacked.html @@ -0,0 +1,172 @@ + + + + + Stacked Symbols + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

5.2 Stacked Symbologies

+

5.2.1 Basic Symbol +Stacking

+

An early innovation to get more information into a +symbol, used primarily in the vehicle industry, is to simply stack +one-dimensional codes on top of each other. This can be achieved at +the command prompt by giving more than one set of input data. For +example

+

zint -d +'This' -d 'That'

+

will draw two Code 128 symbols, one on top of the +other. The same result can be achieved using the API by executing the +ZBarcode_Encode() function +more than once on a symbol. For example:

+

my_symbol->symbology += BARCODE_CODE128;
error = ZBarcode_Encode(my_symbol, +"This");
error = ZBarcode_Encode(my_symbol, +"That");
error = ZBarcode_Print(my_symbol);

+

The example below shows 5 EAN-13 symbols stacked in +this way.

+




+

+

5.2.2 Code 16k +(EN 12323)

+

A more sophisticated method is to use some type of line +indexing which indicates to the barcode reader which order the +symbols should be read. This is demonstrated by Code 16k which uses a +Code128 based system which can stack up to 16 rows in a block. This +gives a maximum data capacity of 77 characters or 154 numerical +digits and includes two modulo-107 check digits. Code 16k also +supports extended ASCII character encoding in the same manner as Code +128.

+




+

+

5.2.3 PDF417 (ISO +15438)

+

Heavily used in the parcel industry, the PDF417 +symbology can encode a vast amount of data into a small space. Zint +supports encoding up to the ISO standard maximum symbol size of 925 +codewords which (at error correction level 0) allows a maximum data +size of 1850 text characters, or 2710 digits. The width of the +generated PDF417 symbol can be specified at the command line using +the --cols switch followed by a number between 1 and 30, and the +amount of check digit information can be specified by using the +--security switch followed by a number between 0 and 8 where the +number of codewords used for check information is determined by +2(value + 1). If using the API these values are assigned +to option_2 and option_1 +respectively. The default level of check information is determined by +the amount of data being encoded. International text support is +provided using the Latin-1 character set as described in Appendix +A.

+




+

+

5.2.4 Compact +PDF417

+

Also known as truncated PDF417. Options are as for +PDF417 above.

+




+

+

5.2.5 +MicroPDF417 (ISO 24728)

+

A variation of the PDF417 standard, MicroPDF417 is +intended for applications where symbol size needs to be kept to a +minimum. 34 pre-defined symbol sizes are available with 1 - 4 columns +and 4 - 44 rows. The maximum size MicroPDF417 symbol can hold 250 +alphanumeric characters or 366 digits. The amount of error correction +used is dependant on symbol size. The number of columns used can be +determined using the --cols +switch or option_2 as with +PDF417.

+




+

+

5.2.6 GS1 +DataBar-14 Stacked (ISO 24724)

+

A stacked variation of the GS1 DataBar-14 symbol +requiring the same input (see section 5.1.12.1). +The height of this symbol is fixed. The data is encoded in two rows +of bars with a central finder pattern. This symbol can be generated +with a two-dimensional component to make a composite +symbol.

+




+

+

5.2.7 GS1 +DataBar-14 Stacked Omnidirectional (ISO 24724)

+

Another variation of the GS1 DataBar-14 symbol +requiring the same input (see section 5.1.12.1). +The data is encoded in two rows of bars with a central finder +pattern. This symbol can be generated with a two-dimensional +component to make a composite symbol.

+




+

+

5.2.8 GS1 +DataBar Expanded Stacked (ISO 24724)

+

A stacked variation of the GS1 DataBar Expanded symbol +for smaller packages. Input is the same as for GS1 DataBar Expanded +(see section 5.1.12.3). In addition +the width of the symbol can be altered using the --cols +switch or option_2. In this +case the number of columns relates to the number of character pairs +on each row of the symbol. For symbols with a 2D component the number +of columns must be at least 2. This symbol can be generated with a +two-dimensional component to make a composite +symbol.

+




+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

One-Dimensional Symbols

+
+

 

+
+

Composite Symbols

+
+



+

+ + \ No newline at end of file diff --git a/docs/stacked.png b/docs/stacked.png new file mode 100644 index 00000000..30fb5806 Binary files /dev/null and b/docs/stacked.png differ diff --git a/docs/symbologies.html b/docs/symbologies.html new file mode 100644 index 00000000..f49b1715 --- /dev/null +++ b/docs/symbologies.html @@ -0,0 +1,183 @@ + + + + + Types of Symbol + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

5. Types of Symbol

+

This section is intended to be a brief +guide to the barcode symbologies supported by Zint. The symbologies +break down easily into groups as shown in the table below. Each group +has a page dedicated to it.

+


+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Symbol Type

+
+

Example Symbol

+
+

Example Symbologies

+
+

One-Dimensional

+
+

+
+

Code + 11, Code 2 of 5, UPC, EAN, Plessey, MSI, Telepen, Code 39, + Codabar, Pharmacode

+
+

Stacked Symbols

+
+

+
+

Code + 16k, PDF417

+
+

Composite Symbols

+
+

+
+

CC-A, CC-B, CC-C

+
+

Two-Track Symbols

+
+

+
+

Two-Track + Pharmacode, PostNet, PLANET

+
+

4-State Codes

+
+

+
+

USPS + OneCode, RM4SCC, Australia Post 4-State Codes

+
+

Two-Dimensional

+
+

+
+

Data + Matrix, QR Code, Maxicode

+
+

Other Markings

+
+

+
+

FIM, + Flattermarken

+
+
+



+

+



+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Using the API

+
+

 

+
+

One-Dimensional Symbols

+
+



+

+ + \ No newline at end of file diff --git a/docs/telepen.png b/docs/telepen.png new file mode 100644 index 00000000..2b309a97 Binary files /dev/null and b/docs/telepen.png differ diff --git a/docs/twodims.html b/docs/twodims.html new file mode 100644 index 00000000..46a541f6 --- /dev/null +++ b/docs/twodims.html @@ -0,0 +1,375 @@ + + + + + Two-Dimensional Symbols + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

5.6 Two-Dimensional Symbols

+

5.6.1 Data Matrix (ISO +16022)

+

Also known as Semacode this symbology can encode a large amount of +data in a small area. Any length ASCII string can be encoded up to +780 characters. Symbol size is determined by the length of the input +data and Reed-Solomon error correction is added.

+




+

+

5.6.2 QR Code (ISO 18004)

+

Also known as Quick Response Code this symbology was developed by +Denso. QR Code support in Zint relies on libqrencode (version +2.0.0) which is available from +http://megaui.net/fukuchi/works/qrencode/index.en.html. +Support for QR Code through libzint means that developers only +need to write handlers for one API which covers QR Code as well as +all of the other code symbologies provided by libzint. Four +levels of error correction are available using the security= +option or setting option_1 as +shown in the following table.

+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Input

+
+

ECC Level

+
+

Error Correction Capacity

+
+

Recovery Capacity

+
+

1

+
+

L (default)

+
+

Approx 20% of symbol

+
+

Approx 7%

+
+

2

+
+

M

+
+

Approx 37% of symbol

+
+

Approx 15%

+
+

3

+
+

Q

+
+

Approx 55% of symbol

+
+

Approx 25%

+
+

4

+
+

H

+
+

Approx 65% of symbol

+
+

Approx 30%

+
+
+
+
+
+
+
+
+



+

+

The size of the symbol can be set by using the vers= +option or setting option_2 to +the QR Code version required (1-40). The maximum capacity of a +(version 40) QR Code symbol is 7089 numeric digits, 4296 alphanumeric +characters or 2953 bytes of data.

+




+

+

5.6.3 Maxicode (ISO 16023)

+

Developed by UPS the Maxicode symbology employs a grid +of hexagons surrounding a 'bulls-eye' finder pattern. This symbology +is designed for the identification of parcels. Zint encodes Maxicode +symbols in Mode 2 or Mode 3 depending on the postcode data entered. +In these modes Maxicode symbols are composed of two parts named the +primary and secondary messages. The primary message consists of a +structured data field which includes various data about the package +being sent, the secondary message usually consists of address data in +a data structure. The format of the primary message is given in the +following table: +

+
+ + + + + + + + + + + + + + + + + + + + + + + +
+

Characters

+
+

Meaning

+
+

1-9

+
+

Postcode data which can consist of up to 9 + digits (for mode 2) or up to 6 alphanumeric characters (for mode + 3). Remaining unused characters should be filled with the SPACE + character (ASCII 32).

+
+

10-12

+
+

Three digit country code according to ISO 3166 + (see Appendix B).

+
+

13-15

+
+

Three digit service code. This depends on your + parcel courier.

+
+
+



+

+

The primary message can be designated at the command +prompt using the --primary= +switch. The secondary message uses the normal data entry method. For +example:

+

zint -o test.eps -b 57 +--primary='999999999840012' -d 'Secondary Message Here'

+

When using the API the primary message must be placed +in the symbol->primary +string. The secondary is entered in the same way as described in +section 4.2.

+

Modes 4 to 6 can be encoded using the --mode= +switch or by setting option_1. +Modes 4 to 6 do not require a primary message. For example:

+

zint -o test.eps -b 57 +--mode=4 -d 'A MaxiCode Message in Mode 4'

+

Mode 6 is reserved for the maintenance of scanner +hardware and should not be used to encode user data. All modes +support extended ASCII characters and number compression. The maximum +length of text which can be placed in a Maxicode symbol depends on +the type of characters used in the text. Example maximum data lengths +are given in the table below:

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Mode

+
+

Maximum Data Length for Capital Letters

+
+

Maximum Data Length for Numeric Digits

+
+

Number of Error Correction Codewords

+
+

2 (secondary only)

+
+

84

+
+

126

+
+

50

+
+

3 (secondary only)

+
+

84

+
+

126

+
+

50

+
+

4

+
+

93

+
+

135

+
+

50

+
+

5

+
+

77

+
+

110

+
+

66

+
+

6

+
+

93

+
+

135

+
+

50

+
+
+



+

+

PLEASE NOTE that due to the unique style of the +Maxicode symbol not all of the options available for other +symbologies are available. Settings for height, whitespace width, +border width and output options will be ignored. Colour options are +available as with other symbologies. PNG output is set at a +resolution of 12 pixels per millimetre (approx 300 dpi) and uses the +methods set out in Annex J of the ISO/IEC standard.

+




+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

4-State Codes

+
+

 

+
+

Markings

+
+



+

+ + \ No newline at end of file diff --git a/docs/twotrack.html b/docs/twotrack.html new file mode 100644 index 00000000..96a4f8fd --- /dev/null +++ b/docs/twotrack.html @@ -0,0 +1,95 @@ + + + + + Two-Track Symbols + + + + + + + + + + + + + + + +
+

Zint Barcode Generator

+
+

Prev

+
+

Next

+
+
+

5.4 Two-Track Symbols

+

5.4.1 Two-Track +Pharmacode

+

Developed by Laetus, Pharmacode Two-Track is an +alternative system to Pharmacode One-Track used for the +identification of pharmaceuticals. The symbology is able to encode +whole numbers between 4 and 64570080.

+




+

+

5.4.2 PostNet

+

Used by the United States Postal Service and due to be +superseded by the OneCode system by 2009, the PostNet barcode is used +for encoding zip-codes on mail items. PostNet uses numerical input +data and includes a modulo-10 check digit. While Zint will encode +PostNet symbols of any length, standard lengths used by USPS are +PostNet6 (5 digits ZIP input), PostNet10 (5 digit ZIP + 4 digit user +data) and PostNet12 (5 digit ZIP + 6 digit user data).

+




+

+

5.4.3 PLANET

+

Used by the United States Postal Service and due to be +superseded by the OneCode system by 2009, the PLANET (Postal Alpha +Numeric Encoding Technique) barcode is used for encoding routing data +on mail items. Planet uses numerical input data and includes a +modulo-10 check digit. While Zint will encode PLANET symbols of any +length, standard lengths used by USPS are Planet12 (11 digit input) +and Planet14 (13 digit input).

+




+

+
+ + + + + + + + + + + +
+

Prev

+
+

Home

+
+

Next

+
+

Composite Symbols

+
+

 

+
+

4-State Codes

+
+



+

+ + \ No newline at end of file diff --git a/docs/upca.png b/docs/upca.png new file mode 100644 index 00000000..a365f795 Binary files /dev/null and b/docs/upca.png differ diff --git a/frontend/COPYING b/frontend/COPYING new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/frontend/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/frontend/Makefile b/frontend/Makefile new file mode 100644 index 00000000..ac68f38c --- /dev/null +++ b/frontend/Makefile @@ -0,0 +1,24 @@ +# Linux makefile for zint - requires libzint +# +# make compiles zint +# make install copies binary to /usr/local/bin +# make uninstall removes the binary +# make clean cleans up a previous compilation and any object or editor files +# + +CC := gcc +INCLUDE := -I/usr/local/include + +zint: main.c + $(CC) $(INCLUDE) -g main.c -o zint -lzint + +.PHONY: install uninstall clean dist + +clean: + rm -f zint *.o *.a *~ *.png *.eps + +install: + mv zint /usr/local/bin + +uninstall: + rm /usr/local/bin/zint diff --git a/frontend/main.c b/frontend/main.c new file mode 100644 index 00000000..ff37a517 --- /dev/null +++ b/frontend/main.c @@ -0,0 +1,239 @@ +/* main.c - Command line handling routines for Zint */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include +#include + +#define NESET "0123456789" + +void usage(void) +{ + printf( + "Zint version %s\n" + "Encode input data in a barcode and save as a PNG or EPS file.\n\n" + " -h, --help Display this message.\n" + " -o, --output=FILE Write image to FILE. (default is out.png)\n" + " -d, --data=DATA Barcode content.\n" + " -b, --barcode=NUMBER Number of barcode type (default is 20 (=Code128)).\n" + " --height=HEIGHT Height of my_symbol in pixels.\n" + " -w, --whitesp=NUMBER Width of whitespace in pixels.\n" + " --border=NUMBER Width of border in pixels.\n" + " --box Add a box.\n" + " --bind Add boundary bars.\n" + " -r, --reverse Reverse colours (white on black).\n" + " --fg=COLOUR Specify a foreground colour.\n" + " --bg=COLOUR Specify a background colour.\n" + " --cols=NUMBER (PDF417) Number of columns.\n" + " --vers=NUMBER (QR Code) Version\n" + " --secure=NUMBER (PDF417 and QR Code) Error correction level.\n" + " --primary=STRING (Maxicode and Composite) Structured primary message.\n" + " --mode=NUMBER (Maxicode and Composite) Set encoding mode.\n" + , VERSION); +} + +int main(int argc, char **argv) +{ + struct zint_symbol *my_symbol; + int i, mode, stack_row; + int c; + int errornum; + + errornum = 0; + my_symbol = ZBarcode_Create(); + + if(argc == 1) { + usage(); + exit(1); + } + + while(1) { + int option_index = 0; + static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"bind", 0, 0, 0}, + {"box", 0, 0, 0}, + {"barcode=", 1, 0, 'b'}, + {"height=", 1, 0, 0}, + {"whitesp=", 1, 0, 'w'}, + {"border=", 1, 0, 0}, + {"data=", 1, 0, 'd'}, + {"output=", 1, 0, 'o'}, + {"fg=", 1, 0, 0}, + {"bg=", 1, 0, 0}, + {"cols=", 1, 0, 0}, + {"vers=", 1, 0, 0}, + {"secure=", 1, 0, 0}, + {"reverse", 1, 0, 'r'}, + {"case", 0, 0, 'c'}, + {"mode=", 1, 0, 0}, + {"primary=", 1, 0, 0}, + {0, 0, 0, 0} + }; + c = getopt_long(argc, argv, "hb:w:d:o:i:rcmp", long_options, &option_index); + if(c == -1) break; + + switch(c) { + case 0: + if(!strcmp(long_options[option_index].name, "bind")) { + my_symbol->output_options = BARCODE_BIND; + } + if(!strcmp(long_options[option_index].name, "box")) { + my_symbol->output_options = BARCODE_BOX; + } + if(!strcmp(long_options[option_index].name, "fg=")) { + strncpy(my_symbol->fgcolour, optarg, 7); + } + if(!strcmp(long_options[option_index].name, "bg=")) { + strncpy(my_symbol->bgcolour, optarg, 7); + } + if(!strcmp(long_options[option_index].name, "border=")) { + errornum = is_sane(NESET, optarg); + if(errornum == ERROR_INVALID_DATA) { + fprintf(stderr, "Invalid border width\n"); + exit(1); + } + if((atoi(optarg) >= 0) && (atoi(optarg) <= 1000)) { + my_symbol->border_width = atoi(optarg); + } else { + fprintf(stderr, "Border width out of range\n"); + } + } + if(!strcmp(long_options[option_index].name, "height=")) { + errornum = is_sane(NESET, optarg); + if(errornum == ERROR_INVALID_DATA) { + fprintf(stderr, "Invalid symbol height\n"); + exit(1); + } + if((atoi(optarg) >= 1) && (atoi(optarg) <= 1000)) { + my_symbol->height = atoi(optarg); + } else { + fprintf(stderr, "Symbol height out of range\n"); + } + } + + if(!strcmp(long_options[option_index].name, "cols=")) { + if((atoi(optarg) >= 1) && (atoi(optarg) <= 30)) { + my_symbol->option_2 = atoi(optarg); + } else { + fprintf(stderr, "Number of columns out of range\n"); + } + } + if(!strcmp(long_options[option_index].name, "vers=")) { + if((atoi(optarg) >= 1) && (atoi(optarg) <= 40)) { + my_symbol->option_2 = atoi(optarg); + } else { + fprintf(stderr, "Invalid QR Code version\n"); + } + } + if(!strcmp(long_options[option_index].name, "secure=")) { + if((atoi(optarg) >= 1) && (atoi(optarg) <= 8)) { + my_symbol->option_1 = atoi(optarg); + } else { + fprintf(stderr, "ECC level out of range\n"); + } + } + if(!strcmp(long_options[option_index].name, "primary=")) { + if(strlen(optarg) <= 90) { + strcpy(my_symbol->primary, optarg); + } else { + fprintf(stderr, "Primary data string too long"); + } + } + if(!strcmp(long_options[option_index].name, "mode=")) { + /* Don't allow specification of modes 2 and 3 - do it + automagically instead */ + if((optarg[0] >= '0') && (optarg[0] <= '6')) { + my_symbol->option_1 = optarg[0] - '0'; + } else { + fprintf(stderr, "Invalid mode\n"); + } + } + break; + + case 'h': + usage(); + break; + + case 'b': + errornum = is_sane(NESET, optarg); + if(errornum == ERROR_INVALID_DATA) { + printf("Invalid barcode type\n"); + exit(1); + } + my_symbol->symbology = atoi(optarg); + break; + + case 'w': + errornum = is_sane(NESET, optarg); + if(errornum == ERROR_INVALID_DATA) { + printf("Invalid whitespace value\n"); + exit(1); + } + if((atoi(optarg) >= 0) && (atoi(optarg) <= 1000)) { + my_symbol->whitespace_width = atoi(optarg); + } else { + fprintf(stderr, "Whitespace value out of range"); + } + break; + + case 'd': /* we have some data! */ + if(ZBarcode_Encode_and_Print(my_symbol, optarg) != 0) { + printf("%s\n", my_symbol->errtxt); + return 1; + } + break; + + case 'o': + strncpy(my_symbol->outfile, optarg, 250); + break; + + case 'r': + strcpy(my_symbol->fgcolour, "ffffff"); + strcpy(my_symbol->bgcolour, "000000"); + break; + + case '?': + break; + + default: + printf("?? getopt error 0%o\n", c); + } + } + + if (optind < argc) { + printf("Invalid option "); + while (optind < argc) + printf("%s", argv[optind++]); + printf("\n"); + } + + if(strcmp(my_symbol->errtxt, "")) { + printf(my_symbol->errtxt); + printf("\n"); + } + + ZBarcode_Delete(my_symbol); + + return errornum; +} diff --git a/frontend/test.sh b/frontend/test.sh new file mode 100755 index 00000000..9cacc732 --- /dev/null +++ b/frontend/test.sh @@ -0,0 +1,258 @@ +echo testing Code 11 +zint -o bar01.png -b 1 --height=50 -d 87654321 +zint -o bar01.eps -b 1 --height=50 -d 87654321 +echo testing Code 2 of 5 Standard +zint -o bar02.png -b 2 --height=50 -d 87654321 +zint -o bar02.eps -b 2 --height=50 -d 87654321 +echo testing Interleaved 2 of 5 +zint -o bar03.png -b 3 --height=50 -d 87654321 +zint -o bar03.eps -b 3 --height=50 -d 87654321 +echo testing Code 2 of 5 IATA +zint -o bar04.png -b 4 --height=50 -d 87654321 +zint -o bar04.eps -b 4 --height=50 -d 87654321 +echo testing Code 2 of 5 Data Logic +zint -o bar06.png -b 6 --height=50 -d 87654321 +zint -o bar06.eps -b 6 --height=50 -d 87654321 +echo testing Code 2 of 5 Industrial +zint -o bar07.png -b 7 --height=50 -d 87654321 +zint -o bar07.eps -b 7 --height=50 -d 87654321 +echo testing Code 39 +zint -o bar08.png -b 8 --height=50 -d CODE39 +zint -o bar08.eps -b 8 --height=50 -d CODE39 +echo testing Extended Code 39 +zint -o bar09.png -b 9 --height=50 -d 'Code 39e' +zint -o bar09.eps -b 9 --height=50 -d 'Code 39e' +echo testing EAN8 +zint -o bar10.png -b 13 --height=50 -d 7654321 +zint -o bar10.eps -b 13 --height=50 -d 7654321 +echo testing EAN8 - 2 digits add on +zint -o bar11.png -b 13 --height=50 -d 7654321+21 +zint -o bar11.eps -b 13 --height=50 -d 7654321+21 +echo testing EAN8 - 5 digits add-on +zint -o bar12.png -b 13 --height=50 -d 7654321+54321 +zint -o bar12.eps -b 13 --height=50 -d 7654321+54321 +echo testing EAN13 +zint -o bar13.png -b 13 --height=50 -d 210987654321 +zint -o bar13.eps -b 13 --height=50 -d 210987654321 +echo testing EAN13 - 2 digits add-on +zint -o bar14.png -b 13 --height=50 -d 210987654321+21 +zint -o bar14.eps -b 13 --height=50 -d 210987654321+21 +echo testing EAN13 - 5 digits add-on +zint -o bar15.png -b 13 --height=50 -d 210987654321+54321 +zint -o bar15.eps -b 13 --height=50 -d 210987654321+54321 +echo testing GS1-128 +zint -o bar16.png -b 16 --height=50 -d "[01]98898765432106[3202]012345[15]991231" +zint -o bar16.eps -b 16 --height=50 -d "[01]98898765432106[3202]012345[15]991231" +echo testing CodaBar +zint -o bar18.png -b 18 --height=50 -d D765432C +zint -o bar18.eps -b 18 --height=50 -d D765432C +echo testing Code 128 +zint -o bar20.png -b 20 --height=50 -d 'Code 128' +zint -o bar20.eps -b 20 --height=50 -d 'Code 128' +echo testing Deutshe Post Leitcode +zint -o bar21.png -b 21 --height=50 -d 3210987654321 +zint -o bar21.eps -b 21 --height=50 -d 3210987654321 +echo testing Deutche Post Identcode +zint -o bar22.png -b 22 --height=50 -d 10987654321 +zint -o bar22.eps -b 22 --height=50 -d 10987654321 +echo testing Code 16k +zint -o bar23.png -b 23 --height=50 -d 'Code 16k is a stacked symbology' +zint -o bar23.eps -b 23 --height=50 -d 'Code 16k is a stacked symbology' +echo testing Code 93 +zint -o bar25.png -b 25 --height=50 -d 'Code 93' +zint -o bar25.eps -b 25 --height=50 -d 'Code 93' +echo testing Flattermarken +zint -o bar28.png -b 28 --height=50 -d 87654321 +zint -o bar28.eps -b 28 --height=50 -d 87654321 +echo testing GS1 DataBar-14 +zint -o bar29.png -b 29 --height=33 -d 2001234567890 +zint -o bar29.eps -b 29 --height=33 -d 2001234567890 +echo testing GS1 DataBar Limited +zint -o bar30.png -b 30 --height=50 -w 2 -d 31234567890 +zint -o bar30.eps -b 30 --height=50 -w 2 -d 31234567890 +echo testing GS1 DataBar Expanded +zint -o bar31.png -b 31 --height=50 -d "[01]90012345678908[3103]001750" +zint -o bar31.eps -b 31 --height=50 -d "[01]90012345678908[3103]001750" +echo testing Telepen Alpha +zint -o bar32.png -b 32 --height=50 -d 'Telepen' +zint -o bar32.eps -b 32 --height=50 -d 'Telepen' +echo testing UPC A +zint -o bar34.png -b 34 --height=50 -d 10987654321 +zint -o bar34.eps -b 34 --height=50 -d 10987654321 +echo testing UPC A - 2 digit add-on +zint -o bar35.png -b 34 --height=50 -d 10987654321+21 +zint -o bar35.eps -b 34 --height=50 -d 10987654321+21 +echo testing UPC A - 5 digit add-on +zint -o bar36.png -b 36 --height=50 -d 10987654321+54321 +zint -o bar36.eps -b 36 --height=50 -d 10987654321+54321 +echo testing UPC E +zint -o bar37.png -b 37 --height=50 -d 654321 +zint -o bar37.eps -b 37 --height=50 -d 654321 +echo testing UPC E - 2 digit add-on +zint -o bar38.png -b 37 --height=50 -d 654321+21 +zint -o bar38.eps -b 37 --height=50 -d 654321+21 +echo testing UPC E - 5 digit add-on +zint -o bar39.png -b 37 --height=50 -d 654321+54321 +zint -o bar39.eps -b 37 --height=50 -d 654321+54321 +echo testing PostNet-6 +zint -o bar41.png -b 40 -d 54321 +zint -o bar41.eps -b 40 -d 54321 +echo testing PostNet-10 +zint -o bar43.png -b 40 -d 987654321 +zint -o bar43.eps -b 40 -d 987654321 +echo testing PostNet-12 +zint -o bar45.png -b 40 -d 10987654321 +zint -o bar45.eps -b 40 -d 10987654321 +echo testing MSI Code +zint -o bar47.png -b 47 --height=50 -d 87654321 +zint -o bar47.eps -b 47 --height=50 -d 87654321 +echo testing FIM +zint -o bar49.png -b 49 --height=50 -d D +zint -o bar49.eps -b 49 --height=50 -d D +echo testing LOGMARS +zint -o bar50.png -b 50 --height=50 -d LOGMARS +zint -o bar50.eps -b 50 --height=50 -d LOGMARS +echo testing Pharmacode One-Track +zint -o bar51.png -b 51 --height=50 -d 123456 +zint -o bar51.eps -b 51 --height=50 -d 123456 +echo testing Pharmazentralnumber +zint -o bar52.png -b 52 --height=50 -d 654321 +zint -o bar52.eps -b 52 --height=50 -d 654321 +echo testing Pharmacode Two-Track +zint -o bar53.png -b 53 --height=50 -d 12345678 +zint -o bar53.eps -b 53 --height=50 -d 12345678 +echo testing PDF417 +zint -o bar55.png -b 55 -d 'PDF417 is a stacked symbology' +zint -o bar55.eps -b 55 -d 'PDF417 is a stacked symbology' +echo testing PDF417 Truncated +zint -o bar56.png -b 56 -d 'PDF417 is a stacked symbology' +zint -o bar56.eps -b 56 -d 'PDF417 is a stacked symbology' +echo testing Maxicode +zint -o bar57.png -b 57 --primary="999999999840012" -d 'UPS Maxicode with hexagons' +zint -o bar57.eps -b 57 --primary="999999999840012" -d 'UPS Maxicode with hexagons' +echo testing QR Code +zint -o bar58.png -b 58 -d 'QR Code is a matrix symbology' +zint -o bar58.eps -b 58 -d 'QR Code is a matrix symbology' +echo testing Code 128 Subset B +zint -o bar60.png -b 60 --height=50 -d 87654321 +zint -o bar60.eps -b 60 --height=50 -d 87654321 +echo testing Australian Post Standard Customer +zint -o bar63.png -b 63 -d 87654321 +zint -o bar63.eps -b 63 -d 87654321 +echo testing Australian Post Customer 2 +zint -o bar64.png -b 63 -d 87654321AUSPS +zint -o bar64.eps -b 63 -d 87654321AUSPS +echo testing Australian Post Customer 3 +zint -o bar65.png -b 63 -d '87654321 AUSTRALIA' +zint -o bar65.eps -b 63 -d '87654321 AUSTRALIA' +echo testing Australian Post Reply Paid +zint -o bar66.png -b 66 -d 87654321 +zint -o bar66.eps -b 66 -d 87654321 +echo testing Australian Post Routing +zint -o bar67.png -b 67 -d 87654321 +zint -o bar67.eps -b 67 -d 87654321 +echo testing Australian Post Redirection +zint -o bar68.png -b 68 -d 87654321 +zint -o bar68.eps -b 68 -d 87654321 +echo testing ISBN Code +zint -o bar69.png -b 69 --height=50 -d 0333638514 +zint -o bar69.eps -b 69 --height=50 -d 0333638514 +echo testing Royal Mail 4 State +zint -o bar70.png -b 70 -d ROYALMAIL +zint -o bar70.eps -b 70 -d ROYALMAIL +echo testing Data Matrix +zint -o bar71.png -b 71 -d 'Data Matrix is a matrix symbology' +zint -o bar71.eps -b 71 -d 'Data Matrix is a matrix symbology' +echo testing EAN-14 +zint -o bar72.png -b 72 --height=50 -d 3210987654321 +zint -o bar72.eps -b 72 --height=50 -d 3210987654321 +echo testing NVE-18 +zint -o bar75.png -b 75 --height=50 -d 76543210987654321 +zint -o bar75.eps -b 75 --height=50 -d 76543210987654321 +echo testing GS1 DataBar Truncated +zint -o bar78.eps -b 29 --height=13 -d 1234567890 +zint -o bar78.png -b 29 --height=13 -d 1234567890 +echo testing GS1 DataBar Stacked +zint -o bar79.eps -b 79 -d 1234567890 +zint -o bar79.png -b 79 -d 1234567890 +echo testing GS1 DataBar Stacked Omnidirectional +zint -o bar80.eps -b 80 --height=69 -d 3456789012 +zint -o bar80.png -b 80 --height=69 -d 3456789012 +echo testing GS1 DataBar Expanded Stacked +zint -o bar81.eps -b 81 -d "[01]98898765432106[3202]012345[15]991231" +zint -o bar81.png -b 81 -d "[01]98898765432106[3202]012345[15]991231" +echo testing Planet 12 Digit +zint -o bar82.png -b 82 -d 10987654321 +zint -o bar82.eps -b 82 -d 10987654321 +echo testing Planet 14 Digit +zint -o bar83.png -b 82 -d 3210987654321 +zint -o bar83.eps -b 82 -d 3210987654321 +echo testing Micro PDF417 +zint -o bar84.png -b 84 -d 'MicroPDF417 is a very small stacked symbology' +zint -o bar84.eps -b 84 -d 'MicroPDF417 is a very small stacked symbology' +echo testing USPS OneCode 4-State Customer Barcode +zint -o bar85.png -b 85 -d 01234567094987654321 +zint -o bar85.eps -b 85 -d 01234567094987654321 +echo testing Plessey Code with bidirectional reading support +zint -o bar86.png -b 86 --height=50 -d 87654321 +zint -o bar86.eps -b 86 --height=50 -d 87654321 +echo testing Telepen Numeric +zint -o bar100.png -b 100 --height=50 -d 87654321 +zint -o bar100.eps -b 100 --height=50 -d 87654321 +echo testing MSI Plessey with Mod-10 check +zint -o bar101.png -b 101 --height=50 -d 87654321 +zint -o bar101.eps -b 101 --height=50 -d 87654321 +echo testing MSI Plessey with 2 x Mod-10 checks +zint -o bar102.png -b 102 --height=50 -d 87654321 +zint -o bar102.eps -b 102 --height=50 -d 87654321 +echo testing MSI Plessey with Mod-11 check +zint -o bar103.png -b 103 --height=50 -d 87654321 +zint -o bar103.eps -b 103 --height=50 -d 87654321 +echo testing MSI Plessey with Mod-10 and Mod-11 check +zint -o bar104.png -b 104 --height=50 -d 87654321 +zint -o bar104.eps -b 104 --height=50 -d 87654321 +echo testing Code 39 with Modulo 43 check +zint -o bar105.png -b 105 --height=50 -d 'CODE 39 MOD 43' +zint -o bar105.eps -b 105 --height=50 -d 'CODE 39 MOD 43' +echo testing Extended Code 39 with Modulo 43 check +zint -o bar106.png -b 106 --height=50 -d 'Code 39e MOD 43' +zint -o bar106.eps -b 106 --height=50 -d 'Code 39e MOD 43' +echo testing Aztec Code +zint -o bar107.eps -b 107 -d "Demonstration Aztec Code symbol generated by libzint" +zint -o bar107.png -b 107 -d "Demonstration Aztec Code symbol generated by libzint" +echo testing UPC-E Composite with CC-A +zint -o bar116.eps -b 116 --height=100 --mode=1 --primary=121230 -d "[15]021231" +zint -o bar116.png -b 116 --height=100 --mode=1 --primary=121230 -d "[15]021231" +echo testing UPC-A Composite with CC-A +zint -o bar115.eps -b 115 --height=100 --mode=1 --primary=10987654321 -d "[15]021231" +zint -o bar115.png -b 115 --height=100 --mode=1 --primary=10987654321 -d "[15]021231" +echo testing EAN-8 Composite with CC-A +zint -o bar110.eps -b 110 --height=100 --mode=1 --primary=1234567 -d "[21]A12345678" +zint -o bar110.png -b 110 --height=100 --mode=1 --primary=1234567 -d "[21]A12345678" +echo testing EAN-13 Composite with CC-A +zint -o bar110a.eps -b 110 --height=100 --mode=1 --primary=331234567890 -d "[99]1234-abcd" +zint -o bar110a.png -b 110 --height=100 --mode=1 --primary=331234567890 -d "[99]1234-abcd" +echo testing RSS-14 Stacked Composite with CC-A +zint -o bar117.eps -b 117 --mode=1 --primary=341234567890 -d "[17]010200" +zint -o bar117.png -b 117 --mode=1 --primary=341234567890 -d "[17]010200" +echo testing RSS-14 Stacked Omnidirectional Composite with CC-A +zint -o bar118.eps -b 118 --mode=1 --primary=341234567890 -d "[17]010200" +zint -o bar118.png -b 118 --mode=1 --primary=341234567890 -d "[17]010200" +echo testing RSS Limited Composite with CC-B +zint -o bar113.eps -b 113 --height=100 --mode=2 --primary=351234567890 -d "[21]abcdefghijklmnopqrstuv" +zint -o bar113.png -b 113 --height=100 --mode=2 --primary=351234567890 -d "[21]abcdefghijklmnopqrstuv" +echo testing RSS-14 Composite with CC-A +zint -o bar112.eps -b 112 --height=100 --mode=1 --primary=361234567890 -d "[11]990102" +zint -o bar112.png -b 112 --height=100 --mode=1 --primary=361234567890 -d "[11]990102" +echo testing RSS Expanded Composite with CC-A +zint -o bar114.eps -b 114 --height=100 --mode=1 --primary="[01]93712345678904[3103]001234" -d "[91]1A2B3C4D5E" +zint -o bar114.png -b 114 --height=100 --mode=1 --primary="[01]93712345678904[3103]001234" -d "[91]1A2B3C4D5E" +echo testing RSS Expanded Stacked Composite with CC-A +zint -o bar119.eps -b 119 --height=150 --mode=1 --primary="[01]00012345678905[10]ABCDEF" -d "[21]12345678" +zint -o bar119.png -b 119 --height=150 --mode=1 --primary="[01]00012345678905[10]ABCDEF" -d "[21]12345678" +echo testing UCC/EAN-128 Composite with CC-A +zint -o bar111.eps -b 111 --height=100 --mode=1 --primary="[01]03212345678906" -d "[10]1234567ABCDEFG" +zint -o bar111.png -b 111 --height=100 --mode=1 --primary="[01]03212345678906" -d "[10]1234567ABCDEFG" +echo testing UCC/EAN-128 Composite with CC-C +zint -o bar111a.eps -b 111 --height=100 --mode=3 --primary="[00]030123456789012340" -d "[02]130123456789093724[10]1234567ABCDEFG" +zint -o bar111a.png -b 111 --height=100 --mode=3 --primary="[00]030123456789012340" -d "[02]130123456789093724[10]1234567ABCDEFG" \ No newline at end of file diff --git a/readme b/readme new file mode 100644 index 00000000..b139697d --- /dev/null +++ b/readme @@ -0,0 +1,39 @@ +Zint and libzint 1.6.0 +---------------------- + +Zint is a front end program and library which provides support for over 30 barcode symbologies +in an open source package released under the GNU General Public License. Currently supported +symbologies include: + +Code 11, Standard Code 2 of 5, IATA Code 2 of 5, Industrial Code 2 of 5, Interleaved Code 2 of 5, +Code 2 of 5 Data Logic, ITF-14, Deutche Post Leitcode, Deutche Post Identcode, UPC-A, UPC-E, EAN-2, +EAN-5, EAN-8, EAN-13, UK Plessey, MSI Plessey, Telepen Alpha, Telepen Numeric, Code 39, +Extended Code 39, Code 93, PZN, LOGMARS, Codabar, Pharmacode, Code 128, EAN-128, NVE-18, Code 16k, +PDF417, MicroPDF417, Two-Track Pharmacode, PostNet, PLANET, Australia Post 4-State Symbols, RM4SCC, +USPS OneCode, GS1 DataBar, DataBar-14, DataBar Limited, DataBar Extended, DataBar Stacked, +Composite Symbology, Data Matrix, QR Code, Maxicode, FIM and Flattermarken. + +Full documentation is included in the 'docs' directory. The libzint back end code is included +in the 'backend' directory, and the front end command line program 'zint' is included in the +'frontend' directory. See the HTML documentation for full installation instructions. The file +DEVELOPERS in the backend folder gives a brief guide to which symbologies are handled by which +source code files. + + +CONTACT ME +---------- + +The home of libzint is + +http://www.sourceforge.net/projects/zint + +and a new home for information about Zint is under construction at: + +http://www.zint.org.uk + +I am keen to hear your ideas / recieve bug reports at zint@hotmail.co.uk + +Thanks for your interest in libzint. +Happy encoding. + +Robin. \ No newline at end of file