Technický článek

Delphi HotPDF Hello World: Váš první program pro PDF

Každá knihovna PDF obsahuje příklad „hello world“ a u toho od HotPDF stojí za to se zastavit, protože ten nejmenší program, který něco dělá, vás už nutí ke dvěma rozhodnutím, která budete následně opakovat u každého dokumentu: jaké písmo nastavit a kam na stránce text umístit. Pokud tyto dvě věci zvládnete správně, zbytek API jsou jen variace na toto téma. Zde je to celé, konzolový program, který napíše jedinou stránku a pozdraví čtenáře v téměř tuctu jazyků:

Diagram čtyřvolacího toku programu HotPDF Hello World v Delphi s původem PDF vlevo dole a dvěma zvýrazněnými tichými pastmi
Vytvořit, začít, kreslit, ukončit — to je celá páteř, a počátek vlevo dole vysvětluje, proč pozdější řádky používají menší hodnoty Y
program HelloWorld;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows,   // pro DEFAULT_CHARSET; v Delphi před XE2 použijte běžné Windows
  HPDFDoc;          // hlavní unit HotPDF

procedure CreateHelloWorld(const FileName: string);
var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := FileName;
    Pdf.Compression := cmFlateDecode;   // zmenšete proudy obsahu
    Pdf.FontEmbedding := True;          // vložte řez písma, aby se vykreslil kdekoli
    Pdf.BeginDoc;

    // Jeden řez pokrývající mnoho písem. 4. argument je znaková sada Windows
    // DEFAULT_CHARSET nechá systém vybrat glyfy podle řetězce
    Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 14, DEFAULT_CHARSET);

    // TextOut měří od levého dolního rohu v bodech, osa Y roste nahoru
    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.

Vícejazyčné Hello World PDF vytvořené komponentou HotPDF v Delphi

To je celý příklad. Volání THotPDF.Create(nil) spárované s try/finally ... Free je běžný vzor vlastnictví v Delphi a PDF na tom nic nemění. Co si zaslouží pozornost, je vnitřní páteř o čtyřech krocích: nastavení vlastností, BeginDoc, kreslení, EndDoc. Toto pořadí nelze zaměnit

Před BeginDoc nastavte vlastnosti dokumentu

BeginDoc je okamžik, kdy HotPDF potvrdí (commitne) strukturu dokumentu, takže vše, co ovlivňuje celý soubor, musí být nastaveno před ním. Compression := cmFlateDecode zapíná kódování FlateDecode pro datové toky (content streams), což tvoří rozdíl mezi kompaktním a zbytečně nabobtnalým souborem. FontEmbedding := True přibalí písmo, kterým kreslíte, do souboru, takže dokument bude vypadat stejně na stroji, kde nikdy nebylo nainstalováno písmo Arial Unicode MS, jako u vás. Pokud kteroukoli z těchto vlastností přiřadíte až po BeginDoc, tiše to na již rozpracovaném dokumentu neudělá nic a neupozorní vás žádná chyba

SetFont, pak TextOut, a dávejte pozor na počátek (origin)

Na prvních vykreslovacích voláních každého zaskočí dvě věci. Tou první je pořadí: SetFont se musí provést před každým TextOut, které na něm závisí, a musí se zopakovat po každém AddPage, protože aktuální písmo nepřežije zalomení stránky. Druhou je souřadnicový systém. TextOut měří od levého dolního rohu stránky, nikoliv od levého horního, přičemž Y se směrem nahoru zvětšuje, a to v bodech (1/72 palce). Proto zde řádky kráčejí směrem dolů z hodnoty 760, každý o 30 bodů níže než ten předchozí. Každý, kdo přichází ze světa počítačové grafiky, předpokládá opak a napíše první řádek rovnou mimo spodní okraj stránky

Jedno písmo, mnoho abeced (skriptů)

Důvodem, proč jedno volání SetFont zvládne latinku, cyrilici, japonštinu a čínštinu na jedné stránce, je samotný typ písma: Arial Unicode MS do jednoho souboru balí glyfy pro téměř každé písmo. Čtvrtým argumentem funkce SetFont je znaková sada Windows a předání DEFAULT_CHARSET umožňuje systému vybírat glyfy pro každý řetězec zvlášť, místo aby vše vázal na jednu zastaralou kódovou stránku. S tímto pohodlím se však pojí dvě upozornění. Písmo musí být přítomno na stroji, který PDF sestavuje, protože HotPDF vloží to, na co OS název přeloží; pokud Arial Unicode MS chybí, Windows jej tiše zamění za náhradu a váš text CJK (čínština-japonština-korejština) se může zobrazit jako prázdné rámečky. Navíc nepokrývá všechna písma rovnocenně: pro písma psaná zprava doleva, jako je arabština a hebrejština, nebo pro cokoliv, co vyžaduje složité tvarování (shaping), sáhněte po specializovaném písmu nahraném pomocí RegisterUnicodeTTF a volání textu zprava doleva, což je téma samo pro sebe

Spusťte to a v pracovním adresáři získáte HelloWorld.pdf: jednu stránku, několik řádků vícejazyčného textu, zkomprimováno a s vloženým písmem. Jasnými dalšími kroky jsou přidělení velikosti, stylu a rotace tomuto textu, stejně jako cílené umístění více než jednoho bloku textu. Obojí probírá ukázka TextOut sample. Když chcete kreslit čáry, rámečky a obrázky, nejen text, stejný objekt stránky obsahuje i tato volání

Zde zobrazená volání TextOut, SetFont a volání dokumentu jsou součástí HotPDF Delphi Component pro Delphi a C++Builder