Sử dụng kiểu chữ nâng cao với phông chữ trên máy

Tìm hiểu cách Local Font Access API cho phép bạn truy cập vào phông chữ được cài đặt trên máy của người dùng và nhận thông tin cấp thấp về phông chữ đó

Phông chữ an toàn trên web

Nếu đã làm phát triển web đủ lâu, bạn có thể nhớ cái gọi là phông chữ an toàn trên web. Những phông chữ này được xác định là hoạt động trên hầu hết các phiên bản của các hệ điều hành được sử dụng nhiều nhất (cụ thể là Windows, macOS, các bản phân phối Linux phổ biến nhất, Android và iOS). Vào đầu những năm 2000, Microsoft thậm chí còn khởi đầu một sáng kiến có tên là phông chữ cốt lõi TrueType cho Web. Các phông chữ này cung cấp cho người dùng tải xuống miễn phí bằng rằng "bất cứ khi nào bạn truy cập vào một trang Web xác định trang web, bạn sẽ thấy chính xác các trang nhà thiết kế trang web của bạn". Có, danh sách trang web được bao gồm trong Comic Sans MS. Dưới đây là ngăn xếp phông chữ an toàn trên web cổ điển (với tính năng dự phòng cuối cùng là bất kỳ sans-serif ) có thể có dạng như sau:

body {
  font-family: Helvetica, Arial, sans-serif;
}

Phông chữ trên web

Thời kỳ mà phông chữ an toàn trên web thực sự quan trọng đã qua lâu. Hôm nay, chúng tôi có phông chữ trên web, một số phông chữ thậm chí là cả phông chữ biến mà chúng ta có thể tinh chỉnh thêm bằng cách thay đổi các giá trị cho biến các trục khác nhau. Bạn có thể sử dụng phông chữ trên web bằng cách khai báo chặn @font-face ở đầu CSS, Mã này chỉ định(các) tệp phông chữ cần tải xuống:

@font-face {
  font-family: 'FlamboyantSansSerif';
  src: url('flamboyant.woff2');
}

Sau đó, bạn có thể sử dụng phông chữ tuỳ chỉnh trên web bằng cách chỉ định font-family, như bình thường:

body {
  font-family: 'FlamboyantSansSerif';
}

Phông chữ trên máy dưới dạng vectơ vân tay

Hầu hết phông chữ trên web đều bắt nguồn từ web. Tuy nhiên, một thực tế thú vị là Thuộc tính src trong @font-face ngoài việc khai báo url() cũng chấp nhận một local() . Điều này cho phép tải phông chữ tuỳ chỉnh (ngạc nhiên!) cục bộ. Nếu người dùng tình cờ phải FlamboyantSansSerif được cài đặt trên hệ điều hành của họ, bản sao cục bộ sẽ được sử dụng thay vì nội dung đó đang được tải xuống:

@font-face {
  font-family: 'FlamboyantSansSerif';
  src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}

Phương pháp này cung cấp cơ chế dự phòng hữu ích có thể giúp tiết kiệm băng thông. Trên Internet, rất tiếc là chúng ta không thể có những điều tốt đẹp. Vấn đề với hàm local() là nó có thể bị lạm dụng để tạo vân tay số của trình duyệt. Hoá ra, danh sách các phông chữ mà người dùng đã cài đặt có thể rất đẹp xác định danh tính. Nhiều công ty có phông chữ riêng của công ty được cài đặt trên trình duyệt của nhân viên máy tính xách tay. Ví dụ: Google có phông chữ của công ty tên là Google Sans.

Ứng dụng Phông chữ trên macOS cho thấy bản xem trước của phông chữ Google Sans.
Phông chữ Google Sans được cài đặt trên máy tính xách tay của một nhân viên Google.

Kẻ tấn công có thể cố gắng xác định xem ai đó làm việc cho công ty nào bằng cách thử nghiệm sự tồn tại của số lượng lớn các phông chữ đã biết của công ty như Google Sans. Kẻ tấn công sẽ cố gắng kết xuất văn bản đặt bằng phông chữ này trên canvas và đo các ký tự. Nếu các ký tự khớp với hình dạng đã biết của của công ty, kẻ tấn công có một lần tấn công. Nếu các ký tự không khớp, kẻ tấn công biết rằng phông chữ thay thế mặc định đã được sử dụng vì phông chữ của công ty chưa được cài đặt. Để biết toàn bộ thông tin chi tiết về cuộc tấn công này và các cuộc tấn công khác bằng vân tay số của trình duyệt, hãy đọc bài khảo sát của Laperdix et al.

