zint.c 61 KB

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