PDFium Delphi Component Docs

Транзакционное слияние навигации

Добавьте FPdfMerge в uses, чтобы включить TPdfNavigationMergeHelper.MergeFilesWithNavigation, либо вызовите глобальную функцию MergePdfFilesWithNavigation с явным целевым документом

Помощник подготавливает нативный импорт страниц, перестраивает иерархические оглавления, объединяет именованные назначения, перепривязывает ссылки на страницы и независимо переоткрывает результат перед заменой документа вызывающего

pmnPreserve сохраняет исходную иерархию; pmnGroupBySource добавляет заголовок с именем каждого исходного файла

Заголовки, связи с родителем, стили, цвета, раскрытые ветви, URI-действия и разрешённые внутренние назначения страниц сохраняются; выбранные, повторные и переупорядоченные страницы отображаются на первый импортированный экземпляр, а назначения опущенных страниц становятся заголовками

Существующие назначения в оглавлении сдвигаются при вставке страниц; исходные файлы остаются открытыми с запретом совместной записи, пока захватываются навигация и нативный импорт страниц

Поддерживается только слияние с остановкой при ошибке; подписанные назначения, неподдерживаемые действия оглавления и постобработка шифрованных документов отклоняются с отчётом об ошибке, а сбой или отмена сохраняют документ вызывающего неизменным

Этот API сохраняет прежнюю политику работы с формами; для расширенной обработки коллизий полей AcroForm и ресурсов используйте FPdfFormMerge

Именованные назначения и ссылки на страницы

PreserveNamedDestinations и PreservePageLinks по умолчанию равны True; установка любой опции в False пропускает соответствующую часть дополнительной обработки навигации

Именованные назначения читаются как из устаревшего словаря /Dests каталога, так и из дерева имён /Names/Dests, включая иерархические деревья, косвенные массивы и словари назначений с /D; когда обе формы определяют один ключ, приоритет у значения дерева имён

Результат использует сбалансированное дерево /Names/Dests и сохраняет не относящиеся к назначениям деревья имён, например /EmbeddedFiles; деревья исходников, не связанные с назначениями, этот помощник не импортирует

Ключи сохраняют исходные байты PDF-строк, включая кодировку UTF-16BE; режим и параметры просмотра воспроизводятся точно, включая /FitH null и /XYZ null 34 null

ПолитикаПоведение
pndRejectИсходный ключ, уже существующий в целевом документе, отклоняет всю транзакцию
pndRenameПолитика по умолчанию сохраняет неконфликтующие имена и снабжает конфликтующие префиксом DestinationPrefix (по умолчанию Imported_); при повторных коллизиях используются детерминированные префиксы вроде 2_Imported_Shared
pndNamespaceКаждый исходный ключ получает префикс DestinationPrefix, порядковый номер источника с единицы и подчёркивание, например Imported_1_Shared; оставшиеся коллизии получают детерминированный числовой префикс

DestinationPrefix должен содержать от 1 до 256 печатаемых ASCII-символов; префиксы вставляются после BOM UTF-16BE, если ключ использует эту кодировку

Аннотации-ссылки с /Dest или одиночным действием /A /GoTo переписываются как явные назначения, поэтому именованные цели ссылок остаются корректными после переименования при коллизии

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

Назначения с опущенной целевой страницей удаляются из дерева именованных назначений; у затронутой ссылки удаляется /Dest или действие GoTo, но аннотация и остальные её свойства сохраняются

URI-ссылки остаются нетронутыми; цепочки действий ссылок с /Next отклоняются, поскольку перепривязка цепочек действий вне текущих возможностей помощника

Искажённые или циклические деревья назначений, недоступные ссылки на объекты и дубликаты ключей дерева имён отклоняют транзакцию; сбой, отмена или исчерпанный бюджет оставляют документ вызывающего без изменений

Бюджеты и отчёты

Значения по умолчанию: 10 000 пунктов оглавления, глубина 128, 1 048 576 символов заголовков, 10 000 именованных назначений, 100 000 ссылок на страницы и 256 МиБ байтов документа; потолок байтов документа не должен превышать MaxInt

При включённой дополнительной обработке назначений и ссылок максимальная настраиваемая глубина — 256, лимит именованных назначений — не более 65 536, лимит ссылок на страницы — не более 1 000 000; захват источника также ограничивает сырые байты ключей 1 МиБ

