PDFium Delphi Component Docs

Esempi di programmazione PDFium VCL

Scegliere una demo eseguibile

La raccolta comprende 32 argomenti: 32 progetti Delphi, 31 C++Builder e 32 Lazarus, per un totale di 95 progetti nativi. Ogni piattaforma mantiene 22 demo di workflow completi nella directory principale. Dieci argomenti mirati si trovano sotto Miscellaneous, con 29 progetti nativi nelle tre piattaforme; XfaLab è disponibile per Delphi e Lazarus

Si apre prima un workflow della directory principale: PDFViewer per il feature tour, CreatePDF per la creazione live, ContentExtractionLab per un inventario immediato, FormFill per i moduli modificabili, StandardsLab per validazione e conversione, oppure IntakeWorkbenchCli per l'acquisizione automatizzata. Questi sei entry point producono risultati funzionanti all'istante; gli esempi mirati qui sotto servono quando bisogna esaminare una singola API nel dettaglio

Demo dei workflow principali

DemoA cosa serveIn cosa differisce dai demo correlati
PDFViewerVisualizzazione generale e valutazione delle funzionalitàIl visualizzatore principale combina navigazione, ricerca, miniature, modalità di visualizzazione, stampa e una panoramica delle funzionalità
MultiPageViewerPagine continue, doppie pagine e layout con copertinaUn esempio mirato sui layout che usa le API di selezione integrate nel visualizzatore; per l'esperienza di visualizzatore più ampia si usa PDFViewer
SplitViewConfrontare pagine o documenti in riquadri separatiDimostra posizioni delle view indipendenti e l'instradamento dei comandi al riquadro attivo, invece del layout a due pagine in un'unica view
SearchAndSelectRisultati di ricerca tra le pagine e selezioneUn elenco di risultati e le opzioni di ricerca espongono il workflow di ricerca in modo più diretto di una barra degli strumenti del visualizzatore
PrintPDFAnteprima e lavori di stampa ordinariIntervalli di pagine, ridimensionamento, progresso e annullamento costituiscono il workflow di stampa principale
ContentExtractionLabIspezionare insieme più categorie di contenutoGli inventari TXT/JSON descrivono gli oggetti e mostrano testi in anteprima; non sostituiscono l'esportazione completa del testo o dei file immagine
ExtractImagesEsportare oggetti immagine incorporatiEstrae bitmap delle immagini invece di screenshot di pagine intere; il campione integrato contiene due oggetti immagine reali su ciascuna delle due pagine
TableExtractionLabRilevare tabelle ed esportare CSV/JSONTabelle con righe di bordo e tabelle allineate con spazi bianchi, celle unite, gruppi di continuazione e controlli di confidenza sono indipendenti dall'estrazione di testo semplice
AttachmentLeggere, aggiungere ed esportare allegati incorporatiLe operazioni sui payload degli allegati vanno oltre l'elenco di nomi e dimensioni di ContentExtractionLab
BatchExportEsportare immagini di pagina da più documentiOutput in streaming, stato per file e guasti isolati dimostrano l'elaborazione batch invece di una singola conversione
CreatePDFCreare contenuto di pagina con un'anteprima liveTutte e tre le varianti native creano testo ricercabile, forme vettoriali, un'immagine raster reale, tabelle e un'annotazione di revisione; le opzioni ricostruiscono l'anteprima prima di un salvataggio esplicito
ImageToPDFCostruire pagine da file immagine in inputLayout delle immagini, adattamento, ordinamento e gestione JPEG costituiscono un workflow di conversione di documenti
MergePDFAssemblare pagine da più PDFEsaminare gli input per controllare conteggi delle pagine e intervalli di output, riordinare le sorgenti e avviare l'unione solo dopo la validazione di tutti gli input
SplitPDFScrivere gruppi di pagine selezionati in PDF separatiDenominazione degli output e validazione dei gruppi di pagine si distinguono dall'unione e dal rendering in immagini di pagina
WatermarkStampApplicare overlay ripetuti a pagine esistentiScegliere un PDF di destinazione, un PDF timbro riutilizzabile e un intervallo di pagine; i timbri si adattano a ogni pagina e quelle non selezionate restano invariate
FormFillInserimento interattivo in AcroForm e appiattimentoL'input nei campi e le appearance salvate si distinguono dall'interscambio XFDF e dal comportamento specifico di XFA
AccessibilityReaderLettura interattiva e sintesi vocaleIl lettore GUI dimostra navigazione in lettura ed evidenziazione, non un audit di conformità
AccessibilityWorkbenchCliRevisione di accessibilità batch e generazione di reportRiscontri, riepiloghi e gate di revisione servono l'automazione; i riscontri non sostituiscono la revisione manuale di accessibilità
StandardsLabValidazione e conversione specifiche per gli standardIl laboratorio interattivo espone operazioni e opzioni invece di generare soltanto un report aggregato
PreflightReportReport sugli standard interattiviLa GUI supporta l'ispezione manuale e l'esportazione dei report
PreflightReportCliReport sugli standard automatizzatiInput in batch, formati di report e gate sul codice di uscita costituiscono la controparte automatizzata di PreflightReport
IntakeWorkbenchCliAcquisizione batch, triage e instradamentoReport aggregati, gate sui guasti e decisioni di instradamento ne fanno un workflow di elaborazione che va oltre la GUI di SecurityAudit

Esempi mirati in Miscellaneous

Aprire questi progetti da Demo\Delphi\Miscellaneous, Demo\CBuilder\Miscellaneous o Demo\Lazarus\Miscellaneous. Mantengono ricette API e attività di esportazione mirate, mentre la directory principale si concentra su esperienze complete. Verifiche Unicode di base e la guida fissa per creare ed elencare annotazioni sono coperte da creazione, estrazione, scambio XFDF e test API; non hanno più progetti demo separati

DemoA cosa serveIn cosa differisce dai demo correlati
SecurityAuditEsaminare interattivamente la sicurezza del documentoLa GUI si concentra su permessi, script, firme e dettagli di sicurezza, anziché sull'instradamento dei file
XfdfLabImportare ed esportare dati XFDFLo scambio e il salvataggio esplicito del PDF importato mostrano la persistenza; esportare solo XFDF non salva il PDF modificato
AccessibilityLabPercorrere le API di lettura in una consoleUn percorso eseguibile compatto espone unità di lettura, box delle parole, struttura e output degli script di sintesi vocale
ExtractTextEsportare il testo completo dalle pagine selezionateOutput dal livello di testo, separatori di pagina e annullamento si distinguono dalle anteprime di inventario e dal rilevamento delle tabelle; non viene eseguito alcun OCR
FontPropertiesIspezionare le metriche di font e caratteriParte con le metriche reali di font e caratteri del primo oggetto di testo; si seleziona un'altra riga per confrontare i font senza esportare i payload del documento
NavigationLabSegnalibri, destinazioni e azioni di navigazioneLa panoramica compatta delle API completa i controlli di navigazione visibili in PDFViewer
PDFtoJpgRenderizzare un documento in immagini di paginaUn esempio compatto di rendering su un singolo documento; Delphi espone intervalli di pagine discreti, mentre BatchExport si concentra su più documenti in input
PrintPreferencesFogli N-up e preferenze di stampa dell'autore del PDFCopie, filtro pari/dispari e preferenze fornite dall'autore sono il focus didattico; è un complemento a PrintPDF
ViewerInteractionLabDiagnosticare le interazioni di mouse, tastiera e coordinateIl log delle interazioni e la conversione tra coordinate pagina e dispositivo ne fanno uno strumento di diagnostica delle API
XfaLabPacchetti XFA statici e capacità del runtimeApre i pacchetti template e datasets con il runtime ordinario; il rendering XFA interattivo richiede un runtime con supporto XFA, con varianti Delphi e Lazarus

