color.c

来自「一个很有名的浏览器」· C语言 代码 · 共 330 行

C
330
字号
/* Terminal color composing. *//* $Id: color.c,v 1.78.2.1 2005/04/06 08:31:03 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "elinks.h"#include "terminal/color.h"#include "terminal/draw.h"#include "util/color.h"#include "util/error.h"#include "terminal/palette.inc"struct rgb_cache_entry {	int color;	int level;	color_t rgb;};static inline intcolor_distance(struct rgb *c1, struct rgb *c2){	int r = c1->r - c2->r;	int g = c1->g - c2->g;	int b = c1->b - c2->b;	return (3 * r * r) + (4 * g * g) + (2 * b * b);}/* FIXME: Namespace clash with <wingdi.h> */#undef RGB#define RED(color)	(RED_COLOR(color)   << 3)#define GREEN(color)	(GREEN_COLOR(color) << 2)#define BLUE(color)	(BLUE_COLOR(color)  << 0)#define RGB(color)	(RED(color) + GREEN(color) + BLUE(color))#define RGB_HASH_SIZE		4096#define HASH_RGB(color, l)	((RGB(color) + (l)) & (RGB_HASH_SIZE - 1))/* Locates the nearest terminal color. */static inline unsigned charget_color(color_t color, struct rgb *palette, int level){	static struct rgb_cache_entry cache[RGB_HASH_SIZE];	struct rgb_cache_entry *rgb_cache = &cache[HASH_RGB(color, level)];	/* Uninialized cache entries have level = 0. */	if (rgb_cache->level == 0	    || rgb_cache->level != level	    || rgb_cache->rgb != color) {		struct rgb rgb = INIT_RGB(color);		unsigned char nearest_color = 0;		int min_dist = 0xffffff;		int i;		/* This is a hotspot so maybe this is a bad idea. --jonas */		assertm(level, "find_nearest_color() called with @level = 0");		for (i = 0; i < level; i++) {			int dist = color_distance(&rgb, &palette[i]);			if (dist < min_dist) {				min_dist = dist;				nearest_color = i;			}		}		rgb_cache->color = nearest_color;		rgb_cache->level = level;		rgb_cache->rgb = color;	}	return rgb_cache->color;}#undef HASH_RGB#undef RGB_HASH_SIZE/* Controls what color ranges to use when setting the terminal color. *//* TODO: Part of the 256 color palette is gray scale, maybe we could experiment * with a grayscale mode. ;) --jonas */enum palette_range {       PALETTE_FULL = 0,       PALETTE_HALF,       PALETTE_RANGES, /* XXX: Keep last */};struct color_mode_info {	struct rgb *palette;	struct {		int bg;		int fg;	} palette_range[PALETTE_RANGES];};static struct color_mode_info color_mode_16 = {	palette16,	{		/* PALETTE_FULL */	{ 8, 16 },		/* PALETTE_HALF */	{ 8,  8 },	}};#ifdef CONFIG_256_COLORSstatic struct color_mode_info color_mode_256 = {	palette256,	{		/* PALETTE_FULL */	{ 256, 256 },		/* PALETTE_HALF */	{ 256, 128 },	}};#endifstatic struct color_mode_info *color_modes[] = {	/* COLOR_MODE_MONO */	&color_mode_16,	/* COLOR_MODE_16 */	&color_mode_16,#ifdef CONFIG_256_COLORS	/* COLOR_MODE_256 */	&color_mode_256,#endif};/* Colors values used in the foreground color table: * *	0 == black	 8 == darkgrey (brightblack ;) *	1 == red	 9 == brightred *	2 == green	10 == brightgreen *	3 == brown	11 == brightyellow *	4 == blue	12 == brightblue *	5 == magenta	13 == brightmagenta *	6 == cyan	14 == brightcyan *	7 == white	15 == brightwhite * * Bright colors will be rendered bold. *//* This table is based mostly on wild guesses of mine. Feel free to * correct it. --pasky *//* Indexed by [fg][bg]->fg: */static unsigned char fg_color[16][8] = {	/* bk  r  gr  br  bl   m   c   w */	/* 0 (black) */	{  7,  0,  0,  0,  7,  0,  0,  0 },	/* 1 (red) */	{  1,  9,  1,  9,  9,  9,  1,  1 },	/* 2 (green) */	{  2,  2, 10,  2,  2,  2, 10, 10 },	/* 3 (brown) */	{  3, 11,  3, 11,  3, 11,  3,  3 },	/* 4 (blue) */	{ 12, 12,  6,  4, 12,  6,  4,  4 },	/* 5 (magenta) */	{  5, 13,  5, 13, 13, 13,  5,  5 },	/* 6 (cyan) */	{  6,  6, 14,  6,  6,  6, 14, 14 },	/* 7 (grey) */	{  7,  7,  0,  7,  7,  7,  0,  0 }, /* Don't s/0/8/, messy --pasky */	/* 8 (darkgrey) */	{ 15, 15,  8, 15, 15, 15,  8,  8 },	/* 9 (brightred) */	{  9,  9,  1,  9,  9,  9,  1,  9 }, /* I insist on 7->9 --pasky */	/* 10 (brightgreen) */	{ 10, 10, 10, 10, 10, 10, 10, 10 },	/* 11 (brightyellow) */	{ 11, 11, 11, 11, 11, 11, 11, 11 },	/* 12 (brightblue) */	{ 12, 12,  6,  4,  6,  6,  4, 12 },	/* 13 (brightmagenta) */	{ 13, 13,  5, 13, 13, 13,  5,  5 },	/* 14 (brightcyan) */	{ 14, 14, 14, 14, 14, 14, 14, 14 },	/* 15 (brightwhite) */	{ 15, 15, 15, 15, 15, 15, 15, 15 },};/* When determining wether to use negative image we make the most significant * be least significant. */#define CMPCODE(c) (((c) << 1 | (c) >> 2) & TERM_COLOR_MASK)#define use_inverse(bg, fg) CMPCODE(fg & TERM_COLOR_MASK) < CMPCODE(bg)static inline voidset_term_color16(struct screen_char *schar, enum color_flags flags,		 unsigned char fg, unsigned char bg){	/* Adjusts the foreground color to be more visible. */	if (flags & COLOR_INCREASE_CONTRAST) {		fg = fg_color[fg][bg];	}	/* Add various color enhancement based on the attributes. */	if (schar->attr) {		if (schar->attr & SCREEN_ATTR_ITALIC)			fg ^= 0x01;		if (schar->attr & SCREEN_ATTR_BOLD)			fg |= SCREEN_ATTR_BOLD;		if ((schar->attr & SCREEN_ATTR_UNDERLINE)		    && (flags & COLOR_ENHANCE_UNDERLINE)) {			fg |= SCREEN_ATTR_BOLD;			fg ^= 0x04;		}	}	/* Adjusts the foreground color to be more visible. */	if ((flags & COLOR_INCREASE_CONTRAST)	    || (bg == fg && (flags & COLOR_ENSURE_CONTRAST))) {		if (flags & COLOR_ENSURE_INVERTED_CONTRAST) {			unsigned char contrastbg = fg_color[fg][bg];			fg = bg;			bg = contrastbg;		} else {			fg = fg_color[fg][bg];		}	}	if (fg & SCREEN_ATTR_BOLD) {		schar->attr |= SCREEN_ATTR_BOLD;	}	if (use_inverse(bg, fg)) {		schar->attr |= SCREEN_ATTR_STANDOUT;	}#ifdef CONFIG_256_COLORS	/* With 256 color support we use memcmp() when comparing color in	 * terminal/screen.c:add_char*() so we need to clear this byte. */	TERM_COLOR_FOREGROUND(schar->color) = (fg & TERM_COLOR_MASK);	TERM_COLOR_BACKGROUND(schar->color) = bg;#else	schar->color[0] = (bg << 4 | fg);#endif}voidset_term_color(struct screen_char *schar, struct color_pair *pair,	       enum color_flags flags, enum color_mode color_mode){	struct color_mode_info *mode;	enum palette_range palette_range = PALETTE_FULL;	unsigned char fg, bg;	assert(color_mode >= COLOR_MODE_DUMP && color_mode < COLOR_MODES);	/* Options for the various color modes. */	switch (color_mode) {	case COLOR_MODE_MONO:		/* TODO: A better way if possible to find out whether to		 * inverse the fore- and backgroundcolor. Else figure out what:		 *		 *	CMPCODE(c) (((c) << 1 | (c) >> 2) & TERM_COLOR_MASK)		 *		 * mean. :) --jonas */		/* Decrease the range of the 16 palette to not include		 * bright colors. */		if (flags & COLOR_DECREASE_LIGHTNESS) {			palette_range = PALETTE_HALF;			schar->attr |= SCREEN_ATTR_STANDOUT;		}		break;	case COLOR_MODE_16:		/* Decrease the range of the 16 palette to not include		 * bright colors. */		if (flags & COLOR_DECREASE_LIGHTNESS)			palette_range = PALETTE_HALF;		break;#ifdef CONFIG_256_COLORS	case COLOR_MODE_256:		/* TODO: Handle decrease lightness by converting to		 * hue-ligthness-saturation color model */		break;#endif	case COLOR_MODE_DUMP:		return;	case COLOR_MODES:		/* This is caught by the assert() above. */		return;	}	assert(schar);	mode = color_modes[color_mode];	fg = get_color(pair->foreground, mode->palette, mode->palette_range[palette_range].fg);	bg = get_color(pair->background, mode->palette, mode->palette_range[palette_range].bg);	switch (color_mode) {	case COLOR_MODES:	case COLOR_MODE_DUMP:		INTERNAL("Bad color mode, it should _never_ occur here.");		break;#ifdef CONFIG_256_COLORS	case COLOR_MODE_256:		/* Adjusts the foreground color to be more visible. */		/* TODO: Be smarter! Here we just choose either black or white		 * ANSI color to make sure the color is visible. Pasky		 * mentioned maybe calculating a distance and choosing some		 * intermediate color. --jonas */		/* TODO: Maybe also do something to honour the		 * allow_dark_on_black option. --jonas */		if (bg == fg && (flags & COLOR_ENSURE_CONTRAST)) {			if (flags & COLOR_ENSURE_INVERTED_CONTRAST) {				bg = (fg == 0) ? 15 : 0;			} else {				fg = (bg == 0) ? 15 : 0;			}		}		TERM_COLOR_FOREGROUND(schar->color) = fg;		TERM_COLOR_BACKGROUND(schar->color) = bg;		break;#endif	case COLOR_MODE_MONO:	case COLOR_MODE_16:		set_term_color16(schar, flags, fg, bg);		break;	}}

⌨️ 快捷键说明

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