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