TPDFlibDynamicComponentSession
頁面版面配置、分頁、資料類型
描述
每次在一個目標頁面上合成有狀態的元件,不預先為後續頁面建構內容
每次嘗試都在隔離 Form XObject 內的複本上執行,只在驗證過的內容成功放置後才提交複本
延伸放置可拒絕溢出、裁切自然尺寸內容,或按比例縮小並在目標槽位內對齊
分頁政策可允許正常切分、把第一個部分片段延後到新區域,或要求整個元件在提交任何內容前保持可見
flow-space 約束可在呼叫元件前拒絕過短的區域,或在其最終片段之後為下一個元件保留足夠高度
被拒的結果、失敗的繪製呼叫或回呼例外會移除暫時頁面、還原呼叫者所選頁面,目標內容與目前元件狀態都保持不變
附加的 TPDFlib 執行個體仍由呼叫者擁有,且必須比 session 存活更久
宣告
const
PDF_DYNAMIC_COMPONENT_ERROR = 0;
PDF_DYNAMIC_COMPONENT_MORE = 1;
PDF_DYNAMIC_COMPONENT_COMPLETE = 2;
PDF_DYNAMIC_COMPONENT_RETRY = 3;
type
TPDFlibDynamicPageContext = record
LibraryInstance: TPDFlib;
PageNumber: Integer;
CompositionIndex: Integer;
DestinationLeft: Double;
DestinationTop: Double;
AvailableWidth: Double;
AvailableHeight: Double;
end;
TPDFlibDynamicPageResult = record
HasContent: Boolean;
HasMoreContent: Boolean;
UsedWidth: Double;
UsedHeight: Double;
end;
TPDFlibDynamicOverflowPolicy = (dopReject, dopClip, dopScaleDown);
TPDFlibDynamicHorizontalAlignment = (dhaLeft, dhaCenter, dhaRight);
TPDFlibDynamicVerticalAlignment = (dvaTop, dvaCenter, dvaBottom);
TPDFlibDynamicPaginationPolicy = (dppAllowSplit, dppKeepTogether,
dppRequireComplete);
TPDFlibDynamicRetryReason = (drrNone, drrKeepTogether,
drrRequireComplete, drrMinimumSlotHeight, drrMinimumFollowingHeight);
TPDFlibDynamicLayoutOptions = record
ContentWidth: Double;
ContentHeight: Double;
OverflowPolicy: TPDFlibDynamicOverflowPolicy;
HorizontalAlignment: TPDFlibDynamicHorizontalAlignment;
VerticalAlignment: TPDFlibDynamicVerticalAlignment;
PaginationPolicy: TPDFlibDynamicPaginationPolicy;
MinimumSlotHeight: Double;
MinimumFollowingHeight: Double;
end;
TPDFlibDynamicPlacementTransform = record
M11, M12, M21, M22, MDX, MDY: Double;
end;
TPDFlibDynamicPagePlacement = record
PageNumber: Integer;
CompositionIndex: Integer;
Left: Double;
Top: Double;
Width: Double;
Height: Double;
HasContent: Boolean;
HasMoreContent: Boolean;
SourceWidth: Double;
SourceHeight: Double;
SlotLeft: Double;
SlotTop: Double;
SlotWidth: Double;
SlotHeight: Double;
Transform: TPDFlibDynamicPlacementTransform;
WasClipped: Boolean;
WasScaled: Boolean;
end;
TPDFlibDynamicComponent = class
public
function CloneComponent: TPDFlibDynamicComponent; virtual; abstract;
function Compose(const Context: TPDFlibDynamicPageContext;
out ComposeResult: TPDFlibDynamicPageResult): Integer; virtual; abstract;
end;
TPDFlibDynamicComponentSession = class
private
FLibrary: TPDFlib;
FCompositionCount: Integer;
FCompleted: Boolean;
FKeepTogetherRetryPending: Boolean;
FLastRetryReason: TPDFlibDynamicRetryReason;
FLastRequiredSlotHeight: Double;
public
constructor Create(ALibrary: TPDFlib;
AComponent: TPDFlibDynamicComponent);
function AttachComponent(AComponent: TPDFlibDynamicComponent): Integer;
function Reset: Integer;
function CloneCurrentComponent: TPDFlibDynamicComponent;
class function CreateLayoutOptions(ContentWidth, ContentHeight: Double;
OverflowPolicy: TPDFlibDynamicOverflowPolicy = dopReject;
HorizontalAlignment: TPDFlibDynamicHorizontalAlignment = dhaLeft;
VerticalAlignment: TPDFlibDynamicVerticalAlignment = dvaTop;
PaginationPolicy: TPDFlibDynamicPaginationPolicy = dppAllowSplit;
MinimumSlotHeight: Double = 0;
MinimumFollowingHeight: Double = 0):
TPDFlibDynamicLayoutOptions; static;
function ComposeNext(Page: Integer; Left, Top, Width, Height: Double;
out Placement: TPDFlibDynamicPagePlacement): Integer;
function ComposeNextLayout(Page: Integer; SlotLeft, SlotTop, SlotWidth,
SlotHeight: Double; const Options: TPDFlibDynamicLayoutOptions;
out Placement: TPDFlibDynamicPagePlacement): Integer;
property LibraryInstance: TPDFlib read FLibrary;
property CompositionCount: Integer read FCompositionCount;
property Completed: Boolean read FCompleted;
property KeepTogetherRetryPending: Boolean
read FKeepTogetherRetryPending;
property LastRetryReason: TPDFlibDynamicRetryReason read FLastRetryReason;
property LastRequiredSlotHeight: Double read FLastRequiredSlotHeight;
end;
元件合約
CloneComponent會傳回所有可變分頁狀態中與呼叫端無關的複本Compose透過Context.LibraryInstance以區域 Form 座標繪圖,其可用大小為AvailableWidth乘以AvailableHeightPageNumber識別目的地頁面,即使在回呼執行期間程式庫選取的是隔離的暫時頁面- 回呼可以使用繪圖與內容 API,但不得變更文件、頁面或巢狀繪圖容器
- 內容結果需要在內容畫布內有限的正值
UsedWidth與UsedHeight - 使用的矩形從區域座標零開始,並應涵蓋所有可見的元件內容
- 無內容的結果只有在
HasMoreContent為False且兩個使用維度皆為零時才有效 - 傳回零表示拒絕該次嘗試;引發的例外狀況會在暫時狀態清理完畢後傳播
方法
| Create | 附加呼叫端擁有的程式庫,並將提供的元件複製成獨立的初始與目前快照 |
|---|---|
| AttachComponent | 以呼叫端擁有元件的複本,以原子方式取代兩個快照,並清除完成狀態 |
| Reset | 從初始快照還原新的目前複本,並重設成功的組合計數 |
| CloneCurrentComponent | 傳回呼叫端擁有的複本,用於檢視目前已提交的元件狀態 |
| CreateLayoutOptions | 為延伸放置建立具型別的自然畫布、溢出、對齊、分頁與流排空間設定 |
| ComposeNext | 組合一個頁面插槽、驗證並放置其 Form XObject、釋放擷取控制代碼,並提交工作狀態 |
| ComposeNextLayout | 在設定的自然畫布上組合、套用溢出與對齊原則,並傳回來源、插槽與最終轉換資料 |
溢出與放置
dopReject | 拒絕比插槽更寬或更高的內容,且不變更目的地內容或已提交的元件狀態 |
|---|---|
dopClip | 保持縮放 1,並在叫用 Form XObject 之前將頁面剪裁路徑與目的地插槽相交 |
dopScaleDown | 只在需要時使用較小的寬度或高度比例,且絕不放大內容 |
對齊會從轉換後的使用矩形解析,因此置中或尾端被裁剪的內容會選取對應的可見部分
Transform[M11 M12 M21 M22 MDX MDY]
SlotLeft 回報從元件區域座標到最終由上而下文件座標的邏輯版面矩陣 SlotTop
SlotWidth、SlotHeight、
分頁原則
dppAllowSplit | 保留預設行為,並提交其回呼回報還有更多內容的任何有效片段 |
|---|---|
dppKeepTogether | 第一次出現部分或不可見的嘗試時傳回 PDF_DYNAMIC_COMPONENT_RETRY,然後在同一個未提交片段的下一次有效嘗試時允許分割或所選的裁剪後備 |
dppRequireComplete | 持續傳回 PDF_DYNAMIC_COMPONENT_RETRY,直到回呼回報沒有剩餘內容,且完整的使用矩形能符合插槽,或透過等比例縮小保持可見 |
Placement
KeepTogetherRetryPending 記錄
Reset 識別單次後備狀態,並在成功提交、AttachComponent 或
流程空間限制
MinimumSlotHeight | 目標槽位短於設定高度時,在複製或呼叫元件之前即傳回 PDF_DYNAMIC_COMPONENT_RETRY |
|---|---|
MinimumFollowingHeight | 只適用於最終內容片段,要求其解析高度加上保留的後續高度能放進槽位 |
後續高度重試會捨棄隔離的試排、保留先前已提交的片段,讓標題、標籤或短導入能跟著下一個元件的第一個可用區域一起移動
LastRetryReason 區分整元件、嚴格完整、最小槽位與後續空間重試;LastRequiredSlotHeight 回報 flow-space 約束已知的所需高度
最小槽位檢查在元件複製與 Form 擷取之前執行,因此反覆被拒的過短區域不會產生元件回呼或暫時頁面成本
傳回值
PDF_DYNAMIC_COMPONENT_ERROR | 請求、元件回呼、結果幾何或 Form 放置失敗,且未提交任何狀態 |
|---|---|
PDF_DYNAMIC_COMPONENT_MORE | 內容已提交,且元件要求另一個頁面插槽 |
PDF_DYNAMIC_COMPONENT_COMPLETE | 元件已完成,或工作階段已經完成而未進行任何回呼 |
PDF_DYNAMIC_COMPONENT_RETRY | 所選的分頁或流排空間原則延後放置,而未提交內容或狀態 |
範例
type
TNumberedPagesComponent = class(TPDFlibDynamicComponent)
private
FNextPage: Integer;
FPageCount: Integer;
public
constructor Create(ANextPage, APageCount: Integer);
function CloneComponent: TPDFlibDynamicComponent; override;
function Compose(const Context: TPDFlibDynamicPageContext;
out ComposeResult: TPDFlibDynamicPageResult): Integer; override;
end;
constructor TNumberedPagesComponent.Create(ANextPage, APageCount: Integer);
begin
inherited Create;
FNextPage := ANextPage;
FPageCount := APageCount;
end;
function TNumberedPagesComponent.CloneComponent: TPDFlibDynamicComponent;
begin
Result := TNumberedPagesComponent.Create(FNextPage, FPageCount);
end;
function TNumberedPagesComponent.Compose(
const Context: TPDFlibDynamicPageContext;
out ComposeResult: TPDFlibDynamicPageResult): Integer;
begin
Context.LibraryInstance.DrawText(0, 0, IntToStr(FNextPage));
Inc(FNextPage);
ComposeResult.HasContent := True;
ComposeResult.HasMoreContent := FNextPage <= FPageCount;
ComposeResult.UsedWidth := Context.AvailableWidth;
ComposeResult.UsedHeight := 24;
Result := 1;
end;
Template := TNumberedPagesComponent.Create(1, 10);
try
Session := TPDFlibDynamicComponentSession.Create(PDF, Template);
try
repeat
Status := Session.ComposeNext(PageNumber, 36, 36, 540, 720,
Placement);
if Status = PDF_DYNAMIC_COMPONENT_MORE then
PageNumber := PDF.NewPage;
until Status <> PDF_DYNAMIC_COMPONENT_MORE;
finally
Session.Free;
end;
finally
Template.Free;
end;
另請參閱
BeginFormXObject, ReleaseCapturedPage, ApplyRepeatedPageFragment