File: CharisRules.gdh

package info (click to toggle)
grcompiler 4.2-4
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 11,076 kB
  • ctags: 5,163
  • sloc: cpp: 45,565; sh: 4,451; ansic: 4,377; makefile: 185; xml: 175; perl: 127
file content (696 lines) | stat: -rw-r--r-- 23,820 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
/*
    Title:  Roman Font GDL description
    Author: Martin Hosken & Bob Hallissy
    
    Changes:
SJC 2007-Jan-26  Cleaned up distinction between Open-O alternates and J-stroke-hook-alternate
SJC 2006-Dec-4   Various changes for new version to support Unicode 5.0:
	Changed VNStyle to vN; added Chinantec tones, Cyrillic cursive italics, open-o serif feature
SJC 2006 ??????  Added barred-j modifier to take smaller diacritics; added smallcaps code (turned off)
SJC 2006-Apr-6   Allow ogonek and literacy rules to both fire
SJC 2006-Mar-21  Handle literacy alternates + Vietnamese diacritics for NFC data
SJC 2006-Jan-23  Added Cyrillic shha alternate
SJC 2005-Oct-14  Added slant-italic ff, fi, fl ligatures
SJC 2005-Oct-13  Made ff, fi, fl true ligatures with components.
SJC 2005-Oct-12  Fixed problems with dotted modifier super/subscripts and partial fix for F17A (double diaeresis).
SJC 2005-Sep-1   Added slant-italic special forms, diaersis on superscripts, and bridging diacritics.
SJC 2005-May-16  Handle features modlowcolon, ltnglottalstop, and ltnjstroke.
SJC 2005-May-16  Turn off AutoPseudo.
SJC 2005-May-10  Added a few comments.
AKW 2005-May-09  Changed gF176 to g035C (PUA character accepted into Unicode).
JMW 2004-Sep-02  For now, I will take easy option on fixing Literacy Alts and Romanian,
    by backing up. Later I may re-write. Input to WP2 is now NFD, necessitating a change.
JMW 2004-Jul-21  Comments on Viet, add 4th Eng.
RMH 2004-Mar-17  Changed logic for ou alternates due to default is now closed top,
	and alternate is .OpenType  (issue RFS-5WXH4D);
	added omacron and Omacron to things that can composite with ogonek (related to issue RFS-5X5FKC);
	renamed cnDia to cDia -- it is a class of all diacritics, not the class of non-diacritics;
	added cHDia to cBDia, but I think the cBDia and cnBDia classes aren't used...?
RMH 2004-Feb-25  removed all smartcode that builds alternates (of composites) by decomposition
	(we now have real alternates available in the font);
	in the process, eliminated viet.gdh -- integrating it directly here.
RMH 2004-Feb-13  Made explicit associations to quiet new GrCompiler warnings.
RMH 2004-Feb-05  Rewrote rules that had been generated by normal_rules() function in makegdl.pl so
	that (1) only those glyphs that need composition (things with ogonek, cedilla, horn)
	are actually composed, and (2) now permits other diacritcs to intervene.
	Similarly added code to permit intevening diacs in rules for .vNStyle diac ligatures.
RMH 2004-Feb-04 Changes after B14: implemented logic for retrohookstyle ogonek alternates feature.
RMH 2004-Jan-19 Changes after B10: omehow p_hook feature wasn't ever implemented.
RMH 10-Oct-2003 Significant rework:
	added "else" clauses for most features (so this same code works if
	Feature table and cmap are changed so an "alternate" glyph is the default);
	added code to handle cedillas that need to be rendered as commaaccent;
	added DeBuG feature (only compiled in if symbol DEBUG is defined as non-zero).
RMH 01-Sep-2003 Reworked all features per PC's design.
RMH 15-Aug-2003  Added other Unicode 4.0 double-diacritics;
    fixed double diacritic positioning so not dependent on glyph's default location
	(requires double diacritics should NOT have attachment points).
RMH 17-Jul-2003  Removed all references to "P" and "_P" attachment points -- it no longer exists;
    replace refs to U+F177 with U+035E (Unicode 4.0).
RMH 10-Jul-2003  Added logic to decompose 1E2D and 1ECB in the context of upper diacritics.
MJPH 16-Nov-2002 Move overarch to down by -1200m from -700m.
*/

