2010-08-12 23 views
6

Chữ ghép là các ký tự Unicode được biểu thị bằng nhiều hơn một điểm mã. Ví dụ: trong Devanagari त्र là một đường bao gồm các điểm mã त + ् + र.Phát hiện chữ ligatures Unicode trong Clojure/Java

Khi nhìn thấy trong các trình chỉnh sửa tệp văn bản đơn giản như Notepad, त्र được hiển thị là त् + र và được lưu trữ dưới dạng ba ký tự Unicode. Tuy nhiên, khi cùng một tệp được mở trong Firefox, nó được hiển thị dưới dạng một kết nối thích hợp.

Vì vậy, câu hỏi của tôi là, cách phát hiện các chữ ghép đó theo chương trình khi đọc tệp từ mã của tôi. Kể từ khi Firefox làm điều đó, phải tồn tại một cách để làm điều đó theo lập trình. Có bất kỳ thuộc tính Unicode nào chứa thông tin này hoặc tôi có cần phải có một bản đồ cho tất cả các chữ ghép đó không?

Thuộc tính CSS SVG text-rendering khi được đặt thành optimizeLegibility thực hiện điều tương tự (kết hợp các điểm mã vào đúng kết nối).

PS: Tôi đang sử dụng Java.

EDIT

Mục đích của mã của tôi là để đếm số ký tự trong văn bản Unicode giả định một dấu gạch nối để trở thành một nhân vật duy nhất. Vì vậy, tôi cần một cách để thu gọn nhiều điểm mã vào một dây chằng duy nhất.

+0

Bạn có thể giải thích lý do bạn cần điều đó không? Tôi hỏi điều này vì không có cách nào dễ dàng để làm điều này. – sorin

+0

@SorinSbarnea: Tôi đã thêm mục đích vào bài đăng. –

+0

Tôi không nghĩ rằng có rất nhiều hy vọng để thực hiện xử lý kịch bản phức tạp một mình. Sử dụng một trong các thư viện hiện có như Uniscribe hoặc libfreetype. – Philipp

Trả lời

1

Trong khi Aaron's answer không chính xác, nó đã đẩy tôi đi đúng hướng. Sau khi đọc qua các tài liệu Java API của java.awt.font.GlyphVector và chơi rất nhiều trên Clojure REPL, tôi đã có thể viết một hàm thực hiện những gì tôi muốn.

Ý tưởng là tìm chiều rộng của hình tượng trong glyphVector và kết hợp các glyph với chiều rộng bằng 0 với chiều rộng không được tìm thấy lần cuối glyph. Giải pháp là trong Clojure nhưng nó nên được dịch sang Java nếu cần thiết.

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

Cũng được đăng on Gist.

2

Trang Computer Typesetting wikipedia nói -

Các máy tính hiện đại La Mã chữ cung cấp với TeX bao gồm năm ligature chung ff, fi, fl, ffi, và FFL. Khi TeX tìm thấy các kết hợp này trong một văn bản, nó thay thế các dây buộc thích hợp , trừ khi ghi đè bởi bộ sắp chữ.

Điều này cho biết rằng đó là trình chỉnh sửa thay thế. Hơn nữa,

Unicode duy trì ligaturing được một vấn đề trình bày chứ không phải là một vấn đề định nghĩa nhân vật, và rằng, ví dụ, "nếu một phông chữ hiện đại là hỏi để hiển thị 'h' tiếp theo 'r' , và phông chữ có hình chữ 'hr' ở , nó có thể hiển thị hình thắt. "

Theo như tôi thấy (tôi đã quan tâm đến chủ đề này và chỉ đọc vài bài báo), hướng dẫn về thay thế ghép được nhúng bên trong phông chữ. Bây giờ, tôi đào sâu hơn và tìm thấy những thứ này cho bạn; GSUB - The Glyph Substitution TableLigature Substitution Subtable từ đặc tả định dạng tệp OpenType.