Iniziare con una demo funzionante delle funzionalità

PDFViewer apre il proprio PDFiumDemoShowcase.pdf in bundle, un documento di sei pagine con testo ricercabile, grafici vettoriali, due immagini incorporate, una tabella, quattro campi AcroForm, segnalibri dei capitoli, link, una nota di revisione e due allegati. La barra delle esperienze offre Restart showcase, Find live text, 2-page spread, Night reading, Inspect this PDF ed Explore forms; ogni azione agisce sul documento corrente

CreatePDF apre un'anteprima live del report su due pagine. Se ne modificano titolo e autore, oppure si attivano e disattivano forme, tabella e filigrana per ricostruire il contenuto reale delle pagine; l'opzione Unicode aggiunge una terza pagina. Non si scrive nulla finché non si salva, e il PDF salvato resta ricercabile

MultiPageViewer, SearchAndSelect, ContentExtractionLab e FormFill aprono lo stesso documento per i rispettivi workflow, con risultati di ricerca, inventario di estrazione e campi modificabili pronti all'istante. Miscellaneous\NavigationLab usa la propria copia locale per un percorso tra le API di segnalibri e destinazioni

Attachment parte con due file incorporati reali. PrintPreferences parte con quattro pagine e le preferenze dell'autore per due copie, intervalli di pagine selezionati, ridimensionamento e duplex; il workflow di stampa attuale applica copie e intervalli di pagine, mentre ridimensionamento e duplex vengono ispezionati e riportati. XfaLab parte con pacchetti template e datasets effettivi per l'ispezione dello XFA statico; il rendering XFA interattivo richiede un runtime appropriato e resta una funzionalità separata

Ogni progetto di visualizzazione, moduli, estrazione e navigazione contiene il proprio PDFiumDemoShowcase.pdf. Si copia la directory del progetto e si conserva questo input in bundle accanto all'eseguibile distribuito; le build Lazarus lo predispongono automaticamente. Il tour funziona offline, e anche i visualizzatori generici e gli esempi di estrazione offrono contenuti di fallback generati quando il PDF locale non è disponibile

Copiare e mantenere gli esempi nativi

Ogni demo nativo contiene la propria implementazione di esempio. Gli entry point Delphi e Lazarus di AccessibilityLab, AccessibilityWorkbenchCli, IntakeWorkbenchCli e PreflightReportCli includono il workflow completo nella directory del progetto, comprese l'inizializzazione specifica del compilatore e la scrittura JPEG. Anche gli esempi di allegati, preferenze di stampa e XFA costruiscono localmente i propri input specifici di ciascuna funzione. Fuori dal progetto copiato servono solo la libreria, il runtime nativo corrispondente e le normali dipendenze del framework del compilatore

L'estrazione di oggetti immagine è la scelta giusta quando servono bitmap incorporate, il rendering di pagina quando serve la pagina visibile, l'estrazione del testo quando il PDF ha già un livello di testo. Un report che elenca queste categorie non esporta i payload completi. Questi confini mantengono utili gli esempi mirati senza dilatare ogni demo in un altro visualizzatore o workbench per usi generali

Operazioni di base sui documenti

Caricamento e visualizzazione di un documento PDF

Pdf1.FileName := 'C:\MyDocument.pdf';
Pdf1.Active := True;
ShowMessage('Pages: ' + IntToStr(Pdf1.PageCount));
ShowMessage('Title: ' + Pdf1.Title);
ShowMessage('Author: ' + Pdf1.Author);

var
  Stream: TMemoryStream;
begin
  Stream := TMemoryStream.Create;
  try
    Stream.LoadFromFile('C:\MyDocument.pdf');
    Pdf1.LoadDocument(Stream, True);
    Pdf1.Active := True;
    ShowMessage('PDF loaded from stream');
  finally
    Stream.Free;
  end;
end;

Creazione di un nuovo documento PDF

Pdf1.CreateDocument;
Pdf1.Active := True;
Pdf1.AddPage(0, 612, 792);
Pdf1.PageNumber := 1;
Pdf1.AddText('Hello World!', 'Arial', 12, 100, 700, clBlack, $FF, 0.0);
Pdf1.UpdatePage;
Pdf1.SaveAs('C:\NewDocument.pdf');
Pdf1.Active := False;

Operazioni sul testo

Estrazione del testo da un PDF

var
  PageText: WString;
  RectText: WString;
begin
  Pdf1.PageNumber := 1;
  PageText := Pdf1.Text;
  Memo1.Text := PageText;
  RectText := Pdf1.TextInRectangle(100, 100, 500, 200);
  ShowMessage('Text in rectangle: ' + RectText);
end;

Ricerca di testo

var
  Position: Integer;
begin
  Position := Pdf1.FindFirst('Hello', [seCaseSensitive]);
  while Position >= 0 do
  begin
    ShowMessage('Found at character: ' + IntToStr(Position));
    Position := Pdf1.FindNext;
  end;
end;

Aggiunta di testo con formattazione

Pdf1.PageNumber := 1;
Pdf1.AddText('Document Title', 'Times New Roman', 16, 100, 750, clBlue);
Pdf1.AddText('This is the document content.', 'Arial', 12, 100, 700, clBlack);
Pdf1.UpdatePage;

Ispezione dei metadati di caratteri e font

var
  I: Integer;
  MetricSize: Single;
  FontBytes: TBytes;
begin
  Pdf1.PageNumber := 1;
  for I := 0 to Pdf1.ObjectCount - 1 do
    if Pdf1.ObjectType[I] = otText then
    begin
      MetricSize := 12.0;
      FontBytes := Pdf1.FontData[I];
      Memo1.Lines.Add('Object ' + IntToStr(I));
      Memo1.Lines.Add('Base name: ' + Pdf1.FontBaseName[I]);
      Memo1.Lines.Add('Family: ' + Pdf1.FontFamilyName[I]);
      Memo1.Lines.Add('Embedded: ' + BoolToStr(Pdf1.FontIsEmbedded[I], True));
      Memo1.Lines.Add('Weight: ' + IntToStr(Pdf1.FontWeight[I]));
      Memo1.Lines.Add('Italic angle: ' + IntToStr(Pdf1.FontItalicAngle[I]));
      Memo1.Lines.Add('Ascent: ' + FloatToStr(Pdf1.FontAscent[I, MetricSize]));
      Memo1.Lines.Add('Descent: ' + FloatToStr(Pdf1.FontDescent[I, MetricSize]));
      Memo1.Lines.Add('Font data bytes: ' + IntToStr(Length(FontBytes)));
    end;

  if Pdf1.CharacterCount > 0 then
  begin
    Memo1.Lines.Add('First character size: ' + FloatToStr(Pdf1.CharacterFontSize[0]));
    Memo1.Lines.Add('First character weight: ' + IntToStr(Pdf1.CharacterFontWeight[0]));
    Memo1.Lines.Add('First character angle: ' + FloatToStr(Pdf1.CharacterAngle[0]));
  end;
