static void fz_drawtriangle(fz_pixmap *pix, float *av, float *bv, float *cv, int n) { float poly[MAXV][MAXN]; float temp[MAXV][MAXN]; float cx0 = pix->x; float cy0 = pix->y; float cx1 = pix->x + pix->w; float cy1 = pix->y + pix->h; int gel[MAXV][MAXN]; int ael[2][MAXN]; int del[2][MAXN]; int y, s0, s1, e0, e1; int top, bot, len; int i, k; copyvert(poly[0], av, n); copyvert(poly[1], bv, n); copyvert(poly[2], cv, n); len = clippoly(poly, temp, 3, n, cx0, 0, 0); len = clippoly(temp, poly, len, n, cx1, 0, 1); len = clippoly(poly, temp, len, n, cy0, 1, 0); len = clippoly(temp, poly, len, n, cy1, 1, 1); if (len < 3) return; for (i = 0; i < len; i++) { gel[i][0] = fz_floor(poly[i][0] + 0.5) * 65536; /* trunc and fix */ gel[i][1] = fz_floor(poly[i][1] + 0.5); /* y is not fixpoint */ for (k = 2; k < n; k++) gel[i][k] = poly[i][k] * 65536; /* fix with precision */ } top = bot = 0; for (i = 0; i < len; i++) { if (gel[i][1] < gel[top][1]) top = i; if (gel[i][1] > gel[bot][1]) bot = i; } if (gel[bot][1] - gel[top][1] == 0) return; y = gel[top][1]; if (findnext(gel, len, top, &s0, &e0, 1)) return; if (findnext(gel, len, top, &s1, &e1, -1)) return; loadedge(gel, s0, e0, ael[0], del[0], n); loadedge(gel, s1, e1, ael[1], del[1], n); while (1) { int x0 = ael[0][0] >> 16; int x1 = ael[1][0] >> 16; if (ael[0][0] < ael[1][0]) drawscan(pix, y, x0, x1, ael[0]+2, ael[1]+2, n-2); else drawscan(pix, y, x1, x0, ael[1]+2, ael[0]+2, n-2); stepedge(ael[0], del[0], n); stepedge(ael[1], del[1], n); y ++; if (y >= gel[e0][1]) { if (findnext(gel, len, e0, &s0, &e0, 1)) return; loadedge(gel, s0, e0, ael[0], del[0], n); } if (y >= gel[e1][1]) { if (findnext(gel, len, e1, &s1, &e1, -1)) return; loadedge(gel, s1, e1, ael[1], del[1], n); } } }
LOCAL void fbp_drawtriangle(struct rfb_Display *mod, struct rfb_Window *v, TINT x0, TINT y0, TINT x1, TINT y1, TINT x2, TINT y2, struct rfb_Pen *pen) { struct Coord res[MAX_VERT]; TINT outlen; struct Region R; if (!rfb_getlayermask(mod, &R, v->rfbw_ClipRect.r, v, 0, 0)) return; TUINT p = pixconv_rgbfmt(v->rfbw_PixBuf.tpb_Format, pen->rgb); struct TNode *next, *node = R.rg_Rects.rl_List.tlh_Head.tln_Succ; for (; (next = node->tln_Succ); node = next) { struct RectNode *rn = (struct RectNode *) node; TINT *r = rn->rn_Rect; if (!clippoly(res, &outlen, x0, y0, x1, y1, x2, y2, r[0], r[1], r[2], r[3])) continue; TINT d[4]; if (outlen == 1) { d[0] = res[0].x; d[1] = res[0].y; d[2] = res[0].x; d[3] = res[0].y; rfb_markdirty(mod, v, d); pixconv_setpixelbuf(&v->rfbw_PixBuf, res[0].x, res[0].y, p); } else if (outlen == 2) { TINT rect[4] = { res[0].x, res[0].y, res[1].x, res[1].y }; rfb_markdirty(mod, v, rect); fbp_drawline(mod, v, rect, pen); } else { TINT i; d[0] = TMIN(TMIN(res[0].x, res[1].x), res[2].x); d[1] = TMIN(TMIN(res[0].y, res[1].y), res[2].y); d[2] = TMAX(TMAX(res[0].x, res[1].x), res[2].x); d[3] = TMAX(TMAX(res[0].y, res[1].y), res[2].y); rfb_markdirty(mod, v, d); rendertriangle(v, res[0], res[1], res[2], p); for (i = 2; i < outlen; i++) { if ((i + 1) < outlen) rendertriangle(v, res[0], res[i], res[i + 1], p); } } } region_free(&mod->rfb_RectPool, &R); }