#help_index "Graphics"
public BoolI8 GrPlot0(GrBitMap *base,I8 x,I8 y)
{ //No clipping or transformation or pen width
U1 *dst;
I4 *db;
U8 d,c,c2,bit,not_bit,dist,
color=base->color,bkcolor=base->bkcolor;
GrBitMap *mask;
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 TRUE;
d=base->width_internal*y+x;
if (db=base->depth_buffer) {
db+=d;
if (0<=base->db_z<=*db)
*db=base->db_z;
else
return TRUE;
}
if (color&(ROP_DITHER|ROP_PROBABILITY_DITHER)) {
if (color&ROP_PROBABILITY_DITHER) {
if (RandU2<base->dither_probability) {
color.u1[7]=color.u1[3];
color.u4[0]=color.u4[1];
}
} else {
if ((x^y)&1) {
color.u1[7]=color.u1[3];
color.u4[0]=color.u4[1];
}
}
}
nobound_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];
nobound_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;
}
break;
case BMT_MONO:
c=color&0xFFFFFF00FFFFFF;
nobound_switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
BEqu(base->body,d,c);
break;
case ROPB_COLLISION:
if (c) {
if (bkcolor&0xFFFFFF00FFFFFF)
base->collision_cnt+=Bt(base->body,d);
else
base->collision_cnt+=!Bt(base->body,d);
} else {
if (bkcolor&0xFFFFFF00FFFFFF)
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;
}
break;
}
if (mask=base->mask) {
mask->brush=base->brush;
mask->color=WHITE;
if (base->color.u1[3]==ROPB_CLEAR_MASK_EQU)
mask->color=ROPB_EQU+BLACK;
else if (base->color.u1[3]==ROPB_CLEAR_MASK_TRANSPARENT)
mask->color=ROPB_TRANSPARENT+BLACK;
else
mask->color.u1[3]=base->color.u1[3];
mask->win_task=base->win_task;
if (mask->alias)
mask->alias->flags|=BMF_DIRTY;
GrPlot0(mask,x,y);
}
return TRUE;
}
public I8 GrPeek0(GrBitMap *base,I8 x,I8 y)
{ //No clipping or transformation
U8 d,c,bit;
U1 *src;
d=base->width_internal*y+x;
nobound_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_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 _x,I8 _y,GrBitMap *img)
{ //Clipping but not transformation
I8 x=_x,y=_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;
I4 *db=base->depth_buffer;
GrBitMap *mask;
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_task->win_pixel_left;
y+=base->win_task->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_task->win_pixel_right+1)
w2=base->win_task->win_pixel_right+1-x;
if (y+h1<0) h1=-y;
if (y+h2>base->win_task->win_pixel_bottom+1)
h2=base->win_task->win_pixel_bottom+1-y;
}
if (x+w2>base->width)
w2=base->width-x;
if (y+h2>base->height)
h2=base->height-y;
if (w1<w2<=img->width && h1<h2<=img->height &&
(!(base->flags & BMF_SCREEN_BITMAP) ||
base->flags&BMF_ON_TOP ||
!IsPixelCovered(base->win_task,x+w1,y+h1) &&
!IsPixelCovered(base->win_task,x+w2,y+h2))) {
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;
base->depth_buffer=NULL;
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;
nobound_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;
nobound_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++) {
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_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++) {
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:
if (img->type==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,y+j);
}
}
k+=img->width_internal;
}
base->color=color;
} else
goto here1;
break;
default:
here1:
plane_size=img->plane_size<<3;
plane_size1=base->plane_size<<3;
nobound_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;
}
if (base->type==BMT_COLOR4 ||img->type==BMT_MONO) {
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;
nobound_switch (img->type) {
case BMT_COLOR4:
nobound_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++)
BEqu(ptr1,k1,Bt(ptr,k++));
ptr+=k>>3;
ptr1><(U1 *)+=k1>>3;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
*ptr1=*ptr1 & bit_mask | *ptr++<<bit_shift;
ptr=img->body;
ptr1=base->body;
k+=i2<<3;
k1+=i2<<3;
for (i=0;i<i3;i++,k1++)
BEqu(ptr1,k1,Bt(ptr,k++));
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
case ROPB_XOR:
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++)
if (Bt(ptr,k++))
Btc(ptr1,k1);
ptr+=k>>3;
ptr1><(U1 *)+=k1>>3;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
*ptr1^=*ptr++<<bit_shift;
ptr=img->body;
ptr1=base->body;
k+=i2<<3;
k1+=i2<<3;
for (i=0;i<i3;i++,k1++)
if (Bt(ptr,k++))
Btc(ptr1,k1);
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
}
break;
case BMT_MONO:
nobound_switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
for (j=h2-h1;j;j--) {
k=kk;
k1=kk1+plane1;
ptr=img->body;
ptr1=base->body;
for (i=0;i<i1;i++,k1++)
BEqu(ptr1,k1,color_byte&&Bt(ptr,k++));
ptr+=k>>3;
ptr1><(U1 *)+=k1>>3;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
*ptr1=*ptr1 & bit_mask | (*ptr++ & color_byte)<<bit_shift;
ptr=img->body;
ptr1=base->body;
k+=i2<<3;
k1+=i2<<3;
for (i=0;i<i3;i++,k1++)
BEqu(ptr1,k1,color_byte && Bt(ptr,k++));
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;
k1=kk1+plane1;
ptr=img->body;
ptr1=base->body;
if (!(img->bkcolor&0xFFFFFF)) {
for (i=0;i<i1;i++,k1++)
if (Bt(ptr,k++))
BEqu(ptr1,k1,color_byte);
ptr+=k>>3;
ptr1><(U1 *)+=k1>>3;
for (i=0;i<i2;i++,ptr1><(U1 *)++) {
bit_mask=~(*ptr<<bit_shift);
*ptr1=*ptr1 & bit_mask | (*ptr++ & color_byte)<<bit_shift;
}
ptr=img->body;
ptr1=base->body;
k+=i2<<3;
k1+=i2<<3;
for (i=0;i<i3;i++,k1++)
if (Bt(ptr,k++))
BEqu(ptr1,k1,color_byte);
} else {
for (i=0;i<i1;i++,k1++)
if (!Bt(ptr,k++))
BEqu(ptr1,k1,color_byte);
ptr+=k>>3;
ptr1><(U1 *)+=k1>>3;
for (i=0;i<i2;i++,ptr1><(U1 *)++) {
bit_mask=~((~*ptr&0xFF)<<bit_shift);
*ptr1=*ptr1 & bit_mask | (~*ptr++ & color_byte)<<bit_shift;
}
ptr=img->body;
ptr1=base->body;
k+=i2<<3;
k1+=i2<<3;
for (i=0;i<i3;i++,k1++)
if (!Bt(ptr,k++))
BEqu(ptr1,k1,color_byte);
}
kk+=img->width_internal;
kk1+=base->width_internal;
}
break;
case ROPB_XOR:
if (color_byte) {
for (j=h2-h1;j;j--) {
k=kk;
k1=kk1+plane1;
ptr=img->body;
ptr1=base->body;
for (i=0;i<i1;i++,k1++)
if (Bt(ptr,k++))
Btc(ptr1,k1);
ptr+=k>>3;
ptr1><(U1 *)+=k1>>3;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
*ptr1^=*ptr++<<bit_shift;
ptr=img->body;
ptr1=base->body;
k+=i2<<3;
k1+=i2<<3;
for (i=0;i<i3;i++,k1++)
if (Bt(ptr,k++))
Btc(ptr1,k1);
kk+=img->width_internal;
kk1+=base->width_internal;
}
}
break;
}
break;
}
}
} else {
if (img->type==BMT_COLOR4) {
plane_limit=plane_size*4;
k=h1*img->width_internal;
kk1=(h1+y)*base->width_internal+x;
for (j=h2-h1;j;j--) {
k1=kk1+w1;
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!=img->bkcolor)
Bts(base->body,k1);
k1++;
}
k+=img->width_internal;
kk1+=base->width_internal;
}
}
}
break;
}
base->depth_buffer=db;
if (mask=base->mask) {
if (color.u1[3]!=ROPB_COLLISION &&
(!(color.u1[3]==ROPB_TRANSPARENT ||
color.u1[3]==ROPB_CLEAR_MASK_TRANSPARENT) ||
img->type==BMT_MONO)) {
mask->brush=base->brush;
mask->color=WHITE;
if (base->color.u1[3]==ROPB_CLEAR_MASK_EQU)
mask->color=ROPB_EQU+BLACK;
else if (base->color.u1[3]==ROPB_CLEAR_MASK_TRANSPARENT)
mask->color=ROPB_TRANSPARENT+BLACK;
else
mask->color.u1[3]=base->color.u1[3];
mask->win_task=base->win_task;
if (mask->alias)
mask->alias->flags|=BMF_DIRTY;
GrBlot(mask,_x,_y,img);
}
}
return TRUE;
} else
return FALSE;
}
//This makes lots of assumptions.
U0 GrBlotWithMask(GrBitMap *base,GrBitMap *img)
{
U8 reg *mask_ptr,reg *m_dst,reg *m_src;
U8 reg j,row,reg col,plane,
d0=img->width_internal>>6;
m_src=img->body;
m_dst=base->body;
for (plane=1;plane<0x10;plane<<=1) {
mask_ptr=img->mask->body;
for (row=0;row<img->height;row++)
for (col=0;col<d0;col++) {
if (j=*mask_ptr)
*m_dst=*m_dst&~j|*m_src&j;
m_dst++;
mask_ptr++;
m_src++;
}
}
}
public GrBitMap *GrExtractBitMap(GrBitMap *b,I8 x1,I8 y1,I8 x2,I8 y2,TaskStruct *task=NULL)
{
GrBitMap *result;
if (x1>x2) SwapU8(&x1,&x2);
if (y1>y2) SwapU8(&y1,&y2);
if (b->flags & BMF_SCREEN_BITMAP) {
x1+=b->win_task->win_pixel_left;
y1+=b->win_task->win_pixel_top;
x2+=b->win_task->win_pixel_left;
y2+=b->win_task->win_pixel_top;
}
result=GrNew(b->type,x2-x1+1,y2-y1+1,task);
result->color=1;
GrBlot(result,-x1,-y1,b);
result->color=0;
return result;
}
#help_index "Graphics"
public BoolI8 GrPutS(GrBitMap *base,I8 _x,I8 _y,U1 *_s)
{ //Clipping but not transformation
U1 *s=_s;
I8 x=_x,y=_y,len,ch,reg i,i1,i2,i3,j,k1,kk1,w1,h1,w2,h2,plane1,reg bit_mask,reg bit_shift,p,p1,dist,l,l1;
U1 reg *ptr,*font_ptr,*s1;
U2 reg *ptr1,*ptr2;
I8 color,reg color_byte,c,plane_size1,plane_limit1;
GrBitMap *mask;
if (!_s) return FALSE;
len=StrLen(s);
w1=x<0 ?-x:0;
h1=y<0 ?-y:0;
w2=len*FONT_WIDTH;
h2=FONT_HEIGHT;
if (base->flags & BMF_SCREEN_BITMAP) {
x+=base->win_task->win_pixel_left;
y+=base->win_task->win_pixel_top;
}
if (base->flags & BMF_LOCATE_NEAREST) { //TODO:Untested
dist=DistI8(x+w2>>1,y+h2>>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_task->win_pixel_right+1)
w2=base->win_task->win_pixel_right+1-x;
if (y+h1<0) h1=-y;
if (y+h2>base->win_task->win_pixel_bottom+1)
h2=base->win_task->win_pixel_bottom+1-y;
}
if (x+w2>base->width)
w2=base->width-x;
if (y+h2>base->height)
h2=base->height-y;
if (w1<w2<=len*FONT_WIDTH && h1<h2<=FONT_HEIGHT &&
(!(base->flags & BMF_SCREEN_BITMAP) ||
base->flags&BMF_ON_TOP ||
!IsPixelCovered(base->win_task,x+w1,y+h1) &&
!IsPixelCovered(base->win_task,x+w2,y+h2))) {
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;
plane_size1=base->plane_size<<3;
nobound_switch (base->type) {
case BMT_COLOR4:
plane_limit1=plane_size1*4;
break;
case BMT_MONO:
plane_limit1=plane_size1;
break;
}
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+w1)&7;
bit_mask=-1-255<<bit_shift;
s+=w1/FONT_WIDTH;
l=w1%FONT_WIDTH;
if (color.u1[3]==ROPB_COLLISION) {
color =base->bkcolor&0xFFFFFF;
ch=*s++;
font_ptr=&grfont[(FONT_WIDTH*(FONT_HEIGHT*ch+h1))>>3];
for (i=w1;i<w2;i++) {
k1=(h1+y)*base->width_internal+x;
ptr=font_ptr;
for (j=h2-h1;j;j--) {
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(ptr,l))
base->collision_cnt++;
}
k1+=base->width_internal;
ptr++;
}
if (++l==FONT_WIDTH) {
ch=*s++;
font_ptr=&grfont[(FONT_WIDTH*(FONT_HEIGHT*ch+h1))>>3];
l=0;
}
}
} else {
for (p1=0,plane1=0;plane1<plane_limit1;plane1+=plane_size1,p1++) {
s1=s;
l1=l;
if (Bt(&color,p1))
color_byte=255;
else
color_byte=0;
ptr2=base->body+plane1>>3;
kk1=(h1+y)*base->width_internal+x+w1;
ch=*s1++;
font_ptr=&grfont[(FONT_WIDTH*(FONT_HEIGHT*ch+h1))>>3];
for (i=0;i<i1;i++) {
k1=kk1;
ptr=font_ptr;
nobound_switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
for (j=h2-h1;j;j--) {
if (Bt(ptr++,l1))
BEqu(ptr2,k1,color_byte);
k1+=base->width_internal;
}
break;
case ROPB_XOR:
if (color_byte)
for (j=h2-h1;j;j--) {
if (Bt(ptr++,l1))
Btc(ptr2,k1);
k1+=base->width_internal;
}
break;
}
if (++l1==FONT_WIDTH) {
ch=*s1++;
font_ptr=&grfont[(FONT_WIDTH*(FONT_HEIGHT*ch+h1))>>3];
l1=0;
}
}
kk1+=i1;
ptr2><(U1 *)+=kk1>>3;
for (i=0;i<i2;i++) {
ptr1=ptr2;
ptr=font_ptr;
nobound_switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
for (j=h2-h1;j;j--) {
bit_mask=~(*ptr<<bit_shift);
*ptr1=*ptr1 & bit_mask | (*ptr++ & color_byte)<<bit_shift;
ptr1><(U1 *)+=base->width_internal>>3;
}
break;
case ROPB_XOR:
if (color_byte)
for (j=h2-h1;j;j--) {
*ptr1^=*ptr++<<bit_shift;
ptr1><(U1 *)+=base->width_internal>>3;
}
break;
}
ptr2><(U1 *)++;
ch=*s1++;
font_ptr=&grfont[(FONT_WIDTH*(FONT_HEIGHT*ch+h1))>>3];
}
kk1+=i2<<3;
ptr1=base->body+plane1>>3;
for (i=0;i<i3;i++) {
ptr=font_ptr;
k1=kk1+i;
nobound_switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
for (j=h2-h1;j;j--) {
if (Bt(ptr++,l1))
BEqu(ptr1,k1,color_byte);
k1+=base->width_internal;
}
break;
case ROPB_XOR:
if (color_byte)
for (j=h2-h1;j;j--) {
if (Bt(ptr++,l1))
Btc(ptr1,k1);
k1+=base->width_internal;
}
break;
}
if (++l1==FONT_WIDTH) {
ch=*s1++;
font_ptr=&grfont[(FONT_WIDTH*(FONT_HEIGHT*ch+h1))>>3];
l1=0;
}
}
}
}
if (mask=base->mask) {
mask->brush=base->brush;
mask->color=WHITE;
if (base->color.u1[3]==ROPB_CLEAR_MASK_EQU)
mask->color=ROPB_EQU+BLACK;
else if (base->color.u1[3]==ROPB_CLEAR_MASK_TRANSPARENT)
mask->color=ROPB_TRANSPARENT+BLACK;
else
mask->color.u1[3]=base->color.u1[3];
mask->win_task=base->win_task;
if (mask->alias)
mask->alias->flags|=BMF_DIRTY;
GrPutS(mask,_x,_y,_s);
}
return TRUE;
} else
return FALSE;
}
public BoolI8 GrVPutS(GrBitMap *base,I8 _x,I8 _y,U1 *_s)
{ //Vertical text
U1 buf[2];
BoolI1 result=FALSE,first=TRUE;
buf[1]=0;
while (buf[0]=*_s++) {
if (first) {
result=GrPutS(base,_x,_y,buf);
first=FALSE;
} else
GrPutS(base,_x,_y,buf);
_y+=FONT_HEIGHT;
}
return result;
}
public U0 GrPrintF(GrBitMap *base,I8 x,I8 y,U1 *fmt,...)
{
U1 *buf=SPrintFJoin(NULL,fmt,argc,argv);
GrPutS(base,x,y,buf);
Free(buf);
}
public U0 GrVPrintF(GrBitMap *base,I8 x,I8 y,U1 *fmt,...)
{ //Vertical text
U1 *buf=SPrintFJoin(NULL,fmt,argc,argv);
GrVPutS(base,x,y,buf);
Free(buf);
}
public BoolI8 GrRect(GrBitMap *base,I8 _x,I8 _y,I8 w,I8 h)
{ //Clipping but not transformation
I8 x=_x,y=_y;
I8 i,i1,i2,i3,j,k1,kk1,w1,h1,w2,h2,plane1,bit_mask,bit_shift,p,p1,dist;
U2 *ptr1;
I8 color,color_byte,c,plane_size1,plane_limit1,dither_colors;
BoolI1 dither,probability_dither;
GrBitMap *mask;
w1=x<0 ?-x:0;
h1=y<0 ?-y:0;
w2=w;
h2=h;
if (base->flags & BMF_SCREEN_BITMAP) {
x+=base->win_task->win_pixel_left;
y+=base->win_task->win_pixel_top;
}
if (base->flags & BMF_LOCATE_NEAREST) { //TODO:Untested
if (base->cur_x>=x && base->cur_y>=y &&
base->cur_x<=x+w && base->cur_y<=y+h) {
base->nearest_grelem_num=base->cur_grelem_num;
base->nearest_dist=0;
} else {
dist=DistI8(x+w>>1,y+h>>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_task->win_pixel_right+1)
w2=base->win_task->win_pixel_right+1-x;
if (y+h1<0) h1=-y;
if (y+h2>base->win_task->win_pixel_bottom+1)
h2=base->win_task->win_pixel_bottom+1-y;
}
if (x+w2>base->width)
w2=base->width-x;
if (y+h2>base->height)
h2=base->height-y;
if (w1<w2<=w && h1<h2<=h &&
(!(base->flags & BMF_SCREEN_BITMAP) ||
base->flags&BMF_ON_TOP ||
!IsPixelCovered(base->win_task,x+w1,y+h1) &&
!IsPixelCovered(base->win_task,x+w2,y+h2))) {
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;
if (color&(ROP_DITHER|ROP_PROBABILITY_DITHER)) {
dither=TRUE;
if (color&ROP_PROBABILITY_DITHER) {
probability_dither=TRUE;
color.u1[7]=color.u1[3];
dither_colors=color;
} else {
probability_dither=FALSE;
color.u1[7]=color.u1[3];
}
} else
dither=FALSE;
plane_size1=base->plane_size<<3;
nobound_switch (base->type) {
case BMT_COLOR4:
plane_limit1=plane_size1*4;
break;
case BMT_MONO:
plane_limit1=plane_size1;
break;
}
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;
if (dither) {
if (probability_dither) {
if (RandU2<base->dither_probability)
color.u4[0]=dither_colors.u4[1];
else
color.u4[0]=dither_colors.u4[0];
} else
if (((x+w1)^(y+h1))&1)
SwapU4(&color.u4[0],&color.u4[1]);
if (color.u1[3]==ROPB_COLLISION) {
color =base->bkcolor&0xFFFFFF;
k1=(h1+y)*base->width_internal+x;
for (j=h2-h1;j;j--) {
for (i=w1;i<w2;i++) {
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)
base->collision_cnt++;
}
k1+=base->width_internal;
}
} else {
bit_mask=-1-0x55<<bit_shift;
for (p1=0,plane1=0;plane1<plane_limit1;
plane1+=plane_size1,p1++) {
kk1=(h1+y)*base->width_internal+x+w1+plane1;
nobound_switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
for (j=h2-h1;j;j--) {
if (Bt(&color,p1))
color_byte=0x55<<bit_shift;
else
color_byte=0;
k1=kk1;
for (i=0;i<i1;i+=2,k1+=2)
BEqu(base->body,k1,color_byte);
k1-=i1&1;
ptr1=k1>>3+base->body;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
*ptr1=*ptr1 & bit_mask | color_byte;
k1+=i2<<3;
for (i=0;i<i3;i+=2,k1+=2)
BEqu(base->body,k1,color_byte);
kk1+=base->width_internal;
if (probability_dither) {
if (RandU2<base->dither_probability)
color.u4[0]=dither_colors.u4[1];
else
color.u4[0]=dither_colors.u4[0];
} else
SwapU4(&color.u4[0],&color.u4[1]);
}
break;
case ROPB_XOR:
for (j=h2-h1;j;j--) {
if (Bt(&color,p1))
color_byte=0x55<<bit_shift;
else
color_byte=0;
if (color_byte) {
k1=kk1;
for (i=0;i<i1;i+=2,k1+=2)
Btc(base->body,k1);
k1-=i1&1;
ptr1=k1>>3+base->body;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
*ptr1^=color_byte;
k1+=i2<<3;
for (i=0;i<i3;i+=2,k1+=2)
Btc(base->body,k1);
kk1+=base->width_internal;
}
if (probability_dither) {
if (RandU2<base->dither_probability)
color.u4[0]=dither_colors.u4[1];
else
color.u4[0]=dither_colors.u4[0];
} else
SwapU4(&color.u4[0],&color.u4[1]);
}
break;
}
if (probability_dither) {
if (RandU2<base->dither_probability)
color.u4[0]=dither_colors.u4[1];
else
color.u4[0]=dither_colors.u4[0];
} else
if ((h2-h1)&1)
SwapU4(&color.u4[0],&color.u4[1]);
}
bit_mask=-1-0xAA<<bit_shift;
color=base->color;
color.u1[7]=color.u1[3];
if (probability_dither) {
if (RandU2<base->dither_probability)
color.u4[0]=dither_colors.u4[1];
else
color.u4[0]=dither_colors.u4[0];
} else
if (((x+w1+1)^(y+h1))&1)
SwapU4(&color.u4[0],&color.u4[1]);
for (p1=0,plane1=0;plane1<plane_limit1;
plane1+=plane_size1,p1++) {
kk1=(h1+y)*base->width_internal+x+1+w1+plane1;
nobound_switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
for (j=h2-h1;j;j--) {
if (Bt(&color,p1))
color_byte=0xAA<<bit_shift;
else
color_byte=0;
k1=kk1;
for (i=1;i<i1;i+=2,k1+=2)
BEqu(base->body,k1,color_byte);
k1+=i1&1;
ptr1=(k1-1)>>3+base->body;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
*ptr1=*ptr1 & bit_mask | color_byte;
k1+=i2<<3;
for (i=1;i<i3;i+=2,k1+=2)
BEqu(base->body,k1,color_byte);
kk1+=base->width_internal;
if (probability_dither) {
if (RandU2<base->dither_probability)
color.u4[0]=dither_colors.u4[1];
else
color.u4[0]=dither_colors.u4[0];
} else
SwapU4(&color.u4[0],&color.u4[1]);
}
break;
case ROPB_XOR:
for (j=h2-h1;j;j--) {
if (Bt(&color,p1))
color_byte=0xAA<<bit_shift;
else
color_byte=0;
if (color_byte) {
k1=kk1;
for (i=1;i<i1;i+=2,k1+=2)
Btc(base->body,k1);
k1+=i1&1;
ptr1=(k1-1)>>3+base->body;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
*ptr1^=color_byte;
k1+=i2<<3;
for (i=1;i<i3;i+=2,k1+=2)
Btc(base->body,k1);
kk1+=base->width_internal;
}
if (probability_dither) {
if (RandU2<base->dither_probability)
color.u4[0]=dither_colors.u4[1];
else
color.u4[0]=dither_colors.u4[0];
} else
SwapU4(&color.u4[0],&color.u4[1]);
}
break;
}
if (probability_dither) {
if (RandU2<base->dither_probability)
color.u4[0]=dither_colors.u4[1];
else
color.u4[0]=dither_colors.u4[0];
} else
if ((h2-h1)&1)
SwapU4(&color.u4[0],&color.u4[1]);
}
}
} else {
if (color.u1[3]==ROPB_COLLISION) {
color =base->bkcolor&0xFFFFFF;
k1=(h1+y)*base->width_internal+x;
for (j=h2-h1;j;j--) {
for (i=w1;i<w2;i++) {
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)
base->collision_cnt++;
}
k1+=base->width_internal;
}
} else
for (p1=0,plane1=0;plane1<plane_limit1;
plane1+=plane_size1,p1++) {
if (Bt(&color,p1))
color_byte=255<<bit_shift;
else
color_byte=0;
kk1=(h1+y)*base->width_internal+x+w1+plane1;
nobound_switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
for (j=h2-h1;j;j--) {
k1=kk1;
for (i=0;i<i1;i++,k1++)
BEqu(base->body,k1,color_byte);
ptr1=k1>>3+base->body;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
*ptr1=*ptr1 & bit_mask | color_byte;
k1+=i2<<3;
for (i=0;i<i3;i++,k1++)
BEqu(base->body,k1,color_byte);
kk1+=base->width_internal;
}
break;
case ROPB_XOR:
if (color_byte)
for (j=h2-h1;j;j--) {
k1=kk1;
for (i=0;i<i1;i++,k1++)
Btc(base->body,k1);
ptr1=k1>>3+base->body;
for (i=0;i<i2;i++,ptr1><(U1 *)++)
*ptr1^=color_byte;
k1+=i2<<3;
for (i=0;i<i3;i++,k1++)
Btc(base->body,k1);
kk1+=base->width_internal;
}
break;
}
}
}
if (mask=base->mask) {
mask->brush=base->brush;
mask->color=WHITE;
if (base->color.u1[3]==ROPB_CLEAR_MASK_EQU)
mask->color=ROPB_EQU+BLACK;
else if (base->color.u1[3]==ROPB_CLEAR_MASK_TRANSPARENT)
mask->color=ROPB_TRANSPARENT+BLACK;
else
mask->color.u1[3]=base->color.u1[3];
mask->win_task=base->win_task;
if (mask->alias)
mask->alias->flags|=BMF_DIRTY;
GrRect(mask,_x,_y,w,h);
}
return TRUE;
} else
return FALSE;
}
I8 GrRayLenMinus(GrBitMap *base,I8 x,I8 y)
{
I8 cnt=0,c,x3=x,y3=y,d,bit;
U1 *dst,*dst2,*mask_dst;
BoolI1 not_color=ToBool(base->flags&BMF_FILL_NOT_COLOR);
GrBitMap *mask;
if (x3<0 || y3<0)
goto gr_done;
if (base->flags & BMF_SCREEN_BITMAP) {
x3+=base->win_task->win_pixel_left;
y3+=base->win_task->win_pixel_top;
if (x3<0 || y3<0 ||
x3>base->win_task->win_pixel_right ||
y3>base->win_task->win_pixel_bottom ||
!(base->flags&BMF_ON_TOP) &&
IsPixelCovered(base->win_task,x3,y3))
goto gr_done;
}
if (x3>=base->width || y3>=base->height)
goto gr_done;
d=y3*base->width_internal;
nobound_switch (base->type) {
case BMT_COLOR4:
if (mask=base->mask)
mask_dst=mask->body-base->body;
else
mask_dst=NULL;
dst2=base->body+d>>3;
d=base->plane_size;
while (TRUE) {
x3=x;
if (x3&(FONT_WIDTH-1)==FONT_WIDTH-1) {
if (base->flags & BMF_SCREEN_BITMAP) {
if (x3<0) break;
x3+=base->win_task->win_pixel_left;
if (x3<0 || x3>base->win_task->win_pixel_right ||
x3>=base->width ||
!(base->flags&BMF_ON_TOP) &&
IsPixelCovered(base->win_task,x3,y3))
break;
} else
if (!(0<=x3<base->width))
break;
} else if (base->flags & BMF_SCREEN_BITMAP)
x3+=base->win_task->win_pixel_left;
dst=dst2+x3>>3;
bit=1<<(x3&7);
if (mask_dst)
if (!(mask_dst[dst]&bit)) {
c=MAX_I4;
goto here1a;
}
c=0;
if (*dst & bit)
c|=1;
dst+=d;
if (*dst & bit)
c|=2;
dst+=d;
if (*dst & bit)
c|=4;
dst+=d;
if (*dst & bit)
c|=8;
here1a:
if (not_color) {
if (c!=base->color2) {
cnt++;
x--;
} else
break;
} else {
if (c==base->color2) {
cnt++;
x--;
} else
break;
}
}
return cnt;
case BMT_MONO:
while (TRUE) {
x3=x;
if (x3&(FONT_WIDTH-1)==FONT_WIDTH-1) {
if (base->flags & BMF_SCREEN_BITMAP) {
if (x3<0) break;
x3+=base->win_task->win_pixel_left;
if (x3<0 || x3>base->win_task->win_pixel_right ||
x3>=base->width ||
!(base->flags&BMF_ON_TOP) &&
IsPixelCovered(base->win_task,x3,y3))
break;
} else
if (!(0<=x3<base->width))
break;
} else if (base->flags & BMF_SCREEN_BITMAP)
x3+=base->win_task->win_pixel_left;
c=1;
if (mask=base->mask)
c=Bt(mask->body,d+x3);
if (not_color) {
if (!c || Bt(base->body,d+x3)!=base->color2) {
cnt++;
x--;
} else
break;
} else {
if (c && Bt(base->body,d+x3)==base->color2) {
cnt++;
x--;
} else
break;
}
}
return cnt;
}
gr_done:
return 0;
}
I8 GrRayLen(GrBitMap *base,I8 *x1,I8 y,I8 z=0,I4 *db=NULL)
{
I8 cnt=0,d,c,c2,x=*x1,x2=x,x3=x,y3=y,dist;
BoolI1 dither,probability_dither,not_color=ToBool(base->flags&BMF_FILL_NOT_COLOR);
U1 *dst,*dst2,*mask_dst;
U8 color=base->color,bkcolor=base->bkcolor,bit,not_bit;
I4 *db2;
BoolI1 plot;
GrBitMap *mask;
if (x3<0 || y3<0)
goto gr_done;
if (base->flags & BMF_SCREEN_BITMAP) {
x3+=base->win_task->win_pixel_left;
y3+=base->win_task->win_pixel_top;
if (x3<0 || y3<0 ||
x3>base->win_task->win_pixel_right ||
y3>base->win_task->win_pixel_bottom ||
!(base->flags&BMF_ON_TOP) &&
IsPixelCovered(base->win_task,x3,y3))
goto gr_done;
}
if (x3>=base->width || y3>=base->height)
goto gr_done;
d=base->width_internal*y3;
if (db) db+=d;
color=base->color;
if (color&(ROP_DITHER|ROP_PROBABILITY_DITHER)) {
dither=TRUE;
if (color&ROP_PROBABILITY_DITHER) {
probability_dither=TRUE;
color.u1[7]=color.u1[3];
} else {
probability_dither=FALSE;
color.u1[7]=color.u1[3];
if (color&0xFFFFFF==base->color2&0xFFFFFF)
SwapU4(&color.u4[0],&color.u4[1]);
}
} else
dither=FALSE;
nobound_switch (base->type) {
case BMT_COLOR4:
if (mask=base->mask) {
mask_dst=mask->body-base->body;
if (mask->alias)
mask->alias->flags|=BMF_DIRTY;
} else
mask_dst=NULL;
dst2=base->body+d>>3;
d=base->plane_size;
while (TRUE) {
x3=x;
if (!(x3&(FONT_WIDTH-1))) {
if (base->flags & BMF_SCREEN_BITMAP) {
if (x3<0) break;
x3+=base->win_task->win_pixel_left;
if (x3<0 || x3>base->win_task->win_pixel_right ||
x3>=base->width ||
!(base->flags&BMF_ON_TOP) &&
IsPixelCovered(base->win_task,x3,y3))
break;
} else {
if (!(0<=x3<base->width))
break;
}
} else if (base->flags & BMF_SCREEN_BITMAP)
x3+=base->win_task->win_pixel_left;
dst=dst2+x3>>3;
bit=1<<(x3&7);
not_bit=~bit;
if (mask_dst)
if (!(mask_dst[dst]&bit)) {
c=MAX_I4;
goto here3a;
}
c=0;
if (*dst & bit)
c|=1;
dst+=d;
if (*dst & bit)
c|=2;
dst+=d;
if (*dst & bit)
c|=4;
dst+=d;
if (*dst & bit)
c|=8;
here3a:
if (db) {
db2=db+x3;
if (0<=z<=*db2) {
*db2=z;
plot=TRUE;
} else
plot=FALSE;
} else
plot=TRUE;
if ((not_color && c!=base->color2 ||
!not_color && c==base->color2) && plot) {
if (base->flags & BMF_LOCATE_NEAREST) {
dist=DistI8(x3,y3,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 (x3<base->min_x) base->min_x=x3;
if (x3>base->max_x) base->max_x=x3;
if (y3<base->min_y) base->min_y=y3;
if (y3>base->max_y) base->max_y=y3;
}
dst=dst2+x3>>3;
c=color.u1[0];
if (dither) {
if (probability_dither) {
if (RandU2<base->dither_probability)
c=color.u1[4];
} else
if ((x3^y3)&1)
c=color.u1[4];
}
nobound_switch (color.u1[3]) {
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
if (mask_dst)
mask_dst[dst]&=not_bit;
goto here1a;
case ROPB_EQU:
case ROPB_TRANSPARENT:
if (mask_dst)
mask_dst[dst]|=bit;
here1a:
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 (mask_dst)
mask_dst[dst]|=bit;
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;
}
cnt++;
x++;
} else
break;
}
*x1=x-1;
x=x2-1;
while (TRUE) {
x3=x;
if (x3&(FONT_WIDTH-1)==FONT_WIDTH-1) {
if (base->flags & BMF_SCREEN_BITMAP) {
if (x3<0) break;
x3+=base->win_task->win_pixel_left;
if (x3<0 || x3>base->win_task->win_pixel_right ||
x3>=base->width ||
!(base->flags&BMF_ON_TOP) &&
IsPixelCovered(base->win_task,x3,y3))
break;
} else
if (!(0<=x3<base->width))
break;
} else if (base->flags & BMF_SCREEN_BITMAP)
x3+=base->win_task->win_pixel_left;
dst=dst2+x3>>3;
bit=1<<(x3&7);
not_bit=~bit;
if (mask_dst)
if (!(mask_dst[dst]&bit)) {
c=MAX_I4;
goto here4a;
}
c=0;
if (*dst & bit)
c|=1;
dst+=d;
if (*dst & bit)
c|=2;
dst+=d;
if (*dst & bit)
c|=4;
dst+=d;
if (*dst & bit)
c|=8;
here4a:
if (db) {
db2=db+x3;
if (0<=z<=*db2) {
*db2=z;
plot=TRUE;
} else
plot=FALSE;
} else
plot=TRUE;
if ((not_color && c!=base->color2 ||
!not_color && c==base->color2) && plot) {
if (base->flags & BMF_LOCATE_NEAREST) {
dist=DistI8(x3,y3,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 (x3<base->min_x) base->min_x=x3;
if (x3>base->max_x) base->max_x=x3;
if (y3<base->min_y) base->min_y=y3;
if (y3>base->max_y) base->max_y=y3;
}
dst=dst2+x3>>3;
c=color.u1[0];
if (dither) {
if (probability_dither) {
if (RandU2<base->dither_probability)
c=color.u1[4];
} else
if ((x3^y3)&1)
c=color.u1[4];
}
nobound_switch (color.u1[3]) {
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
if (mask_dst)
mask_dst[dst]&=not_bit;
goto here2a;
case ROPB_EQU:
case ROPB_TRANSPARENT:
if (mask_dst)
mask_dst[dst]|=bit;
here2a:
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 (mask_dst)
mask_dst[dst]|=bit;
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;
}
cnt++;
x--;
} else
break;
}
return cnt;
case BMT_MONO:
if (mask=base->mask)
if (mask->alias)
mask->alias->flags|=BMF_DIRTY;
while (TRUE) {
x3=x;
if (!(x3&(FONT_WIDTH-1))) {
if (base->flags & BMF_SCREEN_BITMAP) {
if (x3<0) break;
x3+=base->win_task->win_pixel_left;
if (x3<0 || x3>base->win_task->win_pixel_right ||
x3>=base->width ||
!(base->flags&BMF_ON_TOP) &&
IsPixelCovered(base->win_task,x3,y3))
break;
} else
if (!(0<=x3<base->width))
break;
} else if (base->flags & BMF_SCREEN_BITMAP)
x3+=base->win_task->win_pixel_left;
c=Bt(base->body,d+x3);
if (mask)
if (!Bt(mask->body,d+x3))
c=MAX_I4;
if (db) {
db2=db+x3;
if (0<=z<=*db2) {
*db2=z;
plot=TRUE;
} else
plot=FALSE;
} else
plot=TRUE;
if ((not_color && c!=base->color2 ||
!not_color && c==base->color2) && plot) {
if (base->flags & BMF_LOCATE_NEAREST) {
dist=DistI8(x3,y3,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 (x3<base->min_x) base->min_x=x3;
if (x3>base->max_x) base->max_x=x3;
if (y3<base->min_y) base->min_y=y3;
if (y3>base->max_y) base->max_y=y3;
}
c=color.u1[0];
if (dither) {
if (probability_dither) {
if (RandU2<base->dither_probability)
c=color.u1[4];
} else
if ((x3^y3)&1)
c=color.u1[4];
}
nobound_switch (color.u1[3]) {
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
BEqu(base->body,d+x3,c);
if (mask)
Btr(mask->body,d+x3);
break;
case ROPB_EQU:
case ROPB_TRANSPARENT:
BEqu(base->body,d+x3,c);
if (mask)
Bts(mask->body,d+x3);
break;
case ROPB_COLLISION:
if (c) {
if (bkcolor&0xFFFFFF00FFFFFF)
base->collision_cnt+=Bt(base->body,d+x3);
else
base->collision_cnt+=!Bt(base->body,d+x3);
} else {
if (bkcolor&0xFFFFFF00FFFFFF)
base->collision_cnt+=!Bt(base->body,d+x3);
else
base->collision_cnt+=Bt(base->body,d+x3);
}
break;
case ROPB_XOR:
if (c)
Btc(base->body,d+x3);
if (mask)
Bts(mask->body,d+x3);
break;
}
cnt++;
x++;
} else
break;
}
*x1=x-1;
x=x2-1;
while (TRUE) {
x3=x;
if (x3&(FONT_WIDTH-1)==FONT_WIDTH-1) {
if (base->flags & BMF_SCREEN_BITMAP) {
if (x3<0) break;
x3+=base->win_task->win_pixel_left;
if (x3<0 || x3>base->win_task->win_pixel_right ||
x3>=base->width ||
!(base->flags&BMF_ON_TOP) &&
IsPixelCovered(base->win_task,x3,y3))
break;
} else
if (!(0<=x3<base->width) )
break;
} else if (base->flags & BMF_SCREEN_BITMAP)
x3+=base->win_task->win_pixel_left;
c=Bt(base->body,d+x3);
if (mask)
if (!Bt(mask->body,d+x3))
c=MAX_I4;
if (db) {
db2=db+x3;
if (0<=z<=*db2) {
*db2=z;
plot=TRUE;
} else
plot=FALSE;
} else
plot=TRUE;
if ((not_color && c!=base->color2 ||
!not_color && c==base->color2) && plot) {
if (base->flags & BMF_LOCATE_NEAREST) {
dist=DistI8(x3,y3,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 (x3<base->min_x) base->min_x=x3;
if (x3>base->max_x) base->max_x=x3;
if (y3<base->min_y) base->min_y=y3;
if (y3>base->max_y) base->max_y=y3;
}
c=color.u1[0];
if (dither) {
if (probability_dither) {
if (RandU2<base->dither_probability)
c=color.u1[4];
} else
if ((x3^y3)&1)
c=color.u1[4];
}
nobound_switch (color.u1[3]) {
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
BEqu(base->body,d+x3,c);
if (mask)
Btr(mask->body,d+x3);
break;
case ROPB_EQU:
case ROPB_TRANSPARENT:
BEqu(base->body,d+x3,c);
if (mask)
Bts(mask->body,d+x3);
break;
case ROPB_COLLISION:
if (c) {
if (bkcolor&0xFFFFFF00FFFFFF)
base->collision_cnt+=Bt(base->body,d+x3);
else
base->collision_cnt+=!Bt(base->body,d+x3);
} else {
if (bkcolor&0xFFFFFF00FFFFFF)
base->collision_cnt+=!Bt(base->body,d+x3);
else
base->collision_cnt+=Bt(base->body,d+x3);
}
break;
case ROPB_XOR:
if (c)
Btc(base->body,d+x3);
if (mask)
Bts(mask->body,d+x3);
break;
}
cnt++;
x--;
} else
break;
}
return cnt;
}
gr_done:
return 0;
}
public I8 GrHLine(GrBitMap *base,I8 x1,I8 x2,I8 y,I8 z1=0,I8 z2=0)
{ //No transformation or pen width
I8 dx,dz,z,cnt=0,i,j,_x1=x1,_x2=x2,_y=y,_z1=z1,_z2=z2,dist;
U8 d,dd,c,c2,bit,not_bit;
U1 *dst;
U8 color=base->color,bkcolor=base->bkcolor,dither_colors;
I4 *db;
BoolI1 plot=TRUE,char_clear,dither,probability_dither;
GrBitMap *mask;
if (base->flags & BMF_RECORD_EXTENTS) {
if (x1<base->min_x) base->min_x=x1;
if (x1>base->max_x) base->max_x=x1;
if (x2<base->min_x) base->min_x=x2;
if (x2>base->max_x) base->max_x=x2;
if (y<base->min_y) base->min_y=y;
if (y>base->max_y) base->max_y=y;
}
if (y<0) goto gr_done;
if (x2<x1) {
SwapU8(&x1,&x2);
SwapU8(&z1,&z2);
}
if (x2<0)
goto gr_done;
if (x1<0) {
i=-x1;
x1=0;
} else
i=0;
j=0;
if (base->flags & BMF_SCREEN_BITMAP) {
x1+=base->win_task->win_pixel_left;
x2+=base->win_task->win_pixel_left;
if (x1>base->win_task->win_pixel_right)
goto gr_done;
if (x2>base->win_task->win_pixel_right) {
j=x2-base->win_task->win_pixel_right;
x2=base->win_task->win_pixel_right;
}
y+=base->win_task->win_pixel_top;
if (y>base->win_task->win_pixel_bottom ||
y<0 ||
x2<0)
goto gr_done;
}
if (x1>=base->width || y>=base->height)
goto gr_done;
dx=x2+j-(x1-i);
d=base->width_internal*y+x1;
if (db=base->depth_buffer) {
db+=d;
if (dx)
dz=(z2-z1)<<32/dx;
else
dz=0;
z=z1<<32;
}
if (i)
z+=i*dz;
if (x2>=base->width)
x2=base->width-1;
dd=base->plane_size;
if (base->flags & BMF_LOCATE_NEAREST) {
if (x1<=base->cur_x<=x2)
dist=0;
else if (base->cur_x<x1)
dist=SqrI8(x1-base->cur_x);
else
dist=SqrI8(base->cur_x-x2);
dist+=SqrI8(y-base->cur_y);
if (dist<=base->nearest_dist) {
base->nearest_grelem_num=base->cur_grelem_num;
base->nearest_dist=dist;
}
}
if (base->flags & BMF_DONT_DRAW)
goto gr_done;
if (base->win_task->next_task==sys_winmgr_task ||
base->flags&BMF_ON_TOP ||
!IsPixelCovered(base->win_task,x1,y))
char_clear=TRUE;
else
char_clear=FALSE;
if (color&(ROP_DITHER|ROP_PROBABILITY_DITHER)) {
dither=TRUE;
if (color&ROP_PROBABILITY_DITHER) {
probability_dither=TRUE;
color.u1[7]=color.u1[3];
dither_colors=color;
if (RandU2<base->dither_probability)
color.u4[0]=dither_colors.u4[1];
else
color.u4[0]=dither_colors.u4[0];
} else {
probability_dither=FALSE;
color.u1[7]=color.u1[3];
if ((x1^y)&1)
SwapU4(&color.u4[0],&color.u4[1]);
}
} else
dither=FALSE;
while (x1<=x2) {
if (char_clear) {
if (db) {
if (0<=z.i4[1]<=*db) {
*db=z.i4[1];
plot=TRUE;
} else
plot=FALSE;
}
if (plot) {
nobound_switch (base->type) {
case BMT_COLOR4:
dst=base->body+d>>3;
bit=1<<(x1&7);
not_bit=~bit;
c=color.u1[0];
nobound_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+=dd;
if (c & 2)
*dst|=bit;
else
*dst&=not_bit;
dst+=dd;
if (c & 4)
*dst|=bit;
else
*dst&=not_bit;
dst+=dd;
if (c & 8)
*dst|=bit;
else
*dst&=not_bit;
break;
case ROPB_COLLISION:
c2=0;
if (*dst&bit)
c2+=1;
dst+=dd;
if (*dst&bit)
c2+=2;
dst+=dd;
if (*dst&bit)
c2+=4;
dst+=dd;
if (*dst&bit)
c2+=8;
if (c2!=bkcolor.u1[0])
base->collision_cnt++;
break;
case ROPB_XOR:
if (c & 1) *dst^=bit;
dst+=dd;
if (c & 2) *dst^=bit;
dst+=dd;
if (c & 4) *dst^=bit;
dst+=dd;
if (c & 8) *dst^=bit;
break;
}
break;
case BMT_MONO:
c=color&0xFFFFFF;
nobound_switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_CLEAR_MASK_EQU:
case ROPB_CLEAR_MASK_TRANSPARENT:
case ROPB_TRANSPARENT:
BEqu(base->body,d,c);
break;
case ROPB_COLLISION:
if (c) {
if (bkcolor&0xFFFFFF00FFFFFF)
base->collision_cnt+=Bt(base->body,d);
else
base->collision_cnt+=!Bt(base->body,d);
} else {
if (bkcolor&0xFFFFFF00FFFFFF)
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;
}
break;
}
cnt++;
}
}
if (dither) {
if (probability_dither) {
if (RandU2<base->dither_probability)
color.u4[0]=dither_colors.u4[1];
else
color.u4[0]=dither_colors.u4[0];
} else
SwapU4(&color.u4[0],&color.u4[1]);
}
d++;
x1++;
if (db)
db++;
z+=dz;
if (!(x1&(FONT_WIDTH-1)) && x1<=x2) {
if (base->win_task->next_task==sys_winmgr_task ||
base->flags&BMF_ON_TOP ||
!IsPixelCovered(base->win_task,x1,y))
char_clear=TRUE;
else
char_clear=FALSE;
}
}
if (mask=base->mask) {
mask->brush=base->brush;
mask->color=WHITE;
if (base->color.u1[3]==ROPB_CLEAR_MASK_EQU)
mask->color=ROPB_EQU+BLACK;
else if (base->color.u1[3]==ROPB_CLEAR_MASK_TRANSPARENT)
mask->color=ROPB_TRANSPARENT+BLACK;
else
mask->color.u1[3]=base->color.u1[3];
mask->win_task=base->win_task;
if (mask->alias)
mask->alias->flags|=BMF_DIRTY;
GrHLine(mask,_x1,_x2,_y,_z1,_z2);
}
gr_done:
return cnt;
}