Şartnamenin bakış açısıyla yazılmış bir ilk satır y = 770'e düşer. Mantık kâğıt üzerinde sağlamdır: ISO 32000-1, user space'in kökenini sol alt köşeye koyar, bir A4 sayfası 842 punto uzundur; dolayısıyla 770, üst kenarın bir inç altındadır. O programı bunun yerine üstten ölçen bir bileşene karşı çalıştırın ve selamlama, alt kenarın bir inç kadar üstüne düşer; sayfanın geri kalanı üstünde boş kalır. İkinci bir sayfa ekleyin ve özenle seçilmiş font 12 punto Arial'e geri döner. İki sürpriz de her PDF programının ilk sayfasında verdiği iki karardan gelir: hangi fontun güncel olduğu ve sayıların hangi köşeden sayıldığı
Delphi'deki en küçük HotPDF programı
HotPDF Hello World, sabit bir sırayla dört çağrısı olan bir konsol programıdır: belge özelliklerini ayarla, BeginDoc, SetFont ile TextOut ile çiz, sonra EndDoc. Geri kalan her şey sıradan Delphi'dir. İşte program; okuyucuyu on bir dilde selamlayan tek bir sayfayı yazıyor:
program HelloWorld;
{$APPTYPE CONSOLE}
uses
Winapi.Windows, // DEFAULT_CHARSET; XE2 öncesi Delphi'de düz Windows kullanın
HPDFDoc; // HotPDF ana unit'i
procedure CreateHelloWorld(const FileName: string);
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
// Belge çapında ayarlar: bunların tümü BeginDoc'tan önce gelir
Pdf.FileName := FileName;
Pdf.AutoLaunch := False; // varsayılan True'dur: EndDoc'tan sonra görüntüleyiciyi açar
Pdf.Compression := cmFlateDecode; // varsayılan cmNone'dur
Pdf.FontEmbedding := True; // zaten varsayılan; okuyucu için açıkça yazıldı
Pdf.EnableFontSubsetting := True; // yalnızca gerçekten çizilen glifleri gömer
Pdf.BeginDoc; // 1. sayfayı oluşturur (A4)
// 4. bağımsız değişkenin varsayılanı ANSI_CHARSET'tir; DEFAULT_CHARSET'i açıkça geçirin
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 14, DEFAULT_CHARSET);
// X, Y SOL ÜST köşeden punto cinsindendir; Y satırın üst kenarıdır
Pdf.CurrentPage.TextOut(72, 72, 0, 'Hello, Delphi PDF world!'); // İngilizce
Pdf.CurrentPage.TextOut(72, 102, 0, 'Hola, mundo Delphi PDF!'); // İspanyolca
Pdf.CurrentPage.TextOut(72, 132, 0, 'Hallo, Delphi PDF Welt!'); // Almanca
Pdf.CurrentPage.TextOut(72, 162, 0, 'Bonjour, monde PDF Delphi!'); // Fransızca
Pdf.CurrentPage.TextOut(72, 192, 0, 'Ciao, mondo Delphi PDF!'); // İtalyanca
Pdf.CurrentPage.TextOut(72, 222, 0, 'Olá, mundo Delphi PDF!'); // Portekizce
Pdf.CurrentPage.TextOut(72, 252, 0, 'Здравствуйте, Delphi PDF мир!'); // Rusça
Pdf.CurrentPage.TextOut(72, 282, 0, 'こんにちは、Delphi PDFの世界!'); // Japonca
Pdf.CurrentPage.TextOut(72, 312, 0, 'Merhaba, Delphi PDF dünyası!'); // Türkçe
Pdf.CurrentPage.TextOut(72, 342, 0, '你好,Delphi PDF世界'); // Çince
Pdf.CurrentPage.TextOut(72, 372, 0, '여보세요, Delphi PDF 세계!'); // Korece
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
begin
CreateHelloWorld('HelloWorld.pdf');
Writeln('Wrote HelloWorld.pdf');
end.

