5 に答える
Computer Typesettingウィキペディアのページには次のように書かれています -
TeX で提供される Computer Modern Roman 書体には、5 つの一般的な合字 ff、fi、fl、ffi、および ffl が含まれています。TeX は、テキスト内でこれらの組み合わせを見つけると、タイプセッターによってオーバーライドされない限り、適切な合字に置き換えます。
これは、置換を行うのがエディターであることを示しています。さらに、
ユニコードは、合字は文字定義の問題ではなく表現上の問題であると主張しており、たとえば、「最新のフォントで 'h' の後に 'r' を表示するように要求され、そのフォントに 'hr' の合字が含まれている場合。 、合字を表示できます。」
私が見る限り (このトピックに興味を持ち、今いくつかの記事を読んでいます)、合字の代用の指示はフォント内に埋め込まれています。さて、私はさらに掘り下げて、あなたのためにこれらを見つけました。GSUB - OpenType ファイル形式仕様の Glyph Substitution TableとLigature Substitution Subtable 。
次に、OpenType フォント ファイル内のピークを可能にするライブラリ、つまりすばやくアクセスするためのファイル パーサーを見つける必要があります。次の 2 つの説明を読むと、これらの置換を行う方法についていくつかの指示が得られる場合があります。
あなたが話しているのは、合字ではなく(少なくともUnicodeの用語では)、書記素クラスターです。書記素クラスター境界を含むテキスト境界の検出に関係する標準の付録があります。
http://www.unicode.org/reports/tr29/tr29-15.html#Grapheme_Cluster_Boundaries
正規表現で調整された書記素クラスターの説明も参照してください。
http://unicode.org/reports/tr18/#Tailored_Graphemes_Clusters
そして、照合書記素の定義:
http://www.unicode.org/reports/tr10/#Collation_Graphemes
これらが出発点だと思います。難しい部分は、おそらくデーバナーガリーロケールで機能するUnicode照合アルゴリズムのJava実装を見つけることでしょう。見つかった場合は、OpenType機能を使用せずに文字列を分析できます。OpenTypeは文字や書記素クラスターのセマンティクスではなく、純粋に表現の詳細に関係しているため、これは少しわかりやすくなりますが、照合アルゴリズムと調整された書記素クラスター境界検索アルゴリズムは、フォントとは独立して実装できるように見えます。
この情報はGlyphVectorクラスから取得できる場合があります。
特定の文字列に対して、Fontインスタンスは、テキストのレンダリングに関する情報を提供できるGlyphVectorを作成できます。
フォントのlayoutGlyphVector()メソッドはこれを提供できます。
GlyphVectorのFLAG_COMPLEX_GLYPHS属性は、テキストに入力文字との1対1のマッピングがないかどうかを示します。
次のコードは、この例を示しています。
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は、入力テキストの表示に使用される文字数を表す必要があります。
残念ながら、FontRenderContextを取得するにはJavaGUIコンポーネントを作成する必要があります。
アーロンの答えは正確ではありませんが、正しい方向に私を押してくれました. Clojure REPLの Java API ドキュメントを読みjava.awt.font.GlyphVector、Clojure REPL でたくさん遊んだ後、私は自分のやりたいことを行う関数を書くことができました。
アイデアは、 でグリフの幅を見つけ、幅がglyphVectorゼロのグリフを、最後に見つかった幅がゼロでないグリフと結合することです。ソリューションは Clojure にありますが、必要に応じて Java に変換できる必要があります。
(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))))))))))
Gist にも投稿されています。
あなたが本当に探しているのはですUnicode Normalization。
Javaの場合は、http://download.oracle.com/javase/6/docs/api/java/text/Normalizer.htmlを確認する必要があります。
適切な正規化フォームを選択することにより、探しているものを取得できます。