slitaz-forge rev 355
chub, pro, tank: add qrcode pseudo link
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Mon Mar 25 18:45:42 2013 +0100 (2013-03-25) |
parents | 57d3af1446c3 |
children | ced643b618ba |
files | chub/web/lib/html/footer.html chub/web/lib/html/qrcode.js pro/lib/html/footer.html pro/lib/html/footer.ru.html pro/lib/html/qrcode.js tank/web/lib/html/footer.html tank/web/lib/html/qrcode.js |
line diff
1.1 --- a/chub/web/lib/html/footer.html Mon Mar 25 18:34:38 2013 +0100 1.2 +++ b/chub/web/lib/html/footer.html Mon Mar 25 18:45:42 2013 +0100 1.3 @@ -1,4 +1,7 @@ 1.4 <!-- Footer --> 1.5 + 1.6 +<script type="text/javascript" src="qrcode.js"></script> 1.7 + 1.8 <div id="footer"> 1.9 Copyright © <span class="year"></span> 1.10 <a href="http://www.slitaz.org/">SliTaz</a> - Network: 1.11 @@ -7,9 +10,10 @@ 1.12 <a href="http://forum.slitaz.org/">Forum</a> 1.13 <a href="http://pkgs.slitaz.org/">Packages</a> 1.14 <a href="http://bugs.slitaz.org">Bugs</a> 1.15 - <a href="http://hg.slitaz.org/">Hg</a> 1.16 + <a href="http://hg.slitaz.org/?sort=lastchange">Hg</a> 1.17 <p> 1.18 - SliTaz @ 1.19 + <img src="#" alt="SliTaz @" onmouseover="this.title = location.href" 1.20 + onclick="this.src = QRCode.generatePNG(location.href, {ecclevel: 'H'})" /> 1.21 <a href="http://twitter.com/slitaz">Twitter</a> 1.22 <a href="http://www.facebook.com/slitaz">Facebook</a> 1.23 <a href="http://distrowatch.com/slitaz">Distrowatch</a>
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/chub/web/lib/html/qrcode.js Mon Mar 25 18:45:42 2013 +0100 2.3 @@ -0,0 +1,733 @@ 2.4 +/* qr.js -- QR code generator in Javascript (revision 2011-01-19) 2.5 + * Written by Kang Seonghoon <public+qrjs@mearie.org>. 2.6 + * 2.7 + * This source code is in the public domain; if your jurisdiction does not 2.8 + * recognize the public domain the terms of Creative Commons CC0 license 2.9 + * apply. In the other words, you can always do what you want. 2.10 + */ 2.11 + 2.12 +var QRCode = (function(){ 2.13 + 2.14 +/* Quick overview: QR code composed of 2D array of modules (a rectangular 2.15 + * area that conveys one bit of information); some modules are fixed to help 2.16 + * the recognition of the code, and remaining data modules are further divided 2.17 + * into 8-bit code words which are augumented by Reed-Solomon error correcting 2.18 + * codes (ECC). There could be multiple ECCs, in the case the code is so large 2.19 + * that it is helpful to split the raw data into several chunks. 2.20 + * 2.21 + * The number of modules is determined by the code's "version", ranging from 1 2.22 + * (21x21) to 40 (177x177). How many ECC bits are used is determined by the 2.23 + * ECC level (L/M/Q/H). The number and size (and thus the order of generator 2.24 + * polynomial) of ECCs depend to the version and ECC level. 2.25 + */ 2.26 + 2.27 +// per-version information (cf. JIS X 0510:2004 pp. 30--36, 71) 2.28 +// 2.29 +// [0]: the degree of generator polynomial by ECC levels 2.30 +// [1]: # of code blocks by ECC levels 2.31 +// [2]: left-top positions of alignment patterns 2.32 +// 2.33 +// the number in this table (in particular, [0]) does not exactly match with 2.34 +// the numbers in the specficiation. see augumenteccs below for the reason. 2.35 +var VERSIONS = [ 2.36 + null, 2.37 + [[10, 7,17,13], [ 1, 1, 1, 1], []], 2.38 + [[16,10,28,22], [ 1, 1, 1, 1], [4,16]], 2.39 + [[26,15,22,18], [ 1, 1, 2, 2], [4,20]], 2.40 + [[18,20,16,26], [ 2, 1, 4, 2], [4,24]], 2.41 + [[24,26,22,18], [ 2, 1, 4, 4], [4,28]], 2.42 + [[16,18,28,24], [ 4, 2, 4, 4], [4,32]], 2.43 + [[18,20,26,18], [ 4, 2, 5, 6], [4,20,36]], 2.44 + [[22,24,26,22], [ 4, 2, 6, 6], [4,22,40]], 2.45 + [[22,30,24,20], [ 5, 2, 8, 8], [4,24,44]], 2.46 + [[26,18,28,24], [ 5, 4, 8, 8], [4,26,48]], 2.47 + [[30,20,24,28], [ 5, 4,11, 8], [4,28,52]], 2.48 + [[22,24,28,26], [ 8, 4,11,10], [4,30,56]], 2.49 + [[22,26,22,24], [ 9, 4,16,12], [4,32,60]], 2.50 + [[24,30,24,20], [ 9, 4,16,16], [4,24,44,64]], 2.51 + [[24,22,24,30], [10, 6,18,12], [4,24,46,68]], 2.52 + [[28,24,30,24], [10, 6,16,17], [4,24,48,72]], 2.53 + [[28,28,28,28], [11, 6,19,16], [4,28,52,76]], 2.54 + [[26,30,28,28], [13, 6,21,18], [4,28,54,80]], 2.55 + [[26,28,26,26], [14, 7,25,21], [4,28,56,84]], 2.56 + [[26,28,28,30], [16, 8,25,20], [4,32,60,88]], 2.57 + [[26,28,30,28], [17, 8,25,23], [4,26,48,70,92]], 2.58 + [[28,28,24,30], [17, 9,34,23], [4,24,48,72,96]], 2.59 + [[28,30,30,30], [18, 9,30,25], [4,28,52,76,100]], 2.60 + [[28,30,30,30], [20,10,32,27], [4,26,52,78,104]], 2.61 + [[28,26,30,30], [21,12,35,29], [4,30,56,82,108]], 2.62 + [[28,28,30,28], [23,12,37,34], [4,28,56,84,112]], 2.63 + [[28,30,30,30], [25,12,40,34], [4,32,60,88,116]], 2.64 + [[28,30,30,30], [26,13,42,35], [4,24,48,72,96,120]], 2.65 + [[28,30,30,30], [28,14,45,38], [4,28,52,76,100,124]], 2.66 + [[28,30,30,30], [29,15,48,40], [4,24,50,76,102,128]], 2.67 + [[28,30,30,30], [31,16,51,43], [4,28,54,80,106,132]], 2.68 + [[28,30,30,30], [33,17,54,45], [4,32,58,84,110,136]], 2.69 + [[28,30,30,30], [35,18,57,48], [4,28,56,84,112,140]], 2.70 + [[28,30,30,30], [37,19,60,51], [4,32,60,88,116,144]], 2.71 + [[28,30,30,30], [38,19,63,53], [4,28,52,76,100,124,148]], 2.72 + [[28,30,30,30], [40,20,66,56], [4,22,48,74,100,126,152]], 2.73 + [[28,30,30,30], [43,21,70,59], [4,26,52,78,104,130,156]], 2.74 + [[28,30,30,30], [45,22,74,62], [4,30,56,82,108,134,160]], 2.75 + [[28,30,30,30], [47,24,77,65], [4,24,52,80,108,136,164]], 2.76 + [[28,30,30,30], [49,25,81,68], [4,28,56,84,112,140,168]]]; 2.77 + 2.78 +// mode constants (cf. Table 2 in JIS X 0510:2004 p. 16) 2.79 +var MODE_TERMINATOR = 0; 2.80 +var MODE_NUMERIC = 1, MODE_ALPHANUMERIC = 2, MODE_OCTET = 4, MODE_KANJI = 8; 2.81 + 2.82 +// validation regexps 2.83 +var NUMERIC_REGEXP = /^\d*$/; 2.84 +var ALPHANUMERIC_REGEXP = /^[A-Za-z0-9 $%*+\-./:]*$/; 2.85 +var ALPHANUMERIC_OUT_REGEXP = /^[A-Z0-9 $%*+\-./:]*$/; 2.86 + 2.87 +// ECC levels (cf. Table 22 in JIS X 0510:2004 p. 45) 2.88 +var ECCLEVEL_L = 1, ECCLEVEL_M = 0, ECCLEVEL_Q = 3, ECCLEVEL_H = 2; 2.89 + 2.90 +// GF(2^8)-to-integer mapping with a reducing polynomial x^8+x^4+x^3+x^2+1 2.91 +// invariant: GF256_MAP[GF256_INVMAP[i]] == i for all i in [1,256) 2.92 +var GF256_MAP = [], GF256_INVMAP = [-1]; 2.93 +for (var i = 0, v = 1; i < 255; ++i) { 2.94 + GF256_MAP.push(v); 2.95 + GF256_INVMAP[v] = i; 2.96 + v = (v * 2) ^ (v >= 128 ? 0x11d : 0); 2.97 +} 2.98 + 2.99 +// generator polynomials up to degree 30 2.100 +// (should match with polynomials in JIS X 0510:2004 Appendix A) 2.101 +// 2.102 +// generator polynomial of degree K is product of (x-\alpha^0), (x-\alpha^1), 2.103 +// ..., (x-\alpha^(K-1)). by convention, we omit the K-th coefficient (always 1) 2.104 +// from the result; also other coefficients are written in terms of the exponent 2.105 +// to \alpha to avoid the redundant calculation. (see also calculateecc below.) 2.106 +var GF256_GENPOLY = [[]]; 2.107 +for (var i = 0; i < 30; ++i) { 2.108 + var prevpoly = GF256_GENPOLY[i], poly = []; 2.109 + for (var j = 0; j <= i; ++j) { 2.110 + var a = (j < i ? GF256_MAP[prevpoly[j]] : 0); 2.111 + var b = GF256_MAP[(i + (prevpoly[j-1] || 0)) % 255]; 2.112 + poly.push(GF256_INVMAP[a ^ b]); 2.113 + } 2.114 + GF256_GENPOLY.push(poly); 2.115 +} 2.116 + 2.117 +// alphanumeric character mapping (cf. Table 5 in JIS X 0510:2004 p. 19) 2.118 +var ALPHANUMERIC_MAP = {}; 2.119 +for (var i = 0; i < 45; ++i) { 2.120 + ALPHANUMERIC_MAP['0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'.charAt(i)] = i; 2.121 +} 2.122 + 2.123 +// mask functions in terms of row # and column # 2.124 +// (cf. Table 20 in JIS X 0510:2004 p. 42) 2.125 +var MASKFUNCS = [ 2.126 + function(i,j) { return (i+j) % 2 == 0; }, 2.127 + function(i,j) { return i % 2 == 0; }, 2.128 + function(i,j) { return j % 3 == 0; }, 2.129 + function(i,j) { return (i+j) % 3 == 0; }, 2.130 + function(i,j) { return (((i/2)|0) + ((j/3)|0)) % 2 == 0; }, 2.131 + function(i,j) { return (i*j) % 2 + (i*j) % 3 == 0; }, 2.132 + function(i,j) { return ((i*j) % 2 + (i*j) % 3) % 2 == 0; }, 2.133 + function(i,j) { return ((i+j) % 2 + (i*j) % 3) % 2 == 0; }]; 2.134 + 2.135 +// returns true when the version information has to be embeded. 2.136 +var needsverinfo = function(ver) { return ver > 6; }; 2.137 + 2.138 +// returns the size of entire QR code for given version. 2.139 +var getsizebyver = function(ver) { return 4 * ver + 17; }; 2.140 + 2.141 +// returns the number of bits available for code words in this version. 2.142 +var nfullbits = function(ver) { 2.143 + /* 2.144 + * |<--------------- n --------------->| 2.145 + * | |<----- n-17 ---->| | 2.146 + * +-------+ ///+-------+ ---- 2.147 + * | | ///| | ^ 2.148 + * | 9x9 | @@@@@ ///| 9x8 | | 2.149 + * | | # # # @5x5@ # # # | | | 2.150 + * +-------+ @@@@@ +-------+ | 2.151 + * # ---| 2.152 + * ^ | 2.153 + * # | 2.154 + * @@@@@ @@@@@ @@@@@ | n 2.155 + * @5x5@ @5x5@ @5x5@ n-17 2.156 + * @@@@@ @@@@@ @@@@@ | | 2.157 + * # | | 2.158 + * ////// v | 2.159 + * //////# ---| 2.160 + * +-------+ @@@@@ @@@@@ | 2.161 + * | | @5x5@ @5x5@ | 2.162 + * | 8x9 | @@@@@ @@@@@ | 2.163 + * | | v 2.164 + * +-------+ ---- 2.165 + * 2.166 + * when the entire code has n^2 modules and there are m^2-3 alignment 2.167 + * patterns, we have: 2.168 + * - 225 (= 9x9 + 9x8 + 8x9) modules for finder patterns and 2.169 + * format information; 2.170 + * - 2n-34 (= 2(n-17)) modules for timing patterns; 2.171 + * - 36 (= 3x6 + 6x3) modules for version information, if any; 2.172 + * - 25m^2-75 (= (m^2-3)(5x5)) modules for alignment patterns 2.173 + * if any, but 10m-20 (= 2(m-2)x5) of them overlaps with 2.174 + * timing patterns. 2.175 + */ 2.176 + var v = VERSIONS[ver]; 2.177 + var nbits = 16*ver*ver + 128*ver + 64; // finder, timing and format info. 2.178 + if (needsverinfo(ver)) nbits -= 36; // version information 2.179 + if (v[2].length) { // alignment patterns 2.180 + nbits -= 25 * v[2].length * v[2].length - 10 * v[2].length - 55; 2.181 + } 2.182 + return nbits; 2.183 +}; 2.184 + 2.185 +// returns the number of bits available for data portions (i.e. excludes ECC 2.186 +// bits but includes mode and length bits) in this version and ECC level. 2.187 +var ndatabits = function(ver, ecclevel) { 2.188 + var nbits = nfullbits(ver) & ~7; // no sub-octet code words 2.189 + var v = VERSIONS[ver]; 2.190 + nbits -= 8 * v[0][ecclevel] * v[1][ecclevel]; // ecc bits 2.191 + return nbits; 2.192 +} 2.193 + 2.194 +// returns the number of bits required for the length of data. 2.195 +// (cf. Table 3 in JIS X 0510:2004 p. 16) 2.196 +var ndatalenbits = function(ver, mode) { 2.197 + switch (mode) { 2.198 + case MODE_NUMERIC: return (ver < 10 ? 10 : ver < 27 ? 12 : 14); 2.199 + case MODE_ALPHANUMERIC: return (ver < 10 ? 9 : ver < 27 ? 11 : 13); 2.200 + case MODE_OCTET: return (ver < 10 ? 8 : 16); 2.201 + case MODE_KANJI: return (ver < 10 ? 8 : ver < 27 ? 10 : 12); 2.202 + } 2.203 +}; 2.204 + 2.205 +// returns the maximum length of data possible in given configuration. 2.206 +var getmaxdatalen = function(ver, mode, ecclevel) { 2.207 + var nbits = ndatabits(ver, ecclevel) - 4 - ndatalenbits(ver, mode); // 4 for mode bits 2.208 + switch (mode) { 2.209 + case MODE_NUMERIC: 2.210 + return ((nbits/10) | 0) * 3 + (nbits%10 < 4 ? 0 : nbits%10 < 7 ? 1 : 2); 2.211 + case MODE_ALPHANUMERIC: 2.212 + return ((nbits/11) | 0) * 2 + (nbits%11 < 6 ? 0 : 1); 2.213 + case MODE_OCTET: 2.214 + return (nbits/8) | 0; 2.215 + case MODE_KANJI: 2.216 + return (nbits/13) | 0; 2.217 + } 2.218 +}; 2.219 + 2.220 +// checks if the given data can be encoded in given mode, and returns 2.221 +// the converted data for the further processing if possible. otherwise 2.222 +// returns null. 2.223 +// 2.224 +// this function does not check the length of data; it is a duty of 2.225 +// encode function below (as it depends on the version and ECC level too). 2.226 +var validatedata = function(mode, data) { 2.227 + switch (mode) { 2.228 + case MODE_NUMERIC: 2.229 + if (!data.match(NUMERIC_REGEXP)) return null; 2.230 + return data; 2.231 + 2.232 + case MODE_ALPHANUMERIC: 2.233 + if (!data.match(ALPHANUMERIC_REGEXP)) return null; 2.234 + return data.toUpperCase(); 2.235 + 2.236 + case MODE_OCTET: 2.237 + if (typeof data === 'string') { // encode as utf-8 string 2.238 + var newdata = []; 2.239 + for (var i = 0; i < data.length; ++i) { 2.240 + var ch = data.charCodeAt(i); 2.241 + if (ch < 0x80) { 2.242 + newdata.push(ch); 2.243 + } else if (ch < 0x800) { 2.244 + newdata.push(0xc0 | (ch >> 6), 2.245 + 0x80 | (ch & 0x3f)); 2.246 + } else if (ch < 0x10000) { 2.247 + newdata.push(0xe0 | (ch >> 12), 2.248 + 0x80 | ((ch >> 6) & 0x3f), 2.249 + 0x80 | (ch & 0x3f)); 2.250 + } else { 2.251 + newdata.push(0xf0 | (ch >> 18), 2.252 + 0x80 | ((ch >> 12) & 0x3f), 2.253 + 0x80 | ((ch >> 6) & 0x3f), 2.254 + 0x80 | (ch & 0x3f)); 2.255 + } 2.256 + } 2.257 + return newdata; 2.258 + } else { 2.259 + return data; 2.260 + } 2.261 + } 2.262 +}; 2.263 + 2.264 +// returns the code words (sans ECC bits) for given data and configurations. 2.265 +// requires data to be preprocessed by validatedata. no length check is 2.266 +// performed, and everything has to be checked before calling this function. 2.267 +var encode = function(ver, mode, data, maxbuflen) { 2.268 + var buf = []; 2.269 + var bits = 0, remaining = 8; 2.270 + var datalen = data.length; 2.271 + 2.272 + // this function is intentionally no-op when n=0. 2.273 + var pack = function(x, n) { 2.274 + if (n >= remaining) { 2.275 + buf.push(bits | (x >> (n -= remaining))); 2.276 + while (n >= 8) buf.push((x >> (n -= 8)) & 255); 2.277 + bits = 0; 2.278 + remaining = 8; 2.279 + } 2.280 + if (n > 0) bits |= (x & ((1 << n) - 1)) << (remaining -= n); 2.281 + }; 2.282 + 2.283 + var nlenbits = ndatalenbits(ver, mode); 2.284 + pack(mode, 4); 2.285 + pack(datalen, nlenbits); 2.286 + 2.287 + switch (mode) { 2.288 + case MODE_NUMERIC: 2.289 + for (var i = 2; i < datalen; i += 3) { 2.290 + pack(parseInt(data.substring(i-2,i+1), 10), 10); 2.291 + } 2.292 + pack(parseInt(data.substring(i-2), 10), [0,4,7][datalen%3]); 2.293 + break; 2.294 + 2.295 + case MODE_ALPHANUMERIC: 2.296 + for (var i = 1; i < datalen; i += 2) { 2.297 + pack(ALPHANUMERIC_MAP[data.charAt(i-1)] * 45 + 2.298 + ALPHANUMERIC_MAP[data.charAt(i)], 11); 2.299 + } 2.300 + if (datalen % 2 == 1) { 2.301 + pack(ALPHANUMERIC_MAP[data.charAt(i-1)], 6); 2.302 + } 2.303 + break; 2.304 + 2.305 + case MODE_OCTET: 2.306 + for (var i = 0; i < datalen; ++i) { 2.307 + pack(data[i], 8); 2.308 + } 2.309 + break; 2.310 + }; 2.311 + 2.312 + // final bits. it is possible that adding terminator causes the buffer 2.313 + // to overflow, but then the buffer truncated to the maximum size will 2.314 + // be valid as the truncated terminator mode bits and padding is 2.315 + // identical in appearance (cf. JIS X 0510:2004 sec 8.4.8). 2.316 + pack(MODE_TERMINATOR, 4); 2.317 + if (remaining < 8) buf.push(bits); 2.318 + 2.319 + // the padding to fill up the remaining space. we should not add any 2.320 + // words when the overflow already occurred. 2.321 + while (buf.length + 1 < maxbuflen) buf.push(0xec, 0x11); 2.322 + if (buf.length < maxbuflen) buf.push(0xec); 2.323 + return buf; 2.324 +}; 2.325 + 2.326 +// calculates ECC code words for given code words and generator polynomial. 2.327 +// 2.328 +// this is quite similar to CRC calculation as both Reed-Solomon and CRC use 2.329 +// the certain kind of cyclic codes, which is effectively the division of 2.330 +// zero-augumented polynomial by the generator polynomial. the only difference 2.331 +// is that Reed-Solomon uses GF(2^8), instead of CRC's GF(2), and Reed-Solomon 2.332 +// uses the different generator polynomial than CRC's. 2.333 +var calculateecc = function(poly, genpoly) { 2.334 + var modulus = poly.slice(0); 2.335 + var polylen = poly.length, genpolylen = genpoly.length; 2.336 + for (var i = 0; i < genpolylen; ++i) modulus.push(0); 2.337 + for (var i = 0; i < polylen; ) { 2.338 + var quotient = GF256_INVMAP[modulus[i++]]; 2.339 + if (quotient >= 0) { 2.340 + for (var j = 0; j < genpolylen; ++j) { 2.341 + modulus[i+j] ^= GF256_MAP[(quotient + genpoly[j]) % 255]; 2.342 + } 2.343 + } 2.344 + } 2.345 + return modulus.slice(polylen); 2.346 +}; 2.347 + 2.348 +// auguments ECC code words to given code words. the resulting words are 2.349 +// ready to be encoded in the matrix. 2.350 +// 2.351 +// the much of actual augumenting procedure follows JIS X 0510:2004 sec 8.7. 2.352 +// the code is simplified using the fact that the size of each code & ECC 2.353 +// blocks is almost same; for example, when we have 4 blocks and 46 data words 2.354 +// the number of code words in those blocks are 11, 11, 12, 12 respectively. 2.355 +var augumenteccs = function(poly, nblocks, genpoly) { 2.356 + var subsizes = []; 2.357 + var subsize = (poly.length / nblocks) | 0, subsize0 = 0; 2.358 + var pivot = nblocks - poly.length % nblocks; 2.359 + for (var i = 0; i < pivot; ++i) { 2.360 + subsizes.push(subsize0); 2.361 + subsize0 += subsize; 2.362 + } 2.363 + for (var i = pivot; i < nblocks; ++i) { 2.364 + subsizes.push(subsize0); 2.365 + subsize0 += subsize+1; 2.366 + } 2.367 + subsizes.push(subsize0); 2.368 + 2.369 + var eccs = []; 2.370 + for (var i = 0; i < nblocks; ++i) { 2.371 + eccs.push(calculateecc(poly.slice(subsizes[i], subsizes[i+1]), genpoly)); 2.372 + } 2.373 + 2.374 + var result = []; 2.375 + var nitemsperblock = (poly.length / nblocks) | 0; 2.376 + for (var i = 0; i < nitemsperblock; ++i) { 2.377 + for (var j = 0; j < nblocks; ++j) { 2.378 + result.push(poly[subsizes[j] + i]); 2.379 + } 2.380 + } 2.381 + for (var j = pivot; j < nblocks; ++j) { 2.382 + result.push(poly[subsizes[j+1] - 1]); 2.383 + } 2.384 + for (var i = 0; i < genpoly.length; ++i) { 2.385 + for (var j = 0; j < nblocks; ++j) { 2.386 + result.push(eccs[j][i]); 2.387 + } 2.388 + } 2.389 + return result; 2.390 +}; 2.391 + 2.392 +// auguments BCH(p+q,q) code to the polynomial over GF(2), given the proper 2.393 +// genpoly. the both input and output are in binary numbers, and unlike 2.394 +// calculateecc genpoly should include the 1 bit for the highest degree. 2.395 +// 2.396 +// actual polynomials used for this procedure are as follows: 2.397 +// - p=10, q=5, genpoly=x^10+x^8+x^5+x^4+x^2+x+1 (JIS X 0510:2004 Appendix C) 2.398 +// - p=18, q=6, genpoly=x^12+x^11+x^10+x^9+x^8+x^5+x^2+1 (ibid. Appendix D) 2.399 +var augumentbch = function(poly, p, genpoly, q) { 2.400 + var modulus = poly << q; 2.401 + for (var i = p - 1; i >= 0; --i) { 2.402 + if ((modulus >> (q+i)) & 1) modulus ^= genpoly << i; 2.403 + } 2.404 + return (poly << q) | modulus; 2.405 +}; 2.406 + 2.407 +// creates the base matrix for given version. it returns two matrices, one of 2.408 +// them is the actual one and the another represents the "reserved" portion 2.409 +// (e.g. finder and timing patterns) of the matrix. 2.410 +// 2.411 +// some entries in the matrix may be undefined, rather than 0 or 1. this is 2.412 +// intentional (no initialization needed!), and putdata below will fill 2.413 +// the remaining ones. 2.414 +var makebasematrix = function(ver) { 2.415 + var v = VERSIONS[ver], n = getsizebyver(ver); 2.416 + var matrix = [], reserved = []; 2.417 + for (var i = 0; i < n; ++i) { 2.418 + matrix.push([]); 2.419 + reserved.push([]); 2.420 + } 2.421 + 2.422 + var blit = function(y, x, h, w, bits) { 2.423 + for (var i = 0; i < h; ++i) { 2.424 + for (var j = 0; j < w; ++j) { 2.425 + matrix[y+i][x+j] = (bits[i] >> j) & 1; 2.426 + reserved[y+i][x+j] = 1; 2.427 + } 2.428 + } 2.429 + }; 2.430 + 2.431 + // finder patterns and a part of timing patterns 2.432 + // will also mark the format information area (not yet written) as reserved. 2.433 + blit(0, 0, 9, 9, [0x7f, 0x41, 0x5d, 0x5d, 0x5d, 0x41, 0x17f, 0x00, 0x40]); 2.434 + blit(n-8, 0, 8, 9, [0x100, 0x7f, 0x41, 0x5d, 0x5d, 0x5d, 0x41, 0x7f]); 2.435 + blit(0, n-8, 9, 8, [0xfe, 0x82, 0xba, 0xba, 0xba, 0x82, 0xfe, 0x00, 0x00]); 2.436 + 2.437 + // the rest of timing patterns 2.438 + for (var i = 9; i < n-8; ++i) { 2.439 + matrix[6][i] = matrix[i][6] = ~i & 1; 2.440 + reserved[6][i] = reserved[i][6] = 1; 2.441 + } 2.442 + 2.443 + // alignment patterns 2.444 + var aligns = v[2], m = aligns.length; 2.445 + for (var i = 0; i < m; ++i) { 2.446 + var minj = (i==0 || i==m-1 ? 1 : 0), maxj = (i==0 ? m-1 : m); 2.447 + for (var j = minj; j < maxj; ++j) { 2.448 + blit(aligns[i], aligns[j], 5, 5, [0x1f, 0x11, 0x15, 0x11, 0x1f]); 2.449 + } 2.450 + } 2.451 + 2.452 + // version information 2.453 + if (needsverinfo(ver)) { 2.454 + var code = augumentbch(ver, 6, 0x1f25, 12); 2.455 + var k = 0; 2.456 + for (var i = 0; i < 6; ++i) { 2.457 + for (var j = 0; j < 3; ++j) { 2.458 + matrix[i][(n-11)+j] = matrix[(n-11)+j][i] = (code >> k++) & 1; 2.459 + reserved[i][(n-11)+j] = reserved[(n-11)+j][i] = 1; 2.460 + } 2.461 + } 2.462 + } 2.463 + 2.464 + return {matrix: matrix, reserved: reserved}; 2.465 +}; 2.466 + 2.467 +// fills the data portion (i.e. unmarked in reserved) of the matrix with given 2.468 +// code words. the size of code words should be no more than available bits, 2.469 +// and remaining bits are padded to 0 (cf. JIS X 0510:2004 sec 8.7.3). 2.470 +var putdata = function(matrix, reserved, buf) { 2.471 + var n = matrix.length; 2.472 + var k = 0, dir = -1; 2.473 + for (var i = n-1; i >= 0; i -= 2) { 2.474 + if (i == 6) --i; // skip the entire timing pattern column 2.475 + var jj = (dir < 0 ? n-1 : 0); 2.476 + for (var j = 0; j < n; ++j) { 2.477 + for (var ii = i; ii > i-2; --ii) { 2.478 + if (!reserved[jj][ii]) { 2.479 + // may overflow, but (undefined >> x) 2.480 + // is 0 so it will auto-pad to zero. 2.481 + matrix[jj][ii] = (buf[k >> 3] >> (~k&7)) & 1; 2.482 + ++k; 2.483 + } 2.484 + } 2.485 + jj += dir; 2.486 + } 2.487 + dir = -dir; 2.488 + } 2.489 + return matrix; 2.490 +}; 2.491 + 2.492 +// XOR-masks the data portion of the matrix. repeating the call with the same 2.493 +// arguments will revert the prior call (convenient in the matrix evaluation). 2.494 +var maskdata = function(matrix, reserved, mask) { 2.495 + var maskf = MASKFUNCS[mask]; 2.496 + var n = matrix.length; 2.497 + for (var i = 0; i < n; ++i) { 2.498 + for (var j = 0; j < n; ++j) { 2.499 + if (!reserved[i][j]) matrix[i][j] ^= maskf(i,j); 2.500 + } 2.501 + } 2.502 + return matrix; 2.503 +} 2.504 + 2.505 +// puts the format information. 2.506 +var putformatinfo = function(matrix, reserved, ecclevel, mask) { 2.507 + var n = matrix.length; 2.508 + var code = augumentbch((ecclevel << 3) | mask, 5, 0x537, 10) ^ 0x5412; 2.509 + for (var i = 0; i < 15; ++i) { 2.510 + var r = [0,1,2,3,4,5,7,8,n-7,n-6,n-5,n-4,n-3,n-2,n-1][i]; 2.511 + var c = [n-1,n-2,n-3,n-4,n-5,n-6,n-7,n-8,7,5,4,3,2,1,0][i]; 2.512 + matrix[r][8] = matrix[8][c] = (code >> i) & 1; 2.513 + // we don't have to mark those bits reserved; always done 2.514 + // in makebasematrix above. 2.515 + } 2.516 + return matrix; 2.517 +}; 2.518 + 2.519 +// evaluates the resulting matrix and returns the score (lower is better). 2.520 +// (cf. JIS X 0510:2004 sec 8.8.2) 2.521 +// 2.522 +// the evaluation procedure tries to avoid the problematic patterns naturally 2.523 +// occuring from the original matrix. for example, it penaltizes the patterns 2.524 +// which just look like the finder pattern which will confuse the decoder. 2.525 +// we choose the mask which results in the lowest score among 8 possible ones. 2.526 +// 2.527 +// note: zxing seems to use the same procedure and in many cases its choice 2.528 +// agrees to ours, but sometimes it does not. practically it doesn't matter. 2.529 +var evaluatematrix = function(matrix) { 2.530 + // N1+(k-5) points for each consecutive row of k same-colored modules, where k >= 5. no overlapping row counts. 2.531 + var PENALTY_CONSECUTIVE = 3; 2.532 + // N2 points for each 2x2 block of same-colored modules. Overlapping block does count. 2.533 + var PENALTY_TWOBYTWO = 3; 2.534 + // N3 points for each pattern with >4W:1B:1W:3B:1W:1B or 2.535 + // 1B:1W:3B:1W:1B:>4W, or their multiples (e.g. highly unlikely, but 13W:3B:3W:9B:3W:3B counts). 2.536 + var PENALTY_FINDERLIKE = 40; 2.537 + // N4*k points for every (5*k)% deviation from 50% black density. 2.538 + // i.e. k=1 for 55~60% and 40~45%, k=2 for 60~65% and 35~40%, etc. 2.539 + var PENALTY_DENSITY = 10; 2.540 + 2.541 + var evaluategroup = function(groups) { // assumes [W,B,W,B,W,...,B,W] 2.542 + var score = 0; 2.543 + for (var i = 0; i < groups.length; ++i) { 2.544 + if (groups[i] >= 5) score += PENALTY_CONSECUTIVE + (groups[i]-5); 2.545 + } 2.546 + for (var i = 5; i < groups.length; i += 2) { 2.547 + var p = groups[i]; 2.548 + if (groups[i-1] == p && groups[i-2] == 3*p && groups[i-3] == p && 2.549 + groups[i-4] == p && (groups[i-5] >= 4*p || groups[i+1] >= 4*p)) { 2.550 + // this part differs from zxing... 2.551 + score += PENALTY_FINDERLIKE; 2.552 + } 2.553 + } 2.554 + return score; 2.555 + }; 2.556 + 2.557 + var n = matrix.length; 2.558 + var score = 0, nblacks = 0; 2.559 + for (var i = 0; i < n; ++i) { 2.560 + var row = matrix[i]; 2.561 + var groups; 2.562 + 2.563 + // evaluate the current row 2.564 + groups = [0]; // the first empty group of white 2.565 + for (var j = 0; j < n; ) { 2.566 + var k; 2.567 + for (k = 0; j < n && row[j]; ++k) ++j; 2.568 + groups.push(k); 2.569 + for (k = 0; j < n && !row[j]; ++k) ++j; 2.570 + groups.push(k); 2.571 + } 2.572 + score += evaluategroup(groups); 2.573 + 2.574 + // evaluate the current column 2.575 + groups = [0]; 2.576 + for (var j = 0; j < n; ) { 2.577 + var k; 2.578 + for (k = 0; j < n && matrix[j][i]; ++k) ++j; 2.579 + groups.push(k); 2.580 + for (k = 0; j < n && !matrix[j][i]; ++k) ++j; 2.581 + groups.push(k); 2.582 + } 2.583 + score += evaluategroup(groups); 2.584 + 2.585 + // check the 2x2 box and calculate the density 2.586 + var nextrow = matrix[i+1] || []; 2.587 + nblacks += row[0]; 2.588 + for (var j = 1; j < n; ++j) { 2.589 + var p = row[j]; 2.590 + nblacks += p; 2.591 + // at least comparison with next row should be strict... 2.592 + if (row[j-1] == p && nextrow[j] === p && nextrow[j-1] === p) { 2.593 + score += PENALTY_TWOBYTWO; 2.594 + } 2.595 + } 2.596 + } 2.597 + 2.598 + score += PENALTY_DENSITY * ((Math.abs(nblacks / n / n - 0.5) / 0.05) | 0); 2.599 + return score; 2.600 +}; 2.601 + 2.602 +// returns the fully encoded QR code matrix which contains given data. 2.603 +// it also chooses the best mask automatically when mask is -1. 2.604 +var generate = function(data, ver, mode, ecclevel, mask) { 2.605 + var v = VERSIONS[ver]; 2.606 + var buf = encode(ver, mode, data, ndatabits(ver, ecclevel) >> 3); 2.607 + buf = augumenteccs(buf, v[1][ecclevel], GF256_GENPOLY[v[0][ecclevel]]); 2.608 + 2.609 + var result = makebasematrix(ver); 2.610 + var matrix = result.matrix, reserved = result.reserved; 2.611 + putdata(matrix, reserved, buf); 2.612 + 2.613 + if (mask < 0) { 2.614 + // find the best mask 2.615 + maskdata(matrix, reserved, 0); 2.616 + putformatinfo(matrix, reserved, ecclevel, 0); 2.617 + var bestmask = 0, bestscore = evaluatematrix(matrix); 2.618 + maskdata(matrix, reserved, 0); 2.619 + for (mask = 1; mask < 8; ++mask) { 2.620 + maskdata(matrix, reserved, mask); 2.621 + putformatinfo(matrix, reserved, ecclevel, mask); 2.622 + var score = evaluatematrix(matrix); 2.623 + if (bestscore > score) { 2.624 + bestscore = score; 2.625 + bestmask = mask; 2.626 + } 2.627 + maskdata(matrix, reserved, mask); 2.628 + } 2.629 + mask = bestmask; 2.630 + } 2.631 + 2.632 + maskdata(matrix, reserved, mask); 2.633 + putformatinfo(matrix, reserved, ecclevel, mask); 2.634 + return matrix; 2.635 +}; 2.636 + 2.637 +// the public interface is trivial; the options available are as follows: 2.638 +// 2.639 +// - version: an integer in [1,40]. when omitted (or -1) the smallest possible 2.640 +// version is chosen. 2.641 +// - mode: one of 'numeric', 'alphanumeric', 'octet'. when omitted the smallest 2.642 +// possible mode is chosen. 2.643 +// - ecclevel: one of 'L', 'M', 'Q', 'H'. defaults to 'L'. 2.644 +// - mask: an integer in [0,7]. when omitted (or -1) the best mask is chosen. 2.645 +// 2.646 +// for generate{HTML,PNG}: 2.647 +// 2.648 +// - modulesize: a number. this is a size of each modules in pixels, and 2.649 +// defaults to 5px. 2.650 +// - margin: a number. this is a size of margin in *modules*, and defaults to 2.651 +// 4 (white modules). the specficiation mandates the margin no less than 4 2.652 +// modules, so it is better not to alter this value unless you know what 2.653 +// you're doing. 2.654 +var QRCode = { 2.655 + 'generate': function(data, options) { 2.656 + var MODES = {'numeric': MODE_NUMERIC, 'alphanumeric': MODE_ALPHANUMERIC, 2.657 + 'octet': MODE_OCTET}; 2.658 + var ECCLEVELS = {'L': ECCLEVEL_L, 'M': ECCLEVEL_M, 'Q': ECCLEVEL_Q, 2.659 + 'H': ECCLEVEL_H}; 2.660 + 2.661 + options = options || {}; 2.662 + var ver = options.version || -1; 2.663 + var ecclevel = ECCLEVELS[(options.ecclevel || 'L').toUpperCase()]; 2.664 + var mode = options.mode ? MODES[options.mode.toLowerCase()] : -1; 2.665 + var mask = 'mask' in options ? options.mask : -1; 2.666 + 2.667 + if (mode < 0) { 2.668 + if (typeof data === 'string') { 2.669 + if (data.match(NUMERIC_REGEXP)) { 2.670 + mode = MODE_NUMERIC; 2.671 + } else if (data.match(ALPHANUMERIC_OUT_REGEXP)) { 2.672 + // while encode supports case-insensitive 2.673 + // encoding, we restrict the data to be 2.674 + // uppercased when auto-selecting the mode. 2.675 + mode = MODE_ALPHANUMERIC; 2.676 + } else { 2.677 + mode = MODE_OCTET; 2.678 + } 2.679 + } else { 2.680 + mode = MODE_OCTET; 2.681 + } 2.682 + } else if (!(mode == MODE_NUMERIC || mode == MODE_ALPHANUMERIC || 2.683 + mode == MODE_OCTET)) { 2.684 + throw 'invalid or unsupported mode'; 2.685 + } 2.686 + 2.687 + data = validatedata(mode, data); 2.688 + if (data === null) throw 'invalid data format'; 2.689 + 2.690 + if (ecclevel < 0 || ecclevel > 3) throw 'invalid ECC level'; 2.691 + 2.692 + if (ver < 0) { 2.693 + for (ver = 1; ver <= 40; ++ver) { 2.694 + if (data.length <= getmaxdatalen(ver, mode, ecclevel)) break; 2.695 + } 2.696 + if (ver > 40) throw 'too large data'; 2.697 + } else if (ver < 1 || ver > 40) { 2.698 + throw 'invalid version'; 2.699 + } 2.700 + 2.701 + if (mask != -1 && (mask < 0 || mask > 8)) throw 'invalid mask'; 2.702 + 2.703 + return generate(data, ver, mode, ecclevel, mask); 2.704 + }, 2.705 + 2.706 + 2.707 + 'generatePNG': function(data, options) { 2.708 + options = options || {}; 2.709 + var matrix = QRCode['generate'](data, options); 2.710 + var modsize = Math.max(options.modulesize || 5, 0.5); 2.711 + var margin = Math.max(options.margin || 4, 0.0); 2.712 + var n = matrix.length; 2.713 + var size = modsize * (n + 2 * margin); 2.714 + 2.715 + var canvas = document.createElement('canvas'), context; 2.716 + canvas.width = canvas.height = size; 2.717 + context = canvas.getContext('2d'); 2.718 + if (!context) throw 'canvas support is needed for PNG output'; 2.719 + 2.720 + context.fillStyle = '#fff'; 2.721 + context.fillRect(0, 0, size, size); 2.722 + context.fillStyle = '#000'; 2.723 + for (var i = 0; i < n; ++i) { 2.724 + for (var j = 0; j < n; ++j) { 2.725 + if (matrix[i][j]) { 2.726 + context.fillRect(modsize * (margin + j), modsize * (margin + i), modsize, modsize); 2.727 + } 2.728 + } 2.729 + } 2.730 + //context.fillText('evaluation: ' + evaluatematrix(matrix), 10, 10); 2.731 + return canvas.toDataURL(); 2.732 + } 2.733 +}; 2.734 + 2.735 +return QRCode; 2.736 +})();
3.1 --- a/pro/lib/html/footer.html Mon Mar 25 18:34:38 2013 +0100 3.2 +++ b/pro/lib/html/footer.html Mon Mar 25 18:45:42 2013 +0100 3.3 @@ -1,4 +1,7 @@ 3.4 <!-- Footer --> 3.5 + 3.6 +<script type="text/javascript" src="qrcode.js"></script> 3.7 + 3.8 <div id="footer"> 3.9 Copyright © <span class="year"></span> 3.10 <a href="http://www.slitaz.org/">SliTaz</a> - Network: 3.11 @@ -7,9 +10,10 @@ 3.12 <a href="http://forum.slitaz.org/">Forum</a> 3.13 <a href="http://pkgs.slitaz.org/">Packages</a> 3.14 <a href="http://bugs.slitaz.org">Bugs</a> 3.15 - <a href="http://hg.slitaz.org/">Hg</a> 3.16 + <a href="http://hg.slitaz.org/?sort=lastchange">Hg</a> 3.17 <p> 3.18 - SliTaz @ 3.19 + <img src="#" alt="SliTaz @" onmouseover="this.title = location.href" 3.20 + onclick="this.src = QRCode.generatePNG(location.href, {ecclevel: 'H'})" /> 3.21 <a href="http://twitter.com/slitaz">Twitter</a> 3.22 <a href="http://www.facebook.com/slitaz">Facebook</a> 3.23 <a href="http://distrowatch.com/slitaz">Distrowatch</a>
4.1 --- a/pro/lib/html/footer.ru.html Mon Mar 25 18:34:38 2013 +0100 4.2 +++ b/pro/lib/html/footer.ru.html Mon Mar 25 18:45:42 2013 +0100 4.3 @@ -1,4 +1,7 @@ 4.4 <!-- Footer --> 4.5 + 4.6 +<script type="text/javascript" src="qrcode.js"></script> 4.7 + 4.8 <div id="footer"> 4.9 Copyright © <span class="year"></span> 4.10 <a href="http://www.slitaz.org/">SliTaz</a> — Сеть: 4.11 @@ -7,9 +10,10 @@ 4.12 <a href="http://forum.slitaz.org/">Форум</a> 4.13 <a href="http://pkgs.slitaz.org/">Пакеты</a> 4.14 <a href="http://bugs.slitaz.org">Bugs</a> 4.15 - <a href="http://hg.slitaz.org/">Hg</a> 4.16 + <a href="http://hg.slitaz.org/?sort=lastchange">Hg</a> 4.17 <p> 4.18 - SliTaz @ 4.19 + <img src="#" alt="SliTaz @" onmouseover="this.title = location.href" 4.20 + onclick="this.src = QRCode.generatePNG(location.href, {ecclevel: 'H'})" /> 4.21 <a href="http://twitter.com/slitaz">Twitter</a> 4.22 <a href="http://www.facebook.com/slitaz">Facebook</a> 4.23 <a href="http://distrowatch.com/slitaz">Distrowatch</a>
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/pro/lib/html/qrcode.js Mon Mar 25 18:45:42 2013 +0100 5.3 @@ -0,0 +1,733 @@ 5.4 +/* qr.js -- QR code generator in Javascript (revision 2011-01-19) 5.5 + * Written by Kang Seonghoon <public+qrjs@mearie.org>. 5.6 + * 5.7 + * This source code is in the public domain; if your jurisdiction does not 5.8 + * recognize the public domain the terms of Creative Commons CC0 license 5.9 + * apply. In the other words, you can always do what you want. 5.10 + */ 5.11 + 5.12 +var QRCode = (function(){ 5.13 + 5.14 +/* Quick overview: QR code composed of 2D array of modules (a rectangular 5.15 + * area that conveys one bit of information); some modules are fixed to help 5.16 + * the recognition of the code, and remaining data modules are further divided 5.17 + * into 8-bit code words which are augumented by Reed-Solomon error correcting 5.18 + * codes (ECC). There could be multiple ECCs, in the case the code is so large 5.19 + * that it is helpful to split the raw data into several chunks. 5.20 + * 5.21 + * The number of modules is determined by the code's "version", ranging from 1 5.22 + * (21x21) to 40 (177x177). How many ECC bits are used is determined by the 5.23 + * ECC level (L/M/Q/H). The number and size (and thus the order of generator 5.24 + * polynomial) of ECCs depend to the version and ECC level. 5.25 + */ 5.26 + 5.27 +// per-version information (cf. JIS X 0510:2004 pp. 30--36, 71) 5.28 +// 5.29 +// [0]: the degree of generator polynomial by ECC levels 5.30 +// [1]: # of code blocks by ECC levels 5.31 +// [2]: left-top positions of alignment patterns 5.32 +// 5.33 +// the number in this table (in particular, [0]) does not exactly match with 5.34 +// the numbers in the specficiation. see augumenteccs below for the reason. 5.35 +var VERSIONS = [ 5.36 + null, 5.37 + [[10, 7,17,13], [ 1, 1, 1, 1], []], 5.38 + [[16,10,28,22], [ 1, 1, 1, 1], [4,16]], 5.39 + [[26,15,22,18], [ 1, 1, 2, 2], [4,20]], 5.40 + [[18,20,16,26], [ 2, 1, 4, 2], [4,24]], 5.41 + [[24,26,22,18], [ 2, 1, 4, 4], [4,28]], 5.42 + [[16,18,28,24], [ 4, 2, 4, 4], [4,32]], 5.43 + [[18,20,26,18], [ 4, 2, 5, 6], [4,20,36]], 5.44 + [[22,24,26,22], [ 4, 2, 6, 6], [4,22,40]], 5.45 + [[22,30,24,20], [ 5, 2, 8, 8], [4,24,44]], 5.46 + [[26,18,28,24], [ 5, 4, 8, 8], [4,26,48]], 5.47 + [[30,20,24,28], [ 5, 4,11, 8], [4,28,52]], 5.48 + [[22,24,28,26], [ 8, 4,11,10], [4,30,56]], 5.49 + [[22,26,22,24], [ 9, 4,16,12], [4,32,60]], 5.50 + [[24,30,24,20], [ 9, 4,16,16], [4,24,44,64]], 5.51 + [[24,22,24,30], [10, 6,18,12], [4,24,46,68]], 5.52 + [[28,24,30,24], [10, 6,16,17], [4,24,48,72]], 5.53 + [[28,28,28,28], [11, 6,19,16], [4,28,52,76]], 5.54 + [[26,30,28,28], [13, 6,21,18], [4,28,54,80]], 5.55 + [[26,28,26,26], [14, 7,25,21], [4,28,56,84]], 5.56 + [[26,28,28,30], [16, 8,25,20], [4,32,60,88]], 5.57 + [[26,28,30,28], [17, 8,25,23], [4,26,48,70,92]], 5.58 + [[28,28,24,30], [17, 9,34,23], [4,24,48,72,96]], 5.59 + [[28,30,30,30], [18, 9,30,25], [4,28,52,76,100]], 5.60 + [[28,30,30,30], [20,10,32,27], [4,26,52,78,104]], 5.61 + [[28,26,30,30], [21,12,35,29], [4,30,56,82,108]], 5.62 + [[28,28,30,28], [23,12,37,34], [4,28,56,84,112]], 5.63 + [[28,30,30,30], [25,12,40,34], [4,32,60,88,116]], 5.64 + [[28,30,30,30], [26,13,42,35], [4,24,48,72,96,120]], 5.65 + [[28,30,30,30], [28,14,45,38], [4,28,52,76,100,124]], 5.66 + [[28,30,30,30], [29,15,48,40], [4,24,50,76,102,128]], 5.67 + [[28,30,30,30], [31,16,51,43], [4,28,54,80,106,132]], 5.68 + [[28,30,30,30], [33,17,54,45], [4,32,58,84,110,136]], 5.69 + [[28,30,30,30], [35,18,57,48], [4,28,56,84,112,140]], 5.70 + [[28,30,30,30], [37,19,60,51], [4,32,60,88,116,144]], 5.71 + [[28,30,30,30], [38,19,63,53], [4,28,52,76,100,124,148]], 5.72 + [[28,30,30,30], [40,20,66,56], [4,22,48,74,100,126,152]], 5.73 + [[28,30,30,30], [43,21,70,59], [4,26,52,78,104,130,156]], 5.74 + [[28,30,30,30], [45,22,74,62], [4,30,56,82,108,134,160]], 5.75 + [[28,30,30,30], [47,24,77,65], [4,24,52,80,108,136,164]], 5.76 + [[28,30,30,30], [49,25,81,68], [4,28,56,84,112,140,168]]]; 5.77 + 5.78 +// mode constants (cf. Table 2 in JIS X 0510:2004 p. 16) 5.79 +var MODE_TERMINATOR = 0; 5.80 +var MODE_NUMERIC = 1, MODE_ALPHANUMERIC = 2, MODE_OCTET = 4, MODE_KANJI = 8; 5.81 + 5.82 +// validation regexps 5.83 +var NUMERIC_REGEXP = /^\d*$/; 5.84 +var ALPHANUMERIC_REGEXP = /^[A-Za-z0-9 $%*+\-./:]*$/; 5.85 +var ALPHANUMERIC_OUT_REGEXP = /^[A-Z0-9 $%*+\-./:]*$/; 5.86 + 5.87 +// ECC levels (cf. Table 22 in JIS X 0510:2004 p. 45) 5.88 +var ECCLEVEL_L = 1, ECCLEVEL_M = 0, ECCLEVEL_Q = 3, ECCLEVEL_H = 2; 5.89 + 5.90 +// GF(2^8)-to-integer mapping with a reducing polynomial x^8+x^4+x^3+x^2+1 5.91 +// invariant: GF256_MAP[GF256_INVMAP[i]] == i for all i in [1,256) 5.92 +var GF256_MAP = [], GF256_INVMAP = [-1]; 5.93 +for (var i = 0, v = 1; i < 255; ++i) { 5.94 + GF256_MAP.push(v); 5.95 + GF256_INVMAP[v] = i; 5.96 + v = (v * 2) ^ (v >= 128 ? 0x11d : 0); 5.97 +} 5.98 + 5.99 +// generator polynomials up to degree 30 5.100 +// (should match with polynomials in JIS X 0510:2004 Appendix A) 5.101 +// 5.102 +// generator polynomial of degree K is product of (x-\alpha^0), (x-\alpha^1), 5.103 +// ..., (x-\alpha^(K-1)). by convention, we omit the K-th coefficient (always 1) 5.104 +// from the result; also other coefficients are written in terms of the exponent 5.105 +// to \alpha to avoid the redundant calculation. (see also calculateecc below.) 5.106 +var GF256_GENPOLY = [[]]; 5.107 +for (var i = 0; i < 30; ++i) { 5.108 + var prevpoly = GF256_GENPOLY[i], poly = []; 5.109 + for (var j = 0; j <= i; ++j) { 5.110 + var a = (j < i ? GF256_MAP[prevpoly[j]] : 0); 5.111 + var b = GF256_MAP[(i + (prevpoly[j-1] || 0)) % 255]; 5.112 + poly.push(GF256_INVMAP[a ^ b]); 5.113 + } 5.114 + GF256_GENPOLY.push(poly); 5.115 +} 5.116 + 5.117 +// alphanumeric character mapping (cf. Table 5 in JIS X 0510:2004 p. 19) 5.118 +var ALPHANUMERIC_MAP = {}; 5.119 +for (var i = 0; i < 45; ++i) { 5.120 + ALPHANUMERIC_MAP['0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'.charAt(i)] = i; 5.121 +} 5.122 + 5.123 +// mask functions in terms of row # and column # 5.124 +// (cf. Table 20 in JIS X 0510:2004 p. 42) 5.125 +var MASKFUNCS = [ 5.126 + function(i,j) { return (i+j) % 2 == 0; }, 5.127 + function(i,j) { return i % 2 == 0; }, 5.128 + function(i,j) { return j % 3 == 0; }, 5.129 + function(i,j) { return (i+j) % 3 == 0; }, 5.130 + function(i,j) { return (((i/2)|0) + ((j/3)|0)) % 2 == 0; }, 5.131 + function(i,j) { return (i*j) % 2 + (i*j) % 3 == 0; }, 5.132 + function(i,j) { return ((i*j) % 2 + (i*j) % 3) % 2 == 0; }, 5.133 + function(i,j) { return ((i+j) % 2 + (i*j) % 3) % 2 == 0; }]; 5.134 + 5.135 +// returns true when the version information has to be embeded. 5.136 +var needsverinfo = function(ver) { return ver > 6; }; 5.137 + 5.138 +// returns the size of entire QR code for given version. 5.139 +var getsizebyver = function(ver) { return 4 * ver + 17; }; 5.140 + 5.141 +// returns the number of bits available for code words in this version. 5.142 +var nfullbits = function(ver) { 5.143 + /* 5.144 + * |<--------------- n --------------->| 5.145 + * | |<----- n-17 ---->| | 5.146 + * +-------+ ///+-------+ ---- 5.147 + * | | ///| | ^ 5.148 + * | 9x9 | @@@@@ ///| 9x8 | | 5.149 + * | | # # # @5x5@ # # # | | | 5.150 + * +-------+ @@@@@ +-------+ | 5.151 + * # ---| 5.152 + * ^ | 5.153 + * # | 5.154 + * @@@@@ @@@@@ @@@@@ | n 5.155 + * @5x5@ @5x5@ @5x5@ n-17 5.156 + * @@@@@ @@@@@ @@@@@ | | 5.157 + * # | | 5.158 + * ////// v | 5.159 + * //////# ---| 5.160 + * +-------+ @@@@@ @@@@@ | 5.161 + * | | @5x5@ @5x5@ | 5.162 + * | 8x9 | @@@@@ @@@@@ | 5.163 + * | | v 5.164 + * +-------+ ---- 5.165 + * 5.166 + * when the entire code has n^2 modules and there are m^2-3 alignment 5.167 + * patterns, we have: 5.168 + * - 225 (= 9x9 + 9x8 + 8x9) modules for finder patterns and 5.169 + * format information; 5.170 + * - 2n-34 (= 2(n-17)) modules for timing patterns; 5.171 + * - 36 (= 3x6 + 6x3) modules for version information, if any; 5.172 + * - 25m^2-75 (= (m^2-3)(5x5)) modules for alignment patterns 5.173 + * if any, but 10m-20 (= 2(m-2)x5) of them overlaps with 5.174 + * timing patterns. 5.175 + */ 5.176 + var v = VERSIONS[ver]; 5.177 + var nbits = 16*ver*ver + 128*ver + 64; // finder, timing and format info. 5.178 + if (needsverinfo(ver)) nbits -= 36; // version information 5.179 + if (v[2].length) { // alignment patterns 5.180 + nbits -= 25 * v[2].length * v[2].length - 10 * v[2].length - 55; 5.181 + } 5.182 + return nbits; 5.183 +}; 5.184 + 5.185 +// returns the number of bits available for data portions (i.e. excludes ECC 5.186 +// bits but includes mode and length bits) in this version and ECC level. 5.187 +var ndatabits = function(ver, ecclevel) { 5.188 + var nbits = nfullbits(ver) & ~7; // no sub-octet code words 5.189 + var v = VERSIONS[ver]; 5.190 + nbits -= 8 * v[0][ecclevel] * v[1][ecclevel]; // ecc bits 5.191 + return nbits; 5.192 +} 5.193 + 5.194 +// returns the number of bits required for the length of data. 5.195 +// (cf. Table 3 in JIS X 0510:2004 p. 16) 5.196 +var ndatalenbits = function(ver, mode) { 5.197 + switch (mode) { 5.198 + case MODE_NUMERIC: return (ver < 10 ? 10 : ver < 27 ? 12 : 14); 5.199 + case MODE_ALPHANUMERIC: return (ver < 10 ? 9 : ver < 27 ? 11 : 13); 5.200 + case MODE_OCTET: return (ver < 10 ? 8 : 16); 5.201 + case MODE_KANJI: return (ver < 10 ? 8 : ver < 27 ? 10 : 12); 5.202 + } 5.203 +}; 5.204 + 5.205 +// returns the maximum length of data possible in given configuration. 5.206 +var getmaxdatalen = function(ver, mode, ecclevel) { 5.207 + var nbits = ndatabits(ver, ecclevel) - 4 - ndatalenbits(ver, mode); // 4 for mode bits 5.208 + switch (mode) { 5.209 + case MODE_NUMERIC: 5.210 + return ((nbits/10) | 0) * 3 + (nbits%10 < 4 ? 0 : nbits%10 < 7 ? 1 : 2); 5.211 + case MODE_ALPHANUMERIC: 5.212 + return ((nbits/11) | 0) * 2 + (nbits%11 < 6 ? 0 : 1); 5.213 + case MODE_OCTET: 5.214 + return (nbits/8) | 0; 5.215 + case MODE_KANJI: 5.216 + return (nbits/13) | 0; 5.217 + } 5.218 +}; 5.219 + 5.220 +// checks if the given data can be encoded in given mode, and returns 5.221 +// the converted data for the further processing if possible. otherwise 5.222 +// returns null. 5.223 +// 5.224 +// this function does not check the length of data; it is a duty of 5.225 +// encode function below (as it depends on the version and ECC level too). 5.226 +var validatedata = function(mode, data) { 5.227 + switch (mode) { 5.228 + case MODE_NUMERIC: 5.229 + if (!data.match(NUMERIC_REGEXP)) return null; 5.230 + return data; 5.231 + 5.232 + case MODE_ALPHANUMERIC: 5.233 + if (!data.match(ALPHANUMERIC_REGEXP)) return null; 5.234 + return data.toUpperCase(); 5.235 + 5.236 + case MODE_OCTET: 5.237 + if (typeof data === 'string') { // encode as utf-8 string 5.238 + var newdata = []; 5.239 + for (var i = 0; i < data.length; ++i) { 5.240 + var ch = data.charCodeAt(i); 5.241 + if (ch < 0x80) { 5.242 + newdata.push(ch); 5.243 + } else if (ch < 0x800) { 5.244 + newdata.push(0xc0 | (ch >> 6), 5.245 + 0x80 | (ch & 0x3f)); 5.246 + } else if (ch < 0x10000) { 5.247 + newdata.push(0xe0 | (ch >> 12), 5.248 + 0x80 | ((ch >> 6) & 0x3f), 5.249 + 0x80 | (ch & 0x3f)); 5.250 + } else { 5.251 + newdata.push(0xf0 | (ch >> 18), 5.252 + 0x80 | ((ch >> 12) & 0x3f), 5.253 + 0x80 | ((ch >> 6) & 0x3f), 5.254 + 0x80 | (ch & 0x3f)); 5.255 + } 5.256 + } 5.257 + return newdata; 5.258 + } else { 5.259 + return data; 5.260 + } 5.261 + } 5.262 +}; 5.263 + 5.264 +// returns the code words (sans ECC bits) for given data and configurations. 5.265 +// requires data to be preprocessed by validatedata. no length check is 5.266 +// performed, and everything has to be checked before calling this function. 5.267 +var encode = function(ver, mode, data, maxbuflen) { 5.268 + var buf = []; 5.269 + var bits = 0, remaining = 8; 5.270 + var datalen = data.length; 5.271 + 5.272 + // this function is intentionally no-op when n=0. 5.273 + var pack = function(x, n) { 5.274 + if (n >= remaining) { 5.275 + buf.push(bits | (x >> (n -= remaining))); 5.276 + while (n >= 8) buf.push((x >> (n -= 8)) & 255); 5.277 + bits = 0; 5.278 + remaining = 8; 5.279 + } 5.280 + if (n > 0) bits |= (x & ((1 << n) - 1)) << (remaining -= n); 5.281 + }; 5.282 + 5.283 + var nlenbits = ndatalenbits(ver, mode); 5.284 + pack(mode, 4); 5.285 + pack(datalen, nlenbits); 5.286 + 5.287 + switch (mode) { 5.288 + case MODE_NUMERIC: 5.289 + for (var i = 2; i < datalen; i += 3) { 5.290 + pack(parseInt(data.substring(i-2,i+1), 10), 10); 5.291 + } 5.292 + pack(parseInt(data.substring(i-2), 10), [0,4,7][datalen%3]); 5.293 + break; 5.294 + 5.295 + case MODE_ALPHANUMERIC: 5.296 + for (var i = 1; i < datalen; i += 2) { 5.297 + pack(ALPHANUMERIC_MAP[data.charAt(i-1)] * 45 + 5.298 + ALPHANUMERIC_MAP[data.charAt(i)], 11); 5.299 + } 5.300 + if (datalen % 2 == 1) { 5.301 + pack(ALPHANUMERIC_MAP[data.charAt(i-1)], 6); 5.302 + } 5.303 + break; 5.304 + 5.305 + case MODE_OCTET: 5.306 + for (var i = 0; i < datalen; ++i) { 5.307 + pack(data[i], 8); 5.308 + } 5.309 + break; 5.310 + }; 5.311 + 5.312 + // final bits. it is possible that adding terminator causes the buffer 5.313 + // to overflow, but then the buffer truncated to the maximum size will 5.314 + // be valid as the truncated terminator mode bits and padding is 5.315 + // identical in appearance (cf. JIS X 0510:2004 sec 8.4.8). 5.316 + pack(MODE_TERMINATOR, 4); 5.317 + if (remaining < 8) buf.push(bits); 5.318 + 5.319 + // the padding to fill up the remaining space. we should not add any 5.320 + // words when the overflow already occurred. 5.321 + while (buf.length + 1 < maxbuflen) buf.push(0xec, 0x11); 5.322 + if (buf.length < maxbuflen) buf.push(0xec); 5.323 + return buf; 5.324 +}; 5.325 + 5.326 +// calculates ECC code words for given code words and generator polynomial. 5.327 +// 5.328 +// this is quite similar to CRC calculation as both Reed-Solomon and CRC use 5.329 +// the certain kind of cyclic codes, which is effectively the division of 5.330 +// zero-augumented polynomial by the generator polynomial. the only difference 5.331 +// is that Reed-Solomon uses GF(2^8), instead of CRC's GF(2), and Reed-Solomon 5.332 +// uses the different generator polynomial than CRC's. 5.333 +var calculateecc = function(poly, genpoly) { 5.334 + var modulus = poly.slice(0); 5.335 + var polylen = poly.length, genpolylen = genpoly.length; 5.336 + for (var i = 0; i < genpolylen; ++i) modulus.push(0); 5.337 + for (var i = 0; i < polylen; ) { 5.338 + var quotient = GF256_INVMAP[modulus[i++]]; 5.339 + if (quotient >= 0) { 5.340 + for (var j = 0; j < genpolylen; ++j) { 5.341 + modulus[i+j] ^= GF256_MAP[(quotient + genpoly[j]) % 255]; 5.342 + } 5.343 + } 5.344 + } 5.345 + return modulus.slice(polylen); 5.346 +}; 5.347 + 5.348 +// auguments ECC code words to given code words. the resulting words are 5.349 +// ready to be encoded in the matrix. 5.350 +// 5.351 +// the much of actual augumenting procedure follows JIS X 0510:2004 sec 8.7. 5.352 +// the code is simplified using the fact that the size of each code & ECC 5.353 +// blocks is almost same; for example, when we have 4 blocks and 46 data words 5.354 +// the number of code words in those blocks are 11, 11, 12, 12 respectively. 5.355 +var augumenteccs = function(poly, nblocks, genpoly) { 5.356 + var subsizes = []; 5.357 + var subsize = (poly.length / nblocks) | 0, subsize0 = 0; 5.358 + var pivot = nblocks - poly.length % nblocks; 5.359 + for (var i = 0; i < pivot; ++i) { 5.360 + subsizes.push(subsize0); 5.361 + subsize0 += subsize; 5.362 + } 5.363 + for (var i = pivot; i < nblocks; ++i) { 5.364 + subsizes.push(subsize0); 5.365 + subsize0 += subsize+1; 5.366 + } 5.367 + subsizes.push(subsize0); 5.368 + 5.369 + var eccs = []; 5.370 + for (var i = 0; i < nblocks; ++i) { 5.371 + eccs.push(calculateecc(poly.slice(subsizes[i], subsizes[i+1]), genpoly)); 5.372 + } 5.373 + 5.374 + var result = []; 5.375 + var nitemsperblock = (poly.length / nblocks) | 0; 5.376 + for (var i = 0; i < nitemsperblock; ++i) { 5.377 + for (var j = 0; j < nblocks; ++j) { 5.378 + result.push(poly[subsizes[j] + i]); 5.379 + } 5.380 + } 5.381 + for (var j = pivot; j < nblocks; ++j) { 5.382 + result.push(poly[subsizes[j+1] - 1]); 5.383 + } 5.384 + for (var i = 0; i < genpoly.length; ++i) { 5.385 + for (var j = 0; j < nblocks; ++j) { 5.386 + result.push(eccs[j][i]); 5.387 + } 5.388 + } 5.389 + return result; 5.390 +}; 5.391 + 5.392 +// auguments BCH(p+q,q) code to the polynomial over GF(2), given the proper 5.393 +// genpoly. the both input and output are in binary numbers, and unlike 5.394 +// calculateecc genpoly should include the 1 bit for the highest degree. 5.395 +// 5.396 +// actual polynomials used for this procedure are as follows: 5.397 +// - p=10, q=5, genpoly=x^10+x^8+x^5+x^4+x^2+x+1 (JIS X 0510:2004 Appendix C) 5.398 +// - p=18, q=6, genpoly=x^12+x^11+x^10+x^9+x^8+x^5+x^2+1 (ibid. Appendix D) 5.399 +var augumentbch = function(poly, p, genpoly, q) { 5.400 + var modulus = poly << q; 5.401 + for (var i = p - 1; i >= 0; --i) { 5.402 + if ((modulus >> (q+i)) & 1) modulus ^= genpoly << i; 5.403 + } 5.404 + return (poly << q) | modulus; 5.405 +}; 5.406 + 5.407 +// creates the base matrix for given version. it returns two matrices, one of 5.408 +// them is the actual one and the another represents the "reserved" portion 5.409 +// (e.g. finder and timing patterns) of the matrix. 5.410 +// 5.411 +// some entries in the matrix may be undefined, rather than 0 or 1. this is 5.412 +// intentional (no initialization needed!), and putdata below will fill 5.413 +// the remaining ones. 5.414 +var makebasematrix = function(ver) { 5.415 + var v = VERSIONS[ver], n = getsizebyver(ver); 5.416 + var matrix = [], reserved = []; 5.417 + for (var i = 0; i < n; ++i) { 5.418 + matrix.push([]); 5.419 + reserved.push([]); 5.420 + } 5.421 + 5.422 + var blit = function(y, x, h, w, bits) { 5.423 + for (var i = 0; i < h; ++i) { 5.424 + for (var j = 0; j < w; ++j) { 5.425 + matrix[y+i][x+j] = (bits[i] >> j) & 1; 5.426 + reserved[y+i][x+j] = 1; 5.427 + } 5.428 + } 5.429 + }; 5.430 + 5.431 + // finder patterns and a part of timing patterns 5.432 + // will also mark the format information area (not yet written) as reserved. 5.433 + blit(0, 0, 9, 9, [0x7f, 0x41, 0x5d, 0x5d, 0x5d, 0x41, 0x17f, 0x00, 0x40]); 5.434 + blit(n-8, 0, 8, 9, [0x100, 0x7f, 0x41, 0x5d, 0x5d, 0x5d, 0x41, 0x7f]); 5.435 + blit(0, n-8, 9, 8, [0xfe, 0x82, 0xba, 0xba, 0xba, 0x82, 0xfe, 0x00, 0x00]); 5.436 + 5.437 + // the rest of timing patterns 5.438 + for (var i = 9; i < n-8; ++i) { 5.439 + matrix[6][i] = matrix[i][6] = ~i & 1; 5.440 + reserved[6][i] = reserved[i][6] = 1; 5.441 + } 5.442 + 5.443 + // alignment patterns 5.444 + var aligns = v[2], m = aligns.length; 5.445 + for (var i = 0; i < m; ++i) { 5.446 + var minj = (i==0 || i==m-1 ? 1 : 0), maxj = (i==0 ? m-1 : m); 5.447 + for (var j = minj; j < maxj; ++j) { 5.448 + blit(aligns[i], aligns[j], 5, 5, [0x1f, 0x11, 0x15, 0x11, 0x1f]); 5.449 + } 5.450 + } 5.451 + 5.452 + // version information 5.453 + if (needsverinfo(ver)) { 5.454 + var code = augumentbch(ver, 6, 0x1f25, 12); 5.455 + var k = 0; 5.456 + for (var i = 0; i < 6; ++i) { 5.457 + for (var j = 0; j < 3; ++j) { 5.458 + matrix[i][(n-11)+j] = matrix[(n-11)+j][i] = (code >> k++) & 1; 5.459 + reserved[i][(n-11)+j] = reserved[(n-11)+j][i] = 1; 5.460 + } 5.461 + } 5.462 + } 5.463 + 5.464 + return {matrix: matrix, reserved: reserved}; 5.465 +}; 5.466 + 5.467 +// fills the data portion (i.e. unmarked in reserved) of the matrix with given 5.468 +// code words. the size of code words should be no more than available bits, 5.469 +// and remaining bits are padded to 0 (cf. JIS X 0510:2004 sec 8.7.3). 5.470 +var putdata = function(matrix, reserved, buf) { 5.471 + var n = matrix.length; 5.472 + var k = 0, dir = -1; 5.473 + for (var i = n-1; i >= 0; i -= 2) { 5.474 + if (i == 6) --i; // skip the entire timing pattern column 5.475 + var jj = (dir < 0 ? n-1 : 0); 5.476 + for (var j = 0; j < n; ++j) { 5.477 + for (var ii = i; ii > i-2; --ii) { 5.478 + if (!reserved[jj][ii]) { 5.479 + // may overflow, but (undefined >> x) 5.480 + // is 0 so it will auto-pad to zero. 5.481 + matrix[jj][ii] = (buf[k >> 3] >> (~k&7)) & 1; 5.482 + ++k; 5.483 + } 5.484 + } 5.485 + jj += dir; 5.486 + } 5.487 + dir = -dir; 5.488 + } 5.489 + return matrix; 5.490 +}; 5.491 + 5.492 +// XOR-masks the data portion of the matrix. repeating the call with the same 5.493 +// arguments will revert the prior call (convenient in the matrix evaluation). 5.494 +var maskdata = function(matrix, reserved, mask) { 5.495 + var maskf = MASKFUNCS[mask]; 5.496 + var n = matrix.length; 5.497 + for (var i = 0; i < n; ++i) { 5.498 + for (var j = 0; j < n; ++j) { 5.499 + if (!reserved[i][j]) matrix[i][j] ^= maskf(i,j); 5.500 + } 5.501 + } 5.502 + return matrix; 5.503 +} 5.504 + 5.505 +// puts the format information. 5.506 +var putformatinfo = function(matrix, reserved, ecclevel, mask) { 5.507 + var n = matrix.length; 5.508 + var code = augumentbch((ecclevel << 3) | mask, 5, 0x537, 10) ^ 0x5412; 5.509 + for (var i = 0; i < 15; ++i) { 5.510 + var r = [0,1,2,3,4,5,7,8,n-7,n-6,n-5,n-4,n-3,n-2,n-1][i]; 5.511 + var c = [n-1,n-2,n-3,n-4,n-5,n-6,n-7,n-8,7,5,4,3,2,1,0][i]; 5.512 + matrix[r][8] = matrix[8][c] = (code >> i) & 1; 5.513 + // we don't have to mark those bits reserved; always done 5.514 + // in makebasematrix above. 5.515 + } 5.516 + return matrix; 5.517 +}; 5.518 + 5.519 +// evaluates the resulting matrix and returns the score (lower is better). 5.520 +// (cf. JIS X 0510:2004 sec 8.8.2) 5.521 +// 5.522 +// the evaluation procedure tries to avoid the problematic patterns naturally 5.523 +// occuring from the original matrix. for example, it penaltizes the patterns 5.524 +// which just look like the finder pattern which will confuse the decoder. 5.525 +// we choose the mask which results in the lowest score among 8 possible ones. 5.526 +// 5.527 +// note: zxing seems to use the same procedure and in many cases its choice 5.528 +// agrees to ours, but sometimes it does not. practically it doesn't matter. 5.529 +var evaluatematrix = function(matrix) { 5.530 + // N1+(k-5) points for each consecutive row of k same-colored modules, where k >= 5. no overlapping row counts. 5.531 + var PENALTY_CONSECUTIVE = 3; 5.532 + // N2 points for each 2x2 block of same-colored modules. Overlapping block does count. 5.533 + var PENALTY_TWOBYTWO = 3; 5.534 + // N3 points for each pattern with >4W:1B:1W:3B:1W:1B or 5.535 + // 1B:1W:3B:1W:1B:>4W, or their multiples (e.g. highly unlikely, but 13W:3B:3W:9B:3W:3B counts). 5.536 + var PENALTY_FINDERLIKE = 40; 5.537 + // N4*k points for every (5*k)% deviation from 50% black density. 5.538 + // i.e. k=1 for 55~60% and 40~45%, k=2 for 60~65% and 35~40%, etc. 5.539 + var PENALTY_DENSITY = 10; 5.540 + 5.541 + var evaluategroup = function(groups) { // assumes [W,B,W,B,W,...,B,W] 5.542 + var score = 0; 5.543 + for (var i = 0; i < groups.length; ++i) { 5.544 + if (groups[i] >= 5) score += PENALTY_CONSECUTIVE + (groups[i]-5); 5.545 + } 5.546 + for (var i = 5; i < groups.length; i += 2) { 5.547 + var p = groups[i]; 5.548 + if (groups[i-1] == p && groups[i-2] == 3*p && groups[i-3] == p && 5.549 + groups[i-4] == p && (groups[i-5] >= 4*p || groups[i+1] >= 4*p)) { 5.550 + // this part differs from zxing... 5.551 + score += PENALTY_FINDERLIKE; 5.552 + } 5.553 + } 5.554 + return score; 5.555 + }; 5.556 + 5.557 + var n = matrix.length; 5.558 + var score = 0, nblacks = 0; 5.559 + for (var i = 0; i < n; ++i) { 5.560 + var row = matrix[i]; 5.561 + var groups; 5.562 + 5.563 + // evaluate the current row 5.564 + groups = [0]; // the first empty group of white 5.565 + for (var j = 0; j < n; ) { 5.566 + var k; 5.567 + for (k = 0; j < n && row[j]; ++k) ++j; 5.568 + groups.push(k); 5.569 + for (k = 0; j < n && !row[j]; ++k) ++j; 5.570 + groups.push(k); 5.571 + } 5.572 + score += evaluategroup(groups); 5.573 + 5.574 + // evaluate the current column 5.575 + groups = [0]; 5.576 + for (var j = 0; j < n; ) { 5.577 + var k; 5.578 + for (k = 0; j < n && matrix[j][i]; ++k) ++j; 5.579 + groups.push(k); 5.580 + for (k = 0; j < n && !matrix[j][i]; ++k) ++j; 5.581 + groups.push(k); 5.582 + } 5.583 + score += evaluategroup(groups); 5.584 + 5.585 + // check the 2x2 box and calculate the density 5.586 + var nextrow = matrix[i+1] || []; 5.587 + nblacks += row[0]; 5.588 + for (var j = 1; j < n; ++j) { 5.589 + var p = row[j]; 5.590 + nblacks += p; 5.591 + // at least comparison with next row should be strict... 5.592 + if (row[j-1] == p && nextrow[j] === p && nextrow[j-1] === p) { 5.593 + score += PENALTY_TWOBYTWO; 5.594 + } 5.595 + } 5.596 + } 5.597 + 5.598 + score += PENALTY_DENSITY * ((Math.abs(nblacks / n / n - 0.5) / 0.05) | 0); 5.599 + return score; 5.600 +}; 5.601 + 5.602 +// returns the fully encoded QR code matrix which contains given data. 5.603 +// it also chooses the best mask automatically when mask is -1. 5.604 +var generate = function(data, ver, mode, ecclevel, mask) { 5.605 + var v = VERSIONS[ver]; 5.606 + var buf = encode(ver, mode, data, ndatabits(ver, ecclevel) >> 3); 5.607 + buf = augumenteccs(buf, v[1][ecclevel], GF256_GENPOLY[v[0][ecclevel]]); 5.608 + 5.609 + var result = makebasematrix(ver); 5.610 + var matrix = result.matrix, reserved = result.reserved; 5.611 + putdata(matrix, reserved, buf); 5.612 + 5.613 + if (mask < 0) { 5.614 + // find the best mask 5.615 + maskdata(matrix, reserved, 0); 5.616 + putformatinfo(matrix, reserved, ecclevel, 0); 5.617 + var bestmask = 0, bestscore = evaluatematrix(matrix); 5.618 + maskdata(matrix, reserved, 0); 5.619 + for (mask = 1; mask < 8; ++mask) { 5.620 + maskdata(matrix, reserved, mask); 5.621 + putformatinfo(matrix, reserved, ecclevel, mask); 5.622 + var score = evaluatematrix(matrix); 5.623 + if (bestscore > score) { 5.624 + bestscore = score; 5.625 + bestmask = mask; 5.626 + } 5.627 + maskdata(matrix, reserved, mask); 5.628 + } 5.629 + mask = bestmask; 5.630 + } 5.631 + 5.632 + maskdata(matrix, reserved, mask); 5.633 + putformatinfo(matrix, reserved, ecclevel, mask); 5.634 + return matrix; 5.635 +}; 5.636 + 5.637 +// the public interface is trivial; the options available are as follows: 5.638 +// 5.639 +// - version: an integer in [1,40]. when omitted (or -1) the smallest possible 5.640 +// version is chosen. 5.641 +// - mode: one of 'numeric', 'alphanumeric', 'octet'. when omitted the smallest 5.642 +// possible mode is chosen. 5.643 +// - ecclevel: one of 'L', 'M', 'Q', 'H'. defaults to 'L'. 5.644 +// - mask: an integer in [0,7]. when omitted (or -1) the best mask is chosen. 5.645 +// 5.646 +// for generate{HTML,PNG}: 5.647 +// 5.648 +// - modulesize: a number. this is a size of each modules in pixels, and 5.649 +// defaults to 5px. 5.650 +// - margin: a number. this is a size of margin in *modules*, and defaults to 5.651 +// 4 (white modules). the specficiation mandates the margin no less than 4 5.652 +// modules, so it is better not to alter this value unless you know what 5.653 +// you're doing. 5.654 +var QRCode = { 5.655 + 'generate': function(data, options) { 5.656 + var MODES = {'numeric': MODE_NUMERIC, 'alphanumeric': MODE_ALPHANUMERIC, 5.657 + 'octet': MODE_OCTET}; 5.658 + var ECCLEVELS = {'L': ECCLEVEL_L, 'M': ECCLEVEL_M, 'Q': ECCLEVEL_Q, 5.659 + 'H': ECCLEVEL_H}; 5.660 + 5.661 + options = options || {}; 5.662 + var ver = options.version || -1; 5.663 + var ecclevel = ECCLEVELS[(options.ecclevel || 'L').toUpperCase()]; 5.664 + var mode = options.mode ? MODES[options.mode.toLowerCase()] : -1; 5.665 + var mask = 'mask' in options ? options.mask : -1; 5.666 + 5.667 + if (mode < 0) { 5.668 + if (typeof data === 'string') { 5.669 + if (data.match(NUMERIC_REGEXP)) { 5.670 + mode = MODE_NUMERIC; 5.671 + } else if (data.match(ALPHANUMERIC_OUT_REGEXP)) { 5.672 + // while encode supports case-insensitive 5.673 + // encoding, we restrict the data to be 5.674 + // uppercased when auto-selecting the mode. 5.675 + mode = MODE_ALPHANUMERIC; 5.676 + } else { 5.677 + mode = MODE_OCTET; 5.678 + } 5.679 + } else { 5.680 + mode = MODE_OCTET; 5.681 + } 5.682 + } else if (!(mode == MODE_NUMERIC || mode == MODE_ALPHANUMERIC || 5.683 + mode == MODE_OCTET)) { 5.684 + throw 'invalid or unsupported mode'; 5.685 + } 5.686 + 5.687 + data = validatedata(mode, data); 5.688 + if (data === null) throw 'invalid data format'; 5.689 + 5.690 + if (ecclevel < 0 || ecclevel > 3) throw 'invalid ECC level'; 5.691 + 5.692 + if (ver < 0) { 5.693 + for (ver = 1; ver <= 40; ++ver) { 5.694 + if (data.length <= getmaxdatalen(ver, mode, ecclevel)) break; 5.695 + } 5.696 + if (ver > 40) throw 'too large data'; 5.697 + } else if (ver < 1 || ver > 40) { 5.698 + throw 'invalid version'; 5.699 + } 5.700 + 5.701 + if (mask != -1 && (mask < 0 || mask > 8)) throw 'invalid mask'; 5.702 + 5.703 + return generate(data, ver, mode, ecclevel, mask); 5.704 + }, 5.705 + 5.706 + 5.707 + 'generatePNG': function(data, options) { 5.708 + options = options || {}; 5.709 + var matrix = QRCode['generate'](data, options); 5.710 + var modsize = Math.max(options.modulesize || 5, 0.5); 5.711 + var margin = Math.max(options.margin || 4, 0.0); 5.712 + var n = matrix.length; 5.713 + var size = modsize * (n + 2 * margin); 5.714 + 5.715 + var canvas = document.createElement('canvas'), context; 5.716 + canvas.width = canvas.height = size; 5.717 + context = canvas.getContext('2d'); 5.718 + if (!context) throw 'canvas support is needed for PNG output'; 5.719 + 5.720 + context.fillStyle = '#fff'; 5.721 + context.fillRect(0, 0, size, size); 5.722 + context.fillStyle = '#000'; 5.723 + for (var i = 0; i < n; ++i) { 5.724 + for (var j = 0; j < n; ++j) { 5.725 + if (matrix[i][j]) { 5.726 + context.fillRect(modsize * (margin + j), modsize * (margin + i), modsize, modsize); 5.727 + } 5.728 + } 5.729 + } 5.730 + //context.fillText('evaluation: ' + evaluatematrix(matrix), 10, 10); 5.731 + return canvas.toDataURL(); 5.732 + } 5.733 +}; 5.734 + 5.735 +return QRCode; 5.736 +})();
6.1 --- a/tank/web/lib/html/footer.html Mon Mar 25 18:34:38 2013 +0100 6.2 +++ b/tank/web/lib/html/footer.html Mon Mar 25 18:45:42 2013 +0100 6.3 @@ -1,4 +1,7 @@ 6.4 <!-- Footer --> 6.5 + 6.6 +<script type="text/javascript" src="qrcode.js"></script> 6.7 + 6.8 <div id="footer"> 6.9 Copyright © <span class="year"></span> 6.10 <a href="http://www.slitaz.org/">SliTaz</a> - Network: 6.11 @@ -9,7 +12,8 @@ 6.12 <a href="http://bugs.slitaz.org">Bugs</a> 6.13 <a href="http://hg.slitaz.org/?sort=lastchange">Hg</a> 6.14 <p> 6.15 - SliTaz @ 6.16 + <img src="#" alt="SliTaz @" onmouseover="this.title = location.href" 6.17 + onclick="this.src = QRCode.generatePNG(location.href, {ecclevel: 'H'})" /> 6.18 <a href="http://twitter.com/slitaz">Twitter</a> 6.19 <a href="http://www.facebook.com/slitaz">Facebook</a> 6.20 <a href="http://distrowatch.com/slitaz">Distrowatch</a>
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/tank/web/lib/html/qrcode.js Mon Mar 25 18:45:42 2013 +0100 7.3 @@ -0,0 +1,733 @@ 7.4 +/* qr.js -- QR code generator in Javascript (revision 2011-01-19) 7.5 + * Written by Kang Seonghoon <public+qrjs@mearie.org>. 7.6 + * 7.7 + * This source code is in the public domain; if your jurisdiction does not 7.8 + * recognize the public domain the terms of Creative Commons CC0 license 7.9 + * apply. In the other words, you can always do what you want. 7.10 + */ 7.11 + 7.12 +var QRCode = (function(){ 7.13 + 7.14 +/* Quick overview: QR code composed of 2D array of modules (a rectangular 7.15 + * area that conveys one bit of information); some modules are fixed to help 7.16 + * the recognition of the code, and remaining data modules are further divided 7.17 + * into 8-bit code words which are augumented by Reed-Solomon error correcting 7.18 + * codes (ECC). There could be multiple ECCs, in the case the code is so large 7.19 + * that it is helpful to split the raw data into several chunks. 7.20 + * 7.21 + * The number of modules is determined by the code's "version", ranging from 1 7.22 + * (21x21) to 40 (177x177). How many ECC bits are used is determined by the 7.23 + * ECC level (L/M/Q/H). The number and size (and thus the order of generator 7.24 + * polynomial) of ECCs depend to the version and ECC level. 7.25 + */ 7.26 + 7.27 +// per-version information (cf. JIS X 0510:2004 pp. 30--36, 71) 7.28 +// 7.29 +// [0]: the degree of generator polynomial by ECC levels 7.30 +// [1]: # of code blocks by ECC levels 7.31 +// [2]: left-top positions of alignment patterns 7.32 +// 7.33 +// the number in this table (in particular, [0]) does not exactly match with 7.34 +// the numbers in the specficiation. see augumenteccs below for the reason. 7.35 +var VERSIONS = [ 7.36 + null, 7.37 + [[10, 7,17,13], [ 1, 1, 1, 1], []], 7.38 + [[16,10,28,22], [ 1, 1, 1, 1], [4,16]], 7.39 + [[26,15,22,18], [ 1, 1, 2, 2], [4,20]], 7.40 + [[18,20,16,26], [ 2, 1, 4, 2], [4,24]], 7.41 + [[24,26,22,18], [ 2, 1, 4, 4], [4,28]], 7.42 + [[16,18,28,24], [ 4, 2, 4, 4], [4,32]], 7.43 + [[18,20,26,18], [ 4, 2, 5, 6], [4,20,36]], 7.44 + [[22,24,26,22], [ 4, 2, 6, 6], [4,22,40]], 7.45 + [[22,30,24,20], [ 5, 2, 8, 8], [4,24,44]], 7.46 + [[26,18,28,24], [ 5, 4, 8, 8], [4,26,48]], 7.47 + [[30,20,24,28], [ 5, 4,11, 8], [4,28,52]], 7.48 + [[22,24,28,26], [ 8, 4,11,10], [4,30,56]], 7.49 + [[22,26,22,24], [ 9, 4,16,12], [4,32,60]], 7.50 + [[24,30,24,20], [ 9, 4,16,16], [4,24,44,64]], 7.51 + [[24,22,24,30], [10, 6,18,12], [4,24,46,68]], 7.52 + [[28,24,30,24], [10, 6,16,17], [4,24,48,72]], 7.53 + [[28,28,28,28], [11, 6,19,16], [4,28,52,76]], 7.54 + [[26,30,28,28], [13, 6,21,18], [4,28,54,80]], 7.55 + [[26,28,26,26], [14, 7,25,21], [4,28,56,84]], 7.56 + [[26,28,28,30], [16, 8,25,20], [4,32,60,88]], 7.57 + [[26,28,30,28], [17, 8,25,23], [4,26,48,70,92]], 7.58 + [[28,28,24,30], [17, 9,34,23], [4,24,48,72,96]], 7.59 + [[28,30,30,30], [18, 9,30,25], [4,28,52,76,100]], 7.60 + [[28,30,30,30], [20,10,32,27], [4,26,52,78,104]], 7.61 + [[28,26,30,30], [21,12,35,29], [4,30,56,82,108]], 7.62 + [[28,28,30,28], [23,12,37,34], [4,28,56,84,112]], 7.63 + [[28,30,30,30], [25,12,40,34], [4,32,60,88,116]], 7.64 + [[28,30,30,30], [26,13,42,35], [4,24,48,72,96,120]], 7.65 + [[28,30,30,30], [28,14,45,38], [4,28,52,76,100,124]], 7.66 + [[28,30,30,30], [29,15,48,40], [4,24,50,76,102,128]], 7.67 + [[28,30,30,30], [31,16,51,43], [4,28,54,80,106,132]], 7.68 + [[28,30,30,30], [33,17,54,45], [4,32,58,84,110,136]], 7.69 + [[28,30,30,30], [35,18,57,48], [4,28,56,84,112,140]], 7.70 + [[28,30,30,30], [37,19,60,51], [4,32,60,88,116,144]], 7.71 + [[28,30,30,30], [38,19,63,53], [4,28,52,76,100,124,148]], 7.72 + [[28,30,30,30], [40,20,66,56], [4,22,48,74,100,126,152]], 7.73 + [[28,30,30,30], [43,21,70,59], [4,26,52,78,104,130,156]], 7.74 + [[28,30,30,30], [45,22,74,62], [4,30,56,82,108,134,160]], 7.75 + [[28,30,30,30], [47,24,77,65], [4,24,52,80,108,136,164]], 7.76 + [[28,30,30,30], [49,25,81,68], [4,28,56,84,112,140,168]]]; 7.77 + 7.78 +// mode constants (cf. Table 2 in JIS X 0510:2004 p. 16) 7.79 +var MODE_TERMINATOR = 0; 7.80 +var MODE_NUMERIC = 1, MODE_ALPHANUMERIC = 2, MODE_OCTET = 4, MODE_KANJI = 8; 7.81 + 7.82 +// validation regexps 7.83 +var NUMERIC_REGEXP = /^\d*$/; 7.84 +var ALPHANUMERIC_REGEXP = /^[A-Za-z0-9 $%*+\-./:]*$/; 7.85 +var ALPHANUMERIC_OUT_REGEXP = /^[A-Z0-9 $%*+\-./:]*$/; 7.86 + 7.87 +// ECC levels (cf. Table 22 in JIS X 0510:2004 p. 45) 7.88 +var ECCLEVEL_L = 1, ECCLEVEL_M = 0, ECCLEVEL_Q = 3, ECCLEVEL_H = 2; 7.89 + 7.90 +// GF(2^8)-to-integer mapping with a reducing polynomial x^8+x^4+x^3+x^2+1 7.91 +// invariant: GF256_MAP[GF256_INVMAP[i]] == i for all i in [1,256) 7.92 +var GF256_MAP = [], GF256_INVMAP = [-1]; 7.93 +for (var i = 0, v = 1; i < 255; ++i) { 7.94 + GF256_MAP.push(v); 7.95 + GF256_INVMAP[v] = i; 7.96 + v = (v * 2) ^ (v >= 128 ? 0x11d : 0); 7.97 +} 7.98 + 7.99 +// generator polynomials up to degree 30 7.100 +// (should match with polynomials in JIS X 0510:2004 Appendix A) 7.101 +// 7.102 +// generator polynomial of degree K is product of (x-\alpha^0), (x-\alpha^1), 7.103 +// ..., (x-\alpha^(K-1)). by convention, we omit the K-th coefficient (always 1) 7.104 +// from the result; also other coefficients are written in terms of the exponent 7.105 +// to \alpha to avoid the redundant calculation. (see also calculateecc below.) 7.106 +var GF256_GENPOLY = [[]]; 7.107 +for (var i = 0; i < 30; ++i) { 7.108 + var prevpoly = GF256_GENPOLY[i], poly = []; 7.109 + for (var j = 0; j <= i; ++j) { 7.110 + var a = (j < i ? GF256_MAP[prevpoly[j]] : 0); 7.111 + var b = GF256_MAP[(i + (prevpoly[j-1] || 0)) % 255]; 7.112 + poly.push(GF256_INVMAP[a ^ b]); 7.113 + } 7.114 + GF256_GENPOLY.push(poly); 7.115 +} 7.116 + 7.117 +// alphanumeric character mapping (cf. Table 5 in JIS X 0510:2004 p. 19) 7.118 +var ALPHANUMERIC_MAP = {}; 7.119 +for (var i = 0; i < 45; ++i) { 7.120 + ALPHANUMERIC_MAP['0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'.charAt(i)] = i; 7.121 +} 7.122 + 7.123 +// mask functions in terms of row # and column # 7.124 +// (cf. Table 20 in JIS X 0510:2004 p. 42) 7.125 +var MASKFUNCS = [ 7.126 + function(i,j) { return (i+j) % 2 == 0; }, 7.127 + function(i,j) { return i % 2 == 0; }, 7.128 + function(i,j) { return j % 3 == 0; }, 7.129 + function(i,j) { return (i+j) % 3 == 0; }, 7.130 + function(i,j) { return (((i/2)|0) + ((j/3)|0)) % 2 == 0; }, 7.131 + function(i,j) { return (i*j) % 2 + (i*j) % 3 == 0; }, 7.132 + function(i,j) { return ((i*j) % 2 + (i*j) % 3) % 2 == 0; }, 7.133 + function(i,j) { return ((i+j) % 2 + (i*j) % 3) % 2 == 0; }]; 7.134 + 7.135 +// returns true when the version information has to be embeded. 7.136 +var needsverinfo = function(ver) { return ver > 6; }; 7.137 + 7.138 +// returns the size of entire QR code for given version. 7.139 +var getsizebyver = function(ver) { return 4 * ver + 17; }; 7.140 + 7.141 +// returns the number of bits available for code words in this version. 7.142 +var nfullbits = function(ver) { 7.143 + /* 7.144 + * |<--------------- n --------------->| 7.145 + * | |<----- n-17 ---->| | 7.146 + * +-------+ ///+-------+ ---- 7.147 + * | | ///| | ^ 7.148 + * | 9x9 | @@@@@ ///| 9x8 | | 7.149 + * | | # # # @5x5@ # # # | | | 7.150 + * +-------+ @@@@@ +-------+ | 7.151 + * # ---| 7.152 + * ^ | 7.153 + * # | 7.154 + * @@@@@ @@@@@ @@@@@ | n 7.155 + * @5x5@ @5x5@ @5x5@ n-17 7.156 + * @@@@@ @@@@@ @@@@@ | | 7.157 + * # | | 7.158 + * ////// v | 7.159 + * //////# ---| 7.160 + * +-------+ @@@@@ @@@@@ | 7.161 + * | | @5x5@ @5x5@ | 7.162 + * | 8x9 | @@@@@ @@@@@ | 7.163 + * | | v 7.164 + * +-------+ ---- 7.165 + * 7.166 + * when the entire code has n^2 modules and there are m^2-3 alignment 7.167 + * patterns, we have: 7.168 + * - 225 (= 9x9 + 9x8 + 8x9) modules for finder patterns and 7.169 + * format information; 7.170 + * - 2n-34 (= 2(n-17)) modules for timing patterns; 7.171 + * - 36 (= 3x6 + 6x3) modules for version information, if any; 7.172 + * - 25m^2-75 (= (m^2-3)(5x5)) modules for alignment patterns 7.173 + * if any, but 10m-20 (= 2(m-2)x5) of them overlaps with 7.174 + * timing patterns. 7.175 + */ 7.176 + var v = VERSIONS[ver]; 7.177 + var nbits = 16*ver*ver + 128*ver + 64; // finder, timing and format info. 7.178 + if (needsverinfo(ver)) nbits -= 36; // version information 7.179 + if (v[2].length) { // alignment patterns 7.180 + nbits -= 25 * v[2].length * v[2].length - 10 * v[2].length - 55; 7.181 + } 7.182 + return nbits; 7.183 +}; 7.184 + 7.185 +// returns the number of bits available for data portions (i.e. excludes ECC 7.186 +// bits but includes mode and length bits) in this version and ECC level. 7.187 +var ndatabits = function(ver, ecclevel) { 7.188 + var nbits = nfullbits(ver) & ~7; // no sub-octet code words 7.189 + var v = VERSIONS[ver]; 7.190 + nbits -= 8 * v[0][ecclevel] * v[1][ecclevel]; // ecc bits 7.191 + return nbits; 7.192 +} 7.193 + 7.194 +// returns the number of bits required for the length of data. 7.195 +// (cf. Table 3 in JIS X 0510:2004 p. 16) 7.196 +var ndatalenbits = function(ver, mode) { 7.197 + switch (mode) { 7.198 + case MODE_NUMERIC: return (ver < 10 ? 10 : ver < 27 ? 12 : 14); 7.199 + case MODE_ALPHANUMERIC: return (ver < 10 ? 9 : ver < 27 ? 11 : 13); 7.200 + case MODE_OCTET: return (ver < 10 ? 8 : 16); 7.201 + case MODE_KANJI: return (ver < 10 ? 8 : ver < 27 ? 10 : 12); 7.202 + } 7.203 +}; 7.204 + 7.205 +// returns the maximum length of data possible in given configuration. 7.206 +var getmaxdatalen = function(ver, mode, ecclevel) { 7.207 + var nbits = ndatabits(ver, ecclevel) - 4 - ndatalenbits(ver, mode); // 4 for mode bits 7.208 + switch (mode) { 7.209 + case MODE_NUMERIC: 7.210 + return ((nbits/10) | 0) * 3 + (nbits%10 < 4 ? 0 : nbits%10 < 7 ? 1 : 2); 7.211 + case MODE_ALPHANUMERIC: 7.212 + return ((nbits/11) | 0) * 2 + (nbits%11 < 6 ? 0 : 1); 7.213 + case MODE_OCTET: 7.214 + return (nbits/8) | 0; 7.215 + case MODE_KANJI: 7.216 + return (nbits/13) | 0; 7.217 + } 7.218 +}; 7.219 + 7.220 +// checks if the given data can be encoded in given mode, and returns 7.221 +// the converted data for the further processing if possible. otherwise 7.222 +// returns null. 7.223 +// 7.224 +// this function does not check the length of data; it is a duty of 7.225 +// encode function below (as it depends on the version and ECC level too). 7.226 +var validatedata = function(mode, data) { 7.227 + switch (mode) { 7.228 + case MODE_NUMERIC: 7.229 + if (!data.match(NUMERIC_REGEXP)) return null; 7.230 + return data; 7.231 + 7.232 + case MODE_ALPHANUMERIC: 7.233 + if (!data.match(ALPHANUMERIC_REGEXP)) return null; 7.234 + return data.toUpperCase(); 7.235 + 7.236 + case MODE_OCTET: 7.237 + if (typeof data === 'string') { // encode as utf-8 string 7.238 + var newdata = []; 7.239 + for (var i = 0; i < data.length; ++i) { 7.240 + var ch = data.charCodeAt(i); 7.241 + if (ch < 0x80) { 7.242 + newdata.push(ch); 7.243 + } else if (ch < 0x800) { 7.244 + newdata.push(0xc0 | (ch >> 6), 7.245 + 0x80 | (ch & 0x3f)); 7.246 + } else if (ch < 0x10000) { 7.247 + newdata.push(0xe0 | (ch >> 12), 7.248 + 0x80 | ((ch >> 6) & 0x3f), 7.249 + 0x80 | (ch & 0x3f)); 7.250 + } else { 7.251 + newdata.push(0xf0 | (ch >> 18), 7.252 + 0x80 | ((ch >> 12) & 0x3f), 7.253 + 0x80 | ((ch >> 6) & 0x3f), 7.254 + 0x80 | (ch & 0x3f)); 7.255 + } 7.256 + } 7.257 + return newdata; 7.258 + } else { 7.259 + return data; 7.260 + } 7.261 + } 7.262 +}; 7.263 + 7.264 +// returns the code words (sans ECC bits) for given data and configurations. 7.265 +// requires data to be preprocessed by validatedata. no length check is 7.266 +// performed, and everything has to be checked before calling this function. 7.267 +var encode = function(ver, mode, data, maxbuflen) { 7.268 + var buf = []; 7.269 + var bits = 0, remaining = 8; 7.270 + var datalen = data.length; 7.271 + 7.272 + // this function is intentionally no-op when n=0. 7.273 + var pack = function(x, n) { 7.274 + if (n >= remaining) { 7.275 + buf.push(bits | (x >> (n -= remaining))); 7.276 + while (n >= 8) buf.push((x >> (n -= 8)) & 255); 7.277 + bits = 0; 7.278 + remaining = 8; 7.279 + } 7.280 + if (n > 0) bits |= (x & ((1 << n) - 1)) << (remaining -= n); 7.281 + }; 7.282 + 7.283 + var nlenbits = ndatalenbits(ver, mode); 7.284 + pack(mode, 4); 7.285 + pack(datalen, nlenbits); 7.286 + 7.287 + switch (mode) { 7.288 + case MODE_NUMERIC: 7.289 + for (var i = 2; i < datalen; i += 3) { 7.290 + pack(parseInt(data.substring(i-2,i+1), 10), 10); 7.291 + } 7.292 + pack(parseInt(data.substring(i-2), 10), [0,4,7][datalen%3]); 7.293 + break; 7.294 + 7.295 + case MODE_ALPHANUMERIC: 7.296 + for (var i = 1; i < datalen; i += 2) { 7.297 + pack(ALPHANUMERIC_MAP[data.charAt(i-1)] * 45 + 7.298 + ALPHANUMERIC_MAP[data.charAt(i)], 11); 7.299 + } 7.300 + if (datalen % 2 == 1) { 7.301 + pack(ALPHANUMERIC_MAP[data.charAt(i-1)], 6); 7.302 + } 7.303 + break; 7.304 + 7.305 + case MODE_OCTET: 7.306 + for (var i = 0; i < datalen; ++i) { 7.307 + pack(data[i], 8); 7.308 + } 7.309 + break; 7.310 + }; 7.311 + 7.312 + // final bits. it is possible that adding terminator causes the buffer 7.313 + // to overflow, but then the buffer truncated to the maximum size will 7.314 + // be valid as the truncated terminator mode bits and padding is 7.315 + // identical in appearance (cf. JIS X 0510:2004 sec 8.4.8). 7.316 + pack(MODE_TERMINATOR, 4); 7.317 + if (remaining < 8) buf.push(bits); 7.318 + 7.319 + // the padding to fill up the remaining space. we should not add any 7.320 + // words when the overflow already occurred. 7.321 + while (buf.length + 1 < maxbuflen) buf.push(0xec, 0x11); 7.322 + if (buf.length < maxbuflen) buf.push(0xec); 7.323 + return buf; 7.324 +}; 7.325 + 7.326 +// calculates ECC code words for given code words and generator polynomial. 7.327 +// 7.328 +// this is quite similar to CRC calculation as both Reed-Solomon and CRC use 7.329 +// the certain kind of cyclic codes, which is effectively the division of 7.330 +// zero-augumented polynomial by the generator polynomial. the only difference 7.331 +// is that Reed-Solomon uses GF(2^8), instead of CRC's GF(2), and Reed-Solomon 7.332 +// uses the different generator polynomial than CRC's. 7.333 +var calculateecc = function(poly, genpoly) { 7.334 + var modulus = poly.slice(0); 7.335 + var polylen = poly.length, genpolylen = genpoly.length; 7.336 + for (var i = 0; i < genpolylen; ++i) modulus.push(0); 7.337 + for (var i = 0; i < polylen; ) { 7.338 + var quotient = GF256_INVMAP[modulus[i++]]; 7.339 + if (quotient >= 0) { 7.340 + for (var j = 0; j < genpolylen; ++j) { 7.341 + modulus[i+j] ^= GF256_MAP[(quotient + genpoly[j]) % 255]; 7.342 + } 7.343 + } 7.344 + } 7.345 + return modulus.slice(polylen); 7.346 +}; 7.347 + 7.348 +// auguments ECC code words to given code words. the resulting words are 7.349 +// ready to be encoded in the matrix. 7.350 +// 7.351 +// the much of actual augumenting procedure follows JIS X 0510:2004 sec 8.7. 7.352 +// the code is simplified using the fact that the size of each code & ECC 7.353 +// blocks is almost same; for example, when we have 4 blocks and 46 data words 7.354 +// the number of code words in those blocks are 11, 11, 12, 12 respectively. 7.355 +var augumenteccs = function(poly, nblocks, genpoly) { 7.356 + var subsizes = []; 7.357 + var subsize = (poly.length / nblocks) | 0, subsize0 = 0; 7.358 + var pivot = nblocks - poly.length % nblocks; 7.359 + for (var i = 0; i < pivot; ++i) { 7.360 + subsizes.push(subsize0); 7.361 + subsize0 += subsize; 7.362 + } 7.363 + for (var i = pivot; i < nblocks; ++i) { 7.364 + subsizes.push(subsize0); 7.365 + subsize0 += subsize+1; 7.366 + } 7.367 + subsizes.push(subsize0); 7.368 + 7.369 + var eccs = []; 7.370 + for (var i = 0; i < nblocks; ++i) { 7.371 + eccs.push(calculateecc(poly.slice(subsizes[i], subsizes[i+1]), genpoly)); 7.372 + } 7.373 + 7.374 + var result = []; 7.375 + var nitemsperblock = (poly.length / nblocks) | 0; 7.376 + for (var i = 0; i < nitemsperblock; ++i) { 7.377 + for (var j = 0; j < nblocks; ++j) { 7.378 + result.push(poly[subsizes[j] + i]); 7.379 + } 7.380 + } 7.381 + for (var j = pivot; j < nblocks; ++j) { 7.382 + result.push(poly[subsizes[j+1] - 1]); 7.383 + } 7.384 + for (var i = 0; i < genpoly.length; ++i) { 7.385 + for (var j = 0; j < nblocks; ++j) { 7.386 + result.push(eccs[j][i]); 7.387 + } 7.388 + } 7.389 + return result; 7.390 +}; 7.391 + 7.392 +// auguments BCH(p+q,q) code to the polynomial over GF(2), given the proper 7.393 +// genpoly. the both input and output are in binary numbers, and unlike 7.394 +// calculateecc genpoly should include the 1 bit for the highest degree. 7.395 +// 7.396 +// actual polynomials used for this procedure are as follows: 7.397 +// - p=10, q=5, genpoly=x^10+x^8+x^5+x^4+x^2+x+1 (JIS X 0510:2004 Appendix C) 7.398 +// - p=18, q=6, genpoly=x^12+x^11+x^10+x^9+x^8+x^5+x^2+1 (ibid. Appendix D) 7.399 +var augumentbch = function(poly, p, genpoly, q) { 7.400 + var modulus = poly << q; 7.401 + for (var i = p - 1; i >= 0; --i) { 7.402 + if ((modulus >> (q+i)) & 1) modulus ^= genpoly << i; 7.403 + } 7.404 + return (poly << q) | modulus; 7.405 +}; 7.406 + 7.407 +// creates the base matrix for given version. it returns two matrices, one of 7.408 +// them is the actual one and the another represents the "reserved" portion 7.409 +// (e.g. finder and timing patterns) of the matrix. 7.410 +// 7.411 +// some entries in the matrix may be undefined, rather than 0 or 1. this is 7.412 +// intentional (no initialization needed!), and putdata below will fill 7.413 +// the remaining ones. 7.414 +var makebasematrix = function(ver) { 7.415 + var v = VERSIONS[ver], n = getsizebyver(ver); 7.416 + var matrix = [], reserved = []; 7.417 + for (var i = 0; i < n; ++i) { 7.418 + matrix.push([]); 7.419 + reserved.push([]); 7.420 + } 7.421 + 7.422 + var blit = function(y, x, h, w, bits) { 7.423 + for (var i = 0; i < h; ++i) { 7.424 + for (var j = 0; j < w; ++j) { 7.425 + matrix[y+i][x+j] = (bits[i] >> j) & 1; 7.426 + reserved[y+i][x+j] = 1; 7.427 + } 7.428 + } 7.429 + }; 7.430 + 7.431 + // finder patterns and a part of timing patterns 7.432 + // will also mark the format information area (not yet written) as reserved. 7.433 + blit(0, 0, 9, 9, [0x7f, 0x41, 0x5d, 0x5d, 0x5d, 0x41, 0x17f, 0x00, 0x40]); 7.434 + blit(n-8, 0, 8, 9, [0x100, 0x7f, 0x41, 0x5d, 0x5d, 0x5d, 0x41, 0x7f]); 7.435 + blit(0, n-8, 9, 8, [0xfe, 0x82, 0xba, 0xba, 0xba, 0x82, 0xfe, 0x00, 0x00]); 7.436 + 7.437 + // the rest of timing patterns 7.438 + for (var i = 9; i < n-8; ++i) { 7.439 + matrix[6][i] = matrix[i][6] = ~i & 1; 7.440 + reserved[6][i] = reserved[i][6] = 1; 7.441 + } 7.442 + 7.443 + // alignment patterns 7.444 + var aligns = v[2], m = aligns.length; 7.445 + for (var i = 0; i < m; ++i) { 7.446 + var minj = (i==0 || i==m-1 ? 1 : 0), maxj = (i==0 ? m-1 : m); 7.447 + for (var j = minj; j < maxj; ++j) { 7.448 + blit(aligns[i], aligns[j], 5, 5, [0x1f, 0x11, 0x15, 0x11, 0x1f]); 7.449 + } 7.450 + } 7.451 + 7.452 + // version information 7.453 + if (needsverinfo(ver)) { 7.454 + var code = augumentbch(ver, 6, 0x1f25, 12); 7.455 + var k = 0; 7.456 + for (var i = 0; i < 6; ++i) { 7.457 + for (var j = 0; j < 3; ++j) { 7.458 + matrix[i][(n-11)+j] = matrix[(n-11)+j][i] = (code >> k++) & 1; 7.459 + reserved[i][(n-11)+j] = reserved[(n-11)+j][i] = 1; 7.460 + } 7.461 + } 7.462 + } 7.463 + 7.464 + return {matrix: matrix, reserved: reserved}; 7.465 +}; 7.466 + 7.467 +// fills the data portion (i.e. unmarked in reserved) of the matrix with given 7.468 +// code words. the size of code words should be no more than available bits, 7.469 +// and remaining bits are padded to 0 (cf. JIS X 0510:2004 sec 8.7.3). 7.470 +var putdata = function(matrix, reserved, buf) { 7.471 + var n = matrix.length; 7.472 + var k = 0, dir = -1; 7.473 + for (var i = n-1; i >= 0; i -= 2) { 7.474 + if (i == 6) --i; // skip the entire timing pattern column 7.475 + var jj = (dir < 0 ? n-1 : 0); 7.476 + for (var j = 0; j < n; ++j) { 7.477 + for (var ii = i; ii > i-2; --ii) { 7.478 + if (!reserved[jj][ii]) { 7.479 + // may overflow, but (undefined >> x) 7.480 + // is 0 so it will auto-pad to zero. 7.481 + matrix[jj][ii] = (buf[k >> 3] >> (~k&7)) & 1; 7.482 + ++k; 7.483 + } 7.484 + } 7.485 + jj += dir; 7.486 + } 7.487 + dir = -dir; 7.488 + } 7.489 + return matrix; 7.490 +}; 7.491 + 7.492 +// XOR-masks the data portion of the matrix. repeating the call with the same 7.493 +// arguments will revert the prior call (convenient in the matrix evaluation). 7.494 +var maskdata = function(matrix, reserved, mask) { 7.495 + var maskf = MASKFUNCS[mask]; 7.496 + var n = matrix.length; 7.497 + for (var i = 0; i < n; ++i) { 7.498 + for (var j = 0; j < n; ++j) { 7.499 + if (!reserved[i][j]) matrix[i][j] ^= maskf(i,j); 7.500 + } 7.501 + } 7.502 + return matrix; 7.503 +} 7.504 + 7.505 +// puts the format information. 7.506 +var putformatinfo = function(matrix, reserved, ecclevel, mask) { 7.507 + var n = matrix.length; 7.508 + var code = augumentbch((ecclevel << 3) | mask, 5, 0x537, 10) ^ 0x5412; 7.509 + for (var i = 0; i < 15; ++i) { 7.510 + var r = [0,1,2,3,4,5,7,8,n-7,n-6,n-5,n-4,n-3,n-2,n-1][i]; 7.511 + var c = [n-1,n-2,n-3,n-4,n-5,n-6,n-7,n-8,7,5,4,3,2,1,0][i]; 7.512 + matrix[r][8] = matrix[8][c] = (code >> i) & 1; 7.513 + // we don't have to mark those bits reserved; always done 7.514 + // in makebasematrix above. 7.515 + } 7.516 + return matrix; 7.517 +}; 7.518 + 7.519 +// evaluates the resulting matrix and returns the score (lower is better). 7.520 +// (cf. JIS X 0510:2004 sec 8.8.2) 7.521 +// 7.522 +// the evaluation procedure tries to avoid the problematic patterns naturally 7.523 +// occuring from the original matrix. for example, it penaltizes the patterns 7.524 +// which just look like the finder pattern which will confuse the decoder. 7.525 +// we choose the mask which results in the lowest score among 8 possible ones. 7.526 +// 7.527 +// note: zxing seems to use the same procedure and in many cases its choice 7.528 +// agrees to ours, but sometimes it does not. practically it doesn't matter. 7.529 +var evaluatematrix = function(matrix) { 7.530 + // N1+(k-5) points for each consecutive row of k same-colored modules, where k >= 5. no overlapping row counts. 7.531 + var PENALTY_CONSECUTIVE = 3; 7.532 + // N2 points for each 2x2 block of same-colored modules. Overlapping block does count. 7.533 + var PENALTY_TWOBYTWO = 3; 7.534 + // N3 points for each pattern with >4W:1B:1W:3B:1W:1B or 7.535 + // 1B:1W:3B:1W:1B:>4W, or their multiples (e.g. highly unlikely, but 13W:3B:3W:9B:3W:3B counts). 7.536 + var PENALTY_FINDERLIKE = 40; 7.537 + // N4*k points for every (5*k)% deviation from 50% black density. 7.538 + // i.e. k=1 for 55~60% and 40~45%, k=2 for 60~65% and 35~40%, etc. 7.539 + var PENALTY_DENSITY = 10; 7.540 + 7.541 + var evaluategroup = function(groups) { // assumes [W,B,W,B,W,...,B,W] 7.542 + var score = 0; 7.543 + for (var i = 0; i < groups.length; ++i) { 7.544 + if (groups[i] >= 5) score += PENALTY_CONSECUTIVE + (groups[i]-5); 7.545 + } 7.546 + for (var i = 5; i < groups.length; i += 2) { 7.547 + var p = groups[i]; 7.548 + if (groups[i-1] == p && groups[i-2] == 3*p && groups[i-3] == p && 7.549 + groups[i-4] == p && (groups[i-5] >= 4*p || groups[i+1] >= 4*p)) { 7.550 + // this part differs from zxing... 7.551 + score += PENALTY_FINDERLIKE; 7.552 + } 7.553 + } 7.554 + return score; 7.555 + }; 7.556 + 7.557 + var n = matrix.length; 7.558 + var score = 0, nblacks = 0; 7.559 + for (var i = 0; i < n; ++i) { 7.560 + var row = matrix[i]; 7.561 + var groups; 7.562 + 7.563 + // evaluate the current row 7.564 + groups = [0]; // the first empty group of white 7.565 + for (var j = 0; j < n; ) { 7.566 + var k; 7.567 + for (k = 0; j < n && row[j]; ++k) ++j; 7.568 + groups.push(k); 7.569 + for (k = 0; j < n && !row[j]; ++k) ++j; 7.570 + groups.push(k); 7.571 + } 7.572 + score += evaluategroup(groups); 7.573 + 7.574 + // evaluate the current column 7.575 + groups = [0]; 7.576 + for (var j = 0; j < n; ) { 7.577 + var k; 7.578 + for (k = 0; j < n && matrix[j][i]; ++k) ++j; 7.579 + groups.push(k); 7.580 + for (k = 0; j < n && !matrix[j][i]; ++k) ++j; 7.581 + groups.push(k); 7.582 + } 7.583 + score += evaluategroup(groups); 7.584 + 7.585 + // check the 2x2 box and calculate the density 7.586 + var nextrow = matrix[i+1] || []; 7.587 + nblacks += row[0]; 7.588 + for (var j = 1; j < n; ++j) { 7.589 + var p = row[j]; 7.590 + nblacks += p; 7.591 + // at least comparison with next row should be strict... 7.592 + if (row[j-1] == p && nextrow[j] === p && nextrow[j-1] === p) { 7.593 + score += PENALTY_TWOBYTWO; 7.594 + } 7.595 + } 7.596 + } 7.597 + 7.598 + score += PENALTY_DENSITY * ((Math.abs(nblacks / n / n - 0.5) / 0.05) | 0); 7.599 + return score; 7.600 +}; 7.601 + 7.602 +// returns the fully encoded QR code matrix which contains given data. 7.603 +// it also chooses the best mask automatically when mask is -1. 7.604 +var generate = function(data, ver, mode, ecclevel, mask) { 7.605 + var v = VERSIONS[ver]; 7.606 + var buf = encode(ver, mode, data, ndatabits(ver, ecclevel) >> 3); 7.607 + buf = augumenteccs(buf, v[1][ecclevel], GF256_GENPOLY[v[0][ecclevel]]); 7.608 + 7.609 + var result = makebasematrix(ver); 7.610 + var matrix = result.matrix, reserved = result.reserved; 7.611 + putdata(matrix, reserved, buf); 7.612 + 7.613 + if (mask < 0) { 7.614 + // find the best mask 7.615 + maskdata(matrix, reserved, 0); 7.616 + putformatinfo(matrix, reserved, ecclevel, 0); 7.617 + var bestmask = 0, bestscore = evaluatematrix(matrix); 7.618 + maskdata(matrix, reserved, 0); 7.619 + for (mask = 1; mask < 8; ++mask) { 7.620 + maskdata(matrix, reserved, mask); 7.621 + putformatinfo(matrix, reserved, ecclevel, mask); 7.622 + var score = evaluatematrix(matrix); 7.623 + if (bestscore > score) { 7.624 + bestscore = score; 7.625 + bestmask = mask; 7.626 + } 7.627 + maskdata(matrix, reserved, mask); 7.628 + } 7.629 + mask = bestmask; 7.630 + } 7.631 + 7.632 + maskdata(matrix, reserved, mask); 7.633 + putformatinfo(matrix, reserved, ecclevel, mask); 7.634 + return matrix; 7.635 +}; 7.636 + 7.637 +// the public interface is trivial; the options available are as follows: 7.638 +// 7.639 +// - version: an integer in [1,40]. when omitted (or -1) the smallest possible 7.640 +// version is chosen. 7.641 +// - mode: one of 'numeric', 'alphanumeric', 'octet'. when omitted the smallest 7.642 +// possible mode is chosen. 7.643 +// - ecclevel: one of 'L', 'M', 'Q', 'H'. defaults to 'L'. 7.644 +// - mask: an integer in [0,7]. when omitted (or -1) the best mask is chosen. 7.645 +// 7.646 +// for generate{HTML,PNG}: 7.647 +// 7.648 +// - modulesize: a number. this is a size of each modules in pixels, and 7.649 +// defaults to 5px. 7.650 +// - margin: a number. this is a size of margin in *modules*, and defaults to 7.651 +// 4 (white modules). the specficiation mandates the margin no less than 4 7.652 +// modules, so it is better not to alter this value unless you know what 7.653 +// you're doing. 7.654 +var QRCode = { 7.655 + 'generate': function(data, options) { 7.656 + var MODES = {'numeric': MODE_NUMERIC, 'alphanumeric': MODE_ALPHANUMERIC, 7.657 + 'octet': MODE_OCTET}; 7.658 + var ECCLEVELS = {'L': ECCLEVEL_L, 'M': ECCLEVEL_M, 'Q': ECCLEVEL_Q, 7.659 + 'H': ECCLEVEL_H}; 7.660 + 7.661 + options = options || {}; 7.662 + var ver = options.version || -1; 7.663 + var ecclevel = ECCLEVELS[(options.ecclevel || 'L').toUpperCase()]; 7.664 + var mode = options.mode ? MODES[options.mode.toLowerCase()] : -1; 7.665 + var mask = 'mask' in options ? options.mask : -1; 7.666 + 7.667 + if (mode < 0) { 7.668 + if (typeof data === 'string') { 7.669 + if (data.match(NUMERIC_REGEXP)) { 7.670 + mode = MODE_NUMERIC; 7.671 + } else if (data.match(ALPHANUMERIC_OUT_REGEXP)) { 7.672 + // while encode supports case-insensitive 7.673 + // encoding, we restrict the data to be 7.674 + // uppercased when auto-selecting the mode. 7.675 + mode = MODE_ALPHANUMERIC; 7.676 + } else { 7.677 + mode = MODE_OCTET; 7.678 + } 7.679 + } else { 7.680 + mode = MODE_OCTET; 7.681 + } 7.682 + } else if (!(mode == MODE_NUMERIC || mode == MODE_ALPHANUMERIC || 7.683 + mode == MODE_OCTET)) { 7.684 + throw 'invalid or unsupported mode'; 7.685 + } 7.686 + 7.687 + data = validatedata(mode, data); 7.688 + if (data === null) throw 'invalid data format'; 7.689 + 7.690 + if (ecclevel < 0 || ecclevel > 3) throw 'invalid ECC level'; 7.691 + 7.692 + if (ver < 0) { 7.693 + for (ver = 1; ver <= 40; ++ver) { 7.694 + if (data.length <= getmaxdatalen(ver, mode, ecclevel)) break; 7.695 + } 7.696 + if (ver > 40) throw 'too large data'; 7.697 + } else if (ver < 1 || ver > 40) { 7.698 + throw 'invalid version'; 7.699 + } 7.700 + 7.701 + if (mask != -1 && (mask < 0 || mask > 8)) throw 'invalid mask'; 7.702 + 7.703 + return generate(data, ver, mode, ecclevel, mask); 7.704 + }, 7.705 + 7.706 + 7.707 + 'generatePNG': function(data, options) { 7.708 + options = options || {}; 7.709 + var matrix = QRCode['generate'](data, options); 7.710 + var modsize = Math.max(options.modulesize || 5, 0.5); 7.711 + var margin = Math.max(options.margin || 4, 0.0); 7.712 + var n = matrix.length; 7.713 + var size = modsize * (n + 2 * margin); 7.714 + 7.715 + var canvas = document.createElement('canvas'), context; 7.716 + canvas.width = canvas.height = size; 7.717 + context = canvas.getContext('2d'); 7.718 + if (!context) throw 'canvas support is needed for PNG output'; 7.719 + 7.720 + context.fillStyle = '#fff'; 7.721 + context.fillRect(0, 0, size, size); 7.722 + context.fillStyle = '#000'; 7.723 + for (var i = 0; i < n; ++i) { 7.724 + for (var j = 0; j < n; ++j) { 7.725 + if (matrix[i][j]) { 7.726 + context.fillRect(modsize * (margin + j), modsize * (margin + i), modsize, modsize); 7.727 + } 7.728 + } 7.729 + } 7.730 + //context.fillText('evaluation: ' + evaluatematrix(matrix), 10, 10); 7.731 + return canvas.toDataURL(); 7.732 + } 7.733 +}; 7.734 + 7.735 +return QRCode; 7.736 +})();