]> git.wh0rd.org - tt-rss.git/blame - lib/phpqrcode/qrrscode.php
first stage of headline element handling refactoring
[tt-rss.git] / lib / phpqrcode / qrrscode.php
CommitLineData
fb70f26e
AD
1<?php\r
2/*\r
3 * PHP QR Code encoder\r
4 *\r
5 * Reed-Solomon error correction support\r
6 * \r
7 * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q\r
8 * (libfec is released under the GNU Lesser General Public License.)\r
9 *\r
10 * Based on libqrencode C library distributed under LGPL 2.1\r
11 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>\r
12 *\r
13 * PHP QR Code is distributed under LGPL 3\r
14 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>\r
15 *\r
16 * This library is free software; you can redistribute it and/or\r
17 * modify it under the terms of the GNU Lesser General Public\r
18 * License as published by the Free Software Foundation; either\r
19 * version 3 of the License, or any later version.\r
20 *\r
21 * This library is distributed in the hope that it will be useful,\r
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
24 * Lesser General Public License for more details.\r
25 *\r
26 * You should have received a copy of the GNU Lesser General Public\r
27 * License along with this library; if not, write to the Free Software\r
28 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\r
29 */\r
30 \r
31 class QRrsItem {\r
32 \r
33 public $mm; // Bits per symbol \r
34 public $nn; // Symbols per block (= (1<<mm)-1) \r
35 public $alpha_to = array(); // log lookup table \r
36 public $index_of = array(); // Antilog lookup table \r
37 public $genpoly = array(); // Generator polynomial \r
38 public $nroots; // Number of generator roots = number of parity symbols \r
39 public $fcr; // First consecutive root, index form \r
40 public $prim; // Primitive element, index form \r
41 public $iprim; // prim-th root of 1, index form \r
42 public $pad; // Padding bytes in shortened block \r
43 public $gfpoly;\r
44 \r
45 //----------------------------------------------------------------------\r
46 public function modnn($x)\r
47 {\r
48 while ($x >= $this->nn) {\r
49 $x -= $this->nn;\r
50 $x = ($x >> $this->mm) + ($x & $this->nn);\r
51 }\r
52 \r
53 return $x;\r
54 }\r
55 \r
56 //----------------------------------------------------------------------\r
57 public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)\r
58 {\r
59 // Common code for intializing a Reed-Solomon control block (char or int symbols)\r
60 // Copyright 2004 Phil Karn, KA9Q\r
61 // May be used under the terms of the GNU Lesser General Public License (LGPL)\r
62\r
63 $rs = null;\r
64 \r
65 // Check parameter ranges\r
66 if($symsize < 0 || $symsize > 8) return $rs;\r
67 if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs;\r
68 if($prim <= 0 || $prim >= (1<<$symsize)) return $rs;\r
69 if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values!\r
70 if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding\r
71\r
72 $rs = new QRrsItem();\r
73 $rs->mm = $symsize;\r
74 $rs->nn = (1<<$symsize)-1;\r
75 $rs->pad = $pad;\r
76\r
77 $rs->alpha_to = array_fill(0, $rs->nn+1, 0);\r
78 $rs->index_of = array_fill(0, $rs->nn+1, 0);\r
79 \r
80 // PHP style macro replacement ;)\r
81 $NN =& $rs->nn;\r
82 $A0 =& $NN;\r
83 \r
84 // Generate Galois field lookup tables\r
85 $rs->index_of[0] = $A0; // log(zero) = -inf\r
86 $rs->alpha_to[$A0] = 0; // alpha**-inf = 0\r
87 $sr = 1;\r
88 \r
89 for($i=0; $i<$rs->nn; $i++) {\r
90 $rs->index_of[$sr] = $i;\r
91 $rs->alpha_to[$i] = $sr;\r
92 $sr <<= 1;\r
93 if($sr & (1<<$symsize)) {\r
94 $sr ^= $gfpoly;\r
95 }\r
96 $sr &= $rs->nn;\r
97 }\r
98 \r
99 if($sr != 1){\r
100 // field generator polynomial is not primitive!\r
101 $rs = NULL;\r
102 return $rs;\r
103 }\r
104\r
105 /* Form RS code generator polynomial from its roots */\r
106 $rs->genpoly = array_fill(0, $nroots+1, 0);\r
107 \r
108 $rs->fcr = $fcr;\r
109 $rs->prim = $prim;\r
110 $rs->nroots = $nroots;\r
111 $rs->gfpoly = $gfpoly;\r
112\r
113 /* Find prim-th root of 1, used in decoding */\r
114 for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)\r
115 ; // intentional empty-body loop!\r
116 \r
117 $rs->iprim = (int)($iprim / $prim);\r
118 $rs->genpoly[0] = 1;\r
119 \r
120 for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {\r
121 $rs->genpoly[$i+1] = 1;\r
122\r
123 // Multiply rs->genpoly[] by @**(root + x)\r
124 for ($j = $i; $j > 0; $j--) {\r
125 if ($rs->genpoly[$j] != 0) {\r
126 $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];\r
127 } else {\r
128 $rs->genpoly[$j] = $rs->genpoly[$j-1];\r
129 }\r
130 }\r
131 // rs->genpoly[0] can never be zero\r
132 $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];\r
133 }\r
134 \r
135 // convert rs->genpoly[] to index form for quicker encoding\r
136 for ($i = 0; $i <= $nroots; $i++)\r
137 $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];\r
138\r
139 return $rs;\r
140 }\r
141 \r
142 //----------------------------------------------------------------------\r
143 public function encode_rs_char($data, &$parity)\r
144 {\r
145 $MM =& $this->mm;\r
146 $NN =& $this->nn;\r
147 $ALPHA_TO =& $this->alpha_to;\r
148 $INDEX_OF =& $this->index_of;\r
149 $GENPOLY =& $this->genpoly;\r
150 $NROOTS =& $this->nroots;\r
151 $FCR =& $this->fcr;\r
152 $PRIM =& $this->prim;\r
153 $IPRIM =& $this->iprim;\r
154 $PAD =& $this->pad;\r
155 $A0 =& $NN;\r
156\r
157 $parity = array_fill(0, $NROOTS, 0);\r
158\r
159 for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {\r
160 \r
161 $feedback = $INDEX_OF[$data[$i] ^ $parity[0]];\r
162 if($feedback != $A0) { \r
163 // feedback term is non-zero\r
164 \r
165 // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must\r
166 // always be for the polynomials constructed by init_rs()\r
167 $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);\r
168 \r
169 for($j=1;$j<$NROOTS;$j++) {\r
170 $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];\r
171 }\r
172 }\r
173 \r
174 // Shift \r
175 array_shift($parity);\r
176 if($feedback != $A0) {\r
177 array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);\r
178 } else {\r
179 array_push($parity, 0);\r
180 }\r
181 }\r
182 }\r
183 }\r
184 \r
185 //##########################################################################\r
186 \r
187 class QRrs {\r
188 \r
189 public static $items = array();\r
190 \r
191 //----------------------------------------------------------------------\r
192 public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)\r
193 {\r
194 foreach(self::$items as $rs) {\r
195 if($rs->pad != $pad) continue;\r
196 if($rs->nroots != $nroots) continue;\r
197 if($rs->mm != $symsize) continue;\r
198 if($rs->gfpoly != $gfpoly) continue;\r
199 if($rs->fcr != $fcr) continue;\r
200 if($rs->prim != $prim) continue;\r
201\r
202 return $rs;\r
203 }\r
204\r
205 $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);\r
206 array_unshift(self::$items, $rs);\r
207\r
208 return $rs;\r
209 }\r
210 }