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