استخدام أسلوب الخط المتقدم مع الخطوط المحلية

تعرَّف على كيفية السماح لك واجهة برمجة التطبيقات Local Font Access API بالوصول إلى الخطوط المثبَّتة على جهاز المستخدم والحصول على تفاصيل منخفضة المستوى بشأنها

الخطوط الآمنة على الويب

إذا كنت تعمل في مجال تطوير الويب منذ فترة طويلة، قد تتذكر ما يُعرف باسم خطوط الويب الآمنة. من المعروف أنّ هذه الخطوط متوفّرة على جميع إصدارات أنظمة التشغيل الأكثر استخدامًا تقريبًا (أي Windows وmacOS وتوزيعات Linux الأكثر شيوعًا وAndroid وiOS). في أوائل الألفية الثانية، أطلقت شركة 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.

تطبيق Font Book على نظام التشغيل macOS يعرض معاينة لخط Google Sans.
خط Google Sans مثبّت على جهاز كمبيوتر محمول خاص بموظف في Google

يمكن للمهاجم محاولة تحديد الشركة التي يعمل فيها شخص ما من خلال اختبار توفّر عدد كبير من خطوط الشركات المعروفة، مثل Google Sans. سيحاول المهاجم عرض النص المضبوط في هذه الخطوط على لوحة الرسم وقياس الرموز الرسومية. إذا كانت الرموز الرسومية تتطابق مع الشكل المعروف لخط الشركة، يكون المهاجم قد حقّق نجاحًا. إذا لم تتطابق الرموز الرسومية، سيعرف المهاجم أنّه تم استخدام خط بديل تلقائي لأنّ خط الشركة لم يكن مثبّتًا. للاطّلاع على التفاصيل الكاملة حول هذا النوع من الهجمات وغيرها من الهجمات التي تستخدم بصمة المتصفّح، يُرجى قراءة ورقة البحث التي أعدّها Laperdix وآخرون.

وبصرف النظر عن خطوط الشركة، يمكن أن تكون حتى قائمة الخطوط المثبَّتة معرِّفة. وقد تفاقم الوضع بشأن هذا النوع من الهجمات، ما دفع فريق WebKit مؤخرًا إلى اتخاذ قرار "بإدراج خطوط الويب والخطوط التي تأتي مع نظام التشغيل فقط في قائمة الخطوط المتاحة، وليس الخطوط التي يثبّتها المستخدم محليًا". (وها أنا أكتب مقالة حول منح الإذن بالوصول إلى الخطوط المحلية.)

‫Local Font Access API

ربما تكون بداية هذه المقالة قد أثّرت سلبًا في مزاجك. هل لا يمكننا حقًا الاستمتاع بأشياء جميلة؟ لا تقلق. نعتقد أنّنا نستطيع ذلك، وربما لا يزال هناك أمل. ولكن قبل ذلك، اسمح لي بالإجابة عن سؤال قد يراودك.

لماذا نحتاج إلى Local Font Access API عندما تتوفّر خطوط ويب؟

لطالما كان من الصعب توفير أدوات تصميم ورسومات عالية الجودة على الويب. وقد تمثّلت إحدى العقبات في عدم القدرة على الوصول إلى مجموعة متنوعة وكاملة من الخطوط المصمَّمة بشكل احترافي والمزوّدة بتلميحات، والتي ثبّتها المصمّمون على أجهزتهم. تتيح خطوط الويب بعض حالات الاستخدام في النشر، ولكنّها لا تتيح الوصول آليًا إلى أشكال الرسومات المتجهة وجداول الخطوط التي تستخدمها برامج تحويل الرسومات النقطية لعرض الخطوط. وبالمثل، لا يمكن الوصول إلى بيانات ثنائية لخط ويب.

  • تحتاج أدوات التصميم إلى الوصول إلى وحدات بايت الخط لتنفيذ تخطيط OpenType الخاص بها والسماح لأدوات التصميم بالربط على مستويات أدنى، وذلك لتنفيذ إجراءات مثل تطبيق فلاتر متجهة أو عمليات تحويل على أشكال الرموز الرسومية.
  • قد يكون لدى المطوّرين حِزم خطوط قديمة لتطبيقاتهم التي ينقلونها إلى الويب. ولاستخدام هذه الحزم، يجب عادةً توفير إذن وصول مباشر إلى بيانات الخطوط، وهو ما لا توفّره خطوط الويب.
  • قد لا تكون بعض الخطوط مرخّصة للعرض على الويب. على سبيل المثال، لدى شركة Linotype ترخيص لبعض الخطوط يتضمّن الاستخدام على أجهزة الكمبيوتر فقط.

