Прогрессивный рендеринг и отмена

HotPDF умеет рендерить загруженную страницу за несколько ограниченных вызовов и останавливать долгие операции с документом через общий cancellation token, принадлежащий вызывающей стороне

Прогрессивный рендеринг страниц

Для линеаризованных сетевых источников THPDFLinearizedPageRedrawScheduler отделяет диапазоны первого отображения от опциональных зависимостей shared-object и запрашивает перерисовку только когда прибывшая зависимость способна изменить страницу

Session := PDF.BeginLoadedPageProgressiveRender(0, 144);
try
  repeat
    Status := Session.ContinueRender(8, 128);
    Preview.Assign(Session.Bitmap);
  until Status in [prsCompleted, prsCancelled];

  if Status = prsCompleted then
    FinalBitmap := Session.TakeBitmap;
finally
  Session.Free;
end;

ContinueRender принимает максимальное прошедшее время в миллисекундах, максимальное число операторов верхнего уровня в содержимом страницы — или и то и другое; ноль означает отсутствие ограничения по этому бюджету

Вызов завершает хотя бы один оператор до применения ненулевого временного бюджета, поэтому graphics state всегда ставится на паузу на границе оператора

Bitmap открывает живой частичный bitmap, доступный вызывающей стороне только для чтения, а TakeBitmap после достижения сессией prsCompleted или prsCancelled передаёт владение без копирования

ObjectsProcessed и TotalObjects считают операторы верхнего уровня из каждого stream'а /Contents страницы в порядке источника

Прогрессивный рендеринг области

Session := PDF.BeginLoadedPageProgressiveRegionRender(
  0, 72, 144, 360, 432, 144);
try
  repeat
    Status := Session.ContinueRender(6, 96);
  until Status in [prsCompleted, prsCancelled];
finally
  Session.Free;
end;

Четыре координаты области задаются в пользовательских координатах PDF с началом в левом нижнем углу, а выходной bitmap покрывает ровно это окно при запрошенном DPI

Сессия переиспользует кешированную display list, сохраняет graphics и text state между вызовами и подавляет дорогие отрисовки path, текста, изображений, Form и shadings, чьи консервативные границы не пересекают ROI

Операторы состояния и продвижение текста всё равно выполняются в порядке источника, поэтому отсечение более раннего знака не может сдвинуть или перекрасить более поздний видимый знак

RegionVisiblePaintObjects и RegionCulledPaintObjects открывают отбор display list, а резерв пиковой памяти считается по размерам области, а не полной страницы

Прогрессивные JPEG scan'ы

Когда THotPDF.ProgressiveJPEGScanDecoding включён, подходящее прогрессивное изображение DCTDecode продвигается на один JPEG scan за ограниченный вызов ContinueRender, так что живой bitmap может показать грубый ранний предпросмотр до финального scan'а

THotPDF.ProgressiveJPEGMaxScans ограничивает каждое изображение диапазоном 1–4096 scan'ов, а байтовый бюджет декодирования документа покрывает и выровненный выходной bitmap

THPDFLoadedPageRenderSession.ProgressiveJPEGScansDecoded и THPDFLoadedPageRenderSession.ProgressiveJPEGImagesDecoded сообщают числа завершённых scan'ов и изображений; THPDFLoadedPageRenderSession.OnProgressiveJPEGScan получает THPDFProgressiveJPEGScanEvent после каждого видимого scan'а и может отменить сессию

Модуль HPDFJpeg также открывает THPDFJpegScanDecoder для сырых входов THPDFJpegByteArray — с результатами THPDFJpegScanDecodeStatus и опциональным callback'ом THPDFJpegCancellationCheck для отмены на уровне строк

Инкрементальный путь принимает отрисовку JPEG-изображений на всю целевую область в DeviceRGB или DeviceGray с непрозрачностью по умолчанию и без mask, transfer functions, halftones, overprint или состояния transparency-group; все прочие отрисовки идут через декодер полного изображения, чтобы не менять семантику рендеринга

Выключенная опция, требование изоляции codec, превышение лимита или повреждённый ввод тоже переключают на путь полного изображения — без показа частично неудачного декодирования

Callback'и прогресса

THPDFProgressiveRenderProgressEvent срабатывает после каждого завершённого оператора и получает счётчики обработанных и всех операторов плюс время выполнения рендеринга

Установите параметр Cancel callback'а в true, чтобы завершить сессию в prsCancelled, не отменяя общий token

Form XObject, pattern, декодирование изображения и другие вложенные операции принадлежат объемлющему оператору верхнего уровня и могут выйти за маленький временной бюджет до возврата управления

Отмена на уровне операции

Token := THPDFCancellationToken.Create;
try
  PDF.OperationCancellationToken := Token;
  Worker.Start;
  // Call Token.Cancel from another thread when the operation should stop
finally
  PDF.OperationCancellationToken := nil;
  Token.Free;
end;

THPDFCancellationToken потокобезопасен, одноразовый и принадлежит вызывающей стороне; Cancel перманентно запрашивает отмену, а IsCancellationRequested открывает состояние

ThrowIfCancellationRequested возбуждает EHPDFOperationCancelled и сохраняет имя операции в OperationName

THotPDF.OperationCancellationToken действует на загрузку, синхронный рендеринг, прогрессивный рендеринг без явного token, OptimizeLoadedStreams, CreatePreflightReport и ValidatePDFVT

SignPDFWithPFX и SignPDFWithSystemCertificate имеют перегрузки, принимающие token напрямую

Владение и правила частичных результатов

Связанные API