Yerel yazı tipleriyle gelişmiş yazı biçimi kullanma

Local Font Access API'nin, kullanıcının yerel olarak yüklenen yazı tiplerine erişmenize ve bunlarla ilgili alt düzey ayrıntıları öğrenmenize nasıl olanak sağladığını öğrenin

Web'de kullanıma uygun yazı tipleri

Web geliştirme konusunda uzun süredir çalışıyorsanız web'de kullanılabilen yazı tipleri olarak bilinenleri hatırlayabilirsiniz. Bu yazı tiplerinin, en çok kullanılan işletim sistemlerinin (Windows, macOS, en yaygın Linux dağıtımları, Android ve iOS) neredeyse tüm sürümlerinde kullanılabildiği bilinmektedir. 2000'lerin başlarında Microsoft, Web için TrueType temel yazı tipleri adlı bir girişime öncülük etti. Bu girişim, bu yazı tiplerini belirten bir web sitesini her ziyaret ettiğinizde sayfaları site tasarımcısının amaçladığı şekilde göreceğiniz hedefiyle bu yazı tiplerini ücretsiz olarak indirmenizi sağlıyordu. Evet, Comic Sans MS yazı tipiyle ayarlanmış siteler de bu kapsamdadır. Klasik bir web'de kullanıma uygun yazı tipi grubu (sans-serif yazı tipinin nihai yedeğiyle birlikte) aşağıdaki gibi görünebilir:

body {
 
font-family: Helvetica, Arial, sans-serif;
}

Web yazı tipleri

Web'de kullanılabilen yazı tiplerinin gerçekten önemli olduğu günler çoktan geride kaldı. Bugün, web yazı tipleri sunuyoruz. Bunlardan bazıları değişken yazı tipleridir. Hatta gösterilen çeşitli eksenlerin değerlerini değiştirerek daha fazla düzenleme yapabiliriz. CSS'nin başında, indirilecek yazı tipi dosyalarını belirten bir @font-face bloğu tanımlayarak web yazı tiplerini kullanabilirsiniz:

@font-face {
 
font-family: 'FlamboyantSansSerif';
 
src: url('flamboyant.woff2');
}

Ardından, normalde olduğu gibi font-family değerini belirterek özel web yazı tipini kullanabilirsiniz:

body {
 
font-family: 'FlamboyantSansSerif';
}

Parmak izi vektörü olarak yerel yazı tipleri

Çoğu web yazı tipi de web'den gelir. Ancak ilginç bir bilgi de @font-face bildirimindeki src özelliğinin, url() işlevinden ayrı olarak local() işlevini de kabul etmesidir. Bu sayede özel yazı tipleri yerel olarak yüklenebilir. Kullanıcının işletim sisteminde FlamboyantSansSerif yüklüyse indirilmek yerine yerel kopya kullanılır:

@font-face {
 
font-family: 'FlamboyantSansSerif';
 
src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}

Bu yaklaşım, bant genişliğinden tasarruf sağlama potansiyeli olan güzel bir yedek mekanizması sağlar. İnternette maalesef her şey yolunda gitmez. local() işlevinin sorunu, tarayıcı parmak izi için kötüye kullanılabilmesidir. Böylece, bir kullanıcının yüklediği yazı tipleri listesi oldukça açıklayıcı olabilir. Pek çok şirket, çalışanların dizüstü bilgisayarlarına yüklenen kendi kurumsal yazı tiplerine sahiptir. Örneğin, Google'ın Google Sans adında kurumsal bir yazı tipi vardır.

Google Sans yazı tipinin önizlemesini gösteren macOS Font Book uygulaması.
Bir Google çalışanının dizüstü bilgisayarına yüklenen Google Sans yazı tipi.

