SmartPDF - lightweight pdf viewer app for rosapps
[reactos.git] / rosapps / smartpdf / fitz / mupdf / pdf_shade4.c
1 #include <fitz.h>
2 #include <mupdf.h>
3
4 /* this mess is jeong's */
5
6 typedef struct pdf_tensorpatch_s pdf_tensorpatch;
7 struct pdf_tensorpatch_s {
8 fz_point pole[4][4];
9 float color[4][FZ_MAXCOLORS];
10 };
11
12 fz_error *
13 pdf_loadtype4shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref)
14 {
15 fz_error *error;
16 fz_obj *obj;
17 int bpcoord;
18 int bpcomp;
19 int bpflag;
20 int ncomp;
21 float x0, x1, y0, y1;
22 float c0[FZ_MAXCOLORS];
23 float c1[FZ_MAXCOLORS];
24 int i, z;
25 int bitspervertex;
26 int bytepervertex;
27 fz_buffer *buf;
28 int n;
29 int j;
30 float cval[16];
31
32 int flag;
33 unsigned int t;
34 float x, y;
35
36 error = nil;
37
38 ncomp = shade->cs->n;
39 bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate"));
40 bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent"));
41 bpflag = fz_toint(fz_dictgets(shading, "BitsPerFlag"));
42
43 obj = fz_dictgets(shading, "Decode");
44 if (fz_isarray(obj))
45 {
46 pdf_logshade("decode array\n");
47 x0 = fz_toreal(fz_arrayget(obj, 0));
48 x1 = fz_toreal(fz_arrayget(obj, 1));
49 y0 = fz_toreal(fz_arrayget(obj, 2));
50 y1 = fz_toreal(fz_arrayget(obj, 3));
51 for (i=0; i < fz_arraylen(obj) / 2; ++i) {
52 c0[i] = fz_toreal(fz_arrayget(obj, i*2+4));
53 c1[i] = fz_toreal(fz_arrayget(obj, i*2+5));
54 }
55 }
56 else {
57 error = fz_throw("syntaxerror: No Decode key in Type 4 Shade");
58 goto cleanup;
59 }
60
61 obj = fz_dictgets(shading, "Function");
62 if (obj) {
63 ncomp = 1;
64 pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]);
65 }
66
67 bitspervertex = bpflag + bpcoord * 2 + bpcomp * ncomp;
68 bytepervertex = (bitspervertex+7) / 8;
69
70 error = pdf_loadstream(&buf, xref, fz_tonum(ref), fz_togen(ref));
71 if (error) goto cleanup;
72
73 shade->usefunction = 0;
74
75
76 n = 2 + shade->cs->n;
77 j = 0;
78 for (z = 0; z < (buf->ep - buf->bp) / bytepervertex; ++z)
79 {
80 flag = *buf->rp++;
81
82 t = *buf->rp++;
83 t = (t << 8) + *buf->rp++;
84 t = (t << 8) + *buf->rp++;
85 x = x0 + (t * (x1 - x0) / (pow(2, 24) - 1));
86
87 t = *buf->rp++;
88 t = (t << 8) + *buf->rp++;
89 t = (t << 8) + *buf->rp++;
90 y = y0 + (t * (y1 - y0) / (pow(2, 24) - 1));
91
92 for (i=0; i < ncomp; ++i) {
93 t = *buf->rp++;
94 t = (t << 8) + *buf->rp++;
95 }
96
97 if (flag == 0) {
98 j += n;
99 }
100 if (flag == 1 || flag == 2) {
101 j += 3 * n;
102 }
103 }
104 buf->rp = buf->bp;
105
106 shade->mesh = (float*) malloc(sizeof(float) * j);
107 /* 8, 24, 16 only */
108 j = 0;
109 for (z = 0; z < (buf->ep - buf->bp) / bytepervertex; ++z)
110 {
111 flag = *buf->rp++;
112
113 t = *buf->rp++;
114 t = (t << 8) + *buf->rp++;
115 t = (t << 8) + *buf->rp++;
116 x = x0 + (t * (x1 - x0) / (pow(2, 24) - 1));
117
118 t = *buf->rp++;
119 t = (t << 8) + *buf->rp++;
120 t = (t << 8) + *buf->rp++;
121 y = y0 + (t * (y1 - y0) / (pow(2, 24) - 1));
122
123 for (i=0; i < ncomp; ++i) {
124 t = *buf->rp++;
125 t = (t << 8) + *buf->rp++;
126 cval[i] = t / (double)(pow(2, 16) - 1);
127 }
128
129 if (flag == 0) {
130 shade->mesh[j++] = x;
131 shade->mesh[j++] = y;
132 for (i=0; i < ncomp; ++i) {
133 shade->mesh[j++] = cval[i];
134 }
135 }
136 if (flag == 1) {
137 memcpy(&(shade->mesh[j]), &(shade->mesh[j - 2 * n]), n * sizeof(float));
138 memcpy(&(shade->mesh[j + 1 * n]), &(shade->mesh[j - 1 * n]), n * sizeof(float));
139 j+= 2 * n;
140 shade->mesh[j++] = x;
141 shade->mesh[j++] = y;
142 for (i=0; i < ncomp; ++i) {
143 shade->mesh[j++] = cval[i];
144 }
145 }
146 if (flag == 2) {
147 memcpy(&(shade->mesh[j]), &(shade->mesh[j - 3 * n]), n * sizeof(float));
148 memcpy(&(shade->mesh[j + 1 * n]), &(shade->mesh[j - 1 * n]), n * sizeof(float));
149 j+= 2 * n;
150 shade->mesh[j++] = x;
151 shade->mesh[j++] = y;
152 for (i=0; i < ncomp; ++i) {
153 shade->mesh[j++] = cval[i];
154 }
155 }
156 }
157 shade->meshlen = j / n / 3;
158
159 fz_dropbuffer(buf);
160
161 cleanup:
162
163 return nil;
164 }
165
166 static int
167 getdata(fz_stream *stream, int bps)
168 {
169 unsigned int bitmask = (1 << bps) - 1;
170 unsigned int buf = 0;
171 int bits = 0;
172 int s;
173
174 while (bits < bps)
175 {
176 buf = (buf << 8) | (fz_readbyte(stream) & 0xff);
177 bits += 8;
178 }
179 s = buf >> (bits - bps);
180 if (bps < 32)
181 s = s & bitmask;
182 bits -= bps;
183
184 return s;
185 }
186
187 fz_error *
188 pdf_loadtype5shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref)
189 {
190 fz_error *error;
191 fz_stream *stream;
192 fz_obj *obj;
193
194 int bpcoord;
195 int bpcomp;
196 int vpr, vpc;
197 int ncomp;
198
199 float x0, x1, y0, y1;
200
201 float c0[FZ_MAXCOLORS];
202 float c1[FZ_MAXCOLORS];
203
204 int i, n, j;
205 int p, q;
206 unsigned int t;
207
208 float *x, *y, *c[FZ_MAXCOLORS];
209
210 error = nil;
211
212 ncomp = shade->cs->n;
213 bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate"));
214 bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent"));
215 vpr = fz_toint(fz_dictgets(shading, "VerticesPerRow"));
216 if (vpr < 2) {
217 error = fz_throw("VerticesPerRow must be greater than or equal to 2");
218 goto cleanup;
219 }
220
221 obj = fz_dictgets(shading, "Decode");
222 if (fz_isarray(obj))
223 {
224 pdf_logshade("decode array\n");
225 x0 = fz_toreal(fz_arrayget(obj, 0));
226 x1 = fz_toreal(fz_arrayget(obj, 1));
227 y0 = fz_toreal(fz_arrayget(obj, 2));
228 y1 = fz_toreal(fz_arrayget(obj, 3));
229 for (i=0; i < fz_arraylen(obj) / 2; ++i) {
230 c0[i] = fz_toreal(fz_arrayget(obj, i*2+4));
231 c1[i] = fz_toreal(fz_arrayget(obj, i*2+5));
232 }
233 }
234 else {
235 error = fz_throw("syntaxerror: No Decode key in Type 4 Shade");
236 goto cleanup;
237 }
238
239 obj = fz_dictgets(shading, "Function");
240 if (obj) {
241 ncomp = 1;
242 pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]);
243 shade->usefunction = 1;
244 }
245 else
246 shade->usefunction = 0;
247
248 n = 2 + shade->cs->n;
249 j = 0;
250
251 #define BIGNUM 1024
252
253 x = fz_malloc(sizeof(float) * vpr * BIGNUM);
254 y = fz_malloc(sizeof(float) * vpr * BIGNUM);
255 for (i = 0; i < ncomp; ++i) {
256 c[i] = fz_malloc(sizeof(float) * vpr * BIGNUM);
257 }
258 q = 0;
259
260 error = pdf_openstream(&stream, xref, fz_tonum(ref), fz_togen(ref));
261 if (error) goto cleanup;
262
263 while (fz_peekbyte(stream) != EOF)
264 {
265 for (p = 0; p < vpr; ++p) {
266 int idx;
267 idx = q * vpr + p;
268
269 t = getdata(stream, bpcoord);
270 x[idx] = x0 + (t * (x1 - x0) / ((float)pow(2, bpcoord) - 1));
271 t = getdata(stream, bpcoord);
272 y[idx] = y0 + (t * (y1 - y0) / ((float)pow(2, bpcoord) - 1));
273
274 for (i=0; i < ncomp; ++i) {
275 t = getdata(stream, bpcomp);
276 c[i][idx] = c0[i] + (t * (c1[i] - c0[i]) / (float)(pow(2, bpcomp) - 1));
277 }
278 }
279 q++;
280 }
281
282 fz_dropstream(stream);
283
284 #define ADD_VERTEX(idx) \
285 {\
286 int z;\
287 shade->mesh[j++] = x[idx];\
288 shade->mesh[j++] = y[idx];\
289 for (z = 0; z < shade->cs->n; ++z) {\
290 shade->mesh[j++] = c[z][idx];\
291 }\
292 }\
293
294 vpc = q;
295
296 shade->meshcap = 0;
297 shade->mesh = fz_malloc(sizeof(float) * 1024);
298 if (!shade) {
299 error = fz_outofmem;
300 goto cleanup;
301 }
302
303 j = 0;
304 for (p = 0; p < vpr-1; ++p) {
305 for (q = 0; q < vpc-1; ++q) {
306 ADD_VERTEX(q * vpr + p);
307 ADD_VERTEX(q * vpr + p + 1);
308 ADD_VERTEX((q + 1) * vpr + p + 1);
309
310 ADD_VERTEX(q * vpr + p);
311 ADD_VERTEX((q + 1) * vpr + p + 1);
312 ADD_VERTEX((q + 1) * vpr + p);
313 }
314 }
315
316 shade->meshlen = j / n / 3;
317
318 fz_free(x);
319 fz_free(y);
320 for (i = 0; i < ncomp; ++i) {
321 fz_free(c[i]);
322 }
323
324
325 cleanup:
326
327 return nil;
328 }
329
330 #define SEGMENTATION_DEPTH 2
331
332 static inline void copyvert(float *dst, float *src, int n)
333 {
334 while (n--)
335 *dst++ = *src++;
336 }
337
338
339 static inline void copycolor(float *c, const float *s)
340 {
341 int i;
342 for (i = 0; i<FZ_MAXCOLORS; ++i)
343 c[i] = s[i];
344 }
345
346 static inline void midcolor(float *c, const float *c1, const float *c2)
347 {
348 int i;
349 for (i = 0; i<FZ_MAXCOLORS; ++i)
350 c[i] = (float)((c1[i] + c2[i]) / 2.0);
351 }
352
353
354 static void
355 filltensorinterior(pdf_tensorpatch *p)
356 {
357 #define lcp1(p0, p3)\
358 ((p0 + p0 + p3) / 3.0f)
359
360 #define lcp2(p0, p3)\
361 ((p0 + p3 + p3) / 3.0f)
362
363 p->pole[1][1].x = lcp1(p->pole[0][1].x, p->pole[3][1].x) +
364 lcp1(p->pole[1][0].x, p->pole[1][3].x) -
365 lcp1(lcp1(p->pole[0][0].x, p->pole[0][3].x),
366 lcp1(p->pole[3][0].x, p->pole[3][3].x));
367 p->pole[1][2].x = lcp1(p->pole[0][2].x, p->pole[3][2].x) +
368 lcp2(p->pole[1][0].x, p->pole[1][3].x) -
369 lcp1(lcp2(p->pole[0][0].x, p->pole[0][3].x),
370 lcp2(p->pole[3][0].x, p->pole[3][3].x));
371 p->pole[2][1].x = lcp2(p->pole[0][1].x, p->pole[3][1].x) +
372 lcp1(p->pole[2][0].x, p->pole[2][3].x) -
373 lcp2(lcp1(p->pole[0][0].x, p->pole[0][3].x),
374 lcp1(p->pole[3][0].x, p->pole[3][3].x));
375 p->pole[2][2].x = lcp2(p->pole[0][2].x, p->pole[3][2].x) +
376 lcp2(p->pole[2][0].x, p->pole[2][3].x) -
377 lcp2(lcp2(p->pole[0][0].x, p->pole[0][3].x),
378 lcp2(p->pole[3][0].x, p->pole[3][3].x));
379
380 p->pole[1][1].y = lcp1(p->pole[0][1].y, p->pole[3][1].y) +
381 lcp1(p->pole[1][0].y, p->pole[1][3].y) -
382 lcp1(lcp1(p->pole[0][0].y, p->pole[0][3].y),
383 lcp1(p->pole[3][0].y, p->pole[3][3].y));
384 p->pole[1][2].y = lcp1(p->pole[0][2].y, p->pole[3][2].y) +
385 lcp2(p->pole[1][0].y, p->pole[1][3].y) -
386 lcp1(lcp2(p->pole[0][0].y, p->pole[0][3].y),
387 lcp2(p->pole[3][0].y, p->pole[3][3].y));
388 p->pole[2][1].y = lcp2(p->pole[0][1].y, p->pole[3][1].y) +
389 lcp1(p->pole[2][0].y, p->pole[2][3].y) -
390 lcp2(lcp1(p->pole[0][0].y, p->pole[0][3].y),
391 lcp1(p->pole[3][0].y, p->pole[3][3].y));
392 p->pole[2][2].y = lcp2(p->pole[0][2].y, p->pole[3][2].y) +
393 lcp2(p->pole[2][0].y, p->pole[2][3].y) -
394 lcp2(lcp2(p->pole[0][0].y, p->pole[0][3].y),
395 lcp2(p->pole[3][0].y, p->pole[3][3].y));
396
397 #undef lcp1
398 #undef lcp2
399 }
400
401 static void
402 split_curve_s(const fz_point *pole, fz_point *q0, fz_point *q1, int pole_step)
403 {
404 #define midpoint(a,b)\
405 ((a)/2.0f + (b)/2.0f) // to avoid overflow
406 float x12 = midpoint(pole[1 * pole_step].x, pole[2 * pole_step].x);
407 float y12 = midpoint(pole[1 * pole_step].y, pole[2 * pole_step].y);
408
409 q0[1 * pole_step].x = midpoint(pole[0 * pole_step].x, pole[1 * pole_step].x);
410 q0[1 * pole_step].y = midpoint(pole[0 * pole_step].y, pole[1 * pole_step].y);
411 q1[2 * pole_step].x = midpoint(pole[2 * pole_step].x, pole[3 * pole_step].x);
412 q1[2 * pole_step].y = midpoint(pole[2 * pole_step].y, pole[3 * pole_step].y);
413 q0[2 * pole_step].x = midpoint(q0[1 * pole_step].x, x12);
414 q0[2 * pole_step].y = midpoint(q0[1 * pole_step].y, y12);
415 q1[1 * pole_step].x = midpoint(x12, q1[2 * pole_step].x);
416 q1[1 * pole_step].y = midpoint(y12, q1[2 * pole_step].y);
417 q0[0 * pole_step].x = pole[0 * pole_step].x;
418 q0[0 * pole_step].y = pole[0 * pole_step].y;
419 q0[3 * pole_step].x = q1[0 * pole_step].x = midpoint(q0[2 * pole_step].x, q1[1 * pole_step].x);
420 q0[3 * pole_step].y = q1[0 * pole_step].y = midpoint(q0[2 * pole_step].y, q1[1 * pole_step].y);
421 q1[3 * pole_step].x = pole[3 * pole_step].x;
422 q1[3 * pole_step].y = pole[3 * pole_step].y;
423 #undef midpoint
424 }
425
426 static inline void
427 split_patch(pdf_tensorpatch *s0, pdf_tensorpatch *s1, const pdf_tensorpatch *p)
428 {
429 split_curve_s(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
430 split_curve_s(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
431 split_curve_s(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
432 split_curve_s(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
433
434 copycolor(s0->color[0], p->color[0]);
435 midcolor(s0->color[1], p->color[0], p->color[1]);
436 midcolor(s0->color[2], p->color[2], p->color[3]);
437 copycolor(s0->color[3], p->color[3]);
438
439 copycolor(s1->color[0], s0->color[1]);
440 copycolor(s1->color[1], p->color[1]);
441 copycolor(s1->color[2], p->color[2]);
442 copycolor(s1->color[3], s0->color[2]);
443 }
444
445 static inline void
446 split_stripe(pdf_tensorpatch *s0, pdf_tensorpatch *s1, const pdf_tensorpatch *p)
447
448 {
449 split_curve_s(p->pole[0], s0->pole[0], s1->pole[0], 1);
450 split_curve_s(p->pole[1], s0->pole[1], s1->pole[1], 1);
451 split_curve_s(p->pole[2], s0->pole[2], s1->pole[2], 1);
452 split_curve_s(p->pole[3], s0->pole[3], s1->pole[3], 1);
453
454 copycolor(s0->color[0], p->color[0]);
455 copycolor(s0->color[1], p->color[1]);
456 midcolor(s0->color[2], p->color[1], p->color[2]);
457 midcolor(s0->color[3], p->color[0], p->color[3]);
458
459 copycolor(s1->color[0], s0->color[3]);
460 copycolor(s1->color[1], s0->color[2]);
461 copycolor(s1->color[2], p->color[2]);
462 copycolor(s1->color[3], p->color[3]);
463 }
464
465 static fz_error *
466 growshademesh(fz_shade *shade, int amount)
467 {
468 float *newmesh;
469 int newcap;
470
471 newcap = shade->meshcap + amount;
472 newmesh = fz_realloc(shade->mesh, sizeof(float) * newcap);
473 if (!newmesh)
474 return fz_outofmem;
475
476 shade->mesh = newmesh;
477 shade->meshcap = newcap;
478
479 return nil;
480 }
481
482 static inline int setvertex(float *mesh, fz_point pt, float *color, int ptr, int ncomp)
483 {
484 int i;
485
486 mesh[ptr++] = pt.x;
487 mesh[ptr++] = pt.y;
488 for (i=0; i < ncomp; ++i) {
489 mesh[ptr++] = color[i];
490 }
491
492 return ptr;
493 }
494
495 static int
496 triangulatepatch(pdf_tensorpatch p, fz_shade *shade, int ptr, int ncomp)
497 {
498 fz_error* error;
499
500 ptr = setvertex(shade->mesh, p.pole[0][0], p.color[0], ptr, ncomp);
501 ptr = setvertex(shade->mesh, p.pole[3][0], p.color[1], ptr, ncomp);
502 ptr = setvertex(shade->mesh, p.pole[3][3], p.color[2], ptr, ncomp);
503 ptr = setvertex(shade->mesh, p.pole[0][0], p.color[0], ptr, ncomp);
504 ptr = setvertex(shade->mesh, p.pole[3][3], p.color[2], ptr, ncomp);
505 ptr = setvertex(shade->mesh, p.pole[0][3], p.color[3], ptr, ncomp);
506
507 if (shade->meshcap - 1024 < ptr) {
508 error = growshademesh(shade, 1024);
509 if (error) goto cleanup;
510 }
511
512 return ptr;
513
514 cleanup:
515 // error handling
516 return -1;
517 }
518
519 static int
520 drawstripe(pdf_tensorpatch patch, fz_shade *shade, int ptr, int ncomp, int depth)
521 {
522 pdf_tensorpatch s0, s1;
523
524 split_stripe(&s0, &s1, &patch);
525
526 depth++;
527
528 if (depth >= SEGMENTATION_DEPTH)
529 {
530 ptr = triangulatepatch(s0, shade, ptr, ncomp);
531 ptr = triangulatepatch(s1, shade, ptr, ncomp);
532 }
533 else {
534 ptr = drawstripe(s0, shade, ptr, ncomp, depth);
535 ptr = drawstripe(s1, shade, ptr, ncomp, depth);
536 }
537
538 return ptr;
539 }
540
541 static int
542 drawpatch(pdf_tensorpatch patch, fz_shade *shade, int ptr, int ncomp, int depth)
543 {
544 pdf_tensorpatch s0, s1;
545
546 split_patch(&s0, &s1, &patch);
547 depth++;
548
549 if (depth > SEGMENTATION_DEPTH)
550 {
551 ptr = drawstripe(s0, shade, ptr, ncomp, 0);
552 ptr = drawstripe(s1, shade, ptr, ncomp, 0);
553 }
554 else {
555 ptr = drawpatch(s0, shade, ptr, ncomp, depth);
556 ptr = drawpatch(s1, shade, ptr, ncomp, depth);
557 }
558
559 return ptr;
560 }
561
562 fz_error *
563 pdf_loadtype6shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref)
564 {
565 fz_error *error;
566 fz_stream *stream;
567 fz_obj *obj;
568
569 int bpcoord;
570 int bpcomp;
571 int bpflag;
572 int ncomp;
573
574 fz_point p0, p1;
575
576 float c0[FZ_MAXCOLORS];
577 float c1[FZ_MAXCOLORS];
578
579 int i, n, j;
580 unsigned int t;
581
582 int flag;
583 fz_point p[12];
584
585 pdf_tensorpatch patch;
586
587 error = nil;
588
589 ncomp = shade->cs->n;
590 bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate"));
591 bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent"));
592 bpflag = fz_toint(fz_dictgets(shading, "BitsPerFlag"));
593
594 obj = fz_dictgets(shading, "Decode");
595 if (fz_isarray(obj))
596 {
597 pdf_logshade("decode array\n");
598 p0.x = fz_toreal(fz_arrayget(obj, 0));
599 p1.x = fz_toreal(fz_arrayget(obj, 1));
600 p0.y = fz_toreal(fz_arrayget(obj, 2));
601 p1.y = fz_toreal(fz_arrayget(obj, 3));
602 for (i=0; i < fz_arraylen(obj) / 2; ++i) {
603 c0[i] = fz_toreal(fz_arrayget(obj, i*2+4));
604 c1[i] = fz_toreal(fz_arrayget(obj, i*2+5));
605 }
606 }
607 else {
608 error = fz_throw("syntaxerror: No Decode key in Type 6 Shade");
609 goto cleanup;
610 }
611
612 obj = fz_dictgets(shading, "Function");
613 if (obj) {
614 ncomp = 1;
615 pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]);
616 shade->usefunction = 1;
617 }
618 else
619 shade->usefunction = 0;
620
621 shade->meshcap = 0;
622 shade->mesh = nil;
623 error = growshademesh(shade, 1024);
624 if (error) goto cleanup;
625
626 n = 2 + shade->cs->n;
627 j = 0;
628
629 error = pdf_openstream(&stream, xref, fz_tonum(ref), fz_togen(ref));
630 if (error) goto cleanup;
631
632 while (fz_peekbyte(stream) != EOF)
633 {
634 flag = getdata(stream, bpflag);
635
636 for (i = 0; i < 12; ++i) {
637 t = getdata(stream, bpcoord);
638 p[i].x = (float)(p0.x + (t * (p1.x - p0.x) / (pow(2, bpcoord) - 1.)));
639 t = getdata(stream, bpcoord);
640 p[i].y = (float)(p0.y + (t * (p1.y - p0.y) / (pow(2, bpcoord) - 1.)));
641 }
642
643 for (i = 0; i < 4; ++i) {
644 int k;
645 for (k=0; k < ncomp; ++k) {
646 t = getdata(stream, bpcomp);
647 patch.color[i][k] =
648 c0[k] + (t * (c1[k] - c0[k]) / (pow(2, bpcomp) - 1.0f));
649 }
650 }
651
652 patch.pole[0][0] = p[0];
653 patch.pole[1][0] = p[1];
654 patch.pole[2][0] = p[2];
655 patch.pole[3][0] = p[3];
656 patch.pole[3][1] = p[4];
657 patch.pole[3][2] = p[5];
658 patch.pole[3][3] = p[6];
659 patch.pole[2][3] = p[7];
660 patch.pole[1][3] = p[8];
661 patch.pole[0][3] = p[9];
662 patch.pole[0][2] = p[10];
663 patch.pole[0][1] = p[11];
664 filltensorinterior(&patch);
665
666 j = drawpatch(patch, shade, j, ncomp, 0);
667 }
668
669 fz_dropstream(stream);
670
671 shade->meshlen = j / n / 3;
672
673 cleanup:
674
675 return nil;
676 }
677
678 fz_error *
679 pdf_loadtype7shade(fz_shade *shade, pdf_xref *xref, fz_obj *shading, fz_obj *ref)
680 {
681 fz_error *error;
682 fz_stream *stream;
683 fz_obj *obj;
684
685 int bpcoord;
686 int bpcomp;
687 int bpflag;
688 int ncomp;
689
690 float x0, x1, y0, y1;
691
692 float c0[FZ_MAXCOLORS];
693 float c1[FZ_MAXCOLORS];
694
695 int i, n, j;
696 unsigned int t;
697
698 int flag;
699 fz_point p[16];
700 pdf_tensorpatch patch;
701
702 error = nil;
703
704 ncomp = shade->cs->n;
705 bpcoord = fz_toint(fz_dictgets(shading, "BitsPerCoordinate"));
706 bpcomp = fz_toint(fz_dictgets(shading, "BitsPerComponent"));
707 bpflag = fz_toint(fz_dictgets(shading, "BitsPerFlag"));
708
709 obj = fz_dictgets(shading, "Decode");
710 if (fz_isarray(obj))
711 {
712 pdf_logshade("decode array\n");
713 x0 = fz_toreal(fz_arrayget(obj, 0));
714 x1 = fz_toreal(fz_arrayget(obj, 1));
715 y0 = fz_toreal(fz_arrayget(obj, 2));
716 y1 = fz_toreal(fz_arrayget(obj, 3));
717 for (i=0; i < fz_arraylen(obj) / 2; ++i) {
718 c0[i] = fz_toreal(fz_arrayget(obj, i*2+4));
719 c1[i] = fz_toreal(fz_arrayget(obj, i*2+5));
720 }
721 }
722 else {
723 error = fz_throw("syntaxerror: No Decode key in Type 6 Shade");
724 goto cleanup;
725 }
726
727 obj = fz_dictgets(shading, "Function");
728 if (obj) {
729 ncomp = 1;
730 pdf_loadshadefunction(shade, xref, shading, c0[0], c1[0]);
731 shade->usefunction = 1;
732 }
733 else
734 shade->usefunction = 0;
735
736 shade->meshcap = 0;
737 shade->mesh = nil;
738 error = growshademesh(shade, 1024);
739 if (error) goto cleanup;
740
741 n = 2 + shade->cs->n;
742 j = 0;
743
744 error = pdf_openstream(&stream, xref, fz_tonum(ref), fz_togen(ref));
745 if (error) goto cleanup;
746
747 while (fz_peekbyte(stream) != EOF)
748 {
749 flag = getdata(stream, bpflag);
750
751 for (i = 0; i < 16; ++i) {
752 t = getdata(stream, bpcoord);
753 p[i].x = x0 + (t * (x1 - x0) / (pow(2, bpcoord) - 1.));
754 t = getdata(stream, bpcoord);
755 p[i].y = y0 + (t * (y1 - y0) / (pow(2, bpcoord) - 1.));
756 }
757
758 for (i = 0; i < 4; ++i) {
759 int k;
760 for (k=0; k < ncomp; ++k) {
761 t = getdata(stream, bpcomp);
762 patch.color[i][k] =
763 c0[k] + (t * (c1[k] - c0[k]) / (pow(2, bpcomp) - 1.0f));
764 }
765 }
766
767 patch.pole[0][0] = p[0];
768 patch.pole[0][1] = p[1];
769 patch.pole[0][2] = p[2];
770 patch.pole[0][3] = p[3];
771 patch.pole[1][3] = p[4];
772 patch.pole[2][3] = p[5];
773 patch.pole[3][3] = p[6];
774 patch.pole[3][2] = p[7];
775 patch.pole[3][1] = p[8];
776 patch.pole[3][0] = p[9];
777 patch.pole[2][0] = p[10];
778 patch.pole[1][0] = p[11];
779 patch.pole[1][1] = p[12];
780 patch.pole[1][2] = p[13];
781 patch.pole[2][2] = p[14];
782 patch.pole[2][1] = p[15];
783
784 j = drawpatch(patch, shade, j, ncomp, 0);
785 }
786
787 fz_dropstream(stream);
788
789 shade->meshlen = j / n / 3;
790
791 cleanup:
792
793 return nil;
794 }
795