Thêm nhiều tuỳ chọn phông chữ có thể thay đổi cho phông chữ giao diện người dùng hệ thống của macOS trong Chromium 83

Catalina mang đến một phông chữ hệ thống có thể thay đổi mới và thống nhất cho macOS.

Mục "system-ui" của quy cách Mô-đun phông chữ CSS cấp 4 xác định một từ khoá phông chữ system-ui cho phép nhà phát triển sử dụng phông chữ mặc định của hệ điều hành được tích hợp sẵn, tối ưu hoá turbo, bản địa hoá, chất lượng siêu cao, không cần tải xuống ngay trong trang web và ứng dụng của họ.

body {
  font-family: system-ui;
}

Lựa chọn kiểu chữ này tương tự như việc nói "sử dụng phông chữ hệ thống mặc định cho ngôn ngữ hiện tại của người dùng này".

Trên macOS, phông chữ system-ui là San Francisco, một phông chữ mà nhóm thiết kế đã kiểm tra, thử nghiệm và… gần đây đã nâng cấp! Trước tiên, chúng ta sẽ tìm hiểu về các tính năng mới thú vị của phông chữ có thể thay đổi trong Catalina, sau đó, chúng ta sẽ tìm hiểu về một số lỗi và cách các kỹ sư Chromium giải quyết những lỗi đó.

Bài đăng này giả định rằng bạn đã quen thuộc với phông chữ có thể thay đổi. Nếu không, hãy xem bài viết Giới thiệu về phông chữ có thể thay đổi trên web và video bên dưới.

Khả năng tương thích với trình duyệt

Tại thời điểm viết bài, system-ui được Chromium (từ phiên bản 56), Edge (từ phiên bản 79), Safari (từ phiên bản 11) và Firefox (từ phiên bản 43) hỗ trợ nhưng phải có từ khoá -apple-system. Hãy xem phần Tôi có thể sử dụng phông chữ có thể thay đổi không? để biết thông tin cập nhật.

Sức mạnh mới

Kể từ Chromium 83, các nhà phát triển web có thể sử dụng những khả năng mới mà Catalina mang lại cho phông chữ hệ thống. Phông chữ system-ui hiện có nhiều chế độ cài đặt biến số hơn: kích thước quang học và 2 chế độ điều chỉnh độ đậm riêng biệt:

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
  ;
}

Trên Mojave, system-ui là một phông chữ có thể thay đổi và chỉ có chế độ cài đặt wght. Trong khi system-ui trên Catalina là một phông chữ biến đổi với các chế độ cài đặt wght, opsz, GRADYAXS.

Có vẻ như tôi có một số cơ hội thiết kế nâng cao tăng dần! Bạn có thể tìm hiểu kỹ hơn về các điểm tinh tế của phông chữ hệ thống nếu muốn.

wght

Chấp nhận độ đậm phông chữ từ 0 đến 900 và được áp dụng cho tất cả các ký tự.

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

opsz

Định cỡ bằng mắt tương tự như kerning hoặc khoảng cách giữa các chữ cái, nhưng khoảng cách được thực hiện bằng mắt người thay vì bằng toán học. Giá trị 19 trở xuống dành cho khoảng cách giữa văn bản và nội dung, trong khi 20 trở lên dành cho khoảng cách giữa tiêu đề và tên hiển thị.

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

GRAD

Tương tự như trọng số, nhưng không ảnh hưởng đến khoảng cách ngang. Trường này chấp nhận các giá trị từ 400 đến 1000.

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

YAXS

Kéo dài glyph theo chiều dọc. Trường này chấp nhận các giá trị từ 400 đến 1000.

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

Kết hợp các lựa chọn

Với một vài dòng CSS, chúng ta có thể điều chỉnh chế độ cài đặt phông chữ thành một kiểu chữ in đậm mà chúng ta chọn hoặc thử các tổ hợp thú vị khác:

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

Và thế là người dùng Chromium trên macOS sẽ thấy phiên bản tuỳ chỉnh được nâng cấp với trọng số 750 cùng một số điểm điều chỉnh thú vị khác 👍

macOS 10.15 đã thêm các tính năng mới vào phông chữ hệ thống và trong macOS 10.15, một lỗi system-ui phức tạp đã được ghi lại trong trình theo dõi lỗi của Chromium. Tôi tự hỏi liệu chúng có liên quan đến nhau không!?

Phụ lục: Phép hồi quy system-ui

Câu chuyện này bắt đầu bằng một lỗi khác: #1005969. Vấn đề này được báo cáo trên macOS 10.15 vì khoảng cách phông chữ system-ui trông hẹp và chật chội.

