summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/tt_cmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdfm-x/tt_cmap.c')
-rw-r--r--Build/source/texk/dvipdfm-x/tt_cmap.c1400
1 files changed, 756 insertions, 644 deletions
diff --git a/Build/source/texk/dvipdfm-x/tt_cmap.c b/Build/source/texk/dvipdfm-x/tt_cmap.c
index 9e2736cfe93..539024ed6e5 100644
--- a/Build/source/texk/dvipdfm-x/tt_cmap.c
+++ b/Build/source/texk/dvipdfm-x/tt_cmap.c
@@ -1,6 +1,6 @@
/* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
- Copyright (C) 2007-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
@@ -68,11 +68,12 @@ read_cmap0 (sfnt *sfont, ULONG len)
struct cmap0 *map;
int i;
- if (len < 256)
- ERROR("invalid cmap subtable");
+ if (len < 256) {
+ WARN("invalid format 0 TT cmap subtable");
+ return NULL;
+ }
map = NEW(1, struct cmap0);
-
for (i = 0; i < 256; i++)
map->glyphIndexArray[i] = sfnt_get_byte(sfont);
@@ -114,14 +115,14 @@ read_cmap2 (sfnt *sfont, ULONG len)
struct cmap2 *map;
USHORT i, n;
- if (len < 512)
- ERROR("invalid cmap subtable");
-
- map = NEW(1, struct cmap2);
+ if (len < 512) {
+ WARN("invalid fromt2 TT cmap subtable");
+ return NULL;
+ }
+ map = NEW(1, struct cmap2);
for (i = 0; i < 256; i++)
map->subHeaderKeys[i] = sfnt_get_ushort(sfont);
-
for (n = 0, i = 0; i < 256; i++) {
map->subHeaderKeys[i] /= 8;
if (n < map->subHeaderKeys[i])
@@ -129,7 +130,13 @@ read_cmap2 (sfnt *sfont, ULONG len)
}
n += 1; /* the number of subHeaders is one plus the max of subHeaderKeys */
- map->subHeaders = NEW(n, struct SubHeader);
+ if (len < 512 + n * 8 ) {
+ WARN("invalid/truncated format2 TT cmap subtable");
+ RELEASE(map);
+ return NULL;
+ }
+
+ map->subHeaders = NEW(n, struct SubHeader);
for (i = 0; i < n; i++) {
map->subHeaders[i].firstCode = sfnt_get_ushort(sfont);
map->subHeaders[i].entryCount = sfnt_get_ushort(sfont);
@@ -222,8 +229,10 @@ read_cmap4(sfnt *sfont, ULONG len)
struct cmap4 *map;
USHORT i, n, segCount;
- if (len < 8)
- ERROR("invalid cmap subtable");
+ if (len < 8) {
+ WARN("invalid format 4 TT cmap subtable");
+ return NULL;
+ }
map = NEW(1, struct cmap4);
@@ -288,19 +297,19 @@ lookup_cmap4 (struct cmap4 *map, USHORT cc)
* Last segment maps 0xffff to gid 0 (?)
*/
i = segCount = map->segCountX2 / 2;
- while (i-- > 0 && cc <= map->endCount[i]) {
+ while (i-- > 0 && cc <= map->endCount[i]) {
if (cc >= map->startCount[i]) {
if (map->idRangeOffset[i] == 0) {
- gid = (cc + map->idDelta[i]) & 0xffff;
+ gid = (cc + map->idDelta[i]) & 0xffff;
} else if (cc == 0xffff && map->idRangeOffset[i] == 0xffff) {
- /* this is for protection against some old broken fonts... */
- gid = 0;
+ /* this is for protection against some old broken fonts... */
+ gid = 0;
} else {
- j = map->idRangeOffset[i] - (segCount - i) * 2;
- j = (cc - map->startCount[i]) + (j / 2);
- gid = map->glyphIndexArray[j];
- if (gid != 0)
- gid = (gid + map->idDelta[i]) & 0xffff;
+ j = map->idRangeOffset[i] - (segCount - i) * 2;
+ j = (cc - map->startCount[i]) + (j / 2);
+ gid = map->glyphIndexArray[j];
+ if (gid != 0)
+ gid = (gid + map->idDelta[i]) & 0xffff;
}
break;
}
@@ -323,14 +332,15 @@ read_cmap6 (sfnt *sfont, ULONG len)
struct cmap6 *map;
USHORT i;
- if (len < 4)
- ERROR("invalid cmap subtable");
+ if (len < 4) {
+ WARN("invalid format 6 TT cmap subtable");
+ return NULL;
+ }
map = NEW(1, struct cmap6);
map->firstCode = sfnt_get_ushort(sfont);
map->entryCount = sfnt_get_ushort(sfont);
- map->glyphIndexArray = NEW(map->entryCount, USHORT);
-
+ map->glyphIndexArray = NEW(map->entryCount, USHORT);
for (i = 0; i < map->entryCount; i++)
map->glyphIndexArray[i] = sfnt_get_ushort(sfont);
@@ -390,13 +400,14 @@ read_cmap12 (sfnt *sfont, ULONG len)
struct cmap12 *map;
ULONG i;
- if (len < 4)
- ERROR("invalid cmap subtable");
+ if (len < 4) {
+ WARN("invalid format 12 TT cmap subtable");
+ return NULL;
+ }
map = NEW(1, struct cmap12);
map->nGroups = sfnt_get_ulong(sfont);
map->groups = NEW(map->nGroups, struct charGroup);
-
for (i = 0; i < map->nGroups; i++) {
map->groups[i].startCharCode = sfnt_get_ulong(sfont);
map->groups[i].endCharCode = sfnt_get_ulong(sfont);
@@ -427,8 +438,8 @@ lookup_cmap12 (struct cmap12 *map, ULONG cccc)
cccc <= map->groups[i].endCharCode) {
if (cccc >= map->groups[i].startCharCode) {
gid = (USHORT) ((cccc -
- map->groups[i].startCharCode +
- map->groups[i].startGlyphID) & 0xffff);
+ map->groups[i].startCharCode +
+ map->groups[i].startGlyphID) & 0xffff);
break;
}
}
@@ -510,6 +521,7 @@ tt_cmap_read (sfnt *sfont, USHORT platform, USHORT encoding)
WARN("Unrecognized OpenType/TrueType cmap format.");
tt_cmap_release(cmap);
return NULL;
+ break;
}
if (!cmap->map) {
@@ -526,24 +538,25 @@ tt_cmap_release (tt_cmap *cmap)
if (cmap) {
if (cmap->map) {
- switch(cmap->format) {
+ switch (cmap->format) {
case 0:
- release_cmap0(cmap->map);
- break;
+ release_cmap0(cmap->map);
+ break;
case 2:
- release_cmap2(cmap->map);
- break;
+ release_cmap2(cmap->map);
+ break;
case 4:
- release_cmap4(cmap->map);
- break;
+ release_cmap4(cmap->map);
+ break;
case 6:
- release_cmap6(cmap->map);
- break;
+ release_cmap6(cmap->map);
+ break;
case 12:
- release_cmap12(cmap->map);
- break;
+ release_cmap12(cmap->map);
+ break;
default:
- ERROR("Unrecognized OpenType/TrueType cmap format.");
+ WARN("Unrecognized OpenType/TrueType cmap format: %d", cmap->format);
+ break;
}
}
RELEASE(cmap);
@@ -582,129 +595,20 @@ tt_cmap_lookup (tt_cmap *cmap, ULONG cc)
gid = lookup_cmap12(cmap->map, (ULONG) cc);
break;
default:
- ERROR("Unrecognized OpenType/TrueType cmap subtable format");
+ WARN("Unrecognized OpenType/TrueType cmap subtable format: %d", cmap->format);
break;
}
return gid;
}
-/* Sorry for placing this here.
- * We need to rewrite TrueType font support code...
- */
-#define WBUF_SIZE 1024
-static unsigned char wbuf[WBUF_SIZE];
static unsigned char srange_min[2] = {0x00, 0x00};
static unsigned char srange_max[2] = {0xff, 0xff};
static unsigned char lrange_min[4] = {0x00, 0x00, 0x00, 0x00};
static unsigned char lrange_max[4] = {0x7f, 0xff, 0xff, 0xff};
-static void
-load_cmap4 (struct cmap4 *map,
- unsigned char *GIDToCIDMap,
- otl_gsub *gsub_vert, otl_gsub *gsub_list,
- CMap *cmap, CMap *tounicode_add)
-{
- USHORT c0, c1, gid, cid;
- USHORT j, d, segCount;
- USHORT ch;
- int i;
-
- segCount = map->segCountX2 / 2;
- for (i = segCount - 1; i >= 0 ; i--) {
- c0 = map->startCount[i];
- c1 = map->endCount[i];
- d = map->idRangeOffset[i] / 2 - (segCount - i);
- for (j = 0; j <= c1 - c0; j++) {
- ch = c0 + j;
- if (map->idRangeOffset[i] == 0) {
- gid = (ch + map->idDelta[i]) & 0xffff;
- } else if (c0 == 0xffff && c1 == 0xffff &&
- map->idRangeOffset[i] == 0xffff) {
- /* this is for protection against some old broken fonts... */
- gid = 0;
- } else {
- gid = (map->glyphIndexArray[j+d] + map->idDelta[i]) & 0xffff;
- }
- if (gid != 0 && gid != 0xffff) {
- if (gsub_list)
- 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)
- WARN("GID %u does not have corresponding CID %u.", gid, cid);
- } else {
- cid = gid;
- }
- wbuf[0] = 0;
- wbuf[1] = 0;
- wbuf[2] = (ch >> 8) & 0xff;
- wbuf[3] = ch & 0xff;
- wbuf[4] = (cid >> 8) & 0xff;
- wbuf[5] = cid & 0xff;
- CMap_add_cidchar(cmap, wbuf, 4, cid);
- if (tounicode_add) {
- unsigned char *p = wbuf + 6;
- size_t uc_len;
- uc_len = UC_UTF16BE_encode_char(ch, &p, wbuf + WBUF_SIZE -1 );
- CMap_add_bfchar(tounicode_add, wbuf+4, 2, wbuf+6, uc_len);
- }
- }
- }
- }
-
- return;
-}
-
-static void
-load_cmap12 (struct cmap12 *map,
- unsigned char *GIDToCIDMap,
- otl_gsub *gsub_vert, otl_gsub *gsub_list,
- CMap *cmap, CMap *tounicode_add)
-{
- ULONG i, ch; /* LONG ? */
- USHORT gid, cid;
-
- for (i = 0; i < map->nGroups; i++) {
- for (ch = map->groups[i].startCharCode;
- ch <= map->groups[i].endCharCode;
- ch++) {
- int d = ch - map->groups[i].startCharCode;
- gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff);
- if (gsub_list)
- 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)
- WARN("GID %u does not have corresponding CID %u.", gid, cid);
- } else {
- cid = gid;
- }
- wbuf[0] = (ch >> 24) & 0xff;
- wbuf[1] = (ch >> 16) & 0xff;
- wbuf[2] = (ch >> 8) & 0xff;
- wbuf[3] = ch & 0xff;
- wbuf[4] = (cid >> 8) & 0xff;
- wbuf[5] = cid & 0xff;
- CMap_add_cidchar(cmap, wbuf, 4, cid);
- if (tounicode_add) {
- unsigned char *p = wbuf + 6;
- size_t uc_len;
- uc_len = UC_UTF16BE_encode_char(ch, &p, wbuf + WBUF_SIZE -1 );
- CMap_add_bfchar(tounicode_add, wbuf+4, 2, wbuf+6, uc_len);
- }
- }
- }
-
- return;
-}
-
/* OpenType CIDFont:
*
* We don't use GID for them. OpenType cmap table is for
@@ -717,78 +621,37 @@ load_cmap12 (struct cmap12 *map,
#include "cff_dict.h"
#include "cff.h"
-static int
-handle_CIDFont (sfnt *sfont,
- unsigned char **GIDToCIDMap, CIDSysInfo *csi)
+/* This should be moved to cff.c */
+static void
+create_GIDToCIDMap (uint16_t *GIDToCIDMap, uint16_t num_glyphs, cff_font *cffont)
{
- cff_font *cffont;
- int offset, i;
- card16 num_glyphs, gid;
- cff_charsets *charset;
- unsigned char *map;
- struct tt_maxp_table *maxp;
-
- ASSERT(csi);
-
- offset = sfnt_find_table_pos(sfont, "CFF ");
- if (offset == 0) {
- csi->registry = NULL;
- csi->ordering = NULL;
- *GIDToCIDMap = NULL;
- return 0;
- }
+ cff_charsets *charset;
+ uint16_t gid, i;
- maxp = tt_read_maxp_table(sfont);
- num_glyphs = (card16) maxp->numGlyphs;
- RELEASE(maxp);
- if (num_glyphs < 1)
- ERROR("No glyph contained in this font...");
+ ASSERT(GIDToCIDMap);
- cffont = cff_open(sfont->stream, offset, 0);
- if (!cffont)
- ERROR("Could not open CFF font...");
+ if (!cffont || !(cffont->flag & FONTTYPE_CIDFONT)) {
+ for (gid = 0; gid < num_glyphs; gid++) {
+ GIDToCIDMap[gid] = gid;
+ }
-
- if (!(cffont->flag & FONTTYPE_CIDFONT)) {
- cff_close(cffont);
- csi->registry = NULL;
- csi->ordering = NULL;
- *GIDToCIDMap = NULL;
- return 0;
+ return;
}
- if (!cff_dict_known(cffont->topdict, "ROS")) {
- ERROR("No CIDSystemInfo???");
- } else {
- card16 reg, ord;
-
- reg = (card16) cff_dict_get(cffont->topdict, "ROS", 0);
- ord = (card16) cff_dict_get(cffont->topdict, "ROS", 1);
-
- csi->registry = cff_get_string(cffont, reg);
- csi->ordering = cff_get_string(cffont, ord);
- csi->supplement = (int) cff_dict_get(cffont->topdict, "ROS", 2);
- }
+ memset(GIDToCIDMap, 0, num_glyphs*sizeof(uint16_t));
- cff_read_charsets(cffont);
charset = cffont->charsets;
- if (!charset) {
- ERROR("No CFF charset data???");
- }
-
- map = NEW(65536 * 2, unsigned char);
- memset(map, 0, 65536 * 2);
+ if (!charset)
+ return;
switch (charset->format) {
case 0:
{
s_SID *cids; /* CID... */
-
+
cids = charset->data.glyphs;
- for (gid = 1, i = 0;
- i < charset->num_entries; i++) {
- map[2*gid ] = (cids[i] >> 8) & 0xff;
- map[2*gid+1] = cids[i] & 0xff;
- gid++;
+ for (gid = 1, i = 0; i < charset->num_entries; i++) {
+ GIDToCIDMap[gid] = cids[i];
+ gid++;
}
}
break;
@@ -798,16 +661,14 @@ handle_CIDFont (sfnt *sfont,
card16 cid, count;
ranges = charset->data.range1;
- for (gid = 1, i = 0;
- i < charset->num_entries; i++) {
- cid = ranges[i].first;
- count = ranges[i].n_left + 1; /* card8 */
- while (count-- > 0 &&
- gid <= num_glyphs) {
- map[2*gid ] = (cid >> 8) & 0xff;
- map[2*gid + 1] = cid & 0xff;
- gid++; cid++;
- }
+ for (gid = 1, i = 0; i < charset->num_entries; i++) {
+ cid = ranges[i].first;
+ count = ranges[i].n_left + 1; /* card8 */
+ while (count-- > 0 && gid <= num_glyphs) {
+ GIDToCIDMap[gid] = cid;
+ gid++;
+ cid++;
+ }
}
}
break;
@@ -817,55 +678,52 @@ handle_CIDFont (sfnt *sfont,
card16 cid, count;
ranges = charset->data.range2;
- if (charset->num_entries == 1 &&
- ranges[0].first == 1) {
- /* "Complete" CIDFont */
- RELEASE(map); map = NULL;
+ if (charset->num_entries == 1 && ranges[0].first == 1) {
+ /* "Complete" CIDFont */
+ for (gid = 0; gid < num_glyphs; gid++) {
+ GIDToCIDMap[gid] = gid;
+ }
} else {
- /* Not trivial mapping */
- for (gid = 1, i = 0;
- i < charset->num_entries; i++) {
- cid = ranges[i].first;
- count = ranges[i].n_left + 1;
- while (count-- > 0 &&
- gid <= num_glyphs) {
- map[2*gid] = (cid >> 8) & 0xff;
- map[2*gid+1] = cid & 0xff;
- gid++; cid++;
- }
- }
+ /* Not trivial mapping */
+ for (gid = 1, i = 0; i < charset->num_entries; i++) {
+ cid = ranges[i].first;
+ count = ranges[i].n_left + 1;
+ while (count-- > 0 && gid <= num_glyphs) {
+ GIDToCIDMap[gid] = cid;
+ gid++;
+ cid++;
+ }
+ }
}
}
break;
default:
- RELEASE(map); map = NULL;
- ERROR("Unknown CFF charset format...: %d", charset->format);
+ WARN("Unknown CFF charset format...: %d", charset->format);
break;
}
- cff_close(cffont);
- *GIDToCIDMap = map;
- return 1;
+ return;
}
static int is_PUA_or_presentation (unsigned int uni)
{
/* Some of CJK Radicals Supplement and Kangxi Radicals
* are commonly double encoded, lower the priority.
+ * CJK Compatibility Ideographs & Supplement added.
*/
return ((uni >= 0x2E80 && uni <= 0x2EF3) || (uni >= 0x2F00 && uni <= 0x2FD5) ||
(uni >= 0xE000 && uni <= 0xF8FF) || (uni >= 0xFB00 && uni <= 0xFB4F) ||
+ (uni >= 0xF900 && uni <= 0xFAFF) || (uni >= 0x2F800 && uni <= 0x2FA1F) ||
(uni >= 0xF0000 && uni <= 0xFFFFD) || (uni >= 0x100000 && uni <= 0x10FFFD));
}
-static char*
-sfnt_get_glyphname(struct tt_post_table *post, cff_font *cffont, USHORT gid)
+static char *
+lookup_glyph_name (struct tt_post_table *post, cff_font *cffont, USHORT gid)
{
- char* name = NULL;
+ char *name = NULL;
if (post)
name = tt_get_glyphname(post, gid);
-
if (!name && cffont)
name = cff_get_glyphname(cffont, gid);
@@ -881,94 +739,82 @@ sfnt_get_glyphname(struct tt_post_table *post, cff_font *cffont, USHORT gid)
#define is_used_char2(b,c) (((b)[(c)/8]) & (1 << (7-((c)%8))))
#endif
-static USHORT
-handle_subst_glyphs (CMap *cmap,
- CMap *cmap_add,
- const char *used_glyphs,
- sfnt *sfont,
- cff_font *cffont)
+static int32_t
+handle_subst_glyphs (CMap *cmap, CMap *cmap_add, char *used_chars)
{
- USHORT count;
- USHORT i;
- struct tt_post_table *post = NULL;
+ int32_t count = 0;
+ int32_t cid;
- if (!cmap_add)
- post = tt_read_post_table(sfont);
+ for (cid = 0; cid < 65536; cid++) {
+ if (!is_used_char2(used_chars, cid))
+ continue;
+ else {
+ unsigned char buf[256];
+ int inbytesleft = 2, outbytesleft = 254;
+ size_t len;
+ unsigned char *outbuf = buf + 2;
+ const unsigned char *inbuf = buf;
+
+ buf[0] = (cid >> 8) & 0xff;
+ buf[1] = cid & 0xff;
+ CMap_decode(cmap_add, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+ if (inbytesleft == 0) {
+ len = 254 - outbytesleft;
+ CMap_add_bfchar(cmap, buf, 2, buf + 2, len);
+ used_chars[cid / 8] &= ~(1 << (7 - (cid % 8)));
+ count++;
+ }
+ }
+ }
- for (count = 0, i = 0; i < 8192; i++) {
- int j;
- int32_t len;
- int inbytesleft, outbytesleft;
- const unsigned char *inbuf;
- unsigned char *outbuf;
+ return count;
+}
- if (used_glyphs[i] == 0)
- continue;
+static int32_t
+add_ToUnicode_via_glyph_name (CMap *cmap, char *used_chars, USHORT num_glyphs,
+ uint16_t *GIDToCIDMap,
+ sfnt *sfont, cff_font *cffont)
+{
+ int32_t count = 0;
+ USHORT gid;
+ struct tt_post_table *post = NULL;
- for (j = 0; j < 8; j++) {
- USHORT gid = 8 * i + j;
-
- if (!is_used_char2(used_glyphs, gid))
- continue;
-
- if (!cmap_add) {
-#define MAX_UNICODES 16
- /* try to look up Unicode values from the glyph name... */
- char* name;
- int32_t unicodes[MAX_UNICODES];
- int unicode_count = -1;
- name = sfnt_get_glyphname(post, cffont, gid);
- if (name) {
- unicode_count = agl_get_unicodes(name, unicodes, MAX_UNICODES);
- }
+ post = tt_read_post_table(sfont);
+ if (!post && !cffont)
+ return count;
+
+ for (gid = 0; gid < num_glyphs; gid++) {
+ uint16_t cid = GIDToCIDMap[gid];
+ if (is_used_char2(used_chars, cid)) {
+#define MAX_UNICODES 32
+ char *name;
+ int32_t unicodes[MAX_UNICODES];
+ int unicode_count = -1;
+
+ name = lookup_glyph_name(post, cffont, gid);
+ if (name) {
+ unicode_count = agl_get_unicodes(name, unicodes, MAX_UNICODES);
#undef MAX_UNICODES
- if (unicode_count == -1) {
- if(dpx_conf.verbose_level > VERBOSE_LEVEL_MIN) {
- if (name)
- MESG("No Unicode mapping available: GID=%u, name=%s\n", gid, name);
- else
- MESG("No Unicode mapping available: GID=%u\n", gid);
- }
- } else {
- /* the Unicode characters go into wbuf[2] and following, in UTF16BE */
- /* we rely on WBUF_SIZE being more than adequate for MAX_UNICODES */
- unsigned char* p = wbuf + 2;
- int k;
- len = 0;
+ RELEASE(name);
+ if (unicode_count > 0) {
+ unsigned char *buf;
+ unsigned char *p, *endptr;
+ int k;
+ size_t len = 0;
+
+ buf = NEW(unicode_count*4+2, unsigned char);
+ p = buf + 2;
+ endptr = buf + (unicode_count * 4 + 2);
for (k = 0; k < unicode_count; ++k) {
- len += UC_UTF16BE_encode_char(unicodes[k], &p, wbuf+WBUF_SIZE);
+ len += UC_UTF16BE_encode_char(unicodes[k], &p, endptr);
}
- wbuf[0] = (gid >> 8) & 0xff;
- wbuf[1] = gid & 0xff;
- CMap_add_bfchar(cmap, wbuf, 2, wbuf + 2, len);
- }
- RELEASE(name);
- } else {
- wbuf[0] = (gid >> 8) & 0xff;
- wbuf[1] = gid & 0xff;
-
- inbuf = wbuf;
- inbytesleft = 2;
- outbuf = wbuf + 2;
- outbytesleft = WBUF_SIZE - 2;
- CMap_decode(cmap_add, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
-
- if (inbytesleft != 0) {
- WARN("CMap conversion failed...");
- } else {
- len = WBUF_SIZE - 2 - outbytesleft;
- CMap_add_bfchar(cmap, wbuf, 2, wbuf + 2, len);
+ buf[0] = (cid >> 8) & 0xff;
+ buf[1] = cid & 0xff;
+ CMap_add_bfchar(cmap, buf, 2, buf + 2, len);
+ used_chars[cid / 8] &= ~(1 << (7 - (cid % 8)));
count++;
- if (dpx_conf.verbose_level > VERBOSE_LEVEL_MIN) {
- int _i;
-
- MESG("otf_cmap>> Additional ToUnicode mapping: <%04X> <", gid);
- for (_i = 0; _i < len; _i++) {
- MESG("%02X", wbuf[2 + _i]);
- }
- MESG(">\n");
- }
+ RELEASE(buf);
}
}
}
@@ -980,70 +826,11 @@ handle_subst_glyphs (CMap *cmap,
return count;
}
-static cff_font *
-prepare_CIDFont_from_sfnt(sfnt* sfont)
-{
- cff_font *cffont;
- unsigned offset = 0;
-
- if (sfont->type != SFNT_TYPE_POSTSCRIPT ||
- sfnt_read_table_directory(sfont, 0) < 0 ||
- (offset = sfnt_find_table_pos(sfont, "CFF ")) == 0) {
- return NULL;
- }
-
- cffont = cff_open(sfont->stream, offset, 0);
- if (!cffont)
- return NULL;
-
- cff_read_charsets(cffont);
- return cffont;
-}
-
-static USHORT
-add_to_cmap_if_used (CMap *cmap,
- cff_font *cffont,
- char *used_chars,
- USHORT gid,
- ULONG ch)
-{
- USHORT count = 0;
- USHORT cid = cffont ? cff_charsets_lookup_inverse(cffont, gid) : gid;
- if (is_used_char2(used_chars, cid)) {
- int len;
- unsigned char *p = wbuf + 2;
-
- count++;
-
- wbuf[0] = (cid >> 8) & 0xff;
- wbuf[1] = (cid & 0xff);
- len = UC_UTF16BE_encode_char((int32_t) ch, &p, wbuf + WBUF_SIZE);
- CMap_add_bfchar(cmap, wbuf, 2, wbuf + 2, len);
-
- /* Skip PUA characters and alphabetic presentation forms, allowing
- * handle_subst_glyphs() as it might find better mapping. Fixes the
- * mapping of ligatures encoded in PUA in fonts like Linux Libertine
- * and old Adobe fonts.
- */
- if (!is_PUA_or_presentation(ch)) {
- /* Avoid duplicate entry
- * There are problem when two Unicode code is mapped to
- * single glyph...
- */
- used_chars[cid / 8] &= ~(1 << (7 - (cid % 8)));
- }
- }
-
- return count;
-}
-
-static USHORT
-create_ToUnicode_cmap4 (CMap *cmap,
- struct cmap4 *map,
- char *used_chars,
- cff_font *cffont)
+static void
+create_inverse_cmap4 (int32_t *map_base, int32_t *map_sub, USHORT num_glyphs,
+ struct cmap4 *map)
{
- USHORT count = 0, segCount = map->segCountX2 / 2;
+ USHORT segCount = map->segCountX2 / 2;
USHORT i, j;
for (i = 0; i < segCount; i++) {
@@ -1062,32 +849,33 @@ create_ToUnicode_cmap4 (CMap *cmap,
} else {
gid = (map->glyphIndexArray[j + d] + map->idDelta[i]) & 0xffff;
}
-
- count += add_to_cmap_if_used(cmap, cffont, used_chars, gid, ch);
+ if (is_PUA_or_presentation(ch)) {
+ map_sub[gid] = ch;
+ } else {
+ map_base[gid] = ch;
+ }
}
}
-
- return count;
}
-static USHORT
-create_ToUnicode_cmap12 (CMap *cmap,
- struct cmap12 *map,
- char *used_chars,
- cff_font *cffont)
+static void
+create_inverse_cmap12 (int32_t *map_base, int32_t *map_sub, USHORT num_glyphs,
+ struct cmap12 *map)
{
- ULONG i, ch, count = 0;
+ ULONG i, ch;
for (i = 0; i < map->nGroups; i++) {
for (ch = map->groups[i].startCharCode;
ch <= map->groups[i].endCharCode; ch++) {
int d = ch - map->groups[i].startCharCode;
USHORT gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff);
- count += add_to_cmap_if_used(cmap, cffont, used_chars, gid, ch);
+ if (is_PUA_or_presentation(ch)) {
+ map_sub[gid] = ch;
+ } else {
+ map_base[gid] = ch;
+ }
}
}
-
- return count;
}
/* NOTE: Reverse mapping code which had been placed here is removed since:
@@ -1096,60 +884,163 @@ create_ToUnicode_cmap12 (CMap *cmap,
* Especially, the second one causes problems.
*/
static pdf_obj *
-create_ToUnicode_cmap (tt_cmap *ttcmap,
+create_ToUnicode_cmap (tt_cmap *ttcmap,
const char *cmap_name,
- CMap *cmap_add,
+ CMap *cmap_add,
const char *used_chars,
- sfnt *sfont)
+ sfnt *sfont)
{
- pdf_obj *stream = NULL;
- CMap *cmap;
- USHORT count = 0;
- cff_font *cffont = prepare_CIDFont_from_sfnt(sfont);
- char is_cidfont = cffont && (cffont->flag & FONTTYPE_CIDFONT);
-
- cmap = CMap_new();
- CMap_set_name (cmap, cmap_name);
- CMap_set_wmode(cmap, 0);
- CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE);
- CMap_set_CIDSysInfo(cmap, &CSI_UNICODE);
- CMap_add_codespacerange(cmap, srange_min, srange_max, 2);
-
- /* cmap_add here stores information about all unencoded glyphs which can be
- * accessed only through OT Layout GSUB table.
- */
- {
- char used_chars_copy[8192];
- memcpy(used_chars_copy, used_chars, 8192);
+ pdf_obj *stream = NULL;
+ int32_t *map_base = NULL, *map_sub = NULL;
+ USHORT gid, num_glyphs = 0;
- /* For create_ToUnicode_cmap{4,12}(), cffont is for GID -> CID lookup,
- * so it is only needed for CID fonts. */
- switch (ttcmap->format) {
- case 4:
- count = create_ToUnicode_cmap4(cmap, ttcmap->map, used_chars_copy,
- is_cidfont ? cffont : NULL);
- break;
- case 12:
- count = create_ToUnicode_cmap12(cmap, ttcmap->map, used_chars_copy,
- is_cidfont ? cffont : NULL);
- break;
+ ASSERT(ttcmap);
+
+ /* Get num_glyphs from maxp talbe */
+ {
+ struct tt_maxp_table *maxp;
+
+ maxp = tt_read_maxp_table(sfont);
+ if (maxp) {
+ num_glyphs = maxp->numGlyphs;
+ RELEASE(maxp);
}
+ }
- /* For handle_subst_glyphs(), cffont is for GID -> glyph name lookup, so
- * it is only needed for non-CID fonts. */
- count += handle_subst_glyphs(cmap, cmap_add, used_chars_copy, sfont,
- is_cidfont ? NULL : cffont);
+ /* Initialize GID to Unicode mapping table */
+ map_base = NEW(num_glyphs, int32_t);
+ map_sub = NEW(num_glyphs, int32_t);
+ for (gid = 0; gid < num_glyphs; gid++) {
+ map_base[gid] = -1;
+ map_sub [gid] = -1;
}
- if (count < 1)
- stream = NULL;
- else {
- stream = CMap_create_stream(cmap);
+ /* Create "base" mapping from inverse mapping of OpenType cmap */
+ switch (ttcmap->format) {
+ case 4:
+ create_inverse_cmap4(map_base, map_sub, num_glyphs, ttcmap->map);
+ break;
+ case 12:
+ create_inverse_cmap12(map_base, map_sub, num_glyphs, ttcmap->map);
+ break;
}
- CMap_release(cmap);
- if (cffont)
- cff_close(cffont);
+ /* Now create ToUnicode CMap stream */
+ {
+ CMap *cmap;
+ int32_t count;
+ cff_font *cffont = NULL;
+ char is_cidfont = 0;
+ uint16_t *GIDToCIDMap = NULL;
+ char *used_chars_copy = NULL;
+
+ if (sfont->type == SFNT_TYPE_POSTSCRIPT) {
+ ULONG offset;
+ offset = sfnt_find_table_pos(sfont, "CFF ");
+ cffont = cff_open(sfont->stream, offset, 0);
+ cff_read_charsets(cffont);
+ }
+ is_cidfont = cffont && (cffont->flag & FONTTYPE_CIDFONT);
+
+ /* GIT to CID mapping info. */
+ GIDToCIDMap = NEW(num_glyphs, uint16_t);
+ if (is_cidfont) {
+ create_GIDToCIDMap(GIDToCIDMap, num_glyphs, cffont);
+ } else {
+ for (gid = 0; gid < num_glyphs; gid++) {
+ GIDToCIDMap[gid] = gid;
+ }
+ }
+ cmap = CMap_new();
+ CMap_set_name (cmap, cmap_name);
+ CMap_set_wmode(cmap, 0);
+ CMap_set_type (cmap, CMAP_TYPE_TO_UNICODE);
+ CMap_set_CIDSysInfo(cmap, &CSI_UNICODE);
+ CMap_add_codespacerange(cmap, srange_min, srange_max, 2);
+
+ count = 0;
+ used_chars_copy = NEW(8192, char);
+ memcpy(used_chars_copy, used_chars, 8192);
+ for (gid = 0; gid < num_glyphs; gid++) {
+ uint16_t cid = GIDToCIDMap[gid];
+ if (is_used_char2(used_chars_copy, cid)) {
+ int32_t ch;
+ unsigned char src[2], dst[4];
+ unsigned char *p = dst, *endptr = dst + 4;
+ size_t len;
+
+ ch = map_base[gid];
+ if (UC_is_valid(ch)) {
+ src[0] = (cid >> 8) & 0xff;
+ src[1] = cid & 0xff;
+ len = UC_UTF16BE_encode_char(ch, &p, endptr);
+ CMap_add_bfchar(cmap, src, 2, dst, len);
+ used_chars_copy[cid / 8] &= ~(1 << (7 - (cid % 8)));
+ count++;
+ }
+ }
+ }
+
+ /* cmap_add here stores information about all unencoded glyphs which can be
+ * accessed only through OT Layout GSUB table.
+ * This is only availabel when encoding is "unicode".
+ */
+ if (cmap_add) {
+ count += handle_subst_glyphs(cmap, cmap_add, used_chars_copy);
+ } else {
+ /* Else, try gathering information from GSUB tables */
+ count += otl_gsub_add_ToUnicode(cmap, used_chars_copy,
+ map_base, map_sub, num_glyphs,
+ GIDToCIDMap, sfont);
+ }
+ /* Find Unicode mapping via PostScript glyph names... */
+ count += add_ToUnicode_via_glyph_name(cmap, used_chars_copy, num_glyphs,
+ GIDToCIDMap, sfont, is_cidfont ? NULL : cffont);
+ if (cffont)
+ cff_close(cffont);
+
+ /* Finaly, PUA and presentation forms... */
+ for (gid = 0; gid < num_glyphs; gid++) {
+ uint16_t cid = GIDToCIDMap[gid];
+ if (is_used_char2(used_chars_copy, cid)) {
+ int32_t ch;
+ unsigned char src[2], dst[4];
+ unsigned char *p = dst, *endptr = dst + 4;
+ size_t len;
+
+ ch = map_sub[gid];
+ if (UC_is_valid(ch)) {
+ src[0] = (cid >> 8) & 0xff;
+ src[1] = cid & 0xff;
+ len = UC_UTF16BE_encode_char(ch, &p, endptr);
+ CMap_add_bfchar(cmap, src, 2, dst, len);
+ used_chars_copy[cid / 8] &= ~(1 << (7 - (cid % 8)));
+ count++;
+ }
+ }
+ }
+
+ /* Check for missing mapping */
+ if (dpx_conf.verbose_level > VERBOSE_LEVEL_MIN) {
+ for (gid = 0; gid < num_glyphs; gid++) {
+ uint16_t cid = GIDToCIDMap[gid];
+ if (is_used_char2(used_chars_copy, cid)) {
+ WARN("Unable to find ToUnicode mapping for glyph CID=%u (GID=%u)", cid, gid);
+ }
+ }
+ }
+ RELEASE(GIDToCIDMap);
+ RELEASE(used_chars_copy);
+
+ if (count < 1)
+ stream = NULL;
+ else {
+ stream = CMap_create_stream(cmap);
+ }
+ CMap_release(cmap);
+ }
+ RELEASE(map_base);
+ RELEASE(map_sub);
return stream;
}
@@ -1169,29 +1060,27 @@ static cmap_plat_enc_rec cmap_plat_encs[] = {
pdf_obj *
otf_create_ToUnicode_stream (const char *font_name,
- int ttc_index, /* 0 for non-TTC */
+ int ttc_index, /* 0 for non-TTC */
const char *basefont,
const char *used_chars)
{
- pdf_obj *cmap_ref = NULL;
- int res_id;
- pdf_obj *cmap_obj = NULL;
- CMap *cmap_add;
- int cmap_add_id;
- tt_cmap *ttcmap;
- char *cmap_name, *cmap_add_name;
- FILE *fp = NULL;
- sfnt *sfont;
- ULONG offset = 0;
- int i;
+ pdf_obj *cmap_ref = NULL; /* returned value */
+ CMap *cmap_add = NULL;
+ char *cmap_name;
+ FILE *fp = NULL;
+ sfnt *sfont;
+ ULONG offset = 0;
+ tt_cmap *ttcmap;
+ int cmap_id, cmap_add_id;
+ int i;
cmap_name = NEW(strlen(basefont)+strlen("-UTF16")+1, char);
sprintf(cmap_name, "%s-UTF16", basefont);
- res_id = pdf_findresource("CMap", cmap_name);
- if (res_id >= 0) {
+ cmap_id = pdf_findresource("CMap", cmap_name);
+ if (cmap_id >= 0) {
RELEASE(cmap_name);
- cmap_ref = pdf_get_resource_reference(res_id);
+ cmap_ref = pdf_get_resource_reference(cmap_id);
return cmap_ref;
}
@@ -1212,7 +1101,10 @@ otf_create_ToUnicode_stream (const char *font_name,
}
if (!sfont) {
- ERROR("Could not open OpenType/TrueType font file \"%s\"", font_name);
+ WARN("Could not open OpenType/TrueType font file \"%s\"", font_name);
+ RELEASE(cmap_name);
+ DPXFCLOSE(fp);
+ return NULL;
}
switch (sfont->type) {
@@ -1222,7 +1114,11 @@ otf_create_ToUnicode_stream (const char *font_name,
case SFNT_TYPE_TTC:
offset = ttc_read_offset(sfont, ttc_index);
if (offset == 0) {
- ERROR("Invalid TTC index");
+ WARN("Invalid TTC index for font: %s", font_name);
+ sfnt_close(sfont);
+ DPXFCLOSE(fp);
+ RELEASE(cmap_name);
+ return NULL;
}
break;
default:
@@ -1231,111 +1127,180 @@ otf_create_ToUnicode_stream (const char *font_name,
}
if (sfnt_read_table_directory(sfont, offset) < 0) {
- ERROR("Could not read OpenType/TrueType table directory.");
+ WARN("Could not read OpenType/TrueType table directory: %s", font_name);
+ sfnt_close(sfont);
+ DPXFCLOSE(fp);
+ RELEASE(cmap_name);
+ return NULL;
}
- cmap_add_name = NEW(strlen(font_name)+strlen(",000-UCS32-Add")+1, char);
- sprintf(cmap_add_name, "%s,%03d-UCS32-Add", font_name, ttc_index);
- cmap_add_id = CMap_cache_find(cmap_add_name);
- RELEASE(cmap_add_name);
- if (cmap_add_id < 0) {
- cmap_add = NULL;
- } else {
- cmap_add = CMap_cache_get(cmap_add_id);
+ /* cmap_add is used for storing information on ToUnicode mapping for
+ * unencoded glyphs which can be reached only through GSUB substitution.
+ * This is available only when "unicode" is specified in the encoding
+ * field of fontmap. We remember the inverse mapping via cmap_add in this
+ * case.
+ */
+ {
+ char *cmap_add_name;
+
+ cmap_add_name = NEW(strlen(font_name)+strlen(",000-UCS32-Add")+1, char);
+ sprintf(cmap_add_name, "%s,%03d-UCS32-Add", font_name, ttc_index);
+ cmap_add_id = CMap_cache_find(cmap_add_name);
+ RELEASE(cmap_add_name);
+ if (cmap_add_id < 0) {
+ cmap_add = NULL;
+ } else {
+ cmap_add = CMap_cache_get(cmap_add_id);
+ }
}
- CMap_set_silent(1); /* many warnings without this... */
+ ttcmap = NULL;
for (i = 0; i < sizeof(cmap_plat_encs) / sizeof(cmap_plat_enc_rec); ++i) {
ttcmap = tt_cmap_read(sfont, cmap_plat_encs[i].platform, cmap_plat_encs[i].encoding);
if (!ttcmap)
continue;
if (ttcmap->format == 4 || ttcmap->format == 12) {
- cmap_obj = create_ToUnicode_cmap(ttcmap, cmap_name, cmap_add, used_chars, sfont);
break;
+ } else {
+ tt_cmap_release(ttcmap);
+ ttcmap = NULL;
}
}
-#if defined(LIBDPX)
- if (cmap_obj == NULL && dpx_conf.verbose_level > VERBOSE_LEVEL_MIN)
-#else
- if (cmap_obj == NULL)
-#endif /* LIBDPX */
- WARN("Unable to read OpenType/TrueType Unicode cmap table.");
- tt_cmap_release(ttcmap);
- CMap_set_silent(0);
-
- if (cmap_obj) {
- res_id = pdf_defineresource("CMap", cmap_name,
- cmap_obj, PDF_RES_FLUSH_IMMEDIATE);
- cmap_ref = pdf_get_resource_reference(res_id);
- } else {
- cmap_ref = NULL;
+ if (ttcmap) {
+ pdf_obj *cmap_obj;
+
+ CMap_set_silent(1); /* many warnings without this... */
+ cmap_obj = create_ToUnicode_cmap(ttcmap, cmap_name, cmap_add, used_chars, sfont);
+ CMap_set_silent(0);
+ if (cmap_obj) {
+ cmap_id = pdf_defineresource("CMap", cmap_name,
+ cmap_obj, PDF_RES_FLUSH_IMMEDIATE);
+ cmap_ref = pdf_get_resource_reference(cmap_id);
+ }
+ tt_cmap_release(ttcmap);
}
- RELEASE(cmap_name);
+ /* Cleanup */
+ RELEASE(cmap_name);
sfnt_close(sfont);
- if (fp)
- DPXFCLOSE(fp);
+ DPXFCLOSE(fp);
+
+#ifndef LIBDPX
+ if (!cmap_ref) {
+ WARN("Creating ToUnicode CMap failed for \"%s\"", font_name);
+ }
+#endif
return cmap_ref;
}
-static int
-load_base_CMap (const char *cmap_name, CMap *tounicode_add, int wmode,
- CIDSysInfo *csi, unsigned char *GIDToCIDMap,
- otl_gsub *gsub_vert, otl_gsub *gsub_list,
- tt_cmap *ttcmap)
-{
- int cmap_id;
- cmap_id = CMap_cache_find(cmap_name);
- if (cmap_id < 0) {
- CMap *cmap;
+/* Creating input CMaps from OT cmap table */
- 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);
+static void
+load_cmap4 (struct cmap4 *map, uint16_t *GIDToCIDMap, USHORT num_glyphs,
+ otl_gsub *gsub_vert, otl_gsub *gsub_list,
+ CMap *cmap, int32_t *map_base, int32_t *map_sub)
+{
+ USHORT c0, c1, gid, cid;
+ USHORT j, d, segCount;
+ USHORT ch;
+ int i;
+ unsigned char buf[4];
- if (csi) { /* CID */
- CMap_set_CIDSysInfo(cmap, csi);
- } else {
- CMap_set_CIDSysInfo(cmap, &CSI_IDENTITY);
+ segCount = map->segCountX2 / 2;
+ for (i = segCount - 1; i >= 0 ; i--) {
+ c0 = map->startCount[i];
+ c1 = map->endCount[i];
+ d = map->idRangeOffset[i] / 2 - (segCount - i);
+ for (j = 0; j <= c1 - c0; j++) {
+ ch = c0 + j;
+ if (map->idRangeOffset[i] == 0) {
+ gid = (ch + map->idDelta[i]) & 0xffff;
+ } else if (c0 == 0xffff && c1 == 0xffff && map->idRangeOffset[i] == 0xffff) {
+ /* this is for protection against some old broken fonts... */
+ gid = 0;
+ } else {
+ gid = (map->glyphIndexArray[j+d] + map->idDelta[i]) & 0xffff;
+ }
+ if (gid != 0 && gid != 0xffff) {
+ /* Apply GSUB features */
+ if (gsub_list)
+ otl_gsub_apply_chain(gsub_list, &gid);
+ if (gsub_vert)
+ otl_gsub_apply(gsub_vert, &gid);
+ cid = (gid < num_glyphs) ? GIDToCIDMap[gid] : 0;
+ buf[0] = 0;
+ buf[1] = 0;
+ buf[2] = (ch >> 8) & 0xff;
+ buf[3] = ch & 0xff;
+ CMap_add_cidchar(cmap, buf, 4, cid);
+ /* For ToUnicode creation */
+ if (map_base && map_sub) {
+ if (is_PUA_or_presentation(ch)) {
+ map_sub[gid] = ch;
+ } else {
+ map_base[gid] = ch;
+ }
+ }
+ }
}
+ }
- if (ttcmap->format == 12) {
- load_cmap12(ttcmap->map, GIDToCIDMap, gsub_vert, gsub_list,
- cmap, tounicode_add);
- } else if (ttcmap->format == 4) {
- load_cmap4(ttcmap->map, GIDToCIDMap, gsub_vert, gsub_list,
- cmap, tounicode_add);
- }
+ return;
+}
- cmap_id = CMap_cache_add(cmap);
+static void
+load_cmap12 (struct cmap12 *map, uint16_t *GIDToCIDMap, USHORT num_glyphs,
+ otl_gsub *gsub_vert, otl_gsub *gsub_list,
+ CMap *cmap, int32_t *map_base, int32_t *map_sub)
+{
+ ULONG i, ch;
+ USHORT gid, cid;
+ unsigned char buf[4];
+
+ for (i = 0; i < map->nGroups; i++) {
+ for (ch = map->groups[i].startCharCode;
+ ch <= map->groups[i].endCharCode; ch++) {
+ int d = ch - map->groups[i].startCharCode;
+ gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff);
+ if (gsub_list)
+ otl_gsub_apply_chain(gsub_list, &gid);
+ if (gsub_vert)
+ otl_gsub_apply(gsub_vert, &gid);
+ cid = (gid < num_glyphs) ? GIDToCIDMap[gid] : 0;
+ buf[0] = (ch >> 24) & 0xff;
+ buf[1] = (ch >> 16) & 0xff;
+ buf[2] = (ch >> 8) & 0xff;
+ buf[3] = ch & 0xff;
+ CMap_add_cidchar(cmap, buf, 4, cid);
+ if (map_base && map_sub) {
+ if (is_PUA_or_presentation(ch)) {
+ map_sub[gid] = ch;
+ } else {
+ map_base[gid] = ch;
+ }
+ }
+ }
}
- return cmap_id;
+ return;
}
int
otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC font */
- const char *otl_tags, int wmode)
+ const char *otl_tags, int wmode)
{
- int cmap_id = -1;
- /* Additional ToUncidoe mappings required by OTL GSUB substitusion */
- int tounicode_add_id = -1;
- CMap *tounicode_add = NULL;
- char *tounicode_add_name = NULL;
- int is_cidfont = 0;
- sfnt *sfont;
- ULONG offset = 0;
- char *cmap_name = NULL;
- FILE *fp = NULL;
- otl_gsub *gsub_vert = NULL, *gsub_list = NULL;
- tt_cmap *ttcmap;
- CIDSysInfo csi = {NULL, NULL, 0};
- unsigned char *GIDToCIDMap = NULL;
+ int cmap_id = -1;
+ char *cmap_name = NULL;
+ sfnt *sfont = NULL;
+ ULONG offset = 0;
+ uint16_t num_glyphs = 0;
+ FILE *fp = NULL;
+ tt_cmap *ttcmap = NULL;
+ CIDSysInfo csi = {NULL, NULL, 0};
+ uint16_t *GIDToCIDMap = NULL;
if (!map_name)
return -1;
@@ -1359,11 +1324,6 @@ otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC fon
sprintf(cmap_name, "%s,%03d-UCS4-H", map_name, ttc_index);
}
}
- if (dpx_conf.verbose_level > 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);
@@ -1374,6 +1334,12 @@ otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC fon
}
/* CMap not found */
+ if (dpx_conf.verbose_level > VERBOSE_LEVEL_MIN) {
+ MESG("\n");
+ MESG("otf_cmap>> Creating Unicode charmap for font=\"%s\" layout=\"%s\"\n",
+ map_name, (otl_tags ? otl_tags : "none"));
+ }
+
fp = DPXFOPEN(map_name, DPX_RES_TYPE_TTFONT);
if (!fp) {
fp = DPXFOPEN(map_name, DPX_RES_TYPE_OTFONT);
@@ -1390,13 +1356,20 @@ otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC fon
}
if (!sfont) {
- ERROR("Could not open OpenType/TrueType/dfont font file \"%s\"", map_name);
+ WARN("Could not open OpenType/TrueType/dfont font file \"%s\"", map_name);
+ RELEASE(cmap_name);
+ DPXFCLOSE(fp);
+ return -1;
}
switch (sfont->type) {
case SFNT_TYPE_TTC:
offset = ttc_read_offset(sfont, ttc_index);
if (offset == 0) {
- ERROR("Invalid TTC index");
+ WARN("Offset=0 returned for font=%s, TTC_index=%d", map_name, ttc_index);
+ RELEASE(cmap_name);
+ sfnt_close(sfont);
+ DPXFCLOSE(fp);
+ return -1;
}
break;
case SFNT_TYPE_TRUETYPE:
@@ -1407,41 +1380,79 @@ otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC fon
offset = sfont->offset;
break;
default:
- ERROR("Not a OpenType/TrueType/TTC font?: %s", map_name);
+ WARN("Not a OpenType/TrueType/TTC font?: %s", map_name);
+ RELEASE(cmap_name);
+ sfnt_close(sfont);
+ DPXFCLOSE(fp);
+ return -1;
break;
}
- if (sfnt_read_table_directory(sfont, offset) < 0)
- ERROR("Could not read OpenType/TrueType table directory.");
+ if (sfnt_read_table_directory(sfont, offset) < 0) {
+ WARN("Could not read OpenType/TrueType table directory: %s", map_name);
+ RELEASE(cmap_name);
+ sfnt_close(sfont);
+ DPXFCLOSE(fp);
+ return -1;
+ }
+ {
+ struct tt_maxp_table *maxp;
- if (otl_tags) {
- /* tounicode_add here is later refered by otf_create_ToUnicode_stream()
- * for finding additional CID to Unicode mapping entries required by
- * OTL gsub substitution.
- */
- tounicode_add_name = NEW(strlen(map_name)+strlen(",000-UCS32-Add")+1, char);
- sprintf(tounicode_add_name, "%s,%03d-UCS32-Add", map_name, ttc_index);
- tounicode_add_id = CMap_cache_find(tounicode_add_name);
- if (tounicode_add_id >= 0)
- tounicode_add = CMap_cache_get(tounicode_add_id);
- else {
- tounicode_add = CMap_new();
- CMap_set_name (tounicode_add, tounicode_add_name);
- CMap_set_type (tounicode_add, CMAP_TYPE_TO_UNICODE);
- CMap_set_wmode(tounicode_add, 0);
- CMap_add_codespacerange(tounicode_add, srange_min, srange_max, 2);
- CMap_set_CIDSysInfo(tounicode_add, &CSI_UNICODE);
- CMap_add_bfchar(tounicode_add, srange_min, 2, srange_max, 2);
- tounicode_add_id = CMap_cache_add(tounicode_add);
- }
- RELEASE(tounicode_add_name);
+ maxp = tt_read_maxp_table(sfont);
+ num_glyphs = (card16) maxp->numGlyphs;
+ RELEASE(maxp);
}
+ GIDToCIDMap = NEW(num_glyphs, uint16_t);
+ memset(GIDToCIDMap, 0, num_glyphs*sizeof(uint16_t));
if (sfont->type == SFNT_TYPE_POSTSCRIPT) {
- is_cidfont = handle_CIDFont(sfont, &GIDToCIDMap, &csi);
+ cff_font *cffont;
+ card16 gid;
+
+ offset = sfnt_find_table_pos(sfont, "CFF ");
+ cffont = cff_open(sfont->stream, offset, 0);
+ if (!cffont) {
+ RELEASE(cmap_name);
+ RELEASE(GIDToCIDMap);
+ sfnt_close(sfont);
+ DPXFCLOSE(fp);
+ return -1;
+ }
+ if (!(cffont->flag & FONTTYPE_CIDFONT)) {
+ csi.registry = strdup("Adobe");
+ csi.ordering = strdup("Identity");
+ csi.supplement = 0;
+ for (gid = 0; gid < num_glyphs; gid++) {
+ GIDToCIDMap[gid] = gid;
+ }
+ } else {
+ if (!cff_dict_known(cffont->topdict, "ROS")) {
+ csi.registry = strdup("Adobe");
+ csi.ordering = strdup("Identity");
+ csi.supplement = 0;
+ } else {
+ card16 reg, ord;
+
+ reg = (card16) cff_dict_get(cffont->topdict, "ROS", 0);
+ ord = (card16) cff_dict_get(cffont->topdict, "ROS", 1);
+ csi.registry = cff_get_string(cffont, reg);
+ csi.ordering = cff_get_string(cffont, ord);
+ csi.supplement = (int) cff_dict_get(cffont->topdict, "ROS", 2);
+ }
+ cff_read_charsets(cffont);
+ create_GIDToCIDMap(GIDToCIDMap, num_glyphs, cffont);
+ }
+ cff_close(cffont);
} else {
- is_cidfont = 0;
+ uint16_t gid;
+
+ csi.registry = strdup("Adobe");
+ csi.ordering = strdup("Identity");
+ csi.supplement = 0;
+ for (gid = 0; gid < num_glyphs; gid++) {
+ GIDToCIDMap[gid] = gid;
+ }
}
ttcmap = tt_cmap_read(sfont, 3, 10); /* Microsoft UCS4 */
@@ -1449,63 +1460,122 @@ otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC fon
ttcmap = tt_cmap_read(sfont, 3, 1); /* Microsoft UCS2 */
if (!ttcmap) {
ttcmap = tt_cmap_read(sfont, 0, 3); /* Unicode 2.0 or later */
-#if defined(LIBDPX)
- if (!ttcmap && dpx_conf.verbose_level > VERBOSE_LEVEL_MIN) {
-#else
- if (!ttcmap) {
-#endif /* LIBDPX */
- ERROR("Unable to read OpenType/TrueType Unicode cmap table.");
- }
}
}
- if (wmode == 1) {
- 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_vert);
- gsub_vert = NULL;
+
+ if (ttcmap) {
+ CMap *cmap = NULL;
+ int32_t *map_base, *map_sub;
+ otl_gsub *gsub_vert = NULL;
+ otl_gsub *gsub_list = NULL;
+ uint32_t gid;
+
+ if (wmode == 1) {
+ 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_vert);
+ gsub_vert = NULL;
+ } else {
+ otl_gsub_select(gsub_vert, "*", "*", "vert");
+ }
} else {
- otl_gsub_select(gsub_vert, "*", "*", "vert");
+ otl_gsub_select(gsub_vert, "*", "*", "vrt2");
}
} else {
- otl_gsub_select(gsub_vert, "*", "*", "vrt2");
+ gsub_vert = NULL;
}
- } 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);
+ if (otl_tags) {
+ gsub_list = otl_gsub_new();
+ if (otl_gsub_add_feat_list(gsub_list, otl_tags, sfont) < 0) {
+ WARN("Reading GSUB feature table(s) failed for \"%s\"", otl_tags);
+ } else {
+ otl_gsub_set_chain(gsub_list, otl_tags);
+ }
} else {
- otl_gsub_set_chain(gsub_list, otl_tags);
+ gsub_list = NULL;
}
- } else {
- gsub_list = NULL;
- }
- cmap_id = load_base_CMap(cmap_name, tounicode_add, wmode,
- (is_cidfont ? &csi : NULL), GIDToCIDMap,
- 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;
+ 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_CIDSysInfo(cmap, &csi);
+ map_base = NEW(num_glyphs, int32_t);
+ map_sub = NEW(num_glyphs, int32_t);
+ for (gid = 0; gid < num_glyphs; gid++) {
+ map_base[gid] = -1;
+ map_sub[gid] = -1;
+ }
+ switch (ttcmap->format) {
+ case 12:
+ load_cmap12(ttcmap->map, GIDToCIDMap, num_glyphs,
+ gsub_vert, gsub_list,
+ cmap, map_base, map_sub);
+ break;
+ case 4:
+ load_cmap4(ttcmap->map, GIDToCIDMap, num_glyphs,
+ gsub_vert, gsub_list,
+ cmap, map_base, map_sub);
+ break;
+ }
+ if (gsub_vert)
+ otl_gsub_release(gsub_vert);
+ if (gsub_list)
+ otl_gsub_release(gsub_list);
+ tt_cmap_release(ttcmap);
+
+ if (otl_tags) {
+ CMap *tounicode = NULL;
+ char *tounicode_name;
+ int tounicode_id;
+
+ tounicode_name = NEW(strlen(map_name)+strlen(",000-UCS32-Add")+1, char);
+ sprintf(tounicode_name, "%s,%03d-UCS32-Add", map_name, ttc_index);
+ 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);
+ CMap_add_bfchar(tounicode, srange_min, 2, srange_max, 2);
+ tounicode_id = CMap_cache_add(tounicode);
+ }
+ RELEASE(tounicode_name);
+
+ for (gid = 0; gid < num_glyphs; gid++) {
+ uint16_t cid = GIDToCIDMap[gid];
+ unsigned char src[2], dst[4];
+ if (cid > 0) {
+ int32_t ch = UC_is_valid(map_base[gid]) ? map_base[gid] : map_sub[gid];
+ if (UC_is_valid(ch)) {
+ unsigned char *p = dst;
+ unsigned char *endptr = dst + 4;
+ size_t len;
+ src[0] = (cid >> 8) & 0xff;
+ src[1] = cid & 0xff;
+ len = UC_UTF16BE_encode_char(ch, &p, endptr);
+ if (len > 0) {
+ CMap_add_bfchar(tounicode, src, 2, dst, len);
+ }
+ }
+ }
+ }
+ }
+ cmap_id = CMap_cache_add(cmap);
+ }
RELEASE(cmap_name);
- if (GIDToCIDMap)
- RELEASE(GIDToCIDMap);
- if (is_cidfont) {
- if (csi.registry)
- RELEASE(csi.registry);
- if (csi.ordering)
- RELEASE(csi.ordering);
- }
- tt_cmap_release(ttcmap);
+ RELEASE(GIDToCIDMap);
+ if (csi.registry)
+ RELEASE(csi.registry);
+ if (csi.ordering)
+ RELEASE(csi.ordering);
sfnt_close(sfont);
DPXFCLOSE(fp);
@@ -1515,14 +1585,11 @@ otf_load_Unicode_CMap (const char *map_name, int ttc_index, /* 0 for non-TTC fon
int
otf_try_load_GID_to_CID_map (const char *map_name, int ttc_index, int wmode)
{
- int cmap_id = -1;
- sfnt *sfont;
- ULONG offset = 0;
- char *cmap_name = NULL;
- FILE *fp = NULL;
- CIDSysInfo csi = {NULL, NULL, 0};
- int is_cidfont = 0;
- unsigned char *GIDToCIDMap = NULL;
+ int cmap_id = -1;
+ sfnt *sfont = NULL;
+ ULONG offset = 0;
+ char *cmap_name = NULL;
+ FILE *fp = NULL;
if (!map_name)
return -1;
@@ -1559,13 +1626,20 @@ otf_try_load_GID_to_CID_map (const char *map_name, int ttc_index, int wmode)
}
if (!sfont) {
- ERROR("Could not open OpenType/TrueType/dfont font file \"%s\"", map_name);
+ WARN("Could not open OpenType/TrueType/dfont font file \"%s\"", map_name);
+ RELEASE(cmap_name);
+ DPXFCLOSE(fp);
+ return -1;
}
switch (sfont->type) {
case SFNT_TYPE_TTC:
offset = ttc_read_offset(sfont, ttc_index);
if (offset == 0) {
- ERROR("Invalid TTC index");
+ WARN("Invalid TTC index for font \"%s\": %d", map_name, ttc_index);
+ sfnt_close(sfont);
+ DPXFCLOSE(fp);
+ RELEASE(cmap_name);
+ return -1;
}
break;
case SFNT_TYPE_TRUETYPE:
@@ -1576,12 +1650,20 @@ otf_try_load_GID_to_CID_map (const char *map_name, int ttc_index, int wmode)
offset = sfont->offset;
break;
default:
- ERROR("Not a OpenType/TrueType/TTC font?: %s", map_name);
- break;
+ WARN("Not a OpenType/TrueType/TTC font?: %s", map_name);
+ sfnt_close(sfont);
+ DPXFCLOSE(fp);
+ RELEASE(cmap_name);
+ return -1;
}
- if (sfnt_read_table_directory(sfont, offset) < 0)
- ERROR("Could not read OpenType/TrueType table directory.");
+ if (sfnt_read_table_directory(sfont, offset) < 0) {
+ WARN("Could not read OpenType/TrueType table directory: %s", map_name);
+ sfnt_close(sfont);
+ DPXFCLOSE(fp);
+ RELEASE(cmap_name);
+ return -1;
+ }
if (sfont->type != SFNT_TYPE_POSTSCRIPT) {
RELEASE(cmap_name);
sfnt_close(sfont);
@@ -1590,41 +1672,71 @@ otf_try_load_GID_to_CID_map (const char *map_name, int ttc_index, int wmode)
}
/* Read GID-to-CID mapping if CFF OpenType is found. */
- is_cidfont = handle_CIDFont(sfont, &GIDToCIDMap, &csi);
- if (is_cidfont) {
- if (GIDToCIDMap) {
- CMap *cmap;
- int32_t gid;
- const unsigned char csrange[4] = {0x00, 0x00, 0xff, 0xff};
+ if (sfont->type == SFNT_TYPE_POSTSCRIPT) {
+ cff_font *cffont;
+ struct tt_maxp_table *maxp;
+ const unsigned char csrange[4] = {0x00, 0x00, 0xff, 0xff};
+ uint16_t num_glyphs = 0;
+
+ maxp = tt_read_maxp_table(sfont);
+ num_glyphs = (card16) maxp->numGlyphs;
+ RELEASE(maxp);
+
+ offset = sfnt_find_table_pos(sfont, "CFF ");
+ cffont = cff_open(sfont->stream, offset, 0);
+ if (cffont && cffont->flag & FONTTYPE_CIDFONT) {
+ CMap *cmap;
+ uint16_t gid;
+ uint16_t *GIDToCIDMap = NULL;
+ CIDSysInfo csi = {NULL, NULL, 0};
+
+ if (!cff_dict_known(cffont->topdict, "ROS")) {
+ csi.registry = strdup("Adobe");
+ csi.ordering = strdup("Identity");
+ csi.supplement = 0;
+ } else {
+ card16 reg, ord;
+ reg = (card16) cff_dict_get(cffont->topdict, "ROS", 0);
+ ord = (card16) cff_dict_get(cffont->topdict, "ROS", 1);
+ csi.registry = cff_get_string(cffont, reg);
+ csi.ordering = cff_get_string(cffont, ord);
+ csi.supplement = (int) cff_dict_get(cffont->topdict, "ROS", 2);
+ }
+ cff_read_charsets(cffont);
+ GIDToCIDMap = NEW(num_glyphs, uint16_t);
+ memset(GIDToCIDMap, 0, num_glyphs*sizeof(uint16_t));
+ create_GIDToCIDMap(GIDToCIDMap, num_glyphs, cffont);
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, &csrange[0], &csrange[2], 2);
CMap_set_CIDSysInfo(cmap, &csi);
-
- for (gid = 0; gid < 65536; gid++) {
- unsigned char src[2];
+ for (gid = 0; gid < num_glyphs; gid++) {
+ unsigned char src[2], dst[2];
src[0] = (gid >> 8) & 0xff;
src[1] = gid & 0xff;
- CMap_add_bfchar(cmap, src, 2, &GIDToCIDMap[gid*2], 2);
+ dst[0] = (GIDToCIDMap[gid] >> 8) & 0xff;
+ dst[1] = GIDToCIDMap[gid] & 0xff;
+ CMap_add_bfchar(cmap, src, 2, dst, 2);
}
cmap_id = CMap_cache_add(cmap);
if (dpx_conf.verbose_level > VERBOSE_LEVEL_MIN) {
MESG("\n");
MESG("otf_cmap>> Creating GID-to-CID mapping for font=\"%s\"\n", map_name);
}
+ RELEASE(GIDToCIDMap);
+ if (csi.registry)
+ RELEASE(csi.registry);
+ if (csi.ordering)
+ RELEASE(csi.ordering);
}
- /* Identity mapping for null GIDToCIDMap */
+ if (cffont)
+ cff_close(cffont);
}
+
RELEASE(cmap_name);
- if (GIDToCIDMap)
- RELEASE(GIDToCIDMap);
- if (csi.registry)
- RELEASE(csi.registry);
- if (csi.ordering)
- RELEASE(csi.ordering);
sfnt_close(sfont);
DPXFCLOSE(fp);