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 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 /* vim: set ts=4 sw=4 et : */
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 */
126
127 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
128 #pragma warning(disable : 4201 4214 4514)
129 #define STRICT
130 #define WIN32_LEAN_AND_MEAN
131 /* TCL Defines */
132 #define DLL_BUILD
133
134 #include <windows.h>
135
136 /* Define ERROR_INVALID_DATA is also used by zint... */
137 #ifdef ERROR_INVALID_DATA
138 #undef ERROR_INVALID_DATA
139 #endif
140 #endif
141
142 #include <zint.h>
143 /* Load version defines */
144 #include <zintconfig.h>
145 #include <string.h>
146
147 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
148 #define USE_TCL_STUBS
149 #define USE_TK_STUBS
150 #endif
151
152 #include <tcl.h>
153 #include <tk.h>
154
155 #undef EXPORT
156 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
157 #define EXPORT __declspec(dllexport)
158 #else
159 #define EXPORT
160 #endif
161
162
163 /*----------------------------------------------------------------------------*/
164 /* >>>>> Hepler defines */
165
166 /* Two macros are necessary to not include the define name, but the value */
167 #define STRING(x) #x
168 #define TOSTRING(x) STRING(x)
169
170 /* Define VERSION as the first 3 digits of the zint library version number */
171 #define VERSION TOSTRING( ZINT_VERSION_MAJOR ) \
172 "." TOSTRING( ZINT_VERSION_MINOR ) \
173 "." TOSTRING( ZINT_VERSION_RELEASE )
174
175 /*----------------------------------------------------------------------------*/
176 /* >>>> External Prototypes (exports) */
177 EXPORT int Zint_Init (Tcl_Interp *interp);
178 EXPORT int Zint_Unload (Tcl_Interp *Interp, int Flags);
179 /*----------------------------------------------------------------------------*/
180 /* >>>> local prototypes */
181 static void InterpCleanupProc(ClientData clientData, Tcl_Interp *interp);
182 static int CheckForTk(Tcl_Interp *interp, int *tkFlagPtr);
183 static int Zint(ClientData unused, Tcl_Interp *interp, int objc,
184 Tcl_Obj *CONST objv[]);
185 static int Encode(Tcl_Interp *interp, int objc,
186 Tcl_Obj *CONST objv[]);
187 /*----------------------------------------------------------------------------*/
188 /* >>>> File Global Variables */
189
190 /* >> List of Codes */
191
192 static char *s_code_list[] = {
193 "Code11",
194 "Standard2of5",
195 "Interleaved2of5",
196 "IATAC2of5",
197 "Logic2of5",
198 "Ind2of5",
199 "Code39",
200 "Code39Extended",
201 "EAN",
202 "EAN+Check",
203 "GS1-128",
204 "Codabar",
205 "Code128",
206 "DPLeit",
207 "DPIdent",
208 "Code16K",
209 "Code49",
210 "Code93",
211 "Flat",
212 "GS1DataBar",
213 "GS1DataBarLimited",
214 "GS1DataBarExpanded",
215 "Telepen",
216 "UPC-A",
217 "UPC-A+Check",
218 "UPC-E",
219 "UPC-E+Check",
220 "POSTNET",
221 "MSIPlessey",
222 "FIM",
223 "Logmars",
224 "Pharma",
225 "PZN",
226 "PharmaTwo",
227 "PDF417",
228 "PDF417Compact",
229 "MaxiCode",
230 "QR",
231 "Code128B",
232 "AusPost",
233 "AusReply",
234 "AusRoute",
235 "AusRedirect",
236 "ISBN",
237 "RM4SCC",
238 "Datamatrix",
239 "EAN14",
240 "VIN",
241 "CodablockF",
242 "NVE18",
243 "JapanPost",
244 "KoreaPost",
245 "GS1DataBarStacked",
246 "GS1DataBarSstackedOmni",
247 "GS1DataBarExpandedStacked",
248 "PLANET",
249 "DPDCode",
250 "MicroPDF417",
251 "USPSIntelligentMail",
252 "Plessey",
253 "TelepenNum",
254 "ITF14",
255 "KIX",
256 "Aztec",
257 "DAFT",
258 "MicroQR",
259 "HIBC-128",
260 "HIBC-39",
261 "HIBC-DM",
262 "HIBC-QR",
263 "HIBC-PDF",
264 "HIBC-MicroPDF",
265 "HIBC-CodablockF",
266 "HIBCAztec",
267 "DotCode",
268 "HanXin",
269 "MailMark",
270 "AztecRunes",
271 "Code32",
272 "EAN-CC",
273 "GS1-128-CC",
274 "GS1DataBarOmni-CC",
275 "GS1DataBarLimited-CC",
276 "GS1DataBarExpanded-CC",
277 "UPCA-CC",
278 "UPCE-CC",
279 "GS1DataBarStacked-CC",
280 "GS1DataBarStackedOmni-CC",
281 "GS1DataBarExpandedStacked-CC",
282 "Channel",
283 "CodeOne",
284 "GridMatrix",
285 "UPNQR",
286 "UltraCode",
287 "rMQR",
288 NULL};
289
290 static int s_code_number[] = {
291 BARCODE_CODE11,
292 BARCODE_C25STANDARD,
293 BARCODE_C25INTER,
294 BARCODE_C25IATA,
295 BARCODE_C25LOGIC,
296 BARCODE_C25IND,
297 BARCODE_CODE39,
298 BARCODE_EXCODE39,
299 BARCODE_EANX,
300 BARCODE_EANX_CHK,
301 BARCODE_GS1_128,
302 BARCODE_CODABAR,
303 BARCODE_CODE128,
304 BARCODE_DPLEIT,
305 BARCODE_DPIDENT,
306 BARCODE_CODE16K,
307 BARCODE_CODE49,
308 BARCODE_CODE93,
309 BARCODE_FLAT,
310 BARCODE_DBAR_OMN,
311 BARCODE_DBAR_LTD,
312 BARCODE_DBAR_EXP,
313 BARCODE_TELEPEN,
314 BARCODE_UPCA,
315 BARCODE_UPCA_CHK,
316 BARCODE_UPCE,
317 BARCODE_UPCE_CHK,
318 BARCODE_POSTNET,
319 BARCODE_MSI_PLESSEY,
320 BARCODE_FIM,
321 BARCODE_LOGMARS,
322 BARCODE_PHARMA,
323 BARCODE_PZN,
324 BARCODE_PHARMA_TWO,
325 BARCODE_PDF417,
326 BARCODE_PDF417COMP,
327 BARCODE_MAXICODE,
328 BARCODE_QRCODE,
329 BARCODE_CODE128B,
330 BARCODE_AUSPOST,
331 BARCODE_AUSREPLY,
332 BARCODE_AUSROUTE,
333 BARCODE_AUSREDIRECT,
334 BARCODE_ISBNX,
335 BARCODE_RM4SCC,
336 BARCODE_DATAMATRIX,
337 BARCODE_EAN14,
338 BARCODE_VIN,
339 BARCODE_CODABLOCKF,
340 BARCODE_NVE18,
341 BARCODE_JAPANPOST,
342 BARCODE_KOREAPOST,
343 BARCODE_DBAR_STK,
344 BARCODE_DBAR_OMNSTK,
345 BARCODE_DBAR_EXPSTK,
346 BARCODE_PLANET,
347 BARCODE_DPD,
348 BARCODE_MICROPDF417,
349 BARCODE_USPS_IMAIL,
350 BARCODE_PLESSEY,
351 BARCODE_TELEPEN_NUM,
352 BARCODE_ITF14,
353 BARCODE_KIX,
354 BARCODE_AZTEC,
355 BARCODE_DAFT,
356 BARCODE_MICROQR,
357 BARCODE_HIBC_128,
358 BARCODE_HIBC_39,
359 BARCODE_HIBC_DM,
360 BARCODE_HIBC_QR,
361 BARCODE_HIBC_PDF,
362 BARCODE_HIBC_MICPDF,
363 BARCODE_HIBC_BLOCKF,
364 BARCODE_HIBC_AZTEC,
365 BARCODE_DOTCODE,
366 BARCODE_HANXIN,
367 BARCODE_MAILMARK,
368 BARCODE_AZRUNE,
369 BARCODE_CODE32,
370 BARCODE_EANX_CC,
371 BARCODE_GS1_128_CC,
372 BARCODE_DBAR_OMN_CC,
373 BARCODE_DBAR_LTD_CC,
374 BARCODE_DBAR_EXP_CC,
375 BARCODE_UPCA_CC,
376 BARCODE_UPCE_CC,
377 BARCODE_DBAR_STK_CC,
378 BARCODE_DBAR_OMNSTK_CC,
379 BARCODE_DBAR_EXPSTK_CC,
380 BARCODE_CHANNEL,
381 BARCODE_CODEONE,
382 BARCODE_GRIDMATRIX,
383 BARCODE_UPNQR,
384 BARCODE_ULTRA,
385 BARCODE_RMQR,
386 0};
387
388 /* ECI TCL encoding names.
389 * The ECI comments are given after the name.
390 * A ** indicates encodings where native data must be delivered and not utf-8
391 */
392 static char *s_eci_list[] = {
393 "iso8859-1", /* 3: ISO-8859-1 - Latin alphabet No. 1 (default)*/
394 "iso8859-2", /* 4: ISO-8859-2 - Latin alphabet No. 2*/
395 "iso8859-3", /* 5: ISO-8859-3 - Latin alphabet No. 3*/
396 "iso8859-4", /* 6: ISO-8859-4 - Latin alphabet No. 4*/
397 "iso8859-5", /* 7: ISO-8859-5 - Latin/Cyrillic alphabet*/
398 "iso8859-6", /* 8: ISO-8859-6 - Latin/Arabic alphabet*/
399 "iso8859-7", /* 9: ISO-8859-7 - Latin/Greek alphabet*/
400 "iso8859-9", /*10: ISO-8859-8 - Latin/Hebrew alphabet*/
401 "iso8859-9", /*11: ISO-8859-9 - Latin alphabet No. 5*/
402 "iso8859-10", /*12: ISO-8859-10 - Latin alphabet No. 6*/
403 "iso8859-11", /*13: ISO-8859-11 - Latin/Thai alphabet*/
404 "iso8859-13", /*15: ISO-8859-13 - Latin alphabet No. 7*/
405 "iso8859-14", /*16: ISO-8859-14 - Latin alphabet No. 8 (Celtic)*/
406 "iso8859-15", /*17: ISO-8859-15 - Latin alphabet No. 9*/
407 "iso8859-16", /*18: ISO-8859-16 - Latin alphabet No. 10*/
408 "jis0208", /*20: Shift JIS (JIS X 0208 and JIS X 0201)*/
409 "cp1250", /*21: Windows-1250*/
410 "cp1251", /*22: Windows-1251*/
411 "cp1252", /*23: Windows-1252*/
412 "cp1256", /*24: Windows-1256*/
413 "unicode", /*25: UCS-2BE (High order byte first) Unicode BMP*/
414 "utf-8", /*26: Unicode (UTF-8)*/
415 "ascii", /*27: ISO-646:1991 7-bit character set*/
416 "big5", /*28: Big5 (Taiwan) Chinese Character Set*/
417 "euc-cn", /*29: GB (PRC) Chinese Character Set*/
418 "iso2022-kr", /*30: Korean Character Set EUC-KR (KS X 1001:2002)*/
419 NULL
420 };
421
422 /* The ECI numerical number to pass to ZINT */
423 static int s_eci_number[] = {
424 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
425 };
426
427
428 /* Version information */
429 static char version_string[] = VERSION;
430 /* Help text */
431 static char help_message[] = "zint tcl(stub,obj) dll\n"
432 " Generate barcode in tk images\n"
433 "Usage:\n"
434 " zint encode data photo ?option value? ...\n"
435 " data: data to encode in the symbol\n"
436 " photo: a tcl photo image handle ('p' after 'image create photo p')\n"
437 " Available options:\n"
438 " -barcode choice: symbology, use 'zint symbology' to get a list\n"
439 " -addongap number: (7..12, default: 9) set add-on gap in multiple of module size (UPC/EAN-CC)\n"
440 " -bg color: set background color as 6 or 8 hex rrggbbaa\n"
441 /* cli option --binary internally handled */
442 " -bind bool: bars above/below the code, size set by -border\n"
443 " -bold bool: use bold text\n"
444 " -border integer: width of a border around the symbol. Use with -bind/-box 1\n"
445 " -box bool: box around bar code, size set be -border\n"
446 /* cli option --cmyk not supported as no corresponding output */
447 " -cols integer: PDF417, Codablock F, DotCode: number of columns\n"
448 /* cli option --data is standard parameter */
449 " -dmre bool: Allow Data Matrix Rectangular Extended\n"
450 " -dotsize number: radius ratio of dots from 0.01 to 1.0\n"
451 " -dotty bool: use dots instead of boxes for matrix codes\n"
452 /* cli option --dump not supported */
453 /* cli option --ecinos not supported */
454 " -eci number: ECI to use\n"
455 /* cli option --esc not supported */
456 " -fg color: set foreground color as 6 or 8 hex rrggbbaa\n"
457 /* replaces cli options --binary and --gs1 */
458 " -format binary|unicode|gs1: input data format. Default:unicode\n"
459 " -fullmultibyte bool: allow multibyte compaction for xQR, HanXin, Gridmatrix\n"
460 /* cli option --gs1 replaced by -format */
461 " -gs1nocheck bool: for gs1, do not check validity of data (allows non-standard symbols)\n"
462 " -gs1parens bool: for gs1, AIs enclosed in parentheses instead of square brackets\n"
463 " -gssep bool: for gs1, use gs as separator instead fnc1 (Datamatrix only)\n"
464 " -height double: Symbol height in modules\n"
465 /* cli option --input not supported */
466 " -init bool: Create reader initialisation symbol (Code 128, Data Matrix)\n"
467 " -mask number: set masking pattern to use (QR/MicroQR/HanXin/DotCode)\n"
468 /* cli option --mirror not supported */
469 " -mode number: set encoding mode (MaxiCode, Composite)\n"
470 " -nobackground bool: set background transparent\n"
471 " -notext bool: no interpretation line\n"
472 /* cli option --output not supported */
473 " -primary text: Structured primary data (MaxiCode, Composite)\n"
474 " -reverse bool: Reverse colours (white on black)\n"
475 " -rotate angle: Image rotation by 0,90 or 270 degrees\n"
476 " -rows integer: Codablock F: number of rows\n"
477 " -scale double: Scale the image to this factor\n"
478 " -scmvv number: Prefix SCM with [)>\\R01\\Gvv (vv is NUMBER) (MaxiCode)\n"
479 " -secure integer: EC Level (PDF417, QR)\n"
480 " -separator 0..4 (default: 1) : Stacked symbologies: separator width\n"
481 /* cli option --small replaced by -smalltext */
482 " -smalltext bool: tiny interpretation line font\n"
483 " -square bool: force Data Matrix symbols to be square\n"
484 /* cli option --types not supported */
485 " -vers integer: Symbology option\n"
486 " -vwhitesp integer: vertical quiet zone in modules\n"
487 " -whitesp integer: horizontal quiet zone in modules\n"
488 " -werror bool: Convert all warnings into errors\n"
489 " -to {x0 y0 ?width? ?height?}: place to put in photo image\n"
490 "\n"
491 "zint symbologies: List available symbologies\n"
492 "zint eci: List available eci tables\n"
493 "zint help\n"
494 "zint version\n"
495 ;
496
497 /*----------------------------------------------------------------------------*/
498 /* Exported symbols */
499 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32)
DllEntryPoint(HINSTANCE hInstance,DWORD seginfo,LPVOID lpCmdLine)500 EXPORT BOOL WINAPI DllEntryPoint (HINSTANCE hInstance,
501 DWORD seginfo, LPVOID lpCmdLine)
502 {
503 /* Don't do anything, so just return true */
504 return TRUE;
505 }
506 #endif
507 /*----------------------------------------------------------------------------*/
508 /* Initialisation Procedures */
Zint_Init(Tcl_Interp * interp)509 EXPORT int Zint_Init (Tcl_Interp *interp)
510 {
511 int * tkFlagPtr;
512 /*------------------------------------------------------------------------*/
513 #ifdef USE_TCL_STUBS
514 if (Tcl_InitStubs(interp, "8.5", 0) == NULL)
515 #else
516 if (Tcl_PkgRequire(interp, "Tcl", "8.5", 0) == NULL)
517 #endif
518 {
519 return TCL_ERROR;
520 }
521 /*------------------------------------------------------------------------*/
522 /* This procedure is called once per thread and any thread local data */
523 /* should be allocated and initialized here (and not in static variables) */
524
525 /* Create a flag if Tk is loaded */
526 tkFlagPtr = (int *)ckalloc(sizeof(int));
527 *tkFlagPtr = 0;
528 Tcl_CallWhenDeleted(interp, InterpCleanupProc, (ClientData)tkFlagPtr);
529 /*------------------------------------------------------------------------*/
530 Tcl_CreateObjCommand(interp, "zint", Zint, (ClientData)tkFlagPtr,
531 (Tcl_CmdDeleteProc *)NULL);
532 Tcl_PkgProvide (interp, "zint", version_string);
533 /*------------------------------------------------------------------------*/
534 return TCL_OK;
535 }
536 /*----------------------------------------------------------------------------*/
537 /* >>>> Cleanup procedure */
538 /*----------------------------------------------------------------------------*/
539 /* This routine is called, if a thread is terminated */
InterpCleanupProc(ClientData clientData,Tcl_Interp * interp)540 static void InterpCleanupProc(ClientData clientData, Tcl_Interp *interp)
541 {
542 ckfree( (char *)clientData );
543 }
544 /*----------------------------------------------------------------------------*/
545 /* >>>> Unload Procedures */
546 /*----------------------------------------------------------------------------*/
Zint_Unload(Tcl_Interp * Interp,int Flags)547 EXPORT int Zint_Unload (Tcl_Interp *Interp, int Flags)
548 {
549 // Allow unload
550 return TCL_OK;
551 }
552 /*----------------------------------------------------------------------------*/
553 /* >>>>> Called routine */
554 /*----------------------------------------------------------------------------*/
555 /* Decode tcl commands */
Zint(ClientData tkFlagPtr,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])556 static int Zint(ClientData tkFlagPtr, Tcl_Interp *interp, int objc,
557 Tcl_Obj *CONST objv[])
558 {
559 /* Option list and indexes */
560 enum iCommand {iEncode, iSymbologies, iECI, iVersion, iHelp};
561 /* choice of option */
562 int Index;
563 /*------------------------------------------------------------------------*/
564 /* > Check if option argument is given and decode it */
565 if (objc > 1)
566 {
567 char *subCmds[] = {"encode", "symbologies", "eci", "version", "help", NULL};
568 if(Tcl_GetIndexFromObj(interp, objv[1], (const char **) subCmds,
569 "option", 0, &Index)
570 == TCL_ERROR)
571 {
572 return TCL_ERROR;
573 }
574 } else {
575 Tcl_WrongNumArgs(interp, 1, objv, "option");
576 return TCL_ERROR;
577 }
578 /*------------------------------------------------------------------------*/
579 /* > Call functions in dependency of Index */
580 /*------------------------------------------------------------------------*/
581 switch (Index)
582 {
583 case iEncode:
584 if (CheckForTk(interp, (int *)tkFlagPtr) != TCL_OK) {
585 return TCL_ERROR;
586 }
587 return Encode(interp, objc, objv);
588 case iSymbologies:
589 {
590 Tcl_Obj *oRes;
591 int posCur;
592 oRes = Tcl_NewObj();
593 for (posCur = 0 ; s_code_list[posCur] != NULL; posCur++) {
594 if( ZBarcode_ValidID(s_code_number[posCur]) != 0) {
595 if (TCL_OK != Tcl_ListObjAppendElement(interp,
596 oRes, Tcl_NewStringObj(s_code_list[posCur],-1)))
597 {
598 return TCL_ERROR;
599 }
600 }
601 }
602 Tcl_SetObjResult(interp,oRes);
603 return TCL_OK;
604 }
605 case iECI:
606 {
607 Tcl_Obj *oRes;
608 int posCur;
609 oRes = Tcl_NewObj();
610 for (posCur = 0 ; s_eci_list[posCur] != NULL; posCur++) {
611 if (TCL_OK != Tcl_ListObjAppendElement(interp,
612 oRes, Tcl_NewStringObj(s_eci_list[posCur],-1)))
613 {
614 return TCL_ERROR;
615 }
616 }
617 Tcl_SetObjResult(interp,oRes);
618 return TCL_OK;
619 }
620 case iVersion:
621 Tcl_SetObjResult(interp,
622 Tcl_NewStringObj(version_string, -1));
623 return TCL_OK;
624 case iHelp:
625 default:
626 Tcl_SetObjResult(interp,
627 Tcl_NewStringObj(help_message, -1));
628 return TCL_OK;
629 }
630 }
631 /*----------------------------------------------------------------------
632 * Check availability of Tk.
633 *----------------------------------------------------------------------
634 */
CheckForTk(Tcl_Interp * interp,int * tkFlagPtr)635 static int CheckForTk(Tcl_Interp *interp, int *tkFlagPtr)
636 {
637 if (*tkFlagPtr > 0) {
638 return TCL_OK;
639 }
640 if (*tkFlagPtr == 0) {
641 if ( ! Tcl_PkgPresent(interp, "Tk", "8.5", 0) ) {
642 Tcl_SetResult(interp, "package Tk not loaded", TCL_STATIC);
643 return TCL_ERROR;
644 }
645 }
646 #ifdef USE_TK_STUBS
647 if (*tkFlagPtr < 0 || Tk_InitStubs(interp, "8.5", 0) == NULL) {
648 *tkFlagPtr = -1;
649 Tcl_SetResult(interp, "error initializing Tk", TCL_STATIC);
650 return TCL_ERROR;
651 }
652 #endif
653 *tkFlagPtr = 1;
654 return TCL_OK;
655 }/*----------------------------------------------------------------------------*/
656 /* >>>>> Encode */
657 /*----------------------------------------------------------------------------*/
658 /* Encode image */
Encode(Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])659 static int Encode(Tcl_Interp *interp, int objc,
660 Tcl_Obj *CONST objv[])
661 {
662 struct zint_symbol *my_symbol;
663 Tcl_DString dsInput;
664 char *pStr = NULL;
665 int lStr;
666 Tcl_Encoding hZINTEncoding;
667 int rotate_angle=0;
668 int fError = 0;
669 Tcl_DString dString;
670 int optionPos;
671 int destX0 = 0;
672 int destY0 = 0;
673 int destWidth = 0;
674 int destHeight = 0;
675 int ECIIndex = 0;
676 int fFullMultiByte = 0;
677 int addon_gap = 0;
678 int Separator = 1;
679 int Mask = 0;
680 unsigned int cap;
681 /*------------------------------------------------------------------------*/
682 /* >> Check if at least data and object is given and a pair number of */
683 /* >> options */
684 if ( objc < 4 || (objc % 2) != 0 )
685 {
686 Tcl_WrongNumArgs(interp, 2, objv, "data photo ?-switch value?...");
687 return TCL_ERROR;
688 }
689 /*------------------------------------------------------------------------*/
690 /* >>> Prepare encoding */
691 hZINTEncoding = Tcl_GetEncoding(interp, "utf-8");
692 if (NULL == hZINTEncoding) {
693 return TCL_ERROR;
694 }
695 /*------------------------------------------------------------------------*/
696 /* >>> Prepare zint object */
697 my_symbol = ZBarcode_Create();
698 my_symbol->input_mode = UNICODE_MODE;
699 my_symbol->option_3 = 0;
700 /*------------------------------------------------------------------------*/
701 /* >> Decode options */
702 for (optionPos = 4; optionPos < objc; optionPos+=2) {
703 /*--------------------------------------------------------------------*/
704 /* Option list and indexes */
705 char *optionList[] = {
706 "-addongap", "-barcode", "-bg", "-bind", "-bold", "-border", "-box",
707 "-cols", "-dmre", "-dotsize", "-dotty", "-eci", "-fg", "-format",
708 "-fullmultibyte", "-gs1nocheck", "-gs1parens", "-gssep", "-height",
709 "-init", "-mask", "-mode",
710 "-nobackground", "-notext", "-primary", "-reverse", "-rotate",
711 "-rows", "-scale", "-scmvv", "-secure", "-separator", "-smalltext",
712 "-square", "-to", "-vers", "-vwhitesp", "-werror", "-whitesp",
713 NULL};
714 enum iOption {
715 iAddonGap, iBarcode, iBG, iBind, iBold, iBorder, iBox,
716 iCols, iDMRE, iDotSize, iDotty, iECI, iFG, iFormat,
717 iFullMultiByte, iGS1NoCheck, iGS1Parens, iGSSep, iHeight,
718 iInit, iMask, iMode,
719 iNoBackground, iNoText, iPrimary, iReverse, iRotate,
720 iRows, iScale, iSCMvv, iSecure, iSeparator, iSmallText,
721 iSquare, iTo, iVers, iVWhiteSp, iWError, iWhiteSp
722 };
723 int optionIndex;
724 int intValue;
725 double doubleValue;
726 /*--------------------------------------------------------------------*/
727 if(Tcl_GetIndexFromObj(interp, objv[optionPos],
728 (const char **) optionList,
729 "zint option", optionPos-1, &optionIndex)
730 == TCL_ERROR)
731 {
732 fError = 1;
733 break;
734 }
735 /*--------------------------------------------------------------------*/
736 /* >> Decode object */
737 switch (optionIndex) {
738 case iBind:
739 case iBold:
740 case iBox:
741 case iDMRE:
742 case iDotty:
743 case iGS1NoCheck:
744 case iGS1Parens:
745 case iGSSep:
746 case iInit:
747 case iNoBackground:
748 case iNoText:
749 case iSmallText:
750 case iSquare:
751 case iFullMultiByte:
752 case iReverse:
753 case iWError:
754 /* >> Binary options */
755 if (TCL_OK != Tcl_GetBooleanFromObj(interp, objv[optionPos+1],
756 &intValue))
757 {
758 fError = 1;
759 }
760 break;
761 case iFG:
762 case iBG:
763 /* >> Colors */
764 pStr = Tcl_GetStringFromObj(objv[optionPos+1],&lStr);
765 if (lStr != 6 && lStr != 8) {
766 Tcl_SetObjResult(interp,
767 Tcl_NewStringObj("Color is not 6 or 8 hex",-1));
768 fError = 1;
769 }
770 break;
771 case iDotSize:
772 case iScale:
773 /* >> Float */
774 if (TCL_OK != Tcl_GetDoubleFromObj(interp, objv[optionPos+1],
775 &doubleValue))
776 {
777 fError = 1;
778 }
779 break;
780 case iAddonGap:
781 case iBorder:
782 case iCols:
783 case iHeight:
784 case iMask:
785 case iMode:
786 case iRotate:
787 case iRows:
788 case iSecure:
789 case iSeparator:
790 case iSCMvv:
791 case iVers:
792 case iVWhiteSp:
793 case iWhiteSp:
794 /* >> Int */
795 if (TCL_OK != Tcl_GetIntFromObj(interp, objv[optionPos+1],
796 &intValue))
797 {
798 fError = 1;
799 }
800 break;
801 case iPrimary:
802 /* > Primary String up to 90 characters */
803 /* > Output filename up to 250 characters */
804 Tcl_DStringInit(& dString);
805 pStr = Tcl_GetStringFromObj(objv[optionPos+1], &lStr);
806 Tcl_UtfToExternalDString( hZINTEncoding, pStr, lStr, &dString);
807 if (Tcl_DStringLength(&dString) > (optionIndex==iPrimary?90:250)) {
808 Tcl_DStringFree(&dString);
809 Tcl_SetObjResult(interp,Tcl_NewStringObj("String to long", -1));
810 fError = 1;
811 }
812 break;
813 }
814 if (fError) {
815 break;
816 }
817 /*--------------------------------------------------------------------*/
818 switch (optionIndex) {
819 case iAddonGap:
820 if (intValue < 7 || intValue > 12) {
821 Tcl_SetObjResult(interp,
822 Tcl_NewStringObj("Invalid add-on gap value not within 7 to 12", -1));
823 fError = 1;
824 } else {
825 addon_gap = intValue;
826 }
827 break;
828 case iBind:
829 if (intValue) {
830 my_symbol->output_options |= BARCODE_BIND;
831 } else {
832 my_symbol->output_options &= ~BARCODE_BIND;
833 }
834 break;
835 case iBold:
836 if (intValue) {
837 my_symbol->output_options |= BOLD_TEXT;
838 } else {
839 my_symbol->output_options &= ~BOLD_TEXT;
840 }
841 break;
842 case iBox:
843 if (intValue) {
844 my_symbol->output_options |= BARCODE_BOX;
845 } else {
846 my_symbol->output_options &= ~BARCODE_BOX;
847 }
848 break;
849 case iDotSize:
850 if (doubleValue < 0.01) {
851 Tcl_SetObjResult(interp,
852 Tcl_NewStringObj("Dot size below 0.01", -1));
853 fError = 1;
854 } else {
855 my_symbol->dot_size = (float)doubleValue;
856 }
857 break;
858 case iDotty:
859 if (intValue) {
860 my_symbol->output_options |= BARCODE_DOTTY_MODE;
861 } else {
862 my_symbol->output_options &= ~BARCODE_DOTTY_MODE;
863 }
864 break;
865 case iGS1NoCheck:
866 if (intValue) {
867 my_symbol->input_mode |= GS1NOCHECK_MODE;
868 } else {
869 my_symbol->input_mode &= ~GS1NOCHECK_MODE;
870 }
871 break;
872 case iGS1Parens:
873 if (intValue) {
874 my_symbol->input_mode |= GS1PARENS_MODE;
875 } else {
876 my_symbol->input_mode &= ~GS1PARENS_MODE;
877 }
878 break;
879 case iGSSep:
880 if (intValue) {
881 my_symbol->output_options |= GS1_GS_SEPARATOR;
882 } else {
883 my_symbol->output_options &= ~GS1_GS_SEPARATOR;
884 }
885 break;
886 case iFullMultiByte:
887 fFullMultiByte = intValue;
888 break;
889 case iECI:
890 if(Tcl_GetIndexFromObj(interp, objv[optionPos+1],
891 (const char **) s_eci_list,"-eci", optionPos, &ECIIndex)
892 == TCL_ERROR)
893 {
894 fError = 1;
895 } else {
896 my_symbol->eci = s_eci_number[ECIIndex];
897 }
898 break;
899 case iInit:
900 if (intValue) {
901 my_symbol->output_options |= READER_INIT;
902 } else {
903 my_symbol->output_options &= ~READER_INIT;
904 }
905 break;
906 case iSmallText:
907 if (intValue) {
908 my_symbol->output_options |= SMALL_TEXT;
909 } else {
910 my_symbol->output_options &= ~SMALL_TEXT;
911 }
912 break;
913 case iReverse:
914 if (intValue) {
915 strcpy(my_symbol->fgcolour, "ffffff");
916 strcpy(my_symbol->bgcolour, "000000");
917 }
918 break;
919 case iWError:
920 if (intValue) {
921 my_symbol->warn_level = WARN_FAIL_ALL;
922 }
923 break;
924 case iFG:
925 strncpy(my_symbol->fgcolour, pStr, lStr);
926 my_symbol->fgcolour[lStr]='\0';
927 break;
928 case iBG:
929 strncpy(my_symbol->bgcolour, pStr, lStr);
930 my_symbol->bgcolour[lStr]='\0';
931 break;
932 case iNoBackground:
933 if (intValue) {
934 strcpy(my_symbol->bgcolour, "ffffff00");
935 }
936 break;
937 case iNoText:
938 my_symbol->show_hrt = (intValue?0:1);
939 break;
940 case iSquare:
941 /* DM_SQUARE overwrites DM_DMRE */
942 if (intValue)
943 my_symbol->option_3 = DM_SQUARE;
944 break;
945 case iDMRE:
946 /* DM_DMRE overwrites DM_SQUARE */
947 if (intValue)
948 my_symbol->option_3 = DM_DMRE;
949 break;
950 case iScale:
951 if (doubleValue < 0.01) {
952 Tcl_SetObjResult(interp,
953 Tcl_NewStringObj("Scale below 0.01", -1));
954 fError = 1;
955 } else {
956 my_symbol->scale = (float)doubleValue;
957 }
958 break;
959 case iBorder:
960 if (intValue < 0 || intValue > 1000) {
961 Tcl_SetObjResult(interp,
962 Tcl_NewStringObj("Border out of range", -1));
963 fError = 1;
964 } else {
965 my_symbol->border_width = intValue;
966 }
967 break;
968 case iHeight:
969 if ((float)doubleValue < 0.5f || (float)doubleValue > 1000.0f) {
970 Tcl_SetObjResult(interp,
971 Tcl_NewStringObj("Height out of range", -1));
972 fError = 1;
973 } else {
974 my_symbol->height = (float)doubleValue;
975 }
976 break;
977 case iSeparator:
978 if (intValue < 0 || intValue > 4) {
979 Tcl_SetObjResult(interp,
980 Tcl_NewStringObj("Separator out of range", -1));
981 fError = 1;
982 } else {
983 Separator = intValue;
984 }
985 break;
986 case iMask:
987 if (intValue < 0 || intValue > 7) {
988 Tcl_SetObjResult(interp,
989 Tcl_NewStringObj("Mask out of range", -1));
990 fError = 1;
991 } else {
992 Mask = intValue + 1;
993 }
994 break;
995 case iSCMvv:
996 if (intValue < 0 || intValue > 99) {
997 Tcl_SetObjResult(interp,
998 Tcl_NewStringObj("SCM version out of range", -1));
999 fError = 1;
1000 } else {
1001 my_symbol->option_2 = intValue + 1;
1002 }
1003 break;
1004 case iCols:
1005 case iVers:
1006 /* >> Int in Option 2 */
1007 if (intValue < 1
1008 || (optionIndex==iCols && intValue > 200)
1009 || (optionIndex==iVers && intValue > 47))
1010 {
1011 Tcl_SetObjResult(interp,
1012 Tcl_NewStringObj("cols/vers out of range", -1));
1013 fError = 1;
1014 } else {
1015 my_symbol->option_2 = intValue;
1016 }
1017 break;
1018 case iSecure:
1019 case iMode:
1020 case iRows:
1021 /* >> Int in Option 1 */
1022 if ( (optionIndex==iSecure && (intValue < 1 || intValue > 8))
1023 || (optionIndex==iMode && (intValue < 0 || intValue > 6))
1024 || (optionIndex==iRows && (intValue < 0 || intValue > 44)))
1025 {
1026 Tcl_SetObjResult(interp,
1027 Tcl_NewStringObj("secure/mode/rows out of range", -1));
1028 fError = 1;
1029 } else {
1030 my_symbol->option_1 = intValue;
1031 }
1032 break;
1033 case iPrimary:
1034 strcpy(my_symbol->primary, Tcl_DStringValue( &dString ) );
1035 Tcl_DStringFree(&dString);
1036 break;
1037 case iRotate:
1038 /* >> Rotate angle */
1039 /*----------------------------------------------------------------*/
1040 {
1041 char *rotateList[] = {"0", "90", "180", "270", NULL};
1042 enum iRotate { iRotate0, iRotate90, iRotate180, iRotate270 };
1043 /*------------------------------------------------------------*/
1044 if(Tcl_GetIndexFromObj(interp, objv[optionPos+1],
1045 (const char **) rotateList,
1046 "rotate", optionPos, &intValue)
1047 == TCL_ERROR)
1048 {
1049 fError = 1;
1050 break;
1051 }
1052 switch (intValue) {
1053 case iRotate90: rotate_angle = 90; break;
1054 case iRotate180: rotate_angle = 180; break;
1055 case iRotate270: rotate_angle = 270; break;
1056 default: rotate_angle = 0; break;
1057 }
1058 }
1059 break;
1060 case iBarcode:
1061 if(Tcl_GetIndexFromObj(interp, objv[optionPos+1],
1062 (const char **) s_code_list,"-barcode", optionPos, &intValue)
1063 == TCL_ERROR)
1064 {
1065 fError = 1;
1066 } else {
1067 my_symbol->symbology = s_code_number[intValue];
1068 }
1069 break;
1070 case iVWhiteSp:
1071 my_symbol->whitespace_height = intValue;
1072 break;
1073 case iWhiteSp:
1074 my_symbol->whitespace_width = intValue;
1075 break;
1076 case iTo:
1077 /* >> Decode the -to parameter as list of X0 Y0 ?Width Height? */
1078 {
1079 Tcl_Obj *poParam;
1080 if (TCL_OK != Tcl_ListObjLength(interp,
1081 objv[optionPos+1], &lStr))
1082 {
1083 fError = 1;
1084 } else if ( ! ( lStr == 2 || lStr == 4 ) ) {
1085 Tcl_SetObjResult(interp,
1086 Tcl_NewStringObj(
1087 "option -to not a list of 2 or 4", -1));
1088 fError = 1;
1089 } else if ((
1090 TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1091 0, &poParam)
1092 || TCL_OK != Tcl_GetIntFromObj(interp,poParam,&destX0)
1093 || TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1094 1, &poParam)
1095 || TCL_OK != Tcl_GetIntFromObj(interp,poParam,&destY0)
1096 || lStr == 4) && (
1097 TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1098 2, &poParam)
1099 || TCL_OK != Tcl_GetIntFromObj(interp,poParam,
1100 &destWidth)
1101 || TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1],
1102 3, &poParam)
1103 || TCL_OK != Tcl_GetIntFromObj(interp,poParam,
1104 &destHeight)
1105 ))
1106 {
1107 fError = 1;
1108 }
1109 }
1110 break;
1111 case iFormat:
1112 /* >> Format of the input data */
1113 /*----------------------------------------------------------------*/
1114 {
1115 char *formatList[] = {"binary", "gs1", "unicode",NULL};
1116 enum iFormat { iBinary, iGS1, iUnicode };
1117 /*------------------------------------------------------------*/
1118 if(Tcl_GetIndexFromObj(interp, objv[optionPos+1],
1119 (const char **) formatList,
1120 "format", optionPos, &intValue)
1121 == TCL_ERROR)
1122 {
1123 fError = 1;
1124 break;
1125 }
1126 switch (intValue) {
1127 case iBinary: my_symbol->input_mode = (my_symbol->input_mode & ~0x07) | DATA_MODE; break;
1128 case iGS1: my_symbol->input_mode = (my_symbol->input_mode & ~0x07) | GS1_MODE; break;
1129 default: my_symbol->input_mode = (my_symbol->input_mode & ~0x07) | UNICODE_MODE; break;
1130 }
1131 }
1132 }
1133 }
1134 /*------------------------------------------------------------------------*/
1135 /* >>> Get symbology capability mask */
1136 cap = ZBarcode_Cap(my_symbol->symbology,
1137 ZINT_CAP_STACKABLE | ZINT_CAP_EXTENDABLE | ZINT_CAP_FULL_MULTIBYTE
1138 | ZINT_CAP_MASK);
1139 /*------------------------------------------------------------------------*/
1140 /* >>> option_3 is set by three values depending on the symbology */
1141 /* On wrong symbology, the option is ignored(as does the zint program)*/
1142 if (fFullMultiByte && (cap & ZINT_CAP_FULL_MULTIBYTE)) {
1143 my_symbol->option_3 = ZINT_FULL_MULTIBYTE;
1144 }
1145 if (Mask && (cap & ZINT_CAP_MASK)) {
1146 my_symbol->option_3 |= Mask << 8;
1147 }
1148 if (Separator && (cap & ZINT_CAP_STACKABLE)) {
1149 my_symbol->option_3 = Separator;
1150 }
1151 /*------------------------------------------------------------------------*/
1152 /* >>> option_2 is set by two values depending on the symbology */
1153 /* On wrong symbology, the option is ignored(as does the zint program)*/
1154 if (addon_gap && (cap & ZINT_CAP_EXTENDABLE)) {
1155 my_symbol->option_2 = addon_gap;
1156 }
1157 /*------------------------------------------------------------------------*/
1158 /* >>> Prepare input dstring and encode it to ECI encoding*/
1159 Tcl_DStringInit(& dsInput);
1160 /*------------------------------------------------------------------------*/
1161 if (!fError) {
1162 /*--------------------------------------------------------------------*/
1163 /* >>> Get input mode */
1164 if ((my_symbol->input_mode & 0x07) == DATA_MODE) {
1165 /* Binary data */
1166 pStr = (char *) Tcl_GetByteArrayFromObj(objv[2], &lStr);
1167 } else {
1168 /* UTF8 Data */
1169 pStr = Tcl_GetStringFromObj(objv[2], &lStr);
1170 Tcl_UtfToExternalDString( hZINTEncoding, pStr, lStr, &dsInput);
1171 pStr = Tcl_DStringValue( &dsInput );
1172 lStr = Tcl_DStringLength( &dsInput );
1173 }
1174 }
1175 /*------------------------------------------------------------------------*/
1176 /* >>> Build symbol graphic */
1177 if (! fError ) {
1178 int ErrorNumber;
1179 Tk_PhotoHandle hPhoto;
1180 /*--------------------------------------------------------------------*/
1181 /* call zint graphic creation to buffer */
1182 ErrorNumber = ZBarcode_Encode_and_Buffer(my_symbol,
1183 (unsigned char *) pStr, lStr, rotate_angle);
1184 /*--------------------------------------------------------------------*/
1185 /* >> Show a message */
1186 if( 0 != ErrorNumber )
1187 {
1188 Tcl_SetObjResult(interp, Tcl_NewStringObj(my_symbol->errtxt, -1));
1189 }
1190 if( ZINT_ERROR <= ErrorNumber )
1191 {
1192 /* >> Encode error */
1193 fError = 1;
1194 } else if (
1195 NULL == (hPhoto = Tk_FindPhoto(interp, Tcl_GetString(objv[3]))))
1196 {
1197 Tcl_SetObjResult(interp,
1198 Tcl_NewStringObj("Unknown photo image", -1));
1199 fError = 1;
1200 } else {
1201 Tk_PhotoImageBlock sImageBlock;
1202 char * pImageRGBA = NULL;
1203 if (my_symbol->alphamap == NULL) {
1204 sImageBlock.pixelPtr = (unsigned char *) my_symbol->bitmap;
1205 sImageBlock.width = my_symbol->bitmap_width;
1206 sImageBlock.height = my_symbol->bitmap_height;
1207 sImageBlock.pitch = 3*my_symbol->bitmap_width;
1208 sImageBlock.pixelSize = 3;
1209 sImageBlock.offset[0] = 0;
1210 sImageBlock.offset[1] = 1;
1211 sImageBlock.offset[2] = 2;
1212 sImageBlock.offset[3] = 0;
1213 } else {
1214 int index;
1215 /* Alpha channel present - prepare the image data in rgba order */
1216 pImageRGBA = ckalloc(my_symbol->bitmap_width*my_symbol->bitmap_height*4);
1217 for (index = 0; index < my_symbol->bitmap_width*my_symbol->bitmap_height; index++) {
1218 pImageRGBA[index*4] = my_symbol->bitmap[index*3];
1219 pImageRGBA[index*4+1] = my_symbol->bitmap[index*3+1];
1220 pImageRGBA[index*4+2] = my_symbol->bitmap[index*3+2];
1221 pImageRGBA[index*4+3] = my_symbol->alphamap[index];
1222 }
1223 sImageBlock.pixelPtr = (unsigned char *) pImageRGBA;
1224 sImageBlock.width = my_symbol->bitmap_width;
1225 sImageBlock.height = my_symbol->bitmap_height;
1226 sImageBlock.pitch = 4*my_symbol->bitmap_width;
1227 sImageBlock.pixelSize = 4;
1228 sImageBlock.offset[0] = 0;
1229 sImageBlock.offset[1] = 1;
1230 sImageBlock.offset[2] = 2;
1231 sImageBlock.offset[3] = 3;
1232 }
1233 if (0 == destWidth) {
1234 destWidth = my_symbol->bitmap_width;
1235 }
1236 if (0 == destHeight) {
1237 destHeight = my_symbol->bitmap_height;
1238 }
1239 if (TCL_OK != Tk_PhotoPutBlock(interp, hPhoto, &sImageBlock,
1240 destX0, destY0, destWidth, destHeight,
1241 TK_PHOTO_COMPOSITE_OVERLAY))
1242 {
1243 fError = 1;
1244 }
1245 if (pImageRGBA != NULL) {
1246 ckfree(pImageRGBA);
1247 }
1248 }
1249 }
1250 /*------------------------------------------------------------------------*/
1251 Tcl_FreeEncoding(hZINTEncoding);
1252 Tcl_DStringFree(& dsInput);
1253 ZBarcode_Delete(my_symbol);
1254 /*------------------------------------------------------------------------*/
1255 if (fError) {
1256 return TCL_ERROR;
1257 }
1258 return TCL_OK;
1259 }
1260