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

Catalina menghadirkan font sistem variabel bersatu baru ke macOS.

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

body {
  font-family: system-ui;
}

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

Di macOS, font system-ui adalah San Francisco, font yang telah diseleksi, diuji, dan… baru-baru ini diupgrade oleh tim desain. Pertama, kita akan membahas fitur font variabel baru yang menarik di Catalina, lalu kami 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, system-ui memiliki dukungan dari Chromium (mulai versi 56), Edge (mulai versi 79), Safari (mulai versi 11), dan dari Firefox (mulai versi 43), tetapi dengan kata kunci -apple-system. Lihat Dapatkah saya menggunakan font variabel? untuk mengetahui info terbaru.

Kekuatan baru

Kemampuan baru yang dibawa Catalina ke font sistem kini tersedia untuk developer web mulai Chromium 83. Font system-ui kini 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 setelan wght saja. Sementara system-ui di Catalina adalah font variabel dengan setelan wght, opsz, GRAD, dan YAXS.

Sepertinya ada beberapa peluang desain progressive enhancement yang bagus. Pelajari detail font sistem jika Anda mau.

wght

Menerima ketebalan font antara 0 dan 900 dan diterapkan secara merata ke 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 di bawahnya ditujukan untuk spasi teks dan teks isi, sedangkan 20 atau di atasnya ditujukan untuk spasi header dan judul tampilan.

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

GRAD

Mirip dengan ketebalan, tetapi tanpa menyentuh spasi horizontal. Kolom 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 menyesuaikan setelan font menjadi tebal sesuai pilihan atau mencoba kombinasi menarik lainnya:

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

Dan begitulah, pengguna Chromium di macOS akan melihat ketebalan 750 kustom yang diupgrade dengan beberapa penyesuaian menarik 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 dalam pelacak bug Chromium. Saya ingin tahu apakah keduanya terkait?

Lampiran: Regresi system-ui

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

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

Latar belakang

Pernahkah Anda memperhatikan di macOS 10.14 bagaimana paragraf atau {i>header<i} Anda "dipaskan" ke tampilan {i>font<i} yang terlihat berbeda saat ukuran naik atau turun?

Di Mojave (macOS 10.14), font system-ui beralih antara dua font, bergantung pada ukuran font target. Jika teks berada di bawah 20px, macOS akan menggunakan "Teks San Francisco". Jika teks berukuran 20px atau lebih, macOS akan menggunakan "San Francisco Display". Pengukuran optik dibuat secara statis ke dalam dua font terpisah.

Catalina (macOS 10.15) meluncurkan {i>font<i} variabel bersatu baru untuk San Francisco. Tidak perlu lagi mengelola "Teks" dan "Tampilan". Halaman ini juga mendapatkan setelan varian baru opsz yang dijelaskan sebelumnya.

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

Sayangnya, nilai opsz default dalam font Catalina yang 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 apakah…?

Belum selesai

Di sinilah letak masalahnya: Chromium menerapkan opsz, tetapi ada yang masih terlihat salah. Font sistem di Mac memiliki tabel font tambahan yang disebut trak, yang menyesuaikan spasi horizontal. Saat mengerjakan perbaikan ini, engineer Chromium mendapati bahwa di macOS, saat mengambil metrik horizontal dari objek CTFontRef, metrik trak sudah diperhitungkan dalam hasil metrik. Library pembentukan Chromium HarfBuzz memerlukan metrik yang nilai trak-nya belum diperhitungkan.

Tampilan UI sistem dan semua ketebalan font serta variasinya dalam sebuah daftar. Setengah darinya tidak menerapkan perbedaan bobot.
Kiri: Ketebalan tebal diterapkan ke ukuran font 19 dan yang lebih rendah. Kanan: Ukuran font 20 dan yang lebih besar kehilangan gaya 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 mempertahankan kompatibilitas mundur dan mengakses API yang diperlukan di kedua class), Skia akan kehilangan informasi ketebalan dalam situasi tertentu dan font tebal akan berhenti berfungsi. Masalah ini dilacak dalam Masalah #1057654.

