*** empty log message ***
[m17n/m17n-db.git] / BENG-OTF.flt
1 ;; BENG-OTF.flt -- Font Layout Table for Bengali OpenType font
2 ;; Copyright (C) 2004
3 ;;   National Institute of Advanced Industrial Science and Technology (AIST)
4 ;;   Registration Number H15PRO112
5
6 ;; This file is part of the m17n database; a sub-part of the m17n
7 ;; library.
8
9 ;; The m17n library is free software; you can redistribute it and/or
10 ;; modify it under the terms of the GNU Lesser General Public License
11 ;; as published by the Free Software Foundation; either version 2.1 of
12 ;; the License, or (at your option) any later version.
13
14 ;; The m17n library is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 ;; Lesser General Public License for more details.
18
19 ;; You should have received a copy of the GNU Lesser General Public
20 ;; License along with the m17n library; if not, write to the Free
21 ;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 ;; Boston, MA 02110-1301, USA.
23
24 ;;; <li> BENG-OTF.flt
25 ;;;
26 ;;; For Bengali OpenType fonts to draw the Bengali script.  Tested with
27 ;;; MuktiNarrow.ttf <http://www.nongnu.org/freebangfont/index.html>
28 ;;; and
29 ;;; LikhanNormal.otf <http:http://www.stat.wisc.edu/~deepayan/Bengali/WebPage/Font/fonts.html>
30
31 (category
32  ;; C: consonant (excluding B, Y and R)
33  ;; B: consonant BA (below)
34  ;; Y: consonant YA (post)
35  ;; R: consonant RA (reph, below)
36  ;; n: NUKTA
37  ;; H: HALANT
38  ;; m: MATRA (pre)
39  ;; b: MATRA (below)
40  ;; p: MATRA (post)
41  ;; t: MATRA (two-part)
42  ;; A: vowel modifier (above)
43  ;; a: vowel modifier (post)
44  ;; V: independent vowel
45  ;; N: ZWNJ (ZERO WIDTH NON-JOINER)
46  ;; J: ZWJ (ZERO WIDTH JOINER)
47  ;; E: ELSE
48  ;;
49  (0x200C        ?N)                     ; ZWNJ
50  (0x200D        ?J)                     ; ZWJ
51  (0x0964 0x0965 ?E)                     ; DANDA, DOUBLE DANDA
52  (0x0980 0x09FF ?E)                     ; ELSE
53  (0x0981        ?A)                     ; SIGN CANDRABINDU (above)
54  (0x0982 0x0983 ?a)                     ; SIGN ANUSWAR, VISARGA (post)
55  (0x0985 0x098C ?V)                     ; LETTER A .. VOCALIC L
56  (0x098F 0x0990 ?V)                     ; LETTER E .. AI
57  (0x0993 0x0994 ?V)                     ; LETTER O .. AU
58  (0x0995 0x09B9 ?C)                     ; LETTER KA .. HA
59  (0x09AC        ?B)                     ; LETTER BA
60  (0x09AF        ?Y)                     ; LETTER YA
61  (0x09B0        ?R)                     ; LETTER RA
62  (0x09BC        ?n)                     ; SIGN NUKTA
63  (0x09BE        ?p)                     ; VOWEL SIGN AA (post)
64  (0x09BF        ?m)                     ; VOWEL SIGN I (pre)
65  (0x09C0        ?p)                     ; VOWEL SIGN II (post)
66  (0x09C1 0x09C4 ?b)                     ; VOWEL SIGN U, UU, R, RR (below)
67  (0x09C7 0x09C8 ?m)                     ; VOWEL SIGN E, AI (pre)
68  (0x09CB 0x09CC ?t)                     ; VOWEL SIGN O, AU (two-part)
69  (0x09CD        ?H)                     ; SIGN VIRAMA (HASANT)
70  (0x09CE        ?C)                     ; LETTER KHANDA TA
71  (0x09D7        ?p)                     ; AU LENGTH MARK
72  (0x09DC 0x09DD ?C)                     ; LETTER RRA, RHA
73  (0x09DF        ?C)                     ; LETTER YYA
74  (0x09E0 0x09E1 ?V)                     ; LETTER VOCALIC RR, LL
75  (0x09E2 0x09E3 ?b)                     ; VOWEL SIGN L .. LL (below)
76  (0x09F0 0x09F1 ?C)                     ; LETTER RR', RR'' (assamese)
77  (0x09FE        ?x)                     ; mark #1 (internal use)
78  (0x09FF        ?y)                     ; mark #2 (internal use)
79  )
80
81 ;; Step 1 : Syllable identification.  Recognised syllables are quoted
82 ;; by the pseudo character, which is generated by the command "|" and
83 ;; has the category " " (space).
84 (generator
85  (0
86   (cond
87    ;; Case A-C are for those syllables that end with an explicit vowel
88    ;; mark and/or a vowel modifier.  They are divided into three cases
89    ;; for the readability of regular expression.  The leading
90    ;; consonant-Hasant repetition is analysed for reordering in the
91    ;; next step.  Two-part vowel, if any, is split for
92    ;; canonicalisation.
93
94    ;; Case A : A syllable ending with a vowel modifier.
95    ;;1    23                4          5       6   7
96    ("(RH)?(([CRBY]n?H[NJ]?)*([CRBY]n?))([mbp]*)(t)?([Aa])"
97     < |
98     (1 = =)
99     (2 set-marks)
100     (5 = *)
101     (6 split)
102     (7 =)
103     | >)
104
105    ;; Case B : A syllable ending with a two-part vowel.
106    ;;1    23                4          5
107    ("(RH)?(([CRBY]n?H[NJ]?)*([CRBY]n?))(t)"
108     < |
109     (1 = =)
110     (2 set-marks)
111     (5 split)
112     | >)
113
114    ;; Case C : A syllable ending with other vowel.  Note that a
115    ;; two-part vowel may be expressed with two vowel marks for
116    ;; backward compatibility.
117    ;;1    23                4          5
118    ("(RH)?(([CRBY]n?H[NJ]?)*([CRBY]n?))([mbp]+)"
119     < |
120     (1 = =)
121     (2 set-marks)
122     (5 = *)
123     | >)
124
125    ;; Case D : Ya-phalaa.  Reorder H and Y for the next step.
126    ;; The web page "Unicode FAQ for Indic Scripts and Languages"
127    ;; <http://www.unicode.org/faq/indic.html> says "it should be
128    ;; permissible for the Ya-phalla to be consistently formed by "ZWNJ
129    ;; + VIRAMA + YA".
130    ("([CRBY]n?N)(H)(Y)"
131     < |
132     (1 = *)
133     (3 =)
134     (2 =)
135     | >)
136
137    ;; Case E : No explicit vowel nor modifier.  If the syllable ends
138    ;; with a consonant, analyse it for reordering in the next step.
139    ;; Otherwise, just identify the syllable without changing anything.
140    ;;1    23                         4
141    ("(RH)?(([CRBY]n?H[NJ]?)*[CRBY]n?)(HN|HJ|H)?"
142     < |
143     (1 = =)
144     (2 set-marks)
145     (4 = *)
146     | >)
147
148    ;; Case F : Syllables that begin with an independent vowel.  An
149    ;; optional HYp sequence appears when this syllable represents the
150    ;; sound "a" in English "bat" (see the FAQ above).  If it appears,
151    ;; we reorder the H and Y for the next step.
152    ("(V)(HYp)?([aA])?"
153     < | (1 =) (2 ("HY(p)" 0x09AF 0x09CD (1 =))) (3 =) | >)
154
155    ("." =))
156   *)
157
158  ;; Set mark #1 (x) at the position where below consonants begin, and
159  ;; mark #2 (y) at the position to which below and above signs will be
160  ;; moved.
161  (set-marks
162   (cond
163    ;; Ending with Y.
164    ;;1        2            3  45        6
165    ("([CRBY]n?(H[NJ]?Cn?)*)(H)(([RB]H)*)(Y)"
166     (1 = *)                             ; prebase & base
167     0x09FE                              ; mark #1
168     (4 = *)                             ; below consonants
169     0x09FF                              ; mark #2
170     (6 =)                               ; YA
171     (3 =))                              ; moved HASANT
172    ;; Ending with R or B.
173    ;;1        2            3  45
174    ("([CRBY]n?(H[NJ]?Cn?)*)(H)(([RB]H)*[RB])"
175     (1 = *)                             ; prebase & base
176     0x09FE                              ; mark #1
177     (4 = *)                             ; below consonants 
178     (3 =)                               ; moved HASANT
179     0x09FF)                             ; mark #2
180    (".+"
181     = *
182     0x09FE                              ; mark #1
183     0x09FF)))                           ; mark #2
184
185  ;; Split two-part dependent vowel signs for canonicalisation.
186  (split
187   (cond
188    ((0x09CB)    0x09C7 0x09BE)
189    ((0x09CC)    0x09C7 0x09D7)))
190  )
191
192 ;; Step 2 : Move Reph and Matra if necessary.  From now on, we care
193 ;; only for those syllables that have been identified in Step 1.
194 (generator
195  (0
196   (cond
197    ;; Special case: a single consonant and a Halant.
198    (" (.)xy(H[NJ]?) "
199     |
200     0x09FE
201     (1 =)
202     (2 = *)
203     0x09FE
204     |)
205
206    ;; This is the most generic pattern.  It follows Cases A, B, C and
207    ;; E in Step 1.  Now Mark #1 is used to indicate the critical part
208    ;; that requires pre-base substitution in the following steps.
209
210    ;; 1    2         3        4    5   6   7   8   9   10
211    (" (RH)?([^ xy]+)x([^ y]*)y(YH)?(m)?(b)?(p)?(A)?(a)?(HN|HJ|H)? "
212     |
213     (5 =)                               ; [Mpre]
214     ;; Actually, the nukt feature is not necessary for Bengali because
215     ;; all the necessary Nukta forms are precomposed in the Unicode
216     ;; standard.  Even if a Nukta consonant is given in the form of
217     ;; the combination of the base consonant and a Nukta sign, we can
218     ;; safely perform the composition here because it does not affect
219     ;; surrounding letters in the syllable.  The Akhand ligature
220     ;; operation is also applied here, before applying the half form
221     ;; operation because the Mukti font generates Akhand ligatures
222     ;; directly from the "C H C" sequence, not via the half form.
223     0x09FE                              ; begin Cpre & Cbase
224     (2 otf:beng=nukt,akhn)              ; {Cpre + H} + Cbase
225     0x09FE                              ; end Cpre & Cbase
226     (3 otf:beng=blwf)                   ; {Cbelow + H}
227     (6 =)                               ; [Mbelow]
228     (1 otf:beng=rphf)                   ; [Reph]
229     (8 =)                               ; [VMabove]
230     (4 otf:beng=pstf)                   ; [Cpost + H]
231     (7 =)                               ; [Mpost]
232     (9 =)                               ; [VMpost]
233     (10 = *)                            ; optional HASANT
234     |)
235
236    ;; Syllables that begin with an independent vowel (following up
237    ;; Step 1, Case F).  If a YH sequence exist, it is changed to the
238    ;; post-base form.  Syllables of this type do not require further
239    ;; modification.
240    (" (V)(YH)(.*) "
241     |
242     (1 =)
243     (2 otf:beng=pstf)
244     (3 = *)
245     |)
246
247    ;; Ya-phalaa (following up Step 1, Case D).  Remove N and change YH
248    ;; to the post base form.  Syllables of this type do not require
249    ;; further modification.
250    (" ([CBRY]n?)N(YH) "
251     |
252     (1 =)
253     (2 otf:beng=pstf)
254     |)
255
256    ("." =))
257   *))
258
259 ;; Step 3 : Now only those syllables that contain the pseudo character
260 ;; x require pre-base substition.  This is the most complicated part
261 ;; in this FLT.
262
263 ;; If the sequence "C1 H C2" makes ligature L12, L12 replaces the
264 ;; original sequence.
265
266 ;; To test the availability of such a ligature, we try to generate it
267 ;; using the pre-base substitute feature, then see whether succeeded
268 ;; or not.  In the case of failure, the pre-base feature does not
269 ;; change the original sequence.
270
271 ;; To create a ligature, the "C1 H" part must be first converted into
272 ;; the half form of C1.  Creating the half form of a consonant always
273 ;; succeeds.
274
275 ;; ligature(half(C1,H),C2)
276 ;; ==> ligature(C1half,C2)
277 ;; ==> L12         ; success
278 ;;     C1half C2   ; fail
279
280 ;; If the ligature is not available, the "C1 H" part must be converted
281 ;; into the _Halant_ (not half) form of C1.  However, there is no way
282 ;; to reconvert C1half into C1halant nor to revert back to "C1 H".
283 ;; Thus we duplicate the critical part in two different forms so that
284 ;; we can select the appropriate one in the next step.  The pseudo
285 ;; character x is used to indicate the boundaries.
286
287 ;; ... C1 H C2 ...  ==>  ... x C1halant C2 x L12 x ...
288
289 ;; If the length of the L12 part is one, ligature generation was
290 ;; successful.  In this case we wipe out the duplicated C1halant and
291 ;; C2.  Otherwise we remove L12.
292
293 ;; In very few cases (I found only one in the Mukti font), the "C1 H"
294 ;; part need to be converted into C1halant (instead of C1half) to make
295 ;; a ligature with C2.  So when we try to generate a ligature form, we
296 ;; apply the GSUB features "half", "haln" and "pres" in this order.
297
298 (category
299  ;; C: consonant (excluding B, Y and R)
300  ;; H: HALANT
301  ;; N: ZWNJ (ZERO WIDTH NON-JOINER)
302  ;; J: ZWJ (ZERO WIDTH JOINER)
303  ;; E: ELSE
304  ;;
305  (0x200C        ?N)                     ; ZWNJ
306  (0x200D        ?J)                     ; ZWJ
307  (0x0964 0x0965 ?E)                     ; DANDA, DOUBLE DANDA
308  (0x0980 0x09FF ?E)                     ; ELSE
309  (0x09CD        ?H)                     ; SIGN VIRAMA (HASANT)
310  (0x0995        ?K)                     ; LETTER KA
311  (0x09B7        ?S)                     ; LETTER SSA
312  (0x09A3        ?M)                     ; LETTER NNA
313  (0x09AE        ?M)                     ; LETTER MA
314  (0x09FE        ?x)                     ; mark #1 (internal use)
315  )
316
317 (generator
318  (0
319   (cond
320
321    ;; One pre-base and base.
322    ;; 1        23   4       5    6
323    (" ([^x ]*)x((.H)([^NJ]))(H)?x([^ ]*) "
324     |
325     (1 = *)
326     0x09FE                              ; x
327     (3 otf:beng=haln)                   ; C1halant
328     (4 =)                               ; C2
329     0x09FE                              ; x
330     (2 otf:beng=half,haln,pres)         ; ligature result
331     0x09FE                              ; x
332     (5 =)
333     (6 = *)
334     |)
335
336    ;; One pre-base with ZWJ.  According to the Unicode FAQ, the half
337    ;; form is forced in this case.  So we fake as if ligature
338    ;; generation was failed.
339    (" ([^x ]*)x(.H)J(.)?x([^ ]*) "
340     |
341     (1 = *)
342     0x09FE                              ; x
343     (2 otf:beng=half)                   ; C1half
344     (3 =)                               ; C2
345     0x09FE                              ; x
346     0x09FD                              ; pseudo result
347     0x09FD                              ; pseudo result
348     0x09FE                              ; x
349     (4 = *)
350     |)
351
352    ;; One pre-base possibly with ZWNJ.  Similar to above.
353    (" ([^x ]*)x(.H)N?(.)?x([^ ]*) "
354     |
355     (1 = *)
356     0x09FE                              ; x
357     (2 otf:beng=haln)                   ; C1halant
358     (3 =)                               ; C2
359     0x09FE                              ; x
360     0x09FD                              ; pseudo result
361     0x09FD                              ; pseudo result
362     0x09FE                              ; x
363     (4 = *)
364     |)
365
366    ;; Standalone base.  There is nothing more to do.
367    (" ([^x ]*)x(.)x([^ ]*) "
368     |
369     (1 = *)
370     (2 =)
371     (3 = *)
372     |)
373
374    ;; KA-SSA-NNA and KA-SSA-MA are the only pre-base ligatures that
375    ;; consist of three consonants.
376    ;; 1        23   4   5   6    7
377    (" ([^x ]*)x((KH)(SH)(M))(H)?x([^ ]*) "
378     |
379     (1 = *)
380     0x09FE                              ; x
381     (3 otf:beng=haln)                   ; KAhalant
382     (4 otf:beng=haln)                   ; SSAhalant
383     (5 =)                               ; NNA or MA
384     0x09FE                              ; x
385     (2 otf:beng=half,haln,pres)         ; ligature result
386     0x09FE                              ; x
387     (6 =)
388     (7 = *)
389     |)
390
391    ;; Two or more pre-bases plus base.  Give up.  Convert all
392    ;; pre-bases into halant form.
393    ;; 1        23             4       5
394    (" ([^x ]*)x(([^x]H[JN]?)+)([^x])?x([^ ]*) "
395     |
396     (1 = *)
397     0x09FE                              ; x
398     (2 force-haln)                      ; halant forms
399     (4 =)                               ; full form
400     0x09FE                              ; x
401     0x09FD                              ; pseudo result
402     0x09FD                              ; pseudo result
403     0x09FE                              ; x
404     (5 = *)
405     |)
406
407    ("." =))
408   *)
409
410  ;; This is to remove ZWNJ and ZWJ.  The half-form-force-effect of ZWJ
411  ;; is ignored.  Sorry.
412  (force-haln
413   (cond
414    ("([^JN]*)[JN](.*)"
415     (1 otf:beng=haln)
416     (2 force-haln))
417    (".+"
418     otf:beng=haln)))
419  )
420
421 ;; Step 4 : Select the appropriate representation.  Only those
422 ;; syllables that contain the virtual character x require
423 ;; modification.
424 (generator
425  (0
426   (cond
427    ;; Only one glyph in the ligature section (between the second and
428    ;; the third x).  It means a ligature was successfully generated.
429    ;; C1halant and C2 (between the first and second x) are removed.
430    (" ([^x ]*)x[^x]+x(.)x([^ ]*) "
431     |
432     (1 = *)
433     (2 =)
434     (3 = *)
435     |)
436
437    ;; Otherwise halant and base forms are used.  The failed ligature
438    ;; is removed.
439    (" ([^x ]*)x([^x]+)x[^x]+x([^ ]*) "
440     |
441     (1 = *)
442     (2 = *)
443     (3 = *)
444     |)
445
446    ;; No need to care the other cases.
447    ("." =))
448   *))
449
450 ;; Step 5 : Select appropriate glyph variants for fine adjustments.
451 ;; Now the syllable boundary marks are removed so that the final step
452 ;; can find word boundaries.
453 (generator
454  (0
455   (cond
456    (" ([^ ]+) "
457     (1 otf:beng=blws,abvs,psts,vatu))
458    ("."
459     [ otf:beng=+ ] ))
460   *)
461  )
462
463 ;; Step 6 : Word initial substitute.  As the syllable boundaries have
464 ;; been eliminated in the previous step, this rule is applied to a run
465 ;; of Bengali glyphs, i.e. word by word.  We finally apply the init
466 ;; feature to the word initial gylphs to get the final result.
467 (generator
468  (0
469   ("(.)(.*)"
470    (1 otf:beng=init)
471    (2 = *))))
472
473 ;; Local Variables:
474 ;; mode: emacs-lisp
475 ;; End: