⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdf_font.c.svn-base

📁 SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多KB)
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
#include "fitz.h"#include "mupdf.h"#define noHINT#include <ft2build.h>#include FT_FREETYPE_H#include FT_XFREE86_Hstatic char *basefontnames[14][7] ={	{ "Courier", "CourierNew", "CourierNewPSMT", 0 },	{ "Courier-Bold", "CourierNew,Bold", "Courier,Bold",		"CourierNewPS-BoldMT", "CourierNew-Bold", 0 },	{ "Courier-Oblique", "CourierNew,Italic", "Courier,Italic",		"CourierNewPS-ItalicMT", "CourierNew-Italic", 0 },	{ "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic",		"CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", 0 },	{ "Helvetica", "ArialMT", "Arial", 0 },	{ "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold",		"Helvetica,Bold", 0 },	{ "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic",		"Helvetica,Italic", "Helvetica-Italic", 0 },	{ "Helvetica-BoldOblique", "Arial-BoldItalicMT",		"Arial,BoldItalic", "Arial-BoldItalic",		"Helvetica,BoldItalic", "Helvetica-BoldItalic", 0 },	{ "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman",		"TimesNewRomanPS", 0 },	{ "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold",		"TimesNewRomanPS-Bold", "TimesNewRoman-Bold", 0 },	{ "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic",		"TimesNewRomanPS-Italic", "TimesNewRoman-Italic", 0 },	{ "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT",		"TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic",		"TimesNewRoman-BoldItalic", 0 },	{ "Symbol", 0 },	{ "ZapfDingbats", 0 }};/* * FreeType and Rendering glue */enum { UNKNOWN, TYPE1, TRUETYPE, CID };#undef __FTERRORS_H__#define FT_ERRORDEF(e, v, s)	{ (e), (s) },#define FT_ERROR_START_LIST#define FT_ERROR_END_LIST	{ 0, NULL }struct ft_error{	int err;	char *str;};const struct ft_error ft_errors[] ={#include FT_ERRORS_H};char *ft_errstr(int err){	const struct ft_error *e;	for (e = ft_errors; e->str != NULL; e++)		if (e->err == err)			return e->str;	return "Unknown error";}static int ftkind(FT_Face face){	const char *kind = FT_Get_X11_Font_Format(face);	pdf_logfont("ft font format %s\n", kind);	if (!strcmp(kind, "TrueType"))		return TRUETYPE;	if (!strcmp(kind, "Type 1"))		return TYPE1;	if (!strcmp(kind, "CFF"))		return TYPE1;	if (!strcmp(kind, "CID Type 1"))		return TYPE1;	return UNKNOWN;}static int ftcharindex(FT_Face face, int cid){	int gid = FT_Get_Char_Index(face, cid);	if (gid == 0)		gid = FT_Get_Char_Index(face, 0xf000 + cid);	return gid;}static inline int ftcidtogid(pdf_font *font, int cid){	if (font->tottfcmap)	{		cid = pdf_lookupcmap(font->tottfcmap, cid);		return ftcharindex(font->ftface, cid);	}	if (font->cidtogid)		return font->cidtogid[cid];	return cid;}static int ftwidth(pdf_font *font, int cid){	int e;	cid = ftcidtogid(font, cid);	e = FT_Load_Glyph(font->ftface, cid,			FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);	if (e)		return 0;	return ((FT_Face)font->ftface)->glyph->advance.x;}static fz_error *ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm){	pdf_font *font = (pdf_font*)fzfont;	FT_Face face = font->ftface;	FT_Matrix m;	FT_Vector v;	FT_Error fterr;	float scale;	int gid;	int x, y;	int hint = font->hint;	gid = ftcidtogid(font, cid);	if (font->substitute && fzfont->wmode == 0)	{		fz_hmtx subw;		int realw;		FT_Set_Char_Size(face, 1000, 1000, 72, 72);		fterr = FT_Load_Glyph(font->ftface, gid,				FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);		if (fterr)			return fz_throw("freetype failed to load glyph: %s", ft_errstr(fterr));		realw = ((FT_Face)font->ftface)->glyph->advance.x;		subw = fz_gethmtx(fzfont, cid);		if (realw)			scale = (float) subw.w / realw;		else			scale = 1.0;		trm = fz_concat(fz_scale(scale, 1.0), trm);	}	glyph->w = 0;	glyph->h = 0;	glyph->x = 0;	glyph->y = 0;	glyph->samples = nil;	/* freetype mutilates complex glyphs if they are loaded	 * with FT_Set_Char_Size 1.0. it rounds the coordinates	 * before applying transformation. to get more precision in	 * freetype, we shift part of the scale in the matrix	 * into FT_Set_Char_Size instead	 */#ifdef HINT	hint = 1;#endif	if (hint)	{		scale = fz_matrixexpansion(trm);		m.xx = trm.a * 65536 / scale;		m.yx = trm.b * 65536 / scale;		m.xy = trm.c * 65536 / scale;		m.yy = trm.d * 65536 / scale;		v.x = 0;		v.y = 0;		FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72);		FT_Set_Transform(face, &m, &v);		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP);		if (fterr)			fz_warn("freetype load glyph: %s", ft_errstr(fterr));	}	else	{		m.xx = trm.a * 64;	/* should be 65536 */		m.yx = trm.b * 64;		m.xy = trm.c * 64;		m.yy = trm.d * 64;		v.x = trm.e * 64;		v.y = trm.f * 64;		FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */		FT_Set_Transform(face, &m, &v);		fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);		if (fterr)			fz_warn("freetype load glyph: %s", ft_errstr(fterr));	}	fterr = FT_Render_Glyph(face->glyph, ft_render_mode_normal);	if (fterr)		fz_warn("freetype render glyph: %s", ft_errstr(fterr));	glyph->w = face->glyph->bitmap.width;	glyph->h = face->glyph->bitmap.rows;	glyph->x = face->glyph->bitmap_left;	glyph->y = face->glyph->bitmap_top - glyph->h;	glyph->samples = face->glyph->bitmap.buffer;	for (y = 0; y < glyph->h / 2; y++)	{		for (x = 0; x < glyph->w; x++)		{			unsigned char a = glyph->samples[y * glyph->w + x ];			unsigned char b = glyph->samples[(glyph->h - y - 1) * glyph->w + x];			glyph->samples[y * glyph->w + x ] = b;			glyph->samples[(glyph->h - y - 1) * glyph->w + x] = a;		}	}	return fz_okay;}/* * Basic encoding tables */static char *cleanfontname(char *fontname){	int i, k;	for (i = 0; i < 14; i++)		for (k = 0; basefontnames[i][k]; k++)			if (!strcmp(basefontnames[i][k], fontname))				return basefontnames[i][0];	return fontname;}static int mrecode(char *name){	int i;	for (i = 0; i < 256; i++)		if (pdf_macroman[i] && !strcmp(name, pdf_macroman[i]))			return i;	return -1;}/* * Create and destroy */static void ftdropfont(fz_font *font){	pdf_font *pfont = (pdf_font*)font;	if (pfont->encoding)		pdf_dropcmap(pfont->encoding);	if (pfont->tottfcmap)		pdf_dropcmap(pfont->tottfcmap);	if (pfont->tounicode)		pdf_dropcmap(pfont->tounicode);	fz_free(pfont->cidtogid);	fz_free(pfont->cidtoucs);	if (pfont->ftface)		FT_Done_Face((FT_Face)pfont->ftface);	if (pfont->fontdata)		fz_dropbuffer(pfont->fontdata);}/* List of fonts that don't render properly without hinting. This list comes   freetype */static const char* const force_hinting[] ={  "DFKaiSho-SB",	 /* dfkaisb.ttf */  "DFKai-SB",		 /* kaiu.ttf */  "HuaTianSongTi?",  /* htst3.ttf */  "MingLiU",		 /* mingliu.ttf & mingliu.ttc */  "PMingLiU",		 /* mingliu.ttc */  "MingLi43",		 /* mingli.ttf */  NULL};pdf_font *pdf_newfont(char *name){	pdf_font *font;	int i;	font = fz_malloc(sizeof (pdf_font));	if (!font)		return nil;	fz_initfont((fz_font*)font, name);	font->super.render = ftrender;	font->super.drop = (void(*)(fz_font*)) ftdropfont;	font->ftface = nil;	font->substitute = 0;	font->flags = 0;	font->italicangle = 0;	font->ascent = 0;	font->descent = 0;	font->capheight = 0;	font->xheight = 0;	font->missingwidth = 0;	font->encoding = nil;	font->tottfcmap = 0;	font->ncidtogid = 0;	font->cidtogid = nil;	font->tounicode = nil;	font->ncidtoucs = 0;	font->cidtoucs = nil;	font->filename = nil;	font->fontdata = nil;	for (i = 0; i < 256; i++)		font->charprocs[i] = nil;	font->hint = 0;	for (i = 0; force_hinting[i]; i++)	{		char *pos = strstr(name, force_hinting[i]);		if (pos && (pos == name || pos[-1] == '+'))		{			font->hint = 1;			break;		}	}	return font;}/* * Simple fonts (Type1 and TrueType) */static fz_error *loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref){	fz_error *error;	fz_obj *descriptor = nil;	fz_obj *encoding = nil;	fz_obj *widths = nil;	fz_obj *basefontobj = nil;	unsigned short *etable = nil;	pdf_font *font;	fz_irect bbox;	FT_Face face;	FT_CharMap cmap;	int kind;	int symbolic;	char *basefont;	char *fontname;	char *estrings[256];	char ebuffer[256][32];	int i, k, n;	int fterr;	basefontobj = fz_dictgets(dict, "BaseFont");	error = pdf_resolve(&basefontobj, xref);	if (error)		return fz_rethrow(error, "cannot load simple font");	basefont = fz_toname(basefontobj);	fontname = cleanfontname(basefont);	/*	 * Load font file	 */	font = pdf_newfont(fontname);	if (!font)		return fz_outofmem;	pdf_logfont("load simple font (%d %d R) ptr=%p {\n", fz_tonum(ref), fz_togen(ref), font);	pdf_logfont("basefont0 %s\n", basefont);	pdf_logfont("basefont1 %s\n", fontname);	descriptor = fz_dictgets(dict, "FontDescriptor");	if (descriptor && basefont == fontname)		error = pdf_loadfontdescriptor(font, xref, descriptor, nil);	else		error = pdf_loadbuiltinfont(font, fontname);	if (error)		goto cleanup;	face = font->ftface;	kind = ftkind(face);	pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name);	bbox.x0 = (face->bbox.xMin * 1000) / face->units_per_EM;	bbox.y0 = (face->bbox.yMin * 1000) / face->units_per_EM;	bbox.x1 = (face->bbox.xMax * 1000) / face->units_per_EM;	bbox.y1 = (face->bbox.yMax * 1000) / face->units_per_EM;	pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.x0, bbox.y0, bbox.x1, bbox.y1);	if (bbox.x0 == bbox.x1)		fz_setfontbbox((fz_font*)font, -1000, -1000, 2000, 2000);	else		fz_setfontbbox((fz_font*)font, bbox.x0, bbox.y0, bbox.x1, bbox.y1);	/*	 * Encoding	 */	symbolic = font->flags & 4;	if (face->num_charmaps > 0)		cmap = face->charmaps[0];	else		cmap = nil;	for (i = 0; i < face->num_charmaps; i++)	{		FT_CharMap test = face->charmaps[i];		if (kind == TYPE1)		{			if (test->platform_id == 7)				cmap = test;		}		if (kind == TRUETYPE)		{			if (test->platform_id == 1 && test->encoding_id == 0)				cmap = test;			if (test->platform_id == 3 && test->encoding_id == 1)				cmap = test;		}	}	if (cmap)	{		fterr = FT_Set_Charmap(face, cmap);		if (fterr)		{			error = fz_throw("freetype could not set cmap: %s", ft_errstr(fterr));			goto cleanup;		}	}	else		fz_warn("freetype could not find any cmaps");	etable = fz_malloc(sizeof(unsigned short) * 256);	if (!etable)		goto cleanup;	for (i = 0; i < 256; i++)	{		estrings[i] = nil;		etable[i] = 0;	}	encoding = fz_dictgets(dict, "Encoding");	if (encoding && !(kind == TRUETYPE && symbolic))	{		error = pdf_resolve(&encoding, xref);		if (error)			goto cleanup;		if (fz_isname(encoding))			pdf_loadencoding(estrings, fz_toname(encoding));		if (fz_isdict(encoding))		{			fz_obj *base, *diff, *item;			base = fz_dictgets(encoding, "BaseEncoding");			if (fz_isname(base))				pdf_loadencoding(estrings, fz_toname(base));			diff = fz_dictgets(encoding, "Differences");			if (fz_isarray(diff))			{				n = fz_arraylen(diff);				k = 0;				for (i = 0; i < n; i++)				{					item = fz_arrayget(diff, i);					if (fz_isint(item))						k = fz_toint(item);					if (fz_isname(item))						estrings[k++] = fz_toname(item);					if (k < 0) k = 0;					if (k > 255) k = 255;				}			}		}		if (kind == TYPE1)		{			pdf_logfont("encode type1/cff by strings\n");			for (i = 0; i < 256; i++)				if (estrings[i])					etable[i] = FT_Get_Name_Index(face, estrings[i]);				else					etable[i] = ftcharindex(face, i);		}		if (kind == TRUETYPE)		{			/* Unicode cmap */			if (face->charmap && face->charmap->platform_id == 3)			{				pdf_logfont("encode truetype via unicode\n");				for (i = 0; i < 256; i++)					if (estrings[i])					{						int aglbuf[256];						int aglnum;						aglnum = pdf_lookupagl(estrings[i], aglbuf, nelem(aglbuf));						if (aglnum != 1)							etable[i] = FT_Get_Name_Index(face, estrings[i]);						else							etable[i] = ftcharindex(face, aglbuf[0]);					}					else						etable[i] = ftcharindex(face, i);			}			/* MacRoman cmap */			else if (face->charmap && face->charmap->platform_id == 1)			{				pdf_logfont("encode truetype via macroman\n");				for (i = 0; i < 256; i++)					if (estrings[i])					{						k = mrecode(estrings[i]);						if (k <= 0)							etable[i] = FT_Get_Name_Index(face, estrings[i]);						else							etable[i] = ftcharindex(face, k);					}					else						etable[i] = ftcharindex(face, i);			}			/* Symbolic cmap */			else			{				pdf_logfont("encode truetype symbolic\n");				for (i = 0; i < 256; i++)				{					etable[i] = ftcharindex(face, i);					if (etable[i])						FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32);					else						FT_Get_Glyph_Name(face, i, ebuffer[i], 32);				}				/* map encoding to gid via glyph names */				for (i = 0; i < 256; i++)				{					char *s = estrings[i];					if (!etable[i] && s)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -