QRspec::maximumWords()   A
last analyzed

Complexity

Conditions 5
Paths 7

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 13
nc 7
nop 2
dl 0
loc 21
rs 9.5222
c 0
b 0
f 0
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
namespace tinymeng\code\Gateways\qrcode;
34
35
class QRspec {
36
37
    public static $capacity = array(
38
        array(  0,    0, 0, array(   0,    0,    0,    0)),
39
        array( 21,   26, 0, array(   7,   10,   13,   17)), // 1
40
        array( 25,   44, 7, array(  10,   16,   22,   28)),
41
        array( 29,   70, 7, array(  15,   26,   36,   44)),
42
        array( 33,  100, 7, array(  20,   36,   52,   64)),
43
        array( 37,  134, 7, array(  26,   48,   72,   88)), // 5
44
        array( 41,  172, 7, array(  36,   64,   96,  112)),
45
        array( 45,  196, 0, array(  40,   72,  108,  130)),
46
        array( 49,  242, 0, array(  48,   88,  132,  156)),
47
        array( 53,  292, 0, array(  60,  110,  160,  192)),
48
        array( 57,  346, 0, array(  72,  130,  192,  224)), //10
49
        array( 61,  404, 0, array(  80,  150,  224,  264)),
50
        array( 65,  466, 0, array(  96,  176,  260,  308)),
51
        array( 69,  532, 0, array( 104,  198,  288,  352)),
52
        array( 73,  581, 3, array( 120,  216,  320,  384)),
53
        array( 77,  655, 3, array( 132,  240,  360,  432)), //15
54
        array( 81,  733, 3, array( 144,  280,  408,  480)),
55
        array( 85,  815, 3, array( 168,  308,  448,  532)),
56
        array( 89,  901, 3, array( 180,  338,  504,  588)),
57
        array( 93,  991, 3, array( 196,  364,  546,  650)),
58
        array( 97, 1085, 3, array( 224,  416,  600,  700)), //20
59
        array(101, 1156, 4, array( 224,  442,  644,  750)),
60
        array(105, 1258, 4, array( 252,  476,  690,  816)),
61
        array(109, 1364, 4, array( 270,  504,  750,  900)),
62
        array(113, 1474, 4, array( 300,  560,  810,  960)),
63
        array(117, 1588, 4, array( 312,  588,  870, 1050)), //25
64
        array(121, 1706, 4, array( 336,  644,  952, 1110)),
65
        array(125, 1828, 4, array( 360,  700, 1020, 1200)),
66
        array(129, 1921, 3, array( 390,  728, 1050, 1260)),
67
        array(133, 2051, 3, array( 420,  784, 1140, 1350)),
68
        array(137, 2185, 3, array( 450,  812, 1200, 1440)), //30
69
        array(141, 2323, 3, array( 480,  868, 1290, 1530)),
70
        array(145, 2465, 3, array( 510,  924, 1350, 1620)),
71
        array(149, 2611, 3, array( 540,  980, 1440, 1710)),
72
        array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
73
        array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35
74
        array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
75
        array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
76
        array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
77
        array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
78
        array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40
79
    );
80
    
81
    //----------------------------------------------------------------------
82
    public static function getDataLength($version, $level)
83
    {
84
        return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
85
    }
86
    
87
    //----------------------------------------------------------------------
88
    public static function getECCLength($version, $level)
89
    {
90
        return self::$capacity[$version][QRCAP_EC][$level];
91
    }
92
    
93
    //----------------------------------------------------------------------
94
    public static function getWidth($version)
95
    {
96
        return self::$capacity[$version][QRCAP_WIDTH];
97
    }
98
    
99
    //----------------------------------------------------------------------
100
    public static function getRemainder($version)
101
    {
102
        return self::$capacity[$version][QRCAP_REMINDER];
103
    }
104
    
105
    //----------------------------------------------------------------------
106
    public static function getMinimumVersion($size, $level)
107
    {
108
109
        for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) {
110
            $words  = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
111
            if($words >= $size) 
112
                return $i;
113
        }
114
115
        return -1;
116
    }
117
118
    //######################################################################
119
    
120
    public static $lengthTableBits = array(
121
        array(10, 12, 14),
122
        array( 9, 11, 13),
123
        array( 8, 16, 16),
124
        array( 8, 10, 12)
125
    );
126
    
127
    //----------------------------------------------------------------------
128
    public static function lengthIndicator($mode, $version)
