From dac0181028f2e02f44dd258e91d2df66975c3b89 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 29 Dec 2010 01:52:21 +0000 Subject: Support linear shadings as a special case in the fitz shading struct and renderer. --- draw/meshdraw.c | 141 ++++++++++++++++++++++++++++++++++++++++++++---------- fitz/fitz.h | 10 ++++ fitz/res_shade.c | 12 +++++ mupdf/pdf_shade.c | 54 ++++++--------------- 4 files changed, 153 insertions(+), 64 deletions(-) diff --git a/draw/meshdraw.c b/draw/meshdraw.c index 74035cfd..df4dfe41 100644 --- a/draw/meshdraw.c +++ b/draw/meshdraw.c @@ -310,39 +310,90 @@ fz_drawtriangle(fz_pixmap *pix, float *av, float *bv, float *cv, int n, fz_bbox * mesh drawing */ -void -fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) +#define HUGENUM 32000 + +static void +fz_renderlinear(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) +{ + float v[4][3]; + float e[2][3]; + fz_point p0, p1; + float theta; + + p0.x = shade->mesh[0]; + p0.y = shade->mesh[1]; + p0 = fz_transformpoint(ctm, p0); + + p1.x = shade->mesh[3]; + p1.y = shade->mesh[4]; + p1 = fz_transformpoint(ctm, p1); + + theta = atan2f(p1.y - p0.y, p1.x - p0.x); + theta += (float)M_PI * 0.5f; + + v[0][0] = p0.x + HUGENUM * cosf(theta); + v[0][1] = p0.y + HUGENUM * sinf(theta); + v[0][2] = 0; + + v[1][0] = p1.x + HUGENUM * cosf(theta); + v[1][1] = p1.y + HUGENUM * sinf(theta); + v[1][2] = 255; + + v[2][0] = p0.x - HUGENUM * cosf(theta); + v[2][1] = p0.y - HUGENUM * sinf(theta); + v[2][2] = 0; + + v[3][0] = p1.x - HUGENUM * cosf(theta); + v[3][1] = p1.y - HUGENUM * sinf(theta); + v[3][2] = 255; + + fz_drawtriangle(dest, v[0], v[1], v[2], 3, bbox); + fz_drawtriangle(dest, v[1], v[2], v[3], 3, bbox); + + if (shade->extend[0]) + { + e[0][0] = v[0][0] - (p1.x - p0.x) * HUGENUM; + e[0][1] = v[0][1] - (p1.y - p0.y) * HUGENUM; + e[0][2] = v[0][2]; + + e[1][0] = v[2][0] - (p1.x - p0.x) * HUGENUM; + e[1][1] = v[2][1] - (p1.y - p0.y) * HUGENUM; + e[1][2] = v[2][2]; + + fz_drawtriangle(dest, e[0], v[0], v[2], 3, bbox); + fz_drawtriangle(dest, e[0], v[2], e[1], 3, bbox); + } + + if (shade->extend[1]) + { + e[0][0] = v[1][0] + (p1.x - p0.x) * HUGENUM; + e[0][1] = v[1][1] + (p1.y - p0.y) * HUGENUM; + e[0][2] = v[1][2]; + + e[1][0] = v[3][0] + (p1.x - p0.x) * HUGENUM; + e[1][1] = v[3][1] + (p1.y - p0.y) * HUGENUM; + e[1][2] = v[3][2]; + + fz_drawtriangle(dest, e[0], v[1], v[3], 3, bbox); + fz_drawtriangle(dest, e[0], v[3], e[1], 3, bbox); + } +} + +static void +fz_rendermesh(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) { - unsigned char clut[256][FZ_MAXCOLORS]; - fz_pixmap *temp, *conv; - float color[FZ_MAXCOLORS]; float tri[3][MAXN]; fz_point p; float *mesh; int ntris; - int i, j, k; + int i, k; - ctm = fz_concat(shade->matrix, ctm); mesh = shade->mesh; if (shade->usefunction) - { - for (i = 0; i < 256; i++) - { - fz_convertcolor(shade->cs, shade->function[i], dest->colorspace, color); - for (k = 0; k < dest->colorspace->n; k++) - clut[i][k] = color[k] * 255; - } - conv = fz_newpixmapwithrect(dest->colorspace, bbox); - temp = fz_newpixmapwithrect(fz_devicegray, bbox); - fz_clearpixmap(temp); ntris = shade->meshlen / 9; - } else - { - temp = dest; ntris = shade->meshlen / ((2 + shade->cs->n) * 3); - } while (ntris--) { @@ -357,13 +408,52 @@ fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) tri[k][2] = *mesh++ * 255; else { - fz_convertcolor(shade->cs, mesh, temp->colorspace, tri[k] + 2); - for (j = 0; j < temp->colorspace->n; j++) - tri[k][j + 2] *= 255; + fz_convertcolor(shade->cs, mesh, dest->colorspace, tri[k] + 2); + for (i = 0; i < dest->colorspace->n; i++) + tri[k][i + 2] *= 255; mesh += shade->cs->n; } } - fz_drawtriangle(temp, tri[0], tri[1], tri[2], 2 + temp->colorspace->n, bbox); + fz_drawtriangle(dest, tri[0], tri[1], tri[2], 2 + dest->colorspace->n, bbox); + } +} + +void +fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) +{ + unsigned char clut[256][FZ_MAXCOLORS]; + fz_pixmap *temp, *conv; + float color[FZ_MAXCOLORS]; + int i, k; + + ctm = fz_concat(shade->matrix, ctm); + + if (shade->usefunction) + { + for (i = 0; i < 256; i++) + { + fz_convertcolor(shade->cs, shade->function[i], dest->colorspace, color); + for (k = 0; k < dest->colorspace->n; k++) + clut[i][k] = color[k] * 255; + } + conv = fz_newpixmapwithrect(dest->colorspace, bbox); + temp = fz_newpixmapwithrect(fz_devicegray, bbox); + fz_clearpixmap(temp); + } + else + { + temp = dest; + } + + switch (shade->type) + { + case FZ_LINEAR: + fz_renderlinear(shade, ctm, temp, bbox); + break; + /* TODO: FZ_RADIAL */ + case FZ_MESH: + fz_rendermesh(shade, ctm, temp, bbox); + break; } if (shade->usefunction) @@ -384,3 +474,4 @@ fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) fz_droppixmap(temp); } } + diff --git a/fitz/fitz.h b/fitz/fitz.h index 99751b3e..3275dc4e 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -795,6 +795,13 @@ fz_text *fz_clonetext(fz_text *old); * The shading code uses gouraud shaded triangle meshes. */ +enum +{ + FZ_LINEAR, + FZ_RADIAL, + FZ_MESH, +}; + typedef struct fz_shade_s fz_shade; struct fz_shade_s @@ -811,6 +818,9 @@ struct fz_shade_s int usefunction; float function[256][FZ_MAXCOLORS]; + int type; /* linear, radial, mesh */ + int extend[2]; + int meshlen; int meshcap; float *mesh; /* [x y t] or [x y c1 ... cn] */ diff --git a/fitz/res_shade.c b/fitz/res_shade.c index 30d2bd16..d6108236 100644 --- a/fitz/res_shade.c +++ b/fitz/res_shade.c @@ -32,6 +32,11 @@ fz_boundshade(fz_shade *shade, fz_matrix ctm) nvert = shade->meshlen / ncomp; v = shade->mesh; + if (shade->type == FZ_LINEAR) + return fz_infiniterect; + if (shade->type == FZ_RADIAL) + return fz_infiniterect; + if (nvert == 0) return fz_emptyrect; @@ -66,6 +71,13 @@ fz_debugshade(fz_shade *shade) printf("shading {\n"); + switch (shade->type) + { + case FZ_LINEAR: printf("\ttype linear\n"); break; + case FZ_RADIAL: printf("\ttype radial\n"); break; + case FZ_MESH: printf("\ttype mesh\n"); break; + } + printf("\tbbox [%g %g %g %g]\n", shade->bbox.x0, shade->bbox.y0, shade->bbox.x1, shade->bbox.y1); diff --git a/mupdf/pdf_shade.c b/mupdf/pdf_shade.c index 1b55356d..caa0b98e 100644 --- a/mupdf/pdf_shade.c +++ b/mupdf/pdf_shade.c @@ -461,10 +461,8 @@ pdf_loadaxialshading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, p fz_obj *obj; float d0, d1; int e0, e1; - struct vertex p1, p2, p3, p4; - struct vertex ep1, ep2, ep3, ep4; float x0, y0, x1, y1; - float theta; + struct vertex p1, p2; pdf_logshade("load type2 (axial) shading\n"); @@ -497,45 +495,20 @@ pdf_loadaxialshading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, p if (error) return fz_rethrow(error, "unable to sample shading function"); - theta = atan2f(y1 - y0, x1 - x0); - theta += (float)M_PI * 0.5f; + shade->type = FZ_LINEAR; - p1.x = x0 + HUGENUM * cosf(theta); - p1.y = y0 + HUGENUM * sinf(theta); - p1.c[0] = 0; - p2.x = x1 + HUGENUM * cosf(theta); - p2.y = y1 + HUGENUM * sinf(theta); - p2.c[0] = 1; - p3.x = x0 - HUGENUM * cosf(theta); - p3.y = y0 - HUGENUM * sinf(theta); - p3.c[0] = 0; - p4.x = x1 - HUGENUM * cosf(theta); - p4.y = y1 - HUGENUM * sinf(theta); - p4.c[0] = 1; - - pdf_addquad(shade, &p1, &p2, &p4, &p3); + shade->extend[0] = e0; + shade->extend[1] = e1; - if (e0) - { - ep1.x = p1.x - (x1 - x0) * HUGENUM; - ep1.y = p1.y - (y1 - y0) * HUGENUM; - ep1.c[0] = 0; - ep3.x = p3.x - (x1 - x0) * HUGENUM; - ep3.y = p3.y - (y1 - y0) * HUGENUM; - ep3.c[0] = 0; - pdf_addquad(shade, &ep1, &p1, &p3, &ep3); - } + p1.x = x0; + p1.y = y0; + p1.c[0] = 0; + pdf_addvertex(shade, &p1); - if (e1) - { - ep2.x = p2.x + (x1 - x0) * HUGENUM; - ep2.y = p2.y + (y1 - y0) * HUGENUM; - ep2.c[0] = 1; - ep4.x = p4.x + (x1 - x0) * HUGENUM; - ep4.y = p4.y + (y1 - y0) * HUGENUM; - ep4.c[0] = 1; - pdf_addquad(shade, &p2, &ep2, &ep4, &p4); - } + p2.x = x1; + p2.y = y1; + p2.c[0] = 1; + pdf_addvertex(shade, &p2); return fz_okay; } @@ -1146,10 +1119,13 @@ pdf_loadshadingdict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_matrix t shade = fz_malloc(sizeof(fz_shade)); shade->refs = 1; + shade->type = FZ_MESH; shade->usebackground = 0; shade->usefunction = 0; shade->matrix = transform; shade->bbox = fz_infiniterect; + shade->extend[0] = 0; + shade->extend[1] = 0; shade->meshlen = 0; shade->meshcap = 0; -- cgit v1.2.3