Files
TempleOS-Rijn/LT/ADAM/GRMODE3.CPZ
T
2018-09-08 21:45:17 +02:00

1229 lines
28 KiB
Plaintext

U8 GrScale;
GrScale.u4[0]=0;
GrScale.u4[1]=1;
U4 *gr_screen_capture=NULL;
public void Line(U1 *aux_data,
I8 x1,I8 y1,I8 z1,
I8 x2,I8 y2,I8 z2,
U1 *plot_cb(U1 *aux,I8 x,I8 y,I8 z),
I8 step=1,I8 start=0)
{
I8 i,j,d,dx=x2-x1,dy=y2-y1,dz=z2-z1;
I8 adx=AbsI8(dx),ady=AbsI8(dy),adz=AbsI8(dz);
if (adx>=ady)
d=(adx>=adz) ? adx:adz;
else
d=(ady>=adz) ? ady:adz;
if (d) {
dx=DivI8(dx<<32,d);
dy=DivI8(dy<<32,d);
dz=DivI8(dz<<32,d);
}
x1<<=32; y1<<=32; z1<<=32;
for (j=0;j<start;j++) {
x1+=dx; y1+=dy; z1+=dz;
}
for (i=start;i<=d;i+=step) {
plot_cb(aux_data,x1.i4[1],y1.i4[1],z1.i4[1]);
for (j=0;j<step;j++) {
x1+=dx; y1+=dy; z1+=dz;
}
}
}
public void GrRotate(I8 *r,I8 *x,I8 *y,I8 *z)
{
I8 x1,y1,z1;
x1=(MulI8(r[0],*x)+MulI8(r[1],*y)+MulI8(r[2],*z))>>32;
y1=(MulI8(r[3],*x)+MulI8(r[4],*y)+MulI8(r[5],*z))>>32;
z1=(MulI8(r[6],*x)+MulI8(r[7],*y)+MulI8(r[8],*z))>>32;
*x=x1;*y=y1;*z=z1;
}
public void GrTransform(GrBitMap *base,I8 *x,I8 *y,I8 *z)
{
GrRotate(base->r,x,y,z);
*x+=base->x;
*y+=base->y;
*z+=base->z;
}
public I8 *GrTheta(double theta)
{
double my_cos,my_sin;
I8 *r=MAllocZ(sizeof(I8)*9);
my_cos=Cos(theta)*GrScale;
my_sin=Sin(theta)*GrScale;
r[0]=my_cos;
r[4]=my_cos;
r[3]=my_sin;
r[1]=-my_sin;
r[8]=GrScale;
return r;
}
public I8 *GrPhi(double phi)
{
double my_cos,my_sin;
I8 *r=MAllocZ(sizeof(I8)*9);
my_cos=Cos(phi)*GrScale;
my_sin=Sin(phi)*GrScale;
r[4]=my_cos;
r[8]=my_cos;
r[7]=my_sin;
r[5]=-my_sin;
r[0]=GrScale;
return r;
}
public I4 *GrScaleMat(I8 *m1,double s)
{
I8 i,*r=MAllocZ(sizeof(I8)*9);
for (i=0;i<9;i++)
r[i]=m1[i]*s;
return r;
}
public I4 *GrMulMat(I8 *m1,I8 *m2)
{ //TODO convert to I4 arith
I8 *r=MAllocZ(sizeof(I8)*9);
I8 i,j,k;
double d;
for (i=0;i<3;i++) {
for (j=0;j<3;j++) {
for (k=0;k<3;k++) {
d=m1[k+3*j];
d*=m2[i+3*k];
d/=GrScale;
r[i+3*j]+=d;
}
}
}
return r;
}
void GrSetIdent(I8 *r)
{
MemSet(r,0,9<<3);
r[0].u4[1]=1;
r[4].u4[1]=1;
r[8].u4[1]=1;
}
public void Circle(U1 *aux_data,
I8 cx,I8 cy,I8 cz,
I8 radius,
U1 *plot_cb(U1 *aux,I8 x,I8 y,I8 z),
I8 step=1,
double start_rad=0,
double len_rad=pi2)
{
I8 i,j,len=len_rad*radius;
I8 x,y,x1,y1,s1,s2,c;
double t;
if (radius<0) return;
if (!radius) {
plot_cb(aux_data,cx,cy,cz);
return;
}
t=1.0/radius;
s1=(1<<24)*Sin(t);
s2=-s1;
c=(1<<24)*Cos(t);
if (start_rad) {
x=radius*Cos(start_rad);
y=-radius*Sin(start_rad);
} else {
x=radius;
y=0;
}
x<<=8;
y<<=8;
for (i=0;i<=len;i+=step) {
plot_cb(aux_data,cx+x>>8,cy+y>>8,cz);
for (j=0;j<step;j++) {
x1=(MulI8(c,x)+MulI8(s1,y))>>24;
y1=(MulI8(s2,x)+MulI8(c,y))>>24;
x=x1; y=y1;
}
}
}
I8 DistP3I4(P3I4 *p1,P3I4 *p2)
{
return Sqrt(SqrI8(p1->x-p2->x)+SqrI8(p1->y-p2->y)+SqrI8(p1->z-p2->z));
}
void Bezier2(U1 *aux_data,P3I4 *ctrl,U1 *plot_cb(U1 *aux,I8 x,I8 y,I8 z))
{//2nd order
I8 x,y,z,xx,yy,zz,dx,dy,dz,d_max;
double x0=ctrl[0].x,y0=ctrl[0].y,z0=ctrl[0].z;
double x1=ctrl[1].x-x0,y1=ctrl[1].y-y0,z1=ctrl[1].z-z0;
double x2=ctrl[2].x-x0,y2=ctrl[2].y-y0,z2=ctrl[2].z-z0;
double t,d=DistP3I4(&ctrl[0],&ctrl[1])+
DistP3I4(&ctrl[1],&ctrl[2])+
DistP3I4(&ctrl[2],&ctrl[0]),
s=1.0/d,t1,t2;
xx=x0; yy=y0; zz=z0;
for (t=0.0;t<=1.0;t+=s) {
t1=t*(1.0-t);
t2=t*t;
x=x0+x1*t1+x2*t2;
y=y0+y1*t1+y2*t2;
z=z0+z1*t1+z2*t2;
dx=AbsI8(x-xx);
dy=AbsI8(y-yy);
dz=AbsI8(z-zz);
if (dx>dy)
d_max=dx;
else
d_max=dy;
if (dz>d_max)
d_max=dz;
if (!d_max)
s*=1.1;
else {
s*=0.9;
plot_cb(aux_data,x,y,z);
xx=x;yy=y;zz=z;
}
}
}
void Bezier3(U1 *aux_data,P3I4 *ctrl,U1 *plot_cb(U1 *aux,I8 x,I8 y,I8 z))
{ //3rd order
I8 x,y,z,xx,yy,zz,dx,dy,dz,d_max;
double x0=ctrl[0].x,y0=ctrl[0].y,z0=ctrl[0].z;
double x1=ctrl[1].x-x0,y1=ctrl[1].y-y0,z1=ctrl[1].z-z0;
double x2=ctrl[2].x-x0,y2=ctrl[2].y-y0,z2=ctrl[2].z-z0;
double x3=ctrl[3].x-x0,y3=ctrl[3].y-y0,z3=ctrl[3].z-z0;
double t,d=DistP3I4(&ctrl[0],&ctrl[1])+
DistP3I4(&ctrl[1],&ctrl[2])+
DistP3I4(&ctrl[2],&ctrl[3])+
DistP3I4(&ctrl[3],&ctrl[0]),
s=1.0/d,nt,t1,t2,t3;
xx=x0; yy=y0; zz=z0;
for (t=0.0;t<=1.0;t+=s) {
nt=1.0-t;
t1=t*nt*nt;
t2=t*t*nt;
t3=t*t*t;
x=x0+x1*t1+x2*t2+x3*t3;
y=y0+y1*t1+y2*t2+y3*t3;
z=z0+z1*t1+z2*t2+z3*t3;
dx=AbsI8(x-xx);
dy=AbsI8(y-yy);
dz=AbsI8(z-zz);
if (dx>dy)
d_max=dx;
else
d_max=dy;
if (dz>d_max)
d_max=dz;
if (!d_max)
s*=1.1;
else {
s*=0.9;
plot_cb(aux_data,x,y,z);
xx=x;yy=y;zz=z;
}
}
}
void BSpline2(U1 *aux_data,P3I4 *ctrl,I8 cnt,U1 *plot_cb(U1 *aux,I8 x,I8 y,I8 z),BoolU4 closed=FALSE)
{ //2nd order
I8 i,j;
P3I4 *c;
if (cnt<3) return;
if (closed) {
cnt++;
c=MAlloc(sizeof(P3I4)*(cnt*2-1));
j=1;
for (i=0;i<cnt-2;i++) {
c[j].x=(ctrl[i].x+ctrl[i+1].x)/2.0;
c[j].y=(ctrl[i].y+ctrl[i+1].y)/2.0;
c[j].z=(ctrl[i].z+ctrl[i+1].z)/2.0;
j+=2;
}
c[j].x=(ctrl[0].x+ctrl[cnt-2].x)/2.0;
c[j].y=(ctrl[0].y+ctrl[cnt-2].y)/2.0;
c[j].z=(ctrl[0].z+ctrl[cnt-2].z)/2.0;
c[0].x=(c[1].x+c[j].x)/2.0;
c[0].y=(c[1].y+c[j].y)/2.0;
c[0].z=(c[1].z+c[j].z)/2.0;
j=2;
for (i=0;i<cnt-2;i++) {
c[j].x=(c[j-1].x+c[j+1].x)/2.0;
c[j].y=(c[j-1].y+c[j+1].y)/2.0;
c[j].z=(c[j-1].z+c[j+1].z)/2.0;
j+=2;
}
c[j].x=c[0].x;
c[j].y=c[0].y;
c[j].z=c[0].z;
} else {
c=MAlloc(sizeof(P3I4)*(cnt*2-1));
c[0].x=ctrl[0].x;
c[0].y=ctrl[0].y;
c[0].z=ctrl[0].z;
c[cnt*2-2].x=ctrl[cnt-1].x;
c[cnt*2-2].y=ctrl[cnt-1].y;
c[cnt*2-2].z=ctrl[cnt-1].z;
j=1;
for (i=0;i<cnt-1;i++) {
c[j].x=(ctrl[i].x+ctrl[i+1].x)/2.0;
c[j].y=(ctrl[i].y+ctrl[i+1].y)/2.0;
c[j].z=(ctrl[i].z+ctrl[i+1].z)/2.0;
j+=2;
}
j=2;
for (i=0;i<cnt-2;i++) {
c[j].x=(c[j-1].x+c[j+1].x)/2.0;
c[j].y=(c[j-1].y+c[j+1].y)/2.0;
c[j].z=(c[j-1].z+c[j+1].z)/2.0;
j+=2;
}
}
for (i=0;i<cnt*2-2;i+=2)
Bezier2(aux_data,&c[i],plot_cb);
Free(c);
}
void BSpline3(U1 *aux_data,P3I4 *ctrl,I8 cnt,U1 *plot_cb(U1 *aux,I8 x,I8 y,I8 z),BoolU4 closed=FALSE)
{ //3rd order
I8 i,j;
double x,y,z;
P3I4 *c;
if (cnt<3) return;
if (closed) {
cnt++;
c=MAlloc(sizeof(P3I4)*(cnt*3-2));
j=1;
for (i=0;i<cnt-2;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
c[j].x=(ctrl[i+1].x-x)/3.0+x;
c[j].y=(ctrl[i+1].y-y)/3.0+y;
c[j].z=(ctrl[i+1].z-z)/3.0+z;
j++;
c[j].x=2.0*(ctrl[i+1].x-x)/3.0+x;
c[j].y=2.0*(ctrl[i+1].y-y)/3.0+y;
c[j].z=2.0*(ctrl[i+1].z-z)/3.0+z;
j+=2;
}
x=ctrl[cnt-2].x;
y=ctrl[cnt-2].y;
z=ctrl[cnt-2].z;
c[j].x=(ctrl[0].x-x)/3.0+x;
c[j].y=(ctrl[0].y-y)/3.0+y;
c[j].z=(ctrl[0].z-z)/3.0+z;
j++;
c[j].x=2.0*(ctrl[0].x-x)/3.0+x;
c[j].y=2.0*(ctrl[0].y-y)/3.0+y;
c[j].z=2.0*(ctrl[0].z-z)/3.0+z;
c[0].x=(c[1].x+c[j].x)/2.0;
c[0].y=(c[1].y+c[j].y)/2.0;
c[0].z=(c[1].z+c[j].z)/2.0;
j=3;
for (i=0;i<cnt-2;i++) {
c[j].x=(c[j-1].x+c[j+1].x)/2.0;
c[j].y=(c[j-1].y+c[j+1].y)/2.0;
c[j].z=(c[j-1].z+c[j+1].z)/2.0;
j+=3;
}
c[j].x=c[0].x;
c[j].y=c[0].y;
c[j].z=c[0].z;
} else {
c=MAlloc(sizeof(P3I4)*(cnt*3-2));
c[0].x=ctrl[0].x;
c[0].y=ctrl[0].y;
c[0].z=ctrl[0].z;
c[cnt*3-3].x=ctrl[cnt-1].x;
c[cnt*3-3].y=ctrl[cnt-1].y;
c[cnt*3-3].z=ctrl[cnt-1].z;
j=1;
for (i=0;i<cnt-1;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
c[j].x=(ctrl[i+1].x-x)/3.0+x;
c[j].y=(ctrl[i+1].y-y)/3.0+y;
c[j].z=(ctrl[i+1].z-z)/3.0+z;
j++;
c[j].x=2.0*(ctrl[i+1].x-x)/3.0+x;
c[j].y=2.0*(ctrl[i+1].y-y)/3.0+y;
c[j].z=2.0*(ctrl[i+1].z-z)/3.0+z;
j+=2;
}
j=3;
for (i=0;i<cnt-2;i++) {
c[j].x=(c[j-1].x+c[j+1].x)/2.0;
c[j].y=(c[j-1].y+c[j+1].y)/2.0;
c[j].z=(c[j-1].z+c[j+1].z)/2.0;
j+=3;
}
}
for (i=0;i<cnt*3-3;i+=3)
Bezier3(aux_data,&c[i],plot_cb);
Free(c);
}
void GrReset(GrBitMap *base)
{
base->color=GR_BLACK;
base->pen_width=1;
}
GrBitMap *GrNew(GrBitMap *base)
{
GrBitMap *result=MAlloc(sizeof(GrBitMap));
MemCpy(result,base,sizeof(GrBitMap));
result->r=MAlloc(9<<1<<2);
GrSetIdent(result->r);
GrReset(result);
result->flags|=BMF_ALIAS;
return result;
}
void GrDel(GrBitMap *base)
{
Free(base->r);
if (!(base->flags & BMF_ALIAS))
Free(base->body);
Free(base);
}
I4 gr_table[1024];
BoolU4 gr_table_initialized=FALSE;
#define GR_NUM_PEN_BRUSHES 64
GrBitMap *gr_pen_brushes[GR_NUM_PEN_BRUSHES];
void GrSetupTable(GrBitMap *hidden)
{
GrBitMap *b;
I8 i,j,k;
for (i=-16;i<16;i++) {
for (j=-16;j<16;j++) {
k=((i>=0) ? i:32+i)<<5+((j>=0) ? j:32+j);
gr_table[k]=(MulI8(i,hidden->internal_width)+j)>>3;
}
}
for (i=0;i<(256*FONT_HEIGHT*FONT_WIDTH)>>3;i++)
grfont[i]=reverse_bits_table[grfont[i]];
for (i=0;i<GR_NUM_PEN_BRUSHES;i++) {
j=((i+7)>>3)<<3;
if (!j)
b=GrBitMapNew(BMT_MONO,8,1);
else
b=GrBitMapNew(BMT_MONO,j,i);
gr_pen_brushes[i]=b;
b->color=GR_WHITE;
if (i<2)
GrPlot0(b,0,0);
else {
GrPlot0(b,i>>1,i>>1);
for (j=1;j<=i;j+=2)
GrCircle(b,i>>1+1,i>>1,j>>1);
for (j=1;j<=i;j+=2)
GrCircle(b,i>>1,i>>1+1,j>>1);
for (j=2;j<=i;j+=2)
GrCircle(b,i>>1,i>>1,j>>1);
}
}
OutP(VGA_SC_INDEX,VGA_MAP_MASK);
OutP(VGA_SC_DATA,0x0F);
MemSet(0xA0000,0,grheight*grwidth>>3);
MemSet(vga_image,0,grwidth*grheight>>1);
gr_table_initialized=TRUE;
}
////**************************PROCEDURE*************************
// Format of U4 text entry
// Bits 0-7 ASCII
// Bits 8-11 Foreground color
// Bits 12-15 Background color
// Bits 16-20 Signed X position shift value
// Bits 21-25 Signed Y position shift value
// Bit 28 Blink
// Bit 29 Inverted (Swap foreground and background)
// Bit 30 Selected (XOR colors with FF)
// Bit 31 Underline
void GrUpdateScreen(GrBitMap *b1,GrBitMap *b2,
U4 *my_textbase)
{
U4 *src,*src2,cur_ch,u;
//U8 d;
U8 row,col,plane,ch_line,i,
d0=(b2->internal_width+1)<<2,
d1=(b2->internal_width)>>3,
d2=(b2->internal_width*b2->height-FONT_HEIGHT*b2->width)>>3,
d3=(b2->internal_width*b2->height<<2)>>3,
d4=(b2->internal_width*FONT_HEIGHT-b1->width)>>3,
d5=(b1->internal_width)>>5,
d6=(b2->internal_width)<<2,
num_cols=b1->width/FONT_WIDTH,
num_rows=b1->height/FONT_HEIGHT;
BoolU4 old_preempt;
U2 *dst2;
U4 *dst3,*dst4=vga_image;
BoolU4 GrBlinkFlag=(jiffies/(JIFFY_FREQ/5))&1;
U1 *dst,*font_ptr,*font_ptr2,saved_font_line;
if (!gr_table_initialized) GrSetupTable(b2);
//Update Text Background
src=my_textbase;
dst=b2->body+d0;
for (row=0;row<num_rows;row++) {
for (col=0;col<num_cols;col++) {
cur_ch=*src;
src+=4;
if (cur_ch & LTFLT_SELECTED)
cur_ch.u1[1]=cur_ch.u1[1]^0xFF;
if (cur_ch & LTFLT_INVERTED)
cur_ch.u1[1]=(cur_ch.u1[1]<<4)+(cur_ch.u1[1]>>4);
if (cur_ch & LTFLT_BLINK)
if (GrBlinkFlag)
cur_ch.u1[1]=(cur_ch.u1[1]<<4)+(cur_ch.u1[1]>>4);
GrPlotBackground(cur_ch.u1[1],&dst,d1,d2);
/*
for (plane=0x10;plane!=0x100;plane=plane<<1) {
d=(cur_ch.u1[1] & plane) ? 0xFF:0x00;
for (ch_line=0;ch_line<FONT_HEIGHT;ch_line++) {
*dst=d;
dst+=d1;
}
dst+=d2;
}
*/
dst+=1-d3;
}
dst+=d4;
}
//Update Text Foreground
src=my_textbase;
dst=b2->body+d0;
for (row=0;row<num_rows;row++) {
for (col=0;col<num_cols;col++) {
cur_ch=*src;
src+=4;
if (cur_ch & LTFLT_SELECTED)
cur_ch.u1[1]=cur_ch.u1[1]^0xFF;
if (cur_ch & LTFLT_INVERTED)
cur_ch.u1[1]=(cur_ch.u1[1]<<4)+(cur_ch.u1[1]>>4);
if (cur_ch & LTFLT_BLINK)
if (GrBlinkFlag)
cur_ch.u1[1]=(cur_ch.u1[1]<<4)+(cur_ch.u1[1]>>4);
font_ptr=&grfont[FONT_WIDTH*FONT_HEIGHT>>3*cur_ch.u1[0]];
if (cur_ch & LTFLT_UNDERLINED) {
saved_font_line=font_ptr[7];
font_ptr[7]=0xFF;
}
i=cur_ch.u2[1]&0x3FF;
dst2=dst+gr_table[i];
if (i) {
i&=7;
for (plane=0x01;plane!=0x10;plane<<=1) {
font_ptr2=font_ptr;
if (cur_ch.u1[1] & plane) {
for (ch_line=0;ch_line<FONT_HEIGHT;ch_line++) {
u=*font_ptr2++<<i;
*dst2|=u.u2[0] | u.u2[1];
dst2+=d1;
}
} else {
for (ch_line=0;ch_line<FONT_HEIGHT;ch_line++) {
u=*font_ptr2++<<i;
*dst2&=~(u.u2[0] | u.u2[1]);
dst2+=d1;
}
}
dst2+=d2;
}
} else {
GrPlotChar(font_ptr,cur_ch.u1[1],&dst2,d1,d2);
/*
for (plane=0x01;plane!=0x10;plane<<=1) {
font_ptr2=font_ptr;
if (cur_ch.u1[1] & plane) {
for (ch_line=0;ch_line<FONT_HEIGHT;ch_line++) {
*dst2|=*font_ptr2++;
dst2+=d1;
}
} else {
for (ch_line=0;ch_line<FONT_HEIGHT;ch_line++) {
*dst2&=~*font_ptr2++;
dst2+=d1;
}
}
dst2+=d2;
}
*/
}
if (cur_ch & LTFLT_UNDERLINED)
font_ptr[7]=saved_font_line;
dst++;
}
dst+=d4;
}
if (Btr(&sys_flags,SYSf_CLEAR_SCREEN_TEXT))
MemSet(textbase,0,(grheight/FONT_HEIGHT)*(grwidth/FONT_WIDTH)<<2);
old_preempt=Preempt(OFF);
GrUpdateWindows;
PlotInputPointer;
Preempt(ON);
//Update Graphic Card
src=b1->body;
src2=b2->body;
for (plane=1;plane<0x10;plane<<=1) {
OutP(VGA_SC_INDEX,VGA_MAP_MASK);
OutP(VGA_SC_DATA,plane);
dst3=0xA0000;
src2+=d6;
for (row=0;row<b1->height;row++) {
src2+=32>>3;
GrXorLine(&dst3,&src,&src2,d5,&dst4);
/*
for (col=0;col<d5;col++) {
*dst3=*src^*src2;
dst3+=4;
src+=4;
src2+=4;
}
*/
src2+=32>>3;
}
src2+=d6;
}
Preempt(old_preempt);
if (gr_screen_capture) {
MemCpy(gr_screen_capture,vga_image,grheight*grwidth>>1);
gr_screen_capture=NULL;
}
}
public void GrPlot0(GrBitMap *base,I8 x,I8 y)
{ //No clipping or transformation or pen width
U8 d,c;
U1 *dst,bit,not_bit;
U8 color=base->color;
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_sub_GrElem=base->cur_sub_GrElem;
base->nearest_dist=dist;
}
}
if (base->flags & BMF_DONT_DRAW)
return;
switch (base->type) {
case BMT_COLOR4:
d=base->plane_size;
dst=base->body+(base->left_margin+
(y+base->top_margin)*base->internal_width)>>3+(x>>3);
bit=1<<(x&7);
not_bit=~bit;
c=color.u1[0];
switch (color.u1[3]) {
case ROPB_EQU:
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_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_NAND:
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_MONO:
d=base->internal_width*y+x;
c=color.u1[0];
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_TRANSPARENT:
AssignBit(base->body,d,c);
break;
case ROPB_XOR:
if (c)
Btc(base->body,d);
break;
case ROPB_OR:
if (c)
Bts(base->body,d);
break;
case ROPB_NAND:
if (c)
Btr(base->body,d);
break;
}
break;
}
}
public BoolU4 GrBlot(GrBitMap *base,I8 x,I8 y,GrBitMap *img)
{ //Clipping but not transformation
I8 i,i1,i2,i3,j,k,k1,w1,h1,w2,h2,plane,plane1,bit_mask,bit_shift,p;
U1 *ptr;
U2 *ptr1;
I8 color,color_byte,plane_size,plane_size1,plane_limit;
BoolU4 draw=TRUE,color_bit;
w1= (x<0)?-x:0;
h1= (y<0)?-y:0;
w2=img->width;
h2=img->height;
if (base->flags & BMF_SCREEN_BITMAP) {
x+=Fs->window_pixel_left;
if (x+w1<0) w1=-x;
if (x+w2>Fs->window_pixel_right)
w2=Fs->window_pixel_right-x;
y+=Fs->window_pixel_top;
if (y+h1<0) h1=-y;
if (y+h2>Fs->window_pixel_bottom)
h2=Fs->window_pixel_bottom-y;
if (IsPixelCovered(Fs,x+w1,y+h1))
draw=FALSE;
else if (IsPixelCovered(Fs,x+w2,y+h2))
draw=FALSE;
x+=base->left_margin;
y+=base->top_margin;
}
if (x+w2>base->width)
w2=base->width-x;
if (y+h2>base->height)
h2=base->height-y;
if (draw && w1<w2 && h1<h2 && w2<=img->width && h2<=img->height) {
if (base->flags & BMF_DONT_DRAW)
return TRUE;
color=base->color;
p=0;
plane_size=img->plane_size<<3;
plane_size1=base->plane_size<<3;
switch (base->type) {
case BMT_COLOR4: plane_limit=plane_size*4; break;
case BMT_MONO: plane_limit=plane_size; break;
}
i1=(-w1)&7;
if (i1>w2) i1=w2;
i2=(w2-w1-i1)>>3;
i3=w2-w1-i2<<3-i1;
bit_shift=(x+w1)&7;
bit_mask=-1-255<<bit_shift;
for (plane=0,plane1=0;plane<plane_limit;
plane+=plane_size,plane1+=plane_size1) {
if (color_bit=Bt(&color,p++))
color_byte=255;
else
color_byte=0;
for (j=h1;j<h2;j++) {
switch (img->type) {
case BMT_COLOR4:
k=j*img->internal_width+w1+plane;
k1=(j+y)*base->internal_width+x+w1+plane1;
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_TRANSPARENT:
for (i=0;i<i1;i++)
AssignBit(base->body,k1++,Bt(img->body,k++));
break;
case ROPB_XOR:
for (i=0;i<i1;i++)
if (Bt(img->body,k++))
Btc(base->body,k1++);
break;
case ROPB_OR:
for (i=0;i<i1;i++)
if (Bt(img->body,k++))
Bts(base->body,k1++);
break;
case ROPB_NAND:
for (i=0;i<i1;i++)
if (Bt(img->body,k++))
Btr(base->body,k1++);
break;
}
ptr=k>>3+img->body;
ptr1=k1>>3+base->body;
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_TRANSPARENT:
for (i=0;i<i2;i++) {
*ptr1=*ptr1 & bit_mask | (*ptr++<<bit_shift);
ptr1++;
}
break;
case ROPB_XOR:
for (i=0;i<i2;i++) {
*ptr1^=*ptr++<<bit_shift;
ptr1++;
}
break;
case ROPB_OR:
for (i=0;i<i2;i++) {
*ptr1|=*ptr++<<bit_shift;
ptr1++;
}
break;
case ROPB_NAND:
for (i=0;i<i2;i++) {
*ptr1= *ptr1 & (bit_mask | ~(*ptr++<<bit_shift));
ptr1++;
}
break;
}
k+=i2<<3;
k1+=i2<<3;
switch (color.u1[3]) {
case ROPB_EQU:
case ROPB_TRANSPARENT:
for (i=0;i<i3;i++)
AssignBit(base->body,k1++,Bt(img->body,k++));
break;
case ROPB_XOR:
for (i=0;i<i3;i++)
if (Bt(img->body,k++))
Btc(base->body,k1++);
break;
case ROPB_OR:
for (i=0;i<i3;i++)
if (Bt(img->body,k++))
Bts(base->body,k1++);
break;
case ROPB_NAND:
for (i=0;i<i3;i++)
if (Bt(img->body,k++))
Btr(base->body,k1++);
break;
}
break;
case BMT_MONO:
k=j*img->internal_width+w1;
k1=(j+y)*base->internal_width+x+w1+plane1;
switch (color.u1[3]) {
case ROPB_EQU:
for (i=0;i<i1;i++)
AssignBit(base->body,k1++,color_bit && Bt(img->body,k++));
break;
case ROPB_TRANSPARENT:
for (i=0;i<i1;i++)
if (Bt(img->body,k++))
AssignBit(base->body,k1++,color_bit);
break;
case ROPB_XOR:
if (color_bit)
for (i=0;i<i1;i++)
if (Bt(img->body,k++))
Btc(base->body,k1++);
break;
case ROPB_OR:
if (color_bit)
for (i=0;i<i1;i++)
if (Bt(img->body,k++))
Bts(base->body,k1++);
break;
case ROPB_NAND:
if (color_bit)
for (i=0;i<i1;i++)
if (Bt(img->body,k++))
Btr(base->body,k1++);
break;
}
ptr=k>>3+img->body;
ptr1=k1>>3+base->body;
switch (color.u1[3]) {
case ROPB_EQU:
for (i=0;i<i2;i++) {
*ptr1=*ptr1 & bit_mask | ((*ptr++ & color_byte)<<bit_shift);
ptr1++;
}
break;
case ROPB_TRANSPARENT:
for (i=0;i<i2;i++) {
bit_mask=~(*ptr<<bit_shift);
*ptr1=*ptr1 & bit_mask | ((*ptr++ & color_byte)<<bit_shift);
ptr1++;
}
break;
case ROPB_XOR:
if (color_bit)
for (i=0;i<i2;i++) {
*ptr1^=*ptr++<<bit_shift;
ptr1++;
}
break;
case ROPB_OR:
if (color_bit)
for (i=0;i<i2;i++) {
*ptr1|=*ptr++<<bit_shift;
ptr1++;
}
break;
case ROPB_NAND:
if (color_bit)
for (i=0;i<i2;i++) {
*ptr1= *ptr1 & (bit_mask | ~(*ptr++<<bit_shift));
ptr1++;
}
break;
}
k+=i2<<3;
k1+=i2<<3;
switch (color.u1[3]) {
case ROPB_EQU:
for (i=0;i<i3;i++)
AssignBit(base->body,k1++,color_bit && Bt(img->body,k++));
break;
case ROPB_TRANSPARENT:
for (i=0;i<i3;i++)
if (Bt(img->body,k++))
AssignBit(base->body,k1++,color_bit);
break;
case ROPB_XOR:
if (color_bit)
for (i=0;i<i3;i++)
if (Bt(img->body,k++))
Btc(base->body,k1++);
break;
case ROPB_OR:
if (color_bit)
for (i=0;i<i3;i++)
if (Bt(img->body,k++))
Bts(base->body,k1++);
break;
case ROPB_NAND:
if (color_bit)
for (i=0;i<i3;i++)
if (Bt(img->body,k++))
Btr(base->body,k1++);
break;
}
break;
}
}
}
return TRUE;
}
return FALSE;
}
public void GrPlot(GrBitMap *base,I8 x,I8 y)
{ //Clipping but No transformation or pen width
BoolU4 draw=TRUE;
if (base->brush) {
GrBlot(base,x,y,base->brush);
return;
}
if (base->flags & BMF_SCREEN_BITMAP) {
if (x<0) draw=FALSE;
x+=Fs->window_pixel_left;
if (x>Fs->window_pixel_right) draw=FALSE;
if (y<0) draw=FALSE;
y+=Fs->window_pixel_top;
if (y>Fs->window_pixel_bottom) draw=FALSE;
if (x>=base->width) draw=FALSE;
if (y>=base->height) draw=FALSE;
if (IsPixelCovered(Fs,x,y)) draw=FALSE;
} else {
if (x<0) draw=FALSE;
if (x>=base->width) draw=FALSE;
if (y<0) draw=FALSE;
if (y>=base->height) draw=FALSE;
}
if (draw)
GrPlot0(base,x,y);
}
public void GrPlot2(GrBitMap *base,I8 x,I8 y,I8 z)
{ //Clipping and transformation but no pen_width
if (base->flags & BMF_TRANSFORMATION) {
GrRotate(base->r,&x,&y,&z);
x+=base->x;
y+=base->y;
z+=base->z;
}
GrPlot(base,x,y);
}
public void GrPlot3(GrBitMap *base,I8 x,I8 y,I8 z)
{ //clipping and transformation and pen width
I8 i,j,w,old_color;
double dist;
if (base->flags & BMF_TRANSFORMATION) {
GrRotate(base->r,&x,&y,&z);
x+=base->x;
y+=base->y;
z+=base->z;
}
w=base->pen_width>>1;
if (w<=0)
GrPlot(base,x,y);
else if (base->pen_width<GR_NUM_PEN_BRUSHES) {
old_color=base->color;
if (base->color.u1[3]==ROPB_EQU)
base->color.u1[3]=ROPB_TRANSPARENT;
if (GrBlot(base,x-w,y-w,gr_pen_brushes[base->pen_width])) {
if (base->flags & BMF_SCREEN_BITMAP) {
x+=Fs->window_pixel_left;
y+=Fs->window_pixel_top;
}
if (base->flags & BMF_LOCATE_NEAREST) {
dist=DistI8(x,y,base->cur_x,base->cur_y);
if (dist<base->nearest_dist) {
base->nearest_sub_GrElem=base->cur_sub_GrElem;
base->nearest_dist=dist;
}
}
}
base->color=old_color;
} else if (base->pen_width & 1) {
for (i=-w;i<=w;i++)
for (j=-w;j<=w;j++)
GrPlot(base,x+i,y+j);
} else {
for (i=-w;i<w;i++)
for (j=-w;j<w;j++)
GrPlot(base,x+i,y+j);
}
}
public void GrPlot4(GrBitMap *base,I8 x,I8 y)
{
BoolU4 draw=TRUE;
if (x<0) draw=FALSE;
x+=Fs->window_pixel_left;
if (x>Fs->window_pixel_right) draw=FALSE;
if (y<0) draw=FALSE;
y+=Fs->window_pixel_top;
if (y>Fs->window_pixel_bottom) draw=FALSE;
if (x>=base->width) draw=FALSE;
if (y>=base->height) draw=FALSE;
if (draw) {
if (base->brush)
GrBlot(base,x,y,base->brush);
else
GrPlot0(base,x,y);
}
}
void GrLinePlot(GrBitMap *base,I8 x,I8 y,I8 z)
{
GrPlot(base,x,y);
}
public void GrLine(GrBitMap *base,I8 x1,I8 y1,I8 x2,I8 y2,I8 step=1,I8 start=0)
{
Line(base,x1,y1,0,x2,y2,0,&GrLinePlot,step,start);
}
public void GrCircle(GrBitMap *base,I8 cx,I8 cy,I8 radius,
I8 step=1,double start_rad=0,double len_rad=pi2)
{
Circle(base,cx,cy,0,radius,&GrLinePlot,step,start_rad,len_rad);
}
public void Gr2Bezier(GrBitMap *base,P3I4 *ctrl)
{
Bezier2(base,ctrl,&GrLinePlot);
}
public void Gr3Bezier(GrBitMap *base,P3I4 *ctrl)
{
Bezier3(base,ctrl,&GrLinePlot);
}
public void Gr2BSpline(GrBitMap *base,P3I4 *ctrl,I8 cnt,BoolU4 closed=FALSE)
{
BSpline2(base,ctrl,cnt,&GrLinePlot,closed);
}
public void Gr3BSpline(GrBitMap *base,P3I4 *ctrl,I8 cnt,BoolU4 closed=FALSE)
{
BSpline3(base,ctrl,cnt,&GrLinePlot,closed);
}
public void GrLine2(GrBitMap *base,I8 x1,I8 y1,I8 z1,I8 x2,I8 y2,I8 z2,I8 step=1,I8 start=0)
{ //tarnsformation but not pen width
if (base->flags & BMF_TRANSFORMATION) {
GrRotate(base->r,&x1,&y1,&z1);
x1+=base->x;
y1+=base->y;
z1+=base->z;
}
if (base->flags & BMF_TRANSFORMATION) {
GrRotate(base->r,&x2,&y2,&z2);
x2+=base->x;
y2+=base->y;
z2+=base->z;
}
Line(base,x1,y1,0,x2,y2,0,&GrLinePlot,step,start);
}
void GrLine3Plot(GrBitMap *base,I8 x,I8 y,I8 z)
{
GrPlot3(base,x,y,z);
}
public void GrLine3(GrBitMap *base,I8 x1,I8 y1,I8 z1,I8 x2,I8 y2,I8 z2,I8 step=1,I8 start=0)
{ //transformation with pen width
U8 old_flags=base->flags;
if (base->flags & BMF_TRANSFORMATION) {
GrRotate(base->r,&x1,&y1,&z1);
x1+=base->x;
y1+=base->y;
z1+=base->z;
GrRotate(base->r,&x2,&y2,&z2);
x2+=base->x;
y2+=base->y;
z2+=base->z;
}
base->flags&=~BMF_TRANSFORMATION;
Line(base,x1,y1,z1,x2,y2,z2,&GrLine3Plot,step,start);
base->flags=old_flags;
}
public void Gr2Bezier3(GrBitMap *base,P3I4 *ctrl)
{
Bezier2(base,ctrl,&GrLine3Plot);
}
public void Gr3Bezier3(GrBitMap *base,P3I4 *ctrl)
{
Bezier3(base,ctrl,&GrLine3Plot);
}
public void Gr2BSpline3(GrBitMap *base,P3I4 *ctrl,I8 cnt,BoolU4 closed=FALSE)
{
BSpline2(base,ctrl,cnt,&GrLine3Plot,closed);
}
public void Gr3BSpline3(GrBitMap *base,P3I4 *ctrl,I8 cnt,BoolU4 closed=FALSE)
{
BSpline3(base,ctrl,cnt,&GrLine3Plot,closed);
}
void GrLinePlot4(GrBitMap *base,I8 x,I8 y,I8 z)
{
GrPlot4(base,x,y);
}
public void GrLine4(GrBitMap *base,I8 x1,I8 y1,I8 x2,I8 y2,I8 step=1,I8 start=0)
{
Line(base,x1,y1,0,x2,y2,0,&GrLinePlot4,step,start);
}
void PlotScreenString(I1 *s,U8 attr,I8 x,I8 y)
{
U1 ch;
attr<<=8;
while (ch=*s++) {
PlotScreenChar(ch+attr,x,y);
x+=4;
}
}
void PlotWindowString(I1 *s,U8 attr,I8 x,I8 y)
{
U1 ch;
attr<<=8;
while (ch=*s++) {
PlotWindowChar(ch+attr,x,y);
x+=4;
}
}
void PlotBorderString(I1 *s,U8 attr,I8 x,I8 y)
{
U1 ch;
attr<<=8;
while (ch=*s++) {
PlotBorderChar(ch+attr,x,y);
x+=4;
}
}