PDFium Delphi Component Docs

交易式導覽合併

在 uses 子句加入 FPdfMerge,即可使用 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 字元;鍵值使用 UTF-16BE 時,前綴插入在 BOM 之後

使用 /Dest 或單一 /A /GoTo 動作的內部連結註解會改寫為明確目的地,因此具名連結目標在衝突重新命名後仍然正確

插入頁面時,既有連結的擁有者頁面及目標會位移;重複匯入頁面的每次出現都得到獨立連結註解,其內部目標則對應到目標頁面第一次選取的出現位置

目標頁面被省略的目的地會從具名目的地樹移除;受影響連結會移除 /Dest 或 GoTo 動作,保留註解及其其他屬性

URI 連結維持完整;使用 /Next 的串接連結動作會遭拒絕,因為重新對應動作鏈尚不在此輔助功能範圍內

格式錯誤或循環的目的地樹、不可用物件參照及重複的名稱樹鍵值都會拒絕交易;失敗、取消或超出預算時,呼叫端文件維持原樣

預算與報告

預設上限為 10,000 個大綱項目、深度 128、1,048,576 個標題字元、10,000 個具名目的地、100,000 個頁面連結及 256 MiB 文件位元組;文件位元組上限不得超過 MaxInt

啟用額外目的地或連結處理時,可設定的最大深度為 256,具名目的地上限不得超過 65,536,頁面連結上限不得超過 1,000,000;來源擷取也將原始鍵值位元組限制為 1 MiB

合併的具名鍵值使用獨立位元組預算,等於 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;