Перейти к содержимому
getnextpdf.com

Pro редакция

Font Tools — глубокий справочник

Эта страница — справочник уровня контракта для NextPDF Pro Font Tools. Поверхность состоит из одного сканера, NextPDF\Pro\FontTools\FontDesubsetter, и двух неизменяемых объектов-значений, SubsetInfo и DesubsetPlan. Сканер читает необработанные байты PDF, сообщает о каждой отдельной записи /BaseFont и помечает записи, которые следуют соглашению об именовании подмножеств из ISO 32000-2:2020 §9.9.2. План агрегирует помеченные подмножества и оценивает стоимость в байтах для восстановления полных программ шрифтов. Модуль только анализирует и оценивает; он никогда не переписывает встроенную программу шрифта. Эта страница описывает публичный API, контракт наблюдаемого поведения и режимы отказа.

Эта возможность поставляется в составе NextPDF Pro (nextpdf/pro) и активируется лицензионным конвертом уровня Pro. Развёртывание без соответствующего права не загружает классы этой возможности. Сравнить редакции и получить лицензию.

Никакой лицензионный флаг отдельной возможности не закрывает этот модуль. Классы Font Tools доступны всегда, когда установлен nextpdf/pro.

СимволПараметрыПоведение по умолчаниюВозвращаетБросает или завершается сПримечания
FontDesubsetterнетСканер без состояния над необработанными байтами PDFfinal; безопасно переиспользовать между документами
FontDesubsetter::analyzeSubsets()string $pdfDataСообщает о каждой отдельной записи /BaseFont, подмножество или нет, с флагом isSubsetlist<SubsetInfo>InvalidArgumentException, когда оценка подмножества по ширинам превышает оценку полного числа по имениПобайтовое сканирование; сжатые потоки объектов не декодируются
FontDesubsetter::isSubsetFont()string $baseFontNameСопоставляет соглашение о префиксе из шести заглавных букв плюс +boolПривязано к началу имени
FontDesubsetter::extractSubsetPrefix()string $baseFontNameВозвращает шестибуквенный тег подмножестваstringПустая строка для имён без подмножества
FontDesubsetter::generateDesubsetPlan()list<SubsetInfo> $subsetsСобирает записи, у которых isSubset равно true, и суммирует оценку размераDesubsetPlanНе бросает исключенийЗаписи без подмножества пропускаются молча
SubsetInfoконструктор: $fontName, $baseFont, $subsetGlyphCount, $fullGlyphCount, $isSubset, $encodingНеизменяемое описание одной записи /BaseFontInvalidArgumentException при отрицательном числе глифов или числе глифов подмножества выше полногоfinal readonly; все свойства публичны
SubsetInfo::subsetPrefix()нетИзвлекает шестибуквенный тег из fontNamestringПустая строка, когда это не подмножество или + стоит не на шестой позиции
SubsetInfo::coveragePercent()нетДоля подмножества от полного набора глифовfloat в [0.0, 100.0]Возвращает 0.0, когда fullGlyphCount равно 0
DesubsetPlanконструктор: list<SubsetInfo> $targets, int $estimatedSizeIncreaseНеизменяемый план де-сабсетингаfinal readonly; все свойства публичны
DesubsetPlan::count()нетЧисло целевых шрифтовintРавно длине targets
DesubsetPlan::totalGlyphsNeeded()нетНедостающие глифы, просуммированные по всем целямintСумма fullGlyphCount - subsetGlyphCount по каждой цели
public function analyzeSubsets(string $pdfData): array
public function isSubsetFont(string $baseFontName): bool
public function extractSubsetPrefix(string $baseFontName): string
public function generateDesubsetPlan(array $subsets): DesubsetPlan
public function __construct(
public string $fontName,
public string $baseFont,
public int $subsetGlyphCount,
public int $fullGlyphCount,
public bool $isSubset,
public string $encoding,
)
public function subsetPrefix(): string
public function coveragePercent(): float
public function __construct(
public array $targets,
public int $estimatedSizeIncrease,
) {}
public function count(): int
public function totalGlyphsNeeded(): int

analyzeSubsets() извлекает токены имён /BaseFont из необработанных байтов с помощью побайтового сопоставления с образцом. Дублирующиеся имена сворачиваются в одну запись; порядок следует первому появлению. Каждое отдельное имя даёт SubsetInfo, независимо от того, является ли оно подмножеством. Имя является подмножеством, когда оно начинается ровно с шести заглавных ASCII-букв, за которыми следует +, — соглашение §9.9.2. Для имён подмножеств baseFont — это имя с удалённым семисимвольным префиксом. Для обычных имён baseFont равно fontName. Каждое отдельное имя подмножества сообщается как собственная запись, что соответствует рекомендации §9.9.2 рассматривать подмножества как независимые сущности.

Для каждого шрифта сканер просматривает ограниченное байтовое окно после вхождения /BaseFont. Запись-имя /Encoding в окне имеет приоритет. Если её нет, сообщается о подстроке Identity-H или Identity-V в окне. Если нет ни того, ни другого, запись сообщает Unknown. Значения кодировки, хранящиеся в словарях или доступные через косвенные ссылки, сообщают Unknown.

