From a818144eedc913ba5f7c89d0c6a8357906a884b8 Mon Sep 17 00:00:00 2001
From: Ben Hosmer
B$;HJE<9&thsu7#0{fa-`cr3%6O&@xT}H2Tl%9Tvw@!$ zlA&;OQPp=gmwU5T<1F$+8{t|fGiHgWw*WUnKNN(8-e_#+)-^F)d+TaB# z8m+U)4UZwusdiUKCjQ+r-wbbbW@bdgzWC6$bw>Frpa$PR!4}oWvi)#Je*}hT0U61b z&ZytLEUI@`#Q6paNVBRJv~~)nEA`pPI6juUr9{nc );37ic*zro%OBm`j+la7*$u7P(v!n;}}o%4Uchm+TxD^mWxU}5@#o6qr2cj4hoz# zaNw>efxl6)M* MDSn>z`K z2zdl5PY^?(d3;pr+d8j5yN*~uCgg%@fpQbXjMn(B(vT20S}UAS(i(W?r`1y@tDT!A z?)uivWF*`Z4@A)NsZm5&m@m{ow?Wp4JiBZ9-A)c9T9D_>$9SH|@_Zt;o840fHoIFp zON6UIgRHULM&7MO^|-#RA~OS&S;a9ozNh6FkMC*i?tGDhsrH_>&Sxo1RYoehjwM4~ z=Zj8+c%hUcrKFHt;v^^JNz>s(B3y5Kkw<7msAYr#;e5^sjD)iIMNo#(oD)>MjGMfU zf-)vv#tUU#@Pkn@&j*GC#a`_kAmej;*Zj?qF2du;2o!;TIEvk6Kpl74F-(aRQJH&g zMO5ytAmt%a9*UQXNV(Wu5yeKFnQ_}@uG;;rITJzOIO+HFxMSNtAN?n__8&O%cYI>} zzj@zZ6 OUGfN;e(tJ34ff=8r<@;TE&QvA=IWb>SgQ`}SeSKD>S3fqm5QzV-Vk z_Qd#Kc*{Piyyobhm-kS#Z#Q=A#*gkkx|_OvHx_C)?1ozZ{h|At?x*?t73v!Q4*cj2 zyzy?cgTKA`c8ca!I9Ft^ps5x3?<=ru2#*ipr-tyJA$;@Dh9Rnc2+Nk@@um2wrFhR$ zT)z~Htk~Rc(TzLA%(z1YeGkpUj(Prhp?Tx;7=EyM@W5bnkO|Gj>bXbfQtW|&3j-8Q zI@vTJlGXJ0`5ckHT1Q`VlH;E<@fS03+swOWQd4K*;+gn|Zv1sOUet~2yK!+h7U_c8 zb{0s-1nG7Mjn#CBK1$Q-8IBqL88mt3a~)bk&57{~&vl69us{7=n{a-bU(zO$*GzBr zIYP}%&3(=E JJV3Fe&aEM#C#$|C2g$4mEJ^@bC&mE{j*gDg0Kz9V?)~ zNA4UZ7s5H53VQ^9u@Cu%SKwjt*9W^{pAY_FAKZ(4=3bE=$x$PCx+ZipJIcNd?0?;l zsY7}M7{>S)r109`m_ByhRsa7F<5&SYj7HHZcpCVE!mk~zM|;qtXbt%JN8rEZ@E`e| zM6bg}eg~oUUg790It$mW5soMSMA3@~5D@r1gr0zY#I5Cc?e6$a_`3itMcdJFFqJ3Y zjL;w&0&iqDI*rZ)*TjD@JO$po3dKNU2&l$&&zL;?3J!Lod!V(u(I%`wyRjL32RqtH zb)!3J^42HgEv9ZozeC5d3?aN8EdlmBAUt9T+ `)}tZn8KFM@rv|OU2%n_tXo^mu zJLtRVQ}kaLCsWAW#N5w(!X~mS*uRTvL`TF);yUp+l0nH!(j;lG^nmpDvSzteez!cP zn5EdS_&}Mgyi<8Xc}114x=VFXZB{Q-zs6~~+qthaotk}`|I}t^|ER0b?bN-g`%16U z2lUPQ`TF||lwrVd$S5<;H~z+S!1PD6-W)MU&A+mgSZ=etW=*l)V|~X~X4`4|AR#N^ z_x7ds|4d9t97#OrK#n%}Z@&{cZ*i$yce `Xc7WxN&M+r6)NFQ- U?8|R z7!Cd^7v(nR?#(@(`(Eyqywto|c_;Gq`FG^MlK)*nMnPS{PVhz_82=OA0a8kXoKATW z;qgnnPNolYmJ!Q#%K-~RtM(Cmi>PFoSQcim^dTKZqmcjGcd*|V^m7*jJvrGv?52Zs zZW$E}BvJ;wigG7qQMmcm;K!HrNm(|lKS{4o@>^|LNqYPUW4`=iN}fxtcIBmb@{%|% zDUa|9g*MPnP|pf&5u*a$&FmG6rSC~ENGZQ`NV--^qrHgc=nM2EnxRD$C8nVr!Jt2g z{XG|ZdbCCUi#getcGE7{a9!GP8kL!LQyM!uc8TK1M&1D^9`ilC!-gE_LB5lwtyZ%! z(Jp30CX>j5FvGCN%x0Itksx8Ddc9Vyk~6wvvSto*oI)XOmSI@}4lA+ph(f|B9Edxj zu^2QVO_Szh4Xw~9G^|M{lCj7i3 z1(@IKoSp|~P)M1y$<=|DCu)~qq?80i7!$nD4xw>JAN+J@m5;6hHlwk=1E(-cJ zghu|}9zq+Ra00~B0%?L87+zn`Mc}j#pn7@WqNa#YuqW69oCp5_v4G#i26rB?oHs9# z4r;RKJYdCwyr3Zwo5Wezt4XBAxlpSq!&sk4nKUX)|1Qw8p>1 2nHAOhYJxp8V_HpWMNU^MeyQfBwgSbUKayn!}vSs=?1D zR 5d(iG*PVEQPH|6>?+7i(Z;r@W>Y^;F7l^n@N%w;@HvYH$G;E- z* JyI#o_8NlEmxOg_PFeMbez*W_1St_9}<hi|=< LQ3jVmNis5$ zoM9Ypw}-hTXA+fEUY?_EX)+4;s%uM%Ste(yLEW5#{1-zYb?`4lc!`jVd!q-AdV4Nv zpj;4I?jm@bWib!lt>a?L+M@eQvpm%d;>-w45fwm fwX?f*dY`FMjPGs@zjSGG;T*_>Po>h9>WqeIqa%qO8>&K&})O-it;|hh_ z3-f1|Ctqs3ZJ;APdD@IQMfEGe&}>~<&oAj|N{-!YFR5zuR}9T=Pm6tcII}j#mN#z~ z2s7wiOo&gTbUxuU`yP9NrTy#>OI@#UDN0bc0=;@b c~YOQv$x z{NvMeJ!fKpZ&rTs$KUpLzjN^tksFLk;rS-v`3bxVo-e-?g;Im+d-ezN0`3nz7s(q0 zec&boMtOsYG-XPzU*34AdSN(u`_{va%j@9{w_m#WPIvEb|M GMub`>pAIYd|lP%a7u{5=>r nS|KM2p){>i{P4sGea1REe!D^5ko;7MUK*VGpEEN z=^^@Sgq cY~y)~^xfY#4L=K2-r0 zCyflelwx^!J$ey?jKSl$cVM{lT!!iR5`O>5Cxx~N_6E8PJd(%TMhx2x2Mn~vfMvT+ zqxTS%i>lB7S^;=HG;tK{4a7dA7TV_P>G_g0tYAWOO&S>w+-P46-Dp~1@H7zhnZVzP z;Gh#VD+LpVLo5XNz>?A6U}3;t7|h8gN{{+%?80-DiyfWRM--Yp{skieeWU|zox&Ru zhfo@qhV?^EFb3SiYO!UQwSW>1kv Z4<^|9)j~@D*%6b_|=( z49-0h`|oFWU)WV&xAWqj-4}M&)$P1M#{606<5}n<2XuAuTCBz@6 >%j7%XrO zJ28(L5mu^2$PD80Heur)GO=ocKv$PrLj+SrtFadcsk2c`(^zA*B^q`{@Y>z<4&Utl zt|YD1Y}4Ml8eBi}&ItG)mtY=qqY~cfmJHc!9?pZ4hOi53G)|1MB#BcF8^u)83h-4z z7XzV-U=sn6g!%qUu#Ef{f$C{E50vJFdKG)i=xe$ZjG#+bmf_y|TUs-cLLGU14^|JR z&RTd&dE}wR#d$sJ>SLc#$M)kjEq9NsYbfpxIj5DZOb%t)^5^cD*}iYr?v~hj!2<+7 z9sh#<3ffwPdU&}j+m)@g4oSU3gwOa?y(x^4wAfjUo3vOfat=T3!neAx+=V4Bm%*Pg zoF_I6YgI7FK^SG|L!5M^E5PIdzmLooWZsxiK45pm`7;F!5*YmWnEP lO3hc zWVNoSJ$9n}u3v3la;AO8uX|?QJtHk|_SUWq8(QvY&q%JARk-Nqb+b}>maeH;{PU%S zOl0b+&LV}#`23E@ffamG=Ao=WYTe?>s{T;op47U*(%k7qiIw?l9QkSH{QeDK^P0fs z4Y4ml Yc8_krtkHxH1WL|+;mePnt6k!z7T~I@U z;VM|!V0{Ilz%STdZjD>x%EMr$xdaAslc|phosW+7P<~6hu7#l1h;4plhS0b2*!ic1}lfZEF z>WHabhAG#ar`Lw7?tXnFIA`W`z@%r-NpHHnBP;r(Efgv;bQe(1j(y>EE}+*HEIzQ{ zrqMepWx7QDVN1n*BW!oNBB4vuG=o7IXk&5((Ld!vK$bjd3VBr<;&YY!+q;jqt zn~H}Z83Q>%`Q+bhw~I4|y%ug*Ozb$pA`#R`0Gb{Ee+H&YhRB1-kOlfg#fXE~ hOmpbHZL% z#hi-Dp+=u)>QZX?g7;oNcxyGqirI%03SZ;m^*fuBLz&j%n;u_y)9Bishzky_nXz zc1F!mW4gaSl3lrBVWlu`kTJoCVBAE=cT5Blb&1zN_c1HsB$#5U6?9zV2vZq|3z%9& z*@BA!a|6Z}DmbR1509N^xhHm9{t&3L5a@ &Dyhm! zlsT-o6c0nX%LK7|dd`3rEQ)I-q7OOH;2_d)q%9&+eT{p>iD2}_U0cDwh#P+Nbz0qz zRTw9U1k;9Sv=l0@ZP)UO)S5`)l%W}UmA5`Mxb*3pOEVkhPs!;Bc`9$(b=FxmKU}jY zoa~)C7)rcj1REEwahJ^qX19lu?_l4~=)9}5a`BAn1V=;PEmLRhnqQbd_x@S+t0Hv? zj;Y;CDrT(j%=qz%ysnVjT|TQYw=K*&R3#75Z42iXP3MDVV{S!T{@jIx7YR)n;Kejl z3Nu7vkzojhI55hVDmbUpNjY II`K31tOY={Vq7#e krx zR{ 3&6nissB*ca}HEL_~i2!RCzRz~ns0%+W5W)R&rIW3V+|BKo2znLNQ4sV`IrE=wY zJ-Gz($b~T>cG?bTuL5*IKkw&~Mv}HC9Y|tKyH6|MQ&I!U6-ugEiK~>jScx4 ^Ot{HI&4{5o$AxAngVagFbNPfgzy=v0^3r_PB6HjwvPp-H5s4s8q1<~7s=qs>g zKLYu0 zD)k40*bK+Sc=Ui}V31;lx-vlTA9GP3e}$hM#1{|5cE(-;`VHcf3 G#ozEn&} zdARrugnx $8{7?$>kWNpg}#HUz%m%qXh^hHL}e4tf%@P3 z4%6&U`mU3b&f`Jq!kCl17H`89c=3UlV=&eUefNz2iS~dz6a1izcLnyPrh022XHQ;} zQ0gzmdbvrBFnBDP4;ARR783&^9rS-nAQr&_gLx6uFccBUOweZ6TVTXq6<|EEinil_ z;TMbATM@{v@);6~+6!BE*MwS5_4j~ovgJ4D=T@Yset9Dc;YU10vzn)+r&U%r 3^X4N@u5yr#OpBOwO(xU z*3@`SbYqSaMqwep5Et`}xG_U9Q!CaEB&f9x?aNx2coMK!o1jhL^IK`YdMdzjXF_KL z7r(csw}(3eP}3Q~v^fLw?ea6=|N8;5g9`49V9Uid-VK`0M5}NDSa{cTojZw%d$dIP z6&Q%=pA5=BSDT+43@}EmfU}fQAuLSdlxUsKQ`FEuC39-7OT=jNYrFEMt(@*F9(rVU zX7}`JlL=!(lFyV?<2QHgeSh^+vDne>rU(D@K |-uYbYvsVXi`4AVJ*^fmp zFT7%y+g{KZurjKIY3X%yLkZM}WowrAhtm=RwquS^&`i sP*NL#*Gwo0@<3 9k=GfIw_v`G -bHM9h`QXzZU)#_q>^9{m1D-|H23oVfX|$AF0y)aNh8KL2Ge zJ38z6*f*p1pWj^h<0ed!u7P&IEA&h7emSb(Q}hxnkzfYRQ;KBWct9cTYZ76#=%|PS zs9VPNQM9ZN$D0E*>LpVQVF&Kd#1;mMrC|ZoA;6A{erZff{d4S9$~5*lRmzSYjFmh# z_We)ZDMib84ZKiI<8c~~(A!}~6(ZbxA(%8YEmzC^@@?{?az-pd&>oqzPfgkr5)FyQ zMT|tmTkT;H&l$piX_3|uVG9wy^!ctfP7pX4)a6htzym_-3@*Ix F IL@_T&6C!b{`f*lIis?a(1VpYX8(M-0mhl;42W-3q{Y6`X<+ zE0nYt#tq 6gBRpv(@ED*4d^R)MD}1qLQ-R I$)rU=f+aA2`890fRtna9q>O1GRmc`JVH z{ju+ fI;y*3C`#G>*bk6ZeGWTj|#{r-HirB0Fd+%dIK5YRpdoE*#Iqo#GXA# z1oZNyC*t}* gPcjf! zmBh+fR5vxWrRd6TcJ#+i=E=)-^vc}3OKYe8NX7ffs-T}H)WWB!Qo+tQfV^0u7QD@Z z5vX9w3&ToFyJZ7rBgKi#VM ua92zXh&$Z?TaWKUT9=0aP zs{UgvC*IWa)Nf#JC&=Ux=H#@7^81Re0IvIELqnajva-xdI|-jrWL{&JPvEt=yfYEz zhP2aZ_~kUbEDih9`qC) ANu*%4>vSC za_Q#}{q;c0kMHL$di TeRr)*k7OC z^x=aoEf0RUY4d;WX=&N>U-32**$4t%Rlq?te1>6WDk?-IKs(R&t_|}7lZe#fZpnaE z9my8)B1$9@TOv{#)>eS-Ci6&qQi*dykI)Mhnc`sR!OECGAya&q2^QS(?%v%e@xr@b zxuayPab3@rnOO&q9AIQKpIkR>3_#?fB?n^joVCka?jw02K+o80fu44h0}+L!RG??@ zbP&HB#LFN!8|({Gi8J+sfy_P& AqdVHI@Z=Lr{ zP?M(p-^jfFkI&zg(z~tXzNv4lrKtZ~dLICKt6_D(oqUH>ZBbJ{0K6!XtHWxARDs0` zY@8_(o5d7lA*k@@svlI8iqxu C5Rki?<9!g!!Y0C0a)aa z(=xvR-}hncXP+MIzN5uMfVczHtg(aa=sWMvxU;8BKen8j^@zKAUUhhYx5Kz$G#~KP zw_r{Vf{o%O0IH@N&C7c^Z#<8R Iw!!^`G`FMIuPbgV>cGm-;m{~g#rsy)h!<|Yx+bw1@QnN zW()LRffn-|O-ZE;ir{6CfqDrukWG4;H-fzm42e~K)mqidDq6*h zq+yo$SjQPyMj<5$kTOje_Lq1WR6!_AivX-36Kc>0nwfZ8K4Cfqs>DGF82un{We|h> zmf-^W^*3UsU&bu2W3N43qt0@~gJoCxXFgR|_f)^YdoWI-7_>7TeLTuZz^~u{x&Quo zI8ckBo!|3XIK+t5Afuh^> +13TrRVy{(dTU$Lk*}^coew+Io`` zGVq=(T(+P$C8c}Lyd3%_n1Bxj7yAoxg9ZL&`B%WpyRtEB&g_{fp4p3sawd2p0<@N+ zb-Z0F<76^a09J&g5P)(Dpe=-#p%KV8q=jggp1_`9X(`o8f+?<5GO)k~DDfPuWfWX- zj!C7k7odB{fP$h4dslF_fi3|OD!t~76VM8*F5nk4loO*1f~ZpBi-XM-ITw2b`U*aG z_ZzqYH@*~`Nv$5+KwY6uj=fL$#~KJb$9cK{+Al%Fyya^Ms`64rSn{+O?-gTSjBR2J zJOdEICEhO Id z?mY0aLh>g0qjE+fVHi9p6El5~1t5ugdXQWK8uZTre*j>nKLgR?aZVxR;i6+#+NiT* z)9CeMQ>YJjFl(RK@#DJqdk#X5LlL}33|=jucK;Cljl^!F_%w(&`z`go=vxfQ4imBF zFTrR6qt0ajr-LerEyBA#{y26@ba~fhu(&bkCq#V?&!Um*1qzHw%p!0mE*&RpsX*ZU zkjnwaa fE7RN|YT|SWk?< z$0sT^VJipxYPBjlf)-=5J$*XI*}3FqN^C?15 zEary*h7}TwATS)qUo{?>9!fD_um-)6ws<72ipEH&dPRHoXJ4GK7qsNIZmZzyMh6CW z^=HTYrSltn+q!R?>g?Z}S)Q) 8cM8c0&sFNbkNSB_&Jt^%h5_6`K^E z4WktNB&I3TB9`Vw-p_dt-dMFEs#ockGm-;HN{<$Vc8R$ zzkk8phZhz6*Kgi?2ReaCtd$;uv2s8Tli99x^|{u%D9(kAVYb7mYmsr57G#{@SK`G9 zxITL|d^LeJfC&SWGJ&lyHGOXM&bo#T&ki>33gnv#OQu*K-o9gJ%liEM)%wt;^SdAZ za8p^5WuHu^mcI4dbFX?VkJ%IB^dxa#N}y*p%H{1T$X1)!9^e8vD=hEGaTpSiui40P z&SorvCJFXdoR*V(;kn8d@u-uD_(B+bA&r~xM8O275VmNO7>lPxN_zG!Eh$;LuLnq4 zVgwJKVn!c`z0t6s+(Au{^MRz&EbCQ@W=wG=IjjX7KK{cO>$7^d_NK+D`TpC$_k@-g zftHC7U8v+!-C+wiBke*O9!kSW8lY#YrrDO{OQO_CSd^5ccQng5{Umh-d~3oLA+{rl zVP7M2B4x*}ct!+)25CrxZ~@m-k)@;S!xgK3F?Y@*ON+-E*a!CnXS6hUQ>V4eh}^V6 zj=!)Kb?WQx`}d9ae6XvrcHQ$!m!BDx>FnCabO~As{o(#yRm+<*1U>-Kr7npakl(wE zZ+zGOv7L(8N9^0}2keZ)9 %v(`C jWi?+78O{%SOjV`;j98e;dYLF+U zr?0>mga9$>MZe%J$^hG1TcGtv3YHa&6wn3!0>3wG@2Z7$JE!?+FsHLDmf7)`9Y^i> z9y@m0v+cZ{w%a3)2!1*8afCV$!Mv9Th`~#-0VPw?F -n_iFWM)OWTsJ+hv@2a3YKa89 z?wy@0m;Ok3_$=G-;;bny1(z|6jtnmwTDf|~D$qMeh(7|dZb1R?x@s-$HqI8Yjo4_l zN>(dxvvN$cfm48K2J9062AYID1f2;fGeQyy!DoV+cxs2yprL0iSk|(%(mpyWky)yz z&&qz`Me5Z%@5~+C85uhZdN8ov7fRQ^{O@DIxV||63h-w5mH-VIvmRd0>6|)Bfod7t zrWLoUVIfj{9`b)GxO61E4bBau>*vSAd?Ik`@WANkYo(b+uU!+$$Sh^*a9T;eGQpP! zYqQ}c)cC2GUU-KNxlk5wfu+E1DnVVV(9^V{Ey>jCa46N{W)M5z90)YVO&<^sc$w~B z07KpNudc`rnXLJ4Tb5flniO85yVi=BUM1ftldHYuLFStu&C^!T@QeGdZ&sZC^d%u@ zvljyT48((JQ5D#|L@G=~Dma$q)SREA#7b$ctW7OPU 7Iz}kQ!lKj9pq)6kAjo5Q8HiQqqAB!$Iew?EU4&enc&)5$9{q$J3 zNI#Yz`!e1>JOJ&ZAtzSFu}(;;t;KB&SR_QB2)Y+0Q_8`H)*y z`=T80mOmk FQT(sJSMf$L;!)b3;bEanYn#n-mfjBle;lWR2gs_6e5Z6{rX62e^ zhvpqwTU&YibHaWMZQ8eQBiShLrt>=*8g`uDbkDgR_4PZ>-ShsrbML?ZE_|qm*qTRT zdL{&If)=5CJ~1n7n?Wpw6i%e5Rkr0gn>9vGrB>K{%`CBFzyKqo8aKcoSB$ibOtapr zc<%&d;&FT$)T%fhu#THxannn%6Lwk!)2n2{DqDBG(V!=$mtZKwe4_lF?$S)#qzOTP znALl4--Ovfj4+@p^nrptaPdC)oUErdSulK5VPi*5vMovNlsDVB3 L`$@beaOWiwv z_!T~{n__b&5#wl5_TY;?y+Gq~Uj8io3QZAfAigHmCYD2V&75s+HjkKTjj~qNW>Tw_ z1}%wPgw9O#B|xwf2%Le+xMl pyxzq!Cpd0Kk!V`HY%x8LZwc8;zoI*1SLIr&Vj~38e0nVtEK59Q|r|cd1 zDQV5R3^s|As^VN52*Hd@oR04xdz|ntq_;qmu1E3WX{rB57%wzs$-c;v{l$)kwyuow znMGE8-mGwVxY<`QaBoNd&%&YdO|^rwO@+NR;pNTgIJ0?GOR78R2?FF9(~6TFft-ND zQBv1mS+k@rB|Yf@yRWj$otx#iCzjMlh@Nwee?e_yYhV>j^D&E{vHg(P$+C`+qsc*; zY_)oa)~|(+!*F0Mb5ZUz_Z}w_aaL`UQ4i@Y&7cO!Y%^hyy+JH9f%ec(fsf+BXDSbj zvJeg$NB~oB#Fw?1>29eqH9OZ*ws2a;Lk~4B!1~x1p>>Q%LT?r+q^z@X!(3`jOXHuf zY#LkNKU?67gJ9E3VAZOX=qqfhwYDd436X@61R5s6Hk( Kw@V(U2}0HJJ_|j8vocT11vX%Pkh#f;gCX1;8pqfU60lFW%=#oX-a_)oT!+ za0FB!$t5XX_fNpRI86x5H$ffx(vyrr0jposBKUZXMSl2P?6a5G%k)|mq{wOvM%i<( z9hRDmS_tDRwFdd7ld(^z`P$4tu4PJDXi8wAXKX*v@ c{A r3UZ{Om$+&G^>V8T@0jRX}L&(|0%(rN^m~Jyv4lH5*Cwn ze2c`Z#ncQjo&xK1!I ;@;HsIVU6CIrltJn?j8XhJCmZ$j07_>Q3@~DY z?TtP9?&Ztx#vaBuzZ?4|_V;(GAZ3aT;(cSEkG+kL$0l$^8Te2i1C5f <^`Oc20L&I{JHw2zgu9b?3-MJ6N$PgHJm^#9zoCp!1+lQo#S^(mjwKAdxD= z@dPUk2#8n=sAQjft(@KqqX#nfJXFIc>Y(E t_6TTvXz1js YIIrWOj(K=m sJ&p8T znVkGjG5VYJJ3YPKj_r)~+pjI-7V3AfR@S0Q{?`42@>^9LJQb{PK#Iwd);~}59lWE0 zJOcNS7#l2Tg)W1GY=HP0i5`jbAXD=q>E~qsUFDIoYZSo63vYwotzLi|1Ul>z=n#7@ zH=L;lO2nQOD6w0h1n|=!RR@+*H|UcRUTG)mcQ}w>(=##$QLIKz2kUp)XA(%PAf#+k z4k@=OMM^+ZgMWL|?+Xa2vLsU%$1`=rd4f-Af>pQ#r!s(R3Fwa2Q;?ZvOeiTXv<&RD z2MQ|vo&tZWP+*?3ixf~>IHQu)xiTz|EoPM#{ZGz-@UTujwgqyfd%=$~q4F2ulM(TC z>e;YHJ!&~^0lRY_;7LL_NDX43La fn!`vEi$UsS~N&K(|w1o1KK%st0xR9xYv?W*C{r;N`tIF^pu{ zGG6wcj1kFf!)mSCHOx}1pmG#yZCK5!S(+2WOcWv}nm@kYnP5qA=HlKUSz%zy q)vTPA?Y-zHLTzN4()aCXzy zU*A)&JbaLLnFPG@SHJ!DS3TyR5q(kx_=TH&3#Fo)d5uyt Z^BhGHuVL7 zhgM@d{ROiHc)bAK&AV0GjM!+*dfK2?m_>;$2uv)4)nBmcqX;w39nuhdsDOs_2bdf#z9EG8$@2a; zdgA>jWrPGhFysC0w6K1P$hx-xf~o{CEHDY^nMiCBdr68!idXC{$if8zJ{C9DNjls~ zw`1Mxwf@B=C5y7w&AHRzal6(=)@3aM0624PWUa%!*;76v5bUZ*NvY@x24<9dsB^`O z{Oe|~b0#M{*TJO#zfWA6?1Vcq7ni_QDJj?PitBU0Qke$OX-2e*pP6k2`%z&$WWWZ4 zf|1~-DeQpBgxU*a64UbT2lZIbsTFv$0+aMHUO|h&+>5BiYLPagqmgc{dYhVpaL;?h z5OwG%wN9 7*5|qMpo9wI?w4b0zmA>5nXz-v#&>^-Z8%M$df<>hvMF{Mi(m&S%0#zZHwTDO z5${1#oDC}pmPtpX0OKEm)difG7mtWfi&?Rl S;7SI z4OmVA$3Q7zZ6cT_AW6VYKS8G_Q#J&tyN2A7uPA{2o=EZ_{O6chp$Xa5o2;2r9QEyj z6Zmkru>9WIIfLe+K5zmX)6HqQ3Dph7iyw+Cj{A+i>Yf6VCfM6Bb+|cgUqWbZ*sV`< z8LZ`tr(66fCOR$H%4e!mZfYx?UFAu2Zb|SK7um8h{Pu+M#{RP0_Np8%Wl3Z0(6m&S z^AR; 1zUeFq)!o$5;AfKJnFd~u!QBp zsop75ys3qFWnrq$ZRMt itH@|dds0UI1GNnTEjNOqXrmq2j_@5mN`ZoER;Jk zYu_wxc{7u&S|rbS(>;OvFNF?Zi?oAu@sE>k1hd zd9ucVxlzf`t4n)%m%X&F(v)9RXffyHmAD7@&JE@-cyJ(eS8-Wx|CN{W`#1mM^!)j! zf3dkg|N7%4bC3RI!-l^cojbW_>=~`A>Kj*0_lXr6>3X?VC9b&b(7d_7SXJq=ueBz` zUb^8Sn`Y4u6w>t^cT> zO}-#EnIez|k(K$0T5ZMNPmt)e?i1@DfO^*7zjm<*CRxDGKsS@bRt{p=BqED}!G-*s zTp=I}=sa1dOSCh<@=E8hxMrD+4{ zNmG0l+CJUrwkWN^X~Dt8EaM0l*^L9%sog!Pvn@{E+S1A*lL6^4$XX>J$r_GMPGrK{w*v4Bo=vTN&KJ;CcoZGFS`W z2?8gSd4_!s$St^j#J2;r^asM4g0^O;T~~gf?PH(gb+D2O!Pj>uz9pa)fsDe`b5(XE zFw#>{BYK5jbI^F)_?nSEZhFl`nT&Y4L1j`IUpJ`q27^i^MV8mC($^US17SO4J#Br@ zN{hEK*veQLNA;^H6Q9lmn5y_yhsyjGLPnd>V3oXOgNxNxht+RgYu#pj)CyuJ#Bi2D z6o<9ithN;X&0JmGn<+%@NTy|6?v@i$lEo+_vVXn&2}wdwN@lU5jhv4|XEw4v?llZE zRu6Cz0bqTYe2GO2xw)WO-82at0*n1`GD&?Fp4rseRfF%hWfnOq^GxY3ne4fD`X2uL z$wz+t>-7?N{qes@BaOnx)vAOJ{g$3pE-Xi5;NV+!=fI|AQRj@yjATBN80| zE%$%O&0s`7e#0n4dLcIh>@T{5B5MT5cN8l5jKrs9X^+Bp6b@yBMy8PE2&Z bL4wO_>Wok5}%RFE-;C3g9z z+CSJo#UBYwO4j%ZALsH-EF*_^7myWx*A!YjFrdaRYRTAZ?-zwr)fM@{p3KJl4bw~d zt33Anrr=I|FIBhfld|^8;-qpukkXr7?h4H;3Usv3EO;2&=b(zH`Ov;>SiM?8Bk*lS zi5DTTbx{=P3v3He0n$*fSH)YLVHIupBraur){m{M#A?;1xIfMKgZ5Lk{9_>r;vy(6 z;$6p^P8v>@CxU>%VlN;bxc%1~C|3muzNr8bHJLdhd^>__Y^m<-Ol`fRqh@tc=&rok zor@x~XU}TWyZyG}{$RDew5lPadO?kw`K)oF*|e~+WS} 1-wcg9V@)iS=j!!?D9x0g^~mvK{7m=j2SUx7Q}LC0cDX1WDwE1StSd z5Lt+?J`f^3WSWZSjtUtekV7Q+3X_TcK|HW R2y4%xZr$r=RZh7nqGYB|{4%*~m9z-kwLYi3stXL&}5E(cFMu7QIO2`&v zA)N{qpAh~AIgF1Qv`I*R& ^;KXY5qdm8h4BuW#N&dzl{3V@3d8)re-h?XVX^j?AXYbOfqz+=O`ZE6{C79R zv-iT=EijKc^g5kkt#%uP8nhziUC1V~YVU>5*{H$>gHE;;mMCBJlXM5L7NEZbvLRwE z@Z?pHPvAjsK@dI?fcI|QZTx?#`xdyWt}E}o&$*Wi7q}03gTUeal6!$Gf&$*FA|Mh$ z6yFw*H{oFbu_m=nHO4$9F_~sEe$>`ZVoWsA*a=Z%ny4kFd9_KVoih2-R-GpO&DYW< z)33vCW~%qjf9-QFT&`d{o%#K~-^X=%&OLXZwfA0Y?X}n5d#$~5&E|YdWnHYznYLxm zVzLI@H=26_ whBvuZ1$ z-ajFYn?qf<-=vA}>ZkNb)?K~j&h9liSv9@oOYdH@z`bPkhKALv8#b)g^{(5$8CzQK zU$^dSn{2jCUt70(&z{|1##W&y&wAKCPieN#2A5qka16iJNk)9+;2;wtV~3n`TnKc7 z!2`3$h>x$$Lk_ysA!B})!pCojX%uwT(7$4+m=T7}jP%&62^aY(_q$~1@I~%U_j_dg z@IuMtZd=2*@oj6|JL0Bq$u4oi@en@OmUP+)(~`kHlByZA8ra`UH*cM%6=Ye8jFzQK zksLD$PE0Crmz6Usx1wLeb$g+8yMXP5h0F;cobXoCe_O@*8x<#>1Lu(J0M1NTv=kmK zF^pOGSu3HlvYm{p=)Cv{nZT6@TtC#mgYxat%J;llKG_LerLGKFDn|Ks7W2AdUd%@w z{J4YP4?W@Fbq=2A;0i{~<{G{o34T^4g()%@V7j0{AaTPWllt;XR*#JT8;$mj8gWO1tz=VH96`UjD_U6cq25yKPo zQf1tKYEG)NWGwSWoENQsYNe~5BF;OC;|kY`i1UlL&)cOf*}Ar7I^x`s@>khQ98C{z zD(@5#=Sx@QgmJr{Vh|@l;1mwS;JkE}DrmUE^E$6*5u;LsJ{^ )Xt bZa6*xZo#*?Rx_d?g&dM46)(a0bxed7H&n`)rFl5 Ms7B~WRwCeaA=1cx(Ry|k(d4r zyOS(%Om&cnEsXDC2Sw6qq5Ipn?>+S9o0xADvq-dZfvC|GPF9xy3W5vRa4XQA_TEM5 zu>1}pZ6j~}N-F!qF8=i%5go3D-14_1G$W$VUi8<9lLmd#g-qPbZ{mmGbG$Y?HChqE zAkra*OMXMhPNpV1=LK(}rqW@meQ$Ig=Ei(v$3OirbE>@M(RiUc1Sdp!Q_qTj%=0h4 z_-~DZs8esC+$w&O1+_fgo_|$k0a8H1!$TA`y^ky`1ru9E9iXA0k5;%}@y+9T|2j}S z>%%_jhdp2RsYCZ|b+97+NuTs%9AgnMbGuR$5=P8;zLJKWVNrNSdm^+d*hr;Yf)R=ND z!2F0VPz0CrI`>%-U@oUgPf%?6SrKP09cZE$bGPYfcRWv3`KLD-sO@7m5WKj`9?@u} zfL6vNyK#!!s+>~Xqo6GeE8-nnkMz)8nL>BHFlx)3euL!NFa0o VX8dDYc+j0JB9Q@cjXJ+m07B$ z_sT1J*GGA-{4?Es7@Hk>l?5P*1$((6n&rAH8cQwALOZ)DxC^4YAiARn2ug(Obypr9 zxI(!BJJkepUPr5`MkDq+R)Co)m?osanQt?73N|Q!z06|Z0elapr^%fTb|6i>iv9D{ z{nKd^^&nmp#G`_^Aqd9Ud+zUb@iM-=(|w6M+ud)t$2z1Rac7tNdwgk!`;z-|J1=uz z?SMMLD0;7F6mga};bTG^-{xA9m6)BNi_6%`V}eaOtIj{_GH$E2y&y3wAzPQ5+=$4t zU|mpbq%OBHBuES6!^|*kX)3%7p{5ZatUiDpXNV-BrGA$d8N^;C+9CwT7E#(hC3*{% zvoO+HD(S w2#6IjBVy}> z48!kK$Z(mE8KDwkXN)F92Tw^oWX3=JFuSVCBu_;fsftdRPCYCBF}BAS|E*DFHvA-$ zYI(Ya3_~U*P8~ew(F@cZyfTS0;ZIj2>QE}`FwF9`GC}R~mLRhMXGy3Q1d^(ISy1e+ z1@5z@uB0f$*Tx@<=azVG4W@|S`PQa@xTfF$d< vdHbDr}evF~=mv*x^Cr z3Jt4jwDrU36#CW9 Xi%6`C zjfA@vMU4n=a+H_K3<*VC9VT`#-bZc300VQ 1Nl&{X<2z3Gc7eO{SX60JqZRL1}sKNMrD z<~sHjSFAmJbwZVH`EpiMl^(ybzP7%x{#d=dxQdDOdmBQkuzBf*wQRX%xwJe1i!~O^ zznNDju9gg|S6h=x>+A~_Mq)RCx+okH2BD%UHt|0?WvnY>Du25gY(+Es>i!}~LIDa` zZ}khbiWG~let{`8tXCHTiqx4F5r&1W{Y1FRmuALa9XOHWIMLBO(zEzhlm6>p&u>^$ zotCk>wjuxFcb6vDG!9i)-nV7p>&>-O5nA%WzJ0-bJho^(cg&2@YS`Ye-9Nl#U~o}G zNh0F8>bGr}4&IVlw4fL81Aey@`viVe2z_%eUk<$j`_!JU=tG6L3E32JJwi5N qQ7ct6pR E6si}Y!t{Azi+MS9UEgrd6GX%7BlL`iR- z03F{CeVQAPf-&@BHsq?9mx-+hmB<*~{N(8Q$;tDhv8T(%5?9HGCD%)2a|sV9fD`%> zB_<_O7nPJ0pIZkvl9$Yvuz+snQRXOfJTKCm)5UTGR?TTSf=&>i4gvbq@=J9 >xgLl;@~8LPS)_WicfPc*(mDKmSNlj#VB(jzcv$tvnGN=e zW%ri+qIzsaf9- qp`e9x|BM_>Ed+2XtF3v8PXG}P?flK*`gV}WOg>nDA+R> B_WK>6QB#>4)o7*<64Z)+p)Isb|4G_6Hx_ z|1p|5D{fJ4wJcYmlgZ*1Ww|w)RWyx#x-3F=)b!n`XUsWS$|BLf;Q9AaWuc#qD`WlP z-=P0qgoPM|y=0qQ5qY^h`BZeY>C^_fU6wNCV$2Q-hs8`d`!QX{X_yWWk@$EXbee@x zJWx~E*|5uDABGtW*tqL7r&T%H@c=So7fUMGj|FpPn4F;rRa%?yTUzmUvudAgldu!w ztxNL~v!bK2m3i}&?5OCh#CiVTv7qsk`?o3fgwW6gdrFc$(PT=rOP}~XKvP4_20f!X zyY30tzNuK%-R3IENX&%on^qMS9T{N=#3_)WY@^*}|ImKjE}QK 5BT<)= zTxT#wV+tX1o+YO)kYYC8y5W4w$M~i8;A8s=yF&G?@p?lD*BeY`s+MnnexYjkF4Ea4 zqGRul@&k3w3JU6Q-jk2}r7Lf-ut@%B{OVjte0hd@AhC+>M2tsaZ}ovHHOwP^e$T3} zt@`MJ^#>f%A?v&kK04NN>prXHN2oGnP56`xIo_no@iQblJWgn}Z;U3zg~WKJe%AEE zO==s-zzZAWlBQG7f_p4bO-smGiVtRQS|O8aIl3j1Nr|VDGP~gU!)Tmc#qHH+ct`lw zin4DLWgj-F`0c>ok&?xxdlD_S1#1fmMm5E*M0=HSqr>9h8A@VA9M(Dt;#pkWg1QKE zWKtb=<`hQabaZin7TtpN72mZ!pFkI@A#G-O3vZ=ZVsAi;7G^ABUCssaMBlIx`J8V^ zi%+l%&Wv94q}4CNg?J|FEoi0IyZbw$?~*tv6CRvWq}E)cl!$ZUtyt^vkN;A=?#0Lq zuH{(%rT8zTLsy4$a6gtu5W^nM(p*-vNvC6%19hgqVCKNaKpe7-VQ1|7SaXhjpEh5h zb%+#baqKve0;jnm5!pVn$I-KJQMY4HZ25{3#7&f}SQ(@HIJvo~s5v=KtVbn_Fn0;( z?S3rh2OJV>0WMc=_yL*`sYT2@*3b{+kt^t5l1HG^Tx)Jb59Bc$0?hG$Y1TKwr4c2$ z@na|v41{m|*t_G9>OG+@%o@acqZ(5!=ckmd&o8JiQIwMUg1q%hQ+7G?vBP6=zEl5q zj JwF?VNOA7%SEk4r!0wbehSBg2xj%9y_tzINUP^A8_$p!yZlM8;_ zCR5m9tdwEY4!1g57s)}SB^2EIwC;+fVe;d^aRwwoG~tW`IwW^yZB2!en`i3OClyxP zve(wEjL)^1yXc$llaw4#vvkMGw3O_Wg-c7DSEhqCzz-h<`HV#89mKzi>CVfp-~hN! zgBCdT;B{zKv8w@MCP<0a%iE^TJ-~a0Klwew^m|eA6<&w2VF+X)s?o%;2UMe>-*CzB z0ld*dj_{D9*bmK#)vy~73sT 4L(4`sRJRF12GPSc*sNtLg>#$7VX)4Z*l4U_Y-2@ zvnL8)WhT%k+!$TuMZHg;=HdW~^Voh6Cr{weGRlR{0NQ>7ber0x_>KopU{8Dbiu947 zOAOoLs=5@%AE!OC8sqxo {MhzZdo; zfS(tZ)x6t9V~h*`F68d#&gJXG<(H4smC1g6P5xZ=$Ov-4N{>7vFCB%6V2$;*tQ^~k z7vy;>)=~LQte*bnH-4+9l$ZP47$bF}eL_#pICBMSI1pB>U;7@p(s}bAzA5A6AaUf1 z#6sZra#;UeW<+FKg)2Kqx)F@C-l7_#4nzCX%6P;LJ=c8}WDZWmMyGOMaIj?l%2_=^tuhHSii zxnEjw>jz`mE&0J|*_q}qP#ydw@IDBD`nQmEYxf*wd_}vL;PFmELVq|7hwHR^9W(Mg z?H;kayi2 V`+P#6Tk1)KyVqgmIaa&Zvjx0FyT=Yb z{4cb713SvUrQHXzOz9Er-pGC^y{p{^vtoq0t7Qmb+jN_?`%v8fQoA>?_4+~WejW?g z{~j}EU91Bz1h|*A;Y1(>(2VcRxNE_J%}%z54Tw~oc&f0IfCBg-<-xOm0q!f2rXM(Z z@V0_=kbb1zDgGxcUAXIGHpa@kI=Y6s?rm#TTAPQOm6raUdj`5XI){{#N mHd1>pU!1w_0-x;|Ed7tAkYz4hESho zQLkQ6>$~x+A0t 4Rj5*cC`?z2f^#xSvI>cu_=c6$cir|r$xn=YMrPHQKC<)yMkJ&0!4RJ z?=C^ZA<$|kzPIC7q6f8yHl(0-(uX^uD4i=yGPO&4lk(})=;?h=<(A5UHqknWek9IR zf)+vTew3&eSkxyo+sl-YD}uzGyLy}ZKt*K`a<2@w4Rp0DLwk0%wKuo4DXndTT^)TO zZ+riMvI{?g&Y(B_2KImvZ9Q!*Lj(PNT`g#Ny}i3|<85Nps)tbHC0Jju<8)p6*iiSG z?T0i0wQCznPNl}WZ|Bg^&LwvH?%lg>%~}&`LF2U{1N!yPMC&F0Orj5 HHgf0g8m#&YCXh zk3kTBm(U_Zoo&jpoy{${Xum8_ysf{$hV*k$W;%15Aa)0c+%u!#gLqQIRzb <8?c{X5c=m}jGeG!Bs@|q%! Qvj^B?>=E`&^l!(x#2!Yd)B*N&_B-}}*`qkW`aw3ve$M`deT$u9 z|H^*PCfU>MG 2m#9|`&{G@W6z!e8N(>U*J$?!$@LUtt&6 z-{O4fuVRt>Yit6egNtk&HpI`^$2gDfWp<98XK&*4>sQ!Sc8I;fF5&cOodNAUFK=0S zQ2#KxA2iOkkoNvv1B1JELVfh3mxSR6{z;f?kp)Nb-}l{Tuh9=zM$kLq@9n7CNnzz+ z(g|FoKiZp`vA@UvI`NHUfr0x8;2!U39_oWM&@VKHL%;C5+Xm>FnvUL*@C_T1GH(5? zNZAg`{DeQqALE|_ekIjO-O?yxKsx0U@~66L-ErM7;UZgs9T7(iPX;~~WRW}hgT`ch zG674BO~zs4SH$ j4|_+h)KPw3}_X?gyR&fcpUl z0S^EU0Uq>hgS2L`!+^&DPXLYq_w&GU5^xIe0^mi!X}~Dp6~H;bdB6q0MZhJzcLl)F z>h42JO~ ugRZF&*jD1vO1quo^iDgjl1YP?s6HnbK{ zkMHYnU5{%6t{ZUOgzIK-X$xR0U>jgNU_X940JtA;5byxt5a2-%QDAOe@ifvr12_(N z7H|Ua9N>AtNx&(<3xF2^rvWb`|503D0h|Mz2V4ML1iXgdz6*FA@CM)#^1T9h3-{kg zz1{(B-WN17gJ)I%wcWYf=QwN(Uz$$SbL=+VQI33O>hm$saU671_4+zoNw+uPx&g2W zupi$K0PY7I1UvvZ1b7g2xl@~Z8fl&Z90xoLI01MLFqhtc8F|g6`(MLv-vzu5cmv?2 z5!JjM($o%VIs;mr5!%OJZ hXOYuIq7az*VjF1f+#%K9|Ni zBihScy69=V_YB}T;90;4z;l4-0Ve^c051Su1e^xEjJ!s1eFbn1a2{|0a1rnte#4#; zsQCnHK7pFILpo^u?Cm4``-cjossvO4aJnsOHgQKjJ&)f{0!{&50K5n|4HyNy0yqaa z4}eD gmwOwCKJxEzvQ0jLC20n`>e1|E!|lq28)SrsGT!5DaO29ifD zcN{I3ctI_91X4HxDI9?mjz9`WAcZ4Z%bmL?d>Uz<0UQTB3pfFI4)8qSB;XX_1;C4d z(}0(e*C?*90L}r<1K>)6nvZ}NW8lRYcrgZEz#>7}t_X^#Ef%wWC^3yP)Sl7XqXkV# z>1OCM)m{pRJrfRlhWb5~qxvb1R*R=9l?msVz^PgUUg}GNIwYkbQ`pP#jb!_2z%zj3 zfM)?G0M7w@b5eEiMv;?RddgpYy2|G%VOMjemO>Idm!x`2MtIcvt9aC2Jy6IZ$=Y0U zl`&;?g+jBKF c6=w>;TuTjZ>3$r zJ68Z+Yc1`MmhR6f+5cpz_W96k{J%uAjh@dyuYUl&J_Efz`7>zs3261n6s?Gp(8_>N z&;R>Uy^V4Z7vIB`?Cxpn+5-NPY 1kX*I^|B7=F&Cw zLYoAkjAZMDKqG{LR=3-H)4fHm=M9#J^xkofYWtC2T$UJ1xPZgI7g+^~{Zo1puQu@Q zQJR47|A$@$vmTx!qG!PYXWHHS;1u+%rytMzq4PeO>J2D0PILz(OzB}WzF7guo>BC{ zljwsd(Fadr7AhRnn}lYbMBh7!5q$tO{3QCtN%V`8=ocr^FHWLgoP^e%M4vc`K5-I# z;w1XSN%V=6=u^tryPikI$n6KXeh6M0Zp+!XC!i7He}Bed?y=1O%xnYp9Uuy09*AZN zIdrQP^G>Ol{R@CRQjfR*pI|Zn7lPTpLd+xyk zZf_&z4>zL^%Vhg8?`6ZR+FxPL@JV(A?~Py#yh6;=t-=i11*E RfBp)EW$ZrzpwELT literal 0 HcmV?d00001 diff --git a/sites/all/modules/barcode/includes/barcode.admin.inc b/sites/all/modules/barcode/includes/barcode.admin.inc new file mode 100644 index 0000000..aed44e1 --- /dev/null +++ b/sites/all/modules/barcode/includes/barcode.admin.inc @@ -0,0 +1,40 @@ + t('Default path'), + '#description' => t('A file system URI where the barcode images will be stored. Changing this location will cause that barcodes will be generated again upon view.'), + '#type' => 'textfield', + '#default_value' => $barcode['default_path'], + '#size' => 60, + '#required' => TRUE, + ); + $form['barcode_font'] = array( + '#title' => t('Font file'), + '#description' => t("The font used in barcode, must be relative path to Drupal's base."), + '#type' => 'textfield', + '#default_value' => $barcode['font'], + '#size' => 100, + '#required' => TRUE, + ); + return system_settings_form($form); +} + +function barcode_settings_validate($form, &$form_state) { + + $created = file_prepare_directory($form_state['values']['barcode_default_path'], FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); + + if (!$created) { + form_set_error('barcode_default_path', t('Path could not be created or made writeable.')); + } +} diff --git a/sites/all/modules/barcode/includes/barcode.plugins.inc b/sites/all/modules/barcode/includes/barcode.plugins.inc new file mode 100644 index 0000000..4e6ca35 --- /dev/null +++ b/sites/all/modules/barcode/includes/barcode.plugins.inc @@ -0,0 +1,133 @@ + t('UPC-A'), + 'EAN-13' => t('EAN-13'), + 'ISBN' => t('ISBN') + ); + $plugins['ean8'] = array('EAN-8' => t('EAN-8')); + $plugins['upce'] = array('UPC-E' => t('UPC-E')); + $plugins['s2o5'] = array( + 'S2O5' => t('Standard 2 of 5'), + 'I2O5' => t('Industrial 2 of 5') + ); + $plugins['i25'] = array('I25' => t('Interleaved 2 of 5')); + $plugins['postnet'] = array('POSTNET' => t('Postnet')); + $plugins['codabar'] = array('CODABAR' => t('Codabar')); + $plugins['code128'] = array('CODE128' => t('Code 128')); + $plugins['code39'] = array('CODE39' => t('Code 39')); + $plugins['code93'] = array('CODE93' => t('Code 93')); + $plugins['qrcode'] = array('QRCODE' => t('QR Code')); + return $plugins; +} + +/** + * Return the plugin filename containing the given encoding. + */ +function barcode_load_plugin($encoding_name) { + $plugins = barcode_discover_plugins(); + foreach ($plugins as $plugin => $encodings) { + foreach ($encodings as $encoding => $display_string) { + if ($encoding == $encoding_name) { + module_load_include('inc', 'barcode', 'plugins/' . $plugin); + return $plugin; + } + } + } + return ''; +} + +function barcode_plugin_generate_image($plugin, $barcode, $settings) { + $gen_function = 'barcode_'. $plugin .'_barcode'; + $gen_function($barcode, $settings); +} + +function barcode_plugin_max_length($encoding_name) { + $plugin = barcode_load_plugin($encoding_name); + $max_length_function = 'barcode_'. $plugin .'_max_length'; + + if (function_exists($max_length_function)) { + return $max_length_function($encoding_name); + } +} + +/** + * Creates or return the plugin filename containing the given encoding. + */ +function barcode_generate_image($barcode, $variables) { + $name = md5($variables['barcode_value']); + $filename_noformat = $barcode['default_path'] .'/'. $name . $variables['encoding']; + $filename = $filename_noformat .'.'. $variables['image_format']; + + // First check if the images already exists. + if (!file_exists($filename)) { + $plugin = barcode_load_plugin($variables['encoding']); + + $settings = new stdClass(); + $settings->default_path = drupal_realpath($barcode['default_path']); + $settings->encode = $variables['encoding']; + $settings->height = $variables['height']; + $settings->font = $barcode['font']; + $settings->format = $variables['image_format']; + // GD library fails on stream wrappers - get the realpath. + $settings->filename_no_format = drupal_realpath($filename_noformat); + $settings->n2w = 2; + + if ($variables['encoding'] != 'QRCODE') { + $settings->color = array(hexdec(substr($variables['barcolor'], 1, 2)), hexdec(substr($variables['barcolor'], 3, 2)), hexdec(substr($variables['barcolor'], 5, 2))); + $settings->bgcolor = array(hexdec(substr($variables['bgcolor'], 1, 2)), hexdec(substr($variables['bgcolor'], 3, 2)), hexdec(substr($variables['bgcolor'], 5, 2))); + $settings->scale = $variables['scale']; + } + barcode_plugin_generate_image($plugin, $variables['barcode_value'], $settings); + } + + if (!file_exists($filename)) { + watchdog('barcode', 'Failed to generate image using settings @settings', array('@settings' => print_r($settings, TRUE))); + return FALSE; + } + + return $filename; +} + +function barcode_check_digit($barnumber, $number) { + $csum_total = 0; // The checksum working variable starts at zero + + // If the source message string is less than 12 characters long, we make it + // 12 characters + if (strlen($barnumber) < $number) { + $barnumber = str_pad($barnumber, $number, "0", STR_PAD_LEFT); + } + + // Calculate the checksum value for the message + for ($i = 0; $i < strlen($barnumber); $i++) { + if ($i % 2 == 0) { + $csum_total = $csum_total + (3 * intval($barnumber{$i})); + } + else { + $csum_total = $csum_total + intval($barnumber{$i}); + } + } + + // Calculate the checksum digit + if ($csum_total % 10 == 0) { + $checksum_digit = ''; + } + else { + $checksum_digit = 10 - ($csum_total % 10); + } + + return $barnumber . $checksum_digit; +} diff --git a/sites/all/modules/barcode/modules/barcode_example/barcode_example.info b/sites/all/modules/barcode/modules/barcode_example/barcode_example.info new file mode 100644 index 0000000..ea4749e --- /dev/null +++ b/sites/all/modules/barcode/modules/barcode_example/barcode_example.info @@ -0,0 +1,5 @@ +name = Barcode example +description = Barcode FAPI element example. +core = 7.x +dependencies[] = barcode +files[] = barcode_example.module diff --git a/sites/all/modules/barcode/modules/barcode_example/barcode_example.module b/sites/all/modules/barcode/modules/barcode_example/barcode_example.module new file mode 100644 index 0000000..27e488f --- /dev/null +++ b/sites/all/modules/barcode/modules/barcode_example/barcode_example.module @@ -0,0 +1,45 @@ + 'Barcode example', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('barcode_example_example'), + 'access arguments' => array('access content'), + ); + return $items; +} + +function barcode_example_example($form, &$form_state) { + $encoding = variable_get('barcode_encoding', 'EAN-13'); + + if (isset($form_state['barcode'])) { + $form['barcode_image'] = array( + '#markup' => theme('barcode_image', array('barcode_value' => $form_state['barcode'], 'encoding' => $encoding)), + ); + } + + $settings = url('admin/config/media/barcode', array( + 'query' => array('destination' => 'barcode_example'), + )); + + $form['barcode'] = array( + '#type' => 'barcode', + '#title' => t('Barcode'), + '#description' => t('Enter a number to generate a barcode image using the %encoding encoding. You can change which encoding is used in the Barcode settings page.', array('%encoding' => $encoding, '@settings' => $settings)), + '#encoding' => $encoding, + ); + + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Show the barcode'), + ); + + return $form; +} + +function barcode_example_example_submit($form, &$form_state) { + $form_state['barcode'] = $form_state['values']['barcode']; + $form_state['rebuild'] = TRUE; +} + diff --git a/sites/all/modules/barcode/plugins/codabar.inc b/sites/all/modules/barcode/plugins/codabar.inc new file mode 100644 index 0000000..b199e6d --- /dev/null +++ b/sites/all/modules/barcode/plugins/codabar.inc @@ -0,0 +1,144 @@ +filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $scale = $settings->scale; + if ($scale < 1) { + $scale = 2; + } + + $total_y = (double)$scale * $settings->height; + $space = array( + 'top' => 2 * $scale, + 'bottom' => 2 * $scale, + 'left' => 2 * $scale, + 'right' => 2 * $scale + ); + + /* count total width */ + $xpos = 0; + + $xpos = $scale * strlen($bars); + + /* allocate the image */ + $total_x = $xpos + $space['left'] + $space['right']; + $xpos = $space['left']; + + $height = floor($total_y - ($scale * 10)); + $height2 = floor($total_y - $space['bottom']); + + $im = @imagecreatetruecolor($total_x, $total_y); + $bg_color = @imagecolorallocate($im, $settings->bgcolor[0], $settings->bgcolor[1], $settings->bgcolor[2]); + @imagefilledrectangle($im, 0, 0, $total_x, $total_y, $bg_color); + $bar_color = @imagecolorallocate($im, $settings->color[0], $settings->color[1], $settings->color[2]); + + for ($i = 0; $i < strlen($bars); $i++) { + $h = $height; + $val = strtoupper($bars[$i]); + + if ($val == 1) { + @imagefilledrectangle($im, $xpos, $space['top'], $xpos+$scale-1, $h, $bar_color); + } + + $xpos += $scale; + } + + + $x = ($total_x - strlen($bars)) / 2; + @imagettftext($im, $scale * 6, 0, $x, $height2, $bar_color, $settings->font, $barnumber); + + if ($settings->format == "png") { + if (!empty($settings->filename_no_format)) { + @imagepng($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagepng($im); + } + } + + if ($settings->format == "gif") { + if (!empty($settings->filename_no_format)) { + @imagegif($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagegif($im); + } + } + + if ($settings->format == "jpg" || $settings->format == "jpeg" ) { + if (!empty($settings->filename_no_format)) { + @imagejpeg($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagejpeg($im); + } + } + + @imagedestroy($im); +} + +/* A Code 11 Barcode has the following structure: + * + * One of four possible start characters (A, B, C, or D), encoded from the + * table below. + * + * A narrow, inter-character space. + * + * The data of the message, encoded from the table below, with a narrow + * inter-character space between each character. + * + * One of four possible stop characters (A, B, C, or D), encoded from the + * table below + */ +function barcode_codabar_encode($barnumber, $settings) { + $enc_table=array("0000011", "0000110", "0001001", "1100000", "0010010", "1000010", "0100001", "0100100", "0110000", "1001000"); + $chr_table=array("-" => "0001100", "$" => "0011000", ":" => "1000101", "/" => "1010001", "." => "1010100", "+" => "0011111", "A" => "0011010", "B" => "0001011", "C" => "0101001", "D" => "0001110"); + + $mfc_str = ""; + + $widebar = str_pad("", $settings->n2w, "1", STR_PAD_LEFT); + $widespc = str_pad("", $settings->n2w, "0", STR_PAD_LEFT); + + for ($i=0; $i < strlen($barnumber); $i++) { + if (preg_match("/[0-9]+/", $barnumber[$i])) { + $tmp = $enc_table[(int)$barnumber[$i]]; + } + else { + $tmp = $chr_table[strtoupper(trim($barnumber[$i]))]; + } + + $bar = TRUE; + + for ($j = 0; $j < strlen($tmp); $j++) { + if ($tmp[$j] == '0' && $bar) { + $mfc_str .= '1'; + } + elseif ($tmp[$j] == '0' && !$bar) { + $mfc_str .= '0'; + } + elseif ($tmp[$j] == '1' && $bar) { + $mfc_str .= $widebar; + } + elseif ($tmp[$j] == '1' && !$bar) { + $mfc_str .= $widespc; + } + + $bar = !$bar; + } + $mfc_str .= '0'; + } + + return $mfc_str; +} diff --git a/sites/all/modules/barcode/plugins/code128.inc b/sites/all/modules/barcode/plugins/code128.inc new file mode 100644 index 0000000..44ffc6c --- /dev/null +++ b/sites/all/modules/barcode/plugins/code128.inc @@ -0,0 +1,173 @@ +filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $scale = $settings->scale; + if ($scale < 1) { + $scale = 2; + } + + $total_y = (double)$scale * $settings->height + 10 * $scale; + + $space = array( + 'top' => 2 * $scale, + 'bottom' => 2 * $scale, + 'left' => 2 * $scale, + 'right' => 2 * $scale, + ); + + /* count total width */ + $xpos = 0; + + $xpos = $scale * strlen($bars) + 2 * $scale * 10; + + /* allocate the image */ + $total_x = $xpos + $space['left'] + $space['right']; + $xpos = $space['left'] + $scale * 10; + + $height = floor($total_y - ($scale * 20)); + $height2 = floor($total_y - $space['bottom']); + + $im = @imagecreatetruecolor($total_x, $total_y); + $bg_color = @imagecolorallocate($im, $settings->bgcolor[0], $settings->bgcolor[1], $settings->bgcolor[2]); + @imagefilledrectangle($im, 0, 0, $total_x, $total_y, $bg_color); + $bar_color = @imagecolorallocate($im, $settings->color[0], $settings->color[1], $settings->color[2]); + + for ($i=0; $i < strlen($bars); $i++) { + $h = $height; + $val = strtoupper($bars[$i]); + + if ($val == 1) { + @imagefilledrectangle($im, $xpos, $space['top'], $xpos + $scale - 1, $h, $bar_color); + } + + $xpos += $scale; + } + + $font_arr = @imagettfbbox($scale * 10, 0, $settings->font, $barnumber); + $x = floor($total_x - (int)$font_arr[0] - (int)$font_arr[2] + $scale * 10) / 2; + @imagettftext($im, $scale * 10, 0, $x, $height2, $bar_color, $settings->font, $barnumber); + + if ($settings->format == "png") { + if (!empty($settings->filename_no_format)) { + @imagepng($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagepng($im); + } + } + + if ($settings->format == "gif") { + if (!empty($settings->filename_no_format)) { + @imagegif($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagegif($im); + } + } + + if ($settings->format == "jpg" || $settings->format == "jpeg") { + if (!empty($settings->filename_no_format)) { + @imagejpeg($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagejpeg($im); + } + } + + @imagedestroy($im); +} + +function barcode_code128_encode($barnumber, $settings, $use_keys) { + $enc_table=array("11011001100", "11001101100", "11001100110", "10010011000", "10010001100", "10001001100", "10011001000", "10011000100", "10001100100", "11001001000", "11001000100", "11000100100", "10110011100", "10011011100", "10011001110", "10111001100", "10011101100", "10011100110", "11001110010", "11001011100", "11001001110", "11011100100", "11001110100", "11101101110", "11101001100", "11100101100", "11100100110", "11101100100", "11100110100", "11100110010", "11011011000", "11011000110", "11000110110", "10100011000", "10001011000", "10001000110", "10110001000", "10001101000", "10001100010", "11010001000", "11000101000", "11000100010", "10110111000", "10110001110", "10001101110", "10111011000", "10111000110", "10001110110", "11101110110", "11010001110", "11000101110", "11011101000", "11011100010", "11011101110", "11101011000", "11101000110", "11100010110", "11101101000", "11101100010", "11100011010", "11101111010", "11001000010", "11110001010", "10100110000", "10100001100", "10010110000", "10010000110", "10000101100", "10000100110", "10110010000", "10110000100", "10011010000", "10011000010", "10000110100", "10000110010", "11000010010", "11001010000", "11110111010", "11000010100", "10001111010", "10100111100", "10010111100", "10010011110", "10111100100", "10011110100", "10011110010", "11110100100", "11110010100", "11110010010", "11011011110", "11011110110", "11110110110", "10101111000", "10100011110", "10001011110", "10111101000", "10111100010", "11110101000", "11110100010", "10111011110", "10111101110", "11101011110", "11110101110", "11010000100", "11010010000", "11010011100", "11000111010"); + + $start = array( + "A" => "11010000100", + "B" => "11010010000", + "C" => "11010011100", + ); + $stop = "11000111010"; + + $sum = 0; + $mfc_str = ""; + if ($use_keys == 'C') { + for ($i = 0; $i < strlen($barnumber); $i += 2) { + $val = substr($barnumber, $i, 2); + if (is_int($val)) { + $sum += ($i + 1) * (int)($val); + } + elseif ($barnumber == chr(129)) { + $sum += ($i+1) * 100; + } + elseif ($barnumber == chr(130)) { + $sum += ($i + 1) * 101; + } + + $mfc_str .= isset($enc_table[$val]) ? $enc_table[$val] : ''; + } + } + else { + for ($i = 0; $i < strlen($barnumber); $i++) { + $num = ord($barnumber[$i]); + if ($num >= 32 && $num <= 126) { + $num = ord($barnumber[$i]) - 32; + } + elseif ($num == 128) { + $num = 99; + } + elseif ($num == 129) { + $num = 100; + } + elseif ($num == 130) { + $num = 101; + } + elseif ($num < 32 && $use_keys == 'A') { + $num = $num + 64; + } + + $sum += ($i + 1) * $num; + $mfc_str .= isset($enc_table[$num]) ? $enc_table[$num] : ''; + } + } + + if ($use_keys == 'A') { + $check = ($sum + 103) % 103; + } + + if ($use_keys == 'B') { + $check = ($sum + 104) % 103; + } + + if ($use_keys == 'C') { + $check = ($sum + 105) % 103; + } + + return $start[$use_keys] . $mfc_str . $enc_table[$check] . $stop ."11"; +} diff --git a/sites/all/modules/barcode/plugins/code39.inc b/sites/all/modules/barcode/plugins/code39.inc new file mode 100644 index 0000000..e82ee42 --- /dev/null +++ b/sites/all/modules/barcode/plugins/code39.inc @@ -0,0 +1,219 @@ +filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $scale = $settings->scale; + if ($scale < 1) { + $scale = 2; + } + + $total_y = (double)$scale * $settings->height + 10 * $scale; + + $space = array( + 'top' => 2 * $scale, + 'bottom' => 2 * $scale, + 'left' => 2 * $scale, + 'right' => 2 * $scale, + ); + + /* count total width */ + $xpos = 0; + + $xpos = $scale * strlen($bars) + 2 * $scale * 10; + + /* allocate the image */ + $total_x = $xpos + $space['left'] + $space['right']; + $xpos = $space['left'] + $scale * 10; + + $height = floor($total_y - ($scale * 20)); + $height2 = floor($total_y - $space['bottom']); + + $im = @imagecreatetruecolor($total_x, $total_y); + $bg_color = @imagecolorallocate($im, $settings->bgcolor[0], $settings->bgcolor[1], $settings->bgcolor[2]); + @imagefilledrectangle($im, 0, 0, $total_x, $total_y, $bg_color); + $bar_color = @imagecolorallocate($im, $settings->color[0], $settings->color[1], $settings->color[2]); + + for ($i = 0; $i < strlen($bars); $i++) { + $h = $height; + $val = $bars[$i]; + + if ($val == 1) { + @imagefilledrectangle($im, $xpos, $space['top'], $xpos + $scale - 1, $h, $bar_color); + } + + $xpos += $scale; + } + + $font_arr = @imagettfbbox ($scale*10, 0, $settings->font, $barnumber); + $x = floor($total_x - (int)$font_arr[0] - (int)$font_arr[2] + $scale * 10) / 2; + @imagettftext($im, $scale * 10, 0, $x, $height2, $bar_color, $settings->font, $barnumber); + + if ($settings->format == "png") { + if (!empty($settings->filename_no_format)) { + @imagepng($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagepng($im); + } + } + + if ($settings->format == "gif") { + if (!empty($settings->filename_no_format)) { + @imagegif($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagegif($im); + } + } + + if ($settings->format == "jpg" || $settings->format == "jpeg") { + if (!empty($settings->filename_no_format)) { + @imagejpeg($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagejpeg($im); + } + } + + @imagedestroy($im); +} + +/* A Code 39 barcode has the following structure: + * A start character - the asterisk (*) character. Any number of characters + * encoded from the table below. An optional checksum digit calculated as + * described above and encoded from the table below. A stop character, which + * is a second asterisk character. + */ +function barcode_code39_encode($barnumber, $settings, $checkdigit = FALSE) { + $enc_table = array( + "0" => "NNNWWNWNN", + "1" => "WNNWNNNNW", + "2" => "NNWWNNNNW", + "3" => "WNWWNNNNN", + "4" => "NNNWWNNNW", + "5" => "WNNWWNNNN", + "6" => "NNWWWNNNN", + "7" => "NNNWNNWNW", + "8" => "WNNWNNWNN", + "9" => "NNWWNNWNN", + "A" => "WNNNNWNNW", + "B" => "NNWNNWNNW", + "C" => "WNWNNWNNN", + "D" => "NNNNWWNNW", + "E" => "WNNNWWNNN", + "F" => "NNWNWWNNN", + "G" => "NNNNNWWNW", + "H" => "WNNNNWWNN", + "I" => "NNWNNWWNN", + "J" => "NNNNWWWNN", + "K" => "WNNNNNNWW", + "L" => "NNWNNNNWW", + "M" => "WNWNNNNWN", + "N" => "NNNNWNNWW", + "O" => "WNNNWNNWN", + "P" => "NNWNWNNWN", + "Q" => "NNNNNNWWW", + "R" => "WNNNNNWWN", + "S" => "NNWNNNWWN", + "T" => "NNNNWNWWN", + "U" => "WWNNNNNNW", + "V" => "NWWNNNNNW", + "W" => "WWWNNNNNN", + "X" => "NWNNWNNNW", + "Y" => "WWNNWNNNN", + "Z" => "NWWNWNNNN", + "-" => "NWNNNNWNW", + "." => "WWNNNNWNN", + " " => "NWWNNNWNN", + "$" => "NWNWNWNNN", + "/" => "NWNWNNNWN", + "+" => "NWNNNWNWN", + "%" => "NNNWNWNWN", + "*" => "NWNNWNWNN", + ); + + $mfc_str = ""; + $widebar = str_pad("", $settings->n2w, "1", STR_PAD_LEFT); + $widespc = str_pad("", $settings->n2w, "0", STR_PAD_LEFT); + + if ($checkdigit == TRUE) { + $arr_key = array_keys($enc_table); + $sum = 0; + for ($i = 0; $i < strlen($barnumber); $i++) { + $num = $barnumber[$i]; + if (preg_match("/[A-Z]+/", $num)) { + $num = ord($num)-55; + } + elseif ($num == '-') { + $num = 36; + } + elseif ($num == '.') { + $num = 37; + } + elseif ($num == ' ') { + $num=38; + } + elseif ($num == '$') { + $num = 39; + } + elseif ($num == '/') { + $num = 40; + } + elseif ($num == '+') { + $num = 41; + } + elseif ($num == '%') { + $num = 42; + } + elseif ($num == '*') { + $num = 43; + } + + $sum += $num; + } + $barnumber .= trim($arr_key[(int)($sum % 43)]); + } + + $barnumber = "*". $barnumber ."*"; + + for ($i = 0; $i < strlen($barnumber); $i++) { + $tmp = $enc_table[$barnumber[$i]]; + + $bar = TRUE; + + for ($j = 0; $j < strlen($tmp); $j++) { + if ($tmp[$j] == 'N' && $bar) { + $mfc_str .= '1'; + } + elseif ($tmp[$j] == 'N' && !$bar) { + $mfc_str .= '0'; + } + elseif ($tmp[$j] == 'W' && $bar) { + $mfc_str .= $widebar; + } + elseif ($tmp[$j] == 'W' && !$bar) { + $mfc_str .= $widespc; + } + + $bar = !$bar; + } + + $mfc_str .= '0'; + } + + return $mfc_str; +} + + diff --git a/sites/all/modules/barcode/plugins/code93.inc b/sites/all/modules/barcode/plugins/code93.inc new file mode 100644 index 0000000..b0f64ae --- /dev/null +++ b/sites/all/modules/barcode/plugins/code93.inc @@ -0,0 +1,200 @@ +filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $scale = $settings->scale; + if ($scale < 1) { + $scale = 2; + } + + $total_y = (double)$scale * $settings->height + 10 * $scale; + + $space = array( + 'top' => 2 * $scale, + 'bottom' => 2 * $scale, + 'left' => 2 * $scale, + 'right' => 2 * $scale, + ); + + /* count total width */ + $xpos = 0; + + $xpos = $scale * strlen($bars) + 2 * $scale * 10; + + /* allocate the image */ + $total_x = $xpos + $space['left'] + $space['right']; + $xpos = $space['left'] + $scale * 10; + + $height = floor($total_y - ($scale * 20)); + $height2 = floor($total_y - $space['bottom']); + + $im = @imagecreatetruecolor($total_x, $total_y); + $bg_color = @imagecolorallocate($im, $settings->bgcolor[0], $settings->bgcolor[1], $settings->bgcolor[2]); + @imagefilledrectangle($im, 0, 0, $total_x, $total_y, $bg_color); + $bar_color = @imagecolorallocate($im, $settings->color[0], $settings->color[1], $settings->color[2]); + + for ($i=0; $i < strlen($bars); $i++) { + $h = $height; + $val = $bars[$i]; + + if ($val == 1) { + @imagefilledrectangle($im, $xpos, $space['top'], $xpos + $scale - 1, $h, $bar_color); + } + + $xpos += $scale; + } + + $font_arr = @imagettfbbox ($scale*10, 0, $settings->font, $barnumber); + $x = floor($total_x - (int)$font_arr[0] - (int)$font_arr[2] + $scale * 10) / 2; + @imagettftext($im, $scale * 10, 0, $x, $height2, $bar_color, $settings->font, $barnumber); + + if ($settings->format == "png") { + if (!empty($settings->filename_no_format)) { + @imagepng($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagepng($im); + } + } + + if ($settings->format == "gif") { + if (!empty($settings->filename_no_format)) { + @imagegif($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagegif($im); + } + } + + if ($settings->format == "jpg" || $settings->format == "jpeg") { + if (!empty($settings->filename_no_format)) { + @imagejpeg($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagejpeg($im); + } + } + + @imagedestroy($im); +} + +/* A Code 93 barcode has the following structure: + * A start character , represented below by the asterisk (*) character. Any + * number of characters encoded from the table below. The "C" and "K" checksum + * digits calculated as described above and encoded using the table below. A + * stop character, which is a second asterisk character. + */ +function barcode_code93_encode($barnumber, $settings) { + $enc_table = array( + "0" => "100010100", + "1" => "101001000", + "2" => "101000100", + "3" => "101000010", + "4" => "100101000", + "5" => "100100100", + "6" => "100100010", + "7" => "101010000", + "8" => "100010010", + "9" => "100001010", + "A" => "110101000", + "B" => "110100100", + "C" => "110100010", + "D" => "110010100", + "E" => "110010010", + "F" => "110001010", + "G" => "101101000", + "H" => "101100100", + "I" => "101100010", + "J" => "100110100", + "K" => "100011010", + "L" => "101011000", + "M" => "101001100", + "N" => "101000110", + "O" => "100101100", + "P" => "100010110", + "Q" => "110110100", + "R" => "110110010", + "S" => "110101100", + "T" => "110100110", + "U" => "110010110", + "V" => "110011010", + "W" => "101101100", + "X" => "101100110", + "Y" => "100110110", + "Z" => "100111010", + "-" => "100101110", + "." => "111010100", + " " => "111010010", + "$" => "111001010", + "/" => "101101110", + "+" => "101110110", + "%" => "110101110", + "$" => "100100110", + "%" => "111011010", + "/" => "111010110", + "+" => "100110010", + "*" => "101011110", + ); + + $mfc_str = ""; + $widebar = str_pad("", $settings->n2w, "1", STR_PAD_LEFT); + $widespc = str_pad("", $settings->n2w, "0", STR_PAD_LEFT); + + $arr_key = array_keys($enc_table); + /// calculating C And K + + for ($j = 0; $j < 2; $j++) { + $sum = 0; + for ($i = strlen($barnumber); $i > 0; $i--) { + $num = $barnumber[strlen($barnumber) - $i]; + if (preg_match("/[A-Z]+/", $num)) + $num = ord($num) - 55; + elseif ($num == '-') { + $num = 36; + } + elseif ($num == '.') { + $num = 37; + } + elseif ($num == ' ') { + $num = 38; + } + elseif ($num == '$') { + $num = 39; + } + elseif ($num == '/') { + $num = 40; + } + elseif ($num == '+') { + $num = 41; + } + elseif ($num == '%') { + $num = 42; + } + elseif ($num == '*') { + $num = 43; + } + + $sum += $i * $num; + } + $barnumber .= trim($arr_key[(int)($sum % 47)]); + } + + $barnumber = "*". $barnumber ."*"; + + for ($i = 0; $i < strlen($barnumber); $i++) { + $mfc_str .= $enc_table[$barnumber[$i]]; + } + $mfc_str .= '1'; + + return $mfc_str; +} diff --git a/sites/all/modules/barcode/plugins/ean.inc b/sites/all/modules/barcode/plugins/ean.inc new file mode 100644 index 0000000..5927d6d --- /dev/null +++ b/sites/all/modules/barcode/plugins/ean.inc @@ -0,0 +1,232 @@ +filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $scale = $settings->scale; + if ($scale < 1) { + $scale = 2; + } + + $total_y = (double)$scale * $settings->height; + $space = array( + 'top' => 2 * $scale, + 'bottom' => 2 * $scale, + 'left' => 2 * $scale, + 'right' => 2 * $scale, + ); + + /* count total width */ + $xpos = 0; + + $xpos = $scale * (114); + + /* allocate the image */ + $total_x = $xpos + $space['left'] + $space['right']; + $xpos = $space['left'] + ($scale * 6); + + $height = floor($total_y - ($scale * 10)); + $height2 = floor($total_y - $space['bottom']); + + $im = @imagecreatetruecolor($total_x, $total_y); + $bg_color = @imagecolorallocate($im, $settings->bgcolor[0], $settings->bgcolor[1], $settings->bgcolor[2]); + @imagefilledrectangle($im, 0, 0, $total_x, $total_y, $bg_color); + $bar_color = @imagecolorallocate($im, $settings->color[0], $settings->color[1], $settings->color[2]); + + for ($i = 0; $i < strlen($bars); $i++) { + $h = $height; + $val = strtoupper($bars[$i]); + if (preg_match("/[a-z]/i", $val)) { + $val = ord($val) - 65; + $h = $height2; + } + + if ($settings->encode == "UPC-A" && ($i < 10 || $i>strlen($bars) - 13)) { + $h = $height2; + } + + if ($val == 1) { + @imagefilledrectangle($im, $xpos, $space['top'], $xpos + $scale - 1, $h, $bar_color); + } + + $xpos += $scale; + } + + + if ($settings->encode == "UPC-A") { + $str = substr($barnumber, 1, 1); + } + else { + $str = substr($barnumber, 0, 1); + } + + @imagettftext($im, $scale * 6, 0, $space['left'], $height, $bar_color, $settings->font, $str); + + if ($settings->encode == "UPC-A") { + $str = substr($barnumber, 2, 5); + } + else { + $str = substr($barnumber, 1, 6); + } + + $x = $space['left'] + $scale * strlen($barnumber) + $scale * 6; + @imagettftext($im, $scale * 6, 0, $x, $height2, $bar_color, $settings->font, $str); + + if ($settings->encode == "UPC-A") { + $str = substr($barnumber, 7, 5); + } + else { + $str = substr($barnumber, 7, 6); + } + + $x = $space['left'] + $scale * strlen($bars) / 1.65 + $scale * 6; + @imagettftext($im, $scale * 6, 0, $x, $height2, $bar_color, $settings->font, $str); + + if ($settings->encode == "UPC-A") { + $str = substr($barnumber, 12, 1); + $x = $total_x - $space['left'] - $scale * 6; + @imagettftext($im, $scale * 6, 0, $x, $height, $bar_color, $settings->font, $str); + } + + if ($settings->format == "png") { + if (!empty($settings->filename_no_format)) { + @imagepng($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagepng($im); + } + } + + if ($settings->format == "gif") { + if (!empty($settings->filename_no_format)) { + @imagegif($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagegif($im); + } + } + + if ($settings->format == "jpg" || $settings->format == "jpeg") { + if (!empty($settings->filename_no_format)) { + @imagejpeg($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagejpeg($im); + } + } + + @imagedestroy($im); +} + +/* An EAN-13 barcode has the following physical structure: + * + * Left-hand guard bars, or start sentinel, encoded as 101. + * The second character of the number system code, encoded as described below. + * The five characters of the manufacturer code, encoded as described below. + * Center guard pattern, encoded as 01010. + * The five characters of the product code, encoded as right-hand characters, + * described below. + * Check digit, encoded as a right-hand character, described below. + * Right-hand guard bars, or end sentinel, encoded as 101. + * FIRST NUMBER + * + * SYSTEM DIGIT PARITY TO ENCODE WITH + * SECOND NUMBER + * SYSTEM DIGIT MANUFACTURER CODE CHARACTERS + * 1 2 3 4 5 + * 0 (UPC-A) Odd Odd Odd Odd Odd Odd + * 1 Odd Odd Even Odd Even Even + * 2 Odd Odd Even Even Odd Even + * 3 Odd Odd Even Even Even Odd + * 4 Odd Even Odd Odd Even Even + * 5 Odd Even Even Odd Odd Even + * 6 Odd Even Even Even Odd Odd + * 7 Odd Even Odd Even Odd Even + * 8 Odd Even Odd Even Even Odd + * 9 Odd Even Even Odd Even Odd + */ +function barcode_ean_encode($barnumber) { + $left_odd = array("0001101", "0011001", "0010011", "0111101", "0100011", "0110001", "0101111", "0111011", "0110111", "0001011"); + $left_even = array("0100111", "0110011", "0011011", "0100001", "0011101", "0111001", "0000101", "0010001", "0001001", "0010111"); + $right_all = array("1110010", "1100110", "1101100", "1000010", "1011100", "1001110", "1010000", "1000100", "1001000", "1110100"); + + $enc_table = array("000000", "001011", "001101", "001110", "010011", "011001", "011100", "010101", "010110", "011010"); + + $guards = array("bab", "ababa", "bab"); + + $mfc_str = ""; + $prod_str = ""; + + $encbit = $barnumber[0]; + + for ($i = 1; $i < strlen($barnumber); $i++) { + $num = (int)$barnumber{$i}; + if ($i < 7) { + $even = (substr($enc_table[$encbit], $i - 1, 1) == 1); + if (!$even) { + $mfc_str .= $left_odd[$num]; + } + else { + $mfc_str .= $left_even[$num]; + } + } + elseif ($i >= 7) { + $prod_str .= $right_all[$num]; + } + } + + return $guards[0] . $mfc_str . $guards[1] . $prod_str . $guards[2]; +} diff --git a/sites/all/modules/barcode/plugins/ean8.inc b/sites/all/modules/barcode/plugins/ean8.inc new file mode 100644 index 0000000..235896a --- /dev/null +++ b/sites/all/modules/barcode/plugins/ean8.inc @@ -0,0 +1,138 @@ +filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $scale = $settings->scale; + if ($scale < 1) { + $scale = 2; + } + + $total_y = (double)$scale * $settings->height; + + $space = array( + 'top' => 2 * $scale, + 'bottom' => 2 * $scale, + 'left' => 2 * $scale, + 'right' => 2 * $scale, + ); + + /* count total width */ + $xpos = 0; + + $xpos = $scale * strlen($bars); + + /* allocate the image */ + $total_x = $xpos + $space['left'] + $space['right']; + $xpos = $space['left']; + + $height = floor($total_y - ($scale * 10)); + $height2 = floor($total_y - $space['bottom']); + + $im =@imagecreatetruecolor($total_x, $total_y); + $bg_color = @imagecolorallocate($im, $settings->bgcolor[0], $settings->bgcolor[1], $settings->bgcolor[2]); + @imagefilledrectangle($im, 0, 0, $total_x, $total_y, $bg_color); + $bar_color = @imagecolorallocate($im, $settings->color[0], $settings->color[1], $settings->color[2]); + + for ($i = 0; $i < strlen($bars); $i++) { + $h = $height; + $val = strtoupper($bars[$i]); + if (preg_match("/[a-z]/i", $val)) { + $val = ord($val) - 65; + $h = $height2; + } + + if ($val == 1) { + @imagefilledrectangle($im, $xpos, $space['top'], $xpos + $scale - 1, $h, $bar_color); + } + + $xpos += $scale; + } + + $str = substr($barnumber, 0, 4); + $x = $space['left'] + $scale * strlen($barnumber); + @imagettftext($im, $scale * 6, 0, $x, $height2, $bar_color, $settings->font, $str); + + $str = substr($barnumber, 4, 4); + $x = $space['left'] + $scale * strlen($bars) / 1.65; + @imagettftext($im, $scale * 6, 0, $x, $height2, $bar_color, $settings->font, $str); + + if ($settings->format == "png") { + if (!empty($settings->filename_no_format)) { + @imagepng($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagepng($im); + } + } + + if ($settings->format == "gif") { + if (!empty($settings->filename_no_format)) { + @imagegif($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagegif($im); + } + } + + if ($settings->format == "jpg" || $settings->format == "jpeg" ) { + if (!empty($settings->filename_no_format)) { + @imagejpeg($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagejpeg($im); + } + } + + @imagedestroy($im); +} + +/* An EAN-8 barcode has the following physical structure: + * + * Left-hand guard bars, or start sentinel, encoded as 101. + * Two number system characters, encoded as left-hand odd-parity characters. + * First two message characters, encoded as left-hand odd-parity characters. + * Center guard bars, encoded as 01010. + * Last three message characters, encoded as right-hand characters. + * Check digit, encoded as right-hand character. + * Right-hand guar bars, or end sentinel, encoded as 101. + */ +function barcode_ean8_encode($barnumber) { + $left_odd = array("0001101", "0011001", "0010011", "0111101", "0100011", "0110001", "0101111", "0111011", "0110111", "0001011"); + $left_even = array("0100111", "0110011", "0011011", "0100001", "0011101", "0111001", "0000101", "0010001", "0001001", "0010111"); + $right_all = array("1110010", "1100110", "1101100", "1000010", "1011100", "1001110", "1010000", "1000100", "1001000", "1110100"); + + $enc_table = array("000000", "001011", "001101", "001110", "010011", "011001", "011100", "010101", "010110", "011010"); + + $guards=array("bab", "ababa", "bab"); + + $mfc_str = ""; + $prod_str = ""; + + for ($i = 0; $i < strlen($barnumber); $i++) { + $num = (int)$barnumber{$i}; + if ($i < 4) { + $mfc_str .= $left_odd[$num]; + } + elseif ($i >= 4) { + $prod_str .= $right_all[$num]; + } + } + + return $guards[0] . $mfc_str . $guards[1] . $prod_str . $guards[2]; +} diff --git a/sites/all/modules/barcode/plugins/i25.inc b/sites/all/modules/barcode/plugins/i25.inc new file mode 100644 index 0000000..4edb1cd --- /dev/null +++ b/sites/all/modules/barcode/plugins/i25.inc @@ -0,0 +1,149 @@ +filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $scale = $settings->scale; + if ($scale < 1) { + $scale = 2; + } + + $total_y = (double)$scale * $settings->height; + + $space = array( + 'top' => 2 * $scale, + 'bottom' => 2 * $scale, + 'left' => 2 * $scale, + 'right' => 2 * $scale + ); + + /* count total width */ + $xpos = 0; + + $xpos = $scale * strlen($bars); + + /* allocate the image */ + $total_x = $xpos + $space['left'] + $space['right']; + $xpos = $space['left']; + + $height = floor($total_y - ($scale * 10)); + $height2 = floor($total_y - $space['bottom']); + + $im = @imagecreatetruecolor($total_x, $total_y); + $bg_color = @imagecolorallocate($im, $settings->bgcolor[0], $settings->bgcolor[1], $settings->bgcolor[2]); + @imagefilledrectangle($im, 0, 0, $total_x, $total_y, $bg_color); + $bar_color = @imagecolorallocate($im, $settings->color[0], $settings->color[1], $settings->color[2]); + + for ($i = 0; $i < strlen($bars); $i++) { + $h = $height; + $val = strtoupper($bars[$i]); + + if ($val == 1) { + @imagefilledrectangle($im, $xpos, $space['top'], $xpos+$scale - 1, $h, $bar_color); + } + + $xpos+=$scale; + } + + $x = ($total_x - strlen($bars)) / 2; + @imagettftext($im, $scale * 6, 0, $x, $height2, $bar_color, $settings->font, $barnumber); + + if ($settings->format == "png") { + if (!empty($settings->filename_no_format)) { + @imagepng($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagepng($im); + } + } + + if ($settings->format=="gif") { + if (!empty($settings->filename_no_format)) { + @imagegif($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagegif($im); + } + } + + if ($settings->format == "jpg" || $settings->format == "jpeg" ) { + if (!empty($settings->filename_no_format)) { + @imagejpeg($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagejpeg($im); + } + } + + @imagedestroy($im); +} + +/* A Standard 2 of 5 barcode has the following physical structure: + * + * Start character, encoded as 11011010. + * Data characters properly encoded (see encoding table below). + * Stop character, encoded as 11010110. + * + * ASCII BARCODE + * 0 NNWWN + * 1 WNNNW + * 2 NWNNW + * 3 WWNNN + * 4 NNWNW + * 5 WNWNN + * 6 NWWNN + * 7 NNNWW + * 8 WNNWN + * 9 NWNWN + */ +function barcode_i25_encode($barnumber, $settings) { + $enc_table=array("NNWWN", "WNNNW", "NWNNW", "WWNNN", "NNWNW", "WNWNN", "NWWNN", "NNNWW", "WNNWN", "NWNWN"); + $guards=array("1010", "1101"); + + $len=strlen($barnumber); + if ($len % 2 != 0) { + $barnumber = barcode_check_digit($barnumber, $len); + if ($len == strlen($barnumber) && substr($barnumber, -1) != '0') { + $barnumber .= '0'; + } + } + + $mfc_str = ""; + + $widebar = str_pad("", $settings->n2w, "1", STR_PAD_LEFT); + $widespc = str_pad("", $settings->n2w, "0", STR_PAD_LEFT); + + for ($i = 0; $i < strlen($barnumber); $i += 2) { + $tmp = $enc_table[(int)$barnumber[$i]]; + $tmp1 = $enc_table[(int)$barnumber[$i+1]]; + for ($j = 0; $j < strlen($tmp); $j++) { + if ($tmp[$j]=='N') { + $mfc_str .= '1'; + } + else { + $mfc_str .= $widebar; + } + + if ($tmp1[$j]=='N') { + $mfc_str .= '0'; + } + else { + $mfc_str .= $widespc; + } + } + } + + return $guards[0] . $mfc_str . $guards[1]; +} + diff --git a/sites/all/modules/barcode/plugins/postnet.inc b/sites/all/modules/barcode/plugins/postnet.inc new file mode 100644 index 0000000..08b2674 --- /dev/null +++ b/sites/all/modules/barcode/plugins/postnet.inc @@ -0,0 +1,126 @@ +filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $scale = $settings->scale; + if ($scale < 1) { + $scale = 2; + } + + $total_y = (double)$scale * $settings->height; + $space = array( + 'top' => 2 * $scale, + 'bottom' => 2 * $scale, + 'left' => 2 * $scale, + 'right' => 2 * $scale + ); + + /* count total width */ + $xpos = 0; + + $xpos = $scale * strlen($bars) * 2; + + /* allocate the image */ + $total_x = $xpos + $space['left'] + $space['right']; + $xpos = $space['left']; + + $height = floor($total_y - ($scale * 10)); + $height2 = floor($total_y - $space['bottom']); + + $im = @imagecreatetruecolor($total_x, $total_y); + $bg_color = @imagecolorallocate($im, $settings->bgcolor[0], $settings->bgcolor[1], $settings->bgcolor[2]); + @imagefilledrectangle($im, 0, 0, $total_x, $total_y, $bg_color); + $bar_color = @imagecolorallocate($im, $settings->color[0], $settings->color[1], $settings->color[2]); + + for ($i = 0; $i < strlen($bars); $i++) { + $val = strtoupper($bars[$i]); + $h = $total_y - $space['bottom']; + + if ($val == 1) { + @imagefilledrectangle($im, $xpos, $space['top'], $xpos + $scale - 1, $height2, $bar_color); + } + else { + @imagefilledrectangle($im, $xpos, floor($height2 / 1.5), $xpos + $scale - 1, $height2, $bar_color); + } + + $xpos += 2 * $scale; + } + + if ($settings->format == "png") { + if (!empty($settings->filename_no_format)) { + @imagepng($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagepng($im); + } + } + + if ($settings->format == "gif") { + if (!empty($settings->filename_no_format)) { + @imagegif($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagegif($im); + } + } + + if ($settings->format == "jpg" || $settings->format == "jpeg" ) { + if (!empty($settings->filename_no_format)) { + @imagejpeg($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagejpeg($im); + } + } + + @imagedestroy($im); +} + +/* + * A PostNet barcode has the following structure: + * + * Frame bar, encoded as a single 1. + * 5, 9, or 11 data characters properly encoded (see encoding table below). + * Check digit, encoded using encoding table below. + * Final frame bar, encoded as a single 1. + * + * 0 11000 + * 1 00011 + * 2 00101 + * 3 00110 + * 4 01001 + * 5 01010 + * 6 01100 + * 7 10001 + * 8 10010 + * 9 10100 + */ +function barcode_postnet_encode($barnumber, $settings) { + $enc_table = array("11000", "00011", "00101", "00110", "01001", "01010", "01100", "10001", "10010", "10100"); + + $sum = 0; + $encstr = ""; + for ($i = 0; $i < strlen($barnumber); $i++) { + $sum += (int)$barnumber[$i]; + $encstr .= $enc_table[(int)$barnumber[$i]]; + } + + if ($sum % 10 != 0) { + $check = (int)(10 - ($sum % 10)); + } + + $encstr .= $enc_table[$check]; + $encstr = "1" . $encstr . "1"; + return $encstr; +} diff --git a/sites/all/modules/barcode/plugins/qrcode.inc b/sites/all/modules/barcode/plugins/qrcode.inc new file mode 100755 index 0000000..61de8f0 --- /dev/null +++ b/sites/all/modules/barcode/plugins/qrcode.inc @@ -0,0 +1,40 @@ +filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $h = $settings->height; + $name = md5($barnumber); + $content = urlencode($barnumber); + $url = 'http://chart.apis.google.com/chart?chs=' . $h . 'x' . $h . '&cht=qr&chl=' . $content; + $img = $settings->default_path .'/'. $name . $settings->encode .'.'. $settings->format; + + // file_put_contents($img, file_get_contents($url)); + + /**Added by H. **/ + $headers = array( + "Expect:", + // more headers here + ); + $curl_handle=curl_init(); + curl_setopt($curl_handle, CURLOPT_URL, $url); + curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2); + curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl_handle, CURLOPT_USERAGENT, 'Drupal'); + curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $headers); + $query = curl_exec($curl_handle); + curl_close($curl_handle); + + file_put_contents($img, $query); +} + +function barcode_qrcode_max_length($encoding) { + return 8192; +} diff --git a/sites/all/modules/barcode/plugins/s2o5.inc b/sites/all/modules/barcode/plugins/s2o5.inc new file mode 100644 index 0000000..7683751 --- /dev/null +++ b/sites/all/modules/barcode/plugins/s2o5.inc @@ -0,0 +1,133 @@ +filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $scale = $settings->scale; + if ($scale < 1) { + $scale = 2; + } + + $total_y = (double)$scale * $settings->height; + $space = array( + 'top' => 2 * $scale, + 'bottom' => 2 * $scale, + 'left' => 2 * $scale, + 'right' => 2 * $scale + ); + + /* count total width */ + $xpos = $scale * strlen($bars); + + /* allocate the image */ + $total_x = $xpos + $space['left'] + $space['right']; + $xpos = $space['left']; + + $height = floor($total_y - ($scale * 10)); + $height2 = floor($total_y - $space['bottom']); + + $im = @imagecreatetruecolor($total_x, $total_y); + $bg_color = @imagecolorallocate($im, $settings->bgcolor[0], $settings->bgcolor[1], $settings->bgcolor[2]); + @imagefilledrectangle($im, 0, 0, $total_x, $total_y, $bg_color); + $bar_color = @imagecolorallocate($im, $settings->color[0], $settings->color[1], $settings->color[2]); + + for ($i = 0; $i < strlen($bars); $i++) { + $h = $height; + $val = strtoupper($bars[$i]); + + if ($val == 1) { + @imagefilledrectangle($im, $xpos, $space['top'], $xpos + $scale - 1, $h, $bar_color); + } + + $xpos += $scale; + } + + $x = ($total_x - strlen($bars)) / 2; + @imagettftext($im, $scale * 6, 0, $x, $height2, $bar_color, $settings->font, $barnumber); + + if ($settings->format == "png") { + if (!empty($settings->filename_no_format)) { + @imagepng($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagepng($im); + } + } + + if ($settings->format == "gif") { + if (!empty($settings->filename_no_format)) { + @imagegif($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagegif($im); + } + } + + if ($settings->format == "jpg" || $settings->format == "jpeg" ) { + if (!empty($settings->filename_no_format)) { + @imagejpeg($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagejpeg($im); + } + } + + @imagedestroy($im); +} + +/* A Standard 2 of 5 barcode has the following physical structure: + * + * Start character, encoded as 11011010. + * Data characters properly encoded (see encoding table below). + * Stop character, encoded as 11010110. + * + * ASCII BARCODE + * 0 NNWWN + * 1 WNNNW + * 2 NWNNW + * 3 WWNNN + * 4 NNWNW + * 5 WNWNN + * 6 NWWNN + * 7 NNNWW + * 8 WNNWN + * 9 NWNWN + */ +function barcode_s2o5_encode($barnumber, $settings) { + $enc_table = array("NNWWN", "WNNNW", "NWNNW", "WWNNN", "NNWNW", "WNWNN", "NWWNN", "NNNWW", "WNNWN", "NWNWN"); + $guards = array("11011010", "1101011"); + + $len = strlen($barnumber); + $barnumber = barcode_check_digit($barnumber, $len); + if ($len == strlen($barnumber) && substr($barnumber, -1) != '0') { + $barnumber .= '0'; + } + + $mfc_str = ""; + + $widebar = str_pad("", $settings->n2w, "1", STR_PAD_LEFT); + $widebar .= "0"; + + for ($i = 0; $i < strlen($barnumber); $i++) { + $num = (int)$barnumber{$i}; + $str = ""; + $str = str_replace("N", "10", $enc_table[$num]); + $str = str_replace("W", $widebar, $str); + $mfc_str .= $str; + } + + return $guards[0] . $mfc_str . $guards[1]; +} + + diff --git a/sites/all/modules/barcode/plugins/upce.inc b/sites/all/modules/barcode/plugins/upce.inc new file mode 100644 index 0000000..dca7a33 --- /dev/null +++ b/sites/all/modules/barcode/plugins/upce.inc @@ -0,0 +1,190 @@ +6) { + barcode_load_plugin('ean'); + barcode_ean13_check_digit($barnumber); + $barnumber = substr($this->barcode_ean13_check_digit($barnumber), 1); + $encbit = $barnumber[0]; + $checkdigit = $barnumber[11]; + $barnumber = barcode_convert_upca_to_upce($barnumber, $settings); + } + else { + $barnumber = barcode_check_digit($barnumber, 7); + $encbit = $barnumber[0]; + $checkdigit = $barnumber[7]; + $barnumber = substr($barnumber, 1, 6); + } + + $bars = barcode_upce_encode($barnumber, $settings, $encbit, $checkdigit); + + if (empty($settings->filename_no_format)) { + header("Content-type: image/". $settings->format); + } + + $scale = $settings->scale; + if ($scale < 1) { + $scale = 2; + } + + $total_y = (double)$scale * $settings->height; + $space = array( + 'top' => 2 * $scale, + 'bottom' => 2 * $scale, + 'left' => 2 * $scale, + 'right' => 2 * $scale + ); + + /* count total width */ + $xpos=$scale*strlen($bars)+$scale*12; + + /* allocate the image */ + $total_x = $xpos + $space['left'] + $space['right']; + $xpos = $space['left'] + ($scale * 6); + + $height = floor($total_y - ($scale * 10)); + $height2 = floor($total_y - $space['bottom']); + + $im = @imagecreatetruecolor($total_x, $total_y); + $bg_color = @imagecolorallocate($im, $settings->bgcolor[0], $settings->bgcolor[1], $settings->bgcolor[2]); + @imagefilledrectangle($im, 0, 0, $total_x, $total_y, $bg_color); + $bar_color = @imagecolorallocate($im, $settings->color[0], $settings->color[1], $settings->color[2]); + + for ($i=0; $i < strlen($bars); $i++) { + $h = $height; + $val = strtoupper($bars[$i]); + if (preg_match("/[a-z]/i", $val)) { + $val = ord($val) - 65; + $h = $height2; + } + + if ($val == 1) { + @imagefilledrectangle($im, $xpos, $space['top'], $xpos + $scale - 1, $h, $bar_color); + } + + $xpos += $scale; + } + + @imagettftext($im, $scale * 6, 0, $space['left'], $height, $bar_color, $settings->font, $encbit); + + $x = $space['left'] + $scale * strlen($barnumber) + $scale * 6; + @imagettftext($im, $scale * 6, 0, $x, $height2, $bar_color, $settings->font, $barnumber); + + $x = $total_x - $space['left'] - $scale * 6; + @imagettftext($im, $scale * 6, 0, $x, $height, $bar_color, $settings->font, $checkdigit); + + if ($settings->format == "png") { + if (!empty($settings->filename_no_format)) { + @imagepng($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagepng($im); + } + } + + if ($settings->format=="gif") { + if (!empty($settings->filename_no_format)) { + @imagegif($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagegif($im); + } + } + + if ($settings->format == "jpg" || $settings->format == "jpeg") { + if (!empty($settings->filename_no_format)) { + @imagejpeg($im, $settings->filename_no_format .".". $settings->format); + } + else { + @imagejpeg($im); + } + } + + @imagedestroy($im); +} + +function barcode_upce_encode($barnumber, $settings, $encbit, $checkdigit) { + $left_odd = array("0001101", "0011001", "0010011", "0111101", "0100011", "0110001", "0101111", "0111011", "0110111", "0001011"); + $left_even=array("0100111", "0110011", "0011011", "0100001", "0011101", "0111001", "0000101", "0010001", "0001001", "0010111"); + + $enc_table0=array("EEEOOO", "EEOEOO", "EEOOEO", "EEOOOE", "EOEEOO", "EOOEEO", "EOOOEE", "EOEOEO", "EOEOOE", "EOOEOE"); + $enc_table1=array("OOOEEE", "OOEOEE", "OOEEOE", "OOEEEO", "OEOOEE", "OEEOOE", "OEEEOO", "OEOEOE", "OEOEEO", "OEEOEO"); + + $guards=array("bab", "ababa", "b"); + + if ($encbit == 0) { + $enc_table = $enc_table0; + } + elseif ($encbit == 1) { + $enc_table = $enc_table1; + } + else { + $settings->error = "Not an UPC-E barcode number"; + return FALSE; + } + + $mfc_str = ""; + $prod_str = ""; + $checkdigit; + $enc_table[$checkdigit]; + + for ($i = 0; $i < strlen($barnumber); $i++) { + $num = (int)$barnumber{$i}; + $even = (substr($enc_table[$checkdigit], $i, 1) == 'E'); + if (!$even) { + $mfc_str .= $left_odd[$num]; + } + else { + $mfc_str .= $left_even[$num]; + } + } + + return $guards[0] . $mfc_str . $guards[1] . $guards[2]; +} + +// @todo handle error +function barcode_convert_upca_to_upce($upca, &$settings) { + $upce = ""; + + // If the source message string is less than 12 characters long, we make it + // 12 characters + if (strlen($upca) < 12) { + $upca = str_pad($upca, 12, "0", STR_PAD_LEFT); + } + + if (substr($upca, 0, 1) != '0' && substr($upca, 0, 1) != '1') { + $settings->error = 'Invalid Number System (only 0 & 1 are valid)'; + return FALSE; + } + else { + if (substr($upca, 3, 3) == '000' || substr($upca, 3, 3) == '100' || substr($upca, 3, 3) == '200') { + $upce = substr($upca, 1, 2) . substr($upca, 8, 3) . substr($upca, 3, 1); + } + elseif (substr($upca, 4, 2) == '00') { + $upce = substr($upca, 1, 2) . substr($upca, 9, 2) .'3'; + } + elseif (substr($upca, 5, 1) == '0') { + $upce = substr($upca, 1, 4) . substr($upca, 10, 1) .'4'; + } + elseif (substr($upca, 10, 1) >= '5') { + $upce = substr($upca, 1, 5) . substr($upca, 10, 1); + } + else { + $settings->error = 'Invalid product code (00005 to 00009 are valid)'; + return FALSE; + } + } + + return $upce; +} +