Bir PDF'teki eksik glif bir hata değildir. Üretici, seçili fontun eşleyemediği bir karakter ister; font glif indeksi sıfır döndürür ve ortaya çıkan dosya yapısal olarak geçerlidir, her yerde açılır ve bir adın ya da bir tutarın olması gereken yerde boş bir kutu gösterir. Üreten hatta kimse fark etmez. Alıcı eder. HotPDF o döngüyü TrackUnresolvedGlyphs ile kapatır: açın, metin çizme yolu glif araması indeks sıfıra çözülen her kod noktasını kaydeder ve her benzersiz bulgu için bir kez OnUnresolvedGlyph tetikler; kod noktasıyla, başarısız olduğu fontla, ait olduğu yazı sistemiyle ve onu kapsayacak font önerisiyle
Yakalama cevabın yarısıdır. Diğer yarısı SetFontFallbackChain'dir; yazı sistemi başına sıralı bir font listesi kaydeder, böylece olağan durumlar kendiliğinden çözülür ve yalnızca gerçek boşluklar işleyicinize ulaşır. Birlikte, eskiden müşterilerce bildirilen bir hata sınıfını derleme zamanı bir denetime dönüştürürler
Eksik bir glif neden hiçbir şey tetiklemez?
Çünkü ISO 32000, üreticiye kapsamı doğrulama yükümlülüğü yüklemez ve glif indeksi sıfır meşru bir gliftir. O, .notdef'tir; dış çizgisini font tasarımcısı seçer: genellikle boş ya da içi boş bir dikdörtgen, bazen hiçbir şey. Onu çizen bir görüntüleyici doğru davranır. Metin çıkarma hatta doğru karakterleri döndürebilir, çünkü /ToUnicode eşlemesi dış çizgilerden değil kaynak metinden yazılır; dolayısıyla otomatik bir gidiş dönüş denetimi, görünür metninde delikler olan bir belgeyi memnun biçimde geçer
Pratik sonuç şudur: kapsam, çizim anında denetlenmelidir; kitaplığın hangi kod noktasının istendiğini ve fontun gerçekte hangi glifi sunduğunu hâlâ bildiği anda. Sonrasında bilgi gitmiştir
Yakalayıcı aygıt bağlamını değil alt küme durumunu izlemeli
İlk uygulamanın yanlış gittiği yer burasıdır ve nedeni anlamaya değer; çünkü bir metin hattına vida edilmiş her kapsam denetimi için geçerlidir. HotPDF'in iki metin yolu vardır. Biri, kayıt zamanında kurulan bellek içi bir karakter haritasıyla kayıtlı bir Unicode TrueType font üzerinden yayar. Diğeri, her karakter dizisi için yeni bir aygıt bağlamı ve font tanıtıcısı oluşturan eski bir GDI yoludur
Kapsamı GDI yolundan yargılamak umutsuzdur. Onun eşlemesi, yayılan içerik akışına düşen eşleme değildir ve ikisi eşzamanlı değildir; dolayısıyla GDI sonuçlarını okuyan bir yakalayıcı, yazdırılabilir ASCII aralığının tamamını çözülmemiş raporlar. Yetkili cevap kayıtlı fontta yaşar: RegisterUnicodeTTF çözümlemesinin yaptığıve GetUnicodeGlyphForCodepoint üzerinden sorgulanan karakter haritası. Yakalayıcı bu nedenle alt kümeye hazır durumda kapılanır, herhangi bir GDI koşulunda değil ve hiç Unicode font kaydetmemiş belgelerde hiç çalışmaz; bu doğrudur, çünkü o belgeler zaten standart kodlamalarla sınırlıdır
Bir ikinci tuzak onun yanı başında oturur. Bir fontun GDI aile adı ile kayıt sırasında font ikilisinden çıkarılan PostScript adı farklı dizelerdir ve normalleştirebileceğiniz bir şekilde değil: Arial Unicode MS adlı bir aile, PostScript adı olarak ArialMT taşır. "Şu anda seçili font kaydettiğimiz font mu" diye yazılıp adla karşılaştırılan her kapı, hiç tetiklenmeyen ölü koddur. Durumda kapı koyun, asla font adlarında değil
Bir glif yakalayıcısını emojiyle test etmeyin
Bariz test durumu gülümseyen bir yüzdür ve size yakalayıcının bozuk olduğunu ikna edecektir. Astral düzlemlerdeki yaygın emoji kod noktaları, onları doğrudan bir glif indeksine eşleyen özel kullanım sentezi bir yoldan çözülür; dolayısıyla genel kapsam dalına hiç ulaşmazlar. Yakalayıcı doğru davranıyor ve test yanlış yolu ölçüyor
Bunun yerine atanmamış bir kod noktası kullanın. U+0378, Unicode'da kalıcı olarak ayrılmamıştır; dolayısıyla hiçbir font onu meşru biçimde eşleyemez ve tam olarak doğrulamak istediğiniz dalı çalıştırır. "Özellik bozuk" ile "test, özelliği atlayan bir girdi seçti" ayrımı gerçek saatlere mal olur ve atanmamış kod noktaları bundan kaçınmanın en ucuz yoludur
type
TCoverageAudit = class
private
FFindings: TStringList;
public
procedure Handle(Sender: TObject;
const Info: THPDFUnresolvedGlyphInfo);
property Findings: TStringList read FFindings;
end;
procedure TCoverageAudit.Handle(Sender: TObject;
const Info: THPDFUnresolvedGlyphInfo);
begin
// Her benzersiz kod noktası için bir kez tetiklenir, her geçtiği yerde değil
FFindings.Add(Format('U+%.4X missing in %s (script %d), try: %s',
[Info.CodePoint, String(Info.FontName), Ord(Info.Script),
String(Info.SuggestedFonts)]));
end;
// Üreten bir işe bağlamak
Pdf := THotPDF.Create(nil);
try
Pdf.TrackUnresolvedGlyphs := True;
Pdf.OnUnresolvedGlyph := Audit.Handle;
Pdf.RegisterUnicodeTTF('C:\Windows\Fonts\arial.ttf');
Pdf.BeginDoc;
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(50, 720, 0, CustomerName);
Pdf.EndDoc;
if Audit.Findings.Count > 0 then
// Kutulu bir sayfa göndermek yerine işi düşürün
raise Exception.Create(Audit.Findings.Text);
finally
Pdf.Free;
end;
Yedek zincirleri font başına değil yazı sistemi başınadır
Yedeğin kaynak fonta göre değil yazı sistemine göre kapsanmasının nedeni, kapsam boşluklarının yazı sistemine göre kümelenmesidir. Bir Latince metin fontu Devanagari, Tayca, Han ve emojilerin tamamından yoksundur ve her birinin yerine geçen farklı bir fonttur. Yazı sistemi başına tek zincir beyan etmek bu nedenle gerçek dağıtımı betimler: gövde metni için bir Latin fontu, bir CJK fontu, bir emoji fontu, bir hepsini kapsayan
// THPDFFontScript şunları kapsar: hfsCommon, hfsLatin, hfsGreek,
// hfsCyrillic, hfsHebrew, hfsArabic, hfsIndic, hfsSoutheastAsian,
// hfsCJK, hfsKana, hfsHangul, hfsEmoji ve hfsOther
Pdf.SetFontFallbackChain(hfsCJK,
['Microsoft YaHei', 'SimSun', 'Yu Gothic']);
Pdf.SetFontFallbackChain(hfsArabic, ['Segoe UI', 'Arial']);
Pdf.SetFontFallbackChain(hfsEmoji, ['Segoe UI Emoji']);
Pdf.SetFontFallbackChain(hfsOther, ['Arial Unicode MS']);
Yedek ile yakalama alternatif değil, birbirini tamamlar. Zincirler öngördüğünüz kapsamı ele alır; yakalayıcı öngörmediğinizi bildirir ve keyfi müşteri verisi işleyen bir sistemde ilginç yarısı odur. Font ikamesinin metrikleri değiştirdiğini unutmayın; dolayısıyla yedeğe düşen bir paragraf yeniden akabilir. Sayfa düzeni önemliyse ikame edilen fontun kapanış ve alt kümeleme davranışını font alt küme kapanışı makalesinde okumaya değer; yeniden sıralama ya da birleştirme gerektiren yazı sistemleri ise karmaşık yazı sistemi metin şekillendirmede anlatılan şekillendirme aşaması tarafından ele alınır
Mevcut yolu riske atmadan davranış sonradan nasıl eklenir
Aynı sürüm, çift aralığı için eski bir kern tablosu yedeği ekledi ve kapsanma biçimi kopyalanmaya değer bir desendir. Kerning mantığına yeni bir karar noktası eklemek yerine yedek, GPOS tablosu olmayan fontlar için zaten var olan erken çıkış dalına asıldı. GPOS'lu modern bir font ona hiç ulaşmaz; dolayısıyla davranışı testle değil kurguyla değişmez kalır. Unicode font kaydetmeyen yollar iki sıfır ofset üretir; onlar da değişmez kalır
Olgun bir çizim kitaplığında düşük riskli bir sonradan ekleme genel biçimi budur: şu anda hiçbir şey üretmeyen dalı bulun ve yeni davranışı oraya koyun. Bu, "bir şeyi gerilettiğimize inanmıyoruz" ifadesini "bu hiçbir şeyi geriletemezdi" ifadesine çevirir; başkalarının faturalarının geçtiği bir metin motoru hakkında söylenebilecek çok daha iyisi budur
Onu günlük değil kapı yapın
Kapsam bulguları yalnızca bir şey onlarda başarısız oluyorsa faydalıdır. Belge üreten bir hizmette verimli düzen, geceleyin çalıştırılan gerileme işinde izlemeyi gerçek müşteri adları, adresler ve ürün betimlemelerinden oluşan bir derlem üzerinde açık tutmak ve herhangi bir bulguda işi düşürmektir. Olay her geçtiği yerde değil her benzersiz kod noktasında bir kez tetiklendiği için çıktı, bütün bir yazı sistemi eksik olsa bile okunacak kadar küçük kalır
Üretimde aynı işleyici telemetri olarak daha iyi kullanılır: kod noktasını ve fontu kaydedin, belgeyi sunmaya devam edin ve birikimin, dağıtım font kümesine sıradaki hangi yazı sisteminin ekleneceğini size söylemesine izin verin. Gömülü ve ikame fontlar için çizim davranışı gömülü font gliflerinin çiziminde ayrıca kapsanır ve TrackUnresolvedGlyphs dahil özellik listesinin tamamı HotPDF Delphi PDF component ürün sayfasında belgelenir