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