Custom Stream Filter Registry

HotPDF can decode application-defined PDF stream filters inside the same bounded pipeline used by its built-in Flate, LZW, ASCII85, ASCIIHex, and RunLength decoders

Register push or pull filters

Implement IHPDFCustomStreamFilter, choose csfmPush or csfmPull, and register the interface through THotPDF.RegisterCustomStreamFilter

Names are matched case-insensitively without a leading slash, duplicate registration is explicit, built-in names cannot be replaced, and each document accepts at most 64 custom names

Registry lookups retain an interface snapshot under a short critical section; filter callbacks and interface destruction run outside the registry lock

One budget across every stage

Custom output consumes DecodeBudgetBytes and DocumentDecodeBudgetBytes through the existing aggregate tracker, so a mixed custom and built-in chain cannot reset expansion accounting between stages

THPDFCustomStreamFilterRequest.MaxOutputBytes reports the remaining per-chain allowance, while zero means the configured per-chain budget is unlimited

The request also supplies the decoded PDF filter name, zero-based stage index, pipeline depth, input size when available, and the caller cancellation token

Cancellation and seek contracts

The cancellation-aware DecodeLoadedStreamToStream overload checks before and after custom execution and during pull-stream transfer

Custom implementations should check Request.CancellationToken inside long push loops or blocking external work

csscSeekable declares that the borrowed input, push destination, or returned pull stream must support seeking; contract violations produce dpsSeekContractViolation

Failure isolation

Every custom stage writes to a bounded THPDFAdaptiveTempStream before any bytes are published to the next stage or caller destination

A false result, exception, cancellation, seek violation, or budget failure discards that temporary output and returns a typed pipeline status without leaking a custom exception across the public decode boundary

A successful pull filter transfers ownership of its returned stream to HotPDF; returning the borrowed input or a nil stream is rejected

Telemetry

GetCustomStreamFilterStatistics reports registered names, push and pull attempts, success, failure, cancellation and seek-violation counts, aggregate input and produced bytes, plus the latest name and diagnostic

THPDFDecodePipelineInfo.CustomFilterCount and CustomFilterFailureCount describe the current chain

Example

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;

Related APIs