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