hschumann2/TempleOS-Source-Code
0847
1 2#help_index "Graphics"3 4public Bool GrClamp(CDC *dc=gr.dc,I64 *left,I64 *top,I64 *right,I64 *bottom,5 I64 width=0,I64 height=0)6{//Returns scrn, not window coordinates.7 CTask *win_task;8 *left=0;9 *top=0;10 *right=dc->width-1;11 *bottom=dc->height-1;12 if (dc->flags & DCF_SCRN_BITMAP) {13 win_task=dc->win_task;14 if (GR_WIDTH-1<*right)15 *right=GR_WIDTH-1;16 if (GR_HEIGHT-1<*bottom)17 *bottom=GR_HEIGHT-1;18 if (win_task->pix_left>*left)19 *left=win_task->pix_left;20 if (win_task->pix_top>*top)21 *top=win_task->pix_top;22 if (win_task->pix_right<*right)23 *right=win_task->pix_right;24 if (win_task->pix_bottom<*bottom)25 *bottom=win_task->pix_bottom;26 }27 *left-=width;28 *right+=width;29 *top-=height;30 *bottom+=height;31 return *left<=*right && *top<=*bottom;32}33 34Bool DCClipLine(CDC *dc=gr.dc,I64 *x1,I64 *y1,I64 *x2,I64 *y2,35 I64 width=0,I64 height=0)36{//Also converts window to scrn coordinates37 I64 left,top,right,bottom;38 CTask *win_task;39 if (GrClamp(dc,&left,&top,&right,&bottom,width,height)) {40 if (dc->flags & DCF_SCRN_BITMAP) {41 win_task=dc->win_task;42 *x1+=win_task->pix_left+win_task->scroll_x;43 *y1+=win_task->pix_top+win_task->scroll_y;44 *x2+=win_task->pix_left+win_task->scroll_x;45 *y2+=win_task->pix_top+win_task->scroll_y;46 }47 return ClipLine(x1,y1,x2,y2,left,top,right,bottom);48 } else49 return FALSE;50}51 52public Bool GrPlot(CDC *dc=gr.dc,I64 x,I64 y)53{//2D. Clipping but No transformation or thick.54 I32 *db=dc->depth_buf;55 CTask *win_task;56 CColorROPU32 old_color;57 dc->depth_buf=NULL;58 if (dc->brush) {59 old_color=dc->color;60 if (dc->color.c0.rop!=ROPB_COLLISION)61 dc->color.c0.rop=ROPB_MONO;62 GrBlot(dc,x,y,dc->brush);63 dc->color=old_color;64 } else if (dc->flags & DCF_SCRN_BITMAP) {65 win_task=dc->win_task;66 x+=win_task->pix_left+win_task->scroll_x;67 y+=win_task->pix_top+win_task->scroll_y;68 if (win_task->pix_left<=x<=win_task->pix_right &&69 win_task->pix_top<=y<=win_task->pix_bottom &&70 0<=x<dc->width && 0<=y<dc->height &&71 (win_task->next_task==sys_winmgr_task ||72 dc->flags&DCF_ON_TOP ||73 !IsPixCovered0(win_task,x,y)))74 GrPlot0(dc,x,y);75 } else76 if (0<=x<dc->width && 0<=y<dc->height)77 GrPlot0(dc,x,y);78 dc->depth_buf=db;79 return TRUE;80}81 82Bool GrPlot1(CDC *dc=gr.dc,I64 x,I64 y)83{//Clipping but No transformation or thick, called with db_z set84 CTask *win_task;85 CColorROPU32 old_color;86 if (dc->brush) {87 old_color=dc->color;88 if (dc->color.c0.rop!=ROPB_COLLISION)89 dc->color.c0.rop=ROPB_MONO;90 if (dc->depth_buf)91 GrBlot3(dc,x,y,dc->db_z,dc->brush);92 else93 GrBlot(dc,x,y,dc->brush);94 dc->color=old_color;95 } else if (dc->flags & DCF_SCRN_BITMAP) {96 win_task=dc->win_task;97 x+=win_task->pix_left+win_task->scroll_x;98 y+=win_task->pix_top+win_task->scroll_y;99 if (win_task->pix_left<=x<=win_task->pix_right &&100 win_task->pix_top <=y<=win_task->pix_bottom &&101 0<=x<dc->width && 0<=y<dc->height &&102 (win_task->next_task==sys_winmgr_task ||103 dc->flags&DCF_ON_TOP ||104 !IsPixCovered0(win_task,x,y)))105 GrPlot0(dc,x,y);106 } else107 if (0<=x<dc->width && 0<=y<dc->height)108 GrPlot0(dc,x,y);109 return TRUE;110}111 112public I64 GrPeek(CDC *dc=gr.dc,I64 x,I64 y)113{//2D. Clipping but no transformation.114//Returns pix color or -1 if off-scrn or covered.115 CTask *win_task;116 if (dc->flags & DCF_SCRN_BITMAP) {117 win_task=dc->win_task;118 x+=win_task->pix_left+win_task->scroll_x;119 y+=win_task->pix_top+win_task->scroll_y;120 if (!(win_task->pix_left<=x<=win_task->pix_right) ||121 !(win_task->pix_top <=y<=win_task->pix_bottom) ||122 !(0<=x<dc->width) || !(0<=y<dc->height) ||123 win_task->next_task!=sys_winmgr_task &&124 !(dc->flags&DCF_ON_TOP) &&125 IsPixCovered0(win_task,x,y))126 return -1;127 } else128 if (!(0<=x<dc->width) || !(0<=y<dc->height))129 return -1;130 return GrPeek0(dc,x,y);131}132 133/*134 135This is an easier to understand136version of the nonrecursive routine below.137I64 GrFloodFillRay(CDC *dc,I64 x,I64 y,I64 z,I32 *db)138{139 I64 res,j,x1,ray_len,ray_len2;140 141 if (UnusedStk<0x80)142 Panic("Stk Overflow",Fs);143 144 res=ray_len=GrRayLen(dc,&x,y,z,db);145 y--;146 j=ray_len;147 x1=x;148 while (j>0) {149 if (ray_len2=GrRayLenMinus(dc,x1,y))150 res+=GrFloodFillRay(dc,x1,y,z,db);151 j-=ray_len2+1;152 x1-=ray_len2+1;153 }154 y+=2;155 j=ray_len;156 x1=x;157 while (j>0) {158 if (ray_len2=GrRayLenMinus(dc,x1,y))159 res+=GrFloodFillRay(dc,x1,y,z,db);160 j-=ray_len2+1;161 x1-=ray_len2+1;162 }163 return res;164}165*/166 167class CFFRay168{169 I64 state,x,y,j,x1,ray_len,ray_len2;170};171 172I64 GrFloodFillRay(CDC *dc,I64 x,I64 y,I64 z,I32 *db)173{//See the above commented-out routine for an easier to understand version.174//Returns cnt of pixs changed175 I64 res=0;176//We don't dynamically calculate the size to avoid177 //fragmentation of memory.178 CFFRay *f_dc=MAlloc(sizeof(CFFRay)*0x80000),*f=f_dc;179 f->x=x;180 f->y=y;181 f->state=0;182 do {183 switch [f->state] {184 case 0:185 f->state++;186 res+=f->ray_len=GrRayLen(dc,&f->x,f->y,z,db);187 f->y--;188 f->j=f->ray_len;189 f->x1=f->x;190 break;191 case 1:192 if (f->j>0) {193 f->state++;194 if (f->ray_len2=GrRayLenMinus(dc,f->x1,f->y)) {195 f[1].x=f->x1;196 f[1].y=f->y;197 f[1].state=0;198 f++;199 }200 } else201 f->state+=2;202 break;203 case 2:204 f->state--;205 f->j-=f->ray_len2+1;206 f->x1-=f->ray_len2+1;207 break;208 case 3:209 f->state++;210 f->y+=2;211 f->j=f->ray_len;212 f->x1=f->x;213 break;214 case 4:215 if (f->j>0) {216 f->state++;217 if (f->ray_len2=GrRayLenMinus(dc,f->x1,f->y)) {218 f[1].x=f->x1;219 f[1].y=f->y;220 f[1].state=0;221 f++;222 }223 } else224 f->state+=2;225 break;226 case 5:227 f->state--;228 f->j-=f->ray_len2+1;229 f->x1-=f->ray_len2+1;230 break;231 case 6:232 f--;233 break;234 }235 } while (f>=f_dc);236 Free(f_dc);237 return res;238}239 240public I64 GrFloodFill(CDC *dc=gr.dc,I64 x,I64 y,241 Bool not_color=FALSE,I64 z=0,I32 *db=NULL)242{//2D. Ignore z and db.243//not_color=TRUE means fill up to everything which is not the current color.244 //not_color=FALSE means fill all parts equ to the color under the point.245 //Returns cnt of pixs changed246 I64 res=0,j,old_flags=dc->flags;247 CColorROPU32 old_color2=dc->color2;248 CDC *old_brush;249 if (dc->flags & DCF_DONT_DRAW) //TODO250 return 0;251 old_brush=dc->brush;252 dc->brush=NULL;253 if ((j=GrPeek(dc,x,y))>=0) {254 if (not_color) {255 dc->color2=dc->color.c0.color;256 dc->flags|=DCF_FILL_NOT_COLOR;257 } else {258 dc->color2=j;259 if (dc->color.c1.rop&ROPBF_DITHER) {260 if (dc->color2.c0.color==dc->color.c0.color &&261 dc->color.c0.color==dc->color.c1.color)262 goto ff_done;263 } else if (dc->color2.c0.color==dc->color.c0.color)264 goto ff_done;265 dc->flags&=~DCF_FILL_NOT_COLOR;266 }267 if (not_color && j!=dc->color2 ||268 !not_color)269 res=GrFloodFillRay(dc,x,y,z,db);270 }271ff_done:272 dc->brush=old_brush;273 dc->flags=old_flags;274 dc->color2=old_color2;275 return res;276}277 278I64 GrFillSemiCircle(CDC *dc=gr.dc,I64 cx,I64 cy,I64 z=0,I64 diameter,I64 n)279{//2D. Clipping but not transformation.280 I64 res=0,i,k,r=diameter>>1,rr;281 if (diameter>=1)282 switch (n) {283 case 0:284 if (diameter<GR_PEN_BRUSHES_NUM)285 for (i=0;i<r;i++)286 res+=GrHLine(dc,gr.circle_lo[diameter][i]+cx,287 gr.circle_hi[diameter][i]+cx,cy+i-r,z,z);288 else {289 k=diameter+1;290 rr=SqrI64((k+1)>>1);291 for (i=0;i<r;i++)292 res+=GrHLine(dc,-Sqrt(rr-SqrI64(r-i))+cx,293 Sqrt(rr-SqrI64(r-i))+cx,cy+i-r,z,z);294 }295 break;296 case 1:297 if (diameter<GR_PEN_BRUSHES_NUM)298 for (i=r+1;i<diameter;i++)299 res+=GrHLine(dc,gr.circle_lo[diameter][i]+cx,300 gr.circle_hi[diameter][i]+cx,cy+i-r,z,z);301 else {302 k=diameter+1;303 rr=SqrI64((k+1)>>1);304 for (i=r+1;i<k;i++)305 res+=GrHLine(dc,-Sqrt(rr-SqrI64(i-r))+cx,306 Sqrt(rr-SqrI64(i-r))+cx,cy+i-r,z,z);307 }308 break;309 case 2:310 if (diameter<GR_PEN_BRUSHES_NUM)311 for (i=0;i<r;i++)312 res+=GrVLine(dc,cx+i-r,gr.circle_lo[diameter][i]+cy,313 gr.circle_hi[diameter][i]+cy,z,z);314 else {315 k=diameter+1;316 rr=SqrI64((k+1)>>1);317 for (i=0;i<r;i++)318 res+=GrVLine(dc,cx+i-r,-Sqrt(rr-SqrI64(r-i))+cy,319 Sqrt(rr-SqrI64(r-i))+cy,z,z);320 }321 break;322 case 3:323 if (diameter<GR_PEN_BRUSHES_NUM)324 for (i=r+1;i<diameter;i++)325 res+=GrVLine(dc,cx+i-r,gr.circle_lo[diameter][i]+cy,326 gr.circle_hi[diameter][i]+cy,z,z);327 else {328 k=diameter+1;329 rr=SqrI64((k+1)>>1);330 for (i=r+1;i<k;i++)331 res+=GrVLine(dc,cx+i-r,-Sqrt(rr-SqrI64(i-r))+cy,332 Sqrt(rr-SqrI64(i-r))+cy,z,z);333 }334 break;335 case 4:336 if (diameter<GR_PEN_BRUSHES_NUM)337 for (i=0;i<r;i++)338 res+=GrHLine(dc,gr.circle_lo[diameter][i]+cx,339 gr.circle_hi[diameter][i]+cx,cy+i-r,z,z);340 else {341 k=diameter+1;342 rr=SqrI64((k+1)>>1);343 for (i=0;i<r;i++)344 res+=GrHLine(dc,-Sqrt(rr-SqrI64(r-i))+cx,345 Sqrt(rr-SqrI64(r-i))+cx,cy+i-r,z,z);346 }347 break;348 case 5:349 if (diameter<GR_PEN_BRUSHES_NUM)350 for (i=r+1;i<diameter;i++)351 res+=GrHLine(dc,gr.circle_lo[diameter][i]+cx,352 gr.circle_hi[diameter][i]+cx,cy+i-r,z,z);353 else {354 k=diameter+1;355 rr=SqrI64((k+1)>>1);356 for (i=r+1;i<k;i++)357 res+=GrHLine(dc,-Sqrt(rr-SqrI64(i-r))+cx,358 Sqrt(rr-SqrI64(i-r))+cx,cy+i-r,z,z);359 }360 break;361 case 6:362 if (diameter<GR_PEN_BRUSHES_NUM)363 for (i=0;i<r;i++)364 res+=GrVLine(dc,cx+i-r,gr.circle_lo[diameter][i]+cy,365 gr.circle_hi[diameter][i]+cy,z,z);366 else {367 k=diameter+1;368 rr=SqrI64((k+1)>>1);369 for (i=0;i<r;i++)370 res+=GrVLine(dc,cx+i-r,-Sqrt(rr-SqrI64(r-i))+cy,371 Sqrt(rr-SqrI64(r-i))+cy,z,z);372 }373 break;374 case 7:375 if (diameter<GR_PEN_BRUSHES_NUM)376 for (i=r+1;i<diameter;i++)377 res+=GrVLine(dc,cx+i-r,gr.circle_lo[diameter][i]+cy,378 gr.circle_hi[diameter][i]+cy,z,z);379 else {380 k=diameter+1;381 rr=SqrI64((k+1)>>1);382 for (i=r+1;i<k;i++)383 res+=GrVLine(dc,cx+i-r,-Sqrt(rr-SqrI64(i-r))+cy,384 Sqrt(rr-SqrI64(i-r))+cy,z,z);385 }386 break;387 }388 return res;389}390 391public I64 GrFillCircle(CDC *dc=gr.dc,I64 cx,I64 cy,I64 z=0,I64 diameter)392{//2D. Clipping but not transformation.393 I64 res=0,i,k,r=diameter>>1,rr;394 if (diameter>=1) {395 if (diameter<GR_PEN_BRUSHES_NUM)396 for (i=0;i<diameter;i++)397 res+=GrHLine(dc,gr.circle_lo[diameter][i]+cx,398 gr.circle_hi[diameter][i]+cx,cy+i-r,z,z);399 else {400 k=diameter+1;401 rr=SqrI64((k+1)>>1);402 for (i=0;i<=r;i++)403 res+=GrHLine(dc,-Sqrt(rr-SqrI64(r-i))+cx,404 Sqrt(rr-SqrI64(r-i))+cx,cy+i-r,z,z);405 for (;i<k;i++)406 res+=GrHLine(dc,-Sqrt(rr-SqrI64(i-r))+cx,407 Sqrt(rr-SqrI64(i-r))+cx,cy+i-r,z,z);408 }409 }410 return res;411}412 413public Bool GrPlot3B(CDC *dc=gr.dc,I64 x,I64 y,I64 z)414{//3D. Clipping and transformation but no thick.415 I64 _x,_y,_z;416 Bool was_transform=FALSE,was_symmetry=FALSE;417 if (dc->flags & DCF_TRANSFORMATION) {418 (*dc->transform)(dc,&x,&y,&z);419 dc->flags&=~DCF_TRANSFORMATION;420 was_transform=TRUE;421 }422 if (dc->flags & DCF_SYMMETRY) {423 _x=x; _y=y; _z=z;424 DCReflect(dc,&_x,&_y,&_z);425 dc->flags&=~DCF_SYMMETRY;426 dc->db_z=_z;427 GrPlot1(dc,_x,_y);428 was_symmetry=TRUE;429 if (dc->flags&DCF_JUST_MIRROR)430 goto gr_done;431 }432 dc->db_z=z;433 GrPlot1(dc,x,y);434gr_done:435 if (was_transform)436 dc->flags|=DCF_TRANSFORMATION;437 if (was_symmetry)438 dc->flags|=DCF_SYMMETRY;439 return TRUE;440}441 442public Bool GrPlot3(CDC *dc=gr.dc,I64 x,I64 y,I64 z)443{//3D. Clipping and transformation and thick.444 I64 _x,_y,_z,w,dist;445 CColorROPU32 old_color=dc->color;446 Bool record,was_transform=FALSE,was_symmetry=FALSE;447 CTask *win_task;448 if (dc->flags & DCF_TRANSFORMATION) {449 (*dc->transform)(dc,&x,&y,&z);450 dc->flags&=~DCF_TRANSFORMATION;451 was_transform=TRUE;452 }453 if (dc->flags & DCF_SYMMETRY) {454 _x=x; _y=y; _z=z;455 DCReflect(dc,&_x,&_y,&_z);456 dc->flags&=~DCF_SYMMETRY;457 GrPlot3(dc,_x,_y,_z);458 was_symmetry=TRUE;459 if (dc->flags&DCF_JUST_MIRROR)460 goto gr_done;461 }462 w=dc->thick>>1;463 dc->db_z=z;464 if (dc->brush || w<=0)465 GrPlot1(dc,x,y);466 else if (dc->thick<GR_PEN_BRUSHES_NUM) {467 if (dc->color.c0.rop!=ROPB_COLLISION)468 dc->color.c0.rop=ROPB_MONO;469 if (dc->depth_buf) {470 if (dc->color.c1.rop&ROPBF_DITHER) {471 dc->color.c1.rop=dc->color.c0.rop;472 if (((x-w)^(y-w))&1) {473 record=GrBlot3(dc,x-w,y-w,z,gr.odd_pen_brushes[dc->thick]);474 dc->color.c0=dc->color.c1;475 record=GrBlot3(dc,x-w,y-w,z,gr.even_pen_brushes[dc->thick]);476 } else {477 record=GrBlot3(dc,x-w,y-w,z,gr.even_pen_brushes[dc->thick]);478 dc->color.c0=dc->color.c1;479 record=GrBlot3(dc,x-w,y-w,z,gr.odd_pen_brushes[dc->thick]);480 }481 } else {482 if (dc->color.c0.rop==ROPB_COLLISION) {483 if (dc->color.c0.color!=dc->bkcolor.c0.color &&484 dc->color.c0.color!=TRANSPARENT)485 record=GrBlot3(dc,x-w,y-w,z,486 gr.collision_pen_brushes[dc->thick]);487 else488 record=FALSE;489 } else490 record=GrBlot3(dc,x-w,y-w,z,gr.pen_brushes[dc->thick]);491 }492 } else {493 if (dc->color.c1.rop&ROPBF_DITHER) {494 dc->color.c1.rop=dc->color.c0.rop;495 if (((x-w)^(y-w))&1) {496 record=GrBlot(dc,x-w,y-w,gr.odd_pen_brushes[dc->thick]);497 dc->color.c0=dc->color.c1;498 record=GrBlot(dc,x-w,y-w,gr.even_pen_brushes[dc->thick]);499 } else {500 record=GrBlot(dc,x-w,y-w,gr.even_pen_brushes[dc->thick]);501 dc->color.c0=dc->color.c1;502 record=GrBlot(dc,x-w,y-w,gr.odd_pen_brushes[dc->thick]);503 }504 } else {505 if (dc->color.c0.rop==ROPB_COLLISION) {506 if (dc->color.c0.color!=dc->bkcolor.c0.color &&507 dc->color.c0.color!=TRANSPARENT)508 record=GrBlot(dc,x-w,y-w,gr.collision_pen_brushes[dc->thick]);509 else510 record=FALSE;511 } else512 record=GrBlot(dc,x-w,y-w,gr.pen_brushes[dc->thick]);513 }514 }515 if (record) {516 if (dc->flags & DCF_SCRN_BITMAP) {517 win_task=dc->win_task;518 x+=win_task->pix_left+win_task->scroll_x;519 y+=win_task->pix_top+win_task->scroll_y;520 }521 if (dc->flags & DCF_LOCATE_NEAREST) {522 dist=DistSqrI64(x,y,dc->cur_x,dc->cur_y);523 if (dist<=dc->nearest_dist)524 dc->nearest_dist=dist;525 }526 if (dc->flags & DCF_RECORD_EXTENTS) {527 if (x-w<dc->min_x) dc->min_x=x-w;528 if (y-w<dc->min_y) dc->min_y=y-w;529 if (dc->thick & 1) {530 if (x+w>dc->max_x) dc->max_x=x+w;531 if (y+w>dc->max_y) dc->max_y=y+w;532 } else {533 if (x+w-1>dc->max_x) dc->max_x=x+w-1;534 if (y+w-1>dc->max_y) dc->max_y=y+w-1;535 }536 }537 }538 } else539 GrFillCircle(dc,x,y,dc->db_z,dc->thick);540gr_done:541 dc->color=old_color;542 if (was_transform)543 dc->flags|=DCF_TRANSFORMATION;544 if (was_symmetry)545 dc->flags|=DCF_SYMMETRY;546 return TRUE;547}548 549Bool GrLinePlot0(CDC *dc,I64 x,I64 y,I64 z)550{//This is a callback.551 CTask *win_task=dc->win_task;552 if (!(dc->flags & DCF_SCRN_BITMAP) ||553 win_task->next_task==sys_winmgr_task ||554 dc->flags&DCF_ON_TOP ||555 !IsPixCovered0(win_task,x,y)) {556 dc->db_z=z;557 GrPlot0(dc,x,y);558 }559 return TRUE;560}561 562Bool GrLinePlot(CDC *dc,I64 x,I64 y,I64 z)563{//This is a callback.564 dc->db_z=z;565 GrPlot1(dc,x,y);566 return TRUE;567}568 569public Bool GrLine(CDC *dc=gr.dc,I64 x1,I64 y1,I64 x2,I64 y2,570 I64 step=1,I64 start=0)571{//2D. Clipping but not transformation.572 Bool res=FALSE;573 I32 *db=dc->depth_buf;574 dc->depth_buf=NULL;575 if (step==1 && !start && !dc->brush && !dc->depth_buf) {576 if (DCClipLine(dc,&x1,&y1,&x2,&y2))577 res=Line(dc,x1,y1,0,x2,y2,0,&GrLinePlot0,step,start);578 } else579 res=Line(dc,x1,y1,0,x2,y2,0,&GrLinePlot,step,start);580 dc->depth_buf=db;581 return res;582}583 584public Bool GrCircle(CDC *dc=gr.dc,I64 cx,I64 cy,I64 radius,585 I64 step=1,F64 start_radians=0,F64 len_radians=2*pi)586{//2D. Clipping but not transformation.587 Bool res;588 I32 *db=dc->depth_buf;589 dc->depth_buf=NULL;590 res=Circle(dc,cx,cy,0,radius,&GrLinePlot,step,start_radians,len_radians);591 dc->depth_buf=db;592 return res;593}594 595public Bool GrEllipse(CDC *dc=gr.dc,596 I64 cx,I64 cy,597 I64 x_radius,I64 y_radius,598 F64 rot_angle=0,599 I64 step=1,600 F64 start_radians=0,601 F64 len_radians=2*pi)602{//2D. Clipping but not transformation.603 Bool res;604 I32 *db=dc->depth_buf;605 dc->depth_buf=NULL;606 res=Ellipse(dc,cx,cy,0,x_radius,y_radius,&GrLinePlot,607 rot_angle,step,start_radians,len_radians);608 dc->depth_buf=db;609 return res;610}611 612public Bool GrRegPoly(CDC *dc=gr.dc,613 I64 cx,I64 cy,614 I64 x_radius,I64 y_radius,I64 sides,615 F64 rot_angle=0,616 I64 step=1,617 F64 start_radians=0,618 F64 len_radians=2*pi)619{//2D. Clipping but no transform or thick.620 Bool res;621 I32 *db=dc->depth_buf;622 dc->depth_buf=NULL;623 res=RegPoly(dc,cx,cy,0,x_radius,y_radius,sides,624 &GrLinePlot,rot_angle,step,start_radians,len_radians);625 dc->depth_buf=db;626 return res;627}628 629public Bool Gr2Bezier(CDC *dc=gr.dc,CD3I32 *ctrl)630{//2nd order. Clipping but no transform or thick.631 return Bezier2(dc,ctrl,&GrLinePlot);632}633 634public Bool Gr3Bezier(CDC *dc=gr.dc,CD3I32 *ctrl)635{//3rd order. Clipping but no transform or thick.636 return Bezier3(dc,ctrl,&GrLinePlot);637}638 639public Bool Gr2BSpline(CDC *dc=gr.dc,CD3I32 *ctrl,I64 cnt,Bool closed=FALSE)640{//2nd order. Clipping but no transform or thick.641 return BSpline2(dc,ctrl,cnt,&GrLinePlot,closed);642}643 644public Bool Gr3BSpline(CDC *dc=gr.dc,CD3I32 *ctrl,I64 cnt,Bool closed=FALSE)645{//3rd order. Clipping but no transform or thick.646 return BSpline3(dc,ctrl,cnt,&GrLinePlot,closed);647}648 649I64 GrLineFat3(CDC *dc=gr.dc,I64 x1,I64 y1,I64 z1,I64 x2,I64 y2,I64 z2,650 I64 width,I64 start=0)651{//Step through line segment calling callback.652//Uses fixed-point.653 I64 res=0,i,j,d,dx=x2-x1,dy=y2-y1,dz=z2-z1,_x,_y,_z,d_lo,d_hi,654 adx=AbsI64(dx),ady=AbsI64(dy),adz=AbsI64(dz);655 if (width>0) {656 if (adx>=ady) {657 if (adx>=adz) {658 if (d=adx) {659 if (dx>=0)660 dx=0x100000000;661 else662 dx=-0x100000000;663 dy=dy<<32/d;664 dz=dz<<32/d;665 }666 } else {667 if (d=adz) {668 dx=dx<<32/d;669 dy=dy<<32/d;670 if (dz>=0)671 dz=0x100000000;672 else673 dz=-0x100000000;674 }675 }676 x1<<=32; y1<<=32; z1<<=32;677 for (j=0;j<start;j++) {678 x1+=dx; y1+=dy; z1+=dz;679 }680 if (start>=d)681 res+=GrFillCircle(dc,x1.i32[1],y1.i32[1],z1.i32[1],width);682 else {683 if (width==1)684 for (i=start;i<=d;i++) {685 dc->db_z=z1.i32[1];686 res+=GrPlot1(dc,x1.i32[1],y1.i32[1]);687 _x=x1.i32[1]; _y=y1.i32[1]; _z=z1.i32[1];688 x1+=dx; y1+=dy; z1+=dz;689 }690 else {691 i=width*Sqrt(SqrI64(adx)+SqrI64(ady))/adx;692 d_lo=i>>1; d_hi=(i-1)>>1;693 694 if (dx>=0)695 res+=GrFillSemiCircle(dc,x1.i32[1],y1.i32[1],z1.i32[1],width,2);696 else697 res+=GrFillSemiCircle(dc,x1.i32[1],y1.i32[1],z1.i32[1],width,7);698 for (i=start;i<=d;i++) {699 res+=GrVLine(dc,x1.i32[1],y1.i32[1]-d_lo,y1.i32[1]+d_hi,700 z1.i32[1],z1.i32[1]);701 _x=x1.i32[1]; _y=y1.i32[1]; _z=z1.i32[1];702 x1+=dx; y1+=dy; z1+=dz;703 }704 x1-=dx; y1-=dy; z1-=dz;705 if (dx>=0)706 res+=GrFillSemiCircle(dc,x1.i32[1],y1.i32[1],z1.i32[1],width,3);707 else708 res+=GrFillSemiCircle(dc,x1.i32[1],y1.i32[1],z1.i32[1],width,6);709 }710 }711 } else {712 if (ady>=adz) {713 if (d=ady) {714 dx=dx<<32/d;715 if (dy>=0)716 dy=0x100000000;717 else718 dy=-0x100000000;719 dz=dz<<32/d;720 }721 } else {722 if (d=adz) {723 dx=dx<<32/d;724 dy=dy<<32/d;725 if (dz>=0)726 dz=0x100000000;727 else728 dz=-0x100000000;729 }730 }731 x1<<=32; y1<<=32; z1<<=32;732 for (j=0;j<start;j++) {733 x1+=dx; y1+=dy; z1+=dz;734 }735 if (start>=d)736 res+=GrFillCircle(dc,x1.i32[1],y1.i32[1],z1.i32[1],width);737 else {738 if (width==1)739 for (i=start;i<=d;i++) {740 dc->db_z=z1.i32[1];741 res+=GrPlot1(dc,x1.i32[1],y1.i32[1]);742 _x=x1.i32[1]; _y=y1.i32[1]; _z=z1.i32[1];743 x1+=dx; y1+=dy; z1+=dz;744 }745 else {746 i=width*Sqrt(SqrI64(ady)+SqrI64(adx))/ady;747 d_lo=i>>1; d_hi=(i-1)>>1;748 749 if (dy>=0)750 res+=GrFillSemiCircle(dc,x1.i32[1],y1.i32[1],z1.i32[1],width,0);751 else752 res+=GrFillSemiCircle(dc,x1.i32[1],y1.i32[1],z1.i32[1],width,5);753 for (i=start;i<=d;i++) {754 res+=GrHLine(dc,x1.i32[1]-d_lo,x1.i32[1]+d_hi,y1.i32[1],755 z1.i32[1],z1.i32[1]);756 _x=x1.i32[1]; _y=y1.i32[1]; _z=z1.i32[1];757 x1+=dx; y1+=dy; z1+=dz;758 }759 x1-=dx; y1-=dy; z1-=dz;760 if (dy>=0)761 res+=GrFillSemiCircle(dc,x1.i32[1],y1.i32[1],z1.i32[1],width,1);762 else763 res+=GrFillSemiCircle(dc,x1.i32[1],y1.i32[1],z1.i32[1],width,4);764 }765 }766 }767 }768 return res;769}770 771public Bool GrLine3(CDC *dc=gr.dc,I64 x1,I64 y1,I64 z1,I64 x2,I64 y2,I64 z2,772 I64 step=1,I64 start=0)773{//3D. Transformation with thick.774 I64 _x1,_y1,_z1,_x2,_y2,_z2;775 Bool res=FALSE,was_transform=FALSE,was_symmetry=FALSE;776 if (dc->flags & DCF_TRANSFORMATION) {777 (*dc->transform)(dc,&x1,&y1,&z1);778 (*dc->transform)(dc,&x2,&y2,&z2);779 dc->flags&=~DCF_TRANSFORMATION;780 was_transform=TRUE;781 }782 if (dc->flags & DCF_SYMMETRY) {783 _x1=x1; _y1=y1; _z1=z1;784 DCReflect(dc,&_x1,&_y1,&_z1);785 _x2=x2; _y2=y2; _z2=z2;786 DCReflect(dc,&_x2,&_y2,&_z2);787 dc->flags&=~DCF_SYMMETRY;788 if (step==1 && !dc->brush) {789 if (!start && dc->thick<2 && !dc->depth_buf) {//TODO: clip z depbuf790 if (DCClipLine(dc,&_x1,&_y1,&_x2,&_y2))791 res=Line(dc,_x1,_y1,0,_x2,_y2,0,&GrLinePlot0,step,start);792 } else {793 if (GrLineFat3(dc,_x1,_y1,_z1,_x2,_y2,_z2,dc->thick,start))794 res=TRUE;795 }796 } else797 res=Line(dc,_x1,_y1,_z1,_x2,_y2,_z2,&GrPlot3,step,start);798 was_symmetry=TRUE;799 if (dc->flags&DCF_JUST_MIRROR)800 goto gr_done;801 }802 if (step==1 && !dc->brush) {803 if (!start && dc->thick<2 && !dc->depth_buf) {//TODO: clip z depbuf804 if (DCClipLine(dc,&x1,&y1,&x2,&y2))805 res|=Line(dc,x1,y1,0,x2,y2,0,&GrLinePlot0,step,start);806 } else {807 if (GrLineFat3(dc,x1,y1,z1,x2,y2,z2,dc->thick,start))808 res=TRUE;809 }810 } else811 res|=Line(dc,x1,y1,z1,x2,y2,z2,&GrPlot3,step,start);812gr_done:813 if (was_transform)814 dc->flags|=DCF_TRANSFORMATION;815 if (was_symmetry)816 dc->flags|=DCF_SYMMETRY;817 return res;818}819 820#help_index "Graphics/Char;Char/Graphics"821 822public Bool GrPutChar3(CDC *dc=gr.dc,I64 x,I64 y,I64 z,U8 ch)823{//3D. Transformation. DCF_SYMMETRY is silly.824 if (dc->flags & DCF_TRANSFORMATION)825 (*dc->transform)(dc,&x,&y,&z);826 return GrPutChar(dc,x,y,ch);827}828 829public I64 GrPrint3(CDC *dc=gr.dc,I64 x,I64 y,I64 z,U8 *fmt,...)830{//3D. Transformation. DCF_SYMMETRY is silly.831 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv);832 I64 res;833 if (dc->flags & DCF_TRANSFORMATION)834 (*dc->transform)(dc,&x,&y,&z);835 res=GrPrint(dc,x,y,"%s",buf);836 Free(buf);837 return res;838}839 840public I64 GrVPrint3(CDC *dc=gr.dc,I64 x,I64 y,I64 z,U8 *fmt,...)841{//3D. Vertical text. Transformation. DCF_SYMMETRY is silly.842 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv);843 I64 res;844 if (dc->flags & DCF_TRANSFORMATION)845 (*dc->transform)(dc,&x,&y,&z);846 res=GrVPrint(dc,x,y,"%s",buf);847 Free(buf);848 return res;849}850 851#help_index "Graphics"852 853public Bool GrEllipse3(CDC *dc=gr.dc,854 I64 cx,I64 cy,I64 cz,855 I64 x_radius,I64 y_radius,856 F64 rot_angle=0,857 I64 step=1,858 F64 start_radians=0,859 F64 len_radians=2*pi)860{//3D. Transformation with thick.861 Bool res;862 I64 x,y,z,xx,yy,zz;863 F64 m1,arg1,m2,arg2,s,c;864 if (dc->flags & DCF_TRANSFORMATION) {865 dc->flags&=~DCF_TRANSFORMATION;866 (*dc->transform)(dc,&cx,&cy,&cz);867 868 c=Cos(rot_angle);869 s=Sin(rot_angle);870 871 x_radius<<=16;872 y_radius<<=16;873 874 xx=0;875 yy=0;876 zz=0;877 (*dc->transform)(dc,&xx,&yy,&zz);878 879 x=x_radius*c;880 y=x_radius*s;881 z=0;882 (*dc->transform)(dc,&x,&y,&z);883 x-=xx;884 y-=yy;885 z-=zz;886 R2P(&m1,&arg1,x,y);887 888 x=-y_radius*s;889 y=y_radius*c;890 z=0;891 (*dc->transform)(dc,&x,&y,&z);892 x-=xx;893 y-=yy;894 z-=zz;895 R2P(&m2,&arg2,x,y);896 m2*=Abs(Sin(arg2-arg1));897 898 res=Ellipse(dc,cx,cy,cz,899 m1/0x10000,m2/0x10000,&GrPlot3,-arg1,step,start_radians,len_radians);900 dc->flags|=DCF_TRANSFORMATION;901 } else902 res=Ellipse(dc,cx,cy,cz,x_radius,y_radius,&GrPlot3,903 rot_angle,step,start_radians,len_radians);904 return res;905}906 907public Bool GrCircle3(CDC *dc=gr.dc,I64 cx,I64 cy,I64 cz,I64 radius,908 I64 step=1,F64 start_radians=0,F64 len_radians=2*pi)909{//3D. Transformation with thick.910 if (dc->flags & DCF_TRANSFORMATION)911 return GrEllipse3(dc,cx,cy,cz,radius,radius,0,step,912 start_radians,len_radians);913 else914 return Circle(dc,cx,cy,cz,radius,&GrPlot3,step,915 start_radians,len_radians);916}917 918public Bool GrRegPoly3(CDC *dc=gr.dc,919 I64 cx,I64 cy,I64 cz,920 I64 x_radius,I64 y_radius,I64 sides,921 F64 rot_angle=0,922 I64 step=1,923 F64 start_radians=0,924 F64 len_radians=2*pi)925{//3D. Clipping and transform and thick.926 Bool res;927 I64 x,y,z,xx,yy,zz;928 F64 m1,arg1,m2,arg2,s,c;929 if (dc->flags & DCF_TRANSFORMATION) {930 dc->flags&=~DCF_TRANSFORMATION;931 (*dc->transform)(dc,&cx,&cy,&cz);932 933 c=Cos(rot_angle);934 s=Sin(rot_angle);935 936 x_radius<<=16;937 y_radius<<=16;938 939 xx=0;940 yy=0;941 zz=0;942 (*dc->transform)(dc,&xx,&yy,&zz);943 944 x=x_radius*c;945 y=x_radius*s;946 z=0;947 (*dc->transform)(dc,&x,&y,&z);948 x-=xx;949 y-=yy;950 z-=zz;951 R2P(&m1,&arg1,x,y);952 953 x=-y_radius*s;954 y=y_radius*c;955 z=0;956 (*dc->transform)(dc,&x,&y,&z);957 x-=xx;958 y-=yy;959 z-=zz;960 R2P(&m2,&arg2,x,y);961 m2*=Abs(Sin(arg2-arg1));962 963 res=RegPoly(dc,cx,cy,cz,964 m1/0x10000,m2/0x10000,sides,&GrPlot3,-arg1,965 step,start_radians,len_radians);966 dc->flags|=DCF_TRANSFORMATION;967 } else968 res=RegPoly(dc,cx,cy,cz,x_radius,y_radius,sides,&GrPlot3,969 rot_angle,step,start_radians,len_radians);970 return res;971}972 973public I64 GrFloodFill3(CDC *dc=gr.dc,I64 x1,I64 y1,I64 z1,Bool not_color=FALSE)974{//3D. Transformation.975//not_color=TRUE means fill up to everything which is not the current color.976 //not_color=FALSE means fill all parts equ to the color under the point.977 //Returns cnt of pixs changed978 I64 res,old_flags=dc->flags,979 _x,_y,_z;980 if (dc->flags & DCF_TRANSFORMATION) {981 (*dc->transform)(dc,&x1,&y1,&z1);982 dc->flags&=~DCF_TRANSFORMATION;983 }984 if (dc->flags & DCF_SYMMETRY) {985 _x=x1; _y=y1; _z=z1;986 DCReflect(dc,&_x,&_y,&_z);987 dc->flags&=~DCF_SYMMETRY;988 res=GrFloodFill(dc,_x,_y,not_color,_z,dc->depth_buf);989 if (dc->flags&DCF_JUST_MIRROR)990 goto gr_done;991 }992 res=GrFloodFill(dc,x1,y1,not_color,z1,dc->depth_buf);993gr_done:994 dc->flags=old_flags;995 return res;996}997 998#help_index "Graphics;Graphics/Device Contexts"999 1000Option(OPTf_WARN_HEADER_MISMATCH,OFF);1001public I64 GrBlot3(CDC *dc=gr.dc,I64 x1,I64 y1,I64 z1,CDC *img)1002{//3D. Clipping and transformation.1003 CColorROPU32 old_color=dc->color;1004 I64 color,reg i,j,w=img->width,h=img->height,1005 d1,dx1,dy1,dz1,1006 reg d2,dx2,dy2,dz2,1007 adx1,ady1,adz1,1008 adx2,ady2,adz2,1009 x2,y2,z2,x3,y3,z3,1010 dw,reg dh,x,y,_x1,_y1,_z1,_x2,_y2,_z2,_x3,_y3,_z3,1011 last_x,last_y,res=0;1012 Bool first;1013 CDC *old_brush=dc->brush;1014 1015 if (dc->depth_buf || dc->flags & (DCF_TRANSFORMATION | DCF_SYMMETRY)) {1016 x2=x1+w; y2=y1; z2=z1;1017 x3=x1; y3=y1+h; z3=z1;1018 if (dc->flags & DCF_TRANSFORMATION) {1019 (*dc->transform)(dc,&x1,&y1,&z1);1020 (*dc->transform)(dc,&x2,&y2,&z2);1021 (*dc->transform)(dc,&x3,&y3,&z3);1022 }1023 if (dc->flags & DCF_SYMMETRY) {1024 _x1=x1; _y1=y1; _z1=z1;1025 DCReflect(dc,&_x1,&_y1,&_z1);1026 _x2=x2; _y2=y2; _z2=z2;1027 DCReflect(dc,&_x2,&_y2,&_z2);1028 _x3=x3; _y3=y3; _z3=z3;1029 DCReflect(dc,&_x3,&_y3,&_z3);1030 dx1=_x2-_x1; dy1=_y2-_y1; dz1=_z2-_z1;1031 dx2=_x3-_x1; dy2=_y3-_y1; dz2=_z3-_z1;1032 adx1=AbsI64(dx1); ady1=AbsI64(dy1); adz1=AbsI64(dz1);1033 adx2=AbsI64(dx2); ady2=AbsI64(dy2); adz2=AbsI64(dz2);1034 1035 if (adx1>=ady1) {1036 if (adx1>=adz1)1037 d1=adx1;1038 else1039 d1=adz1;1040 } else {1041 if (ady1>=adz1)1042 d1=ady1;1043 else1044 d1=adz1;1045 }1046 if (adx2>=ady2) {1047 if (adx2>=adz2)1048 d2=adx2;1049 else1050 d2=adz2;1051 } else {1052 if (ady2>=adz2)1053 d2=ady2;1054 else1055 d2=adz2;1056 }1057 1058 if (AbsI64(d1)!=w ||AbsI64(d2)!=h) {1059 d1<<=1;1060 d2<<=1;1061 }1062 if (d1) {1063 dx1=dx1<<32/d1;1064 dy1=dy1<<32/d1;1065 dz1=dz1<<32/d1;1066 } else1067 goto normal_image;1068 if (d2) {1069 dx2=dx2<<32/d2;1070 dy2=dy2<<32/d2;1071 dz2=dz2<<32/d2;1072 } else1073 goto normal_image;1074 dc->brush=NULL;1075 x=0;y=0;1076 dw=w<<32/d1;1077 dh=h<<32/d2;1078 1079 first=TRUE;1080 _x1<<=32; _y1<<=32; _z1<<=32;1081 for (j=0;j<=d1;j++) {1082 _x2=_x1; _y2=_y1; _z2=_z1;1083 y=0;1084 for (i=0;i<=d2;i++) {1085 if (_x2.i32[1]!=last_x || _y2.i32[1]!=last_y ||first) {1086 if ((color=GrPeek(img,x.i32[1],y.i32[1]))>=0) {1087 if (dc->color.c0.rop==ROPB_MONO) {1088 if (color) {1089 dc->color=old_color&~ROPF_DITHER;1090 if (dc->depth_buf) {1091 dc->db_z=_z2.i32[1];1092 GrPlot1(dc,_x2.i32[1],_y2.i32[1]);1093 } else1094 GrPlot(dc,_x2.i32[1],_y2.i32[1]);1095 }1096 } else {1097 if (color!=TRANSPARENT) {1098 dc->color=old_color&~COLORROP_NO_ROP0_MASK|color;1099 if (dc->depth_buf) {1100 dc->db_z=_z2.i32[1];1101 GrPlot1(dc,_x2.i32[1],_y2.i32[1]);1102 } else1103 GrPlot(dc,_x2.i32[1],_y2.i32[1]);1104 }1105 }1106 }1107 }1108 first=FALSE;1109 last_x=_x2.i32[1]; last_y=_y2.i32[1];1110 _x2+=dx2; _y2+=dy2; _z2+=dz2;1111 y+=dh;1112 }1113 _x1+=dx1; _y1+=dy1; _z1+=dz1;1114 x+=dw;1115 }1116 res=1;1117normal_image:1118 if (dc->flags&DCF_JUST_MIRROR)1119 goto gr_done;1120 }1121 dx1=x2-x1; dy1=y2-y1; dz1=z2-z1;1122 dx2=x3-x1; dy2=y3-y1; dz2=z3-z1;1123 adx1=AbsI64(dx1); ady1=AbsI64(dy1); adz1=AbsI64(dz1);1124 adx2=AbsI64(dx2); ady2=AbsI64(dy2); adz2=AbsI64(dz2);1125 1126 if (adx1>=ady1) {1127 if (adx1>=adz1)1128 d1=adx1;1129 else1130 d1=adz1;1131 } else {1132 if (ady1>=adz1)1133 d1=ady1;1134 else1135 d1=adz1;1136 }1137 if (adx2>=ady2) {1138 if (adx2>=adz2)1139 d2=adx2;1140 else1141 d2=adz2;1142 } else {1143 if (ady2>=adz2)1144 d2=ady2;1145 else1146 d2=adz2;1147 }1148 if (AbsI64(d1)!=w ||AbsI64(d2)!=h) {1149 d1<<=1;1150 d2<<=1;1151 }1152 if (d1) {1153 dx1=dx1<<32/d1;1154 dy1=dy1<<32/d1;1155 dz1=dz1<<32/d1;1156 } else1157 goto gr_done;1158 if (d2) {1159 dx2=dx2<<32/d2;1160 dy2=dy2<<32/d2;1161 dz2=dz2<<32/d2;1162 } else1163 goto gr_done;1164 dc->brush=NULL;1165 x=0;y=0;1166 dw=w<<32/d1;1167 dh=h<<32/d2;1168 1169 first=TRUE;1170 x1<<=32; y1<<=32; z1<<=32;1171 for (j=0;j<=d1;j++) {1172 x2=x1; y2=y1; z2=z1;1173 y=0;1174 for (i=0;i<=d2;i++) {1175 if (x2.i32[1]!=last_x || y2.i32[1]!=last_y || first) {1176 if ((color=GrPeek(img,x.i32[1],y.i32[1]))>=0) {1177 if (dc->color.c0.rop==ROPB_MONO) {1178 if (color) {1179 dc->color=old_color&~ROPF_DITHER;1180 if (dc->depth_buf) {1181 dc->db_z=z2.i32[1];1182 GrPlot1(dc,x2.i32[1],y2.i32[1]);1183 } else1184 GrPlot(dc,x2.i32[1],y2.i32[1]);1185 }1186 } else {1187 if (color!=TRANSPARENT) {1188 dc->color=old_color&~COLORROP_NO_ROP0_MASK|color;//COLOR1189 if (dc->depth_buf) {1190 dc->db_z=z2.i32[1];1191 GrPlot1(dc,x2.i32[1],y2.i32[1]);1192 } else1193 GrPlot(dc,x2.i32[1],y2.i32[1]);1194 }1195 }1196 }1197 }1198 first=FALSE;1199 last_x=x2.i32[1]; last_y=y2.i32[1];1200 x2+=dx2; y2+=dy2; z2+=dz2;