comparison mupdf-source/thirdparty/zint/backend/auspost.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /* auspost.c - Handles Australia Post 4-State Barcode */
2 /*
3 libzint - the open source barcode library
4 Copyright (C) 2008-2024 Robin Stuart <rstuart114@gmail.com>
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of the project nor the names of its contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 SUCH DAMAGE.
30 */
31 /* SPDX-License-Identifier: BSD-3-Clause */
32
33 static const char GDSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #";
34 #define GDSET_F (IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F)
35
36 static const char AusNTable[10][2] = {
37 {'0','0'}, {'0','1'}, {'0','2'}, {'1','0'}, {'1','1'}, {'1','2'}, {'2','0'}, {'2','1'}, {'2','2'}, {'3','0'}
38 };
39
40 static const char AusCTable[64][3] = {
41 {'2','2','2'}, {'3','0','0'}, {'3','0','1'}, {'3','0','2'}, {'3','1','0'}, {'3','1','1'},
42 {'3','1','2'}, {'3','2','0'}, {'3','2','1'}, {'3','2','2'}, {'0','0','0'}, {'0','0','1'},
43 {'0','0','2'}, {'0','1','0'}, {'0','1','1'}, {'0','1','2'}, {'0','2','0'}, {'0','2','1'},
44 {'0','2','2'}, {'1','0','0'}, {'1','0','1'}, {'1','0','2'}, {'1','1','0'}, {'1','1','1'},
45 {'1','1','2'}, {'1','2','0'}, {'1','2','1'}, {'1','2','2'}, {'2','0','0'}, {'2','0','1'},
46 {'2','0','2'}, {'2','1','0'}, {'2','1','1'}, {'2','1','2'}, {'2','2','0'}, {'2','2','1'},
47 {'0','2','3'}, {'0','3','0'}, {'0','3','1'}, {'0','3','2'}, {'0','3','3'}, {'1','0','3'},
48 {'1','1','3'}, {'1','2','3'}, {'1','3','0'}, {'1','3','1'}, {'1','3','2'}, {'1','3','3'},
49 {'2','0','3'}, {'2','1','3'}, {'2','2','3'}, {'2','3','0'}, {'2','3','1'}, {'2','3','2'},
50 {'2','3','3'}, {'3','0','3'}, {'3','1','3'}, {'3','2','3'}, {'3','3','0'}, {'3','3','1'},
51 {'3','3','2'}, {'3','3','3'}, {'0','0','3'}, {'0','1','3'}
52 };
53
54 static const char AusBarTable[64][3] = {
55 {'0','0','0'}, {'0','0','1'}, {'0','0','2'}, {'0','0','3'}, {'0','1','0'}, {'0','1','1'},
56 {'0','1','2'}, {'0','1','3'}, {'0','2','0'}, {'0','2','1'}, {'0','2','2'}, {'0','2','3'},
57 {'0','3','0'}, {'0','3','1'}, {'0','3','2'}, {'0','3','3'}, {'1','0','0'}, {'1','0','1'},
58 {'1','0','2'}, {'1','0','3'}, {'1','1','0'}, {'1','1','1'}, {'1','1','2'}, {'1','1','3'},
59 {'1','2','0'}, {'1','2','1'}, {'1','2','2'}, {'1','2','3'}, {'1','3','0'}, {'1','3','1'},
60 {'1','3','2'}, {'1','3','3'}, {'2','0','0'}, {'2','0','1'}, {'2','0','2'}, {'2','0','3'},
61 {'2','1','0'}, {'2','1','1'}, {'2','1','2'}, {'2','1','3'}, {'2','2','0'}, {'2','2','1'},
62 {'2','2','2'}, {'2','2','3'}, {'2','3','0'}, {'2','3','1'}, {'2','3','2'}, {'2','3','3'},
63 {'3','0','0'}, {'3','0','1'}, {'3','0','2'}, {'3','0','3'}, {'3','1','0'}, {'3','1','1'},
64 {'3','1','2'}, {'3','1','3'}, {'3','2','0'}, {'3','2','1'}, {'3','2','2'}, {'3','2','3'},
65 {'3','3','0'}, {'3','3','1'}, {'3','3','2'}, {'3','3','3'}
66 };
67
68 #include <stdio.h>
69 #include "common.h"
70 #include "reedsol.h"
71
72 static char aus_convert_pattern(char data, int shift) {
73 return (data - '0') << shift;
74 }
75
76 /* Adds Reed-Solomon error correction to auspost */
77 static char *aus_rs_error(char data_pattern[], char *d) {
78 int reader, length, triple_writer = 0;
79 unsigned char triple[31];
80 unsigned char result[5];
81 rs_t rs;
82
83 for (reader = 2, length = d - data_pattern; reader < length; reader += 3, triple_writer++) {
84 triple[triple_writer] = aus_convert_pattern(data_pattern[reader], 4)
85 + aus_convert_pattern(data_pattern[reader + 1], 2)
86 + aus_convert_pattern(data_pattern[reader + 2], 0);
87 }
88
89 rs_init_gf(&rs, 0x43);
90 rs_init_code(&rs, 4, 1);
91 rs_encode(&rs, triple_writer, triple, result);
92
93 for (reader = 0; reader < 4; reader++, d += 3) {
94 memcpy(d, AusBarTable[result[reader]], 3);
95 }
96
97 return d;
98 }
99
100 INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, const float max_height);
101
102 /* Handles Australia Posts's 4 State Codes */
103 INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int length) {
104 /* Customer Standard Barcode, Barcode 2 or Barcode 3 system determined automatically
105 (i.e. the FCC doesn't need to be specified by the user) dependent
106 on the length of the input string */
107
108 /* The contents of data_pattern conform to the following standard:
109 0 = Tracker, Ascender and Descender
110 1 = Tracker and Ascender
111 2 = Tracker and Descender
112 3 = Tracker only */
113 int i;
114 int error_number;
115 int writer;
116 int loopey, reader;
117 int h;
118
119 char data_pattern[200];
120 char *d = data_pattern;
121 char fcc[3] = {0}, dpid[10];
122 char localstr[30];
123
124 /* Do all of the length checking first to avoid stack smashing */
125 if (symbol->symbology == BARCODE_AUSPOST) {
126 if (length != 8 && length != 13 && length != 16 && length != 18 && length != 23) {
127 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 401, "Input length %d wrong (8, 13, 16, 18 or 23 only)",
128 length);
129 }
130 } else if (length > 8) {
131 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 403, "Input length %d too long (maximum 8)", length);
132 }
133
134 /* Check input immediately to catch nuls */
135 if ((i = not_sane(GDSET_F, source, length))) {
136 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 404,
137 "Invalid character at position %d in input (alphanumerics, space and \"#\" only)", i);
138 }
139
140 localstr[0] = '\0';
141
142 if (symbol->symbology == BARCODE_AUSPOST) {
143 /* Format control code (FCC) */
144 switch (length) {
145 case 8:
146 strcpy(fcc, "11");
147 break;
148 case 13:
149 strcpy(fcc, "59");
150 break;
151 case 16:
152 strcpy(fcc, "59");
153 if ((i = not_sane(NEON_F, source, length))) {
154 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 402,
155 "Invalid character at position %d in input (digits only for FCC 59 length 16)",
156 i);
157 }
158 break;
159 case 18:
160 strcpy(fcc, "62");
161 break;
162 case 23:
163 strcpy(fcc, "62");
164 if ((i = not_sane(NEON_F, source, length))) {
165 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 406,
166 "Invalid character at position %d in input (digits only for FCC 62 length 23)",
167 i);
168 }
169 break;
170 }
171 } else {
172 int zeroes;
173 switch (symbol->symbology) {
174 case BARCODE_AUSREPLY: strcpy(fcc, "45");
175 break;
176 case BARCODE_AUSROUTE: strcpy(fcc, "87");
177 break;
178 case BARCODE_AUSREDIRECT: strcpy(fcc, "92");
179 break;
180 }
181
182 /* Add leading zeros as required */
183 zeroes = 8 - length;
184 memset(localstr, '0', zeroes);
185 localstr[zeroes] = '\0';
186 }
187
188 if (symbol->debug & ZINT_DEBUG_PRINT) {
189 printf("AUSPOST FCC: %s\n", fcc);
190 }
191
192 ustrncat(localstr, source, length);
193 h = (int) strlen(localstr);
194 /* Verify that the first 8 characters are numbers */
195 memcpy(dpid, localstr, 8);
196 dpid[8] = '\0';
197 if ((i = not_sane(NEON_F, (unsigned char *) dpid, 8))) {
198 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 405,
199 "Invalid character at position %d in DPID (first 8 characters) (digits only)", i);
200 }
201
202 /* Start character */
203 memcpy(d, "13", 2);
204 d += 2;
205
206 /* Encode the FCC */
207 for (reader = 0; reader < 2; reader++, d += 2) {
208 memcpy(d, AusNTable[fcc[reader] - '0'], 2);
209 }
210
211 /* Delivery Point Identifier (DPID) */
212 for (reader = 0; reader < 8; reader++, d += 2) {
213 memcpy(d, AusNTable[dpid[reader] - '0'], 2);
214 }
215
216 /* Customer Information */
217 if (h > 8) {
218 if ((h == 13) || (h == 18)) {
219 for (reader = 8; reader < h; reader++, d += 3) {
220 memcpy(d, AusCTable[posn(GDSET, localstr[reader])], 3);
221 }
222 } else if ((h == 16) || (h == 23)) {
223 for (reader = 8; reader < h; reader++, d += 2) {
224 memcpy(d, AusNTable[localstr[reader] - '0'], 2);
225 }
226 }
227 }
228
229 /* Filler bar */
230 h = d - data_pattern;
231 switch (h) {
232 case 22:
233 case 37:
234 case 52:
235 *d++ = '3';
236 break;
237 default:
238 break;
239 }
240
241 /* Reed Solomon error correction */
242 d = aus_rs_error(data_pattern, d);
243
244 /* Stop character */
245 memcpy(d, "13", 2);
246 d += 2;
247
248 /* Turn the symbol into a bar pattern ready for plotting */
249 writer = 0;
250 h = d - data_pattern;
251 for (loopey = 0; loopey < h; loopey++) {
252 if ((data_pattern[loopey] == '1') || (data_pattern[loopey] == '0')) {
253 set_module(symbol, 0, writer);
254 }
255 set_module(symbol, 1, writer);
256 if ((data_pattern[loopey] == '2') || (data_pattern[loopey] == '0')) {
257 set_module(symbol, 2, writer);
258 }
259 writer += 2;
260 }
261
262 if (symbol->output_options & COMPLIANT_HEIGHT) {
263 /* Australia Post Customer Barcoding Technical Specifications (Revised Aug 2012) Dimensions, placement and
264 printing p.12
265 (https://auspost.com.au/content/dam/auspost_corp/media/documents/
266 customer-barcode-technical-specifications-aug2012.pdf)
267 X 0.5mm (average of 0.4mm - 0.6mm), min height 4.2mm / 0.6mm (X max) = 7, max 5.6mm / 0.4mm (X min) = 14
268 Tracker 1.3mm (average of 1mm - 1.6mm)
269 Ascender/Descender 3.15mm (average of 2.6mm - 3.7mm) less T = 1.85mm
270 */
271 symbol->row_height[0] = 3.7f; /* 1.85f / 0.5f */
272 symbol->row_height[1] = 2.6f; /* 1.3f / 0.5f */
273 error_number = daft_set_height(symbol, 7.0f, 14.0f); /* Note using max X for minimum and min X for maximum */
274 } else {
275 symbol->row_height[0] = 3.0f;
276 symbol->row_height[1] = 2.0f;
277 error_number = daft_set_height(symbol, 0.0f, 0.0f);
278 }
279 symbol->rows = 3;
280 symbol->width = writer - 1;
281
282 return error_number;
283 }
284
285 /* vim: set ts=4 sw=4 et : */