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