src/SVG.php
<?php
namespace SVG;
use SVG\Fonts\FontRegistry;
use SVG\Nodes\Structures\SVGDocumentFragment;
use SVG\Rasterization\SVGRasterizer;
use SVG\Reading\SVGReader;
use SVG\Writing\SVGWriter;
/**
* This is the main class for any SVG image, as it hosts the document root and
* offers conversion methods.
*/
class SVG
{
/**
* @var SVGReader $reader The singleton reader used by this class.
*/
private static $reader;
private static $fontRegistry;
/**
* @var SVGDocumentFragment $document This image's root `svg` node/tag.
*/
private SVGDocumentFragment $document;
/**
* @param mixed $width The image's width (any CSS length).
* @param mixed $height The image's height (any CSS length).
*/
public function __construct($width = null, $height = null)
{
$this->document = new SVGDocumentFragment($width, $height);
}
/**
* @return SVGDocumentFragment The document/root node of this image.
*/
public function getDocument(): SVGDocumentFragment
{
return $this->document;
}
/**
* Converts this image into a rasterized GD resource of the given size.
*
* The resulting image resource supports transparency and represents the
* SVG as accurately as possible (with PHP's limited imaging functions).
* Note that, since images in SVG have an innate size, the given size only
* scales the output canvas and does not influence element positions.
*
* @param int $width The target canvas's width, in pixels.
* @param int $height The target canvas's height, in pixels.
* @param string|null $background The background color (hex/rgb[a]/hsl[a]/...).
*
* @return resource The rasterized image as a GD resource (with alpha).
*/
public function toRasterImage(int $width, int $height, ?string $background = null)
{
$docWidth = $this->document->getWidth();
$docHeight = $this->document->getHeight();
$viewBox = $this->document->getViewBox();
$rasterizer = new SVGRasterizer($docWidth, $docHeight, $viewBox, $width, $height, $background);
$rasterizer->setFontRegistry(self::getFontRegistry());
$this->document->rasterize($rasterizer);
return $rasterizer->finish();
}
/**
* @see SVG::toXMLString() For the implementation (this is a wrapper).
*/
public function __toString(): string
{
return $this->toXMLString();
}
/**
* Converts this image's document tree into an XML source code string.
*
* Note that an image parsed from an XML string might not have the exact
* same XML string generated by this method, since the output is optimized
* and formatted according to specific rules.
*
* @param bool $standalone optional, false omits the leading <?xml tag
*
* @return string This image's document tree as an XML string.
*/
public function toXMLString(bool $standalone = true): string
{
$writer = new SVGWriter($standalone);
$writer->writeNode($this->document);
return $writer->getString();
}
/**
* Parses the given XML string into an instance of this class.
*
* @param string $string The XML string to parse.
*
* @return SVG A new image, with the nodes parsed from the XML.
*/
public static function fromString($string): ?SVG
{
return self::getReader()->parseString($string);
}
/**
* Reads the file at the given path as an XML string, and then parses it
* into an instance of this class.
*
* @param string $file The path to the file to parse.
*
* @return SVG A new image, with the nodes parsed from the XML.
*/
public static function fromFile(string $file): ?SVG
{
return self::getReader()->parseFile($file);
}
/**
* @return SVGReader The singleton reader shared across all instances.
*/
private static function getReader(): SVGReader
{
if (!isset(self::$reader)) {
self::$reader = new SVGReader();
}
return self::$reader;
}
/**
* @return FontRegistry The singleton font registry.
*/
private static function getFontRegistry(): FontRegistry
{
if (!isset(self::$fontRegistry)) {
self::$fontRegistry = new FontRegistry();
}
return self::$fontRegistry;
}
/**
* Register a font file to be used when rasterizing text.
*
* @param string $path The path to the font file.
* @return void
*/
public static function addFont(string $path): void
{
self::getFontRegistry()->addFont($path);
}
}