diff options
Diffstat (limited to 'pdf/pdf_fontfile.c')
-rw-r--r-- | pdf/pdf_fontfile.c | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/pdf/pdf_fontfile.c b/pdf/pdf_fontfile.c new file mode 100644 index 00000000..c164033e --- /dev/null +++ b/pdf/pdf_fontfile.c @@ -0,0 +1,295 @@ +#include "fitz.h" +#include "mupdf.h" + +extern const unsigned char pdf_font_Dingbats_cff_buf[]; +extern const unsigned int pdf_font_Dingbats_cff_len; +extern const unsigned char pdf_font_NimbusMonL_Bold_cff_buf[]; +extern const unsigned int pdf_font_NimbusMonL_Bold_cff_len; +extern const unsigned char pdf_font_NimbusMonL_BoldObli_cff_buf[]; +extern const unsigned int pdf_font_NimbusMonL_BoldObli_cff_len; +extern const unsigned char pdf_font_NimbusMonL_Regu_cff_buf[]; +extern const unsigned int pdf_font_NimbusMonL_Regu_cff_len; +extern const unsigned char pdf_font_NimbusMonL_ReguObli_cff_buf[]; +extern const unsigned int pdf_font_NimbusMonL_ReguObli_cff_len; +extern const unsigned char pdf_font_NimbusRomNo9L_Medi_cff_buf[]; +extern const unsigned int pdf_font_NimbusRomNo9L_Medi_cff_len; +extern const unsigned char pdf_font_NimbusRomNo9L_MediItal_cff_buf[]; +extern const unsigned int pdf_font_NimbusRomNo9L_MediItal_cff_len; +extern const unsigned char pdf_font_NimbusRomNo9L_Regu_cff_buf[]; +extern const unsigned int pdf_font_NimbusRomNo9L_Regu_cff_len; +extern const unsigned char pdf_font_NimbusRomNo9L_ReguItal_cff_buf[]; +extern const unsigned int pdf_font_NimbusRomNo9L_ReguItal_cff_len; +extern const unsigned char pdf_font_NimbusSanL_Bold_cff_buf[]; +extern const unsigned int pdf_font_NimbusSanL_Bold_cff_len; +extern const unsigned char pdf_font_NimbusSanL_BoldItal_cff_buf[]; +extern const unsigned int pdf_font_NimbusSanL_BoldItal_cff_len; +extern const unsigned char pdf_font_NimbusSanL_Regu_cff_buf[]; +extern const unsigned int pdf_font_NimbusSanL_Regu_cff_len; +extern const unsigned char pdf_font_NimbusSanL_ReguItal_cff_buf[]; +extern const unsigned int pdf_font_NimbusSanL_ReguItal_cff_len; +extern const unsigned char pdf_font_StandardSymL_cff_buf[]; +extern const unsigned int pdf_font_StandardSymL_cff_len; +extern const unsigned char pdf_font_URWChanceryL_MediItal_cff_buf[]; +extern const unsigned int pdf_font_URWChanceryL_MediItal_cff_len; + +#ifndef NOCJK +extern const unsigned char pdf_font_DroidSansFallback_ttf_buf[]; +extern const unsigned int pdf_font_DroidSansFallback_ttf_len; +#endif + +enum +{ + FD_FIXED = 1 << 0, + FD_SERIF = 1 << 1, + FD_SYMBOLIC = 1 << 2, + FD_SCRIPT = 1 << 3, + FD_NONSYMBOLIC = 1 << 5, + FD_ITALIC = 1 << 6, + FD_ALLCAP = 1 << 16, + FD_SMALLCAP = 1 << 17, + FD_FORCEBOLD = 1 << 18 +}; + +enum { CNS, GB, Japan, Korea }; +enum { MINCHO, GOTHIC }; + +static const struct { + const char *name; + const unsigned char *cff; + const unsigned int *len; +} basefonts[] = { + { "Courier", + pdf_font_NimbusMonL_Regu_cff_buf, + &pdf_font_NimbusMonL_Regu_cff_len }, + { "Courier-Bold", + pdf_font_NimbusMonL_Bold_cff_buf, + &pdf_font_NimbusMonL_Bold_cff_len }, + { "Courier-Oblique", + pdf_font_NimbusMonL_ReguObli_cff_buf, + &pdf_font_NimbusMonL_ReguObli_cff_len }, + { "Courier-BoldOblique", + pdf_font_NimbusMonL_BoldObli_cff_buf, + &pdf_font_NimbusMonL_BoldObli_cff_len }, + { "Helvetica", + pdf_font_NimbusSanL_Regu_cff_buf, + &pdf_font_NimbusSanL_Regu_cff_len }, + { "Helvetica-Bold", + pdf_font_NimbusSanL_Bold_cff_buf, + &pdf_font_NimbusSanL_Bold_cff_len }, + { "Helvetica-Oblique", + pdf_font_NimbusSanL_ReguItal_cff_buf, + &pdf_font_NimbusSanL_ReguItal_cff_len }, + { "Helvetica-BoldOblique", + pdf_font_NimbusSanL_BoldItal_cff_buf, + &pdf_font_NimbusSanL_BoldItal_cff_len }, + { "Times-Roman", + pdf_font_NimbusRomNo9L_Regu_cff_buf, + &pdf_font_NimbusRomNo9L_Regu_cff_len }, + { "Times-Bold", + pdf_font_NimbusRomNo9L_Medi_cff_buf, + &pdf_font_NimbusRomNo9L_Medi_cff_len }, + { "Times-Italic", + pdf_font_NimbusRomNo9L_ReguItal_cff_buf, + &pdf_font_NimbusRomNo9L_ReguItal_cff_len }, + { "Times-BoldItalic", + pdf_font_NimbusRomNo9L_MediItal_cff_buf, + &pdf_font_NimbusRomNo9L_MediItal_cff_len }, + { "Symbol", + pdf_font_StandardSymL_cff_buf, + &pdf_font_StandardSymL_cff_len }, + { "ZapfDingbats", + pdf_font_Dingbats_cff_buf, + &pdf_font_Dingbats_cff_len }, + { "Chancery", + pdf_font_URWChanceryL_MediItal_cff_buf, + &pdf_font_URWChanceryL_MediItal_cff_len }, + { nil, nil, nil } +}; + +fz_error +pdf_loadbuiltinfont(pdf_fontdesc *fontdesc, char *fontname) +{ + fz_error error; + unsigned char *data; + unsigned int len; + int i; + + for (i = 0; basefonts[i].name; i++) + if (!strcmp(fontname, basefonts[i].name)) + goto found; + + return fz_throw("cannot find font: '%s'", fontname); + +found: + pdf_logfont("load builtin font %s\n", fontname); + + data = (unsigned char *) basefonts[i].cff; + len = *basefonts[i].len; + + error = fz_newfontfrombuffer(&fontdesc->font, data, len, 0); + if (error) + return fz_rethrow(error, "cannot load freetype font from buffer"); + + fz_strlcpy(fontdesc->font->name, fontname, sizeof fontdesc->font->name); + + if (!strcmp(fontname, "Symbol") || !strcmp(fontname, "ZapfDingbats")) + fontdesc->flags |= FD_SYMBOLIC; + + return fz_okay; +} + +static fz_error +loadsystemcidfont(pdf_fontdesc *fontdesc, int ros, int kind) +{ +#ifndef NOCJK + fz_error error; + /* + We only have one builtin fallback font. + We'd really like to have one for each combination of ROS and Kind. + */ + pdf_logfont("loading builtin CJK font\n"); + error = fz_newfontfrombuffer(&fontdesc->font, + (unsigned char *)pdf_font_DroidSansFallback_ttf_buf, + pdf_font_DroidSansFallback_ttf_len, 0); + if (error) + return fz_rethrow(error, "cannot load builtin CJK font"); + fontdesc->font->ftsubstitute = 1; /* substitute font */ + return fz_okay; +#else + return fz_throw("no builtin CJK font file"); +#endif +} + +fz_error +pdf_loadsystemfont(pdf_fontdesc *fontdesc, char *fontname, char *collection) +{ + fz_error error; + char *name; + + int isbold = 0; + int isitalic = 0; + int isserif = 0; + int isscript = 0; + int isfixed = 0; + + if (strstr(fontname, "Bold")) + isbold = 1; + if (strstr(fontname, "Italic")) + isitalic = 1; + if (strstr(fontname, "Oblique")) + isitalic = 1; + + if (fontdesc->flags & FD_FIXED) + isfixed = 1; + if (fontdesc->flags & FD_SERIF) + isserif = 1; + if (fontdesc->flags & FD_ITALIC) + isitalic = 1; + if (fontdesc->flags & FD_SCRIPT) + isscript = 1; + if (fontdesc->flags & FD_FORCEBOLD) + isbold = 1; + + pdf_logfont("fixed-%d serif-%d italic-%d script-%d bold-%d\n", + isfixed, isserif, isitalic, isscript, isbold); + + if (collection) + { + int kind; + + if (isserif) + kind = MINCHO; + else + kind = GOTHIC; + + if (!strcmp(collection, "Adobe-CNS1")) + return loadsystemcidfont(fontdesc, CNS, kind); + else if (!strcmp(collection, "Adobe-GB1")) + return loadsystemcidfont(fontdesc, GB, kind); + else if (!strcmp(collection, "Adobe-Japan1")) + return loadsystemcidfont(fontdesc, Japan, kind); + else if (!strcmp(collection, "Adobe-Japan2")) + return loadsystemcidfont(fontdesc, Japan, kind); + else if (!strcmp(collection, "Adobe-Korea1")) + return loadsystemcidfont(fontdesc, Korea, kind); + + fz_warn("unknown cid collection: %s", collection); + } + + if (isscript) + name = "Chancery"; + + else if (isfixed) + { + if (isitalic) { + if (isbold) name = "Courier-BoldOblique"; + else name = "Courier-Oblique"; + } + else { + if (isbold) name = "Courier-Bold"; + else name = "Courier"; + } + } + + else if (isserif) + { + if (isitalic) { + if (isbold) name = "Times-BoldItalic"; + else name = "Times-Italic"; + } + else { + if (isbold) name = "Times-Bold"; + else name = "Times-Roman"; + } + } + + else + { + if (isitalic) { + if (isbold) name = "Helvetica-BoldOblique"; + else name = "Helvetica-Oblique"; + } + else { + if (isbold) name = "Helvetica-Bold"; + else name = "Helvetica"; + } + } + + error = pdf_loadbuiltinfont(fontdesc, name); + if (error) + return fz_throw("cannot load builtin substitute font: %s", name); + + /* it's a substitute font: override the metrics */ + fontdesc->font->ftsubstitute = 1; + + return fz_okay; +} + +fz_error +pdf_loadembeddedfont(pdf_fontdesc *fontdesc, pdf_xref *xref, fz_obj *stmref) +{ + fz_error error; + fz_buffer *buf; + + pdf_logfont("load embedded font\n"); + + error = pdf_loadstream(&buf, xref, fz_tonum(stmref), fz_togen(stmref)); + if (error) + return fz_rethrow(error, "cannot load font stream (%d %d R)", fz_tonum(stmref), fz_togen(stmref)); + + error = fz_newfontfrombuffer(&fontdesc->font, buf->data, buf->len, 0); + if (error) + { + fz_dropbuffer(buf); + return fz_rethrow(error, "cannot load embedded font (%d %d R)", fz_tonum(stmref), fz_togen(stmref)); + } + + /* save the buffer so we can free it later */ + fontdesc->font->ftdata = buf->data; + fontdesc->font->ftsize = buf->len; + fz_free(buf); /* only free the fz_buffer struct, not the contained data */ + + fontdesc->isembedded = 1; + + return fz_okay; +} |