comparison mupdf-source/thirdparty/zint/backend_tcl/zint.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 /* zint_tcl.c TCL binding for zint */
2 /*
3 zint - the open source tcl binding to the zint barcode library
4 Copyright (C) 2014-2024 Harald Oehlmann <oehhar@users.sourceforge.net>
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 History
34
35 2014-06-16 2.5.0 HaO
36 First implementation
37 2016-09-14 2.5.1 HaO
38 - Added Codablock F options "-rows".
39 - Adopted to new image format of zint
40 2016-10-14 2.5.2 HaO
41 - Include the upstream reverted image format
42 2016-12-12 2.5.3 HaO
43 - No changes here, take 2.5.1 framework files
44 2017-05-12 2.6.0 HaO
45 - No changes here, take 2.6 framework files
46 2017-08-29 2.6.1 HaO
47 - Framework 2.6.1 extensions
48 - EAN/UPC Codes with included check digit
49 - UPNQR Code
50 - Misspelled symbology: AztecRunes
51 2017-10-23 2.6.2 HaO
52 - Framework 2.6.2 bugfixes
53 - Allow dll unload
54 2018-02-13 2.6.3 HaO
55 - Framework trunk update
56 - Added VIN and MailMark symbologies.
57 2018-11-02 2.6.4 HaO
58 - Framework trunk update
59 - Add options -bold, -dotted, -dotsize, -dmre, -eci
60 - Implemented ECI logic
61 2019-09-01 2.6.5 HaO
62 - Framework 2.6.5 update
63 - Add option -gssep
64 2019-09-18 2.6.6 HaO
65 - Framework 2.6.6 update
66 2019-10-07 2.6.7 HaO
67 - Framework 2.6.7 update
68 2019-12-05 2.7.0 HaO
69 - Framework 2.7.0 update
70 - Add symbology rmqr
71 2020-02-01 2.7.1 HaO
72 - Framework 2.7.1 update
73 2020-04-06 HaO
74 - Added option -fullmultibyte
75 2020-04-07 2.8.0 HaO
76 - Added symbology "UltraCode".
77 2020-05-19 HaO
78 - Added option -separator to specify stacked symbology separator width
79 - -cols maximum changed from 66 to 67
80 2020-07-27 2.9.0 HaO
81 - added option "-addongap"
82 - Renamed symbology names:
83 - Matrix2of5 -> Standard2of5
84 - PDF417Trunc -> PDF417Compact
85 - RSS14Stacked -> GS1DataBarStacked
86 - RSS14Stacked -> GS1DataBarStacked
87 - RSS14StackedOmni -> GS1DataBarSstackedOmni
88 - RSS14ExpandedStacked -> GS1DataBarExpandedStacked
89 - OneCode -> USPSIntelligentMail
90 - EAN128-CC -> GS1-128-CC
91 - RSS14-CC -> GS1DataBarOmni-CC
92 - RSSLimited-CC -> GS1DataBarLimited-CC
93 - RSSExpandedStacked-CC -> GS1DataBarExpanded-CC
94 - RSSEXPanded-CC -> GS1DataBarExpanded-CC
95 - RSS14Stacked-CC -> GS1DataBarStacked-CC
96 - RSS14Omni-CC -> GS1DataBarStackedOmni-CC
97 - RSSExpandedStacked-CC -> GS1DataBarExpandedStacked-CC
98 *** Potential incompatibility ***
99 2020-08-04 2.10.0 HaO
100 - added symbology "DPDCode"
101 - Alpha channel support added:
102 - added option -nobackground
103 - also allow RRGGBBAA for -fg and -bg options
104 2021-01-05 2.9.1 HaO
105 - Added options -reverse, -werror, -wzpl
106 - Use version number from zint.h (first 3 digits). Do not use an own one.
107 2021-01-14 GL
108 - Removed TCL native encoding of ECI's and replace by zint buildin mechanism.
109 The input is now UTF-8 for any ECI and zint cares about the encoding.
110 2021-01-14 HaO
111 - Added detection of presence of the Tk package and late initialization.
112 This is a preparation to add a TCL only mode to the DLL.
113 2021-01-22 GL
114 - -cols maximum changed from 67 to 108 (DotCode)
115 2021-05-10 GL
116 - Added -gs1parens option
117 2021-05-22 GL
118 - Added -vwhitesp option
119 2021-05-28 GL
120 - -cols maximum changed from 108 to 200 (DotCode)
121 2021-07-09 GL
122 - Removed -wzpl, added -gs1nocheck
123 - Made -format position independent
124 - Tabs -> spaces
125 2021-09-21 GL
126 - Added -guarddescent option
127 - iHeight check int -> double
128 2021-09-24 GL
129 - Added -quietzones and -noquietzones options
130 2021-09-27 GL
131 - Added -structapp
132 - Split up -to parsing (could seg fault if given non-int for X0 or Y0)
133 2021-10-05 GL
134 - Added -compliantheight option
135 2021-10-30 GL
136 - Added PDF417 -rows
137 2021-11-19 GL
138 - Added -heightperrow option
139 - Added DBAR_EXPSTK, CODE16K, CODE49 -rows
140 2021-12-17 GL
141 - Added -fast option
142 2022-04-08 GL
143 - Updated ECIs to AIM ITS/04-023:2022
144 Note changed names "unicode" -> "utf-16be", "euc-cn" -> "gb2312"
145 2022-04-24 GL
146 - Added -segN options
147 - Added "invariant" and "binary" ECIs
148 - Tcl_GetIndexFromObj() flags arg -> 0
149 2022-05-12 GL
150 - -vers maximum changed to 999 (DAFT)
151 2022-07-03 GL
152 - Added BC412
153 2022-08-20 GL
154 - Added CEPNet
155 2022-11-10 GL
156 - Added -bindtop option
157 2022-12-02 GL
158 - Added -scalexdimdp option
159 - Renamed CODE128B to CODE128AB
160 *** Potential incompatibility ***
161 2022-12-08 GL
162 - Added MAILMARK_2D
163 - Renamed MAILMARK to MAILMARK_4S
164 *** Potential incompatibility ***
165 2022-12-09 GL
166 - Added UPU_S10
167 2023-01-15 GL
168 - Added -esc and -extraesc options
169 2023-02-10 GL
170 - Added -textgap option
171 2023-08-11 GL
172 - Added -guardwhitespace option
173 2023-10-30 GL
174 - Added -dmiso144 option
175 2024-12-09 HaO
176 - TCL 9 compatibility
177 - support TCL buildinfo
178 - remove the zint command on dll unload
179 2024-12-23 GL
180 - Added DXFILMEDGE
181 */
182
183 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
184 #pragma warning(disable : 4201 4214 4514)
185 #define STRICT
186 #define WIN32_LEAN_AND_MEAN
187 /* TCL Defines */
188 #define DLL_BUILD
189
190 #include <windows.h>
191
192 /* Define ERROR_INVALID_DATA is also used by zint... */
193 #ifdef ERROR_INVALID_DATA
194 #undef ERROR_INVALID_DATA
195 #endif
196 #endif
197
198 #include <zint.h>
199 /* Load version defines */
200 #include "../backend/zintconfig.h"
201 #include <string.h>
202
203 #include <tcl.h>
204 #include <tk.h>
205
206 /* TCL 9 compatibility for TCL 8.6 compile */
207 #ifndef TCL_SIZE_MAX
208 #ifndef Tcl_Size
209 typedef int Tcl_Size;
210 #endif
211 # define Tcl_GetSizeIntFromObj Tcl_GetIntFromObj
212 # define Tcl_NewSizeIntObj Tcl_NewIntObj
213 # define TCL_SIZE_MAX INT_MAX
214 # define TCL_SIZE_MODIFIER ""
215 #endif
216
217 #undef EXPORT
218 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
219 #define EXPORT __declspec(dllexport)
220 #else
221 #define EXPORT
222 #endif
223
224
225 /*----------------------------------------------------------------------------*/
226 /* >>>>> Helper defines */
227
228 /* Two macros are necessary to not include the define name, but the value */
229 #define STRING(x) #x
230 #define TOSTRING(x) STRING(x)
231
232 /* Define VERSION as the first 3 digits of the zint library version number */
233 #define VERSION TOSTRING( ZINT_VERSION_MAJOR ) \
234 "." TOSTRING( ZINT_VERSION_MINOR ) \
235 "." TOSTRING( ZINT_VERSION_RELEASE )
236
237 /*----------------------------------------------------------------------------*/
238 /* >>>> External Prototypes (exports) */
239 DLLEXPORT int Zint_Init (Tcl_Interp *interp);
240 DLLEXPORT int Zint_Unload (Tcl_Interp *Interp, int Flags);
241 /*----------------------------------------------------------------------------*/
242 /* >>>> local prototypes */
243 static void InterpCleanupProc(ClientData clientData, Tcl_Interp *interp);
244 static int CheckForTk(Tcl_Interp *interp, int *tkFlagPtr);
245 static int ZintCmd(ClientData unused, Tcl_Interp *interp, int objc,
246 Tcl_Obj *CONST objv[]);
247 static int Encode(Tcl_Interp *interp, int objc,
248 Tcl_Obj *CONST objv[]);
249 /*----------------------------------------------------------------------------*/
250 /* >>>> File Global Variables */
251
252 /* >> List of Codes */
253
254 static const char *s_code_list[] = {
255 "Code11",
256 "Standard2of5",
257 "Interleaved2of5",
258 "IATAC2of5",
259 "Logic2of5",
260 "Ind2of5",
261 "Code39",
262 "Code39Extended",
263 "EAN",
264 "EAN+Check",
265 "GS1-128",
266 "Codabar",
267 "Code128",
268 "DPLeit",
269 "DPIdent",
270 "Code16K",
271 "Code49",
272 "Code93",
273 "Flat",
274 "GS1DataBar",
275 "GS1DataBarLimited",
276 "GS1DataBarExpanded",
277 "Telepen",
278 "UPC-A",
279 "UPC-A+Check",
280 "UPC-E",
281 "UPC-E+Check",
282 "POSTNET",
283 "MSIPlessey",
284 "FIM",
285 "Logmars",
286 "Pharma",
287 "PZN",
288 "PharmaTwo",
289 "CEPNet",
290 "PDF417",
291 "PDF417Compact",
292 "MaxiCode",
293 "QR",
294 "Code128AB",
295 "AusPost",
296 "AusReply",
297 "AusRoute",
298 "AusRedirect",
299 "ISBN",
300 "RM4SCC",
301 "Datamatrix",
302 "EAN14",
303 "VIN",
304 "CodablockF",
305 "NVE18",
306 "JapanPost",
307 "KoreaPost",
308 "GS1DataBarStacked",
309 "GS1DataBarSstackedOmni",
310 "GS1DataBarExpandedStacked",
311 "PLANET",
312 "DPDCode",
313 "MicroPDF417",
314 "USPSIntelligentMail",
315 "Plessey",
316 "TelepenNum",
317 "ITF14",
318 "KIX",
319 "Aztec",
320 "DAFT",
321 "MicroQR",
322 "HIBC-128",
323 "HIBC-39",
324 "HIBC-DM",
325 "HIBC-QR",
326 "HIBC-PDF",
327 "HIBC-MicroPDF",
328 "HIBC-CodablockF",
329 "HIBCAztec",
330 "DotCode",
331 "HanXin",
332 "MailMark-2D",
333 "UPU-S10",
334 "MailMark-4S",
335 "DXFilmEdge",
336 "AztecRunes",
337 "Code32",
338 "EAN-CC",
339 "GS1-128-CC",
340 "GS1DataBarOmni-CC",
341 "GS1DataBarLimited-CC",
342 "GS1DataBarExpanded-CC",
343 "UPCA-CC",
344 "UPCE-CC",
345 "GS1DataBarStacked-CC",
346 "GS1DataBarStackedOmni-CC",
347 "GS1DataBarExpandedStacked-CC",
348 "Channel",
349 "CodeOne",
350 "GridMatrix",
351 "UPNQR",
352 "UltraCode",
353 "rMQR",
354 "BC412",
355 NULL};
356
357 static const int s_code_number[] = {
358 BARCODE_CODE11,
359 BARCODE_C25STANDARD,
360 BARCODE_C25INTER,
361 BARCODE_C25IATA,
362 BARCODE_C25LOGIC,
363 BARCODE_C25IND,
364 BARCODE_CODE39,
365 BARCODE_EXCODE39,
366 BARCODE_EANX,
367 BARCODE_EANX_CHK,
368 BARCODE_GS1_128,
369 BARCODE_CODABAR,
370 BARCODE_CODE128,
371 BARCODE_DPLEIT,
372 BARCODE_DPIDENT,
373 BARCODE_CODE16K,
374 BARCODE_CODE49,
375 BARCODE_CODE93,
376 BARCODE_FLAT,
377 BARCODE_DBAR_OMN,
378 BARCODE_DBAR_LTD,
379 BARCODE_DBAR_EXP,
380 BARCODE_TELEPEN,
381 BARCODE_UPCA,
382 BARCODE_UPCA_CHK,
383 BARCODE_UPCE,
384 BARCODE_UPCE_CHK,
385 BARCODE_POSTNET,
386 BARCODE_MSI_PLESSEY,
387 BARCODE_FIM,
388 BARCODE_LOGMARS,
389 BARCODE_PHARMA,
390 BARCODE_PZN,
391 BARCODE_PHARMA_TWO,
392 BARCODE_CEPNET,
393 BARCODE_PDF417,
394 BARCODE_PDF417COMP,
395 BARCODE_MAXICODE,
396 BARCODE_QRCODE,
397 BARCODE_CODE128AB,
398 BARCODE_AUSPOST,
399 BARCODE_AUSREPLY,
400 BARCODE_AUSROUTE,
401 BARCODE_AUSREDIRECT,
402 BARCODE_ISBNX,
403 BARCODE_RM4SCC,
404 BARCODE_DATAMATRIX,
405 BARCODE_EAN14,
406 BARCODE_VIN,
407 BARCODE_CODABLOCKF,
408 BARCODE_NVE18,
409 BARCODE_JAPANPOST,
410 BARCODE_KOREAPOST,
411 BARCODE_DBAR_STK,
412 BARCODE_DBAR_OMNSTK,
413 BARCODE_DBAR_EXPSTK,
414 BARCODE_PLANET,
415 BARCODE_DPD,
416 BARCODE_MICROPDF417,
417 BARCODE_USPS_IMAIL,
418 BARCODE_PLESSEY,
419 BARCODE_TELEPEN_NUM,
420 BARCODE_ITF14,
421 BARCODE_KIX,
422 BARCODE_AZTEC,
423 BARCODE_DAFT,
424 BARCODE_MICROQR,
425 BARCODE_HIBC_128,
426 BARCODE_HIBC_39,
427 BARCODE_HIBC_DM,
428 BARCODE_HIBC_QR,
429 BARCODE_HIBC_PDF,
430 BARCODE_HIBC_MICPDF,
431 BARCODE_HIBC_BLOCKF,
432 BARCODE_HIBC_AZTEC,
433 BARCODE_DOTCODE,
434 BARCODE_HANXIN,
435 BARCODE_MAILMARK_2D,
436 BARCODE_UPU_S10,
437 BARCODE_MAILMARK_4S,
438 BARCODE_DXFILMEDGE,
439 BARCODE_AZRUNE,
440 BARCODE_CODE32,
441 BARCODE_EANX_CC,
442 BARCODE_GS1_128_CC,
443 BARCODE_DBAR_OMN_CC,
444 BARCODE_DBAR_LTD_CC,
445 BARCODE_DBAR_EXP_CC,
446 BARCODE_UPCA_CC,
447 BARCODE_UPCE_CC,
448 BARCODE_DBAR_STK_CC,
449 BARCODE_DBAR_OMNSTK_CC,
450 BARCODE_DBAR_EXPSTK_CC,
451 BARCODE_CHANNEL,
452 BARCODE_CODEONE,
453 BARCODE_GRIDMATRIX,
454 BARCODE_UPNQR,
455 BARCODE_ULTRA,
456 BARCODE_RMQR,
457 BARCODE_BC412,
458 0};
459
460 /* ECI TCL encoding names.
461 * The ECI comments are given after the name.
462 * A ** indicates encodings where native data must be delivered and not utf-8
463 */
464 static const char *s_eci_list[] = {
465 "iso8859-1", /* 3: ISO-8859-1 - Latin alphabet No. 1 (default)*/
466 "iso8859-2", /* 4: ISO-8859-2 - Latin alphabet No. 2*/
467 "iso8859-3", /* 5: ISO-8859-3 - Latin alphabet No. 3*/
468 "iso8859-4", /* 6: ISO-8859-4 - Latin alphabet No. 4*/
469 "iso8859-5", /* 7: ISO-8859-5 - Latin/Cyrillic alphabet*/
470 "iso8859-6", /* 8: ISO-8859-6 - Latin/Arabic alphabet*/
471 "iso8859-7", /* 9: ISO-8859-7 - Latin/Greek alphabet*/
472 "iso8859-9", /*10: ISO-8859-8 - Latin/Hebrew alphabet*/
473 "iso8859-9", /*11: ISO-8859-9 - Latin alphabet No. 5*/
474 "iso8859-10", /*12: ISO-8859-10 - Latin alphabet No. 6*/
475 "iso8859-11", /*13: ISO-8859-11 - Latin/Thai alphabet*/
476 "iso8859-13", /*15: ISO-8859-13 - Latin alphabet No. 7*/
477 "iso8859-14", /*16: ISO-8859-14 - Latin alphabet No. 8 (Celtic)*/
478 "iso8859-15", /*17: ISO-8859-15 - Latin alphabet No. 9*/
479 "iso8859-16", /*18: ISO-8859-16 - Latin alphabet No. 10*/
480 "jis0208", /*20: Shift JIS (JIS X 0208 and JIS X 0201)*/
481 "cp1250", /*21: Windows-1250*/
482 "cp1251", /*22: Windows-1251*/
483 "cp1252", /*23: Windows-1252*/
484 "cp1256", /*24: Windows-1256*/
485 "utf-16be", /*25: UTF-16BE (High order byte first) Unicode*/
486 "utf-8", /*26: Unicode (UTF-8)*/
487 "ascii", /*27: ISO-646:1991 7-bit character set ASCII*/
488 "big5", /*28: Big5 (Taiwan) Chinese Character Set*/
489 "gb2312", /*29: GB 2312 (PRC) Chinese Character Set*/
490 "iso2022-kr", /*30: Korean Character Set EUC-KR (KS X 1001:2002)*/
491 "gbk", /*31: GBK Chinese Character Set*/
492 "gb18030", /*32: GB 18030 Chinese Character Set*/
493 "utf-16le", /*33: UTF-16LE (Low order byte first) Unicode*/
494 "utf-32be", /*34: UTF-32BE (High order byte first) Unicode*/
495 "utf-32le", /*35: UTF-32BE (Low order byte first) Unicode*/
496 "invariant", /*170: ISO-646:1991 7-bit character set invariant*/
497 "binary", /*899: 8-bit binary*/
498 NULL
499 };
500
501 /* The ECI numerical number to pass to ZINT */
502 static const int s_eci_number[] = {
503 3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,20,21,22,23,24,25,26,27,28,29,30,
504 31,32,33,34,35,170,899
505 };
506
507 /* Version information */
508 static const char version_string[] = VERSION;
509 /* Help text */
510 static const char help_message[] = "zint tcl(stub,obj) dll\n"
511 " Generate barcode in tk images\n"
512 "Usage:\n"
513 " zint encode data photo ?option value? ...\n"
514 " data: data to encode in the symbol\n"
515 " photo: a tcl photo image handle ('p' after 'image create photo p')\n"
516 " Available options:\n"
517 " -barcode choice: symbology, use 'zint symbology' to get a list\n"
518 " -addongap integer: (7..12, default: 9) set add-on gap in multiple of module size (EAN/UPC-CC)\n"
519 " -bg color: set background color as 6 or 8 hex rrggbbaa\n"
520 /* cli option --binary internally handled */
521 " -bind bool: bars above/below the code, size set by -border\n"
522 " -bindtop bool: bar above the code, size set by -border\n"
523 " -bold bool: use bold text\n"
524 " -border integer: width of a border around the symbol. Use with -bind/-box/-bindtop 1\n"
525 " -box bool: box around bar code, size set by -border\n"
526 /* cli option --cmyk not supported as no corresponding output */
527 " -cols integer: Codablock F, DotCode, PDF417: number of columns\n"
528 " -compliantheight bool: warn if height not compliant, and use standard default\n"
529 /* cli option --data is standard parameter */
530 " -dmiso144 bool: Use ISO format for 144x144 Data Matrix symbols\n"
531 " -dmre bool: Allow Data Matrix Rectangular Extended\n"
532 " -dotsize number: radius ratio of dots from 0.01 to 1.0\n"
533 " -dotty bool: use dots instead of boxes for matrix codes\n"
534 /* cli option --dump not supported */
535 /* cli option --ecinos not supported */
536 " -eci choice: ECI to use\n"
537 /* cli option --embedfont not supported (vector output only) */
538 " -esc bool: Process escape sequences in input data\n"
539 " -extraesc bool: Process symbology-specific escape sequences (Code 128 only)\n"
540 " -fast bool: use fast encodation (Data Matrix)\n"
541 " -fg color: set foreground color as 6 or 8 hex rrggbbaa\n"
542 /* replaces cli options --binary and --gs1 */
543 " -format binary|unicode|gs1: input data format. Default:unicode\n"
544 " -fullmultibyte bool: allow multibyte compaction for xQR, HanXin, Gridmatrix\n"
545 /* cli option --gs1 replaced by -format */
546 " -gs1nocheck bool: for gs1, do not check validity of data (allows non-standard symbols)\n"
547 " -gs1parens bool: for gs1, AIs enclosed in parentheses instead of square brackets\n"
548 " -gssep bool: for gs1, use gs as separator instead fnc1 (Datamatrix only)\n"
549 " -guarddescent double: Height of guard bar descent in modules (EAN/UPC only)\n"
550 " -guardwhitespace bool: add quiet zone indicators (EAN/UPC only)\n"
551 " -height double: Symbol height in modules\n"
552 " -heightperrow bool: treat height as per-row\n"
553 /* cli option --input not supported */
554 " -init bool: Create reader initialisation symbol (Code 128, Data Matrix)\n"
555 " -mask integer: set masking pattern to use (QR/MicroQR/HanXin/DotCode)\n"
556 /* cli option --mirror not supported */
557 " -mode integer: set encoding mode (MaxiCode, Composite)\n"
558 " -nobackground bool: set background transparent\n"
559 " -noquietzones bool: disable default quiet zones\n"
560 " -notext bool: no interpretation line\n"
561 /* cli option --output not supported */
562 " -primary text: Structured primary data (MaxiCode, Composite)\n"
563 " -quietzones bool: add compliant quiet zones to whitespace\n"
564 " -reverse bool: Reverse colours (white on black)\n"
565 " -rotate angle: Image rotation by 0,90 or 270 degrees\n"
566 " -rows integer: Codablock F, PDF417: number of rows\n"
567 " -scale double: Scale the image to this factor\n"
568 " -scalexdimdp {xdim ?resolution?}: Scale with X-dimension mm, resolution dpmm\n"
569 " -scmvv integer: Prefix SCM with [)>\\R01\\Gvv (vv is integer) (MaxiCode)\n"
570 " -secure integer: EC Level (Aztec, GridMatrix, HanXin, PDF417, QR, UltraCode)\n"
571 " -segN {eci data}: Set the ECI & data content for segment N where N is 1 to 9\n"
572 " -separator 0..4 (default: 1) : Stacked symbologies: separator width\n"
573 /* cli option --small replaced by -smalltext */
574 " -smalltext bool: tiny interpretation line font\n"
575 " -square bool: force Data Matrix symbols to be square\n"
576 " -structapp {index count ?id?}: set Structured Append info\n"
577 " -textgap double: Gap between barcode and text\n"
578 /* cli option --types not supported */
579 " -vers integer: Symbology option\n"
580 /* cli option --version not supported */
581 " -vwhitesp integer: vertical quiet zone in modules\n"
582 " -whitesp integer: horizontal quiet zone in modules\n"
583 " -werror bool: Convert all warnings into errors\n"
584 " -to {x0 y0 ?width? ?height?}: place to put in photo image\n"
585 "\n"
586 "zint symbologies: List available symbologies\n"
587 "zint eci: List available eci tables\n"
588 "zint help\n"
589 "zint version\n"
590 ;
591
592 /*----------------------------------------------------------------------------*/
593 /* Exported symbols */
594 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
595 EXPORT BOOL WINAPI DllEntryPoint (HINSTANCE hInstance,
596 DWORD seginfo, LPVOID lpCmdLine)
597 {
598 /* Don't do anything, so just return true */
599 return TRUE;
600 }
601 #endif
602 /*----------------------------------------------------------------------------*/
603 /* Initialisation Procedures */
604 DLLEXPORT int Zint_Init (Tcl_Interp *interp)
605 {
606 int * tkFlagPtr;
607 Tcl_CmdInfo info;
608 /*------------------------------------------------------------------------*/
609 /* If TCL_STUB is not defined, the following only does a version check */
610 if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
611 return TCL_ERROR;
612 }
613 /*------------------------------------------------------------------------*/
614 /* Add build info */
615 if (Tcl_GetCommandInfo(interp, "::tcl::build-info", &info)) {
616 Tcl_CreateObjCommand(interp, "::zint::build-info",
617 info.objProc, (void *)(
618 PACKAGE_VERSION "+" STRINGIFY(SAMPLE_VERSION_UUID)
619 #if defined(__clang__) && defined(__clang_major__)
620 ".clang-" STRINGIFY(__clang_major__)
621 #if __clang_minor__ < 10
622 "0"
623 #endif
624 STRINGIFY(__clang_minor__)
625 #endif
626 #if defined(__cplusplus) && !defined(__OBJC__)
627 ".cplusplus"
628 #endif
629 #ifndef NDEBUG
630 ".debug"
631 #endif
632 #if !defined(__clang__) && !defined(__INTEL_COMPILER) && defined(__GNUC__)
633 ".gcc-" STRINGIFY(__GNUC__)
634 #if __GNUC_MINOR__ < 10
635 "0"
636 #endif
637 STRINGIFY(__GNUC_MINOR__)
638 #endif
639 #ifdef __INTEL_COMPILER
640 ".icc-" STRINGIFY(__INTEL_COMPILER)
641 #endif
642 #ifdef TCL_MEM_DEBUG
643 ".memdebug"
644 #endif
645 #if defined(_MSC_VER)
646 ".msvc-" STRINGIFY(_MSC_VER)
647 #endif
648 #ifdef USE_NMAKE
649 ".nmake"
650 #endif
651 #ifndef TCL_CFG_OPTIMIZED
652 ".no-optimize"
653 #endif
654 #ifdef __OBJC__
655 ".objective-c"
656 #if defined(__cplusplus)
657 "plusplus"
658 #endif
659 #endif
660 #ifdef TCL_CFG_PROFILED
661 ".profile"
662 #endif
663 #ifdef PURIFY
664 ".purify"
665 #endif
666 #ifdef STATIC_BUILD
667 ".static"
668 #endif
669 ), NULL);
670 }
671 /*------------------------------------------------------------------------*/
672 /* This procedure is called once per thread and any thread local data */
673 /* should be allocated and initialized here (and not in static variables) */
674
675 /* Create a flag if Tk is loaded */
676 tkFlagPtr = (int *)ckalloc(sizeof(int));
677 *tkFlagPtr = 0;
678 Tcl_CallWhenDeleted(interp, InterpCleanupProc, (ClientData)tkFlagPtr);
679 /*------------------------------------------------------------------------*/
680 Tcl_CreateObjCommand(interp, "zint", ZintCmd, (ClientData)tkFlagPtr,
681 (Tcl_CmdDeleteProc *)NULL);
682 Tcl_PkgProvide (interp, "zint", version_string);
683 /*------------------------------------------------------------------------*/
684 return TCL_OK;
685 }
686 /*----------------------------------------------------------------------------*/
687 /* >>>> Cleanup procedure */
688 /*----------------------------------------------------------------------------*/
689 /* This routine is called, if a thread is terminated */
690 static void InterpCleanupProc(ClientData clientData, Tcl_Interp *interp)
691 {
692 ckfree( (char *)clientData );
693 }
694 /*----------------------------------------------------------------------------*/
695 /* >>>> Unload Procedures */
696 /*----------------------------------------------------------------------------*/
697 DLLEXPORT int Zint_Unload (Tcl_Interp *Interp, int Flags)
698 {
699 /* Remove created commands */
700 Tcl_DeleteCommand(Interp, "::zint::build-info");
701 Tcl_DeleteCommand(Interp, "zint");
702 // Allow unload
703 return TCL_OK;
704 }
705 /*----------------------------------------------------------------------------*/
706 /* >>>>> Called routine */
707 /*----------------------------------------------------------------------------*/
708 /* Decode tcl commands */
709 static int ZintCmd(ClientData tkFlagPtr, Tcl_Interp *interp, int objc,
710 Tcl_Obj *CONST objv[])
711 {
712 /* Option list and indexes */
713 enum iCommand {iEncode, iSymbologies, iECI, iVersion, iHelp};
714 /* choice of option */
715 int Index;
716 /*------------------------------------------------------------------------*/
717 /* > Check if option argument is given and decode it */
718 if (objc > 1)
719 {
720 char *subCmds[] = {"encode", "symbologies", "eci", "version", "help", NULL};
721 if(Tcl_GetIndexFromObj(interp, objv[1], (const char **) subCmds,
722 "option", 0, &Index)
723 == TCL_ERROR)
724 {
725 return TCL_ERROR;
726 }
727 } else {
728 Tcl_WrongNumArgs(interp, 1, objv, "option");
729 return TCL_ERROR;
730 }
731 /*------------------------------------------------------------------------*/
732 /* > Call functions in dependency of Index */
733 /*------------------------------------------------------------------------*/
734 switch (Index)
735 {
736 case iEncode:
737 if (CheckForTk(interp, (int *)tkFlagPtr) != TCL_OK) {
738 return TCL_ERROR;
739 }
740 return Encode(interp, objc, objv);
741 case iSymbologies:
742 {
743 Tcl_Obj *oRes;
744 int posCur;
745 oRes = Tcl_NewObj();
746 for (posCur = 0 ; s_code_list[posCur] != NULL; posCur++) {
747 if( ZBarcode_ValidID(s_code_number[posCur]) != 0) {
748 if (TCL_OK != Tcl_ListObjAppendElement(interp,
749 oRes, Tcl_NewStringObj(s_code_list[posCur],-1)))
750 {
751 return TCL_ERROR;
752 }
753 }
754 }
755 Tcl_SetObjResult(interp,oRes);
756 return TCL_OK;
757 }
758 case iECI:
759 {
760 Tcl_Obj *oRes;
761 int posCur;
762 oRes = Tcl_NewObj();
763 for (posCur = 0 ; s_eci_list[posCur] != NULL; posCur++) {
764 if (TCL_OK != Tcl_ListObjAppendElement(interp,
765 oRes, Tcl_NewStringObj(s_eci_list[posCur],-1)))
766 {
767 return TCL_ERROR;
768 }
769 }
770 Tcl_SetObjResult(interp,oRes);
771 return TCL_OK;
772 }
773 case iVersion:
774 Tcl_SetObjResult(interp,
775 Tcl_NewStringObj(version_string, -1));
776 return TCL_OK;
777 case iHelp:
778 default:
779 Tcl_SetObjResult(interp,
780 Tcl_NewStringObj(help_message, -1));
781 return TCL_OK;
782 }
783 }
784 /*----------------------------------------------------------------------
785 * Check availability of Tk.
786 *----------------------------------------------------------------------
787 */
788 static int CheckForTk(Tcl_Interp *interp, int *tkFlagPtr)
789 {
790 if (*tkFlagPtr > 0) {
791 return TCL_OK;
792 }
793 if (*tkFlagPtr == 0) {
794 if ( ! Tcl_PkgPresent(interp, "Tk", "8.5-", 0) ) {
795 Tcl_SetResult(interp, "package Tk not loaded", TCL_STATIC);
796 return TCL_ERROR;
797 }
798 }
799 #ifdef USE_TK_STUBS
800 if (*tkFlagPtr < 0 || Tk_InitStubs(interp, "8.5-", 0) == NULL) {
801 *tkFlagPtr = -1;
802 Tcl_SetResult(interp, "error initializing Tk", TCL_STATIC);
803 return TCL_ERROR;
804 }
805 #endif
806 *tkFlagPtr = 1;
807 return TCL_OK;
808 }/*----------------------------------------------------------------------------*/
809 /* >>>>> Encode */
810 /*----------------------------------------------------------------------------*/
811 /* Encode image */
812 static int Encode(Tcl_Interp *interp, int objc,
813 Tcl_Obj *CONST objv[])
814 {
815 struct zint_symbol *my_symbol;
816 Tcl_DString dsInput;
817 char *pStr = NULL;
818 Tcl_Size lStr;
819 Tcl_Encoding hZINTEncoding;
820 int rotate_angle=0;
821 int fError = 0;
822 Tcl_DString dString;
823 int optionPos;
824 int destX0 = 0;
825 int destY0 = 0;
826 int destWidth = 0;
827 int destHeight = 0;
828 int ECIIndex = 0;
829 int fFullMultiByte = 0;
830 int addon_gap = 0;
831 int Separator = 1;
832 int Mask = 0;
833 int rows = 0;
834 unsigned int cap;
835 int seg_count = 0;
836 int seg_no;
837 Tcl_Obj *pSegDataObjs[10] = {0};
838 Tcl_DString segInputs[10];
839 struct zint_seg segs[10];
840 double xdim = 0.0;
841 double resolution = 0.0;
842 /*------------------------------------------------------------------------*/
843 /* >> Check if at least data and object is given and a pair number of */
844 /* >> options */
845 if ( objc < 4 || (objc % 2) != 0 )
846 {
847 Tcl_WrongNumArgs(interp, 2, objv, "data photo ?-switch value?...");
848 return TCL_ERROR;
849 }
850 /*------------------------------------------------------------------------*/
851 /* >>> Prepare encoding */
852 hZINTEncoding = Tcl_GetEncoding(interp, "utf-8");
853 if (NULL == hZINTEncoding) {
854 return TCL_ERROR;
855 }
856 /*------------------------------------------------------------------------*/
857 /* >>> Prepare zint object */
858 my_symbol = ZBarcode_Create();
859 my_symbol->input_mode = UNICODE_MODE;
860 my_symbol->option_3 = 0;
861 /*------------------------------------------------------------------------*/
862 /* >> Decode options */
863 for (optionPos = 4; optionPos < objc; optionPos+=2) {
864 /*--------------------------------------------------------------------*/
865 /* Option list and indexes */
866 static const char *optionList[] = {
867 "-addongap", "-barcode", "-bg", "-bind", "-bindtop", "-bold", "-border", "-box",
868 "-cols", "-compliantheight", "-dmiso144", "-dmre", "-dotsize", "-dotty",
869 "-eci", "-esc", "-extraesc", "-fast", "-fg", "-format", "-fullmultibyte",
870 "-gs1nocheck", "-gs1parens", "-gssep", "-guarddescent", "-guardwhitespace",
871 "-height", "-heightperrow", "-init", "-mask", "-mode",
872 "-nobackground", "-noquietzones", "-notext", "-primary", "-quietzones",
873 "-reverse", "-rotate", "-rows", "-scale", "-scalexdimdp", "-scmvv", "-secure",
874 "-seg1", "-seg2", "-seg3", "-seg4", "-seg5", "-seg6", "-seg7", "-seg8", "-seg9",
875 "-separator", "-smalltext", "-square", "-structapp",
876 "-textgap", "-to", "-vers", "-vwhitesp", "-werror", "-whitesp",
877 NULL};
878 enum iOption {
879 iAddonGap, iBarcode, iBG, iBind, iBindTop, iBold, iBorder, iBox,
880 iCols, iCompliantHeight, iDMISO144, iDMRE, iDotSize, iDotty,
881 iECI, iEsc, iExtraEsc, iFast, iFG, iFormat, iFullMultiByte,
882 iGS1NoCheck, iGS1Parens, iGSSep, iGuardDescent, iGuardWhitespace,
883 iHeight, iHeightPerRow, iInit, iMask, iMode,
884 iNoBackground, iNoQuietZones, iNoText, iPrimary, iQuietZones,
885 iReverse, iRotate, iRows, iScale, iScaleXdimDp, iSCMvv, iSecure,
886 iSeg1, iSeg2, iSeg3, iSeg4, iSeg5, iSeg6, iSeg7, iSeg8, iSeg9,
887 iSeparator, iSmallText, iSquare, iStructApp,
888 iTextGap, iTo, iVers, iVWhiteSp, iWError, iWhiteSp
889 };
890 int optionIndex;
891 int intValue;
892 double doubleValue;
893 /*--------------------------------------------------------------------*/
894 if(Tcl_GetIndexFromObj(interp, objv[optionPos],
895 (const char **) optionList,
896 "zint option", 0, &optionIndex)
897 == TCL_ERROR)
898 {
899 fError = 1;
900 break;
901 }
902 /*--------------------------------------------------------------------*/
903 /* >> Decode object */
904 switch (optionIndex) {
905 case iBind:
906 case iBindTop:
907 case iBold:
908 case iBox:
909 case iCompliantHeight:
910 case iDMISO144:
911 case iDMRE:
912 case iDotty:
913 case iEsc:
914 case iExtraEsc:
915 case iFast:
916 case iGS1NoCheck:
917 case iGS1Parens:
918 case iGSSep:
919 case iGuardWhitespace:
920 case iHeightPerRow:
921 case iInit:
922 case iNoBackground:
923 case iNoQuietZones:
924 case iNoText:
925 case iQuietZones:
926 case iSmallText:
927 case iSquare:
928 case iFullMultiByte:
929 case iReverse:
930 case iWError:
931 /* >> Binary options */
932 if (TCL_OK != Tcl_GetBooleanFromObj(interp, objv[optionPos+1],
933 &intValue))
934 {
935 fError = 1;
936 }
937 break;
938 case iFG:
939 case iBG:
940 /* >> Colors */
941 pStr = Tcl_GetStringFromObj(objv[optionPos+1],&lStr);
942 if (lStr != 6 && lStr != 8) {
943 Tcl_SetObjResult(interp,
944 Tcl_NewStringObj("Color is not 6 or 8 hex",-1));
945 fError = 1;
946 }
947 break;
948 case iHeight:
949 case iGuardDescent:
950 case iDotSize:
951 case iScale:
952 case iTextGap:
953 /* >> Float */
954 if (TCL_OK != Tcl_GetDoubleFromObj(interp, objv[optionPos+1],
955 &doubleValue))
956 {
957 fError = 1;
958 }
959 break;
960 case iAddonGap:
961 case iBorder:
962 case iCols:
963 case iMask:
964 case iMode:
965 case iRotate:
966 case iRows:
967 case iSecure:
968 case iSeparator:
969 case iSCMvv:
970 case iVers:
971 case iVWhiteSp:
972 case iWhiteSp:
973 /* >> Int */
974 if (TCL_OK != Tcl_GetIntFromObj(interp, objv[optionPos+1],
975 &intValue))
976 {
977 fError = 1;
978 }
979 break;
980 case iPrimary:
981 /* > Primary String up to 90 characters */
982 /* > Output filename up to 250 characters */
983 Tcl_DStringInit(& dString);
984 pStr = Tcl_GetStringFromObj(objv[optionPos+1], &lStr);
985 Tcl_UtfToExternalDString( hZINTEncoding, pStr, lStr, &dString);
986 if (Tcl_DStringLength(&dString) > (optionIndex==iPrimary?90:250)) {
987 Tcl_DStringFree(&dString);
988 Tcl_SetObjResult(interp,Tcl_NewStringObj("String too long", -1));
989 fError = 1;
990 }
991 break;
992 case iSeg1: case iSeg2: case iSeg3: case iSeg4: case iSeg5:
993 case iSeg6: case iSeg7: case iSeg8: case iSeg9:
994 seg_no = optionIndex - iSeg1 + 1;
995 if (pSegDataObjs[seg_no]) {
996 Tcl_SetObjResult(interp, Tcl_NewStringObj("duplicate segment", -1));
997 fError = 1;
998 } else {
999 Tcl_Obj *poParam;
1000 if (TCL_OK != Tcl_ListObjLength(interp, objv[optionPos+1], &lStr)) {
1001 Tcl_SetObjResult(interp, Tcl_Format(interp, "option %s not a list", 1, objv + optionPos));
1002 fError = 1;
1003 } else if (lStr != 2) {
1004 Tcl_SetObjResult(interp, Tcl_Format(interp, "option %s not a list of 2", 1, objv + optionPos));
1005 fError = 1;
1006 } else if (TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1007 0, &poParam)
1008 || TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1009 1, &pSegDataObjs[seg_no])) {
1010 Tcl_SetObjResult(interp, Tcl_Format(interp, "option %s list format is {eci data}", 1, objv + optionPos));
1011 fError = 1;
1012 } else if (Tcl_GetIndexFromObj(interp, poParam,
1013 (const char **) s_eci_list, Tcl_GetString(objv[optionPos]), 0, &ECIIndex)
1014 == TCL_ERROR) {
1015 fError = 1;
1016 } else {
1017 segs[seg_no].eci = s_eci_number[ECIIndex];
1018 if (seg_no >= seg_count) {
1019 seg_count = seg_no + 1;
1020 }
1021 }
1022 }
1023 break;
1024 }
1025 if (fError) {
1026 break;
1027 }
1028 /*--------------------------------------------------------------------*/
1029 switch (optionIndex) {
1030 case iAddonGap:
1031 if (intValue < 7 || intValue > 12) {
1032 Tcl_SetObjResult(interp,
1033 Tcl_NewStringObj("Invalid add-on gap value not within 7 to 12", -1));
1034 fError = 1;
1035 } else {
1036 addon_gap = intValue;
1037 }
1038 break;
1039 case iBind:
1040 if (intValue) {
1041 my_symbol->output_options |= BARCODE_BIND;
1042 } else {
1043 my_symbol->output_options &= ~BARCODE_BIND;
1044 }
1045 break;
1046 case iBindTop:
1047 if (intValue) {
1048 my_symbol->output_options |= BARCODE_BIND_TOP;
1049 } else {
1050 my_symbol->output_options &= ~BARCODE_BIND_TOP;
1051 }
1052 break;
1053 case iBold:
1054 if (intValue) {
1055 my_symbol->output_options |= BOLD_TEXT;
1056 } else {
1057 my_symbol->output_options &= ~BOLD_TEXT;
1058 }
1059 break;
1060 case iBox:
1061 if (intValue) {
1062 my_symbol->output_options |= BARCODE_BOX;
1063 } else {
1064 my_symbol->output_options &= ~BARCODE_BOX;
1065 }
1066 break;
1067 case iCompliantHeight:
1068 if (intValue) {
1069 my_symbol->output_options |= COMPLIANT_HEIGHT;
1070 } else {
1071 my_symbol->output_options &= ~COMPLIANT_HEIGHT;
1072 }
1073 break;
1074 case iDotSize:
1075 if (doubleValue < 0.01) {
1076 Tcl_SetObjResult(interp,
1077 Tcl_NewStringObj("Dot size below 0.01", -1));
1078 fError = 1;
1079 } else {
1080 my_symbol->dot_size = (float)doubleValue;
1081 }
1082 break;
1083 case iDotty:
1084 if (intValue) {
1085 my_symbol->output_options |= BARCODE_DOTTY_MODE;
1086 } else {
1087 my_symbol->output_options &= ~BARCODE_DOTTY_MODE;
1088 }
1089 break;
1090 case iEsc:
1091 if (intValue) {
1092 my_symbol->input_mode |= ESCAPE_MODE;
1093 } else {
1094 my_symbol->input_mode &= ~ESCAPE_MODE;
1095 }
1096 break;
1097 case iExtraEsc:
1098 if (intValue) {
1099 my_symbol->input_mode |= EXTRA_ESCAPE_MODE;
1100 } else {
1101 my_symbol->input_mode &= ~EXTRA_ESCAPE_MODE;
1102 }
1103 break;
1104 case iFast:
1105 if (intValue) {
1106 my_symbol->input_mode |= FAST_MODE;
1107 } else {
1108 my_symbol->input_mode &= ~FAST_MODE;
1109 }
1110 break;
1111 case iGS1NoCheck:
1112 if (intValue) {
1113 my_symbol->input_mode |= GS1NOCHECK_MODE;
1114 } else {
1115 my_symbol->input_mode &= ~GS1NOCHECK_MODE;
1116 }
1117 break;
1118 case iGS1Parens:
1119 if (intValue) {
1120 my_symbol->input_mode |= GS1PARENS_MODE;
1121 } else {
1122 my_symbol->input_mode &= ~GS1PARENS_MODE;
1123 }
1124 break;
1125 case iGSSep:
1126 if (intValue) {
1127 my_symbol->output_options |= GS1_GS_SEPARATOR;
1128 } else {
1129 my_symbol->output_options &= ~GS1_GS_SEPARATOR;
1130 }
1131 break;
1132 case iFullMultiByte:
1133 fFullMultiByte = intValue;
1134 break;
1135 case iECI:
1136 if(Tcl_GetIndexFromObj(interp, objv[optionPos+1],
1137 (const char **) s_eci_list, "-eci", 0, &ECIIndex)
1138 == TCL_ERROR)
1139 {
1140 fError = 1;
1141 } else {
1142 my_symbol->eci = s_eci_number[ECIIndex];
1143 }
1144 break;
1145 case iGuardWhitespace:
1146 if (intValue) {
1147 my_symbol->output_options |= EANUPC_GUARD_WHITESPACE;
1148 } else {
1149 my_symbol->output_options &= ~EANUPC_GUARD_WHITESPACE;
1150 }
1151 break;
1152 case iHeightPerRow:
1153 if (intValue) {
1154 my_symbol->input_mode |= HEIGHTPERROW_MODE;
1155 } else {
1156 my_symbol->input_mode &= ~HEIGHTPERROW_MODE;
1157 }
1158 break;
1159 case iInit:
1160 if (intValue) {
1161 my_symbol->output_options |= READER_INIT;
1162 } else {
1163 my_symbol->output_options &= ~READER_INIT;
1164 }
1165 break;
1166 case iSmallText:
1167 if (intValue) {
1168 my_symbol->output_options |= SMALL_TEXT;
1169 } else {
1170 my_symbol->output_options &= ~SMALL_TEXT;
1171 }
1172 break;
1173 case iReverse:
1174 if (intValue) {
1175 strcpy(my_symbol->fgcolour, "ffffff");
1176 strcpy(my_symbol->bgcolour, "000000");
1177 }
1178 break;
1179 case iWError:
1180 if (intValue) {
1181 my_symbol->warn_level = WARN_FAIL_ALL;
1182 }
1183 break;
1184 case iFG:
1185 strncpy(my_symbol->fgcolour, pStr, lStr);
1186 my_symbol->fgcolour[lStr]='\0';
1187 break;
1188 case iBG:
1189 strncpy(my_symbol->bgcolour, pStr, lStr);
1190 my_symbol->bgcolour[lStr]='\0';
1191 break;
1192 case iNoBackground:
1193 if (intValue) {
1194 strcpy(my_symbol->bgcolour, "ffffff00");
1195 }
1196 break;
1197 case iNoQuietZones:
1198 if (intValue) {
1199 my_symbol->output_options |= BARCODE_NO_QUIET_ZONES;
1200 } else {
1201 my_symbol->output_options &= ~BARCODE_NO_QUIET_ZONES;
1202 }
1203 break;
1204 case iNoText:
1205 my_symbol->show_hrt = (intValue?0:1);
1206 break;
1207 case iQuietZones:
1208 if (intValue) {
1209 my_symbol->output_options |= BARCODE_QUIET_ZONES;
1210 } else {
1211 my_symbol->output_options &= ~BARCODE_QUIET_ZONES;
1212 }
1213 break;
1214 case iSquare:
1215 /* DM_SQUARE overwrites DM_DMRE */
1216 if (intValue)
1217 my_symbol->option_3 = DM_SQUARE | (my_symbol->option_3 & ~0x7F);
1218 break;
1219 case iDMRE:
1220 /* DM_DMRE overwrites DM_SQUARE */
1221 if (intValue)
1222 my_symbol->option_3 = DM_DMRE | (my_symbol->option_3 & ~0x7F);
1223 break;
1224 case iDMISO144:
1225 if (intValue)
1226 my_symbol->option_3 |= DM_ISO_144;
1227 break;
1228 case iScale:
1229 if (doubleValue < 0.01) {
1230 Tcl_SetObjResult(interp,
1231 Tcl_NewStringObj("Scale below 0.01", -1));
1232 fError = 1;
1233 } else {
1234 my_symbol->scale = (float)doubleValue;
1235 }
1236 break;
1237 case iTextGap:
1238 if (doubleValue < 0.0 || doubleValue > 5.0) {
1239 Tcl_SetObjResult(interp,
1240 Tcl_NewStringObj("Text Gap out of range", -1));
1241 fError = 1;
1242 } else {
1243 my_symbol->text_gap = (float)doubleValue;
1244 }
1245 break;
1246 case iScaleXdimDp:
1247 /* >> Decode the -scalexdimdp parameter as list of xdim ?resolution? */
1248 {
1249 Tcl_Obj *poParam;
1250 xdim = resolution = 0.0;
1251 if (TCL_OK != Tcl_ListObjLength(interp,
1252 objv[optionPos+1], &lStr))
1253 {
1254 fError = 1;
1255 } else if ( ! ( lStr == 1 || lStr == 2 ) ) {
1256 Tcl_SetObjResult(interp,
1257 Tcl_NewStringObj(
1258 "option -scalexdimdp not a list of 1 or 2", -1));
1259 fError = 1;
1260 } else {
1261 if (TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1262 0, &poParam)
1263 || TCL_OK != Tcl_GetDoubleFromObj(interp, poParam, &xdim)
1264 || xdim < 0.0)
1265 {
1266 fError = 1;
1267 }
1268 if (!fError && lStr == 2 && (
1269 TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1270 1, &poParam)
1271 || TCL_OK != Tcl_GetDoubleFromObj(interp, poParam, &resolution)
1272 || resolution < 0.0))
1273 {
1274 fError = 1;
1275 }
1276 if (!fError && resolution == 0.0) {
1277 resolution = 12.0; /* Default 12 dpmm (~300 dpi) */
1278 }
1279 }
1280 }
1281 break;
1282 case iBorder:
1283 if (intValue < 0 || intValue > 1000) {
1284 Tcl_SetObjResult(interp,
1285 Tcl_NewStringObj("Border out of range", -1));
1286 fError = 1;
1287 } else {
1288 my_symbol->border_width = intValue;
1289 }
1290 break;
1291 case iGuardDescent:
1292 if ((float)doubleValue < 0.0f || (float)doubleValue > 50.0f) {
1293 Tcl_SetObjResult(interp,
1294 Tcl_NewStringObj("Guard bar descent out of range", -1));
1295 fError = 1;
1296 } else {
1297 my_symbol->guard_descent = (float)doubleValue;
1298 }
1299 break;
1300 case iHeight:
1301 if ((float)doubleValue < 0.5f || (float)doubleValue > 2000.0f) {
1302 Tcl_SetObjResult(interp,
1303 Tcl_NewStringObj("Height out of range", -1));
1304 fError = 1;
1305 } else {
1306 my_symbol->height = (float)doubleValue;
1307 }
1308 break;
1309 case iSeparator:
1310 if (intValue < 0 || intValue > 4) {
1311 Tcl_SetObjResult(interp,
1312 Tcl_NewStringObj("Separator out of range", -1));
1313 fError = 1;
1314 } else {
1315 Separator = intValue;
1316 }
1317 break;
1318 case iMask:
1319 if (intValue < 0 || intValue > 7) {
1320 Tcl_SetObjResult(interp,
1321 Tcl_NewStringObj("Mask out of range", -1));
1322 fError = 1;
1323 } else {
1324 Mask = intValue + 1;
1325 }
1326 break;
1327 case iSCMvv:
1328 if (intValue < 0 || intValue > 99) {
1329 Tcl_SetObjResult(interp,
1330 Tcl_NewStringObj("SCM version out of range", -1));
1331 fError = 1;
1332 } else {
1333 my_symbol->option_2 = intValue + 1;
1334 }
1335 break;
1336 case iCols:
1337 case iVers:
1338 /* >> Int in Option 2 */
1339 if (intValue < 1
1340 || (optionIndex==iCols && intValue > 200)
1341 || (optionIndex==iVers && intValue > 999))
1342 {
1343 Tcl_SetObjResult(interp,
1344 Tcl_NewStringObj("cols/vers out of range", -1));
1345 fError = 1;
1346 } else {
1347 my_symbol->option_2 = intValue;
1348 }
1349 break;
1350 case iSecure:
1351 case iMode:
1352 case iRows:
1353 /* >> Int in Option 1 for Codablock, Option 3 for PDF417 */
1354 if ( (optionIndex==iSecure && (intValue < 1 || intValue > 8))
1355 || (optionIndex==iMode && (intValue < 0 || intValue > 6))
1356 || (optionIndex==iRows && (intValue < 0 || intValue > 90)))
1357 {
1358 Tcl_SetObjResult(interp,
1359 Tcl_NewStringObj("secure/mode/rows out of range", -1));
1360 fError = 1;
1361 } else {
1362 rows = intValue;
1363 }
1364 break;
1365 case iPrimary:
1366 strcpy(my_symbol->primary, Tcl_DStringValue( &dString ) );
1367 Tcl_DStringFree(&dString);
1368 break;
1369 case iRotate:
1370 /* >> Rotate angle */
1371 /*----------------------------------------------------------------*/
1372 {
1373 char *rotateList[] = {"0", "90", "180", "270", NULL};
1374 enum iRotate { iRotate0, iRotate90, iRotate180, iRotate270 };
1375 /*------------------------------------------------------------*/
1376 if(Tcl_GetIndexFromObj(interp, objv[optionPos+1],
1377 (const char **) rotateList,
1378 "-rotate", 0, &intValue)
1379 == TCL_ERROR)
1380 {
1381 fError = 1;
1382 break;
1383 }
1384 switch (intValue) {
1385 case iRotate90: rotate_angle = 90; break;
1386 case iRotate180: rotate_angle = 180; break;
1387 case iRotate270: rotate_angle = 270; break;
1388 default: rotate_angle = 0; break;
1389 }
1390 }
1391 break;
1392 case iBarcode:
1393 if(Tcl_GetIndexFromObj(interp, objv[optionPos+1],
1394 (const char **) s_code_list, "-barcode", 0, &intValue)
1395 == TCL_ERROR)
1396 {
1397 fError = 1;
1398 } else {
1399 my_symbol->symbology = s_code_number[intValue];
1400 }
1401 break;
1402 case iVWhiteSp:
1403 my_symbol->whitespace_height = intValue;
1404 break;
1405 case iWhiteSp:
1406 my_symbol->whitespace_width = intValue;
1407 break;
1408 case iStructApp:
1409 /* >> Decode the -structapp parameter as list of index count ?ID? */
1410 {
1411 Tcl_Obj *poParam;
1412 struct zint_structapp structapp = { 0, 0, "" };
1413 char *pStructAppId = NULL;
1414 Tcl_Size lStructAppId = 0;
1415 if (TCL_OK != Tcl_ListObjLength(interp,
1416 objv[optionPos+1], &lStr))
1417 {
1418 fError = 1;
1419 } else if ( ! ( lStr == 2 || lStr == 3 ) ) {
1420 Tcl_SetObjResult(interp,
1421 Tcl_NewStringObj(
1422 "option -structapp not a list of 2 or 3", -1));
1423 fError = 1;
1424 } else {
1425 if (TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1426 0, &poParam)
1427 || TCL_OK != Tcl_GetIntFromObj(interp, poParam, &structapp.index)
1428 || TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1429 1, &poParam)
1430 || TCL_OK != Tcl_GetIntFromObj(interp, poParam, &structapp.count))
1431 {
1432 fError = 1;
1433 }
1434 if (!fError && lStr == 3 && (
1435 TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1436 2, &poParam)
1437 || !(pStructAppId = Tcl_GetStringFromObj(poParam, &lStructAppId))
1438 || lStructAppId > 32
1439 ))
1440 {
1441 if (lStructAppId > 32) {
1442 Tcl_SetObjResult(interp,
1443 Tcl_NewStringObj("Structured Append ID too long", -1));
1444 }
1445 fError = 1;
1446 }
1447 if (!fError) {
1448 my_symbol->structapp = structapp;
1449 if (lStr == 3 && pStructAppId && lStructAppId) {
1450 strncpy(my_symbol->structapp.id, pStructAppId, lStructAppId);
1451 }
1452 }
1453 }
1454 }
1455 break;
1456 case iTo:
1457 /* >> Decode the -to parameter as list of X0 Y0 ?Width Height? */
1458 {
1459 Tcl_Obj *poParam;
1460 if (TCL_OK != Tcl_ListObjLength(interp,
1461 objv[optionPos+1], &lStr))
1462 {
1463 fError = 1;
1464 } else if ( ! ( lStr == 2 || lStr == 4 ) ) {
1465 Tcl_SetObjResult(interp,
1466 Tcl_NewStringObj(
1467 "option -to not a list of 2 or 4", -1));
1468 fError = 1;
1469 } else {
1470 if (TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1471 0, &poParam)
1472 || TCL_OK != Tcl_GetIntFromObj(interp,poParam,&destX0)
1473 || TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1474 1, &poParam)
1475 || TCL_OK != Tcl_GetIntFromObj(interp,poParam,&destY0))
1476 {
1477 fError = 1;
1478 }
1479 if (!fError && lStr == 4 && (
1480 TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1481 2, &poParam)
1482 || TCL_OK != Tcl_GetIntFromObj(interp,poParam,
1483 &destWidth)
1484 || TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1485 3, &poParam)
1486 || TCL_OK != Tcl_GetIntFromObj(interp,poParam,
1487 &destHeight)
1488 ))
1489 {
1490 fError = 1;
1491 }
1492 }
1493 }
1494 break;
1495 case iFormat:
1496 /* >> Format of the input data */
1497 /*----------------------------------------------------------------*/
1498 {
1499 char *formatList[] = {"binary", "gs1", "unicode",NULL};
1500 enum iFormat { iBinary, iGS1, iUnicode };
1501 /*------------------------------------------------------------*/
1502 if(Tcl_GetIndexFromObj(interp, objv[optionPos+1],
1503 (const char **) formatList,
1504 "-format", 0, &intValue)
1505 == TCL_ERROR)
1506 {
1507 fError = 1;
1508 break;
1509 }
1510 switch (intValue) {
1511 case iBinary: my_symbol->input_mode = (my_symbol->input_mode & ~0x07) | DATA_MODE; break;
1512 case iGS1: my_symbol->input_mode = (my_symbol->input_mode & ~0x07) | GS1_MODE; break;
1513 default: my_symbol->input_mode = (my_symbol->input_mode & ~0x07) | UNICODE_MODE; break;
1514 }
1515 }
1516 }
1517 }
1518 /*------------------------------------------------------------------------*/
1519 /* >>> Get symbology capability mask */
1520 cap = ZBarcode_Cap(my_symbol->symbology,
1521 ZINT_CAP_STACKABLE | ZINT_CAP_EXTENDABLE | ZINT_CAP_FULL_MULTIBYTE
1522 | ZINT_CAP_MASK);
1523 /*------------------------------------------------------------------------*/
1524 /* >>> option_3 is set by three values depending on the symbology */
1525 /* On wrong symbology, the option is ignored(as does the zint program)*/
1526 if (fFullMultiByte && (cap & ZINT_CAP_FULL_MULTIBYTE)) {
1527 my_symbol->option_3 = ZINT_FULL_MULTIBYTE;
1528 }
1529 if (Mask && (cap & ZINT_CAP_MASK)) {
1530 my_symbol->option_3 |= Mask << 8;
1531 }
1532 if (Separator && (cap & ZINT_CAP_STACKABLE)) {
1533 my_symbol->option_3 = Separator;
1534 }
1535 /*------------------------------------------------------------------------*/
1536 /* >>> option_2 is set by two values depending on the symbology */
1537 /* On wrong symbology, the option is ignored(as does the zint program)*/
1538 if (addon_gap && (cap & ZINT_CAP_EXTENDABLE)) {
1539 my_symbol->option_2 = addon_gap;
1540 }
1541 /*------------------------------------------------------------------------*/
1542 if (rows) {
1543 /* PDF417 and DBAR_EXPSTK use option 3 for rows */
1544 if (my_symbol->symbology == BARCODE_PDF417
1545 || my_symbol->symbology == BARCODE_PDF417COMP
1546 || my_symbol->symbology == BARCODE_HIBC_PDF
1547 || my_symbol->symbology == BARCODE_DBAR_EXPSTK
1548 || my_symbol->symbology == BARCODE_DBAR_EXPSTK_CC) {
1549 my_symbol->option_3 = rows;
1550 } else if (my_symbol->symbology == BARCODE_CODABLOCKF
1551 || my_symbol->symbology == BARCODE_HIBC_BLOCKF
1552 || my_symbol->symbology == BARCODE_CODE16K
1553 || my_symbol->symbology == BARCODE_CODE49) {
1554 my_symbol->option_1 = rows;
1555 }
1556 }
1557 if (resolution) {
1558 float scale;
1559 if (xdim == 0.0) {
1560 xdim = ZBarcode_Default_Xdim(my_symbol->symbology);
1561 }
1562 scale = ZBarcode_Scale_From_XdimDp(my_symbol->symbology, (float)xdim, (float)resolution, NULL /*filetype*/);
1563 if (scale > 0.0f) {
1564 my_symbol->scale = scale;
1565 }
1566 }
1567 /*------------------------------------------------------------------------*/
1568 /* >>> Prepare input dstring and encode it to ECI encoding*/
1569 Tcl_DStringInit(& dsInput);
1570 /*------------------------------------------------------------------------*/
1571 if (!fError) {
1572 /*--------------------------------------------------------------------*/
1573 /* >>> Get input mode */
1574 if ((my_symbol->input_mode & 0x07) == DATA_MODE) {
1575 /* Binary data */
1576 pStr = (char *) Tcl_GetByteArrayFromObj(objv[2], &lStr);
1577 } else {
1578 /* UTF8 Data */
1579 pStr = Tcl_GetStringFromObj(objv[2], &lStr);
1580 Tcl_UtfToExternalDString( hZINTEncoding, pStr, lStr, &dsInput);
1581 pStr = Tcl_DStringValue( &dsInput );
1582 lStr = Tcl_DStringLength( &dsInput );
1583 }
1584 if (seg_count) {
1585 segs[0].source = (unsigned char *) pStr;
1586 segs[0].length = (int)lStr;
1587 segs[0].eci = my_symbol->eci;
1588 for (seg_no = 1; seg_no < seg_count; seg_no++) {
1589 if (!pSegDataObjs[seg_no]) {
1590 Tcl_SetObjResult(interp, Tcl_NewStringObj("Segments must be consecutive", -1));
1591 fError = 1;
1592 break;
1593 }
1594 }
1595 if (!fError) {
1596 for (seg_no = 1; seg_no < seg_count; seg_no++) {
1597 if ((my_symbol->input_mode & 0x07) == DATA_MODE) {
1598 Tcl_Size LengthTemp;
1599 segs[seg_no].source = (unsigned char *) Tcl_GetByteArrayFromObj(pSegDataObjs[seg_no],
1600 &LengthTemp);
1601 segs[seg_no].length = (int)LengthTemp;
1602 } else {
1603 pStr = Tcl_GetStringFromObj(pSegDataObjs[seg_no], &lStr);
1604 Tcl_DStringInit(& segInputs[seg_no]);
1605 Tcl_UtfToExternalDString( hZINTEncoding, pStr, lStr, &segInputs[seg_no]);
1606 segs[seg_no].source = (unsigned char *) Tcl_DStringValue( &segInputs[seg_no] );
1607 segs[seg_no].length = (int)Tcl_DStringLength( &segInputs[seg_no] );
1608 }
1609 }
1610 }
1611 }
1612 }
1613 /*------------------------------------------------------------------------*/
1614 /* >>> Build symbol graphic */
1615 if (! fError ) {
1616 int ErrorNumber;
1617 Tk_PhotoHandle hPhoto;
1618 /*--------------------------------------------------------------------*/
1619 /* call zint graphic creation to buffer */
1620 if (seg_count) {
1621 ErrorNumber = ZBarcode_Encode_Segs_and_Buffer(my_symbol,
1622 segs, seg_count, rotate_angle);
1623 } else {
1624 ErrorNumber = ZBarcode_Encode_and_Buffer(my_symbol,
1625 (unsigned char *) pStr, (int)lStr, rotate_angle);
1626 }
1627 /*--------------------------------------------------------------------*/
1628 /* >> Show a message */
1629 if( 0 != ErrorNumber )
1630 {
1631 Tcl_SetObjResult(interp, Tcl_NewStringObj(my_symbol->errtxt, -1));
1632 }
1633 if( ZINT_ERROR <= ErrorNumber )
1634 {
1635 /* >> Encode error */
1636 fError = 1;
1637 } else if (
1638 NULL == (hPhoto = Tk_FindPhoto(interp, Tcl_GetString(objv[3]))))
1639 {
1640 Tcl_SetObjResult(interp,
1641 Tcl_NewStringObj("Unknown photo image", -1));
1642 fError = 1;
1643 } else {
1644 Tk_PhotoImageBlock sImageBlock;
1645 char * pImageRGBA = NULL;
1646 if (my_symbol->alphamap == NULL) {
1647 sImageBlock.pixelPtr = (unsigned char *) my_symbol->bitmap;
1648 sImageBlock.width = my_symbol->bitmap_width;
1649 sImageBlock.height = my_symbol->bitmap_height;
1650 sImageBlock.pitch = 3*my_symbol->bitmap_width;
1651 sImageBlock.pixelSize = 3;
1652 sImageBlock.offset[0] = 0;
1653 sImageBlock.offset[1] = 1;
1654 sImageBlock.offset[2] = 2;
1655 sImageBlock.offset[3] = 0;
1656 } else {
1657 int index;
1658 /* Alpha channel present - prepare the image data in rgba order */
1659 pImageRGBA = ckalloc(my_symbol->bitmap_width*my_symbol->bitmap_height*4);
1660 for (index = 0; index < my_symbol->bitmap_width*my_symbol->bitmap_height; index++) {
1661 pImageRGBA[index*4] = my_symbol->bitmap[index*3];
1662 pImageRGBA[index*4+1] = my_symbol->bitmap[index*3+1];
1663 pImageRGBA[index*4+2] = my_symbol->bitmap[index*3+2];
1664 pImageRGBA[index*4+3] = my_symbol->alphamap[index];
1665 }
1666 sImageBlock.pixelPtr = (unsigned char *) pImageRGBA;
1667 sImageBlock.width = my_symbol->bitmap_width;
1668 sImageBlock.height = my_symbol->bitmap_height;
1669 sImageBlock.pitch = 4*my_symbol->bitmap_width;
1670 sImageBlock.pixelSize = 4;
1671 sImageBlock.offset[0] = 0;
1672 sImageBlock.offset[1] = 1;
1673 sImageBlock.offset[2] = 2;
1674 sImageBlock.offset[3] = 3;
1675 }
1676 if (0 == destWidth) {
1677 destWidth = my_symbol->bitmap_width;
1678 }
1679 if (0 == destHeight) {
1680 destHeight = my_symbol->bitmap_height;
1681 }
1682 if (TCL_OK != Tk_PhotoPutBlock(interp, hPhoto, &sImageBlock,
1683 destX0, destY0, destWidth, destHeight,
1684 TK_PHOTO_COMPOSITE_OVERLAY))
1685 {
1686 fError = 1;
1687 }
1688 if (pImageRGBA != NULL) {
1689 ckfree(pImageRGBA);
1690 }
1691 }
1692 }
1693 /*------------------------------------------------------------------------*/
1694 Tcl_FreeEncoding(hZINTEncoding);
1695 Tcl_DStringFree(& dsInput);
1696 ZBarcode_Delete(my_symbol);
1697 /*------------------------------------------------------------------------*/
1698 if (fError) {
1699 return TCL_ERROR;
1700 }
1701 return TCL_OK;
1702 }
1703
1704 /* vim: set ts=4 sw=4 et : */