Teknisk artikel

Delphi HotPDF Hello World: Ditt första PDF-program

Varje PDF-bibliotek levereras med ett "hello world", och HotPDF:s är värt att stanna upp vid, eftersom det minsta program som gör något överhuvudtaget redan tvingar fram två beslut som du kommer att upprepa i varje dokument därefter: vilket typsnitt som ska ställas in, och var på sidan texten landar. Få dessa två rätt och resten av API:et är variationer på ett tema. Här är hela alltet, ett konsolprogram som skriver en enda sida och hälsar läsaren på nästan ett dussin språk:

Diagram över programflödet för HotPDF Hello World med fyra anrop i Delphi, med PDF:s origo i nedre vänstra hörnet och två tysta fallgropar markerade
Create, begin, draw, end är hela ryggraden, och origo i nedre vänster förklarar varför senare rader använder mindre Y-värden
program HelloWorld;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows,   // för DEFAULT_CHARSET; på Delphi före XE2 använd bara Windows
  HPDFDoc;          // HotPDF:s huvudunit

procedure CreateHelloWorld(const FileName: string);
var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := FileName;
    Pdf.Compression := cmFlateDecode;   // krymp content streams
    Pdf.FontEmbedding := True;          // bädda in typsnittet så det renderar överallt
    Pdf.BeginDoc;

    // Ett typsnitt som täcker många skriftsystem. Fjärde argumentet är Windows charset;
    // DEFAULT_CHARSET låter systemet välja glyfer per sträng
    Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 14, DEFAULT_CHARSET);

    // TextOut mäter från NEDRE VÄNSTRA hörnet, i punkter, med Y uppåt
    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.

Flerspråkig Hello World-PDF producerad av HotPDF-Delphi-komponenten i Delphi

Det är hela exemplet. THotPDF.Create(nil) ihopparad med try/finally ... Free är det vanliga ägandemönstret i Delphi, och PDF ändrar inte på det. Det som förtjänar uppmärksamhet är fyrastegskärnan (spine) inuti: ställ in egenskaper, BeginDoc, rita, EndDoc. Ordningen är inte utbytbar

Ställ in dokumentegenskaper före BeginDoc

BeginDoc är det ögonblick då HotPDF bekräftar dokumentets struktur, så allt som påverkar hela filen måste ställas in innan dess. Compression := cmFlateDecode aktiverar FlateDecode för innehållsströmmarna, vilket är skillnaden mellan en kompakt fil och en onödigt uppsvälld (bloated) en. FontEmbedding := True packar det typsnitt du ritar med in i filen, så att den ser likadan ut på en dator som aldrig haft Arial Unicode MS installerat som den gör på din. Att tilldela någon av dem efter BeginDoc gör ingenting med det dokument som redan är igång, i all tysthet och utan något felmeddelande för att varna dig

SetFont, därefter TextOut, och se upp med origon

Två saker gällande ritanropen (drawing calls) överraskar alla på deras första sida. Det första är ordningen: SetFont måste köras innan någon TextOut som beror på det, och det måste upprepas efter varje AddPage, eftersom det aktuella typsnittet inte överlever en sidbrytning. Det andra är koordinatsystemet. TextOut mäter från sidans nedre vänstra hörn, inte det övre vänstra, med Y-axeln som ökar när du rör dig uppåt, i punkter (1/72 tum). Det är därför raderna här marscherar nedåt från 760, där varje är 30 punkter under den förra. Den som kommer från skärmgrafik antar motsatsen och skriver den första raden rakt ut från den nedre kanten

Ett typsnitt, många skript (scripts)

Anledningen till att en enda SetFont kan bära latin, kyrilliska, japanska och kinesiska på samma sida är själva typsnittet: Arial Unicode MS buntar ihop glyfer för nästan varje skript i en fil. Det fjärde argumentet till SetFont är Windows teckenuppsättning, och att skicka DEFAULT_CHARSET låter systemet välja glyfer per sträng istället för att låsa allt till en gammal kodsida. Två förbehåll (caveats) följer med den bekvämligheten. Typsnittet måste finnas på den dator som bygger PDF-filen, eftersom HotPDF bäddar in det som operativsystemet löser namnet till; om Arial Unicode MS saknas byter Windows tyst ut det mot en ersättare och din CJK-text kan komma ut som tomma rutor. Dessutom täcker den inte alla skript lika bra: för text från höger till vänster som arabiska och hebreiska, eller något som behöver komplex formning (complex shaping), sträcker du dig efter ett dedikerat typsnitt laddat med RegisterUnicodeTTF och de särskilda textanropen för höger-till-vänster, vilket är ett ämne i sig självt

Kör det och du får HelloWorld.pdf i arbetskatalogen: en sida, några rader med flerspråkig text, komprimerad, med typsnittet inbäddat. De uppenbara nästa stegen är att ge den texten storlek, stil och rotation, och att placera mer än ett block av det medvetet, vilket båda är saker som TextOut-exemplet arbetar sig igenom. När du vill rita linjer, rutor och bilder snarare än bara text, håller samma sidobjekt de anropen också

TextOut, SetFont, och de dokumentanrop som visas här är en del av HotPDF-Delphi-komponenten för Delphi och C++Builder