# include "bitmapConfig.h" # include "bmintern.h" # include # include /************************************************************************/ /* */ /* Set one run in a bitmap. */ /* These routines only work for 1 bit/pixel. */ /* */ /* 1) End point inclusive. */ /* */ /************************************************************************/ static unsigned char BM_BitCounts[256]; static int bmCount1Run1Bit( const unsigned char * buffer, int col0, int col1 ) { int d; unsigned char c1, c2; const unsigned char * b1= (unsigned char *)0; const unsigned char * b2= (unsigned char *)0; int count= 0; /* APP_DEB(appDebug( "bmCount1Run(,col0=%d,col1=%d)\n", col0, col1 )); */ /* 1 */ col1++; d= ( col0 % 8 ); if ( d ) { b1= buffer+ col0/ 8; col0= 8* ( col0/ 8 )+ 8; c1= 0xff >> d; } else{ c1= 0; } d= ( col1 % 8 ); if ( d ) { b2= buffer+ col1/ 8; col1= 8* ( col1/ 8 ); c2= 0xff << ( 8- d ); } else{ c2= 0; } if ( b1 ) { if ( b1 == b2 ) { count += BM_BitCounts[ *b1 & c1 & c2 ]; } else{ count += BM_BitCounts[ *b1 & c1 ]; } } if ( b2 && b2 != b1 ) { count += BM_BitCounts[ *b2 & c2 ]; } col0 /= 8; col1 /= 8; b1= buffer+ col0; while( col0++ < col1 ) { count += BM_BitCounts[ *(b1++) ]; } return count; } /************************************************************************/ /* */ /* Count the number of bits set to 0 on a horizontal stretch. */ /* */ /* 1) Switch to 'upto' semantics. */ /* 2) If the beginning is not on a byte boundary, obtain a mask for */ /* the tail of the byte. Exclude this byte from the count below */ /* 3) If the end is not on a byte boundary, obtain a mask for the */ /* head of the byte. Exclude this byte from the count below */ /* 4) Count bits in the head byte. Handle the situation where head */ /* and tail refer to the same byte. */ /* 5) Count bits in the tail byte. (Unless head and tail are the same)*/ /* 6) Count bits in the bytes between head and tail. */ /* */ /************************************************************************/ static int bmCount0Run1Bit( const unsigned char * buffer, int col0, int col1 ) { int d; unsigned char c1, c2; const unsigned char * b1= (unsigned char *)0; const unsigned char * b2= (unsigned char *)0; int count= 0; /* 1 */ col1++; /* 2 */ d= ( col0 % 8 ); if ( d ) { b1= buffer+ col0/ 8; col0= 8* ( col0/ 8 )+ 8; c1= 0xff >> d; c1= ~c1; } else{ c1= 0xff; } /* 3 */ d= ( col1 % 8 ); if ( d ) { b2= buffer+ col1/ 8; col1= 8* ( col1/ 8 ); c2= 0xff << ( 8- d ); c2= ~c2; } else{ c2= 0xff; } /* 4 */ if ( b1 ) { if ( b1 == b2 ) { count += 8- BM_BitCounts[ *b1 | c1 | c2 ]; } else{ count += 8- BM_BitCounts[ *b1 | c1 ]; } } if ( b2 && b2 != b1 ) { count += 8- BM_BitCounts[ *b2 | c2 ]; } col0 /= 8; col1 /= 8; b1= buffer+ col0; while( col0++ < col1 ) { count += 8- (int)BM_BitCounts[ *(b1++) ]; } return count; } /************************************************************************/ /* */ /* count a line using Bressenham. */ /* */ /* 1) Line is supposed to be to the right. */ /* */ /************************************************************************/ static int bmCountBres1Line1Bit( const unsigned char * buffer, int x0, int y0, int x1, int y1, int bytesPerRow ) { int dx; int dy; int i; int e, d2, e2; unsigned char byteMask; int count= 0; dx= x1- x0; dy= y1- y0; /* 1 */ if ( dx < 0 ) { LDEB(dx); return 0; } buffer += y0* bytesPerRow+ x0/ 8; byteMask= 0x80 >> ( x0 % 8 ); if ( dy < 0 ) { dy = -dy; bytesPerRow= -bytesPerRow; } if ( dx > dy ) { e= 2* dy- dx; d2= 2* dx; e2= 2* dy; while( x0 <= x1 ) { count += BM_BitCounts[ *buffer & byteMask ]; while( e >= 0 ) { buffer += bytesPerRow; e -= d2; } byteMask >>= 1; x0++; e += e2; if ( ! ( x0 % 8 ) ) { buffer++; byteMask= 0x80; } } } else{ e= 2* dx- dy; d2= 2* dy; e2= 2* dx; for ( i= 0; i <= dy; i++ ) { count += BM_BitCounts[ *buffer & byteMask ]; while( e > 0 ) { byteMask >>= 1; x0++; e -= d2; if ( ! ( x0 % 8 ) ) { buffer++; byteMask= 0x80; } } buffer += bytesPerRow; e += e2; } } return count; } static int bmCountBres0Line1Bit( const unsigned char * buffer, int x0, int y0, int x1, int y1, int bytesPerRow ) { int dx; int dy; int i; int e, d2, e2; unsigned char byteMask; int count= 0; dx= x1- x0; dy= y1- y0; /* 1 */ if ( dx < 0 ) { LDEB(dx); return 0; } buffer += y0* bytesPerRow+ x0/ 8; byteMask= 0x80 >> ( x0 % 8 ); byteMask= ~byteMask; if ( dy < 0 ) { dy = -dy; bytesPerRow= -bytesPerRow; } if ( dx > dy ) { e= 2* dy- dx; d2= 2* dx; e2= 2* dy; while( x0 <= x1 ) { count += 8- BM_BitCounts[ *buffer | byteMask ]; while( e >= 0 ) { buffer += bytesPerRow; e -= d2; } byteMask >>= 1; byteMask |= 0x80; x0++; e += e2; if ( ! ( x0 % 8 ) ) { buffer++; byteMask= 0x7f; } } } else{ e= 2* dx- dy; d2= 2* dy; e2= 2* dx; for ( i= 0; i <= dy; i++ ) { count += 8- BM_BitCounts[ *buffer | byteMask ]; while( e > 0 ) { byteMask >>= 1; byteMask |= 0x80; x0++; e -= d2; if ( ! ( x0 % 8 ) ) { buffer++; byteMask= 0x7f; } } buffer += bytesPerRow; e += e2; } } return count; } /************************************************************************/ /* */ /* Draw a line segment. */ /* */ /* 1) Make it vertical or to the right. */ /* */ /************************************************************************/ int bmCountLinePixels( const unsigned char * buffer, const BitmapDescription * bd, int x0, int y0, int x1, int y1 ) { int i; int count= 0; int (*countRun)( const unsigned char * _buffer, int _x0, int _y0 ); int (*countLine)( const unsigned char * _buffer, int _x0, int _y0, int _x1, int _y1, int _bytesPerRow ); switch( bd->bdColorEncoding ) { case BMcoBLACKWHITE: if ( bd->bdBitsPerPixel != 1 ) { LLDEB(bd->bdColorEncoding,bd->bdBitsPerPixel); return -1; } countLine= bmCountBres1Line1Bit; countRun= bmCount1Run1Bit; break; case BMcoWHITEBLACK: if ( bd->bdBitsPerPixel != 1 ) { LLDEB(bd->bdColorEncoding,bd->bdBitsPerPixel); return -1; } countLine= bmCountBres0Line1Bit; countRun= bmCount0Run1Bit; break; default: LDEB(bd->bdColorEncoding); return -1; } if ( x0 < 0 || x0 >= bd->bdPixelsWide ) { LLDEB(x0,bd->bdPixelsWide); return -1; } if ( x1 < 0 || x1 >= bd->bdPixelsWide ) { LLDEB(x1,bd->bdPixelsWide); return -1; } if ( y0 < 0 || y0 >= bd->bdPixelsHigh ) { LLDEB(y0,bd->bdPixelsHigh); return -1; } if ( y1 < 0 || y1 >= bd->bdPixelsHigh ) { LLDEB(y1,bd->bdPixelsHigh); return -1; } if ( BM_BitCounts[1] == 0 ) { int pos; for ( pos= 0; pos < 256; pos++ ) { unsigned int p= pos; BM_BitCounts[pos]= 0; while( p ) { if ( p & 0x01 ) { BM_BitCounts[pos]++; } p >>= 1; } } } /* 1 */ if ( x0 > x1 ) { i= x0; x0= x1; x1= i; i= y0; y0= y1; y1= i; } if ( y1 == y0 ) { count += (*countRun)( buffer+ y0* bd->bdBytesPerRow, x0, x1 ); return count; } if ( x1 == x0 ) { if ( y1 < y0 ) { i= y0; y0= y1; y1= i; } buffer += y0* bd->bdBytesPerRow; while( y0 <= y1 ) { count += (*countRun)( buffer, x0, x1 ); y0++; buffer += bd->bdBytesPerRow; } return count; } count += (*countLine)( buffer, x0, y0, x1, y1, bd->bdBytesPerRow ); return count; }