/* * Create an Identity-* CMap (for both 1 and 2-byte encodings) */ fz_error pdf_newidentitycmap(pdf_cmap **cmapp, int wmode, int bytes) { fz_error error; pdf_cmap *cmap; error = pdf_newcmap(&cmap); if (error) return fz_rethrow(error, "cannot create cmap"); sprintf(cmap->cmapname, "Identity-%c", wmode ? 'V' : 'H'); error = pdf_addcodespace(cmap, 0x0000, 0xffff, bytes); if (error) { pdf_dropcmap(cmap); return fz_rethrow(error, "cannot add code space"); } error = pdf_maprangetorange(cmap, 0x0000, 0xffff, 0); if (error) { pdf_dropcmap(cmap); return fz_rethrow(error, "cannot map <0000> to <ffff>"); } error = pdf_sortcmap(cmap); if (error) { pdf_dropcmap(cmap); return fz_rethrow(error, "cannot sort cmap"); } pdf_setwmode(cmap, wmode); *cmapp = cmap; return fz_okay; }
/* * Create an Identity-* CMap (for both 1 and 2-byte encodings) */ pdf_cmap * pdf_newidentitycmap(int wmode, int bytes) { pdf_cmap *cmap = pdf_newcmap(); sprintf(cmap->cmapname, "Identity-%c", wmode ? 'V' : 'H'); pdf_addcodespace(cmap, 0x0000, 0xffff, bytes); pdf_maprangetorange(cmap, 0x0000, 0xffff, 0); pdf_sortcmap(cmap); pdf_setwmode(cmap, wmode); return cmap; }
static fz_error *new_kscms_uhc_h(pdf_cmap **out) { fz_error *error; pdf_cmap *cmap; error = pdf_newcmap(&cmap); if (error) return error; cmap->staticdata = 1; cmap->ranges = (pdf_range*)&g_cmap_kscms_uhc_h_ranges[0]; cmap->table = (int*)&g_cmap_kscms_uhc_h_table[0]; strcpy(cmap->cmapname, "KSCms-UHC-H"); strcpy(cmap->usecmapname, ""); cmap->wmode = 0; cmap->ncspace = 2; cmap->cspace[0].n = 1; cmap->cspace[0].lo[0] = 0; cmap->cspace[0].hi[0] = 128; cmap->cspace[0].lo[1] = 0; cmap->cspace[0].hi[1] = 0; cmap->cspace[0].lo[2] = 0; cmap->cspace[0].hi[2] = 0; cmap->cspace[0].lo[3] = 0; cmap->cspace[0].hi[3] = 0; cmap->cspace[1].n = 2; cmap->cspace[1].lo[0] = 129; cmap->cspace[1].hi[0] = 254; cmap->cspace[1].lo[1] = 65; cmap->cspace[1].hi[1] = 254; cmap->cspace[1].lo[2] = 0; cmap->cspace[1].hi[2] = 0; cmap->cspace[1].lo[3] = 0; cmap->cspace[1].hi[3] = 0; cmap->rlen = 601; cmap->rcap = 601; cmap->tlen = 113; cmap->tcap = 113; *out = cmap; return fz_okay; }
fz_error pdf_loadtounicode(pdf_fontdesc *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm) { fz_error error = fz_okay; pdf_cmap *cmap; int cid; int ucsbuf[8]; int ucslen; int i; if (pdf_isstream(xref, fz_tonum(cmapstm), fz_togen(cmapstm))) { pdf_logfont("tounicode embedded cmap\n"); error = pdf_loadembeddedcmap(&cmap, xref, cmapstm); if (error) return fz_rethrow(error, "cannot load embedded cmap (%d %d R)", fz_tonum(cmapstm), fz_togen(cmapstm)); font->tounicode = pdf_newcmap(); for (i = 0; i < (strings ? 256 : 65536); i++) { cid = pdf_lookupcmap(font->encoding, i); if (cid >= 0) { ucslen = pdf_lookupcmapfull(cmap, i, ucsbuf); if (ucslen == 1) pdf_maprangetorange(font->tounicode, cid, cid, ucsbuf[0]); if (ucslen > 1) pdf_maponetomany(font->tounicode, cid, ucsbuf, ucslen); } } pdf_sortcmap(font->tounicode); pdf_dropcmap(cmap); } else if (collection) { pdf_logfont("tounicode cid collection (%s)\n", collection); error = fz_okay; if (!strcmp(collection, "Adobe-CNS1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Japan2")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Japan2-UCS2"); /* where's this? */ else if (!strcmp(collection, "Adobe-Korea1")) error = pdf_loadsystemcmap(&font->tounicode, "Adobe-Korea1-UCS2"); if (error) return fz_rethrow(error, "cannot load tounicode system cmap %s-UCS2", collection); } if (strings) { pdf_logfont("tounicode strings\n"); /* TODO one-to-many mappings */ font->ncidtoucs = 256; font->cidtoucs = fz_calloc(256, sizeof(unsigned short)); for (i = 0; i < 256; i++) { if (strings[i]) font->cidtoucs[i] = pdf_lookupagl(strings[i]); else font->cidtoucs[i] = '?'; } } if (!font->tounicode && !font->cidtoucs) { pdf_logfont("tounicode could not be loaded\n"); /* TODO: synthesize a ToUnicode if it's a freetype font with * cmap and/or post tables or if it has glyph names. */ } return fz_okay; }
fz_error pdf_parsecmap(pdf_cmap **cmapp, fz_stream *file) { fz_error error; pdf_cmap *cmap; char key[64]; char buf[256]; pdf_token_e tok; int len; cmap = pdf_newcmap(); strcpy(key, ".notdef"); while (1) { error = lexcmap(&tok, file, buf, sizeof buf, &len); if (error) { /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=642 */ fz_warn("syntaxerror in cmap"); tok = PDF_TEOF; } if (tok == PDF_TEOF) break; else if (tok == PDF_TNAME) { if (!strcmp(buf, "CMapName")) { error = parsecmapname(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap after /CMapName"); goto cleanup; } } else if (!strcmp(buf, "WMode")) { error = parsewmode(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap after /WMode"); goto cleanup; } } else strlcpy(key, buf, sizeof key); } else if (tok == TUSECMAP) { strlcpy(cmap->usecmapname, key, sizeof(cmap->usecmapname)); } else if (tok == TBEGINCODESPACERANGE) { error = parsecodespacerange(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap codespacerange"); goto cleanup; } } else if (tok == TBEGINBFCHAR) { error = parsebfchar(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap bfchar"); goto cleanup; } } else if (tok == TBEGINCIDCHAR) { error = parsecidchar(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap cidchar"); goto cleanup; } } else if (tok == TBEGINBFRANGE) { error = parsebfrange(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap bfrange"); goto cleanup; } } else if (tok == TBEGINCIDRANGE) { error = parsecidrange(cmap, file); if (error) { error = fz_rethrow(error, "syntaxerror in cmap cidrange"); goto cleanup; } } /* ignore everything else */ } pdf_sortcmap(cmap); *cmapp = cmap; return fz_okay; cleanup: pdf_dropcmap(cmap); return error; /* already rethrown */ }