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