summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jamfile43
-rw-r--r--data/Dingbats.cffbin0 -> 29492 bytes
-rw-r--r--data/NimbusMonL-Bold.cffbin0 -> 32860 bytes
-rw-r--r--data/NimbusMonL-BoldObli.cffbin0 -> 33584 bytes
-rw-r--r--data/NimbusMonL-Regu.cffbin0 -> 25616 bytes
-rw-r--r--data/NimbusMonL-ReguObli.cffbin0 -> 28416 bytes
-rw-r--r--data/NimbusRomNo9L-Medi.cffbin0 -> 24324 bytes
-rw-r--r--data/NimbusRomNo9L-MediItal.cffbin0 -> 27120 bytes
-rw-r--r--data/NimbusRomNo9L-Regu.cffbin0 -> 25264 bytes
-rw-r--r--data/NimbusRomNo9L-ReguItal.cffbin0 -> 27632 bytes
-rw-r--r--data/NimbusSanL-Bold.cffbin0 -> 17476 bytes
-rw-r--r--data/NimbusSanL-BoldItal.cffbin0 -> 19968 bytes
-rw-r--r--data/NimbusSanL-Regu.cffbin0 -> 16608 bytes
-rw-r--r--data/NimbusSanL-ReguItal.cffbin0 -> 20160 bytes
-rw-r--r--data/StandardSymL.cffbin0 -> 18944 bytes
-rw-r--r--data/URWChanceryL-MediItal.cffbin0 -> 34436 bytes
-rw-r--r--mupdf/build.c2
-rw-r--r--mupdf/font.c19
-rw-r--r--mupdf/fontfile.c303
-rw-r--r--mupdf/fontfilefc.c272
20 files changed, 474 insertions, 165 deletions
diff --git a/Jamfile b/Jamfile
index 2576ed77..eb4038e0 100644
--- a/Jamfile
+++ b/Jamfile
@@ -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
new file mode 100644
index 00000000..ea81c873
--- /dev/null
+++ b/data/Dingbats.cff
Binary files differ
diff --git a/data/NimbusMonL-Bold.cff b/data/NimbusMonL-Bold.cff
new file mode 100644
index 00000000..64737cab
--- /dev/null
+++ b/data/NimbusMonL-Bold.cff
Binary files differ
diff --git a/data/NimbusMonL-BoldObli.cff b/data/NimbusMonL-BoldObli.cff
new file mode 100644
index 00000000..29645992
--- /dev/null
+++ b/data/NimbusMonL-BoldObli.cff
Binary files differ
diff --git a/data/NimbusMonL-Regu.cff b/data/NimbusMonL-Regu.cff
new file mode 100644
index 00000000..f39a9ab9
--- /dev/null
+++ b/data/NimbusMonL-Regu.cff
Binary files differ
diff --git a/data/NimbusMonL-ReguObli.cff b/data/NimbusMonL-ReguObli.cff
new file mode 100644
index 00000000..1cf5f15d
--- /dev/null
+++ b/data/NimbusMonL-ReguObli.cff
Binary files differ
diff --git a/data/NimbusRomNo9L-Medi.cff b/data/NimbusRomNo9L-Medi.cff
new file mode 100644
index 00000000..a1b3c184
--- /dev/null
+++ b/data/NimbusRomNo9L-Medi.cff
Binary files differ
diff --git a/data/NimbusRomNo9L-MediItal.cff b/data/NimbusRomNo9L-MediItal.cff
new file mode 100644
index 00000000..02f69d64
--- /dev/null
+++ b/data/NimbusRomNo9L-MediItal.cff
Binary files differ
diff --git a/data/NimbusRomNo9L-Regu.cff b/data/NimbusRomNo9L-Regu.cff
new file mode 100644
index 00000000..3ddca966
--- /dev/null
+++ b/data/NimbusRomNo9L-Regu.cff
Binary files differ
diff --git a/data/NimbusRomNo9L-ReguItal.cff b/data/NimbusRomNo9L-ReguItal.cff
new file mode 100644
index 00000000..05a430e1
--- /dev/null
+++ b/data/NimbusRomNo9L-ReguItal.cff
Binary files differ
diff --git a/data/NimbusSanL-Bold.cff b/data/NimbusSanL-Bold.cff
new file mode 100644
index 00000000..2784e4e3
--- /dev/null
+++ b/data/NimbusSanL-Bold.cff
Binary files differ
diff --git a/data/NimbusSanL-BoldItal.cff b/data/NimbusSanL-BoldItal.cff
new file mode 100644
index 00000000..6b4bdcb3
--- /dev/null
+++ b/data/NimbusSanL-BoldItal.cff
Binary files differ
diff --git a/data/NimbusSanL-Regu.cff b/data/NimbusSanL-Regu.cff
new file mode 100644
index 00000000..716df70a
--- /dev/null
+++ b/data/NimbusSanL-Regu.cff
Binary files differ
diff --git a/data/NimbusSanL-ReguItal.cff b/data/NimbusSanL-ReguItal.cff
new file mode 100644
index 00000000..72c13d0e
--- /dev/null
+++ b/data/NimbusSanL-ReguItal.cff
Binary files differ
diff --git a/data/StandardSymL.cff b/data/StandardSymL.cff
new file mode 100644
index 00000000..ab1f4b50
--- /dev/null
+++ b/data/StandardSymL.cff
Binary files differ
diff --git a/data/URWChanceryL-MediItal.cff b/data/URWChanceryL-MediItal.cff
new file mode 100644
index 00000000..faed6179
--- /dev/null
+++ b/data/URWChanceryL-MediItal.cff
Binary files differ
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;
+}
+