TPDFlibDynamicComponentSession
페이지 레이아웃, 페이지 매김, 데이터 타입
설명
상태를 지닌 컴포넌트를, 이후 페이지의 콘텐츠를 미리 만들지 않고 한 번에 한 대상 페이지씩 합성합니다
각 시도는 격리된 Form XObject 안의 클론에서 실행되며, 검증된 콘텐츠가 성공적으로 배치된 뒤에만 클론을 커밋합니다
확장 배치는 오버플로를 거부하거나, 자연 크기 콘텐츠를 클립하거나, 대상 슬롯 안에 정렬하며 비례 축소할 수 있습니다
페이지 매김 정책은 보통 분할을 허용하거나, 첫 부분 프래그먼트를 새 영역으로 미루거나, 무언가를 커밋하기 전에 컴포넌트 전체가 보이기를 요구할 수 있습니다
흐름 공간 제약은 컴포넌트를 호출하기 전에 짧은 영역을 거부하거나, 마지막 프래그먼트 뒤에 다음 컴포넌트를 위한 충분한 높이를 확보할 수 있습니다
거부된 결과, 실패한 그리기 호출, 콜백 예외는 임시 페이지를 제거하고 호출자가 선택한 페이지를 복원하며, 대상 콘텐츠와 현재 컴포넌트 상태 둘 다 그대로 둡니다
연결된 TPDFlib 인스턴스는 호출자 소유로 남아 세션보다 오래 살아 있어야 합니다
선언
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×AvailableHeight입니다PageNumber는 콜백이 실행되는 동안 라이브러리가 격리된 임시 페이지를 선택하더라도 대상 페이지를 식별합니다- 콜백은 그리기 및 콘텐츠 API를 사용할 수 있지만 문서, 페이지, 중첩된 그리기 컨테이너를 변경해서는 안 됩니다
- 콘텐츠 결과에는 콘텐츠 캔버스 안의 유한한 양수
UsedWidth와UsedHeight값이 필요합니다 - 사용된 사각형은 로컬 좌표 0에서 시작하며 표시되는 모든 컴포넌트 콘텐츠를 감싸야 합니다
- 콘텐츠 없는 결과는
HasMoreContent가False이고 사용된 두 치수가 모두 0일 때만 유효합니다 - 0을 반환하면 시도가 거부되며, 발생한 예외는 임시 상태가 정리된 후 전파됩니다
메서드
| 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를 반환합니다 |
재시도는 Form XObject 시행을 버리고, 대상 페이지, 컴포넌트 스냅샷, 완료 플래그, 합성 카운트를 보존하며, 빈 Placement 레코드를 반환합니다
KeepTogetherRetryPending은 일회용 폴백 상태를 식별하며 성공한 커밋, Reset, AttachComponent 뒤에 지워집니다
흐름 공간 제약
MinimumSlotHeight | 대상 슬롯이 설정된 높이보다 짧으면 컴포넌트를 클론하거나 호출하기 전에 PDF_DYNAMIC_COMPONENT_RETRY를 반환합니다 |
|---|---|
MinimumFollowingHeight | 마지막 콘텐츠 프래그먼트에만 적용되며, 해석된 높이에 예약된 다음 높이를 더한 값이 슬롯에 들어가기를 요구합니다 |
다음 높이 재시도는 이전에 커밋된 프래그먼트를 보존하면서 격리 시행을 버려, 제목이나 레이블, 짧은 도입부가 다음 컴포넌트의 첫 사용 가능 영역과 함께 움직일 수 있게 합니다
LastRetryReason은 전체 컴포넌트, 엄격 완결, 최소 슬롯, 다음 공간 재시도를 구별하고, LastRequiredSlotHeight는 흐름 공간 제약의 알려진 요구 높이를 보고합니다
최소 슬롯 검사는 컴포넌트 클론과 폼 캡처 전에 실행되므로, 거듭 거부되는 짧은 영역이 컴포넌트 콜백이나 임시 페이지 비용을 내지 않습니다
반환 값
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