宣告式版面 DOM
HPDFLayoutDOM 在 THPDFLayoutElement、MeasureLayoutElement、PlaceLayoutElement、所屬溢位片段與 ImmediateFlushLayout 之上建置可重用的文件元件
文件與區段組合
Document := THPDFDOMDocument.Create;
Renderer := THPDFDOMRenderer.Create;
try
Section := Document.AddSection;
Section.PageWidth := 595.28;
Section.PageHeight := 841.89;
Section.Header := THPDFDOMText.Create('Quarterly report');
Section.Footer := THPDFDOMText.Create('Confidential');
Section.Body.Style.Padding := 12;
Section.Body.Style.Spacing := 8;
Section.Body.AddText(BodyText, 'Narrative');
PDF.OutputStream := Output;
PDF.ImmediateFlushLayout := True;
Statistics := Renderer.Render(Document, PDF);
finally
Renderer.Free;
Document.Free;
end;
THPDFDOMDocument 擁有其區段、每個 THPDFDOMSection 擁有其本體、頁首、頁尾與樣式,而每個堆疊或容器都擁有附加到它的元件
THPDFDOMRenderer.Render 啟動與結束目標文件、為每個新區段建立新頁面、在接續頁面上重複區段傢飾,並傳回頁面、放置、分割、傢飾、結構、標記內容、工件與最大接續統計
在呼叫 Render 之前設定所有的 THotPDF 輸出、壓縮、遵循、圖層與立即清除選項
GenerateStructure 預設為 True,因此轉譯器也會建置支援接續的邏輯結構樹,並在目標沒有語言時使用 THPDFDOMDocument.Language
元件
THPDFDOMText包裝 Unicode 文字、依寬度與繼承的文字度量快取行界限,並透過來源字元範圍分割,而不複製來源文字THPDFDOMSpacer保留垂直空間,並可跨頁面分割THPDFDOMStack以繼承的內距與間距垂直排列所屬的子項THPDFDOMContainer在一個所屬子項周圍加入樣式化的框,並轉發分割接續THPDFDOMTable解析加權欄、繪製樣式化的列與儲存格,並在接續頁面上重複前導的頁首列THPDFDOMList建立帶有標籤與本體元件的編號或非編號清單項目THPDFDOMImage擁有複製的圖形、解析明確維度,並提供圖形語意與壓縮控制
所有元件都公開穩定的 Name、Path、Style、Clone、Measure、Draw 與 Split 契約,加上語意角色、語言、替代文字、取代文字、擴充文字與工件覆寫
頂層本體遍歷是線性的,且不複製元件;文字與表格接續保留範圍或列切片中繼資料,而不複製完整的內容樹
樣式繼承
THPDFDOMStyle 透過其父鏈解析字型名稱、大小、樣式、文字色彩、背景、邊框、內距、間距與行高
區段樣式是其本體與傢飾的父、堆疊或容器樣式是其子項的父,而表格樣式會流過列到儲存格
只有明確指派的值會覆寫父;Clear 移除本地指派與父連結,而 Assign 在不複製擁有權或血統的情況下複製本地指派
深度超過 64 層的父鏈會作為循環或無界而遭到拒絕
可重用的元件工廠
THPDFDOMComponentFactory 是一個匿名函式,每次呼叫都建立一個呼叫端所屬的 THPDFDOMComponent 執行個體
Document.RegisterComponent('notice',
function: THPDFDOMComponent
begin
Result := THPDFDOMContainer.Create(
THPDFDOMText.Create('Reusable notice'));
end);
Section.Body.Add(Document.CreateComponent('notice'));
工廠名稱是大小寫不敏感且唯一的、每個呼叫都必須傳回新的元件執行個體,而接收容器在 Add 之後取得擁有權
當一個宣告的元件必須在多個擁有權位置重用時,請使用 SetHeaderClone、SetFooterClone 或 Clone
重複頁首表格
Table := THPDFDOMTable.Create('Orders');
Table.AddColumn(1);
Table.AddColumn(3);
Header := Table.AddRow(18, True);
Header[0].Text := 'ID';
Header[1].Text := 'Description';
Row := Table.AddRow(22);
Row[0].Text := '1001';
Row[1].Text := 'Bounded streaming layout';
Section.Body.Add(Table);
頁首列必須連續且位於內文列之前、正的欄權重分割可用寬度,而列高是明確的正值
當 RepeatHeaders 為真時,分割需要所有前導頁首列加上至少一個內文列的位置,防止只有頁首的接續頁面
分頁與失敗界限
轉譯器會先針對剩餘的本體矩形重新量測每個元件、在可能時把無法分割的最小片段移到新頁面,並把每個有效的分割委派給 PlaceLayoutElement
無法容納空內文頁面的元素會以穩定的元素路徑提高例外,而不會靜默捨棄內容
MaximumContinuationDepth 預設為 100,000,並約束反覆傳回不進展接續的格式錯誤元件
區段頁面維度必須為正、邊界與傢飾間距不能為負,而頁首加頁尾的幾何必須留下正的本體矩形
C++Builder
std::unique_ptr<THPDFDOMDocument> document(new THPDFDOMDocument());
THPDFDOMSection* section = document->AddSection();
section->Header = new THPDFDOMText(L"Report", "Header");
section->Body->AddText(L"Declarative content", "BodyText");
std::unique_ptr<THPDFDOMRenderer> renderer(new THPDFDOMRenderer());
THPDFDOMRenderStatistics statistics =
renderer->Render(document.get(), pdf.get());
產生的 HPDFLayoutDOM.hpp 匯出相同的文件、樣式、元件、表格、區段、轉譯器與統計介面