static void pdf_makewidthtable(pdf_fontdesc *fontdesc) { fz_font *font = fontdesc->font; int i, k, cid, gid; font->widthcount = 0; for (i = 0; i < fontdesc->nhmtx; i++) { for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++) { cid = pdf_lookupcmap(fontdesc->encoding, k); gid = pdf_fontcidtogid(fontdesc, cid); if (gid > font->widthcount) font->widthcount = gid; } } font->widthcount ++; font->widthtable = fz_malloc(sizeof(int) * font->widthcount); memset(font->widthtable, 0, sizeof(int) * font->widthcount); for (i = 0; i < fontdesc->nhmtx; i++) { for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++) { cid = pdf_lookupcmap(fontdesc->encoding, k); gid = pdf_fontcidtogid(fontdesc, cid); font->widthtable[gid] = fontdesc->hmtx[i].w; } } }
void pdf_showstring(pdf_csi *csi, unsigned char *buf, int len) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_fontdesc *fontdesc = gstate->font; unsigned char *end = buf + len; int cpt, cid; if (!fontdesc) { fz_warn("cannot draw text since font and size not set"); return; } while (buf < end) { buf = pdf_decodecmap(fontdesc->encoding, buf, &cpt); cid = pdf_lookupcmap(fontdesc->encoding, cpt); if (cid >= 0) pdf_showglyph(csi, cid); else fz_warn("cannot encode character with code point %#x", cpt); if (cpt == 32) pdf_showspace(csi, gstate->wordspace); } }
static inline int ftcidtogid(pdf_fontdesc *fontdesc, int cid) { if (fontdesc->tottfcmap) { cid = pdf_lookupcmap(fontdesc->tottfcmap, cid); return ftcharindex(fontdesc->font->ftface, cid); } if (fontdesc->cidtogid) return fontdesc->cidtogid[cid]; return cid; }
static inline int ftcidtogid(pdf_font *font, int cid) { if (font->tottfcmap) { cid = pdf_lookupcmap(font->tottfcmap, cid); return FT_Get_Char_Index(font->ftface, cid); } if (font->cidtogid) return font->cidtogid[cid]; return cid; }
fz_error * pdf_showtext(pdf_csi *csi, fz_obj *text) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_font *font = gstate->font; fz_error *error; unsigned char *buf; unsigned char *end; int i, len; int cpt, cid; if (fz_isarray(text)) { for (i = 0; i < fz_arraylen(text); i++) { fz_obj *item = fz_arrayget(text, i); if (fz_isstring(item)) { error = pdf_showtext(csi, item); if (error) return fz_rethrow(error, "cannot draw text item"); } else { showspace(csi, - fz_toreal(item) * gstate->size / 1000.0); } } return fz_okay; } buf = (unsigned char *)fz_tostrbuf(text); len = fz_tostrlen(text); end = buf + len; while (buf < end) { buf = pdf_decodecmap(font->encoding, buf, &cpt); cid = pdf_lookupcmap(font->encoding, cpt); if (cid == -1) cid = 0; error = showglyph(csi, cid); if (error) return fz_rethrow(error, "cannot draw glyph"); if (cpt == 32) showspace(csi, gstate->wordspace); } return fz_okay; }
void pdf_showtext(pdf_csi *csi, fz_obj *text) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_fontdesc *fontdesc = gstate->font; unsigned char *buf; unsigned char *end; int i, len; int cpt, cid; if (!fontdesc) { fz_warn("cannot draw text since font and size not set"); return; } if (fz_isarray(text)) { for (i = 0; i < fz_arraylen(text); i++) { fz_obj *item = fz_arrayget(text, i); if (fz_isstring(item)) pdf_showtext(csi, item); else pdf_showspace(csi, - fz_toreal(item) * gstate->size * 0.001f); } } if (fz_isstring(text)) { buf = (unsigned char *)fz_tostrbuf(text); len = fz_tostrlen(text); end = buf + len; while (buf < end) { buf = pdf_decodecmap(fontdesc->encoding, buf, &cpt); cid = pdf_lookupcmap(fontdesc->encoding, cpt); if (cid == -1) cid = 0; pdf_showglyph(csi, cid); if (cpt == 32) pdf_showspace(csi, gstate->wordspace); } } }
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; }