end;

I progetti Demo\Delphi\Miscellaneous\FontProperties, Demo\CBuilder\Miscellaneous\FontProperties e Demo\Lazarus\Miscellaneous\FontProperties mostrano gli stessi metadati sia tramite TPdf sia tramite TPdfView

Costruzione di un report di estrazione contenuti multi-categoria

I progetti Demo\Delphi\ContentExtractionLab, Demo\CBuilder\ContentExtractionLab e Demo\Lazarus\ContentExtractionLab trasformano l'estrazione di contenuti in un unico workflow. Aprono o creano un PDF, permettono di scegliere metadati, testo di pagina, oggetti di pagina, immagini, allegati, link, annotazioni, segnalibri e metriche di font / caratteri, quindi generano un riepilogo più un report TXT o JSON dettagliato. Il laboratorio include anche la selezione di categorie tutto / niente, la copia del report negli appunti e le azioni di salvataggio del PDF sorgente affinché gli utenti possano conservare il PDF di esempio generato accanto al suo report di estrazione. ExtractImages e Attachment offrono workflow di esportazione dei payload, mentre Miscellaneous\ExtractText e Miscellaneous\FontProperties conservano esempi mirati sulle API; ExtractText supporta le opzioni di intervallo di pagine e di separatore di pagine per produrre output di testo per pagina in Delphi, C++Builder e Lazarus, mentre ContentExtractionLab è l'esempio trasversale di inventario

Rilevare ed estrarre tabelle

I progetti Demo\Delphi\TableExtractionLab, Demo\CBuilder\TableExtractionLab e Demo\Lazarus\TableExtractionLab trasformano il rilevamento delle tabelle in un unico flusso di lavoro. Il laboratorio costruisce un documento di esempio contenente una tabella con righe di bordo e celle di intestazione unite, una tabella allineata con spazi bianchi senza bordi e una tabella lunga che si interrompe oltre il confine di pagina, poi esegue ExtractTables per la pagina corrente oppure ExtractDocumentTables per l'intero documento e riporta righe, colonne, valori RowSpan e ColumnSpan, flag di intestazione, modalità di rilevamento, confidenza e gruppi di continuazione. Le opzioni DetectRuledTables, DetectWhitespaceTables, DetectContinuations, DetectFilledRulings e MinConfidence sono modificabili nell'interfaccia utente, e la tabella selezionata viene esportata tramite TPdfTable.ToCsv e TPdfTable.ToJson. Il laboratorio elabora anche un'intera cartella in batch: Batch folder esegue ExtractDocumentTables su ogni PDF, riporta i conteggi delle tabelle per documento, segnala le scansioni prive di livello di testo e riprova i documenti vuoti con un preset di colonne compatte; Export all CSV scrive ogni tabella rilevata accanto ai file di origine. Ogni documento si apre nella propria istanza TPdf, così un file illeggibile non può influire sul resto del batch

Operazioni sui moduli

Lavorare con i campi dei moduli

var
  I: Integer;
  FieldInfo: TPdfFormFieldInfo;
begin
  Pdf1.FormField[0] := 'John';
  for I := 0 to Pdf1.FormFieldCount - 1 do
  begin
    FieldInfo := Pdf1.FormFieldInfo[I];
    ShowMessage(FieldInfo.Name + ': ' + Pdf1.FormField[I]);
  end;
end;

Appiattimento dei valori dei moduli compilati nella pagina

// Without flattening, FormField[i] := value writes only the /V entry —
// the visible appearance comes from the /AP stream and may not refresh
// GenerateFormAppearances regenerates /AP for every widget, then
// FlattenAllPages bakes every page's annotations and widgets into
// permanent, non-editable content
Pdf1.FileName := 'C:\Application.pdf';
Pdf1.Active := True;
Pdf1.FormField[0] := 'John Smith';
Pdf1.FormField[1] := '[email protected]';
Pdf1.GenerateFormAppearances;
if Pdf1.FlattenAllPages then
  Pdf1.SaveAs('C:\Application.flat.pdf');
Pdf1.Active := False;

Operazioni sulle immagini

Estrazione di immagini

var
  I: Integer;
  Bitmap: TBitmap;
begin
  for I := 0 to Pdf1.BitmapCount - 1 do
  begin
    Bitmap := Pdf1.Bitmap[I];
    try
      Bitmap.SaveToFile('C:\ExtractedImage' + IntToStr(I) + '.bmp');
    finally
      Bitmap.Free;
    end;
  end;
end;

Aggiunta di immagini

var
  JpegStream: TFileStream;
begin
  JpegStream := TFileStream.Create('C:\MyImage.jpg', fmOpenRead or fmShareDenyWrite);
  try
    Pdf1.AddJpegImage(JpegStream, 100, 500, 200, 150);
  finally
    JpegStream.Free;
  end;
  Pdf1.AddPicture(Image1.Picture, 100, 300, 150, 100);
  Pdf1.UpdatePage;
end;

Operazioni sulle annotazioni

Lavorare con le annotazioni

var
  I: Integer;
  Annotation: TPdfAnnotation;
begin
  for I := 0 to Pdf1.AnnotationCount - 1 do
  begin
    Annotation := Pdf1.Annotation[I];
    ShowMessage('Annotation ' + IntToStr(I) + ': ' + Annotation.ContentsText);
  end;
end;

Operazioni di disegno

Disegno di forme

Pdf1.CreatePath(100, 100, 200, 150, fmAlternate, clYellow, $FF, True, clBlack, $FF, 2.0);
Pdf1.AddPath;

Pdf1.CreatePath(100, 100, fmNone, clBlack, $FF, True, clRed, $FF, 3.0);
Pdf1.LineTo(200, 100);
Pdf1.LineTo(150, 200);
Pdf1.ClosePath;
Pdf1.AddPath;
Pdf1.UpdatePage;

Navigazione e segnalibri

Lavorare con i segnalibri

var
  I: Integer;
  Bookmarks: TBookmarks;
begin
  Bookmarks := Pdf1.Bookmarks;
  for I := 0 to Length(Bookmarks) - 1 do
    ShowMessage(Bookmarks[I].Title + ' -> Page ' + IntToStr(Bookmarks[I].PageNumber));
end;

Lavorare con le destinazioni con nome

var
  I: Integer;
  Destination: TDestination;
begin
  for I := 0 to Pdf1.DestinationCount - 1 do
  begin
    Destination := Pdf1.Destination[I];
    if Destination.Name = 'Chapter1' then
    begin
      Pdf1.PageNumber := Destination.PageNumber;
      Break;
    end;
  end;
end;

Operazioni sugli allegati

Lavorare con gli allegati

var
  I: Integer;
  AttachmentData: TBytes;
  AttachmentName: WString;
  FileStream: TFileStream;
