reactos/rosapps/smartpdf/fitz/mupdf/pdf_shade4.c
Daniel Reimer a7fddf9c07 Delete all Trailing spaces in code.
svn path=/trunk/; revision=29689
2007-10-19 23:05:02 +00:00

796 lines
18 KiB
C

#include <fitz.h>
#include <mupdf.h>
/* this mess is jeong's */
typedef struct pdf_tensorpatch_s pdf_tensorpatch;
struct pdf_tensorpatch_s {
fz_point pole[4][4];
float color[4][FZ_MAXCOLORS];
};
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;
}
static int
getdata(fz_stream *stream, int bps)
{
unsigned int bitmask = (1 << bps) - 1;
unsigned int buf = 0;
int bits = 0;
int s;
while (bits < bps)
{
buf = (buf << 8) | (fz_readbyte(stream) & 0xff);
bits += 8;
}
s = buf >> (bits - bps);
if (bps < 32)
s = s & bitmask;
bits -= bps;
return s;
}
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;
}
#define SEGMENTATION_DEPTH 2
static inline void copyvert(float *dst, float *src, int n)
{
while (n--)
*dst++ = *src++;
}
static inline void copycolor(float *c, const float *s)
{
int i;
for (i = 0; i<FZ_MAXCOLORS; ++i)
c[i] = s[i];
}
static inline void midcolor(float *c, const float *c1, const float *c2)
{
int i;
for (i = 0; i<FZ_MAXCOLORS; ++i)
c[i] = (float)((c1[i] + c2[i]) / 2.0);
}
static void
filltensorinterior(pdf_tensorpatch *p)
{
#define lcp1(p0, p3)\
((p0 + p0 + p3) / 3.0f)
#define lcp2(p0, p3)\
((p0 + p3 + p3) / 3.0f)
p->pole[1][1].x = lcp1(p->pole[0][1].x, p->pole[3][1].x) +
lcp1(p->pole[1][0].x, p->pole[1][3].x) -
lcp1(lcp1(p->pole[0][0].x, p->pole[0][3].x),
lcp1(p->pole[3][0].x, p->pole[3][3].x));
p->pole[1][2].x = lcp1(p->pole[0][2].x, p->pole[3][2].x) +
lcp2(p->pole[1][0].x, p->pole[1][3].x) -
lcp1(lcp2(p->pole[0][0].x, p->pole[0][3].x),
lcp2(p->pole[3][0].x, p->pole[3][3].x));
p->pole[2][1].x = lcp2(p->pole[0][1].x, p->pole[3][1].x) +
lcp1(p->pole[2][0].x, p->pole[2][3].x) -
lcp2(lcp1(p->pole[0][0].x, p->pole[0][3].x),
lcp1(p->pole[3][0].x, p->pole[3][3].x));
p->pole[2][2].x = lcp2(p->pole[0][2].x, p->pole[3][2].x) +
lcp2(p->pole[2][0].x, p->pole[2][3].x) -
lcp2(lcp2(p->pole[0][0].x, p->pole[0][3].x),
lcp2(p->pole[3][0].x, p->pole[3][3].x));
p->pole[1][1].y = lcp1(p->pole[0][1].y, p->pole[3][1].y) +
lcp1(p->pole[1][0].y, p->pole[1][3].y) -
lcp1(lcp1(p->pole[0][0].y, p->pole[0][3].y),
lcp1(p->pole[3][0].y, p->pole[3][3].y));
p->pole[1][2].y = lcp1(p->pole[0][2].y, p->pole[3][2].y) +
lcp2(p->pole[1][0].y, p->pole[1][3].y) -
lcp1(lcp2(p->pole[0][0].y, p->pole[0][3].y),
lcp2(p->pole[3][0].y, p->pole[3][3].y));
p->pole[2][1].y = lcp2(p->pole[0][1].y, p->pole[3][1].y) +
lcp1(p->pole[2][0].y, p->pole[2][3].y) -
lcp2(lcp1(p->pole[0][0].y, p->pole[0][3].y),
lcp1(p->pole[3][0].y, p->pole[3][3].y));
p->pole[2][2].y = lcp2(p->pole[0][2].y, p->pole[3][2].y) +
lcp2(p->pole[2][0].y, p->pole[2][3].y) -
lcp2(lcp2(p->pole[0][0].y, p->pole[0][3].y),
lcp2(p->pole[3][0].y, p->pole[3][3].y));
#undef lcp1
#undef lcp2
}
static void
split_curve_s(const fz_point *pole, fz_point *q0, fz_point *q1, int pole_step)
{
#define midpoint(a,b)\
((a)/2.0f + (b)/2.0f) // to avoid overflow
float x12 = midpoint(pole[1 * pole_step].x, pole[2 * pole_step].x);
float y12 = midpoint(pole[1 * pole_step].y, pole[2 * pole_step].y);
q0[1 * pole_step].x = midpoint(pole[0 * pole_step].x, pole[1 * pole_step].x);
q0[1 * pole_step].y = midpoint(pole[0 * pole_step].y, pole[1 * pole_step].y);
q1[2 * pole_step].x = midpoint(pole[2 * pole_step].x, pole[3 * pole_step].x);
q1[2 * pole_step].y = midpoint(pole[2 * pole_step].y, pole[3 * pole_step].y);
q0[2 * pole_step].x = midpoint(q0[1 * pole_step].x, x12);
q0[2 * pole_step].y = midpoint(q0[1 * pole_step].y, y12);
q1[1 * pole_step].x = midpoint(x12, q1[2 * pole_step].x);
q1[1 * pole_step].y = midpoint(y12, q1[2 * pole_step].y);
q0[0 * pole_step].x = pole[0 * pole_step].x;
q0[0 * pole_step].y = pole[0 * pole_step].y;
q0[3 * pole_step].x = q1[0 * pole_step].x = midpoint(q0[2 * pole_step].x, q1[1 * pole_step].x);
q0[3 * pole_step].y = q1[0 * pole_step].y = midpoint(q0[2 * pole_step].y, q1[1 * pole_step].y);
q1[3 * pole_step].x = pole[3 * pole_step].x;
q1[3 * pole_step].y = pole[3 * pole_step].y;
#undef midpoint
}
static inline void
split_patch(pdf_tensorpatch *s0, pdf_tensorpatch *s1, const pdf_tensorpatch *p)
{
split_curve_s(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
split_curve_s(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
split_curve_s(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
split_curve_s(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
copycolor(s0->color[0], p->color[0]);
midcolor(s0->color[1], p->color[0], p->color[1]);
midcolor(s0->color[2], p->color[2], p->color[3]);
copycolor(s0->color[3], p->color[3]);
copycolor(s1->color[0], s0->color[1]);
copycolor(s1->color[1], p->color[1]);
copycolor(s1->color[2], p->color[2]);
copycolor(s1->color[3], s0->color[2]);
}
static inline void
split_stripe(pdf_tensorpatch *s0, pdf_tensorpatch *s1, const pdf_tensorpatch *p)
{
split_curve_s(p->pole[0], s0->pole[0], s1->pole[0], 1);
split_curve_s(p->pole[1], s0->pole[1], s1->pole[1], 1);
split_curve_s(p->pole[2], s0->pole[2], s1->pole[2], 1);
split_curve_s(p->pole[3], s0->pole[3], s1->pole[3], 1);
copycolor(s0->color[0], p->color[0]);
copycolor(s0->color[1], p->color[1]);
midcolor(s0->color[2], p->color[1], p->color[2]);
midcolor(s0->color[3], p->color[0], p->color[3]);
copycolor(s1->color[0], s0->color[3]);
copycolor(s1->color[1], s0->color[2]);
copycolor(s1->color[2], p->color[2]);
copycolor(s1->color[3], p->color[3]);
}
static fz_error *
growshademesh(fz_shade *shade, int amount)
{
float *newmesh;
int newcap;
newcap = shade->meshcap + amount;
newmesh = fz_realloc(shade->mesh, sizeof(float) * newcap);
if (!newmesh)
return fz_outofmem;
shade->mesh = newmesh;
shade->meshcap = newcap;
return nil;
}
static inline int setvertex(float *mesh, fz_point pt, float *color, int ptr, int ncomp)
{
int i;
mesh[ptr++] = pt.x;
mesh[ptr++] = pt.y;
for (i=0; i < ncomp; ++i) {
mesh[ptr++] = color[i];
}
return ptr;
}
static int
triangulatepatch(pdf_tensorpatch p, fz_shade *shade, int ptr, int ncomp)
{
fz_error* error;
ptr = setvertex(shade->mesh, p.pole[0][0], p.color[0], ptr, ncomp);
ptr = setvertex(shade->mesh, p.pole[3][0], p.color[1], ptr, ncomp);
ptr = setvertex(shade->mesh, p.pole[3][3], p.color[2], ptr, ncomp);
ptr = setvertex(shade->mesh, p.pole[0][0], p.color[0], ptr, ncomp);
ptr = setvertex(shade->mesh, p.pole[3][3], p.color[2], ptr, ncomp);
ptr = setvertex(shade->mesh, p.pole[0][3], p.color[3], ptr, ncomp);
if (shade->meshcap - 1024 < ptr) {
error = growshademesh(shade, 1024);
if (error) goto cleanup;
}
return ptr;
cleanup:
// error handling
return -1;
}
static int
drawstripe(pdf_tensorpatch patch, fz_shade *shade, int ptr, int ncomp, int depth)
{
pdf_tensorpatch s0, s1;
split_stripe(&s0, &s1, &patch);
depth++;
if (depth >= SEGMENTATION_DEPTH)
{
ptr = triangulatepatch(s0, shade, ptr, ncomp);
ptr = triangulatepatch(s1, shade, ptr, ncomp);
}
else {
ptr = drawstripe(s0, shade, ptr, ncomp, depth);
ptr = drawstripe(s1, shade, ptr, ncomp, depth);
}
return ptr;
}
static int
drawpatch(pdf_tensorpatch patch, fz_shade *shade, int ptr, int ncomp, int depth)
{
pdf_tensorpatch s0, s1;
split_patch(&s0, &s1, &patch);
depth++;
if (depth > SEGMENTATION_DEPTH)
{
ptr = drawstripe(s0, shade, ptr, ncomp, 0);
ptr = drawstripe(s1, shade, ptr, ncomp, 0);
}
else {
ptr = drawpatch(s0, shade, ptr, ncomp, depth);
ptr = drawpatch(s1, shade, ptr, ncomp, depth);
}
return ptr;
}
fz_error *
pdf_loadtype6shade(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;
fz_point p0, p1;
float c0[FZ_MAXCOLORS];
float c1[FZ_MAXCOLORS];
int i, n, j;
unsigned int t;
int flag;
fz_point p[12];
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");
p0.x = fz_toreal(fz_arrayget(obj, 0));
p1.x = fz_toreal(fz_arrayget(obj, 1));
p0.y = fz_toreal(fz_arrayget(obj, 2));
p1.y = 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 < 12; ++i) {
t = getdata(stream, bpcoord);
p[i].x = (float)(p0.x + (t * (p1.x - p0.x) / (pow(2, bpcoord) - 1.)));
t = getdata(stream, bpcoord);
p[i].y = (float)(p0.y + (t * (p1.y - p0.y) / (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[1][0] = p[1];
patch.pole[2][0] = p[2];
patch.pole[3][0] = p[3];
patch.pole[3][1] = p[4];
patch.pole[3][2] = p[5];
patch.pole[3][3] = p[6];
patch.pole[2][3] = p[7];
patch.pole[1][3] = p[8];
patch.pole[0][3] = p[9];
patch.pole[0][2] = p[10];
patch.pole[0][1] = p[11];
filltensorinterior(&patch);
j = drawpatch(patch, shade, j, ncomp, 0);
}
fz_dropstream(stream);
shade->meshlen = j / n / 3;
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;
}