Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QRMatrix M_TYPE bitmask rework #205

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions examples/image.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@
'drawCircularModules' => true,
'drawLightModules' => true,
'circleRadius' => 0.4,
'keepAsSquare' => [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
],
'keepAsSquare' => ((QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT | QRMatrix::M_ALIGNMENT) << 12),
'moduleValues' => [
// finder
QRMatrix::M_FINDER_DARK => [0, 63, 255], // dark (true)
Expand Down
2 changes: 1 addition & 1 deletion examples/imageWithLogo.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public function dump(string $file = null, string $logo = null):string{
'imageTransparent' => false,
'drawCircularModules' => true,
'circleRadius' => 0.45,
'keepAsSquare' => [QRMatrix::M_FINDER, QRMatrix::M_FINDER_DOT],
'keepAsSquare' => (QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT),
]);

$qrcode = new QRCode($options);
Expand Down
6 changes: 1 addition & 5 deletions examples/imagick.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@
'drawLightModules' => true,
'drawCircularModules' => true,
'circleRadius' => 0.4,
'keepAsSquare' => [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
],
'keepAsSquare' => ((QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT | QRMatrix::M_ALIGNMENT) << 12),
'moduleValues' => [
// finder
QRMatrix::M_FINDER_DARK => '#A71111', // dark (true)
Expand Down
6 changes: 1 addition & 5 deletions examples/imagickWithLogo.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,7 @@ protected function set_pngLogo(string $pngLogo):void{
'drawLightModules' => false,
'drawCircularModules' => true,
'circleRadius' => 0.4,
'keepAsSquare' => [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
],
'keepAsSquare' => ((QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT | QRMatrix::M_ALIGNMENT) << 12),
]);


Expand Down
7 changes: 2 additions & 5 deletions examples/svg.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,8 @@
// connect paths
'connectPaths' => true,
// keep modules of these types as square
'keepAsSquare' => [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
],
'keepAsSquare' => ((QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT | QRMatrix::M_ALIGNMENT) << 12),
# 'keepAsSquare' => 0b110000010100010000000000,
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
'svgDefs' => '
<linearGradient id="rainbow" x1="100%" y2="100%">
Expand Down
9 changes: 3 additions & 6 deletions examples/svgMeltedModules.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ protected function collectModules(Closure $transform):array{
$M_TYPE_LAYER = QRMatrix::M_DATA;

if($this->matrix->check($x, $y)){
$M_TYPE_LAYER |= QRMatrix::IS_DARK;
$M_TYPE_LAYER = QRMatrix::M_DATA_DARK;
}
}