begin
  for I := 0 to Pdf1.AttachmentCount - 1 do
  begin
    AttachmentName := Pdf1.AttachmentName[I];
    AttachmentData := Pdf1.Attachment[I];
    FileStream := TFileStream.Create('C:\Extracted_' + string(AttachmentName), fmCreate);
    try
      if Length(AttachmentData) > 0 then
        FileStream.WriteBuffer(AttachmentData[0], Length(AttachmentData));
    finally
      FileStream.Free;
    end;
  end;
  if Pdf1.CreateAttachment('MyFile.txt') then
    Pdf1.Attachment[Pdf1.AttachmentCount - 1] := TFile.ReadAllBytes('C:\MyFile.txt');
end;

Gestione delle pagine

Operazioni sulle pagine

Pdf1.AddPage(Pdf1.PageCount + 1, 612, 792);
Pdf1.AddPage(Pdf1.PageCount + 1, 595, 842);
Pdf1.AddPage(Pdf1.PageCount + 1, 400, 600);

var
  SourcePdf: TPdf;
begin
  SourcePdf := TPdf.Create(nil);
  try
    SourcePdf.FileName := 'C:\SourceDocument.pdf';
    SourcePdf.Active := True;
    Pdf1.ImportPages(SourcePdf, '1', Pdf1.PageCount + 1);
  finally
    SourcePdf.Free;
  end;
end;

if Pdf1.PageCount > 1 then
  Pdf1.DeletePage(Pdf1.PageCount);

Salvataggio e compressione

Salvataggio con compressione

// Create a compressed PDF document
Pdf1.CreateDocument;
Pdf1.Compressed := True; // ensure all streams are FlateDecode compressed (default)
Pdf1.Active := True;
Pdf1.AddPage(0, 595, 842); // A4 size
Pdf1.AddText('Hello World!', 'Arial', 24, 100, 700, clBlack, $FF, 0.0);
Pdf1.SaveAs('C:\Compressed.pdf');
Pdf1.Active := False;

// Save with options
Pdf1.SaveAs('C:\Output.pdf', saIncremental); // incremental save
Pdf1.SaveAs('C:\NoSecurity.pdf', saRemoveSecurity); // remove security

// Save to a specific PDF version target. The PDF version validator rejects
// any feature introduced after the chosen target (JBIG2Decode, MarkInfo,
// AES encryption, Polygon / Caret / Watermark / Redact annotations, ...)
if not Pdf1.SaveAs('C:\Legacy15.pdf', saNone, pv15) then
  ShowMessage('Save rejected: document contains features newer than PDF 1.5');

Creazione di output di archiviazione PDF/A-1b

// SaveAsPdfA post-processes the base save with an incremental update that
// injects an XMP metadata stream, an sRGB ICC OutputIntent, and an updated
// document catalog so the result is PDF/A-1b conformant. The bundled
// sRGB IEC61966-2.1 profile is used automatically when no custom profile
// is supplied
Pdf1.FileName := 'C:\Report.pdf';
Pdf1.Active := True;
if Pdf1.SaveAsPdfA('C:\Report.pdfa.pdf', pac1b) then
  ShowMessage('Saved PDF/A-1b archive');

// PDF/A with a custom ICC profile (CMYK printing pipelines for example)
var
  Opts: TPdfASaveOptions;
begin
  Opts := Default(TPdfASaveOptions);
  Opts.Conformance    := pac1b;
  Opts.IccProfileData := TFile.ReadAllBytes('C:\Profiles\Coated_GRACoL_2006.icc');
  Pdf1.SaveAsPdfA('C:\Report.cmyk.pdfa.pdf', Opts);
end;

// In-memory PDF/A output
var
  Stream: TMemoryStream;
begin
  Stream := TMemoryStream.Create;
  try
    Opts := Default(TPdfASaveOptions);
    Opts.Conformance := pac1b;
    if Pdf1.SaveAsPdfAToStream(Stream, Opts) then
      UploadToArchive(Stream);
  finally
    Stream.Free;
  end;
end;

Validazione della conformità PDF/A

var
  Validation: TPdfAValidationResult;
  Issue: TPdfAValidationIssue;
begin
  Pdf1.FileName := 'C:\Incoming\report.pdf';
  Pdf1.Active   := True;

  // Cheap header-style probe — reads the conformance without iterating
  // the full validator. Result: pacNone, pac1a, pac1b, pac2b, pac3b, or
  // pacUnknown
  case Pdf1.PdfAConformance of
    pac1b: Status.Caption := 'PDF/A-1b';
    pac2b: Status.Caption := 'PDF/A-2b';
    pacNone: Status.Caption := 'Not PDF/A';
  else
    Status.Caption := 'Unknown conformance';
  end;

  // Full validator with per-issue diagnostics
  Validation := Pdf1.ValidatePdfA;
  Memo1.Lines.Add('Conformance: ' + GetEnumName(TypeInfo(TPdfAConformance),
    Ord(Validation.Conformance)));
  for Issue in Validation.Issues do
    Memo1.Lines.Add('- ' + Issue.Description);
end;

Ispezione di più standard PDF in StandardsLab

I progetti Demo\Delphi\StandardsLab, Demo\CBuilder\StandardsLab e Demo\Lazarus\StandardsLab caricano o creano un PDF, eseguono ValidatePdfA, ValidatePdfUa, ValidatePdfE, ValidatePdfX, ValidatePdfR e ValidatePdfVT, quindi mostrano in un'unica griglia ciascun livello di conformità rilevato e il conteggio dei problemi. I loro pulsanti di salvataggio chiamano SaveAsPdfA, SaveAsPdfUa, SaveAsPdfE, SaveAsPdfX, SaveAsPdfR e SaveAsPdfVT in modo che il workflow di output con marcatori sia visibile senza scrivere un harness personalizzato

Generazione di report di preflight

L'unità FPdfPreflightReport avvolge ValidatePdfA, ValidatePdfUa, ValidatePdfE, ValidatePdfX, ValidatePdfR e ValidatePdfVT in un unico oggetto report interrogabile con gravità Info / Warning / Error, aggregazione di stati e problemi, lookup, ricerca, filtraggio e impronte SHA-256 stabili. I report possono essere emessi come testo, HTML, Markdown, JSON, CSV, SARIF 2.1.0, JUnit XML, NDJSON o XML nativo. Demo\Delphi\PreflightReport, Demo\Lazarus\PreflightReport e Demo\CBuilder\PreflightReport forniscono workflow interattivi di selezione e anteprima, mentre Demo\Delphi\PreflightReportCli aggiunge argomenti di input / output scriptabili, filtro per standard, incorporamento opzionale dell'allegato del report, gating del codice di uscita per la CI, elaborazione di elenchi batch e di directory, routing a prova di collisione, riepiloghi aggregati e manifest CSV. Il report generato dichiara che i validatori incorporati coprono i controlli a livello di marcatore e una selezione di controlli a livello di file, quindi il preflight completo a livello di contenuto può comunque essere delegato a un motore di validazione dedicato

Caricamento in streaming e documenti di grandi dimensioni

Caricamento di un PDF su richiesta con LoadCustomDocument

// LoadCustomDocument lets PDFium pull blocks from any seekable TStream on
// demand. The stream is NOT copied into memory, so multi-GB PDFs, remote
// HTTP body streams, and database-backed sources are all viable without
// an up-front buffer
var
  FileStream: TFileStream;
