diff options
author | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2019-05-02 22:41:16 +0000 |
---|---|---|
committer | Akira Kakuto <kakuto@fuk.kindai.ac.jp> | 2019-05-02 22:41:16 +0000 |
commit | ca41953d8194eb312599a487346a176bf07cda55 (patch) | |
tree | 157b2124306cadbe088fcb5cbf937d26d612468d /Build/source/texk/dvipdfm-x/tt_gsub.c | |
parent | 76e559e4657cc54e211e35d7ae6fdb91f89ee034 (diff) |
Support ASCIIHex and ASCII85 Decode filters. Revise ToUnicode CMap creation for OpenType. (S. Hirata)
git-svn-id: svn://tug.org/texlive/trunk@50943 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipdfm-x/tt_gsub.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/tt_gsub.c | 368 |
1 files changed, 285 insertions, 83 deletions
diff --git a/Build/source/texk/dvipdfm-x/tt_gsub.c b/Build/source/texk/dvipdfm-x/tt_gsub.c index 0ae31330749..d88d729e7d1 100644 --- a/Build/source/texk/dvipdfm-x/tt_gsub.c +++ b/Build/source/texk/dvipdfm-x/tt_gsub.c @@ -1,6 +1,6 @@ /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks. - Copyright (C) 2002-2018 by Jin-Hwan Cho and Shunsaku Hirata, + Copyright (C) 2002-2019 by Jin-Hwan Cho and Shunsaku Hirata, the dvipdfmx project team. This program is free software; you can redistribute it and/or modify @@ -977,10 +977,11 @@ otl_gsub_read_feat (struct otl_gsub_tab *gsub, sfnt *sfont) sfnt_seek_set(sfont, offset); clt_read_feature_table(&feature_table, sfont); +#if 0 if (feature_table.FeatureParams != 0) { ERROR("unrecognized FeatureParams"); } - +#endif /* Lookup table */ for (i = 0; i < feature_table.LookupListIndex.count; i++) { struct clt_lookup_table lookup_table; @@ -1680,98 +1681,303 @@ otl_gsub_apply_chain (otl_gsub *gsub_list, USHORT *gid) { return retval; } -#if 0 +#if 1 +#include "unicode.h" + +#ifndef is_used_char2 +#define is_used_char2(b,c) (((b)[(c)/8]) & (1 << (7-((c)%8)))) +#endif + +static int +add_glyph_if_valid (CMap *cmap, char *used_chars, + int32_t *map_base, int32_t *map_sub, USHORT num_glyphs, + uint16_t *GIDToCIDMap, USHORT gid, USHORT gid_sub) +{ + int count = 0; + unsigned char src[2], dst[4]; + unsigned char *p = dst, *endptr = dst + 4; + size_t len; + uint16_t cid_sub; + + if (gid_sub >= num_glyphs || gid >= num_glyphs) + return 0; + + cid_sub = GIDToCIDMap[gid_sub]; + if (is_used_char2(used_chars, cid_sub)) { + int32_t ch = map_base[gid]; + if (UC_is_valid(ch)) { + src[0] = (cid_sub >> 8) & 0xff; + src[1] = cid_sub & 0xff; + len = UC_UTF16BE_encode_char(ch, &p, endptr); + CMap_add_bfchar(cmap, src, 2, dst, len); + used_chars[cid_sub / 8] &= ~(1 << (7 - (cid_sub % 8))); + count = 1; + } else { + ch = map_sub[gid]; + if (UC_is_valid(ch)) { + src[0] = (cid_sub >> 8) & 0xff; + src[1] = cid_sub & 0xff; + len = UC_UTF16BE_encode_char(ch, &p, endptr); + CMap_add_bfchar(cmap, src, 2, dst, len); + used_chars[cid_sub / 8] &= ~(1 << (7 - (cid_sub % 8))); + count = 1; + } + } + } + return count; +} + static int -otl_gsub_dump_single (struct otl_gsub_subtab *subtab) +add_ToUnicode_single (CMap *cmap, char *used_chars, + struct otl_gsub_subtab *subtab, + int32_t *map_base, int32_t *map_sub, USHORT num_glyphs, + uint16_t *GIDToCIDMap) { - int gid, idx; + int count = 0; + USHORT i, idx, gid; + USHORT gid_sub; ASSERT(subtab); if (subtab->SubstFormat == 1) { struct otl_gsub_single1 *data; + struct clt_coverage *cov; data = (subtab->table).single1; - for (gid = 0; gid < 0x10000; gid++) { - idx = clt_lookup_coverage(&data->coverage, gid); - if (idx >= 0) { - fprintf(stdout, "substitute \\%u by \\%u;\n", - (USHORT) gid, (USHORT) (gid + data->DeltaGlyphID)); + cov = &data->coverage; + switch (cov->format) { + case 1: /* list */ + for (idx = 0; idx < cov->count; idx++) { + gid = cov->list[idx]; + gid_sub = gid + data->DeltaGlyphID; + count += add_glyph_if_valid(cmap, used_chars, + map_base, map_sub, num_glyphs, + GIDToCIDMap, gid, gid_sub); } + break; + case 2: /* range */ + for (i = 0; i < cov->count; i++) { + for (gid = cov->range[i].Start; + gid <= cov->range[i].End && gid < num_glyphs; gid++) { + idx = cov->range[i].StartCoverageIndex + gid - cov->range[i].Start; + gid_sub = gid + data->DeltaGlyphID; + count += add_glyph_if_valid(cmap, used_chars, + map_base, map_sub, num_glyphs, + GIDToCIDMap, gid, gid_sub); + } + } + break; } } else if (subtab->SubstFormat == 2) { struct otl_gsub_single2 *data; + struct clt_coverage *cov; data = (subtab->table).single2; - for (gid = 0; gid < 0x10000; gid++) { - idx = clt_lookup_coverage(&data->coverage, gid); - if (idx >= 0 && - idx < data->GlyphCount) { - fprintf(stdout, "substitute \\%u by \\%u;\n", - (USHORT) gid, (data->Substitute)[idx]); + cov = &data->coverage; + switch (cov->format) { + case 1: /* list */ + for (idx = 0; idx < cov->count; idx++) { + gid = cov->list[idx]; + if (idx >= 0 && idx < data->GlyphCount) { + gid_sub = (data->Substitute)[idx]; + count += add_glyph_if_valid(cmap, used_chars, + map_base, map_sub, num_glyphs, + GIDToCIDMap, gid, gid_sub); + } } + break; + case 2: /* range */ + for (i = 0; i < cov->count; i++) { + for (gid = cov->range[i].Start; + gid <= cov->range[i].End && gid < num_glyphs; gid++) { + idx = cov->range[i].StartCoverageIndex + gid - cov->range[i].Start; + if (idx >= 0 && idx < data->GlyphCount) { + gid_sub = (data->Substitute)[idx]; + count += add_glyph_if_valid(cmap, used_chars, + map_base, map_sub, num_glyphs, + GIDToCIDMap, gid, gid_sub); + } + } + } + break; } } - return 0; + return count; } -static int -otl_gsub_dump_alternate (struct otl_gsub_subtab *subtab) +static int32_t +add_alternate1_inverse_map (CMap *cmap, char *used_chars, + int32_t *map_base, int32_t *map_sub, USHORT num_glyphs, + uint16_t *GIDToCIDMap, USHORT gid, int idx, + struct otl_gsub_alternate1 *data) +{ + int32_t count = 0; + + if (idx >= 0 && idx < data->AlternateSetCount) { + struct otl_gsub_altset *altset; + USHORT i; + + altset = &(data->AlternateSet[idx]); + if (altset->GlyphCount == 0) + return count; + for (i = 0; i < altset->GlyphCount; i++) { + USHORT gid_alt = altset->Alternate[i]; + count += add_glyph_if_valid(cmap, used_chars, + map_base, map_sub, num_glyphs, + GIDToCIDMap, gid, gid_alt); + } + } + return count; +} + +static int32_t +add_ToUnicode_alternate (CMap *cmap, char *used_chars, + struct otl_gsub_subtab *subtab, + int32_t *map_base, int32_t *map_sub, USHORT num_glyphs, + uint16_t *GIDToCIDMap) { - int gid, idx; + int32_t count = 0; + USHORT i, gid, idx; ASSERT(subtab); if (subtab->SubstFormat == 1) { struct otl_gsub_alternate1 *data; - + struct clt_coverage *cov; data = subtab->table.alternate1; - for (gid = 0; gid < 0x10000; gid++) { - idx = clt_lookup_coverage(&data->coverage, gid); - if (idx >= 0 && idx < data->AlternateSetCount) { - struct otl_gsub_altset *altset; - USHORT i; - altset = &(data->AlternateSet[idx]); - if (altset->GlyphCount == 0) - continue; - fprintf(stdout, "substitute \\%u from [", (USHORT) gid); - for (i = 0; i < altset->GlyphCount; i++) { - fprintf(stdout, " \\%u", altset->Alternate[i]); + cov = &data->coverage; + switch (cov->format) { + case 1: /* list */ + for (idx = 0; idx < cov->count; idx++) { + gid = cov->list[idx]; + if (gid < num_glyphs) { + count += add_alternate1_inverse_map(cmap, used_chars, + map_base, map_sub, num_glyphs, + GIDToCIDMap, gid, idx, data); } - fprintf(stdout, " ];\n"); } + break; + case 2: /* range */ + for (i = 0; i < cov->count; i++) { + for (gid = cov->range[i].Start; + gid <= cov->range[i].End && gid < num_glyphs; gid++) { + idx = cov->range[i].StartCoverageIndex + gid - cov->range[i].Start; + count += add_alternate1_inverse_map(cmap, used_chars, + map_base, map_sub, num_glyphs, + GIDToCIDMap, gid, idx, data); + } + } + break; } } + return count; +} - return 0; +static int32_t +add_ligature1_inverse_map (CMap *cmap, char *used_chars, + int32_t *map_base, int32_t *map_sub, USHORT num_glyphs, + uint16_t *GIDToCIDMap, USHORT gid_1, int idx, + struct otl_gsub_ligature1 *data) +{ + int32_t count = 0; + + if (idx >= 0 && idx < data->LigSetCount) { + struct otl_gsub_ligset *ligset; + USHORT i, j; + + ligset = &(data->LigatureSet[idx]); + for (j = 0; j < ligset->LigatureCount; j++) { + USHORT gid_sub = ligset->Ligature[j].LigGlyph; + if (gid_sub < num_glyphs) { + uint16_t cid = GIDToCIDMap[gid_sub]; + if (is_used_char2(used_chars, cid)) { + int32_t ch, *ucv; + USHORT comp_count = ligset->Ligature[j].CompCount; + int fail_count = 0; + + ucv = NEW(comp_count, int32_t); + ch = UC_is_valid(map_base[gid_1]) ? map_base[gid_1] : map_sub[gid_1]; + ucv[0] = ch; + fail_count += UC_is_valid(ch) ? 0 : 1; + for (i = 0; i < ligset->Ligature[j].CompCount - 1; i++) { + USHORT gid = ligset->Ligature[j].Component[i]; + if (gid < num_glyphs) { + ch = UC_is_valid(map_base[gid]) ? map_base[gid] : map_sub[gid]; + ucv[i+1] = ch; + fail_count += UC_is_valid(ch) ? 0 : 1; + } else { + fail_count += 1; + } + } + if (fail_count == 0) { + unsigned char src[2], *dst; + unsigned char *p, *endptr; + size_t len = 0; + + src[0] = (cid >> 8) & 0xff; + src[1] = cid & 0xff; + dst = NEW(comp_count*4, unsigned char); + p = dst; + endptr = dst + comp_count * 4; + for (i = 0; i < comp_count; i++) { + len += UC_UTF16BE_encode_char(ucv[i], &p, endptr); + } + CMap_add_bfchar(cmap, src, 2, dst, len); + used_chars[cid / 8] &= ~(1 << (7 - (cid % 8))); + count++; + RELEASE(dst); + } + RELEASE(ucv); + } + } + } + } + + return count; } -static int -otl_gsub_dump_ligature (struct otl_gsub_subtab *subtab) +static int32_t +add_ToUnicode_ligature (CMap *cmap, char *used_chars, + struct otl_gsub_subtab *subtab, + int32_t *map_base, int32_t *map_sub, USHORT num_glyphs, + uint16_t *GIDToCIDMap) { - int gid, idx; + int32_t count = 0; + USHORT i, idx, gid; ASSERT(subtab); if (subtab->SubstFormat == 1) { struct otl_gsub_ligature1 *data; + struct clt_coverage *cov; data = subtab->table.ligature1; - for (gid = 0; gid < 0x10000; gid++) { - idx = clt_lookup_coverage(&data->coverage, gid); - if (idx >= 0 && idx < data->LigSetCount) { - struct otl_gsub_ligset *ligset; - USHORT i, j; - ligset = &(data->LigatureSet[idx]); - for (j = 0; j < ligset->LigatureCount; j++) { - fprintf(stdout, "substitute \\%u", (USHORT) gid); - for (i = 0; i < ligset->Ligature[j].CompCount - 1; i++) { - fprintf(stdout, " \\%u", ligset->Ligature[j].Component[i]); + cov = &data->coverage; + switch (cov->format) { + case 1: /* list */ + for (idx = 0; idx < cov->count; idx++) { + gid = cov->list[idx]; + if (gid < num_glyphs) { + count += add_ligature1_inverse_map(cmap, used_chars, + map_base, map_sub, num_glyphs, + GIDToCIDMap, gid, idx, data); + } + } + break; + case 2: /* range */ + for (i = 0; i < cov->count; i++) { + for (gid = cov->range[i].Start; + gid <= cov->range[i].End && gid < num_glyphs; gid++) { + idx = cov->range[i].StartCoverageIndex + gid - cov->range[i].Start; + if (gid < num_glyphs) { + count += add_ligature1_inverse_map(cmap, used_chars, + map_base, map_sub, num_glyphs, + GIDToCIDMap, gid, idx, data); } - fprintf(stdout, " by \\%u;\n", ligset->Ligature[j].LigGlyph); } } + break; } } @@ -1779,48 +1985,44 @@ otl_gsub_dump_ligature (struct otl_gsub_subtab *subtab) } int -otl_gsub_dump (otl_gsub *gsub_list, - const char *script, const char *language, const char *feature) +otl_gsub_add_ToUnicode (CMap *cmap, char *used_chars, + int32_t *map_base, int32_t *map_sub, USHORT num_glyphs, + uint16_t *GIDToCIDMap, sfnt *sfont) { - int error = -1; + int count = 0; + otl_gsub *gsub_list; struct otl_gsub_tab *gsub; struct otl_gsub_subtab *subtab; - int sel, i, j; - - if (!gsub_list) - return -1; - - sel = gsub_list->select; - error = otl_gsub_select(gsub_list, script, language, feature); - if (error < 0) { - ERROR("GSUB feature %s.%s.%s not found.", script, language, feature); - } + int i, j; - i = gsub_list->select; - if (i < 0 || i >= gsub_list->num_gsubs) { - ERROR("GSUB not selected..."); - return -1; - } - gsub = &(gsub_list->gsubs[i]); + gsub_list = otl_gsub_new(); + otl_gsub_add_feat(gsub_list, "*", "*", "*", sfont); - for (j = 0; - !error && - j < gsub->num_subtables; j++) { - subtab = &(gsub->subtables[j]); - switch ((int) subtab->LookupType){ - case OTL_GSUB_TYPE_SINGLE: - error = otl_gsub_dump_single(subtab); - break; - case OTL_GSUB_TYPE_ALTERNATE: - error = otl_gsub_dump_alternate(subtab); - break; - case OTL_GSUB_TYPE_LIGATURE: - error = otl_gsub_dump_ligature(subtab); - break; + for (i = 0; i < gsub_list->num_gsubs; i++) { + gsub = &(gsub_list->gsubs[i]); + for (j = 0; j < gsub->num_subtables; j++) { + subtab = &(gsub->subtables[j]); + switch ((int) subtab->LookupType){ + case OTL_GSUB_TYPE_SINGLE: + count += add_ToUnicode_single(cmap, used_chars, subtab, + map_base, map_sub, num_glyphs, + GIDToCIDMap); + break; + case OTL_GSUB_TYPE_ALTERNATE: + count += add_ToUnicode_alternate(cmap, used_chars, subtab, + map_base, map_sub, num_glyphs, + GIDToCIDMap); + break; + case OTL_GSUB_TYPE_LIGATURE: + count += add_ToUnicode_ligature(cmap, used_chars, subtab, + map_base, map_sub, num_glyphs, + GIDToCIDMap); + break; + } } } - gsub_list->select = sel; + otl_gsub_release(gsub_list); - return error; + return count; } #endif |