PDF converter
* distributed under the OSL-3.0 License
*
* @package Html2pdf
* @author Laurent MINGUET
* @copyright 2017 Laurent MINGUET
*/
namespace Spipu\Html2Pdf;
use Spipu\Html2Pdf\Exception\HtmlParsingException;
/**
* Class SvgDrawer
*/
class SvgDrawer
{
/**
* @var MyPdf
*/
private $pdf;
/**
* @var array
*/
private $properties;
/**
* @var CssConverter
*/
private $cssConverter;
/**
* SvgDrawer constructor.
*
* @param MyPdf $pdf
* @param CssConverter $cssConverter
*/
public function __construct(
MyPdf $pdf,
CssConverter $cssConverter
) {
$this->pdf = $pdf;
$this->cssConverter = $cssConverter;
}
/**
* Start Drawing
*
* @param array $properties
* @throws HtmlParsingException
*/
public function startDrawing($properties)
{
if ($this->isDrawing()) {
$e = new HtmlParsingException('We are already in a draw tag');
$e->setInvalidTag('draw');
throw $e;
}
$this->properties = $properties;
// init the translate matrix : (0,0) => (x, y)
$this->pdf->doTransform(array(1,0,0,1,$this->getProperty('x'),$this->getProperty('y')));
$this->pdf->setAlpha(1.);
}
/**
* Stop Drawing
*/
public function stopDrawing()
{
$this->properties = null;
$this->pdf->setAlpha(1.);
$this->pdf->undoTransform();
$this->pdf->clippingPathStop();
}
/**
* Are we drawing ?
*
* @return bool
*/
public function isDrawing()
{
return is_array($this->properties);
}
/**
* Get the property
*
* @param string $key
* @return mixed
*/
public function getProperty($key)
{
return $this->properties[$key];
}
/**
* prepare a transform matrix
*
* @param string $transform
* @return array
*/
public function prepareTransform($transform)
{
// it can not be empty
if (!$transform) {
return null;
}
// sections must be like scale(...)
if (!preg_match_all('/([a-z]+)\(([^\)]*)\)/isU', $transform, $match)) {
return null;
}
// prepare the list of the actions
$actions = array();
// for actions
$amountMatches = count($match[0]);
for ($k=0; $k < $amountMatches; $k++) {
// get the name of the action
$name = strtolower($match[1][$k]);
// get the parameters of the action
$values = [];
$string = trim($match[2][$k]);
if ($string !== '') {
$values = explode(',', $string);
}
foreach ($values as $key => $value) {
$value = trim($value);
if ($value === '') {
unset($values[$key]);
continue;
}
$values[$key] = $value;
}
// prepare the matrix, depending on the action
switch ($name) {
case 'scale':
if (!array_key_exists(0, $values)) {
$values[0] = 1.;
}
if (!array_key_exists(1, $values)) {
$values[1] = $values[0];
}
$values[0] = floatval($values[0]);
$values[1] = floatval($values[1]);
$actions[] = array($values[0],0.,0.,$values[1],0.,0.);
break;
case 'translate':
if (!array_key_exists(0, $values)) {
$values[0] = 0.;
}
if (!array_key_exists(1, $values)) {
$values[1] = 0.;
}
$values[0] = $this->cssConverter->convertToMM($values[0], $this->getProperty('w'));
$values[1] = $this->cssConverter->convertToMM($values[1], $this->getProperty('h'));
$actions[] = array(1.,0.,0.,1.,$values[0],$values[1]);
break;
case 'rotate':
if (!array_key_exists(0, $values)) {
$values[0] = 0.;
}
if (!array_key_exists(1, $values)) {
$values[1] = 0.;
}
if (!array_key_exists(2, $values)) {
$values[2] = 0.;
}
$values[0] = $values[0]*M_PI/180.;
$values[1] = $this->cssConverter->convertToMM($values[1], $this->getProperty('w'));
$values[2] = $this->cssConverter->convertToMM($values[2], $this->getProperty('h'));
if ($values[1] || $values[2]) {
$actions[] = array(1.,0.,0.,1.,-$values[1],-$values[2]);
}
$actions[] = array(cos($values[0]),sin($values[0]),-sin($values[0]),cos($values[0]),0.,0.);
if ($values[1] || $values[2]) {
$actions[] = array(1.,0.,0.,1.,$values[1],$values[2]);
}
break;
case 'skewx':
if (!array_key_exists(0, $values)) {
$values[0] = 0.;
}
$values[0] = $values[0]*M_PI/180.;
$actions[] = array(1.,0.,tan($values[0]),1.,0.,0.);
break;
case 'skewy':
if (!array_key_exists(0, $values)) {
$values[0] = 0.;
}
$values[0] = $values[0]*M_PI/180.;
$actions[] = array(1.,tan($values[0]),0.,1.,0.,0.);
break;
case 'matrix':
if (!array_key_exists(0, $values)) {
$values[0] = 0.;
}
if (!array_key_exists(1, $values)) {
$values[1] = 0.;
}
if (!array_key_exists(2, $values)) {
$values[2] = 0.;
}
if (!array_key_exists(3, $values)) {
$values[3] = 0.;
}
if (!array_key_exists(4, $values)) {
$values[4] = 0.;
}
if (!array_key_exists(5, $values)) {
$values[5] = 0.;
}
$values[0] = floatval($values[0]);
$values[1] = floatval($values[1]);
$values[2] = floatval($values[2]);
$values[3] = floatval($values[3]);
$values[4] = $this->cssConverter->convertToMM($values[4], $this->getProperty('w'));
$values[5] = $this->cssConverter->convertToMM($values[5], $this->getProperty('h'));
$actions[] = $values;
break;
}
}
// if there are no actions => return
if (!$actions) {
return null;
}
// get the first matrix
$m = $actions[0];
unset($actions[0]);
// foreach matrix => multiply to the last matrix
foreach ($actions as $n) {
$m = array(
$m[0]*$n[0]+$m[2]*$n[1],
$m[1]*$n[0]+$m[3]*$n[1],
$m[0]*$n[2]+$m[2]*$n[3],
$m[1]*$n[2]+$m[3]*$n[3],
$m[0]*$n[4]+$m[2]*$n[5]+$m[4],
$m[1]*$n[4]+$m[3]*$n[5]+$m[5]
);
}
// return the matrix
return $m;
}
}