Upgrade php-svg-lib to v0.3

This commit is contained in:
Alexander A. Klimov 2017-12-14 10:12:58 +01:00
parent fcd851d1e5
commit 4ce4ad1074
23 changed files with 474 additions and 175 deletions

View File

@ -10,7 +10,7 @@ mkdir -p lib/php-font-lib
tar xzf php-font-lib-0.4.tar.gz --strip-components 1 -C lib/php-font-lib php-font-lib-0.4/{src,LICENSE}
rm php-font-lib-0.4.tar.gz
curl https://codeload.github.com/PhenX/php-svg-lib/tar.gz/v0.1 -o php-svg-lib-0.1.tar.gz
curl https://codeload.github.com/PhenX/php-svg-lib/tar.gz/v0.3 -o php-svg-lib-0.3.tar.gz
mkdir -p lib/php-svg-lib
tar xzf php-svg-lib-0.1.tar.gz --strip-components 1 -C lib/php-svg-lib php-svg-lib-0.1/src
rm php-svg-lib-0.1.tar.gz
tar xzf php-svg-lib-0.3.tar.gz --strip-components 1 -C lib/php-svg-lib php-svg-lib-0.3/src
rm php-svg-lib-0.3.tar.gz

View File

@ -12,6 +12,7 @@ class DefaultStyle extends Style
{
public $color = '';
public $opacity = 1.0;
public $display = 'inline';
public $fill = 'black';
public $fillOpacity = 1.0;

View File

@ -14,6 +14,7 @@ use Svg\Tag\Anchor;
use Svg\Tag\Circle;
use Svg\Tag\Ellipse;
use Svg\Tag\Group;
use Svg\Tag\ClipPath;
use Svg\Tag\Image;
use Svg\Tag\Line;
use Svg\Tag\LinearGradient;
@ -23,11 +24,13 @@ use Svg\Tag\Polyline;
use Svg\Tag\Rect;
use Svg\Tag\Stop;
use Svg\Tag\Text;
use Svg\Tag\StyleTag;
use Svg\Tag\UseTag;
class Document extends AbstractTag
{
protected $filename;
protected $inDefs = false;
public $inDefs = false;
protected $x;
protected $y;
@ -50,6 +53,9 @@ class Document extends AbstractTag
/** @var AbstractTag[] */
protected $defs = array();
/** @var \Sabberworm\CSS\CSSList\Document[] */
protected $styleSheets = array();
public function loadFile($filename)
{
$this->filename = $filename;
@ -132,12 +138,12 @@ class Document extends AbstractTag
public function handleSizeAttributes($attributes){
if ($this->width === null) {
if (isset($attributes["width"])) {
$width = (int)$attributes["width"];
$width = Style::convertSize($attributes["width"], 400);
$this->width = $width;
}
if (isset($attributes["height"])) {
$height = (int)$attributes["height"];
$height = Style::convertSize($attributes["height"], 300);
$this->height = $height;
}
@ -166,17 +172,35 @@ class Document extends AbstractTag
);
}
protected function getDocument(){
public function getDocument(){
return $this;
}
protected function before($attribs)
/**
* Append a style sheet
*
* @param \Sabberworm\CSS\CSSList\Document $stylesheet
*/
public function appendStyleSheet($stylesheet) {
$this->styleSheets[] = $stylesheet;
}
/**
* Get the document style sheets
*
* @return \Sabberworm\CSS\CSSList\Document[]
*/
public function getStyleSheets() {
return $this->styleSheets;
}
protected function before($attributes)
{
$surface = $this->getSurface();
$style = new DefaultStyle();
$style->inherit($this);
$style->fromAttributes($attribs);
$style->fromAttributes($attributes);
$this->setStyle($style);
@ -211,6 +235,12 @@ class Document extends AbstractTag
$this->handleSizeAttributes($attributes);
}
public function getDef($id) {
$id = ltrim($id, "#");
return isset($this->defs[$id]) ? $this->defs[$id] : null;
}
private function _tagStart($parser, $name, $attributes)
{
$this->x = 0;
@ -227,7 +257,7 @@ class Document extends AbstractTag
case 'svg':
if (count($this->attributes)) {
$tag = new Group($this);
$tag = new Group($this, $name);
}
else {
$tag = $this;
@ -236,72 +266,90 @@ class Document extends AbstractTag
break;
case 'path':
$tag = new Path($this);
$tag = new Path($this, $name);
break;
case 'rect':
$tag = new Rect($this);
$tag = new Rect($this, $name);
break;
case 'circle':
$tag = new Circle($this);
$tag = new Circle($this, $name);
break;
case 'ellipse':
$tag = new Ellipse($this);
$tag = new Ellipse($this, $name);
break;
case 'image':
$tag = new Image($this);
$tag = new Image($this, $name);
break;
case 'line':
$tag = new Line($this);
$tag = new Line($this, $name);
break;
case 'polyline':
$tag = new Polyline($this);
$tag = new Polyline($this, $name);
break;
case 'polygon':
$tag = new Polygon($this);
$tag = new Polygon($this, $name);
break;
case 'lineargradient':
$tag = new LinearGradient($this);
$tag = new LinearGradient($this, $name);
break;
case 'radialgradient':
$tag = new LinearGradient($this);
$tag = new LinearGradient($this, $name);
break;
case 'stop':
$tag = new Stop($this);
$tag = new Stop($this, $name);
break;
case 'style':
$tag = new StyleTag($this, $name);
break;
case 'a':
$tag = new Anchor($this);
$tag = new Anchor($this, $name);
break;
case 'g':
$tag = new Group($this);
case 'symbol':
$tag = new Group($this, $name);
break;
case 'clippath':
$tag = new ClipPath($this, $name);
break;
case 'use':
$tag = new UseTag($this, $name);
break;
case 'text':
$tag = new Text($this);
$tag = new Text($this, $name);
break;
}
if ($tag) {
if (!$this->inDefs) {
$this->stack[] = $tag;
$tag->handle($attributes);
if (isset($attributes["id"])) {
$this->defs[$attributes["id"]] = $tag;
}
else {
if (isset($attributes["id"])) {
$this->defs[$attributes["id"]] = $tag;
/** @var AbstractTag $top */
$top = end($this->stack);
if ($top && $top != $tag) {
$top->children[] = $tag;
}
}
$this->stack[] = $tag;
$tag->handle($attributes);
} else {
echo "Unknown: '$name'\n";
}
@ -311,7 +359,7 @@ class Document extends AbstractTag
{
$stack_top = end($this->stack);
if ($stack_top instanceof Text) {
if ($stack_top instanceof Text || $stack_top instanceof StyleTag) {
$stack_top->appendText($data);
}
}
@ -337,16 +385,18 @@ class Document extends AbstractTag
case 'radialgradient':
case 'lineargradient':
case 'stop':
case 'style':
case 'text':
case 'g':
case 'symbol':
case 'clippath':
case 'use':
case 'a':
if (!$this->inDefs) {
$tag = array_pop($this->stack);
}
$tag = array_pop($this->stack);
break;
}
if ($tag) {
if (!$this->inDefs && $tag) {
$tag->handleEnd();
}
}

View File

@ -2,7 +2,7 @@
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @author Fabien M<EFBFBD>nager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
@ -20,6 +20,7 @@ class Style
public $color;
public $opacity;
public $display;
public $fill;
public $fillOpacity;
@ -45,6 +46,7 @@ class Style
return array(
'color' => array('color', self::TYPE_COLOR),
'opacity' => array('opacity', self::TYPE_NUMBER),
'display' => array('display', self::TYPE_NAME),
'fill' => array('fill', self::TYPE_COLOR),
'fill-opacity' => array('fillOpacity', self::TYPE_NUMBER),
@ -61,7 +63,7 @@ class Style
'font-family' => array('fontFamily', self::TYPE_NAME),
'font-size' => array('fontSize', self::TYPE_NUMBER),
'font-weight' => array('fontWeight', self::TYPE_NUMBER),
'font-weight' => array('fontWeight', self::TYPE_NAME),
'font-style' => array('fontStyle', self::TYPE_NAME),
'text-anchor' => array('textAnchor', self::TYPE_NAME),
);
@ -95,6 +97,52 @@ class Style
}
}
public function fromStyleSheets(AbstractTag $tag, $attributes) {
$class = isset($attributes["class"]) ? preg_split('/\s+/', trim($attributes["class"])) : null;
$stylesheets = $tag->getDocument()->getStyleSheets();
$styles = array();
foreach ($stylesheets as $_sc) {
/** @var \Sabberworm\CSS\RuleSet\DeclarationBlock $_decl */
foreach ($_sc->getAllDeclarationBlocks() as $_decl) {
/** @var \Sabberworm\CSS\Property\Selector $_selector */
foreach ($_decl->getSelectors() as $_selector) {
$_selector = $_selector->getSelector();
// Match class name
if ($class !== null) {
foreach ($class as $_class) {
if ($_selector === ".$_class") {
/** @var \Sabberworm\CSS\Rule\Rule $_rule */
foreach ($_decl->getRules() as $_rule) {
$styles[$_rule->getRule()] = $_rule->getValue() . "";
}
break 2;
}
}
}
// Match tag name
if ($_selector === $tag->tagName) {
/** @var \Sabberworm\CSS\Rule\Rule $_rule */
foreach ($_decl->getRules() as $_rule) {
$styles[$_rule->getRule()] = $_rule->getValue() . "";
}
break;
}
}
}
}
$this->fillStyles($styles);
}
protected function fillStyles($styles)
{
foreach ($this->getStyleMap() as $from => $spec) {
@ -125,7 +173,7 @@ class Style
{
$color = strtolower(trim($color));
$parts = preg_split('/\s+/', $color, 2);
$parts = preg_split('/[^,]\s+/', $color, 2);
if (count($parts) == 2) {
$color = $parts[1];
@ -218,6 +266,19 @@ class Style
);
}
// Gradient
if (strpos($color, "url(#") !== false) {
$i = strpos($color, "(");
$j = strpos($color, ")");
// Bad url format
if ($i === false || $j === false) {
return null;
}
return trim(substr($color, $i + 1, $j - $i - 1));
}
return null;
}
@ -298,13 +359,13 @@ class Style
/**
* Convert a size to a float
*
* @param string $size SVG size
* @param float $dpi DPI
* @param float $fontsize Reference font size
* @param string $size SVG size
* @param float $dpi DPI
* @param float $referenceSize Reference size
*
* @return float|null
*/
static function convertSize($size, $dpi = 72.0, $fontsize = 11.0) {
static function convertSize($size, $referenceSize = 11.0, $dpi = 96.0) {
$size = trim(strtolower($size));
if (is_numeric($size)) {
@ -319,12 +380,16 @@ class Style
return floatval(substr($size, 0, $pos));
}
if ($pos = strpos($size, "cm")) {
return floatval(substr($size, 0, $pos)) * $dpi;
}
if ($pos = strpos($size, "%")) {
return $fontsize * substr($size, 0, $pos) / 100;
return $referenceSize * substr($size, 0, $pos) / 100;
}
if ($pos = strpos($size, "em")) {
return $fontsize * substr($size, 0, $pos);
return $referenceSize * substr($size, 0, $pos);
}
// TODO cm, mm, pc, in, etc

View File

@ -2,7 +2,7 @@
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @author Fabien M<EFBFBD>nager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
@ -15,7 +15,7 @@ class SurfaceCpdf implements SurfaceInterface
{
const DEBUG = false;
/** @var Cpdf */
/** @var \CPdf\CPdf */
private $canvas;
private $width;
@ -33,7 +33,9 @@ class SurfaceCpdf implements SurfaceInterface
$h = $dimensions["height"];
if (!$canvas) {
$canvas = new CPdf(array(0, 0, $w, $h));
$canvas = new \CPdf\CPdf(array(0, 0, $w, $h));
$refl = new \ReflectionClass($canvas);
$canvas->fontcache = realpath(dirname($refl->getFileName()) . "/../../fonts/")."/";
}
// Flip PDF coordinate system so that the origin is in
@ -141,7 +143,7 @@ class SurfaceCpdf implements SurfaceInterface
public function strokeText($text, $x, $y, $maxWidth = null)
{
if (self::DEBUG) echo __FUNCTION__ . "\n";
// TODO: Implement drawImage() method.
$this->canvas->addText($x, $y, $this->style->fontSize, $text);
}
public function drawImage($image, $sx, $sy, $sw = null, $sh = null, $dx = null, $dy = null, $dw = null, $dh = null)
@ -149,9 +151,22 @@ class SurfaceCpdf implements SurfaceInterface
if (self::DEBUG) echo __FUNCTION__ . "\n";
if (strpos($image, "data:") === 0) {
$data = substr($image, strpos($image, ";") + 1);
if (strpos($data, "base64") === 0) {
$data = base64_decode(substr($data, 7));
$parts = explode(',', $image, 2);
$data = $parts[1];
$base64 = false;
$token = strtok($parts[0], ';');
while ($token !== false) {
if ($token == 'base64') {
$base64 = true;
}
$token = strtok(';');
}
if ($base64) {
$data = base64_decode($data);
}
}
else {
@ -281,6 +296,9 @@ class SurfaceCpdf implements SurfaceInterface
return;
}
$rx = min($rx, $w / 2);
$rx = min($rx, $h / 2);
/* Define a path for a rectangle with corners rounded by a given radius.
* Start from the lower left corner and proceed counterclockwise.
*/
@ -340,7 +358,7 @@ class SurfaceCpdf implements SurfaceInterface
{
if (self::DEBUG) echo __FUNCTION__ . "\n";
$style = $this->getStyle();
$this->getFont($style->fontFamily, $style->fontStyle);
$this->setFont($style->fontFamily, $style->fontStyle, $style->fontWeight);
return $this->canvas->getTextWidth($this->getStyle()->fontSize, $text);
}
@ -358,12 +376,12 @@ class SurfaceCpdf implements SurfaceInterface
$this->style = $style;
$canvas = $this->canvas;
if ($stroke = $style->stroke) {
$canvas->setStrokeColor(array($stroke[0]/255, $stroke[1]/255, $stroke[2]/255), true);
if (is_array($style->stroke) && $stroke = $style->stroke) {
$canvas->setStrokeColor(array((float)$stroke[0]/255, (float)$stroke[1]/255, (float)$stroke[2]/255), true);
}
if ($fill = $style->fill) {
$canvas->setColor(array($fill[0]/255, $fill[1]/255, $fill[2]/255), true);
if (is_array($style->fill) && $fill = $style->fill) {
$canvas->setColor(array((float)$fill[0]/255, (float)$fill[1]/255, (float)$fill[2]/255), true);
}
if ($fillRule = strtolower($style->fillRule)) {
@ -392,17 +410,22 @@ class SurfaceCpdf implements SurfaceInterface
}
}
$dashArray = null;
if ($style->strokeDasharray) {
$dashArray = preg_split('/\s*,\s*/', $style->strokeDasharray);
}
$canvas->setLineStyle(
$style->strokeWidth,
$style->strokeLinecap,
$style->strokeLinejoin
$style->strokeLinejoin,
$dashArray
);
//$font = $this->getFont($style->fontFamily, $style->fontStyle);
//$canvas->setfont($font, $style->fontSize);
$this->setFont($style->fontFamily, $style->fontStyle, $style->fontWeight);
}
private function getFont($family, $style)
public function setFont($family, $style, $weight)
{
$map = array(
"serif" => "Times",
@ -415,11 +438,49 @@ class SurfaceCpdf implements SurfaceInterface
"verdana" => "Helvetica",
);
$styleMap = array(
'Helvetica' => array(
'b' => 'Helvetica-Bold',
'i' => 'Helvetica-Oblique',
'bi' => 'Helvetica-BoldOblique',
),
'Courier' => array(
'b' => 'Courier-Bold',
'i' => 'Courier-Oblique',
'bi' => 'Courier-BoldOblique',
),
'Times' => array(
'' => 'Times-Roman',
'b' => 'Times-Bold',
'i' => 'Times-Italic',
'bi' => 'Times-BoldItalic',
),
);
$family = strtolower($family);
$style = strtolower($style);
$weight = strtolower($weight);
if (isset($map[$family])) {
$family = $map[$family];
}
//return $this->canvas->load_font($family, "unicode", "fontstyle=$style");
if (isset($styleMap[$family])) {
$key = "";
if ($weight === "bold" || $weight === "bolder" || (is_numeric($weight) && $weight >= 600)) {
$key .= "b";
}
if ($style === "italic" || $style === "oblique") {
$key .= "i";
}
if (isset($styleMap[$family][$key])) {
$family = $styleMap[$family][$key];
}
}
$this->canvas->selectFont("$family.afm");
}
}
}

View File

@ -2,7 +2,7 @@
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @author Fabien M<EFBFBD>nager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
@ -256,11 +256,11 @@ class SurfaceGmagick implements SurfaceInterface
$this->style = $style;
$canvas = $this->canvas;
if ($stroke = $style->stroke) {
if (is_array($style->stroke) && $stroke = $style->stroke) {
$canvas->setcolor("stroke", "rgb", $stroke[0] / 255, $stroke[1] / 255, $stroke[2] / 255, null);
}
if ($fill = $style->fill) {
if (is_array($style->fill) && $fill = $style->fill) {
// $canvas->setcolor("fill", "rgb", $fill[0] / 255, $fill[1] / 255, $fill[2] / 255, null);
}
@ -300,4 +300,9 @@ class SurfaceGmagick implements SurfaceInterface
return $this->canvas->load_font($family, "unicode", "fontstyle=$style");
}
public function setFont($family, $style, $weight)
{
// TODO: Implement setFont() method.
}
}

View File

@ -2,7 +2,7 @@
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @author Fabien M<EFBFBD>nager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
@ -85,4 +85,6 @@ interface SurfaceInterface
* @return Style
*/
public function getStyle();
public function setFont($family, $style, $weight);
}

View File

@ -2,7 +2,7 @@
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @author Fabien M<EFBFBD>nager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
@ -315,7 +315,7 @@ class SurfacePDFLib implements SurfaceInterface
$this->style = $style;
$canvas = $this->canvas;
if (($stroke = $style->stroke) && $stroke !== "none") {
if ($stroke = $style->stroke && is_array($style->stroke)) {
$canvas->setcolor(
"stroke",
"rgb",
@ -326,7 +326,7 @@ class SurfacePDFLib implements SurfaceInterface
);
}
if (($fill = $style->fill) && $fill !== "none") {
if ($fill = $style->fill && is_array($style->fill)) {
$canvas->setcolor(
"fill",
"rgb",
@ -414,4 +414,9 @@ class SurfacePDFLib implements SurfaceInterface
return $this->canvas->load_font($family, "unicode", "fontstyle=$style");
}
public function setFont($family, $style, $weight)
{
// TODO: Implement setFont() method.
}
}

View File

@ -16,6 +16,8 @@ abstract class AbstractTag
/** @var Document */
protected $document;
public $tagName;
/** @var Style */
protected $style;
@ -23,12 +25,16 @@ abstract class AbstractTag
protected $hasShape = true;
public function __construct(Document $document)
/** @var self[] */
protected $children = array();
public function __construct(Document $document, $tagName)
{
$this->document = $document;
$this->tagName = $tagName;
}
protected function getDocument(){
public function getDocument(){
return $this->document;
}
@ -48,25 +54,29 @@ abstract class AbstractTag
return null;
}
public final function handle($attributes)
public function handle($attributes)
{
$this->attributes = $attributes;
$this->before($attributes);
$this->start($attributes);
if (!$this->getDocument()->inDefs) {
$this->before($attributes);
$this->start($attributes);
}
}
public final function handleEnd()
public function handleEnd()
{
$this->end();
$this->after();
if (!$this->getDocument()->inDefs) {
$this->end();
$this->after();
}
}
protected function before($attribs)
protected function before($attributes)
{
}
protected function start($attribs)
protected function start($attributes)
{
}
@ -86,23 +96,43 @@ abstract class AbstractTag
protected function setStyle(Style $style)
{
$this->style = $style;
if ($style->display === "none") {
$this->hasShape = false;
}
}
/**
* @return \Svg\Style
* @return Style
*/
public function getStyle()
{
return $this->style;
}
protected function applyTransform($attribs)
/**
* 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($attribs["transform"])) {
if (isset($attributes["transform"])) {
$surface = $this->document->getSurface();
$transform = $attribs["transform"];
$transform = $attributes["transform"];
$match = array();
preg_match_all(

View File

@ -14,16 +14,16 @@ class Circle extends Shape
protected $cy = 0;
protected $r;
public function start($attribs)
public function start($attributes)
{
if (isset($attribs['cx'])) {
$this->cx = $attribs['cx'];
if (isset($attributes['cx'])) {
$this->cx = $attributes['cx'];
}
if (isset($attribs['cy'])) {
$this->cy = $attribs['cy'];
if (isset($attributes['cy'])) {
$this->cy = $attributes['cy'];
}
if (isset($attribs['r'])) {
$this->r = $attribs['r'];
if (isset($attributes['r'])) {
$this->r = $attributes['r'];
}
$this->document->getSurface()->circle($this->cx, $this->cy, $this->r);

View File

@ -15,21 +15,21 @@ class Ellipse extends Shape
protected $rx = 0;
protected $ry = 0;
public function start($attribs)
public function start($attributes)
{
parent::start($attribs);
parent::start($attributes);
if (isset($attribs['cx'])) {
$this->cx = $attribs['cx'];
if (isset($attributes['cx'])) {
$this->cx = $attributes['cx'];
}
if (isset($attribs['cy'])) {
$this->cy = $attribs['cy'];
if (isset($attributes['cy'])) {
$this->cy = $attributes['cy'];
}
if (isset($attribs['rx'])) {
$this->rx = $attribs['rx'];
if (isset($attributes['rx'])) {
$this->rx = $attributes['rx'];
}
if (isset($attribs['ry'])) {
$this->ry = $attribs['ry'];
if (isset($attributes['ry'])) {
$this->ry = $attributes['ry'];
}
$this->document->getSurface()->ellipse($this->cx, $this->cy, $this->rx, $this->ry, 0, 0, 360, false);

View File

@ -12,21 +12,18 @@ use Svg\Style;
class Group extends AbstractTag
{
protected function before($attribs)
protected function before($attributes)
{
$surface = $this->document->getSurface();
$surface->save();
$style = new Style();
$style->inherit($this);
$style->fromAttributes($attribs);
$style = $this->makeStyle($attributes);
$this->setStyle($style);
$surface->setStyle($style);
$this->applyTransform($attribs);
$this->applyTransform($attributes);
}
protected function after()

View File

@ -16,38 +16,38 @@ class Image extends AbstractTag
protected $height = 0;
protected $href = null;
protected function before($attribs)
protected function before($attributes)
{
parent::before($attribs);
parent::before($attributes);
$surface = $this->document->getSurface();
$surface->save();
$this->applyTransform($attribs);
$this->applyTransform($attributes);
}
public function start($attribs)
public function start($attributes)
{
$document = $this->document;
$height = $this->document->getHeight();
$this->y = $height;
if (isset($attribs['x'])) {
$this->x = $attribs['x'];
if (isset($attributes['x'])) {
$this->x = $attributes['x'];
}
if (isset($attribs['y'])) {
$this->y = $height - $attribs['y'];
if (isset($attributes['y'])) {
$this->y = $height - $attributes['y'];
}
if (isset($attribs['width'])) {
$this->width = $attribs['width'];
if (isset($attributes['width'])) {
$this->width = $attributes['width'];
}
if (isset($attribs['height'])) {
$this->height = $attribs['height'];
if (isset($attributes['height'])) {
$this->height = $attributes['height'];
}
if (isset($attribs['xlink:href'])) {
$this->href = $attribs['xlink:href'];
if (isset($attributes['xlink:href'])) {
$this->href = $attributes['xlink:href'];
}
$document->getSurface()->transform(1, 0, 0, -1, 0, $height);

View File

@ -16,19 +16,19 @@ class Line extends Shape
protected $x2 = 0;
protected $y2 = 0;
public function start($attribs)
public function start($attributes)
{
if (isset($attribs['x1'])) {
$this->x1 = $attribs['x1'];
if (isset($attributes['x1'])) {
$this->x1 = $attributes['x1'];
}
if (isset($attribs['y1'])) {
$this->y1 = $attribs['y1'];
if (isset($attributes['y1'])) {
$this->y1 = $attributes['y1'];
}
if (isset($attribs['x2'])) {
$this->x2 = $attribs['x2'];
if (isset($attributes['x2'])) {
$this->x2 = $attributes['x2'];
}
if (isset($attribs['y2'])) {
$this->y2 = $attribs['y2'];
if (isset($attributes['y2'])) {
$this->y2 = $attributes['y2'];
}
$surface = $this->document->getSurface();

View File

@ -9,10 +9,75 @@
namespace Svg\Tag;
use Svg\Gradient\Stop;
use Svg\Style;
class LinearGradient extends AbstractTag
{
public function start($attribs)
{
protected $x1;
protected $y1;
protected $x2;
protected $y2;
/** @var 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 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;
}
}

View File

@ -29,23 +29,22 @@ class Path extends Shape
'M' => 'L',
);
public function start($attribs)
public function start($attributes)
{
if (!isset($attribs['d'])) {
if (!isset($attributes['d'])) {
$this->hasShape = false;
return;
}
$commands = array();
preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $attribs['d'], $commands, PREG_SET_ORDER);
preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $attributes['d'], $commands, PREG_SET_ORDER);
$path = array();
foreach ($commands as $c) {
if (count($c) == 3) {
$arguments = array();
preg_match_all('/[\-^]?[\d.]+(e[\-]?[\d]+){0,1}/i', $c[2], $arguments, PREG_PATTERN_ORDER);
preg_match_all('/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/i', $c[2], $arguments, PREG_PATTERN_ORDER);
$item = $arguments[0];
$commandLower = strtolower($c[1]);

View File

@ -10,10 +10,10 @@ namespace Svg\Tag;
class Polygon extends Shape
{
public function start($attribs)
public function start($attributes)
{
$tmp = array();
preg_match_all('/([\-]*[0-9\.]+)/', $attribs['points'], $tmp);
preg_match_all('/([\-]*[0-9\.]+)/', $attributes['points'], $tmp);
$points = $tmp[0];
$count = count($points);

View File

@ -10,10 +10,10 @@ namespace Svg\Tag;
class Polyline extends Shape
{
public function start($attribs)
public function start($attributes)
{
$tmp = array();
preg_match_all('/([\-]*[0-9\.]+)/', $attribs['points'], $tmp);
preg_match_all('/([\-]*[0-9\.]+)/', $attributes['points'], $tmp);
$points = $tmp[0];
$count = count($points);

View File

@ -10,7 +10,7 @@ namespace Svg\Tag;
class RadialGradient extends AbstractTag
{
public function start($attribs)
public function start($attributes)
{
}

View File

@ -17,27 +17,27 @@ class Rect extends Shape
protected $rx = 0;
protected $ry = 0;
public function start($attribs)
public function start($attributes)
{
if (isset($attribs['x'])) {
$this->x = $attribs['x'];
if (isset($attributes['x'])) {
$this->x = $attributes['x'];
}
if (isset($attribs['y'])) {
$this->y = $attribs['y'];
if (isset($attributes['y'])) {
$this->y = $attributes['y'];
}
if (isset($attribs['width'])) {
$this->width = $attribs['width'];
if (isset($attributes['width'])) {
$this->width = $attributes['width'];
}
if (isset($attribs['height'])) {
$this->height = $attribs['height'];
if (isset($attributes['height'])) {
$this->height = $attributes['height'];
}
if (isset($attribs['rx'])) {
$this->rx = $attribs['rx'];
if (isset($attributes['rx'])) {
$this->rx = $attributes['rx'];
}
if (isset($attribs['ry'])) {
$this->ry = $attribs['ry'];
if (isset($attributes['ry'])) {
$this->ry = $attributes['ry'];
}
$this->document->getSurface()->rect($this->x, $this->y, $this->width, $this->height, $this->rx, $this->ry);

View File

@ -2,7 +2,7 @@
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
@ -12,21 +12,18 @@ use Svg\Style;
class Shape extends AbstractTag
{
protected function before($attribs)
protected function before($attributes)
{
$surface = $this->document->getSurface();
$surface->save();
$style = new Style();
$style->inherit($this);
$style->fromAttributes($attribs);
$style = $this->makeStyle($attributes);
$this->setStyle($style);
$surface->setStyle($style);
$this->applyTransform($attribs);
$this->applyTransform($attributes);
}
protected function after()
@ -36,16 +33,24 @@ class Shape extends AbstractTag
if ($this->hasShape) {
$style = $surface->getStyle();
$fill = $style->fill && $style->fill !== "none";
$stroke = $style->stroke && $style->stroke !== "none";
$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) {
}
elseif ($stroke) {
$surface->stroke();
}
else {

View File

@ -10,7 +10,7 @@ namespace Svg\Tag;
class Stop extends AbstractTag
{
public function start($attribs)
public function start($attributes)
{
}

View File

@ -2,7 +2,7 @@
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
@ -14,17 +14,17 @@ class Text extends Shape
protected $y = 0;
protected $text = "";
public function start($attribs)
public function start($attributes)
{
$document = $this->document;
$height = $this->document->getHeight();
$this->y = $height;
if (isset($attribs['x'])) {
$this->x = $attribs['x'];
if (isset($attributes['x'])) {
$this->x = $attributes['x'];
}
if (isset($attribs['y'])) {
$this->y = $height - $attribs['y'];
if (isset($attributes['y'])) {
$this->y = $height - $attributes['y'];
}
$document->getSurface()->transform(1, 0, 0, -1, 0, $height);
@ -35,13 +35,22 @@ class Text extends Shape
$surface = $this->document->getSurface();
$x = $this->x;
$y = $this->y;
$style = $surface->getStyle();
$surface->setFont($style->fontFamily, $style->fontStyle, $style->fontWeight);
if ($surface->getStyle()->textAnchor == "middle") {
$width = $surface->measureText($this->text);
$x -= $width / 2;
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->text, $x, $y);
$surface->fillText($this->getText(), $x, $y);
}
protected function after()
@ -53,4 +62,9 @@ class Text extends Shape
{
$this->text .= $text;
}
}
public function getText()
{
return trim($this->text);
}
}