diff options
-rw-r--r-- | draw/draw_mesh.c | 106 | ||||
-rw-r--r-- | fitz/fitz-internal.h | 69 | ||||
-rw-r--r-- | fitz/res_shade.c | 855 | ||||
-rw-r--r-- | pdf/pdf_shade.c | 822 | ||||
-rw-r--r-- | xps/xps_gradient.c | 38 |
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, <ri[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]); |