fix svgtopdf
[pear] / XML / SvgToPdfAlt / Text.php
1 <?php
2
3
4 class XML_SvgToPDFAlt_Text  extends XML_SvgToPDFAlt_Base { 
5
6     function fromNode($node) {
7         parent::fromNode($node);
8         if (!isset($this->children[0]->content)) {
9             return;
10         }
11         if (substr($this->children[0]->content,0,2) == '==') {
12             $this->style['text-anchor'] = 'justify';
13             $this->children[0]->content = substr($this->children[0]->content,2);
14         }
15     }
16       
17     function transform() {
18         parent::transform();
19         if (!@$this->transform) {
20             return; 
21         }
22         if (preg_match('/scale\(([0-9e.-]+),([0-9e.-]+)\)/',$this->transform,$args)) {
23                   $xscale = $args[1];
24                   $yscale = $args[2];
25           $this->style['font-size'] *= $args[1];
26         }
27     }
28     
29         
30         
31
32     function writePDF($pdf,$data) {
33         // set up font.. 
34          
35         $font = strtolower($this->style['font-family']);
36         
37         static $map = array(
38             'times new roman' => 'times',
39             'courier new' => 'courier',
40             'arial' => 'arial',
41         );
42         if (isset($map[$font])) {
43             $font = $map[$font];
44         } else {
45             $font = 'times';
46         }
47         if (preg_match('/big5/i',$this->style['font-family'])) {
48             $font = 'Big5';
49         }
50             
51         
52         
53         $weight =  '';
54         if ($this->style['font-weight'] == 'bold') {
55             $weight .=  'B';
56         }
57         if (@$this->style['font-style'] == 'italic') {
58             $weight .=  'I';
59         }
60         
61         if (@$this->style['text-decoration'] == 'underline') {
62             $weight .=  'U';
63         }
64         // size..
65         $size = $this->style['font-size']  * 0.85;
66         
67         $pdf->setFont($font,$weight,$size);
68      
69         switch(@$this->style['text-anchor']) {
70             case 'end':
71                 $align = 'E';
72                 break;
73             case 'middle':
74                 $align = 'M';
75                 break;
76             case 'justify':
77                 $align = 'J';
78                 $max = 0;
79                 foreach ($this->children as $child) {
80                     if (!@$child->content) {
81                         continue;
82                     }
83                     $l = $pdf->getStringWidth($child->content);
84                     $max = ($l > $max) ? $l : $max;
85                 }
86                 // fudge factor!
87                 $this->justifyLen = $max;
88                 break;
89             default:
90                 $align = 'L';
91             
92         }
93         
94         $f = $this->toColor(@$this->style['fill']);
95         if ($f) {
96             $pdf->setTextColor($f[0],$f[1],$f[2]);
97         }
98      
99      
100      
101         $yoffset = 0;
102         $x =  $this->x   + @$this->xx;
103         $y =  $this->y  + @$this->yy;
104         if (!@$this->children) {
105             return;
106         }
107         $lineno = 0;
108         foreach($this->children as $i=>$c) {
109         
110             $xx = isset($c->x) ? $c->x + @$this->xx : $x;
111             $yy = isset($c->y) ? $c->y + @$this->yy : $y + ($lineno * $size * 1.3);
112             $lineno++;              
113             $val = isset($c->content) ? $c->content : '';
114             
115             if (isset($c->args)) {
116                 
117                 $args = array();
118                 foreach($c->args as $v) {
119                     if ($v == 'page') {
120                         $args[] = $pdf->PageNo();
121                         continue;
122                     }
123                     if ($v == 'nb') {
124                         $args[] = '{nb}';
125                         continue;
126                     }
127                     $args[] = $this->getValue($data,trim($v));
128                 }
129                 
130                 $has_template = preg_match('/%s/', $val);
131                      
132                 $val = vsprintf($val,$args);
133                 
134                if ($has_template && ($font == 'Big5')) {
135                     require_once  'Text/ZhDetect.php';
136                     $detect = new Text_zhDetect;
137                     $type = $detect->guess($val);
138                     if ($v == 'S') {
139                        
140                         $val = @iconv('utf8', 'GB2312//IGNORE', $val);
141                         $pdf->setFont('GB' ,
142                             $weight,
143                             $size);
144                     } else {
145                                                 $vv = $val;
146                         $val = @iconv('utf8', 'BIG5//IGNORE', $val);
147                                                 //var_dump(array($vv, $val));
148                         $pdf->setFont('Big5' ,
149                             $weight,
150                             $size);
151                    }
152                  }
153                 
154                 /*
155                 
156                 
157                 if ($has_template  && ($font == 'Big5')) {
158                    
159                     
160                     $val =    @iconv('utf8', 'utf16be//TRANSLIT', $val);
161                     
162                     $pdf->setFont('Uni-hw' ,
163                         $weight,
164                         $size);
165                 }
166                 */
167             }
168             
169             $talign = $align;
170             if ((empty($this->children[$i+1]) ||  !isset($this->children[$i+1]->content) || !strlen(trim($this->children[$i+1]->content))) && ($align == 'J')) {
171                 $talign = 'L';
172             }
173             
174             
175              
176             
177             
178             
179             $yoffset += $this->multiLine($pdf,explode("\n",$val),
180                     $xx/ 3.543307,
181                     ($yy / 3.543307) + $yoffset,
182                     ($size / 3.543307) + 1,
183                     $talign
184                 );
185             
186              
187         }
188         
189         // now daraw
190     
191     }
192     
193     /**
194     * get a value from the data
195     *
196     * eg. $data = array(
197     *     'fred' => 'somevalue'
198     *
199     *  getValue ($data,'fred') returns 'somevalue' 
200     * 
201     * value can also be a method = eg. getFred()
202     *
203     * @param   object|array $data 
204     * @param   string $v key to get.
205     * 
206     *
207     * @return   string
208     * @access   public
209     */
210   
211     function iconvert($str) {
212         if (is_object($str) || is_array($str)) {
213             return $str;
214         }
215         return  $str ;//. ' - ' . @iconv( "UTF-8" , "Big5//IGNORE", $str  );
216     }
217   
218     function getValue($data,$v) {
219         
220         // not a method:
221         
222         if ($v[strlen($v)-1]  != ')') {
223             $data = (array) $data;
224             if (false === strpos($v,'.')) {
225                 if (!isset($data[$v])) {
226                     return '';
227                 }
228                 if (is_array($data[$v]) || is_object($data[$v])) {
229                     return '';
230                 }
231                 
232                 return $this->iconvert(@$data[$v]);
233             }
234             $dd = (array)$data;
235             foreach(explode('.', $v) as $vv) {
236                 if (!is_array($dd)) {
237                     return '';   
238                 }
239                 if (!isset($dd[$vv])) {
240                     return '';
241                 }
242                 $dd = is_object($dd[$vv]) ? ((array) $dd[$vv]) : $this->iconvert($dd[$vv]);
243             }
244             //echo "ATTEMPT: $v: got $dd\n";
245             //exit;
246             if (is_array($dd) || is_object($dd)) {
247                 return '';
248             }
249             return $this->iconvert($dd);
250         }
251         // method !!!
252         if (!is_object($data)) {
253             return '';
254         }
255         $method = substr($v,0,-2);
256         if (is_callable(array($data,$method))) {
257             $ret = $data->$method();
258             if (is_array($ret) || is_object($ret)) {
259                 return '';
260             }
261             // not in original!!!
262             return $this->iconvert($ret);
263         }
264         //echo 
265         //print_r($data);
266         
267         //exit;
268         return "no method $method in ".get_class($data);
269     
270     
271     }
272     
273     
274     function breakLines(&$pdf,$str,$x,$y,$h,$align) {
275         // do the estimation...
276         $len = strlen($str);
277  
278         $total = $pdf->getStringWidth($str . '      ');
279          
280         $charsize = $total/$len;
281         
282         $max_chars = floor(($this->maxWidth / 3.543307) / $charsize);
283         //echo "LEN: $len, $total, $charsize, $max_chars";
284         $lines = explode("\n",wordwrap($str,$max_chars));
285          
286         return $this->multiLine($pdf,$lines,$x,$y,$h,$align);
287     }
288     
289     function multiLine(&$pdf,$lines,$x,$y,$h,$align) {
290         // now dealing with mm
291         XML_SvgToPDFAlt::debug("MULTILINE '" .implode("\n",$lines) . "' $x, $y, $h");
292         $yoffset  = 0;
293         $line = -1;
294         foreach ($lines as $l=>$v) {
295             $line++;
296             if (@$this->maxWidth && ($pdf->getStringWidth($v) > ($this->maxWidth / 3.543307))) {
297                 $yoffset += $this->breakLines($pdf,$v,$x,$y + ($l * $h) + $yoffset, $h,$align);
298                 continue;
299             }
300             
301             $xoffset = 0;
302             if ($align == 'M') { // center
303                 $xoffset = -1 * ($pdf->getStringWidth($v) / 2);
304             }
305             if ($align == 'E') { // right/end
306                 $xoffset = -1 * $pdf->getStringWidth($v);
307             }
308            
309             if ($align == 'J' ) { // justified (eg. started with ==
310                 $this->justify($pdf, $x , $y + ($l * $h) + $yoffset , $v, $this->justifyLen);
311                 continue;
312             }
313             XML_SvgToPDFAlt::debug("TEXT:   " . ( $xoffset + $x ) . "," .
314                 ($y + ($l * $h) + $yoffset) . "," . 
315                 $v);
316             
317             $pdf->text(
318                 $xoffset + $x ,
319                 $y + ($l * $h) + $yoffset ,
320                 $v);
321                 
322         }
323         return   ($l * $h) + $yoffset;
324         
325     }
326         
327         
328     function justify(&$pdf,$x,$y,$text,$len) {
329         if (!strlen(trim($text))) {
330             return;
331         }
332         $bits = explode(' ', $text);
333         $textlen = $pdf->getStringWidth(implode('',$bits));
334         $spacesize = ($len - $textlen) / (count($bits) -1);
335         foreach($bits as $word) {
336             $pdf->text($x , $y ,$word );
337             $x += $spacesize + $pdf->getStringWidth($word);
338         }
339     }
340         
341      
342
343 }