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

Catalina นำแบบอักษรระบบแบบตัวแปรใหม่ที่รวมกันมาสู่ macOS

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

body {
  font-family: system-ui;
}

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

ใน macOS system-ui แบบอักษรคือ San Francisco ซึ่งเป็นแบบอักษรที่ทีมออกแบบตรวจสอบ ทดสอบ และ...เพิ่งอัปเกรด ก่อนอื่นเราจะพูดถึงฟีเจอร์ใหม่ที่น่าตื่นเต้นของแบบอักษรตัวแปรใน Catalina จากนั้นเราจะพูดถึงข้อบกพร่อง 2-3 อย่างและวิธีที่วิศวกรของ 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
  ;
}
คาตาลินา
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 ที่กำหนดเองพร้อมการปรับแต่งอื่นๆ ที่น่าสนใจ 👍

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

ภาคผนวก: การถดถอยของ 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 มาพิจารณาในผลลัพธ์ของเมตริกอยู่แล้ว ไลบรารีการปรับรูปร่างของ Chromium HarfBuzz ต้องการเมตริกที่ยังไม่ได้รวมค่า 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" ไม่ใช่แบบอักษรที่เปลี่ยนแปลงได้ด้วยซ้ำ แต่เป็นชุดแบบอักษรแยกกันสำหรับแต่ละความหนาที่มี เมื่อถึงจุดหนึ่ง รหัสกลีฟของทั้ง 2 แบบก็ไม่ซิงค์กัน ดังนั้นหาก 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 ยังได้ลองใช้แฟล็กบิลด์อื่นเพื่อเปลี่ยนโค้ดพาธที่เกี่ยวข้องกับแบบอักษรใน Skia ซึ่งแก้ไขปัญหาแบบอักษรตัวหนาได้ แต่ทำให้เกิดปัญหาการเว้นวรรค

การแก้ไข

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

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

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