summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-12-08 04:07:39 +0100
committerTor Andersson <tor@ghostscript.com>2004-12-08 04:07:39 +0100
commit6bed81dda73a38ca993f1970125c3cf800f6cce8 (patch)
treeb9da08c7362ba8457dc99484b7a383008ebd02a1
parent25a178ec4d53df16d5166760600f76bedf20ee74 (diff)
downloadmupdf-6bed81dda73a38ca993f1970125c3cf800f6cce8.tar.xz
de-nauseate function.c
-rw-r--r--include/mupdf/rsrc.h2
-rw-r--r--mupdf/debug.c2
-rw-r--r--mupdf/function.c2122
-rw-r--r--mupdf/shade.c2
-rw-r--r--render/meshdraw.c9
-rw-r--r--render/render.c2
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);