Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */
3
/**
4
* ASCII art text creation
5
*
6
* Project home page (Russian): http://bolknote.ru/files/figlet/
7
*
8
* PHP Version 4
9
*
10
* @category Text
11
* @package  Text_Figlet
12
* @author   Evgeny Stepanischev <imbolk@gmail.com>
13
* @author   Christian Weiske <cweiske@php.net>
14
* @license  http://www.php.net/license PHP License
15
* @version  CVS: $Id$
16
* @link     http://pear.php.net/package/Text_Figlet
17
*/
18
require_once 'PEAR.php';
19
 
20
/**
21
* ASCII art text creation
22
*
23
* Project home page (Russian): http://bolknote.ru/files/figlet/
24
*
25
* PHP Version 4
26
*
27
* @category Text
28
* @package  Text_Figlet
29
* @author   Evgeny Stepanischev <imbolk@gmail.com>
30
* @author   Christian Weiske <cweiske@php.net>
31
* @license  http://www.php.net/license PHP License
32
* @link     http://pear.php.net/package/Text_Figlet
33
*/
34
class Text_Figlet
35
{
36
    /**
37
     * Height of a letter
38
     *
39
     * @var integer
40
     *
41
     * @access protected
42
     */
43
    var $height;
44
 
45
    /**
46
     * Letter baseline
47
     *
48
     * @var integer
49
     *
50
     * @access protected
51
     */
52
    var $oldlayout;
53
 
54
    /**
55
     * Flag - RTL (right to left) or LTR (left to right) text direction
56
     *
57
     * @var integer
58
     *
59
     * @access protected
60
     */
61
    var $rtol;
62
 
63
    /**
64
     * Information about special 'hardblank' character
65
     *
66
     * @var integer
67
     *
68
     * @access protected
69
     */
70
    var $hardblank;
71
 
72
    /**
73
     * Is used for keeping font
74
     *
75
     * @var array
76
     *
77
     * @access protected
78
     */
79
    var $font;
80
 
81
    /**
82
     * Flag is true if smushing occured in letters printing cycle
83
     *
84
     * @var integer
85
     *
86
     * @access protected
87
     */
88
    var $smush_flag;
89
 
90
    /**
91
     * Comment lines buffer
92
     *
93
     * @var string
94
     *
95
     * @access public
96
     */
97
 
98
    var $font_comment;
99
 
100
 
101
    /**
102
     * Load user font. Must be invoked first.
103
     * Automatically tries the Text_Figlet font data directory
104
     *  as long as no path separator is in the filename.
105
     *
106
     * @param string $filename   font file name
107
     * @param bool   $loadgerman (optional) load German character set or not
108
     *
109
     * @access public
110
     * @return mixed PEAR_Error or true for success
111
     */
112
    function loadFont($filename, $loadgerman = true)
113
    {
114
        $this->font = array();
115
        if (!file_exists($filename)) {
116
            //if it does not exist, try the Text_Figlet data directory
117
            include_once 'PEAR/Config.php';
118
 
119
            $config  = PEAR_Config::singleton();
120
            $fontdir = $config->get('data_dir') . '/Text_Figlet/fonts/';
121
 
122
            //only for filenames without path separators
123
            if (strpos($filename, '/') === false
124
                && file_exists($fontdir . $filename)
125
            ) {
126
                $filename = $fontdir . $filename;
127
            } else {
128
                return PEAR::raiseError('Figlet font file "'
129
                                        . $filename
130
                                        . '" cannot be found', 1);
131
            }
132
        }
133
 
134
        $this->font_comment = '';
135
 
136
        // If Gzip compressed font
137
        if (substr($filename, -3, 3) == '.gz') {
138
            $filename   = 'compress.zlib://' . $filename;
139
            $compressed = true;
140
 
141
            if (!function_exists('gzcompress')) {
142
                return PEAR::raiseError('Cannot load gzip compressed fonts since'
143
                                        . ' gzcompress() is not available.',
144
                                        3);
145
            }
146
        } else {
147
            $compressed = false;
148
        }
149
 
150
        if (!($fp = fopen($filename, 'rb'))) {
151
            return PEAR::raiseError('Cannot open figlet font file ' . $filename, 2);
152
        }
153
 
154
        if (!$compressed) {
155
            /* ZIPed font */
156
            if (fread($fp, 2) == 'PK') {
157
                if (!function_exists('zip_open')) {
158
                    return PEAR::raiseError('Cannot load ZIP compressed fonts since'
159
                                            . ' ZIP PHP extension is not available.',
160
                                            5);
161
                }
162
 
163
                fclose($fp);
164
 
165
                if (!($fp = zip_open($filename))) {
166
                    return PEAR::raiseError('Cannot open figlet font file ' . $filename, 2);
167
                }
168
 
169
                $name = zip_entry_name(zip_read($fp));
170
                zip_close($fp);
171
 
172
                if (!($fp = fopen('zip://' . realpath($filename) . '#' . $name, 'rb'))) {
173
                    return PEAR::raiseError('Cannot open figlet font file ' . $filename, 2);
174
                }
175
 
176
                $compressed = true;
177
            } else {
178
                flock($fp, LOCK_SH);
179
                rewind($fp);
180
            }
181
        }
182
 
183
        //            flf2a$ 6 5 20 15 3 0 143 229
184
        //              |  | | | |  |  | |  |   |
185
        //             /  /  | | |  |  | |  |   \
186
        //    Signature  /  /  | |  |  | |   \   Codetag_Count
187
        //      Hardblank  /  /  |  |  |  \   Full_Layout
188
        //           Height  /   |  |   \  Print_Direction
189
        //           Baseline   /    \   Comment_Lines
190
        //            Max_Length      Old_Layout
191
 
192
 
193
        $header = explode(' ', fgets($fp, 2048));
194
 
195
        if (substr($header[0], 0, 5) <> 'flf2a') {
196
            return PEAR::raiseError('Unknown FIGlet font format.', 4);
197
        }
198
 
199
        @list ($this->hardblank, $this->height,,,
200
        $this->oldlayout, $cmt_count, $this->rtol) = $header;
201
 
202
        $this->hardblank = substr($this->hardblank, -1, 1);
203
 
204
        for ($i = 0; $i < $cmt_count; $i++) {
205
            $this->font_comment .= fgets($fp, 2048);
206
        }
207
 
208
        // ASCII charcters
209
        for ($i = 32; $i < 127; $i++) {
210
            $this->font[$i] = $this->_char($fp);
211
        }
212
 
213
        foreach (array(196, 214, 220, 228, 246, 252, 223) as $i) {
214
            if ($loadgerman) {
215
                $letter = $this->_char($fp);
216
 
217
                // Invalid character but main font is loaded and I can use it
218
                if ($letter === false) {
219
                    fclose($fp);
220
                    return true;
221
                }
222
 
223
                // Load if it is not blank only
224
                if (trim(implode('', $letter)) <> '') {
225
                    $this->font[$i] = $letter;
226
                }
227
            } else {
228
                $this->_skip($fp);
229
            }
230
        }
231
 
232
        // Extented characters
233
        for ($n = 0; !feof($fp); $n++) {
234
            list ($i) = explode(' ', rtrim(fgets($fp, 1024)), 2);
235
            if ($i == '') {
236
                continue;
237
            }
238
 
239
            // If comment
240
            if (preg_match('/^\-0x/i', $i)) {
241
                $this->_skip($fp);
242
            } else {
243
                // If Unicode
244
                if (preg_match('/^0x/i', $i)) {
245
                    $i = hexdec(substr($i, 2));
246
                } else {
247
                    // If octal
248
                    if ($i{0} === '0' && $i !== '0' || substr($i, 0, 2) == '-0') {
249
                        $i = octdec($i);
250
                    }
251
                }
252
 
253
                $letter = $this->_char($fp);
254
 
255
                // Invalid character but main font is loaded and I can use it
256
                if ($letter === false) {
257
                    fclose($fp);
258
                    return true;
259
                }
260
 
261
                $this->font[$i] = $letter;
262
            }
263
        }
264
 
265
        fclose($fp);
266
        return true;
267
    }
268
 
269
 
270
 
271
    /**
272
    * Print string using font loaded by LoadFont method
273
    *
274
    * @param string $str    string for printing
275
    * @param bool   $inhtml (optional) output mode
276
    *                       - HTML (true) or plain text (false)
277
    *
278
    * @access public
279
    * @return string contains
280
    */
281
    function lineEcho($str, $inhtml = false)
282
    {
283
        $out = array();
284
 
285
        for ($i = 0; $i<strlen($str); $i++) {
286
            // Pseudo Unicode support
287
            if (substr($str, $i, 2) == '%u') {
288
                $lt = hexdec(substr($str, $i+2, 4));
289
                $i += 5;
290
            } else {
291
                $lt = ord($str{$i});
292
            }
293
 
294
            $hb = preg_quote($this->hardblank, '/');
295
            $sp = "$hb\\x00\\s";
296
 
297
            // If chosen character not found try to use default
298
            // If default character is not defined skip it
299
 
300
            if (!isset($this->font[$lt])) {
301
                if (isset($this->font[0])) {
302
                    $lt = 0;
303
                } else {
304
                    continue;
305
                }
306
            }
307
 
308
            for ($j = 0; $j < $this->height; $j++) {
309
                $line = $this->font[$lt][$j];
310
 
311
                // Replace hardblanks
312
                if (isset($out[$j])) {
313
                    if ($this->rtol) {
314
                        $out[$j] = $line . $out[$j];
315
                    } else {
316
                        $out[$j] .= $line;
317
                    }
318
                } else {
319
                    $out[$j] = $line;
320
                }
321
            }
322
 
323
            if ($this->oldlayout > -1 && $i) {
324
                // Calculate minimal distance between two last letters
325
 
326
                $mindiff = -1;
327
 
328
                for ($j = 0; $j < $this->height; $j++) {
329
                    if (preg_match("/\S(\s*\\x00\s*)\S/", $out[$j], $r)) {
330
                        if ($mindiff == -1) {
331
                            $mindiff = strlen($r[1]);
332
                        } else {
333
                            $mindiff = min($mindiff, strlen($r[1]));
334
                        }
335
                    }
336
                }
337
 
338
                // Remove spaces between two last letter
339
                // dec mindiff for exclude \x00 symbol
340
 
341
                if (--$mindiff > 0) {
342
                    for ($j = 0; $j < $this->height; $j++) {
343
                        if (preg_match("/\\x00(\s{0,{$mindiff}})/", $out[$j], $r)) {
344
                            $l       = strlen($r[1]);
345
                            $b       = $mindiff - $l;
346
                            $out[$j] = preg_replace("/\s{0,$b}\\x00\s{{$l}}/",
347
                                                    "\0",
348
                                                    $out[$j],
349
                                                    1);
350
                        }
351
                    }
352
                }
353
                // Smushing
354
 
355
                $this->smush_flag = 0;
356
 
357
                for ($j = 0; $j < $this->height; $j++) {
358
                    $out[$j] = preg_replace_callback("#([^$sp])\\x00([^$sp])#",
359
                                                     array(&$this, '_rep'),
360
                                                     $out[$j]);
361
                }
362
 
363
                // Remove one space if smushing
364
                // and remove all \x00 except tail whenever
365
 
366
                if ($this->smush_flag) {
367
                    $pat = array("/\s\\x00(?!$)|\\x00\s/", "/\\x00(?!$)/");
368
                    $rep = array('', '');
369
                } else {
370
                    $pat = "/\\x00(?!$)/";
371
                    $rep = '';
372
                }
373
 
374
                for ($j = 0; $j<$this->height; $j++) {
375
                    $out[$j] = preg_replace($pat, $rep, $out[$j]);
376
                }
377
            }
378
        }
379
 
380
        $trans = array("\0" => '', $this->hardblank => ' ');
381
        $str   = strtr(implode("\n", $out), $trans);
382
 
383
        if ($inhtml) {
384
            return '<nobr>'.
385
                   nl2br(str_replace(' ', '&nbsp;', htmlspecialchars($str))).
386
                   '</nobr>';
387
        }
388
 
389
        return $str;
390
    }
391
 
392
 
393
 
394
    /**
395
    * It is preg_replace callback function that makes horizontal letter smushing
396
    *
397
    * @param array $r preg_replace matches array
398
    *
399
    * @return string
400
    * @access private
401
    */
402
    function _rep($r)
403
    {
404
        if ($this->oldlayout & 1 && $r[1] == $r[2]) {
405
            $this->smush_flag = 1;
406
            return $r[1];
407
        }
408
 
409
        if ($this->oldlayout & 2) {
410
            $symb = '|/\\[]{}()<>';
411
 
412
            if ($r[1] == '_' && strpos($symb, $r[2]) !== false ||
413
                $r[2] == '_' && strpos($symb, $r[1]) !== false) {
414
                $this->smush_flag = 1;
415
                return $r[1];
416
            }
417
        }
418
 
419
        if ($this->oldlayout & 4) {
420
            $classes = '|/\\[]{}()<>';
421
 
422
            if (($left = strpos($classes, $r[1])) !== false) {
423
                if (($right = strpos($classes, $r[2])) !== false) {
424
                    $this->smush_flag = 1;
425
                    return $right > $left ? $r[2] : $r[1];
426
                }
427
            }
428
        }
429
 
430
        if ($this->oldlayout & 8) {
431
            $t = array('[' => ']', ']' => '[', '{' => '}', '}' => '{',
432
            '(' => ')', ')' => '(');
433
 
434
            if (isset($t[$r[2]]) && $r[1] == $t[$r[2]]) {
435
                $this->smush_flag = 1;
436
                return '|';
437
            }
438
        }
439
 
440
        if ($this->oldlayout & 16) {
441
            $t = array("/\\" => '|', "\\/" => 'Y', '><' => 'X');
442
 
443
            if (isset($t[$r[1].$r[2]])) {
444
                $this->smush_flag = 1;
445
                return $t[$r[1].$r[2]];
446
            }
447
        }
448
 
449
        if ($this->oldlayout & 32) {
450
            if ($r[1] == $r[2] && $r[1] == $this->hardblank) {
451
                $this->smush_flag = 1;
452
                return $this->hardblank;
453
            }
454
        }
455
 
456
        return $r[1]."\00".$r[2];
457
    }
458
 
459
 
460
 
461
    /**
462
    * Function loads one character in the internal array from file
463
    *
464
    * @param resource &$fp handle of font file
465
    *
466
    * @return mixed lines of the character or false if foef occured
467
    * @access private
468
    */
469
    function _char(&$fp)
470
    {
471
        $out = array();
472
 
473
        for ($i = 0; $i < $this->height; $i++) {
474
            if (feof($fp)) {
475
                return false;
476
            }
477
 
478
            $line = rtrim(fgets($fp, 2048), "\r\n");
479
            if (preg_match('/(.){1,2}$/', $line, $r)) {
480
                $line = str_replace($r[1], '', $line);
481
            }
482
 
483
            $line .= "\x00";
484
 
485
            $out[] = $line;
486
        }
487
 
488
        return $out;
489
    }
490
 
491
 
492
 
493
    /**
494
    * Function for skipping one character in a font file
495
    *
496
    * @param resource &$fp handle of font file
497
    *
498
    * @return boolean always return true
499
    * @access private
500
    */
501
    function _skip(&$fp)
502
    {
503
        for ($i = 0; $i<$this->height && !feof($fp); $i++) {
504
            fgets($fp, 2048);
505
        }
506
 
507
        return true;
508
    }
509
}
510
?>