ตัวเลือกแบบอักษรตัวแปรเพิ่มเติมสำหรับแบบอักษร UI ระบบ macOS ใน Chromium 83

Catalina จะนำแบบอักษรระบบแบบแปรผันแบบใหม่มาสู่ macOS

ส่วน "system-ui" ของข้อกำหนดระดับ 4 ของโมดูลแบบอักษร CSS จะกำหนดคีย์เวิร์ดแบบอักษร system-ui ซึ่งช่วยให้นักพัฒนาซอฟต์แวร์ใช้แบบอักษรของระบบปฏิบัติการเริ่มต้นที่มีคุณภาพสูงมาก แปลเป็นภาษาท้องถิ่น เพิ่มประสิทธิภาพให้เร็วขึ้นแบบทันใจ และไม่ต้องดาวน์โหลดในเว็บไซต์และแอปได้

body {
  font-family: system-ui;
}

ตัวเลือกการจัดรูปแบบตัวอักษรนี้คล้ายกับ "ใช้แบบอักษรเริ่มต้นของระบบสำหรับภาษาปัจจุบันของผู้ใช้รายนี้"

ใน macOS แบบอักษร system-ui คือ San Francisco ซึ่งเป็นแบบอักษรที่ทีมออกแบบได้ตรวจสอบ ทดสอบ และ… อัปเกรดไปเมื่อเร็วๆ นี้ ก่อนอื่น เราจะพูดถึงฟีเจอร์แบบอักษรแบบแปรผันที่น่าตื่นเต้นใหม่ใน Catalina จากนั้นจะพูดถึงข้อบกพร่อง 2 ข้อและวิธีที่วิศวกร Chromium แก้ไขปัญหา

โพสต์นี้ถือว่าคุณคุ้นเคยกับแบบอักษรแบบผันอยู่แล้ว หากยังไม่คุ้นเคย โปรดดูข้อมูลเบื้องต้นเกี่ยวกับแบบอักษรแบบแปรผันในเว็บและวิดีโอด้านล่าง

ความเข้ากันได้กับเบราว์เซอร์

ขณะเขียนบทความนี้ system-ui ได้รับการสนับสนุนจาก Chromium (ตั้งแต่เวอร์ชัน 56), Edge (ตั้งแต่เวอร์ชัน 79), Safari (ตั้งแต่เวอร์ชัน 11) และ Firefox (ตั้งแต่เวอร์ชัน 43) โดยใช้คีย์เวิร์ด -apple-system ดูการอัปเดตที่หัวข้อฉันจะใช้แบบอักษรที่หลากหลายได้ไหม

ความสามารถใหม่

ความสามารถใหม่ๆ ที่ Catalina นำมาสู่แบบอักษรของระบบพร้อมให้นักพัฒนาเว็บใช้งานแล้วใน Chromium เวอร์ชัน 83 ตอนนี้แบบอักษร system-ui มีการตั้งค่าแบบปรับเปลี่ยนได้มากขึ้น ได้แก่ การปรับขนาดแบบออปติคอลและการปรับน้ำหนัก 2 แบบที่ไม่ซ้ำกัน ดังนี้

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

ใน Mojave system-ui เป็นแบบอักษรที่เปลี่ยนแปลงได้ที่มีการตั้งค่า wght เท่านั้น ส่วน system-ui ใน Catalina จะเป็นแบบอักษรตัวแปรที่มีการตั้งค่า wght, opsz, GRAD และ YAXS

ดูเหมือนว่าฉันจะได้รับโอกาสในการออกแบบการเพิ่มประสิทธิภาพแบบต่อเนื่องที่ดีมากๆ เจาะลึกรายละเอียดเล็กๆ น้อยๆ ของแบบอักษรของระบบได้หากต้องการ

wght

ยอมรับน้ำหนักแบบอักษรระหว่าง 0 ถึง 900 และใช้กับอักขระทั้งหมดอย่างเท่าเทียมกัน

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

opsz

การปรับขนาดแบบออปติคอลคล้ายกับการปรับระยะห่างแบบตัวยึดหรือระยะห่างระหว่างตัวอักษร แต่ระยะห่างจะกำหนดโดยสายตามนุษย์แทนการคำนวณทางคณิตศาสตร์ ค่า 19 หรือต่ำกว่ามีไว้สำหรับการเว้นระยะห่างระหว่างข้อความและเนื้อหา ส่วนค่าตั้งแต่ 20 ขึ้นไปมีไว้สำหรับการเว้นระยะห่างระหว่างส่วนหัวและชื่อในการแสดง

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

GRAD

