clrghouz/app/Classes/Font.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'));
}
}