LICENSE 0000644 0000155 0177776 00000002424 12220311324 012013 0 ustar jenkins nogroup Copyright (c) 2013, Tim Düsterhus All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. file.tar 0000644 0000155 0177776 00001224000 12252442157 012450 0 ustar jenkins nogroup lib/ 0000755 0000155 0177776 00000000000 12220311242 011551 5 ustar jenkins nogroup lib/system/ 0000755 0000155 0177776 00000000000 12220313707 013105 5 ustar jenkins nogroup lib/system/api/ 0000755 0000155 0177776 00000000000 12220311242 013646 5 ustar jenkins nogroup lib/system/api/qr/ 0000755 0000155 0177776 00000000000 12220311243 014271 5 ustar jenkins nogroup lib/system/api/qr/autoload_function.php 0000644 0000155 0177776 00000000344 12220311243 020520 0 ustar jenkins nogroup =5.3.3" }, "suggest": { "ext-gd": "to generate QR code images" }, "authors": [ { "name": "Ben Scholzen 'DASPRiD'", "email": "mail@dasprids.de", "homepage": "http://www.dasprids.de", "role": "Developer" } ], "autoload": { "psr-0": { "BaconQrCode": "src/" } } } lib/system/api/qr/.git 0000644 0000155 0177776 00000000073 12220311243 015055 0 ustar jenkins nogroup gitdir: ../../../../../.git/modules/file/lib/system/api/qr lib/system/api/qr/src/ 0000755 0000155 0177776 00000000000 12220311243 015060 5 ustar jenkins nogroup lib/system/api/qr/src/BaconQrCode/ 0000755 0000155 0177776 00000000000 12220311243 017200 5 ustar jenkins nogroup lib/system/api/qr/src/BaconQrCode/Common/ 0000755 0000155 0177776 00000000000 12220311243 020430 5 ustar jenkins nogroup lib/system/api/qr/src/BaconQrCode/Common/ReedSolomonCodec.php 0000644 0000155 0177776 00000035712 12220311243 024335 0 ustar jenkins nogroup 8) { throw new Exception\InvalidArgumentException('Symbol size must be between 0 and 8'); } if ($firstRoot < 0 || $firstRoot >= (1 << $symbolSize)) { throw new Exception\InvalidArgumentException('First root must be between 0 and ' . (1 << $symbolSize)); } if ($numRoots < 0 || $numRoots >= (1 << $symbolSize)) { throw new Exception\InvalidArgumentException('Num roots must be between 0 and ' . (1 << $symbolSize)); } if ($padding < 0 || $padding >= ((1 << $symbolSize) - 1 - $numRoots)) { throw new Exception\InvalidArgumentException('Padding must be between 0 and ' . ((1 << $symbolSize) - 1 - $numRoots)); } $this->symbolSize = $symbolSize; $this->blockSize = (1 << $symbolSize) - 1; $this->padding = $padding; $this->alphaTo = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0)); $this->indexOf = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0)); // Generate galous field lookup table $this->indexOf[0] = $this->blockSize; $this->alphaTo[$this->blockSize] = 0; $sr = 1; for ($i = 0; $i < $this->blockSize; $i++) { $this->indexOf[$sr] = $i; $this->alphaTo[$i] = $sr; $sr <<= 1; if ($sr & (1 << $symbolSize)) { $sr ^= $gfPoly; } $sr &= $this->blockSize; } if ($sr !== 1) { throw new Exception\RuntimeException('Field generator polynomial is not primitive'); } // Form RS code generator polynomial from its roots $this->generatorPoly = SplFixedArray::fromArray(array_fill(0, $numRoots + 1, 0)); $this->firstRoot = $firstRoot; $this->primitive = $primitive; $this->numRoots = $numRoots; // Find prim-th root of 1, used in decoding for ($iPrimitive = 1; ($iPrimitive % $primitive) !== 0; $iPrimitive += $this->blockSize); $this->iPrimitive = intval($iPrimitive / $primitive); $this->generatorPoly[0] = 1; for ($i = 0, $root = $firstRoot * $primitive; $i < $numRoots; $i++, $root += $primitive) { $this->generatorPoly[$i + 1] = 1; for ($j = $i; $j > 0; $j--) { if ($this->generatorPoly[$j] !== 0) { $this->generatorPoly[$j] = $this->generatorPoly[$j - 1] ^ $this->alphaTo[$this->modNn($this->indexOf[$this->generatorPoly[$j]] + $root)]; } else { $this->generatorPoly[$j] = $this->generatorPoly[$j - 1]; } } $this->generatorPoly[$j] = $this->alphaTo[$this->modNn($this->indexOf[$this->generatorPoly[0]] + $root)]; } // Convert generator poly to index form for quicker encoding for ($i = 0; $i <= $numRoots; $i++) { $this->generatorPoly[$i] = $this->indexOf[$this->generatorPoly[$i]]; } } /** * Encodes data and writes result back into parity array. * * @param SplFixedArray $data * @param SplFixedArray $parity * @return void */ public function encode(SplFixedArray $data, SplFixedArray $parity) { for ($i = 0; $i < $this->numRoots; $i++) { $parity[$i] = 0; } $iterations = $this->blockSize - $this->numRoots - $this->padding; for ($i = 0; $i < $iterations; $i++) { $feedback = $this->indexOf[$data[$i] ^ $parity[0]]; if ($feedback !== $this->blockSize) { // Feedback term is non-zero $feedback = $this->modNn($this->blockSize - $this->generatorPoly[$this->numRoots] + $feedback); for ($j = 1; $j < $this->numRoots; $j++) { $parity[$j] = $parity[$j] ^ $this->alphaTo[$this->modNn($feedback + $this->generatorPoly[$this->numRoots - $j])]; } } for ($j = 0; $j < $this->numRoots - 1; $j++) { $parity[$j] = $parity[$j + 1]; } if ($feedback !== $this->blockSize) { $parity[$this->numRoots - 1] = $this->alphaTo[$this->modNn($feedback + $this->generatorPoly[0])]; } else { $parity[$this->numRoots - 1] = 0; } } } /** * Decodes received data. * * @param SplFixedArray $data * @param SplFixedArray|null $erasures * @return null|integer */ public function decode(SplFixedArray $data, SplFixedArray $erasures = null) { // This speeds up the initialization a bit. $numRootsPlusOne = SplFixedArray::fromArray(array_fill(0, $this->numRoots + 1, 0)); $numRoots = SplFixedArray::fromArray(array_fill(0, $this->numRoots, 0)); $lambda = clone $numRootsPlusOne; $b = clone $numRootsPlusOne; $t = clone $numRootsPlusOne; $omega = clone $numRootsPlusOne; $root = clone $numRoots; $loc = clone $numRoots; $numErasures = ($erasures !== null ? count($erasures) : 0); // Form the Syndromes; i.e., evaluate data(x) at roots of g(x) $syndromes = SplFixedArray::fromArray(array_fill(0, $this->numRoots, $data[0])); for ($i = 1; $i < $this->blockSize - $this->padding; $i++) { for ($j = 0; $j < $this->numRoots; $j++) { if ($syndromes[$j] === 0) { $syndromes[$j] = $data[$i]; } else { $syndromes[$j] = $data[$i] ^ $this->alphaTo[ $this->modNn($this->indexOf[$syndromes[$j]] + ($this->firstRoot + $j) * $this->primitive) ]; } } } // Convert syndromes to index form, checking for nonzero conditions $syndromeError = 0; for ($i = 0; $i < $this->numRoots; $i++) { $syndromeError |= $syndromes[$i]; $syndromes[$i] = $this->indexOf[$syndromes[$i]]; } if (!$syndromeError) { // If syndrome is zero, data[] is a codeword and there are no errors // to correct, so return data[] unmodified. return 0; } $lambda[0] = 1; if ($numErasures > 0) { // Init lambda to be the erasure locator polynomial $lambda[1] = $this->alphaTo[$this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[0]))]; for ($i = 1; $i < $numErasures; $i++) { $u = $this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[$i])); for ($j = $i + 1; $j > 0; $j--) { $tmp = $this->indexOf[$lambda[$j - 1]]; if ($tmp !== $this->blockSize) { $lambda[$j] = $lambda[$j] ^ $this->alphaTo[$this->modNn($u + $tmp)]; } } } } for ($i = 0; $i <= $this->numRoots; $i++) { $b[$i] = $this->indexOf[$lambda[$i]]; } // Begin Berlekamp-Massey algorithm to determine error+erasure locator // polynomial $r = $numErasures; $el = $numErasures; while (++$r <= $this->numRoots) { // Compute discrepancy at the r-th step in poly form $discrepancyR = 0; for ($i = 0; $i < $r; $i++) { if ($lambda[$i] !== 0 && $syndromes[$r - $i - 1] !== $this->blockSize) { $discrepancyR ^= $this->alphaTo[$this->modNn($this->indexOf[$lambda[$i]] + $syndromes[$r - $i - 1])]; } } $discrepancyR = $this->indexOf[$discrepancyR]; if ($discrepancyR === $this->blockSize) { $tmp = $b->toArray(); array_unshift($tmp, $this->blockSize); array_pop($tmp); $b = SplFixedArray::fromArray($tmp); } else { $t[0] = $lambda[0]; for ($i = 0; $i < $this->numRoots; $i++) { if ($b[$i] !== $this->blockSize) { $t[$i + 1] = $lambda[$i + 1] ^ $this->alphaTo[$this->modNn($discrepancyR + $b[$i])]; } else { $t[$i + 1] = $lambda[$i + 1]; } } if (2 * $el <= $r + $numErasures - 1) { $el = $r + $numErasures - $el; for ($i = 0; $i <= $this->numRoots; $i++) { $b[$i] = ( $lambda[$i] === 0 ? $this->blockSize : $this->modNn($this->indexOf[$lambda[$i]] - $discrepancyR + $this->blockSize) ); } } else { $tmp = $b->toArray(); array_unshift($tmp, $this->blockSize); array_pop($tmp); $b = SplFixedArray::fromArray($tmp); } $lambda = clone $t; } } // Convert lambda to index form and compute deg(lambda(x)) $degLambda = 0; for ($i = 0; $i <= $this->numRoots; $i++) { $lambda[$i] = $this->indexOf[$lambda[$i]]; if ($lambda[$i] !== $this->blockSize) { $degLambda = $i; } } // Find roots of the error+erasure locator polynomial by Chien search. $reg = clone $lambda; $reg[0] = 0; $count = 0; for ($i = 1, $k = $this->iPrimitive - 1; $i <= $this->blockSize; $i++, $k = $this->modNn($k + $this->iPrimitive)) { $q = 1; for ($j = $degLambda; $j > 0; $j--) { if ($reg[$j] !== $this->blockSize) { $reg[$j] = $this->modNn($reg[$j] + $j); $q ^= $this->alphaTo[$reg[$j]]; } } if ($q !== 0) { // Not a root continue; } // Store root (index-form) and error location number $root[$count] = $i; $loc[$count] = $k; if (++$count === $degLambda) { break; } } if ($degLambda !== $count) { // deg(lambda) unequal to number of roots: uncorreactable error // detected return null; } // Compute err+eras evaluate poly omega(x) = s(x)*lambda(x) (modulo // x**numRoots). In index form. Also find deg(omega). $degOmega = $degLambda - 1; for ($i = 0; $i <= $degOmega; $i++) { $tmp = 0; for ($j = $i; $j >= 0; $j--) { if ($syndromes[$i - $j] !== $this->blockSize && $lambda[$j] !== $this->blockSize) { $tmp ^= $this->alphaTo[$this->modNn($syndromes[$i - $j] + $lambda[$j])]; } } $omega[$i] = $this->indexOf[$tmp]; } // Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = // inv(X(l))**(firstRoot-1) and den = lambda_pr(inv(X(l))) all in poly // form. for ($j = $count - 1; $j >= 0; $j--) { $num1 = 0; for ($i = $degOmega; $i >= 0; $i--) { if ($omega[$i] !== $this->blockSize) { $num1 ^= $this->alphaTo[$this->modNn($omega[$i] + $i * $root[$j])]; } } $num2 = $this->alphaTo[$this->modNn($root[$j] * ($this->firstRoot - 1) + $this->blockSize)]; $den = 0; // lambda[i+1] for i even is the formal derivativelambda_pr of // lambda[i] for ($i = min($degLambda, $this->numRoots - 1) & ~1; $i >= 0; $i -= 2) { if ($lambda[$i + 1] !== $this->blockSize) { $den ^= $this->alphaTo[$this->modNn($lambda[$i + 1] + $i * $root[$j])]; } } // Apply error to data if ($num1 !== 0 && $loc[$j] >= $this->padding) { $data[$loc[$j] - $this->padding] = $data[$loc[$j] - $this->padding] ^ ( $this->alphaTo[ $this->modNn( $this->indexOf[$num1] + $this->indexOf[$num2] + $this->blockSize - $this->indexOf[$den] ) ] ); } } if ($erasures !== null) { if (count($erasures) < $count) { $erasures->setSize($count); } for ($i = 0; $i < $count; $i++) { $erasures[$i] = $loc[$i]; } } return $count; } /** * Computes $x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1, without a slow * divide. * * @param itneger $x * @return integer */ protected function modNn($x) { while ($x >= $this->blockSize) { $x -= $this->blockSize; $x = ($x >> $this->symbolSize) + ($x & $this->blockSize); } return $x; } } lib/system/api/qr/src/BaconQrCode/Common/BitUtils.php 0000644 0000155 0177776 00000002226 12220311243 022702 0 ustar jenkins nogroup >>" in other * languages. * * @param integer $a * @param integer $b * @return integer */ public static function unsignedRightShift($a, $b) { return ( $a >= 0 ? $a >> $b : (($a & 0x7fffffff) >> $b) | (0x40000000 >> ($b - 1)) ); } /** * Gets the number of trailing zeros. * * @param integer $i * @return integer */ public static function numberOfTrailingZeros($i) { $lastPos = strrpos(str_pad(decbin($i), 32, '0', STR_PAD_LEFT), '1'); return $lastPos === false ? 32 : 31 - $lastPos; } } lib/system/api/qr/src/BaconQrCode/Common/BitMatrix.php 0000644 0000155 0177776 00000020333 12220311243 023045 0 ustar jenkins nogroup width = $width; $this->height = $height; $this->rowSize = ($width + 31) >> 5; $this->bits = new SplFixedArray($this->rowSize * $height); } /** * Gets the requested bit, where true means black. * * @param integer $x * @param integer $y * @return boolean */ public function get($x, $y) { $offset = $y * $this->rowSize + ($x >> 5); return (BitUtils::unsignedRightShift($this->bits[$offset], ($x & 0x1f)) & 1) !== 0; } /** * Sets the given bit to true. * * @param integer $x * @param integer $y * @return void */ public function set($x, $y) { $offset = $y * $this->rowSize + ($x >> 5); $this->bits[$offset] = $this->bits[$offset] | (1 << ($x & 0x1f)); } /** * Flips the given bit. * * @param integer $x * @param integer $y * @return void */ public function flip($x, $y) { $offset = $y * $this->rowSize + ($x >> 5); $this->bits[$offset] = $this->bits[$offset] ^ (1 << ($x & 0x1f)); } /** * Clears all bits (set to false). * * @return void */ public function clear() { $max = count($this->bits); for ($i = 0; $i < $max; $i++) { $this->bits[$i] = 0; } } /** * Sets a square region of the bit matrix to true. * * @param integer $left * @param integer $top * @param integer $width * @param integer $height * @return void */ public function setRegion($left, $top, $width, $height) { if ($top < 0 || $left < 0) { throw new Exception\InvalidArgumentException('Left and top must be non-negative'); } if ($height < 1 || $width < 1) { throw new Exception\InvalidArgumentException('Width and height must be at least 1'); } $right = $left + $width; $bottom = $top + $height; if ($bottom > $this->height || $right > $this->width) { throw new Exception\InvalidArgumentException('The region must fit inside the matrix'); } for ($y = $top; $y < $bottom; $y++) { $offset = $y * $this->rowSize; for ($x = $left; $x < $right; $x++) { $index = $offset + ($x >> 5); $this->bits[$index] = $this->bits[$index] | (1 << ($x & 0x1f)); } } } /** * A fast method to retrieve one row of data from the matrix as a BitArray. * * @param integer $y * @param BitArray $row * @return BitArray */ public function getRow($y, BitArray $row = null) { if ($row === null || $row->getSize() < $this->width) { $row = new BitArray($this->width); } $offset = $y * $this->rowSize; for ($x = 0; $x < $this->rowSize; $x++) { $row->setBulk($x << 5, $this->bits[$offset + $x]); } return $row; } /** * Sets a row of data from a BitArray. * * @param integer $y * @param BitArray $row * @return void */ public function setRow($y, BitArray $row) { $bits = $row->getBitArray(); for ($i = 0; $i < $this->rowSize; $i++) { $this->bits[$y * $this->rowSize + $i] = $bits[$i]; } } /** * This is useful in detecting the enclosing rectangle of a 'pure' barcode. * * @return SplFixedArray */ public function getEnclosingRectangle() { $left = $this->width; $top = $this->height; $right = -1; $bottom = -1; for ($y = 0; $y < $this->height; $y++) { for ($x32 = 0; $x32 < $this->rowSize; $x32++) { $bits = $this->bits[$y * $this->rowSize + $x32]; if ($bits !== 0) { if ($y < $top) { $top = $y; } if ($y > $bottom) { $bottom = $y; } if ($x32 * 32 < $left) { $bit = 0; while (($bits << (31 - $bit)) === 0) { $bit++; } if (($x32 * 32 + $bit) < $left) { $left = $x32 * 32 + $bit; } } } if ($x32 * 32 + 31 > $right) { $bit = 31; while (BitUtils::unsignedRightShift($bits, $bit) === 0) { $bit--; } if (($x32 * 32 + $bit) > $right) { $right = $x32 * 32 + $bit; } } } } $width = $right - $left; $height = $bottom - $top; if ($width < 0 || $height < 0) { return null; } return SplFixedArray::fromArray(array($left, $top, $width, $height)); } /** * Gets the most top left set bit. * * This is useful in detecting a corner of a 'pure' barcode. * * @return SplFixedArray */ public function getTopLeftOnBit() { $bitsOffset = 0; while ($bitsOffset < count($this->bits) && $this->bits[$bitsOffset] === 0) { $bitsOffset++; } if ($bitsOffset === count($this->bits)) { return null; } $x = intval($bitsOffset / $this->rowSize); $y = ($bitsOffset % $this->rowSize) << 5; $bits = $this->bits[$bitsOffset]; $bit = 0; while (($bits << (31 - $bit)) === 0) { $bit++; } $x += $bit; return SplFixedArray::fromArray(array($x, $y)); } /** * Gets the most bottom right set bit. * * This is useful in detecting a corner of a 'pure' barcode. * * @return SplFixedArray */ public function getBottomRightOnBit() { $bitsOffset = count($this->bits) - 1; while ($bitsOffset >= 0 && $this->bits[$bitsOffset] === 0) { $bitsOffset--; } if ($bitsOffset < 0) { return null; } $x = intval($bitsOffset / $this->rowSize); $y = ($bitsOffset % $this->rowSize) << 5; $bits = $this->bits[$bitsOffset]; $bit = 0; while (BitUtils::unsignedRightShift($bits, $bit) === 0) { $bit--; } $x += $bit; return SplFixedArray::fromArray(array($x, $y)); } /** * Gets the width of the matrix, * * @return integer */ public function getWidth() { return $this->width; } /** * Gets the height of the matrix. * * @return integer */ public function getHeight() { return $this->height; } } lib/system/api/qr/src/BaconQrCode/Common/ErrorCorrectionLevel.php 0000644 0000155 0177776 00000002201 12220311243 025245 0 ustar jenkins nogroup value) { case self::L: return 0; break; case self::M: return 1; break; case self::Q: return 2; break; case self::H: return 3; break; } } } lib/system/api/qr/src/BaconQrCode/Common/FormatInformation.php 0000644 0000155 0177776 00000014672 12220311243 024611 0 ustar jenkins nogroup ecLevel = new ErrorCorrectionLevel(($formatInfo >> 3) & 0x3); $this->dataMask = $formatInfo & 0x7; } /** * Checks how many bits are different between two integers. * * @param integer $a * @param integer $b * @return integer */ public static function numBitsDiffering($a, $b) { $a ^= $b; return ( self::$bitsSetInHalfByte[$a & 0xf] + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 4) & 0xf)] + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 8) & 0xf)] + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 12) & 0xf)] + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 16) & 0xf)] + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 20) & 0xf)] + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 24) & 0xf)] + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 28) & 0xf)] ); } /** * Decodes format information. * * @param integer $maskedFormatInfo1 * @param integer $maskedFormatInfo2 * @return FormatInformation|null */ public static function decodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2) { $formatInfo = self::doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2); if ($formatInfo !== null) { return $formatInfo; } // Should return null, but, some QR codes apparently do not mask this // info. Try again by actually masking the pattern first. return self::doDecodeFormatInformation( $maskedFormatInfo1 ^ self::FORMAT_INFO_MASK_QR, $maskedFormatInfo2 ^ self::FORMAT_INFO_MASK_QR ); } /** * Internal method for decoding format information. * * @param integer $maskedFormatInfo1 * @param integer $maskedFormatInfo2 * @return FormatInformation|null */ protected static function doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2) { $bestDifference = PHP_INT_MAX; $bestFormatInfo = 0; foreach (self::$formatInfoDecodeLookup as $decodeInfo) { $targetInfo = $decodeInfo[0]; if ($targetInfo === $maskedFormatInfo1 || $targetInfo === $maskedFormatInfo2) { // Found an exact match return new self($decodeInfo[1]); } $bitsDifference = self::numBitsDiffering($maskedFormatInfo1, $targetInfo); if ($bitsDifference < $bestDifference) { $bestFormatInfo = $decodeInfo[1]; $bestDifference = $bitsDifference; } if ($maskedFormatInfo1 !== $maskedFormatInfo2) { // Also try the other option $bitsDifference = self::numBitsDiffering($maskedFormatInfo2, $targetInfo); if ($bitsDifference < $bestDifference) { $bestFormatInfo = $decodeInfo[1]; $bestDifference = $bitsDifference; } } } // Hamming distance of the 32 masked codes is 7, by construction, so // <= 3 bits differing means we found a match. if ($bestDifference <= 3) { return new self($bestFormatInfo); } return null; } /** * Gets the error correction level. * * @return ErrorCorrectionLevel */ public function getErrorCorrectionLevel() { return $this->ecLevel; } /** * Gets the data mask. * * @return integer */ public function getDataMask() { return $this->dataMask; } /** * Hashes the code of the EC level. * * @return integer */ public function hashCode() { return ($this->ecLevel->get() << 3) | $this->dataMask; } /** * Verifies if this instance equals another one. * * @param mixed $other * @return boolean */ public function equals($other) { if (!$other instanceof self) { return false; } return ( $this->ecLevel->get() === $other->getErrorCorrectionLevel()->get() && $this->dataMask === $other->getDataMask() ); } } lib/system/api/qr/src/BaconQrCode/Common/CharacterSetEci.php 0000644 0000155 0177776 00000007564 12220311243 024146 0 ustar jenkins nogroup self::ISO8859_1, 'ISO-8859-2' => self::ISO8859_2, 'ISO-8859-3' => self::ISO8859_3, 'ISO-8859-4' => self::ISO8859_4, 'ISO-8859-5' => self::ISO8859_5, 'ISO-8859-6' => self::ISO8859_6, 'ISO-8859-7' => self::ISO8859_7, 'ISO-8859-8' => self::ISO8859_8, 'ISO-8859-9' => self::ISO8859_9, 'ISO-8859-10' => self::ISO8859_10, 'ISO-8859-11' => self::ISO8859_11, 'ISO-8859-12' => self::ISO8859_12, 'ISO-8859-13' => self::ISO8859_13, 'ISO-8859-14' => self::ISO8859_14, 'ISO-8859-15' => self::ISO8859_15, 'ISO-8859-16' => self::ISO8859_16, 'SHIFT-JIS' => self::SJIS, 'WINDOWS-1250' => self::CP1250, 'WINDOWS-1251' => self::CP1251, 'WINDOWS-1252' => self::CP1252, 'WINDOWS-1256' => self::CP1256, 'UTF-16BE' => self::UNICODE_BIG_UNMARKED, 'UTF-8' => self::UTF8, 'ASCII' => self::ASCII, 'GBK' => self::GB18030, 'EUC-KR' => self::EUC_KR, ); /** * Additional possible values for character sets. * * @var array */ protected $additionalValues = array( self::CP437 => 2, self::ASCII => 170, ); /** * Gets character set ECI by value. * * @param string $name * @return CharacterSetEci|null */ public static function getCharacterSetECIByValue($value) { if ($value < 0 || $value >= 900) { throw new Exception\InvalidArgumentException('Value must be between 0 and 900'); } if (false !== ($key = array_search($value, self::$additionalValues))) { $value = $key; } try { return new self($value); } catch (Exception\UnexpectedValueException $e) { return null; } } /** * Gets character set ECI by name. * * @param string $name * @return CharacterSetEci|null */ public static function getCharacterSetECIByName($name) { $name = strtoupper($name); if (isset(self::$nameToEci[$name])) { return new self(self::$nameToEci[$name]); } return null; } } lib/system/api/qr/src/BaconQrCode/Common/Mode.php 0000644 0000155 0177776 00000003771 12220311243 022035 0 ustar jenkins nogroup array(0, 0, 0), self::NUMERIC => array(10, 12, 14), self::ALPHANUMERIC => array(9, 11, 13), self::STRUCTURED_APPEND => array(0, 0, 0), self::BYTE => array(8, 16, 16), self::ECI => array(0, 0, 0), self::KANJI => array(8, 10, 12), self::FNC1_FIRST_POSITION => array(0, 0, 0), self::FNC1_SECOND_POSITION => array(0, 0, 0), self::HANZI => array(8, 10, 12), ); /** * Gets the number of bits used in a specific QR code version. * * @param Version $version * @return integer */ public function getCharacterCountBits(Version $version) { $number = $version->getVersionNumber(); if ($number <= 9) { $offset = 0; } elseif ($number <= 26) { $offset = 1; } else { $offset = 2; } return self::$characterCountBitsForVersions[$this->value][$offset]; } } lib/system/api/qr/src/BaconQrCode/Common/BitArray.php 0000644 0000155 0177776 00000023235 12220311243 022663 0 ustar jenkins nogroup size = $size; $this->bits = new SplFixedArray(($this->size + 31) >> 3); } /** * Gets the size in bits. * * @return integer */ public function getSize() { return $this->size; } /** * Gets the size in bytes. * * @return integer */ public function getSizeInBytes() { return ($this->size + 7) >> 3; } /** * Ensures that the array has a minimum capacity. * * @param integer $size * @return void */ public function ensureCapacity($size) { if ($size > count($this->bits) << 5) { $this->bits->setSize(($size + 31) >> 5); } } /** * Gets a specific bit. * * @param integer $i * @return boolean */ public function get($i) { return ($this->bits[$i >> 5] & (1 << ($i & 0x1f))) !== 0; } /** * Sets a specific bit. * * @param integer $i * @return void */ public function set($i) { $this->bits[$i >> 5] = $this->bits[$i >> 5] | 1 << ($i & 0x1f); } /** * Flips a specific bit. * * @param integer $i * @return void */ public function flip($i) { $this->bits[$i >> 5] ^= 1 << ($i & 0x1f); } /** * Gets the next set bit position from a given position. * * @param integer $from * @return integer */ public function getNextSet($from) { if ($from >= $this->size) { return $this->size; } $bitsOffset = $from >> 5; $currentBits = $this->bits[$bitsOffset]; $bitsLength = count($this->bits); $currentBits &= ~((1 << ($from & 0x1f)) - 1); while ($currentBits === 0) { if (++$bitsOffset === $bitsLength) { return $this->size; } $currentBits = $this->bits[$bitsOffset]; } $result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits); return $result > $this->size ? $this->size : $result; } /** * Gets the next unset bit position from a given position. * * @param integer $from * @return integer */ public function getNextUnset($from) { if ($from >= $this->size) { return $this->size; } $bitsOffset = $from >> 5; $currentBits = ~$this->bits[$bitsOffset]; $bitsLength = count($this->bits); $currentBits &= ~((1 << ($from & 0x1f)) - 1); while ($currentBits === 0) { if (++$bitsOffset === $bitsLength) { return $this->size; } $currentBits = ~$this->bits[$bitsOffset]; } $result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits); return $result > $this->size ? $this->size : $result; } /** * Sets a bulk of bits. * * @param integer $i * @param integer $newBits * @return void */ public function setBulk($i, $newBits) { $this->bits[$i >> 5] = $newBits; } /** * Sets a range of bits. * * @param integer $start * @param integer $end * @return void * @throws Exception\InvalidArgumentException */ public function setRange($start, $end) { if ($end < $start) { throw new Exception\InvalidArgumentException('End must be greater or equal to start'); } if ($end === $start) { return; } $end--; $firstInt = $start >> 5; $lastInt = $end >> 5; for ($i = $firstInt; $i <= $lastInt; $i++) { $firstBit = $i > $firstInt ? 0 : $start & 0x1f; $lastBit = $i < $lastInt ? 31 : $end & 0x1f; if ($firstBit === 0 && $lastBit === 31) { $mask = 0x7fffffff; } else { $mask = 0; for ($j = $firstBit; $j < $lastBit; $j++) { $mask |= 1 << $j; } } $this->bits[$i] = $this->bits[$i] | $mask; } } /** * Clears the bit array, unsetting every bit. * * @return void */ public function clear() { $bitsLength = count($this->bits); for ($i = 0; $i < $bitsLength; $i++) { $this->bits[$i] = 0; } } /** * Checks if a range of bits is set or not set. * * @param integer $start * @param integer $end * @param integer $value * @return boolean * @throws Exception\InvalidArgumentException */ public function isRange($start, $end, $value) { if ($end < $start) { throw new Exception\InvalidArgumentException('End must be greater or equal to start'); } if ($end === $start) { return; } $end--; $firstInt = $start >> 5; $lastInt = $end >> 5; for ($i = $firstInt; $i <= $lastInt; $i++) { $firstBit = $i > $firstInt ? 0 : $start & 0x1f; $lastBit = $i < $lastInt ? 31 : $end & 0x1f; if ($firstBit === 0 && $lastBit === 31) { $mask = 0x7fffffff; } else { $mask = 0; for ($j = $firstBit; $j <= $lastBit; $j++) { $mask |= 1 << $j; } } if (($this->bits[$i] & $mask) !== ($value ? $mask : 0)) { return false; } } return true; } /** * Appends a bit to the array. * * @param boolean $bit * @return void */ public function appendBit($bit) { $this->ensureCapacity($this->size + 1); if ($bit) { $this->bits[$this->size >> 5] = $this->bits[$this->size >> 5] | (1 << ($this->size & 0x1f)); } $this->size++; } /** * Appends a number of bits (up to 32) to the array. * * @param integer $value * @param integer $numBits * @return void * @throws Exception\InvalidArgumentException */ public function appendBits($value, $numBits) { if ($numBits < 0 || $numBits > 32) { throw new Exception\InvalidArgumentException('Num bits must be between 0 and 32'); } $this->ensureCapacity($this->size + $numBits); for ($numBitsLeft = $numBits; $numBitsLeft > 0; $numBitsLeft--) { $this->appendBit((($value >> ($numBitsLeft - 1)) & 0x01) === 1); } } /** * Appends another bit array to this array. * * @param BitArray $other * @return void */ public function appendBitArray(self $other) { $otherSize = $other->getSize(); $this->ensureCapacity($this->size + $other->getSize()); for ($i = 0; $i < $otherSize; $i++) { $this->appendBit($other->get($i)); } } /** * Makes an exclusive-or comparision on the current bit array. * * @param BitArray $other * @return void * @throws Exception\InvalidArgumentException */ public function xorBits(self $other) { $bitsLength = count($this->bits); $otherBits = $other->getBitArray(); if ($bitsLength !== count($otherBits)) { throw new Exception\InvalidArgumentException('Sizes don\'t match'); } for ($i = 0; $i < $bitsLength; $i++) { $this->bits[$i] = $this->bits[$i] ^ $otherBits[$i]; } } /** * Converts the bit array to a byte array. * * @param integer $bitOffset * @param integer $numBytes * @return SplFixedArray */ public function toBytes($bitOffset, $numBytes) { $bytes = new SplFixedArray($numBytes); for ($i = 0; $i < $numBytes; $i++) { $byte = 0; for ($j = 0; $j < 8; $j++) { if ($this->get($bitOffset)) { $byte |= 1 << (7 - $j); } $bitOffset++; } $bytes[$i] = $byte; } return $bytes; } /** * Gets the internal bit array. * * @return SplFixedArray */ public function getBitArray() { return $this->bits; } /** * Reverses the array. * * @return void */ public function reverse() { $newBits = new SplFixedArray(count($this->bits)); for ($i = 0; $i < $this->size; $i++) { if ($this->get($this->size - $i - 1)) { $newBits[$i >> 5] = $newBits[$i >> 5] | (1 << ($i & 0x1f)); } } $this->bits = newBits; } /** * Returns a string representation of the bit array. * * @return string */ public function __toString() { $result = ''; for ($i = 0; $i < $this->size; $i++) { if (($i & 0x07) === 0) { $result .= ' '; } $result .= $this->get($i) ? 'X' : '.'; } return $result; } } lib/system/api/qr/src/BaconQrCode/Common/Version.php 0000644 0000155 0177776 00000062054 12220311243 022575 0 ustar jenkins nogroup versionNumber = $versionNumber; $this->alignmentPatternCenters = $alignmentPatternCenters; $this->errorCorrectionBlocks = $ecBlocks; $totalCodewords = 0; $ecCodewords = $ecBlocks[0]->getEcCodewordsPerBlock(); foreach ($ecBlocks[0]->getEcBlocks() as $ecBlock) { $totalCodewords += $ecBlock->getCount() * ($ecBlock->getDataCodewords() + $ecCodewords); } $this->totalCodewords = $totalCodewords; } /** * Gets the version number. * * @return integer */ public function getVersionNumber() { return $this->versionNumber; } /** * Gets the alignment pattern centers. * * @return SplFixedArray */ public function getAlignmentPatternCenters() { return $this->alignmentPatternCenters; } /** * Gets the total number of codewords. * * @return integer */ public function getTotalCodewords() { return $this->totalCodewords; } /** * Gets the dimension for the current version. * * @return integer */ public function getDimensionForVersion() { return 17 + 4 * $this->versionNumber; } /** * Gets the number of EC blocks for a specific EC level. * * @param ErrorCorrectionLevel $ecLevel * @return integer */ public function getEcBlocksForLevel(ErrorCorrectionLevel $ecLevel) { return $this->errorCorrectionBlocks[$ecLevel->getOrdinal()]; } /** * Gets a provisional version number for a specific dimension. * * @param integer $dimension * @return Version * @throws Exception\InvalidArgumentException */ public static function getProvisionalVersionForDimension($dimension) { if ($dimension % 4 !== 1) { throw new Exception\InvalidArgumentException('Dimension is not 1 mod 4'); } return self::getVersionForNumber(($dimension - 17) >> 2); } /** * Gets a version instance for a specific version number. * * @param integer $versionNumber * @return Version * @throws Exception\InvalidArgumentException */ public static function getVersionForNumber($versionNumber) { if ($versionNumber < 1 || $versionNumber > 40) { throw new Exception\InvalidArgumentException('Version number must be between 1 and 40'); } if (!isset(self::$versions[$versionNumber])) { self::buildVersion($versionNumber); } return self::$versions[$versionNumber - 1]; } /** * Decodes version information from an integer and returns the version. * * @param integer $versionBits * @return Version|null */ public static function decodeVersionInformation($versionBits) { $bestDifference = PHP_INT_MAX; $bestVersion = 0; foreach (self::$versionDecodeInfo as $i => $targetVersion) { if ($targetVersion === $versionBits) { return self::getVersionForNumber($i + 7); } $bitsDifference = FormatInformation::numBitsDiffering($versionBits, $targetVersion); if ($bitsDifference < $bestDifference) { $bestVersion = $i + 7; $bestDifference = $bitsDifference; } } if ($bestDifference <= 3) { return self::getVersionForNumber($bestVersion); } return null; } /** * Builds the function pattern for the current version. * * @return BitMatrix */ public function buildFunctionPattern() { $dimension = $this->getDimensionForVersion(); $bitMatrix = new BitMatrix($dimension); // Top left finder pattern + separator + format $bitMatrix->setRegion(0, 0, 9, 9); // Top right finder pattern + separator + format $bitMatrix->setRegion($dimension - 8, 0, 8, 9); // Bottom left finder pattern + separator + format $bitMatrix->setRegion(0, $dimension - 8, 9, 8); // Alignment patterns $max = count($this->alignmentPatternCenters); for ($x = 0; $x < $max; $x++) { $i = $this->alignmentPatternCenters[$x] - 2; for ($y = 0; $y < $max; $y++) { if (($x === 0 && ($y === 0 || $y === $max - 1)) || ($x === $max - 1 && $y === 0)) { // No alignment patterns near the three finder paterns continue; } $bitMatrix->setRegion($this->alignmentPatternCenters[$y] - 2, $i, 5, 5); } } // Vertical timing pattern $bitMatrix->setRegion(6, 9, 1, $dimension - 17); // Horizontal timing pattern $bitMatrix->setRegion(9, 6, $dimension - 17, 1); if ($this->versionNumber > 6) { // Version info, top right $bitMatrix->setRegion($dimension - 11, 0, 3, 6); // Version info, bottom left $bitMatrix->setRegion(0, $dimension - 11, 6, 3); } return $bitMatrix; } /** * Returns a string representation for the version. * * @return string */ public function __toString() { return (string) $this->versionNumber; } /** * Build and cache a specific version. * * See ISO 18004:2006 6.5.1 Table 9. * * @param integer $versionNumber * @return void */ protected static function buildVersion($versionNumber) { switch ($versionNumber) { case 1: $patterns = array(); $ecBlocks = array( new EcBlocks(7, new EcBlock(1, 19)), new EcBlocks(10, new EcBlock(1, 16)), new EcBlocks(13, new EcBlock(1, 13)), new EcBlocks(17, new EcBlock(1, 9)), ); break; case 2: $patterns = array(6, 18); $ecBlocks = array( new EcBlocks(10, new EcBlock(1, 34)), new EcBlocks(16, new EcBlock(1, 28)), new EcBlocks(22, new EcBlock(1, 22)), new EcBlocks(28, new EcBlock(1, 16)), ); break; case 3: $patterns = array(6, 22); $ecBlocks = array( new EcBlocks(15, new EcBlock(1, 55)), new EcBlocks(26, new EcBlock(1, 44)), new EcBlocks(18, new EcBlock(2, 17)), new EcBlocks(22, new EcBlock(2, 13)), ); break; case 4: $patterns = array(6, 26); $ecBlocks = array( new EcBlocks(20, new EcBlock(1, 80)), new EcBlocks(18, new EcBlock(2, 32)), new EcBlocks(26, new EcBlock(3, 24)), new EcBlocks(16, new EcBlock(4, 9)), ); break; case 5: $patterns = array(6, 30); $ecBlocks = array( new EcBlocks(26, new EcBlock(1, 108)), new EcBlocks(24, new EcBlock(2, 43)), new EcBlocks(18, new EcBlock(2, 15), new EcBlock(2, 16)), new EcBlocks(22, new EcBlock(2, 11), new EcBlock(2, 12)), ); break; case 6: $patterns = array(6, 34); $ecBlocks = array( new EcBlocks(18, new EcBlock(2, 68)), new EcBlocks(16, new EcBlock(4, 27)), new EcBlocks(24, new EcBlock(4, 19)), new EcBlocks(28, new EcBlock(4, 15)), ); break; case 7: $patterns = array(6, 22, 38); $ecBlocks = array( new EcBlocks(20, new EcBlock(2, 78)), new EcBlocks(18, new EcBlock(4, 31)), new EcBlocks(18, new EcBlock(2, 14), new EcBlock(4, 15)), new EcBlocks(26, new EcBlock(4, 13)), ); break; case 8: $patterns = array(6, 24, 42); $ecBlocks = array( new EcBlocks(24, new EcBlock(2, 97)), new EcBlocks(22, new EcBlock(2, 38), new EcBlock(2, 39)), new EcBlocks(22, new EcBlock(4, 18), new EcBlock(2, 19)), new EcBlocks(26, new EcBlock(4, 14), new EcBlock(2, 15)), ); break; case 9: $patterns = array(6, 26, 46); $ecBlocks = array( new EcBlocks(30, new EcBlock(2, 116)), new EcBlocks(22, new EcBlock(3, 36), new EcBlock(2, 37)), new EcBlocks(20, new EcBlock(4, 16), new EcBlock(4, 17)), new EcBlocks(24, new EcBlock(4, 12), new EcBlock(4, 13)), ); break; case 10: $patterns = array(6, 28, 50); $ecBlocks = array( new EcBlocks(18, new EcBlock(2, 68), new EcBlock(2, 69)), new EcBlocks(26, new EcBlock(4, 43), new EcBlock(1, 44)), new EcBlocks(24, new EcBlock(6, 19), new EcBlock(2, 20)), new EcBlocks(28, new EcBlock(6, 15), new EcBlock(2, 16)), ); break; case 11: $patterns = array(6, 30, 54); $ecBlocks = array( new EcBlocks(20, new EcBlock(4, 81)), new EcBlocks(30, new EcBlock(1, 50), new EcBlock(4, 51)), new EcBlocks(28, new EcBlock(4, 22), new EcBlock(4, 23)), new EcBlocks(24, new EcBlock(3, 12), new EcBlock(8, 13)), ); break; case 12: $patterns = array(6, 32, 58); $ecBlocks = array( new EcBlocks(24, new EcBlock(2, 92), new EcBlock(2, 93)), new EcBlocks(22, new EcBlock(6, 36), new EcBlock(2, 37)), new EcBlocks(26, new EcBlock(4, 20), new EcBlock(6, 21)), new EcBlocks(28, new EcBlock(7, 14), new EcBlock(4, 15)), ); break; case 13: $patterns = array(6, 34, 62); $ecBlocks = array( new EcBlocks(26, new EcBlock(4, 107)), new EcBlocks(22, new EcBlock(8, 37), new EcBlock(1, 38)), new EcBlocks(24, new EcBlock(8, 20), new EcBlock(4, 21)), new EcBlocks(22, new EcBlock(12, 11), new EcBlock(4, 12)), ); break; case 14: $patterns = array(6, 26, 46, 66); $ecBlocks = array( new EcBlocks(30, new EcBlock(3, 115), new EcBlock(1, 116)), new EcBlocks(24, new EcBlock(4, 40), new EcBlock(5, 41)), new EcBlocks(20, new EcBlock(11, 16), new EcBlock(5, 17)), new EcBlocks(24, new EcBlock(11, 12), new EcBlock(5, 13)), ); break; case 15: $patterns = array(6, 26, 48, 70); $ecBlocks = array( new EcBlocks(22, new EcBlock(5, 87), new EcBlock(1, 88)), new EcBlocks(24, new EcBlock(5, 41), new EcBlock(5, 42)), new EcBlocks(30, new EcBlock(5, 24), new EcBlock(7, 25)), new EcBlocks(24, new EcBlock(11, 12), new EcBlock(7, 13)), ); break; case 16: $patterns = array(6, 26, 50, 74); $ecBlocks = array( new EcBlocks(24, new EcBlock(5, 98), new EcBlock(1, 99)), new EcBlocks(28, new EcBlock(7, 45), new EcBlock(3, 46)), new EcBlocks(24, new EcBlock(15, 19), new EcBlock(2, 20)), new EcBlocks(30, new EcBlock(3, 15), new EcBlock(13, 16)), ); break; case 17: $patterns = array(6, 30, 54, 78); $ecBlocks = array( new EcBlocks(28, new EcBlock(1, 107), new EcBlock(5, 108)), new EcBlocks(28, new EcBlock(10, 46), new EcBlock(1, 47)), new EcBlocks(28, new EcBlock(1, 22), new EcBlock(15, 23)), new EcBlocks(28, new EcBlock(2, 14), new EcBlock(17, 15)), ); break; case 18: $patterns = array(6, 30, 56, 82); $ecBlocks = array( new EcBlocks(30, new EcBlock(5, 120), new EcBlock(1, 121)), new EcBlocks(26, new EcBlock(9, 43), new EcBlock(4, 44)), new EcBlocks(28, new EcBlock(17, 22), new EcBlock(1, 23)), new EcBlocks(28, new EcBlock(2, 14), new EcBlock(19, 15)), ); break; case 19: $patterns = array(6, 30, 58, 86); $ecBlocks = array( new EcBlocks(28, new EcBlock(3, 113), new EcBlock(4, 114)), new EcBlocks(26, new EcBlock(3, 44), new EcBlock(11, 45)), new EcBlocks(26, new EcBlock(17, 21), new EcBlock(4, 22)), new EcBlocks(26, new EcBlock(9, 13), new EcBlock(16, 14)), ); break; case 20: $patterns = array(6, 34, 62, 90); $ecBlocks = array( new EcBlocks(28, new EcBlock(3, 107), new EcBlock(5, 108)), new EcBlocks(26, new EcBlock(3, 41), new EcBlock(13, 42)), new EcBlocks(30, new EcBlock(15, 24), new EcBlock(5, 25)), new EcBlocks(28, new EcBlock(15, 15), new EcBlock(10, 16)), ); break; case 21: $patterns = array(6, 28, 50, 72, 94); $ecBlocks = array( new EcBlocks(28, new EcBlock(4, 116), new EcBlock(4, 117)), new EcBlocks(26, new EcBlock(17, 42)), new EcBlocks(28, new EcBlock(17, 22), new EcBlock(6, 23)), new EcBlocks(30, new EcBlock(19, 16), new EcBlock(6, 17)), ); break; case 22: $patterns = array(6, 26, 50, 74, 98); $ecBlocks = array( new EcBlocks(28, new EcBlock(2, 111), new EcBlock(7, 112)), new EcBlocks(28, new EcBlock(17, 46)), new EcBlocks(30, new EcBlock(7, 24), new EcBlock(16, 25)), new EcBlocks(24, new EcBlock(34, 13)), ); break; case 23: $patterns = array(6, 30, 54, 78, 102); $ecBlocks = array( new EcBlocks(30, new EcBlock(4, 121), new EcBlock(5, 122)), new EcBlocks(28, new EcBlock(4, 47), new EcBlock(14, 48)), new EcBlocks(30, new EcBlock(11, 24), new EcBlock(14, 25)), new EcBlocks(30, new EcBlock(16, 15), new EcBlock(14, 16)), ); break; case 24: $patterns = array(6, 28, 54, 80, 106); $ecBlocks = array( new EcBlocks(30, new EcBlock(6, 117), new EcBlock(4, 118)), new EcBlocks(28, new EcBlock(6, 45), new EcBlock(14, 46)), new EcBlocks(30, new EcBlock(11, 24), new EcBlock(16, 25)), new EcBlocks(30, new EcBlock(30, 16), new EcBlock(2, 17)), ); break; case 25: $patterns = array(6, 32, 58, 84, 110); $ecBlocks = array( new EcBlocks(26, new EcBlock(8, 106), new EcBlock(4, 107)), new EcBlocks(28, new EcBlock(8, 47), new EcBlock(13, 48)), new EcBlocks(30, new EcBlock(7, 24), new EcBlock(22, 25)), new EcBlocks(30, new EcBlock(22, 15), new EcBlock(13, 16)), ); break; case 26: $patterns = array(6, 30, 58, 86, 114); $ecBlocks = array( new EcBlocks(28, new EcBlock(10, 114), new EcBlock(2, 115)), new EcBlocks(28, new EcBlock(19, 46), new EcBlock(4, 47)), new EcBlocks(28, new EcBlock(28, 22), new EcBlock(6, 23)), new EcBlocks(30, new EcBlock(33, 16), new EcBlock(4, 17)), ); break; case 27: $patterns = array(6, 34, 62, 90, 118); $ecBlocks = array( new EcBlocks(30, new EcBlock(8, 122), new EcBlock(4, 123)), new EcBlocks(28, new EcBlock(22, 45), new EcBlock(3, 46)), new EcBlocks(30, new EcBlock(8, 23), new EcBlock(26, 24)), new EcBlocks(30, new EcBlock(12, 15), new EcBlock(28, 16)), ); break; case 28: $patterns = array(6, 26, 50, 74, 98, 122); $ecBlocks = array( new EcBlocks(30, new EcBlock(3, 117), new EcBlock(10, 118)), new EcBlocks(28, new EcBlock(3, 45), new EcBlock(23, 46)), new EcBlocks(30, new EcBlock(4, 24), new EcBlock(31, 25)), new EcBlocks(30, new EcBlock(11, 15), new EcBlock(31, 16)), ); break; case 29: $patterns = array(6, 30, 54, 78, 102, 126); $ecBlocks = array( new EcBlocks(30, new EcBlock(7, 116), new EcBlock(7, 117)), new EcBlocks(28, new EcBlock(21, 45), new EcBlock(7, 46)), new EcBlocks(30, new EcBlock(1, 23), new EcBlock(37, 24)), new EcBlocks(30, new EcBlock(19, 15), new EcBlock(26, 16)), ); break; case 30: $patterns = array(6, 26, 52, 78, 104, 130); $ecBlocks = array( new EcBlocks(30, new EcBlock(5, 115), new EcBlock(10, 116)), new EcBlocks(28, new EcBlock(19, 47), new EcBlock(10, 48)), new EcBlocks(30, new EcBlock(15, 24), new EcBlock(25, 25)), new EcBlocks(30, new EcBlock(23, 15), new EcBlock(25, 16)), ); break; case 31: $patterns = array(6, 30, 56, 82, 108, 134); $ecBlocks = array( new EcBlocks(30, new EcBlock(13, 115), new EcBlock(3, 116)), new EcBlocks(28, new EcBlock(2, 46), new EcBlock(29, 47)), new EcBlocks(30, new EcBlock(42, 24), new EcBlock(1, 25)), new EcBlocks(30, new EcBlock(23, 15), new EcBlock(28, 16)), ); break; case 32: $patterns = array(6, 34, 60, 86, 112, 138); $ecBlocks = array( new EcBlocks(30, new EcBlock(17, 115)), new EcBlocks(28, new EcBlock(10, 46), new EcBlock(23, 47)), new EcBlocks(30, new EcBlock(10, 24), new EcBlock(35, 25)), new EcBlocks(30, new EcBlock(19, 15), new EcBlock(35, 16)), ); break; case 33: $patterns = array(6, 30, 58, 86, 114, 142); $ecBlocks = array( new EcBlocks(30, new EcBlock(17, 115), new EcBlock(1, 116)), new EcBlocks(28, new EcBlock(14, 46), new EcBlock(21, 47)), new EcBlocks(30, new EcBlock(29, 24), new EcBlock(19, 25)), new EcBlocks(30, new EcBlock(11, 15), new EcBlock(46, 16)), ); break; case 34: $patterns = array(6, 34, 62, 90, 118, 146); $ecBlocks = array( new EcBlocks(30, new EcBlock(13, 115), new EcBlock(6, 116)), new EcBlocks(28, new EcBlock(14, 46), new EcBlock(23, 47)), new EcBlocks(30, new EcBlock(44, 24), new EcBlock(7, 25)), new EcBlocks(30, new EcBlock(59, 16), new EcBlock(1, 17)), ); break; case 35: $patterns = array(6, 30, 54, 78, 102, 126, 150); $ecBlocks = array( new EcBlocks(30, new EcBlock(12, 121), new EcBlock(7, 122)), new EcBlocks(28, new EcBlock(12, 47), new EcBlock(26, 48)), new EcBlocks(30, new EcBlock(39, 24), new EcBlock(14, 25)), new EcBlocks(30, new EcBlock(22, 15), new EcBlock(41, 16)), ); break; case 36: $patterns = array(6, 24, 50, 76, 102, 128, 154); $ecBlocks = array( new EcBlocks(30, new EcBlock(6, 121), new EcBlock(14, 122)), new EcBlocks(28, new EcBlock(6, 47), new EcBlock(34, 48)), new EcBlocks(30, new EcBlock(46, 24), new EcBlock(10, 25)), new EcBlocks(30, new EcBlock(2, 15), new EcBlock(64, 16)), ); break; case 37: $patterns = array(6, 28, 54, 80, 106, 132, 158); $ecBlocks = array( new EcBlocks(30, new EcBlock(17, 122), new EcBlock(4, 123)), new EcBlocks(28, new EcBlock(29, 46), new EcBlock(14, 47)), new EcBlocks(30, new EcBlock(49, 24), new EcBlock(10, 25)), new EcBlocks(30, new EcBlock(24, 15), new EcBlock(46, 16)), ); break; case 38: $patterns = array(6, 32, 58, 84, 110, 136, 162); $ecBlocks = array( new EcBlocks(30, new EcBlock(4, 122), new EcBlock(18, 123)), new EcBlocks(28, new EcBlock(13, 46), new EcBlock(32, 47)), new EcBlocks(30, new EcBlock(48, 24), new EcBlock(14, 25)), new EcBlocks(30, new EcBlock(42, 15), new EcBlock(32, 16)), ); break; case 39: $patterns = array(6, 26, 54, 82, 110, 138, 166); $ecBlocks = array( new EcBlocks(30, new EcBlock(20, 117), new EcBlock(4, 118)), new EcBlocks(28, new EcBlock(40, 47), new EcBlock(7, 48)), new EcBlocks(30, new EcBlock(43, 24), new EcBlock(22, 25)), new EcBlocks(30, new EcBlock(10, 15), new EcBlock(67, 16)), ); break; case 40: $patterns = array(6, 30, 58, 86, 114, 142, 170); $ecBlocks = array( new EcBlocks(30, new EcBlock(19, 118), new EcBlock(6, 119)), new EcBlocks(28, new EcBlock(18, 47), new EcBlock(31, 48)), new EcBlocks(30, new EcBlock(34, 24), new EcBlock(34, 25)), new EcBlocks(30, new EcBlock(20, 15), new EcBlock(61, 16)), ); break; } self::$versions[$versionNumber - 1] = new self( $versionNumber, SplFixedArray::fromArray($patterns), SplFixedArray::fromArray($ecBlocks) ); } } lib/system/api/qr/src/BaconQrCode/Common/EcBlock.php 0000644 0000155 0177776 00000002546 12220311243 022452 0 ustar jenkins nogroup count = $count; $this->dataCodewords = $dataCodewords; } /** * Returns how many times the block is used. * * @return integer */ public function getCount() { return $this->count; } /** * Returns the number of data codewords. * * @return integer */ public function getDataCodewords() { return $this->dataCodewords; } } lib/system/api/qr/src/BaconQrCode/Common/AbstractEnum.php 0000644 0000155 0177776 00000004423 12220311243 023534 0 ustar jenkins nogroup strict = $strict; $this->change($initialValue); } /** * Changes the value of the enum. * * @param mixed $value * @return void */ public function change($value) { if (!in_array($value, $this->getConstList(), $this->strict)) { throw new Exception\UnexpectedValueException('Value not a const in enum ' . get_class($this)); } $this->value = $value; } /** * Gets current value. * * @return mixed */ public function get() { return $this->value; } /** * Gets all constants (possible values) as an array. * * @param boolean $includeDefault * @return array */ public function getConstList($includeDefault = true) { if ($this->constants === null) { $reflection = new ReflectionClass($this); $this->constants = $reflection->getConstants(); } if ($includeDefault) { return $this->constants; } $constants = $this->constants; unset($constants['__default']); return $constants; } /** * Gets the name of the enum. * * @return string */ public function __toString() { return array_search($this->value, $this->getConstList()); } } lib/system/api/qr/src/BaconQrCode/Common/EcBlocks.php 0000644 0000155 0177776 00000004377 12220311243 022641 0 ustar jenkins nogroup ecCodewordsPerBlock = $ecCodewordsPerBlock; $this->ecBlocks = new SplFixedArray($ecb2 === null ? 1 : 2); $this->ecBlocks[0] = $ecb1; if ($ecb2 !== null) { $this->ecBlocks[1] = $ecb2; } } /** * Gets the number of EC codewords per block. * * @return integer */ public function getEcCodewordsPerBlock() { return $this->ecCodewordsPerBlock; } /** * Gets the total number of EC block appearances. * * @return integer */ public function getNumBlocks() { $total = 0; foreach ($this->ecBlocks as $ecBlock) { $total += $ecBlock->getCount(); } return $total; } /** * Gets the total count of EC codewords. * * @return integer */ public function getTotalEcCodewords() { return $this->ecCodewordsPerBlock * $this->getNumBlocks(); } /** * Gets the EC blocks included in this collection. * * @return SplFixedArray */ public function getEcBlocks() { return $this->ecBlocks; } } lib/system/api/qr/src/BaconQrCode/Renderer/ 0000755 0000155 0177776 00000000000 12220311243 020746 5 ustar jenkins nogroup lib/system/api/qr/src/BaconQrCode/Renderer/Text/ 0000755 0000155 0177776 00000000000 12220311243 021672 5 ustar jenkins nogroup lib/system/api/qr/src/BaconQrCode/Renderer/Text/Plain.php 0000644 0000155 0177776 00000006566 12220311243 023463 0 ustar jenkins nogroup fullBlock = $fullBlock; } /** * Get char used as full block (occupied space, "black"). * * @return string */ public function getFullBlock() { return $this->fullBlock; } /** * Set char used as empty block (empty space, "white"). * * @param string $emptyBlock */ public function setEmptyBlock($emptyBlock) { $this->emptyBlock = $emptyBlock; } /** * Get char used as empty block (empty space, "white"). * * @return string */ public function getEmptyBlock() { return $this->emptyBlock; } /** * Sets the margin around the QR code. * * @param integer $margin * @return AbstractRenderer * @throws Exception\InvalidArgumentException */ public function setMargin($margin) { if ($margin < 0) { throw new Exception\InvalidArgumentException('Margin must be equal to greater than 0'); } $this->margin = (int) $margin; return $this; } /** * Gets the margin around the QR code. * * @return integer */ public function getMargin() { return $this->margin; } /** * render(): defined by RendererInterface. * * @see RendererInterface::render() * @param QrCode $qrCode * @return string */ public function render(QrCode $qrCode) { $result = ''; $matrix = $qrCode->getMatrix(); $width = $matrix->getWidth(); // Top margin for ($x = 0; $x < $this->margin; $x++) { $result .= str_repeat($this->emptyBlock, $width + 2 * $this->margin)."\n"; } // Body $array = $matrix->getArray(); foreach ($array as $row) { $result .= str_repeat($this->emptyBlock, $this->margin); // left margin foreach ($row as $byte) { $result .= $byte ? $this->fullBlock : $this->emptyBlock; } $result .= str_repeat($this->emptyBlock, $this->margin); // right margin $result .= "\n"; } // Bottom margin for ($x = 0; $x < $this->margin; $x++) { $result .= str_repeat($this->emptyBlock, $width + 2 * $this->margin)."\n"; } return $result; } } lib/system/api/qr/src/BaconQrCode/Renderer/Text/Html.php 0000644 0000155 0177776 00000003431 12220311243 023310 0 ustar jenkins nogroup class = $class; } /** * Get CSS class name. * * @return string */ public function getClass() { return $this->class; } /** * Set CSS style value. * * @param string $style */ public function setStyle($style) { $this->style = $style; } /** * Get CSS style value. * * @return string */ public function getStyle() { return $this->style; } /** * render(): defined by RendererInterface. * * @see RendererInterface::render() * @param QrCode $qrCode * @return string */ public function render(QrCode $qrCode) { $textCode = parent::render($qrCode); $result = '
' . $textCode . ''; return $result; } } lib/system/api/qr/src/BaconQrCode/Renderer/Color/ 0000755 0000155 0177776 00000000000 12220311243 022024 5 ustar jenkins nogroup lib/system/api/qr/src/BaconQrCode/Renderer/Color/Gray.php 0000644 0000155 0177776 00000003167 12220311243 023446 0 ustar jenkins nogroup 100) { throw new Exception\InvalidArgumentException('Gray must be between 0 and 100'); } $this->gray = (int) $gray; } /** * Returns the gray value. * * @return integer */ public function getGray() { return $this->gray; } /** * toRgb(): defined by ColorInterface. * * @see ColorInterface::toRgb() * @return Rgb */ public function toRgb() { return new Rgb($this->gray * 2.55, $this->gray * 2.55, $this->gray * 2.55); } /** * toCmyk(): defined by ColorInterface. * * @see ColorInterface::toCmyk() * @return Cmyk */ public function toCmyk() { return new Cmyk(0, 0, 0, 100 - $this->gray); } /** * toGray(): defined by ColorInterface. * * @see ColorInterface::toGray() * @return Gray */ public function toGray() { return $this; } } lib/system/api/qr/src/BaconQrCode/Renderer/Color/ColorInterface.php 0000644 0000155 0177776 00000001224 12220311243 025433 0 ustar jenkins nogroup 100) { throw new Exception\InvalidArgumentException('Cyan must be between 0 and 100'); } if ($magenta < 0 || $magenta > 100) { throw new Exception\InvalidArgumentException('Magenta must be between 0 and 100'); } if ($yellow < 0 || $yellow > 100) { throw new Exception\InvalidArgumentException('Yellow must be between 0 and 100'); } if ($black < 0 || $black > 100) { throw new Exception\InvalidArgumentException('Black must be between 0 and 100'); } $this->cyan = (int) $cyan; $this->magenta = (int) $magenta; $this->yellow = (int) $yellow; $this->black = (int) $black; } /** * Returns the cyan value. * * @return integer */ public function getCyan() { return $this->cyan; } /** * Returns the magenta value. * * @return integer */ public function getMagenta() { return $this->magenta; } /** * Returns the yellow value. * * @return integer */ public function getYellow() { return $this->yellow; } /** * Returns the black value. * * @return integer */ public function getBlack() { return $this->black; } /** * toRgb(): defined by ColorInterface. * * @see ColorInterface::toRgb() * @return Rgb */ public function toRgb() { $k = $this->black / 100; $c = (-$k * $this->cyan + $k * 100 + $this->cyan) / 100; $m = (-$k * $this->magenta + $k * 100 + $this->magenta) / 100; $y = (-$k * $this->yellow + $k * 100 + $this->yellow) / 100; return new Rgb( -$c * 255 + 255, -$m * 255 + 255, -$y * 255 + 255 ); } /** * toCmyk(): defined by ColorInterface. * * @see ColorInterface::toCmyk() * @return Cmyk */ public function toCmyk() { return $this; } /** * toGray(): defined by ColorInterface. * * @see ColorInterface::toGray() * @return Gray */ public function toGray() { return $this->toRgb()->toGray(); } } lib/system/api/qr/src/BaconQrCode/Renderer/Color/Rgb.php 0000644 0000155 0177776 00000005655 12220311243 023262 0 ustar jenkins nogroup 255) { throw new Exception\InvalidArgumentException('Red must be between 0 and 255'); } if ($green < 0 || $green > 255) { throw new Exception\InvalidArgumentException('Green must be between 0 and 255'); } if ($blue < 0 || $blue > 255) { throw new Exception\InvalidArgumentException('Blue must be between 0 and 255'); } $this->red = (int) $red; $this->green = (int) $green; $this->blue = (int) $blue; } /** * Returns the red value. * * @return integer */ public function getRed() { return $this->red; } /** * Returns the green value. * * @return integer */ public function getGreen() { return $this->green; } /** * Returns the blue value. * * @return integer */ public function getBlue() { return $this->blue; } /** * Returns a hexadecimal string representation of the RGB value. * * @return string */ public function __toString() { return sprintf('%02x%02x%02x', $this->red, $this->green, $this->blue); } /** * toRgb(): defined by ColorInterface. * * @see ColorInterface::toRgb() * @return Rgb */ public function toRgb() { return $this; } /** * toCmyk(): defined by ColorInterface. * * @see ColorInterface::toCmyk() * @return Cmyk */ public function toCmyk() { $c = 1 - ($this->red / 255); $m = 1 - ($this->green / 255); $y = 1 - ($this->blue / 255); $k = min($c, $m, $y); return new Cmyk( 100 * ($c - $k) / (1 - $k), 100 * ($m - $k) / (1 - $k), 100 * ($y - $k) / (1 - $k), 100 * $k ); } /** * toGray(): defined by ColorInterface. * * @see ColorInterface::toGray() * @return Gray */ public function toGray() { return new Gray(($this->red * 0.21 + $this->green * 0.71 + $this->blue * 0.07) / 2.55); } } lib/system/api/qr/src/BaconQrCode/Renderer/RendererInterface.php 0000644 0000155 0177776 00000001004 12220311243 025041 0 ustar jenkins nogroup svg = new SimpleXMLElement( '' . '' ); $this->svg->addAttribute('version', '1.1'); $this->svg->addAttribute('width', $this->finalWidth . 'px'); $this->svg->addAttribute('height', $this->finalHeight . 'px'); $this->svg->addChild('defs'); } /** * addColor(): defined by RendererInterface. * * @see ImageRendererInterface::addColor() * @param string $id * @param ColorInterface $color * @return void * @throws Exception\InvalidArgumentException */ public function addColor($id, ColorInterface $color) { $this->colors[$id] = (string) $color->toRgb(); } /** * drawBackground(): defined by RendererInterface. * * @see ImageRendererInterface::drawBackground() * @param string $colorId * @return void */ public function drawBackground($colorId) { $rect = $this->svg->addChild('rect'); $rect->addAttribute('x', 0); $rect->addAttribute('y', 0); $rect->addAttribute('width', $this->finalWidth); $rect->addAttribute('height', $this->finalHeight); $rect->addAttribute('fill', '#' . $this->colors[$colorId]); } /** * drawBlock(): defined by RendererInterface. * * @see ImageRendererInterface::drawBlock() * @param integer $x * @param integer $y * @param string $colorId * @return void */ public function drawBlock($x, $y, $colorId) { $use = $this->svg->addChild('use'); $use->addAttribute('x', $x); $use->addAttribute('y', $y); $use->addAttribute( 'xlink:href', $this->getRectPrototypeId($colorId), 'http://www.w3.org/1999/xlink' ); } /** * getByteStream(): defined by RendererInterface. * * @see ImageRendererInterface::getByteStream() * @return string */ public function getByteStream() { return $this->svg->asXML(); } /** * Get the prototype ID for a color. * * @param integer $colorId * @return string */ protected function getRectPrototypeId($colorId) { if (!isset($this->prototypeIds[$colorId])) { $id = 'r' . dechex(count($this->prototypeIds)); $rect = $this->svg->defs->addChild('rect'); $rect->addAttribute('id', $id); $rect->addAttribute('width', $this->blockSize); $rect->addAttribute('height', $this->blockSize); $rect->addAttribute('fill', '#' . $this->colors[$colorId]); $this->prototypeIds[$colorId] = '#' . $id; } return $this->prototypeIds[$colorId]; } } lib/system/api/qr/src/BaconQrCode/Renderer/Image/Eps.php 0000644 0000155 0177776 00000007354 12220311243 023241 0 ustar jenkins nogroup eps = "%!PS-Adobe-3.0 EPSF-3.0\n" . "%%BoundingBox: 0 0 " . $this->finalWidth . " " . $this->finalHeight . "\n" . "/F { rectfill } def\n"; } /** * addColor(): defined by RendererInterface. * * @see ImageRendererInterface::addColor() * @param string $id * @param ColorInterface $color * @return void */ public function addColor($id, ColorInterface $color) { if ( !$color instanceof Rgb && !$color instanceof Cmyk && !$color instanceof Gray ) { $color = $color->toCmyk(); } $this->colors[$id] = $color; } /** * drawBackground(): defined by RendererInterface. * * @see ImageRendererInterface::drawBackground() * @param string $colorId * @return void */ public function drawBackground($colorId) { $this->setColor($colorId); $this->eps .= "0 0 " . $this->finalWidth . " " . $this->finalHeight . " F\n"; } /** * drawBlock(): defined by RendererInterface. * * @see ImageRendererInterface::drawBlock() * @param integer $x * @param integer $y * @param string $colorId * @return void */ public function drawBlock($x, $y, $colorId) { $this->setColor($colorId); $this->eps .= $x . " " . ($this->finalHeight - $y) . " " . $this->blockSize . " " . $this->blockSize . " F\n"; } /** * getByteStream(): defined by RendererInterface. * * @see ImageRendererInterface::getByteStream() * @return string */ public function getByteStream() { return $this->eps; } /** * Sets color to use. * * @param string $colorId * @return void */ protected function setColor($colorId) { if ($colorId !== $this->currentColor) { $color = $this->colors[$colorId]; if ($color instanceof Rgb) { $this->eps .= sprintf( "%F %F %F setrgbcolor\n", $color->getRed() / 100, $color->getGreen() / 100, $color->getBlue() / 100 ); } elseif ($color instanceof Cmyk) { $this->eps .= sprintf( "%F %F %F %F setcmykcolor\n", $color->getCyan() / 100, $color->getMagenta() / 100, $color->getYellow() / 100, $color->getBlack() / 100 ); } elseif ($color instanceof Gray) { $this->eps .= sprintf( "%F setgray\n", $color->getGray() / 100 ); } $this->currentColor = $colorId; } } } lib/system/api/qr/src/BaconQrCode/Renderer/Image/Decorator/ 0000755 0000155 0177776 00000000000 12220311243 023712 5 ustar jenkins nogroup lib/system/api/qr/src/BaconQrCode/Renderer/Image/Decorator/FinderPattern.php 0000644 0000155 0177776 00000013155 12220311243 027175 0 ustar jenkins nogroup outerColor = $color; return $this; } /** * Gets outer color. * * @return Color\ColorInterface */ public function getOuterColor() { if ($this->outerColor === null) { $this->outerColor = new Color\Gray(100); } return $this->outerColor; } /** * Sets inner color. * * @param Color\ColorInterface $color * @return FinderPattern */ public function setInnerColor(Color\ColorInterface $color) { $this->innerColor = $color; return $this; } /** * Gets inner color. * * @return Color\ColorInterface */ public function getInnerColor() { if ($this->innerColor === null) { $this->innerColor = new Color\Gray(0); } return $this->innerColor; } /** * preProcess(): defined by DecoratorInterface. * * @see DecoratorInterface::preProcess() * @param QrCode $qrCode * @param RendererInterface $renderer * @param integer $outputWidth * @param integer $outputHeight * @param integer $leftPadding * @param integer $topPadding * @param integer $multiple * @return void */ public function preProcess( QrCode $qrCode, RendererInterface $renderer, $outputWidth, $outputHeight, $leftPadding, $topPadding, $multiple ) { $matrix = $qrCode->getMatrix(); $positions = array( array(0, 0), array($matrix->getWidth() - 7, 0), array(0, $matrix->getHeight() - 7), ); foreach (self::$outerPositionDetectionPattern as $y => $row) { foreach ($row as $x => $isSet) { foreach ($positions as $position) { $matrix->set($x + $position[0], $y + $position[1], 0); } } } } /** * postProcess(): defined by DecoratorInterface. * * @see DecoratorInterface::postProcess() * * @param QrCode $qrCode * @param RendererInterface $renderer * @param integer $outputWidth * @param integer $outputHeight * @param integer $leftPadding * @param integer $topPadding * @param integer $multiple * @return void */ public function postProcess( QrCode $qrCode, RendererInterface $renderer, $outputWidth, $outputHeight, $leftPadding, $topPadding, $multiple ) { $matrix = $qrCode->getMatrix(); $positions = array( array(0, 0), array($matrix->getWidth() - 7, 0), array(0, $matrix->getHeight() - 7), ); $renderer->addColor('finder-outer', $this->getOuterColor()); $renderer->addColor('finder-inner', $this->getInnerColor()); foreach (self::$outerPositionDetectionPattern as $y => $row) { foreach ($row as $x => $isOuterSet) { $isInnerSet = self::$innerPositionDetectionPattern[$y][$x]; if ($isOuterSet) { foreach ($positions as $position) { $renderer->drawBlock( $leftPadding + $x * $multiple + $position[0] * $multiple, $topPadding + $y * $multiple + $position[1] * $multiple, 'finder-outer' ); } } if ($isInnerSet) { foreach ($positions as $position) { $renderer->drawBlock( $leftPadding + $x * $multiple + $position[0] * $multiple, $topPadding + $y * $multiple + $position[1] * $multiple, 'finder-inner' ); } } } } } } lib/system/api/qr/src/BaconQrCode/Renderer/Image/Decorator/DecoratorInterface.php 0000644 0000155 0177776 00000003125 12220311243 030167 0 ustar jenkins nogroup margin = (int) $margin; return $this; } /** * Gets the margin around the QR code. * * @return integer */ public function getMargin() { return $this->margin; } /** * Sets the height around the renderd image. * * If the width is smaller than the matrix width plus padding, the renderer * will automatically use that as the width instead of the specified one. * * @param integer $width * @return AbstractRenderer */ public function setWidth($width) { $this->width = (int) $width; return $this; } /** * Gets the width of the rendered image. * * @return integer */ public function getWidth() { return $this->width; } /** * Sets the height around the renderd image. * * If the height is smaller than the matrix height plus padding, the * renderer will automatically use that as the height instead of the * specified one. * * @param integer $height * @return AbstractRenderer */ public function setHeight($height) { $this->height = (int) $height; return $this; } /** * Gets the height around the rendered image. * * @return integer */ public function getHeight() { return $this->height; } /** * Sets whether dimensions should be rounded down. * * @param boolean $flag * @return AbstractRenderer */ public function setRoundDimensions($flag) { $this->floorToClosestDimension = $flag; return $this; } /** * Gets whether dimensions should be rounded down. * * @return boolean */ public function shouldRoundDimensions() { return $this->floorToClosestDimension; } /** * Sets background color. * * @param Color\ColorInterface $color * @return AbstractRenderer */ public function setBackgroundColor(Color\ColorInterface $color) { $this->backgroundColor = $color; return $this; } /** * Gets background color. * * @return Color\ColorInterface */ public function getBackgroundColor() { if ($this->backgroundColor === null) { $this->backgroundColor = new Color\Gray(100); } return $this->backgroundColor; } /** * Sets foreground color. * * @param Color\ColorInterface $color * @return AbstractRenderer */ public function setForegroundColor(Color\ColorInterface $color) { $this->foregroundColor = $color; return $this; } /** * Gets foreground color. * * @return Color\ColorInterface */ public function getForegroundColor() { if ($this->foregroundColor === null) { $this->foregroundColor = new Color\Gray(0); } return $this->foregroundColor; } /** * Adds a decorator to the renderer. * * @param DecoratorInterface $decorator * @return AbstractRenderer */ public function addDecorator(DecoratorInterface $decorator) { $this->decorators[] = $decorator; return $this; } /** * render(): defined by RendererInterface. * * @see RendererInterface::render() * @param QrCode $qrCode * @return string */ public function render(QrCode $qrCode) { $input = $qrCode->getMatrix(); $inputWidth = $input->getWidth(); $inputHeight = $input->getHeight(); $qrWidth = $inputWidth + ($this->getMargin() << 1); $qrHeight = $inputHeight + ($this->getMargin() << 1); $outputWidth = max($this->getWidth(), $qrWidth); $outputHeight = max($this->getHeight(), $qrHeight); $multiple = (int) min($outputWidth / $qrWidth, $outputHeight / $qrHeight); if ($this->shouldRoundDimensions()) { $outputWidth -= $outputWidth % $multiple; $outputHeight -= $outputHeight % $multiple; } // Padding includes both the quiet zone and the extra white pixels to // accommodate the requested dimensions. For example, if input is 25x25 // the QR will be 33x33 including the quiet zone. If the requested size // is 200x160, the multiple will be 4, for a QR of 132x132. These will // handle all the padding from 100x100 (the actual QR) up to 200x160. $leftPadding = (int) (($outputWidth - ($inputWidth * $multiple)) / 2); $topPadding = (int) (($outputHeight - ($inputHeight * $multiple)) / 2); // Store calculated parameters $this->finalWidth = $outputWidth; $this->finalHeight = $outputHeight; $this->blockSize = $multiple; $this->init(); $this->addColor('background', $this->getBackgroundColor()); $this->addColor('foreground', $this->getForegroundColor()); $this->drawBackground('background'); foreach ($this->decorators as $decorator) { $decorator->preProcess( $qrCode, $this, $outputWidth, $outputHeight, $leftPadding, $topPadding, $multiple ); } for ($inputY = 0, $outputY = $topPadding; $inputY < $inputHeight; $inputY++, $outputY += $multiple) { for ($inputX = 0, $outputX = $leftPadding; $inputX < $inputWidth; $inputX++, $outputX += $multiple) { if ($input->get($inputX, $inputY) === 1) { $this->drawBlock($outputX, $outputY, 'foreground'); } } } foreach ($this->decorators as $decorator) { $decorator->postProcess( $qrCode, $this, $outputWidth, $outputHeight, $leftPadding, $topPadding, $multiple ); } return $this->getByteStream(); } } lib/system/api/qr/src/BaconQrCode/Renderer/Image/Png.php 0000644 0000155 0177776 00000005144 12220311243 023231 0 ustar jenkins nogroup image = imagecreatetruecolor($this->finalWidth, $this->finalHeight); } /** * addColor(): defined by RendererInterface. * * @see ImageRendererInterface::addColor() * @param string $id * @param ColorInterface $color * @return void * @throws Exception\RuntimeException */ public function addColor($id, ColorInterface $color) { if ($this->image === null) { throw new Exception\RuntimeException('Colors can only be added after init'); } $color = $color->toRgb(); $this->colors[$id] = imagecolorallocate( $this->image, $color->getRed(), $color->getGreen(), $color->getBlue() ); } /** * drawBackground(): defined by RendererInterface. * * @see ImageRendererInterface::drawBackground() * @param string $colorId * @return void */ public function drawBackground($colorId) { imagefill($this->image, 0, 0, $this->colors[$colorId]); } /** * drawBlock(): defined by RendererInterface. * * @see ImageRendererInterface::drawBlock() * @param integer $x * @param integer $y * @param string $colorId * @return void */ public function drawBlock($x, $y, $colorId) { imagefilledrectangle( $this->image, $x, $y, $x + $this->blockSize - 1, $y + $this->blockSize - 1, $this->colors[$colorId] ); } /** * getByteStream(): defined by RendererInterface. * * @see ImageRendererInterface::getByteStream() * @return string */ public function getByteStream() { ob_start(); imagepng($this->image); return ob_get_clean(); } } lib/system/api/qr/src/BaconQrCode/Writer.php 0000644 0000155 0177776 00000005026 12220311243 021170 0 ustar jenkins nogroup renderer = $renderer; } /** * Sets the renderer used to create a byte stream. * * @param RendererInterface $renderer * @return Writer */ public function setRenderer(RendererInterface $renderer) { $this->renderer = $renderer; return $this; } /** * Gets the renderer used to create a byte stream. * * @return RendererInterface */ public function getRenderer() { return $this->renderer; } /** * Writes QR code and returns it as string. * * Content is a string which *should* be encoded in UTF-8, in case there are * non ASCII-characters present. * * @param string $content * @param string $encoding * @param integer $ecLevel * @return string * @throws Exception\InvalidArgumentException */ public function writeString( $content, $encoding = Encoder::DEFAULT_BYTE_MODE_ECODING, $ecLevel = ErrorCorrectionLevel::L ) { if (strlen($content) === 0) { throw new Exception\InvalidArgumentException('Found empty contents'); } $qrCode = Encoder::encode($content, new ErrorCorrectionLevel($ecLevel), $encoding); return $this->getRenderer()->render($qrCode); } /** * Writes QR code to a file. * * @see Writer::writeString() * @param string $content * @param string $filename * @param string $encoding * @param integer $ecLevel * @return void */ public function writeFile( $content, $filename, $encoding = Encoder::DEFAULT_BYTE_MODE_ECODING, $ecLevel = ErrorCorrectionLevel::L ) { file_put_contents($filename, $this->writeString($content, $encoding, $ecLevel)); } } lib/system/api/qr/src/BaconQrCode/Exception/ 0000755 0000155 0177776 00000000000 12220311243 021136 5 ustar jenkins nogroup lib/system/api/qr/src/BaconQrCode/Exception/UnexpectedValueException.php 0000644 0000155 0177776 00000000566 12220311243 026636 0 ustar jenkins nogroup height = $height; $this->width = $width; $this->bytes = new SplFixedArray($height); for ($y = 0; $y < $height; $y++) { $this->bytes[$y] = new SplFixedArray($width); } } /** * Gets the width of the matrix. * * @return integer */ public function getWidth() { return $this->width; } /** * Gets the height of the matrix. * * @return integer */ public function getHeight() { return $this->height; } /** * Gets the internal representation of the matrix. * * @return SplFixedArray */ public function getArray() { return $this->bytes; } /** * Gets the byte for a specific position. * * @param integer $x * @param integer $y * @return integer */ public function get($x, $y) { return $this->bytes[$y][$x]; } /** * Sets the byte for a specific position. * * @param integer $x * @param integer $y * @param integer $value * @return void */ public function set($x, $y, $value) { $this->bytes[$y][$x] = (int) $value; } /** * Clears the matrix with a specific value. * * @param integer $value * @return void */ public function clear($value) { for ($y = 0; $y < $this->height; $y++) { for ($x = 0; $x < $this->width; $x++) { $this->bytes[$y][$x] = $value; } } } /** * Returns a string representation of the matrix. * * @return string */ public function __toString() { $result = ''; for ($y = 0; $y < $this->height; $y++) { for ($x = 0; $x < $this->width; $x++) { switch ($this->bytes[$y][$x]) { case 0: $result .= ' 0'; break; case 1: $result .= ' 1'; break; default: $result .= ' '; break; } } $result .= "\n"; } return $result; } } lib/system/api/qr/src/BaconQrCode/Encoder/BlockPair.php 0000644 0000155 0177776 00000002361 12220311243 023140 0 ustar jenkins nogroup dataBytes = $data; $this->errorCorrectionBytes = $errorCorrection; } /** * Gets the data bytes. * * @return SplFixedArray */ public function getDataBytes() { return $this->dataBytes; } /** * Gets the error correction bytes. * * @return SplFixedArray */ public function getErrorCorrectionBytes() { return $this->errorCorrectionBytes; } } lib/system/api/qr/src/BaconQrCode/Encoder/QrCode.php 0000644 0000155 0177776 00000007342 12220311243 022453 0 ustar jenkins nogroup mode; } /** * Sets the mode. * * @param Mode $mode * @return void */ public function setMode(Mode $mode) { $this->mode = $mode; } /** * Gets the EC level. * * @return ErrorCorrectionLevel */ public function getErrorCorrectionLevel() { return $this->errorCorrectionLevel; } /** * Sets the EC level. * * @param ErrorCorrectionLevel $errorCorrectionLevel * @return void */ public function setErrorCorrectionLevel(ErrorCorrectionLevel $errorCorrectionLevel) { $this->errorCorrectionLevel = $errorCorrectionLevel; } /** * Gets the version. * * @return Version */ public function getVersion() { return $this->version; } /** * Sets the version. * * @param Version $version * @return void */ public function setVersion(Version $version) { $this->version = $version; } /** * Gets the mask pattern. * * @return integer */ public function getMaskPattern() { return $this->maskPattern; } /** * Sets the mask pattern. * * @param integer $maskPattern * @return void */ public function setMaskPattern($maskPattern) { $this->maskPattern = $maskPattern; } /** * Gets the matrix. * * @return ByteMatrix */ public function getMatrix() { return $this->matrix; } /** * Sets the matrix. * * @param ByteMatrix $matrix * @return void */ public function setMatrix(ByteMatrix $matrix) { $this->matrix = $matrix; } /** * Validates whether a mask pattern is valid. * * @param integer $maskPattern * @return boolean */ public static function isValidMaskPattern($maskPattern) { return $maskPattern > 0 && $maskPattern < self::NUM_MASK_PATTERNS; } /** * Returns a string representation of the QR code. * * @return string */ public function __toString() { $result = "<<\n" . " mode: " . $this->mode . "\n" . " ecLevel: " . $this->errorCorrectionLevel . "\n" . " version: " . $this->version . "\n" . " maskPattern: " . $this->maskPattern . "\n"; if ($this->matrix === null) { $result .= " matrix: null\n"; } else { $result .= " matrix:\n"; $result .= $this->matrix; } $result .= ">>\n"; return $result; } } lib/system/api/qr/src/BaconQrCode/Encoder/MaskUtil.php 0000644 0000155 0177776 00000021347 12220311243 023030 0 ustar jenkins nogroup getArray(); $width = $matrix->getWidth(); $height = $matrix->getHeight(); for ($y = 0; $y < $height - 1; $y++) { for ($x = 0; $x < $width - 1; $x++) { $value = $array[$y][$x]; if ($value === $array[$y][$x + 1] && $value === $array[$y + 1][$x] && $value === $array[$y + 1][$x + 1]) { $penalty++; } } } return self::N2 * $penalty; } /** * Applies mask penalty rule 3 and returns the penalty. * * Finds consecutive cells of 00001011101 or 10111010000, and gives penalty * to them. If we find patterns like 000010111010000, we give penalties * twice (i.e. 40 * 2). * * @param ByteMatrix $matrix * @return integer */ public static function applyMaskPenaltyRule3(ByteMatrix $matrix) { $penalty = 0; $array = $matrix->getArray(); $width = $matrix->getWidth(); $height = $matrix->getHeight(); for ($y = 0; $y < $height; $y++) { for ($x = 0; $x < $width; $x++) { if ( $x + 6 < $width && $array[$y][$x] === 1 && $array[$y][$x + 1] === 0 && $array[$y][$x + 2] === 1 && $array[$y][$x + 3] === 1 && $array[$y][$x + 4] === 1 && $array[$y][$x + 5] === 0 && $array[$y][$x + 6] === 1 && ( ( $x + 10 < $width && $array[$y][$x + 7] === 0 && $array[$y][$x + 8] === 0 && $array[$y][$x + 9] === 0 && $array[$y][$x + 10] === 0 ) || ( $x - 4 >= 0 && $array[$y][$x - 1] === 0 && $array[$y][$x - 2] === 0 && $array[$y][$x - 3] === 0 && $array[$y][$x - 4] === 0 ) ) ) { $penalty += self::N3; } if ( $y + 6 < $height && $array[$y][$x] === 1 && $array[$y + 1][$x] === 0 && $array[$y + 2][$x] === 1 && $array[$y + 3][$x] === 1 && $array[$y + 4][$x] === 1 && $array[$y + 5][$x] === 0 && $array[$y + 6][$x] === 1 && ( ( $y + 10 < $height && $array[$y + 7][$x] === 0 && $array[$y + 8][$x] === 0 && $array[$y + 9][$x] === 0 && $array[$y + 10][$x] === 0 ) || ( $y - 4 >= 0 && $array[$y - 1][$x] === 0 && $array[$y - 2][$x] === 0 && $array[$y - 3][$x] === 0 && $array[$y - 4][$x] === 0 ) ) ) { $penalty += self::N3; } } } return $penalty; } /** * Applies mask penalty rule 4 and returns the penalty. * * Calculates the ratio of dark cells and gives penalty if the ratio is far * from 50%. It gives 10 penalty for 5% distance. * * @param ByteMatrix $matrix * @return integer */ public static function applyMaskPenaltyRule4(ByteMatrix $matrix) { $numDarkCells = 0; $array = $matrix->getArray(); $width = $matrix->getWidth(); $height = $matrix->getHeight(); for ($y = 0; $y < $height; $y++) { $arrayY = $array[$y]; for ($x = 0; $x < $width; $x++) { if ($arrayY[$x] === 1) { $numDarkCells++; } } } $numTotalCells = $height * $width; $darkRatio = $numDarkCells / $numTotalCells; $fixedPercentVariances = (int) (abs($darkRatio - 0.5) * 20); return $fixedPercentVariances * self::N4; } /** * Returns the mask bit for "getMaskPattern" at "x" and "y". * * See 8.8 of JISX0510:2004 for mask pattern conditions. * * @param integer $maskPattern * @param integer $x * @param integer $y * @return integer * @throws Exception\InvalidArgumentException */ public static function getDataMaskBit($maskPattern, $x, $y) { switch ($maskPattern) { case 0: $intermediate = ($y + $x) & 0x1; break; case 1: $intermediate = $y & 0x1; break; case 2: $intermediate = $x % 3; break; case 3: $intermediate = ($y + $x) % 3; break; case 4: $intermediate = (BitUtils::unsignedRightShift($y, 1) + ($x / 3)) & 0x1; break; case 5: $temp = $y * $x; $intermediate = ($temp & 0x1) + ($temp % 3); break; case 6: $temp = $y * $x; $intermediate = (($temp & 0x1) + ($temp % 3)) & 0x1; break; case 7: $temp = $y * $x; $intermediate = (($temp % 3) + (($y + $x) & 0x1)) & 0x1; break; default: throw new Exception\InvalidArgumentException('Invalid mask pattern: ' . $maskPattern); } return $intermediate === 0; } /** * Helper function for applyMaskPenaltyRule1. * * We need this for doing this calculation in both vertical and horizontal * orders respectively. * * @param ByteMatrix $matrix * @param boolean $isHorizontal * @return integer */ protected static function applyMaskPenaltyRule1Internal(ByteMatrix $matrix, $isHorizontal) { $penalty = 0; $iLimit = $isHorizontal ? $matrix->getHeight() : $matrix->getWidth(); $jLimit = $isHorizontal ? $matrix->getWidth() : $matrix->getHeight(); $array = $matrix->getArray(); for ($i = 0; $i < $iLimit; $i++) { $numSameBitCells = 0; $prevBit = -1; for ($j = 0; $j < $jLimit; $j++) { $bit = $isHorizontal ? $array[$i][$j] : $array[$j][$i]; if ($bit === $prevBit) { $numSameBitCells++; } else { if ($numSameBitCells >= 5) { $penalty += self::N1 + ($numSameBitCells - 5); } $numSameBitCells = 1; $prevBit = $bit; } } if ($numSameBitCells >= 5) { $penalty += self::N1 + ($numSameBitCells - 5); } } return $penalty; } } lib/system/api/qr/src/BaconQrCode/Encoder/MatrixUtil.php 0000644 0000155 0177776 00000043740 12220311243 023402 0 ustar jenkins nogroup clear(-1); } /** * Builds a complete matrix. * * @param BitArray $dataBits * @param ErrorCorrectionLevel $level * @param Version $version * @param integer $maskPattern * @param ByteMatrix $matrix * @return void */ public static function buildMatrix( BitArray $dataBits, ErrorCorrectionLevel $level, Version $version, $maskPattern, ByteMatrix $matrix ) { self::clearMatrix($matrix); self::embedBasicPatterns($version, $matrix); self::embedTypeInfo($level, $maskPattern, $matrix); self::maybeEmbedVersionInfo($version, $matrix); self::embedDataBits($dataBits, $maskPattern, $matrix); } /** * Embeds type information into a matrix. * * @param ErrorCorrectionLevel $level * @param integer $maskPattern * @param ByteMatrix $matrix * @return void */ protected static function embedTypeInfo(ErrorCorrectionLevel $level, $maskPattern, ByteMatrix $matrix) { $typeInfoBits = new BitArray(); self::makeTypeInfoBits($level, $maskPattern, $typeInfoBits); $typeInfoBitsSize = $typeInfoBits->getSize(); for ($i = 0; $i < $typeInfoBitsSize; $i++) { $bit = $typeInfoBits->get($typeInfoBitsSize - 1 - $i); $x1 = self::$typeInfoCoordinates[$i][0]; $y1 = self::$typeInfoCoordinates[$i][1]; $matrix->set($x1, $y1, $bit); if ($i < 8) { $x2 = $matrix->getWidth() - $i - 1; $y2 = 8; } else { $x2 = 8; $y2 = $matrix->getHeight() - 7 + ($i - 8); } $matrix->set($x2, $y2, $bit); } } /** * Generates type information bits and appends them to a bit array. * * @param ErrorCorrectionLevel $level * @param integer $maskPattern * @param BitArray $bits * @return void * @throws Exception\RuntimeException */ protected static function makeTypeInfoBits(ErrorCorrectionLevel $level, $maskPattern, BitArray $bits) { $typeInfo = ($level->get() << 3) | $maskPattern; $bits->appendBits($typeInfo, 5); $bchCode = self::calculateBchCode($typeInfo, self::$typeInfoPoly); $bits->appendBits($bchCode, 10); $maskBits = new BitArray(); $maskBits->appendBits(self::$typeInfoMaskPattern, 15); $bits->xorBits($maskBits); if ($bits->getSize() !== 15) { throw new Exception\RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize()); } } /** * Embeds version information if required. * * @param Version $version * @param ByteMatrix $matrix * @return void */ protected static function maybeEmbedVersionInfo(Version $version, ByteMatrix $matrix) { if ($version->getVersionNumber() < 7) { return; } $versionInfoBits = new BitArray(); self::makeVersionInfoBits($version, $versionInfoBits); $bitIndex = 6 * 3 - 1; for ($i = 0; $i < 6; $i++) { for ($j = 0; $j < 3; $j++) { $bit = $versionInfoBits->get($bitIndex); $bitIndex--; $matrix->set($i, $matrix->getHeight() - 11 + $j, $bit); $matrix->set($matrix->getHeight() - 11 + $j, $i, $bit); } } } /** * Generates version information bits and appends them to a bit array. * * @param Version $version * @param BitArray $bits * @return void * @throws Exception\RuntimeException */ protected static function makeVersionInfoBits(Version $version, BitArray $bits) { $bits->appendBits($version->getVersionNumber(), 6); $bchCode = self::calculateBchCode($version->getVersionNumber(), self::$versionInfoPoly); $bits->appendBits($bchCode, 12); if ($bits->getSize() !== 18) { throw new Exception\RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize()); } } /** * Calculates the BHC code for a value and a polynomial. * * @param integer $value * @param integer $poly * @return integer */ protected static function calculateBchCode($value, $poly) { $msbSetInPoly = self::findMsbSet($poly); $value <<= $msbSetInPoly - 1; while (self::findMsbSet($value) >= $msbSetInPoly) { $value ^= $poly << (self::findMsbSet($value) - $msbSetInPoly); } return $value; } /** * Finds and MSB set. * * @param integer $value * @return integer */ protected static function findMsbSet($value) { $numDigits = 0; while ($value !== 0) { $value >>= 1; $numDigits++; } return $numDigits; } /** * Embeds basic patterns into a matrix. * * @param Version $version * @param ByteMatrix $matrix * @return void */ protected static function embedBasicPatterns(Version $version, ByteMatrix $matrix) { self::embedPositionDetectionPatternsAndSeparators($matrix); self::embedDarkDotAtLeftBottomCorner($matrix); self::maybeEmbedPositionAdjustmentPatterns($version, $matrix); self::embedTimingPatterns($matrix); } /** * Embeds position detection patterns and separators into a byte matrix. * * @param ByteMatrix $matrix * @return void */ protected static function embedPositionDetectionPatternsAndSeparators(ByteMatrix $matrix) { $pdpWidth = count(self::$positionDetectionPattern[0]); self::embedPositionDetectionPattern(0, 0, $matrix); self::embedPositionDetectionPattern($matrix->getWidth() - $pdpWidth, 0, $matrix); self::embedPositionDetectionPattern(0, $matrix->getWidth() - $pdpWidth, $matrix); $hspWidth = 8; self::embedHorizontalSeparationPattern(0, $hspWidth - 1, $matrix); self::embedHorizontalSeparationPattern($matrix->getWidth() - $hspWidth, $hspWidth - 1, $matrix); self::embedHorizontalSeparationPattern(0, $matrix->getWidth() - $hspWidth, $matrix); $vspSize = 7; self::embedVerticalSeparationPattern($vspSize, 0, $matrix); self::embedVerticalSeparationPattern($matrix->getHeight() - $vspSize - 1, 0, $matrix); self::embedVerticalSeparationPattern($vspSize, $matrix->getHeight() - $vspSize, $matrix); } /** * Embeds a single position detection pattern into a byte matrix. * * @param integer $xStart * @param integer $yStart * @param ByteMatrix $matrix * @return void */ protected static function embedPositionDetectionPattern($xStart, $yStart, ByteMatrix $matrix) { for ($y = 0; $y < 7; $y++) { for ($x = 0; $x < 7; $x++) { $matrix->set($xStart + $x, $yStart + $y, self::$positionDetectionPattern[$y][$x]); } } } /** * Embeds a single horizontal separation pattern. * * @param integer $xStart * @param integer $yStart * @param ByteMatrix $matrix * @return void * @throws Exception\RuntimeException */ protected static function embedHorizontalSeparationPattern($xStart, $yStart, ByteMatrix $matrix) { for ($x = 0; $x < 8; $x++) { if ($matrix->get($xStart + $x, $yStart) !== -1) { throw new Exception\RuntimeException('Byte already set'); } $matrix->set($xStart + $x, $yStart, 0); } } /** * Embeds a single vertical separation pattern. * * @param integer $xStart * @param integer $yStart * @param ByteMatrix $matrix * @return void * @throws Exception\RuntimeException */ protected static function embedVerticalSeparationPattern($xStart, $yStart, ByteMatrix $matrix) { for ($y = 0; $y < 7; $y++) { if ($matrix->get($xStart, $yStart + $y) !== -1) { throw new Exception\RuntimeException('Byte already set'); } $matrix->set($xStart, $yStart + $y, 0); } } /** * Embeds a dot at the left bottom corner. * * @param ByteMatrix $matrix * @return void * @throws Exception\RuntimeException */ protected static function embedDarkDotAtLeftBottomCorner(ByteMatrix $matrix) { if ($matrix->get(8, $matrix->getHeight() - 8) === 0) { throw new Exception\RuntimeException('Byte already set to 0'); } $matrix->set(8, $matrix->getHeight() - 8, 1); } /** * Embeds position adjustment patterns if required. * * @param Version $version * @param ByteMatrix $matrix * @return void */ protected static function maybeEmbedPositionAdjustmentPatterns(Version $version, ByteMatrix $matrix) { if ($version->getVersionNumber() < 2) { return; } $index = $version->getVersionNumber() - 1; $coordinates = self::$positionAdjustmentPatternCoordinateTable[$index]; $numCoordinates = count($coordinates); for ($i = 0; $i < $numCoordinates; $i++) { for ($j = 0; $j < $numCoordinates; $j++) { $y = $coordinates[$i]; $x = $coordinates[$j]; if ($x === null || $y === null) { continue; } if ($matrix->get($x, $y) === -1) { self::embedPositionAdjustmentPattern($x - 2, $y - 2, $matrix); } } } } /** * Embeds a single position adjustment pattern. * * @param integer $xStart * @param intger $yStart * @param ByteMatrix $matrix * @return void */ protected static function embedPositionAdjustmentPattern($xStart, $yStart, ByteMatrix $matrix) { for ($y = 0; $y < 5; $y++) { for ($x = 0; $x < 5; $x++) { $matrix->set($xStart + $x, $yStart + $y, self::$positionAdjustmentPattern[$y][$x]); } } } /** * Embeds timing patterns into a matrix. * * @param ByteMatrix $matrix * @return void */ protected static function embedTimingPatterns(ByteMatrix $matrix) { $matrixWidth = $matrix->getWidth(); for ($i = 8; $i < $matrixWidth - 8; $i++) { $bit = ($i + 1) % 2; if ($matrix->get($i, 6) === -1) { $matrix->set($i, 6, $bit); } if ($matrix->get(6, $i) === -1) { $matrix->set(6, $i, $bit); } } } /** * Embeds "dataBits" using "getMaskPattern". * * For debugging purposes, it skips masking process if "getMaskPattern" is * -1. See 8.7 of JISX0510:2004 (p.38) for how to embed data bits. * * @param BitArray $dataBits * @param integer $maskPattern * @param ByteMatrix $matrix * @return void * @throws Exception\WriterException */ protected static function embedDataBits(BitArray $dataBits, $maskPattern, ByteMatrix $matrix) { $bitIndex = 0; $direction = -1; // Start from the right bottom cell. $x = $matrix->getWidth() - 1; $y = $matrix->getHeight() - 1; while ($x > 0) { // Skip vertical timing pattern. if ($x === 6) { $x--; } while ($y >= 0 && $y < $matrix->getHeight()) { for ($i = 0; $i < 2; $i++) { $xx = $x - $i; // Skip the cell if it's not empty. if ($matrix->get($xx, $y) !== -1) { continue; } if ($bitIndex < $dataBits->getSize()) { $bit = $dataBits->get($bitIndex); $bitIndex++; } else { // Padding bit. If there is no bit left, we'll fill the // left cells with 0, as described in 8.4.9 of // JISX0510:2004 (p. 24). $bit = false; } // Skip masking if maskPattern is -1. if ($maskPattern !== -1 && MaskUtil::getDataMaskBit($maskPattern, $xx, $y)) { $bit = !$bit; } $matrix->set($xx, $y, $bit); } $y += $direction; } $direction = -$direction; $y += $direction; $x -= 2; } // All bits should be consumed if ($bitIndex !== $dataBits->getSize()) { throw new Exception\WriterException('Not all bits consumed (' . $bitIndex . ' out of ' . $dataBits->getSize() .')'); } } } lib/system/api/qr/src/BaconQrCode/Encoder/Encoder.php 0000644 0000155 0177776 00000053576 12220311243 022667 0 ustar jenkins nogroup get() === Mode::BYTE && $encoding !== self::DEFAULT_BYTE_MODE_ECODING) { $eci = CharacterSetEci::getCharacterSetEciByName($encoding); if ($eci !== null) { self::appendEci($eci, $headerBits); } } // (With ECI in place,) Write the mode marker self::appendModeInfo($mode, $headerBits); // Collect data within the main segment, separately, to count its size // if needed. Don't add it to main payload yet. $dataBits = new BitArray(); self::appendBytes($content, $mode, $dataBits, $encoding); // Hard part: need to know version to know how many bits length takes. // But need to know how many bits it takes to know version. First we // take a guess at version by assuming version will be the minimum, 1: $provisionalBitsNeeded = $headerBits->getSize() + $mode->getCharacterCountBits(Version::getVersionForNumber(1)) + $dataBits->getSize(); $provisionalVersion = self::chooseVersion($provisionalBitsNeeded, $ecLevel); // Use that guess to calculate the right version. I am still not sure // this works in 100% of cases. $bitsNeeded = $headerBits->getSize() + $mode->getCharacterCountBits($provisionalVersion) + $dataBits->getSize(); $version = self::chooseVersion($bitsNeeded, $ecLevel); $headerAndDataBits = new BitArray(); $headerAndDataBits->appendBitArray($headerBits); // Find "length" of main segment and write it. $numLetters = ($mode->get() === Mode::BYTE ? $dataBits->getSizeInBytes() : strlen($content)); self::appendLengthInfo($numLetters, $version, $mode, $headerAndDataBits); // Put data together into the overall payload. $headerAndDataBits->appendBitArray($dataBits); $ecBlocks = $version->getEcBlocksForLevel($ecLevel); $numDataBytes = $version->getTotalCodewords() - $ecBlocks->getTotalEcCodewords(); // Terminate the bits properly. self::terminateBits($numDataBytes, $headerAndDataBits); // Interleave data bits with error correction code. $finalBits = self::interleaveWithEcBytes( $headerAndDataBits, $version->getTotalCodewords(), $numDataBytes, $ecBlocks->getNumBlocks() ); $qrCode = new QrCode(); $qrCode->setErrorCorrectionLevel($ecLevel); $qrCode->setMode($mode); $qrCode->setVersion($version); // Choose the mask pattern and set to "qrCode". $dimension = $version->getDimensionForVersion(); $matrix = new ByteMatrix($dimension, $dimension); $maskPattern = self::chooseMaskPattern($finalBits, $ecLevel, $version, $matrix); $qrCode->setMaskPattern($maskPattern); // Build the matrix and set it to "qrCode". MatrixUtil::buildMatrix($finalBits, $ecLevel, $version, $maskPattern, $matrix); $qrCode->setMatrix($matrix); return $qrCode; } /** * Gets the alphanumeric code for a byte. * * @param string|integer $code * @return integer */ protected static function getAlphanumericCode($code) { $code = (is_string($code) ? ord($code) : $code); if (isset(self::$alphanumericTable[$code])) { return self::$alphanumericTable[$code]; } return -1; } /** * Chooses the best mode for a given content. * * @param string $content * @param string $encoding * @return Mode */ protected static function chooseMode($content, $encoding = null) { if (strcasecmp($encoding, 'SHIFT-JIS') === 0) { return self::isOnlyDoubleByteKanji($content) ? new Mode(Mode::KANJI) : new Mode(Mode::BYTE); } $hasNumeric = false; $hasAlphanumeric = false; $contentLength = strlen($content); for ($i = 0; $i < $contentLength; $i++) { $char = $content[$i]; if (ctype_digit($char)) { $hasNumeric = true; } elseif (self::getAlphanumericCode($char) !== -1) { $hasAlphanumeric = true; } else { return new Mode(Mode::BYTE); } } if ($hasAlphanumeric) { return new Mode(Mode::ALPHANUMERIC); } elseif ($hasNumeric) { return new Mode(Mode::NUMERIC); } return new Mode(Mode::BYTE); } /** * Calculates the mask penalty for a matrix. * * @param ByteMatrix $matrix * @return integer */ protected static function calculateMaskPenalty(ByteMatrix $matrix) { return ( MaskUtil::applyMaskPenaltyRule1($matrix) + MaskUtil::applyMaskPenaltyRule2($matrix) + MaskUtil::applyMaskPenaltyRule3($matrix) + MaskUtil::applyMaskPenaltyRule4($matrix) ); } /** * Chooses the best mask pattern for a matrix. * * @param BitArray $bits * @param ErrorCorrectionLevel $ecLevel * @param Version $version * @param ByteMatrix $matrix * @return integer */ protected static function chooseMaskPattern( BitArray $bits, ErrorCorrectionLevel $ecLevel, Version $version, ByteMatrix $matrix ) { $minPenality = PHP_INT_MAX; $bestMaskPattern = -1; for ($maskPattern = 0; $maskPattern < QrCode::NUM_MASK_PATTERNS; $maskPattern++) { MatrixUtil::buildMatrix($bits, $ecLevel, $version, $maskPattern, $matrix); $penalty = self::calculateMaskPenalty($matrix); if ($penalty < $minPenality) { $minPenality = $penalty; $bestMaskPattern = $maskPattern; } } return $bestMaskPattern; } /** * Chooses the best version for the input. * * @param integer $numInputBits * @param ErrorCorrectionLevel $ecLevel * @return Version * @throws Exception\WriterException */ protected static function chooseVersion($numInputBits, ErrorCorrectionLevel $ecLevel) { for ($versionNum = 1; $versionNum <= 40; $versionNum++) { $version = Version::getVersionForNumber($versionNum); $numBytes = $version->getTotalCodewords(); $ecBlocks = $version->getEcBlocksForLevel($ecLevel); $numEcBytes = $ecBlocks->getTotalEcCodewords(); $numDataBytes = $numBytes - $numEcBytes; $totalInputBytes = intval(($numInputBits + 8) / 8); if ($numDataBytes >= $totalInputBytes) { return $version; } } throw new Exception\WriterException('Data too big'); } /** * Terminates the bits in a bit array. * * @param integer $numDataBytes * @param BitArray $bits * @throws Exception\WriterException */ protected static function terminateBits($numDataBytes, BitArray $bits) { $capacity = $numDataBytes << 3; if ($bits->getSize() > $capacity) { throw new Exception\WriterException('Data bits cannot fit in the QR code'); } for ($i = 0; $i < 4 && $bits->getSize() < $capacity; $i++) { $bits->appendBit(false); } $numBitsInLastByte = $bits->getSize() & 0x7; if ($numBitsInLastByte > 0) { for ($i = $numBitsInLastByte; $i < 8; $i++) { $bits->appendBit(false); } } $numPaddingBytes = $numDataBytes - $bits->getSizeInBytes(); for ($i = 0; $i < $numPaddingBytes; $i++) { $bits->appendBits(($i & 0x1) === 0 ? 0xec : 0x11, 8); } if ($bits->getSize() !== $capacity) { throw new Exception\WriterException('Bits size does not equal capacity'); } } /** * Gets number of data- and EC bytes for a block ID. * * @param integer $numTotalBytes * @param integer $numDataBytes * @param integer $numRsBlocks * @param integer $blockId * @return array * @throws Exception\WriterException */ protected static function getNumDataBytesAndNumEcBytesForBlockId( $numTotalBytes, $numDataBytes, $numRsBlocks, $blockId ) { if ($blockId >= $numRsBlocks) { throw new Exception\WriterException('Block ID too large'); } $numRsBlocksInGroup2 = $numTotalBytes % $numRsBlocks; $numRsBlocksInGroup1 = $numRsBlocks - $numRsBlocksInGroup2; $numTotalBytesInGroup1 = intval($numTotalBytes / $numRsBlocks); $numTotalBytesInGroup2 = $numTotalBytesInGroup1 + 1; $numDataBytesInGroup1 = intval($numDataBytes / $numRsBlocks); $numDataBytesInGroup2 = $numDataBytesInGroup1 + 1; $numEcBytesInGroup1 = $numTotalBytesInGroup1 - $numDataBytesInGroup1; $numEcBytesInGroup2 = $numTotalBytesInGroup2 - $numDataBytesInGroup2; if ($numEcBytesInGroup1 !== $numEcBytesInGroup2) { throw new Exception\WriterException('EC bytes mismatch'); } if ($numRsBlocks !== $numRsBlocksInGroup1 + $numRsBlocksInGroup2) { throw new Exception\WriterException('RS blocks mismatch'); } if ($numTotalBytes !== (($numDataBytesInGroup1 + $numEcBytesInGroup1) * $numRsBlocksInGroup1) + (($numDataBytesInGroup2 + $numEcBytesInGroup2) * $numRsBlocksInGroup2) ) { throw new Exception\WriterException('Total bytes mismatch'); } if ($blockId < $numRsBlocksInGroup1) { return array($numDataBytesInGroup1, $numEcBytesInGroup1); } else { return array($numDataBytesInGroup2, $numEcBytesInGroup2); } } /** * Interleaves data with EC bytes. * * @param BitArray $bits * @param integer $numTotalBytes * @param integer $numDataBytes * @param integer $numRsBlocks * @return BitArray * @throws Exception\WriterException */ protected static function interleaveWithEcBytes(BitArray $bits, $numTotalBytes, $numDataBytes, $numRsBlocks) { if ($bits->getSizeInBytes() !== $numDataBytes) { throw new Exception\WriterException('Number of bits and data bytes does not match'); } $dataBytesOffset = 0; $maxNumDataBytes = 0; $maxNumEcBytes = 0; $blocks = new SplFixedArray($numRsBlocks); for ($i = 0; $i < $numRsBlocks; $i++) { list($numDataBytesInBlock, $numEcBytesInBlock) = self::getNumDataBytesAndNumEcBytesForBlockId( $numTotalBytes, $numDataBytes, $numRsBlocks, $i ); $size = $numDataBytesInBlock; $dataBytes = $bits->toBytes(8 * $dataBytesOffset, $size); $ecBytes = self::generateEcBytes($dataBytes, $numEcBytesInBlock); $blocks[$i] = new BlockPair($dataBytes, $ecBytes); $maxNumDataBytes = max($maxNumDataBytes, $size); $maxNumEcBytes = max($maxNumEcBytes, count($ecBytes)); $dataBytesOffset += $numDataBytesInBlock; } if ($numDataBytes !== $dataBytesOffset) { throw new Exception\WriterException('Data bytes does not match offset'); } $result = new BitArray(); for ($i = 0; $i < $maxNumDataBytes; $i++) { foreach ($blocks as $block) { $dataBytes = $block->getDataBytes(); if ($i < count($dataBytes)) { $result->appendBits($dataBytes[$i], 8); } } } for ($i = 0; $i < $maxNumEcBytes; $i++) { foreach ($blocks as $block) { $ecBytes = $block->getErrorCorrectionBytes(); if ($i < count($ecBytes)) { $result->appendBits($ecBytes[$i], 8); } } } if ($numTotalBytes !== $result->getSizeInBytes()) { throw new Exception\WriterException('Interleaving error: ' . $numTotalBytes . ' and ' . $result->getSizeInBytes() . ' differ'); } return $result; } /** * Generates EC bytes for given data. * * @param SplFixedArray $dataBytes * @param integer $numEcBytesInBlock * @return SplFixedArray */ protected static function generateEcBytes(SplFixedArray $dataBytes, $numEcBytesInBlock) { $numDataBytes = count($dataBytes); $toEncode = new SplFixedArray($numDataBytes + $numEcBytesInBlock); for ($i = 0; $i < $numDataBytes; $i++) { $toEncode[$i] = $dataBytes[$i] & 0xff; } $ecBytes = new SplFixedArray($numEcBytesInBlock); $codec = self::getCodec($numDataBytes, $numEcBytesInBlock); $codec->encode($toEncode, $ecBytes); return $ecBytes; } /** * Gets an RS codec and caches it. * * @param integer $numDataBytes * @param integer $numEcBytesInBlock * @return ReedSolomonCodec */ protected static function getCodec($numDataBytes, $numEcBytesInBlock) { $cacheId = $numDataBytes . '-' . $numEcBytesInBlock; if (!isset(self::$codecs[$cacheId])) { self::$codecs[$cacheId] = new ReedSolomonCodec( 8, 0x11d, 0, 1, $numEcBytesInBlock, 255 - $numDataBytes - $numEcBytesInBlock ); } return self::$codecs[$cacheId]; } /** * Appends mode information to a bit array. * * @param Mode $mode * @param BitArray $bits * @return void */ protected static function appendModeInfo(Mode $mode, BitArray $bits) { $bits->appendBits($mode->get(), 4); } /** * Appends length information to a bit array. * * @param integer $numLetters * @param Version $version * @param Mode $mode * @param BitArray $bits * @return void * @throws Exception\WriterException */ protected static function appendLengthInfo($numLetters, Version $version, Mode $mode, BitArray $bits) { $numBits = $mode->getCharacterCountBits($version); if ($numLetters >= (1 << $numBits)) { throw new Exception\WriterException($numLetters . ' is bigger than ' . ((1 << $numBits) - 1)); } $bits->appendBits($numLetters, $numBits); } /** * Appends bytes to a bit array in a specific mode. * * @param stirng $content * @param Mode $mode * @param BitArray $bits * @param string $encoding * @return void * @throws Exception\WriterException */ protected static function appendBytes($content, Mode $mode, BitArray $bits, $encoding) { switch ($mode->get()) { case Mode::NUMERIC: self::appendNumericBytes($content, $bits); break; case Mode::ALPHANUMERIC: self::appendAlphanumericBytes($content, $bits); break; case Mode::BYTE: self::append8BitBytes($content, $bits, $encoding); break; case Mode::KANJI: self::appendKanjiBytes($content, $bits); break; default: throw new Exception\WriterException('Invalid mode: ' . $mode->get()); } } /** * Appends numeric bytes to a bit array. * * @param string $content * @param BitArray $bits * @return void */ protected static function appendNumericBytes($content, BitArray $bits) { $length = strlen($content); $i = 0; while ($i < $length) { $num1 = (int) $content[$i]; if ($i + 2 < $length) { // Encode three numeric letters in ten bits. $num2 = (int) $content[$i + 1]; $num3 = (int) $content[$i + 2]; $bits->appendBits($num1 * 100 + $num2 * 10 + $num3, 10); $i += 3; } elseif ($i + 1 < $length) { // Encode two numeric letters in seven bits. $num2 = (int) $content[$i + 1]; $bits->appendBits($num1 * 10 + $num2, 7); $i += 2; } else { // Encode one numeric letter in four bits. $bits->appendBits($num1, 4); $i++; } } } /** * Appends alpha-numeric bytes to a bit array. * * @param string $content * @param BitArray $bits * @return void */ protected static function appendAlphanumericBytes($content, BitArray $bits) { $length = strlen($content); $i = 0; while ($i < $length) { if (-1 === ($code1 = self::getAlphanumericCode($content[$i]))) { throw new Exception\WriterException('Invalid alphanumeric code'); } if ($i + 1 < $length) { if (-1 === ($code2 = self::getAlphanumericCode($content[$i + 1]))) { throw new Exception\WriterException('Invalid alphanumeric code'); } // Encode two alphanumeric letters in 11 bits. $bits->appendBits($code1 * 45 + $code2, 11); $i += 2; } else { // Encode one alphanumeric letter in six bits. $bits->appendBits($code1, 6); $i++; } } } /** * Appends regular 8-bit bytes to a bit array. * * @param string $content * @param BitArray $bits * @return void */ protected static function append8BitBytes($content, BitArray $bits, $encoding) { if (false === ($bytes = @iconv('utf-8', $encoding, $content))) { throw new Exception\WriterException('Could not encode content to ' . $encoding); } $length = strlen($bytes); for ($i = 0; $i < $length; $i++) { $bits->appendBits(ord($bytes[$i]), 8); } } /** * Appends KANJI bytes to a bit array. * * @param string $content * @param BitArray $bits * @return void */ protected static function appendKanjiBytes($content, BitArray $bits) { if (strlen($content) % 2 > 0) { // We just do a simple length check here. The for loop will check // individual characters. throw new Exception\WriterException('Content does not seem to be encoded in SHIFT-JIS'); } $length = strlen($content); for ($i = 0; $i < $length; $i += 2) { $byte1 = ord($content[$i]) & 0xff; $byte2 = ord($content[$i + 1]) & 0xff; $code = ($byte1 << 8) | $byte2; if ($code >= 0x8140 && $code <= 0x9ffc) { $subtracted = $code - 0x8140; } elseif ($code >= 0xe040 && $code <= 0xebbf) { $subtracted = $code - 0xc140; } else { throw new Exception\WriterException('Invalid byte sequence'); } $encoded = (($subtracted >> 8) * 0xc0) + ($subtracted & 0xff); $bits->appendBits($encoded, 13); } } /** * Appends ECI information to a bit array. * * @param CharacterSetEci $eci * @param BitArray $bits * @return void */ protected static function appendEci(CharacterSetEci $eci, BitArray $bits) { $mode = new Mode(Mode::ECI); $bits->appendBits($mode->get(), 4); $bits->appendBits($eci->get(), 8); } } lib/system/api/qr/README.md 0000644 0000155 0177776 00000000761 12220311243 015554 0 ustar jenkins nogroup QR Code generator ================= Master: [![Build Status](https://api.travis-ci.org/Bacon/BaconQrCode.png?branch=master)](http://travis-ci.org/Bacon/BaconQrCode) Introduction ------------ BaconQrCode is a port of QR code portion of the ZXing library. It currently only features the encoder part, but could later receive the decoder part as well. As the Reed Solomon codec implementation of the ZXing library performs quite slow in PHP, it was exchanged with the implementation by Phil Karn. lib/system/api/qr/autoload_classmap.php 0000644 0000155 0177776 00000011317 12220311243 020500 0 ustar jenkins nogroup __DIR__ . '/src/BaconQrCode/Common/AbstractEnum.php', 'BaconQrCode\Common\BitArray' => __DIR__ . '/src/BaconQrCode/Common/BitArray.php', 'BaconQrCode\Common\BitMatrix' => __DIR__ . '/src/BaconQrCode/Common/BitMatrix.php', 'BaconQrCode\Common\BitUtils' => __DIR__ . '/src/BaconQrCode/Common/BitUtils.php', 'BaconQrCode\Common\CharacterSetEci' => __DIR__ . '/src/BaconQrCode/Common/CharacterSetEci.php', 'BaconQrCode\Common\EcBlock' => __DIR__ . '/src/BaconQrCode/Common/EcBlock.php', 'BaconQrCode\Common\EcBlocks' => __DIR__ . '/src/BaconQrCode/Common/EcBlocks.php', 'BaconQrCode\Common\ErrorCorrectionLevel' => __DIR__ . '/src/BaconQrCode/Common/ErrorCorrectionLevel.php', 'BaconQrCode\Common\FormatInformation' => __DIR__ . '/src/BaconQrCode/Common/FormatInformation.php', 'BaconQrCode\Common\Mode' => __DIR__ . '/src/BaconQrCode/Common/Mode.php', 'BaconQrCode\Common\ReedSolomonCodec' => __DIR__ . '/src/BaconQrCode/Common/ReedSolomonCodec.php', 'BaconQrCode\Common\Version' => __DIR__ . '/src/BaconQrCode/Common/Version.php', 'BaconQrCode\Encoder\BlockPair' => __DIR__ . '/src/BaconQrCode/Encoder/BlockPair.php', 'BaconQrCode\Encoder\ByteMatrix' => __DIR__ . '/src/BaconQrCode/Encoder/ByteMatrix.php', 'BaconQrCode\Encoder\Encoder' => __DIR__ . '/src/BaconQrCode/Encoder/Encoder.php', 'BaconQrCode\Encoder\MaskUtil' => __DIR__ . '/src/BaconQrCode/Encoder/MaskUtil.php', 'BaconQrCode\Encoder\MatrixUtil' => __DIR__ . '/src/BaconQrCode/Encoder/MatrixUtil.php', 'BaconQrCode\Encoder\QrCode' => __DIR__ . '/src/BaconQrCode/Encoder/QrCode.php', 'BaconQrCode\Exception\ExceptionInterface' => __DIR__ . '/src/BaconQrCode/Exception/ExceptionInterface.php', 'BaconQrCode\Exception\InvalidArgumentException' => __DIR__ . '/src/BaconQrCode/Exception/InvalidArgumentException.php', 'BaconQrCode\Exception\OutOfBoundsException' => __DIR__ . '/src/BaconQrCode/Exception/OutOfBoundsException.php', 'BaconQrCode\Exception\RuntimeException' => __DIR__ . '/src/BaconQrCode/Exception/RuntimeException.php', 'BaconQrCode\Exception\UnexpectedValueException' => __DIR__ . '/src/BaconQrCode/Exception/UnexpectedValueException.php', 'BaconQrCode\Exception\WriterException' => __DIR__ . '/src/BaconQrCode/Exception/WriterException.php', 'BaconQrCode\Renderer\Color\Cmyk' => __DIR__ . '/src/BaconQrCode/Renderer/Color/Cmyk.php', 'BaconQrCode\Renderer\Color\ColorInterface' => __DIR__ . '/src/BaconQrCode/Renderer/Color/ColorInterface.php', 'BaconQrCode\Renderer\Color\Gray' => __DIR__ . '/src/BaconQrCode/Renderer/Color/Gray.php', 'BaconQrCode\Renderer\Color\Rgb' => __DIR__ . '/src/BaconQrCode/Renderer/Color/Rgb.php', 'BaconQrCode\Renderer\Image\AbstractRenderer' => __DIR__ . '/src/BaconQrCode/Renderer/Image/AbstractRenderer.php', 'BaconQrCode\Renderer\Image\Decorator\DecoratorInterface' => __DIR__ . '/src/BaconQrCode/Renderer/Image/Decorator/DecoratorInterface.php', 'BaconQrCode\Renderer\Image\Decorator\FinderPattern' => __DIR__ . '/src/BaconQrCode/Renderer/Image/Decorator/FinderPattern.php', 'BaconQrCode\Renderer\Image\Eps' => __DIR__ . '/src/BaconQrCode/Renderer/Image/Eps.php', 'BaconQrCode\Renderer\Image\Png' => __DIR__ . '/src/BaconQrCode/Renderer/Image/Png.php', 'BaconQrCode\Renderer\Image\RendererInterface' => __DIR__ . '/src/BaconQrCode/Renderer/Image/RendererInterface.php', 'BaconQrCode\Renderer\Image\Svg' => __DIR__ . '/src/BaconQrCode/Renderer/Image/Svg.php', 'BaconQrCode\Renderer\RendererInterface' => __DIR__ . '/src/BaconQrCode/Renderer/RendererInterface.php', 'BaconQrCode\Renderer\Text\Plain' => __DIR__ . '/src/BaconQrCode/Renderer/Text/Plain.php', 'BaconQrCode\Renderer\Text\Html' => __DIR__ . '/src/BaconQrCode/Renderer/Text/Html.php', 'BaconQrCode\Writer' => __DIR__ . '/src/BaconQrCode/Writer.php', ); lib/system/api/qr/.travis.yml 0000644 0000155 0177776 00000000203 12220311243 016375 0 ustar jenkins nogroup language: php php: - 5.3 - 5.4 - 5.5 script: phpunit --bootstrap tests/bootstrap.php --configuration tests/phpunit.xml tests lib/system/api/qr/tests/ 0000755 0000155 0177776 00000000000 12220311243 015433 5 ustar jenkins nogroup lib/system/api/qr/tests/BaconQrCode/ 0000755 0000155 0177776 00000000000 12220311243 017553 5 ustar jenkins nogroup lib/system/api/qr/tests/BaconQrCode/Common/ 0000755 0000155 0177776 00000000000 12220311243 021003 5 ustar jenkins nogroup lib/system/api/qr/tests/BaconQrCode/Common/ReedSolomonCodecTest.php 0000644 0000155 0177776 00000006725 12220311243 025552 0 ustar jenkins nogroup encode($block, $parity); // Copy parity into test blocks for ($i = 0; $i < $numRoots; $i++) { $block[$i + $dataSize] = $parity[$i]; $tBlock[$i + $dataSize] = $parity[$i]; } // Seed with errors for ($i = 0; $i < $errors; $i++) { $errorValue = mt_rand(1, $blockSize); do { $errorLocation = mt_rand(0, $blockSize); } while ($errorLocations[$errorLocation] !== 0); $errorLocations[$errorLocation] = 1; if (mt_rand(0, 1)) { $erasures[] = $errorLocation; } $tBlock[$errorLocation] ^= $errorValue; } $erasures = SplFixedArray::fromArray($erasures); // Decode the errored block $foundErrors = $codec->decode($tBlock, $erasures); if ($errors > 0 && $foundErrors === null) { $this->assertEquals($block, $tBlock, 'Decoder failed to correct errors'); } $this->assertEquals($errors, $foundErrors, 'Found errors do not equal expected errors'); for ($i = 0; $i < $foundErrors; $i++) { if ($errorLocations[$erasures[$i]] === 0) { $this->fail(sprintf('Decoder indicates error in location %d without error', $erasures[$i])); } } $this->assertEquals($block, $tBlock, 'Decoder did not correct errors'); } } } lib/system/api/qr/tests/BaconQrCode/Common/ErrorCorrectionLevelTest.php 0000644 0000155 0177776 00000002370 12220311243 026467 0 ustar jenkins nogroup assertEquals(0x0, ErrorCorrectionLevel::M); $this->assertEquals(0x1, ErrorCorrectionLevel::L); $this->assertEquals(0x2, ErrorCorrectionLevel::H); $this->assertEquals(0x3, ErrorCorrectionLevel::Q); } public function testInvalidErrorCorrectionLevelThrowsException() { $this->setExpectedException( 'BaconQrCode\Exception\UnexpectedValueException', 'Value not a const in enum BaconQrCode\Common\ErrorCorrectionLevel' ); new ErrorCorrectionLevel(4); } } lib/system/api/qr/tests/BaconQrCode/Common/BitArrayTest.php 0000644 0000155 0177776 00000011465 12220311243 024100 0 ustar jenkins nogroup assertFalse($array->get($i)); $array->set($i); $this->assertTrue($array->get($i)); } } public function testGetNextSet1() { $array = new BitArray(32); for ($i = 0; $i < $array->getSize(); $i++) { $this->assertEquals($i, 32, '', $array->getNextSet($i)); } $array = new BitArray(33); for ($i = 0; $i < $array->getSize(); $i++) { $this->assertEquals($i, 33, '', $array->getNextSet($i)); } } public function testGetNextSet2() { $array = new BitArray(33); for ($i = 0; $i < $array->getSize(); $i++) { $this->assertEquals($i, $i <= 31 ? 31 : 33, '', $array->getNextSet($i)); } $array = new BitArray(33); for ($i = 0; $i < $array->getSize(); $i++) { $this->assertEquals($i, 32, '', $array->getNextSet($i)); } } public function testGetNextSet3() { $array = new BitArray(63); $array->set(31); $array->set(32); for ($i = 0; $i < $array->getSize(); $i++) { if ($i <= 31) { $expected = 31; } elseif ($i <= 32) { $expected = 32; } else { $expected = 63; } $this->assertEquals($i, $expected, '', $array->getNextSet($i)); } } public function testGetNextSet4() { $array = new BitArray(63); $array->set(33); $array->set(40); for ($i = 0; $i < $array->getSize(); $i++) { if ($i <= 33) { $expected = 33; } elseif ($i <= 40) { $expected = 40; } else { $expected = 63; } $this->assertEquals($i, $expected, '', $array->getNextSet($i)); } } public function testGetNextSet5() { mt_srand(hexdec('deadbeef')); for ($i = 0; $i < 10; $i++) { $array = new BitArray(mt_rand(1, 100)); $numSet = mt_rand(0, 19); for ($j = 0; $j < $numSet; $j++) { $array->set(mt_rand(0, $array->getSize() - 1)); } $numQueries = mt_rand(0, 19); for ($j = 0; $j < $numQueries; $j++) { $query = mt_rand(0, $array->getSize() - 1); $expected = $query; while ($expected < $array->getSize() && !$array->get($expected)) { $expected++; } $actual = $array->getNextSet($query); if ($actual !== $expected) { $array->getNextSet($query); } $this->assertEquals($expected, $actual); } } } public function testSetBulk() { $array = new BitArray(64); $array->setBulk(32, 0xFFFF0000); for ($i = 0; $i < 48; $i++) { $this->assertFalse($array->get($i)); } for ($i = 48; $i < 64; $i++) { $this->assertTrue($array->get($i)); } } public function testClear() { $array = new BitArray(32); for ($i = 0; $i < 32; $i++) { $array->set($i); } $array->clear(); for ($i = 0; $i < 32; $i++) { $this->assertFalse($array->get($i)); } } public function testGetArray() { $array = new BitArray(64); $array->set(0); $array->set(63); $ints = $array->getBitArray(); $this->assertEquals(1, $ints[0]); $this->assertEquals(0x80000000, $ints[1]); } public function testIsRange() { $array = new BitArray(64); $this->assertTrue($array->isRange(0, 64, false)); $this->assertFalse($array->isRange(0, 64, true)); $array->set(32); $this->assertTrue($array->isRange(32, 33, true)); $array->set(31); $this->assertTrue($array->isRange(31, 33, true)); $array->set(34); $this->assertFalse($array->isRange(31, 35, true)); for ($i = 0; $i < 31; $i++) { $array->set($i); } $this->assertTrue($array->isRange(0, 33, true)); for ($i = 33; $i < 64; $i++) { $array->set($i); } $this->assertTrue($array->isRange(0, 64, true)); $this->assertFalse($array->isRange(0, 64, false)); } } lib/system/api/qr/tests/BaconQrCode/Common/BitMatrixTest.php 0000644 0000155 0177776 00000006445 12220311243 024270 0 ustar jenkins nogroup assertEquals(33, $matrix->getHeight()); for ($y = 0; $y < 33; $y++) { for ($x = 0; $x < 33; $x++) { if ($y * $x % 3 === 0) { $matrix->set($x, $y); } } } for ($y = 0; $y < 33; $y++) { for ($x = 0; $x < 33; $x++) { $this->assertEquals($x * $y % 3 === 0, $matrix->get($x, $y)); } } } public function testSetRegion() { $matrix = new BitMatrix(5); $matrix->setRegion(1, 1, 3, 3); for ($y = 0; $y < 5; $y++) { for ($x = 0; $x < 5; $x++) { $this->assertEquals($y >= 1 && $y <= 3 && $x >= 1 && $x <= 3, $matrix->get($x, $y)); } } } public function testRectangularMatrix() { $matrix = new BitMatrix(75, 20); $this->assertEquals(75, $matrix->getWidth()); $this->assertEquals(20, $matrix->getHeight()); $matrix->set(10, 0); $matrix->set(11, 1); $matrix->set(50, 2); $matrix->set(51, 3); $matrix->flip(74, 4); $matrix->flip(0, 5); $this->assertTrue($matrix->get(10, 0)); $this->assertTrue($matrix->get(11, 1)); $this->assertTrue($matrix->get(50, 2)); $this->assertTrue($matrix->get(51, 3)); $this->assertTrue($matrix->get(74, 4)); $this->assertTrue($matrix->get(0, 5)); $matrix->flip(50, 2); $matrix->flip(51, 3); $this->assertFalse($matrix->get(50, 2)); $this->assertFalse($matrix->get(51, 3)); } public function testRectangularSetRegion() { $matrix = new BitMatrix(320, 240); $this->assertEquals(320, $matrix->getWidth()); $this->assertEquals(240, $matrix->getHeight()); $matrix->setRegion(105, 22, 80, 12); for ($y = 0; $y < 240; $y++) { for ($x = 0; $x < 320; $x++) { $this->assertEquals($y >= 22 && $y < 34 && $x >= 105 && $x < 185, $matrix->get($x, $y)); } } } public function testGetRow() { $matrix = new BitMatrix(102, 5); for ($x = 0; $x < 102; $x++) { if ($x & 3 === 0) { $matrix->set($x, 2); } } $array1 = $matrix->getRow(2, null); $this->assertEquals(102, $array1->getSize()); $array2 = new BitArray(60); $array2 = $matrix->getRow(2, $array2); $this->assertEquals(102, $array2->getSize()); $array3 = new BitArray(200); $array3 = $matrix->getRow(2, $array3); $this->assertEquals(200, $array3->getSize()); for ($x = 0; $x < 102; $x++) { $on = ($x & 3 === 0); $this->assertEquals($on, $array1->get($x)); $this->assertEquals($on, $array2->get($x)); $this->assertEquals($on, $array3->get($x)); } } } lib/system/api/qr/tests/BaconQrCode/Common/VersionTest.php 0000644 0000155 0177776 00000005427 12220311243 024011 0 ustar jenkins nogroup assertNotNull($version); $this->assertEquals($versionNumber, $version->getVersionNumber()); $this->assertNotNull($version->getAlignmentPatternCenters()); if ($versionNumber > 1) { $this->assertTrue(count($version->getAlignmentPatternCenters()) > 0); } $this->assertEquals($dimension, $version->getDimensionForVersion()); $this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::H))); $this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::L))); $this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::M))); $this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::Q))); $this->assertNotNull($version->buildFunctionPattern()); } /** * @dataProvider versionProvider * @param integer $versionNumber * @param integer $dimension */ public function testGetProvisionalVersionForDimension($versionNumber, $dimension) { $this->assertEquals( $versionNumber, Version::getProvisionalVersionForDimension($dimension)->getVersionNumber() ); } /** * @dataProvider decodeInformationProvider * @param integer $expectedVersion * @param integer $mask */ public function testDecodeVersionInformation($expectedVersion, $mask) { $version = Version::decodeVersionInformation($mask); $this->assertNotNull($version); $this->assertEquals($expectedVersion, $version->getVersionNumber()); } } lib/system/api/qr/tests/BaconQrCode/Common/BitUtilsTest.php 0000644 0000155 0177776 00000001706 12220311243 024117 0 ustar jenkins nogroup assertEquals(1, BitUtils::unsignedRightShift(1, 0)); $this->assertEquals(1, BitUtils::unsignedRightShift(10, 3)); $this->assertEquals(536870910, BitUtils::unsignedRightShift(-10, 3)); } public function testNumberOfTrailingZeros() { $this->assertEquals(32, BitUtils::numberOfTrailingZeros(0)); $this->assertEquals(1, BitUtils::numberOfTrailingZeros(10)); $this->assertEquals(0, BitUtils::numberOfTrailingZeros(15)); $this->assertEquals(2, BitUtils::numberOfTrailingZeros(20)); } } lib/system/api/qr/tests/BaconQrCode/Common/ModeTest.php 0000644 0000155 0177776 00000002201 12220311243 023233 0 ustar jenkins nogroup assertEquals(0x0, Mode::TERMINATOR); $this->assertEquals(0x1, Mode::NUMERIC); $this->assertEquals(0x2, Mode::ALPHANUMERIC); $this->assertEquals(0x4, Mode::BYTE); $this->assertEquals(0x8, Mode::KANJI); } public function testInvalidModeThrowsException() { $this->setExpectedException( 'BaconQrCode\Exception\UnexpectedValueException', 'Value not a const in enum BaconQrCode\Common\Mode' ); new Mode(10); } } lib/system/api/qr/tests/BaconQrCode/Common/FormatInformationTest.php 0000644 0000155 0177776 00000006073 12220311243 026020 0 ustar jenkins nogroup unmaskedTestFormatInfo = $this->maskedTestFormatInfo ^ 0x5412; } public function testBitsDiffering() { $this->assertEquals(0, FormatInformation::numBitsDiffering(1, 1)); $this->assertEquals(1, FormatInformation::numBitsDiffering(0, 2)); $this->assertEquals(2, FormatInformation::numBitsDiffering(1, 2)); $this->assertEquals(32, FormatInformation::numBitsDiffering(-1, 0)); } public function testDecode() { $expected = FormatInformation::decodeFormatInformation( $this->maskedTestFormatInfo, $this->maskedTestFormatInfo ); $this->assertNotNull($expected); $this->assertEquals(7, $expected->getDataMask()); $this->assertEquals(ErrorCorrectionLevel::Q, $expected->getErrorCorrectionLevel()->get()); $this->assertEquals( $expected, FormatInformation::decodeFormatInformation( $this->unmaskedTestFormatInfo, $this->maskedTestFormatInfo ) ); } public function testDecodeWithBitDifference() { $expected = FormatInformation::decodeFormatInformation( $this->maskedTestFormatInfo, $this->maskedTestFormatInfo ); $this->assertEquals( $expected, FormatInformation::decodeFormatInformation( $this->maskedTestFormatInfo ^ 0x1, $this->maskedTestFormatInfo ^ 0x1 ) ); $this->assertEquals( $expected, FormatInformation::decodeFormatInformation( $this->maskedTestFormatInfo ^ 0x3, $this->maskedTestFormatInfo ^ 0x3 ) ); $this->assertEquals( $expected, FormatInformation::decodeFormatInformation( $this->maskedTestFormatInfo ^ 0x7, $this->maskedTestFormatInfo ^ 0x7 ) ); $this->assertNull( FormatInformation::decodeFormatInformation( $this->maskedTestFormatInfo ^ 0xf, $this->maskedTestFormatInfo ^ 0xf ) ); } public function testDecodeWithMisRead() { $expected = FormatInformation::decodeFormatInformation( $this->maskedTestFormatInfo, $this->maskedTestFormatInfo ); $this->assertEquals( $expected, FormatInformation::decodeFormatInformation( $this->maskedTestFormatInfo ^ 0x3, $this->maskedTestFormatInfo ^ 0xf ) ); } } lib/system/api/qr/tests/BaconQrCode/Renderer/ 0000755 0000155 0177776 00000000000 12220311243 021321 5 ustar jenkins nogroup lib/system/api/qr/tests/BaconQrCode/Renderer/Text/ 0000755 0000155 0177776 00000000000 12220311243 022245 5 ustar jenkins nogroup lib/system/api/qr/tests/BaconQrCode/Renderer/Text/TextTest.php 0000644 0000155 0177776 00000013270 12220311243 024545 0 ustar jenkins nogroup renderer = new Plain(); $this->writer = new Writer($this->renderer); } public function testBasicRender() { $content = 'foobar'; $expected = " \n" . " ███████ █████ ███████ \n" . " █ █ █ █ █ █ \n" . " █ ███ █ ██ █ ███ █ \n" . " █ ███ █ ███ █ ███ █ \n" . " █ ███ █ █ █ █ ███ █ \n" . " █ █ ██ █ █ \n" . " ███████ █ █ █ ███████ \n" . " █████ \n" . " ██ ██ █ ██ █ █ █ \n" . " ██ ██ █ █ ██ \n" . " ████████ █ ██ █ ██ \n" . " ██ █ █ \n" . " ██ ███ █ █ █ █ \n" . " █ ███ █ █ \n" . " ███████ ██ ██████ \n" . " █ █ ████ ██ \n" . " █ ███ █ ██ ██ ██ █ ██ \n" . " █ ███ █ ██ ██ █ ██ \n" . " █ ███ █ █ █ ██ ██ \n" . " █ █ ███ ███ ████ \n" . " ███████ ████ ██ \n" . " \n" ; $qrCode = Encoder::encode( $content, new ErrorCorrectionLevel(ErrorCorrectionLevel::L), Encoder::DEFAULT_BYTE_MODE_ECODING ); $this->assertEquals($expected, $this->renderer->render($qrCode)); } public function testBasicRenderNoMargins() { $content = 'foobar'; $expected = "███████ █████ ███████\n" . "█ █ █ █ █ █\n" . "█ ███ █ ██ █ ███ █\n" . "█ ███ █ ███ █ ███ █\n" . "█ ███ █ █ █ █ ███ █\n" . "█ █ ██ █ █\n" . "███████ █ █ █ ███████\n" . " █████ \n" . "██ ██ █ ██ █ █ █\n" . " ██ ██ █ █ ██ \n" . " ████████ █ ██ █ ██\n" . " ██ █ █\n" . " ██ ███ █ █ █ █\n" . " █ ███ █ █ \n" . "███████ ██ ██████ \n" . "█ █ ████ ██ \n" . "█ ███ █ ██ ██ ██ █ ██\n" . "█ ███ █ ██ ██ █ ██ \n" . "█ ███ █ █ █ ██ ██\n" . "█ █ ███ ███ ████\n" . "███████ ████ ██ \n" ; $qrCode = Encoder::encode( $content, new ErrorCorrectionLevel(ErrorCorrectionLevel::L), Encoder::DEFAULT_BYTE_MODE_ECODING ); $this->renderer->setMargin(0); $this->assertEquals(0, $this->renderer->getMargin()); $this->assertEquals($expected, $this->renderer->render($qrCode)); } public function testBasicRenderCustomChar() { $content = 'foobar'; $expected = "-----------------------\n" . "-#######-#####-#######-\n" . "-#-----#--#-#--#-----#-\n" . "-#-###-#--##---#-###-#-\n" . "-#-###-#--###--#-###-#-\n" . "-#-###-#---#-#-#-###-#-\n" . "-#-----#----##-#-----#-\n" . "-#######-#-#-#-#######-\n" . "---------#####---------\n" . "-##-##-#--##-#-#-----#-\n" . "----##----##-#-#-##----\n" . "--########-#--##-#--##-\n" . "-----------##------#-#-\n" . "--##--###--#---#--#--#-\n" . "---------#-###----#-#--\n" . "-#######--##-######----\n" . "-#-----#---####---##---\n" . "-#-###-#-##-##-##-#-##-\n" . "-#-###-#-##-##--#-##---\n" . "-#-###-#---#---#-##-##-\n" . "-#-----#-###--###-####-\n" . "-#######-####---##-----\n" . "-----------------------\n" ; $qrCode = Encoder::encode( $content, new ErrorCorrectionLevel(ErrorCorrectionLevel::L), Encoder::DEFAULT_BYTE_MODE_ECODING ); $this->renderer->setFullBlock('#'); $this->renderer->setEmptyBlock('-'); $this->assertEquals('#', $this->renderer->getFullBlock()); $this->assertEquals('-', $this->renderer->getEmptyBlock()); $this->assertEquals($expected, $this->renderer->render($qrCode)); } } lib/system/api/qr/tests/BaconQrCode/Renderer/Text/HtmlTest.php 0000644 0000155 0177776 00000006712 12220311243 024530 0 ustar jenkins nogroup renderer = new Html(); $this->writer = new Writer($this->renderer); } public function testBasicRender() { $content = 'foobar'; $expected = '
' . " \n" . " ███████ █████ ███████ \n" . " █ █ █ █ █ █ \n" . " █ ███ █ ██ █ ███ █ \n" . " █ ███ █ ███ █ ███ █ \n" . " █ ███ █ █ █ █ ███ █ \n" . " █ █ ██ █ █ \n" . " ███████ █ █ █ ███████ \n" . " █████ \n" . " ██ ██ █ ██ █ █ █ \n" . " ██ ██ █ █ ██ \n" . " ████████ █ ██ █ ██ \n" . " ██ █ █ \n" . " ██ ███ █ █ █ █ \n" . " █ ███ █ █ \n" . " ███████ ██ ██████ \n" . " █ █ ████ ██ \n" . " █ ███ █ ██ ██ ██ █ ██ \n" . " █ ███ █ ██ ██ █ ██ \n" . " █ ███ █ █ █ ██ ██ \n" . " █ █ ███ ███ ████ \n" . " ███████ ████ ██ \n" . " \n" . '' ; $qrCode = Encoder::encode( $content, new ErrorCorrectionLevel(ErrorCorrectionLevel::L), Encoder::DEFAULT_BYTE_MODE_ECODING ); $this->assertEquals($expected, $this->renderer->render($qrCode)); } public function testSetStyle() { $content = 'foobar'; $qrCode = Encoder::encode( $content, new ErrorCorrectionLevel(ErrorCorrectionLevel::L), Encoder::DEFAULT_BYTE_MODE_ECODING ); $this->renderer->setStyle('bar'); $this->assertEquals('bar', $this->renderer->getStyle()); $this->assertStringMatchesFormat('%astyle="bar"%a', $this->renderer->render($qrCode)); } public function testSetClass() { $content = 'foobar'; $qrCode = Encoder::encode( $content, new ErrorCorrectionLevel(ErrorCorrectionLevel::L), Encoder::DEFAULT_BYTE_MODE_ECODING ); $this->renderer->setClass('bar'); $this->assertEquals('bar', $this->renderer->getClass()); $this->assertStringMatchesFormat('%aclass="bar"%a', $this->renderer->render($qrCode)); } } lib/system/api/qr/tests/BaconQrCode/Encoder/ 0000755 0000155 0177776 00000000000 12220311243 021132 5 ustar jenkins nogroup lib/system/api/qr/tests/BaconQrCode/Encoder/MaskUtilTest.php 0000644 0000155 0177776 00000021355 12220311243 024242 0 ustar jenkins nogroup fail('Data mask bit did not match'); } } } } public function testApplyMaskPenaltyRule1() { $matrix = new ByteMatrix(4, 1); $matrix->set(0, 0, 0); $matrix->set(1, 0, 0); $matrix->set(2, 0, 0); $matrix->set(3, 0, 0); $this->assertEquals(0, MaskUtil::applyMaskPenaltyRule1($matrix)); // Horizontal $matrix = new ByteMatrix(6, 1); $matrix->set(0, 0, 0); $matrix->set(1, 0, 0); $matrix->set(2, 0, 0); $matrix->set(3, 0, 0); $matrix->set(4, 0, 0); $matrix->set(5, 0, 1); $this->assertEquals(3, MaskUtil::applyMaskPenaltyRule1($matrix)); $matrix->set(5, 0, 0); $this->assertEquals(4, MaskUtil::applyMaskPenaltyRule1($matrix)); // Vertical $matrix = new ByteMatrix(1, 6); $matrix->set(0, 0, 0); $matrix->set(0, 1, 0); $matrix->set(0, 2, 0); $matrix->set(0, 3, 0); $matrix->set(0, 4, 0); $matrix->set(0, 5, 1); $this->assertEquals(3, MaskUtil::applyMaskPenaltyRule1($matrix)); $matrix->set(0, 5, 0); $this->assertEquals(4, MaskUtil::applyMaskPenaltyRule1($matrix)); } public function testApplyMaskPenaltyRule2() { $matrix = new ByteMatrix(1, 1); $matrix->set(0, 0, 0); $this->assertEquals(0, MaskUtil::applyMaskPenaltyRule2($matrix)); $matrix = new ByteMatrix(2, 2); $matrix->set(0, 0, 0); $matrix->set(1, 0, 0); $matrix->set(0, 1, 0); $matrix->set(1, 1, 1); $this->assertEquals(0, MaskUtil::applyMaskPenaltyRule2($matrix)); $matrix = new ByteMatrix(2, 2); $matrix->set(0, 0, 0); $matrix->set(1, 0, 0); $matrix->set(0, 1, 0); $matrix->set(1, 1, 0); $this->assertEquals(3, MaskUtil::applyMaskPenaltyRule2($matrix)); $matrix = new ByteMatrix(3, 3); $matrix->set(0, 0, 0); $matrix->set(1, 0, 0); $matrix->set(2, 0, 0); $matrix->set(0, 1, 0); $matrix->set(1, 1, 0); $matrix->set(2, 1, 0); $matrix->set(0, 2, 0); $matrix->set(1, 2, 0); $matrix->set(2, 2, 0); $this->assertEquals(3 * 4, MaskUtil::applyMaskPenaltyRule2($matrix)); } public function testApplyMaskPenalty3() { // Horizontal 00001011101 $matrix = new ByteMatrix(11, 1); $matrix->set(0, 0, 0); $matrix->set(1, 0, 0); $matrix->set(2, 0, 0); $matrix->set(3, 0, 0); $matrix->set(4, 0, 1); $matrix->set(5, 0, 0); $matrix->set(6, 0, 1); $matrix->set(7, 0, 1); $matrix->set(8, 0, 1); $matrix->set(9, 0, 0); $matrix->set(10, 0, 1); $this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix)); // Horizontal 10111010000 $matrix = new ByteMatrix(11, 1); $matrix->set(0, 0, 1); $matrix->set(1, 0, 0); $matrix->set(2, 0, 1); $matrix->set(3, 0, 1); $matrix->set(4, 0, 1); $matrix->set(5, 0, 0); $matrix->set(6, 0, 1); $matrix->set(7, 0, 0); $matrix->set(8, 0, 0); $matrix->set(9, 0, 0); $matrix->set(10, 0, 0); $this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix)); // Vertical 00001011101 $matrix = new ByteMatrix(1, 11); $matrix->set(0, 0, 0); $matrix->set(0, 1, 0); $matrix->set(0, 2, 0); $matrix->set(0, 3, 0); $matrix->set(0, 4, 1); $matrix->set(0, 5, 0); $matrix->set(0, 6, 1); $matrix->set(0, 7, 1); $matrix->set(0, 8, 1); $matrix->set(0, 9, 0); $matrix->set(0, 10, 1); $this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix)); // Vertical 10111010000 $matrix = new ByteMatrix(1, 11); $matrix->set(0, 0, 1); $matrix->set(0, 1, 0); $matrix->set(0, 2, 1); $matrix->set(0, 3, 1); $matrix->set(0, 4, 1); $matrix->set(0, 5, 0); $matrix->set(0, 6, 1); $matrix->set(0, 7, 0); $matrix->set(0, 8, 0); $matrix->set(0, 9, 0); $matrix->set(0, 10, 0); $this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix)); } public function testApplyMaskPenaltyRule4() { // Dark cell ratio = 0% $matrix = new ByteMatrix(1, 1); $matrix->set(0, 0, 0); $this->assertEquals(100, MaskUtil::applyMaskPenaltyRule4($matrix)); // Dark cell ratio = 5% $matrix = new ByteMatrix(2, 1); $matrix->set(0, 0, 0); $matrix->set(0, 0, 1); $this->assertEquals(0, MaskUtil::applyMaskPenaltyRule4($matrix)); // Dark cell ratio = 66.67% $matrix = new ByteMatrix(6, 1); $matrix->set(0, 0, 0); $matrix->set(1, 0, 1); $matrix->set(2, 0, 1); $matrix->set(3, 0, 1); $matrix->set(4, 0, 1); $matrix->set(5, 0, 0); $this->assertEquals(30, MaskUtil::applyMaskPenaltyRule4($matrix)); } } lib/system/api/qr/tests/BaconQrCode/Encoder/MatrixUtilTest.php 0000644 0000155 0177776 00000036411 12220311243 024612 0 ustar jenkins nogroup getMethods(ReflectionMethod::IS_STATIC) as $method) { $method->setAccessible(true); $this->methods[$method->getName()] = $method; } } public function testToString() { $matrix= new ByteMatrix(3, 3); $matrix->set(0, 0, 0); $matrix->set(1, 0, 1); $matrix->set(2, 0, 0); $matrix->set(0, 1, 1); $matrix->set(1, 1, 0); $matrix->set(2, 1, 1); $matrix->set(0, 2, -1); $matrix->set(1, 2, -1); $matrix->set(2, 2, -1); $expected = " 0 1 0\n 1 0 1\n \n"; $this->assertEquals($expected, $matrix->__toString()); } public function testClearMatrix() { $matrix = new ByteMatrix(2, 2); MatrixUtil::clearMatrix($matrix); $this->assertEquals(-1, $matrix->get(0, 0)); $this->assertEquals(-1, $matrix->get(1, 0)); $this->assertEquals(-1, $matrix->get(0, 1)); $this->assertEquals(-1, $matrix->get(1, 1)); } public function testEmbedBasicPatterns1() { $matrix = new ByteMatrix(21, 21); MatrixUtil::clearMatrix($matrix); $this->methods['embedBasicPatterns']->invoke( null, Version::getVersionForNumber(1), $matrix ); $expected = " 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1\n" . " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" . " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n" . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n" . " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 1 \n" . " 0 \n" . " 1 \n" . " 0 \n" . " 1 \n" . " 0 0 0 0 0 0 0 0 1 \n" . " 1 1 1 1 1 1 1 0 \n" . " 1 0 0 0 0 0 1 0 \n" . " 1 0 1 1 1 0 1 0 \n" . " 1 0 1 1 1 0 1 0 \n" . " 1 0 1 1 1 0 1 0 \n" . " 1 0 0 0 0 0 1 0 \n" . " 1 1 1 1 1 1 1 0 \n"; $this->assertEquals($expected, $matrix->__toString()); } public function testEmbedBasicPatterns2() { $matrix = new ByteMatrix(25, 25); MatrixUtil::clearMatrix($matrix); $this->methods['embedBasicPatterns']->invoke( null, Version::getVersionForNumber(2), $matrix ); $expected = " 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1\n" . " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 0 1 1 1 0 1\n" . " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1\n" . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n" . " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 1 \n" . " 0 \n" . " 1 \n" . " 0 \n" . " 1 \n" . " 0 \n" . " 1 \n" . " 0 \n" . " 1 1 1 1 1 1 \n" . " 0 0 0 0 0 0 0 0 1 1 0 0 0 1 \n" . " 1 1 1 1 1 1 1 0 1 0 1 0 1 \n" . " 1 0 0 0 0 0 1 0 1 0 0 0 1 \n" . " 1 0 1 1 1 0 1 0 1 1 1 1 1 \n" . " 1 0 1 1 1 0 1 0 \n" . " 1 0 1 1 1 0 1 0 \n" . " 1 0 0 0 0 0 1 0 \n" . " 1 1 1 1 1 1 1 0 \n"; $this->assertEquals($expected, $matrix->__toString()); } public function testEmbedTypeInfo() { $matrix = new ByteMatrix(21, 21); MatrixUtil::clearMatrix($matrix); $this->methods['embedTypeInfo']->invoke( null, new ErrorCorrectionLevel(ErrorCorrectionLevel::M), 5, $matrix ); $expected = " 0 \n" . " 1 \n" . " 1 \n" . " 1 \n" . " 0 \n" . " 0 \n" . " \n" . " 1 \n" . " 1 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0\n" . " \n" . " \n" . " \n" . " \n" . " \n" . " 0 \n" . " 0 \n" . " 0 \n" . " 0 \n" . " 0 \n" . " 0 \n" . " 1 \n"; $this->assertEquals($expected, $matrix->__toString()); } public function testEmbedVersionInfo() { $matrix = new ByteMatrix(21, 21); MatrixUtil::clearMatrix($matrix); $this->methods['maybeEmbedVersionInfo']->invoke( null, Version::getVersionForNumber(7), $matrix ); $expected = " 0 0 1 \n" . " 0 1 0 \n" . " 0 1 0 \n" . " 0 1 1 \n" . " 1 1 1 \n" . " 0 0 0 \n" . " \n" . " \n" . " \n" . " \n" . " 0 0 0 0 1 0 \n" . " 0 1 1 1 1 0 \n" . " 1 0 0 1 1 0 \n" . " \n" . " \n" . " \n" . " \n" . " \n" . " \n" . " \n" . " \n"; $this->assertEquals($expected, $matrix->__toString()); } public function testEmbedDataBits() { $matrix = new ByteMatrix(21, 21); MatrixUtil::clearMatrix($matrix); $this->methods['embedBasicPatterns']->invoke( null, Version::getVersionForNumber(1), $matrix ); $bits = new BitArray(); $this->methods['embedDataBits']->invoke( null, $bits, -1, $matrix ); $expected = " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n" . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n" . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n" . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n" . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n" . " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n" . " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"; $this->assertEquals($expected, $matrix->__toString()); } public function testBuildMatrix() { $bytes = array( 32, 65, 205, 69, 41, 220, 46, 128, 236, 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219 , 61 ); $bits = new BitArray(); foreach ($bytes as $byte) { $bits->appendBits($byte, 8); } $matrix = new ByteMatrix(21, 21); MatrixUtil::buildMatrix( $bits, new ErrorCorrectionLevel(ErrorCorrectionLevel::H), Version::getVersionForNumber(1), 3, $matrix ); $expected = " 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1\n" . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n" . " 1 0 1 1 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 1 0 1\n" . " 1 0 0 0 0 0 1 0 0 0 1 1 1 0 1 0 0 0 0 0 1\n" . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n" . " 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0\n" . " 0 0 1 1 0 0 1 1 1 0 0 1 1 1 1 0 1 0 0 0 0\n" . " 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 1 0 1 1 1 0\n" . " 1 1 1 1 0 1 1 0 1 0 1 1 1 0 0 1 1 1 0 1 0\n" . " 1 0 1 0 1 1 0 1 1 1 0 0 1 1 1 0 0 1 0 1 0\n" . " 0 0 1 0 0 1 1 1 0 0 0 0 0 0 1 0 1 1 1 1 1\n" . " 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1\n" . " 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 1 0\n" . " 1 0 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 0 0 0 0\n" . " 1 0 1 1 1 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 1\n" . " 1 0 1 1 1 0 1 0 1 1 0 1 0 0 0 0 0 1 1 1 0\n" . " 1 0 1 1 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 0 0\n" . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0\n" . " 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 1 0 0 1 0\n"; $this->assertEquals($expected, $matrix->__toString()); } public function testFindMsbSet() { $this->assertEquals(0, $this->methods['findMsbSet']->invoke(null, 0)); $this->assertEquals(1, $this->methods['findMsbSet']->invoke(null, 1)); $this->assertEquals(8, $this->methods['findMsbSet']->invoke(null, 0x80)); $this->assertEquals(32, $this->methods['findMsbSet']->invoke(null, 0x80000000)); } public function testCalculateBchCode() { // Encoding of type information. // From Appendix C in JISX0510:2004 (p 65) $this->assertEquals(0xdc, $this->methods['calculateBchCode']->invoke(null, 5, 0x537)); // From http://www.swetake.com/qr/qr6.html $this->assertEquals(0x1c2, $this->methods['calculateBchCode']->invoke(null, 0x13, 0x537)); // From http://www.swetake.com/qr/qr11.html $this->assertEquals(0x214, $this->methods['calculateBchCode']->invoke(null, 0x1b, 0x537)); // Encoding of version information. // From Appendix D in JISX0510:2004 (p 68) $this->assertEquals(0xc94, $this->methods['calculateBchCode']->invoke(null, 7, 0x1f25)); $this->assertEquals(0x5bc, $this->methods['calculateBchCode']->invoke(null, 8, 0x1f25)); $this->assertEquals(0xa99, $this->methods['calculateBchCode']->invoke(null, 9, 0x1f25)); $this->assertEquals(0x4d3, $this->methods['calculateBchCode']->invoke(null, 10, 0x1f25)); $this->assertEquals(0x9a6, $this->methods['calculateBchCode']->invoke(null, 20, 0x1f25)); $this->assertEquals(0xd75, $this->methods['calculateBchCode']->invoke(null, 30, 0x1f25)); $this->assertEquals(0xc69, $this->methods['calculateBchCode']->invoke(null, 40, 0x1f25)); } public function testMakeVersionInfoBits() { // From Appendix D in JISX0510:2004 (p 68) $bits = new BitArray(); $this->methods['makeVersionInfoBits']->invoke(null, Version::getVersionForNumber(7), $bits); $this->assertEquals(' ...XXXXX ..X..X.X ..', $bits->__toString()); } public function testMakeTypeInfoBits() { // From Appendix D in JISX0510:2004 (p 68) $bits = new BitArray(); $this->methods['makeTypeInfoBits']->invoke(null, new ErrorCorrectionLevel(ErrorCorrectionLevel::M), 5, $bits); $this->assertEquals(' X......X X..XXX.', $bits->__toString()); } } lib/system/api/qr/tests/BaconQrCode/Encoder/EncoderTest.php 0000644 0000155 0177776 00000046624 12220311243 024076 0 ustar jenkins nogroup getMethods(ReflectionMethod::IS_STATIC) as $method) { $method->setAccessible(true); $this->methods[$method->getName()] = $method; } } public function testGetAlphanumericCode() { // The first ten code points are numbers. for ($i = 0; $i < 10; $i++) { $this->assertEquals($i, $this->methods['getAlphanumericCode']->invoke(null, ord('0') + $i)); } // The next 26 code points are capital alphabet letters. for ($i = 10; $i < 36; $i++) { // The first ten code points are numbers $this->assertEquals($i, $this->methods['getAlphanumericCode']->invoke(null, ord('A') + $i - 10)); } // Others are symbol letters. $this->assertEquals(36, $this->methods['getAlphanumericCode']->invoke(null, ' ')); $this->assertEquals(37, $this->methods['getAlphanumericCode']->invoke(null, '$')); $this->assertEquals(38, $this->methods['getAlphanumericCode']->invoke(null, '%')); $this->assertEquals(39, $this->methods['getAlphanumericCode']->invoke(null, '*')); $this->assertEquals(40, $this->methods['getAlphanumericCode']->invoke(null, '+')); $this->assertEquals(41, $this->methods['getAlphanumericCode']->invoke(null, '-')); $this->assertEquals(42, $this->methods['getAlphanumericCode']->invoke(null, '.')); $this->assertEquals(43, $this->methods['getAlphanumericCode']->invoke(null, '/')); $this->assertEquals(44, $this->methods['getAlphanumericCode']->invoke(null, ':')); // Should return -1 for other letters. $this->assertEquals(-1, $this->methods['getAlphanumericCode']->invoke(null, 'a')); $this->assertEquals(-1, $this->methods['getAlphanumericCode']->invoke(null, '#')); $this->assertEquals(-1, $this->methods['getAlphanumericCode']->invoke(null, "\0")); } public function testChooseMode() { // Numeric mode $this->assertSame(Mode::NUMERIC, $this->methods['chooseMode']->invoke(null, '0')->get()); $this->assertSame(Mode::NUMERIC, $this->methods['chooseMode']->invoke(null, '0123456789')->get()); // Alphanumeric mode $this->assertSame(Mode::ALPHANUMERIC, $this->methods['chooseMode']->invoke(null, 'A')->get()); $this->assertSame(Mode::ALPHANUMERIC, $this->methods['chooseMode']->invoke(null, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:')->get()); // 8-bit byte mode $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, 'a')->get()); $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, '#')->get()); $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, '')->get()); // AIUE in Hiragana in SHIFT-JIS $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, "\x8\xa\x8\xa\x8\xa\x8\xa6")->get()); // Nihon in Kanji in SHIFT-JIS $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, "\x9\xf\x9\x7b")->get()); // Sou-Utso-Byou in Kanji in SHIFT-JIS $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, "\xe\x4\x9\x5\x9\x61")->get()); } public function testEncode() { $qrCode = Encoder::encode('ABCDEF', new ErrorCorrectionLevel(ErrorCorrectionLevel::H)); $expected = "<<\n" . " mode: ALPHANUMERIC\n" . " ecLevel: H\n" . " version: 1\n" . " maskPattern: 0\n" . " matrix:\n" . " 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1\n" . " 1 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 1 1 1 0 1 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1\n" . " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1\n" . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n" . " 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0\n" . " 0 0 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1\n" . " 1 0 1 1 1 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0\n" . " 0 0 1 1 0 0 1 0 1 0 0 0 1 0 1 0 1 0 1 1 0\n" . " 1 1 0 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0\n" . " 0 0 1 1 0 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0\n" . " 0 0 0 0 0 0 0 0 1 0 0 1 1 1 0 1 0 1 0 0 0\n" . " 1 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 1\n" . " 1 0 0 0 0 0 1 0 1 1 1 1 0 1 0 1 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 1 0 0 0 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 1 0\n" . " 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1\n" . " 1 0 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 0 1 1\n" . " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 1\n" . ">>\n"; $this->assertEquals($expected, $qrCode->__toString()); } public function testSimpleUtf8Eci() { $qrCode = Encoder::encode('hello', new ErrorCorrectionLevel(ErrorCorrectionLevel::H), 'utf-8'); $expected = "<<\n" . " mode: BYTE\n" . " ecLevel: H\n" . " version: 1\n" . " maskPattern: 3\n" . " matrix:\n" . " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n" . " 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 0 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 1 0 1 0 1 0 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 0 1\n" . " 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1\n" . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n" . " 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0\n" . " 0 0 1 1 0 0 1 1 1 1 0 0 0 1 1 0 1 0 0 0 0\n" . " 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 1 1 0\n" . " 0 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 1 1 1\n" . " 1 1 0 0 1 0 0 1 1 0 0 1 1 1 1 0 1 0 1 1 0\n" . " 0 0 0 0 1 0 1 1 1 1 0 0 0 0 0 1 0 0 1 0 0\n" . " 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 1 1 0 0 0 1\n" . " 1 1 1 1 1 1 1 0 1 1 1 0 1 0 1 1 0 0 1 0 0\n" . " 1 0 0 0 0 0 1 0 0 0 1 0 0 1 1 1 1 1 1 0 1\n" . " 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 0\n" . " 1 0 1 1 1 0 1 0 1 1 1 0 1 0 0 0 1 1 0 0 0\n" . " 1 0 1 1 1 0 1 0 1 1 0 0 0 1 0 0 1 0 0 0 0\n" . " 1 0 0 0 0 0 1 0 0 0 0 1 1 0 1 0 1 0 1 1 0\n" . " 1 1 1 1 1 1 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0\n" . ">>\n"; $this->assertEquals($expected, $qrCode->__toString()); } public function testAppendModeInfo() { $bits = new BitArray(); $this->methods['appendModeInfo']->invoke(null, new Mode(Mode::NUMERIC), $bits); $this->assertEquals(' ...X', $bits->__toString()); } public function testAppendLengthInfo() { // 1 letter (1/1), 10 bits. $bits = new BitArray(); $this->methods['appendLengthInfo']->invoke( null, 1, Version::getVersionForNumber(1), new Mode(Mode::NUMERIC), $bits ); $this->assertEquals(' ........ .X', $bits->__toString()); // 2 letters (2/1), 11 bits. $bits = new BitArray(); $this->methods['appendLengthInfo']->invoke( null, 2, Version::getVersionForNumber(10), new Mode(Mode::ALPHANUMERIC), $bits ); $this->assertEquals(' ........ .X.', $bits->__toString()); // 255 letters (255/1), 16 bits. $bits = new BitArray(); $this->methods['appendLengthInfo']->invoke( null, 255, Version::getVersionForNumber(27), new Mode(Mode::BYTE), $bits ); $this->assertEquals(' ........ XXXXXXXX', $bits->__toString()); // 512 letters (1024/2), 12 bits. $bits = new BitArray(); $this->methods['appendLengthInfo']->invoke( null, 512, Version::getVersionForNumber(40), new Mode(Mode::KANJI), $bits ); $this->assertEquals(' ..X..... ....', $bits->__toString()); } public function testAppendBytes() { // Should use appendNumericBytes. // 1 = 01 = 0001 in 4 bits. $bits = new BitArray(); $this->methods['appendBytes']->invoke( null, '1', new Mode(Mode::NUMERIC), $bits, Encoder::DEFAULT_BYTE_MODE_ECODING ); $this->assertEquals(' ...X', $bits->__toString()); // Should use appendAlphaNumericBytes. // A = 10 = 0xa = 001010 in 6 bits. $bits = new BitArray(); $this->methods['appendBytes']->invoke( null, 'A', new Mode(Mode::ALPHANUMERIC), $bits, Encoder::DEFAULT_BYTE_MODE_ECODING ); $this->assertEquals(' ..X.X.', $bits->__toString()); // Should use append8BitBytes. // 0x61, 0x62, 0x63 $bits = new BitArray(); $this->methods['appendBytes']->invoke( null, 'abc', new Mode(Mode::BYTE), $bits, Encoder::DEFAULT_BYTE_MODE_ECODING ); $this->assertEquals(' .XX....X .XX...X. .XX...XX', $bits->__toString()); // Should use appendKanjiBytes. // 0x93, 0x5f $bits = new BitArray(); $this->methods['appendBytes']->invoke( null, "\x93\x5f", new Mode(Mode::KANJI), $bits, Encoder::DEFAULT_BYTE_MODE_ECODING ); $this->assertEquals(' .XX.XX.. XXXXX', $bits->__toString()); // Lower letters such as 'a' cannot be encoded in alphanumeric mode. $this->setExpectedException( 'BaconQrCode\Exception\WriterException', 'Invalid alphanumeric code' ); $this->methods['appendBytes']->invoke( null, "a", new Mode(Mode::ALPHANUMERIC), $bits, Encoder::DEFAULT_BYTE_MODE_ECODING ); } public function testTerminateBits() { $bits = new BitArray(); $this->methods['terminateBits']->invoke(null, 0, $bits); $this->assertEquals('', $bits->__toString()); $bits = new BitArray(); $this->methods['terminateBits']->invoke(null, 1, $bits); $this->assertEquals(' ........', $bits->__toString()); $bits = new BitArray(); $bits->appendBits(0, 3); $this->methods['terminateBits']->invoke(null, 1, $bits); $this->assertEquals(' ........', $bits->__toString()); $bits = new BitArray(); $bits->appendBits(0, 5); $this->methods['terminateBits']->invoke(null, 1, $bits); $this->assertEquals(' ........', $bits->__toString()); $bits = new BitArray(); $bits->appendBits(0, 8); $this->methods['terminateBits']->invoke(null, 1, $bits); $this->assertEquals(' ........', $bits->__toString()); $bits = new BitArray(); $this->methods['terminateBits']->invoke(null, 2, $bits); $this->assertEquals(' ........ XXX.XX..', $bits->__toString()); $bits = new BitArray(); $bits->appendBits(0, 1); $this->methods['terminateBits']->invoke(null, 3, $bits); $this->assertEquals(' ........ XXX.XX.. ...X...X', $bits->__toString()); } public function testGetNumDataBytesAndNumEcBytesForBlockId() { // Version 1-H. list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 26, 9, 1, 0); $this->assertEquals(9, $numDataBytes); $this->assertEquals(17, $numEcBytes); // Version 3-H. 2 blocks. list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 70, 26, 2, 0); $this->assertEquals(13, $numDataBytes); $this->assertEquals(22, $numEcBytes); list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 70, 26, 2, 1); $this->assertEquals(13, $numDataBytes); $this->assertEquals(22, $numEcBytes); // Version 7-H. (4 + 1) blocks. list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 196, 66, 5, 0); $this->assertEquals(13, $numDataBytes); $this->assertEquals(26, $numEcBytes); list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 196, 66, 5, 4); $this->assertEquals(14, $numDataBytes); $this->assertEquals(26, $numEcBytes); // Version 40-H. (20 + 61) blocks. list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 3706, 1276, 81, 0); $this->assertEquals(15, $numDataBytes); $this->assertEquals(30, $numEcBytes); list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 3706, 1276, 81, 20); $this->assertEquals(16, $numDataBytes); $this->assertEquals(30, $numEcBytes); list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 3706, 1276, 81, 80); $this->assertEquals(16, $numDataBytes); $this->assertEquals(30, $numEcBytes); } public function testInterleaveWithEcBytes() { $dataBytes = SplFixedArray::fromArray(array(32, 65, 205, 69, 41, 220, 46, 128, 236)); $in = new BitArray(); foreach ($dataBytes as $dataByte) { $in->appendBits($dataByte, 8); } $outBits = $this->methods['interleaveWithEcBytes']->invoke(null, $in, 26, 9, 1); $expected = SplFixedArray::fromArray(array( // Data bytes. 32, 65, 205, 69, 41, 220, 46, 128, 236, // Error correction bytes. 42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61, )); $out = $outBits->toBytes(0, count($expected)); $this->assertEquals($expected, $out); } public function testAppendNumericBytes() { // 1 = 01 = 0001 in 4 bits. $bits = new BitArray(); $this->methods['appendNumericBytes']->invoke(null, '1', $bits); $this->assertEquals(' ...X', $bits->__toString()); // 12 = 0xc = 0001100 in 7 bits. $bits = new BitArray(); $this->methods['appendNumericBytes']->invoke(null, '12', $bits); $this->assertEquals(' ...XX..', $bits->__toString()); // 123 = 0x7b = 0001111011 in 10 bits. $bits = new BitArray(); $this->methods['appendNumericBytes']->invoke(null, '123', $bits); $this->assertEquals(' ...XXXX. XX', $bits->__toString()); // 1234 = "123" + "4" = 0001111011 + 0100 in 14 bits. $bits = new BitArray(); $this->methods['appendNumericBytes']->invoke(null, '1234', $bits); $this->assertEquals(' ...XXXX. XX.X..', $bits->__toString()); // Empty $bits = new BitArray(); $this->methods['appendNumericBytes']->invoke(null, '', $bits); $this->assertEquals('', $bits->__toString()); } public function testAppendAlphanumericBytes() { $bits = new BitArray(); $this->methods['appendAlphanumericBytes']->invoke(null, 'A', $bits); $this->assertEquals(' ..X.X.', $bits->__toString()); $bits = new BitArray(); $this->methods['appendAlphanumericBytes']->invoke(null, 'AB', $bits); $this->assertEquals(' ..XXX..X X.X', $bits->__toString()); $bits = new BitArray(); $this->methods['appendAlphanumericBytes']->invoke(null, 'ABC', $bits); $this->assertEquals(' ..XXX..X X.X..XX. .', $bits->__toString()); // Empty $bits = new BitArray(); $this->methods['appendAlphanumericBytes']->invoke(null, '', $bits); $this->assertEquals('', $bits->__toString()); // Invalid data $this->setExpectedException('BaconQrCode\Exception\WriterException', 'Invalid alphanumeric code'); $bits = new BitArray(); $this->methods['appendAlphanumericBytes']->invoke(null, 'abc', $bits); } public function testAppend8BitBytes() { // 0x61, 0x62, 0x63 $bits = new BitArray(); $this->methods['append8BitBytes']->invoke(null, 'abc', $bits, Encoder::DEFAULT_BYTE_MODE_ECODING); $this->assertEquals(' .XX....X .XX...X. .XX...XX', $bits->__toString()); // Empty $bits = new BitArray(); $this->methods['append8BitBytes']->invoke(null, '', $bits, Encoder::DEFAULT_BYTE_MODE_ECODING); $this->assertEquals('', $bits->__toString()); } public function testAppendKanjiBytes() { // Numbers are from page 21 of JISX0510:2004 $bits = new BitArray(); $this->methods['appendKanjiBytes']->invoke(null, "\x93\x5f", $bits); $this->assertEquals(' .XX.XX.. XXXXX', $bits->__toString()); $this->methods['appendKanjiBytes']->invoke(null, "\xe4\xaa", $bits); $this->assertEquals(' .XX.XX.. XXXXXXX. X.X.X.X. X.', $bits->__toString()); } public function testGenerateEcBytes() { // Numbers are from http://www.swetake.com/qr/qr3.html and // http://www.swetake.com/qr/qr9.html $dataBytes = SplFixedArray::fromArray(array(32, 65, 205, 69, 41, 220, 46, 128, 236)); $ecBytes = $this->methods['generateEcBytes']->invoke(null, $dataBytes, 17); $expected = SplFixedArray::fromArray(array(42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61)); $this->assertEquals($expected, $ecBytes); $dataBytes = SplFixedArray::fromArray(array(67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214)); $ecBytes = $this->methods['generateEcBytes']->invoke(null, $dataBytes, 18); $expected = SplFixedArray::fromArray(array(175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187)); $this->assertEquals($expected, $ecBytes); // High-order zero coefficient case. $dataBytes = SplFixedArray::fromArray(array(32, 49, 205, 69, 42, 20, 0, 236, 17)); $ecBytes = $this->methods['generateEcBytes']->invoke(null, $dataBytes, 17); $expected = SplFixedArray::fromArray(array(0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213)); $this->assertEquals($expected, $ecBytes); } } lib/system/api/qr/tests/bootstrap.php 0000644 0000155 0177776 00000000446 12220311243 020165 0 ustar jenkins nogroup