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:

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.

Flerspråkig Hello World-PDF producerad av HotPDF-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-komponenten för Delphi och C++Builder