summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKim Jeong Hee <jeong@pdfpro.co.kr>2004-11-30 09:56:33 +0100
committerKim Jeong Hee <jeong@pdfpro.co.kr>2004-11-30 09:56:33 +0100
commitb772787951d718a0ae5e51355acbe4d66ab793c3 (patch)
treebf10875bc9abb654c85bf934f1d5031969f1cd47
parent170ed5fe09746901cc53bb0ad501d43f9864323e (diff)
downloadmupdf-b772787951d718a0ae5e51355acbe4d66ab793c3.tar.xz
first clumsy shade implementation
-rw-r--r--include/fitz/shade.h12
-rw-r--r--mupdf/function.c163
-rw-r--r--mupdf/shade.c117
-rw-r--r--render/rastshade.c428
-rw-r--r--render/render.c3
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);