| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- <?php
- namespace SimpleSoftwareIO\QrCode;
- use BaconQrCode\Common\ErrorCorrectionLevel;
- use BaconQrCode\Encoder\Encoder;
- use BaconQrCode\Exception\WriterException;
- use BaconQrCode\Renderer\Color\Alpha;
- use BaconQrCode\Renderer\Color\ColorInterface;
- use BaconQrCode\Renderer\Color\Rgb;
- use BaconQrCode\Renderer\Eye\EyeInterface;
- use BaconQrCode\Renderer\Eye\ModuleEye;
- use BaconQrCode\Renderer\Eye\SimpleCircleEye;
- use BaconQrCode\Renderer\Eye\SquareEye;
- use BaconQrCode\Renderer\Image\EpsImageBackEnd;
- use BaconQrCode\Renderer\Image\ImageBackEndInterface;
- use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
- use BaconQrCode\Renderer\Image\SvgImageBackEnd;
- use BaconQrCode\Renderer\ImageRenderer;
- use BaconQrCode\Renderer\Module\DotsModule;
- use BaconQrCode\Renderer\Module\ModuleInterface;
- use BaconQrCode\Renderer\Module\RoundnessModule;
- use BaconQrCode\Renderer\Module\SquareModule;
- use BaconQrCode\Renderer\RendererStyle\EyeFill;
- use BaconQrCode\Renderer\RendererStyle\Fill;
- use BaconQrCode\Renderer\RendererStyle\Gradient;
- use BaconQrCode\Renderer\RendererStyle\GradientType;
- use BaconQrCode\Renderer\RendererStyle\RendererStyle;
- use BaconQrCode\Writer;
- use BadMethodCallException;
- use InvalidArgumentException;
- use SimpleSoftwareIO\QrCode\DataTypes\DataTypeInterface;
- class Generator
- {
- /**
- * Holds the selected formatter.
- *
- * @var string
- */
- protected $format = 'svg';
- /**
- * Holds the size of the QrCode in pixels.
- *
- * @var int
- */
- protected $pixels = 100;
- /**
- * Holds the margin size of the QrCode.
- *
- * @var int
- */
- protected $margin = 0;
- /**
- * Holds the selected error correction.
- * L: 7% loss.
- * M: 15% loss.
- * Q: 25% loss.
- * H: 30% loss.
- *
- * @var string|null
- */
- protected $errorCorrection = null;
- /**
- * Holds the selected encoder. Possible values are
- * ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6,
- * ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-11,
- * ISO-8859-12, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16,
- * SHIFT-JIS, WINDOWS-1250, WINDOWS-1251, WINDOWS-1252, WINDOWS-1256,
- * UTF-16BE, UTF-8, ASCII, GBK, EUC-KR.
- *
- * @var string
- */
- protected $encoding = Encoder::DEFAULT_BYTE_MODE_ECODING;
- /**
- * The style of the blocks within the QrCode.
- * Possible values are square, dot, and round.
- *
- * @var string
- */
- protected $style = 'square';
- /**
- * The size of the selected style between 0 and 1.
- * This only applies to dot and round.
- *
- * @var float|null
- */
- protected $styleSize = null;
- /**
- * The style to apply to the eye.
- * Possible values are circle and square.
- *
- * @var string|null
- */
- protected $eyeStyle = null;
- /**
- * The foreground color of the QrCode.
- *
- * @var ColorInterface|null
- */
- protected $color = null;
- /**
- * The background color of the QrCode.
- *
- * @var ColorInterface|null
- */
- protected $backgroundColor = null;
- /**
- * An array that holds EyeFills of the color of the eyes.
- *
- * @var array
- */
- protected $eyeColors = [];
- /**
- * The gradient to apply to the QrCode.
- *
- * @var Gradient
- */
- protected $gradient;
- /**
- * Holds an image string that will be merged with the QrCode.
- *
- * @var null|string
- */
- protected $imageMerge = null;
- /**
- * The percentage that a merged image should take over the source image.
- *
- * @var float
- */
- protected $imagePercentage = .2;
- /**
- * Creates a new datatype object and then generates a QrCode.
- *
- * @param $method
- * @param array $arguments
- */
- public function __call($method, array $arguments)
- {
- $dataType = $this->createClass($method);
- $dataType->create($arguments);
- return $this->generate(strval($dataType));
- }
- /**
- * Generates the QrCode.
- *
- * @param string $text
- * @param string|null $filename
- * @return void|Illuminate\Support\HtmlString|string
- * @throws WriterException
- * @throws InvalidArgumentException
- */
- public function generate(string $text, string $filename = null)
- {
- $qrCode = $this->getWriter($this->getRenderer())->writeString($text, $this->encoding, $this->errorCorrection);
- if ($this->imageMerge !== null && $this->format === 'png') {
- $merger = new ImageMerge(new Image($qrCode), new Image($this->imageMerge));
- $qrCode = $merger->merge($this->imagePercentage);
- }
- if ($filename) {
- file_put_contents($filename, $qrCode);
- return;
- }
- if (class_exists(\Illuminate\Support\HtmlString::class)) {
- return new \Illuminate\Support\HtmlString($qrCode);
- }
- return $qrCode;
- }
- /**
- * Merges an image over the QrCode.
- *
- * @param string $filepath
- * @param float $percentage
- * @param SimpleSoftwareIO\QrCode\boolean|bool $absolute
- * @return Generator
- */
- public function merge(string $filepath, float $percentage = .2, bool $absolute = false): self
- {
- if (function_exists('base_path') && ! $absolute) {
- $filepath = base_path().$filepath;
- }
- $this->imageMerge = file_get_contents($filepath);
- $this->imagePercentage = $percentage;
- return $this;
- }
- /**
- * Merges an image string with the center of the QrCode.
- *
- * @param string $content
- * @param float $percentage
- * @return Generator
- */
- public function mergeString(string $content, float $percentage = .2): self
- {
- $this->imageMerge = $content;
- $this->imagePercentage = $percentage;
- return $this;
- }
- /**
- * Sets the size of the QrCode.
- *
- * @param int $pixels
- * @return Generator
- */
- public function size(int $pixels): self
- {
- $this->pixels = $pixels;
- return $this;
- }
- /**
- * Sets the format of the QrCode.
- *
- * @param string $format
- * @return Generator
- * @throws InvalidArgumentException
- */
- public function format(string $format): self
- {
- if (! in_array($format, ['svg', 'eps', 'png'])) {
- throw new InvalidArgumentException("\$format must be svg, eps, or png. {$format} is not a valid.");
- }
- $this->format = $format;
- return $this;
- }
- /**
- * Sets the foreground color of the QrCode.
- *
- * @param int $red
- * @param int $green
- * @param int $blue
- * @param null|int $alpha
- * @return Generator
- */
- public function color(int $red, int $green, int $blue, ?int $alpha = null): self
- {
- $this->color = $this->createColor($red, $green, $blue, $alpha);
- return $this;
- }
- /**
- * Sets the background color of the QrCode.
- *
- * @param int $red
- * @param int $green
- * @param int $blue
- * @param null|int $alpha
- * @return Generator
- */
- public function backgroundColor(int $red, int $green, int $blue, ?int $alpha = null): self
- {
- $this->backgroundColor = $this->createColor($red, $green, $blue, $alpha);
- return $this;
- }
- /**
- * Sets the eye color for the provided eye index.
- *
- * @param int $eyeNumber
- * @param int $innerRed
- * @param int $innerGreen
- * @param int $innerBlue
- * @param int $outterRed
- * @param int $outterGreen
- * @param int $outterBlue
- * @return Generator
- * @throws InvalidArgumentException
- */
- public function eyeColor(int $eyeNumber, int $innerRed, int $innerGreen, int $innerBlue, int $outterRed = 0, int $outterGreen = 0, int $outterBlue = 0): self
- {
- if ($eyeNumber < 0 || $eyeNumber > 2) {
- throw new InvalidArgumentException("\$eyeNumber must be 0, 1, or 2. {$eyeNumber} is not valid.");
- }
- $this->eyeColors[$eyeNumber] = new EyeFill(
- $this->createColor($innerRed, $innerGreen, $innerBlue),
- $this->createColor($outterRed, $outterGreen, $outterBlue)
- );
- return $this;
- }
- public function gradient($startRed, $startGreen, $startBlue, $endRed, $endGreen, $endBlue, string $type): self
- {
- $type = strtoupper($type);
- $this->gradient = new Gradient(
- $this->createColor($startRed, $startGreen, $startBlue),
- $this->createColor($endRed, $endGreen, $endBlue),
- GradientType::$type()
- );
- return $this;
- }
- /**
- * Sets the eye style.
- *
- * @param string $style
- * @return Generator
- * @throws InvalidArgumentException
- */
- public function eye(string $style): self
- {
- if (! in_array($style, ['square', 'circle'])) {
- throw new InvalidArgumentException("\$style must be square or circle. {$style} is not a valid eye style.");
- }
- $this->eyeStyle = $style;
- return $this;
- }
- /**
- * Sets the style of the blocks for the QrCode.
- *
- * @param string $style
- * @param float $size
- * @return Generator
- * @throws InvalidArgumentException
- */
- public function style(string $style, float $size = 0.5): self
- {
- if (! in_array($style, ['square', 'dot', 'round'])) {
- throw new InvalidArgumentException("\$style must be square, dot, or round. {$style} is not a valid.");
- }
- if ($size < 0 || $size >= 1) {
- throw new InvalidArgumentException("\$size must be between 0 and 1. {$size} is not valid.");
- }
- $this->style = $style;
- $this->styleSize = $size;
- return $this;
- }
- /**
- * Sets the encoding for the QrCode.
- * Possible values are
- * ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6,
- * ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-11,
- * ISO-8859-12, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16,
- * SHIFT-JIS, WINDOWS-1250, WINDOWS-1251, WINDOWS-1252, WINDOWS-1256,
- * UTF-16BE, UTF-8, ASCII, GBK, EUC-KR.
- *
- * @param string $encoding
- * @return Generator
- */
- public function encoding(string $encoding): self
- {
- $this->encoding = strtoupper($encoding);
- return $this;
- }
- /**
- * Sets the error correction for the QrCode.
- * L: 7% loss.
- * M: 15% loss.
- * Q: 25% loss.
- * H: 30% loss.
- *
- * @param string $errorCorrection
- * @return Generator
- */
- public function errorCorrection(string $errorCorrection): self
- {
- $errorCorrection = strtoupper($errorCorrection);
- $this->errorCorrection = ErrorCorrectionLevel::$errorCorrection();
- return $this;
- }
- /**
- * Sets the margin of the QrCode.
- *
- * @param int $margin
- * @return Generator
- */
- public function margin(int $margin): self
- {
- $this->margin = $margin;
- return $this;
- }
- /**
- * Fetches the Writer.
- *
- * @param ImageRenderer $renderer
- * @return Writer
- */
- public function getWriter(ImageRenderer $renderer): Writer
- {
- return new Writer($renderer);
- }
- /**
- * Fetches the Image Renderer.
- *
- * @return ImageRenderer
- */
- public function getRenderer(): ImageRenderer
- {
- $renderer = new ImageRenderer(
- $this->getRendererStyle(),
- $this->getFormatter()
- );
- return $renderer;
- }
- /**
- * Returns the Renderer Style.
- *
- * @return RendererStyle
- */
- public function getRendererStyle(): RendererStyle
- {
- return new RendererStyle($this->pixels, $this->margin, $this->getModule(), $this->getEye(), $this->getFill());
- }
- /**
- * Fetches the formatter.
- *
- * @return ImageBackEndInterface
- */
- public function getFormatter(): ImageBackEndInterface
- {
- if ($this->format === 'png') {
- return new ImagickImageBackEnd('png');
- }
- if ($this->format === 'eps') {
- return new EpsImageBackEnd;
- }
- return new SvgImageBackEnd;
- }
- /**
- * Fetches the module.
- *
- * @return ModuleInterface
- */
- public function getModule(): ModuleInterface
- {
- if ($this->style === 'dot') {
- return new DotsModule($this->styleSize);
- }
- if ($this->style === 'round') {
- return new RoundnessModule($this->styleSize);
- }
- return SquareModule::instance();
- }
- /**
- * Fetches the eye style.
- *
- * @return EyeInterface
- */
- public function getEye(): EyeInterface
- {
- if ($this->eyeStyle === 'square') {
- return SquareEye::instance();
- }
- if ($this->eyeStyle === 'circle') {
- return SimpleCircleEye::instance();
- }
- return new ModuleEye($this->getModule());
- }
- /**
- * Fetches the color fill.
- *
- * @return Fill
- */
- public function getFill(): Fill
- {
- $foregroundColor = $this->color ?? new Rgb(0, 0, 0);
- $backgroundColor = $this->backgroundColor ?? new Rgb(255, 255, 255);
- $eye0 = $this->eyeColors[0] ?? EyeFill::inherit();
- $eye1 = $this->eyeColors[1] ?? EyeFill::inherit();
- $eye2 = $this->eyeColors[2] ?? EyeFill::inherit();
- if ($this->gradient) {
- return Fill::withForegroundGradient($backgroundColor, $this->gradient, $eye0, $eye1, $eye2);
- }
- return Fill::withForegroundColor($backgroundColor, $foregroundColor, $eye0, $eye1, $eye2);
- }
- /**
- * Creates a RGB or Alpha channel color.
- * @param int $red
- * @param int $green
- * @param int $blue
- * @param null|int $alpha
- * @return ColorInterface
- */
- public function createColor(int $red, int $green, int $blue, ?int $alpha = null): ColorInterface
- {
- if (is_null($alpha)) {
- return new Rgb($red, $green, $blue);
- }
- return new Alpha($alpha, new Rgb($red, $green, $blue));
- }
- /**
- * Creates a new DataType class dynamically.
- *
- * @param string $method
- * @return DataTypeInterface
- */
- protected function createClass(string $method): DataTypeInterface
- {
- $class = $this->formatClass($method);
- if (! class_exists($class)) {
- throw new BadMethodCallException();
- }
- return new $class();
- }
- /**
- * Formats the method name correctly.
- *
- * @param $method
- * @return string
- */
- protected function formatClass(string $method): string
- {
- $method = ucfirst($method);
- $class = "SimpleSoftwareIO\QrCode\DataTypes\\".$method;
- return $class;
- }
- }
|