Phông chữ của công ty riêng biệt, thậm chí chỉ cần danh sách các phông chữ đã cài đặt cũng có thể được xác định. Tình huống với vectơ tấn công này trở nên tồi tệ đến mức gần đây nhóm WebKit đã quyết định "chỉ bao gồm [trong danh sách phông chữ có sẵn] phông chữ và phông chữ web đi kèm với thao tác hệ thống, nhưng không phải phông chữ do người dùng cài đặt trên máy". (Và tôi đang ở đây, với bài viết về việc cấp quyền truy cập thành phông chữ trên máy).

Local Font Access API (API Truy cập phông chữ cục bộ)

Phần đầu của bài viết này có thể đã khiến bạn có tâm trạng tiêu cực. Chúng ta có thể không vui không? Đừng lo. Chúng tôi cho rằng mình có thể, và có lẽ mọi thứ chẳng phải là vô vọng. Nhưng trước tiên, hãy để tôi trả lời một câu hỏi mà có thể bạn đang tự hỏi.

Tại sao chúng ta cần API Truy cập phông chữ cục bộ khi có phông chữ trên web?

Các công cụ đồ hoạ và thiết kế chất lượng chuyên nghiệp trước đây vẫn khó cung cấp trên web. Một vướng mắc là không thể tiếp cận và sử dụng toàn bộ các phông chữ được tạo và gợi ý mà nhà thiết kế đã cài đặt trên máy. Phông chữ trên web cho phép xuất bản một số nội dung trường hợp sử dụng, nhưng không cho phép truy cập có lập trình vào các hình dạng ký tự vectơ và bảng phông chữ được sử dụng bởi trình tạo điểm ảnh để kết xuất đường viền ký tự. Tương tự như vậy, không có cách nào để truy cập vào tệp nhị phân của phông chữ trên web .

  • Các công cụ thiết kế cần quyền truy cập vào các byte phông chữ để triển khai bố cục OpenType riêng và cho phép các công cụ thiết kế để bắt đầu ở mức thấp hơn, cho các hành động như thực hiện bộ lọc vectơ hoặc biến đổi trên các hình dạng ký tự.
  • Nhà phát triển có thể sử dụng các ngăn xếp phông chữ cũ cho ứng dụng mà họ đưa lên web. Để sử dụng các ngăn xếp này, chúng thường yêu cầu quyền truy cập trực tiếp vào dữ liệu phông chữ, điều mà phông chữ trên web không làm được cung cấp.
  • Một số phông chữ có thể không được cấp phép để phân phối qua web. Ví dụ: Linotype có giấy phép cho một số phông chữ chỉ sử dụng trên máy tính.

Local Font Access API là một nỗ lực nhằm giải quyết những thách thức này. Nó bao gồm hai phần:

  • API liệt kê phông chữ, cho phép người dùng cấp quyền truy cập vào toàn bộ hệ thống hiện có phông chữ.
  • Từ mỗi kết quả liệt kê, khả năng yêu cầu vùng chứa SFNT cấp thấp (định hướng byte) quyền truy cập bao gồm toàn bộ dữ liệu phông chữ.

Hỗ trợ trình duyệt

Hỗ trợ trình duyệt

  • Chrome: 103.
  • Cạnh: 103.
  • Firefox: không được hỗ trợ.
  • Safari: không được hỗ trợ.

Nguồn

Cách sử dụng Local Font Access API (API Truy cập phông chữ cục bộ)

Phát hiện tính năng

Để kiểm tra xem Local Font Access API có được hỗ trợ hay không, hãy sử dụng:

if ('queryLocalFonts' in window) {
  // The Local Font Access API is supported
}

Liệt kê phông chữ trên máy

Để lấy danh sách các phông chữ đã cài đặt cục bộ, bạn cần gọi window.queryLocalFonts(). Chiến lược phát hành đĩa đơn lần đầu tiên, thao tác này sẽ kích hoạt lời nhắc cấp quyền mà người dùng có thể phê duyệt hoặc từ chối. Nếu người dùng phê duyệt phông chữ trên máy cần truy vấn, trình duyệt sẽ trả về một mảng có dữ liệu phông chữ mà bạn có thể lặp lại. Mỗi phông chữ được biểu thị dưới dạng một đối tượng FontData với các thuộc tính family (ví dụ: "Comic Sans MS"), fullName (ví dụ: "Comic Sans MS"), postscriptName (ví dụ: ví dụ "ComicSansMS") và style (ví dụ: "Regular").

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

Nếu chỉ quan tâm đến một số phông chữ, bạn cũng có thể lọc các phông chữ đó dựa trên tệp PostScript bằng cách thêm tham số postscriptNames.

const availableFonts = await window.queryLocalFonts({
  postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});

Truy cập dữ liệu SFNT

Bạn có thể truy cập đầy đủ SFNT thông qua phương thức blob() của Đối tượng FontData. SFNT là định dạng tệp phông chữ có thể chứa các phông chữ khác như PostScript, TrueType, OpenType, Phông chữ Định dạng phông chữ Mở trên web (WOFF) và các phông chữ khác.

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

Bản minh hoạ

