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