Tipografi: yazı tipi kaydı, alt küme oluşturma, CMap, kodlama ve BiDi
Bir bakışta
“Bir bakışta” başlıklı bölümTipografi modülü, bir yazı tipi dosyasını ve bir Unicode dizgesini Portable Document Format (PDF) içerik akışının gerektirdiği baytlara dönüştürür. Yazı tipi ayrıştırmayı, işlem ömrü boyunca geçerli kaydı, glif alt kümesi oluşturmayı, ToUnicode CMap çıktısını, cmap’e duyarlı kodlama stratejilerini ve Unicode çift yönlü motorunu yönetir.
Kurulum
“Kurulum” başlıklı bölümcomposer require nextpdf/core:^3Kavramsal genel bakış
“Kavramsal genel bakış” başlıklı bölümFontRegistry, yazı tiplerini bir işlemin ömrü boyunca saklar ve FontRegistryInterface arayüzünü uygular. Bir TrueType, OpenType, TrueType Collection (TTC) veya Type 1 dosyasını (Printer Font Binary (PFB) ve Adobe Font Metrics (AFM)) bir kez ayrıştırır ve değişmez bir FontInfo döndürür. Uzun süre çalışan iş parçacıklarında şöyle kullanın: yazı tipi kümesini başlatma sırasında ısıtın, ardından lock() çağırın. Bundan sonra kayıt, aramalar trafiğe hizmet vermeyi sürdürürken her değişikliği reddeder. Yalnızca saf PHP verisi tutar: ayrıştırılmış meta veriler ve ham yazı tipi baytları. Bir iş parçacığı havuzu tek bir örneği paylaşabilir. registerFromBinary() ham yazı tipi baytlarını kabul eder; HyperText Markup Language (HTML) @font-face köprüsü bunları uzak bir kaynaktan veya bir veri URI’sinden alınan bir yazı tipi için kullanır.
Motor, kullandığı her yazı tipini gömer ve alt kümesini oluşturur. Gömülü yazı tipi programı PDF’nin içinde taşınır; bu sayede belge her görüntüleyicide aynı şekilde işlenir ve kurulu sistem yazı tiplerine bağlı kalmaz — ISO 32000-2 §9. Bir alt küme yalnızca belgenin başvurduğu glifleri içerir; bu da Çince, Japonca ve Korece (CJK) veya Unicode açısından zengin içerik için önemlidir — ISO 32000-2 §9. FontSubsetter, özgün tablo dizinini ayrıştırır, cmap’i çıkarır, bileşik glif bağımlılıklarını geçişli bir kapanış olarak çözümler ve head, hhea, maxp, cmap, loca, glyf ve hmtx tablolarını yeniden oluşturur. Özgün glif tanımlayıcı numaralandırmasını korur ve kullanılmayan yuvaları sıfırlarla doldurur; böylece bir CIDToGIDMap, /Identity türündeyken geçerli kalır. Alt küme yüzde ondan az tasarruf sağlayacaksa, kendini amorti etmeyen işlemden kaçınarak özgün yazı tipini değiştirmeden döndürür. CffSubsetter, bir Compact Font Format dış hat tablosu taşıyan OpenType yazı tipleri için aynı işlemi gerçekleştirir.
Metin üretimi üç gösterim arasında çeviri yapar: Unicode kod noktası, içerik akışındaki karakter kodu ve yazı tipinin içindeki glif tanımlayıcısı. Modül bu yolu açık biçimde korur. FontInfo::encodeText() cephedir; FontEncodingStrategyResolver yazı tipine göre yönlendirme yapar. Unicode cmap’e sahip gömülü bir TrueType veya OpenType yazı tipi, iki baytlık bir Identity-H onaltılık akış üreten TrueTypeCmapStrategy stratejisine yönlendirilir. Bu, Identity-H CMap’li ve CIDFontType2 alt türünde bir Type 0 yazı tipinin gerektirdiği biçimdir (ISO 32000-2 §9.7.4; ilgili retrieval-augmented generation (RAG) parça özeti lisans sınırı nedeniyle kesik döndürüldü ve _downgraded-claims-o3.md dosyasına kaydedildi). Diğer her yazı tipi — Base 14 standart yazı tipleri, Type 1 PFB ve AFM — tek baytlık bir WinAnsi düz değer dizgesi üreten Base14EncodingStrategy stratejisine yönlendirilir. Bu akış, tam WinAnsiEncoding (Windows kod sayfası 1252) repertuvarını kapsar — aksanlı Latin, Euro işareti ve yaygın tipografik noktalama. Bunun dışındaki kod noktaları tek baytlık akıştan çıkarılır ve kapsayan bir yazı tipi kaydedildiğinde küme başına yazı tipi yedeklemesine girer (ISO 32000-2 Annex D.2). Çözümleyici, tüm FontInfo değer uzayını kapsar; null döndürebilen bir yol yoktur. ToUnicodeCMapBuilder, bir okuyucunun Identity-H yazı tipinden özgün Unicode’u geri kazanmasını sağlayan /ToUnicode kaynağını oluşturur. Açgözlü bfrange birleştirmesi ve 100 girişlik bir blok sınırı uygular.
BidiEngine, Unicode Standard Annex #9 (UAX #9), Unicode 16 ile tanımlanan Unicode Çift Yönlü Algoritması’nın sınır hizmetidir. İzolat desteği kapalıyken, mevcut çağıranların aynı davranışı görmesi için eski çözümleyiciye devreder. İzolat desteği açıkken, izolata duyarlı işlem hattını çalıştırır: derinliği en fazla 125 olan açık izolat yığını, zayıf tür geçişleri, eşli parantez çözümlemesi dahil olmak üzere nötr tür geçişleri ve örtük düzey ile satır yeniden sıralama geçişleri. Aday bir yazı tipi için CJK glif kapsamı ayrı bir tanılamadır: CjkFontValidator, betik başına gerekli Unicode bloklarını örnekler ve bir kapsam yüzdesi raporlar.
API yüzeyi
“API yüzeyi” başlıklı bölüm| Tür | Çeşit | Temel üyeler | Kararlılık | Beri |
|---|---|---|---|---|
FontRegistry | final sınıf | register(), registerType1(), registerFromBinary(), registerFromDirectory(), get(), has(), all(), warmup(), lock(), isLocked(), memoryUsage() | kararlı | 1.7.0 |
FontInfo | final readonly sınıf | $family, $type, $widths, $unicodeMap, $cmapForward, getKey(), encodeText() | kararlı | 1.0.0 |
FontSubsetter | final sınıf | subset(string, array<int>, int): string | kararlı | 1.0.0 |
CffSubsetter | final sınıf | OpenType/CFF dış hat alt kümesi oluşturma | kararlı | 1.0.0 |
FontEncodingStrategyResolver | final sınıf | resolve(FontInfo): FontEncodingStrategy | kararlı | 2.7.0 |
ToUnicodeCMapBuilder | final sınıf | buildFromRun(), buildFromMap(), encodeUnicodeUtf16Be() | kararlı | 2.7.0 |
BidiEngine | final sınıf | UAX #9 izolata duyarlı çözümleme | kararlı | 3.1.0 |
CjkFontValidator | final sınıf | validateCoverage(), detectScript(), isCjkCodepoint() | kararlı | 1.0.0 |
FontInfo değişmezdir: kurucu imzası ve genel özellikleri dondurulmuştur. Kodlama stratejileri (FontInfo, UTF-8 text) değerlerinin saf fonksiyonlarıdır: aynı girdi her çağrıda aynı EncodedGlyphRun sonucunu döndürür.
Kod örneği — hızlı başlangıç
“Kod örneği — hızlı başlangıç” başlıklı bölüm<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Typography\Encoding\EncodingMode;use NextPDF\Typography\FontRegistry;
$registry = new FontRegistry();$cjkFont = $registry->register('/path/to/NotoSansTC-Regular.ttf', alias: 'NotoSansTC');
$encoded = $cjkFont->encodeText('PDF 2.0 引擎 — 使用 CMap 編碼');
// An embedded CJK TrueType face resolves to the two-byte Identity-H path.assert($encoded->mode === EncodingMode::TwoByteCid);register() yazı tipini bir kez ayrıştırır ve değişmez bir FontInfo döndürür. encodeText() çözümleyici üzerinden yönlendirir ve bayt akışını, PDF dizge işlenenini, glif başına ilerleme genişliklerini ve glif tanımlayıcısı (GID)‘den Unicode’a haritayı taşıyan bir EncodedGlyphRun döndürür; bu haritayı bir /ToUnicode CMap kullanır.
Kod örneği — üretim
“Kod örneği — üretim” başlıklı bölüm<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Exception\NextPdfException;use NextPDF\Typography\FontRegistry;use Psr\Log\LoggerInterface;
final readonly class FontBootstrap{ public function __construct( private FontRegistry $registry, private LoggerInterface $logger, ) {}
/** * Warm a font set at worker boot, then lock the registry for the * lifetime of the process. * * @param list<string> $fontFiles Absolute paths to font files. */ public function boot(array $fontFiles): void { try { $this->registry->warmup($fontFiles); $this->registry->lock(); } catch (NextPdfException $e) { $this->logger->error('Font warmup failed', ['error' => $e->getMessage()]);
throw $e; }
$report = $this->registry->memoryUsage(); $this->logger->info('Font cache primed', [ 'fonts' => $report->entryCount, 'bytes' => $report->currentBytes, ]); }}warmup() çağrısının ardından lock() çağrısı, iş parçacığı başlatma dizisidir. lock() çağrısından sonra her değişiklik girişimi hata fırlatır ve aramalar trafiğe hizmet vermeyi sürdürür. memoryUsage() bir MemoryReport döndürür; böylece bir iş parçacığı yazı tipi önbelleğini bütçesine göre izleyebilir.
Uç durumlar & tuzaklar
“Uç durumlar & tuzaklar” başlıklı bölüm- Kayıt kilitliyken
register(),registerFromBinary(),addFontDirectory()vewarmup()çağrılarını reddeder. Başlatma sırasında ısıtın ve kilitleyin; istek işleme sırasında asla kayıt yapmayın. FontSubsetter::subset(), tasarruf yüzde onun altında kalacaksa veya temel bir tablo eksikse özgün baytları değiştirmeden döndürür. Girdiyle aynı olan döndürülmüş yazı tipi, belgelenmiş kazanç sağlamayan yoldur; hata değildir.- Alt küme oluşturucu, özgün glif tanımlayıcı numaralandırmasını korur ve kullanılmayan glifleri sıfırlarla doldurur. Bu,
CIDToGIDMap /Identityöğesini geçerli tutar; glif tanımlayıcılarının bitişik bir aralığa yeniden numaralandırıldığını varsaymayın. registerFromBinary(), baytları ayrıştırmak için geçici bir dosyaya yazar ve hem uzantı dosyasını hem detempnam()taban dosyasını birfinallybloğunda siler. Güvenilmeyen yazı tipi verisi bir ayrıştırma saldırısı yüzeyidir; ayrıştırıcıya ulaşmadan önce bir kabul denetiminden geçirin (Güvenlik notlarına bakın).BidiEngine, izolat desteği kapalıyken eski çözümleyiciye birebir devreder. İzolat biçimlendirme karakterleri bu durumda sınır-nötr olarak geçer. Tam UAX #9 davranışı için izolat desteğini uygunluk ilkesi üzerinden açın.CjkFontValidator, her kod noktasını test etmek yerine kod noktalarını bir adımla örnekler; bu nedenle kapsam değeri istatistiksel olarak yeterli bir tahmindir, eksiksiz bir sayım değildir.
Performans
“Performans” başlıklı bölümİlk kullanımda yazı tipi ayrıştırma baskındır; kayıt bu maliyeti işlem başına bir kez olacak şekilde amorti eder. Isıtmadan sonra get() ve has() O(1) harita aramalarıdır. Alt küme oluşturma maliyeti, yazı tipinin tam glif tablosuyla değil, belgenin kullandığı glif sayısıyla ölçeklenir. Alt küme oluşturmanın CJK içeriği için hem boyutu hem de hızı iyileştirmesinin nedeni budur: alt küme oluşturucu, 20,000 üzerinde glife sahip yazı tiplerini ikili arama, önceden ayrılmış arabellekler ve toplu dizge işlemleri aracılığıyla işler. Bileşik glif çözümlemesi sınırlıdır; döngüsel bileşen başvurularına karşı korunmak için 100 kapanış yinelemesiyle sınırlandırılır. cmap Format 12 ayrıştırıcısı, düşmanca yazı tipi girdisi için bellek kullanımını sınırlamak amacıyla grup ve giriş sayılarını sınırlar. 1500 ms duvar süresi ve 64 MB tepe bellek değerinden oluşan performance_budget, tipik bir yazı tipi ısıtmasını ve belge işlemeyi kapsar.
Güvenlik notları
“Güvenlik notları” başlıklı bölümGüvenlik açısından iki yüzey önemlidir. Birincisi yazı tipi girdisidir. register() ve registerFromBinary() rastgele baytları ayrıştırır. registerFromBinary() geçici bir dosya oluşturur. Sınır katmanı, yollardaki akış sarmalayıcılarını ve null baytları reddeder. Güvenilmeyen yazı tipi verisi, ayrıştırıcıya ulaşmadan önce dosya boyutunu ve glif sayısını sınırlayan bir dış kaynak ilkesinden geçmelidir. Alt küme oluşturucunun ikili okuyucuları her ofseti sınır denetiminden geçirir. cmap ayrıştırıcıları grup, giriş ve tablo sayılarını sınırlar (Format 12’de numGroups > 31000 ve 200,000 girişlik bir sınır); böylece hazırlanmış bir yazı tipi sınırsız ayırmaya yol açamaz. İkinci yüzey metin geri kazanımıdır: ToUnicodeCMapBuilder, her karakter kodunun 16 bitlik kod uzayının içinde ve her Unicode değerinin geçerli bir skaler olduğunu doğrular. Vekil yarımları reddeder; böylece bozuk bir harita, hatalı bir çıkarma kaynağı üretemez. Dışarıdan sağlanan herhangi bir yazı tipini veya metni güvenilmeyen olarak ele alın.
Uygunluk
“Uygunluk” başlıklı bölüm| İddia | Standart | Madde | Kanıt |
|---|---|---|---|
| Belgenin kullandığı her yazı tipi gömülüdür; böylece belge, sistem yazı tiplerine güvenmeden işlenir. | ISO 32000-2 | §9 | |
| Gömülü yazı tipinin, belgenin başvurduğu gliflere göre alt kümesi oluşturulur. | ISO 32000-2 | §9 | |
Gömülü bir CJK TrueType yüzü, Identity-H CMap’li ve CIDFontType2 alt türlü bir Type 0 yazı tipi olarak üretilir. | ISO 32000-2 | §9.7.4 | RAG özeti lisans sınırı nedeniyle kesik; ön ek 7a5258772f508e3b, bkz. _downgraded-claims-o3.md |
İlk iki madde başka sözcüklerle ifade edilmiş ve özetle sabitlenmiştir. Üçüncü maddenin tam RAG özeti döndürülmedi (lisans sınırı kesintisi); ADR-013 ve cmap kodlayıcı geliştirici genel bakışı bunu doğrular ve düşürülmüş olarak kaydedilmiştir. NextPDF normatif metni yeniden üretmez. CJK içeriği için PDF/A-4 ve PDF/UA-2 uygunluğu, orada izlenen yazıcı tarafı alt küme oluşturma ve /ToUnicode bağlantısına dayanır.
Ticari bağlam
“Ticari bağlam” başlıklı bölümTicari bir OpenType özellik paketi ve premium yazı tipi yedekleme zincirleri, Core kayıt ve kodlama katmanı üzerine inşa edilir. Core tipografi modülü her yazı tipini lisanssız olarak gömer, alt kümesini oluşturur ve kodlar; ücretli paket, derlenmiş yedekleme çözümlemesi ekler. Dönüşüm bağlantısının atlanması kasıtlıdır: bu sayfa belgelemedir, bir satış yolu değildir.
Ayrıca bakınız
“Ayrıca bakınız” başlıklı bölüm- Font: TrueType, OpenType ve CID kaydı — yazı tipi değer türleri, gömme ve yedekleme.
- Text: şekillendirme, satır sonu, BiDi — kodlanmış glifleri tüketen koşu işleme ve şekillendirme.
- Contracts / Typography —
FontRegistryInterfaceve metin ön işlemci sözleşmeleri. - HTML işleme motoru —
@font-faceköprüsü;registerFromBinary()çağrısını yapar.