TPDFlibDynamicComponentSession

Sidelayout, paginering, datatyper

Beskrivelse

Komponerer en tilstandsfuld komponent én destinationsside ad gangen uden på forhånd at opbygge indhold til senere sider

Hvert forsøg kører på en klon inde i en isoleret Form XObject og committer klonen først, efter at valideret indhold er placeret med succes

Udvidet placering kan afvise overløb, klippe indhold i naturlig størrelse eller skalere det ned proportionalt, mens det justeres inden for en destinationsplads

Pagineringspolitik kan tillade normal deling, udskyde det første delvise fragment til en frisk region eller kræve, at hele komponenten forbliver synlig, før noget committes

Flow-space-begrænsninger kan afvise en kort region før kald af komponenten eller reservere nok højde efter dens sidste fragment til en følgende komponent

Et afvist resultat, et fejlet tegnekald eller en callback-undtagelse fjerner den midlertidige side, gendanner kalderens valgte side og efterlader både destinationsindhold og aktuel komponenttilstand uændret

Den tilknyttede TPDFlib-instans forbliver ejet af kalderen og skal overleve sessionen

Deklaration

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;

Komponentkontrakt

Metoder

CreateTilknytter et kalder-ejet bibliotek og kloner den angivne komponent til uafhængige snapshots af begyndelses- og aktuel tilstand
AttachComponentErstatter atomært begge snapshots med kloner af en kalder-ejet komponent og rydder fuldførelsestilstanden
ResetGendanner en ny aktuel klon fra begyndelsessnapshotet og nulstiller antallet af succesfulde kompositioner
CloneCurrentComponentReturnerer en kalder-ejet klon til inspektion af den aktuelle committede komponenttilstand
CreateLayoutOptionsOpbygger typede indstillinger for naturligt lærred, overløb, justering, paginering og flowrum til udvidet placering
ComposeNextKomponerer én sideslot, validerer og placerer dets Form XObject, frigiver fangsthandlet og committer arbejdstilstanden
ComposeNextLayoutKomponerer på det konfigurerede naturlige lærred, anvender overløbs- og justeringspolitik og returnerer kilde-, slot- og endelige transformdata

Overløb og placering

dopRejectAfviser indhold, der er bredere eller højere end slotten, uden at ændre destinationsindhold eller committed komponenttilstand
dopClipBevarer skalering 1 og skærer sideklippestien sammen med destinationsslotten, før Form XObject kaldes
dopScaleDownBruger kun den mindre bredde- eller højderatio, når det er nødvendigt, og forstørrer aldrig indhold

Justeringen opløses ud fra det transformerede anvendte rektangel, så centreret eller til slut klippet indhold vælger den tilsvarende synlige del

Transform[M11 M12 M21 M22 MDX MDY]

SlotLeft rapporterer den logiske layoutmatrice SlotTop fra komponentlokale koordinater til de endelige top-down dokumentkoordinater SlotWidth, SlotHeight,

Pagineringspolitikker

dppAllowSplitBevarer standardopførslen og committer ethvert gyldigt fragment, hvis callback rapporterer mere indhold
dppKeepTogetherReturnerer PDF_DYNAMIC_COMPONENT_RETRY for det første delvise eller ikke-synlige forsøg og tillader derefter opdeling eller den valgte klippe-fallback ved det næste gyldige forsøg for det samme ucommittede fragment
dppRequireCompleteReturnerer PDF_DYNAMIC_COMPONENT_RETRY, indtil callbacken rapporterer intet resterende indhold, og det fulde anvendte rektangel enten passer i slotten eller forbliver synligt gennem proportional nedskalering

Placement

KeepTogetherRetryPending-post Reset identificerer engangs-fallback-tilstanden og ryddes efter en succesfuld commit, AttachComponent eller

Flow-space-begrænsninger

MinimumSlotHeightReturnerer PDF_DYNAMIC_COMPONENT_RETRY før kloning eller kald af komponenten, når destinationspladsen er kortere end den konfigurerede højde
MinimumFollowingHeightGælder kun en sidste indholdsfragment og kræver, at dens afgjorte højde plus den reserverede følgende højde passer i pladsen

En følgende-højde-gentagelse kasserer det isolerede forsøg, mens tidligere committede fragmenter bevares, så en overskrift, etikette eller kort indledning kan flytte med den første brugbare region af næste komponent

LastRetryReason skelner helkomponent-, streng-fuldførelses-, minimumsplads- og følgende-rums-gentagelser, mens LastRequiredSlotHeight rapporterer den kendte krævede højde for flow-space-begrænsninger

Minimumsplads-kontrollen kører før komponentkloning og Form-fangst, så gentagne afviste korte områder ikke medfører komponent-callback eller midlertidig side-omkostning

Returværdier

PDF_DYNAMIC_COMPONENT_ERRORAnmodningen, komponent-callbacken, resultatgeometrien eller Form-placeringen mislykkedes, og ingen tilstand blev committet
PDF_DYNAMIC_COMPONENT_MOREIndholdet blev committet, og komponenten anmodede om en ny sideslot
PDF_DYNAMIC_COMPONENT_COMPLETEKomponenten fuldførte, eller sessionen var allerede fuldført, og der blev ikke foretaget noget callback
PDF_DYNAMIC_COMPONENT_RETRYDen valgte paginerings- eller flowrumspolitik udskød placeringen uden at committe indhold eller tilstand

Eksempel

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;

Se også

BeginFormXObject, ReleaseCapturedPage, ApplyRepeatedPageFragment