Line data Source code
1 : /*
2 : * liblierre - writer.c
3 : *
4 : * This file is part of liblierre.
5 : *
6 : * Author: Go Kudo <zeriyoshi@gmail.com>
7 : * SPDX-License-Identifier: MIT
8 : */
9 :
10 : #include <stdint.h>
11 : #include <string.h>
12 :
13 : #include <lierre.h>
14 : #include <lierre/writer.h>
15 :
16 : #include <poporon.h>
17 :
18 : #include "../internal/memory.h"
19 : #include "../internal/structs.h"
20 :
21 : #define RS_GF256_PRIMITIVE_POLY 0x11D
22 : #define RS_GF256_GENERATOR_ROOT 0x1
23 : #define RS_BYTE_BITS 7
24 :
25 : #define FORMAT_POLY 0x537
26 : #define FORMAT_XOR_MASK 0x5412
27 : #define FORMAT_POLY_SHIFT 9
28 : #define FORMAT_DATA_SHIFT 10
29 : #define FORMAT_BITS_COUNT 15
30 : #define FORMAT_BITS_LOOP_END 6
31 : #define FORMAT_BITS_LOOP_START 9
32 :
33 : #define QR_VERSION_MAX 40
34 : #define QR_VERSION_MIN 1
35 : #define QR_VERSION1_SIZE 17
36 : #define QR_VERSION_SIZE_FORMULA(v) ((v) * 4 + QR_VERSION1_SIZE)
37 : #define QR_BUFFER_LEN_FOR_VERSION(n) (((((n) * 4 + 17) * ((n) * 4 + 17) + 7) >> 3) + 1)
38 : #define QR_BUFFER_LEN_MAX QR_BUFFER_LEN_FOR_VERSION(QR_VERSION_MAX)
39 : #define QR_RS_DEGREE_MAX 30
40 : #define QR_MASK_COUNT 8
41 :
42 : #define QR_MODE_NUMERIC_INDICATOR 0x1
43 : #define QR_MODE_ALPHANUMERIC_INDICATOR 0x2
44 : #define QR_MODE_BYTE_INDICATOR 0x4
45 : #define QR_MODE_ECI_INDICATOR 0x7
46 : #define QR_MODE_KANJI_INDICATOR 0x8
47 : #define QR_MODE_INDICATOR_BITS 4
48 : #define QR_TERMINATOR_MAX_BITS 4
49 : #define QR_PAD_BYTE_BITS 8
50 :
51 : #define VERSION_THRESHOLD_SMALL 10
52 : #define VERSION_THRESHOLD_MEDIUM 27
53 : #define VERSION_INFO_MIN 7
54 : #define VERSION_INFO_BITS 12
55 : #define VERSION_INFO_POLY 0x1F25
56 : #define VERSION_INFO_SHIFT 11
57 : #define VERSION_INFO_DATA_SHIFT 12
58 : #define VERSION_INFO_AREA_WIDTH 3
59 : #define VERSION_INFO_AREA_HEIGHT 6
60 : #define VERSION_INFO_OFFSET 11
61 :
62 : #define NUMERIC_BITS_SMALL 10
63 : #define NUMERIC_BITS_MEDIUM 12
64 : #define NUMERIC_BITS_LARGE 14
65 :
66 : #define ALPHA_BITS_SMALL 9
67 : #define ALPHA_BITS_MEDIUM 11
68 : #define ALPHA_BITS_LARGE 13
69 :
70 : #define BYTE_BITS_SMALL 8
71 : #define BYTE_BITS_LARGE 16
72 :
73 : #define KANJI_BITS_SMALL 8
74 : #define KANJI_BITS_MEDIUM 10
75 : #define KANJI_BITS_LARGE 12
76 :
77 : #define NUMERIC_GROUP_SIZE 3
78 : #define NUMERIC_GROUP_BITS 10
79 : #define NUMERIC_REMAINDER2_BITS 7
80 : #define NUMERIC_REMAINDER1_BITS 4
81 :
82 : #define ALPHANUMERIC_CHARSET_SIZE 45
83 : #define ALPHANUMERIC_GROUP_SIZE 2
84 : #define ALPHANUMERIC_GROUP_BITS 11
85 : #define ALPHANUMERIC_REMAINDER_BITS 6
86 :
87 : #define KANJI_ENCODED_BITS 13
88 : #define KANJI_SJIS_RANGE1_START 0x8140
89 : #define KANJI_SJIS_RANGE1_END 0x9FFC
90 : #define KANJI_SJIS_RANGE2_START 0xE040
91 : #define KANJI_SJIS_RANGE2_END 0xEBBF
92 : #define KANJI_ENCODE_BASE1 0x8140
93 : #define KANJI_ENCODE_BASE2 0xC140
94 : #define KANJI_ENCODE_MULTIPLIER 0xC0
95 :
96 : #define PAD_BYTE_FIRST 0xEC
97 : #define PAD_BYTE_SECOND 0x11
98 :
99 : #define ECI_SINGLE_BYTE_MAX 127
100 : #define ECI_DOUBLE_BYTE_MAX 16383
101 : #define ECI_PREFIX_2BYTE 0x80
102 : #define ECI_PREFIX_3BYTE 0xC0
103 : #define ECI_MASK_2BYTE 0x3F
104 : #define ECI_MASK_3BYTE 0x1F
105 : #define ECI_BITS_3BYTE 24
106 : #define ECI_DEFAULT_VALUE 26
107 :
108 : #define FINDER_PATTERN_CENTER 3
109 : #define FINDER_PATTERN_RADIUS 4
110 : #define FINDER_QUIET_SIZE 8
111 : #define FINDER_CORNER_SIZE 9
112 :
113 : #define TIMING_PATTERN_POSITION 6
114 : #define TIMING_PATTERN_START 7
115 :
116 : #define ALIGNMENT_PATTERN_SIZE 5
117 : #define ALIGNMENT_PATTERN_OFFSET 2
118 : #define ALIGNMENT_BASE_POSITION 6
119 :
120 : #define PENALTY_RUN_THRESHOLD 5
121 : #define PENALTY_RUN_BASE 3
122 : #define PENALTY_FINDER_LIKE 40
123 : #define PENALTY_2X2_BLOCK 3
124 : #define PENALTY_BALANCE_MULTIPLIER 10
125 : #define PENALTY_BALANCE_FACTOR_DARK 20
126 : #define PENALTY_BALANCE_FACTOR_TOTAL 10
127 : #define PENALTY_HISTORY_SIZE 7
128 : #define PENALTY_HISTORY_MOVE_SIZE 6
129 :
130 : #define ALPHA_LETTER_OFFSET 10
131 : #define ALPHA_SPACE_VALUE 36
132 : #define ALPHA_DOLLAR_VALUE 37
133 : #define ALPHA_PERCENT_VALUE 38
134 : #define ALPHA_ASTERISK_VALUE 39
135 : #define ALPHA_PLUS_VALUE 40
136 : #define ALPHA_MINUS_VALUE 41
137 : #define ALPHA_DOT_VALUE 42
138 : #define ALPHA_SLASH_VALUE 43
139 : #define ALPHA_COLON_VALUE 44
140 :
141 : static const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = {
142 : {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28,
143 : 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},
144 : {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26,
145 : 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28},
146 : {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30,
147 : 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},
148 : {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28,
149 : 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},
150 : };
151 :
152 : static const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = {
153 : {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8,
154 : 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25},
155 : {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16,
156 : 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49},
157 : {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20,
158 : 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68},
159 : {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25,
160 : 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81},
161 : };
162 :
163 : static const int16_t DATA_CODEWORDS[4][41] = {
164 : /* ECL L */
165 : {-1, 19, 34, 55, 80, 108, 136, 156, 194, 232, 274, 324, 370, 428,
166 : 461, 523, 589, 647, 721, 795, 861, 932, 1006, 1094, 1174, 1276, 1370, 1468,
167 : 1531, 1631, 1735, 1843, 1955, 2071, 2191, 2306, 2434, 2566, 2702, 2812, 2956},
168 : /* ECL M */
169 : {-1, 16, 28, 44, 64, 86, 108, 124, 154, 182, 216, 254, 290, 334,
170 : 365, 415, 453, 507, 563, 627, 669, 714, 782, 860, 914, 1000, 1062, 1128,
171 : 1193, 1267, 1373, 1455, 1541, 1631, 1725, 1812, 1914, 1992, 2102, 2216, 2334},
172 : /* ECL Q */
173 : {-1, 13, 22, 34, 48, 62, 76, 88, 110, 132, 154, 180, 206, 244, 261, 295, 325, 367, 397, 445, 485,
174 : 512, 568, 614, 664, 718, 754, 808, 871, 911, 985, 1033, 1115, 1171, 1231, 1286, 1354, 1426, 1502, 1582, 1666},
175 : /* ECL H */
176 : {-1, 9, 16, 26, 36, 46, 60, 66, 86, 100, 122, 140, 158, 180, 197, 223, 253, 283, 313, 341, 385,
177 : 406, 442, 464, 514, 538, 596, 628, 661, 701, 745, 793, 845, 901, 961, 986, 1054, 1096, 1142, 1222, 1276},
178 : };
179 :
180 : static const int16_t CHAR_CAPACITY[4][41][4] = {
181 : /* ECL L */
182 : {
183 : {-1, -1, -1, -1}, /* version 0 (invalid) */
184 : {41, 25, 17, 10}, /* version 1 */
185 : {77, 47, 32, 20}, /* version 2 */
186 : {127, 77, 53, 32}, /* version 3 */
187 : {187, 114, 78, 48}, /* version 4 */
188 : {255, 154, 106, 65}, /* version 5 */
189 : {322, 195, 134, 82}, /* version 6 */
190 : {370, 224, 154, 95}, /* version 7 */
191 : {461, 279, 192, 118}, /* version 8 */
192 : {552, 335, 230, 141}, /* version 9 */
193 : {652, 395, 271, 167}, /* version 10 */
194 : {772, 468, 321, 198}, /* version 11 */
195 : {883, 535, 367, 226}, /* version 12 */
196 : {1022, 619, 425, 262}, /* version 13 */
197 : {1101, 667, 458, 282}, /* version 14 */
198 : {1250, 758, 520, 320}, /* version 15 */
199 : {1408, 854, 586, 361}, /* version 16 */
200 : {1548, 938, 644, 397}, /* version 17 */
201 : {1725, 1046, 718, 442}, /* version 18 */
202 : {1903, 1153, 792, 488}, /* version 19 */
203 : {2061, 1249, 858, 528}, /* version 20 */
204 : {2232, 1352, 929, 572}, /* version 21 */
205 : {2409, 1460, 1003, 618}, /* version 22 */
206 : {2620, 1588, 1091, 672}, /* version 23 */
207 : {2812, 1704, 1171, 721}, /* version 24 */
208 : {3057, 1853, 1273, 784}, /* version 25 */
209 : {3283, 1990, 1367, 842}, /* version 26 */
210 : {3517, 2132, 1465, 902}, /* version 27 */
211 : {3669, 2223, 1528, 940}, /* version 28 */
212 : {3909, 2369, 1628, 1002}, /* version 29 */
213 : {4158, 2520, 1732, 1066}, /* version 30 */
214 : {4417, 2677, 1840, 1132}, /* version 31 */
215 : {4686, 2840, 1952, 1201}, /* version 32 */
216 : {4965, 3009, 2068, 1273}, /* version 33 */
217 : {5253, 3183, 2188, 1347}, /* version 34 */
218 : {5529, 3351, 2303, 1417}, /* version 35 */
219 : {5836, 3537, 2431, 1496}, /* version 36 */
220 : {6153, 3729, 2563, 1577}, /* version 37 */
221 : {6479, 3927, 2699, 1661}, /* version 38 */
222 : {6743, 4087, 2809, 1729}, /* version 39 */
223 : {7089, 4296, 2953, 1817}, /* version 40 */
224 : },
225 : /* ECL M */
226 : {
227 : {-1, -1, -1, -1}, /* version 0 (invalid) */
228 : {34, 20, 14, 8}, /* version 1 */
229 : {63, 38, 26, 16}, /* version 2 */
230 : {101, 61, 42, 26}, /* version 3 */
231 : {149, 90, 62, 38}, /* version 4 */
232 : {202, 122, 84, 52}, /* version 5 */
233 : {255, 154, 106, 65}, /* version 6 */
234 : {293, 178, 122, 75}, /* version 7 */
235 : {365, 221, 152, 93}, /* version 8 */
236 : {432, 262, 180, 111}, /* version 9 */
237 : {513, 311, 213, 131}, /* version 10 */
238 : {604, 366, 251, 155}, /* version 11 */
239 : {691, 419, 287, 177}, /* version 12 */
240 : {796, 483, 331, 204}, /* version 13 */
241 : {871, 528, 362, 223}, /* version 14 */
242 : {991, 600, 412, 254}, /* version 15 */
243 : {1082, 656, 450, 277}, /* version 16 */
244 : {1212, 734, 504, 310}, /* version 17 */
245 : {1346, 816, 560, 345}, /* version 18 */
246 : {1500, 909, 624, 384}, /* version 19 */
247 : {1600, 970, 666, 410}, /* version 20 */
248 : {1708, 1035, 711, 438}, /* version 21 */
249 : {1872, 1134, 779, 480}, /* version 22 */
250 : {2059, 1248, 857, 528}, /* version 23 */
251 : {2188, 1326, 911, 561}, /* version 24 */
252 : {2395, 1451, 997, 614}, /* version 25 */
253 : {2544, 1542, 1059, 652}, /* version 26 */
254 : {2701, 1637, 1125, 692}, /* version 27 */
255 : {2857, 1732, 1190, 732}, /* version 28 */
256 : {3035, 1839, 1264, 778}, /* version 29 */
257 : {3289, 1994, 1370, 843}, /* version 30 */
258 : {3486, 2113, 1452, 894}, /* version 31 */
259 : {3693, 2238, 1538, 947}, /* version 32 */
260 : {3909, 2369, 1628, 1002}, /* version 33 */
261 : {4134, 2506, 1722, 1060}, /* version 34 */
262 : {4343, 2632, 1809, 1113}, /* version 35 */
263 : {4588, 2780, 1911, 1176}, /* version 36 */
264 : {4775, 2894, 1989, 1224}, /* version 37 */
265 : {5039, 3054, 2099, 1292}, /* version 38 */
266 : {5313, 3220, 2213, 1362}, /* version 39 */
267 : {5596, 3391, 2331, 1435}, /* version 40 */
268 : },
269 : /* ECL Q */
270 : {
271 : {-1, -1, -1, -1}, /* version 0 (invalid) */
272 : {27, 16, 11, 7}, /* version 1 */
273 : {48, 29, 20, 12}, /* version 2 */
274 : {77, 47, 32, 20}, /* version 3 */
275 : {111, 67, 46, 28}, /* version 4 */
276 : {144, 87, 60, 37}, /* version 5 */
277 : {178, 108, 74, 45}, /* version 6 */
278 : {207, 125, 86, 53}, /* version 7 */
279 : {259, 157, 108, 66}, /* version 8 */
280 : {312, 189, 130, 80}, /* version 9 */
281 : {364, 221, 151, 93}, /* version 10 */
282 : {427, 259, 177, 109}, /* version 11 */
283 : {489, 296, 203, 125}, /* version 12 */
284 : {580, 352, 241, 149}, /* version 13 */
285 : {621, 376, 258, 159}, /* version 14 */
286 : {703, 426, 292, 180}, /* version 15 */
287 : {775, 470, 322, 198}, /* version 16 */
288 : {876, 531, 364, 224}, /* version 17 */
289 : {948, 574, 394, 243}, /* version 18 */
290 : {1063, 644, 442, 272}, /* version 19 */
291 : {1159, 702, 482, 297}, /* version 20 */
292 : {1224, 742, 509, 314}, /* version 21 */
293 : {1358, 823, 565, 348}, /* version 22 */
294 : {1468, 890, 611, 376}, /* version 23 */
295 : {1588, 963, 661, 407}, /* version 24 */
296 : {1718, 1041, 715, 440}, /* version 25 */
297 : {1804, 1094, 751, 462}, /* version 26 */
298 : {1933, 1172, 805, 496}, /* version 27 */
299 : {2085, 1263, 868, 534}, /* version 28 */
300 : {2181, 1322, 908, 559}, /* version 29 */
301 : {2358, 1429, 982, 604}, /* version 30 */
302 : {2473, 1499, 1030, 634}, /* version 31 */
303 : {2670, 1618, 1112, 684}, /* version 32 */
304 : {2805, 1700, 1168, 719}, /* version 33 */
305 : {2949, 1787, 1228, 756}, /* version 34 */
306 : {3081, 1867, 1283, 790}, /* version 35 */
307 : {3244, 1966, 1351, 832}, /* version 36 */
308 : {3417, 2071, 1423, 876}, /* version 37 */
309 : {3599, 2181, 1499, 923}, /* version 38 */
310 : {3791, 2298, 1579, 972}, /* version 39 */
311 : {3993, 2420, 1663, 1024}, /* version 40 */
312 : },
313 : /* ECL H */
314 : {
315 : {-1, -1, -1, -1}, /* version 0 (invalid) */
316 : {17, 10, 7, 4}, /* version 1 */
317 : {34, 20, 14, 8}, /* version 2 */
318 : {58, 35, 24, 15}, /* version 3 */
319 : {82, 50, 34, 21}, /* version 4 */
320 : {106, 64, 44, 27}, /* version 5 */
321 : {139, 84, 58, 36}, /* version 6 */
322 : {154, 93, 64, 39}, /* version 7 */
323 : {202, 122, 84, 52}, /* version 8 */
324 : {235, 143, 98, 60}, /* version 9 */
325 : {288, 174, 119, 74}, /* version 10 */
326 : {331, 200, 137, 85}, /* version 11 */
327 : {374, 227, 155, 96}, /* version 12 */
328 : {427, 259, 177, 109}, /* version 13 */
329 : {468, 283, 194, 120}, /* version 14 */
330 : {530, 321, 220, 136}, /* version 15 */
331 : {602, 365, 250, 154}, /* version 16 */
332 : {674, 408, 280, 173}, /* version 17 */
333 : {746, 452, 310, 191}, /* version 18 */
334 : {813, 493, 338, 208}, /* version 19 */
335 : {919, 557, 382, 235}, /* version 20 */
336 : {969, 587, 403, 248}, /* version 21 */
337 : {1056, 640, 439, 270}, /* version 22 */
338 : {1108, 672, 461, 284}, /* version 23 */
339 : {1228, 744, 511, 315}, /* version 24 */
340 : {1286, 779, 535, 330}, /* version 25 */
341 : {1425, 864, 593, 365}, /* version 26 */
342 : {1501, 910, 625, 385}, /* version 27 */
343 : {1581, 958, 658, 405}, /* version 28 */
344 : {1677, 1016, 698, 430}, /* version 29 */
345 : {1782, 1080, 742, 457}, /* version 30 */
346 : {1897, 1150, 790, 486}, /* version 31 */
347 : {2022, 1226, 842, 518}, /* version 32 */
348 : {2157, 1307, 898, 553}, /* version 33 */
349 : {2301, 1394, 958, 590}, /* version 34 */
350 : {2361, 1431, 983, 605}, /* version 35 */
351 : {2524, 1530, 1051, 647}, /* version 36 */
352 : {2625, 1591, 1093, 673}, /* version 37 */
353 : {2735, 1658, 1139, 701}, /* version 38 */
354 : {2927, 1774, 1219, 750}, /* version 39 */
355 : {3057, 1852, 1273, 784}, /* version 40 */
356 : },
357 : };
358 :
359 106782 : static inline void append_bits(uint32_t val, uint8_t num_bits, uint8_t buffer[], int32_t *bit_len)
360 : {
361 : int32_t i;
362 :
363 950110 : for (i = num_bits - 1; i >= 0; i--, (*bit_len)++) {
364 843328 : buffer[*bit_len >> 3] |= ((val >> i) & 1) << (7 - (*bit_len & 7));
365 : }
366 106782 : }
367 :
368 1450 : static inline int32_t get_num_raw_data_modules(uint8_t ver)
369 : {
370 : int32_t result, num_align;
371 :
372 1450 : result = (16 * ver + 128) * ver + 64;
373 1450 : if (ver >= 2) {
374 1238 : num_align = ver / 7 + 2;
375 1238 : result -= (25 * num_align - 10) * num_align - 55;
376 1238 : if (ver >= 7) {
377 284 : result -= 36;
378 : }
379 : }
380 1450 : return result;
381 : }
382 :
383 5609 : static inline int32_t get_num_data_codewords(uint8_t version, uint8_t ecl)
384 : {
385 5609 : if (ecl > 3 || version < 1 || version > 40) {
386 0 : return DATA_CODEWORDS[0][version < 1 ? 1 : (version > 40 ? 40 : version)];
387 : }
388 :
389 5609 : return DATA_CODEWORDS[ecl][version];
390 : }
391 :
392 725 : static inline bool add_ecc_and_interleave(uint8_t data[], uint8_t version, uint8_t ecl, uint8_t result[])
393 : {
394 : const uint8_t *dat;
395 : poporon_t *pprn;
396 : poporon_config_t *config;
397 : uint8_t num_blocks, block_ecc_len, num_short_blocks, short_block_data_len, *ecc;
398 : int32_t raw_codewords, data_len, i, j, k, dat_len;
399 :
400 725 : num_blocks = NUM_ERROR_CORRECTION_BLOCKS[ecl][version];
401 725 : block_ecc_len = ECC_CODEWORDS_PER_BLOCK[ecl][version];
402 725 : raw_codewords = get_num_raw_data_modules(version) >> 3;
403 725 : data_len = get_num_data_codewords(version, ecl);
404 725 : num_short_blocks = num_blocks - raw_codewords % num_blocks;
405 725 : short_block_data_len = raw_codewords / num_blocks - block_ecc_len;
406 :
407 725 : config = poporon_rs_config_create(8, RS_GF256_PRIMITIVE_POLY, 0, 1, block_ecc_len, NULL, NULL);
408 725 : if (!config) {
409 0 : return false;
410 : }
411 :
412 725 : pprn = poporon_create(config);
413 725 : if (!pprn) {
414 0 : poporon_config_destroy(config);
415 0 : return false;
416 : }
417 :
418 725 : dat = data;
419 :
420 3729 : for (i = 0; i < num_blocks; i++) {
421 3004 : dat_len = short_block_data_len + (i < num_short_blocks ? 0 : 1);
422 3004 : ecc = &data[data_len];
423 :
424 3004 : poporon_encode(pprn, (uint8_t *)dat, (size_t)dat_len, ecc);
425 :
426 108420 : for (j = 0, k = i; j < dat_len; j++, k += num_blocks) {
427 105416 : if (j == short_block_data_len) {
428 1073 : k -= num_short_blocks;
429 : }
430 105416 : result[k] = dat[j];
431 : }
432 :
433 75804 : for (j = 0, k = data_len + i; j < block_ecc_len; j++, k += num_blocks) {
434 72800 : result[k] = ecc[j];
435 : }
436 :
437 3004 : dat += dat_len;
438 : }
439 :
440 725 : poporon_destroy(pprn);
441 725 : poporon_config_destroy(config);
442 725 : return true;
443 : }
444 :
445 2175 : static inline uint8_t get_alignment_pattern_positions(uint8_t version, uint8_t result[7])
446 : {
447 : uint8_t num_align, step, i, pos;
448 :
449 2175 : if (version == 1) {
450 318 : return 0;
451 : }
452 :
453 1857 : num_align = version / 7 + 2;
454 1857 : step = (version * 8 + num_align * 3 + 5) / (num_align * 4 - 4) * 2;
455 :
456 4542 : for (i = num_align - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) {
457 2685 : result[i] = pos;
458 : }
459 :
460 1857 : result[0] = 6;
461 :
462 1857 : return num_align;
463 : }
464 :
465 12864 : static inline void fill_rectangle(int32_t left, int32_t top, int32_t width, int32_t height, uint8_t qrcode[])
466 : {
467 : int32_t dx, dy, qrsize, index, byte_idx, bit_idx;
468 :
469 12864 : qrsize = qrcode[0];
470 :
471 137722 : for (dy = 0; dy < height; dy++) {
472 703326 : for (dx = 0; dx < width; dx++) {
473 578468 : index = (top + dy) * qrsize + (left + dx);
474 578468 : byte_idx = (index >> 3) + 1;
475 578468 : bit_idx = index & 7;
476 578468 : qrcode[byte_idx] |= 1 << bit_idx;
477 : }
478 : }
479 12864 : }
480 :
481 132851923 : static inline bool get_module(const uint8_t qrcode[], int32_t x, int32_t y)
482 : {
483 : int32_t qrsize, index;
484 :
485 132851923 : qrsize = qrcode[0];
486 132851923 : if (x < 0 || x >= qrsize || y < 0 || y >= qrsize) {
487 0 : return false;
488 : }
489 :
490 132851923 : index = y * qrsize + x;
491 :
492 132851923 : return ((qrcode[(index >> 3) + 1] >> (index & 7)) & 1) != 0;
493 : }
494 :
495 24129115 : static inline void set_module(uint8_t qrcode[], int32_t x, int32_t y, bool is_dark)
496 : {
497 : int32_t qrsize, index, bit_idx, byte_idx;
498 :
499 24129115 : qrsize = qrcode[0];
500 24129115 : if (x < 0 || x >= qrsize || y < 0 || y >= qrsize) {
501 36975 : return;
502 : }
503 :
504 24092140 : index = y * qrsize + x;
505 24092140 : bit_idx = index & 7;
506 24092140 : byte_idx = (index >> 3) + 1;
507 :
508 24092140 : if (is_dark) {
509 11672800 : qrcode[byte_idx] |= 1 << bit_idx;
510 : } else {
511 12419340 : qrcode[byte_idx] &= (1 << bit_idx) ^ 0xFF;
512 : }
513 : }
514 :
515 1450 : static inline void initialize_function_modules(uint8_t version, uint8_t qrcode[])
516 : {
517 : uint8_t qrsize, align_pat_pos[7], num_align, i, j;
518 :
519 1450 : qrsize = QR_VERSION_SIZE_FORMULA(version);
520 1450 : lmemset(qrcode, 0, (size_t)(((qrsize * qrsize + 7) >> 3) + 1) * sizeof(qrcode[0]));
521 1450 : qrcode[0] = qrsize;
522 :
523 1450 : fill_rectangle(TIMING_PATTERN_POSITION, 0, 1, qrsize, qrcode);
524 1450 : fill_rectangle(0, TIMING_PATTERN_POSITION, qrsize, 1, qrcode);
525 :
526 1450 : fill_rectangle(0, 0, FINDER_CORNER_SIZE, FINDER_CORNER_SIZE, qrcode);
527 1450 : fill_rectangle(qrsize - FINDER_QUIET_SIZE, 0, FINDER_QUIET_SIZE, FINDER_CORNER_SIZE, qrcode);
528 1450 : fill_rectangle(0, qrsize - FINDER_QUIET_SIZE, FINDER_CORNER_SIZE, FINDER_QUIET_SIZE, qrcode);
529 :
530 1450 : num_align = get_alignment_pattern_positions(version, align_pat_pos);
531 :
532 4478 : for (i = 0; i < num_align; i++) {
533 11788 : for (j = 0; j < num_align; j++) {
534 8760 : if (!((i == 0 && j == 0) || (i == 0 && j == num_align - 1) || (i == num_align - 1 && j == 0))) {
535 5046 : fill_rectangle(align_pat_pos[i] - ALIGNMENT_PATTERN_OFFSET, align_pat_pos[j] - ALIGNMENT_PATTERN_OFFSET,
536 : ALIGNMENT_PATTERN_SIZE, ALIGNMENT_PATTERN_SIZE, qrcode);
537 : }
538 : }
539 : }
540 :
541 1450 : if (version >= VERSION_INFO_MIN) {
542 284 : fill_rectangle(qrsize - VERSION_INFO_OFFSET, 0, VERSION_INFO_AREA_WIDTH, VERSION_INFO_AREA_HEIGHT, qrcode);
543 284 : fill_rectangle(0, qrsize - VERSION_INFO_OFFSET, VERSION_INFO_AREA_HEIGHT, VERSION_INFO_AREA_WIDTH, qrcode);
544 : }
545 1450 : }
546 :
547 725 : static inline void draw_light_function_modules(uint8_t qrcode[], uint8_t version)
548 : {
549 : uint32_t bits;
550 : uint8_t align_pat_pos[7], num_align;
551 : int32_t qrsize, i, j, k, dx, dy, dist, rem;
552 :
553 725 : qrsize = qrcode[0];
554 10493 : for (i = TIMING_PATTERN_START; i < qrsize - TIMING_PATTERN_START; i += 2) {
555 9768 : set_module(qrcode, TIMING_PATTERN_POSITION, i, false);
556 9768 : set_module(qrcode, i, TIMING_PATTERN_POSITION, false);
557 : }
558 :
559 7250 : for (dy = -FINDER_PATTERN_RADIUS; dy <= FINDER_PATTERN_RADIUS; dy++) {
560 65250 : for (dx = -FINDER_PATTERN_RADIUS; dx <= FINDER_PATTERN_RADIUS; dx++) {
561 58725 : dist = (dx < 0) ? -dx : dx;
562 :
563 58725 : if ((dy < 0 ? -dy : dy) > dist) {
564 23200 : dist = (dy < 0) ? -dy : dy;
565 : }
566 :
567 58725 : if (dist == ALIGNMENT_PATTERN_OFFSET || dist == FINDER_PATTERN_RADIUS) {
568 34800 : set_module(qrcode, FINDER_PATTERN_CENTER + dx, FINDER_PATTERN_CENTER + dy, false);
569 34800 : set_module(qrcode, qrsize - FINDER_PATTERN_RADIUS + dx, FINDER_PATTERN_CENTER + dy, false);
570 34800 : set_module(qrcode, FINDER_PATTERN_CENTER + dx, qrsize - FINDER_PATTERN_RADIUS + dy, false);
571 : }
572 : }
573 : }
574 :
575 725 : num_align = get_alignment_pattern_positions(version, align_pat_pos);
576 2239 : for (i = 0; i < num_align; i++) {
577 5894 : for (j = 0; j < num_align; j++) {
578 4380 : if ((i == 0 && j == 0) || (i == 0 && j == num_align - 1) || (i == num_align - 1 && j == 0)) {
579 1857 : continue;
580 : }
581 :
582 10092 : for (dy = -1; dy <= 1; dy++) {
583 30276 : for (dx = -1; dx <= 1; dx++) {
584 22707 : set_module(qrcode, align_pat_pos[i] + dx, align_pat_pos[j] + dy, dx == 0 && dy == 0);
585 : }
586 : }
587 : }
588 : }
589 :
590 725 : if (version >= VERSION_INFO_MIN) {
591 142 : rem = version;
592 :
593 1846 : for (i = 0; i < VERSION_INFO_BITS; i++) {
594 1704 : rem = (rem << 1) ^ ((rem >> VERSION_INFO_SHIFT) * VERSION_INFO_POLY);
595 : }
596 :
597 142 : bits = (uint32_t)version << VERSION_INFO_DATA_SHIFT | (uint32_t)rem;
598 :
599 994 : for (i = 0; i < VERSION_INFO_AREA_HEIGHT; i++) {
600 3408 : for (j = 0; j < VERSION_INFO_AREA_WIDTH; j++) {
601 2556 : k = qrsize - VERSION_INFO_OFFSET + j;
602 :
603 2556 : set_module(qrcode, k, i, (bits & 1) != 0);
604 2556 : set_module(qrcode, i, k, (bits & 1) != 0);
605 2556 : bits >>= 1;
606 : }
607 : }
608 : }
609 725 : }
610 :
611 5053 : static inline void draw_format_bits(uint8_t ecl, int8_t mask, uint8_t qrcode[])
612 : {
613 : static const int32_t table[] = {1, 0, 3, 2};
614 : int32_t data, rem, bits_val, qrsize, i;
615 :
616 5053 : data = table[ecl] << 3 | mask;
617 5053 : rem = data;
618 :
619 55583 : for (i = 0; i < FORMAT_DATA_SHIFT; i++) {
620 50530 : rem = (rem << 1) ^ ((rem >> FORMAT_POLY_SHIFT) * FORMAT_POLY);
621 : }
622 :
623 5053 : bits_val = (data << FORMAT_DATA_SHIFT | rem) ^ FORMAT_XOR_MASK;
624 :
625 35371 : for (i = 0; i <= 5; i++) {
626 30318 : set_module(qrcode, 8, i, ((bits_val >> i) & 1) != 0);
627 : }
628 :
629 5053 : set_module(qrcode, 8, 7, ((bits_val >> 6) & 1) != 0);
630 5053 : set_module(qrcode, 8, 8, ((bits_val >> 7) & 1) != 0);
631 5053 : set_module(qrcode, 7, 8, ((bits_val >> 8) & 1) != 0);
632 :
633 35371 : for (i = FORMAT_BITS_LOOP_START; i < FORMAT_BITS_COUNT; i++) {
634 30318 : set_module(qrcode, 14 - i, 8, ((bits_val >> i) & 1) != 0);
635 : }
636 :
637 5053 : qrsize = qrcode[0];
638 :
639 45477 : for (i = 0; i < FINDER_QUIET_SIZE; i++) {
640 40424 : set_module(qrcode, qrsize - 1 - i, 8, ((bits_val >> i) & 1) != 0);
641 : }
642 :
643 40424 : for (i = FINDER_QUIET_SIZE; i < FORMAT_BITS_COUNT; i++) {
644 35371 : set_module(qrcode, 8, qrsize - FORMAT_BITS_COUNT + i, ((bits_val >> i) & 1) != 0);
645 : }
646 :
647 5053 : set_module(qrcode, 8, qrsize - FINDER_QUIET_SIZE, true);
648 5053 : }
649 :
650 725 : static inline void draw_codewords(const uint8_t data[], int32_t data_len, uint8_t qrcode[])
651 : {
652 : int32_t qrsize, bit_idx, right, vert, j, x, y;
653 : bool upward, dark;
654 :
655 725 : qrsize = qrcode[0];
656 725 : bit_idx = 0;
657 :
658 14843 : for (right = qrsize - 1; right >= 1; right -= 2) {
659 14118 : if (right == 6) {
660 725 : right = 5;
661 : }
662 :
663 845156 : for (vert = 0; vert < qrsize; vert++) {
664 2493114 : for (j = 0; j < 2; j++) {
665 1662076 : x = right - j;
666 1662076 : upward = ((right + 1) & 2) == 0;
667 1662076 : y = upward ? qrsize - 1 - vert : vert;
668 :
669 1662076 : if (!get_module(qrcode, x, y) && bit_idx < data_len * 8) {
670 1425728 : dark = ((data[bit_idx >> 3] >> (7 - (bit_idx & 7))) & 1) != 0;
671 1425728 : set_module(qrcode, x, y, dark);
672 1425728 : bit_idx++;
673 : }
674 : }
675 : }
676 : }
677 725 : }
678 :
679 9381 : static inline void apply_mask(const uint8_t function_modules[], uint8_t qrcode[], int8_t mask)
680 : {
681 : int32_t qrsize, y, x;
682 : bool invert, val;
683 :
684 9381 : qrsize = qrcode[0];
685 :
686 413782 : for (y = 0; y < qrsize; y++) {
687 26449822 : for (x = 0; x < qrsize; x++) {
688 26045421 : if (get_module(function_modules, x, y)) {
689 3650432 : continue;
690 : }
691 :
692 22394989 : switch (mask) {
693 2903648 : case 0:
694 2903648 : invert = (x + y) % 2 == 0;
695 2903648 : break;
696 2659304 : case 1:
697 2659304 : invert = y % 2 == 0;
698 2659304 : break;
699 2965000 : case 2:
700 2965000 : invert = x % 3 == 0;
701 2965000 : break;
702 2925246 : case 3:
703 2925246 : invert = (x + y) % 3 == 0;
704 2925246 : break;
705 2828161 : case 4:
706 2828161 : invert = (x / 3 + y / 2) % 2 == 0;
707 2828161 : break;
708 2672945 : case 5:
709 2672945 : invert = x * y % 2 + x * y % 3 == 0;
710 2672945 : break;
711 2737328 : case 6:
712 2737328 : invert = (x * y % 2 + x * y % 3) % 2 == 0;
713 2737328 : break;
714 2703357 : case 7:
715 2703357 : invert = ((x + y) % 2 + x * y % 3) % 2 == 0;
716 2703357 : break;
717 0 : default:
718 0 : invert = false;
719 0 : break;
720 : }
721 :
722 22394989 : val = get_module(qrcode, x, y);
723 22394989 : set_module(qrcode, x, y, val ^ invert);
724 : }
725 : }
726 9381 : }
727 :
728 12732054 : static inline int32_t finder_penalty_add_history(int32_t current_run_len, int32_t run_history[PENALTY_HISTORY_SIZE],
729 : int32_t qrsize)
730 : {
731 12732054 : if (run_history[0] == 0) {
732 375440 : current_run_len += qrsize;
733 : }
734 :
735 12732054 : lmemmove(&run_history[1], &run_history[0], PENALTY_HISTORY_MOVE_SIZE * sizeof(run_history[0]));
736 12732054 : run_history[0] = current_run_len;
737 :
738 12732054 : return current_run_len;
739 : }
740 :
741 6553747 : static inline int32_t finder_penalty_count_patterns(const int32_t run_history[PENALTY_HISTORY_SIZE], int32_t qrsize)
742 : {
743 : int32_t n;
744 : bool core;
745 :
746 6553747 : n = run_history[1];
747 : (void)qrsize;
748 6553747 : core = n > 0 && run_history[2] == n && run_history[3] == n * 3 && run_history[4] == n && run_history[5] == n;
749 13107494 : return (core && run_history[0] >= n * 4 && run_history[6] >= n ? 1 : 0) +
750 6553747 : (core && run_history[6] >= n * 4 && run_history[0] >= n ? 1 : 0);
751 : }
752 :
753 375440 : static inline int32_t finder_penalty_terminate(bool current_run_color, int32_t current_run_len,
754 : int32_t run_history[PENALTY_HISTORY_SIZE], int32_t qrsize)
755 : {
756 375440 : if (current_run_color) {
757 210220 : finder_penalty_add_history(current_run_len, run_history, qrsize);
758 210220 : current_run_len = 0;
759 : }
760 :
761 375440 : current_run_len += qrsize;
762 :
763 375440 : finder_penalty_add_history(current_run_len, run_history, qrsize);
764 :
765 375440 : return finder_penalty_count_patterns(run_history, qrsize);
766 : }
767 :
768 4328 : static inline int32_t get_penalty_score(const uint8_t qrcode[])
769 : {
770 : int32_t qrsize, y, x, run_x, run_y, run_history[PENALTY_HISTORY_SIZE], dark, total, k, result;
771 : bool run_color, color;
772 :
773 4328 : qrsize = qrcode[0];
774 4328 : result = 0;
775 :
776 192048 : for (y = 0; y < qrsize; y++) {
777 187720 : run_color = false;
778 187720 : run_x = 0;
779 187720 : lmemset(run_history, 0, sizeof(run_history));
780 :
781 12364912 : for (x = 0; x < qrsize; x++) {
782 12177192 : if (get_module(qrcode, x, y) == run_color) {
783 6101801 : run_x++;
784 6101801 : if (run_x == PENALTY_RUN_THRESHOLD) {
785 415024 : result += PENALTY_RUN_BASE;
786 5686777 : } else if (run_x > PENALTY_RUN_THRESHOLD) {
787 480823 : result++;
788 : }
789 : } else {
790 6075391 : finder_penalty_add_history(run_x, run_history, qrsize);
791 6075391 : if (!run_color) {
792 3088947 : result += finder_penalty_count_patterns(run_history, qrsize) * PENALTY_FINDER_LIKE;
793 : }
794 6075391 : run_color = get_module(qrcode, x, y);
795 6075391 : run_x = 1;
796 : }
797 : }
798 187720 : result += finder_penalty_terminate(run_color, run_x, run_history, qrsize) * PENALTY_FINDER_LIKE;
799 : }
800 :
801 192048 : for (x = 0; x < qrsize; x++) {
802 187720 : run_color = false;
803 187720 : run_y = 0;
804 187720 : lmemset(run_history, 0, sizeof(run_history));
805 :
806 12364912 : for (y = 0; y < qrsize; y++) {
807 12177192 : if (get_module(qrcode, x, y) == run_color) {
808 6106189 : run_y++;
809 6106189 : if (run_y == PENALTY_RUN_THRESHOLD) {
810 402837 : result += PENALTY_RUN_BASE;
811 5703352 : } else if (run_y > PENALTY_RUN_THRESHOLD) {
812 496823 : result++;
813 : }
814 : } else {
815 6071003 : finder_penalty_add_history(run_y, run_history, qrsize);
816 6071003 : if (!run_color) {
817 3089360 : result += finder_penalty_count_patterns(run_history, qrsize) * PENALTY_FINDER_LIKE;
818 : }
819 6071003 : run_color = get_module(qrcode, x, y);
820 6071003 : run_y = 1;
821 : }
822 : }
823 :
824 187720 : result += finder_penalty_terminate(run_color, run_y, run_history, qrsize) * PENALTY_FINDER_LIKE;
825 : }
826 :
827 187720 : for (y = 0; y < qrsize - 1; y++) {
828 11989472 : for (x = 0; x < qrsize - 1; x++) {
829 11806080 : color = get_module(qrcode, x, y);
830 14638917 : if (color == get_module(qrcode, x + 1, y) && color == get_module(qrcode, x, y + 1) &&
831 2832837 : color == get_module(qrcode, x + 1, y + 1)) {
832 1402264 : result += PENALTY_2X2_BLOCK;
833 : }
834 : }
835 : }
836 :
837 4328 : dark = 0;
838 192048 : for (y = 0; y < qrsize; y++) {
839 12364912 : for (x = 0; x < qrsize; x++) {
840 12177192 : if (get_module(qrcode, x, y)) {
841 6170136 : dark++;
842 : }
843 : }
844 : }
845 :
846 4328 : total = qrsize * qrsize;
847 :
848 8656 : k = ((dark * PENALTY_BALANCE_FACTOR_DARK - total * PENALTY_BALANCE_FACTOR_TOTAL) < 0
849 1499 : ? -(dark * PENALTY_BALANCE_FACTOR_DARK - total * PENALTY_BALANCE_FACTOR_TOTAL)
850 4328 : : (dark * PENALTY_BALANCE_FACTOR_DARK - total * PENALTY_BALANCE_FACTOR_TOTAL));
851 :
852 4328 : k = (k + total - 1) / total - 1;
853 :
854 4328 : result += k * PENALTY_BALANCE_MULTIPLIER;
855 :
856 4328 : return result;
857 : }
858 :
859 : static inline bool is_numeric_data(const uint8_t *data, size_t data_len)
860 : {
861 : size_t i;
862 :
863 : for (i = 0; i < data_len; i++) {
864 : if (data[i] < '0' || data[i] > '9') {
865 : return false;
866 : }
867 : }
868 :
869 : return true;
870 : }
871 :
872 3 : static inline int32_t numeric_count_bits(uint8_t version, size_t char_count)
873 : {
874 : int32_t count_bits;
875 :
876 3 : if (version < VERSION_THRESHOLD_SMALL) {
877 3 : count_bits = NUMERIC_BITS_SMALL;
878 0 : } else if (version < VERSION_THRESHOLD_MEDIUM) {
879 0 : count_bits = NUMERIC_BITS_MEDIUM;
880 : } else {
881 0 : count_bits = NUMERIC_BITS_LARGE;
882 : }
883 :
884 3 : return QR_MODE_INDICATOR_BITS + count_bits + ((int32_t)char_count / NUMERIC_GROUP_SIZE) * NUMERIC_GROUP_BITS +
885 3 : ((char_count % NUMERIC_GROUP_SIZE == 1)
886 : ? NUMERIC_REMAINDER1_BITS
887 3 : : ((char_count % NUMERIC_GROUP_SIZE == 2) ? NUMERIC_REMAINDER2_BITS : 0));
888 : }
889 :
890 2 : static inline bool encode_numeric(const uint8_t *data, size_t data_len, uint8_t temp_buffer[], uint8_t qrcode[],
891 : uint8_t ecl, int8_t min_version, int8_t max_version, int8_t mask)
892 : {
893 : uint8_t pad_byte, version, best_mask;
894 : int32_t data_capacity_bits, data_used_bits, bit_len, terminator_bits, i, min_penalty, penalty, count_bits, value;
895 : size_t idx;
896 :
897 2 : for (version = min_version;; version++) {
898 3 : data_capacity_bits = get_num_data_codewords(version, ecl) * 8;
899 3 : data_used_bits = numeric_count_bits(version, data_len);
900 :
901 3 : if (data_used_bits <= data_capacity_bits) {
902 2 : break;
903 : }
904 :
905 1 : if (version >= max_version) {
906 0 : qrcode[0] = 0;
907 0 : return false;
908 : }
909 : }
910 :
911 2 : if (version < VERSION_THRESHOLD_SMALL) {
912 2 : count_bits = NUMERIC_BITS_SMALL;
913 0 : } else if (version < VERSION_THRESHOLD_MEDIUM) {
914 0 : count_bits = NUMERIC_BITS_MEDIUM;
915 : } else {
916 0 : count_bits = NUMERIC_BITS_LARGE;
917 : }
918 :
919 2 : lmemset(qrcode, 0, (size_t)QR_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0]));
920 2 : bit_len = 0;
921 2 : append_bits(QR_MODE_NUMERIC_INDICATOR, QR_MODE_INDICATOR_BITS, qrcode, &bit_len);
922 2 : append_bits((uint32_t)data_len, count_bits, qrcode, &bit_len);
923 :
924 2 : idx = 0;
925 21 : while (idx + NUMERIC_GROUP_SIZE <= data_len) {
926 19 : value = (data[idx] - '0') * 100 + (data[idx + 1] - '0') * 10 + (data[idx + 2] - '0');
927 19 : append_bits((uint32_t)value, NUMERIC_GROUP_BITS, qrcode, &bit_len);
928 19 : idx += NUMERIC_GROUP_SIZE;
929 : }
930 :
931 2 : if (data_len - idx == 2) {
932 1 : value = (data[idx] - '0') * 10 + (data[idx + 1] - '0');
933 1 : append_bits((uint32_t)value, NUMERIC_REMAINDER2_BITS, qrcode, &bit_len);
934 1 : } else if (data_len - idx == 1) {
935 1 : value = data[idx] - '0';
936 1 : append_bits((uint32_t)value, NUMERIC_REMAINDER1_BITS, qrcode, &bit_len);
937 : }
938 :
939 2 : data_capacity_bits = get_num_data_codewords(version, ecl) * QR_PAD_BYTE_BITS;
940 2 : terminator_bits = data_capacity_bits - bit_len;
941 :
942 2 : if (terminator_bits > QR_TERMINATOR_MAX_BITS) {
943 2 : terminator_bits = QR_TERMINATOR_MAX_BITS;
944 : }
945 :
946 2 : append_bits(0, terminator_bits, qrcode, &bit_len);
947 2 : append_bits(0, (QR_PAD_BYTE_BITS - bit_len % QR_PAD_BYTE_BITS) % QR_PAD_BYTE_BITS, qrcode, &bit_len);
948 :
949 21 : for (pad_byte = PAD_BYTE_FIRST; bit_len < data_capacity_bits; pad_byte ^= PAD_BYTE_FIRST ^ PAD_BYTE_SECOND) {
950 19 : append_bits(pad_byte, QR_PAD_BYTE_BITS, qrcode, &bit_len);
951 : }
952 :
953 2 : if (!add_ecc_and_interleave(qrcode, version, ecl, temp_buffer)) {
954 0 : return false;
955 : }
956 2 : initialize_function_modules(version, qrcode);
957 2 : draw_codewords(temp_buffer, get_num_raw_data_modules(version) >> 3, qrcode);
958 2 : draw_light_function_modules(qrcode, version);
959 2 : initialize_function_modules(version, temp_buffer);
960 :
961 2 : if (mask < 0) {
962 2 : min_penalty = INT32_MAX;
963 2 : best_mask = 0;
964 :
965 18 : for (i = 0; i < QR_MASK_COUNT; i++) {
966 16 : apply_mask(temp_buffer, qrcode, (int8_t)i);
967 16 : draw_format_bits(ecl, (int8_t)i, qrcode);
968 16 : penalty = get_penalty_score(qrcode);
969 :
970 16 : if (penalty < min_penalty) {
971 2 : best_mask = (int8_t)i;
972 2 : min_penalty = penalty;
973 : }
974 :
975 16 : apply_mask(temp_buffer, qrcode, (int8_t)i);
976 : }
977 2 : mask = best_mask;
978 : }
979 :
980 2 : apply_mask(temp_buffer, qrcode, mask);
981 2 : draw_format_bits(ecl, mask, qrcode);
982 :
983 2 : return true;
984 : }
985 :
986 26 : static inline int8_t alphanumeric_char_value(uint8_t c)
987 : {
988 26 : if (c >= '0' && c <= '9') {
989 3 : return (int8_t)(c - '0');
990 : }
991 :
992 23 : if (c >= 'A' && c <= 'Z') {
993 13 : return (int8_t)(c - 'A' + ALPHA_LETTER_OFFSET);
994 : }
995 :
996 10 : switch (c) {
997 2 : case ' ':
998 2 : return ALPHA_SPACE_VALUE;
999 1 : case '$':
1000 1 : return ALPHA_DOLLAR_VALUE;
1001 1 : case '%':
1002 1 : return ALPHA_PERCENT_VALUE;
1003 1 : case '*':
1004 1 : return ALPHA_ASTERISK_VALUE;
1005 1 : case '+':
1006 1 : return ALPHA_PLUS_VALUE;
1007 1 : case '-':
1008 1 : return ALPHA_MINUS_VALUE;
1009 1 : case '.':
1010 1 : return ALPHA_DOT_VALUE;
1011 1 : case '/':
1012 1 : return ALPHA_SLASH_VALUE;
1013 1 : case ':':
1014 1 : return ALPHA_COLON_VALUE;
1015 0 : default:
1016 0 : return -1;
1017 : }
1018 : }
1019 :
1020 : static inline bool is_alphanumeric_data(const uint8_t *data, size_t data_len)
1021 : {
1022 : size_t i;
1023 :
1024 : for (i = 0; i < data_len; i++) {
1025 : if (alphanumeric_char_value(data[i]) < 0) {
1026 : return false;
1027 : }
1028 : }
1029 :
1030 : return true;
1031 : }
1032 :
1033 2 : static inline int32_t alphanumeric_count_bits(uint8_t version, size_t char_count)
1034 : {
1035 : int32_t count_bits;
1036 :
1037 2 : if (version < VERSION_THRESHOLD_SMALL) {
1038 2 : count_bits = ALPHA_BITS_SMALL;
1039 0 : } else if (version < VERSION_THRESHOLD_MEDIUM) {
1040 0 : count_bits = ALPHA_BITS_MEDIUM;
1041 : } else {
1042 0 : count_bits = ALPHA_BITS_LARGE;
1043 : }
1044 :
1045 2 : return QR_MODE_INDICATOR_BITS + count_bits +
1046 2 : ((int32_t)char_count / ALPHANUMERIC_GROUP_SIZE) * ALPHANUMERIC_GROUP_BITS +
1047 2 : ((char_count % ALPHANUMERIC_GROUP_SIZE) ? ALPHANUMERIC_REMAINDER_BITS : 0);
1048 : }
1049 :
1050 2 : static inline bool encode_alphanumeric(const uint8_t *data, size_t data_len, uint8_t temp_buffer[], uint8_t qrcode[],
1051 : uint8_t ecl, int8_t min_version, int8_t max_version, int8_t mask)
1052 : {
1053 : uint8_t pad_byte, version, best_mask;
1054 : int32_t data_capacity_bits, data_used_bits, bit_len, terminator_bits, i, min_penalty, penalty, count_bits, value;
1055 : size_t idx;
1056 :
1057 2 : for (version = min_version;; version++) {
1058 2 : data_capacity_bits = get_num_data_codewords(version, ecl) * 8;
1059 2 : data_used_bits = alphanumeric_count_bits(version, data_len);
1060 :
1061 2 : if (data_used_bits <= data_capacity_bits) {
1062 2 : break;
1063 : }
1064 :
1065 0 : if (version >= max_version) {
1066 0 : qrcode[0] = 0;
1067 0 : return false;
1068 : }
1069 : }
1070 :
1071 2 : if (version < VERSION_THRESHOLD_SMALL) {
1072 2 : count_bits = ALPHA_BITS_SMALL;
1073 0 : } else if (version < VERSION_THRESHOLD_MEDIUM) {
1074 0 : count_bits = ALPHA_BITS_MEDIUM;
1075 : } else {
1076 0 : count_bits = ALPHA_BITS_LARGE;
1077 : }
1078 :
1079 2 : lmemset(qrcode, 0, (size_t)QR_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0]));
1080 2 : bit_len = 0;
1081 2 : append_bits(QR_MODE_ALPHANUMERIC_INDICATOR, QR_MODE_INDICATOR_BITS, qrcode, &bit_len);
1082 2 : append_bits((uint32_t)data_len, count_bits, qrcode, &bit_len);
1083 :
1084 2 : idx = 0;
1085 14 : while (idx + ALPHANUMERIC_GROUP_SIZE <= data_len) {
1086 12 : value = alphanumeric_char_value(data[idx]) * ALPHANUMERIC_CHARSET_SIZE + alphanumeric_char_value(data[idx + 1]);
1087 12 : append_bits((uint32_t)value, ALPHANUMERIC_GROUP_BITS, qrcode, &bit_len);
1088 12 : idx += ALPHANUMERIC_GROUP_SIZE;
1089 : }
1090 :
1091 2 : if (data_len - idx == 1) {
1092 2 : value = alphanumeric_char_value(data[idx]);
1093 2 : append_bits((uint32_t)value, ALPHANUMERIC_REMAINDER_BITS, qrcode, &bit_len);
1094 : }
1095 :
1096 2 : data_capacity_bits = get_num_data_codewords(version, ecl) * QR_PAD_BYTE_BITS;
1097 2 : terminator_bits = data_capacity_bits - bit_len;
1098 :
1099 2 : if (terminator_bits > QR_TERMINATOR_MAX_BITS) {
1100 2 : terminator_bits = QR_TERMINATOR_MAX_BITS;
1101 : }
1102 :
1103 2 : append_bits(0, terminator_bits, qrcode, &bit_len);
1104 2 : append_bits(0, (QR_PAD_BYTE_BITS - bit_len % QR_PAD_BYTE_BITS) % QR_PAD_BYTE_BITS, qrcode, &bit_len);
1105 :
1106 14 : for (pad_byte = PAD_BYTE_FIRST; bit_len < data_capacity_bits; pad_byte ^= PAD_BYTE_FIRST ^ PAD_BYTE_SECOND) {
1107 12 : append_bits(pad_byte, QR_PAD_BYTE_BITS, qrcode, &bit_len);
1108 : }
1109 :
1110 2 : if (!add_ecc_and_interleave(qrcode, version, ecl, temp_buffer)) {
1111 0 : return false;
1112 : }
1113 :
1114 2 : initialize_function_modules(version, qrcode);
1115 2 : draw_codewords(temp_buffer, get_num_raw_data_modules(version) >> 3, qrcode);
1116 2 : draw_light_function_modules(qrcode, version);
1117 2 : initialize_function_modules(version, temp_buffer);
1118 :
1119 2 : if (mask < 0) {
1120 2 : min_penalty = INT32_MAX;
1121 2 : best_mask = 0;
1122 :
1123 18 : for (i = 0; i < QR_MASK_COUNT; i++) {
1124 16 : apply_mask(temp_buffer, qrcode, (int8_t)i);
1125 16 : draw_format_bits(ecl, (int8_t)i, qrcode);
1126 16 : penalty = get_penalty_score(qrcode);
1127 :
1128 16 : if (penalty < min_penalty) {
1129 3 : best_mask = (int8_t)i;
1130 3 : min_penalty = penalty;
1131 : }
1132 :
1133 16 : apply_mask(temp_buffer, qrcode, (int8_t)i);
1134 : }
1135 2 : mask = best_mask;
1136 : }
1137 :
1138 2 : apply_mask(temp_buffer, qrcode, mask);
1139 2 : draw_format_bits(ecl, mask, qrcode);
1140 :
1141 2 : return true;
1142 : }
1143 :
1144 : static inline bool is_kanji_byte_pair(uint8_t high, uint8_t low)
1145 : {
1146 : uint16_t code;
1147 :
1148 : code = ((uint16_t)high << 8) | low;
1149 :
1150 : return (code >= KANJI_SJIS_RANGE1_START && code <= KANJI_SJIS_RANGE1_END) ||
1151 : (code >= KANJI_SJIS_RANGE2_START && code <= KANJI_SJIS_RANGE2_END);
1152 : }
1153 :
1154 : static inline bool is_kanji_data(const uint8_t *data, size_t data_len)
1155 : {
1156 : size_t i;
1157 :
1158 : if (data_len == 0 || data_len % 2 != 0) {
1159 : return false;
1160 : }
1161 :
1162 : for (i = 0; i < data_len; i += 2) {
1163 : if (!is_kanji_byte_pair(data[i], data[i + 1])) {
1164 : return false;
1165 : }
1166 : }
1167 :
1168 : return true;
1169 : }
1170 :
1171 2 : static inline int32_t kanji_count_bits(uint8_t version, size_t char_count)
1172 : {
1173 : int32_t count_bits;
1174 :
1175 2 : if (version < VERSION_THRESHOLD_SMALL) {
1176 2 : count_bits = KANJI_BITS_SMALL;
1177 0 : } else if (version < VERSION_THRESHOLD_MEDIUM) {
1178 0 : count_bits = KANJI_BITS_MEDIUM;
1179 : } else {
1180 0 : count_bits = KANJI_BITS_LARGE;
1181 : }
1182 :
1183 2 : return QR_MODE_INDICATOR_BITS + count_bits + (int32_t)char_count * KANJI_ENCODED_BITS;
1184 : }
1185 :
1186 2 : static inline bool encode_kanji(const uint8_t *data, size_t data_len, uint8_t temp_buffer[], uint8_t qrcode[],
1187 : uint8_t ecl, int8_t min_version, int8_t max_version, int8_t mask)
1188 : {
1189 : uint16_t sjis_char;
1190 : uint8_t pad_byte, version, best_mask;
1191 : int32_t data_capacity_bits, data_used_bits, bit_len, terminator_bits, i, min_penalty, penalty, count_bits,
1192 : high_byte, low_byte, intermediate, encoded_value;
1193 : size_t idx, char_count;
1194 :
1195 2 : char_count = data_len / 2;
1196 :
1197 2 : for (version = min_version;; version++) {
1198 2 : data_capacity_bits = get_num_data_codewords(version, ecl) * 8;
1199 2 : data_used_bits = kanji_count_bits(version, char_count);
1200 :
1201 2 : if (data_used_bits <= data_capacity_bits) {
1202 2 : break;
1203 : }
1204 :
1205 0 : if (version >= max_version) {
1206 0 : qrcode[0] = 0;
1207 0 : return false;
1208 : }
1209 : }
1210 :
1211 2 : if (version < VERSION_THRESHOLD_SMALL) {
1212 2 : count_bits = KANJI_BITS_SMALL;
1213 0 : } else if (version < VERSION_THRESHOLD_MEDIUM) {
1214 0 : count_bits = KANJI_BITS_MEDIUM;
1215 : } else {
1216 0 : count_bits = KANJI_BITS_LARGE;
1217 : }
1218 :
1219 2 : lmemset(qrcode, 0, (size_t)QR_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0]));
1220 2 : bit_len = 0;
1221 2 : append_bits(QR_MODE_KANJI_INDICATOR, QR_MODE_INDICATOR_BITS, qrcode, &bit_len);
1222 2 : append_bits((uint32_t)char_count, count_bits, qrcode, &bit_len);
1223 :
1224 7 : for (idx = 0; idx < data_len; idx += 2) {
1225 5 : sjis_char = ((uint16_t)data[idx] << 8) | data[idx + 1];
1226 :
1227 5 : if (sjis_char >= KANJI_SJIS_RANGE1_START && sjis_char <= KANJI_SJIS_RANGE1_END) {
1228 5 : intermediate = sjis_char - KANJI_ENCODE_BASE1;
1229 : } else {
1230 0 : intermediate = sjis_char - KANJI_ENCODE_BASE2;
1231 : }
1232 :
1233 5 : high_byte = (intermediate >> 8) & 0xFF;
1234 5 : low_byte = intermediate & 0xFF;
1235 5 : encoded_value = high_byte * KANJI_ENCODE_MULTIPLIER + low_byte;
1236 :
1237 5 : append_bits((uint32_t)encoded_value, KANJI_ENCODED_BITS, qrcode, &bit_len);
1238 : }
1239 :
1240 2 : data_capacity_bits = get_num_data_codewords(version, ecl) * QR_PAD_BYTE_BITS;
1241 2 : terminator_bits = data_capacity_bits - bit_len;
1242 :
1243 2 : if (terminator_bits > QR_TERMINATOR_MAX_BITS) {
1244 2 : terminator_bits = QR_TERMINATOR_MAX_BITS;
1245 : }
1246 :
1247 2 : append_bits(0, terminator_bits, qrcode, &bit_len);
1248 2 : append_bits(0, (QR_PAD_BYTE_BITS - bit_len % QR_PAD_BYTE_BITS) % QR_PAD_BYTE_BITS, qrcode, &bit_len);
1249 :
1250 24 : for (pad_byte = PAD_BYTE_FIRST; bit_len < data_capacity_bits; pad_byte ^= PAD_BYTE_FIRST ^ PAD_BYTE_SECOND) {
1251 22 : append_bits(pad_byte, QR_PAD_BYTE_BITS, qrcode, &bit_len);
1252 : }
1253 :
1254 2 : if (!add_ecc_and_interleave(qrcode, version, ecl, temp_buffer)) {
1255 0 : return false;
1256 : }
1257 2 : initialize_function_modules(version, qrcode);
1258 2 : draw_codewords(temp_buffer, get_num_raw_data_modules(version) >> 3, qrcode);
1259 2 : draw_light_function_modules(qrcode, version);
1260 2 : initialize_function_modules(version, temp_buffer);
1261 :
1262 2 : if (mask < 0) {
1263 2 : min_penalty = INT32_MAX;
1264 2 : best_mask = 0;
1265 :
1266 18 : for (i = 0; i < QR_MASK_COUNT; i++) {
1267 16 : apply_mask(temp_buffer, qrcode, (int8_t)i);
1268 16 : draw_format_bits(ecl, (int8_t)i, qrcode);
1269 16 : penalty = get_penalty_score(qrcode);
1270 :
1271 16 : if (penalty < min_penalty) {
1272 3 : best_mask = (int8_t)i;
1273 3 : min_penalty = penalty;
1274 : }
1275 :
1276 16 : apply_mask(temp_buffer, qrcode, (int8_t)i);
1277 : }
1278 2 : mask = best_mask;
1279 : }
1280 :
1281 2 : apply_mask(temp_buffer, qrcode, mask);
1282 2 : draw_format_bits(ecl, mask, qrcode);
1283 :
1284 2 : return true;
1285 : }
1286 :
1287 1 : static inline int32_t eci_header_bits(uint32_t eci_value)
1288 : {
1289 1 : if (eci_value <= ECI_SINGLE_BYTE_MAX) {
1290 1 : return QR_MODE_INDICATOR_BITS + QR_PAD_BYTE_BITS;
1291 0 : } else if (eci_value <= ECI_DOUBLE_BYTE_MAX) {
1292 0 : return QR_MODE_INDICATOR_BITS + BYTE_BITS_LARGE;
1293 : } else {
1294 0 : return QR_MODE_INDICATOR_BITS + ECI_BITS_3BYTE;
1295 : }
1296 : }
1297 :
1298 1 : static inline bool encode_eci(const uint8_t *data, size_t data_len, uint8_t temp_buffer[], uint8_t qrcode[],
1299 : uint8_t ecl, int8_t min_version, int8_t max_version, int8_t mask, uint32_t eci_value)
1300 : {
1301 : uint8_t pad_byte, version, best_mask;
1302 : int32_t data_capacity_bits, data_used_bits, bit_len, terminator_bits, i, min_penalty, penalty, ehb;
1303 :
1304 1 : ehb = eci_header_bits(eci_value);
1305 :
1306 1 : for (version = min_version;; version++) {
1307 1 : data_capacity_bits = get_num_data_codewords(version, ecl) * QR_PAD_BYTE_BITS;
1308 2 : data_used_bits = ehb + QR_MODE_INDICATOR_BITS +
1309 1 : ((version < VERSION_THRESHOLD_SMALL) ? BYTE_BITS_SMALL : BYTE_BITS_LARGE) +
1310 1 : (int32_t)data_len * QR_PAD_BYTE_BITS;
1311 :
1312 1 : if (data_used_bits <= data_capacity_bits) {
1313 1 : break;
1314 : }
1315 :
1316 0 : if (version >= max_version) {
1317 0 : qrcode[0] = 0;
1318 0 : return false;
1319 : }
1320 : }
1321 :
1322 1 : lmemset(qrcode, 0, (size_t)QR_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0]));
1323 1 : bit_len = 0;
1324 :
1325 1 : append_bits(QR_MODE_ECI_INDICATOR, QR_MODE_INDICATOR_BITS, qrcode, &bit_len);
1326 :
1327 1 : if (eci_value <= ECI_SINGLE_BYTE_MAX) {
1328 1 : append_bits(eci_value, QR_PAD_BYTE_BITS, qrcode, &bit_len);
1329 0 : } else if (eci_value <= ECI_DOUBLE_BYTE_MAX) {
1330 0 : append_bits(ECI_PREFIX_2BYTE | ((eci_value >> 8) & ECI_MASK_2BYTE), QR_PAD_BYTE_BITS, qrcode, &bit_len);
1331 0 : append_bits(eci_value & 0xFF, QR_PAD_BYTE_BITS, qrcode, &bit_len);
1332 : } else {
1333 0 : append_bits(ECI_PREFIX_3BYTE | ((eci_value >> 16) & ECI_MASK_3BYTE), QR_PAD_BYTE_BITS, qrcode, &bit_len);
1334 0 : append_bits((eci_value >> 8) & 0xFF, QR_PAD_BYTE_BITS, qrcode, &bit_len);
1335 0 : append_bits(eci_value & 0xFF, QR_PAD_BYTE_BITS, qrcode, &bit_len);
1336 : }
1337 :
1338 1 : append_bits(QR_MODE_BYTE_INDICATOR, QR_MODE_INDICATOR_BITS, qrcode, &bit_len);
1339 1 : append_bits((uint32_t)data_len, (version < VERSION_THRESHOLD_SMALL) ? BYTE_BITS_SMALL : BYTE_BITS_LARGE, qrcode,
1340 : &bit_len);
1341 :
1342 13 : for (i = 0; i < (int32_t)data_len; i++) {
1343 12 : append_bits(data[i], QR_PAD_BYTE_BITS, qrcode, &bit_len);
1344 : }
1345 :
1346 1 : data_capacity_bits = get_num_data_codewords(version, ecl) * QR_PAD_BYTE_BITS;
1347 1 : terminator_bits = data_capacity_bits - bit_len;
1348 :
1349 1 : if (terminator_bits > QR_TERMINATOR_MAX_BITS) {
1350 1 : terminator_bits = QR_TERMINATOR_MAX_BITS;
1351 : }
1352 :
1353 1 : append_bits(0, terminator_bits, qrcode, &bit_len);
1354 1 : append_bits(0, (QR_PAD_BYTE_BITS - bit_len % QR_PAD_BYTE_BITS) % QR_PAD_BYTE_BITS, qrcode, &bit_len);
1355 :
1356 4 : for (pad_byte = PAD_BYTE_FIRST; bit_len < data_capacity_bits; pad_byte ^= PAD_BYTE_FIRST ^ PAD_BYTE_SECOND) {
1357 3 : append_bits(pad_byte, QR_PAD_BYTE_BITS, qrcode, &bit_len);
1358 : }
1359 :
1360 1 : if (!add_ecc_and_interleave(qrcode, version, ecl, temp_buffer)) {
1361 0 : return false;
1362 : }
1363 1 : initialize_function_modules(version, qrcode);
1364 1 : draw_codewords(temp_buffer, get_num_raw_data_modules(version) >> 3, qrcode);
1365 1 : draw_light_function_modules(qrcode, version);
1366 1 : initialize_function_modules(version, temp_buffer);
1367 :
1368 1 : if (mask < 0) {
1369 1 : min_penalty = INT32_MAX;
1370 1 : best_mask = 0;
1371 :
1372 9 : for (i = 0; i < QR_MASK_COUNT; i++) {
1373 8 : apply_mask(temp_buffer, qrcode, (int8_t)i);
1374 8 : draw_format_bits(ecl, (int8_t)i, qrcode);
1375 8 : penalty = get_penalty_score(qrcode);
1376 :
1377 8 : if (penalty < min_penalty) {
1378 4 : best_mask = (int8_t)i;
1379 4 : min_penalty = penalty;
1380 : }
1381 :
1382 8 : apply_mask(temp_buffer, qrcode, (int8_t)i);
1383 : }
1384 1 : mask = best_mask;
1385 : }
1386 :
1387 1 : apply_mask(temp_buffer, qrcode, mask);
1388 1 : draw_format_bits(ecl, mask, qrcode);
1389 :
1390 1 : return true;
1391 : }
1392 :
1393 718 : static inline bool encode_binary(const uint8_t *data, size_t data_len, uint8_t temp_buffer[], uint8_t qrcode[],
1394 : uint8_t ecl, int8_t min_version, int8_t max_version, int8_t mask)
1395 : {
1396 : uint8_t pad_byte, version, best_mask;
1397 : int32_t data_capacity_bits, data_used_bits, bit_len, terminator_bits, i, min_penalty, penalty;
1398 :
1399 718 : for (version = min_version;; version++) {
1400 4151 : data_capacity_bits = get_num_data_codewords(version, ecl) * QR_PAD_BYTE_BITS;
1401 4151 : data_used_bits = QR_MODE_INDICATOR_BITS +
1402 : ((version < VERSION_THRESHOLD_SMALL) ? BYTE_BITS_SMALL : BYTE_BITS_LARGE) +
1403 4151 : (int32_t)data_len * QR_PAD_BYTE_BITS;
1404 :
1405 4151 : if (data_used_bits <= data_capacity_bits) {
1406 718 : break;
1407 : }
1408 :
1409 3433 : if (version >= max_version) {
1410 0 : qrcode[0] = 0;
1411 0 : return false;
1412 : }
1413 : }
1414 :
1415 718 : lmemset(qrcode, 0, (size_t)QR_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0]));
1416 718 : bit_len = 0;
1417 718 : append_bits(QR_MODE_BYTE_INDICATOR, QR_MODE_INDICATOR_BITS, qrcode, &bit_len);
1418 718 : append_bits((uint32_t)data_len, (version < VERSION_THRESHOLD_SMALL) ? BYTE_BITS_SMALL : BYTE_BITS_LARGE, qrcode,
1419 : &bit_len);
1420 :
1421 94619 : for (i = 0; i < (int32_t)data_len; i++) {
1422 93901 : append_bits(data[i], QR_PAD_BYTE_BITS, qrcode, &bit_len);
1423 : }
1424 :
1425 718 : data_capacity_bits = get_num_data_codewords(version, ecl) * QR_PAD_BYTE_BITS;
1426 718 : terminator_bits = data_capacity_bits - bit_len;
1427 :
1428 718 : if (terminator_bits > QR_TERMINATOR_MAX_BITS) {
1429 686 : terminator_bits = QR_TERMINATOR_MAX_BITS;
1430 : }
1431 :
1432 718 : append_bits(0, terminator_bits, qrcode, &bit_len);
1433 718 : append_bits(0, (QR_PAD_BYTE_BITS - bit_len % QR_PAD_BYTE_BITS) % QR_PAD_BYTE_BITS, qrcode, &bit_len);
1434 :
1435 10589 : for (pad_byte = PAD_BYTE_FIRST; bit_len < data_capacity_bits; pad_byte ^= PAD_BYTE_FIRST ^ PAD_BYTE_SECOND) {
1436 9871 : append_bits(pad_byte, QR_PAD_BYTE_BITS, qrcode, &bit_len);
1437 : }
1438 :
1439 718 : if (!add_ecc_and_interleave(qrcode, version, ecl, temp_buffer)) {
1440 0 : return false;
1441 : }
1442 718 : initialize_function_modules(version, qrcode);
1443 718 : draw_codewords(temp_buffer, get_num_raw_data_modules(version) >> 3, qrcode);
1444 718 : draw_light_function_modules(qrcode, version);
1445 718 : initialize_function_modules(version, temp_buffer);
1446 :
1447 718 : if (mask < 0) {
1448 534 : min_penalty = INT32_MAX;
1449 534 : best_mask = 0;
1450 :
1451 4806 : for (i = 0; i < QR_MASK_COUNT; i++) {
1452 4272 : apply_mask(temp_buffer, qrcode, (int8_t)i);
1453 4272 : draw_format_bits(ecl, (int8_t)i, qrcode);
1454 4272 : penalty = get_penalty_score(qrcode);
1455 :
1456 4272 : if (penalty < min_penalty) {
1457 1064 : best_mask = (int8_t)i;
1458 1064 : min_penalty = penalty;
1459 : }
1460 :
1461 4272 : apply_mask(temp_buffer, qrcode, (int8_t)i);
1462 : }
1463 534 : mask = best_mask;
1464 : }
1465 :
1466 718 : apply_mask(temp_buffer, qrcode, mask);
1467 718 : draw_format_bits(ecl, mask, qrcode);
1468 :
1469 718 : return true;
1470 : }
1471 :
1472 1001 : extern lierre_error_t lierre_writer_param_init(lierre_writer_param_t *param, uint8_t *data, size_t data_size,
1473 : size_t scale, size_t margin, lierre_writer_ecc_t ecc_level,
1474 : lierre_writer_mask_t mask_pattern, lierre_writer_mode_t mode)
1475 : {
1476 1001 : if (!param || !data || data_size == 0 || scale == 0) {
1477 4 : return LIERRE_ERROR_INVALID_PARAMS;
1478 : }
1479 :
1480 997 : param->data = data;
1481 997 : param->data_size = data_size;
1482 997 : param->scale = scale;
1483 997 : param->margin = margin;
1484 997 : param->ecc_level = ecc_level;
1485 997 : param->mask_pattern = mask_pattern;
1486 997 : param->mode = mode;
1487 :
1488 997 : return LIERRE_ERROR_SUCCESS;
1489 : }
1490 :
1491 2240 : extern lierre_qr_version_t lierre_writer_qr_version(const lierre_writer_param_t *param)
1492 : {
1493 : lierre_qr_version_t ver;
1494 : uint8_t ecl, mode_idx;
1495 : size_t char_count;
1496 :
1497 2240 : if (!param || !param->data || param->data_size == 0) {
1498 3 : return LIERRE_WRITER_QR_VERSION_ERR;
1499 : }
1500 :
1501 2237 : ecl = (uint8_t)param->ecc_level;
1502 2237 : if (ecl > 3) {
1503 1 : ecl = 0;
1504 : }
1505 :
1506 2237 : switch (param->mode) {
1507 58 : case MODE_NUMERIC:
1508 58 : mode_idx = 0;
1509 58 : char_count = param->data_size;
1510 58 : break;
1511 58 : case MODE_ALPHANUMERIC:
1512 58 : mode_idx = 1;
1513 58 : char_count = param->data_size;
1514 58 : break;
1515 58 : case MODE_KANJI:
1516 58 : mode_idx = 3;
1517 58 : char_count = param->data_size / 2;
1518 58 : break;
1519 2063 : case MODE_BYTE:
1520 : default:
1521 2063 : mode_idx = 2;
1522 2063 : char_count = param->data_size;
1523 2063 : break;
1524 : }
1525 :
1526 14331 : for (ver = 1; ver <= 40; ver++) {
1527 14325 : if ((size_t)CHAR_CAPACITY[ecl][ver][mode_idx] >= char_count) {
1528 2231 : return ver;
1529 : }
1530 : }
1531 :
1532 6 : return LIERRE_WRITER_QR_VERSION_ERR;
1533 : }
1534 :
1535 1286 : extern bool lierre_writer_get_res(const lierre_writer_param_t *param, lierre_reso_t *res)
1536 : {
1537 : lierre_qr_version_t ver;
1538 : size_t qr_size, total_size;
1539 :
1540 1286 : if (!param || !res) {
1541 4 : return false;
1542 : }
1543 :
1544 1282 : ver = lierre_writer_qr_version(param);
1545 1282 : if (ver == LIERRE_WRITER_QR_VERSION_ERR) {
1546 3 : return false;
1547 : }
1548 :
1549 1279 : qr_size = (size_t)QR_VERSION_SIZE_FORMULA(ver);
1550 :
1551 1279 : if (param->margin > SIZE_MAX / 2) {
1552 0 : return false;
1553 : }
1554 :
1555 1279 : if (param->margin * 2 > SIZE_MAX - qr_size) {
1556 0 : return false;
1557 : }
1558 :
1559 1279 : if (param->scale != 0 && (qr_size + param->margin * 2) > SIZE_MAX / param->scale) {
1560 0 : return false;
1561 : }
1562 :
1563 1279 : total_size = (qr_size + param->margin * 2) * param->scale;
1564 :
1565 1279 : res->width = total_size;
1566 1279 : res->height = total_size;
1567 :
1568 1279 : return true;
1569 : }
1570 :
1571 4 : extern size_t lierre_writer_get_res_width(const lierre_writer_param_t *param)
1572 : {
1573 : lierre_reso_t res;
1574 :
1575 4 : if (!lierre_writer_get_res(param, &res)) {
1576 2 : return 0;
1577 : }
1578 :
1579 2 : return res.width;
1580 : }
1581 :
1582 3 : extern size_t lierre_writer_get_res_height(const lierre_writer_param_t *param)
1583 : {
1584 : lierre_reso_t res;
1585 :
1586 3 : if (!lierre_writer_get_res(param, &res)) {
1587 1 : return 0;
1588 : }
1589 :
1590 2 : return res.height;
1591 : }
1592 :
1593 730 : extern lierre_writer_t *lierre_writer_create(const lierre_writer_param_t *param, const lierre_rgba_t *fill_color,
1594 : const lierre_rgba_t *bg_color)
1595 : {
1596 : lierre_writer_t *writer;
1597 : lierre_reso_t res;
1598 : size_t data_size;
1599 :
1600 730 : if (!param || !fill_color || !bg_color) {
1601 3 : return NULL;
1602 : }
1603 :
1604 727 : if (!lierre_writer_get_res(param, &res)) {
1605 1 : return NULL;
1606 : }
1607 :
1608 726 : writer = lmalloc(sizeof(lierre_writer_t));
1609 726 : if (!writer) {
1610 0 : return NULL;
1611 : }
1612 :
1613 726 : writer->param = lmalloc(sizeof(lierre_writer_param_t));
1614 726 : if (!writer->param) {
1615 0 : lfree(writer);
1616 0 : return NULL;
1617 : }
1618 726 : lmemcpy(writer->param, param, sizeof(lierre_writer_param_t));
1619 :
1620 726 : if (res.width != 0 && res.height > SIZE_MAX / res.width) {
1621 0 : lfree(writer->param);
1622 0 : lfree(writer);
1623 0 : return NULL;
1624 : }
1625 :
1626 726 : if (res.width * res.height > SIZE_MAX / 4) {
1627 0 : lfree(writer->param);
1628 0 : lfree(writer);
1629 0 : return NULL;
1630 : }
1631 726 : data_size = res.width * res.height * 4;
1632 726 : writer->data = lmalloc(sizeof(lierre_rgb_data_t));
1633 726 : if (!writer->data) {
1634 0 : lfree(writer->param);
1635 0 : lfree(writer);
1636 0 : return NULL;
1637 : }
1638 :
1639 726 : writer->data->data = lmalloc(data_size);
1640 726 : if (!writer->data->data) {
1641 0 : lfree(writer->data);
1642 0 : lfree(writer->param);
1643 0 : lfree(writer);
1644 0 : return NULL;
1645 : }
1646 :
1647 726 : writer->data->data_size = data_size;
1648 726 : writer->data->width = res.width;
1649 726 : writer->data->height = res.height;
1650 :
1651 726 : writer->stroke_color_rgba[0] = fill_color->r;
1652 726 : writer->stroke_color_rgba[1] = fill_color->g;
1653 726 : writer->stroke_color_rgba[2] = fill_color->b;
1654 726 : writer->stroke_color_rgba[3] = fill_color->a;
1655 :
1656 726 : writer->fill_color_rgba[0] = bg_color->r;
1657 726 : writer->fill_color_rgba[1] = bg_color->g;
1658 726 : writer->fill_color_rgba[2] = bg_color->b;
1659 726 : writer->fill_color_rgba[3] = bg_color->a;
1660 :
1661 726 : return writer;
1662 : }
1663 :
1664 727 : extern void lierre_writer_destroy(lierre_writer_t *writer)
1665 : {
1666 727 : if (!writer) {
1667 1 : return;
1668 : }
1669 :
1670 726 : if (writer->data) {
1671 726 : if (writer->data->data) {
1672 726 : lfree(writer->data->data);
1673 : }
1674 :
1675 726 : lfree(writer->data);
1676 : }
1677 :
1678 726 : if (writer->param) {
1679 726 : lfree(writer->param);
1680 : }
1681 :
1682 726 : lfree(writer);
1683 : }
1684 :
1685 726 : extern lierre_error_t lierre_writer_write(lierre_writer_t *writer)
1686 : {
1687 : lierre_qr_version_t ver;
1688 : uint8_t *temp_buffer, *qr_buffer, *pixel;
1689 : int32_t qr_size, x, y, px, py;
1690 : size_t scale, margin, sx, sy, img_x, img_y, offset;
1691 : bool is_dark, encode_success;
1692 :
1693 726 : if (!writer || !writer->param || !writer->data || !writer->data->data) {
1694 1 : return LIERRE_ERROR_INVALID_PARAMS;
1695 : }
1696 :
1697 725 : ver = lierre_writer_qr_version(writer->param);
1698 725 : if (ver == LIERRE_WRITER_QR_VERSION_ERR) {
1699 0 : return LIERRE_ERROR_SIZE_EXCEEDED;
1700 : }
1701 :
1702 725 : temp_buffer = lcalloc(1, QR_BUFFER_LEN_MAX);
1703 725 : qr_buffer = lcalloc(1, QR_BUFFER_LEN_MAX);
1704 725 : if (!temp_buffer || !qr_buffer) {
1705 0 : lfree(temp_buffer);
1706 0 : lfree(qr_buffer);
1707 :
1708 0 : return LIERRE_ERROR_DATA_OVERFLOW;
1709 : }
1710 :
1711 725 : encode_success = false;
1712 :
1713 725 : switch (writer->param->mode) {
1714 2 : case MODE_NUMERIC:
1715 2 : encode_success = encode_numeric(writer->param->data, writer->param->data_size, temp_buffer, qr_buffer,
1716 2 : (uint8_t)writer->param->ecc_level, 1, 40, (int8_t)writer->param->mask_pattern);
1717 2 : break;
1718 2 : case MODE_ALPHANUMERIC:
1719 : encode_success =
1720 2 : encode_alphanumeric(writer->param->data, writer->param->data_size, temp_buffer, qr_buffer,
1721 2 : (uint8_t)writer->param->ecc_level, 1, 40, (int8_t)writer->param->mask_pattern);
1722 2 : break;
1723 2 : case MODE_KANJI:
1724 2 : encode_success = encode_kanji(writer->param->data, writer->param->data_size, temp_buffer, qr_buffer,
1725 2 : (uint8_t)writer->param->ecc_level, 1, 40, (int8_t)writer->param->mask_pattern);
1726 2 : break;
1727 1 : case MODE_ECI:
1728 1 : encode_success = encode_eci(writer->param->data, writer->param->data_size, temp_buffer, qr_buffer,
1729 1 : (uint8_t)writer->param->ecc_level, 1, 40, (int8_t)writer->param->mask_pattern, 26);
1730 1 : break;
1731 718 : case MODE_BYTE:
1732 : default:
1733 718 : encode_success = encode_binary(writer->param->data, writer->param->data_size, temp_buffer, qr_buffer,
1734 718 : (uint8_t)writer->param->ecc_level, 1, 40, (int8_t)writer->param->mask_pattern);
1735 718 : break;
1736 : }
1737 :
1738 725 : if (!encode_success) {
1739 0 : lfree(temp_buffer);
1740 0 : lfree(qr_buffer);
1741 :
1742 0 : return LIERRE_ERROR_SIZE_EXCEEDED;
1743 : }
1744 :
1745 725 : qr_size = qr_buffer[0];
1746 725 : scale = writer->param->scale;
1747 725 : margin = writer->param->margin;
1748 :
1749 158971 : for (x = 0; x < (int32_t)writer->data->width; x++) {
1750 158246 : offset = (size_t)x * 4;
1751 158246 : pixel = &writer->data->data[offset];
1752 158246 : pixel[0] = writer->fill_color_rgba[0];
1753 158246 : pixel[1] = writer->fill_color_rgba[1];
1754 158246 : pixel[2] = writer->fill_color_rgba[2];
1755 158246 : pixel[3] = writer->fill_color_rgba[3];
1756 : }
1757 158246 : for (y = 1; y < (int32_t)writer->data->height; y++) {
1758 157521 : lmemcpy(&writer->data->data[(size_t)y * writer->data->width * 4], writer->data->data, writer->data->width * 4);
1759 : }
1760 :
1761 29686 : for (py = 0; py < qr_size; py++) {
1762 1719998 : for (px = 0; px < qr_size; px++) {
1763 1691037 : is_dark = get_module(qr_buffer, px, py);
1764 14021341 : for (sy = 0; sy < scale; sy++) {
1765 126179848 : for (sx = 0; sx < scale; sx++) {
1766 113849544 : img_x = (margin + (size_t)px) * scale + sx;
1767 113849544 : img_y = (margin + (size_t)py) * scale + sy;
1768 :
1769 113849544 : if (img_x < writer->data->width && img_y < writer->data->height) {
1770 113849544 : offset = (img_y * writer->data->width + img_x) * 4;
1771 113849544 : pixel = &writer->data->data[offset];
1772 :
1773 113849544 : if (is_dark) {
1774 57723331 : pixel[0] = writer->stroke_color_rgba[0];
1775 57723331 : pixel[1] = writer->stroke_color_rgba[1];
1776 57723331 : pixel[2] = writer->stroke_color_rgba[2];
1777 57723331 : pixel[3] = writer->stroke_color_rgba[3];
1778 : }
1779 : }
1780 : }
1781 : }
1782 : }
1783 : }
1784 :
1785 725 : lfree(temp_buffer);
1786 725 : lfree(qr_buffer);
1787 :
1788 725 : return LIERRE_ERROR_SUCCESS;
1789 : }
1790 :
1791 113 : extern const uint8_t *lierre_writer_get_rgba_data(const lierre_writer_t *writer)
1792 : {
1793 113 : if (!writer || !writer->data) {
1794 0 : return NULL;
1795 : }
1796 :
1797 113 : return writer->data->data;
1798 : }
1799 :
1800 1 : extern size_t lierre_writer_get_rgba_data_size(const lierre_writer_t *writer)
1801 : {
1802 1 : if (!writer || !writer->data) {
1803 0 : return 0;
1804 : }
1805 :
1806 1 : return writer->data->data_size;
1807 : }
|