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

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

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

หากทํางานด้านการพัฒนาเว็บมาอย่างยาวนาน คุณอาจคุ้นเคยกับสิ่งที่เรียกว่าแบบอักษรที่ปลอดภัยบนเว็บ แบบอักษรเหล่านี้เป็นที่รู้จักกันว่ามีให้บริการในอินสแตนซ์เกือบทั้งหมดของระบบปฏิบัติการที่ใช้กันมากที่สุด (ได้แก่ Windows, macOS, ดิสทริบิวชัน Linux ที่พบบ่อยที่สุด, Android และ iOS) ในช่วงต้นปี 2000 ทาง Microsoft ยังได้เป็นผู้ริเริ่มโครงการที่ชื่อว่า แบบอักษรหลัก TrueType สำหรับเว็บ ซึ่งให้บริการดาวน์โหลดแบบอักษรเหล่านี้ได้ฟรี โดยมีวัตถุประสงค์ว่า"เมื่อใดก็ตามที่คุณเข้าชมเว็บไซต์ที่ระบุแบบอักษรเหล่านี้ คุณจะเห็นหน้าเว็บตามที่นักออกแบบเว็บไซต์ตั้งใจไว้ทุกประการ" ใช่ ซึ่งรวมถึงเว็บไซต์ที่ตั้งค่าเป็น 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

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

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

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

Local Font Access API

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

เหตุใดเราจึงต้องใช้ Local Font Access API เมื่อมีแบบอักษรของเว็บ

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

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

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

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

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

การรองรับเบราว์เซอร์

  • Chrome: 103
  • Edge: 103
  • Firefox: ไม่รองรับ
  • Safari: ไม่รองรับ

แหล่งที่มา

วิธีใช้ 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, 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 ได้รับการออกแบบให้แสดงเฉพาะข้อมูลที่จําเป็นเพื่อเปิดใช้ Use Case ที่กล่าวถึงเท่านั้น System API อาจแสดงรายการแบบอักษรที่ติดตั้งไว้ไม่เรียงตามลำดับแบบสุ่มหรือจัดเรียง แต่เรียงตามลำดับการติดตั้งแบบอักษร การแสดงรายการแบบตัวอักษรที่ติดตั้งไว้ทั้งหมดซึ่ง API ของระบบดังกล่าวระบุอาจเปิดเผยข้อมูลเพิ่มเติมที่อาจใช้สำหรับลายนิ้วมือ และการจัดเรียงนี้ไม่ได้ช่วยกรณีการใช้งานที่เราต้องการเปิดใช้ ด้วยเหตุนี้ API นี้จึงกำหนดให้ต้องจัดเรียงข้อมูลที่แสดงผลก่อนแสดงผล

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

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

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

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

ความโปร่งใส

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

การเก็บรักษาสิทธิ์

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

ความคิดเห็น

ทีม Chrome อยากทราบความคิดเห็นของคุณเกี่ยวกับ Local Font Access API

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

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

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

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

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

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

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

ขอขอบคุณ

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