summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2010-12-29 01:52:21 +0000
committerTor Andersson <tor@ghostscript.com>2010-12-29 01:52:21 +0000
commitdac0181028f2e02f44dd258e91d2df66975c3b89 (patch)
tree7a073e2b28acfe3b1e43afa8bf7987bbf3cca797
parent6b935a6c9c2a2fa7a0fd4fdd6919ea7965fa4942 (diff)
downloadmupdf-dac0181028f2e02f44dd258e91d2df66975c3b89.tar.xz
Support linear shadings as a special case in the fitz shading struct and renderer.
-rw-r--r--draw/meshdraw.c141
-rw-r--r--fitz/fitz.h10
-rw-r--r--fitz/res_shade.c12
-rw-r--r--mupdf/pdf_shade.c54
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;