Bagikan melalui


Font Variabel OpenType

Topik ini menjelaskan font variabel OpenType, dukungannya di DirectWrite dan Direct2D, dan cara menggunakannya di aplikasi Anda. 

Apa itu font variabel OpenType?

Spesifikasi format font OpenType versi 1.8 memperkenalkan ekstensi baru ke format yang dikenal sebagai Variasi Font OpenType. Font yang menggunakan ekstensi ini dikenal sebagai font variabel OpenType. Font variabel OpenType adalah font tunggal yang dapat berpura-pura seperti beberapa font dengan menggunakan interpolasi berkelanjutan antara desain yang berbeda, semuanya ditentukan dalam font tunggal.

Font variabel OpenType dapat menentukan variasi berkelanjutan dari desainnya di sepanjang satu atau beberapa sumbu independen, seperti berat atau lebar:

 

Menampilkan font variabel OpenType menggunakan huruf 'G' dan memperlihatkan variasi yang berbeda di sepanjang sumbu lebar horizontal dan sumbu bobot vertikal.

Pengembang font menentukan sekumpulan sumbu variasi untuk digunakan dalam font tertentu. Sumbu ini dapat mencakup sekumpulan sumbu variasi yang terkenal (atau "terdaftar"), seperti berat dan lebar, tetapi mereka juga dapat menyertakan sumbu variasi kustom yang segan dan didefinisikan oleh pengembang font.  

Dengan memilih sekumpulan sumbu variasi untuk font, pengembang font menentukan ruang variasi desain n-dimensi abstrak untuk font. Mesin teks dapat menentukan kemungkinan posisi apa pun, atau "instans", dalam ruang berkelanjutan tersebut untuk meletakkan dan merender teks. 

Pengembang font juga dapat memilih dan menetapkan nama ke instans tertentu dalam ruang variasi desain; ini disebut sebagai "instans bernama". Misalnya, font dengan variasi berat dapat mendukung variasi berkelanjutan antara goresan yang sangat ringan dan sangat berat, sementara pengembang font telah memilih bobot tertentu di sepanjang kontinum tersebut dan nama yang ditetapkan untuk mereka, seperti "Light", "Regular" dan "Semibold". 

Format font variabel OpenType menggunakan tabel data yang ditemukan dalam font OpenType tradisional ditambah tabel tambahan tertentu yang menjelaskan bagaimana nilai berbagai item data berubah untuk instans yang berbeda. Format ini menunjuk satu instans variasi sebagai "instans default", yang menggunakan tabel tradisional untuk mendapatkan nilai default. Semua instans lain bergantung pada data default ditambah data delta lainnya. Misalnya, tabel 'glyf' dapat memiliki deskripsi kurva Bezier dari bentuk glyph nominal, yang merupakan bentuk yang digunakan untuk instans default, sementara tabel 'gvar' akan menjelaskan bagaimana titik kontrol Bezier untuk glyph disesuaikan untuk instans lain. Demikian pula, nilai font lainnya dapat memiliki nilai nominal ditambah data delta yang menjelaskan bagaimana nilai tersebut berubah untuk instans yang berbeda; misalnya, tinggi x dan metrik di seluruh font lainnya, atau posisi mark-anchoring khusus glyph dan penyesuaian kerning. 

Karena font variabel dapat mendukung serangkaian sumbu variasi arbitrer, mereka memerlukan model keluarga font yang dapat diperluas yang lebih langsung mencerminkan bagaimana perancang font membuat keluarga font: keluarga font didefinisikan oleh nama keluarga dan karakteristik desain tertentu yang konstan, dengan angka arbitrer (ditentukan oleh pengembang font) tentang cara-cara di mana desain dapat bervariasi. Satu keluarga font dapat dibuat dengan varian untuk berat badan, tetapi keluarga font yang berbeda dapat dibuat dengan varian untuk tinggi x, ukuran serif, "keceriaan", atau apa pun yang diinginkan pengembang font. Dalam model ini, pilihan wajah font paling baik dijelaskan menggunakan umum, atau "lebih disukai" atau "tipografi", nama keluarga ditambah sekumpulan pasangan kunci-nilai, masing-masing mewakili semacam variasi dan nilai tertentu, dengan jenis variasi secara umum menjadi set yang dapat diperluas. Gagasan umum keluarga font ini dapat berlaku untuk font tradisional dan non-variabel serta ke font variabel. Misalnya, di bawah model keluarga tipografi umum ini, keluarga "Selawik VF" mungkin memiliki variasi untuk berat badan, ukuran optik, dan desain serif, dengan instans seperti "Semilight Banner Sans". 

