Clever Svg PHP5 library

Clever Svg is a library developed by Clever Age allows an easy creation of SVG documents using PHP5. Clever Svg is based on the DOM implementation of PHP.

Features

  • Basic shapes (rectangle, circle, polyline, polygon, line, ellipse, path)
  • Text and image management
  • Groups
  • Definitions
  • Embedding SVG in XHTML documents
  • Links
  • Styles (inline, stylesheets embedding and linking)
  • Scripts embedding
  • Gradients (Linear and Radial)
  • Transformations (matrix, translate, scale, rotate, skewX, skewY)

License

CleverSvg is licensed under the terms of the GNU Lesser General Public License.

Support

Quick example

This quick example generates a 550px x 300px SVG document (with title: "SVG test document") containing a red rectangle with a yellow stroke :

<?php
require_once('cleversvg.php');

$doc = new csDocument(550, 300, 'SVG test document');

$rect = new csRect(60, 60, 40, 40);
$rect->setFill('red');
$rect->setStroke('yellow');
$rect->setStrokeWidth('4');

$doc->addElement($rect);

header("Content-type: image/svg+xml");
echo $doc->toXML();
?>

Documentation

Installation

Prerequisites

  • PHP5+

Installation

The Clever Svg library is only available through svn export at this time:

$ svn export http://www.clever-age.org/svn/cleversvg/trunk/ cleversvg

Please let us know if a PEAR package is required.

Usage

First, require the library call script :

<?php
require_once('cleversvg.php');

Instanciate a SVG document, specifying its width and height :

<?php
$doc = new csDocument(550, 300);

Then, you can define as many shapes objects as you want and add them to the document :

<?php
$rect = new csRect(10, 10, 20, 30, array('fill' => 'blue'));
$circ = new csCircle(30, 30, 30, array('fill' => 'red'));
$doc->addElement($rect);
$doc->addElement($circ);

Never forget to send image/svg+xml headers before outputing

<?php
header("Content-type: image/svg+xml");

When you're done, render the document as a standalone one :

<?php
echo $doc->toXML();

Or an embedded one :

<?php
echo $doc->toXML(true);

Available shapes

Rectangle

<?php
// Adds a yellow rectangle
$rect = new csRect(10, 10, 40, 40, array('stroke_width' => 10, 
                                            'stroke'       => 'black', 
                                            'fill'         => 'yellow'));
$doc->addElement($rect);

// Adds a red rectangle, yellow stroked
$rect = new csRect(60, 60, 40, 40);
$rect->setFill('red');
$rect->setStroke('yellow');
$rect->setStrokeWidth('4');
$doc->addElement($rect);

// Add a purple rounded cornered rectangle, grey stroke
$rect = new csRect(110, 110, 40, 40, array('fill'   => 'purple',
                                              'stroke' => 'grey'));
$rect->setRadius(10);
$doc->addElement($rect);

// Add a green rectangle, unstroked
$rect = new csRect(160, 160, 40, 40);
$rect->setFill('green');
$doc->addElement($rect);

// Add a rectangle, unfilled, black stroke
$rect = new csRect(210, 210, 40, 40);
$rect->setStroke('black');
$rect->setFill('none');
$doc->addElement($rect);

Circle

<?php
$circle = new csCircle(110, 110, 100);
$circle->setStroke('red');
$circle->setStrokeWidth(10);
$circle->setFill('blue');
$doc->addElement($circle);

Polyline

<?php
$line = new csPolyline();
$line->setPointsArray(array(array(0, 0),
                            array(50, 0),
                            array(50, 50),
                            array(100, 50),
                            array(100, 100),
                            array(150, 100),
                            array(150, 150),
                            array(200, 150),
                            array(200, 200)));
$line->setStroke('green');
$line->setStrokeWidth(4);
$doc->addElement($line);

Polygon

<?php
$polygon = new csPolygon();
$polygon->setPointsArray(array(array(350,75),
                            array(379,161),
                            array(469,161),
                            array(397,215),
                            array(423,301), 
                            array(350,250), 
                            array(277,301), 
                            array(303,215),
                            array(231,161),
                            array(321,161)));
$polygon->setStroke('blue');
$polygon->setFill('grey');
$polygon->setStrokeWidth(4);
$doc->addElement($polygon);

Line

Reference: http://www.w3.org/TR/SVG11/shapes.html#LineElement

<?php
$line = new csLine(0, 0, 40, 40);
$line->setStroke('maroon');
$line->setStrokeWidth(1);
$doc->addElement($line);

$line = new csLine(50, 50, 90, 90);
$line->setStroke('red');
$line->setStrokeWidth(2);
$doc->addElement($line);

$line = new csLine(100, 100, 140, 140);
$line->setStroke('orange');
$line->setStrokeWidth(5);
$doc->addElement($line);

$line = new csLine(150, 150, 190, 190);
$line->setStroke('yellow');
$line->setStrokeWidth(10);
$doc->addElement($line);

Ellipse

Reference: http://www.w3.org/TR/SVG11/shapes.html#EllipseElement

