<?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')); } }