ใช้แบบอักษรขั้นสูงกับแบบอักษรในเครื่อง

ดูว่า Local Font Access API ช่วยให้คุณเข้าถึงแบบอักษรที่ติดตั้งในเครื่องของผู้ใช้และรับรายละเอียดระดับต่ำเกี่ยวกับแบบอักษรเหล่านั้นได้อย่างไร

แบบอักษรที่ปลอดภัยสำหรับเว็บ

หากคุณเป็นนักพัฒนาเว็บมานานพอ คุณอาจจำสิ่งที่เรียกว่า แบบอักษรที่ใช้บนเว็บได้อย่างปลอดภัยได้ แบบอักษรเหล่านี้เป็นแบบอักษรที่ทราบกันว่ามีอยู่ในระบบปฏิบัติการที่ใช้กันมากที่สุดเกือบทุกอินสแตนซ์ (ได้แก่ Windows, macOS, การกระจาย Linux ที่ใช้กันมากที่สุด, Android และ iOS) ในช่วงต้นปี 2000 Microsoft เป็นหัวหอกในการริเริ่ม ที่ชื่อว่า TrueType core fonts for the Web ซึ่งให้บริการแบบอักษรเหล่านี้ให้ดาวน์โหลดฟรีโดยมี วัตถุประสงค์ที่ว่า "เมื่อใดก็ตามที่คุณเข้าชมเว็บไซต์ที่ระบุแบบอักษรเหล่านี้ คุณจะเห็นหน้าเว็บตรงตามที่ ผู้ออกแบบเว็บไซต์ตั้งใจไว้" ได้ รวมถึงเว็บไซต์ที่ตั้งค่าเป็นComic Sans MS ด้วย ตัวอย่างsans-serif สแต็กแบบอักษรที่ปลอดภัยสำหรับเว็บแบบคลาสสิก (พร้อมแบบอักษรสํารองสุดท้าย) อาจมีลักษณะดังนี้

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

เว็บฟอนต์

สมัยที่แบบอักษรที่ปลอดภัยบนเว็บมีความสำคัญจริงๆ นั้นผ่านไปนานแล้ว ปัจจุบันเรามีแบบอักษรบนเว็บ ซึ่งบางแบบเป็นแบบอักษรตัวแปรที่เราปรับแต่งเพิ่มเติมได้โดยเปลี่ยนค่าสำหรับแกนต่างๆ ที่แสดง คุณใช้แบบอักษรบนเว็บได้โดยการประกาศบล็อก @font-face ที่จุดเริ่มต้นของ CSS ซึ่งระบุไฟล์แบบอักษรที่จะดาวน์โหลด

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

หลังจากนี้ คุณจะใช้แบบอักษรเว็บที่กำหนดเองได้โดยการระบุ font-family ตามปกติ ดังนี้

body {
  font-family: 'FlamboyantSansSerif';
}

แบบอักษรในเครื่องเป็นเวกเตอร์ลายนิ้วมือ

แบบอักษรเว็บส่วนใหญ่มาจากเว็บ แต่ข้อเท็จจริงที่น่าสนใจคือพร็อพเพอร์ตี้ src ในการประกาศ @font-face นอกเหนือจากฟังก์ชัน url() แล้วยังยอมรับฟังก์ชัน local() ด้วย ซึ่งจะช่วยให้โหลดแบบอักษรที่กำหนดเองได้ (เซอร์ไพรส์!) ในเครื่อง หากผู้ใช้ติดตั้ง FlamboyantSansSerif ในระบบปฏิบัติการ ระบบจะใช้สำเนาในเครื่องแทนการดาวน์โหลด

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

แนวทางนี้เป็นกลไกสำรองที่ดีที่อาจช่วยประหยัดแบนด์วิดท์ได้ บนอินเทอร์เน็ต เราไม่สามารถมีสิ่งดีๆ ได้ ปัญหาของฟังก์ชัน local() คืออาจถูกนำไปใช้ในทางที่ผิดเพื่อการเก็บลายนิ้วมือของเบราว์เซอร์ ปรากฏว่ารายการแบบอักษรที่ผู้ใช้ติดตั้งไว้สามารถระบุตัวตนได้ บริษัทหลายแห่งมีแบบอักษรของบริษัทที่ติดตั้งไว้ในแล็ปท็อปของพนักงาน ตัวอย่างเช่น Google มีแบบอักษรขององค์กรที่ชื่อว่า Google Sans

