Page rendering using ANSI support
This commit is contained in:
@@ -11,6 +11,127 @@ class Font
|
||||
|
||||
protected const MSG_WIDTH = 79;
|
||||
|
||||
private string $text = '';
|
||||
private int $width = 0;
|
||||
private int $height = 0;
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
switch ($key) {
|
||||
case 'height':
|
||||
return $this->height;
|
||||
|
||||
case 'width':
|
||||
return $this->width;
|
||||
|
||||
default:
|
||||
throw new \Exception(sprintf('Unknown key %s',$key));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Message text, goes after header, and if a logo, to the right of it
|
||||
*
|
||||
* @param string $text
|
||||
*/
|
||||
public function addText(string $text)
|
||||
{
|
||||
$this->text = $text;
|
||||
$this->dimensions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Characters used in the font
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function chars(): Collection
|
||||
{
|
||||
static $chars = NULL;
|
||||
|
||||
if (is_null($chars) && $this->text) {
|
||||
// Trim any leading/trailing spaces
|
||||
$text = trim(strtolower($this->text));
|
||||
$chars = collect();
|
||||
|
||||
// Work out the characters we need
|
||||
foreach (array_unique(str_split($text)) as $c) {
|
||||
if (! $x=Arr::get(static::FONT,$c))
|
||||
continue;
|
||||
|
||||
$chars->put($c,$x);
|
||||
}
|
||||
}
|
||||
|
||||
return $chars ?: collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Full width of the rendered text
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function dimensions(): void
|
||||
{
|
||||
$chars = $this->chars();
|
||||
$escape = FALSE;
|
||||
|
||||
foreach (str_split(strtolower($this->text)) as $c) {
|
||||
if ($c == "\x1b") {
|
||||
$escape = TRUE;
|
||||
continue;
|
||||
|
||||
} elseif ($escape) {
|
||||
$escape = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->width += ($x=Arr::get($chars->get($c),0)) ? count($x) : 1;
|
||||
|
||||
if ($x)
|
||||
$this->height = (($y=count($chars->get($c))) > $this->height) ? $y : $this->height;
|
||||
}
|
||||
|
||||
// If the last character is a space, we'll reduce the width
|
||||
$space = TRUE;
|
||||
foreach ($chars->get($c) as $line => $x)
|
||||
if (array_pop($x) != 32) {
|
||||
$space = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($space)
|
||||
$this->width--;
|
||||
}
|
||||
|
||||
public function render_line(int $line): string
|
||||
{
|
||||
$chars = $this->chars();
|
||||
$result = '';
|
||||
$escape = FALSE;
|
||||
$ansi = FALSE;
|
||||
|
||||
foreach (str_split(strtolower($this->text)) as $c) {
|
||||
if (ord($c) == 0x1b) {
|
||||
$escape = TRUE;
|
||||
|
||||
} elseif ($escape && $c) {
|
||||
$result .= ANSI::ansi_color(ord($c));
|
||||
$escape = FALSE;
|
||||
$ansi = TRUE;
|
||||
|
||||
} elseif (($c == ' ') || (! $font_chars=$chars->get($c))) {
|
||||
$result .= $c;
|
||||
|
||||
} else {
|
||||
foreach (Arr::get($font_chars,$line) as $char)
|
||||
$result .= chr($char);
|
||||
}
|
||||
}
|
||||
|
||||
return $result.($ansi ? ANSI::ansi_color(0x0e) : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will format text to static::MSG_WIDTH, as well as adding the logo.
|
||||
* It is up to the text to be spaced appropriately to wrap around the icon.
|
||||
@@ -146,9 +267,9 @@ class Font
|
||||
for ($line=0;$line<$font_height;$line++) {
|
||||
if ($line == 0) {
|
||||
$line_icon_width = $icon_width
|
||||
->skip(intdiv($result_height,$step)*$step)
|
||||
->take($step)
|
||||
->max();
|
||||
->skip(intdiv($result_height,$step)*$step)
|
||||
->take($step)
|
||||
->max();
|
||||
|
||||
if ($line_icon_width)
|
||||
$line_icon_width += ANSI::LOGO_OFFSET_WIDTH+ANSI::LOGO_BUFFER_WIDTH;
|
||||
|
Reference in New Issue
Block a user