123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870 |
- /*
- THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
- SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
- END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
- ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
- IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
- SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
- FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
- CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
- AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
- COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
- */
- #pragma off (unreferenced)
- static char rcsid[] = "$Id: ibitblt.c 1.16 1996/12/19 16:51:38 matt Exp $";
- #pragma on (unreferenced)
- #ifndef MACINTOSH
- #include <conio.h>
- #include <dos.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "pa_enabl.h" //$$POLY_ACC
- #include "types.h"
- #include "gr.h"
- #include "mem.h"
- #include "error.h"
- #include "ibitblt.h"
- #include "grdef.h"
- #if defined(POLY_ACC)
- #include "poly_acc.h"
- #endif
- #define MODE_NONE 0
- #define MODE_SKIP 1
- #define MODE_DRAW 2
- #define OPCODE_ADD 0x81
- #define OPCODE_ESI 0xC6 // Followed by a dword (add esi, ????)
- #define OPCODE_EDI 0xC7 // Followed by a dword (add edi, ????)
- #define OPCODE_MOV_ECX 0xB9 // Followed by a dword (mov ecx,????)
- #define OPCODE_MOVSB 0xA4 // movsb
- #define OPCODE_16BIT 0x66 // movsw
- #define OPCODE_MOVSD 0xA5 // movsd
- #define OPCODE_REP 0xF3 // rep
- #define OPCODE_RET 0xC3 // ret
- #define OPCODE_MOV_EAX 0xB8 // mov eax, im dword
- #define OPCODE_MOV_EBX 0xBB // mov ebx, im dword
- #define OPCODE_CALL_EBX1 0xFF // call
- #define OPCODE_CALL_EBX2 0xD3 // ebx
- #define OPCODE_MOV_EDI 0xBF // mov edi, im dword
- ubyte *Code_pointer = NULL;
- int Code_counter = 0;
- int ibitblt_svga_page = 0;
- int is_svga = 0;
- uint linear_address;
- void count_block( int ecx )
- {
- int blocks;
- while ( ecx > 0 ) {
- switch(ecx) {
- case 1: Code_counter++; ecx = 0; break; // MOVSB
- case 2: Code_counter+=2; ecx = 0; break; // MOVSW
- case 3: Code_counter+=3; ecx = 0; break; // MOVSW, MOVSB
- case 4: Code_counter++; ecx = 0; break; // MOVSD
- default:
- blocks = ecx / 4;
- if ( blocks == 1 )
- Code_counter++; // MOVSD
- else
- Code_counter+=7;
- ecx -= blocks*4;
- }
- }
- }
- void move_and_count( int dsource, int ddest, int ecx )
- {
- if ( ecx <= 0 )
- return;
- if ( dsource > 0 ) {
- // ADD ESI, dsource
- Code_counter += 6;
- }
- if ( !is_svga ) {
- if ( ddest > 0 ) {
- // ADD EDI, ddest
- Code_counter += 6;
- }
- count_block( ecx );
- } else {
- int p1, p2, o1;
- linear_address += ddest; // Skip to next block
- p1 = linear_address >> 16; o1 = linear_address & 0xFFFF;
- p2 = (linear_address+ecx) >> 16;
- if ( p1 != ibitblt_svga_page ) {
- // Set page
- // MOV EAX, ?, CALL EBX
- Code_counter += 7;
- ibitblt_svga_page = p1;
- }
- Code_counter += 5; // mov edi, ????
- if ( p1 == p2 ) {
- count_block( ecx );
- } else {
- int nbytes;
- nbytes = 0xFFFF-o1+1;
- count_block( nbytes );
- // set page
- // MOV EAX, 0
- Code_counter += 7; // mov eax,???? call ebx
- ibitblt_svga_page = p2;
- Code_counter += 5; // mov edi, ????
- nbytes = ecx - nbytes;
- if (nbytes > 0 )
- count_block( nbytes );
- }
- linear_address += ecx;
- }
- }
- void draw_block( int ecx )
- {
- int blocks;
- int * iptr;
- while ( ecx > 0 ) {
- switch( ecx ) {
- case 1:
- // MOVSB
- *Code_pointer++ = OPCODE_MOVSB;
- ecx = 0;
- break;
- case 2:
- // MOVSW
- *Code_pointer++ = OPCODE_16BIT;
- *Code_pointer++ = OPCODE_MOVSD;
- ecx = 0;
- break;
- case 3:
- // MOVSW, MOVSB
- *Code_pointer++ = OPCODE_16BIT;
- *Code_pointer++ = OPCODE_MOVSD;
- *Code_pointer++ = OPCODE_MOVSB;
- ecx = 0;
- break;
- case 4:
- // MOVSD
- *Code_pointer++ = OPCODE_MOVSD;
- ecx = 0;
- break;
- default:
- blocks = ecx / 4;
- if ( blocks == 1 ) {
- // MOVSD
- *Code_pointer++ = OPCODE_MOVSD;
- } else {
- // MOV ECX, blocks
- *Code_pointer++ = OPCODE_MOV_ECX;
- iptr = (int *)Code_pointer;
- *iptr++ = blocks;
- Code_pointer = (ubyte *)iptr;
- // REP MOVSD
- *Code_pointer++ = OPCODE_REP;
- *Code_pointer++ = OPCODE_MOVSD;
- }
- ecx -= blocks*4;
- }
- }
- }
- void move_and_draw( int dsource, int ddest, int ecx )
- {
- int * iptr;
- if ( ecx <= 0 )
- return;
- if ( dsource > 0 ) {
- // ADD ESI, dsource
- *Code_pointer++ = OPCODE_ADD;
- *Code_pointer++ = OPCODE_ESI;
- iptr = (int *)Code_pointer;
- *iptr++ = dsource;
- Code_pointer = (ubyte *)iptr;
- }
- if ( !is_svga ) {
- if ( ddest > 0 ) {
- // ADD EDI, ddest
- *Code_pointer++ = OPCODE_ADD;
- *Code_pointer++ = OPCODE_EDI;
- iptr = (int *)Code_pointer;
- *iptr++ = ddest;
- Code_pointer = (ubyte *)iptr;
- }
- draw_block( ecx );
- } else {
- unsigned int temp;
- int temp_offset;
- int p1, p2, o1;
- linear_address += ddest; // Skip to next block
- p1 = linear_address >> 16; o1 = linear_address & 0xFFFF;
- p2 = (linear_address+ecx) >> 16;
- if ( p1 != ibitblt_svga_page ) {
- // Set page
- // MOV EAX, 0
- *Code_pointer++ = OPCODE_MOV_EAX;
- temp = p1;
- memcpy( Code_pointer, &temp, sizeof(int) );
- Code_pointer += sizeof(int);
- // CALL EBX
- *Code_pointer++ = OPCODE_CALL_EBX1;
- *Code_pointer++ = OPCODE_CALL_EBX2;
- ibitblt_svga_page = p1;
- }
- temp_offset = 0xA0000 + o1;
- *Code_pointer++ = OPCODE_MOV_EDI;
- iptr = (int *)Code_pointer;
- *iptr++ = temp_offset;
- Code_pointer = (ubyte *)iptr;
- if ( p1 == p2 ) {
- draw_block( ecx );
- } else {
- int nbytes;
- nbytes = 0xFFFF-o1+1;
- draw_block( nbytes );
- // set page
- // MOV EAX, 0
- *Code_pointer++ = OPCODE_MOV_EAX;
- temp = p2;
- memcpy( Code_pointer, &temp, sizeof(int) );
- Code_pointer += sizeof(int);
- // CALL EBX
- *Code_pointer++ = OPCODE_CALL_EBX1;
- *Code_pointer++ = OPCODE_CALL_EBX2;
- ibitblt_svga_page = p2;
- temp_offset = 0xA0000;
- *Code_pointer++ = OPCODE_MOV_EDI;
- iptr = (int *)Code_pointer;
- *iptr++ = temp_offset;
- Code_pointer = (ubyte *)iptr;
- nbytes = ecx - nbytes;
- if (nbytes > 0 )
- draw_block( nbytes );
- }
- linear_address += ecx;
- }
- }
- //-----------------------------------------------------------------------------------------
- // Given bitmap, bmp, finds the size of the code
- int gr_ibitblt_find_code_size_sub( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize, int dest_type )
- {
- int x,y;
- ubyte pixel;
- int draw_mode = MODE_NONE;
- int source_offset = 0;
- int dest_offset = 0;
- int num_to_draw, draw_start_source, draw_start_dest;
- int esi, edi;
- Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
- Code_counter = 0;
- if ( dest_type == BM_SVGA ) {
- Code_counter += 1+4; // move ebx, gr_vesa_set_page
- Code_counter += 1+4; // move eax, 0
- Code_counter += 2; // call ebx
- ibitblt_svga_page = 0;
- linear_address = 0;
- is_svga = 1;
- } else {
- is_svga = 0;
- }
- esi = source_offset = 0;
- edi = dest_offset = 0;
- draw_start_source = draw_start_dest = 0;
- for ( y=sy; y<sy+sh; y++ ) {
- for ( x=sx; x<sx+sw; x++ ) {
- dest_offset = y*mask_bmp->bm_rowsize+x;
- pixel = mask_bmp->bm_data[dest_offset];
- if ( pixel!=255 ) {
- switch ( draw_mode) {
- case MODE_DRAW:
- move_and_count( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
- esi = draw_start_source + num_to_draw;
- edi = draw_start_dest + num_to_draw;
- // fall through!!!
- case MODE_NONE:
- case MODE_SKIP:
- break;
- }
- draw_mode = MODE_SKIP;
- } else {
- switch ( draw_mode) {
- case MODE_SKIP:
- case MODE_NONE:
- draw_start_source = source_offset;
- draw_start_dest = dest_offset;
- num_to_draw = 0;
- // fall through
- case MODE_DRAW:
- num_to_draw++;
- break;
- }
- draw_mode = MODE_DRAW;
- }
- source_offset++;
- }
- if ( draw_mode == MODE_DRAW ) {
- move_and_count( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
- esi = draw_start_source + num_to_draw;
- edi = draw_start_dest + num_to_draw;
- }
- draw_mode = MODE_NONE;
- source_offset += (srowsize - sw);
- }
- Code_counter++; // for return
- //printf( "Code will be %d bytes\n", Code_counter );
- Code_counter += 16; // for safety was 16
- return Code_counter;
- }
- int gr_ibitblt_find_code_size( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
- {
- return gr_ibitblt_find_code_size_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_LINEAR );
- }
- int gr_ibitblt_find_code_size_svga( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
- {
- return gr_ibitblt_find_code_size_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_SVGA );
- }
- //-----------------------------------------------------------------------------------------
- // Given bitmap, bmp, create code that transfers a bitmap of size sw*sh to position
- // (sx,sy) on top of bmp, only overwritting transparent pixels of the bitmap.
- ubyte *gr_ibitblt_create_mask_sub( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize, int dest_type )
- {
- int x,y;
- ubyte pixel;
- int draw_mode = MODE_NONE;
- int source_offset = 0;
- int dest_offset = 0;
- int num_to_draw, draw_start_source, draw_start_dest;
- int esi, edi;
- int code_size;
- ubyte *code;
- uint temp;
- Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
- if ( dest_type == BM_SVGA )
- code_size = gr_ibitblt_find_code_size_svga( mask_bmp, sx, sy, sw, sh, srowsize );
- else
- code_size = gr_ibitblt_find_code_size( mask_bmp, sx, sy, sw, sh, srowsize );
- code = malloc( code_size );
- if ( code == NULL )
- return NULL;
- Code_pointer = code;
- if ( dest_type == BM_SVGA ) {
- // MOV EBX, gr_vesa_setpage
- *Code_pointer++ = OPCODE_MOV_EBX;
- temp = (uint)gr_vesa_setpage;
- memcpy( Code_pointer, &temp, sizeof(int) );
- Code_pointer += sizeof(int);
- // MOV EAX, 0
- *Code_pointer++ = OPCODE_MOV_EAX;
- temp = 0;
- memcpy( Code_pointer, &temp, sizeof(int) );
- Code_pointer += sizeof(int);
- // CALL EBX
- *Code_pointer++ = OPCODE_CALL_EBX1;
- *Code_pointer++ = OPCODE_CALL_EBX2;
- ibitblt_svga_page = 0;
- is_svga = 1;
- linear_address = 0;
- } else {
- is_svga = 0;
- }
- esi = source_offset = 0;
- edi = dest_offset = 0;
- draw_start_source = draw_start_dest = 0;
- for ( y=sy; y<sy+sh; y++ ) {
- for ( x=sx; x<sx+sw; x++ ) {
- dest_offset = y*mask_bmp->bm_rowsize+x;
- pixel = mask_bmp->bm_data[dest_offset];
- if ( pixel!=255 ) {
- switch ( draw_mode) {
- case MODE_DRAW:
- move_and_draw( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
- esi = draw_start_source + num_to_draw;
- edi = draw_start_dest + num_to_draw;
- // fall through!!!
- case MODE_NONE:
- case MODE_SKIP:
- break;
- }
- draw_mode = MODE_SKIP;
- } else {
- switch ( draw_mode) {
- case MODE_SKIP:
- case MODE_NONE:
- draw_start_source = source_offset;
- draw_start_dest = dest_offset;
- num_to_draw = 0;
- // fall through
- case MODE_DRAW:
- num_to_draw++;
- break;
- }
- draw_mode = MODE_DRAW;
- }
- source_offset++;
- }
- if ( draw_mode == MODE_DRAW ) {
- move_and_draw( draw_start_source-esi, draw_start_dest-edi, num_to_draw );
- esi = draw_start_source + num_to_draw;
- edi = draw_start_dest + num_to_draw;
- }
- draw_mode = MODE_NONE;
- source_offset += (srowsize - sw);
- }
- *Code_pointer++ = OPCODE_RET;
- if ( Code_pointer >= &code[code_size-1] )
- Error( "ibitblt overwrote allocated code block\n" );
- //printf( "Code is %d bytes\n", Code_pointer - code );
- return code;
- }
- ubyte *gr_ibitblt_create_mask( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
- {
- return gr_ibitblt_create_mask_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_LINEAR );
- }
- #if defined(POLY_ACC)
- ulong *pa_emit_blit(int gencode, ulong *buf, int w, int h, int sx, int sy, int dx, int dy)
- {
- if(w == 0 || h == 0)
- return buf;
- if(gencode)
- {
- buf[0] = (w << 16) | h;
- buf[1] = (sx << 16) | sy;
- buf[2] = (dx << 16) | dy;
- }
- return buf + 3;
- }
- ubyte *gr_ibitblt_create_mask_pa( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
- {
- ulong *ret, *code = 0;
- int pass, x, y, n;
- ushort *s;
- Assert(mask_bmp->bm_type == BM_LINEAR15);
- srowsize /= PA_BPP;
- pa_flush();
- // make two passes, first pass gets size of output block, second actually creates data.
- for(pass = 0; pass != 2; ++pass)
- {
- for (y = sy; y < sy + sh; y++ )
- {
- // first byte of interest in mask
- s = (ushort *)(mask_bmp->bm_data + y * mask_bmp->bm_rowsize + sx * PA_BPP);
- for ( x=0; x < sw; )
- {
- for(; x != sw && (s[x] & 0x8000); ++x) // while opaque...
- ;
- for(n = 0; x != sw && !(s[x] & 0x8000); ++n, ++x) // while transparent...
- ;
- code = pa_emit_blit(pass, code, n, 1, x - n, y - sy, x + sx - n, y);
- }
- }
- if(pass == 0)
- {
- ret = malloc((int)code + sizeof(ulong));
- ret[0] = (int)code / sizeof(ulong); // store num ulongs in list.
- code = ret + 1;
- }
- }
- return (ubyte *)ret;
- }
- #else
- ubyte *gr_ibitblt_create_mask_svga( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
- {
- return gr_ibitblt_create_mask_sub( mask_bmp, sx, sy, sw, sh, srowsize, BM_SVGA );
- }
- #endif
- void gr_ibitblt_do_asm(char *start_si, char *start_di, ubyte * code);
- #pragma aux gr_ibitblt_do_asm parm [esi] [edi] [eax] modify [ecx edi esi eax] = \
- "pusha" \
- "cld" \
- "call eax" \
- "popa"
- void gr_ibitblt(grs_bitmap * source_bmp, grs_bitmap * dest_bmp, ubyte * mask )
- {
- #if defined(POLY_ACC)
- Assert(source_bmp->bm_type == BM_LINEAR15);
- pa_ibitblt(source_bmp->bm_data, dest_bmp->bm_data, mask);
- #else
- if (mask != NULL )
- gr_ibitblt_do_asm( source_bmp->bm_data, dest_bmp->bm_data, mask );
- #endif
- }
- void gr_ibitblt_find_hole_size( grs_bitmap * mask_bmp, int *minx, int *miny, int *maxx, int *maxy )
- {
- int x, y, count=0;
- #if defined(POLY_ACC)
- short c;
- #else
- ubyte c;
- #endif
- Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
- #if defined(POLY_ACC)
- Assert(mask_bmp->bm_type == BM_LINEAR15);
- pa_flush();
- #endif
- *minx = mask_bmp->bm_w-1;
- *maxx = 0;
- *miny = mask_bmp->bm_h-1;
- *maxy = 0;
- for ( y=0; y<mask_bmp->bm_h; y++ )
- for ( x=0; x<mask_bmp->bm_w; x++ ) {
- #if defined(POLY_ACC)
- c = *(short *)(mask_bmp->bm_data + mask_bmp->bm_rowsize * y + x * PA_BPP);
- if (c >= 0) { // hi true means opaque.
- #else
- c = mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x];
- if (c == 255 ) {
- #endif
- if ( x < *minx ) *minx = x;
- if ( y < *miny ) *miny = y;
- if ( x > *maxx ) *maxx = x;
- if ( y > *maxy ) *maxy = y;
- count++;
- }
- }
- if ( count == 0 ) {
- Error( "Bitmap for ibitblt doesn't have transparency!\n" );
- }
- }
- #else // ifdef MACINTOSH
- #include "pa_enabl.h"
- #include "pstypes.h"
- #include "gr.h"
- #include "ibitblt.h"
- #include "error.h"
- #include "mem.h"
- #if defined(POLY_ACC)
- #include "poly_acc.h"
- #endif
- #define FIND_START 1
- #define FIND_STOP 2
- #define MAX_WIDTH 640
- #define MAX_SCANLINES 480
- #define MAX_HOLES 5
- static short start_points[MAX_SCANLINES][MAX_HOLES];
- static short hole_length[MAX_SCANLINES][MAX_HOLES];
- static double *scanline = NULL;
- void gr_ibitblt(grs_bitmap *src_bmp, grs_bitmap *dest_bmp, ubyte pixel_double)
- {
- int x, y, sw, sh, srowsize, drowsize, dstart, sy, dy;
- ubyte *src, *dest;
- short *current_hole, *current_hole_length;
- // variable setup
- if ( PAEnabled )
- return;
- sw = src_bmp->bm_w;
- sh = src_bmp->bm_h;
- srowsize = src_bmp->bm_rowsize;
- drowsize = dest_bmp->bm_rowsize;
- src = src_bmp->bm_data;
- dest = dest_bmp->bm_data;
- sy = 0;
- while (start_points[sy][0] == -1) {
- sy++;
- dest += drowsize;
- }
- if (pixel_double) {
- ubyte *scan = (ubyte *)scanline; // set up for byte processing of scanline
- dy = sy;
- for (y = sy; y < sy + sh; y++) {
- int i, j;
- gr_linear_movsd_double(src, scan, sw*2);
- current_hole = start_points[dy];
- current_hole_length = hole_length[dy];
- for (x = 0; x < MAX_HOLES; x++) {
- if (*current_hole == -1)
- break;
- dstart = *current_hole;
- gr_linear_movsd(&(scan[dstart]), &(dest[dstart]), *current_hole_length);
- current_hole++;
- current_hole_length++;
- }
- dy++;
- dest += drowsize;
- current_hole = start_points[dy];
- current_hole_length = hole_length[dy];
- for (x = 0;x < MAX_HOLES; x++) {
- if (*current_hole == -1)
- break;
- dstart = *current_hole;
- gr_linear_movsd(&(scan[dstart]), &(dest[dstart]), *current_hole_length);
- current_hole++;
- current_hole_length++;
- }
- dy++;
- dest += drowsize;
- src += srowsize;
- }
- } else {
- Assert(sw <= MAX_WIDTH);
- Assert(sh <= MAX_SCANLINES);
- for (y = sy; y < sy + sh; y++) {
- for (x = 0; x < MAX_HOLES; x++) {
- if (start_points[y][x] == -1)
- break;
- dstart = start_points[y][x];
- gr_linear_movsd(&(src[dstart]), &(dest[dstart]), hole_length[y][x]);
- }
- dest += drowsize;
- src += srowsize;
- }
- }
- }
- #if defined(POLY_ACC)
- ulong *pa_emit_blit(int gencode, ulong *buf, int w, int h, int sx, int sy, int dx, int dy)
- {
- if(w == 0 || h == 0)
- return buf;
- if(gencode)
- {
- buf[0] = (w << 16) | h;
- buf[1] = (sx << 16) | sy;
- buf[2] = (dx << 16) | dy;
- }
- return buf + 3;
- }
- void gr_ibitblt_create_mask_pa( grs_bitmap * mask_bmp, int sx, int sy, int sw, int sh, int srowsize )
- {
- ulong *ret, *code = 0;
- int pass, x, y, n;
- ushort *s;
- Assert(mask_bmp->bm_type == BM_LINEAR15);
- srowsize /= PA_BPP;
- pa_flush();
- // make two passes, first pass gets size of output block, second actually creates data.
- for(pass = 0; pass != 2; ++pass)
- {
- for (y = sy; y < sy + sh; y++ )
- {
- // first byte of interest in mask
- s = (ushort *)(mask_bmp->bm_data + y * mask_bmp->bm_rowsize + sx * PA_BPP);
- for ( x=0; x < sw; )
- {
- for(; x != sw && (s[x] & 0x8000); ++x) // while opaque...
- ;
- for(n = 0; x != sw && !(s[x] & 0x8000); ++n, ++x) // while transparent...
- ;
- code = pa_emit_blit(pass, code, n, 1, x - n, y - sy, x + sx - n, y);
- }
- }
-
- if(pass == 0) {
- ret = malloc((int)code + sizeof(ulong));
- ret[0] = (int)code / sizeof(ulong); // store num ulongs in list.
- code = ret + 1;
- }
- }
- // return (ubyte *)ret;
- }
- #endif
- void gr_ibitblt_create_mask(grs_bitmap *mask_bmp, int sx, int sy, int sw, int sh, int srowsize)
- {
- int x, y, dest_offset;
- ubyte pixel, mode;
- int count = 0;
- Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
- for (y = 0; y < MAX_SCANLINES; y++) {
- for (x = 0; x < MAX_HOLES; x++) {
- start_points[y][x] = -1;
- hole_length[y][x] = -1;
- }
- }
- for (y = sy; y < sy+sh; y++) {
- count = 0;
- mode = FIND_START;
- for (x = sx; x < sx + sw; x++) {
- if ((mode == FIND_START) && (mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x] == TRANSPARENCY_COLOR)) {
- start_points[y][count] = x;
- mode = FIND_STOP;
- } else if ((mode == FIND_STOP) && (mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x] != TRANSPARENCY_COLOR)) {
- hole_length[y][count] = x - start_points[y][count];
- count++;
- mode = FIND_START;
- }
- }
- if (mode == FIND_STOP) {
- hole_length[y][count] = x - start_points[y][count];
- count++;
- }
- Assert(count <= MAX_HOLES);
- }
- }
- #if defined(POLY_ACC)
- void gr_ibitblt_find_hole_size_pa( grs_bitmap * mask_bmp, int *minx, int *miny, int *maxx, int *maxy )
- {
- int x, y, count=0;
- short c;
- Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
- Assert(mask_bmp->bm_type == BM_LINEAR15);
- while(!pa_idle());
- *minx = mask_bmp->bm_w-1;
- *maxx = 0;
- *miny = mask_bmp->bm_h-1;
- *maxy = 0;
- for ( y=0; y<mask_bmp->bm_h; y++ )
- for ( x=0; x<mask_bmp->bm_w; x++ ) {
- c = *(short *)(mask_bmp->bm_data + mask_bmp->bm_rowsize * y + x * PA_BPP);
- if (c >= 0) { // hi true means opaque.
- if ( x < *minx ) *minx = x;
- if ( y < *miny ) *miny = y;
- if ( x > *maxx ) *maxx = x;
- if ( y > *maxy ) *maxy = y;
- count++;
- }
- }
- if ( count == 0 ) {
- Error( "Bitmap for ibitblt doesn't have transparency!\n" );
- }
- }
- #endif
- void gr_ibitblt_find_hole_size(grs_bitmap *mask_bmp, int *minx, int *miny, int *maxx, int *maxy)
- {
- ubyte c;
- int x, y, count = 0;
- #if defined(POLY_ACC)
- if ( PAEnabled ) {
- gr_ibitblt_find_hole_size_pa( mask_bmp, minx, miny, maxx, maxy );
- return;
- }
- #endif
-
- Assert( (!(mask_bmp->bm_flags&BM_FLAG_RLE)) );
- Assert( mask_bmp->bm_flags&BM_FLAG_TRANSPARENT );
- *minx = mask_bmp->bm_w - 1;
- *maxx = 0;
- *miny = mask_bmp->bm_h - 1;
- *maxy = 0;
- if (scanline == NULL)
- scanline = (double *)malloc(sizeof(double) * (MAX_WIDTH / sizeof(double)));
- for (y = 0; y < mask_bmp->bm_h; y++) {
- for (x = 0; x < mask_bmp->bm_w; x++) {
- c = mask_bmp->bm_data[mask_bmp->bm_rowsize*y+x];
- if (c == TRANSPARENCY_COLOR) { // don't look for transparancy color here.
- count++;
- if (x < *minx) *minx = x;
- if (y < *miny) *miny = y;
- if (x > *maxx) *maxx = x;
- if (y > *maxy) *maxy = y;
- }
- }
- }
- Assert (count);
- }
- #endif // ifdef MACINTOSH
|