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