Pregunta

Las ligaduras son los caracteres Unicode que están representados por más de un código de puntos. Por ejemplo, en Devanagari त्र es una ligadura que consta de puntos de código त + ् + र.

Cuando se ve en simples editores de archivos de texto como el Bloc de notas, त्र se muestra como त् + र y se almacena como tres caracteres Unicode. Sin embargo, cuando el mismo archivo se abre en Firefox, que se muestra como una ligadura adecuada.

Así que mi pregunta es, ¿cómo detectar dichas ligaduras mediante programación al leer el archivo de mi código. Dado que Firefox lo hace, debe existir una manera de hacerlo mediante programación. ¿Hay algunas propiedades Unicode que contienen esta información o tengo que tener un mapa de tales ligaduras?

text-rendering Cuando se establece en optimizeLegibility hace lo mismo (se combinan puntos de código en la ligadura adecuada).

PS:. Estoy usando Java

editar

El propósito de mi código es contar los caracteres del texto Unicode asumiendo una ligadura a ser un único carácter. Así que necesito una manera de colapsar múltiples puntos de código en una sola ligadura.

¿Fue útil?

Solución 4

Si bien la respuesta de Aaron no es exactamente correcta, me empujó en la dirección correcta. Después de leer a través de los documentos de la API de Java de java.awt.font.GlyphVector y jugar mucho en el Clojure REPL, yo era capaz de escribir una función que hace lo que yo quiero.

La idea es encontrar el ancho de glifos de la glyphVector y combinar los glifos con un ancho de cero con el fin encontró glifo ancho distinto de cero. La solución está en Clojure pero debe ser traducible a Java, si es necesario.

(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))))))))))

de Gist .

Otros consejos

ordenador Typesetting dice -

  

El tipo de letra Computer Modern Roman   proporcionado con TeX incluye los cinco   ligaduras comunes ff, fi, fi, fi, y   ffl. Cuando TeX encuentra estas combinaciones   en un texto que sustituye la   ligadura apropiado, a menos   anulado por la máquina de componer.

Esto indica que es el editor que hace la sustitución. Por otra parte,

  

Unicode sostiene que es ligadura   un problema de presentación en lugar de una   cuestión de la definición de caracteres, y que,   por ejemplo, "si una fuente moderna es   pedido para mostrar 'h' seguido por 'r',   y la fuente tiene una ligadura 'hr' en   ella, puede mostrar la ligadura ".

Por lo que veo (Tengo cierto interés en este tema y ahora la lectura de algunos artículos), las instrucciones para sustituir ligadura es Embebido en el interior de la fuente. Ahora, cavé en más y encontré esto para usted; GSUB - El Glyph tabla de sustitución de y Ligadura Sustitución Subtabla de la especificación de formato de archivo OpenType.

A continuación, es necesario encontrar alguna biblioteca que le puede permitir a pico dentro de los archivos de fuentes OpenType, es decir analizador de archivos para un acceso rápido. La lectura de los dos siguientes discusiones le puede dar algunas indicaciones de cómo hacer estas sustituciones:

  1. http://code.google.com/p / cromo / temas / detalle? id = 22240
  2. https://bugs.launchpad.net/firefox/+bug/37828

Lo que estamos hablando no son ligaduras (al menos no en el lenguaje Unicode), pero grupos de grafemas. Hay un anexo estándar que tiene que ver con el descubrimiento de límites de texto, incluyendo límites de las agrupaciones grafema:

http://www.unicode.org/reports/tr29 /tr29-15.html#Grapheme_Cluster_Boundaries

También ver la descripción de los grupos de grafema medida en expresiones regulares:

http://unicode.org/reports/tr18/#Tailored_Graphemes_Clusters

Y la definición de grafemas intercalación:

http://www.unicode.org/reports/tr10/#Collation_Graphemes

creo que estos son puntos de partida. La parte más difícil probablemente será encontrar una implementación de Java del algoritmo de intercalación Unicode que trabaja para las configuraciones regionales devanagari. Si encuentra uno, se puede analizar cadenas sin recurrir a funciones OpenType. Esto sería un poco más limpio desde OpenType se ocupa de los detalles solamente a la presentación y no con carácter o la semántica de racimo de grafema, pero el algoritmo de cotejo y el aspecto algoritmo de medida grafema cúmulo límite encontrando como si se pueden implementar de forma independiente de las fuentes.

puede ser capaz de obtener esta información de la clase GlyphVector.

Para un determinado cuerdas de una instancia de fuente puede crear un GlyphVector que puede proporcionar información acerca de la prestación del texto.

La layoutGlyphVector () método de la fuente puede proporcionar esto.

El FLAG_COMPLEX_GLYPHS atributo del GlyphVector puede decir si el texto no tiene una correspondencia 1 a 1 con los caracteres de entrada.

El código siguiente muestra un ejemplo de esto:

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 debe representar el número de caracteres que se utilizan para visualizar el texto de entrada.

Por desgracia, es necesario crear un componente de interfaz gráfica de usuario Java para obtener el FontRenderContext.

Creo que lo que realmente está buscando es Unicode Normalization.

Para Java debe comprobar http: // download.oracle.com/javase/6/docs/api/java/text/Normalizer.html

Al elegir la forma correcta normalización se puede obtener lo que busca.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top