توفّر واجهة برمجة التطبيقات Local Font Access API آلية للوصول إلى بيانات الخطوط المثبَّتة محليًا للمستخدم، بما في ذلك التفاصيل ذات المستوى الأعلى مثل الأسماء والأنماط والعائلات، بالإضافة إلى وحدات البايت الأولية لملفات الخطوط الأساسية. تعرَّف على كيفية استخدام تطبيق تعديل ملفات SVG المُسمى Boxy SVG لواجهة برمجة التطبيقات هذه.
مقدمة
(تتوفر هذه المقالة أيضًا في شكل فيديو).
Boxy SVG هي محرر رسومات متجهات. وتشمل حالات الاستخدام الرئيسية لهذا التنسيق تعديل الرسومات بتنسيق ملف SVG لإنشاء الرسوم التوضيحية والشعارات والرموز والعناصر الأخرى لتصميم الرسومات. وقد تم تطويره من قِبل مطوّر البرامج البولندي Jarosaw Foksa وتم طرحه للمرة الأولى في 15 آذار (مارس) 2013. يدير جاروسواف مدونة Boxy SVG التي يعلن فيها عن الميزات الجديدة التي يضيفها إلى التطبيق. ويدعم مطوّر البرامج بشكل كبير مشروع Fugu في Chromium ولديه علامة Fugu في أداة تتبُّع الأفكار في التطبيق.
واجهة برمجة تطبيقات Local Font Access API في Boxy SVG
كانت Local Font Access API إحدى الميزات التي تمت تدوينها عن "جاروسواف". تتيح واجهة برمجة التطبيقات Local Font Access API للمستخدمين الوصول إلى الخطوط المثبَّتة على الجهاز، بما في ذلك التفاصيل ذات المستوى الأعلى، مثل الأسماء والأنماط ومجموعات الخطوط، بالإضافة إلى البايتات الأوّلية لملفات الخطوط الأساسية. في لقطة الشاشة التالية، يمكنك الاطّلاع على كيفية منحي التطبيق إذن الوصول إلى الخطوط المثبَّتة على جهاز MacBook واختيار خط Marker Felt للنص.
إنّ الرمز الأساسي بسيط جدًا. عندما يفتح المستخدم أداة اختيار عائلة الخطوط لأول مرة، يتحقّق التطبيق أولاً ممّا إذا كان متصفّح الويب متوافقًا مع Local Font Access API.
ويتم أيضًا التحقّق من الإصدار التجريبي القديم لواجهة برمجة التطبيقات واستخدامه في حال توفُّره. اعتبارًا من عام 2023، يمكنك تجاهل واجهة برمجة التطبيقات القديمة بأمان، لأنّها لم تكن متاحة إلا لفترة قصيرة من خلال ميزات 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 في هذا العنصر المخصّص وغيره من العناصر المخصّصة.
الاستنتاجات
حظيت ميزة الخطوط المحلية بشعبية كبيرة، حيث يستفيد المستخدمون من الوصول إلى الخطوط المحلية لتصاميمهم وإبداعاتهم. عندما تغيّر شكل واجهة برمجة التطبيقات وتعطّلت الميزة لفترة قصيرة، لاحظ المستخدمون ذلك على الفور. سارع ياروسلاو إلى تغيير الرمز إلى النمط الدفاعي الذي يمكنك رؤيته في المقتطف أعلاه الذي يعمل مع إصدار Chrome المحدّث وأيضًا مشتقات Chromium الأخرى التي ربما لم يتم تحويلها إلى أحدث إصدار. جرِّب استخدام Boxy SVG وتأكَّد من الاطّلاع على الخطوط المثبَّتة على الجهاز. قد تكتشف بعض الخطوط الكلاسيكية التي تم نسيان استخدامها منذ فترة طويلة، مثل Zapf Dingbats أو Webdings.