129
    {
130
        if ($mode == QR_MODE_STRUCTURE)
131
            return 0;
132
            
133
        if ($version <= 9) {
134
            $l = 0;
135
        } else if ($version <= 26) {
136
            $l = 1;
137
        } else {
138
            $l = 2;
139
        }
140
141
        return self::$lengthTableBits[$mode][$l];
142
    }
143
    
144
    //----------------------------------------------------------------------
145
    public static function maximumWords($mode, $version)
146
    {
147
        if($mode == QR_MODE_STRUCTURE) 
148
            return 3;
149
            
150
        if($version <= 9) {
151
            $l = 0;
152
        } else if($version <= 26) {
153
            $l = 1;
154
        } else {
155
            $l = 2;
156
        }
157
158
        $bits = self::$lengthTableBits[$mode][$l];
159
        $words = (1 << $bits) - 1;
160
        
161
        if($mode == QR_MODE_KANJI) {
162
            $words *= 2; // the number of bytes is required
163
        }
164
165
        return $words;
166
    }
167
168
    // Error correction code -----------------------------------------------
169
    // Table of the error correction code (Reed-Solomon block)
170
    // See Table 12-16 (pp.30-36), JIS X0510:2004.
171
172
    public static $eccTable = array(
173
        array(array( 0,  0), array( 0,  0), array( 0,  0), array( 0,  0)),
174
        array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)), // 1
175
        array(array( 1,  0), array( 1,  0), array( 1,  0), array( 1,  0)),
176
        array(array( 1,  0), array( 1,  0), array( 2,  0), array( 2,  0)),
177
        array(array( 1,  0), array( 2,  0), array( 2,  0), array( 4,  0)),
178
        array(array( 1,  0), array( 2,  0), array( 2,  2), array( 2,  2)), // 5
179
        array(array( 2,  0), array( 4,  0), array( 4,  0), array( 4,  0)),
180
        array(array( 2,  0), array( 4,  0), array( 2,  4), array( 4,  1)),
181
        array(array( 2,  0), array( 2,  2), array( 4,  2), array( 4,  2)),
182
        array(array( 2,  0), array( 3,  2), array( 4,  4), array( 4,  4)),
183
        array(array( 2,  2), array( 4,  1), array( 6,  2), array( 6,  2)), //10
184
        array(array( 4,  0), array( 1,  4), array( 4,  4), array( 3,  8)),
185
        array(array( 2,  2), array( 6,  2), array( 4,  6), array( 7,  4)),
186
        array(array( 4,  0), array( 8,  1), array( 8,  4), array(12,  4)),
187
        array(array( 3,  1), array( 4,  5), array(11,  5), array(11,  5)),
188
        array(array( 5,  1), array( 5,  5), array( 5,  7), array(11,  7)), //15
189
        array(array( 5,  1), array( 7,  3), array(15,  2), array( 3, 13)),
190
        array(array( 1,  5), array(10,  1), array( 1, 15), array( 2, 17)),
191
        array(array( 5,  1), array( 9,  4), array(17,  1), array( 2, 19)),
192
        array(array( 3,  4), array( 3, 11), array(17,  4), array( 9, 16)),
193
        array(array( 3,  5), array( 3, 13), array(15,  5), array(15, 10)), //20
194
        array(array( 4,  4), array(17,  0), array(17,  6), array(19,  6)),
195
        array(array( 2,  7), array(17,  0), array( 7, 16), array(34,  0)),
196
        array(array( 4,  5), array( 4, 14), array(11, 14), array(16, 14)),
197
        array(array( 6,  4), array( 6, 14), array(11, 16), array(30,  2)),
198
        array(array( 8,  4), array( 8, 13), array( 7, 22), array(22, 13)), //25
199
        array(array(10,  2), array(19,  4), array(28,  6), array(33,  4)),
200
        array(array( 8,  4), array(22,  3), array( 8, 26), array(12, 28)),
201
        array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
202
        array(array( 7,  7), array(21,  7), array( 1, 37), array(19, 26)),
203
        array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
204
        array(array(13,  3), array( 2, 29), array(42,  1), array(23, 28)),
205
        array(array(17,  0), array(10, 23), array(10, 35), array(19, 35)),
206
        array(array(17,  1), array(14, 21), array(29, 19), array(11, 46)),
207
        array(array(13,  6), array(14, 23), array(44,  7), array(59,  1)),
208
        array(array(12,  7), array(12, 26), array(39, 14), array(22, 41)), //35