Namun, beberapa implementasi perangkat lunak yang ada, termasuk API DirectWrite yang ada, dapat dirancang dengan asumsi model keluarga font yang lebih terbatas. Misalnya, beberapa aplikasi dapat mengasumsikan bahwa keluarga font dapat memiliki, paling banyak, varian Miring Reguler, Tebal, Miring, dan Tebal. IDWriteFontCollectionyang ada dan antarmukaIDWriteFontFamilymengasumsikan model keluarga berat/stretch/style ("WSS"), memungkinkan varian dalam keluarga ditentukan menggunakan enumerasi DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH, atau DWRITE_FONT_STYLE sebagai parameter. Mengambil contoh sebelumnya, ukuran optik dan sumbu serif tidak akan diperlakukan sebagai sumbu variasi keluarga-internal dalam model WSS. 

Dukungan lengkap untuk font variabel akan memerlukan API yang memungkinkan anggota keluarga ditentukan dengan kemungkinan beberapa parameter, seperti yang ditentukan oleh font. Tetapi desain API yang ada mungkin dapat memberikan dukungan parsial untuk font variabel dengan memproyeksikan instans bernama yang ditentukan dalam font variabel ke dalam model keluarga font yang lebih terbatas. Dalam contoh sebelumnya, "Selawik VF Semilight Banner Sans" dapat diproyeksikan ke dalam model WSS sebagai keluarga "Selawik VF Banner Sans" dengan "Semilight" sebagai varian berat. 

Misalnya, pertimbangkan keluarga font tipografi seperti Sitka, dengan varian berat dan ukuran optik. Varian bernama dalam keluarga termasuk Sitka Text Regular dan Sitka Banner Bold (ditambah banyak lainnya). Nama keluarga tipografis adalah "Sitka" sedangkan nama wajah untuk varian ini dalam model keluarga tipografik adalah "Text Regular" dan "Banner Bold". Model keluarga empat anggota dan WSS tidak memungkinkan varian ukuran optik dalam keluarga, sehingga perbedaan ukuran optik harus diperlakukan seperti perbedaan tingkat keluarga. Tabel berikut ini menggambarkan bagaimana pilihan font dari keluarga tipografi Sitka akan diperlakukan dalam model keluarga WSS:

Model keluarga tipografi

Model keluarga WSS

Keluarga

Muka

Keluarga

Muka

Sitka

Teks Reguler

Teks Sitka

Biasa

Sitka

Banner Tebal

Spanduk Sitka

Berani

Sitka

Keterangan Miring

Keterangan Sitka

Miring

 

Proyeksi nama dari model keluarga tipografis ke model keluarga WSS dapat diterapkan ke font non-variabel, dan ke instans font variabel bernama. Namun, ini tidak dapat dilakukan untuk instans lain yang tidak bernama dari ruang variasi desain berkelanjutan dari font variabel. Untuk alasan ini, dukungan untuk fungsionalitas lengkap font variabel akan memerlukan API yang dirancang untuk mereferensikan wajah dalam keluarga tipografis dalam hal serangkaian sumbu variasi dan nilai sumbu yang tidak dibatasi. 

Dukungan font variabel OpenType di DirectWrite

Pada rilis Pembaruan Pembuat Windows 10, format font variabel OpenType masih sangat baru, dan vendor font, platform, dan aplikasi masih dalam proses penerapan format baru. Pembaruan ini menyediakan implementasi awal untuk format ini di DirectWrite. 

Internal DirectWrite telah diperbarui untuk mendukung font variabel OpenType. Dengan menggunakan API saat ini, ini menyediakan dukungan untuk setiap instans bernama dari font variabel. Dukungan ini dapat digunakan untuk alur kerja lengkap — mulai dari enumerasi instans bernama, pemilihan instans bernama, penggunaan dalam tata letak dan pembentukan, hingga penyajian dan pencetakan. Untuk keuntungan aplikasi yang juga menggunakan interop teks GDI untuk operasi tertentu, dukungan serupa juga telah ditambahkan di API GDI yang ada. 

