+ int l;
+ if(!filename)
+ return;
+ msg("<verbose> Removing temporary font file %s", filename);
+ l=strlen(filename);
+ unlink(filename);
+ if(!strncmp(&filename[l-4],".afm",4)) {
+ memcpy(&filename[l-4],".pfb",4); unlink(filename);
+ memcpy(&filename[l-4],".pfa",4); unlink(filename);
+ memcpy(&filename[l-4],".afm",4);
+ return;
+ } else
+ if(!strncmp(&filename[l-4],".pfa",4)) {
+ memcpy(&filename[l-4],".afm",4); unlink(filename);
+ memcpy(&filename[l-4],".pfa",4);
+ return;
+ } else
+ if(!strncmp(&filename[l-4],".pfb",4)) {
+ memcpy(&filename[l-4],".afm",4); unlink(filename);
+ memcpy(&filename[l-4],".pfb",4);
+ return;
+ }
+}
+
+static int config_use_fontconfig = 1;
+static int fcinitcalled = 0;
+
+GFXGlobalParams::GFXGlobalParams()
+: GlobalParams((char*)"")
+{
+ //setupBaseFonts(char *dir); //not tested yet
+}
+GFXGlobalParams::~GFXGlobalParams()
+{
+ msg("<verbose> Performing cleanups");
+ int t;
+ for(t=0;t<sizeof(pdf2t1map)/sizeof(fontentry);t++) {
+ if(pdf2t1map[t].fullfilename) {
+ unlinkfont(pdf2t1map[t].fullfilename);
+ }
+ }
+#ifdef HAVE_FONTCONFIG
+ if(config_use_fontconfig && fcinitcalled)
+ FcFini();
+#endif
+}
+#ifdef HAVE_FONTCONFIG
+static char stralphacmp(const char*s1, const char*s2)
+{
+ while(*s1 && *s2) {
+ /* skip over space, minus, comma etc. */
+ while(*s1>=32 && *s1<=63) s1++;
+ while(*s2>=32 && *s2<=63) s2++;
+ if(*s1!=*s2)
+ break;
+ s1++;s2++;
+ }
+ return *s1 - *s2;
+}
+
+static char fc_ismatch(FcPattern*match, char*family, char*style)
+{
+ char*fcfamily=0,*fcstyle=0,*fcfullname=0,*filename=0;
+ FcBool scalable=FcFalse, outline=FcFalse;
+ FcPatternGetString(match, "family", 0, (FcChar8**)&fcfamily);
+ FcPatternGetString(match, "style", 0, (FcChar8**)&fcstyle);
+ FcPatternGetString(match, "file", 0, (FcChar8**)&filename);
+ FcPatternGetBool(match, "outline", 0, &outline);
+ FcPatternGetBool(match, "scalable", 0, &scalable);
+
+ if(scalable!=FcTrue || outline!=FcTrue)
+ return 0;
+
+ if (!stralphacmp(fcfamily, family)) {
+ msg("<debug> Font %s-%s (%s) is a match for %s%s%s", fcfamily, fcstyle, filename, family, style?"-":"", style?style:"");
+ return 1;
+ } else {
+ //msg("<debug> Font %s-%s (%s) is NOT a match for %s%s%s", fcfamily, fcstyle, filename, family, style?"-":"", style?style:"");
+ return 0;
+ }
+}
+#endif
+
+char* fontconfig_searchForFont(char*name)
+{
+#ifdef HAVE_FONTCONFIG
+ if(!config_use_fontconfig)
+ return 0;
+
+ // call init ony once
+ if (!fcinitcalled) {
+ fcinitcalled = 1;
+
+ // check whether we have a config file
+ char* configfile = (char*)FcConfigFilename(0);
+ int configexists = 0;
+ FILE*fi = fopen(configfile, "rb");
+ if(fi) {
+ configexists = 1;fclose(fi);
+ msg("<debug> Initializing FontConfig (configfile=%s)", configfile);
+ } else {
+ msg("<debug> Initializing FontConfig (no configfile)");
+ }
+
+ if(!configexists) {
+ /* A fontconfig instance which didn't find a configfile is unbelievably
+ cranky, so let's just write out a small xml file and make fontconfig
+ happy */
+ FcConfig*c = FcConfigCreate();
+ char namebuf[512];
+ char* tmpFileName = mktmpname(namebuf);
+ FILE*fi = fopen(tmpFileName, "wb");
+ fprintf(fi, "<?xml version=\"1.0\"?>\n<fontconfig>\n");//<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+#ifdef WIN32
+ fprintf(fi, "<dir>WINDOWSFONTDIR</dir>\n");
+#endif
+ fprintf(fi, "<dir>~/.fonts</dir>\n");
+#ifdef WIN32
+ fprintf(fi, "<cachedir>WINDOWSTEMPDIR_FONTCONFIG_CACHE</cachedir>\n");
+#endif
+ fprintf(fi, "<cachedir>~/.fontconfig</cachedir>\n");
+ fprintf(fi, "</fontconfig>\n");
+ fclose(fi);
+ FcConfigParseAndLoad(c, (FcChar8*)tmpFileName, 1);
+ FcConfigBuildFonts(c);
+ FcConfigSetCurrent(c);
+ }
+
+ if(!FcInit()) {
+ msg("<debug> FontConfig Initialization failed. Disabling.");
+ config_use_fontconfig = 0;
+ return 0;
+ }
+ FcConfig * config = FcConfigGetCurrent();
+ if(!config) {
+ msg("<debug> FontConfig Config Initialization failed. Disabling.");
+ config_use_fontconfig = 0;
+ return 0;
+ }
+
+ /* add external fonts to fontconfig's config, too. */
+ fontfile_t*fd = global_fonts;
+ while(fd) {
+ FcConfigAppFontAddFile(config, (FcChar8*)fd->filename);
+ msg("<debug> Adding font %s to fontconfig", fd->filename);
+ fd = fd->next;
+ }
+
+ FcFontSet * set = FcConfigGetFonts(config, FcSetSystem);
+ msg("<verbose> FontConfig initialized. Found %d fonts", set?set->nfont:0);
+ if(!set || !set->nfont) {
+ msg("<debug> FontConfig has zero fonts. Disabling.");
+ config_use_fontconfig = 0;
+ return 0;
+ }
+
+ if(getLogLevel() >= LOGLEVEL_TRACE) {
+ int t;
+ int p;
+ for(p=0;p<2;p++) {
+ for(t=0;t<set->nfont;t++) {
+ char*fcfamily=0,*fcstyle=0,*filename=0;
+ FcBool scalable=FcFalse, outline=FcFalse;
+ FcPatternGetString(set->fonts[t], "family", 0, (FcChar8**)&fcfamily);
+ FcPatternGetString(set->fonts[t], "style", 0, (FcChar8**)&fcstyle);
+ FcPatternGetString(set->fonts[t], "file", 0, (FcChar8**)&filename);
+ FcPatternGetBool(set->fonts[t], "outline", 0, &outline);
+ FcPatternGetBool(set->fonts[t], "scalable", 0, &scalable);
+ if(scalable && outline) {
+ msg("<trace> %s (%s) -> %s", fcfamily, fcstyle, filename);
+ }
+ }
+ set = FcConfigGetFonts(config, FcSetApplication);
+ }
+ }
+ }
+
+ char*family = strdup(name);
+ char*style = 0;
+ char*dash = strchr(family, '-');
+ if(!dash) dash = strchr(family, ',');
+
+ FcPattern*pattern = 0;
+ if(dash) {
+ *dash = 0;
+ style = dash+1;
+ msg("<debug> FontConfig: Looking for font %s (family=%s style=%s)", name, family, style);
+ pattern = FcPatternBuild(NULL, FC_OUTLINE, FcTypeBool, FcTrue, FC_SCALABLE, FcTypeBool, FcTrue, FC_FAMILY, FcTypeString, family, FC_STYLE, FcTypeString, style, NULL);
+ } else {
+ msg("<debug> FontConfig: Looking for font %s (family=%s)", name, family);
+ pattern = FcPatternBuild(NULL, FC_OUTLINE, FcTypeBool, FcTrue, FC_SCALABLE, FcTypeBool, FcTrue, FC_FAMILY, FcTypeString, family, NULL);
+ }
+
+ FcResult result;
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ FcFontSet*set = FcFontSort(0, pattern, 1, 0, &result);
+ if(set) {
+ int t;
+ for(t=0;t<set->nfont;t++) {
+ FcPattern*match = set->fonts[t];
+ //FcPattern*match = FcFontMatch(0, pattern, &result);
+ if(fc_ismatch(match, family, style)) {
+ char*filename=0;
+ if(FcPatternGetString(match, "file", 0, (FcChar8**)&filename) != FcResultMatch) {
+ msg("<debug> FontConfig: Couldn't get fontconfig's filename for font %s", name);
+ filename=0;
+ }
+ //FcPatternDestroy(match);
+ msg("<debug> fontconfig: returning filename %s", filename);
+ free(family);
+ FcPatternDestroy(pattern);
+ FcFontSetDestroy(set);
+ return filename?strdup(filename):0;
+ }
+ }
+ }
+ free(family);
+ FcPatternDestroy(pattern);
+ FcFontSetDestroy(set);
+ return 0;
+#else
+ return 0;
+#endif
+}
+
+static DisplayFontParamKind detectFontType(const char*filename)
+{
+ if(strstr(filename, ".ttf") || strstr(filename, ".TTF"))
+ return displayFontTT;
+ if(strstr(filename, ".pfa") || strstr(filename, ".PFA") || strstr(filename, ".pfb"))
+ return displayFontT1;
+ return displayFontTT;
+}
+
+DisplayFontParam *GFXGlobalParams::getDisplayFont(GString *fontName)
+{
+ msg("<verbose> looking for font %s", fontName->getCString());
+
+ char*name = fontName->getCString();
+
+ /* see if it is a pdf standard font */
+ int t;
+ for(t=0;t<sizeof(pdf2t1map)/sizeof(fontentry);t++) {
+ if(!strcmp(name, pdf2t1map[t].pdffont)) {
+ if(!pdf2t1map[t].fullfilename) {
+ pdf2t1map[t].fullfilename = writeOutStdFont(&pdf2t1map[t]);
+ if(!pdf2t1map[t].fullfilename) {
+ msg("<error> Couldn't save default font- is the Temp Directory writable?");
+ } else {
+ msg("<verbose> Storing standard PDF font %s at %s", name, pdf2t1map[t].fullfilename);
+ }
+ }
+ DisplayFontParam *dfp = new DisplayFontParam(new GString(fontName), displayFontT1);
+ dfp->t1.fileName = new GString(pdf2t1map[t].fullfilename);
+ return dfp;
+ }
+ }
+
+ int bestlen = 0x7fffffff;
+ const char*bestfilename = 0;
+
+#ifndef HAVE_FONTCONFIG
+ /* if we don't have fontconfig, try a simple filename-comparison approach */
+ fontfile_t*f = global_fonts;
+ while(f) {
+ if(strstr(f->filename, name)) {
+ if(f->len < bestlen) {
+ bestlen = f->len;
+ bestfilename = f->filename;
+ }
+ }
+ f = f->next;
+ }
+#endif
+
+ /* if we didn't find anything up to now, try looking for the
+ font via fontconfig */
+ char*filename = 0;
+ if(!bestfilename) {
+ filename = fontconfig_searchForFont(name);
+ } else {
+ filename = strdup(bestfilename);
+ }
+
+ if(filename) {
+ msg("<verbose> Font %s maps to %s\n", name, filename);
+ DisplayFontParamKind kind = detectFontType(filename);
+ DisplayFontParam *dfp = new DisplayFontParam(new GString(fontName), kind);
+ if(kind == displayFontTT) {
+ dfp->tt.fileName = new GString(filename);
+ } else {
+ dfp->t1.fileName = new GString(filename);
+ }
+ free(filename);
+ return dfp;
+ } else {
+ msg("<verbose> Font %s not found\n", name);
+ return GlobalParams::getDisplayFont(fontName);
+ }
+}
+
+GFXOutputDev::GFXOutputDev(InfoOutputDev*info, PDFDoc*doc)
+{
+ if(!gfxglobals)
+ gfxglobals = new GFXOutputGlobals();
+
+ this->info = info;
+ this->doc = doc;
+ this->xref = doc->getXRef();
+