diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-12-07 08:36:41 +0100 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-12-07 08:36:41 +0100 |
commit | a8531cec26bd6e3ea876ce6a01a35c21ee8e7d85 (patch) | |
tree | 3931c05338a37bf7d3daeebf79af70d2145fcccf /render | |
parent | f04ff9cf7f22f9a34f6e9ed1d8159fe67eb2c79d (diff) | |
download | mupdf-a8531cec26bd6e3ea876ce6a01a35c21ee8e7d85.tar.xz |
new mesh drawing code
Diffstat (limited to 'render')
-rw-r--r-- | render/imagedraw.c (renamed from render/optimage.c) | 0 | ||||
-rw-r--r-- | render/imagescale.c (renamed from render/optscale.c) | 0 | ||||
-rw-r--r-- | render/imageunpack.c (renamed from render/optunpack.c) | 0 | ||||
-rw-r--r-- | render/meshdraw.c | 388 | ||||
-rw-r--r-- | render/porterduff.c (renamed from render/optduff.c) | 0 | ||||
-rw-r--r-- | render/rastshade.c | 168 |
6 files changed, 388 insertions, 168 deletions
diff --git a/render/optimage.c b/render/imagedraw.c index 0654b006..0654b006 100644 --- a/render/optimage.c +++ b/render/imagedraw.c diff --git a/render/optscale.c b/render/imagescale.c index ede19f1c..ede19f1c 100644 --- a/render/optscale.c +++ b/render/imagescale.c diff --git a/render/optunpack.c b/render/imageunpack.c index 0885c293..0885c293 100644 --- a/render/optunpack.c +++ b/render/imageunpack.c diff --git a/render/meshdraw.c b/render/meshdraw.c new file mode 100644 index 00000000..92b0cb06 --- /dev/null +++ b/render/meshdraw.c @@ -0,0 +1,388 @@ +#include <fitz.h> + +/* + * polygon clipping + */ + +enum { IN, OUT, ENTER, LEAVE }; +enum { MAXV = 3 + 4 }; +enum { MAXN = 2 + FZ_MAXCOLORS }; + +typedef struct { float v[MAXV][MAXN]; } polygon; + +static inline float winding(float *a, float *b, float *c) +{ + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); +} + +static inline float sideline(float *v, float *a, float *b) +{ + return (a[1] - v[1]) * (b[0] - a[0]) - (a[0] - v[0]) * (b[1] - a[1]); +} + +static int clipline(float *c1, float *c2, float *v1, float *v2, int n) +{ + float a, b, c, d1, d2, t; + int v1o, v2o; + int i; + + /* cross */ + v1o = sideline(v1, c1, c2) > 1.0; + v2o = sideline(v2, c1, c2) > 1.0; + + if (v1o + v2o == 0) + return IN; + + if (v1o + v2o == 2) + return OUT; + + /* ax + by + c = 0 */ + a = (c2[1] - c1[1]); + b = (c1[0] - c2[0]); + c = (c2[0] * c1[1]) - (c1[0] * c2[1]); + + /* distance */ + d1 = fabs(a * v1[0] + b * v1[1] + c); + d2 = fabs(a * v2[0] + b * v2[1] + c); + + if (v2o) + { + t = d1 / (d1 + d2); + for (i = 0; i < n; i++) + v2[i] = v1[i] + t * (v2[i] - v1[i]); + return LEAVE; + } + + else + { + t = d2 / (d1 + d2); + for (i = 0; i < n; i++) + v1[i] = v2[i] + t * (v1[i] - v2[i]); + return ENTER; + } +} + +static inline void copyvert(float *dst, float *src, int n) +{ + while (n--) + *dst++ = *src++; +} + +static int clippoly(float *c1, float *c2, polygon *src, polygon *dst, int len, int n) +{ + float cv1[MAXN]; + float cv2[MAXN]; + int v1, v2, cp; + + v1 = len - 1; + cp = 0; + + for (v2 = 0; v2 < len; v2++) + { + copyvert(cv1, src->v[v1], n); + copyvert(cv2, src->v[v2], n); + switch (clipline(c1, c2, cv1, cv2, n)) + { + case IN: + copyvert(dst->v[cp++], cv2, n); + break; + case OUT: + break; + case LEAVE: + copyvert(dst->v[cp++], cv2, n); + break; + case ENTER: + copyvert(dst->v[cp++], cv1, n); + copyvert(dst->v[cp++], cv2, n); + break; + } + v1 = v2; + } + + return cp; +} + +/* + * gouraud shaded polygon scan conversion + */ + +static inline void +drawscan(fz_pixmap *pix, int y, int x1, int x2, int *v1, int *v2, int n) +{ + unsigned char *p = pix->samples + ((y - pix->y) * pix->w + (x1 - pix->x)) * pix->n; + int v[FZ_MAXCOLORS]; + int dv[FZ_MAXCOLORS]; + int w = x2 - x1; + int k; + + for (k = 0; k < n; k++) + { + v[k] = v1[k]; + dv[k] = (v2[k] - v1[k]) / w; + } + + while (w--) + { + *p++ = 255; + for (k = 0; k < n; k++) + { + *p++ = v[k] >> 16; + v[k] += dv[k]; + } + } +} + +void +fz_drawtriangle(fz_pixmap *pix, float *av, float *bv, float *cv, int n) +{ + int i, k; + polygon poly; + polygon temp; + float clip[4][2]; + int vert[MAXV][MAXN]; + int len; + + int top, bot; + int sv1, sv2; + int ev1, ev2; + + int y, diffy1, diffy2; + int x1, x2, dx1, dx2; + int v1[MAXN], d1[MAXN]; + int v2[MAXN], d2[MAXN]; + + /* + * Round coords and correct winding order + */ + + av[0] = fz_floor(av[0]); + av[1] = fz_floor(av[1]); + bv[0] = fz_floor(bv[0]); + bv[1] = fz_floor(bv[1]); + cv[0] = fz_floor(cv[0]); + cv[1] = fz_floor(cv[1]); + + if (winding(av, bv, cv) > 0) + for (i = 0; i < n; i++) + { + poly.v[0][i] = av[i]; + poly.v[1][i] = bv[i]; + poly.v[2][i] = cv[i]; + } + else + for (i = 0; i < n; i++) + { + poly.v[0][i] = av[i]; + poly.v[1][i] = cv[i]; + poly.v[2][i] = bv[i]; + } + + /* + * Clip triangle + */ + + clip[0][0] = pix->x; + clip[0][1] = pix->y; + + clip[1][0] = pix->x + pix->w; + clip[1][1] = pix->y; + + clip[2][0] = pix->x + pix->w; + clip[2][1] = pix->y + pix->h; + + clip[3][0] = pix->x; + clip[3][1] = pix->y + pix->h; + + len = clippoly(clip[0], clip[1], &poly, &temp, 3, n); + len = clippoly(clip[1], clip[2], &temp, &poly, len, n); + len = clippoly(clip[2], clip[3], &poly, &temp, len, n); + len = clippoly(clip[3], clip[0], &temp, &poly, len, n); + + if (len < 3) + return; + + /* + * Init scan conversion + */ + + for (i = 0; i < len; i++) + { + vert[i][0] = poly.v[i][0]; + vert[i][1] = poly.v[i][1]; + for (k = 2; k < n; k++) + vert[i][k] = poly.v[i][k] * 65536; + } + + top = bot = 0; + for (i = 0; i < len; i++) + { + if (vert[i][1] < vert[top][1]) + top = i; + if (vert[i][1] > vert[bot][1]) + bot = i; + } + + y = vert[top][1]; + sv1 = ev1 = top; + sv2 = ev2 = top; + + x1 = x2 = dx1 = dx2 = 0; /* silence compiler */ + + goto start; + + /* + * Loopetyloop + */ + + while (sv1 != bot && sv2 != bot) + { + drawscan(pix, y, x1 >> 16, x2 >> 16, v1+2, v2+2, n-2); + + y += 1; + x1 += dx1; + x2 += dx2; + for (k = 2; k < n; k++) + { + v1[k] += d1[k]; + v2[k] += d2[k]; + } + +start: + + while (y >= vert[ev1][1] && sv1 != bot) + { + sv1 = ev1; + ev1 = sv1 == 0 ? len - 1 : sv1 - 1; + + diffy1 = vert[ev1][1] - vert[sv1][1]; + if (diffy1 == 0) + continue; + + x1 = vert[sv1][0] << 16; + dx1 = ((vert[ev1][0] - vert[sv1][0]) << 16) / diffy1; + + for (k = 2; k < n; k++) + { + v1[k] = vert[sv1][k]; + d1[k] = (vert[ev1][k] - vert[sv1][k]) / diffy1; + } + } + + while (y >= vert[ev2][1] && sv2 != bot) + { + sv2 = ev2; + ev2 = sv2 == len - 1 ? 0 : sv2 + 1; + + diffy2 = vert[ev2][1] - vert[sv2][1]; + if (diffy2 == 0) + continue; + + x2 = vert[sv2][0] << 16; + dx2 = ((vert[ev2][0] - vert[sv2][0]) << 16) / diffy2; + + for (k = 2; k < n; k++) + { + v2[k] = vert[sv2][k]; + d2[k] = (vert[ev2][k] - vert[sv2][k]) / diffy2; + } + } + } +} + +/* + * mesh drawing + */ + +fz_error * +fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_colorspace *destcs, fz_pixmap *dest) +{ + unsigned char clut[256][3]; + unsigned char *s, *d; + fz_error *error; + fz_pixmap *temp; + float rgb[3]; + float tri[3][MAXN]; + fz_point p; + int i, j, k, n; + + assert(dest->n == 4); + + ctm = fz_concat(shade->matrix, ctm); + + if (shade->usefunction) + { +printf("draw function mesh\n"); + n = 3; + error = fz_newpixmap(&temp, dest->x, dest->y, dest->w, dest->h, 2); + if (error) + return error; + } + else if (shade->colorspace != destcs) + { +printf("draw colorspace mesh\n"); + n = 2 + shade->colorspace->n; + error = fz_newpixmap(&temp, dest->x, dest->y, dest->w, dest->h, + shade->colorspace->n + 1); + if (error) + return error; + } + else + { +printf("draw direct mesh\n"); + n = 2 + shade->colorspace->n; + temp = dest; + } + + fz_clearpixmap(temp); + + for (i = 0; i < shade->meshlen; i++) + { + for (k = 0; k < 3; k++) + { + p.x = shade->mesh[(i * 3 + k) * n + 0]; + p.y = shade->mesh[(i * 3 + k) * n + 1]; + p = fz_transformpoint(ctm, p); + tri[k][0] = p.x; + tri[k][1] = p.y; + for (j = 2; j < n; j++) + tri[k][j] = shade->mesh[( i * 3 + k) * n + j] * 255; + } + fz_drawtriangle(temp, tri[0], tri[1], tri[2], n); + } + + if (shade->usefunction) + { + for (int i = 0; i < 256; i++) + { + fz_convertcolor(shade->colorspace, shade->function[i], destcs, rgb); + clut[i][0] = rgb[0] * 255; + clut[i][1] = rgb[1] * 255; + clut[i][2] = rgb[2] * 255; + } + + n = temp->w * temp->h; + s = temp->samples; + d = dest->samples; + + while (n--) + { + d[0] = s[0]; + d[1] = fz_mul255(s[0], clut[s[1]][0]); + d[2] = fz_mul255(s[0], clut[s[1]][1]); + d[3] = fz_mul255(s[0], clut[s[1]][2]); + s += 2; + d += 4; + } + + fz_droppixmap(temp); + } + + else if (shade->colorspace != destcs) + { + fz_convertpixmap(shade->colorspace, temp, destcs, dest); + fz_droppixmap(temp); + } + + return nil; +} + diff --git a/render/optduff.c b/render/porterduff.c index 9cd99dbb..9cd99dbb 100644 --- a/render/optduff.c +++ b/render/porterduff.c diff --git a/render/rastshade.c b/render/rastshade.c deleted file mode 100644 index b002de82..00000000 --- a/render/rastshade.c +++ /dev/null @@ -1,168 +0,0 @@ -#include <fitz.h> - -typedef struct fz_vertex -{ - float x, y; - float l; -} fz_vertex; - -typedef struct fz_triangle -{ - fz_vertex vertex[3]; -} fz_triangle; - -#define putpixel(x, y, c) \ - if (x >= 0 && x < dstp->w && y >= 0 && y < dstp->h) { \ - dstp->samples[((x)+(y)*(dstp->w))*4+0] = 255; \ - dstp->samples[((x)+(y)*(dstp->w))*4+1] = c[0]; \ - dstp->samples[((x)+(y)*(dstp->w))*4+2] = c[1]; \ - dstp->samples[((x)+(y)*(dstp->w))*4+3] = c[2]; \ - } \ - -void fz_swapvertex(fz_vertex *a, fz_vertex *b) -{ - fz_vertex temp; - temp = *a; - *a = *b; - *b = temp; -} - -fz_error * -fz_drawgouraudtriangle(fz_triangle triangle, fz_pixmap *dstp, int destcol[512][4], - int bx0, int by0, int bx1, int by1) -{ - fz_error *error; - fz_vertex a, b, c; - - a = triangle.vertex[0]; - b = triangle.vertex[1]; - c = triangle.vertex[2]; - - /* need more accurate clipping method */ - { - fz_rect bb1; - fz_rect bb2; - - bb1.min.x = MIN(MIN(a.x, b.x), c.x); - bb1.min.y = MIN(MIN(a.y, b.y), c.y); - bb1.max.x = MAX(MAX(a.x, b.x), c.x); - bb1.max.y = MAX(MAX(a.y, b.y), c.y); - - bb2.min.x = bx0; - bb2.min.y = by0; - bb2.max.x = bx1; - bb2.max.y = by1; - - if (fz_isemptyrect(fz_intersectrects(bb1, bb2))) - return nil; - } - - if(a.y > b.y) fz_swapvertex(&a, &b); - if(a.y > c.y) fz_swapvertex(&a, &c); - if(b.y > c.y) fz_swapvertex(&b, &c); - - float diff_y = (b.y - a.y); - float slopeab_x = (b.x - a.x) / diff_y; - float slopeab_l = (b.l - a.l) / diff_y; - float xab = a.x; - float lab = a.l; - diff_y = (c.y - a.y); - float slopeac_x = (c.x - a.x) / diff_y; - float slopeac_l = (c.l - a.l) / diff_y; - float xac = a.x; - float lac = a.l; - int maxy = (int)(b.y); - - int incx; - int y; - for(y = (int)(a.y); y < maxy; y++) - { - int maxx = (int)(xac); - if(xab < xac) incx = 1; - else incx = -1; - float diff_x = (xac - xab) * incx; - float slope_l = (lac - lab) / diff_x; - float l = lab; - - for(int x = (int)(xab); x != maxx+incx; x += incx) - { - if (l < 0) l = 0; - if (l > 511) l = 511; - putpixel(x, y, destcol[(int)(l)]); - l += slope_l; - } - - xab += slopeab_x; - lab += slopeab_l; - xac += slopeac_x; - lac += slopeac_l; - } - - diff_y = (c.y - b.y); - float slopebc_x = (c.x - b.x) / diff_y; - float slopebc_l = (c.l - b.l) / diff_y; - float xbc = b.x; - float lbc = b.l; - maxy = (int)(c.y); - for(; y < maxy; y++) - { - int maxx = (int)(xac); - if(xbc < xac) incx = 1; - else incx = -1; - float diff_x = (xac - xbc) * incx; - float slope_l = (lac - lbc) / diff_x; - float l = lbc; - for(int x = (int)(xbc); x != maxx+incx; x += incx) - { - if (l < 0) l = 0; - if (l > 511) l = 511; - putpixel(x, y, destcol[(int)(l)]); - l += slope_l; - } - - xac += slopeac_x; - lac += slopeac_l; - xbc += slopebc_x; - lbc += slopebc_l; - } - - return nil; -} - -fz_error * -fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_colorspace *dsts, fz_pixmap *dstp) -{ - int x, y; - fz_triangle triangle; - fz_point point; - int destcol[512][4]; - - for (int i=0; i<512; ++i) { - float col[4]; - shade->colorspace->convcolor(shade->colorspace, - shade->function[i], dsts, col); - for (int j=0; j<3; ++j) { - destcol[i][j] = col[j] * 255; - } - } - - if (!shade) return nil; - - ctm = fz_concat(shade->matrix, ctm); - ctm = fz_concat(ctm, fz_translate(-dstp->x, -dstp->y)); - - int ncomp = shade->meshcap; - for (int i=0; i<shade->meshlen; ++i) { - for (int j=0; j<3; ++j) { - point.x = shade->mesh[(i*3+j)*3+0]; - point.y = shade->mesh[(i*3+j)*3+1]; - point = fz_transformpoint(ctm, point); - triangle.vertex[j].x = point.x; - triangle.vertex[j].y = point.y; - triangle.vertex[j].l = shade->mesh[(i*3+j)*3+2]; - } - fz_drawgouraudtriangle(triangle, dstp, destcol, 0, 0, dstp->w, dstp->h); - } - - return nil; -} |