2026-01-09 07:13:59 +00:00

66 lines
2.3 KiB
PHP

<?php declare(strict_types=1);
namespace PrinsFrank\PdfParser\Document\Dictionary\DictionaryValue\Array;
use Override;
use PrinsFrank\PdfParser\Document\Dictionary\DictionaryValue\Array\Item\ConsecutiveCIDWidth;
use PrinsFrank\PdfParser\Document\Dictionary\DictionaryValue\Array\Item\RangeCIDWidth;
use PrinsFrank\PdfParser\Document\Dictionary\DictionaryValue\DictionaryValue;
/** @see 9.7.4.3 Glyph metrics in CIDFonts */
class CIDFontWidths implements DictionaryValue {
/** @var list<ConsecutiveCIDWidth|RangeCIDWidth> */
private readonly array $widths;
/** @no-named-arguments */
public function __construct(
ConsecutiveCIDWidth|RangeCIDWidth ...$widths,
) {
$this->widths = $widths;
}
public function getWidthForCharacter(int $characterCode): ?float {
foreach ($this->widths as $widthItem) {
if (($widthForCharacterCode = $widthItem->getWidthForCharacterCode($characterCode)) !== null) {
return $widthForCharacterCode;
}
}
return null;
}
#[Override]
public static function fromValue(string $valueString): ?self {
$valueString = str_replace("\n", ' ', $valueString);
if (preg_match_all('/(?<startingCID>[0-9]+)\s*(?<CIDS>[0-9]+\s*[0-9.]+|\[[0-9. ]+\])/', $valueString, $matches, PREG_SET_ORDER) <= 0) {
return null;
}
$widths = [];
foreach ($matches as $match) {
if ((string) ($startingCID = (int) $match['startingCID']) !== $match['startingCID']) {
return null;
}
if (str_starts_with($match['CIDS'], '[') && str_ends_with($match['CIDS'], ']')) {
$widths[] = new ConsecutiveCIDWidth($startingCID, array_map('floatval', explode(' ', rtrim(ltrim($match['CIDS'], '['), ']'))));
continue;
}
$arguments = explode(' ', $match['CIDS']);
if (count($arguments) !== 2) {
return null;
}
if ((string)($endCID = (int) $arguments[0]) !== $arguments[0] || (string)($width = (float) $arguments[1]) !== $arguments[1]) {
return null;
}
$widths[] = new RangeCIDWidth($startingCID, $endCID, $width);
}
return new self(... $widths);
}
}