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 &copy; <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 &copy; <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 &copy; <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 +})();