root/cleversvg/trunk/base/csBaseElement.class.php

Revision 336, 7.0 kB (checked in by nperriault, 10 months ago)

Clever Svg:

  • refs #40: more elements tests
  • Removed depth management, as svg handle it natively

Warning: breaks BC from 0.5.

  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2 /**
3  * SVG Base Element abstract class. Shapes and Groups inherit from this class.
4  *
5  * @author     Nicolas Perriault <nperriault@gmail.com>
6  * @package    cleversvg
7  * @subpackage elements
8  */
9 class csBaseElement
10 {
11
12   protected
13     $dom_document  = null,
14     $attributes    = array(),
15     $styles        = array(),
16     $transforms    = array(),
17     $xml_node_name = 'unknown';
18
19   /**
20    * Manage object cloning
21    *
22    */
23   public function __clone()
24   {
25     $this->deteleAttribute('id');
26   }
27
28   /**
29    * Adds a transformation to current shape
30    *
31    * @param  string  $type    Transform type (matrix, translate, etc...)
32    * @param  array   $params  Parameters of transformation
33    * @link   http://www.w3.org/TR/SVG11/coords.html#TransformAttribute
34    */
35   protected function addTransform($type, $params=array())
36   {
37     static $types = array('matrix',
38                           'translate',
39                           'scale',
40                           'rotate',
41                           'skewX',
42                           'skewY');
43     if (!in_array($type, $types))
44     {
45       throw new csException(sprintf('"%s" is not a valid transform type',
46                                        $type));
47     }
48     $this->transforms[$type] = $params;
49   }
50
51   /**
52    * Computes DOMXML Node
53    *
54    * @param  boolean  $embedded  Is SVG element embedded ?
55    * @return DOMElement
56    */
57   protected function compile($embedded=false)
58   {
59     $dom = $this->getDomDocument();
60     $element_node = $dom->createElement($this->getElementName($embedded));
61
62     // Attributes
63     foreach ($this->attributes as $attr_name => $attr_value)
64     {
65       if (!is_null($attr_value))
66       {
67         switch ($attr_name)
68         {
69           case 'style':
70             $styles = array();
71             if (is_array($attr_value))
72             {
73               foreach ($attr_value as $style_name => $style_value)
74               {
75                 $styles[] = sprintf('%s: %s', $style_name, (string)$style_value);
76               }
77             }
78             if (count($styles) > 0)
79             {
80               $element_node->setAttribute('style', implode('; ', $styles));
81             }
82           break;
83           default:
84             $element_node->setAttribute($attr_name, $attr_value);
85           break;
86         }
87       }
88     }
89
90     // Transformations, if any
91     if (count($this->transforms) > 0)
92     {
93       $transforms = array();
94       foreach ($this->transforms as $transform_name => $transform_params)
95       {
96         $transforms[] = sprintf('%s(%s)',
97                                 $transform_name,
98                                 implode(',', $transform_params));
99
100       }
101       $element_node->setAttribute('transform', implode(' ', $transforms));
102     }
103
104     return $element_node;
105   }
106
107   /**
108    * Gets the current depth
109    *
110    * @return mixed (int depth or NULL)
111    */
112   public function getDepth()
113   {
114     if (array_key_exists('style', $this->attributes) &&
115         array_key_exists('z-index', $this->attributes['style']))
116     {
117       return (int) $this->attributes['style']['z-index'];
118     }
119     else
120     {
121       return null;
122     }
123   }
124
125   /**
126    * Returns a DOM DOcument
127    *
128    * @return DOMDocument
129    */
130   public function getDomDocument()
131   {
132     if (is_null($this->dom_document))
133     {
134       $this->dom_document = new DOMDocument('1.0', 'UTF-8');
135     }
136     return $this->dom_document;
137   }
138
139   /**
140    * Gets the node name of current SVG element
141    *
142    * @param  boolean  $embedded
143    * @return string
144    */
145   public function getElementName($embedded = false)
146   {
147     if ($embedded === true)
148     {
149       $node_name = 'svg:'.$this->xml_node_name;
150     }
151     else
152     {
153       $node_name = $this->xml_node_name;
154     }
155     return $node_name;
156   }
157
158   /**
159    * Specifies a transformation in the form of a transformation matrix of
160    * six values
161    *
162    * @param  int  $a
163    * @param  int  $b
164    * @param  int  $c
165    * @param  int  $d
166    * @param  int  $e
167    * @param  int  $f
168    */
169   public function matrix($a, $b, $c, $d, $e, $f)
170   {
171     $this->addTransform('matrix', array($a, $b, $c, $d, $e, $f));
172   }
173
174   /**
175    * Rotates shape
176    *
177    * @param  int  $angle
178    * @param  int  $cx
179    * @param  int  $cy
180    */
181   public function rotate($angle, $cx=0, $cy=0)
182   {
183     $this->addTransform('rotate', array($angle, $cx, $cy));
184   }
185
186   /**
187    * Scales shape
188    *
189    * @param  int  $xscale
190    * @param  int  $yscale
191    */
192   public function scale($xscale, $yscale=null)
193   {
194     $params = array($xscale);
195     if ($yscale)
196     {
197       $params[] = $yscale;
198     }
199     $this->addTransform('scale', $params);
200   }
201
202   /**
203    * Specifies a skew transformation along the x-axis
204    *
205    * @param  int  $angle
206    */
207   public function skewX($angle)
208   {
209     $this->addTransform('skewX', array($angle));
210   }
211
212   /**
213    * Specifies a skew transformation along the y-axis
214    *
215    * @param  int  $angle
216    */
217   public function skewY($angle)
218   {
219     $this->addTransform('skewY', array($angle));
220   }
221
222   /**
223    * Translates shape
224    *
225    * @param  int  $tx
226    * @param  int  $ty
227    */
228   public function translate($tx, $ty=null)
229   {
230     $params = array($tx);
231     if ($ty)
232     {
233       $params[] = $ty;
234     }
235     $this->addTransform('translate', $params);
236   }
237
238   /**
239    * Deletes an attribute
240    *
241    */
242   protected function deteleAttribute($name)
243   {
244     if (array_key_exists($name, $this->attributes))
245     {
246       unset($this->attributes[$name]);
247     }
248   }
249
250   /**
251    * Sets an attribute for current element
252    *
253    * @param  string  $name
254    * @param  mixed   $value
255    * @param  string  $default  Default value
256    */
257   protected function setAttribute($name, $value, $default=null)
258   {
259     if (!is_null($default) && is_null($value))
260     {
261       $value = $default;
262     }
263     if (!is_null($value))
264     {
265       $this->attributes[strtolower($name)] = $value;
266     }
267   }
268
269   /**
270    * Sets the depth of object
271    *
272    * @param  int  $depth
273    */
274   public function setDepth($depth)
275   {
276     if (is_null($depth))
277     {
278       unset($this->attributes['style']['z-index']);
279     }
280     elseif (is_int($depth))
281     {
282       $this->attributes['style']['z-index'] = (string) $depth;
283     }
284   }
285
286   /**
287    * Gets the DOM id of current element tag
288    *
289    * @return mixed (string id or NULL)
290    */
291   public function getId()
292   {
293     if (isset($this->attributes['id']))
294     {
295       return $this->attributes['id'];
296     }
297     else
298     {
299       return null;
300     }
301   }
302
303   /**
304    * Sets the DOM id of current element tag
305    *
306    * @param  string  $id
307    */
308   public function setId($id)
309   {
310     if (is_string($id) && trim($id) != '')
311     {
312       $this->setAttribute('id', $id);
313     }
314   }
315
316   /**
317    * Sets a SVG style via an associative array
318    *
319    * @param  array  $style
320    */
321   public function setStyle($style)
322   {
323     // Styles properties bellow should be treated as attributes and not
324     // in a style attribute (FF 1.5 compat)
325     $convert_styles = array('stroke', 'stroke-width', 'fill');
326     foreach ($style as $style_name => $style_value)
327     {
328       if (in_array($style_name, $convert_styles))
329       {
330         $this->setAttribute($style_name, $style_value);
331         unset($style[$style_name]);
332       }
333     }
334     if (count($style) > 0)
335     {
336       $this->setAttribute('style', $style);
337     }
338   }
339
340 }
341
Note: See TracBrowser for help on using the browser.