📄 pdf_font.c.svn-base
字号:
{ int j; /* TODO: this is horribly slow */ for (j = 0; j < 256; j++) { if (ebuffer[j][0] && !strcmp(s, ebuffer[j])) { etable[i] = j; break; } } } /* TODO: should this really be here? */ if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } } } fz_dropobj(encoding); } else { pdf_logfont("encode builtin\n"); for (i = 0; i < 256; i++) { etable[i] = ftcharindex(face, i); FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); if (ebuffer[i][0]) estrings[i] = ebuffer[i]; } } error = pdf_newidentitycmap(&font->encoding, 0, 1); if (error) goto cleanup; font->ncidtogid = 256; font->cidtogid = etable; error = pdf_loadtounicode(font, xref, estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; /* * Widths */ fz_setdefaulthmtx((fz_font*)font, font->missingwidth); widths = fz_dictgets(dict, "Widths"); if (widths) { int first, last; error = pdf_resolve(&widths, xref); if (error) goto cleanup; first = fz_toint(fz_dictgets(dict, "FirstChar")); last = fz_toint(fz_dictgets(dict, "LastChar")); if (first < 0 || last > 255 || first > last) first = last = 0; for (i = 0; i < last - first + 1; i++) { int wid = fz_toint(fz_arrayget(widths, i)); error = fz_addhmtx((fz_font*)font, i + first, i + first, wid); if (error) goto cleanup; } fz_dropobj(widths); } else { FT_Set_Char_Size(face, 1000, 1000, 72, 72); for (i = 0; i < 256; i++) { error = fz_addhmtx((fz_font*)font, i, i, ftwidth(font, i)); if (error) goto cleanup; } } error = fz_endhmtx((fz_font*)font); if (error) goto cleanup; pdf_logfont("}\n"); *fontp = font; return fz_okay;cleanup: fz_free(etable); if (widths) fz_dropobj(widths); fz_dropfont((fz_font*)font); return fz_rethrow(error, "cannot load simple font");}/* * CID Fonts */static fz_error *loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj *encoding, fz_obj *tounicode){ fz_error *error; fz_obj *widths = nil; fz_obj *descriptor; pdf_font *font; FT_Face face; fz_irect bbox; int kind; char collection[256]; char *basefont; int i, k; /* * Get font name and CID collection */ basefont = fz_toname(fz_dictgets(dict, "BaseFont")); { fz_obj *cidinfo; fz_obj *obj; char tmpstr[64]; int tmplen; cidinfo = fz_dictgets(dict, "CIDSystemInfo"); error = pdf_resolve(&cidinfo, xref); if (error) return fz_rethrow(error, "cannot find CIDSystemInfo"); obj = fz_dictgets(cidinfo, "Registry"); tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj)); memcpy(tmpstr, fz_tostrbuf(obj), tmplen); tmpstr[tmplen] = '\0'; strlcpy(collection, tmpstr, sizeof collection); strlcat(collection, "-", sizeof collection); obj = fz_dictgets(cidinfo, "Ordering"); tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj)); memcpy(tmpstr, fz_tostrbuf(obj), tmplen); tmpstr[tmplen] = '\0'; strlcat(collection, tmpstr, sizeof collection); fz_dropobj(cidinfo); } /* * Load font file */ font = pdf_newfont(basefont); if (!font) return fz_outofmem; pdf_logfont("load cid font (%d %d R) ptr=%p {\n", fz_tonum(ref), fz_togen(ref), font); pdf_logfont("basefont %s\n", basefont); pdf_logfont("collection %s\n", collection); descriptor = fz_dictgets(dict, "FontDescriptor"); if (descriptor) error = pdf_loadfontdescriptor(font, xref, descriptor, collection); else error = fz_throw("syntaxerror: missing font descriptor"); if (error) goto cleanup; face = font->ftface; kind = ftkind(face); bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM; bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM; bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM; bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM; pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); if (bbox.x0 == bbox.x1) fz_setfontbbox((fz_font*)font, -1000, -1000, 2000, 2000); else fz_setfontbbox((fz_font*)font, bbox.x0, bbox.y0, bbox.x1, bbox.y1); /* * Encoding */ if (fz_isname(encoding)) { pdf_logfont("encoding /%s\n", fz_toname(encoding)); if (!strcmp(fz_toname(encoding), "Identity-H")) error = pdf_newidentitycmap(&font->encoding, 0, 2); else if (!strcmp(fz_toname(encoding), "Identity-V")) error = pdf_newidentitycmap(&font->encoding, 1, 2); else error = pdf_loadsystemcmap(&font->encoding, fz_toname(encoding)); } else if (fz_isindirect(encoding)) { pdf_logfont("encoding %d %d R\n", fz_tonum(encoding), fz_togen(encoding)); error = pdf_loadembeddedcmap(&font->encoding, xref, encoding); } else { error = fz_throw("syntaxerror: font missing encoding"); } if (error) goto cleanup; fz_setfontwmode((fz_font*)font, pdf_getwmode(font->encoding)); pdf_logfont("wmode %d\n", pdf_getwmode(font->encoding)); if (kind == TRUETYPE) { fz_obj *cidtogidmap; cidtogidmap = fz_dictgets(dict, "CIDToGIDMap"); if (fz_isindirect(cidtogidmap)) { unsigned short *map; fz_buffer *buf; int len; pdf_logfont("cidtogidmap stream\n"); error = pdf_loadstream(&buf, xref, fz_tonum(cidtogidmap), fz_togen(cidtogidmap)); if (error) goto cleanup; len = (buf->wp - buf->rp) / 2; map = fz_malloc(len * sizeof(unsigned short)); if (!map) { fz_dropbuffer(buf); error = fz_outofmem; goto cleanup; } for (i = 0; i < len; i++) map[i] = (buf->rp[i * 2] << 8) + buf->rp[i * 2 + 1]; font->ncidtogid = len; font->cidtogid = map; fz_dropbuffer(buf); } /* if truetype font is external, cidtogidmap should not be identity */ /* so we map from cid to unicode and then map that through the (3 1) */ /* unicode cmap to get a glyph id */ else if (font->substitute) { int e; pdf_logfont("emulate ttf cidfont\n"); e = FT_Select_Charmap(face, ft_encoding_unicode); if (e) return fz_throw("fonterror: no unicode cmap when emulating CID font"); if (!strcmp(collection, "Adobe-CNS1")) error = pdf_loadsystemcmap(&font->tottfcmap, "Adobe-CNS1-UCS2"); else if (!strcmp(collection, "Adobe-GB1")) error = pdf_loadsystemcmap(&font->tottfcmap, "Adobe-GB1-UCS2"); else if (!strcmp(collection, "Adobe-Japan1")) error = pdf_loadsystemcmap(&font->tottfcmap, "Adobe-Japan1-UCS2"); else if (!strcmp(collection, "Adobe-Japan2")) error = pdf_loadsystemcmap(&font->tottfcmap, "Adobe-Japan2-UCS2"); else if (!strcmp(collection, "Adobe-Korea1")) error = pdf_loadsystemcmap(&font->tottfcmap, "Adobe-Korea1-UCS2"); else error = fz_okay; if (error) return fz_rethrow(error, "cannot load system cmap %s", collection); } } error = pdf_loadtounicode(font, xref, nil, collection, tounicode); if (error) goto cleanup; /* * Horizontal */ fz_setdefaulthmtx((fz_font*)font, fz_toint(fz_dictgets(dict, "DW"))); widths = fz_dictgets(dict, "W"); if (widths) { int c0, c1, w; fz_obj *obj; error = pdf_resolve(&widths, xref); if (error) goto cleanup; for (i = 0; i < fz_arraylen(widths); ) { c0 = fz_toint(fz_arrayget(widths, i)); obj = fz_arrayget(widths, i + 1); if (fz_isarray(obj)) { for (k = 0; k < fz_arraylen(obj); k++) { w = fz_toint(fz_arrayget(obj, k)); error = fz_addhmtx((fz_font*)font, c0 + k, c0 + k, w); if (error) goto cleanup; } i += 2; } else { c1 = fz_toint(obj); w = fz_toint(fz_arrayget(widths, i + 2)); error = fz_addhmtx((fz_font*)font, c0, c1, w); if (error) goto cleanup; i += 3; } } fz_dropobj(widths); } error = fz_endhmtx((fz_font*)font); if (error) goto cleanup; /* * Vertical */ if (pdf_getwmode(font->encoding) == 1) { fz_obj *obj; int dw2y = 880; int dw2w = -1000; obj = fz_dictgets(dict, "DW2"); if (obj) { dw2y = fz_toint(fz_arrayget(obj, 0)); dw2w = fz_toint(fz_arrayget(obj, 1)); } fz_setdefaultvmtx((fz_font*)font, dw2y, dw2w); widths = fz_dictgets(dict, "W2"); if (widths) { int c0, c1, w, x, y, k; error = pdf_resolve(&widths, xref); if (error) goto cleanup; for (i = 0; i < fz_arraylen(widths); ) { c0 = fz_toint(fz_arrayget(widths, i)); obj = fz_arrayget(widths, i + 1); if (fz_isarray(obj)) { for (k = 0; k < fz_arraylen(obj); k += 3) { w = fz_toint(fz_arrayget(obj, k + 0)); x = fz_toint(fz_arrayget(obj, k + 1)); y = fz_toint(fz_arrayget(obj, k + 2)); error = fz_addvmtx((fz_font*)font, c0 + k, c0 + k, x, y, w); if (error) goto cleanup; } i += 2; } else { c1 = fz_toint(obj); w = fz_toint(fz_arrayget(widths, i + 2)); x = fz_toint(fz_arrayget(widths, i + 3)); y = fz_toint(fz_arrayget(widths, i + 4)); error = fz_addvmtx((fz_font*)font, c0, c1, x, y, w); if (error) goto cleanup; i += 5; } } fz_dropobj(widths); } error = fz_endvmtx((fz_font*)font); if (error) goto cleanup; } pdf_logfont("}\n"); *fontp = font; return fz_okay;cleanup: if (widths) fz_dropobj(widths); fz_dropfont((fz_font*)font); return fz_rethrow(error, "cannot load cid font");}static fz_error *loadtype0(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref){ fz_error *error; fz_obj *dfonts; fz_obj *dfont; fz_obj *subtype; fz_obj *encoding; fz_obj *tounicode; dfonts = fz_dictgets(dict, "DescendantFonts"); error = pdf_resolve(&dfonts, xref); if (error) return fz_rethrow(error, "cannot find DescendantFonts"); dfont = fz_arrayget(dfonts, 0); error = pdf_resolve(&dfont, xref); if (error) { fz_dropobj(dfonts); return fz_rethrow(error, "cannot find descendant font"); } subtype = fz_dictgets(dfont, "Subtype"); encoding = fz_dictgets(dict, "Encoding"); tounicode = fz_dictgets(dict, "ToUnicode"); if (!strcmp(fz_toname(subtype), "CIDFontType0")) error = loadcidfont(fontp, xref, dfont, ref, encoding, tounicode); else if (!strcmp(fz_toname(subtype), "CIDFontType2")) error = loadcidfont(fontp, xref, dfont, ref, encoding, tounicode); else error = fz_throw("syntaxerror: unknown cid font type"); fz_dropobj(dfont); fz_dropobj(dfonts); if (error) return fz_rethrow(error, "cannot load descendant font"); return fz_okay;}/* * FontDescriptor */fz_error *pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, char *collection){ fz_error *error; fz_obj *obj1, *obj2, *obj3, *obj; fz_rect bbox; char *fontname; error = pdf_resolve(&desc, xref); if (error) return fz_rethrow(error, "cannot find font descriptor"); pdf_logfont("load fontdescriptor {\n"); obj = fz_dictgets(desc, "FontName"); if (error) return fz_rethrow(error, "cannot resolve FontName"); fontname = fz_toname(obj); pdf_logfont("fontname %s\n", fontname); font->flags = fz_toint(fz_dictgets(desc, "Flags")); font->italicangle = fz_toreal(fz_dictgets(desc, "ItalicAngle")); font->ascent = fz_toreal(fz_dictgets(desc, "Ascent")); font->descent = fz_toreal(fz_dictgets(desc, "Descent")); font->capheight = fz_toreal(fz_dictgets(desc, "CapHeight")); font->xheight = fz_toreal(fz_dictgets(desc, "XHeight")); font->missingwidth = fz_toreal(fz_dictgets(desc, "MissingWidth")); bbox = pdf_torect(fz_dictgets(desc, "FontBBox")); pdf_logfont("bbox [%g %g %g %g]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1); pdf_logfont("flags %d\n", font->flags); obj1 = fz_dictgets(desc, "FontFile"); obj2 = fz_dictgets(desc, "FontFile2"); obj3 = fz_dictgets(desc, "FontFile3"); obj = obj1 ? obj1 : obj2 ? obj2 : obj3; if (getenv("NOFONT")) obj = nil; if (fz_isindirect(obj)) { error = pdf_loadembeddedfont(font, xref, obj); if (error) goto cleanup; } else { error = pdf_loadsystemfont(font, fontname, collection); if (error) goto cleanup; } fz_dropobj(desc); pdf_logfont("}\n"); return fz_okay;cleanup: fz_dropobj(desc); return fz_rethrow(error, "cannot load font descriptor");}fz_error *pdf_loadfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref){ fz_error *error; char *subtype; if ((*fontp = pdf_finditem(xref->store, PDF_KFONT, ref))) { fz_keepfont((fz_font*)*fontp); return fz_okay; } subtype = fz_toname(fz_dictgets(dict, "Subtype")); if (!strcmp(subtype, "Type0")) error = loadtype0(fontp, xref, dict, ref); else if (!strcmp(subtype, "Type1") || !strcmp(subtype, "MMType1")) error = loadsimplefont(fontp, xref, dict, ref); else if (!strcmp(subtype, "TrueType")) error = loadsimplefont(fontp, xref, dict, ref); else if (!strcmp(subtype, "Type3")) error = pdf_loadtype3font(fontp, xref, dict, ref); else return fz_throw("cannot recognize font format %s", subtype); if (error) return fz_rethrow(error, "cannot load font"); error = pdf_storeitem(xref->store, PDF_KFONT, ref, *fontp); if (error) return fz_rethrow(error, "cannot store font resource"); return fz_okay;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -