diff options
-rw-r--r-- | Jamfile | 43 | ||||
-rw-r--r-- | data/Dingbats.cff | bin | 0 -> 29492 bytes | |||
-rw-r--r-- | data/NimbusMonL-Bold.cff | bin | 0 -> 32860 bytes | |||
-rw-r--r-- | data/NimbusMonL-BoldObli.cff | bin | 0 -> 33584 bytes | |||
-rw-r--r-- | data/NimbusMonL-Regu.cff | bin | 0 -> 25616 bytes | |||
-rw-r--r-- | data/NimbusMonL-ReguObli.cff | bin | 0 -> 28416 bytes | |||
-rw-r--r-- | data/NimbusRomNo9L-Medi.cff | bin | 0 -> 24324 bytes | |||
-rw-r--r-- | data/NimbusRomNo9L-MediItal.cff | bin | 0 -> 27120 bytes | |||
-rw-r--r-- | data/NimbusRomNo9L-Regu.cff | bin | 0 -> 25264 bytes | |||
-rw-r--r-- | data/NimbusRomNo9L-ReguItal.cff | bin | 0 -> 27632 bytes | |||
-rw-r--r-- | data/NimbusSanL-Bold.cff | bin | 0 -> 17476 bytes | |||
-rw-r--r-- | data/NimbusSanL-BoldItal.cff | bin | 0 -> 19968 bytes | |||
-rw-r--r-- | data/NimbusSanL-Regu.cff | bin | 0 -> 16608 bytes | |||
-rw-r--r-- | data/NimbusSanL-ReguItal.cff | bin | 0 -> 20160 bytes | |||
-rw-r--r-- | data/StandardSymL.cff | bin | 0 -> 18944 bytes | |||
-rw-r--r-- | data/URWChanceryL-MediItal.cff | bin | 0 -> 34436 bytes | |||
-rw-r--r-- | mupdf/build.c | 2 | ||||
-rw-r--r-- | mupdf/font.c | 19 | ||||
-rw-r--r-- | mupdf/fontfile.c | 303 | ||||
-rw-r--r-- | mupdf/fontfilefc.c | 272 |
20 files changed, 474 insertions, 165 deletions
@@ -118,6 +118,46 @@ Library libmupdf : mupdf/interpret.c ; +rule HexDump { DEPENDS $(<) : $(>) ; } +actions HexDump +{ + xxd -i $(>) | sed -e 's/data_//g;s/, /,/g' > $(<) ; +} + +HexDump data/Dingbats.c : data/Dingbats.cff ; +HexDump data/NimbusMonL-Bold.c : data/NimbusMonL-Bold.cff ; +HexDump data/NimbusMonL-BoldObli.c : data/NimbusMonL-BoldObli.cff ; +HexDump data/NimbusMonL-Regu.c : data/NimbusMonL-Regu.cff ; +HexDump data/NimbusMonL-ReguObli.c : data/NimbusMonL-ReguObli.cff ; +HexDump data/NimbusRomNo9L-Medi.c : data/NimbusRomNo9L-Medi.cff ; +HexDump data/NimbusRomNo9L-MediItal.c : data/NimbusRomNo9L-MediItal.cff ; +HexDump data/NimbusRomNo9L-Regu.c : data/NimbusRomNo9L-Regu.cff ; +HexDump data/NimbusRomNo9L-ReguItal.c : data/NimbusRomNo9L-ReguItal.cff ; +HexDump data/NimbusSanL-Bold.c : data/NimbusSanL-Bold.cff ; +HexDump data/NimbusSanL-BoldItal.c : data/NimbusSanL-BoldItal.cff ; +HexDump data/NimbusSanL-Regu.c : data/NimbusSanL-Regu.cff ; +HexDump data/NimbusSanL-ReguItal.c : data/NimbusSanL-ReguItal.cff ; +HexDump data/StandardSymL.c : data/StandardSymL.cff ; +HexDump data/URWChanceryL-MediItal.c : data/URWChanceryL-MediItal.cff ; + +Library libfonts : + data/Dingbats.c + data/NimbusMonL-Bold.c + data/NimbusMonL-BoldObli.c + data/NimbusMonL-Regu.c + data/NimbusMonL-ReguObli.c + data/NimbusRomNo9L-Medi.c + data/NimbusRomNo9L-MediItal.c + data/NimbusRomNo9L-Regu.c + data/NimbusRomNo9L-ReguItal.c + data/NimbusSanL-Bold.c + data/NimbusSanL-BoldItal.c + data/NimbusSanL-Regu.c + data/NimbusSanL-ReguItal.c + data/StandardSymL.c + data/URWChanceryL-MediItal.c + ; + LINKLIBS = -lfontconfig -lfreetype @@ -145,6 +185,5 @@ LinkLibraries pdfrip pdffunction x11pdf - : libmupdf libfitz ; - + : libmupdf libfonts libfitz ; diff --git a/data/Dingbats.cff b/data/Dingbats.cff Binary files differnew file mode 100644 index 00000000..ea81c873 --- /dev/null +++ b/data/Dingbats.cff diff --git a/data/NimbusMonL-Bold.cff b/data/NimbusMonL-Bold.cff Binary files differnew file mode 100644 index 00000000..64737cab --- /dev/null +++ b/data/NimbusMonL-Bold.cff diff --git a/data/NimbusMonL-BoldObli.cff b/data/NimbusMonL-BoldObli.cff Binary files differnew file mode 100644 index 00000000..29645992 --- /dev/null +++ b/data/NimbusMonL-BoldObli.cff diff --git a/data/NimbusMonL-Regu.cff b/data/NimbusMonL-Regu.cff Binary files differnew file mode 100644 index 00000000..f39a9ab9 --- /dev/null +++ b/data/NimbusMonL-Regu.cff diff --git a/data/NimbusMonL-ReguObli.cff b/data/NimbusMonL-ReguObli.cff Binary files differnew file mode 100644 index 00000000..1cf5f15d --- /dev/null +++ b/data/NimbusMonL-ReguObli.cff diff --git a/data/NimbusRomNo9L-Medi.cff b/data/NimbusRomNo9L-Medi.cff Binary files differnew file mode 100644 index 00000000..a1b3c184 --- /dev/null +++ b/data/NimbusRomNo9L-Medi.cff diff --git a/data/NimbusRomNo9L-MediItal.cff b/data/NimbusRomNo9L-MediItal.cff Binary files differnew file mode 100644 index 00000000..02f69d64 --- /dev/null +++ b/data/NimbusRomNo9L-MediItal.cff diff --git a/data/NimbusRomNo9L-Regu.cff b/data/NimbusRomNo9L-Regu.cff Binary files differnew file mode 100644 index 00000000..3ddca966 --- /dev/null +++ b/data/NimbusRomNo9L-Regu.cff diff --git a/data/NimbusRomNo9L-ReguItal.cff b/data/NimbusRomNo9L-ReguItal.cff Binary files differnew file mode 100644 index 00000000..05a430e1 --- /dev/null +++ b/data/NimbusRomNo9L-ReguItal.cff diff --git a/data/NimbusSanL-Bold.cff b/data/NimbusSanL-Bold.cff Binary files differnew file mode 100644 index 00000000..2784e4e3 --- /dev/null +++ b/data/NimbusSanL-Bold.cff diff --git a/data/NimbusSanL-BoldItal.cff b/data/NimbusSanL-BoldItal.cff Binary files differnew file mode 100644 index 00000000..6b4bdcb3 --- /dev/null +++ b/data/NimbusSanL-BoldItal.cff diff --git a/data/NimbusSanL-Regu.cff b/data/NimbusSanL-Regu.cff Binary files differnew file mode 100644 index 00000000..716df70a --- /dev/null +++ b/data/NimbusSanL-Regu.cff diff --git a/data/NimbusSanL-ReguItal.cff b/data/NimbusSanL-ReguItal.cff Binary files differnew file mode 100644 index 00000000..72c13d0e --- /dev/null +++ b/data/NimbusSanL-ReguItal.cff diff --git a/data/StandardSymL.cff b/data/StandardSymL.cff Binary files differnew file mode 100644 index 00000000..ab1f4b50 --- /dev/null +++ b/data/StandardSymL.cff diff --git a/data/URWChanceryL-MediItal.cff b/data/URWChanceryL-MediItal.cff Binary files differnew file mode 100644 index 00000000..faed6179 --- /dev/null +++ b/data/URWChanceryL-MediItal.cff diff --git a/mupdf/build.c b/mupdf/build.c index 7c52ccab..6a8f4fdf 100644 --- a/mupdf/build.c +++ b/mupdf/build.c @@ -432,7 +432,7 @@ showglyph(pdf_csi *csi, int cid) { v = fz_getvmtx((fz_font*)font, cid); tm.e -= v.x * gstate->size / 1000.0; - tm.f += v.y * gstate->size / 1000.0; + tm.f -= v.y * gstate->size / 1000.0; } trm = fz_concat(tsm, tm); diff --git a/mupdf/font.c b/mupdf/font.c index 1268624d..1ab2ea5f 100644 --- a/mupdf/font.c +++ b/mupdf/font.c @@ -324,18 +324,17 @@ printf("loading simple font %s\n", basefont); } } - if (!cmap) + if (cmap) { - error = fz_throw("freetype could not find any cmaps"); - goto cleanup; - } - - e = FT_Set_Charmap(face, cmap); - if (e) - { - error = fz_throw("freetype could not set cmap: 0x%x", e); - goto cleanup; + e = FT_Set_Charmap(face, cmap); + if (e) + { + error = fz_throw("freetype could not set cmap: 0x%x", e); + goto cleanup; + } } + else + fz_warn("freetype could not find any cmaps"); etable = fz_malloc(sizeof(unsigned short) * 256); if (!etable) diff --git a/mupdf/fontfile.c b/mupdf/fontfile.c index 481d609d..a7ea31d3 100644 --- a/mupdf/fontfile.c +++ b/mupdf/fontfile.c @@ -1,30 +1,28 @@ #include <fitz.h> #include <mupdf.h> -#ifdef WIN32 -#error Compile "fontfilems.c" instead -#endif +#include <mupdf/base14.h> #include <ft2build.h> #include FT_FREETYPE_H #include <fontconfig/fontconfig.h> static FT_Library ftlib = nil; -static FcConfig *fclib = nil; 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_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 }; -static char *basenames[14] = +static char *basenames[15] = { "Courier", "Courier-Bold", @@ -39,27 +37,41 @@ static char *basenames[14] = "Times-Italic", "Times-BoldItalic", "Symbol", - "ZapfDingbats" + "ZapfDingbats", + "Chancery" }; -static char *basepatterns[14] = +static struct { char *collection; char *serif; char *gothic; } cidfonts[5] = { - "Nimbus Mono L,Courier,Courier New:style=Regular,Roman", - "Nimbus Mono L,Courier,Courier New:style=Bold", - "Nimbus Mono L,Courier,Courier New:style=Oblique,Italic", - "Nimbus Mono L,Courier,Courier New:style=BoldOblique,BoldItalic", - "Nimbus Sans L,Helvetica,Arial:style=Regular,Roman", - "Nimbus Sans L,Helvetica,Arial:style=Bold", - "Nimbus Sans L,Helvetica,Arial:style=Oblique,Italic", - "Nimbus Sans L,Helvetica,Arial:style=BoldOblique,BoldItalic", - "Nimbus Roman No9 L,Times,Times New Roman:style=Regular,Roman", - "Nimbus Roman No9 L,Times,Times New Roman:style=Bold,Medium", - "Nimbus Roman No9 L,Times,Times New Roman:style=Italic,Regular Italic", - "Nimbus Roman No9 L,Times,Times New Roman:style=BoldItalic,Medium Italic", - "Standard Symbols L,Symbol", - "Zapf Dingbats,Dingbats" + { "Adobe-CNS1", "MOESung-Regular", "MOEKai-Regular" }, + { "Adobe-GB1", "GB1-Serif", "GB1-Gothic" }, + { "Adobe-Japan1", "WadaMin-Regular", "WadaMaruGo-Regular" }, + { "Adobe-Japan2", "WadaMin-RegularH", "WadaMaruGo-RegularH" }, + { "Adobe-Korea1", "Munhwa-Regular", "MunhwaGothic-Regular" }, }; +static void loadfontdata(int i, unsigned char **d, unsigned int *l) +{ + switch (i) + { + case 0: *d=NimbusMonL_Regu_cff;*l=NimbusMonL_Regu_cff_len;break; + case 1: *d=NimbusMonL_Bold_cff;*l=NimbusMonL_Bold_cff_len;break; + case 2: *d=NimbusMonL_ReguObli_cff;*l=NimbusMonL_ReguObli_cff_len;break; + case 3: *d=NimbusMonL_BoldObli_cff;*l=NimbusMonL_BoldObli_cff_len;break; + case 4: *d=NimbusSanL_Regu_cff;*l=NimbusSanL_Regu_cff_len;break; + case 5: *d=NimbusSanL_Bold_cff;*l=NimbusSanL_Bold_cff_len;break; + case 6: *d=NimbusSanL_ReguItal_cff;*l=NimbusSanL_ReguItal_cff_len;break; + case 7: *d=NimbusSanL_BoldItal_cff;*l=NimbusSanL_BoldItal_cff_len;break; + case 8: *d=NimbusRomNo9L_Regu_cff;*l=NimbusRomNo9L_Regu_cff_len;break; + case 9: *d=NimbusRomNo9L_Medi_cff;*l=NimbusRomNo9L_Medi_cff_len;break; + case 10: *d=NimbusRomNo9L_ReguItal_cff;*l=NimbusRomNo9L_ReguItal_cff_len;break; + case 11: *d=NimbusRomNo9L_MediItal_cff;*l=NimbusRomNo9L_MediItal_cff_len;break; + case 12: *d=StandardSymL_cff;*l=StandardSymL_cff_len;break; + case 13: *d=Dingbats_cff;*l=Dingbats_cff_len;break; + default: *d=URWChanceryL_MediItal_cff;*l=URWChanceryL_MediItal_cff_len;break; + } +} + static fz_error *initfontlibs(void) { int fterr; @@ -76,169 +88,156 @@ static fz_error *initfontlibs(void) if (maj == 2 && min == 1 && pat < 7) return fz_throw("freetype version too old: %d.%d.%d", maj, min, pat); - fclib = FcInitLoadConfigAndFonts(); - if (!fclib) - return fz_throw("fontconfig failed initialisation"); - return nil; } fz_error * -pdf_loadbuiltinfont(pdf_font *font, char *basefont) +pdf_loadbuiltinfont(pdf_font *font, char *fontname) { fz_error *error; - FcResult fcerr; - int fterr; - - FcPattern *searchpat; - FcPattern *matchpat; - FT_Face face; - char *pattern; - char *file; - int index; + unsigned char *data; + unsigned int len; + FT_Error e; int i; error = initfontlibs(); if (error) return error; - pattern = basefont; - for (i = 0; i < 14; i++) - if (!strcmp(basefont, basenames[i])) - pattern = basepatterns[i]; + for (i = 0; i < 15; i++) + if (!strcmp(fontname, basenames[i])) + goto found; - fcerr = FcResultMatch; - searchpat = FcNameParse(pattern); - FcDefaultSubstitute(searchpat); - FcConfigSubstitute(fclib, searchpat, FcMatchPattern); + return fz_throw("font not found: %s", fontname); - matchpat = FcFontMatch(fclib, searchpat, &fcerr); - if (fcerr != FcResultMatch) - return fz_throw("fontconfig could not find font %s", pattern); +found: + loadfontdata(i, &data, &len); - fcerr = FcPatternGetString(matchpat, FC_FILE, 0, (FcChar8**)&file); - if (fcerr != FcResultMatch) - return fz_throw("fontconfig could not find font %s", pattern); + e = FT_New_Memory_Face(ftlib, data, len, 0, (FT_Face*)&font->ftface); + if (e) + return fz_throw("freetype: could not load font: 0x%x", e); + + return nil; +} - index = 0; - fcerr = FcPatternGetInteger(matchpat, FC_INDEX, 0, &index); +static fz_error * +loadcidfont(pdf_font *font, char *filename) +{ + char path[1024]; + char *fontdir; + int e; -printf(" builtin font %s idx %d\n", file, index); +printf(" load system cid font '%s'\n", filename); - fterr = FT_New_Face(ftlib, file, index, &face); - if (fterr) - return fz_throw("freetype could not load font file '%s': 0x%x", file, fterr); + fontdir = getenv("FONTDIR"); + if (!fontdir) + return fz_throw("ioerror: FONTDIR environment not set"); - FcPatternDestroy(matchpat); - FcPatternDestroy(searchpat); + strlcpy(path, fontdir, sizeof path); + strlcat(path, "/", sizeof path); + strlcat(path, filename, sizeof path); + strlcat(path, ".cid.cff", sizeof path); - font->ftface = face; + e = FT_New_Face(ftlib, path, 0, (FT_Face*)&font->ftface); + if (e) + return fz_throw("freetype: could not load font: 0x%x", e); return nil; } fz_error * -pdf_loadsystemfont(pdf_font *font, char *basefont, char *collection) +pdf_loadsystemfont(pdf_font *font, char *fontname, char *collection) { fz_error *error; - FcResult fcerr; - int fterr; + char *name; + int i; - char fontname[200]; - FcPattern *searchpat; - FcPattern *matchpat; - FT_Face face; - char *style; - char *file; - int index; + int isbold = 0; + int isitalic = 0; + int isserif = 0; + int isscript = 0; + int isfixed = 0; error = initfontlibs(); if (error) return error; - /* parse windows-style font name descriptors Font,Style or Font-Style */ - strlcpy(fontname, basefont, sizeof fontname); - - style = strchr(fontname, ','); - if (style) { - *style++ = 0; - } - else { - style = strchr(fontname, '-'); - if (style) - *style++ = 0; - } + font->substitute = 1; + + if (strstr(fontname, "Bold")) + isbold = 1; + if (strstr(fontname, "Italic")) + isitalic = 1; + if (strstr(fontname, "Oblique")) + isitalic = 1; + + if (font->flags & FD_FIXED) + isfixed = 1; + if (font->flags & FD_SERIF) + isserif = 1; + if (font->flags & FD_ITALIC) + isitalic = 1; + if (font->flags & FD_SCRIPT) + isscript = 1; + if (font->flags & FD_FORCEBOLD) + isbold = 1; - searchpat = FcPatternCreate(); - if (!searchpat) - return fz_outofmem; - - error = fz_outofmem; - - /* pattern from name */ - if (!FcPatternAddString(searchpat, FC_FAMILY, fontname)) - goto cleanup; if (collection) - if (!FcPatternAddString(searchpat, FC_FAMILY, collection)) - goto cleanup; - if (style) - if (!FcPatternAddString(searchpat, FC_STYLE, style)) - goto cleanup; - if (!FcPatternAddBool(searchpat, FC_OUTLINE, 1)) - goto cleanup; - - /* additional pattern from fd flags */ - FcPatternAddString(searchpat, FC_FAMILY, font->flags & FD_SERIF ? "serif" : "sans-serif"); - FcPatternAddString(searchpat, FC_STYLE, font->flags & FD_ITALIC ? "Italic" : "Regular"); - -file = FcNameUnparse(searchpat); -printf(" system font pattern %s\n", file); -free(file); - - fcerr = FcResultMatch; - FcDefaultSubstitute(searchpat); - FcConfigSubstitute(fclib, searchpat, FcMatchPattern); - - matchpat = FcFontMatch(fclib, searchpat, &fcerr); - if (fcerr != FcResultMatch) - return fz_throw("fontconfig could not find font %s", basefont); - - fcerr = FcPatternGetString(matchpat, FC_FAMILY, 0, (FcChar8**)&file); - if (file && strcmp(fontname, file)) - font->substitute = 1; - - fcerr = FcPatternGetString(matchpat, FC_STYLE, 0, (FcChar8**)&file); - if (file && style && strcmp(style, file)) - font->substitute = 1; - -printf(" is a substituted font\n"); - - fcerr = FcPatternGetString(matchpat, FC_FILE, 0, (FcChar8**)&file); - if (fcerr != FcResultMatch) - return fz_throw("fontconfig could not find font %s", basefont); - - index = 0; - fcerr = FcPatternGetInteger(matchpat, FC_INDEX, 0, &index); - -printf(" system font file %s idx %d\n", file, index); - - fterr = FT_New_Face(ftlib, file, index, &face); - if (fterr) { - FcPatternDestroy(matchpat); - FcPatternDestroy(searchpat); - return fz_throw("freetype could not load font file '%s': 0x%x", file, fterr); + { +printf(" find cid font %s (%d)\n", collection, isserif); + for (i = 0; i < 5; i++) + { + if (!strcmp(collection, cidfonts[i].collection)) + { + if (isserif) + return loadcidfont(font, cidfonts[i].serif); + else + return loadcidfont(font, cidfonts[i].gothic); + } + } + fz_warn("unknown cid collection: %s", collection); } - FcPatternDestroy(matchpat); - FcPatternDestroy(searchpat); + 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"; + } + } - font->ftface = face; + else if (isserif) + { + if (isitalic) { + if (isbold) name = "Times-BoldItalic"; + else name = "Times-Italic"; + } + else { + if (isbold) name = "Times-Bold"; + else name = "Times-Roman"; + } + } - return nil; + else + { + if (isitalic) { + if (isbold) name = "Helvetica-BoldOblique"; + else name = "Helvetica-Oblique"; + } + else { + if (isbold) name = "Helvetica-Bold"; + else name = "Helvetica"; + } + } -cleanup: - FcPatternDestroy(searchpat); - return error; + return pdf_loadbuiltinfont(font, name); } fz_error * diff --git a/mupdf/fontfilefc.c b/mupdf/fontfilefc.c new file mode 100644 index 00000000..481d609d --- /dev/null +++ b/mupdf/fontfilefc.c @@ -0,0 +1,272 @@ +#include <fitz.h> +#include <mupdf.h> + +#ifdef WIN32 +#error Compile "fontfilems.c" instead +#endif + +#include <ft2build.h> +#include FT_FREETYPE_H +#include <fontconfig/fontconfig.h> + +static FT_Library ftlib = nil; +static FcConfig *fclib = nil; + +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, +}; + +static char *basenames[14] = +{ + "Courier", + "Courier-Bold", + "Courier-Oblique", + "Courier-BoldOblique", + "Helvetica", + "Helvetica-Bold", + "Helvetica-Oblique", + "Helvetica-BoldOblique", + "Times-Roman", + "Times-Bold", + "Times-Italic", + "Times-BoldItalic", + "Symbol", + "ZapfDingbats" +}; + +static char *basepatterns[14] = +{ + "Nimbus Mono L,Courier,Courier New:style=Regular,Roman", + "Nimbus Mono L,Courier,Courier New:style=Bold", + "Nimbus Mono L,Courier,Courier New:style=Oblique,Italic", + "Nimbus Mono L,Courier,Courier New:style=BoldOblique,BoldItalic", + "Nimbus Sans L,Helvetica,Arial:style=Regular,Roman", + "Nimbus Sans L,Helvetica,Arial:style=Bold", + "Nimbus Sans L,Helvetica,Arial:style=Oblique,Italic", + "Nimbus Sans L,Helvetica,Arial:style=BoldOblique,BoldItalic", + "Nimbus Roman No9 L,Times,Times New Roman:style=Regular,Roman", + "Nimbus Roman No9 L,Times,Times New Roman:style=Bold,Medium", + "Nimbus Roman No9 L,Times,Times New Roman:style=Italic,Regular Italic", + "Nimbus Roman No9 L,Times,Times New Roman:style=BoldItalic,Medium Italic", + "Standard Symbols L,Symbol", + "Zapf Dingbats,Dingbats" +}; + +static fz_error *initfontlibs(void) +{ + int fterr; + int maj, min, pat; + + if (ftlib) + return nil; + + fterr = FT_Init_FreeType(&ftlib); + if (fterr) + return fz_throw("freetype failed initialisation: 0x%x", fterr); + + FT_Library_Version(ftlib, &maj, &min, &pat); + if (maj == 2 && min == 1 && pat < 7) + return fz_throw("freetype version too old: %d.%d.%d", maj, min, pat); + + fclib = FcInitLoadConfigAndFonts(); + if (!fclib) + return fz_throw("fontconfig failed initialisation"); + + return nil; +} + +fz_error * +pdf_loadbuiltinfont(pdf_font *font, char *basefont) +{ + fz_error *error; + FcResult fcerr; + int fterr; + + FcPattern *searchpat; + FcPattern *matchpat; + FT_Face face; + char *pattern; + char *file; + int index; + int i; + + error = initfontlibs(); + if (error) + return error; + + pattern = basefont; + for (i = 0; i < 14; i++) + if (!strcmp(basefont, basenames[i])) + pattern = basepatterns[i]; + + fcerr = FcResultMatch; + searchpat = FcNameParse(pattern); + FcDefaultSubstitute(searchpat); + FcConfigSubstitute(fclib, searchpat, FcMatchPattern); + + matchpat = FcFontMatch(fclib, searchpat, &fcerr); + if (fcerr != FcResultMatch) + return fz_throw("fontconfig could not find font %s", pattern); + + fcerr = FcPatternGetString(matchpat, FC_FILE, 0, (FcChar8**)&file); + if (fcerr != FcResultMatch) + return fz_throw("fontconfig could not find font %s", pattern); + + index = 0; + fcerr = FcPatternGetInteger(matchpat, FC_INDEX, 0, &index); + +printf(" builtin font %s idx %d\n", file, index); + + fterr = FT_New_Face(ftlib, file, index, &face); + if (fterr) + return fz_throw("freetype could not load font file '%s': 0x%x", file, fterr); + + FcPatternDestroy(matchpat); + FcPatternDestroy(searchpat); + + font->ftface = face; + + return nil; +} + +fz_error * +pdf_loadsystemfont(pdf_font *font, char *basefont, char *collection) +{ + fz_error *error; + FcResult fcerr; + int fterr; + + char fontname[200]; + FcPattern *searchpat; + FcPattern *matchpat; + FT_Face face; + char *style; + char *file; + int index; + + error = initfontlibs(); + if (error) + return error; + + /* parse windows-style font name descriptors Font,Style or Font-Style */ + strlcpy(fontname, basefont, sizeof fontname); + + style = strchr(fontname, ','); + if (style) { + *style++ = 0; + } + else { + style = strchr(fontname, '-'); + if (style) + *style++ = 0; + } + + searchpat = FcPatternCreate(); + if (!searchpat) + return fz_outofmem; + + error = fz_outofmem; + + /* pattern from name */ + if (!FcPatternAddString(searchpat, FC_FAMILY, fontname)) + goto cleanup; + if (collection) + if (!FcPatternAddString(searchpat, FC_FAMILY, collection)) + goto cleanup; + if (style) + if (!FcPatternAddString(searchpat, FC_STYLE, style)) + goto cleanup; + if (!FcPatternAddBool(searchpat, FC_OUTLINE, 1)) + goto cleanup; + + /* additional pattern from fd flags */ + FcPatternAddString(searchpat, FC_FAMILY, font->flags & FD_SERIF ? "serif" : "sans-serif"); + FcPatternAddString(searchpat, FC_STYLE, font->flags & FD_ITALIC ? "Italic" : "Regular"); + +file = FcNameUnparse(searchpat); +printf(" system font pattern %s\n", file); +free(file); + + fcerr = FcResultMatch; + FcDefaultSubstitute(searchpat); + FcConfigSubstitute(fclib, searchpat, FcMatchPattern); + + matchpat = FcFontMatch(fclib, searchpat, &fcerr); + if (fcerr != FcResultMatch) + return fz_throw("fontconfig could not find font %s", basefont); + + fcerr = FcPatternGetString(matchpat, FC_FAMILY, 0, (FcChar8**)&file); + if (file && strcmp(fontname, file)) + font->substitute = 1; + + fcerr = FcPatternGetString(matchpat, FC_STYLE, 0, (FcChar8**)&file); + if (file && style && strcmp(style, file)) + font->substitute = 1; + +printf(" is a substituted font\n"); + + fcerr = FcPatternGetString(matchpat, FC_FILE, 0, (FcChar8**)&file); + if (fcerr != FcResultMatch) + return fz_throw("fontconfig could not find font %s", basefont); + + index = 0; + fcerr = FcPatternGetInteger(matchpat, FC_INDEX, 0, &index); + +printf(" system font file %s idx %d\n", file, index); + + fterr = FT_New_Face(ftlib, file, index, &face); + if (fterr) { + FcPatternDestroy(matchpat); + FcPatternDestroy(searchpat); + return fz_throw("freetype could not load font file '%s': 0x%x", file, fterr); + } + + FcPatternDestroy(matchpat); + FcPatternDestroy(searchpat); + + font->ftface = face; + + return nil; + +cleanup: + FcPatternDestroy(searchpat); + return error; +} + +fz_error * +pdf_loadembeddedfont(pdf_font *font, pdf_xref *xref, fz_obj *stmref) +{ + fz_error *error; + int fterr; + FT_Face face; + fz_buffer *buf; + + error = initfontlibs(); + if (error) + return error; + + error = pdf_loadstream(&buf, xref, fz_tonum(stmref), fz_togen(stmref)); + if (error) + return error; + + fterr = FT_New_Memory_Face(ftlib, buf->rp, buf->wp - buf->rp, 0, &face); + + if (fterr) { + fz_free(buf); + return fz_throw("freetype could not load embedded font: 0x%x", fterr); + } + + font->ftface = face; + font->fontdata = buf; + + return nil; +} + |