#include "stddef.gdh"

#define CHARISfont 1
#define DOULOSfont 2
#define GENTIUMfont 3
#define ANDIKAfont 4
// Now turn on the font we want, so we get specific features. (This file is copied from
// something like doulos.gdh or charis.gdh by the build process.
#include "CharisSpecific.gdh"

#define DEBUG 0
// #define DEBUG 1  //jw 7/21/04 Use this to turn on DEBUG

#define SMALLCAPS 0

Bidi = 0;

// To make double-encoded characters act identically:
AutoPseudo = 0;

#define DIASTR4(x) [ x [ x [ x x?]?]?]?
#define DIASTR5(x) [ x [ x [ x [ x x?]?]?]?]?
#define attached user1


#if DEBUG
#define DeBuG g__d g_e g__b g_u g__g g_colon 
#endif

//////////////////////////////////////////////////////////////////////////////////////
//
//	Glyphs
//

table(glyph);

// Classes of double-diacritics above and below:
cUDblDia = (g035D g035E g0360 g0361 gF17A);
cLDblDia = (g035F g0362 g035C);

// Various classes of diacritics:
cBDia = (cLDia cODia cHDia);			// Below = Lower + Ogonek + Cedilla
cnBDia = (cUDia cRDia);				// Not Below
cnHDia = (cLDia cODia cRDia cUDia);		// Not Cedilla
cnLDia = (cHDia cODia cRDia cUDia);		// Not Lower
cnODia = (cHDia cLDia cRDia cUDia);		// Not Ogonek
cnRDia = (cHDia cLDia cODia cUDia);		// Not Horn (right)
cnUDia = (cHDia cLDia cODia cRDia );		// Not Upper
cDia =  (cHDia cLDia cODia cRDia cUDia);	// Any (but not double dias)

// ff, fi, fl ligatures
cfLigC2 = (g_f  g_i  g_l);
cfLig  = (g_f_f  g_f_i  g_f_l);
cffLigC3 = (g_i  g_l);
cffLig = (g_f_f_i  g_f_f_l);

cfLigC2_slantItalic = (g_f_slant_italic, g_i_slant_italic, g_l_slant_italic);
cfLig_slantItalic = (g_f_f_slant_italic, g_f_i_slant_italic, g_f_l_slant_italic);
cffLigC3_slantItalic = (g_i_slant_italic, g_l_slant_italic);
cffLig_slantItalic = (g_f_f_i_slant_italic, g_f_f_l_slant_italic);

cfLig_all = (cfLig  cfLig_slantItalic)
	{ component {f1 = box(0, -descent, aw/2, ascent); f2 = box(aw/2, -descent, aw, ascent) }};
cffLig_all = (cffLig  cffLig_slantItalic)
	{ component { f1 = box(0, -descent, aw/3, ascent);
					f2 = box(aw/3, -descent, (2*aw)/3, ascent);
					f3 = box((2*aw)/3, -descent, aw, ascent) }}

cSpecialDotted = (g1E2D g1ECB);
cSpecialDottedDia = (g0330 g_dotbelowcomb);

// Special class defs for cedilla compositions that are rendered as commaaccent:
// Note: tested removal JW 8/28 to see if they are pre-composed by Graphite. No, they are decomposed on the way in, apparently.
cCedillaBase = (g__g  g_g  g__k  g_k  g__l  g_l  g__n  g_n  g__r  g_r);
cCedillaComposite = (g__gcommaaccent g_gcommaaccent g__kcommaaccent g_kcommaaccent
		g__lcommaaccent	g_lcommaaccent g__ncommaaccent g_ncommaaccent g__rcommaaccent
		g_rcommaaccent);

// Add in other cedilla composites:
cCedillaBase += (g__c  g_c  g__s  g_s  g__t  g_t  g__e  g_e)
cCedillaComposite += (g__ccedilla g_ccedilla g__scedilla g_scedilla
		g0162 g0163 g0228 g0229)

