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

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

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

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

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

واجهة برمجة التطبيقات Local Font Access API

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

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

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

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

واجهة برمجة التطبيقات Local Font Access API هي محاولة لحلّ هذه التحديات. وهو يتألّف من جزأين:

  • font enumeration API التي تتيح للمستخدمين منح إذن الوصول إلى المجموعة الكاملة من خطوط النظام المتاحة
  • من كل نتيجة تعداد، إمكانية طلب الوصول إلى حاوية SFNT من المستوى المنخفض (الموجّهة إلى البايتات) التي تتضمّن بيانات الخط الكامل

دعم المتصفح

توافق المتصفّح

  • Chrome: 103
  • الحافة: 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 و 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 في مربّع المكوّنات. يُعدّ تطبيق Glitch مثاليًا لمشاركة عمليات إعادة الإنتاج بسرعة وسهولة.

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

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

أرسِل تغريدة إلى ‎@ChromiumDev باستخدام الهاشتاغ #LocalFontAccess وأخبِرنا بمكان استخدامك للميزة وطريقة استخدامك لها.

الشكر والتقدير

تم تعديل مواصفات Local Font Access API بواسطة إيميل أ. Eklund، Alex Russell، Joshua Bell، Olivier Yiptong تمت مراجعة هذه المقالة من قِبل جو ميديل، دومينيك روتشس، و أوليفير يبيتونغ. الصورة الرئيسية من أعمال Brett Jordan على Unsplash.