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