TPDFlibDynamicComponentSession

Diseño de página, paginación, tipos de datos

Descripción

Compone un componente con estado una página de destino a la vez sin construir por adelantado contenido de páginas posteriores

Cada intento corre sobre un clon dentro de un Form XObject aislado y confirma el clon solo después de que el contenido validado se haya colocado con éxito

La colocación extendida puede rechazar el desbordamiento, recortar el contenido de tamaño natural o reducirlo proporcionalmente alineándolo dentro de una ranura de destino

La política de paginación puede permitir la división normal, diferir el primer fragmento parcial a una región fresca o exigir que el componente completo permanezca visible antes de confirmar nada

Las restricciones de espacio de flujo pueden rechazar una región corta antes de invocar al componente o reservar altura suficiente tras su fragmento final para un componente siguiente

Un resultado rechazado, una llamada de dibujo fallida o una excepción de retrollamada elimina la página temporal, restaura la página seleccionada por el llamador y deja tanto el contenido de destino como el estado del componente actual sin cambios

TPDFlib adjunta permanece siendo propiedad del llamador y debe sobrevivir a la sesión

Declaración

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;

Contrato del componente

Métodos

CreateAdjunta una biblioteca propiedad del llamador y clona el componente suministrado en instantáneas iniciales y actuales independientes
AttachComponentReemplaza atómicamente ambas instantáneas por clones de un componente propiedad del llamador y borra el estado de finalización
ResetRestaura un nuevo clon actual desde la instantánea inicial y restablece el recuento de composiciones con éxito
CloneCurrentComponentDevuelve un clon propiedad del llamador para inspeccionar el estado actual del componente confirmado
CreateLayoutOptionsConstruye ajustes con tipos de lienzo natural, desbordamiento, alineación, paginación y espacio de flujo para la colocación extendida
ComposeNextCompone una ranura de página, valida y coloca su Form XObject, libera el manipulador de captura y confirma el estado de trabajo
ComposeNextLayoutCompone sobre el lienzo natural configurado, aplica la política de desbordamiento y de alineación y devuelve datos de origen, de ranura y de transformación final

Desbordamiento y colocación

dopRejectRechaza el contenido más ancho o más alto que la ranura sin cambiar el contenido del destino ni el estado confirmado del componente
dopClipMantiene la escala 1 e intersecta la ruta de recortado de la página con la ranura de destino antes de invocar el Form XObject
dopScaleDownUsa la menor razón de anchura o altura solo cuando es necesario y nunca amplía el contenido

La alineación se resuelve a partir del rectángulo usado transformado, de modo que el contenido centrado o final recortado selecciona la porción visible correspondiente

Transform[M11 M12 M21 M22 MDX MDY]

SlotLeft informa de la matriz de disposición lógica SlotTop desde las coordenadas locales del componente hasta las coordenadas finales del documento de arriba hacia abajo SlotWidth, SlotHeight,

Directivas de paginación

dppAllowSplitPreserva el comportamiento predeterminado y confirma cualquier fragmento válido cuya devolución de llamada informe de más contenido
dppKeepTogetherDevuelve PDF_DYNAMIC_COMPONENT_RETRY para el primer intento parcial o no visible y después permite la división o el recurso de recortado seleccionado en el siguiente intento válido para el mismo fragmento sin confirmar
dppRequireCompleteDevuelve PDF_DYNAMIC_COMPONENT_RETRY hasta que la devolución de llamada informe de que no queda contenido y el rectángulo usado completo quepa en la ranura o permanezca visible mediante la reducción proporcional

Placement

KeepTogetherRetryPending vacío Reset identifica el estado de recurso de un solo uso y se borra después de una confirmación con éxito, AttachComponent o

Restricciones del espacio de flujo

MinimumSlotHeightDevuelve PDF_DYNAMIC_COMPONENT_RETRY antes de clonar o invocar al componente cuando la ranura de destino es más corta que la altura configurada
MinimumFollowingHeightSe aplica solo a un fragmento de contenido final y exige que su altura resuelta más la altura de reserva siguiente quepan en la ranura

Un reintento por altura siguiente descarta el intento aislado preservando los fragmentos confirmados anteriores, lo que permite que un encabezado, una etiqueta o una breve introducción se muevan con la primera región utilizable del siguiente componente

LastRetryReason distingue los reintentos de componente completo, de finalización estricta, de ranura mínima y de espacio siguiente, mientras LastRequiredSlotHeight informa de la altura requerida conocida para las restricciones de espacio de flujo

La comprobación de ranura mínima corre antes de clonar el componente y capturar el Form, así que las regiones cortas rechazadas repetidamente no incurren en coste de retrollamada del componente ni de página temporal

Valores devueltos

PDF_DYNAMIC_COMPONENT_ERRORLa solicitud, la devolución de llamada del componente, la geometría del resultado o la colocación del Form fallaron y no se confirmó ningún estado
PDF_DYNAMIC_COMPONENT_MOREEl contenido se confirmó y el componente solicitó otra ranura de página
PDF_DYNAMIC_COMPONENT_COMPLETEEl componente terminó, o la sesión ya estaba completa y no se realizó ninguna devolución de llamada
PDF_DYNAMIC_COMPONENT_RETRYLa política de paginación o de espacio de flujo seleccionada aplazó la colocación sin confirmar contenido ni estado

Ejemplo

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;

Véase también

BeginFormXObject, ReleaseCapturedPage, ApplyRepeatedPageFragment