begin
  // Read-from-file streaming (no in-memory copy)
  FileStream := TFileStream.Create('C:\Huge.pdf',
    fmOpenRead or fmShareDenyWrite);
  Pdf1.LoadCustomDocument(FileStream, True{AOwnsStream});
  // ^^ ownership transferred — Pdf1 frees FileStream on UnloadDocument
  Pdf1.Active := True;
  ShowMessage('Pages: ' + IntToStr(Pdf1.PageCount));
end;

// Externally-owned stream (caller frees it after UnloadDocument)
var
  Stream: TFileStream;
begin
  Stream := TFileStream.Create('C:\Live.pdf',
    fmOpenRead or fmShareDenyNone);
  try
    Pdf1.LoadCustomDocument(Stream, False);
    Pdf1.Active := True;
    DoWork;
    Pdf1.Active := False;
  finally
    Stream.Free;
  end;
end;

Annullamento asincrono e rendering progressivo

Token di annullamento cooperativi

// FPdfAsync exposes IPdfCancellationToken /
// IPdfCancellationTokenSource for cancel-from-UI semantics that work
// across the long-running export and render paths
uses FPdfAsync;

var
  CancelSource: IPdfCancellationTokenSource;
  CancelToken:  IPdfCancellationToken;
begin
  CancelSource := PdfCancellationTokenSource;
  CancelToken  := CancelSource.Token;

  // user clicks Cancel
  CancelSource.Cancel;

  // The worker periodically checks CancelToken.IsCancelled, or the render
  // path polls it through PDFium's IFSDK_PAUSE callback
  if CancelToken.IsCancelled then
    Memo1.Lines.Add('Cancelled by user');
end;

Rendering progressivo di pagina annullabile

// RenderPageProgressive lets a long high-DPI render abort mid-page when
// the user clicks Cancel, instead of blocking the caller until done
var
  Status: TPdfProgressiveStatus;
  Bitmap: TBitmap;
begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.PixelFormat := pf32bit;
    Bitmap.SetSize(2480, 3508); // A4 @ 300 DPI

    Status := Pdf1.RenderPageProgressive(Bitmap, 0, 0, Bitmap.Width,
      Bitmap.Height, CancelToken, ro0, [reAnnotations], clWhite);

    case Status of
      prsDone:      SaveBitmap(Bitmap);
      prsCancelled: Memo1.Lines.Add('Render cancelled — partial result available');
      prsFailed:    Memo1.Lines.Add('PDFium reported FPDF_RENDER_FAILED');
    end;
  finally
    Bitmap.Free;
  end;
end;

Esecuzione del rendering su un thread in background con TPdfFuture

// TPdfFuture<T> spins up a worker on a background thread and posts a
// TPdfFutureResult<T> envelope back to the main thread
//
// Important: TPdf serializes render calls per instance, but the worker still
// owns dispatch and document lifetime. Do not mutate a TPdf while a render is
// in flight; batch export usually keeps one TPdf per file
type
  TRenderResult = record
    Bitmap : TBitmap;
    PageNo : Integer;
  end;

var
  Future: TPdfFuture<TRenderResult>;
begin
  Future := TPdfFuture<TRenderResult>.Create(
    function (const ACancelToken: IPdfCancellationToken): TRenderResult
    var
      LocalPdf: TPdf;
    begin
      LocalPdf := TPdf.Create(nil);
      try
        LocalPdf.FileName := 'C:\Huge.pdf';
        LocalPdf.Active   := True;
        LocalPdf.PageNumber := 1;
        Result.Bitmap := LocalPdf.RenderPage(0, 0, 2480, 3508);
        Result.PageNo := 1;
      finally
        LocalPdf.Free;
      end;
    end,
    procedure (const AResult: TPdfFutureResult<TRenderResult>)
    begin
      case AResult.State of
        pfsSuccess:   PaintBitmapToView(AResult.Value.Bitmap);
        pfsCancelled: Log.Add('Cancelled');
        pfsFailed:    Log.Add('Worker failed: ' + AResult.ErrorMessage);
      end;
    end);
end;

Matrici di trasformazione

Composizione di Translate / Scale / Rotate / Skew

// FPdfMatrix wraps PDFium's FS_MATRIX so callers can build a transform
// declaratively and hand it to FPDFPageObj_SetMatrix
uses FPdfMatrix, FPdfView;

var
  M: TPdfMatrix;
  RawMatrix: FS_MATRIX;
  PageObj: FPDF_PAGEOBJECT;
begin
  M := TPdfMatrix.Create;
  try
    M.Translate(72, 200);       // move 1in right, ~2.8in up
    M.Scale(0.5, 0.5);          // half-size stamp
    M.Rotate(15);               // 15-degree CCW rotation
    // M.HorizontalFlip;
    // M.VerticalFlip;
    // M.CentralFlip;
    // M.Skew(10, 5);
    // M.Multiply(Other);       // post-multiply with another matrix

    // Apply to any PDFium page object (text / path / image / form XObject)
    RawMatrix := M.Handle;
    FPDFPageObj_SetMatrix(PageObj, RawMatrix);
  finally
    M.Free;
  end;
end;

Composizione di pagine

Importazione di un sottoinsieme di pagine per indice

// ImportPagesByIndex copies an explicit zero-based index array from a
// source PDF into this document. InsertAt = 0 inserts before page 1;
// PageCount appends
var
  Source: TPdf;
begin
  Source := TPdf.Create(nil);
  try
    Source.FileName := 'C:\Report.pdf';
    Source.Active   := True;

    // Import pages 0, 2, 4 (one-based: pages 1, 3, 5) from Source
    // and append them at the end of Pdf1
    Pdf1.ImportPagesByIndex(Source, [0, 2, 4], Pdf1.PageCount);

    // Empty array imports every source page
    // Pdf1.ImportPagesByIndex(Source, [], 0);
  finally
    Source.Free;
  end;
end;

Output composito N-up

// ImportNPagesToOne returns a brand-new TPdf whose pages are NumX*NumY
// composites of THIS document. OutputWidth/Height are PDF user units
// (1 unit = 1/72 in)
var
  Composite: TPdf;
begin
  Pdf1.FileName := 'C:\Slides.pdf';
  Pdf1.Active   := True;
  // 4-up A4 landscape: 842 x 595 pt, 2 columns x 2 rows
  Composite := Pdf1.ImportNPagesToOne(842, 595, 2, 2);
  try
    if Composite <> nil then
      Composite.SaveAs('C:\Slides_4up.pdf');
  finally
    Composite.Free;
  end;
end;

Riordino delle pagine in posto

// MovePages takes the zero-based indices of the pages to move plus the
// destination index for the first moved page after the move completes
// Other pages shift around the moved block so the document length stays
// the same
//
// Example: in a 5-page document with pages numbered [0,1,2,3,4],
// MovePages([2, 3], 0) reorders to [2, 3, 0, 1, 4]
if not Pdf1.MovePages([2, 3], 0) then
  ShowMessage('Invalid indices passed to MovePages');

Filigranatura tramite riutilizzo di pagine con Form XObject

// CreateXObjectFromPage manufactures a reusable Form XObject handle from
// any page of any other TPdf. Stamp that handle onto as many pages of
// THIS document as you want — each stamp is a single PDFium page object
// that can be positioned, scaled, and rotated through the matrix API
uses FPdfMatrix, FPdfView;