// Ogonek composites:
cOgonekBase = (g__a  g_a  g__e  g_e  g__u  g_u  g__o  g_o  g__omacron  g_omacron);
cOgonekComposite = (g__aogonek g_aogonek g__eogonek g_eogonek g__uogonek
		g_uogonek g01EA g01EB g01EC g01ED);

// Horn composites:
cHornBase = (g__o  g_o  g__u  g_u);
cHornComposite = (g__ohorn  g_ohorn  g__uhorn  g_uhorn);

// Modifier superscripts that require smaller diacritics:
cModSuper = (g02B0 g02B1 g02B2 g02B3 g02B4 g02B5 g02B6 g02B7 g02B8
		g02C0 g02C1 g02E0 g02E1 g02E2 g02E3 g02E4
		g1D2C g1D2D g1D2E g1D2F
		g1D30 g1D31 g1D32 g1D33 g1D34 g1D35 g1D36 g1D37
		g1D38 g1D39 g1D3A g1D3B g1D3C g1D3D g1D3E g1D3F
		g1D40 g1D41 g1D42 g1D43 g1D44 g1D45 g1D46 g1D47
		g1D48 g1D49 g1D4A g1D4B g1D4C g1D4D g1D4E g1D4F
		g1D50 g1D51 g1D52 g1D53 g1D54 g1D55 g1D56 g1D57
		g1D58 g1D59 g1D5A g1D5B g1D5C g1D5D g1D5E g1D5F g1D60 g1D61 g1D78
		g1D9B g1D9C g1D9D g1D9E g1D9F
		g1DA0 g1DA1 g1DA2 g1DA3 g1DA4 g1DA5 g1DA6 g1DA7
		g1DA8 g1DA9 g1DAA g1DAB g1DAC g1DAD g1DAE g1DAF
		g1DB0 g1DB1 g1DB2 g1DB3 g1DB4 g1DB5 g1DB6 g1DB7
		g1DB8 g1DB9 g1DBA g1DBB g1DBC g1DBD g1DBE g1DBF g2071 g207F
		g2071_dotless g02B2_dotless g1DA4_dotless g1DA8_dotless);
		
// Modifier subscripts that require smaller diacritics:
cModSub = (g1D62 g1D63 g1D64 g1D65 g1D66 g1D67 g1D68 g1D69 g1D6A
		g2090 g2091 g2092 g2093 g2094
		g1D62_dotless);
    
cBridgeDiac = (g0308_uU g0308_uL g0308_lL g0311_uU g0311_uL g0311_lL);

// Vietnamese diacritic combinations
cDiacComb = (g_acutecomb g_gravecomb g_hookabovecomb g_tildecomb);
c_g0302DiacComb = (g0302_acutecomb_vN  g0302_gravecomb_vN 
						g0302_hookabovecomb_vN  g0302_tildecomb_vN);
c_g0306DiacComb = (g0306_acutecomb_vN  g0306_gravecomb_vN
						g0306_hookabovecomb_vN  g0306_tildecomb_vN);
						

// Vietnamese/literacy combinations

// a with stacked diacritics
c_aStack_noLit = (g1EA5 g1EA7 g1EA9 g1EAB g1EAF g1EB1 g1EB5 g1EB3); // eg, a+circum+acute
c_diacComb_vN = (g0302_acutecomb_vN, g0302_gravecomb_vN,
			g0302_hookabovecomb_vN, g0302_tildecomb_vN, 
			g0306_acutecomb_vN, g0306_gravecomb_vN,
			g0306_hookabovecomb_vN, g0306_tildecomb_vN);


// The top-serif alternate affects two different features:
cTopSerifOpenO = (g0254_topSerif, g1D53_topSerif, g1D97_topSerif, g0186_topSerif, g1D10_topSerif);
cno_TopSerifOpenO = (g0254, g1D53, g1D97, g0186, g1D10);

cTopSerifJStroke = (g0284_topSerif);
cno_TopSerifJStroke = (g0284);


#if SMALLCAPS