209
        array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
210
        array(array(17,  4), array(29, 14), array(49, 10), array(24, 46)),
211
        array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
212
        array(array(20,  4), array(40,  7), array(43, 22), array(10, 67)),
213
        array(array(19,  6), array(18, 31), array(34, 34), array(20, 61)),//40
214
    );                                                                       
215
216
    //----------------------------------------------------------------------
217
    // CACHEABLE!!!
218
    
219
    public static function getEccSpec($version, $level, array &$spec)
220
    {
221
        if (count($spec) < 5) {
222
            $spec = array(0,0,0,0,0);
223
        }
224
225
        $b1   = self::$eccTable[$version][$level][0];
226
        $b2   = self::$eccTable[$version][$level][1];
227
        $data = self::getDataLength($version, $level);
228
        $ecc  = self::getECCLength($version, $level);
229
230
        if($b2 == 0) {
231
            $spec[0] = $b1;
232
            $spec[1] = (int)($data / $b1);
233
            $spec[2] = (int)($ecc / $b1);
234
            $spec[3] = 0; 
235
            $spec[4] = 0;
236
        } else {
237
            $spec[0] = $b1;
238
            $spec[1] = (int)($data / ($b1 + $b2));
239
            $spec[2] = (int)($ecc  / ($b1 + $b2));
240
            $spec[3] = $b2;
241
            $spec[4] = $spec[1] + 1;
242
        }
243
    }
244
245
    // Alignment pattern ---------------------------------------------------
246
247
    // Positions of alignment patterns.
248
    // This array includes only the second and the third position of the 
249
    // alignment patterns. Rest of them can be calculated from the distance 
250
    // between them.
251
     
252
    // See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
253
     
254
    public static $alignmentPattern = array(      
255
        array( 0,  0),
256
        array( 0,  0), array(18,  0), array(22,  0), array(26,  0), array(30,  0), // 1- 5
257
        array(34,  0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10
258
        array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15
259
        array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20
260
        array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
261
        array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
262
        array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
263
        array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40
264
    );                                                                                  
265
266
    
267
    /** --------------------------------------------------------------------
268
     * Put an alignment marker.
269
     * @param frame
270
     * @param width
271
     * @param ox,oy center coordinate of the pattern
0 ignored issues
show
Bug introduced by
The type tinymeng\code\Gateways\qrcode\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...
272
     */
273
    public static function putAlignmentMarker(array &$frame, $ox, $oy)
274
    {
275
        $finder = array(
276
            "\xa1\xa1\xa1\xa1\xa1",
277
            "\xa1\xa0\xa0\xa0\xa1",
278
            "\xa1\xa0\xa1\xa0\xa1",
279
            "\xa1\xa0\xa0\xa0\xa1",
280
            "\xa1\xa1\xa1\xa1\xa1"
281
        );                        
282
        
283
        $yStart = $oy-2;         
284
        $xStart = $ox-2;
285
        
286
        for($y=0; $y<5; $y++) {
287
            QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]);
288
        }
289
    }
290
291
    //----------------------------------------------------------------------
292
    public static function putAlignmentPattern($version, &$frame, $width)
293
    {
294
        if($version < 2)
295
            return;
296
297
        $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
298
        if($d < 0) {
299
            $w = 2;
300
        } else {
301
            $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2);
302
        }
303
304
        if($w * $w - 3 == 1) {
305
            $x = self::$alignmentPattern[$version][0];
306
            $y = self::$alignmentPattern[$version][0];
307
            self::putAlignmentMarker($frame, $x, $y);
308
            return;
309
        }
310
311
        $cx = self::$alignmentPattern[$version][0];
312
        for($x=1; $x<$w - 1; $x++) {
313
            self::putAlignmentMarker($frame, 6, $cx);
314
            self::putAlignmentMarker($frame, $cx,  6);
315
            $cx += $d;
316
        }
317
318
        $cy = self::$alignmentPattern[$version][0];
319
        for($y=0; $y<$w-1; $y++) {
320
            $cx = self::$alignmentPattern[$version][0];
321
            for($x=0; $x<$w-1; $x++) {
322
                self::putAlignmentMarker($frame, $cx, $cy);
323
                $cx += $d;
324
            }
325
            $cy += $d;
326
        }
327
    }
328
329
    // Version information pattern -----------------------------------------
330
331
    // Version information pattern (BCH coded).
332
    // See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
333
    
