每个 PDF 库都会附带一个“hello world”,而 HotPDF 的这个示例值得您放慢脚步仔细研究,因为即使是执行任何操作的最小程序,也会迫使您做出在之后每个文档中都会重复的两个决定:设置哪种字体,以及文本落在页面上的哪个位置。只要把这两个决定做对,API 的其余部分就只是主题的变体。这里是完整的代码,一个控制台程序,它写入单页内容,用近十几种语言向读者问好:
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.

这就是整个示例。THotPDF.Create(nil) 搭配 try/finally ... Free 是普通的 Delphi 所有权模式,PDF 并没有改变它。值得注意的是内部的四步核心流程:设置属性、BeginDoc、绘制、EndDoc。这个顺序是不可互换的
在 BeginDoc 之前设置文档属性
BeginDoc 是 HotPDF 提交文档结构的时刻,因此任何影响整个文件的内容都必须在此之前设置。Compression := cmFlateDecode 会开启内容流的 FlateDecode 压缩,这就是紧凑文件与不必要臃肿文件之间的区别。FontEmbedding := True 会将您绘制所用的字体打包到文件中,因此它在从未安装过 Arial Unicode MS 的机器上看起来与在您的机器上一样。如果在 BeginDoc 之后指定其中任何一个,它对正在进行的文档将默默地不起任何作用,也没有错误来警告您
先 SetFont,再 TextOut,并注意原点
关于绘制调用的两件事在每个人绘制第一页时都会引起注意。第一是顺序:SetFont 必须在任何依赖于它的 TextOut 之前运行,并且必须在每个 AddPage 之后重复调用,因为当前字体无法在分页后保留。第二是坐标系。TextOut 是从页面的左下角进行测量,而不是左上角,Y 坐标随着向上移动而增加,单位为磅(1/72 英寸)。这就是为什么这里的行从 760 开始向下排列,每一行都在上一行的下方 30 磅处。任何习惯于屏幕图形的人都会做相反的假设,结果将第一行直接写到了底边缘之外
一种字体,多种脚本
单个 SetFont 能够在同一页面上承载拉丁文、西里尔文、日文和中文的原因在于字体本身:Arial Unicode MS 将几乎所有脚本的字形捆绑在一个文件中。SetFont 的第四个参数是 Windows 字符集,传递 DEFAULT_CHARSET 可以让系统为每个字符串选择字形,而不是将所有内容固定在一个传统的代码页上。这种便利伴随着两个警告。构建 PDF 的机器上必须存在该字体,因为 HotPDF 会嵌入操作系统所解析到的任何名称的字体;如果缺少 Arial Unicode MS,Windows 会默默地换上一个替代品,您的中日韩(CJK)文本可能会变成空方块。而且它并没有同等涵盖每一个脚本:对于像阿拉伯语和希伯来语这样从右到左的书写系统,或者任何需要复杂成形的语言,您需要使用通过 RegisterUnicodeTTF 加载的专用字体以及从右到左的文本调用,这又是另一个话题了
运行它,您会在工作目录中得到 HelloWorld.pdf:单页,几行多语言文本,已压缩,并嵌入了字体。显然接下来的步骤是赋予该文本大小、样式和旋转效果,并刻意放置多个文本块,这两个方面在 TextOut 示例 中都有详细说明。当您想要绘制线条、方框和图像而不仅仅是文本时,同一个页面对象也包含这些调用
这里展示的 TextOut、SetFont 和文档调用是适用于 Delphi 和 C++Builder 的 HotPDF 组件的一部分