static fz_error * loadshadedict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_matrix matrix) { fz_error *error; fz_shade *shade; fz_obj *obj; int type; int i; pdf_logshade("load shade dict %d %d {\n", fz_tonum(ref), fz_togen(ref)); shade = fz_malloc(sizeof(fz_shade)); if (!shade) return fz_outofmem; shade->refs = 1; shade->usebackground = 0; shade->usefunction = 0; shade->matrix = matrix; shade->bbox = fz_infiniterect; shade->meshlen = 0; shade->meshcap = 0; shade->mesh = nil; obj = fz_dictgets(dict, "ShadingType"); type = fz_toint(obj); pdf_logshade("type %d\n", type); /* TODO: flatten indexed... */ obj = fz_dictgets(dict, "ColorSpace"); if (obj) { shade->cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj); if (shade->cs) fz_keepcolorspace(shade->cs); else { error = pdf_resolve(&obj, xref); if (error) return error; error = pdf_loadcolorspace(&shade->cs, xref, obj); if (error) return error; fz_dropobj(obj); } } pdf_logshade("colorspace %s\n", shade->cs->name); obj = fz_dictgets(dict, "Background"); if (obj) { pdf_logshade("background\n"); shade->usebackground = 1; for (i = 0; i < shade->cs->n; i++) shade->background[i] = fz_toreal(fz_arrayget(obj, i)); } obj = fz_dictgets(dict, "BBox"); if (fz_isarray(obj)) { shade->bbox = pdf_torect(obj); pdf_logshade("bbox [%g %g %g %g]\n", shade->bbox.x0, shade->bbox.y0, shade->bbox.x1, shade->bbox.y1); } switch(type) { case 1: error = pdf_loadtype1shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 2: error = pdf_loadtype2shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 3: error = pdf_loadtype3shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 4: error = pdf_loadtype4shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 5: error = pdf_loadtype5shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 6: error = pdf_loadtype6shade(shade, xref, dict, ref); if (error) goto cleanup; break; case 7: error = pdf_loadtype7shade(shade, xref, dict, ref); if (error) goto cleanup; break; default: fz_warn("syntaxerror: unknown shading type: %d", type); break; }; pdf_logshade("}\n"); *shadep = shade; return nil; cleanup: fz_dropshade(shade); return error; }
fz_error * pdf_loadshade(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { fz_error *error; fz_matrix mat; fz_obj *obj; fz_obj *shd; if ((*shadep = pdf_finditem(xref->store, PDF_KSHADE, ref))) return nil; /* * Type 2 pattern dictionary */ if (fz_dictgets(dict, "PatternType")) { pdf_logshade("load shade pattern %d %d {\n", fz_tonum(ref), fz_togen(ref)); obj = fz_dictgets(dict, "Matrix"); if (obj) { mat = pdf_tomatrix(obj); pdf_logshade("matrix [%g %g %g %g %g %g]\n", mat.a, mat.b, mat.c, mat.d, mat.e, mat.f); } else { mat = fz_identity(); } obj = fz_dictgets(dict, "ExtGState"); if (obj) { pdf_logshade("extgstate ...\n"); } obj = fz_dictgets(dict, "Shading"); if (!obj) return fz_throw("syntaxerror: missing shading dictionary"); shd = obj; error = pdf_resolve(&shd, xref); if (error) return error; error = loadshadedict(shadep, xref, shd, obj, mat); fz_dropobj(shd); if (error) return error; pdf_logshade("}\n"); } /* * Naked shading dictionary */ else { error = loadshadedict(shadep, xref, dict, ref, fz_identity()); if (error) return error; } error = pdf_storeitem(xref->store, PDF_KSHADE, ref, *shadep); if (error) { fz_dropshade(*shadep); return error; } return nil; }
fz_error * pdf_loadtype5shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref) { fz_error *error; fz_stream *stream; fz_obj *obj; int bpcoord; int bpcomp; int vpr, vpc; int ncomp; float x0, x1, y0, y1; float c0[FZ_MAXCOLORS]; float c1[FZ_MAXCOLORS]; int i, n, j; int p, q; unsigned int t; float *x, *y, *c[FZ_MAXCOLORS]; error = nil; ncomp = shade->cs->n; bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate")); bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent")); vpr = fz_toint(fz_dictgets(shading, "VerticesPerRow")); if (vpr < 2) { error = fz_throw("VerticesPerRow must be greater than or equal to 2"); goto cleanup; } obj = fz_dictgets(shading, "Decode"); if (fz_isarray(obj)) { pdf_logshade("decode array\n"); x0 = fz_toreal(fz_arrayget(obj, 0)); x1 = fz_toreal(fz_arrayget(obj, 1)); y0 = fz_toreal(fz_arrayget(obj, 2)); y1 = fz_toreal(fz_arrayget(obj, 3)); for (i=0; i < fz_arraylen(obj) / 2; ++i) { c0[i] = fz_toreal(fz_arrayget(obj, i*2+4)); c1[i] = fz_toreal(fz_arrayget(obj, i*2+5)); } } else { error = fz_throw("syntaxerror: No Decode key in Type 4 Shade"); goto cleanup; } obj = fz_dictgets(shading, "Function"); if (obj) { ncomp = 1; pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]); shade->usefunction = 1; } else shade->usefunction = 0; n = 2 + shade->cs->n; j = 0; #define BIGNUM 1024 x = fz_malloc(sizeof(float) * vpr * BIGNUM); y = fz_malloc(sizeof(float) * vpr * BIGNUM); for (i = 0; i < ncomp; ++i) { c[i] = fz_malloc(sizeof(float) * vpr * BIGNUM); } q = 0; error = pdf_openstream(&stream, xref, fz_tonum(ref), fz_togen(ref)); if (error) goto cleanup; while (fz_peekbyte(stream) != EOF) { for (p = 0; p < vpr; ++p) { int idx; idx = q * vpr + p; t = getdata(stream, bpcoord); x[idx] = x0 + (t * (x1 - x0) / ((float)pow(2, bpcoord) - 1)); t = getdata(stream, bpcoord); y[idx] = y0 + (t * (y1 - y0) / ((float)pow(2, bpcoord) - 1)); for (i=0; i < ncomp; ++i) { t = getdata(stream, bpcomp); c[i][idx] = c0[i] + (t * (c1[i] - c0[i]) / (float)(pow(2, bpcomp) - 1)); } } q++; } fz_dropstream(stream); #define ADD_VERTEX(idx) \ {\ int z;\ shade->mesh[j++] = x[idx];\ shade->mesh[j++] = y[idx];\ for (z = 0; z < shade->cs->n; ++z) {\ shade->mesh[j++] = c[z][idx];\ }\ }\ vpc = q; shade->meshcap = 0; shade->mesh = fz_malloc(sizeof(float) * 1024); if (!shade) { error = fz_outofmem; goto cleanup; } j = 0; for (p = 0; p < vpr-1; ++p) { for (q = 0; q < vpc-1; ++q) { ADD_VERTEX(q * vpr + p); ADD_VERTEX(q * vpr + p + 1); ADD_VERTEX((q + 1) * vpr + p + 1); ADD_VERTEX(q * vpr + p); ADD_VERTEX((q + 1) * vpr + p + 1); ADD_VERTEX((q + 1) * vpr + p); } } shade->meshlen = j / n / 3; fz_free(x); fz_free(y); for (i = 0; i < ncomp; ++i) { fz_free(c[i]); } cleanup: return nil; }
fz_error * pdf_loadtype7shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref) { fz_error *error; fz_stream *stream; fz_obj *obj; int bpcoord; int bpcomp; int bpflag; int ncomp; float x0, x1, y0, y1; float c0[FZ_MAXCOLORS]; float c1[FZ_MAXCOLORS]; int i, n, j; unsigned int t; int flag; fz_point p[16]; pdf_tensorpatch patch; error = nil; ncomp = shade->cs->n; bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate")); bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent")); bpflag = fz_toint(fz_dictgets(shading, "BitsPerFlag")); obj = fz_dictgets(shading, "Decode"); if (fz_isarray(obj)) { pdf_logshade("decode array\n"); x0 = fz_toreal(fz_arrayget(obj, 0)); x1 = fz_toreal(fz_arrayget(obj, 1)); y0 = fz_toreal(fz_arrayget(obj, 2)); y1 = fz_toreal(fz_arrayget(obj, 3)); for (i=0; i < fz_arraylen(obj) / 2; ++i) { c0[i] = fz_toreal(fz_arrayget(obj, i*2+4)); c1[i] = fz_toreal(fz_arrayget(obj, i*2+5)); } } else { error = fz_throw("syntaxerror: No Decode key in Type 6 Shade"); goto cleanup; } obj = fz_dictgets(shading, "Function"); if (obj) { ncomp = 1; pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]); shade->usefunction = 1; } else shade->usefunction = 0; shade->meshcap = 0; shade->mesh = nil; error = growshademesh(shade, 1024); if (error) goto cleanup; n = 2 + shade->cs->n; j = 0; error = pdf_openstream(&stream, xref, fz_tonum(ref), fz_togen(ref)); if (error) goto cleanup; while (fz_peekbyte(stream) != EOF) { flag = getdata(stream, bpflag); for (i = 0; i < 16; ++i) { t = getdata(stream, bpcoord); p[i].x = x0 + (t * (x1 - x0) / (pow(2, bpcoord) - 1.)); t = getdata(stream, bpcoord); p[i].y = y0 + (t * (y1 - y0) / (pow(2, bpcoord) - 1.)); } for (i = 0; i < 4; ++i) { int k; for (k=0; k < ncomp; ++k) { t = getdata(stream, bpcomp); patch.color[i][k] = c0[k] + (t * (c1[k] - c0[k]) / (pow(2, bpcomp) - 1.0f)); } } patch.pole[0][0] = p[0]; patch.pole[0][1] = p[1]; patch.pole[0][2] = p[2]; patch.pole[0][3] = p[3]; patch.pole[1][3] = p[4]; patch.pole[2][3] = p[5]; patch.pole[3][3] = p[6]; patch.pole[3][2] = p[7]; patch.pole[3][1] = p[8]; patch.pole[3][0] = p[9]; patch.pole[2][0] = p[10]; patch.pole[1][0] = p[11]; patch.pole[1][1] = p[12]; patch.pole[1][2] = p[13]; patch.pole[2][2] = p[14]; patch.pole[2][1] = p[15]; j = drawpatch(patch, shade, j, ncomp, 0); } fz_dropstream(stream); shade->meshlen = j / n / 3; cleanup: return nil; }
fz_error * pdf_loadtype4shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref) { fz_error *error; fz_obj *obj; int bpcoord; int bpcomp; int bpflag; int ncomp; float x0, x1, y0, y1; float c0[FZ_MAXCOLORS]; float c1[FZ_MAXCOLORS]; int i, z; int bitspervertex; int bytepervertex; fz_buffer *buf; int n; int j; float cval[16]; int flag; unsigned int t; float x, y; error = nil; ncomp = shade->cs->n; bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate")); bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent")); bpflag = fz_toint(fz_dictgets(shading, "BitsPerFlag")); obj = fz_dictgets(shading, "Decode"); if (fz_isarray(obj)) { pdf_logshade("decode array\n"); x0 = fz_toreal(fz_arrayget(obj, 0)); x1 = fz_toreal(fz_arrayget(obj, 1)); y0 = fz_toreal(fz_arrayget(obj, 2)); y1 = fz_toreal(fz_arrayget(obj, 3)); for (i=0; i < fz_arraylen(obj) / 2; ++i) { c0[i] = fz_toreal(fz_arrayget(obj, i*2+4)); c1[i] = fz_toreal(fz_arrayget(obj, i*2+5)); } } else { error = fz_throw("syntaxerror: No Decode key in Type 4 Shade"); goto cleanup; } obj = fz_dictgets(shading, "Function"); if (obj) { ncomp = 1; pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]); } bitspervertex = bpflag + bpcoord * 2 + bpcomp * ncomp; bytepervertex = (bitspervertex+7) / 8; error = pdf_loadstream(&buf, xref, fz_tonum(ref), fz_togen(ref)); if (error) goto cleanup; shade->usefunction = 0; n = 2 + shade->cs->n; j = 0; for (z = 0; z < (buf->ep - buf->bp) / bytepervertex; ++z) { flag = *buf->rp++; t = *buf->rp++; t = (t << 8) + *buf->rp++; t = (t << 8) + *buf->rp++; x = x0 + (t * (x1 - x0) / (pow(2, 24) - 1)); t = *buf->rp++; t = (t << 8) + *buf->rp++; t = (t << 8) + *buf->rp++; y = y0 + (t * (y1 - y0) / (pow(2, 24) - 1)); for (i=0; i < ncomp; ++i) { t = *buf->rp++; t = (t << 8) + *buf->rp++; } if (flag == 0) { j += n; } if (flag == 1 || flag == 2) { j += 3 * n; } } buf->rp = buf->bp; shade->mesh = (float*) malloc(sizeof(float) * j); /* 8, 24, 16 only */ j = 0; for (z = 0; z < (buf->ep - buf->bp) / bytepervertex; ++z) { flag = *buf->rp++; t = *buf->rp++; t = (t << 8) + *buf->rp++; t = (t << 8) + *buf->rp++; x = x0 + (t * (x1 - x0) / (pow(2, 24) - 1)); t = *buf->rp++; t = (t << 8) + *buf->rp++; t = (t << 8) + *buf->rp++; y = y0 + (t * (y1 - y0) / (pow(2, 24) - 1)); for (i=0; i < ncomp; ++i) { t = *buf->rp++; t = (t << 8) + *buf->rp++; cval[i] = t / (double)(pow(2, 16) - 1); } if (flag == 0) { shade->mesh[j++] = x; shade->mesh[j++] = y; for (i=0; i < ncomp; ++i) { shade->mesh[j++] = cval[i]; } } if (flag == 1) { memcpy(&(shade->mesh[j]), &(shade->mesh[j - 2 * n]), n * sizeof(float)); memcpy(&(shade->mesh[j + 1 * n]), &(shade->mesh[j - 1 * n]), n * sizeof(float)); j+= 2 * n; shade->mesh[j++] = x; shade->mesh[j++] = y; for (i=0; i < ncomp; ++i) { shade->mesh[j++] = cval[i]; } } if (flag == 2) { memcpy(&(shade->mesh[j]), &(shade->mesh[j - 3 * n]), n * sizeof(float)); memcpy(&(shade->mesh[j + 1 * n]), &(shade->mesh[j - 1 * n]), n * sizeof(float)); j+= 2 * n; shade->mesh[j++] = x; shade->mesh[j++] = y; for (i=0; i < ncomp; ++i) { shade->mesh[j++] = cval[i]; } } } shade->meshlen = j / n / 3; fz_dropbuffer(buf); cleanup: return nil; }