Dalam Pembaruan Pembuat Windows 10, DirectWrite tidak mendukung instans arbitrer yang menggunakan kemampuan variasi berkelanjutan dari font variabel.

Dalam banyak operasi, perilaku dalam DirectWrite instans bernama dari font variabel tidak dapat dibedakan dari perilaku font non-variabel. Dan karena dukungan disediakan menggunakan API DirectWrite yang ada, instans font variabel yang dinamai bahkan dapat berfungsi di banyak aplikasi DirectWrite yang ada tanpa perubahan apa pun. Pengecualian dapat berlaku, namun, dalam situasi tertentu:

  • Jika aplikasi memproses data font secara langsung untuk operasi tertentu. Misalnya, jika aplikasi membaca data kerangka glyph langsung dari file font untuk membuat efek visual tertentu.
  • Jika aplikasi menggunakan pustaka pihak ketiga untuk operasi tertentu. Misalnya, jika aplikasi menggunakan DirectWrite untuk tata letak, untuk mendapatkan indeks dan posisi glyph akhir, tetapi kemudian menggunakan pustaka pihak ketiga untuk penyajian.
  • Jika aplikasi menyematkan data font ke dalam dokumen atau dengan cara lain meneruskan data font ke proses hilir.

Jika operasi dilakukan menggunakan implementasi yang tidak mendukung font variabel, maka operasi ini mungkin tidak menghasilkan hasil yang diharapkan. Misalnya, posisi glyph mungkin dihitung untuk satu instans bernama dari font variabel, tetapi glyph mungkin dirender dengan asumsi instans bernama yang berbeda. Bergantung pada implementasi aplikasi, hasil dapat berfungsi dalam beberapa konteks tetapi tidak dalam konteks lain di mana pustaka lain dapat digunakan. Misalnya, teks dapat ditampilkan dengan benar di layar, tetapi tidak saat dicetak. Jika alur kerja end-to-end diimplementasikan hanya menggunakan DirectWrite, perilaku yang benar untuk instans bernama dari font variabel dapat diharapkan. 

Karena API DirectWrite yang ada mendukung pemilihan wajah menggunakan model berat/rentang/gaya, instans font bernama yang menggunakan sumbu variasi lainnya akan diproyeksikan dari model keluarga tipografi umum ke dalam model WSS, seperti yang dijelaskan di atas. Ini bergantung pada font variabel termasuk tabel "atribut gaya" ('STAT') dengan subtable nilai sumbu, yang digunakan DWrite untuk membedakan token nama wajah yang menunjuk atribut berat, bentang, atau gaya dari token yang berkaitan dengan sumbu variasi lainnya.  

Jika font variabel tidak menyertakan tabel 'STAT', seperti yang diperlukan untuk font variabel berdasarkan spesifikasi OpenType, maka DirectWrite akan memperlakukan font sebagai font non-variabel yang hanya berisi instans default.  

Jika font memang berisi tabel 'STAT' tetapi tidak menyertakan subtable nilai sumbu yang sesuai, ini dapat menyebabkan hasil yang tidak terduga, seperti memiliki beberapa wajah yang memiliki nama wajah yang identik. Font tersebut tidak didukung saat ini. 

Spesifikasi OpenType memungkinkan data kerangka glyph diwakili dalam salah satu dari dua format: menggunakan tabel 'glyf', yang menggunakan kerangka TrueType dan format petunjuk, atau menggunakan tabel 'CFF', yang menggunakan representasi Format Font Ringkas ("CFF"). Dalam font variabel dengan kerangka TrueType, tabel 'glyf' terus digunakan, dan dilengkapi dengan tabel 'gvar' yang menyediakan data variasi untuk kerangka. Ini berarti bahwa instans default font variabel dengan kerangka TrueType hanya menggunakan tabel OpenType tradisional yang akan didukung dalam perangkat lunak lama yang tidak memiliki dukungan font variabel. Namun, dalam font variabel dengan kerangka CFF, tabel 'CFF' digantikan oleh tabel 'CFF2', yang merangkum data kerangka default dan data variasi terkait dalam satu tabel. Data CFF diproses oleh rasterizer terpisah dari yang digunakan untuk data TrueType, dan tabel 'CFF2' memerlukan rasterizer CFF yang diperbarui yang memiliki dukungan 'CFF2'. Tabel 'CFF2' tidak dapat diproses oleh rasterizer CFF yang lebih lama. Untuk font variabel dengan data kerangka CFF, ini berarti bahwa bahkan instans default tidak akan berfungsi di perangkat lunak yang lebih lama. 

