PDF'de değişken yazı tipi kavramı yoktur. Bir PDF dosyasına gömülen yazı tipi, sabit metriklere sahip sabit bir anahat kümesidir, bu yüzden bir değişken yazı tipinin belgeye girebilmesi için önce tek bir statik örneğe indirgenmesi gerekir. HotPDF bu örneklemeyi (instancing) dahili olarak gerçekleştirir: değişken bir yazı tipinin eksenlerini incelersiniz, 620 ağırlık veya 87,5 genişlik gibi koordinatlar seçersiniz ve kütüphane bu değerleri, uyumlu herhangi bir PDF okuyucunun render edebileceği eksiksiz, kendi kendine yeten bir yazı tipi programına işler
Bunun önemi kuramsal değil pratiktir. Yazı tipi dökümhaneleri giderek düzine kadar statik ağırlık yerine tek bir değişken dosya sunuyor ve tasarım ekipleri, hiçbir adlandırılmış örneğin sağlamadığı değerleri seçiyor. Örnekleme olmadan, bir rapor üretici ya tasarım kararını çöpe atan varsayılan örneğe geri döner ya da tüm değişken yazı tipini gömer ve görüntüleyicinin, bilmesinin hiçbir yolu olmayan eksen koordinatlarına uymasını umar — ki hiçbir okuyucunun bunu yapması zorunlu değildir
Örnekleme gerçekte neyi yeniden oluşturmak zorundadır?
Bir OpenType değişken yazı tipi, her glif için bir varsayılan anahat artı tasarım uzayındaki konuma göre indekslenmiş bir dizi delta saklar. Bir eksen koordinatını uygulamak, bir başlığa sayı yazmak değildir; bu, gvar tablosunda gezinmek, istenen konum için deltaları enterpolasyon yapmak, noktaları taşımak ve ardından bu noktalardan türetilen her şeyi yeniden hesaplamak anlamına gelir. HotPDF; glif anahatlarını, uzun loca tablosunu, eksiksiz yatay ve dikey metrikleri, genel yazı tipi sınırlayıcı kutusunu (bounding box) ve sfnt sağlama toplamı (checksum) düzeltmesini yeniden oluşturur
Neyin kaldırıldığı da bir o kadar önemlidir. Statik bir örnek fvar, avar, gvar, HVAR, VVAR, MVAR, STAT veya cvar'ı elinde tutmamalıdır ve imzalanmış baytlar artık var olmadığından eskimiş bir DSIG de gitmelidir. Bunlardan herhangi birini geride bırakmak, zaten taşınmış anahatlar taşırken kendini değişken olarak tanıtan bir yazı tipi üretir ve varyasyonları gerçekten uygulayan okuyucular bunları bir kez daha uygular
Hayalet noktalar ve çifte uygulama tuzağı
Tüm süreçteki en incelikli kural metriklerle ilgilidir. gvar'da, bir glif için nokta sayısı; anahat noktalarını veya bileşik bir glif için bileşen noktalarını, artı sol yan payını (left side bearing), ilerleme genişliğini (advance width) ve bunların dikey karşılıklarını kodlayan dört hayalet noktayı kapsar. Bu hayalet noktaların kendisi de deltalara tabidir
Bu yüzden bir yazı tipinin gvar tablosu olduğunda, HotPDF yatay ve dikey metrikleri enterpolasyonu yapılmış hayalet noktalardan türetir ve ayrıca HVAR veya VVAR uygulamaz. İkisini birden eklemek klasik hatadır: aynı varyasyon iki kez uygulanır ve her ilerleme genişliği biraz fazla geniş çıkar, bu da satır sonuna doğru giderek sağa kayan bir metin olarak kendini gösterir. Kütüphane, metrik varyasyon deposunu doğrudan hmtx veya vmtx'e yalnızca bir yazı tipinin gvar'ı olmadığında işler
İki ek ayrıntı geometriyi doğru tutar. Hayalet noktalar hiçbir zaman kontur enterpolasyonuna katılmaz, bu yüzden basit bir glif için açıkça listelenmemiş noktalar, hayalet noktalar hariç tutularak kontur başına IUP ile çıkarsanır. Bileşik glifler ise deltalarını XY parametreleri kullanan bileşen ofsetlerine uygular, ardından alt sınırlar özyinelemeli olarak yeniden hesaplanır. Bu özyineleme derinlik açısından sınırlıdır ve döngü denetiminden geçer, çünkü kötü niyetli veya yalnızca bozuk bir bileşen grafiği aksi halde sonsuz özyinelemeye girebilir
Seçim yapmadan önce tasarım uzayını incelemek
Herhangi bir örnekleme iş akışındaki ilk çağrı, dökümhanenin tanımladığı eksenleri ve adlandırılmış örnekleri bildiren InspectVariableFont'tur. Eksen kayıtları dört baytlık etiketi, minimum, varsayılan ve maksimum değerleri, bayrakları ve bir ad kimliğini (name ID) taşır; adlandırılmış örnekler ise bir alt aile ad kimliğini, bayrakları, isteğe bağlı bir PostScript ad kimliğini ve eksen başına bir koordinatı taşır:
var
Pdf: THotPDF;
Axes: THPDFVariableFontAxisArray;
Instances: THPDFVariableFontNamedInstanceArray;
I: Integer;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.InspectVariableFont('C:\Fonts\Inter.ttf', Axes, Instances) then
begin
for I := 0 to High(Axes) do
Writeln(Format('%s min=%.1f default=%.1f max=%.1f',
[string(Axes[I].Tag), Axes[I].MinimumValue,
Axes[I].DefaultValue, Axes[I].MaximumValue]));
Writeln(Format('%d named instance(s) defined', [Length(Instances)]));
end
else
Writeln('not a variable font - embed it as an ordinary TrueType face');
finally
Pdf.Free;
end;
end;
Eksen aralığını bildirmek önemlidir, çünkü eksen değerleri UI'nizin sunduğu aralığa değil, yazı tipinin bildirdiği aralığa göre sınırlandırılır (clamp). wght ekseni 900'de duran bir yazı tipinde kullanıcının 1000 ağırlık istemesine izin veren bir kaydırıcı, sessizce yazı tipi katmanında değil arayüzde düzeltilmelidir, aksi halde basılan çıktı önizlemeyle uyuşmayacaktır
Koordinatları seçmek ve belgeyi üretmek
Eksen seçimi durumsaldır (stateful) ve sonrasında kaydedilen yazı tiplerine uygulanır. SetVariableFontAxis, dört baytlık yazdırılabilir bir ASCII etiketi ve sonlu bir değer alır; başka her şeyi sessizce yok saymak yerine bir istisna ile reddeder. ClearVariableFontAxes seçimi sıfırlar ve GetVariableFontAxisSelections o an bekleyen şeyi bildirir; bu, birden çok kod yolunun aynı belge nesnesine dokunmuş olabileceği rapor motorlarında günlüğe kaydetmeye değer bir bilgidir. Ailenin kendisi, gömülü diğer herhangi bir TrueType yüzü gibi SetFont üzerinden ada göre seçilir:
begin
Pdf := THotPDF.Create(nil);
try
Pdf.BeginDoc;
Pdf.SetVariableFontAxis('wght', 620); // yarı kalın (semibold), adlandırılmış bir örnek değil
Pdf.SetVariableFontAxis('wdth', 87.5); // hafifçe dar (condensed)
Pdf.CurrentPage.SetFont('Inter', [], 11);
Pdf.CurrentPage.TextOut(72, 720, 0, 'Quarterly results');
Pdf.ClearVariableFontAxes; // varsayılan örneğe geri dön
Pdf.CurrentPage.SetFont('Inter', [], 10);
Pdf.CurrentPage.TextOut(72, 700, 0, 'Prepared by the finance team');
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
OnVariableFontInstance olayı her örnek üretildiğinde tetiklenir ve kullanılan eksen değerlerini bildirir; bu, belirli bir PDF'nin gerçekte neler içerdiğini bir günlükte kanıtlamanın en ucuz yoludur. Her farklı koordinat kümesi farklı bir yazı tipi programı ürettiğinden, eksen seçimlerini yazı tipi önbellek anahtarınızın bir parçası olarak ele alın; önbellekleme mekaniği kalıcı yazı tipi alt kümesi önbelleği yazısında anlatılmıştır
Örnekleme, alt kümeleme ve şekillendirmeyle nasıl etkileşir?
Örnekleme, alt kümelemeden (subsetting) önce çalışır ve bu sıralama doğrudur. Örneklenmiş yazı tipi sıradan bir statik TrueType yüzüdür, bu yüzden olağan alt kümeleyici onu başka herhangi biri gibi ele alır: glif kapanışını (closure) hesaplar, belgenin gerçekten kullandığı glifleri tutar ve geri kalanını atar. Farkında olunması gereken etkileşim, aynı ailenin iki farklı eksen seçiminin iki farklı yazı tipi programı olduğudur; bu yüzden ağırlık 400 ile ağırlık 620'yi karıştıran bir belge, iki örnekli tek bir paylaşılan yüz değil, iki ayrı alt küme gömer
Şekillendirme (shaping) ilke olarak etkilenmez, ama pratikte kontrol etmeye değer. Yerleşim özellikleri GSUB ve GPOS içinde yaşar ve örnekleme bunları korur, bu yüzden bitişik harfler (ligature) ve biçemsel alternatifler OpenType GSUB biçemsel alternatifleri yazısında anlatıldığı gibi çalışmaya devam eder. Değişen şey konumlandırmadır: dar (condensed) bir örneğin ilerlemeleri varsayılandan daha dardır, bu yüzden metni örneklemeden önce ölçen herhangi bir yerleşim yanlış genişlikleri ölçmüş olur. Render edeceğiniz eksen seçimiyle aynı seçimle ölçün, tutarsızlık ortadan kalkar
Uygulamadan gelen, bu yolu genişletecek herkes için işe yarayacak son bir savunma amaçlı not. Dikey metrikleri olmayan yazı tipleri bile Delphi çağrı noktasında dinamik dizi bağımsız değişkenlerini yine de değerlendirir, bu yüzden ayrıştırma zamanı (parse-time) dizileri, boş bir indeksi atlamak için bir HasVerticalMetrics denetimine güvenmek yerine her zaman ayrılır (allocate). Bu, görünüşte korumalı bir dalı, tam olarak test etmediğiniz yazı tiplerinde bir erişim ihlaline (access violation) çeviren türden bir dil düzeyi ayrıntısıdır
Değişken yazı tipi desteği, gömme, alt kümeleme ve glif kapanışıyla aynı yazı tipi işlem hattına (pipeline) oturur; bu, yazı tipi alt kümesi kapanışı ve şekillendirilmiş glifler yazısında daha derinlemesine anlatılmıştır. Delphi ve C++Builder için tam tipografi özellik seti HotPDF Delphi PDF bileşeni sayfasında listelenmiştir