TPDFlibDynamicComponentSession

Rozvržení stránek, stránkování, datové typy

Popis

Skládá stavovou komponentu vždy na jednu cílovou stránku, aniž by dopředu stavěla obsah pozdějších stránek

Každý pokus běží na klonu uvnitř izolovaného Form XObject a potvrzuje klon, jen když je ověřený obsah úspěšně umístěn

Rozšířené umístění může odmítnout přetečení, oříznout obsah v přirozené velikosti nebo jej proporcionálně zmenšit, zatímco jej zarovnává uvnitř cílového slotu

Politika stránkování může dovolit normální rozdělení, odložit první částečný fragment do čerstvé oblasti nebo vyžadovat, aby celá komponenta zůstala viditelná, než se cokoli potvrdí

Omezení prostoru toku mohou odmítnout krátkou oblast před vyvoláním komponenty, nebo po jejím posledním fragmentu rezervovat dostatečnou výšku pro následující komponentu

Odmítnutý výsledek, neúspěšné kreslicí volání nebo výjimka zpětného volání odstraní dočasnou stránku, obnoví stránku vybranou volajícím a ponechá obsah cíle i aktuální stav komponenty beze změny

Připojená instance TPDFlib zůstává ve vlastnictví volajícího a musí přežít relaci

Deklarace

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;

Kontrakt komponenty

Metody

CreatePřipojí knihovnu vlastněnou volajícím a naklonuje dodanou komponentu do nezávislých snímků počátečního a aktuálního stavu
AttachComponentAtomicky nahradí oba snímky klony komponenty vlastněné volajícím a vymaže stav dokončení
ResetObnoví nový aktuální klon z počátečního snímku a vynuluje počet úspěšných kompozic
CloneCurrentComponentVrací klon ve vlastnictví volajícího k prohlédnutí aktuálního potvrzeného stavu komponenty
CreateLayoutOptionsSestaví typovaná nastavení přirozeného plátna, přetečení, zarovnání, paginace a prostoru toku pro rozšířené umístění
ComposeNextSkládá jeden slot stránky, ověří a umístí jeho Form XObject, uvolní handle zachycení a potvrdí pracovní stav
ComposeNextLayoutSkládá na nakonfigurovaném přirozeném plátně, aplikuje politiku přetečení a zarovnání a vrací data zdroje, slotu i finální transformace

Přetečení a umístění

dopRejectOdmítá obsah širší nebo vyšší než slot, aniž by měnila obsah cíle nebo potvrzený stav komponenty
dopClipDrží měřítko 1 a protnout klipovou cestu stránky s cílovým slotem, než vyvolá Form XObject
dopScaleDownMenší poměr šířky či výšky používá jen tehdy, když je to potřeba, a nikdy nezvětšuje obsah

Zarovnání se rozliší z transformovaného používaného obdélníku, takže vycentrovaný nebo na konci oříznutý obsah si vybere odpovídající viditelnou část

Transform hlásí logickou matici rozvržení [M11 M12 M21 M22 MDX MDY] z komponentou lokálních souřadnic na finální souřadnice dokumentu shora dolů

SlotLeft, SlotTop, SlotWidth a SlotHeight zachovávají oblast dodanou volajícím, i když původ finálního obsahu leží pod ořezem mimo ni

Zásady stránkování

dppAllowSplitZachovává výchozí chování a potvrdí jakýkoli platný fragment, jehož zpětné volání hlásí další obsah
dppKeepTogetherVrací PDF_DYNAMIC_COMPONENT_RETRY pro první částečnou či neviditelnou zkoušku, a pak dovolí rozdělení nebo vybranou ořezovou náhradu při dalším platném pokusu pro tentýž nepotvrzený fragment
dppRequireCompleteVrací PDF_DYNAMIC_COMPONENT_RETRY, dokud zpětné volání nehlásí žádný zbývající obsah a kompletní použitý obdélník se buď vejde do slotu, nebo zůstane viditelný proporcionalním zmenšením

Opakování zahodí zkušební Form XObject, zachová cílovou stránku, snímek komponenty, příznak dokončení a počet skladeb a vrátí prázdný záznam Placement

KeepTogetherRetryPending identifikuje stav jednorázové náhrady a maže se po úspěšném potvrzení, Reset nebo AttachComponent

Omezení prostoru toku

MinimumSlotHeightVrací PDF_DYNAMIC_COMPONENT_RETRY před klonováním nebo vyvoláním komponenty, když je cílový slot kratší než nakonfigurovaná výška
MinimumFollowingHeightVztahuje se jen na konečný obsahový fragment a vyžaduje, aby jeho rozlišená výška plus rezervovaná následná výška se vešly do slotu

Opakování kvůli následné výšce zahodí izolovanou zkoušku, zatímco dříve potvrzené fragmenty zachová, takže nadpis, popisek nebo krátký úvod se mohou přemístit s první použitelnou oblastí další komponenty

LastRetryReason rozlišuje opakování celé komponenty, striktního dokončení, minimálního slotu a následného prostoru, zatímco LastRequiredSlotHeight hlásí známou požadovanou výšku pro omezení prostoru toku

Kontrola minimálního slotu běží před klonováním komponenty a zachytáváním Form, takže opakovaně odmítnuté krátké oblasti nenesou žádné náklady na zpětné volání komponenty ani dočasnou stránku

Návratové hodnoty

PDF_DYNAMIC_COMPONENT_ERRORPožadavek, callback komponenty, výsledná geometrie nebo umístění Formu selhalo a žádný stav nebyl potvrzen
PDF_DYNAMIC_COMPONENT_MOREObsah byl potvrzen a komponenta si vyžádala další slot stránky
PDF_DYNAMIC_COMPONENT_COMPLETEKomponenta dokončila, nebo už byla relace dokončená a callback se neuskutečnil
PDF_DYNAMIC_COMPONENT_RETRYVybraná politika paginace nebo prostoru toku odložila umístění bez potvrzení obsahu či stavu

Příklad

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;

Viz také

BeginFormXObject, ReleaseCapturedPage, ApplyRepeatedPageFragment