extern int finite(double); /* undef'ing this makes things look a bit nicer, but slower */ #define DBL_PIXELS void NAME(fzort_ctx *ctx, struct pvertex *v1, struct pvertex *v2, struct pvertex *v3) { long x_left, x_right, dxdy_left, dxdy_right; struct pvertex *v_min, *v_mid, *v_max; struct edge e_maj, e_top, e_bot, *e_left, *e_right; float area, inv_area, bf = 1.f; long dudy, dudy_left, u_left; long dvdy, dvdy_left, v_left; int sub_tri, left_to_right, y, lines; int xa, xb, adjx; PIXEL_TYPE *scanline_ptr; PIXEL_TYPE *texture_ptr; register int l; register long u, v, dudx, dvdx; #if (defined DBL_PIXELS) && !(defined MONOCHROME) register PIXEL_TYPE t; register long dudx2, dvdx2, dudx4, dvdx4; #endif register PIXEL_TYPE *pixel_ptr; #ifdef MONOCHROME register unsigned int mask, bits; register unsigned int *dither_ptr; #endif texture_ptr = (PIXEL_TYPE *)ctx->texture; if (v1->y_scr <= v2->y_scr) { if (v2->y_scr <= v3->y_scr) { v_min = v1; v_mid = v2; v_max = v3; } else if (v3->y_scr <= v1->y_scr) { v_min = v3; v_mid = v1; v_max = v2; } else { v_min = v1; v_mid = v3; v_max = v2; bf = -bf; } } else { if (v1->y_scr <= v3->y_scr) { v_min = v2; v_mid = v1; v_max = v3; bf = -bf; } else if (v3->y_scr <= v2->y_scr) { v_min = v3; v_mid = v2; v_max = v1; bf = -bf; } else { v_min = v2; v_mid = v3; v_max = v1; } } area = (v_max->x_scr - v_min->x_scr)*(v_mid->y_scr - v_min->y_scr) - (v_mid->x_scr - v_min->x_scr)*(v_max->y_scr - v_min->y_scr); if (!finite(area) || area == 0.) return; if (area*bf < 0.) return; init_edge(ctx, &e_maj, v_min, v_max); if (e_maj.lines == 0) return; init_edge(ctx, &e_top, v_mid, v_max); init_edge(ctx, &e_bot, v_min, v_mid); left_to_right = area < 0.; /* inter edge is to the left */ inv_area = 1./area; dudx = (long) (inv_area*(e_maj.du*e_bot.dy - e_maj.dy*e_bot.du)); dudy = (long) (inv_area*(e_maj.dx*e_bot.du - e_maj.du*e_bot.dx)); dvdx = (long) (inv_area*(e_maj.dv*e_bot.dy - e_maj.dy*e_bot.dv)); dvdy = (long) (inv_area*(e_maj.dx*e_bot.dv - e_maj.dv*e_bot.dx)); #if (defined DBL_PIXELS) && !(defined MONOCHROME) dudx2 = dudx*2; dvdx2 = dvdx*2; dudx4 = dudx2*2; dvdx4 = dvdx2*2; #endif x_left = x_right = dxdy_left = dxdy_right = 0; /* shut up compiler */ u_left = dudy_left = v_left = dvdy_left = 0; for (sub_tri = 0; sub_tri <= 1; sub_tri++) { if (sub_tri == 0) { if (left_to_right) { e_left = &e_maj; e_right = &e_bot; lines = e_right->lines; } else { e_left = &e_bot; e_right = &e_maj; lines = e_left->lines; } x_left = e_left->sx; dxdy_left = e_left->dxdy; x_right = e_right->sx; dxdy_right = e_right->dxdy; dudy_left = fp_mul(dxdy_left, dudx) + dudy; u_left = v_min->u_txt; dvdy_left = fp_mul(dxdy_left, dvdx) + dvdy; v_left = v_min->v_txt; if (e_left->adjy) { u_left += e_left->adjy*dudy_left; v_left += e_left->adjy*dvdy_left; } y = e_left->sy; } else { if (left_to_right) { e_right = &e_top; lines = e_right->lines; y = e_right->sy; x_right = e_right->sx; dxdy_right = e_right->dxdy; } else { e_left = &e_top; lines = e_left->lines; y = e_left->sy; x_left = e_left->sx; dxdy_left = e_left->dxdy; dudy_left = fp_mul(dxdy_left, dudx) + dudy; u_left = v_mid->u_txt; dvdy_left = fp_mul(dxdy_left, dvdx) + dvdy; v_left = v_mid->v_txt; if (e_left->adjy) { u_left += e_left->adjy*dudy_left; v_left += e_left->adjy*dvdy_left; } } } if (lines > 0) { scanline_ptr = (PIXEL_TYPE *)((unsigned char *)ctx->raster.bits + y*ctx->raster.pitch); while (lines--) { xa = FP_ICEIL(x_left); xb = FP_IFLOOR(x_right); if (xa < ctx->clip.x_min) { adjx = ctx->clip.x_min - xa; xa = ctx->clip.x_min; } else { adjx = 0; } if (xb > ctx->clip.x_max) { xb = ctx->clip.x_max; } if (xb >= ctx->clip.x_min && xa <= xb) { u = u_left; v = v_left; if (adjx) { u += dudx*adjx; v += dvdx*adjx; } #ifdef MONOCHROME pixel_ptr = scanline_ptr + (xa>>3); dither_ptr = &dither6[y&7][xa&7]; #ifdef LSB_TO_MSB mask = 1 << (xa&7); #else mask = 1 << (7 - (xa&7)); #endif #else pixel_ptr = scanline_ptr + xa; #endif l = 1 + xb - xa; #define TEXTURE_PIXEL texture_ptr[(FP_TO_INT(v)&(TEXTURE_SIZE - 1)) + \ (FP_TO_INT(u)&(TEXTURE_SIZE - 1))*TEXTURE_SIZE] #ifdef MONOCHROME bits = *pixel_ptr; while (l--) { if ((TEXTURE_PIXEL>>2) > *dither_ptr++) bits |= mask; else bits &= ~mask; #ifdef LSB_TO_MSB if ((mask <<= 1) == (1<<8)) { #else if (!(mask >>= 1)) { #endif *pixel_ptr++ = bits; bits = *pixel_ptr; dither_ptr -= 8; #ifdef LSB_TO_MSB mask = 1; #else mask = 1<<7; #endif } u += dudx; v += dvdx; } *pixel_ptr = bits; #else if (l & 1) { *pixel_ptr++ = TEXTURE_PIXEL; u += dudx; v += dvdx; } l >>= 1; if (l & 1) { #ifdef DBL_PIXELS t = TEXTURE_PIXEL; pixel_ptr[0] = t; pixel_ptr[1] = t; pixel_ptr += 2; u += dudx2; v += dvdx2; #else *pixel_ptr++ = TEXTURE_PIXEL; u += dudx; v += dvdx; *pixel_ptr++ = TEXTURE_PIXEL; u += dudx; v += dvdx; #endif } l >>= 1; while (l--) { #ifdef DBL_PIXELS t = TEXTURE_PIXEL; pixel_ptr[0] = t; pixel_ptr[1] = t; pixel_ptr[2] = t; pixel_ptr[3] = t; pixel_ptr += 4; u += dudx4; v += dvdx4; #else *pixel_ptr++ = TEXTURE_PIXEL; u += dudx; v += dvdx; *pixel_ptr++ = TEXTURE_PIXEL; u += dudx; v += dvdx; *pixel_ptr++ = TEXTURE_PIXEL; u += dudx; v += dvdx; *pixel_ptr++ = TEXTURE_PIXEL; u += dudx; v += dvdx; #endif } #endif /* MONOCHROME */ #undef TEXTURE_PIXEL } scanline_ptr += ctx->raster.pitch/sizeof(*scanline_ptr); x_left += dxdy_left; x_right += dxdy_right; u_left += dudy_left; v_left += dvdy_left; y++; } } } } #undef LSB_TO_MSB #undef MONOCHROME #undef FILL_SCANLINE #undef PIXEL_TYPE #undef NAME