คล้ายกับน้ำหนัก แต่จะไม่เกี่ยวข้องกับระยะห่างแนวนอน และยอมรับค่าระหว่าง 400 ถึง 1000

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

YAXS

ยืดรูปอักขระในแนวตั้ง ค่าที่ใช้ได้คือระหว่าง 400 ถึง 1000

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

การรวมตัวเลือก

เราสามารถปรับแต่งการตั้งค่าแบบอักษรให้เป็นแบบหนาหรือลองใช้ชุดค่าผสมอื่นๆ ที่น่าสนใจได้โดยใช้ CSS เพียงไม่กี่บรรทัด ดังนี้

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

เพียงเท่านี้ ผู้ใช้ Chromium ใน macOS ก็จะเห็นน้ำหนัก 750 ที่อัปเกรดและปรับแต่งเองพร้อมการปรับแต่งอื่นๆ ที่น่าสนใจ 👍

สนามเด็กเล่น

คลิกรีมิกซ์เพื่อแก้ไขใน Glitch ด้านล่างเพื่อรับสำเนา Glitch ที่แก้ไขได้ จากนั้นแก้ไขตัวเลือก font-variation-settings ใหม่เพื่อดูว่าตัวเลือกดังกล่าวส่งผลต่อแบบอักษรอย่างไร โปรดทราบว่า Glitch นี้จะทำงานได้เมื่อคุณใช้อุปกรณ์ macOS Catalina เท่านั้น

macOS 10.15 เพิ่มฟีเจอร์ใหม่ในแบบอักษรของระบบ และใน macOS 10.15 มีการบันทึกข้อบกพร่อง system-ui ที่ยุ่งยากไว้ในเครื่องมือติดตามข้อบกพร่องของ Chromium สงสัยว่าเกี่ยวข้องกันไหม

ภาคผนวก: การถดถอย system-ui

เรื่องราวนี้เริ่มต้นด้วยข้อบกพร่องอื่น: #1005969 มีการรายงานปัญหานี้ใน macOS 10.15 เนื่องจากระยะห่างแบบอักษร system-ui ดูแคบและคับแน่น

การเปรียบเทียบย่อหน้า 2 ย่อหน้าจากหน้ากลุ่ม Facebook ทางด้านซ้ายคือ Chrome และทางด้านขวาคือ Safari โดย Chrome มีการเว้นวรรคที่น้อยลงเล็กน้อย
Chrome ทางด้านซ้าย (การติดตามที่แน่นกว่า) และ Safari ทางด้านขวา (ระยะห่างของตัวอักษรที่ดีกว่า)

ข้อมูลเบื้องต้น

คุณเคยสังเกตไหมว่าใน macOS 10.14 ย่อหน้าหรือส่วนหัวจะ "เปลี่ยน" เป็นแบบอักษรที่ดูแตกต่างออกไปเมื่อปรับขนาดขึ้นหรือลง

ใน Mojave (macOS 10.14) แบบอักษร system-ui จะสลับระหว่าง 2 แบบอักษรโดยขึ้นอยู่กับขนาดแบบอักษรเป้าหมาย เมื่อข้อความต่ำกว่า 20px ระบบของ macOS จะใช้ "San Francisco Text" เมื่อข้อความมีขนาดใหญ่กว่าหรือเท่ากับ 20px ขึ้นไป macOS จะใช้ "San Francisco Display" การปรับขนาดแบบออปติคอลสร้างขึ้นแบบคงที่ในแบบอักษร 2 แบบแยกกัน

Catalina (macOS 10.15) มาพร้อมกับแบบอักษร San Francisco แบบอักษรที่ปรับเปลี่ยนได้ในแบบรวมใหม่ ไม่ต้องจัดการ "ข้อความ" และ "การแสดงผล" อีกต่อไป รวมถึงได้การตั้งค่ารูปแบบใหม่ opsz ที่อธิบายไว้ก่อนหน้านี้ด้วย

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

ขออภัย ค่า opsz เริ่มต้นในแบบอักษร Catalina ใหม่คือ 20 และวิศวกร Chromium ยังไม่พร้อมที่จะใช้ opsz กับแบบอักษรของระบบ ซึ่งทำให้ขนาดที่เล็กกว่าแสดงผลแคบเกินไป

Chromium จึงต้องนำ opsz ไปใช้กับแบบอักษรของระบบอย่างถูกต้องเพื่อแก้ไขปัญหานี้ ซึ่งทำให้ปัญหา #1005969 ได้รับการแก้ไข ชนะเลิศ! หรือเป็น…

ยังไม่เสร็จ

