有界段落編輯
HPDFParagraphReflow 在明確的來源矩形內選取已載入的字形中心,並在同一頁的明確目標矩形內寫入重新量測的段落
驗收設定檔涵蓋 Delphi Win32/Win64 與 Windows FPC/Lazarus;量測字型的產生使用既有的文件外觀建構器及其已安裝字型支援
選取、版面與保留
座標是未旋轉的 PDF 頁面 user space points,y 軸向上;兩個矩形都必須有限、尺寸為正且不超過 14400 points,並容納於頁面 MediaBox
選取範圍可跨越多條原始基線與多個頁面內容串流;literal、十六進位、TJ、單引號與雙引號文字運算元會在選取的字元碼邊界重寫
保留的前綴、後綴、文字推進量與原始數值 kerning 調整維持原位;來源文字是從實際運算元中移除,而不是用背景矩形遮住
巢狀 Form XObject 使用其 Matrix 與 BBox;每個選取的 invocation 及其祖系資源都會私下複製,共用原始 Form 的其他 invocation 與其他頁面則保持原樣
落在 Form BBox 之外的字形中心會被排除;部分重疊的來源字形邊界預設會拒絕,而 RejectPartialSourceGlyphs = False 則明確允許在其中心被選取時移除整個字元碼
Appearance 選擇已安裝字型、樣式、大小、色彩、內距、對齊與溢出政策;目標寬度控制換行,shrink-to-fit 會回報實際的 EffectiveFontSize
產生的字形幾何會被獨立解讀並對目標矩形檢查;這個有界輔助函式把旋轉固定為零、不透明度固定為一
空的取代內容會刪除選取的來源文字;設定 RequireSourceText = False 可在空的來源區域插入段落
碰撞證據
未選取的非空白文字、XObject 與內嵌影像、繪製路徑邊界與註解矩形,都會與產生的取代字形邊界比較
每個碰撞會標明種類、頁面空間邊界、選填的相鄰文字與取代字形索引;即使回傳的碰撞清單達到上限,總數仍會保留
路徑控制點、轉換後的 Form 裁剪邊界、筆畫寬度與 miter 極限會產生保守的方框;繪製範圍未知的 shading 會保守地佔滿整個目標矩形
這個幾何測試可能對透明影像、未繪製的註解區域、曲線、被裁剪路徑與旋轉的 Form 外框誤報;它不證明像素級的墨水分離,也不檢查任意裁剪路徑、混合合成或字型輪廓
RejectCollisions = True 會在更動前拒絕重疊的取代內容;設為 false 則保留報告,並允許呼叫端自訂的重疊政策
預覽、提交與回溯
HPDFPreviewParagraphReflow 回傳呼叫端自有的封閉計畫、語意取代版面、指紋與碰撞證據,然後回溯產生的文件物件
HPDFCommitParagraphReflow 重複有界分析,且只在來源內容、Form 邊界、註解幾何與取代字型幾何仍與預覽一致時,才原子式套用計畫
計畫屬於同一個活著的文件實例;用完請釋放,期間保持文件存活,載入其他文件或變更選取內容後請重新產生預覽
THPDFParagraphReflowSession 加入已套用的審閱狀態:Apply 暴露編輯後的文件供抽取或轉譯,Commit 發布它,Rollback 或解構則還原原始圖形
session 請序列使用;文件必須活得比 session 久,且 Pending 為 true 時不得交錯其他圖形交易或編輯呼叫
回溯還原的是記憶體內的文件狀態;已儲存的外部檔案仍由呼叫端負責
有限工作量與失敗行為
預設限制為 64 MiB 解碼內容、64 MiB 產生串流、100000000 工作單位、100000 字形、250000 token、12 層 Form、256 個 Form invocation、256 個回傳碰撞與 100000 個複製資源節點
編碼字串 bytes 會在字形解讀之前,先對剩餘字形限制檢查,因此多位元組字元編碼可能保守地消耗比可見字形數更多的預算
解碼與產生的限制涵蓋此輔助函式處理的內容;產生串流大小會在發布前檢查,不代表處理程序峰值記憶體上限,也不約束所有已安裝字型建構器的配置
取消是合作式的,貫穿內容斷詞與輔助迴圈,並在既有字型產生呼叫周圍檢查;請保留 token 直到呼叫完成
來源缺失、無效輸入、碰撞、過期計畫、不支援的內容、預算耗盡、取消與一般失敗都回傳 false,附明確狀態並保留原始物件圖
選取的直式或單一字元文字、循環或未解析的 Form、不支援的繪製 XObject 類型,以及含簽章欄位的文件都會被拒絕;保留簽章的增量編輯需要另一套工作流程
範例
Options := HPDFDefaultParagraphReflowOptions;
Options.Appearance.FontName := 'Arial';
Options.Appearance.FontSize := 11;
Source.Left := 55; Source.Bottom := 659;
Source.Right := 350; Source.Top := 714;
Target := Source;
Plan := nil;
try
if HPDFPreviewParagraphReflow(Document, 0, Source, Target,
'The Supplier must deliver signed monthly reports.', Options,
Plan, Report, CancellationToken) then
if HPDFCommitParagraphReflow(Document, Plan, Report, CancellationToken) then
Document.SaveLoadedDocument('reviewed-contract.pdf');
finally
Plan.Free;
end;
驗收與已儲存輸出
專屬的 Delphi 與 FPC 執行器使用真實載入的 PDF fixtures,涵蓋多基線段落、部分運算元、巢狀共用 Form、被裁剪的 Form 文字、寬度與字型變更、碰撞種類、取消與圖形回溯
重複的檔案/檔案與串流/檔案儲存會保留編輯後的圖形;全新未變更的已載入文件保持精確的來源 bytes,注入的輸出寫入失敗之後可以成功重試
Tests/Fixtures/ParagraphReflow/loaded-repeat-save.pdf 隔離儲存迴歸,不使用段落輔助函式:載入、插入標記、儲存兩次,然後獨立讀取第二個檔案
執行 Tests/Delphi/Run-ParagraphReflowTests.ps1 -Platform Win64 或 Tests/FPC/Run-ParagraphReflowTests.ps1 -Platform Win64,另一種架構請選 Win32
選用的 Python 驗證器 Tests/Fixtures/ParagraphReflow/verify_output.py 使用 PyMuPDF 抽取實際儲存的 Unicode 文字並轉譯編輯後的頁面;每個執行器都會抑制自動開啟檢視器