Technical Article

Delphi HotPDF Hello World: Váš prvý PDF program

Každá knižnica PDF obsahuje príklad "hello world" a pri HotPDF sa pri ňom oplatí pristaviť, pretože aj ten najmenší program, ktorý niečo robí, si vyžaduje dve rozhodnutia, ktoré budete opakovať v každých ďalších dokumentoch: aké písmo nastaviť a kam na stránke umiestniť text. Ak zvládnete tieto dve veci, zvyšok API sú už len variácie na rovnakú tému. Tu je kompletný kód konzolového programu, ktorý vytvorí jednu stránku s pozdravom pre čitateľa v takmer tucte jazykov:

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.

Viacjazyčné Hello World PDF vytvorené pomocou komponentu HotPDF v Delphi

To je celý príklad. Konštrukcia THotPDF.Create(nil) spárovaná s try/finally ... Free predstavuje bežný delphiovský vzor vlastníctva objektov a PDF na tom nič nemení. Pozornosť si zaslúži štvorfázový postup vo vnútri: nastavenie vlastností, BeginDoc, kreslenie a EndDoc. Ich poradie nie je možné zameniť.

Nastavenie vlastností dokumentu pred BeginDoc

BeginDoc je moment, kedy HotPDF potvrdí štruktúru dokumentu, takže všetko, čo ovplyvňuje celý súbor, musí byť nastavené pred ním. Compression := cmFlateDecode zapína FlateDecode pre dátové toky obsahu, čo predstavuje rozdiel medzi kompaktným súborom a zbytočne nafúknutým dokumentom. FontEmbedding := True zabalí použité písmo priamo do súboru, takže bude vyzerať rovnako na počítači, ktorý Arial Unicode MS nikdy nemal nainštalovaný, ako aj na vašom. Priradenie ktorejkoľvek z týchto vlastností po zavolaní BeginDoc ticho prebehne bez účinku na už rozpracovaný dokument a bez akejkoľvek chybovej správy.

SetFont, potom TextOut a pozor na počiatok súradníc

Pri prvých pokusoch s kreslením zvyčajne každého prekvapia dve veci. Prvou je poradie: SetFont sa musí spustiť pred akýmkoľvek volaním TextOut, ktoré na ňom závisí, a musí sa opakovať po každom AddPage, pretože aktuálne písmo neprežije prechod na novú stránku. Druhou vecou je súradnicový systém. TextOut meria súradnice od ľavého dolného rohu stránky, nie od ľavého horného rohu, pričom Y rastie smerom nahor v bodoch (1/72 palca). Preto riadky v tomto príklade smerujú nadol od hodnoty 760, pričom každý ďalší je o 30 bodov nižšie ako predchádzajúci. Každý, kto je zvyknutý na obrazovkovú grafiku, predpokladá opak a vykreslí prvý riadok priamo mimo spodného okraja stránky.

Jedno písmo, veľa skriptov

Dôvodom, prečo jedno volanie SetFont dokáže na rovnakej stránke zobraziť latinku, azbuku, japončinu a čínštinu, je samotná rodina písma: Arial Unicode MS spája glyfy pre takmer každý skript do jedného súboru. Štvrtým argumentom metódy SetFont je znaková sada systému Windows. Odovzdaním DEFAULT_CHARSET umožníte systému vybrať glyfy pre každý reťazec samostatne namiesto toho, aby sa všetko viazalo na jednu staršiu kódovú stránku. Táto vymoženosť však prináša dve úskalia. Písmo musí byť prítomné na počítači, ktorý PDF generuje, pretože HotPDF vloží presne to, na čo systém Windows daný názov rozlíši. Ak Arial Unicode MS chýba, Windows ho ticho nahradí iným písmom a váš CJK text sa môže zobraziť ako prázdne štvorčeky. A navyše nepokrýva všetky skripty rovnako: pre písanie sprava doľava, ako je arabčina a hebrejčina, alebo pre čokoľvek, čo si vyžaduje zložité tvarovanie textu, budete musieť použiť špecializované písmo načítané pomocou RegisterUnicodeTTF a volania pre text sprava doľava, čo je samostatná téma.

Spustite ho a v pracovnom adresári získate súbor HelloWorld.pdf: jednu stránku, niekoľko riadkov viacjazyčného textu, skomprimovanú a so zabudovaným písmom. Ďalšími logickými krokmi sú nastavenie veľkosti, štýlu a otočenia tohto textu, ako aj zámerné umiestnenie viacerých blokov textu, čomu sa podrobne venuje príklad TextOut. Ak chcete okrem textu kresliť aj čiary, obdĺžniky a obrázky, rovnaký objekt stránky poskytuje aj tieto funkcie.

Volania TextOut, SetFont a ďalšie zdokumentované volania sú súčasťou HotPDF Component pre Delphi a C++Builder.