Оба числа глифов являются оценками. subsetGlyphCount выводится из массивов ширин, видимых рядом с записью шрифта: массив /W шрифта CIDFont даёт примерно один глиф на тройку ширин, а массив /Widths простого шрифта даёт один глиф на числовую запись. Когда ни один массив не виден в окне, применяется небольшое фиксированное значение по умолчанию. Когда вхождение /BaseFont не удаётся заново найти для поиска в окне, число равно 0. fullGlyphCount выводится из эвристик по имени семейства: таблица хорошо известных латинских семейств, набор индикаторов имён семейств CJK и общий нижний предел в остальных случаях. Встроенная программа шрифта никогда не разбирается. Конкретные таблицы, размеры окон и константы являются деталью реализации, не публикуются и могут меняться между выпусками.

generateDesubsetPlan() фильтрует входные данные до записей, у которых isSubset равно true. Каждая цель добавляет своё число недостающих глифов, умноженное на фиксированную константу среднего числа байтов на глиф, к estimatedSizeIncrease. План — это прогноз для решений о ёмкости, а не измеренная разница. Выполнение плана — переписывание программ шрифтов — находится вне этого модуля.

Вся поверхность — чистая функция от своих входных данных. Идентичные байты дают идентичные результаты. Нет ни случайности, ни сетевых вызовов, ни доступа к файловой системе.

  • Конструирование SubsetInfo отклоняет недопустимые состояния: отрицательное число глифов или число глифов подмножества выше полного бросает InvalidArgumentException.
  • analyzeSubsets() может передать это исключение в одном крайнем случае: шрифт, чьё имя соответствует известному семейству, но чей видимый массив ширин даёт большую оценку подмножества, чем показатель полного числа для этого семейства.
  • Обнаружение работает на байтовом представлении. Записи /BaseFont, сериализованные внутри сжатых потоков объектов, невидимы; распакуйте эти потоки перед сканированием.
  • Записи, у которых ключ и значение /BaseFont разделены пробельным символом, отличным от одного пробела, всё равно обнаруживаются, но поиск по окну для каждого шрифта не может их заново найти. Такие записи сообщают кодировку Unknown и число глифов подмножества 0.
  • Имена PDF, использующие байты, экранированные через #, сообщаются в необработанной экранированной форме; экранирование не декодируется.
  • Дублирующиеся имена /BaseFont сворачиваются в одну запись. Два разных объекта шрифта с одним именем неразличимы для этого сканера.
  • generateDesubsetPlan() никогда не завершается ошибкой на входных данных без подмножеств; записи с isSubset, равным false, просто исключаются из targets.
  • Все числа и estimatedSizeIncrease — эвристики. Не рассматривайте их как измеренные значения; используйте их только для сортировки и планирования ёмкости.
  • В этом модуле не выполняется никаких криптографических операций, поэтому нет поведения, специфичного для режима FIPS.
УтверждениеСтандартПункт
Обнаружение подмножеств соответствует соглашению об именовании подмножеств: тег из шести заглавных букв, за которым следует +, добавленный как префикс к значению BaseFont.ISO 32000-2:2020§9.9.2
Каждое отдельное имя подмножества сообщается независимо, следуя рекомендации рассматривать несколько подмножеств как отдельные сущности.ISO 32000-2:2020§9.9.2

Все пункты перефразированы; NextPDF не воспроизводит нормативный текст. Это утверждения о возможностях, а не сертификаты. NextPDF не имеет сертификации и не предоставляет никакой. Модуль утверждает обнаружение соглашения об именовании и детерминированное сообщение; он не утверждает точность оценок числа глифов или размера.

  • Устанавливается через composer require nextpdf/pro:^3. Доступно начиная с nextpdf/pro 1.9.0; актуально в nextpdf/pro 3.1.0.
  • FontDesubsetter не имеет состояния. Создайте один раз и переиспользуйте между документами и потоками работы.
  • Передавайте в analyzeSubsets() распакованные байты, когда важен охват подмножеств; иначе словари шрифтов, упакованные в потоки объектов, будут пропущены.
  • Разветвляйте логику по SubsetInfo::isSubset перед действием; список результатов намеренно включает шрифты без подмножеств для целей инвентаризации.
  • Используйте DesubsetPlan::totalGlyphsNeeded() и estimatedSizeIncrease, чтобы решить, стоит ли де-сабсетинг затрат на размер файла, прежде чем искать полные программы шрифтов.
  • Сканирование линейно по длине входных данных с ограниченным поиском по окну для каждого шрифта. Модуль ничего не хранит и не отправляет телеметрию.

Эта страница документирует только внешне наблюдаемое поведение и поддерживаемую публичную поверхность API. Внутренние пути пространств имён, вспомогательные классы, таблицы механизмов, имена файлов runbook и префиксы тикетов выходят за рамки.