TPDFlibDynamicComponentSession

Mise en page, pagination, types de données

Description

Compose un composant avec état une page de destination à la fois sans construire à l'avance le contenu des pages suivantes

Chaque tentative s'exécute sur un clone dans un Form XObject isolé et ne valide le clone qu'après que le contenu validé a été placé avec succès

Le placement étendu peut rejeter le débordement, rogner le contenu à taille naturelle ou le réduire proportionnellement en l'alignant dans un emplacement de destination

La politique de pagination peut autoriser la division normale, différer le premier fragment partiel vers une région fraîche ou exiger que le composant entier reste visible avant de valider quoi que ce soit

Les contraintes d'espace de flux peuvent rejeter une région courte avant d'invoquer le composant ou réserver assez de hauteur après son dernier fragment pour un composant suivant

Un résultat rejeté, un appel de dessin échoué ou une exception de callback supprime la page temporaire, restaure la page sélectionnée par l'appelant et laisse le contenu de destination et l'état du composant actuel inchangés

TPDFlib attachée reste la propriété de l'appelant et doit survivre à la session

Déclaration

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;

Contrat du composant

Méthodes

CreateAttache une bibliothèque propriété de l'appelant et clone le composant fourni en instantanés initial et courant indépendants
AttachComponentRemplace atomiquement les deux instantanés par des clones d'un composant propriété de l'appelant et efface l'état d'achèvement
ResetRestaure un nouveau clone courant à partir de l'instantané initial et réinitialise le compteur de compositions réussies
CloneCurrentComponentRetourne un clone propriété de l'appelant pour inspecter l'état du composant courant validé
CreateLayoutOptionsConstruit des réglages typés de canevas naturel, de débordement, d'alignement, de pagination et d'espace de flux pour le placement étendu
ComposeNextCompose un emplacement de page, valide et place son Form XObject, libère le handle de capture et valide l'état de travail
ComposeNextLayoutCompose sur le canevas naturel configuré, applique la politique de débordement et d'alignement et retourne les données de source, d'emplacement et de transformation finale

Débordement et placement

dopRejectRejette un contenu plus large ou plus haut que l'emplacement sans changer le contenu de destination ni l'état validé du composant
dopClipConserve l'échelle 1 et intersecte le chemin de détourage de la page avec l'emplacement de destination avant d'invoquer le Form XObject
dopScaleDownUtilise le plus petit rapport de largeur ou de hauteur uniquement si nécessaire et n'agrandit jamais le contenu

L'alignement est résolu à partir du rectangle utilisé transformé, de sorte qu'un contenu centré ou tronqué en queue sélectionne la portion visible correspondante

Transform[M11 M12 M21 M22 MDX MDY]

SlotLeft signale la matrice logique de mise en page SlotTop des coordonnées locales du composant vers les coordonnées finales du document vertical descendant SlotWidth, SlotHeight,

Règles de pagination

dppAllowSplitPréserve le comportement par défaut et valide tout fragment valide dont le callback signale du contenu supplémentaire
dppKeepTogetherRetourne PDF_DYNAMIC_COMPONENT_RETRY pour la première tentative partielle ou non visible, puis autorise la scission ou le repli de rognage sélectionné à la prochaine tentative valide pour le même fragment non validé
dppRequireCompleteRetourne PDF_DYNAMIC_COMPONENT_RETRY jusqu'à ce que le callback signale qu'il ne reste aucun contenu et que le rectangle utilisé complet tienne dans l'emplacement ou reste visible après réduction proportionnelle

Placement

KeepTogetherRetryPending vide Reset identifie l'état de repli à usage unique et est effacé après une validation réussie, AttachComponent ou

Contraintes d'espace de flux

MinimumSlotHeightRetourne PDF_DYNAMIC_COMPONENT_RETRY avant le clonage ou l'invocation du composant lorsque l'emplacement de destination est plus court que la hauteur configurée
MinimumFollowingHeightNe s'applique qu'à un fragment de contenu final et exige que sa hauteur résolue plus la hauteur de suite réservée tiennent dans l'emplacement

Une nouvelle tentative pour la hauteur de suite abandonne l'essai isolé tout en préservant les fragments antérieurs validés, permettant à un titre, une étiquette ou une courte amorce de suivre la première région utilisable du composant suivant

LastRetryReason distingue les réessais de composant entier, d'achèvement strict, de slot minimum et d'espace suivant, tandis que LastRequiredSlotHeight signale la hauteur requise connue pour les contraintes d'espace de flux

La vérification de slot minimum s'exécute avant le clonage du composant et la capture du Form, si bien les régions courtes rejetées à répétition n'encourent aucun coût de callback de composant ni de page temporaire

Valeurs de retour

PDF_DYNAMIC_COMPONENT_ERRORLa requête, le callback du composant, la géométrie du résultat ou le placement du Form a échoué et aucun état n'a été validé
PDF_DYNAMIC_COMPONENT_MORELe contenu a été validé et le composant a demandé un autre emplacement de page
PDF_DYNAMIC_COMPONENT_COMPLETELe composant est achevé, ou la session était déjà achevée et aucun callback n'a été effectué
PDF_DYNAMIC_COMPONENT_RETRYLa politique de pagination ou d'espace de flux sélectionnée a reporté le placement sans valider de contenu ni d'état

Exemple

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;

Voir aussi

BeginFormXObject, ReleaseCapturedPage, ApplyRepeatedPageFragment