Tiếp theo, bạn cần tìm một số thư viện có thể cho phép bạn đạt đến đỉnh trong các tệp phông chữ OpenType, tức là tệp phân tích cú pháp để truy cập nhanh.Đọc sau hai thảo luận có thể cung cấp cho bạn một số hướng dẫn trong cách thực hiện những thay:

  1. Chromium lỗi http://code.google.com/p/chromium/issues/detail?id=22240
  2. Firefox lỗi https://bugs.launchpad.net/firefox/+bug/37828
+0

Có vẻ tốt. Tôi sẽ đi qua các bài báo và mã vá lỗi và cố gắng tìm một giải pháp. –

2

gì bạn đang nói về không phải là chữ ghép (tại ít nhất là không phải trong Unicode) nhưng các cụm grapheme. Có một phụ lục tiêu chuẩn mà là có liên quan với việc khám phá ranh giới văn bản, bao gồm ranh giới cụm grapheme:

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

Cũng xem mô tả về cụm grapheme chỉnh cho phù hợp trong biểu thức thông thường:

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

Và định nghĩa về đồ thị đối chiếu:

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

Tôi nghĩ rằng đây là những điểm khởi đầu. Phần khó khăn hơn có lẽ sẽ là tìm một Java thực hiện thuật toán đối chiếu Unicode làm việc cho các ngôn ngữ Devanagari. Nếu bạn tìm thấy nó, bạn có thể phân tích các chuỗi mà không cần đến các tính năng của OpenType. Điều này sẽ sạch hơn một chút vì OpenType có liên quan đến các chi tiết thuần túy và không phải với các thuật ngữ cụm ký tự hoặc grapheme, nhưng thuật toán đối chiếu và thuật toán tìm đường biên grapheme được thiết kế trông giống như chúng có thể được thực hiện độc lập với phông chữ.

+0

Đây không phải là một cụm grapheme. Ligutures là sự kết hợp của một số đồ thị (cụm grapheme). Ví dụ trên là một kết cấu gồm hai cụm, đầu tiên là hai ký tự và thứ hai là một. Tôi đã thực hiện một UAX-29 và đây là các cụm: đầu tiên là hai ký tự (् (kết thúc bằng dấu kết hợp virama) và thứ hai là một ký tự र –

1

Bạn có thể nhận thông tin này từ lớp GlyphVector.

Đối với chuỗi đã cho, thể hiện Phông chữ có thể tạo GlyphVector có thể cung cấp thông tin về hiển thị văn bản.

Phương thức layoutGlyphVector() trên Phông chữ có thể cung cấp điều này.

Thuộc tính FLAG_COMPLEX_GLYPHS của GlyphVector có thể cho bạn biết nếu văn bản không có ánh xạ từ 1 đến 1 với các ký tự nhập.

Các mã sau đây cho thấy một ví dụ về điều này:

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 nên đại diện cho số ký tự dùng để hiển thị văn bản đầu vào.

Thật không may là bạn cần phải tạo một thành phần GUI java để lấy FontRenderContext.

+0

Không hoạt động. 'hasComplexGlyphs' có giá trị true nhưng' numberOfGlyphs' trả về cùng số với độ dài của văn bản unicode. –

0

Tôi nghĩ rằng những gì bạn đang thực sự tìm kiếm là Unicode Normalization.

Đối với Java bạn nên kiểm tra http://download.oracle.com/javase/6/docs/api/java/text/Normalizer.html

Bằng cách lựa chọn bình thường thích mẫu bạn có thể có được những gì bạn đang tìm kiếm.

+0

Không hoạt động. Tất cả các chế độ chuẩn hóa trả về cùng văn bản với đầu vào. –

+0

Bình thường hóa hoạt động trên mức độ mã điểm và quan hệ tương đương Unicode và không có khái niệm về các cụm grapheme. – Philipp

Các vấn đề liên quan