// Lower-to-uppercase mappings for all-caps feature
c_lowercaseAC = (g_a, g_agrave, g_abreve, g_acircumflex, g_atilde,
	g_amacron, g_adieresis, g_aring,
	g_b, g_c, g_cacute, g_ccircumflex, g_ccaron,
	g_d, g_e, g_f, g_g, g_h, g_i, g_j, g_k,
	g_l, g_m, g_n, g_o, g_p, g_q, g_r, g_s, g_t, g_u, g_v,
	g_w, g_x, g_y, g_z);
		
c_uppercaseAC = (g__a, g__agrave, g__abreve, g__acircumflex, g__atilde,
	g__amacron, g__adieresis, g__aring,
	g__b, g__c, g__cacute, g__ccircumflex, g__ccaron,
	g__d, g__e, g__f, g__g, g__h, g__i, g__j, g__k,
	g__l, g__m, g__n, g__o, g__p, g__q, g__r, g__s, g__t, g__u, g__v,
	g__w, g__x, g__y, g__z);


// Lower-to-uppercase mappings for small-caps feature
c_lowercaseSC = (g_a, g_b, g_c, g_d, g_e,
	// g_f, - NO F!!!
	g_g, g_h, g_i, g_j, g_k,
	g_l, g_m, g_n, g_o, g_p,
	// g_q, - NO Q!
	g_r, g_s, g_t, g_u, g_v,
	g_w, g_x, g_y, g_z);
		
c_uppercaseSC = (glyphid(110), glyphid(183), glyphid(233), glyphid(292), glyphid(391),
	// NO F!
	glyphid(512), glyphid(553), glyphid(655), glyphid(714), glyphid(749),
	glyphid(801), glyphid(841), glyphid(880), glyphid(987), glyphid(1071),
	// NO Q!
	glyphid(1122), glyphid(1144), glyphid(1216), glyphid(1288), glyphid(1326),
	glyphid(1378), glyphid(1387), glyphid(1446), glyphid(1472));
	
#endif // SMALLCAPS

endtable; // glyph


//////////////////////////////////////////////////////////////////////////////////////
//
//	Features
//

#include "CharisFeatures.gdh"


//////////////////////////////////////////////////////////////////////////////////////
//
//	Rules
//

table(substitution);

pass(1) {MaxBackup = 15; MaxRuleLoop = 30}

#if SMALLCAPS
if (smallcaps)
	c_lowercaseSC  >  c_uppercaseSC /  ^ _ ;
endif;

if (allcaps)
	c_lowercaseAC  >  c_uppercaseAC /  ^ _ ;
endif;
#endif // SMALLCAPS

// Turn combining half-marks into one double-width combining mark
gFE20=d1  gFE21=d2  >  g0361:(d1 d2) _  /  ^ _  cTakesUDia  DIASTR5(cDia)  _ ;
gFE22=d1  gFE23=d2  >  g0360:(d1 d2) _  /  ^ _  cTakesUDia  DIASTR5(cDia)  _ ;

// For Chinantec, make the standard Unicode characters look like the special PUA characters
if (chinantec_tone == 1)
	cno_ChinantecTn  >  cChinantecTn;
else
	cChinantecTn  >  cno_ChinantecTn;
endif;

// Handle cedillas (including those that need to look like comma-accent by precomposing them);
// back-up needed to also handle rom feature:
cCedillaBase g0327 > cCedillaComposite:(b d) _ / ^ _=b DIASTR4(cnHDia) _=d; // force a composite even if 
                                                                            // 0-4 diacs intervene

// Handle ogoneks; backup needed to also handle literacy feature:
cOgonekBase g0328 > cOgonekComposite:(b d) _ / ^ _=b DIASTR4(cnODia) _=d;

// Handle horns:
cHornBase g031B > cHornComposite:(b d) _ / _=b DIASTR4(cnRDia) _=d;

// Handle Vietnamese
/* jw comments
     2 stacked diacs go to side-by-side unless there is an intervening upper diac.
     pre-composed base + stacked diacs go to pre-composed base+side-by-side (cVN) */