var
  WatermarkSource: TPdf;
  XObj:            TPdfXObject;
  PageObj:         FPDF_PAGEOBJECT;
  M:               TPdfMatrix;
  RawMatrix:       FS_MATRIX;
  I:               Integer;
begin
  WatermarkSource := TPdf.Create(nil);
  try
    WatermarkSource.FileName := 'C:\Watermarks\Confidential.pdf';
    WatermarkSource.Active   := True;

    // Wrap page 0 of WatermarkSource as a reusable XObject
    XObj := Pdf1.CreateXObjectFromPage(WatermarkSource, 0);
    try
      for I := 1 to Pdf1.PageCount do
      begin
        Pdf1.PageNumber := I;
        PageObj := Pdf1.InsertFormObjectFromXObject(XObj);
        if PageObj = nil then Continue;

        // Centre the watermark on the page
        M := TPdfMatrix.Create;
        try
          M.Scale(0.5, 0.5);
          M.Translate(0.25 * Pdf1.PageWidth, 0.5 * Pdf1.PageHeight);
          RawMatrix := M.Handle;
          FPDFPageObj_SetMatrix(PageObj, RawMatrix);
        finally
          M.Free;
        end;

        Pdf1.UpdatePage;
      end;
    finally
      XObj.Free; // closes the FPDF_XOBJECT handle
    end;

    Pdf1.SaveAs('C:\Watermarked.pdf');
  finally
    WatermarkSource.Free;
  end;
end;

I progetti Demo\Delphi\WatermarkStamp, Demo\Lazarus\WatermarkStamp e Demo\CBuilder\WatermarkStamp trasformano questo pattern in un workflow eseguibile: creano un PDF di destinazione e un PDF timbro riutilizzabile, incapsulano la pagina del timbro con CreateXObjectFromPage, inseriscono lo stesso Form XObject su ogni pagina di destinazione, applicano trasformazioni TPdfMatrix per filigrane centrate e timbri in alto a destra, e aggiungono etichette di numero di pagina opzionali prima di salvare il risultato

Inserimento immagini (overload diretti di AddImage)

Aggiunta di un file immagine registrato o di un TBitmap

// AddImage(FileName) accepts any format registered with the VCL or LCL
// graphics units (BMP, PNG via PngImage, JPG, ...)
Pdf1.AddImage('C:\Photo.png', 100, 500, 200, 150);

// AddImage(TBitmap) skips the TPicture intermediary, ideal when the
// bitmap already comes from rendering or batch generation work
var
  Bitmap: TBitmap;
begin
  Bitmap := Pdf1.RenderPage(0, 0, 595, 842);
  try
    Pdf1.PageNumber := 2;
    Pdf1.AddImage(Bitmap, 50, 50, 250, 350);
    Pdf1.UpdatePage;
  finally
    Bitmap.Free;
  end;
end;

I progetti Demo\Delphi\ImageToPDF, Demo\CBuilder\ImageToPDF e Demo\Lazarus\ImageToPDF trasformano tutto ciò in un workflow batch completo: selezione di più file immagine, anteprima dell'elemento selezionato, creazione di una pagina PDF per immagine, ridimensionamento di ciascuna immagine in una pagina A4 verticale o orizzontale, salvataggio del risultato e apertura del PDF generato

Evidenziazione della ricerca nel visualizzatore

Evidenziazione di ogni corrispondenza nella pagina corrente

var
  MatchCount: Integer;
begin
  // Paint a clYellow mask over every match on the view's current page
  // Switching to a different page clears the highlight automatically
  PdfView1.HighlightColor := clYellow;
  MatchCount := PdfView1.HighlightSearchText('invoice', False{Case}, True{Word});
  Status.Caption := Format('%d match(es) on this page', [MatchCount]);

  // Programmatically remove the overlay before the page changes
  PdfView1.ClearHighlight;
end;

Layout del visualizzatore e colore della pagina

Modalità di adattamento e sfondo della pagina

// FitMode keeps long documents framed during Resize or page changes
// Setting Zoom directly cancels FitMode (it reverts to pfmNone)
PdfView1.FitMode := pfmFitPage;       // whole page in viewport
// PdfView1.FitMode := pfmFitWidth;   // page width matches viewport width
// PdfView1.FitMode := pfmActualSize; // 100%

// PageColor decouples the rendered PDF page from the host control's Color
// — typical dark-mode viewer setup keeps the scroll area dark while the
// PDF page stays paper-white
PdfView1.Color     := clBlack;        // scroll area
PdfView1.PageColor := clWhite;        // PDF page background

// Optional drop shadow and page border to lift the page off a dark bg
PdfView1.PageShadowSize  := 6;
PdfView1.PageShadowColor := $00404040;
PdfView1.PageBorderColor := clGray;

Esplorazione dell'interazione del visualizzatore in ViewerInteractionLab

I progetti Demo\Delphi\Miscellaneous\ViewerInteractionLab, Demo\CBuilder\Miscellaneous\ViewerInteractionLab e Demo\Lazarus\Miscellaneous\ViewerInteractionLab mantengono la moderna superficie di interazione di TPdfView in un unico form compatto: aprire o creare un PDF di esempio, alternare DisplayMode, applicare FitMode, cambiare PageColor, ruotare le pagine, evidenziare le occorrenze di ricerca della pagina corrente con HighlightSearchText, abilitare o disabilitare la selezione del testo da parte dell'utente, ispezionare SelectedText, chiamare SelectAll, CopySelectionToClipboard e ClearSelection, e osservare l'aggiornamento delle coordinate DeviceToPage nella barra di stato mentre il mouse si muove sulla pagina

Ricerca e selezione del testo in SearchAndSelect

I progetti Demo\Delphi\SearchAndSelect, Demo\CBuilder\SearchAndSelect e Demo\Lazarus\SearchAndSelect trasformano il workflow di ricerca e selezione del visualizzatore in esempi autonomi. Aprono o creano un PDF, elencano i risultati di ricerca su tutte le pagine con numero di pagina, indice di carattere e testo di anteprima, supportano la navigazione Precedente / Successivo e il salto al risultato con doppio clic, evidenziano le corrispondenze della pagina corrente con HighlightSearchText, espongono le opzioni maiuscole/minuscole e parola intera, alternano AllowUserTextSelection, mostrano l'anteprima di SelectedText, pilotano SelectAll, CopySelectionToClipboard e ClearSelection dai pulsanti, e permettono di passare tra le modalità di visualizzazione singola e a doppia pagina

Lettura delle preferenze di stampa PDF in PrintPreferences

I progetti Demo\Delphi\Miscellaneous\PrintPreferences, Demo\CBuilder\Miscellaneous\PrintPreferences e Demo\Lazarus\Miscellaneous\PrintPreferences leggono le preferenze di stampa dell'autore prima di stampare. Visualizzano PrintCopies, PrintPageRanges, PrintScaling e PrintPaperHandling, possono copiare le copie e gli intervalli forniti dall'autore negli input di stampa, e mostrano come SetPdfPrintPaperHandlingDevMode mappa l'intento duplex PDF in un DEVMODE di Windows

Stampa PDF standard in PrintPDF

