diff options
author | Kim Jeong Hee <jeong@pdfpro.co.kr> | 2004-11-30 09:56:33 +0100 |
---|---|---|
committer | Kim Jeong Hee <jeong@pdfpro.co.kr> | 2004-11-30 09:56:33 +0100 |
commit | b772787951d718a0ae5e51355acbe4d66ab793c3 (patch) | |
tree | bf10875bc9abb654c85bf934f1d5031969f1cd47 | |
parent | 170ed5fe09746901cc53bb0ad501d43f9864323e (diff) | |
download | mupdf-b772787951d718a0ae5e51355acbe4d66ab793c3.tar.xz |
first clumsy shade implementation
-rw-r--r-- | include/fitz/shade.h | 12 | ||||
-rw-r--r-- | mupdf/function.c | 163 | ||||
-rw-r--r-- | mupdf/shade.c | 117 | ||||
-rw-r--r-- | render/rastshade.c | 428 | ||||
-rw-r--r-- | render/render.c | 3 |
5 files changed, 638 insertions, 85 deletions
diff --git a/include/fitz/shade.h b/include/fitz/shade.h index 542581c9..c8a47ffd 100644 --- a/include/fitz/shade.h +++ b/include/fitz/shade.h @@ -4,6 +4,18 @@ struct fz_shade_s { int refs; fz_colorspace *cs; + fz_obj *background; + fz_rect *bbox; + int antialias; + + int type; + fz_obj *coords; + fz_obj *domain; + fz_matrix matrix; + fz_matrix matrix2; + void *function; + fz_obj *extend; + /* ... */ }; diff --git a/mupdf/function.c b/mupdf/function.c index 9838d4df..eb246a12 100644 --- a/mupdf/function.c +++ b/mupdf/function.c @@ -62,40 +62,40 @@ else if(a > (max)) a = (max); (ymin) + ((x)-(xmin)) * ((ymax)-(ymin)) / ((xmax) - (xmin)); #define SAFE_PUSHINT(st,a)\ - {err = pushint(st,a);\ - if(err) goto cleanup;} + {error = pushint(st,a);\ + if(error) goto cleanup;} #define SAFE_PUSHREAL(st,a)\ - {err = pushreal(st,a);\ - if(err) goto cleanup;} + {error = pushreal(st,a);\ + if(error) goto cleanup;} #define SAFE_PUSHBOOL(st,a)\ - {err = pushbool(st,a);\ - if(err) goto cleanup;} + {error = pushbool(st,a);\ + if(error) goto cleanup;} #define SAFE_POPINT(st,a)\ - {err = popint(st,a);\ - if(err) goto cleanup;} + {error = popint(st,a);\ + if(error) goto cleanup;} #define SAFE_POPNUM(st,a)\ - {err = popnum(st,a);\ - if(err) goto cleanup;} + {error = popnum(st,a);\ + if(error) goto cleanup;} #define SAFE_POPBOOL(st,a)\ - {err = popbool(st,a);\ - if(err) goto cleanup;} + {error = popbool(st,a);\ + if(error) goto cleanup;} #define SAFE_POP(st)\ - {err = pop(st);\ - if(err) goto cleanup;} + {error = pop(st);\ + if(error) goto cleanup;} #define SAFE_INDEX(st,i)\ - {err = index(st,i);\ - if(err) goto cleanup;} + {error = index(st,i);\ + if(error) goto cleanup;} #define SAFE_COPY(st,n)\ - {err = copy(st,n);\ - if(err) goto cleanup;} + {error = copy(st,n);\ + if(error) goto cleanup;} #define RADIAN 57.2957795 @@ -434,7 +434,7 @@ pop(psstack *st) static fz_error * loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gid) { - fz_error *err = nil; + fz_error *error = nil; fz_obj *tmpobj; int i; int bps; @@ -526,8 +526,8 @@ loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gi } /* read samples from stream */ - err = pdf_openstream(xref, oid, gid); - if (err) goto cleanup; + error = pdf_openstream(xref, oid, gid); + if (error) goto cleanup; for(i = 0, samplecount = func->n; i < func->m; ++i) samplecount *= size[i]; @@ -536,7 +536,7 @@ loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gi streamsamples = fz_malloc(bytetoread); samples = fz_malloc(samplecount * sizeof(int)); func->u.sa.samples = samples; - if(!streamsamples || !samples) { err = fz_outofmem; goto cleanup2; } + if(!streamsamples || !samples) { error = fz_outofmem; goto cleanup2; } /* read samples */ { @@ -551,7 +551,7 @@ loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gi if(readbyte != bytetoread) { - err = fz_throw("syntaxerror : "); + error = fz_throw("syntaxerror : "); goto cleanup2; } @@ -583,10 +583,10 @@ cleanup2: fz_free(streamsamples); pdf_closestream(xref); - return err; + return error; cleanup: - if(err) return err; + if(error) return error; return fz_throw("syntaxerror : "); } @@ -663,7 +663,7 @@ cleanup: static fz_error * loadexponentialfunc(pdf_function *func, fz_obj *dict) { - fz_error *err = nil; + fz_error *error = nil; fz_obj *tmpobj; int i; float *c0, *c1; @@ -688,7 +688,7 @@ loadexponentialfunc(pdf_function *func, fz_obj *dict) func->n = fz_arraylen(tmpobj); func->u.e.c0 = c0 = fz_malloc(func->n * sizeof(float)); - if(!c0) { err = fz_outofmem; goto cleanup; } + if(!c0) { error = fz_outofmem; goto cleanup; } for(i = 0; i < func->n; ++i) { objnum = fz_arrayget(tmpobj,i); @@ -704,7 +704,7 @@ loadexponentialfunc(pdf_function *func, fz_obj *dict) func->n = 1; func->u.e.c0 = c0 = fz_malloc(func->n * sizeof(float)); - if(!c0) { err = fz_outofmem; goto cleanup; } + if(!c0) { error = fz_outofmem; goto cleanup; } c0[0] = 0; } @@ -712,7 +712,7 @@ loadexponentialfunc(pdf_function *func, fz_obj *dict) /* optional */ tmpobj = fz_dictgets(dict,"C1"); func->u.e.c1 = c1 = fz_malloc(func->n * sizeof(float)); - if(!c1) { err = fz_outofmem; goto cleanup; } + if(!c1) { error = fz_outofmem; goto cleanup; } if(fz_isarray(tmpobj)) { fz_obj *objnum; @@ -736,14 +736,14 @@ loadexponentialfunc(pdf_function *func, fz_obj *dict) return nil; cleanup: - if(err) return err; + if(error) return error; return fz_throw("syntaxerror : "); } static fz_error * evalexponentialfunc(pdf_function *func, float in, float *out) { - fz_error *err = nil; + fz_error *error = nil; float x = in; float tmp; int i; @@ -771,14 +771,14 @@ evalexponentialfunc(pdf_function *func, float in, float *out) return nil; cleanup: - if(err) return err; + if(error) return error; return fz_throw("syntaxerror : "); } static fz_error * loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) { - fz_error *err = nil; + fz_error *error = nil; fz_obj *tmpobj; fz_obj *funcobj; fz_obj *numobj; @@ -792,18 +792,21 @@ loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) /* 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) { err = fz_outofmem; goto cleanup; } + 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); - err = pdf_loadfunction(funcs+i,xref,funcobj); - if(err) goto cleanup; + error = pdf_loadfunction(funcs+i,xref,funcobj); + if(error) goto cleanup; if(funcs[i]->m != 1 || funcs[i]->n != funcs[0]->n) goto cleanup; } @@ -815,11 +818,14 @@ loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) /* 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) { err = fz_outofmem; goto cleanup; } + if(!bounds) { error = fz_outofmem; goto cleanup; } for(i = 0; i < k-1; ++i) { numobj = fz_arrayget(tmpobj,i); @@ -835,11 +841,12 @@ loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) /* 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) { err = fz_outofmem; goto cleanup; } + if(!encode) { error = fz_outofmem; goto cleanup; } for(i = 0; i < k*2; ++i) { numobj = fz_arrayget(tmpobj,i); @@ -853,14 +860,14 @@ loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) return nil; cleanup: - if(err) return err; + if(error) return error; return fz_throw("syntaxerror : "); } static fz_error* evalstitchingfunc(pdf_function *func, float in, float *out) { - fz_error *err = nil; + fz_error *error = nil; float low,high; int k = func->u.st.k; float *bounds = func->u.st.bounds; @@ -874,7 +881,7 @@ evalstitchingfunc(pdf_function *func, float in, float *out) } if(i == 0) { low = func->domain[0]; - high = bounds[0]; + high = func->domain[1]; } else if(i == k - 1) { low = bounds[k-2]; @@ -888,8 +895,8 @@ evalstitchingfunc(pdf_function *func, float in, float *out) in = INTERPOLATE(in,low,high, func->u.st.encode[i*2],func->u.st.encode[i*2 + 1]); - err = pdf_evalfunction(func->u.st.funcs[i],&in,1,out,func->n); - if(err) return err; + error = pdf_evalfunction(func->u.st.funcs[i],&in,1,out,func->n); + if(error) return error; return nil; } @@ -911,7 +918,7 @@ resizecode(pdf_function *func, int newsize) { static fz_error * parsecode(pdf_function *func, fz_file *stream, int *codeptr) { - fz_error *err = nil; + fz_error *error = nil; char buf[64]; int buflen = sizeof(buf) / sizeof(buf[0]); int len; @@ -944,8 +951,8 @@ parsecode(pdf_function *func, fz_file *stream, int *codeptr) opPtr = *codeptr; *codeptr += 3; resizecode(func,opPtr + 2); - err = parsecode(func, stream, codeptr); - if(err) goto cleanup; + error = parsecode(func, stream, codeptr); + if(error) goto cleanup; token = pdf_lex(stream,buf,buflen,&len); @@ -954,8 +961,8 @@ parsecode(pdf_function *func, fz_file *stream, int *codeptr) if(token == PDF_TOBRACE) { elsePtr = *codeptr; - err = parsecode(func, stream, codeptr); - if(err) goto cleanup; + error = parsecode(func, stream, codeptr); + if(error) goto cleanup; token = pdf_lex(stream,buf,buflen,&len); if(token == PDF_TERROR || token == PDF_TEOF) goto cleanup; @@ -1023,7 +1030,7 @@ parsecode(pdf_function *func, fz_file *stream, int *codeptr) } return nil; cleanup: - if(err) return err; + if(error) return error; return fz_throw("syntaxerror : postscript code"); } @@ -1031,32 +1038,32 @@ static fz_error * loadpostscriptfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gid) { - fz_error *err = nil; + fz_error *error = nil; int codeptr; /* read postcript from stream */ - err = pdf_openstream(xref, oid, gid); - if (err) goto cleanup; + error = pdf_openstream(xref, oid, gid); + if (error) goto cleanup; codeptr = 0; if(fz_readbyte(xref->stream) != '{') goto cleanup; - err = parsecode(func, xref->stream, &codeptr); - if(err) goto cleanup; + error = parsecode(func, xref->stream, &codeptr); + if(error) goto cleanup; pdf_closestream(xref); return nil; cleanup: pdf_closestream(xref); - if(err) return err; + if(error) return error; return fz_throw("syntaxerror : "); } static fz_error * evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) { - fz_error *err = nil; + fz_error *error = nil; int i1, i2; float r1, r2; int b1, b2; @@ -1386,7 +1393,7 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) } cleanup: - return err; + return error; } void @@ -1438,7 +1445,7 @@ pdf_dropfunction(pdf_function *func) fz_error * pdf_loadfunction(pdf_function **func, pdf_xref *xref, fz_obj *obj) { - fz_error *err = nil; + fz_error *error = nil; fz_obj *objfunc = nil; fz_obj *tmpobj; pdf_function *newfunc = nil; @@ -1451,8 +1458,8 @@ pdf_loadfunction(pdf_function **func, pdf_xref *xref, fz_obj *obj) memset(newfunc,0,sizeof(pdf_function)); objfunc = obj; - err = pdf_resolve(&objfunc,xref); - if(err) { objfunc = nil; goto cleanup; } + error = pdf_resolve(&objfunc,xref); + if(error) { objfunc = nil; goto cleanup; } if(!fz_isdict(objfunc)) goto cleanup; @@ -1511,26 +1518,26 @@ pdf_loadfunction(pdf_function **func, pdf_xref *xref, fz_obj *obj) goto cleanup; if(!pdf_isstream(xref, fz_tonum(obj), fz_togen(obj))) goto cleanup; - err = loadsamplefunc(newfunc, xref, objfunc, + error = loadsamplefunc(newfunc, xref, objfunc, fz_tonum(obj), fz_togen(obj)); - if(err) goto cleanup; + if(error) goto cleanup; break; case PDF_FUNC_EXPONENTIAL: - err = loadexponentialfunc(newfunc, objfunc); - if(err) goto cleanup; + error = loadexponentialfunc(newfunc, objfunc); + if(error) goto cleanup; break; case PDF_FUNC_STITCHING: - err = loadstitchingfunc(newfunc, xref, objfunc); - if(err) goto cleanup; + error = loadstitchingfunc(newfunc, xref, objfunc); + if(error) goto cleanup; break; case PDF_FUNC_POSTSCRIPT: if(!fz_isindirect(obj)) goto cleanup; if(!pdf_isstream(xref, fz_tonum(obj), fz_togen(obj))) goto cleanup; - err = loadpostscriptfunc(newfunc, xref, objfunc, + error = loadpostscriptfunc(newfunc, xref, objfunc, fz_tonum(obj), fz_togen(obj)); - if(err) goto cleanup; + if(error) goto cleanup; break; default: goto cleanup; @@ -1548,28 +1555,28 @@ cleanup: pdf_dropfunction(newfunc); - if(err) return err; + if(error) return error; return fz_throw("syntaxerror : "); } fz_error * pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outlen) { - fz_error *err = nil; + 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("syntaxerror : input lenth or output length mismatch"); switch(func->type) { case PDF_FUNC_SAMPLE: - err = evalsamplefunc(func, in, out); + error = evalsamplefunc(func, in, out); break; case PDF_FUNC_EXPONENTIAL: - err = evalexponentialfunc(func, *in, out); + error = evalexponentialfunc(func, *in, out); break; case PDF_FUNC_STITCHING: - err = evalstitchingfunc(func, *in, out); + error = evalstitchingfunc(func, *in, out); break; case PDF_FUNC_POSTSCRIPT: { @@ -1578,8 +1585,8 @@ pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outle for (i = 0; i < func->m; ++i) SAFE_PUSHREAL(&st,in[i]); - err = evalpostscriptfunc(func, &st, 0); - if(err) goto cleanup; + error = evalpostscriptfunc(func, &st, 0); + if(error) goto cleanup; for (i = func->n - 1; i >= 0; --i) { SAFE_POPNUM(&st,out+i); @@ -1589,5 +1596,5 @@ pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outle break; } cleanup: - return err; + return error; } diff --git a/mupdf/shade.c b/mupdf/shade.c index 9d5e4568..472390bc 100644 --- a/mupdf/shade.c +++ b/mupdf/shade.c @@ -2,18 +2,133 @@ #include <mupdf.h> fz_error * +pdf_loadshadedict(fz_shade **shadep, pdf_xref *xref, fz_obj *shading, fz_obj *ref, fz_matrix mat) +{ + fz_error *error; + fz_shade *shade; + pdf_function *func; + + fz_colorspace *cs = nil; + + fz_obj *sobj; + int type; + + shade = fz_malloc(sizeof(fz_shade)); + + shade->matrix = mat; + + sobj = fz_dictgets(shading, "ShadingType"); + type = fz_toint(sobj); + + shade->type = type; + + sobj = fz_dictgets(shading, "ColorSpace"); + if (sobj) + { + error = pdf_resolve(&sobj, xref); + if (error) + return error; + + error = pdf_loadcolorspace(&cs, xref, sobj); + if (error) + return error; + + /* + if (!strcmp(cs->name, "Indexed")) + { + indexed = (pdf_indexed*)cs; + cs = indexed->base; + } + n = cs->n; + a = 0; + */ + + fz_dropobj(sobj); + } + shade->cs = cs; + + shade->background = fz_dictgets(shading, "Background"); + + //shade->bbox = fz_torect(fz_dictgets(shading, "BBox")); + shade->antialias = fz_toint(fz_dictgets(shading, "AntiAlias")); + + switch(type) { + case 1: + shade->domain = fz_dictgets(shading, "Domain"); +// shade->matrix = fz_dictgets(shading, "Matrix"); /* NYI */ + sobj = fz_dictgets(shading, "Function"); + error = pdf_loadfunction(&shade->function, xref, sobj); + if (error) goto cleanup; + + break; + case 2: + case 3: + shade->coords = fz_dictgets(shading, "Coords"); + shade->domain = fz_dictgets(shading, "Domain"); + sobj = fz_dictgets(shading, "Function"); +// if (fz_isindirect(sobj)) { +// error = pdf_loadindirect(&sobj, xref, sobj); +// } + error = pdf_loadfunction(&shade->function, xref, sobj); + if (error) goto cleanup; + + shade->extend = fz_dictgets(shading, "Extend"); + break; + case 4: + break; + default: + }; + + *shadep = shade; + return nil; + +cleanup: + return error; +} + +fz_error * pdf_loadshade(fz_shade **shadep, pdf_xref *xref, fz_obj *obj, fz_obj *ref) { fz_error *error; fz_shade *shade; + + fz_obj *shading; + fz_matrix mat; + fz_obj *extgstate; shade = fz_malloc(sizeof(fz_shade)); if (!shade) return fz_outofmem; printf("loading shade pattern\n"); + shading = fz_dictgets(obj, "Shading"); + + if (fz_isindirect(shading)) { + error = pdf_loadindirect(&shading, xref, shading); + if (error) goto cleanup; + } + + obj = fz_dictgets(obj, "Matrix"); + if (obj) { + mat.a = fz_toreal(fz_arrayget(obj, 0)); + mat.b = fz_toreal(fz_arrayget(obj, 1)); + mat.c = fz_toreal(fz_arrayget(obj, 2)); + mat.d = fz_toreal(fz_arrayget(obj, 3)); + mat.e = fz_toreal(fz_arrayget(obj, 4)); + mat.f = fz_toreal(fz_arrayget(obj, 5)); + } + else { + mat = fz_identity(); + } - /* ... */ + if (fz_isdict(shading)) { + pdf_loadshadedict(&shade, xref, shading, ref, mat); + } + else if (pdf_isstream(xref, fz_tonum(shading), fz_togen(shading))) { + goto cleanup; /* NYI */ + } + else + goto cleanup; *shadep = shade; return nil; diff --git a/render/rastshade.c b/render/rastshade.c index 7e7f82ce..89a06f40 100644 --- a/render/rastshade.c +++ b/render/rastshade.c @@ -1,10 +1,432 @@ #include <fitz.h> +#include <mupdf.h> + +fz_error * +fz_rendershade1(fz_shade *shade, fz_matrix ctm, fz_colorspace *dsts, fz_pixmap *dstp, int over) +{ + fz_error *error; + int x, y; + int dx, dy, dw, dh; + float x0, y0, x1, y1; + float xp; + float yp; + // pdf_function *func; + + dx = dstp->x; + dy = dstp->y; + dw = dstp->w; + dh = dstp->h; + + x0 = 0; + y0 = 0; + x1 = 0; + y1 = 0; + + for (int y = 0; y < dh; ++y) { + for (int x = 0; x < dw; ++x) { + float outcol[16], outn; + float destcol[16]; + xp = ((x1 - x0) * (x - x0) + (y1 - y0) * (y - y0)) + / ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); + + error = pdf_evalfunction(shade->function, &xp, 1, outcol, outn); + shade->cs->convcolor(shade->cs, outcol, dsts, destcol); + dstp->samples[(x+y*dw)*4+0] = 255; + dstp->samples[(x+y*dw)*4+1] = destcol[0] * 255; + dstp->samples[(x+y*dw)*4+2] = destcol[1] * 255; + dstp->samples[(x+y*dw)*4+3] = destcol[2] * 255; + } + } + + return error; +} + +fz_error * +fz_rendershade2(fz_shade *shade, fz_matrix ctm, fz_colorspace *dsts, fz_pixmap *dstp, int over) +{ + fz_error *error; + int x, y; + int dx, dy, dw, dh; + float x0, y0, x1, y1; + float t0, t1; + int e0, e1; + float xp; + float yp; + // pdf_function *func; + int destcol[512][4]; + + ctm = fz_concat(shade->matrix, ctm); + + dx = dstp->x; + dy = dstp->y; + dw = dstp->w; + dh = dstp->h; + + x0 = fz_toreal(fz_arrayget(shade->coords, 0)); + y0 = fz_toreal(fz_arrayget(shade->coords, 1)); + x1 = fz_toreal(fz_arrayget(shade->coords, 2)); + y1 = fz_toreal(fz_arrayget(shade->coords, 3)); + + if (shade->domain) { + t0 = fz_toreal(fz_arrayget(shade->domain, 0)); + t1 = fz_toreal(fz_arrayget(shade->domain, 1)); + } else { + t0 = 0.; + t1 = 1.; + } + + if (shade->extend) { + e0 = fz_toint(fz_arrayget(shade->extend, 0)); + e1 = fz_toint(fz_arrayget(shade->extend, 1)); + } else { + e0 = 0; + e1 = 0; + } + + /* build color table */ + for (int i=0; i<512; ++i) { + float destc[4]; + float outcol[4]; + float t = (i / 511.) / (t1 - t0) - t0; + error = pdf_evalfunction(shade->function, &t, 1, outcol, 3); + shade->cs->convcolor(shade->cs, outcol, dsts, destc); + destcol[i][0] = destc[0]*255.; + destcol[i][1] = destc[1]*255.; + destcol[i][2] = destc[2]*255.; + } + + for (int y = 0; y < dh; ++y) { + for (int x = 0; x < dw; ++x) { + int cidx; + float t; + float ix, iy; + + xp = x + dx; + yp = y + dy; + + ix = (xp * ctm.d - yp * ctm.c + ctm.c * ctm.f - ctm.e*ctm.d) + / (ctm.a * ctm.d - ctm.b * ctm.c); /* inverse */ + iy = (xp * ctm.b - yp * ctm.a + ctm.a * ctm.f - ctm.b*ctm.e) + / (ctm.b * ctm.c - ctm.a * ctm.d); /* inverse */ + + t = ((x1 - x0) * (ix - x0) + (y1 - y0) * (iy - y0)) + / ((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); + + cidx = ((t + t0) * (t1 - t0)) * 511; + + dstp->samples[(x+y*dw)*4+0] = 255; + dstp->samples[(x+y*dw)*4+1] = destcol[cidx][0]; + dstp->samples[(x+y*dw)*4+2] = destcol[cidx][1]; + dstp->samples[(x+y*dw)*4+3] = destcol[cidx][2]; + } + } + + return error; +} + +#define putpixel(x, y, c) \ + if (x >= 0 && x < dstp->w && y >= 0 && y < dstp->h) { \ + dstp->samples[((x)+(y)*(dstp->w))*4+0] = 255; \ + dstp->samples[((x)+(y)*(dstp->w))*4+1] = c[0]; \ + dstp->samples[((x)+(y)*(dstp->w))*4+2] = c[1]; \ + dstp->samples[((x)+(y)*(dstp->w))*4+3] = c[2]; \ + } \ + + +typedef struct fz_vertex +{ + float x, y; + float l; +} fz_vertex; + +typedef struct fz_triangle +{ + fz_vertex vertex[3]; +} fz_triangle; + +void fz_swapvertex(fz_vertex *a, fz_vertex *b) +{ + fz_vertex temp; + temp = *a; + *a = *b; + *b = temp; +} + +int fz_pointinrect(fz_point point, fz_rect rect) +{ + if (point.x < rect.min.x || point.x > rect.max.x) return 0; + if (point.y < rect.min.y || point.y > rect.max.y) return 0; + + return 1; +} + +void fz_drawgouraudtriangle(fz_triangle triangle, fz_pixmap *dstp, int destcol[512][4], + int bx0, int by0, int bx1, int by1) +{ + fz_vertex a, b, c; + + a = triangle.vertex[0]; + b = triangle.vertex[1]; + c = triangle.vertex[2]; + + /* need more accurate clipping method */ + { + fz_rect bb1; + fz_rect bb2; + + bb1.min.x = min(min(a.x, b.x), c.x); + bb1.min.y = min(min(a.y, b.y), c.y); + bb1.max.x = max(max(a.x, b.x), c.x); + bb1.max.y = max(max(a.y, b.y), c.y); + + bb2.min.x = bx0; + bb2.min.y = by0; + bb2.max.x = bx1; + bb2.max.y = by1; + + if (fz_isemptyrect(fz_intersectrects(bb1, bb2))) + return; + } + + if(a.y > b.y) fz_swapvertex(&a, &b); + if(a.y > c.y) fz_swapvertex(&a, &c); + if(b.y > c.y) fz_swapvertex(&b, &c); + + float diff_y = (b.y - a.y); + float slopeab_x = (b.x - a.x) / diff_y; + float slopeab_l = (b.l - a.l) / diff_y; + float xab = a.x; + float lab = a.l; + diff_y = (c.y - a.y); + float slopeac_x = (c.x - a.x) / diff_y; + float slopeac_l = (c.l - a.l) / diff_y; + float xac = a.x; + float lac = a.l; + int maxy = (int)(b.y); + + int incx; + int y; + for(y = (int)(a.y); y < maxy; y++) + { + int maxx = (int)(xac); + if(xab < xac) incx = 1; + else incx = -1; + float diff_x = (xac - xab) * incx; + float slope_l = (lac - lab) / diff_x; + float l = lab; + + for(int x = (int)(xab); x != maxx+incx; x += incx) + { + if (l >= 0 && l <= 511) + putpixel(x, y, destcol[(int)(l)]); + l += slope_l; + } + + xab += slopeab_x; + lab += slopeab_l; + xac += slopeac_x; + lac += slopeac_l; + } + + diff_y = (c.y - b.y); + float slopebc_x = (c.x - b.x) / diff_y; + float slopebc_l = (c.l - b.l) / diff_y; + float xbc = b.x; + float lbc = b.l; + maxy = (int)(c.y); + for(; y < maxy; y++) + { + int maxx = (int)(xac); + if(xbc < xac) incx = 1; + else incx = -1; + float diff_x = (xac - xbc) * incx; + float slope_l = (lac - lbc) / diff_x; + float l = lbc; + for(int x = (int)(xbc); x != maxx+incx; x += incx) + { + if (l >= 0 && l <= 511) + putpixel(x, y, destcol[(int)(l)]); + l += slope_l; + } + + xac += slopeac_x; + lac += slopeac_l; + xbc += slopebc_x; + lbc += slopebc_l; + } +} + +fz_error * +fz_renderannulus(int x0, int y0, int r0, int x1, int y1, int r1, int t0, int t1, + fz_matrix ctm, fz_pixmap *dstp, int destcol[512][4]) +{ + fz_point pt1, pt2, pt3, pt4; + fz_triangle triangle; + float step; + float theta; + + ctm = fz_concat(ctm, fz_translate(-dstp->x, -dstp->y)); + + /* + theta = atan((y1 - y0) / (x1 - x0)); + if ((x1 - x0) < 0) theta += M_PI; + theta -= (M_PI / 2.); + */ + theta = 0; + step = 3.1415921 * 2 / 36.; + for (; theta < step*36; theta += step) { + pt1.x = cos (theta) * r1 + x1; + pt1.y = sin (theta) * r1 + y1; + pt2.x = cos (theta) * r0 + x0; + pt2.y = sin (theta) * r0 + y0; + pt3.x = cos (theta+step) * r1 + x1; + pt3.y = sin (theta+step) * r1 + y1; + pt4.x = cos (theta+step) * r0 + x0; + pt4.y = sin (theta+step) * r0 + y0; + + pt1 = fz_transformpoint(ctm, pt1); + pt2 = fz_transformpoint(ctm, pt2); + pt3 = fz_transformpoint(ctm, pt3); + pt4 = fz_transformpoint(ctm, pt4); + + triangle.vertex[0].x = pt1.x; + triangle.vertex[0].y = pt1.y; + triangle.vertex[0].l = t1; + triangle.vertex[1].x = pt2.x; + triangle.vertex[1].y = pt2.y; + triangle.vertex[1].l = t0; + triangle.vertex[2].x = pt4.x; + triangle.vertex[2].y = pt4.y; + triangle.vertex[2].l = t0; + + fz_drawgouraudtriangle(triangle, dstp, destcol, 0, 0, dstp->w, dstp->h); + + triangle.vertex[0].x = pt1.x; + triangle.vertex[0].y = pt1.y; + triangle.vertex[0].l = t1; + triangle.vertex[1].x = pt3.x; + triangle.vertex[1].y = pt3.y; + triangle.vertex[1].l = t1; + triangle.vertex[2].x = pt4.x; + triangle.vertex[2].y = pt4.y; + triangle.vertex[2].l = t0; + + fz_drawgouraudtriangle(triangle, dstp, destcol, 0, 0, dstp->w, dstp->h); + } +} + +fz_error * +fz_rendershade3(fz_shade *shade, fz_matrix ctm, fz_colorspace *dsts, fz_pixmap *dstp, int over) +{ + fz_error *error; + int x, y; + int dx, dy, dw, dh; + float x0, y0, r0, x1, y1, r1; + float t0, t1; + float xp; + float yp; + int e0, e1; + float t; + int destcol[512][4]; + int cidx0, cidx1; + + ctm = fz_concat(shade->matrix, ctm); + + dx = dstp->x; dy = dstp->y; + dw = dstp->w; dh = dstp->h; + + x0 = fz_toreal(fz_arrayget(shade->coords, 0)); + y0 = fz_toreal(fz_arrayget(shade->coords, 1)); + r0 = fz_toreal(fz_arrayget(shade->coords, 2)); + x1 = fz_toreal(fz_arrayget(shade->coords, 3)); + y1 = fz_toreal(fz_arrayget(shade->coords, 4)); + r1 = fz_toreal(fz_arrayget(shade->coords, 5)); + + if (shade->domain) { + t0 = fz_toreal(fz_arrayget(shade->domain, 0)); + t1 = fz_toreal(fz_arrayget(shade->domain, 1)); + } else { + t0 = 0.; + t1 = 1.; + } + + if (shade->extend) { + e0 = fz_toint(fz_arrayget(shade->extend, 0)); + e1 = fz_toint(fz_arrayget(shade->extend, 1)); + } else { + e0 = 0; + e1 = 0; + } + + /* build color table */ + for (int i=0; i<512; ++i) { + float destc[4]; + float outcol[4]; + float t = (i / 511.) / (t1 - t0) - t0; + error = pdf_evalfunction(shade->function, &t, 1, outcol, 3); + shade->cs->convcolor(shade->cs, outcol, dsts, destc); + destcol[i][0] = destc[0]*255.; + destcol[i][1] = destc[1]*255.; + destcol[i][2] = destc[2]*255.; + } + + int steps = 10; + float step = 0.1; + steps = 10; + step = 0.1; + for (int i=0; i<steps ; ++i) { + float nt0, nt1; + float nx0, ny0, nr0; + float nx1, ny1, nr1; + + nt0 = t0 + ((t1 - t0) * step * (i)); + nt1 = t0 + ((t1 - t0) * step * (i+1)); + + nx0 = x0 + ((x1 - x0) * step * (i)); + nx1 = x0 + ((x1 - x0) * step * (i+1)); + + ny0 = y0 + ((y1 - y0) * step * (i)); + ny1 = y0 + ((y1 - y0) * step * (i+1)); + + nr0 = r0 + ((r1 - r0) * step * (i)); + nr1 = r0 + ((r1 - r0) * step * (i+1)); + + cidx0 = ((nt0 + t0) * (t1 - t0)) * 511; + cidx1 = ((nt1 + t0) * (t1 - t0)) * 511; + + if (cidx0 < 0 || cidx0 > 511) { + int a; + a++; + } + if (cidx1 < 0 || cidx1 > 511) { + int a; + a++; + } + + fz_renderannulus(nx0, ny0, nr0, nx1, ny1, nr1, cidx0, cidx1, ctm, dstp, destcol); + } +} fz_error * fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_colorspace *dsts, fz_pixmap *dstp, int over) { - if (!over) - fz_clearpixmap(dstp); + int x, y, w, h; + + switch (shade->type) { + case 1: + fz_rendershade1(shade, ctm, dsts, dstp, over); + break; + case 2: + fz_rendershade2(shade, ctm, dsts, dstp, over); + break; + case 3: + fz_rendershade3(shade, ctm, dsts, dstp, over); + break; + default: + } + + //dstp->samples + // if (!over) + // fz_clearpixmap(dstp); return nil; } - diff --git a/render/render.c b/render/render.c index 7ae10fb4..70ff5c75 100644 --- a/render/render.c +++ b/render/render.c @@ -526,9 +526,6 @@ rendershade(fz_renderer *gc, fz_shadenode *node, fz_matrix ctm) assert(!gc->maskonly); - if (gc->flag & FOVER) - return fz_rendershade(node->shade, ctm, gc->model, gc->over, 1); - bbox = fz_roundrect(fz_boundnode((fz_node*)node, ctm)); bbox = fz_intersectirects(gc->clip, bbox); |