if (viet == 1)
	// decompose the stacked form and replace the base 'a' with the literacy form,
	// the diacritics with the Vietnamese form
	_  c_aStack_noLit  >  g_a_sng_story:2  c_diacComb_vN / _ _ {literacy == 1};
	
	g0302 cDiacComb  >  c_g0302DiacComb$d:(b d)  _  / _=b DIASTR4(cnUDia) _=d;
	g0306 cDiacComb  >  c_g0306DiacComb$d:(b d)  _  / _=b DIASTR4(cnUDia) _=d;
	cno_VN > cVN; // ie, when literacy == false
else
	cVN > cno_VN;
endif;


if (bridging_diac)
  // LL with bridging diaeresis (U+035F is possible intervening bridging underbar)
  g0308  >  g0308_uU  /  g__l  g035F?  _  g035F?  g__l;
  g0308  >  g0308_uL  /  g__l  g035F?  _  g035F?  g_l;
  g0308  >  g0308_lL  /  g_l   g035F?  _  g035F?  g_l;
  
  // OU with bridging inverted breve
  g0311  >  g0311_uU  /  g__o  g035F?  _  g035F?  g__u;
  g0311  >  g0311_uL  /  g__o  g035F?  _  g035F?  g_u;
  g0311  >  g0311_lL  /  g_o   g035F?  _  g035F?  g_u;
endif;


#if DEBUG

if (debug == 1)
	g_question > g_one		/ DeBuG g_space g_e g_n g_g g_equal _ {eng == 0};
	g_question > g_two		/ DeBuG g_space g_e g_n g_g g_equal _ {eng == 1};
	g_question > g_three	/ DeBuG g_space g_e g_n g_g g_equal _ {eng == 2};
endif;

#endif  // DEBUG

/*
# NOTES:
#
# The rules are designed so that they work correctly no matter how the 
# default value for a feature is set. While this means the rules don't
# demand that the cmap and feature table agree on the default glyph, 
# the font will be more usable in non-GDL apps if they do agree.
# (One exception remaining is vietnamese processing -- so don't
# try to build a font with vietnamese on by default)
#
# If a glyph name extension (which is what drives the class names) is used 
# within more than one feature (e.g., .LrgBowl is used in the Rams horn alternate 
# and the Small ezh-curl alternate), then we cannot use the automatically generated
# class names (e.g., cLrgBowl and cno_LrgBowl), but rather must explicitly
# handle each glyph -- sigh.
#
# For programmer benefit, these are arranged in order of the feature ID value:
*/



// Note: we can't use the cUCStyle class because that label has been generalized to apply to
// more than just uppercase engs.
if (eng == descender)
	// for fonts with default = base, capital, or short:
	(cBaselineHook g__eng_u_c_style cKom) > g__eng;
endif;
if (eng == base)
	// for fonts with default = descender, capital, or short:
	(cno_BaselineHook g__eng_u_c_style cKom) > cBaselineHook;
endif;
if (eng == capital)
	// for fonts with default = descender, base, or short:
	(cBaselineHook g__eng cKom) > g__eng_u_c_style;
endif;
if (eng == short)
	// for fonts with default = descender, capital, or base:
	(cBaselineHook g__eng cno_Kom) > cKom;
endif;


if (ramshorn == small)
	// for fonts with default = large or gamma
	(g0264_lrgBowl g0264_gammaStyle) > g0264;
endif;
if (ramshorn == large)
	// for fonts with default = small or gamma
	(g0264 	g0264_gammaStyle)	> g0264_lrgBowl;
endif;
if (ramshorn == gamma)
	// for fonts with default = small or large
	(g0264 g0264_lrgBowl)		> g0264_gammaStyle;
endif

// supernum feature dealt with in pitches.gdh

if (mongol_e == 1)
	cno_MongolStyle > cMongolStyle;
else
	cMongolStyle >cno_MongolStyle;
endif;

#if 1 // FONT != DOULOSfont
/**** obsolete feature
if (cyr_curs_ital == 1)
	cno_Cursive  >  cCursive;
else
	cCursive  >  cno_Cursive;
endif;
****/
#endif // !DOULOSfont

if (short_breve == 1)
	cno_CyShortMrkAlt > cCyShortMrkAlt;
