reactos/rosapps/smartpdf/fitz/mupdf/pdf_fontfile.c
Klemens Friedl 435a566751 SmartPDF - lightweight pdf viewer app for rosapps
* sumatrapdf - vendor import
* everything compiles (libjpeg, poppler, fitz, sumatrapdf)
* does NOT link

(remove the comment tags in the parent directory.rbuild file (rosapps dir) to build it)

svn path=/trunk/; revision=29295
2007-09-29 08:39:35 +00:00

421 lines
8.7 KiB
C

#include <fitz.h>
#include <mupdf.h>
#include <mupdf/base14.h>
#include <ft2build.h>
#include FT_FREETYPE_H
static FT_Library ftlib = nil;
#ifdef WIN32
#include <io.h>
static int path_exists(const char *path)
{
if (0 == _access(path, 04))
return 1;
return 0;
}
fz_error *initfontlibs_ms(void)
{
return nil;
}
void deinitfontlibs_ms(void)
{
if (!ftlib)
return;
FT_Done_FreeType(ftlib);
ftlib = nil;
}
#else
static int path_exists(const char *path)
{
if (access(path, R_OK) == 0)
return 1;
return 0;
}
#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
};
static const struct
{
const char *name;
const unsigned char *cff;
const unsigned int *len;
} basefonts[15] =
{
{ "Courier",
fonts_NimbusMonL_Regu_cff,
&fonts_NimbusMonL_Regu_cff_len },
{ "Courier-Bold",
fonts_NimbusMonL_Bold_cff,
&fonts_NimbusMonL_Bold_cff_len },
{ "Courier-Oblique",
fonts_NimbusMonL_ReguObli_cff,
&fonts_NimbusMonL_ReguObli_cff_len },
{ "Courier-BoldOblique",
fonts_NimbusMonL_BoldObli_cff,
&fonts_NimbusMonL_BoldObli_cff_len },
{ "Helvetica",
fonts_NimbusSanL_Regu_cff,
&fonts_NimbusSanL_Regu_cff_len },
{ "Helvetica-Bold",
fonts_NimbusSanL_Bold_cff,
&fonts_NimbusSanL_Bold_cff_len },
{ "Helvetica-Oblique",
fonts_NimbusSanL_ReguItal_cff,
&fonts_NimbusSanL_ReguItal_cff_len },
{ "Helvetica-BoldOblique",
fonts_NimbusSanL_BoldItal_cff,
&fonts_NimbusSanL_BoldItal_cff_len },
{ "Times-Roman",
fonts_NimbusRomNo9L_Regu_cff,
&fonts_NimbusRomNo9L_Regu_cff_len },
{ "Times-Bold",
fonts_NimbusRomNo9L_Medi_cff,
&fonts_NimbusRomNo9L_Medi_cff_len },
{ "Times-Italic",
fonts_NimbusRomNo9L_ReguItal_cff,
&fonts_NimbusRomNo9L_ReguItal_cff_len },
{ "Times-BoldItalic",
fonts_NimbusRomNo9L_MediItal_cff,
&fonts_NimbusRomNo9L_MediItal_cff_len },
{ "Symbol",
fonts_StandardSymL_cff,
&fonts_StandardSymL_cff_len },
{ "ZapfDingbats",
fonts_Dingbats_cff,
&fonts_Dingbats_cff_len },
{ "Chancery",
fonts_URWChanceryL_MediItal_cff,
&fonts_URWChanceryL_MediItal_cff_len }
};
enum { CNS, GB, Japan, Korea };
enum { MINCHO, GOTHIC };
struct subent { int csi; int kind; char *name; };
static const struct subent fontsubs[] =
{
{ CNS, MINCHO, "bkai00mp.ttf" },
{ CNS, GOTHIC, "bsmi00lp.ttf" },
{ CNS, MINCHO, "\345\204\267\345\256\213 Pro.ttf" }, /* LiSong Pro */
{ CNS, GOTHIC, "\345\204\267\351\273\221 Pro.ttf" }, /* LiHei Pro */
{ CNS, MINCHO, "simsun.ttc" },
{ CNS, GOTHIC, "simhei.ttf" },
{ GB, MINCHO, "gkai00mp.ttf" },
{ GB, GOTHIC, "gbsn00lp.ttf" },
{ GB, MINCHO, "\345\215\216\346\226\207\345\256\213\344\275\223.ttf" }, /* STSong */
{ GB, GOTHIC, "\345\215\216\346\226\207\346\245\267\344\275\223.ttf" }, /* STHeiti */
{ GB, MINCHO, "mingliu.ttc" },
{ GB, GOTHIC, "mingliu.ttc" },
{ Japan, MINCHO, "kochi-mincho.ttf" },
{ Japan, GOTHIC, "kochi-gothic.ttf" },
{ Japan, MINCHO, "\343\203\222\343\203\251\343\202\255\343\202\231\343\203\216\346\230\216\346\234\235 Pro W3.otf" },
{ Japan, GOTHIC, "\343\203\222\343\203\251\343\202\255\343\202\231\343\203\216\350\247\222\343\202\263\343\202\231 Pro W3.otf" },
{ Japan, MINCHO, "msmincho.ttc" },
{ Japan, GOTHIC, "msgothic.ttc" },
{ Korea, MINCHO, "batang.ttf" },
{ Korea, GOTHIC, "dotum.ttf" },
{ Korea, MINCHO, "AppleMyungjo.dfont" },
{ Korea, GOTHIC, "AppleGothic.dfont" },
{ Korea, MINCHO, "batang.ttc" },
{ Korea, GOTHIC, "dotum.ttc" },
};
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);
return nil;
}
fz_error *
pdf_loadbuiltinfont(pdf_font *font, char *fontname)
{
fz_error *error;
unsigned char *data;
unsigned int len;
FT_Error e;
int i;
error = initfontlibs();
if (error)
return error;
for (i = 0; i < 15; i++)
if (!strcmp(fontname, basefonts[i].name))
goto found;
return fz_throw("font not found: %s", fontname);
found:
pdf_logfont("load builtin font %s\n", fontname);
data = (unsigned char *) basefonts[i].cff;
len = *basefonts[i].len;
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;
}
static int
findcidfont(char *filename, char *path, int pathlen)
{
static const char *dirs[] =
{
"$/.fonts",
"$/Library/Fonts",
"/usr/X11R6/lib/X11/fonts/TTF",
"/usr/X11R6/lib/X11/fonts/TrueType",
"/usr/share/fonts/arphic",
"/usr/share/fonts/baekmuk",
"/usr/share/fonts/kochi",
"/System/Library/Fonts",
"/Library/Fonts",
nil
};
char **dirp;
char *home;
char *dir;
dir = getenv("FONTDIR");
if (dir)
{
strlcpy(path, dir, pathlen);
strlcat(path, "/", pathlen);
strlcat(path, filename, pathlen);
if (path_exists(path))
return 1;
}
dir = getenv("WINDIR");
if (dir)
{
strlcpy(path, dir, pathlen);
strlcat(path, "/Fonts/", pathlen);
strlcat(path, filename, pathlen);
if (path_exists(path))
return 1;
}
home = getenv("HOME");
if (!home)
home = "/";
for (dirp = (char**)dirs; *dirp; dirp++)
{
dir = *dirp;
if (dir[0] == '$')
{
strlcpy(path, home, pathlen);
strlcat(path, "/", pathlen);
strlcat(path, dir + 1, pathlen);
}
else
{
strlcpy(path, dir, pathlen);
}
strlcat(path, "/", pathlen);
strlcat(path, filename, pathlen);
if (path_exists(path))
return 1;
}
return 0;
}
static fz_error *
loadcidfont(pdf_font *font, int csi, int kind)
{
char path[1024];
int e;
int i;
for (i = 0; i < nelem(fontsubs); i++)
{
if (fontsubs[i].csi == csi && fontsubs[i].kind == kind)
{
if (findcidfont(fontsubs[i].name, path, sizeof path))
{
pdf_logfont("load system font '%s'\n", fontsubs[i].name);
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;
}
}
}
return fz_throw("could not find cid font file");
}
fz_error *
pdf_loadsystemfont(pdf_font *font, char *fontname, char *collection)
{
fz_error *error;
char *name;
int isbold = 0;
int isitalic = 0;
int isserif = 0;
int isscript = 0;
int isfixed = 0;
error = initfontlibs();
if (error)
return error;
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;
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 loadcidfont(font, CNS, kind);
else if (!strcmp(collection, "Adobe-GB1"))
return loadcidfont(font, GB, kind);
else if (!strcmp(collection, "Adobe-Japan1"))
return loadcidfont(font, Japan, kind);
else if (!strcmp(collection, "Adobe-Japan2"))
return loadcidfont(font, Japan, kind);
else if (!strcmp(collection, "Adobe-Korea1"))
return loadcidfont(font, 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";
}
}
return pdf_loadbuiltinfont(font, name);
}
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;
pdf_logfont("load embedded font\n");
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;
}