Tehnički članak

Delphi HotPDF Hello World: Vaš prvi PDF program

Svaka PDF biblioteka dolazi s primjerom "hello world," i HotPDF-ov je vrijedan usporavanja, jer najmanji program koji uopće nešto radi već nameće dvije odluke koje ćete ponavljati u svakom dokumentu nakon toga: koji font postaviti, te gdje na stranici se smješta tekst. Ispravno odradite ovo dvoje i ostatak API-ja samo je varijacija na temu. Ovdje je cijela stvar, konzolni program koji upisuje samo jednu stranicu pozdravljajući čitatelja na gotovo 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 мир!'); // 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 primjer. Povezivanje naredbe THotPDF.Create(nil) uz try/finally ... Free uobičajeni je Delphi obrazac (pattern) vlasništva, a PDF to ne mijenja. Ono što zaslužuje pažnju je kralježnica (spine) od četiri koraka iznutra: postavljanje svojstava (properties), BeginDoc, crtanje (draw), EndDoc. Redoslijed se ne može zamijeniti

Postavite svojstva dokumenta prije BeginDoc

BeginDoc je trenutak kada HotPDF primjenjuje strukturu dokumenta, tako da se sve što utječe na cijelu datoteku mora postaviti prije toga. Svojstvo Compression := cmFlateDecode uključuje FlateDecode za tokove sadržaja (content streams), što je razlika između kompaktne datoteke i bespotrebno prenapuhane. Svojstvo FontEmbedding := True ugrađuje (packs) font s kojim iscrtavate u datoteku, tako da izgleda isto na računalu koje nikada nije imalo instaliran Arial Unicode MS kao što izgleda na vašem računalu. Dodijelite li bilo koje od ovog nakon poziva BeginDoc, to tiho ne radi ništa u odnosu na dokument koji je već u procesu kreiranja, bez greške da vas upozori

SetFont, zatim TextOut, te pazite na ishodište

Dvije stvari vezane uz pozive za crtanje uhvate svakoga na njihovoj prvoj stranici. Prva je redoslijed: SetFont mora biti pokrenut prije bilo kojeg TextOut-a koji ovisi o njemu, i to se mora ponoviti nakon svakog poziva AddPage, jer trenutačni font ne preživljava prijelom stranice (page break). Druga je koordinatni sustav. TextOut mjeri od donjeg lijevog kuta stranice, a ne od gornjeg lijevog, s Y usmjerenim prema gore pri pomicanju, u točkama (points, 1/72 inča). To je razlog zašto se linije ovdje kreću prema dolje od 760, svaka 30 točaka ispod zadnje. Svatko tko dolazi iz svijeta grafike na ekranu pretpostavlja suprotno i prvu liniju upisuje točno iznad donjeg ruba

Jedan font, mnoga pisma

Razlog zašto jedan SetFont može podržati (carry) latinicu, ćirilicu, japansko i kinesko pismo na istoj stranici je u samom izgledu lica fonta: Arial Unicode MS povezuje (bundles) glifove (glyphs) za gotovo svako pismo u jednoj datoteci. Četvrti argument za SetFont je Windows skup znakova (character set), i prosljeđivanje DEFAULT_CHARSET omogućuje sustavu da izabere glifove prema nizu znakova (string) umjesto da veže sve (pinning) za samo jednu staru (legacy) kodnu stranicu. Uz tu su praktičnost povezana dva upozorenja (caveats). Font mora biti prisutan na stroju koji izgrađuje PDF, jer HotPDF ugrađuje u PDF bilo što, na što operativni sustav upućuje tim imenom; ako Arial Unicode MS nedostaje, Windows će tiho dodati zamjenu, a vaš CJK (kineski/japanski/korejski) tekst može izaći kao prazne kućice. I on ne obuhvaća svako pismo (script) na jednak način: za pismo zdesna nalijevo kao što su arapski i hebrejski, ili bilo što što zahtijeva složeno oblikovanje (shaping), morate posegnuti za dediciranim (dedicated) fontom učitanim s funkcijom RegisterUnicodeTTF uz pozive za tekst zdesna nalijevo, što je tema za sebe

Pokrenite ga i dobit ćete HelloWorld.pdf u radnom direktoriju: jednu stranicu, nekoliko redaka teksta na više jezika, sažetih s ugrađenim fontom. Sljedeći očiti koraci daju tom tekstu veličinu, stil i rotaciju i osmišljeno postavljaju više blokova, što sve prolazi primjer (sample) u TextOut-u. Kada umjesto samo teksta želite nacrtati crte (rules), okvire (boxes) i slike (images), objekt te iste stranice sadržavat će i te pozive

Metode TextOut, SetFont i pozivi funkcija za dokument koji su ovdje prikazani sastavni su dio HotPDF komponente namijenjene za Delphi i C++Builder