diff options
Diffstat (limited to 'Build/source/texk/dvipdfm-x/tt_gsub.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/tt_gsub.c | 175 |
1 files changed, 171 insertions, 4 deletions
diff --git a/Build/source/texk/dvipdfm-x/tt_gsub.c b/Build/source/texk/dvipdfm-x/tt_gsub.c index 3151e9ed9f7..86d5e8c0e5e 100644 --- a/Build/source/texk/dvipdfm-x/tt_gsub.c +++ b/Build/source/texk/dvipdfm-x/tt_gsub.c @@ -1269,10 +1269,16 @@ otl_gsub_apply_ligature (struct otl_gsub_subtab *subtab, } #define GSUB_LIST_MAX 32 +struct gsub_entry { + int index; + struct gsub_entry *next; +}; + struct otl_gsub { int num_gsubs; int select; + struct gsub_entry *first; struct otl_gsub_tab gsubs[GSUB_LIST_MAX]; }; @@ -1284,10 +1290,21 @@ otl_gsub_new (void) gsub_list = NEW(1, struct otl_gsub); gsub_list->num_gsubs = 0; gsub_list->select = -1; + gsub_list->first = NULL; return (otl_gsub *) gsub_list; } +static void +clear_chain (otl_gsub *gsub_list) { + struct gsub_entry *entry, *next; + for (entry = gsub_list->first; entry != NULL; entry = next) { + next = entry->next; + RELEASE(entry); + } + gsub_list->first = NULL; +} + int otl_gsub_add_feat (otl_gsub *gsub_list, const char *script, @@ -1342,6 +1359,56 @@ otl_gsub_add_feat (otl_gsub *gsub_list, return retval; } +static const char * +scan_otl_tag (const char *otl_tags, const char *endptr, + char *script, char *language, char *feature) +{ + const char *p, *period; + + ASSERT(script && language && feature); + ASSERT(otl_tags < endptr); + + if (!otl_tags) + return NULL; + + memset(script, ' ', 4); script[4] = 0; + memset(language, ' ', 4); language[4] = 0; + memset(feature, ' ', 4); feature[4] = 0; + + /* First parse otl_tags variable */ + p = otl_tags; + period = strchr(p, '.'); + if (period && period < endptr) { + /* Format scrp.lang.feat */ + if (period < p + 5) { + strncpy(script, p, period - p); + } else { + WARN("Invalid OTL script tag found: %s", p); + } + p = period + 1; + period = strchr(p, '.'); + if (period && period < endptr) { + /* Now lang part */ + if (period < p + 5) { + strncpy(language, p, period - p); + } else { + WARN("Invalid OTL lanuage tag found: %s", p); + } + p = period + 1; + } + } else { + strcpy(script, "*"); + strcpy(language, "*"); + } + /* Finally feature */ + if (p < endptr) { + strncpy(feature, p, endptr - p); + p = endptr; + } + + return p; +} + void otl_gsub_release (otl_gsub *gsub_list) { @@ -1381,7 +1448,7 @@ otl_gsub_release (otl_gsub *gsub_list) } RELEASE(gsub->subtables); } - + clear_chain(gsub_list); RELEASE(gsub_list); } @@ -1487,7 +1554,7 @@ otl_gsub_apply_lig (otl_gsub *gsub_list, } int -otl_gsub_select (otl_gsub *gsub_list, +gsub_find (otl_gsub *gsub_list, const char *script, const char *language, const char *feature) @@ -1500,14 +1567,114 @@ otl_gsub_select (otl_gsub *gsub_list, if (!strcmp(gsub->script, script) && !strcmp(gsub->language, language) && !strcmp(gsub->feature, feature)) { - gsub_list->select = i; return i; } } - gsub_list->select = -1; + return -1; +} + +int +otl_gsub_select (otl_gsub *gsub_list, + const char *script, + const char *language, + const char *feature) +{ + gsub_list->select = gsub_find(gsub_list, script, language, feature); + return gsub_list->select; +} + +int +otl_gsub_set_chain (otl_gsub *gsub_list, const char *otl_tags) { + struct gsub_entry *prev = NULL; + const char *p, *nextptr, *endptr; + char script[5], language[5], feature[5]; + int idx; + + clear_chain(gsub_list); + + endptr = otl_tags + strlen(otl_tags); + for (p = otl_tags; p < endptr; p = nextptr) { + nextptr = strchr(p, ':'); + if (!nextptr) + nextptr = endptr; + scan_otl_tag(p, nextptr, script, language, feature); + idx = gsub_find(gsub_list, script, language, feature); + if (idx >= 0 && idx <= gsub_list->num_gsubs) { + struct gsub_entry *entry; + entry = NEW(1, struct gsub_entry); + if (prev) + prev->next = entry; + entry->index = idx; + prev = entry; + } + nextptr++; + } + if (prev) + prev->next = NULL; + gsub_list->first = prev; + + return 0; +} + +int +otl_gsub_add_feat_list (otl_gsub *gsub_list, const char *otl_tags, sfnt *sfont) +{ + const char *p, *nextptr, *endptr; + char script[5], language[5], feature[5]; + int idx; + if (!gsub_list || !otl_tags || !sfont) return -1; + + clear_chain(gsub_list); + endptr = otl_tags + strlen(otl_tags); + for (p = otl_tags; p < endptr; p = nextptr) { + nextptr = strchr(p, ':'); + if (!nextptr) + nextptr = endptr; + scan_otl_tag(p, nextptr, script, language, feature); + idx = gsub_find(gsub_list, script, language, feature); + if (idx < 0) { + otl_gsub_add_feat(gsub_list, script, language, feature, sfont); + } + nextptr++; + } + + return 0; +} + +int +otl_gsub_apply_chain (otl_gsub *gsub_list, USHORT *gid) { + int retval = -1; + struct otl_gsub_tab *gsub; + struct otl_gsub_subtab *subtab; + struct gsub_entry *entry; + int i, idx; + + if (!gsub_list || !gid) + return retval; + + for (entry = gsub_list->first; + entry != NULL; entry = entry->next) { + idx = entry->index; + if (idx < 0 || idx >= gsub_list->num_gsubs) + continue; + gsub = &(gsub_list->gsubs[idx]); + for (i = 0, retval = -1; + retval < 0 && i < gsub->num_subtables; i++) { + subtab = &(gsub->subtables[i]); + switch ((int) subtab->LookupType){ + case OTL_GSUB_TYPE_SINGLE: + retval = otl_gsub_apply_single(subtab, gid); + break; + default: + break; + } + } + } + + return retval; } #if 0 |