Saldırganlar, Google Sans gibi çok sayıda bilinen kurumsal yazı tipinin varlığını test ederek kullanıcının hangi şirkette çalıştığını belirlemeye çalışabilir. Saldırgan, bu yazı tiplerinde ayarlanmış metni bir kanvasta oluşturmaya ve glifleri ölçmeye çalışır. Glifler, kurumsal yazı tipinin bilinen şekliyle eşleşirse saldırgan isabet elde eder. Simgeler eşleşmiyorsa saldırgan, kurumsal yazı tipi yüklenmediği için varsayılan bir değişim yazı tipinin kullanıldığını bilir. Bu ve diğer tarayıcı parmak izi saldırılarıyla ilgili tüm ayrıntılar için Laperdix ve arkadaşları tarafından yazılan araştırma makalesini okuyun.

Şirket yazı tiplerini birbirinden farklı kılan, sadece yüklenen yazı tiplerinin listesi bile tanımlanabilir. Bu saldırı vektörüyle ilgili durum o kadar kötüye gitti ki kısa süre önce WebKit ekibi "kullanıcı tarafından yerel olarak yüklenen yazı tiplerini değil, yalnızca web yazı tiplerini ve işletim sistemiyle birlikte gelen yazı tiplerini [kullanılabilir yazı tipleri listesine] dahil etmeye karar verdi. (Ve şimdi buradayım, yerel yazı tiplerine erişim vermeyle ilgili bir makaleyle.)

Yerel Yazı Tipi Erişimi API'si

Bu makalenin başlangıcı sizi olumsuz bir ruh haline sokmuş olabilir. Gerçekten güzel şeylere sahip olamaz mıyız? Üzülmeyin. Bunu yapabileceğimizi düşünüyoruz ve her şeyin umutsuz olmadığını umuyoruz. Ancak önce, aklınızdan geçen bir soruyu yanıtlayayım.

Web yazı tipleri varken neden Yerel Yazı Tipi Erişimi API'sine ihtiyacımız var?

Profesyonel kalitede tasarım ve grafik araçlarını web'de sunmak geçmişte zordu. Tasarımcıların yerel olarak yüklediği profesyonelce oluşturulmuş ve ipucu verilmiş yazı tiplerinin tamamına erişip bunları kullanamama sorunuyla karşılaşıyorduk. Web yazı tipleri bazı yayınlama kullanım alanlarını destekler ancak rasterleştiriciler tarafından glif ana hatlarını oluşturmak için kullanılan vektör glif şekillerine ve yazı tipi tablolarına programatik erişim sağlamaz. Benzer şekilde, bir web yazı tipinin ikili verilerine erişmek de mümkün değildir.

  • Tasarım araçlarının kendi OpenType düzeni uygulamalarını gerçekleştirmek ve tasarım araçlarının, karakter şekillerinde vektör filtreleri veya dönüştürme işlemleri gibi işlemler için daha düşük seviyelerde bağlantı kurmasına izin vermek üzere yazı tipi baytlarına erişmesi gerekir.
  • Geliştiricilerin, web'e taşıdıkları uygulamaları için eski yazı tipi grupları olabilir. Bu yığınları kullanmak için genellikle yazı tipi verilerine doğrudan erişim gerekir. Ancak web yazı tipleri bu özelliği sunmaz.
  • Bazı yazı tipleri web üzerinden yayınlanmak için lisanslı olmayabilir. Örneğin, Linotype'ın bazı yazı tipleri için yalnızca masaüstü kullanımını kapsayan bir lisansı vardır.

Yerel Yazı Tipi Erişimi API'si, bu zorlukların üstesinden gelmek için geliştirilmiştir. İki bölümden oluşur:

  • Kullanıcıların mevcut sistem yazı tiplerinin tamamına erişim izni vermesini sağlayan bir yazı tipi numaralandırma API'si.
  • Her bir listeleme sonucunda, yazı tipi verilerinin tamamını içeren düşük düzey (bayt odaklı) SFNT kapsayıcı erişimi isteğinde bulunma olanağı.

