You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
8.1 KiB
217 lines
8.1 KiB
/****************************************************************************
|
|
*
|
|
* Gamma-correct alpha blending of text
|
|
*
|
|
* (C) 2004 David Turner
|
|
*
|
|
*/
|
|
|
|
#ifndef __GBLENDER_H__
|
|
#define __GBLENDER_H__
|
|
|
|
#ifndef GBLENDER_API
|
|
#define GBLENDER_API(x) extern x
|
|
#endif
|
|
|
|
#ifndef GBLENDER_APIDEF
|
|
#define GBLENDER_APIDEF(x) x
|
|
#endif
|
|
|
|
#define GBLENDER_SHADE_BITS 4 /* must be <= 7 !! */
|
|
#define GBLENDER_SHADE_COUNT ( 1 << GBLENDER_SHADE_BITS )
|
|
#define GBLENDER_SHADE_INDEX(n) ((n + (GBLENDER_SHADE_COUNT/2)) >> GBLENDER_SHADE_BITS)
|
|
#define GBLENDER_KEY_COUNT 256
|
|
#define GBLENDER_GAMMA_SHIFT 2
|
|
|
|
#define xGBLENDER_STORE_BYTES /* define this to store (R,G,B) values on 3 \
|
|
* bytes, instead of a single 32-bit integer.\
|
|
* surprisingly, this can speed up \
|
|
* the blender on certain machines. \
|
|
* Go figure what's really happenning though :-) \
|
|
*/
|
|
|
|
#define GBLENDER_STATS /* define this to collect statistics in the \
|
|
* blender \
|
|
*/
|
|
|
|
typedef unsigned int GBlenderPixel; /* needs 32-bits here !! */
|
|
|
|
#ifdef GBLENDER_STORE_BYTES
|
|
typedef unsigned char GBlenderCell;
|
|
# define GBLENDER_CELL_SIZE 3
|
|
#else
|
|
typedef GBlenderPixel GBlenderCell;
|
|
# define GBLENDER_CELL_SIZE 1
|
|
#endif
|
|
|
|
|
|
typedef struct
|
|
{
|
|
GBlenderPixel background;
|
|
GBlenderPixel foreground;
|
|
GBlenderCell* cells;
|
|
|
|
} GBlenderKeyRec, *GBlenderKey;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
unsigned short backfore; /* (fore << 8) | back */
|
|
signed short index; /* offset in (unsigned char*)cells */
|
|
|
|
} GBlenderChanKeyRec, *GBlenderChanKey;
|
|
|
|
|
|
typedef struct GBlenderRec_
|
|
{
|
|
GBlenderKeyRec keys [ GBLENDER_KEY_COUNT ];
|
|
GBlenderCell cells[ GBLENDER_KEY_COUNT*GBLENDER_SHADE_COUNT*GBLENDER_CELL_SIZE ];
|
|
|
|
/* a small cache for normal modes
|
|
*/
|
|
GBlenderPixel cache_back;
|
|
GBlenderPixel cache_fore;
|
|
GBlenderCell* cache_cells;
|
|
|
|
/* a small cache for RGB channels modes
|
|
*/
|
|
int cache_r_back;
|
|
int cache_r_fore;
|
|
unsigned char* cache_r_cells;
|
|
|
|
int cache_g_back;
|
|
int cache_g_fore;
|
|
unsigned char* cache_g_cells;
|
|
|
|
int cache_b_back;
|
|
int cache_b_fore;
|
|
unsigned char* cache_b_cells;
|
|
|
|
/* are we in color or channel mode ?
|
|
*/
|
|
int channels;
|
|
|
|
/* the gamma table
|
|
*/
|
|
unsigned short gamma_ramp[256]; /* voltage to linear */
|
|
unsigned char gamma_ramp_inv[256 << GBLENDER_GAMMA_SHIFT]; /* linear to voltage */
|
|
|
|
#ifdef GBLENDER_STATS
|
|
long stat_hits; /* number of direct hits */
|
|
long stat_lookups; /* number of table lookups */
|
|
long stat_keys; /* number of table key recomputation */
|
|
long stat_clears; /* number of table clears */
|
|
#endif
|
|
|
|
} GBlenderRec, *GBlender;
|
|
|
|
|
|
/* initialize with a given gamma */
|
|
GBLENDER_API( void )
|
|
gblender_init( GBlender blender,
|
|
double gamma );
|
|
|
|
|
|
/* clear blender, and reset stats */
|
|
GBLENDER_API( void )
|
|
gblender_reset( GBlender reset );
|
|
|
|
|
|
/* lookup a cell range for a given (background,foreground) pair
|
|
*/
|
|
GBLENDER_API( GBlenderCell* )
|
|
gblender_lookup( GBlender blender,
|
|
GBlenderPixel background,
|
|
GBlenderPixel foreground );
|
|
|
|
GBLENDER_API( unsigned char* )
|
|
gblender_lookup_channel( GBlender blender,
|
|
int background,
|
|
int foreground );
|
|
|
|
#ifdef GBLENDER_STATS
|
|
GBLENDER_API( void )
|
|
gblender_dump_stats( GBlender blender );
|
|
#else
|
|
# define gblender_dump_stats(b) do { } while (0);
|
|
#endif
|
|
|
|
|
|
/* no final `;'! */
|
|
#define GBLENDER_VARS(_gb,_fore) \
|
|
GBlenderPixel _gback = (_gb)->cache_back; \
|
|
GBlenderCell* _gcells = ( (_fore) == (_gb)->cache_fore ? (_gb)->cache_cells : gblender_lookup( (_gb), _gback, _fore ) ); \
|
|
GBlenderPixel _gfore = (_fore)
|
|
|
|
#define GBLENDER_CLOSE(_gb) \
|
|
(_gb)->cache_back = _gback; \
|
|
(_gb)->cache_fore = _gfore; \
|
|
(_gb)->cache_cells = _gcells;
|
|
|
|
|
|
|
|
/* no final `;'! */
|
|
#define GBLENDER_CHANNEL_VARS(_gb,_rfore,_gfore,_bfore) \
|
|
int _grback = (_gb)->cache_r_back; \
|
|
unsigned char* _grcells = ( (_rfore) == (_gb)->cache_r_fore ? (_gb)->cache_r_cells : gblender_lookup_channel( (_gb), _grback, _rfore )); \
|
|
int _grfore = (_rfore); \
|
|
int _ggback = (_gb)->cache_g_back; \
|
|
unsigned char* _ggcells = ( (_gfore) == (_gb)->cache_g_fore ? (_gb)->cache_g_cells : gblender_lookup_channel( (_gb), _ggback, _gfore )); \
|
|
int _ggfore = (_rfore); \
|
|
int _gbback = (_gb)->cache_b_back; \
|
|
unsigned char* _gbcells = ( (_bfore) == (_gb)->cache_b_fore ? (_gb)->cache_b_cells : gblender_lookup_channel( (_gb), _gbback, _bfore )); \
|
|
int _gbfore = (_bfore)
|
|
|
|
#define GBLENDER_CHANNEL_CLOSE(_gb) \
|
|
(_gb)->cache_r_back = _grback; \
|
|
(_gb)->cache_r_fore = _grfore; \
|
|
(_gb)->cache_r_cells = _grcells; \
|
|
(_gb)->cache_g_back = _ggback; \
|
|
(_gb)->cache_g_fore = _ggfore; \
|
|
(_gb)->cache_g_cells = _ggcells; \
|
|
(_gb)->cache_b_back = _gbback; \
|
|
(_gb)->cache_b_fore = _gbfore; \
|
|
(_gb)->cache_b_cells = _gbcells;
|
|
|
|
|
|
#ifdef GBLENDER_STATS
|
|
#define GBLENDER_STAT_HIT(gb) (gb)->stat_hits++
|
|
#else
|
|
#define GBLENDER_STAT_HIT(gb) /* nothing */
|
|
#endif
|
|
|
|
#define GBLENDER_LOOKUP(gb,back) \
|
|
GBLENDER_STAT_HIT(gb); \
|
|
if ( _gback != (GBlenderPixel)(back) ) \
|
|
{ \
|
|
_gback = (GBlenderPixel)(back); \
|
|
_gcells = gblender_lookup( (gb), _gback, _gfore ); \
|
|
}
|
|
|
|
#define GBLENDER_LOOKUP_R(gb,back) \
|
|
GBLENDER_STAT_HIT(gb); \
|
|
if ( _grback != (int)(back) ) \
|
|
{ \
|
|
_grback = (GBlenderPixel)(back); \
|
|
_grcells = gblender_lookup_channel( (gb), _grback, _grfore ); \
|
|
}
|
|
|
|
#define GBLENDER_LOOKUP_G(gb,back) \
|
|
GBLENDER_STAT_HIT(gb); \
|
|
if ( _ggback != (int)(back) ) \
|
|
{ \
|
|
_ggback = (GBlenderPixel)(back); \
|
|
_ggcells = gblender_lookup_channel( (gb), _ggback, _ggfore ); \
|
|
}
|
|
|
|
#define GBLENDER_LOOKUP_B(gb,back) \
|
|
GBLENDER_STAT_HIT(gb); \
|
|
if ( _gbback != (int)(back) ) \
|
|
{ \
|
|
_gbback = (GBlenderPixel)(back); \
|
|
_gbcells = gblender_lookup_channel( (gb), _gbback, _gbfore ); \
|
|
}
|
|
|
|
|
|
#endif /* __GBENCH_CACHE_H__ */
|