📄 pdf_fontfilems.c.svn-base
字号:
#include "fitz.h"#include "mupdf.h"/* we use built-in fonts in addition to those installed on windows because the metric for Times-Roman in windows fonts seems wrong and we end up with over-lapping text if this font is used. poppler doesn't have this problem even when using windows fonts so maybe there's a better fix. */#define USE_BUILTIN_FONTS 1#ifdef USE_BUILTIN_FONTS#include "mupdf/base14.h"#endif#include <windows.h>#include <ft2build.h>#include FT_FREETYPE_H#define SAFE_FZ_READ(file, buf, size)\ err = fz_read(&byteread, (file), (char*)(buf), (size)); \ if (err) goto cleanup; \ if (byteread != (size)) err = fz_throw("ioerror");\ if (err) goto cleanup;#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))#define PLATFORM_UNICODE 0#define PLATFORM_MACINTOSH 1#define PLATFORM_ISO 2#define PLATFORM_MICROSOFT 3#define UNI_ENC_UNI_1 0#define UNI_ENC_UNI_1_1 1#define UNI_ENC_ISO 2#define UNI_ENC_UNI_2_BMP 3#define UNI_ENC_UNI_2_FULL_REPERTOIRE 4#define MAC_ROMAN 0#define MAC_JAPANESE 1#define MAC_CHINESE_TRADITIONAL 2#define MAC_KOREAN 3#define MAC_CHINESE_SIMPLIFIED 25#define MS_ENC_SYMBOL 0#define MS_ENC_UNI_BMP 1#define MS_ENC_SHIFTJIS 2#define MS_ENC_PRC 3#define MS_ENC_BIG5 4#define MS_ENC_WANSUNG 5#define MS_ENC_JOHAB 6#define MS_ENC_UNI_FULL_REPETOIRE 10#define TTC_VERSION1 0x00010000#define TTC_VERSION2 0x00020000typedef struct pdf_fontmapMS_s pdf_fontmapMS;typedef struct pdf_fontlistMS_s pdf_fontlistMS;struct pdf_fontmapMS_s{ char fontface[128]; char fontpath[MAX_PATH+1]; int index;};struct pdf_fontlistMS_s{ pdf_fontmapMS *fontmap; int len; int cap;};typedef struct _tagTT_OFFSET_TABLE{ USHORT uMajorVersion; USHORT uMinorVersion; USHORT uNumOfTables; USHORT uSearchRange; USHORT uEntrySelector; USHORT uRangeShift;} TT_OFFSET_TABLE;typedef struct _tagTT_TABLE_DIRECTORY{ char szTag[4]; //table name ULONG uCheckSum; //Check sum ULONG uOffset; //Offset from beginning of file ULONG uLength; //length of the table in bytes} TT_TABLE_DIRECTORY;typedef struct _tagTT_NAME_TABLE_HEADER{ USHORT uFSelector; //format selector. Always 0 USHORT uNRCount; //Name Records count USHORT uStorageOffset; //Offset for strings storage, from start of the table} TT_NAME_TABLE_HEADER;typedef struct _tagTT_NAME_RECORD{ USHORT uPlatformID; USHORT uEncodingID; USHORT uLanguageID; USHORT uNameID; USHORT uStringLength; USHORT uStringOffset; //from start of storage area} TT_NAME_RECORD;typedef struct _tagFONT_COLLECTION{ char Tag[4]; ULONG Version; ULONG NumFonts;}FONT_COLLECTION;static char *basenames[13] ={ "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique", "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique", "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic", "Symbol",};static char *basepatterns[13] ={ "CourierNewPSMT", "CourierNewPS-BoldMT", "CourierNewPS-ItalicMT", "CourierNewPS-BoldItalicMT", "ArialMT", "Arial-BoldMT", "Arial-ItalicMT", "Arial-BoldItalicMT", "TimesNewRomanPSMT", "TimesNewRomanPS-BoldMT", "TimesNewRomanPS-ItalicMT", "TimesNewRomanPS-BoldItalicMT", "SymbolMT"};static pdf_fontlistMS fontlistMS ={ NULL, 0, 0,};struct pdf_fontmapMS_s defaultSubstitute;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};/* A little bit more sophisticated name matching so that e.g. "EurostileExtended" matches "EurostileExtended-Roman" */static intfontnamematches(const char *s1, const char *s2){ const char *rest; int c1, c2; while (*s1 && *s2) { c1 = tolower(*s1++); c2 = tolower(*s2++); if (c1 != c2) return 0; } if (!*s1 && !*s2) return 1; rest = s2; if (*s1) rest = s1; if (0 == stricmp(rest, "-roman")) return 1; return 0;}static intlookupcompare(const void *elem1, const void *elem2){ pdf_fontmapMS *val1 = (pdf_fontmapMS *)elem1; pdf_fontmapMS *val2 = (pdf_fontmapMS *)elem2; if (val1->fontface[0] == 0) return 1; if (val2->fontface[0] == 0) return -1; if (fontnamematches(val1->fontface, val2->fontface)) return 0; return stricmp(val1->fontface, val2->fontface);}static intsortcompare(const void *elem1, const void *elem2){ pdf_fontmapMS *val1 = (pdf_fontmapMS *)elem1; pdf_fontmapMS *val2 = (pdf_fontmapMS *)elem2; if (val1->fontface[0] == 0) return 1; if (val2->fontface[0] == 0) return -1; return stricmp(val1->fontface, val2->fontface);}static void *localbsearch (const void *key, const void *base, size_t num, size_t width, int (*compare)(const void *, const void *)){ char *lo = (char *)base; char *hi = (char *)base + (num - 1) * width; char *mid; unsigned int half; int result; while (lo <= hi) if (half = num / 2) { mid = lo + (num & 1 ? half : (half - 1)) * width; if (!(result = (*compare)(key,mid))) return(mid); else if (result < 0) { hi = mid - width; num = num & 1 ? half : half-1; } else { lo = mid + width; num = half; } } else if (num) return((*compare)(key,lo) ? 0 : lo); else break; return(0);}static voidremoveredundancy(pdf_fontlistMS *fl){ int i; int roffset = 0; int redundancy_count = 0; qsort(fl->fontmap, fl->len, sizeof(pdf_fontmapMS), sortcompare); for (i = 0; i < fl->len - 1; ++i) { if (strcmp(fl->fontmap[i].fontface,fl->fontmap[i+1].fontface) == 0) { fl->fontmap[i].fontface[0] = 0; ++redundancy_count; } } qsort(fl->fontmap, fl->len, sizeof(pdf_fontmapMS), sortcompare); fl->len -= redundancy_count;#if 0 for (i = 0; i < fl->len; ++i) fprintf(stdout,"%s , %s , %d\n",fl->fontmap[i].fontface, fl->fontmap[i].fontpath,fl->fontmap[i].index);#endif}static voidfinddefaultsubstitutes(pdf_fontlistMS *fl){ int i; for (i = 0; i < fl->len; ++i) { char *face = fl->fontmap[i].fontface;#if defined(_MSC_VER) && 0 OutputDebugStringA(face); OutputDebugStringA("\n");#endif if (0 == strcmp(face, "TimesNewRomanPSMT")) { defaultSubstitute = fl->fontmap[i]; } }}static fz_error *swapword(char* pbyte, int nLen){ int i; char tmp; int nMax; if (nLen % 2) return fz_throw("fonterror"); nMax = nLen / 2; for (i = 0; i < nLen; ++i) { tmp = pbyte[i*2]; pbyte[i*2] = pbyte[i*2+1]; pbyte[i*2+1] = tmp; } return 0;}/* pSouce and PDest can be same */static fz_error *decodeunicodeBMP(char* source, int sourcelen,char* dest, int destlen){ wchar_t tmp[1024*2]; int converted; memset(tmp,0,sizeof(tmp)); memcpy(tmp,source,sourcelen); swapword((char*)tmp,sourcelen); converted = WideCharToMultiByte(CP_ACP, 0, tmp, -1, dest, destlen, NULL, NULL); if (converted == 0) return fz_throw("fonterror"); return 0;}static fz_error *decodeunicodeplatform(char* source, int sourcelen,char* dest, int destlen, int enctype){ fz_error *err = nil; switch(enctype) { case UNI_ENC_UNI_1: case UNI_ENC_UNI_2_BMP: err = decodeunicodeBMP(source,sourcelen,dest,destlen); break; case UNI_ENC_UNI_2_FULL_REPERTOIRE: case UNI_ENC_UNI_1_1: case UNI_ENC_ISO: default: err = fz_throw("fonterror : unsupported encoding"); break; } return err;}static fz_error *decodemacintoshplatform(char* source, int sourcelen,char* dest, int destlen, int enctype){ fz_error *err = nil; switch(enctype) { case MAC_ROMAN: if (sourcelen + 1 > destlen) err = fz_throw("fonterror : short buf lenth"); else { memcpy(source,dest,sourcelen); dest[sourcelen] = 0; } break; default: err = fz_throw("fonterror : unsupported encoding"); break; } return err;}static fz_error *decodemicrosoftplatform(char* source, int sourcelen,char* dest, int destlen, int enctype){ fz_error *err = nil; switch(enctype) { case MS_ENC_SYMBOL: case MS_ENC_UNI_BMP: case MS_ENC_UNI_FULL_REPETOIRE: err = decodeunicodeBMP(source,sourcelen,dest,destlen); break; default: err = fz_throw("fonterror : unsupported encoding"); break; } return err;}static fz_error *growfontlist(pdf_fontlistMS *fl){ int newcap; pdf_fontmapMS *newitems; if (fl->cap == 0) newcap = 1024; else newcap = fl->cap * 2; newitems = fz_realloc(fl->fontmap, sizeof(pdf_fontmapMS) * newcap); if (!newitems) return fz_outofmem; memset(newitems + fl->cap, 0, sizeof(struct fz_keyval_s) * (newcap - fl->cap)); fl->fontmap = newitems; fl->cap = newcap; return fz_okay;}static fz_error *insertmapping(pdf_fontlistMS *fl, char *facename, char *path, int index){ fz_error *err; if (fl->len == fl->cap) { err = growfontlist(fl); if (err) return err; } if (fl->len >= fl->cap) return fz_throw("fonterror : fontlist overflow"); strlcpy(fl->fontmap[fl->len].fontface, facename, sizeof(fl->fontmap[0].fontface)); strlcpy(fl->fontmap[fl->len].fontpath, path, sizeof(fl->fontmap[0].fontpath)); fl->fontmap[fl->len].index = index; ++fl->len; return fz_okay;}static fz_error *parseTTF(fz_stream *file, int offset, int index, char *path){ fz_error *err = nil; int byteread; TT_OFFSET_TABLE ttOffsetTable; TT_TABLE_DIRECTORY tblDir; TT_NAME_TABLE_HEADER ttNTHeader; TT_NAME_RECORD ttRecord; char szTemp[4096]; int found; int i; fz_seek(file,offset,0); SAFE_FZ_READ(file, &ttOffsetTable, sizeof(TT_OFFSET_TABLE)); ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables); ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion); ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion); //check is this is a true type font and the version is 1.0 if (ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0) return fz_throw("fonterror : invalid font version"); found = 0; for (i = 0; i< ttOffsetTable.uNumOfTables; i++) { SAFE_FZ_READ(file,&tblDir,sizeof(TT_TABLE_DIRECTORY)); memcpy(szTemp, tblDir.szTag, 4); szTemp[4] = 0; if (stricmp(szTemp, "name") == 0) { found = 1; tblDir.uLength = SWAPLONG(tblDir.uLength); tblDir.uOffset = SWAPLONG(tblDir.uOffset); break; } else if (szTemp[0] == 0) { break; } } if (found) { fz_seek(file,tblDir.uOffset,0); SAFE_FZ_READ(file,&ttNTHeader,sizeof(TT_NAME_TABLE_HEADER)); ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount); ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset); offset = tblDir.uOffset + sizeof(TT_NAME_TABLE_HEADER); for (i = 0; i < ttNTHeader.uNRCount && err == nil; ++i) { fz_seek(file, offset + sizeof(TT_NAME_RECORD)*i, 0); SAFE_FZ_READ(file,&ttRecord,sizeof(TT_NAME_RECORD));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -