From 40f64ab4dff88debe8fe309d12834696a205937b Mon Sep 17 00:00:00 2001 From: Jonatas Souza Date: Fri, 20 Oct 2023 16:01:26 -0300 Subject: [PATCH] feature: adding gradient colors for foreground and foreground styles --- docs/helpful-guides/advance-usage.md | 55 ++++++ src/Contracts/ColorsInterface.php | 78 ++++++++ src/Contracts/PathStyleInterface.php | 45 +++++ src/Contracts/QrCodeInterface.php | 8 +- src/QrCode.php | 203 ++++++++++++++++---- src/StyleManager.php | 274 +++++++++++++++++++++++++++ src/Traits/ImageTrait.php | 13 +- src/Writer/AbstractWriter.php | 68 ++++--- src/Writer/EpsWriter.php | 8 +- src/Writer/SvgWriter.php | 12 +- tests/_data/colors/gradient.jpg | Bin 0 -> 18307 bytes tests/_data/colors/gradient.png | Bin 0 -> 4563 bytes tests/_data/colors/gradient.svg | 2 + tests/_data/colors/gradient2.png | Bin 0 -> 14447 bytes tests/_data/colors/gradient3.png | Bin 0 -> 3745 bytes tests/_data/colors/gradient4.png | Bin 0 -> 4791 bytes tests/_data/colors/uniform.eps | 1 + tests/_data/colors/uniform2.eps | 1 + tests/_data/path/dots.png | Bin 0 -> 5063 bytes tests/_data/path/dots2.png | Bin 0 -> 5323 bytes tests/_data/path/rounded.png | Bin 0 -> 7589 bytes tests/_data/path/rounded2.png | Bin 0 -> 6325 bytes tests/unit/ColorsTest.php | 159 ++++++++++++++++ tests/unit/PathTest.php | 60 ++++++ tests/unit/QrCodeTest.php | 35 +++- 25 files changed, 922 insertions(+), 100 deletions(-) create mode 100644 src/Contracts/ColorsInterface.php create mode 100644 src/Contracts/PathStyleInterface.php create mode 100644 src/StyleManager.php create mode 100644 tests/_data/colors/gradient.jpg create mode 100644 tests/_data/colors/gradient.png create mode 100644 tests/_data/colors/gradient.svg create mode 100644 tests/_data/colors/gradient2.png create mode 100644 tests/_data/colors/gradient3.png create mode 100644 tests/_data/colors/gradient4.png create mode 100644 tests/_data/colors/uniform.eps create mode 100644 tests/_data/colors/uniform2.eps create mode 100644 tests/_data/path/dots.png create mode 100644 tests/_data/path/dots2.png create mode 100644 tests/_data/path/rounded.png create mode 100644 tests/_data/path/rounded2.png create mode 100644 tests/unit/ColorsTest.php create mode 100644 tests/unit/PathTest.php diff --git a/docs/helpful-guides/advance-usage.md b/docs/helpful-guides/advance-usage.md index b0dd225..4bc00c5 100644 --- a/docs/helpful-guides/advance-usage.md +++ b/docs/helpful-guides/advance-usage.md @@ -46,5 +46,60 @@ $qrCode = (new QrCode('https://2am.tech')) ->setScaleLogoHeight(false); ``` +### Gradient Foreground + +You can easily change from uniform to gradient color by setting +the range limit for you gradient for using the method `setForegroundEndColor`. +When you do this, the color you've set for the foreground using `setForegroundColor` +function will be taken as the start point for the gradient color. + +```PHP +$qrCode = (new QrCode('https://2am.tech')) + ->setForegroundColor(0, 255, 0, 70) + ->setForegroundEndColor(0, 0, 255, 50); +``` + +By default, it will render the gradient color using a vertical orientation. +You can change it by the `setGradientType` function. It takes one parameter +to determine witch gradient type must be set. +The available types are: + +* \Da\QrCode\Contracts\ColorsInterface::GRADIENT_VERTICAL +* \Da\QrCode\Contracts\ColorsInterface::GRADIENT_HORIZONTAL +* \Da\QrCode\Contracts\ColorsInterface::GRADIENT_RADIAL +* \Da\QrCode\Contracts\ColorsInterface::GRADIENT_DIAGONAL +* \Da\QrCode\Contracts\ColorsInterface::GRADIENT_INVERSE_DIAGONAL + +```PHP +$qrCode = (new QrCode('https://2am.tech')) + ->setForegroundColor(0, 255, 0, 70) + ->setForegroundEndColor(0, 0, 255, 50) + ->setGradientType(\Da\QrCode\Contracts\ColorsInterface::GRADIENT_DIAGONAL); +``` + +### Foreground Path Style +It is possible to change the foreground path style by using the `setPathStyle` +function. The default style will be the square pattern, and the available +styles are the following: + +* \Da\QrCode\Contracts\PathStyleInterface::SQUARE; +* \Da\QrCode\Contracts\PathStyleInterface::DOTS; +* \Da\QrCode\Contracts\PathStyleInterface::ROUNDED; + +```PHP +$qrCode = (new QrCode('https://2am.tech')) + ->setPathStyle(\Da\QrCode\Contracts\PathStyleInterface::ROUNDED); +``` + +You can also set the intensity for the pattern appliance: + +```PHP +$qrCode = (new QrCode('https://2am.tech')) + ->setPathStyle(\Da\QrCode\Contracts\PathStyleInterface::ROUNDED) + ->setPathIntensity(0.7); +``` + +The default value for the intensity is 1. It must be a number between 0 and 1, +otherwise an exception will be thrown. © [2amigos](https://2am.tech/) 2013-2023 diff --git a/src/Contracts/ColorsInterface.php b/src/Contracts/ColorsInterface.php new file mode 100644 index 0000000..9a44979 --- /dev/null +++ b/src/Contracts/ColorsInterface.php @@ -0,0 +1,78 @@ + 0, - 'g' => 0, - 'b' => 0, - 'a' => 100, - ]; - /** - * @var array - */ - protected $backgroundColor = [ - 'r' => 255, - 'g' => 255, - 'b' => 255, - 'a' => 100, - ]; /** * @var string */ @@ -79,6 +63,11 @@ class QrCode implements QrCodeInterface */ protected $writer; + /** + * @var StyleManager + */ + protected $styleManager; + /** * QrCode constructor. * @@ -91,6 +80,13 @@ public function __construct(string $text, string $errorCorrectionLevel = null, W $this->text = $text; $this->errorCorrectionLevel = $errorCorrectionLevel ?: ErrorCorrectionLevelInterface::LOW; $this->writer = $writer ?: new PngWriter(); + + $canApplyAlpha = ! $this->writer instanceof EpsWriter; + + $this->styleManager = new StyleManager( + StyleManager::buildColor(0, 0, 0, 100, $canApplyAlpha), + StyleManager::buildColor(255, 255, 255, 100, $canApplyAlpha) + ); } /** @@ -102,12 +98,47 @@ public function __construct(string $text, string $errorCorrectionLevel = null, W */ public function setForegroundColor(int $red, int $green, int $blue, int $alpha = 100): self { - $this->foregroundColor = [ - 'r' => $red, - 'g' => $green, - 'b' => $blue, - 'a' => $alpha, - ]; + $color = StyleManager::buildColor( + $red, + $green, + $blue, + $alpha, + ! $this->getWriter() instanceof EpsWriter + ); + + $this->styleManager->setForegroundColor($color); + + return $this; + } + + /** + * @param int $red + * @param int $green + * @param int $blue + * + * @return $this + */ + public function setForegroundEndColor(int $red, int $green, int $blue, int $alpha = 100): self + { + $color = StyleManager::buildColor( + $red, + $green, + $blue, + $alpha, + !$this->getWriter() instanceof EpsWriter + ); + + $this->styleManager->setForegroundEndColor($color); + + return $this; + } + + /** + * @return $this + */ + public function unsetForegroundEndColor(): self + { + $this->styleManager->unsetForegroundEndColor(); return $this; } @@ -121,16 +152,67 @@ public function setForegroundColor(int $red, int $green, int $blue, int $alpha = */ public function setBackgroundColor(int $red, int $green, int $blue): self { - $this->backgroundColor = [ - 'r' => $red, - 'g' => $green, - 'b' => $blue, - 'a' => 100, - ]; + $color = StyleManager::buildColor( + $red, + $green, + $blue, + 100, + ! $this->getWriter() instanceof EpsWriter + ); + + $this->styleManager->setBackgroundColor($color); + + return $this; + } + + /** + * @param string $style + * @return $this + */ + public function setPathStyle(string $style): self + { + $this->styleManager->setPathStyle($style); + + return $this; + } + + /** + * @param float $intensity + * @return $this + */ + public function setPathIntensity(float $intensity): self + { + $this->styleManager->setIntensity($intensity); return $this; } + /** + * @return StyleManager + */ + public function getStyleManager() + { + return $this->styleManager; + } + + /** + * @return float + */ + public function getPathIntensity(): float + { + return $this->styleManager->getIntensity(); + } + + /** + * @return string + */ + public function getGradientType(): string + { + return $this + ->styleManager + ->getGradientTye(); + } + /** * @param string $path * @@ -169,6 +251,21 @@ public function setWriter(WriterInterface $writer): self { $this->writer = $writer; + if ($writer instanceof EpsWriter) { + $this->styleManager->forceUniformRgbColors(); + } + + return $this; + } + + /** + * @param string $type + * @return $this + */ + public function setGradientType(string $type): self + { + $this->styleManager->setGradientType($type); + return $this; } @@ -292,7 +389,40 @@ public function getMargin(): int */ public function getForegroundColor(): array { - return $this->foregroundColor; + $color = $this->styleManager->getForegroundColor(); + $rgb = $color->toRgb(); + + return [ + 'r' => $rgb->getRed(), + 'g' => $rgb->getGreen(), + 'b' => $rgb->getBlue(), + 'a' => $color instanceof Alpha + ? $color->getAlpha() + : 100 + ]; + } + + /** + * @inheritdoc + */ + public function getForegroundEndColor() + { + $color = $this->styleManager->getForegroundEndColor(); + + if (is_null($color)) { + return null; + } + + $rgb = $color->toRgb(); + + return [ + 'r' => $rgb->getRed(), + 'g' => $rgb->getGreen(), + 'b' => $rgb->getBlue(), + 'a' => $color instanceof Alpha + ? $color->getAlpha() + : 100 + ]; } /** @@ -300,7 +430,14 @@ public function getForegroundColor(): array */ public function getBackgroundColor(): array { - return $this->backgroundColor; + $color = $this->styleManager->getBackgroundColor(); + $rgb = $color->toRgb(); + + return [ + 'r' => $rgb->getRed(), + 'g' => $rgb->getGreen(), + 'b' => $rgb->getBlue() + ]; } /** @@ -382,7 +519,7 @@ public function writeFile(string $path) /** * @return bool */ - public function getScaleLogoHeight(): bool + public function isScaleLogoHeight(): bool { return $this->scaleLogoHeight; } diff --git a/src/StyleManager.php b/src/StyleManager.php new file mode 100644 index 0000000..68b1515 --- /dev/null +++ b/src/StyleManager.php @@ -0,0 +1,274 @@ +setForegroundColor($foregroundColor); + $this->setBackgroundColor($backgroundColor); + + $this->pathStyle = $pathStyle ?: PathStyleInterface::SQUARE; + $this->styleIntensity = $styleIntensity ?: 1; + $this->gradientType = $gradientType ?: ColorsInterface::GRADIENT_VERTICAL; + } + + /** + * @param $color + * @return void + * @throws Exception + */ + public function setForegroundColor($color): void + { + if (! $color instanceof ColorInterface) { + throw new Exception('Invalid type. Variable `color` should be instance of ' . ColorInterface::class); + } + + $this->foregroundColor = $color; + } + + public function getForegroundColor() + { + return $this->foregroundColor; + } + + public function getForegroundEndColor() + { + return $this->foregroundEndColor; + } + + /** + * @param Alpha|Rgb $color + * @return void + * @throws \Exception + */ + public function setForegroundEndColor($color): void + { + if (! $color instanceof ColorInterface) { + throw new Exception('Invalid type. Variable `color` should be instance of ' . ColorInterface::class); + } + + $this->foregroundEndColor = $color; + } + + /** + * @return void + */ + public function unsetForegroundEndColor(): void + { + $this->foregroundEndColor = null; + } + + public function setBackgroundColor($color): void + { + if (! $color instanceof ColorInterface) { + throw new Exception('Invalid type. Variable `color` should be instance of ' . ColorInterface::class); + } + + $this->backgroundColor = $color; + } + + /** + * @return Alpha|Rgb|Gradient + */ + public function getBackgroundColor() + { + return $this->backgroundColor; + } + + /** + * @param string $pathStyle + * @return void + */ + public function setPathStyle(string $pathStyle): void + { + $this->pathStyle = $pathStyle; + } + + /** + * @return string + */ + public function getPathStyle(): string + { + return $this->pathStyle; + } + + /** + * @param float $intensity + * @return void + */ + public function setIntensity(float $intensity): void + { + $this->styleIntensity = $intensity; + } + + /** + * @return float + */ + public function getIntensity(): float + { + return $this->styleIntensity; + } + + /** + * @param string $type + * @return void + */ + public function setGradientType(string $type): void + { + $this->gradientType = $type; + } + + /** + * @return GradientType + */ + public function getGradientTye() + { + switch ($this->gradientType) { + case ColorsInterface::GRADIENT_VERTICAL: { + return GradientType::VERTICAL(); + } + case ColorsInterface::GRADIENT_DIAGONAL: { + return GradientType::DIAGONAL(); + } + case ColorsInterface::GRADIENT_INVERSE_DIAGONAL: { + return GradientType::INVERSE_DIAGONAL(); + } + case ColorsInterface::GRADIENT_HORIZONTAL: { + return GradientType::HORIZONTAL(); + } + case ColorsInterface::GRADIENT_RADIAL: { + return GradientType::RADIAL(); + } + default: return GradientType::VERTICAL(); + } + } + + /** + * @return void + */ + public function forceUniformRgbColors(): void + { + $this->unsetForegroundEndColor(); + + $this->foregroundColor = $this->foregroundColor instanceof Alpha + ? $this->foregroundColor->getBaseColor() + : $this->foregroundColor; + + $this->backgroundColor = $this->backgroundColor instanceof Alpha + ? $this->backgroundColor->getBaseColor() + : $this->backgroundColor; + } + + /** + * @param $red + * @param $green + * @param $blue + * @param $alpha + * @return Alpha|Rgb + */ + public static function buildColor($red, $green, $blue, $alpha = 100, $applyAlpha = true) + { + if ($applyAlpha) { + return new Alpha($alpha, new Rgb( + $red, + $green, + $blue, + )); + } + + return new Rgb($red, $green, $blue); + } + + /** + * @return Fill + */ + public function buildFillColor() + { + if (! is_null($this->foregroundEndColor)) { + return Fill::uniformGradient( + $this->getBackgroundColor(), + new Gradient( + $this->getForegroundColor(), + $this->getForegroundEndColor(), + $this->getGradientTye(), + ) + ); + } + else { + return Fill::uniformColor( + $this->getBackgroundColor(), + $this->getForegroundColor() + ); + } + } + + /** + * @return ModuleInterface + */ + public function buildModule() + { + switch ($this->getPathStyle()) { + case PathStyleInterface::DOTS: return new DotsModule($this->getIntensity()); + case PathStyleInterface::ROUNDED: return new RoundnessModule($this->getIntensity()); + default: return SquareModule::instance(); + } + } + + /** + * @return ModuleEye + */ + public function buildEye() + { + return new ModuleEye($this->buildModule()); + } +} \ No newline at end of file diff --git a/src/Traits/ImageTrait.php b/src/Traits/ImageTrait.php index 95512e4..ec7a145 100644 --- a/src/Traits/ImageTrait.php +++ b/src/Traits/ImageTrait.php @@ -11,8 +11,6 @@ namespace Da\QrCode\Traits; -use BaconQrCode\Renderer\RendererStyle\RendererStyle; -use BaconQrCode\Renderer\ImageRenderer; use BaconQrCode\Writer; use Da\QrCode\Contracts\LabelInterface; use Da\QrCode\Contracts\QrCodeInterface; @@ -45,14 +43,7 @@ public function validateResult(bool $validate): self */ public function writeString(QrCodeInterface $qrCode): string { - $fill = $this->buildQrCodeFillColor($qrCode); - - $rendererStyle = new RendererStyle($qrCode->getSize(), 0, null, null, $fill); - - $renderer = new ImageRenderer( - $rendererStyle, - $this->renderBackEnd - ); + $renderer = $this->buildRenderer($qrCode); $writer = new Writer($renderer); $string = $writer->writeString( @@ -75,7 +66,7 @@ public function writeString(QrCodeInterface $qrCode): string $image, $qrCode->getLogoPath(), $qrCode->getLogoWidth(), - $qrCode->getScaleLogoHeight() + $qrCode->isScaleLogoHeight() ); } diff --git a/src/Writer/AbstractWriter.php b/src/Writer/AbstractWriter.php index c4df8bd..8542d3a 100644 --- a/src/Writer/AbstractWriter.php +++ b/src/Writer/AbstractWriter.php @@ -12,10 +12,9 @@ namespace Da\QrCode\Writer; use BaconQrCode\Common\ErrorCorrectionLevel; -use BaconQrCode\Renderer\Color\Alpha; -use BaconQrCode\Renderer\Color\Rgb; use BaconQrCode\Renderer\Image\ImageBackEndInterface; -use BaconQrCode\Renderer\RendererStyle\Fill; +use BaconQrCode\Renderer\ImageRenderer; +use BaconQrCode\Renderer\RendererStyle\RendererStyle; use Da\QrCode\Contracts\QrCodeInterface; use Da\QrCode\Contracts\WriterInterface; use Da\QrCode\Dto\LogoDto; @@ -39,22 +38,6 @@ protected function __construct(ImageBackEndInterface $renderBackEnd) $this->renderBackEnd = $renderBackEnd; } - /** - * @param QrCodeInterface $qrCode - * @return Fill - */ - protected function buildQrCodeFillColor(QrCodeInterface $qrCode): Fill - { - $background = $qrCode->getBackgroundColor(); - $foreground = $qrCode->getForegroundColor(); - $isAlphaColor = ! $qrCode->getWriter() instanceof EpsWriter; - - return Fill::uniformColor( - $this->convertColor($background, $isAlphaColor), - $this->convertColor($foreground, $isAlphaColor), - ); - } - /** * @inheritdoc */ @@ -80,22 +63,6 @@ public function getName(): string return strtolower(str_replace('Writer', '', (new ReflectionClass($this))->getShortName())); } - /** - * @param array $color - * - * @return Alpha|Rgb - */ - protected function convertColor(array $color, bool $isAlphaColor = true) - { - $baseColor = new Rgb($color['r'], $color['g'], $color['b']); - - if ($isAlphaColor) { - return new Alpha($color['a'], $baseColor); - } - - return $baseColor; - } - /** * @param string $errorCorrectionLevel * @@ -131,4 +98,35 @@ protected function transformLogo($logoPath, $logoWidth = null, $scale = false) return LogoDto::create($logoImage, $logoSourceWidth, $logoSourceHeight, $logoTargetWidth, $logoTargetHeight); } + + /** + * @param QrCodeInterface $qrCode + * @return RendererStyle + */ + protected function getRendererStyle(QrCodeInterface $qrCode) + { + $margin = $qrCode->getWriter() instanceof EpsWriter + ? $qrCode->getMargin() + : 0; + + return new RendererStyle( + $qrCode->getSize(), + $margin, + $qrCode->getStyleManager()->buildModule(), + $qrCode->getStyleManager()->buildEye(), + $qrCode->getStyleManager()->buildFillColor() + ); + } + + /** + * @param QrCodeInterface $qrCode + * @return ImageRenderer + */ + protected function buildRenderer(QrCodeInterface $qrCode) + { + return new ImageRenderer( + $this->getRendererStyle($qrCode), + $this->renderBackEnd + ); + } } diff --git a/src/Writer/EpsWriter.php b/src/Writer/EpsWriter.php index f4c9aa8..89d1308 100644 --- a/src/Writer/EpsWriter.php +++ b/src/Writer/EpsWriter.php @@ -32,13 +32,7 @@ public function __construct() */ public function writeString(QrCodeInterface $qrCode): string { - $fill = $this->buildQrCodeFillColor($qrCode); - $rendererStyle = new RendererStyle($qrCode->getSize(), $qrCode->getMargin(), null, null, $fill); - - $renderer = new ImageRenderer( - $rendererStyle, - $this->renderBackEnd - ); + $renderer = $this->buildRenderer($qrCode);; $writer = new Writer($renderer); diff --git a/src/Writer/SvgWriter.php b/src/Writer/SvgWriter.php index 28a4f8d..d192cb8 100644 --- a/src/Writer/SvgWriter.php +++ b/src/Writer/SvgWriter.php @@ -14,7 +14,6 @@ use BaconQrCode\Encoder\Encoder; use BaconQrCode\Renderer\Image\SvgImageBackEnd; use BaconQrCode\Renderer\ImageRenderer; -use BaconQrCode\Renderer\RendererStyle\RendererStyle; use BaconQrCode\Writer; use Da\QrCode\Contracts\LabelInterface; use Da\QrCode\Contracts\QrCodeInterface; @@ -37,14 +36,7 @@ public function __construct() */ public function writeString(QrCodeInterface $qrCode): string { - $fill = $this->buildQrCodeFillColor($qrCode); - - $rendererStyle = new RendererStyle($qrCode->getSize(), 0, null, null, $fill); - - $renderer = new ImageRenderer( - $rendererStyle, - $this->renderBackEnd - ); + $renderer = $this->buildRenderer($qrCode); $writer = new Writer($renderer); @@ -64,7 +56,7 @@ public function writeString(QrCodeInterface $qrCode): string $qrCode, $qrCode->getLogoPath(), $qrCode->getLogoWidth(), - $qrCode->getScaleLogoHeight() + $qrCode->isScaleLogoHeight() ); } diff --git a/tests/_data/colors/gradient.jpg b/tests/_data/colors/gradient.jpg new file mode 100644 index 0000000000000000000000000000000000000000..46f92cd879fc485729891176e41110894c3f614b GIT binary patch literal 18307 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 BgX{nR literal 0 HcmV?d00001 diff --git a/tests/_data/colors/gradient.png b/tests/_data/colors/gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..c539ca21c875ce3ccf8bc7a08d2a57cecb4b77f5 GIT binary patch literal 4563 zcmaJ_c|25a`(_XZBcZV?#31{YG-9$;U(1MTQiCy;qN(g zjg8%8=i&hYBZ!~c+rSU6&q+srHZ}-#=VE`L3Xx=E6N))yX6kSwdp_sX+#!@Gt%TRc z4CH&snkSB?tbnH`YPlY~ij7hyT0rYti|4ThiM;_jgC+)1x?hMk_<;O(m*ntRd0KMv zZ;LO z27ew#;SkL3(*->#Rze_ksA$eQDbPw~&T-6P#b#wHpO}*`=|U zt%hikw^uoTO}ze14x^yuQe88RxvDu#e+003TO^u)O5fvlZN~NS@#85iy=q9brOUfC zJGx+&w0`~gPn*MT(Y{>$rdr4GL4!VA`kw9>LLl<57i5L~V2oNUbF$cVPbYQV%uf`e z-OT@s7^Z6f7k*#nIhS8k8D%GsoiPGu3OxDQTT`dnI50uD;M+gGCmD|%bzc@ zldEN>dpHl>nBeX&nNfzOsrp1p>$?b%W{UTt`!9Rw*v*AiA9_j3_45su9u#wxbGlTW zaF*{rgH9Q`he6pkkud~dbj|*kehiw9w)AF2tNEa@GDa{A!2lR8ryL7HDmXAm z6%$up?I(|g=G!@hw*<80#$Qkd(k+zb0RA=CJ#H2>(Hk;#6emLPT;A>;(aI<+;}1vW z`VZniXB0N2$<;q16HMB32Rh}NAmyzku9*}o6iGWic-5vfieXRkH3E}Vq2qt~zyJ*K*Z^@<%!q0gQojOw<`KHRdh|J7QdW9bJ5|O8`d+1*OPJ;K@I|8%d&^#-_&kl17!z%Kk=Bqp z8^&z3BedmJXaLJ4VD%@vl1%vigG#6EZKJKaGrry4|258osF@PVs7)B@=oW1UKR)98 z5xb%Pe#dCJ6F-iE{EpGL5JNN02Wi_$Rrqn%_wuUvNwbGn4RxCNHqMNKFP3(c2D#$~KA^NJ+U@L}pqw6$P7$rsgjGk+7?7ggYmne-9v5_826 z{xy-IRiQ+qpxoiQ=rk*{jt2EU*cxt|0sQ%g^?mxYM$S%zpu+?4tCf{*qnXL8|Bt@j9T$yMK>?8v#c- zW$L#tm-B74@@_PiM3V;64ae-55%ArO_!@^wNOAF(B&eyQu{#Au-d|4Xs%$r}7M@*w zv{fBUM?o9QMmiV@g?Hx6l2U@frf=7?)dQX-z`X7{Pt07`PfZxDdo<&ee#`A0-Cy%K z%*cWHEyG*-+)t9MiI#eMPa!e=qCpi==yq{jdq37BUo34bjXRcJ^M?_x$+QEj^*?#e z;`Am``ZM$g5=MJaEIxUeeoO~$)3I6v1-Fw$TDFbcbDN0wZ{aY`7H?Wb(`9#~e7Md6 zQ=l1A+A5lg8ZV50m~{zJZSU9RigEWGZ}Fuje|h&iQsR2uGWUto(E4t@vedQxy?9>4 zQ>EYyeYd3EW))NabVKLltvn|4k))$&dKp-`+`n4O58~Bd-t=d?F0a3FpOAX*z^GN% z9b!8fKgbvACw+MXED~@TRMmBL2#ATue?u0! z?{b>95z(_m&QPmAbuLW~yjk4|8dF!*H&SlK5RB|TNSPLct9E?g;n;#Ho-?RBA8g_^ zthk!j4U$-3yLM4B`^+%5=ERt)mqtMH>{n*)v5P$A;rP`L94X5o*YH$#L zUHdN_Xmc$BK68j^*3mo1n|%uh8q%%#9%rIWC|UJ-kF+|F<*5%BI-}bFQp!s=(eDO2 z8yPfU@;Bx{F$G^S@!-V2Dc;eUM_f@N!X1Sf*0#|i-4WTnJ7s2&^fxU7j3+u4V!4`s z6w6vb8h&N76xZcu^HjVa8u30;KII<@GO%UJ+rlM&1hg4KV?+Y&*Ghtur9gVm5|t;s zv#jn;by(cpAAp`MXhy=k^>q#aOdyf-o@3~H)Q|}jF**ITJfu~Me zc}`AF%p+Fzi;Juzb!&UKhwHBv5+u2gEuXx*?{J21=lXg5$n~S6DFZImVHAOzH^^R` zCkt~6E39t0^goucFVooLx#72Sa;s&O+#42gKiHa|Ju6@k{bW{OPd4?^cv4rPne(~A zPh-0w;MY%0`#C)?OXM>vhfGJwW=k%Yc7$5F2Y1Z)zJp$%nx~2Lke>BUg0=1Oa>{c+ z7hvSbd`|S;$n#t_KZUveZ4@@lSx$EsEisr<*}S}I9!XqKz|E-t)C z)!t!ZV~ej<)WVA=ceSG^Sr9Agef|wo^kC8Jz>w5hrKMIUmw$R&JIkIKzdOnq6mn)# z9HxjPWn3gpDAZ(UuX66W%KG?N4<6O|a(*OHm^ssjP=dXIT)@EKdX82$6B@O@In*et zY)$jTn5=U&9^oR2v)Z{^^Xws?#rc27EJV+16wDLNpMb78$Ef445o&W?moe`LkZ z!|8Q866KWeN|YFY9pSkCDk$lqk=v+xfGpnWEHLyhO}`YKBB6&9dNA`(Oy3`O>dAEIkLozCdL%yviG#vscK$8_Sf)d$%uUM75E(E$@eDY;Z8NUg3>UN zZhx%;BY-dWm0lDFN&-U|h*E>iI^G5-KN^hjlT`UP!M5*9zHY+G;hnm>j@c#LtGE;_ zysPrN>8N6VNF|rY?tOkWF<`PJ2`Cx=*DjD+NGs-D>UjL#l=}}K#aY=lEo**n>cuav z0IvkJz^!!}R`!U_;shVUd%f*$_VE0FlF!|yNIkVnu+=d z0c*&M>u8r#q=HBrBya8*fOqAEzau!*&+nBtL566LpV>jhN5B^lse{EcB_wGP6{D(- z{t*S2BjwXOrZZ6a?W*+!6{H{}8B`HFChD|15AeTZ7UCn?FW=3#(ptxL`9ELob(&UR z*jhe#Cuh3?E@3!FeFS;79!cqkmtU6&*?A$^f@X5I??Dx6=o`U?sppeYR$v>rny6RS zrGes(Nd-H@TSrDih^3bApjpx)ycd+6ZVDqy<1(5D=klfp#=&#~4n=3SdveF5r4Rv` zi-m}k;C9miarOVk0ZSH4&JDlTc+hXK^I4MaT_h$;AXbnvOVLpX&qgJKZ z?3wUomO>*ERW)OCtStKJ`x{t@3d@g1q(8pU{DG%4qVQK8nL{`h9C+O09t!)6GIo<_ z$d_4uY;hObi3)ww#&2=Es|QZL!mIe;2@5f@JyEu8acd3UX1%cf|}xCxrH&~nSdywLcqXjlp64s1Nai80I6Fv9c3yKV*?5^YTky{G! zW4BbiZCXXi!hkXp(Ywg-P;iSD4;1HZ?-=>iZD!{WKINiRdfL;E6p^nHSuiC9sO2{6 zQULmlp?Fs5DsD2b$dCi*I)E-je#i#;wo*C85a#_ByYqRYPEX9Op9(yFo^f70Q8V}d czgd{ByzAe)LzS6LrGPf}+M_?oW52GN6Q~&?~ literal 0 HcmV?d00001 diff --git a/tests/_data/colors/gradient.svg b/tests/_data/colors/gradient.svg new file mode 100644 index 0000000..b8de3bc --- /dev/null +++ b/tests/_data/colors/gradient.svg @@ -0,0 +1,2 @@ + + diff --git a/tests/_data/colors/gradient2.png b/tests/_data/colors/gradient2.png new file mode 100644 index 0000000000000000000000000000000000000000..32920c9ddbda8bba9e9bd1c96f647030eb50f764 GIT binary patch literal 14447 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

;p31$4vb}mNj}r#T`)(8m=b0LfBS< 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 literal 0 HcmV?d00001 diff --git a/tests/_data/path/dots2.png b/tests/_data/path/dots2.png new file mode 100644 index 0000000000000000000000000000000000000000..7c820a11377fea6c2f376d53d1fd8025bb0c21f4 GIT binary patch literal 5323 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 OBwF|M)GJl(!v6>E2vV{D literal 0 HcmV?d00001 diff --git a/tests/unit/ColorsTest.php b/tests/unit/ColorsTest.php new file mode 100644 index 0000000..0465ba7 --- /dev/null +++ b/tests/unit/ColorsTest.php @@ -0,0 +1,159 @@ +writeDataUri(); + + $eps2 = (new QrCode('2am Technologies')) + ->setWriter(new EpsWriter()) + ->writeDataUri(); + file_put_contents(codecept_data_dir('colors/uniform.eps'), $eps); + file_put_contents(codecept_data_dir('colors/uniform2.eps'), $eps2); + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('colors/uniform.eps'))), + $this->normalizeString($eps) + ); + + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('colors/uniform2.eps'))), + $this->normalizeString($eps2) + ); + } + + public function testGradientColors() + { + $png = (new QrCode('2am Technologies')) + ->setWriter(new PngWriter()) + ->setForegroundColor(0, 255, 0,75) + ->setForegroundEndColor(0, 0, 255,50) + ->setBackgroundColor(200, 200, 200) + ->setGradientType('x') + ->writeString(); + + $jpg = (new QrCode('2am Technologies')) + ->setWriter(new JpgWriter()) + ->setForegroundColor(0, 255, 0,25) + ->setForegroundEndColor(0, 0, 255,75) + ->setBackgroundColor(200, 200, 200) + ->setGradientType(ColorsInterface::GRADIENT_DIAGONAL) + ->writeString(); + + $svg = (new QrCode('2am Technologies')) + ->setWriter(new SvgWriter()) + ->setForegroundColor(0, 255, 0,25) + ->setForegroundEndColor(0, 0, 255,95) + ->setBackgroundColor(200, 200, 200) + ->setGradientType(ColorsInterface::GRADIENT_RADIAL) + ->writeString(); + + $png2 = (new QrCode('2am Technologies')) + ->setWriter(new PngWriter()) + ->setForegroundColor(0, 255, 0,80) + ->setForegroundEndColor(0, 0, 255,50) + ->setBackgroundColor(200, 200, 200) + ->setGradientType(ColorsInterface::GRADIENT_INVERSE_DIAGONAL) + ->writeString(); + + $png3 = (new QrCode('2am Technologies')) + ->setWriter(new PngWriter()) + ->setForegroundColor(0, 255, 0,75) + ->setForegroundEndColor(0, 0, 255,100) + ->setBackgroundColor(200, 200, 200) + ->setGradientType(ColorsInterface::GRADIENT_HORIZONTAL) + ->writeString(); + + $png4 = (new QrCode('2am Technologies')) + ->setWriter(new PngWriter()) + ->setForegroundColor(0, 255, 0,75) + ->setForegroundEndColor(0, 0, 255,100) + ->setBackgroundColor(200, 200, 200) + ->setGradientType(ColorsInterface::GRADIENT_VERTICAL) + ->writeString(); + + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('colors/gradient.png'))), + $this->normalizeString($png) + ); + + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('colors/gradient.jpg'))), + $this->normalizeString($jpg) + ); + + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('colors/gradient.svg'))), + $this->normalizeString($svg) + ); + + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('colors/gradient2.png'))), + $this->normalizeString($png2) + ); + + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('colors/gradient3.png'))), + $this->normalizeString($png3) + ); + + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('colors/gradient4.png'))), + $this->normalizeString($png4) + ); + } + + public function testInvalidForegroundColorShouldThrowException() + { + $this->expectException(\Exception::class); + + new StyleManager('x', 'y'); + } + + public function testInvalidForegroundEndColorShouldThrowException() + { + $this->expectException(\Exception::class); + + (new StyleManager( + new Rgb(0,0,0), new Rgb(255,255,255) + ))->setForegroundEndColor('x'); + } + + public function testInvalidBackgroundColorShouldThrowException() + { + $this->expectException(\Exception::class); + + (new StyleManager( + new Rgb(0,0,0), new Rgb(255,255,255) + ))->setBackgroundColor('x'); + } + + public function testForceRgb() + { + $this->expectNotToPerformAssertions(); + + (new StyleManager(new Rgb(0,0,0), new Rgb(255,255,255))) + ->forceUniformRgbColors(); + } + + protected function normalizeString($string) + { + return str_replace( + "\r\n", "\n", str_replace( + " ", "", $string + ) + ); + } +} \ No newline at end of file diff --git a/tests/unit/PathTest.php b/tests/unit/PathTest.php new file mode 100644 index 0000000..223e352 --- /dev/null +++ b/tests/unit/PathTest.php @@ -0,0 +1,60 @@ +setPathStyle(\Da\QrCode\Contracts\PathStyleInterface::ROUNDED) + ->writeString(); + file_put_contents(codecept_data_dir('path/rounded.png'), $rounded); + $rounded2 = (new \Da\QrCode\QrCode('2am Technologies')) + ->setPathStyle(\Da\QrCode\Contracts\PathStyleInterface::ROUNDED) + ->setPathIntensity(0.7) + ->writeString(); + file_put_contents(codecept_data_dir('path/rounded2.png'), $rounded2); + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('path/rounded.png'))), + $this->normalizeString($rounded) + ); + + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('path/rounded2.png'))), + $this->normalizeString($rounded2) + ); + } + + public function testDotsPath() + { + $dots = (new \Da\QrCode\QrCode('2am Technologies')) + ->setPathStyle(\Da\QrCode\Contracts\PathStyleInterface::DOTS) + ->writeString(); + file_put_contents(codecept_data_dir('path/dots.png'), $dots); + + $dots2 = (new \Da\QrCode\QrCode('2am Technologies')) + ->setPathStyle(\Da\QrCode\Contracts\PathStyleInterface::DOTS) + ->setPathIntensity(0.7) + ->writeString(); + file_put_contents(codecept_data_dir('path/dots2.png'), $dots2); + + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('path/dots.png'))), + $this->normalizeString($dots) + ); + + $this->assertEquals( + $this->normalizeString(file_get_contents(codecept_data_dir('path/dots2.png'))), + $this->normalizeString($dots2) + ); + } + + protected function normalizeString($string) + { + return str_replace( + "\r\n", "\n", str_replace( + " ", "", $string + ) + ); + } +} \ No newline at end of file diff --git a/tests/unit/QrCodeTest.php b/tests/unit/QrCodeTest.php index c1bf603..bcdadfb 100644 --- a/tests/unit/QrCodeTest.php +++ b/tests/unit/QrCodeTest.php @@ -1,5 +1,6 @@ tester->assertEquals( $this->normalizeString(file_get_contents(codecept_data_dir('data.eps'))), - $out + $this->normalizeString($out) ); } @@ -103,12 +104,12 @@ public function testSetOutputFormat() $eps = (new QrCode('https://2am.tech')) ->setWriter(new \Da\QrCode\Writer\EpsWriter()) ->writeString(); - + file_put_contents(codecept_data_dir('writers/qrcode.eps'), $this->normalizeString($eps)); $this->tester->assertEquals(file_get_contents(codecept_data_dir('writers/qrcode.png')), $png); $this->tester->assertEquals(file_get_contents(codecept_data_dir('writers/qrcode.jpg')), $jpeg); $this->tester->assertEquals( $this->normalizeString(file_get_contents(codecept_data_dir('writers/qrcode.eps'))), - $eps + $this->normalizeString($eps) ); $this->tester->assertEquals( $this->normalizeString(file_get_contents(codecept_data_dir('writers/qrcode.svg'))), @@ -272,6 +273,34 @@ public function testScaleLogoSvg() ); } + public function testUnsetForegroundEndColor() + { + $qrCode = (new QrCode('2am Technologies')) + ->setForegroundEndColor(255, 255, 255); + + $color = $qrCode->getForegroundEndColor(); + + $this->assertIsArray($color); + $this->assertEquals($color['r'], 255); + $this->assertEquals($color['g'], 255); + $this->assertEquals($color['b'], 255); + + $qrCode->unsetForegroundEndColor(); + $this->assertNull($qrCode->getForegroundEndColor()); + } + + public function testGetPathIntensity() + { + $qrCode = (new QrCode('2am Technologies')); + $this->assertEquals($qrCode->getPathIntensity(), 1); + } + + public function testGetGradientType() + { + $qrCode = (new QrCode('2am Technologies')); + $this->assertEquals($qrCode->getGradientType(), GradientType::VERTICAL()); + } + protected function normalizeString($string) { return str_replace(