Добавьте 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;