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