try/finally ... Free ile eşleştirilen THotPDF.Create(nil), sıradan Delphi sahiplik desenidir ve PDF üretmek bunu değiştirmez. Satırlar Y = 72'den aşağı doğru, 30 punto arayla yürür; bu da 14 puntoluk metne rahat bir satır arası bırakır. Çalıştırın, çalışma dizininde HelloWorld.pdf belirir: tek sayfa, sıkıştırılmış içerik, font alt küme olarak gömülü
Belge özellikleri BeginDoc'tan önceye ait
BeginDoc belgeyi başlatır ve ilk sayfasını oluşturur; dolayısıyla tüm dosyayı şekillendiren her şey ondan önce atanmalıdır. HotPDF bunu bazı özellikler için geleneklere bırakmak yerine zorlar. Compression'i BeginDoc'tan sonra atarsanız setter, Cannot set Compression value - document in progress. iletisiyle bir istisna fırlatır; AutoLaunch da aynı şekilde korunur. Gürültülü olmak burada iyidir. Tüm belge ayarlarını BeginDoc'un üstünde tek bir bloğa koyun; o iletiyi hiç görmezsiniz
İki varsayılan ikinci bir bakışı hak eder. Compression cmNone olarak başlar; ona hiç dokunmayan bir program, sıkıştırılmamış içerik akışları yazar. Bir metin sayfası için bu yalnızca israftır, yüzlerce sayfalık bir raporda ise dosya boyutunda herkesin ilk fark ettiği şeydir. AutoLaunch True olarak başlar; yani bir konsol aracı, EndDoc döner dönmez biten PDF'yi ilişkili görüntüleyicide açar. Masanızda bu hoştur; bir servisin, zamanlanmış bir işin ya da bir build agent'ın içinde yanlıştır. O ortamlar için kodda False yapın; kodu değiştiremediğiniz CI koşularında HOTPDF_SUPPRESS_AUTO_LAUNCH ortam değişkenini 1 yapmak da açmayı kapatır
Font işlemede tarafımız belli. FontEmbedding varsayılan olarak True'dur; böylece yüz dosyayla seyahat eder ve hiç Arial Unicode MS yüklenmemiş bir makinede de işlenir. EnableFontSubsetting ise varsayılan olarak kapalıdır, ki tam fontlar düzenleme iş akışları için kullanılabilir kalsın. Üretilmiş bir selamlama, fatura ya da rapor için alt kümelemeyi açın. Arial Unicode MS çok geniş bir yazı sistemi aralığını kapsar ve on bir kısa satır göstermek için bütün yüzü gömmek, dosyayı görülür bir fayda olmadan megabaytlarca büyütür. Bunu yalnızca birileri aşağı akışta metni düzenleyecekse ve sizin çizmediğiniz gliflere ihtiyaç duyacaksa açık bırakın
HotPDF sayfasında (0, 0) nerededir?
HotPDF sayfa koordinatlarını sol üst köşeden, Y aşağı doğru artacak şekilde ölçer; bir VCL TCanvas'ın kullandığı çerçevenin aynısı. Varsayılan Resolution 72'de bir birim bir puandır, 1/72 inç. PDF dosyasının kendisi koordinatları yine aşağıdan yukarı saklar; ISO 32000-1 §8.3.2.3 bunu gerektirir. HotPDF, içerik akışını yazarken geçirdiğiniz her Y'yi sayfa yüksekliğinden çıkararak çevirir
Açılış örneğinin arkasındaki aritmetik kısadır. BeginDoc ile AddPage'in oluşturduğu varsayılan sayfa A4'tür, 595'e 842 punto. Üstten bir inç oturması tasarlanan bir satır, HotPDF terimleriyle Y = 72, ham PDF terimleriyle y = 770'tir; çünkü 842 − 72 = 770. TextOut'a 770 geçirirseniz metin üstten 770 punto aşağı gider; bu da alt kenarın 72 punto üstüdür
Aynı çağrıda ikinci, daha küçük bir tuzak daha var. Varsayılan olarak geçtiğiniz Y metnin üst kenarıdır ve HotPDF, taban çizgisini yerleştirmeden önce metin yüksekliği kadar aşağı iner. GDI'den taşınan kod genellikle tam olarak bunu bekler. Başka bir PDF kütüphanesinden ya da kendi içerik akışı yazıcınızdan gelen kod ise genellikle Y'nin taban çizgisi olmasını bekler ve her satır, planlanandan bir metin yüksekliği aşağı çıkar. THPDFPage.TextFromBaseLine(True), geçerli sayfayı taban çizgisi konumlandırmasına geçirir:
// Aşağıdan yukarı akan bir kaynaktan gelen koordinatlar için köprü (bir PDF layout'u,
// bir şartname şeması, başka bir kütüphane). Yardımcı bu yazı için yazıldı,
// HotPDF'in parçası değil. Varsayılan Resolution 72'de geçerlidir
function FromBottomUp(Page: THPDFPage; PdfY: Single): Single;
begin
Result := Page.Height - PdfY;
end;
procedure DrawFromPdfCoordinates(Pdf: THotPDF);
begin
Pdf.CurrentPage.SetFont('Arial', [], 12);
// Y artık taban çizgisini adlandırır; PDF'in kendi metin işleçleri glifleri öyle yerleştirir
Pdf.CurrentPage.TextFromBaseLine(True);
// Alt kenarın 770 punto üstünde taban çizgisi; yani üstten Y = 72
Pdf.CurrentPage.TextOut(72, FromBottomUp(Pdf.CurrentPage, 770), 0,
'Baseline one inch below the top edge');
end;
Resolution, sayıların ne anlama geldiğini değiştiren diğer ayardır. THotPDF.Resolution'ı 96 yaparsanız X/Y koordinatları, kenar boşlukları ve TextWidth sonuçları 1/96 inç cinsinden ifade edilir; bu da yerleşim ekran pikselleriyle tasarlanmışsa kullanışlıdır. Yine de sayfa Width ve Height punto bildirmeye devam eder; dolayısıyla sayfa sınırlarını çizim koordinatlarıyla harmanlayan yerleşim kodu, X ve Y ile aynı birimlerde dönen CurrentPage.UserWidth ve CurrentPage.UserHeight'i okumalıdır. 72'de iki çift aynıdır. Milimetreyle düşünmeyi tercih ediyorsanız MeasurementUnit özelliği (varsayılan muPoints; muMM, muInches, muCentimeters, muTwips ve muPixels mevcut) daha temiz anahtardır. Program başına tek bir kural seçin. Asla üst üste bindirmeyin
İkinci sayfa neden 12 punto Arial ile basılır?
Çünkü her yeni sayfa bilinen bir durumdan başlar. THotPDF.AddPage yeni sayfayı geçerli yapar, onu A4 boyutlar ve üzerinde SetFont('Arial', [], 12) çağırır; boyutu, Resolution ne olursa olsun 12 puntoda tutar. BeginDoc da birinci sayfayı aynı yoldan oluşturur; Hello World'ün fontunu BeginDoc'tan hemen sonra, öncesinde değil, ayarlamasının nedeni budur. Çok sayfalı çıktı için sonucu gözden kaçırmak kolaydır: birinci sayfada çağırdığınız SetFont devralınmaz. İkinci sayfadaki Latin satırlar Arial'de yine iyi görünür, yalnızca daha küçüktür. CJK satırları ele verir; çünkü Arial'in onlar için glifi yoktur ve okuyucu boş kutular ya da hiçbir şey gösterir
Öngörülebilir bir başlangıç fontu, bir sayfa nesnesi için doğru tasarımdır: beşinci sayfanın çizim kodu, dördüncü sayfanın tesadüfen geride bıraktığına sessizce bağımlı kalmaz. Maliyeti, sayfa kurulumunun tekrarlanması gerektiğidir; onu tekrarlamanın en temiz yolu da ilk sayfa dâhil her sayfanın geçtiği tek bir prosedürdür:
uses
Winapi.Windows, Vcl.Graphics, HPDFDoc;
// Kendi yardımcınız: taze bir sayfanın neye ihtiyacı olduğunu bilen tek yer
procedure PreparePage(Pdf: THotPDF; IsFirst: Boolean);
begin
if not IsFirst then
Pdf.AddPage; // fontu Arial 12'ye sıfırlar
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 14, DEFAULT_CHARSET);
end;
procedure WriteGreetings(Pdf: THotPDF; Lines: array of string);
const
TopMargin = 72;
Leading = 30;
LinesPerPage = 20;
var
I, Row: Integer;
begin
PreparePage(Pdf, True); // sayfa 1, BeginDoc'tan sonra zaten var
Row := 0;
for I := 0 to High(Lines) do
begin
if Row = LinesPerPage then
begin
PreparePage(Pdf, False);
Row := 0;
end;
Pdf.CurrentPage.TextOut(72, TopMargin + Row * Leading, 0, Lines[I]);
Inc(Row);
end;
// Kalın bir başlık kendi SetFont'unu ister, sonra gövde fontu geri gelir
Pdf.AddPage;
Pdf.CurrentPage.SetFont('Arial Unicode MS', [fsBold], 18, DEFAULT_CHARSET);
Pdf.CurrentPage.TextOut(72, 72, 0, 'Appendix');
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 14, DEFAULT_CHARSET);
Pdf.CurrentPage.TextOut(72, 110, 0, 'Body text after the heading');
end;
Sayfalarınız ayrıca TextFromBaseLine ile taban çizgisi konumlandırmasına geçiyorsa o çağrıyı da fontun yanına PreparePage'e koyun. Sayfa başına her ayarı tek bir prosedürde tutmak; yeni bir gereksinimin, bir rengin ya da farklı bir boyutun bir kez eklenip her sayfaya ulaşması demektir
Bir font, birçok yazı sistemi ve sınırının nerede bittiği
Tek bir SetFont aynı sayfada Latin, Kiril, Japonca ve Çinceyi taşıyabilir; çünkü Arial Unicode MS çok geniş bir yazı sistemi aralığı için glifleri tek bir yüzde toplar. SetFont'un dördüncü bağımsız değişkeni Windows karakter setidir ve varsayılanı ANSI_CHARSET'tir; bu, font seçimini Batı kod sayfasına bağlar. DEFAULT_CHARSET (değer 1) geçirmek ise Windows'un yüzü ada göre seçmesine izin verir; çok dilli bir sayfanın istediği de tam olarak budur
Font, PDF'yi derleyen makinede bulunmalıdır. HotPDF, Windows adı hangi fonta çözümlerse onu gömer ve Arial Unicode MS eksikken Windows hiçbir şikayet olmadan başka bir yüzle değiştirir. Çıktı o zaman yedeği gömer ve o yüzün kapsamadığı yazı sistemlerindeki satırlar boş kutu olarak çıkar. Bunun tipik görüldüğü yer bir build server'dır; çünkü kimse oraya Office fontlarını kurmaz. Toplu bir çalışmaya güvenmeden önce yeni bir makinenin ürettiği ilk dosyanın gömülü font listesini kontrol edin
Tek bir yüz her dizeyi kapsamadığında TextOutWithFallback, TextOut ile aynı bağımsız değişkenleri alır, her karakter için bir font çözümler, her koşuyu onları işleyebilen yüzle çizer ve sonrasında özgün fontunuzu geri yükler. Arapça ve İbranice gibi sağdan sola yazı sistemleri glif kapsamından fazlasını ister: şekillendirme ve ters koşu sırası gerekir; bu da RtLTextOut fonksiyonunun alanıdır ve genellikle RegisterUnicodeTTF ile yüklenen bir TrueType dosyasıyla birlikte kullanılır
Buradan sonraki doğal adımlar, metnin boyutu, stili ve döndürmesi ile birkaç bloğun tek sayfaya kasıtlı yerleştirilmesidir; TextOut örneği bunları tek tek işler. Cetveller, kutular ve resimler aynı CurrentPage nesnesini ve aynı sol üst koordinatları kullanır; dolayısıyla kökenler ve sayfa başına kurulum hakkında yukarıda söylenenler onlar için de değişmeden geçerlidir
Bu Hello World kendi fontlarınıza karşı temiz çalıştıktan sonra, HotPDF Delphi Component sayfası şekiller ve resimlerden formlara kadar çizim API'sinin geri kalanını kapsar