Terminal için Glyph Protocol'e Giriş
(rapha.land)- Terminal uygulamalarında özel simgeleri render edebilmek için yamalanmış fontların (Nerd Font vb.) kurulmasını gerektiren mevcut sorunu çözmek amacıyla yeni bir terminal protokolü ortaya çıktı
- Glyph Protocol, uygulamaların çalışma anında vektör glifleri doğrudan terminale kaydetmesine ve belirli codepoint'lerin render edilip edilemeyeceğini sorgulamasına olanak tanıyan bir yapı sunuyor
- Glif verisi TrueType'ın
glyfformatını kullanıyor; böylece terminalin zaten sahip olduğu rasterizer aynen kullanılabiliyor ve yeni bir bağımlılık eklemeden uygulanabiliyor - Kayıt yapılacak codepoint'leri Unicode Private Use Area (PUA) ile sınırlayarak phishing ve görsel sahtecilik saldırıları en baştan engelliyor
- İlk uygulama Rio terminal üzerinde geliştiriliyor; Bubble Tea, Ratatui, Ink gibi başlıca TUI framework'leri için örnek kodlar da yayımlanmış durumda
Mevcut sorun: yamalı font bağımlılığı
- Terminal editörleri, prompt'lar ve TUI'ların simgeleri düzgün gösterebilmesi için kullanıcıların Nerd Font veya Powerline gibi yamalı fontları elle kurması gerekiyor
- Font kurulmadığında simge yerinde tofu (□) görüntüleniyor; ayrıca yamalı fontlar tek tek 6–12MB civarında büyük dosyalar
- JetBrainsMono Nerd Font Regular yaklaşık 7.8MB, FiraCode Nerd Font Regular yaklaşık 10.4MB, tüm sembol arşivi ise yaklaşık 60MB
- Uygulama geliştiricilerinin istedikleri glifleri doğrudan dağıtma yolu yok; bu yüzden kullanıcıların doğru fonta, sürüme ve codepoint eşlemesine sahip olmasını ummak zorunda kalıyorlar
Glyph Protocol'ün temel işlevleri
- İki temel işlem destekleniyor
- Özel glif kaydı: Uygulama bir Unicode PUA codepoint'i seçip vektör outline'ı doğrudan terminale göndererek çalışma anında kaydediyor
- Codepoint sorgulama: Belirli bir codepoint'in sistem fontu tarafından mı, oturum içi kayıt tarafından mı, ikisi tarafından da mı, yoksa hiçbiri tarafından mı kapsandığı sorgulanabiliyor
- Kullanıcının sisteminde Nerd Font zaten kuruluysa sorgu üzerinden glif gönderimi atlanabiliyor; kurulu değilse de uygulama outline'ı kendisi göndererek simgenin doğru görünmesini sağlayabiliyor
Protokol yapısı
Taşıma yöntemi (Transport)
- OSC yerine APC (Application Program Command) kullanılıyor
- APC, uygulama tanımlı komutlar için tasarlanmış; uygulanmamış terminaller bu diziyi güvenli biçimde yok sayabiliyor
- OSC, komut tanımlayıcısı olarak tek bir ondalık tamsayı kullanan küresel namespace'i paylaştığından çakışma riski taşıyor; APC'de ise kendi tanımlama yapısı bulunduğu için bu sorun yok
Tanımlayıcı (Identifier)
- Tüm Glyph Protocol mesajları
25a1(U+25A1, WHITE SQUARE) codepoint'i ile önekleniyor- Bu karakter, glif olmadığında terminalin çizdiği tofu'nun standart sembolü
- Framing biçimi:
ESC _ 25a1 ; <verb> [ ; key=value ]* [ ; <payload> ] ESC \\ - 4 verb var:
s(support),q(query),r(register),c(clear)
Support (s): terminal desteğini kontrol etme
- Terminalin hangi payload formatlarını ve protokol sürümünü desteklediğini kontrol etmek için kullanılıyor
- Aynı zamanda Glyph Protocol'ün varlığını tespit etmenin standart yolu
- Yanıttaki
fmt, her bitin bir payload formatını temsil ettiği bir bitfield1=glyf: TrueType basit glif, v1'de zorunlu2=colrv0: katmanlı düz renkli glif (OpenType COLR v0), v1.2'de eklendi4=colrv1: gradient ve transform içeren tam paint graph (OpenType COLR v1), v1.2'de eklendi
- Yanıt gelirse protokol desteği doğrulanmış olur; timeout olursa desteklenmiyor demektir;
fmt=0ise protokol uygulanmış ama format desteği yoktur (tamlık için tanımlanmış durum)
Query (q): codepoint render edilebilir mi sorgusu
- Belirli bir codepoint'in render edilip edilemeyeceği sorgulanır ve
statusdeğeriyle yanıt alınır0(free): hiçbir şey render edilmez, tofu gösterilir1(system): sistem fontu kapsıyor2(glossary): oturum içi kayıt kapsıyor3(both): ikisi de kapsıyor; kayıt, render sırasında sistem fontunun üzerine yazıyor
- TUI, sistemde ilgili simge zaten varsa kaydı atlayabilir; yoksa özel bir codepoint kaydedip zarif fallback sağlayabilir
Register (r): glif kaydı
- Uygulama bir PUA codepoint'i seçip base64 ile kodlanmış
glyfoutline'ını göndererek kayıt yapıyor - Başlıca parametreler
cp: hedef codepoint (hex), mutlaka 3 Unicode PUA aralığından biri içinde olmalı (U+E000–U+F8FF,U+F0000–U+FFFFD,U+100000–U+10FFFD); aralık dışındaysareason=out_of_namespaceile reddediliyorfmt: payload formatı; v1'de yalnızcaglyftanımlı ve varsayılan olduğu için çoğu durumda yazılmayabilirupm: units per em, outline koordinat uzayını tanımlar; varsayılan değer 1000
- Aynı
cpiçin ikinci kezrgönderilirse önceki kayıt ezilir - Hata durumunda (PUA dışı codepoint, bozuk payload, composite glif vb.)
status=<nonzero>; reason=<code>ile yanıt verilir
Neden glyf formatı seçildi?
Neden vektör?
- Glifler fotoğraf değildir; bu yüzden sabit bir çözünürlükleri yoktur: aynı simgenin hem 12px yoğun TUI'da hem de 24px HiDPI ekranda render edilmesi gerekir
- Raster glifler belirli bir çözünürlüğe sabitlenir; bu da HiDPI'da bulanıklık veya küçük hücrelerde okunamazlık yaratır
Özellikle neden glyf?
- Metin render eden tüm terminallerde zaten
glyfrasterizer'ı bağlıdır (FreeType, swash, ttf-parser, fontdue, allsorts vb.) - Glyph Protocol benimsendiğinde terminal tarafına hiçbir yeni bağımlılık eklenmez
- SVG tercih edilseydi
resvgeklemek ya da yeni bir XML+path parser yazmak gerekirdi - Wire boyutu da küçüktür: tipik bir simge 150–400 bayt
glyfverisiyle taşınabilir; bu da eşdeğer SVG'ye göre 2–3 kat daha küçüktür (base64 overhead dahil)- 50 simge kaydında yaklaşık 13KB yerine 35KB fark oluşur; bu özellikle tmux pipe'larında veya mobil SSH bağlantılarında hissedilebilir
glyf için kısa açıklama
- Bir
glyfkaydı, glifi kapalı contour kümeleri olarak saklar - Her nokta için on-curve veya off-curve şeklinde 1 bit metadata bulunur
- art arda iki on-curve nokta → düz çizgi
- iki on-curve nokta arasında bir off-curve nokta → ikinci dereceden Bézier eğrisi
- art arda iki off-curve nokta → aradaki orta noktada örtük bir on-curve nokta vardır (sıkıştırma hilesi)
- Koordinatlar EM karesi içindeki tamsayı grid konumlarıdır;
upm=1000iken(500, 900)yarım genişlik ve %90 yükseklik anlamına gelir - Kapalı bir üçgen yaklaşık 30 bayt, 30 noktalı bir simge ise yaklaşık 200 bayttır
Protokolün tanımladığı glyf alt kümesi
- Yalnızca basit gliflere izin verilir: composite glifler, başka gliflere referanslar ve font düzeyi bağlamlar yoktur
- OpenType spesifikasyonunda tanımlanan standart flag encoding kullanılır
- Hinting komutları yoktur: hinting, tüm fonta ait kontrol değerleri setini varsayar; burada böyle bir bağlam bulunmaz
- Koordinat uzayı
upmile tanımlanır; varsayılan 1000'dir ve kayıt başına değiştirilebilir
Renk, ölçekleme ve üretim
glyfoutline'ları renk bilgisi taşımaz ve mevcut foreground color ile render edilir; bu, Nerd Font mirası kullanım senaryosuyla aynıdır- Renkli glifler ayrı payload formatları olan
fmt=colrv0/fmt=colrv1ile desteklenir upmdeğeri glif koordinat uzayını tanımlar; terminal bunu render sırasında hücreye eşler → font boyutu değiştiğinde yeniden kayıt gerekmez- Çoğu geliştirici
glyfbaytlarını elle yazmayacak; bunun yerine SVG'den build time'da dönüştürecek:fonttoolsiçindekittx/pensarayüzleri kullanılabilir,svg2glyfyardımcı aracı da Rio referans implementasyonuyla birlikte dağıtılacak
Yaşam süresi ve kapasite
- Her terminal oturumu, 3 PUA aralığındaki codepoint'lerle anahtarlanan ve aynı anda en fazla 1024 kayıt tutabilen bir glossary barındırır
- Kayıtlar oturum sürdüğü sürece geçerlidir
-
- glif kaydedildiğinde FIFO sırasıyla en eski kayıt çıkarılır → "glossary full" hatası yoktur
- Sessiz çıkarma kabul edilemeyen uygulamalar, çıktı vermeden önce ilgili codepoint'i sorgulamalıdır
Gerçek örnek: boş bir PUA'ya simge kaydetmek
U+100000'e (Supplementary PUA-B içindeki ilk codepoint) stilize bir outline kaydeden tam pipeline örneği veriliyor- SVG→
glyfdönüştürücüsü olarakfontToolskullanılıyor TTGlyphPenile outline çizildikten sonrabase64ile kodlanıp APC dizisi olarak gönderiliyor, ardından ilgili codepoint yazdırılıyor- Tipik 20 noktalı bir simgenin
glyfpayload'ı yaklaşık 150 bayt, APC sarmalama vebase64dahil toplam yaklaşık 250 bayt - SVG varlıkları olan geliştiriciler için
svg2glyfyardımcı aracı sunulacak → kayıt işlemi 2 satırda tamamlanabilecek
Toplu kayıt için seçenek: reply=
- Varsayılan olarak terminal her
riçin bir ACK yanıtı gönderir; ancak 100 glif kaydedilen bir başlangıç hook'unda PTY üzerinden kuyruğa giren 100 ACK'nin shell'de çöp olarak görünmesi sorunu ortaya çıkar - 3 aşamalı kontrol
reply=1(varsayılan): başarı ve hata için yanıt verir; etkileşimli tekil kayıtlar için uygundurreply=2: yalnızca hatalarda yanıt verir; başarılar sessizdir, toplu kayıtta sadece hataları izlemek için kullanılırreply=0: hiç yanıt yoktur; fire-and-forget kullanımına uygundur, örneğin başlangıç hook'u gibi yanıt okuyacak tarafın bulunmadığı durumlarda
- Bilinmeyen değerler otomatik olarak
reply=1'e fallback eder; böylece gelecekteki genişlemelerde geriye dönük uyumluluk korunur
Clear (c): kaydı kaldırma
- Editör kapanırken terminal varsayılanlarını geri yüklemek, TUI temasını değiştirmek veya debug için kullanılır
- Tek bir slot'u temizleme:
cpparametresiyle belirli bir codepoint seçilir - Tüm glossary'yi temizleme:
cpbelirtilmez - Boş bir slot'u temizlemek hata sayılmaz; no-op olarak
status=0yanıtı döner cpPUA aralığında olmalıdır; aralık dışındaysareason=out_of_namespacedöner
v1'e bilinçli olarak dahil edilmeyen özellikler
- PUA dışı codepoint kaydı yok: yalnızca 3 Unicode PUA aralığına izin verilir
- Ligature yok: kayıt yalnızca tek bir codepoint'e uygulanır; dizisel tuş yer değiştirmeleri v1 kapsamı dışındadır, programlama ligature'leri (
->→⟶) zaten OpenType fontları tarafından işlenir - Oturumlar arası kalıcılık yok: glifler her çalıştırmada yeniden gönderilir; böylece terminal bir font cache'e dönüşmez
- Uygulamalar arası paylaşım yok: her terminal oturumu kendi glossary'sine sahiptir; IPC veya daemon yoktur
- v1
glyfpayload'ında renkli glif yok: foreground color ile render edilir; renk desteği v1.2'decolrv0/colrv1olarak ayrılmıştır - Bu özellikler gerekirse daha sonra eklenebilir; ancak bir kez eklendikten sonra kolayca kaldırılamayacakları için bilerek dışarıda bırakılmışlardır
PUA kısıtlamasının güvenlik gerekçesi
- PUA kısıtlaması API estetiği değil, protokol varsayılan olarak etkin olsa bile güvenli kalmasını sağlayan bir özelliktir
- Rastgele codepoint kaydına izin verilirse
U+0061(a) üzerineoşeklinde bir glif kaydedilipbad.com,bod.comgibi gösterilebilir- Hücre tamponu hâlâ
bad.comolarak kalır; dolayısıyla kopyala-yapıştır sırasında baytlar doğru olur ama kullanıcının gördüğü şey yalandır - Böylece tüm terminal programlarına bir phishing primitive kazandırılmış olur ve etkisi aynı oturumda daha sonra çalışacak programlara da sürer
- Hücre tamponu hâlâ
- PUA ile sınırlandığında bu saldırı türü mekanik olarak imkânsız hâle gelir: kullanıcılar PUA codepoint'lerini yazmaz; dosya adlarında, URL'lerde, komutlarda, değişken adlarında veya loglarda PUA codepoint'leri bulunmaz
- Nerd Font'ın teamül hâline getirdiği güven modeli (özel glifler yalnızca ayrılmış aralıklarda bulunur, gerçek metnin üstüne yazılamaz) protokol düzeyinde zorunlu kılınır
- Ek güvenlik özellikleri
- Hücre tamponu otoritatiftir: seçim, kopyalama, arama, hyperlink algılama, shell history vb. işlemler uygulamanın yazdırdığı codepoint'leri döndürmelidir; böylece “görünenle kopyalananın farklı olduğu” tuzaklar üretilemez
- Oturum izolasyonu: iki sekme
U+E0A0üzerine birbirinden farklı branch simgeleri bağımsız biçimde kaydedebilir; bir sekmedeki kayıt diğer sekmenin render sonucunu etkileyemez
Mevcut yaklaşımlarla karşılaştırma
Kitty Image Protocol (KIP) + Unicode Placeholders
- KIP'in Unicode placeholder mekanizmasıyla Glyph Protocol yaklaşık olarak uygulanabilir; ancak entegrasyon zordur ve placeholder desteği olan terminaller yalnızca Kitty, Ghostty ve Rio'dur
- KIP bir görüntü protokolüdür; glif ise görüntü değildir
- Kullanım başına maliyet: ekranda 200 kez yeniden kullanılan bir glif için (tablo kenarlıkları, bullet marker'lar vb.) 200 görüntü referansı yerleştirmek gerekir ve bu yerleşimle birleştirme maliyeti doğurur. Glyph Protocol'de ise codepoint bir kez kaydedildikten sonra font hızında render edilir
- Doğal çözünürlük yok:
glyfoutline'larında piksel boyutu bulunmaz; font boyutu değişince otomatik uyum sağlar. KIP ise belirli boyutta bitmap gönderdiği için boyut değişince bulanıklaşır veya yeniden yükleme gerekir; ayrıca font boyutu değişimini algılayacak bir mekanizma yoktur - Foreground color mirası: tek renkli
glyfoutline'ları hücrenin mevcut foreground color'ı ile render edildiği için tema otomatik uygulanır. Görüntüler kendi piksellerine sahip olduğundan metin renklendirmesine katılmaz
DEC DECDLD / DRCS
- VT220'nin 1983'te sunduğu Dynamically Redefinable Character Sets, biçim olarak Glyph Protocol'e benzer
- Ancak iki temel sorunu var
- Bitmap tabanlıdır: terminalin o anki hücre boyutuna uygun piksel grid'i yüklenir; bu yüzden font boyutu değiştiğinde, HiDPI'ya geçildiğinde veya 4K monitöre taşındığında blok pikseller büyür ya da küçülür. Sabit 10×20 CRT dönemi için tasarlanmıştır ve günümüzün değişken hücre boyutlarına uygun değildir
- Namespace kısıtı yoktur: DECDLD, GL aralığına (a, b, c gibi karakterlerin bulunduğu alan) eşlenebilen karakter kümelerini ezebilir; yani güvenilmeyen bir program
akarakterinin render'ını yeniden tanımlayabilir → modern terminallerin DECDLD'yi etkinleştirmekte isteksiz olmasının başlıca sebebi budur
Rio terminalindeki uygulama durumu
- Glyph Protocol, Rio terminal'in main branch'inde şimdiden kullanılabiliyor ve mayıs içinde resmen dahil edilmesi planlanıyor → ilk implementasyon
- Tam spesifikasyon sürümle birlikte yayımlanacak; glif kaydı ve terminal sorgusu için örnek kodlar da içerecek
- Çalışan örnekler raphamorim/glyph-protocol-examples deposunda görülebiliyor: Bubble Tea, Ratatui ve Ink için örnek entegrasyonlar mevcut
- Protokol hâlâ güncellenebilir; daha fazla uygulama ve terminal katıldıkça mesaj biçimleri, sorgu yanıtları ve edge case'ler değişebilir → bugün bunun üzerine build edenlerin hareketli hedef gibi ele alması ve implementasyon sürümünü sabitlemesi öneriliyor
- Diğer terminal emülatörlerinin de bunu benimsemesi umuluyor; çünkü tüm ekosistem için faydası büyük, implementasyon kapsamı ise bilinçli olarak küçük tutulmuş
Topluluğa açık sorular
- Font boyutu değişikliği bildirimi protokol kapsamına girmeli mi?: Glyph Protocol'ün kendisi outline'ların çözünürlükten bağımsız olması sayesinde bu sorunu aşsa da görüntü ve glifi birlikte kullanan TUI'lar için hücre metriklerinin değiştiğini polling dışında öğrenmenin bir yolu yok →
resizeveyametrics-changedbildiriminin kapsam içinde mi dışında mı olması gerektiği tartışılıyor - PUA dışı kayda izin veren sorumlu bir yöntem var mı?: Yalnızca PUA kuralı varsayılan güvenliği sağlıyor; ama kapsanmayan Han karakterleri için glif gönderen CJK input method'lar veya glif override etmek isteyen dil araçları gibi kullanım senaryolarını da kapatıyor → açık phishing riskini geri getirmeden bunu mümkün kılacak açık kullanıcı seviyesinde opt-in, imzalı yetenekler veya güvenilir kaynak işaretleri gibi yaklaşımlar hakkında görüş isteniyor
Henüz yorum yok.