static inline int find_nearest_color(struct rgb *r, int l) { int dist, dst, min, i; static struct rgb_cache_entry rgb_cache[RGB_HASH_SIZE]; static int cache_init = 0; int h; if (!cache_init) goto initialize; back: h = HASH_RGB(r, l); if (rgb_cache[h].color != -1 && rgb_cache[h].l == l && rgb_cache[h].rgb.r == r->r && rgb_cache[h].rgb.g == r->g && rgb_cache[h].rgb.b == r->b) return rgb_cache[h].color; dist = 0xffffff; min = 0; for (i = 0; i < l; i++) if ((dst = color_distance(r, &palette[i])) < dist) dist = dst, min = i; rgb_cache[h].color = min; rgb_cache[h].l = l; rgb_cache[h].rgb.r = r->r; rgb_cache[h].rgb.g = r->g; rgb_cache[h].rgb.b = r->b; return min; initialize: for (h = 0; h < RGB_HASH_SIZE; h++) rgb_cache[h].color = -1; cache_init = 1; goto back; }
/* Locates the nearest terminal color. */ static inline unsigned char get_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)]; /* Uninitialized cache entries have level set to zero. */ 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 = color_distance(&rgb, &palette[0]); int i; #ifdef CONFIG_DEBUG if (level <= 0) INTERNAL("get_color() called with @level <= 0"); #endif for (i = 1; 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; }