(print_anchor, print_glyph_positioning): New functions.
[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 unsigned
742 get_anchor (OTF_Anchor *anchor, OTF_ValueRecord *rec)
743 {
744   unsigned value_format = OTF_XPlacement | OTF_YPlacement;
745
746   rec->XPlacement = anchor->XCoordinate;
747   rec->YPlacement = anchor->YCoordinate;
748   if (anchor->AnchorFormat == 1)
749     /* Nothing to do */
750     ;
751   else if (anchor->AnchorFormat == 2)
752     /* Not yet implemented */
753     ;
754   else if (anchor->AnchorFormat == 3)
755     /* Not yet implemented */
756     ;
757   return value_format;
758 }
759
760 static int
761 gstring_insert_for_gpos (OTF_GlyphString *gstring, int gidx)
762 {
763   int errret = -1;
764   int orig_gidx = gidx++;
765
766   while (gidx < gstring->used
767          && ! gstring->glyphs[gidx].glyph_id
768          && gstring->glyphs[gidx].positioning_type)
769     gidx++;
770   GSTRING_INSERT (gstring, gidx, 1);
771   gstring->glyphs[gidx] = gstring->glyphs[orig_gidx];
772   gstring->glyphs[gidx].glyph_id = 0;
773   return gidx;
774 }
775
776 static void
777 print_anchor (char *head, OTF_Anchor *anchor)
778 {
779   if (anchor->AnchorFormat == 1)
780     fprintf (stderr, " %s(X:%d Y:%d)", head,
781              anchor->XCoordinate, anchor->YCoordinate);
782   else if (anchor->AnchorFormat == 2)
783     fprintf (stderr, " %s(X:%d Y:%d AP:%d)", head,
784              anchor->XCoordinate, anchor->YCoordinate,
785              anchor->f.f1.AnchorPoint);
786   else
787     fprintf (stderr, " %s(X:%d Y:%d +alpha)", head,
788              anchor->XCoordinate, anchor->YCoordinate);
789 }
790
791 static void
792 print_glyph_positioning (OTF_Glyph *g, int type)
793 {
794   if (type)
795     fprintf (stderr, " %0X=", g->glyph_id);
796   switch (g->positioning_type)
797     {
798     case 1: case 2:
799       {
800         int format = g->f.f1.format;
801
802         if (format & OTF_XPlacement)
803           fprintf (stderr, "X:%d", g->f.f1.value->XPlacement);
804         if (format & OTF_XPlaDevice)
805           fprintf (stderr, "+alpha");
806         if (format & OTF_YPlacement)
807           fprintf (stderr, "Y:%d", g->f.f1.value->YPlacement);
808         if (format & OTF_YPlaDevice)
809           fprintf (stderr, "+alpha");
810         if (format & OTF_XAdvance)
811           fprintf (stderr, "X+:%d", g->f.f1.value->XAdvance);
812         if (format & OTF_XAdvDevice)
813           fprintf (stderr, "+alpha");
814         break;
815       }
816     case 3:
817       print_anchor ("entry", g->f.f3.entry_anchor);
818       print_anchor ("exit", g->f.f3.entry_anchor);
819       break;
820     case 4:
821       print_anchor ("mark", g->f.f4.mark_anchor);
822       print_anchor ("base", g->f.f4.base_anchor);
823       break;
824     case 5:
825       print_anchor ("mark", g->f.f5.mark_anchor);
826       print_anchor ("lig", g->f.f5.ligature_anchor);
827       break;
828     case 6:
829       print_anchor ("mark1", g->f.f6.mark1_anchor);
830       print_anchor ("mark2", g->f.f6.mark2_anchor);
831       break;
832     }
833 }
834
835 static int
836 lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index,
837              OTF_GlyphString *gstring, int gidx, int accumulate)
838 {
839   char *errfmt = "GPOS Looking up%s";
840   int errret = -1;
841   OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index;
842   unsigned int flag = (lookup->LookupFlag
843                        & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType));
844   int orig_gidx = gidx;
845   OTF_Glyph *g = gstring->glyphs + gidx;
846   int i;
847
848   if (debug_flag)
849     fprintf (stderr, "[GPOS] glyph:%04X lookup:%02d",
850              g->glyph_id, lookup_list_index);
851   if (IGNORED_GLYPH (g, flag))
852     {
853       if (debug_flag)
854         fprintf (stderr, " glyph ignored\n");
855       return (gidx + 1);
856     }
857
858   /* Try all subtables until one of them handles the current glyph.  */
859   for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++)
860     {
861       unsigned lookup_type = lookup->LookupType;
862       OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i;
863       int coverage_idx;
864       int positioning_type;
865       enum OTF_ValueFormat format;
866       OTF_ValueRecord *value;
867       OTF_Anchor *anchor1, *anchor2;
868
869       if (lookup_type == 9)
870         {
871           OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1;
872
873           lookup_type = extension1->ExtensionLookupType;
874           subtable = extension1->ExtensionSubtable;
875         }
876
877       if (debug_flag)
878         fprintf (stderr, "/%d", lookup_type);
879       if (subtable->Coverage.offset)
880         {
881           coverage_idx = get_coverage_index (&subtable->Coverage,
882                                              g->glyph_id);
883           if (coverage_idx < 0)
884             continue;
885         }
886
887       switch (lookup_type)
888         {
889         case 1:
890           positioning_type = lookup_type;
891           if (subtable->Format == 1)
892             {
893               OTF_GPOS_Single1 *single1 = &subtable->u.single1;
894
895               format = single1->ValueFormat;
896               value = &single1->Value;
897             }
898           else if (subtable->Format == 2)
899             {
900               OTF_GPOS_Single2 *single2 = &subtable->u.single2;
901
902               format = single2->ValueFormat;
903               value = single2->Value + coverage_idx;
904             }
905           if (accumulate && g->positioning_type)
906             {
907               gidx = gstring_insert_for_gpos (gstring, gidx);         
908               g = gstring->glyphs + gidx;
909             }
910           g->positioning_type = positioning_type;
911           g->f.f1.format = format;
912           g->f.f1.value = value;
913           if (debug_flag)
914             print_glyph_positioning (g, 0);
915           gidx++;
916           break;
917
918         case 2:
919           {
920             int next_gidx;
921             OTF_Glyph *nextg;
922
923             for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx;
924                  next_gidx < gstring->used && IGNORED_GLYPH (nextg, flag);
925                  next_gidx++, nextg++);
926
927             if (next_gidx >= gstring->used)
928               continue;
929             if (subtable->Format == 1)
930               {
931                 OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1;
932                 OTF_PairSet *set = pair1->PairSet + coverage_idx;
933                 int j;
934
935                 for (j = 0; j < set->PairValueCount; j++)
936                   if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id)
937                     {
938                       if (pair1->ValueFormat1)
939                         {
940                           if (accumulate && g->positioning_type)
941                             {
942                               gidx = gstring_insert_for_gpos (gstring, gidx);
943                               g = gstring->glyphs + gidx;
944                               next_gidx += gidx - orig_gidx;
945                               nextg = gstring->glyphs + next_gidx;
946                             }
947                           g->positioning_type = lookup_type;
948                           g->f.f2.format = pair1->ValueFormat1;
949                           g->f.f2.value = &set->PairValueRecord[j].Value1;
950                           if (debug_flag)
951                             print_glyph_positioning (g, 1);
952                         }
953                       gidx = next_gidx;
954                       g = nextg;
955                       if (pair1->ValueFormat2)
956                         {
957                           if (accumulate && g->positioning_type)
958                             {
959                               gidx = gstring_insert_for_gpos (gstring, gidx);
960                               g = gstring->glyphs + gidx;
961                             }
962                           g->positioning_type = lookup_type;
963                           g->f.f2.format = pair1->ValueFormat2;
964                           g->f.f2.value = &set->PairValueRecord[j].Value2;
965                           if (debug_flag)
966                             print_glyph_positioning (g, 2);
967                         }
968                       break;
969                     }
970               }
971             else if (subtable->Format == 2)
972               {
973                 OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2;
974                 unsigned class1, class2;
975
976                 class1 = get_class_def (&pair2->ClassDef1, g->glyph_id);
977                 class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id);
978                 if (pair2->ValueFormat1)
979                   {
980                     if (accumulate && g->positioning_type)
981                       {
982                         gidx = gstring_insert_for_gpos (gstring, gidx);
983                         g = gstring->glyphs + gidx;
984                         next_gidx += gidx - orig_gidx;
985                         nextg = gstring->glyphs + next_gidx;
986                       }
987                     g->positioning_type = lookup_type;
988                     g->f.f2.format = pair2->ValueFormat1;
989                     g->f.f2.value
990                       = &pair2->Class1Record[class1].Class2Record[class2].Value1;
991                     if (debug_flag)
992                       print_glyph_positioning (g, 1);
993                   }
994                 gidx = next_gidx;
995                 g = nextg;
996                 if (pair2->ValueFormat2)
997                   {
998                     if (accumulate && g->positioning_type)
999                       {
1000                         gidx = gstring_insert_for_gpos (gstring, gidx);
1001                         g = gstring->glyphs + gidx;
1002                       }
1003                     g->positioning_type = lookup_type;
1004                     g->f.f2.format = pair2->ValueFormat2;
1005                     g->f.f2.value
1006                       = &pair2->Class1Record[class1].Class2Record[class2].Value2;
1007                     if (debug_flag)
1008                       print_glyph_positioning (g, 2);
1009                   }
1010               }
1011           }
1012           break;
1013
1014         case 3:
1015           {
1016             OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1;
1017           
1018             g->positioning_type = lookup_type;
1019             g->f.f3.entry_anchor
1020               = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor;
1021             g->f.f3.exit_anchor
1022               = &cursive1->EntryExitRecord[coverage_idx].ExitAnchor;
1023             if (debug_flag)
1024               print_glyph_positioning (g, 0);
1025             gidx++;
1026           }
1027           break;
1028
1029         case 4:
1030           if (gidx < 1)
1031             continue;
1032           if (subtable->Format == 1)
1033             {
1034               OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1;
1035               OTF_MarkRecord *mark_record;
1036               OTF_AnchorRecord *base_record;
1037               OTF_Glyph *baseg;
1038               int coverage_idx_base;
1039               unsigned int this_flag = flag | OTF_IgnoreMarks;
1040
1041               for (baseg = g - 1;
1042                    baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, this_flag);
1043                    baseg--);
1044               if (baseg < gstring->glyphs)
1045                 continue;
1046               coverage_idx_base
1047                 = get_coverage_index (&mark_base1->BaseCoverage,
1048                                       baseg->glyph_id);
1049               if (coverage_idx_base < 0)
1050                 continue;
1051               mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx;
1052               base_record
1053                 = mark_base1->BaseArray.AnchorRecord + coverage_idx_base;
1054               g->f.f4.mark_anchor = &mark_record->MarkAnchor;
1055               g->f.f4.base_anchor
1056                 = &base_record->Anchor[mark_record->Class];
1057               g->positioning_type = lookup_type;
1058               if (debug_flag)
1059                 print_glyph_positioning (g, 0);
1060               gidx++;
1061             }
1062           break;
1063
1064         case 5:
1065           if (gidx < 1)
1066             continue;
1067           if (subtable->Format == 1)
1068             {
1069               OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1;
1070               OTF_Glyph *ligg;
1071               int coverage_idx_lig;
1072               OTF_MarkRecord *mark_record;
1073               OTF_LigatureAttach *attach;
1074               int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount);
1075               int j;
1076                                        
1077               for (j = 0; j < mark_lig1->ClassCount; j++)
1078                 num_class[j] = 0;
1079
1080               for (ligg = g - 1;
1081                    (ligg >= gstring->glyphs
1082                     && (IGNORED_GLYPH (ligg, flag)
1083                         || ligg->GlyphClass > OTF_GlyphClassLigature));
1084                    ligg--)
1085                 if (ligg->positioning_type == 5
1086                     && ligg->MarkAttachClass < mark_lig1->ClassCount)
1087                   num_class[ligg->MarkAttachClass]++;
1088               if (ligg < gstring->glyphs)
1089                 continue;
1090               coverage_idx_lig
1091                 = get_coverage_index (&mark_lig1->LigatureCoverage,
1092                                       ligg->glyph_id);
1093               if (coverage_idx_lig < 0)
1094                 continue;
1095               mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx;
1096               g->MarkAttachClass = mark_record->Class;
1097               attach = (mark_lig1->LigatureArray.LigatureAttach
1098                         + coverage_idx_lig);
1099               for (j = 0; j < attach->ComponentCount; j++)
1100                 {
1101                   OTF_Anchor *lig_anchor
1102                     = attach->ComponentRecord[j].LigatureAnchor;
1103
1104                   if (lig_anchor[mark_record->Class].AnchorFormat
1105                       && num_class[mark_record->Class]-- == 0)
1106                     {
1107                       g->positioning_type = lookup_type;
1108                       g->f.f5.mark_anchor = &mark_record->MarkAnchor;
1109                       g->f.f5.ligature_anchor = lig_anchor + mark_record->Class;
1110                       if (debug_flag)
1111                         print_glyph_positioning (g, 0);
1112                       gidx++;
1113                       break;
1114                     }
1115                 }
1116             }
1117           break;
1118
1119         case 6:
1120           if (gidx < 1)
1121             continue;
1122           if (subtable->Format == 1)
1123             {
1124               OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1;
1125               OTF_MarkRecord *mark1_record;
1126               OTF_AnchorRecord *mark2_record;
1127               OTF_Glyph *prevg;
1128               int coverage_idx_base;
1129
1130               for (prevg = g - 1;
1131                    prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag);
1132                    prevg--);
1133               if (prevg < gstring->glyphs)
1134                 continue;
1135               coverage_idx_base
1136                 = get_coverage_index (&mark_mark1->Mark2Coverage,
1137                                       prevg->glyph_id);
1138               if (coverage_idx_base < 0)
1139                 continue;
1140               mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx;
1141               mark2_record
1142                 = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base;
1143               g->f.f6.mark1_anchor = &mark1_record->MarkAnchor;
1144               g->f.f6.mark2_anchor
1145                 = &mark2_record->Anchor[mark1_record->Class];
1146               g->positioning_type = lookup_type;
1147               if (debug_flag)
1148                 print_glyph_positioning (g, 0);
1149               gidx++;
1150               break;
1151             }
1152           break;
1153
1154         case 7:
1155           if (subtable->Format == 1)
1156             {
1157               OTF_GPOS_Context1 *context1 = &subtable->u.context1;
1158               OTF_RuleSet *set = context1->RuleSet + coverage_idx;
1159               OTF_Rule *rule;
1160               int orig_used;
1161               int j, k;
1162
1163               for (j = 0; j < set->RuleCount; j++)
1164                 {
1165                   rule = set->Rule + j;
1166                   if (match_ids (gstring, gidx + 1, flag,
1167                                  rule->GlyphCount - 1, rule->Input) < 0)
1168                     continue;
1169                   orig_used = gstring->used;
1170                   for (k = 0; k < rule->LookupCount; k++)
1171                     lookup_gpos (lookup_list,
1172                                  rule->LookupRecord[k].LookupListIndex,
1173                                  gstring,
1174                                  gidx + rule->LookupRecord[k].SequenceIndex,
1175                                  accumulate);
1176                   gidx += rule->GlyphCount + (gstring->used - orig_used);
1177                   break;
1178                 }
1179             }
1180           else if (subtable->Format == 2)
1181             {
1182               OTF_GPOS_Context2 *context2 = &subtable->u.context2;
1183               OTF_ClassSet *set;
1184               OTF_ClassRule *rule;
1185               unsigned class;
1186               int orig_used;
1187               int j, k;
1188
1189               class = get_class_def (&context2->ClassDef, g->glyph_id);
1190               set = context2->ClassSet + class;
1191               if (set)
1192                 for (j = 0; j < set->ClassRuleCnt; j++)
1193                   {
1194                     rule = set->ClassRule + j;
1195                     if (match_classes (&context2->ClassDef,
1196                                        gstring, gidx + 1, flag,
1197                                        rule->GlyphCount - 1, rule->Class)
1198                         < 0)
1199                       continue;
1200                     orig_used = gstring->used;
1201                     for (k = 0; k < rule->LookupCount; k++)
1202                       lookup_gpos (lookup_list,
1203                                    rule->LookupRecord[k].LookupListIndex,
1204                                    gstring,
1205                                    gidx + rule->LookupRecord[k].SequenceIndex,
1206                                    accumulate);
1207                     gidx += rule->GlyphCount + (gstring->used - orig_used);
1208                     break;
1209                   }
1210             }
1211           else                  /* subtable->Format == 3 */
1212             {
1213               OTF_GPOS_Context3 *context3 = &subtable->u.context3;
1214               int orig_used;
1215               int j;
1216
1217               if (match_coverages (gstring, gidx + 1, flag,
1218                                    context3->GlyphCount - 1,
1219                                    context3->Coverage + 1) < 0)
1220                 continue;
1221               orig_used = gstring->used;
1222               for (j = 0; j < context3->LookupCount; j++)
1223                 lookup_gpos (lookup_list,
1224                              context3->LookupRecord[j].LookupListIndex,
1225                              gstring,
1226                              gidx + context3->LookupRecord[j].SequenceIndex,
1227                              accumulate);
1228               gidx += context3->GlyphCount + (gstring->used - orig_used);
1229             }
1230           break;
1231
1232         case 8:
1233           if (subtable->Format == 1)
1234             {
1235               OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1;
1236               OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx;
1237               int orig_used;
1238               int j, k;
1239               
1240               for (j = 0; j < set->ChainRuleCount; j++)
1241                 {
1242                   OTF_ChainRule *rule = set->ChainRule + j;
1243
1244                   if (gidx < rule->BacktrackGlyphCount
1245                       || (gidx + rule->InputGlyphCount
1246                           + rule->LookaheadGlyphCount) > gstring->used)
1247                     continue;
1248                   if (match_chain_ids (gstring, gidx, flag, rule) < 0)
1249                     continue;
1250                   orig_used = gstring->used;
1251                   for (k = 0; k < rule->LookupCount; k++)
1252                     lookup_gpos (lookup_list,
1253                                  rule->LookupRecord[k].LookupListIndex,
1254                                  gstring,
1255                                  gidx + rule->LookupRecord[k].SequenceIndex,
1256                                  accumulate);
1257                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1258                   break;
1259                 }
1260             }
1261           else if (subtable->Format == 2)
1262             {
1263               OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2;
1264               OTF_ChainClassSet *set;
1265               unsigned class;
1266               int j;
1267               int orig_used;
1268
1269               class = get_class_def (&context2->InputClassDef, g->glyph_id);
1270               set = context2->ChainClassSet + class;
1271               for (j = 0; j < set->ChainClassRuleCnt; j++)
1272                 {
1273                   OTF_ChainClassRule *rule = set->ChainClassRule + j;
1274                   int k;
1275
1276                   if (gidx < rule->BacktrackGlyphCount
1277                       || (gidx + rule->InputGlyphCount
1278                           + rule->LookaheadGlyphCount) > gstring->used)
1279                     continue;
1280                   if (match_chain_classes (gstring, gidx, flag,
1281                                            &context2->BacktrackClassDef,
1282                                            &context2->InputClassDef,
1283                                            &context2->LookaheadClassDef,
1284                                            rule) < 0)
1285                     continue;
1286                   orig_used = gstring->used;
1287                   for (k = 0; k < rule->LookupCount; k++)
1288                     lookup_gpos (lookup_list,
1289                                  rule->LookupRecord[k].LookupListIndex,
1290                                  gstring,
1291                                  gidx + rule->LookupRecord[k].SequenceIndex,
1292                                  accumulate);
1293                   gidx += rule->InputGlyphCount + (gstring->used - orig_used);
1294                   break;
1295                 }
1296             }
1297           else if (subtable->Format == 3)
1298             {
1299               OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3;
1300               int orig_used;
1301               int j;
1302
1303               if (gidx < context3->BacktrackGlyphCount
1304                   || (gidx + context3->InputGlyphCount
1305                       + context3->LookaheadGlyphCount) > gstring->used)
1306                 continue;
1307               if (match_chain_coverages (gstring, gidx, flag, context3) < 0)
1308                 continue;
1309               orig_used = gstring->used;
1310               for (j = 0; j < context3->LookupCount; j++)
1311                 lookup_gpos (lookup_list,
1312                              context3->LookupRecord[j].LookupListIndex,
1313                              gstring,
1314                              gidx + context3->LookupRecord[j].SequenceIndex,
1315                              accumulate);
1316               gidx += context3->InputGlyphCount + (gstring->used - orig_used);
1317             }
1318           else
1319             OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)");
1320           break;
1321
1322         default:
1323           continue;
1324         }
1325     }
1326   if (gidx == orig_gidx)
1327     {
1328       if (debug_flag)
1329         fprintf (stderr, " no match\n");
1330       gidx++;
1331     }
1332   else if (debug_flag)
1333     fprintf (stderr, "\n");
1334   return gidx;
1335 }
1336
1337 static unsigned
1338 lookup_encoding_0 (int c, OTF_EncodingSubtable *sub)
1339 {
1340   return ((c < 0 || c >= 256)
1341           ? 0
1342           : sub->f.f0->glyphIdArray[c]);
1343 }
1344
1345 static unsigned
1346 lookup_encoding_2 (int c, OTF_EncodingSubtable *sub)
1347 {
1348   return 0;
1349 }
1350
1351 static unsigned
1352 lookup_encoding_4 (int c, OTF_EncodingSubtable *sub)
1353 {
1354   int segCount, i;
1355   OTF_EncodingSubtable4 *sub4;
1356
1357   if (c < 0)
1358     return 0;
1359   sub4 = sub->f.f4;
1360   segCount = sub4->segCountX2 / 2;
1361   for (i = 0; i < segCount; i++)
1362     {
1363       OTF_cmapSegment *seg = sub4->segments + i;
1364
1365       if (c >= seg->startCount && c <= seg->endCount)
1366         {
1367           if (seg->idRangeOffset == 0xFFFF)
1368             return c + seg->idDelta;
1369           else
1370             return sub4->glyphIdArray[seg->idRangeOffset
1371                                       + (c - seg->startCount)];
1372         }
1373     }
1374   return 0;
1375 }
1376
1377 static unsigned
1378 lookup_encoding_6 (int c, OTF_EncodingSubtable *sub)
1379 {
1380   return 0;
1381 }
1382
1383 static unsigned
1384 lookup_encoding_8 (int c, OTF_EncodingSubtable *sub)
1385 {
1386   return 0;
1387 }
1388
1389 static unsigned
1390 lookup_encoding_10 (int c, OTF_EncodingSubtable *sub)
1391 {
1392   return 0;
1393 }
1394
1395 static unsigned
1396 lookup_encoding_12 (int c, OTF_EncodingSubtable *sub)
1397 {
1398   OTF_EncodingSubtable12 *sub12;
1399   OTF_cmapGroup *g, *gend;
1400
1401   if (c < 0)
1402     return 0;
1403   sub12 = sub->f.f12;
1404   g = sub12->Groups;
1405   gend = sub12->Groups + sub12->nGroups;
1406   while (g < gend)
1407     {
1408       if (g->startCharCode <= c && c <= g->endCharCode)
1409         return (g->startGlyphID + (c - g->startCharCode));
1410       g++;
1411     }
1412   return 0;
1413 }
1414
1415 typedef unsigned (*lookup_cmap_func) (int, OTF_EncodingSubtable *);
1416
1417 static lookup_cmap_func lookup_cmap_func_table[] =
1418   {
1419     lookup_encoding_0, lookup_encoding_2, lookup_encoding_4, lookup_encoding_6,
1420     lookup_encoding_8, lookup_encoding_10, lookup_encoding_12
1421   };
1422
1423 static unsigned
1424 get_GlyphID (OTF_cmap *cmap, int c)
1425 {
1426   OTF_EncodingSubtable *sub;
1427   lookup_cmap_func lookupper;
1428
1429   if (c < 0x10000 && cmap->unicode_table)
1430     return cmap->unicode_table[c];
1431   if (cmap->table_index < 0)
1432     return 0;
1433   sub = &cmap->EncodingRecord[cmap->table_index].subtable;
1434   lookupper = lookup_cmap_func_table[sub->format / 2];
1435   return lookupper (c, sub);
1436 }
1437
1438 static OTF_GlyphID
1439 get_uvs_glyph (OTF_cmap *cmap, OTF_EncodingSubtable14 *sub14, int c1, int c2)
1440 {
1441   unsigned nRecords = sub14->nRecords;
1442   OTF_VariationSelectorRecord *record;
1443   unsigned i;
1444
1445   for (i = 0; i < nRecords; i++)
1446     {
1447       record = &sub14->Records[i];
1448       if (record->varSelector == c2)
1449         {
1450           if (record->defaultUVSOffset)
1451             {
1452               OTF_UnicodeValueRange *uVRs = record->unicodeValueRanges;
1453               unsigned numUVRs = record->numUnicodeValueRanges;
1454               unsigned top = numUVRs, bottom = 0, middle;
1455
1456               if (uVRs[0].startUnicodeValue <= c1)
1457                 {
1458                   unsigned additionalCount, startUnicodeValue;
1459
1460                   for (;;)
1461                     {
1462                       middle = (top + bottom) / 2;
1463                       if (c1 < uVRs[middle].startUnicodeValue)
1464                         top = middle;
1465                       else if (bottom == middle)
1466                         break;
1467                       else
1468                         bottom = middle;
1469                     }
1470                   startUnicodeValue = uVRs[bottom].startUnicodeValue;
1471                   additionalCount = uVRs[bottom].additionalCount;
1472                   if (c1 <= startUnicodeValue + additionalCount)
1473                     return get_GlyphID (cmap, c1);
1474                 }
1475             }
1476           if (record->nonDefaultUVSOffset)
1477             {
1478               OTF_UVSMapping *uvsMappings = record->uvsMappings;
1479               unsigned numUVSMs = record->numUVSMappings;
1480               unsigned top = numUVSMs, bottom = 0, middle;
1481
1482               if (uvsMappings[0].unicodeValue <= c1)
1483                 {
1484                   for (;;)
1485                     {
1486                       middle = (top + bottom) / 2;
1487                       if (c1 < uvsMappings[middle].unicodeValue)
1488                         top = middle;
1489                       else if (bottom == middle)
1490                         break;
1491                       else
1492                         bottom = middle;
1493                     }
1494                   if (uvsMappings[bottom].unicodeValue == c1)
1495                     return uvsMappings[bottom].glyphID;
1496                 }
1497             }
1498           return 0;
1499         }
1500     }
1501   return 0;
1502 }
1503
1504 static void
1505 check_cmap_uvs (OTF_cmap *cmap, OTF_GlyphString *gstring, int idx)
1506 {  
1507   OTF_EncodingSubtable14 *sub14;
1508   int c1 = gstring->glyphs[idx - 1].c;
1509   int c2 = gstring->glyphs[idx].c;
1510   OTF_GlyphID code;
1511   int i;
1512
1513   gstring->glyphs[idx].glyph_id = 0;
1514   for (i = 0; i < cmap->numTables; i++)
1515     if (cmap->EncodingRecord[i].subtable.format == 14)
1516       break;
1517   if (i == cmap->numTables)
1518     return;
1519   code = get_uvs_glyph (cmap, cmap->EncodingRecord[i].subtable.f.f14, c1, c2);
1520   if (code == 0)
1521     return;
1522   gstring->glyphs[idx - 1].glyph_id = code;
1523   gstring->glyphs[idx - 1].f.index.to = gstring->glyphs[idx].f.index.to;
1524   gstring->used--;
1525   memmove (gstring->glyphs + idx, gstring->glyphs + idx + 1,
1526            sizeof (OTF_Glyph) * (gstring->used - idx));
1527 }
1528
1529 \f
1530
1531 /* GDEF */
1532 /* Table of GlyphClass and MarkAttackClass.
1533
1534    For the Nth element CHAR, CHAR and the succeeding characters
1535    (before CHAR of the next element) has GlyphClass C (= (N % 2) ? 3 : 1).
1536
1537    This table is generated from the General Category (GC) property of
1538    characters defined in the Unicode Character Database.  */
1539
1540 static int glyph_class_table[] =
1541   { 0x00000, 0x00300, 0x00370, 0x00483, 0x00487, 0x00488, 0x0048A, 0x00591,
1542     0x005BE, 0x005BF, 0x005C0, 0x005C1, 0x005C3, 0x005C4, 0x005C6, 0x005C7,
1543     0x005C8, 0x00610, 0x00616, 0x0064B, 0x0065F, 0x00670, 0x00671, 0x006D6,
1544     0x006DD, 0x006DE, 0x006E5, 0x006E7, 0x006E9, 0x006EA, 0x006EE, 0x00711,
1545     0x00712, 0x00730, 0x0074B, 0x007A6, 0x007B1, 0x007EB, 0x007F4, 0x00901,
1546     0x00904, 0x0093C, 0x0093D, 0x0093E, 0x0094E, 0x00951, 0x00955, 0x00962,
1547     0x00964, 0x00981, 0x00984, 0x009BC, 0x009BD, 0x009BE, 0x009C5, 0x009C7,
1548     0x009CE, 0x009D7, 0x009D8, 0x009E2, 0x009E4, 0x00A01, 0x00A04, 0x00A3C,
1549     0x00A3D, 0x00A3E, 0x00A4E, 0x00A70, 0x00A72, 0x00A81, 0x00A84, 0x00ABC,
1550     0x00ABD, 0x00ABE, 0x00ACE, 0x00AE2, 0x00AE4, 0x00B01, 0x00B04, 0x00B3C,
1551     0x00B3D, 0x00B3E, 0x00B44, 0x00B47, 0x00B58, 0x00B82, 0x00B83, 0x00BBE,
1552     0x00BCE, 0x00BD7, 0x00BD8, 0x00C01, 0x00C04, 0x00C3E, 0x00C45, 0x00C46,
1553     0x00C57, 0x00C82, 0x00C84, 0x00CBC, 0x00CBD, 0x00CBE, 0x00CC5, 0x00CC6,
1554     0x00CCE, 0x00CD5, 0x00CD7, 0x00CE2, 0x00CE4, 0x00D02, 0x00D04, 0x00D3E,
1555     0x00D44, 0x00D46, 0x00D4E, 0x00D57, 0x00D58, 0x00D82, 0x00D84, 0x00DCA,
1556     0x00DCB, 0x00DCF, 0x00DD7, 0x00DD8, 0x00DF4, 0x00E31, 0x00E32, 0x00E34,
1557     0x00E3B, 0x00E47, 0x00E4F, 0x00EB1, 0x00EB2, 0x00EB4, 0x00EBD, 0x00EC8,
1558     0x00ECE, 0x00F18, 0x00F1A, 0x00F35, 0x00F36, 0x00F37, 0x00F38, 0x00F39,
1559     0x00F3A, 0x00F3E, 0x00F40, 0x00F71, 0x00F85, 0x00F86, 0x00F88, 0x00F90,
1560     0x00FBD, 0x00FC6, 0x00FC7, 0x0102C, 0x0103A, 0x01056, 0x0105A, 0x0135F,
1561     0x01360, 0x01712, 0x01715, 0x01732, 0x01735, 0x01752, 0x01754, 0x01772,
1562     0x01774, 0x017B6, 0x017D4, 0x017DD, 0x017DE, 0x0180B, 0x0180E, 0x018A9,
1563     0x018AA, 0x01920, 0x0193C, 0x019B0, 0x019C1, 0x019C8, 0x019CA, 0x01A17,
1564     0x01A1C, 0x01B00, 0x01B05, 0x01B34, 0x01B45, 0x01B6B, 0x01B74, 0x01DC0,
1565     0x01E00, 0x020D0, 0x020F0, 0x0302A, 0x03030, 0x03099, 0x0309B, 0x0A802,
1566     0x0A803, 0x0A806, 0x0A807, 0x0A80B, 0x0A80C, 0x0A823, 0x0A828, 0x0FB1E,
1567     0x0FB1F, 0x0FE00, 0x0FE10, 0x0FE20, 0x0FE24, 0x10A01, 0x10A10, 0x10A38,
1568     0x10A40, 0x1D165, 0x1D16A, 0x1D16D, 0x1D173, 0x1D17B, 0x1D183, 0x1D185,
1569     0x1D18C, 0x1D1AA, 0x1D1AE, 0x1D242, 0x1D245, 0xE0100, 0xE01F0 };
1570
1571 int get_class_def_auto (int c)
1572 {
1573   static int table_size
1574     = sizeof glyph_class_table / sizeof glyph_class_table[0];
1575   int low, high, mid;
1576
1577   if (c >= glyph_class_table[table_size - 1])
1578     return 0;
1579   low = 0;
1580   high = table_size - 1;
1581   while (1)
1582     {
1583       mid = (low + high) / 2;
1584       if (c < glyph_class_table[mid])
1585         high = mid - 1;
1586       else if (c >= glyph_class_table[mid + 1])
1587         low = mid + 1;
1588       else
1589         break;
1590     }
1591   return ((mid % 2) ? 3 : 1);
1592 }
1593
1594 \f
1595
1596 /* API */
1597
1598 #define UVS_P(C)        \
1599   (((C) >= 0xFE00 && (C) <= 0xFE0F) || ((C) >= 0xE0100 && (C) <= 0xE01EF))
1600
1601 int
1602 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1603 {
1604   OTF_cmap *cmap;
1605   int i;
1606   OTF_EncodingSubtable *sub;
1607   lookup_cmap_func lookupper;
1608
1609   if (! otf->cmap
1610       && OTF_get_table (otf, "cmap") < 0)
1611     return -1;
1612
1613   cmap = otf->cmap;
1614   if (cmap->table_index < 0)
1615     lookupper = NULL;
1616   else
1617     {
1618       sub = &cmap->EncodingRecord[cmap->table_index].subtable;
1619       lookupper = lookup_cmap_func_table[sub->format / 2];
1620     }
1621   for (i = 0; i < gstring->used; i++)
1622     if (! gstring->glyphs[i].glyph_id)
1623       {
1624         int c = gstring->glyphs[i].c;
1625         if (c < 32 || ! cmap->unicode_table)
1626           gstring->glyphs[i].glyph_id = 0;
1627         else if (UVS_P (c) && i > 0)
1628           check_cmap_uvs (cmap, gstring, i);
1629         else if (c < 0x10000)
1630           gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1631         else if (lookupper)
1632           gstring->glyphs[i].glyph_id = lookupper (c, sub);
1633       }
1634   return 0;
1635 }
1636
1637
1638 int
1639 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1640                  int platform_id, int encoding_id)
1641 {
1642   OTF_cmap *cmap;
1643   int i;
1644   char *errfmt = "CMAP Looking up%s";
1645   int errret = -1;
1646   OTF_EncodingRecord *enc;
1647   lookup_cmap_func lookupper;
1648
1649   if (! otf->cmap
1650       && OTF_get_table (otf, "cmap") < 0)
1651     return -1;
1652
1653   cmap = otf->cmap;
1654   for (i = 0; i < cmap->numTables; i++)
1655     if (cmap->EncodingRecord[i].platformID == platform_id
1656         && cmap->EncodingRecord[i].encodingID == encoding_id)
1657       break;
1658   if (i == cmap->numTables)
1659     OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1660   enc = cmap->EncodingRecord + i;
1661   if (enc->subtable.format > 12)
1662     OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1663   lookupper = lookup_cmap_func_table[enc->subtable.format / 2];
1664
1665   for (i = 0; i < gstring->used; i++)
1666     if (! gstring->glyphs[i].glyph_id)
1667       {
1668         int c = gstring->glyphs[i].c;
1669         if (c < 32 || ! cmap->unicode_table)
1670           gstring->glyphs[i].glyph_id = 0;
1671         else if (UVS_P (c) && i > 0)
1672           check_cmap_uvs (cmap, gstring, i);
1673         else if (c < 0x10000)
1674           gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1675         else
1676           gstring->glyphs[i].glyph_id = lookupper (c, &enc->subtable);
1677       }
1678 }
1679
1680
1681 int
1682 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1683 {
1684   if (! otf->cmap
1685       && OTF_get_table (otf, "cmap") < 0)
1686     return 0;
1687   if (code == 0
1688       || code > otf->cmap->max_glyph_id
1689       || ! otf->cmap->decode_table)
1690     return 0;
1691   return otf->cmap->decode_table[code];
1692 }
1693
1694 int
1695 OTF_get_variation_glyphs (OTF *otf, int c, OTF_GlyphID code[256])
1696 {
1697   int i, n;
1698   OTF_cmap *cmap;
1699   OTF_EncodingSubtable14 *sub14;
1700
1701   memset (code, 0, sizeof (OTF_GlyphID) * 256);
1702   if (! otf->cmap
1703       && OTF_get_table (otf, "cmap") < 0)
1704     return 0;
1705   cmap = otf->cmap;
1706   for (i = 0; i < cmap->numTables; i++)
1707     if (cmap->EncodingRecord[i].subtable.format == 14)
1708       break;
1709   if (i == cmap->numTables)
1710     return 0;
1711   sub14 = cmap->EncodingRecord[i].subtable.f.f14;
1712   for (i = 0, n = 0; i < 256; i++)
1713     {
1714       int uvs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
1715
1716       if ((code[i] = get_uvs_glyph (cmap, sub14, c, uvs)))
1717         n++;
1718     }
1719   return n;
1720 }
1721
1722
1723 int
1724 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1725 {
1726   OTF_GDEF *gdef;
1727   int i;
1728
1729   if (! otf->gdef
1730       && OTF_get_table (otf, "GDEF") < 0)
1731     return -1;
1732   gdef = otf->gdef;
1733
1734   if (gdef->glyph_class_def.offset)
1735     for (i = 0; i < gstring->used; i++)
1736       gstring->glyphs[i].GlyphClass
1737         = get_class_def (&gdef->glyph_class_def,
1738                          gstring->glyphs[i].glyph_id);
1739   else
1740     for (i = 0; i < gstring->used; i++)
1741       gstring->glyphs[i].GlyphClass
1742         = get_class_def_auto (gstring->glyphs[i].c);
1743
1744   if (gdef->mark_attach_class_def.offset)
1745     for (i = 0; i < gstring->used; i++)
1746       gstring->glyphs[i].MarkAttachClass
1747         = get_class_def (&gdef->mark_attach_class_def,
1748                          gstring->glyphs[i].glyph_id);
1749
1750   return 0;
1751 }
1752
1753 static int
1754 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1755                          const char *script, const char *language,
1756                          const char *features,
1757                          int alternate_subst)
1758 {
1759   char *errfmt = "GSUB driving%s";
1760   int errret = -1;
1761   OTF_GSUB *gsub;
1762   OTF_LangSys *LangSys;
1763   char *lookup_flags;
1764   int i;
1765
1766   for (i = 0; i < gstring->used; i++)
1767     {
1768       gstring->glyphs[i].positioning_type = 0;
1769       gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1770     }
1771
1772   if (OTF_get_table (otf, "GSUB") < 0)
1773     return errret;
1774   gsub = otf->gsub;
1775   if (gsub->FeatureList.FeatureCount == 0
1776       || gsub->LookupList.LookupCount == 0)
1777     return 0;
1778
1779   LangSys = get_langsys (&gsub->ScriptList, script, language);
1780   if (! LangSys)
1781     return errret;
1782
1783   lookup_flags = alloca (gsub->LookupList.LookupCount);
1784   if (! lookup_flags
1785       || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, LangSys,
1786                              features, lookup_flags) < 0)
1787     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1788
1789   for (i = 0; i < gsub->LookupList.LookupCount; i++)
1790     {
1791       int gidx;
1792
1793       if (! lookup_flags[i]) continue;
1794
1795       if (gsub->LookupList.Lookup[i].LookupType != 8)
1796         {
1797           gidx = 0;
1798           while (gidx < gstring->used)
1799             {
1800               gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1801                                   alternate_subst);
1802               if (gidx < 0)
1803                 return errret;
1804             }
1805         }
1806       else
1807         {
1808           gidx = gstring->used - 1;
1809           while (gidx >= 0)
1810             {
1811               gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1812                                   alternate_subst);
1813               if (gidx < 0)
1814                 return errret;
1815             }
1816         }
1817     }
1818
1819   return 0;
1820 }
1821
1822 int
1823 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1824                 const char *script, const char *language, const char *features)
1825 {
1826   if (! otf->cmap)
1827     OTF_get_table (otf, "cmap");
1828   return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1829 }
1830
1831 int
1832 OTF_drive_gpos_internal (OTF *otf, OTF_GlyphString *gstring,
1833                          const char *script, const char *language,
1834                          const char *features,
1835                          int accumulate)
1836 {
1837   char *errfmt = "GPOS driving%s";
1838   int errret = -1;
1839   OTF_GPOS *gpos;
1840   OTF_LangSys *LangSys;
1841   char *lookup_flags;
1842   int i, n;
1843
1844   for (i = 0; i < gstring->used; i++)
1845     gstring->glyphs[i].positioning_type = 0;
1846
1847   if (OTF_get_table (otf, "GPOS") < 0)
1848     return errret;
1849   gpos = otf->gpos;
1850   if (gpos->FeatureList.FeatureCount == 0
1851       || gpos->LookupList.LookupCount == 0)
1852     return 0;
1853
1854   LangSys = get_langsys (&gpos->ScriptList, script, language);
1855   if (! LangSys)
1856     return errret;
1857
1858   lookup_flags = alloca (gpos->LookupList.LookupCount);
1859   if (! lookup_flags
1860       || setup_lookup_flags (&gpos->LookupList, &gpos->FeatureList, LangSys,
1861                              features, lookup_flags) < 0)
1862     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1863
1864   for (i = 0; i < gpos->LookupList.LookupCount; i++)
1865     {
1866       int gidx = 0;
1867
1868       if (! lookup_flags[i]) continue;
1869
1870       while (gidx < gstring->used)
1871         {
1872           gidx = lookup_gpos (&gpos->LookupList, i, gstring, gidx, accumulate);
1873           if (gidx < 0)
1874             return errret;
1875         }
1876     }
1877
1878   return 0;
1879 }
1880
1881 int
1882 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1883                 const char *script, const char *language, const char *features)
1884 {
1885   if (! otf->cmap)
1886     OTF_get_table (otf, "cmap");
1887   return OTF_drive_gpos_internal (otf, gstring, script, language, features, 0);
1888 }
1889
1890 int
1891 OTF_drive_gpos2 (OTF *otf, OTF_GlyphString *gstring,
1892                 const char *script, const char *language, const char *features)
1893 {
1894   if (! otf->cmap)
1895     OTF_get_table (otf, "cmap");
1896   return OTF_drive_gpos_internal (otf, gstring, script, language, features, 1);
1897 }
1898
1899 int
1900 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1901                   const char *script, const char *language,
1902                   const char *gsub_features, const char *gpos_features)
1903 {
1904   if (OTF_drive_cmap (otf, gstring) < 0)
1905     return -1;
1906   if (OTF_drive_gdef (otf, gstring) < 0)
1907     return -1;
1908   if (gsub_features
1909       && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1910     return -1;
1911   if (gpos_features
1912       && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1913     return -1;
1914   return 0;
1915 }
1916
1917 int
1918 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1919                           const char *script, const char *language,
1920                           const char *features)
1921 {
1922   return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);
1923 }
1924
1925 static int
1926 iterate_coverage (OTF *otf, const char *feature, 
1927                   OTF_Feature_Callback callback,
1928                   OTF_Coverage *coverage)
1929 {
1930   int i;
1931
1932   if (coverage->CoverageFormat == 1)
1933     {
1934       for (i = 0; i < coverage->Count; i++)
1935         if (callback (otf, feature, coverage->table.GlyphArray[i]) < 0)
1936           return -1;
1937     }
1938   else
1939     {
1940       for (i = 0; i < coverage->Count; i++)
1941         {
1942           OTF_RangeRecord *range = coverage->table.RangeRecord + i;
1943           unsigned id;
1944           for (id = range->Start; id <= range->End; id++)
1945             if (callback (otf, feature, id) < 0)
1946               return -1;
1947         }
1948     }
1949   return 0;
1950 }
1951
1952 static int
1953 iterate_feature (OTF *otf, const char *feature,
1954                  OTF_Feature_Callback callback,
1955                  OTF_Lookup *lookup)
1956 {
1957   int i, j, k, l;
1958
1959   for (i = 0; i < lookup->SubTableCount; i++)
1960     {
1961       unsigned lookup_type = lookup->LookupType;
1962       OTF_LookupSubTableGSUB *subtable = lookup->SubTable.gsub + i;
1963
1964       if (lookup_type == 7)
1965         {
1966           OTF_GSUB_Extension1 *extension1 = &subtable->u.extension1;
1967
1968           lookup_type = extension1->ExtensionLookupType;
1969           subtable = extension1->ExtensionSubtable;
1970         }
1971
1972       if ((lookup_type >= 1 && lookup_type <= 3) || lookup_type == 8)
1973         {
1974           if (iterate_coverage (otf, feature, callback, &subtable->Coverage)
1975               < 0)
1976             return -1;
1977         }
1978       else if (lookup_type == 4)
1979         {
1980           OTF_GSUB_Ligature1 *lig1;
1981
1982           if (iterate_coverage (otf, feature, callback, &subtable->Coverage)
1983               < 0)
1984             return -1;
1985           lig1 = &subtable->u.ligature1;
1986           for (j = 0; j < lig1->LigSetCount; j++)
1987             {
1988               OTF_LigatureSet *ligset = lig1->LigatureSet + j;
1989
1990               for (k = 0; k < ligset->LigatureCount; k++)
1991                 {
1992                   OTF_Ligature *lig = ligset->Ligature + k;
1993                   for (l = 0; l < lig->CompCount - 1; l++)
1994                     if (callback (otf, feature, lig->Component[l]) < 0)
1995                       return -1;
1996                 }
1997             }
1998         }
1999       else if (lookup_type == 6)
2000         {
2001           if (subtable->Format == 1)
2002             {
2003               OTF_GSUB_ChainContext1 *context1 = &subtable->u.chain_context1;
2004               for (j = 0; j < context1->ChainRuleSetCount; j++)
2005                 {
2006                   OTF_ChainRuleSet *set = context1->ChainRuleSet + j;
2007                   for (k = 0; k < set->ChainRuleCount; k++)
2008                     {
2009                       OTF_ChainRule *rule = set->ChainRule + k;
2010                       for (l = 0; l < rule->LookupCount; l++)
2011                         {
2012                           OTF_Lookup *lkup
2013                             = (otf->gsub->LookupList.Lookup
2014                                + rule->LookupRecord[l].LookupListIndex);
2015                           if (iterate_feature (otf, feature, callback, lkup)
2016                               < 0)
2017                             return -1;
2018                         }
2019                     }
2020                 }
2021             }
2022           else if (subtable->Format == 2)
2023             {
2024               OTF_GSUB_ChainContext2 *context2 = &subtable->u.chain_context2;
2025
2026               for (j = 0; j < context2->ChainClassSetCnt; j++)
2027                 {
2028                   OTF_ChainClassSet *set = context2->ChainClassSet + j;
2029                   for (k = 0; k < set->ChainClassRuleCnt; j++)
2030                     {
2031                       OTF_ChainClassRule *rule = set->ChainClassRule + k;
2032
2033                       for (l = 0; l < rule->LookupCount; l++)
2034                         {
2035                           OTF_Lookup *lkup
2036                             = (otf->gsub->LookupList.Lookup
2037                                + rule->LookupRecord[k].LookupListIndex);
2038                           if (iterate_feature (otf, feature, callback, lkup)
2039                               < 0)
2040                             return -1;
2041                         }
2042                     }
2043                 }
2044             }
2045           else
2046             {
2047               OTF_GSUB_ChainContext3 *context3 = &subtable->u.chain_context3;
2048               for (j = 0; j < context3->LookupCount; j++)
2049                 {
2050                   OTF_Lookup *lkup
2051                     = (otf->gsub->LookupList.Lookup
2052                        + context3->LookupRecord[j].LookupListIndex);
2053                   if (iterate_feature (otf, feature, callback, lkup) < 0)
2054                     return -1;
2055                 }
2056             }
2057         }
2058     }
2059   return 0;
2060 }
2061
2062 int
2063 OTF_iterate_gsub_feature (OTF *otf, OTF_Feature_Callback callback,
2064                           const char *script, const char *language,
2065                           const char *feature)
2066 {
2067   char *errfmt = "GSUB iterate feature%s";
2068   int errret = -1;
2069   int i;
2070
2071   OTF_GSUB *gsub;
2072   OTF_LangSys *langsys;
2073   char *lookup_flags;
2074
2075   if (OTF_get_table (otf, "GSUB") < 0)
2076     return errret;
2077   gsub = otf->gsub;
2078   if (gsub->FeatureList.FeatureCount == 0
2079       || gsub->LookupList.LookupCount == 0)
2080     return 0;
2081   langsys = get_langsys (&gsub->ScriptList, script, language);
2082   if (! langsys)
2083     return errret;
2084   lookup_flags = alloca (gsub->LookupList.LookupCount);
2085   if (! lookup_flags
2086       || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, langsys,
2087                              feature, lookup_flags) < 0)
2088     OTF_ERROR (OTF_ERROR_MEMORY, " feature");
2089
2090   for (i = 0; i < gsub->LookupList.LookupCount; i++)
2091     if (lookup_flags[i])
2092       if (iterate_feature (otf, feature, callback, gsub->LookupList.Lookup + i)
2093           < 0)
2094         return -1;
2095   return 0;
2096 }