334
    // size: [QRSPEC_VERSION_MAX - 6]
335
    
336
    public static $versionPattern = array(
337
        0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
338
        0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
339
        0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
340
        0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
341
        0x27541, 0x28c69
342
    );
343
344
    //----------------------------------------------------------------------
345
    public static function getVersionPattern($version)
346
    {
347
        if($version < 7 || $version > QRSPEC_VERSION_MAX)
348
            return 0;
349
350
        return self::$versionPattern[$version -7];
351
    }
352
353
    // Format information --------------------------------------------------
354
    // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)
355
    
356
    public static $formatInfo = array(
357
        array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
358
        array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
359
        array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
360
        array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
361
    );
362
363
    public static function getFormatInfo($mask, $level)
364
    {
365
        if($mask < 0 || $mask > 7)
366
            return 0;
367
            
368
        if($level < 0 || $level > 3)
369
            return 0;                
370
371
        return self::$formatInfo[$level][$mask];
372
    }
373
374
    // Frame ---------------------------------------------------------------
375
    // Cache of initial frames.
376
     
377
    public static $frames = array();
378
379
    /** --------------------------------------------------------------------
380
     * Put a finder pattern.
381
     * @param frame
382
     * @param width
383
     * @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...
384
     */
385
    public static function putFinderPattern(&$frame, $ox, $oy)
386
    {
387
        $finder = array(
388
            "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
389
            "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
390
            "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
391
            "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
392
            "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
393
            "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
394
            "\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
395
        );                            
396
        
397
        for($y=0; $y<7; $y++) {
398
            QRstr::set($frame, $ox, $oy+$y, $finder[$y]);
399
        }
400
    }
401
402
    //----------------------------------------------------------------------
403
    public static function createFrame($version)
404
    {
405
        $width = self::$capacity[$version][QRCAP_WIDTH];
406
        $frameLine = str_repeat ("\0", $width);
407
        $frame = array_fill(0, $width, $frameLine);
408
409
        // Finder pattern
410
        self::putFinderPattern($frame, 0, 0);
411
        self::putFinderPattern($frame, $width - 7, 0);
412
        self::putFinderPattern($frame, 0, $width - 7);
413
        
414
        // Separator
415
        $yOffset = $width - 7;
416
        
417
        for($y=0; $y<7; $y++) {
418
            $frame[$y][7] = "\xc0";
419
            $frame[$y][$width - 8] = "\xc0";
420
            $frame[$yOffset][7] = "\xc0";
421
            $yOffset++;
422
        }
423
        
424
        $setPattern = str_repeat("\xc0", 8);
425
        
426
        QRstr::set($frame, 0, 7, $setPattern);
427
        QRstr::set($frame, $width-8, 7, $setPattern);
428
        QRstr::set($frame, 0, $width - 8, $setPattern);
429
    
430
        // Format info
431
        $setPattern = str_repeat("\x84", 9);
432
        QRstr::set($frame, 0, 8, $setPattern);
433
        QRstr::set($frame, $width - 8, 8, $setPattern, 8);
434
        
435
        $yOffset = $width - 8;
436
437
        for($y=0; $y<8; $y++,$yOffset++) {
438
            $frame[$y][8] = "\x84";
439
            $frame[$yOffset][8] = "\x84";
440
        }
441
442
        // Timing pattern  
443
        
444
        for($i=1; $i<$width-15; $i++) {
445
            $frame[6][7+$i] = chr(0x90 | ($i & 1));
446
            $frame[7+$i][6] = chr(0x90 | ($i & 1));
447
        }
448
        
449
        // Alignment pattern  
450
        self::putAlignmentPattern($version, $frame, $width);
451
        
452
        // Version information 
453
        if($version >= 7) {
454
            $vinf = self::getVersionPattern($version);
455
456
            $v = $vinf;
457
            
458
            for($x=0; $x<6; $x++) {
459
                for($y=0; $y<3; $y++) {
460
                    $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1));
461
                    $v = $v >> 1;
462
                }
463
            }
464
465
            $v = $vinf;
466
            for($y=0; $y<6; $y++) {
467
                for($x=0; $x<3; $x++) {
468
                    $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1));
469
                    $v = $v >> 1;
470
                }
471
            }
472
        }
473
474
        // and a little bit...  
475
        $frame[$width - 8][8] = "\x81";
476
        
477
        return $frame;
478
    }
479
480
    //----------------------------------------------------------------------
481
    public static function debug($frame, $binary_mode = false)
