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