diff options
Diffstat (limited to 'Build/source/texk/dvipdfm-x/tt_cmap.c')
-rw-r--r-- | Build/source/texk/dvipdfm-x/tt_cmap.c | 622 |
1 files changed, 38 insertions, 584 deletions
diff --git a/Build/source/texk/dvipdfm-x/tt_cmap.c b/Build/source/texk/dvipdfm-x/tt_cmap.c index b356ed4de44..5f4f99ec741 100644 --- a/Build/source/texk/dvipdfm-x/tt_cmap.c +++ b/Build/source/texk/dvipdfm-x/tt_cmap.c @@ -45,12 +45,9 @@ #include "unicode.h" #include "agl.h" -#include "pdfparse.h" -#include "pdfresource.h" -#include "otl_conf.h" +#include "pdfresource.h" #include "dpxfile.h" - /* Hash */ #include "dpxutil.h" @@ -612,7 +609,8 @@ static unsigned char lrange_max[4] = {0x7f, 0xff, 0xff, 0xff}; static void load_cmap4 (struct cmap4 *map, - unsigned char *GIDToCIDMap, otl_gsub *gsub_list, CMap *cmap) + unsigned char *GIDToCIDMap, + otl_gsub *gsub_vert, otl_gsub *gsub_list, CMap *cmap) { USHORT c0, c1, gid, cid; USHORT j, d, segCount; @@ -637,7 +635,9 @@ load_cmap4 (struct cmap4 *map, } if (gid != 0 && gid != 0xffff) { if (gsub_list) - otl_gsub_apply(gsub_list, &gid); + otl_gsub_apply_chain(gsub_list, &gid); + if (gsub_vert) + otl_gsub_apply(gsub_vert, &gid); if (GIDToCIDMap) { cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]); if (cid == 0) @@ -659,7 +659,8 @@ load_cmap4 (struct cmap4 *map, static void load_cmap12 (struct cmap12 *map, - unsigned char *GIDToCIDMap, otl_gsub *gsub_list, CMap *cmap) + unsigned char *GIDToCIDMap, + otl_gsub *gsub_vert, otl_gsub *gsub_list, CMap *cmap) { ULONG i, ch; /* LONG ? */ USHORT gid, cid; @@ -671,7 +672,9 @@ load_cmap12 (struct cmap12 *map, int d = ch - map->groups[i].startCharCode; gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff); if (gsub_list) - otl_gsub_apply(gsub_list, &gid); + otl_gsub_apply_chain(gsub_list, &gid); + if (gsub_vert) + otl_gsub_apply(gsub_vert, &gid); if (GIDToCIDMap) { cid = ((GIDToCIDMap[2*gid] << 8)|GIDToCIDMap[2*gid+1]); if (cid == 0) @@ -1304,300 +1307,10 @@ otf_create_ToUnicode_stream (const char *font_name, return cmap_ref; } -/* Must be smaller than (WBUF_SIZE-2)/8 */ -#define MAX_UNICODES 16 - -struct gent -{ - USHORT gid; - int32_t ucv; /* assigned PUA unicode */ - - int num_unicodes; - int32_t unicodes[MAX_UNICODES]; -}; - -static void -create_cmaps (CMap *cmap, CMap *tounicode, - struct ht_table *unencoded, unsigned char *GIDToCIDMap) -{ - struct ht_iter iter; - - ASSERT(cmap && unencoded); - - if (ht_set_iter(unencoded, &iter) < 0) - return; - - CMap_set_silent(1); /* many warnings without this... */ - - do { - struct gent *glyph; - unsigned char *ucv; - int i, len; - unsigned char *p, *endptr; - CID cid; - - glyph = (struct gent *) ht_iter_getval(&iter); - ucv = (unsigned char *) ht_iter_getkey(&iter, &len); - - if (GIDToCIDMap) { - cid = ((GIDToCIDMap[2 * glyph->gid] << 8)|GIDToCIDMap[2 * glyph->gid + 1]); - if (cid == 0) - WARN("Glyph gid=%u does not have corresponding CID.", glyph->gid); - } else { - cid = glyph->gid; - } - - CMap_add_cidchar(cmap, ucv, 4, cid); - - if (tounicode) { - wbuf[0] = (cid >> 8) & 0xff; - wbuf[1] = cid & 0xff; - p = wbuf + 2; - endptr = wbuf + WBUF_SIZE; - len = 0; - for (i = 0; i < glyph->num_unicodes; i++) { - len += UC_UTF16BE_encode_char(glyph->unicodes[i], &p, endptr); - } - CMap_add_bfchar(tounicode, wbuf, 2, wbuf + 2, len); - } - } while (ht_iter_next(&iter) >= 0); - - CMap_set_silent(0); - - ht_clear_iter(&iter); -} - -static void -add_glyph (struct ht_table *unencoded, - USHORT gid, int32_t ucv, int num_unicodes, int32_t *unicodes) -{ - struct gent *glyph; - int i; - - ASSERT(unencoded); - - if (gid == 0 || num_unicodes < 1) { - return; - } - - wbuf[0] = (ucv >> 24) & 0xff; - wbuf[1] = (ucv >> 16) & 0xff; - wbuf[2] = (ucv >> 8) & 0xff; - wbuf[3] = ucv & 0xff; - - glyph = NEW(1, struct gent); - glyph->gid = gid; - glyph->num_unicodes = num_unicodes; - for (i = 0; - i < num_unicodes && i < MAX_UNICODES; i++) { - glyph->unicodes[i] = unicodes[i]; - } - - ht_append_table(unencoded, wbuf, 4, glyph); -} - -/* This seriously affects speed... */ -static struct gent * -find_glyph (struct ht_table *unencoded, int32_t ucv) -{ - ASSERT(unencoded); - - wbuf[0] = (ucv >> 24) & 0xff; - wbuf[1] = (ucv >> 16) & 0xff; - wbuf[2] = (ucv >> 8) & 0xff; - wbuf[3] = ucv & 0xff; - - return (struct gent *) ht_lookup_table(unencoded, wbuf, 4); -} - -static void -handle_subst (pdf_obj *dst_obj, pdf_obj *src_obj, int flag, - otl_gsub *gsub_list, tt_cmap *ttcmap, - struct ht_table *unencoded) -{ - pdf_obj *tmp; - int32_t i, j, src_size, dst_size; - int32_t src, dst; - int32_t src_start, src_end, dst_start, dst_end; - - src_size = pdf_array_length(src_obj); - dst_size = pdf_array_length(dst_obj); - - dst_start = dst_end = -1; dst = 0; - src_start = src_end = -1; src = 0; - for (i = 0, j = 0; - i < src_size && j < dst_size; i++) { - USHORT gid; - int rv; - struct gent *glyph; - - tmp = pdf_get_array(src_obj, i); - if (PDF_OBJ_ARRAYTYPE(tmp)) { - src_start = (int32_t) pdf_number_value(pdf_get_array(tmp, 0)); - src_end = (int32_t) pdf_number_value(pdf_get_array(tmp, 1)); - } else { - src_start = src_end = (int32_t) pdf_number_value(tmp); - } - for (src = src_start; src <= src_end; src++) { - glyph = find_glyph(unencoded, src); - if (glyph) - gid = glyph->gid; - else { - gid = tt_cmap_lookup(ttcmap, src); - } - dst++; - if (dst > dst_end) { - tmp = pdf_get_array(dst_obj, j++); - if (PDF_OBJ_ARRAYTYPE(tmp)) { - dst_start = (int32_t) pdf_number_value(pdf_get_array(tmp, 0)); - dst_end = (int32_t) pdf_number_value(pdf_get_array(tmp, 1)); - } else { - dst_start = dst_end = (int32_t) pdf_number_value(tmp); - } - dst = dst_start; - } - if (gid == 0) { - if (flag == 'r' || flag == 'p') { - if (src < 0x10000) { - WARN("Font does not have glyph for U+%04X.", src); - } else { - WARN("Font does not have glyph for U+%06X.", src); - } - } - if (flag == 'r') { - ERROR("Missing glyph found..."); - } - continue; - } - rv = otl_gsub_apply(gsub_list, &gid); - if (rv < 0) { - if (flag == 'p' || flag == 'r') { - if (src < 0x10000) { - WARN("No substituted glyph for U+%04X.", src); - } else { - WARN("No substituted glyph for U+%06X.", src); - } - } - if (flag == 'r') { - ERROR("Missing glyph found..."); - } - continue; - } - - if (glyph) { - glyph->gid = gid; - } else { - add_glyph(unencoded, gid, dst, 1, &src); - } - - if (verbose > VERBOSE_LEVEL_MIN) { - if (dst < 0x10000) { - MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%04X\n", - gid, dst); - } else { - MESG("otf_cmap>> Substituted glyph gid=%u assigned to U+%06X\n", - gid, dst); - } - } - - } - } - - if (dst < dst_end || src < src_end || - i < src_size || j < dst_size) { - WARN("Number of glyphs in left-side and right-side not equal..."); - WARN("Please check .otl file..."); - } -} - -static void -handle_assign (pdf_obj *dst, pdf_obj *src, int flag, - otl_gsub *gsub_list, tt_cmap *ttcmap, - struct ht_table *unencoded) -{ - int32_t unicodes[MAX_UNICODES], ucv; - int i, n_unicodes, rv; - USHORT gid_in[MAX_UNICODES], lig; - - n_unicodes = pdf_array_length(src); /* FIXME */ - ucv = (int32_t) pdf_number_value(pdf_get_array(dst, 0)); /* FIXME */ - if (!UC_is_valid(ucv)) { - if (flag == 'r' || flag == 'p') { - if (ucv < 0x10000) { - WARN("Invalid Unicode in: %04X", ucv); - } else { - WARN("Invalid Unicode in: %06X", ucv); - } - } - if (flag == 'r') { - ERROR("Invalid Unicode code specified."); - } - return; - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Ligature component:"); - } - - for (i = 0; i < n_unicodes; i++) { - unicodes[i] = - (int32_t) pdf_number_value(pdf_get_array(src, i)); - gid_in[i] = tt_cmap_lookup(ttcmap, unicodes[i]); - - if (verbose > VERBOSE_LEVEL_MIN) { - if (unicodes[i] < 0x10000) { - MESG(" U+%04X (gid=%u)", unicodes[i], gid_in[i]); - } else { - MESG(" U+%06X (gid=%u)", unicodes[i], gid_in[i]); - } - } - - if (gid_in[i] == 0) { - if (flag == 'r' || flag == 'p') { - if (unicodes[i] < 0x10000) { - WARN("Unicode char U+%04X not exist in font...", unicodes[i]); - } else { - WARN("Unicode char U+%06X not exist in font...", unicodes[i]); - } - } - if (flag == 'r') { - ERROR("Missing glyph found..."); - } - return; - } - - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("\n"); - } - - rv = otl_gsub_apply_lig(gsub_list, - gid_in, (USHORT)n_unicodes, &lig); - if (rv < 0) { - if (flag == 'p') - WARN("No ligature found..."); - else if (flag == 'r') - ERROR("No ligature found..."); - return; - } - - add_glyph(unencoded, lig, ucv, n_unicodes, unicodes); - - if (verbose > VERBOSE_LEVEL_MIN) { - if (ucv < 0x10000) { - MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%04X\n", lig, ucv); - } else { - MESG("otf_cmap>> Ligature glyph gid=%u assigned to U+%06X\n", lig, ucv); - } - } - - return; -} - static int load_base_CMap (const char *cmap_name, int wmode, - CIDSysInfo *csi, unsigned char *GIDToCIDMap, otl_gsub *gsub_list, + CIDSysInfo *csi, unsigned char *GIDToCIDMap, + otl_gsub *gsub_vert, otl_gsub *gsub_list, tt_cmap *ttcmap) { int cmap_id; @@ -1619,9 +1332,9 @@ load_base_CMap (const char *cmap_name, int wmode, } if (ttcmap->format == 12) { - load_cmap12(ttcmap->map, GIDToCIDMap, gsub_list, cmap); + load_cmap12(ttcmap->map, GIDToCIDMap, gsub_vert, gsub_list, cmap); } else if (ttcmap->format == 4) { - load_cmap4(ttcmap->map, GIDToCIDMap, gsub_list, cmap); + load_cmap4(ttcmap->map, GIDToCIDMap, gsub_vert, gsub_list, cmap); } cmap_id = CMap_cache_add(cmap); @@ -1630,156 +1343,18 @@ load_base_CMap (const char *cmap_name, int wmode, return cmap_id; } -static void -load_gsub (pdf_obj *conf, otl_gsub *gsub_list, sfnt *sfont) -{ - pdf_obj *rule; - char *script, *language, *feature; - int i, size; - - rule = otl_conf_get_rule(conf); - if (!rule) - return; - - script = otl_conf_get_script (conf); - language = otl_conf_get_language(conf); - - size = pdf_array_length(rule); - for (i = 0; i < size; i += 2) { - pdf_obj *tmp, *commands; - int flag; - int j, num_comms; - - tmp = pdf_get_array(rule, i); - flag = (int) pdf_number_value(tmp); - - commands = pdf_get_array(rule, i+1); - num_comms = pdf_array_length(commands); - - /* (assign|substitute) tag dst src */ - for (j = 0 ; j < num_comms; j += 4) { - tmp = pdf_get_array(commands, 1); - if (PDF_OBJ_STRINGTYPE(tmp)) { - feature = pdf_string_value(tmp); - if (otl_gsub_add_feat(gsub_list, - script, language, feature, sfont) < 0) { - if (flag == 'p') - WARN("No OTL feature matches \"%s.%s.%s\" found.", - script, language, feature); - else if (flag == 'r') - ERROR("No OTL feature matches \"%s.%s.%s\" found.", - script, language, feature); - } - } - - } - } - -} - -static void -handle_gsub (pdf_obj *conf, - tt_cmap *ttcmap, otl_gsub *gsub_list, - struct ht_table *unencoded) -{ - pdf_obj *rule; - char *script, *language, *feature; - int i, size; - - if (!conf) - return; - - rule = otl_conf_get_rule(conf); - if (!rule) { - return; - } - - if (!PDF_OBJ_ARRAYTYPE(rule)) { - WARN("Not arraytype?"); - return; - } - script = otl_conf_get_script (conf); - language = otl_conf_get_language(conf); - - size = pdf_array_length(rule); - for (i = 0; i < size; i += 2) { - pdf_obj *tmp, *commands; - int j, num_comms; - int flag; - - tmp = pdf_get_array(rule, i); - flag = (int) pdf_number_value(tmp); - - commands = pdf_get_array (rule, i+1); - num_comms = pdf_array_length(commands); - - for (j = 0; j < num_comms; j += 4) { - pdf_obj *operator; - pdf_obj *src, *dst, *feat; - int rv; - - /* (assing|substitute) tag dst src */ - operator = pdf_get_array(commands, j); - - feat = pdf_get_array(commands, j+1); - if (PDF_OBJ_STRINGTYPE(feat)) - feature = pdf_string_value(feat); - else - feature = NULL; - - dst = pdf_get_array(commands, j+2); - src = pdf_get_array(commands, j+3); - - rv = otl_gsub_select(gsub_list, script, language, feature); - if (rv < 0) { - if (flag == 'p') { - WARN("No GSUB feature %s.%s.%s loaded...", - script, language, feature); - } else if (flag == 'r') { - ERROR("No GSUB feature %s.%s.%s loaded...", - script, language, feature); - } - } else { - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> %s:\n", pdf_name_value(operator)); - } - - if (!strcmp(pdf_name_value(operator), "assign")) { - handle_assign(dst, src, flag, - gsub_list, ttcmap, unencoded); - } else if (!strcmp(pdf_name_value(operator), "substitute")) { - handle_subst(dst, src, flag, - gsub_list, ttcmap, unencoded); - } - } - - } - - } - -} - -static inline void -hval_free (void *hval) -{ - RELEASE(hval); -} - int otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC font */ const char *otl_tags, int wmode) { int cmap_id = -1; - int tounicode_id = -1, is_cidfont = 0; + int is_cidfont = 0; sfnt *sfont; ULONG offset = 0; char *base_name = NULL, *cmap_name = NULL; - char *tounicode_name = NULL; FILE *fp = NULL; - otl_gsub *gsub_list = NULL; + otl_gsub *gsub_vert = NULL, *gsub_list = NULL; tt_cmap *ttcmap; - CMap *cmap, *base, *tounicode = NULL; CIDSysInfo csi = {NULL, NULL, 0}; unsigned char *GIDToCIDMap = NULL; @@ -1851,28 +1426,17 @@ otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC fon is_cidfont = 0; } - if (is_cidfont) { - tounicode_name = NULL; - } else { - tounicode_name = NEW(strlen(map_name)+strlen("-UTF16")+5, char); - sprintf(tounicode_name, "%s,%03d-UTF16", map_name, ttc_index); - } - if (verbose > VERBOSE_LEVEL_MIN) { MESG("\n"); MESG("otf_cmap>> Unicode charmap for font=\"%s\" layout=\"%s\"\n", map_name, (otl_tags ? otl_tags : "none")); } - cmap_id = CMap_cache_find(cmap_name); if (cmap_id >= 0) { RELEASE(cmap_name); RELEASE(base_name); if (GIDToCIDMap) RELEASE(GIDToCIDMap); - if (tounicode_name) - RELEASE(tounicode_name); - sfnt_close(sfont); DPXFCLOSE(fp); @@ -1897,37 +1461,47 @@ otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC fon } } if (wmode == 1) { - gsub_list = otl_gsub_new(); - if (otl_gsub_add_feat(gsub_list, "*", "*", "vrt2", sfont) < 0) { - if (otl_gsub_add_feat(gsub_list, "*", "*", "vert", sfont) < 0) { + gsub_vert = otl_gsub_new(); + if (otl_gsub_add_feat(gsub_vert, "*", "*", "vrt2", sfont) < 0) { + if (otl_gsub_add_feat(gsub_vert, "*", "*", "vert", sfont) < 0) { WARN("GSUB feature vrt2/vert not found."); - otl_gsub_release(gsub_list); - gsub_list = NULL; + otl_gsub_release(gsub_vert); + gsub_vert = NULL; } else { - otl_gsub_select(gsub_list, "*", "*", "vert"); + otl_gsub_select(gsub_vert, "*", "*", "vert"); } } else { - otl_gsub_select(gsub_list, "*", "*", "vrt2"); + otl_gsub_select(gsub_vert, "*", "*", "vrt2"); + } + } else { + gsub_vert = NULL; + } + if (otl_tags) { + gsub_list = otl_gsub_new(); + if (otl_gsub_add_feat_list(gsub_list, otl_tags, sfont) < 0) { + WARN("Readin GSUB feature table(s) failed for \"%s\"", otl_tags); + } else { + otl_gsub_set_chain(gsub_list, otl_tags); } } else { gsub_list = NULL; } cmap_id = load_base_CMap(base_name, wmode, (is_cidfont ? &csi : NULL), GIDToCIDMap, - gsub_list, ttcmap); + gsub_vert, gsub_list, ttcmap); if (cmap_id < 0) ERROR("Failed to read OpenType/TrueType cmap table."); + if (gsub_vert) + otl_gsub_release(gsub_vert); + gsub_vert = NULL; if (gsub_list) otl_gsub_release(gsub_list); gsub_list = NULL; - if (!otl_tags) { RELEASE(cmap_name); RELEASE(base_name); if (GIDToCIDMap) RELEASE(GIDToCIDMap); - if (tounicode_name) - RELEASE(tounicode_name); if (is_cidfont) { if (csi.registry) RELEASE(csi.registry); @@ -1938,125 +1512,5 @@ otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC fon sfnt_close(sfont); DPXFCLOSE(fp); - return cmap_id; - } - - base = CMap_cache_get(cmap_id); - - cmap = CMap_new(); - CMap_set_name (cmap, cmap_name); - CMap_set_type (cmap, CMAP_TYPE_CODE_TO_CID); - CMap_set_wmode(cmap, wmode); - /* CMap_add_codespacerange(cmap, lrange_min, lrange_max, 4); */ - CMap_set_usecmap(cmap, base); - CMap_add_cidchar(cmap, lrange_max, 4, 0); /* FIXME */ - - if (is_cidfont) { - CMap_set_CIDSysInfo(cmap, &csi); - if (csi.registry) - RELEASE(csi.registry); - if (csi.ordering) - RELEASE(csi.ordering); - } else { - CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY); - } - - gsub_list = otl_gsub_new(); - - { - struct ht_table unencoded; - char *conf_name, *opt_tag; - pdf_obj *conf, *opt_conf; - - conf_name = NEW(strlen(otl_tags)+1, char); - memset (conf_name, 0, strlen(otl_tags)+1); - opt_tag = strchr(otl_tags, ':'); - if (opt_tag) { - opt_tag++; - strncpy(conf_name, otl_tags, - strlen(otl_tags) - strlen(opt_tag) - 1); - } else { - strcpy(conf_name, otl_tags); - } - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Read layout config. \"%s\"\n", conf_name); - } - - conf = otl_find_conf(conf_name); - if (!conf) - ERROR("Layout file \"%s\" not found...", conf_name); - - load_gsub(conf, gsub_list, sfont); - if (opt_tag) { - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Layout option \"%s\" enabled\n", opt_tag); - } - opt_conf = otl_conf_find_opt(conf, opt_tag); - if (!opt_conf) - ERROR("There is no option \"%s\" in \"%s\".", - opt_tag, conf_name); - load_gsub(opt_conf, gsub_list, sfont); - } - - ht_init_table(&unencoded, hval_free); - - handle_gsub(conf, ttcmap, gsub_list, &unencoded); - if (opt_tag) { - opt_conf = otl_conf_find_opt(conf, opt_tag); - if (!opt_conf) - ERROR("There is no option \"%s\" in \"%s\".", - opt_tag, conf_name); - handle_gsub(opt_conf, ttcmap, gsub_list, &unencoded); - } - if (is_cidfont) { - tounicode_id = -1; - tounicode = NULL; - } else { - tounicode_id = CMap_cache_find(tounicode_name); - if (tounicode_id >= 0) - tounicode = CMap_cache_get(tounicode_id); - else { - tounicode = CMap_new(); - CMap_set_name (tounicode, tounicode_name); - CMap_set_type (tounicode, CMAP_TYPE_TO_UNICODE); - CMap_set_wmode(tounicode, 0); - CMap_add_codespacerange(tounicode, srange_min, srange_max, 2); - CMap_set_CIDSysInfo(tounicode, &CSI_UNICODE); - /* FIXME */ - CMap_add_bfchar(tounicode, srange_min, 2, srange_max, 2); - } - } - create_cmaps(cmap, tounicode, &unencoded, GIDToCIDMap); - - ht_clear_table(&unencoded); - RELEASE(conf_name); - } - - cmap_id = CMap_cache_add(cmap); - if (!is_cidfont && tounicode_id < 0) /* New */ - CMap_cache_add(tounicode); - - tt_cmap_release(ttcmap); - if (gsub_list) - otl_gsub_release(gsub_list); - - if (verbose > VERBOSE_LEVEL_MIN) { - MESG("otf_cmap>> Overwrite CMap \"%s\" by \"%s\" with usecmap\n", - base_name, cmap_name); - } - - if (GIDToCIDMap) - RELEASE(GIDToCIDMap); - if (base_name) - RELEASE(base_name); - if (cmap_name) - RELEASE(cmap_name); - if (tounicode_name) - RELEASE(tounicode_name); - - sfnt_close(sfont); - DPXFCLOSE(fp); - return cmap_id; } |