1<?php
2
3class Image_3D_Driver_SVG extends Image_3D_Driver
4{
5
6    protected $_x;
7    protected $_y;
8
9    protected $_id;
10
11    protected $_gradients;
12    protected $_polygones;
13
14    public function __construct()
15    {
16        $this->_image = '';
17        $this->_id    = 1;
18
19        $this->_gradients = array();
20        $this->_polygones = array();
21    }
22
23    public function createImage($x, $y)
24    {
25        $this->_x = (int) $x;
26        $this->_y = (int) $y;
27
28        $this->_image = <<<EOF
29<?xml version="1.0" ?>
30<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
31         "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
32
33<svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" width="{$this->_x}" height="{$this->_y}">
34EOF;
35
36        $this->_image .= "\n\n";
37    }
38
39    public function setBackground(Image_3D_Color $color)
40    {
41        $this->_addPolygon(sprintf("\t<polygon id=\"background%d\" points=\"0,0 %d,0 %d,%d 0,%d\" style=\"%s\" />\n",
42            $this->_id++,
43            $this->_x,
44            $this->_x,
45            $this->_y,
46            $this->_y,
47            $this->_getStyle($color)));
48    }
49
50    protected function _getStyle(Image_3D_Color $color)
51    {
52        $values = $color->getValues();
53
54        $values[0] = (int) round($values[0] * 255);
55        $values[1] = (int) round($values[1] * 255);
56        $values[2] = (int) round($values[2] * 255);
57        $values[3] = 1 - $values[3];
58
59        return sprintf('fill: #%02x%02x%02x; fill-opacity: %.2f; stroke: none;', $values[0], $values[1], $values[2], $values[3]);
60    }
61
62    protected function _getStop(Image_3D_Color $color, $offset = 0, $alpha = null)
63    {
64        $values = $color->getValues();
65
66        $values[0] = (int) round($values[0] * 255);
67        $values[1] = (int) round($values[1] * 255);
68        $values[2] = (int) round($values[2] * 255);
69        if ($alpha === null) {
70            $values[3] = 1 - $values[3];
71        } else {
72            $values[3] = 1 - $alpha;
73        }
74
75        return sprintf("\t\t\t<stop id=\"stop%d\" offset=\"%.1f\" style=\"stop-color: rgb(%d, %d, %d); stop-opacity: %.4f;\" />\n", $this->_id++, $offset, $values[0], $values[1], $values[2], $values[3]);
76    }
77
78    protected function _addGradient($string)
79    {
80        $id = 'linearGradient' . $this->_id++;
81
82        $this->_gradients[] = str_replace('[id]', $id, $string);
83        return $id;
84    }
85
86    protected function _addPolygon($string)
87    {
88        $id = 'polygon' . $this->_id++;
89
90        $this->_polygones[] = str_replace('[id]', $id, $string);
91        return $id;
92    }
93
94    public function drawPolygon(Image_3D_Polygon $polygon)
95    {
96
97        $list   = '';
98        $points = $polygon->getPoints();
99        foreach ($points as $point) {
100            $pointarray = $point->getScreenCoordinates();
101
102            $list .= sprintf('%.2f,%.2f ', $pointarray[0], $pointarray[1]);
103        }
104
105        $this->_addPolygon(sprintf("\t<polygon points=\"%s\" style=\"%s\" />\n",
106            substr($list, 0, -1),
107            $this->_getStyle($polygon->getColor())));
108    }
109
110    public function drawGradientPolygon(Image_3D_Polygon $polygon)
111    {
112        $points = $polygon->getPoints();
113
114        $list = '';
115
116        $pointarray = array();
117        foreach ($points as $nr => $point) {
118            $pointarray[$nr] = $point->getScreenCoordinates();
119
120            $list .= sprintf('%.2f,%.2f ', $pointarray[$nr][0], $pointarray[$nr][1]);
121        }
122
123        // Groessen
124        $xOffset = min($pointarray[0][0], $pointarray[1][0], $pointarray[2][0]);
125        $yOffset = min($pointarray[0][1], $pointarray[1][1], $pointarray[2][1]);
126
127        $xSize = max(abs($pointarray[0][0] - $pointarray[1][0]), abs($pointarray[0][0] - $pointarray[2][0]), abs($pointarray[1][0] - $pointarray[2][0]));
128        $ySize = max(abs($pointarray[0][1] - $pointarray[1][1]), abs($pointarray[0][1] - $pointarray[2][1]), abs($pointarray[1][1] - $pointarray[2][1]));
129
130        // Base Polygon
131        $lg = $this->_addGradient(sprintf("\t\t<linearGradient id=\"[id]\" x1=\"%.2f\" y1=\"%.2f\" x2=\"%.2f\" y2=\"%.2f\">\n%s\t\t</linearGradient>\n",
132            ($pointarray[0][0] - $xOffset) / $xSize,
133            ($pointarray[0][1] - $yOffset) / $ySize,
134            ($pointarray[1][0] - $xOffset) / $xSize,
135            ($pointarray[1][1] - $yOffset) / $ySize,
136            $this->_getStop($points[0]->getColor()) . $this->_getStop($points[1]->getColor(), 1)));
137
138        $this->_addPolygon(sprintf("\t<polygon id=\"[id]\" points=\"%s\" style=\"fill: url(#%s); stroke: none; fill-opacity: 1;\" />\n", $list, $lg));
139
140        // Overlay Polygon
141        $lg = $this->_addGradient(sprintf("\t\t<linearGradient id=\"[id]\" x1=\"%.2f\" y1=\"%.2f\" x2=\"%.2f\" y2=\"%.2f\">\n%s\t\t</linearGradient>\n",
142            ($pointarray[2][0] - $xOffset) / $xSize,
143            ($pointarray[2][1] - $yOffset) / $ySize,
144            ((($pointarray[0][0] + $pointarray[1][0]) / 2) - $xOffset) / $xSize,
145            ((($pointarray[0][1] + $pointarray[1][1]) / 2) - $yOffset) / $ySize,
146            $this->_getStop($points[2]->getColor()) . $this->_getStop($points[2]->getColor(), 1, 1)));
147
148        $this->_addPolygon(sprintf("\t<polygon id=\"[id]\" points=\"%s\" style=\"fill: url(#%s); stroke: none; fill-opacity: 1;\" />\n", $list, $lg));
149    }
150
151    public function save($file)
152    {
153        $this->_image .= sprintf("\t<defs id=\"defs%d\">\n", $this->_id++);
154        $this->_image .= implode('', $this->_gradients);
155        $this->_image .= sprintf("\t</defs>\n\n");
156
157        $this->_image .= implode('', $this->_polygones);
158        $this->_image .= "</svg>\n";
159        file_put_contents($file, $this->_image);
160    }
161
162    public function getSupportedShading()
163    {
164        return array(Image_3D_Renderer::SHADE_NO, Image_3D_Renderer::SHADE_FLAT, Image_3D_Renderer::SHADE_GAUROUD);
165    }
166}
167
168?>
169