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

📄 selfont.c

📁 神龙卡开发原代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2000 Greg Haerr <greg@censoft.com> * Copyright (c) 2000 Morten Rolland * * Device-independent font selection routines *//*#define NDEBUG*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <ctype.h>		/* toupper*/#include <string.h>#include "device.h"#if (UNIX | DOS_DJGPP)#define strcmpi	strcasecmp#endif#if FONTMAPPER/* entry points*/int select_font(const PMWLOGFONT plogfont, char *physname);/* * The following structure, defines and variables are used to administrate * a set of fonts that are scanned when a font is requested.  The set of * fonts can be configured with the GdClearFontList and GdAddFont functions. */struct available_font {	MWLOGFONT	lf;	char *foundry;	char *family;	char *fontname;	int fontclass, alias;	struct available_font *next;};static struct available_font *all_fonts = 0;/* * Stupid little function to perform a comparison of two strings, * returning one of STREQ_EXACT, STREQ_CASE or STREQ_NOMATCH. */#define STREQ_EXACT	0#define STREQ_CASE	1#define STREQ_NOMATCH	2static int streq(const char *a, const char *b){	int rc;	for ( rc = STREQ_EXACT;  *a != 0; a++, b++ ) {		if ( *a == *b )			continue;		if ( toupper((unsigned char)*a) != toupper((unsigned char)*b) )			return STREQ_NOMATCH;		rc = STREQ_CASE;	}	if ( *b != 0 )		return STREQ_NOMATCH;	return rc;}/* * Decode the "foundry" information into a MWLF_CLASS_ value denoting * which rendering system should be used to render the font. */static int decode_font_class(const char *class){	if ( class == NULL )		return 0;	if ( !strcmp("T1",class) )		return MWLF_CLASS_T1LIB;	if ( !strcmp("FT",class) )		return MWLF_CLASS_FREETYPE;	if ( !strcmp("MWF",class) )		return MWLF_CLASS_BUILTIN;	return 0;}/* * Try to find a font that matches the foundry and font name * requested. */void test_font_naming(const char *foundry, const char *fontname,		      struct available_font *af,		      struct available_font **best, int *goodness){	int penalty = 0;	if ( foundry != 0 ) {		if ( af->foundry != 0 ) {			switch ( streq(foundry,af->foundry) ) {				case STREQ_EXACT:					break;				case STREQ_CASE:					penalty += 2;					break;				default:					penalty += 8;					break;			}		} else {			penalty += 4;		}	}	switch ( streq(fontname,af->fontname) ) {		case STREQ_EXACT:			break;		case STREQ_CASE:			penalty += 1;			break;		default:			penalty += 16;			break;	}	if ( *goodness < 0 || penalty < *goodness ) {		*best = af;		*goodness = penalty;	}}/* * The 'test_font_goodness' function attempts to find how suitable a font is * compared to a desired one.  The desired font is specified by: * *   foundry (can be NULL), family and the MWLOGFONT *   structure (can be NULL). * * If any fonts are configured, one will always be returned from here, * but the goodness may be very bad.  The goodness (or similarity) * factor is computed by adding up: */#define GOODNESS_NO_FONTNAME		1000	/* No matching font-name found*/#define GOODNESS_WEIGHT_DIFF		1	/* 0-900 for weight difference*/#define GOODNESS_NO_FOUNDRY		100	/* No foundry */#define GOODNESS_FOUNDRY_UNKNOWN	16	/* Foundry unknown */#define GOODNESS_CASE_FAMILY		8#define GOODNESS_CASE_FONTNAME		4#define GOODNESS_CASE_FOUNDRY		2#define GOODNESS_EXACT_FAMILY		1	/* Matched font family */#define GOODNESS_EXACT_FOUNDRY		0	/* Clean match */#define GOODNESS_EXACT_FONTNAME		0	/* Clean match */#define GOODNESS_FAMILY_UNKNOWN		3000#define GOODNESS_NOMATCH_FAMILY		10000#define GOODNESS_EXACT_FONTFAMILY	0#define GOODNESS_CASE_FONTFAMILY	32#define GOODNESS_CLOSE_SLANT		128#define GOODNESS_BAD_SLANT		256#define GOODNESS_WRONG_SPACING		2048#define GOODNESS_WRONG_SERIFSTYLE	1024#define GOODNESS_WANTED_SMALLCAPS_NOT_AVAILABLE		4096#define GOODNESS_ONLY_SMALLCAPS_AVAILABLE		8192static int find_foundry_penalty(const struct available_font *have,			 const char *foundry){	if ( foundry == 0 )		return 0;	if ( have->foundry == 0 )		return GOODNESS_FOUNDRY_UNKNOWN;	switch ( streq(foundry,have->foundry) ) {		case STREQ_EXACT:			return GOODNESS_EXACT_FOUNDRY;			break;		case STREQ_CASE:			return GOODNESS_CASE_FOUNDRY;			break;		default:			return GOODNESS_NO_FOUNDRY;			break;	}}static int find_family_penalty(const struct available_font *have,			       const char *family){	if ( family == 0 )		return 0;	if ( have->family == 0 )		return GOODNESS_FAMILY_UNKNOWN;	switch ( streq(family,have->family) ) {		case STREQ_EXACT:			return GOODNESS_EXACT_FAMILY;			break;		case STREQ_CASE:			return GOODNESS_CASE_FAMILY;			break;		default:			return GOODNESS_NOMATCH_FAMILY;			break;	}}static int find_fontname_penalty(const struct available_font *have,				 const char *fontname){	switch ( streq(have->fontname,fontname) ) {		case STREQ_EXACT:			return GOODNESS_EXACT_FONTNAME;			break;		case STREQ_CASE:			return GOODNESS_CASE_FONTNAME;			break;		default:			break;	}	/* Test Fontname against font family name */	if ( have->family != 0 ) {		switch ( streq(have->family,fontname) ) {			case STREQ_EXACT:				return GOODNESS_EXACT_FONTFAMILY;				break;			case STREQ_CASE:				return GOODNESS_CASE_FONTFAMILY;				break;			default:				/* No suitable fontname found */				break;		}	}	return GOODNESS_NO_FONTNAME;}static int find_weight_penalty(PMWLOGFONT want, PMWLOGFONT have){	int weight_diff;	weight_diff = want->lfWeight - have->lfWeight;	if ( weight_diff < 0 )		weight_diff = -weight_diff;	return weight_diff * GOODNESS_WEIGHT_DIFF;}static int find_slant_penalty(PMWLOGFONT want, PMWLOGFONT have){	/* See if slant is acceptable */	if ( !want->lfItalic && !want->lfRoman && !want->lfOblique ) {		/* Try to default to Romans if not specified */		if ( have->lfItalic || have->lfOblique )			return GOODNESS_CLOSE_SLANT;		return 0;	}	if ( want->lfItalic && have->lfItalic )		return 0;	if ( want->lfRoman && have->lfRoman )		return 0;	if ( want->lfOblique && have->lfOblique )		return 0;	/* No perfect match for the slant, try "closest" one */	if ( want->lfItalic && have->lfOblique )		return GOODNESS_CLOSE_SLANT;	if ( want->lfOblique && have->lfItalic )		return GOODNESS_CLOSE_SLANT;	return GOODNESS_BAD_SLANT;}static int find_spacing_penalty(PMWLOGFONT want, PMWLOGFONT have){	if ( want->lfProportional && have->lfProportional )		return 0;	if ( want->lfMonospace && have->lfMonospace )		return 0;	if ( want->lfMonospace || want->lfProportional )		return GOODNESS_WRONG_SPACING;	return 0;	/* No special desires */}static int find_serif_penalty(PMWLOGFONT want, PMWLOGFONT have){	if ( !want->lfSerif && !want->lfSansSerif )		return 0;	if ( want->lfSerif && have->lfSerif )		return 0;	if ( want->lfSansSerif && have->lfSansSerif )		return 0;	return GOODNESS_WRONG_SERIFSTYLE;}static int find_smallcaps_penalty(PMWLOGFONT want, PMWLOGFONT have){	if ( !want->lfSmallCaps && !have->lfSmallCaps )		return 0;	if ( want->lfSmallCaps && have->lfSmallCaps )		return 0;	if ( want->lfSmallCaps )		return GOODNESS_WANTED_SMALLCAPS_NOT_AVAILABLE;	return GOODNESS_ONLY_SMALLCAPS_AVAILABLE;}		static void test_font_goodness(const char *foundry, const char *family,			       const char *fontname, const PMWLOGFONT lf,			       struct available_font *af,			       struct available_font **best, int *goodness){	int penalty = 0;	penalty += find_foundry_penalty(af,foundry);	penalty += find_family_penalty(af,family);	/* Test Fontname, but only if there is no family */	if ( family == 0 )		penalty += find_fontname_penalty(af,fontname);	if ( lf != 0 ) {		/* Check logical font attributes */		penalty += find_weight_penalty(lf,&af->lf);		penalty += find_slant_penalty(lf,&af->lf);		penalty += find_spacing_penalty(lf,&af->lf);		penalty += find_serif_penalty(lf,&af->lf);		penalty += find_smallcaps_penalty(lf,&af->lf);	}	/* See if this font is better than the previous one */	if ( *goodness < 0 || penalty < *goodness ) {		/* Yes, this font is better; change to it */		*best = af;		*goodness = penalty;	}}static struct available_font *find_suitable_font(const char *foundry,					       const char *fontname,					       const PMWLOGFONT plogfont){	struct available_font *af, *best;	char *family;	int goodness;	/*	 * Try to find a font that matches the name specified as the	 * desired font (and foundry if possible).  If we find a	 * suitable font, we will use the family name when trying to	 * find a font that matches the MWLOGFONT attributes.  This	 * makes it possible to ask for an Italic version of	 * "Times Roman" and the expected thing will happen (get the	 * font "Times Italic").	 */	goodness = -1;	for ( af = best = all_fonts; af != 0; af = af->next ) {		test_font_naming(foundry,fontname,af,&best,&goodness);	}	family = 0;	if ( goodness != -1 ) {		/* A font with a name that kind of matched was found,		 * make a note of its family.  If it has no family, we		 * can't make any use of the 		 */		family = best->family;	}	/*	 * Try to find the closest font that matches the font family	 * we have established.  If no family was found above, all	 * fonts will be considered.	 */	goodness = -1;	for ( af = best = all_fonts; af != 0; af = af->next ) {		test_font_goodness(foundry,family,fontname,plogfont,af,				   &best,&goodness);	}		return best;}int select_font(const PMWLOGFONT plogfont, char *physname){	struct available_font *font;	char fndry[128], *foundry;	const char *fontname;	char *tmp;	int t, comma;	int fontclass = 0;	int found_font = 0;	fontname = plogfont->lfFaceName;

⌨️ 快捷键说明

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