Issues (1270)

lib/phpqrcode/qrspec.php (2 issues)

1
<?php
2
/*
3
 * PHP QR Code encoder
4
 *
5
 * QR Code specifications
6
 *
7
 * Based on libqrencode C library distributed under LGPL 2.1
8
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
9
 *
10
 * PHP QR Code is distributed under LGPL 3
11
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
12
 *
13
 * The following data / specifications are taken from
14
 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
15
 *  or
16
 * "Automatic identification and data capture techniques -- 
17
 *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
18
 *
19
 * This library is free software; you can redistribute it and/or
20
 * modify it under the terms of the GNU Lesser General Public
21
 * License as published by the Free Software Foundation; either
22
 * version 3 of the License, or any later version.
23
 *
24
 * This library is distributed in the hope that it will be useful,
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27
 * Lesser General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU Lesser General Public
30
 * License along with this library; if not, write to the Free Software
31
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
32
 */
33
 
34
    define('QRSPEC_VERSION_MAX', 40);
35
    define('QRSPEC_WIDTH_MAX', 177);
36
37
    define('QRCAP_WIDTH', 0);
38
    define('QRCAP_WORDS', 1);
39
    define('QRCAP_REMINDER', 2);
40
    define('QRCAP_EC', 3);
41
42
    class QRspec {
43
    
44
        public static $capacity = array(
45
            array(0, 0, 0, array(0, 0, 0, 0)),
46
            array(21, 26, 0, array(7, 10, 13, 17)), // 1
47
            array(25, 44, 7, array(10, 16, 22, 28)),
48
            array(29, 70, 7, array(15, 26, 36, 44)),
49
            array(33, 100, 7, array(20, 36, 52, 64)),
50
            array(37, 134, 7, array(26, 48, 72, 88)), // 5
51
            array(41, 172, 7, array(36, 64, 96, 112)),
52
            array(45, 196, 0, array(40, 72, 108, 130)),
53
            array(49, 242, 0, array(48, 88, 132, 156)),
54
            array(53, 292, 0, array(60, 110, 160, 192)),
55
            array(57, 346, 0, array(72, 130, 192, 224)), //10
56
            array(61, 404, 0, array(80, 150, 224, 264)),
57
            array(65, 466, 0, array(96, 176, 260, 308)),
58
            array(69, 532, 0, array(104, 198, 288, 352)),
59
            array(73, 581, 3, array(120, 216, 320, 384)),
60
            array(77, 655, 3, array(132, 240, 360, 432)), //15
61
            array(81, 733, 3, array(144, 280, 408, 480)),
62
            array(85, 815, 3, array(168, 308, 448, 532)),
63
            array(89, 901, 3, array(180, 338, 504, 588)),
64
            array(93, 991, 3, array(196, 364, 546, 650)),
65
            array(97, 1085, 3, array(224, 416, 600, 700)), //20
66
            array(101, 1156, 4, array(224, 442, 644, 750)),
67
            array(105, 1258, 4, array(252, 476, 690, 816)),
68
            array(109, 1364, 4, array(270, 504, 750, 900)),
69
            array(113, 1474, 4, array(300, 560, 810, 960)),
70
            array(117, 1588, 4, array(312, 588, 870, 1050)), //25
71
            array(121, 1706, 4, array(336, 644, 952, 1110)),
72
            array(125, 1828, 4, array(360, 700, 1020, 1200)),
73
            array(129, 1921, 3, array(390, 728, 1050, 1260)),
74
            array(133, 2051, 3, array(420, 784, 1140, 1350)),
75
            array(137, 2185, 3, array(450, 812, 1200, 1440)), //30
76
            array(141, 2323, 3, array(480, 868, 1290, 1530)),
77
            array(145, 2465, 3, array(510, 924, 1350, 1620)),
78
            array(149, 2611, 3, array(540, 980, 1440, 1710)),
79
            array(153, 2761, 3, array(570, 1036, 1530, 1800)),
80
            array(157, 2876, 0, array(570, 1064, 1590, 1890)), //35
81
            array(161, 3034, 0, array(600, 1120, 1680, 1980)),
82
            array(165, 3196, 0, array(630, 1204, 1770, 2100)),
83
            array(169, 3362, 0, array(660, 1260, 1860, 2220)),
84
            array(173, 3532, 0, array(720, 1316, 1950, 2310)),
85
            array(177, 3706, 0, array(750, 1372, 2040, 2430)) //40
86
        );
87
        
88
        //----------------------------------------------------------------------
89
        public static function getDataLength($version, $level)
90
        {
91
            return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
92
        }
93
        
94
        //----------------------------------------------------------------------
95
        public static function getECCLength($version, $level)
96
        {
97
            return self::$capacity[$version][QRCAP_EC][$level];
98
        }
99
        
100
        //----------------------------------------------------------------------
101
        public static function getWidth($version)
102
        {
103
            return self::$capacity[$version][QRCAP_WIDTH];
104
        }
105
        
106
        //----------------------------------------------------------------------
107
        public static function getRemainder($version)
108
        {
109
            return self::$capacity[$version][QRCAP_REMINDER];
110
        }
111
        
112
        //----------------------------------------------------------------------
113
        public static function getMinimumVersion($size, $level)
114
        {
115
116
            for ($i = 1; $i <= QRSPEC_VERSION_MAX; $i++) {
117
                $words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
118
                if ($words >= $size) {
119
                                    return $i;
120
                }
121
            }
122
123
            return -1;
124
        }
125
    
126
        //######################################################################
127
        
128
        public static $lengthTableBits = array(
129
            array(10, 12, 14),
130
            array(9, 11, 13),
131
            array(8, 16, 16),
132
            array(8, 10, 12)
133
        );
134
        
135
        //----------------------------------------------------------------------
136
        public static function lengthIndicator($mode, $version)
137
        {
138
            if ($mode == QR_MODE_STRUCTURE) {
139
                            return 0;
140
            }
141
                
142
            if ($version <= 9) {
143
                $l = 0;
144
            } else if ($version <= 26) {
145
                $l = 1;
146
            } else {
147
                $l = 2;
148
            }
149
150
            return self::$lengthTableBits[$mode][$l];
151
        }
152
        
153
        //----------------------------------------------------------------------
154
        public static function maximumWords($mode, $version)
155
        {
156
            if ($mode == QR_MODE_STRUCTURE) {
157
                            return 3;
158
            }
159
                
160
            if ($version <= 9) {
161
                $l = 0;
162
            } else if ($version <= 26) {
163
                $l = 1;
164
            } else {
165
                $l = 2;
166
            }
167
168
            $bits = self::$lengthTableBits[$mode][$l];
169
            $words = (1 << $bits) - 1;
170
            
171
            if ($mode == QR_MODE_KANJI) {
172
                $words *= 2; // the number of bytes is required
173
            }
174
175
            return $words;
176
        }
177
178
        // Error correction code -----------------------------------------------
179
        // Table of the error correction code (Reed-Solomon block)
180
        // See Table 12-16 (pp.30-36), JIS X0510:2004.
181
182
        public static $eccTable = array(
183
            array(array(0, 0), array(0, 0), array(0, 0), array(0, 0)),
184
            array(array(1, 0), array(1, 0), array(1, 0), array(1, 0)), // 1
185
            array(array(1, 0), array(1, 0), array(1, 0), array(1, 0)),
186
            array(array(1, 0), array(1, 0), array(2, 0), array(2, 0)),
187
            array(array(1, 0), array(2, 0), array(2, 0), array(4, 0)),
188
            array(array(1, 0), array(2, 0), array(2, 2), array(2, 2)), // 5
189
            array(array(2, 0), array(4, 0), array(4, 0), array(4, 0)),
190
            array(array(2, 0), array(4, 0), array(2, 4), array(4, 1)),
191
            array(array(2, 0), array(2, 2), array(4, 2), array(4, 2)),
192
            array(array(2, 0), array(3, 2), array(4, 4), array(4, 4)),
193
            array(array(2, 2), array(4, 1), array(6, 2), array(6, 2)), //10
194
            array(array(4, 0), array(1, 4), array(4, 4), array(3, 8)),
195
            array(array(2, 2), array(6, 2), array(4, 6), array(7, 4)),
196
            array(array(4, 0), array(8, 1), array(8, 4), array(12, 4)),
197
            array(array(3, 1), array(4, 5), array(11, 5), array(11, 5)),
198
            array(array(5, 1), array(5, 5), array(5, 7), array(11, 7)), //15
199
            array(array(5, 1), array(7, 3), array(15, 2), array(3, 13)),
200
            array(array(1, 5), array(10, 1), array(1, 15), array(2, 17)),
201
            array(array(5, 1), array(9, 4), array(17, 1), array(2, 19)),
202
            array(array(3, 4), array(3, 11), array(17, 4), array(9, 16)),
203
            array(array(3, 5), array(3, 13), array(15, 5), array(15, 10)), //20
204
            array(array(4, 4), array(17, 0), array(17, 6), array(19, 6)),
205
            array(array(2, 7), array(17, 0), array(7, 16), array(34, 0)),
206
            array(array(4, 5), array(4, 14), array(11, 14), array(16, 14)),
207
            array(array(6, 4), array(6, 14), array(11, 16), array(30, 2)),
208
            array(array(8, 4), array(8, 13), array(7, 22), array(22, 13)), //25
209
            array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)),