I progetti Demo\Delphi\PrintPDF, Demo\CBuilder\PrintPDF e Demo\Lazarus\PrintPDF mostrano il workflow di stampa standard: apertura di un PDF, anteprima delle pagine, scelta degli intervalli di pagine e delle copie nella finestra di dialogo di stampa della piattaforma, rispetto della modalità di fascicolazione, rendering di ciascuna pagina tramite TPdf.RenderPage ed esposizione del progresso di stampa con annullamento. L'esempio Delphi accetta anche file PDF trascinati per un caricamento rapido

Visualizzazione multi-pagina veloce in MultiPageViewer

I progetti Demo\Delphi\MultiPageViewer, Demo\CBuilder\MultiPageViewer e Demo\Lazarus\MultiPageViewer esercitano la visualizzazione continua, a doppia pagina e con gestione della copertina con i consueti workflow di navigazione e zoom delle pagine. Sono utili anche per testare la velocità di apertura alla prima pagina e la reattività del rendering su PDF molto grandi: nei test con file di grandi dimensioni, documenti da 2,x GB che possono far spendere ad Acrobat o Foxit 20-30 secondi prima della prima vista possono diventare usabili quasi immediatamente attraverso il percorso del visualizzatore di PDFium Delphi Component

Revisione di documenti affiancati in SplitView

I progetti Demo\Delphi\SplitView, Demo\CBuilder\SplitView e Demo\Lazarus\SplitView mostrano la revisione PDF side-by-side. Gli esempi C++Builder e Lazarus si concentrano sul confronto a due o tre riquadri, sulla selezione della view attiva, su comandi di navigazione sincronizzati opzionali, su preset di zoom condivisi e sulla rotazione per la view selezionata o per tutte le view caricate. Usare questi esempi per confrontare documenti di grandi dimensioni mantenendo reattive la prima vista utilizzabile e il rendering successivo delle pagine; gli stessi file PDF da 2,x GB che possono richiedere ad Acrobat o Foxit 20-30 secondi per l'apertura possono diventare usabili quasi immediatamente nel percorso del visualizzatore di PDFium Delphi Component

Audit della superficie di rischio PDF in SecurityAudit

I progetti Demo\Delphi\Miscellaneous\SecurityAudit, Demo\CBuilder\Miscellaneous\SecurityAudit e Demo\Lazarus\Miscellaneous\SecurityAudit aprono un PDF in sola lettura ed elencano permessi, allegati incorporati, azioni JavaScript del documento, annotazioni di link URI e Launch, web link, riepiloghi delle firme, stato XFA, disponibilità degli helper V8 e Callback di funzionalità non supportate. Riepilogo e segnalazioni possono essere salvati o copiati come report TXT, oppure salvati in JSON strutturato. Sono pannelli di rischio per applicazioni host, non rilevatori di malware

Gestione dei link nel visualizzatore

Clic sicuro per seguire i link con liste di consentiti per azione

// LinkOptions controls automatic handling of the four PDF link action
// types. Defaults enable goto and URI only; launch (run a program) and
// embedded GotoR (jump to another file) stay OFF so a stray click cannot
// run arbitrary code
PdfView1.LinkOptions :=
  [loAutoGoto, loAutoOpenURI];  // safe defaults

// OnAnnotationLinkClick fires for in-document destinations (page jumps,
// named destinations, action chains). Mark Handled = True to prevent the
// view from auto-following the link
procedure TForm1.PdfView1AnnotationLinkClick(Sender: TObject;
  LinkIndex: Integer; const Action: TPdfAction;
  var Handled: Boolean);
begin
  if Action.Kind = paUri then
  begin
    if MessageDlg('Open ' + Action.Uri + '?', mtConfirmation, [mbYes, mbNo], 0)
      <> mrYes then
      Handled := True;  // suppress auto-handling
  end;
end;

// OnWebLinkClick fires for URI strings discovered by PDFium's web-link
// scanner (auto-detected URLs in the text stream, even without an
// /A <</S/URI...>> annotation)
procedure TForm1.PdfView1WebLinkClick(Sender: TObject;
  WebLinkIndex: Integer; const Url: WString;
  var Handled: Boolean);
begin
  Log.Add('Web link clicked: ' + string(Url));
end;

Modifica dei widget di modulo nel visualizzatore

Selezione e Undo / Redo

// On the focused AcroForm widget, six new methods drive PDFium's form
// edit history. All six short-circuit safely if no widget is focused or
// the document carries no AcroForm
procedure TForm1.btnSelectAllClick(Sender: TObject);
begin
  PdfView1.SelectAllFormText;
  EditMenuCopy.Caption := 'Copy: ' + string(PdfView1.GetSelectedFormText);
end;

procedure TForm1.btnUndoClick(Sender: TObject);
begin
  btnUndo.Enabled := PdfView1.FormCanUndo;
  btnRedo.Enabled := PdfView1.FormCanRedo;
  if PdfView1.FormCanUndo then
    PdfView1.FormUndo;
end;

procedure TForm1.btnRedoClick(Sender: TObject);
begin
  if PdfView1.FormCanRedo then
    PdfView1.FormRedo;
end;

Blocco del visualizzatore per chioschi

Disabilitare i gesti di navigazione delle pagine

// All three default to True so existing apps upgrade with no behaviour
// change. Flip them False for kiosks, preview panes, or read-only
// embeddings without subclassing TPdfView
PdfView1.AllowUserPageChange       := False;  // PgUp/PgDn/Ctrl+Home/End
PdfView1.ChangePageOnMouseScrolling := False; // wheel up/down jumps
PdfView1.AllowUserTextSelection    := False;  // mouse/keyboard text selection

// Ctrl+wheel is reserved for zoom and is skipped by the navigation
// handler regardless of ChangePageOnMouseScrolling.

Pannello laterale miniature

Collegamento di un TPdfThumbnailView a un TPdfView

// TPdfThumbnailView (unit FPdfThumbnail) renders one page thumbnail per
// row in a scrollable side panel
uses FPdfThumbnail;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ThumbView.Pdf              := Pdf1;
  ThumbView.ThumbnailWidth   := 120;
  ThumbView.ThumbnailHeight  := 160;
  ThumbView.SelectionColor   := $00CFA85F;  // warm highlight
  ThumbView.OnPageClick      := ThumbViewPageClick;
end;

procedure TForm1.ThumbViewPageClick(Sender: TObject; PageIndex: Integer);
begin
  PdfView1.PageNumber := PageIndex + 1; // PageIndex is zero-based
end;

procedure TForm1.PdfView1PageNumberChanged(Sender: TObject);
begin
  ThumbView.CurrentPageIndex := PdfView1.PageNumber - 1;
end;

Esportazione batch cooperativamente annullabile

Conversione multi-file PDF in JPG con progresso per file e per pagina

// Pattern used by Demo\Delphi\BatchExport, Demo\CBuilder\BatchExport,
// and Demo\Lazarus\BatchExport. One TPdf per file, IPdfCancellationToken
// for cancel-from-UI, TPdfStreamAdapter for buffered file load
uses FPdfAsync;

procedure ExportBatch(const Files: TArray<string>;
  const OutDir: string; DPI: Integer; Quality: Integer;
  const ACancelToken: IPdfCancellationToken);