<?php
$ellipse = new csEllipse(110, 110, 75, 100);
$ellipse->setStroke('yellow');
$ellipse->setStrokeWidth(5);
$ellipse->setFill('orange');
$doc->addElement($ellipse);

Path

Reference: http://www.w3.org/TR/SVG11/shapes.html#PathElement

<?php
$path = new csPath();
$path->begin();
$path->moveTo(100, 100);
$path->lineTo(300, 100);
$path->lineTo(200, 300);
$path->end();
$path->setStroke('blue');
$path->setStrokeWidth(5);
$path->setFill('yellow');
$doc->addElement($path);

Image

Reference: http://www.w3.org/TR/SVG11/shapes.html#ImageElement

<?php
$image = new csImage(10, 10);
$image->setHref('/images/avatar.png');
$image->setWidth(258);
$image->setHeight(194);
$doc->addElement($image);

Text

Reference: http://www.w3.org/TR/SVG11/shapes.html#TextElement

<?php
$text = new csText();
$text->setFill('brown');
$text->setContent('I love Ubuntu');

Grouping

You can use groups to link a shapes with others :

<?php
$doc = new csDocument(320, 200);

$group1 = new csGroup('1stgroup');
$group2 = new csGroup('2ndgroup');

$rectA = new csRect   (10, 10, 20, 20, array('fill' => 'red'));
$rectB = new csRect   (20, 20, 20, 20, array('fill' => 'blue'));
$group1->addElement($rectA);
$group1->addElement($rectB);

$circA = new csCircle (10, 10, 30, array('fill' => 'red'));
$circB = new csCircle (30, 30, 30, array('fill' => 'blue'));
$group2->addElement($circA);
$group2->addElement($circB);

$doc->addElement($group1);
$doc->addElement($group2);

This will produce a SVG code output like this :

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="200" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>SVG test document</title>
  <g id="1stgroup">
    <rect fill="red" x="10" y="10" width="20" height="20"/>
    <rect fill="blue" x="20" y="20" width="20" height="20"/>
  </g>
  <g id="2ndgroup">
    <circle fill="red" cx="10" cy="10" r="30"/>
    <circle fill="blue" cx="30" cy="30" r="30"/>
  </g>
</svg>

Definitions

Each shape element can be reused at a glance.

<?php
$circle = new csCircle(null, null, 10);
$circle->setStroke('yellow');
$circle->setStrokeWidth(2);
$circle->setFill('orange');
$circle->setId('circle1');

$square = new csRect(null, null, 20, 20);
$square->setFill('blue');
$square->setStroke('red');
$square->setId('square1');

$doc->addAsDefinition($circle, 'c1');
$doc->addAsDefinition($square, 's1');

for ($i=20; $i<=200; $i+= 30)
{
  $doc->useDefinition('c1', array('x' => $i, 'y' => 30));
}

for ($i=10; $i<200; $i+= 30)
{
  $doc->useDefinition('s1', array('x' => $i, 'y' => 60));
}

This will produce a SVG code output like this :

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="550" height="300" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>SVG test document</title>
  <defs>
    <circle r="10" stroke="yellow" stroke-width="2" fill="orange" id="c1"/>
    <rect width="20" height="20" fill="blue" stroke="red" id="s1"/>
  </defs>
  <use xlink:href="#c1" x="20" y="30"/>
  <use xlink:href="#c1" x="50" y="30"/>
  <use xlink:href="#c1" x="80" y="30"/>
  <use xlink:href="#c1" x="110" y="30"/>
  <use xlink:href="#c1" x="140" y="30"/>
  <use xlink:href="#c1" x="170" y="30"/>
  <use xlink:href="#c1" x="200" y="30"/>
  <use xlink:href="#s1" x="10" y="60"/>
  <use xlink:href="#s1" x="40" y="60"/>
  <use xlink:href="#s1" x="70" y="60"/>
  <use xlink:href="#s1" x="100" y="60"/>
  <use xlink:href="#s1" x="130" y="60"/>
  <use xlink:href="#s1" x="160" y="60"/>
  <use xlink:href="#s1" x="190" y="60"/>
</svg>

Embedding SVG in XHTML documents

SVG related XML namespaces must be declared in the container. Eg. for XHTML :

<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:svg="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink">

To render SVG inside a XHTML document, the toXml() method must be called with a boolean set to true as parameter :

<?php
echo $doc->toXml(true);
?>

Note: For rendering in IE, these lines should be added before SVG output :

!-- START Required for IE to support inlined SVG -->
<object id="AdobeSVG" classid="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2" width="1" height="1"></object>
<?import namespace="svg" implementation="#AdobeSVG"?>
<!-- END Required for IE to support inlined SVG -->

Linking a SVG shape is easy as this example (with a circle):

