aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenichi Handa2010-07-12 14:25:46 +0900
committerKenichi Handa2010-07-12 14:25:46 +0900
commit6f2cdcd11202a6976a399bed4c071b9ac9ce254f (patch)
treeca480f60a413349000296f91de2cff759fd98da5
parent2300368463c9719839a0289cd6dccaa93d3274cf (diff)
downloademacs-6f2cdcd11202a6976a399bed4c071b9ac9ce254f.tar.gz
emacs-6f2cdcd11202a6976a399bed4c071b9ac9ce254f.zip
Improve Hebrew rendering.
-rw-r--r--lisp/ChangeLog8
-rw-r--r--lisp/language/hebrew.el178
-rw-r--r--src/ChangeLog3
-rw-r--r--src/Makefile.in4
4 files changed, 169 insertions, 24 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index e988b6bdef4..3d8648c86b6 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,11 @@
12010-07-12 Kenichi Handa <handa@m17n.org>
2
3 * language/hebrew.el: Remove no-byte-compile declaration. Change
4 coding: tag to utf-8. Register hebrew-shape-gstring in
5 composition-function-table for 3-character looking back.
6 (hebrew-font-get-precomposed): New function.
7 (hebrew-shape-gstring): Utilize precomposed glyphs if available.
8
12010-07-11 Chong Yidong <cyd@stupidchicken.com> 92010-07-11 Chong Yidong <cyd@stupidchicken.com>
2 10
3 * mouse.el (mouse-drag-track): Handle select-active-regions 11 * mouse.el (mouse-drag-track): Handle select-active-regions
diff --git a/lisp/language/hebrew.el b/lisp/language/hebrew.el
index f024251c60b..89a22d2d238 100644
--- a/lisp/language/hebrew.el
+++ b/lisp/language/hebrew.el
@@ -1,4 +1,4 @@
1;;; hebrew.el --- support for Hebrew -*- coding: iso-2022-7bit; no-byte-compile: t -*- 1;;; hebrew.el --- support for Hebrew -*- coding: utf-8 -*-
2 2
3;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 3;; Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4;; Free Software Foundation, Inc. 4;; Free Software Foundation, Inc.
@@ -59,7 +59,7 @@
59 (nonascii-translation . iso-8859-8) 59 (nonascii-translation . iso-8859-8)
60 (input-method . "hebrew") 60 (input-method . "hebrew")
61 (unibyte-display . hebrew-iso-8bit) 61 (unibyte-display . hebrew-iso-8bit)
62 (sample-text . "Hebrew ,Hylem(B") 62 (sample-text . "Hebrew שלום")
63 (documentation . "Bidirectional editing is supported."))) 63 (documentation . "Bidirectional editing is supported.")))
64 64
65(set-language-info-alist 65(set-language-info-alist
@@ -85,33 +85,167 @@ Bidirectional editing is supported.")))
85 :mime-charset 'cp862) 85 :mime-charset 'cp862)
86(define-coding-system-alias 'ibm862 'cp862) 86(define-coding-system-alias 'ibm862 'cp862)
87 87
88;; Composition function for hebrew. 88;; Return a nested alist of Hebrew character sequences vs the
89;; corresponding glyph of FONT-OBJECT.
90(defun hebrew-font-get-precomposed (font-object)
91 (let ((precomposed (font-get font-object 'hebrew-precomposed))
92 ;; Vector of Hebrew precomposed charaters.
93 (chars [#xFB2A #xFB2B #xFB2C #xFB2D #xFB2E #xFB2F #xFB30 #xFB31
94 #xFB32 #xFB33 #xFB34 #xFB35 #xFB36 #xFB38 #xFB39 #xFB3A
95 #xFB3B #xFB3C #xFB3E #xFB40 #xFB41 #xFB43 #xFB44 #xFB46
96 #xFB47 #xFB48 #xFB49 #xFB4A #xFB4B #xFB4C #xFB4D #xFB4E])
97 ;; Vector of decomposition character sequences corresponding
98 ;; to the above vector.
99 (decomposed
100 [[#x05E9 #x05C1]
101 [#x05E9 #x05C2]
102 [#x05E9 #x05BC #x05C1]
103 [#x05E9 #x05BC #x05C2]
104 [#x05D0 #x05B7]
105 [#x05D0 #x05B8]
106 [#x05D0 #x05BC]
107 [#x05D1 #x05BC]
108 [#x05D2 #x05BC]
109 [#x05D3 #x05BC]
110 [#x05D4 #x05BC]
111 [#x05D5 #x05BC]
112 [#x05D6 #x05BC]
113 [#x05D8 #x05BC]
114 [#x05D9 #x05BC]
115 [#x05DA #x05BC]
116 [#x05DB #x05BC]
117 [#x05DC #x05BC]
118 [#x05DE #x05BC]
119 [#x05E0 #x05BC]
120 [#x05E1 #x05BC]
121 [#x05E3 #x05BC]
122 [#x05E4 #x05BC]
123 [#x05E6 #x05BC]
124 [#x05E7 #x05BC]
125 [#x05E8 #x05BC]
126 [#x05E9 #x05BC]
127 [#x05EA #x05BC]
128 [#x05D5 #x05B9]
129 [#x05D1 #x05BF]
130 [#x05DB #x05BF]
131 [#x05E4 #x05BF]]))
132 (unless precomposed
133 (setq precomposed (list t))
134 (let ((gvec (font-get-glyphs font-object 0 (length chars) chars)))
135 (dotimes (i (length chars))
136 (if (aref gvec i)
137 (set-nested-alist (aref decomposed i) (aref gvec i)
138 precomposed))))
139 ;; Cache the result in FONT-OBJECT's property.
140 (font-put font-object 'hebrew-precomposed precomposed))
141 precomposed))
142
143;; Composition function for hebrew. GSTRING is made of a Hebrew base
144;; character followed by Hebrew diacritical marks, or is made of
145;; single Hebrew diacritical mark. Adjust GSTRING to display that
146;; sequence properly. The basic strategy is:
147;;
148;; (1) If there's single diacritical, add padding space to the left
149;; and right of the glyph.
150;;
151;; (2) If the font has OpenType features for Hebrew, ask the OTF
152;; driver the whole work.
153;;
154;; (3) If the font has precomposed glyphs, use them as far as
155;; possible. Adjust the remaining glyphs artificially.
156
89(defun hebrew-shape-gstring (gstring) 157(defun hebrew-shape-gstring (gstring)
90 (setq gstring (font-shape-gstring gstring)) 158 (let* ((font (lgstring-font gstring))
91 (let ((header (lgstring-header gstring)) 159 (otf (font-get font :otf))
92 (nchars (lgstring-char-len gstring)) 160 (nchars (lgstring-char-len gstring))
93 (nglyphs (lgstring-glyph-len gstring)) 161 header nglyphs base-width glyph precomposed val idx)
94 (base-width (lglyph-width (lgstring-glyph gstring 0)))) 162 (cond
95 (while (and (> nglyphs 1) 163 ((= nchars 1)
96 (not (lgstring-glyph gstring (1- nglyphs)))) 164 ;; Independent diacritical mark. Add padding space to left or
97 (setq nglyphs (1- nglyphs))) 165 ;; right so that the glyph doesn't overlap with the surrounding
98 (while (> nglyphs 1) 166 ;; chars.
99 (setq nglyphs (1- nglyphs)) 167 (setq glyph (lgstring-glyph gstring 0))
100 (let* ((glyph (lgstring-glyph gstring nglyphs)) 168 (let ((width (lglyph-width glyph))
101 (adjust (and glyph (lglyph-adjustment glyph)))) 169 bearing)
102 (if adjust 170 (if (< (setq bearing (lglyph-lbearing glyph)) 0)
103 (setq nglyphs 0) 171 (lglyph-set-adjustment glyph bearing 0 (- width bearing)))
104 (if (>= (lglyph-lbearing glyph) 0) 172 (if (> (setq bearing (lglyph-rbearing glyph)) width)
105 (lglyph-set-adjustment glyph (- base-width) 0 0)))))) 173 (lglyph-set-adjustment glyph 0 0 bearing))))
106 gstring) 174
175 ((or (assq 'hebr (car otf)) (assq 'hebr (cdr otf)))
176 ;; FONT has OpenType features for Hebrew.
177 (font-shape-gstring gstring))
178
179 (t
180 ;; FONT doesn't have OpenType features for Hebrew.
181 ;; Try a precomposed glyph.
182 ;; Now GSTRING is in this form:
183 ;; [[FONT CHAR1 CHAR2 ... CHARn] nil GLYPH1 GLYPH2 ... GLYPHn nil ...]
184 (setq precomposed (hebrew-font-get-precomposed font)
185 header (lgstring-header gstring)
186 val (lookup-nested-alist header precomposed nil 1))
187 (if (and (consp val) (vectorp (car val)))
188 ;; All characters can be displayed by a single precomposed glyph.
189 ;; Reform GSTRING to [HEADER nil PRECOMPOSED-GLYPH nil ...]
190 (let ((glyph (copy-sequence (car val))))
191 (lglyph-set-from-to glyph 0 (1- nchars))
192 (lgstring-set-glyph gstring 0 glyph)
193 (lgstring-set-glyph gstring 1 nil))
194 (if (and (integerp val) (> val 2)
195 (setq glyph (lookup-nested-alist header precomposed val 1))
196 (consp glyph) (vectorp (car glyph)))
197 ;; The first (1- VAL) characters can be displayed by a
198 ;; precomposed glyph. Provided that VAL is 3, the first
199 ;; two glyphs should be replaced by the precomposed glyph.
200 ;; In that case, reform GSTRING to:
201 ;; [HEADER nil PRECOMPOSED-GLYPH GLYPH3 ... GLYPHn nil ...]
202 (let* ((ncmp (1- val)) ; number of composed glyphs
203 (diff (1- ncmp))) ; number of reduced glyphs
204 (setq glyph (copy-sequence (car glyph)))
205 (lglyph-set-from-to glyph 0 (1- nchars))
206 (lgstring-set-glyph gstring 0 glyph)
207 (setq idx ncmp)
208 (while (< idx nchars)
209 (setq glyph (lgstring-glyph gstring idx))
210 (lglyph-set-from-to glyph 0 (1- nchars))
211 (lgstring-set-glyph gstring (- idx diff) glyph)
212 (setq idx (1+ idx)))
213 (lgstring-set-glyph gstring (- idx diff) nil)
214 (setq idx (- ncmp diff)
215 nglyphs (- nchars diff)))
216 (setq glyph (lgstring-glyph gstring 0))
217 (lglyph-set-from-to glyph 0 (1- nchars))
218 (setq idx 1 nglyphs nchars))
219 ;; Now IDX is an index to the first non-precomposed glyph.
220 ;; Adjust positions of the remaining glyphs artificially.
221 (setq base-width (lglyph-width (lgstring-glyph gstring 0)))
222 (while (< idx nglyphs)
223 (setq glyph (lgstring-glyph gstring idx))
224 (lglyph-set-from-to glyph 0 (1- nchars))
225 (if (>= (lglyph-lbearing glyph) (lglyph-width glyph))
226 ;; It seems that this glyph is designed to be rendered
227 ;; before the base glyph.
228 (lglyph-set-adjustment glyph (- base-width) 0 0)
229 (if (>= (lglyph-lbearing glyph) 0)
230 ;; Align the horizontal center of this glyph to the
231 ;; horizontal center of the base glyph.
232 (let ((width (- (lglyph-rbearing glyph)
233 (lglyph-lbearing glyph))))
234 (lglyph-set-adjustment glyph
235 (- (/ (- base-width width) 2)
236 (lglyph-lbearing glyph)
237 base-width) 0 0))))
238 (setq idx (1+ idx))))))
239 gstring))
107 240
108(let ((pattern1 "[\u05D0-\u05F2][\u0591-\u05BF\u05C1-\u05C5\u05C7]+") 241(let ((pattern1 "[\u05D0-\u05F2][\u0591-\u05BF\u05C1-\u05C5\u05C7]+")
109 (pattern2 "[\u05D0-\u05F2]\u200D[\u0591-\u05BF\u05C1-\u05C5\u05C7]+")) 242 (pattern2 "[\u05D0-\u05F2]\u200D[\u0591-\u05BF\u05C1-\u05C5\u05C7]+"))
110 (set-char-table-range 243 (set-char-table-range
111 composition-function-table '(#x591 . #x5C7) 244 composition-function-table '(#x591 . #x5C7)
112 (list (vector pattern2 2 'hebrew-shape-gstring) 245 (list (vector pattern2 3 'hebrew-shape-gstring)
246 (vector pattern2 2 'hebrew-shape-gstring)
113 (vector pattern1 1 'hebrew-shape-gstring) 247 (vector pattern1 1 'hebrew-shape-gstring)
114 ["[\u0591-\u05C7]" 0 font-shape-gstring])) 248 [nil 0 hebrew-shape-gstring]))
115 (set-char-table-range 249 (set-char-table-range
116 composition-function-table #x5C0 nil) 250 composition-function-table #x5C0 nil)
117 (set-char-table-range 251 (set-char-table-range
diff --git a/src/ChangeLog b/src/ChangeLog
index 5acf42608e4..c7e5c5c3ef2 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,8 @@
12010-07-12 Kenichi Handa <handa@m17n.org> 12010-07-12 Kenichi Handa <handa@m17n.org>
2 2
3 * Makefile.in (lisp): Change hebrew.el to hebrew.elc.
4 (shortlisp): Likewise.
5
3 * font.h (enum font_property_index): New member FONT_ENTITY_INDEX. 6 * font.h (enum font_property_index): New member FONT_ENTITY_INDEX.
4 7
5 * font.c (font_open_entity): Record ENTITY in FONT_OBJECT's slot 8 * font.c (font_open_entity): Record ENTITY in FONT_OBJECT's slot
diff --git a/src/Makefile.in b/src/Makefile.in
index 933ec98a8d5..6a60b1d1ffe 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -426,7 +426,7 @@ lisp= \
426 ${lispsource}language/slovak.el \ 426 ${lispsource}language/slovak.el \
427 ${lispsource}language/romanian.el \ 427 ${lispsource}language/romanian.el \
428 ${lispsource}language/greek.el \ 428 ${lispsource}language/greek.el \
429 ${lispsource}language/hebrew.el \ 429 ${lispsource}language/hebrew.elc \
430 ${lispsource}language/japanese.el \ 430 ${lispsource}language/japanese.el \
431 ${lispsource}language/korean.el \ 431 ${lispsource}language/korean.el \
432 ${lispsource}language/lao.el \ 432 ${lispsource}language/lao.el \
@@ -517,7 +517,7 @@ shortlisp= \
517 ../lisp/language/slovak.el \ 517 ../lisp/language/slovak.el \
518 ../lisp/language/romanian.el \ 518 ../lisp/language/romanian.el \
519 ../lisp/language/greek.el \ 519 ../lisp/language/greek.el \
520 ../lisp/language/hebrew.el \ 520 ../lisp/language/hebrew.elc \
521 ../lisp/language/japanese.el \ 521 ../lisp/language/japanese.el \
522 ../lisp/language/korean.el \ 522 ../lisp/language/korean.el \
523 ../lisp/language/lao.el \ 523 ../lisp/language/lao.el \