Skia masih perlu mendukung macOS 10.11 karena Chromium masih mendukungnya. Pada 10.11, font "San Francisco Text" dan "San Francisco Display" bahkan bukan font variabel. Sebaliknya, masing-masing adalah keluarga {i>font<i} yang terpisah untuk setiap bobot yang tersedia. Pada suatu saat, ID glyph-nya menjadi tidak sinkron satu sama lain. Jadi, jika Skia melakukan pembentukan teks (mengonversi teks menjadi glyph yang dapat digambar) dengan "San Francisco Text", teks tersebut akan menjadi tidak jelas jika digambar dengan "San Francisco Display", dan sebaliknya. Dan bahkan jika Skia hanya meminta ukuran macOS yang berbeda, mungkin akan beralih ke ukuran lain. Anda seharusnya dapat selalu menggunakan salah satu font dan hanya menskalakannya (menggunakan matriks untuk menskalakannya, bukan meminta ukuran yang lebih besar), tetapi CoreText memiliki masalah yang tidak akan menskalakan glyph sbix (emoji warna) ke atas (hanya ke bawah). Caranya sedikit lebih rumit dari itu. CoreText sebenarnya tampaknya membatasi ekstensi vertikal setelah penerapan matriks, yang tampaknya terkait dengan ketidakmampuan untuk menggambar emoji pada sudut 45 derajat. Apa pun yang terjadi, jika Anda ingin emoji ditampilkan dalam ukuran besar, Anda perlu membuat salinan font untuk mendapatkan versi besar.

Jadi, untuk membuat salinan objek CTFont dengan ukuran yang berbeda secara internal sekaligus memastikan bahwa data font yang mendasarinya sama, Chromium menarik CGFont dari CTFont, lalu membuat CTFont baru dari CGFont (objek CGFont tidak bergantung pada ukuran, peralihan ajaib terjadi di tingkat CoreText). Ini berfungsi dengan baik hingga 10.154. Di 10.15, perjalanan pulang-pergi ini akhirnya kehilangan terlalu banyak informasi, sehingga menyebabkan masalah berat. Flutter mendeteksi masalah bobot dan perbaikan alternatif untuk mengubah ukuran dilakukan untuk membuat CTFont baru langsung dari CTFont asli sambil mengontrol ukuran optik secara langsung menggunakan atribut lama tetapi tidak terdokumentasi di CoreText. Hal ini membuat versi tetap berfungsi pada versi 10.11 dan memperbaiki masalah lainnya (seperti menyetel ukuran optik ke nilai default secara eksplisit).

Namun, hal ini akan mempertahankan lebih banyak 'keajaiban' CoreText dalam font. Salah satunya tampaknya masih menyesuaikan kemajuan glyph dengan cara lain selain tabel trak (aplikasi yang sudah dicoba dinonaktifkan oleh Chromium melalui atribut lain yang tidak terdokumentasi).

CGFont tidak melakukan 'keajaiban' ini, jadi mungkin Chromium dapat menghapus CGFont dari CTFont dan hanya menggunakannya untuk mendapatkan kemajuan? Sayangnya, hal ini tidak akan berhasil karena CoreText juga diketahui mengganggu font dengan cara lain. Misalnya, fitur ini membuat emoji kecil sedikit lebih besar dari yang sebenarnya Anda minta (meningkatkan ukurannya sedikit). CGFont tidak mengetahui hal ini, sehingga Anda akan mendapatkan emoji berbasis sbix yang terlalu berdekatan karena Anda akan mengukur pada satu ukuran, tetapi CoreText akan menggambarnya lebih besar dengan jumlah tertentu. Chromium memang menginginkan CTFont maju, tetapi menginginkannya tanpa pelacakan, dan sebaiknya tanpa gangguan lain.

Karena perbaikan untuk masalah spasi memerlukan serangkaian perbaikan Blink dan Skia yang saling terhubung, engineer Chromium tidak dapat "langsung mengembalikan" untuk memperbaiki masalah tersebut. Engineer Chromium juga mencoba menggunakan flag build yang berbeda untuk mengubah codepath terkait font di Skia, yang memperbaiki masalah font tebal, tetapi mengalami regresi pada masalah spasi.

Perbaikan

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

Tampilan UI sistem dan semua ketebalan dan variasi fontnya dalam daftar. Bagian yang sebelumnya tidak berfungsi sekarang terlihat bagus.

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