Tarayıcı desteği

Tarayıcı desteği

  • Chrome: 103.
  • Edge: 103.
  • Firefox: Desteklenmez.
  • Safari: Desteklenmez.

Kaynak

Local Font Access API'yi kullanma

Özellik algılama

Yerel Yazı Tipi Erişimi API'sinin desteklenip desteklenmediğini kontrol etmek için:

if ('queryLocalFonts' in window) {
 
// The Local Font Access API is supported
}

Yerel yazı tiplerini numaralandırma

Yerel olarak yüklenen yazı tiplerinin listesini almak için window.queryLocalFonts() işlevini çağırmanız gerekir. İlk kez bu işlem, kullanıcının onaylayabileceği veya reddedebileceği bir izin istemi tetikler. Kullanıcı, yerel yazı tiplerinin sorgulanması için izin verirse tarayıcı, döngü oluşturabileceğiniz yazı tipi verilerini içeren bir dizi döndürür. Her yazı tipi, family (ör. "Comic Sans MS"), fullName (ör. "Comic Sans MS"), postscriptName (ör. "ComicSansMS") ve style (ör. "Regular") özelliklerine sahip bir FontData nesnesi olarak temsil edilir.

// Query for all available fonts and log metadata.
try {
 
const availableFonts = await window.queryLocalFonts();
 
for (const fontData of availableFonts) {
    console
.log(fontData.postscriptName);
    console
.log(fontData.fullName);
    console
.log(fontData.family);
    console
.log(fontData.style);
 
}
} catch (err) {
  console
.error(err.name, err.message);
}

Yalnızca yazı tiplerinin bir alt kümesiyle ilgileniyorsanız postscriptNames parametresi ekleyerek bunları PostScript adlarına göre de filtreleyebilirsiniz.

const availableFonts = await window.queryLocalFonts({
  postscriptNames
: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});

SFNT verilerine erişme

FontData nesnesinin blob() yöntemi aracılığıyla tam SFNT erişimi kullanılabilir. SFNT, PostScript, TrueType, OpenType, Web Open Font Format (WOFF) yazı tipleri gibi diğer yazı tiplerini içerebilen bir yazı tipi dosya biçimidir.

try {
 
const availableFonts = await window.queryLocalFonts({
    postscriptNames
: ['ComicSansMS'],
 
});
 
for (const fontData of availableFonts) {
   
// `blob()` returns a Blob containing valid and complete
   
// SFNT-wrapped font data.
   
const sfnt = await fontData.blob();
   
// Slice out only the bytes we need: the first 4 bytes are the SFNT
   
// version info.
   
// Spec: https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organization-of-an-opentype-font
   
const sfntVersion = await sfnt.slice(0, 4).text();

    let outlineFormat
= 'UNKNOWN';
   
switch (sfntVersion) {
     
case '\x00\x01\x00\x00':
     
case 'true':
     
case 'typ1':
        outlineFormat
= 'truetype';
       
break;
     
case 'OTTO':
        outlineFormat
= 'cff';
       
break;
   
}
    console
.log('Outline format:', outlineFormat);
 
}
} catch (err) {
  console
.error(err.name, err.message);
}

Demo

Aşağıdaki demoda Local Font Access API'nin işleyiş şeklini görebilirsiniz. Kaynak koda da göz atmayı unutmayın. Demoda, yerel yazı tipi seçici uygulayan <font-select> adlı özel bir öğe gösterilmektedir.

Gizlilik ile ilgili dikkat edilmesi gereken noktalar

"local-fonts" izni, yüksek oranda parmak izi alınabilen bir yüzey sağlıyor. Ancak tarayıcıların istedikleri her şeyi iade etme hakkı vardır. Örneğin, anonimliğe odaklanan tarayıcılar yalnızca tarayıcıya yerleştirilmiş bir dizi varsayılan yazı tipi sunmayı tercih edebilir. Benzer şekilde, tarayıcıların tablo verilerini tam olarak diskte göründükleri gibi sağlamaları gerekmez.

