:octocat: extract MaskPattern

This commit is contained in:
codemasher
2021-01-19 01:15:34 +01:00
parent 307b6462f6
commit 182ebf4e70
10 changed files with 120 additions and 66 deletions
+6 -5
View File
@@ -14,6 +14,7 @@
namespace chillerlan\QRCode\Data;
use chillerlan\QRCode\Common\MaskPattern;
use function abs, array_search, call_user_func_array, min;
/**
@@ -45,14 +46,14 @@ final class MaskPatternTester{
*
* @see \chillerlan\QRCode\Data\MaskPatternTester
*/
public function getBestMaskPattern():int{
public function getBestMaskPattern():MaskPattern{
$penalties = [];
for($pattern = 0; $pattern < 8; $pattern++){
$penalties[$pattern] = $this->testPattern($pattern);
foreach(MaskPattern::PATTERNS as $pattern){
$penalties[$pattern] = $this->testPattern(new MaskPattern($pattern));
}
return array_search(min($penalties), $penalties, true);
return new MaskPattern(array_search(min($penalties), $penalties, true));
}
/**
@@ -61,7 +62,7 @@ final class MaskPatternTester{
* @see \chillerlan\QRCode\QROptions::$maskPattern
* @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
*/
public function testPattern(int $pattern):int{
public function testPattern(MaskPattern $pattern):int{
$matrix = $this->qrData->writeMatrix($pattern, true);
$penalty = 0;
+2 -2
View File
@@ -12,7 +12,7 @@
namespace chillerlan\QRCode\Data;
use chillerlan\QRCode\Common\{BitBuffer, EccLevel, Mode, ReedSolomonEncoder, Version};
use chillerlan\QRCode\Common\{BitBuffer, EccLevel, MaskPattern, Mode, ReedSolomonEncoder, Version};
use chillerlan\QRCode\QRCode;
use chillerlan\Settings\SettingsContainerInterface;
@@ -100,7 +100,7 @@ final class QRData{
/**
* returns a fresh matrix object with the data written for the given $maskPattern
*/
public function writeMatrix(int $maskPattern, bool $test = null):QRMatrix{
public function writeMatrix(MaskPattern $maskPattern, bool $test = null):QRMatrix{
$data = (new ReedSolomonEncoder)->interleaveEcBytes($this->bitBuffer, $this->version, $this->eccLevel);
return (new QRMatrix($this->version, $this->eccLevel))
+8 -40
View File
@@ -12,9 +12,7 @@
namespace chillerlan\QRCode\Data;
use chillerlan\QRCode\Common\{EccLevel, Version};
use chillerlan\QRCode\QRCode;
use Closure;
use chillerlan\QRCode\Common\{EccLevel, MaskPattern, Version};
use SplFixedArray;
use function array_fill, array_push, array_unshift, floor, max, min, range;
@@ -57,9 +55,9 @@ final class QRMatrix{
public const IS_DARK = 0b100000000000;
/**
* the used mask pattern, set via QRMatrix::mapData()
* the used mask pattern, set via QRMatrix::mask()
*/
protected int $maskPattern = QRCode::MASK_PATTERN_AUTO;
protected ?MaskPattern $maskPattern = null;
/**
* the size (side length) of the matrix, including quiet zone (if created)
@@ -96,7 +94,7 @@ final class QRMatrix{
/**
* shortcut to initialize the matrix
*/
public function init(int $maskPattern, bool $test = null):QRMatrix{
public function init(MaskPattern $maskPattern, bool $test = null):QRMatrix{
return $this
->setFinderPattern()
->setSeparators()
@@ -149,7 +147,7 @@ final class QRMatrix{
/**
* Returns the current mask pattern
*/
public function maskPattern():int{
public function maskPattern():?MaskPattern{
return $this->maskPattern;
}
@@ -365,7 +363,7 @@ final class QRMatrix{
*
* ISO/IEC 18004:2000 Section 8.9
*/
public function setFormatInfo(int $maskPattern, bool $test = null):QRMatrix{
public function setFormatInfo(MaskPattern $maskPattern, bool $test = null):QRMatrix{
$bits = $this->eccLevel->getformatPattern($maskPattern);
for($i = 0; $i < 15; $i++){
@@ -569,9 +567,9 @@ final class QRMatrix{
*
* ISO/IEC 18004:2000 Section 8.8.1
*/
public function mask(int $maskPattern):QRMatrix{
public function mask(MaskPattern $maskPattern):QRMatrix{
$this->maskPattern = $maskPattern;
$mask = $this->getMask($this->maskPattern);
$mask = $this->maskPattern->getMask();
foreach($this->matrix as $y => &$row){
foreach($row as $x => &$val){
@@ -584,34 +582,4 @@ final class QRMatrix{
return $this;
}
/**
* ISO/IEC 18004:2000 Section 8.8.1
*
* Note that some versions of the QR code standard have had errors in the section about mask patterns.
* The information below has been corrected. (https://www.thonky.com/qr-code-tutorial/mask-patterns)
*
* @see \chillerlan\QRCode\QRMatrix::mapData()
*
* @internal
*
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
protected function getMask(int $maskPattern):Closure{
if((0b111 & $maskPattern) !== $maskPattern){
throw new QRCodeDataException('invalid mask pattern'); // @codeCoverageIgnore
}
return [
0b000 => fn($x, $y):int => ($x + $y) % 2,
0b001 => fn($x, $y):int => $y % 2,
0b010 => fn($x, $y):int => $x % 3,
0b011 => fn($x, $y):int => ($x + $y) % 3,
0b100 => fn($x, $y):int => ((int)($y / 2) + (int)($x / 3)) % 2,
0b101 => fn($x, $y):int => (($x * $y) % 2) + (($x * $y) % 3),
0b110 => fn($x, $y):int => ((($x * $y) % 2) + (($x * $y) % 3)) % 2,
0b111 => fn($x, $y):int => ((($x * $y) % 3) + (($x + $y) % 2)) % 2,
][$maskPattern];
}
}