Local Font Access API מספק מנגנון לגישה לנתוני הגופנים שמותקנים באופן מקומי על ידי המשתמש, כולל פרטים ברמה גבוהה יותר כמו שמות, סגנונות ומשפחות, וכן הבייטים של קובצי הגופנים הבסיסיים. מידע על אופן השימוש ב-API הזה על ידי אפליקציית העריכה בפורמט SVG של Boxy SVG.
מבוא
(המאמר הזה זמין גם בצורת סרטון.)
Boxy SVG היא כלי לעריכת גרפיקה וקטורית. התרחיש העיקרי לדוגמה הוא עריכת שרטוטים בפורמט הקובץ SVG ליצירת איורים, סמלי לוגו, סמלים ואלמנטים אחרים של עיצוב גרפי. הכלי פותח על ידי המפתח הפולני ירוסלב פוקסה, והוא הושק לראשונה ב-15 במרץ 2013. ירוסלאו מפעיל בלוג Boxy SVG שבו הוא מכריז על תכונות חדשות שהוא מוסיף לאפליקציה. המפתח הוא תומך נלהב ב-Project Fugu של Chromium, ויש לו תג Fugu במעקב הרעיונות של האפליקציה.
Local Font Access API ב-Boxy SVG
אחת מהתכונות שנוספו על ידי ירוסלב בבלוג הייתה Local Font Access API. Local Font Access API מאפשר למשתמשים לגשת לגופנים שמותקנים באופן מקומי, כולל פרטים ברמה גבוהה יותר כמו שמות, סגנונות ומשפחות, וכן לבייטים הגולמיים של קובצי הגופנים הבסיסיים. בצילום המסך הבא אפשר לראות איך הענקתי לאפליקציה גישה לגופנים שמותקנים באופן מקומי ב-MacBook שלי ובחרתי בגופן Mark Felt לטקסט שלי.
הקוד הבסיסי הוא די פשוט. כשהמשתמש פותח את בוחר משפחת הגופנים בפעם הראשונה, האפליקציה בודקת קודם אם דפדפן האינטרנט תומך ב-Local Font Access API.
הוא גם בודק את הגרסה הניסיונית הישנה של ה-API ומשתמש בה, אם היא קיימת. החל מ-2023, אפשר להתעלם בבטחה מה-API הישן, כי הוא היה זמין רק לזמן קצר באמצעות תכונות ניסיוניות של Chrome, אבל יכול להיות שחלק מהנגזרים של Chromium עדיין משתמשים בו.
let isLocalFontsApiEnabled = (
// Local Font Access API, Chrome >= 102
window.queryLocalFonts !== undefined ||
// Experimental Local Font Access API, Chrome < 102
navigator.fonts?.query !== undefined
);
אם Local Font Access API לא זמין, הצבע של בוחר משפחת הגופנים בצבע אפור. טקסט מציין מיקום יוצג למשתמש במקום רשימת הגופנים:
if (isLocalFontsApiEnabled === false) {
showPlaceholder("no-local-fonts-api");
return;
}
במקרים אחרים, ה-Local Font Access API משמש לאחזור הרשימה של כל הגופנים ממערכת ההפעלה. שימו לב לבלוק try…catch
, שנדרש כדי לטפל בשגיאות הרשאה כראוי.
let localFonts;
if (isLocalFontsApiEnabled === true) {
try {
// Local Font Access API, Chrome >= 102
if (window.queryLocalFonts) {
localFonts = await window.queryLocalFonts();
}
// Experimental Local Font Access API, Chrome < 102
else if (navigator.fonts?.query) {
localFonts = await navigator.fonts.query({
persistentAccess: true,
});
}
} catch (error) {
showError(error.message, error.name);
}
}
אחרי אחזור רשימת הגופנים המקומיים, נוצר ממנה fontsIndex
פשוט ומנורמל:
let fontsIndex = [];
for (let localFont of localFonts) {
let face = "400";
// Determine the face name
{
let subfamily = localFont.style.toLowerCase();
subfamily = subfamily.replaceAll(" ", "");
subfamily = subfamily.replaceAll("-", "");
subfamily = subfamily.replaceAll("_", "");
if (subfamily.includes("thin")) {
face = "100";
} else if (subfamily.includes("extralight")) {
face = "200";
} else if (subfamily.includes("light")) {
face = "300";
} else if (subfamily.includes("medium")) {
face = "500";
} else if (subfamily.includes("semibold")) {
face = "600";
} else if (subfamily.includes("extrabold")) {
face = "800";
} else if (subfamily.includes("ultrabold")) {
face = "900";
} else if (subfamily.includes("bold")) {
face = "700";
}
if (subfamily.includes("italic")) {
face += "i";
}
}
let descriptor = fontsIndex.find((descriptor) => {
return descriptor.family === localFont.family);
});
if (descriptor) {
if (descriptor.faces.includes(face) === false) {
descriptor.faces.push(face);
}
} else {
let descriptor = {
family: localFont.family,
faces: [face],
};
fontsIndex.push(descriptor);
}
}
for (let descriptor of fontsIndex) {
descriptor.faces.sort();
}
לאחר מכן, אינדקס הגופנים המנורמל נשמר במסד הנתונים IndexedDB כדי שניתן יהיה לשלוח אליו שאילתות, לשתף אותו בין מופעים שונים של אפליקציות ולשמור אותו בקלות בין סשנים. בפורמט Boxy SVG נעשה שימוש ב-Dexie.js כדי לנהל את מסד הנתונים:
let database = new Dexie("LocalFontsManager");
database.version(1).stores({cache: "family"}).
await database.cache.clear();
await database.cache.bulkPut(fontsIndex);
לאחר אכלוס מסד הנתונים, הווידג'ט של בוחר הגופנים יכול להריץ שאילתות עליו ולהציג את התוצאות על המסך:
חשוב לציין שפורמט Boxy SVG מעבד את הרשימה באלמנט מותאם אישית בשם <bx-fontfamilypicker>
ומעצב כל פריט ברשימת הגופנים כך שהוא יוצג במשפחת הגופנים המסוימת. כדי לבודד משאר הדף, Boxy SVG משתמש ב-Shadow DOM ברכיב הזה וברכיבים מותאמים אישית אחרים.
מסקנות
התכונה של גופנים מקומיים הפכה לפופולרית מאוד, והמשתמשים נהנו מגישה לגופנים המקומיים בזכות העיצובים והיצירות שלהם. אם צורת ה-API השתנתה והתכונה התבטלה לזמן קצר, המשתמשים ציינו זאת מיד. ירוסלב שינתה במהירות את הקוד לתבנית ההגנה שניתן לראות בקטע הקוד שלמעלה, שעובד עם הגרסה העדכנית של Chrome ונגזרות אחרות של Chromium שייתכן שלא עברו לגרסה האחרונה. נסו את ערכת ה-SVG של Boxy ואל תשכחו לבדוק את הגופנים שמותקנים באופן מקומי. יכול להיות שתגלו כמה קלאסיקות נשכחות מזמן, כמו Zapf Dingbats או Webdings.