summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mupdf/shade.c6
-rw-r--r--mupdf/shade2.c70
-rw-r--r--mupdf/shade3.c335
3 files changed, 387 insertions, 24 deletions
diff --git a/mupdf/shade.c b/mupdf/shade.c
index 05a53e72..cbe319f7 100644
--- a/mupdf/shade.c
+++ b/mupdf/shade.c
@@ -85,8 +85,7 @@ pdf_loadshadedict(fz_shade **shadep, pdf_xref *xref, fz_obj *shading, fz_obj *re
shade->bbox.max.x, shade->bbox.max.y);
}
- switch(type)
- {
+ switch(type) {
case 1:
// error = pdf_loadtype1shade(shade, xref, shading, ref, mat);
if (error) goto cleanup;
@@ -105,13 +104,10 @@ pdf_loadshadedict(fz_shade **shadep, pdf_xref *xref, fz_obj *shading, fz_obj *re
break;
};
- pdf_logshade("}\n");
-
*shadep = shade;
return nil;
cleanup:
- pdf_logshade("have an error: %s\n", error->msg);
return error;
}
diff --git a/mupdf/shade2.c b/mupdf/shade2.c
index 459933b6..8871b6bf 100644
--- a/mupdf/shade2.c
+++ b/mupdf/shade2.c
@@ -8,6 +8,7 @@ pdf_buildt2shademesh(fz_shade *shade, pdf_xref *xref, fz_obj *shading,
fz_error *error;
float x0, y0, x1, y1;
float t0, t1;
+ int e0, e1;
fz_obj *obj;
pdf_function *func;
@@ -30,21 +31,35 @@ pdf_buildt2shademesh(fz_shade *shade, pdf_xref *xref, fz_obj *shading,
t1 = 1.;
}
+ obj = fz_dictgets(shading, "Extend");
+ if (obj) {
+ e0 = fz_tobool(fz_arrayget(obj, 0));
+ e1 = fz_tobool(fz_arrayget(obj, 1));
+ } else {
+ e0 = 0;
+ e1 = 0;
+ }
+
pdf_logshade("domain %g %g\n", t0, t1);
+ pdf_logshade("extend %d %d\n", e0, e1);
pdf_loadshadefunction(shade, xref, shading, t0, t1);
- shade->meshlen = 2;
+ shade->meshlen = 2 + e0 *2 + e1 * 2;
shade->mesh = (float*) malloc(sizeof(float) * 3*3 * shade->meshlen);
float theta;
- theta = atan2(x1 - x0, y1 - y0);
+ theta = atan2(y1 - y0, x1 - x0);
+ theta += M_PI / 2.0;
pdf_logshade("theta=%g\n", theta);
fz_point p1, p2, p3, p4;
+ fz_point ep1, ep2, ep3, ep4;
+ float dist;
+ dist = hypot(x1 - x0, y1 - y0);
-#define BIGNUM 10000
+#define BIGNUM 1000
p1.x = x0 + BIGNUM * cos(theta);
p1.y = y0 + BIGNUM * sin(theta);
@@ -55,27 +70,46 @@ pdf_buildt2shademesh(fz_shade *shade, pdf_xref *xref, fz_obj *shading,
p4.x = x1 - BIGNUM * cos(theta);
p4.y = y1 - BIGNUM * sin(theta);
+ ep1.x = p1.x - (x1 - x0) / dist * BIGNUM;
+ ep1.y = p1.y - (y1 - y0) / dist * BIGNUM;
+ ep2.x = p2.x + (x1 - x0) / dist * BIGNUM;
+ ep2.y = p2.y + (y1 - y0) / dist * BIGNUM;
+ ep3.x = p3.x - (x1 - x0) / dist * BIGNUM;
+ ep3.y = p3.y - (y1 - y0) / dist * BIGNUM;
+ ep4.x = p4.x + (x1 - x0) / dist * BIGNUM;
+ ep4.y = p4.y + (y1 - y0) / dist * BIGNUM;
+
pdf_logshade("p1 %g %g\n", p1.x, p1.y);
pdf_logshade("p2 %g %g\n", p2.x, p2.y);
pdf_logshade("p3 %g %g\n", p3.x, p3.y);
pdf_logshade("p4 %g %g\n", p4.x, p4.y);
- pdf_setmeshvalue(shade->mesh, 0, p1.x, p1.y, 0);
- pdf_setmeshvalue(shade->mesh, 1, p2.x, p2.y, 1);
- pdf_setmeshvalue(shade->mesh, 2, p4.x, p4.y, 1);
- pdf_setmeshvalue(shade->mesh, 3, p1.x, p1.y, 0);
- pdf_setmeshvalue(shade->mesh, 4, p4.x, p4.y, 1);
- pdf_setmeshvalue(shade->mesh, 5, p3.x, p3.y, 0);
-
- /*
- if (shade->extend) {
- e0 = fz_toint(fz_arrayget(shade->extend, 0));
- e1 = fz_toint(fz_arrayget(shade->extend, 1));
- } else {
- e0 = 0;
- e1 = 0;
+ int n = 0;
+
+ pdf_setmeshvalue(shade->mesh, n++, p1.x, p1.y, 0);
+ pdf_setmeshvalue(shade->mesh, n++, p2.x, p2.y, 1);
+ pdf_setmeshvalue(shade->mesh, n++, p4.x, p4.y, 1);
+ pdf_setmeshvalue(shade->mesh, n++, p1.x, p1.y, 0);
+ pdf_setmeshvalue(shade->mesh, n++, p4.x, p4.y, 1);
+ pdf_setmeshvalue(shade->mesh, n++, p3.x, p3.y, 0);
+
+ if (e0) {
+ pdf_setmeshvalue(shade->mesh, n++, ep1.x, ep1.y, 0);
+ pdf_setmeshvalue(shade->mesh, n++, p1.x, p1.y, 0);
+ pdf_setmeshvalue(shade->mesh, n++, p3.x, p3.y, 0);
+ pdf_setmeshvalue(shade->mesh, n++, ep1.x, ep1.y, 0);
+ pdf_setmeshvalue(shade->mesh, n++, p3.x, p3.y, 0);
+ pdf_setmeshvalue(shade->mesh, n++, ep3.x, ep3.y, 0);
+ }
+
+ if (e1) {
+ pdf_setmeshvalue(shade->mesh, n++, p2.x, p2.y, 1);
+ pdf_setmeshvalue(shade->mesh, n++, ep2.x, ep2.y, 1);
+ pdf_setmeshvalue(shade->mesh, n++, ep4.x, ep4.y, 1);
+ pdf_setmeshvalue(shade->mesh, n++, p2.x, p2.y, 1);
+ pdf_setmeshvalue(shade->mesh, n++, ep4.x, ep4.y, 1);
+ pdf_setmeshvalue(shade->mesh, n++, p4.x, p4.y, 1);
}
- */
pdf_logshade("}\n");
diff --git a/mupdf/shade3.c b/mupdf/shade3.c
index 1e077cb5..eb2badac 100644
--- a/mupdf/shade3.c
+++ b/mupdf/shade3.c
@@ -1,6 +1,340 @@
#include <fitz.h>
#include <mupdf.h>
+#ifdef NONE__
+double
+fz_shadet3rectradius(fz_rect rect, double x0, double y0)
+{
+ double d, dd;
+
+ dd = hypot(rect.min.x - x0, rect.min.y - y0);
+ d = hypot(rect.min.x - x0, rect.max.y - y0);
+ dd = max(dd, d);
+ d = hypot(rect.max.x - x0, rect.max.y - y0);
+ dd = max(dd, d);
+ d = hypot(rect.max.x - x0, rect.min.y - y0);
+ dd = max(dd, d);
+
+ return dd;
+}
+
+void
+fz_outercircle(const fz_rect rect,
+ double x0, double y0, double r0,
+ double x1, double y1, double r1,
+ double *x2, double *y2, double *r2)
+{
+ double dx = x1 - x0, dy = y1 - y0;
+ double sp, sq, s;
+
+
+ /* Compute a cone circle, which contacts the rect externally. */
+ /* Don't bother with all 4 sides of the rect,
+ just do with the X or Y span only,
+ so it's not an exact contact, sorry. */
+ if (fabs(dx) > fabs(dy)) {
+ /* Solving :
+ x0 + (x1 - x0) * s - r0 - (r1 - r0) * s == bbox_x
+ (x1 - x0) * s - (r1 - r0) * s == bbox_x - x0 + r0
+ s = (bbox_x - x0 + r0) / (x1 - x0 - r1 + r0)
+ */
+ assert(x1 - x0 + r1 - r0); /* We checked for obtuse cone. */
+ sp = (rect.min.x - x0 + r0) / (x1 - x0 - r1 + r0);
+ sq = (rect.max.x - x0 + r0) / (x1 - x0 - r1 + r0);
+ } else {
+ /* Same by Y. */
+ sp = (rect.min.y - y0 + r0) / (y1 - y0 - r1 + r0);
+ sq = (rect.max.y - y0 + r0) / (y1 - y0 - r1 + r0);
+ }
+ if (sp >= 1 && sq >= 1)
+ s = min(sp, sq);
+ else if(sp >= 1)
+ s = sp;
+ else if (sq >= 1)
+ s = sq;
+ else {
+ /* The circle 1 is outside the rect, use it. */
+ s = 1;
+ }
+ if (r0 + (r1 - r0) * s < 0) {
+ /* Passed the cone apex, use the apex. */
+ s = r0 / (r0 - r1);
+ *r2 = 0;
+ } else
+ *r2 = r0 + (r1 - r0) * s;
+ *x2 = x0 + (x1 - x0) * s;
+ *y2 = y0 + (y1 - y0) * s;
+}
+
+int
+fz_iscovered(double ax, double ay,
+ const fz_point *p0, const fz_point *p1, const fz_point *p)
+{
+ double dx0 = p0->x - ax, dy0 = p0->y - ay;
+ double dx1 = p1->x - ax, dy1 = p1->y - ay;
+ double dx = p->x - ax, dy = p->y - ay;
+ double vp0 = dx0 * dy - dy0 * dx;
+ double vp1 = dx * dy1 - dy * dx1;
+
+ return vp0 >= 0 && vp1 >= 0;
+}
+
+fz_error *
+fz_shadet3obtusecone(fz_rect rect,
+ float x0, float y0, float r0,
+ float x1, float y1, float r1,
+ double t1, double r,
+ fz_matrix ctm, fz_pixmap *dstp, int destcol[512][4])
+{
+ fz_error *error;
+ double dx = x1 - x0, dy = y1 - y0, dr = fabs(r1 - r0);
+ double d = hypot(dx, dy);
+ double ax, ay, as; /* Cone apex. */
+ fz_point p0, p1; /* Tangent limits. */
+ fz_point cp[4]; /* Corners.. */
+ fz_point rp[4]; /* Covered corners.. */
+ fz_point pb;
+ int rp_count = 0, cp_start, i;
+ int covered[4];
+
+
+
+ as = r0 / (r0 - r1);
+ ax = x0 + (x1 - x0) * as;
+ ay = y0 + (y1 - y0) * as;
+
+ if (fabs(d - dr) < 1e-7 * (d + dr)) {
+ /* Nearly degenerate, replace with half-plane. */
+ p0.x = ax - dy * r / d;
+ p0.y = ay + dx * r / d;
+ p1.x = ax + dy * r / d;
+ p1.y = ay - dx * r / d;
+ } else {
+ /* Tangent limits by proportional triangles. */
+ double da = hypot(ax - x0, ay - y0);
+ double h = r * r0 / da, g;
+
+ assert(h <= r);
+ g = sqrt(r * r - h * h);
+ p0.x = ax - dx * g / d - dy * h / d;
+ p0.y = ay - dy * g / d + dx * h / d;
+ p1.x = ax - dx * g / d + dy * h / d;
+ p1.y = ay - dy * g / d - dx * h / d;
+ }
+ /* Now we have 2 limited tangents, and 4 corners of the rect.
+ Need to know what corners are covered. */
+ cp[0].x = rect.min.x, cp[0].y = rect.min.y;
+ cp[1].x = rect.max.x, cp[1].y = rect.min.y;
+ cp[2].x = rect.max.x, cp[2].y = rect.max.y;
+ cp[3].x = rect.min.x, cp[3].y = rect.max.y;
+ covered[0] = fz_iscovered(ax, ay, &p0, &p1, &cp[0]);
+ covered[1] = fz_iscovered(ax, ay, &p0, &p1, &cp[1]);
+ covered[2] = fz_iscovered(ax, ay, &p0, &p1, &cp[2]);
+ covered[3] = fz_iscovered(ax, ay, &p0, &p1, &cp[3]);
+
+ if (!covered[0] && !covered[1] && !covered[2] && !covered[3]) {
+ fz_point pt1, pt2, pt3;
+ pt1.x = ax; pt1.y = ay;
+ pt2 = p0;
+ pt3 = p1;
+
+ pt1 = fz_transformpoint(ctm, pt1);
+ pt2 = fz_transformpoint(ctm, pt2);
+ pt3 = fz_transformpoint(ctm, pt3);
+
+ fz_triangle triangle;
+ triangle.vertex[0].x = pt1.x;
+ triangle.vertex[0].y = pt1.y;
+ triangle.vertex[0].l = t1;
+ triangle.vertex[1].x = pt2.x;
+ triangle.vertex[1].y = pt2.y;
+ triangle.vertex[1].l = t1;
+ triangle.vertex[2].x = pt3.x;
+ triangle.vertex[2].y = pt3.y;
+ triangle.vertex[2].l = t1;
+
+ error = fz_drawgouraudtriangle(triangle, dstp, destcol,
+ rect.min.x, rect.min.y, rect.max.x, rect.max.y);
+ goto end;
+ }
+ if (!covered[0] && covered[1])
+ cp_start = 1;
+ else if (!covered[1] && covered[2])
+ cp_start = 2;
+ else if (!covered[2] && covered[3])
+ cp_start = 3;
+ else if (!covered[3] && covered[0])
+ cp_start = 0;
+ else {
+ /* Must not happen, handle somehow for safety. */
+ cp_start = 0;
+ }
+ for (i = cp_start; i < cp_start + 4 && covered[i % 4]; i++) {
+ rp[rp_count] = cp[i % 4];
+ rp_count++;
+ }
+ /* Do paint. */
+ pb = p0;
+ for (i = 0; i < rp_count; i++) {
+ fz_point pt1, pt2, pt3;
+ pt1.x = ax; pt1.y = ay;
+ pt2 = pb;
+ pt3 = rp[i];
+
+ pt1 = fz_transformpoint(ctm, pt1);
+ pt2 = fz_transformpoint(ctm, pt2);
+ pt3 = fz_transformpoint(ctm, pt3);
+
+ fz_triangle triangle;
+ triangle.vertex[0].x = pt1.x;
+ triangle.vertex[0].y = pt1.y;
+ triangle.vertex[0].l = t1;
+ triangle.vertex[1].x = pt2.x;
+ triangle.vertex[1].y = pt2.y;
+ triangle.vertex[1].l = t1;
+ triangle.vertex[2].x = pt3.x;
+ triangle.vertex[2].y = pt3.y;
+ triangle.vertex[2].l = t1;
+
+ error = fz_drawgouraudtriangle(triangle, dstp, destcol,
+ rect.min.x, rect.min.y, rect.max.x, rect.max.y);
+ if (error < 0)
+ return error;
+ pb = rp[i];
+ }
+
+ fz_point pt1, pt2, pt3;
+ pt1.x = ax; pt1.y = ay;
+ pt2 = pb;
+ pt3 = p1;
+
+ pt1 = fz_transformpoint(ctm, pt1);
+ pt2 = fz_transformpoint(ctm, pt2);
+ pt3 = fz_transformpoint(ctm, pt3);
+
+ fz_triangle triangle;
+ triangle.vertex[0].x = pt1.x;
+ triangle.vertex[0].y = pt1.y;
+ triangle.vertex[0].l = t1;
+ triangle.vertex[1].x = pt2.x;
+ triangle.vertex[1].y = pt2.y;
+ triangle.vertex[1].l = t1;
+ triangle.vertex[2].x = pt3.x;
+ triangle.vertex[2].y = pt3.y;
+ triangle.vertex[2].l = t1;
+
+ error = fz_drawgouraudtriangle(triangle, dstp, destcol,
+ rect.min.x, rect.min.y, rect.max.x, rect.max.y);
+
+end:
+ return error;
+}
+
+fz_error *
+fz_shadet3tensorconeapex(fz_rect rect,
+ double x0, double y0, double r0,
+ double x1, double y1, double r1, double t,
+ fz_matrix ctm, fz_pixmap *dstp, int destcol[512][4])
+{
+ double as = r0 / (r0 - r1);
+ double ax = x0 + (x1 - x0) * as;
+ double ay = y0 + (y1 - y0) * as;
+
+ return fz_renderannulus(x1, y1, r1, ax, ay, 0, t, t, ctm, dstp, destcol);
+}
+
+
+fz_error *
+fz_rendershadet3extentions(fz_rect rect,
+ float x0, float y0, float r0,
+ float x1, float y1, float r1,
+ double t0, double t1, int Extend0, int Extend1,
+ fz_matrix ctm, fz_pixmap *dstp, int destcol[512][4])
+{
+ double dx = x1 - x0, dy = y1 - y0, dr = fabs(r1 - r0);
+ double d = hypot(dx, dy), r;
+ fz_error *error;
+
+ if (dr >= d - 1e-7 * (d + dr)) {
+ /* Nested circles, or degenerate. */
+ if (r0 > r1) {
+ if (Extend0) {
+ r = fz_shadet3rectradius(rect, x0, y0);
+ if (r > r0) {
+ error = fz_renderannulus(x0, y0, r, x0, y0, r0, t0, t0, ctm, dstp, destcol);
+ if (error)
+ return error;
+ }
+ }
+ if (Extend1 && r1 > 0)
+ return fz_renderannulus(x1, y1, r1, x1, y1, 0, t1, t1, ctm, dstp, destcol);
+ } else {
+ if (Extend1) {
+ r = fz_shadet3rectradius(rect, x1, y1);
+ if (r > r1) {
+ error = fz_renderannulus(x1, y1, r, x1, y1, r1, t1, t1, ctm, dstp, destcol);
+ if (error < 0)
+ return error;
+ }
+ }
+ if (Extend0 && r0 > 0)
+ return fz_renderannulus(x0, y0, r0, x0, y0, 0, t0, t0, ctm, dstp, destcol);
+ }
+ } else if (dr > d / 3) {
+ /* Obtuse cone. */
+ if (r0 > r1) {
+ if (Extend0) {
+ r = fz_shadet3rectradius(rect, x0, y0);
+ error = fz_shadet3obtusecone(rect, x0, y0, r0, x1, y1, r1, t0, r,
+ ctm, dstp, destcol);
+ if (error < 0)
+ return error;
+ }
+ if (Extend1 && r1 != 0)
+ return fz_shadet3tensorconeapex(rect, x0, y0, r0, x1, y1, r1, t1,
+ ctm, dstp, destcol);
+ return 0;
+ } else {
+ if (Extend1) {
+ r = fz_shadet3rectradius(rect, x1, y1);
+ error = fz_shadet3obtusecone(rect, x1, y1, r1, x0, y0, r0, t1, r,
+ ctm, dstp, destcol);
+ if (error < 0)
+ return error;
+ }
+ if (Extend0 && r0 != 0)
+ return fz_shadet3tensorconeapex(rect, x1, y1, r1, x0, y0, r0, t0,
+ ctm, dstp, destcol);
+ }
+ } else {
+ /* Acute cone or cylinder. */
+ double x2, y2, r2, x3, y3, r3;
+
+ if (Extend0) {
+ fz_outercircle(rect, x1, y1, r1, x0, y0, r0, &x3, &y3, &r3);
+ if (x3 != x1 || y3 != y1) {
+ error = fz_renderannulus(x0, y0, r0, x3, y3, r3, t0, t0,
+ ctm, dstp, destcol);
+ if (error < 0)
+ return error;
+ }
+ }
+ if (Extend1) {
+ fz_outercircle(rect, x0, y0, r0, x1, y1, r1, &x2, &y2, &r2);
+ if (x2 != x0 || y2 != y0) {
+ error = fz_renderannulus(x1, y1, r1, x2, y2, r2, t1, t1,
+ ctm, dstp, destcol);
+ if (error < 0)
+ return error;
+ }
+ }
+ }
+ return 0;
+}
+
+#endif
+
+
fz_error *
fz_buildannulusmesh(float* mesh,
int x0, int y0, int r0, int x1, int y1, int r1,
@@ -109,4 +443,3 @@ pdf_loadtype3shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading,
cleanup:
return error;
}
-