*** 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               // printf ("GSUB 6-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
570               class = get_class_def (&context2->InputClassDef, g->glyph_id);
571               set = context2->ChainClassSet + class;
572               for (j = 0; j < set->ChainClassRuleCnt; j++)
573                 {
574                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
575                   int k;
576
577                   if (gidx < rule->BacktrackGlyphCount
578                       || (gidx + rule->InputGlyphCount
579                           + rule->LookaheadGlyphCount) > gstring->used)
580                     continue;
581                   if (match_chain_classes (gstring, gidx,
582                                            &context2->BacktrackClassDef,
583                                            &context2->InputClassDef,
584                                            &context2->LookaheadClassDef,
585                                            rule) < 0)
586                     continue;
587                   orig_used = gstring->used;
588                   for (k = 0; k < rule->LookupCount; k++)
589                     lookup_gsub (lookup_list,
590                                  rule->LookupRecord[k].LookupListIndex,
591                                  gstring,
592                                  gidx + rule->LookupRecord[k].SequenceIndex);
593                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
594                   break;
595                 }
596             }
597           else
598             {
599               OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
600               int orig_used;
601               int j;
602
603               if (gidx < context3->BacktrackGlyphCount
604                   || (gidx + context3->InputGlyphCount
605                       + context3->LookaheadGlyphCount) > gstring->used)
606                 return -1;
607               if (match_chain_coverages (gstring, gidx, context3) < 0)
608                 continue;
609               orig_used = gstring->used;
610               for (j = 0; j < context3->LookupCount; j++)
611                 lookup_gsub (lookup_list,
612                              context3->LookupRecord[j].LookupListIndex,
613                              gstring,
614                              gidx + context3->LookupRecord[j].SequenceIndex);
615               gidx += context3->InputGlyphCount + (gstring->used - orig_used);
616             }
617           break;
618
619         case 8:
620           {
621             OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
622             int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
623             int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
624             int j;
625
626             if (back_gidx > gstring->used || ahead_gidx < 0)
627               break;
628
629             for (j = 0; j < reverse->BacktrackGlyphCount; j++)
630               if (get_coverage_index (reverse->Backtrack + j,
631                                       gstring->glyphs[gidx + 1 + j].glyph_id)
632                   < 0)
633                 break;
634             if (j < reverse->BacktrackGlyphCount)
635               continue;
636             for (j = 0; j < reverse->LookaheadGlyphCount; j++)
637               if (get_coverage_index (reverse->LookAhead + j,
638                                       gstring->glyphs[gidx - 1 - j].glyph_id)
639                   < 0)
640                 break;
641             if (j < reverse->LookaheadGlyphCount)
642               continue;
643             g->glyph_id = reverse->Substitute[coverage_idx];
644             gidx--;
645           }
646
647         default:
648           continue;
649         }
650     }
651   if (gidx == orig_gidx)
652     {
653       //printf ("not applied\n");
654       gidx++;
655     }
656   else
657     {
658       // printf ("done\n");
659     }
660   return gidx;
661 }
662
663 \f
664
665 /* GPOS */
666 unsigned
667 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
668 {
669   unsigned value_format = OTF_XPlacement | OTF_YPlacement;
670
671   rec->XPlacement = anchor->XCoordinate;
672   rec->YPlacement = anchor->YCoordinate;
673   if (anchor->AnchorFormat == 1)
674     /* Nothing to do */
675     ;
676   else if (anchor->AnchorFormat == 2)
677     /* Not yet implemented */
678     ;
679   else if (anchor->AnchorFormat == 3)
680     /* Not yet implemented */
681     ;
682   return value_format;
683 }
684
685
686 static int
687 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
688              OTF_GlyphString *gstring, int gidx)
689 {
690   char *errfmt = "GPOS Looking up%s";
691   int errret = -1;
692   OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
693   unsigned int flag = lookup->LookupFlag;
694   int orig_gidx = gidx;
695   OTF_Glyph *g = gstring->glyphs + gidx;
696   int i;
697
698   if (! g->glyph_id
699       || (g->GlyphClass
700           && (flag & (1 << g->GlyphClass))))
701     return (gidx + 1);
702
703   /* Try all subtables until one of them handles the current glyph.  */
704   for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
705     {
706       OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
707       int coverage_idx;
708
709       // printf ("subtype:%d ", subtable->Format);
710       if (subtable->Coverage.offset)
711         {
712           coverage_idx = get_coverage_index (&subtable->Coverage,
713                                              g->glyph_id);
714           if (coverage_idx < 0)
715             {
716               // printf ("not covererd ");
717               continue;
718             }
719         }
720
721       switch (lookup->LookupType)
722         {
723         case 1:
724           g->positioning_type = lookup->LookupType;
725           if (subtable->Format == 1)
726             {
727               OTF_GPOS_Single1 *single1 = &subtable->u.single1;
728
729               g->f.f1.format = single1->ValueFormat;
730               g->f.f1.value = &single1->Value;
731             }
732           else if (subtable->Format == 2)
733             {
734               OTF_GPOS_Single2 *single2 = &subtable->u.single2;
735
736               g->f.f1.format = single2->ValueFormat;
737               g->f.f1.value = single2->Value + coverage_idx;
738             }
739           break;
740
741         case 2:
742           if (gidx + 1 >= gstring->used)
743             continue;
744           if (subtable->Format == 1)
745             {
746               OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
747               OTF_PairSet *set = pair1->PairSet + coverage_idx;
748               int j;
749
750               for (j = 0; j < set->PairValueCount; j++)
751                 {
752                   if (set->PairValueRecord[j].SecondGlyph != g[1].glyph_id)
753                     continue;
754                   gidx++;
755                   g->positioning_type = lookup->LookupType;
756                   g->f.f2.format = pair1->ValueFormat1;
757                   g->f.f2.value = &set->PairValueRecord[j].Value1;
758                   if (pair1->ValueFormat2)
759                     {
760                       g++, gidx++;
761                       g->positioning_type = lookup->LookupType;
762                       g->f.f2.format = pair1->ValueFormat2;
763                       g->f.f2.value = &set->PairValueRecord[j].Value2;
764                     }
765                 }
766             }
767           else if (subtable->Format == 2)
768             {
769               OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
770               unsigned class1, class2;
771
772               // printf ("GPOS 2-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
773               gidx++;
774               class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
775               class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id);
776               g->positioning_type = lookup->LookupType;
777               g->f.f2.format = pair2->ValueFormat1;
778               g->f.f2.value
779                 = &pair2->Class1Record[class1].Class2Record[class2].Value1;
780               if (pair2->ValueFormat2)
781                 {
782                   g++, gidx++;
783                   g->positioning_type = lookup->LookupType;
784                   g->f.f2.format = pair2->ValueFormat2;
785                   g->f.f2.value
786                     = &pair2->Class1Record[class1].Class2Record[class2].Value2;
787                 }
788             }
789           break;
790
791         case 3:
792           {
793             OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
794           
795             g->positioning_type = lookup->LookupType;
796             g->f.f3.entry_anchor
797               = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
798             g->f.f3.exit_anchor
799               = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
800           }
801           break;
802
803         case 4:
804           if (gidx < 1)
805             continue;
806           if (subtable->Format == 1)
807             {
808               OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
809               OTF_MarkRecord *mark_record;
810               OTF_AnchorRecord *base_record;
811               int coverage_idx_base
812                 = get_coverage_index (&mark_base1->BaseCoverage,
813                                       g[-1].glyph_id);
814
815               if (coverage_idx_base < 0)
816                 continue;
817               // printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
818               mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
819               base_record
820                 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
821               g->f.f4.mark_anchor = &mark_record->MarkAnchor;
822               g->f.f4.base_anchor
823                 = &base_record->Anchor[mark_record->Class];
824               g->positioning_type = lookup->LookupType;
825               break;
826             }
827           break;
828
829         case 5:
830           if (gidx < 1)
831             continue;
832           if (subtable->Format == 1)
833             {
834               /* As the document of this lookup type is quite
835                  ambiguous, and we can't know the exact procedure to
836                  handle it?!?  */
837               OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
838             }
839           break;
840
841         case 6:
842           if (gidx < 1)
843             continue;
844           if (subtable->Format == 1)
845             {
846               OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
847               OTF_MarkRecord *mark1_record;
848               OTF_AnchorRecord *mark2_record;
849               int coverage_idx_base
850                 = get_coverage_index (&mark_mark1->Mark2Coverage,
851                                       g[-1].glyph_id);
852
853               if (coverage_idx_base < 0)
854                 continue;
855               // printf ("GPOS 6-1: c:0x%x g:0x%x\n", g->c, g->glyph_id);
856               mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
857               mark2_record
858                 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
859               g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
860               g->f.f6.mark2_anchor
861                 = &mark2_record->Anchor[mark1_record->Class];
862               g->positioning_type = lookup->LookupType;
863               break;
864             }
865           break;
866
867         case 7:
868           OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
869           break;
870
871         case 8:
872           if (subtable->Format == 1)
873             OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
874           else if (subtable->Format == 2)
875             {
876               OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
877               OTF_ChainClassSet *set;
878               unsigned class;
879               int j;
880               int orig_used;
881
882               // printf ("GPOS 8-2: c:0x%x g:0x%x\n", g->c, g->glyph_id);
883               class = get_class_def (&context2->InputClassDef, g->glyph_id);
884               set = context2->ChainClassSet + class;
885               for (j = 0; j < set->ChainClassRuleCnt; j++)
886                 {
887                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
888                   int fore_idx = gidx + rule->InputGlyphCount;
889                   int k;
890
891                   if (gidx < rule->BacktrackGlyphCount
892                       || (gidx + rule->InputGlyphCount
893                           + rule->LookaheadGlyphCount) > gstring->used)
894                     continue;
895                   for (k = 0; k < rule->BacktrackGlyphCount; k++)
896                     if (get_class_def (&context2->BacktrackClassDef,
897                                        gstring->glyphs[gidx - 1 - k].glyph_id)
898                         != rule->Backtrack[k])
899                       break;
900                   if (k < rule->BacktrackGlyphCount)
901                     continue;
902                   for (k = 1; k < rule->InputGlyphCount; k++)
903                     if (get_class_def (&context2->InputClassDef,
904                                        gstring->glyphs[gidx + k].glyph_id)
905                         != rule->Input[k - 1])
906                       break;
907                   if (k < rule->InputGlyphCount)
908                     continue;
909                   for (k = 0; k < rule->LookaheadGlyphCount; k++)
910                     if (get_class_def (&context2->LookaheadClassDef,
911                                        gstring->glyphs[fore_idx + k].glyph_id)
912                         != rule->LookAhead[k])
913                       break;
914                   if (k < rule->LookaheadGlyphCount)
915                     continue;
916
917                   orig_used = gstring->used;
918                   for (k = 0; k < rule->LookupCount; k++)
919                     lookup_gpos (lookup_list,
920                                  rule->LookupRecord[k].LookupListIndex,
921                                  gstring,
922                                  gidx + rule->LookupRecord[k].SequenceIndex);
923                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
924                   break;
925                 }
926             }
927           else if (subtable->Format == 3)
928             OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
929           else
930             OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
931           break;
932
933         case 9:
934           OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)");
935           break;
936
937         default:
938           continue;
939         }
940     }
941   if (gidx == orig_gidx)
942     {
943       // printf ("not applied\n");
944       gidx++;
945     }
946   else
947     {
948       // printf ("done\n");
949     }
950   return gidx;
951 }
952
953 \f
954
955 /* API */
956
957 int
958 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
959 {
960   OTF_cmap *cmap;
961   int i;
962
963   if (! otf->cmap
964       && OTF_get_table (otf, "cmap") < 0)
965     return -1;
966
967   cmap = otf->cmap;
968   for (i = 0; i < gstring->used; i++)
969     if (! gstring->glyphs[i].glyph_id)
970       {
971         int c = gstring->glyphs[i].c;
972         if (c < 32 || ! cmap->unicode_table)
973           gstring->glyphs[i].glyph_id = 0;
974         else
975           gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
976       }
977   return 0;
978 }
979
980 int
981 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
982 {
983   if (! otf->cmap
984       && OTF_get_table (otf, "cmap") < 0)
985     return 0;
986   if (code == 0
987       || code > otf->cmap->max_glyph_id
988       || ! otf->cmap->decode_table)
989     return 0;
990   return otf->cmap->decode_table[code];
991 }
992
993 int
994 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
995 {
996   OTF_GDEF *gdef;
997   int i;
998
999   if (! otf->gdef
1000       && OTF_get_table (otf, "GDEF") < 0)
1001     return -1;
1002   gdef = otf->gdef;
1003
1004   if (gdef->glyph_class_def.offset)
1005     for (i = 0; i < gstring->used; i++)
1006       gstring->glyphs[i].GlyphClass
1007         = get_class_def (&gdef->glyph_class_def,
1008                          gstring->glyphs[i].glyph_id);
1009
1010   if (gdef->mark_attach_class_def.offset)
1011     for (i = 0; i < gstring->used; i++)
1012       gstring->glyphs[i].MarkAttachClass
1013         = get_class_def (&gdef->mark_attach_class_def,
1014                          gstring->glyphs[i].glyph_id);
1015
1016   return 0;
1017 }
1018
1019
1020 int
1021 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1022                 char *script, char *language, char *features)
1023 {
1024   char *errfmt = "GSUB driving%s";
1025   int errret = -1;
1026   OTF_GSUB *gsub;
1027   OTF_LangSys *LangSys;
1028   int *lookup_indices;
1029   int i, n;
1030
1031   if (! otf->gsub
1032       && OTF_get_table (otf, "GSUB") < 0)
1033     return errret;
1034   gsub = otf->gsub;
1035   if (gsub->FeatureList.FeatureCount == 0
1036       || gsub->LookupList.LookupCount == 0)
1037     return 0;
1038
1039   LangSys = get_langsys (&gsub->ScriptList, script, language);
1040   if (! LangSys)
1041     return errret;
1042
1043   /* One lookup may be used by multiple features.  */
1044   lookup_indices = alloca (sizeof (int)
1045                            * gsub->LookupList.LookupCount
1046                            * (gsub->FeatureList.FeatureCount + 1));
1047   if (! lookup_indices)
1048     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1049   n = setup_lookup_indices (&gsub->LookupList, &gsub->FeatureList,
1050                             features, lookup_indices);
1051   if (n < 0)
1052     return errret;
1053
1054   for (i = 0; i < n; i++)
1055     {
1056       int index = lookup_indices[i];
1057       int gidx;
1058
1059       if (gsub->LookupList.Lookup[index].LookupType != 8)
1060         {
1061           gidx = 0;
1062           while (gidx < gstring->used)
1063             {
1064               gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1065               if (gidx < 0)
1066                 return errret;
1067             }
1068         }
1069       else
1070         {
1071           gidx = gstring->used - 1;
1072           while (gidx >= 0)
1073             {
1074               gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx);
1075               if (gidx < 0)
1076                 return errret;
1077             }
1078         }
1079     }
1080
1081   return 0;
1082 }
1083
1084 int
1085 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1086                 char *script, char *language, char *features)
1087 {
1088   char *errfmt = "GPOS driving%s";
1089   int errret = -1;
1090   OTF_GPOS *gpos;
1091   OTF_LangSys *LangSys;
1092   int *lookup_indices;
1093   int i, n;
1094
1095   if (! otf->gpos
1096       && OTF_get_table (otf, "GPOS") < 0)
1097     return errret;
1098   gpos = otf->gpos;
1099   if (gpos->FeatureList.FeatureCount == 0
1100       || gpos->LookupList.LookupCount == 0)
1101     return 0;
1102
1103   LangSys = get_langsys (&gpos->ScriptList, script, language);
1104   if (! LangSys)
1105     return errret;
1106
1107   /* One lookup may be used by multiple features.  */
1108   lookup_indices = alloca (sizeof (int)
1109                            * gpos->LookupList.LookupCount
1110                            * (gpos->FeatureList.FeatureCount + 1));
1111   if (! lookup_indices)
1112     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1113   n = setup_lookup_indices (&gpos->LookupList, &gpos->FeatureList,
1114                             features, lookup_indices);
1115   if (n < 0)
1116     return errret;
1117
1118   for (i = 0; i < n; i++)
1119     {
1120       int index = lookup_indices[i];
1121       int gidx = 0;
1122
1123       while (gidx < gstring->used)
1124         {
1125           gidx = lookup_gpos (&gpos->LookupList, index, gstring, gidx);
1126           if (gidx < 0)
1127             return errret;
1128         }
1129     }
1130
1131   return 0;
1132 }
1133
1134 int
1135 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1136                   char *script, char *language,
1137                   char *gsub_features, char *gpos_features)
1138 {
1139   if (OTF_drive_cmap (otf, gstring) < 0)
1140     return -1;
1141   if (OTF_drive_gdef (otf, gstring) < 0)
1142     return -1;
1143   if (gsub_features
1144       && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1145     return -1;
1146   if (gpos_features
1147       && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1148     return -1;
1149   return 0;
1150 }