else
	cCyShortMrkAlt > cno_CyShortMrkAlt;
endif;

// Vietnamese alternates handled above

if (invis == 1)
	cno_ShowInv > cShowInv;
endif;

// NB: Because 01E5 is affected by two features, barred_bowl and literacy,
// these features take special organization of their rules. Specifically,
// 01E5 should be displayed as:
//	if Literacy Alternates then LtnSmGBarredSngBowl (uni01E5.BarBowl.SngBowl)
//	else if Barred-Bowl Forms then LtnSmGBarredBowl (uni01E5.BarBowl)
//	else LtnSmGStrk (uni01E5)
// Note also that uni01E5 doesn't show up in any class


// Note: literacy alternates take precedence over slant-italic feature (below).
if (literacy == 1)
	cno_SngBowl  > cSngBowl;		// (includes uni01E5.BarBowl > uni01E5.BarBowl.SngBowl)
	cno_SngStory > cSngStory;
	g01E5 > g01E5_barBowl_sngBowl;
else
	cSngBowl  > cno_SngBowl;		// (includes uni01E5.BarBowl.SngBowl > uni01E5.BarBowl)
	cSngStory > cno_SngStory;	
endif;

// TODO: the code below will have to be extended somewhat to correctly handle the case where
// the slant-italic glyphs are the default.
#if 1 // FONT != DOULOSfont
if (slant_italic == 1)
  // ff, fi, fl ligatures
  g_f cfLigC2 > g_f_slant_italic cfLigC2_slantItalic   / _ _ cDia;  // don't create a ligature, a following diac stops ligature from forming
  g_f cfLigC2 > _ cfLig_slantItalic:(1 2) {component {f1.ref = @1; f2.ref = @2}};

  g_f g_f cffLigC3 > g_f_slant_italic g_f_slant_italic cffLigC3_slantItalic  / _ _ _ cDia;  // don't create a ligature
  g_f g_f cffLigC3 > _ _ cffLig_slantItalic:(1 2 3) {component {f1.ref = @1; f2.ref = @2; f3.ref = @3}};

  cno_SlantItalic  >  cSlantItalic;		// f, i, l, v
  cno_2StorySlantItalic  >  c2StorySlantItalic;  // a, ae
else
#endif // !DOULOSfont
  // ff, fi, fl ligatures
  g_f cfLigC2 > @1 @2 / _ _ cDia; // do nothing, a following diac stops ligature from forming
  g_f cfLigC2 > _ cfLig:(1 2) {component {f1.ref = @1; f2.ref = @2}};

  g_f g_f cffLigC3 > @1 @2 @3 / _ _ _ cDia;  // do nothing
  g_f g_f cffLigC3 > _ _ cffLig:(1 2 3) {component {f1.ref = @1; f2.ref = @2; f3.ref = @3}};
  
#if 1 // FONT != DOULOSfont
  cSlantItalic  >  cno_SlantItalic;
  c2StorySlantItalic  >  cno_2StorySlantItalic;
endif;
#endif // !DOULOSfont

// The barred_bowl rule must happen *after* the literacy rule
if (barred_bowl == 1)                   //  does contain g01E5, no such naming as uni01e5 or
                                        // uni anything. That is the Postscript Name from xml file.  jw 8/27/04
	cno_BarBowl  >  cBarBowl;	// (does NOT include uni01E5 > uni01E5.BarBowl)
//	g01E5  >  g01E5_barBowl;		        yes it does jw.  commented 8/31 
//					see: cno_BarBowl = (g0180, g_dcroat, g01E5);
else
	cBarBowl  >  cno_BarBowl;	// (does NOT include uni01E5.BarBowl > uni01E5)
//	g01E5_barBowl  >  g01E5;			yes it does jw
endif;

if (ltnjstroke == topSerif)
	cno_TopSerifJStroke  >  cTopSerifJStroke;
else
	cTopSerifJStroke  >  cno_TopSerifJStroke;
endif;

if (open_o == topSerif)
	cno_TopSerifOpenO  >  cTopSerifOpenO;
