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 rifiutare 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 nueva 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 callback 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 inicial y actual independientes
AttachComponentReemplaza atómicamente ambas instantáneas con clones de un componente propiedad del llamador y limpia el estado de finalización
ResetRestaura un nuevo clon actual desde la instantánea inicial y restablece el recuento de composiciones exitosas
CloneCurrentComponentDevuelve un clon propiedad del llamador para inspeccionar el estado actual del componente confirmado
CreateLayoutOptionsConstruye configuraciones tipadas 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 manejador de captura y confirma el estado de trabajo
ComposeNextLayoutCompone sobre el lienzo natural configurado, aplica la política de desbordamiento y alineación y devuelve datos de fuente, ranura y transformación final

Desbordamiento y colocación

dopRejectRechaza el contenido más ancho o más alto que la ranura sin cambiar el contenido de destino ni el estado confirmado del componente
dopClipMantiene la escala 1 e intersecta la ruta de recorte de la página con la ranura de destino antes de invocar el Form XObject
dopScaleDownUsa la relación menor de ancho o alto 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 recortado al final selecciona la porción visible correspondiente

Transform[M11 M12 M21 M22 MDX MDY]

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

Políticas de paginación

dppAllowSplitPreserva el comportamiento predeterminado y confirma cualquier fragmento válido cuyo callback informe más contenido
dppKeepTogetherDevuelve PDF_DYNAMIC_COMPONENT_RETRY para el primer intento parcial o no visible, luego permite la división o el recorte de respaldo seleccionado en el siguiente intento válido para el mismo fragmento sin confirmar
dppRequireCompleteDevuelve PDF_DYNAMIC_COMPONENT_RETRY hasta que el callback informe 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 respaldo de una sola vez y se limpia después de una confirmación exitosa, AttachComponent o

Restricciones de espacio de flujo

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

Un reintento por altura siguiente descarta el intento aislado mientras preserva los fragmentos confirmados anteriores, permitiendo que un encabezado, una etiqueta o una entrada corta se muevan con la primera región utilizable del siguiente componente

LastRetryReason distingue i reintentos de componente completo, de finalización estricta, de ranura mínima y de espacio siguiente, mientras LastRequiredSlotHeight informa 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 callback del componente ni de página temporal

Valores devueltos

PDF_DYNAMIC_COMPONENT_ERRORLa solicitud, el callback 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 completó, o la sesión ya estaba completa y no se hizo ningún callback
PDF_DYNAMIC_COMPONENT_RETRYLa política seleccionada de paginación o de espacio de flujo difirió 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