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-1width-1; bottom=base->win_tss->win_pixel_bottom-base->win_tss->win_pixel_top-1; if (base->height-1height-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_widthcolor; 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 (distnearest_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;ibrush 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;ir,&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;ir,&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; }