PHP Classes

File: src/Contracts/Customs/Writer/AbstractSvgWriter.php

Recommend this page to a friend!
  Packages of Amirreza Ebrahimi   HeroQR Powerful PHP QR Code Library to generate PNG, SVG, PDF, Logos Ready to Use with Laravel   src/Contracts/Customs/Writer/AbstractSvgWriter.php   Download  
File: src/Contracts/Customs/Writer/AbstractSvgWriter.php
Role: Class source
Content type: text/plain
Description: Class source
Class: HeroQR Powerful PHP QR Code Library to generate PNG, SVG, PDF, Logos Ready to Use with Laravel
Generate QR code images in several formats
Author: By
Last change:
Date: 22 days ago
Size: 4,720 bytes
 

Contents

Class file image Download
<?php

declare(strict_types=1);

namespace
HeroQR\Contracts\Customs\Writer;

use
Endroid\QrCode\{QrCodeInterface,
   
ImageData\LogoImageData,
   
Logo\LogoInterface,
   
Label\LabelInterface,
   
Writer\AbstractGdWriter,
   
Writer\WriterInterface,
   
Writer\Result\ResultInterface,
   
Writer\Result\SvgResult,
   
RoundBlockSizeMode};
use
HeroQR\{Contracts\Customs\Drawers\SvgDrawer,
   
Customs\ImageOverlay, Customs\ShapePaths};

/**
 * The AbstractWriter class is responsible for generating QR code images using the GD library
 * This class provides base functionality for creating QR code images with options like logo and label embedding
 * Subclasses should implement specific logic for rendering QR codes using the GD image processing library
 */
readonly abstract class AbstractSvgWriter extends AbstractGdWriter implements WriterInterface
{
    public const
WRITER_OPTION_FORCE_XLINK_HREF = 'force_xlink_href';
    protected
ImageOverlay $imageOverlay;
    protected
string $blockShape;

    public function
__construct($background, $overlay, $blockShape)
    {
       
$this->imageOverlay = new ImageOverlay($background, $overlay);
       
$this->blockShape = ShapePaths::getValueByKey($blockShape) ?? 'drawSquare';
    }

   
/**
     * Writes a QR code image with optional logo and label
     *
     * @param QrCodeInterface $qrCode The QR code to be generated
     * @param LogoInterface|null $logo The logo to be embedded in the QR code (optional)
     * @param LabelInterface|null $label The label to be added to the QR code (optional)
     * @param array $options Additional options for the QR code generation
     *
     * @return ResultInterface The result containing the generated QR code image
     *
     * @throws \Exception If the GD extension is not loaded
     */
   
public function write(
       
QrCodeInterface $qrCode,
        ?
LogoInterface $logo = null,
        ?
LabelInterface $label = null,
        array
$options = []
    ):
ResultInterface
   
{
        if (!
extension_loaded('gd')) {
            throw new \
Exception('Unable to generate image: please check if the GD extension is enabled and configured correctly');
        }

       
$matrix = $this->getMatrix($qrCode);
       
$baseBlockSize = (RoundBlockSizeMode::Margin === $qrCode->getRoundBlockSizeMode() ? 10 : intval($matrix->getBlockSize()));

       
$xml = SvgDrawer::drawQrCode($matrix, $qrCode, $logo, $this->imageOverlay, $this->blockShape, $baseBlockSize);

        if (empty(
$xml)) {
            throw new \
Exception('SvgDrawer::drawQrCode() returned empty XML');
        }

       
$result = new SvgResult($matrix, $xml, boolval($options['exclude_xml_declaration']));

        if (
$logo instanceof LogoInterface) {
           
$this->addLogoToResult($logo, $result, $options);
        }

        return
$result;
    }

   
/**
     * Adds a logo to the image, centered and with optional punch out background
     * Throws an exception if the logo is not in PNG format
     *
     * @param LogoInterface $logo The logo to add
     * @param SvgResult $result The image to add the logo to
     * @param array $options
     *
     * @return void
     * @throws \Exception
     */
   
private function addLogoToResult(
       
LogoInterface $logo,
       
SvgResult $result,
        array
$options
   
): void
   
{
        if (
$logo->getPunchoutBackground()) {
            throw new \
Exception('The SVG writer does not support logo punchout background');
        }

       
$logoImageData = LogoImageData::createForLogo($logo);

        if (!isset(
$options[self::WRITER_OPTION_FORCE_XLINK_HREF])) {
           
$options[self::WRITER_OPTION_FORCE_XLINK_HREF] = false;
        }

       
$xml = $result->getXml();

       
/** @var \SimpleXMLElement $xmlAttributes */
       
$xmlAttributes = $xml->attributes();

       
$x = intval($xmlAttributes->width) / 2 - $logoImageData->getWidth() / 2;
       
$y = intval($xmlAttributes->height) / 2 - $logoImageData->getHeight() / 2;

       
$imageDefinition = $xml->addChild('image');
       
$imageDefinition->addAttribute('x', strval($x));
       
$imageDefinition->addAttribute('y', strval($y));
       
$imageDefinition->addAttribute('width', strval($logoImageData->getWidth()));
       
$imageDefinition->addAttribute('height', strval($logoImageData->getHeight()));
       
$imageDefinition->addAttribute('preserveAspectRatio', 'none');

        if (
$options[self::WRITER_OPTION_FORCE_XLINK_HREF]) {
           
$imageDefinition->addAttribute('xlink:href', $logoImageData->createDataUri(), 'http://www.w3.org/1999/xlink');
        } else {
           
$imageDefinition->addAttribute('href', $logoImageData->createDataUri());
        }
    }
}