diff options
-rw-r--r-- | include/mupdf/rsrc.h | 2 | ||||
-rw-r--r-- | mupdf/debug.c | 2 | ||||
-rw-r--r-- | mupdf/function.c | 2122 | ||||
-rw-r--r-- | mupdf/shade.c | 2 | ||||
-rw-r--r-- | render/meshdraw.c | 9 | ||||
-rw-r--r-- | render/render.c | 2 |
6 files changed, 1039 insertions, 1100 deletions
diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h index 82a201c9..328a483b 100644 --- a/include/mupdf/rsrc.h +++ b/include/mupdf/rsrc.h @@ -189,7 +189,7 @@ struct pdf_font_s fz_error *pdf_parsecmap(fz_cmap **cmapp, fz_file *file); fz_error *pdf_loadembeddedcmap(fz_cmap **cmapp, pdf_xref *xref, fz_obj *ref); fz_error *pdf_loadsystemcmap(fz_cmap **cmapp, char *name); -fz_error *pdf_makeidentitycmap(fz_cmap **cmapp, int wmode, int bytes); // XXX +fz_error *pdf_makeidentitycmap(fz_cmap **cmapp, int wmode, int bytes); /* unicode.c */ fz_error *pdf_loadtounicode(pdf_font *font, pdf_xref *xref, char **strings, char *collection, fz_obj *cmapstm); diff --git a/mupdf/debug.c b/mupdf/debug.c index d51fa476..e44a23d2 100644 --- a/mupdf/debug.c +++ b/mupdf/debug.c @@ -16,7 +16,7 @@ enum PDF_LFONT = 4, PDF_LIMAGE = 8, PDF_LSHADE = 16, - PDF_LPAGE = 32, + PDF_LPAGE = 32 }; static inline void pdflog(int tag, char *name, char *fmt, va_list ap) diff --git a/mupdf/function.c b/mupdf/function.c index 84431e8c..86e8f8bc 100644 --- a/mupdf/function.c +++ b/mupdf/function.c @@ -1,222 +1,125 @@ #include <fitz.h> #include <mupdf.h> -#define index psindex /* collide with string.h index() */ +/* author: seokgyo@gmail.com */ + +enum +{ + MAXN = FZ_MAXCOLORS, + MAXM = FZ_MAXCOLORS, + MAXK = 32 +}; typedef struct psobj_s psobj; +enum +{ + SAMPLE = 0, + EXPONENTIAL = 2, + STITCHING = 3, + POSTSCRIPT = 4 +}; + struct pdf_function_s { int refs; int type; /* 0=sample 2=exponential 3=stitching 4=postscript */ int m; /* number of input values */ int n; /* number of output values */ - float *domain; /* even index : min value, odd index : max value */ - float *range; /* even index : min value, odd index : max value */ + float domain[MAXM][2]; /* even index : min value, odd index : max value */ + float range[MAXN][2]; /* even index : min value, odd index : max value */ + int hasrange; + union { struct { unsigned short bps; - unsigned short order; - int *size; /* the num of samples in each input dimension */ - float *encode; - float *decode; + int size[MAXM]; + float encode[MAXM][2]; + float decode[MAXN][2]; int *samples; } sa; + struct { float n; - float *c0; - float *c1; + float c0[MAXN]; + float c1[MAXN]; } e; + struct { int k; - pdf_function **funcs; - float *bounds; - float *encode; + pdf_function *funcs[MAXK]; + float bounds[MAXK-1]; + float encode[MAXK][2]; } st; + struct { psobj *code; int cap; } p; - }u; -}; - -struct psobj_s -{ - unsigned short type; - union { - int b; /* boolean (stack only) */ - int i; /* integer (stack and code) */ - float f; /* real (stack and code) */ - int op; /* operator (code only) */ - int blk; /* if/ifelse block pointer (code only) */ } u; }; -#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0]) - -#define MIN_MAX(a,min,max) \ - if(a < (min)) a = (min);\ -else if(a > (max)) a = (max); - -#define INTERPOLATE(x,xmin,xmax,ymin,ymax) \ -(ymin) + ((x)-(xmin)) * ((ymax)-(ymin)) / ((xmax) - (xmin)); - -#define SAFE_PUSHINT(st,a)\ - {error = pushint(st,a);\ - if(error) goto cleanup;} - -#define SAFE_PUSHREAL(st,a)\ - {error = pushreal(st,a);\ - if(error) goto cleanup;} - -#define SAFE_PUSHBOOL(st,a)\ - {error = pushbool(st,a);\ - if(error) goto cleanup;} - -#define SAFE_POPINT(st,a)\ - {error = popint(st,a);\ - if(error) goto cleanup;} - -#define SAFE_POPNUM(st,a)\ - {error = popnum(st,a);\ - if(error) goto cleanup;} - -#define SAFE_POPBOOL(st,a)\ - {error = popbool(st,a);\ - if(error) goto cleanup;} - -#define SAFE_POP(st)\ - {error = pop(st);\ - if(error) goto cleanup;} +#define RADIAN 57.2957795 -#define SAFE_INDEX(st,i)\ - {error = index(st,i);\ - if(error) goto cleanup;} +#define LERP(x, xmin, xmax, ymin, ymax) \ + (ymin) + ((x) - (xmin)) * ((ymax) - (ymin)) / ((xmax) - (xmin)) -#define SAFE_COPY(st,n)\ - {error = copy(st,n);\ - if(error) goto cleanup;} +#define SAFE_PUSHINT(st, a) {error = pspushint(st, a); if (error) goto cleanup;} +#define SAFE_PUSHREAL(st, a) {error = pspushreal(st, a); if (error) goto cleanup;} +#define SAFE_PUSHBOOL(st, a) {error = pspushbool(st, a); if (error) goto cleanup;} +#define SAFE_POPINT(st, a) {error = pspopint(st, a); if (error) goto cleanup;} +#define SAFE_POPNUM(st, a) {error = pspopnum(st, a); if (error) goto cleanup;} +#define SAFE_POPBOOL(st, a) {error = pspopbool(st, a); if (error) goto cleanup;} +#define SAFE_POP(st) {error = pspop(st); if (error) goto cleanup;} +#define SAFE_INDEX(st, i) {error = psindex(st, i); if (error) goto cleanup;} +#define SAFE_COPY(st, n) {error = pscopy(st, n); if (error) goto cleanup;} -#define RADIAN 57.2957795 +enum { PSBOOL, PSINT, PSREAL, PSOPERATOR, PSBLOCK }; -enum pdf_funckind_e +enum { - PDF_FUNC_SAMPLE = 0, - PDF_FUNC_EXPONENTIAL = 2, - PDF_FUNC_STITCHING = 3, - PDF_FUNC_POSTSCRIPT = 4 + PSOABS, PSOADD, PSOAND, PSOATAN, PSOBITSHIFT, PSOCEILING, + PSOCOPY, PSOCOS, PSOCVI, PSOCVR, PSODIV, PSODUP, PSOEQ, + PSOEXCH, PSOEXP, PSOFALSE, PSOFLOOR, PSOGE, PSOGT, PSOIDIV, + PSOINDEX, PSOLE, PSOLN, PSOLOG, PSOLT, PSOMOD, PSOMUL, + PSONE, PSONEG, PSONOT, PSOOR, PSOPOP, PSOROLL, PSOROUND, + PSOSIN, PSOSQRT, PSOSUB, PSOTRUE, PSOTRUNCATE, PSOXOR, + PSOIF, PSOIFELSE, PSORETURN }; -enum psop_e { - psOpAbs, - psOpAdd, - psOpAnd, - psOpAtan, - psOpBitshift, - psOpCeiling, - psOpCopy, - psOpCos, - psOpCvi, - psOpCvr, - psOpDiv, - psOpDup, - psOpEq, - psOpExch, - psOpExp, - psOpFalse, - psOpFloor, - psOpGe, - psOpGt, - psOpIdiv, - psOpIndex, - psOpLe, - psOpLn, - psOpLog, - psOpLt, - psOpMod, - psOpMul, - psOpNe, - psOpNeg, - psOpNot, - psOpOr, - psOpPop, - psOpRoll, - psOpRound, - psOpSin, - psOpSqrt, - psOpSub, - psOpTrue, - psOpTruncate, - psOpXor, - psOpIf, - psOpIfelse, - psOpReturn +static char *psopnames[] = +{ + "abs", "add", "and", "atan", "bitshift", "ceiling", "copy", + "cos", "cvi", "cvr", "div", "dup", "eq", "exch", "exp", + "false", "floor", "ge", "gt", "idiv", "index", "le", "ln", + "log", "lt", "mod", "mul", "ne", "neg", "not", "or", "pop", + "roll", "round", "sin", "sqrt", "sub", "true", "truncate", + "xor", /* "if", "ifelse", "return" */ }; -/* Note: 'if' and 'ifelse' are parsed separately. - * The rest are listed here in alphabetical order. - * The index in this table is equivalent to the entry in PSOp. */ -char *psOpNames[] = { - "abs", - "add", - "and", - "atan", - "bitshift", - "ceiling", - "copy", - "cos", - "cvi", - "cvr", - "div", - "dup", - "eq", - "exch", - "exp", - "false", - "floor", - "ge", - "gt", - "idiv", - "index", - "le", - "ln", - "log", - "lt", - "mod", - "mul", - "ne", - "neg", - "not", - "or", - "pop", - "roll", - "round", - "sin", - "sqrt", - "sub", - "true", - "truncate", - "xor" +struct psobj_s +{ + int type; + union + { + int b; /* boolean (stack only) */ + int i; /* integer (stack and code) */ + float f; /* real (stack and code) */ + int op; /* operator (code only) */ + int block; /* if/ifelse block pointer (code only) */ + } u; }; -enum psobjtype_e { - psBool, - psInt, - psReal, - psOperator, - psBlock -}; +/* + * PostScript calculator + */ -static int bps_supported[] = { 1,2,4,8,12,16,24,32 }; +enum { PSSTACKSIZE = 100 }; -/************************************************************************/ -/* Start Stack Impl */ -/************************************************************************/ -#define PSSTACKSIZE 100 -#define fz_stackoverflow fz_throw("syntaxerror : stackoverflow") -#define fz_stackunderflow fz_throw("syntaxerror : stackunderflow") -#define fz_stacktypemismatch fz_throw("syntaxerror : type mismatching") +#define fz_stackoverflow fz_throw("rangecheck: stackoverflow in calculator") +#define fz_stackunderflow fz_throw("rangecheck: stackunderflow in calculator") +#define fz_stacktypemismatch fz_throw("typecheck: postscript calculator") typedef struct psstack_s psstack; @@ -227,153 +130,154 @@ struct psstack_s }; static void -initstack(psstack *st) +psinitstack(psstack *st) { - memset(st->stack,0,sizeof(st->stack)); + memset(st->stack, 0, sizeof(st->stack)); st->sp = PSSTACKSIZE; } -static int -checkoverflow(psstack *st, int n) +static int +pscheckoverflow(psstack *st, int n) { return st->sp >= n; } -static int -checkunderflow(psstack *st) +static int +pscheckunderflow(psstack *st) { return st->sp != PSSTACKSIZE; } -static int -checktype(psstack *st, unsigned short t1, unsigned short t2) +static int +pschecktype(psstack *st, unsigned short t1, unsigned short t2) { return (st->stack[st->sp].type == t1 || - st->stack[st->sp].type == t2); + st->stack[st->sp].type == t2); } -static fz_error * -pushbool(psstack *st, int booln) +static fz_error * +pspushbool(psstack *st, int booln) { - if (checkoverflow(st, 1)) { - st->stack[--st->sp].type = psBool; + if (pscheckoverflow(st, 1)) + { + st->stack[--st->sp].type = PSBOOL; st->stack[st->sp].u.b = booln; } else return fz_stackoverflow; - return nil; } -static fz_error * -pushint(psstack *st, int intg) +static fz_error * +pspushint(psstack *st, int intg) { - if (checkoverflow(st, 1)) { - st->stack[--st->sp].type = psInt; + if (pscheckoverflow(st, 1)) + { + st->stack[--st->sp].type = PSINT; st->stack[st->sp].u.i = intg; } else return fz_stackoverflow; - return nil; } -static fz_error * -pushreal(psstack *st, float real) +static fz_error * +pspushreal(psstack *st, float real) { - if (checkoverflow(st, 1)) { - st->stack[--st->sp].type = psReal; + if (pscheckoverflow(st, 1)) + { + st->stack[--st->sp].type = PSREAL; st->stack[st->sp].u.f = real; } else return fz_stackoverflow; - return nil; } static fz_error * -popbool(psstack *st, int *booln) +pspopbool(psstack *st, int *booln) { - if (checkunderflow(st) && checktype(st, psBool, psBool)) { + if (pscheckunderflow(st) && pschecktype(st, PSBOOL, PSBOOL)) + { *booln = st->stack[st->sp++].u.b; } - else if(checkunderflow(st)) + else if (pscheckunderflow(st)) return fz_stackunderflow; else return fz_stacktypemismatch; - return nil; } static fz_error * -popint(psstack *st, int *intg) +pspopint(psstack *st, int *intg) { - if (checkunderflow(st) && checktype(st, psInt, psInt)) { + if (pscheckunderflow(st) && pschecktype(st, PSINT, PSINT)) + { *intg = st->stack[st->sp++].u.i; } - else if(checkunderflow(st)) + else if (pscheckunderflow(st)) return fz_stackunderflow; else return fz_stacktypemismatch; - return nil; } static fz_error * -popnum(psstack *st, float *real) +pspopnum(psstack *st, float *real) { - if (checkunderflow(st) && checktype(st, psInt, psReal)) { + if (pscheckunderflow(st) && pschecktype(st, PSINT, PSREAL)) + { float ret; - ret = (st->stack[st->sp].type == psInt) ? - (float)st->stack[st->sp].u.i : st->stack[st->sp].u.f; + ret = (st->stack[st->sp].type == PSINT) ? + (float) st->stack[st->sp].u.i : st->stack[st->sp].u.f; ++st->sp; *real = ret; } - else if(checkunderflow(st)) + else if (pscheckunderflow(st)) return fz_stackunderflow; else return fz_stacktypemismatch; - return nil; } -static int -topisint(psstack *st) +static int +pstopisint(psstack *st) { - return st->sp < PSSTACKSIZE && st->stack[st->sp].type == psInt; + return st->sp < PSSTACKSIZE && st->stack[st->sp].type == PSINT; } -static int -toptwoareints(psstack *st) +static int +pstoptwoareints(psstack *st) { return st->sp < PSSTACKSIZE - 1 && - st->stack[st->sp].type == psInt && - st->stack[st->sp+1].type == psInt; + st->stack[st->sp].type == PSINT && + st->stack[st->sp + 1].type == PSINT; } -static int -topisreal(psstack *st) +static int +pstopisreal(psstack *st) { - return st->sp < PSSTACKSIZE && st->stack[st->sp].type == psReal; + return st->sp < PSSTACKSIZE && st->stack[st->sp].type == PSREAL; } -static int -toptwoarenums(psstack *st) +static int +pstoptwoarenums(psstack *st) { return st->sp < PSSTACKSIZE - 1 && - (st->stack[st->sp].type == psInt || st->stack[st->sp].type == psReal) && - (st->stack[st->sp+1].type == psInt || st->stack[st->sp+1].type == psReal); + (st->stack[st->sp].type == PSINT || st->stack[st->sp].type == PSREAL) && + (st->stack[st->sp + 1].type == PSINT || st->stack[st->sp + 1].type == PSREAL); } static fz_error * -copy(psstack *st, int n) +pscopy(psstack *st, int n) { int i; - - if (!checkoverflow(st,n)) + + if (!pscheckoverflow(st, n)) return fz_stackoverflow; - for (i = st->sp + n - 1; i <= st->sp; ++i) { + for (i = st->sp + n - 1; i <= st->sp; ++i) + { st->stack[i - n] = st->stack[i]; } st->sp -= n; @@ -381,36 +285,44 @@ copy(psstack *st, int n) return nil; } -static void -roll(psstack *st, int n, int j) +static void +psroll(psstack *st, int n, int j) { psobj obj; int i, k; - - if (j >= 0) { + + if (j >= 0) + { j %= n; - } else { + } + else + { j = -j % n; - if (j != 0) { + if (j != 0) + { j = n - j; } } - if (n <= 0 || j == 0) { + if (n <= 0 || j == 0) + { return; } - for (i = 0; i < j; ++i) { + for (i = 0; i < j; ++i) + { obj = st->stack[st->sp]; - for (k = st->sp; k < st->sp + n - 1; ++k) { - st->stack[k] = st->stack[k+1]; + for (k = st->sp; k < st->sp + n - 1; ++k) + { + st->stack[k] = st->stack[k + 1]; } st->stack[st->sp + n - 1] = obj; } } static fz_error * -index(psstack *st, int i) +psindex(psstack *st, int i) { - if (!checkoverflow(st, 1)) { + if (!pscheckoverflow(st, 1)) + { return fz_stackoverflow; } --st->sp; @@ -419,496 +331,25 @@ index(psstack *st, int i) } static fz_error * -pop(psstack *st) +pspop(psstack *st) { - if (!checkoverflow(st, 1)) { + if (!pscheckoverflow(st, 1)) + { return fz_stackoverflow; } ++st->sp; return nil; } -/************************************************************************/ -/* End Stack Impl */ -/************************************************************************/ - static fz_error * -loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gid) +resizecode(pdf_function *func, int newsize) { - fz_error *error = nil; - fz_obj *tmpobj; - int i; - int bps; - int samplecount, bytetoread; - int *size; - unsigned char *streamsamples = nil; - int *samples = nil; - float *encode; - float *decode; - - /* required */ - tmpobj = fz_dictgets(dict,"Size"); - if(!fz_isarray(tmpobj) || fz_arraylen(tmpobj) != func->m) - goto cleanup; - - size = fz_malloc(func->m * sizeof(int)); - if(!size) return fz_outofmem; - - for(i = 0; i < func->m; ++i) - size[i] = fz_toint(fz_arrayget(tmpobj,i)); - func->u.sa.size = size; - - /* required */ - tmpobj = fz_dictgets(dict,"BitsPerSample"); - if(!fz_isint(tmpobj)) - goto cleanup; - func->u.sa.bps = bps = fz_toint(tmpobj); - - for(i = 0; i < ARRAY_SIZE(bps_supported); ++i) - if(bps == bps_supported[i]) break; - if(i == ARRAY_SIZE(bps_supported)) - goto cleanup; - - /* optional */ - tmpobj = fz_dictgets(dict, "Order"); - if(!fz_isint(tmpobj)) - func->u.sa.order = 1; /* default : linear interpolation */ - else - func->u.sa.order = fz_toint(tmpobj); - if(func->u.sa.order != 1 && func->u.sa.order != 3) - goto cleanup; - - if(func->u.sa.order == 3) { - for(i = 0; i < func->m; ++i) - if(size[i] < 4) { - func->u.sa.order = 1; - break; - } - } - - /* optional */ - tmpobj = fz_dictgets(dict, "Encode"); - func->u.sa.encode = encode = fz_malloc(func->m*2 * sizeof(float)); - if(!encode) return fz_outofmem; - if(fz_isarray(tmpobj)) { - if(fz_arraylen(tmpobj) != func->m*2) - goto cleanup; - - for(i = 0; i < func->m; ++i) { - encode[i*2] = fz_toreal(fz_arrayget(tmpobj, i*2)); - encode[i*2+1] = fz_toreal(fz_arrayget(tmpobj, i*2+1)); - } - } - else { - for(i = 0; i < func->m; ++i) { - encode[i*2] = 0; - encode[i*2+1] = size[i] - 1; - } - } - - /* optional */ - tmpobj = fz_dictgets(dict, "Decode"); - func->u.sa.decode = decode = fz_malloc(func->n*2 * sizeof(float)); - if(!decode) return fz_outofmem; - if(fz_isarray(tmpobj)) { - if(fz_arraylen(tmpobj) != func->n*2) - goto cleanup; - - for(i = 0; i < func->n; ++i) { - decode[i*2] = fz_toreal(fz_arrayget(tmpobj, i*2)); - decode[i*2+1] = fz_toreal(fz_arrayget(tmpobj, i*2+1)); - } - } - else { - for(i = 0; i < func->n; ++i) { - decode[i*2] = func->range[i*2]; - decode[i*2+1] = func->range[i*2+1]; - } - } - - /* read samples from stream */ - error = pdf_openstream(xref, oid, gid); - if (error) goto cleanup; - - for(i = 0, samplecount = func->n; i < func->m; ++i) - samplecount *= size[i]; - - bytetoread = (samplecount*bps + 7)/8; - streamsamples = fz_malloc(bytetoread); - samples = fz_malloc(samplecount * sizeof(int)); - func->u.sa.samples = samples; - if(!streamsamples || !samples) { error = fz_outofmem; goto cleanup2; } - - /* read samples */ + if (newsize >= func->u.p.cap) { - int pos; - unsigned int bitMask = (1 << bps) - 1; - unsigned int buf = 0; - int bits = 0; - int s; - - int readbyte = - fz_read(xref->stream, streamsamples, bytetoread); - - if(readbyte != bytetoread) - { - error = fz_throw("syntaxerror : "); - goto cleanup2; - } - - for (i = 0, pos = 0; i < samplecount; ++i) { - if (bps == 8) { - s = streamsamples[pos++]; - } else if (samplecount == 16) { - s = streamsamples[pos++]; - s = (s << 8) + streamsamples[pos++]; - } else if (samplecount == 32) { - s = streamsamples[pos++]; - s = (s << 8) + streamsamples[pos++]; - s = (s << 8) + streamsamples[pos++]; - s = (s << 8) + streamsamples[pos++]; - } else { - while (bits < bps) { - buf = (buf << 8) | (streamsamples[pos++] & 0xff); - bits += 8; - } - s = (buf >> (bits - bps)) & bitMask; - bits -= bps; - } - samples[i] = s; - } - } - -cleanup2: - if(streamsamples) - fz_free(streamsamples); - - pdf_closestream(xref); - return error; - -cleanup: - if(error) return error; - return fz_throw("syntaxerror : "); -} - -static fz_error * -evalsamplefunc(pdf_function *func, float *in, float *out) -{ - int i , j, k, idx; - int e[2][func->m]; - float efrac[func->m]; - float s0[1 << func->m], s1[1 << func->m]; - float x; - float *domain = func->domain; - float *encode = func->u.sa.encode; - float *range = func->range; - float *decode = func->u.sa.decode; - int *size = func->u.sa.size; - float byterange = (1<<func->u.sa.bps)-1; - - if(func->type != PDF_FUNC_SAMPLE) - goto cleanup; - - switch(func->u.sa.order) { - case 3: - /* cubic spline interpolation */ - case 1: - for (i = 0; i < func->m; ++i) { - x = in[i]; - MIN_MAX(x,domain[i*2],domain[i*2+1]); - - if(domain[i*2+1] != domain[i*2]) - x = ((x - domain[i*2]) / (domain[i*2+1] - domain[i*2])) * - (encode[i*2+1] - encode[i*2]) + encode[i*2]; - - MIN_MAX(x,0,size[i] - 1); - - e[0][i] = (int)floor(x); - e[1][i] = (int)ceil(x); - efrac[i] = x - e[0][i]; - } - - /* for each output, do m-linear interpolation */ - for (i = 0; i < func->n; ++i) { - /* pull 2^m values out of the sample array */ - for (j = 0; j < (1 << func->m); ++j) { - idx = 0; - for (k = func->m - 1; k >= 0; --k) { - idx = idx * func->u.sa.size[k] + e[(j >> k) & 1][k]; - } - idx = idx * func->n + i; - s0[j] = func->u.sa.samples[idx]; - } - - /* do m sets of interpolations */ - for (j = 0; j < func->m; ++j) { - for (k = 0; k < (1 << (func->m - j)); k += 2) { - s1[k >> 1] = (1 - efrac[j]) * s0[k] + efrac[j] * s0[k+1]; - } - memcpy(s0, s1, (1 << (func->m - j - 1)) * sizeof(float)); - } - - /* map output value to range */ - /*out[i] = s0[0] * (decode[i*2+1] - decode[i*2]) + decode[i*2]; */ - out[i] = INTERPOLATE(s0[0],0,byterange,decode[i*2],decode[i*2+1]); - MIN_MAX(out[i],range[i*2],range[i*2+1]); - } - break; - } - return nil; - -cleanup: - return fz_throw("syntaxerror : "); -} - -static fz_error * -loadexponentialfunc(pdf_function *func, fz_obj *dict) -{ - fz_error *error = nil; - fz_obj *tmpobj; - int i; - float *c0, *c1; - - /* single input */ - if(func->m != 1) - goto cleanup; - - /* required */ - tmpobj = fz_dictgets(dict,"N"); - if(!fz_isint(tmpobj) && !fz_isreal(tmpobj)) - goto cleanup; - func->u.e.n = fz_toreal(tmpobj); - - /* optional */ - tmpobj = fz_dictgets(dict,"C0"); - if(fz_isarray(tmpobj)) { - fz_obj *objnum; - - if(func->range && fz_arraylen(tmpobj) != func->n) - goto cleanup; - - func->n = fz_arraylen(tmpobj); - func->u.e.c0 = c0 = fz_malloc(func->n * sizeof(float)); - if(!c0) { error = fz_outofmem; goto cleanup; } - - for(i = 0; i < func->n; ++i) { - objnum = fz_arrayget(tmpobj,i); - if(!fz_isint(objnum) && !fz_isreal(objnum)) - goto cleanup; - - c0[i] = fz_toreal(objnum); - } - } - else { - if(func->range && func->n != 1) - goto cleanup; - - func->n = 1; - func->u.e.c0 = c0 = fz_malloc(func->n * sizeof(float)); - if(!c0) { error = fz_outofmem; goto cleanup; } - - c0[0] = 0; - } - - /* optional */ - tmpobj = fz_dictgets(dict,"C1"); - func->u.e.c1 = c1 = fz_malloc(func->n * sizeof(float)); - if(!c1) { error = fz_outofmem; goto cleanup; } - if(fz_isarray(tmpobj)) { - fz_obj *objnum; - - if(fz_arraylen(tmpobj) != func->n) - goto cleanup; - - for(i = 0; i < func->n; ++i) { - objnum = fz_arrayget(tmpobj,i); - if(!fz_isint(objnum) && !fz_isreal(objnum)) - goto cleanup; - - c1[i] = fz_toreal(objnum); - } - } - else { - if(func->n != 1) - goto cleanup; - - c1[0] = 1; - } - - return nil; -cleanup: - if(error) return error; - return fz_throw("syntaxerror : "); -} - -static fz_error * -evalexponentialfunc(pdf_function *func, float in, float *out) -{ - fz_error *error = nil; - float x = in; - float tmp; - int i; - - if(func->type != PDF_FUNC_EXPONENTIAL) - goto cleanup; - - MIN_MAX(x,func->domain[0],func->domain[1]); - - /* constraint */ - if(func->u.e.n != (int)func->u.e.n && x < 0) - goto cleanup; - - if(func->u.e.n < 0 && x == 0) - goto cleanup; - - tmp = pow(x, func->u.e.n); - for (i = 0; i < func->n; ++i) { - out[i] = func->u.e.c0[i] + - tmp * (func->u.e.c1[i] - func->u.e.c0[i]); - if (func->range) { - MIN_MAX(out[i],func->range[i*2],func->range[i*2+1]); - } - } - - return nil; -cleanup: - if(error) return error; - return fz_throw("syntaxerror : "); -} - -static fz_error * -loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) -{ - fz_error *error = nil; - fz_obj *tmpobj; - fz_obj *funcobj; - fz_obj *numobj; - pdf_function **funcs; - float *bounds, *encode; - int i; - int k; - - if(func->m != 1) - goto cleanup; - - /* required */ - tmpobj = fz_dictgets(dict,"Functions"); - error = pdf_resolve(&tmpobj,xref); - if (error) goto cleanup; - - if(!fz_isarray(tmpobj)) - goto cleanup; - k = fz_arraylen(tmpobj); - - func->u.st.funcs = funcs = fz_malloc(k*sizeof(pdf_function*)); - if(!funcs) { error = fz_outofmem; goto cleanup; } - memset(funcs, 0, k * sizeof(pdf_function*)); - - for(i = 0; i < k; ++i) { - funcobj = fz_arrayget(tmpobj,i); - error = pdf_loadfunction(funcs+i,xref,funcobj); - if(error) goto cleanup; - if(funcs[i]->m != 1 || funcs[i]->n != funcs[0]->n) - goto cleanup; - } - - if(!func->range) - func->n = funcs[0]->n; - else if(func->n != funcs[0]->n) - goto cleanup; - - /* required */ - tmpobj = fz_dictgets(dict,"Bounds"); - error = pdf_resolve(&tmpobj,xref); - if (error) goto cleanup; - - if(!fz_isarray(tmpobj) || fz_arraylen(tmpobj) != k-1) - goto cleanup; - - func->u.st.bounds = bounds = fz_malloc((k-1) * sizeof(float)); - if(!bounds) { error = fz_outofmem; goto cleanup; } - - for(i = 0; i < k-1; ++i) { - numobj = fz_arrayget(tmpobj,i); - if(!fz_isint(numobj) && !fz_isreal(numobj)) - goto cleanup; - bounds[i] = fz_toreal(numobj); - if(i && bounds[i-1] >= bounds[i]) - goto cleanup; - } - if(k != 1 && - (func->domain[0] >= bounds[0] || func->domain[1] <= bounds[k-2])) - goto cleanup; - - /* required */ - tmpobj = fz_dictgets(dict,"Encode"); - error = pdf_resolve(&tmpobj,xref); - if(!fz_isarray(tmpobj) || fz_arraylen(tmpobj) != k*2) - goto cleanup; - - func->u.st.encode = encode = fz_malloc((k*2) * sizeof(float)); - if(!encode) { error = fz_outofmem; goto cleanup; } - - for(i = 0; i < k*2; ++i) { - numobj = fz_arrayget(tmpobj,i); - if(!fz_isint(numobj) && !fz_isreal(numobj)) - goto cleanup; - encode[i] = fz_toreal(numobj); - } - - func->u.st.k = k; - - return nil; - -cleanup: - if(error) return error; - return fz_throw("syntaxerror : "); -} - -static fz_error* -evalstitchingfunc(pdf_function *func, float in, float *out) -{ - fz_error *error = nil; - float low,high; - int k = func->u.st.k; - float *bounds = func->u.st.bounds; - int i; - - MIN_MAX(in,func->domain[0],func->domain[1]); - - for(i = 0; i < k - 1; ++i) { - if (in < bounds[i]) - break; - } - if(i == 0) { - low = func->domain[0]; - high = func->domain[1]; - } - else if(i == k - 1) { - low = bounds[k-2]; - high = func->domain[1]; - } - else { - low = bounds[i-1]; - high = bounds[i]; - } - - in = INTERPOLATE(in,low,high, - func->u.st.encode[i*2],func->u.st.encode[i*2 + 1]); - - error = pdf_evalfunction(func->u.st.funcs[i],&in,1,out,func->n); - if(error) return error; - - return nil; -} - -static fz_error * -resizecode(pdf_function *func, int newsize) { - if (newsize >= func->u.p.cap) { int newcodecap = func->u.p.cap + 64; psobj *newcode; newcode = fz_realloc(func->u.p.code, newcodecap * sizeof(psobj)); - if(!newcode) + if (!newcode) return fz_outofmem; func->u.p.cap = newcodecap; func->u.p.code = newcode; @@ -924,71 +365,75 @@ parsecode(pdf_function *func, fz_file *stream, int *codeptr) int buflen = sizeof(buf) / sizeof(buf[0]); int len; int token; - int opPtr, elsePtr; + int opptr, elseptr; int a, b, mid, cmp; - - memset(buf,0,sizeof(buf)); - - while (1) { - token = pdf_lex(stream,buf,buflen,&len); - if(token == PDF_TERROR || token == PDF_TEOF) + + memset(buf, 0, sizeof(buf)); + + while (1) + { + token = pdf_lex(stream, buf, buflen, &len); + + if (token == PDF_TERROR || token == PDF_TEOF) goto cleanup; - + switch(token) { case PDF_TINT: - resizecode(func,*codeptr); - func->u.p.code[*codeptr].type = psInt; + resizecode(func, *codeptr); + func->u.p.code[*codeptr].type = PSINT; func->u.p.code[*codeptr].u.i = atoi(buf); ++*codeptr; break; + case PDF_TREAL: - resizecode(func,*codeptr); - func->u.p.code[*codeptr].type = psReal; + resizecode(func, *codeptr); + func->u.p.code[*codeptr].type = PSREAL; func->u.p.code[*codeptr].u.f = atof(buf); ++*codeptr; break; + case PDF_TOBRACE: - opPtr = *codeptr; + opptr = *codeptr; *codeptr += 3; - resizecode(func,opPtr + 2); + resizecode(func, opptr + 2); error = parsecode(func, stream, codeptr); - if(error) goto cleanup; - - token = pdf_lex(stream,buf,buflen,&len); - - if(token == PDF_TEOF || token == PDF_TERROR) + if (error) goto cleanup; + + token = pdf_lex(stream, buf, buflen, &len); + + if (token == PDF_TEOF || token == PDF_TERROR) goto cleanup; - - if(token == PDF_TOBRACE) { - elsePtr = *codeptr; + + if (token == PDF_TOBRACE) { + elseptr = *codeptr; error = parsecode(func, stream, codeptr); - if(error) goto cleanup; - token = pdf_lex(stream,buf,buflen,&len); - if(token == PDF_TERROR || token == PDF_TEOF) + if (error) goto cleanup; + token = pdf_lex(stream, buf, buflen, &len); + if (token == PDF_TERROR || token == PDF_TEOF) goto cleanup; } else - elsePtr = -1; - - if(token == PDF_TKEYWORD) { - if(!strcmp(buf,"if")) { - if (elsePtr >= 0) + elseptr = -1; + + if (token == PDF_TKEYWORD) { + if (!strcmp(buf, "if")) { + if (elseptr >= 0) goto cleanup; - func->u.p.code[opPtr].type = psOperator; - func->u.p.code[opPtr].u.op = psOpIf; - func->u.p.code[opPtr+2].type = psBlock; - func->u.p.code[opPtr+2].u.blk = *codeptr; + func->u.p.code[opptr].type = PSOPERATOR; + func->u.p.code[opptr].u.op = PSOIF; + func->u.p.code[opptr+2].type = PSBLOCK; + func->u.p.code[opptr+2].u.block = *codeptr; } - else if(!strcmp(buf,"ifelse")) { - if (elsePtr < 0) + else if (!strcmp(buf, "ifelse")) { + if (elseptr < 0) goto cleanup; - func->u.p.code[opPtr].type = psOperator; - func->u.p.code[opPtr].u.op = psOpIfelse; - func->u.p.code[opPtr+1].type = psBlock; - func->u.p.code[opPtr+1].u.blk = elsePtr; - func->u.p.code[opPtr+2].type = psBlock; - func->u.p.code[opPtr+2].u.blk = *codeptr; + func->u.p.code[opptr].type = PSOPERATOR; + func->u.p.code[opptr].u.op = PSOIFELSE; + func->u.p.code[opptr+1].type = PSBLOCK; + func->u.p.code[opptr+1].u.block = elseptr; + func->u.p.code[opptr+2].type = PSBLOCK; + func->u.p.code[opptr+2].u.block = *codeptr; } else goto cleanup; @@ -996,19 +441,21 @@ parsecode(pdf_function *func, fz_file *stream, int *codeptr) else goto cleanup; break; + case PDF_TCBRACE: - resizecode(func,*codeptr); - func->u.p.code[*codeptr].type = psOperator; - func->u.p.code[*codeptr].u.op = psOpReturn; + resizecode(func, *codeptr); + func->u.p.code[*codeptr].type = PSOPERATOR; + func->u.p.code[*codeptr].u.op = PSORETURN; ++*codeptr; return nil; + case PDF_TKEYWORD: a = -1; - b = sizeof(psOpNames) / sizeof(psOpNames[0]); - /* invariant: psOpNames[a] < op < psOpNames[b] */ + b = sizeof(psopnames) / sizeof(psopnames[0]); + /* invariant: psopnames[a] < op < psopnames[b] */ while (b - a > 1) { mid = (a + b) / 2; - cmp = strcmp(buf,psOpNames[mid]); + cmp = strcmp(buf, psopnames[mid]); if (cmp > 0) { a = mid; } else if (cmp < 0) { @@ -1019,46 +466,54 @@ parsecode(pdf_function *func, fz_file *stream, int *codeptr) } if (cmp != 0) goto cleanup; - - resizecode(func,*codeptr); - func->u.p.code[*codeptr].type = psOperator; + + resizecode(func, *codeptr); + func->u.p.code[*codeptr].type = PSOPERATOR; func->u.p.code[*codeptr].u.op = a; ++*codeptr; break; + default: goto cleanup; } } return nil; + cleanup: - if(error) return error; - return fz_throw("syntaxerror : postscript code"); + if (error) return error; + return fz_throw("syntaxerror: postscript calculator"); } static fz_error * -loadpostscriptfunc(pdf_function *func, pdf_xref *xref, - fz_obj *dict, int oid, int gid) +loadpostscriptfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gen) { fz_error *error = nil; int codeptr; - - /* read postcript from stream */ - error = pdf_openstream(xref, oid, gid); + + pdf_logrsrc("load postscript function %d %d\n", oid, gen); + + error = pdf_openstream(xref, oid, gen); if (error) goto cleanup; - codeptr = 0; - if(fz_readbyte(xref->stream) != '{') + + if (fz_readbyte(xref->stream) != '{') goto cleanup; + func->u.p.code = nil; + func->u.p.cap = 0; + + + codeptr = 0; error = parsecode(func, xref->stream, &codeptr); - if(error) goto cleanup; + if (error) goto cleanup; pdf_closestream(xref); + return nil; - + cleanup: pdf_closestream(xref); - if(error) return error; - return fz_throw("syntaxerror : "); + if (error) return error; + return fz_throw("syntaxerror: postscript calculator"); } static fz_error * @@ -1068,225 +523,258 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) int i1, i2; float r1, r2; int b1, b2; - - while (1) { - switch (func->u.p.code[codeptr].type) { - case psInt: - SAFE_PUSHINT(st,func->u.p.code[codeptr++].u.i); + + while (1) + { + switch (func->u.p.code[codeptr].type) + { + case PSINT: + SAFE_PUSHINT(st, func->u.p.code[codeptr++].u.i); break; - case psReal: - SAFE_PUSHREAL(st,func->u.p.code[codeptr++].u.f); + + case PSREAL: + SAFE_PUSHREAL(st, func->u.p.code[codeptr++].u.f); break; - case psOperator: - switch (func->u.p.code[codeptr++].u.op) { - case psOpAbs: - if (topisint(st)) { - SAFE_POPINT(st,&i1); - SAFE_PUSHINT(st,abs(i1)); + + case PSOPERATOR: + switch (func->u.p.code[codeptr++].u.op) + { + case PSOABS: + if (pstopisint(st)) { + SAFE_POPINT(st, &i1); + SAFE_PUSHINT(st, abs(i1)); } else { - SAFE_POPNUM(st,&r1); - SAFE_PUSHREAL(st,fabs(r1)); + SAFE_POPNUM(st, &r1); + SAFE_PUSHREAL(st, fabs(r1)); } break; - case psOpAdd: - if (toptwoareints(st)) { - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); - SAFE_PUSHINT(st,i1 + i2); + + case PSOADD: + if (pstoptwoareints(st)) { + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); + SAFE_PUSHINT(st, i1 + i2); } else { - SAFE_POPNUM(st,&r2); - SAFE_POPNUM(st,&r1); - SAFE_PUSHREAL(st,r1 + r2); + SAFE_POPNUM(st, &r2); + SAFE_POPNUM(st, &r1); + SAFE_PUSHREAL(st, r1 + r2); } break; - case psOpAnd: - if (toptwoareints(st)) { + + case PSOAND: + if (pstoptwoareints(st)) { SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); - SAFE_PUSHINT(st,i1 & i2); + SAFE_PUSHINT(st, i1 & i2); } else { SAFE_POPBOOL(st, &b2); SAFE_POPBOOL(st, &b1); - SAFE_PUSHBOOL(st,b1 && b2); + SAFE_PUSHBOOL(st, b1 && b2); } break; - case psOpAtan: + + case PSOATAN: SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); - SAFE_PUSHREAL(st,atan2(r1, r2)*RADIAN); + SAFE_PUSHREAL(st, atan2(r1, r2)*RADIAN); break; - case psOpBitshift: + + case PSOBITSHIFT: SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); if (i2 > 0) { - SAFE_PUSHINT(st,i1 << i2); + SAFE_PUSHINT(st, i1 << i2); } else if (i2 < 0) { - SAFE_PUSHINT(st,(int)((unsigned int)i1 >> i2)); + SAFE_PUSHINT(st, (int)((unsigned int)i1 >> i2)); } else { - SAFE_PUSHINT(st,i1); + SAFE_PUSHINT(st, i1); } break; - case psOpCeiling: - if (!topisint(st)) { - SAFE_POPNUM(st,&r1); - SAFE_PUSHREAL(st,ceil(r1)); + + case PSOCEILING: + if (!pstopisint(st)) { + SAFE_POPNUM(st, &r1); + SAFE_PUSHREAL(st, ceil(r1)); } break; - case psOpCopy: - SAFE_POPINT(st,&i1); - SAFE_COPY(st,i1); + + case PSOCOPY: + SAFE_POPINT(st, &i1); + SAFE_COPY(st, i1); break; - case psOpCos: - SAFE_POPNUM(st,&r1); - SAFE_PUSHREAL(st,cos(r1/RADIAN)); + + case PSOCOS: + SAFE_POPNUM(st, &r1); + SAFE_PUSHREAL(st, cos(r1/RADIAN)); break; - case psOpCvi: - if (!topisint(st)) { - SAFE_POPNUM(st,&r1); - SAFE_PUSHINT(st,(int)r1); + + case PSOCVI: + if (!pstopisint(st)) { + SAFE_POPNUM(st, &r1); + SAFE_PUSHINT(st, (int)r1); } break; - case psOpCvr: - if (!topisreal(st)) { - SAFE_POPNUM(st,&r1); - SAFE_PUSHREAL(st,r1); + + case PSOCVR: + if (!pstopisreal(st)) { + SAFE_POPNUM(st, &r1); + SAFE_PUSHREAL(st, r1); } break; - case psOpDiv: + + case PSODIV: SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); - SAFE_PUSHREAL(st,r1 / r2); + SAFE_PUSHREAL(st, r1 / r2); break; - case psOpDup: - SAFE_COPY(st,1); + + case PSODUP: + SAFE_COPY(st, 1); break; - case psOpEq: - if (toptwoareints(st)) { + + case PSOEQ: + if (pstoptwoareints(st)) { SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); - SAFE_PUSHBOOL(st,i1 == i2); - } else if (toptwoarenums(st)) { + SAFE_PUSHBOOL(st, i1 == i2); + } else if (pstoptwoarenums(st)) { SAFE_POPNUM(st, &r1); SAFE_POPNUM(st, &r1); - SAFE_PUSHBOOL(st,r1 == r2); + SAFE_PUSHBOOL(st, r1 == r2); } else { SAFE_POPBOOL(st, &b2); SAFE_POPBOOL(st, &b2); - SAFE_PUSHBOOL(st,b1 == b2); + SAFE_PUSHBOOL(st, b1 == b2); } break; - case psOpExch: - roll(st,2, 1); + + case PSOEXCH: + psroll(st, 2, 1); break; - case psOpExp: + + case PSOEXP: SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); - SAFE_PUSHREAL(st,pow(r1, r2)); + SAFE_PUSHREAL(st, pow(r1, r2)); break; - case psOpFalse: - SAFE_PUSHBOOL(st,0); + + case PSOFALSE: + SAFE_PUSHBOOL(st, 0); break; - case psOpFloor: - if (!topisint(st)) { + + case PSOFLOOR: + if (!pstopisint(st)) { SAFE_POPNUM(st, &r1); - SAFE_PUSHREAL(st,floor(r1)); + SAFE_PUSHREAL(st, floor(r1)); } break; - case psOpGe: - if (toptwoareints(st)) { + + case PSOGE: + if (pstoptwoareints(st)) { SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); - SAFE_PUSHBOOL(st,i1 >= i2); + SAFE_PUSHBOOL(st, i1 >= i2); } else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); - SAFE_PUSHBOOL(st,r1 >= r2); + SAFE_PUSHBOOL(st, r1 >= r2); } break; - case psOpGt: - if (toptwoareints(st)) { - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); - SAFE_PUSHBOOL(st,i1 > i2); + + case PSOGT: + if (pstoptwoareints(st)) { + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); + SAFE_PUSHBOOL(st, i1 > i2); } else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); - SAFE_PUSHBOOL(st,r1 > r2); + SAFE_PUSHBOOL(st, r1 > r2); } break; - case psOpIdiv: - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); - SAFE_PUSHINT(st,i1 / i2); + + case PSOIDIV: + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); + SAFE_PUSHINT(st, i1 / i2); break; - case psOpIndex: + + case PSOINDEX: SAFE_POPINT(st, &i1); SAFE_INDEX(st, i1); break; - case psOpLe: - if (toptwoareints(st)) { - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); - SAFE_PUSHBOOL(st,i1 <= i2); + + case PSOLE: + if (pstoptwoareints(st)) { + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); + SAFE_PUSHBOOL(st, i1 <= i2); } else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); - SAFE_PUSHBOOL(st,r1 <= r2); + SAFE_PUSHBOOL(st, r1 <= r2); } break; - case psOpLn: + + case PSOLN: SAFE_POPNUM(st, &r1); - SAFE_PUSHREAL(st,log(r1)); + SAFE_PUSHREAL(st, log(r1)); break; - case psOpLog: + + case PSOLOG: SAFE_POPNUM(st, &r1); - SAFE_PUSHREAL(st,log10(r1)); + SAFE_PUSHREAL(st, log10(r1)); break; - case psOpLt: - if (toptwoareints(st)) { - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); - SAFE_PUSHBOOL(st,i1 < i2); + + case PSOLT: + if (pstoptwoareints(st)) { + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); + SAFE_PUSHBOOL(st, i1 < i2); } else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); - SAFE_PUSHBOOL(st,r1 < r2); + SAFE_PUSHBOOL(st, r1 < r2); } break; - case psOpMod: - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); - SAFE_PUSHINT(st,i1 % i2); + + case PSOMOD: + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); + SAFE_PUSHINT(st, i1 % i2); break; - case psOpMul: - if (toptwoareints(st)) { - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); + + case PSOMUL: + if (pstoptwoareints(st)) { + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); /*~ should check for out-of-range, and push a real instead */ - SAFE_PUSHINT(st,i1 * i2); + SAFE_PUSHINT(st, i1 * i2); } else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); - SAFE_PUSHREAL(st,r1 * r2); + SAFE_PUSHREAL(st, r1 * r2); } break; - case psOpNe: - if (toptwoareints(st)) { + + case PSONE: + if (pstoptwoareints(st)) { SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHBOOL(st, i1 != i2); - } else if (toptwoarenums(st)) { + } else if (pstoptwoarenums(st)) { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); SAFE_PUSHBOOL(st, r1 != r2); } else { SAFE_POPBOOL(st, &b2); SAFE_POPBOOL(st, &b1); - SAFE_PUSHBOOL(st,b1 != b2); + SAFE_PUSHBOOL(st, b1 != b2); } break; - case psOpNeg: - if (topisint(st)) { + + case PSONEG: + if (pstopisint(st)) { SAFE_POPINT(st, &i1); SAFE_PUSHINT(st, -i1); } else { @@ -1294,8 +782,9 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_PUSHREAL(st, -r1); } break; - case psOpNot: - if (topisint(st)) { + + case PSONOT: + if (pstopisint(st)) { SAFE_POPINT(st, &i1); SAFE_PUSHINT(st, ~i1); } else { @@ -1303,92 +792,106 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_PUSHBOOL(st, !b1); } break; - case psOpOr: - if (toptwoareints(st)) { - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); - SAFE_PUSHINT(st,i1 | i2); + + case PSOOR: + if (pstoptwoareints(st)) { + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); + SAFE_PUSHINT(st, i1 | i2); } else { SAFE_POPBOOL(st, &b2); SAFE_POPBOOL(st, &b1); - SAFE_PUSHBOOL(st,b1 || b2); + SAFE_PUSHBOOL(st, b1 || b2); } break; - case psOpPop: + + case PSOPOP: SAFE_POP(st); break; - case psOpRoll: - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); - roll(st,i1, i2); + + case PSOROLL: + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); + psroll(st, i1, i2); break; - case psOpRound: - if (!topisint(st)) { + + case PSOROUND: + if (!pstopisint(st)) { SAFE_POPNUM(st, &r1); - SAFE_PUSHREAL(st,(r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5)); + SAFE_PUSHREAL(st, (r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5)); } break; - case psOpSin: + + case PSOSIN: SAFE_POPNUM(st, &r1); SAFE_PUSHREAL(st, sin(r1/RADIAN)); break; - case psOpSqrt: + + case PSOSQRT: SAFE_POPNUM(st, &r1); SAFE_PUSHREAL(st, sqrt(r1)); break; - case psOpSub: - if (toptwoareints(st)) { - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); - SAFE_PUSHINT(st,i1 - i2); + + case PSOSUB: + if (pstoptwoareints(st)) { + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); + SAFE_PUSHINT(st, i1 - i2); } else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); - SAFE_PUSHREAL(st,r1 - r2); + SAFE_PUSHREAL(st, r1 - r2); } break; - case psOpTrue: - SAFE_PUSHBOOL(st,1); + + case PSOTRUE: + SAFE_PUSHBOOL(st, 1); break; - case psOpTruncate: - if (!topisint(st)) { + + case PSOTRUNCATE: + if (!pstopisint(st)) { SAFE_POPNUM(st, &r1); - SAFE_PUSHREAL(st,(r1 >= 0) ? floor(r1) : ceil(r1)); + SAFE_PUSHREAL(st, (r1 >= 0) ? floor(r1) : ceil(r1)); } break; - case psOpXor: - if (toptwoareints(st)) { - SAFE_POPINT(st,&i2); - SAFE_POPINT(st,&i1); - SAFE_PUSHINT(st,i1 ^ i2); + + case PSOXOR: + if (pstoptwoareints(st)) { + SAFE_POPINT(st, &i2); + SAFE_POPINT(st, &i1); + SAFE_PUSHINT(st, i1 ^ i2); } else { SAFE_POPBOOL(st, &b2); SAFE_POPBOOL(st, &b1); - SAFE_PUSHBOOL(st,b1 ^ b2); + SAFE_PUSHBOOL(st, b1 ^ b2); } break; - case psOpIf: + + case PSOIF: SAFE_POPBOOL(st, &b1); if (b1) { evalpostscriptfunc(func, st, codeptr + 2); } - codeptr = func->u.p.code[codeptr + 1].u.blk; + codeptr = func->u.p.code[codeptr + 1].u.block; break; - case psOpIfelse: + + case PSOIFELSE: SAFE_POPBOOL(st, &b1); if (b1) { evalpostscriptfunc(func, st, codeptr + 2); } else { - evalpostscriptfunc(func, st, func->u.p.code[codeptr].u.blk); + evalpostscriptfunc(func, st, func->u.p.code[codeptr].u.block); } - codeptr = func->u.p.code[codeptr + 1].u.blk; + codeptr = func->u.p.code[codeptr + 1].u.block; break; - case psOpReturn: + + case PSORETURN: return nil; } break; + default: - return fz_throw("syntaxerror : "); + return fz_throw("syntaxerror: postscript calculator"); break; } } @@ -1397,6 +900,470 @@ cleanup: return error; } +/* + * Sample function + */ + +static int bps_supported[] = { 1, 2, 4, 8, 12, 16, 24, 32 }; + +static fz_error * +loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gen) +{ + fz_error *error = nil; + fz_obj *obj; + int samplecount; + int bps; + int i; + + pdf_logrsrc("sampled function {\n", oid, gen); + + func->u.sa.samples = nil; + + obj = fz_dictgets(dict, "Size"); + if (!fz_isarray(obj) || fz_arraylen(obj) != func->m) + goto cleanup0; + for (i = 0; i < func->m; ++i) + func->u.sa.size[i] = fz_toint(fz_arrayget(obj, i)); + + obj = fz_dictgets(dict, "BitsPerSample"); + if (!fz_isint(obj)) + goto cleanup0; + func->u.sa.bps = bps = fz_toint(obj); + + pdf_logrsrc("bsp %d\n", bps); + + for (i = 0; i < nelem(bps_supported); ++i) + if (bps == bps_supported[i]) + break; + if (i == nelem(bps_supported)) + goto cleanup0; + + obj = fz_dictgets(dict, "Encode"); + if (fz_isarray(obj)) + { + if (fz_arraylen(obj) != func->m * 2) + goto cleanup0; + for (i = 0; i < func->m; ++i) + { + func->u.sa.encode[i][0] = fz_toreal(fz_arrayget(obj, i*2+0)); + func->u.sa.encode[i][1] = fz_toreal(fz_arrayget(obj, i*2+1)); + } + } + else + { + for (i = 0; i < func->m; ++i) + { + func->u.sa.encode[i][0] = 0; + func->u.sa.encode[i][1] = func->u.sa.size[i] - 1; + } + } + + obj = fz_dictgets(dict, "Decode"); + if (fz_isarray(obj)) + { + if (fz_arraylen(obj) != func->n * 2) + goto cleanup0; + for (i = 0; i < func->n; ++i) + { + func->u.sa.decode[i][0] = fz_toreal(fz_arrayget(obj, i*2+0)); + func->u.sa.decode[i][1] = fz_toreal(fz_arrayget(obj, i*2+1)); + } + } + else + { + for (i = 0; i < func->n; ++i) + { + func->u.sa.decode[i][0] = func->range[i][0]; + func->u.sa.decode[i][1] = func->range[i][1]; + } + } + + for (i = 0, samplecount = func->n; i < func->m; ++i) + samplecount *= func->u.sa.size[i]; + + pdf_logrsrc("samplecount %d\n", samplecount); + + func->u.sa.samples = fz_malloc(samplecount * sizeof(int)); + if (!func->u.sa.samples) + { + error = fz_outofmem; + goto cleanup0; + } + + error = pdf_openstream(xref, oid, gen); + if (error) + goto cleanup0; + + /* read samples */ + { + unsigned int bitmask = (1 << bps) - 1; + unsigned int buf = 0; + int bits = 0; + int s; + + for (i = 0; i < samplecount; ++i) + { + if (fz_peekbyte(xref->stream) == EOF) + { + error = fz_throw("syntaxerror: too few samples in function"); + goto cleanup1; + } + + if (bps == 8) { + s = fz_readbyte(xref->stream); + } + else if (samplecount == 16) { + s = fz_readbyte(xref->stream); + s = (s << 8) + fz_readbyte(xref->stream); + } + else if (samplecount == 32) { + s = fz_readbyte(xref->stream); + s = (s << 8) + fz_readbyte(xref->stream); + s = (s << 8) + fz_readbyte(xref->stream); + s = (s << 8) + fz_readbyte(xref->stream); + } + else { + while (bits < bps) + { + buf = (buf << 8) | (fz_readbyte(xref->stream) & 0xff); + bits += 8; + } + s = (buf >> (bits - bps)) & bitmask; + bits -= bps; + } + + func->u.sa.samples[i] = s; + + error = fz_ferror(xref->stream); + if (error) + goto cleanup1; + } + } + + pdf_closestream(xref); + + pdf_logrsrc("}\n"); + + return nil; + +cleanup1: + pdf_closestream(xref); +cleanup0: + if (error) return error; + return fz_throw("syntaxerror: sample function"); +} + +static fz_error * +evalsamplefunc(pdf_function *func, float *in, float *out) +{ + float x; + int e[2][MAXM]; + float efrac[MAXM]; + float static0[1 << 4]; + float static1[1 << 4]; + float *s0 = static0; + float *s1 = static1; + int i, j, k; + int idx; + + /* encode input coordinates */ + for (i = 0; i < func->m; i++) + { + x = CLAMP(in[i], func->domain[i][0], func->domain[i][1]); + x = LERP(x, func->domain[i][0], func->domain[i][1], + func->u.sa.encode[i][0], func->u.sa.encode[i][1]); + x = CLAMP(x, 0, func->u.sa.size[i] - 1); + e[0][i] = floor(x); + e[1][i] = ceil(x); + efrac[i] = x - floor(x); + } + + if (func->m > 4) + { + s0 = fz_malloc((1 << func->m) * 2 * sizeof(float)); + s1 = s0 + (1 << func->m); + if (!s0) + return fz_outofmem; + } + + for (i = 0; i < func->n; i++) + { + /* pull 2^m values out of the sample array */ + for (j = 0; j < (1 << func->m); ++j) + { + idx = 0; + for (k = func->m - 1; k >= 0; --k) + idx = idx * func->u.sa.size[k] + e[(j >> k) & 1][k]; + idx = idx * func->n + i; + s0[j] = func->u.sa.samples[idx]; + } + + /* do m sets of interpolations */ + for (j = 0; j < func->m; ++j) + { + for (k = 0; k < (1 << (func->m - j)); k += 2) + s1[k >> 1] = (1 - efrac[j]) * s0[k] + efrac[j] * s0[k+1]; + memcpy(s0, s1, (1 << (func->m - j - 1)) * sizeof(float)); + } + + /* decode output values */ + out[i] = LERP(out[i], 0, (1 << func->u.sa.bps) - 1, + func->u.sa.decode[i][0], func->u.sa.decode[i][1]); + out[i] = CLAMP(out[i], func->range[i][0], func->range[i][1]); + } + + if (func->m > 4) + fz_free(s0); + + return nil; +} + +/* + * Exponential function + */ + +static fz_error * +loadexponentialfunc(pdf_function *func, fz_obj *dict) +{ + fz_error *error = nil; + fz_obj *obj; + int i; + + pdf_logrsrc("exponential function {\n"); + + if (func->m != 1) + goto cleanup; + + obj = fz_dictgets(dict, "N"); + if (!fz_isint(obj) && !fz_isreal(obj)) + goto cleanup; + func->u.e.n = fz_toreal(obj); + pdf_logrsrc("n %g\n", func->u.e.n); + + obj = fz_dictgets(dict, "C0"); + if (fz_isarray(obj)) + { + func->n = fz_arraylen(obj); + for (i = 0; i < func->n; ++i) + func->u.e.c0[i] = fz_toreal(fz_arrayget(obj, i)); + pdf_logrsrc("c0 %d\n", func->n); + } + else + { + func->n = 1; + func->u.e.c0[0] = 0; + } + + obj = fz_dictgets(dict, "C1"); + if (fz_isarray(obj)) + { + if (fz_arraylen(obj) != func->n) + goto cleanup; + for (i = 0; i < func->n; ++i) + func->u.e.c1[i] = fz_toreal(fz_arrayget(obj, i)); + pdf_logrsrc("c1 %d\n", func->n); + } + else + { + if (func->n != 1) + goto cleanup; + func->u.e.c1[0] = 1; + } + + pdf_logrsrc("}\n"); + + return nil; + +cleanup: + if (error) return error; + return fz_throw("syntaxerror: exponential function"); +} + +static fz_error * +evalexponentialfunc(pdf_function *func, float in, float *out) +{ + fz_error *error = nil; + float x = in; + float tmp; + int i; + + x = CLAMP(x, func->domain[0][0], func->domain[0][1]); + + /* constraint */ + if (func->u.e.n != (int)func->u.e.n && x < 0) + goto cleanup; + if (func->u.e.n < 0 && x == 0) + goto cleanup; + + tmp = pow(x, func->u.e.n); + for (i = 0; i < func->n; ++i) + { + out[i] = func->u.e.c0[i] + tmp * (func->u.e.c1[i] - func->u.e.c0[i]); + if (func->hasrange) + out[i] = CLAMP(out[i], func->range[i][0], func->range[i][1]); + } + + return nil; + +cleanup: + if (error) return error; + return fz_throw("rangecheck: exponential function"); +} + +/* + * Stitching function + */ + +static fz_error * +loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) +{ + pdf_function **funcs = func->u.st.funcs; + fz_error *error = nil; + fz_obj *obj; + fz_obj *sub; + fz_obj *num; + int k; + int i; + + pdf_logrsrc("stitching {\n"); + + func->u.st.k = 0; + + if (func->m != 1) + goto cleanup; + + obj = fz_dictgets(dict, "Functions"); + { + error = pdf_resolve(&obj, xref); + if (error) + return error; + + k = fz_arraylen(obj); + func->u.st.k = k; + + pdf_logrsrc("k %d\n", func->u.st.k); + assert(k < MAXK); + + for (i = 0; i < k; ++i) + { + sub = fz_arrayget(obj, i); + error = pdf_loadfunction(funcs + i, xref, sub); + if (error) + goto cleanup; + if (funcs[i]->m != 1 || funcs[i]->n != funcs[0]->n) + goto cleanup; + } + + if (!func->n) + func->n = funcs[0]->n; + else if (func->n != funcs[0]->n) + goto cleanup; + + fz_dropobj(obj); + } + + obj = fz_dictgets(dict, "Bounds"); + { + error = pdf_resolve(&obj, xref); + if (error) + goto cleanup; + + if (!fz_isarray(obj) || fz_arraylen(obj) != k - 1) + goto cleanup; + + for (i = 0; i < k-1; ++i) + { + num = fz_arrayget(obj, i); + if (!fz_isint(num) && !fz_isreal(num)) + goto cleanup; + func->u.st.bounds[i] = fz_toreal(num); + if (i && func->u.st.bounds[i-1] >= func->u.st.bounds[i]) + goto cleanup; + } + + if (k != 1 && + (func->domain[0][0] >= func->u.st.bounds[0] || + func->domain[0][1] <= func->u.st.bounds[k-2])) + goto cleanup; + + fz_dropobj(obj); + } + + obj = fz_dictgets(dict, "Encode"); + { + error = pdf_resolve(&obj, xref); + if (!fz_isarray(obj) || fz_arraylen(obj) != k * 2) + goto cleanup; + for (i = 0; i < k; ++i) + { + func->u.st.encode[i][0] = fz_toreal(fz_arrayget(obj, i*2+0)); + func->u.st.encode[i][1] = fz_toreal(fz_arrayget(obj, i*2+1)); + } + fz_dropobj(obj); + } + + pdf_logrsrc("}\n"); + + return nil; + +cleanup: + fz_dropobj(obj); + if (error) + return error; + return fz_throw("syntaxerror: stitching function"); +} + +static fz_error* +evalstitchingfunc(pdf_function *func, float in, float *out) +{ + fz_error *error = nil; + float low, high; + int k = func->u.st.k; + float *bounds = func->u.st.bounds; + int i; + + in = CLAMP(in, func->domain[0][0], func->domain[0][1]); + + for (i = 0; i < k - 1; ++i) + { + if (in < bounds[i]) + break; + } + + if (i == 0 && k == 1) + { + low = func->domain[0][0]; + high = func->domain[0][1]; + } + else if (i == 0) + { + low = func->domain[0][0]; + high = bounds[0]; + } + else if (i == k - 1) + { + low = bounds[k-2]; + high = func->domain[0][1]; + } + else + { + low = bounds[i-1]; + high = bounds[i]; + } + + in = LERP(in, low, high, func->u.st.encode[i][0], func->u.st.encode[i][1]); + + error = pdf_evalfunction(func->u.st.funcs[i], &in, 1, out, func->n); + if (error) + return error; + + return nil; +} + +/* + * Common + */ + pdf_function * pdf_keepfunction(pdf_function *func) { @@ -1407,46 +1374,23 @@ pdf_keepfunction(pdf_function *func) void pdf_dropfunction(pdf_function *func) { + int i; if (--func->refs == 0) { - int i; - - if(func->domain) - fz_free(func->domain); - - if(func->range) - fz_free(func->range); - - switch(func->type) { - case PDF_FUNC_SAMPLE: - if(func->u.sa.decode) - fz_free(func->u.sa.decode); - if(func->u.sa.encode) - fz_free(func->u.sa.encode); - if(func->u.sa.samples) - fz_free(func->u.sa.samples); + switch(func->type) + { + case SAMPLE: + fz_free(func->u.sa.samples); break; - case PDF_FUNC_EXPONENTIAL: - if(func->u.e.c0) - fz_free(func->u.e.c0); - if(func->u.e.c1) - fz_free(func->u.e.c1); + case EXPONENTIAL: break; - case PDF_FUNC_STITCHING: - if(func->u.st.bounds) - fz_free(func->u.st.bounds); - if(func->u.st.encode) - fz_free(func->u.st.encode); - if(func->u.st.funcs) { - for(i = 0; i < func->u.st.k; ++i) + case STITCHING: + if (func->u.st.funcs) + for (i = 0; i < func->u.st.k; ++i) pdf_dropfunction(func->u.st.funcs[i]); - - fz_free(func->u.st.funcs); - } break; - case PDF_FUNC_POSTSCRIPT: - if(func->u.p.code) - fz_free(func->u.p.code); + case POSTSCRIPT: + fz_free(func->u.p.code); break; } fz_free(func); @@ -1454,127 +1398,119 @@ pdf_dropfunction(pdf_function *func) } fz_error * -pdf_loadfunction(pdf_function **func, pdf_xref *xref, fz_obj *ref) +pdf_loadfunction(pdf_function **funcp, pdf_xref *xref, fz_obj *ref) { - fz_error *error = nil; - fz_obj *objfunc = nil; - fz_obj *tmpobj; - pdf_function *newfunc = nil; - int tmp; + fz_error *error; + pdf_function *func; + fz_obj *dict; + fz_obj *obj; int i; - float min,max; - if ((*func = pdf_finditem(xref->store, PDF_KFUNCTION, ref))) + if ((*funcp = pdf_finditem(xref->store, PDF_KFUNCTION, ref))) + { + pdf_keepfunction(*funcp); return nil; + } - newfunc = fz_malloc(sizeof(pdf_function)); - if(!newfunc) return fz_outofmem; - memset(newfunc,0,sizeof(pdf_function)); - - newfunc->refs = 1; - - objfunc = ref; - error = pdf_resolve(&objfunc,xref); - if(error) { objfunc = nil; goto cleanup; } - - if(!fz_isdict(objfunc)) - goto cleanup; - - /* required */ - tmpobj = fz_dictgets(objfunc,"FunctionType"); - if(!fz_isint(tmpobj)) - goto cleanup; - newfunc->type = fz_toint(tmpobj); - - /* required */ - tmpobj = fz_dictgets(objfunc,"Domain"); - if(!fz_isarray(tmpobj)) - goto cleanup; - tmp = fz_arraylen(tmpobj); - if(tmp % 2) + pdf_logrsrc("load function %d %d {\n", fz_tonum(ref), fz_togen(ref)); + + func = fz_malloc(sizeof(pdf_function)); + if (!func) + return fz_outofmem; + + func->refs = 1; + + dict = ref; + error = pdf_resolve(&dict, xref); + if (error) + { + fz_free(func); goto cleanup; - newfunc->m = tmp / 2; - newfunc->domain = fz_malloc(tmp * sizeof(float)); - for (i = 0; i < tmp / 2; ++i) + } + + obj = fz_dictgets(dict, "FunctionType"); + func->type = fz_toint(obj); + + pdf_logrsrc("type %d\n", func->type); + + /* required for all */ + obj = fz_dictgets(dict, "Domain"); + func->m = fz_arraylen(obj) / 2; + for (i = 0; i < func->m; i++) { - min = fz_toreal(fz_arrayget(tmpobj, i*2)); - max = fz_toreal(fz_arrayget(tmpobj, i*2+1)); - if(min > max) - goto cleanup; - newfunc->domain[i*2] = min; - newfunc->domain[i*2+1] = max; + func->domain[i][0] = fz_toreal(fz_arrayget(obj, i * 2 + 0)); + func->domain[i][1] = fz_toreal(fz_arrayget(obj, i * 2 + 1)); } + pdf_logrsrc("domain %d\n", func->m); /* required for type0 and type4, optional otherwise */ - tmpobj = fz_dictgets(objfunc,"Range"); - if(fz_isarray(tmpobj)) { - tmp = fz_arraylen(tmpobj); - if(tmp % 2) - goto cleanup; - newfunc->n = tmp / 2; - newfunc->range = fz_malloc(tmp * sizeof(float)); - for (i = 0; i < tmp / 2; ++i) + obj = fz_dictgets(dict, "Range"); + if (fz_isarray(obj)) + { + func->hasrange = 1; + func->n = fz_arraylen(obj) / 2; + for (i = 0; i < func->n; i++) { - min = fz_toreal(fz_arrayget(tmpobj, i*2)); - max = fz_toreal(fz_arrayget(tmpobj, i*2+1)); - if(min > max) - goto cleanup; - newfunc->range[i*2] = min; - newfunc->range[i*2+1] = max; + func->range[i][0] = fz_toreal(fz_arrayget(obj, i * 2 + 0)); + func->range[i][1] = fz_toreal(fz_arrayget(obj, i * 2 + 1)); } + pdf_logrsrc("range %d\n", func->n); } - else if(newfunc->type == PDF_FUNC_SAMPLE || - newfunc->type == PDF_FUNC_POSTSCRIPT) - goto cleanup; - - switch(newfunc->type) + else { - case PDF_FUNC_SAMPLE: - if(!fz_isindirect(ref)) - goto cleanup; - if(!pdf_isstream(xref, fz_tonum(ref), fz_togen(ref))) + func->hasrange = 0; + func->n = 0; + } + + assert(func->m < MAXM); + assert(func->n < MAXN); + + switch(func->type) + { + case SAMPLE: + error = loadsamplefunc(func, xref, dict, fz_tonum(ref), fz_togen(ref)); + if (error) goto cleanup; - error = loadsamplefunc(newfunc, xref, objfunc, - fz_tonum(ref), fz_togen(ref)); - if(error) goto cleanup; - break; - case PDF_FUNC_EXPONENTIAL: - error = loadexponentialfunc(newfunc, objfunc); - if(error) goto cleanup; break; - case PDF_FUNC_STITCHING: - error = loadstitchingfunc(newfunc, xref, objfunc); - if(error) goto cleanup; + + case EXPONENTIAL: + error = loadexponentialfunc(func, dict); + if (error) + goto cleanup; break; - case PDF_FUNC_POSTSCRIPT: - if(!fz_isindirect(ref)) + + case STITCHING: + error = loadstitchingfunc(func, xref, dict); + if (error) goto cleanup; - if(!pdf_isstream(xref, fz_tonum(ref), fz_togen(ref))) + break; + + case POSTSCRIPT: + error = loadpostscriptfunc(func, xref, dict, fz_tonum(ref), fz_togen(ref)); + if (error) goto cleanup; - error = loadpostscriptfunc(newfunc, xref, objfunc, - fz_tonum(ref), fz_togen(ref)); - if(error) goto cleanup; break; + default: + error = fz_throw("syntaxerror: unknown function type"); goto cleanup; } - - fz_dropobj(objfunc); - error = pdf_storeitem(xref->store, PDF_KFUNCTION, ref, newfunc); - if (error) goto cleanup; + fz_dropobj(dict); - *func = newfunc; + pdf_logrsrc("}\n"); + + error = pdf_storeitem(xref->store, PDF_KFUNCTION, ref, func); + if (error) + goto cleanup; + + *funcp = func; return nil; - + cleanup: - if(objfunc) - fz_dropobj(objfunc); - - pdf_dropfunction(newfunc); - - if(error) return error; - return fz_throw("syntaxerror : "); + fz_dropobj(dict); + pdf_dropfunction(func); + return error; } fz_error * @@ -1583,36 +1519,40 @@ pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outle fz_error *error = nil; int i; -// if(func->m != inlen || func->n != outlen) -// return fz_throw("syntaxerror : input lenth or output length mismatch"); + if (func->m != inlen || func->n != outlen) + return fz_throw("rangecheck: function argument count mismatch"); - switch(func->type) { - case PDF_FUNC_SAMPLE: - error = evalsamplefunc(func, in, out); - break; - case PDF_FUNC_EXPONENTIAL: - error = evalexponentialfunc(func, *in, out); - break; - case PDF_FUNC_STITCHING: - error = evalstitchingfunc(func, *in, out); - break; - case PDF_FUNC_POSTSCRIPT: + switch(func->type) + { + case SAMPLE: + return evalsamplefunc(func, in, out); + case EXPONENTIAL: + return evalexponentialfunc(func, *in, out); + case STITCHING: + return evalstitchingfunc(func, *in, out); + + case POSTSCRIPT: { psstack st; - initstack(&st); + psinitstack(&st); + for (i = 0; i < func->m; ++i) - SAFE_PUSHREAL(&st,in[i]); + SAFE_PUSHREAL(&st, in[i]); error = evalpostscriptfunc(func, &st, 0); - if(error) goto cleanup; + if (error) + return error; - for (i = func->n - 1; i >= 0; --i) { - SAFE_POPNUM(&st,out+i); - MIN_MAX(out[i],func->range[i*2],func->range[i*2+1]); + for (i = func->n - 1; i >= 0; --i) + { + SAFE_POPNUM(&st, out+i); + out[i] = CLAMP(out[i], func->range[i][0], func->range[i][1]); } } - break; + return nil; } + cleanup: return error; } + diff --git a/mupdf/shade.c b/mupdf/shade.c index d273d817..05a53e72 100644 --- a/mupdf/shade.c +++ b/mupdf/shade.c @@ -17,7 +17,7 @@ pdf_loadshadefunction(fz_shade *shade, pdf_xref *xref, fz_obj *shading, float t0 for (int i=0; i<256; ++i) { t = t0 + (i / 255.0) * (t1 - t0); - error = pdf_evalfunction(func, &t, 1, shade->function[i], 0); + error = pdf_evalfunction(func, &t, 1, shade->function[i], shade->colorspace->n); } if (error) return error; diff --git a/render/meshdraw.c b/render/meshdraw.c index 5264a2f1..79a49768 100644 --- a/render/meshdraw.c +++ b/render/meshdraw.c @@ -234,12 +234,9 @@ fz_drawtriangle(fz_pixmap *pix, float *av, float *bv, float *cv, int n) int i, k; - for (i = 0; i < n; i++) - { - poly[0][i] = av[i]; - poly[1][i] = bv[i]; - poly[2][i] = cv[i]; - } + copyvert(poly[0], av, n); + copyvert(poly[1], bv, n); + copyvert(poly[2], cv, n); len = clippoly(poly, temp, 3, n, cx0, 0, 0); len = clippoly(temp, poly, len, n, cx1, 0, 1); diff --git a/render/render.c b/render/render.c index 6db055bd..a754f6ca 100644 --- a/render/render.c +++ b/render/render.c @@ -484,6 +484,8 @@ rendershade(fz_renderer *gc, fz_shadenode *node, fz_matrix ctm) assert(!gc->maskonly); + DEBUG("shade;\n"); + bbox = fz_roundrect(fz_boundnode((fz_node*)node, ctm)); bbox = fz_intersectirects(gc->clip, bbox); |