Реестр пользовательских stream filter
HotPDF умеет декодировать определённые приложением stream filter PDF внутри того же ограниченного конвейера, что и встроенные декодеры Flate, LZW, ASCII85, ASCIIHex и RunLength
Регистрация push- или pull-фильтров
Реализуйте IHPDFCustomStreamFilter, выберите csfmPush или csfmPull и зарегистрируйте интерфейс через THotPDF.RegisterCustomStreamFilter
Имена сопоставляются без учёта регистра и без ведущего слеша, повторная регистрация должна быть явной, встроенные имена заменить нельзя, а каждый документ принимает максимум 64 пользовательских имени
Поиск в реестре берёт снимок интерфейса под короткой критической секцией; callback фильтра и разрушение интерфейса выполняются вне блокировки реестра
Один бюджет на все стадии
Пользовательский вывод расходует DecodeBudgetBytes и DocumentDecodeBudgetBytes через существующий агрегатный трекер, поэтому смешанная цепочка из пользовательских и встроенных стадий не может обнулить учёт расширения между стадиями
THPDFCustomStreamFilterRequest.MaxOutputBytes сообщает остаток лимита на цепочку, а ноль означает, что настроенный бюджет цепочки не ограничен
Запрос также несёт декодированное имя PDF-фильтра, стадию с нуля, глубину конвейера, размер ввода, когда он доступен, и cancellation token вызывающего
Отмена и seek-контракты
Перегрузка DecodeLoadedStreamToStream с поддержкой отмены проверяется до и после выполнения пользовательской стадии и во время передачи pull stream
Пользовательские реализации должны проверять Request.CancellationToken внутри длинных push-циклов или блокирующей внешней работы
csscSeekable объявляет, что заёмный ввод, push-приёмник или возвращённый pull stream должны поддерживать seek; нарушение контракта даёт dpsSeekContractViolation
Изоляция сбоев
Каждая пользовательская стадия пишет в ограниченный THPDFAdaptiveTempStream, прежде чем какие-либо байты уйдут на следующую стадию или в назначение вызывающего
Ложный результат, исключение, отмена, нарушение seek или выход за бюджет отбрасывают этот временный вывод и возвращают типизированный статус конвейера, не выпуская пользовательское исключение за публичную границу декодирования
Успешный pull filter передаёт владение возвращённым stream самому HotPDF; возврат заёмного ввода или nil stream отвергается
Телеметрия
GetCustomStreamFilterStatistics сообщает зарегистрированные имена, попытки push и pull, успехи, отказы, счётчики отмен и нарушений seek, суммарные входные и произведённые байты, а также последнее имя и диагностику
THPDFDecodePipelineInfo.CustomFilterCount и CustomFilterFailureCount описывают текущую цепочку
Пример
Filter := TApplicationFilter.Create;
PDF.RegisterCustomStreamFilter(Filter);
try
if not PDF.DecodeLoadedStreamToStream(StreamObject, Output,
CancellationToken, Info) then
HandleDecodeFailure(Info.Status, Info.Diagnostic);
finally
PDF.UnregisterCustomStreamFilter(Filter.FilterName);
end;