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

تعرَّف على كيفية استخدام 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.

تطبيق macOS Font Book يعرض معاينة للخط 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 إلى محاولة حل هذه التحديات. ويتكون من جزأين:

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

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

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

  • 103
  • 103
  • x
  • x

المصدر

كيفية استخدام 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 وأليكس راسل وجوشوا بيل وأوليفير يبتونغ. راجع هذه المقالة جو ميدلي ودومينيك روتشس وأوليفير ييبتونغ. صورة رئيسية من تصوير بريت جوردان على قناة Unلمحة