
#define BLACK 0
#define BLUE 1
#define GREEN 2
#define CYAN 3
#define RED 4
#define PURPLE 5
#define BROWN 6
#define LTGRAY 7
#define DKGRAY 8
#define LTBLUE 9
#define LTGREEN 10
#define LTCYAN 11
#define LTRED 12
#define LTPURPLE 13
#define YELLOW 14
#define WHITE 15
//Low 8 bits reserved for flags that go into saved bitmaps
#define BMF_COMPRESSED 1
#define BMF_TRANSFORMATION 0x100
//See $LK,"GrSetSymmetry","MN:GrSetSymmetry"$() or $LK,"GrSetSymmetry3","MN:GrSetSymmetry3"$()
#define BMF_SYMMETRY 0x200
//Must be used with BMF_SYMMETRY set also.
//See $LK,"WarGame","FF:::/LT/Apps/WarGame/WarGame.CPZ,BMF_JUST_MIRROR"$
#define BMF_JUST_MIRROR 0x400
#define BMF_LOCATE_NEAREST 0x800
#define BMF_DONT_DRAW 0x1000
#define BMF_ALIAS 0x2000
#define BMF_SCREEN_BITMAP 0x4000
#define BMF_FILL_NOT_COLOR 0x8000
#define BMF_RECORD_EXTENTS 0x10000
#define BMF_ON_TOP 0x20000
#define BMT_COLOR4 1
#define BMT_MONO 2
//This is using a byte plane instead of 4 bit planes.
//It doesn't help performance, however,
//might provide a starting point if anyone
//wants to do 24 bit color.
#define BMT_COLOR4_U1 3
#define BMS_SIGNATURE 0x28768922
public class GrSymStruct
{
I4 sx,sy,sz,pad2;
//Normal of symmetry plane
I8 snx,sny,snz;
};
public class GrBitMap
{
U0 start_saved_area;
I4 type,width,width_internal,height;
U8 flags;
I8 plane_size;
I4 left_margin,right_margin,top_margin,bottom_margin;
U0 end_saved_area;
//public
I4 color,bkcolor;
I4 color2,pen_width;
GrBitMap *brush;
I8 *r; //rotation matrix of quads decimal in lo
I4 x,y,z,pad1; //translation
GrSymStruct sym;
//not document num, but num in a GrElems collection
I8 nearest_grelem_num;
U8 nearest_dist;
//not document num, but num in a GrElems collection
I8 cur_grelem_num;
I4 cur_x,cur_y,cur_z,pad3;
double speedline_scale;
U8 collision_cnt;
//Set by $LK,"BMF_RECORD_EXTENTS","MN:BMF_RECORD_EXTENTS"$
I8 min_x,max_x,min_y,max_y; //screen coordinates
U4 bitmap_signature,pad4;
TssStruct *mem_tss,*win_tss;
GrBitMap *mask;
U1 *body;
};
#help_index "Graphics/Bitmaps"
public void GrReset(GrBitMap *base)
{
base->color=BLACK;
base->color2=BLACK;
base->bkcolor=BLACK;
base->pen_width=1;
base->flags&=~(BMF_SYMMETRY|BMF_TRANSFORMATION|BMF_JUST_MIRROR);
}
public GrBitMap *GrAlias(GrBitMap *base,TssStruct *tss)
{
GrBitMap *result;
if (!base) return NULL;
result=MAlloc(sizeof(GrBitMap),tss);
if (base->bitmap_signature!=BMS_SIGNATURE)
Debugger;
MemCpy(result,base,sizeof(GrBitMap));
result->win_tss=tss;
result->mem_tss=tss;
result->r=MAlloc(16<<3,tss);
GrSetIdent(result->r);
GrReset(result);
result->flags|=BMF_ALIAS;
if (base->mask) {
result->mask=GrAlias(base->mask,tss);
result->mask->color=base->mask->color;
}
return result;
}
public GrBitMap *GrNew(U8 type,U8 width,U8 height,TssStruct *tss=NULL,BoolI1 null_bitmap=FALSE)
{ //This internally only allows widths which are divisible by 8
//$FG,4$Don't forget these$FG$
$MA+A-X+PU,"sizeof(GrBitMap)","Grep(\"sizeof(GrBitMap)\",\"/LT/\"TEXT_FILE_MASK);View;"$.
GrBitMap *result;
if (!tss) tss=Fs;
result=MAllocZ(sizeof(GrBitMap),tss);
result->win_tss=tss;
result->mem_tss=tss;
result->type=type;
result->width=width;
result->width_internal=(width+7)&~7;
result->height=height;
result->left_margin=0;
result->right_margin=width;
result->top_margin=0;
result->bottom_margin=height;
switch (type) {
case BMT_COLOR4:
result->plane_size=(result->width_internal*result->height)>>3;
if (!null_bitmap)
result->body=MAllocZ(result->plane_size<<2,tss);
break;
case BMT_COLOR4_U1:
result->plane_size=result->width_internal*result->height;
if (!null_bitmap)
result->body=MAllocZ(result->plane_size,tss);
break;
case BMT_MONO:
result->plane_size=(result->width_internal*result->height)>>3;
if (!null_bitmap)
result->body=MAllocZ(result->plane_size,tss);
break;
default:
throw(EXCEPT_GRAPHICS,1);
}
if (null_bitmap)
result->flags|=BMF_DONT_DRAW;
result->pen_width=1;
result->r=MAllocZ(16<<3,tss);
result->r[0].u4[1]=1;
result->r[5].u4[1]=1;
result->r[10].u4[1]=1;
result->r[15].u4[1]=1;
result->speedline_scale=0.04;
result->mask=NULL;
result->bitmap_signature=BMS_SIGNATURE;
return result;
}
public void GrDel(GrBitMap *base)
{
if (!base) return;
if (base->bitmap_signature!=BMS_SIGNATURE)
Debugger;
base->bitmap_signature=0;
Free(base->r);
if (!(base->flags & BMF_ALIAS))
Free(base->body);
GrDel(base->mask);
Free(base);
}
public GrBitMap *GrCopy(GrBitMap *base,TssStruct *tss=NULL)
{
GrBitMap *result;
if (!base) return NULL;
if (base->bitmap_signature!=BMS_SIGNATURE)
Debugger;
result=MAllocIdentical(base,tss);
result->r=MAllocIdentical(base->r,tss);
result->mem_tss=tss;
result->body=MAllocIdentical(base->body,tss);
result->mask=GrCopy(base->mask,tss);
return result;
}
/* $AN,"GrBitMaps","GrBitMaps"$
$FG,2$ The format of a stored bitmap includes a
0x30 byte header. See $LK,"GrBitMap","MN:GrBitMap"$. The body
consists of bit planes like VGA except bits
in bytes are reversed. For $LK,"BMT_MONO","MN:BMT_MONO"$, there
is one bit-plane; for $LK,"BMT_COLOR4","MN:BMT_COLOR4"$, there are
four bit-planes.
If you look at the color values ($LK,"BLACK","MN:BLACK"$-$LK,"WHITE","MN:WHITE"$)
you'll see the color of the planes is as follows:
Plane 0: BLUE
Plane 1: GREEN
Plane 2: RED
Plane 3: INTENSITY
If you are unfamiliar with bit planes, all
the blue bits for all the pixels are stored,
for all the green bits for all pixels, etc. Therefore,
a single pixel's value is spread-out in mem
instead of residing in one location. This
was done because that is how VGA is stored.
However, I made the order of the bits suitable
for doing $LK,"Bts","MN:Bts"$() or $LK,"Btr","MN:Btr"$() operations instead of
how VGA stores them.
The data for the following bitmap is displayed
width : 11 pixels
height : 8 pixels
internal width: 16 pixels (rounded-up to multiple of 8)
plane size : 16 bytes
$PI,"",1$
#define RED 4
#define YELLOW 14
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000010 00 00 00 00 00 00 F0 07 10 00 10 00 10 00 10 00
00000020 01 00 01 00 01 00 F1 07 11 00 11 00 11 00 11 00
00000030 00 00 00 00 00 00 F0 07 10 00 10 00 10 00 10 00
$FG$*/
public U1 *GrSave(GrBitMap *b,U8 *size=NULL,BoolI1 compressed=TRUE)
{ //stores to mem
U1 *ptr,*body,*result;
BoolI1 old_preempt;
ArcCompressStruct *ac;
I8 i,j,old_flags=b->flags;
switch (b->type) {
case BMT_COLOR4:
i=b->plane_size<<2;
break;
case BMT_COLOR4_U1:
case BMT_MONO:
i=b->plane_size;
break;
default:
throw(EXCEPT_GRAPHICS,2);
}
if (compressed) {
ac=CompressBuf(b->body,i);
j=ac->compressed_size;
body=ac;
} else {
ac=NULL;
j=i;
body=b->body;
}
ptr=result=MAlloc(offset(GrBitMap.end_saved_area)-
offset(GrBitMap.start_saved_area)+j);
old_preempt=Preempt(OFF); //in case it is a screen bitmap
if (compressed) b->flags|=BMF_COMPRESSED;
b->flags&=BMF_COMPRESSED;
MemCpy(result,&b->start_saved_area,
offset(GrBitMap.end_saved_area)-
offset(GrBitMap.start_saved_area));
b->flags=old_flags;
Preempt(old_preempt);
ptr+=offset(GrBitMap.end_saved_area)-
offset(GrBitMap.start_saved_area);
MemCpy(ptr,body,j);
ptr+=j;
Free(ac);
if (size)
*size=ptr-result;
return result;
}
public GrBitMap *GrLoad(U1 *src,U8 *size=NULL,TssStruct *tss=NULL)
{ //loads from mem
I8 i;
GrBitMap *result;
U1 *ptr=src;
ArcCompressStruct *ac;
if (!tss) tss=Fs;
result=MAllocZ(sizeof(GrBitMap),tss);
result->win_tss=tss;
result->mem_tss=tss;
MemCpy(&result->start_saved_area,src,
offset(GrBitMap.end_saved_area)-
offset(GrBitMap.start_saved_area));
ptr+=offset(GrBitMap.end_saved_area)-
offset(GrBitMap.start_saved_area);
switch (result->type) {
case BMT_COLOR4:
i=result->plane_size<<2;
break;
case BMT_COLOR4_U1:
case BMT_MONO:
i=result->plane_size;
break;
default:
throw(EXCEPT_GRAPHICS,3);
}
if (result->flags&BMF_COMPRESSED) {
result->flags&=~BMF_COMPRESSED;
ac=ptr;
result->body=ExpandBuf(ac,tss);
ptr+=ac->compressed_size;
} else {
result->body=MAlloc(i,tss);
MemCpy(result->body,ptr,i);
}
result->pen_width=1;
result->r=MAllocZ(16<<3,tss);
result->r[0].u4[1]=1;
result->r[5].u4[1]=1;
result->r[10].u4[1]=1;
result->r[15].u4[1]=1;
result->speedline_scale=0.04;
result->bitmap_signature=BMS_SIGNATURE;
result->mask=NULL;
if (size)
*size=ptr-src;
return result;
}
public U8 WriteLGR(I1 *filename,GrBitMap *base)
{ // LoseThos LGR File
U8 size;
U1 *src=GrSave(base,&size);
WriteFile(filename,src,size);
Free(src);
return size;
}
public GrBitMap *ReadLGR(I1 *filename)
{ // LoseThos LGR File
GrBitMap *base=NULL;
U1 *src=ReadFile(filename);
if (src)
base=GrLoad(src);
Free(src);
return base;
}
#help_index "Graphics/Bitmaps;Graphics/Screen"
public GrBitMap *GrCaptureScreen(TssStruct *tss=NULL)
{
WinSync(TRUE);
return GrCopy(gr_screen_image,tss);
}
public U8 CaptureScreenLGR(I1 *filename)
{ // LoseThos LGR File
U8 size;
GrBitMap *base=GrCaptureScreen;
size=WriteLGR(filename,base);
GrDel(base);
return size;
}
#help_index "Graphics;Graphics/Bitmaps"
public void GrInitExtents(GrBitMap *base)
{//See $LK,"::/LT/Demo/Graphics/Extents.CPZ","FI:::/LT/Demo/Graphics/Extents.CPZ"$
//You should clear the record flag yourself
base->flags|=BMF_RECORD_EXTENTS;
base->min_x=MAX_I8;
base->max_x=MIN_I8;
base->min_y=MAX_I8;
base->max_y=MIN_I8;
}
#help_index "Graphics"
public void GrPlot0(GrBitMap *base,I8 x,I8 y)
{ //No clipping or transformation or pen width
U8 d,c,c2;
U1 *dst,bit,not_bit;
U8 color=base->color,bkcolor=base->bkcolor;
double dist;
if (base->flags & BMF_LOCATE_NEAREST) {
dist=DistI8(x,y,base->cur_x,base->cur_y);
if (dist<=base->nearest_dist) {
base->nearest_grelem_num=base->cur_grelem_num;
base->nearest_dist=dist;
}
}
if (base->flags & BMF_RECORD_EXTENTS) {
if (x<base->min_x) base->min_x=x;
if (x>base->max_x) base->max_x=x;
if (y<base->min_y) base->min_y=y;
if (y>base->max_y) base->max_y=y;
}
if (base->flags & BMF_DONT_DRAW)
return;
d=base->width_internal*(y+base->top_margin)+x+base->left_margin;
switch (base->type) {
case BMT_COLOR4:
dst=base->body+d>>3;
d=base->plane_size;
bit=1<<(x&7);
not_bit=~bit;
c=color.u1[0];
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
if (c & 1)
*dst|=bit;
else
*dst&=not_bit;
dst+=d;
if (c & 2)
*dst|=bit;
else
*dst&=not_bit;
dst+=d;
if (c & 4)
*dst|=bit;
else
*dst&=not_bit;
dst+=d;
if (c & 8)
*dst|=bit;
else
*dst&=not_bit;
break;
case ROPB_COLLISION:
c2=0;
if (*dst&bit)
c2+=1;
dst+=d;
if (*dst&bit)
c2+=2;
dst+=d;
if (*dst&bit)
c2+=4;
dst+=d;
if (*dst&bit)
c2+=8;
if (c2!=bkcolor.u1[0])
base->collision_cnt++;
break;
case ROPB_XOR:
if (c & 1) *dst^=bit;
dst+=d;
if (c & 2) *dst^=bit;
dst+=d;
if (c & 4) *dst^=bit;
dst+=d;
if (c & 8) *dst^=bit;
break;
case ROPB_OR:
if (c & 1) *dst|=bit;
dst+=d;
if (c & 2) *dst|=bit;
dst+=d;
if (c & 4) *dst|=bit;
dst+=d;
if (c & 8) *dst|=bit;
break;
case ROPB_CLEAR_BITS:
if (c & 1) *dst&=not_bit;
dst+=d;
if (c & 2) *dst&=not_bit;
dst+=d;
if (c & 4) *dst&=not_bit;
dst+=d;
if (c & 8) *dst&=not_bit;
break;
}
break;
case BMT_COLOR4_U1:
dst=base->body+d;
c=color.u1[0]&15;
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
*dst=c;
break;
case ROPB_COLLISION:
if (*dst!=bkcolor.u1[0])
base->collision_cnt++;
break;
case ROPB_XOR:
*dst^=c;
break;
case ROPB_OR:
*dst|=c;
break;
case ROPB_CLEAR_BITS:
*dst&=c^15;
break;
}
break;
case BMT_MONO:
c=color&0xFFFFFF;
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
AssignBit(base->body,d,c);
break;
case ROPB_COLLISION:
if (c) {
if (bkcolor&0xFFFFFF)
base->collision_cnt+=Bt(base->body,d);
else
base->collision_cnt+=!Bt(base->body,d);
} else {
if (bkcolor&0xFFFFFF)
base->collision_cnt+=!Bt(base->body,d);
else
base->collision_cnt+=Bt(base->body,d);
}
break;
case ROPB_XOR:
if (c)
Btc(base->body,d);
break;
case ROPB_OR:
if (c)
Bts(base->body,d);
break;
case ROPB_CLEAR_BITS:
if (c)
Btr(base->body,d);
break;
}
break;
}
if (base->mask) {
base->mask->brush=base->brush;
base->mask->color=WHITE;
if (base->color.u1[3]==ROPB_CLEAR_MASK_EQU)
base->mask->color=ROPB_EQU+BLACK;
else if (base->color.u1[3]==ROPB_CLEAR_MASK_TRANSPARENT)
base->mask->color=ROPB_TRANSPARENT+BLACK;
else
base->mask->color.u1[3]=base->color.u1[3];
GrPlot0(base->mask,x,y);
}
}
public I8 GrPeek0(GrBitMap *base,I8 x,I8 y)
{ //No clipping or transformation
U8 d,c;
U1 *src,bit;
d=base->width_internal*(y+base->top_margin)+
x+base->left_margin;
switch (base->type) {
case BMT_COLOR4:
if (base->mask && !Bt(base->mask->body,d))
return MAX_I4;
src=base->body+d>>3;
bit=1<<(x&7);
d=base->plane_size;
c=0;
if (*src & bit)
c|=1;
src+=d;
if (*src & bit)
c|=2;
src+=d;
if (*src & bit)
c|=4;
src+=d;
if (*src & bit)
c|=8;
return c;
case BMT_COLOR4_U1:
if (base->mask && !Bt(base->mask->body,d))
return MAX_I4;
src=base->body+d;
return *src;
case BMT_MONO:
if (base->mask && !Bt(base->mask->body,d))
return MAX_I4;
return Bt(base->body,d);
}
}
#help_index "Graphics;Graphics/Bitmaps"
public BoolI8 GrBlot(GrBitMap *base,I8 my_x,I8 my_y,GrBitMap *img)
{ //Clipping but not transformation
I8 x=my_x,y=my_y,reg i,i1,i2,i3,j,k,k1,kk,kk1,w1,h1,w2,h2,plane,plane1,reg bit_mask,reg
bit_shift,p,p1,dist;
U1 reg *ptr;
U2 reg *ptr1;
I8 color,color2,reg color_byte,c,plane_size,plane_size1,plane_limit,plane_limit1;
w1=x<0 ?-x:0;
h1=y<0 ?-y:0;
w2=img->width;
h2=img->height;
if (base->flags & BMF_SCREEN_BITMAP) {
x+=base->win_tss->win_pixel_left;
y+=base->win_tss->win_pixel_top;
}
if (base->flags & BMF_LOCATE_NEAREST) { //TODO:Untested
dist=DistI8(x+img->width>>1,y+img->height>>1,base->cur_x,base->cur_y);
if (dist<=base->nearest_dist) {
base->nearest_grelem_num=base->cur_grelem_num;
base->nearest_dist=dist;
}
}
if (base->flags & BMF_SCREEN_BITMAP) {
if (x+w1<0) w1=-x;
if (x+w2>base->win_tss->win_pixel_right+1)
w2=base->win_tss->win_pixel_right+1-x;
if (y+h1<0) h1=-y;
if (y+h2>base->win_tss->win_pixel_bottom+1)
h2=base->win_tss->win_pixel_bottom+1-y;
}
x+=base->left_margin;
y+=base->top_margin;
if (x+w2>base->right_margin)
w2=base->right_margin-x;
if (y+h2>base->bottom_margin)
h2=base->bottom_margin-y;
if (w1<w2<=img->width && h1<h2<=img->height &&
(!(base->flags & BMF_SCREEN_BITMAP) ||
base->flags&BMF_ON_TOP ||
(!IsPixelCovered(base->win_tss,x+w1-base->left_margin,y+h1-base->top_margin) &&
!IsPixelCovered(base->win_tss,x+w2-base->left_margin,y+h2-base->top_margin)))) {
if (base->flags & BMF_RECORD_EXTENTS) {
if (x+w1<base->min_x) base->min_x=x+w1;
if (x+w2-1>base->max_x) base->max_x=x+w2-1;
if (y+h1<base->min_y) base->min_y=y+h1;
if (y+h2-1>base->max_y) base->max_y=y+h2-1;
}
if (base->flags & BMF_DONT_DRAW)
return TRUE;
color=base->color;
i1=(-w1)&7;
if (i1>w2) i1=w2;
i2=w2-w1-i1;
if (i2<0)
i2=0;
else
i2>>=3;
i3=w2-w1-i2<<3-i1;
bit_shift=x&7;
bit_mask=-1-255<<bit_shift;
switch (color.u1[3]) {
case ROPB_COLLISION:
plane_size=img->plane_size<<3;
plane_size1=base->plane_size<<3;
switch (base->type) {
case BMT_COLOR4:
plane_limit=plane_size*4;
plane_limit1=plane_size1*4;
break;
case BMT_MONO:
plane_limit=plane_size;
plane_limit1=plane_size1;
break;
}
color =base->bkcolor&0xFFFFFF;
color2=img->bkcolor &0xFFFFFF;
switch (img->type) {
case BMT_COLOR4:
k=h1*img->width_internal;
k1=(h1+y)*base->width_internal+x;
for (j=h2-h1;j;j--) {
for (i=w1;i<w2;i++) {
if (base->type==BMT_COLOR4_U1)
c=base->body><(U1 *)[k1+i];
else {
c=0;
for (plane1=0,p=1;plane1<plane_limit1;
plane1+=plane_size1,p<<=1)
if (Bt(base->body,k1+i+plane1))
c+=p;
}
if (c!=color) {
c=0;
for (plane=0,p=1;plane<plane_limit;
plane+=plane_size,p<<=1)
if (Bt(img->body,k+i+plane))
c+=p;
if (c!=color2)
base->collision_cnt++;
}
}
k+=img->width_internal;
k1+=base->width_internal;
}
break;
case BMT_COLOR4_U1:
k=h1*img->width_internal;
k1=(h1+y)*base->width_internal+x;
for (j=h2-h1;j;j--) {
for (i=w1;i<w2;i++) {
if (base->type==BMT_COLOR4_U1)
c=base->body><(U1 *)[k1+i];
else {
c=0;
for (plane1=0,p=1;plane1<plane_limit1;
plane1+=plane_size1,p<<=1)
if (Bt(base->body,k1+i+plane1))
c+=p;
}
if (c!=color) {
if (img->body><(U1 *)[k+i]!=color2)
base->collision_cnt++;
}
}
k+=img->width_internal;
k1+=base->width_internal;
}
break;
case BMT_MONO:
k=h1*img->width_internal;
k1=(h1+y)*base->width_internal+x;
for (j=h2-h1;j;j--) {
for (i=w1;i<w2;i++) {
if (base->type==BMT_COLOR4_U1)
c=base->body><(U1 *)[k1+i];
else {
c=0;
for (plane1=0,p=1;plane1<plane_limit1;
plane1+=plane_size1,p<<=1)
if (Bt(base->body,k1+i+plane1))
c+=p;
}
if (c!=color) {
if (Bt(img->body,k+i)!=color2)
base->collision_cnt++;
}
}
k+=img->width_internal;
k1+=base->width_internal;
}
break;
}
break;
case ROPB_TRANSPARENT:
case ROPB_CLEAR_MASK_TRANSPARENT:
switch (img->type) {
case BMT_COLOR4:
plane_size=img->plane_size<<3;
plane_limit=plane_size*4;
color2=img->bkcolor &0xFFFFFF;
k=h1*img->width_internal;
for (j=h1;j<h2;j++) {
for (i=w1;i<w2;i++) {
c=0;
for (plane=0,p=1;plane<plane_limit;
plane+=plane_size,p<<=1)
if (Bt(img->body,k+i+plane))
c+=p;
if (c!=color2) {
base->color=c;
GrPlot0(base,x+i-base->left_margin,y+j-base->top_margin);
}
}
k+=img->width_internal;
}
base->color=color;
break;
case BMT_COLOR4_U1:
color2=img->bkcolor &0xFFFFFF;
k=h1*img->width_internal;
for (j=h1;j<h2;j++) {
for (i=w1;i<w2;i++) {
c=img->body><(U1 *)[k+i];
if (c!=color2) {
base->color=c;
GrPlot0(base,x+i-base->left_margin,y+j-base->top_margin);
}
}
k+=img->width_internal;
}
base->color=color;
break;
default:
goto here1;
}
break;
default:
here1:
plane_size=img->plane_size<<3;
plane_size1=base->plane_size<<3;
switch (base->type) {
case BMT_COLOR4:
plane_limit=plane_size*4;
plane_limit1=plane_size1*4;
break;
case BMT_COLOR4_U1:
if (img->type==BMT_COLOR4)
plane_limit=plane_size*4;
else
plane_limit=plane_size;
break;
case BMT_MONO:
plane_limit=plane_size;
plane_limit1=plane_size1;
break;
}
if (base->type==BMT_COLOR4 ||base->type==BMT_COLOR4_U1 ||img->type==BMT_MONO) {
if (base->type==BMT_COLOR4_U1) {
switch (img->type) {
case BMT_COLOR4:
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
for (p1=0,p=1,plane=0;plane<plane_limit;
plane+=plane_size,p<<=1,p1++) {
kk=h1*img->width_internal+w1;
kk1=(h1+y)*base->width_internal+x+w1;
for (j=h2-h1;j;j--) {
k=kk+plane;
ptr=img->body;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--)
AssignBit(ptr1><(U1 *)++,p1,Bt(ptr,k++));
kk+=img->width_internal;
kk1+=base->width_internal;
}
}
break;
case ROPB_XOR:
for (p1=0,p=1,plane=0;plane<plane_limit;
plane+=plane_size,p<<=1,p1++) {
kk=h1*img->width_internal+w1;
kk1=(h1+y)*base->width_internal+x+w1;
for (j=h2-h1;j;j--) {
k=kk+plane;
ptr=img->body;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--,ptr1><(U1 *)++)
if (Bt(ptr,k++))
Btc(ptr1,p1);
kk+=img->width_internal;
kk1+=base->width_internal;
}
}
break;
case ROPB_OR:
for (p1=0,p=1,plane=0;plane<plane_limit;
plane+=plane_size,p<<=1,p1++) {
kk=h1*img->width_internal+w1;
kk1=(h1+y)*base->width_internal+x+w1;
for (j=h2-h1;j;j--) {
k=kk+plane;
ptr=img->body;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--,ptr1><(U1 *)++)
if (Bt(ptr,k++))
Bts(ptr1,p1);
kk+=img->width_internal;
kk1+=base->width_internal;
}
}
break;
case ROPB_CLEAR_BITS:
for (p1=0,p=1,plane=0;plane<plane_limit;
plane+=plane_size,p<<=1,p1++) {
kk=h1*img->width_internal+w1;
kk1=(h1+y)*base->width_internal+x+w1;
for (j=h2-h1;j;j--) {
k=kk+plane;
ptr=img->body;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--,ptr1><(U1 *)++)
if (Bt(ptr,k++))
Btr(ptr1,p1);
kk+=img->width_internal;
kk1+=base->width_internal;
}
}
break;
}
break;
case BMT_COLOR4_U1:
for (p1=0,p=1,plane=0;plane<plane_limit;
plane+=plane_size,p<<=1,p1++) {
kk=h1*img->width_internal+w1;
kk1=(h1+y)*base->width_internal+x+w1;
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
for (j=h2-h1;j;j--) {
ptr=img->body+kk;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--)
*ptr1><(U1 *)++=*ptr++;
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
case ROPB_XOR:
for (j=h2-h1;j;j--) {
ptr=img->body+kk;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--)
*ptr1><(U1 *)++^=*ptr++;
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
case ROPB_OR:
for (j=h2-h1;j;j--) {
ptr=img->body+kk;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--)
*ptr1><(U1 *)++|=*ptr++;
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
case ROPB_CLEAR_BITS:
for (j=h2-h1;j;j--) {
ptr=img->body+kk;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--)
*ptr1><(U1 *)++&=~*ptr++;
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
}
}
break;
case BMT_MONO:
for (p1=0,p=1,plane=0;plane<plane_limit;
plane+=plane_size,p<<=1,p1++) {
kk=h1*img->width_internal+w1;
kk1=(h1+y)*base->width_internal+x+w1;
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
for (j=h2-h1;j;j--) {
k=kk;
ptr=img->body;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--)
if (Bt(ptr,k++))
*ptr1><(U1 *)++=color.u1[0];
else
*ptr1><(U1 *)++=0;
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
for (j=h2-h1;j;j--) {
k=kk;
ptr=img->body;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--,ptr1><(U1 *)++)
if (Bt(ptr,k++))
*ptr1><(U1 *)=color.u1[0];
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
case ROPB_XOR:
for (j=h2-h1;j;j--) {
k=kk;
ptr=img->body;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--,ptr1><(U1 *)++)
if (Bt(ptr,k++))
*ptr1><(U1 *)^=color.u1[0];
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
case ROPB_OR:
for (j=h2-h1;j;j--) {
k=kk;
ptr=img->body;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--,ptr1><(U1 *)++)
if (Bt(ptr,k++))
*ptr1><(U1 *)|=color.u1[0];
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
case ROPB_CLEAR_BITS:
for (j=h2-h1;j;j--) {
k=kk;
ptr=img->body;
ptr1=base->body+kk1;
for (i=w2-w1;i;i--,ptr1><(U1 *)++)
if (Bt(ptr,k++))
*ptr1><(U1 *)&=~color.u1[0];
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
}
break;
}
break;
}
} else {
for (p1=0,p=1,plane=0,plane1=0;plane<plane_limit;
plane+=plane_size,plane1+=plane_size1,p<<=1,p1++) {
if (Bt(&color,p1))
color_byte=255;
else
color_byte=0;
kk=h1*img->width_internal+w1;
kk1=(h1+y)*base->width_internal+x+w1;
switch (img->type) {
case BMT_COLOR4:
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
for (j=h2-h1;j;j--) {
k=kk+plane;
k1=kk1+plane1;
ptr=img->body;
ptr1=base->body;
for (i=0;i<i1;i++,k1++)
AssignBit(ptr1,k1,Bt(ptr,k++));
ptr+=k>>3;
ptr1><(U1 *)+=k1>>3;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
&n