Rilevazione Unicode legature di testo in Clojure / Java
Domanda
legature sono caratteri Unicode che sono rappresentati da più punti di codice. Ad esempio, in Devanagari त्र
è una legatura che consiste di punti di codice त + ् + र
.
Quando visto in semplici editor di file di testo come Blocco note, त्र
è mostrato come त् + र
ed è archiviato come tre caratteri Unicode. Tuttavia, quando lo stesso file viene aperto in Firefox, si è mostrato come una vera e propria legatura.
Quindi la mia domanda è, come rilevare tali legature di programmazione durante la lettura del file dal mio codice. Dal momento che Firefox lo fa, deve esistere un modo per farlo a livello di codice. Ci sono delle proprietà Unicode che contengono queste informazioni o ho bisogno di avere una mappa di tutti tali legature?
text-rendering
se impostato su optimizeLegibility
fa la stessa cosa (si combinano punti di codice in una corretta legatura).
PS:. Sto usando Java
Modifica
Lo scopo del mio codice è quello di contare i caratteri nel testo Unicode assumendo una legatura di essere un singolo carattere. Quindi ho bisogno di un modo per comprimere molteplici punti di codice in un unico legatura.
Soluzione 4
Mentre la risposta di Aaron non è esattamente corretto, mi ha spinto nella direzione giusta. Dopo la lettura attraverso la documentazione Java API di java.awt.font.GlyphVector
e giocando molto sulla Clojure REPL, sono stato in grado di scrivere una funzione che fa quello che voglio.
L'idea è quella di trovare la larghezza dei glifi nel glyphVector
e combinare i glifi con larghezza pari a zero con l'ultimo trovato non da zero larghezza glifo. La soluzione è in Clojure ma dovrebbe essere traducibile a Java, se necessario.
(ns net.abhinavsarkar.unicode
(:import [java.awt.font TextAttribute GlyphVector]
[java.awt Font]
[javax.swing JTextArea]))
(let [^java.util.Map text-attrs {
TextAttribute/FAMILY "Arial Unicode MS"
TextAttribute/SIZE 25
TextAttribute/LIGATURES TextAttribute/LIGATURES_ON}
font (Font/getFont text-attrs)
ta (doto (JTextArea.) (.setFont font))
frc (.getFontRenderContext (.getFontMetrics ta font))]
(defn unicode-partition
"takes an unicode string and returns a vector of strings by partitioning
the input string in such a way that multiple code points of a single
ligature are in same partition in the output vector"
[^String text]
(let [glyph-vector
(.layoutGlyphVector
font, frc, (.toCharArray text),
0, (.length text), Font/LAYOUT_LEFT_TO_RIGHT)
glyph-num (.getNumGlyphs glyph-vector)
glyph-positions
(map first (partition 2
(.getGlyphPositions glyph-vector 0 glyph-num nil)))
glyph-widths
(map -
(concat (next glyph-positions)
[(.. glyph-vector getLogicalBounds width)])
glyph-positions)
glyph-indices
(seq (.getGlyphCharIndices glyph-vector 0 glyph-num nil))
glyph-index-width-map (zipmap glyph-indices glyph-widths)
corrected-glyph-widths
(vec (reduce
(fn [acc [k v]] (do (aset acc k v) acc))
(make-array Float (count glyph-index-width-map))
glyph-index-width-map))]
(loop [idx 0 pidx 0 char-seq text acc []]
(if (nil? char-seq)
acc
(if-not (zero? (nth corrected-glyph-widths idx))
(recur (inc idx) (inc pidx) (next char-seq)
(conj acc (str (first char-seq))))
(recur (inc idx) pidx (next char-seq)
(assoc acc (dec pidx)
(str (nth acc (dec pidx)) (first char-seq))))))))))
su Gist .
Altri suggerimenti
Computer Composizione dice -
Il carattere tipografico Computer Modern Roman provvisto TeX include cinque legature comuni ff, fi, fl, ffi, e ffl. Quando TeX trova queste combinazioni in un testo sostituisce la appropriata legatura, a meno che prevalga il tipografo.
Questo indica che è l'editor che fa sostituzione. Inoltre,
Unicode sostiene che è legatura un problema di presentazione piuttosto che un personaggio problema definizione, e che, per esempio, "se un font moderno è chiesto di visualizzare 'h' seguito da 'r', e il font ha una legatura 'hr' in esso, è possibile visualizzare la legatura ".
Per quanto riguarda la vedo (ho avuto un certo interesse per questo argomento e solo ora leggendo alcuni articoli), le istruzioni per la legatura sostituto è immerso all'interno di carattere. Ora, ho scavato in più e ho trovato questi per voi; gsub - Il glifo tabella di sostituzione e legature Sostituzione sottotabella dalla specifica formato file OpenType.
Successivamente, è necessario trovare qualche libreria che si può permettere a picco dentro i file dei font OpenType, vale a dire parser di file per un accesso rapido. Leggendo le due seguenti discussioni può dare alcune direzioni di come fare queste sostituzioni:
Che cosa si sta parlando non sono legature (almeno non in Unicode gergo), ma cluster grafema. C'è un allegato standard che si occupa di scoprire i limiti di testo, tra cui i confini di cluster grafema:
http://www.unicode.org/reports/tr29 /tr29-15.html#Grapheme_Cluster_Boundaries
vedere anche la descrizione dei cluster grafema su misura nelle espressioni regolari:
http://unicode.org/reports/tr18/#Tailored_Graphemes_Clusters
E la definizione di regole di confronto grafemi:
http://www.unicode.org/reports/tr10/#Collation_Graphemes
Credo che questi sono punti di partenza. La parte più difficile sarà probabilmente di trovare un'implementazione Java dell'algoritmo regole di confronto Unicode che funziona per locali Devanagari. Se si trova uno, è possibile analizzare le stringhe senza ricorrere a funzioni OpenType. Questo sarebbe un po 'più pulito in quanto OpenType si occupa di dettagli puramente di presentazione e non con il carattere o la semantica a grappolo grafema, ma l'algoritmo di confronto e l'aspetto algoritmo sartoriale grafema grappolo confine trovando come se possono essere implementate in modo indipendente dei font.
Si può essere in grado di ottenere queste informazioni dalla classe GlyphVector.
Per un dato String un'istanza di carattere in grado di creare un GlyphVector in grado di fornire informazioni sulla resa del testo.
Il layoutGlyphVector () metodo sul font può fornire questo.
Il FLAG_COMPLEX_GLYPHS attributo del GlyphVector può dire se il testo non ha un 1 a 1 mappatura con i personaggi di ingresso.
Quanto segue mostra un esempio di codice di questo:
JTextField textField = new JTextField();
String textToTest = "abcdefg";
FontRenderContext fontRenderContext = textField.getFontMetrics(font).getFontRenderContext();
GlyphVector glyphVector = font.layoutGlyphVector(fontRenderContext, textToTest.toCharArray(), 0, 4, Font.LAYOUT_LEFT_TO_RIGHT);
int layoutFlags = glyphVector.getLayoutFlags();
boolean hasComplexGlyphs = (layoutFlags & GlyphVector.FLAG_COMPLEX_GLYPHS) != 0;
int numberOfGlyphs = glyphVector.getNumGlyphs();
numberOfGlyphs dovrebbe rappresentare il numero di caratteri utilizzati per visualizzare il testo di input.
Purtroppo è necessario creare un componente Java GUI per ottenere il FontRenderContext.
Credo che quello che stai veramente cercando è Unicode Normalization
.
Per Java si dovrebbe verificare http: // download.oracle.com/javase/6/docs/api/java/text/Normalizer.html
Con la scelta del modulo di normalizzazione corretta è possibile ottenere ciò che si sta cercando.