<?php
$circle = new csCircle(110, 110, 100, array('fill' => 'blue');

$link = new csLink();
$link->setHref('http://www.clever-age.com/');
$link->setTarget('_blank');

$link->addElement($circle);
$doc->addElement($link);

Styles

Inline styles

You can specify custom inline styles for any SVG shape :

<?php
$rect = new csRect(10, 10, 100, 50);
$rect->setStyle(array('fill' => 'blue', stroke => 'red', 'opacity' => 0.5));

Embedded stylesheet

You can define a global stylesheet declaration in the document :

<?php
$doc = new csDocument(640, 480);
$doc->addStyleDeclaration('
  rect {
    fill: red;
    stroke: blue;
    stroke-width: 4;
  }
');

$rect = new csRect(10, 10, 100, 50);
$doc->addElement($rect);

External stylesheet

External stylesheets allow easy design changes and reusability :

<?php
...
$doc->addStylesheetLink('/css/example_style.css');
...

Scripts

Clever Svg permits to embed Javascripts (and Ecmascripts) in a document :

<?php
...
$javascript = 'function cc(evt) {
  var circle = evt.target;
  var currentRadius = circle.getAttribute("r");
  if (currentRadius == 60) {
    circle.setAttribute("r", 50);
    circle.setAttribute("fill", "url(#myRadialGradient2)");
  } else {
    circle.setAttribute("r", 60);
    circle.setAttribute("fill", "url(#myRadialGradient1)");
  }
}';
$doc->addScript($javascript);

Gradients

Linear gradients

See the official SVG specification : http://www.w3.org/TR/SVG11/pservers.html#LinearGradients

<?php
...
$gradient = new csLinearGradient(0, 0, '100%', '100%');
$gradient->addStop('0%', 'yellow');
$gradient->addStop('100%', 'red');
$doc->addAsDefinition($gradient, 'myLinearGradient');

$circle = new csCircle(110, 110, 100);
$circle->setFill('url(#myLinearGradient)');
$doc->addElement($circle);

Radial gradients

See the official SVG specification : http://www.w3.org/TR/SVG11/pservers.html#RadialGradients

<?php
...
$gradient = new csRadialGradient('50%', '50%', '30%', '30%', '50%');
$gradient->addStop('15%', 'lightblue', 0.5);
$gradient->addStop('100%', 'darkblue');
$doc->addAsDefinition($gradient, 'myRadialGradient');

$circle = new csCircle(110, 110, 100);
$circle->setFill('url(#myRadialGradient)');
$doc->addElement($circle);

Transformations

Documentation : http://www.w3.org/TR/SVG/coords.html#TransformAttribute

matrix

Specifies a transformation in the form of a transformation matrix of six values

<?php
...
$ellipse = new csEllipse(110, 110, 50, 75);
$ellipse->setStroke('yellow');
$ellipse->setStrokeWidth(5);
$ellipse->setFill('orange');
$ellipse->matrix(1, 2, 2, 1, 2, -100);
$doc->addElement($ellipse);

translate

Specifies a translation (a block move): translate($tx, $ty=null)

<?php
...
$ellipse = new csEllipse(110, 110, 75, 100);
$ellipse->setStroke('yellow');
$ellipse->setStrokeWidth(5);
$ellipse->setFill('orange');
$ellipse->translate(100, 50);
$doc->addElement($ellipse);

scale

Specifies a scale operation: scale($xscale, $yscale=null)

<?php
...
$ellipse = new csEllipse(110, 110, 75, 100);
$ellipse->setStroke('yellow');
$ellipse->setStrokeWidth(5);
$ellipse->setFill('orange');
$ellipse->scale(0.5, 1);
$doc->addElement($ellipse);

rotate

Specifies a rotation: rotate($angle, $cx=0, $cy=0)

<?php
...
$ellipse = new csEllipse(110, 110, 75, 100);
$ellipse->setStroke('yellow');
$ellipse->setStrokeWidth(5);
$ellipse->setFill('orange');
$ellipse->rotate(45, 110, 110);
$doc->addElement($ellipse);

skewX

Specifies a skew transformation along the x-axis: skewX($angle)

<?php
...
$ellipse = new csEllipse(110, 110, 75, 100);
$ellipse->setStroke('yellow');
$ellipse->setStrokeWidth(5);
$ellipse->setFill('orange');
$ellipse->skewX(50);
$doc->addElement($ellipse);

skewY

Specifies a skew transformation along the y-axis: skewY($angle)

<?php
...
$ellipse = new csEllipse(110, 110, 75, 100);
$ellipse->setStroke('yellow');
$ellipse->setStrokeWidth(5);
$ellipse->setFill('orange');
$ellipse->skewY(50);
$doc->addElement($ellipse);

Changelog

Roadmap

version 0.6

  • Write complete PHPUnit test suite

version 0.7

  • Create existing SVG document import utility

Changelog

2008-03-XX - 0.6

  • Complete PHPUnit test suite
  • Refactorized containers classes (BC)

2008-02-26 - 0.5

  • Initial public release. Features:
    • Basic shapes (rectangle, circle, polyline, polygon, line, ellipse, path)
    • Text and image management
    • Groups
    • Definitions
    • Embedding SVG in XHTML documents
    • Links
    • Styles (inline, stylesheets embedding and linking)
    • Scripts embedding
    • Gradients (Linear and Radial)
    • Transformations (matrix, translate, scale, rotate, skewX, skewY)

Currently active tickets

#38
Provide package.xml
#40
Create unit test suite

Attachments