*** empty log message ***
[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 #define GSTRING_DELETE(gstring, from, len)                              \
33   do {                                                                  \
34     memmove (gstring->glyphs + from, gstring->glyphs + from + len,      \
35              sizeof (OTF_Glyph) * (gstring->used - from - len));        \
36     gstring->used -= len;                                               \
37   } while (0)
38
39
40 #define GSTRING_INSERT(gstring, pos, len)                               \
41   do {                                                                  \
42     if (gstring->used + len > gstring->size)                            \
43       {                                                                 \
44         char *errfmt = "GSTRING%s";                                     \
45                                                                         \
46         gstring->size = gstring->used + len;                            \
47         gstring->glyphs = (OTF_Glyph *) realloc (gstring->glyphs,       \
48                                                  gstring->size);        \
49         if (! gstring->glyphs)                                          \
50           OTF_ERROR (OTF_ERROR_MEMORY, "");                             \
51       }                                                                 \
52     memmove (gstring->glyphs + pos + len, gstring->glyphs + pos,        \
53              sizeof (OTF_Glyph) * (gstring->used - pos));               \
54     gstring->used += len;                                               \
55   } while (0)
56
57
58 static int
59 gstring_subst (OTF_GlyphString *gstring, int from, int to,
60                OTF_GlyphID *ids, int num)
61 {
62   int errret = -1;
63   int len = to - from;
64   int i;
65
66   if (len < num)
67     GSTRING_INSERT (gstring, from, (num - len));
68   else if (len > num)
69     GSTRING_DELETE (gstring, from, (len - num));
70   for (i = 0; i < num; i++)
71     gstring->glyphs[from + i].glyph_id = ids[i];
72   return 0;
73 }
74
75 \f
76 static int
77 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
78 {
79   int i;
80
81   if (coverage->CoverageFormat == 1)
82     {
83       for (i = 0; i < coverage->Count; i++)
84         if (coverage->table.GlyphArray[i] == id)
85           return i;
86     }
87   else
88     {
89       for (i = 0; i < coverage->Count; i++)
90         if (coverage->table.RangeRecord[i].Start <= id
91             && coverage->table.RangeRecord[i].End >= id)
92           return (coverage->table.RangeRecord[i].StartCoverageIndex
93                   + (id - coverage->table.RangeRecord[i].Start));
94     }
95   return -1;
96 }
97
98 static unsigned
99 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
100 {
101   if (class_def->ClassFormat == 1)
102     {
103       int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
104
105       if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
106         return class_def->f.f1.ClassValueArray[idx];
107     }
108   else
109     {
110       int i;
111
112       for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
113         if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
114             && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
115           return class_def->f.f2.ClassRangeRecord[i].Class;
116     }
117   return 0;
118 }
119
120 static OTF_LangSys *
121 get_langsys (OTF_ScriptList *script_list, char *script, char *language)
122 {
123
124   OTF_Tag script_tag = OTF_tag (script);
125   OTF_Tag langsys_tag = OTF_tag (language);
126   int i, j;
127
128   for (i = 0; i < script_list->ScriptCount; i++)
129     if (script_list->Script[i].ScriptTag == script_tag)
130       {
131         OTF_Script *script = script_list->Script + i;
132
133         if (! langsys_tag)
134           return &script->DefaultLangSys;
135         for (j = 0; j < script->LangSysCount; j++)
136           if (script->LangSysRecord[j].LangSysTag == langsys_tag)
137             return script->LangSys + j;
138         return &script->DefaultLangSys; 
139       }
140
141   return NULL;
142 }
143
144 static int
145 setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
146                       char *features, int *lookup_indices)
147 {
148   int i, j, n = 0;
149   OTF_Feature *feature;
150   int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
151
152   for (i = 0; i < FeatureList->FeatureCount; i++)
153     feature_table[i] = 0;
154
155   while (*features)
156     {
157       char tagname[4];
158       OTF_Tag tag;
159       int negate = 0;
160
161       if (*features == '*')
162         {
163           /* Consume all remaining features.  */
164           /* We are sure that the last LookupCount elements of
165              lookup_indices are free to be used for this work.  */
166           int *free_table = (lookup_indices + (LookupList->LookupCount
167                                                * FeatureList->FeatureCount));
168
169           for (i = 0; i < LookupList->LookupCount; i++)
170             free_table[i] = 0;
171           for (i = 0; i < FeatureList->FeatureCount; i++)
172             if (! feature_table[i])
173               {
174                 feature = FeatureList->Feature + i;
175                 for (j = 0; j < feature->LookupCount; j++)
176                   free_table[feature->LookupListIndex[j]] = 1;
177               }
178           for (i = 0; i < LookupList->LookupCount; i++)
179             if (free_table[i])
180               lookup_indices[n++] = i;
181           break;
182         }
183
184       if (*features == '~')
185         negate = 1, features++;
186       for (i = 0; *features && *features != ','; i++, features++)
187         tagname[i] = *features;
188       if (*features)
189         /* Skip ',' */
190         features++;
191       for (; i < 4; i++)
192         tagname[i] = '\0';
193       tag = OTF_tag (tagname);
194       for (i = 0; i < FeatureList->FeatureCount; i++)
195         {
196           feature = FeatureList->Feature + i;
197           if (tag == feature->FeatureTag)
198             {
199               if (! negate)
200                 for (j = 0; j < feature->LookupCount; j++)
201                   lookup_indices[n++] = feature->LookupListIndex[j];
202               feature_table[i] = 1;
203               break;
204             }
205         }
206     }
207
208   return n;
209 }
210
211 static int
212 match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids)
213 {
214   OTF_Glyph *gbeg = gstring->glyphs + gidx;
215   OTF_Glyph *gend = gstring->glyphs + gstring->used;
216   OTF_Glyph *g;
217   int i;
218
219   for (g = gbeg, i = 0; g < gend && i < count; g++)
220     if (g->glyph_id && g->glyph_id != ids[i++])
221       return -1;
222   return (i < count ? -1 : g - gbeg);
223 }
224
225 static int
226 match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule)
227 {
228   int i = rule->BacktrackGlyphCount;
229
230   if (i > 0)
231     {
232       int j;
233
234       for (j = gidx - 1; j >= 0; j--)
235         if (gstring->glyphs[j].glyph_id
236             && --i == 0)
237           break;
238       if (i > 0)
239         return -1;
240       if (match_ids (gstring, j, rule->BacktrackGlyphCount, rule->Backtrack)
241           < 0)
242         return -1;
243     }
244   gidx++;
245   i = match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input);
246   if (i < 0)
247     return -1;
248   gidx += i;
249   i = match_ids (gstring, gidx, rule->LookaheadGlyphCount, rule->LookAhead);
250   if (i < 0)
251     return -1;
252   return 0;
253 }
254
255 static int
256 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
257                int count, unsigned *classes)
258 {
259   OTF_Glyph *gbeg = gstring->glyphs + gidx;
260   OTF_Glyph *gend = gstring->glyphs + gstring->used;
261   OTF_Glyph *g;
262   int i;
263
264   for (g = gbeg, i = 0; g < gend && i < count; g++)
265     if (g->glyph_id
266         && get_class_def (class_def, g->glyph_id) != classes[i++])
267       return -1;
268   return (i < count ? -1 : g - gbeg);
269 }
270
271 static int
272 match_chain_classes (OTF_GlyphString *gstring, int gidx,
273                      OTF_ClassDef *BacktrackClassDef,
274                      OTF_ClassDef *InputClassDef,
275                      OTF_ClassDef *LookaheadClassDef,
276                      OTF_ChainClassRule *rule)
277 {
278   int i = rule->BacktrackGlyphCount;
279
280   if (i > 0)
281     {
282       int j;
283
284       for (j = gidx - 1; j >= 0 && i > 0; j--)
285         if (gstring->glyphs[j].glyph_id
286             && i-- == 0)
287           break;
288       if (i > 0)
289         return -1;
290       if (match_classes (BacktrackClassDef, gstring, j,
291                          rule->BacktrackGlyphCount, rule->Backtrack) < 0);
292       return -1;
293     }
294   gidx++;
295   i = match_classes (InputClassDef, gstring, gidx,
296                      rule->InputGlyphCount - 1, rule->Input);
297   if (i < 0)
298     return -1;
299   gidx += i;
300   i = match_classes (LookaheadClassDef, gstring, gidx,
301                      rule->LookaheadGlyphCount, rule->LookAhead);
302   if (i < 0)
303     return -1;
304   return 0;
305 }
306
307
308 static int
309 match_coverages (OTF_GlyphString *gstring, int gidx, int count,
310                  OTF_Coverage *coverages)
311 {
312   OTF_Glyph *gbeg = gstring->glyphs + gidx;
313   OTF_Glyph *gend = gstring->glyphs + gstring->used;
314   OTF_Glyph *g;
315   int i;
316
317   for (g = gbeg, i = 0; g < gend && i < count; g++)
318     if (g->glyph_id
319         && get_coverage_index (coverages + i++, g->glyph_id) < 0)
320       return -1;
321   return (i < count ? -1 : g - gbeg);
322 }
323
324 static int
325 match_chain_coverages (OTF_GlyphString *gstring, int gidx,
326                        OTF_GSUB_ChainContext3 *context3)
327 {
328   int i = context3->BacktrackGlyphCount;
329
330   if (i > 0)
331     {
332       int j;
333
334       for (j = gidx - 1; j >= 0; j--)
335         if (gstring->glyphs[j].glyph_id
336             && --i == 0)
337           break;
338       if (i > 0)
339         return -1;
340       if (match_coverages (gstring, j, context3->BacktrackGlyphCount,
341                            context3->Backtrack) < 0)
342         return -1;
343     }
344   gidx++;
345   if (context3->InputGlyphCount > 1)
346     {
347       i = match_coverages (gstring, gidx, context3->InputGlyphCount - 1,
348                            context3->Input + 1);
349       if (i < 0)
350         return -1;
351       gidx += i;
352     }
353   if (match_coverages (gstring, gidx, context3->LookaheadGlyphCount,
354                        context3->LookAhead) < 0)
355     return -1;
356   return 0;
357 }
358
359 static int
360 lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index,
361              OTF_GlyphString *gstring, int gidx)
362 {
363   char *errfmt = "GSUB Looking up%s";
364   int errret = -1;
365   OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
366   unsigned int flag = lookup->LookupFlag;
367   int orig_gidx = gidx;
368   OTF_Glyph *g = gstring->glyphs + gidx;
369   int i;
370
371   if (! g->glyph_id
372       || (g->GlyphClass
373           && (flag & (1 << g->GlyphClass))))
374     return (gidx + 1);
375
376   /* Try all subtables until one of them handles the current glyph.  */
377   for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
378     {
379       unsigned lookup_type = lookup->LookupType;
380       OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
381       int coverage_idx;
382
383       if (lookup_type == 7)
384         {
385           OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
386
387           lookup_type = extension1->ExtensionLookupType;
388           subtable = extension1->ExtensionSubtable;
389         }
390
391       if (subtable->Coverage.offset)
392         {
393           coverage_idx = get_coverage_index (&subtable->Coverage,
394                                              g->glyph_id);
395           if (coverage_idx < 0)
396             continue;
397         }
398
399       switch (lookup->LookupType)
400         {
401         case 1:
402           if (subtable->Format == 1)
403             g->glyph_id += subtable->u.single1.DeltaGlyphID;
404           else
405             g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
406           gidx++;
407           break;
408
409         case 2:
410           {
411             OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
412             OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
413
414             gstring_subst (gstring, gidx, gidx + 1,
415                            seq->Substitute, seq->GlyphCount);
416             gidx += seq->GlyphCount;
417           }
418           break;
419
420         case 3:
421           if (subtable->Format == 1)
422             {
423               OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
424               OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
425
426               g->glyph_id = altset->Alternate[0];
427               gidx++;
428             }
429           else
430             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
431           break;
432
433         case 4:
434           if (subtable->Format == 1)
435             {
436               OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
437               OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
438               OTF_Ligature *lig;
439               int j;
440
441               for (j = 0; j < ligset->LigatureCount; j++)
442                 {
443                   int n;
444
445                   lig = ligset->Ligature + j;
446                   n = match_ids (gstring, gidx + 1,
447                                  lig->CompCount - 1, lig->Component);
448                   if (n < 0)
449                     continue;
450                   gstring_subst (gstring, gidx, gidx + 1 + n,
451                                  &lig->LigGlyph, 1);
452                   gidx++;
453                   break;
454                 }
455             }
456           else
457             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
458           break;
459
460         case 5:
461           if (subtable->Format == 1)
462             {
463               OTF_GSUB_Context1 *context1 = &subtable->u.context1;
464               OTF_RuleSet *set = context1->RuleSet + coverage_idx;
465               OTF_Rule *rule;
466               int orig_used;
467               int j, k;
468
469               for (j = 0; j < set->RuleCount; j++)
470                 {
471                   rule = set->Rule + j;
472                   if (match_ids (gstring, gidx + 1,
473                                  rule->GlyphCount - 1, rule->Input) < 0)
474                     continue;
475                   orig_used = gstring->used;
476                   for (k = 0; k < rule->LookupCount; k++)
477                     lookup_gsub (lookup_list,
478                                  rule->LookupRecord[k].LookupListIndex,
479                                  gstring,
480                                  gidx + rule->LookupRecord[k].SequenceIndex);
481                   gidx += rule->GlyphCount + (gstring->used - orig_used);
482                   break;
483                 }
484             }
485           else if (subtable->Format == 2)
486             {
487               OTF_GSUB_Context2 *context2 = &subtable->u.context2;
488               OTF_ClassSet *set;
489               OTF_ClassRule *rule;
490               unsigned class;
491               int orig_used;
492               int j, k;
493
494               class = get_class_def (&context2->ClassDef, g->glyph_id);
495               set = context2->ClassSet + class;
496               for (j = 0; j < set->ClassRuleCnt; j++)
497                 {
498                   rule = set->ClassRule + j;
499                   if (match_classes (&context2->ClassDef,
500                                      gstring, gidx + 1,
501                                      rule->GlyphCount - 1, rule->Class)
502                       < 0)
503                     continue;
504                   orig_used = gstring->used;
505                   for (k = 0; k < rule->LookupCount; k++)
506                     lookup_gsub (lookup_list,
507                                  rule->LookupRecord[k].LookupListIndex,
508                                  gstring,
509                                  gidx + rule->LookupRecord[k].SequenceIndex);
510                   gidx += rule->GlyphCount + (gstring->used - orig_used);
511                   break;
512                 }
513             }
514           else                  /* subtable->Format == 3 */
515             {
516               OTF_GSUB_Context3 *context3 = &subtable->u.context3;
517               int orig_used;
518               int j;
519
520               if (match_coverages (gstring, gidx + 1, context3->GlyphCount - 1,
521                                    context3->Coverage + 1) < 0)
522                 continue;
523               orig_used = gstring->used;
524               for (j = 0; j < context3->LookupCount; j++)
525                 lookup_gsub (lookup_list,
526                              context3->LookupRecord[j].LookupListIndex,
527                              gstring,
528                              gidx + context3->LookupRecord[j].SequenceIndex);
529               gidx += context3->GlyphCount + (gstring->used - orig_used);
530             }
531           break;
532
533         case 6:
534           if (subtable->Format == 1)
535             {
536               OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
537               OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
538               int orig_used;
539               int j, k;
540               
541               for (j = 0; j < set->ChainRuleCount; j++)
542                 {
543                   OTF_ChainRule *rule = set->ChainRule + j;
544
545                   if (gidx < rule->BacktrackGlyphCount
546                       || (gidx + rule->InputGlyphCount
547                           + rule->LookaheadGlyphCount) > gstring->used)
548                     continue;
549                   if (match_chain_ids (gstring, gidx, rule) < 0)
550                     continue;
551                   orig_used = gstring->used;
552                   for (k = 0; k < rule->LookupCount; k++)
553                     lookup_gsub (lookup_list,
554                                  rule->LookupRecord[k].LookupListIndex,
555                                  gstring,
556                                  gidx + rule->LookupRecord[k].SequenceIndex);
557                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
558                   break;
559                 }
560             }
561           else if (subtable->Format == 2)
562             {
563               OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
564               OTF_ChainClassSet *set;
565               unsigned class;
566               int j;
567               int orig_used;
568
569               class = get_class_def (&context2->InputClassDef, g->glyph_id);
570               set = context2->ChainClassSet + class;
571               for (j = 0; j < set->ChainClassRuleCnt; j++)
572                 {
573                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
574                   int k;
575
576                   if (gidx < rule->BacktrackGlyphCount
577                       || (gidx + rule->InputGlyphCount
578                           + rule->LookaheadGlyphCount) > gstring->used)
579                     continue;
580                   if (match_chain_classes (gstring, gidx,
581                                            &context2->BacktrackClassDef,
582                                            &context2->InputClassDef,
583                                            &context2->LookaheadClassDef,
584                                            rule) < 0)
585                     continue;
586                   orig_used = gstring->used;
587                   for (k = 0; k < rule->LookupCount; k++)
588                     lookup_gsub (lookup_list,
589                                  rule->LookupRecord[k].LookupListIndex,
590                                  gstring,
591                                  gidx + rule->LookupRecord[k].SequenceIndex);
592                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
593                   break;
594                 }
595             }
596           else
597             {
598               OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
599               int orig_used;
600               int j;
601
602               if (gidx < context3->BacktrackGlyphCount
603                   || (gidx + context3->InputGlyphCount
604                       + context3->LookaheadGlyphCount) > gstring->used)
605                 return -1;
606               if (match_chain_coverages (gstring, gidx, context3) < 0)
607                 continue;
608               orig_used = gstring->used;
609               for (j = 0; j < context3->LookupCount; j++)
610                 lookup_gsub (lookup_list,
611                              context3->LookupRecord[j].LookupListIndex,
612                              gstring,
613                              gidx + context3->LookupRecord[j].SequenceIndex);
614               gidx += context3->InputGlyphCount + (gstring->used - orig_used);
615             }
616           break;
617
618         case 8:
619           {
620             OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
621             int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
622             int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
623             int j;
624
625             if (back_gidx > gstring->used || ahead_gidx < 0)
626               break;
627
628             for (j = 0; j < reverse->BacktrackGlyphCount; j++)
629               if (get_coverage_index (reverse->Backtrack + j,
630                                       gstring->glyphs[gidx + 1 + j].glyph_id)
631                   < 0)
632                 break;
633             if (j < reverse->BacktrackGlyphCount)
634               continue;
635             for (j = 0; j < reverse->LookaheadGlyphCount; j++)
636               if (get_coverage_index (reverse->LookAhead + j,
637                                       gstring->glyphs[gidx - 1 - j].glyph_id)
638                   < 0)
639                 break;
640             if (j < reverse->LookaheadGlyphCount)
641               continue;
642             g->glyph_id = reverse->Substitute[coverage_idx];
643             gidx--;
644           }
645
646         default:
647           continue;
648         }
649     }
650   if (gidx == orig_gidx)
651     gidx++;
652   return gidx;
653 }
654
655 \f
656
657 /* GPOS */
658 unsigned
659 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
660 {
661   unsigned value_format = OTF_XPlacement | OTF_YPlacement;
662
663   rec->XPlacement = anchor->XCoordinate;
664   rec->YPlacement = anchor->YCoordinate;
665   if (anchor->AnchorFormat == 1)
666     /* Nothing to do */
667     ;
668   else if (anchor->AnchorFormat == 2)
669     /* Not yet implemented */
670     ;
671   else if (anchor->AnchorFormat == 3)
672     /* Not yet implemented */
673     ;
674   return value_format;
675 }
676
677
678 static int
679 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
680              OTF_GlyphString *gstring, int gidx)
681 {
682   char *errfmt = "GPOS Looking up%s";
683   int errret = -1;
684   OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
685   unsigned int flag = lookup->LookupFlag;
686   int orig_gidx = gidx;
687   OTF_Glyph *g = gstring->glyphs + gidx;
688   int i;
689
690   if (! g->glyph_id
691       || (g->GlyphClass
692           && (flag & (1 << g->GlyphClass))))
693     return (gidx + 1);
694
695   /* Try all subtables until one of them handles the current glyph.  */
696   for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
697     {
698       OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
699       int coverage_idx;
700
701       if (subtable->Coverage.offset)
702         {
703           coverage_idx = get_coverage_index (&subtable->Coverage,
704                                              g->glyph_id);
705           if (coverage_idx < 0)
706             continue;
707         }
708
709       switch (lookup->LookupType)
710         {
711         case 1:
712           g->positioning_type = lookup->LookupType;
713           if (subtable->Format == 1)
714             {
715               OTF_GPOS_Single1 *single1 = &subtable->u.single1;
716
717               g->f.f1.format = single1->ValueFormat;
718               g->f.f1.value = &single1->Value;
719             }
720           else if (subtable->Format == 2)
721             {
722               OTF_GPOS_Single2 *single2 = &subtable->u.single2;
723
724               g->f.f1.format = single2->ValueFormat;
725               g->f.f1.value = single2->Value + coverage_idx;
726             }
727           break;
728
729         case 2:
730           if (gidx + 1 >= gstring->used)
731             continue;
732           if (subtable->Format == 1)
733             {
734               OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
735               OTF_PairSet *set = pair1->PairSet + coverage_idx;
736               int j;
737
738               for (j = 0; j < set->PairValueCount; j++)
739                 {
740                   if (set->PairValueRecord[j].SecondGlyph != g[1].glyph_id)
741                     continue;
742                   gidx++;
743                   g->positioning_type = lookup->LookupType;
744                   g->f.f2.format = pair1->ValueFormat1;
745                   g->f.f2.value = &set->PairValueRecord[j].Value1;
746                   if (pair1->ValueFormat2)
747                     {
748                       g++, gidx++;
749                       g->positioning_type = lookup->LookupType;
750                       g->f.f2.format = pair1->ValueFormat2;
751                       g->f.f2.value = &set->PairValueRecord[j].Value2;
752                     }
753                 }
754             }
755           else if (subtable->Format == 2)
756             {
757               OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
758               unsigned class1, class2;
759
760               gidx++;
761               class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
762               class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
763               g->positioning_type = lookup->LookupType;
764               g->f.f2.format = pair2->ValueFormat1;
765               g->f.f2.value
766                 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
767               if (pair2->ValueFormat2)
768                 {
769                   g++, gidx++;
770                   g->positioning_type = lookup->LookupType;
771                   g->f.f2.format = pair2->ValueFormat2;
772                   g->f.f2.value
773                     = &pair2->Class1Record[class1].Class2Record[class2].Value2;
774                 }
775             }
776           break;
777
778         case 3:
779           {
780             OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
781           
782             g->positioning_type = lookup->LookupType;
783             g->f.f3.entry_anchor
784               = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
785             g->f.f3.exit_anchor
786               = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
787           }
788           break;
789
790         case 4:
791           if (gidx < 1)
792             continue;
793           if (subtable->Format == 1)
794             {
795               OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
796               OTF_MarkRecord *mark_record;
797               OTF_AnchorRecord *base_record;
798               int coverage_idx_base
799                 = get_coverage_index (&mark_base1->BaseCoverage,
800                                       g[-1].glyph_id);
801
802               if (coverage_idx_base < 0)
803                 continue;
804               mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
805               base_record
806                 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
807               g->f.f4.mark_anchor = &mark_record->MarkAnchor;
808               g->f.f4.base_anchor
809                 = &base_record->Anchor[mark_record->Class];
810               g->positioning_type = lookup->LookupType;
811               break;
812             }
813           break;
814
815         case 5:
816           if (gidx < 1)
817             continue;
818           if (subtable->Format == 1)
819             {
820               /* As the document of this lookup type is quite
821                  ambiguous, and we can't know the exact procedure to
822                  handle it?!?  */
823               OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
824             }
825           break;
826
827         case 6:
828           if (gidx < 1)
829             continue;
830           if (subtable->Format == 1)
831             {
832               OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
833               OTF_MarkRecord *mark1_record;
834               OTF_AnchorRecord *mark2_record;
835               int coverage_idx_base
836                 = get_coverage_index (&mark_mark1->Mark2Coverage,
837                                       g[-1].glyph_id);
838
839               if (coverage_idx_base < 0)
840                 continue;
841               mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
842               mark2_record
843                 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
844               g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
845               g->f.f6.mark2_anchor
846                 = &mark2_record->Anchor[mark1_record->Class];
847               g->positioning_type = lookup->LookupType;
848               break;
849             }
850           break;
851
852         case 7:
853           OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
854           break;
855
856         case 8:
857           if (subtable->Format == 1)
858             OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
859           else if (subtable->Format == 2)
860             {
861               OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
862               OTF_ChainClassSet *set;
863               unsigned class;
864               int j;
865               int orig_used;
866
867               class = get_class_def (&context2->InputClassDef, g->glyph_id);
868               set = context2->ChainClassSet + class;
869               for (j = 0; j < set->ChainClassRuleCnt; j++)
870                 {
871                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
872                   int fore_idx = gidx + rule->InputGlyphCount;
873                   int k;
874
875                   if (gidx < rule->BacktrackGlyphCount
876                       || (gidx + rule->InputGlyphCount
877                           + rule->LookaheadGlyphCount) > gstring->used)
878                     continue;
879                   for (k = 0; k < rule->BacktrackGlyphCount; k++)
880                     if (get_class_def (&context2->BacktrackClassDef,
881                                        gstring->glyphs[gidx - 1 - k].glyph_id)
882                         != rule->Backtrack[k])
883                       break;
884                   if (k < rule->BacktrackGlyphCount)
885                     continue;
886                   for (k = 1; k < rule->InputGlyphCount; k++)
887                     if (get_class_def (&context2->InputClassDef,
888                                        gstring->glyphs[gidx + k].glyph_id)
889                         != rule->Input[k - 1])
890                       break;
891                   if (k < rule->InputGlyphCount)
892                     continue;
893                   for (k = 0; k < rule->LookaheadGlyphCount; k++)
894                     if (get_class_def (&context2->LookaheadClassDef,
895                                        gstring->glyphs[fore_idx + k].glyph_id)
896                         != rule->LookAhead[k])
897                       break;
898                   if (k < rule->LookaheadGlyphCount)
899                     continue;
900
901                   orig_used = gstring->used;
902                   for (k = 0; k < rule->LookupCount; k++)
903                     lookup_gpos (lookup_list,
904                                  rule->LookupRecord[k].LookupListIndex,
905                                  gstring,
906                                  gidx + rule->LookupRecord[k].SequenceIndex);
907                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
908                   break;
909                 }
910             }
911           else if (subtable->Format == 3)
912             OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
913           else
914             OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
915           break;
916
917         case 9:
918           OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
919           break;
920
921         default:
922           continue;
923         }
924     }
925   if (gidx == orig_gidx)
926     gidx++;
927   return gidx;
928 }
929
930 \f
931
932 /* API */
933
934 int
935 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
936 {
937   OTF_cmap *cmap;
938   int i;
939
940   if (! otf->cmap
941       && OTF_get_table (otf, "cmap") < 0)
942     return -1;
943
944   cmap = otf->cmap;
945   for (i = 0; i < gstring->used; i++)
946     if (! gstring->glyphs[i].glyph_id)
947       {
948         int c = gstring->glyphs[i].c;
949         if (c < 32 || ! cmap->unicode_table)
950           gstring->glyphs[i].glyph_id = 0;
951         else
952           gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
953       }
954   return 0;
955 }
956
957 int
958 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
959 {
960   if (! otf->cmap
961       && OTF_get_table (otf, "cmap") < 0)
962     return 0;
963   if (code == 0
964       || code > otf->cmap->max_glyph_id
965       || ! otf->cmap->decode_table)
966     return 0;
967   return otf->cmap->decode_table[code];
968 }
969
970 int
971 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
972 {
973   OTF_GDEF *gdef;
974   int i;
975
976   if (! otf->gdef
977       && OTF_get_table (otf, "GDEF") < 0)
978     return -1;
979   gdef = otf->gdef;
980
981   if (gdef->glyph_class_def.offset)
982     for (i = 0; i < gstring->used; i++)
983       gstring->glyphs[i].GlyphClass
984         = get_class_def (&gdef->glyph_class_def,
985                          gstring->glyphs[i].glyph_id);
986
987   if (gdef->mark_attach_class_def.offset)
988     for (i = 0; i < gstring->used; i++)
989       gstring->glyphs[i].MarkAttachClass
990         = get_class_def (&gdef->mark_attach_class_def,
991                          gstring->glyphs[i].glyph_id);
992
993   return 0;
994 }
995
996
997 int
998 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
999                 char *script, char *language, char *features)
1000 {
1001   char *errfmt = "GSUB driving%s";
1002   int errret = -1;
1003   OTF_GSUB *gsub;
1004   OTF_LangSys *LangSys;
1005   int *lookup_indices;
1006   int i, n;
1007
1008   if (! otf->gsub
1009       && OTF_get_table (otf, "GSUB") < 0)
1010     return errret;
1011   gsub = otf->gsub;
1012   if (gsub->FeatureList.FeatureCount == 0
1013       || gsub->LookupList.LookupCount == 0)
1014     return 0;
1015
1016   LangSys = get_langsys (&gsub->ScriptList, script, language);
1017   if (! LangSys)
1018     return errret;
1019
1020   /* One lookup may be used by multiple features.  */
1021   lookup_indices = alloca (sizeof (int)
1022                            * gsub->LookupList.LookupCount
1023                            * (gsub->FeatureList.FeatureCount + 1));
1024   if (! lookup_indices)
1025     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1026   n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1027                             features, lookup_indices);
1028   if (n < 0)
1029     return errret;
1030
1031   for (i = 0; i < n; i++)
1032     {
1033       int index = lookup_indices[i];
1034       int gidx;
1035
1036       if (gsub->LookupList.Lookup[index].LookupType != 8)
1037         {
1038           gidx = 0;
1039           while (gidx < gstring->used)
1040             {
1041               gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1042               if (gidx < 0)
1043                 return errret;
1044             }
1045         }
1046       else
1047         {
1048           gidx = gstring->used - 1;
1049           while (gidx >= 0)
1050             {
1051               gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1052               if (gidx < 0)
1053                 return errret;
1054             }
1055         }
1056     }
1057
1058   return 0;
1059 }
1060
1061 int
1062 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1063                 char *script, char *language, char *features)
1064 {
1065   char *errfmt = "GPOS driving%s";
1066   int errret = -1;
1067   OTF_GPOS *gpos;
1068   OTF_LangSys *LangSys;
1069   int *lookup_indices;
1070   int i, n;
1071
1072   if (! otf->gpos
1073       && OTF_get_table (otf, "GPOS") < 0)
1074     return errret;
1075   gpos = otf->gpos;
1076   if (gpos->FeatureList.FeatureCount == 0
1077       || gpos->LookupList.LookupCount == 0)
1078     return 0;
1079
1080   LangSys = get_langsys (&gpos->ScriptList, script, language);
1081   if (! LangSys)
1082     return errret;
1083
1084   /* One lookup may be used by multiple features.  */
1085   lookup_indices = alloca (sizeof (int)
1086                            * gpos->LookupList.LookupCount
1087                            * (gpos->FeatureList.FeatureCount + 1));
1088   if (! lookup_indices)
1089     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1090   n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1091                             features, lookup_indices);
1092   if (n < 0)
1093     return errret;
1094
1095   for (i = 0; i < n; i++)
1096     {
1097       int index = lookup_indices[i];
1098       int gidx = 0;
1099
1100       while (gidx < gstring->used)
1101         {
1102           gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1103           if (gidx < 0)
1104             return errret;
1105         }
1106     }
1107
1108   return 0;
1109 }
1110
1111 int
1112 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1113                   char *script, char *language,
1114                   char *gsub_features, char *gpos_features)
1115 {
1116   if (OTF_drive_cmap (otf, gstring) < 0)
1117     return -1;
1118   if (OTF_drive_gdef (otf, gstring) < 0)
1119     return -1;
1120   if (gsub_features
1121       && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1122     return -1;
1123   if (gpos_features
1124       && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1125     return -1;
1126   return 0;
1127 }