210
            array(array(8, 4), array(22, 3), array(8, 26), array(12, 28)),
211
            array(array(3, 10), array(3, 23), array(4, 31), array(11, 31)),
212
            array(array(7, 7), array(21, 7), array(1, 37), array(19, 26)),
213
            array(array(5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
214
            array(array(13, 3), array(2, 29), array(42, 1), array(23, 28)),
215
            array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)),
216
            array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)),
217
            array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)),
218
            array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35
219
            array(array(6, 14), array(6, 34), array(46, 10), array(2, 64)),
220
            array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)),
221
            array(array(4, 18), array(13, 32), array(48, 14), array(42, 32)),
222
            array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)),
223
            array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)), //40
224
        );                                                                       
225
226
        //----------------------------------------------------------------------
227
        // CACHEABLE!!!
228
        
229
        public static function getEccSpec($version, $level, array &$spec)
230
        {
231
            if (count($spec) < 5) {
232
                $spec = array(0, 0, 0, 0, 0);
233
            }
234
235
            $b1   = self::$eccTable[$version][$level][0];
236
            $b2   = self::$eccTable[$version][$level][1];
237
            $data = self::getDataLength($version, $level);
238
            $ecc  = self::getECCLength($version, $level);
239
240
            if ($b2 == 0) {
241
                $spec[0] = $b1;
242
                $spec[1] = (int) ($data / $b1);
243
                $spec[2] = (int) ($ecc / $b1);
244
                $spec[3] = 0; 
245
                $spec[4] = 0;
246
            } else {
247
                $spec[0] = $b1;
248
                $spec[1] = (int) ($data / ($b1 + $b2));
249
                $spec[2] = (int) ($ecc / ($b1 + $b2));
250
                $spec[3] = $b2;
251
                $spec[4] = $spec[1] + 1;
252
            }
253
        }
