summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mupdf/rsrc.h13
-rw-r--r--mupdf/shade3.c380
2 files changed, 70 insertions, 323 deletions
diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h
index 3c263c08..30a35b1e 100644
--- a/include/mupdf/rsrc.h
+++ b/include/mupdf/rsrc.h
@@ -86,6 +86,19 @@ void pdf_droppattern(pdf_pattern *pat);
* Shading
*/
+fz_error *
+pdf_loadtype1shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading,
+ fz_obj *ref, fz_matrix mat);
+fz_error *
+pdf_loadtype2shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading,
+ fz_obj *ref, fz_matrix mat);
+fz_error *
+pdf_loadtype3shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading,
+ fz_obj *ref, fz_matrix mat);
+
+fz_error *
+pdf_loadshadefunction(fz_shade *shade, pdf_xref *xref, fz_obj *shading, float t0, float t1);
+
void pdf_setmeshvalue(float *mesh, int i, float x, float y, float t);
fz_error *pdf_loadshade(fz_shade **shadep, pdf_xref *xref, fz_obj *obj, fz_obj *ref);
diff --git a/mupdf/shade3.c b/mupdf/shade3.c
index a6b4b40a..a7914c90 100644
--- a/mupdf/shade3.c
+++ b/mupdf/shade3.c
@@ -1,335 +1,57 @@
#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;
-}
+#define MAX_RAD_SEGS 36
-int
-fz_iscovered(double ax, double ay,
- const fz_point *p0, const fz_point *p1, const fz_point *p)
+int
+buildannulusmesh(float* mesh, int pos,
+ float x0, float y0, float r0, float x1, float y1, float r1,
+ float c0, float c1, int nomesh)
{
- 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;
-}
+ int n = pos * 3;
+ float dist = hypot(x1 - x0, y1 - y0);
+ float theta;
+ if (dist != 0)
+ theta = asin((r1 - r0) / dist) + M_PI/2.0 + atan2(y1 - y0, x1 - x0);
+ else
+ theta = 0;
+ if (!(theta >= 0 && theta <= M_PI)) {
+ theta = 0;
+ }
-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);
-}
+ float step = M_PI * 2. / (float)MAX_RAD_SEGS;
+ fz_point pt1, pt2, pt3, pt4;
+ for (int i=0; i < MAX_RAD_SEGS; theta -= step, ++i) {
+ pt1.x = cos (theta) * r1 + x1;
+ pt1.y = sin (theta) * r1 + y1;
+ pt2.x = cos (theta) * r0 + x0;
+ pt2.y = sin (theta) * r0 + y0;
+ pt3.x = cos (theta+step) * r1 + x1;
+ pt3.y = sin (theta+step) * r1 + y1;
+ pt4.x = cos (theta+step) * r0 + x0;
+ pt4.y = sin (theta+step) * r0 + y0;
-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 (r0 > 0) {
+ if (!nomesh) {
+ pdf_setmeshvalue(mesh, n++, pt1.x, pt1.y, c1);
+ pdf_setmeshvalue(mesh, n++, pt2.x, pt2.y, c0);
+ pdf_setmeshvalue(mesh, n++, pt4.x, pt4.y, c0);
}
+ pos++;
}
- 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;
+
+ if (r1 > 0) {
+ if (!nomesh) {
+ pdf_setmeshvalue(mesh, n++, pt1.x, pt1.y, c1);
+ pdf_setmeshvalue(mesh, n++, pt3.x, pt3.y, c1);
+ pdf_setmeshvalue(mesh, n++, pt4.x, pt4.y, c0);
}
+ pos++;
}
- }
- return 0;
+ }
+
+ return pos;
}
#endif
@@ -344,12 +66,11 @@ fz_buildannulusmesh(float* mesh,
fz_point pt1, pt2, pt3, pt4;
float step;
float theta;
- int n;
theta = 0.;
step = 3.1415921 * 2. / (float)nsegs;
- for (n=0; theta < step*nsegs; theta += step) {
+ for (int n=0; theta < step*nsegs; theta += step) {
pt1.x = cos (theta) * r1 + x1;
pt1.y = sin (theta) * r1 + y1;
pt2.x = cos (theta) * r0 + x0;
@@ -384,6 +105,8 @@ pdf_loadtype3shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading,
fz_error *error;
float x0, y0, r0, x1, y1, r1;
float t0, t1;
+ int e0, e1;
+ int e0meshlen, e1meshlen;
fz_obj *obj;
pdf_function *func;
int i;
@@ -409,6 +132,17 @@ pdf_loadtype3shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading,
t1 = 1.;
}
+ obj = fz_dictgets(shading, "Extend");
+ pdf_logshade("extend %d %d\n", e0, e1);
+
+ 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_loadshadefunction(shade, xref, shading, t0, t1);
@@ -421,7 +155,7 @@ pdf_loadtype3shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading,
tn = t0;
tn1 = t0 + tstep;
- for (i = 0; i < 10; ++i) {
+ for (int i = 0; i < 10; ++i) {
float tx0, ty0, tr0;
float tx1, ty1, tr1;
float c0, c1;