Tehnični članak

Delphi HotPDF Hello World: Vaš prvi PDF program

Vsaka PDF knjižnica ponuja "hello world" in ob HotPDF-jevem se je vredno ustaviti, saj vas že najmanjši program, ki sploh kaj naredi, prisili v dve odločitvi, ki ju boste ponovili v vsakem nadaljnjem dokumentu: katero pisavo nastaviti in kam na strani bo padlo besedilo. Če pravilno izberete to dvoje, je preostali del API-ja le variacija na temo. Tukaj je celotna stvar, konzolni program, ki napiše eno stran in bralca pozdravi v skoraj dvanajstih jezikih:

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.

Večjezični Hello World PDF, ki ga je ustvarila komponenta HotPDF v Delphiju

To je celoten primer. Povezava THotPDF.Create(nil) v paru s try/finally ... Free je običajen vzorec lastništva (ownership pattern) v Delphiju in PDF tega ne spremeni. Tisto, kar si zasluži pozornost, je štiristopenjska hrbtenica v notranjosti: nastavitev lastnosti, BeginDoc, risanje, EndDoc. Vrstnega reda ni mogoče zamenjati

Nastavitev lastnosti dokumenta pred BeginDoc

BeginDoc je trenutek, ko HotPDF potrdi (commit) strukturo dokumenta, zato mora biti vse, kar vpliva na celotno datoteko, nastavljeno pred tem. Compression := cmFlateDecode vklopi FlateDecode za tokove vsebine (content streams), kar je razlika med kompaktno in po nepotrebnem napihnjeno datoteko. FontEmbedding := True zapakira pisavo, s katero rišete, v datoteko, tako da je videti enako tudi na računalniku, ki nikoli ni imel nameščene pisave Arial Unicode MS, kot pri vas. Če katero od njiju dodelite po klicu BeginDoc, ta tiho ne naredi ničesar na dokumentu, ki se že obdeluje, brez napake, ki bi vas opozorila

SetFont, nato TextOut, in pazite na izhodišče

Pri klicih risanja vsakogar na prvi strani presenetita dve stvari. Prva je vrstni red: SetFont se mora izvesti pred katerimkoli klicem TextOut, ki je odvisen od njega, in ga je treba ponoviti po vsakem AddPage, saj trenutna pisava ne preživi preloma strani. Druga je koordinatni sistem. TextOut meri od spodnjega levega kota strani (bottom-left corner), ne od zgoraj levo, pri čemer se Y povečuje, ko se pomikate navzgor, in sicer v točkah (1/72 palca). Zato vrstice tukaj korakajo navzdol od 760, pri čemer je vsaka 30 točk pod prejšnjo. Kdor prihaja iz zaslonske grafike, predvideva nasprotno in napiše prvo vrstico naravnost s spodnjega roba

Ena pisava, veliko pisav

Razlog, zakaj lahko en klic SetFont nosi latinično, cirilično, japonsko in kitajsko pisavo na isti strani, je sama pisava: Arial Unicode MS združuje glife (glyphs) za skoraj vse pisave v eno datoteko. Četrti argument za SetFont je znakovni nabor operacijskega sistema Windows (character set), s posredovanjem DEFAULT_CHARSET pa sistemu omogočimo, da izbere glife za vsak niz (string) posebej, namesto da bi vse priklenil na en star nabor znakov (legacy code page). Kljub temu udobju pa veljata dve opozorili. Pisava mora biti prisotna na računalniku, ki gradi PDF, saj HotPDF vključi tisto, v kar OS razreši njeno ime; če Arial Unicode MS manjka, Windows tiho podtakne zamenjavo in vaše CJK besedilo se lahko izpiše kot prazni kvadratki. Prav tako pisava ne pokriva vseh sistemov pisanja enako: za pisanje od desne proti levi, kot sta arabščina in hebrejščina, ali karkoli, kar potrebuje kompleksno oblikovanje (complex shaping), posežete po namenski pisavi, naloženi z RegisterUnicodeTTF, in klicih besedila od desne proti levi, kar pa je že svoja tema

Zaženite kodo in v delovni mapi dobite HelloWorld.pdf: ena stran, nekaj vrstic večjezičnega besedila, stisnjeno, z vdelano pisavo. Očitni naslednji koraki so dodajanje velikosti, sloga in rotacije temu besedilu ter namerna postavitev več kot enega bloka, kar je obdelano v TextOut primeru. Če želite risati črte, polja in slike namesto zgolj besedila, isti predmet strani vsebuje tudi te klice

TextOut, SetFont in klici dokumentov, prikazani tukaj, so del komponente HotPDF Component za Delphi in C++Builder