reactos/rosapps/smartpdf/fitz/mupdf/pdf_shade1.c
Klemens Friedl 435a566751 SmartPDF - lightweight pdf viewer app for rosapps
* sumatrapdf - vendor import
* everything compiles (libjpeg, poppler, fitz, sumatrapdf)
* does NOT link

(remove the comment tags in the parent directory.rbuild file (rosapps dir) to build it)

svn path=/trunk/; revision=29295
2007-09-29 08:39:35 +00:00

370 lines
8.2 KiB
C

#include <fitz.h>
#include <mupdf.h>
/* this mess is jeong's */
#define BIGNUM 32000
#define NSEGS 32
#define MAX_RAD_SEGS 36
fz_error *
pdf_loadtype1shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
{
fz_error *error;
fz_obj *obj;
fz_matrix matrix;
pdf_function *func;
int xx, yy;
float x, y;
float xn, yn;
float x0, y0, x1, y1;
int n;
pdf_logshade("load type1 shade {\n");
obj = fz_dictgets(dict, "Domain");
if (obj) {
x0 = fz_toreal(fz_arrayget(obj, 0));
x1 = fz_toreal(fz_arrayget(obj, 1));
y0 = fz_toreal(fz_arrayget(obj, 2));
y1 = fz_toreal(fz_arrayget(obj, 3));
}
else {
x0 = 0;
x1 = 1.0;
y0 = 0;
y1 = 1.0;
}
pdf_logshade("domain %g %g %g %g\n", x0, x1, y0, y1);
obj = fz_dictgets(dict, "Matrix");
if (obj)
{
matrix = pdf_tomatrix(obj);
pdf_logshade("matrix [%g %g %g %g %g %g]\n",
matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f);
}
else
matrix = fz_identity();
obj = fz_dictgets(dict, "Function");
error = pdf_loadfunction(&func, xref, obj);
if (error)
return error;
shade->usefunction = 0;
if (error)
return error;
shade->meshlen = NSEGS * NSEGS * 2;
shade->mesh = fz_malloc(sizeof(float) * (2 + shade->cs->n) * 3 * shade->meshlen);
if (!shade->mesh)
return fz_outofmem;
n = 0;
for (yy = 0; yy < NSEGS; ++yy)
{
y = y0 + (y1 - y0) * yy / (float)NSEGS;
yn = y0 + (y1 - y0) * (yy + 1) / (float)NSEGS;
for (xx = 0; xx < NSEGS; ++xx)
{
x = x0 + (x1 - x0) * (xx / (float)NSEGS);
xn = x0 + (x1 - x0) * (xx + 1) / (float)NSEGS;
#define ADD_VERTEX(xx, yy) \
{\
fz_point p;\
float cp[2], cv[FZ_MAXCOLORS];\
int c;\
p.x = xx;\
p.y = yy;\
p = fz_transformpoint(matrix, p);\
shade->mesh[n++] = p.x;\
shade->mesh[n++] = p.y;\
\
cp[0] = xx;\
cp[1] = yy;\
error = pdf_evalfunction(func, cp, 2, cv, shade->cs->n);\
\
for (c = 0; c < shade->cs->n; ++c) {\
shade->mesh[n++] = cv[c];\
}\
}\
ADD_VERTEX(x, y);
ADD_VERTEX(xn, y);
ADD_VERTEX(xn, yn);
ADD_VERTEX(x, y);
ADD_VERTEX(xn, yn);
ADD_VERTEX(x, yn);
}
}
pdf_logshade("}\n");
return nil;
}
fz_error *
pdf_loadtype2shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
{
fz_point p1, p2, p3, p4;
fz_point ep1, ep2, ep3, ep4;
float x0, y0, x1, y1;
float t0, t1;
int e0, e1;
fz_obj *obj;
float theta;
float dist;
int n;
pdf_logshade("load type2 shade {\n");
obj = fz_dictgets(dict, "Coords");
x0 = fz_toreal(fz_arrayget(obj, 0));
y0 = fz_toreal(fz_arrayget(obj, 1));
x1 = fz_toreal(fz_arrayget(obj, 2));
y1 = fz_toreal(fz_arrayget(obj, 3));
pdf_logshade("coords %g %g %g %g\n", x0, y0, x1, y1);
obj = fz_dictgets(dict, "Domain");
if (obj) {
t0 = fz_toreal(fz_arrayget(obj, 0));
t1 = fz_toreal(fz_arrayget(obj, 1));
} else {
t0 = 0.;
t1 = 1.;
}
obj = fz_dictgets(dict, "Extend");
if (obj) {
e0 = fz_tobool(fz_arrayget(obj, 0));
e1 = fz_tobool(fz_arrayget(obj, 1));
} else {
e0 = 0;
e1 = 0;
}
pdf_logshade("domain %g %g\n", t0, t1);
pdf_logshade("extend %d %d\n", e0, e1);
pdf_loadshadefunction(shade, xref, dict, t0, t1);
shade->meshlen = 2 + e0 * 2 + e1 * 2;
shade->mesh = fz_malloc(sizeof(float) * 3*3 * shade->meshlen);
if (!shade->mesh)
return fz_outofmem;
theta = atan2(y1 - y0, x1 - x0);
theta += M_PI / 2.0;
pdf_logshade("theta=%g\n", theta);
dist = hypot(x1 - x0, y1 - y0);
p1.x = x0 + BIGNUM * cos(theta);
p1.y = y0 + BIGNUM * sin(theta);
p2.x = x1 + BIGNUM * cos(theta);
p2.y = y1 + BIGNUM * sin(theta);
p3.x = x0 - BIGNUM * cos(theta);
p3.y = y0 - BIGNUM * sin(theta);
p4.x = x1 - BIGNUM * cos(theta);
p4.y = y1 - BIGNUM * sin(theta);
ep1.x = p1.x - (x1 - x0) / dist * BIGNUM;
ep1.y = p1.y - (y1 - y0) / dist * BIGNUM;
ep2.x = p2.x + (x1 - x0) / dist * BIGNUM;
ep2.y = p2.y + (y1 - y0) / dist * BIGNUM;
ep3.x = p3.x - (x1 - x0) / dist * BIGNUM;
ep3.y = p3.y - (y1 - y0) / dist * BIGNUM;
ep4.x = p4.x + (x1 - x0) / dist * BIGNUM;
ep4.y = p4.y + (y1 - y0) / dist * BIGNUM;
pdf_logshade("p1 %g %g\n", p1.x, p1.y);
pdf_logshade("p2 %g %g\n", p2.x, p2.y);
pdf_logshade("p3 %g %g\n", p3.x, p3.y);
pdf_logshade("p4 %g %g\n", p4.x, p4.y);
n = 0;
pdf_setmeshvalue(shade->mesh, n++, p1.x, p1.y, 0);
pdf_setmeshvalue(shade->mesh, n++, p2.x, p2.y, 1);
pdf_setmeshvalue(shade->mesh, n++, p4.x, p4.y, 1);
pdf_setmeshvalue(shade->mesh, n++, p1.x, p1.y, 0);
pdf_setmeshvalue(shade->mesh, n++, p4.x, p4.y, 1);
pdf_setmeshvalue(shade->mesh, n++, p3.x, p3.y, 0);
if (e0) {
pdf_setmeshvalue(shade->mesh, n++, ep1.x, ep1.y, 0);
pdf_setmeshvalue(shade->mesh, n++, p1.x, p1.y, 0);
pdf_setmeshvalue(shade->mesh, n++, p3.x, p3.y, 0);
pdf_setmeshvalue(shade->mesh, n++, ep1.x, ep1.y, 0);
pdf_setmeshvalue(shade->mesh, n++, p3.x, p3.y, 0);
pdf_setmeshvalue(shade->mesh, n++, ep3.x, ep3.y, 0);
}
if (e1) {
pdf_setmeshvalue(shade->mesh, n++, p2.x, p2.y, 1);
pdf_setmeshvalue(shade->mesh, n++, ep2.x, ep2.y, 1);
pdf_setmeshvalue(shade->mesh, n++, ep4.x, ep4.y, 1);
pdf_setmeshvalue(shade->mesh, n++, p2.x, p2.y, 1);
pdf_setmeshvalue(shade->mesh, n++, ep4.x, ep4.y, 1);
pdf_setmeshvalue(shade->mesh, n++, p4.x, p4.y, 1);
}
pdf_logshade("}\n");
return nil;
}
static int
buildannulusmesh(float* mesh, int pos,
float x0, float y0, float r0, float x1, float y1, float r1,
float c0, float c1, int nomesh)
{
int n = pos * 3;
float dist = hypot(x1 - x0, y1 - y0);
float step;
float theta;
int i;
if (dist != 0)
theta = asin((r1 - r0) / dist) + M_PI/2.0 + atan2(y1 - y0, x1 - x0);
else
theta = 0;
if (!(theta >= 0 && theta <= M_PI))
theta = 0;
step = M_PI * 2.f / (float)MAX_RAD_SEGS;
for (i = 0; i < MAX_RAD_SEGS; theta -= step, ++i)
{
fz_point pt1, pt2, pt3, pt4;
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;
if (r0 > 0) {
if (!nomesh) {
pdf_setmeshvalue(mesh, n++, pt1.x, pt1.y, c1);
pdf_setmeshvalue(mesh, n++, pt2.x, pt2.y, c0);
pdf_setmeshvalue(mesh, n++, pt4.x, pt4.y, c0);
}
pos++;
}
if (r1 > 0) {
if (!nomesh) {
pdf_setmeshvalue(mesh, n++, pt1.x, pt1.y, c1);
pdf_setmeshvalue(mesh, n++, pt3.x, pt3.y, c1);
pdf_setmeshvalue(mesh, n++, pt4.x, pt4.y, c0);
}
pos++;
}
}
return pos;
}
fz_error *
pdf_loadtype3shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref)
{
fz_obj *obj;
float x0, y0, r0, x1, y1, r1;
float t0, t1;
int e0, e1;
float ex0, ey0, er0;
float ex1, ey1, er1;
float rs;
int i;
pdf_logshade("load type3 shade {\n");
obj = fz_dictgets(shading, "Coords");
x0 = fz_toreal(fz_arrayget(obj, 0));
y0 = fz_toreal(fz_arrayget(obj, 1));
r0 = fz_toreal(fz_arrayget(obj, 2));
x1 = fz_toreal(fz_arrayget(obj, 3));
y1 = fz_toreal(fz_arrayget(obj, 4));
r1 = fz_toreal(fz_arrayget(obj, 5));
pdf_logshade("coords %g %g %g %g %g %g\n", x0, y0, r0, x1, y1, r1);
obj = fz_dictgets(shading, "Domain");
if (obj) {
t0 = fz_toreal(fz_arrayget(obj, 0));
t1 = fz_toreal(fz_arrayget(obj, 1));
} else {
t0 = 0.;
t1 = 1.;
}
obj = fz_dictgets(shading, "Extend");
if (obj) {
e0 = fz_tobool(fz_arrayget(obj, 0));
e1 = fz_tobool(fz_arrayget(obj, 1));
} else {
e0 = 0;
e1 = 0;
}
pdf_logshade("domain %g %g\n", t0, t1);
pdf_logshade("extend %d %d\n", e0, e1);
pdf_loadshadefunction(shade, xref, shading, t0, t1);
if (r0 < r1)
rs = r0 / (r0 - r1);
else
rs = -BIGNUM;
ex0 = x0 + (x1 - x0) * rs;
ey0 = y0 + (y1 - y0) * rs;
er0 = r0 + (r1 - r0) * rs;
if (r0 > r1)
rs = r1 / (r1 - r0);
else
rs = -BIGNUM;
ex1 = x1 + (x0 - x1) * rs;
ey1 = y1 + (y0 - y1) * rs;
er1 = r1 + (r0 - r1) * rs;
for (i=0; i<2; ++i)
{
int pos = 0;
if (e0)
pos = buildannulusmesh(shade->mesh, pos, ex0, ey0, er0, x0, y0, r0, 0, 0, 1-i);
pos = buildannulusmesh(shade->mesh, pos, x0, y0, r0, x1, y1, r1, 0, 1., 1-i);
if (e1)
pos = buildannulusmesh(shade->mesh, pos, x1, y1, r1, ex1, ey1, er1, 1., 1., 1-i);
if (i == 0)
{
shade->meshlen = pos;
shade->mesh = fz_malloc(sizeof(float) * 9 * shade->meshlen);
if (!shade->mesh)
return fz_outofmem;
}
}
pdf_logshade("}\n");
return nil;
}