(debug_flag): Extern it.
[m17n/libotf.git] / src / otfdrive.c
1 /* otfdrive.c -- OpenType font driver.
2
3 Copyright (C) 2003, 2004
4   National Institute of Advanced Industrial Science and Technology (AIST)
5   Registration Number H15PRO167
6
7 This file is part of libotf.
8
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17 License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA.  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <config.h>
28
29 #include "otf.h"
30 #include "otferror.h"
31
32 extern int debug_flag;
33
34 /* Return nonzero (-1 if ID is zero, 1 otherwise) if OTF_Glyph *G
35    should be ignored according to LookupFlag FLAG.  */
36 #define IGNORED_GLYPH(g, flag)                          \
37   ((g)->glyph_id == 0 ? -1                              \
38    : (((flag) & (1 << (g)->GlyphClass))                 \
39       || (((flag) & OTF_MarkAttachmentType)             \
40           && (g)->GlyphClass == OTF_GlyphClassMark      \
41           && ((flag) >> 8) != (g)->MarkAttachClass)))
42
43 #define GSTRING_DELETE(gstring, from, len)                              \
44   do {                                                                  \
45     memmove (gstring->glyphs + from, gstring->glyphs + from + len,      \
46              sizeof (OTF_Glyph) * (gstring->used - from - len));        \
47     gstring->used -= len;                                               \
48   } while (0)
49
50
51 #define GSTRING_INSERT(gstring, pos, len)                               \
52   do {                                                                  \
53     if (gstring->used + len > gstring->size)                            \
54       {                                                                 \
55         char *errfmt = "GSTRING%s";                                     \
56                                                                         \
57         gstring->size = gstring->used + len;                            \
58         gstring->glyphs                                                 \
59           = (OTF_Glyph *) realloc (gstring->glyphs,                     \
60                                    sizeof (OTF_Glyph) * gstring->size); \
61         if (! gstring->glyphs)                                          \
62           OTF_ERROR (OTF_ERROR_MEMORY, "");                             \
63       }                                                                 \
64     memmove (gstring->glyphs + pos + len, gstring->glyphs + pos,        \
65              sizeof (OTF_Glyph) * (gstring->used - pos));               \
66     gstring->used += len;                                               \
67   } while (0)
68
69
70 static unsigned get_class_def (OTF_ClassDef *, OTF_GlyphID);
71
72 static int
73 gstring_subst (OTF *otf, OTF_GlyphString *gstring, int from, int to, int flag,
74                OTF_GlyphID *ids, int num)
75 {
76   int errret = -1;
77   int len = to - from;
78   int i;
79   int from_idx = gstring->glyphs[from].f.index.from;
80   int to_idx = gstring->glyphs[to - 1].f.index.to;
81   int non_ignored_idx;
82
83   for (i = non_ignored_idx = to - 1; i >= from; i--)
84     {
85       OTF_Glyph *g = gstring->glyphs + i;
86
87       if (IGNORED_GLYPH (g, flag) == 1)
88         {
89           /* Move this glyph to the next of the current target of
90              substitution.  */
91           OTF_Glyph temp = *g;
92
93           memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
94           temp.f.index.from = from_idx;
95           temp.f.index.to = to_idx;
96           gstring->glyphs[non_ignored_idx--] = temp;
97           len--;
98         }
99     }
100
101   if (len < num)
102     GSTRING_INSERT (gstring, from, (num - len));
103   else if (len > num)
104     GSTRING_DELETE (gstring, from, (len - num));
105   for (i = 0; i < num; i++)
106     {
107       if (gstring->glyphs[from + i].glyph_id != ids[i])
108         {
109           gstring->glyphs[from + i].c = 0;
110           if (otf->gdef)
111             gstring->glyphs[from + i].GlyphClass
112               = get_class_def (&otf->gdef->glyph_class_def, ids[i]);
113           else
114             gstring->glyphs[from + i].GlyphClass = 0;
115         }
116       gstring->glyphs[from + i].glyph_id = ids[i];
117       gstring->glyphs[from + i].positioning_type = 0;
118       gstring->glyphs[from + i].f.index.from = from_idx;
119       gstring->glyphs[from + i].f.index.to = to_idx;
120     }
121   return 0;
122 }
123
124 \f
125 static int
126 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
127 {
128   int i;
129
130   if (coverage->CoverageFormat == 1)
131     {
132       for (i = 0; i < coverage->Count; i++)
133         if (coverage->table.GlyphArray[i] == id)
134           return i;
135     }
136   else
137     {
138       for (i = 0; i < coverage->Count; i++)
139         if (coverage->table.RangeRecord[i].Start <= id
140             && coverage->table.RangeRecord[i].End >= id)
141           return (coverage->table.RangeRecord[i].StartCoverageIndex
142                   + (id - coverage->table.RangeRecord[i].Start));
143     }
144   return -1;
145 }
146
147 static unsigned
148 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
149 {
150   if (class_def->ClassFormat == 1)
151     {
152       int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
153
154       if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
155         return class_def->f.f1.ClassValueArray[idx];
156     }
157   else
158     {
159       int i;
160
161       for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
162         if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
163             && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
164           return class_def->f.f2.ClassRangeRecord[i].Class;
165     }
166   return 0;
167 }
168
169 static OTF_LangSys *
170 get_langsys (OTF_ScriptList *script_list,
171              const char *script, const char *language)
172 {
173
174   OTF_Tag script_tag = OTF_tag (script);
175   OTF_Tag langsys_tag = OTF_tag (language);
176   int i, j;
177   OTF_Tag dflt_tag = OTF_tag ("DFLT");
178   OTF_Script *dflt = NULL;
179
180   for (i = 0; i < script_list->ScriptCount; i++)
181     {
182       OTF_Script *script = script_list->Script + i;
183
184       if (script_list->Script[i].ScriptTag == dflt_tag)
185         dflt = script;
186       if (script_list->Script[i].ScriptTag == script_tag)
187         {
188           if (! langsys_tag)
189             return &script->DefaultLangSys;
190           for (j = 0; j < script->LangSysCount; j++)
191             if (script->LangSysRecord[j].LangSysTag == langsys_tag)
192               return script->LangSys + j;
193           return &script->DefaultLangSys;       
194         }
195     }
196
197   if (! dflt)
198     dflt = script_list->Script;
199   if (! langsys_tag)
200     return &dflt->DefaultLangSys;
201   for (j = 0; j < dflt->LangSysCount; j++)
202     if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
203       return dflt->LangSys + j;
204   return &dflt->DefaultLangSys; 
205 }
206
207 static int
208 setup_lookup_flags (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
209                     OTF_LangSys *LangSys,
210                     const char *features, char *lookup_flags)
211 {
212   int i, j, n = 0;
213   OTF_Feature *feature;
214   int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
215
216   if (! feature_table)
217     return -1;
218   for (i = 0; i < FeatureList->FeatureCount; i++)
219     feature_table[i] = 0;
220   memset (lookup_flags, 0, LookupList->LookupCount);
221
222   while (*features)
223     {
224       char tagname[4];
225       OTF_Tag tag;
226       int use_it = 1;
227
228       if (*features == '*')
229         {
230           /* Consume all remaining features.  */
231           for (i = 0; i < LangSys->FeatureCount; i++) 
232             {
233               int index = LangSys->FeatureIndex[i];
234
235               if (! feature_table[index])
236                 {
237                   feature = FeatureList->Feature + index;
238                   for (j = 0; j < feature->LookupCount; j++)
239                     lookup_flags[feature->LookupListIndex[j]] = 1;
240                 }
241             }
242           break;
243         }
244
245       if (*features == '~')
246         use_it = -1, features++;
247       for (i = 0; *features && *features != ','; i++, features++)
248         tagname[i] = *features;
249       if (*features)
250         /* Skip ',' */
251         features++;
252       for (; i < 4; i++)
253         tagname[i] = '\0';
254       tag = OTF_tag (tagname);
255       for (i = 0; i < LangSys->FeatureCount; i++)
256         {
257           feature = FeatureList->Feature + LangSys->FeatureIndex[i];
258           if (tag == feature->FeatureTag)
259             {
260               if (feature_table[i])
261                 break;
262               if (use_it > 0)
263                 for (j = 0; j < feature->LookupCount; j++)
264                   lookup_flags[feature->LookupListIndex[j]] = 1;
265               feature_table[i] = use_it;
266               break;
267             }
268         }
269     }
270   return 0;
271 }
272
273 static int
274 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
275            int count, OTF_GlyphID *ids)
276 {
277   OTF_Glyph *gbeg = gstring->glyphs + gidx;
278   OTF_Glyph *gend = gstring->glyphs + gstring->used;
279   OTF_Glyph *g;
280   int i;
281
282   for (g = gbeg, i = 0; g < gend && i < count; g++)
283     if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
284       return -1;
285   return (i < count ? -1 : g - gbeg);
286 }
287
288 static int
289 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
290                  OTF_ChainRule *rule)
291 {
292   int i = rule->BacktrackGlyphCount;
293
294   if (i > 0)
295     {
296       int j;
297       OTF_Glyph *g;
298
299       for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
300         if (! IGNORED_GLYPH (g, flag) && --i == 0)
301           break;
302       if (i > 0)
303         return -1;
304       if (match_ids (gstring, j, flag,
305                      rule->BacktrackGlyphCount, rule->Backtrack)
306           < 0)
307         return -1;
308     }
309   gidx++;
310   i = match_ids (gstring, gidx, flag,
311                  rule->InputGlyphCount - 1, rule->Input);
312   if (i < 0)
313     return -1;
314   gidx += i;
315   i = match_ids (gstring, gidx, flag,
316                  rule->LookaheadGlyphCount, rule->LookAhead);
317   if (i < 0)
318     return -1;
319   return 0;
320 }
321
322 static int
323 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
324                int flag, int count, unsigned *classes)
325 {
326   OTF_Glyph *gbeg = gstring->glyphs + gidx;
327   OTF_Glyph *gend = gstring->glyphs + gstring->used;
328   OTF_Glyph *g;
329   int i;
330
331   for (g = gbeg, i = 0; g < gend && i < count; g++)
332     if (! IGNORED_GLYPH (g, flag)
333         && get_class_def (class_def, g->glyph_id) != classes[i++])
334       return -1;
335   return (i < count ? -1 : g - gbeg);
336 }
337
338 static int
339 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
340                      OTF_ClassDef *BacktrackClassDef,
341                      OTF_ClassDef *InputClassDef,
342                      OTF_ClassDef *LookaheadClassDef,
343                      OTF_ChainClassRule *rule)
344 {
345   int i = rule->BacktrackGlyphCount;
346
347   if (i > 0)
348     {
349       int j;
350       OTF_Glyph *g;
351
352       for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
353         if (! IGNORED_GLYPH (g, flag) && i-- == 0)
354           break;
355       if (i > 0)
356         return -1;
357       if (match_classes (BacktrackClassDef, gstring, j, flag,
358                          rule->BacktrackGlyphCount, rule->Backtrack) < 0);
359       return -1;
360     }
361   gidx++;
362   i = match_classes (InputClassDef, gstring, gidx, flag,
363                      rule->InputGlyphCount - 1, rule->Input);
364   if (i < 0)
365     return -1;
366   gidx += i;
367   i = match_classes (LookaheadClassDef, gstring, gidx, flag,
368                      rule->LookaheadGlyphCount, rule->LookAhead);
369   if (i < 0)
370     return -1;
371   return 0;
372 }
373
374
375 static int
376 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
377                  OTF_Coverage *coverages)
378 {
379   OTF_Glyph *gbeg = gstring->glyphs + gidx;
380   OTF_Glyph *gend = gstring->glyphs + gstring->used;
381   OTF_Glyph *g;
382   int i;
383
384   for (g = gbeg, i = 0; g < gend && i < count; g++)
385     if (! IGNORED_GLYPH (g, flag)
386         && get_coverage_index (coverages + i++, g->glyph_id) < 0)
387       return -1;
388   return (i < count ? -1 : g - gbeg);
389 }
390
391 static int
392 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
393                        OTF_GSUB_ChainContext3 *context3)
394 {
395   int i = context3->BacktrackGlyphCount;
396
397   if (i > 0)
398     {
399       int j;
400       OTF_Glyph *g;
401
402       for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
403         if (! IGNORED_GLYPH (g, flag) && --i == 0)
404           break;
405       if (i > 0)
406         return -1;
407       if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
408                            context3->Backtrack) < 0)
409         return -1;
410     }
411   gidx++;
412   if (context3->InputGlyphCount > 1)
413     {
414       i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
415                            context3->Input + 1);
416       if (i < 0)
417         return -1;
418       gidx += i;
419     }
420   if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
421                        context3->LookAhead) < 0)
422     return -1;
423   return 0;
424 }
425
426 static int
427 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
428              OTF_GlyphString *gstring, int gidx, int alternate_subst)
429 {
430   char *errfmt = "GSUB Looking up%s";
431   int errret = -1;
432   OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
433   unsigned int flag = (lookup->LookupFlag
434                        & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
435   int orig_gidx = gidx;
436   OTF_Glyph *g = gstring->glyphs + gidx;
437   int i;
438
439   if (IGNORED_GLYPH (g, flag))
440     return (gidx + 1);
441
442   /* Try all subtables until one of them handles the current glyph.  */
443   for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
444     {
445       unsigned lookup_type = lookup->LookupType;
446       OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
447       int coverage_idx;
448
449       if (lookup_type == 7)
450         {
451           OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
452
453           lookup_type = extension1->ExtensionLookupType;
454           subtable = extension1->ExtensionSubtable;
455         }
456
457       if (alternate_subst
458           ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
459           : (lookup_type == 3))
460         continue;
461
462       if (subtable->Coverage.offset)
463         {
464           coverage_idx = get_coverage_index (&subtable->Coverage,
465                                              g->glyph_id);
466           if (coverage_idx < 0)
467             continue;
468         }
469
470       switch (lookup_type)
471         {
472         case 1:
473           if (subtable->Format == 1)
474             g->glyph_id += subtable->u.single1.DeltaGlyphID;
475           else
476             g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
477           gidx++;
478           break;
479
480         case 2:
481           if (subtable->Format == 1)
482             {
483               OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
484               OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
485
486               gstring_subst (otf, gstring, gidx, gidx + 1, flag,
487                              seq->Substitute, seq->GlyphCount);
488               gidx += seq->GlyphCount;
489             }
490           else
491             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
492           break;
493
494         case 3:
495           if (subtable->Format == 1)
496             {
497               OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
498               OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
499
500               gstring_subst (otf, gstring, gidx, gidx + 1, flag,
501                              altset->Alternate, altset->GlyphCount);
502               gidx += altset->GlyphCount;;
503             }
504           else
505             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
506           break;
507
508         case 4:
509           if (subtable->Format == 1)
510             {
511               OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
512               OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
513               OTF_Ligature *lig;
514               int j;
515
516               for (j = 0; j < ligset->LigatureCount; j++)
517                 {
518                   int n;
519
520                   lig = ligset->Ligature + j;
521                   n = match_ids (gstring, gidx + 1, flag,
522                                  lig->CompCount - 1, lig->Component);
523                   if (n < 0)
524                     continue;
525                   gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
526                                  &lig->LigGlyph, 1);
527                   gidx++;
528                   break;
529                 }
530             }
531           else
532             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
533           break;
534
535         case 5:
536           if (subtable->Format == 1)
537             {
538               OTF_GSUB_Context1 *context1 = &subtable->u.context1;
539               OTF_RuleSet *set = context1->RuleSet + coverage_idx;
540               OTF_Rule *rule;
541               int orig_used;
542               int j, k;
543
544               for (j = 0; j < set->RuleCount; j++)
545                 {
546                   rule = set->Rule + j;
547                   if (match_ids (gstring, gidx + 1, flag,
548                                  rule->GlyphCount - 1, rule->Input) < 0)
549                     continue;
550                   orig_used = gstring->used;
551                   for (k = 0; k < rule->LookupCount; k++)
552                     lookup_gsub (otf, lookup_list,
553                                  rule->LookupRecord[k].LookupListIndex,
554                                  gstring,
555                                  gidx + rule->LookupRecord[k].SequenceIndex,
556                                  alternate_subst);
557                   gidx += rule->GlyphCount + (gstring->used - orig_used);
558                   break;
559                 }
560             }
561           else if (subtable->Format == 2)
562             {
563               OTF_GSUB_Context2 *context2 = &subtable->u.context2;
564               OTF_ClassSet *set;
565               OTF_ClassRule *rule;
566               unsigned class;
567               int orig_used;
568               int j, k;
569
570               class = get_class_def (&context2->ClassDef, g->glyph_id);
571               set = context2->ClassSet + class;
572               if (set)
573                 for (j = 0; j < set->ClassRuleCnt; j++)
574                   {
575                     rule = set->ClassRule + j;
576                     if (match_classes (&context2->ClassDef,
577                                        gstring, gidx + 1, flag,
578                                        rule->GlyphCount - 1, rule->Class)
579                         < 0)
580                       continue;
581                     orig_used = gstring->used;
582                     for (k = 0; k < rule->LookupCount; k++)
583                       lookup_gsub (otf, lookup_list,
584                                    rule->LookupRecord[k].LookupListIndex,
585                                    gstring,
586                                    gidx + rule->LookupRecord[k].SequenceIndex,
587                                    alternate_subst);
588                     gidx += rule->GlyphCount + (gstring->used - orig_used);
589                     break;
590                   }
591             }
592           else                  /* subtable->Format == 3 */
593             {
594               OTF_GSUB_Context3 *context3 = &subtable->u.context3;
595               int orig_used;
596               int j;
597
598               if (match_coverages (gstring, gidx + 1, flag,
599                                    context3->GlyphCount - 1,
600                                    context3->Coverage + 1) < 0)
601                 continue;
602               orig_used = gstring->used;
603               for (j = 0; j < context3->LookupCount; j++)
604                 lookup_gsub (otf, lookup_list,
605                              context3->LookupRecord[j].LookupListIndex,
606                              gstring,
607                              gidx + context3->LookupRecord[j].SequenceIndex,
608                              alternate_subst);
609               gidx += context3->GlyphCount + (gstring->used - orig_used);
610             }
611           break;
612
613         case 6:
614           if (subtable->Format == 1)
615             {
616               OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
617               OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
618               int orig_used;
619               int j, k;
620               
621               for (j = 0; j < set->ChainRuleCount; j++)
622                 {
623                   OTF_ChainRule *rule = set->ChainRule + j;
624
625                   if (gidx < rule->BacktrackGlyphCount
626                       || (gidx + rule->InputGlyphCount
627                           + rule->LookaheadGlyphCount) > gstring->used)
628                     continue;
629                   if (match_chain_ids (gstring, gidx, flag, rule) < 0)
630                     continue;
631                   orig_used = gstring->used;
632                   for (k = 0; k < rule->LookupCount; k++)
633                     lookup_gsub (otf, lookup_list,
634                                  rule->LookupRecord[k].LookupListIndex,
635                                  gstring,
636                                  gidx + rule->LookupRecord[k].SequenceIndex,
637                                  alternate_subst);
638                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
639                   break;
640                 }
641             }
642           else if (subtable->Format == 2)
643             {
644               OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
645               OTF_ChainClassSet *set;
646               unsigned class;
647               int j;
648               int orig_used;
649
650               class = get_class_def (&context2->InputClassDef, g->glyph_id);
651               set = context2->ChainClassSet + class;
652               for (j = 0; j < set->ChainClassRuleCnt; j++)
653                 {
654                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
655                   int k;
656
657                   if (gidx < rule->BacktrackGlyphCount
658                       || (gidx + rule->InputGlyphCount
659                           + rule->LookaheadGlyphCount) > gstring->used)
660                     continue;
661                   if (match_chain_classes (gstring, gidx, flag,
662                                            &context2->BacktrackClassDef,
663                                            &context2->InputClassDef,
664                                            &context2->LookaheadClassDef,
665                                            rule) < 0)
666                     continue;
667                   orig_used = gstring->used;
668                   for (k = 0; k < rule->LookupCount; k++)
669                     lookup_gsub (otf, lookup_list,
670                                  rule->LookupRecord[k].LookupListIndex,
671                                  gstring,
672                                  gidx + rule->LookupRecord[k].SequenceIndex,
673                                  alternate_subst);
674                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
675                   break;
676                 }
677             }
678           else
679             {
680               OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
681               int orig_used;
682               int j;
683
684               if (gidx < context3->BacktrackGlyphCount
685                   || (gidx + context3->InputGlyphCount
686                       + context3->LookaheadGlyphCount) > gstring->used)
687                 continue;
688               if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
689                 continue;
690               orig_used = gstring->used;
691               for (j = 0; j < context3->LookupCount; j++)
692                 lookup_gsub (otf, lookup_list,
693                              context3->LookupRecord[j].LookupListIndex,
694                              gstring,
695                              gidx + context3->LookupRecord[j].SequenceIndex,
696                              alternate_subst);
697               gidx += context3->InputGlyphCount + (gstring->used - orig_used);
698             }
699           break;
700
701         case 8:
702           {
703             OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
704             int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
705             int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
706             int j;
707
708             if (back_gidx > gstring->used || ahead_gidx < 0)
709               break;
710
711             for (j = 0; j < reverse->BacktrackGlyphCount; j++)
712               if (get_coverage_index (reverse->Backtrack + j,
713                                       gstring->glyphs[gidx + 1 + j].glyph_id)
714                   < 0)
715                 break;
716             if (j < reverse->BacktrackGlyphCount)
717               continue;
718             for (j = 0; j < reverse->LookaheadGlyphCount; j++)
719               if (get_coverage_index (reverse->LookAhead + j,
720                                       gstring->glyphs[gidx - 1 - j].glyph_id)
721                   < 0)
722                 break;
723             if (j < reverse->LookaheadGlyphCount)
724               continue;
725             g->glyph_id = reverse->Substitute[coverage_idx];
726             gidx--;
727           }
728
729         default:
730           continue;
731         }
732     }
733   if (gidx == orig_gidx)
734     gidx++;
735   return gidx;
736 }
737
738 \f
739
740 /* GPOS */
741 unsigned
742 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
743 {
744   unsigned value_format = OTF_XPlacement | OTF_YPlacement;
745
746   rec->XPlacement = anchor->XCoordinate;
747   rec->YPlacement = anchor->YCoordinate;
748   if (anchor->AnchorFormat == 1)
749     /* Nothing to do */
750     ;
751   else if (anchor->AnchorFormat == 2)
752     /* Not yet implemented */
753     ;
754   else if (anchor->AnchorFormat == 3)
755     /* Not yet implemented */
756     ;
757   return value_format;
758 }
759
760 static int
761 gstring_insert_for_gpos (OTF_GlyphString *gstring, int gidx)
762 {
763   int errret = -1;
764   int orig_gidx = gidx++;
765
766   while (gidx < gstring->used
767          && ! gstring->glyphs[gidx].glyph_id
768          && gstring->glyphs[gidx].positioning_type)
769     gidx++;
770   GSTRING_INSERT (gstring, gidx, 1);
771   gstring->glyphs[gidx] = gstring->glyphs[orig_gidx];
772   gstring->glyphs[gidx].glyph_id = 0;
773   return gidx;
774 }
775
776 static int
777 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
778              OTF_GlyphString *gstring, int gidx, int accumulate)
779 {
780   char *errfmt = "GPOS Looking up%s";
781   int errret = -1;
782   OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
783   unsigned int flag = (lookup->LookupFlag
784                        & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
785   int orig_gidx = gidx;
786   OTF_Glyph *g = gstring->glyphs + gidx;
787   int i;
788
789   if (debug_flag)
790     fprintf (stderr, "[GPOS] glyph:%X lookup(%d)",
791              g->glyph_id, lookup_list_index);
792   if (IGNORED_GLYPH (g, flag))
793     {
794       if (debug_flag)
795         fprintf (stderr, " ignored glyph\n");
796       return (gidx + 1);
797     }
798
799   /* Try all subtables until one of them handles the current glyph.  */
800   for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
801     {
802       unsigned lookup_type = lookup->LookupType;
803       OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
804       int coverage_idx;
805       int positioning_type;
806       enum OTF_ValueFormat format;
807       OTF_ValueRecord *value;
808       OTF_Anchor *anchor1, *anchor2;
809
810       if (lookup_type == 9)
811         {
812           OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
813
814           lookup_type = extension1->ExtensionLookupType;
815           subtable = extension1->ExtensionSubtable;
816         }
817
818       if (debug_flag)
819         fprintf (stderr, " type(%d)", lookup_type);
820       if (subtable->Coverage.offset)
821         {
822           coverage_idx = get_coverage_index (&subtable->Coverage,
823                                              g->glyph_id);
824           if (coverage_idx < 0)
825             continue;
826         }
827
828       switch (lookup_type)
829         {
830         case 1:
831           positioning_type = lookup_type;
832           if (subtable->Format == 1)
833             {
834               OTF_GPOS_Single1 *single1 = &subtable->u.single1;
835
836               format = single1->ValueFormat;
837               value = &single1->Value;
838             }
839           else if (subtable->Format == 2)
840             {
841               OTF_GPOS_Single2 *single2 = &subtable->u.single2;
842
843               format = single2->ValueFormat;
844               value = single2->Value + coverage_idx;
845             }
846           if (accumulate && g->positioning_type)
847             {
848               gidx = gstring_insert_for_gpos (gstring, gidx);         
849               g = gstring->glyphs + gidx;
850             }
851           g->positioning_type = positioning_type;
852           g->f.f1.format = format;
853           g->f.f1.value = value;
854           gidx++;
855           break;
856
857         case 2:
858           {
859             int next_gidx;
860             OTF_Glyph *nextg;
861
862             for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
863                  next_gidx < gstring->used && IGNORED_GLYPH (nextg, flag);
864                  next_gidx++, nextg++);
865
866             if (next_gidx >= gstring->used)
867               continue;
868             if (subtable->Format == 1)
869               {
870                 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
871                 OTF_PairSet *set = pair1->PairSet + coverage_idx;
872                 int j;
873
874                 for (j = 0; j < set->PairValueCount; j++)
875                   if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
876                     {
877                       if (pair1->ValueFormat1)
878                         {
879                           if (accumulate && g->positioning_type)
880                             {
881                               gidx = gstring_insert_for_gpos (gstring, gidx);
882                               g = gstring->glyphs + gidx;
883                               next_gidx += gidx - orig_gidx;
884                               nextg = gstring->glyphs + next_gidx;
885                             }
886                           g->positioning_type = lookup_type;
887                           g->f.f2.format = pair1->ValueFormat1;
888                           g->f.f2.value = &set->PairValueRecord[j].Value1;
889                         }
890                       gidx = next_gidx;
891                       g = nextg;
892                       if (pair1->ValueFormat2)
893                         {
894                           if (accumulate && g->positioning_type)
895                             {
896                               gidx = gstring_insert_for_gpos (gstring, gidx);
897                               g = gstring->glyphs + gidx;
898                             }
899                           g->positioning_type = lookup_type;
900                           g->f.f2.format = pair1->ValueFormat2;
901                           g->f.f2.value = &set->PairValueRecord[j].Value2;
902                           gidx++;
903                         }
904                       break;
905                     }
906               }
907             else if (subtable->Format == 2)
908               {
909                 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
910                 unsigned class1, class2;
911
912                 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
913                 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
914                 if (pair2->ValueFormat1)
915                   {
916                     if (accumulate && g->positioning_type)
917                       {
918                         gidx = gstring_insert_for_gpos (gstring, gidx);
919                         g = gstring->glyphs + gidx;
920                         next_gidx += gidx - orig_gidx;
921                         nextg = gstring->glyphs + next_gidx;
922                       }
923                     g->positioning_type = lookup_type;
924                     g->f.f2.format = pair2->ValueFormat1;
925                     g->f.f2.value
926                       = &pair2->Class1Record[class1].Class2Record[class2].Value1;
927                   }
928                 gidx = next_gidx;
929                 g = nextg;
930                 if (pair2->ValueFormat2)
931                   {
932                     if (accumulate && g->positioning_type)
933                       {
934                         gidx = gstring_insert_for_gpos (gstring, gidx);
935                         g = gstring->glyphs + gidx;
936                       }
937                     g->positioning_type = lookup_type;
938                     g->f.f2.format = pair2->ValueFormat2;
939                     g->f.f2.value
940                       = &pair2->Class1Record[class1].Class2Record[class2].Value2;
941                     gidx++;
942                   }
943               }
944           }
945           break;
946
947         case 3:
948           {
949             OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
950           
951             if (accumulate && g->positioning_type)
952               {
953                 gidx = gstring_insert_for_gpos (gstring, gidx);
954                 g = gstring->glyphs + gidx;
955               }
956             g->positioning_type = lookup_type;
957             g->f.f3.entry_anchor
958               = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
959             g->f.f3.exit_anchor
960               = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
961             gidx++;
962           }
963           break;
964
965         case 4:
966           if (gidx < 1)
967             continue;
968           if (subtable->Format == 1)
969             {
970               OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
971               OTF_MarkRecord *mark_record;
972               OTF_AnchorRecord *base_record;
973               OTF_Glyph *baseg;
974               int coverage_idx_base;
975               unsigned int this_flag = flag | OTF_IgnoreMarks;
976
977               for (baseg = g - 1;
978                    baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, this_flag);
979                    baseg--);
980               if (baseg < gstring->glyphs)
981                 continue;
982               coverage_idx_base
983                 = get_coverage_index (&mark_base1->BaseCoverage,
984                                       baseg->glyph_id);
985               if (coverage_idx_base < 0)
986                 continue;
987               mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
988               base_record
989                 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
990               if (accumulate && g->positioning_type)
991                 {
992                   gidx = gstring_insert_for_gpos (gstring, gidx);
993                   g = gstring->glyphs + gidx;
994                 }
995               g->f.f4.mark_anchor = &mark_record->MarkAnchor;
996               g->f.f4.base_anchor
997                 = &base_record->Anchor[mark_record->Class];
998               g->positioning_type = lookup_type;
999               gidx++;
1000             }
1001           break;
1002
1003         case 5:
1004           if (gidx < 1)
1005             continue;
1006           if (subtable->Format == 1)
1007             {
1008               OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
1009               OTF_Glyph *ligg;
1010               int coverage_idx_lig;
1011               OTF_MarkRecord *mark_record;
1012               OTF_LigatureAttach *attach;
1013               int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
1014               int j;
1015                                        
1016               for (j = 0; j < mark_lig1->ClassCount; j++)
1017                 num_class[j] = 0;
1018
1019               for (ligg = g - 1;
1020                    (ligg >= gstring->glyphs
1021                     && (IGNORED_GLYPH (ligg, flag)
1022                         || ligg->GlyphClass > OTF_GlyphClassLigature));
1023                    ligg--)
1024                 if (ligg->positioning_type == 5
1025                     && ligg->MarkAttachClass < mark_lig1->ClassCount)
1026                   num_class[ligg->MarkAttachClass]++;
1027               if (ligg < gstring->glyphs)
1028                 continue;
1029               coverage_idx_lig
1030                 = get_coverage_index (&mark_lig1->LigatureCoverage,
1031                                       ligg->glyph_id);
1032               if (coverage_idx_lig < 0)
1033                 continue;
1034               mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
1035               g->MarkAttachClass = mark_record->Class;
1036               attach = (mark_lig1->LigatureArray.LigatureAttach
1037                         + coverage_idx_lig);
1038               for (j = 0; j < attach->ComponentCount; j++)
1039                 {
1040                   OTF_Anchor *lig_anchor
1041                     = attach->ComponentRecord[j].LigatureAnchor;
1042
1043                   if (lig_anchor[mark_record->Class].AnchorFormat
1044                       && num_class[mark_record->Class]-- == 0)
1045                     {
1046                       if (accumulate && g->positioning_type)
1047                         {
1048                           gidx = gstring_insert_for_gpos (gstring, gidx);
1049                           g = gstring->glyphs + gidx;
1050                         }
1051                       g->positioning_type = lookup_type;
1052                       g->f.f5.mark_anchor = &mark_record->MarkAnchor;
1053                       g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
1054                       gidx++;
1055                       break;
1056                     }
1057                 }
1058             }
1059           break;
1060
1061         case 6:
1062           if (gidx < 1)
1063             continue;
1064           if (subtable->Format == 1)
1065             {
1066               OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
1067               OTF_MarkRecord *mark1_record;
1068               OTF_AnchorRecord *mark2_record;
1069               OTF_Glyph *prevg;
1070               int coverage_idx_base;
1071
1072               for (prevg = g - 1;
1073                    prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
1074                    prevg--);
1075               if (prevg < gstring->glyphs)
1076                 continue;
1077               coverage_idx_base
1078                 = get_coverage_index (&mark_mark1->Mark2Coverage,
1079                                       prevg->glyph_id);
1080               if (coverage_idx_base < 0)
1081                 continue;
1082               mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
1083               mark2_record
1084                 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
1085               if (accumulate && g->positioning_type)
1086                 {
1087                   gidx = gstring_insert_for_gpos (gstring, gidx);
1088                   g = gstring->glyphs + gidx;
1089                 }
1090               g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
1091               g->f.f6.mark2_anchor
1092                 = &mark2_record->Anchor[mark1_record->Class];
1093               g->positioning_type = lookup_type;
1094               gidx++;
1095               break;
1096             }
1097           break;
1098
1099         case 7:
1100           if (subtable->Format == 1)
1101             {
1102               OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1103               OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1104               OTF_Rule *rule;
1105               int orig_used;
1106               int j, k;
1107
1108               for (j = 0; j < set->RuleCount; j++)
1109                 {
1110                   rule = set->Rule + j;
1111                   if (match_ids (gstring, gidx + 1, flag,
1112                                  rule->GlyphCount - 1, rule->Input) < 0)
1113                     continue;
1114                   orig_used = gstring->used;
1115                   for (k = 0; k < rule->LookupCount; k++)
1116                     lookup_gpos (lookup_list,
1117                                  rule->LookupRecord[k].LookupListIndex,
1118                                  gstring,
1119                                  gidx + rule->LookupRecord[k].SequenceIndex,
1120                                  accumulate);
1121                   gidx += rule->GlyphCount + (gstring->used - orig_used);
1122                   break;
1123                 }
1124             }
1125           else if (subtable->Format == 2)
1126             {
1127               OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1128               OTF_ClassSet *set;
1129               OTF_ClassRule *rule;
1130               unsigned class;
1131               int orig_used;
1132               int j, k;
1133
1134               class = get_class_def (&context2->ClassDef, g->glyph_id);
1135               set = context2->ClassSet + class;
1136               if (set)
1137                 for (j = 0; j < set->ClassRuleCnt; j++)
1138                   {
1139                     rule = set->ClassRule + j;
1140                     if (match_classes (&context2->ClassDef,
1141                                        gstring, gidx + 1, flag,
1142                                        rule->GlyphCount - 1, rule->Class)
1143                         < 0)
1144                       continue;
1145                     orig_used = gstring->used;
1146                     for (k = 0; k < rule->LookupCount; k++)
1147                       lookup_gpos (lookup_list,
1148                                    rule->LookupRecord[k].LookupListIndex,
1149                                    gstring,
1150                                    gidx + rule->LookupRecord[k].SequenceIndex,
1151                                    accumulate);
1152                     gidx += rule->GlyphCount + (gstring->used - orig_used);
1153                     break;
1154                   }
1155             }
1156           else                  /* subtable->Format == 3 */
1157             {
1158               OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1159               int orig_used;
1160               int j;
1161
1162               if (match_coverages (gstring, gidx + 1, flag,
1163                                    context3->GlyphCount - 1,
1164                                    context3->Coverage + 1) < 0)
1165                 continue;
1166               orig_used = gstring->used;
1167               for (j = 0; j < context3->LookupCount; j++)
1168                 lookup_gpos (lookup_list,
1169                              context3->LookupRecord[j].LookupListIndex,
1170                              gstring,
1171                              gidx + context3->LookupRecord[j].SequenceIndex,
1172                              accumulate);
1173               gidx += context3->GlyphCount + (gstring->used - orig_used);
1174             }
1175           break;
1176
1177         case 8:
1178           if (subtable->Format == 1)
1179             {
1180               OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1181               OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1182               int orig_used;
1183               int j, k;
1184               
1185               for (j = 0; j < set->ChainRuleCount; j++)
1186                 {
1187                   OTF_ChainRule *rule = set->ChainRule + j;
1188
1189                   if (gidx < rule->BacktrackGlyphCount
1190                       || (gidx + rule->InputGlyphCount
1191                           + rule->LookaheadGlyphCount) > gstring->used)
1192                     continue;
1193                   if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1194                     continue;
1195                   orig_used = gstring->used;
1196                   for (k = 0; k < rule->LookupCount; k++)
1197                     lookup_gpos (lookup_list,
1198                                  rule->LookupRecord[k].LookupListIndex,
1199                                  gstring,
1200                                  gidx + rule->LookupRecord[k].SequenceIndex,
1201                                  accumulate);
1202                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1203                   break;
1204                 }
1205             }
1206           else if (subtable->Format == 2)
1207             {
1208               OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1209               OTF_ChainClassSet *set;
1210               unsigned class;
1211               int j;
1212               int orig_used;
1213
1214               class = get_class_def (&context2->InputClassDef, g->glyph_id);
1215               set = context2->ChainClassSet + class;
1216               for (j = 0; j < set->ChainClassRuleCnt; j++)
1217                 {
1218                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
1219                   int k;
1220
1221                   if (gidx < rule->BacktrackGlyphCount
1222                       || (gidx + rule->InputGlyphCount
1223                           + rule->LookaheadGlyphCount) > gstring->used)
1224                     continue;
1225                   if (match_chain_classes (gstring, gidx, flag,
1226                                            &context2->BacktrackClassDef,
1227                                            &context2->InputClassDef,
1228                                            &context2->LookaheadClassDef,
1229                                            rule) < 0)
1230                     continue;
1231                   orig_used = gstring->used;
1232                   for (k = 0; k < rule->LookupCount; k++)
1233                     lookup_gpos (lookup_list,
1234                                  rule->LookupRecord[k].LookupListIndex,
1235                                  gstring,
1236                                  gidx + rule->LookupRecord[k].SequenceIndex,
1237                                  accumulate);
1238                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1239                   break;
1240                 }
1241             }
1242           else if (subtable->Format == 3)
1243             {
1244               OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1245               int orig_used;
1246               int j;
1247
1248               if (gidx < context3->BacktrackGlyphCount
1249                   || (gidx + context3->InputGlyphCount
1250                       + context3->LookaheadGlyphCount) > gstring->used)
1251                 continue;
1252               if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1253                 continue;
1254               orig_used = gstring->used;
1255               for (j = 0; j < context3->LookupCount; j++)
1256                 lookup_gpos (lookup_list,
1257                              context3->LookupRecord[j].LookupListIndex,
1258                              gstring,
1259                              gidx + context3->LookupRecord[j].SequenceIndex,
1260                              accumulate);
1261               gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1262             }
1263           else
1264             OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1265           break;
1266
1267         default:
1268           continue;
1269         }
1270     }
1271   if (gidx == orig_gidx)
1272     {
1273       if (debug_flag)
1274         fprintf (stderr, " no match\n");
1275       gidx++;
1276     }
1277   else if (debug_flag)
1278     fprintf (stderr, " match %d glyphs\n", gidx - orig_gidx);
1279   return gidx;
1280 }
1281
1282 static unsigned
1283 lookup_encoding_0 (int c, OTF_EncodingSubtable *sub)
1284 {
1285   return ((c < 0 || c >= 256)
1286           ? 0
1287           : sub->f.f0->glyphIdArray[c]);
1288 }
1289
1290 static unsigned
1291 lookup_encoding_2 (int c, OTF_EncodingSubtable *sub)
1292 {
1293   return 0;
1294 }
1295
1296 static unsigned
1297 lookup_encoding_4 (int c, OTF_EncodingSubtable *sub)
1298 {
1299   int segCount, i;
1300   OTF_EncodingSubtable4 *sub4;
1301
1302   if (c < 0)
1303     return 0;
1304   sub4 = sub->f.f4;
1305   segCount = sub4->segCountX2 / 2;
1306   for (i = 0; i < segCount; i++)
1307     {
1308       OTF_cmapSegment *seg = sub4->segments + i;
1309
1310       if (c >= seg->startCount && c <= seg->endCount)
1311         {
1312           if (seg->idRangeOffset == 0xFFFF)
1313             return c + seg->idDelta;
1314           else
1315             return sub4->glyphIdArray[seg->idRangeOffset
1316                                       + (c - seg->startCount)];
1317         }
1318     }
1319   return 0;
1320 }
1321
1322 static unsigned
1323 lookup_encoding_6 (int c, OTF_EncodingSubtable *sub)
1324 {
1325   return 0;
1326 }
1327
1328 static unsigned
1329 lookup_encoding_8 (int c, OTF_EncodingSubtable *sub)
1330 {
1331   return 0;
1332 }
1333
1334 static unsigned
1335 lookup_encoding_10 (int c, OTF_EncodingSubtable *sub)
1336 {
1337   return 0;
1338 }
1339
1340 static unsigned
1341 lookup_encoding_12 (int c, OTF_EncodingSubtable *sub)
1342 {
1343   OTF_EncodingSubtable12 *sub12;
1344   OTF_cmapGroup *g, *gend;
1345
1346   if (c < 0)
1347     return 0;
1348   sub12 = sub->f.f12;
1349   g = sub12->Groups;
1350   gend = sub12->Groups + sub12->nGroups;
1351   while (g < gend)
1352     {
1353       if (g->startCharCode <= c && c <= g->endCharCode)
1354         return (g->startGlyphID + (c - g->startCharCode));
1355       g++;
1356     }
1357   return 0;
1358 }
1359
1360 typedef unsigned (*lookup_cmap_func) (int, OTF_EncodingSubtable *);
1361
1362 static lookup_cmap_func lookup_cmap_func_table[] =
1363   {
1364     lookup_encoding_0, lookup_encoding_2, lookup_encoding_4, lookup_encoding_6,
1365     lookup_encoding_8, lookup_encoding_10, lookup_encoding_12
1366   };
1367
1368 static unsigned
1369 get_GlyphID (OTF_cmap *cmap, int c)
1370 {
1371   OTF_EncodingSubtable *sub;
1372   lookup_cmap_func lookupper;
1373
1374   if (c < 0x10000 && cmap->unicode_table)
1375     return cmap->unicode_table[c];
1376   if (cmap->table_index < 0)
1377     return 0;
1378   sub = &cmap->EncodingRecord[cmap->table_index].subtable;
1379   lookupper = lookup_cmap_func_table[sub->format / 2];
1380   return lookupper (c, sub);
1381 }
1382
1383 static OTF_GlyphID
1384 get_uvs_glyph (OTF_cmap *cmap, OTF_EncodingSubtable14 *sub14, int c1, int c2)
1385 {
1386   unsigned nRecords = sub14->nRecords;
1387   OTF_VariationSelectorRecord *record;
1388   unsigned i;
1389
1390   for (i = 0; i < nRecords; i++)
1391     {
1392       record = &sub14->Records[i];
1393       if (record->varSelector == c2)
1394         {
1395           if (record->defaultUVSOffset)
1396             {
1397               OTF_UnicodeValueRange *uVRs = record->unicodeValueRanges;
1398               unsigned numUVRs = record->numUnicodeValueRanges;
1399               unsigned top = numUVRs, bottom = 0, middle;
1400
1401               if (uVRs[0].startUnicodeValue <= c1)
1402                 {
1403                   unsigned additionalCount, startUnicodeValue;
1404
1405                   for (;;)
1406                     {
1407                       middle = (top + bottom) / 2;
1408                       if (c1 < uVRs[middle].startUnicodeValue)
1409                         top = middle;
1410                       else if (bottom == middle)
1411                         break;
1412                       else
1413                         bottom = middle;
1414                     }
1415                   startUnicodeValue = uVRs[bottom].startUnicodeValue;
1416                   additionalCount = uVRs[bottom].additionalCount;
1417                   if (c1 <= startUnicodeValue + additionalCount)
1418                     return get_GlyphID (cmap, c1);
1419                 }
1420             }
1421           if (record->nonDefaultUVSOffset)
1422             {
1423               OTF_UVSMapping *uvsMappings = record->uvsMappings;
1424               unsigned numUVSMs = record->numUVSMappings;
1425               unsigned top = numUVSMs, bottom = 0, middle;
1426
1427               if (uvsMappings[0].unicodeValue <= c1)
1428                 {
1429                   for (;;)
1430                     {
1431                       middle = (top + bottom) / 2;
1432                       if (c1 < uvsMappings[middle].unicodeValue)
1433                         top = middle;
1434                       else if (bottom == middle)
1435                         break;
1436                       else
1437                         bottom = middle;
1438                     }
1439                   if (uvsMappings[bottom].unicodeValue == c1)
1440                     return uvsMappings[bottom].glyphID;
1441                 }
1442             }
1443           return 0;
1444         }
1445     }
1446   return 0;
1447 }
1448
1449 static void
1450 check_cmap_uvs (OTF_cmap *cmap, OTF_GlyphString *gstring, int idx)
1451 {  
1452   OTF_EncodingSubtable14 *sub14;
1453   int c1 = gstring->glyphs[idx - 1].c;
1454   int c2 = gstring->glyphs[idx].c;
1455   OTF_GlyphID code;
1456   int i;
1457
1458   gstring->glyphs[idx].glyph_id = 0;
1459   for (i = 0; i < cmap->numTables; i++)
1460     if (cmap->EncodingRecord[i].subtable.format == 14)
1461       break;
1462   if (i == cmap->numTables)
1463     return;
1464   code = get_uvs_glyph (cmap, cmap->EncodingRecord[i].subtable.f.f14, c1, c2);
1465   if (code == 0)
1466     return;
1467   gstring->glyphs[idx - 1].glyph_id = code;
1468   gstring->glyphs[idx - 1].f.index.to = gstring->glyphs[idx].f.index.to;
1469   gstring->used--;
1470   memmove (gstring->glyphs + idx, gstring->glyphs + idx + 1,
1471            sizeof (OTF_Glyph) * (gstring->used - idx));
1472 }
1473
1474 \f
1475
1476 /* GDEF */
1477 /* Table of GlyphClass and MarkAttackClass.
1478
1479    For the Nth element CHAR, CHAR and the succeeding characters
1480    (before CHAR of the next element) has GlyphClass C (= (N % 2) ? 3 : 1).
1481
1482    This table is generated from the General Category (GC) property of
1483    characters defined in the Unicode Character Database.  */
1484
1485 static int glyph_class_table[] =
1486   { 0x00000, 0x00300, 0x00370, 0x00483, 0x00487, 0x00488, 0x0048A, 0x00591,
1487     0x005BE, 0x005BF, 0x005C0, 0x005C1, 0x005C3, 0x005C4, 0x005C6, 0x005C7,
1488     0x005C8, 0x00610, 0x00616, 0x0064B, 0x0065F, 0x00670, 0x00671, 0x006D6,
1489     0x006DD, 0x006DE, 0x006E5, 0x006E7, 0x006E9, 0x006EA, 0x006EE, 0x00711,
1490     0x00712, 0x00730, 0x0074B, 0x007A6, 0x007B1, 0x007EB, 0x007F4, 0x00901,
1491     0x00904, 0x0093C, 0x0093D, 0x0093E, 0x0094E, 0x00951, 0x00955, 0x00962,
1492     0x00964, 0x00981, 0x00984, 0x009BC, 0x009BD, 0x009BE, 0x009C5, 0x009C7,
1493     0x009CE, 0x009D7, 0x009D8, 0x009E2, 0x009E4, 0x00A01, 0x00A04, 0x00A3C,
1494     0x00A3D, 0x00A3E, 0x00A4E, 0x00A70, 0x00A72, 0x00A81, 0x00A84, 0x00ABC,
1495     0x00ABD, 0x00ABE, 0x00ACE, 0x00AE2, 0x00AE4, 0x00B01, 0x00B04, 0x00B3C,
1496     0x00B3D, 0x00B3E, 0x00B44, 0x00B47, 0x00B58, 0x00B82, 0x00B83, 0x00BBE,
1497     0x00BCE, 0x00BD7, 0x00BD8, 0x00C01, 0x00C04, 0x00C3E, 0x00C45, 0x00C46,
1498     0x00C57, 0x00C82, 0x00C84, 0x00CBC, 0x00CBD, 0x00CBE, 0x00CC5, 0x00CC6,
1499     0x00CCE, 0x00CD5, 0x00CD7, 0x00CE2, 0x00CE4, 0x00D02, 0x00D04, 0x00D3E,
1500     0x00D44, 0x00D46, 0x00D4E, 0x00D57, 0x00D58, 0x00D82, 0x00D84, 0x00DCA,
1501     0x00DCB, 0x00DCF, 0x00DD7, 0x00DD8, 0x00DF4, 0x00E31, 0x00E32, 0x00E34,
1502     0x00E3B, 0x00E47, 0x00E4F, 0x00EB1, 0x00EB2, 0x00EB4, 0x00EBD, 0x00EC8,
1503     0x00ECE, 0x00F18, 0x00F1A, 0x00F35, 0x00F36, 0x00F37, 0x00F38, 0x00F39,
1504     0x00F3A, 0x00F3E, 0x00F40, 0x00F71, 0x00F85, 0x00F86, 0x00F88, 0x00F90,
1505     0x00FBD, 0x00FC6, 0x00FC7, 0x0102C, 0x0103A, 0x01056, 0x0105A, 0x0135F,
1506     0x01360, 0x01712, 0x01715, 0x01732, 0x01735, 0x01752, 0x01754, 0x01772,
1507     0x01774, 0x017B6, 0x017D4, 0x017DD, 0x017DE, 0x0180B, 0x0180E, 0x018A9,
1508     0x018AA, 0x01920, 0x0193C, 0x019B0, 0x019C1, 0x019C8, 0x019CA, 0x01A17,
1509     0x01A1C, 0x01B00, 0x01B05, 0x01B34, 0x01B45, 0x01B6B, 0x01B74, 0x01DC0,
1510     0x01E00, 0x020D0, 0x020F0, 0x0302A, 0x03030, 0x03099, 0x0309B, 0x0A802,
1511     0x0A803, 0x0A806, 0x0A807, 0x0A80B, 0x0A80C, 0x0A823, 0x0A828, 0x0FB1E,
1512     0x0FB1F, 0x0FE00, 0x0FE10, 0x0FE20, 0x0FE24, 0x10A01, 0x10A10, 0x10A38,
1513     0x10A40, 0x1D165, 0x1D16A, 0x1D16D, 0x1D173, 0x1D17B, 0x1D183, 0x1D185,
1514     0x1D18C, 0x1D1AA, 0x1D1AE, 0x1D242, 0x1D245, 0xE0100, 0xE01F0 };
1515
1516 int get_class_def_auto (int c)
1517 {
1518   static int table_size
1519     = sizeof glyph_class_table / sizeof glyph_class_table[0];
1520   int low, high, mid;
1521
1522   if (c >= glyph_class_table[table_size - 1])
1523     return 0;
1524   low = 0;
1525   high = table_size - 1;
1526   while (1)
1527     {
1528       mid = (low + high) / 2;
1529       if (c < glyph_class_table[mid])
1530         high = mid - 1;
1531       else if (c >= glyph_class_table[mid + 1])
1532         low = mid + 1;
1533       else
1534         break;
1535     }
1536   return ((mid % 2) ? 3 : 1);
1537 }
1538
1539 \f
1540
1541 /* API */
1542
1543 #define UVS_P(C)        \
1544   (((C) >= 0xFE00 && (C) <= 0xFE0F) || ((C) >= 0xE0100 && (C) <= 0xE01EF))
1545
1546 int
1547 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1548 {
1549   OTF_cmap *cmap;
1550   int i;
1551   OTF_EncodingSubtable *sub;
1552   lookup_cmap_func lookupper;
1553
1554   if (! otf->cmap
1555       && OTF_get_table (otf, "cmap") < 0)
1556     return -1;
1557
1558   cmap = otf->cmap;
1559   if (cmap->table_index < 0)
1560     lookupper = NULL;
1561   else
1562     {
1563       sub = &cmap->EncodingRecord[cmap->table_index].subtable;
1564       lookupper = lookup_cmap_func_table[sub->format / 2];
1565     }
1566   for (i = 0; i < gstring->used; i++)
1567     if (! gstring->glyphs[i].glyph_id)
1568       {
1569         int c = gstring->glyphs[i].c;
1570         if (c < 32 || ! cmap->unicode_table)
1571           gstring->glyphs[i].glyph_id = 0;
1572         else if (UVS_P (c) && i > 0)
1573           check_cmap_uvs (cmap, gstring, i);
1574         else if (c < 0x10000)
1575           gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1576         else if (lookupper)
1577           gstring->glyphs[i].glyph_id = lookupper (c, sub);
1578       }
1579   return 0;
1580 }
1581
1582
1583 int
1584 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1585                  int platform_id, int encoding_id)
1586 {
1587   OTF_cmap *cmap;
1588   int i;
1589   char *errfmt = "CMAP Looking up%s";
1590   int errret = -1;
1591   OTF_EncodingRecord *enc;
1592   lookup_cmap_func lookupper;
1593
1594   if (! otf->cmap
1595       && OTF_get_table (otf, "cmap") < 0)
1596     return -1;
1597
1598   cmap = otf->cmap;
1599   for (i = 0; i < cmap->numTables; i++)
1600     if (cmap->EncodingRecord[i].platformID == platform_id
1601         && cmap->EncodingRecord[i].encodingID == encoding_id)
1602       break;
1603   if (i == cmap->numTables)
1604     OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1605   enc = cmap->EncodingRecord + i;
1606   if (enc->subtable.format > 12)
1607     OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1608   lookupper = lookup_cmap_func_table[enc->subtable.format / 2];
1609
1610   for (i = 0; i < gstring->used; i++)
1611     if (! gstring->glyphs[i].glyph_id)
1612       {
1613         int c = gstring->glyphs[i].c;
1614         if (c < 32 || ! cmap->unicode_table)
1615           gstring->glyphs[i].glyph_id = 0;
1616         else if (UVS_P (c) && i > 0)
1617           check_cmap_uvs (cmap, gstring, i);
1618         else if (c < 0x10000)
1619           gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1620         else
1621           gstring->glyphs[i].glyph_id = lookupper (c, &enc->subtable);
1622       }
1623 }
1624
1625
1626 int
1627 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1628 {
1629   if (! otf->cmap
1630       && OTF_get_table (otf, "cmap") < 0)
1631     return 0;
1632   if (code == 0
1633       || code > otf->cmap->max_glyph_id
1634       || ! otf->cmap->decode_table)
1635     return 0;
1636   return otf->cmap->decode_table[code];
1637 }
1638
1639 int
1640 OTF_get_variation_glyphs (OTF *otf, int c, OTF_GlyphID code[256])
1641 {
1642   int i, n;
1643   OTF_cmap *cmap;
1644   OTF_EncodingSubtable14 *sub14;
1645
1646   memset (code, 0, sizeof (OTF_GlyphID) * 256);
1647   if (! otf->cmap
1648       && OTF_get_table (otf, "cmap") < 0)
1649     return 0;
1650   cmap = otf->cmap;
1651   for (i = 0; i < cmap->numTables; i++)
1652     if (cmap->EncodingRecord[i].subtable.format == 14)
1653       break;
1654   if (i == cmap->numTables)
1655     return 0;
1656   sub14 = cmap->EncodingRecord[i].subtable.f.f14;
1657   for (i = 0, n = 0; i < 256; i++)
1658     {
1659       int uvs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
1660
1661       if ((code[i] = get_uvs_glyph (cmap, sub14, c, uvs)))
1662         n++;
1663     }
1664   return n;
1665 }
1666
1667
1668 int
1669 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1670 {
1671   OTF_GDEF *gdef;
1672   int i;
1673
1674   if (! otf->gdef
1675       && OTF_get_table (otf, "GDEF") < 0)
1676     return -1;
1677   gdef = otf->gdef;
1678
1679   if (gdef->glyph_class_def.offset)
1680     for (i = 0; i < gstring->used; i++)
1681       gstring->glyphs[i].GlyphClass
1682         = get_class_def (&gdef->glyph_class_def,
1683                          gstring->glyphs[i].glyph_id);
1684   else
1685     for (i = 0; i < gstring->used; i++)
1686       gstring->glyphs[i].GlyphClass
1687         = get_class_def_auto (gstring->glyphs[i].c);
1688
1689   if (gdef->mark_attach_class_def.offset)
1690     for (i = 0; i < gstring->used; i++)
1691       gstring->glyphs[i].MarkAttachClass
1692         = get_class_def (&gdef->mark_attach_class_def,
1693                          gstring->glyphs[i].glyph_id);
1694
1695   return 0;
1696 }
1697
1698 static int
1699 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1700                          const char *script, const char *language,
1701                          const char *features,
1702                          int alternate_subst)
1703 {
1704   char *errfmt = "GSUB driving%s";
1705   int errret = -1;
1706   OTF_GSUB *gsub;
1707   OTF_LangSys *LangSys;
1708   char *lookup_flags;
1709   int i;
1710
1711   for (i = 0; i < gstring->used; i++)
1712     {
1713       gstring->glyphs[i].positioning_type = 0;
1714       gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1715     }
1716
1717   if (OTF_get_table (otf, "GSUB") < 0)
1718     return errret;
1719   gsub = otf->gsub;
1720   if (gsub->FeatureList.FeatureCount == 0
1721       || gsub->LookupList.LookupCount == 0)
1722     return 0;
1723
1724   LangSys = get_langsys (&gsub->ScriptList, script, language);
1725   if (! LangSys)
1726     return errret;
1727
1728   lookup_flags = alloca (gsub->LookupList.LookupCount);
1729   if (! lookup_flags
1730       || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, LangSys,
1731                              features, lookup_flags) < 0)
1732     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1733
1734   for (i = 0; i < gsub->LookupList.LookupCount; i++)
1735     {
1736       int gidx;
1737
1738       if (! lookup_flags[i]) continue;
1739
1740       if (gsub->LookupList.Lookup[i].LookupType != 8)
1741         {
1742           gidx = 0;
1743           while (gidx < gstring->used)
1744             {
1745               gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1746                                   alternate_subst);
1747               if (gidx < 0)
1748                 return errret;
1749             }
1750         }
1751       else
1752         {
1753           gidx = gstring->used - 1;
1754           while (gidx >= 0)
1755             {
1756               gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1757                                   alternate_subst);
1758               if (gidx < 0)
1759                 return errret;
1760             }
1761         }
1762     }
1763
1764   return 0;
1765 }
1766
1767 int
1768 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1769                 const char *script, const char *language, const char *features)
1770 {
1771   if (! otf->cmap)
1772     OTF_get_table (otf, "cmap");
1773   return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1774 }
1775
1776 int
1777 OTF_drive_gpos_internal (OTF *otf, OTF_GlyphString *gstring,
1778                          const char *script, const char *language,
1779                          const char *features,
1780                          int accumulate)
1781 {
1782   char *errfmt = "GPOS driving%s";
1783   int errret = -1;
1784   OTF_GPOS *gpos;
1785   OTF_LangSys *LangSys;
1786   char *lookup_flags;
1787   int i, n;
1788
1789   for (i = 0; i < gstring->used; i++)
1790     gstring->glyphs[i].positioning_type = 0;
1791
1792   if (OTF_get_table (otf, "GPOS") < 0)
1793     return errret;
1794   gpos = otf->gpos;
1795   if (gpos->FeatureList.FeatureCount == 0
1796       || gpos->LookupList.LookupCount == 0)
1797     return 0;
1798
1799   LangSys = get_langsys (&gpos->ScriptList, script, language);
1800   if (! LangSys)
1801     return errret;
1802
1803   lookup_flags = alloca (gpos->LookupList.LookupCount);
1804   if (! lookup_flags
1805       || setup_lookup_flags (&gpos->LookupList, &gpos->FeatureList, LangSys,
1806                              features, lookup_flags) < 0)
1807     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1808
1809   for (i = 0; i < gpos->LookupList.LookupCount; i++)
1810     {
1811       int gidx = 0;
1812
1813       if (! lookup_flags[i]) continue;
1814
1815       while (gidx < gstring->used)
1816         {
1817           gidx = lookup_gpos (&gpos->LookupList, i, gstring, gidx, accumulate);
1818           if (gidx < 0)
1819             return errret;
1820         }
1821     }
1822
1823   return 0;
1824 }
1825
1826 int
1827 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1828                 const char *script, const char *language, const char *features)
1829 {
1830   if (! otf->cmap)
1831     OTF_get_table (otf, "cmap");
1832   return OTF_drive_gpos_internal (otf, gstring, script, language, features, 0);
1833 }
1834
1835 int
1836 OTF_drive_gpos2 (OTF *otf, OTF_GlyphString *gstring,
1837                 const char *script, const char *language, const char *features)
1838 {
1839   if (! otf->cmap)
1840     OTF_get_table (otf, "cmap");
1841   return OTF_drive_gpos_internal (otf, gstring, script, language, features, 1);
1842 }
1843
1844 int
1845 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1846                   const char *script, const char *language,
1847                   const char *gsub_features, const char *gpos_features)
1848 {
1849   if (OTF_drive_cmap (otf, gstring) < 0)
1850     return -1;
1851   if (OTF_drive_gdef (otf, gstring) < 0)
1852     return -1;
1853   if (gsub_features
1854       && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1855     return -1;
1856   if (gpos_features
1857       && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1858     return -1;
1859   return 0;
1860 }
1861
1862 int
1863 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1864                           const char *script, const char *language,
1865                           const char *features)
1866 {
1867   return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);
1868 }
1869
1870 static int
1871 iterate_coverage (OTF *otf, const char *feature, 
1872                   OTF_Feature_Callback callback,
1873                   OTF_Coverage *coverage)
1874 {
1875   int i;
1876
1877   if (coverage->CoverageFormat == 1)
1878     {
1879       for (i = 0; i < coverage->Count; i++)
1880         if (callback (otf, feature, coverage->table.GlyphArray[i]) < 0)
1881           return -1;
1882     }
1883   else
1884     {
1885       for (i = 0; i < coverage->Count; i++)
1886         {
1887           OTF_RangeRecord *range = coverage->table.RangeRecord + i;
1888           unsigned id;
1889           for (id = range->Start; id <= range->End; id++)
1890             if (callback (otf, feature, id) < 0)
1891               return -1;
1892         }
1893     }
1894   return 0;
1895 }
1896
1897 static int
1898 iterate_feature (OTF *otf, const char *feature,
1899                  OTF_Feature_Callback callback,
1900                  OTF_Lookup *lookup)
1901 {
1902   int i, j, k, l;
1903
1904   for (i = 0; i < lookup->SubTableCount; i++)
1905     {
1906       unsigned lookup_type = lookup->LookupType;
1907       OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
1908
1909       if (lookup_type == 7)
1910         {
1911           OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
1912
1913           lookup_type = extension1->ExtensionLookupType;
1914           subtable = extension1->ExtensionSubtable;
1915         }
1916
1917       if ((lookup_type >= 1 && lookup_type <= 3) || lookup_type == 8)
1918         {
1919           if (iterate_coverage (otf, feature, callback, &subtable->Coverage)
1920               < 0)
1921             return -1;
1922         }
1923       else if (lookup_type == 4)
1924         {
1925           OTF_GSUB_Ligature1 *lig1;
1926
1927           if (iterate_coverage (otf, feature, callback, &subtable->Coverage)
1928               < 0)
1929             return -1;
1930           lig1 = &subtable->u.ligature1;
1931           for (j = 0; j < lig1->LigSetCount; j++)
1932             {
1933               OTF_LigatureSet *ligset = lig1->LigatureSet + j;
1934
1935               for (k = 0; k < ligset->LigatureCount; k++)
1936                 {
1937                   OTF_Ligature *lig = ligset->Ligature + k;
1938                   for (l = 0; l < lig->CompCount - 1; l++)
1939                     if (callback (otf, feature, lig->Component[l]) < 0)
1940                       return -1;
1941                 }
1942             }
1943         }
1944       else if (lookup_type == 6)
1945         {
1946           if (subtable->Format == 1)
1947             {
1948               OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
1949               for (j = 0; j < context1->ChainRuleSetCount; j++)
1950                 {
1951                   OTF_ChainRuleSet *set = context1->ChainRuleSet + j;
1952                   for (k = 0; k < set->ChainRuleCount; k++)
1953                     {
1954                       OTF_ChainRule *rule = set->ChainRule + k;
1955                       for (l = 0; l < rule->LookupCount; l++)
1956                         {
1957                           OTF_Lookup *lkup
1958                             = (otf->gsub->LookupList.Lookup
1959                                + rule->LookupRecord[l].LookupListIndex);
1960                           if (iterate_feature (otf, feature, callback, lkup)
1961                               < 0)
1962                             return -1;
1963                         }
1964                     }
1965                 }
1966             }
1967           else if (subtable->Format == 2)
1968             {
1969               OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
1970
1971               for (j = 0; j < context2->ChainClassSetCnt; j++)
1972                 {
1973                   OTF_ChainClassSet *set = context2->ChainClassSet + j;
1974                   for (k = 0; k < set->ChainClassRuleCnt; j++)
1975                     {
1976                       OTF_ChainClassRule *rule = set->ChainClassRule + k;
1977
1978                       for (l = 0; l < rule->LookupCount; l++)
1979                         {
1980                           OTF_Lookup *lkup
1981                             = (otf->gsub->LookupList.Lookup
1982                                + rule->LookupRecord[k].LookupListIndex);
1983                           if (iterate_feature (otf, feature, callback, lkup)
1984                               < 0)
1985                             return -1;
1986                         }
1987                     }
1988                 }
1989             }
1990           else
1991             {
1992               OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
1993               for (j = 0; j < context3->LookupCount; j++)
1994                 {
1995                   OTF_Lookup *lkup
1996                     = (otf->gsub->LookupList.Lookup
1997                        + context3->LookupRecord[j].LookupListIndex);
1998                   if (iterate_feature (otf, feature, callback, lkup) < 0)
1999                     return -1;
2000                 }
2001             }
2002         }
2003     }
2004   return 0;
2005 }
2006
2007 int
2008 OTF_iterate_gsub_feature (OTF *otf, OTF_Feature_Callback callback,
2009                           const char *script, const char *language,
2010                           const char *feature)
2011 {
2012   char *errfmt = "GSUB iterate feature%s";
2013   int errret = -1;
2014   int i;
2015
2016   OTF_GSUB *gsub;
2017   OTF_LangSys *langsys;
2018   char *lookup_flags;
2019
2020   if (OTF_get_table (otf, "GSUB") < 0)
2021     return errret;
2022   gsub = otf->gsub;
2023   if (gsub->FeatureList.FeatureCount == 0
2024       || gsub->LookupList.LookupCount == 0)
2025     return 0;
2026   langsys = get_langsys (&gsub->ScriptList, script, language);
2027   if (! langsys)
2028     return errret;
2029   lookup_flags = alloca (gsub->LookupList.LookupCount);
2030   if (! lookup_flags
2031       || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, langsys,
2032                              feature, lookup_flags) < 0)
2033     OTF_ERROR (OTF_ERROR_MEMORY, " feature");
2034
2035   for (i = 0; i < gsub->LookupList.LookupCount; i++)
2036     if (lookup_flags[i])
2037       if (iterate_feature (otf, feature, callback, gsub->LookupList.Lookup + i)
2038           < 0)
2039         return -1;
2040   return 0;
2041 }