Dalam Pembaruan Pembuat Windows 10, DirectWrite tidak mendukung font variabel dengan data kerangka CFF menggunakan tabel 'CFF2'. 

Menggunakan font variabel OpenType

Font variabel OpenType dapat mudah digunakan, mengingat batasan saat ini yang disebutkan di atas:

  • Hanya instans bernama dari font variabel yang didukung saat ini.
  • Hanya font variabel yang menggunakan data kerangka glyph TrueType (bukan kerangka CFF) yang didukung saat ini. 
  • Untuk font yang menggunakan sumbu variasi desain selain berat, rentang atau gaya, instans bernama akan diproyeksikan ke dalam model keluarga WSS, yang dapat mengakibatkan beberapa instans bernama muncul sebagai keluarga terpisah (seperti yang akan terjadi di masa lalu untuk font non-variabel). Untuk mendukung ini, font variabel harus memiliki tabel 'STAT' yang menyertakan subtable nilai sumbu yang sesuai.
  • Instans font variabel yang dinamai didukung dalam API DirectWrite, tetapi jika operasi tertentu dilakukan dalam implementasi lama yang tidak mendukung font variabel, itu dapat menghasilkan hasil yang salah. 
  • API DirectWrite tertentu menggunakan enumerasi DWRITE_FONT_WEIGHT, DWRITE_FONT_STRETCH, dan DWRITE_FONT_STYLE untuk menentukan atribut berat, regangan, dan gaya saat memilih wajah. Jika font variabel menggunakan sumbu variasi yang sesuai tetapi memiliki banyak instans bernama yang memerlukan granularitas yang lebih halus, tidak semua instans bernama akan dapat dipilih di API tersebut.

Font variabel OpenType yang sesuai dengan persyaratan ini dapat diinstal dari shell Windows sama seperti font OpenType lainnya, dan juga dapat digunakan dalam set font kustom yang dibuat oleh aplikasi.  

Ketika diinstal dalam sistem, semua instans bernama dari font variabel akan disertakan dalam kumpulan font yang dikembalikan dengan memanggil metodeIDWriteFontFamily3::GetSystemFontSet. Perhatikan bahwa kumpulan font adalah daftar datar tanpa hierarki pengelompokan keluarga, tetapi setiap item dalam set memiliki properti nama keluarga berdasarkan model keluarga WSS. Kumpulan font dapat difilter untuk instans bernama font variabel tertentu menggunakan metodeIDWriteFontSet::GetMatchingFonts. Namun, jika menggunakan GetMatchingFonts kelebihan beban yang mengambil familyName, familyName yang ditentukan harus menggunakan nama yang sesuai dengan model keluarga font WSS. Daftar lengkap nama keluarga yang kompatibel dengan WSS yang terjadi dalam kumpulan font dapat diperoleh menggunakan metode IDWriteFontSet::GetPropertyValues menggunakan DWRITE_FONT_PROPERTY_ID_FAMILY_NAME.  

Demikian pula, semua instans bernama dari font variabel akan diwakili dalam koleksi font yang dikembalikan oleh metodeIDWriteFactory::GetSystemFontCollection. Karena elemen koleksi font adalah keluarga font berdasarkan model WSS, instans bernama dari font variabel dapat diwakili dalam koleksi sebagai anggota dua keluarga font atau lebih. Jika metode IDWriteFontCollection::FindFamilyName digunakan, parameter familyName harus berupa nama keluarga yang kompatibel dengan WSS. Untuk menemukan semua nama keluarga yang kompatibel dengan WSS dari koleksi font, aplikasi dapat mengulangi setiap keluarga dan memanggil IDWriteFontFamily::GetFamilyNames, meskipun mungkin lebih mudah untuk mendapatkan kumpulan font yang sesuai dan menggunakan metode GetPropertyValues seperti yang dijelaskan di atas. 

