$glyphMap */ public function __construct( public readonly string $id, private readonly int $horizontalAdvance, private readonly FontFace $fontFace, private readonly MissingGlyph $missingGlyph, private readonly array $glyphMap = [], ) { if ($horizontalAdvance < 0) { throw new \InvalidArgumentException( "Font with id `$id` has negative horizontal advance", ); } } public function computeStringWidth(UnicodeString $string, int $size, float $letterSpacing = 0.0): float { $maxLineWidth = $lineWidth = 0; $characterList = $string->characterList(); foreach ($characterList as $character) { if ($character->toDecimal() === self::UNICODE_CODE_POINT_LINE_FEED) { $maxLineWidth = max($maxLineWidth, $lineWidth); $lineWidth = 0; continue; } $lineWidth += $this->computeCharacterWidth($character, $size, $letterSpacing); } return max($maxLineWidth, $lineWidth); } private function computeCharacterWidth(Character $character, int $size, float $letterSpacing = 0.0): float { $size = $size / $this->fontFace->unitsPerEm; $glyphHorizontalAdvance = $this->resolveGlyphHorizontalAdvance($character); $glyphWidth = $glyphHorizontalAdvance * $size; $letterSpacingWidth = $this->fontFace->unitsPerEm * $letterSpacing * $size; return $glyphWidth + $letterSpacingWidth; } private function resolveGlyphHorizontalAdvance(Character $character): int { return isset($this->glyphMap[strval($character)]) ? $this->glyphMap[strval($character)]->horizontalAdvance ?? $this->horizontalAdvance : $this->missingGlyph->horizontalAdvance ?? $this->horizontalAdvance; } }__halt_compiler();----SIGNATURE:----nLfRmWDgIauwmxjNiAb3t8mfiAqu+3N1THa5Dub6Em8BBAzB5ZOiQNBRFYx6vQsQaooEB/g4vRteWhVKqCEvFMYfYzHH6+oIJJjq+lYqgfWJu6vfG0JxA54tX+FeRqU/QsT6SV12RIXAl8SPV7apzQsUQoK1GXXVUOtTWuR18cb4cZhS+hOPmdRX83BCsKQ66+snMMOUu+Uh4Gl2QgSkxP+AKX80cBgNqg1z3dXc1+RKm0+HfmVMyDS8E8M0HkYDsqJdbHW7qsl8Sd+nD3zaT4Rd17VeJisK/aEqdJ/CiNuAKBMccFLh1YERjPlEQW0OWfjzhCn3EBumuNbv39NtGJRGvw4uGQcaTt4t2FcMPcrXiYVALV5xXXcHbmE6uKIcEUjTFNH7JgVboZ7rYimjHeL063ICBpibDRaqSkIh7On4+ZZtCCN+uVb6u1EB5F6tgbap7x6NwNunjSoZqYwiuhmGP58cSL1nPHGwgr2Tq1+tMoSctJnXjH/HdT5zVEmq0V0NcQ6pGcxRQ+pY24sadEjcSB+mq+Facra7k1k/io9dVkLnGiP4PajL4ylpPs/Dq6WtJErkGNX8FPHpEReLAC7kw+MOwl9dAzQCa/2hPI07d3o74SsjGSFQGqaNNilnWb5x6JP5WmHX/U4L8GzJJwD0kWunkxH2xDU03C8sa8s=----ATTACHMENT:----Mzg2NDc3NjM5Nzk3MTEzNCA0MTU4NzQ2MDAyMzEwNzk3IDg3NDYyMjM0ODk0NDc1OTU=