var
  I, J: Integer;
  Job:  TPdf;
  Bmp:  TBitmap;
  Jpeg: TJPEGImage;
begin
  for I := 0 to High(Files) do
  begin
    if ACancelToken.IsCancelled then Break;
    OverallProgress.Position := I;

    Job := TPdf.Create(nil);
    try
      Job.FileName := Files[I];
      Job.Active   := True;
      PageProgress.Max := Job.PageCount;

      for J := 1 to Job.PageCount do
      begin
        if ACancelToken.IsCancelled then Break;
        PageProgress.Position := J;

        Job.PageNumber := J;
        Bmp := Job.RenderPage(
          0, 0,
          Round(Job.PageWidth  * DPI / 72),
          Round(Job.PageHeight * DPI / 72));
        try
          Jpeg := TJPEGImage.Create;
          try
            Jpeg.CompressionQuality := Quality;
            Jpeg.Assign(Bmp);
            Jpeg.SaveToFile(Format('%s\%s.p%.3d.jpg',
              [OutDir, ExtractFileName(Files[I]), J]));
          finally
            Jpeg.Free;
          end;
        finally
          Bmp.Free;
        end;
      end;
    finally
      Job.Free;
    end;
  end;
end;

Coordinate del visualizzatore e hit testing

Adattare la pagina corrente e ispezionare il testo sotto il mouse

procedure FitCurrentPage;
begin
  PdfView1.Zoom := PdfView1.PageZoom[PdfView1.PageNumber];
end;

procedure InspectViewerPoint(X, Y: Integer);
var
  PageNo: Integer;
  PageX, PageY: Double;
  CharIndex: Integer;
  Ch: WString;
begin
  PageNo := PdfView1.PageNumber;
  if not PdfView1.DeviceToPage(X, Y, PageNo, PageX, PageY) then
    Exit;

  CharIndex := PdfView1.CharacterIndexAtPos(X, Y, 8, 8);
  if CharIndex >= 0 then
  begin
    Ch := PdfView1.Text(CharIndex, 1);
    ShowMessage(Format('Page %d, X %.2f, Y %.2f, character %s',
      [PageNo, PageX, PageY, string(Ch)]));
  end;
end;

Gestione degli errori

Operazioni PDF robuste

function LoadPdfSafely(const FileName: string): Boolean;
begin
  Result := False;
  if not FileExists(FileName) then
    Exit;
  try
    Pdf1.FileName := FileName;
    Pdf1.Active := True;
    Result := Pdf1.Active;
  except
    Result := False;
  end;
end;

function ExtractTextSafely(PageNo: Integer): WString;
begin
  Result := '';
  if not Pdf1.Active then
    Exit;
  if (PageNo < 1) or (PageNo > Pdf1.PageCount) then
    Exit;
  Pdf1.PageNumber := PageNo;
  Result := Pdf1.Text;
end;

Tagged PDF e accessibilità

Rilevare Tagged PDF e attraversare l'albero della struttura

// IsTagged is a cheap catalog probe — True when /StructTreeRoot exists
// StructureElements materialises the tree into a flat array of
// TPdfStructureElement records with type, title, alternate text, actual
// text, expansion text, language, level, parent index, and child / marked
// content / attribute counts
var
  Elements: TPdfStructureElements;
  I: Integer;
begin
  if not Pdf1.IsTagged then
  begin
    Log.Add('Document is NOT tagged — accessibility tools may struggle.');
    Exit;
  end;
  if Pdf1.Language = '' then
    Log.Add('Tagged PDF without /Lang — fails PDF/UA.');

  Elements := Pdf1.StructureElements;
  for I := 0 to High(Elements) do
    Log.Add(StringOfChar(' ', Elements[I].Level * 2)
      + Elements[I].StructType + ' "' + Elements[I].Title + '"');
end;

Selezione della modalità di stampa

Impostazione della modalità di stampa EMF / PostScript / Image-Mask

// SetPdfPrintMode is a global function that maps to PDFium's
// FPDF_SetPrintMode. Use the matching TPdfPrintMode value for the
// printer driver in use
SetPdfPrintMode(pmEmf);                   // GDI EMF (default)
// SetPdfPrintMode(pmTextOnly);           // text-only rendering
// SetPdfPrintMode(pmPostScript2);        // PostScript Level 2
// SetPdfPrintMode(pmPostScript3);        // PostScript Level 3
// SetPdfPrintMode(pmPostScript2PassThrough);
// SetPdfPrintMode(pmPostScript3PassThrough);
// SetPdfPrintMode(pmEmfImageMasks);      // EMF + image masks
// SetPdfPrintMode(pmPostScript3Type42);  // PostScript 3 + Type 42 fonts

Lettura delle impostazioni di stampa volute dall'autore

// PrintCopies, PrintPageRanges, PrintScaling, and PrintPaperHandling are
// the viewer-preference dictionary entries — they encode what the
// document author wanted PDF readers to default to
var
  Ranges: TPrintPageRanges;
  Range: TPrintPageRange;
begin
  ShowMessage('Suggested copies: ' + IntToStr(Pdf1.PrintCopies));
  ShowMessage('Print scaling: ' + GetEnumName(TypeInfo(TPrintScaling),
    Ord(Pdf1.PrintScaling)));

  Ranges := Pdf1.PrintPageRanges; // one-based ranges
  for Range in Ranges do
    Log.Add(Format('Pages %d..%d', [Range.First, Range.Last]));

  if SetPdfPrintPaperHandlingDevMode(PrinterDevMode, Pdf1.PrintPaperHandling) then
    ApplyPrinterDevMode(PrinterDevMode);
end;

Azioni JavaScript del documento

Enumerazione del JavaScript del name tree

// Document-level JavaScript is stored in the /Names /JavaScript name
// tree. JavaScriptAction[i] returns one entry; JavaScriptActions returns
// the full array
var
  I: Integer;
  Action: TPdfJavaScriptAction;
begin
  for I := 0 to Pdf1.JavaScriptActionCount - 1 do
  begin
    Action := Pdf1.JavaScriptAction[I];
    Memo1.Lines.Add('Name:   ' + string(Action.Name));
    Memo1.Lines.Add('Script: ' + string(Action.Script));
    Memo1.Lines.Add('---');
  end;
end;

Suggerimenti sulle prestazioni

Ottimizzazione delle operazioni PDF

procedure ProcessMultiplePages;
var
  I: Integer;
  PageText: WString;
begin
  for I := 1 to Pdf1.PageCount do
  begin
    Pdf1.PageNumber := I;
    PageText := Pdf1.Text;
    ProcessPageText(PageText);
  end;
end;

procedure SetOptimalRenderOptions;
begin
  PdfView1.Options := [reAnnotations, reLcd];
end;

// Zero-copy render path (default since v1.21.0): RenderPage writes
// directly into the destination TBitmap's DIB buffer when callers pass a
// pre-allocated bitmap, avoiding one width * height * 4 bytes copy
procedure RenderIntoCallerBitmap(Bitmap: TBitmap);
begin
  Bitmap.PixelFormat := pf32bit;
  Bitmap.SetSize(2480, 3508); // A4 @ 300 DPI
  Pdf1.RenderPage(Bitmap, 0, 0, Bitmap.Width, Bitmap.Height);
end;