Saat bekerja dengan font kustom, berbagai pendekatan yang dijelaskan dalam Set Font Kustom topik dapat digunakan untuk membuat kumpulan font. Untuk menambahkan font variabel ke kumpulan font kustom, metode IDWriteFontSetBuilder1::AddFontFile direkomendasikan karena mendukung font variabel dan akan menambahkan semua instans bernama font variabel dalam satu panggilan. Saat ini tidak ada cara untuk menambahkan instans bernama individu dari font variabel kustom ke kumpulan font menggunakan IDWriteFontSetBuilder::AddFontFaceReference metode karena tidak ada cara untuk membuat referensi wajah font yang menentukan instans bernama mana dari file font variabel yang dimaksudkan. Ini berarti bahwa saat ini tidak ada cara untuk menambahkan instans bernama font kustom ke kumpulan font kustom dengan properti kustom yang ditetapkan. Itu pada gilirannya berarti bahwa font variabel kustom saat ini tidak dapat dengan mudah digunakan bersama dengan API DirectWrite untuk font jarak jauh. Jika instans bernama dari font variabel disertakan dalam kumpulan font sistem, namun, referensi wajah font untuk setiap instans bernama sudah ada, dan ini dapat ditambahkan ke kumpulan font kustom, termasuk dengan penggunaan nilai properti kustom. Lihat topik Set Font Kustom untuk detail selengkapnya. 

Saat bekerja dengan font variabel, enumerasi DirectWrite DWRITE_FONT_WEIGHT dan DWRITE_FONT_STRETCH terhubung erat ke sumbu variasi berat dan lebar yang ditentukan dalam spesifikasi OpenType, tetapi tidak sama. Pertama, skala numerik untuk sumbu variasi apa pun selalu mendukung nilai pecahan, sementara fontWeight dan fontStretch menggunakan bilangan bulat. Skala sumbu bobot OpenType menggunakan nilai mulai dari 1 hingga 1000, yang juga didukung oleh fontWeight. Dengan demikian perubahan dari nilai sumbu bobot variasi ke fontWeight relatif kecil: fontWeight yang dilaporkan untuk instans bernama dapat dibulatkan dari nilai yang tepat yang digunakan untuk menentukan instans bernama dalam font. Perbedaan antara font DirectWriteStretch dan skala sumbu lebar OpenType lebih besar: DirectWrite menggunakan nilai dari 1 hingga 9, mengikuti nilai usWidthClass tabel OpenType OS/2, sementara skala sumbu lebar OpenType menggunakan nilai positif yang mewakili persentase lebar normal. Dokumentasi usWidthClass dalam spesifikasi OpenType menyediakan pemetaan antara nilai 1 hingga 9 dan persen dari nilai normal. Nilai fontStretch yang dilaporkan untuk instans bernama mungkin melibatkan pembulatan saat mengonversi dari nilai sumbu lebar. 

Saat membuatIDWriteTextFormat, koleksi font dan properti font yang kompatibel dengan WSS (nama keluarga, berat, rentang, dan gaya) harus ditentukan. Ini juga berlaku saat mengatur properti pemformatan font pada rentang teks IDWriteTextLayout. Properti dapat diperoleh dari objek IDWriteFontFace3 atau dari IDWriteFont dan idWriteFontFamily objek yang mewakili instans bernama tertentu. Seperti yang diamati di atas, nilai yang dikembalikan oleh metode GetWeight dan GetStretch dapat dibulatkan perkiraan untuk nilai sumbu aktual yang digunakan untuk menentukan instans bernama, tetapi DirectWrite akan memetakan kombinasi properti kembali ke instans bernama yang diinginkan. 

Demikian pula, jika aplikasi menggunakan IDWriteFontFallbackBuilder untuk membuat data fallback font kustom, keluarga ditentukan untuk pemetaan rentang karakter menggunakan nama keluarga yang kompatibel dengan WSS. Fallback font dalam DirectWrite didasarkan pada keluarga dengan DirectWrite yang memilih varian dalam keluarga fallback yang merupakan kecocokan terdekat untuk varian keluarga awal. Untuk varian yang melibatkan dimensi selain berat, bentang dan gaya, DirectWrite saat ini tidak akan dapat memilih varian tersebut dalam keluarga fallback kecuali data fallback kustom dibuat khusus untuk memberikan pemetaan fallback untuk keluarga yang memiliki atribut non-WSS tertentu, seperti varian ukuran optik "Keterangan".