Opsi font variabel lainnya untuk font UI sistem macOS di Chromium 83

Catalina menghadirkan font sistem variabel united baru ke macOS.

Dominik Röttsches
Dominik Röttsches

Bagian'system-ui' pada spesifikasi Modul Font CSS Level 4 menentukan kata kunci font system-ui yang memungkinkan developer menggunakan font sistem operasi default bawaan, dioptimalkan turbo, dilokalkan, berkualitas sangat tinggi, tidak perlu didownload, langsung di situs dan aplikasi mereka.

body {
  font-family: system-ui;
}

Pilihan tipografi ini mirip dengan mengatakan "gunakan font sistem default untuk lokalitas pengguna saat ini."

Di macOS, font system-ui adalah San Francisco, font yang telah diperiksa, diuji, dan... baru-baru ini oleh tim desain. Pertama, kita akan membahas fitur font variabel baru yang menarik di Catalina, lalu kita akan membahas beberapa bug dan cara engineer Chromium menyelesaikannya.

Postingan ini mengasumsikan bahwa Anda sudah memahami font variabel. Jika belum, lihat Pengantar font variabel di web dan video di bawah.

Kompatibilitas browser

Pada saat penulisan ini, system-ui memiliki dukungan dari Chromium (sejak 56), Edge (sejak 79), Safari (sejak 11), dan dari Firefox (sejak 43), tetapi dengan kata kunci -apple-system. Lihat Dapatkah saya menggunakan font variabel? untuk mengetahui info terbaru.

Kekuatan baru

Kemampuan baru yang dihadirkan Catalina ke font sistem kini tersedia untuk developer web mulai Chromium 83. Font system-ui sekarang memiliki lebih banyak setelan variabel: ukuran optik dan 2 penyesuaian ketebalan yang unik:

Mojave
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750
  ;
}

Catalina
h1 {
  font-family: system-ui;
  font-weight: 700;
  font-variation-settings:
    'wght' 750,
    'opsz' 20,
    'GRAD' 400,
    'YAXS' 400
  ;
}

Di Mojave, system-ui adalah font variabel dengan hanya setelan wght. Sedangkan system-ui pada Catalina adalah font variabel dengan setelan wght, opsz, GRAD, dan YAXS.

Sepertinya saya bisa mendapatkan beberapa peluang {i>progressive enhancement<i} yang bagus. Pelajari seluk-beluk {i>font<i} sistem jika Anda mau.

wght

Menerima ketebalan font antara 0 dan 900 serta diterapkan secara merata untuk semua karakter.

/* 0-900 */
font-variation-settings: 'wght' 750;

opsz

Ukuran optik mirip dengan kerning atau spasi huruf, tetapi spasi dilakukan oleh mata manusia, bukan matematika. Nilai 19 atau lebih rendah ditujukan untuk spasi teks dan isi teks, sedangkan 20 atau lebih tinggi ditujukan untuk spasi header dan judul tampilan.

/* 19 or 20 */
font-variation-settings: 'opsz' 20;

GRAD

Mirip dengan berat, tetapi tanpa menyentuh spasi horizontal. Properti ini menerima nilai antara 400 dan 1000.

/* 400-1000 */
font-variation-settings: 'GRAD' 500;

YAXS

Meregangkan glyph secara vertikal. Properti ini menerima nilai antara 400 dan 1000.

/* 400-1000 */
font-variation-settings: 'YAXS' 500;

Menggabungkan opsi

Dengan beberapa baris CSS, kita dapat mengubah pengaturan font menjadi tebal pilihan kita atau mencoba kombinasi menarik lainnya:

font-weight: 700;
font-weight: bold;
font-variation-settings: 'wght' 750, 'YAXS' 600, 'GRAD' 500, 'opsz' 20;

Dengan begitu, pengguna Chromium di macOS melihat bobot 750 khusus Anda yang telah diupgrade dengan beberapa penyesuaian menyenangkan lainnya 👍

Taman Bermain

Klik Remix to Edit di Glitch di bawah untuk mendapatkan salinan Glitch yang dapat diedit, lalu edit opsi font-variation-settings baru untuk melihat pengaruhnya terhadap font Anda. Perlu diingat bahwa Glitch ini hanya akan berfungsi jika Anda menggunakan perangkat macOS Catalina.