254
255
        // Alignment pattern ---------------------------------------------------
256
257
        // Positions of alignment patterns.
258
        // This array includes only the second and the third position of the 
259
        // alignment patterns. Rest of them can be calculated from the distance 
260
        // between them.
261
         
262
        // See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
263
         
264
        public static $alignmentPattern = array(      
265
            array(0, 0),
266
            array(0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5
267
            array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10
268
            array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15
269
            array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20
270
            array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
271
            array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
272
            array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
273
            array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40
274
        );                                                                                  
275
276
        
277
        /** --------------------------------------------------------------------
278
         * Put an alignment marker.
279
         * @param frame
280
         * @param width
281
         * @param ox,oy center coordinate of the pattern
0 ignored issues
show
The type center was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
282
         */
283
        public static function putAlignmentMarker(array &$frame, $ox, $oy)
284
        {
285
            $finder = array(
286
                "\xa1\xa1\xa1\xa1\xa1",
287
                "\xa1\xa0\xa0\xa0\xa1",
288
                "\xa1\xa0\xa1\xa0\xa1",
289
                "\xa1\xa0\xa0\xa0\xa1",
290
                "\xa1\xa1\xa1\xa1\xa1"
291
            );                        
292
            
293
            $yStart = $oy - 2;         
294
            $xStart = $ox - 2;
295
            
296
            for ($y = 0; $y < 5; $y++) {
297
                QRstr::set($frame, $xStart, $yStart + $y, $finder[$y]);
298
            }
299
        }
300
301
        //----------------------------------------------------------------------
302
        public static function putAlignmentPattern($version, &$frame, $width)
303
        {
304
            if ($version < 2) {
305
                            return;
306
            }
307
308
            $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
309
            if ($d < 0) {
310
                $w = 2;
311
            } else {
312
                $w = (int) (($width - self::$alignmentPattern[$version][0]) / $d + 2);
313
            }
314
315
            if ($w * $w - 3 == 1) {
316
                $x = self::$alignmentPattern[$version][0];
317
                $y = self::$alignmentPattern[$version][0];
318
                self::putAlignmentMarker($frame, $x, $y);
319
                return;
320
            }
321
322
            $cx = self::$alignmentPattern[$version][0];
323
            for ($x = 1; $x < $w - 1; $x++) {
324
                self::putAlignmentMarker($frame, 6, $cx);
325
                self::putAlignmentMarker($frame, $cx, 6);
326
                $cx += $d;
327
            }
328
329
            $cy = self::$alignmentPattern[$version][0];
330
            for ($y = 0; $y < $w - 1; $y++) {
331
                $cx = self::$alignmentPattern[$version][0];
332
                for ($x = 0; $x < $w - 1; $x++) {
333
                    self::putAlignmentMarker($frame, $cx, $cy);
334
                    $cx += $d;
335
                }
336
                $cy += $d;
337
            }
338
        }
339
340
        // Version information pattern -----------------------------------------
341
342
        // Version information pattern (BCH coded).
343
        // See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
344
        
345
        // size: [QRSPEC_VERSION_MAX - 6]
346
		
347
        public static $versionPattern = array(
348
            0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
349
            0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
350
            0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
351
            0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
352
            0x27541, 0x28c69
353
        );
354
355
        //----------------------------------------------------------------------
356
        public static function getVersionPattern($version)
357
        {
358
            if ($version < 7 || $version > QRSPEC_VERSION_MAX) {
359
                            return 0;
360
            }
361
362
            return self::$versionPattern[$version - 7];
363
        }
364
365
        // Format information --------------------------------------------------
366
        // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)
367
        
368
        public static $formatInfo = array(
369
            array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
370
            array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
371
            array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
372
            array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
373
        );
374
375
        public static function getFormatInfo($mask, $level)
376
        {
377
            if ($mask < 0 || $mask > 7) {
378
                            return 0;
379
            }
380
                
381
            if ($level < 0 || $level > 3) {
382
                            return 0;
383
            }
384
385
            return self::$formatInfo[$level][$mask];
386
        }
387
388
        // Frame ---------------------------------------------------------------
389
        // Cache of initial frames.
390
         
391
        public static $frames = array();
392
393
        /** --------------------------------------------------------------------
394
         * Put a finder pattern.
395
         * @param frame
396
         * @param width
397
         * @param ox,oy upper-left coordinate of the pattern
0 ignored issues
show
Documentation Bug introduced by
The doc comment upper-left at position 0 could not be parsed: Unknown type name 'upper-left' at position 0 in upper-left.
Loading history...
398
         */
399
        public static function putFinderPattern(&$frame, $ox, $oy)
400
        {
401
            $finder = array(
402
                "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
403
                "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
404
                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
405
                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
406
                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
407
                "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
408
                "\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
409
            );                            
410
            
411
            for ($y = 0; $y < 7; $y++) {
412
                QRstr::set($frame, $ox, $oy + $y, $finder[$y]);
413
            }
414
        }
415
416
        //----------------------------------------------------------------------
417
        public static function createFrame($version)
418
        {
419
            $width = self::$capacity[$version][QRCAP_WIDTH];
420
            $frameLine = str_repeat("\0", $width);
421
            $frame = array_fill(0, $width, $frameLine);
422
423
            // Finder pattern
424
            self::putFinderPattern($frame, 0, 0);
425
            self::putFinderPattern($frame, $width - 7, 0);
426
            self::putFinderPattern($frame, 0, $width - 7);
427
            
428
            // Separator
429
            $yOffset = $width - 7;
430
            
431
            for ($y = 0; $y < 7; $y++) {
432
                $frame[$y][7] = "\xc0";
433
                $frame[$y][$width - 8] = "\xc0";
434
                $frame[$yOffset][7] = "\xc0";
435
                $yOffset++;
436
            }
437
            
438
            $setPattern = str_repeat("\xc0", 8);
439
            
440
            QRstr::set($frame, 0, 7, $setPattern);
441
            QRstr::set($frame, $width - 8, 7, $setPattern);
442
            QRstr::set($frame, 0, $width - 8, $setPattern);
443
        
444
            // Format info
445
            $setPattern = str_repeat("\x84", 9);
446
            QRstr::set($frame, 0, 8, $setPattern);
447
            QRstr::set($frame, $width - 8, 8, $setPattern, 8);
448
            
449
            $yOffset = $width - 8;
450
451
            for ($y = 0; $y < 8; $y++, $yOffset++) {
452
                $frame[$y][8] = "\x84";
453
                $frame[$yOffset][8] = "\x84";
454
            }
455
456
            // Timing pattern  
457
            
458
            for ($i = 1; $i < $width - 15; $i++) {
459
                $frame[6][7 + $i] = chr(0x90 | ($i & 1));
460
                $frame[7 + $i][6] = chr(0x90 | ($i & 1));
461
            }
462
            
463
            // Alignment pattern  
464
            self::putAlignmentPattern($version, $frame, $width);
465
            
466
            // Version information 
467
            if ($version >= 7) {
468
                $vinf = self::getVersionPattern($version);
469
470
                $v = $vinf;
471
                
472
                for ($x = 0; $x < 6; $x++) {
473
                    for ($y = 0; $y < 3; $y++) {
474
                        $frame[($width - 11) + $y][$x] = chr(0x88 | ($v & 1));
475
                        $v = $v >> 1;
476
                    }
477
                }
478
479
                $v = $vinf;
480
                for ($y = 0; $y < 6; $y++) {
481
                    for ($x = 0; $x < 3; $x++) {
482
                        $frame[$y][$x + ($width - 11)] = chr(0x88 | ($v & 1));
483
                        $v = $v >> 1;
484
                    }
485
                }
486
            }
487
    
488
            // and a little bit...  
489
            $frame[$width - 8][8] = "\x81";
490
            
491
            return $frame;
492
        }
493
494
        //----------------------------------------------------------------------
495
        public static function debug($frame, $binary_mode = false)
496
        {
497
            if ($binary_mode) {
498
            
499
                    foreach ($frame as &$frameLine) {
500
                        $frameLine = join('<span class="m">&nbsp;&nbsp;</span>', explode('0', $frameLine));
501
                        $frameLine = join('&#9608;&#9608;', explode('1', $frameLine));
502
                    }
503
                    
504
                    ?>
505
                <style>
506
                    .m { background-color: white; }
507
                </style>
508
                <?php
509
                    echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
510
                    echo join("<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $frame);
511
                    echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
512
            
513
            } else {
514
            
515
                foreach ($frame as &$frameLine) {
516
                    $frameLine = join('<span class="m">&nbsp;</span>', explode("\xc0", $frameLine));
517
                    $frameLine = join('<span class="m">&#9618;</span>', explode("\xc1", $frameLine));
518
                    $frameLine = join('<span class="p">&nbsp;</span>', explode("\xa0", $frameLine));
519
                    $frameLine = join('<span class="p">&#9618;</span>', explode("\xa1", $frameLine));
520
                    $frameLine = join('<span class="s">&#9671;</span>', explode("\x84", $frameLine)); //format 0
521
                    $frameLine = join('<span class="s">&#9670;</span>', explode("\x85", $frameLine)); //format 1
522
                    $frameLine = join('<span class="x">&#9762;</span>', explode("\x81", $frameLine)); //special bit
523
                    $frameLine = join('<span class="c">&nbsp;</span>', explode("\x90", $frameLine)); //clock 0
524
                    $frameLine = join('<span class="c">&#9719;</span>', explode("\x91", $frameLine)); //clock 1
525
                    $frameLine = join('<span class="f">&nbsp;</span>', explode("\x88", $frameLine)); //version
526
                    $frameLine = join('<span class="f">&#9618;</span>', explode("\x89", $frameLine)); //version
527
                    $frameLine = join('&#9830;', explode("\x01", $frameLine));
528
                    $frameLine = join('&#8901;', explode("\0", $frameLine));
529
                }
530
                
531
                ?>
532
                <style>
533
                    .p { background-color: yellow; }
534
                    .m { background-color: #00FF00; }
535
                    .s { background-color: #FF0000; }
536
                    .c { background-color: aqua; }
537
                    .x { background-color: pink; }
538
                    .f { background-color: gold; }
539
                </style>
540
                <?php
541
                echo "<pre><tt>";
542
                echo join("<br/ >", $frame);
543
                echo "</tt></pre>";
544
            
545
            }
546
        }
547
548
        //----------------------------------------------------------------------
549
        public static function serial($frame)
550
        {
551
            return gzcompress(join("\n", $frame), 9);
552
        }
553
        
554
        //----------------------------------------------------------------------
555
        public static function unserial($code)
556
        {
557
            return explode("\n", gzuncompress($code));
558
        }
559
        
560
        //----------------------------------------------------------------------
561
        public static function newFrame($version)
562
        {
563
            if ($version < 1 || $version > QRSPEC_VERSION_MAX) {
564
                            return null;
565
            }
566
567
            if (!isset(self::$frames[$version])) {
568
                
569
                $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
570
                
571
                if (QR_CACHEABLE) {
572
                    if (file_exists($fileName)) {
573
                        self::$frames[$version] = self::unserial(file_get_contents($fileName));
574
                    } else {
575
                        self::$frames[$version] = self::createFrame($version);
576
                        file_put_contents($fileName, self::serial(self::$frames[$version]));
577
                    }
578
                } else {
579
                    self::$frames[$version] = self::createFrame($version);
580
                }
581
            }
582
            
583
            if (is_null(self::$frames[$version])) {
584
                            return null;
585
            }
586
587
            return self::$frames[$version];
588
        }
589
590
        //----------------------------------------------------------------------
591
        public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; }
592
        public static function rsBlockNum1($spec) { return $spec[0]; }
593
        public static function rsDataCodes1($spec) { return $spec[1]; }
594
        public static function rsEccCodes1($spec) { return $spec[2]; }
595
        public static function rsBlockNum2($spec) { return $spec[3]; }
596
        public static function rsDataCodes2($spec) { return $spec[4]; }
597
        public static function rsEccCodes2($spec) { return $spec[2]; }
598
        public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); }
599
        public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; }
600
        
601
    }