Expand Down Expand Up @@ -251,19 +251,16 @@ protected function set_meltRadius(float $meltRadius):void{

'version' => 7,
'eccLevel' => EccLevel::H,
'imageBase64' => false,
'addQuietzone' => true,
'addLogoSpace' => true,
'logoSpaceWidth' => 13,
'logoSpaceHeight' => 13,
'connectPaths' => true,
'imageBase64' => false,
'excludeFromConnect' => (QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT),

'outputType' => QROutputInterface::CUSTOM,
'outputInterface' => MeltedSVGQRCodeOutput::class,
'excludeFromConnect' => [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
],
'svgDefs' => '
<linearGradient id="rainbow" x1="100%" y2="100%">
<stop stop-color="#e2453c" offset="2.5%"/>
Expand Down
35 changes: 12 additions & 23 deletions examples/svgRandomColoredDots.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,19 @@ protected function collectModules(Closure $transform):array{
$M_TYPE = $this->matrix->get($x, $y);
$M_TYPE_LAYER = $M_TYPE;

if($this->options->connectPaths
&& !$this->matrix->checkTypeIn($x, $y, $this->options->excludeFromConnect)
){
if($this->options->connectPaths && !$this->matrix->checkTypeIn($x, $y, $this->options->excludeFromConnect)){
// to connect paths we'll redeclare the $M_TYPE_LAYER to data only
$M_TYPE_LAYER = QRMatrix::M_DATA;

if($this->matrix->check($x, $y)){
$M_TYPE_LAYER |= QRMatrix::IS_DARK;
$M_TYPE_LAYER = QRMatrix::M_DATA_DARK;
}
}

// randomly assign another $M_TYPE_LAYER for the given types
// note that the layer id has to be an integer value,
// ideally outside the several bitmask values
if($M_TYPE_LAYER === QRMatrix::M_DATA_DARK){
// note that the layer id has to be an integer value,
// ideally outside the several bitmask values
$M_TYPE_LAYER = array_rand($this->options->dotColors);
}

Expand Down Expand Up @@ -100,12 +98,12 @@ class RandomDotsOptions extends QROptions{

// our custom dot colors
$dotColors = [
111 => '#e2453c',
222 => '#e07e39',
333 => '#e5d667',
444 => '#51b95b',
555 => '#1e72b7',
666 => '#6f5ba7',
(111 | QRMatrix::IS_DARK) => '#e2453c',
(222 | QRMatrix::IS_DARK) => '#e07e39',
(333 | QRMatrix::IS_DARK) => '#e5d667',
(444 | QRMatrix::IS_DARK) => '#51b95b',
(555 | QRMatrix::IS_DARK) => '#1e72b7',
(666 | QRMatrix::IS_DARK) => '#6f5ba7',
];

// generate the CSS for the several colored layers
Expand Down Expand Up @@ -134,20 +132,11 @@ class RandomDotsOptions extends QROptions{
'drawLightModules' => false,

'connectPaths' => true,
'excludeFromConnect' => [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
],
'excludeFromConnect' => (QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT | QRMatrix::M_ALIGNMENT),

'drawCircularModules' => true,
'circleRadius' => 0.4,
'keepAsSquare' => [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
],

'keepAsSquare' => (QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT | QRMatrix::M_ALIGNMENT),
]);

// dump the output
Expand Down
23 changes: 7 additions & 16 deletions examples/svgRoundQuietzone.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,14 @@ protected function collectModules(Closure $transform):array{
$M_TYPE_LAYER = QRMatrix::M_DATA;

if($this->matrix->check($x, $y)){
$M_TYPE_LAYER |= QRMatrix::IS_DARK;
$M_TYPE_LAYER = QRMatrix::M_DATA_DARK;
}
}

// randomly assign another $M_TYPE_LAYER for the given types
// note that the layer id has to be an integer value,
// ideally outside the several bitmask values
if($M_TYPE_LAYER === QRMatrix::M_DATA_DARK){
if($this->matrix->checkType($x, $y, QRMatrix::M_QUIETZONE_DARK)){
// note that the layer id has to be an integer value,
// ideally outside the several bitmask values
$M_TYPE_LAYER = array_rand($this->options->dotColors);
}

Expand Down Expand Up @@ -330,20 +330,11 @@ protected function set_svgLogoScale(float $svgLogoScale):void{

// common SVG options
'svgDefs' => $svgDefs,
// 'connectPaths' => true, // this has been set to "always on" internally
'excludeFromConnect' => [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
(QRMatrix::M_QUIETZONE | QRMatrix::IS_DARK),
],
# 'connectPaths' => true, // this has been set to "always on" internally
# 'excludeFromConnect' => (QRMatrix::M_TIMING_DARK | QRMatrix::M_FORMAT_DARK),
'drawCircularModules' => true,
'circleRadius' => 0.4,
'keepAsSquare' => [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
],
'keepAsSquare' => (QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT | QRMatrix::M_ALIGNMENT),
]);

$qrcode = (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
Expand Down
6 changes: 1 addition & 5 deletions examples/svgWithLogo.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,7 @@ protected function set_svgLogoScale(float $svgLogoScale):void{
// connect paths
'connectPaths' => true,
// keep modules of thhese types as square
'keepAsSquare' => [
QRMatrix::M_FINDER_DARK,
QRMatrix::M_FINDER_DOT,
QRMatrix::M_ALIGNMENT_DARK,
],
'keepAsSquare' => ((QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT | QRMatrix::M_ALIGNMENT) << 12),
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
'svgDefs' => '
<linearGradient id="gradient" x1="100%" y2="100%">
Expand Down
8 changes: 2 additions & 6 deletions examples/svgWithLogoAndCustomShapes.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,8 @@ protected function path(string $path, int $M_TYPE):string{
*/
protected function module(int $x, int $y, int $M_TYPE):string{

if(
!$this->matrix->check($x, $y)
// we're skipping the finder patterns here
|| $this->matrix->checkType($x, $y, QRMatrix::M_FINDER)
|| $this->matrix->checkType($x, $y, QRMatrix::M_FINDER_DOT)
){
// we're skipping the finder patterns here
if(!$this->matrix->check($x, $y) || $this->matrix->checkTypeIn($x, $y, (QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT))){
return '';
}

Expand Down
74 changes: 44 additions & 30 deletions src/Data/QRMatrix.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,47 +22,51 @@
class QRMatrix{

/** @var int */
public const IS_DARK = 0b100000000000;
public const IS_DARK = 0b100000000000000000000000;
/** @var int */
public const M_NULL = 0b000000000000;
public const M_NULL = 0b000000000000000000000000;
/** @var int */
public const M_DARKMODULE = 0b100000000001;
public const M_DARKMODULE = 0b100000000001000000000001;
/** @var int */
public const M_DATA = 0b000000000010;
public const M_DATA = 0b000000000000000000000010;
/** @var int */
public const M_DATA_DARK = 0b100000000010;
public const M_DATA_DARK = 0b100000000010000000000010;
/** @var int */
public const M_FINDER = 0b000000000100;
public const M_FINDER = 0b000000000000000000000100;
/** @var int */
public const M_FINDER_DARK = 0b100000000100;
public const M_FINDER_DARK = 0b100000000100000000000100;
/** @var int */
public const M_SEPARATOR = 0b000000001000;
public const M_SEPARATOR = 0b000000000000000000001000;
/** @var int */
public const M_ALIGNMENT = 0b000000010000;
public const M_ALIGNMENT = 0b000000000000000000010000;
/** @var int */
public const M_ALIGNMENT_DARK = 0b100000010000;
public const M_ALIGNMENT_DARK = 0b100000010000000000010000;
/** @var int */
public const M_TIMING = 0b000000100000;
public const M_TIMING = 0b000000000000000000100000;
/** @var int */
public const M_TIMING_DARK = 0b100000100000;
public const M_TIMING_DARK = 0b100000100000000000100000;
/** @var int */
public const M_FORMAT = 0b000001000000;
public const M_FORMAT = 0b000000000000000001000000;
/** @var int */
public const M_FORMAT_DARK = 0b100001000000;
public const M_FORMAT_DARK = 0b100001000000000001000000;
/** @var int */
public const M_VERSION = 0b000010000000;
public const M_VERSION = 0b000000000000000010000000;
/** @var int */
public const M_VERSION_DARK = 0b100010000000;
public const M_VERSION_DARK = 0b100010000000000010000000;
/** @var int */
public const M_QUIETZONE = 0b000100000000;
public const M_QUIETZONE = 0b000000000000000100000000;
/** @var int */
public const M_LOGO = 0b001000000000;
public const M_QUIETZONE_DARK = 0b100100000000000100000000;
/** @var int */
public const M_FINDER_DOT = 0b110000000000;
public const M_LOGO = 0b000000000000001000000000;
/** @var int */
public const M_TEST = 0b011111111111;
public const M_LOGO_DARK = 0b101000000000001000000000;
/** @var int */
public const M_TEST_DARK = 0b111111111111;
public const M_FINDER_DOT = 0b110000000000010000000000;
/** @var int */
public const M_TEST = 0b000000000000011111111111;
/** @var int */
public const M_TEST_DARK = 0b111111111111011111111111;

/**
* Map of flag => coord
Expand Down Expand Up @@ -256,15 +260,24 @@ public function get(int $x, int $y):int{
/**
* Sets the $M_TYPE value for the module at position [$x, $y]
*
* true => $M_TYPE | 0x800
* true => (self::IS_DARK | ($M_TYPE << 12) | $M_TYPE)
* false => $M_TYPE
*/
public function set(int $x, int $y, bool $value, int $M_TYPE):self{

if(isset($this->matrix[$y][$x])){
$this->matrix[$y][$x] = (($M_TYPE & ~$this::IS_DARK) | (($value) ? $this::IS_DARK : 0));
if(!isset($this->matrix[$y][$x])){
return $this;
}

// we'll convert to the basic light value (lowest 11 bits), in case we get passed a dark $M_TYPE value
$val = ($M_TYPE & 0x7ff);

if($value === true){
$val = ($this::IS_DARK | ($val << 12) | $val);
}

$this->matrix[$y][$x] = $val;

return $this;
}

Expand Down Expand Up @@ -301,15 +314,16 @@ public function checkType(int $x, int $y, int $M_TYPE):bool{
* checks whether the module at ($x, $y) is in the given array of $M_TYPES,
* returns true if a match is found, otherwise false.
*/
public function checkTypeIn(int $x, int $y, array $M_TYPES):bool{
public function checkTypeIn(int $x, int $y, int $M_TYPES):bool{
$val = $this->get($x, $y);

foreach($M_TYPES as $type){
if($this->checkType($x, $y, $type)){
return true;
}
if($val === -1){
return false;
}

return false;
# printf("%024b\n%024b\n%024b\n\n", $M_TYPES, $val, (($val & $M_TYPES)));

return ($val & $M_TYPES & 0x7fffff) > 0;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/Output/QROutputInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ interface QROutputInterface{
QRMatrix::M_TIMING_DARK => true,
QRMatrix::M_FORMAT_DARK => true,
QRMatrix::M_VERSION_DARK => true,
QRMatrix::M_QUIETZONE_DARK => true,
QRMatrix::M_LOGO_DARK => true,
QRMatrix::M_FINDER_DOT => true,
QRMatrix::M_TEST_DARK => true,
];
Expand Down
4 changes: 2 additions & 2 deletions src/QROptionsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ trait QROptionsTrait{
/**
* specifies which module types to exclude when $drawCircularModules is set to true
*/
protected array $keepAsSquare = [];
protected int $keepAsSquare = 0;

/**
* whether to connect the paths for the several module types to avoid weird glitches when using gradients etc.
Expand All @@ -193,7 +193,7 @@ trait QROptionsTrait{
/**
* specify which paths/patterns to exclude from connecting if $connectPaths is set to true
*/
protected array $excludeFromConnect = [];
protected int $excludeFromConnect = 0;

/**
* Module values map
Expand Down
Loading