Scopri come l'API Accesso ai caratteri locali ti consente di accedere ai caratteri installati localmente dall'utente e di ottenere dettagli di basso livello su di essi
Caratteri sicuri per il web
Se ti occupi di sviluppo web da abbastanza tempo, potresti ricordare i cosiddetti
font web safe.
Questi caratteri sono noti per essere disponibili su quasi tutte le istanze dei sistemi operativi più utilizzati (ovvero Windows, macOS, le distribuzioni Linux più comuni, Android e iOS). All'inizio degli anni 2000,
Microsoft ha persino lanciato un'iniziativa
chiamata Caratteri di base TrueType per il web che forniva questi caratteri per il download senza costi con l'obiettivo che "ogni volta che visiti un sito web che li specifica, vedrai le pagine esattamente come previsto dal designer del sito". Sì, sono inclusi i siti impostati su
Comic Sans MS. Ecco un
classico stack di caratteri sicuri per il web (con il fallback finale di qualsiasi carattere
sans-serif
) che potrebbe avere il seguente aspetto:
body {
font-family: Helvetica, Arial, sans-serif;
}
Caratteri web
I tempi in cui i caratteri web sicuri erano davvero importanti sono lontani. Oggi abbiamo i caratteri web, alcuni dei quali sono persino caratteri variabili che possiamo modificare ulteriormente modificando i valori per i vari assi esposti. Puoi utilizzare i caratteri web dichiarando un blocco @font-face
all'inizio del CSS, che specifica i file dei caratteri da scaricare:
@font-face {
font-family: 'FlamboyantSansSerif';
src: url('flamboyant.woff2');
}
Dopodiché, puoi utilizzare il carattere web personalizzato specificando font-family
, come di consueto:
body {
font-family: 'FlamboyantSansSerif';
}
Caratteri locali come vettore di impronte
La maggior parte dei caratteri web proviene, indovinate un po', dal web. Un fatto interessante, però, è che la proprietà
src
nella dichiarazione @font-face
, oltre alla funzione
url()
, accetta anche una funzione
local()
. In questo modo, i caratteri personalizzati possono essere caricati localmente. Se l'utente ha installato
FlamboyantSansSerif sul proprio sistema operativo, verrà utilizzata la copia locale anziché scaricarla:
@font-face {
font-family: 'FlamboyantSansSerif';
src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}
Questo approccio fornisce un ottimo meccanismo di riserva che consente di risparmiare potenzialmente sulla larghezza di banda. Purtroppo, su internet non possiamo avere cose belle. Il problema con la funzione local()
è che può essere usata in modo improprio per l'impronta del browser. A quanto pare, l'elenco dei caratteri installati da un utente può essere molto identificativo. Molte aziende hanno i propri caratteri aziendali installati sui laptop dei dipendenti. Ad esempio, Google ha un carattere aziendale chiamato Google Sans.
Un malintenzionato può provare a determinare per quale azienda lavora una persona verificando l'esistenza di un gran numero di caratteri aziendali noti come Google Sans. L'attaccante tenterà di eseguire il rendering del testo impostato su questi caratteri su una tela e di misurare i glifi. Se i glifi corrispondono alla forma nota del carattere aziendale, l'attaccante ha un hit. Se i glifi non corrispondono, l'aggressore sa che è stato utilizzato un carattere di sostituzione predefinito poiché il carattere aziendale non è stato installato. Per informazioni dettagliate su questo e su altri attacchi di fingerprinting del browser, leggi il report di sondaggio di Laperdix et al.
A parte i caratteri dell'azienda, anche solo l'elenco dei caratteri installati può essere un elemento di identificazione. La situazione con questo vettore di attacco è diventata così grave che di recente il team di WebKit ha deciso di "includere [nell'elenco dei caratteri disponibili] solo i caratteri web e i caratteri forniti con il sistema operativo, ma non i caratteri installati localmente dall'utente". Eccomi qui con un articolo su come concedere l'accesso ai caratteri locali.
L'API Local Fonts Access
L'inizio di questo articolo potrebbe averti messo di cattivo umore. Non possiamo davvero avere cose belle? Non preoccuparti. Pensiamo di potercela fare e forse non tutto è perduto. Ma prima, rispondi a una domanda che potresti farti.
Perché abbiamo bisogno dell'API Accesso ai caratteri locali se esistono caratteri web?
È sempre stato difficile trovare strumenti di progettazione e grafica di qualità professionale sul web. Un ostacolo è stato l'impossibilità di accedere e utilizzare l'intera gamma di caratteri professionali costruiti e con indicatori che i designer hanno installato localmente. I caratteri web consentono alcuni use case di pubblicazione, ma non attivano l'accesso programmatico alle forme dei glifi vettoriali e alle tabelle dei caratteri utilizzate dai rasterizzatori per il rendering dei contorni dei glifi. Allo stesso modo, non è possibile accedere ai dati binari di un carattere web.
- Gli strumenti di progettazione devono accedere ai byte dei caratteri per eseguire la propria implementazione del layout OpenType e consentire agli strumenti di progettazione di collegarsi a livelli inferiori, per azioni come l'applicazione di filtri vettoriali o trasformazioni alle forme dei glifi.
- Gli sviluppatori potrebbero avere stack di caratteri precedenti per le loro applicazioni che stanno portando sul web. Per utilizzare questi stack, in genere è necessario l'accesso diretto ai dati dei caratteri, cosa che i caratteri web non forniscono.
- Alcuni caratteri potrebbero non essere concessi in licenza per la pubblicazione sul web. Ad esempio, Linotype ha una licenza per alcuni caratteri che include solo l'utilizzo su computer.
L'API Accesso ai caratteri locali è un tentativo di risolvere questi problemi. È composto da due parti:
- Un'API di enumerazione dei caratteri, che consente agli utenti di concedere l'accesso all'insieme completo dei caratteri sistema disponibili.
- Da ogni risultato dell'enumerazione, la possibilità di richiedere l'accesso ai contenitori SFNT a basso livello (orientato a byte) che include i dati completi dei caratteri.
Supporto browser
Come utilizzare l'API Accesso ai caratteri locali
Rilevamento di funzionalità
Per verificare se l'API Local Font Access è supportata, utilizza:
if ('queryLocalFonts' in window) {
// The Local Font Access API is supported
}
Elenco dei caratteri locali
Per ottenere un elenco dei caratteri installati localmente, devi chiamare window.queryLocalFonts()
. La prima volta verrà attivata una richiesta di autorizzazione, che l'utente potrà approvare o negare. Se l'utente approva la query sui caratteri locali, il browser restituirà un array con i dati dei caratteri su cui puoi eseguire un ciclo. Ogni carattere è rappresentato come un oggetto FontData
con le proprietà family
(ad esempio "Comic Sans MS"
), fullName
(ad esempio "Comic Sans MS"
), postscriptName
(ad eg."ComicSansMS"
) e style
(ad es. "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);
}
Se ti interessa solo un sottoinsieme di caratteri, puoi anche filtrarli in base ai nomi PostScript aggiungendo un parametro postscriptNames
.
const availableFonts = await window.queryLocalFonts({
postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});
Accesso ai dati SFNT
L'accesso completo a SFNT è disponibile tramite il metodo blob()
dell'oggetto
FontData
. SFNT è un formato di file di caratteri che può contenere altri caratteri, ad esempio PostScript, TrueType, OpenType, Web Open Font Format (WOFF) e altri.
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);
}
Demo
Puoi vedere l'API Local Font Access in azione nella
demo di seguito. Assicurati di controllare anche il
codice sorgente. La demo mostra un elemento personalizzato chiamato <font-select>
che implementa un selettore di caratteri locale.
Considerazioni sulla privacy
L'autorizzazione "local-fonts"
sembra fornire una superficie altamente rilevabile. Tuttavia, i browser sono liberi di restituire qualsiasi cosa. Ad esempio, i browser incentrati sull'anonimato possono scegliere di fornire solo un insieme di caratteri predefiniti integrati nel browser. Analogamente, i browser non sono tenuti a fornire i dati della tabella esattamente come appaiono sul disco.
Ove possibile, l'API Local Font Access è progettata per esporre solo le informazioni necessarie per abilitare i casi d'uso menzionati. Le API di sistema potrebbero produrre un elenco di caratteri installati non in ordine alfabetico o casuale, ma nell'ordine di installazione. Il ritorno esatto dell'elenco dei caratteri installati fornito da un'API di sistema di questo tipo può esporre dati aggiuntivi che potrebbero essere utilizzati per il fingerprinting e i casi d'uso che vogliamo abilitare non sono supportati dal mantenimento di questo ordinamento. Di conseguenza, questa API richiede che i dati restituiti vengano ordinati prima di essere restituiti.
Sicurezza e autorizzazioni
Il team di Chrome ha progettato e implementato l'API Local Font Access utilizzando i principi fondamentali definiti in Controllo dell'accesso a funzionalità potenti della piattaforma web, tra cui il controllo dell'utente, la trasparenza e l'ergonomia.
Controllo utente
L'accesso ai caratteri di un utente è completamente sotto il suo controllo e non sarà consentito a meno che non venga concessa l'autorizzazione"local-fonts"
, indicata nel registro delle autorizzazioni.
Trasparenza
La presenza o meno di un sito a cui è stato concesso l'accesso ai caratteri locali dell'utente sarà visibile nella scheda informativa del sito.
Persistenza delle autorizzazioni
L'autorizzazione "local-fonts"
verrà mantenuta tra i ricaricamenti della pagina. Può essere revocata tramite il foglio Informazioni sul sito.
Feedback
Il team di Chrome vuole conoscere le tue esperienze con l'API Local Font Access.
Fornisci informazioni sul design dell'API
C'è qualcosa nell'API che non funziona come previsto? Oppure mancano metodi o proprietà di cui hai bisogno per implementare la tua idea? Hai domande o commenti sul modello di sicurezza? Invia una segnalazione relativa alle specifiche nel repository GitHub corrispondente o aggiungi il tuo parere a un problema esistente.
Segnalare un problema con l'implementazione
Hai trovato un bug nell'implementazione di Chrome? Oppure l'implementazione è diversa dalla specifica?
Segnala un bug all'indirizzo new.crbug.com. Assicurati di includere il maggior numero di dettagli possibile, istruzioni semplici per la riproduzione e inserisci Blink>Storage>FontAccess
nella casella Componenti.
Glitch è ideale per condividere riproduzioni rapide e semplici.
Mostra il supporto per l'API
Hai intenzione di utilizzare l'API Accesso ai caratteri locali? Il tuo supporto pubblico aiuta il team di Chrome a dare la priorità alle funzionalità e mostra ad altri fornitori di browser quanto sia fondamentale supportarle.
Invia un tweet a @ChromiumDev utilizzando l'hashtag
#LocalFontAccess
e facci sapere dove e come lo stai utilizzando.
Link utili
- Spiegazione
- Bozza delle specifiche
- Bug di Chromium per l'enumerazione dei caratteri
- Bug di Chromium per l'accesso alla tabella dei caratteri
- Voce ChromeStatus
- Repository GitHub
- Revisione TAG
- Posizione di Mozilla sugli standard
Ringraziamenti
La specifica dell'API Local Font Access è stata modificata da Emil A. Eklund, Alex Russell, Joshua Bell e Olivier Yiptong. Questo articolo è stato esaminato da Joe Medley, Dominik Röttsches e Olivier Yiptong. Immagine hero di Brett Jordan su Unsplash.