Files
TempleOS-Rijn/LT/Adam/Gr/GrPlot.APZ
T
2018-09-08 21:45:20 +02:00

729 lines
17 KiB
Plaintext

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+=base->win_tss->win_pixel_left;
if (x>base->win_tss->win_pixel_right) draw=FALSE;
if (y<0) draw=FALSE;
y+=base->win_tss->win_pixel_top;
if (y>base->win_tss->win_pixel_bottom) draw=FALSE;
if (x>=base->width) draw=FALSE;
if (y>=base->height) draw=FALSE;
if (IsPixelCovered(base->win_tss,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 I8 GrPeek(GrBitMap *base,I8 x,I8 y)
{ //Clipping but No transformation
BoolU4 peek=TRUE;
if (base->flags & BMF_SCREEN_BITMAP) {
if (x<0) peek=FALSE;
x+=base->win_tss->win_pixel_left;
if (x>base->win_tss->win_pixel_right) peek=FALSE;
if (y<0) peek=FALSE;
y+=base->win_tss->win_pixel_top;
if (y>base->win_tss->win_pixel_bottom) peek=FALSE;
if (x>=base->width) peek=FALSE;
if (y>=base->height) peek=FALSE;
if (IsPixelCovered(base->win_tss,x,y)) peek=FALSE;
} else {
if (x<0) peek=FALSE;
if (x>=base->width) peek=FALSE;
if (y<0) peek=FALSE;
if (y>=base->height) peek=FALSE;
}
if (peek)
return GrPeek0(base,x,y);
else
return -1;
}
#define CC_LEFT 1
#define CC_RIGHT 2
#define CC_TOP 4
#define CC_BOTTOM 8
U8 ClipCode(I8 x,I8 y,I8 right,I8 bottom)
{
U8 result;
if (y>bottom)
result=CC_BOTTOM;
else if (y<0)
result=CC_TOP;
else
result=0;
if (x>right)
result|=CC_RIGHT;
else if (x<0)
result|=CC_LEFT;
return result;
}
public BoolU8 ClipLine(GrBitMap *base,I8 *x1,I8 *y1,I8 *x2,I8 *y2)
{
I8 x,y,right,bottom;
U8 cc,cc1,cc2;
if (base->flags & BMF_SCREEN_BITMAP) {
right=base->win_tss->win_pixel_right-base->win_tss->win_pixel_left-1;
if (base->width-1<right)
right=base->width-1;
bottom=base->win_tss->win_pixel_bottom-base->win_tss->win_pixel_top-1;
if (base->height-1<bottom)
bottom=base->height-1;
} else {
right=base->width-1;
bottom=base->height-1;
}
cc1=ClipCode(*x1,*y1,right,bottom);
cc2=ClipCode(*x2,*y2,right,bottom);
do {
if (!(cc1|cc2))
return TRUE;
if (cc1&cc2)
return FALSE;
if (cc1)
cc=cc1;
else
cc=cc2;
if (cc&CC_BOTTOM) {
x=*x1+(*x2-*x1)*(bottom-*y1)/(*y2-*y1);
y=bottom;
} else if (cc&CC_TOP) {
x=*x1+(*x2-*x1)*(-*y1)/(*y2-*y1);
y=0;
} else if (cc&CC_RIGHT) {
y=*y1+(*y2-*y1)*(right-*x1)/(*x2-*x1);
x=right;
} else {
y=*y1+(*y2-*y1)*(-*x1)/(*x2-*x1);
x=0;
}
if (cc==cc1) {
*x1=x;
*y1=y;
cc1=ClipCode(*x1,*y1,right,bottom);
} else {
*x2=x;
*y2=y;
cc2=ClipCode(*x2,*y2,right,bottom);
}
} while (TRUE);
}
I8 GrFloodFillRay(GrBitMap *base,I8 x,I8 y)
{
I8 cnt,j,x1,ray_len,ray_len2;
cnt=ray_len=GrRayLen(base,&x,y);
y--;
j=ray_len;
x1=x;
while (j>0) {
if (ray_len2=GrRayLenMinus(base,x1,y))
cnt+=GrFloodFillRay(base,x1,y);
j-=ray_len2+1;
x1-=ray_len2+1;
}
y+=2;
j=ray_len;
x1=x;
while (j>0) {
if (ray_len2=GrRayLenMinus(base,x1,y))
cnt+=GrFloodFillRay(base,x1,y);
j-=ray_len2+1;
x1-=ray_len2+1;
}
return cnt;
}
public I8 GrFloodFill(GrBitMap *base,I8 x,I8 y,BoolU4 not_color=TRUE)
{
I8 cnt=0,j,c,old_color2=base->color2,old_flags=base->flags;
GrBitMap *old_brush;
if (base->flags & BMF_DONT_DRAW) //TODO
return 0;
old_brush=base->brush;
base->brush=NULL;
j=GrPeek(base,x,y);
if (j>=0) {
switch (base->type) {
case BMT_COLOR4:
if (not_color) {
base->color2=base->color&0xFFFFFF;
base->flags|=BMF_FILL_NOT_COLOR;
} else {
base->color2=j;
if (base->color2==base->color&0xFFFFFF)
break;
base->flags&=~BMF_FILL_NOT_COLOR;
}
if (not_color && j!=base->color2 ||
!not_color)
cnt=GrFloodFillRay(base,x,y);
break;
case BMT_MONO:
c=(base->color&0xFFFFFF)?1:0;
if (not_color) {
base->color2=c;
base->flags|=BMF_FILL_NOT_COLOR;
} else {
base->color2=(j)?1:0;
if (base->color2==c)
break;
base->flags&=~BMF_FILL_NOT_COLOR;
}
if (not_color && j!=c ||
!not_color)
cnt=GrFloodFillRay(base,x,y);
break;
}
}
base->brush=old_brush;
base->flags=old_flags;
base->color2=old_color2;
return cnt;
}
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,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+=base->win_tss->win_pixel_left;
y+=base->win_tss->win_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)
{ //Plot with base->brush
BoolU4 draw=TRUE;
if (x<0) draw=FALSE;
x+=base->win_tss->win_pixel_left;
if (x>base->win_tss->win_pixel_right) draw=FALSE;
if (y<0) draw=FALSE;
y+=base->win_tss->win_pixel_top;
if (y>base->win_tss->win_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)
{
nounusedwarn z;
GrPlot(base,x,y);
}
public void GrLine(GrBitMap *base,I8 x1,I8 y1,I8 x2,I8 y2,I8 step=1,I8 start=0)
{
if (ClipLine(base,&x1,&y1,&x2,&y2))
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 GrEllipse(GrBitMap *base,
I8 cx,I8 cy,
I8 x_radius,I8 y_radius,
double rot_angle=0,
I8 step=1,
double start_rad=0,
double len_rad=pi2)
{
Ellipse(base,cx,cy,0,x_radius,y_radius,&GrLinePlot,rot_angle,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)
{ //transformation but not pen width
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;
}
if (ClipLine(base,&x1,&y1,&x2,&y2))
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;
}
if (ClipLine(base,&x1,&y1,&x2,&y2)) {
base->flags&=~BMF_TRANSFORMATION;
Line(base,x1,y1,0,x2,y2,0,&GrLine3Plot,step,start);
base->flags=old_flags;
}
}
public void GrText3(GrBitMap *base,I8 x1,I8 y1,I8 z1,I1 *s)
{ //transformation
if (base->flags & BMF_TRANSFORMATION) {
GrRotate(base->r,&x1,&y1,&z1);
x1+=base->x;
y1+=base->y;
z1+=base->z;
}
GrText(base,x1,y1,s);
}
public void GrCircle3(GrBitMap *base,I8 cx,I8 cy,I8 cz,I8 radius,
I8 step=1,double start_rad=0,double len_rad=pi2)
{ //transformation with pen width
I8 x,y,z;
double m1,a1,m2;
if (base->flags & BMF_TRANSFORMATION) {
base->flags&=~BMF_TRANSFORMATION;
GrRotate(base->r,&cx,&cy,&cz);
cx+=base->x;
cy+=base->y;
cz+=base->z;
radius<<=24;
x=radius; y=0; z=0;
GrRotate(base->r,&x,&y,&z);
R2P(&m1,&a1,x,y);
x=0; y=radius; z=0;
GrRotate(base->r,&x,&y,&z);
m2=Sqrt(x*x+y*y);
Ellipse(base,cx,cy,cz,
m1/0x1000000,m2/0x1000000,
&GrLine3Plot,-a1,step,start_rad,len_rad);
base->flags|=BMF_TRANSFORMATION;
} else
Circle(base,cx,cy,cz,radius,&GrLine3Plot,step,start_rad,len_rad);
}
public void GrEllipse3(GrBitMap *base,
I8 cx,I8 cy,I8 cz,
I8 x_radius,I8 y_radius,
double rot_angle=0,
I8 step=1,
double start_rad=0,
double len_rad=pi2)
{
I8 x,y,z;
double m1,a1,m2,a2,s,c;
if (base->flags & BMF_TRANSFORMATION) {
base->flags&=~BMF_TRANSFORMATION;
GrRotate(base->r,&cx,&cy,&cz);
cx+=base->x;
cy+=base->y;
cz+=base->z;
c=Cos(rot_angle);
s=Sin(rot_angle);
x_radius<<=24;
y_radius<<=24;
x=x_radius*c;
y=x_radius*s;
z=0;
GrRotate(base->r,&x,&y,&z);
R2P(&m1,&a1,x,y);
x=-y_radius*s;
y=y_radius*c;
z=0;
GrRotate(base->r,&x,&y,&z);
R2P(&m2,&a2,x,y);
m2=m2*Abs(Sin(a2-a1));
Ellipse(base,cx,cy,cz,
m1/0x1000000,m2/0x1000000,&GrLine3Plot,-a1,step,start_rad,len_rad);
base->flags|=BMF_TRANSFORMATION;
} else
Ellipse(base,cx,cy,cz,x_radius,y_radius,&GrLine3Plot,rot_angle,step,start_rad,len_rad);
}
public I8 GrFloodFill3(GrBitMap *base,I8 x1,I8 y1,I8 z1,BoolU4 not_color=TRUE)
{ //transformation
I8 cnt,old_flags=base->flags;
if (base->flags & BMF_TRANSFORMATION) {
GrRotate(base->r,&x1,&y1,&z1);
x1+=base->x;
y1+=base->y;
z1+=base->z;
}
base->flags&=~BMF_TRANSFORMATION;
cnt=GrFloodFill(base,x1,y1,not_color);
base->flags=old_flags;
return cnt;
}
public void GrBox3(GrBitMap *base,I8 x,I8 y,I8 z,I8 w,I8 h)
{ //Clipping and transformation
I8 x2,y2,z2,x3,y3,z3;
GrBitMap *old_brush=base->brush;
if (base->flags & BMF_TRANSFORMATION) {
base->brush=NULL;
x2=x+w; y2=y; z2=z;
x3=x; y3=y+h; z3=z;
GrRotate(base->r,&x,&y,&z);
x+=base->x;
y+=base->y;
z+=base->z;
GrRotate(base->r,&x2,&y2,&z2);
x2+=base->x;
y2+=base->y;
z2+=base->z;
GrRotate(base->r,&x3,&y3,&z3);
x3+=base->x;
y3+=base->y;
z3+=base->z;
Box(base,x,y,z,x2,y2,z2,x3,y3,z3,&GrLinePlot);
base->brush=old_brush;
} else
GrBox(base,x,y,w,h);
}
public BoolU8 GrBlot3(GrBitMap *base,I8 x1,I8 y1,I8 z1,GrBitMap *img)
{ //Clipping and transformation
I8 reg i,j,w=img->width,h=img->height,old_color=base->color,reg color,
d1,dx1,dy1,dz1,
reg d2,dx2,dy2,dz2,
adx1,ady1,adz1,
adx2,ady2,adz2,
x2,y2,z2,x3,y3,z3,
dw,reg dh,x,y;
GrBitMap *old_brush=base->brush;
if (base->flags & BMF_TRANSFORMATION) {
x2=x1+w; y2=y1; z2=z1;
x3=x1; y3=y1+h; z3=z1;
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;
GrRotate(base->r,&x3,&y3,&z3);
x3+=base->x;
y3+=base->y;
z3+=base->z;
dx1=x2-x1; dy1=y2-y1; dz1=z2-z1;
dx2=x3-x1; dy2=y3-y1; dz2=z3-z1;
adx1=AbsI8(dx1); ady1=AbsI8(dy1); adz1=AbsI8(dz1);
adx2=AbsI8(dx2); ady2=AbsI8(dy2); adz2=AbsI8(dz2);
if (adx1>=ady1)
d1=(adx1>=adz1) ? adx1:adz1;
else
d1=(ady1>=adz1) ? ady1:adz1;
d1<<=1;
if (d1) {
dx1=dx1<<32/d1;
dy1=dy1<<32/d1;
dz1=dz1<<32/d1;
} else
return FALSE;
if (adx2>=ady2)
d2=(adx2>=adz2) ? adx2:adz2;
else
d2=(ady2>=adz2) ? ady2:adz2;
d2<<=1;
if (d2) {
dx2=dx2<<32/d2;
dy2=dy2<<32/d2;
dz2=dz2<<32/d2;
} else
return FALSE;
base->brush=NULL;
x=0;y=0;
dw=w<<32/d1;
dh=h<<32/d2;
x1<<=32; y1<<=32; z1<<=32;
for (j=0;j<=d1;j++) {
x2=x1; y2=y1; z2=z1;
y=0;
for (i=0;i<=d2;i++) {
color=GrPeek(img,x.i4[1],y.i4[1]);
if (color>=0 &&
(old_color.u1[3]!=ROPB_TRANSPARENT ||
color&0xFFFFFF!=img->bkcolor&0xFFFFFF)) {
base->color=old_color&0xFF000000+color;
GrPlot(base,x2.i4[1],y2.i4[1]);
}
x2+=dx2; y2+=dy2; z2+=dz2;
y+=dh;
}
x1+=dx1; y1+=dy1; z1+=dz1;
x+=dw;
}
base->color=old_color;
base->brush=old_brush;
return TRUE; //TODO: check off screen
} else
return GrBlot(base,x1,y1,img);
}
public void Gr2Bezier3(GrBitMap *base,P3I4 *ctrl)
{
I8 i,x,y,z;
P3I4 *ctrl2;
if (base->flags & BMF_TRANSFORMATION) {
ctrl2=MAlloc(sizeof(P3I4)*3);
for (i=0;i<3;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
GrRotate(base->r,&x,&y,&z);
ctrl2[i].x=x+base->x;
ctrl2[i].y=y+base->y;
ctrl2[i].z=z+base->z;
}
base->flags&=~BMF_TRANSFORMATION;
Bezier2(base,ctrl2,&GrLine3Plot);
base->flags|=BMF_TRANSFORMATION;
Free(ctrl2);
} else
Bezier2(base,ctrl,&GrLine3Plot);
}
public void Gr3Bezier3(GrBitMap *base,P3I4 *ctrl)
{
I8 i,x,y,z;
P3I4 *ctrl2;
if (base->flags & BMF_TRANSFORMATION) {
ctrl2=MAlloc(sizeof(P3I4)*4);
for (i=0;i<4;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
GrRotate(base->r,&x,&y,&z);
ctrl2[i].x=x+base->x;
ctrl2[i].y=y+base->y;
ctrl2[i].z=z+base->z;
}
base->flags&=~BMF_TRANSFORMATION;
Bezier3(base,ctrl2,&GrLine3Plot);
base->flags|=BMF_TRANSFORMATION;
Free(ctrl2);
} else
Bezier3(base,ctrl,&GrLine3Plot);
}
public void Gr2BSpline3(GrBitMap *base,P3I4 *ctrl,I8 cnt,BoolU4 closed=FALSE)
{
I8 i,x,y,z;
P3I4 *ctrl2;
if (base->flags & BMF_TRANSFORMATION) {
ctrl2=MAlloc(sizeof(P3I4)*cnt);
for (i=0;i<cnt;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
GrRotate(base->r,&x,&y,&z);
ctrl2[i].x=x+base->x;
ctrl2[i].y=y+base->y;
ctrl2[i].z=z+base->z;
}
base->flags&=~BMF_TRANSFORMATION;
BSpline2(base,ctrl2,cnt,&GrLine3Plot,closed);
base->flags|=BMF_TRANSFORMATION;
Free(ctrl2);
} else
BSpline2(base,ctrl,cnt,&GrLine3Plot,closed);
}
public void Gr3BSpline3(GrBitMap *base,P3I4 *ctrl,I8 cnt,BoolU4 closed=FALSE)
{
I8 i,x,y,z;
P3I4 *ctrl2;
if (base->flags & BMF_TRANSFORMATION) {
ctrl2=MAlloc(sizeof(P3I4)*cnt);
for (i=0;i<cnt;i++) {
x=ctrl[i].x;
y=ctrl[i].y;
z=ctrl[i].z;
GrRotate(base->r,&x,&y,&z);
ctrl2[i].x=x+base->x;
ctrl2[i].y=y+base->y;
ctrl2[i].z=z+base->z;
}
base->flags&=~BMF_TRANSFORMATION;
BSpline3(base,ctrl2,cnt,&GrLine3Plot,closed);
base->flags|=BMF_TRANSFORMATION;
Free(ctrl2);
} else
BSpline3(base,ctrl,cnt,&GrLine3Plot,closed);
}
void GrLinePlot4(GrBitMap *base,I8 x,I8 y,I8 z)
{
nounusedwarn 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 with base->brush
if (ClipLine(base,&x1,&y1,&x2,&y2))
Line(base,x1,y1,0,x2,y2,0,&GrLinePlot4,step,start);
}
public void GrSpeedLine(GrBitMap *base,I8 x1,I8 y1,I8 x2,I8 y2,double speed)
{
U8 old_flags=base->flags;
I8 old_pen_width=base->pen_width;
if (ClipLine(base,&x1,&y1,&x2,&y2)) {
base->pen_width=base->speedline_scale*speed;
base->flags&=~BMF_TRANSFORMATION;
GrLine3(base,x1,y1,0,x2,y2,0);
base->flags=old_flags;
base->pen_width=old_pen_width;
}
}
public void GrSpeedLine2(GrBitMap *base,I8 x1,I8 y1,I8 z1,I8 x2,I8 y2,I8 z2,double speed)
{ //transformation but not 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;
GrSpeedLine(base,x1,y1,x2,y2,speed);
base->flags=old_flags;
}