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.
Публичная поверхность API
Заголовок раздела «Публичная поверхность API»| Символ | Параметры | Поведение по умолчанию | Возвращает | Бросает или завершается с | Примечания |
|---|---|---|---|---|---|
FontDesubsetter | нет | Сканер без состояния над необработанными байтами PDF | — | — | final; безопасно переиспользовать между документами |
FontDesubsetter::analyzeSubsets() | string $pdfData | Сообщает о каждой отдельной записи /BaseFont, подмножество или нет, с флагом isSubset | list<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 | Неизменяемое описание одной записи /BaseFont | — | InvalidArgumentException при отрицательном числе глифов или числе глифов подмножества выше полного | final readonly; все свойства публичны |
SubsetInfo::subsetPrefix() | нет | Извлекает шестибуквенный тег из fontName | string | — | Пустая строка, когда это не подмножество или + стоит не на шестой позиции |
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): DesubsetPlanpublic 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(): floatpublic 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/pro1.9.0; актуально вnextpdf/pro3.1.0. FontDesubsetterне имеет состояния. Создайте один раз и переиспользуйте между документами и потоками работы.- Передавайте в
analyzeSubsets()распакованные байты, когда важен охват подмножеств; иначе словари шрифтов, упакованные в потоки объектов, будут пропущены. - Разветвляйте логику по
SubsetInfo::isSubsetперед действием; список результатов намеренно включает шрифты без подмножеств для целей инвентаризации. - Используйте
DesubsetPlan::totalGlyphsNeeded()иestimatedSizeIncrease, чтобы решить, стоит ли де-сабсетинг затрат на размер файла, прежде чем искать полные программы шрифтов. - Сканирование линейно по длине входных данных с ограниченным поиском по окну для каждого шрифта. Модуль ничего не хранит и не отправляет телеметрию.
Граница публикации
Заголовок раздела «Граница публикации»Эта страница документирует только внешне наблюдаемое поведение и поддерживаемую публичную поверхность API. Внутренние пути пространств имён, вспомогательные классы, таблицы механизмов, имена файлов runbook и префиксы тикетов выходят за рамки.
См. также
Заголовок раздела «См. также»- Font Tools (возможность) — установка, быстрый старт и примеры рабочего процесса планирования.
- Optimizer — глубокий справочник — родственная поверхность сокращения размера, включая оптимизацию, связанную со шрифтами.
- Модуль шрифтов Core — встраивание и сабсетинг шрифтов во время создания документа в NextPDF Core.