(gstring_subst): Correctly set temp.f.index.
[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 /* Return nonzero if OTF_Glyph *G should be ignored according to
33    LookupFlag FLAG.  */
34 #define IGNORED_GLYPH(g, flag)                  \
35   ((g)->glyph_id == 0                           \
36    || ((flag) & (1 << (g)->GlyphClass))         \
37    || (((flag) & OTF_MarkAttachmentType)        \
38        && (g)->GlyphClass == OTF_GlyphClassMark \
39        && ((flag) >> 8) != (g)->MarkAttachClass))
40
41 #define GSTRING_DELETE(gstring, from, len)                              \
42   do {                                                                  \
43     memmove (gstring->glyphs + from, gstring->glyphs + from + len,      \
44              sizeof (OTF_Glyph) * (gstring->used - from - len));        \
45     gstring->used -= len;                                               \
46   } while (0)
47
48
49 #define GSTRING_INSERT(gstring, pos, len)                               \
50   do {                                                                  \
51     if (gstring->used + len > gstring->size)                            \
52       {                                                                 \
53         char *errfmt = "GSTRING%s";                                     \
54                                                                         \
55         gstring->size = gstring->used + len;                            \
56         gstring->glyphs                                                 \
57           = (OTF_Glyph *) realloc (gstring->glyphs,                     \
58                                    sizeof (OTF_Glyph) * gstring->size); \
59         if (! gstring->glyphs)                                          \
60           OTF_ERROR (OTF_ERROR_MEMORY, "");                             \
61       }                                                                 \
62     memmove (gstring->glyphs + pos + len, gstring->glyphs + pos,        \
63              sizeof (OTF_Glyph) * (gstring->used - pos));               \
64     gstring->used += len;                                               \
65   } while (0)
66
67
68 static int
69 gstring_subst (OTF *otf, OTF_GlyphString *gstring, int from, int to, int flag,
70                OTF_GlyphID *ids, int num)
71 {
72   int errret = -1;
73   int len = to - from;
74   int i;
75   int from_idx = gstring->glyphs[from].f.index.from;
76   int to_idx = gstring->glyphs[to - 1].f.index.to;
77   int non_ignored_idx;
78
79   for (i = non_ignored_idx = to - 1; i >= from; i--)
80     {
81       OTF_Glyph *g = gstring->glyphs + i;
82       if (IGNORED_GLYPH (g, flag))
83         {
84           OTF_Glyph temp = *g;
85
86           memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
87           temp.f.index.from = from_idx;
88           temp.f.index.to = to_idx;
89           gstring->glyphs[non_ignored_idx--] = temp;
90           len--;
91         }
92     }
93
94   if (len < num)
95     GSTRING_INSERT (gstring, from, (num - len));
96   else if (len > num)
97     GSTRING_DELETE (gstring, from, (len - num));
98   for (i = 0; i < num; i++)
99     {
100       gstring->glyphs[from + i].c = otf->cmap->decode_table[ids[i]];
101       gstring->glyphs[from + i].glyph_id = ids[i];
102       gstring->glyphs[from + i].f.index.from = from_idx;
103       gstring->glyphs[from + i].f.index.to = to_idx;
104     }
105   return 0;
106 }
107
108 \f
109 static int
110 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
111 {
112   int i;
113
114   if (coverage->CoverageFormat == 1)
115     {
116       for (i = 0; i < coverage->Count; i++)
117         if (coverage->table.GlyphArray[i] == id)
118           return i;
119     }
120   else
121     {
122       for (i = 0; i < coverage->Count; i++)
123         if (coverage->table.RangeRecord[i].Start <= id
124             && coverage->table.RangeRecord[i].End >= id)
125           return (coverage->table.RangeRecord[i].StartCoverageIndex
126                   + (id - coverage->table.RangeRecord[i].Start));
127     }
128   return -1;
129 }
130
131 static unsigned
132 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
133 {
134   if (class_def->ClassFormat == 1)
135     {
136       int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
137
138       if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
139         return class_def->f.f1.ClassValueArray[idx];
140     }
141   else
142     {
143       int i;
144
145       for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
146         if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
147             && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
148           return class_def->f.f2.ClassRangeRecord[i].Class;
149     }
150   return 0;
151 }
152
153 static OTF_LangSys *
154 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
155 {
156
157   OTF_Tag script_tag = OTF_tag (script);
158   OTF_Tag langsys_tag = OTF_tag (language);
159   int i, j;
160   OTF_Tag dflt_tag = OTF_tag ("DFLT");
161   OTF_Script *dflt = NULL;
162
163   for (i = 0; i < script_list->ScriptCount; i++)
164     {
165       OTF_Script *script = script_list->Script + i;
166
167       if (script_list->Script[i].ScriptTag == dflt_tag)
168         dflt = script;
169       if (script_list->Script[i].ScriptTag == script_tag)
170         {
171           if (! langsys_tag)
172             return &script->DefaultLangSys;
173           for (j = 0; j < script->LangSysCount; j++)
174             if (script->LangSysRecord[j].LangSysTag == langsys_tag)
175               return script->LangSys + j;
176           return &script->DefaultLangSys;       
177         }
178     }
179
180   if (! dflt)
181     dflt = script_list->Script;
182   if (! langsys_tag)
183     return &dflt->DefaultLangSys;
184   for (j = 0; j < dflt->LangSysCount; j++)
185     if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
186       return dflt->LangSys + j;
187   return &dflt->DefaultLangSys; 
188 }
189
190 static int
191 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
192                       char *features, int *lookup_indices)
193 {
194   int i, j, n = 0;
195   OTF_Feature *feature;
196   int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
197
198   for (i = 0; i < FeatureList->FeatureCount; i++)
199     feature_table[i] = 0;
200
201   while (*features)
202     {
203       char tagname[4];
204       OTF_Tag tag;
205       int use_it = 1;
206
207       if (*features == '*')
208         {
209           /* Consume all remaining features.  */
210           for (i = 0; i < FeatureList->FeatureCount; i++)
211             if (! feature_table[i])
212               {
213                 feature = FeatureList->Feature + i;
214                 for (j = 0; j < feature->LookupCount; j++)
215                   lookup_indices[n++] = feature->LookupListIndex[j];
216               }
217           break;
218         }
219
220       if (*features == '~')
221         use_it = -1, features++;
222       for (i = 0; *features && *features != ','; i++, features++)
223         tagname[i] = *features;
224       if (*features)
225         /* Skip ',' */
226         features++;
227       for (; i < 4; i++)
228         tagname[i] = '\0';
229       tag = OTF_tag (tagname);
230       for (i = 0; i < FeatureList->FeatureCount; i++)
231         {
232           feature = FeatureList->Feature + i;
233           if (tag == feature->FeatureTag)
234             {
235               if (feature_table[i])
236                 break;
237               if (use_it > 0)
238                 for (j = 0; j < feature->LookupCount; j++)
239                   lookup_indices[n++] = feature->LookupListIndex[j];
240               feature_table[i] = use_it;
241               break;
242             }
243         }
244     }
245
246   return n;
247 }
248
249 static int
250 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
251            int count, OTF_GlyphID *ids)
252 {
253   OTF_Glyph *gbeg = gstring->glyphs + gidx;
254   OTF_Glyph *gend = gstring->glyphs + gstring->used;
255   OTF_Glyph *g;
256   int i;
257
258   for (g = gbeg, i = 0; g < gend && i < count; g++)
259     if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
260       return -1;
261   return (i < count ? -1 : g - gbeg);
262 }
263
264 static int
265 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
266                  OTF_ChainRule *rule)
267 {
268   int i = rule->BacktrackGlyphCount;
269
270   if (i > 0)
271     {
272       int j;
273       OTF_Glyph *g;
274
275       for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
276         if (! IGNORED_GLYPH (g, flag) && --i == 0)
277           break;
278       if (i > 0)
279         return -1;
280       if (match_ids (gstring, j, flag,
281                      rule->BacktrackGlyphCount, rule->Backtrack)
282           < 0)
283         return -1;
284     }
285   gidx++;
286   i = match_ids (gstring, gidx, flag,
287                  rule->InputGlyphCount - 1, rule->Input);
288   if (i < 0)
289     return -1;
290   gidx += i;
291   i = match_ids (gstring, gidx, flag,
292                  rule->LookaheadGlyphCount, rule->LookAhead);
293   if (i < 0)
294     return -1;
295   return 0;
296 }
297
298 static int
299 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
300                int flag, int count, unsigned *classes)
301 {
302   OTF_Glyph *gbeg = gstring->glyphs + gidx;
303   OTF_Glyph *gend = gstring->glyphs + gstring->used;
304   OTF_Glyph *g;
305   int i;
306
307   for (g = gbeg, i = 0; g < gend && i < count; g++)
308     if (! IGNORED_GLYPH (g, flag)
309         && get_class_def (class_def, g->glyph_id) != classes[i++])
310       return -1;
311   return (i < count ? -1 : g - gbeg);
312 }
313
314 static int
315 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
316                      OTF_ClassDef *BacktrackClassDef,
317                      OTF_ClassDef *InputClassDef,
318                      OTF_ClassDef *LookaheadClassDef,
319                      OTF_ChainClassRule *rule)
320 {
321   int i = rule->BacktrackGlyphCount;
322
323   if (i > 0)
324     {
325       int j;
326       OTF_Glyph *g;
327
328       for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
329         if (! IGNORED_GLYPH (g, flag) && i-- == 0)
330           break;
331       if (i > 0)
332         return -1;
333       if (match_classes (BacktrackClassDef, gstring, j, flag,
334                          rule->BacktrackGlyphCount, rule->Backtrack) < 0);
335       return -1;
336     }
337   gidx++;
338   i = match_classes (InputClassDef, gstring, gidx, flag,
339                      rule->InputGlyphCount - 1, rule->Input);
340   if (i < 0)
341     return -1;
342   gidx += i;
343   i = match_classes (LookaheadClassDef, gstring, gidx, flag,
344                      rule->LookaheadGlyphCount, rule->LookAhead);
345   if (i < 0)
346     return -1;
347   return 0;
348 }
349
350
351 static int
352 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
353                  OTF_Coverage *coverages)
354 {
355   OTF_Glyph *gbeg = gstring->glyphs + gidx;
356   OTF_Glyph *gend = gstring->glyphs + gstring->used;
357   OTF_Glyph *g;
358   int i;
359
360   for (g = gbeg, i = 0; g < gend && i < count; g++)
361     if (! IGNORED_GLYPH (g, flag)
362         && get_coverage_index (coverages + i++, g->glyph_id) < 0)
363       return -1;
364   return (i < count ? -1 : g - gbeg);
365 }
366
367 static int
368 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
369                        OTF_GSUB_ChainContext3 *context3)
370 {
371   int i = context3->BacktrackGlyphCount;
372
373   if (i > 0)
374     {
375       int j;
376       OTF_Glyph *g;
377
378       for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
379         if (! IGNORED_GLYPH (g, flag) && --i == 0)
380           break;
381       if (i > 0)
382         return -1;
383       if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
384                            context3->Backtrack) < 0)
385         return -1;
386     }
387   gidx++;
388   if (context3->InputGlyphCount > 1)
389     {
390       i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
391                            context3->Input + 1);
392       if (i < 0)
393         return -1;
394       gidx += i;
395     }
396   if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
397                        context3->LookAhead) < 0)
398     return -1;
399   return 0;
400 }
401
402 static int
403 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
404              OTF_GlyphString *gstring, int gidx, int alternate_subst)
405 {
406   char *errfmt = "GSUB Looking up%s";
407   int errret = -1;
408   OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
409   unsigned int flag = (lookup->LookupFlag
410                        & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
411   int orig_gidx = gidx;
412   OTF_Glyph *g = gstring->glyphs + gidx;
413   int i;
414
415   if (IGNORED_GLYPH (g, flag))
416     return (gidx + 1);
417
418   /* Try all subtables until one of them handles the current glyph.  */
419   for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
420     {
421       unsigned lookup_type = lookup->LookupType;
422       OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
423       int coverage_idx;
424
425       if (lookup_type == 7)
426         {
427           OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
428
429           lookup_type = extension1->ExtensionLookupType;
430           subtable = extension1->ExtensionSubtable;
431         }
432
433       if (alternate_subst
434           ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
435           : (lookup_type == 3))
436         continue;
437
438       if (subtable->Coverage.offset)
439         {
440           coverage_idx = get_coverage_index (&subtable->Coverage,
441                                              g->glyph_id);
442           if (coverage_idx < 0)
443             continue;
444         }
445
446       switch (lookup_type)
447         {
448         case 1:
449           if (subtable->Format == 1)
450             g->glyph_id += subtable->u.single1.DeltaGlyphID;
451           else
452             g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
453           gidx++;
454           break;
455
456         case 2:
457           if (subtable->Format == 1)
458             {
459               OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
460               OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
461
462               gstring_subst (otf, gstring, gidx, gidx + 1, flag,
463                              seq->Substitute, seq->GlyphCount);
464               gidx += seq->GlyphCount;
465             }
466           else
467             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
468           break;
469
470         case 3:
471           if (subtable->Format == 1)
472             {
473               OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
474               OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
475
476               gstring_subst (otf, gstring, gidx + 1, gidx + 1, flag,
477                              altset->Alternate, altset->GlyphCount);
478               gidx += altset->GlyphCount;;
479             }
480           else
481             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
482           break;
483
484         case 4:
485           if (subtable->Format == 1)
486             {
487               OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
488               OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
489               OTF_Ligature *lig;
490               int j;
491
492               for (j = 0; j < ligset->LigatureCount; j++)
493                 {
494                   int n;
495
496                   lig = ligset->Ligature + j;
497                   n = match_ids (gstring, gidx + 1, flag,
498                                  lig->CompCount - 1, lig->Component);
499                   if (n < 0)
500                     continue;
501                   gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
502                                  &lig->LigGlyph, 1);
503                   gidx += lig->CompCount;
504                   break;
505                 }
506             }
507           else
508             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
509           break;
510
511         case 5:
512           if (subtable->Format == 1)
513             {
514               OTF_GSUB_Context1 *context1 = &subtable->u.context1;
515               OTF_RuleSet *set = context1->RuleSet + coverage_idx;
516               OTF_Rule *rule;
517               int orig_used;
518               int j, k;
519
520               for (j = 0; j < set->RuleCount; j++)
521                 {
522                   rule = set->Rule + j;
523                   if (match_ids (gstring, gidx + 1, flag,
524                                  rule->GlyphCount - 1, rule->Input) < 0)
525                     continue;
526                   orig_used = gstring->used;
527                   for (k = 0; k < rule->LookupCount; k++)
528                     lookup_gsub (otf, lookup_list,
529                                  rule->LookupRecord[k].LookupListIndex,
530                                  gstring,
531                                  gidx + rule->LookupRecord[k].SequenceIndex,
532                                  alternate_subst);
533                   gidx += rule->GlyphCount + (gstring->used - orig_used);
534                   break;
535                 }
536             }
537           else if (subtable->Format == 2)
538             {
539               OTF_GSUB_Context2 *context2 = &subtable->u.context2;
540               OTF_ClassSet *set;
541               OTF_ClassRule *rule;
542               unsigned class;
543               int orig_used;
544               int j, k;
545
546               class = get_class_def (&context2->ClassDef, g->glyph_id);
547               set = context2->ClassSet + class;
548               if (set)
549                 for (j = 0; j < set->ClassRuleCnt; j++)
550                   {
551                     rule = set->ClassRule + j;
552                     if (match_classes (&context2->ClassDef,
553                                        gstring, gidx + 1, flag,
554                                        rule->GlyphCount - 1, rule->Class)
555                         < 0)
556                       continue;
557                     orig_used = gstring->used;
558                     for (k = 0; k < rule->LookupCount; k++)
559                       lookup_gsub (otf, lookup_list,
560                                    rule->LookupRecord[k].LookupListIndex,
561                                    gstring,
562                                    gidx + rule->LookupRecord[k].SequenceIndex,
563                                    alternate_subst);
564                     gidx += rule->GlyphCount + (gstring->used - orig_used);
565                     break;
566                   }
567             }
568           else                  /* subtable->Format == 3 */
569             {
570               OTF_GSUB_Context3 *context3 = &subtable->u.context3;
571               int orig_used;
572               int j;
573
574               if (match_coverages (gstring, gidx + 1, flag,
575                                    context3->GlyphCount - 1,
576                                    context3->Coverage + 1) < 0)
577                 continue;
578               orig_used = gstring->used;
579               for (j = 0; j < context3->LookupCount; j++)
580                 lookup_gsub (otf, lookup_list,
581                              context3->LookupRecord[j].LookupListIndex,
582                              gstring,
583                              gidx + context3->LookupRecord[j].SequenceIndex,
584                              alternate_subst);
585               gidx += context3->GlyphCount + (gstring->used - orig_used);
586             }
587           break;
588
589         case 6:
590           if (subtable->Format == 1)
591             {
592               OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
593               OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
594               int orig_used;
595               int j, k;
596               
597               for (j = 0; j < set->ChainRuleCount; j++)
598                 {
599                   OTF_ChainRule *rule = set->ChainRule + j;
600
601                   if (gidx < rule->BacktrackGlyphCount
602                       || (gidx + rule->InputGlyphCount
603                           + rule->LookaheadGlyphCount) > gstring->used)
604                     continue;
605                   if (match_chain_ids (gstring, gidx, flag, rule) < 0)
606                     continue;
607                   orig_used = gstring->used;
608                   for (k = 0; k < rule->LookupCount; k++)
609                     lookup_gsub (otf, lookup_list,
610                                  rule->LookupRecord[k].LookupListIndex,
611                                  gstring,
612                                  gidx + rule->LookupRecord[k].SequenceIndex,
613                                  alternate_subst);
614                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
615                   break;
616                 }
617             }
618           else if (subtable->Format == 2)
619             {
620               OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
621               OTF_ChainClassSet *set;
622               unsigned class;
623               int j;
624               int orig_used;
625
626               class = get_class_def (&context2->InputClassDef, g->glyph_id);
627               set = context2->ChainClassSet + class;
628               for (j = 0; j < set->ChainClassRuleCnt; j++)
629                 {
630                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
631                   int k;
632
633                   if (gidx < rule->BacktrackGlyphCount
634                       || (gidx + rule->InputGlyphCount
635                           + rule->LookaheadGlyphCount) > gstring->used)
636                     continue;
637                   if (match_chain_classes (gstring, gidx, flag,
638                                            &context2->BacktrackClassDef,
639                                            &context2->InputClassDef,
640                                            &context2->LookaheadClassDef,
641                                            rule) < 0)
642                     continue;
643                   orig_used = gstring->used;
644                   for (k = 0; k < rule->LookupCount; k++)
645                     lookup_gsub (otf, lookup_list,
646                                  rule->LookupRecord[k].LookupListIndex,
647                                  gstring,
648                                  gidx + rule->LookupRecord[k].SequenceIndex,
649                                  alternate_subst);
650                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
651                   break;
652                 }
653             }
654           else
655             {
656               OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
657               int orig_used;
658               int j;
659
660               if (gidx < context3->BacktrackGlyphCount
661                   || (gidx + context3->InputGlyphCount
662                       + context3->LookaheadGlyphCount) > gstring->used)
663                 continue;
664               if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
665                 continue;
666               orig_used = gstring->used;
667               for (j = 0; j < context3->LookupCount; j++)
668                 lookup_gsub (otf, lookup_list,
669                              context3->LookupRecord[j].LookupListIndex,
670                              gstring,
671                              gidx + context3->LookupRecord[j].SequenceIndex,
672                              alternate_subst);
673               gidx += context3->InputGlyphCount + (gstring->used - orig_used);
674             }
675           break;
676
677         case 8:
678           {
679             OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
680             int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
681             int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
682             int j;
683
684             if (back_gidx > gstring->used || ahead_gidx < 0)
685               break;
686
687             for (j = 0; j < reverse->BacktrackGlyphCount; j++)
688               if (get_coverage_index (reverse->Backtrack + j,
689                                       gstring->glyphs[gidx + 1 + j].glyph_id)
690                   < 0)
691                 break;
692             if (j < reverse->BacktrackGlyphCount)
693               continue;
694             for (j = 0; j < reverse->LookaheadGlyphCount; j++)
695               if (get_coverage_index (reverse->LookAhead + j,
696                                       gstring->glyphs[gidx - 1 - j].glyph_id)
697                   < 0)
698                 break;
699             if (j < reverse->LookaheadGlyphCount)
700               continue;
701             g->glyph_id = reverse->Substitute[coverage_idx];
702             gidx--;
703           }
704
705         default:
706           continue;
707         }
708     }
709   if (gidx == orig_gidx)
710     gidx++;
711   return gidx;
712 }
713
714 \f
715
716 /* GPOS */
717 unsigned
718 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
719 {
720   unsigned value_format = OTF_XPlacement | OTF_YPlacement;
721
722   rec->XPlacement = anchor->XCoordinate;
723   rec->YPlacement = anchor->YCoordinate;
724   if (anchor->AnchorFormat == 1)
725     /* Nothing to do */
726     ;
727   else if (anchor->AnchorFormat == 2)
728     /* Not yet implemented */
729     ;
730   else if (anchor->AnchorFormat == 3)
731     /* Not yet implemented */
732     ;
733   return value_format;
734 }
735
736
737 static int
738 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
739              OTF_GlyphString *gstring, int gidx)
740 {
741   char *errfmt = "GPOS Looking up%s";
742   int errret = -1;
743   OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
744   unsigned int flag = (lookup->LookupFlag
745                        & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
746   int orig_gidx = gidx;
747   OTF_Glyph *g = gstring->glyphs + gidx;
748   int i;
749
750   if (IGNORED_GLYPH (g, flag)
751       || g->positioning_type)
752     return (gidx + 1);
753
754   /* Try all subtables until one of them handles the current glyph.  */
755   for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
756     {
757       unsigned lookup_type = lookup->LookupType;
758       OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
759       int coverage_idx;
760
761       if (lookup_type == 9)
762         {
763           OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
764
765           lookup_type = extension1->ExtensionLookupType;
766           subtable = extension1->ExtensionSubtable;
767         }
768
769       if (subtable->Coverage.offset)
770         {
771           coverage_idx = get_coverage_index (&subtable->Coverage,
772                                              g->glyph_id);
773           if (coverage_idx < 0)
774             continue;
775         }
776
777       switch (lookup_type)
778         {
779         case 1:
780           g->positioning_type = lookup_type;
781           if (subtable->Format == 1)
782             {
783               OTF_GPOS_Single1 *single1 = &subtable->u.single1;
784
785               g->f.f1.format = single1->ValueFormat;
786               g->f.f1.value = &single1->Value;
787             }
788           else if (subtable->Format == 2)
789             {
790               OTF_GPOS_Single2 *single2 = &subtable->u.single2;
791
792               g->f.f1.format = single2->ValueFormat;
793               g->f.f1.value = single2->Value + coverage_idx;
794             }
795           break;
796
797         case 2:
798           {
799             int next_gidx;
800             OTF_Glyph *nextg;
801
802             for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
803                  next_gidx < gstring->used && ! IGNORED_GLYPH (nextg, flag);
804                  next_gidx++, nextg++);
805
806             if (next_gidx >= gstring->used
807                 || nextg->positioning_type)
808               continue;
809             if (subtable->Format == 1)
810               {
811                 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
812                 OTF_PairSet *set = pair1->PairSet + coverage_idx;
813                 int j;
814
815                 for (j = 0; j < set->PairValueCount; j++)
816                   if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
817                     {
818                       if (pair1->ValueFormat1)
819                         {
820                           g->positioning_type = lookup_type;
821                           g->f.f2.format = pair1->ValueFormat1;
822                           g->f.f2.value = &set->PairValueRecord[j].Value1;
823                         }
824                       gidx = next_gidx;
825                       if (pair1->ValueFormat2)
826                         {
827                           nextg->positioning_type = lookup_type;
828                           nextg->f.f2.format = pair1->ValueFormat2;
829                           nextg->f.f2.value = &set->PairValueRecord[j].Value2;
830                           gidx++;
831                         }
832                       break;
833                     }
834               }
835             else if (subtable->Format == 2)
836               {
837                 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
838                 unsigned class1, class2;
839
840                 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
841                 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
842                 if (pair2->ValueFormat1)
843                   {
844                     g->positioning_type = lookup_type;
845                     g->f.f2.format = pair2->ValueFormat1;
846                     g->f.f2.value
847                       = &pair2->Class1Record[class1].Class2Record[class2].Value1;
848                   }
849                 gidx = next_gidx;
850                 if (pair2->ValueFormat2)
851                   {
852                     nextg->positioning_type = lookup_type;
853                     nextg->f.f2.format = pair2->ValueFormat2;
854                     nextg->f.f2.value
855                       = &pair2->Class1Record[class1].Class2Record[class2].Value2;
856                     gidx++;
857                   }
858               }
859           }
860           break;
861
862         case 3:
863           {
864             OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
865           
866             g->positioning_type = lookup_type;
867             g->f.f3.entry_anchor
868               = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
869             g->f.f3.exit_anchor
870               = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
871           }
872           break;
873
874         case 4:
875           if (gidx < 1)
876             continue;
877           if (subtable->Format == 1)
878             {
879               OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
880               OTF_MarkRecord *mark_record;
881               OTF_AnchorRecord *base_record;
882               OTF_Glyph *baseg;
883               int coverage_idx_base;
884
885               for (baseg = g - 1;
886                    baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, flag);
887                    baseg--);
888               if (baseg < gstring->glyphs)
889                 continue;
890               coverage_idx_base
891                 = get_coverage_index (&mark_base1->BaseCoverage,
892                                       baseg->glyph_id);
893               if (coverage_idx_base < 0)
894                 continue;
895               mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
896               base_record
897                 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
898               g->f.f4.mark_anchor = &mark_record->MarkAnchor;
899               g->f.f4.base_anchor
900                 = &base_record->Anchor[mark_record->Class];
901               g->positioning_type = lookup_type;
902             }
903           break;
904
905         case 5:
906           if (gidx < 1)
907             continue;
908           if (subtable->Format == 1)
909             {
910               OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
911               OTF_Glyph *ligg;
912               int coverage_idx_lig;
913               OTF_MarkRecord *mark_record;
914               OTF_LigatureAttach *attach;
915               int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
916               int j;
917                                        
918               for (j = 0; j < mark_lig1->ClassCount; j++)
919                 num_class[j] = 0;
920
921               for (ligg = g - 1;
922                    (ligg >= gstring->glyphs
923                     && (IGNORED_GLYPH (ligg, flag)
924                         || ligg->GlyphClass > OTF_GlyphClassLigature));
925                    ligg--)
926                 if (ligg->positioning_type == 5
927                     && ligg->MarkAttachClass < mark_lig1->ClassCount)
928                   num_class[ligg->MarkAttachClass]++;
929               if (ligg < gstring->glyphs)
930                 continue;
931               coverage_idx_lig
932                 = get_coverage_index (&mark_lig1->LigatureCoverage,
933                                       ligg->glyph_id);
934               if (coverage_idx_lig < 0)
935                 continue;
936               mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
937               g->MarkAttachClass = mark_record->Class;
938               attach = (mark_lig1->LigatureArray.LigatureAttach
939                         + coverage_idx_lig);
940               for (j = 0; j < attach->ComponentCount; j++)
941                 {
942                   OTF_Anchor *lig_anchor
943                     = attach->ComponentRecord[j].LigatureAnchor;
944
945                   if (lig_anchor[mark_record->Class].AnchorFormat
946                       && num_class[mark_record->Class]-- == 0)
947                     {
948                       g->positioning_type = lookup_type;
949                       g->f.f5.mark_anchor = &mark_record->MarkAnchor;
950                       g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
951                       break;
952                     }
953                 }
954             }
955           break;
956
957         case 6:
958           if (gidx < 1)
959             continue;
960           if (subtable->Format == 1)
961             {
962               OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
963               OTF_MarkRecord *mark1_record;
964               OTF_AnchorRecord *mark2_record;
965               OTF_Glyph *prevg;
966               int coverage_idx_base;
967
968               for (prevg = g - 1;
969                    prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
970                    prevg--);
971               if (prevg < gstring->glyphs)
972                 continue;
973               coverage_idx_base
974                 = get_coverage_index (&mark_mark1->Mark2Coverage,
975                                       prevg->glyph_id);
976               if (coverage_idx_base < 0)
977                 continue;
978               mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
979               mark2_record
980                 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
981               g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
982               g->f.f6.mark2_anchor
983                 = &mark2_record->Anchor[mark1_record->Class];
984               g->positioning_type = lookup_type;
985               break;
986             }
987           break;
988
989         case 7:
990           if (subtable->Format == 1)
991             {
992               OTF_GPOS_Context1 *context1 = &subtable->u.context1;
993               OTF_RuleSet *set = context1->RuleSet + coverage_idx;
994               OTF_Rule *rule;
995               int orig_used;
996               int j, k;
997
998               for (j = 0; j < set->RuleCount; j++)
999                 {
1000                   rule = set->Rule + j;
1001                   if (match_ids (gstring, gidx + 1, flag,
1002                                  rule->GlyphCount - 1, rule->Input) < 0)
1003                     continue;
1004                   orig_used = gstring->used;
1005                   for (k = 0; k < rule->LookupCount; k++)
1006                     lookup_gpos (lookup_list,
1007                                  rule->LookupRecord[k].LookupListIndex,
1008                                  gstring,
1009                                  gidx + rule->LookupRecord[k].SequenceIndex);
1010                   gidx += rule->GlyphCount + (gstring->used - orig_used);
1011                   break;
1012                 }
1013             }
1014           else if (subtable->Format == 2)
1015             {
1016               OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1017               OTF_ClassSet *set;
1018               OTF_ClassRule *rule;
1019               unsigned class;
1020               int orig_used;
1021               int j, k;
1022
1023               class = get_class_def (&context2->ClassDef, g->glyph_id);
1024               set = context2->ClassSet + class;
1025               if (set)
1026                 for (j = 0; j < set->ClassRuleCnt; j++)
1027                   {
1028                     rule = set->ClassRule + j;
1029                     if (match_classes (&context2->ClassDef,
1030                                        gstring, gidx + 1, flag,
1031                                        rule->GlyphCount - 1, rule->Class)
1032                         < 0)
1033                       continue;
1034                     orig_used = gstring->used;
1035                     for (k = 0; k < rule->LookupCount; k++)
1036                       lookup_gpos (lookup_list,
1037                                    rule->LookupRecord[k].LookupListIndex,
1038                                    gstring,
1039                                    gidx + rule->LookupRecord[k].SequenceIndex);
1040                     gidx += rule->GlyphCount + (gstring->used - orig_used);
1041                     break;
1042                   }
1043             }
1044           else                  /* subtable->Format == 3 */
1045             {
1046               OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1047               int orig_used;
1048               int j;
1049
1050               if (match_coverages (gstring, gidx + 1, flag,
1051                                    context3->GlyphCount - 1,
1052                                    context3->Coverage + 1) < 0)
1053                 continue;
1054               orig_used = gstring->used;
1055               for (j = 0; j < context3->LookupCount; j++)
1056                 lookup_gpos (lookup_list,
1057                              context3->LookupRecord[j].LookupListIndex,
1058                              gstring,
1059                              gidx + context3->LookupRecord[j].SequenceIndex);
1060               gidx += context3->GlyphCount + (gstring->used - orig_used);
1061             }
1062           break;
1063
1064         case 8:
1065           if (subtable->Format == 1)
1066             {
1067               OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1068               OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1069               int orig_used;
1070               int j, k;
1071               
1072               for (j = 0; j < set->ChainRuleCount; j++)
1073                 {
1074                   OTF_ChainRule *rule = set->ChainRule + j;
1075
1076                   if (gidx < rule->BacktrackGlyphCount
1077                       || (gidx + rule->InputGlyphCount
1078                           + rule->LookaheadGlyphCount) > gstring->used)
1079                     continue;
1080                   if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1081                     continue;
1082                   orig_used = gstring->used;
1083                   for (k = 0; k < rule->LookupCount; k++)
1084                     lookup_gpos (lookup_list,
1085                                  rule->LookupRecord[k].LookupListIndex,
1086                                  gstring,
1087                                  gidx + rule->LookupRecord[k].SequenceIndex);
1088                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1089                   break;
1090                 }
1091             }
1092           else if (subtable->Format == 2)
1093             {
1094               OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1095               OTF_ChainClassSet *set;
1096               unsigned class;
1097               int j;
1098               int orig_used;
1099
1100               class = get_class_def (&context2->InputClassDef, g->glyph_id);
1101               set = context2->ChainClassSet + class;
1102               for (j = 0; j < set->ChainClassRuleCnt; j++)
1103                 {
1104                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
1105                   int k;
1106
1107                   if (gidx < rule->BacktrackGlyphCount
1108                       || (gidx + rule->InputGlyphCount
1109                           + rule->LookaheadGlyphCount) > gstring->used)
1110                     continue;
1111                   if (match_chain_classes (gstring, gidx, flag,
1112                                            &context2->BacktrackClassDef,
1113                                            &context2->InputClassDef,
1114                                            &context2->LookaheadClassDef,
1115                                            rule) < 0)
1116                     continue;
1117                   orig_used = gstring->used;
1118                   for (k = 0; k < rule->LookupCount; k++)
1119                     lookup_gpos (lookup_list,
1120                                  rule->LookupRecord[k].LookupListIndex,
1121                                  gstring,
1122                                  gidx + rule->LookupRecord[k].SequenceIndex);
1123                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1124                   break;
1125                 }
1126             }
1127           else if (subtable->Format == 3)
1128             {
1129               OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1130               int orig_used;
1131               int j;
1132
1133               if (gidx < context3->BacktrackGlyphCount
1134                   || (gidx + context3->InputGlyphCount
1135                       + context3->LookaheadGlyphCount) > gstring->used)
1136                 continue;
1137               if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1138                 continue;
1139               orig_used = gstring->used;
1140               for (j = 0; j < context3->LookupCount; j++)
1141                 lookup_gpos (lookup_list,
1142                              context3->LookupRecord[j].LookupListIndex,
1143                              gstring,
1144                              gidx + context3->LookupRecord[j].SequenceIndex);
1145               gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1146             }
1147           else
1148             OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1149           break;
1150
1151         default:
1152           continue;
1153         }
1154     }
1155   if (gidx == orig_gidx)
1156     gidx++;
1157   return gidx;
1158 }
1159
1160 static int
1161 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1162 {
1163   int i, c;
1164
1165   for (i = 0; i < gstring->used; i++)
1166     {
1167       c = gstring->glyphs[i].c;
1168       if (c < 0 || c >= 256)
1169         gstring->glyphs[i].glyph_id = 0;
1170       else
1171         gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1172     }
1173   return 0;
1174 }
1175
1176 static int
1177 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1178 {
1179   return 0;
1180 }
1181
1182 static int
1183 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1184 {
1185   int i, j, c;
1186   int segCount = sub4->segCountX2 / 2;
1187
1188   for (i = 0; i < gstring->used; i++)
1189     {
1190       c = gstring->glyphs[i].c;
1191       if (c < 0)
1192         gstring->glyphs[i].glyph_id = 0;
1193       for (j = 0; j < segCount; j++)
1194         {
1195           OTF_cmapSegument *seg = sub4->segments + i;
1196
1197           if (c >= seg->startCount && c <= seg->endCount)
1198             {
1199               if (seg->idRangeOffset == 0xFFFF)
1200                 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1201               else
1202                 gstring->glyphs[i].glyph_id
1203                   = sub4->glyphIdArray[seg->idRangeOffset
1204                                        + (c - seg->startCount)];
1205               break;
1206             }
1207         }
1208     }
1209
1210   return 0;
1211 }
1212
1213 static int
1214 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1215 {
1216   return 0;
1217 }
1218
1219 static int
1220 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1221 {
1222   return 0;
1223 }
1224
1225 static int
1226 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1227 {
1228   return 0;
1229 }
1230
1231 static int
1232 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1233 {
1234   return 0;
1235 }
1236
1237 \f
1238
1239 /* API */
1240
1241 int
1242 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1243 {
1244   OTF_cmap *cmap;
1245   int i;
1246
1247   if (! otf->cmap
1248       && OTF_get_table (otf, "cmap") < 0)
1249     return -1;
1250
1251   cmap = otf->cmap;
1252   for (i = 0; i < gstring->used; i++)
1253     if (! gstring->glyphs[i].glyph_id)
1254       {
1255         int c = gstring->glyphs[i].c;
1256         if (c < 32 || ! cmap->unicode_table)
1257           gstring->glyphs[i].glyph_id = 0;
1258         else
1259           gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1260       }
1261   return 0;
1262 }
1263
1264
1265 int
1266 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1267                  int platform_id, int encoding_id)
1268 {
1269   OTF_cmap *cmap;
1270   int i;
1271   char *errfmt = "CMAP Looking up%s";
1272   int errret = -1;
1273   OTF_EncodingRecord *enc;
1274
1275   if (! otf->cmap
1276       && OTF_get_table (otf, "cmap") < 0)
1277     return -1;
1278
1279   cmap = otf->cmap;
1280   for (i = 0; i < cmap->numTables; i++)
1281     if (cmap->EncodingRecord[i].platformID == platform_id
1282         && cmap->EncodingRecord[i].encodingID == encoding_id)
1283       break;
1284   if (i == cmap->numTables)
1285     OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1286   enc = cmap->EncodingRecord + i;
1287   switch (enc->subtable.format)
1288     {
1289     case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1290     case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1291     case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1292     case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1293     case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1294     case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1295     case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1296     }
1297   OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1298 }
1299
1300
1301 int
1302 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1303 {
1304   if (! otf->cmap
1305       && OTF_get_table (otf, "cmap") < 0)
1306     return 0;
1307   if (code == 0
1308       || code > otf->cmap->max_glyph_id
1309       || ! otf->cmap->decode_table)
1310     return 0;
1311   return otf->cmap->decode_table[code];
1312 }
1313
1314 int
1315 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1316 {
1317   OTF_GDEF *gdef;
1318   int i;
1319
1320   if (! otf->gdef
1321       && OTF_get_table (otf, "GDEF") < 0)
1322     return -1;
1323   gdef = otf->gdef;
1324
1325   if (gdef->glyph_class_def.offset)
1326     for (i = 0; i < gstring->used; i++)
1327       gstring->glyphs[i].GlyphClass
1328         = get_class_def (&gdef->glyph_class_def,
1329                          gstring->glyphs[i].glyph_id);
1330
1331   if (gdef->mark_attach_class_def.offset)
1332     for (i = 0; i < gstring->used; i++)
1333       gstring->glyphs[i].MarkAttachClass
1334         = get_class_def (&gdef->mark_attach_class_def,
1335                          gstring->glyphs[i].glyph_id);
1336
1337   return 0;
1338 }
1339
1340 static int
1341 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1342                          char *script, char *language, char *features,
1343                          int alternate_subst)
1344 {
1345   char *errfmt = "GSUB driving%s";
1346   int errret = -1;
1347   OTF_GSUB *gsub;
1348   OTF_LangSys *LangSys;
1349   int *lookup_indices;
1350   int i, n;
1351
1352   for (i = 0; i < gstring->used; i++)
1353     gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1354
1355   if (! otf->gsub
1356       && OTF_get_table (otf, "GSUB") < 0)
1357     return errret;
1358   gsub = otf->gsub;
1359   if (gsub->FeatureList.FeatureCount == 0
1360       || gsub->LookupList.LookupCount == 0)
1361     return 0;
1362
1363   LangSys = get_langsys (&gsub->ScriptList, script, language);
1364   if (! LangSys)
1365     return errret;
1366
1367   /* One lookup may be used by multiple features.  */
1368   lookup_indices = alloca (sizeof (int)
1369                            * gsub->LookupList.LookupCount
1370                            * (gsub->FeatureList.FeatureCount + 1));
1371   if (! lookup_indices)
1372     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1373   n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1374                             features, lookup_indices);
1375   if (n < 0)
1376     return errret;
1377
1378   for (i = 0; i < n; i++)
1379     {
1380       int index = lookup_indices[i];
1381       int gidx;
1382
1383       if (gsub->LookupList.Lookup[index].LookupType != 8)
1384         {
1385           gidx = 0;
1386           while (gidx < gstring->used)
1387             {
1388               gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1389                                   alternate_subst);
1390               if (gidx < 0)
1391                 return errret;
1392             }
1393         }
1394       else
1395         {
1396           gidx = gstring->used - 1;
1397           while (gidx >= 0)
1398             {
1399               gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx,
1400                                   alternate_subst);
1401               if (gidx < 0)
1402                 return errret;
1403             }
1404         }
1405     }
1406
1407   return 0;
1408 }
1409
1410 int
1411 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1412                 char *script, char *language, char *features)
1413 {
1414   return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1415 }
1416
1417 int
1418 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1419                 char *script, char *language, char *features)
1420 {
1421   char *errfmt = "GPOS driving%s";
1422   int errret = -1;
1423   OTF_GPOS *gpos;
1424   OTF_LangSys *LangSys;
1425   int *lookup_indices;
1426   int i, n;
1427
1428   if (! otf->gpos
1429       && OTF_get_table (otf, "GPOS") < 0)
1430     return errret;
1431   gpos = otf->gpos;
1432   if (gpos->FeatureList.FeatureCount == 0
1433       || gpos->LookupList.LookupCount == 0)
1434     return 0;
1435
1436   LangSys = get_langsys (&gpos->ScriptList, script, language);
1437   if (! LangSys)
1438     return errret;
1439
1440   /* One lookup may be used by multiple features.  */
1441   lookup_indices = alloca (sizeof (int)
1442                            * gpos->LookupList.LookupCount
1443                            * (gpos->FeatureList.FeatureCount + 1));
1444   if (! lookup_indices)
1445     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1446   n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1447                             features, lookup_indices);
1448   if (n < 0)
1449     return errret;
1450
1451   for (i = 0; i < gstring->used; i++)
1452     gstring->glyphs[i].positioning_type = 0;
1453
1454   for (i = 0; i < n; i++)
1455     {
1456       int index = lookup_indices[i];
1457       int gidx = 0;
1458
1459       while (gidx < gstring->used)
1460         {
1461           gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1462           if (gidx < 0)
1463             return errret;
1464         }
1465     }
1466
1467   return 0;
1468 }
1469
1470 int
1471 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1472                   char *script, char *language,
1473                   char *gsub_features, char *gpos_features)
1474 {
1475   if (OTF_drive_cmap (otf, gstring) < 0)
1476     return -1;
1477   if (OTF_drive_gdef (otf, gstring) < 0)
1478     return -1;
1479   if (gsub_features
1480       && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1481     return -1;
1482   if (gpos_features
1483       && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1484     return -1;
1485   return 0;
1486 }
1487
1488 int
1489 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1490                           char *script, char *language, char *features)
1491 {
1492   return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);
1493 }