static void 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); if (funcs > 0) { ncomp = 1; pdf_sample_shade_function(ctx, shade, funcs, func, p.c0[0], p.c1[0]); } else ncomp = shade->colorspace->n; 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; } } fz_close(stream); }
static void 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); 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; 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; } } fz_close(stream); }
static void fz_mesh_type7_process(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter) { fz_stream *stream = fz_open_compressed_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); fz_transform_point(&v[i], ctm); } 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); } }
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, const fz_matrix *ctm, fz_mesh_processor *painter) { fz_stream *stream = fz_open_compressed_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); fz_transform_point(&vd->p, ctm); 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); fz_transform_point(&vb->p, ctm); 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); fz_transform_point(&vc->p, ctm); 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 int read_lzwd(fz_stream *stm, unsigned char *buf, int len) { fz_lzwd *lzw = stm->state; lzw_code *table = lzw->table; unsigned char *p = buf; unsigned char *ep = buf + len; unsigned char *s; int codelen; int code_bits = lzw->code_bits; int code = lzw->code; int old_code = lzw->old_code; int next_code = lzw->next_code; while (lzw->rp < lzw->wp && p < ep) *p++ = *lzw->rp++; while (p < ep) { if (lzw->eod) return 0; code = fz_read_bits(lzw->chain, code_bits); if (fz_is_eof_bits(lzw->chain)) { lzw->eod = 1; break; } if (code == LZW_EOD) { lzw->eod = 1; break; } if (code == LZW_CLEAR) { code_bits = MIN_BITS; next_code = LZW_FIRST; old_code = -1; continue; } /* if stream starts without a clear code, old_code is undefined... */ if (old_code == -1) { old_code = code; } else { /* add new entry to the code table */ table[next_code].prev = old_code; table[next_code].first_char = table[old_code].first_char; table[next_code].length = table[old_code].length + 1; if (code < next_code) table[next_code].value = table[code].first_char; else if (code == next_code) table[next_code].value = table[next_code].first_char; else fz_warn(stm->ctx, "out of range code encountered in lzw decode"); next_code ++; if (next_code > (1 << code_bits) - lzw->early_change - 1) { code_bits ++; if (code_bits > MAX_BITS) code_bits = MAX_BITS; /* FIXME */ } old_code = code; } /* code maps to a string, copy to output (in reverse...) */ if (code > 255) { codelen = table[code].length; lzw->rp = lzw->bp; lzw->wp = lzw->bp + codelen; assert(codelen < MAX_LENGTH); s = lzw->wp; do { *(--s) = table[code].value; code = table[code].prev; } while (code >= 0 && s > lzw->bp); } /* ... or just a single character */ else { lzw->bp[0] = code; lzw->rp = lzw->bp; lzw->wp = lzw->bp + 1; } /* copy to output */ while (lzw->rp < lzw->wp && p < ep) *p++ = *lzw->rp++; } lzw->code_bits = code_bits; lzw->code = code; lzw->old_code = old_code; lzw->next_code = next_code; return p - buf; }
static int next_lzwd(fz_context *ctx, fz_stream *stm, size_t len) { fz_lzwd *lzw = stm->state; lzw_code *table = lzw->table; unsigned char *buf = lzw->buffer; unsigned char *p = buf; unsigned char *ep; unsigned char *s; int codelen; int code_bits = lzw->code_bits; int code = lzw->code; int old_code = lzw->old_code; int next_code = lzw->next_code; if (len > sizeof(lzw->buffer)) len = sizeof(lzw->buffer); ep = buf + len; while (lzw->rp < lzw->wp && p < ep) *p++ = *lzw->rp++; while (p < ep) { if (lzw->eod) return EOF; if (lzw->reverse_bits) code = fz_read_rbits(ctx, lzw->chain, code_bits); else code = fz_read_bits(ctx, lzw->chain, code_bits); if (fz_is_eof_bits(ctx, lzw->chain)) { lzw->eod = 1; break; } if (code == LZW_EOD(lzw)) { lzw->eod = 1; break; } /* Old Tiffs are allowed to NOT send the clear code, and to * overrun at the end. */ if (!lzw->old_tiff && next_code > NUM_CODES && code != LZW_CLEAR(lzw)) { fz_warn(ctx, "missing clear code in lzw decode"); code = LZW_CLEAR(lzw); } if (code == LZW_CLEAR(lzw)) { code_bits = lzw->min_bits; next_code = LZW_FIRST(lzw); old_code = -1; continue; } /* if stream starts without a clear code, old_code is undefined... */ if (old_code == -1) { old_code = code; } else if (!lzw->old_tiff && next_code == NUM_CODES) { /* TODO: Ghostscript checks for a following clear code before tolerating */ fz_warn(ctx, "tolerating a single out of range code in lzw decode"); next_code++; } else if (code > next_code || (!lzw->old_tiff && next_code >= NUM_CODES)) { fz_warn(ctx, "out of range code encountered in lzw decode"); } else if (next_code < NUM_CODES) { /* add new entry to the code table */ table[next_code].prev = old_code; table[next_code].first_char = table[old_code].first_char; table[next_code].length = table[old_code].length + 1; if (code < next_code) table[next_code].value = table[code].first_char; else if (code == next_code) table[next_code].value = table[next_code].first_char; else fz_warn(ctx, "out of range code encountered in lzw decode"); next_code ++; if (next_code > (1 << code_bits) - lzw->early_change - 1) { code_bits ++; if (code_bits > MAX_BITS) code_bits = MAX_BITS; } old_code = code; } /* code maps to a string, copy to output (in reverse...) */ if (code >= LZW_CLEAR(lzw)) { codelen = table[code].length; lzw->rp = lzw->bp; lzw->wp = lzw->bp + codelen; assert(codelen < MAX_LENGTH); s = lzw->wp; do { *(--s) = table[code].value; code = table[code].prev; } while (code >= 0 && s > lzw->bp); } /* ... or just a single character */ else { lzw->bp[0] = code; lzw->rp = lzw->bp; lzw->wp = lzw->bp + 1; } /* copy to output */ while (lzw->rp < lzw->wp && p < ep) *p++ = *lzw->rp++; } lzw->code_bits = code_bits; lzw->code = code; lzw->old_code = old_code; lzw->next_code = next_code; stm->rp = buf; stm->wp = p; if (buf == p) return EOF; stm->pos += p - buf; return *stm->rp++; }
static void fz_process_mesh_type7(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter) { fz_stream *stream = fz_open_compressed_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 color_storage[2][4][FZ_MAX_COLORS]; fz_point point_storage[2][16]; int store = 0; int ncomp = painter->ncomp; int i, k; float (*prevc)[FZ_MAX_COLORS] = NULL; fz_point (*prevp) = NULL; fz_try(ctx) { while (!fz_is_eof_bits(ctx, stream)) { float (*c)[FZ_MAX_COLORS] = color_storage[store]; fz_point *v = point_storage[store]; int startcolor; int startpt; int flag; tensor_patch patch; flag = fz_read_bits(ctx, 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(ctx, stream, bpcoord, x0, x1); v[i].y = read_sample(ctx, stream, bpcoord, y0, y1); fz_transform_point(&v[i], ctm); } for (i = startcolor; i < 4; i++) { for (k = 0; k < ncomp; k++) c[i][k] = read_sample(ctx, stream, bpcomp, c0[k], c1[k]); } if (flag == 0) { } else if (flag == 1 && prevc) { 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)); } else if (flag == 2 && prevc) { 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)); } else if (flag == 3 && prevc) { 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)); } else continue; /* We have no patch! */ make_tensor_patch(&patch, 7, v); for (i = 0; i < 4; i++) memcpy(patch.color[i], c[i], ncomp * sizeof(float)); draw_patch(ctx, painter, &patch, SUBDIV, SUBDIV); prevp = v; prevc = c; store ^= 1; } } fz_always(ctx) { fz_drop_stream(ctx, stream); } fz_catch(ctx) { fz_rethrow(ctx); } }
static void fz_process_mesh_type4(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter) { fz_stream *stream = fz_open_compressed_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 = painter->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; float x, y, c[FZ_MAX_COLORS]; fz_try(ctx) { while (!fz_is_eof_bits(ctx, stream)) { flag = fz_read_bits(ctx, stream, bpflag); x = read_sample(ctx, stream, bpcoord, x0, x1); y = read_sample(ctx, stream, bpcoord, y0, y1); for (i = 0; i < ncomp; i++) c[i] = read_sample(ctx, stream, bpcomp, c0[i], c1[i]); fz_prepare_vertex(ctx, painter, vd, ctm, x, y, c); switch (flag) { case 0: /* start new triangle */ SWAP(va, vd); fz_read_bits(ctx, stream, bpflag); x = read_sample(ctx, stream, bpcoord, x0, x1); y = read_sample(ctx, stream, bpcoord, y0, y1); for (i = 0; i < ncomp; i++) c[i] = read_sample(ctx, stream, bpcomp, c0[i], c1[i]); fz_prepare_vertex(ctx, painter, vb, ctm, x, y, c); fz_read_bits(ctx, stream, bpflag); x = read_sample(ctx, stream, bpcoord, x0, x1); y = read_sample(ctx, stream, bpcoord, y0, y1); for (i = 0; i < ncomp; i++) c[i] = read_sample(ctx, stream, bpcomp, c0[i], c1[i]); fz_prepare_vertex(ctx, painter, vc, ctm, x, y, c); paint_tri(ctx, painter, va, vb, vc); break; case 1: /* Vb, Vc, Vd */ SWAP(va, vb); SWAP(vb, vc); SWAP(vc, vd); paint_tri(ctx, painter, va, vb, vc); break; case 2: /* Va, Vc, Vd */ SWAP(vb, vc); SWAP(vc, vd); paint_tri(ctx, painter, va, vb, vc); break; } } } fz_always(ctx) { fz_drop_stream(ctx, stream); } fz_catch(ctx) { fz_rethrow(ctx); } }