Mümkün olan her yerde, Local Font Access API yalnızca belirtilen kullanım alanlarını etkinleştirmek için gereken bilgileri tam olarak gösterecek şekilde tasarlanmıştır. Sistem API'leri, yüklü yazı tiplerinin listesini rastgele veya sıralı olarak değil, yazı tipi yükleme sırasına göre oluşturabilir. Bu tür bir sistem API'si tarafından verilen yüklü yazı tiplerinin tam listesini döndürmek, parmak izi oluşturmak için kullanılabilecek ek verileri açığa çıkarabilir ve etkinleştirmek istediğimiz kullanım alanlarına bu sıralamanın korunması yardımcı olmaz. Sonuç olarak bu API, döndürülen verilerin döndürülmeden önce sıralanması gerektiğini belirtir.

Güvenlik ve izinler

Chrome ekibi, yerel yazı tipi erişim API'sini tasarlarken ve uygularken kullanıcı kontrolü, şeffaflık ve ergonomi gibi Güçlü Web Platformu Özelliklerine Erişimi Kontrol Etme başlıklı makalede belirtilen temel ilkeleri temel almıştır.

Kullanıcı denetimi

Kullanıcının yazı tiplerine erişim tamamen kullanıcının denetimindedir ve izin kaydında belirtildiği üzere "local-fonts" izni verilmediği sürece bunlara izin verilmez.

Şeffaflık

Bir siteye kullanıcının yerel yazı tiplerine erişim izni verilip verilmediği site bilgileri sayfasında gösterilir.

İzin kalıcılığı

"local-fonts" izni, sayfa yeniden yüklemeleri arasında devam eder. Site bilgileri sayfası aracılığıyla iptal edilebilir.

Geri bildirim

Chrome ekibi, Yerel Yazı Tipi Erişimi API'si ile ilgili deneyimlerinizi öğrenmek istiyor.

API tasarımı hakkında bilgi verin

API'de beklediğiniz gibi çalışmayan bir şeyler mi var? Yoksa fikrinizi uygulamak için ihtiyacınız olan yöntemler veya özellikler mi var? Güvenlik modeliyle ilgili sorunuz veya yorumunuz mu var? İlgili GitHub deposunda spesifikasyon sorunu oluşturun veya mevcut bir soruna düşüncelerinizi ekleyin.

Uygulamayla ilgili bir sorunu bildirin

Chrome'un uygulanmasıyla ilgili bir hata buldunuz mu? Yoksa uygulama, spesifikasyondan farklı mı? new.crbug.com adresinden hata kaydı oluşturun. Mümkün olduğunca fazla ayrıntı ekleyin, hatayı yeniden oluşturmayla ilgili basit talimatlar verin ve Bileşenler kutusuna Blink>Storage>FontAccess yazın. Glitch, hızlı ve kolay yeniden oluşturma işlemlerini paylaşmak için idealdir.

API'yi destekleme

Yerel Yazı Tipi Erişimi API'yi kullanmayı planlıyor musunuz? Herkese açık desteğiniz, Chrome ekibinin özelliklere öncelik vermesine yardımcı olur ve diğer tarayıcı tedarikçi firmalarına bu özellikleri desteklemenin ne kadar önemli olduğunu gösterir.

#LocalFontAccess hashtag'ini kullanarak @ChromiumDev'e bir tweet gönderin ve etiketi nerede ve nasıl kullandığınızı bize bildirin.

Teşekkür ederiz

Yerel Yazı Tipi Erişimi API spesifikasyonu, Emil A. Eklund, Alex Russell, Joshua Bell ve Olivier Yiptong. Bu makale Joe Medley, Dominik Röttsches ve Olivier Yiptong tarafından incelenmiştir. Unsplash'tan Brett Jordan tarafından oluşturulan hero resim.