05ebfcbebd1f54827c5c86e2864c277b55205dda
[pear] / XML / SvgToPdf / Base.php
1 <?php
2
3 /*
4 The base node includes:
5     fromNode - convert the XML_Tree node into object with vars
6         (and parse styles)
7     
8     // iternate tree with writePDF
9     writePDF($pdf,$data) 
10     childrenWritePDF($pdf,$data)  
11
12     // shift coordinates of group dynamic elements 
13     // so the x is relative to the block corner.
14     shiftChildren($x,$y) {
15     shift($x,$y) 
16     
17     // find a dynamic block and calculate how much data it can hold.
18     // so you know how many pages are needed.
19     calcPerPage()
20 */
21
22 class XML_SvgToPDF_Base { 
23
24     var $x = 0;
25     var $y = 0;
26     var $width = 0; // used in svg..
27     var $height= 0; 
28     
29     var $style = array();
30     var $children = array();
31     
32     var $transform = '';
33     var $id;
34     var $nodetypes;
35     var $version;
36     var $docname;
37     var $docbase;
38     var $sodipodirole;
39     var $sodipodilinespacing;
40     var $sodipodinonprintable;
41     var $sodipodinodetypes;
42     var $sodipodiversion;
43     var $sodipodidocname;
44     var $sodipodidocbase;
45     var $sodipodi;
46     var $xmlnssodipodi;
47     var $xmlns;
48     var $xmlnsxlink;
49     var $xmlnsinkscape;
50     var $inkscape;     
51     var $inkscapeversion;
52     var $xmlnsrdf;
53     var $xmlnscc;
54     var $xmlnsdc;
55     
56     var $xlink;
57     var $rdf;
58     var $cc;
59     var $dc;
60     var $d;
61     var $content = '';
62     var $role;
63     var $linespacing;
64     var $attributes;
65     var $nonprintable;
66     var $about;
67     var $resource;
68     
69     
70     var $name;
71     
72     static function factory($node)
73     {
74         if (is_a($node, 'XML_SvgToPDF_Base')) {
75             return $node;
76         }
77         
78         $class = 'XML_SvgToPDF_'.$node->name;
79         /*
80         if (strlen(trim($node->content)) && (@$this->language)) {
81             $node->language = $this->language;
82         }
83         */
84  
85
86         //echo "look for $class?";
87         if (!class_exists($class)) {
88             // try loading it..
89             $file = dirname(__FILE__) .'/'.ucfirst(strtolower($node->name)). '.php';
90            
91             if (file_exists($file)) {
92                 require_once 'XML/SvgToPdf/'.ucfirst(strtolower($node->name)) . '.php';
93             }
94         }
95         // now if it doesnt exist..
96         if (!class_exists($class)) {
97             
98            $class = 'XML_SvgToPDF_Base';
99         }
100         $r = new $class;
101         $r->fromNode($node);
102         return $r;
103     }
104     
105     function factoryChildren($ar) {
106         foreach($ar as $c) {
107             if (!empty($c)) {
108                 $this->children[] = $this->factory($c);
109             }
110         }
111     }
112     
113     
114     function fromXmlNode(DomElement $node)
115     {
116         // extract attributes
117         foreach($node->attributes as $k=>$v) {
118             if (in_array($k, array('style'))) {
119                 continue;
120             }
121             $k = preg_replace('/[^a-z]+/', '', $k);
122             
123             $v = is_object($v) ? $v->value : $v;
124             if (preg_match('/[0-9]+mm$/',$v)) {
125                 $vv = str_replace('mm','',$v);
126                 $vv = $vv * 3.543307;
127                 
128                 $this->$k = $vv;
129                 continue;
130             }
131             
132             $this->$k = $v;
133         }
134         // deal with style..
135         if ($node->hasAttribute('style') && strlen($node->getAttribute('style'))) {
136             
137             $s = explode(';',$node->getAttribute('style'));
138             foreach($s as $ss) {
139                 if (!strlen(trim($ss))) {
140                     continue;
141                 }
142                
143                 $sss = explode(':',$ss);
144                 if (preg_match('/[0-9]+pt$/',$sss[1])) {
145                     $sss[1] =  str_replace('pt','',$sss[1]);
146                 }
147                 $style[$sss[0]] = $sss[1];
148             }
149             $this->style = $style;
150         }
151         $this->name = $node->tagName;
152         
153         //?? needed?
154         if ($node->children) {
155             $this->factoryChildren($node->children);
156         }
157         
158         $this->transform();
159         
160         
161         // if node is a tspan  
162        
163          
164          
165     }
166     
167     
168     function fromNode($node) {
169         
170         if ($node->attributes) {
171             foreach($node->attributes as $k=>$v) {
172                 
173                 //echo $node->name . ":" . $k . "=>". $v. "<BR>";
174                 
175                 if (strpos($k,':')) {
176                     $kk = explode(':',$k);
177                     $k = $kk[1];
178                 }
179                 $this->$k = $v;
180                 if (preg_match('/[0-9]+mm$/',$v)) {
181                     $v = str_replace('mm','',$v);
182                     $v = $v * 3.543307;
183                     
184                     $this->$k = $v;
185                     continue;
186                 }
187                 
188             }
189         }
190         
191         if (isset($this->style) && is_string($this->style)) {
192             
193             $s = explode(';',$this->style);
194             foreach($s as $ss) {
195                 if (!strlen(trim($ss))) {
196                     continue;
197                 }
198                 if (strpos($ss,':') === false) {
199                     $style[$ss] = true;
200                     continue;
201                 }
202                 $sss = explode(':',$ss);
203                 if (preg_match('/[0-9]+pt$/',$sss[1])) {
204                     $sss[1] =  str_replace('pt','',$sss[1]);
205                 }
206                 $style[$sss[0]] = $sss[1];
207             }
208             $this->style = $style;
209         }
210                 
211         $this->name = $node->name;
212         
213         if ($node->content) {
214             $this->content = trim($node->content);
215             //echo $node->name . ":CONTENT=>". $node->content. "<BR>";
216         }
217         
218         if ($node->children) {
219             $this->factoryChildren($node->children);
220         }
221        // echo "<PRE>BEFORE:";print_r($this->toArray());
222         $this->transform();
223         //echo "<PRE>AFTER:";print_r($this->toArray());
224     }
225
226
227     function transform() {
228         if (empty($this->transform)) {
229             return;
230         }
231         // do not transform tspans -- done by overwriting this...
232         //if ($this->x === false) {
233         //    return;
234        // }
235         
236         // deal with transformation..
237         $tr = $this->transform;
238         if (preg_match('/scale\(([0-9e.-]+),([0-9e.-]+)\)/',$tr,$args)) {
239             $xscale = $args[1];
240             $yscale = $args[2];
241             $method = 'scale';
242             } else if (preg_match('/matrix\(([0-9e.-]+),([0-9e.-]+),([0-9e.-]+),([0-9e.-]+),([0-9e.-]+),([0-9e.-]+)\)/',$tr,$args)) {
243             array_shift($args);
244             require_once 'Math/Matrix.php';
245             $matrix =  new Math_Matrix( array(
246                     array($args[0],$args[2],$args[4]),
247                     array($args[1],$args[3],$args[5]),
248                     array(       0,       0,    1))
249             );
250             $method = 'matrix';
251         } else if (preg_match('/translate\(([0-9e.-]+),([0-9e.-]+)\)/',$tr,$args)) {
252             $x = $args[1];
253             $y = $args[2];
254             $method = 'translate';
255         } else {
256             echo "<PRE>no match?";print_r($this); exit;
257             return;
258         }
259         //
260         switch ($method) {
261             case 'scale':
262                 $this->x *=  $xscale;
263                 $this->y *=  $yscale;
264                 if (empty($this->children)) {
265                     return;
266                 }
267                 foreach(array_keys($this->children) as $i) {
268                     if ($this->children[$i]->x === false) {
269                         continue;
270                         // echo "<PRE>";print_r($this);exit;
271                     }
272                     $this->children[$i]->x *=  $xscale;
273                     $this->children[$i]->y *=  $yscale;
274                 }
275                 break;
276             case 'matrix':
277                 $v = new Math_Vector(array($this->x,$this->y,0));
278                 
279                 $r = $matrix->vectorMultiply($v);
280                 $r = $r->getData();
281                 $this->x = $r[0];
282                 $this->y = $r[1];
283                 //echo "<PRE>";var_dump(        $r);exit;
284                 if (empty($this->children)) {
285                     return;
286                 }
287                 foreach(array_keys($this->children) as $i) {
288                     if ($this->children[$i]->x === false) {
289                         continue;
290                         // echo "<PRE>";print_r($this);exit;
291                     }
292                     $v = new Math_Vector(array($this->children[$i]->x,$this->children[$i]->y,0));
293                     $r =  $matrix->vectorMultiply($v);
294                     $r = $r->getData();
295                     $this->children[$i]->x = $r[0];
296                     $this->children[$i]->y = $r[1];
297      
298                 }
299                 break; 
300             case 'translate':
301                 if ($this->x !== false &&  $this->y !== false) {
302                          
303                    $this->x +=  $x;
304                    $this->y +=  $y;
305                 }
306                 if (empty($this->children)) {
307                     return;
308                 }
309                 foreach(array_keys($this->children) as $i) {
310                     if ($this->children[$i]->x === false || $this->children[$i]->y === false) {
311                         continue;
312                         // echo "<PRE>";print_r($this);exit;
313                     }
314                     $this->children[$i]->x +=  $x;
315                     $this->children[$i]->y +=  $y;
316                 }
317                 break; 
318                  
319           }
320      }
321
322
323
324
325     
326     function writePDF($pdf,$data) {
327         $this->childrenWritePDF($pdf,$data);
328     }
329     
330     function childrenWritePDF($pdf,&$data) {
331         if (!@$this->children) {
332             return;
333         }
334         foreach(array_keys($this->children) as $k) {
335             if (empty($this->children[$k])) {
336                 continue;
337             }
338             if (!method_exists($this->children[$k],'writePDF')) {
339                 echo '<PRE>'; print_r(array($this, $k));  
340                 trigger_error( "OOPS unknown object?" ); 
341             }
342             $this->children[$k]->writePDF($pdf,$data);
343         }
344     }
345     
346     
347     // add the values to the children..
348     function shiftChildren($x,$y) {
349         if (empty($this->children)) {
350             return;
351         }
352         foreach(array_keys($this->children) as $k) {
353             if (!$this->children[$k]) {
354                 continue;
355             }
356             $this->children[$k]->shift($x,$y);
357         }
358     }
359     
360     function shift($x,$y) {
361         //XML_SvgToPDF::debug('shift');
362         //XML_SvgToPDF::debug(array($x,$y));
363         //XML_SvgToPDF::debug($this);
364         
365         if ($x === false) {
366             return;
367         }
368         
369         //var_dump(array("SHIFT", $x, $y, "TO: ", $this->x , $this->y));
370         if ($this->x !== false) {
371             $this->x += $x;
372         }
373         if ($this->y !== false) {
374             $this->y += $y;
375         }
376         //XML_SvgToPDF::debug($this);
377         $this->shiftChildren($x,$y);
378     }
379     function calcPerPage() {
380         $ret = array();
381         foreach($this->children as $n) {
382             if (!$n) {
383                 continue;
384             }
385             if (!is_a($n, 'XML_SvgToPDF_G')) {
386                 continue;
387             }
388             if (!isset($n->settings) || !isset($n->settings['dynamic']))  {
389                 continue;
390             }
391             
392             
393             $rows  = isset($n->settings['rows']) ? $n->settings['rows'] : 1;
394             $cols  = isset($n->settings['cols']) ? $n->settings['cols'] : 1;
395            // return array($n->settings['dynamic'], $rows * $cols);
396
397              
398             $ret[$n->settings['dynamic']] =  $rows * $cols;
399             
400             
401             
402             
403         }
404         //return array('',0);
405
406         return $ret;
407          
408     
409     
410     
411     
412     }
413     
414     function toColor($color) {
415         if (!$color || ($color == 'none')) {
416             return false;
417         }
418         
419         if ($color == 'black') {
420             $color = '#000000';
421         }
422         
423         return array(
424             hexdec(substr($color,1,2)),
425             hexdec(substr($color,3,2)),
426             hexdec(substr($color,5,2)));
427         
428     }
429     function toArray()
430     {
431         $ret = array();
432         $ar = (array) $this;
433         $ret['__CLASS__'] = get_class($this);
434         foreach($ar as $k=>$v) {
435             if (is_array($v) || is_object($v)) {
436                 $ret[$k] = "**ARRAY|OBJECT**";
437                 continue;
438             }
439             $ret[$k] = $v;
440         }
441         return $ret;    
442     }
443     
444     
445     
446     
447 }