*** 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 extern int debug_flag;
33
34 /* Return nonzero (-1 if ID is zero, 1 otherwise) if OTF_Glyph *G
35    should be ignored according to LookupFlag FLAG.  */
36 #define IGNORED_GLYPH(g, flag)                          \
37   ((g)->glyph_id == 0 ? -1                              \
38    : (((flag) & (1 << (g)->GlyphClass))                 \
39       || (((flag) & OTF_MarkAttachmentType)             \
40           && (g)->GlyphClass == OTF_GlyphClassMark      \
41           && ((flag) >> 8) != (g)->MarkAttachClass)))
42
43 #define GSTRING_DELETE(gstring, from, len)                              \
44   do {                                                                  \
45     memmove (gstring->glyphs + from, gstring->glyphs + from + len,      \
46              sizeof (OTF_Glyph) * (gstring->used - from - len));        \
47     gstring->used -= len;                                               \
48   } while (0)
49
50
51 #define GSTRING_INSERT(gstring, pos, len)                               \
52   do {                                                                  \
53     if (gstring->used + len > gstring->size)                            \
54       {                                                                 \
55         char *errfmt = "GSTRING%s";                                     \
56                                                                         \
57         gstring->size = gstring->used + len;                            \
58         gstring->glyphs                                                 \
59           = (OTF_Glyph *) realloc (gstring->glyphs,                     \
60                                    sizeof (OTF_Glyph) * gstring->size); \
61         if (! gstring->glyphs)                                          \
62           OTF_ERROR (OTF_ERROR_MEMORY, "");                             \
63       }                                                                 \
64     memmove (gstring->glyphs + pos + len, gstring->glyphs + pos,        \
65              sizeof (OTF_Glyph) * (gstring->used - pos));               \
66     gstring->used += len;                                               \
67   } while (0)
68
69
70 static unsigned get_class_def (OTF_ClassDef *, OTF_GlyphID);
71
72 static int
73 gstring_subst (OTF *otf, OTF_GlyphString *gstring, int from, int to, int flag,
74                OTF_GlyphID *ids, int num)
75 {
76   int errret = -1;
77   int len = to - from;
78   int i;
79   int from_idx = gstring->glyphs[from].f.index.from;
80   int to_idx = gstring->glyphs[to - 1].f.index.to;
81   int non_ignored_idx;
82
83   for (i = non_ignored_idx = to - 1; i >= from; i--)
84     {
85       OTF_Glyph *g = gstring->glyphs + i;
86
87       if (IGNORED_GLYPH (g, flag) == 1)
88         {
89           /* Move this glyph to the next of the current target of
90              substitution.  */
91           OTF_Glyph temp = *g;
92
93           memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i));
94           temp.f.index.from = from_idx;
95           temp.f.index.to = to_idx;
96           gstring->glyphs[non_ignored_idx--] = temp;
97           len--;
98         }
99     }
100
101   if (len < num)
102     GSTRING_INSERT (gstring, from, (num - len));
103   else if (len > num)
104     GSTRING_DELETE (gstring, from, (len - num));
105   for (i = 0; i < num; i++)
106     {
107       if (gstring->glyphs[from + i].glyph_id != ids[i])
108         {
109           gstring->glyphs[from + i].c = 0;
110           if (otf->gdef)
111             gstring->glyphs[from + i].GlyphClass
112               = get_class_def (&otf->gdef->glyph_class_def, ids[i]);
113           else
114             gstring->glyphs[from + i].GlyphClass = 0;
115         }
116       gstring->glyphs[from + i].glyph_id = ids[i];
117       gstring->glyphs[from + i].positioning_type = 0;
118       gstring->glyphs[from + i].f.index.from = from_idx;
119       gstring->glyphs[from + i].f.index.to = to_idx;
120     }
121   return 0;
122 }
123
124 \f
125 static int
126 get_coverage_index (OTF_Coverage *coverage, OTF_GlyphID id)
127 {
128   int i;
129
130   if (coverage->CoverageFormat == 1)
131     {
132       for (i = 0; i < coverage->Count; i++)
133         if (coverage->table.GlyphArray[i] == id)
134           return i;
135     }
136   else
137     {
138       for (i = 0; i < coverage->Count; i++)
139         if (coverage->table.RangeRecord[i].Start <= id
140             && coverage->table.RangeRecord[i].End >= id)
141           return (coverage->table.RangeRecord[i].StartCoverageIndex
142                   + (id - coverage->table.RangeRecord[i].Start));
143     }
144   return -1;
145 }
146
147 static unsigned
148 get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id)
149 {
150   if (class_def->ClassFormat == 1)
151     {
152       int idx = (int) glyph_id - (int) class_def->f.f1.StartGlyph;
153
154       if (idx >= 0 && idx < class_def->f.f1.GlyphCount)
155         return class_def->f.f1.ClassValueArray[idx];
156     }
157   else
158     {
159       int i;
160
161       for (i = 0; i < class_def->f.f2.ClassRangeCount; i++)
162         if (glyph_id >= class_def->f.f2.ClassRangeRecord[i].Start
163             && glyph_id <= class_def->f.f2.ClassRangeRecord[i].End)
164           return class_def->f.f2.ClassRangeRecord[i].Class;
165     }
166   return 0;
167 }
168
169 static OTF_LangSys *
170 get_langsys (OTF_ScriptList *script_list,
171              const char *script, const char *language)
172 {
173
174   OTF_Tag script_tag = OTF_tag (script);
175   OTF_Tag langsys_tag = OTF_tag (language);
176   int i, j;
177   OTF_Tag dflt_tag = OTF_tag ("DFLT");
178   OTF_Script *dflt = NULL;
179
180   for (i = 0; i < script_list->ScriptCount; i++)
181     {
182       OTF_Script *script = script_list->Script + i;
183
184       if (script_list->Script[i].ScriptTag == dflt_tag)
185         dflt = script;
186       if (script_list->Script[i].ScriptTag == script_tag)
187         {
188           if (! langsys_tag)
189             return &script->DefaultLangSys;
190           for (j = 0; j < script->LangSysCount; j++)
191             if (script->LangSysRecord[j].LangSysTag == langsys_tag)
192               return script->LangSys + j;
193           return &script->DefaultLangSys;       
194         }
195     }
196
197   if (! dflt)
198     dflt = script_list->Script;
199   if (! langsys_tag)
200     return &dflt->DefaultLangSys;
201   for (j = 0; j < dflt->LangSysCount; j++)
202     if (dflt->LangSysRecord[j].LangSysTag == langsys_tag)
203       return dflt->LangSys + j;
204   return &dflt->DefaultLangSys; 
205 }
206
207 static int
208 setup_lookup_flags (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList,
209                     OTF_LangSys *LangSys,
210                     const char *features, char *lookup_flags)
211 {
212   int i, j, n = 0;
213   OTF_Feature *feature;
214   int *feature_table = alloca (sizeof (int) * FeatureList->FeatureCount);
215
216   if (! feature_table)
217     return -1;
218   for (i = 0; i < FeatureList->FeatureCount; i++)
219     feature_table[i] = 0;
220   memset (lookup_flags, 0, LookupList->LookupCount);
221
222   while (*features)
223     {
224       char tagname[4];
225       OTF_Tag tag;
226       int use_it = 1;
227
228       if (*features == '*')
229         {
230           /* Consume all remaining features.  */
231           for (i = 0; i < LangSys->FeatureCount; i++) 
232             {
233               int index = LangSys->FeatureIndex[i];
234
235               if (! feature_table[index])
236                 {
237                   feature = FeatureList->Feature + index;
238                   for (j = 0; j < feature->LookupCount; j++)
239                     lookup_flags[feature->LookupListIndex[j]] = 1;
240                 }
241             }
242           break;
243         }
244
245       if (*features == '~')
246         use_it = -1, features++;
247       for (i = 0; *features && *features != ','; i++, features++)
248         tagname[i] = *features;
249       if (*features)
250         /* Skip ',' */
251         features++;
252       for (; i < 4; i++)
253         tagname[i] = '\0';
254       tag = OTF_tag (tagname);
255       for (i = 0; i < LangSys->FeatureCount; i++)
256         {
257           feature = FeatureList->Feature + LangSys->FeatureIndex[i];
258           if (tag == feature->FeatureTag)
259             {
260               if (feature_table[i])
261                 break;
262               if (use_it > 0)
263                 for (j = 0; j < feature->LookupCount; j++)
264                   lookup_flags[feature->LookupListIndex[j]] = 1;
265               feature_table[i] = use_it;
266               break;
267             }
268         }
269     }
270   return 0;
271 }
272
273 static int
274 match_ids (OTF_GlyphString *gstring, int gidx, int flag,
275            int count, OTF_GlyphID *ids)
276 {
277   OTF_Glyph *gbeg = gstring->glyphs + gidx;
278   OTF_Glyph *gend = gstring->glyphs + gstring->used;
279   OTF_Glyph *g;
280   int i;
281
282   for (g = gbeg, i = 0; g < gend && i < count; g++)
283     if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++])
284       return -1;
285   return (i < count ? -1 : g - gbeg);
286 }
287
288 static int
289 match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag,
290                  OTF_ChainRule *rule)
291 {
292   int i = rule->BacktrackGlyphCount;
293
294   if (i > 0)
295     {
296       int j;
297       OTF_Glyph *g;
298
299       for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
300         if (! IGNORED_GLYPH (g, flag) && --i == 0)
301           break;
302       if (i > 0)
303         return -1;
304       if (match_ids (gstring, j, flag,
305                      rule->BacktrackGlyphCount, rule->Backtrack)
306           < 0)
307         return -1;
308     }
309   gidx++;
310   i = match_ids (gstring, gidx, flag,
311                  rule->InputGlyphCount - 1, rule->Input);
312   if (i < 0)
313     return -1;
314   gidx += i;
315   i = match_ids (gstring, gidx, flag,
316                  rule->LookaheadGlyphCount, rule->LookAhead);
317   if (i < 0)
318     return -1;
319   return 0;
320 }
321
322 static int
323 match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx,
324                int flag, int count, unsigned *classes)
325 {
326   OTF_Glyph *gbeg = gstring->glyphs + gidx;
327   OTF_Glyph *gend = gstring->glyphs + gstring->used;
328   OTF_Glyph *g;
329   int i;
330
331   for (g = gbeg, i = 0; g < gend && i < count; g++)
332     if (! IGNORED_GLYPH (g, flag)
333         && get_class_def (class_def, g->glyph_id) != classes[i++])
334       return -1;
335   return (i < count ? -1 : g - gbeg);
336 }
337
338 static int
339 match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag,
340                      OTF_ClassDef *BacktrackClassDef,
341                      OTF_ClassDef *InputClassDef,
342                      OTF_ClassDef *LookaheadClassDef,
343                      OTF_ChainClassRule *rule)
344 {
345   int i = rule->BacktrackGlyphCount;
346
347   if (i > 0)
348     {
349       int j;
350       OTF_Glyph *g;
351
352       for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--)
353         if (! IGNORED_GLYPH (g, flag) && i-- == 0)
354           break;
355       if (i > 0)
356         return -1;
357       if (match_classes (BacktrackClassDef, gstring, j, flag,
358                          rule->BacktrackGlyphCount, rule->Backtrack) < 0);
359       return -1;
360     }
361   gidx++;
362   i = match_classes (InputClassDef, gstring, gidx, flag,
363                      rule->InputGlyphCount - 1, rule->Input);
364   if (i < 0)
365     return -1;
366   gidx += i;
367   i = match_classes (LookaheadClassDef, gstring, gidx, flag,
368                      rule->LookaheadGlyphCount, rule->LookAhead);
369   if (i < 0)
370     return -1;
371   return 0;
372 }
373
374
375 static int
376 match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count,
377                  OTF_Coverage *coverages)
378 {
379   OTF_Glyph *gbeg = gstring->glyphs + gidx;
380   OTF_Glyph *gend = gstring->glyphs + gstring->used;
381   OTF_Glyph *g;
382   int i;
383
384   for (g = gbeg, i = 0; g < gend && i < count; g++)
385     if (! IGNORED_GLYPH (g, flag)
386         && get_coverage_index (coverages + i++, g->glyph_id) < 0)
387       return -1;
388   return (i < count ? -1 : g - gbeg);
389 }
390
391 static int
392 match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag,
393                        OTF_GSUB_ChainContext3 *context3)
394 {
395   int i = context3->BacktrackGlyphCount;
396
397   if (i > 0)
398     {
399       int j;
400       OTF_Glyph *g;
401
402       for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--)
403         if (! IGNORED_GLYPH (g, flag) && --i == 0)
404           break;
405       if (i > 0)
406         return -1;
407       if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount,
408                            context3->Backtrack) < 0)
409         return -1;
410     }
411   gidx++;
412   if (context3->InputGlyphCount > 1)
413     {
414       i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1,
415                            context3->Input + 1);
416       if (i < 0)
417         return -1;
418       gidx += i;
419     }
420   if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount,
421                        context3->LookAhead) < 0)
422     return -1;
423   return 0;
424 }
425
426 static int
427 lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index,
428              OTF_GlyphString *gstring, int gidx, int alternate_subst)
429 {
430   char *errfmt = "GSUB Looking up%s";
431   int errret = -1;
432   OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
433   unsigned int flag = (lookup->LookupFlag
434                        & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
435   int orig_gidx = gidx;
436   OTF_Glyph *g = gstring->glyphs + gidx;
437   int i;
438
439   if (IGNORED_GLYPH (g, flag))
440     return (gidx + 1);
441
442   /* Try all subtables until one of them handles the current glyph.  */
443   for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
444     {
445       unsigned lookup_type = lookup->LookupType;
446       OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
447       int coverage_idx;
448
449       if (lookup_type == 7)
450         {
451           OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
452
453           lookup_type = extension1->ExtensionLookupType;
454           subtable = extension1->ExtensionSubtable;
455         }
456
457       if (alternate_subst
458           ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6)
459           : (lookup_type == 3))
460         continue;
461
462       if (subtable->Coverage.offset)
463         {
464           coverage_idx = get_coverage_index (&subtable->Coverage,
465                                              g->glyph_id);
466           if (coverage_idx < 0)
467             continue;
468         }
469
470       switch (lookup_type)
471         {
472         case 1:
473           if (subtable->Format == 1)
474             g->glyph_id += subtable->u.single1.DeltaGlyphID;
475           else
476             g->glyph_id = subtable->u.single2.Substitute[coverage_idx];
477           gidx++;
478           break;
479
480         case 2:
481           if (subtable->Format == 1)
482             {
483               OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1;
484               OTF_Sequence *seq = multiple1->Sequence + coverage_idx;
485
486               gstring_subst (otf, gstring, gidx, gidx + 1, flag,
487                              seq->Substitute, seq->GlyphCount);
488               gidx += seq->GlyphCount;
489             }
490           else
491             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
492           break;
493
494         case 3:
495           if (subtable->Format == 1)
496             {
497               OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1;
498               OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx;
499
500               gstring_subst (otf, gstring, gidx, gidx + 1, flag,
501                              altset->Alternate, altset->GlyphCount);
502               gidx += altset->GlyphCount;;
503             }
504           else
505             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
506           break;
507
508         case 4:
509           if (subtable->Format == 1)
510             {
511               OTF_GSUB_Ligature1 *lig1 = &subtable->u.ligature1;
512               OTF_LigatureSet *ligset = lig1->LigatureSet + coverage_idx;
513               OTF_Ligature *lig;
514               int j;
515
516               for (j = 0; j < ligset->LigatureCount; j++)
517                 {
518                   int n;
519
520                   lig = ligset->Ligature + j;
521                   n = match_ids (gstring, gidx + 1, flag,
522                                  lig->CompCount - 1, lig->Component);
523                   if (n < 0)
524                     continue;
525                   gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag,
526                                  &lig->LigGlyph, 1);
527                   gidx++;
528                   break;
529                 }
530             }
531           else
532             OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)");
533           break;
534
535         case 5:
536           if (subtable->Format == 1)
537             {
538               OTF_GSUB_Context1 *context1 = &subtable->u.context1;
539               OTF_RuleSet *set = context1->RuleSet + coverage_idx;
540               OTF_Rule *rule;
541               int orig_used;
542               int j, k;
543
544               for (j = 0; j < set->RuleCount; j++)
545                 {
546                   rule = set->Rule + j;
547                   if (match_ids (gstring, gidx + 1, flag,
548                                  rule->GlyphCount - 1, rule->Input) < 0)
549                     continue;
550                   orig_used = gstring->used;
551                   for (k = 0; k < rule->LookupCount; k++)
552                     lookup_gsub (otf, lookup_list,
553                                  rule->LookupRecord[k].LookupListIndex,
554                                  gstring,
555                                  gidx + rule->LookupRecord[k].SequenceIndex,
556                                  alternate_subst);
557                   gidx += rule->GlyphCount + (gstring->used - orig_used);
558                   break;
559                 }
560             }
561           else if (subtable->Format == 2)
562             {
563               OTF_GSUB_Context2 *context2 = &subtable->u.context2;
564               OTF_ClassSet *set;
565               OTF_ClassRule *rule;
566               unsigned class;
567               int orig_used;
568               int j, k;
569
570               class = get_class_def (&context2->ClassDef, g->glyph_id);
571               set = context2->ClassSet + class;
572               if (set)
573                 for (j = 0; j < set->ClassRuleCnt; j++)
574                   {
575                     rule = set->ClassRule + j;
576                     if (match_classes (&context2->ClassDef,
577                                        gstring, gidx + 1, flag,
578                                        rule->GlyphCount - 1, rule->Class)
579                         < 0)
580                       continue;
581                     orig_used = gstring->used;
582                     for (k = 0; k < rule->LookupCount; k++)
583                       lookup_gsub (otf, lookup_list,
584                                    rule->LookupRecord[k].LookupListIndex,
585                                    gstring,
586                                    gidx + rule->LookupRecord[k].SequenceIndex,
587                                    alternate_subst);
588                     gidx += rule->GlyphCount + (gstring->used - orig_used);
589                     break;
590                   }
591             }
592           else                  /* subtable->Format == 3 */
593             {
594               OTF_GSUB_Context3 *context3 = &subtable->u.context3;
595               int orig_used;
596               int j;
597
598               if (match_coverages (gstring, gidx + 1, flag,
599                                    context3->GlyphCount - 1,
600                                    context3->Coverage + 1) < 0)
601                 continue;
602               orig_used = gstring->used;
603               for (j = 0; j < context3->LookupCount; j++)
604                 lookup_gsub (otf, lookup_list,
605                              context3->LookupRecord[j].LookupListIndex,
606                              gstring,
607                              gidx + context3->LookupRecord[j].SequenceIndex,
608                              alternate_subst);
609               gidx += context3->GlyphCount + (gstring->used - orig_used);
610             }
611           break;
612
613         case 6:
614           if (subtable->Format == 1)
615             {
616               OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
617               OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
618               int orig_used;
619               int j, k;
620               
621               for (j = 0; j < set->ChainRuleCount; j++)
622                 {
623                   OTF_ChainRule *rule = set->ChainRule + j;
624
625                   if (gidx < rule->BacktrackGlyphCount
626                       || (gidx + rule->InputGlyphCount
627                           + rule->LookaheadGlyphCount) > gstring->used)
628                     continue;
629                   if (match_chain_ids (gstring, gidx, flag, rule) < 0)
630                     continue;
631                   orig_used = gstring->used;
632                   for (k = 0; k < rule->LookupCount; k++)
633                     lookup_gsub (otf, lookup_list,
634                                  rule->LookupRecord[k].LookupListIndex,
635                                  gstring,
636                                  gidx + rule->LookupRecord[k].SequenceIndex,
637                                  alternate_subst);
638                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
639                   break;
640                 }
641             }
642           else if (subtable->Format == 2)
643             {
644               OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
645               OTF_ChainClassSet *set;
646               unsigned class;
647               int j;
648               int orig_used;
649
650               class = get_class_def (&context2->InputClassDef, g->glyph_id);
651               set = context2->ChainClassSet + class;
652               for (j = 0; j < set->ChainClassRuleCnt; j++)
653                 {
654                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
655                   int k;
656
657                   if (gidx < rule->BacktrackGlyphCount
658                       || (gidx + rule->InputGlyphCount
659                           + rule->LookaheadGlyphCount) > gstring->used)
660                     continue;
661                   if (match_chain_classes (gstring, gidx, flag,
662                                            &context2->BacktrackClassDef,
663                                            &context2->InputClassDef,
664                                            &context2->LookaheadClassDef,
665                                            rule) < 0)
666                     continue;
667                   orig_used = gstring->used;
668                   for (k = 0; k < rule->LookupCount; k++)
669                     lookup_gsub (otf, lookup_list,
670                                  rule->LookupRecord[k].LookupListIndex,
671                                  gstring,
672                                  gidx + rule->LookupRecord[k].SequenceIndex,
673                                  alternate_subst);
674                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
675                   break;
676                 }
677             }
678           else
679             {
680               OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
681               int orig_used;
682               int j;
683
684               if (gidx < context3->BacktrackGlyphCount
685                   || (gidx + context3->InputGlyphCount
686                       + context3->LookaheadGlyphCount) > gstring->used)
687                 continue;
688               if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
689                 continue;
690               orig_used = gstring->used;
691               for (j = 0; j < context3->LookupCount; j++)
692                 lookup_gsub (otf, lookup_list,
693                              context3->LookupRecord[j].LookupListIndex,
694                              gstring,
695                              gidx + context3->LookupRecord[j].SequenceIndex,
696                              alternate_subst);
697               gidx += context3->InputGlyphCount + (gstring->used - orig_used);
698             }
699           break;
700
701         case 8:
702           {
703             OTF_GSUB_ReverseChain1 *reverse = &subtable->u.reverse_chain1;
704             int back_gidx = gidx + 1 + reverse->BacktrackGlyphCount;
705             int ahead_gidx = gidx - reverse->LookaheadGlyphCount;
706             int j;
707
708             if (back_gidx > gstring->used || ahead_gidx < 0)
709               break;
710
711             for (j = 0; j < reverse->BacktrackGlyphCount; j++)
712               if (get_coverage_index (reverse->Backtrack + j,
713                                       gstring->glyphs[gidx + 1 + j].glyph_id)
714                   < 0)
715                 break;
716             if (j < reverse->BacktrackGlyphCount)
717               continue;
718             for (j = 0; j < reverse->LookaheadGlyphCount; j++)
719               if (get_coverage_index (reverse->LookAhead + j,
720                                       gstring->glyphs[gidx - 1 - j].glyph_id)
721                   < 0)
722                 break;
723             if (j < reverse->LookaheadGlyphCount)
724               continue;
725             g->glyph_id = reverse->Substitute[coverage_idx];
726             gidx--;
727           }
728
729         default:
730           continue;
731         }
732     }
733   if (gidx == orig_gidx)
734     gidx++;
735   return gidx;
736 }
737
738 \f
739
740 /* GPOS */
741
742 static int
743 gstring_insert_for_gpos (OTF_GlyphString *gstring, int gidx)
744 {
745   int errret = -1;
746   int orig_gidx = gidx++;
747
748   while (gidx < gstring->used
749          && ! gstring->glyphs[gidx].glyph_id
750          && gstring->glyphs[gidx].positioning_type)
751     gidx++;
752   GSTRING_INSERT (gstring, gidx, 1);
753   gstring->glyphs[gidx] = gstring->glyphs[orig_gidx];
754   gstring->glyphs[gidx].glyph_id = 0;
755   return gidx;
756 }
757
758 static void
759 print_anchor (char *head, OTF_Anchor *anchor)
760 {
761   if (anchor->AnchorFormat == 1)
762     fprintf (stderr, " %s(X:%d Y:%d)", head,
763              anchor->XCoordinate, anchor->YCoordinate);
764   else if (anchor->AnchorFormat == 2)
765     fprintf (stderr, " %s(X:%d Y:%d AP:%d)", head,
766              anchor->XCoordinate, anchor->YCoordinate,
767              anchor->f.f1.AnchorPoint);
768   else
769     fprintf (stderr, " %s(X:%d Y:%d +alpha)", head,
770              anchor->XCoordinate, anchor->YCoordinate);
771 }
772
773 static void
774 print_glyph_positioning (OTF_Glyph *g, int type)
775 {
776   if (type)
777     fprintf (stderr, " %0X=", g->glyph_id);
778   switch (g->positioning_type)
779     {
780     case 1: case 2:
781       {
782         int format = g->f.f1.format;
783
784         if (format & OTF_XPlacement)
785           fprintf (stderr, "X:%d", g->f.f1.value->XPlacement);
786         if (format & OTF_XPlaDevice)
787           fprintf (stderr, "+alpha");
788         if (format & OTF_YPlacement)
789           fprintf (stderr, "Y:%d", g->f.f1.value->YPlacement);
790         if (format & OTF_YPlaDevice)
791           fprintf (stderr, "+alpha");
792         if (format & OTF_XAdvance)
793           fprintf (stderr, "X+:%d", g->f.f1.value->XAdvance);
794         if (format & OTF_XAdvDevice)
795           fprintf (stderr, "+alpha");
796         break;
797       }
798     case 3:
799       print_anchor ("entry", g->f.f3.entry_anchor);
800       print_anchor ("exit", g->f.f3.entry_anchor);
801       break;
802     case 4:
803       print_anchor ("mark", g->f.f4.mark_anchor);
804       print_anchor ("base", g->f.f4.base_anchor);
805       break;
806     case 5:
807       print_anchor ("mark", g->f.f5.mark_anchor);
808       print_anchor ("lig", g->f.f5.ligature_anchor);
809       break;
810     case 6:
811       print_anchor ("mark1", g->f.f6.mark1_anchor);
812       print_anchor ("mark2", g->f.f6.mark2_anchor);
813       break;
814     }
815 }
816
817 static int
818 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
819              OTF_GlyphString *gstring, int gidx, int accumulate)
820 {
821   char *errfmt = "GPOS Looking up%s";
822   int errret = -1;
823   OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
824   unsigned int flag = (lookup->LookupFlag
825                        & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
826   int orig_gidx = gidx;
827   OTF_Glyph *g = gstring->glyphs + gidx;
828   int i;
829
830   if (debug_flag)
831     fprintf (stderr, "[GPOS] glyph:%04X lookup:%02d",
832              g->glyph_id, lookup_list_index);
833   if (IGNORED_GLYPH (g, flag))
834     {
835       if (debug_flag)
836         fprintf (stderr, " glyph ignored\n");
837       return (gidx + 1);
838     }
839
840   /* Try all subtables until one of them handles the current glyph.  */
841   for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
842     {
843       unsigned lookup_type = lookup->LookupType;
844       OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
845       int coverage_idx;
846       int positioning_type;
847       enum OTF_ValueFormat format;
848       OTF_ValueRecord *value;
849       OTF_Anchor *anchor1, *anchor2;
850
851       if (lookup_type == 9)
852         {
853           OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
854
855           lookup_type = extension1->ExtensionLookupType;
856           subtable = extension1->ExtensionSubtable;
857         }
858
859       if (debug_flag)
860         fprintf (stderr, "/%d", lookup_type);
861       if (subtable->Coverage.offset)
862         {
863           coverage_idx = get_coverage_index (&subtable->Coverage,
864                                              g->glyph_id);
865           if (coverage_idx < 0)
866             continue;
867         }
868
869       switch (lookup_type)
870         {
871         case 1:
872           positioning_type = lookup_type;
873           if (subtable->Format == 1)
874             {
875               OTF_GPOS_Single1 *single1 = &subtable->u.single1;
876
877               format = single1->ValueFormat;
878               value = &single1->Value;
879             }
880           else if (subtable->Format == 2)
881             {
882               OTF_GPOS_Single2 *single2 = &subtable->u.single2;
883
884               format = single2->ValueFormat;
885               value = single2->Value + coverage_idx;
886             }
887           if (accumulate && g->positioning_type)
888             {
889               gidx = gstring_insert_for_gpos (gstring, gidx);         
890               g = gstring->glyphs + gidx;
891             }
892           g->positioning_type = positioning_type;
893           g->f.f1.format = format;
894           g->f.f1.value = value;
895           if (debug_flag)
896             print_glyph_positioning (g, 0);
897           gidx++;
898           break;
899
900         case 2:
901           {
902             int next_gidx;
903             OTF_Glyph *nextg;
904
905             for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
906                  next_gidx < gstring->used && IGNORED_GLYPH (nextg, flag);
907                  next_gidx++, nextg++);
908
909             if (next_gidx >= gstring->used)
910               continue;
911             if (subtable->Format == 1)
912               {
913                 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
914                 OTF_PairSet *set = pair1->PairSet + coverage_idx;
915                 int j;
916
917                 for (j = 0; j < set->PairValueCount; j++)
918                   if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
919                     {
920                       if (pair1->ValueFormat1)
921                         {
922                           if (accumulate && g->positioning_type)
923                             {
924                               gidx = gstring_insert_for_gpos (gstring, gidx);
925                               g = gstring->glyphs + gidx;
926                               next_gidx += gidx - orig_gidx;
927                               nextg = gstring->glyphs + next_gidx;
928                             }
929                           g->positioning_type = lookup_type;
930                           g->f.f2.format = pair1->ValueFormat1;
931                           g->f.f2.value = &set->PairValueRecord[j].Value1;
932                           if (debug_flag)
933                             print_glyph_positioning (g, 1);
934                         }
935                       gidx = next_gidx;
936                       g = nextg;
937                       if (pair1->ValueFormat2)
938                         {
939                           if (accumulate && g->positioning_type)
940                             {
941                               gidx = gstring_insert_for_gpos (gstring, gidx);
942                               g = gstring->glyphs + gidx;
943                             }
944                           g->positioning_type = lookup_type;
945                           g->f.f2.format = pair1->ValueFormat2;
946                           g->f.f2.value = &set->PairValueRecord[j].Value2;
947                           if (debug_flag)
948                             print_glyph_positioning (g, 2);
949                         }
950                       break;
951                     }
952               }
953             else if (subtable->Format == 2)
954               {
955                 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
956                 unsigned class1, class2;
957
958                 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
959                 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
960                 if (pair2->ValueFormat1)
961                   {
962                     if (accumulate && g->positioning_type)
963                       {
964                         gidx = gstring_insert_for_gpos (gstring, gidx);
965                         g = gstring->glyphs + gidx;
966                         next_gidx += gidx - orig_gidx;
967                         nextg = gstring->glyphs + next_gidx;
968                       }
969                     g->positioning_type = lookup_type;
970                     g->f.f2.format = pair2->ValueFormat1;
971                     g->f.f2.value
972                       = &pair2->Class1Record[class1].Class2Record[class2].Value1;
973                     if (debug_flag)
974                       print_glyph_positioning (g, 1);
975                   }
976                 gidx = next_gidx;
977                 g = nextg;
978                 if (pair2->ValueFormat2)
979                   {
980                     if (accumulate && g->positioning_type)
981                       {
982                         gidx = gstring_insert_for_gpos (gstring, gidx);
983                         g = gstring->glyphs + gidx;
984                       }
985                     g->positioning_type = lookup_type;
986                     g->f.f2.format = pair2->ValueFormat2;
987                     g->f.f2.value
988                       = &pair2->Class1Record[class1].Class2Record[class2].Value2;
989                     if (debug_flag)
990                       print_glyph_positioning (g, 2);
991                   }
992               }
993           }
994           break;
995
996         case 3:
997           {
998             OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
999           
1000             g->positioning_type = lookup_type;
1001             g->f.f3.entry_anchor
1002               = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
1003             g->f.f3.exit_anchor
1004               = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
1005             if (debug_flag)
1006               print_glyph_positioning (g, 0);
1007             gidx++;
1008           }
1009           break;
1010
1011         case 4:
1012           if (gidx < 1)
1013             continue;
1014           if (subtable->Format == 1)
1015             {
1016               OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
1017               OTF_MarkRecord *mark_record;
1018               OTF_AnchorRecord *base_record;
1019               OTF_Glyph *baseg;
1020               int coverage_idx_base;
1021               unsigned int this_flag = flag | OTF_IgnoreMarks;
1022
1023               for (baseg = g - 1;
1024                    baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, this_flag);
1025                    baseg--);
1026               if (baseg < gstring->glyphs)
1027                 continue;
1028               coverage_idx_base
1029                 = get_coverage_index (&mark_base1->BaseCoverage,
1030                                       baseg->glyph_id);
1031               if (coverage_idx_base < 0)
1032                 continue;
1033               mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
1034               base_record
1035                 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
1036               g->f.f4.mark_anchor = &mark_record->MarkAnchor;
1037               g->f.f4.base_anchor
1038                 = &base_record->Anchor[mark_record->Class];
1039               g->positioning_type = lookup_type;
1040               if (debug_flag)
1041                 print_glyph_positioning (g, 0);
1042               gidx++;
1043             }
1044           break;
1045
1046         case 5:
1047           if (gidx < 1)
1048             continue;
1049           if (subtable->Format == 1)
1050             {
1051               OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
1052               OTF_Glyph *ligg;
1053               int coverage_idx_lig;
1054               OTF_MarkRecord *mark_record;
1055               OTF_LigatureAttach *attach;
1056               int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
1057               int j;
1058                                        
1059               for (j = 0; j < mark_lig1->ClassCount; j++)
1060                 num_class[j] = 0;
1061
1062               for (ligg = g - 1;
1063                    (ligg >= gstring->glyphs
1064                     && (IGNORED_GLYPH (ligg, flag)
1065                         || ligg->GlyphClass > OTF_GlyphClassLigature));
1066                    ligg--)
1067                 if (ligg->positioning_type == 5
1068                     && ligg->MarkAttachClass < mark_lig1->ClassCount)
1069                   num_class[ligg->MarkAttachClass]++;
1070               if (ligg < gstring->glyphs)
1071                 continue;
1072               coverage_idx_lig
1073                 = get_coverage_index (&mark_lig1->LigatureCoverage,
1074                                       ligg->glyph_id);
1075               if (coverage_idx_lig < 0)
1076                 continue;
1077               mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
1078               g->MarkAttachClass = mark_record->Class;
1079               attach = (mark_lig1->LigatureArray.LigatureAttach
1080                         + coverage_idx_lig);
1081               for (j = 0; j < attach->ComponentCount; j++)
1082                 {
1083                   OTF_Anchor *lig_anchor
1084                     = attach->ComponentRecord[j].LigatureAnchor;
1085
1086                   if (lig_anchor[mark_record->Class].AnchorFormat
1087                       && num_class[mark_record->Class]-- == 0)
1088                     {
1089                       g->positioning_type = lookup_type;
1090                       g->f.f5.mark_anchor = &mark_record->MarkAnchor;
1091                       g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
1092                       if (debug_flag)
1093                         print_glyph_positioning (g, 0);
1094                       gidx++;
1095                       break;
1096                     }
1097                 }
1098             }
1099           break;
1100
1101         case 6:
1102           if (gidx < 1)
1103             continue;
1104           if (subtable->Format == 1)
1105             {
1106               OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
1107               OTF_MarkRecord *mark1_record;
1108               OTF_AnchorRecord *mark2_record;
1109               OTF_Glyph *prevg;
1110               int coverage_idx_base;
1111
1112               for (prevg = g - 1;
1113                    prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
1114                    prevg--);
1115               if (prevg < gstring->glyphs)
1116                 continue;
1117               coverage_idx_base
1118                 = get_coverage_index (&mark_mark1->Mark2Coverage,
1119                                       prevg->glyph_id);
1120               if (coverage_idx_base < 0)
1121                 continue;
1122               mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
1123               mark2_record
1124                 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
1125               g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
1126               g->f.f6.mark2_anchor
1127                 = &mark2_record->Anchor[mark1_record->Class];
1128               g->positioning_type = lookup_type;
1129               if (debug_flag)
1130                 print_glyph_positioning (g, 0);
1131               gidx++;
1132               break;
1133             }
1134           break;
1135
1136         case 7:
1137           if (subtable->Format == 1)
1138             {
1139               OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1140               OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1141               OTF_Rule *rule;
1142               int orig_used;
1143               int j, k;
1144
1145               for (j = 0; j < set->RuleCount; j++)
1146                 {
1147                   rule = set->Rule + j;
1148                   if (match_ids (gstring, gidx + 1, flag,
1149                                  rule->GlyphCount - 1, rule->Input) < 0)
1150                     continue;
1151                   orig_used = gstring->used;
1152                   for (k = 0; k < rule->LookupCount; k++)
1153                     lookup_gpos (lookup_list,
1154                                  rule->LookupRecord[k].LookupListIndex,
1155                                  gstring,
1156                                  gidx + rule->LookupRecord[k].SequenceIndex,
1157                                  accumulate);
1158                   gidx += rule->GlyphCount + (gstring->used - orig_used);
1159                   break;
1160                 }
1161             }
1162           else if (subtable->Format == 2)
1163             {
1164               OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1165               OTF_ClassSet *set;
1166               OTF_ClassRule *rule;
1167               unsigned class;
1168               int orig_used;
1169               int j, k;
1170
1171               class = get_class_def (&context2->ClassDef, g->glyph_id);
1172               set = context2->ClassSet + class;
1173               if (set)
1174                 for (j = 0; j < set->ClassRuleCnt; j++)
1175                   {
1176                     rule = set->ClassRule + j;
1177                     if (match_classes (&context2->ClassDef,
1178                                        gstring, gidx + 1, flag,
1179                                        rule->GlyphCount - 1, rule->Class)
1180                         < 0)
1181                       continue;
1182                     orig_used = gstring->used;
1183                     for (k = 0; k < rule->LookupCount; k++)
1184                       lookup_gpos (lookup_list,
1185                                    rule->LookupRecord[k].LookupListIndex,
1186                                    gstring,
1187                                    gidx + rule->LookupRecord[k].SequenceIndex,
1188                                    accumulate);
1189                     gidx += rule->GlyphCount + (gstring->used - orig_used);
1190                     break;
1191                   }
1192             }
1193           else                  /* subtable->Format == 3 */
1194             {
1195               OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1196               int orig_used;
1197               int j;
1198
1199               if (match_coverages (gstring, gidx + 1, flag,
1200                                    context3->GlyphCount - 1,
1201                                    context3->Coverage + 1) < 0)
1202                 continue;
1203               orig_used = gstring->used;
1204               for (j = 0; j < context3->LookupCount; j++)
1205                 lookup_gpos (lookup_list,
1206                              context3->LookupRecord[j].LookupListIndex,
1207                              gstring,
1208                              gidx + context3->LookupRecord[j].SequenceIndex,
1209                              accumulate);
1210               gidx += context3->GlyphCount + (gstring->used - orig_used);
1211             }
1212           break;
1213
1214         case 8:
1215           if (subtable->Format == 1)
1216             {
1217               OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1218               OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1219               int orig_used;
1220               int j, k;
1221               
1222               for (j = 0; j < set->ChainRuleCount; j++)
1223                 {
1224                   OTF_ChainRule *rule = set->ChainRule + j;
1225
1226                   if (gidx < rule->BacktrackGlyphCount
1227                       || (gidx + rule->InputGlyphCount
1228                           + rule->LookaheadGlyphCount) > gstring->used)
1229                     continue;
1230                   if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1231                     continue;
1232                   orig_used = gstring->used;
1233                   for (k = 0; k < rule->LookupCount; k++)
1234                     lookup_gpos (lookup_list,
1235                                  rule->LookupRecord[k].LookupListIndex,
1236                                  gstring,
1237                                  gidx + rule->LookupRecord[k].SequenceIndex,
1238                                  accumulate);
1239                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1240                   break;
1241                 }
1242             }
1243           else if (subtable->Format == 2)
1244             {
1245               OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1246               OTF_ChainClassSet *set;
1247               unsigned class;
1248               int j;
1249               int orig_used;
1250
1251               class = get_class_def (&context2->InputClassDef, g->glyph_id);
1252               set = context2->ChainClassSet + class;
1253               for (j = 0; j < set->ChainClassRuleCnt; j++)
1254                 {
1255                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
1256                   int k;
1257
1258                   if (gidx < rule->BacktrackGlyphCount
1259                       || (gidx + rule->InputGlyphCount
1260                           + rule->LookaheadGlyphCount) > gstring->used)
1261                     continue;
1262                   if (match_chain_classes (gstring, gidx, flag,
1263                                            &context2->BacktrackClassDef,
1264                                            &context2->InputClassDef,
1265                                            &context2->LookaheadClassDef,
1266                                            rule) < 0)
1267                     continue;
1268                   orig_used = gstring->used;
1269                   for (k = 0; k < rule->LookupCount; k++)
1270                     lookup_gpos (lookup_list,
1271                                  rule->LookupRecord[k].LookupListIndex,
1272                                  gstring,
1273                                  gidx + rule->LookupRecord[k].SequenceIndex,
1274                                  accumulate);
1275                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1276                   break;
1277                 }
1278             }
1279           else if (subtable->Format == 3)
1280             {
1281               OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1282               int orig_used;
1283               int j;
1284
1285               if (gidx < context3->BacktrackGlyphCount
1286                   || (gidx + context3->InputGlyphCount
1287                       + context3->LookaheadGlyphCount) > gstring->used)
1288                 continue;
1289               if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1290                 continue;
1291               orig_used = gstring->used;
1292               for (j = 0; j < context3->LookupCount; j++)
1293                 lookup_gpos (lookup_list,
1294                              context3->LookupRecord[j].LookupListIndex,
1295                              gstring,
1296                              gidx + context3->LookupRecord[j].SequenceIndex,
1297                              accumulate);
1298               gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1299             }
1300           else
1301             OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1302           break;
1303
1304         default:
1305           continue;
1306         }
1307     }
1308   if (gidx == orig_gidx)
1309     {
1310       if (debug_flag)
1311         fprintf (stderr, " no match\n");
1312       gidx++;
1313     }
1314   else if (debug_flag)
1315     fprintf (stderr, "\n");
1316   return gidx;
1317 }
1318
1319 static unsigned
1320 lookup_encoding_0 (int c, OTF_EncodingSubtable *sub)
1321 {
1322   return ((c < 0 || c >= 256)
1323           ? 0
1324           : sub->f.f0->glyphIdArray[c]);
1325 }
1326
1327 static unsigned
1328 lookup_encoding_2 (int c, OTF_EncodingSubtable *sub)
1329 {
1330   return 0;
1331 }
1332
1333 static unsigned
1334 lookup_encoding_4 (int c, OTF_EncodingSubtable *sub)
1335 {
1336   int segCount, i;
1337   OTF_EncodingSubtable4 *sub4;
1338
1339   if (c < 0)
1340     return 0;
1341   sub4 = sub->f.f4;
1342   segCount = sub4->segCountX2 / 2;
1343   for (i = 0; i < segCount; i++)
1344     {
1345       OTF_cmapSegment *seg = sub4->segments + i;
1346
1347       if (c >= seg->startCount && c <= seg->endCount)
1348         {
1349           if (seg->idRangeOffset == 0xFFFF)
1350             return c + seg->idDelta;
1351           else
1352             return sub4->glyphIdArray[seg->idRangeOffset
1353                                       + (c - seg->startCount)];
1354         }
1355     }
1356   return 0;
1357 }
1358
1359 static unsigned
1360 lookup_encoding_6 (int c, OTF_EncodingSubtable *sub)
1361 {
1362   return 0;
1363 }
1364
1365 static unsigned
1366 lookup_encoding_8 (int c, OTF_EncodingSubtable *sub)
1367 {
1368   return 0;
1369 }
1370
1371 static unsigned
1372 lookup_encoding_10 (int c, OTF_EncodingSubtable *sub)
1373 {
1374   return 0;
1375 }
1376
1377 static unsigned
1378 lookup_encoding_12 (int c, OTF_EncodingSubtable *sub)
1379 {
1380   OTF_EncodingSubtable12 *sub12;
1381   OTF_cmapGroup *g, *gend;
1382
1383   if (c < 0)
1384     return 0;
1385   sub12 = sub->f.f12;
1386   g = sub12->Groups;
1387   gend = sub12->Groups + sub12->nGroups;
1388   while (g < gend)
1389     {
1390       if (g->startCharCode <= c && c <= g->endCharCode)
1391         return (g->startGlyphID + (c - g->startCharCode));
1392       g++;
1393     }
1394   return 0;
1395 }
1396
1397 typedef unsigned (*lookup_cmap_func) (int, OTF_EncodingSubtable *);
1398
1399 static lookup_cmap_func lookup_cmap_func_table[] =
1400   {
1401     lookup_encoding_0, lookup_encoding_2, lookup_encoding_4, lookup_encoding_6,
1402     lookup_encoding_8, lookup_encoding_10, lookup_encoding_12
1403   };
1404
1405 static unsigned
1406 get_GlyphID (OTF_cmap *cmap, int c)
1407 {
1408   OTF_EncodingSubtable *sub;
1409   lookup_cmap_func lookupper;
1410
1411   if (c < 0x10000 && cmap->unicode_table)
1412     return cmap->unicode_table[c];
1413   if (cmap->table_index < 0)
1414     return 0;
1415   sub = &cmap->EncodingRecord[cmap->table_index].subtable;
1416   lookupper = lookup_cmap_func_table[sub->format / 2];
1417   return lookupper (c, sub);
1418 }
1419
1420 static OTF_GlyphID
1421 get_uvs_glyph (OTF_cmap *cmap, OTF_EncodingSubtable14 *sub14, int c1, int c2)
1422 {
1423   unsigned nRecords = sub14->nRecords;
1424   OTF_VariationSelectorRecord *record;
1425   unsigned i;
1426
1427   for (i = 0; i < nRecords; i++)
1428     {
1429       record = &sub14->Records[i];
1430       if (record->varSelector == c2)
1431         {
1432           if (record->defaultUVSOffset)
1433             {
1434               OTF_UnicodeValueRange *uVRs = record->unicodeValueRanges;
1435               unsigned numUVRs = record->numUnicodeValueRanges;
1436               unsigned top = numUVRs, bottom = 0, middle;
1437
1438               if (uVRs[0].startUnicodeValue <= c1)
1439                 {
1440                   unsigned additionalCount, startUnicodeValue;
1441
1442                   for (;;)
1443                     {
1444                       middle = (top + bottom) / 2;
1445                       if (c1 < uVRs[middle].startUnicodeValue)
1446                         top = middle;
1447                       else if (bottom == middle)
1448                         break;
1449                       else
1450                         bottom = middle;
1451                     }
1452                   startUnicodeValue = uVRs[bottom].startUnicodeValue;
1453                   additionalCount = uVRs[bottom].additionalCount;
1454                   if (c1 <= startUnicodeValue + additionalCount)
1455                     return get_GlyphID (cmap, c1);
1456                 }
1457             }
1458           if (record->nonDefaultUVSOffset)
1459             {
1460               OTF_UVSMapping *uvsMappings = record->uvsMappings;
1461               unsigned numUVSMs = record->numUVSMappings;
1462               unsigned top = numUVSMs, bottom = 0, middle;
1463
1464               if (uvsMappings[0].unicodeValue <= c1)
1465                 {
1466                   for (;;)
1467                     {
1468                       middle = (top + bottom) / 2;
1469                       if (c1 < uvsMappings[middle].unicodeValue)
1470                         top = middle;
1471                       else if (bottom == middle)
1472                         break;
1473                       else
1474                         bottom = middle;
1475                     }
1476                   if (uvsMappings[bottom].unicodeValue == c1)
1477                     return uvsMappings[bottom].glyphID;
1478                 }
1479             }
1480           return 0;
1481         }
1482     }
1483   return 0;
1484 }
1485
1486 static void
1487 check_cmap_uvs (OTF_cmap *cmap, OTF_GlyphString *gstring, int idx)
1488 {  
1489   OTF_EncodingSubtable14 *sub14;
1490   int c1 = gstring->glyphs[idx - 1].c;
1491   int c2 = gstring->glyphs[idx].c;
1492   OTF_GlyphID code;
1493   int i;
1494
1495   gstring->glyphs[idx].glyph_id = 0;
1496   for (i = 0; i < cmap->numTables; i++)
1497     if (cmap->EncodingRecord[i].subtable.format == 14)
1498       break;
1499   if (i == cmap->numTables)
1500     return;
1501   code = get_uvs_glyph (cmap, cmap->EncodingRecord[i].subtable.f.f14, c1, c2);
1502   if (code == 0)
1503     return;
1504   gstring->glyphs[idx - 1].glyph_id = code;
1505   gstring->glyphs[idx - 1].f.index.to = gstring->glyphs[idx].f.index.to;
1506   gstring->used--;
1507   memmove (gstring->glyphs + idx, gstring->glyphs + idx + 1,
1508            sizeof (OTF_Glyph) * (gstring->used - idx));
1509 }
1510
1511 \f
1512
1513 /* GDEF */
1514 /* Table of GlyphClass and MarkAttackClass.
1515
1516    For the Nth element CHAR, CHAR and the succeeding characters
1517    (before CHAR of the next element) has GlyphClass C (= (N % 2) ? 3 : 1).
1518
1519    This table is generated from the General Category (GC) property of
1520    characters defined in the Unicode Character Database.  */
1521
1522 static int glyph_class_table[] =
1523   { 0x00000, 0x00300, 0x00370, 0x00483, 0x00487, 0x00488, 0x0048A, 0x00591,
1524     0x005BE, 0x005BF, 0x005C0, 0x005C1, 0x005C3, 0x005C4, 0x005C6, 0x005C7,
1525     0x005C8, 0x00610, 0x00616, 0x0064B, 0x0065F, 0x00670, 0x00671, 0x006D6,
1526     0x006DD, 0x006DE, 0x006E5, 0x006E7, 0x006E9, 0x006EA, 0x006EE, 0x00711,
1527     0x00712, 0x00730, 0x0074B, 0x007A6, 0x007B1, 0x007EB, 0x007F4, 0x00901,
1528     0x00904, 0x0093C, 0x0093D, 0x0093E, 0x0094E, 0x00951, 0x00955, 0x00962,
1529     0x00964, 0x00981, 0x00984, 0x009BC, 0x009BD, 0x009BE, 0x009C5, 0x009C7,
1530     0x009CE, 0x009D7, 0x009D8, 0x009E2, 0x009E4, 0x00A01, 0x00A04, 0x00A3C,
1531     0x00A3D, 0x00A3E, 0x00A4E, 0x00A70, 0x00A72, 0x00A81, 0x00A84, 0x00ABC,
1532     0x00ABD, 0x00ABE, 0x00ACE, 0x00AE2, 0x00AE4, 0x00B01, 0x00B04, 0x00B3C,
1533     0x00B3D, 0x00B3E, 0x00B44, 0x00B47, 0x00B58, 0x00B82, 0x00B83, 0x00BBE,
1534     0x00BCE, 0x00BD7, 0x00BD8, 0x00C01, 0x00C04, 0x00C3E, 0x00C45, 0x00C46,
1535     0x00C57, 0x00C82, 0x00C84, 0x00CBC, 0x00CBD, 0x00CBE, 0x00CC5, 0x00CC6,
1536     0x00CCE, 0x00CD5, 0x00CD7, 0x00CE2, 0x00CE4, 0x00D02, 0x00D04, 0x00D3E,
1537     0x00D44, 0x00D46, 0x00D4E, 0x00D57, 0x00D58, 0x00D82, 0x00D84, 0x00DCA,
1538     0x00DCB, 0x00DCF, 0x00DD7, 0x00DD8, 0x00DF4, 0x00E31, 0x00E32, 0x00E34,
1539     0x00E3B, 0x00E47, 0x00E4F, 0x00EB1, 0x00EB2, 0x00EB4, 0x00EBD, 0x00EC8,
1540     0x00ECE, 0x00F18, 0x00F1A, 0x00F35, 0x00F36, 0x00F37, 0x00F38, 0x00F39,
1541     0x00F3A, 0x00F3E, 0x00F40, 0x00F71, 0x00F85, 0x00F86, 0x00F88, 0x00F90,
1542     0x00FBD, 0x00FC6, 0x00FC7, 0x0102C, 0x0103A, 0x01056, 0x0105A, 0x0135F,
1543     0x01360, 0x01712, 0x01715, 0x01732, 0x01735, 0x01752, 0x01754, 0x01772,
1544     0x01774, 0x017B6, 0x017D4, 0x017DD, 0x017DE, 0x0180B, 0x0180E, 0x018A9,
1545     0x018AA, 0x01920, 0x0193C, 0x019B0, 0x019C1, 0x019C8, 0x019CA, 0x01A17,
1546     0x01A1C, 0x01B00, 0x01B05, 0x01B34, 0x01B45, 0x01B6B, 0x01B74, 0x01DC0,
1547     0x01E00, 0x020D0, 0x020F0, 0x0302A, 0x03030, 0x03099, 0x0309B, 0x0A802,
1548     0x0A803, 0x0A806, 0x0A807, 0x0A80B, 0x0A80C, 0x0A823, 0x0A828, 0x0FB1E,
1549     0x0FB1F, 0x0FE00, 0x0FE10, 0x0FE20, 0x0FE24, 0x10A01, 0x10A10, 0x10A38,
1550     0x10A40, 0x1D165, 0x1D16A, 0x1D16D, 0x1D173, 0x1D17B, 0x1D183, 0x1D185,
1551     0x1D18C, 0x1D1AA, 0x1D1AE, 0x1D242, 0x1D245, 0xE0100, 0xE01F0 };
1552
1553 static int get_class_def_auto (int c)
1554 {
1555   static int table_size
1556     = sizeof glyph_class_table / sizeof glyph_class_table[0];
1557   int low, high, mid;
1558
1559   if (c >= glyph_class_table[table_size - 1])
1560     return 0;
1561   low = 0;
1562   high = table_size - 1;
1563   while (1)
1564     {
1565       mid = (low + high) / 2;
1566       if (c < glyph_class_table[mid])
1567         high = mid - 1;
1568       else if (c >= glyph_class_table[mid + 1])
1569         low = mid + 1;
1570       else
1571         break;
1572     }
1573   return ((mid % 2) ? 3 : 1);
1574 }
1575
1576 \f
1577
1578 /* API */
1579
1580 #define UVS_P(C)        \
1581   (((C) >= 0xFE00 && (C) <= 0xFE0F) || ((C) >= 0xE0100 && (C) <= 0xE01EF))
1582
1583 int
1584 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1585 {
1586   OTF_cmap *cmap;
1587   int i;
1588   OTF_EncodingSubtable *sub;
1589   lookup_cmap_func lookupper;
1590
1591   if (! otf->cmap
1592       && OTF_get_table (otf, "cmap") < 0)
1593     return -1;
1594
1595   cmap = otf->cmap;
1596   if (cmap->table_index < 0)
1597     lookupper = NULL;
1598   else
1599     {
1600       sub = &cmap->EncodingRecord[cmap->table_index].subtable;
1601       lookupper = lookup_cmap_func_table[sub->format / 2];
1602     }
1603   for (i = 0; i < gstring->used; i++)
1604     if (! gstring->glyphs[i].glyph_id)
1605       {
1606         int c = gstring->glyphs[i].c;
1607         if (c < 32 || ! cmap->unicode_table)
1608           gstring->glyphs[i].glyph_id = 0;
1609         else if (UVS_P (c) && i > 0)
1610           check_cmap_uvs (cmap, gstring, i);
1611         else if (c < 0x10000)
1612           gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1613         else if (lookupper)
1614           gstring->glyphs[i].glyph_id = lookupper (c, sub);
1615       }
1616   return 0;
1617 }
1618
1619
1620 int
1621 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1622                  int platform_id, int encoding_id)
1623 {
1624   OTF_cmap *cmap;
1625   int i;
1626   char *errfmt = "CMAP Looking up%s";
1627   int errret = -1;
1628   OTF_EncodingRecord *enc;
1629   lookup_cmap_func lookupper;
1630
1631   if (! otf->cmap
1632       && OTF_get_table (otf, "cmap") < 0)
1633     return -1;
1634
1635   cmap = otf->cmap;
1636   for (i = 0; i < cmap->numTables; i++)
1637     if (cmap->EncodingRecord[i].platformID == platform_id
1638         && cmap->EncodingRecord[i].encodingID == encoding_id)
1639       break;
1640   if (i == cmap->numTables)
1641     OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1642   enc = cmap->EncodingRecord + i;
1643   if (enc->subtable.format > 12)
1644     OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1645   lookupper = lookup_cmap_func_table[enc->subtable.format / 2];
1646
1647   for (i = 0; i < gstring->used; i++)
1648     if (! gstring->glyphs[i].glyph_id)
1649       {
1650         int c = gstring->glyphs[i].c;
1651         if (c < 32 || ! cmap->unicode_table)
1652           gstring->glyphs[i].glyph_id = 0;
1653         else if (UVS_P (c) && i > 0)
1654           check_cmap_uvs (cmap, gstring, i);
1655         else if (c < 0x10000)
1656           gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1657         else
1658           gstring->glyphs[i].glyph_id = lookupper (c, &enc->subtable);
1659       }
1660 }
1661
1662
1663 int
1664 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1665 {
1666   if (! otf->cmap
1667       && OTF_get_table (otf, "cmap") < 0)
1668     return 0;
1669   if (code == 0
1670       || code > otf->cmap->max_glyph_id
1671       || ! otf->cmap->decode_table)
1672     return 0;
1673   return otf->cmap->decode_table[code];
1674 }
1675
1676 int
1677 OTF_get_variation_glyphs (OTF *otf, int c, OTF_GlyphID code[256])
1678 {
1679   int i, n;
1680   OTF_cmap *cmap;
1681   OTF_EncodingSubtable14 *sub14;
1682
1683   memset (code, 0, sizeof (OTF_GlyphID) * 256);
1684   if (! otf->cmap
1685       && OTF_get_table (otf, "cmap") < 0)
1686     return 0;
1687   cmap = otf->cmap;
1688   for (i = 0; i < cmap->numTables; i++)
1689     if (cmap->EncodingRecord[i].subtable.format == 14)
1690       break;
1691   if (i == cmap->numTables)
1692     return 0;
1693   sub14 = cmap->EncodingRecord[i].subtable.f.f14;
1694   for (i = 0, n = 0; i < 256; i++)
1695     {
1696       int uvs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
1697
1698       if ((code[i] = get_uvs_glyph (cmap, sub14, c, uvs)))
1699         n++;
1700     }
1701   return n;
1702 }
1703
1704
1705 int
1706 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1707 {
1708   OTF_GDEF *gdef;
1709   int i;
1710
1711   if (! otf->gdef
1712       && OTF_get_table (otf, "GDEF") < 0)
1713     return -1;
1714   gdef = otf->gdef;
1715
1716   if (gdef->glyph_class_def.offset)
1717     for (i = 0; i < gstring->used; i++)
1718       gstring->glyphs[i].GlyphClass
1719         = get_class_def (&gdef->glyph_class_def,
1720                          gstring->glyphs[i].glyph_id);
1721   else
1722     for (i = 0; i < gstring->used; i++)
1723       gstring->glyphs[i].GlyphClass
1724         = get_class_def_auto (gstring->glyphs[i].c);
1725
1726   if (gdef->mark_attach_class_def.offset)
1727     for (i = 0; i < gstring->used; i++)
1728       gstring->glyphs[i].MarkAttachClass
1729         = get_class_def (&gdef->mark_attach_class_def,
1730                          gstring->glyphs[i].glyph_id);
1731
1732   return 0;
1733 }
1734
1735 static int
1736 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1737                          const char *script, const char *language,
1738                          const char *features,
1739                          int alternate_subst)
1740 {
1741   char *errfmt = "GSUB driving%s";
1742   int errret = -1;
1743   OTF_GSUB *gsub;
1744   OTF_LangSys *LangSys;
1745   char *lookup_flags;
1746   int i;
1747
1748   for (i = 0; i < gstring->used; i++)
1749     {
1750       gstring->glyphs[i].positioning_type = 0;
1751       gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1752     }
1753
1754   if (OTF_get_table (otf, "GSUB") < 0)
1755     return errret;
1756   gsub = otf->gsub;
1757   if (gsub->FeatureList.FeatureCount == 0
1758       || gsub->LookupList.LookupCount == 0)
1759     return 0;
1760
1761   LangSys = get_langsys (&gsub->ScriptList, script, language);
1762   if (! LangSys)
1763     return errret;
1764
1765   lookup_flags = alloca (gsub->LookupList.LookupCount);
1766   if (! lookup_flags
1767       || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, LangSys,
1768                              features, lookup_flags) < 0)
1769     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1770
1771   for (i = 0; i < gsub->LookupList.LookupCount; i++)
1772     {
1773       int gidx;
1774
1775       if (! lookup_flags[i]) continue;
1776
1777       if (gsub->LookupList.Lookup[i].LookupType != 8)
1778         {
1779           gidx = 0;
1780           while (gidx < gstring->used)
1781             {
1782               gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1783                                   alternate_subst);
1784               if (gidx < 0)
1785                 return errret;
1786             }
1787         }
1788       else
1789         {
1790           gidx = gstring->used - 1;
1791           while (gidx >= 0)
1792             {
1793               gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1794                                   alternate_subst);
1795               if (gidx < 0)
1796                 return errret;
1797             }
1798         }
1799     }
1800
1801   return 0;
1802 }
1803
1804 int
1805 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1806                 const char *script, const char *language, const char *features)
1807 {
1808   if (! otf->cmap)
1809     OTF_get_table (otf, "cmap");
1810   return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1811 }
1812
1813 int
1814 OTF_drive_gpos_internal (OTF *otf, OTF_GlyphString *gstring,
1815                          const char *script, const char *language,
1816                          const char *features,
1817                          int accumulate)
1818 {
1819   char *errfmt = "GPOS driving%s";
1820   int errret = -1;
1821   OTF_GPOS *gpos;
1822   OTF_LangSys *LangSys;
1823   char *lookup_flags;
1824   int i, n;
1825
1826   for (i = 0; i < gstring->used; i++)
1827     gstring->glyphs[i].positioning_type = 0;
1828
1829   if (OTF_get_table (otf, "GPOS") < 0)
1830     return errret;
1831   gpos = otf->gpos;
1832   if (gpos->FeatureList.FeatureCount == 0
1833       || gpos->LookupList.LookupCount == 0)
1834     return 0;
1835
1836   LangSys = get_langsys (&gpos->ScriptList, script, language);
1837   if (! LangSys)
1838     return errret;
1839
1840   lookup_flags = alloca (gpos->LookupList.LookupCount);
1841   if (! lookup_flags
1842       || setup_lookup_flags (&gpos->LookupList, &gpos->FeatureList, LangSys,
1843                              features, lookup_flags) < 0)
1844     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1845
1846   for (i = 0; i < gpos->LookupList.LookupCount; i++)
1847     {
1848       int gidx = 0;
1849
1850       if (! lookup_flags[i]) continue;
1851
1852       while (gidx < gstring->used)
1853         {
1854           gidx = lookup_gpos (&gpos->LookupList, i, gstring, gidx, accumulate);
1855           if (gidx < 0)
1856             return errret;
1857         }
1858     }
1859
1860   return 0;
1861 }
1862
1863 int
1864 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1865                 const char *script, const char *language, const char *features)
1866 {
1867   if (! otf->cmap)
1868     OTF_get_table (otf, "cmap");
1869   return OTF_drive_gpos_internal (otf, gstring, script, language, features, 0);
1870 }
1871
1872 int
1873 OTF_drive_gpos2 (OTF *otf, OTF_GlyphString *gstring,
1874                 const char *script, const char *language, const char *features)
1875 {
1876   if (! otf->cmap)
1877     OTF_get_table (otf, "cmap");
1878   return OTF_drive_gpos_internal (otf, gstring, script, language, features, 1);
1879 }
1880
1881 int
1882 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1883                   const char *script, const char *language,
1884                   const char *gsub_features, const char *gpos_features)
1885 {
1886   if (OTF_drive_cmap (otf, gstring) < 0)
1887     return -1;
1888   if (OTF_drive_gdef (otf, gstring) < 0)
1889     return -1;
1890   if (gsub_features
1891       && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1892     return -1;
1893   if (gpos_features
1894       && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1895     return -1;
1896   return 0;
1897 }
1898
1899 int
1900 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1901                           const char *script, const char *language,
1902                           const char *features)
1903 {
1904   return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);
1905 }
1906
1907 static int
1908 iterate_coverage (OTF *otf, const char *feature, 
1909                   OTF_Feature_Callback callback,
1910                   OTF_Coverage *coverage)
1911 {
1912   int i;
1913
1914   if (coverage->CoverageFormat == 1)
1915     {
1916       for (i = 0; i < coverage->Count; i++)
1917         if (callback (otf, feature, coverage->table.GlyphArray[i]) < 0)
1918           return -1;
1919     }
1920   else
1921     {
1922       for (i = 0; i < coverage->Count; i++)
1923         {
1924           OTF_RangeRecord *range = coverage->table.RangeRecord + i;
1925           unsigned id;
1926           for (id = range->Start; id <= range->End; id++)
1927             if (callback (otf, feature, id) < 0)
1928               return -1;
1929         }
1930     }
1931   return 0;
1932 }
1933
1934 static int
1935 iterate_feature (OTF *otf, const char *feature,
1936                  OTF_Feature_Callback callback,
1937                  OTF_Lookup *lookup)
1938 {
1939   int i, j, k, l;
1940
1941   for (i = 0; i < lookup->SubTableCount; i++)
1942     {
1943       unsigned lookup_type = lookup->LookupType;
1944       OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
1945
1946       if (lookup_type == 7)
1947         {
1948           OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
1949
1950           lookup_type = extension1->ExtensionLookupType;
1951           subtable = extension1->ExtensionSubtable;
1952         }
1953
1954       if ((lookup_type >= 1 && lookup_type <= 3) || lookup_type == 8)
1955         {
1956           if (iterate_coverage (otf, feature, callback, &subtable->Coverage)
1957               < 0)
1958             return -1;
1959         }
1960       else if (lookup_type == 4)
1961         {
1962           OTF_GSUB_Ligature1 *lig1;
1963
1964           if (iterate_coverage (otf, feature, callback, &subtable->Coverage)
1965               < 0)
1966             return -1;
1967           lig1 = &subtable->u.ligature1;
1968           for (j = 0; j < lig1->LigSetCount; j++)
1969             {
1970               OTF_LigatureSet *ligset = lig1->LigatureSet + j;
1971
1972               for (k = 0; k < ligset->LigatureCount; k++)
1973                 {
1974                   OTF_Ligature *lig = ligset->Ligature + k;
1975                   for (l = 0; l < lig->CompCount - 1; l++)
1976                     if (callback (otf, feature, lig->Component[l]) < 0)
1977                       return -1;
1978                 }
1979             }
1980         }
1981       else if (lookup_type == 6)
1982         {
1983           if (subtable->Format == 1)
1984             {
1985               OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
1986               for (j = 0; j < context1->ChainRuleSetCount; j++)
1987                 {
1988                   OTF_ChainRuleSet *set = context1->ChainRuleSet + j;
1989                   for (k = 0; k < set->ChainRuleCount; k++)
1990                     {
1991                       OTF_ChainRule *rule = set->ChainRule + k;
1992                       for (l = 0; l < rule->LookupCount; l++)
1993                         {
1994                           OTF_Lookup *lkup
1995                             = (otf->gsub->LookupList.Lookup
1996                                + rule->LookupRecord[l].LookupListIndex);
1997                           if (iterate_feature (otf, feature, callback, lkup)
1998                               < 0)
1999                             return -1;
2000                         }
2001                     }
2002                 }
2003             }
2004           else if (subtable->Format == 2)
2005             {
2006               OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
2007
2008               for (j = 0; j < context2->ChainClassSetCnt; j++)
2009                 {
2010                   OTF_ChainClassSet *set = context2->ChainClassSet + j;
2011                   for (k = 0; k < set->ChainClassRuleCnt; j++)
2012                     {
2013                       OTF_ChainClassRule *rule = set->ChainClassRule + k;
2014
2015                       for (l = 0; l < rule->LookupCount; l++)
2016                         {
2017                           OTF_Lookup *lkup
2018                             = (otf->gsub->LookupList.Lookup
2019                                + rule->LookupRecord[k].LookupListIndex);
2020                           if (iterate_feature (otf, feature, callback, lkup)
2021                               < 0)
2022                             return -1;
2023                         }
2024                     }
2025                 }
2026             }
2027           else
2028             {
2029               OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
2030               for (j = 0; j < context3->LookupCount; j++)
2031                 {
2032                   OTF_Lookup *lkup
2033                     = (otf->gsub->LookupList.Lookup
2034                        + context3->LookupRecord[j].LookupListIndex);
2035                   if (iterate_feature (otf, feature, callback, lkup) < 0)
2036                     return -1;
2037                 }
2038             }
2039         }
2040     }
2041   return 0;
2042 }
2043
2044 int
2045 OTF_iterate_gsub_feature (OTF *otf, OTF_Feature_Callback callback,
2046                           const char *script, const char *language,
2047                           const char *feature)
2048 {
2049   char *errfmt = "GSUB iterate feature%s";
2050   int errret = -1;
2051   int i;
2052
2053   OTF_GSUB *gsub;
2054   OTF_LangSys *langsys;
2055   char *lookup_flags;
2056
2057   if (OTF_get_table (otf, "GSUB") < 0)
2058     return errret;
2059   gsub = otf->gsub;
2060   if (gsub->FeatureList.FeatureCount == 0
2061       || gsub->LookupList.LookupCount == 0)
2062     return 0;
2063   langsys = get_langsys (&gsub->ScriptList, script, language);
2064   if (! langsys)
2065     return errret;
2066   lookup_flags = alloca (gsub->LookupList.LookupCount);
2067   if (! lookup_flags
2068       || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, langsys,
2069                              feature, lookup_flags) < 0)
2070     OTF_ERROR (OTF_ERROR_MEMORY, " feature");
2071
2072   for (i = 0; i < gsub->LookupList.LookupCount; i++)
2073     if (lookup_flags[i])
2074       if (iterate_feature (otf, feature, callback, gsub->LookupList.Lookup + i)
2075           < 0)
2076         return -1;
2077   return 0;
2078 }