Skip to content

Commit cf87949

Browse files
committed
🔧 fix mask pattern 2 & 3 according to ISO/IEC 18004:2000 Section 8.8.1
1 parent eeb60ed commit cf87949

File tree

2 files changed

+19
-22
lines changed

2 files changed

+19
-22
lines changed

src/Data/QRMatrix.php

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
namespace chillerlan\QRCode\Data;
1414

1515
use chillerlan\QRCode\QRCode;
16+
use Closure;
1617

1718
use function array_fill, array_key_exists, array_push, array_unshift, count, floor, in_array, max, min, range;
1819

@@ -547,6 +548,7 @@ public function mapData(array $data, int $maskPattern):QRMatrix{
547548
$this->maskPattern = $maskPattern;
548549
$byteCount = count($data);
549550
$size = $this->moduleCount - 1;
551+
$mask = $this->getMask($this->maskPattern);
550552

551553
for($i = $size, $y = $size, $inc = -1, $byteIndex = 0, $bitIndex = 7; $i > 0; $i -= 2){
552554

@@ -565,7 +567,7 @@ public function mapData(array $data, int $maskPattern):QRMatrix{
565567
$v = (($data[$byteIndex] >> $bitIndex) & 1) === 1;
566568
}
567569

568-
if($this->getMask($x, $y, $maskPattern) === 0){
570+
if($mask($x, $y) === 0){
569571
$v = !$v;
570572
}
571573

@@ -602,32 +604,27 @@ public function mapData(array $data, int $maskPattern):QRMatrix{
602604
*
603605
* @internal
604606
*
605-
* @param int $x
606-
* @param int $y
607607
* @param int $maskPattern
608608
*
609-
* @return int
609+
* @return \Closure
610610
* @throws \chillerlan\QRCode\Data\QRCodeDataException
611611
*/
612-
protected function getMask(int $x, int $y, int $maskPattern):int{
613-
$a = $y + $x;
614-
$m = $y * $x;
615-
616-
if($maskPattern >= 0 && $maskPattern < 8){
617-
// this is literally the same as the stupid switch...
618-
return [
619-
$a % 2,
620-
$x % 2,
621-
$y % 3,
622-
$a % 3,
623-
((int)($y / 2) + (int)($x / 3)) % 2,
624-
$m % 2 + $m % 3,
625-
($m % 2 + $m % 3) % 2,
626-
($m % 3 + $a % 2) % 2
627-
][$maskPattern];
612+
protected function getMask(int $maskPattern):Closure{
613+
614+
if((0b111 & $maskPattern) !== $maskPattern){
615+
throw new QRCodeDataException('invalid mask pattern'); // @codeCoverageIgnore
628616
}
629617

630-
throw new QRCodeDataException('invalid mask pattern'); // @codeCoverageIgnore
618+
return [
619+
0b000 => function($x, $y):int{ return ($x + $y) % 2; },
620+
0b001 => function($x, $y):int{ return $x % 2; },
621+
0b010 => function($x, $y):int{ return $y % 3; },
622+
0b011 => function($x, $y):int{ return ($x + $y) % 3; },
623+
0b100 => function($x, $y):int{ return ((int)($x / 2) + (int)($y / 3)) % 2; },
624+
0b101 => function($x, $y):int{ return (($x * $y) % 2) + (($x * $y) % 3); },
625+
0b110 => function($x, $y):int{ return ((($x * $y) % 2) + (($x * $y) % 3)) % 2; },
626+
0b111 => function($x, $y):int{ return ((($x * $y) % 3) + (($x + $y) % 2)) % 2; },
627+
][$maskPattern];
631628
}
632629

633630
}

tests/QRCodeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function testCustomOutput(){
109109
'outputInterface' => MyCustomOutput::class,
110110
]);
111111

112-
$expected = '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111110111010000101111010000011111110000000010000010111000001101011000001010000010000000010111010101101011000001101011010111010000000010111010110100111110010100111010111010000000010111010000001101011000001101010111010000000010000010100111110010100111110010000010000000011111110101010101010101010101011111110000000000000000010010100111110010100000000000000000011001110000101111010000101111001011110000000000000000111010000101111010000111100010000000001011010100111110010100111110011001010000000010000101111101011000001101011110011110000000000011010100011000001101011000101110100000000011001100001001101011000001101010011010000000010110111110000001101011000001100110100000000010000100100010100111110010100001100100000000011111110111101111010000101111010100110000000011010000111010000101111010000111100100000000010101111111111110010100111110011001000000000010110001110101011000001101011110011010000000001001111100011000001101011000101110010000000011000100110001101011000001101010011100000000001000011001000001101011000001100110000000000011101001011010100111110010100001100000000000010111010001101111010000101111010100110000000011100000001010000101111010000111100000000000000001110110111110010100111110011001000000000000011001011101011000001101011110011100000000011111110101011000001101011001111110110000000000000000110001101011000001101000111100000000011111110001000001101011000011010110000000000010000010101010100111110010101000100100000000010111010111101111010000101111111100110000000010111010011010000101111010001101100010000000010111010000111110010100111100101101100000000010000010101101011000001101001100111100000000011111110101011000001101011000110010110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';
112+
$expected = '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111110101011110100001011110011111110000000010000010011111001010011111001010000010000000010111010111000001101011000001010111010000000010111010111010110000011010110010111010000000010111010100110101100000110101010111010000000010000010001101011000001101011010000010000000011111110101010101010101010101011111110000000000000000001010011111001010011000000000000000011110010101111010000101111010100111010000000001110001001011110100001011110110010010000000001100010011111001010011111001011110010000000011010000101000001101011000001011001010000000001101011010010110000011010110100000100000000000001001001110101100000110101101011100000000011100010100101011000001101011001100000000000000001000101100101001111100101111101010000000000111011111010111101000010111101100000000000001111000010000101111010000101101001110000000000100011110001111100101001111101000110000000010001001001101100000110101100110100010000000011100111001001101011000001101111011000000000010110101000000011010110000011011101100000000001111011110000110101100000110100001000000000010111100001111110010100111110100110100000000011001011111100001011110100001011010110000000000100101001101000010111101000000100110000000001011011100010100111110010100110011100000000010010101010011010110000011010000010010000000000111011101100000110101100001111110000000000000000000111011000001101011001000110110000000011111110000110000011010110011010111110000000010000010010010011111001010011000111100000000010111010010111010000101111011111101100000000010111010101011110100001011111100010010000000010111010111111001010011111011101010100000000010000010111000001101011000011001101000000000011111110111010110000011010110111100110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';
113113

114114
$this->assertSame($expected, $this->reflection->newInstanceArgs([$options])->render('test'));
115115
}

0 commit comments

Comments
 (0)