summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@hotmail.com>2010-12-29 19:14:58 +0000
committerSebastian Rasmussen <sebras@hotmail.com>2010-12-29 19:14:58 +0000
commit19e87a00961b24e446ee247569db5300b3974b04 (patch)
treef923865759ea6801334a47d8e39e217850c6ec7d
parent2c911e0a3aaeed80b24956d1871c740a5be42398 (diff)
downloadmupdf-19e87a00961b24e446ee247569db5300b3974b04.tar.xz
Support radial shadings as another special case in the fitz renderer.
-rw-r--r--draw/meshdraw.c177
-rw-r--r--fitz/fitz.h2
-rw-r--r--mupdf/pdf_shade.c88
3 files changed, 156 insertions, 111 deletions
diff --git a/draw/meshdraw.c b/draw/meshdraw.c
index df4dfe41..434be9a1 100644
--- a/draw/meshdraw.c
+++ b/draw/meshdraw.c
@@ -306,18 +306,56 @@ fz_drawtriangle(fz_pixmap *pix, float *av, float *bv, float *cv, int n, fz_bbox
}
}
+static void
+fz_drawquad(fz_pixmap *pix,
+ fz_point p0, fz_point p1, fz_point p2, fz_point p3,
+ float c0, float c1, float c2, float c3,
+ int n, fz_bbox bbox)
+{
+ float v[4][3];
+
+ v[0][0] = p0.x;
+ v[0][1] = p0.y;
+ v[0][2] = c0;
+
+ v[1][0] = p1.x;
+ v[1][1] = p1.y;
+ v[1][2] = c1;
+
+ v[2][0] = p2.x;
+ v[2][1] = p2.y;
+ v[2][2] = c2;
+
+ v[3][0] = p3.x;
+ v[3][1] = p3.y;
+ v[3][2] = c3;
+
+ fz_drawtriangle(pix, v[0], v[2], v[3], n, bbox);
+ fz_drawtriangle(pix, v[0], v[3], v[1], n, bbox);
+}
+
/*
- * mesh drawing
+ * linear, radial and mesh drawing
*/
-#define HUGENUM 32000
+#define HUGENUM 32000 /* how far to extend axial/radial shadings */
+#define RADSEGS 32 /* how many segments to generate for radial meshes */
+
+static fz_point
+fz_pointoncircle(fz_point p, float r, float theta)
+{
+ p.x = p.x + cosf(theta) * r;
+ p.y = p.y + sinf(theta) * r;
+
+ return p;
+}
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;
+ fz_point v0, v1, v2, v3;
+ fz_point e0, e1;
float theta;
p0.x = shade->mesh[0];
@@ -331,51 +369,118 @@ fz_renderlinear(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
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;
+ v0 = fz_pointoncircle(p0, HUGENUM, theta);
+ v1 = fz_pointoncircle(p1, HUGENUM, theta);
+ v2 = fz_pointoncircle(p0, -HUGENUM, theta);
+ v3 = fz_pointoncircle(p1, -HUGENUM, theta);
+
+ fz_drawquad(dest, v0, v1, v2, v3, 0, 255, 0, 255, 3, bbox);
+
+ if (shade->extend[0])
+ {
+ e0.x = v0.x - (p1.x - p0.x) * HUGENUM;
+ e0.y = v0.y - (p1.y - p0.y) * HUGENUM;
+
+ e1.x = v2.x - (p1.x - p0.x) * HUGENUM;
+ e1.y = v2.y - (p1.y - p0.y) * HUGENUM;
- v[1][0] = p1.x + HUGENUM * cosf(theta);
- v[1][1] = p1.y + HUGENUM * sinf(theta);
- v[1][2] = 255;
+ fz_drawquad(dest, e0, v0, v2, e1, 0, 0, 0, 0, 3, bbox);
+ }
- v[2][0] = p0.x - HUGENUM * cosf(theta);
- v[2][1] = p0.y - HUGENUM * sinf(theta);
- v[2][2] = 0;
+ if (shade->extend[1])
+ {
+ e0.x = v1.x - (p1.x - p0.x) * HUGENUM;
+ e0.y = v1.y - (p1.y - p0.y) * HUGENUM;
- v[3][0] = p1.x - HUGENUM * cosf(theta);
- v[3][1] = p1.y - HUGENUM * sinf(theta);
- v[3][2] = 255;
+ e1.x = v3.x - (p1.x - p0.x) * HUGENUM;
+ e1.y = v3.y - (p1.y - p0.y) * HUGENUM;
- fz_drawtriangle(dest, v[0], v[1], v[2], 3, bbox);
- fz_drawtriangle(dest, v[1], v[2], v[3], 3, bbox);
+ fz_drawquad(dest, e0, v1, v3, e1, 255, 255, 255, 255, 3, bbox);
+ }
+}
+
+static void
+fz_renderannulus(fz_matrix ctm,
+ fz_point p0, float r0, float c0,
+ fz_point p1, float r1, float c1,
+ fz_pixmap *dest, fz_bbox bbox)
+{
+ fz_point t0, t1, t2, t3, b0, b1, b2, b3;
+ float theta, step;
+ int i;
+
+ theta = atan2f(p1.y - p0.y, p1.x - p0.x);
+ step = (float)M_PI * 2 / RADSEGS;
+
+ for (i = 0; i < RADSEGS / 2; i++)
+ {
+ t0 = fz_pointoncircle(p0, r0, theta + i * step);
+ t1 = fz_pointoncircle(p0, r0, theta + i * step + step);
+ t2 = fz_pointoncircle(p1, r1, theta + i * step);
+ t3 = fz_pointoncircle(p1, r1, theta + i * step + step);
+ b0 = fz_pointoncircle(p0, r0, theta - i * step);
+ b1 = fz_pointoncircle(p0, r0, theta - i * step - step);
+ b2 = fz_pointoncircle(p1, r1, theta - i * step);
+ b3 = fz_pointoncircle(p1, r1, theta - i * step - step);
+
+ t0 = fz_transformpoint(ctm, t0);
+ t1 = fz_transformpoint(ctm, t1);
+ t2 = fz_transformpoint(ctm, t2);
+ t3 = fz_transformpoint(ctm, t3);
+ b0 = fz_transformpoint(ctm, b0);
+ b1 = fz_transformpoint(ctm, b1);
+ b2 = fz_transformpoint(ctm, b2);
+ b3 = fz_transformpoint(ctm, b3);
+
+ fz_drawquad(dest, t0, t1, t2, t3, c0, c0, c1, c1, 3, bbox);
+ fz_drawquad(dest, b0, b1, b2, b3, c0, c0, c1, c1, 3, bbox);
+ }
+}
+
+static void
+fz_renderradial(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
+{
+ fz_point p0, p1;
+ float r0, r1;
+ fz_point e;
+ float er, rs;
+
+ p0.x = shade->mesh[0];
+ p0.y = shade->mesh[1];
+ r0 = shade->mesh[2];
+
+ p1.x = shade->mesh[3];
+ p1.y = shade->mesh[4];
+ r1 = shade->mesh[5];
+
+ fz_renderannulus(ctm, p0, r0, 0, p1, r1, 255, dest, 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];
+ if (r0 < r1)
+ rs = r0 / (r0 - r1);
+ else
+ rs = -HUGENUM;
- 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];
+ e.x = p0.x + (p1.x - p0.x) * rs;
+ e.y = p0.y + (p1.y - p0.y) * rs;
+ er = r0 + (r1 - r0) * rs;
- fz_drawtriangle(dest, e[0], v[0], v[2], 3, bbox);
- fz_drawtriangle(dest, e[0], v[2], e[1], 3, bbox);
+ fz_renderannulus(ctm, e, er, 0, p0, r0, 0, dest, 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];
+ if (r0 > r1)
+ rs = r1 / (r1 - r0);
+ else
+ rs = -HUGENUM;
- 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];
+ e.x = p1.x + (p0.x - p1.x) * rs;
+ e.y = p1.y + (p0.y - p1.y) * rs;
+ er = r1 + (r0 - r1) * rs;
- fz_drawtriangle(dest, e[0], v[1], v[3], 3, bbox);
- fz_drawtriangle(dest, e[0], v[3], e[1], 3, bbox);
+ fz_renderannulus(ctm, p1, r1, 255, e, er, 255, dest, bbox);
}
}
@@ -450,7 +555,9 @@ fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
case FZ_LINEAR:
fz_renderlinear(shade, ctm, temp, bbox);
break;
- /* TODO: FZ_RADIAL */
+ case FZ_RADIAL:
+ fz_renderradial(shade, ctm, temp, bbox);
+ break;
case FZ_MESH:
fz_rendermesh(shade, ctm, temp, bbox);
break;
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 3275dc4e..e35bf0f9 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -823,7 +823,7 @@ struct fz_shade_s
int meshlen;
int meshcap;
- float *mesh; /* [x y t] or [x y c1 ... cn] */
+ float *mesh; /* [x y 0], [x y r], [x y t] or [x y c1 ... cn] */
};
fz_shade *fz_keepshade(fz_shade *shade);
diff --git a/mupdf/pdf_shade.c b/mupdf/pdf_shade.c
index caa0b98e..ef19d1a4 100644
--- a/mupdf/pdf_shade.c
+++ b/mupdf/pdf_shade.c
@@ -507,62 +507,12 @@ pdf_loadaxialshading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, p
p2.x = x1;
p2.y = y1;
- p2.c[0] = 1;
+ p2.c[0] = 0;
pdf_addvertex(shade, &p2);
return fz_okay;
}
-static void
-pdf_buildannulusmesh(fz_shade *shade,
- float x0, float y0, float r0, float c0,
- float x1, float y1, float r1, float c1)
-{
- struct vertex a, b, c, d;
- float start = atan2(y1 - y0, x1 - x0);
- float step = (float)M_PI * 2 / RADSEGS;
- float angle;
- int i;
-
- a.c[0] = c0;
- b.c[0] = c0;
- c.c[0] = c1;
- d.c[0] = c1;
-
- for (i = 0; i < RADSEGS / 2; i ++)
- {
- /* top side */
- angle = start + i * step;
- a.x = x0 + cosf(angle) * r0;
- a.y = y0 + sinf(angle) * r0;
- b.x = x0 + cosf(angle + step) * r0;
- b.y = y0 + sinf(angle + step) * r0;
- c.x = x1 + cosf(angle) * r1;
- c.y = y1 + sinf(angle) * r1;
- d.x = x1 + cosf(angle + step) * r1;
- d.y = y1 + sinf(angle + step) * r1;
- if (r1 > 0) /* a == b, c != d */
- pdf_addtriangle(shade, &a, &c, &d);
- if (r0 > 0) /* a != b, c == d */
- pdf_addtriangle(shade, &a, &d, &b);
-
- /* bottom side */
- angle = start - i * step;
- a.x = x0 + cosf(angle) * r0;
- a.y = y0 + sinf(angle) * r0;
- b.x = x0 + cosf(angle - step) * r0;
- b.y = y0 + sinf(angle - step) * r0;
- c.x = x1 + cosf(angle) * r1;
- c.y = y1 + sinf(angle) * r1;
- d.x = x1 + cosf(angle - step) * r1;
- d.y = y1 + sinf(angle - step) * r1;
- if (r1 > 0) /* a == b, c != d */
- pdf_addtriangle(shade, &a, &c, &d);
- if (r0 > 0) /* a != b, c == d */
- pdf_addtriangle(shade, &a, &d, &b);
- }
-}
-
static fz_error
pdf_loadradialshading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func)
{
@@ -571,9 +521,7 @@ pdf_loadradialshading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs,
float d0, d1;
int e0, e1;
float x0, y0, r0, x1, y1, r1;
- float ex0, ey0, er0;
- float ex1, ey1, er1;
- float rs;
+ struct vertex p1, p2;
pdf_logshade("load type3 (radial) shading\n");
@@ -608,30 +556,20 @@ pdf_loadradialshading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs,
if (error)
return fz_rethrow(error, "unable to sample shading function");
- if (r0 < r1)
- rs = r0 / (r0 - r1);
- else
- rs = -HUGENUM;
-
- ex0 = x0 + (x1 - x0) * rs;
- ey0 = y0 + (y1 - y0) * rs;
- er0 = r0 + (r1 - r0) * rs;
-
- if (r0 > r1)
- rs = r1 / (r1 - r0);
- else
- rs = -HUGENUM;
+ shade->type = FZ_RADIAL;
- ex1 = x1 + (x0 - x1) * rs;
- ey1 = y1 + (y0 - y1) * rs;
- er1 = r1 + (r0 - r1) * rs;
+ shade->extend[0] = e0;
+ shade->extend[1] = e1;
- if (e0)
- pdf_buildannulusmesh(shade, ex0, ey0, er0, 0, x0, y0, r0, 0);
- pdf_buildannulusmesh(shade, x0, y0, r0, 0, x1, y1, r1, 1);
- if (e1)
- pdf_buildannulusmesh(shade, x1, y1, r1, 1, ex1, ey1, er1, 1);
+ p1.x = x0;
+ p1.y = y0;
+ p1.c[0] = r0;
+ pdf_addvertex(shade, &p1);
+ p2.x = x1;
+ p2.y = y1;
+ p2.c[0] = r1;
+ pdf_addvertex(shade, &p2);
return fz_okay;
}