(glyph_class_table): New variable.
[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 int
1263 lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring)
1264 {
1265   int i, c;
1266
1267   for (i = 0; i < gstring->used; i++)
1268     {
1269       c = gstring->glyphs[i].c;
1270       if (c < 0 || c >= 256)
1271         gstring->glyphs[i].glyph_id = 0;
1272       else
1273         gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c];
1274     }
1275   return 0;
1276 }
1277
1278 static int
1279 lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring)
1280 {
1281   return 0;
1282 }
1283
1284 static int
1285 lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring)
1286 {
1287   int i, j, c;
1288   int segCount = sub4->segCountX2 / 2;
1289
1290   for (i = 0; i < gstring->used; i++)
1291     {
1292       c = gstring->glyphs[i].c;
1293       if (c < 0)
1294         gstring->glyphs[i].glyph_id = 0;
1295       for (j = 0; j < segCount; j++)
1296         {
1297           OTF_cmapSegment *seg = sub4->segments + i;
1298
1299           if (c >= seg->startCount && c <= seg->endCount)
1300             {
1301               if (seg->idRangeOffset == 0xFFFF)
1302                 gstring->glyphs[i].glyph_id = c + seg->idDelta;
1303               else
1304                 gstring->glyphs[i].glyph_id
1305                   = sub4->glyphIdArray[seg->idRangeOffset
1306                                        + (c - seg->startCount)];
1307               break;
1308             }
1309         }
1310     }
1311
1312   return 0;
1313 }
1314
1315 static int
1316 lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring)
1317 {
1318   return 0;
1319 }
1320
1321 static int
1322 lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring)
1323 {
1324   return 0;
1325 }
1326
1327 static int
1328 lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring)
1329 {
1330   return 0;
1331 }
1332
1333 static int
1334 lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring)
1335 {
1336   return 0;
1337 }
1338
1339 static OTF_GlyphID
1340 get_uvs_glyph (OTF_cmap *cmap, OTF_EncodingSubtable14 *sub14, int c1, int c2)
1341 {
1342   unsigned nRecords = sub14->nRecords;
1343   OTF_VariationSelectorRecord *record;
1344   unsigned i;
1345
1346   for (i = 0; i < nRecords; i++)
1347     {
1348       record = &sub14->Records[i];
1349       if (record->varSelector == c2)
1350         {
1351           if (record->defaultUVSOffset)
1352             {
1353               OTF_UnicodeValueRange *uVRs = record->unicodeValueRanges;
1354               unsigned numUVRs = record->numUnicodeValueRanges;
1355               unsigned top = numUVRs, bottom = 0, middle;
1356
1357               if (uVRs[0].startUnicodeValue <= c1)
1358                 {
1359                   unsigned additionalCount, startUnicodeValue;
1360
1361                   for (;;)
1362                     {
1363                       middle = (top + bottom) / 2;
1364                       if (c1 < uVRs[middle].startUnicodeValue)
1365                         top = middle;
1366                       else if (bottom == middle)
1367                         break;
1368                       else
1369                         bottom = middle;
1370                     }
1371                   startUnicodeValue = uVRs[bottom].startUnicodeValue;
1372                   additionalCount = uVRs[bottom].additionalCount;
1373                   if (c1 <= startUnicodeValue + additionalCount)
1374                     return cmap->unicode_table[c1];
1375                 }
1376             }
1377           if (record->nonDefaultUVSOffset)
1378             {
1379               OTF_UVSMapping *uvsMappings = record->uvsMappings;
1380               unsigned numUVSMs = record->numUVSMappings;
1381               unsigned top = numUVSMs, bottom = 0, middle;
1382
1383               if (uvsMappings[0].unicodeValue <= c1)
1384                 {
1385                   for (;;)
1386                     {
1387                       middle = (top + bottom) / 2;
1388                       if (c1 < uvsMappings[middle].unicodeValue)
1389                         top = middle;
1390                       else if (bottom == middle)
1391                         break;
1392                       else
1393                         bottom = middle;
1394                     }
1395                   if (uvsMappings[bottom].unicodeValue == c1)
1396                     return uvsMappings[bottom].glyphID;
1397                 }
1398             }
1399           return 0;
1400         }
1401     }
1402   return 0;
1403 }
1404
1405 static void
1406 check_cmap_uvs (OTF_cmap *cmap, OTF_GlyphString *gstring, int idx)
1407 {  
1408   OTF_EncodingSubtable14 *sub14;
1409   int c1 = gstring->glyphs[idx - 1].c;
1410   int c2 = gstring->glyphs[idx].c;
1411   OTF_GlyphID code;
1412   int i;
1413
1414   gstring->glyphs[idx].glyph_id = 0;
1415   for (i = 0; i < cmap->numTables; i++)
1416     if (cmap->EncodingRecord[i].subtable.format == 14)
1417       break;
1418   if (i == cmap->numTables)
1419     return;
1420   code = get_uvs_glyph (cmap, cmap->EncodingRecord[i].subtable.f.f14, c1, c2);
1421   if (code == 0)
1422     return;
1423   gstring->glyphs[idx - 1].glyph_id = code;
1424   gstring->glyphs[idx - 1].f.index.to = gstring->glyphs[idx].f.index.to;
1425   gstring->used--;
1426   memmove (gstring->glyphs + idx, gstring->glyphs + idx + 1,
1427            sizeof (OTF_Glyph) * (gstring->used - idx));
1428 }
1429
1430 \f
1431
1432 /* GDEF */
1433 /* Table of GlyphClass and MarkAttackClass.
1434
1435    For the Nth element CHAR, CHAR and the succeeding characters
1436    (before CHAR of the next element) has GlyphClass C (= (N % 2) ? 3 : 1).
1437
1438    This table is generated from the General Category (GC) property of
1439    characters defined in the Unicode Character Database.  */
1440
1441 static int glyph_class_table[] =
1442   { 0x00000, 0x00300, 0x00370, 0x00483, 0x00487, 0x00488, 0x0048A, 0x00591,
1443     0x005BE, 0x005BF, 0x005C0, 0x005C1, 0x005C3, 0x005C4, 0x005C6, 0x005C7,
1444     0x005C8, 0x00610, 0x00616, 0x0064B, 0x0065F, 0x00670, 0x00671, 0x006D6,
1445     0x006DD, 0x006DE, 0x006E5, 0x006E7, 0x006E9, 0x006EA, 0x006EE, 0x00711,
1446     0x00712, 0x00730, 0x0074B, 0x007A6, 0x007B1, 0x007EB, 0x007F4, 0x00901,
1447     0x00904, 0x0093C, 0x0093D, 0x0093E, 0x0094E, 0x00951, 0x00955, 0x00962,
1448     0x00964, 0x00981, 0x00984, 0x009BC, 0x009BD, 0x009BE, 0x009C5, 0x009C7,
1449     0x009CE, 0x009D7, 0x009D8, 0x009E2, 0x009E4, 0x00A01, 0x00A04, 0x00A3C,
1450     0x00A3D, 0x00A3E, 0x00A4E, 0x00A70, 0x00A72, 0x00A81, 0x00A84, 0x00ABC,
1451     0x00ABD, 0x00ABE, 0x00ACE, 0x00AE2, 0x00AE4, 0x00B01, 0x00B04, 0x00B3C,
1452     0x00B3D, 0x00B3E, 0x00B44, 0x00B47, 0x00B58, 0x00B82, 0x00B83, 0x00BBE,
1453     0x00BCE, 0x00BD7, 0x00BD8, 0x00C01, 0x00C04, 0x00C3E, 0x00C45, 0x00C46,
1454     0x00C57, 0x00C82, 0x00C84, 0x00CBC, 0x00CBD, 0x00CBE, 0x00CC5, 0x00CC6,
1455     0x00CCE, 0x00CD5, 0x00CD7, 0x00CE2, 0x00CE4, 0x00D02, 0x00D04, 0x00D3E,
1456     0x00D44, 0x00D46, 0x00D4E, 0x00D57, 0x00D58, 0x00D82, 0x00D84, 0x00DCA,
1457     0x00DCB, 0x00DCF, 0x00DD7, 0x00DD8, 0x00DF4, 0x00E31, 0x00E32, 0x00E34,
1458     0x00E3B, 0x00E47, 0x00E4F, 0x00EB1, 0x00EB2, 0x00EB4, 0x00EBD, 0x00EC8,
1459     0x00ECE, 0x00F18, 0x00F1A, 0x00F35, 0x00F36, 0x00F37, 0x00F38, 0x00F39,
1460     0x00F3A, 0x00F3E, 0x00F40, 0x00F71, 0x00F85, 0x00F86, 0x00F88, 0x00F90,
1461     0x00FBD, 0x00FC6, 0x00FC7, 0x0102C, 0x0103A, 0x01056, 0x0105A, 0x0135F,
1462     0x01360, 0x01712, 0x01715, 0x01732, 0x01735, 0x01752, 0x01754, 0x01772,
1463     0x01774, 0x017B6, 0x017D4, 0x017DD, 0x017DE, 0x0180B, 0x0180E, 0x018A9,
1464     0x018AA, 0x01920, 0x0193C, 0x019B0, 0x019C1, 0x019C8, 0x019CA, 0x01A17,
1465     0x01A1C, 0x01B00, 0x01B05, 0x01B34, 0x01B45, 0x01B6B, 0x01B74, 0x01DC0,
1466     0x01E00, 0x020D0, 0x020F0, 0x0302A, 0x03030, 0x03099, 0x0309B, 0x0A802,
1467     0x0A803, 0x0A806, 0x0A807, 0x0A80B, 0x0A80C, 0x0A823, 0x0A828, 0x0FB1E,
1468     0x0FB1F, 0x0FE00, 0x0FE10, 0x0FE20, 0x0FE24, 0x10A01, 0x10A10, 0x10A38,
1469     0x10A40, 0x1D165, 0x1D16A, 0x1D16D, 0x1D173, 0x1D17B, 0x1D183, 0x1D185,
1470     0x1D18C, 0x1D1AA, 0x1D1AE, 0x1D242, 0x1D245, 0xE0100, 0xE01F0 };
1471
1472 int get_class_def_auto (int c)
1473 {
1474   static int table_size
1475     = sizeof glyph_class_table / sizeof glyph_class_table[0];
1476   int low, high, mid;
1477
1478   if (c >= glyph_class_table[table_size - 1])
1479     return 0;
1480   low = 0;
1481   high = table_size - 1;
1482   while (1)
1483     {
1484       mid = (low + high) / 2;
1485       if (c < glyph_class_table[mid])
1486         high = mid - 1;
1487       else if (c >= glyph_class_table[mid + 1])
1488         low = mid + 1;
1489       else
1490         break;
1491     }
1492   return ((mid % 2) ? 3 : 1);
1493 }
1494
1495 \f
1496
1497 /* API */
1498
1499 #define UVS_P(C)        \
1500   (((C) >= 0xFE00 && (C) <= 0xFE0F) || ((C) >= 0xE0100 && (C) <= 0xE01EF))
1501
1502 int
1503 OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring)
1504 {
1505   OTF_cmap *cmap;
1506   int i;
1507
1508   if (! otf->cmap
1509       && OTF_get_table (otf, "cmap") < 0)
1510     return -1;
1511
1512   cmap = otf->cmap;
1513   for (i = 0; i < gstring->used; i++)
1514     if (! gstring->glyphs[i].glyph_id)
1515       {
1516         int c = gstring->glyphs[i].c;
1517         if (c < 32 || ! cmap->unicode_table)
1518           gstring->glyphs[i].glyph_id = 0;
1519         else if (UVS_P (c) && i > 0)
1520           check_cmap_uvs (cmap, gstring, i);
1521         else
1522           gstring->glyphs[i].glyph_id = cmap->unicode_table[c];
1523       }
1524   return 0;
1525 }
1526
1527
1528 int
1529 OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring,
1530                  int platform_id, int encoding_id)
1531 {
1532   OTF_cmap *cmap;
1533   int i;
1534   char *errfmt = "CMAP Looking up%s";
1535   int errret = -1;
1536   OTF_EncodingRecord *enc;
1537
1538   if (! otf->cmap
1539       && OTF_get_table (otf, "cmap") < 0)
1540     return -1;
1541
1542   cmap = otf->cmap;
1543   for (i = 0; i < cmap->numTables; i++)
1544     if (cmap->EncodingRecord[i].platformID == platform_id
1545         && cmap->EncodingRecord[i].encodingID == encoding_id)
1546       break;
1547   if (i == cmap->numTables)
1548     OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)");
1549   enc = cmap->EncodingRecord + i;
1550   switch (enc->subtable.format)
1551     {
1552     case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring);
1553     case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring);
1554     case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring);
1555     case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring);
1556     case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring);
1557     case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring);
1558     case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring);
1559     }
1560   OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)");
1561 }
1562
1563
1564 int
1565 OTF_get_unicode (OTF *otf, OTF_GlyphID code)
1566 {
1567   if (! otf->cmap
1568       && OTF_get_table (otf, "cmap") < 0)
1569     return 0;
1570   if (code == 0
1571       || code > otf->cmap->max_glyph_id
1572       || ! otf->cmap->decode_table)
1573     return 0;
1574   return otf->cmap->decode_table[code];
1575 }
1576
1577 int
1578 OTF_get_variation_glyphs (OTF *otf, int c, OTF_GlyphID code[256])
1579 {
1580   int i, n;
1581   OTF_cmap *cmap;
1582   OTF_EncodingSubtable14 *sub14;
1583
1584   memset (code, 0, sizeof (OTF_GlyphID) * 256);
1585   if (! otf->cmap
1586       && OTF_get_table (otf, "cmap") < 0)
1587     return 0;
1588   cmap = otf->cmap;
1589   for (i = 0; i < cmap->numTables; i++)
1590     if (cmap->EncodingRecord[i].subtable.format == 14)
1591       break;
1592   if (i == cmap->numTables)
1593     return 0;
1594   sub14 = cmap->EncodingRecord[i].subtable.f.f14;
1595   for (i = 0, n = 0; i < 256; i++)
1596     {
1597       int uvs = (i < 16 ? 0xFE00 + i : 0xE0100 + (i - 16));
1598
1599       if ((code[i] = get_uvs_glyph (cmap, sub14, c, uvs)))
1600         n++;
1601     }
1602   return n;
1603 }
1604
1605
1606 int
1607 OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring)
1608 {
1609   OTF_GDEF *gdef;
1610   int i;
1611
1612   if (! otf->gdef
1613       && OTF_get_table (otf, "GDEF") < 0)
1614     return -1;
1615   gdef = otf->gdef;
1616
1617   if (gdef->glyph_class_def.offset)
1618     for (i = 0; i < gstring->used; i++)
1619       gstring->glyphs[i].GlyphClass
1620         = get_class_def (&gdef->glyph_class_def,
1621                          gstring->glyphs[i].glyph_id);
1622   else
1623     for (i = 0; i < gstring->used; i++)
1624       gstring->glyphs[i].GlyphClass
1625         = get_class_def_auto (gstring->glyphs[i].c);
1626
1627   if (gdef->mark_attach_class_def.offset)
1628     for (i = 0; i < gstring->used; i++)
1629       gstring->glyphs[i].MarkAttachClass
1630         = get_class_def (&gdef->mark_attach_class_def,
1631                          gstring->glyphs[i].glyph_id);
1632
1633   return 0;
1634 }
1635
1636 static int
1637 OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring,
1638                          const char *script, const char *language,
1639                          const char *features,
1640                          int alternate_subst)
1641 {
1642   char *errfmt = "GSUB driving%s";
1643   int errret = -1;
1644   OTF_GSUB *gsub;
1645   OTF_LangSys *LangSys;
1646   char *lookup_flags;
1647   int i;
1648
1649   for (i = 0; i < gstring->used; i++)
1650     {
1651       gstring->glyphs[i].positioning_type = 0;
1652       gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i;
1653     }
1654
1655   if (OTF_get_table (otf, "GSUB") < 0)
1656     return errret;
1657   gsub = otf->gsub;
1658   if (gsub->FeatureList.FeatureCount == 0
1659       || gsub->LookupList.LookupCount == 0)
1660     return 0;
1661
1662   LangSys = get_langsys (&gsub->ScriptList, script, language);
1663   if (! LangSys)
1664     return errret;
1665
1666   lookup_flags = alloca (gsub->LookupList.LookupCount);
1667   if (! lookup_flags
1668       || setup_lookup_flags (&gsub->LookupList, &gsub->FeatureList, LangSys,
1669                              features, lookup_flags) < 0)
1670     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1671
1672   for (i = 0; i < gsub->LookupList.LookupCount; i++)
1673     {
1674       int gidx;
1675
1676       if (! lookup_flags[i]) continue;
1677
1678       if (gsub->LookupList.Lookup[i].LookupType != 8)
1679         {
1680           gidx = 0;
1681           while (gidx < gstring->used)
1682             {
1683               gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1684                                   alternate_subst);
1685               if (gidx < 0)
1686                 return errret;
1687             }
1688         }
1689       else
1690         {
1691           gidx = gstring->used - 1;
1692           while (gidx >= 0)
1693             {
1694               gidx = lookup_gsub (otf, &gsub->LookupList, i, gstring, gidx,
1695                                   alternate_subst);
1696               if (gidx < 0)
1697                 return errret;
1698             }
1699         }
1700     }
1701
1702   return 0;
1703 }
1704
1705 int
1706 OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring,
1707                 const char *script, const char *language, const char *features)
1708 {
1709   if (! otf->cmap)
1710     OTF_get_table (otf, "cmap");
1711   return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0);
1712 }
1713
1714 int
1715 OTF_drive_gpos_internal (OTF *otf, OTF_GlyphString *gstring,
1716                          const char *script, const char *language,
1717                          const char *features,
1718                          int accumulate)
1719 {
1720   char *errfmt = "GPOS driving%s";
1721   int errret = -1;
1722   OTF_GPOS *gpos;
1723   OTF_LangSys *LangSys;
1724   char *lookup_flags;
1725   int i, n;
1726
1727   for (i = 0; i < gstring->used; i++)
1728     gstring->glyphs[i].positioning_type = 0;
1729
1730   if (OTF_get_table (otf, "GPOS") < 0)
1731     return errret;
1732   gpos = otf->gpos;
1733   if (gpos->FeatureList.FeatureCount == 0
1734       || gpos->LookupList.LookupCount == 0)
1735     return 0;
1736
1737   LangSys = get_langsys (&gpos->ScriptList, script, language);
1738   if (! LangSys)
1739     return errret;
1740
1741   lookup_flags = alloca (gpos->LookupList.LookupCount);
1742   if (! lookup_flags
1743       || setup_lookup_flags (&gpos->LookupList, &gpos->FeatureList, LangSys,
1744                              features, lookup_flags) < 0)
1745     OTF_ERROR (OTF_ERROR_MEMORY, " feature list");
1746
1747   for (i = 0; i < gpos->LookupList.LookupCount; i++)
1748     {
1749       int gidx = 0;
1750
1751       if (! lookup_flags[i]) continue;
1752
1753       while (gidx < gstring->used)
1754         {
1755           gidx = lookup_gpos (&gpos->LookupList, i, gstring, gidx, accumulate);
1756           if (gidx < 0)
1757             return errret;
1758         }
1759     }
1760
1761   return 0;
1762 }
1763
1764 int
1765 OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring,
1766                 const char *script, const char *language, const char *features)
1767 {
1768   if (! otf->cmap)
1769     OTF_get_table (otf, "cmap");
1770   return OTF_drive_gpos_internal (otf, gstring, script, language, features, 0);
1771 }
1772
1773 int
1774 OTF_drive_gpos2 (OTF *otf, OTF_GlyphString *gstring,
1775                 const char *script, const char *language, const char *features)
1776 {
1777   if (! otf->cmap)
1778     OTF_get_table (otf, "cmap");
1779   return OTF_drive_gpos_internal (otf, gstring, script, language, features, 1);
1780 }
1781
1782 int
1783 OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring,
1784                   const char *script, const char *language,
1785                   const char *gsub_features, const char *gpos_features)
1786 {
1787   if (OTF_drive_cmap (otf, gstring) < 0)
1788     return -1;
1789   if (OTF_drive_gdef (otf, gstring) < 0)
1790     return -1;
1791   if (gsub_features
1792       && OTF_drive_gsub (otf, gstring, script, language, gsub_features) < 0)
1793     return -1;
1794   if (gpos_features
1795       && OTF_drive_gpos (otf, gstring, script, language, gpos_features) < 0)
1796     return -1;
1797   return 0;
1798 }
1799
1800 int
1801 OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring,
1802                           const char *script, const char *language,
1803                           const char *features)
1804 {
1805   return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1);
1806 }