Bir HotPDF belgesindeki her görünür dize tek bir çağrı aracılığıyla gelir: TextOut(X, Y, angle, Text). Hello World örneği bunu en sade haliyle kullanır, yazı tipi bir kez ayarlanır ve dört argüman makul varsayılanlarda bırakılır. O ilk sayfanın ötesinde, aynı dört argüman düzenin tüm yükünü taşır. Üçüncü argüman metin dizisini döndürür. Hemen öncesinde ayarlanan yazı tipi, boyut ve stile karar verir. Ve sayfanın köşesinden nokta (point) cinsinden ölçülen X, Y çifti; temiz bir rapor ile başkasının yazıcısında çakışan, kırpılan veya bir satır aşağı kayan bir metin arasında duran tek şeydir. İşte TextOut burada değerini kanıtlar ve varsayılanların yetersiz kaldığı yer burasıdır
Her şeyden önce imzayı akılda tutmakta fayda var: X ve Y nokta cinsinden Single, angle derece cinsinden Extended ve Text bir WideString'dir, böylece Unicode ayrı bir çağrıya gerek kalmadan doğrudan geçer. İkinci bir aşırı yükleme (overload), halihazırda glif kodlarını elinizde tuttuğunuz durumlar için bir PWORD ve bir uzunluk alır, ancak sıradan dizeler için kullanacağınız biçim WideString formudur
Boyut ve stil TextOut'tan değil, SetFont'tan gelir
TextOut'un bir boyut parametresi yoktur. Boyut, kalınlık, eğiklik; bunların tümü diziden önce gelen SetFont çağrısında yer alır ve bir sonraki SetFont onun yerini alana kadar yürürlükte kalır. İlk gün yaşanan karmaşanın çoğunu açıklayan tek gerçek budur: bir satır kalın (bold) çıkar, çünkü üç çağrı önce bir şey [fsBold] ayarlamıştır ve hiçbir şey onu temizlememiştir
Pdf.CurrentPage.SetFont('Times New Roman', [], 24);
Pdf.CurrentPage.TextOut(72, 740, 0, 'Quarterly Report'); // 24pt normal (regular)
Pdf.CurrentPage.SetFont('Times New Roman', [fsBold], 12);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Revenue'); // 12pt kalın (bold)
Pdf.CurrentPage.SetFont('Times New Roman', [fsItalic], 11);
Pdf.CurrentPage.TextOut(72, 694, 0, 'figures in thousands'); // 11pt italik
Pdf.CurrentPage.SetFont('Courier New', [fsBold, fsItalic], 10);
Pdf.CurrentPage.TextOut(72, 676, 0, ' +18.4% YoY'); // stiller birleşir
İkinci argüman bir TFontStyles kümesidir (set), bu nedenle [fsBold, fsItalic] kalın italik, [] ise düzdür (plain). Boyut, koordinatlarla aynı birim olan nokta cinsindendir, bu da dikey boşluklandırma (vertical spacing) üzerinde akıl yürütmeyi kolaylaştırır: 12 noktalı bir satır nefes almak için kabaca 14 ila 16 noktalı bir dikey adıma ihtiyaç duyar, bu nedenle Y değerini her satırda 14 düşürmek makul bir başlangıç satır aralığıdır (leading). Otomatik bir satır ilerlemesi (line advance) yoktur. Her bir taban çizgisini (baseline) kendiniz hesaplarsınız, bu bir paragraf için can sıkıcıdır ancak her alanın sabit bir koordinatta oturduğu bir form için kesindir
Yazı tipi adıyla ilgili iki pratik not. Derleme makinesinde yüklü yazı tiplerine karşı çözümlenir ve işletim sistemi ne döndürürse belgeye o gömülür, bu nedenle masaüstünüzde çözümlenen bir ad ile derleme sunucusunda çözümlenen bir adın aynı yazı tipi yüzü (face) olacağı garanti edilmez. Ayrıca yazı tipi dizedeki alfabeleri (scripts) kapsamalıdır. Yalnızca Latince içeren bir yazı tipi yüzü (face) altında bir Kiril veya CJK metin dizisi, hiçbir hata vermeden eksik glif (missing-glyph) kutuları olarak oluşturulur, bu da Hello World sayfasının dilleri karıştırdığında geniş bir Unicode yazı tipi yüzüne başvurmasının nedenidir
Açı (angle) argümanı, çapa (anchor) etrafında döndürür
Üçüncü argüman, çoğu kodun sonsuza kadar sıfırda bıraktığı argümandır. Sıfır olmayan bir değer iletin ve metin dizisi kendi (X, Y) çapası (metnin sol alt kısmı) etrafında saat yönünün tersine o kadar derece döner. Çapanın kendisi hareket etmez, bu nedenle yatay bir etiketi yerleştiren aynı koordinat, döndürülmüş ikizini de yerleştirir; sadece gliflerin ilerlediği yön değişir
Pdf.CurrentPage.SetFont('Arial', [fsBold], 11);
// Sol kenar boşluğunda dikey bir eksen etiketi: 90 derece aşağıdan yukarıya okunur.
Pdf.CurrentPage.TextOut(40, 300, 90, 'Units sold');
// Sayfa gövdesi boyunca çapraz bir TASLAK (DRAFT) filigranı.
Pdf.CurrentPage.SetFont('Arial', [fsBold], 60);
Pdf.CurrentPage.TextOut(150, 250, 45, 'DRAFT');
// Sütun başlıkları 60 derece eğildi, böylece uzun etiketler dar bir tabloya sığar.
Pdf.CurrentPage.SetFont('Arial', [], 9);
Pdf.CurrentPage.TextOut(120, 600, 60, 'Q1 actual');
Pdf.CurrentPage.TextOut(160, 600, 60, 'Q2 actual');
Doksan derece yaygın olan durumdur, bir grafiğin yan tarafında veya bir sırt başlığında uzanan bir etiket. Kırk beş derece, eğik sütun başlıklarını ele alır, geniş bir etiketin komşularına taşmadan dar bir sütun üzerinde oturmasını sağlayan numara. Döndürme çapanın nasıl yorumlandığını değiştirmez, ki bu da insanların yanıldığı yerdir: 90 derecelik bir metin dizisi hala (X, Y)'den başlar ve oradan yukarı doğru büyür, bu nedenle döndürülmüş bir etiketi ortalamak için açıyı değil, çapayı ayarlarsınız. Birkaç döndürülmüş dizi bir taban çizgisini paylaştığında, istiflenmiş yatay satırlar için Y'yi adımladığınız (step) gibi onlara aynı Y'yi verin ve X'i adımlayın
Tahmin etmeden koordinatları yerleştirme
Koordinatlar, incelemeden geçen veya sessizce başarısız olan kısımdır. HotPDF, sayfanın sol alt köşesinden, Y yukarı doğru büyüyerek ve inç başına 72 nokta (point) olacak şekilde ölçer. Bir US Letter sayfası 612'ye 792 noktadır; A4 595'e 842'dir. Letter üzerindeki bir inçlik üst kenar boşluğu (margin), ilk taban çizginizi üst kısımdaki küçük bir sayıya değil, Y = 792 eksi 72 eksi yazı tipi boyutu civarına yerleştirir. Y'nin sıfırdan aşağı doğru büyüdüğü ekran koordinatlarından gelen herkes, ilk satırı alt kenardan dışarı yazar ve on dakika boyunca nereye gittiğini merak eder
Düzeni (layout), sihirli sayılardan (magic numbers) oluşan bir sütun yerine adlandırılmış çapalara karşı yapılan bir aritmetik olarak ele alın. Bir sol kenar boşluğu, satır başına azalttığınız ilerleyen bir taban çizgisi (running baseline) ve sabit bir satır aralığı (leading), bir blok etiketi sabitlerden oluşan bir duvar yerine kısa bir döngüye dönüştürür:
const
LeftMargin = 72; // 1 inç içeride
TopBaseline = 720; // ilk satır, Letter üzerinde ~1 inç aşağıda
Leading = 16; // satırlar arasındaki dikey adım (step)
var
Y: Single;
Line: string;
begin
Pdf.CurrentPage.SetFont('Arial', [], 11);
Y := TopBaseline;
for Line in ReportLines do
begin
Pdf.CurrentPage.TextOut(LeftMargin, Y, 0, Line);
Y := Y - Leading;
if Y < 72 then // alt kenar boşluğuna ulaşıldı
begin
Pdf.AddPage;
Pdf.CurrentPage.SetFont('Arial', [], 11); // yazı tipi yeni bir sayfada sıfırlanır
Y := TopBaseline;
end;
end;
end;
Sayfa sonu (page-break) koruması, herkesin ilk unuttuğu ve gerçek kullanımda (in the field) en çok etkileyen satırdır. TextOut'un altında bir akış düzeni (flow layout) yoktur. Alt kenar boşluğunu geçecek şekilde azaltmaya devam ederseniz, metin hiçbir uyarı vermeden boşluğa, sayfanın dışına, hiçliğe doğru çizilmeye devam eder. Bu yüzden Y'yi kendiniz izlersiniz, tabanı geçtiğinde AddPage öğesini çağırır ve taban çizgisini sıfırlarsınız. AddPage'den sonraki SetFont isteğe bağlı bir dolgu değildir: mevcut yazı tipi bir sayfa sonundan sağ çıkmaz ve eğer atlarsanız yeni sayfadaki ilk metin dizisi görüntüleyicinin varsayılan yazı tipi yüzünde (face) çıkar
Sığdırma ve hizalama için karakter ve kelime boşlukları
Bazen bir dize doğrudur ancak genişliği yanlıştır: sabit bir çizgiyi (rule) kapsaması gereken bir başlık, daha havadar rakamlarla okunması gereken bir kod, hizalamak için değerlerinin itilmesi gereken bir sütun. PDF bunun için iki metin durumu (text-state) operatörü taşır, karakter boşluğu (Tc, her gliften sonra eklenen fazladan boşluk) ve kelime boşluğu (Tw, her boşluk karakterinde eklenen fazladan boşluk) ve her ikisi de ölçeklenmemiş metin-boşluğu (text-space) birimleriyle, etkin olarak mevcut yazı tipi boyutundaki noktalarla (points) ifade edilir. Bunlar TextOut'a argüman değil, durumdur (state), bu yüzden onları ayarlar, çizer ve geri ayarlarsınız
// Kısa bir başlığı, bir çizgi (rule) boyunca uzanacak şekilde harf boşluklandırması (letter-space) yapın.
Pdf.CurrentPage.SetCharacterSpacing(4);
Pdf.CurrentPage.SetFont('Arial', [fsBold], 14);
Pdf.CurrentPage.TextOut(72, 740, 0, 'S U M M A R Y');
Pdf.CurrentPage.SetCharacterSpacing(0); // normal gövde metninden önce sıfırlayın
// Tek ve geniş bir satırda kelimeler arasındaki boşlukları açın.
Pdf.CurrentPage.SetWordSpacing(6);
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Name Department Extension');
Pdf.CurrentPage.SetWordSpacing(0);
Kelime boşluğu yalnızca boşluk karakterine (kod 32) etki eder, ki bunun bilmeye değer bir sonucu vardır: ASCII boşlukları olmayan bir CJK dizisi içinde hiçbir şey yapmaz ve baytlar (bytes) yerine glif indeksleri olarak kodlanmış metinle tuhaf bir şekilde etkileşime girer. Latince tablo çıktısı için, dizeyi yeniden yazmadan boşlukları genişletmenin ucuz yoludur. Karakter boşluğu, hedef bir genişliğe ulaşması gereken bir başlık için daha iyi bir araçtır, çünkü ayarlamayı boşluklarda toplamak yerine her bir glif üzerine eşit olarak dağıtır
Sıfırlama (reset) tüm disiplindir. Boşluk (spacing), tıpkı yazı tipi gibi, sayfanın çizim durumunun (drawing state) bir parçasıdır ve durum siz onu değiştirene kadar devam eder. Bir başlığa harf boşluğu uygulayıp (letter-space) onu sıfırlamayı unutursanız, aşağıdaki her paragraf bu uzatmayı miras alır; bu da sıradan bir düzeltici okumadan sağ çıkıp dikkatli olanında başarısız olan ince, yerini belirlemesi zor bir yanlışlık olarak okunur. Güvenilir alışkanlık, bir boşluk değeri ayarlamak, buna ihtiyaç duyan diziyi çizmek ve bir sonraki satırda onu tekrar sıfıra ayarlamaktır, böylece daha sonraki hiçbir kod daha önceki bir bölümün ne yaptığını bilmek zorunda kalmaz
Çıktıyı gerçekten bozulduğu yerde kontrol etme
Metin düzeni ilk makinede değil ikinci makinede başarısız olur, bu nedenle önemli olan kontroller masanızdan uzakta gerçekleşir. Oluşturulan dosyayı, geliştirici yazı tipi setinizin yüklü olmadığı bir sistemde açın ve kolay karakterleri rastgele kontrol etmek yerine aksanlı Latince, Latince olmayan herhangi bir alfabe (script) ve noktalama işaretleri de dahil olmak üzere gömülü yüzlerin (faces) hala tek geçişte oluşturulduğunu onaylayın. Arama veya çıkarma işlemi söz konusu olduğu anda önem kazanan, metnin ana hatlar (outlines) değil gerçek metin olduğunu doğrulamak için birkaç satırı seçin ve kopyalayın. Düzene (layout) temsili veriler besleyin, düzenli bir yer tutucu (placeholder) değil; en uzun Almanca etiket ve en geniş sayı gibi. Çünkü bir alana taşan dize her zaman elle yazmadığınız dizedir. Ve eğer sayfa önceden basılmış bir forma inecekse, bir örneği yazdırın veya rasterleştirin ve orijinaline karşı yerleştirin; çeyrek milimetrelik bir taban çizgisi (baseline) kayması ekranda görünmezdir ancak kağıt üzerinde barizdir
Henüz tek bir sayfa bile yazmadıysanız, belgeyi, yazı tipini ve yukarıdaki her şeyin bağlı olduğu sol alt koordinat sistemini ayarlayan HotPDF Hello World örneği ile başlayın. Burada gösterilen TextOut, SetFont ve boşluk çağrıları, Delphi ve C++Builder için olan HotPDF Bileşeninin (HotPDF Component) bir parçasıdır