141 lines
2.7 KiB
PHP
141 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Classes;
|
|
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Collection;
|
|
|
|
class Font
|
|
{
|
|
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
|
|
* @note Text can have color codes added: eg: ANSI::ansi_code([1,37])."text"
|
|
*
|
|
* @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 = [];
|
|
|
|
if ($this->text && empty($chars[$this->text])) {
|
|
// Trim any leading/trailing spaces
|
|
$text = trim(strtolower($this->text));
|
|
$chars[$this->text] = collect();
|
|
|
|
// Work out the characters we need
|
|
foreach (array_unique(str_split($text)) as $c) {
|
|
if (! $x=Arr::get(static::FONT,$c))
|
|
continue;
|
|
|
|
$chars[$this->text]->put($c,$x);
|
|
}
|
|
}
|
|
|
|
return $chars[$this->text] ?: 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 (ord($c) === 0x1b) {
|
|
$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 $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) : '');
|
|
}
|
|
|
|
/**
|
|
* The height of this font (based on the 1st char)
|
|
*
|
|
* @return int
|
|
*/
|
|
public static function height(): int
|
|
{
|
|
return count(Arr::get(static::FONT,'a'));
|
|
}
|
|
} |