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

Added support for hex code colors #276

Open
wants to merge 2 commits into
base: develop
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
69 changes: 59 additions & 10 deletions src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,31 +257,51 @@ public function format(string $format): self
/**
* Sets the foreground color of the QrCode.
*
* @param int $red
* @param int $green
* @param int $blue
* @param int|string $redOrHex
* @param null|int $green
* @param null|int $blue
* @param null|int $alpha
*
* @return Generator
*/
public function color(int $red, int $green, int $blue, ?int $alpha = null): self
public function color(int|string $redOrHex, ?int $green = null, ?int $blue = null, ?int $alpha = null): self
{
$this->color = $this->createColor($red, $green, $blue, $alpha);
if (is_string($redOrHex)) {
$hexToRgb = $this->hexToRgb($redOrHex);

return $this->color(...$hexToRgb);
} else {
if (is_null($green) || is_null($blue)) {
throw new InvalidArgumentException('You must provide a green and blue value.');
}
}
$this->color = $this->createColor($redOrHex, $green, $blue, $alpha);

return $this;
}

/**
* Sets the background color of the QrCode.
*
* @param int $red
* @param int $green
* @param int $blue
* @param int|string $redOrHex
* @param null|int $green
* @param null|int $blue
* @param null|int $alpha
*
* @return Generator
*/
public function backgroundColor(int $red, int $green, int $blue, ?int $alpha = null): self
public function backgroundColor(int|string $redOrHex, ?int $green = null, ?int $blue = null, ?int $alpha = null): self
{
$this->backgroundColor = $this->createColor($red, $green, $blue, $alpha);
if (is_string($redOrHex)) {
$hexToRgb = $this->hexToRgb($redOrHex);

return $this->backgroundColor(...$hexToRgb);
} else {
if (is_null($green) || is_null($blue)) {
throw new InvalidArgumentException('You must provide a green and blue value.');
}
}
$this->backgroundColor = $this->createColor($redOrHex, $green, $blue, $alpha);

return $this;
}
Expand Down Expand Up @@ -313,6 +333,35 @@ public function eyeColor(int $eyeNumber, int $innerRed, int $innerGreen, int $in
return $this;
}

/**
* Sets the eye color for the provided eye index by providing hex codes.
* @param int $eyeNumber
* @param string $innerHex
* @param string $outterHex
*
* @return Generator
*/
public function eyeColorFromHex(int $eyeNumber, string $innerHex, string $outterHex = '#000000'): self
{
if (!in_array($eyeNumber, [0, 1, 2])) {
throw new InvalidArgumentException("\$eyeNumber must be 0, 1, or 2. {$eyeNumber} is not valid.");
}

return $this->eyeColor($eyeNumber, ...$this->hexToRgb($innerHex), ...$this->hexToRgb($outterHex));
}

/**
* Converts a hex color to an array of rgb values.
*
* @param string $hex
*
* @return array
*/
private function hexToRgb(string $hex): array
{
return (new HexToRgb($hex))->toRGBArray();
}

