Odborný článok

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

Každá knižnica pre PDF obsahuje program „hello world“ (ahoj svet). Pri HotPDF sa oplatí pri ňom trochu zastaviť, pretože aj ten najmenší program, ktorý robí vôbec niečo, vás už núti urobiť dve rozhodnutia, ktoré budete opakovať v každom ďalšom dokumente: aké písmo nastaviť a kam na stránke umiestniť text. Keď zvládnete tieto dve veci, zvyšok API sú už len variácie na tú istú tému. Tu je celý príklad – konzolový program, ktorý zapíše jednu stranu zdraviacu č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. Zápis THotPDF.Create(nil) spárovaný s try/finally ... Free je bežný vzor vlastníctva v Delphi a práca s PDF na ňom nič nemení. Pozornosť si zaslúži štvorkroková kostra vo vnútri: nastavenie vlastností, BeginDoc, vykresľovanie, EndDoc. Toto poradie nie je možné zamieňať

Nastavte vlastnosti dokumentu pred BeginDoc

BeginDoc je moment, kedy HotPDF fixuje š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 obsahové toky, čo je rozdiel medzi kompaktným súborom a zbytočne nafúknutým súborom. FontEmbedding := True pribalí písmo, ktorým kreslíte, do súboru, takže bude vyzerať rovnako na stroji, ktorý nikdy nemal nainštalované Arial Unicode MS, ako na vašom. Ak priradíte ktorúkoľvek z týchto vlastností po BeginDoc, v už prebiehajúcom dokumente sa potichu nevykoná žiadna zmena a nezobrazí sa ani žiadna chyba, ktorá by vás na to upozornila

SetFont, potom TextOut, a dávajte pozor na začiatok súradníc

Dve veci týkajúce sa príkazov na vykresľovanie prekvapia každého na jeho prvej stránke. Prvou je poradie: SetFont sa musí spustiť pred akýmkoľvek volaním TextOut, ktoré od neho závisí, a musí sa zopakovať po každom AddPage, pretože aktuálne písmo neprežije zalomenie strany. Druhou vecou je súradnicový systém. TextOut meria od ľavého dolného rohu stránky, nie od ľavého horného, pričom Y narastá, keď sa pohybujete nahor, a to v bodoch (1/72 palca). Preto sa riadky v tomto príklade posúvajú nadol od hodnoty 760, pričom každý je 30 bodov pod tým predchádzajúcim. Každý, kto prichádza s grafikou pre obrazovku, predpokladá opak a zapíše prvý riadok rovno pod spodný okraj

Jedno písmo, veľa skriptov

Dôvod, prečo môže jediné volanie SetFont obsahovať latinku, cyriliku, japončinu a čínštinu na rovnakej stránke, spočíva v samotnom písme: Arial Unicode MS spája piktogramy (glyfy) takmer každého písma do jedného súboru. Štvrtým argumentom pre SetFont je znaková sada Windows a predanie DEFAULT_CHARSET umožňuje systému zvoliť piktogramy na základe reťazca, namiesto toho, aby sa všetko fixovalo na jednu staršiu kódovú stránku (code page). S týmto uľahčením sú spojené dve upozornenia. Písmo musí byť prítomné na stroji, ktorý zostavuje PDF, pretože HotPDF vloží to, na čo OS vyrieši daný názov; ak Arial Unicode MS chýba, Windows potichu použije náhradu a váš text v CJK sa môže zobraziť ako prázdne štvorčeky. Ďalšou vecou je, ž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 (shaping), siahnete po dedikovanom písme načítanom pomocou RegisterUnicodeTTF a príkazoch pre text sprava doľava, čo je úplne samostatná téma

Spustite to a dostanete HelloWorld.pdf v pracovnom adresári: jedna stránka, niekoľko riadkov viacjazyčného textu, komprimované, s vloženým písmom. Zrejmými ďalšími krokmi je pridanie veľkosti, štýlu a rotácie danému textu, a umiestnenie viac ako jedného bloku textu presne podľa predstáv, čomu sa venuje príklad s TextOut. Keď chcete kresliť čiary, obdĺžniky a obrázky, nielen text, rovnaký objekt stránky slúži aj pre tieto príkazy

Volania TextOut, SetFont a príkazy pre dokument uvedené vyššie sú súčasťou HotPDF Component pre Delphi a C++Builder