/** * @fileoverview * - using the 'qrcode for javascript library' * - fixed dataset of 'qrcode for javascript library' for support full-spec. * - this library has no dependencies. * * @author davidshimjs * @see http://www.d-project.com/ * @see http://jeromeetienne.github.com/jquery-qrcode/ */ var qrcode; (function () { //--------------------------------------------------------------------- // qrcode for javascript // // copyright (c) 2009 kazuhiko arase // // url: http://www.d-project.com/ // // licensed under the mit license: // http://www.opensource.org/licenses/mit-license.php // // the word "qr code" is registered trademark of // denso wave incorporated // http://www.denso-wave.com/qrcode/faqpatent-e.html // //--------------------------------------------------------------------- function qr8bitbyte(data) { this.mode = qrmode.mode_8bit_byte; this.data = data; this.parseddata = []; // added to support utf-8 characters for (var i = 0, l = this.data.length; i < l; i++) { var bytearray = []; var code = this.data.charcodeat(i); if (code > 0x10000) { bytearray[0] = 0xf0 | ((code & 0x1c0000) >>> 18); bytearray[1] = 0x80 | ((code & 0x3f000) >>> 12); bytearray[2] = 0x80 | ((code & 0xfc0) >>> 6); bytearray[3] = 0x80 | (code & 0x3f); } else if (code > 0x800) { bytearray[0] = 0xe0 | ((code & 0xf000) >>> 12); bytearray[1] = 0x80 | ((code & 0xfc0) >>> 6); bytearray[2] = 0x80 | (code & 0x3f); } else if (code > 0x80) { bytearray[0] = 0xc0 | ((code & 0x7c0) >>> 6); bytearray[1] = 0x80 | (code & 0x3f); } else { bytearray[0] = code; } this.parseddata.push(bytearray); } this.parseddata = array.prototype.concat.apply([], this.parseddata); if (this.parseddata.length != this.data.length) { this.parseddata.unshift(191); this.parseddata.unshift(187); this.parseddata.unshift(239); } } qr8bitbyte.prototype = { getlength: function (buffer) { return this.parseddata.length; }, write: function (buffer) { for (var i = 0, l = this.parseddata.length; i < l; i++) { buffer.put(this.parseddata[i], 8); } } }; function qrcodemodel(typenumber, errorcorrectlevel) { this.typenumber = typenumber; this.errorcorrectlevel = errorcorrectlevel; this.modules = null; this.modulecount = 0; this.datacache = null; this.datalist = []; } qrcodemodel.prototype={adddata:function(data){var newdata=new qr8bitbyte(data);this.datalist.push(newdata);this.datacache=null;},isdark:function(row,col){if(row<0||this.modulecount<=row||col<0||this.modulecount<=col){throw new error(row+","+col);} return this.modules[row][col];},getmodulecount:function(){return this.modulecount;},make:function(){this.makeimpl(false,this.getbestmaskpattern());},makeimpl:function(test,maskpattern){this.modulecount=this.typenumber*4+17;this.modules=new array(this.modulecount);for(var row=0;row=7){this.setuptypenumber(test);} if(this.datacache==null){this.datacache=qrcodemodel.createdata(this.typenumber,this.errorcorrectlevel,this.datalist);} this.mapdata(this.datacache,maskpattern);},setuppositionprobepattern:function(row,col){for(var r=-1;r<=7;r++){if(row+r<=-1||this.modulecount<=row+r)continue;for(var c=-1;c<=7;c++){if(col+c<=-1||this.modulecount<=col+c)continue;if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}},getbestmaskpattern:function(){var minlostpoint=0;var pattern=0;for(var i=0;i<8;i++){this.makeimpl(true,i);var lostpoint=qrutil.getlostpoint(this);if(i==0||minlostpoint>lostpoint){minlostpoint=lostpoint;pattern=i;}} return pattern;},createmovieclip:function(target_mc,instance_name,depth){var qr_mc=target_mc.createemptymovieclip(instance_name,depth);var cs=1;this.make();for(var row=0;row>i)&1)==1);this.modules[math.floor(i/3)][i%3+this.modulecount-8-3]=mod;} for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[i%3+this.modulecount-8-3][math.floor(i/3)]=mod;}},setuptypeinfo:function(test,maskpattern){var data=(this.errorcorrectlevel<<3)|maskpattern;var bits=qrutil.getbchtypeinfo(data);for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<6){this.modules[i][8]=mod;}else if(i<8){this.modules[i+1][8]=mod;}else{this.modules[this.modulecount-15+i][8]=mod;}} for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<8){this.modules[8][this.modulecount-i-1]=mod;}else if(i<9){this.modules[8][15-i-1+1]=mod;}else{this.modules[8][15-i-1]=mod;}} this.modules[this.modulecount-8][8]=(!test);},mapdata:function(data,maskpattern){var inc=-1;var row=this.modulecount-1;var bitindex=7;var byteindex=0;for(var col=this.modulecount-1;col>0;col-=2){if(col==6)col--;while(true){for(var c=0;c<2;c++){if(this.modules[row][col-c]==null){var dark=false;if(byteindex>>bitindex)&1)==1);} var mask=qrutil.getmask(maskpattern,row,col-c);if(mask){dark=!dark;} this.modules[row][col-c]=dark;bitindex--;if(bitindex==-1){byteindex++;bitindex=7;}}} row+=inc;if(row<0||this.modulecount<=row){row-=inc;inc=-inc;break;}}}}};qrcodemodel.pad0=0xec;qrcodemodel.pad1=0x11;qrcodemodel.createdata=function(typenumber,errorcorrectlevel,datalist){var rsblocks=qrrsblock.getrsblocks(typenumber,errorcorrectlevel);var buffer=new qrbitbuffer();for(var i=0;itotaldatacount*8){throw new error("code length overflow. (" +buffer.getlengthinbits() +">" +totaldatacount*8 +")");} if(buffer.getlengthinbits()+4<=totaldatacount*8){buffer.put(0,4);} while(buffer.getlengthinbits()%8!=0){buffer.putbit(false);} while(true){if(buffer.getlengthinbits()>=totaldatacount*8){break;} buffer.put(qrcodemodel.pad0,8);if(buffer.getlengthinbits()>=totaldatacount*8){break;} buffer.put(qrcodemodel.pad1,8);} return qrcodemodel.createbytes(buffer,rsblocks);};qrcodemodel.createbytes=function(buffer,rsblocks){var offset=0;var maxdccount=0;var maxeccount=0;var dcdata=new array(rsblocks.length);var ecdata=new array(rsblocks.length);for(var r=0;r=0)?modpoly.get(modindex):0;}} var totalcodecount=0;for(var i=0;i=0){d^=(qrutil.g15<<(qrutil.getbchdigit(d)-qrutil.getbchdigit(qrutil.g15)));} return((data<<10)|d)^qrutil.g15_mask;},getbchtypenumber:function(data){var d=data<<12;while(qrutil.getbchdigit(d)-qrutil.getbchdigit(qrutil.g18)>=0){d^=(qrutil.g18<<(qrutil.getbchdigit(d)-qrutil.getbchdigit(qrutil.g18)));} return(data<<12)|d;},getbchdigit:function(data){var digit=0;while(data!=0){digit++;data>>>=1;} return digit;},getpatternposition:function(typenumber){return qrutil.pattern_position_table[typenumber-1];},getmask:function(maskpattern,i,j){switch(maskpattern){case qrmaskpattern.pattern000:return(i+j)%2==0;case qrmaskpattern.pattern001:return i%2==0;case qrmaskpattern.pattern010:return j%3==0;case qrmaskpattern.pattern011:return(i+j)%3==0;case qrmaskpattern.pattern100:return(math.floor(i/2)+math.floor(j/3))%2==0;case qrmaskpattern.pattern101:return(i*j)%2+(i*j)%3==0;case qrmaskpattern.pattern110:return((i*j)%2+(i*j)%3)%2==0;case qrmaskpattern.pattern111:return((i*j)%3+(i+j)%2)%2==0;default:throw new error("bad maskpattern:"+maskpattern);}},geterrorcorrectpolynomial:function(errorcorrectlength){var a=new qrpolynomial([1],0);for(var i=0;i5){lostpoint+=(3+samecount-5);}}} for(var row=0;row=256){n-=255;} return qrmath.exp_table[n];},exp_table:new array(256),log_table:new array(256)};for(var i=0;i<8;i++){qrmath.exp_table[i]=1<>>(7-index%8))&1)==1;},put:function(num,length){for(var i=0;i>>(length-i-1))&1)==1);}},getlengthinbits:function(){return this.length;},putbit:function(bit){var bufindex=math.floor(this.length/8);if(this.buffer.length<=bufindex){this.buffer.push(0);} if(bit){this.buffer[bufindex]|=(0x80>>>(this.length%8));} this.length++;}};var qrcodelimitlength=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]]; function _issupportcanvas() { return typeof canvasrenderingcontext2d != "undefined"; } // android 2.x doesn't support data-uri spec function _getandroid() { var android = false; var sagent = navigator.useragent; if (/android/i.test(sagent)) { // android android = true; var amat = sagent.tostring().match(/android ([0-9]\.[0-9])/i); if (amat && amat[1]) { android = parsefloat(amat[1]); } } return android; } var svgdrawer = (function() { var drawing = function (el, htoption) { this._el = el; this._htoption = htoption; }; drawing.prototype.draw = function (oqrcode) { var _htoption = this._htoption; var _el = this._el; var ncount = oqrcode.getmodulecount(); var nwidth = math.floor(_htoption.width / ncount); var nheight = math.floor(_htoption.height / ncount); this.clear(); function makesvg(tag, attrs) { var el = document.createelementns('http://www.w3.org/2000/svg', tag); for (var k in attrs) if (attrs.hasownproperty(k)) el.setattribute(k, attrs[k]); return el; } var svg = makesvg("svg" , {'viewbox': '0 0 ' + string(ncount) + " " + string(ncount), 'width': '100%', 'height': '100%', 'fill': _htoption.colorlight}); svg.setattributens("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"); _el.appendchild(svg); svg.appendchild(makesvg("rect", {"fill": _htoption.colorlight, "width": "100%", "height": "100%"})); svg.appendchild(makesvg("rect", {"fill": _htoption.colordark, "width": "1", "height": "1", "id": "template"})); for (var row = 0; row < ncount; row++) { for (var col = 0; col < ncount; col++) { if (oqrcode.isdark(row, col)) { var child = makesvg("use", {"x": string(col), "y": string(row)}); child.setattributens("http://www.w3.org/1999/xlink", "href", "#template") svg.appendchild(child); } } } }; drawing.prototype.clear = function () { while (this._el.haschildnodes()) this._el.removechild(this._el.lastchild); }; return drawing; })(); var usesvg = document.documentelement.tagname.tolowercase() === "svg"; // drawing in dom by using table tag var drawing = usesvg ? svgdrawer : !_issupportcanvas() ? (function () { var drawing = function (el, htoption) { this._el = el; this._htoption = htoption; }; /** * draw the qrcode * * @param {qrcode} oqrcode */ drawing.prototype.draw = function (oqrcode) { var _htoption = this._htoption; var _el = this._el; var ncount = oqrcode.getmodulecount(); var nwidth = math.floor(_htoption.width / ncount); var nheight = math.floor(_htoption.height / ncount); var ahtml = ['']; for (var row = 0; row < ncount; row++) { ahtml.push(''); for (var col = 0; col < ncount; col++) { ahtml.push(''); } ahtml.push(''); } ahtml.push('
'); _el.innerhtml = ahtml.join(''); // fix the margin values as real size. var eltable = _el.childnodes[0]; var nleftmargintable = (_htoption.width - eltable.offsetwidth) / 2; var ntopmargintable = (_htoption.height - eltable.offsetheight) / 2; if (nleftmargintable > 0 && ntopmargintable > 0) { eltable.style.margin = ntopmargintable + "px " + nleftmargintable + "px"; } }; /** * clear the qrcode */ drawing.prototype.clear = function () { this._el.innerhtml = ''; }; return drawing; })() : (function () { // drawing in canvas function _onmakeimage() { this._elimage.src = this._elcanvas.todataurl("image/png"); this._elimage.style.display = "block"; this._elcanvas.style.display = "none"; } // android 2.1 bug workaround // http://code.google.com/p/android/issues/detail?id=5141 if (this._android && this._android <= 2.1) { var factor = 1 / window.devicepixelratio; var drawimage = canvasrenderingcontext2d.prototype.drawimage; canvasrenderingcontext2d.prototype.drawimage = function (image, sx, sy, sw, sh, dx, dy, dw, dh) { if (("nodename" in image) && /img/i.test(image.nodename)) { for (var i = arguments.length - 1; i >= 1; i--) { arguments[i] = arguments[i] * factor; } } else if (typeof dw == "undefined") { arguments[1] *= factor; arguments[2] *= factor; arguments[3] *= factor; arguments[4] *= factor; } drawimage.apply(this, arguments); }; } /** * check whether the user's browser supports data uri or not * * @private * @param {function} fsuccess occurs if it supports data uri * @param {function} ffail occurs if it doesn't support data uri */ function _safesetdatauri(fsuccess, ffail) { var self = this; self._ffail = ffail; self._fsuccess = fsuccess; // check it just once if (self._bsupportdatauri === null) { var el = document.createelement("img"); var fonerror = function() { self._bsupportdatauri = false; if (self._ffail) { self._ffail.call(self); } }; var fonsuccess = function() { self._bsupportdatauri = true; if (self._fsuccess) { self._fsuccess.call(self); } }; el.onabort = fonerror; el.onerror = fonerror; el.onload = fonsuccess; el.src = "data:image/gif;base64,ivborw0kggoaaaansuheugaaaauaaaafcayaaacnbyblaaaaheleqvqi12p4//8/w38giaxdibke0dhxgljnbaao9txl0y4ohwaaaabjru5erkjggg=="; // the image contains 1px data. return; } else if (self._bsupportdatauri === true && self._fsuccess) { self._fsuccess.call(self); } else if (self._bsupportdatauri === false && self._ffail) { self._ffail.call(self); } }; /** * drawing qrcode by using canvas * * @constructor * @param {htmlelement} el * @param {object} htoption qrcode options */ var drawing = function (el, htoption) { this._bispainted = false; this._android = _getandroid(); this._htoption = htoption; this._elcanvas = document.createelement("canvas"); this._elcanvas.width = htoption.width; this._elcanvas.height = htoption.height; el.appendchild(this._elcanvas); this._el = el; this._ocontext = this._elcanvas.getcontext("2d"); this._bispainted = false; this._elimage = document.createelement("img"); this._elimage.alt = "scan me!"; this._elimage.style.display = "none"; this._el.appendchild(this._elimage); this._bsupportdatauri = null; }; /** * draw the qrcode * * @param {qrcode} oqrcode */ drawing.prototype.draw = function (oqrcode) { var _elimage = this._elimage; var _ocontext = this._ocontext; var _htoption = this._htoption; var ncount = oqrcode.getmodulecount(); var nwidth = _htoption.width / ncount; var nheight = _htoption.height / ncount; var nroundedwidth = math.round(nwidth); var nroundedheight = math.round(nheight); _elimage.style.display = "none"; this.clear(); for (var row = 0; row < ncount; row++) { for (var col = 0; col < ncount; col++) { var bisdark = oqrcode.isdark(row, col); var nleft = col * nwidth; var ntop = row * nheight; _ocontext.strokestyle = bisdark ? _htoption.colordark : _htoption.colorlight; _ocontext.linewidth = 1; _ocontext.fillstyle = bisdark ? _htoption.colordark : _htoption.colorlight; _ocontext.fillrect(nleft, ntop, nwidth, nheight); // 안티 앨리어싱 방지 처리 _ocontext.strokerect( math.floor(nleft) + 0.5, math.floor(ntop) + 0.5, nroundedwidth, nroundedheight ); _ocontext.strokerect( math.ceil(nleft) - 0.5, math.ceil(ntop) - 0.5, nroundedwidth, nroundedheight ); } } this._bispainted = true; }; /** * make the image from canvas if the browser supports data uri. */ drawing.prototype.makeimage = function () { if (this._bispainted) { _safesetdatauri.call(this, _onmakeimage); } }; /** * return whether the qrcode is painted or not * * @return {boolean} */ drawing.prototype.ispainted = function () { return this._bispainted; }; /** * clear the qrcode */ drawing.prototype.clear = function () { this._ocontext.clearrect(0, 0, this._elcanvas.width, this._elcanvas.height); this._bispainted = false; }; /** * @private * @param {number} nnumber */ drawing.prototype.round = function (nnumber) { if (!nnumber) { return nnumber; } return math.floor(nnumber * 1000) / 1000; }; return drawing; })(); /** * get the type by string length * * @private * @param {string} stext * @param {number} ncorrectlevel * @return {number} type */ function _gettypenumber(stext, ncorrectlevel) { var ntype = 1; var length = _getutf8length(stext); for (var i = 0, len = qrcodelimitlength.length; i <= len; i++) { var nlimit = 0; switch (ncorrectlevel) { case qrerrorcorrectlevel.l : nlimit = qrcodelimitlength[i][0]; break; case qrerrorcorrectlevel.m : nlimit = qrcodelimitlength[i][1]; break; case qrerrorcorrectlevel.q : nlimit = qrcodelimitlength[i][2]; break; case qrerrorcorrectlevel.h : nlimit = qrcodelimitlength[i][3]; break; } if (length <= nlimit) { break; } else { ntype++; } } if (ntype > qrcodelimitlength.length) { throw new error("too long data"); } return ntype; } function _getutf8length(stext) { var replacedtext = encodeuri(stext).tostring().replace(/\%[0-9a-fa-f]{2}/g, 'a'); return replacedtext.length + (replacedtext.length != stext ? 3 : 0); } /** * @class qrcode * @constructor * @example * new qrcode(document.getelementbyid("test"), "http://jindo.dev.naver.com/collie"); * * @example * var oqrcode = new qrcode("test", { * text : "http://naver.com", * width : 128, * height : 128 * }); * * oqrcode.clear(); // clear the qrcode. * oqrcode.makecode("http://map.naver.com"); // re-create the qrcode. * * @param {htmlelement|string} el target element or 'id' attribute of element. * @param {object|string} voption * @param {string} voption.text qrcode link data * @param {number} [voption.width=256] * @param {number} [voption.height=256] * @param {string} [voption.colordark="#000000"] * @param {string} [voption.colorlight="#ffffff"] * @param {qrcode.correctlevel} [voption.correctlevel=qrcode.correctlevel.h] [l|m|q|h] */ qrcode = function (el, voption) { this._htoption = { width : 256, height : 256, typenumber : 4, colordark : "#000000", colorlight : "#ffffff", correctlevel : qrerrorcorrectlevel.h }; if (typeof voption === 'string') { voption = { text : voption }; } // overwrites options if (voption) { for (var i in voption) { this._htoption[i] = voption[i]; } } if (typeof el == "string") { el = document.getelementbyid(el); } if (this._htoption.usesvg) { drawing = svgdrawer; } this._android = _getandroid(); this._el = el; this._oqrcode = null; this._odrawing = new drawing(this._el, this._htoption); if (this._htoption.text) { this.makecode(this._htoption.text); } }; /** * make the qrcode * * @param {string} stext link data */ qrcode.prototype.makecode = function (stext) { this._oqrcode = new qrcodemodel(_gettypenumber(stext, this._htoption.correctlevel), this._htoption.correctlevel); this._oqrcode.adddata(stext); this._oqrcode.make(); this._el.title = stext; this._odrawing.draw(this._oqrcode); this.makeimage(); }; /** * make the image from canvas element * - it occurs automatically * - android below 3 doesn't support data-uri spec. * * @private */ qrcode.prototype.makeimage = function () { if (typeof this._odrawing.makeimage == "function" && (!this._android || this._android >= 3)) { this._odrawing.makeimage(); } }; /** * clear the qrcode */ qrcode.prototype.clear = function () { this._odrawing.clear(); }; /** * @name qrcode.correctlevel */ qrcode.correctlevel = qrerrorcorrectlevel; })(); if (typeof module != "undefined") { module.exports = qrcode; }