macOS 10.15 menambahkan fitur baru ke font sistemnya, dan di macOS 10.15, bug system-ui yang rumit dicatat di pelacak bug Chromium. Apakah mereka terkait?

Lampiran: Regresi system-ui

Cerita ini dimulai dengan bug yang berbeda: #1005969. Hal ini dilaporkan terhadap macOS 10.15 karena spasi font system-ui tampak sempit dan penuh.

Perbandingan dua paragraf dari halaman grup Facebook. Di sebelah kiri adalah Chrome dan yang kanan adalah Safari, dan Chrome lebih halus tetapi sedikit lebih ketat dalam hal spasi.
Chrome di sebelah kiri (pelacakan lebih ketat), Safari di sebelah kanan (spasi optik yang lebih baik)

Latar belakang

Apakah Anda pernah memperhatikan di macOS 10.14 bagaimana paragraf atau header Anda "dipaskan" ke {i>font<i} yang terlihat berbeda ketika ukurannya naik atau turun?

Di Mojave (macOS 10.14), font system-ui beralih di antara dua font bergantung pada ukuran font target. Saat teks dalam format 20px, macOS menggunakan "San Francisco Text". Saat teks adalah 20px atau lebih, macOS menggunakan "San Francisco Display". Ukuran optik dibangun secara statis menjadi dua {i>font<i} terpisah.

Catalina (macOS 10.15) mengirimkan font variabel united baru untuk San Francisco. Tidak perlu lagi mengelola "Teks" dan "Tampilan". Versi ini juga mendapatkan setelan variasi baru opsz yang dijelaskan sebelumnya.

h1 {
  font-variation-settings: 'opsz' 20;
}

Sayangnya, nilai opsz default dalam font Catalina baru adalah 20, dan engineer Chromium tidak siap untuk menerapkan opsz ke font sistem. Hal ini menyebabkan ukuran yang lebih kecil ditampilkan terlalu sempit.

Untuk memperbaikinya, Chromium perlu menerapkan opsz dengan benar ke font sistem. Hal ini menyebabkan Masalah #1005969 diperbaiki. Kemenangan! Atau...?

Belum selesai

Di sini menjadi rumit: Chromium menerapkan opsz, tetapi ada sesuatu yang tidak terlihat dengan baik. Font sistem di Mac memiliki tabel font tambahan yang disebut trak, yang menyesuaikan spasi horizontal. Selagi melakukan perbaikan, engineer Chromium melihat bahwa di macOS, saat mengambil metrik horizontal dari objek CTFontRef, metrik trak sudah diperhitungkan dalam hasil metrik. Library pembentukan Chromium HarfBuzz memerlukan metrik yang belum memperhitungkan nilai trak.

Tampilan system-ui dan semua ketebalan serta variasi font dalam daftar. Setengah dari mereka tidak menerapkan perbedaan berat.
Kiri: Ketebalan tebal diterapkan ke ukuran font 19 dan yang lebih lama. Kanan: Ukuran font 20 ke atas akan kehilangan gaya visual tebal

Secara internal, Skia (library grafis, bukan jenis huruf dengan nama yang sama) menggunakan class CGFontRef dari CoreGraphics dan class CTFontRef dari CoreText. Karena konversi internal yang diperlukan di antara objek tersebut (digunakan untuk menjaga kompatibilitas mundur dan mengakses API yang diperlukan di kedua class), Skia akan kehilangan informasi berat dalam keadaan tertentu dan font tebal akan berhenti berfungsi. Hal ini dilacak dalam Masalah #1057654.