ปัญหานี้ค่อนข้างซับซ้อน Chromium ใช้ opsz แล้ว แต่บางอย่างยังไม่ถูกต้อง แบบอักษรของระบบใน Mac จะมีตารางแบบอักษรเพิ่มเติมชื่อว่า trak ซึ่งจะปรับเปลี่ยนระยะห่างแนวนอน ขณะหาวิธีแก้ไข ทีมวิศวกร Chromium สังเกตเห็นว่าใน macOS เมื่อดึงข้อมูลเมตริกแนวนอนจากออบเจ็กต์ CTFontRef ระบบจะรวมเมตริก trak ไว้ในผลลัพธ์ของเมตริกอยู่แล้ว คลังการจัดรูปแบบ HarfBuzz ของ Chromium ต้องใช้เมตริกที่ยังไม่ได้รวมค่า trak

การแสดง system-ui และน้ำหนักและรูปแบบแบบอักษรทั้งหมดในรายการ ครึ่งหนึ่งไม่มีการใช้น้ำหนักที่แตกต่างกัน
ซ้าย: น้ำหนักแบบหนาที่ใช้กับแบบอักษรขนาด 19 ลงมา ขวา: ขนาดแบบอักษร 20 ขึ้นไปจะไม่มีการจัดรูปแบบตัวหนา

ภายใน Skia (ไลบรารีกราฟิก ไม่ใช่แบบอักษรที่มีชื่อเดียวกัน) ใช้ทั้งคลาส CGFontRef จาก CoreGraphics และคลาส CTFontRef จาก CoreText เนื่องจากต้องแปลงภายในระหว่างออบเจ็กต์เหล่านี้ (ใช้เพื่อรักษาความเข้ากันได้แบบย้อนหลังและการเข้าถึง API ที่จำเป็นในทั้ง 2 คลาส) Skia จะลดข้อมูลน้ำหนักในบางสถานการณ์ และแบบอักษรตัวหนาจะหยุดทำงาน ปัญหานี้ได้รับการติดตามในปัญหา #1057654

Skia ยังต้องรองรับ macOS 10.11 เนื่องจาก Chromium ยังคงรองรับอยู่ ใน 10.11 แบบอักษร "San Francisco Text" และ "San Francisco Display" ยังไม่มีแบบอักษรที่หลากหลาย แต่แต่ละแบบเป็นตระกูลแบบอักษรที่แยกจากกันสำหรับน้ำหนักแต่ละแบบ บางครั้งรหัสรูปอักขระกลับไม่ตรงกัน ดังนั้นหาก Skia ทำการขึ้นรูปข้อความ (แปลงข้อความเป็นอักขระที่สามารถวาดได้) ด้วย "San Francisco Text" ข้อความจะกลายเป็นคำที่ไม่มีความหมายหากวาดด้วย "San Francisco Display" และในทางกลับกัน และแม้ว่า Skia จะขอขนาดอื่น macOS ก็อาจเปลี่ยนไปใช้ขนาดอื่น คุณควรใช้แบบอักษรอย่างใดอย่างหนึ่งเสมอและปรับขนาด (โดยใช้เมทริกซ์เพื่อปรับขนาดขึ้นแทนที่จะขอขนาดที่ใหญ่ขึ้น) แต่ CoreText มีปัญหาที่ไม่ยอมปรับขนาดแบบอักษร sbix (อีโมจิสี) ขึ้น (ปรับขนาดลงได้เท่านั้น) ซับซ้อนกว่านั้นเล็กน้อย ดูเหมือนว่า CoreText จะจำกัดขอบเขตแนวตั้งหลังจากการใช้เมทริกซ์ ซึ่งดูเหมือนว่าจะเกี่ยวข้องกับการวาดอีโมจิในมุม 45 องศาไม่ได้ ไม่ว่าในกรณีใดก็ตาม หากต้องการให้อีโมจิแสดงขนาดใหญ่ คุณต้องคัดลอกแบบอักษรเพื่อรับเวอร์ชันขนาดใหญ่

