Path: blob/master/externals/pear-figlet/Text/Figlet.php
13450 views
<?php1/* vim: set expandtab tabstop=4 softtabstop=4 shiftwidth=4: */2/**3* ASCII art text creation4*5* Project home page (Russian): http://bolknote.ru/files/figlet/6*7* PHP Version 48*9* @category Text10* @package Text_Figlet11* @author Evgeny Stepanischev <[email protected]>12* @author Christian Weiske <[email protected]>13* @license http://www.php.net/license PHP License14* @version CVS: $Id$15* @link http://pear.php.net/package/Text_Figlet16*/1718/**19* ASCII art text creation20*21* Project home page (Russian): http://bolknote.ru/files/figlet/22*23* PHP Version 424*25* @category Text26* @package Text_Figlet27* @author Evgeny Stepanischev <[email protected]>28* @author Christian Weiske <[email protected]>29* @license http://www.php.net/license PHP License30* @link http://pear.php.net/package/Text_Figlet31*/32class Text_Figlet33{34/**35* Height of a letter36*37* @var integer38*39* @access protected40*/41var $height;4243/**44* Letter baseline45*46* @var integer47*48* @access protected49*/50var $oldlayout;5152/**53* Flag - RTL (right to left) or LTR (left to right) text direction54*55* @var integer56*57* @access protected58*/59var $rtol;6061/**62* Information about special 'hardblank' character63*64* @var integer65*66* @access protected67*/68var $hardblank;6970/**71* Is used for keeping font72*73* @var array74*75* @access protected76*/77var $font;7879/**80* Flag is true if smushing occured in letters printing cycle81*82* @var integer83*84* @access protected85*/86var $smush_flag;8788/**89* Comment lines buffer90*91* @var string92*93* @access public94*/9596var $font_comment;979899/**100* Load user font. Must be invoked first.101* Automatically tries the Text_Figlet font data directory102* as long as no path separator is in the filename.103*104* @param string $filename font file name105* @param bool $loadgerman (optional) load German character set or not106*107* @access public108* @return mixed PEAR_Error or true for success109*/110function loadFont($filename, $loadgerman = true)111{112$this->font = array();113if (!file_exists($filename)) {114return self::raiseError('Figlet font file "'115. $filename116. '" cannot be found', 1);117}118119$this->font_comment = '';120121// If Gzip compressed font122if (substr($filename, -3, 3) == '.gz') {123$filename = 'compress.zlib://' . $filename;124$compressed = true;125126if (!function_exists('gzcompress')) {127return self::raiseError('Cannot load gzip compressed fonts since'128. ' gzcompress() is not available.',1293);130}131} else {132$compressed = false;133}134135if (!($fp = fopen($filename, 'rb'))) {136return self::raiseError('Cannot open figlet font file ' . $filename, 2);137}138139if (!$compressed) {140/* ZIPed font */141if (fread($fp, 2) == 'PK') {142fclose($fp);143144$zip = new ZipArchive();145$open_flag = 0;146// The RDONLY flag was only introduced in 7.4.3.147if (defined('ZipArchive::RDONLY')) {148$open_flag = ZipArchive::RDONLY;149}150$open_result = $zip->open($filename, $open_flag);151if ($open_result !== true) {152return self::raiseError('Cannot open figlet font file ' .153$filename . ', got error: ' . $open_result, 2);154}155156$name = $zip->getNameIndex(0);157$zip->close();158159if (!($fp = fopen('zip://' . realpath($filename) . '#' . $name, 'rb'))) {160return self::raiseError('Cannot open figlet font file ' . $filename, 2);161}162163$compressed = true;164} else {165flock($fp, LOCK_SH);166rewind($fp);167}168}169170// flf2a$ 6 5 20 15 3 0 143 229171// | | | | | | | | | |172// / / | | | | | | | \173// Signature / / | | | | | \ Codetag_Count174// Hardblank / / | | | \ Full_Layout175// Height / | | \ Print_Direction176// Baseline / \ Comment_Lines177// Max_Length Old_Layout178179180$header = explode(' ', fgets($fp, 2048));181182if (substr($header[0], 0, 5) <> 'flf2a') {183return self::raiseError('Unknown FIGlet font format.', 4);184}185186@list ($this->hardblank, $this->height,,,187$this->oldlayout, $cmt_count, $this->rtol) = $header;188189$this->hardblank = substr($this->hardblank, -1, 1);190191for ($i = 0; $i < $cmt_count; $i++) {192$this->font_comment .= fgets($fp, 2048);193}194195// ASCII charcters196for ($i = 32; $i < 127; $i++) {197$this->font[$i] = $this->_char($fp);198}199200foreach (array(196, 214, 220, 228, 246, 252, 223) as $i) {201if ($loadgerman) {202$letter = $this->_char($fp);203204// Invalid character but main font is loaded and I can use it205if ($letter === false) {206fclose($fp);207return true;208}209210// Load if it is not blank only211if (trim(implode('', $letter)) <> '') {212$this->font[$i] = $letter;213}214} else {215$this->_skip($fp);216}217}218219// Extented characters220for ($n = 0; !feof($fp); $n++) {221list ($i) = explode(' ', rtrim(fgets($fp, 1024)), 2);222if ($i == '') {223continue;224}225226// If comment227if (preg_match('/^\-0x/i', $i)) {228$this->_skip($fp);229} else {230// If Unicode231if (preg_match('/^0x/i', $i)) {232$i = hexdec(substr($i, 2));233} else {234// If octal235if ($i[0] === '0' && $i !== '0' || substr($i, 0, 2) == '-0') {236$i = octdec($i);237}238}239240$letter = $this->_char($fp);241242// Invalid character but main font is loaded and I can use it243if ($letter === false) {244fclose($fp);245return true;246}247248$this->font[$i] = $letter;249}250}251252fclose($fp);253return true;254}255256257258/**259* Print string using font loaded by LoadFont method260*261* @param string $str string for printing262* @param bool $inhtml (optional) output mode263* - HTML (true) or plain text (false)264*265* @access public266* @return string contains267*/268function lineEcho($str, $inhtml = false)269{270$out = array();271272for ($i = 0; $i<strlen($str); $i++) {273// Pseudo Unicode support274if (substr($str, $i, 2) == '%u') {275$lt = hexdec(substr($str, $i+2, 4));276$i += 5;277} else {278$lt = ord($str[$i]);279}280281$hb = preg_quote($this->hardblank, '/');282$sp = "$hb\\x00\\s";283284// If chosen character not found try to use default285// If default character is not defined skip it286287if (!isset($this->font[$lt])) {288if (isset($this->font[0])) {289$lt = 0;290} else {291continue;292}293}294295for ($j = 0; $j < $this->height; $j++) {296$line = $this->font[$lt][$j];297298// Replace hardblanks299if (isset($out[$j])) {300if ($this->rtol) {301$out[$j] = $line . $out[$j];302} else {303$out[$j] .= $line;304}305} else {306$out[$j] = $line;307}308}309310if ($this->oldlayout > -1 && $i) {311// Calculate minimal distance between two last letters312313$mindiff = -1;314315for ($j = 0; $j < $this->height; $j++) {316if (preg_match("/\S(\s*\\x00\s*)\S/", $out[$j], $r)) {317if ($mindiff == -1) {318$mindiff = strlen($r[1]);319} else {320$mindiff = min($mindiff, strlen($r[1]));321}322}323}324325// Remove spaces between two last letter326// dec mindiff for exclude \x00 symbol327328if (--$mindiff > 0) {329for ($j = 0; $j < $this->height; $j++) {330if (preg_match("/\\x00(\s{0,{$mindiff}})/", $out[$j], $r)) {331$l = strlen($r[1]);332$b = $mindiff - $l;333$out[$j] = preg_replace("/\s{0,$b}\\x00\s{{$l}}/",334"\0",335$out[$j],3361);337}338}339}340// Smushing341342$this->smush_flag = 0;343344for ($j = 0; $j < $this->height; $j++) {345$out[$j] = preg_replace_callback("#([^$sp])\\x00([^$sp])#",346array(&$this, '_rep'),347$out[$j]);348}349350// Remove one space if smushing351// and remove all \x00 except tail whenever352353if ($this->smush_flag) {354$pat = array("/\s\\x00(?!$)|\\x00\s/", "/\\x00(?!$)/");355$rep = array('', '');356} else {357$pat = "/\\x00(?!$)/";358$rep = '';359}360361for ($j = 0; $j<$this->height; $j++) {362$out[$j] = preg_replace($pat, $rep, $out[$j]);363}364}365}366367$trans = array("\0" => '', $this->hardblank => ' ');368$str = strtr(implode("\n", $out), $trans);369370if ($inhtml) {371self::raiseError(372'Do not use the HTML escaping provided by this class in '.373'a Phabricator context.');374}375376return $str;377}378379380381/**382* It is preg_replace callback function that makes horizontal letter smushing383*384* @param array $r preg_replace matches array385*386* @return string387* @access private388*/389function _rep($r)390{391if ($this->oldlayout & 1 && $r[1] == $r[2]) {392$this->smush_flag = 1;393return $r[1];394}395396if ($this->oldlayout & 2) {397$symb = '|/\\[]{}()<>';398399if ($r[1] == '_' && strpos($symb, $r[2]) !== false ||400$r[2] == '_' && strpos($symb, $r[1]) !== false) {401$this->smush_flag = 1;402return $r[1];403}404}405406if ($this->oldlayout & 4) {407$classes = '|/\\[]{}()<>';408409if (($left = strpos($classes, $r[1])) !== false) {410if (($right = strpos($classes, $r[2])) !== false) {411$this->smush_flag = 1;412return $right > $left ? $r[2] : $r[1];413}414}415}416417if ($this->oldlayout & 8) {418$t = array('[' => ']', ']' => '[', '{' => '}', '}' => '{',419'(' => ')', ')' => '(');420421if (isset($t[$r[2]]) && $r[1] == $t[$r[2]]) {422$this->smush_flag = 1;423return '|';424}425}426427if ($this->oldlayout & 16) {428$t = array("/\\" => '|', "\\/" => 'Y', '><' => 'X');429430if (isset($t[$r[1].$r[2]])) {431$this->smush_flag = 1;432return $t[$r[1].$r[2]];433}434}435436if ($this->oldlayout & 32) {437if ($r[1] == $r[2] && $r[1] == $this->hardblank) {438$this->smush_flag = 1;439return $this->hardblank;440}441}442443return $r[1]."\00".$r[2];444}445446447448/**449* Function loads one character in the internal array from file450*451* @param resource &$fp handle of font file452*453* @return mixed lines of the character or false if foef occured454* @access private455*/456function _char(&$fp)457{458$out = array();459460for ($i = 0; $i < $this->height; $i++) {461if (feof($fp)) {462return false;463}464465$line = rtrim(fgets($fp, 2048), "\r\n");466if (preg_match('/(.){1,2}$/', $line, $r)) {467$line = str_replace($r[1], '', $line);468}469470$line .= "\x00";471472$out[] = $line;473}474475return $out;476}477478479480/**481* Function for skipping one character in a font file482*483* @param resource &$fp handle of font file484*485* @return boolean always return true486* @access private487*/488function _skip(&$fp)489{490for ($i = 0; $i<$this->height && !feof($fp); $i++) {491fgets($fp, 2048);492}493494return true;495}496497498private static function raiseError($message, $code = 1) {499throw new Exception($message);500}501}502503