Skia masih perlu mendukung macOS 10.11 karena Chromium masih mendukungnya. Pada versi 10.11, font "San Francisco Text" dan "San Francisco Display" bahkan bukan font variabel. Sebaliknya, masing-masing merupakan kelompok {i>font<i} yang terpisah untuk setiap ketebalan yang tersedia. Pada titik tertentu, ID glyph mereka menjadi tidak sinkron. Jadi, jika Skia melakukan pembentukan teks (mengonversi teks menjadi glyph yang dapat digambar) dengan "Teks San Francisco", akan menjadi nonsens jika digambar dengan "Tampilan San Francisco", dan sebaliknya. Dan bahkan jika Skia hanya meminta ukuran macOS yang berbeda, mungkin akan beralih ke ukuran yang lain. Seharusnya Anda dapat selalu menggunakan salah satu font dan hanya menskalakannya (menggunakan matriks untuk meningkatkan skalanya, bukan meminta ukuran yang lebih besar). Namun, CoreText memiliki masalah yang tidak akan menskalakan glyph sbix (emoji warna) ke atas (hanya ke bawah). Hal ini sedikit lebih rumit. CoreText sebenarnya tampaknya membatasi tingkatan vertikal setelah penerapan matriks, yang tampaknya terkait dengan kemampuannya untuk menggambar emoji pada sudut 45 derajat. Apa pun itu, jika Anda ingin emoji ditampilkan berukuran besar, Anda harus membuat salinan font untuk mendapatkan versi yang besar.

Jadi, untuk membuat salinan objek CTFont dengan ukuran yang berbeda secara internal sambil memastikan bahwa data font dasar yang sama digunakan, Chromium mengambil CGFont dari CTFont, lalu membuat CTFont baru dari CGFont (objek CGFont tidak bergantung pada ukuran, pengalihan ajaib terjadi pada level CoreText). Hal ini berfungsi dengan baik hingga 10.154. Pada 10.15 perjalanan dua arah ini akhirnya kehilangan terlalu banyak informasi, mengakibatkan masalah berat. Flutter melihat masalah berat dan perbaikan alternatif untuk pengubahan ukuran dilakukan untuk membuat CTFont baru langsung dari CTFont asli sambil mengontrol ukuran optik secara langsung menggunakan atribut lama tetapi tidak terdokumentasi di CoreText. Ini membuat semuanya tetap berfungsi pada 10.11 dan memperbaiki masalah lainnya (seperti menyetel ukuran optik ke nilai default secara eksplisit).

Namun, tindakan ini mempertahankan lebih banyak 'magic' CoreText dalam font. Salah satunya tampaknya kode tersebut masih menyesuaikan kemajuan glyph dengan cara tertentu selain hanya tabel trak (aplikasi yang sudah berusaha disembunyikan oleh Chromium melalui atribut lain yang tidak terdokumentasi).

CGFont tidak melakukan 'sulap' ini, jadi mungkin Chromium bisa mengambil CGFont dari CTFont dan hanya menggunakannya untuk mendapatkan kemajuan? Sayangnya, cara ini tidak akan berhasil karena CoreText juga diketahui merusak font dengan cara lain. Misalnya, emoji kecil akan dibuat sedikit lebih besar dari yang sebenarnya Anda minta (sedikit meningkatkan ukurannya). CGFont tidak mengetahui hal ini, jadi Anda akan memiliki emoji berbasis sbix yang terlalu berdekatan satu sama lain karena Anda akan mengukur pada satu ukuran, tetapi CoreText akan menggambarnya lebih besar dalam jumlah tertentu. Chromium memang menginginkan kemajuan CTFont, tetapi membutuhkannya tanpa pelacakan, dan sebaiknya tanpa pembongkaran lainnya.

Karena perbaikan untuk masalah spasi memerlukan serangkaian perbaikan Blink dan Skia yang saling berhubungan, engineer Chromium tidak dapat "kembali" untuk memperbaiki masalah. Para engineer Chromium juga mencoba menggunakan tanda build yang berbeda untuk mengubah codepath terkait font di Skia, yang memperbaiki masalah font tebal, tetapi memundurkan masalah spasi.

Perbaikan

Pada akhirnya, tentu saja Chromium ingin memperbaiki kedua masalah tersebut. Chromium kini memanfaatkan fungsi metrik font OpenType font bawaan HarfBuzz untuk mengambil metrik horizontal langsung dari data biner dalam tabel font font sistem. Dengan menggunakan ini, Chromium men-sidestep CoreText dan Skia saat font memiliki tabel trak (kecuali jika font emoji).

Tampilan system-ui dan semua ketebalan serta variasi font dalam daftar. Setengah bagian yang sebelumnya tidak berfungsi kini terlihat bagus.

Sementara itu, masih ada Masalah Skia #10123 untuk melacak perbaikan ini sepenuhnya di Skia, dan kembali menggunakan Skia untuk mengambil metrik font sistem dari sana, bukan perbaikan saat ini yang melalui HarfBuzz.