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

Yerel Yazı Tipi Erişimi API'sinin, kullanıcının yerel olarak yüklenen yazı tiplerine erişmenize ve bunlarla ilgili ayrıntılı bilgiler edinmenize nasıl olanak tanıdığı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ı. Günümüzde, bazılarında çeşitli açığa çıkarılan eksenlerin değerlerini değiştirerek daha da ince ayar yapabileceğimiz web yazı tipleri var. Hatta bunların bazıları değişken yazı tipleridir. 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 web'den gelir. Ancak @font-face beyanında yer alan src özelliği, url() işlevinin yanı sıra local() işlevini de kabul eder. 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 etmenizi sağlayacak iyi bir yedek mekanizma sağlar. İnternette maalesef her şey yolunda gitmez. local() işlevinin sorunu, tarayıcı parmak izi için kötüye kullanılabilmesidir. Kullanıcının yüklediği yazı tiplerinin listesi oldukça tanımlayıcı olabilir. Birçok şirketin, çalışanlarının dizüstü bilgisayarlarına yüklenen kendi kurumsal yazı tipleri vardır. Örneğin, Google'ın Google Sans adlı bir kurumsal 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ı tipleri dışında, yüklü yazı tiplerinin listesi bile kimliği tanımlayabilir. 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? Endişelenmeyin. 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ştirmesi 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 vermesi için yazı tipi baytlarına erişmesi gerekir.
  • Geliştiricilerin, web'e taşıdıkları uygulamaları için eski yazı tipi grupları olabilir. Bu grupları kullanmak için genellikle yazı tipi verilerine doğrudan erişim gerekir. Web yazı tipleri bu erişimi sağlamaz.
  • Bazı yazı tipleri web üzerinden yayınlanmak için lisanslı olmayabilir. Örneğin, Linotype'in 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 vermesine olanak tanıyan 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

Yerel Yazı Tipi Erişimi API'sini 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 sağlanabilir. 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

Yerel Yazı Tipi Erişimi API'sini aşağıdaki demo'da görebilirsiniz. Kaynak koda da göz atmayı unutmayın. Demoda, yerel yazı tipi seçiciyi 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üğü şekilde sağlaması gerekmez.

Yerel Yazı Tipi Erişimi API'si mümkün olduğunda yalnızca belirtilen kullanım alanlarını etkinleştirmek için gereken bilgileri göstermek üzere 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 kontrolündedir ve izin kayıt defterinde listelenen "local-fonts" izni verilmediği sürece erişim izni 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ı üzerinden 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 ile ilgili olarak beklediğiniz gibi çalışmayan bir şey var mı? Yoksa fikrinizi uygulamak için ihtiyaç duyduğunuz yöntemler veya özellikler eksik mi? 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 sorunları bildirme

Chrome'un uygulamasında bir hata mı buldunuz? 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 hesabına tweet gönderin ve bu özelliği 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.