File: /home/boxelikax/public_html/demoltec.com/Svg.zip
PK C=]M�(8 8 Gradient/Stop.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Gradient;
class Stop
{
public $offset;
public $color;
public $opacity = 1.0;
}
PK C=]�5^M ^M Tag/Path.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Surface\SurfaceInterface;
class Path extends Shape
{
// kindly borrowed from fabric.util.parsePath.
/* @see https://github.com/fabricjs/fabric.js/blob/master/src/util/path.js#L664 */
const NUMBER_PATTERN = '([-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?)\s*';
const COMMA_PATTERN = '(?:\s+,?\s*|,\s*)?';
const FLAG_PATTERN = '([01])';
const ARC_REGEXP = '/'
. self::NUMBER_PATTERN
. self::COMMA_PATTERN
. self::NUMBER_PATTERN
. self::COMMA_PATTERN
. self::NUMBER_PATTERN
. self::COMMA_PATTERN
. self::FLAG_PATTERN
. self::COMMA_PATTERN
. self::FLAG_PATTERN
. self::COMMA_PATTERN
. self::NUMBER_PATTERN
. self::COMMA_PATTERN
. self::NUMBER_PATTERN
. '/';
static $commandLengths = array(
'm' => 2,
'l' => 2,
'h' => 1,
'v' => 1,
'c' => 6,
's' => 4,
'q' => 4,
't' => 2,
'a' => 7,
);
static $repeatedCommands = array(
'm' => 'l',
'M' => 'L',
);
public static function parse(string $commandSequence): array
{
$commands = array();
preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $commandSequence, $commands, PREG_SET_ORDER);
$path = array();
foreach ($commands as $c) {
if (count($c) == 3) {
$commandLower = strtolower($c[1]);
// arcs have special flags that apparently don't require spaces.
if ($commandLower === 'a' && preg_match_all(static::ARC_REGEXP, $c[2], $matches, PREG_PATTERN_ORDER)) {
$numberOfMatches = count($matches[0]);
for ($k = 0; $k < $numberOfMatches; ++$k) {
$path[] = [
$c[1],
$matches[1][$k],
$matches[2][$k],
$matches[3][$k],
$matches[4][$k],
$matches[5][$k],
$matches[6][$k],
$matches[7][$k],
];
}
continue;
}
$arguments = array();
preg_match_all('/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/i', $c[2], $arguments, PREG_PATTERN_ORDER);
$item = $arguments[0];
if (
isset(self::$commandLengths[$commandLower]) &&
($commandLength = self::$commandLengths[$commandLower]) &&
count($item) > $commandLength
) {
$repeatedCommand = isset(self::$repeatedCommands[$c[1]]) ? self::$repeatedCommands[$c[1]] : $c[1];
$command = $c[1];
for ($k = 0, $klen = count($item); $k < $klen; $k += $commandLength) {
$_item = array_slice($item, $k, $k + $commandLength);
array_unshift($_item, $command);
$path[] = $_item;
$command = $repeatedCommand;
}
} else {
array_unshift($item, $c[1]);
$path[] = $item;
}
} else {
$item = array($c[1]);
$path[] = $item;
}
}
return $path;
}
public function start($attributes)
{
if (!isset($attributes['d'])) {
$this->hasShape = false;
return;
}
$path = static::parse($attributes['d']);
$surface = $this->document->getSurface();
// From https://github.com/kangax/fabric.js/blob/master/src/shapes/path.class.js
$current = null; // current instruction
$previous = null;
$subpathStartX = 0;
$subpathStartY = 0;
$x = 0; // current x
$y = 0; // current y
$controlX = 0; // current control point x
$controlY = 0; // current control point y
$tempX = null;
$tempY = null;
$tempControlX = null;
$tempControlY = null;
$l = 0; //-((this.width / 2) + $this.pathOffset.x),
$t = 0; //-((this.height / 2) + $this.pathOffset.y),
foreach ($path as $current) {
switch ($current[0]) { // first letter
case 'l': // lineto, relative
$x += $current[1];
$y += $current[2];
$surface->lineTo($x + $l, $y + $t);
break;
case 'L': // lineto, absolute
$x = $current[1];
$y = $current[2];
$surface->lineTo($x + $l, $y + $t);
break;
case 'h': // horizontal lineto, relative
$x += $current[1];
$surface->lineTo($x + $l, $y + $t);
break;
case 'H': // horizontal lineto, absolute
$x = $current[1];
$surface->lineTo($x + $l, $y + $t);
break;
case 'v': // vertical lineto, relative
$y += $current[1];
$surface->lineTo($x + $l, $y + $t);
break;
case 'V': // verical lineto, absolute
$y = $current[1];
$surface->lineTo($x + $l, $y + $t);
break;
case 'm': // moveTo, relative
$x += $current[1];
$y += $current[2];
$subpathStartX = $x;
$subpathStartY = $y;
$surface->moveTo($x + $l, $y + $t);
break;
case 'M': // moveTo, absolute
$x = $current[1];
$y = $current[2];
$subpathStartX = $x;
$subpathStartY = $y;
$surface->moveTo($x + $l, $y + $t);
break;
case 'c': // bezierCurveTo, relative
$tempX = $x + $current[5];
$tempY = $y + $current[6];
$controlX = $x + $current[3];
$controlY = $y + $current[4];
$surface->bezierCurveTo(
$x + $current[1] + $l, // x1
$y + $current[2] + $t, // y1
$controlX + $l, // x2
$controlY + $t, // y2
$tempX + $l,
$tempY + $t
);
$x = $tempX;
$y = $tempY;
break;
case 'C': // bezierCurveTo, absolute
$x = $current[5];
$y = $current[6];
$controlX = $current[3];
$controlY = $current[4];
$surface->bezierCurveTo(
$current[1] + $l,
$current[2] + $t,
$controlX + $l,
$controlY + $t,
$x + $l,
$y + $t
);
break;
case 's': // shorthand cubic bezierCurveTo, relative
// transform to absolute x,y
$tempX = $x + $current[3];
$tempY = $y + $current[4];
if (!preg_match('/[CcSs]/', $previous[0])) {
// If there is no previous command or if the previous command was not a C, c, S, or s,
// the control point is coincident with the current point
$controlX = $x;
$controlY = $y;
} else {
// calculate reflection of previous control points
$controlX = 2 * $x - $controlX;
$controlY = 2 * $y - $controlY;
}
$surface->bezierCurveTo(
$controlX + $l,
$controlY + $t,
$x + $current[1] + $l,
$y + $current[2] + $t,
$tempX + $l,
$tempY + $t
);
// set control point to 2nd one of this command
// "... the first control point is assumed to be
// the reflection of the second control point on
// the previous command relative to the current point."
$controlX = $x + $current[1];
$controlY = $y + $current[2];
$x = $tempX;
$y = $tempY;
break;
case 'S': // shorthand cubic bezierCurveTo, absolute
$tempX = $current[3];
$tempY = $current[4];
if (!preg_match('/[CcSs]/', $previous[0])) {
// If there is no previous command or if the previous command was not a C, c, S, or s,
// the control point is coincident with the current point
$controlX = $x;
$controlY = $y;
} else {
// calculate reflection of previous control points
$controlX = 2 * $x - $controlX;
$controlY = 2 * $y - $controlY;
}
$surface->bezierCurveTo(
$controlX + $l,
$controlY + $t,
$current[1] + $l,
$current[2] + $t,
$tempX + $l,
$tempY + $t
);
$x = $tempX;
$y = $tempY;
// set control point to 2nd one of this command
// "... the first control point is assumed to be
// the reflection of the second control point on
// the previous command relative to the current point."
$controlX = $current[1];
$controlY = $current[2];
break;
case 'q': // quadraticCurveTo, relative
// transform to absolute x,y
$tempX = $x + $current[3];
$tempY = $y + $current[4];
$controlX = $x + $current[1];
$controlY = $y + $current[2];
$surface->quadraticCurveTo(
$controlX + $l,
$controlY + $t,
$tempX + $l,
$tempY + $t
);
$x = $tempX;
$y = $tempY;
break;
case 'Q': // quadraticCurveTo, absolute
$tempX = $current[3];
$tempY = $current[4];
$surface->quadraticCurveTo(
$current[1] + $l,
$current[2] + $t,
$tempX + $l,
$tempY + $t
);
$x = $tempX;
$y = $tempY;
$controlX = $current[1];
$controlY = $current[2];
break;
case 't': // shorthand quadraticCurveTo, relative
// transform to absolute x,y
$tempX = $x + $current[1];
$tempY = $y + $current[2];
// calculate reflection of previous control points
if (preg_match('/[QqT]/', $previous[0])) {
$controlX = 2 * $x - $controlX;
$controlY = 2 * $y - $controlY;
} elseif ($previous[0] === 't') {
$controlX = 2 * $x - $tempControlX;
$controlY = 2 * $y - $tempControlY;
} else {
$controlX = $x;
$controlY = $y;
}
$tempControlX = $controlX;
$tempControlY = $controlY;
$surface->quadraticCurveTo(
$controlX + $l,
$controlY + $t,
$tempX + $l,
$tempY + $t
);
$x = $tempX;
$y = $tempY;
break;
case 'T':
$tempX = $current[1];
$tempY = $current[2];
// calculate reflection of previous control points
if (preg_match('/[QqTt]/', $previous[0])) {
$controlX = 2 * $x - $controlX;
$controlY = 2 * $y - $controlY;
} else {
$controlX = $x;
$controlY = $y;
}
$surface->quadraticCurveTo(
$controlX + $l,
$controlY + $t,
$tempX + $l,
$tempY + $t
);
$x = $tempX;
$y = $tempY;
break;
case 'a':
$this->drawArc(
$surface,
$x + $l,
$y + $t,
array(
$current[1],
$current[2],
$current[3],
$current[4],
$current[5],
$current[6] + $x + $l,
$current[7] + $y + $t
)
);
$x += $current[6];
$y += $current[7];
break;
case 'A':
// TODO: optimize this
$this->drawArc(
$surface,
$x + $l,
$y + $t,
array(
$current[1],
$current[2],
$current[3],
$current[4],
$current[5],
$current[6] + $l,
$current[7] + $t
)
);
$x = $current[6];
$y = $current[7];
break;
case 'z':
case 'Z':
$x = $subpathStartX;
$y = $subpathStartY;
$surface->closePath();
break;
}
$previous = $current;
}
}
function drawArc(SurfaceInterface $surface, $fx, $fy, $coords)
{
$rx = $coords[0];
$ry = $coords[1];
$rot = $coords[2];
$large = $coords[3];
$sweep = $coords[4];
$tx = $coords[5];
$ty = $coords[6];
$segs = array(
array(),
array(),
array(),
array(),
);
$toX = $tx - $fx;
$toY = $ty - $fy;
if ($toX + $toY === 0) {
return;
}
$segsNorm = $this->arcToSegments($toX, $toY, $rx, $ry, $large, $sweep, $rot);
for ($i = 0, $len = count($segsNorm); $i < $len; $i++) {
$segs[$i][0] = $segsNorm[$i][0] + $fx;
$segs[$i][1] = $segsNorm[$i][1] + $fy;
$segs[$i][2] = $segsNorm[$i][2] + $fx;
$segs[$i][3] = $segsNorm[$i][3] + $fy;
$segs[$i][4] = $segsNorm[$i][4] + $fx;
$segs[$i][5] = $segsNorm[$i][5] + $fy;
call_user_func_array(array($surface, "bezierCurveTo"), $segs[$i]);
}
}
function arcToSegments($toX, $toY, $rx, $ry, $large, $sweep, $rotateX)
{
$th = $rotateX * M_PI / 180;
$sinTh = sin($th);
$cosTh = cos($th);
$fromX = 0;
$fromY = 0;
$rx = abs($rx);
$ry = abs($ry);
$px = -$cosTh * $toX * 0.5 - $sinTh * $toY * 0.5;
$py = -$cosTh * $toY * 0.5 + $sinTh * $toX * 0.5;
$rx2 = $rx * $rx;
$ry2 = $ry * $ry;
$py2 = $py * $py;
$px2 = $px * $px;
$pl = $rx2 * $ry2 - $rx2 * $py2 - $ry2 * $px2;
$root = 0;
if ($pl < 0) {
$s = sqrt(1 - $pl / ($rx2 * $ry2));
$rx *= $s;
$ry *= $s;
} else {
$root = ($large == $sweep ? -1.0 : 1.0) * sqrt($pl / ($rx2 * $py2 + $ry2 * $px2));
}
$cx = $root * $rx * $py / $ry;
$cy = -$root * $ry * $px / $rx;
$cx1 = $cosTh * $cx - $sinTh * $cy + $toX * 0.5;
$cy1 = $sinTh * $cx + $cosTh * $cy + $toY * 0.5;
$mTheta = $this->calcVectorAngle(1, 0, ($px - $cx) / $rx, ($py - $cy) / $ry);
$dtheta = $this->calcVectorAngle(($px - $cx) / $rx, ($py - $cy) / $ry, (-$px - $cx) / $rx, (-$py - $cy) / $ry);
if ($sweep == 0 && $dtheta > 0) {
$dtheta -= 2 * M_PI;
} else {
if ($sweep == 1 && $dtheta < 0) {
$dtheta += 2 * M_PI;
}
}
// $Convert $into $cubic $bezier $segments <= 90deg
$segments = ceil(abs($dtheta / M_PI * 2));
$result = array();
$mDelta = $dtheta / $segments;
$mT = 8 / 3 * sin($mDelta / 4) * sin($mDelta / 4) / sin($mDelta / 2);
$th3 = $mTheta + $mDelta;
for ($i = 0; $i < $segments; $i++) {
$result[$i] = $this->segmentToBezier(
$mTheta,
$th3,
$cosTh,
$sinTh,
$rx,
$ry,
$cx1,
$cy1,
$mT,
$fromX,
$fromY
);
$fromX = $result[$i][4];
$fromY = $result[$i][5];
$mTheta = $th3;
$th3 += $mDelta;
}
return $result;
}
function segmentToBezier($th2, $th3, $cosTh, $sinTh, $rx, $ry, $cx1, $cy1, $mT, $fromX, $fromY)
{
$costh2 = cos($th2);
$sinth2 = sin($th2);
$costh3 = cos($th3);
$sinth3 = sin($th3);
$toX = $cosTh * $rx * $costh3 - $sinTh * $ry * $sinth3 + $cx1;
$toY = $sinTh * $rx * $costh3 + $cosTh * $ry * $sinth3 + $cy1;
$cp1X = $fromX + $mT * (-$cosTh * $rx * $sinth2 - $sinTh * $ry * $costh2);
$cp1Y = $fromY + $mT * (-$sinTh * $rx * $sinth2 + $cosTh * $ry * $costh2);
$cp2X = $toX + $mT * ($cosTh * $rx * $sinth3 + $sinTh * $ry * $costh3);
$cp2Y = $toY + $mT * ($sinTh * $rx * $sinth3 - $cosTh * $ry * $costh3);
return array(
$cp1X,
$cp1Y,
$cp2X,
$cp2Y,
$toX,
$toY
);
}
function calcVectorAngle($ux, $uy, $vx, $vy)
{
$ta = atan2($uy, $ux);
$tb = atan2($vy, $vx);
if ($tb >= $ta) {
return $tb - $ta;
} else {
return 2 * M_PI - ($ta - $tb);
}
}
}
PK C=]��z Tag/Anchor.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
class Anchor extends Group
{
}
PK C=]��V� � Tag/Polygon.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
class Polygon extends Shape
{
public function start($attributes)
{
$tmp = array();
preg_match_all('/([\-]*[0-9\.]+)/', $attributes['points'], $tmp, PREG_PATTERN_ORDER);
$points = $tmp[0];
$count = count($points);
if ($count < 4) {
// nothing to draw
return;
}
$surface = $this->document->getSurface();
list($x, $y) = $points;
$surface->moveTo($x, $y);
for ($i = 2; $i < $count; $i += 2) {
if ($i + 1 === $count) {
// invalid trailing point
continue;
}
$x = $points[$i];
$y = $points[$i + 1];
$surface->lineTo($x, $y);
}
$surface->closePath();
}
}
PK C=]~��X X Tag/Rect.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Style;
class Rect extends Shape
{
protected $x = 0;
protected $y = 0;
protected $width = 0;
protected $height = 0;
protected $rx = 0;
protected $ry = 0;
public function start($attributes)
{
$width = $this->document->getWidth();
$height = $this->document->getHeight();
if (isset($attributes['x'])) {
$this->x = $this->convertSize($attributes['x'], $width);
}
if (isset($attributes['y'])) {
$this->y = $this->convertSize($attributes['y'], $height);
}
if (isset($attributes['width'])) {
$this->width = $this->convertSize($attributes['width'], $width);
}
if (isset($attributes['height'])) {
$this->height = $this->convertSize($attributes['height'], $height);
}
if (isset($attributes['rx'])) {
$this->rx = $attributes['rx'];
}
if (isset($attributes['ry'])) {
$this->ry = $attributes['ry'];
}
$this->document->getSurface()->rect($this->x, $this->y, $this->width, $this->height, $this->rx, $this->ry);
}
}
PK C=]maQ� � Tag/Polyline.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
class Polyline extends Shape
{
public function start($attributes)
{
$tmp = array();
preg_match_all('/([\-]*[0-9\.]+)/', $attributes['points'], $tmp, PREG_PATTERN_ORDER);
$points = $tmp[0];
$count = count($points);
if ($count < 4) {
// nothing to draw
return;
}
$surface = $this->document->getSurface();
list($x, $y) = $points;
$surface->moveTo($x, $y);
for ($i = 2; $i < $count; $i += 2) {
if ($i + 1 === $count) {
// invalid trailing point
continue;
}
$x = $points[$i];
$y = $points[$i + 1];
$surface->lineTo($x, $y);
}
}
}
PK C=]3:�� � Tag/ClipPath.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Style;
class ClipPath extends AbstractTag
{
protected function before($attributes)
{
$surface = $this->document->getSurface();
$surface->save();
$style = $this->makeStyle($attributes);
$this->setStyle($style);
$surface->setStyle($style);
$this->applyTransform($attributes);
}
protected function after()
{
$this->document->getSurface()->restore();
}
}
PK C=]�i�m� � Tag/Circle.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Style;
class Circle extends Shape
{
protected $cx = 0;
protected $cy = 0;
protected $r;
public function start($attributes)
{
if (isset($attributes['cx'])) {
$width = $this->document->getWidth();
$this->cx = $this->convertSize($attributes['cx'], $width);
}
if (isset($attributes['cy'])) {
$height = $this->document->getHeight();
$this->cy = $this->convertSize($attributes['cy'], $height);
}
if (isset($attributes['r'])) {
$diagonal = $this->document->getDiagonal();
$this->r = $this->convertSize($attributes['r'], $diagonal);
}
$this->document->getSurface()->circle($this->cx, $this->cy, $this->r);
}
}
PK C=]�R��# #
Tag/Shape.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Style;
class Shape extends AbstractTag
{
protected function before($attributes)
{
$surface = $this->document->getSurface();
$surface->save();
$style = $this->makeStyle($attributes);
$this->setStyle($style);
$surface->setStyle($style);
$this->applyTransform($attributes);
}
protected function after()
{
$surface = $this->document->getSurface();
if ($this->hasShape) {
$style = $surface->getStyle();
$fill = $style->fill && is_array($style->fill);
$stroke = $style->stroke && is_array($style->stroke);
if ($fill) {
if ($stroke) {
$surface->fillStroke(false);
} else {
// if (is_string($style->fill)) {
// /** @var LinearGradient|RadialGradient $gradient */
// $gradient = $this->getDocument()->getDef($style->fill);
//
// var_dump($gradient->getStops());
// }
$surface->fill();
}
}
elseif ($stroke) {
$surface->stroke(false);
}
else {
$surface->endPath();
}
}
$surface->restore();
}
} PK C=]j]�8� � Tag/UseTag.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
class UseTag extends AbstractTag
{
protected $x = 0;
protected $y = 0;
protected $width;
protected $height;
/** @var AbstractTag */
protected $reference;
protected function before($attributes)
{
if (isset($attributes['x'])) {
$this->x = $attributes['x'];
}
if (isset($attributes['y'])) {
$this->y = $attributes['y'];
}
if (isset($attributes['width'])) {
$this->width = $attributes['width'];
}
if (isset($attributes['height'])) {
$this->height = $attributes['height'];
}
parent::before($attributes);
$document = $this->getDocument();
$link = $attributes["href"] ?? $attributes["xlink:href"];
$this->reference = $document->getDef($link);
if ($this->reference) {
$this->reference->before($attributes);
}
$surface = $document->getSurface();
$surface->save();
$surface->translate($this->x, $this->y);
}
protected function after() {
parent::after();
if ($this->reference) {
$this->reference->after();
}
$this->getDocument()->getSurface()->restore();
}
public function handle($attributes)
{
parent::handle($attributes);
if (!$this->reference) {
return;
}
$mergedAttributes = $this->reference->attributes;
$attributesToNotMerge = ['x', 'y', 'width', 'height'];
foreach ($attributes as $attrKey => $attrVal) {
if (!in_array($attrKey, $attributesToNotMerge) && !isset($mergedAttributes[$attrKey])) {
$mergedAttributes[$attrKey] = $attrVal;
}
}
$this->reference->handle($mergedAttributes);
foreach ($this->reference->children as $_child) {
$_attributes = array_merge($_child->attributes, $mergedAttributes);
$_child->handle($_attributes);
}
}
public function handleEnd()
{
parent::handleEnd();
if (!$this->reference) {
return;
}
$this->reference->handleEnd();
foreach ($this->reference->children as $_child) {
$_child->handleEnd();
}
}
}
PK C=]�v��| | Tag/Ellipse.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Style;
class Ellipse extends Shape
{
protected $cx = 0;
protected $cy = 0;
protected $rx = 0;
protected $ry = 0;
public function start($attributes)
{
parent::start($attributes);
$width = $this->document->getWidth();
$height = $this->document->getHeight();
if (isset($attributes['cx'])) {
$this->cx = $this->convertSize($attributes['cx'], $width);
}
if (isset($attributes['cy'])) {
$this->cy = $this->convertSize($attributes['cy'], $height);
}
if (isset($attributes['rx'])) {
$this->rx = $this->convertSize($attributes['rx'], $width);
}
if (isset($attributes['ry'])) {
$this->ry = $this->convertSize($attributes['ry'], $height);
}
$this->document->getSurface()->ellipse($this->cx, $this->cy, $this->rx, $this->ry, 0, 0, 360, false);
}
}
PK C=]*�T� �
Tag/Group.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Style;
class Group extends AbstractTag
{
protected function before($attributes)
{
$surface = $this->document->getSurface();
$surface->save();
$style = $this->makeStyle($attributes);
$this->setStyle($style);
$surface->setStyle($style);
$this->applyTransform($attributes);
}
protected function after()
{
$this->document->getSurface()->restore();
}
}
PK C=]�㴵� � Tag/Text.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Style;
class Text extends Shape
{
protected $x = 0;
protected $y = 0;
protected $text = "";
public function start($attributes)
{
$height = $this->document->getHeight();
$this->y = $height;
if (isset($attributes['x'])) {
$width = $this->document->getWidth();
$this->x = $this->convertSize($attributes['x'], $width);
}
if (isset($attributes['y'])) {
$this->y = $height - $this->convertSize($attributes['y'], $height);
}
$this->document->getSurface()->transform(1, 0, 0, -1, 0, $height);
}
public function end()
{
$surface = $this->document->getSurface();
$x = $this->x;
$y = $this->y;
$style = $surface->getStyle();
$surface->setFont($style->fontFamily, $style->fontStyle, $style->fontWeight);
switch ($style->textAnchor) {
case "middle":
$width = $surface->measureText($this->text);
$x -= $width / 2;
break;
case "end":
$width = $surface->measureText($this->text);
$x -= $width;
break;
}
$surface->fillText($this->getText(), $x, $y);
}
protected function after()
{
$this->document->getSurface()->restore();
}
public function appendText($text)
{
$this->text .= $text;
}
public function getText()
{
return trim($this->text);
}
}
PK C=]g��> Tag/LinearGradient.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Gradient;
use Svg\Style;
class LinearGradient extends AbstractTag
{
protected $x1;
protected $y1;
protected $x2;
protected $y2;
/** @var Gradient\Stop[] */
protected $stops = array();
public function start($attributes)
{
parent::start($attributes);
if (isset($attributes['x1'])) {
$this->x1 = $attributes['x1'];
}
if (isset($attributes['y1'])) {
$this->y1 = $attributes['y1'];
}
if (isset($attributes['x2'])) {
$this->x2 = $attributes['x2'];
}
if (isset($attributes['y2'])) {
$this->y2 = $attributes['y2'];
}
}
public function getStops() {
if (empty($this->stops)) {
foreach ($this->children as $_child) {
if ($_child->tagName != "stop") {
continue;
}
$_stop = new Gradient\Stop();
$_attributes = $_child->attributes;
// Style
if (isset($_attributes["style"])) {
$_style = Style::parseCssStyle($_attributes["style"]);
if (isset($_style["stop-color"])) {
$_stop->color = Style::parseColor($_style["stop-color"]);
}
if (isset($_style["stop-opacity"])) {
$_stop->opacity = max(0, min(1.0, $_style["stop-opacity"]));
}
}
// Attributes
if (isset($_attributes["offset"])) {
$_stop->offset = $_attributes["offset"];
}
if (isset($_attributes["stop-color"])) {
$_stop->color = Style::parseColor($_attributes["stop-color"]);
}
if (isset($_attributes["stop-opacity"])) {
$_stop->opacity = max(0, min(1.0, $_attributes["stop-opacity"]));
}
$this->stops[] = $_stop;
}
}
return $this->stops;
}
}
PK C=]���L L Tag/AbstractTag.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\CssLength;
use Svg\Document;
use Svg\Style;
abstract class AbstractTag
{
/** @var Document */
protected $document;
public $tagName;
/** @var Style */
protected $style;
protected $attributes = array();
protected $hasShape = true;
/** @var self[] */
protected $children = array();
public function __construct(Document $document, $tagName)
{
$this->document = $document;
$this->tagName = $tagName;
}
public function getDocument(){
return $this->document;
}
/**
* @return Group|null
*/
public function getParentGroup() {
$stack = $this->getDocument()->getStack();
for ($i = count($stack)-2; $i >= 0; $i--) {
$tag = $stack[$i];
if ($tag instanceof Group || $tag instanceof Document) {
return $tag;
}
}
return null;
}
public function handle($attributes)
{
$this->attributes = $attributes;
if (!$this->getDocument()->inDefs) {
$this->before($attributes);
$this->start($attributes);
}
}
public function handleEnd()
{
if (!$this->getDocument()->inDefs) {
$this->end();
$this->after();
}
}
protected function before($attributes)
{
}
protected function start($attributes)
{
}
protected function end()
{
}
protected function after()
{
}
public function getAttributes()
{
return $this->attributes;
}
protected function setStyle(Style $style)
{
$this->style = $style;
if ($style->display === "none") {
$this->hasShape = false;
}
}
/**
* @return Style
*/
public function getStyle()
{
return $this->style;
}
/**
* Make a style object from the tag and its attributes
*
* @param array $attributes
*
* @return Style
*/
protected function makeStyle($attributes) {
$style = new Style();
$style->inherit($this);
$style->fromStyleSheets($this, $attributes);
$style->fromAttributes($attributes);
return $style;
}
protected function applyTransform($attributes)
{
if (isset($attributes["transform"])) {
$surface = $this->document->getSurface();
$transform = $attributes["transform"];
$matches = array();
preg_match_all(
'/(matrix|translate|scale|rotate|skew|skewX|skewY)\((.*?)\)/is',
$transform,
$matches,
PREG_SET_ORDER
);
$transformations = array();
foreach ($matches as $match) {
$arguments = preg_split('/[ ,]+/', $match[2]);
array_unshift($arguments, $match[1]);
$transformations[] = $arguments;
}
foreach ($transformations as $t) {
switch ($t[0]) {
case "matrix":
$surface->transform($t[1], $t[2], $t[3], $t[4], $t[5], $t[6]);
break;
case "translate":
$surface->translate($t[1], isset($t[2]) ? $t[2] : 0);
break;
case "scale":
$surface->scale($t[1], isset($t[2]) ? $t[2] : $t[1]);
break;
case "rotate":
if (isset($t[2])) {
$t[3] = isset($t[3]) ? $t[3] : 0;
$surface->translate($t[2], $t[3]);
$surface->rotate($t[1]);
$surface->translate(-$t[2], -$t[3]);
} else {
$surface->rotate($t[1]);
}
break;
case "skewX":
$tan_x = tan(deg2rad($t[1]));
$surface->transform(1, 0, $tan_x, 1, 0, 0);
break;
case "skewY":
$tan_y = tan(deg2rad($t[1]));
$surface->transform(1, $tan_y, 0, 1, 0, 0);
break;
}
}
}
}
/**
* Convert the given size for the context of this current tag.
* Takes a pixel-based reference, which is usually specific to the context of the size,
* but the actual reference size will be decided based upon the unit used.
*
* @param string $size
* @param float $pxReference
*
* @return float
*/
protected function convertSize(string $size, float $pxReference): float
{
$length = new CssLength($size);
$reference = $pxReference;
$defaultFontSize = 12;
switch ($length->getUnit()) {
case "em":
$reference = $this->style->fontSize ?? $defaultFontSize;
break;
case "rem":
$reference = $this->document->style->fontSize ?? $defaultFontSize;
break;
case "ex":
case "ch":
$emRef = $this->style->fontSize ?? $defaultFontSize;
$reference = $emRef * 0.5;
break;
case "vw":
$reference = $this->getDocument()->getWidth();
break;
case "vh":
$reference = $this->getDocument()->getHeight();
break;
case "vmin":
$reference = min($this->getDocument()->getHeight(), $this->getDocument()->getWidth());
break;
case "vmax":
$reference = max($this->getDocument()->getHeight(), $this->getDocument()->getWidth());
break;
}
return (new CssLength($size))->toPixels($reference);
}
}
PK C=]ˮ`�D D Tag/RadialGradient.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
class RadialGradient extends AbstractTag
{
public function start($attributes)
{
}
}
PK C=]<�: : Tag/Stop.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
class Stop extends AbstractTag
{
public function start($attributes)
{
}
}
PK C=]�e˺y y Tag/Line.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Style;
class Line extends Shape
{
protected $x1 = 0;
protected $y1 = 0;
protected $x2 = 0;
protected $y2 = 0;
public function start($attributes)
{
$height = $this->document->getHeight();
$width = $this->document->getWidth();
if (isset($attributes['x1'])) {
$this->x1 = $this->convertSize($attributes['x1'], $width);
}
if (isset($attributes['y1'])) {
$this->y1 = $this->convertSize($attributes['y1'], $height);
}
if (isset($attributes['x2'])) {
$this->x2 = $this->convertSize($attributes['x2'], $width);
}
if (isset($attributes['y2'])) {
$this->y2 = $this->convertSize($attributes['y2'], $height);
}
$surface = $this->document->getSurface();
$surface->moveTo($this->x1, $this->y1);
$surface->lineTo($this->x2, $this->y2);
}
}
PK C=]=1c Tag/StyleTag.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Sabberworm\CSS;
class StyleTag extends AbstractTag
{
protected $text = "";
public function end()
{
$parser = new CSS\Parser($this->text);
$this->document->appendStyleSheet($parser->parse());
}
public function appendText($text)
{
$this->text .= $text;
}
}
PK C=]���$
Tag/Image.phpnu �[��� <?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg\Tag;
use Svg\Style;
class Image extends AbstractTag
{
protected $x = 0;
protected $y = 0;
protected $width = 0;
protected $height = 0;
protected $href = null;
protected function before($attributes)
{
parent::before($attributes);
$surface = $this->document->getSurface();
$surface->save();
$this->applyTransform($attributes);
}
public function start($attributes)
{
$height = $this->document->getHeight();
$width = $this->document->getWidth();
$this->y = $height;
if (isset($attributes['x'])) {
$this->x = $this->convertSize($attributes['x'], $width);
}
if (isset($attributes['y'])) {
$this->y = $height - $this->convertSize($attributes['y'], $height);
}
if (isset($attributes['width'])) {
$this->width = $this->convertSize($attributes['width'], $width);
}
if (isset($attributes['height'])) {
$this->height = $this->convertSize($attributes['height'], $height);
}
if (isset($attributes['xlink:href'])) {
$this->href = $attributes['xlink:href'];
}
if (isset($attributes['href'])) {
$this->href = $attributes['href'];
}
$this->document->getSurface()->transform(1, 0, 0, -1, 0, $height);
$this->document->getSurface()->drawImage($this->href, $this->x, $this->y, $this->width, $this->height);
}
protected function after()
{
$this->document->getSurface()->restore();
}
}
PK C=]�w�O&