summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--draw/draw_mesh.c106
-rw-r--r--fitz/fitz-internal.h69
-rw-r--r--fitz/res_shade.c855
-rw-r--r--pdf/pdf_shade.c822
-rw-r--r--xps/xps_gradient.c38
5 files changed, 1012 insertions, 878 deletions
diff --git a/draw/draw_mesh.c b/draw/draw_mesh.c
index 924bd34d..532f78f4 100644
--- a/draw/draw_mesh.c
+++ b/draw/draw_mesh.c
@@ -500,12 +500,12 @@ fz_paint_linear(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
fz_point e0, e1;
float theta;
- p0.x = shade->mesh[0];
- p0.y = shade->mesh[1];
+ p0.x = shade->u.a_or_r.coords[0][0];
+ p0.y = shade->u.a_or_r.coords[0][1];
p0 = fz_transform_point(ctm, p0);
- p1.x = shade->mesh[3];
- p1.y = shade->mesh[4];
+ p1.x = shade->u.a_or_r.coords[1][0];
+ p1.y = shade->u.a_or_r.coords[1][1];
p1 = fz_transform_point(ctm, p1);
theta = my_atan2f(p1.y - p0.y, p1.x - p0.x);
@@ -518,7 +518,7 @@ fz_paint_linear(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
fz_paint_quad(dest, v0, v1, v2, v3, 0, 255, 0, 255, 3, bbox);
- if (shade->extend[0])
+ if (shade->u.a_or_r.extend[0])
{
e0.x = v0.x - (p1.x - p0.x) * HUGENUM;
e0.y = v0.y - (p1.y - p0.y) * HUGENUM;
@@ -529,7 +529,7 @@ fz_paint_linear(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
fz_paint_quad(dest, e0, e1, v0, v2, 0, 0, 0, 0, 3, bbox);
}
- if (shade->extend[1])
+ if (shade->u.a_or_r.extend[1])
{
e0.x = v1.x + (p1.x - p0.x) * HUGENUM;
e0.y = v1.y + (p1.y - p0.y) * HUGENUM;
@@ -587,15 +587,15 @@ fz_paint_radial(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
fz_point e;
float er, rs;
- p0.x = shade->mesh[0];
- p0.y = shade->mesh[1];
- r0 = shade->mesh[2];
+ p0.x = shade->u.a_or_r.coords[0][0];
+ p0.y = shade->u.a_or_r.coords[0][1];
+ r0 = shade->u.a_or_r.coords[0][2];
- p1.x = shade->mesh[3];
- p1.y = shade->mesh[4];
- r1 = shade->mesh[5];
+ p1.x = shade->u.a_or_r.coords[1][0];
+ p1.y = shade->u.a_or_r.coords[1][1];
+ r1 = shade->u.a_or_r.coords[1][2];
- if (shade->extend[0])
+ if (shade->u.a_or_r.extend[0])
{
if (r0 < r1)
rs = r0 / (r0 - r1);
@@ -611,7 +611,7 @@ fz_paint_radial(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
fz_paint_annulus(ctm, p0, r0, 0, p1, r1, 255, dest, bbox);
- if (shade->extend[1])
+ if (shade->u.a_or_r.extend[1])
{
if (r0 > r1)
rs = r1 / (r1 - r0);
@@ -626,43 +626,50 @@ fz_paint_radial(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
}
}
+struct paint_tri_data
+{
+ fz_context *ctx;
+ fz_shade *shade;
+ fz_pixmap *dest;
+ fz_bbox bbox;
+};
+
static void
-fz_paint_mesh(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
+do_paint_tri(void *arg, fz_vertex *av, fz_vertex *bv, fz_vertex *cv)
{
- float tri[3][MAXN];
- fz_point p;
- float *mesh;
- int ntris;
+ struct paint_tri_data *ptd = (struct paint_tri_data *)arg;
int i, k;
-
- mesh = shade->mesh;
-
- if (shade->use_function)
- ntris = shade->mesh_len / 9;
- else
- ntris = shade->mesh_len / ((2 + shade->colorspace->n) * 3);
-
- while (ntris--)
+ fz_vertex *vertices[3];
+ fz_vertex *v;
+ float *ltri;
+ fz_context *ctx;
+ fz_shade *shade;
+ fz_pixmap *dest;
+ float local[3][MAXN];
+
+ vertices[0] = av;
+ vertices[1] = bv;
+ vertices[2] = cv;
+
+ dest = ptd->dest;
+ ctx = ptd->ctx;
+ shade = ptd->shade;
+ for (k = 0; k < 3; k++)
{
- for (k = 0; k < 3; k++)
+ v = vertices[k];
+ ltri = &local[k][0];
+ ltri[0] = v->p.x;
+ ltri[1] = v->p.y;
+ if (shade->use_function)
+ ltri[2] = v->c[0] * 255;
+ else
{
- p.x = *mesh++;
- p.y = *mesh++;
- p = fz_transform_point(ctm, p);
- tri[k][0] = p.x;
- tri[k][1] = p.y;
- if (shade->use_function)
- tri[k][2] = *mesh++ * 255;
- else
- {
- fz_convert_color(ctx, dest->colorspace, tri[k] + 2, shade->colorspace, mesh);
- for (i = 0; i < dest->colorspace->n; i++)
- tri[k][i + 2] *= 255;
- mesh += shade->colorspace->n;
- }
+ fz_convert_color(ctx, dest->colorspace, &ltri[2], shade->colorspace, v->c);
+ for (i = 0; i < dest->colorspace->n; i++)
+ ltri[i + 2] *= 255;
}
- fz_paint_triangle(dest, tri[0], tri[1], tri[2], 2 + dest->colorspace->n, bbox);
}
+ fz_paint_triangle(dest, local[0], local[1], local[2], 2 + dest->colorspace->n, ptd->bbox);
}
void
@@ -703,7 +710,16 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest,
{
case FZ_LINEAR: fz_paint_linear(shade, ctm, temp, bbox); break;
case FZ_RADIAL: fz_paint_radial(shade, ctm, temp, bbox); break;
- case FZ_MESH: fz_paint_mesh(ctx, shade, ctm, temp, bbox); break;
+ default:
+ {
+ struct paint_tri_data ptd;
+ ptd.ctx = ctx;
+ ptd.dest = temp;
+ ptd.shade = shade;
+ ptd.bbox = bbox;
+ fz_process_mesh(ctx, shade, ctm, &do_paint_tri, &ptd);
+ break;
+ }
}
if (shade->use_function)
diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h
index 1d641817..5d94896f 100644
--- a/fitz/fitz-internal.h
+++ b/fitz/fitz-internal.h
@@ -957,9 +957,13 @@ void fz_print_text(fz_context *ctx, FILE *out, fz_text*);
enum
{
- FZ_LINEAR,
- FZ_RADIAL,
- FZ_MESH,
+ FZ_FUNCTION_BASED = 1,
+ FZ_LINEAR = 2,
+ FZ_RADIAL = 3,
+ FZ_MESH_TYPE4 = 4,
+ FZ_MESH_TYPE5 = 5,
+ FZ_MESH_TYPE6 = 6,
+ FZ_MESH_TYPE7 = 7
};
typedef struct fz_shade_s fz_shade;
@@ -978,12 +982,36 @@ struct fz_shade_s
int use_function;
float function[256][FZ_MAX_COLORS + 1];
- int type; /* linear, radial, mesh */
- int extend[2];
+ int type; /* function, axial, radial, mesh */
+ union
+ {
+ struct
+ {
+ int extend[2];
+ float coords[2][3]; /* (x,y,r) twice */
+ } a_or_r;
+ struct
+ {
+ int vprow;
+ int bpflag;
+ int bpcoord;
+ int bpcomp;
+ float x0, x1;
+ float y0, y1;
+ float c0[FZ_MAX_COLORS];
+ float c1[FZ_MAX_COLORS];
+ } m;
+ struct
+ {
+ fz_matrix matrix;
+ int xdivs;
+ int ydivs;
+ float domain[2][2];
+ float *fn_vals;
+ } f;
+ } u;
- int mesh_len;
- int mesh_cap;
- float *mesh; /* [x y 0], [x y r], [x y t] or [x y c1 ... cn] */
+ fz_buffer *buffer;
};
fz_shade *fz_keep_shade(fz_context *ctx, fz_shade *shade);
@@ -993,6 +1021,31 @@ void fz_free_shade_imp(fz_context *ctx, fz_storable *shade);
fz_rect fz_bound_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm);
void fz_paint_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox);
+/*
+ * Handy routine for processing mesh based shades
+ */
+typedef struct fz_vertex_s fz_vertex;
+
+struct fz_vertex_s
+{
+ fz_point p;
+ float c[FZ_MAX_COLORS];
+};
+
+typedef struct fz_mesh_processor_s fz_mesh_processor;
+
+typedef void (fz_mesh_process_fn)(void *arg, fz_vertex *av, fz_vertex *bv, fz_vertex *cv);
+
+struct fz_mesh_processor_s {
+ fz_context *ctx;
+ fz_shade *shade;
+ fz_mesh_process_fn *process;
+ void *process_arg;
+};
+
+void fz_process_mesh(fz_context *ctx, fz_shade *shade, fz_matrix ctm,
+ fz_mesh_process_fn *process, void *process_arg);
+
#ifndef NDEBUG
void fz_print_shade(fz_context *ctx, FILE *out, fz_shade *shade);
#endif
diff --git a/fitz/res_shade.c b/fitz/res_shade.c
index 9ebdd51e..231a7ba0 100644
--- a/fitz/res_shade.c
+++ b/fitz/res_shade.c
@@ -1,5 +1,755 @@
#include "fitz-internal.h"
+#define SWAP(a,b) {fz_vertex *t = (a); (a) = (b); (b) = t;}
+
+static void
+paint_tri(fz_mesh_processor *painter, fz_vertex *v0, fz_vertex *v1, fz_vertex *v2)
+{
+ painter->process(painter->process_arg, v0, v1, v2);
+}
+
+static void
+paint_quad(fz_mesh_processor *painter, fz_vertex *v0, fz_vertex *v1, fz_vertex *v2, fz_vertex *v3)
+{
+ painter->process(painter->process_arg, v0, v1, v3);
+ painter->process(painter->process_arg, v1, v3, v2);
+}
+
+static void
+fz_mesh_type1_process(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
+{
+ float *p = shade->u.f.fn_vals;
+ int xdivs = shade->u.f.xdivs;
+ int ydivs = shade->u.f.ydivs;
+ float x0 = shade->u.f.domain[0][0];
+ float y0 = shade->u.f.domain[0][1];
+ float x1 = shade->u.f.domain[1][0];
+ float y1 = shade->u.f.domain[1][1];
+ int xx, yy;
+ float y, yn, x;
+ fz_vertex vs[2][2];
+ fz_vertex *v = vs[0];
+ fz_vertex *vn = vs[1];
+ int n = shade->colorspace->n;
+
+ ctm = fz_concat(shade->u.f.matrix, ctm);
+
+ y = y0;
+ for (yy = 0; yy < ydivs; yy++)
+ {
+ yn = y0 + (y1 - y0) * (yy + 1) / ydivs;
+
+ x = x0;
+ v[0].p.x = x; v[0].p.y = y;
+ v[0].p = fz_transform_point(ctm, v[0].p);
+ memcpy(v[0].c, p, n*sizeof(float));
+ p += n;
+ v[1].p.x = x; v[1].p.y = yn;
+ v[1].p = fz_transform_point(ctm, v[1].p);
+ memcpy(v[1].c, p + xdivs*n, n*sizeof(float));
+ for (xx = 0; xx < xdivs; xx++)
+ {
+ x = x0 + (x1 - x0) * (xx + 1) / xdivs;
+
+ vn[0].p.x = x; vn[0].p.y = y;
+ vn[0].p = fz_transform_point(ctm, vn[0].p);
+ memcpy(vn[0].c, p, n*sizeof(float));
+ p += n;
+ vn[1].p.x = x; vn[1].p.y = yn;
+ vn[1].p = fz_transform_point(ctm, vn[1].p);
+ memcpy(vn[1].c, p + xdivs*n, n*sizeof(float));
+
+ paint_quad(painter, &v[0], &vn[0], &vn[1], &v[1]);
+ SWAP(v,vn);
+ }
+ y = yn;
+ }
+}
+
+static inline float read_sample(fz_stream *stream, int bits, float min, float max)
+{
+ /* we use pow(2,x) because (1<<x) would overflow the math on 32-bit samples */
+ float bitscale = 1 / (powf(2, bits) - 1);
+ return min + fz_read_bits(stream, bits) * (max - min) * bitscale;
+}
+
+static void
+fz_mesh_type4_process(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
+{
+ fz_stream *stream = fz_open_buffer(ctx, shade->buffer);
+ fz_vertex v[4];
+ fz_vertex *va = &v[0];
+ fz_vertex *vb = &v[1];
+ fz_vertex *vc = &v[2];
+ fz_vertex *vd = &v[3];
+ int flag, i, ncomp;
+ int bpflag = shade->u.m.bpflag;
+ int bpcoord = shade->u.m.bpcoord;
+ int bpcomp = shade->u.m.bpcomp;
+ float x0 = shade->u.m.x0;
+ float x1 = shade->u.m.x1;
+ float y0 = shade->u.m.y0;
+ float y1 = shade->u.m.y1;
+ float *c0 = shade->u.m.c0;
+ float *c1 = shade->u.m.c1;
+
+ fz_try(ctx)
+ {
+ ncomp = (shade->use_function > 0 ? 1 : shade->colorspace->n);
+ while (!fz_is_eof_bits(stream))
+ {
+ flag = fz_read_bits(stream, bpflag);
+ vd->p.x = read_sample(stream, bpcoord, x0, x1);
+ vd->p.y = read_sample(stream, bpcoord, y0, y1);
+ vd->p = fz_transform_point(ctm, vd->p);
+ for (i = 0; i < ncomp; i++)
+ vd->c[i] = read_sample(stream, bpcomp, c0[i], c1[i]);
+
+ switch (flag)
+ {
+ case 0: /* start new triangle */
+ SWAP(va, vd);
+
+ fz_read_bits(stream, bpflag);
+ vb->p.x = read_sample(stream, bpcoord, x0, x1);
+ vb->p.y = read_sample(stream, bpcoord, y0, y1);
+ vb->p = fz_transform_point(ctm, vb->p);
+ for (i = 0; i < ncomp; i++)
+ vb->c[i] = read_sample(stream, bpcomp, c0[i], c1[i]);
+
+ fz_read_bits(stream, bpflag);
+ vc->p.x = read_sample(stream, bpcoord, x0, x1);
+ vc->p.y = read_sample(stream, bpcoord, y0, y1);
+ vc->p = fz_transform_point(ctm, vc->p);
+ for (i = 0; i < ncomp; i++)
+ vc->c[i] = read_sample(stream, bpcomp, c0[i], c1[i]);
+
+ paint_tri(painter, va, vb, vc);
+ break;
+
+ case 1: /* Vb, Vc, Vd */
+ SWAP(va, vb);
+ SWAP(vb, vc);
+ SWAP(vc, vd);
+ paint_tri(painter, va, vb, vc);
+ break;
+
+ case 2: /* Va, Vc, Vd */
+ SWAP(vb, vc);
+ SWAP(vc, vd);
+ paint_tri(painter, va, vb, vc);
+ break;
+ }
+ }
+ }
+ fz_always(ctx)
+ {
+ fz_close(stream);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+static void
+fz_mesh_type5_process(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
+{
+ fz_stream *stream = fz_open_buffer(ctx, shade->buffer);
+ fz_vertex *buf = NULL;
+ fz_vertex *ref = NULL;
+ int first;
+ int ncomp;
+ int i, k;
+ int vprow = shade->u.m.vprow;
+ int bpcoord = shade->u.m.bpcoord;
+ int bpcomp = shade->u.m.bpcomp;
+ float x0 = shade->u.m.x0;
+ float x1 = shade->u.m.x1;
+ float y0 = shade->u.m.y0;
+ float y1 = shade->u.m.y1;
+ float *c0 = shade->u.m.c0;
+ float *c1 = shade->u.m.c1;
+
+ fz_var(buf);
+ fz_var(ref);
+
+ fz_try(ctx)
+ {
+ ref = fz_malloc_array(ctx, vprow, sizeof(fz_vertex));
+ buf = fz_malloc_array(ctx, vprow, sizeof(fz_vertex));
+ first = 1;
+
+ ncomp = (shade->use_function > 0 ? 1 : shade->colorspace->n);
+ while (!fz_is_eof_bits(stream))
+ {
+ for (i = 0; i < vprow; i++)
+ {
+ buf[i].p.x = read_sample(stream, bpcoord, x0, x1);
+ buf[i].p.y = read_sample(stream, bpcoord, y0, y1);
+ buf[i].p = fz_transform_point(ctm, buf[i].p);
+ for (k = 0; k < ncomp; k++)
+ buf[i].c[k] = read_sample(stream, bpcomp, c0[k], c1[k]);
+ }
+
+ if (!first)
+ for (i = 0; i < vprow - 1; i++)
+ paint_quad(painter, &ref[i], &ref[i+1], &buf[i+1], &buf[i]);
+
+ SWAP(ref,buf);
+ first = 0;
+ }
+ }
+ fz_always(ctx)
+ {
+ fz_free(ctx, ref);
+ fz_free(ctx, buf);
+ fz_close(stream);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+/* Subdivide and tessellate tensor-patches */
+
+typedef struct tensor_patch_s tensor_patch;
+
+struct tensor_patch_s
+{
+ fz_point pole[4][4];
+ float color[4][FZ_MAX_COLORS];
+};
+
+static void
+triangulate_patch(fz_mesh_processor *painter, tensor_patch p)
+{
+ fz_vertex v0, v1, v2, v3;
+
+ v0.p = p.pole[0][0];
+ memcpy(v0.c, p.color[0], sizeof(v0.c));
+
+ v1.p = p.pole[0][3];
+ memcpy(v1.c, p.color[1], sizeof(v1.c));
+
+ v2.p = p.pole[3][3];
+ memcpy(v2.c, p.color[2], sizeof(v2.c));
+
+ v3.p = p.pole[3][0];
+ memcpy(v3.c, p.color[3], sizeof(v3.c));
+
+ paint_quad(painter, &v0, &v1, &v2, &v3);
+}
+
+static inline void midcolor(float *c, float *c1, float *c2)
+{
+ int i;
+ for (i = 0; i < FZ_MAX_COLORS; i++)
+ c[i] = (c1[i] + c2[i]) * 0.5f;
+}
+
+static void
+split_curve(fz_point *pole, fz_point *q0, fz_point *q1, int polestep)
+{
+ /*
+ split bezier curve given by control points pole[0]..pole[3]
+ using de casteljau algo at midpoint and build two new
+ bezier curves q0[0]..q0[3] and q1[0]..q1[3]. all indices
+ should be multiplies by polestep == 1 for vertical bezier
+ curves in patch and == 4 for horizontal bezier curves due
+ to C's multi-dimensional matrix memory layout.
+ */
+
+ float x12 = (pole[1 * polestep].x + pole[2 * polestep].x) * 0.5f;
+ float y12 = (pole[1 * polestep].y + pole[2 * polestep].y) * 0.5f;
+
+ q0[1 * polestep].x = (pole[0 * polestep].x + pole[1 * polestep].x) * 0.5f;
+ q0[1 * polestep].y = (pole[0 * polestep].y + pole[1 * polestep].y) * 0.5f;
+ q1[2 * polestep].x = (pole[2 * polestep].x + pole[3 * polestep].x) * 0.5f;
+ q1[2 * polestep].y = (pole[2 * polestep].y + pole[3 * polestep].y) * 0.5f;
+
+ q0[2 * polestep].x = (q0[1 * polestep].x + x12) * 0.5f;
+ q0[2 * polestep].y = (q0[1 * polestep].y + y12) * 0.5f;
+ q1[1 * polestep].x = (x12 + q1[2 * polestep].x) * 0.5f;
+ q1[1 * polestep].y = (y12 + q1[2 * polestep].y) * 0.5f;
+
+ q0[3 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
+ q0[3 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
+ q1[0 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
+ q1[0 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
+
+ q0[0 * polestep].x = pole[0 * polestep].x;
+ q0[0 * polestep].y = pole[0 * polestep].y;
+ q1[3 * polestep].x = pole[3 * polestep].x;
+ q1[3 * polestep].y = pole[3 * polestep].y;
+}
+
+static void
+split_stripe(tensor_patch *p, tensor_patch *s0, tensor_patch *s1)
+{
+ /*
+ split all horizontal bezier curves in patch,
+ creating two new patches with half the width.
+ */
+ split_curve(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
+ split_curve(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
+ split_curve(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
+ split_curve(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
+
+ /* interpolate the colors for the two new patches. */
+ memcpy(s0->color[0], p->color[0], sizeof(s0->color[0]));
+ memcpy(s0->color[1], p->color[1], sizeof(s0->color[1]));
+ midcolor(s0->color[2], p->color[1], p->color[2]);
+ midcolor(s0->color[3], p->color[0], p->color[3]);
+
+ memcpy(s1->color[0], s0->color[3], sizeof(s1->color[0]));
+ memcpy(s1->color[1], s0->color[2], sizeof(s1->color[1]));
+ memcpy(s1->color[2], p->color[2], sizeof(s1->color[2]));
+ memcpy(s1->color[3], p->color[3], sizeof(s1->color[3]));
+}
+
+static void
+draw_stripe(fz_mesh_processor *painter, tensor_patch *p, int depth)
+{
+ tensor_patch s0, s1;
+
+ /* split patch into two half-height patches */
+ split_stripe(p, &s0, &s1);
+
+ depth--;
+ if (depth == 0)
+ {
+ /* if no more subdividing, draw two new patches... */
+ triangulate_patch(painter, s1);
+ triangulate_patch(painter, s0);
+ }
+ else
+ {
+ /* ...otherwise, continue subdividing. */
+ draw_stripe(painter, &s1, depth);
+ draw_stripe(painter, &s0, depth);
+ }
+}
+
+static void
+split_patch(tensor_patch *p, tensor_patch *s0, tensor_patch *s1)
+{
+ /*
+ split all vertical bezier curves in patch,
+ creating two new patches with half the height.
+ */
+ split_curve(p->pole[0], s0->pole[0], s1->pole[0], 1);
+ split_curve(p->pole[1], s0->pole[1], s1->pole[1], 1);
+ split_curve(p->pole[2], s0->pole[2], s1->pole[2], 1);
+ split_curve(p->pole[3], s0->pole[3], s1->pole[3], 1);
+
+ /* interpolate the colors for the two new patches. */
+ memcpy(s0->color[0], p->color[0], sizeof(s0->color[0]));
+ midcolor(s0->color[1], p->color[0], p->color[1]);
+ midcolor(s0->color[2], p->color[2], p->color[3]);
+ memcpy(s0->color[3], p->color[3], sizeof(s0->color[3]));
+
+ memcpy(s1->color[0], s0->color[1], sizeof(s1->color[0]));
+ memcpy(s1->color[1], p->color[1], sizeof(s1->color[1]));
+ memcpy(s1->color[2], p->color[2], sizeof(s1->color[2]));
+ memcpy(s1->color[3], s0->color[2], sizeof(s1->color[3]));
+}
+
+static void
+draw_patch(fz_mesh_processor *painter, tensor_patch *p, int depth, int origdepth)
+{
+ tensor_patch s0, s1;
+
+ /* split patch into two half-width patches */
+ split_patch(p, &s0, &s1);
+
+ depth--;
+ if (depth == 0)
+ {
+ /* if no more subdividing, draw two new patches... */
+ draw_stripe(painter, &s0, origdepth);
+ draw_stripe(painter, &s1, origdepth);
+ }
+ else
+ {
+ /* ...otherwise, continue subdividing. */
+ draw_patch(painter, &s0, depth, origdepth);
+ draw_patch(painter, &s1, depth, origdepth);
+ }
+}
+
+static fz_point
+compute_tensor_interior(
+ fz_point a, fz_point b, fz_point c, fz_point d,
+ fz_point e, fz_point f, fz_point g, fz_point h)
+{
+ fz_point pt;
+
+ /* see equations at page 330 in pdf 1.7 */
+
+ pt.x = -4 * a.x;
+ pt.x += 6 * (b.x + c.x);
+ pt.x += -2 * (d.x + e.x);
+ pt.x += 3 * (f.x + g.x);
+ pt.x += -1 * h.x;
+ pt.x /= 9;
+
+ pt.y = -4 * a.y;
+ pt.y += 6 * (b.y + c.y);
+ pt.y += -2 * (d.y + e.y);
+ pt.y += 3 * (f.y + g.y);
+ pt.y += -1 * h.y;
+ pt.y /= 9;
+
+ return pt;
+}
+
+static void
+make_tensor_patch(tensor_patch *p, int type, fz_point *pt)
+{
+ if (type == 6)
+ {
+ /* see control point stream order at page 325 in pdf 1.7 */
+
+ p->pole[0][0] = pt[0];
+ p->pole[0][1] = pt[1];
+ p->pole[0][2] = pt[2];
+ p->pole[0][3] = pt[3];
+ p->pole[1][3] = pt[4];
+ p->pole[2][3] = pt[5];
+ p->pole[3][3] = pt[6];
+ p->pole[3][2] = pt[7];
+ p->pole[3][1] = pt[8];
+ p->pole[3][0] = pt[9];
+ p->pole[2][0] = pt[10];
+ p->pole[1][0] = pt[11];
+
+ /* see equations at page 330 in pdf 1.7 */
+
+ p->pole[1][1] = compute_tensor_interior(
+ p->pole[0][0], p->pole[0][1], p->pole[1][0], p->pole[0][3],
+ p->pole[3][0], p->pole[3][1], p->pole[1][3], p->pole[3][3]);
+
+ p->pole[1][2] = compute_tensor_interior(
+ p->pole[0][3], p->pole[0][2], p->pole[1][3], p->pole[0][0],
+ p->pole[3][3], p->pole[3][2], p->pole[1][0], p->pole[3][0]);
+
+ p->pole[2][1] = compute_tensor_interior(
+ p->pole[3][0], p->pole[3][1], p->pole[2][0], p->pole[3][3],
+ p->pole[0][0], p->pole[0][1], p->pole[2][3], p->pole[0][3]);
+
+ p->pole[2][2] = compute_tensor_interior(
+ p->pole[3][3], p->pole[3][2], p->pole[2][3], p->pole[3][0],
+ p->pole[0][3], p->pole[0][2], p->pole[2][0], p->pole[0][0]);
+ }
+ else if (type == 7)
+ {
+ /* see control point stream order at page 330 in pdf 1.7 */
+
+ p->pole[0][0] = pt[0];
+ p->pole[0][1] = pt[1];
+ p->pole[0][2] = pt[2];
+ p->pole[0][3] = pt[3];
+ p->pole[1][3] = pt[4];
+ p->pole[2][3] = pt[5];
+ p->pole[3][3] = pt[6];
+ p->pole[3][2] = pt[7];
+ p->pole[3][1] = pt[8];
+ p->pole[3][0] = pt[9];
+ p->pole[2][0] = pt[10];
+ p->pole[1][0] = pt[11];
+ p->pole[1][1] = pt[12];
+ p->pole[1][2] = pt[13];
+ p->pole[2][2] = pt[14];
+ p->pole[2][1] = pt[15];
+ }
+}
+
+/* FIXME: Nasty */
+#define SUBDIV 3 /* how many levels to subdivide patches */
+
+static void
+fz_mesh_type6_process(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
+{
+ fz_stream *stream = fz_open_buffer(ctx, shade->buffer);
+ int haspatch, hasprevpatch;
+ float prevc[4][FZ_MAX_COLORS];
+ fz_point prevp[12];
+ int ncomp;
+ int i, k;
+ int bpflag = shade->u.m.bpflag;
+ int bpcoord = shade->u.m.bpcoord;
+ int bpcomp = shade->u.m.bpcomp;
+ float x0 = shade->u.m.x0;
+ float x1 = shade->u.m.x1;
+ float y0 = shade->u.m.y0;
+ float y1 = shade->u.m.y1;
+ float *c0 = shade->u.m.c0;
+ float *c1 = shade->u.m.c1;
+
+ fz_try(ctx)
+ {
+ hasprevpatch = 0;
+ ncomp = (shade->use_function > 0 ? 1 : shade->colorspace->n);
+ while (!fz_is_eof_bits(stream))
+ {
+ float c[4][FZ_MAX_COLORS];
+ fz_point v[12];
+ int startcolor;
+ int startpt;
+ int flag;
+
+ flag = fz_read_bits(stream, bpflag);
+
+ if (flag == 0)
+ {
+ startpt = 0;
+ startcolor = 0;
+ }
+ else
+ {
+ startpt = 4;
+ startcolor = 2;
+ }
+
+ for (i = startpt; i < 12; i++)
+ {
+ v[i].x = read_sample(stream, bpcoord, x0, x1);
+ v[i].y = read_sample(stream, bpcoord, y0, y1);
+ v[i] = fz_transform_point(ctm, v[i]);
+ }
+
+ for (i = startcolor; i < 4; i++)
+ {
+ for (k = 0; k < ncomp; k++)
+ c[i][k] = read_sample(stream, bpcomp, c0[k], c1[k]);
+ }
+
+ haspatch = 0;
+
+ if (flag == 0)
+ {
+ haspatch = 1;
+ }
+ else if (flag == 1 && hasprevpatch)
+ {
+ v[0] = prevp[3];
+ v[1] = prevp[4];
+ v[2] = prevp[5];
+ v[3] = prevp[6];
+ memcpy(c[0], prevc[1], ncomp * sizeof(float));
+ memcpy(c[1], prevc[2], ncomp * sizeof(float));
+
+ haspatch = 1;
+ }
+ else if (flag == 2 && hasprevpatch)
+ {
+ v[0] = prevp[6];
+ v[1] = prevp[7];
+ v[2] = prevp[8];
+ v[3] = prevp[9];
+ memcpy(c[0], prevc[2], ncomp * sizeof(float));
+ memcpy(c[1], prevc[3], ncomp * sizeof(float));
+
+ haspatch = 1;
+ }
+ else if (flag == 3 && hasprevpatch)
+ {
+ v[0] = prevp[ 9];
+ v[1] = prevp[10];
+ v[2] = prevp[11];
+ v[3] = prevp[ 0];
+ memcpy(c[0], prevc[3], ncomp * sizeof(float));
+ memcpy(c[1], prevc[0], ncomp * sizeof(float));
+
+ haspatch = 1;
+ }
+
+ if (haspatch)
+ {
+ tensor_patch patch;
+
+ make_tensor_patch(&patch, 6, v);
+
+ for (i = 0; i < 4; i++)
+ memcpy(patch.color[i], c[i], ncomp * sizeof(float));
+
+ draw_patch(painter, &patch, SUBDIV, SUBDIV);
+
+ for (i = 0; i < 12; i++)
+ prevp[i] = v[i];
+
+ for (i = 0; i < 4; i++)
+ memcpy(prevc[i], c[i], ncomp * sizeof(float));
+
+ hasprevpatch = 1;
+ }
+ }
+ }
+ fz_always(ctx)
+ {
+ fz_close(stream);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+static void
+fz_mesh_type7_process(fz_context *ctx, fz_shade *shade, fz_matrix ctm, fz_mesh_processor *painter)
+{
+ fz_stream *stream = fz_open_buffer(ctx, shade->buffer);
+ int bpflag = shade->u.m.bpflag;
+ int bpcoord = shade->u.m.bpcoord;
+ int bpcomp = shade->u.m.bpcomp;
+ float x0 = shade->u.m.x0;
+ float x1 = shade->u.m.x1;
+ float y0 = shade->u.m.y0;
+ float y1 = shade->u.m.y1;
+ float *c0 = shade->u.m.c0;
+ float *c1 = shade->u.m.c1;
+ float prevc[4][FZ_MAX_COLORS];
+ fz_point prevp[16];
+ int ncomp;
+ int i, k;
+ int haspatch, hasprevpatch;
+
+ fz_try(ctx)
+ {
+ hasprevpatch = 0;
+ ncomp = (shade->use_function > 0 ? 1 : shade->colorspace->n);
+ while (!fz_is_eof_bits(stream))
+ {
+ float c[4][FZ_MAX_COLORS];
+ fz_point v[16];
+ int startcolor;
+ int startpt;
+ int flag;
+
+ flag = fz_read_bits(stream, bpflag);
+
+ if (flag == 0)
+ {
+ startpt = 0;
+ startcolor = 0;
+ }
+ else
+ {
+ startpt = 4;
+ startcolor = 2;
+ }
+
+ for (i = startpt; i < 16; i++)
+ {
+ v[i].x = read_sample(stream, bpcoord, x0, x1);
+ v[i].y = read_sample(stream, bpcoord, y0, y1);
+ v[i] = fz_transform_point(ctm, v[i]);
+ }
+
+ for (i = startcolor; i < 4; i++)
+ {
+ for (k = 0; k < ncomp; k++)
+ c[i][k] = read_sample(stream, bpcomp, c0[k], c1[k]);
+ }
+
+ haspatch = 0;
+
+ if (flag == 0)
+ {
+ haspatch = 1;
+ }
+ else if (flag == 1 && hasprevpatch)
+ {
+ v[0] = prevp[3];
+ v[1] = prevp[4];
+ v[2] = prevp[5];
+ v[3] = prevp[6];
+ memcpy(c[0], prevc[1], ncomp * sizeof(float));
+ memcpy(c[1], prevc[2], ncomp * sizeof(float));
+
+ haspatch = 1;
+ }
+ else if (flag == 2 && hasprevpatch)
+ {
+ v[0] = prevp[6];
+ v[1] = prevp[7];
+ v[2] = prevp[8];
+ v[3] = prevp[9];
+ memcpy(c[0], prevc[2], ncomp * sizeof(float));
+ memcpy(c[1], prevc[3], ncomp * sizeof(float));
+
+ haspatch = 1;
+ }
+ else if (flag == 3 && hasprevpatch)
+ {
+ v[0] = prevp[ 9];
+ v[1] = prevp[10];
+ v[2] = prevp[11];
+ v[3] = prevp[ 0];
+ memcpy(c[0], prevc[3], ncomp * sizeof(float));
+ memcpy(c[1], prevc[0], ncomp * sizeof(float));
+
+ haspatch = 1;
+ }
+
+ if (haspatch)
+ {
+ tensor_patch patch;
+
+ make_tensor_patch(&patch, 7, v);
+
+ for (i = 0; i < 4; i++)
+ memcpy(patch.color[i], c[i], ncomp * sizeof(float));
+
+ draw_patch(painter, &patch, SUBDIV, SUBDIV);
+
+ for (i = 0; i < 16; i++)
+ prevp[i] = v[i];
+
+ for (i = 0; i < 4; i++)
+ memcpy(prevc[i], c[i], FZ_MAX_COLORS * sizeof(float));
+
+ hasprevpatch = 1;
+ }
+ }
+ }
+ fz_always(ctx)
+ {
+ fz_close(stream);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+void
+fz_process_mesh(fz_context *ctx, fz_shade *shade, fz_matrix ctm,
+ fz_mesh_process_fn *process, void *process_arg)
+{
+ fz_mesh_processor painter;
+
+ painter.ctx = ctx;
+ painter.shade = shade;
+ painter.process = process;
+ painter.process_arg = process_arg;
+
+ if (shade->type == FZ_FUNCTION_BASED)
+ fz_mesh_type1_process(ctx, shade, ctm, &painter);
+ else if (shade->type == FZ_MESH_TYPE4)
+ fz_mesh_type4_process(ctx, shade, ctm, &painter);
+ else if (shade->type == FZ_MESH_TYPE5)
+ fz_mesh_type5_process(ctx, shade, ctm, &painter);
+ else if (shade->type == FZ_MESH_TYPE6)
+ fz_mesh_type6_process(ctx, shade, ctm, &painter);
+ else if (shade->type == FZ_MESH_TYPE7)
+ fz_mesh_type7_process(ctx, shade, ctm, &painter);
+ else
+ fz_throw(ctx, "Unexpected mesh type %d\n", shade->type);
+}
+
fz_shade *
fz_keep_shade(fz_context *ctx, fz_shade *shade)
{
@@ -13,7 +763,9 @@ fz_free_shade_imp(fz_context *ctx, fz_storable *shade_)
if (shade->colorspace)
fz_drop_colorspace(ctx, shade->colorspace);
- fz_free(ctx, shade->mesh);
+ if (shade->type == FZ_FUNCTION_BASED)
+ fz_free(ctx, shade->u.f.fn_vals);
+ fz_drop_buffer(ctx, shade->buffer);
fz_free(ctx, shade);
}
@@ -23,65 +775,76 @@ fz_drop_shade(fz_context *ctx, fz_shade *shade)
fz_drop_storable(ctx, &shade->storable);
}
+struct bound_mesh_data
+{
+ fz_rect rect;
+ int first;
+};
+
+static void
+bound_tri(void *arg, fz_vertex *v1, fz_vertex *v2, fz_vertex *v3)
+{
+ struct bound_mesh_data *bmd = (struct bound_mesh_data *)arg;
+
+ if (bmd->first)
+ {
+ bmd->rect.x0 = bmd->rect.x1 = v1->p.x;
+ bmd->rect.y0 = bmd->rect.y1 = v1->p.y;
+ bmd->first = 0;
+ }
+ else
+ {
+ if (v1->p.x < bmd->rect.x0) bmd->rect.x0 = v1->p.x;
+ if (v1->p.y < bmd->rect.y0) bmd->rect.y0 = v1->p.y;
+ if (v1->p.x > bmd->rect.x1) bmd->rect.x1 = v1->p.x;
+ if (v1->p.y > bmd->rect.y1) bmd->rect.y1 = v1->p.y;
+ }
+
+ if (v2->p.x < bmd->rect.x0) bmd->rect.x0 = v2->p.x;
+ if (v2->p.y < bmd->rect.y0) bmd->rect.y0 = v2->p.y;
+ if (v2->p.x > bmd->rect.x1) bmd->rect.x1 = v2->p.x;
+ if (v2->p.y > bmd->rect.y1) bmd->rect.y1 = v2->p.y;
+
+ if (v3->p.x < bmd->rect.x0) bmd->rect.x0 = v3->p.x;
+ if (v3->p.y < bmd->rect.y0) bmd->rect.y0 = v3->p.y;
+ if (v3->p.x > bmd->rect.x1) bmd->rect.x1 = v3->p.x;
+ if (v3->p.y > bmd->rect.y1) bmd->rect.y1 = v3->p.y;
+}
+
fz_rect
fz_bound_shade(fz_context *ctx, fz_shade *shade, fz_matrix ctm)
{
- float *v;
- fz_rect r, s;
- fz_point p;
- int i, ncomp, nvert;
+ fz_rect s;
+ struct bound_mesh_data bmd;
ctm = fz_concat(shade->matrix, ctm);
- ncomp = shade->use_function ? 3 : 2 + shade->colorspace->n;
- nvert = shade->mesh_len / ncomp;
- v = shade->mesh;
-
s = fz_transform_rect(ctm, shade->bbox);
if (shade->type == FZ_LINEAR)
return fz_intersect_rect(s, fz_infinite_rect);
if (shade->type == FZ_RADIAL)
return fz_intersect_rect(s, fz_infinite_rect);
- if (nvert == 0)
- return fz_empty_rect;
+ bmd.rect = fz_empty_rect;
+ bmd.first = 1;
+ fz_process_mesh(ctx, shade, ctm, &bound_tri, &bmd);
- p.x = v[0];
- p.y = v[1];
- v += ncomp;
- p = fz_transform_point(ctm, p);
- r.x0 = r.x1 = p.x;
- r.y0 = r.y1 = p.y;
-
- for (i = 1; i < nvert; i++)
- {
- p.x = v[0];
- p.y = v[1];
- p = fz_transform_point(ctm, p);
- v += ncomp;
- if (p.x < r.x0) r.x0 = p.x;
- if (p.y < r.y0) r.y0 = p.y;
- if (p.x > r.x1) r.x1 = p.x;
- if (p.y > r.y1) r.y1 = p.y;
- }
-
- return fz_intersect_rect(s, r);
+ return fz_intersect_rect(s, bmd.rect);
}
#ifndef NDEBUG
void
fz_print_shade(fz_context *ctx, FILE *out, fz_shade *shade)
{
- int i, j, n;
- float *vertex;
- int triangle;
+ int i;
fprintf(out, "shading {\n");
switch (shade->type)
{
+ case FZ_FUNCTION_BASED: fprintf(out, "\ttype function_based\n"); break;
case FZ_LINEAR: fprintf(out, "\ttype linear\n"); break;
case FZ_RADIAL: fprintf(out, "\ttype radial\n"); break;
- case FZ_MESH: fprintf(out, "\ttype mesh\n"); break;
+ default: /* MESH */ fprintf(out, "\ttype mesh\n"); break;
}
fprintf(out, "\tbbox [%g %g %g %g]\n",
@@ -105,28 +868,6 @@ fz_print_shade(fz_context *ctx, FILE *out, fz_shade *shade)
if (shade->use_function)
{
fprintf(out, "\tfunction\n");
- n = 3;
- }
- else
- n = 2 + shade->colorspace->n;
-
- fprintf(out, "\tvertices: %d\n", shade->mesh_len);
-
- vertex = shade->mesh;
- triangle = 0;
- i = 0;
- while (i < shade->mesh_len)
- {
- fprintf(out, "\t%d:(%g, %g): ", triangle, vertex[0], vertex[1]);
-
- for (j = 2; j < n; j++)
- fprintf(out, "%s%g", j == 2 ? "" : " ", vertex[j]);
- fprintf(out, "\n");
-
- vertex += n;
- i++;
- if (i % 3 == 0)
- triangle++;
}
fprintf(out, "}\n");
diff --git a/pdf/pdf_shade.c b/pdf/pdf_shade.c
index 39e71626..6fbfd6b7 100644
--- a/pdf/pdf_shade.c
+++ b/pdf/pdf_shade.c
@@ -1,326 +1,8 @@
#include "fitz-internal.h"
#include "mupdf-internal.h"
-#define HUGENUM 32000 /* how far to extend axial/radial shadings */
+/* FIXME: Remove this somehow */
#define FUNSEGS 32 /* size of sampled mesh for function-based shadings */
-#define RADSEGS 32 /* how many segments to generate for radial meshes */
-#define SUBDIV 3 /* how many levels to subdivide patches */
-
-struct vertex
-{
- float x, y;
- float c[FZ_MAX_COLORS];
-};
-
-static void
-pdf_grow_mesh(fz_context *ctx, fz_shade *shade, int amount)
-{
- int cap = shade->mesh_cap;
-
- if (shade->mesh_len + amount < cap)
- return;
-
- if (cap == 0)
- cap = 1024;
-
- while (shade->mesh_len + amount > cap)
- cap = (cap * 3) / 2;
-
- shade->mesh = fz_resize_array(ctx, shade->mesh, cap, sizeof(float));
- shade->mesh_cap = cap;
-}
-
-static void
-pdf_add_vertex(fz_context *ctx, fz_shade *shade, struct vertex *v)
-{
- int ncomp = shade->use_function ? 1 : shade->colorspace->n;
- int i;
- pdf_grow_mesh(ctx, shade, 2 + ncomp);
- shade->mesh[shade->mesh_len++] = v->x;
- shade->mesh[shade->mesh_len++] = v->y;
- for (i = 0; i < ncomp; i++)
- shade->mesh[shade->mesh_len++] = v->c[i];
-}
-
-static void
-pdf_add_triangle(fz_context *ctx, fz_shade *shade,
- struct vertex *v0,
- struct vertex *v1,
- struct vertex *v2)
-{
- pdf_add_vertex(ctx, shade, v0);
- pdf_add_vertex(ctx, shade, v1);
- pdf_add_vertex(ctx, shade, v2);
-}
-
-static void
-pdf_add_quad(fz_context *ctx, fz_shade *shade,
- struct vertex *v0,
- struct vertex *v1,
- struct vertex *v2,
- struct vertex *v3)
-{
- pdf_add_triangle(ctx, shade, v0, v1, v3);
- pdf_add_triangle(ctx, shade, v1, v3, v2);
-}
-
-/* Subdivide and tessellate tensor-patches */
-
-typedef struct pdf_tensor_patch_s pdf_tensor_patch;
-
-struct pdf_tensor_patch_s
-{
- fz_point pole[4][4];
- float color[4][FZ_MAX_COLORS];
-};
-
-static void
-triangulate_patch(fz_context *ctx, pdf_tensor_patch p, fz_shade *shade)
-{
- struct vertex v0, v1, v2, v3;
-
- v0.x = p.pole[0][0].x;
- v0.y = p.pole[0][0].y;
- memcpy(v0.c, p.color[0], sizeof(v0.c));
-
- v1.x = p.pole[0][3].x;
- v1.y = p.pole[0][3].y;
- memcpy(v1.c, p.color[1], sizeof(v1.c));
-
- v2.x = p.pole[3][3].x;
- v2.y = p.pole[3][3].y;
- memcpy(v2.c, p.color[2], sizeof(v2.c));
-
- v3.x = p.pole[3][0].x;
- v3.y = p.pole[3][0].y;
- memcpy(v3.c, p.color[3], sizeof(v3.c));
-
- pdf_add_quad(ctx, shade, &v0, &v1, &v2, &v3);
-}
-
-static inline void midcolor(float *c, float *c1, float *c2)
-{
- int i;
- for (i = 0; i < FZ_MAX_COLORS; i++)
- c[i] = (c1[i] + c2[i]) * 0.5f;
-}
-
-static void
-split_curve(fz_point *pole, fz_point *q0, fz_point *q1, int polestep)
-{
- /*
- split bezier curve given by control points pole[0]..pole[3]
- using de casteljau algo at midpoint and build two new
- bezier curves q0[0]..q0[3] and q1[0]..q1[3]. all indices
- should be multiplies by polestep == 1 for vertical bezier
- curves in patch and == 4 for horizontal bezier curves due
- to C's multi-dimensional matrix memory layout.
- */
-
- float x12 = (pole[1 * polestep].x + pole[2 * polestep].x) * 0.5f;
- float y12 = (pole[1 * polestep].y + pole[2 * polestep].y) * 0.5f;
-
- q0[1 * polestep].x = (pole[0 * polestep].x + pole[1 * polestep].x) * 0.5f;
- q0[1 * polestep].y = (pole[0 * polestep].y + pole[1 * polestep].y) * 0.5f;
- q1[2 * polestep].x = (pole[2 * polestep].x + pole[3 * polestep].x) * 0.5f;
- q1[2 * polestep].y = (pole[2 * polestep].y + pole[3 * polestep].y) * 0.5f;
-
- q0[2 * polestep].x = (q0[1 * polestep].x + x12) * 0.5f;
- q0[2 * polestep].y = (q0[1 * polestep].y + y12) * 0.5f;
- q1[1 * polestep].x = (x12 + q1[2 * polestep].x) * 0.5f;
- q1[1 * polestep].y = (y12 + q1[2 * polestep].y) * 0.5f;
-
- q0[3 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
- q0[3 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
- q1[0 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
- q1[0 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
-
- q0[0 * polestep].x = pole[0 * polestep].x;
- q0[0 * polestep].y = pole[0 * polestep].y;
- q1[3 * polestep].x = pole[3 * polestep].x;
- q1[3 * polestep].y = pole[3 * polestep].y;
-}
-
-static void
-split_stripe(pdf_tensor_patch *p, pdf_tensor_patch *s0, pdf_tensor_patch *s1)
-{
- /*
- split all horizontal bezier curves in patch,
- creating two new patches with half the width.
- */
- split_curve(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
- split_curve(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
- split_curve(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
- split_curve(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
-
- /* interpolate the colors for the two new patches. */
- memcpy(s0->color[0], p->color[0], sizeof(s0->color[0]));
- memcpy(s0->color[1], p->color[1], sizeof(s0->color[1]));
- midcolor(s0->color[2], p->color[1], p->color[2]);
- midcolor(s0->color[3], p->color[0], p->color[3]);
-
- memcpy(s1->color[0], s0->color[3], sizeof(s1->color[0]));
- memcpy(s1->color[1], s0->color[2], sizeof(s1->color[1]));
- memcpy(s1->color[2], p->color[2], sizeof(s1->color[2]));
- memcpy(s1->color[3], p->color[3], sizeof(s1->color[3]));
-}
-
-static void
-draw_stripe(fz_context *ctx, pdf_tensor_patch *p, fz_shade *shade, int depth)
-{
- pdf_tensor_patch s0, s1;
-
- /* split patch into two half-height patches */
- split_stripe(p, &s0, &s1);
-
- depth--;
- if (depth == 0)
- {
- /* if no more subdividing, draw two new patches... */
- triangulate_patch(ctx, s1, shade);
- triangulate_patch(ctx, s0, shade);
- }
- else
- {
- /* ...otherwise, continue subdividing. */
- draw_stripe(ctx, &s1, shade, depth);
- draw_stripe(ctx, &s0, shade, depth);
- }
-}
-
-static void
-split_patch(pdf_tensor_patch *p, pdf_tensor_patch *s0, pdf_tensor_patch *s1)
-{
- /*
- split all vertical bezier curves in patch,
- creating two new patches with half the height.
- */
- split_curve(p->pole[0], s0->pole[0], s1->pole[0], 1);
- split_curve(p->pole[1], s0->pole[1], s1->pole[1], 1);
- split_curve(p->pole[2], s0->pole[2], s1->pole[2], 1);
- split_curve(p->pole[3], s0->pole[3], s1->pole[3], 1);
-
- /* interpolate the colors for the two new patches. */
- memcpy(s0->color[0], p->color[0], sizeof(s0->color[0]));
- midcolor(s0->color[1], p->color[0], p->color[1]);
- midcolor(s0->color[2], p->color[2], p->color[3]);
- memcpy(s0->color[3], p->color[3], sizeof(s0->color[3]));
-
- memcpy(s1->color[0], s0->color[1], sizeof(s1->color[0]));
- memcpy(s1->color[1], p->color[1], sizeof(s1->color[1]));
- memcpy(s1->color[2], p->color[2], sizeof(s1->color[2]));
- memcpy(s1->color[3], s0->color[2], sizeof(s1->color[3]));
-}
-
-static void
-draw_patch(fz_context *ctx, fz_shade *shade, pdf_tensor_patch *p, int depth, int origdepth)
-{
- pdf_tensor_patch s0, s1;
-
- /* split patch into two half-width patches */
- split_patch(p, &s0, &s1);
-
- depth--;
- if (depth == 0)
- {
- /* if no more subdividing, draw two new patches... */
- draw_stripe(ctx, &s0, shade, origdepth);
- draw_stripe(ctx, &s1, shade, origdepth);
- }
- else
- {
- /* ...otherwise, continue subdividing. */
- draw_patch(ctx, shade, &s0, depth, origdepth);
- draw_patch(ctx, shade, &s1, depth, origdepth);
- }
-}
-
-static fz_point
-pdf_compute_tensor_interior(
- fz_point a, fz_point b, fz_point c, fz_point d,
- fz_point e, fz_point f, fz_point g, fz_point h)
-{
- fz_point pt;
-
- /* see equations at page 330 in pdf 1.7 */
-
- pt.x = -4 * a.x;
- pt.x += 6 * (b.x + c.x);
- pt.x += -2 * (d.x + e.x);
- pt.x += 3 * (f.x + g.x);
- pt.x += -1 * h.x;
- pt.x /= 9;
-
- pt.y = -4 * a.y;
- pt.y += 6 * (b.y + c.y);
- pt.y += -2 * (d.y + e.y);
- pt.y += 3 * (f.y + g.y);
- pt.y += -1 * h.y;
- pt.y /= 9;
-
- return pt;
-}
-
-static void
-pdf_make_tensor_patch(pdf_tensor_patch *p, int type, fz_point *pt)
-{
- if (type == 6)
- {
- /* see control point stream order at page 325 in pdf 1.7 */
-
- p->pole[0][0] = pt[0];
- p->pole[0][1] = pt[1];
- p->pole[0][2] = pt[2];
- p->pole[0][3] = pt[3];
- p->pole[1][3] = pt[4];
- p->pole[2][3] = pt[5];
- p->pole[3][3] = pt[6];
- p->pole[3][2] = pt[7];
- p->pole[3][1] = pt[8];
- p->pole[3][0] = pt[9];
- p->pole[2][0] = pt[10];
- p->pole[1][0] = pt[11];
-
- /* see equations at page 330 in pdf 1.7 */
-
- p->pole[1][1] = pdf_compute_tensor_interior(
- p->pole[0][0], p->pole[0][1], p->pole[1][0], p->pole[0][3],
- p->pole[3][0], p->pole[3][1], p->pole[1][3], p->pole[3][3]);
-
- p->pole[1][2] = pdf_compute_tensor_interior(
- p->pole[0][3], p->pole[0][2], p->pole[1][3], p->pole[0][0],
- p->pole[3][3], p->pole[3][2], p->pole[1][0], p->pole[3][0]);
-
- p->pole[2][1] = pdf_compute_tensor_interior(
- p->pole[3][0], p->pole[3][1], p->pole[2][0], p->pole[3][3],
- p->pole[0][0], p->pole[0][1], p->pole[2][3], p->pole[0][3]);
-
- p->pole[2][2] = pdf_compute_tensor_interior(
- p->pole[3][3], p->pole[3][2], p->pole[2][3], p->pole[3][0],
- p->pole[0][3], p->pole[0][2], p->pole[2][0], p->pole[0][0]);
- }
- else if (type == 7)
- {
- /* see control point stream order at page 330 in pdf 1.7 */
-
- p->pole[0][0] = pt[0];
- p->pole[0][1] = pt[1];
- p->pole[0][2] = pt[2];
- p->pole[0][3] = pt[3];
- p->pole[1][3] = pt[4];
- p->pole[2][3] = pt[5];
- p->pole[3][3] = pt[6];
- p->pole[3][2] = pt[7];
- p->pole[3][1] = pt[8];
- p->pole[3][0] = pt[9];
- p->pole[2][0] = pt[10];
- p->pole[1][0] = pt[11];
- p->pole[1][1] = pt[12];
- p->pole[1][2] = pt[13];
- p->pole[2][2] = pt[14];
- p->pole[2][1] = pt[15];
- }
-}
/* Sample various functions into lookup tables */
@@ -370,13 +52,11 @@ pdf_load_function_based_shading(fz_shade *shade, pdf_document *xref, pdf_obj *di
{
pdf_obj *obj;
float x0, y0, x1, y1;
+ float fv[2];
fz_matrix matrix;
- struct vertex v[4];
int xx, yy;
- float x, y;
- float xn, yn;
- int i;
fz_context *ctx = xref->ctx;
+ float *p;
x0 = y0 = 0;
x1 = y1 = 1;
@@ -393,39 +73,26 @@ pdf_load_function_based_shading(fz_shade *shade, pdf_document *xref, pdf_obj *di
obj = pdf_dict_gets(dict, "Matrix");
if (pdf_array_len(obj) == 6)
matrix = pdf_to_matrix(ctx, obj);
-
- for (yy = 0; yy < FUNSEGS; yy++)
+ shade->u.f.matrix = matrix;
+ shade->u.f.xdivs = FUNSEGS;
+ shade->u.f.ydivs = FUNSEGS;
+ shade->u.f.fn_vals = fz_malloc(ctx, (FUNSEGS+1)*(FUNSEGS+1)*shade->colorspace->n*sizeof(float));
+ shade->u.f.domain[0][0] = x0;
+ shade->u.f.domain[0][1] = y0;
+ shade->u.f.domain[1][0] = x1;
+ shade->u.f.domain[1][1] = y1;
+
+ p = shade->u.f.fn_vals;
+ for (yy = 0; yy <= FUNSEGS; yy++)
{
- y = y0 + (y1 - y0) * yy / FUNSEGS;
- yn = y0 + (y1 - y0) * (yy + 1) / FUNSEGS;
+ fv[1] = y0 + (y1 - y0) * yy / FUNSEGS;
- for (xx = 0; xx < FUNSEGS; xx++)
+ for (xx = 0; xx <= FUNSEGS; xx++)
{
- x = x0 + (x1 - x0) * xx / FUNSEGS;
- xn = x0 + (x1 - x0) * (xx + 1) / FUNSEGS;
-
- v[0].x = x; v[0].y = y;
- v[1].x = xn; v[1].y = y;
- v[2].x = xn; v[2].y = yn;
- v[3].x = x; v[3].y = yn;
+ fv[0] = x0 + (x1 - x0) * xx / FUNSEGS;
- for (i = 0; i < 4; i++)
- {
- fz_point pt;
- float fv[2];
-
- fv[0] = v[i].x;
- fv[1] = v[i].y;
- pdf_eval_function(ctx, func, fv, 2, v[i].c, shade->colorspace->n);
-
- pt.x = v[i].x;
- pt.y = v[i].y;
- pt = fz_transform_point(matrix, pt);
- v[i].x = pt.x;
- v[i].y = pt.y;
- }
-
- pdf_add_quad(ctx, shade, &v[0], &v[1], &v[2], &v[3]);
+ pdf_eval_function(ctx, func, fv, 2, p, shade->colorspace->n);
+ p += shade->colorspace->n;
}
}
}
@@ -436,15 +103,13 @@ pdf_load_axial_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, int f
pdf_obj *obj;
float d0, d1;
int e0, e1;
- float x0, y0, x1, y1;
- struct vertex p1, p2;
fz_context *ctx = xref->ctx;
obj = pdf_dict_gets(dict, "Coords");
- x0 = pdf_to_real(pdf_array_get(obj, 0));
- y0 = pdf_to_real(pdf_array_get(obj, 1));
- x1 = pdf_to_real(pdf_array_get(obj, 2));
- y1 = pdf_to_real(pdf_array_get(obj, 3));
+ shade->u.a_or_r.coords[0][0] = pdf_to_real(pdf_array_get(obj, 0));
+ shade->u.a_or_r.coords[0][1] = pdf_to_real(pdf_array_get(obj, 1));
+ shade->u.a_or_r.coords[1][0] = pdf_to_real(pdf_array_get(obj, 2));
+ shade->u.a_or_r.coords[1][1] = pdf_to_real(pdf_array_get(obj, 3));
d0 = 0;
d1 = 1;
@@ -465,20 +130,8 @@ pdf_load_axial_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, int f
pdf_sample_shade_function(ctx, shade, funcs, func, d0, d1);
- shade->type = FZ_LINEAR;
-
- shade->extend[0] = e0;
- shade->extend[1] = e1;
-
- p1.x = x0;
- p1.y = y0;
- p1.c[0] = 0;
- pdf_add_vertex(ctx, shade, &p1);
-
- p2.x = x1;
- p2.y = y1;
- p2.c[0] = 0;
- pdf_add_vertex(ctx, shade, &p2);
+ shade->u.a_or_r.extend[0] = e0;
+ shade->u.a_or_r.extend[1] = e1;
}
static void
@@ -487,17 +140,15 @@ pdf_load_radial_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, int
pdf_obj *obj;
float d0, d1;
int e0, e1;
- float x0, y0, r0, x1, y1, r1;
- struct vertex p1, p2;
fz_context *ctx = xref->ctx;
obj = pdf_dict_gets(dict, "Coords");
- x0 = pdf_to_real(pdf_array_get(obj, 0));
- y0 = pdf_to_real(pdf_array_get(obj, 1));
- r0 = pdf_to_real(pdf_array_get(obj, 2));
- x1 = pdf_to_real(pdf_array_get(obj, 3));
- y1 = pdf_to_real(pdf_array_get(obj, 4));
- r1 = pdf_to_real(pdf_array_get(obj, 5));
+ shade->u.a_or_r.coords[0][0] = pdf_to_real(pdf_array_get(obj, 0));
+ shade->u.a_or_r.coords[0][1] = pdf_to_real(pdf_array_get(obj, 1));
+ shade->u.a_or_r.coords[0][2] = pdf_to_real(pdf_array_get(obj, 2));
+ shade->u.a_or_r.coords[1][0] = pdf_to_real(pdf_array_get(obj, 3));
+ shade->u.a_or_r.coords[1][1] = pdf_to_real(pdf_array_get(obj, 4));
+ shade->u.a_or_r.coords[1][2] = pdf_to_real(pdf_array_get(obj, 5));
d0 = 0;
d1 = 1;
@@ -518,31 +169,12 @@ pdf_load_radial_shading(fz_shade *shade, pdf_document *xref, pdf_obj *dict, int
pdf_sample_shade_function(ctx, shade, funcs, func, d0, d1);
- shade->type = FZ_RADIAL;
-
- shade->extend[0] = e0;
- shade->extend[1] = e1;
-
- p1.x = x0;
- p1.y = y0;
- p1.c[0] = r0;
- pdf_add_vertex(ctx, shade, &p1);
-
- p2.x = x1;
- p2.y = y1;
- p2.c[0] = r1;
- pdf_add_vertex(ctx, shade, &p2);
+ shade->u.a_or_r.extend[0] = e0;
+ shade->u.a_or_r.extend[1] = e1;
}
/* Type 4-7 -- Triangle and patch mesh shadings */
-static inline float read_sample(fz_stream *stream, int bits, float min, float max)
-{
- /* we use pow(2,x) because (1<<x) would overflow the math on 32-bit samples */
- float bitscale = 1 / (powf(2, bits) - 1);
- return min + fz_read_bits(stream, bits) * (max - min) * bitscale;
-}
-
struct mesh_params
{
int vprow;
@@ -556,53 +188,53 @@ struct mesh_params
};
static void
-pdf_load_mesh_params(pdf_document *xref, pdf_obj *dict, struct mesh_params *p)
+pdf_load_mesh_params(fz_shade *shade, pdf_document *xref, pdf_obj *dict)
{
pdf_obj *obj;
int i, n;
- p->x0 = p->y0 = 0;
- p->x1 = p->y1 = 1;
+ shade->u.m.x0 = shade->u.m.y0 = 0;
+ shade->u.m.x1 = shade->u.m.y1 = 1;
for (i = 0; i < FZ_MAX_COLORS; i++)
{
- p->c0[i] = 0;
- p->c1[i] = 1;
+ shade->u.m.c0[i] = 0;
+ shade->u.m.c1[i] = 1;
}
- p->vprow = pdf_to_int(pdf_dict_gets(dict, "VerticesPerRow"));
- p->bpflag = pdf_to_int(pdf_dict_gets(dict, "BitsPerFlag"));
- p->bpcoord = pdf_to_int(pdf_dict_gets(dict, "BitsPerCoordinate"));
- p->bpcomp = pdf_to_int(pdf_dict_gets(dict, "BitsPerComponent"));
+ shade->u.m.vprow = pdf_to_int(pdf_dict_gets(dict, "VerticesPerRow"));
+ shade->u.m.bpflag = pdf_to_int(pdf_dict_gets(dict, "BitsPerFlag"));
+ shade->u.m.bpcoord = pdf_to_int(pdf_dict_gets(dict, "BitsPerCoordinate"));
+ shade->u.m.bpcomp = pdf_to_int(pdf_dict_gets(dict, "BitsPerComponent"));
obj = pdf_dict_gets(dict, "Decode");
if (pdf_array_len(obj) >= 6)
{
n = (pdf_array_len(obj) - 4) / 2;
- p->x0 = pdf_to_real(pdf_array_get(obj, 0));
- p->x1 = pdf_to_real(pdf_array_get(obj, 1));
- p->y0 = pdf_to_real(pdf_array_get(obj, 2));
- p->y1 = pdf_to_real(pdf_array_get(obj, 3));
+ shade->u.m.x0 = pdf_to_real(pdf_array_get(obj, 0));
+ shade->u.m.x1 = pdf_to_real(pdf_array_get(obj, 1));
+ shade->u.m.y0 = pdf_to_real(pdf_array_get(obj, 2));
+ shade->u.m.y1 = pdf_to_real(pdf_array_get(obj, 3));
for (i = 0; i < n; i++)
{
- p->c0[i] = pdf_to_real(pdf_array_get(obj, 4 + i * 2));
- p->c1[i] = pdf_to_real(pdf_array_get(obj, 5 + i * 2));
+ shade->u.m.c0[i] = pdf_to_real(pdf_array_get(obj, 4 + i * 2));
+ shade->u.m.c1[i] = pdf_to_real(pdf_array_get(obj, 5 + i * 2));
}
}
- if (p->vprow < 2)
- p->vprow = 2;
+ if (shade->u.m.vprow < 2)
+ shade->u.m.vprow = 2;
- if (p->bpflag != 2 && p->bpflag != 4 && p->bpflag != 8)
- p->bpflag = 8;
+ if (shade->u.m.bpflag != 2 && shade->u.m.bpflag != 4 && shade->u.m.bpflag != 8)
+ shade->u.m.bpflag = 8;
- if (p->bpcoord != 1 && p->bpcoord != 2 && p->bpcoord != 4 &&
- p->bpcoord != 8 && p->bpcoord != 12 && p->bpcoord != 16 &&
- p->bpcoord != 24 && p->bpcoord != 32)
- p->bpcoord = 8;
+ if (shade->u.m.bpcoord != 1 && shade->u.m.bpcoord != 2 && shade->u.m.bpcoord != 4 &&
+ shade->u.m.bpcoord != 8 && shade->u.m.bpcoord != 12 && shade->u.m.bpcoord != 16 &&
+ shade->u.m.bpcoord != 24 && shade->u.m.bpcoord != 32)
+ shade->u.m.bpcoord = 8;
- if (p->bpcomp != 1 && p->bpcomp != 2 && p->bpcomp != 4 &&
- p->bpcomp != 8 && p->bpcomp != 12 && p->bpcomp != 16)
- p->bpcomp = 8;
+ if (shade->u.m.bpcomp != 1 && shade->u.m.bpcomp != 2 && shade->u.m.bpcomp != 4 &&
+ shade->u.m.bpcomp != 8 && shade->u.m.bpcomp != 12 && shade->u.m.bpcomp != 16)
+ shade->u.m.bpcomp = 8;
}
static void
@@ -610,67 +242,15 @@ pdf_load_type4_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
int funcs, pdf_function **func)
{
fz_context *ctx = xref->ctx;
- struct mesh_params p;
- struct vertex va, vb, vc, vd;
- int ncomp;
- int flag;
- int i;
fz_stream *stream;
- pdf_load_mesh_params(xref, dict, &p);
+ pdf_load_mesh_params(shade, xref, dict);
if (funcs > 0)
- {
- ncomp = 1;
- pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]);
- }
- else
- ncomp = shade->colorspace->n;
+ pdf_sample_shade_function(ctx, shade, funcs, func, shade->u.m.c0[0], shade->u.m.c1[0]);
stream = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
-
- while (!fz_is_eof_bits(stream))
- {
- flag = fz_read_bits(stream, p.bpflag);
- vd.x = read_sample(stream, p.bpcoord, p.x0, p.x1);
- vd.y = read_sample(stream, p.bpcoord, p.y0, p.y1);
- for (i = 0; i < ncomp; i++)
- vd.c[i] = read_sample(stream, p.bpcomp, p.c0[i], p.c1[i]);
-
- switch (flag)
- {
- case 0: /* start new triangle */
- va = vd;
-
- fz_read_bits(stream, p.bpflag);
- vb.x = read_sample(stream, p.bpcoord, p.x0, p.x1);
- vb.y = read_sample(stream, p.bpcoord, p.y0, p.y1);
- for (i = 0; i < ncomp; i++)
- vb.c[i] = read_sample(stream, p.bpcomp, p.c0[i], p.c1[i]);
-
- fz_read_bits(stream, p.bpflag);
- vc.x = read_sample(stream, p.bpcoord, p.x0, p.x1);
- vc.y = read_sample(stream, p.bpcoord, p.y0, p.y1);
- for (i = 0; i < ncomp; i++)
- vc.c[i] = read_sample(stream, p.bpcomp, p.c0[i], p.c1[i]);
-
- pdf_add_triangle(ctx, shade, &va, &vb, &vc);
- break;
-
- case 1: /* Vb, Vc, Vd */
- va = vb;
- vb = vc;
- vc = vd;
- pdf_add_triangle(ctx, shade, &va, &vb, &vc);
- break;
-
- case 2: /* Va, Vc, Vd */
- vb = vc;
- vc = vd;
- pdf_add_triangle(ctx, shade, &va, &vb, &vc);
- break;
- }
- }
+ shade->buffer = fz_read_all(stream, 1024 /* FIXME */);
fz_close(stream);
}
@@ -679,50 +259,15 @@ pdf_load_type5_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
int funcs, pdf_function **func)
{
fz_context *ctx = xref->ctx;
- struct mesh_params p;
- struct vertex *buf, *ref;
- int first;
- int ncomp;
- int i, k;
fz_stream *stream;
- pdf_load_mesh_params(xref, dict, &p);
+ pdf_load_mesh_params(shade, xref, dict);
if (funcs > 0)
- {
- ncomp = 1;
- pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]);
- }
- else
- ncomp = shade->colorspace->n;
-
- ref = fz_malloc_array(ctx, p.vprow, sizeof(struct vertex));
- buf = fz_malloc_array(ctx, p.vprow, sizeof(struct vertex));
- first = 1;
+ pdf_sample_shade_function(ctx, shade, funcs, func, shade->u.m.c0[0], shade->u.m.c1[0]);
stream = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
-
- while (!fz_is_eof_bits(stream))
- {
- for (i = 0; i < p.vprow; i++)
- {
- buf[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1);
- buf[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1);
- for (k = 0; k < ncomp; k++)
- buf[i].c[k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]);
- }
-
- if (!first)
- for (i = 0; i < p.vprow - 1; i++)
- pdf_add_quad(ctx, shade,
- &ref[i], &ref[i+1], &buf[i+1], &buf[i]);
-
- memcpy(ref, buf, p.vprow * sizeof(struct vertex));
- first = 0;
- }
-
- fz_free(ctx, ref);
- fz_free(ctx, buf);
+ shade->buffer = fz_read_all(stream, 1024 /* FIXME */);
fz_close(stream);
}
@@ -733,121 +278,15 @@ pdf_load_type6_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
int funcs, pdf_function **func)
{
fz_context *ctx = xref->ctx;
- struct mesh_params p;
- int haspatch, hasprevpatch;
- float prevc[4][FZ_MAX_COLORS];
- fz_point prevp[12];
- int ncomp;
- int i, k;
fz_stream *stream;
- pdf_load_mesh_params(xref, dict, &p);
+ pdf_load_mesh_params(shade, xref, dict);
if (funcs > 0)
- {
- ncomp = 1;
- pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]);
- }
- else
- ncomp = shade->colorspace->n;
-
- hasprevpatch = 0;
+ pdf_sample_shade_function(ctx, shade, funcs, func, shade->u.m.c0[0], shade->u.m.c1[0]);
stream = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
-
- while (!fz_is_eof_bits(stream))
- {
- float c[4][FZ_MAX_COLORS];
- fz_point v[12];
- int startcolor;
- int startpt;
- int flag;
-
- flag = fz_read_bits(stream, p.bpflag);
-
- if (flag == 0)
- {
- startpt = 0;
- startcolor = 0;
- }
- else
- {
- startpt = 4;
- startcolor = 2;
- }
-
- for (i = startpt; i < 12; i++)
- {
- v[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1);
- v[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1);
- }
-
- for (i = startcolor; i < 4; i++)
- {
- for (k = 0; k < ncomp; k++)
- c[i][k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]);
- }
-
- haspatch = 0;
-
- if (flag == 0)
- {
- haspatch = 1;
- }
- else if (flag == 1 && hasprevpatch)
- {
- v[0] = prevp[3];
- v[1] = prevp[4];
- v[2] = prevp[5];
- v[3] = prevp[6];
- memcpy(c[0], prevc[1], ncomp * sizeof(float));
- memcpy(c[1], prevc[2], ncomp * sizeof(float));
-
- haspatch = 1;
- }
- else if (flag == 2 && hasprevpatch)
- {
- v[0] = prevp[6];
- v[1] = prevp[7];
- v[2] = prevp[8];
- v[3] = prevp[9];
- memcpy(c[0], prevc[2], ncomp * sizeof(float));
- memcpy(c[1], prevc[3], ncomp * sizeof(float));
-
- haspatch = 1;
- }
- else if (flag == 3 && hasprevpatch)
- {
- v[0] = prevp[ 9];
- v[1] = prevp[10];
- v[2] = prevp[11];
- v[3] = prevp[ 0];
- memcpy(c[0], prevc[3], ncomp * sizeof(float));
- memcpy(c[1], prevc[0], ncomp * sizeof(float));
-
- haspatch = 1;
- }
-
- if (haspatch)
- {
- pdf_tensor_patch patch;
-
- pdf_make_tensor_patch(&patch, 6, v);
-
- for (i = 0; i < 4; i++)
- memcpy(patch.color[i], c[i], ncomp * sizeof(float));
-
- draw_patch(ctx, shade, &patch, SUBDIV, SUBDIV);
-
- for (i = 0; i < 12; i++)
- prevp[i] = v[i];
-
- for (i = 0; i < 4; i++)
- memcpy(prevc[i], c[i], ncomp * sizeof(float));
-
- hasprevpatch = 1;
- }
- }
+ shade->buffer = fz_read_all(stream, 1024 /* FIXME */);
fz_close(stream);
}
@@ -856,121 +295,15 @@ pdf_load_type7_shade(fz_shade *shade, pdf_document *xref, pdf_obj *dict,
int funcs, pdf_function **func)
{
fz_context *ctx = xref->ctx;
- struct mesh_params p;
- int haspatch, hasprevpatch;
- float prevc[4][FZ_MAX_COLORS];
- fz_point prevp[16];
- int ncomp;
- int i, k;
fz_stream *stream;
- pdf_load_mesh_params(xref, dict, &p);
+ pdf_load_mesh_params(shade, xref, dict);
if (funcs > 0)
- {
- ncomp = 1;
- pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]);
- }
- else
- ncomp = shade->colorspace->n;
-
- hasprevpatch = 0;
+ pdf_sample_shade_function(ctx, shade, funcs, func, shade->u.m.c0[0], shade->u.m.c1[0]);
stream = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
-
- while (!fz_is_eof_bits(stream))
- {
- float c[4][FZ_MAX_COLORS];
- fz_point v[16];
- int startcolor;
- int startpt;
- int flag;
-
- flag = fz_read_bits(stream, p.bpflag);
-
- if (flag == 0)
- {
- startpt = 0;
- startcolor = 0;
- }
- else
- {
- startpt = 4;
- startcolor = 2;
- }
-
- for (i = startpt; i < 16; i++)
- {
- v[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1);
- v[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1);
- }
-
- for (i = startcolor; i < 4; i++)
- {
- for (k = 0; k < ncomp; k++)
- c[i][k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]);
- }
-
- haspatch = 0;
-
- if (flag == 0)
- {
- haspatch = 1;
- }
- else if (flag == 1 && hasprevpatch)
- {
- v[0] = prevp[3];
- v[1] = prevp[4];
- v[2] = prevp[5];
- v[3] = prevp[6];
- memcpy(c[0], prevc[1], ncomp * sizeof(float));
- memcpy(c[1], prevc[2], ncomp * sizeof(float));
-
- haspatch = 1;
- }
- else if (flag == 2 && hasprevpatch)
- {
- v[0] = prevp[6];
- v[1] = prevp[7];
- v[2] = prevp[8];
- v[3] = prevp[9];
- memcpy(c[0], prevc[2], ncomp * sizeof(float));
- memcpy(c[1], prevc[3], ncomp * sizeof(float));
-
- haspatch = 1;
- }
- else if (flag == 3 && hasprevpatch)
- {
- v[0] = prevp[ 9];
- v[1] = prevp[10];
- v[2] = prevp[11];
- v[3] = prevp[ 0];
- memcpy(c[0], prevc[3], ncomp * sizeof(float));
- memcpy(c[1], prevc[0], ncomp * sizeof(float));
-
- haspatch = 1;
- }
-
- if (haspatch)
- {
- pdf_tensor_patch patch;
-
- pdf_make_tensor_patch(&patch, 7, v);
-
- for (i = 0; i < 4; i++)
- memcpy(patch.color[i], c[i], ncomp * sizeof(float));
-
- draw_patch(ctx, shade, &patch, SUBDIV, SUBDIV);
-
- for (i = 0; i < 16; i++)
- prevp[i] = v[i];
-
- for (i = 0; i < 4; i++)
- memcpy(prevc[i], c[i], FZ_MAX_COLORS * sizeof(float));
-
- hasprevpatch = 1;
- }
- }
+ shade->buffer = fz_read_all(stream, 1024 /* FIXME */);
fz_close(stream);
}
@@ -996,17 +329,11 @@ pdf_load_shading_dict(pdf_document *xref, pdf_obj *dict, fz_matrix transform)
{
shade = fz_malloc_struct(ctx, fz_shade);
FZ_INIT_STORABLE(shade, 1, fz_free_shade_imp);
- shade->type = FZ_MESH;
+ shade->type = FZ_MESH_TYPE4;
shade->use_background = 0;
shade->use_function = 0;
shade->matrix = transform;
shade->bbox = fz_infinite_rect;
- shade->extend[0] = 0;
- shade->extend[1] = 0;
-
- shade->mesh_len = 0;
- shade->mesh_cap = 0;
- shade->mesh = NULL;
shade->colorspace = NULL;
@@ -1069,6 +396,7 @@ pdf_load_shading_dict(pdf_document *xref, pdf_obj *dict, fz_matrix transform)
}
}
+ shade->type = type;
switch (type)
{
case 1: pdf_load_function_based_shading(shade, xref, dict, func[0]); break;
@@ -1103,7 +431,9 @@ fz_shade_size(fz_shade *s)
{
if (s == NULL)
return 0;
- return sizeof(*s) + s->mesh_cap * sizeof(*s->mesh) + s->colorspace->size;
+ if (s->type != 1)
+ return sizeof(*s);
+ return sizeof(*s) + sizeof(float) * s->u.f.xdivs * s->u.f.ydivs * s->colorspace->n;
}
fz_shade *
diff --git a/xps/xps_gradient.c b/xps/xps_gradient.c
index e5699719..2d98953e 100644
--- a/xps/xps_gradient.c
+++ b/xps/xps_gradient.c
@@ -219,20 +219,17 @@ xps_draw_one_radial_gradient(xps_document *doc, fz_matrix ctm,
shade->use_background = 0;
shade->use_function = 1;
shade->type = FZ_RADIAL;
- shade->extend[0] = extend;
- shade->extend[1] = extend;
+ shade->u.a_or_r.extend[0] = extend;
+ shade->u.a_or_r.extend[1] = extend;
xps_sample_gradient_stops(shade, stops, count);
- shade->mesh_len = 6;
- shade->mesh_cap = 6;
- shade->mesh = fz_malloc_array(doc->ctx, shade->mesh_cap, sizeof(float));
- shade->mesh[0] = x0;
- shade->mesh[1] = y0;
- shade->mesh[2] = r0;
- shade->mesh[3] = x1;
- shade->mesh[4] = y1;
- shade->mesh[5] = r1;
+ shade->u.a_or_r.coords[0][0] = x0;
+ shade->u.a_or_r.coords[0][1] = y0;
+ shade->u.a_or_r.coords[0][2] = r0;
+ shade->u.a_or_r.coords[1][0] = x1;
+ shade->u.a_or_r.coords[1][1] = y1;
+ shade->u.a_or_r.coords[1][2] = r1;
fz_fill_shade(doc->dev, shade, ctm, 1);
@@ -260,20 +257,17 @@ xps_draw_one_linear_gradient(xps_document *doc, fz_matrix ctm,
shade->use_background = 0;
shade->use_function = 1;
shade->type = FZ_LINEAR;
- shade->extend[0] = extend;
- shade->extend[1] = extend;
+ shade->u.a_or_r.extend[0] = extend;
+ shade->u.a_or_r.extend[1] = extend;
xps_sample_gradient_stops(shade, stops, count);
- shade->mesh_len = 6;
- shade->mesh_cap = 6;
- shade->mesh = fz_malloc_array(doc->ctx, shade->mesh_cap, sizeof(float));
- shade->mesh[0] = x0;
- shade->mesh[1] = y0;
- shade->mesh[2] = 0;
- shade->mesh[3] = x1;
- shade->mesh[4] = y1;
- shade->mesh[5] = 0;
+ shade->u.a_or_r.coords[0][0] = x0;
+ shade->u.a_or_r.coords[0][1] = y0;
+ shade->u.a_or_r.coords[0][2] = 0;
+ shade->u.a_or_r.coords[1][0] = x1;
+ shade->u.a_or_r.coords[1][1] = y1;
+ shade->u.a_or_r.coords[1][2] = 0;
fz_fill_shade(doc->dev, shade, ctm, doc->opacity[doc->opacity_top]);