Bạn có thể xem cách Local Font Access API hoạt động trong bản minh hoạ bên dưới. Hãy nhớ xem mã nguồn. Bản minh hoạ hiển thị một phần tử tuỳ chỉnh có tên <font-select> triển khai bộ chọn phông chữ cục bộ.

Những điều cần cân nhắc về quyền riêng tư

Quyền "local-fonts" dường như cung cấp một nền tảng có khả năng tạo vân tay số cao. Tuy nhiên, trình duyệt được miễn phí trả về bất kỳ nội dung nào họ muốn. Ví dụ: trình duyệt tập trung vào danh tính ẩn danh có thể chọn để chỉ cung cấp một bộ phông chữ mặc định được tích hợp sẵn vào trình duyệt. Tương tự, trình duyệt là không bắt buộc để cung cấp dữ liệu bảng chính xác như xuất hiện trên đĩa.

Bất cứ khi nào có thể, API Truy cập phông chữ cục bộ được thiết kế để chỉ hiển thị chính xác thông tin cần thiết để cung cấp các trường hợp sử dụng nêu trên. API hệ thống có thể tạo danh sách các phông chữ đã cài đặt không nằm trong một ngẫu nhiên hoặc được sắp xếp theo thứ tự cài đặt phông chữ. Trả về chính xác danh sách phông chữ đã cài đặt do API hệ thống cung cấp có thể làm lộ thêm dữ liệu dùng cho tạo vân tay số và các trường hợp sử dụng mà chúng ta muốn bật không được hỗ trợ bằng cách giữ lại thứ tự này. Là một kết quả, API này yêu cầu sắp xếp dữ liệu được trả về trước khi được trả về.

Tính bảo mật và quyền truy cập

Nhóm Chrome đã thiết kế và triển khai Local Font Access API theo các nguyên tắc cốt lõi được xác định trong Kiểm soát quyền truy cập vào các tính năng nền tảng web mạnh mẽ, bao gồm cả người dùng khả năng kiểm soát, tính minh bạch và tính công thái học.

Quyền kiểm soát của người dùng

Quyền truy cập vào phông chữ của người dùng hoàn toàn thuộc quyền kiểm soát của họ và sẽ không được cho phép trừ phi "local-fonts", như được liệt kê trong đăng ký quyền, đã được cấp.

Sự minh bạch

Liệu một trang web có được cấp quyền truy cập vào phông chữ trên máy của người dùng hay không sẽ xuất hiện trong trang thông tin trang web.

Khả năng lưu trữ cố định quyền

Quyền "local-fonts" sẽ được duy trì giữa các lần tải lại trang. Có thể thu hồi thông qua thông tin trang web.

Phản hồi

Nhóm Chrome muốn biết ý kiến của bạn về trải nghiệm của bạn với Local Font Access API (API Truy cập phông chữ cục bộ).

Cho chúng tôi biết về thiết kế API

Có điều gì về API không hoạt động như bạn mong đợi không? Hoặc có phương thức nào bị thiếu hoặc thuộc tính nào bạn cần để triển khai ý tưởng của mình? Có câu hỏi hoặc nhận xét về bảo mật mẫu? Báo cáo vấn đề về thông số kỹ thuật trên kho lưu trữ GitHub tương ứng hoặc thêm ý kiến của bạn vào một vấn đề hiện tại.

Báo cáo sự cố về triển khai

Bạn có phát hiện lỗi trong quá trình triển khai Chrome không? Hay cách triển khai có khác với thông số kỹ thuật không? Báo cáo lỗi tại new.crbug.com. Hãy nhớ cung cấp càng nhiều thông tin chi tiết càng tốt, các hướng dẫn đơn giản để tái tạo rồi nhập Blink>Storage>FontAccess vào hộp Components (Thành phần). Glitch rất hữu ích khi chia sẻ các bản dựng lại nhanh chóng và dễ dàng.

Hiện thông tin hỗ trợ về API này

Bạn có định sử dụng Local Font Access API (API Truy cập phông chữ cục bộ) không? Sự hỗ trợ công khai của bạn giúp nhóm Chrome ưu tiên các tính năng và cho các nhà cung cấp trình duyệt khác biết tầm quan trọng của việc hỗ trợ các tính năng đó.

Gửi một bài đăng đến @ChromiumDev kèm theo hashtag #LocalFontAccess rồi cho phép chúng tôi biết bạn đang sử dụng công cụ đó ở đâu và như thế nào.

Xác nhận

Thông số API Truy cập phông chữ cục bộ đã được chỉnh sửa bởi Emil A. Tiếng Eklund, Alex Russell, Joshua BellOlivier Yiptong. Bài viết này được đánh giá bởi Joe Medley thân mến! Dominik RöttschesOlivier Yiptong. Hình ảnh chính của Brett Jordan đang bật Không hiển thị màn hình.