TPDFlibDynamicComponentSession

Układ strony, paginacja, typy danych

Opis

Komponuje komponent ze stanem po jednej stronie docelowej naraz, bez wcześniejszego budowania treści dla późniejszych stron

Każda próba biegnie na klonie wewnątrz izolowanego Form XObject i zatwierdza klon dopiero po pomyślnym umieszczeniu zwalidowanej treści

Rozszerzone umieszczanie może odrzucić przepełnienie, przyciąć treść o naturalnym rozmiarze albo przeskalować ją proporcjonalnie w dół, wyrównując ją w gnieździe docelowym

Polityka paginacji może pozwolić na normalny podział, odroczyć pierwszy fragment częściowy do świeżego regionu albo wymagać, by cały komponent pozostał widoczny przed zatwierdzeniem czegokolwiek

Ograniczenia przestrzeni przepływu mogą odrzucić krótki region przed wywołaniem komponentu albo zarezerwować dość wysokości po jego ostatnim fragmencie dla komponentu następnego

Odrzucony wynik, nieudane wywołanie rysowania albo wyjątek wywołania zwrotnego usuwa stronę tymczasową, przywraca stronę wybraną przez wywołującego i zostawia i treść celu, i bieżący stan komponentu bez zmian

Dołączona instancja TPDFlib pozostaje własnością wywołującego i musi przeżyć sesję

Deklaracja

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 komponentu

Metody

CreatePodłącza bibliotekę należącą do wywołującego i klonuje podany komponent do niezależnych migawek początkowej i bieżącej
AttachComponentAtomowo zastępuje obie migawki klonami komponentu należącego do wywołującego i czyści stan ukończenia
ResetOdtwarza nowy bieżący klon z migawki początkowej i resetuje licznik udanych kompozycji
CloneCurrentComponentZwraca klon należący do wywołującego do przeglądania bieżącego zatwierdzonego stanu komponentu
CreateLayoutOptionsBuduje typowane ustawienia naturalnego płótna, przepełnienia, wyrównania, paginacji i przestrzeni przepływu dla rozszerzonego rozmieszczania
ComposeNextKomponuje jedno gniazdo strony, waliduje i rozmieszcza jego Form XObject, zwalnia uchwyt przechwycenia i zatwierdza stan roboczy
ComposeNextLayoutKomponuje na skonfigurowanym naturalnym płótnie, stosuje politykę przepełnienia i wyrównania oraz zwraca dane źródła, gniazda i przekształcenia końcowego

Przepełnienie i rozmieszczanie

dopRejectOdrzuca treść szerszą albo wyższą niż gniazdo bez zmiany treści docelowej ani zatwierdzonego stanu komponentu
dopClipZachowuje skalę 1 i przecina ścieżkę przycinania strony z gniazdem docelowym przed wywołaniem Form XObject
dopScaleDownUżywa mniejszego stosunku szerokości albo wysokości tylko w razie potrzeby i nigdy nie powiększa treści

Wyrównanie jest rozstrzygane z przekształconego użytego prostokąta, więc wyśrodkowana albo końcowa przycięta treść wybiera odpowiadającą widoczną część

Transform[M11 M12 M21 M22 MDX MDY]

SlotLeft raportuje logiczną macierz układu SlotTop ze współrzędnych lokalnych komponentu do końcowych współrzędnych dokumentu od góry w dół SlotWidth, SlotHeight,

Zasady paginacji

dppAllowSplitZachowuje domyślne zachowanie i zatwierdza każdy prawidłowy fragment, którego procedura zwrotna raportuje więcej treści
dppKeepTogetherZwraca PDF_DYNAMIC_COMPONENT_RETRY dla pierwszej częściowej albo niewidocznej próby, a przy następnej prawidłowej próbie tego samego niezatwierdzonego fragmentu dopuszcza dzielenie albo wybrane rozwiązanie zapasowe przycinania
dppRequireCompleteZwraca PDF_DYNAMIC_COMPONENT_RETRY, dopóki procedura zwrotna nie raportuje braku pozostałej treści, a cały użyty prostokąt zmieści się w gnieździe albo pozostanie widoczny dzięki proporcjonalnemu pomniejszeniu

Placement

KeepTogetherRetryPending Reset identyfikuje jednorazowy stan rozwiązania zapasowego i jest czyszczony po udanym zatwierdzeniu, AttachComponent albo

Ograniczenia przestrzeni przepływu

MinimumSlotHeightZwraca PDF_DYNAMIC_COMPONENT_RETRY przed klonowaniem albo wywołaniem komponentu, gdy gniazdo docelowe jest krótsze niż skonfigurowana wysokość
MinimumFollowingHeightDotyczy wyłącznie ostatniego fragmentu treści i wymaga, by jego rozwiązana wysokość plus zarezerwowana wysokość następnika zmieściły się w gnieździe

Ponowienie z powodu wysokości następnika porzuca izolowaną próbę, zachowując wcześniej zatwierdzone fragmenty, więc nagłówek, etykieta albo krótki wstęp mogą przenieść się z pierwszym użytecznym regionem następnego komponentu

LastRetryReason rozróżnia ponowienia całego komponentu, ścisłego ukończenia, minimalnego gniazda i przestrzeni następnika, a LastRequiredSlotHeight raportuje znaną wymaganą wysokość dla ograniczeń przestrzeni przepływu

Kontrola minimalnego gniazda biegnie przed klonowaniem komponentu i przechwyceniem Form, więc wielokrotnie odrzucane krótkie regiony nie ponoszą kosztu wywołania zwrotnego komponentu ani strony tymczasowej

Wartości zwracane

PDF_DYNAMIC_COMPONENT_ERRORŻądanie, procedura zwrotna komponentu, geometria wyniku albo rozmieszczenie Form zawiodły i nie zatwierdzono żadnego stanu
PDF_DYNAMIC_COMPONENT_MORETreść została zatwierdzona, a komponent zażądał kolejnego gniazda strony
PDF_DYNAMIC_COMPONENT_COMPLETEKomponent został ukończony albo sesja była już ukończona i procedura zwrotna nie została wywołana
PDF_DYNAMIC_COMPONENT_RETRYWybrana polityka paginacji albo przestrzeni przepływu odroczyła rozmieszczenie bez zatwierdzania treści ani stanu

Przykład

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;

Zobacz również

BeginFormXObject, ReleaseCapturedPage, ApplyRepeatedPageFragment