Комбинированные именованные ключи используют отдельный байтовый бюджет, равный MaxTitleCharacters; каждый источник захватывается в рамках настроенных бюджетов до фильтрации выбранных страниц

PreservedNamedDestinationCount считает итоговые именованные назначения, RenamedNamedDestinationCount — импортированные ключи, изменённые выбранной политикой, а RemovedNamedDestinationCount — неразрешённые или опущенные именованные цели

RemappedPageLinkCount считает итоговые внутренние назначения и у существующих, и у импортированных ссылок, а RemovedPageLinkCount — удалённые внутренние назначения; ссылка, содержащая и /Dest, и GoTo, учитывается по одному разу на каждое назначение

Публичные объявления

type
  TPdfMergeNavigationPolicy= (pmnPreserve, pmnGroupBySource);
  TPdfMergeNamedDestinationPolicy= (pndReject, pndRename, pndNamespace);

  TPdfNavigationMergeOptions= record
    NativeOptions: TPdfBatchMergeOptions;
    NavigationPolicy: TPdfMergeNavigationPolicy;
    MaxOutlineItems: Integer;
    MaxOutlineDepth: Integer;
    MaxTitleCharacters: Integer;
    MaxDocumentBytes: Int64;
    PreserveNamedDestinations, PreservePageLinks: Boolean;
    NamedDestinationPolicy: TPdfMergeNamedDestinationPolicy;
    DestinationPrefix: string;
    MaxNamedDestinations, MaxPageLinks: Integer;
    class function Default: TPdfNavigationMergeOptions; static;
  end;

  TPdfNavigationMergeReport= record
    Succeeded: Boolean;
    Cancelled: Boolean;
    ImportedSourceCount: Integer;
    ImportedPageCount: Integer;
    PreservedOutlineCount: Integer;
    RemovedDestinationCount: Integer;
    SourceGroupCount: Integer;
    PreservedNamedDestinationCount, RenamedNamedDestinationCount: Integer;
    RemovedNamedDestinationCount, RemappedPageLinkCount, RemovedPageLinkCount: Integer;
    ErrorMessage: string;
  end;

  // The caller's document is replaced only after the complete staged result
  // has been independently reopened and its outline destinations checked
  TPdfNavigationMergeHelper= class helper for TPdf
    function MergeFilesWithNavigation(const Sources: TPdfBatchMergeSources;
      const Options: TPdfNavigationMergeOptions;
      out Report: TPdfNavigationMergeReport): Boolean;
  end;

function MergePdfFilesWithNavigation(Destination: TPdf;
  const Sources: TPdfBatchMergeSources;
  const Options: TPdfNavigationMergeOptions;
  out Report: TPdfNavigationMergeReport): Boolean;

Низкоуровневая обработка потоков

FPdfCompress открывает CapturePdfNavigation и WritePdfNavigation для тех, кто сам управляет импортом страниц и разреженными редакциями PDF

TPdfNavigationNamedDestination.NameKey содержит сырые байты ключа PDF; номера страниц абсолютные и считаются с единицы, а ноль обозначает неразрешённую цель

TPdfNavigationPageLink.PageNumber определяет страницу-владелец; AnnotationIndex — нуль-базированный порядковый номер среди всех исходных аннотаций, а LinkIndex — только среди аннотаций-ссылок

Записыватель находит ссылки по LinkIndex, клонирует каждую аннотацию с её итоговой страницей-владельцем и записывает переданные цели страниц и точные суффиксы назначений; вызывающий обязан передать полное отображение, нужное для его импорта

Записывателю требуются различные исходный и выходной потоки, а также незашифрованный и неподписанный документ; отклонение аргументов при совпадающих потоках сохраняет источник, а прочие сбои очищают отдельный выходной поток

Эти потоковые функции не импортируют страницы и не заменяют живой документ TPdf; для полного слияния навигации используйте высокоуровневую транзакционную функцию

function CapturePdfNavigation(Source: TStream; MaxNamedDestinations,
  MaxPageLinks, MaxDepth: Integer; out Names: TPdfNavigationNamedDestinations;
  out Links: TPdfNavigationPageLinks; out ErrorText: string): Boolean;

function WritePdfNavigation(Source, Output: TStream;
  const Names: TPdfNavigationNamedDestinations;
  const Links: TPdfNavigationPageLinks; ReplaceNamedDestinations: Boolean;
  out ErrorText: string): Boolean;