ดังนั้นในการสร้างสำเนาของออบเจ็กต์ CTFont ขนาดต่างๆ ภายในขณะที่ใช้ข้อมูลแบบอักษรเดียวกัน Chromium จึงดึง CGFont ออกจาก CTFont แล้วสร้าง CTFont ใหม่จาก CGFont (ออบเจ็กต์ CGFont นั้นไม่ขึ้นอยู่กับขนาด การเปลี่ยนที่ยอดเยี่ยมนี้เกิดขึ้นที่ระดับ CoreText) การดำเนินการนี้ใช้งานได้ดีจนถึง 10.154 ส่วนในเวลา 10.15 น. เที่ยวบินไปกลับนี้สูญเสียข้อมูลมากเกินไป ซึ่งก่อให้เกิดปัญหาเรื่องน้ำหนัก Flutter พบปัญหาเกี่ยวกับน้ำหนักและทำการแก้ไขทางเลือกสำหรับการปรับขนาดเพื่อสร้าง CTFont ใหม่จาก CTFont เดิมโดยตรง ขณะควบคุมขนาดแบบออปติคอลโดยตรงโดยใช้แอตทริบิวต์เก่าที่ไม่ได้บันทึกไว้ใน CoreText วิธีนี้จะช่วยให้ทุกอย่างทำงานได้บน 10.11 และแก้ไขปัญหาอื่นๆ (เช่น การตั้งค่าขนาดออปติคอลเป็นค่าเริ่มต้นอย่างชัดเจน)

อย่างไรก็ตาม วิธีนี้จะช่วยรักษา "ความมหัศจรรย์" ของ CoreText ในแบบอักษรได้มากกว่า หนึ่งในนั้นดูเหมือนว่ายังคงปรับระยะห่างของสัญลักษณ์ในลักษณะอื่นนอกเหนือจากตาราง trak (แอปพลิเคชันที่ Chromium พยายามปิดใช้ผ่านแอตทริบิวต์ที่ไม่มีเอกสารประกอบอีกรายการหนึ่ง)

CGFont ไม่ได้ทํา "เวทมนตร์" ใดๆ เลย Chromium อาจนํา CGFont ออกจาก CTFont และใช้เพื่อรับค่าล่วงหน้าได้ไหม แต่น่าเสียดายที่วิธีนี้ใช้ไม่ได้เนื่องจาก CoreText เป็นที่รู้จักกันว่ามีการแทรกแซงแบบอักษรด้วยวิธีอื่นๆ ด้วย เช่น จะทำให้อีโมจิขนาดเล็กใหญ่กว่าที่คุณขอเล็กน้อย (เพิ่มขนาดขึ้นเล็กน้อย) CGFont ไม่รู้เรื่องนี้ คุณจึงอาจพบว่าอีโมจิที่ใช้ sbix อยู่ใกล้กันเกินไป เนื่องจากคุณวัดขนาดเป็นขนาดเดียว แต่ CoreText จะวาดอีโมจิให้ใหญ่ขึ้นเล็กน้อย Chromium ต้องการความก้าวหน้าของ CTFont แต่ไม่ต้องการการติดตาม และโดยเฉพาะอย่างยิ่งโดยไม่มีการดัดแปลงใดๆ

เนื่องจากการแก้ไขปัญหาการเว้นวรรคต้องใช้ชุดการแก้ไข Blink และ Skia ที่เชื่อมต่อกัน วิศวกร Chromium ไม่สามารถ "เปลี่ยนกลับ" เพื่อแก้ปัญหาได้ วิศวกร Chromium ยังลองใช้ Flag การสร้างแบบอื่นเพื่อเปลี่ยนเส้นทางโค้ดที่เกี่ยวข้องกับแบบอักษรใน Skia ซึ่งแก้ไขปัญหาแบบอักษรหนาได้ แต่กลับทำให้ปัญหาการเว้นวรรคแย่ลง

การแก้ไข

ท้ายที่สุดแล้ว Chromium ต้องการแก้ไขปัญหาทั้ง 2 อย่าง ตอนนี้ Chromium เปลี่ยนไปใช้ฟังก์ชันเมตริกแบบอักษร OpenType แบบอักษรในตัวของ HarfBuzz ในการดึงข้อมูลเมตริกแนวนอนจากข้อมูลไบนารีในตารางแบบอักษรของระบบโดยตรง เมื่อใช้วิธีนี้ Chromium จะหลีกเลี่ยง CoreText และ Skia เมื่อแบบอักษรมีตาราง trak (ยกเว้นในกรณีที่เป็นแบบอักษรอีโมจิ)

การแสดง system-ui และน้ำหนักและรูปแบบแบบอักษรทั้งหมดในรายการ ส่วนครึ่งที่ก่อนหน้านี้ไม่ทำงานตอนนี้ดูดีมาก

ในระหว่างนี้ โปรดติดตามปัญหา #10123 ของ Skia เพื่อติดตามการแก้ไขปัญหานี้อย่างสมบูรณ์ใน Skia และกลับไปใช้ Skia เพื่อดึงข้อมูลเมตริกแบบอักษรของระบบจาก Skia แทนการแก้ไขปัจจุบันที่ดำเนินการผ่าน HarfBuzz