482
    {
483
        if ($binary_mode) {
484
        
485
                foreach ($frame as &$frameLine) {
486
                    $frameLine = join('<span class="m">&nbsp;&nbsp;</span>', explode('0', $frameLine));
487
                    $frameLine = join('&#9608;&#9608;', explode('1', $frameLine));
488
                }
489
                
490
                ?>
491
            <style>
492
                .m { background-color: white; }
493
            </style>
494
            <?php
495
                echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
496
                echo join("<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $frame);
497
                echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
498
        
499
        } else {
500
        
501
            foreach ($frame as &$frameLine) {
502
                $frameLine = join('<span class="m">&nbsp;</span>',  explode("\xc0", $frameLine));
503
                $frameLine = join('<span class="m">&#9618;</span>', explode("\xc1", $frameLine));
504
                $frameLine = join('<span class="p">&nbsp;</span>',  explode("\xa0", $frameLine));
505
                $frameLine = join('<span class="p">&#9618;</span>', explode("\xa1", $frameLine));
506
                $frameLine = join('<span class="s">&#9671;</span>', explode("\x84", $frameLine)); //format 0
507
                $frameLine = join('<span class="s">&#9670;</span>', explode("\x85", $frameLine)); //format 1
508
                $frameLine = join('<span class="x">&#9762;</span>', explode("\x81", $frameLine)); //special bit
509
                $frameLine = join('<span class="c">&nbsp;</span>',  explode("\x90", $frameLine)); //clock 0
510
                $frameLine = join('<span class="c">&#9719;</span>', explode("\x91", $frameLine)); //clock 1
511
                $frameLine = join('<span class="f">&nbsp;</span>',  explode("\x88", $frameLine)); //version
512
                $frameLine = join('<span class="f">&#9618;</span>', explode("\x89", $frameLine)); //version
513
                $frameLine = join('&#9830;', explode("\x01", $frameLine));
514
                $frameLine = join('&#8901;', explode("\0", $frameLine));
515
            }
516
            
517
            ?>
518
            <style>
519
                .p { background-color: yellow; }
520
                .m { background-color: #00FF00; }
521
                .s { background-color: #FF0000; }
522
                .c { background-color: aqua; }
523
                .x { background-color: pink; }
524
                .f { background-color: gold; }
525
            </style>
526
            <?php
527
            echo "<pre><tt>";
528
            echo join("<br/ >", $frame);
529
            echo "</tt></pre>";
530
        
531
        }
532
    }
533
534
    //----------------------------------------------------------------------
535
    public static function serial($frame)
536
    {
537
        return gzcompress(join("\n", $frame), 9);
538
    }
539
    
540
    //----------------------------------------------------------------------
541
    public static function unserial($code)
542
    {
543
        return explode("\n", gzuncompress($code));
544
    }
545
    
546
    //----------------------------------------------------------------------
547
    public static function newFrame($version)
548
    {
549
        if($version < 1 || $version > QRSPEC_VERSION_MAX) 
550
            return null;
551
552
        if(!isset(self::$frames[$version])) {
553
            
554
            $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
555
            
556
            if (QR_CACHEABLE) {
557
                if (file_exists($fileName)) {
558
                    self::$frames[$version] = self::unserial(file_get_contents($fileName));
559
                } else {
560
                    self::$frames[$version] = self::createFrame($version);
561
                    file_put_contents($fileName, self::serial(self::$frames[$version]));
562
                }
563
            } else {
564
                self::$frames[$version] = self::createFrame($version);
565
            }
566
        }
567
        
568
        if(is_null(self::$frames[$version]))
569
            return null;
570
571
        return self::$frames[$version];
572
    }
573
574
    //----------------------------------------------------------------------
575
    public static function rsBlockNum($spec)     { return $spec[0] + $spec[3]; }
576
    public static function rsBlockNum1($spec)    { return $spec[0]; }
577
    public static function rsDataCodes1($spec)   { return $spec[1]; }
578
    public static function rsEccCodes1($spec)    { return $spec[2]; }
579
    public static function rsBlockNum2($spec)    { return $spec[3]; }
580
    public static function rsDataCodes2($spec)   { return $spec[4]; }
581
    public static function rsEccCodes2($spec)    { return $spec[2]; }
582
    public static function rsDataLength($spec)   { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);    }
583
    public static function rsEccLength($spec)    { return ($spec[0] + $spec[3]) * $spec[2]; }
584
    
585
}