else
	cTopSerifOpenO  >  cno_TopSerifOpenO;
endif;

if (v_hook == 1)
	cno_StraightLft  >  cStraightLft;
else
	cStraightLft  >  cno_StraightLft;
endif;

if (y_hook == 1)
	g01B3  >  g01B3_rtHook;
else
	g01B3_rtHook  >  g01B3;
endif;

if (n_hook == 1)
	g019D  >  g019D_lCStyle;
else
	g019D_lCStyle  >  g019D;
endif;

if (ezh_curl == 1)
	g0293  >  g0293_lrgBowl;
else
	g0293_lrgBowl  >  g0293;
endif;

if (t_hook == 1)
	g01AC  >  g01AC_rtHook;
else
	g01AC_rtHook  >  g01AC;
endif;

if (h_stroke == 1)
	cno_VertStrk  >  cVertStrk;
else
	cVertStrk  >  cno_VertStrk;
endif;

if (r_tail == 1)
	g2C64  >  g2C64_lCStyle;
else
	g2C64_lCStyle  >  g2C64;
endif;

if (p_hook == 1)
	cno_BowlHook  >  cBowlHook;
else
	cBowlHook  >  cno_BowlHook;
endif;

if (rom == 1)
	cno_CommaStyle > cCommaStyle;
else
	cCommaStyle > cno_CommaStyle;
endif;

if (ezh == 1)
	cno_RevSigmaStyle > cRevSigmaStyle;
else
	cRevSigmaStyle > cno_RevSigmaStyle;
endif;

// ogonek processing must be in pass 2

if (apostrophe == 1)
	cno_Lrg > cLrg;
else
	cLrg > cno_Lrg;
endif;

if (ou == 1)
	cno_OpenTop > cOpenTop;
else
	cOpenTop > cno_OpenTop;
endif;

if (emptyset == 1)
	cno_SlashZero > cSlashZero;
else
	cSlashZero > cno_SlashZero;
endif;

if (modlowcolon == wide)
  gF1E9 > gF1E9_wide;
else
  gF1E9_wide > gF1E9;
endif;

/***************
Obsolete feature:
if (ltnglottalstop == capHeight)
  g0294_lC > g0294;
else
  g0294 > g0294_lC;
endif;
***************/

if (cyrillic_shha == 1)
  g04BB > g04BB_uCStyle;
else
  g04BB_uCStyle > g04BB;
endif;

endpass;  // sub - 1


pass(2)  {MaxBackup = 15; MaxRuleLoop = 30}	// substitution

// Convert i to dotless i when followed by upper diacritic

// decomposed sequences:
cno_Dotless > cDotless / _ DIASTR4(cnUDia) cUDia;
// precomposed chars with i are done by decomposition:
cSpecialDotted _ > g_i_dotless cSpecialDottedDia$1:1 / _ _ DIASTR4(cnUDia) cUDia; 

// Now that ogonek has been composed with its vowels, do retrohook style if wanted:

if (ogonek == americanist)
	cno_RetroHookStyle > cRetroHookStyle;
else
	cRetroHookStyle > cno_RetroHookStyle;
endif;
//	g__aogonek	> g__a g0328_retroHookStyle:1;
//	g_aogonek	> g_a  g0328_retroHookStyle:1;
//	g__eogonek	> g__e g0328_retroHookStyle:1;
//	g_eogonek	> g_e  g0328_retroHookStyle:1;
//	g__iogonek	> g__i g0328_retroHookStyle:1;
//	g_iogonek_dotless > g_i_dotless g0328_retroHookStyle:1;
//	g_iogonek	> g_i  g0328_retroHookStyle:1;
//	g__uogonek	> g__u g0328_retroHookStyle:1;
//	g_uogonek	> g_u  g0328_retroHookStyle:1;
//	g01EA		> g__o g0328_retroHookStyle:1;
//	g01EB		> g_o  g0328_retroHookStyle:1;
//	g01EC		> g__omacron g0328_retroHookStyle:1;
//	g01ED		> g_omacron  g0328_retroHookStyle:1;
//	g_ogonek	> g_ogonek_retro_hook_style:1;
//	g0328		> g0328_retroHookStyle:1;
//endif;