แอปสมุดแบบอักษรของ macOS แสดงตัวอย่างแบบอักษร Google Sans
แบบอักษร Google Sans ที่ติดตั้งในแล็ปท็อปของพนักงาน Google

ผู้โจมตีอาจพยายามระบุว่าบุคคลนั้นทำงานที่บริษัทใดโดยทดสอบว่ามีฟอนต์ขององค์กรที่รู้จักจำนวนมาก เช่น Google Sans หรือไม่ ผู้โจมตีจะพยายามแสดงข้อความ ที่ตั้งค่าในแบบอักษรเหล่านี้บน Canvas และวัดรูปร่าง หากกลีฟตรงกับรูปร่างที่ทราบของ แบบอักษรขององค์กร แสดงว่าผู้โจมตีประสบความสำเร็จ หากกลีฟไม่ตรงกัน ผู้โจมตีจะทราบว่ามีการใช้แบบอักษรแทนค่าเริ่มต้นเนื่องจากไม่ได้ติดตั้งแบบอักษรขององค์กร ดูรายละเอียดทั้งหมดเกี่ยวกับการโจมตีด้วยลายนิ้วมือของเบราว์เซอร์นี้และอื่นๆ ได้ในเอกสารการสำรวจของ Laperdix และคณะ

นอกเหนือจากแบบอักษรของบริษัทแล้ว แม้แต่รายชื่อแบบอักษรที่ติดตั้งก็อาจระบุตัวตนได้ สถานการณ์ที่มีช่องโหว่นี้รุนแรงมากจนเมื่อเร็วๆ นี้ ทีม WebKit ตัดสินใจ"รวมเฉพาะแบบอักษรบนเว็บและแบบอักษรที่มาพร้อมกับระบบปฏิบัติการ [ในรายการแบบอักษรที่ใช้ได้] แต่ไม่รวมแบบอักษรที่ผู้ใช้ติดตั้งไว้ในเครื่อง" (และฉันก็มาพร้อมกับบทความเกี่ยวกับการให้สิทธิ์เข้าถึง แบบอักษรในเครื่อง)

Local Font Access API

ตอนต้นของบทความนี้อาจทำให้คุณรู้สึกแย่ เราไม่มีสิ่งดีๆ ได้จริงๆ เหรอ ไม่ต้องกังวล เราคิดว่าทำได้ และบางทีทุกอย่างก็ไม่ได้สิ้นหวัง แต่ก่อนอื่น เราขอตอบคำถามที่คุณอาจสงสัย

ทำไมเราจึงต้องใช้ Local Font Access API ในเมื่อมีแบบอักษรสำหรับเว็บอยู่แล้ว

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

  • เครื่องมือออกแบบต้องมีสิทธิ์เข้าถึงไบต์แบบอักษรเพื่อติดตั้งใช้งานเลย์เอาต์ OpenType ของตนเอง และอนุญาตให้เครื่องมือออกแบบเชื่อมต่อในระดับที่ต่ำกว่าสำหรับการดำเนินการต่างๆ เช่น การใช้ฟิลเตอร์เวกเตอร์หรือการเปลี่ยนรูปทรงของกลีฟ
  • นักพัฒนาแอปอาจมีกลุ่มแบบอักษรเดิมสำหรับแอปพลิเคชันที่นำมาใช้บนเว็บ โดยปกติแล้วการใช้กองซ้อนเหล่านี้จะต้องมีสิทธิ์เข้าถึงข้อมูลแบบอักษรโดยตรง ซึ่งเป็นสิ่งที่แบบอักษรบนเว็บไม่ได้ ให้ไว้
  • แบบอักษรบางแบบอาจไม่มีใบอนุญาตสำหรับการแสดงบนเว็บ ตัวอย่างเช่น Linotype มีใบอนุญาตสำหรับ แบบอักษรบางแบบที่รวมเฉพาะการใช้งานบนเดสก์ท็อป

