static void pdf_load_builtin_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname) { unsigned char *data; unsigned int len; #ifdef _WIN32 /* SumatraPDF: prefer system fonts unless a base font is explicitly requested */ char *clean_name = clean_font_name(fontname); if (!pdf_lookup_builtin_font(fontname, &len) && /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=2173 */ (clean_name == fontname || strncmp(clean_name, "Times-", 6) != 0)) { void pdf_load_windows_font(fz_context *ctx, pdf_font_desc *font, char *fontname); /* TODO: the metrics for Times-Roman and Courier don't match those of Windows' Times New Roman and Courier New; for some reason, Poppler doesn't seem to have this problem */ fz_try(ctx) { pdf_load_windows_font(ctx, fontdesc, fontname); } fz_catch(ctx) { } printf(" fontdesc->font=%p\n",fontdesc->font); if (fontdesc->font) return; }
static void pdf_load_builtin_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname, int has_descriptor) { FT_Face face; const char *clean_name = clean_font_name(fontname); fontdesc->font = fz_load_system_font(ctx, fontname, 0, 0, !has_descriptor); if (!fontdesc->font) { unsigned char *data; unsigned int len; data = pdf_lookup_builtin_font(clean_name, &len); if (!data) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find builtin font: '%s'", fontname); fontdesc->font = fz_new_font_from_memory(ctx, fontname, data, len, 0, 1); } if (!strcmp(clean_name, "Symbol") || !strcmp(clean_name, "ZapfDingbats")) fontdesc->flags |= PDF_FD_SYMBOLIC; face = fontdesc->font->ft_face; fontdesc->ascent = 1000.0f * face->ascender / face->units_per_EM; fontdesc->descent = 1000.0f * face->descender / face->units_per_EM; }
static void pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_document *doc, pdf_obj *dict, char *collection, char *basefont, int iscidfont, int has_encoding) { pdf_obj *obj1, *obj2, *obj3, *obj; char *fontname, *origname; FT_Face face; fz_context *ctx = doc->ctx; /* Prefer BaseFont; don't bother with FontName */ origname = basefont; /* SumatraPDF: handle /BaseFont /Arial,Bold+000041 /FontName /Arial,Bold */ if (strchr(basefont, '+') && pdf_is_name(pdf_dict_gets(dict, "FontName"))) origname = pdf_to_name(pdf_dict_gets(dict, "FontName")); /* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1616 */ if (strlen(origname) > 7 && origname[6] == '+') origname += 7; /* Look through list of alternate names for built in fonts */ fontname = clean_font_name(origname); fontdesc->flags = pdf_to_int(pdf_dict_gets(dict, "Flags")); fontdesc->italic_angle = pdf_to_real(pdf_dict_gets(dict, "ItalicAngle")); fontdesc->ascent = pdf_to_real(pdf_dict_gets(dict, "Ascent")); fontdesc->descent = pdf_to_real(pdf_dict_gets(dict, "Descent")); fontdesc->cap_height = pdf_to_real(pdf_dict_gets(dict, "CapHeight")); fontdesc->x_height = pdf_to_real(pdf_dict_gets(dict, "XHeight")); fontdesc->missing_width = pdf_to_real(pdf_dict_gets(dict, "MissingWidth")); obj1 = pdf_dict_gets(dict, "FontFile"); obj2 = pdf_dict_gets(dict, "FontFile2"); obj3 = pdf_dict_gets(dict, "FontFile3"); obj = obj1 ? obj1 : obj2 ? obj2 : obj3; if (pdf_is_indirect(obj)) { fz_try(ctx) { pdf_load_embedded_font(doc, fontdesc, fontname, obj); } fz_catch(ctx) { fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); fz_warn(ctx, "ignored error when loading embedded font; attempting to load system font"); if (origname != fontname && !iscidfont) pdf_load_builtin_font(ctx, fontdesc, fontname); else pdf_load_system_font(ctx, fontdesc, fontname, collection, has_encoding); } } else { if (origname != fontname && !iscidfont)
static void pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_document *xref, pdf_obj *dict, char *collection, char *basefont) { pdf_obj *obj1, *obj2, *obj3, *obj; char *fontname; char *origname; FT_Face face; fz_context *ctx = xref->ctx; if (!strchr(basefont, ',') || strchr(basefont, '+')) origname = pdf_to_name(pdf_dict_gets(dict, "FontName")); else origname = basefont; fontname = clean_font_name(origname); fontdesc->flags = pdf_to_int(pdf_dict_gets(dict, "Flags")); fontdesc->italic_angle = pdf_to_real(pdf_dict_gets(dict, "ItalicAngle")); fontdesc->ascent = pdf_to_real(pdf_dict_gets(dict, "Ascent")); fontdesc->descent = pdf_to_real(pdf_dict_gets(dict, "Descent")); fontdesc->cap_height = pdf_to_real(pdf_dict_gets(dict, "CapHeight")); fontdesc->x_height = pdf_to_real(pdf_dict_gets(dict, "XHeight")); fontdesc->missing_width = pdf_to_real(pdf_dict_gets(dict, "MissingWidth")); obj1 = pdf_dict_gets(dict, "FontFile"); obj2 = pdf_dict_gets(dict, "FontFile2"); obj3 = pdf_dict_gets(dict, "FontFile3"); obj = obj1 ? obj1 : obj2 ? obj2 : obj3; if (pdf_is_indirect(obj)) { fz_try(ctx) { pdf_load_embedded_font(fontdesc, xref, obj); } fz_catch(ctx) { fz_warn(ctx, "ignored error when loading embedded font; attempting to load system font"); if (origname != fontname) pdf_load_builtin_font(ctx, fontdesc, fontname); else pdf_load_system_font(ctx, fontdesc, fontname, collection); /* RJW: "cannot load font descriptor (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict) */ } } else { if (origname != fontname)
static void pdf_load_builtin_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname) { unsigned char *data; unsigned int len; fontname = clean_font_name(fontname); data = pdf_lookup_builtin_font(fontname, &len); if (!data) fz_throw(ctx, "cannot find builtin font: '%s'", fontname); fontdesc->font = fz_new_font_from_memory(ctx, fontname, data, len, 0, 1); if (!strcmp(fontname, "Symbol") || !strcmp(fontname, "ZapfDingbats")) fontdesc->flags |= PDF_FD_SYMBOLIC; }
static void pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_document *doc, pdf_obj *dict, char *collection, char *basefont, int iscidfont) { pdf_obj *obj1, *obj2, *obj3, *obj; char *fontname, *origname; FT_Face face; fz_context *ctx = doc->ctx; /* Prefer BaseFont; don't bother with FontName */ origname = basefont; /* Look through list of alternate names for built in fonts */ fontname = clean_font_name(origname); fontdesc->flags = pdf_to_int(pdf_dict_gets(dict, "Flags")); fontdesc->italic_angle = pdf_to_real(pdf_dict_gets(dict, "ItalicAngle")); fontdesc->ascent = pdf_to_real(pdf_dict_gets(dict, "Ascent")); fontdesc->descent = pdf_to_real(pdf_dict_gets(dict, "Descent")); fontdesc->cap_height = pdf_to_real(pdf_dict_gets(dict, "CapHeight")); fontdesc->x_height = pdf_to_real(pdf_dict_gets(dict, "XHeight")); fontdesc->missing_width = pdf_to_real(pdf_dict_gets(dict, "MissingWidth")); obj1 = pdf_dict_gets(dict, "FontFile"); obj2 = pdf_dict_gets(dict, "FontFile2"); obj3 = pdf_dict_gets(dict, "FontFile3"); obj = obj1 ? obj1 : obj2 ? obj2 : obj3; if (pdf_is_indirect(obj)) { fz_try(ctx) { pdf_load_embedded_font(doc, fontdesc, fontname, obj); } fz_catch(ctx) { fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); fz_warn(ctx, "ignored error when loading embedded font; attempting to load system font"); if (origname != fontname && !iscidfont) pdf_load_builtin_font(ctx, fontdesc, fontname); else pdf_load_system_font(ctx, fontdesc, fontname, collection); } } else { if (origname != fontname && !iscidfont)
{ void pdf_load_windows_font(fz_context *ctx, pdf_font_desc *font, char *fontname); /* TODO: the metrics for Times-Roman and Courier don't match those of Windows' Times New Roman and Courier New; for some reason, Poppler doesn't seem to have this problem */ fz_try(ctx) { pdf_load_windows_font(ctx, fontdesc, fontname); } fz_catch(ctx) { } printf(" fontdesc->font=%p\n",fontdesc->font); if (fontdesc->font) return; } #endif fontname = clean_font_name(fontname); data = pdf_lookup_builtin_font(fontname, &len); if (!data) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find builtin font: '%s'", fontname); fontdesc->font = fz_new_font_from_memory(ctx, fontname, data, len, 0, 1); if (!strcmp(fontname, "Symbol") || !strcmp(fontname, "ZapfDingbats")) fontdesc->flags |= PDF_FD_SYMBOLIC; } static void pdf_load_substitute_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname, int mono, int serif, int bold, int italic) { unsigned char *data;
static pdf_font_desc * pdf_load_simple_font(pdf_document *xref, pdf_obj *dict) { pdf_obj *descriptor; pdf_obj *encoding; pdf_obj *widths; unsigned short *etable = NULL; pdf_font_desc *fontdesc = NULL; FT_Face face; FT_CharMap cmap; int symbolic; int kind; char *basefont; char *fontname; char *estrings[256]; char ebuffer[256][32]; int i, k, n; int fterr; fz_context *ctx = xref->ctx; fz_var(fontdesc); fz_var(etable); basefont = pdf_to_name(pdf_dict_gets(dict, "BaseFont")); fontname = clean_font_name(basefont); /* Load font file */ fz_try(ctx) { fontdesc = pdf_new_font_desc(ctx); descriptor = pdf_dict_gets(dict, "FontDescriptor"); if (descriptor) pdf_load_font_descriptor(fontdesc, xref, descriptor, NULL, basefont); else pdf_load_builtin_font(ctx, fontdesc, fontname); /* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */ if (!*fontdesc->font->name && !pdf_dict_gets(dict, "ToUnicode") && !strcmp(pdf_to_name(pdf_dict_gets(dict, "Encoding")), "WinAnsiEncoding") && pdf_to_int(pdf_dict_gets(descriptor, "Flags")) == 4) { /* note: without the comma, pdf_load_font_descriptor would prefer /FontName over /BaseFont */ char *cp936fonts[] = { "\xCB\xCE\xCC\xE5", "SimSun,Regular", "\xBA\xDA\xCC\xE5", "SimHei,Regular", "\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular", "\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular", "\xC1\xA5\xCA\xE9", "SimLi,Regular", NULL }; for (i = 0; cp936fonts[i]; i += 2) if (!strcmp(basefont, cp936fonts[i])) break; if (cp936fonts[i]) { fz_warn(ctx, "workaround for S22PDF lying about chinese font encodings"); pdf_drop_font(ctx, fontdesc); fontdesc = pdf_new_font_desc(ctx); pdf_load_font_descriptor(fontdesc, xref, descriptor, "Adobe-GB1", cp936fonts[i+1]); fontdesc->encoding = pdf_load_system_cmap(ctx, "GBK-EUC-H"); fontdesc->to_unicode = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); /* RJW: "cannot load font" */ face = fontdesc->font->ft_face; kind = ft_kind(face); goto skip_encoding; } } face = fontdesc->font->ft_face; kind = ft_kind(face); /* Encoding */ symbolic = fontdesc->flags & 4; if (face->num_charmaps > 0) cmap = face->charmaps[0]; else cmap = NULL; for (i = 0; i < face->num_charmaps; i++) { FT_CharMap test = face->charmaps[i]; if (kind == TYPE1) { if (test->platform_id == 7) cmap = test; } if (kind == TRUETYPE) { if (test->platform_id == 1 && test->encoding_id == 0) cmap = test; if (test->platform_id == 3 && test->encoding_id == 1) cmap = test; } } if (cmap) { fterr = FT_Set_Charmap(face, cmap); if (fterr) fz_warn(ctx, "freetype could not set cmap: %s", ft_error_string(fterr)); } else fz_warn(ctx, "freetype could not find any cmaps"); etable = fz_malloc_array(ctx, 256, sizeof(unsigned short)); fontdesc->size += 256 * sizeof(unsigned short); for (i = 0; i < 256; i++) { estrings[i] = NULL; etable[i] = 0; } encoding = pdf_dict_gets(dict, "Encoding"); if (encoding) { if (pdf_is_name(encoding)) pdf_load_encoding(estrings, pdf_to_name(encoding)); if (pdf_is_dict(encoding)) { pdf_obj *base, *diff, *item; base = pdf_dict_gets(encoding, "BaseEncoding"); if (pdf_is_name(base)) pdf_load_encoding(estrings, pdf_to_name(base)); else if (!fontdesc->is_embedded && !symbolic) pdf_load_encoding(estrings, "StandardEncoding"); diff = pdf_dict_gets(encoding, "Differences"); if (pdf_is_array(diff)) { n = pdf_array_len(diff); k = 0; for (i = 0; i < n; i++) { item = pdf_array_get(diff, i); if (pdf_is_int(item)) k = pdf_to_int(item); if (pdf_is_name(item)) estrings[k++] = pdf_to_name(item); if (k < 0) k = 0; if (k > 255) k = 255; } } } } /* start with the builtin encoding */ for (i = 0; i < 256; i++) etable[i] = ft_char_index(face, i); /* encode by glyph name where we can */ fz_lock(ctx, FZ_LOCK_FREETYPE); if (kind == TYPE1) { for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) { int aglcode = pdf_lookup_agl(estrings[i]); const char **dupnames = pdf_lookup_agl_duplicates(aglcode); while (*dupnames) { etable[i] = FT_Get_Name_Index(face, (char*)*dupnames); if (etable[i]) break; dupnames++; } } } } } /* encode by glyph name where we can */ if (kind == TRUETYPE) { /* Unicode cmap */ if (!symbolic && face->charmap && face->charmap->platform_id == 3) { for (i = 0; i < 256; i++) { if (estrings[i]) { int aglcode = pdf_lookup_agl(estrings[i]); if (!aglcode) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ft_char_index(face, aglcode); } } } /* MacRoman cmap */ else if (!symbolic && face->charmap && face->charmap->platform_id == 1) { for (i = 0; i < 256; i++) { if (estrings[i]) { k = lookup_mre_code(estrings[i]); if (k <= 0) etable[i] = FT_Get_Name_Index(face, estrings[i]); else etable[i] = ft_char_index(face, k); } } } /* Symbolic cmap */ else { for (i = 0; i < 256; i++) { if (estrings[i]) { etable[i] = FT_Get_Name_Index(face, estrings[i]); if (etable[i] == 0) etable[i] = ft_char_index(face, i); } } } } /* try to reverse the glyph names from the builtin encoding */ for (i = 0; i < 256; i++) { if (etable[i] && !estrings[i]) { if (FT_HAS_GLYPH_NAMES(face)) { fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (fterr) fz_warn(ctx, "freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr)); if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } else { estrings[i] = (char*) pdf_win_ansi[i]; /* discard const */ } } } fz_unlock(ctx, FZ_LOCK_FREETYPE); fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1); fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding); fontdesc->cid_to_gid_len = 256; fontdesc->cid_to_gid = etable; pdf_load_to_unicode(xref, fontdesc, estrings, NULL, pdf_dict_gets(dict, "ToUnicode")); /* RJW: "cannot load to_unicode" */ skip_encoding: /* Widths */ pdf_set_default_hmtx(ctx, fontdesc, fontdesc->missing_width); widths = pdf_dict_gets(dict, "Widths"); if (widths) { int first, last; first = pdf_to_int(pdf_dict_gets(dict, "FirstChar")); last = pdf_to_int(pdf_dict_gets(dict, "LastChar")); if (first < 0 || last > 255 || first > last) first = last = 0; for (i = 0; i < last - first + 1; i++) { int wid = pdf_to_int(pdf_array_get(widths, i)); pdf_add_hmtx(ctx, fontdesc, i + first, i + first, wid); } } else { fz_lock(ctx, FZ_LOCK_FREETYPE); fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); if (fterr) fz_warn(ctx, "freetype set character size: %s", ft_error_string(fterr)); for (i = 0; i < 256; i++) { pdf_add_hmtx(ctx, fontdesc, i, i, ft_width(ctx, fontdesc, i)); } fz_unlock(ctx, FZ_LOCK_FREETYPE); } pdf_end_hmtx(ctx, fontdesc); } fz_catch(ctx) { if (fontdesc && etable != fontdesc->cid_to_gid) fz_free(ctx, etable); pdf_drop_font(ctx, fontdesc); fz_throw(ctx, "cannot load simple font (%d %d R)", pdf_to_num(dict), pdf_to_gen(dict)); } return fontdesc; }