blob: f989fb89434f3184d4025a2243c145261a001616 [file] [log] [blame] [edit]
/* Written by Krzysztof Kowalczyk (http://blog.kowalczyk.info)
but mostly based on xpdf code.
// Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
TODO: instead of a fixed mapping defined in displayFontTab, it could
scan the whole fonts directory, parse TTF files and build font
description for all fonts available in Windows. That's how MuPDF works.
*/
#ifndef PACKAGE_NAME
#include <config.h>
#endif
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include <windows.h>
#if !(_WIN32_IE >= 0x0500)
#error "_WIN32_IE must be defined >= 0x0500 for SHGFP_TYPE_CURRENT from shlobj.h"
#endif
#include <shlobj.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include "goo/gmem.h"
#include "goo/GooString.h"
#include "goo/GooList.h"
#include "goo/GooHash.h"
#include "goo/gfile.h"
#include "Error.h"
#include "NameToCharCode.h"
#include "CharCodeToUnicode.h"
#include "UnicodeMap.h"
#include "CMap.h"
#include "BuiltinFontTables.h"
#include "FontEncodingTables.h"
#include "GlobalParams.h"
#include "GfxFont.h"
#if MULTITHREADED
# define lockGlobalParams gLockMutex(&mutex)
# define lockUnicodeMapCache gLockMutex(&unicodeMapCacheMutex)
# define lockCMapCache gLockMutex(&cMapCacheMutex)
# define unlockGlobalParams gUnlockMutex(&mutex)
# define unlockUnicodeMapCache gUnlockMutex(&unicodeMapCacheMutex)
# define unlockCMapCache gUnlockMutex(&cMapCacheMutex)
#else
# define lockGlobalParams
# define lockUnicodeMapCache
# define lockCMapCache
# define unlockGlobalParams
# define unlockUnicodeMapCache
# define unlockCMapCache
#endif
#define DEFAULT_SUBSTITUTE_FONT "Helvetica"
static struct {
char *name;
char *t1FileName;
char *ttFileName;
} displayFontTab[] = {
{"Courier", "n022003l.pfb", "cour.ttf"},
{"Courier-Bold", "n022004l.pfb", "courbd.ttf"},
{"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf"},
{"Courier-Oblique", "n022023l.pfb", "couri.ttf"},
{"Helvetica", "n019003l.pfb", "arial.ttf"},
{"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf"},
{"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf"},
{"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf"},
// TODO: not sure if "symbol.ttf" is right
{"Symbol", "s050000l.pfb", "symbol.ttf"},
{"Times-Bold", "n021004l.pfb", "timesbd.ttf"},
{"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf"},
{"Times-Italic", "n021023l.pfb", "timesi.ttf"},
{"Times-Roman", "n021003l.pfb", "times.ttf"},
// TODO: not sure if "wingding.ttf" is right
{"ZapfDingbats", "d050000l.pfb", "wingding.ttf"},
// those seem to be frequently accessed by PDF files and I kind of guess
// which font file do the refer to
{"Palatino", NULL, "pala.ttf"},
{"Palatino-Roman", NULL, "pala.ttf"},
{"Palatino-Bold", NULL, "palab.ttf"},
{"Palatino-Italic", NULL, "palai.ttf"},
{"Palatino,Italic", NULL, "palai.ttf"},
{"Palatino-BoldItalic", NULL, "palabi.ttf"},
{"ArialBlack", NULL, "arialbd.ttf"},
{"ArialNarrow", NULL, "arialn.ttf"},
{"ArialNarrow,Bold", NULL, "arialnb.ttf"},
{"ArialNarrow,Italic", NULL, "arialni.ttf"},
{"ArialNarrow,BoldItalic", NULL, "arialnbi.ttf"},
{"ArialNarrow-Bold", NULL, "arialnb.ttf"},
{"ArialNarrow-Italic", NULL, "arialni.ttf"},
{"ArialNarrow-BoldItalic", NULL, "arialnbi.ttf"},
{"HelveticaNarrow", NULL, "arialn.ttf"},
{"HelveticaNarrow,Bold", NULL, "arialnb.ttf"},
{"HelveticaNarrow,Italic", NULL, "arialni.ttf"},
{"HelveticaNarrow,BoldItalic", NULL, "arialnbi.ttf"},
{"HelveticaNarrow-Bold", NULL, "arialnb.ttf"},
{"HelveticaNarrow-Italic", NULL, "arialni.ttf"},
{"HelveticaNarrow-BoldItalic", NULL, "arialnbi.ttf"},
{"BookAntiqua", NULL, "bkant.ttf"},
{"BookAntiqua,Bold", NULL, "bkant.ttf"},
{"BookAntiqua,Italic", NULL, "bkant.ttf"},
{"BookAntiqua,BoldItalic", NULL, "bkant.ttf"},
{"BookAntiqua-Bold", NULL, "bkant.ttf"},
{"BookAntiqua-Italic", NULL, "bkant.ttf"},
{"BookAntiqua-BoldItalic", NULL, "bkant.ttf"},
{"Verdana", NULL, "verdana.ttf"},
{"Verdana,Bold", NULL, "verdanab.ttf"},
{"Verdana,Italic", NULL, "verdanai.ttf"},
{"Verdana,BoldItalic", NULL, "verdanaz.ttf"},
{"Verdana-Bold", NULL, "verdanab.ttf"},
{"Verdana-Italic", NULL, "verdanai.ttf"},
{"Verdana-BoldItalic", NULL, "verdanaz.ttf"},
{"Tahoma", NULL, "tahoma.ttf"},
{"Tahoma,Bold", NULL, "tahomabd.ttf"},
{"Tahoma,Italic", NULL, "tahoma.ttf"},
{"Tahoma,BoldItalic", NULL, "tahomabd.ttf"},
{"Tahoma-Bold", NULL, "tahomabd.ttf"},
{"Tahoma-Italic", NULL, "tahoma.ttf"},
{"Tahoma-BoldItalic", NULL, "tahomabd.ttf"},
{"CCRIKH+Verdana", NULL, "verdana.ttf"},
{"CCRIKH+Verdana,Bold", NULL, "verdanab.ttf"},
{"CCRIKH+Verdana,Italic", NULL, "verdanai.ttf"},
{"CCRIKH+Verdana,BoldItalic", NULL, "verdanaz.ttf"},
{"CCRIKH+Verdana-Bold", NULL, "verdanab.ttf"},
{"CCRIKH+Verdana-Italic", NULL, "verdanai.ttf"},
{"CCRIKH+Verdana-BoldItalic", NULL, "verdanaz.ttf"},
{"Georgia", NULL, "georgia.ttf"},
{"Georgia,Bold", NULL, "georgiab.ttf"},
{"Georgia,Italic", NULL, "georgiai.ttf"},
{"Georgia,BoldItalic", NULL, "georgiaz.ttf"},
{"Georgia-Bold", NULL, "georgiab.ttf"},
{"Georgia-Italic", NULL, "georgiai.ttf"},
{"Georgia-BoldItalic", NULL, "georgiaz.ttf"},
{NULL}
};
#define FONTS_SUBDIR "\\fonts"
static void GetWindowsFontDir(char *winFontDir, int cbWinFontDirLen)
{
BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner,
LPTSTR lpszPath,
int nFolder,
BOOL fCreate);
HRESULT (__stdcall *SHGetFolderPathFunc)(HWND hwndOwner,
int nFolder,
HANDLE hToken,
DWORD dwFlags,
LPTSTR pszPath);
// SHGetSpecialFolderPath isn't available in older versions of shell32.dll (Win95 and
// WinNT4), so do a dynamic load of ANSI versions.
winFontDir[0] = '\0';
HMODULE hLib = LoadLibrary("shell32.dll");
if (hLib) {
SHGetFolderPathFunc = (HRESULT (__stdcall *)(HWND, int, HANDLE, DWORD, LPTSTR))
GetProcAddress(hLib, "SHGetFolderPathA");
if (SHGetFolderPathFunc)
(*SHGetFolderPathFunc)(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, winFontDir);
if (!winFontDir[0]) {
// Try an older function
SHGetSpecialFolderPathFunc = (BOOL (__stdcall *)(HWND, LPTSTR, int, BOOL))
GetProcAddress(hLib, "SHGetSpecialFolderPathA");
if (SHGetSpecialFolderPathFunc)
(*SHGetSpecialFolderPathFunc)(NULL, winFontDir, CSIDL_FONTS, FALSE);
}
FreeLibrary(hLib);
}
if (winFontDir[0])
return;
// Try older DLL
hLib = LoadLibrary("SHFolder.dll");
if (hLib) {
SHGetFolderPathFunc = (HRESULT (__stdcall *)(HWND, int, HANDLE, DWORD, LPTSTR))
GetProcAddress(hLib, "SHGetFolderPathA");
if (SHGetFolderPathFunc)
(*SHGetFolderPathFunc)(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, winFontDir);
FreeLibrary(hLib);
}
if (winFontDir[0])
return;
// Everything else failed so the standard fonts directory.
GetWindowsDirectory(winFontDir, cbWinFontDirLen);
if (winFontDir[0]) {
strncat(winFontDir, FONTS_SUBDIR, cbWinFontDirLen);
winFontDir[cbWinFontDirLen-1] = 0;
}
}
static bool FileExists(const char *path)
{
FILE * f = fopen(path, "rb");
if (f) {
fclose(f);
return true;
}
return false;
}
static void AddFont(GooHash *displayFonts, char *fontName, GooString *fontPath, DisplayFontParamKind kind)
{
DisplayFontParam *dfp = new DisplayFontParam(new GooString(fontName), kind);
dfp->setFileName(fontPath);
displayFonts->add(dfp->name, dfp);
}
void GlobalParams::setupBaseFonts(char * dir)
{
if (baseFontsInitialized)
return;
baseFontsInitialized = true;
char winFontDir[MAX_PATH];
GetWindowsFontDir(winFontDir, sizeof(winFontDir));
for (int i = 0; displayFontTab[i].name; ++i) {
char *fontName = displayFontTab[i].name;
if (displayFonts->lookup(fontName))
continue;
if (dir) {
GooString *fontPath = appendToPath(new GooString(dir), displayFontTab[i].t1FileName);
if (FileExists(fontPath->getCString())) {
AddFont(displayFonts, fontName, fontPath, displayFontT1);
continue;
}
delete fontPath;
}
if (winFontDir[0] && displayFontTab[i].ttFileName) {
GooString *fontPath = appendToPath(new GooString(winFontDir), displayFontTab[i].ttFileName);
if (FileExists(fontPath->getCString())) {
AddFont(displayFonts, fontName, fontPath, displayFontTT);
continue;
}
delete fontPath;
}
error(-1, "No display font for '%s'", fontName);
}
}
static char *findSubstituteName(const char *origName)
{
assert(origName);
if (!origName) return NULL;
/* TODO: try to at least guess bold/italic/bolditalic from the name */
return DEFAULT_SUBSTITUTE_FONT;
}
/* Windows implementation of external font matching code */
DisplayFontParam *GlobalParams::getDisplayFont(GfxFont *font) {
DisplayFontParam * dfp;
GooString * fontName = font->getName();
char * substFontName = NULL;
if (!fontName) return NULL;
lockGlobalParams;
setupBaseFonts(NULL);
dfp = (DisplayFontParam *)displayFonts->lookup(fontName);
if (!dfp) {
substFontName = findSubstituteName(fontName->getCString());
error(-1, "Couldn't find a font for '%s', subst is '%s'", fontName->getCString(), substFontName);
dfp = (DisplayFontParam *)displayFonts->lookup(substFontName);
assert(dfp);
}
unlockGlobalParams;
return dfp;
}