<?php
interface Drawable
{
    public function draw($canvas);
}
class Rectangle implements Drawable
{
    protected $x;
    protected $y;
    protected $width;
    protected $height;
    protected $borderColor;
    public function __construct($x, $y, $width, $height,
            $borderColor = array(255, 255, 255))
    {
        $this->x = $x;
        $this->y = $y;
        $this->setDimensions($width, $height);
        $this->borderColor = $borderColor;
    }
    public function setDimensions($width, $height)
    {
        $this->width = $width;
        $this->height = $height;
    }
    public function draw($canvas)
    {
        list($r, $g, $b) = $this->borderColor;
        $color = imagecolorallocate($canvas, $r, $g, $b);
        imagerectangle($canvas, $this->x, $this->y,
                $this->x + $this->width, $this->y + $this->height, $color);
    }
}
class Square extends Rectangle
{
    public function setDimensions($width, $height)
    {
        if ($width !== $height) {
            throw new Exception('Width and height are not equal');
        }
        parent::setDimensions($width, $height);
    }
}
class Text implements Drawable
{
    protected $x;
    protected $y;
    protected $text;
    protected $font;
    public function __construct($x, $y, $text, $font = 'LinLibertine_R')
    {
        $this->x = $x;
        $this->y = $y;
        $this->text = $text;
        $this->font = $font;
    }
    public function draw($canvas)
    {
        $color = imagecolorallocate($canvas, 0, 255, 0);
        imagettftext($canvas, 12, 0, $this->x, $this->y, $color, $this->font, $this->text);
    }
}
class Scene
{
    protected $width;
    protected $height;
    protected $drawingObjects = array();
    public function __construct($width = 640, $height = 480)
    {
        $this->width = $width;
        $this->height = $height;
    }
    public function addDrawingObject(Drawable $do)
    {
        $this->drawingObjects[] = $do;
    }
    public function render()
    {
        $canvas = imagecreatetruecolor($this->width, $this->height);
        foreach ($this->drawingObjects as $do) {
            $do->draw($canvas);
        }
        return $canvas;
    }
}
// Set the enviroment variable for GD
putenv('GDFONTPATH=' . realpath('.'));
$scene = new Scene();
$scene->addDrawingObject(new Rectangle(50, 50, 200, 100));
$scene->addDrawingObject(new Square(250, 150, 200, 200, array(255, 0, 0)));
// Folgende Zeile funktioniert nur, wenn LinLibertine_R.ttf im selben
// Verzeichnis existiert
#$scene->addDrawingObject(new Text(100, 400, 'Hallo Welt!', 'LinLibertine_R'));
// Diese Zeile erzeugt einen Fehler, weil das Quadrat nicht quadratisch ist
#$scene->addDrawingObject(new Square(0, 0, 100, 200));
$canvas = $scene->render();
header('Content-Type: image/png');
imagepng($canvas);