@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update phpqrcode from version 1.1.4 to 1.9.9

Summary:
Update the internal copy of `phpqrcode` from version 1.1.4 (2010100721) to version 1.9.9 (20130526).
Single reason is that it adds a lot of documentation which may come handy one day.
This more recent code is taken from https://sourceforge.net/p/phpqrcode/code/19/ which equals https://github.com/Darkflib/php-qrcode/blob/master/lib/merged/phpqrcode.php, with our two custom one-line patches still on top.

Closes T15878

Test Plan:
* Manually diff between old downstream and slightly newer upstream version in a visual diff tool to review the changes.
* Go to http://phorge.localhost/settings/panel/multifactor/ and select "Add Auth Factor", select TOTP, click "Continue", still see a QR code properly rendered which works.

Reviewers: O1 Blessed Committers, valerio.bozzolan

Reviewed By: O1 Blessed Committers, valerio.bozzolan

Subscribers: tobiaswiese, valerio.bozzolan, Matthew, Cigaryno

Maniphest Tasks: T15878

Differential Revision: https://we.phorge.it/D25725

+1962 -259
+1962 -259
externals/phpqrcode/phpqrcode.php
··· 33 33 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 34 34 */ 35 35 36 - 37 - 38 - /* 39 - * Version: 1.1.4 40 - * Build: 2010100721 41 - */ 42 - 43 - 44 - 45 - //---- qrconst.php ----------------------------- 46 - 47 - 48 - 36 + 37 + 38 + /* 39 + * Version: 1.9.9 40 + * Build: 20130526 41 + */ 42 + 43 + 44 + 45 + //---- qrconst.php ----------------------------- 46 + 47 + 48 + 49 49 50 50 51 51 /* ··· 57 57 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 58 58 * 59 59 * PHP QR Code is distributed under LGPL 3 60 - * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 60 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 61 61 * 62 62 * This library is free software; you can redistribute it and/or 63 63 * modify it under the terms of the GNU Lesser General Public ··· 74 74 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 75 75 */ 76 76 77 - // Encoding modes 78 - 79 - define('QR_MODE_NUL', -1); 80 - define('QR_MODE_NUM', 0); 81 - define('QR_MODE_AN', 1); 82 - define('QR_MODE_8', 2); 83 - define('QR_MODE_KANJI', 3); 84 - define('QR_MODE_STRUCTURE', 4); 77 + 78 + /** \defgroup QR_CONST Global Constants 79 + Constant used globally for function arguments. 80 + Make PHP calls a little bit more clear, in place of missing (in dynamicaly typed language) enum types. 81 + * @{ 82 + */ 83 + 84 + /** @name QR-Code Encoding Modes */ 85 + /** @{ */ 86 + 87 + /** null encoding, used when no encoding was speciffied yet */ 88 + define('QR_MODE_NUL', -1); 89 + /** Numerical encoding, only numbers (0-9) */ 90 + define('QR_MODE_NUM', 0); 91 + /** AlphaNumerical encoding, numbers (0-9) uppercase text (A-Z) and few special characters (space, $, %, *, +, -, ., /, :) */ 92 + define('QR_MODE_AN', 1); 93 + /** 8-bit encoding, raw 8 bit encoding */ 94 + define('QR_MODE_8', 2); 95 + /** Kanji encoding */ 96 + define('QR_MODE_KANJI', 3); 97 + /** Structure, internal encoding for structure-related data */ 98 + define('QR_MODE_STRUCTURE', 4); 99 + /**@}*/ 100 + 101 + /** @name QR-Code Levels of Error Correction 102 + Constants speciffy ECC level from lowest __L__ to the highest __H__. 103 + Higher levels are recomended for Outdoor-presented codes, but generates bigger codes. 104 + */ 105 + /** @{*/ 106 + /** ~7% of codewords can be restored */ 107 + define('QR_ECLEVEL_L', 0); 108 + /** ~15% of codewords can be restored */ 109 + define('QR_ECLEVEL_M', 1); 110 + /** ~25% of codewords can be restored */ 111 + define('QR_ECLEVEL_Q', 2); 112 + /** ~30% of codewords can be restored */ 113 + define('QR_ECLEVEL_H', 3); 114 + /** @}*/ 115 + 116 + /** @name QR-Code Supported output formats */ 117 + /** @{*/ 118 + define('QR_FORMAT_TEXT', 0); 119 + define('QR_FORMAT_PNG', 1); 120 + /** @}*/ 121 + 122 + /** @}*/ 123 + 124 + 125 + 126 + 127 + //---- merged_config.php ----------------------------- 128 + 85 129 86 - // Levels of error correction. 87 130 88 - define('QR_ECLEVEL_L', 0); 89 - define('QR_ECLEVEL_M', 1); 90 - define('QR_ECLEVEL_Q', 2); 91 - define('QR_ECLEVEL_H', 3); 92 - 93 - // Supported output formats 94 - 95 - define('QR_FORMAT_TEXT', 0); 96 - define('QR_FORMAT_PNG', 1); 97 - 98 - class qrstr { 99 - public static function set(&$srctab, $x, $y, $repl, $replLen = false) { 100 - $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); 101 - } 102 - } 103 - 104 - 105 - 106 - //---- merged_config.php ----------------------------- 107 - 108 - 109 - 110 131 111 132 /* 112 133 * PHP QR Code encoder ··· 123 144 define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false 124 145 125 146 define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images 126 - 127 - 128 - 129 - 130 - //---- qrtools.php ----------------------------- 131 - 132 - 133 - 147 + 148 + 149 + 150 + 151 + //---- qrtools.php ----------------------------- 152 + 153 + 154 + 134 155 135 156 /* 136 157 * PHP QR Code encoder ··· 138 159 * Toolset, handy and debug utilites. 139 160 * 140 161 * PHP QR Code is distributed under LGPL 3 141 - * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 162 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 142 163 * 143 164 * This library is free software; you can redistribute it and/or 144 165 * modify it under the terms of the GNU Lesser General Public ··· 155 176 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 156 177 */ 157 178 179 + /** @addtogroup CoreGroup */ 180 + /** @{ */ 181 + 182 + /** Helper class */ 158 183 class QRtools { 159 184 185 + public static $timeBenchmarkStarted = false; 186 + 160 187 //---------------------------------------------------------------------- 161 188 public static function binarize($frame) 162 189 { ··· 255 282 } 256 283 } 257 284 285 + //---------------------------------------------------------------------- 286 + public static function startTimeBenchmark() 287 + { 288 + $GLOBALS['qr_time_bench'] = array(); 289 + self::markTime('start'); 290 + } 291 + 258 292 //---------------------------------------------------------------------- 259 293 public static function markTime($markerId) 260 294 { ··· 265 299 $GLOBALS['qr_time_bench'] = array(); 266 300 267 301 $GLOBALS['qr_time_bench'][$markerId] = $time; 302 + 303 + if ((!self::$timeBenchmarkStarted)&&($markerId != 'start')) { 304 + self::$timeBenchmarkStarted = true; 305 + $GLOBALS['qr_time_bench']['start'] = $time; 306 + } 268 307 } 269 308 270 309 //---------------------------------------------------------------------- ··· 299 338 300 339 } 301 340 341 + /** @}*/ 342 + 302 343 //########################################################################## 303 344 304 - QRtools::markTime('start'); 305 - 306 - 307 - 308 - 309 - //---- qrspec.php ----------------------------- 310 - 311 - 312 - 345 + 346 + 347 + 348 + //---- qrspec.php ----------------------------- 349 + 350 + 351 + 313 352 314 353 /* 315 354 * PHP QR Code encoder ··· 320 359 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 321 360 * 322 361 * PHP QR Code is distributed under LGPL 3 323 - * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 362 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 324 363 * 325 364 * The following data / specifications are taken from 326 365 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) ··· 343 382 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 344 383 */ 345 384 385 + /** Maximal Version no allowed by QR-Code spec */ 346 386 define('QRSPEC_VERSION_MAX', 40); 387 + /** Maximal Code size in pixels allowed by QR-Code spec */ 347 388 define('QRSPEC_WIDTH_MAX', 177); 348 389 349 390 define('QRCAP_WIDTH', 0); 350 391 define('QRCAP_WORDS', 1); 351 392 define('QRCAP_REMINDER', 2); 352 393 define('QRCAP_EC', 3); 394 + 395 + /** @addtogroup CoreGroup */ 396 + /** @{ */ 353 397 398 + /** QR-Code specification and Code Frame handling. 399 + Contains code specifications, calculates base frame, code structure 400 + and base properties 401 + */ 354 402 class QRspec { 355 403 404 + /** Array specifying properties of QR-Code "versions". 405 + Each so-called version has specified code area size and capacity. 406 + There are 40 versions, this table specifies for each of them four parameters: 407 + 408 + - Integer __QRCAP_WIDTH__ - size of code in pixels 409 + - Integer __QRCAP_WORDS__ - code capacity, in words 410 + - Integer __QRCAP_REMINDER__ - remainder words 411 + - Array of Integers __QRCAP_EC__ - RS correction code count for each of four ECC levels 412 + \hideinitializer 413 + */ 356 414 public static $capacity = array( 357 415 array( 0, 0, 0, array( 0, 0, 0, 0)), 358 416 array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 ··· 398 456 ); 399 457 400 458 //---------------------------------------------------------------------- 459 + /** Calculates data length for specified code configuration. 460 + @param Integer $version Code version 461 + @param Integer $level ECC level 462 + @returns Code data capacity 463 + */ 401 464 public static function getDataLength($version, $level) 402 465 { 403 466 return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level]; 404 467 } 405 468 406 469 //---------------------------------------------------------------------- 470 + /** Calculates count of Error Correction Codes for specified code configuration. 471 + @param Integer $version Code version 472 + @param Integer $level ECC level 473 + @returns ECC code count 474 + */ 407 475 public static function getECCLength($version, $level) 408 476 { 409 477 return self::$capacity[$version][QRCAP_EC][$level]; 410 478 } 411 479 412 480 //---------------------------------------------------------------------- 481 + /** Gets pixel width of code. 482 + @param Integer $version Code version 483 + @returns Code width, in pixels 484 + */ 413 485 public static function getWidth($version) 414 486 { 415 487 return self::$capacity[$version][QRCAP_WIDTH]; 416 488 } 417 489 418 490 //---------------------------------------------------------------------- 491 + /** Gets reminder chars length. 492 + @param Integer $version Code version 493 + @returns Reminder length 494 + */ 419 495 public static function getRemainder($version) 420 496 { 421 497 return self::$capacity[$version][QRCAP_REMINDER]; 422 498 } 423 499 424 500 //---------------------------------------------------------------------- 501 + /** Finds minimal code version capable of hosting specified data length. 502 + @param Integer $size amount of raw data 503 + @param Integer $level ECC level 504 + @returns code version capable of hosting specified amount of data at specified ECC level 505 + */ 425 506 public static function getMinimumVersion($size, $level) 426 507 { 427 508 ··· 435 516 } 436 517 437 518 //###################################################################### 438 - 519 + 520 + /** Length bits Table. 521 + \hideinitializer 522 + */ 439 523 public static $lengthTableBits = array( 440 524 array(10, 12, 14), 441 525 array( 9, 11, 13), ··· 485 569 } 486 570 487 571 // Error correction code ----------------------------------------------- 488 - // Table of the error correction code (Reed-Solomon block) 489 - // See Table 12-16 (pp.30-36), JIS X0510:2004. 572 + /** Table of the error correction code (Reed-Solomon block). 573 + @see Table 12-16 (pp.30-36), JIS X0510:2004. 574 + \hideinitializer 575 + */ 490 576 491 577 public static $eccTable = array( 492 578 array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), ··· 563 649 564 650 // Alignment pattern --------------------------------------------------- 565 651 566 - // Positions of alignment patterns. 567 - // This array includes only the second and the third position of the 568 - // alignment patterns. Rest of them can be calculated from the distance 569 - // between them. 652 + /** Positions of alignment patterns. 653 + This array includes only the second and the third position of the 654 + lignment patterns. Rest of them can be calculated from the distance 655 + between them. 570 656 571 - // See Table 1 in Appendix E (pp.71) of JIS X0510:2004. 657 + @see Table 1 in Appendix E (pp.71) of JIS X0510:2004. 658 + \hideinitializer 659 + */ 572 660 573 661 public static $alignmentPattern = array( 574 662 array( 0, 0), ··· 582 670 array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40 583 671 ); 584 672 585 - 586 - /** -------------------------------------------------------------------- 587 - * Put an alignment marker. 588 - * @param frame 589 - * @param width 590 - * @param ox,oy center coordinate of the pattern 591 - */ 673 + //---------------------------------------------------------------------- 674 + /** Puts an alignment marker. 675 + @param frame 676 + @param width 677 + @param ox,oy center coordinate of the pattern 678 + */ 592 679 public static function putAlignmentMarker(array &$frame, $ox, $oy) 593 680 { 594 681 $finder = array( ··· 603 690 $xStart = $ox-2; 604 691 605 692 for($y=0; $y<5; $y++) { 606 - QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]); 693 + self::set($frame, $xStart, $yStart+$y, $finder[$y]); 607 694 } 608 695 } 609 696 ··· 646 733 } 647 734 648 735 // Version information pattern ----------------------------------------- 649 - 650 - // Version information pattern (BCH coded). 651 - // See Table 1 in Appendix D (pp.68) of JIS X0510:2004. 736 + /** Version information pattern (BCH coded). 737 + size: [QRSPEC_VERSION_MAX - 6] 738 + @see Table 1 in Appendix D (pp.68) of JIS X0510:2004. 739 + \hideinitializer 740 + */ 652 741 653 - // size: [QRSPEC_VERSION_MAX - 6] 654 - 655 742 public static $versionPattern = array( 656 743 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, 657 744 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, ··· 669 756 return self::$versionPattern[$version -7]; 670 757 } 671 758 672 - // Format information -------------------------------------------------- 673 - // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib) 759 + //---------------------------------------------------------------------- 760 + /** Format information. 761 + @see calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib) 762 + \hideinitializer 763 + */ 674 764 675 765 public static $formatInfo = array( 676 766 array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), ··· 691 781 } 692 782 693 783 // Frame --------------------------------------------------------------- 694 - // Cache of initial frames. 695 - 784 + 785 + /** Cache of initial frames. */ 696 786 public static $frames = array(); 697 787 698 - /** -------------------------------------------------------------------- 699 - * Put a finder pattern. 700 - * @param frame 701 - * @param width 702 - * @param ox,oy upper-left coordinate of the pattern 703 - */ 788 + /** Put a finder pattern. 789 + @param frame 790 + @param width 791 + @param ox,oy upper-left coordinate of the pattern 792 + \hideinitializer 793 + */ 704 794 public static function putFinderPattern(&$frame, $ox, $oy) 705 795 { 706 796 $finder = array( ··· 714 804 ); 715 805 716 806 for($y=0; $y<7; $y++) { 717 - QRstr::set($frame, $ox, $oy+$y, $finder[$y]); 807 + self::set($frame, $ox, $oy+$y, $finder[$y]); 718 808 } 719 809 } 720 810 ··· 742 832 743 833 $setPattern = str_repeat("\xc0", 8); 744 834 745 - QRstr::set($frame, 0, 7, $setPattern); 746 - QRstr::set($frame, $width-8, 7, $setPattern); 747 - QRstr::set($frame, 0, $width - 8, $setPattern); 835 + self::set($frame, 0, 7, $setPattern); 836 + self::set($frame, $width-8, 7, $setPattern); 837 + self::set($frame, 0, $width - 8, $setPattern); 748 838 749 839 // Format info 750 840 $setPattern = str_repeat("\x84", 9); 751 - QRstr::set($frame, 0, 8, $setPattern); 752 - QRstr::set($frame, $width - 8, 8, $setPattern, 8); 841 + self::set($frame, 0, 8, $setPattern); 842 + self::set($frame, $width - 8, 8, $setPattern, 8); 753 843 754 844 $yOffset = $width - 8; 755 845 ··· 797 887 } 798 888 799 889 //---------------------------------------------------------------------- 890 + /** Dumps debug HTML of frame. 891 + @param Array $frame code frame 892 + @param Boolean $binary_mode in binary mode only contents is dumped, without styling 893 + */ 800 894 public static function debug($frame, $binary_mode = false) 801 895 { 802 896 if ($binary_mode) { ··· 806 900 $frameLine = join('&#9608;&#9608;', explode('1', $frameLine)); 807 901 } 808 902 809 - ?> 810 - <style> 811 - .m { background-color: white; } 812 - </style> 813 - <?php 903 + echo '<style> .m { background-color: white; } </style> '; 814 904 echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'; 815 905 echo join("<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $frame); 816 906 echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >'; ··· 818 908 } else { 819 909 820 910 foreach ($frame as &$frameLine) { 821 - $frameLine = join('<span class="m">&nbsp;</span>', explode("\xc0", $frameLine)); 822 - $frameLine = join('<span class="m">&#9618;</span>', explode("\xc1", $frameLine)); 823 - $frameLine = join('<span class="p">&nbsp;</span>', explode("\xa0", $frameLine)); 824 - $frameLine = join('<span class="p">&#9618;</span>', explode("\xa1", $frameLine)); 825 - $frameLine = join('<span class="s">&#9671;</span>', explode("\x84", $frameLine)); //format 0 826 - $frameLine = join('<span class="s">&#9670;</span>', explode("\x85", $frameLine)); //format 1 827 - $frameLine = join('<span class="x">&#9762;</span>', explode("\x81", $frameLine)); //special bit 828 - $frameLine = join('<span class="c">&nbsp;</span>', explode("\x90", $frameLine)); //clock 0 829 - $frameLine = join('<span class="c">&#9719;</span>', explode("\x91", $frameLine)); //clock 1 830 - $frameLine = join('<span class="f">&nbsp;</span>', explode("\x88", $frameLine)); //version 831 - $frameLine = join('<span class="f">&#9618;</span>', explode("\x89", $frameLine)); //version 832 - $frameLine = join('&#9830;', explode("\x01", $frameLine)); 833 - $frameLine = join('&#8901;', explode("\0", $frameLine)); 834 - } 835 911 836 - ?> 837 - <style> 838 - .p { background-color: yellow; } 839 - .m { background-color: #00FF00; } 840 - .s { background-color: #FF0000; } 841 - .c { background-color: aqua; } 842 - .x { background-color: pink; } 843 - .f { background-color: gold; } 844 - </style> 845 - <?php 846 - echo "<pre><tt>"; 912 + $frameLine = strtr($frameLine, array( 913 + "\xc0" => '<span class="m">&nbsp;</span>', //marker 0 914 + "\xc1" => '<span class="m">&#9618;</span>', //marker 1 915 + "\xa0" => '<span class="p">&nbsp;</span>', //submarker 0 916 + "\xa1" => '<span class="p">&#9618;</span>', //submarker 1 917 + "\x84" => '<span class="s">F</span>', //format 0 918 + "\x85" => '<span class="s">f</span>', //format 1 919 + "\x81" => '<span class="x">S</span>', //special bit 920 + "\x90" => '<span class="c">C</span>', //clock 0 921 + "\x91" => '<span class="c">c</span>', //clock 1 922 + "\x88" => '<span class="f">&nbsp;</span>', //version 0 923 + "\x89" => '<span class="f">&#9618;</span>', //version 1 924 + "\x03" => '1', // 1 925 + "\x02" => '0', // 0 926 + )); 927 + } 928 + 929 + echo '<style>'; 930 + echo ' .p { background-color: yellow; }'; 931 + echo ' .m { background-color: #00FF00; }'; 932 + echo ' .s { background-color: #FF0000; }'; 933 + echo ' .c { background-color: aqua; }'; 934 + echo ' .x { background-color: pink; }'; 935 + echo ' .f { background-color: gold; }'; 936 + echo '</style>'; 937 + 938 + echo "<tt>"; 847 939 echo join("<br/ >", $frame); 848 - echo "</tt></pre>"; 940 + echo "<br/>Legend:<br/>"; 941 + echo '1 - data 1<br/>'; 942 + echo '0 - data 0<br/>'; 943 + echo '<span class="m">&nbsp;</span> - marker bit 0<br/>'; 944 + echo '<span class="m">&#9618;</span> - marker bit 1<br/>'; 945 + echo '<span class="p">&nbsp;</span> - secondary marker bit 0<br/>'; 946 + echo '<span class="p">&#9618;</span> - secondary marker bit 1<br/>'; 947 + echo '<span class="s">F</span> - format bit 0<br/>'; 948 + echo '<span class="s">f</span> - format bit 1<br/>'; 949 + echo '<span class="x">S</span> - special bit<br/>'; 950 + echo '<span class="c">C</span> - clock bit 0<br/>'; 951 + echo '<span class="c">c</span> - clock bit 1<br/>'; 952 + echo '<span class="f">&nbsp;</span> - version bit 0<br/>'; 953 + echo '<span class="f">&#9618;</span> - version bit 1<br/>'; 954 + echo "</tt>"; 849 955 850 956 } 851 957 } 852 958 853 959 //---------------------------------------------------------------------- 960 + /** Serializes frame. 961 + Create compressed, serialized version of frame. 962 + @param Array $frame Code Frame 963 + @return String binary compresed Code Frame 964 + */ 854 965 public static function serial($frame) 855 966 { 856 967 return gzcompress(join("\n", $frame), 9); 857 968 } 858 969 859 970 //---------------------------------------------------------------------- 971 + /** Deserializes frame. 972 + Loads frame from serialized compressed binary 973 + @param String $code binary, GZipped, serialized frame 974 + @return Array Code Frame array 975 + */ 860 976 public static function unserial($code) 861 977 { 862 978 return explode("\n", gzuncompress($code)); ··· 891 1007 } 892 1008 893 1009 //---------------------------------------------------------------------- 1010 + /** Sets code frame with speciffied code. 1011 + @param Array $frame target frame (modified by reference) 1012 + @param Integer $x X-axis position of replacement 1013 + @param Integer $y Y-axis position of replacement 1014 + @param Byte $repl replacement string 1015 + @param Integer $replLen (optional) replacement string length, when __Integer__ > 1 subset of given $repl is used, when __false__ whole $repl is used 1016 + */ 1017 + public static function set(&$frame, $x, $y, $repl, $replLen = false) { 1018 + $frame[$y] = substr_replace($frame[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); 1019 + } 1020 + 1021 + //---------------------------------------------------------------------- 1022 + 1023 + /** @name Reed-Solomon related shorthand getters. 1024 + Syntax-sugar to access code speciffication by getter name, not by spec array field. 1025 + */ 1026 + /** @{*/ 894 1027 public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; } 895 1028 public static function rsBlockNum1($spec) { return $spec[0]; } 896 1029 public static function rsDataCodes1($spec) { return $spec[1]; } ··· 900 1033 public static function rsEccCodes2($spec) { return $spec[2]; } 901 1034 public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); } 902 1035 public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; } 903 - 904 - } 905 - 906 - 907 - 908 - //---- qrimage.php ----------------------------- 909 - 910 - 911 - 1036 + /** @}*/ 1037 + } 1038 + 1039 + /** @}*/ 1040 + 1041 + 1042 + 1043 + 1044 + 1045 + //---- qrimage.php ----------------------------- 1046 + 1047 + 1048 + 912 1049 913 1050 /* 914 1051 * PHP QR Code encoder ··· 916 1053 * Image output of code using GD2 917 1054 * 918 1055 * PHP QR Code is distributed under LGPL 3 919 - * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 1056 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 920 1057 * 921 1058 * This library is free software; you can redistribute it and/or 922 1059 * modify it under the terms of the GNU Lesser General Public ··· 935 1072 936 1073 define('QR_IMAGE', true); 937 1074 1075 + 1076 + /** @defgroup OutputGroup Standard API Output 1077 + Provide simple Raster & Vector output */ 1078 + 1079 + /** @addtogroup OutputGroup */ 1080 + /** @{ */ 1081 + 1082 + /** Image rendering helper. 1083 + Uses GD2 image to render QR Code into image file */ 938 1084 class QRimage { 939 1085 940 1086 //---------------------------------------------------------------------- 1087 + /** 1088 + Creates PNG image. 1089 + @param Array $frame frame containing code 1090 + @param String $filename (optional) output file name, if __false__ outputs to browser with required headers 1091 + @param Integer $pixelPerPoint (optional) pixel size, multiplier for each 'virtual' pixel 1092 + @param Integer $outerFrame (optional) code margin (silent zone) in 'virtual' pixels 1093 + @param Boolean $saveandprint (optional) if __true__ code is outputed to browser and saved to file, otherwise only saved to file. It is effective only if $outfile is specified. 1094 + */ 1095 + 941 1096 public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE) 942 1097 { 943 1098 $image = self::image($frame, $pixelPerPoint, $outerFrame); ··· 959 1114 } 960 1115 961 1116 //---------------------------------------------------------------------- 1117 + /** 1118 + Creates JPEG image. 1119 + @param Array $frame frame containing code 1120 + @param String $filename (optional) output file name, if __false__ outputs to browser with required headers 1121 + @param Integer $pixelPerPoint (optional) pixel size, multiplier for each 'virtual' pixel 1122 + @param Integer $outerFrame (optional) code margin (silent zone) in 'virtual' pixels 1123 + @param Integer $q (optional) JPEG compression level (__0__ .. __100__) 1124 + */ 1125 + 962 1126 public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85) 963 1127 { 964 1128 $image = self::image($frame, $pixelPerPoint, $outerFrame); ··· 974 1138 } 975 1139 976 1140 //---------------------------------------------------------------------- 977 - private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4) 1141 + /** 1142 + Creates generic GD2 image object 1143 + @param Array $frame frame containing code 1144 + @param Integer $pixelPerPoint (optional) pixel size, multiplier for each 'virtual' pixel 1145 + @param Integer $outerFrame (optional) code margin (silent zone) in 'virtual' pixels 1146 + @return __Resource__ GD2 image resource (remember to ImageDestroy it!) 1147 + */ 1148 + public static function image($frame, $pixelPerPoint = 4, $outerFrame = 4) 978 1149 { 979 1150 $h = count($frame); 980 1151 $w = strlen($frame[0]); ··· 1003 1174 1004 1175 return $target_image; 1005 1176 } 1006 - } 1007 - 1008 - 1009 - 1010 - //---- qrinput.php ----------------------------- 1011 - 1012 - 1013 - 1177 + } 1178 + 1179 + /** @} */ 1180 + 1181 + 1182 + 1183 + //---- qrinput.php ----------------------------- 1184 + 1185 + 1186 + 1014 1187 1015 1188 /* 1016 1189 * PHP QR Code encoder ··· 1021 1194 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 1022 1195 * 1023 1196 * PHP QR Code is distributed under LGPL 3 1024 - * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 1197 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 1025 1198 * 1026 1199 * This library is free software; you can redistribute it and/or 1027 1200 * modify it under the terms of the GNU Lesser General Public ··· 1038 1211 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1039 1212 */ 1040 1213 1041 - define('STRUCTURE_HEADER_BITS', 20); 1214 + define('STRUCTURE_HEADER_BITS', 20); 1042 1215 define('MAX_STRUCTURED_SYMBOLS', 16); 1216 + 1217 + /** @addtogroup CoreGroup */ 1218 + /** @{ */ 1043 1219 1044 1220 class QRinputItem { 1045 1221 ··· 1738 1914 } 1739 1915 } 1740 1916 1741 - 1742 - 1743 - 1744 - 1745 - 1746 - //---- qrbitstream.php ----------------------------- 1747 - 1748 - 1749 - 1917 + /** @}*/ 1918 + 1919 + 1920 + 1921 + //---- qrbitstream.php ----------------------------- 1922 + 1923 + 1924 + 1750 1925 1751 1926 /* 1752 1927 * PHP QR Code encoder ··· 1757 1932 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 1758 1933 * 1759 1934 * PHP QR Code is distributed under LGPL 3 1760 - * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 1935 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 1761 1936 * 1762 1937 * This library is free software; you can redistribute it and/or 1763 1938 * modify it under the terms of the GNU Lesser General Public ··· 1773 1948 * License along with this library; if not, write to the Free Software 1774 1949 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1775 1950 */ 1776 - 1951 + 1952 + /** @addtogroup CoreGroup */ 1953 + /** @{ */ 1954 + 1955 + /** 1956 + PHP bit stream. 1957 + Class implementing array of bits (= 1 or 0 ints). Allows to initialize and append 1958 + bits from given Integer or array of Bytes. 1959 + */ 1777 1960 class QRbitstream { 1778 1961 1962 + /** 1963 + Array containing bit data stream 1964 + */ 1779 1965 public $data = array(); 1780 1966 1781 1967 //---------------------------------------------------------------------- 1968 + /** 1969 + @return Integer size of byte stream 1970 + */ 1782 1971 public function size() 1783 1972 { 1784 1973 return count($this->data); 1785 1974 } 1786 1975 1787 1976 //---------------------------------------------------------------------- 1977 + /** 1978 + Allocates bit stream, fills bit data stream with 0's. 1979 + This operation is __destructive__, will replace orginal stream contents! 1980 + @param Integer $setLength desired target stream size 1981 + @return Integer 0 on success, other on failure 1982 + */ 1788 1983 public function allocate($setLength) 1789 1984 { 1790 1985 $this->data = array_fill(0, $setLength, 0); ··· 1792 1987 } 1793 1988 1794 1989 //---------------------------------------------------------------------- 1990 + /** 1991 + Creates new bit stream from given Integer number. 1992 + @param Integer $bits bit count 1993 + @param Integer $num integer to convert 1994 + @return QRbitstream bit stream object containing first $bits bits from $num in order from LSB to MSB 1995 + */ 1795 1996 public static function newFromNum($bits, $num) 1796 1997 { 1797 1998 $bstream = new QRbitstream(); ··· 1811 2012 } 1812 2013 1813 2014 //---------------------------------------------------------------------- 2015 + /** 2016 + Creates new bit stream from given byte array. 2017 + @param Integer $size size of array 2018 + @param Array $data array ob bytes 2019 + @return QRbitstream bit stream object containing bit contents of given bytes array 2020 + */ 1814 2021 public static function newFromBytes($size, $data) 1815 2022 { 1816 2023 $bstream = new QRbitstream(); ··· 1834 2041 } 1835 2042 1836 2043 //---------------------------------------------------------------------- 2044 + /** 2045 + Appends given bit stream at end of this stream. 2046 + @param QRbitstream $arg bit stream to be appended 2047 + @return Integer status of append operation, 0 when success, -1 when $arg is null 2048 + */ 1837 2049 public function append(QRbitstream $arg) 1838 2050 { 1839 2051 if (is_null($arg)) { ··· 1855 2067 } 1856 2068 1857 2069 //---------------------------------------------------------------------- 2070 + /** 2071 + Appends bit stream cteated from given Integer number at end of current stream. 2072 + @param Integer $bits bit count 2073 + @param Integer $num integer to convert 2074 + @return Integer status of append operation, status of append operation, 0 when success, -1 otherwise 2075 + */ 1858 2076 public function appendNum($bits, $num) 1859 2077 { 1860 2078 if ($bits == 0) ··· 1872 2090 } 1873 2091 1874 2092 //---------------------------------------------------------------------- 2093 + /** 2094 + Appends bit stream created from from given byte array at end of current stream. 2095 + @param Integer $size size of array 2096 + @param Array $data array ob bytes 2097 + @return Integer status of append operation, status of append operation, 0 when success, -1 otherwise 2098 + */ 1875 2099 public function appendBytes($size, $data) 1876 2100 { 1877 2101 if ($size == 0) ··· 1889 2113 } 1890 2114 1891 2115 //---------------------------------------------------------------------- 2116 + /** 2117 + Converts current bit stream into byte array. 2118 + @returns Array array of bytes 2119 + */ 1892 2120 public function toByte() 1893 2121 { 1894 2122 ··· 1927 2155 } 1928 2156 1929 2157 } 1930 - 1931 - 1932 - 1933 - 1934 - //---- qrsplit.php ----------------------------- 1935 - 1936 - 1937 - 2158 + 2159 + /** @}*/ 2160 + 2161 + 2162 + 2163 + //---- qrsplit.php ----------------------------- 2164 + 2165 + 2166 + 1938 2167 1939 2168 /* 1940 2169 * PHP QR Code encoder ··· 1945 2174 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 1946 2175 * 1947 2176 * PHP QR Code is distributed under LGPL 3 1948 - * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 2177 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 1949 2178 * 1950 2179 * The following data / specifications are taken from 1951 2180 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) ··· 1967 2196 * License along with this library; if not, write to the Free Software 1968 2197 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1969 2198 */ 2199 + 2200 + /** @addtogroup CoreGroup */ 2201 + /** @{ */ 2202 + 2203 + /** Input stream splitter. */ 1970 2204 class QRsplit { 1971 2205 1972 2206 public $dataStr = ''; ··· 2245 2479 2246 2480 return $split->splitString(); 2247 2481 } 2248 - } 2249 - 2250 - 2251 - 2252 - //---- qrrscode.php ----------------------------- 2253 - 2254 - 2255 - 2482 + } 2483 + 2484 + /** @} */ 2485 + 2486 + 2487 + 2488 + //---- qrrscode.php ----------------------------- 2489 + 2490 + 2491 + 2256 2492 2257 2493 /* 2258 2494 * PHP QR Code encoder ··· 2266 2502 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 2267 2503 * 2268 2504 * PHP QR Code is distributed under LGPL 3 2269 - * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 2505 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 2270 2506 * 2271 2507 * This library is free software; you can redistribute it and/or 2272 2508 * modify it under the terms of the GNU Lesser General Public ··· 2283 2519 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 2284 2520 */ 2285 2521 2522 + /** @addtogroup CoreGroup */ 2523 + /** @{ */ 2524 + 2525 + /** Reed-Solomon encoder item */ 2286 2526 class QRrsItem { 2287 2527 2288 - public $mm; // Bits per symbol 2289 - public $nn; // Symbols per block (= (1<<mm)-1) 2290 - public $alpha_to = array(); // log lookup table 2291 - public $index_of = array(); // Antilog lookup table 2292 - public $genpoly = array(); // Generator polynomial 2293 - public $nroots; // Number of generator roots = number of parity symbols 2294 - public $fcr; // First consecutive root, index form 2295 - public $prim; // Primitive element, index form 2296 - public $iprim; // prim-th root of 1, index form 2297 - public $pad; // Padding bytes in shortened block 2298 - public $gfpoly; 2528 + /** Bits per symbol */ 2529 + public $mm; 2530 + /** Symbols per block (= (1<<mm)-1) */ 2531 + public $nn; 2532 + /** Log lookup table */ 2533 + public $alpha_to = array(); 2534 + /** Antilog lookup table */ 2535 + public $index_of = array(); 2536 + /** Generator polynomial */ 2537 + public $genpoly = array(); 2538 + /** Number of generator roots = number of parity symbols */ 2539 + public $nroots; 2540 + /** First consecutive root, index form */ 2541 + public $fcr; 2542 + /** Primitive element, index form */ 2543 + public $prim; 2544 + /** Prim-th root of 1, index form */ 2545 + public $iprim; 2546 + /** Padding bytes in shortened block */ 2547 + public $pad; 2548 + /** Galois Field Polynomial */ 2549 + public $gfpoly; 2299 2550 2300 2551 //---------------------------------------------------------------------- 2301 - public function modnn($x) 2552 + /** Modulo function in defined Field 2553 + @param Integer $x number to be modulo-mapped 2554 + */ 2555 + public function modnn($x) 2302 2556 { 2303 2557 while ($x >= $this->nn) { 2304 2558 $x -= $this->nn; ··· 2309 2563 } 2310 2564 2311 2565 //---------------------------------------------------------------------- 2312 - public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) 2566 + /** Encoder initialisation 2567 + @param Integer $symsize symbol size, bit count (1..8) 2568 + @param Integer $gfpoly Galois Field Polynomial 2569 + @param Integer $fcr First consecutive root 2570 + @param Integer $prim Primitive element 2571 + @param Integer $nroots Number of generator roots = number of parity symbols 2572 + @param Integer $pad Padding bytes in shortened block 2573 + */ 2574 + public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) 2313 2575 { 2314 2576 // Common code for intializing a Reed-Solomon control block (char or int symbols) 2315 2577 // Copyright 2004 Phil Karn, KA9Q ··· 2395 2657 } 2396 2658 2397 2659 //---------------------------------------------------------------------- 2660 + /** Appends char into encoder 2661 + @param String input 2662 + @param Array parity table 2663 + */ 2398 2664 public function encode_rs_char($data, &$parity) 2399 2665 { 2400 2666 $MM =& $this->mm; ··· 2438 2704 } 2439 2705 2440 2706 //########################################################################## 2441 - 2707 + /** Reed-Solomon encoder */ 2442 2708 class QRrs { 2443 2709 2710 + /** Encoder items array */ 2444 2711 public static $items = array(); 2445 2712 2446 2713 //---------------------------------------------------------------------- 2714 + /** Encoder initialisation 2715 + @param Integer $symsize symbol size, bit count (1..8) 2716 + @param Integer $gfpoly Galois Field Polynomial 2717 + @param Integer $fcr First consecutive root 2718 + @param Integer $prim Primitive element 2719 + @param Integer $nroots Number of generator roots = number of parity symbols 2720 + @param Integer $pad Padding bytes in shortened block 2721 + */ 2447 2722 public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) 2448 2723 { 2449 2724 foreach(self::$items as $rs) { ··· 2462 2737 2463 2738 return $rs; 2464 2739 } 2465 - } 2466 - 2467 - 2468 - 2469 - //---- qrmask.php ----------------------------- 2470 - 2471 - 2472 - 2740 + } 2741 + 2742 + /** @}*/ 2743 + 2744 + 2745 + 2746 + //---- qrmask.php ----------------------------- 2747 + 2748 + 2749 + 2473 2750 2474 2751 /* 2475 2752 * PHP QR Code encoder ··· 2480 2757 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 2481 2758 * 2482 2759 * PHP QR Code is distributed under LGPL 3 2483 - * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 2760 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 2484 2761 * 2485 2762 * This library is free software; you can redistribute it and/or 2486 2763 * modify it under the terms of the GNU Lesser General Public ··· 2497 2774 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 2498 2775 */ 2499 2776 2777 + 2778 + 2500 2779 define('N1', 3); 2501 2780 define('N2', 3); 2502 2781 define('N3', 40); 2503 2782 define('N4', 10); 2504 2783 2784 + /** @addtogroup CoreGroup */ 2785 + /** @{ */ 2786 + 2505 2787 class QRmask { 2506 2788 2507 2789 public $runLength = array(); ··· 2643 2925 $b += (int)(ord($d[$y][$x]) & 1); 2644 2926 } 2645 2927 } 2646 - 2928 + 2647 2929 return $b; 2648 2930 } 2649 2931 ··· 2798 3080 2799 3081 //---------------------------------------------------------------------- 2800 3082 } 2801 - 2802 - 2803 - 2804 - 2805 - //---- qrencode.php ----------------------------- 2806 - 2807 - 2808 - 3083 + 3084 + /** @}*/ 3085 + 3086 + 3087 + 3088 + //---- qrarea.php ----------------------------- 3089 + 3090 + 3091 + 3092 + 3093 + /* 3094 + * PHP QR Code encoder 3095 + * 3096 + * Area finding for SVG and CANVAS output 3097 + * 3098 + * Based on libqrencode C library distributed under LGPL 2.1 3099 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 3100 + * 3101 + * PHP QR Code is distributed under LGPL 3 3102 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 3103 + * 3104 + * This library is free software; you can redistribute it and/or 3105 + * modify it under the terms of the GNU Lesser General Public 3106 + * License as published by the Free Software Foundation; either 3107 + * version 3 of the License, or any later version. 3108 + * 3109 + * This library is distributed in the hope that it will be useful, 3110 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 3111 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 3112 + * Lesser General Public License for more details. 3113 + * 3114 + * You should have received a copy of the GNU Lesser General Public 3115 + * License along with this library; if not, write to the Free Software 3116 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 3117 + */ 3118 + 3119 + // N 3120 + // W E 3121 + // S 3122 + 3123 + define('QR_AREA_N', 0); 3124 + define('QR_AREA_E', 1); 3125 + define('QR_AREA_S', 2); 3126 + define('QR_AREA_W', 3); 3127 + 3128 + define('QR_AREA_X', 0); 3129 + define('QR_AREA_Y', 1); 3130 + 3131 + define('QR_AREA_TRACKER', 0); 3132 + define('QR_AREA_PATH', 1); 3133 + define('QR_AREA_POINT', 2); 3134 + define('QR_AREA_RECT', 3); 3135 + define('QR_AREA_LSHAPE', 4); 3136 + 3137 + /** @addtogroup OutputGroup */ 3138 + /** @{ */ 3139 + 3140 + class QRareaGroup { 3141 + public $total = 0; 3142 + public $vertical = false; 3143 + public $horizontal = false; 3144 + public $points = array(); 3145 + public $id = 0; 3146 + public $paths = array(); 3147 + 3148 + //---------------------------------------------------------------------- 3149 + public function __construct($selfId, $sx, $sy) 3150 + { 3151 + $this->total = 1; 3152 + $this->points = array(array($sx,$sy,false)); 3153 + $this->id = $selfId; 3154 + } 3155 + 3156 + } 3157 + 3158 + //########################################################################## 3159 + 3160 + class QRarea { 3161 + 3162 + public $width = 0; 3163 + private $tab = array(); 3164 + private $tab_edges = array(); 3165 + private $groups = array(); 3166 + private $curr_group = 0; 3167 + public $paths = array(); 3168 + 3169 + 3170 + //---------------------------------------------------------------------- 3171 + public function __construct($source_tab) 3172 + { 3173 + $py = 0; 3174 + $this->width = count($source_tab); 3175 + $this->tab = array(); 3176 + $this->tab_edges = array(); 3177 + $this->paths = array(); 3178 + 3179 + foreach ($source_tab as $line) { 3180 + $arr = array(); 3181 + $arr_edge = array(); 3182 + $px=0; 3183 + 3184 + foreach (str_split($line) as $item) { 3185 + 3186 + if ($py<7 && $px<7) 3187 + $item = 0; 3188 + 3189 + if ($py<7 && $px>=($this->width-7)) 3190 + $item = 0; 3191 + 3192 + if ($py>=($this->width-7) && $px<7) 3193 + $item = 0; 3194 + 3195 + $arr[] = (int)$item; 3196 + $arr_edge[] = array(false, false, false, false); 3197 + 3198 + $px++; 3199 + } 3200 + 3201 + $this->tab[] = $arr; 3202 + $this->tab_edges[] = $arr_edge; 3203 + $py++; 3204 + } 3205 + 3206 + $this->paths[] = array(QR_AREA_TRACKER, 0,0); 3207 + $this->paths[] = array(QR_AREA_TRACKER, 0,($this->width-7)); 3208 + $this->paths[] = array(QR_AREA_TRACKER, ($this->width-7),0); 3209 + 3210 + $this->groups = array(); 3211 + $this->curr_group = 1; 3212 + } 3213 + 3214 + //---------------------------------------------------------------------- 3215 + public function getGroups() 3216 + { 3217 + return $this->groups; 3218 + } 3219 + 3220 + //---------------------------------------------------------------------- 3221 + public function getPaths() 3222 + { 3223 + return $this->paths; 3224 + } 3225 + 3226 + //---------------------------------------------------------------------- 3227 + public function getWidth() 3228 + { 3229 + return $this->width; 3230 + } 3231 + 3232 + //---------------------------------------------------------------------- 3233 + public function dumpTab() 3234 + { 3235 + echo "<style>"; 3236 + echo "td { height: 2.5em; color: black; font-size: 8px; 3237 + border-top: 1px solid silver; border-left: 1px solid silver }"; 3238 + echo "table { border-bottom: 1px solid silver; border-right: 1px solid silver }"; 3239 + echo "</style>"; 3240 + echo "<table border=0 cellpadding=0 cellspacing=0>"; 3241 + 3242 + $colorTab = array(); 3243 + 3244 + foreach($this->tab as $line) { 3245 + foreach($line as $item) { 3246 + if (!isset($colorTab[$item])) { 3247 + $colorTab[$item] = 'hsl('.mt_rand(0, 360).', '.floor((mt_rand(0, 25))+75).'%, 50%)'; 3248 + } 3249 + } 3250 + } 3251 + 3252 + foreach($this->tab as $line) { 3253 + echo "<tr>"; 3254 + foreach($line as $item) { 3255 + if ($item == 0) { 3256 + echo "<td>&nbsp;</td>"; 3257 + } else { 3258 + echo "<td style='text-align:center;width: 4em;background:".$colorTab[$item]."'>".$item."</td>"; 3259 + } 3260 + } 3261 + echo "</tr>"; 3262 + } 3263 + echo "</table>"; 3264 + } 3265 + 3266 + //---------------------------------------------------------------------- 3267 + public function dumpEdges() 3268 + { 3269 + $style_off = '1px dotted silver;'; 3270 + $style_on = '3px solid red;'; 3271 + 3272 + $colorAlloc = array(); 3273 + 3274 + echo "<table border='0'>"; 3275 + $py = 0; 3276 + foreach($this->tab_edges as $line) { 3277 + $px = 0; 3278 + echo "<tr>"; 3279 + foreach($line as $item) { 3280 + 3281 + $styles = 'border-top:'; 3282 + if ($item[QR_AREA_N]) 3283 + $styles .= $style_on; 3284 + else $styles .= $style_off; 3285 + 3286 + $styles .= 'border-bottom:'; 3287 + if ($item[QR_AREA_S]) 3288 + $styles .= $style_on; 3289 + else $styles .= $style_off; 3290 + 3291 + $styles .= 'border-right:'; 3292 + if ($item[QR_AREA_E]) 3293 + $styles .= $style_on; 3294 + else $styles .= $style_off; 3295 + 3296 + $styles .= 'border-left:'; 3297 + if ($item[QR_AREA_W]) 3298 + $styles .= $style_on; 3299 + else $styles .= $style_off; 3300 + 3301 + $color = ''; 3302 + $grp = $this->tab[$py][$px]; 3303 + 3304 + if ($grp>0) { 3305 + if (!isset($colorAlloc[$grp])) { 3306 + $colorAlloc[$grp] = 'hsl('.mt_rand(0, 360).', '.floor((mt_rand(0, 25))+75).'%, 50%)'; 3307 + } 3308 + 3309 + $color = 'background:'.$colorAlloc[$grp]; 3310 + } 3311 + 3312 + if ($grp == 0) 3313 + $grp = '&nbsp;'; 3314 + 3315 + echo "<td style='text-align:center;width:1.5em;".$styles.$color."'>".$grp."</td>"; 3316 + $px++; 3317 + } 3318 + echo "</tr>"; 3319 + $py++; 3320 + } 3321 + echo "</table>"; 3322 + } 3323 + 3324 + //---------------------------------------------------------------------- 3325 + private static function rle(&$stringData) 3326 + { 3327 + $outArray = array(); 3328 + $symbolArray = str_split($stringData); 3329 + $last = ''; 3330 + $run = 1; 3331 + 3332 + while (count($symbolArray) > 0) { 3333 + $symbol = array_shift($symbolArray); 3334 + 3335 + if ($symbol != $last) { 3336 + if ($run > 1) 3337 + $outArray[] = $run; 3338 + 3339 + if ($last != '') 3340 + $outArray[] = $last; 3341 + 3342 + $run = 1; 3343 + $last = $symbol; 3344 + } else { 3345 + $run++; 3346 + } 3347 + } 3348 + 3349 + if ($run > 1) 3350 + $outArray[] = $run; 3351 + 3352 + $outArray[] = $last; 3353 + 3354 + $stringData = $outArray; 3355 + } 3356 + 3357 + 3358 + //---------------------------------------------------------------------- 3359 + private function getAt($posx, $posy) 3360 + { 3361 + if (($posx<0)||($posy<0)||($posx>=$this->width)||($posy>=$this->width)) 3362 + return 0; 3363 + 3364 + return $this->tab[$posy][$posx]; 3365 + } 3366 + 3367 + //---------------------------------------------------------------------- 3368 + private function getOnElem($elem, $deltax = 0, $deltay = 0) 3369 + { 3370 + $posx = $elem[0]+$deltax; 3371 + $posy = $elem[1]+$deltay; 3372 + 3373 + if (($posx<0)||($posy<0)||($posx>=$this->width)||($posy>=$this->width)) 3374 + return 0; 3375 + 3376 + return $this->tab[$posy][$posx]; 3377 + } 3378 + 3379 + //---------------------------------------------------------------------- 3380 + private function addGroupElement($groupId, $h, $v, $sx, $sy) 3381 + { 3382 + $this->groups[$groupId]->total++; 3383 + if ($h) 3384 + $this->groups[$groupId]->horizontal = true; 3385 + if ($v) 3386 + $this->groups[$groupId]->vertical = true; 3387 + $this->groups[$groupId]->points[] = array($sx, $sy, false); 3388 + } 3389 + 3390 + //---------------------------------------------------------------------- 3391 + public function detectGroups() 3392 + { 3393 + for ($sy = 0; $sy < $this->width; $sy++) { 3394 + for ($sx = 0; $sx < $this->width; $sx++) { 3395 + 3396 + if ($this->tab[$sy][$sx] == 1) { // non-allocated 3397 + 3398 + $gid_left = 0; 3399 + $gid_top = 0; 3400 + 3401 + $grouped = false; 3402 + 3403 + if ($sx>0) { 3404 + 3405 + $gid_left = $this->tab[$sy][$sx-1]; // previous on left 3406 + 3407 + if ($gid_left > 1) { // if already in group 3408 + $this->tab[$sy][$sx] = $gid_left; 3409 + $grouped = true; 3410 + $this->addGroupElement($gid_left, true, false, $sx, $sy); 3411 + } 3412 + } 3413 + 3414 + if ($sy > 0) { 3415 + 3416 + $gid_top = $this->tab[$sy-1][$sx]; // previous on top 3417 + 3418 + if ($gid_top > 1) { //if in group 3419 + if (!$grouped) { // and not grouped 3420 + 3421 + $this->tab[$sy][$sx] = $gid_top; 3422 + $grouped = true; 3423 + 3424 + $this->addGroupElement($gid_top, false, true, $sx, $sy); 3425 + 3426 + } else if($gid_top != $gid_left) { // was in left group 3427 + 3428 + $grouped = true; 3429 + 3430 + $this->groups[$gid_top]->vertical = true; 3431 + $this->groups[$gid_top]->horizontal = true; 3432 + 3433 + $this->groups[$gid_top]->total = $this->groups[$gid_top]->total + $this->groups[$gid_left]->total; 3434 + 3435 + foreach($this->groups[$gid_left]->points as $elem) 3436 + $this->tab[$elem[1]][$elem[0]] = $gid_top; 3437 + 3438 + $this->groups[$gid_top]->points = array_values(array_merge($this->groups[$gid_top]->points, $this->groups[$gid_left]->points)); 3439 + unset($this->groups[$gid_left]); 3440 + 3441 + //refarb group 3442 + } 3443 + } 3444 + } 3445 + 3446 + if (!$grouped) { 3447 + $this->curr_group++; 3448 + $this->tab[$sy][$sx] = $this->curr_group; 3449 + $this->groups[$this->curr_group] = new QRareaGroup($this->curr_group, $sx, $sy); 3450 + } 3451 + 3452 + } 3453 + } 3454 + } 3455 + } 3456 + 3457 + //---------------------------------------------------------------------- 3458 + private function detectSquare($group) 3459 + { 3460 + $max_x = 0; 3461 + $max_y = 0; 3462 + $min_x = $this->width; 3463 + $min_y = $this->width; 3464 + 3465 + foreach($group->points as $elem) { 3466 + $min_x = min($min_x, $elem[QR_AREA_X]); 3467 + $max_x = max($max_x, $elem[QR_AREA_X]); 3468 + $min_y = min($min_y, $elem[QR_AREA_Y]); 3469 + $max_y = max($max_y, $elem[QR_AREA_Y]); 3470 + } 3471 + 3472 + return array($min_x, $min_y, $max_x+1, $max_y+1); 3473 + } 3474 + 3475 + //---------------------------------------------------------------------- 3476 + public function detectAreas() 3477 + { 3478 + $squares = array(); 3479 + $points = array(); 3480 + $lshapes = array(); 3481 + 3482 + foreach ($this->groups as $groupId=>&$group) { 3483 + if ($group->total > 3) { 3484 + 3485 + if ((!$group->vertical)||(!$group->horizontal)) { 3486 + 3487 + $squareCoord = $this->detectSquare($group); 3488 + array_unshift($squareCoord, QR_AREA_RECT); 3489 + 3490 + $this->paths[] = $squareCoord; 3491 + 3492 + } else { 3493 + 3494 + $this->detectPaths($group); 3495 + unset($group->points); 3496 + 3497 + foreach($group->paths as &$path) 3498 + self::rle($path[2]); 3499 + 3500 + $this->paths[] = array(QR_AREA_PATH, $group->paths); 3501 + } 3502 + } else if (($group->total == 3)&&($group->vertical)&&($group->horizontal)) { 3503 + $squareCoord = $this->detectSquare($group); 3504 + $variant = 0; 3505 + 3506 + if ($this->getOnElem($squareCoord, 0, 0) != $group->id) 3507 + $variant = 0; 3508 + 3509 + if ($this->getOnElem($squareCoord, 1, 0) != $group->id) 3510 + $variant = 1; 3511 + 3512 + if ($this->getOnElem($squareCoord, 0, 1) != $group->id) 3513 + $variant = 2; 3514 + 3515 + if ($this->getOnElem($squareCoord, 1, 1) != $group->id) 3516 + $variant = 3; 3517 + 3518 + $lshapes[] = $squareCoord[QR_AREA_X]; 3519 + $lshapes[] = $squareCoord[QR_AREA_Y]; 3520 + $lshapes[] = $variant; 3521 + 3522 + } else if ($group->total >= 2) { 3523 + $squareCoord = $this->detectSquare($group); 3524 + $squares = array_merge($squares, $squareCoord); 3525 + } else if ($group->total == 1) { 3526 + $points[] = $group->points[0][0]; 3527 + $points[] = $group->points[0][1]; 3528 + } 3529 + } 3530 + 3531 + if (count($points) > 0) { 3532 + array_unshift($points, QR_AREA_POINT); 3533 + $this->paths[] = $points; 3534 + } 3535 + 3536 + if (count($squares) > 0) { 3537 + array_unshift($squares, QR_AREA_RECT); 3538 + $this->paths[] = $squares; 3539 + } 3540 + 3541 + if (count($lshapes) > 0) { 3542 + array_unshift($lshapes, QR_AREA_LSHAPE); 3543 + $this->paths[] = $lshapes; 3544 + } 3545 + } 3546 + 3547 + //---------------------------------------------------------------------- 3548 + private function reserveEdgeOnElem($elem, $edgeNo) 3549 + { 3550 + $this->tab_edges[$elem[QR_AREA_Y]][$elem[QR_AREA_X]][$edgeNo] = true; 3551 + } 3552 + 3553 + //---------------------------------------------------------------------- 3554 + private function reserveEdge($px, $py, $edgeNo) 3555 + { 3556 + $this->tab_edges[$py][$px][$edgeNo] = true; 3557 + } 3558 + 3559 + //---------------------------------------------------------------------- 3560 + private function markAdjacentEdges($group) 3561 + { 3562 + foreach($group->points as $elem) { 3563 + if ($this->getOnElem($elem, -1, 0) == $group->id) 3564 + $this->reserveEdgeOnElem($elem, QR_AREA_W); 3565 + 3566 + if ($this->getOnElem($elem, +1, 0) == $group->id) 3567 + $this->reserveEdgeOnElem($elem, QR_AREA_E); 3568 + 3569 + if ($this->getOnElem($elem, 0, -1) == $group->id) 3570 + $this->reserveEdgeOnElem($elem, QR_AREA_N); 3571 + 3572 + if ($this->getOnElem($elem, 0, +1) == $group->id) 3573 + $this->reserveEdgeOnElem($elem, QR_AREA_S); 3574 + } 3575 + } 3576 + 3577 + //---------------------------------------------------------------------- 3578 + private function detectPaths(&$group) 3579 + { 3580 + $this->markAdjacentEdges($group); 3581 + 3582 + $elem = $group->points[0]; 3583 + $waylist = $this->findPath($group, $elem[QR_AREA_X], $elem[QR_AREA_Y]); 3584 + $group->paths[] = array($elem[QR_AREA_X], $elem[QR_AREA_Y], $waylist); 3585 + 3586 + $tab = array(); 3587 + foreach($group->points as $elem) { 3588 + 3589 + $edgeTab = $this->tab_edges[$elem[QR_AREA_Y]][$elem[QR_AREA_X]]; 3590 + 3591 + if (!( $edgeTab[QR_AREA_N] 3592 + && $edgeTab[QR_AREA_E] 3593 + && $edgeTab[QR_AREA_S] 3594 + && $edgeTab[QR_AREA_W])) { 3595 + 3596 + if (!$edgeTab[QR_AREA_S]) { 3597 + 3598 + $waylistw = $this->findPath($group, $elem[QR_AREA_X], $elem[QR_AREA_Y]+1); 3599 + $group->paths[] = array($elem[QR_AREA_X], $elem[QR_AREA_Y]+1, $waylistw); 3600 + } 3601 + } 3602 + } 3603 + 3604 + } 3605 + 3606 + //---------------------------------------------------------------------- 3607 + private function findPath($group, $sx, $sy) 3608 + { 3609 + $px = $sx; 3610 + $py = $sy; 3611 + 3612 + $waylist = ''; 3613 + $dir = ''; 3614 + $lastdir = ''; 3615 + 3616 + $moves = array( 3617 + // magic :) 3618 + 0=>'', 1=>'L', 2=>'T', 3=>'L', 4=>'B', 5=>'B', 6=>'B,T', 7=>'B' 3619 + ,8=>'R', 9=>'R,L', 10=>'T', 11=>'L',12=>'R',13=>'R',14=>'T',15=>'' 3620 + ); 3621 + 3622 + do 3623 + { 3624 + $Q = ($this->getAt($px-1, $py-1) == $group->id)?1:0; 3625 + $Q += ($this->getAt($px, $py-1) == $group->id)?2:0; 3626 + $Q += ($this->getAt($px-1, $py) == $group->id)?4:0; 3627 + $Q += ($this->getAt($px, $py) == $group->id)?8:0; 3628 + 3629 + if ($moves[$Q] == '') 3630 + throw new Exception('It should NEVER happened!'); 3631 + 3632 + $move_expl = explode(',', $moves[$Q]); 3633 + $have_way = false; 3634 + 3635 + $dir = ''; 3636 + 3637 + while ((count($move_expl) > 0)&&($have_way == false)) { 3638 + $way = array_shift($move_expl); 3639 + 3640 + if (($have_way==false)&&($way=='R')&&($this->tab_edges[$py][$px][QR_AREA_N]==false)) { 3641 + $have_way = true; 3642 + $dir = $way; 3643 + $this->reserveEdge($px, $py, QR_AREA_N); 3644 + $px++; 3645 + } 3646 + 3647 + if (($have_way==false)&&($way=='B')&&($this->tab_edges[$py][$px-1][QR_AREA_E]==false)) { 3648 + $have_way = true; 3649 + $dir = $way; 3650 + $this->reserveEdge($px-1, $py, QR_AREA_E); 3651 + $py++; 3652 + } 3653 + 3654 + if (($have_way==false)&&($way=='L')&&($this->tab_edges[$py-1][$px-1][QR_AREA_S]==false)) { 3655 + $have_way = true; 3656 + $dir = $way; 3657 + $this->reserveEdge($px-1, $py-1, QR_AREA_S); 3658 + $px--; 3659 + } 3660 + 3661 + if (($have_way==false)&&($way=='T')&&($this->tab_edges[$py-1][$px][QR_AREA_W]==false)) { 3662 + $have_way = true; 3663 + $dir = $way; 3664 + $this->reserveEdge($px, $py-1, QR_AREA_W); 3665 + $py--; 3666 + } 3667 + } 3668 + 3669 + $waylist .= $dir; 3670 + 3671 + } while (!(($px==$sx)&&($py==$sy))); 3672 + 3673 + return $waylist; 3674 + } 3675 + } 3676 + 3677 + /** @} */ 3678 + 3679 + 3680 + 3681 + //---- qrcanvas.php ----------------------------- 3682 + 3683 + 3684 + 3685 + 3686 + /* 3687 + * PHP QR Code encoder 3688 + * 3689 + * CANVAS output 3690 + * 3691 + * Based on libqrencode C library distributed under LGPL 2.1 3692 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 3693 + * 3694 + * PHP QR Code is distributed under LGPL 3 3695 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 3696 + * 3697 + * This library is free software; you can redistribute it and/or 3698 + * modify it under the terms of the GNU Lesser General Public 3699 + * License as published by the Free Software Foundation; either 3700 + * version 3 of the License, or any later version. 3701 + * 3702 + * This library is distributed in the hope that it will be useful, 3703 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 3704 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 3705 + * Lesser General Public License for more details. 3706 + * 3707 + * You should have received a copy of the GNU Lesser General Public 3708 + * License along with this library; if not, write to the Free Software 3709 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 3710 + */ 3711 + 3712 + /** @addtogroup OutputGroup */ 3713 + /** @{ */ 3714 + 3715 + class QRcanvasOutput extends QRarea { 3716 + 3717 + public function __construct($source_tab) 3718 + { 3719 + parent::__construct($source_tab); 3720 + } 3721 + 3722 + //---------------------------------------------------------------------- 3723 + public static function encodeNum($num) 3724 + { 3725 + $addTab = array(0=>'', 1=>'z', 2=>'Z', 3=>'+'); 3726 + $map = '0123456789abcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXY'; 3727 + $mapPos = $num % 60; 3728 + $mapAdd = (int)($num / 60); 3729 + 3730 + return $addTab[$mapAdd].$map[$mapPos]; 3731 + } 3732 + 3733 + //---------------------------------------------------------------------- 3734 + public static function compact_path(&$pathTab) 3735 + { 3736 + if (count($pathTab) == 0) { 3737 + $pathTab = ''; 3738 + } else { 3739 + $pathTab = count($pathTab).','.join(',', $pathTab); 3740 + } 3741 + } 3742 + 3743 + //---------------------------------------------------------------------- 3744 + public static function compact_points(&$pointsTab) 3745 + { 3746 + if (count($pointsTab) == 0) { 3747 + $pointsTab = ''; 3748 + } else { 3749 + $compacted = ''; 3750 + foreach ($pointsTab as $point) 3751 + $compacted .= self::encodeNum($point); 3752 + $pointsTab = $compacted; 3753 + } 3754 + } 3755 + 3756 + //---------------------------------------------------------------------- 3757 + public static function compactCanvasCommands($ops) 3758 + { 3759 + $accumulated = array(); 3760 + 3761 + $accumulated['SR'] = array(); 3762 + $accumulated['WR'] = array(); 3763 + $accumulated['SP'] = array(); 3764 + $accumulated['WP'] = array(); 3765 + $accumulated['SB'] = array(); 3766 + $accumulated['WB'] = array(); 3767 + $accumulated['SO'] = array(); 3768 + 3769 + while (count($ops) > 0) { 3770 + $color = array_shift($ops); 3771 + $opcode = array_shift($ops); 3772 + 3773 + if (($opcode == 'R') || ($opcode == 'P')) { 3774 + 3775 + do { 3776 + $num = array_shift($ops); 3777 + if (is_int($num)) { 3778 + $accumulated[$color.$opcode][] = $num; 3779 + } else { 3780 + array_unshift($ops, $num); 3781 + } 3782 + 3783 + } while ((count($ops) > 0)&&(is_int($num))); 3784 + 3785 + 3786 + } else if ($opcode == 'B') { 3787 + 3788 + array_shift($ops); 3789 + 3790 + $px = array_shift($ops); 3791 + $py = array_shift($ops); 3792 + 3793 + array_shift($ops); 3794 + 3795 + $conftab = array(); 3796 + $num = array_shift($ops); 3797 + 3798 + while ((count($ops) > 0)&&(!($num === 'E'))) { 3799 + $conftab[] = $num; 3800 + $num = array_shift($ops); 3801 + } 3802 + 3803 + $cc = count($conftab); 3804 + $deltas = ''; 3805 + 3806 + $lastposx = $px; 3807 + $lastposy = $py; 3808 + 3809 + for($pos=0;$pos <$cc; $pos+=2) { 3810 + 3811 + $dx = $lastposx - $conftab[$pos]; 3812 + $dy = $lastposy - $conftab[$pos+1]; 3813 + 3814 + $lastposx = $conftab[$pos]; 3815 + $lastposy = $conftab[$pos+1]; 3816 + 3817 + if ($dx < 0) { 3818 + $deltas .= chr(ord('a')-1-$dx); 3819 + } else if ($dx > 0) { 3820 + $deltas .= chr(ord('A')-1+$dx); 3821 + } else { 3822 + $deltas .= '0'; 3823 + } 3824 + 3825 + if ($dy < 0) { 3826 + $deltas .= chr(ord('a')-1-$dy); 3827 + } else if ($dy > 0) { 3828 + $deltas .= chr(ord('A')-1+$dy); 3829 + } else { 3830 + $deltas .= '0'; 3831 + } 3832 + 3833 + } 3834 + 3835 + $deltas = strtr($deltas, array( 3836 + '00'=>'1', 3837 + 'aa'=>'2', 3838 + 'aA'=>'3', 3839 + 'Aa'=>'4', 3840 + 'AA'=>'5', 3841 + 'aB'=>'6', 3842 + 'Ab'=>'7', 3843 + 'bA'=>'8', 3844 + 'Ba'=>'9' 3845 + )); 3846 + 3847 + $accumulated[$color.$opcode][] = join(',', array($px, $py, $deltas)); 3848 + } else if ($opcode == 'O') { 3849 + $px = array_shift($ops); 3850 + $py = array_shift($ops); 3851 + 3852 + $accumulated[$color.$opcode][] = join(',', array($px, $py)); 3853 + } 3854 + } 3855 + 3856 + self::compact_points($accumulated['SR']); 3857 + self::compact_points($accumulated['WR']); 3858 + self::compact_points($accumulated['SP']); 3859 + self::compact_points($accumulated['WP']); 3860 + 3861 + self::compact_path($accumulated['SB']); 3862 + self::compact_path($accumulated['WB']); 3863 + 3864 + if (count($accumulated['SO']) > 0) 3865 + $accumulated['SO'] = join(',',$accumulated['SO']); 3866 + else $accumulated['SO'] = ''; 3867 + 3868 + $mapping = array( 3869 + 'SO'=>'O', 3870 + 'SB'=>'B', 3871 + 'WB'=>'b', 3872 + 'SR'=>'R', 3873 + 'WR'=>'r', 3874 + 'SP'=>'P', 3875 + 'WP'=>'p' 3876 + ); 3877 + 3878 + $whole = array(); 3879 + 3880 + foreach($mapping as $key=>$symb) { 3881 + if ($accumulated[$key]!='') 3882 + $whole[] = $symb.','.$accumulated[$key]; 3883 + } 3884 + 3885 + return join(',', $whole); 3886 + } 3887 + 3888 + 3889 + //---------------------------------------------------------------------- 3890 + public function getCanvasOps() 3891 + { 3892 + $ops = array(); 3893 + 3894 + foreach ($this->paths as $path) { 3895 + switch ($path[0]) { 3896 + case QR_AREA_PATH: 3897 + $pNum = 0; 3898 + 3899 + foreach($path[1] as $pathDetails) { 3900 + if ($pNum == 0) { 3901 + $ops[] = 'S'; 3902 + } else if ($pNum > 0) { 3903 + $ops[] = 'W'; 3904 + } 3905 + 3906 + $ops[] = 'B'; 3907 + 3908 + $px = array_shift($pathDetails); 3909 + $py = array_shift($pathDetails); 3910 + 3911 + $ops[] = 'M'; 3912 + $ops[] = $px; 3913 + $ops[] = $py; 3914 + 3915 + $rle_steps = array_shift($pathDetails); 3916 + 3917 + $lastOp = ''; 3918 + 3919 + while(count($rle_steps) > 0) { 3920 + 3921 + $delta = 1; 3922 + 3923 + $operator = array_shift($rle_steps); 3924 + if (($operator != 'R') && ($operator != 'L') && ($operator != 'T') && ($operator != 'B')) { 3925 + $delta = (int)$operator; 3926 + $operator = array_shift($rle_steps); 3927 + } 3928 + 3929 + if ($operator == 'R') $px += $delta; 3930 + if ($operator == 'L') $px -= $delta; 3931 + if ($operator == 'T') $py -= $delta; 3932 + if ($operator == 'B') $py += $delta; 3933 + 3934 + if ($lastOp != 'T') 3935 + $ops[] = 'T'; 3936 + 3937 + $ops[] = $px; 3938 + $ops[] = $py; 3939 + 3940 + $lastOp = 'T'; 3941 + } 3942 + 3943 + $ops[] = 'E'; 3944 + 3945 + $pNum++; 3946 + } 3947 + 3948 + break; 3949 + case QR_AREA_POINT: 3950 + 3951 + $symb = array_shift($path); 3952 + 3953 + $ops[] = 'S'; 3954 + 3955 + $lastOp = ''; 3956 + 3957 + while(count($path) > 0) { 3958 + $px = array_shift($path); 3959 + $py = array_shift($path); 3960 + 3961 + if ($lastOp != 'P') 3962 + $ops[] = 'P'; 3963 + 3964 + $ops[] = $px; 3965 + $ops[] = $py; 3966 + 3967 + $lastOp = 'P'; 3968 + } 3969 + 3970 + break; 3971 + 3972 + case QR_AREA_RECT: 3973 + 3974 + $symb = array_shift($path); 3975 + 3976 + $ops[] = 'S'; 3977 + 3978 + $lastOp = ''; 3979 + 3980 + while(count($path) > 0) { 3981 + $px = array_shift($path); 3982 + $py = array_shift($path); 3983 + $ex = array_shift($path); 3984 + $ey = array_shift($path); 3985 + 3986 + if ($lastOp != 'R') 3987 + $ops[] = 'R'; 3988 + 3989 + $ops[] = $px; 3990 + $ops[] = $py; 3991 + $ops[] = $ex-$px; 3992 + $ops[] = $ey-$py; 3993 + 3994 + $lastOp = 'R'; 3995 + } 3996 + 3997 + break; 3998 + 3999 + case QR_AREA_LSHAPE: 4000 + 4001 + $symb = array_shift($path); 4002 + 4003 + while(count($path) > 0) { 4004 + $px = array_shift($path); 4005 + $py = array_shift($path); 4006 + $mode = (int)array_shift($path); 4007 + 4008 + $pxd = ($mode % 2)?1:0; 4009 + $pyd = ($mode > 1)?1:0; 4010 + 4011 + $ops[] = 'S'; 4012 + $ops[] = 'R'; 4013 + $ops[] = $px; 4014 + $ops[] = $py; 4015 + $ops[] = 2; 4016 + $ops[] = 2; 4017 + 4018 + $ops[] = 'W'; 4019 + $ops[] = 'P'; 4020 + $ops[] = $px+$pxd; 4021 + $ops[] = $py+$pyd; 4022 + } 4023 + 4024 + break; 4025 + 4026 + case QR_AREA_TRACKER: 4027 + 4028 + $symb = array_shift($path); 4029 + 4030 + $px = array_shift($path); 4031 + $py = array_shift($path); 4032 + 4033 + $ops[] = 'S'; 4034 + $ops[] = 'O'; 4035 + $ops[] = $px; 4036 + $ops[] = $py; 4037 + 4038 + break; 4039 + } 4040 + } 4041 + 4042 + return self::compactCanvasCommands($ops); 4043 + } 4044 + } 4045 + 4046 + /** @} */ 4047 + 4048 + 4049 + 4050 + 4051 + //---- qrsvg.php ----------------------------- 4052 + 4053 + 4054 + 4055 + 4056 + /* 4057 + * PHP QR Code encoder 4058 + * 4059 + * SVG output support 4060 + * 4061 + * Based on libqrencode C library distributed under LGPL 2.1 4062 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 4063 + * 4064 + * PHP QR Code is distributed under LGPL 3 4065 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 4066 + * 4067 + * This library is free software; you can redistribute it and/or 4068 + * modify it under the terms of the GNU Lesser General Public 4069 + * License as published by the Free Software Foundation; either 4070 + * version 3 of the License, or any later version. 4071 + * 4072 + * This library is distributed in the hope that it will be useful, 4073 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 4074 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 4075 + * Lesser General Public License for more details. 4076 + * 4077 + * You should have received a copy of the GNU Lesser General Public 4078 + * License along with this library; if not, write to the Free Software 4079 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 4080 + */ 4081 + 4082 + /** @addtogroup OutputGroup */ 4083 + /** @{ */ 4084 + 4085 + class QRsvgOutput extends QRarea { 4086 + 4087 + public function __construct($source_tab) 4088 + { 4089 + parent::__construct($source_tab); 4090 + } 4091 + 4092 + //---------------------------------------------------------------------- 4093 + public function mapX($px) 4094 + { 4095 + return $px; 4096 + } 4097 + 4098 + //---------------------------------------------------------------------- 4099 + public function mapY($py) 4100 + { 4101 + return $py; 4102 + } 4103 + 4104 + //---------------------------------------------------------------------- 4105 + public function getRawSvg() 4106 + { 4107 + $lib = array(); 4108 + $svg = array(); 4109 + 4110 + $aggregate_paths = array(); 4111 + 4112 + foreach ($this->paths as $path) { 4113 + switch ($path[0]) { 4114 + case QR_AREA_PATH: 4115 + $pNum = 0; 4116 + 4117 + foreach($path[1] as $pathDetails) { 4118 + 4119 + $px = array_shift($pathDetails); 4120 + $py = array_shift($pathDetails); 4121 + $rle_steps = array_shift($pathDetails); 4122 + 4123 + $aggregate_add = 'M'.$px.','.$py.' '; 4124 + 4125 + while(count($rle_steps) > 0) { 4126 + 4127 + $delta = 1; 4128 + 4129 + $operator = array_shift($rle_steps); 4130 + if (($operator != 'R') && ($operator != 'L') && ($operator != 'T') && ($operator != 'B')) { 4131 + $delta = (int)$operator; 4132 + $operator = array_shift($rle_steps); 4133 + } 4134 + 4135 + if ($operator == 'R') $aggregate_add .= 'h'.$delta; 4136 + if ($operator == 'L') $aggregate_add .= 'h-'.$delta; 4137 + if ($operator == 'T') $aggregate_add .= 'v-'.$delta; 4138 + if ($operator == 'B') $aggregate_add .= 'v'.$delta; 4139 + } 4140 + 4141 + $aggregate_paths[] = $aggregate_add; 4142 + 4143 + $pNum++; 4144 + } 4145 + 4146 + break; 4147 + case QR_AREA_POINT: 4148 + 4149 + $symb = array_shift($path); 4150 + 4151 + while(count($path) > 0) { 4152 + $px = array_shift($path); 4153 + $py = array_shift($path); 4154 + 4155 + $aggregate_paths[] = 'M'.$px.','.$py.' v1h1v-1h-1'; 4156 + } 4157 + 4158 + break; 4159 + 4160 + case QR_AREA_RECT: 4161 + 4162 + $symb = array_shift($path); 4163 + 4164 + while(count($path) > 0) { 4165 + $px = array_shift($path); 4166 + $py = array_shift($path); 4167 + $ex = array_shift($path); 4168 + $ey = array_shift($path); 4169 + 4170 + $w = $ex-$px; 4171 + $h = $ey-$py; 4172 + 4173 + $aggregate_paths[] = 'M'.$px.','.$py.' h'.$w.'v'.$h.'h-'.$w.'v-'.$h; 4174 + } 4175 + 4176 + break; 4177 + 4178 + case QR_AREA_LSHAPE: 4179 + 4180 + $symb = array_shift($path); 4181 + 4182 + $l_shapes[0] = 'm1,0h1v2h-2v-1h1z'; 4183 + $l_shapes[1] = 'h1v1h1v1h-2z'; 4184 + $l_shapes[2] = 'h2v2h-1v-1h-1z'; 4185 + $l_shapes[3] = 'h2v1h-1v1h-1z'; 4186 + 4187 + while(count($path) > 0) { 4188 + $px = array_shift($path); 4189 + $py = array_shift($path); 4190 + $mode = (int)array_shift($path); 4191 + 4192 + $aggregate_paths[] = 'M'.$px.','.$py.' '.$l_shapes[$mode]; 4193 + } 4194 + 4195 + break; 4196 + 4197 + case QR_AREA_TRACKER: 4198 + 4199 + if (!isset($lib['tracker'])) { 4200 + $lib['tracker'] = '<symbol id="tracker"><path d="m 0 7 0 7 7 0 0 -7 -7 0 z m 1 1 5 0 0 5 -5 0 0 -5 z m 1 1 0 3 3 0 0 -3 -3 0 z" style="fill:#000000;stroke:none"></path></symbol>'; 4201 + } 4202 + 4203 + $symb = array_shift($path); 4204 + 4205 + $px = array_shift($path); 4206 + $py = array_shift($path); 4207 + 4208 + $svg[] = '<use x="'.$px.'" y="'.($py-7).'" xlink:href="#tracker"></use>'; 4209 + 4210 + break; 4211 + } 4212 + } 4213 + 4214 + $svg[] = '<path d="'.join(' ', $aggregate_paths).'" style="fill:#000000;stroke:none" ></path>'; 4215 + 4216 + 4217 + 4218 + return join("\n", $lib)."\n".join("\n", $svg); 4219 + } 4220 + } 4221 + 4222 + /** @} */ 4223 + 4224 + 4225 + 4226 + 4227 + //---- qrencode.php ----------------------------- 4228 + 4229 + 4230 + 2809 4231 2810 4232 /* 2811 4233 * PHP QR Code encoder ··· 2816 4238 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> 2817 4239 * 2818 4240 * PHP QR Code is distributed under LGPL 3 2819 - * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> 4241 + * Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm> 2820 4242 * 2821 4243 * This library is free software; you can redistribute it and/or 2822 4244 * modify it under the terms of the GNU Lesser General Public ··· 2833 4255 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 2834 4256 */ 2835 4257 4258 + /** @defgroup CoreGroup Standard API Core 4259 + Core encoder classes */ 4260 + 4261 + /** @addtogroup CoreGroup */ 4262 + /** @{ */ 4263 + 4264 + //########################################################################## 4265 + /** 4266 + Data block with raw data and it's Error Correction Code data. 4267 + */ 2836 4268 class QRrsblock { 2837 4269 public $dataLength; 2838 4270 public $data = array(); 2839 4271 public $eccLength; 2840 4272 public $ecc = array(); 2841 4273 4274 + /** Data block Constructor 4275 + @param Integer $dl length of data stream 4276 + @param Array $data data stream 4277 + @param Integer $el ECC length 4278 + @param Array $el ECC stream (modified, by reference) 4279 + @param QRrsItem $rs RS encoding item 4280 + */ 2842 4281 public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs) 2843 4282 { 2844 4283 $rs->encode_rs_char($data, $ecc); ··· 2851 4290 }; 2852 4291 2853 4292 //########################################################################## 2854 - 4293 + /** Raw Code holder. 4294 + Contains encoded code data before there are spatialy distributed into frame and masked. 4295 + Here goes dividing data into blocks and calculating ECC stream. */ 2855 4296 class QRrawcode { 2856 - public $version; 2857 - public $datacode = array(); 2858 - public $ecccode = array(); 2859 - public $blocks; 2860 - public $rsblocks = array(); //of RSblock 2861 - public $count; 2862 - public $dataLength; 2863 - public $eccLength; 2864 - public $b1; 4297 + 4298 + public $version; ///< __Integer__ code Version 4299 + public $datacode = array(); ///< __Array__ data stream 4300 + public $ecccode = array(); ///< __Array__ ECC Stream 4301 + public $blocks; ///< __Integer__ RS Blocks count 4302 + public $rsblocks = array(); ///< __Array__ of RSblock, ECC code blocks 4303 + public $count; ///< __Integer__ position of currently processed ECC code 4304 + public $dataLength; ///< __Integer__ data stream length 4305 + public $eccLength; ///< __Integer__ ECC stream length 4306 + public $b1; ///< __Integer__ width of code in pixels, used as a modulo base for column overflow 2865 4307 2866 4308 //---------------------------------------------------------------------- 4309 + /** Raw Code holder Constructor 4310 + @param QRinput $input input stream 4311 + */ 2867 4312 public function __construct(QRinput $input) 2868 4313 { 2869 4314 $spec = array(0,0,0,0,0); ··· 2892 4337 } 2893 4338 2894 4339 //---------------------------------------------------------------------- 4340 + /** Initializes Raw Code according to current code speciffication 4341 + @param Array $spec code speciffigation, as provided by QRspec 4342 + */ 2895 4343 public function init(array $spec) 2896 4344 { 2897 4345 $dl = QRspec::rsDataCodes1($spec); ··· 2935 4383 } 2936 4384 2937 4385 //---------------------------------------------------------------------- 4386 + /** Gets ECC code 4387 + @return Integer ECC byte for current object position 4388 + */ 2938 4389 public function getCode() 2939 4390 { 2940 4391 $ret = null; ··· 2960 4411 } 2961 4412 2962 4413 //########################################################################## 4414 + /** 4415 + __Main class to create QR-code__. 4416 + QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD. 4417 + The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness. 4418 + This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004. 2963 4419 4420 + Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode. 4421 + 4422 + @abstract Class for generating QR-code images, SVG and HTML5 Canvas 4423 + @author Dominik Dzienia 4424 + @copyright 2010-2013 Dominik Dzienia and others 4425 + @link http://phpqrcode.sourceforge.net 4426 + @license http://www.gnu.org/copyleft/lesser.html LGPL 4427 + */ 4428 + 2964 4429 class QRcode { 2965 4430 2966 - public $version; 2967 - public $width; 2968 - public $data; 4431 + public $version; ///< __Integer__ QR code version. Size of QRcode is defined as version. Version is from 1 to 40. Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. So version 40 is 177*177 matrix. 4432 + public $width; ///< __Integer__ Width of code table. Because code is square shaped - same as height. 4433 + public $data; ///< __Array__ Ready, masked code data. 4434 + 4435 + /** Canvas JS include flag. 4436 + If canvas js support library was included, we remember it static in QRcode. 4437 + (because file should be included only once) 4438 + */ 4439 + public static $jscanvasincluded = false; 2969 4440 2970 4441 //---------------------------------------------------------------------- 4442 + /** 4443 + Encode mask 4444 + Main function responsible for creating code. 4445 + We get empty frame, then fill it with data from input, then select best mask and apply it. 4446 + If $mask argument is greater than -1 we assume that user want's that specific mask number (ranging form 0-7) to be used. 4447 + Otherwise (when $mask is -1) mask is detected using algorithm depending of global configuration, 4448 + 4449 + @param QRinput $input data object 4450 + @param Integer $mask sugested masking mode 4451 + @return QRcode $this (current instance) 4452 + */ 2971 4453 public function encodeMask(QRinput $input, $mask) 2972 4454 { 2973 4455 if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) { ··· 2985 4467 $width = QRspec::getWidth($version); 2986 4468 $frame = QRspec::newFrame($version); 2987 4469 2988 - $filler = new FrameFiller($width, $frame); 4470 + $filler = new QRframeFiller($width, $frame); 2989 4471 if(is_null($filler)) { 2990 4472 return NULL; 2991 4473 } ··· 3035 4517 3036 4518 QRtools::markTime('after_mask'); 3037 4519 3038 - $this->version = $version; 3039 - $this->width = $width; 3040 - $this->data = $masked; 4520 + $this->version = $version; 4521 + $this->width = $width; 4522 + $this->data = $masked; 3041 4523 3042 4524 return $this; 3043 4525 } 3044 4526 3045 4527 //---------------------------------------------------------------------- 4528 + /** 4529 + Encode input with mask detection. 4530 + Shorthand for encodeMask, without specifing particular, static mask number. 4531 + 4532 + @param QRinput $input data object to be encoded 4533 + @return 4534 + */ 3046 4535 public function encodeInput(QRinput $input) 3047 4536 { 3048 4537 return $this->encodeMask($input, -1); 3049 4538 } 3050 4539 3051 4540 //---------------------------------------------------------------------- 4541 + /** 4542 + Encode string, forcing 8-bit encoding 4543 + @param String $string input string 4544 + @param Integer $version code version (size of code area) 4545 + @param Integer $level ECC level (see: Global Constants -> Levels of Error Correction) 4546 + @return QRcode $this (current instance) 4547 + */ 3052 4548 public function encodeString8bit($string, $version, $level) 3053 4549 { 3054 - if(string == NULL) { 4550 + if($string == NULL) { 3055 4551 throw new Exception('empty string!'); 3056 4552 return NULL; 3057 4553 } ··· 3059 4555 $input = new QRinput($version, $level); 3060 4556 if($input == NULL) return NULL; 3061 4557 3062 - $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string)); 4558 + $ret = $input->append(QR_MODE_8, strlen($string), str_split($string)); 3063 4559 if($ret < 0) { 3064 4560 unset($input); 3065 4561 return NULL; ··· 3068 4564 } 3069 4565 3070 4566 //---------------------------------------------------------------------- 4567 + /** 4568 + Encode string, using optimal encodings. 4569 + Encode string dynamically adjusting encoding for subsections of string to 4570 + minimize resulting code size. For complex string it will split string into 4571 + subsections: Numerical, Alphanumerical or 8-bit. 4572 + @param String $string input string 4573 + @param Integer $version code version (size of code area) 4574 + @param String $level ECC level (see: Global Constants -> Levels of Error Correction) 4575 + @param Integer $hint __QR_MODE_8__ or __QR_MODE_KANJI__, Because Kanji encoding 4576 + is kind of 8 bit encoding we need to hint encoder to use Kanji mode explicite. 4577 + (otherwise it may try to encode it as plain 8 bit stream) 4578 + @param Boolean $casesensitive hint if given string is case-sensitive, because 4579 + if not - encoder may use optimal QR_MODE_AN instead of QR_MODE_8 4580 + @return QRcode $this (current instance) 4581 + */ 3071 4582 public function encodeString($string, $version, $level, $hint, $casesensitive) 3072 4583 { 3073 4584 ··· 3087 4598 return $this->encodeInput($input); 3088 4599 } 3089 4600 3090 - //---------------------------------------------------------------------- 4601 + //###################################################################### 4602 + /** 4603 + Creates PNG image containing QR-Code. 4604 + Simple helper function to create QR-Code Png image with one static call. 4605 + @param String $text text string to encode 4606 + @param String $outfile (optional) output file name, if __false__ outputs to browser with required headers 4607 + @param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__ 4608 + @param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel 4609 + @param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels 4610 + @param Boolean $saveandprint (optional) if __true__ code is outputed to browser and saved to file, otherwise only saved to file. It is effective only if $outfile is specified. 4611 + */ 4612 + 3091 4613 public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false) 3092 4614 { 3093 4615 $enc = QRencode::factory($level, $size, $margin); ··· 3095 4617 } 3096 4618 3097 4619 //---------------------------------------------------------------------- 4620 + /** 4621 + Creates text (1's & 0's) containing QR-Code. 4622 + Simple helper function to create QR-Code text with one static call. 4623 + @param String $text text string to encode 4624 + @param String $outfile (optional) output file name, when __false__ file is not saved 4625 + @param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__ 4626 + @param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel 4627 + @param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels 4628 + @return Array containing line of code with 1 and 0 for every code line 4629 + */ 4630 + 3098 4631 public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) 3099 4632 { 3100 4633 $enc = QRencode::factory($level, $size, $margin); ··· 3102 4635 } 3103 4636 3104 4637 //---------------------------------------------------------------------- 4638 + /** 4639 + Creates Raw Array containing QR-Code. 4640 + Simple helper function to create QR-Code array with one static call. 4641 + @param String $text text string to encode 4642 + @param Boolean $outfile (optional) not used, shuold be __false__ 4643 + @param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__ 4644 + @param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel 4645 + @param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels 4646 + @return Array containing Raw QR code 4647 + */ 4648 + 3105 4649 public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) 3106 4650 { 3107 4651 $enc = QRencode::factory($level, $size, $margin); 3108 4652 return $enc->encodeRAW($text, $outfile); 3109 4653 } 4654 + 4655 + //---------------------------------------------------------------------- 4656 + /** 4657 + Creates Html+JS code to draw QR-Code with HTML5 Canvas. 4658 + Simple helper function to create QR-Code array with one static call. 4659 + @param String $text text string to encode 4660 + @param String $elemId (optional) target Canvas tag id attribute, if __false__ Canvas tag with auto id will be created 4661 + @param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__ 4662 + @param Integer $width (optional) CANVAS element width (sam as height) 4663 + @param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel 4664 + @param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels 4665 + @param Boolean $autoInclude (optional) if __true__, required qrcanvas.js lib will be included (only once) 4666 + @return String containing JavaScript creating the code, Canvas element (when $elemId is __false__) and script tag with required lib (when $autoInclude is __true__ and not yet included) 4667 + */ 4668 + 4669 + public static function canvas($text, $elemId = false, $level = QR_ECLEVEL_L, $width = false, $size = false, $margin = 4, $autoInclude = false) 4670 + { 4671 + $html = ''; 4672 + $extra = ''; 4673 + 4674 + if ($autoInclude) { 4675 + if (!self::$jscanvasincluded) { 4676 + self::$jscanvasincluded = true; 4677 + echo '<script type="text/javascript" src="qrcanvas.js"></script>'; 4678 + } 4679 + } 4680 + 4681 + $enc = QRencode::factory($level, 1, 0); 4682 + $tab_src = $enc->encode($text, false); 4683 + $area = new QRcanvasOutput($tab_src); 4684 + $area->detectGroups(); 4685 + $area->detectAreas(); 4686 + 4687 + if ($elemId === false) { 4688 + $elemId = 'qrcode-'.md5(mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000)); 4689 + 4690 + if ($width == false) { 4691 + if (($size !== false) && ($size > 0)) { 4692 + $width = ($area->getWidth()+(2*$margin)) * $size; 4693 + } else { 4694 + $width = ($area->getWidth()+(2*$margin)) * 4; 4695 + } 4696 + } 4697 + 4698 + $html .= '<canvas id="'.$elemId.'" width="'.$width.'" height="'.$width.'">Your browser does not support CANVAS tag! Please upgrade to modern version of FireFox, Opera, Chrome or Safari/Webkit based browser</canvas>'; 4699 + } 4700 + 4701 + if ($width !== false) { 4702 + $extra .= ', '.$width.', '.$width; 4703 + } 4704 + 4705 + if ($margin !== false) { 4706 + $extra .= ', '.$margin.', '.$margin; 4707 + } 4708 + 4709 + $html .= '<script>if(eval("typeof "+\'QRdrawCode\'+"==\'function\'")){QRdrawCode(QRdecompactOps(\''.$area->getCanvasOps().'\')'."\n".', \''.$elemId.'\', '.$area->getWidth().' '.$extra.');}else{alert(\'Please include qrcanvas.js!\');}</script>'; 4710 + 4711 + return $html; 4712 + } 4713 + 4714 + //---------------------------------------------------------------------- 4715 + /** 4716 + Creates SVG with QR-Code. 4717 + Simple helper function to create QR-Code SVG with one static call. 4718 + @param String $text text string to encode 4719 + @param Boolean $elemId (optional) target SVG tag id attribute, if __false__ SVG tag with auto id will be created 4720 + @param String $outfile (optional) output file name, when __false__ file is not saved 4721 + @param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__ 4722 + @param Integer $width (optional) SVG element width (sam as height) 4723 + @param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel 4724 + @param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels 4725 + @param Boolean $compress (optional) if __true__, compressed SVGZ (instead plaintext SVG) is saved to file 4726 + @return String containing SVG tag 4727 + */ 4728 + 4729 + public static function svg($text, $elemId = false, $outFile = false, $level = QR_ECLEVEL_L, $width = false, $size = false, $margin = 4, $compress = false) 4730 + { 4731 + $enc = QRencode::factory($level, 1, 0); 4732 + $tab_src = $enc->encode($text, false); 4733 + $area = new QRsvgOutput($tab_src); 4734 + $area->detectGroups(); 4735 + $area->detectAreas(); 4736 + 4737 + if ($elemId === false) { 4738 + $elemId = 'qrcode-'.md5(mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000)); 4739 + 4740 + if ($width == false) { 4741 + if (($size !== false) && ($size > 0)) { 4742 + $width = ($area->getWidth()+(2*$margin)) * $size; 4743 + } else { 4744 + $width = ($area->getWidth()+(2*$margin)) * 4; 4745 + } 4746 + } 4747 + } 4748 + 4749 + $svg = '<svg xmlns="http://www.w3.org/2000/svg" 4750 + xmlns:xlink="http://www.w3.org/1999/xlink" 4751 + version="1.1" 4752 + baseProfile="full" 4753 + viewBox="'.(-$margin).' '.(-$margin).' '.($area->getWidth()+($margin*2)).' '.($area->getWidth()+($margin*2)).'" 4754 + width="'.$width.'" 4755 + height="'.$width.'" 4756 + id="'.$elemId.'">'."\n"; 4757 + 4758 + $svg .= $area->getRawSvg().'</svg>'; 4759 + 4760 + if ($outFile !== false) { 4761 + $xmlPreamble = '<?xml version="1.0" encoding="UTF-8" standalone="no"'."\n"; 4762 + $svgContent = $xmlPreamble.$svg; 4763 + 4764 + if ($compress === true) { 4765 + file_put_contents($outFile, gzencode($svgContent)); 4766 + } else { 4767 + file_put_contents($outFile, $svgContent); 4768 + } 4769 + } 4770 + 4771 + return $svg; 4772 + } 3110 4773 } 3111 4774 3112 4775 //########################################################################## 3113 - 3114 - class FrameFiller { 4776 + /** Fills frame with data. 4777 + Each empty frame consist of markers, timing symbols and format configuration. 4778 + Remaining place is place for data, and should be filled according to QR Code spec. 4779 + */ 4780 + class QRframeFiller { 3115 4781 3116 - public $width; 3117 - public $frame; 3118 - public $x; 3119 - public $y; 3120 - public $dir; 3121 - public $bit; 4782 + public $width; ///< __Integer__ Frame width 4783 + public $frame; ///< __Array__ Frame itself 4784 + public $x; ///< __Integer__ current X position 4785 + public $y; ///< __Integer__ current Y position 4786 + public $dir; ///< __Integer__ direction 4787 + public $bit; ///< __Integer__ bit 3122 4788 3123 4789 //---------------------------------------------------------------------- 4790 + /** Frame filler Constructor. 4791 + @param Integer $width frame size 4792 + @param Array $frame Frame array 4793 + */ 3124 4794 public function __construct($width, &$frame) 3125 4795 { 3126 4796 $this->width = $width; ··· 3132 4802 } 3133 4803 3134 4804 //---------------------------------------------------------------------- 4805 + /** Sets frame code at given position. 4806 + @param Array $at position, map containing __x__ and __y__ coordinates 4807 + @param Integer $val value to set 4808 + */ 3135 4809 public function setFrameAt($at, $val) 3136 4810 { 3137 4811 $this->frame[$at['y']][$at['x']] = chr($val); 3138 4812 } 3139 4813 3140 4814 //---------------------------------------------------------------------- 4815 + /** Gets frame code from given position. 4816 + @param Array $at position, map containing __x__ and __y__ coordinates 4817 + @return Integer value at requested position 4818 + */ 3141 4819 public function getFrameAt($at) 3142 4820 { 3143 4821 return ord($this->frame[$at['y']][$at['x']]); 3144 4822 } 3145 4823 3146 4824 //---------------------------------------------------------------------- 4825 + /** Proceed to next code point. */ 3147 4826 public function next() 3148 4827 { 3149 4828 do { ··· 3200 4879 } ; 3201 4880 3202 4881 //########################################################################## 3203 - 4882 + /** QR Code encoder. 4883 + Encoder is used by QRCode to create simple static code generators. */ 3204 4884 class QRencode { 3205 4885 3206 - public $casesensitive = true; 3207 - public $eightbit = false; 4886 + public $casesensitive = true; ///< __Boolean__ does input stream id case sensitive, if not encoder may use more optimal charsets 4887 + public $eightbit = false; ///< __Boolean__ does input stream is 8 bit 3208 4888 3209 - public $version = 0; 3210 - public $size = 3; 3211 - public $margin = 4; 4889 + public $version = 0; ///< __Integer__ code version (total size) if __0__ - will be auto-detected 4890 + public $size = 3; ///< __Integer__ pixel zoom factor, multiplier to map virtual code pixels to image output pixels 4891 + public $margin = 4; ///< __Integer__ margin (silent zone) size, in code pixels 3212 4892 3213 - public $structured = 0; // not supported yet 4893 + public $structured = 0; ///< Structured QR codes. Not supported. 3214 4894 3215 - public $level = QR_ECLEVEL_L; 3216 - public $hint = QR_MODE_8; 4895 + public $level = QR_ECLEVEL_L; ///< __Integer__ error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__ 4896 + public $hint = QR_MODE_8; ///< __Integer__ encoding hint, __QR_MODE_8__ or __QR_MODE_KANJI__, Because Kanji encoding is kind of 8 bit encoding we need to hint encoder to use Kanji mode explicite. (otherwise it may try to encode it as plain 8 bit stream) 3217 4897 3218 4898 //---------------------------------------------------------------------- 4899 + /** Encoder instances factory. 4900 + @param Integer $level error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__ 4901 + @param Integer $size pixel zoom factor, multiplier to map virtual code pixels to image output pixels 4902 + @param Integer $margin margin (silent zone) size, in code pixels 4903 + @return builded QRencode instance 4904 + */ 3219 4905 public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4) 3220 4906 { 3221 4907 $enc = new QRencode(); ··· 3251 4937 } 3252 4938 3253 4939 //---------------------------------------------------------------------- 3254 - public function encodeRAW($intext, $outfile = false) 4940 + /** Encodes input into Raw code table. 4941 + @param String $intext input text 4942 + @param Boolean $notused (optional, not used) placeholder for similar outfile parameter 4943 + @return __Array__ Raw code frame 4944 + */ 4945 + public function encodeRAW($intext, $notused = false) 3255 4946 { 3256 4947 $code = new QRcode(); 3257 4948 ··· 3265 4956 } 3266 4957 3267 4958 //---------------------------------------------------------------------- 4959 + /** Encodes input into binary code table. 4960 + @param String $intext input text 4961 + @param String $outfile (optional) output file to save code table, if __false__ file will be not saved 4962 + @return __Array__ binary code frame 4963 + */ 3268 4964 public function encode($intext, $outfile = false) 3269 4965 { 3270 4966 $code = new QRcode(); ··· 3277 4973 3278 4974 QRtools::markTime('after_encode'); 3279 4975 4976 + $binarized = QRtools::binarize($code->data); 3280 4977 if ($outfile!== false) { 3281 - file_put_contents($outfile, join("\n", QRtools::binarize($code->data))); 3282 - } else { 3283 - return QRtools::binarize($code->data); 4978 + file_put_contents($outfile, join("\n", $binarized)); 3284 4979 } 4980 + 4981 + return $binarized; 3285 4982 } 3286 4983 3287 4984 //---------------------------------------------------------------------- 3288 - public function encodePNG($intext, $outfile = false,$saveandprint=false) 4985 + /** Encodes input into PNG image. 4986 + @param String $intext input text 4987 + @param String $outfile (optional) output file name, if __false__ outputs to browser with required headers 4988 + @param Boolean $saveandprint (optional) if __true__ code is outputed to browser and saved to file, otherwise only saved to file. It is effective only if $outfile is specified. 4989 + */ 4990 + public function encodePNG($intext, $outfile = false, $saveandprint=false) 3289 4991 { 3290 4992 try { 3291 4993 ··· 3308 5010 } 3309 5011 } 3310 5012 } 3311 - 3312 - 5013 + 5014 + /** @}*/ 5015 +