जानें कि Local Font Access API की मदद से, उपयोगकर्ता के डिवाइस पर इंस्टॉल किए गए फ़ॉन्ट को कैसे ऐक्सेस किया जा सकता है. साथ ही, उनके बारे में बुनियादी जानकारी कैसे पाई जा सकती है
पब्लिश किया गया: 24 अगस्त, 2020
वेब सेफ़ फ़ॉन्ट
अगर आपको वेब डेवलपमेंट काफ़ी समय से आता है, तो आपको वेब सेफ़ फ़ॉन्ट के बारे में पता होगा.
ये फ़ॉन्ट, सबसे ज़्यादा इस्तेमाल किए जाने वाले ऑपरेटिंग सिस्टम के लगभग सभी वर्शन पर उपलब्ध होते हैं. जैसे, Windows, macOS, Linux के सबसे आम डिस्ट्रिब्यूशन, Android, और iOS. साल 2000 की शुरुआत में, Microsoft ने TrueType core fonts for the Web नाम की एक पहल शुरू की थी. इसके तहत, इन फ़ॉन्ट को मुफ़्त में डाउनलोड करने की सुविधा दी गई थी. इसका मकसद यह था कि "जब भी कोई व्यक्ति ऐसी वेबसाइट पर जाए जो इन फ़ॉन्ट का इस्तेमाल करती है, तो उसे पेज ठीक वैसे ही दिखें जैसे साइट डिज़ाइनर ने डिज़ाइन किए हैं". हां, इसमें Comic Sans MS में सेट की गई साइटें शामिल हैं. यहां एक क्लासिक वेब सेफ़ फ़ॉन्ट स्टैक दिया गया है. इसमें sans-serif फ़ॉन्ट का फ़ॉलबैक शामिल है. यह इस तरह दिख सकता है:
body {
font-family: Helvetica, Arial, sans-serif;
}
वेब फ़ॉन्ट
वेब सेफ़ फ़ॉन्ट का इस्तेमाल करने का चलन अब खत्म हो गया है. आज हमारे पास वेब फ़ॉन्ट हैं. इनमें से कुछ वैरिएबल फ़ॉन्ट भी हैं. हम अलग-अलग ऐक्सिस की वैल्यू बदलकर, इनमें और बदलाव कर सकते हैं. सीएसएस की शुरुआत में @font-face ब्लॉक का एलान करके, वेब फ़ॉन्ट का इस्तेमाल किया जा सकता है. इससे डाउनलोड की जाने वाली फ़ॉन्ट फ़ाइलें तय की जाती हैं:
@font-face {
font-family: 'FlamboyantSansSerif';
src: url('flamboyant.woff2');
}
इसके बाद, कस्टम वेब फ़ॉन्ट का इस्तेमाल किया जा सकता है. इसके लिए, सामान्य तरीके से font-family तय करें:
body {
font-family: 'FlamboyantSansSerif';
}
फ़िंगरप्रिंट वेक्टर के तौर पर लोकल फ़ॉन्ट
ज़्यादातर वेब फ़ॉन्ट, वेब से मिलते हैं. हालांकि, एक दिलचस्प बात यह है कि @font-face डिक्लेरेशन में मौजूद src प्रॉपर्टी, url() फ़ंक्शन के अलावा local() फ़ंक्शन को भी स्वीकार करती है. इससे कस्टम फ़ॉन्ट को स्थानीय तौर पर लोड किया जा सकता है. अगर उपयोगकर्ता के ऑपरेटिंग सिस्टम पर FlamboyantSansSerif इंस्टॉल है, तो डाउनलोड करने के बजाय स्थानीय कॉपी का इस्तेमाल किया जाएगा:
@font-face {
font-family: 'FlamboyantSansSerif';
src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}
इस तरीके से, एक अच्छा फ़ॉलबैक मैकेनिज़्म मिलता है. इससे बैंडविड्थ की बचत भी हो सकती है. इंटरनेट पर, अफ़सोस की बात है कि हम अच्छी चीज़ें नहीं पा सकते. local() फ़ंक्शन में यह समस्या है कि इसका इस्तेमाल ब्राउज़र फ़िंगरप्रिंटिंग के लिए गलत तरीके से किया जा सकता है. ऐसा पता चला है कि उपयोगकर्ता ने जो फ़ॉन्ट इंस्टॉल किए हैं उनसे उसकी पहचान का पता चल सकता है. कई कंपनियों के अपने कॉर्पोरेट फ़ॉन्ट होते हैं. इन्हें कर्मचारियों के लैपटॉप पर इंस्टॉल किया जाता है. उदाहरण के लिए, Google के पास Google Sans नाम का कॉर्पोरेट फ़ॉन्ट है.
हमलावर यह पता लगाने की कोशिश कर सकता है कि कोई व्यक्ति किस कंपनी में काम करता है. इसके लिए, वह कई कॉर्पोरेट फ़ॉन्ट की जांच करता है. जैसे, Google Sans. हमलावर, कैनवस पर इन फ़ॉन्ट में सेट किए गए टेक्स्ट को रेंडर करने की कोशिश करेगा और ग्लिफ़ का मेज़रमेंट करेगा. अगर ग्लिफ़, कॉर्पोरेट फ़ॉन्ट के जाने-पहचाने आकार से मेल खाते हैं, तो हमलावर को सफलता मिल जाती है. अगर ग्लिफ़ मैच नहीं करते हैं, तो हमलावर को पता चल जाता है कि कॉर्पोरेट फ़ॉन्ट इंस्टॉल न होने की वजह से, डिफ़ॉल्ट रिप्लेसमेंट फ़ॉन्ट का इस्तेमाल किया गया है. इस और ब्राउज़र फ़िंगरप्रिंटिंग के अन्य हमलों के बारे में पूरी जानकारी के लिए, Laperdix et al. का सर्वे पेपर पढ़ें.
कंपनी के फ़ॉन्ट के अलावा, इंस्टॉल किए गए फ़ॉन्ट की सूची से भी पहचान ज़ाहिर हो सकती है. इस अटैक वेक्टर की वजह से, स्थिति इतनी खराब हो गई है कि हाल ही में WebKit टीम ने फ़ैसला किया है कि "उपलब्ध फ़ॉन्ट की सूची में सिर्फ़ वेब फ़ॉन्ट और ऑपरेटिंग सिस्टम के साथ आने वाले फ़ॉन्ट शामिल किए जाएंगे. हालांकि, उपयोगकर्ता के इंस्टॉल किए गए फ़ॉन्ट शामिल नहीं किए जाएंगे". (और यहां मैं, स्थानीय फ़ॉन्ट का ऐक्सेस देने के बारे में एक लेख के साथ हूं.)
Local Font Access API
इस लेख की शुरुआत में दी गई जानकारी से, शायद आपका मूड खराब हो गया हो. क्या हमें वाकई अच्छी चीज़ें नहीं मिल सकतीं? चिंता न करें. हमें लगता है कि हम ऐसा कर सकते हैं. शायद, सब कुछ ठीक हो जाए. हालांकि, इससे पहले मैं आपके एक सवाल का जवाब देना चाहता/चाहती हूँ.
वेब फ़ॉन्ट उपलब्ध होने पर, हमें Local Font Access API की ज़रूरत क्यों पड़ती है?
प्रोफ़ेशनल क्वालिटी के डिज़ाइन और ग्राफ़िक टूल को वेब पर उपलब्ध कराना हमेशा से ही मुश्किल रहा है. एक समस्या यह है कि डिज़ाइनर, स्थानीय तौर पर इंस्टॉल किए गए अलग-अलग तरह के फ़ॉन्ट को ऐक्सेस और इस्तेमाल नहीं कर पाते हैं. इन फ़ॉन्ट को प्रोफ़ेशनल तरीके से बनाया गया होता है और इनमें हिंटिंग की सुविधा होती है. वेब फ़ॉन्ट से पब्लिशिंग के कुछ इस्तेमाल के उदाहरणों को चालू किया जा सकता है. हालांकि, ये वेक्टर ग्लिफ़ शेप और फ़ॉन्ट टेबल के प्रोग्रामैटिक ऐक्सेस को चालू नहीं कर पाते. इनका इस्तेमाल, रास्टराइज़र, ग्लिफ़ आउटलाइन को रेंडर करने के लिए करते हैं. इसी तरह, वेब फ़ॉन्ट के बाइनरी डेटा को ऐक्सेस करने का कोई तरीका नहीं है.
- डिज़ाइन टूल को फ़ॉन्ट बाइट का ऐक्सेस चाहिए, ताकि वे OpenType लेआउट को लागू कर सकें. साथ ही, डिज़ाइन टूल को निचले लेवल पर हुक करने की अनुमति दे सकें. ऐसा वेक्टर फ़िल्टर लागू करने या ग्लिफ़ के आकार में बदलाव करने जैसी कार्रवाइयों के लिए किया जाता है.
- डेवलपर के पास अपने ऐप्लिकेशन के लिए लेगसी फ़ॉन्ट स्टैक हो सकते हैं. ये ऐप्लिकेशन, वेब पर उपलब्ध कराए जा रहे हैं. इन स्टैक का इस्तेमाल करने के लिए, आम तौर पर फ़ॉन्ट डेटा को सीधे तौर पर ऐक्सेस करने की ज़रूरत होती है. वेब फ़ॉन्ट ऐसा नहीं करते.
- ऐसा हो सकता है कि कुछ फ़ॉन्ट को वेब पर डिलीवर करने के लिए लाइसेंस न मिला हो. उदाहरण के लिए, Linotype के पास कुछ ऐसे फ़ॉन्ट का लाइसेंस है जिनका इस्तेमाल सिर्फ़ डेस्कटॉप पर किया जा सकता है.
Local Font Access API, इन चुनौतियों को हल करने की एक कोशिश है. इसके दो हिस्से होते हैं:
- फ़ॉन्ट की गिनती करने वाला एपीआई. इसकी मदद से, उपयोगकर्ता सिस्टम में मौजूद सभी फ़ॉन्ट का ऐक्सेस दे सकते हैं.
- गिनती किए गए हर नतीजे से, लो-लेवल (बाइट-ओरिएंटेड) SFNT कंटेनर ऐक्सेस का अनुरोध करने की सुविधा. इसमें फ़ॉन्ट का पूरा डेटा शामिल होता है.
ब्राउज़र समर्थन
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);
}
अगर आपको सिर्फ़ कुछ फ़ॉन्ट में दिलचस्पी है, तो postscriptNames पैरामीटर जोड़कर, उन्हें PostScript नामों के आधार पर फ़िल्टर भी किया जा सकता है.
const availableFonts = await window.queryLocalFonts({
postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});
SFNT डेटा ऐक्सेस करना
FontData ऑब्जेक्ट के blob() तरीके से, SFNT का पूरा ऐक्सेस मिलता है. 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 repo पर, स्पेसिफ़िकेशन से जुड़ी समस्या की शिकायत करें या किसी मौजूदा समस्या के बारे में अपने विचार जोड़ें.
लागू करने से जुड़ी समस्या की शिकायत करना
क्या आपको Chrome के साथ काम करने में कोई गड़बड़ी मिली? या क्या लागू करने का तरीका, स्पेसिफ़िकेशन से अलग है?
new.crbug.com पर जाकर, गड़बड़ी की शिकायत करें. इसमें ज़्यादा से ज़्यादा जानकारी शामिल करें. साथ ही, गड़बड़ी को दोहराने के लिए आसान निर्देश दें. इसके अलावा, कॉम्पोनेंट बॉक्स में Blink>Storage>FontAccess डालें.
एपीआई के लिए अपना सपोर्ट दिखाना
क्या आपको Local Font Access API का इस्तेमाल करना है? सार्वजनिक तौर पर की गई आपकी मदद से, Chrome टीम को सुविधाओं को प्राथमिकता देने में मदद मिलती है. साथ ही, इससे अन्य ब्राउज़र वेंडर को यह पता चलता है कि इन सुविधाओं को सपोर्ट करना कितना ज़रूरी है.
@ChromiumDev को ट्वीट करें. इसके लिए, हैशटैग #LocalFontAccess का इस्तेमाल करें. साथ ही, हमें बताएं कि इसका इस्तेमाल कहां और कैसे किया जा रहा है.
काम के लिंक
- समझाने वाला
- ड्राफ़्ट स्पेसिफ़िकेशन
- फ़ॉन्ट की गिनती के लिए Chromium में गड़बड़ी
- फ़ॉन्ट टेबल ऐक्सेस करने से जुड़ी Chromium की समस्या
- ChromeStatus एंट्री
- GitHub repo
- TAG की समीक्षा
- Mozilla के स्टैंडर्ड की स्थिति
Acknowledgements
Local Font Access API के स्पेसिफ़िकेशन में बदलाव, Emil A. Eklund, Alex Russell, Joshua Bell, and Olivier Yiptong. इस लेख की समीक्षा जो मेडली, डोमिनिक रोट्शेस, और ओलिवियर यिप्टॉन्ग ने की है.