Local Font Access API เป็นความพยายามในการแก้ปัญหาเหล่านี้ โดยประกอบด้วย 2 ส่วน ดังนี้

  • API การแจงนับแบบอักษร ซึ่งช่วยให้ผู้ใช้ให้สิทธิ์เข้าถึงชุดแบบอักษรของระบบทั้งหมดที่พร้อมใช้งานได้
  • จากผลการแจงนับแต่ละรายการ ความสามารถในการขอการเข้าถึงคอนเทนเนอร์ SFNT ระดับต่ำ (ระดับไบต์) ซึ่งรวมถึงข้อมูลแบบอักษรทั้งหมด

การสนับสนุนเบราว์เซอร์

Browser Support

  • Chrome: 103.
  • Edge: 103.
  • Firefox: not supported.
  • Safari: not supported.

Source

วิธีใช้ Local Font Access API

การตรวจหาฟีเจอร์

หากต้องการตรวจสอบว่าเบราว์เซอร์รองรับ Local Font Access API หรือไม่ ให้ใช้

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

การแจงนับแบบอักษรในเครื่อง

หากต้องการดูรายการแบบอักษรที่ติดตั้งไว้ในเครื่อง คุณต้องเรียกใช้ window.queryLocalFonts() ครั้งแรกที่ใช้ฟีเจอร์นี้ ระบบจะแสดงข้อความแจ้งขอสิทธิ์ ซึ่งผู้ใช้สามารถอนุมัติหรือปฏิเสธได้ หากผู้ใช้ อนุมัติให้ค้นหาแบบอักษรในเครื่อง เบราว์เซอร์จะแสดงผลอาร์เรย์ที่มีข้อมูลแบบอักษร ซึ่งคุณสามารถวนซ้ำได้ แบบอักษรแต่ละแบบแสดงเป็นออบเจ็กต์ FontData ที่มีพร็อพเพอร์ตี้ family (เช่น "Comic Sans MS"), fullName (เช่น "Comic Sans MS"), postscriptName (เช่น "ComicSansMS") และ style (เช่น "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);
}

หากสนใจเฉพาะแบบอักษรบางส่วน คุณก็กรองแบบอักษรตามชื่อ PostScript ได้โดยเพิ่มพารามิเตอร์ postscriptNames

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

การเข้าถึงข้อมูล SFNT

คุณจะเข้าถึง SFNT ได้อย่างเต็มรูปแบบผ่านเมธอด blob() ของออบเจ็กต์ FontData SFNT เป็นรูปแบบไฟล์แบบอักษรที่อาจมีแบบอักษรอื่นๆ เช่น PostScript, TrueType, OpenType, Web Open Font Format (WOFF) และอื่นๆ

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

สาธิต

คุณดูการทำงานของ Local Font Access API ได้ในเดโม อย่าลืมดูซอร์สโค้ดด้วย การสาธิต แสดงองค์ประกอบที่กำหนดเองชื่อ <font-select> ซึ่ง ใช้เครื่องมือเลือกแบบอักษรในเครื่อง

ข้อควรพิจารณาด้านความเป็นส่วนตัว

สิทธิ์ "local-fonts" ดูเหมือนจะให้พื้นผิวที่สามารถระบุลายนิ้วมือได้สูง อย่างไรก็ตาม เบราว์เซอร์สามารถแสดงผลอะไรก็ได้ตามที่ต้องการ เช่น เบราว์เซอร์ที่เน้นการไม่ระบุตัวตนอาจเลือก ที่จะให้เฉพาะชุดแบบอักษรเริ่มต้นที่สร้างไว้ในเบราว์เซอร์เท่านั้น ในทำนองเดียวกัน เบราว์เซอร์ก็ไม่จำเป็น ต้องแสดงข้อมูลตารางตรงตามที่ปรากฏในดิสก์

Local Font Access API ได้รับการออกแบบมาให้แสดงเฉพาะข้อมูลที่จำเป็นเพื่อเปิดใช้กรณีการใช้งานที่กล่าวถึงเท่านั้น API ของระบบอาจสร้างรายการแบบอักษรที่ติดตั้งซึ่งไม่ได้อยู่ในลำดับแบบสุ่มหรือลำดับที่จัดเรียง แต่จะอยู่ในลำดับการติดตั้งแบบอักษร การแสดงรายการแบบอักษรที่ติดตั้ง ตามที่ API ของระบบดังกล่าวระบุอย่างตรงไปตรงมาอาจเปิดเผยข้อมูลเพิ่มเติมที่อาจใช้สำหรับการ ลายนิ้วมือ และกรณีการใช้งานที่เราต้องการเปิดใช้จะไม่ได้รับความช่วยเหลือจากการรักษาลำดับนี้ ด้วยเหตุนี้ API นี้จึงกำหนดให้ต้องจัดเรียงข้อมูลที่ส่งคืนก่อนที่จะส่งคืน