public function gradient($startRed, $startGreen, $startBlue, $endRed, $endGreen, $endBlue, string $type): self
{
$type = strtoupper($type);
Expand Down
70 changes: 70 additions & 0 deletions src/HexToRgb.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

namespace SimpleSoftwareIO\QrCode;

use InvalidArgumentException;

class HexToRgb
{
public int $red;
public int $green;
public int $blue;

public function __construct(public string $hex, public mixed $alpha = false)
{
if ($this->validateHex($hex) === false) {
throw new InvalidArgumentException('Invalid hex value, not a hex code');
}

$this->hexToRgb($hex, $alpha);
}

public function toRGBArray(): array
{
return [
$this->red,
$this->green,
$this->blue,
];
}

/**
* Validate a hex code. Returns true if valid, false if not.
* Taken from Drupal.
* @see https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Component%21Utility%21Color.php/function/Color%3A%3AvalidateHex/8.2.x
*
* @param string $hex
*
* @return bool
*/
private function validateHex(string $hex): bool
{
return preg_match('/^[#]?([0-9a-fA-F]{3}){1,2}$/', $hex) === 1;
}

/**
* Convert a hex code to RGB.
*
* @see https://stackoverflow.com/questions/15202079/convert-hex-color-to-rgb-values-in-php
*
* @param string $hex
* @param mixed $alpha
*
* @return void
*/
private function hexToRgb(string $hex, mixed $alpha = false): void
{
$hex = str_replace('#', '', $hex);
$length = strlen($hex);
$this->red = hexdec($length == 6 ? substr($hex, 0, 2) : ($length == 3 ? str_repeat(substr($hex, 0, 1),
2) : 0));
$this->green = hexdec($length == 6 ? substr($hex, 2, 2) : ($length == 3 ? str_repeat(substr($hex, 1, 1),
2) : 0));
$this->blue = hexdec($length == 6 ? substr($hex, 4, 2) : ($length == 3 ? str_repeat(substr($hex, 2, 1),
2) : 0));
if ($alpha) {
$this->alpha = $alpha;
}

}
}
92 changes: 92 additions & 0 deletions tests/HexToRgbTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

use PHPUnit\Framework\TestCase;
use SimpleSoftwareIO\QrCode\Generator;

class HexToRgbTest extends TestCase
{
public function text_hex_code_convert_to_rgb_possible()
{
$this->assertInstanceOf(Generator::class, (new Generator)->color('#ff0000'));
$this->assertInstanceOf(Generator::class, (new Generator)->backgroundColor('#ffffff'));
$this->assertInstanceOf(Generator::class, (new Generator)->eyeColorFromHex(0, '#ffff00', '#0000ff'));
}

public function test_color_is_set()
{
$generator = (new Generator)->color('#324B64');
$this->assertEquals(50, $generator->getFill()->getForegroundColor()->toRgb()->getRed());
$this->assertEquals(75, $generator->getFill()->getForegroundColor()->toRgb()->getGreen());
$this->assertEquals(100, $generator->getFill()->getForegroundColor()->toRgb()->getBlue());

$generator = (new Generator)->color('#324B64', alpha: 25);
// $this->assertEquals(25, $generator->getFill()->getForegroundColor()->getAlpha());
$this->assertEquals(50, $generator->getFill()->getForegroundColor()->toRgb()->getRed());
$this->assertEquals(75, $generator->getFill()->getForegroundColor()->toRgb()->getGreen());
$this->assertEquals(100, $generator->getFill()->getForegroundColor()->toRgb()->getBlue());

$generator = (new Generator)->color('#324B64', alpha: 0);
//$this->assertEquals(0, $generator->getFill()->getForegroundColor()->getAlpha());
$this->assertEquals(50, $generator->getFill()->getForegroundColor()->toRgb()->getRed());
$this->assertEquals(75, $generator->getFill()->getForegroundColor()->toRgb()->getGreen());
$this->assertEquals(100, $generator->getFill()->getForegroundColor()->toRgb()->getBlue());
$this->markTestIncomplete('This test has not been tested yet.');
}

public function test_background_color_is_set()
{
$generator = (new Generator)->backgroundColor('#324B64');
$this->assertEquals(50, $generator->getFill()->getBackgroundColor()->toRgb()->getRed());
$this->assertEquals(75, $generator->getFill()->getBackgroundColor()->toRgb()->getGreen());
$this->assertEquals(100, $generator->getFill()->getBackgroundColor()->toRgb()->getBlue());

$generator = (new Generator)->backgroundColor('#324B64', alpha: 25);
// $this->assertEquals(25, $generator->getFill()->getBackgroundColor()->getAlpha());
$this->assertEquals(50, $generator->getFill()->getBackgroundColor()->toRgb()->getRed());
$this->assertEquals(75, $generator->getFill()->getBackgroundColor()->toRgb()->getGreen());
$this->assertEquals(100, $generator->getFill()->getBackgroundColor()->toRgb()->getBlue());
$this->markTestIncomplete('Alpha is not yet tested.');
}

public function test_eye_color_is_set()
{
$generator = (new Generator)->eyeColorFromHex(0, '#000000', '#fff');
$generator = $generator->eyeColorFromHex(1, '#000', '#fff');
$generator = $generator->eyeColorFromHex(2, '#000', '#fff');

$this->assertEquals(0, $generator->getFill()->getTopLeftEyeFill()->getExternalColor()->getRed());
$this->assertEquals(0, $generator->getFill()->getTopLeftEyeFill()->getExternalColor()->getGreen());
$this->assertEquals(0, $generator->getFill()->getTopLeftEyeFill()->getExternalColor()->getBlue());
$this->assertEquals(255, $generator->getFill()->getTopLeftEyeFill()->getInternalColor()->getRed());
$this->assertEquals(255, $generator->getFill()->getTopLeftEyeFill()->getInternalColor()->getGreen());
$this->assertEquals(255, $generator->getFill()->getTopLeftEyeFill()->getInternalColor()->getBlue());

$this->assertEquals(0, $generator->getFill()->getTopRightEyeFill()->getExternalColor()->getRed());
$this->assertEquals(0, $generator->getFill()->getTopRightEyeFill()->getExternalColor()->getGreen());
$this->assertEquals(0, $generator->getFill()->getTopRightEyeFill()->getExternalColor()->getBlue());
$this->assertEquals(255, $generator->getFill()->getTopRightEyeFill()->getInternalColor()->getRed());
$this->assertEquals(255, $generator->getFill()->getTopRightEyeFill()->getInternalColor()->getGreen());
$this->assertEquals(255, $generator->getFill()->getTopRightEyeFill()->getInternalColor()->getBlue());

$generator = (new Generator)->eyeColor(2, 0, 0, 0, 255, 255, 255);
$this->assertEquals(0, $generator->getFill()->getBottomLeftEyeFill()->getExternalColor()->getRed());
$this->assertEquals(0, $generator->getFill()->getBottomLeftEyeFill()->getExternalColor()->getGreen());
$this->assertEquals(0, $generator->getFill()->getBottomLeftEyeFill()->getExternalColor()->getBlue());
$this->assertEquals(255, $generator->getFill()->getBottomLeftEyeFill()->getInternalColor()->getRed());
$this->assertEquals(255, $generator->getFill()->getBottomLeftEyeFill()->getInternalColor()->getGreen());
$this->assertEquals(255, $generator->getFill()->getBottomLeftEyeFill()->getInternalColor()->getBlue());
}

public function test_eye_color_throws_exception_with_number_greater_than_2()
{
$this->expectException(InvalidArgumentException::class);
(new Generator)->eyeColorFromHex(3, '#fff', '#000');
}

public function test_eye_color_throws_exception_with_negative_number()
{
$this->expectException(InvalidArgumentException::class);
(new Generator)->eyeColorFromHex(-1, '#fff', '#000');
}

}