mirror of
https://github.com/chillerlan/php-qrcode.git
synced 2026-08-31 04:28:03 +00:00
:octocat: M_TYPE bitmask rework
This commit is contained in:
+1
-5
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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%">
|
||||
|
||||
@@ -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%"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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%">
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,
|
||||
];
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user