:octocat: M_TYPE bitmask rework

This commit is contained in:
smiley
2023-06-08 23:21:32 +02:00
parent c8c37a4e36
commit 92a0ba2da9
14 changed files with 83 additions and 113 deletions
+1 -5
View File
@@ -25,11 +25,7 @@ $options = new QROptions([
'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)
+1 -1
View File
@@ -85,7 +85,7 @@ $options = new QROptions([
'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);
+1 -5
View File
@@ -25,11 +25,7 @@ $options = new QROptions([
'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)
+1 -5
View File
@@ -108,11 +108,7 @@ $options = new ImagickWithLogoOptions([
'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),
]);
+2 -5
View File
@@ -33,11 +33,8 @@ $options = new QROptions([
// 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%">
+3 -6
View File
@@ -48,7 +48,7 @@ class MeltedSVGQRCodeOutput extends QRMarkupSVG{
$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;
}
}
@@ -251,19 +251,16 @@ $options = new MeltedOutputOptions([
'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%"/>
+12 -23
View File
@@ -46,21 +46,19 @@ class RandomDotsSVGOutput extends QRMarkupSVG{
$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);
}
@@ -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
@@ -134,20 +132,11 @@ $options = new RandomDotsOptions([
'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
+7 -16
View File
@@ -185,14 +185,14 @@ class RoundQuietzoneSVGoutput extends QRMarkupSVG{
$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);
}
@@ -330,20 +330,11 @@ $options = new RoundQuietzoneOptions([
// 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');
+1 -5
View File
@@ -124,11 +124,7 @@ $options = new SVGWithLogoOptions([
// 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%">
+2 -6
View File
@@ -61,12 +61,8 @@ class QRSvgWithLogoAndCustomShapes extends QRMarkupSVG{
*/
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 '';
}
+44 -30
View File
@@ -22,47 +22,51 @@ use function array_fill, count, floor, range;
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
@@ -256,15 +260,24 @@ class QRMatrix{
/**
* 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;
}
@@ -301,15 +314,16 @@ class QRMatrix{
* 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;
}
/**
+2
View File
@@ -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,
];
+2 -2
View File
@@ -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.
@@ -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
+4 -4
View File
@@ -250,7 +250,7 @@ final class QRMatrixTest extends TestCase{
foreach($alignmentPattern as $py){
foreach($alignmentPattern as $px){
// skip finder pattern
if(!$matrix->checkTypeIn($px, $py, [QRMatrix::M_FINDER, QRMatrix::M_FINDER_DOT])){
if(!$matrix->checkTypeIn($px, $py, (QRMatrix::M_FINDER | QRMatrix::M_FINDER_DOT))){
$this::assertSame(QRMatrix::M_ALIGNMENT_DARK, $matrix->get($px, $py));
}
}
@@ -278,7 +278,7 @@ final class QRMatrixTest extends TestCase{
for($i = 7; $i < ($size - 7); $i++){
if(($i % 2) === 0){
// skip alignment pattern
if(!$matrix->checkTypeIn(6, $i, [QRMatrix::M_ALIGNMENT])){
if(!$matrix->checkTypeIn(6, $i, (QRMatrix::M_ALIGNMENT))){
$this::assertSame(QRMatrix::M_TIMING_DARK, $matrix->get(6, $i));
$this::assertSame(QRMatrix::M_TIMING_DARK, $matrix->get($i, 6));
}
@@ -490,8 +490,8 @@ final class QRMatrixTest extends TestCase{
public function testCheckTypeIn():void{
$this->matrix->set(10, 10, true, QRMatrix::M_QUIETZONE);
$this::assertFalse($this->matrix->checkTypeIn(10, 10, [QRMatrix::M_DATA, QRMatrix::M_FINDER]));
$this::assertTrue($this->matrix->checkTypeIn(10, 10, [QRMatrix::M_QUIETZONE, QRMatrix::M_FINDER]));
$this::assertFalse($this->matrix->checkTypeIn(10, 10, (QRMatrix::M_DATA | QRMatrix::M_FINDER)));
$this::assertTrue($this->matrix->checkTypeIn(10, 10, (QRMatrix::M_QUIETZONE | QRMatrix::M_FINDER)));
}
/**