#include /* A fillpoly in C - for fun * Sed - start : Tue Sep 7 23:31:26 MET DST 1999 * Wed Sep 8 00:30:42 MET DST 1999 : all done, except the low stuff in * fill_left and fill_right and the dealing with colors in fill_lines * Wed Sep 8 00:58:03 MET DST 1999 : all cases dealed in fill_left except * the 12 harder (where x1!x2 and y1!=y2, which makes 4 combinations, each * of them giving 3 subcase (dx>dy or dx=dy or dx #include #include "device.h" #include "poly.h" #define abs(x) ((x)>0 ? (x) : (-(x))) static int miny, maxy; /* returns a*b/c in int 16:16 */ static inline int muldiv(int a, int b, int c) { #ifdef PC_ARCHI register int r; __asm__ volatile ("imul %2 \n" "idiv %3 \n" : "=a" (r) : "a" (a), "b" (b), "c" (c) : "eax", "ebx", "ecx", "edx" ); return r; #else double r, aa=a, bb=b, cc=c; r=aa*bb/cc; return r; #endif } /******************************************************* * fill_left * *******************************************************/ void fill_left(device *d, point *p1, point *p2) { /* lots of goto for lisibility (if if else if if else else is impossible to debug) */ register int x1=p1->x*65536., x2=p2->x*65536., y1=p1->y*65536., y2=p2->y*65536., dx, dy; register int xcur; register int xinc; register int i; register int y1i=(y1+65535)>>16, y2i=(y2+65535)>>16; /* in asm, those two subs are good for us, because we can test if x165535) goto x1_eq_x2_and_y1_inf_y2; /* here x1==x2 && y1==y2 */ if (y1i65535) goto x1_inf_x2_and_y1_inf_y2; /* x165535) goto x1_sup_x2_and_y1_inf_y2; /* x1>x2 && y1==y2 */ if (y1ix*65536., x2=p2->x*65536., y1=p1->y*65536., y2=p2->y*65536., dx, dy; register int xcur; register int xinc; register int i; register int y1i=(y1+65535)>>16, y2i=(y2+65535)>>16; /* in asm, those two subs are good for us, because we can test if x165535) goto x1_eq_x2_and_y1_inf_y2; /* here x1==x2 && y1==y2 */ if (y1i65535) goto x1_inf_x2_and_y1_inf_y2; /* x165535) goto x1_sup_x2_and_y1_inf_y2; /* x1>x2 && y1==y2 */ if (y2idepth==8) { register int i; #ifndef PC_ARCHI register int j; register unsigned char *q; #endif register unsigned char *p=d->buffer; device_line *cur_line=&the_lines[(int)miny]; register int col=thecol; p+=miny*SCREEN_X; for (i=miny; ix_left/65536)+1; register const int xright=cur_line->x_right/65536; q=p; q+=xleft; for (j=xleft; j<=xright /*cur_line->x_right*/; j++, q++) *q=col; #else __asm__ volatile ("movl %0, %%ebx \n" "movl %1, %%ecx \n" "shrl $16, %%ebx \n" "shrl $16, %%ecx \n" "incl %%ebx \n" "addl %%ebx, %%edi \n" "inc %%ecx \n" "subl %%ebx, %%ecx \n" "jbe 1f \n" "2: rep; stosb \n" "1: \n" : : "g" (cur_line->x_left), "g" (cur_line->x_right), "a" (col), "D" (p) : "ebx", "ecx", "eax", "edi" ); #endif } } else if (d->depth==16) { /* here 16bpp */ register int i; #ifndef PC_ARCHI register int j; register unsigned short *q; #endif register unsigned short *p=(unsigned short *)d->buffer; device_line *cur_line=&the_lines[(int)miny]; register int col=thecol; p+=miny*SCREEN_X; for (i=miny; ix_left/65536)+1; register const int xright=cur_line->x_right/65536; q=p; q+=xleft; for (j=xleft; j<=xright /*cur_line->x_right*/; j++, q++) *q=col; #else __asm__ volatile ("movl %0, %%ebx \n" "movl %1, %%ecx \n" "shrl $16, %%ebx \n" "shrl $16, %%ecx \n" "incl %%ebx \n" "addl %%ebx, %%edi \n" "addl %%ebx, %%edi \n" "inc %%ecx \n" "subl %%ebx, %%ecx \n" "jbe 1f \n" "2: rep; stosw \n" "1: \n" : : "g" (cur_line->x_left), "g" (cur_line->x_right), "a" (col), "D" (p) : "ebx", "ecx", "eax", "edi" ); #endif } } else if (d->depth==24) { register int i; register int j; register unsigned char *q; register unsigned char *p=(unsigned char *)d->buffer; device_line *cur_line=&the_lines[(int)miny]; register int col1=thecol&255; register int col2=(thecol>>8)&255; register int col3=thecol>>16; p+=miny*SCREEN_X*3; for (i=miny; ix_left/65536)+1; register const int xright=cur_line->x_right/65536; q=p; q+=xleft*3; for (j=xleft; j<=xright /*cur_line->x_right*/; j++, q++) { *q++=col1; *q++=col2; *q=col3; } } } else { /* here 32bpp */ register int i; #ifndef PC_ARCHI register int j; register unsigned int *q; #endif register unsigned int *p=(unsigned int *)d->buffer; device_line *cur_line=&the_lines[(int)miny]; register int col=thecol; p+=miny*SCREEN_X; for (i=miny; ix_left/65536)+1; register const int xright=cur_line->x_right/65536; q=p; q+=xleft; for (j=xleft; j<=xright /*cur_line->x_right*/; j++, q++) *q=col; #else __asm__ volatile ("movl %0, %%ebx \n" "movl %1, %%ecx \n" "shrl $16, %%ebx \n" "shrl $16, %%ecx \n" "incl %%ebx \n" "addl %%ebx, %%edi \n" "addl %%ebx, %%edi \n" "addl %%ebx, %%edi \n" "addl %%ebx, %%edi \n" "incl %%ecx \n" "subl %%ebx, %%ecx \n" "jbe 1f \n" "2: rep; stosl \n" "1: \n" : : "g" (cur_line->x_left), "g" (cur_line->x_right), "a" (col), "D" (p) : "ebx", "ecx", "eax", "edi" ); #endif } } } /* the poly is direct and clipped and convex */ #include void fillpoly(device *d, poly *p) { register int i; register point *q=&p->points[0], *r=&p->points[0]; register int nb=p->nb_points; register int tl=0, br=0; assert(p); assert(d); assert(p->nb_points>2); /* get top left and bottom right points */ miny=((int)(r[0].y*65536.)+65535)>>16; maxy=((int)(r[0].y*65536.)+32767)>>16; for (i=0; ix, q->y); */ if ((q->y < r[tl].y) || (q->y==r[tl].y && q->x < r[tl].x)) { tl=i; miny=((int)(r[i].y*65536.)+65535)>>16; } if ((q->y > r[br].y) || (q->y==r[br].y && q->x > r[br].x)) { br=i; maxy=((int)(r[i].y*65536.)+32767)>>16; } } /* fprintf(stderr, "top-left=%d bottom-right=%d\nminy=%d maxy=%d\n", tl, br, miny, maxy); */ /* draw left stuff */ if (br==tl) return; assert(br!=tl); if (br tl */ for (i=tl; i<=br-1; i++) { /* fprintf(stderr, "line p[%d] -> p[%d]\n", i, i+1); */ fill_left(d, &r[i], &r[i+1]); } } /* getchar(); */ /* draw right stuff */ if (br>tl) { for (i=br; icolor); }