$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:----PK64DXn55A6tm3E5PQMsGGCHBT1WOIjtN+5lCJyJ86N0i04UQvPSrAi7xG3TZDhjSSJkXT9ZM454yK0EVF/vOEYlD5iSYmy/D6vjuY1Yq9pynVn2zBb6RXsT9D5RtlHQSUDoWgMeKy/Hux2Dh8msa4VUM9V91D+FahVjjTcSXiapMgUHesPDCpf26RNqc+5FmAlWGyjTxbhX0HmoHoG30FbQmgygU2C/OyrSdv+rXZv7zOcwrbOJsUX8ts1Y/CezyVCd/OY3B2T+SLNWxvvGUJm0aHHmGmp9ENOMcj0oznM1w6CAfwxDHyxCK17LMxVwnM6MR6jJZM5mjuu3ehQ8rLbgmTL9s7BOhBaledfvZtfjM2eogx9dVRWrykMZuZqPOKQzp/ZC5Lvp7X57mCnnm62FS/tTOFDLRBicASt0gj84xlMP0HKegbeu3MkukU8bJOG4WwvSr/4tGPetP5I+wOnGjJ+nzn23kE7bLfeBEOJyTn+0lP1PGF3S/k0aKfVhWM6sGSb5ayt1S+8l8ZjzHGhRuCI1ZW1xEaL9XBdXYxQ2/CPPhqGIJ5uWNfCq5utqR/x5C1b62hBAjZ1kUpk3OCaBvRRJ0zlsz8RNxl5dSmCoUiJONrTaCOlF2LXWM1NDNjSmWjY8mu70/sN6jRqd7pwEVcfFz0sUbGrJg84i5G0=----ATTACHMENT:----MzYzNTkzMzY3MjQzMDYzMSA2MjQ4MjQwNjYyMTE0Njg5IDM5NzYzNDY5MTY5NzA4OTM=