Technical Article

Delphi HotPDF Hello World: Vaš prvi PDF program

Svaka PDF biblioteka sadrži „hello world“ primer, a onaj iz HotPDF-a zaslužuje detaljniju analizu. Najmanji program koji radi bilo šta već zahteva dve odluke koje ćete ponavljati u svakom dokumentu nakon toga: koji font postaviti i gde na stranici prikazati tekst. Ako ove dve stvari uradite kako treba, ostatak API-ja je samo varijacija na temu. Evo celog koda, konzolnog programa koji kreira jednu stranicu sa pozdravom čitaocu na skoro desetak jezika:

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 mir!'); // 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.

Multilingual Hello World PDF produced by the HotPDF component in Delphi

To je čitav primer. THotPDF.Create(nil) u kombinaciji sa try/finally ... Free predstavlja uobičajeni šablon vlasništva u Delphi-ju, i PDF to ne menja. Ono što zaslužuje pažnju jeste struktura od četiri koraka: podešavanje svojstava, BeginDoc, crtanje, EndDoc. Redosled nije zamenljiv.

Podešavanje svojstava dokumenta pre poziva BeginDoc

BeginDoc predstavlja trenutak kada HotPDF definiše strukturu dokumenta, tako da sve što utiče na ceo fajl mora biti podešeno pre toga. Podešavanje Compression := cmFlateDecode uključuje FlateDecode za tokove sadržaja (content streams), što čini razliku između kompaktne datoteke i nepotrebno prevelike. Svojstvo FontEmbedding := True pakuje font kojim crtate direktno u fajl, tako da izgleda isto na računaru koji nikada nije imao instaliran Arial Unicode MS kao i na vašem. Ako bilo koje od ovih svojstava dodelite nakon poziva BeginDoc, to neće imati nikakvog efekta na dokument koji je već u toku, i to bez ikakve greške koja bi vas na to upozorila.

SetFont, zatim TextOut, i pazite na koordinatni početak

Dve stvari kod poziva za crtanje zbunjuju skoro svakoga na prvoj stranici. Prva je redosled: SetFont mora da se pokrene pre bilo kog poziva TextOut koji zavisi od njega, i mora se ponoviti nakon svakog AddPage poziva, jer trenutni font ne opstaje nakon preloma stranice. Druga stvar je koordinatni sistem. TextOut meri rastojanje od donjeg levog ugla stranice, a ne od gornjeg levog, pri čemu se vrednost Y povećava kako se krećete nagore, u tačkama (points, 1/72 inča). Zato se linije ovde spuštaju naniže od 760, gde je svaka 30 tačaka ispod prethodne. Svako ko dolazi iz sveta računarske grafike na ekranu pretpostavlja suprotno i ispisuje prvu liniju direktno van donje ivice ekrana.

Jedan font, mnogo pisama

Razlog zašto jedan poziv SetFont može da podrži latinicu, ćirilicu, japanski i kineski na istoj stranici leži u samom fontu: Arial Unicode MS pakuje glifove za skoro svako pismo u jednu datoteku. Četvrti argument za SetFont je Windows skup karaktera (character set), a prosleđivanje DEFAULT_CHARSET omogućava sistemu da bira glifove po stringu umesto da sve vezuje za jednu staru kodnu stranicu. Uz ovu pogodnost idu i dva upozorenja. Font mora biti prisutan na računaru koji kreira PDF, jer HotPDF ugrađuje ono u šta operativni sistem razreši naziv; ako Arial Unicode MS nedostaje, Windows tiho ubacuje zamenu i vaš CJK tekst može biti prikazan kao prazni kvadratići. Takođe, ovo ne pokriva svako pismo podjednako: za pisanje zdesna nalevo kao što su arapski i hebrejski, ili bilo šta što zahteva složeno oblikovanje teksta, koristi se namenski font učitan pomoću RegisterUnicodeTTF i pozivi za tekst zdesna nalevo, što je tema za sebe.

Pokrenite ga i dobićete fajl HelloWorld.pdf u radnom direktorijumu: jedna stranica, nekoliko linija višejezičnog teksta, kompresovano i sa ugrađenim fontom. Očigledni sledeći koraci su definisanje veličine, stila i rotacije tog teksta, kao i pažljivo postavljanje više blokova teksta, što je detaljno objašnjeno u TextOut primeru. Kada želite da crtate linije, okvire i slike umesto samo teksta, isti objekat stranice sadrži i te pozive.

Pozivi TextOut, SetFont, kao i pozivi za dokument prikazani ovde deo su HotPDF komponente za Delphi i C++Builder.