// Handle superscript/subscript diacritics; currently the only one of interest is a diaeresis:
cno_Sup  >  cSup  /  (cModSuper cModSub)  _;


endpass;  // sub - 2

endtable; // substitution


#include "CharisPitches.gdh"


table(positioning) {MUnits = 1000};

// Handle attachments

pass(1)

#define pos_rule(t, x, a, w, n) t x {attach {to = @1; at = a; with = w}; attached = 1} / ^ _ DIASTR4(n) _{attached == 0}
#define pos_ruleSD(t, x, a, w, n) t x {attach {to = @1; at = a; with = w}; insert = 1; attached = 1} / ^ _ DIASTR4(n) _{attached == 0}

if (select_diac)
	pos_ruleSD(cTakesHDia, cHDia, H, HM, cnHDia);
	pos_ruleSD(cTakesLDia, cLDia, L, LM, cnLDia);
	pos_ruleSD(cTakesODia, cODia, O, OM, cnODia);
	pos_ruleSD(cTakesRDia, cRDia, R, RM, cnRDia);
	pos_ruleSD(cTakesUDia, cUDia, U, UM, cnUDia);
else
	pos_rule(cTakesHDia, cHDia, H, HM, cnHDia);
	pos_rule(cTakesLDia, cLDia, L, LM, cnLDia);
	pos_rule(cTakesODia, cODia, O, OM, cnODia);
	pos_rule(cTakesRDia, cRDia, R, RM, cnRDia);
	pos_rule(cTakesUDia, cUDia, U, UM, cnUDia);
endif;

// Bridge diacritics handled by attachment need to have zero advance width,
// otherwise they push the second character out and away. (This wouldn't work if above
// we didn't reprocess attached diacritics using the ^ mechanism.)
cBridgeDiac {advance.x = 0}; 

endpass; // pos - 1


// Handle double-diacritics

pass(2)	// positioning

// Double-diacritics above: the ".1" gives the bounding box of the attached cluster of
// base + diacritics.

// Something on both sides:
cUDblDia {shift.y = max(@B.boundingbox.top.1, @A.boundingbox.top.1) - @D.boundingbox.bottom + 100m ; 
		shift.x = (@A.boundingbox.width.1 - @B.boundingbox.width.1)/2; insert = 1}
		/ cTakesUDia=B DIASTR5(cDia) _=D cTakesUDia=A;
// Begining of line:
cUDblDia {shift.y = @B.boundingbox.top.1 - @D.boundingbox.bottom + 100m ; insert = 1} / cTakesUDia=B DIASTR5(cDia) _=D;
// End of line:
cUDblDia {shift.y = @A.boundingbox.top.1 - @D.boundingbox.bottom + 100m ; insert = 1} / DIASTR5(cDia) _=D cTakesUDia=A;

endpass; // pos - 2


pass(3)

// Double-diacritics below:

// Special case for two bridging diacritics:
g035F {shift.y = min(@B.boundingbox.bottom.1, @A.boundingbox.bottom.1) - @D.boundingbox.top -100m ; 
		  shift.x = (@A.boundingbox.width - @B.boundingbox.width)/2; insert = 1}
		  / cTakesLDia=B DIASTR5(cDia) _=D cTakesLDia=A;
cLDblDia {shift.y = min(@B.boundingbox.bottom.1, @A.boundingbox.bottom.1) - @D.boundingbox.top -100m ; 
		  shift.x = (@A.boundingbox.width.1 - @B.boundingbox.width.1)/2; insert = 1}
		  / cTakesLDia=B DIASTR5(cDia) _=D cTakesLDia=A;
cLDblDia {shift.y = @B.boundingbox.bottom.1 - @D.boundingbox.top -100m ; insert = 1} / cTakesLDia=B DIASTR5(cDia) _=D ;
cLDblDia {shift.y = @A.boundingbox.bottom.1 - @D.boundingbox.top -100m ; insert = 1} / DIASTR5(cDia) _=D cTakesLDia=A ;


endpass; // pos - 3

endtable; // positioning