X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fotfdrive.c;h=3dc6eda562dcb4bb1b150b539c509e3a072da933;hb=092c77ce9d2bd59339ae4a99cc27d2b78318cf06;hp=4e644d5c5a0afd26688cc00dab23a142f9952010;hpb=f08c207e7119e5ddc2da8f6ada24939f1dd1d43e;p=m17n%2Flibotf.git diff --git a/src/otfdrive.c b/src/otfdrive.c index 4e644d5..3dc6eda 100644 --- a/src/otfdrive.c +++ b/src/otfdrive.c @@ -1,33 +1,43 @@ /* otfdrive.c -- OpenType font driver. -Copyright (C) 2003 - by AIST (National Institute of Advanced Industrial Science and Technology) - Registration Number H15PRO??? +Copyright (C) 2003, 2004 + National Institute of Advanced Industrial Science and Technology (AIST) + Registration Number H15PRO167 -This file is part of the OTF library. +This file is part of libotf. -The OTF library is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2, or (at -your option) any later version. +Libotf is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. -The OTF library is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. +Libotf is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. -You should have received a copy of the GNU General Public License -along with the OTF library; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +You should have received a copy of the GNU Lesser General Public +License along with this library, in a file named COPYING; if not, +write to the Free Software Foundation, Inc., 59 Temple Place, Suite +330, Boston, MA 02111-1307, USA. */ #include #include #include +#include #include "otf.h" #include "otferror.h" +/* Return nonzero (-1 if ID is zero, 1 otherwise) if OTF_Glyph *G + should be ignored according to LookupFlag FLAG. */ +#define IGNORED_GLYPH(g, flag) \ + ((g)->glyph_id == 0 ? -1 \ + : (((flag) & (1 << (g)->GlyphClass)) \ + || (((flag) & OTF_MarkAttachmentType) \ + && (g)->GlyphClass == OTF_GlyphClassMark \ + && ((flag) >> 8) != (g)->MarkAttachClass))) + #define GSTRING_DELETE(gstring, from, len) \ do { \ memmove (gstring->glyphs + from, gstring->glyphs + from + len, \ @@ -43,8 +53,9 @@ Boston, MA 02111-1307, USA. */ char *errfmt = "GSTRING%s"; \ \ gstring->size = gstring->used + len; \ - gstring->glyphs = (OTF_Glyph *) realloc (gstring->glyphs, \ - gstring->size); \ + gstring->glyphs \ + = (OTF_Glyph *) realloc (gstring->glyphs, \ + sizeof (OTF_Glyph) * gstring->size); \ if (! gstring->glyphs) \ OTF_ERROR (OTF_ERROR_MEMORY, ""); \ } \ @@ -54,20 +65,57 @@ Boston, MA 02111-1307, USA. */ } while (0) +static unsigned get_class_def (OTF_ClassDef *, OTF_GlyphID); + static int -gstring_subst (OTF_GlyphString *gstring, int from, int to, +gstring_subst (OTF *otf, OTF_GlyphString *gstring, int from, int to, int flag, OTF_GlyphID *ids, int num) { int errret = -1; int len = to - from; int i; + int from_idx = gstring->glyphs[from].f.index.from; + int to_idx = gstring->glyphs[to - 1].f.index.to; + int non_ignored_idx; + + for (i = non_ignored_idx = to - 1; i >= from; i--) + { + OTF_Glyph *g = gstring->glyphs + i; + + if (IGNORED_GLYPH (g, flag) == 1) + { + /* Move this glyph to the next of the current target of + substitution. */ + OTF_Glyph temp = *g; + + memmove (g, g + 1, sizeof (OTF_Glyph) * (non_ignored_idx - i)); + temp.f.index.from = from_idx; + temp.f.index.to = to_idx; + gstring->glyphs[non_ignored_idx--] = temp; + len--; + } + } if (len < num) GSTRING_INSERT (gstring, from, (num - len)); else if (len > num) GSTRING_DELETE (gstring, from, (len - num)); for (i = 0; i < num; i++) - gstring->glyphs[from + i].glyph_id = ids[i]; + { + if (gstring->glyphs[from + i].glyph_id != ids[i]) + { + gstring->glyphs[from + i].c = 0; + if (otf->gdef) + gstring->glyphs[from + i].GlyphClass + = get_class_def (&otf->gdef->glyph_class_def, ids[i]); + else + gstring->glyphs[from + i].GlyphClass = 0; + } + gstring->glyphs[from + i].glyph_id = ids[i]; + gstring->glyphs[from + i].positioning_type = 0; + gstring->glyphs[from + i].f.index.from = from_idx; + gstring->glyphs[from + i].f.index.to = to_idx; + } return 0; } @@ -117,32 +165,46 @@ get_class_def (OTF_ClassDef *class_def, OTF_GlyphID glyph_id) } static OTF_LangSys * -get_langsys (OTF_ScriptList *script_list, char *script, char *language) +get_langsys (OTF_ScriptList *script_list, + const char *script, const char *language) { OTF_Tag script_tag = OTF_tag (script); OTF_Tag langsys_tag = OTF_tag (language); int i, j; + OTF_Tag dflt_tag = OTF_tag ("DFLT"); + OTF_Script *dflt = NULL; for (i = 0; i < script_list->ScriptCount; i++) - if (script_list->Script[i].ScriptTag == script_tag) - { - OTF_Script *script = script_list->Script + i; - - if (! langsys_tag) - return &script->DefaultLangSys; - for (j = 0; j < script->LangSysCount; j++) - if (script->LangSysRecord[j].LangSysTag == langsys_tag) - return script->LangSys + j; - return &script->DefaultLangSys; - } + { + OTF_Script *script = script_list->Script + i; - return NULL; + if (script_list->Script[i].ScriptTag == dflt_tag) + dflt = script; + if (script_list->Script[i].ScriptTag == script_tag) + { + if (! langsys_tag) + return &script->DefaultLangSys; + for (j = 0; j < script->LangSysCount; j++) + if (script->LangSysRecord[j].LangSysTag == langsys_tag) + return script->LangSys + j; + return &script->DefaultLangSys; + } + } + + if (! dflt) + dflt = script_list->Script; + if (! langsys_tag) + return &dflt->DefaultLangSys; + for (j = 0; j < dflt->LangSysCount; j++) + if (dflt->LangSysRecord[j].LangSysTag == langsys_tag) + return dflt->LangSys + j; + return &dflt->DefaultLangSys; } static int setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList, - char *features, int *lookup_indices) + const char *features, int *lookup_indices) { int i, j, n = 0; OTF_Feature *feature; @@ -155,33 +217,23 @@ setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList, { char tagname[4]; OTF_Tag tag; - int negate = 0; + int use_it = 1; if (*features == '*') { /* Consume all remaining features. */ - /* We are sure that the last LookupCount elements of - lookup_indices are free to be used for this work. */ - int *free_table = (lookup_indices + (LookupList->LookupCount - * FeatureList->FeatureCount)); - - for (i = 0; i < LookupList->LookupCount; i++) - free_table[i] = 0; for (i = 0; i < FeatureList->FeatureCount; i++) if (! feature_table[i]) { feature = FeatureList->Feature + i; for (j = 0; j < feature->LookupCount; j++) - free_table[feature->LookupListIndex[j]] = 1; + lookup_indices[n++] = feature->LookupListIndex[j]; } - for (i = 0; i < LookupList->LookupCount; i++) - if (free_table[i]) - lookup_indices[n++] = i; break; } if (*features == '~') - negate = 1, features++; + use_it = -1, features++; for (i = 0; *features && *features != ','; i++, features++) tagname[i] = *features; if (*features) @@ -195,10 +247,12 @@ setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList, feature = FeatureList->Feature + i; if (tag == feature->FeatureTag) { - if (! negate) + if (feature_table[i]) + break; + if (use_it > 0) for (j = 0; j < feature->LookupCount; j++) lookup_indices[n++] = feature->LookupListIndex[j]; - feature_table[i] = 1; + feature_table[i] = use_it; break; } } @@ -208,7 +262,8 @@ setup_lookup_indices (OTF_LookupList *LookupList, OTF_FeatureList *FeatureList, } static int -match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids) +match_ids (OTF_GlyphString *gstring, int gidx, int flag, + int count, OTF_GlyphID *ids) { OTF_Glyph *gbeg = gstring->glyphs + gidx; OTF_Glyph *gend = gstring->glyphs + gstring->used; @@ -216,36 +271,40 @@ match_ids (OTF_GlyphString *gstring, int gidx, int count, OTF_GlyphID *ids) int i; for (g = gbeg, i = 0; g < gend && i < count; g++) - if (g->glyph_id && g->glyph_id != ids[i++]) + if (! IGNORED_GLYPH (g, flag) && g->glyph_id != ids[i++]) return -1; return (i < count ? -1 : g - gbeg); } static int -match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule) +match_chain_ids (OTF_GlyphString *gstring, int gidx, int flag, + OTF_ChainRule *rule) { int i = rule->BacktrackGlyphCount; if (i > 0) { int j; + OTF_Glyph *g; - for (j = gidx - 1; j >= 0; j--) - if (gstring->glyphs[j].glyph_id - && --i == 0) + for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--) + if (! IGNORED_GLYPH (g, flag) && --i == 0) break; if (i > 0) return -1; - if (match_ids (gstring, j, rule->BacktrackGlyphCount, rule->Backtrack) + if (match_ids (gstring, j, flag, + rule->BacktrackGlyphCount, rule->Backtrack) < 0) return -1; } gidx++; - i = match_ids (gstring, gidx, rule->InputGlyphCount - 1, rule->Input); + i = match_ids (gstring, gidx, flag, + rule->InputGlyphCount - 1, rule->Input); if (i < 0) return -1; gidx += i; - i = match_ids (gstring, gidx, rule->LookaheadGlyphCount, rule->LookAhead); + i = match_ids (gstring, gidx, flag, + rule->LookaheadGlyphCount, rule->LookAhead); if (i < 0) return -1; return 0; @@ -253,7 +312,7 @@ match_chain_ids (OTF_GlyphString *gstring, int gidx, OTF_ChainRule *rule) static int match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx, - int count, unsigned *classes) + int flag, int count, unsigned *classes) { OTF_Glyph *gbeg = gstring->glyphs + gidx; OTF_Glyph *gend = gstring->glyphs + gstring->used; @@ -261,14 +320,14 @@ match_classes (OTF_ClassDef *class_def, OTF_GlyphString *gstring, int gidx, int i; for (g = gbeg, i = 0; g < gend && i < count; g++) - if (g->glyph_id + if (! IGNORED_GLYPH (g, flag) && get_class_def (class_def, g->glyph_id) != classes[i++]) return -1; return (i < count ? -1 : g - gbeg); } static int -match_chain_classes (OTF_GlyphString *gstring, int gidx, +match_chain_classes (OTF_GlyphString *gstring, int gidx, int flag, OTF_ClassDef *BacktrackClassDef, OTF_ClassDef *InputClassDef, OTF_ClassDef *LookaheadClassDef, @@ -279,24 +338,24 @@ match_chain_classes (OTF_GlyphString *gstring, int gidx, if (i > 0) { int j; + OTF_Glyph *g; - for (j = gidx - 1; j >= 0 && i > 0; j--) - if (gstring->glyphs[j].glyph_id - && i-- == 0) + for (j = gidx - 1, g = gstring->glyphs + j; j >= 0; j--, g--) + if (! IGNORED_GLYPH (g, flag) && i-- == 0) break; if (i > 0) return -1; - if (match_classes (BacktrackClassDef, gstring, j, + if (match_classes (BacktrackClassDef, gstring, j, flag, rule->BacktrackGlyphCount, rule->Backtrack) < 0); return -1; } gidx++; - i = match_classes (InputClassDef, gstring, gidx, + i = match_classes (InputClassDef, gstring, gidx, flag, rule->InputGlyphCount - 1, rule->Input); if (i < 0) return -1; gidx += i; - i = match_classes (LookaheadClassDef, gstring, gidx, + i = match_classes (LookaheadClassDef, gstring, gidx, flag, rule->LookaheadGlyphCount, rule->LookAhead); if (i < 0) return -1; @@ -305,7 +364,7 @@ match_chain_classes (OTF_GlyphString *gstring, int gidx, static int -match_coverages (OTF_GlyphString *gstring, int gidx, int count, +match_coverages (OTF_GlyphString *gstring, int gidx, int flag, int count, OTF_Coverage *coverages) { OTF_Glyph *gbeg = gstring->glyphs + gidx; @@ -314,14 +373,14 @@ match_coverages (OTF_GlyphString *gstring, int gidx, int count, int i; for (g = gbeg, i = 0; g < gend && i < count; g++) - if (g->glyph_id + if (! IGNORED_GLYPH (g, flag) && get_coverage_index (coverages + i++, g->glyph_id) < 0) return -1; return (i < count ? -1 : g - gbeg); } static int -match_chain_coverages (OTF_GlyphString *gstring, int gidx, +match_chain_coverages (OTF_GlyphString *gstring, int gidx, int flag, OTF_GSUB_ChainContext3 *context3) { int i = context3->BacktrackGlyphCount; @@ -329,47 +388,46 @@ match_chain_coverages (OTF_GlyphString *gstring, int gidx, if (i > 0) { int j; + OTF_Glyph *g; - for (j = gidx - 1; j >= 0; j--) - if (gstring->glyphs[j].glyph_id - && --i == 0) + for (j = gidx - 1, g= gstring->glyphs +j; j >= 0; j--, g--) + if (! IGNORED_GLYPH (g, flag) && --i == 0) break; if (i > 0) return -1; - if (match_coverages (gstring, j, context3->BacktrackGlyphCount, + if (match_coverages (gstring, j, flag, context3->BacktrackGlyphCount, context3->Backtrack) < 0) return -1; } gidx++; if (context3->InputGlyphCount > 1) { - i = match_coverages (gstring, gidx, context3->InputGlyphCount - 1, + i = match_coverages (gstring, gidx, flag, context3->InputGlyphCount - 1, context3->Input + 1); if (i < 0) return -1; gidx += i; } - if (match_coverages (gstring, gidx, context3->LookaheadGlyphCount, + if (match_coverages (gstring, gidx, flag, context3->LookaheadGlyphCount, context3->LookAhead) < 0) return -1; return 0; } static int -lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, - OTF_GlyphString *gstring, int gidx) +lookup_gsub (OTF *otf, OTF_LookupList *lookup_list, unsigned lookup_list_index, + OTF_GlyphString *gstring, int gidx, int alternate_subst) { char *errfmt = "GSUB Looking up%s"; int errret = -1; OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index; - unsigned int flag = lookup->LookupFlag; + unsigned int flag = (lookup->LookupFlag + & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType)); int orig_gidx = gidx; OTF_Glyph *g = gstring->glyphs + gidx; int i; - if (! g->glyph_id - || (g->GlyphClass - && (flag & (1 << g->GlyphClass)))) + if (IGNORED_GLYPH (g, flag)) return (gidx + 1); /* Try all subtables until one of them handles the current glyph. */ @@ -387,6 +445,11 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, subtable = extension1->ExtensionSubtable; } + if (alternate_subst + ? (lookup_type != 3 && lookup_type != 5 && lookup_type != 6) + : (lookup_type == 3)) + continue; + if (subtable->Coverage.offset) { coverage_idx = get_coverage_index (&subtable->Coverage, @@ -395,7 +458,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, continue; } - switch (lookup->LookupType) + switch (lookup_type) { case 1: if (subtable->Format == 1) @@ -406,14 +469,17 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, break; case 2: - { - OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1; - OTF_Sequence *seq = multiple1->Sequence + coverage_idx; + if (subtable->Format == 1) + { + OTF_GSUB_Multiple1 *multiple1 = &subtable->u.multiple1; + OTF_Sequence *seq = multiple1->Sequence + coverage_idx; - gstring_subst (gstring, gidx, gidx + 1, - seq->Substitute, seq->GlyphCount); - gidx += seq->GlyphCount; - } + gstring_subst (otf, gstring, gidx, gidx + 1, flag, + seq->Substitute, seq->GlyphCount); + gidx += seq->GlyphCount; + } + else + OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)"); break; case 3: @@ -422,8 +488,9 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, OTF_GSUB_Alternate1 *alt1 = &subtable->u.alternate1; OTF_AlternateSet *altset = alt1->AlternateSet + coverage_idx; - g->glyph_id = altset->Alternate[0]; - gidx++; + gstring_subst (otf, gstring, gidx, gidx + 1, flag, + altset->Alternate, altset->GlyphCount); + gidx += altset->GlyphCount;; } else OTF_ERROR (OTF_ERROR_GSUB_DRIVE, " (invalid SubFormat)"); @@ -442,11 +509,11 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, int n; lig = ligset->Ligature + j; - n = match_ids (gstring, gidx + 1, + n = match_ids (gstring, gidx + 1, flag, lig->CompCount - 1, lig->Component); if (n < 0) continue; - gstring_subst (gstring, gidx, gidx + 1 + n, + gstring_subst (otf, gstring, gidx, gidx + 1 + n, flag, &lig->LigGlyph, 1); gidx++; break; @@ -468,15 +535,16 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, for (j = 0; j < set->RuleCount; j++) { rule = set->Rule + j; - if (match_ids (gstring, gidx + 1, + if (match_ids (gstring, gidx + 1, flag, rule->GlyphCount - 1, rule->Input) < 0) continue; orig_used = gstring->used; for (k = 0; k < rule->LookupCount; k++) - lookup_gsub (lookup_list, + lookup_gsub (otf, lookup_list, rule->LookupRecord[k].LookupListIndex, gstring, - gidx + rule->LookupRecord[k].SequenceIndex); + gidx + rule->LookupRecord[k].SequenceIndex, + alternate_subst); gidx += rule->GlyphCount + (gstring->used - orig_used); break; } @@ -492,23 +560,25 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, class = get_class_def (&context2->ClassDef, g->glyph_id); set = context2->ClassSet + class; - for (j = 0; j < set->ClassRuleCnt; j++) - { - rule = set->ClassRule + j; - if (match_classes (&context2->ClassDef, - gstring, gidx + 1, - rule->GlyphCount - 1, rule->Class) - < 0) - continue; - orig_used = gstring->used; - for (k = 0; k < rule->LookupCount; k++) - lookup_gsub (lookup_list, - rule->LookupRecord[k].LookupListIndex, - gstring, - gidx + rule->LookupRecord[k].SequenceIndex); - gidx += rule->GlyphCount + (gstring->used - orig_used); - break; - } + if (set) + for (j = 0; j < set->ClassRuleCnt; j++) + { + rule = set->ClassRule + j; + if (match_classes (&context2->ClassDef, + gstring, gidx + 1, flag, + rule->GlyphCount - 1, rule->Class) + < 0) + continue; + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gsub (otf, lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex, + alternate_subst); + gidx += rule->GlyphCount + (gstring->used - orig_used); + break; + } } else /* subtable->Format == 3 */ { @@ -516,15 +586,17 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, int orig_used; int j; - if (match_coverages (gstring, gidx + 1, context3->GlyphCount - 1, + if (match_coverages (gstring, gidx + 1, flag, + context3->GlyphCount - 1, context3->Coverage + 1) < 0) continue; orig_used = gstring->used; for (j = 0; j < context3->LookupCount; j++) - lookup_gsub (lookup_list, + lookup_gsub (otf, lookup_list, context3->LookupRecord[j].LookupListIndex, gstring, - gidx + context3->LookupRecord[j].SequenceIndex); + gidx + context3->LookupRecord[j].SequenceIndex, + alternate_subst); gidx += context3->GlyphCount + (gstring->used - orig_used); } break; @@ -545,14 +617,15 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, || (gidx + rule->InputGlyphCount + rule->LookaheadGlyphCount) > gstring->used) continue; - if (match_chain_ids (gstring, gidx, rule) < 0) + if (match_chain_ids (gstring, gidx, flag, rule) < 0) continue; orig_used = gstring->used; for (k = 0; k < rule->LookupCount; k++) - lookup_gsub (lookup_list, + lookup_gsub (otf, lookup_list, rule->LookupRecord[k].LookupListIndex, gstring, - gidx + rule->LookupRecord[k].SequenceIndex); + gidx + rule->LookupRecord[k].SequenceIndex, + alternate_subst); gidx += rule->InputGlyphCount + (gstring->used - orig_used); break; } @@ -565,7 +638,6 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, int j; int orig_used; - // printf ("GSUB 6-2: c:0x%x g:0x%x\n", g->c, g->glyph_id); class = get_class_def (&context2->InputClassDef, g->glyph_id); set = context2->ChainClassSet + class; for (j = 0; j < set->ChainClassRuleCnt; j++) @@ -577,7 +649,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, || (gidx + rule->InputGlyphCount + rule->LookaheadGlyphCount) > gstring->used) continue; - if (match_chain_classes (gstring, gidx, + if (match_chain_classes (gstring, gidx, flag, &context2->BacktrackClassDef, &context2->InputClassDef, &context2->LookaheadClassDef, @@ -585,10 +657,11 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, continue; orig_used = gstring->used; for (k = 0; k < rule->LookupCount; k++) - lookup_gsub (lookup_list, + lookup_gsub (otf, lookup_list, rule->LookupRecord[k].LookupListIndex, gstring, - gidx + rule->LookupRecord[k].SequenceIndex); + gidx + rule->LookupRecord[k].SequenceIndex, + alternate_subst); gidx += rule->InputGlyphCount + (gstring->used - orig_used); break; } @@ -602,15 +675,16 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, if (gidx < context3->BacktrackGlyphCount || (gidx + context3->InputGlyphCount + context3->LookaheadGlyphCount) > gstring->used) - return -1; - if (match_chain_coverages (gstring, gidx, context3) < 0) + continue; + if (match_chain_coverages (gstring, gidx, flag, context3) < 0) continue; orig_used = gstring->used; for (j = 0; j < context3->LookupCount; j++) - lookup_gsub (lookup_list, + lookup_gsub (otf, lookup_list, context3->LookupRecord[j].LookupListIndex, gstring, - gidx + context3->LookupRecord[j].SequenceIndex); + gidx + context3->LookupRecord[j].SequenceIndex, + alternate_subst); gidx += context3->InputGlyphCount + (gstring->used - orig_used); } break; @@ -648,14 +722,7 @@ lookup_gsub (OTF_LookupList *lookup_list, unsigned lookup_list_index, } } if (gidx == orig_gidx) - { - //printf ("not applied\n"); - gidx++; - } - else - { - // printf ("done\n"); - } + gidx++; return gidx; } @@ -689,38 +756,43 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, char *errfmt = "GPOS Looking up%s"; int errret = -1; OTF_Lookup *lookup = lookup_list->Lookup + lookup_list_index; - unsigned int flag = lookup->LookupFlag; + unsigned int flag = (lookup->LookupFlag + & (OTF_LookupFlagIgnoreMask | OTF_MarkAttachmentType)); int orig_gidx = gidx; OTF_Glyph *g = gstring->glyphs + gidx; int i; - if (! g->glyph_id - || (g->GlyphClass - && (flag & (1 << g->GlyphClass)))) + if (IGNORED_GLYPH (g, flag) + || (0 & g->positioning_type)) return (gidx + 1); /* Try all subtables until one of them handles the current glyph. */ for (i = 0; i < lookup->SubTableCount && gidx == orig_gidx; i++) { + unsigned lookup_type = lookup->LookupType; OTF_LookupSubTableGPOS *subtable = lookup->SubTable.gpos + i; int coverage_idx; - // printf ("subtype:%d ", subtable->Format); + if (lookup_type == 9) + { + OTF_GPOS_Extension1 *extension1 = &subtable->u.extension1; + + lookup_type = extension1->ExtensionLookupType; + subtable = extension1->ExtensionSubtable; + } + if (subtable->Coverage.offset) { coverage_idx = get_coverage_index (&subtable->Coverage, g->glyph_id); if (coverage_idx < 0) - { - // printf ("not covererd "); - continue; - } + continue; } - switch (lookup->LookupType) + switch (lookup_type) { case 1: - g->positioning_type = lookup->LookupType; + g->positioning_type = lookup_type; if (subtable->Format == 1) { OTF_GPOS_Single1 *single1 = &subtable->u.single1; @@ -738,60 +810,75 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, break; case 2: - if (gidx + 1 >= gstring->used) - continue; - if (subtable->Format == 1) - { - OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1; - OTF_PairSet *set = pair1->PairSet + coverage_idx; - int j; + { + int next_gidx; + OTF_Glyph *nextg; - for (j = 0; j < set->PairValueCount; j++) - { - if (set->PairValueRecord[j].SecondGlyph != g[1].glyph_id) - continue; - gidx++; - g->positioning_type = lookup->LookupType; - g->f.f2.format = pair1->ValueFormat1; - g->f.f2.value = &set->PairValueRecord[j].Value1; - if (pair1->ValueFormat2) + for (next_gidx = gidx + 1, nextg = gstring->glyphs + next_gidx; + next_gidx < gstring->used && IGNORED_GLYPH (nextg, flag); + next_gidx++, nextg++); + + if (next_gidx >= gstring->used + || nextg->positioning_type) + continue; + if (subtable->Format == 1) + { + OTF_GPOS_Pair1 *pair1 = &subtable->u.pair1; + OTF_PairSet *set = pair1->PairSet + coverage_idx; + int j; + + for (j = 0; j < set->PairValueCount; j++) + if (set->PairValueRecord[j].SecondGlyph == nextg->glyph_id) { - g++, gidx++; - g->positioning_type = lookup->LookupType; - g->f.f2.format = pair1->ValueFormat2; - g->f.f2.value = &set->PairValueRecord[j].Value2; + if (pair1->ValueFormat1) + { + g->positioning_type = lookup_type; + g->f.f2.format = pair1->ValueFormat1; + g->f.f2.value = &set->PairValueRecord[j].Value1; + } + gidx = next_gidx; + if (pair1->ValueFormat2) + { + nextg->positioning_type = lookup_type; + nextg->f.f2.format = pair1->ValueFormat2; + nextg->f.f2.value = &set->PairValueRecord[j].Value2; + gidx++; + } + break; } - } - } - else if (subtable->Format == 2) - { - OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2; - unsigned class1, class2; - - // printf ("GPOS 2-2: c:0x%x g:0x%x\n", g->c, g->glyph_id); - gidx++; - class1 = get_class_def (&pair2->ClassDef1, g->glyph_id); - class2 = get_class_def (&pair2->ClassDef2, g[1].glyph_id); - g->positioning_type = lookup->LookupType; - g->f.f2.format = pair2->ValueFormat1; - g->f.f2.value - = &pair2->Class1Record[class1].Class2Record[class2].Value1; - if (pair2->ValueFormat2) - { - g++, gidx++; - g->positioning_type = lookup->LookupType; - g->f.f2.format = pair2->ValueFormat2; - g->f.f2.value - = &pair2->Class1Record[class1].Class2Record[class2].Value2; - } - } + } + else if (subtable->Format == 2) + { + OTF_GPOS_Pair2 *pair2 = &subtable->u.pair2; + unsigned class1, class2; + + class1 = get_class_def (&pair2->ClassDef1, g->glyph_id); + class2 = get_class_def (&pair2->ClassDef2, nextg->glyph_id); + if (pair2->ValueFormat1) + { + g->positioning_type = lookup_type; + g->f.f2.format = pair2->ValueFormat1; + g->f.f2.value + = &pair2->Class1Record[class1].Class2Record[class2].Value1; + } + gidx = next_gidx; + if (pair2->ValueFormat2) + { + nextg->positioning_type = lookup_type; + nextg->f.f2.format = pair2->ValueFormat2; + nextg->f.f2.value + = &pair2->Class1Record[class1].Class2Record[class2].Value2; + gidx++; + } + } + } break; case 3: { OTF_GPOS_Cursive1 *cursive1 = &subtable->u.cursive1; - g->positioning_type = lookup->LookupType; + g->positioning_type = lookup_type; g->f.f3.entry_anchor = &cursive1->EntryExitRecord[coverage_idx].EntryAnchor; g->f.f3.exit_anchor @@ -807,21 +894,27 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, OTF_GPOS_MarkBase1 *mark_base1 = &subtable->u.mark_base1; OTF_MarkRecord *mark_record; OTF_AnchorRecord *base_record; - int coverage_idx_base + OTF_Glyph *baseg; + int coverage_idx_base; + unsigned int this_flag = flag | OTF_IgnoreMarks; + + for (baseg = g - 1; + baseg >= gstring->glyphs && IGNORED_GLYPH (baseg, this_flag); + baseg--); + if (baseg < gstring->glyphs) + continue; + coverage_idx_base = get_coverage_index (&mark_base1->BaseCoverage, - g[-1].glyph_id); - + baseg->glyph_id); if (coverage_idx_base < 0) continue; - // printf ("GPOS 4-1: c:0x%x g:0x%x\n", g->c, g->glyph_id); mark_record = mark_base1->MarkArray.MarkRecord + coverage_idx; base_record = mark_base1->BaseArray.AnchorRecord + coverage_idx_base; g->f.f4.mark_anchor = &mark_record->MarkAnchor; g->f.f4.base_anchor = &base_record->Anchor[mark_record->Class]; - g->positioning_type = lookup->LookupType; - break; + g->positioning_type = lookup_type; } break; @@ -830,10 +923,50 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, continue; if (subtable->Format == 1) { - /* As the document of this lookup type is quite - ambiguous, and we can't know the exact procedure to - handle it?!? */ - OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + OTF_GPOS_MarkLig1 *mark_lig1 = &subtable->u.mark_lig1; + OTF_Glyph *ligg; + int coverage_idx_lig; + OTF_MarkRecord *mark_record; + OTF_LigatureAttach *attach; + int *num_class = alloca (sizeof (int) * mark_lig1->ClassCount); + int j; + + for (j = 0; j < mark_lig1->ClassCount; j++) + num_class[j] = 0; + + for (ligg = g - 1; + (ligg >= gstring->glyphs + && (IGNORED_GLYPH (ligg, flag) + || ligg->GlyphClass > OTF_GlyphClassLigature)); + ligg--) + if (ligg->positioning_type == 5 + && ligg->MarkAttachClass < mark_lig1->ClassCount) + num_class[ligg->MarkAttachClass]++; + if (ligg < gstring->glyphs) + continue; + coverage_idx_lig + = get_coverage_index (&mark_lig1->LigatureCoverage, + ligg->glyph_id); + if (coverage_idx_lig < 0) + continue; + mark_record = mark_lig1->MarkArray.MarkRecord + coverage_idx; + g->MarkAttachClass = mark_record->Class; + attach = (mark_lig1->LigatureArray.LigatureAttach + + coverage_idx_lig); + for (j = 0; j < attach->ComponentCount; j++) + { + OTF_Anchor *lig_anchor + = attach->ComponentRecord[j].LigatureAnchor; + + if (lig_anchor[mark_record->Class].AnchorFormat + && num_class[mark_record->Class]-- == 0) + { + g->positioning_type = lookup_type; + g->f.f5.mark_anchor = &mark_record->MarkAnchor; + g->f.f5.ligature_anchor = lig_anchor + mark_record->Class; + break; + } + } } break; @@ -845,31 +978,133 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, OTF_GPOS_MarkMark1 *mark_mark1 = &subtable->u.mark_mark1; OTF_MarkRecord *mark1_record; OTF_AnchorRecord *mark2_record; - int coverage_idx_base - = get_coverage_index (&mark_mark1->Mark2Coverage, - g[-1].glyph_id); + OTF_Glyph *prevg; + int coverage_idx_base; + for (prevg = g - 1; + prevg >= gstring->glyphs && IGNORED_GLYPH (prevg, flag); + prevg--); + if (prevg < gstring->glyphs) + continue; + coverage_idx_base + = get_coverage_index (&mark_mark1->Mark2Coverage, + prevg->glyph_id); if (coverage_idx_base < 0) continue; - // printf ("GPOS 6-1: c:0x%x g:0x%x\n", g->c, g->glyph_id); mark1_record = mark_mark1->Mark1Array.MarkRecord + coverage_idx; mark2_record = mark_mark1->Mark2Array.AnchorRecord + coverage_idx_base; g->f.f6.mark1_anchor = &mark1_record->MarkAnchor; g->f.f6.mark2_anchor = &mark2_record->Anchor[mark1_record->Class]; - g->positioning_type = lookup->LookupType; + g->positioning_type = lookup_type; break; } break; case 7: - OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + if (subtable->Format == 1) + { + OTF_GPOS_Context1 *context1 = &subtable->u.context1; + OTF_RuleSet *set = context1->RuleSet + coverage_idx; + OTF_Rule *rule; + int orig_used; + int j, k; + + for (j = 0; j < set->RuleCount; j++) + { + rule = set->Rule + j; + if (match_ids (gstring, gidx + 1, flag, + rule->GlyphCount - 1, rule->Input) < 0) + continue; + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gpos (lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex); + gidx += rule->GlyphCount + (gstring->used - orig_used); + break; + } + } + else if (subtable->Format == 2) + { + OTF_GPOS_Context2 *context2 = &subtable->u.context2; + OTF_ClassSet *set; + OTF_ClassRule *rule; + unsigned class; + int orig_used; + int j, k; + + class = get_class_def (&context2->ClassDef, g->glyph_id); + set = context2->ClassSet + class; + if (set) + for (j = 0; j < set->ClassRuleCnt; j++) + { + rule = set->ClassRule + j; + if (match_classes (&context2->ClassDef, + gstring, gidx + 1, flag, + rule->GlyphCount - 1, rule->Class) + < 0) + continue; + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gpos (lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex); + gidx += rule->GlyphCount + (gstring->used - orig_used); + break; + } + } + else /* subtable->Format == 3 */ + { + OTF_GPOS_Context3 *context3 = &subtable->u.context3; + int orig_used; + int j; + + if (match_coverages (gstring, gidx + 1, flag, + context3->GlyphCount - 1, + context3->Coverage + 1) < 0) + continue; + orig_used = gstring->used; + for (j = 0; j < context3->LookupCount; j++) + lookup_gpos (lookup_list, + context3->LookupRecord[j].LookupListIndex, + gstring, + gidx + context3->LookupRecord[j].SequenceIndex); + gidx += context3->GlyphCount + (gstring->used - orig_used); + } break; case 8: if (subtable->Format == 1) - OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + { + OTF_GPOS_ChainContext1 *context1 = &subtable->u.chain_context1; + OTF_ChainRuleSet *set = context1->ChainRuleSet + coverage_idx; + int orig_used; + int j, k; + + for (j = 0; j < set->ChainRuleCount; j++) + { + OTF_ChainRule *rule = set->ChainRule + j; + + if (gidx < rule->BacktrackGlyphCount + || (gidx + rule->InputGlyphCount + + rule->LookaheadGlyphCount) > gstring->used) + continue; + if (match_chain_ids (gstring, gidx, flag, rule) < 0) + continue; + orig_used = gstring->used; + for (k = 0; k < rule->LookupCount; k++) + lookup_gpos (lookup_list, + rule->LookupRecord[k].LookupListIndex, + gstring, + gidx + rule->LookupRecord[k].SequenceIndex); + gidx += rule->InputGlyphCount + (gstring->used - orig_used); + break; + } + } else if (subtable->Format == 2) { OTF_GPOS_ChainContext2 *context2 = &subtable->u.chain_context2; @@ -878,41 +1113,23 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, int j; int orig_used; - // printf ("GPOS 8-2: c:0x%x g:0x%x\n", g->c, g->glyph_id); class = get_class_def (&context2->InputClassDef, g->glyph_id); set = context2->ChainClassSet + class; for (j = 0; j < set->ChainClassRuleCnt; j++) { OTF_ChainClassRule *rule = set->ChainClassRule + j; - int fore_idx = gidx + rule->InputGlyphCount; int k; if (gidx < rule->BacktrackGlyphCount || (gidx + rule->InputGlyphCount + rule->LookaheadGlyphCount) > gstring->used) continue; - for (k = 0; k < rule->BacktrackGlyphCount; k++) - if (get_class_def (&context2->BacktrackClassDef, - gstring->glyphs[gidx - 1 - k].glyph_id) - != rule->Backtrack[k]) - break; - if (k < rule->BacktrackGlyphCount) - continue; - for (k = 1; k < rule->InputGlyphCount; k++) - if (get_class_def (&context2->InputClassDef, - gstring->glyphs[gidx + k].glyph_id) - != rule->Input[k - 1]) - break; - if (k < rule->InputGlyphCount) - continue; - for (k = 0; k < rule->LookaheadGlyphCount; k++) - if (get_class_def (&context2->LookaheadClassDef, - gstring->glyphs[fore_idx + k].glyph_id) - != rule->LookAhead[k]) - break; - if (k < rule->LookaheadGlyphCount) + if (match_chain_classes (gstring, gidx, flag, + &context2->BacktrackClassDef, + &context2->InputClassDef, + &context2->LookaheadClassDef, + rule) < 0) continue; - orig_used = gstring->used; for (k = 0; k < rule->LookupCount; k++) lookup_gpos (lookup_list, @@ -924,29 +1141,113 @@ lookup_gpos (OTF_LookupList *lookup_list, unsigned lookup_list_index, } } else if (subtable->Format == 3) - OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); + { + OTF_GPOS_ChainContext3 *context3 = &subtable->u.chain_context3; + int orig_used; + int j; + + if (gidx < context3->BacktrackGlyphCount + || (gidx + context3->InputGlyphCount + + context3->LookaheadGlyphCount) > gstring->used) + continue; + if (match_chain_coverages (gstring, gidx, flag, context3) < 0) + continue; + orig_used = gstring->used; + for (j = 0; j < context3->LookupCount; j++) + lookup_gpos (lookup_list, + context3->LookupRecord[j].LookupListIndex, + gstring, + gidx + context3->LookupRecord[j].SequenceIndex); + gidx += context3->InputGlyphCount + (gstring->used - orig_used); + } else OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (invalid subformat)"); break; - case 9: - OTF_ERROR (OTF_ERROR_GPOS_DRIVE, " (not yet supported)"); - break; - default: continue; } } if (gidx == orig_gidx) + gidx++; + return gidx; +} + +static int +lookup_encoding_0 (OTF_EncodingSubtable0 *sub0, OTF_GlyphString *gstring) +{ + int i, c; + + for (i = 0; i < gstring->used; i++) { - // printf ("not applied\n"); - gidx++; + c = gstring->glyphs[i].c; + if (c < 0 || c >= 256) + gstring->glyphs[i].glyph_id = 0; + else + gstring->glyphs[i].glyph_id = sub0->glyphIdArray[c]; } - else + return 0; +} + +static int +lookup_encoding_2 (OTF_EncodingSubtable2 *sub2, OTF_GlyphString *gstring) +{ + return 0; +} + +static int +lookup_encoding_4 (OTF_EncodingSubtable4 *sub4, OTF_GlyphString *gstring) +{ + int i, j, c; + int segCount = sub4->segCountX2 / 2; + + for (i = 0; i < gstring->used; i++) { - // printf ("done\n"); + c = gstring->glyphs[i].c; + if (c < 0) + gstring->glyphs[i].glyph_id = 0; + for (j = 0; j < segCount; j++) + { + OTF_cmapSegument *seg = sub4->segments + i; + + if (c >= seg->startCount && c <= seg->endCount) + { + if (seg->idRangeOffset == 0xFFFF) + gstring->glyphs[i].glyph_id = c + seg->idDelta; + else + gstring->glyphs[i].glyph_id + = sub4->glyphIdArray[seg->idRangeOffset + + (c - seg->startCount)]; + break; + } + } } - return gidx; + + return 0; +} + +static int +lookup_encoding_6 (OTF_EncodingSubtable6 *sub6, OTF_GlyphString *gstring) +{ + return 0; +} + +static int +lookup_encoding_8 (OTF_EncodingSubtable8 *sub8, OTF_GlyphString *gstring) +{ + return 0; +} + +static int +lookup_encoding_10 (OTF_EncodingSubtable10 *sub10, OTF_GlyphString *gstring) +{ + return 0; +} + +static int +lookup_encoding_12 (OTF_EncodingSubtable12 *sub12, OTF_GlyphString *gstring) +{ + return 0; } @@ -976,6 +1277,43 @@ OTF_drive_cmap (OTF *otf, OTF_GlyphString *gstring) return 0; } + +int +OTF_drive_cmap2 (OTF *otf, OTF_GlyphString *gstring, + int platform_id, int encoding_id) +{ + OTF_cmap *cmap; + int i; + char *errfmt = "CMAP Looking up%s"; + int errret = -1; + OTF_EncodingRecord *enc; + + if (! otf->cmap + && OTF_get_table (otf, "cmap") < 0) + return -1; + + cmap = otf->cmap; + for (i = 0; i < cmap->numTables; i++) + if (cmap->EncodingRecord[i].platformID == platform_id + && cmap->EncodingRecord[i].encodingID == encoding_id) + break; + if (i == cmap->numTables) + OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (unknown platformID/encodingID)"); + enc = cmap->EncodingRecord + i; + switch (enc->subtable.format) + { + case 0: return lookup_encoding_0 (enc->subtable.f.f0, gstring); + case 2: return lookup_encoding_2 (enc->subtable.f.f2, gstring); + case 4: return lookup_encoding_4 (enc->subtable.f.f4, gstring); + case 6: return lookup_encoding_6 (enc->subtable.f.f6, gstring); + case 8: return lookup_encoding_8 (enc->subtable.f.f8, gstring); + case 10: return lookup_encoding_10 (enc->subtable.f.f10, gstring); + case 12: return lookup_encoding_12 (enc->subtable.f.f12, gstring); + } + OTF_ERROR (OTF_ERROR_CMAP_DRIVE, " (invalid format)"); +} + + int OTF_get_unicode (OTF *otf, OTF_GlyphID code) { @@ -1015,10 +1353,11 @@ OTF_drive_gdef (OTF *otf, OTF_GlyphString *gstring) return 0; } - -int -OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring, - char *script, char *language, char *features) +static int +OTF_drive_gsub_internal (OTF *otf, OTF_GlyphString *gstring, + const char *script, const char *language, + const char *features, + int alternate_subst) { char *errfmt = "GSUB driving%s"; int errret = -1; @@ -1027,8 +1366,13 @@ OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring, int *lookup_indices; int i, n; - if (! otf->gsub - && OTF_get_table (otf, "GSUB") < 0) + for (i = 0; i < gstring->used; i++) + { + gstring->glyphs[i].positioning_type = 0; + gstring->glyphs[i].f.index.from = gstring->glyphs[i].f.index.to = i; + } + + if (OTF_get_table (otf, "GSUB") < 0) return errret; gsub = otf->gsub; if (gsub->FeatureList.FeatureCount == 0 @@ -1060,7 +1404,8 @@ OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring, gidx = 0; while (gidx < gstring->used) { - gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx); + gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx, + alternate_subst); if (gidx < 0) return errret; } @@ -1070,7 +1415,8 @@ OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring, gidx = gstring->used - 1; while (gidx >= 0) { - gidx = lookup_gsub (&gsub->LookupList, index, gstring, gidx); + gidx = lookup_gsub (otf, &gsub->LookupList, index, gstring, gidx, + alternate_subst); if (gidx < 0) return errret; } @@ -1081,8 +1427,17 @@ OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring, } int +OTF_drive_gsub (OTF *otf, OTF_GlyphString *gstring, + const char *script, const char *language, const char *features) +{ + if (! otf->cmap) + OTF_get_table (otf, "cmap"); + return OTF_drive_gsub_internal (otf, gstring, script, language, features, 0); +} + +int OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring, - char *script, char *language, char *features) + const char *script, const char *language, const char *features) { char *errfmt = "GPOS driving%s"; int errret = -1; @@ -1091,8 +1446,10 @@ OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring, int *lookup_indices; int i, n; - if (! otf->gpos - && OTF_get_table (otf, "GPOS") < 0) + for (i = 0; i < gstring->used; i++) + gstring->glyphs[i].positioning_type = 0; + + if (OTF_get_table (otf, "GPOS") < 0) return errret; gpos = otf->gpos; if (gpos->FeatureList.FeatureCount == 0 @@ -1132,8 +1489,8 @@ OTF_drive_gpos (OTF *otf, OTF_GlyphString *gstring, int OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring, - char *script, char *language, - char *gsub_features, char *gpos_features) + const char *script, const char *language, + const char *gsub_features, const char *gpos_features) { if (OTF_drive_cmap (otf, gstring) < 0) return -1; @@ -1147,3 +1504,11 @@ OTF_drive_tables (OTF *otf, OTF_GlyphString *gstring, return -1; return 0; } + +int +OTF_drive_gsub_alternate (OTF *otf, OTF_GlyphString *gstring, + const char *script, const char *language, + const char *features) +{ + return OTF_drive_gsub_internal (otf, gstring, script, language, features, 1); +}