تُعدّ Local Font Access 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، حيثما أمكن ذلك، لعرض المعلومات اللازمة فقط لتفعيل حالات الاستخدام المذكورة. قد تعرض واجهات برمجة التطبيقات التابعة للنظام قائمة بالخطوط المثبَّتة بترتيب غير عشوائي أو غير مرتَّب، ولكن بترتيب تثبيت الخطوط. إنّ عرض قائمة خطوط التنسيق المثبّتة التي تقدّمها واجهة برمجة تطبيقات النظام هذه بالضبط قد يؤدي إلى الكشف عن بيانات إضافية يمكن استخدامها في إنشاء بصمة رقمية، كما أنّ حالات الاستخدام التي نريد إتاحتها لا يمكن تحقيقها من خلال الاحتفاظ بهذا الترتيب. نتيجةً لذلك، تتطلّب واجهة برمجة التطبيقات هذه أن يتم فرز البيانات التي يتم عرضها قبل عرضها.

الأمان والأذونات

صمّم فريق Chrome واجهة Local Font Access API ونفّذها باستخدام المبادئ الأساسية المحدّدة في التحكّم في الوصول إلى الميزات الفعّالة لمنصة الويب، بما في ذلك عناصر تحكّم المستخدم والشفافية وبيئة العمل المريحة.

تحكّم المستخدم

يخضع الوصول إلى خطوط المستخدمين بشكل كامل لتحكّمهم، ولن يُسمح به إلا بعد منح إذن "local-fonts"، كما هو موضّح في سجلّ الأذونات.

الشفافية

يمكن الاطّلاع على ما إذا كان الموقع الإلكتروني قد حصل على إذن بالوصول إلى الخطوط المحلية للمستخدم في ورقة معلومات الموقع الإلكتروني.

استمرار الإذن

سيتم الاحتفاظ بإذن "local-fonts" عند إعادة تحميل الصفحة. يمكن إبطالها من خلال ورقة معلومات الموقع الإلكتروني.

الملاحظات

يريد فريق Chrome معرفة تجاربك مع Local Font Access API.

أخبِرنا عن تصميم واجهة برمجة التطبيقات

هل هناك أي شيء في واجهة برمجة التطبيقات لا يعمل على النحو المتوقّع؟ أو هل هناك طرق أو سمات مفقودة تحتاج إليها لتنفيذ فكرتك؟ هل لديك سؤال أو تعليق بشأن نموذج الأمان؟ يمكنك الإبلاغ عن مشكلة في المواصفات في مستودع GitHub ذي الصلة، أو إضافة أفكارك إلى مشكلة حالية.

الإبلاغ عن مشكلة في عملية التنفيذ

هل عثرت على خطأ في تنفيذ Chrome؟ أو هل يختلف التنفيذ عن المواصفات؟ يمكنك الإبلاغ عن خطأ على new.crbug.com. احرص على تضمين أكبر قدر ممكن من التفاصيل، وتعليمات بسيطة لإعادة إنتاج الخطأ، وأدخِل Blink>Storage>FontAccess في مربّع المكوّنات.

إظهار الدعم لواجهة برمجة التطبيقات

هل تخطّط لاستخدام Local Font Access API؟ يساعد دعمك العلني فريق Chrome في تحديد أولويات الميزات، ويوضّح لمورّدي المتصفّحات الآخرين مدى أهمية توفيرها.

يمكنك إرسال تغريدة إلى @ChromiumDev باستخدام الهاشتاغ #LocalFontAccess وإخبارنا بمكان استخدامك لهذه الميزة وكيفية استخدامها.

الإقرارات

تم تعديل مواصفات Local Font Access API بواسطة Emil A. إكلوند وأليكس راسل وجوشوا بيل وأوليفييه ييبتونغ راجع هذه المقالة جو ميدلي و دومينيك روتشيس و أوليفييه ييبتونغ. الصورة الرئيسية من بريت جوردان على Unsplash