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