So sánh hai đoạn văn trên một trang nhóm Facebook. Bên trái là Chrome và bên phải là Safari, Chrome có khoảng cách nhỏ hơn một chút
Chrome ở bên trái (theo dõi chặt chẽ hơn), Safari ở bên phải (khoảng cách quang học tốt hơn)

Thông tin khái quát

Bạn có bao giờ nhận thấy trên macOS 10.14, các đoạn văn hoặc tiêu đề của bạn "chụp" vào một phông chữ có giao diện khác khi kích thước tăng hoặc giảm không?

Trên Mojave (macOS 10.14), phông chữ system-ui chuyển đổi giữa hai phông chữ tuỳ thuộc vào cỡ chữ mục tiêu. Khi văn bản nằm trong 20px, macOS sẽ dùng phông chữ "San Francisco Text". Khi văn bản có kích thước 20px trở lên, macOS sẽ dùng "San Francisco Display". Tính năng định cỡ quang học được tích hợp tĩnh vào 2 phông chữ riêng biệt.

Catalina (macOS 10.15) đã phát hành một phông chữ đa dạng mới, hợp nhất cho San Francisco. Không cần quản lý "Văn bản" và "Hiển thị" nữa. Nó cũng có chế độ cài đặt biến thể mới opsz như mô tả ở trên.

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

Rất tiếc, giá trị opsz mặc định trong phông chữ Catalina mới là 20 và các kỹ sư Chromium chưa chuẩn bị sẵn sàng để áp dụng opsz cho phông chữ hệ thống. Điều này dẫn đến việc các kích thước nhỏ hơn hiển thị quá hẹp.

Để khắc phục vấn đề đó, Chromium cần áp dụng opsz một cách chính xác cho phông chữ hệ thống. Điều này dẫn đến việc Vấn đề #1005969 được khắc phục. Chiến thắng! Hay là…?

Chưa xong

Đây là lúc mọi chuyện trở nên phức tạp: Chromium đã áp dụng opsz nhưng vẫn có gì đó không ổn. Phông chữ hệ thống trên máy Mac có thêm một bảng phông chữ được gọi là trak, giúp điều chỉnh khoảng cách theo chiều ngang. Trong khi khắc phục, các kỹ sư Chromium nhận thấy rằng trên macOS, khi truy xuất các chỉ số ngang từ một đối tượng CTFontRef, các chỉ số trak đã được đưa vào kết quả chỉ số. Thư viện tạo hình HarfBuzz của Chromium cần các chỉ số mà giá trị trak chưa được tính đến.

Màn hình hiển thị giao diện người dùng hệ thống và tất cả các trọng số cũng như biến thể phông chữ của giao diện này trong một danh sách. Một nửa trong số đó không có sự khác biệt về trọng lượng.
Bên trái: Độ đậm được áp dụng cho cỡ chữ từ 19 trở xuống. Bên phải: Cỡ chữ từ 20 trở lên sẽ mất kiểu chữ in đậm

Về nội bộ, Skia (thư viện đồ hoạ, không phải kiểu chữ có cùng tên) sử dụng cả lớp CGFontRef từ CoreGraphics và lớp CTFontRef từ CoreText. Do các lượt chuyển đổi nội bộ bắt buộc giữa những đối tượng đó (được dùng để duy trì khả năng tương thích ngược và truy cập vào các API cần thiết trên cả hai lớp), Skia sẽ mất thông tin về trọng lượng trong một số trường hợp và các phông chữ in đậm sẽ ngừng hoạt động. Vấn đề này đã được theo dõi trong Vấn đề #1057654.

Skia vẫn cần hỗ trợ macOS 10.11 vì Chromium vẫn hỗ trợ hệ điều hành này. Trên phiên bản 10.11, phông chữ "San Francisco Text" và "San Francisco Display" thậm chí còn không phải là phông chữ có thể thay đổi. Thay vào đó, mỗi kiểu chữ là một nhóm gồm các phông chữ riêng biệt cho mọi độ đậm có sẵn. Đến một thời điểm nào đó, mã nhận dạng glyph của chúng không còn đồng bộ với nhau. Vì vậy, nếu Skia định hình văn bản (chuyển đổi văn bản thành các glyph có thể vẽ) bằng "San Francisco Text", thì văn bản đó sẽ trở nên vô nghĩa nếu được vẽ bằng "San Francisco Display" và ngược lại. Ngay cả khi Skia chỉ yêu cầu một kích thước khác, macOS có thể chuyển sang kích thước khác. Bạn có thể luôn sử dụng một trong các phông chữ và chỉ cần điều chỉnh tỷ lệ (sử dụng ma trận để tăng tỷ lệ thay vì yêu cầu kích thước lớn hơn) nhưng CoreText có một vấn đề là nó sẽ không tăng tỷ lệ các glyph sbix (biểu tượng cảm xúc có màu) (chỉ giảm tỷ lệ). Quy trình này phức tạp hơn một chút. CoreText dường như giới hạn phạm vi theo chiều dọc sau khi áp dụng ma trận. Điều này có vẻ như liên quan đến việc không thể vẽ biểu tượng cảm xúc ở góc 45 độ. Trong mọi trường hợp, nếu muốn biểu tượng cảm xúc của mình xuất hiện ở kích thước lớn, bạn cần sao chép phông chữ để có được phiên bản lớn.