ความปลอดภัยและสิทธิ์

ทีม Chrome ได้ออกแบบและใช้ Local Font Access API โดยใช้หลักการสำคัญ ที่ระบุไว้ในการควบคุมการเข้าถึงฟีเจอร์ที่มีประสิทธิภาพของแพลตฟอร์มเว็บ ซึ่งรวมถึงการควบคุมของผู้ใช้ ความโปร่งใส และการยศาสตร์

การควบคุมของผู้ใช้

การเข้าถึงแบบอักษรของผู้ใช้จะอยู่ภายใต้การควบคุมของผู้ใช้โดยสมบูรณ์ และจะไม่อนุญาตให้เข้าถึงเว้นแต่จะได้รับ "local-fonts"สิทธิ์ตามที่ระบุไว้ใน การลงทะเบียนสิทธิ์

ความโปร่งใส

คุณจะดูได้ว่าเว็บไซต์ได้รับสิทธิ์เข้าถึงแบบอักษรในเครื่องของผู้ใช้หรือไม่ในแผ่นข้อมูลเว็บไซต์

การคงอยู่ของสิทธิ์

ระบบจะคงสิทธิ์ "local-fonts" ไว้ระหว่างการโหลดหน้าเว็บซ้ำ คุณเพิกถอนได้ผ่านชีตข้อมูลเว็บไซต์

ความคิดเห็น

ทีม Chrome อยากทราบประสบการณ์การใช้งาน Local Font Access API ของคุณ

บอกเราเกี่ยวกับการออกแบบ API

มีสิ่งใดเกี่ยวกับ API ที่ทำงานไม่เป็นไปตามที่คุณคาดหวังไว้หรือไม่ หรือมีเมธอด หรือพร็อพเพอร์ตี้ที่ขาดหายไปซึ่งคุณต้องใช้เพื่อนำแนวคิดไปใช้ไหม หากมีคำถามหรือความคิดเห็นเกี่ยวกับโมเดลความปลอดภัย แจ้งปัญหาเกี่ยวกับข้อกำหนดในที่เก็บ GitHub ที่เกี่ยวข้อง หรือแสดงความคิดเห็นในปัญหาที่มีอยู่

รายงานปัญหาเกี่ยวกับการติดตั้งใช้งาน

หากพบข้อบกพร่องในการใช้งาน Chrome หรือการติดตั้งใช้งานแตกต่างจากข้อกำหนด ยื่นข้อบกพร่องที่ new.crbug.com โปรดใส่รายละเอียดให้มากที่สุดเท่าที่จะทำได้ วิธีการง่ายๆ ในการทำซ้ำ และป้อน Blink>Storage>FontAccess ในช่องคอมโพเนนต์

แสดงการสนับสนุน API

คุณวางแผนที่จะใช้ Local Font Access API ไหม การสนับสนุนแบบสาธารณะของคุณจะช่วยให้ทีม Chrome จัดลําดับความสําคัญของฟีเจอร์และแสดงให้ผู้ให้บริการเบราว์เซอร์รายอื่นๆ เห็นว่าการสนับสนุนฟีเจอร์เหล่านี้มีความสําคัญเพียงใด

ส่งทวีตถึง @ChromiumDev โดยใช้แฮชแท็ก #LocalFontAccess และแจ้งให้เราทราบว่าคุณใช้ฟีเจอร์นี้ที่ไหนและอย่างไร

คำขอบคุณ

มีการแก้ไขข้อกำหนด API สำหรับการเข้าถึงแบบอักษรในเครื่องโดย Emil A. Eklund, Alex Russell, Joshua Bell และ Olivier Yiptong บทความนี้ได้รับการตรวจสอบโดย Joe Medley Dominik Röttsches และ Olivier Yiptong รูปภาพหลักโดย Brett Jordan บน Unsplash