Quando si creano documenti PDF con i font OpenType in iText, desidero accedere alle varianti di glifo all'interno del carattere, in particolare figure tabulari. Poiché le varianti di glifi di OpenType non hanno indici Unicode, non sono sicuro di come specificare che voglio usare un particolare insieme di varianti (figure tabulari) o di chiamare un glifo specifico tramite il suo ID di glifo. Sto solo cercando il nome della classe iText pertinente se ne esiste uno.Accesso alle varianti di glifi OpenType in iText
risposta
Questo non sembra essere possibile né nell'ultimo tag 5.5.8, né nel ramodi iText.
Come spiegato in this article e nelle varianti OpenType font file specification, glifi della Microsoft sono memorizzati nella Glyph Substitution Table (GSUB)
di un file di font. L'accesso alle varianti di glifo richiede la lettura di questa tabella dal file, che è attualmente implementato nella classe com.itextpdf.text.pdf.fonts.otf.GlyphSubstitutionTableReader
, sebbene questa classe sia disabilitata per ora.
La chiamata readGsubTable()
nella classe com.itextpdf.text.pdf.TrueTypeFontUnicode
è commentata.
void process(byte ttfAfm[], boolean preload) throws DocumentException, IOException {
super.process(ttfAfm, preload);
//readGsubTable();
}
Si scopre che questa linea è disabilitata per una ragione, come il codice in realtà non funziona se si tenta di attivarlo.
Quindi, sfortunatamente, non è possibile utilizzare le varianti di glifo, poiché le informazioni di sostituzione non vengono mai caricate dal file di font.
Aggiornamento
La risposta originale era circa la possibilità di utilizzare per l'accesso iText API
glifo varianti fuori dalla scatola, che non c'è ancora. Tuttavia, il codice di basso livello è a posto e può essere utilizzato dopo un po 'di hacking per accedere alla tabella di mappatura di sostituzione degli glifi.
Quando chiamato read()
, il GlyphSubstitutionTableReader
legge la tabella GSUB
e appiattisce sostituzioni di tutte le funzioni in un unico mappa Map<Integer, List<Integer>> rawLigatureSubstitutionMap
. I nomi simbolici delle funzioni sono attualmente scartati da OpenTypeFontTableReader
. Il rawLigatureSubstitutionMap
Mappe una variante glyphId
ad una base glyphId
, o una legatura glyphId
ad una sequenza di glyphIds
come questo:
629 -> 66 // a.feature -> a
715 -> 71, 71, 77 // ffl ligature
Questa mappatura può essere invertito per ottenere tutte le varianti per una base glyphId
. Quindi tutti i glifi estesi con valori unicode sconosciuti possono essere individuati attraverso la loro connessione a un glifo di base, o una sequenza di glifi.
Successivamente, per poter scrivere un glifo in PDF, è necessario conoscere un valore unicode per tale glyphId
. Una relazione unicode -> glyphId
viene mappata da un campo cmap31
in TrueTypeFont
. L'inversione della mappa dà l'unicode di glyphId.
tweaking
rawLigatureSubstitutionMap
non può essere letta in GlyphSubstitutionTableReader
, come si tratta di un membro private
e non ha una funzione di accesso getter.L'hack semplice sarebbe quella di copiare e incollare la classe originale e aggiungere un getter per la mappa:
public class HackedGlyphSubstitutionTableReader extends OpenTypeFontTableReader {
// copy-pasted code ...
public Map<Integer, List<Integer>> getRawSubstitutionMap() {
return rawLigatureSubstitutionMap;
}
}
problema successivo è che GlyphSubstitutionTableReader
ha bisogno di un offset per GSUB
tavolo, le informazioni che sono memorizzate in protected HashMap<String, int[]> tables
di TrueTypeFont
di classe. Una classe helper inserita nello stesso pacchetto consentirà il collegamento tra gli utenti protetti di TrueTypeFont
.
package com.itextpdf.text.pdf;
import com.itextpdf.text.pdf.fonts.otf.FontReadingException;
import java.io.IOException;
import java.util.List;
import java.util.Map;
public class GsubHelper {
private Map<Integer, List<Integer>> rawSubstitutionMap;
public GsubHelper(TrueTypeFont font) {
// get tables offsets from the font instance
Map<String, int[]> tables = font.tables;
if (tables.get("GSUB") != null) {
HackedGlyphSubstitutionTableReader gsubReader;
try {
gsubReader = new HackedGlyphSubstitutionTableReader(
font.rf, tables.get("GSUB")[0], glyphToCharacterMap, font.glyphWidthsByIndex);
gsubReader.read();
} catch (IOException | FontReadingException e) {
throw new IllegalStateException(e.getMessage());
}
rawSubstitutionMap = gsubReader.getRawSubstitutionMap();
}
}
/** Returns a glyphId substitution map
*/
public Map<Integer, List<Integer>> getRawSubstitutionMap() {
return rawSubstitutionMap;
}
}
Sarebbe bello estendere TrueTypeFont
, ma che non avrebbe funzionato con i metodi di fabbrica createFont()
di BaseFont
, che si basa sui nomi di classe hard coded durante la creazione di un tipo di carattere.
Tu parli e citi con autorità; tuttavia, trovo difficile credere che non sia possibile analizzare le tabelle GSUB con Java. Intendi dire che anche se * puoi * analizzare una tabella GSUB, iText non contiene l'infrastruttura per lavorare con gli indici di "raw", e quindi come parte dell'aggiunta di sostituzioni di GSUB, l'attuale paradigma di gestione del testo di iText avrebbe bisogno sostituzione nella sua interezza? – usr2564301
Scusate, la mia risposta è davvero troppo categorica, persino folle. Non riflette tutta la verità. Quello che intendevo era che l'API per l'utilizzo delle sostituzioni di glifi non è stata completata nella versione corrente di iText. Ma l'infrastruttura è principalmente sul posto. Può essere usato con alcuni copia-incolla e messa a punto delle classi iText. Ho intenzione di aggiornare la mia risposta con maggiori dettagli. – nolexa
Penso che il basso livello di GSUB sia ok. Ogni sezione di dati sembra essere analizzata dal file (non ci sono test per questa funzionalità). Ma il livello API è incompleto, i dati grezzi rimangono incapsulati all'interno delle classi dell'infrastruttura, non consegnati all'API attraverso casi d'uso significativi. Allo stesso modo, le classi chiave di iText in questa storia non sono progettate per l'estensione, il che rende difficile personalizzare la soluzione. – nolexa
Forse ['Class GlyphSubstitutionTableReader'] (http://api.itextpdf.com/itext/com/itextpdf/text/pdf/fonts/otf/GlyphSubstitutionTableReader.html#getGlyphSubstitutionMap()) vale la pena dare un'occhiata. Utilizza ['OpenTypeFontTableReader'] (http://api.itextpdf.com/itext/com/itextpdf/text/pdf/fonts/otf/OpenTypeFontTableReader.html) - ma, a colpo d'occhio, sembra che tu debba sapere in anticipare quale tabella si desidera leggere. (È ancora poco chiaro che cosa si può fare con il "glifo" grezzo.) – usr2564301
Questo sarebbe di aiuto? La classe 'GlyphList' ha un metodo statico:' String unicodeToName (int) '[http://developers.itextpdf.com/reference/com.itextpdf.text.pdf.GlyphList] –