Vì vậy, để tạo bản sao của các đối tượng CTFont ở nhiều kích thước khác nhau trong nội bộ trong khi vẫn đảm bảo sử dụng cùng một dữ liệu phông chữ cơ bản, Chromium đã kéo CGFont ra khỏi CTFont, sau đó tạo một CTFont mới từ CGFont (các đối tượng CGFont không phụ thuộc vào kích thước, quá trình chuyển đổi kỳ diệu diễn ra ở cấp CoreText). Điều này vẫn ổn cho đến phiên bản 10.154. Trong 10.15, chuyến đi khứ hồi này đã làm mất quá nhiều thông tin, dẫn đến vấn đề về trọng lượng. Flutter nhận thấy vấn đề về trọng lượng và đã đưa ra một giải pháp thay thế để đổi kích thước nhằm tạo CTFont mới trực tiếp từ CTFont ban đầu trong khi kiểm soát kích thước quang học trực tiếp bằng cách sử dụng một thuộc tính cũ nhưng không được ghi lại trong CoreText. Điều này giúp mọi thứ hoạt động trên phiên bản 10.11 và khắc phục các vấn đề khác (chẳng hạn như đặt kích thước quang học thành giá trị mặc định một cách rõ ràng).

Tuy nhiên, cách này sẽ giữ lại nhiều "phép màu" CoreText hơn trong phông chữ. Một trong những lý do có vẻ là do Chrome vẫn điều chỉnh khoảng cách giữa các glyph theo cách nào đó ngoài bảng trak (Chromium đã cố gắng ngăn chặn việc áp dụng bảng này thông qua một thuộc tính khác chưa được ghi lại).

CGFont không thực hiện bất kỳ "phép màu" nào trong số này, vì vậy có thể Chromium sẽ loại bỏ CGFont khỏi CTFont và chỉ dùng nó để nhận các tính năng nâng cao? Rất tiếc, cách này sẽ không hiệu quả vì CoreText cũng có thể gây ra các vấn đề khác về phông chữ. Ví dụ: tính năng này sẽ làm cho biểu tượng cảm xúc nhỏ lớn hơn một chút so với kích thước bạn yêu cầu (tăng kích thước của biểu tượng cảm xúc lên một chút). CGFont không biết về điều này, vì vậy, biểu tượng cảm xúc dựa trên sbix của bạn sẽ quá gần nhau vì bạn sẽ đo ở một kích thước nhưng CoreText sẽ vẽ chúng lớn hơn một chút. Chromium muốn có những tiến bộ CTFont, nhưng không muốn bị theo dõi và tốt nhất là không muốn có bất kỳ sự can thiệp nào khác.

Vì bản sửa lỗi cho vấn đề về khoảng cách yêu cầu một bộ các bản sửa lỗi Blink và Skia được kết nối với nhau, nên các kỹ sư Chromium không thể "chỉ cần quay lại" để khắc phục vấn đề. Các kỹ sư Chromium cũng đã thử sử dụng một cờ bản dựng khác để thay đổi đường dẫn mã liên quan đến phông chữ trong Skia. Cách này đã khắc phục được vấn đề về phông chữ in đậm, nhưng lại gây ra vấn đề về khoảng cách.

Cách khắc phục

Cuối cùng, tất nhiên Chromium muốn khắc phục cả hai vấn đề này. Giờ đây, Chromium sẽ sử dụng các hàm chỉ số phông chữ OpenType tích hợp sẵn của HarfBuzz để truy xuất chỉ số ngang trực tiếp từ dữ liệu nhị phân trong bảng phông chữ của phông chữ hệ thống. Bằng cách này, Chromium sẽ bỏ qua CoreText và Skia khi phông chữ có bảng trak (trừ khi đó là phông chữ biểu tượng cảm xúc).

Màn hình hiển thị giao diện người dùng hệ thống và tất cả các trọng số cũng như biến thể phông chữ của giao diện này trong một danh sách. Nửa màn hình trước đây không hoạt động hiện trông rất đẹp.

Trong thời gian chờ đợi, vẫn còn Vấn đề về Skia #10123 cần theo dõi để khắc phục hoàn toàn vấn đề này trong Skia, đồng thời quay lại sử dụng Skia để truy xuất các chỉ số phông chữ hệ thống từ đó, thay vì bản sửa lỗi hiện tại thông qua HarfBuzz.