qrious.js (71856B)
1 /* 2 * QRious v4.0.2 3 * Copyright (C) 2017 Alasdair Mercer 4 * Copyright (C) 2010 Tom Zerucha 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 (function (global, factory) { 20 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 21 typeof define === 'function' && define.amd ? define(factory) : 22 (global.QRious = factory()); 23 }(this, (function () { 'use strict'; 24 25 /* 26 * Copyright (C) 2017 Alasdair Mercer, !ninja 27 * 28 * Permission is hereby granted, free of charge, to any person obtaining a copy 29 * of this software and associated documentation files (the "Software"), to deal 30 * in the Software without restriction, including without limitation the rights 31 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 32 * copies of the Software, and to permit persons to whom the Software is 33 * furnished to do so, subject to the following conditions: 34 * 35 * The above copyright notice and this permission notice shall be included in all 36 * copies or substantial portions of the Software. 37 * 38 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 39 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 40 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 41 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 42 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 43 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 44 * SOFTWARE. 45 */ 46 47 /** 48 * A bare-bones constructor for surrogate prototype swapping. 49 * 50 * @private 51 * @constructor 52 */ 53 var Constructor = /* istanbul ignore next */ function() {}; 54 /** 55 * A reference to <code>Object.prototype.hasOwnProperty</code>. 56 * 57 * @private 58 * @type {Function} 59 */ 60 var hasOwnProperty = Object.prototype.hasOwnProperty; 61 /** 62 * A reference to <code>Array.prototype.slice</code>. 63 * 64 * @private 65 * @type {Function} 66 */ 67 var slice = Array.prototype.slice; 68 69 /** 70 * Creates an object which inherits the given <code>prototype</code>. 71 * 72 * Optionally, the created object can be extended further with the specified <code>properties</code>. 73 * 74 * @param {Object} prototype - the prototype to be inherited by the created object 75 * @param {Object} [properties] - the optional properties to be extended by the created object 76 * @return {Object} The newly created object. 77 * @private 78 */ 79 function createObject(prototype, properties) { 80 var result; 81 /* istanbul ignore next */ 82 if (typeof Object.create === 'function') { 83 result = Object.create(prototype); 84 } else { 85 Constructor.prototype = prototype; 86 result = new Constructor(); 87 Constructor.prototype = null; 88 } 89 90 if (properties) { 91 extendObject(true, result, properties); 92 } 93 94 return result; 95 } 96 97 /** 98 * Extends the constructor to which this method is associated with the <code>prototype</code> and/or 99 * <code>statics</code> provided. 100 * 101 * If <code>name</code> is provided, it will be used as the class name and can be accessed via a special 102 * <code>class_</code> property on the child constructor, otherwise the class name of the super constructor will be used 103 * instead. The class name may also be used string representation for instances of the child constructor (via 104 * <code>toString</code>), but this is not applicable to the <i>lite</i> version of Nevis. 105 * 106 * If <code>constructor</code> is provided, it will be used as the constructor for the child, otherwise a simple 107 * constructor which only calls the super constructor will be used instead. 108 * 109 * The super constructor can be accessed via a special <code>super_</code> property on the child constructor. 110 * 111 * @param {string} [name=this.class_] - the class name to be used for the child constructor 112 * @param {Function} [constructor] - the constructor for the child 113 * @param {Object} [prototype] - the prototype properties to be defined for the child 114 * @param {Object} [statics] - the static properties to be defined for the child 115 * @return {Function} The child <code>constructor</code> provided or the one created if none was given. 116 * @public 117 */ 118 function extend(name, constructor, prototype, statics) { 119 var superConstructor = this; 120 121 if (typeof name !== 'string') { 122 statics = prototype; 123 prototype = constructor; 124 constructor = name; 125 name = null; 126 } 127 128 if (typeof constructor !== 'function') { 129 statics = prototype; 130 prototype = constructor; 131 constructor = function() { 132 return superConstructor.apply(this, arguments); 133 }; 134 } 135 136 extendObject(false, constructor, superConstructor, statics); 137 138 constructor.prototype = createObject(superConstructor.prototype, prototype); 139 constructor.prototype.constructor = constructor; 140 141 constructor.class_ = name || superConstructor.class_; 142 constructor.super_ = superConstructor; 143 144 return constructor; 145 } 146 147 /** 148 * Extends the specified <code>target</code> object with the properties in each of the <code>sources</code> provided. 149 * 150 * if any source is <code>null</code> it will be ignored. 151 * 152 * @param {boolean} own - <code>true</code> to only copy <b>own</b> properties from <code>sources</code> onto 153 * <code>target</code>; otherwise <code>false</code> 154 * @param {Object} target - the target object which should be extended 155 * @param {...Object} [sources] - the source objects whose properties are to be copied onto <code>target</code> 156 * @return {void} 157 * @private 158 */ 159 function extendObject(own, target, sources) { 160 sources = slice.call(arguments, 2); 161 162 var property; 163 var source; 164 165 for (var i = 0, length = sources.length; i < length; i++) { 166 source = sources[i]; 167 168 for (property in source) { 169 if (!own || hasOwnProperty.call(source, property)) { 170 target[property] = source[property]; 171 } 172 } 173 } 174 } 175 176 var extend_1 = extend; 177 178 /** 179 * The base class from which all others should extend. 180 * 181 * @public 182 * @constructor 183 */ 184 function Nevis() {} 185 Nevis.class_ = 'Nevis'; 186 Nevis.super_ = Object; 187 188 /** 189 * Extends the constructor to which this method is associated with the <code>prototype</code> and/or 190 * <code>statics</code> provided. 191 * 192 * If <code>name</code> is provided, it will be used as the class name and can be accessed via a special 193 * <code>class_</code> property on the child constructor, otherwise the class name of the super constructor will be used 194 * instead. The class name may also be used string representation for instances of the child constructor (via 195 * <code>toString</code>), but this is not applicable to the <i>lite</i> version of Nevis. 196 * 197 * If <code>constructor</code> is provided, it will be used as the constructor for the child, otherwise a simple 198 * constructor which only calls the super constructor will be used instead. 199 * 200 * The super constructor can be accessed via a special <code>super_</code> property on the child constructor. 201 * 202 * @param {string} [name=this.class_] - the class name to be used for the child constructor 203 * @param {Function} [constructor] - the constructor for the child 204 * @param {Object} [prototype] - the prototype properties to be defined for the child 205 * @param {Object} [statics] - the static properties to be defined for the child 206 * @return {Function} The child <code>constructor</code> provided or the one created if none was given. 207 * @public 208 * @static 209 * @memberof Nevis 210 */ 211 Nevis.extend = extend_1; 212 213 var nevis = Nevis; 214 215 var lite = nevis; 216 217 /** 218 * Responsible for rendering a QR code {@link Frame} on a specific type of element. 219 * 220 * A renderer may be dependant on the rendering of another element, so the ordering of their execution is important. 221 * 222 * The rendering of a element can be deferred by disabling the renderer initially, however, any attempt get the element 223 * from the renderer will result in it being immediately enabled and the element being rendered. 224 * 225 * @param {QRious} qrious - the {@link QRious} instance to be used 226 * @param {*} element - the element onto which the QR code is to be rendered 227 * @param {boolean} [enabled] - <code>true</code> this {@link Renderer} is enabled; otherwise <code>false</code>. 228 * @public 229 * @class 230 * @extends Nevis 231 */ 232 var Renderer = lite.extend(function(qrious, element, enabled) { 233 /** 234 * The {@link QRious} instance. 235 * 236 * @protected 237 * @type {QRious} 238 * @memberof Renderer# 239 */ 240 this.qrious = qrious; 241 242 /** 243 * The element onto which this {@link Renderer} is rendering the QR code. 244 * 245 * @protected 246 * @type {*} 247 * @memberof Renderer# 248 */ 249 this.element = element; 250 this.element.qrious = qrious; 251 252 /** 253 * Whether this {@link Renderer} is enabled. 254 * 255 * @protected 256 * @type {boolean} 257 * @memberof Renderer# 258 */ 259 this.enabled = Boolean(enabled); 260 }, { 261 262 /** 263 * Draws the specified QR code <code>frame</code> on the underlying element. 264 * 265 * Implementations of {@link Renderer} <b>must</b> override this method with their own specific logic. 266 * 267 * @param {Frame} frame - the {@link Frame} to be drawn 268 * @return {void} 269 * @protected 270 * @abstract 271 * @memberof Renderer# 272 */ 273 draw: function(frame) {}, 274 275 /** 276 * Returns the element onto which this {@link Renderer} is rendering the QR code. 277 * 278 * If this method is called while this {@link Renderer} is disabled, it will be immediately enabled and rendered 279 * before the element is returned. 280 * 281 * @return {*} The element. 282 * @public 283 * @memberof Renderer# 284 */ 285 getElement: function() { 286 if (!this.enabled) { 287 this.enabled = true; 288 this.render(); 289 } 290 291 return this.element; 292 }, 293 294 /** 295 * Calculates the size (in pixel units) to represent an individual module within the QR code based on the 296 * <code>frame</code> provided. 297 * 298 * Any configured padding will be excluded from the returned size. 299 * 300 * The returned value will be at least one, even in cases where the size of the QR code does not fit its contents. 301 * This is done so that the inevitable clipping is handled more gracefully since this way at least something is 302 * displayed instead of just a blank space filled by the background color. 303 * 304 * @param {Frame} frame - the {@link Frame} from which the module size is to be derived 305 * @return {number} The pixel size for each module in the QR code which will be no less than one. 306 * @protected 307 * @memberof Renderer# 308 */ 309 getModuleSize: function(frame) { 310 var qrious = this.qrious; 311 var padding = qrious.padding || 0; 312 var pixels = Math.floor((qrious.size - (padding * 2)) / frame.width); 313 314 return Math.max(1, pixels); 315 }, 316 317 /** 318 * Calculates the offset/padding (in pixel units) to be inserted before the QR code based on the <code>frame</code> 319 * provided. 320 * 321 * The returned value will be zero if there is no available offset or if the size of the QR code does not fit its 322 * contents. It will never be a negative value. This is done so that the inevitable clipping appears more naturally 323 * and it is not clipped from all directions. 324 * 325 * @param {Frame} frame - the {@link Frame} from which the offset is to be derived 326 * @return {number} The pixel offset for the QR code which will be no less than zero. 327 * @protected 328 * @memberof Renderer# 329 */ 330 getOffset: function(frame) { 331 var qrious = this.qrious; 332 var padding = qrious.padding; 333 334 if (padding != null) { 335 return padding; 336 } 337 338 var moduleSize = this.getModuleSize(frame); 339 var offset = Math.floor((qrious.size - (moduleSize * frame.width)) / 2); 340 341 return Math.max(0, offset); 342 }, 343 344 /** 345 * Renders a QR code on the underlying element based on the <code>frame</code> provided. 346 * 347 * @param {Frame} frame - the {@link Frame} to be rendered 348 * @return {void} 349 * @public 350 * @memberof Renderer# 351 */ 352 render: function(frame) { 353 if (this.enabled) { 354 this.resize(); 355 this.reset(); 356 this.draw(frame); 357 } 358 }, 359 360 /** 361 * Resets the underlying element, effectively clearing any previously rendered QR code. 362 * 363 * Implementations of {@link Renderer} <b>must</b> override this method with their own specific logic. 364 * 365 * @return {void} 366 * @protected 367 * @abstract 368 * @memberof Renderer# 369 */ 370 reset: function() {}, 371 372 /** 373 * Ensures that the size of the underlying element matches that defined on the associated {@link QRious} instance. 374 * 375 * Implementations of {@link Renderer} <b>must</b> override this method with their own specific logic. 376 * 377 * @return {void} 378 * @protected 379 * @abstract 380 * @memberof Renderer# 381 */ 382 resize: function() {} 383 384 }); 385 386 var Renderer_1 = Renderer; 387 388 /** 389 * An implementation of {@link Renderer} for working with <code>canvas</code> elements. 390 * 391 * @public 392 * @class 393 * @extends Renderer 394 */ 395 var CanvasRenderer = Renderer_1.extend({ 396 397 /** 398 * @override 399 */ 400 draw: function(frame) { 401 var i, j; 402 var qrious = this.qrious; 403 var moduleSize = this.getModuleSize(frame); 404 var offset = this.getOffset(frame); 405 var context = this.element.getContext('2d'); 406 407 context.fillStyle = qrious.foreground; 408 context.globalAlpha = qrious.foregroundAlpha; 409 410 for (i = 0; i < frame.width; i++) { 411 for (j = 0; j < frame.width; j++) { 412 if (frame.buffer[(j * frame.width) + i]) { 413 context.fillRect((moduleSize * i) + offset, (moduleSize * j) + offset, moduleSize, moduleSize); 414 } 415 } 416 } 417 }, 418 419 /** 420 * @override 421 */ 422 reset: function() { 423 var qrious = this.qrious; 424 var context = this.element.getContext('2d'); 425 var size = qrious.size; 426 427 context.lineWidth = 1; 428 context.clearRect(0, 0, size, size); 429 context.fillStyle = qrious.background; 430 context.globalAlpha = qrious.backgroundAlpha; 431 context.fillRect(0, 0, size, size); 432 }, 433 434 /** 435 * @override 436 */ 437 resize: function() { 438 var element = this.element; 439 440 element.width = element.height = this.qrious.size; 441 } 442 443 }); 444 445 var CanvasRenderer_1 = CanvasRenderer; 446 447 /* eslint no-multi-spaces: "off" */ 448 449 450 451 /** 452 * Contains alignment pattern information. 453 * 454 * @public 455 * @class 456 * @extends Nevis 457 */ 458 var Alignment = lite.extend(null, { 459 460 /** 461 * The alignment pattern block. 462 * 463 * @public 464 * @static 465 * @type {number[]} 466 * @memberof Alignment 467 */ 468 BLOCK: [ 469 0, 11, 15, 19, 23, 27, 31, 470 16, 18, 20, 22, 24, 26, 28, 20, 22, 24, 24, 26, 28, 28, 22, 24, 24, 471 26, 26, 28, 28, 24, 24, 26, 26, 26, 28, 28, 24, 26, 26, 26, 28, 28 472 ] 473 474 }); 475 476 var Alignment_1 = Alignment; 477 478 /* eslint no-multi-spaces: "off" */ 479 480 481 482 /** 483 * Contains error correction information. 484 * 485 * @public 486 * @class 487 * @extends Nevis 488 */ 489 var ErrorCorrection = lite.extend(null, { 490 491 /** 492 * The error correction blocks. 493 * 494 * There are four elements per version. The first two indicate the number of blocks, then the data width, and finally 495 * the ECC width. 496 * 497 * @public 498 * @static 499 * @type {number[]} 500 * @memberof ErrorCorrection 501 */ 502 BLOCKS: [ 503 1, 0, 19, 7, 1, 0, 16, 10, 1, 0, 13, 13, 1, 0, 9, 17, 504 1, 0, 34, 10, 1, 0, 28, 16, 1, 0, 22, 22, 1, 0, 16, 28, 505 1, 0, 55, 15, 1, 0, 44, 26, 2, 0, 17, 18, 2, 0, 13, 22, 506 1, 0, 80, 20, 2, 0, 32, 18, 2, 0, 24, 26, 4, 0, 9, 16, 507 1, 0, 108, 26, 2, 0, 43, 24, 2, 2, 15, 18, 2, 2, 11, 22, 508 2, 0, 68, 18, 4, 0, 27, 16, 4, 0, 19, 24, 4, 0, 15, 28, 509 2, 0, 78, 20, 4, 0, 31, 18, 2, 4, 14, 18, 4, 1, 13, 26, 510 2, 0, 97, 24, 2, 2, 38, 22, 4, 2, 18, 22, 4, 2, 14, 26, 511 2, 0, 116, 30, 3, 2, 36, 22, 4, 4, 16, 20, 4, 4, 12, 24, 512 2, 2, 68, 18, 4, 1, 43, 26, 6, 2, 19, 24, 6, 2, 15, 28, 513 4, 0, 81, 20, 1, 4, 50, 30, 4, 4, 22, 28, 3, 8, 12, 24, 514 2, 2, 92, 24, 6, 2, 36, 22, 4, 6, 20, 26, 7, 4, 14, 28, 515 4, 0, 107, 26, 8, 1, 37, 22, 8, 4, 20, 24, 12, 4, 11, 22, 516 3, 1, 115, 30, 4, 5, 40, 24, 11, 5, 16, 20, 11, 5, 12, 24, 517 5, 1, 87, 22, 5, 5, 41, 24, 5, 7, 24, 30, 11, 7, 12, 24, 518 5, 1, 98, 24, 7, 3, 45, 28, 15, 2, 19, 24, 3, 13, 15, 30, 519 1, 5, 107, 28, 10, 1, 46, 28, 1, 15, 22, 28, 2, 17, 14, 28, 520 5, 1, 120, 30, 9, 4, 43, 26, 17, 1, 22, 28, 2, 19, 14, 28, 521 3, 4, 113, 28, 3, 11, 44, 26, 17, 4, 21, 26, 9, 16, 13, 26, 522 3, 5, 107, 28, 3, 13, 41, 26, 15, 5, 24, 30, 15, 10, 15, 28, 523 4, 4, 116, 28, 17, 0, 42, 26, 17, 6, 22, 28, 19, 6, 16, 30, 524 2, 7, 111, 28, 17, 0, 46, 28, 7, 16, 24, 30, 34, 0, 13, 24, 525 4, 5, 121, 30, 4, 14, 47, 28, 11, 14, 24, 30, 16, 14, 15, 30, 526 6, 4, 117, 30, 6, 14, 45, 28, 11, 16, 24, 30, 30, 2, 16, 30, 527 8, 4, 106, 26, 8, 13, 47, 28, 7, 22, 24, 30, 22, 13, 15, 30, 528 10, 2, 114, 28, 19, 4, 46, 28, 28, 6, 22, 28, 33, 4, 16, 30, 529 8, 4, 122, 30, 22, 3, 45, 28, 8, 26, 23, 30, 12, 28, 15, 30, 530 3, 10, 117, 30, 3, 23, 45, 28, 4, 31, 24, 30, 11, 31, 15, 30, 531 7, 7, 116, 30, 21, 7, 45, 28, 1, 37, 23, 30, 19, 26, 15, 30, 532 5, 10, 115, 30, 19, 10, 47, 28, 15, 25, 24, 30, 23, 25, 15, 30, 533 13, 3, 115, 30, 2, 29, 46, 28, 42, 1, 24, 30, 23, 28, 15, 30, 534 17, 0, 115, 30, 10, 23, 46, 28, 10, 35, 24, 30, 19, 35, 15, 30, 535 17, 1, 115, 30, 14, 21, 46, 28, 29, 19, 24, 30, 11, 46, 15, 30, 536 13, 6, 115, 30, 14, 23, 46, 28, 44, 7, 24, 30, 59, 1, 16, 30, 537 12, 7, 121, 30, 12, 26, 47, 28, 39, 14, 24, 30, 22, 41, 15, 30, 538 6, 14, 121, 30, 6, 34, 47, 28, 46, 10, 24, 30, 2, 64, 15, 30, 539 17, 4, 122, 30, 29, 14, 46, 28, 49, 10, 24, 30, 24, 46, 15, 30, 540 4, 18, 122, 30, 13, 32, 46, 28, 48, 14, 24, 30, 42, 32, 15, 30, 541 20, 4, 117, 30, 40, 7, 47, 28, 43, 22, 24, 30, 10, 67, 15, 30, 542 19, 6, 118, 30, 18, 31, 47, 28, 34, 34, 24, 30, 20, 61, 15, 30 543 ], 544 545 /** 546 * The final format bits with mask (level << 3 | mask). 547 * 548 * @public 549 * @static 550 * @type {number[]} 551 * @memberof ErrorCorrection 552 */ 553 FINAL_FORMAT: [ 554 // L 555 0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976, 556 // M 557 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 558 // Q 559 0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed, 560 // H 561 0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b 562 ], 563 564 /** 565 * A map of human-readable ECC levels. 566 * 567 * @public 568 * @static 569 * @type {Object.<string, number>} 570 * @memberof ErrorCorrection 571 */ 572 LEVELS: { 573 L: 1, 574 M: 2, 575 Q: 3, 576 H: 4 577 } 578 579 }); 580 581 var ErrorCorrection_1 = ErrorCorrection; 582 583 /** 584 * Contains Galois field information. 585 * 586 * @public 587 * @class 588 * @extends Nevis 589 */ 590 var Galois = lite.extend(null, { 591 592 /** 593 * The Galois field exponent table. 594 * 595 * @public 596 * @static 597 * @type {number[]} 598 * @memberof Galois 599 */ 600 EXPONENT: [ 601 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, 602 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 603 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, 604 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, 605 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, 606 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, 607 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, 608 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, 609 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, 610 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, 611 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, 612 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, 613 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, 614 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, 615 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, 616 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x00 617 ], 618 619 /** 620 * The Galois field log table. 621 * 622 * @public 623 * @static 624 * @type {number[]} 625 * @memberof Galois 626 */ 627 LOG: [ 628 0xff, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, 629 0x04, 0x64, 0xe0, 0x0e, 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, 0x4c, 0x71, 630 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, 631 0x1d, 0xb5, 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, 0x4d, 0xe4, 0x72, 0xa6, 632 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, 633 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, 634 0x1e, 0x42, 0xb6, 0xa3, 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, 0xba, 0x3d, 635 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, 636 0x07, 0x70, 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, 0x31, 0xc5, 0xfe, 0x18, 637 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, 638 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, 639 0xf2, 0x56, 0xd3, 0xab, 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, 0x41, 0xa2, 640 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, 641 0x6c, 0xa1, 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, 0xbb, 0xcc, 0x3e, 0x5a, 642 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, 643 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf 644 ] 645 646 }); 647 648 var Galois_1 = Galois; 649 650 /** 651 * Contains version pattern information. 652 * 653 * @public 654 * @class 655 * @extends Nevis 656 */ 657 var Version = lite.extend(null, { 658 659 /** 660 * The version pattern block. 661 * 662 * @public 663 * @static 664 * @type {number[]} 665 * @memberof Version 666 */ 667 BLOCK: [ 668 0xc94, 0x5bc, 0xa99, 0x4d3, 0xbf6, 0x762, 0x847, 0x60d, 0x928, 0xb78, 0x45d, 0xa17, 0x532, 669 0x9a6, 0x683, 0x8c9, 0x7ec, 0xec4, 0x1e1, 0xfab, 0x08e, 0xc1a, 0x33f, 0xd75, 0x250, 0x9d5, 670 0x6f0, 0x8ba, 0x79f, 0xb0b, 0x42e, 0xa64, 0x541, 0xc69 671 ] 672 673 }); 674 675 var Version_1 = Version; 676 677 /** 678 * Generates information for a QR code frame based on a specific value to be encoded. 679 * 680 * @param {Frame~Options} options - the options to be used 681 * @public 682 * @class 683 * @extends Nevis 684 */ 685 var Frame = lite.extend(function(options) { 686 var dataBlock, eccBlock, index, neccBlock1, neccBlock2; 687 var valueLength = options.value.length; 688 689 this._badness = []; 690 this._level = ErrorCorrection_1.LEVELS[options.level]; 691 this._polynomial = []; 692 this._value = options.value; 693 this._version = 0; 694 this._stringBuffer = []; 695 696 while (this._version < 40) { 697 this._version++; 698 699 index = ((this._level - 1) * 4) + ((this._version - 1) * 16); 700 701 neccBlock1 = ErrorCorrection_1.BLOCKS[index++]; 702 neccBlock2 = ErrorCorrection_1.BLOCKS[index++]; 703 dataBlock = ErrorCorrection_1.BLOCKS[index++]; 704 eccBlock = ErrorCorrection_1.BLOCKS[index]; 705 706 index = (dataBlock * (neccBlock1 + neccBlock2)) + neccBlock2 - 3 + (this._version <= 9); 707 708 if (valueLength <= index) { 709 break; 710 } 711 } 712 713 this._dataBlock = dataBlock; 714 this._eccBlock = eccBlock; 715 this._neccBlock1 = neccBlock1; 716 this._neccBlock2 = neccBlock2; 717 718 /** 719 * The data width is based on version. 720 * 721 * @public 722 * @type {number} 723 * @memberof Frame# 724 */ 725 // FIXME: Ensure that it fits instead of being truncated. 726 var width = this.width = 17 + (4 * this._version); 727 728 /** 729 * The image buffer. 730 * 731 * @public 732 * @type {number[]} 733 * @memberof Frame# 734 */ 735 this.buffer = Frame._createArray(width * width); 736 737 this._ecc = Frame._createArray(dataBlock + ((dataBlock + eccBlock) * (neccBlock1 + neccBlock2)) + neccBlock2); 738 this._mask = Frame._createArray(((width * (width + 1)) + 1) / 2); 739 740 this._insertFinders(); 741 this._insertAlignments(); 742 743 // Insert single foreground cell. 744 this.buffer[8 + (width * (width - 8))] = 1; 745 746 this._insertTimingGap(); 747 this._reverseMask(); 748 this._insertTimingRowAndColumn(); 749 this._insertVersion(); 750 this._syncMask(); 751 this._convertBitStream(valueLength); 752 this._calculatePolynomial(); 753 this._appendEccToData(); 754 this._interleaveBlocks(); 755 this._pack(); 756 this._finish(); 757 }, { 758 759 _addAlignment: function(x, y) { 760 var i; 761 var buffer = this.buffer; 762 var width = this.width; 763 764 buffer[x + (width * y)] = 1; 765 766 for (i = -2; i < 2; i++) { 767 buffer[x + i + (width * (y - 2))] = 1; 768 buffer[x - 2 + (width * (y + i + 1))] = 1; 769 buffer[x + 2 + (width * (y + i))] = 1; 770 buffer[x + i + 1 + (width * (y + 2))] = 1; 771 } 772 773 for (i = 0; i < 2; i++) { 774 this._setMask(x - 1, y + i); 775 this._setMask(x + 1, y - i); 776 this._setMask(x - i, y - 1); 777 this._setMask(x + i, y + 1); 778 } 779 }, 780 781 _appendData: function(data, dataLength, ecc, eccLength) { 782 var bit, i, j; 783 var polynomial = this._polynomial; 784 var stringBuffer = this._stringBuffer; 785 786 for (i = 0; i < eccLength; i++) { 787 stringBuffer[ecc + i] = 0; 788 } 789 790 for (i = 0; i < dataLength; i++) { 791 bit = Galois_1.LOG[stringBuffer[data + i] ^ stringBuffer[ecc]]; 792 793 if (bit !== 255) { 794 for (j = 1; j < eccLength; j++) { 795 stringBuffer[ecc + j - 1] = stringBuffer[ecc + j] ^ 796 Galois_1.EXPONENT[Frame._modN(bit + polynomial[eccLength - j])]; 797 } 798 } else { 799 for (j = ecc; j < ecc + eccLength; j++) { 800 stringBuffer[j] = stringBuffer[j + 1]; 801 } 802 } 803 804 stringBuffer[ecc + eccLength - 1] = bit === 255 ? 0 : Galois_1.EXPONENT[Frame._modN(bit + polynomial[0])]; 805 } 806 }, 807 808 _appendEccToData: function() { 809 var i; 810 var data = 0; 811 var dataBlock = this._dataBlock; 812 var ecc = this._calculateMaxLength(); 813 var eccBlock = this._eccBlock; 814 815 for (i = 0; i < this._neccBlock1; i++) { 816 this._appendData(data, dataBlock, ecc, eccBlock); 817 818 data += dataBlock; 819 ecc += eccBlock; 820 } 821 822 for (i = 0; i < this._neccBlock2; i++) { 823 this._appendData(data, dataBlock + 1, ecc, eccBlock); 824 825 data += dataBlock + 1; 826 ecc += eccBlock; 827 } 828 }, 829 830 _applyMask: function(mask) { 831 var r3x, r3y, x, y; 832 var buffer = this.buffer; 833 var width = this.width; 834 835 switch (mask) { 836 case 0: 837 for (y = 0; y < width; y++) { 838 for (x = 0; x < width; x++) { 839 if (!((x + y) & 1) && !this._isMasked(x, y)) { 840 buffer[x + (y * width)] ^= 1; 841 } 842 } 843 } 844 845 break; 846 case 1: 847 for (y = 0; y < width; y++) { 848 for (x = 0; x < width; x++) { 849 if (!(y & 1) && !this._isMasked(x, y)) { 850 buffer[x + (y * width)] ^= 1; 851 } 852 } 853 } 854 855 break; 856 case 2: 857 for (y = 0; y < width; y++) { 858 for (r3x = 0, x = 0; x < width; x++, r3x++) { 859 if (r3x === 3) { 860 r3x = 0; 861 } 862 863 if (!r3x && !this._isMasked(x, y)) { 864 buffer[x + (y * width)] ^= 1; 865 } 866 } 867 } 868 869 break; 870 case 3: 871 for (r3y = 0, y = 0; y < width; y++, r3y++) { 872 if (r3y === 3) { 873 r3y = 0; 874 } 875 876 for (r3x = r3y, x = 0; x < width; x++, r3x++) { 877 if (r3x === 3) { 878 r3x = 0; 879 } 880 881 if (!r3x && !this._isMasked(x, y)) { 882 buffer[x + (y * width)] ^= 1; 883 } 884 } 885 } 886 887 break; 888 case 4: 889 for (y = 0; y < width; y++) { 890 for (r3x = 0, r3y = (y >> 1) & 1, x = 0; x < width; x++, r3x++) { 891 if (r3x === 3) { 892 r3x = 0; 893 r3y = !r3y; 894 } 895 896 if (!r3y && !this._isMasked(x, y)) { 897 buffer[x + (y * width)] ^= 1; 898 } 899 } 900 } 901 902 break; 903 case 5: 904 for (r3y = 0, y = 0; y < width; y++, r3y++) { 905 if (r3y === 3) { 906 r3y = 0; 907 } 908 909 for (r3x = 0, x = 0; x < width; x++, r3x++) { 910 if (r3x === 3) { 911 r3x = 0; 912 } 913 914 if (!((x & y & 1) + !(!r3x | !r3y)) && !this._isMasked(x, y)) { 915 buffer[x + (y * width)] ^= 1; 916 } 917 } 918 } 919 920 break; 921 case 6: 922 for (r3y = 0, y = 0; y < width; y++, r3y++) { 923 if (r3y === 3) { 924 r3y = 0; 925 } 926 927 for (r3x = 0, x = 0; x < width; x++, r3x++) { 928 if (r3x === 3) { 929 r3x = 0; 930 } 931 932 if (!((x & y & 1) + (r3x && r3x === r3y) & 1) && !this._isMasked(x, y)) { 933 buffer[x + (y * width)] ^= 1; 934 } 935 } 936 } 937 938 break; 939 case 7: 940 for (r3y = 0, y = 0; y < width; y++, r3y++) { 941 if (r3y === 3) { 942 r3y = 0; 943 } 944 945 for (r3x = 0, x = 0; x < width; x++, r3x++) { 946 if (r3x === 3) { 947 r3x = 0; 948 } 949 950 if (!((r3x && r3x === r3y) + (x + y & 1) & 1) && !this._isMasked(x, y)) { 951 buffer[x + (y * width)] ^= 1; 952 } 953 } 954 } 955 956 break; 957 } 958 }, 959 960 _calculateMaxLength: function() { 961 return (this._dataBlock * (this._neccBlock1 + this._neccBlock2)) + this._neccBlock2; 962 }, 963 964 _calculatePolynomial: function() { 965 var i, j; 966 var eccBlock = this._eccBlock; 967 var polynomial = this._polynomial; 968 969 polynomial[0] = 1; 970 971 for (i = 0; i < eccBlock; i++) { 972 polynomial[i + 1] = 1; 973 974 for (j = i; j > 0; j--) { 975 polynomial[j] = polynomial[j] ? polynomial[j - 1] ^ 976 Galois_1.EXPONENT[Frame._modN(Galois_1.LOG[polynomial[j]] + i)] : polynomial[j - 1]; 977 } 978 979 polynomial[0] = Galois_1.EXPONENT[Frame._modN(Galois_1.LOG[polynomial[0]] + i)]; 980 } 981 982 // Use logs for generator polynomial to save calculation step. 983 for (i = 0; i <= eccBlock; i++) { 984 polynomial[i] = Galois_1.LOG[polynomial[i]]; 985 } 986 }, 987 988 _checkBadness: function() { 989 var b, b1, h, x, y; 990 var bad = 0; 991 var badness = this._badness; 992 var buffer = this.buffer; 993 var width = this.width; 994 995 // Blocks of same colour. 996 for (y = 0; y < width - 1; y++) { 997 for (x = 0; x < width - 1; x++) { 998 // All foreground colour. 999 if ((buffer[x + (width * y)] && 1000 buffer[x + 1 + (width * y)] && 1001 buffer[x + (width * (y + 1))] && 1002 buffer[x + 1 + (width * (y + 1))]) || 1003 // All background colour. 1004 !(buffer[x + (width * y)] || 1005 buffer[x + 1 + (width * y)] || 1006 buffer[x + (width * (y + 1))] || 1007 buffer[x + 1 + (width * (y + 1))])) { 1008 bad += Frame.N2; 1009 } 1010 } 1011 } 1012 1013 var bw = 0; 1014 1015 // X runs. 1016 for (y = 0; y < width; y++) { 1017 h = 0; 1018 1019 badness[0] = 0; 1020 1021 for (b = 0, x = 0; x < width; x++) { 1022 b1 = buffer[x + (width * y)]; 1023 1024 if (b === b1) { 1025 badness[h]++; 1026 } else { 1027 badness[++h] = 1; 1028 } 1029 1030 b = b1; 1031 bw += b ? 1 : -1; 1032 } 1033 1034 bad += this._getBadness(h); 1035 } 1036 1037 if (bw < 0) { 1038 bw = -bw; 1039 } 1040 1041 var count = 0; 1042 var big = bw; 1043 big += big << 2; 1044 big <<= 1; 1045 1046 while (big > width * width) { 1047 big -= width * width; 1048 count++; 1049 } 1050 1051 bad += count * Frame.N4; 1052 1053 // Y runs. 1054 for (x = 0; x < width; x++) { 1055 h = 0; 1056 1057 badness[0] = 0; 1058 1059 for (b = 0, y = 0; y < width; y++) { 1060 b1 = buffer[x + (width * y)]; 1061 1062 if (b === b1) { 1063 badness[h]++; 1064 } else { 1065 badness[++h] = 1; 1066 } 1067 1068 b = b1; 1069 } 1070 1071 bad += this._getBadness(h); 1072 } 1073 1074 return bad; 1075 }, 1076 1077 _convertBitStream: function(length) { 1078 var bit, i; 1079 var ecc = this._ecc; 1080 var version = this._version; 1081 1082 // Convert string to bit stream. 8-bit data to QR-coded 8-bit data (numeric, alphanumeric, or kanji not supported). 1083 for (i = 0; i < length; i++) { 1084 ecc[i] = this._value.charCodeAt(i); 1085 } 1086 1087 var stringBuffer = this._stringBuffer = ecc.slice(); 1088 var maxLength = this._calculateMaxLength(); 1089 1090 if (length >= maxLength - 2) { 1091 length = maxLength - 2; 1092 1093 if (version > 9) { 1094 length--; 1095 } 1096 } 1097 1098 // Shift and re-pack to insert length prefix. 1099 var index = length; 1100 1101 if (version > 9) { 1102 stringBuffer[index + 2] = 0; 1103 stringBuffer[index + 3] = 0; 1104 1105 while (index--) { 1106 bit = stringBuffer[index]; 1107 1108 stringBuffer[index + 3] |= 255 & (bit << 4); 1109 stringBuffer[index + 2] = bit >> 4; 1110 } 1111 1112 stringBuffer[2] |= 255 & (length << 4); 1113 stringBuffer[1] = length >> 4; 1114 stringBuffer[0] = 0x40 | (length >> 12); 1115 } else { 1116 stringBuffer[index + 1] = 0; 1117 stringBuffer[index + 2] = 0; 1118 1119 while (index--) { 1120 bit = stringBuffer[index]; 1121 1122 stringBuffer[index + 2] |= 255 & (bit << 4); 1123 stringBuffer[index + 1] = bit >> 4; 1124 } 1125 1126 stringBuffer[1] |= 255 & (length << 4); 1127 stringBuffer[0] = 0x40 | (length >> 4); 1128 } 1129 1130 // Fill to end with pad pattern. 1131 index = length + 3 - (version < 10); 1132 1133 while (index < maxLength) { 1134 stringBuffer[index++] = 0xec; 1135 stringBuffer[index++] = 0x11; 1136 } 1137 }, 1138 1139 _getBadness: function(length) { 1140 var i; 1141 var badRuns = 0; 1142 var badness = this._badness; 1143 1144 for (i = 0; i <= length; i++) { 1145 if (badness[i] >= 5) { 1146 badRuns += Frame.N1 + badness[i] - 5; 1147 } 1148 } 1149 1150 // FBFFFBF as in finder. 1151 for (i = 3; i < length - 1; i += 2) { 1152 if (badness[i - 2] === badness[i + 2] && 1153 badness[i + 2] === badness[i - 1] && 1154 badness[i - 1] === badness[i + 1] && 1155 badness[i - 1] * 3 === badness[i] && 1156 // Background around the foreground pattern? Not part of the specs. 1157 (badness[i - 3] === 0 || i + 3 > length || 1158 badness[i - 3] * 3 >= badness[i] * 4 || 1159 badness[i + 3] * 3 >= badness[i] * 4)) { 1160 badRuns += Frame.N3; 1161 } 1162 } 1163 1164 return badRuns; 1165 }, 1166 1167 _finish: function() { 1168 // Save pre-mask copy of frame. 1169 this._stringBuffer = this.buffer.slice(); 1170 1171 var currentMask, i; 1172 var bit = 0; 1173 var mask = 30000; 1174 1175 /* 1176 * Using for instead of while since in original Arduino code if an early mask was "good enough" it wouldn't try for 1177 * a better one since they get more complex and take longer. 1178 */ 1179 for (i = 0; i < 8; i++) { 1180 // Returns foreground-background imbalance. 1181 this._applyMask(i); 1182 1183 currentMask = this._checkBadness(); 1184 1185 // Is current mask better than previous best? 1186 if (currentMask < mask) { 1187 mask = currentMask; 1188 bit = i; 1189 } 1190 1191 // Don't increment "i" to a void redoing mask. 1192 if (bit === 7) { 1193 break; 1194 } 1195 1196 // Reset for next pass. 1197 this.buffer = this._stringBuffer.slice(); 1198 } 1199 1200 // Redo best mask as none were "good enough" (i.e. last wasn't bit). 1201 if (bit !== i) { 1202 this._applyMask(bit); 1203 } 1204 1205 // Add in final mask/ECC level bytes. 1206 mask = ErrorCorrection_1.FINAL_FORMAT[bit + (this._level - 1 << 3)]; 1207 1208 var buffer = this.buffer; 1209 var width = this.width; 1210 1211 // Low byte. 1212 for (i = 0; i < 8; i++, mask >>= 1) { 1213 if (mask & 1) { 1214 buffer[width - 1 - i + (width * 8)] = 1; 1215 1216 if (i < 6) { 1217 buffer[8 + (width * i)] = 1; 1218 } else { 1219 buffer[8 + (width * (i + 1))] = 1; 1220 } 1221 } 1222 } 1223 1224 // High byte. 1225 for (i = 0; i < 7; i++, mask >>= 1) { 1226 if (mask & 1) { 1227 buffer[8 + (width * (width - 7 + i))] = 1; 1228 1229 if (i) { 1230 buffer[6 - i + (width * 8)] = 1; 1231 } else { 1232 buffer[7 + (width * 8)] = 1; 1233 } 1234 } 1235 } 1236 }, 1237 1238 _interleaveBlocks: function() { 1239 var i, j; 1240 var dataBlock = this._dataBlock; 1241 var ecc = this._ecc; 1242 var eccBlock = this._eccBlock; 1243 var k = 0; 1244 var maxLength = this._calculateMaxLength(); 1245 var neccBlock1 = this._neccBlock1; 1246 var neccBlock2 = this._neccBlock2; 1247 var stringBuffer = this._stringBuffer; 1248 1249 for (i = 0; i < dataBlock; i++) { 1250 for (j = 0; j < neccBlock1; j++) { 1251 ecc[k++] = stringBuffer[i + (j * dataBlock)]; 1252 } 1253 1254 for (j = 0; j < neccBlock2; j++) { 1255 ecc[k++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))]; 1256 } 1257 } 1258 1259 for (j = 0; j < neccBlock2; j++) { 1260 ecc[k++] = stringBuffer[(neccBlock1 * dataBlock) + i + (j * (dataBlock + 1))]; 1261 } 1262 1263 for (i = 0; i < eccBlock; i++) { 1264 for (j = 0; j < neccBlock1 + neccBlock2; j++) { 1265 ecc[k++] = stringBuffer[maxLength + i + (j * eccBlock)]; 1266 } 1267 } 1268 1269 this._stringBuffer = ecc; 1270 }, 1271 1272 _insertAlignments: function() { 1273 var i, x, y; 1274 var version = this._version; 1275 var width = this.width; 1276 1277 if (version > 1) { 1278 i = Alignment_1.BLOCK[version]; 1279 y = width - 7; 1280 1281 for (;;) { 1282 x = width - 7; 1283 1284 while (x > i - 3) { 1285 this._addAlignment(x, y); 1286 1287 if (x < i) { 1288 break; 1289 } 1290 1291 x -= i; 1292 } 1293 1294 if (y <= i + 9) { 1295 break; 1296 } 1297 1298 y -= i; 1299 1300 this._addAlignment(6, y); 1301 this._addAlignment(y, 6); 1302 } 1303 } 1304 }, 1305 1306 _insertFinders: function() { 1307 var i, j, x, y; 1308 var buffer = this.buffer; 1309 var width = this.width; 1310 1311 for (i = 0; i < 3; i++) { 1312 j = 0; 1313 y = 0; 1314 1315 if (i === 1) { 1316 j = width - 7; 1317 } 1318 if (i === 2) { 1319 y = width - 7; 1320 } 1321 1322 buffer[y + 3 + (width * (j + 3))] = 1; 1323 1324 for (x = 0; x < 6; x++) { 1325 buffer[y + x + (width * j)] = 1; 1326 buffer[y + (width * (j + x + 1))] = 1; 1327 buffer[y + 6 + (width * (j + x))] = 1; 1328 buffer[y + x + 1 + (width * (j + 6))] = 1; 1329 } 1330 1331 for (x = 1; x < 5; x++) { 1332 this._setMask(y + x, j + 1); 1333 this._setMask(y + 1, j + x + 1); 1334 this._setMask(y + 5, j + x); 1335 this._setMask(y + x + 1, j + 5); 1336 } 1337 1338 for (x = 2; x < 4; x++) { 1339 buffer[y + x + (width * (j + 2))] = 1; 1340 buffer[y + 2 + (width * (j + x + 1))] = 1; 1341 buffer[y + 4 + (width * (j + x))] = 1; 1342 buffer[y + x + 1 + (width * (j + 4))] = 1; 1343 } 1344 } 1345 }, 1346 1347 _insertTimingGap: function() { 1348 var x, y; 1349 var width = this.width; 1350 1351 for (y = 0; y < 7; y++) { 1352 this._setMask(7, y); 1353 this._setMask(width - 8, y); 1354 this._setMask(7, y + width - 7); 1355 } 1356 1357 for (x = 0; x < 8; x++) { 1358 this._setMask(x, 7); 1359 this._setMask(x + width - 8, 7); 1360 this._setMask(x, width - 8); 1361 } 1362 }, 1363 1364 _insertTimingRowAndColumn: function() { 1365 var x; 1366 var buffer = this.buffer; 1367 var width = this.width; 1368 1369 for (x = 0; x < width - 14; x++) { 1370 if (x & 1) { 1371 this._setMask(8 + x, 6); 1372 this._setMask(6, 8 + x); 1373 } else { 1374 buffer[8 + x + (width * 6)] = 1; 1375 buffer[6 + (width * (8 + x))] = 1; 1376 } 1377 } 1378 }, 1379 1380 _insertVersion: function() { 1381 var i, j, x, y; 1382 var buffer = this.buffer; 1383 var version = this._version; 1384 var width = this.width; 1385 1386 if (version > 6) { 1387 i = Version_1.BLOCK[version - 7]; 1388 j = 17; 1389 1390 for (x = 0; x < 6; x++) { 1391 for (y = 0; y < 3; y++, j--) { 1392 if (1 & (j > 11 ? version >> j - 12 : i >> j)) { 1393 buffer[5 - x + (width * (2 - y + width - 11))] = 1; 1394 buffer[2 - y + width - 11 + (width * (5 - x))] = 1; 1395 } else { 1396 this._setMask(5 - x, 2 - y + width - 11); 1397 this._setMask(2 - y + width - 11, 5 - x); 1398 } 1399 } 1400 } 1401 } 1402 }, 1403 1404 _isMasked: function(x, y) { 1405 var bit = Frame._getMaskBit(x, y); 1406 1407 return this._mask[bit] === 1; 1408 }, 1409 1410 _pack: function() { 1411 var bit, i, j; 1412 var k = 1; 1413 var v = 1; 1414 var width = this.width; 1415 var x = width - 1; 1416 var y = width - 1; 1417 1418 // Interleaved data and ECC codes. 1419 var length = ((this._dataBlock + this._eccBlock) * (this._neccBlock1 + this._neccBlock2)) + this._neccBlock2; 1420 1421 for (i = 0; i < length; i++) { 1422 bit = this._stringBuffer[i]; 1423 1424 for (j = 0; j < 8; j++, bit <<= 1) { 1425 if (0x80 & bit) { 1426 this.buffer[x + (width * y)] = 1; 1427 } 1428 1429 // Find next fill position. 1430 do { 1431 if (v) { 1432 x--; 1433 } else { 1434 x++; 1435 1436 if (k) { 1437 if (y !== 0) { 1438 y--; 1439 } else { 1440 x -= 2; 1441 k = !k; 1442 1443 if (x === 6) { 1444 x--; 1445 y = 9; 1446 } 1447 } 1448 } else if (y !== width - 1) { 1449 y++; 1450 } else { 1451 x -= 2; 1452 k = !k; 1453 1454 if (x === 6) { 1455 x--; 1456 y -= 8; 1457 } 1458 } 1459 } 1460 1461 v = !v; 1462 } while (this._isMasked(x, y)); 1463 } 1464 } 1465 }, 1466 1467 _reverseMask: function() { 1468 var x, y; 1469 var width = this.width; 1470 1471 for (x = 0; x < 9; x++) { 1472 this._setMask(x, 8); 1473 } 1474 1475 for (x = 0; x < 8; x++) { 1476 this._setMask(x + width - 8, 8); 1477 this._setMask(8, x); 1478 } 1479 1480 for (y = 0; y < 7; y++) { 1481 this._setMask(8, y + width - 7); 1482 } 1483 }, 1484 1485 _setMask: function(x, y) { 1486 var bit = Frame._getMaskBit(x, y); 1487 1488 this._mask[bit] = 1; 1489 }, 1490 1491 _syncMask: function() { 1492 var x, y; 1493 var width = this.width; 1494 1495 for (y = 0; y < width; y++) { 1496 for (x = 0; x <= y; x++) { 1497 if (this.buffer[x + (width * y)]) { 1498 this._setMask(x, y); 1499 } 1500 } 1501 } 1502 } 1503 1504 }, { 1505 1506 _createArray: function(length) { 1507 var i; 1508 var array = []; 1509 1510 for (i = 0; i < length; i++) { 1511 array[i] = 0; 1512 } 1513 1514 return array; 1515 }, 1516 1517 _getMaskBit: function(x, y) { 1518 var bit; 1519 1520 if (x > y) { 1521 bit = x; 1522 x = y; 1523 y = bit; 1524 } 1525 1526 bit = y; 1527 bit += y * y; 1528 bit >>= 1; 1529 bit += x; 1530 1531 return bit; 1532 }, 1533 1534 _modN: function(x) { 1535 while (x >= 255) { 1536 x -= 255; 1537 x = (x >> 8) + (x & 255); 1538 } 1539 1540 return x; 1541 }, 1542 1543 // *Badness* coefficients. 1544 N1: 3, 1545 N2: 3, 1546 N3: 40, 1547 N4: 10 1548 1549 }); 1550 1551 var Frame_1 = Frame; 1552 1553 /** 1554 * The options used by {@link Frame}. 1555 * 1556 * @typedef {Object} Frame~Options 1557 * @property {string} level - The ECC level to be used. 1558 * @property {string} value - The value to be encoded. 1559 */ 1560 1561 /** 1562 * An implementation of {@link Renderer} for working with <code>img</code> elements. 1563 * 1564 * This depends on {@link CanvasRenderer} being executed first as this implementation simply applies the data URL from 1565 * the rendered <code>canvas</code> element as the <code>src</code> for the <code>img</code> element being rendered. 1566 * 1567 * @public 1568 * @class 1569 * @extends Renderer 1570 */ 1571 var ImageRenderer = Renderer_1.extend({ 1572 1573 /** 1574 * @override 1575 */ 1576 draw: function() { 1577 this.element.src = this.qrious.toDataURL(); 1578 }, 1579 1580 /** 1581 * @override 1582 */ 1583 reset: function() { 1584 this.element.src = ''; 1585 }, 1586 1587 /** 1588 * @override 1589 */ 1590 resize: function() { 1591 var element = this.element; 1592 1593 element.width = element.height = this.qrious.size; 1594 } 1595 1596 }); 1597 1598 var ImageRenderer_1 = ImageRenderer; 1599 1600 /** 1601 * Defines an available option while also configuring how values are applied to the target object. 1602 * 1603 * Optionally, a default value can be specified as well a value transformer for greater control over how the option 1604 * value is applied. 1605 * 1606 * If no value transformer is specified, then any specified option will be applied directly. All values are maintained 1607 * on the target object itself as a field using the option name prefixed with a single underscore. 1608 * 1609 * When an option is specified as modifiable, the {@link OptionManager} will be required to include a setter for the 1610 * property that is defined on the target object that uses the option name. 1611 * 1612 * @param {string} name - the name to be used 1613 * @param {boolean} [modifiable] - <code>true</code> if the property defined on target objects should include a setter; 1614 * otherwise <code>false</code> 1615 * @param {*} [defaultValue] - the default value to be used 1616 * @param {Option~ValueTransformer} [valueTransformer] - the value transformer to be used 1617 * @public 1618 * @class 1619 * @extends Nevis 1620 */ 1621 var Option = lite.extend(function(name, modifiable, defaultValue, valueTransformer) { 1622 /** 1623 * The name for this {@link Option}. 1624 * 1625 * @public 1626 * @type {string} 1627 * @memberof Option# 1628 */ 1629 this.name = name; 1630 1631 /** 1632 * Whether a setter should be included on the property defined on target objects for this {@link Option}. 1633 * 1634 * @public 1635 * @type {boolean} 1636 * @memberof Option# 1637 */ 1638 this.modifiable = Boolean(modifiable); 1639 1640 /** 1641 * The default value for this {@link Option}. 1642 * 1643 * @public 1644 * @type {*} 1645 * @memberof Option# 1646 */ 1647 this.defaultValue = defaultValue; 1648 1649 this._valueTransformer = valueTransformer; 1650 }, { 1651 1652 /** 1653 * Transforms the specified <code>value</code> so that it can be applied for this {@link Option}. 1654 * 1655 * If a value transformer has been specified for this {@link Option}, it will be called upon to transform 1656 * <code>value</code>. Otherwise, <code>value</code> will be returned directly. 1657 * 1658 * @param {*} value - the value to be transformed 1659 * @return {*} The transformed value or <code>value</code> if no value transformer is specified. 1660 * @public 1661 * @memberof Option# 1662 */ 1663 transform: function(value) { 1664 var transformer = this._valueTransformer; 1665 if (typeof transformer === 'function') { 1666 return transformer(value, this); 1667 } 1668 1669 return value; 1670 } 1671 1672 }); 1673 1674 var Option_1 = Option; 1675 1676 /** 1677 * Returns a transformed value for the specified <code>value</code> to be applied for the <code>option</code> provided. 1678 * 1679 * @callback Option~ValueTransformer 1680 * @param {*} value - the value to be transformed 1681 * @param {Option} option - the {@link Option} for which <code>value</code> is being transformed 1682 * @return {*} The transform value. 1683 */ 1684 1685 /** 1686 * Contains utility methods that are useful throughout the library. 1687 * 1688 * @public 1689 * @class 1690 * @extends Nevis 1691 */ 1692 var Utilities = lite.extend(null, { 1693 1694 /** 1695 * Returns the absolute value of a given number. 1696 * 1697 * This method is simply a convenient shorthand for <code>Math.abs</code> while ensuring that nulls are returned as 1698 * <code>null</code> instead of zero. 1699 * 1700 * @param {number} value - the number whose absolute value is to be returned 1701 * @return {number} The absolute value of <code>value</code> or <code>null</code> if <code>value</code> is 1702 * <code>null</code>. 1703 * @public 1704 * @static 1705 * @memberof Utilities 1706 */ 1707 abs: function(value) { 1708 return value != null ? Math.abs(value) : null; 1709 }, 1710 1711 /** 1712 * Returns whether the specified <code>object</code> has a property with the specified <code>name</code> as an own 1713 * (not inherited) property. 1714 * 1715 * @param {Object} object - the object on which the property is to be checked 1716 * @param {string} name - the name of the property to be checked 1717 * @return {boolean} <code>true</code> if <code>object</code> has an own property with <code>name</code>. 1718 * @public 1719 * @static 1720 * @memberof Utilities 1721 */ 1722 hasOwn: function(object, name) { 1723 return Object.prototype.hasOwnProperty.call(object, name); 1724 }, 1725 1726 /** 1727 * A non-operation method that does absolutely nothing. 1728 * 1729 * @return {void} 1730 * @public 1731 * @static 1732 * @memberof Utilities 1733 */ 1734 noop: function() {}, 1735 1736 /** 1737 * Transforms the specified <code>string</code> to upper case while remaining null-safe. 1738 * 1739 * @param {string} string - the string to be transformed to upper case 1740 * @return {string} <code>string</code> transformed to upper case if <code>string</code> is not <code>null</code>. 1741 * @public 1742 * @static 1743 * @memberof Utilities 1744 */ 1745 toUpperCase: function(string) { 1746 return string != null ? string.toUpperCase() : null; 1747 } 1748 1749 }); 1750 1751 var Utilities_1 = Utilities; 1752 1753 /** 1754 * Manages multiple {@link Option} instances that are intended to be used by multiple implementations. 1755 * 1756 * Although the option definitions are shared between targets, the values are maintained on the targets themselves. 1757 * 1758 * @param {Option[]} options - the options to be used 1759 * @public 1760 * @class 1761 * @extends Nevis 1762 */ 1763 var OptionManager = lite.extend(function(options) { 1764 /** 1765 * The available options for this {@link OptionManager}. 1766 * 1767 * @public 1768 * @type {Object.<string, Option>} 1769 * @memberof OptionManager# 1770 */ 1771 this.options = {}; 1772 1773 options.forEach(function(option) { 1774 this.options[option.name] = option; 1775 }, this); 1776 }, { 1777 1778 /** 1779 * Returns whether an option with the specified <code>name</code> is available. 1780 * 1781 * @param {string} name - the name of the {@link Option} whose existence is to be checked 1782 * @return {boolean} <code>true</code> if an {@link Option} exists with <code>name</code>; otherwise 1783 * <code>false</code>. 1784 * @public 1785 * @memberof OptionManager# 1786 */ 1787 exists: function(name) { 1788 return this.options[name] != null; 1789 }, 1790 1791 /** 1792 * Returns the value of the option with the specified <code>name</code> on the <code>target</code> object provided. 1793 * 1794 * @param {string} name - the name of the {@link Option} whose value on <code>target</code> is to be returned 1795 * @param {Object} target - the object from which the value of the named {@link Option} is to be returned 1796 * @return {*} The value of the {@link Option} with <code>name</code> on <code>target</code>. 1797 * @public 1798 * @memberof OptionManager# 1799 */ 1800 get: function(name, target) { 1801 return OptionManager._get(this.options[name], target); 1802 }, 1803 1804 /** 1805 * Returns a copy of all of the available options on the <code>target</code> object provided. 1806 * 1807 * @param {Object} target - the object from which the option name/value pairs are to be returned 1808 * @return {Object.<string, *>} A hash containing the name/value pairs of all options on <code>target</code>. 1809 * @public 1810 * @memberof OptionManager# 1811 */ 1812 getAll: function(target) { 1813 var name; 1814 var options = this.options; 1815 var result = {}; 1816 1817 for (name in options) { 1818 if (Utilities_1.hasOwn(options, name)) { 1819 result[name] = OptionManager._get(options[name], target); 1820 } 1821 } 1822 1823 return result; 1824 }, 1825 1826 /** 1827 * Initializes the available options for the <code>target</code> object provided and then applies the initial values 1828 * within the speciifed <code>options</code>. 1829 * 1830 * This method will throw an error if any of the names within <code>options</code> does not match an available option. 1831 * 1832 * This involves setting the default values and defining properties for all of the available options on 1833 * <code>target</code> before finally calling {@link OptionMananger#setAll} with <code>options</code> and 1834 * <code>target</code>. Any options that are configured to be modifiable will have a setter included in their defined 1835 * property that will allow its corresponding value to be modified. 1836 * 1837 * If a change handler is specified, it will be called whenever the value changes on <code>target</code> for a 1838 * modifiable option, but only when done so via the defined property's setter. 1839 * 1840 * @param {Object.<string, *>} options - the name/value pairs of the initial options to be set 1841 * @param {Object} target - the object on which the options are to be initialized 1842 * @param {Function} [changeHandler] - the function to be called whenever the value of an modifiable option changes on 1843 * <code>target</code> 1844 * @return {void} 1845 * @throws {Error} If <code>options</code> contains an invalid option name. 1846 * @public 1847 * @memberof OptionManager# 1848 */ 1849 init: function(options, target, changeHandler) { 1850 if (typeof changeHandler !== 'function') { 1851 changeHandler = Utilities_1.noop; 1852 } 1853 1854 var name, option; 1855 1856 for (name in this.options) { 1857 if (Utilities_1.hasOwn(this.options, name)) { 1858 option = this.options[name]; 1859 1860 OptionManager._set(option, option.defaultValue, target); 1861 OptionManager._createAccessor(option, target, changeHandler); 1862 } 1863 } 1864 1865 this._setAll(options, target, true); 1866 }, 1867 1868 /** 1869 * Sets the value of the option with the specified <code>name</code> on the <code>target</code> object provided to 1870 * <code>value</code>. 1871 * 1872 * This method will throw an error if <code>name</code> does not match an available option or matches an option that 1873 * cannot be modified. 1874 * 1875 * If <code>value</code> is <code>null</code> and the {@link Option} has a default value configured, then that default 1876 * value will be used instead. If the {@link Option} also has a value transformer configured, it will be used to 1877 * transform whichever value was determined to be used. 1878 * 1879 * This method returns whether the value of the underlying field on <code>target</code> was changed as a result. 1880 * 1881 * @param {string} name - the name of the {@link Option} whose value is to be set 1882 * @param {*} value - the value to be set for the named {@link Option} on <code>target</code> 1883 * @param {Object} target - the object on which <code>value</code> is to be set for the named {@link Option} 1884 * @return {boolean} <code>true</code> if the underlying field on <code>target</code> was changed; otherwise 1885 * <code>false</code>. 1886 * @throws {Error} If <code>name</code> is invalid or is for an option that cannot be modified. 1887 * @public 1888 * @memberof OptionManager# 1889 */ 1890 set: function(name, value, target) { 1891 return this._set(name, value, target); 1892 }, 1893 1894 /** 1895 * Sets all of the specified <code>options</code> on the <code>target</code> object provided to their corresponding 1896 * values. 1897 * 1898 * This method will throw an error if any of the names within <code>options</code> does not match an available option 1899 * or matches an option that cannot be modified. 1900 * 1901 * If any value within <code>options</code> is <code>null</code> and the corresponding {@link Option} has a default 1902 * value configured, then that default value will be used instead. If an {@link Option} also has a value transformer 1903 * configured, it will be used to transform whichever value was determined to be used. 1904 * 1905 * This method returns whether the value for any of the underlying fields on <code>target</code> were changed as a 1906 * result. 1907 * 1908 * @param {Object.<string, *>} options - the name/value pairs of options to be set 1909 * @param {Object} target - the object on which the options are to be set 1910 * @return {boolean} <code>true</code> if any of the underlying fields on <code>target</code> were changed; otherwise 1911 * <code>false</code>. 1912 * @throws {Error} If <code>options</code> contains an invalid option name or an option that cannot be modiifed. 1913 * @public 1914 * @memberof OptionManager# 1915 */ 1916 setAll: function(options, target) { 1917 return this._setAll(options, target); 1918 }, 1919 1920 _set: function(name, value, target, allowUnmodifiable) { 1921 var option = this.options[name]; 1922 if (!option) { 1923 throw new Error('Invalid option: ' + name); 1924 } 1925 if (!option.modifiable && !allowUnmodifiable) { 1926 throw new Error('Option cannot be modified: ' + name); 1927 } 1928 1929 return OptionManager._set(option, value, target); 1930 }, 1931 1932 _setAll: function(options, target, allowUnmodifiable) { 1933 if (!options) { 1934 return false; 1935 } 1936 1937 var name; 1938 var changed = false; 1939 1940 for (name in options) { 1941 if (Utilities_1.hasOwn(options, name) && this._set(name, options[name], target, allowUnmodifiable)) { 1942 changed = true; 1943 } 1944 } 1945 1946 return changed; 1947 } 1948 1949 }, { 1950 1951 _createAccessor: function(option, target, changeHandler) { 1952 var descriptor = { 1953 get: function() { 1954 return OptionManager._get(option, target); 1955 } 1956 }; 1957 1958 if (option.modifiable) { 1959 descriptor.set = function(value) { 1960 if (OptionManager._set(option, value, target)) { 1961 changeHandler(value, option); 1962 } 1963 }; 1964 } 1965 1966 Object.defineProperty(target, option.name, descriptor); 1967 }, 1968 1969 _get: function(option, target) { 1970 return target['_' + option.name]; 1971 }, 1972 1973 _set: function(option, value, target) { 1974 var fieldName = '_' + option.name; 1975 var oldValue = target[fieldName]; 1976 var newValue = option.transform(value != null ? value : option.defaultValue); 1977 1978 target[fieldName] = newValue; 1979 1980 return newValue !== oldValue; 1981 } 1982 1983 }); 1984 1985 var OptionManager_1 = OptionManager; 1986 1987 /** 1988 * Called whenever the value of a modifiable {@link Option} is changed on a target object via the defined property's 1989 * setter. 1990 * 1991 * @callback OptionManager~ChangeHandler 1992 * @param {*} value - the new value for <code>option</code> on the target object 1993 * @param {Option} option - the modifable {@link Option} whose value has changed on the target object. 1994 * @return {void} 1995 */ 1996 1997 /** 1998 * A basic manager for {@link Service} implementations that are mapped to simple names. 1999 * 2000 * @public 2001 * @class 2002 * @extends Nevis 2003 */ 2004 var ServiceManager = lite.extend(function() { 2005 this._services = {}; 2006 }, { 2007 2008 /** 2009 * Returns the {@link Service} being managed with the specified <code>name</code>. 2010 * 2011 * @param {string} name - the name of the {@link Service} to be returned 2012 * @return {Service} The {@link Service} is being managed with <code>name</code>. 2013 * @throws {Error} If no {@link Service} is being managed with <code>name</code>. 2014 * @public 2015 * @memberof ServiceManager# 2016 */ 2017 getService: function(name) { 2018 var service = this._services[name]; 2019 if (!service) { 2020 throw new Error('Service is not being managed with name: ' + name); 2021 } 2022 2023 return service; 2024 }, 2025 2026 /** 2027 * Sets the {@link Service} implementation to be managed for the specified <code>name</code> to the 2028 * <code>service</code> provided. 2029 * 2030 * @param {string} name - the name of the {@link Service} to be managed with <code>name</code> 2031 * @param {Service} service - the {@link Service} implementation to be managed 2032 * @return {void} 2033 * @throws {Error} If a {@link Service} is already being managed with the same <code>name</code>. 2034 * @public 2035 * @memberof ServiceManager# 2036 */ 2037 setService: function(name, service) { 2038 if (this._services[name]) { 2039 throw new Error('Service is already managed with name: ' + name); 2040 } 2041 2042 if (service) { 2043 this._services[name] = service; 2044 } 2045 } 2046 2047 }); 2048 2049 var ServiceManager_1 = ServiceManager; 2050 2051 var optionManager = new OptionManager_1([ 2052 new Option_1('background', true, 'white'), 2053 new Option_1('backgroundAlpha', true, 1, Utilities_1.abs), 2054 new Option_1('element'), 2055 new Option_1('foreground', true, 'black'), 2056 new Option_1('foregroundAlpha', true, 1, Utilities_1.abs), 2057 new Option_1('level', true, 'L', Utilities_1.toUpperCase), 2058 new Option_1('mime', true, 'image/png'), 2059 new Option_1('padding', true, null, Utilities_1.abs), 2060 new Option_1('size', true, 100, Utilities_1.abs), 2061 new Option_1('value', true, '') 2062 ]); 2063 var serviceManager = new ServiceManager_1(); 2064 2065 /** 2066 * Enables configuration of a QR code generator which uses HTML5 <code>canvas</code> for rendering. 2067 * 2068 * @param {QRious~Options} [options] - the options to be used 2069 * @throws {Error} If any <code>options</code> are invalid. 2070 * @public 2071 * @class 2072 * @extends Nevis 2073 */ 2074 var QRious = lite.extend(function(options) { 2075 optionManager.init(options, this, this.update.bind(this)); 2076 2077 var element = optionManager.get('element', this); 2078 var elementService = serviceManager.getService('element'); 2079 var canvas = element && elementService.isCanvas(element) ? element : elementService.createCanvas(); 2080 var image = element && elementService.isImage(element) ? element : elementService.createImage(); 2081 2082 this._canvasRenderer = new CanvasRenderer_1(this, canvas, true); 2083 this._imageRenderer = new ImageRenderer_1(this, image, image === element); 2084 2085 this.update(); 2086 }, { 2087 2088 /** 2089 * Returns all of the options configured for this {@link QRious}. 2090 * 2091 * Any changes made to the returned object will not be reflected in the options themselves or their corresponding 2092 * underlying fields. 2093 * 2094 * @return {Object.<string, *>} A copy of the applied options. 2095 * @public 2096 * @memberof QRious# 2097 */ 2098 get: function() { 2099 return optionManager.getAll(this); 2100 }, 2101 2102 /** 2103 * Sets all of the specified <code>options</code> and automatically updates this {@link QRious} if any of the 2104 * underlying fields are changed as a result. 2105 * 2106 * This is the preferred method for updating multiple options at one time to avoid unnecessary updates between 2107 * changes. 2108 * 2109 * @param {QRious~Options} options - the options to be set 2110 * @return {void} 2111 * @throws {Error} If any <code>options</code> are invalid or cannot be modified. 2112 * @public 2113 * @memberof QRious# 2114 */ 2115 set: function(options) { 2116 if (optionManager.setAll(options, this)) { 2117 this.update(); 2118 } 2119 }, 2120 2121 /** 2122 * Returns the image data URI for the generated QR code using the <code>mime</code> provided. 2123 * 2124 * @param {string} [mime] - the MIME type for the image 2125 * @return {string} The image data URI for the QR code. 2126 * @public 2127 * @memberof QRious# 2128 */ 2129 toDataURL: function(mime) { 2130 return this.canvas.toDataURL(mime || this.mime); 2131 }, 2132 2133 /** 2134 * Updates this {@link QRious} by generating a new {@link Frame} and re-rendering the QR code. 2135 * 2136 * @return {void} 2137 * @protected 2138 * @memberof QRious# 2139 */ 2140 update: function() { 2141 var frame = new Frame_1({ 2142 level: this.level, 2143 value: this.value 2144 }); 2145 2146 this._canvasRenderer.render(frame); 2147 this._imageRenderer.render(frame); 2148 } 2149 2150 }, { 2151 2152 /** 2153 * Configures the <code>service</code> provided to be used by all {@link QRious} instances. 2154 * 2155 * @param {Service} service - the {@link Service} to be configured 2156 * @return {void} 2157 * @throws {Error} If a {@link Service} has already been configured with the same name. 2158 * @public 2159 * @static 2160 * @memberof QRious 2161 */ 2162 use: function(service) { 2163 serviceManager.setService(service.getName(), service); 2164 } 2165 2166 }); 2167 2168 Object.defineProperties(QRious.prototype, { 2169 2170 canvas: { 2171 /** 2172 * Returns the <code>canvas</code> element being used to render the QR code for this {@link QRious}. 2173 * 2174 * @return {*} The <code>canvas</code> element. 2175 * @public 2176 * @memberof QRious# 2177 * @alias canvas 2178 */ 2179 get: function() { 2180 return this._canvasRenderer.getElement(); 2181 } 2182 }, 2183 2184 image: { 2185 /** 2186 * Returns the <code>img</code> element being used to render the QR code for this {@link QRious}. 2187 * 2188 * @return {*} The <code>img</code> element. 2189 * @public 2190 * @memberof QRious# 2191 * @alias image 2192 */ 2193 get: function() { 2194 return this._imageRenderer.getElement(); 2195 } 2196 } 2197 2198 }); 2199 2200 var QRious_1$2 = QRious; 2201 2202 /** 2203 * The options used by {@link QRious}. 2204 * 2205 * @typedef {Object} QRious~Options 2206 * @property {string} [background="white"] - The background color to be applied to the QR code. 2207 * @property {number} [backgroundAlpha=1] - The background alpha to be applied to the QR code. 2208 * @property {*} [element] - The element to be used to render the QR code which may either be an <code>canvas</code> or 2209 * <code>img</code>. The element(s) will be created if needed. 2210 * @property {string} [foreground="black"] - The foreground color to be applied to the QR code. 2211 * @property {number} [foregroundAlpha=1] - The foreground alpha to be applied to the QR code. 2212 * @property {string} [level="L"] - The error correction level to be applied to the QR code. 2213 * @property {string} [mime="image/png"] - The MIME type to be used to render the image for the QR code. 2214 * @property {number} [padding] - The padding for the QR code in pixels. 2215 * @property {number} [size=100] - The size of the QR code in pixels. 2216 * @property {string} [value=""] - The value to be encoded within the QR code. 2217 */ 2218 2219 var index = QRious_1$2; 2220 2221 /** 2222 * Defines a service contract that must be met by all implementations. 2223 * 2224 * @public 2225 * @class 2226 * @extends Nevis 2227 */ 2228 var Service = lite.extend({ 2229 2230 /** 2231 * Returns the name of this {@link Service}. 2232 * 2233 * @return {string} The service name. 2234 * @public 2235 * @abstract 2236 * @memberof Service# 2237 */ 2238 getName: function() {} 2239 2240 }); 2241 2242 var Service_1 = Service; 2243 2244 /** 2245 * A service for working with elements. 2246 * 2247 * @public 2248 * @class 2249 * @extends Service 2250 */ 2251 var ElementService = Service_1.extend({ 2252 2253 /** 2254 * Creates an instance of a canvas element. 2255 * 2256 * Implementations of {@link ElementService} <b>must</b> override this method with their own specific logic. 2257 * 2258 * @return {*} The newly created canvas element. 2259 * @public 2260 * @abstract 2261 * @memberof ElementService# 2262 */ 2263 createCanvas: function() {}, 2264 2265 /** 2266 * Creates an instance of a image element. 2267 * 2268 * Implementations of {@link ElementService} <b>must</b> override this method with their own specific logic. 2269 * 2270 * @return {*} The newly created image element. 2271 * @public 2272 * @abstract 2273 * @memberof ElementService# 2274 */ 2275 createImage: function() {}, 2276 2277 /** 2278 * @override 2279 */ 2280 getName: function() { 2281 return 'element'; 2282 }, 2283 2284 /** 2285 * Returns whether the specified <code>element</code> is a canvas. 2286 * 2287 * Implementations of {@link ElementService} <b>must</b> override this method with their own specific logic. 2288 * 2289 * @param {*} element - the element to be checked 2290 * @return {boolean} <code>true</code> if <code>element</code> is a canvas; otherwise <code>false</code>. 2291 * @public 2292 * @abstract 2293 * @memberof ElementService# 2294 */ 2295 isCanvas: function(element) {}, 2296 2297 /** 2298 * Returns whether the specified <code>element</code> is an image. 2299 * 2300 * Implementations of {@link ElementService} <b>must</b> override this method with their own specific logic. 2301 * 2302 * @param {*} element - the element to be checked 2303 * @return {boolean} <code>true</code> if <code>element</code> is an image; otherwise <code>false</code>. 2304 * @public 2305 * @abstract 2306 * @memberof ElementService# 2307 */ 2308 isImage: function(element) {} 2309 2310 }); 2311 2312 var ElementService_1 = ElementService; 2313 2314 /** 2315 * An implementation of {@link ElementService} intended for use within a browser environment. 2316 * 2317 * @public 2318 * @class 2319 * @extends ElementService 2320 */ 2321 var BrowserElementService = ElementService_1.extend({ 2322 2323 /** 2324 * @override 2325 */ 2326 createCanvas: function() { 2327 return document.createElement('canvas'); 2328 }, 2329 2330 /** 2331 * @override 2332 */ 2333 createImage: function() { 2334 return document.createElement('img'); 2335 }, 2336 2337 /** 2338 * @override 2339 */ 2340 isCanvas: function(element) { 2341 return element instanceof HTMLCanvasElement; 2342 }, 2343 2344 /** 2345 * @override 2346 */ 2347 isImage: function(element) { 2348 return element instanceof HTMLImageElement; 2349 } 2350 2351 }); 2352 2353 var BrowserElementService_1 = BrowserElementService; 2354 2355 index.use(new BrowserElementService_1()); 2356 2357 var QRious_1 = index; 2358 2359 return QRious_1; 2360 2361 }))); 2362 2363 //# sourceMappingURL=qrious.js.map