#include "xttblit.h"
static
void blit_stream( TT_Raster_Map* target,
TT_Byte* source,
TT_Int line_bits,
TT_Int height,
TT_Bool align,
TT_Int x_offset,
TT_Int y_offset,
TT_Bool inverted )
{
TT_Byte* line_buff;
TT_Int line_incr;
TT_Int start_incr;
TT_Int cursor_sign;
TT_UInt acc;
TT_Byte loaded;
TT_Int y;
if ( target->flow == TT_Flow_Down )
{
line_buff = (TT_Byte*)target->bitmap;
start_incr = target->cols;
}
else
{
line_buff = (TT_Byte*)target->bitmap + (target->rows-1)*target->cols;
start_incr = -target->cols;
}
if (inverted)
{
if (height < 0)
return;
line_incr = -target->cols;
}
else
line_incr = target->cols;
cursor_sign = (( target->flow == TT_Flow_Down ) ^ inverted ) ? 1 : -1;
if ( x_offset > 0 )
line_buff += x_offset / 8;
if ( y_offset > 0 )
line_buff += y_offset * start_incr;
if ( height < 0 )
height = target->rows;
acc = 0;
loaded = 0;
if ( y_offset < 0 )
{
switch ( align )
{
TT_Int step;
case -1:
source -= ((TT_Int)( line_bits + 7 ) / 8 ) * y_offset;
break;
case 0:
step = ( - line_bits * y_offset ) & 7;
source += ( - line_bits * y_offset ) / 8;
if (step)
{
acc = ((TT_UShort)*source++) << (step+8);
loaded = 8 - step;
}
break;
default:
source += - align * y_offset;
break;
}
}
for ( y = 0 ; y < height ; y++ )
{
TT_Byte* cur = line_buff;
TT_Int count = line_bits;
TT_Byte shift = x_offset & 7;
TT_Byte space = 8 - shift;
TT_Byte* source_position = source;
TT_Int byte_count;
if ( x_offset >= 0 )
byte_count = x_offset / 8;
else
byte_count = ( x_offset - 7 ) / 8 ;
if (( y_offset + cursor_sign * y ) >= target->rows )
break;
if ( byte_count < 0 )
{
TT_Int skip_byte = - byte_count - 1;
if (!skip_byte)
acc = loaded = 0;
source += skip_byte;
if (loaded < 8)
{
acc |= ((TT_UShort)*source++) << (8-loaded);
loaded += 8;
}
acc <<= space;
loaded -= space;
count += x_offset;
byte_count = 0;
shift = 0;
space = 8;
}
if ( count >= 8 )
{
count -= 8;
#if 0
if ( loaded == 0 )
{
if ( shift == 0 )
{
do
{
*cur++ |= *source++;
count -= 8;
}
while (count >= 0);
}
else
{
TT_Byte cache = cur[0];
do
{
TT_Byte val = *source++;
cur[0] = cache | (val >> shift);
cache = val << space;
cur++;
count -= 8;
}
while (count >= 0);
cur[0] |= cache;
}
}
else
#endif
{
do
{
TT_Byte val;
if (loaded < 8)
{
acc |= ((TT_UShort)*source++) << (8-loaded);
loaded += 8;
}
val = (TT_Byte)(acc >> 8);
if ( byte_count < target->cols )
{
cur[0] |= val >> shift;
if ( byte_count < target->cols - 1 )
cur[1] |= val << space;
}
cur++;
byte_count++;
acc <<= 8;
loaded -= 8;
count -= 8;
}
while ( count >= 0 );
}
count += 8;
}
if ( count > 0 )
{
TT_Byte val;
if (loaded < count)
{
acc |= ((TT_UShort)*source++) << (8-loaded);
loaded += 8;
}
val = ((TT_Byte)(acc >> 8)) & ~(0xFF >> count);
if ( byte_count < target->cols )
{
cur[0] |= val >> shift;
if ((count > space) && (byte_count < target->cols - 1))
cur[1] |= val << space;
}
acc <<= count;
loaded -= count;
}
if ( align )
{
acc = loaded = 0;
if ( align > 0 )
{
source_position += align;
source = source_position;
}
}
line_buff += line_incr;
}
}
TT_Error XTT_Get_SBit_Bitmap( TT_Raster_Map* target,
TT_SBit_Image* source_sbit,
TT_Int x_offset,
TT_Int y_offset )
{
TT_Raster_Map* source = &source_sbit->map;
TT_Int inverted = 0;
TT_Int line_bits;
TT_Int height;
if ((target->flow != TT_Flow_Up) && (target->flow != TT_Flow_Down))
return TT_Err_Invalid_Argument;
x_offset += ( source_sbit->metrics.bbox.xMin & -64 ) / 64;
x_offset *= source_sbit->bit_depth;
y_offset = target->rows
- ( y_offset + (( source_sbit->metrics.bbox.yMax + 63 ) & -64 ) / 64 );
inverted = (( source->flow * target->flow ) == -1 );
line_bits = source->width * source_sbit->bit_depth;
if (( x_offset + line_bits < 0 ) ||
( x_offset >= target->width ) ||
( y_offset >= target->rows ) ||
( y_offset + source->rows < 0 ))
return TT_Err_Invalid_Argument;
if (( source->cols <= 0 ) ||
( source->rows <= 0 ) ||
( source->size <= 0 ))
return TT_Err_Invalid_Argument;
height = ( y_offset >= 0 ) ? source->rows : ( source->rows + y_offset );
blit_stream( target, source->bitmap, line_bits, height,
source->cols, x_offset, y_offset, inverted );
return TT_Err_Ok;
}