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.
2069 lines
51 KiB
2069 lines
51 KiB
15 years ago
|
/****************************************************************************/
|
||
|
/* */
|
||
|
/* The FreeType project -- a free and portable quality TrueType renderer. */
|
||
|
/* */
|
||
|
/* Copyright 1996-1999, 2000, 2001, 2002 by */
|
||
|
/* D. Turner, R.Wilhelm, and W. Lemberg */
|
||
|
/* */
|
||
|
/* grblit.c: Support for blitting of bitmaps with various depth. */
|
||
|
/* */
|
||
|
/****************************************************************************/
|
||
|
|
||
|
#include "grblit.h"
|
||
|
#include "grobjs.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#define GRAY8
|
||
|
|
||
|
static
|
||
|
int compute_clips( grBlitter* blit,
|
||
|
int x_offset,
|
||
|
int y_offset )
|
||
|
{
|
||
|
int xmin, ymin, xmax, ymax, width, height, target_width;
|
||
|
|
||
|
/* perform clipping and setup variables */
|
||
|
width = blit->source.width;
|
||
|
height = blit->source.rows;
|
||
|
|
||
|
switch ( blit->source.mode )
|
||
|
{
|
||
|
case gr_pixel_mode_mono:
|
||
|
width = (width + 7) & -8;
|
||
|
break;
|
||
|
|
||
|
case gr_pixel_mode_pal4:
|
||
|
width = (width + 1) & -2;
|
||
|
break;
|
||
|
|
||
|
case gr_pixel_mode_lcd:
|
||
|
case gr_pixel_mode_lcd2:
|
||
|
width /= 3;
|
||
|
break;
|
||
|
|
||
|
case gr_pixel_mode_lcdv:
|
||
|
case gr_pixel_mode_lcdv2:
|
||
|
height /= 3;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
;
|
||
|
}
|
||
|
|
||
|
xmin = x_offset;
|
||
|
ymin = y_offset;
|
||
|
xmax = xmin + width-1;
|
||
|
ymax = ymin + height-1;
|
||
|
|
||
|
/* clip if necessary */
|
||
|
if ( width == 0 || height == 0 ||
|
||
|
xmax < 0 || xmin >= blit->target.width ||
|
||
|
ymax < 0 || ymin >= blit->target.rows )
|
||
|
return 1;
|
||
|
|
||
|
/* set up clipping and cursors */
|
||
|
blit->yread = 0;
|
||
|
if ( ymin < 0 )
|
||
|
{
|
||
|
blit->yread -= ymin;
|
||
|
height += ymin;
|
||
|
blit->ywrite = 0;
|
||
|
}
|
||
|
else
|
||
|
blit->ywrite = ymin;
|
||
|
|
||
|
if ( ymax >= blit->target.rows )
|
||
|
height -= ymax - blit->target.rows + 1;
|
||
|
|
||
|
blit->xread = 0;
|
||
|
if ( xmin < 0 )
|
||
|
{
|
||
|
blit->xread -= xmin;
|
||
|
width += xmin;
|
||
|
blit->xwrite = 0;
|
||
|
}
|
||
|
else
|
||
|
blit->xwrite = xmin;
|
||
|
|
||
|
target_width = blit->target.width;
|
||
|
|
||
|
switch ( blit->target.mode )
|
||
|
{
|
||
|
case gr_pixel_mode_mono:
|
||
|
target_width = (target_width + 7) & -8;
|
||
|
break;
|
||
|
case gr_pixel_mode_pal4:
|
||
|
target_width = (target_width + 1) & -2;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
;
|
||
|
}
|
||
|
|
||
|
blit->right_clip = xmax - target_width + 1;
|
||
|
if ( blit->right_clip > 0 )
|
||
|
width -= blit->right_clip;
|
||
|
else
|
||
|
blit->right_clip = 0;
|
||
|
|
||
|
blit->width = width;
|
||
|
blit->height = height;
|
||
|
|
||
|
/* set read and write to the top-left corner of the read */
|
||
|
/* and write areas before clipping. */
|
||
|
|
||
|
blit->read = blit->source.buffer;
|
||
|
blit->write = blit->target.buffer;
|
||
|
|
||
|
blit->read_line = blit->source.pitch;
|
||
|
blit->write_line = blit->target.pitch;
|
||
|
|
||
|
if ( blit->read_line < 0 )
|
||
|
blit->read -= (blit->source.rows-1) * blit->read_line;
|
||
|
|
||
|
if ( blit->write_line < 0 )
|
||
|
blit->write -= (blit->target.rows-1) * blit->write_line;
|
||
|
|
||
|
/* now go to the start line. Note that we do not move the */
|
||
|
/* x position yet, as this is dependent on the pixel format */
|
||
|
blit->read += blit->yread * blit->read_line;
|
||
|
blit->write += blit->ywrite * blit->write_line;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_mono_to_mono */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
static
|
||
|
void blit_mono_to_mono( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int shift, left_clip, x, y;
|
||
|
byte* read;
|
||
|
byte* write;
|
||
|
|
||
|
(void)color; /* unused argument */
|
||
|
|
||
|
left_clip = ( blit->xread > 0 );
|
||
|
shift = ( blit->xwrite - blit->xread ) & 7;
|
||
|
|
||
|
read = blit->read + (blit->xread >> 3);
|
||
|
write = blit->write + (blit->xwrite >> 3);
|
||
|
|
||
|
if ( shift == 0 )
|
||
|
{
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
byte* _read = read;
|
||
|
byte* _write = write;
|
||
|
|
||
|
x = blit->width;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
*_write++ |= *_read++;
|
||
|
x -= 8;
|
||
|
} while ( x > 0 );
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
} while ( y > 0 );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int first, last, count;
|
||
|
|
||
|
|
||
|
first = blit->xwrite >> 3;
|
||
|
last = (blit->xwrite + blit->width-1) >> 3;
|
||
|
|
||
|
count = last - first;
|
||
|
|
||
|
if ( blit->right_clip )
|
||
|
count++;
|
||
|
|
||
|
y = blit->height;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
unsigned int old;
|
||
|
int shift2 = (8-shift);
|
||
|
|
||
|
if ( left_clip )
|
||
|
old = (*_read++) << shift2;
|
||
|
else
|
||
|
old = 0;
|
||
|
|
||
|
x = count;
|
||
|
while ( x > 0 )
|
||
|
{
|
||
|
unsigned char val;
|
||
|
|
||
|
val = *_read++;
|
||
|
*_write++ |= (unsigned char)( (val >> shift) | old );
|
||
|
old = val << shift2;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
if ( !blit->right_clip )
|
||
|
*_write |= (unsigned char)old;
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
|
||
|
} while ( y > 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_mono_to_pal8 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
static
|
||
|
void blit_mono_to_pal8( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int x, y, shift;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + (blit->xread >> 3);
|
||
|
write = blit->write + blit->xwrite;
|
||
|
shift = blit->xread & 7;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
unsigned long val = (*_read++ | 0x100) << shift;
|
||
|
|
||
|
x = blit->width;
|
||
|
do
|
||
|
{
|
||
|
if (val & 0x10000)
|
||
|
val = *_read++ | 0x100;
|
||
|
|
||
|
if ( val & 0x80 )
|
||
|
*_write = (unsigned char)color.value;
|
||
|
|
||
|
val <<= 1;
|
||
|
_write++;
|
||
|
|
||
|
} while ( --x > 0 );
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
} while ( y > 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_mono_to_pal4 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
static
|
||
|
void blit_mono_to_pal4( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int x, y, phase,shift;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
unsigned int col;
|
||
|
|
||
|
|
||
|
col = color.value & 15;
|
||
|
read = blit->read + (blit->xread >> 3);
|
||
|
write = blit->write + (blit->xwrite >> 1);
|
||
|
|
||
|
/* now begin blit */
|
||
|
shift = blit->xread & 7;
|
||
|
phase = blit->xwrite & 1;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int _phase = phase;
|
||
|
unsigned long val = (*_read++ | 0x100) << shift;
|
||
|
|
||
|
x = blit->width;
|
||
|
do
|
||
|
{
|
||
|
if (val & 0x10000)
|
||
|
val = *_read++ | 0x100;
|
||
|
|
||
|
if ( val & 0x80 )
|
||
|
{
|
||
|
if ( _phase )
|
||
|
*_write = (unsigned char)((*_write & 0xF0) | col);
|
||
|
else
|
||
|
*_write = (unsigned char)((*_write & 0x0F) | (col << 4));
|
||
|
}
|
||
|
|
||
|
val <<= 1;
|
||
|
|
||
|
_write += _phase;
|
||
|
_phase ^= 1;
|
||
|
x--;
|
||
|
} while ( x > 0 );
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
} while ( y > 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_mono_to_rgb16 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
static
|
||
|
void blit_mono_to_rgb16( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int x, y,shift;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + (blit->xread >> 3);
|
||
|
write = blit->write + blit->xwrite*2;
|
||
|
shift = blit->xread & 7;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
unsigned long val = (*_read++ | 0x100) << shift;
|
||
|
|
||
|
x = blit->width;
|
||
|
do
|
||
|
{
|
||
|
if (val & 0x10000)
|
||
|
val = *_read++ | 0x100;
|
||
|
|
||
|
if ( val & 0x80 )
|
||
|
*(short*)_write = (short)color.value;
|
||
|
|
||
|
val <<= 1;
|
||
|
_write +=2;
|
||
|
x--;
|
||
|
} while ( x > 0 );
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
} while ( y > 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_mono_to_rgb24 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
static
|
||
|
void blit_mono_to_rgb24( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int x, y, shift;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + (blit->xread >> 3);
|
||
|
write = blit->write + blit->xwrite*3;
|
||
|
shift = blit->xread & 7;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
unsigned long val = (*_read++ | 0x100) << shift;
|
||
|
|
||
|
x = blit->width;
|
||
|
do
|
||
|
{
|
||
|
if (val & 0x10000)
|
||
|
val = *_read++ | 0x100;
|
||
|
|
||
|
if ( val & 0x80 )
|
||
|
{
|
||
|
_write[0] = color.chroma[0];
|
||
|
_write[1] = color.chroma[1];
|
||
|
_write[2] = color.chroma[2];
|
||
|
}
|
||
|
|
||
|
val <<= 1;
|
||
|
_write += 3;
|
||
|
x--;
|
||
|
} while ( x > 0 );
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
} while ( y > 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_mono_to_rgb32 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
static
|
||
|
void blit_mono_to_rgb32( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int x, y,shift;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + ( blit->xread >> 3 );
|
||
|
write = blit->write + blit->xwrite*4;
|
||
|
shift = blit->xread & 7;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
unsigned long val = ( *_read++ | 0x100L ) << shift;
|
||
|
|
||
|
x = blit->width;
|
||
|
do
|
||
|
{
|
||
|
if ( val & 0x10000 )
|
||
|
val = *_read++ | 0x100L;
|
||
|
|
||
|
if ( val & 0x80 )
|
||
|
{
|
||
|
/* this could be greatly optimized as */
|
||
|
/* */
|
||
|
/* *(long*)_write = color.value */
|
||
|
/* */
|
||
|
/* but it wouldn't work on 64-bits systems... stupid C types! */
|
||
|
_write[0] = color.chroma[0];
|
||
|
_write[1] = color.chroma[1];
|
||
|
_write[2] = color.chroma[2];
|
||
|
_write[3] = color.chroma[3];
|
||
|
}
|
||
|
|
||
|
val <<= 1;
|
||
|
_write += 4;
|
||
|
x--;
|
||
|
|
||
|
} while ( x > 0 );
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
|
||
|
} while ( y > 0 );
|
||
|
}
|
||
|
|
||
|
|
||
|
static
|
||
|
const grBlitterFunc gr_mono_blitters[gr_pixel_mode_max] =
|
||
|
{
|
||
|
0,
|
||
|
blit_mono_to_mono,
|
||
|
blit_mono_to_pal4,
|
||
|
blit_mono_to_pal8,
|
||
|
blit_mono_to_pal8,
|
||
|
blit_mono_to_rgb16,
|
||
|
blit_mono_to_rgb16,
|
||
|
blit_mono_to_rgb24,
|
||
|
blit_mono_to_rgb32
|
||
|
};
|
||
|
|
||
|
|
||
|
/*******************************************************************/
|
||
|
/* */
|
||
|
/* Saturation tables */
|
||
|
/* */
|
||
|
/*******************************************************************/
|
||
|
|
||
|
typedef struct grSaturation_
|
||
|
{
|
||
|
int count;
|
||
|
const byte* table;
|
||
|
|
||
|
} grSaturation;
|
||
|
|
||
|
|
||
|
static
|
||
|
const byte gr_saturation_5[8] = { 0, 1, 2, 3, 4, 4, 4, 4 };
|
||
|
|
||
|
|
||
|
static
|
||
|
const byte gr_saturation_17[32] =
|
||
|
{
|
||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||
|
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||
|
};
|
||
|
|
||
|
|
||
|
static
|
||
|
grSaturation gr_saturations[ GR_MAX_SATURATIONS ] =
|
||
|
{
|
||
|
{ 5, gr_saturation_5 },
|
||
|
{ 17, gr_saturation_17 }
|
||
|
};
|
||
|
|
||
|
static
|
||
|
int gr_num_saturations = 2;
|
||
|
|
||
|
static
|
||
|
grSaturation* gr_last_saturation = gr_saturations;
|
||
|
|
||
|
|
||
|
extern
|
||
|
const byte* grGetSaturation( int num_grays )
|
||
|
{
|
||
|
/* first of all, scan the current saturations table */
|
||
|
grSaturation* sat = gr_saturations;
|
||
|
grSaturation* limit = sat + gr_num_saturations;
|
||
|
|
||
|
if ( num_grays < 2 )
|
||
|
{
|
||
|
grError = gr_err_bad_argument;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
for ( ; sat < limit; sat++ )
|
||
|
{
|
||
|
if ( sat->count == num_grays )
|
||
|
{
|
||
|
gr_last_saturation = sat;
|
||
|
return sat->table;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* not found, simply create a new entry if there is room */
|
||
|
if (gr_num_saturations < GR_MAX_SATURATIONS)
|
||
|
{
|
||
|
int i;
|
||
|
const byte* table;
|
||
|
|
||
|
table = (const byte*)grAlloc( (3*num_grays-1)*sizeof(byte) );
|
||
|
if (!table) return 0;
|
||
|
|
||
|
sat->count = num_grays;
|
||
|
sat->table = table;
|
||
|
|
||
|
for ( i = 0; i < num_grays; i++, table++ )
|
||
|
*(unsigned char*)table = (unsigned char)i;
|
||
|
|
||
|
for ( i = 2*num_grays-1; i > 0; i--, table++ )
|
||
|
*(unsigned char*)table = (unsigned char)(num_grays-1);
|
||
|
|
||
|
gr_num_saturations++;
|
||
|
gr_last_saturation = sat;
|
||
|
return sat->table;
|
||
|
}
|
||
|
grError = gr_err_saturation_overflow;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*******************************************************************/
|
||
|
/* */
|
||
|
/* conversion tables */
|
||
|
/* */
|
||
|
/*******************************************************************/
|
||
|
|
||
|
typedef struct grConversion_
|
||
|
{
|
||
|
int target_grays;
|
||
|
int source_grays;
|
||
|
const byte* table;
|
||
|
|
||
|
} grConversion;
|
||
|
|
||
|
|
||
|
|
||
|
static
|
||
|
const byte gr_gray5_to_gray17[5] = { 0, 4, 8, 12, 16 };
|
||
|
|
||
|
|
||
|
static
|
||
|
const byte gr_gray5_to_gray128[5] = { 0, 32, 64, 96, 127 };
|
||
|
|
||
|
|
||
|
static
|
||
|
const unsigned char gr_gray17_to_gray128[17] =
|
||
|
{
|
||
|
0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 127
|
||
|
};
|
||
|
|
||
|
static
|
||
|
grConversion gr_conversions[ GR_MAX_CONVERSIONS ] =
|
||
|
{
|
||
|
{ 17, 5, gr_gray5_to_gray17 },
|
||
|
{ 128, 5, gr_gray5_to_gray128 },
|
||
|
{ 128, 17, gr_gray17_to_gray128 }
|
||
|
};
|
||
|
|
||
|
static
|
||
|
int gr_num_conversions = 3;
|
||
|
|
||
|
static
|
||
|
grConversion* gr_last_conversion = gr_conversions;
|
||
|
|
||
|
|
||
|
extern
|
||
|
const byte* grGetConversion( int target_grays,
|
||
|
int source_grays )
|
||
|
{
|
||
|
grConversion* conv = gr_conversions;
|
||
|
grConversion* limit = conv + gr_num_conversions;
|
||
|
|
||
|
if ( target_grays < 2 || source_grays < 2 )
|
||
|
{
|
||
|
grError = gr_err_bad_argument;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* otherwise, scan table */
|
||
|
for ( ; conv < limit; conv++ )
|
||
|
{
|
||
|
if ( conv->target_grays == target_grays &&
|
||
|
conv->source_grays == source_grays )
|
||
|
{
|
||
|
gr_last_conversion = conv;
|
||
|
return conv->table;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* not found, add a new conversion to the table */
|
||
|
if (gr_num_conversions < GR_MAX_CONVERSIONS)
|
||
|
{
|
||
|
const byte* table;
|
||
|
int n;
|
||
|
|
||
|
table = (const byte*)grAlloc( source_grays*sizeof(byte) );
|
||
|
if (!table)
|
||
|
return 0;
|
||
|
|
||
|
conv->target_grays = target_grays;
|
||
|
conv->source_grays = source_grays;
|
||
|
conv->table = table;
|
||
|
|
||
|
for ( n = 0; n < source_grays; n++ )
|
||
|
((unsigned char*)table)[n] = (unsigned char)(n*(target_grays-1) /
|
||
|
(source_grays-1));
|
||
|
|
||
|
gr_num_conversions++;
|
||
|
gr_last_conversion = conv;
|
||
|
return table;
|
||
|
}
|
||
|
grError = gr_err_conversion_overflow;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_gray_to_gray */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
static
|
||
|
void blit_gray_to_gray( grBlitter* blit,
|
||
|
const byte* saturation,
|
||
|
const byte* conversion )
|
||
|
{
|
||
|
int y;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
unsigned char max1;
|
||
|
unsigned char max2;
|
||
|
|
||
|
max1 = (unsigned char)(blit->source.grays-1);
|
||
|
max2 = (unsigned char)(blit->target.grays-1);
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + blit->xwrite;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
#ifdef GR_CONFIG_GRAY_SKIP_WHITE
|
||
|
unsigned char val = *_read;
|
||
|
|
||
|
if (val)
|
||
|
{
|
||
|
if (val == max)
|
||
|
*_write = max2;
|
||
|
else
|
||
|
*_write = saturation[ (int)*_write + conversion[ *_read ] ];
|
||
|
}
|
||
|
#else
|
||
|
*_write = saturation[ (int)*_write + conversion[ *_read ] ];
|
||
|
#endif
|
||
|
_write++;
|
||
|
_read++;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_gray_to_gray_simple */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
static
|
||
|
void blit_gray_to_gray_simple( grBlitter* blit,
|
||
|
const byte* saturation )
|
||
|
{
|
||
|
int y;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
unsigned char max;
|
||
|
|
||
|
max = (unsigned char)(blit->source.grays-1);
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + blit->xwrite;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
#ifdef GR_CONFIG_GRAY_SKIP_WHITE
|
||
|
unsigned char val = *_read;
|
||
|
|
||
|
if (val)
|
||
|
{
|
||
|
if (val == max)
|
||
|
*_write = val;
|
||
|
else
|
||
|
*_write = saturation[ (int)*_write + *_read ];
|
||
|
}
|
||
|
#else
|
||
|
*_write = saturation[ (int)*_write + *_read ];
|
||
|
#endif
|
||
|
_write++;
|
||
|
_read++;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#define compose_pixel_full( a, b, n0, n1, n2, max ) \
|
||
|
{ \
|
||
|
int d, half = max >> 1; \
|
||
|
\
|
||
|
\
|
||
|
d = (int)b.chroma[0] - a.chroma[0]; \
|
||
|
a.chroma[0] += (unsigned char)((n0*d + half)/max); \
|
||
|
\
|
||
|
d = (int)b.chroma[1] - a.chroma[1]; \
|
||
|
a.chroma[1] += (unsigned char)((n1*d + half)/max); \
|
||
|
\
|
||
|
d = (int)b.chroma[2] - a.chroma[2]; \
|
||
|
a.chroma[2] += (unsigned char)((n2*d + half)/max); \
|
||
|
}
|
||
|
|
||
|
#define compose_pixel( a, b, n, max ) \
|
||
|
compose_pixel_full( a, b, n, n, n, max )
|
||
|
|
||
|
|
||
|
#define extract555( pixel, color ) \
|
||
|
color.chroma[0] = (unsigned char)((pixel >> 10) & 0x1F); \
|
||
|
color.chroma[1] = (unsigned char)((pixel >> 5) & 0x1F); \
|
||
|
color.chroma[2] = (unsigned char)((pixel ) & 0x1F);
|
||
|
|
||
|
|
||
|
#define extract565( pixel, color ) \
|
||
|
color.chroma[0] = (unsigned char)((pixel >> 11) & 0x1F); \
|
||
|
color.chroma[1] = (unsigned char)((pixel >> 5) & 0x3F); \
|
||
|
color.chroma[2] = (unsigned char)((pixel ) & 0x1F);
|
||
|
|
||
|
|
||
|
#define inject555( color ) \
|
||
|
( ( (unsigned short)color.chroma[0] << 10 ) | \
|
||
|
( (unsigned short)color.chroma[1] << 5 ) | \
|
||
|
color.chroma[2] )
|
||
|
|
||
|
|
||
|
#define inject565( color ) \
|
||
|
( ( (unsigned short)color.chroma[0] << 11 ) | \
|
||
|
( (unsigned short)color.chroma[1] << 5 ) | \
|
||
|
color.chroma[2] )
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_gray_to_555 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
#ifdef GRAY8
|
||
|
static
|
||
|
void blit_gray8_to_555( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int y;
|
||
|
int sr = (color.chroma[0] << 8) & 0x7C00;
|
||
|
int sg = (color.chroma[1] << 2) & 0x03E0;
|
||
|
int sb = (color.chroma[2] ) & 0x001F;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
long color2;
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + 2*blit->xwrite;
|
||
|
|
||
|
color2 = color.value;
|
||
|
extract565( color2, color );
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
unsigned char val;
|
||
|
|
||
|
val = *_read;
|
||
|
if (val)
|
||
|
{
|
||
|
unsigned short* pixel = (unsigned short*)_write;
|
||
|
|
||
|
if (val >= 254 )
|
||
|
{
|
||
|
pixel[0] = (short)color2;
|
||
|
}
|
||
|
else if ( val >= 2 )
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
int pix = (int)*pixel;
|
||
|
int dr = pix & 0x7C00;
|
||
|
int dg = pix & 0x03E0;
|
||
|
int db = pix & 0x001F;
|
||
|
|
||
|
dr = pix & 0x7C00;
|
||
|
dr += ((sr-dr)*val) >> 8;
|
||
|
dr &= 0xF800;
|
||
|
|
||
|
dg = pix & 0x03E0;
|
||
|
dg += ((sg-dg)*val) >> 8;
|
||
|
dg &= 0x7E0;
|
||
|
|
||
|
db = pix & 0x001F;
|
||
|
db += ((sb-db)*val) >> 8;
|
||
|
db += 0x001F;
|
||
|
|
||
|
*pixel = (short)( dr | dg | db );
|
||
|
}
|
||
|
}
|
||
|
_write +=2;
|
||
|
_read ++;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
|
||
|
}
|
||
|
#endif /* GRAY8 */
|
||
|
|
||
|
static
|
||
|
void blit_gray_to_555( grBlitter* blit,
|
||
|
grColor color,
|
||
|
int max )
|
||
|
{
|
||
|
int y;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
long color2;
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + 2*blit->xwrite;
|
||
|
|
||
|
/* convert color to R:G:B triplet */
|
||
|
color2 = color.value;
|
||
|
extract555( color2, color );
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
unsigned char val;
|
||
|
|
||
|
val = *_read;
|
||
|
if (val)
|
||
|
{
|
||
|
unsigned short* pixel = (unsigned short*)_write;
|
||
|
|
||
|
if (val == max)
|
||
|
{
|
||
|
pixel[0] = (short)color2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
unsigned short pix16 = *pixel;
|
||
|
grColor pix;
|
||
|
|
||
|
extract555( pix16, pix );
|
||
|
|
||
|
compose_pixel( pix, color, val, max );
|
||
|
*pixel = (unsigned short)(inject555(pix));
|
||
|
}
|
||
|
}
|
||
|
_write += 2;
|
||
|
_read ++;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_gray_to_565 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
#ifdef GRAY8
|
||
|
static
|
||
|
void blit_gray8_to_565( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int y;
|
||
|
int sr = (color.chroma[0] << 8) & 0xF800;
|
||
|
int sg = (color.chroma[1] << 2) & 0x07E0;
|
||
|
int sb = (color.chroma[2] ) & 0x001F;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
long color2;
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + 2*blit->xwrite;
|
||
|
|
||
|
color2 = color.value;
|
||
|
extract565( color2, color );
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
unsigned char val;
|
||
|
|
||
|
val = *_read;
|
||
|
if (val)
|
||
|
{
|
||
|
unsigned short* pixel = (unsigned short*)_write;
|
||
|
|
||
|
if (val >= 254 )
|
||
|
{
|
||
|
pixel[0] = (short)color2;
|
||
|
}
|
||
|
else if ( val >= 2 )
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
int pix = (int)*pixel;
|
||
|
int dr = pix & 0xF800;
|
||
|
int dg = pix & 0x07E0;
|
||
|
int db = pix & 0x001F;
|
||
|
|
||
|
dr = pix & 0xF800;
|
||
|
dr += ((sr-dr)*val) >> 8;
|
||
|
dr &= 0xF800;
|
||
|
|
||
|
dg = pix & 0x07E0;
|
||
|
dg += ((sg-dg)*val) >> 8;
|
||
|
dg &= 0x7E0;
|
||
|
|
||
|
db = pix & 0x001F;
|
||
|
db += ((sb-db)*val) >> 8;
|
||
|
db += 0x001F;
|
||
|
|
||
|
*pixel = (short)( dr | dg | db );
|
||
|
}
|
||
|
}
|
||
|
_write +=2;
|
||
|
_read ++;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static
|
||
|
void blit_gray_to_565( grBlitter* blit,
|
||
|
grColor color,
|
||
|
int max )
|
||
|
{
|
||
|
int y;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
long color2;
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + 2*blit->xwrite;
|
||
|
|
||
|
color2 = color.value;
|
||
|
extract565( color2, color );
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
unsigned char val;
|
||
|
|
||
|
val = *_read;
|
||
|
if (val)
|
||
|
{
|
||
|
unsigned short* pixel = (unsigned short*)_write;
|
||
|
|
||
|
if (val == max)
|
||
|
{
|
||
|
pixel[0] = (short)color2;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
unsigned short pix16 = *pixel;
|
||
|
grColor pix;
|
||
|
|
||
|
extract565( pix16, pix );
|
||
|
|
||
|
compose_pixel( pix, color, val, max );
|
||
|
*pixel = (short)inject565( pix );
|
||
|
}
|
||
|
}
|
||
|
_write +=2;
|
||
|
_read ++;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_gray_to_24 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
#ifdef GRAY8
|
||
|
static void
|
||
|
blit_gray8_to_24( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int y;
|
||
|
int sr = color.chroma[0];
|
||
|
int sg = color.chroma[1];
|
||
|
int sb = color.chroma[2];
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + 3*blit->xwrite;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
unsigned char val;
|
||
|
|
||
|
val = *_read;
|
||
|
if (val)
|
||
|
{
|
||
|
if (val >= 254)
|
||
|
{
|
||
|
_write[0] = (unsigned char)sr;
|
||
|
_write[1] = (unsigned char)sg;
|
||
|
_write[2] = (unsigned char)sb;
|
||
|
}
|
||
|
else if ( val >= 2 )
|
||
|
{
|
||
|
int dr = _write[0];
|
||
|
int dg = _write[1];
|
||
|
int db = _write[2];
|
||
|
|
||
|
dr += ((sr-dr)*val) >> 8;
|
||
|
dg += ((sg-dg)*val) >> 8;
|
||
|
db += ((sb-db)*val) >> 8;
|
||
|
|
||
|
_write[0] = (unsigned char)dr;
|
||
|
_write[1] = (unsigned char)dg,
|
||
|
_write[2] = (unsigned char)db;
|
||
|
}
|
||
|
}
|
||
|
_write += 3;
|
||
|
_read ++;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
#endif /* GRAY8 */
|
||
|
|
||
|
|
||
|
static
|
||
|
void blit_gray_to_24( grBlitter* blit,
|
||
|
grColor color,
|
||
|
int max )
|
||
|
{
|
||
|
int y;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + 3*blit->xwrite;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
unsigned char val;
|
||
|
|
||
|
val = *_read;
|
||
|
if (val)
|
||
|
{
|
||
|
if (val == max)
|
||
|
{
|
||
|
_write[0] = color.chroma[0];
|
||
|
_write[1] = color.chroma[1];
|
||
|
_write[2] = color.chroma[2];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
grColor pix;
|
||
|
|
||
|
pix.chroma[0] = _write[0];
|
||
|
pix.chroma[1] = _write[1];
|
||
|
pix.chroma[2] = _write[2];
|
||
|
|
||
|
compose_pixel( pix, color, val, max );
|
||
|
|
||
|
_write[0] = pix.chroma[0];
|
||
|
_write[1] = pix.chroma[1];
|
||
|
_write[2] = pix.chroma[2];
|
||
|
}
|
||
|
}
|
||
|
_write += 3;
|
||
|
_read ++;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_gray_to_32 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
static
|
||
|
void blit_gray_to_32( grBlitter* blit,
|
||
|
grColor color,
|
||
|
int max )
|
||
|
{
|
||
|
int y;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + 4*blit->xwrite;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
unsigned char val;
|
||
|
|
||
|
val = *_read;
|
||
|
if (val)
|
||
|
{
|
||
|
if (val == max)
|
||
|
{
|
||
|
_write[0] = color.chroma[0];
|
||
|
_write[1] = color.chroma[1];
|
||
|
_write[2] = color.chroma[2];
|
||
|
_write[3] = color.chroma[3];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
grColor pix;
|
||
|
|
||
|
pix.chroma[0] = _write[0];
|
||
|
pix.chroma[1] = _write[1];
|
||
|
pix.chroma[2] = _write[2];
|
||
|
|
||
|
compose_pixel( pix, color, val, max );
|
||
|
|
||
|
_write[0] = pix.chroma[0];
|
||
|
_write[1] = pix.chroma[1];
|
||
|
_write[2] = pix.chroma[2];
|
||
|
}
|
||
|
}
|
||
|
_write += 4;
|
||
|
_read ++;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
static
|
||
|
void blit_gray8_to_32( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
blit_gray_to_32( blit, color, 255 );
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_lcd_to_24 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
#ifdef GRAY8
|
||
|
static void
|
||
|
blit_lcd8_to_24( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int y;
|
||
|
int sr = color.chroma[0];
|
||
|
int sg = color.chroma[1];
|
||
|
int sb = color.chroma[2];
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + 3*blit->xread;
|
||
|
write = blit->write + 3*blit->xwrite;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
int val0, val1, val2;
|
||
|
|
||
|
val0 = _read[0];
|
||
|
val1 = _read[1];
|
||
|
val2 = _read[2];
|
||
|
|
||
|
if ( val0 | val1 | val2 )
|
||
|
{
|
||
|
if ( val0 == val1 &&
|
||
|
val0 == val2 &&
|
||
|
val0 == 255 )
|
||
|
{
|
||
|
_write[0] = (unsigned char)sr;
|
||
|
_write[1] = (unsigned char)sg;
|
||
|
_write[2] = (unsigned char)sb;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
int dr, dg, db;
|
||
|
|
||
|
dr = _write[0];
|
||
|
dr += (sr-dr)*val0 >> 8;
|
||
|
|
||
|
dg = _write[1];
|
||
|
dg += (sg-dg)*val1 >> 8;
|
||
|
|
||
|
db = _write[1];
|
||
|
db += (sb-db)*val2 >> 8;
|
||
|
|
||
|
_write[0] = dr;
|
||
|
_write[1] = dg;
|
||
|
_write[2] = db;
|
||
|
}
|
||
|
}
|
||
|
_write += 3;
|
||
|
_read += 3;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
#endif /* GRAY8 */
|
||
|
|
||
|
static void
|
||
|
blit_lcd_to_24( grBlitter* blit,
|
||
|
grColor color,
|
||
|
int max )
|
||
|
{
|
||
|
int y;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + 3*blit->xread;
|
||
|
write = blit->write + 3*blit->xwrite;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
int val0, val1, val2;
|
||
|
|
||
|
val0 = _read[0];
|
||
|
val1 = _read[1];
|
||
|
val2 = _read[2];
|
||
|
|
||
|
if ( val0 | val1 | val2 )
|
||
|
{
|
||
|
if ( val0 == val1 &&
|
||
|
val0 == val2 &&
|
||
|
val0 == max )
|
||
|
{
|
||
|
_write[0] = color.chroma[0];
|
||
|
_write[1] = color.chroma[1];
|
||
|
_write[2] = color.chroma[2];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
grColor pix;
|
||
|
|
||
|
pix.chroma[0] = _write[0];
|
||
|
pix.chroma[1] = _write[1];
|
||
|
pix.chroma[2] = _write[2];
|
||
|
|
||
|
compose_pixel_full( pix, color, val0, val1, val2, max );
|
||
|
|
||
|
_write[0] = pix.chroma[0];
|
||
|
_write[1] = pix.chroma[1];
|
||
|
_write[2] = pix.chroma[2];
|
||
|
}
|
||
|
}
|
||
|
_write += 3;
|
||
|
_read += 3;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef GRAY8
|
||
|
static void
|
||
|
blit_lcd28_to_24( grBlitter* blit,
|
||
|
grColor color )
|
||
|
{
|
||
|
int y;
|
||
|
int sr = color.chroma[0];
|
||
|
int sg = color.chroma[1];
|
||
|
int sb = color.chroma[2];
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + 3*blit->xread;
|
||
|
write = blit->write + 3*blit->xwrite;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
int val0, val1, val2;
|
||
|
|
||
|
val0 = _read[2];
|
||
|
val1 = _read[1];
|
||
|
val2 = _read[0];
|
||
|
|
||
|
if ( val0 | val1 | val2 )
|
||
|
{
|
||
|
if ( val0 == val1 &&
|
||
|
val0 == val2 &&
|
||
|
val0 == 255 )
|
||
|
{
|
||
|
_write[0] = (unsigned char)sr;
|
||
|
_write[1] = (unsigned char)sg;
|
||
|
_write[2] = (unsigned char)sb;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
int dr, dg, db;
|
||
|
|
||
|
dr = _write[0];
|
||
|
dr += (sr-dr)*val0 >> 8;
|
||
|
|
||
|
dg = _write[1];
|
||
|
dg += (sg-dg)*val1 >> 8;
|
||
|
|
||
|
db = _write[1];
|
||
|
db += (sb-db)*val2 >> 8;
|
||
|
|
||
|
_write[0] = dr;
|
||
|
_write[1] = dg;
|
||
|
_write[2] = db;
|
||
|
}
|
||
|
}
|
||
|
_write += 3;
|
||
|
_read += 3;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
#endif /* GRAY8 */
|
||
|
|
||
|
static void
|
||
|
blit_lcd2_to_24( grBlitter* blit,
|
||
|
grColor color,
|
||
|
int max )
|
||
|
{
|
||
|
int y;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
|
||
|
read = blit->read + 3*blit->xread;
|
||
|
write = blit->write + 3*blit->xwrite;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
int val0, val1, val2;
|
||
|
|
||
|
val0 = _read[2];
|
||
|
val1 = _read[1];
|
||
|
val2 = _read[0];
|
||
|
|
||
|
if ( val0 | val1 | val2 )
|
||
|
{
|
||
|
if ( val0 == val1 &&
|
||
|
val0 == val2 &&
|
||
|
val0 == max )
|
||
|
{
|
||
|
_write[0] = color.chroma[0];
|
||
|
_write[1] = color.chroma[1];
|
||
|
_write[2] = color.chroma[2];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
grColor pix;
|
||
|
|
||
|
pix.chroma[0] = _write[0];
|
||
|
pix.chroma[1] = _write[1];
|
||
|
pix.chroma[2] = _write[2];
|
||
|
|
||
|
compose_pixel_full( pix, color, val0, val1, val2, max );
|
||
|
|
||
|
_write[0] = pix.chroma[0];
|
||
|
_write[1] = pix.chroma[1];
|
||
|
_write[2] = pix.chroma[2];
|
||
|
}
|
||
|
}
|
||
|
_write += 3;
|
||
|
_read += 3;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += blit->read_line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> blit_lcdv_to_24 */
|
||
|
/* */
|
||
|
/**************************************************************************/
|
||
|
|
||
|
static void
|
||
|
blit_lcdv_to_24( grBlitter* blit,
|
||
|
grColor color,
|
||
|
int max )
|
||
|
{
|
||
|
int y;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
long line;
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + 3*blit->xwrite;
|
||
|
line = blit->read_line;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
unsigned char val0, val1, val2;
|
||
|
|
||
|
val0 = _read[0*line];
|
||
|
val1 = _read[1*line];
|
||
|
val2 = _read[2*line];
|
||
|
|
||
|
if ( val0 | val1 | val2 )
|
||
|
{
|
||
|
if ( val0 == val1 &&
|
||
|
val0 == val2 &&
|
||
|
val0 == max )
|
||
|
{
|
||
|
_write[0] = color.chroma[0];
|
||
|
_write[1] = color.chroma[1];
|
||
|
_write[2] = color.chroma[2];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
grColor pix;
|
||
|
|
||
|
pix.chroma[0] = _write[0];
|
||
|
pix.chroma[1] = _write[1];
|
||
|
pix.chroma[2] = _write[2];
|
||
|
|
||
|
compose_pixel_full( pix, color, val0, val1, val2, max );
|
||
|
|
||
|
_write[0] = pix.chroma[0];
|
||
|
_write[1] = pix.chroma[1];
|
||
|
_write[2] = pix.chroma[2];
|
||
|
}
|
||
|
}
|
||
|
_write += 3;
|
||
|
_read += 1;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += 3*line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
blit_lcdv2_to_24( grBlitter* blit,
|
||
|
grColor color,
|
||
|
int max )
|
||
|
{
|
||
|
int y;
|
||
|
unsigned char* read;
|
||
|
unsigned char* write;
|
||
|
long line;
|
||
|
|
||
|
read = blit->read + blit->xread;
|
||
|
write = blit->write + 3*blit->xwrite;
|
||
|
line = blit->read_line;
|
||
|
|
||
|
y = blit->height;
|
||
|
do
|
||
|
{
|
||
|
unsigned char* _read = read;
|
||
|
unsigned char* _write = write;
|
||
|
int x = blit->width;
|
||
|
|
||
|
while (x > 0)
|
||
|
{
|
||
|
unsigned char val0, val1, val2;
|
||
|
|
||
|
val0 = _read[2*line];
|
||
|
val1 = _read[1*line];
|
||
|
val2 = _read[0*line];
|
||
|
|
||
|
if ( val0 | val1 | val2 )
|
||
|
{
|
||
|
if ( val0 == val1 &&
|
||
|
val0 == val2 &&
|
||
|
val0 == max )
|
||
|
{
|
||
|
_write[0] = color.chroma[0];
|
||
|
_write[1] = color.chroma[1];
|
||
|
_write[2] = color.chroma[2];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* compose gray value */
|
||
|
grColor pix;
|
||
|
|
||
|
pix.chroma[0] = _write[0];
|
||
|
pix.chroma[1] = _write[1];
|
||
|
pix.chroma[2] = _write[2];
|
||
|
|
||
|
compose_pixel_full( pix, color, val0, val1, val2, max );
|
||
|
|
||
|
_write[0] = pix.chroma[0];
|
||
|
_write[1] = pix.chroma[1];
|
||
|
_write[2] = pix.chroma[2];
|
||
|
}
|
||
|
}
|
||
|
_write += 3;
|
||
|
_read += 1;
|
||
|
x--;
|
||
|
}
|
||
|
|
||
|
read += 3*line;
|
||
|
write += blit->write_line;
|
||
|
y--;
|
||
|
}
|
||
|
while (y > 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**********************************************************************
|
||
|
*
|
||
|
* <Function>
|
||
|
* grBlitGlyphBitmap
|
||
|
*
|
||
|
* <Description>
|
||
|
* writes a given glyph bitmap to a target surface.
|
||
|
*
|
||
|
* <Input>
|
||
|
* surface :: handle to target surface
|
||
|
* x :: position of left-most pixel of glyph image in surface
|
||
|
* y :: position of top-most pixel of glyph image in surface
|
||
|
* bitmap :: source glyph image
|
||
|
*
|
||
|
* <Return>
|
||
|
* Error code. 0 means success
|
||
|
*
|
||
|
**********************************************************************/
|
||
|
|
||
|
typedef void (*grColorGlyphBlitter)( grBlitter* blit,
|
||
|
grColor color,
|
||
|
int max_gray );
|
||
|
|
||
|
static
|
||
|
const grColorGlyphBlitter gr_color_blitters[gr_pixel_mode_max] =
|
||
|
{
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
blit_gray_to_555,
|
||
|
blit_gray_to_565,
|
||
|
blit_gray_to_24,
|
||
|
blit_gray_to_32
|
||
|
};
|
||
|
|
||
|
#ifdef GRAY8
|
||
|
typedef void (*grGray8GlyphBlitter)( grBlitter* blit,
|
||
|
grColor color );
|
||
|
|
||
|
static
|
||
|
const grGray8GlyphBlitter gr_gray8_blitters[gr_pixel_mode_max] =
|
||
|
{
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
0,
|
||
|
blit_gray8_to_555,
|
||
|
blit_gray8_to_565,
|
||
|
blit_gray8_to_24,
|
||
|
blit_gray8_to_32
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#include "gblblit.h"
|
||
|
|
||
|
static double gr_glyph_gamma = 1.0;
|
||
|
|
||
|
void grSetGlyphGamma( double gamma )
|
||
|
{
|
||
|
gr_glyph_gamma = gamma;
|
||
|
}
|
||
|
|
||
|
|
||
|
int
|
||
|
grBlitGlyphToBitmap( grBitmap* target,
|
||
|
grBitmap* glyph,
|
||
|
grPos x,
|
||
|
grPos y,
|
||
|
grColor color )
|
||
|
{
|
||
|
grBlitter blit;
|
||
|
grPixelMode mode;
|
||
|
|
||
|
|
||
|
/* check arguments */
|
||
|
if ( !target || !glyph )
|
||
|
{
|
||
|
grError = gr_err_bad_argument;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* short cut to alpha blender for certain glyph types
|
||
|
*/
|
||
|
{
|
||
|
GBlenderSourceFormat src_format;
|
||
|
GBlenderTargetFormat dst_format;
|
||
|
int width, height;
|
||
|
GBlenderBlitRec gblit[1];
|
||
|
GBlenderPixel gcolor;
|
||
|
static GBlenderRec gblender[1];
|
||
|
static double gblender_gamma = -100.0;
|
||
|
|
||
|
if ( glyph->grays != 256 )
|
||
|
goto DefaultBlit;
|
||
|
|
||
|
switch ( glyph->mode )
|
||
|
{
|
||
|
case gr_pixel_mode_gray: src_format = GBLENDER_SOURCE_GRAY8; break;
|
||
|
case gr_pixel_mode_lcd: src_format = GBLENDER_SOURCE_HRGB; break;
|
||
|
case gr_pixel_mode_lcdv: src_format = GBLENDER_SOURCE_VRGB; break;
|
||
|
case gr_pixel_mode_lcd2: src_format = GBLENDER_SOURCE_HBGR; break;
|
||
|
case gr_pixel_mode_lcdv2: src_format = GBLENDER_SOURCE_VBGR; break;
|
||
|
|
||
|
default:
|
||
|
goto DefaultBlit;
|
||
|
}
|
||
|
|
||
|
width = glyph->width;
|
||
|
height = glyph->rows;
|
||
|
|
||
|
if ( glyph->mode == gr_pixel_mode_lcd ||
|
||
|
glyph->mode == gr_pixel_mode_lcd2 )
|
||
|
width /= 3;
|
||
|
|
||
|
if ( glyph->mode == gr_pixel_mode_lcdv ||
|
||
|
glyph->mode == gr_pixel_mode_lcdv2 )
|
||
|
height /= 3;
|
||
|
|
||
|
switch ( target->mode )
|
||
|
{
|
||
|
case gr_pixel_mode_rgb32: dst_format = GBLENDER_TARGET_RGB32; break;
|
||
|
case gr_pixel_mode_rgb24: dst_format = GBLENDER_TARGET_RGB24; break;
|
||
|
case gr_pixel_mode_rgb565: dst_format = GBLENDER_TARGET_RGB565; break;
|
||
|
default:
|
||
|
goto DefaultBlit;
|
||
|
}
|
||
|
|
||
|
/* initialize blender when needed, i.e. when gamma changes
|
||
|
*/
|
||
|
if ( gblender_gamma != gr_glyph_gamma )
|
||
|
{
|
||
|
gblender_gamma = gr_glyph_gamma;
|
||
|
gblender_init( gblender, gblender_gamma );
|
||
|
}
|
||
|
|
||
|
if ( gblender_blit_init( gblit, gblender,
|
||
|
x, y,
|
||
|
src_format,
|
||
|
glyph->buffer,
|
||
|
glyph->pitch,
|
||
|
width,
|
||
|
height,
|
||
|
dst_format,
|
||
|
target->buffer,
|
||
|
target->pitch,
|
||
|
target->width,
|
||
|
target->rows ) < 0 )
|
||
|
{
|
||
|
/* nothing to do */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
gcolor = ((GBlenderPixel)color.chroma[0] << 16) |
|
||
|
((GBlenderPixel)color.chroma[1] << 8 ) |
|
||
|
((GBlenderPixel)color.chroma[2] ) ;
|
||
|
|
||
|
gblender_blit_run( gblit, gcolor );
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
DefaultBlit:
|
||
|
|
||
|
/* set up blitter and compute clipping. Return immediately if needed */
|
||
|
blit.source = *glyph;
|
||
|
blit.target = *target;
|
||
|
mode = target->mode;
|
||
|
|
||
|
if ( compute_clips( &blit, x, y ) )
|
||
|
return 0;
|
||
|
|
||
|
switch ( glyph->mode )
|
||
|
{
|
||
|
case gr_pixel_mode_mono: /* handle monochrome bitmap blitting */
|
||
|
if ( mode <= gr_pixel_mode_none || mode >= gr_pixel_mode_max )
|
||
|
{
|
||
|
grError = gr_err_bad_source_depth;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
gr_mono_blitters[mode]( &blit, color );
|
||
|
break;
|
||
|
|
||
|
case gr_pixel_mode_gray:
|
||
|
if ( glyph->grays > 1 )
|
||
|
{
|
||
|
int target_grays = target->grays;
|
||
|
int source_grays = glyph->grays;
|
||
|
const byte* saturation;
|
||
|
|
||
|
|
||
|
if ( mode == gr_pixel_mode_gray && target_grays > 1 )
|
||
|
{
|
||
|
/* rendering into a gray target - use special composition */
|
||
|
/* routines.. */
|
||
|
if ( gr_last_saturation->count == target_grays )
|
||
|
saturation = gr_last_saturation->table;
|
||
|
else
|
||
|
{
|
||
|
saturation = grGetSaturation( target_grays );
|
||
|
if ( !saturation )
|
||
|
return -3;
|
||
|
}
|
||
|
|
||
|
if ( target_grays == source_grays )
|
||
|
blit_gray_to_gray_simple( &blit, saturation );
|
||
|
else
|
||
|
{
|
||
|
const byte* conversion;
|
||
|
|
||
|
|
||
|
if ( gr_last_conversion->target_grays == target_grays &&
|
||
|
gr_last_conversion->source_grays == source_grays )
|
||
|
conversion = gr_last_conversion->table;
|
||
|
else
|
||
|
{
|
||
|
conversion = grGetConversion( target_grays, source_grays );
|
||
|
if ( !conversion )
|
||
|
return -3;
|
||
|
}
|
||
|
|
||
|
blit_gray_to_gray( &blit, saturation, conversion );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* rendering into a color target */
|
||
|
if ( mode <= gr_pixel_mode_gray ||
|
||
|
mode >= gr_pixel_mode_max )
|
||
|
{
|
||
|
grError = gr_err_bad_target_depth;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
#ifdef GRAY8
|
||
|
if ( source_grays == 256 )
|
||
|
gr_gray8_blitters[mode]( &blit, color );
|
||
|
else
|
||
|
#endif /* GRAY8 */
|
||
|
gr_color_blitters[mode]( &blit, color, source_grays - 1 );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case gr_pixel_mode_lcd:
|
||
|
if ( mode == gr_pixel_mode_rgb24 )
|
||
|
{
|
||
|
#ifdef GRAY8
|
||
|
if ( glyph->grays == 256 )
|
||
|
blit_lcd8_to_24( &blit, color );
|
||
|
else
|
||
|
#endif
|
||
|
if ( glyph->grays > 1 )
|
||
|
blit_lcd_to_24( &blit, color, glyph->grays-1 );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
|
||
|
case gr_pixel_mode_lcdv:
|
||
|
if ( glyph->grays > 1 && mode == gr_pixel_mode_rgb24 )
|
||
|
{
|
||
|
blit_lcdv_to_24( &blit, color, glyph->grays-1 );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case gr_pixel_mode_lcd2:
|
||
|
if ( mode == gr_pixel_mode_rgb24 )
|
||
|
{
|
||
|
#ifdef GRAY8
|
||
|
if ( glyph->grays == 256 )
|
||
|
blit_lcd28_to_24( &blit, color );
|
||
|
else
|
||
|
#endif
|
||
|
if ( glyph->grays > 1 )
|
||
|
blit_lcd2_to_24( &blit, color, glyph->grays-1 );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case gr_pixel_mode_lcdv2:
|
||
|
if ( mode == gr_pixel_mode_rgb24 )
|
||
|
{
|
||
|
if ( glyph->grays > 1 )
|
||
|
blit_lcdv2_to_24( &blit, color, glyph->grays-1 );
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
/* we don't support the blitting of bitmaps of the following */
|
||
|
/* types : pal4, pal8, rgb555, rgb565, rgb24, rgb32 */
|
||
|
/* */
|
||
|
grError = gr_err_bad_source_depth;
|
||
|
return -2;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* End */
|