summaryrefslogtreecommitdiffstats
path: root/kernel/kls_ttf/ftview/grblit.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 17:43:19 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 17:43:19 +0000
commit0292059f4a16434600564cfa3f0ad2309a508a54 (patch)
treed95953cd53011917c4df679b96aedca39401b54f /kernel/kls_ttf/ftview/grblit.cpp
downloadlibksquirrel-0292059f4a16434600564cfa3f0ad2309a508a54.tar.gz
libksquirrel-0292059f4a16434600564cfa3f0ad2309a508a54.zip
Added libksquirrel for KDE3
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/libraries/libksquirrel@1095624 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kernel/kls_ttf/ftview/grblit.cpp')
-rw-r--r--kernel/kls_ttf/ftview/grblit.cpp2068
1 files changed, 2068 insertions, 0 deletions
diff --git a/kernel/kls_ttf/ftview/grblit.cpp b/kernel/kls_ttf/ftview/grblit.cpp
new file mode 100644
index 0000000..18046ab
--- /dev/null
+++ b/kernel/kls_ttf/ftview/grblit.cpp
@@ -0,0 +1,2068 @@
+/****************************************************************************/
+/* */
+/* 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 */