diff --git a/src/Generator.php b/src/Generator.php index 4ada416..63c5d36 100644 --- a/src/Generator.php +++ b/src/Generator.php @@ -257,15 +257,25 @@ 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; } @@ -273,15 +283,25 @@ public function color(int $red, int $green, int $blue, ?int $alpha = null): self /** * 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; } @@ -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); diff --git a/src/HexToRgb.php b/src/HexToRgb.php new file mode 100644 index 0000000..03b8350 --- /dev/null +++ b/src/HexToRgb.php @@ -0,0 +1,70 @@ +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; + } + + } +} diff --git a/tests/HexToRgbTest.php b/tests/HexToRgbTest.php new file mode 100644 index 0000000..aac31a7 --- /dev/null +++ b/tests/HexToRgbTest.php @@ -0,0 +1,92 @@ +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'); + } + +}