PK m-Zˮ`D D RadialGradient.phpnu W+A * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html */ namespace Svg\Tag; class RadialGradient extends AbstractTag { public function start($attributes) { } } PK m-Z! UseTag.phpnu W+A * @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["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; } $attributes = array_merge($this->reference->attributes, $attributes); $this->reference->handle($attributes); foreach ($this->reference->children as $_child) { $_attributes = array_merge($_child->attributes, $attributes); $_child->handle($_attributes); } } public function handleEnd() { parent::handleEnd(); if (!$this->reference) { return; } $this->reference->handleEnd(); foreach ($this->reference->children as $_child) { $_child->handleEnd(); } } } PK m-Z<: : Stop.phpnu W+A * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html */ namespace Svg\Tag; class Stop extends AbstractTag { public function start($attributes) { } } PK m-Z a6 Shape.phpnu W+A * @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(); } 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(); } else { $surface->endPath(); } } $surface->restore(); } } PK m-Z9 AbstractTag.phpnu W+A * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html */ namespace Svg\Tag; 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"]; $match = array(); preg_match_all( '/(matrix|translate|scale|rotate|skewX|skewY)\((.*?)\)/is', $transform, $match, PREG_SET_ORDER ); $transformations = array(); if (count($match[0])) { foreach ($match 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": $surface->skewX($t[1]); break; case "skewY": $surface->skewY($t[1]); break; } } } } } PK m-Zp Polygon.phpnu W+A * @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); $points = $tmp[0]; $count = count($points); $surface = $this->document->getSurface(); list($x, $y) = $points; $surface->moveTo($x, $y); for ($i = 2; $i < $count; $i += 2) { $x = $points[$i]; $y = $points[$i + 1]; $surface->lineTo($x, $y); } $surface->closePath(); } } PK m-Z3: ClipPath.phpnu W+A * @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 m-Zx1 t t Text.phpnu W+A * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html */ namespace Svg\Tag; class Text extends Shape { protected $x = 0; protected $y = 0; protected $text = ""; public function start($attributes) { $document = $this->document; $height = $this->document->getHeight(); $this->y = $height; if (isset($attributes['x'])) { $this->x = $attributes['x']; } if (isset($attributes['y'])) { $this->y = $height - $attributes['y']; } $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 m-Z=` Image.phpnu W+A * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html */ namespace Svg\Tag; 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) { $document = $this->document; $height = $this->document->getHeight(); $this->y = $height; if (isset($attributes['x'])) { $this->x = $attributes['x']; } if (isset($attributes['y'])) { $this->y = $height - $attributes['y']; } if (isset($attributes['width'])) { $this->width = $attributes['width']; } if (isset($attributes['height'])) { $this->height = $attributes['height']; } if (isset($attributes['xlink:href'])) { $this->href = $attributes['xlink:href']; } $document->getSurface()->transform(1, 0, 0, -1, 0, $height); $document->getSurface()->drawImage($this->href, $this->x, $this->y, $this->width, $this->height); } protected function after() { $this->document->getSurface()->restore(); } } PK m-ZK Circle.phpnu W+A * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html */ namespace Svg\Tag; class Circle extends Shape { protected $cx = 0; protected $cy = 0; protected $r; public function start($attributes) { if (isset($attributes['cx'])) { $this->cx = $attributes['cx']; } if (isset($attributes['cy'])) { $this->cy = $attributes['cy']; } if (isset($attributes['r'])) { $this->r = $attributes['r']; } $this->document->getSurface()->circle($this->cx, $this->cy, $this->r); } } PK m-ZW W W Rect.phpnu W+A * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html */ namespace Svg\Tag; 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) { if (isset($attributes['x'])) { $this->x = $attributes['x']; } if (isset($attributes['y'])) { $this->y = $attributes['y']; } if (isset($attributes['width'])) { if ('%' === substr($attributes['width'], -1)) { $factor = substr($attributes['width'], 0, -1) / 100; $this->width = $this->document->getWidth() * $factor; } else { $this->width = $attributes['width']; } } if (isset($attributes['height'])) { if ('%' === substr($attributes['height'], -1)) { $factor = substr($attributes['height'], 0, -1) / 100; $this->height = $this->document->getHeight() * $factor; } else { $this->height = $attributes['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 m-Z*T Group.phpnu W+A * @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 m-Zg> LinearGradient.phpnu W+A * @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 m-Zo Ellipse.phpnu W+A * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html */ namespace Svg\Tag; class Ellipse extends Shape { protected $cx = 0; protected $cy = 0; protected $rx = 0; protected $ry = 0; public function start($attributes) { parent::start($attributes); if (isset($attributes['cx'])) { $this->cx = $attributes['cx']; } if (isset($attributes['cy'])) { $this->cy = $attributes['cy']; } if (isset($attributes['rx'])) { $this->rx = $attributes['rx']; } if (isset($attributes['ry'])) { $this->ry = $attributes['ry']; } $this->document->getSurface()->ellipse($this->cx, $this->cy, $this->rx, $this->ry, 0, 0, 360, false); } } PK m-Zz Anchor.phpnu W+A * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html */ namespace Svg\Tag; class Anchor extends Group { } PK m-Z0?ؔN N Path.phpnu W+A * @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)) { $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), $methodName = null; 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]; if (preg_match("/[QqTt]/", $previous[0])) { // If there is no previous command or if the previous command was not a Q, q, T or t, // assume the control point is coincident with the current point $controlX = $x; $controlY = $y; } else { if ($previous[0] === 't') { // calculate reflection of previous control points for t $controlX = 2 * $x - $tempControlX; $controlY = 2 * $y - $tempControlY; } else { if ($previous[0] === 'q') { // calculate reflection of previous control points for q $controlX = 2 * $x - $controlX; $controlY = 2 * $y - $controlY; } } } $tempControlX = $controlX; $tempControlY = $controlY; $surface->quadraticCurveTo( $controlX + $l, $controlY + $t, $tempX + $l, $tempY + $t ); $x = $tempX; $y = $tempY; $controlX = $x + $current[1]; $controlY = $y + $current[2]; break; case 'T': $tempX = $current[1]; $tempY = $current[2]; // calculate reflection of previous control points $controlX = 2 * $x - $controlX; $controlY = 2 * $y - $controlY; $surface->quadraticCurveTo( $controlX + $l, $controlY + $t, $tempX + $l, $tempY + $t ); $x = $tempX; $y = $tempY; 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] + $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(), ); $segsNorm = $this->arcToSegments($tx - $fx, $ty - $fy, $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 m-Z)bD Line.phpnu W+A * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html */ namespace Svg\Tag; class Line extends Shape { protected $x1 = 0; protected $y1 = 0; protected $x2 = 0; protected $y2 = 0; public function 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']; } $surface = $this->document->getSurface(); $surface->moveTo($this->x1, $this->y1); $surface->lineTo($this->x2, $this->y2); } } PK m-Zi Polyline.phpnu W+A * @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); $points = $tmp[0]; $count = count($points); $surface = $this->document->getSurface(); list($x, $y) = $points; $surface->moveTo($x, $y); for ($i = 2; $i < $count; $i += 2) { $x = $points[$i]; $y = $points[$i + 1]; $surface->lineTo($x, $y); } } } PK m-Z=1c StyleTag.phpnu W+A * @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 6Zeu TaggedValue.phpnu W+A * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Yaml\Tag; /** * @author Nicolas Grekas
* @author Guilhem N.