Articolo tecnico

Delphi HotPDF Hello World: il tuo primo programma PDF

Ogni libreria PDF include un "hello world," e quello di HotPDF merita un momento di attenzione, perché il programma più semplice che fa qualcosa impone già due decisioni che ripeterai in ogni documento successivo: quale font impostare e dove posizionare il testo sulla pagina. Azzecca queste due cose e il resto dell'API è una variazione sul tema. Ecco il programma completo, una console application che saluta il lettore in quasi una dozzina di lingue:

program HelloWorld;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows,   // for DEFAULT_CHARSET; on pre-XE2 Delphi use plain Windows
  HPDFDoc;          // HotPDF main unit

procedure CreateHelloWorld(const FileName: string);
var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := FileName;
    Pdf.Compression := cmFlateDecode;   // shrink the content streams
    Pdf.FontEmbedding := True;          // embed the face so it renders anywhere
    Pdf.BeginDoc;

    // One face covering many scripts. The 4th argument is the Windows charset;
    // DEFAULT_CHARSET lets the system pick glyphs per string.
    Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 14, DEFAULT_CHARSET);

    // TextOut measures from the BOTTOM-LEFT corner, in points, Y growing upward.
    Pdf.CurrentPage.TextOut(72, 760, 0, 'Hello, Delphi PDF world!');     // English
    Pdf.CurrentPage.TextOut(72, 730, 0, 'Hola, mundo Delphi PDF!');      // Spanish
    Pdf.CurrentPage.TextOut(72, 700, 0, 'Hallo, Delphi PDF Welt!');      // German
    Pdf.CurrentPage.TextOut(72, 670, 0, 'Bonjour, monde PDF Delphi!');   // French
    Pdf.CurrentPage.TextOut(72, 640, 0, 'Ciao, mondo Delphi PDF!');      // Italian
    Pdf.CurrentPage.TextOut(72, 610, 0, 'Olá, mundo Delphi PDF!');       // Portuguese
    Pdf.CurrentPage.TextOut(72, 580, 0, 'Здравствуйте, Delphi PDF мир!'); // Russian
    Pdf.CurrentPage.TextOut(72, 550, 0, 'こんにちは、Delphi PDFの世界!');    // Japanese
    Pdf.CurrentPage.TextOut(72, 520, 0, 'Merhaba, Delphi PDF dünyası!');  // Turkish
    Pdf.CurrentPage.TextOut(72, 490, 0, '你好,Delphi PDF世界');           // Chinese
    Pdf.CurrentPage.TextOut(72, 460, 0, '여보세요, Delphi PDF 세계!');      // Korean

    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

begin
  CreateHelloWorld('HelloWorld.pdf');
  Writeln('Wrote HelloWorld.pdf');
end.

PDF Hello World multilingue prodotto dal componente HotPDF in Delphi

Questo è l'intero esempio. Il pattern THotPDF.Create(nil) abbinato a try/finally ... Free è il normale idioma Delphi di gestione della proprietà, e PDF non lo cambia. Ciò che merita attenzione è la struttura a quattro passi al suo interno: imposta le proprietà, BeginDoc, disegna, EndDoc. L'ordine non è intercambiabile.

Imposta le proprietà del documento prima di BeginDoc

BeginDoc è il momento in cui HotPDF consolida la struttura del documento, quindi tutto ciò che riguarda l'intero file deve essere impostato prima. Compression := cmFlateDecode attiva la compressione FlateDecode per i flussi di contenuto, il che fa la differenza tra un file compatto e uno inutilmente voluminoso. FontEmbedding := True incorpora il font usato per disegnare nel file, in modo che abbia lo stesso aspetto su una macchina che non ha mai avuto Arial Unicode MS installato come ce l'ha la tua. Assegnare uno dei due dopo BeginDoc non ha effetto sul documento già in corso, senza alcun avviso.

SetFont, poi TextOut, e attenzione all'origine

Due aspetti delle chiamate di disegno colgono di sorpresa al primo utilizzo. Il primo è l'ordine: SetFont deve essere chiamato prima di qualsiasi TextOut che dipende da esso, e deve essere ripetuto dopo ogni AddPage, perché il font corrente non sopravvive a un'interruzione di pagina. Il secondo è il sistema di coordinate. TextOut misura dall'angolo in basso a sinistra della pagina, non dall'alto a sinistra, con Y che cresce verso l'alto, in punti (1/72 di pollice). Per questo le righe qui scendono da 760, ciascuna 30 punti sotto la precedente. Chi arriva dalla grafica su schermo assume il contrario e scrive la prima riga fuori dal bordo inferiore.

Un font, molte scritture

Il motivo per cui un singolo SetFont può gestire latino, cirillico, giapponese e cinese nella stessa pagina è il font stesso: Arial Unicode MS raggruppa i glifi di quasi ogni sistema di scrittura in un unico file. Il quarto argomento di SetFont è il set di caratteri Windows, e passare DEFAULT_CHARSET lascia al sistema la scelta dei glifi per stringa invece di vincolare tutto a una singola code page legacy. Questo vantaggio porta con sé due avvertenze. Il font deve essere presente sulla macchina che genera il PDF, perché HotPDF incorpora qualunque cosa il sistema operativo risolva con quel nome; se Arial Unicode MS è assente, Windows sostituisce silenziosamente un altro font e il testo CJK può comparire come caselle vuote. E non copre ogni sistema di scrittura in modo uniforme: per la scrittura da destra a sinistra come l'arabo e l'ebraico, o per tutto ciò che richiede una composizione complessa, si ricorre a un font dedicato caricato con RegisterUnicodeTTF e alle chiamate per testo da destra a sinistra, argomento a sé stante.

Eseguilo e otterrai HelloWorld.pdf nella directory di lavoro: una pagina, alcune righe di testo multilingue, compresso, con il font incorporato. I passi successivi ovvi sono dare a quel testo dimensione, stile e rotazione, e posizionare più blocchi in modo preciso, entrambi trattati nell'esempio TextOut. Quando vuoi disegnare linee, riquadri e immagini oltre al testo, lo stesso oggetto pagina contiene anche quelle chiamate.

Le chiamate TextOut, SetFont e del documento mostrate qui fanno parte del HotPDF Component per Delphi e C++Builder.