diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 17:43:19 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-24 17:43:19 +0000 |
commit | 0292059f4a16434600564cfa3f0ad2309a508a54 (patch) | |
tree | d95953cd53011917c4df679b96aedca39401b54f /kernel/kls_ttf/ftview/grblit.cpp | |
download | libksquirrel-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.cpp | 2068 |
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 */ |