summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/tt_cmap.c
diff options
context:
space:
mode:
authorJjgod Jiang <gzjjgod@gmail.com>2014-08-04 07:29:07 +0000
committerJjgod Jiang <gzjjgod@gmail.com>2014-08-04 07:29:07 +0000
commit9e295194f1137856c64809a484b41306473d7a89 (patch)
treea0f9a63f20aa60fe06c216a40a1c75dae96551e8 /Build/source/texk/dvipdfm-x/tt_cmap.c
parente93685e85b3f0bff2eb571e79d77dccddd1cb2ed (diff)
Fix ToUnicode with reverse CMap lookup
When dvipdfmx is provided a regular CMap in the following format: <unicode codepoint> cid We can try to utilize the data and do a reverse lookup when all we know is the cids used. Initially, when parsing the cmap specified, we build a reverseMap which maps CID to the first Unicode codepoint it corresponds to. (Which is pretty much the reverse of CMap_decode().) Since this cmap is already parsed when we create the fontmap cache, we can just pass the cmap_id all the way down to otf_create_ToUnicode_stream() and get CMap* back from this cmap_id. Second, we refactor create_ToUnicode_cmap{4, 12}() functions into one create_ToUnicode_cmap() and combine the common code. In the third step, in create_ToUnicode_cmap() we try to see if the font is indeed a CFF font (with CID-keyed), and we do have a cmap, we can use the newly added CMap_reverse_decode() to convert all used cids back to Unicode codepoints. With that mapping information we can successfully create the ToUnicode PDF stream we needed. git-svn-id: svn://tug.org/texlive/trunk@34831 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipdfm-x/tt_cmap.c')
-rw-r--r--Build/source/texk/dvipdfm-x/tt_cmap.c187
1 files changed, 108 insertions, 79 deletions
diff --git a/Build/source/texk/dvipdfm-x/tt_cmap.c b/Build/source/texk/dvipdfm-x/tt_cmap.c
index 4638b8628be..d1dc49c797c 100644
--- a/Build/source/texk/dvipdfm-x/tt_cmap.c
+++ b/Build/source/texk/dvipdfm-x/tt_cmap.c
@@ -984,27 +984,14 @@ prepare_CIDFont_from_sfnt(sfnt* sfont)
return cffont;
}
-static pdf_obj *
-create_ToUnicode_cmap4 (struct cmap4 *map,
- const char *cmap_name, CMap *cmap_add,
- const char *used_glyphs,
- sfnt *sfont)
+static USHORT
+create_ToUnicode_cmap4 (CMap *cmap,
+ struct cmap4 *map,
+ char *used_glyphs,
+ cff_font *cffont)
{
- pdf_obj *stream = NULL;
- CMap *cmap;
USHORT c0, c1, gid, count, ch;
USHORT i, j, d, segCount;
- char used_glyphs_copy[8192];
- cff_font *cffont = prepare_CIDFont_from_sfnt(sfont);
-
- 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);
-
- memcpy(used_glyphs_copy, used_glyphs, 8192);
segCount = map->segCountX2 / 2;
for (count = 0, i = 0; i < segCount; i++) {
@@ -1022,7 +1009,7 @@ create_ToUnicode_cmap4 (struct cmap4 *map,
gid = (map->glyphIndexArray[j+d] +
map->idDelta[i]) & 0xffff;
}
- if (is_used_char2(used_glyphs_copy, gid)) {
+ if (is_used_char2(used_glyphs, gid)) {
unsigned int cid = cffont ? cff_charsets_lookup_inverse(cffont, gid) : gid;
count++;
@@ -1039,55 +1026,30 @@ create_ToUnicode_cmap4 (struct cmap4 *map,
* 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_glyphs_copy[gid/8] &= ~(1 << (7 - (gid % 8)));
- count++;
+ if (!is_PUA_or_presentation(ch)) {
+ /* Avoid duplicate entry
+ * There are problem when two Unicode code is mapped to
+ * single glyph...
+ */
+ used_glyphs[gid/8] &= ~(1 << (7 - (gid % 8)));
+ }
+ count++;
}
}
}
- count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy, sfont, cffont);
-
- if (count < 1)
- stream = NULL;
- else {
- stream = CMap_create_stream(cmap, 0);
- }
- CMap_release(cmap);
-
- if (cffont)
- cff_close(cffont);
-
- return stream;
+ return count;
}
-
-static pdf_obj *
-create_ToUnicode_cmap12 (struct cmap12 *map,
- const char *cmap_name, CMap *cmap_add,
- const char *used_glyphs,
- sfnt *sfont)
+static USHORT
+create_ToUnicode_cmap12 (CMap *cmap,
+ struct cmap12 *map,
+ char *used_glyphs,
+ cff_font *cffont)
{
- pdf_obj *stream = NULL;
- CMap *cmap;
- ULONG i, ch;
- USHORT gid, count;
- char used_glyphs_copy[8192];
- cff_font *cffont = prepare_CIDFont_from_sfnt(sfont);
+ USHORT i, gid, ch, count = 0;
- 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);
-
- memcpy(used_glyphs_copy, used_glyphs, 8192);
- for (count = 0, i = 0; i < map->nGroups; i++) {
+ for (i = 0; i < map->nGroups; i++) {
for (ch = map->groups[i].startCharCode;
ch <= map->groups[i].endCharCode; ch++) {
unsigned char *p;
@@ -1097,7 +1059,7 @@ create_ToUnicode_cmap12 (struct cmap12 *map,
p = wbuf + 2;
d = ch - map->groups[i].startCharCode;
gid = (USHORT) ((map->groups[i].startGlyphID + d) & 0xffff);
- if (is_used_char2(used_glyphs_copy, gid)) {
+ if (is_used_char2(used_glyphs, gid)) {
unsigned int cid = cffont ? cff_charsets_lookup_inverse(cffont, gid) : gid;
count++;
wbuf[0] = (cid >> 8) & 0xff;
@@ -1111,18 +1073,86 @@ create_ToUnicode_cmap12 (struct cmap12 *map,
* 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_glyphs_copy[gid/8] &= ~(1 << (7 - (gid % 8)));
+ if (!is_PUA_or_presentation(ch)) {
+ /* Avoid duplicate entry
+ * There are problem when two Unicode code is mapped to
+ * single glyph...
+ */
+ used_glyphs[gid/8] &= ~(1 << (7 - (gid % 8)));
+ }
count++;
}
}
}
- count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy, sfont, cffont);
+ return count;
+}
+
+static pdf_obj *
+create_ToUnicode_cmap (tt_cmap *ttcmap,
+ const char *cmap_name,
+ CMap *cmap_add,
+ const char *used_glyphs,
+ sfnt *sfont,
+ CMap *cmap_loaded)
+{
+ pdf_obj *stream = NULL;
+ CMap *cmap;
+ USHORT i, gid, ch, count = 0;
+ char used_glyphs_copy[8192];
+ cff_font *cffont = prepare_CIDFont_from_sfnt(sfont);
+
+ 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);
+
+ if (cmap_loaded && cffont) {
+ for (i = 0; i < 8192; i++) {
+ int j;
+ long len, inbytesleft, outbytesleft;
+ const unsigned char *inbuf;
+ unsigned char *outbuf;
+
+ if (used_glyphs[i] == 0)
+ continue;
+
+ for (j = 0; j < 8; j++) {
+ unsigned int cid;
+ int ch;
+ gid = 8 * i + j;
+
+ if (!is_used_char2(used_glyphs, gid))
+ continue;
+
+ cid = cff_charsets_lookup_inverse(cffont, gid);
+ ch = CMap_reverse_decode(cmap_loaded, cid);
+ if (ch >= 0) {
+ unsigned char *p = wbuf + 2;
+ wbuf[0] = (cid >> 8) & 0xff;
+ wbuf[1] = cid & 0xff;
+ len = UC_sput_UTF16BE((long)ch, &p, wbuf + WBUF_SIZE);
+ CMap_add_bfchar(cmap, wbuf, 2, wbuf + 2, len);
+ count++;
+ }
+ }
+ }
+ } else {
+ memcpy(used_glyphs_copy, used_glyphs, 8192);
+
+ switch (ttcmap->format) {
+ case 4:
+ count = create_ToUnicode_cmap4(cmap, ttcmap->map, used_glyphs_copy, cffont);
+ break;
+ case 12:
+ count = create_ToUnicode_cmap12(cmap, ttcmap->map, used_glyphs_copy, cffont);
+ break;
+ }
+
+ count += handle_subst_glyphs(cmap, cmap_add, used_glyphs_copy, sfont, cffont);
+ }
if (count < 1)
stream = NULL;
@@ -1152,13 +1182,14 @@ 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 */
- const char *used_glyphs)
+ int ttc_index, /* 0 for non-TTC */
+ const char *used_glyphs,
+ int cmap_id)
{
pdf_obj *cmap_ref = NULL;
long res_id;
pdf_obj *cmap_obj = NULL;
- CMap *cmap_add;
+ CMap *cmap_add, *cmap_loaded;
int cmap_add_id;
tt_cmap *ttcmap;
char *normalized_font_name;
@@ -1226,6 +1257,8 @@ otf_create_ToUnicode_stream (const char *font_name,
ERROR("Could not read OpenType/TrueType table directory.");
}
+ cmap_loaded = CMap_cache_get(cmap_id);
+
cmap_add_id = CMap_cache_find(cmap_name);
if (cmap_add_id < 0) {
cmap_add = NULL;
@@ -1238,14 +1271,10 @@ otf_create_ToUnicode_stream (const char *font_name,
ttcmap = tt_cmap_read(sfont, cmap_plat_encs[i].platform, cmap_plat_encs[i].encoding);
if (!ttcmap)
continue;
- if (ttcmap->format == 4) {
- cmap_obj = create_ToUnicode_cmap4(ttcmap->map,
- cmap_name, cmap_add, used_glyphs, sfont);
- break;
- }
- if (ttcmap->format == 12) {
- cmap_obj = create_ToUnicode_cmap12(ttcmap->map,
- cmap_name, cmap_add, used_glyphs, sfont);
+
+ if (ttcmap->format == 4 || ttcmap->format == 12) {
+ cmap_obj = create_ToUnicode_cmap(ttcmap, cmap_name, cmap_add, used_glyphs,
+ sfont, cmap_loaded);
break;
}
}