Subversion Repositories Kolibri OS

Rev

Rev 4680 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
#include "fitz.h"
2
#include "mupdf.h"
3
 
4
#define HUGENUM 32000 /* how far to extend axial/radial shadings */
5
#define FUNSEGS 32 /* size of sampled mesh for function-based shadings */
6
#define RADSEGS 32 /* how many segments to generate for radial meshes */
7
#define SUBDIV 3 /* how many levels to subdivide patches */
8
 
9
struct vertex
10
{
11
	float x, y;
12
	float c[FZ_MAX_COLORS];
13
};
14
 
15
static void
16
pdf_grow_mesh(fz_shade *shade, int amount)
17
{
18
	if (shade->mesh_len + amount < shade->mesh_cap)
19
		return;
20
 
21
	if (shade->mesh_cap == 0)
22
		shade->mesh_cap = 1024;
23
 
24
	while (shade->mesh_len + amount > shade->mesh_cap)
25
		shade->mesh_cap = (shade->mesh_cap * 3) / 2;
26
 
27
	shade->mesh = fz_realloc(shade->mesh, shade->mesh_cap, sizeof(float));
28
}
29
 
30
static void
31
pdf_add_vertex(fz_shade *shade, struct vertex *v)
32
{
33
	int ncomp = shade->use_function ? 1 : shade->colorspace->n;
34
	int i;
35
	pdf_grow_mesh(shade, 2 + ncomp);
36
	shade->mesh[shade->mesh_len++] = v->x;
37
	shade->mesh[shade->mesh_len++] = v->y;
38
	for (i = 0; i < ncomp; i++)
39
		shade->mesh[shade->mesh_len++] = v->c[i];
40
}
41
 
42
static void
43
pdf_add_triangle(fz_shade *shade,
44
	struct vertex *v0,
45
	struct vertex *v1,
46
	struct vertex *v2)
47
{
48
	pdf_add_vertex(shade, v0);
49
	pdf_add_vertex(shade, v1);
50
	pdf_add_vertex(shade, v2);
51
}
52
 
53
static void
54
pdf_add_quad(fz_shade *shade,
55
	struct vertex *v0,
56
	struct vertex *v1,
57
	struct vertex *v2,
58
	struct vertex *v3)
59
{
60
	pdf_add_triangle(shade, v0, v1, v3);
61
	pdf_add_triangle(shade, v1, v3, v2);
62
}
63
 
64
/* Subdivide and tesselate tensor-patches */
65
 
66
typedef struct pdf_tensor_patch_s pdf_tensor_patch;
67
 
68
struct pdf_tensor_patch_s
69
{
70
	fz_point pole[4][4];
71
	float color[4][FZ_MAX_COLORS];
72
};
73
 
74
static void
75
triangulate_patch(pdf_tensor_patch p, fz_shade *shade)
76
{
77
	struct vertex v0, v1, v2, v3;
78
 
79
	v0.x = p.pole[0][0].x;
80
	v0.y = p.pole[0][0].y;
81
	memcpy(v0.c, p.color[0], sizeof(v0.c));
82
 
83
	v1.x = p.pole[0][3].x;
84
	v1.y = p.pole[0][3].y;
85
	memcpy(v1.c, p.color[1], sizeof(v1.c));
86
 
87
	v2.x = p.pole[3][3].x;
88
	v2.y = p.pole[3][3].y;
89
	memcpy(v2.c, p.color[2], sizeof(v2.c));
90
 
91
	v3.x = p.pole[3][0].x;
92
	v3.y = p.pole[3][0].y;
93
	memcpy(v3.c, p.color[3], sizeof(v3.c));
94
 
95
	pdf_add_quad(shade, &v0, &v1, &v2, &v3);
96
}
97
 
98
static inline void midcolor(float *c, float *c1, float *c2)
99
{
100
	int i;
101
	for (i = 0; i < FZ_MAX_COLORS; i++)
102
		c[i] = (c1[i] + c2[i]) * 0.5f;
103
}
104
 
105
static void
106
split_curve(fz_point *pole, fz_point *q0, fz_point *q1, int polestep)
107
{
108
	/*
109
	split bezier curve given by control points pole[0]..pole[3]
110
	using de casteljau algo at midpoint and build two new
111
	bezier curves q0[0]..q0[3] and q1[0]..q1[3]. all indices
112
	should be multiplies by polestep == 1 for vertical bezier
113
	curves in patch and == 4 for horizontal bezier curves due
114
	to C's multi-dimensional matrix memory layout.
115
	*/
116
 
117
	float x12 = (pole[1 * polestep].x + pole[2 * polestep].x) * 0.5f;
118
	float y12 = (pole[1 * polestep].y + pole[2 * polestep].y) * 0.5f;
119
 
120
	q0[1 * polestep].x = (pole[0 * polestep].x + pole[1 * polestep].x) * 0.5f;
121
	q0[1 * polestep].y = (pole[0 * polestep].y + pole[1 * polestep].y) * 0.5f;
122
	q1[2 * polestep].x = (pole[2 * polestep].x + pole[3 * polestep].x) * 0.5f;
123
	q1[2 * polestep].y = (pole[2 * polestep].y + pole[3 * polestep].y) * 0.5f;
124
 
125
	q0[2 * polestep].x = (q0[1 * polestep].x + x12) * 0.5f;
126
	q0[2 * polestep].y = (q0[1 * polestep].y + y12) * 0.5f;
127
	q1[1 * polestep].x = (x12 + q1[2 * polestep].x) * 0.5f;
128
	q1[1 * polestep].y = (y12 + q1[2 * polestep].y) * 0.5f;
129
 
130
	q0[3 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
131
	q0[3 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
132
	q1[0 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
133
	q1[0 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
134
 
135
	q0[0 * polestep].x = pole[0 * polestep].x;
136
	q0[0 * polestep].y = pole[0 * polestep].y;
137
	q1[3 * polestep].x = pole[3 * polestep].x;
138
	q1[3 * polestep].y = pole[3 * polestep].y;
139
}
140
 
141
static void
142
split_stripe(pdf_tensor_patch *p, pdf_tensor_patch *s0, pdf_tensor_patch *s1)
143
{
144
	/*
145
	split all horizontal bezier curves in patch,
146
	creating two new patches with half the width.
147
	*/
148
	split_curve(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
149
	split_curve(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
150
	split_curve(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
151
	split_curve(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
152
 
153
	/* interpolate the colors for the two new patches. */
154
	memcpy(s0->color[0], p->color[0], sizeof(s0->color[0]));
155
	memcpy(s0->color[1], p->color[1], sizeof(s0->color[1]));
156
	midcolor(s0->color[2], p->color[1], p->color[2]);
157
	midcolor(s0->color[3], p->color[0], p->color[3]);
158
 
159
	memcpy(s1->color[0], s0->color[3], sizeof(s1->color[0]));
160
	memcpy(s1->color[1], s0->color[2], sizeof(s1->color[1]));
161
	memcpy(s1->color[2], p->color[2], sizeof(s1->color[2]));
162
	memcpy(s1->color[3], p->color[3], sizeof(s1->color[3]));
163
}
164
 
165
static void
166
draw_stripe(pdf_tensor_patch *p, fz_shade *shade, int depth)
167
{
168
	pdf_tensor_patch s0, s1;
169
 
170
	/* split patch into two half-height patches */
171
	split_stripe(p, &s0, &s1);
172
 
173
	depth--;
174
	if (depth == 0)
175
	{
176
		/* if no more subdividing, draw two new patches... */
177
		triangulate_patch(s0, shade);
178
		triangulate_patch(s1, shade);
179
	}
180
	else
181
	{
182
		/* ...otherwise, continue subdividing. */
183
		draw_stripe(&s0, shade, depth);
184
		draw_stripe(&s1, shade, depth);
185
	}
186
}
187
 
188
static void
189
split_patch(pdf_tensor_patch *p, pdf_tensor_patch *s0, pdf_tensor_patch *s1)
190
{
191
	/*
192
	split all vertical bezier curves in patch,
193
	creating two new patches with half the height.
194
	*/
195
	split_curve(p->pole[0], s0->pole[0], s1->pole[0], 1);
196
	split_curve(p->pole[1], s0->pole[1], s1->pole[1], 1);
197
	split_curve(p->pole[2], s0->pole[2], s1->pole[2], 1);
198
	split_curve(p->pole[3], s0->pole[3], s1->pole[3], 1);
199
 
200
	/* interpolate the colors for the two new patches. */
201
	memcpy(s0->color[0], p->color[0], sizeof(s0->color[0]));
202
	midcolor(s0->color[1], p->color[0], p->color[1]);
203
	midcolor(s0->color[2], p->color[2], p->color[3]);
204
	memcpy(s0->color[3], p->color[3], sizeof(s0->color[3]));
205
 
206
	memcpy(s1->color[0], s0->color[1], sizeof(s1->color[0]));
207
	memcpy(s1->color[1], p->color[1], sizeof(s1->color[1]));
208
	memcpy(s1->color[2], p->color[2], sizeof(s1->color[2]));
209
	memcpy(s1->color[3], s0->color[2], sizeof(s1->color[3]));
210
}
211
 
212
static void
213
draw_patch(fz_shade *shade, pdf_tensor_patch *p, int depth, int origdepth)
214
{
215
	pdf_tensor_patch s0, s1;
216
 
217
	/* split patch into two half-width patches */
218
	split_patch(p, &s0, &s1);
219
 
220
	depth--;
221
	if (depth == 0)
222
	{
223
		/* if no more subdividing, draw two new patches... */
224
		draw_stripe(&s0, shade, origdepth);
225
		draw_stripe(&s1, shade, origdepth);
226
	}
227
	else
228
	{
229
		/* ...otherwise, continue subdividing. */
230
		draw_patch(shade, &s0, depth, origdepth);
231
		draw_patch(shade, &s1, depth, origdepth);
232
	}
233
}
234
 
235
static fz_point
236
pdf_compute_tensor_interior(
237
	fz_point a, fz_point b, fz_point c, fz_point d,
238
	fz_point e, fz_point f, fz_point g, fz_point h)
239
{
240
	fz_point pt;
241
 
242
	/* see equations at page 330 in pdf 1.7 */
243
 
244
	pt.x = -4 * a.x;
245
	pt.x += 6 * (b.x + c.x);
246
	pt.x += -2 * (d.x + e.x);
247
	pt.x += 3 * (f.x + g.x);
248
	pt.x += -1 * h.x;
249
	pt.x /= 9;
250
 
251
	pt.y = -4 * a.y;
252
	pt.y += 6 * (b.y + c.y);
253
	pt.y += -2 * (d.y + e.y);
254
	pt.y += 3 * (f.y + g.y);
255
	pt.y += -1 * h.y;
256
	pt.y /= 9;
257
 
258
	return pt;
259
}
260
 
261
static void
262
pdf_make_tensor_patch(pdf_tensor_patch *p, int type, fz_point *pt)
263
{
264
	if (type == 6)
265
	{
266
		/* see control point stream order at page 325 in pdf 1.7 */
267
 
268
		p->pole[0][0] = pt[0];
269
		p->pole[0][1] = pt[1];
270
		p->pole[0][2] = pt[2];
271
		p->pole[0][3] = pt[3];
272
		p->pole[1][3] = pt[4];
273
		p->pole[2][3] = pt[5];
274
		p->pole[3][3] = pt[6];
275
		p->pole[3][2] = pt[7];
276
		p->pole[3][1] = pt[8];
277
		p->pole[3][0] = pt[9];
278
		p->pole[2][0] = pt[10];
279
		p->pole[1][0] = pt[11];
280
 
281
		/* see equations at page 330 in pdf 1.7 */
282
 
283
		p->pole[1][1] = pdf_compute_tensor_interior(
284
			p->pole[0][0], p->pole[0][1], p->pole[1][0], p->pole[0][3],
285
			p->pole[3][0], p->pole[3][1], p->pole[1][3], p->pole[3][3]);
286
 
287
		p->pole[1][2] = pdf_compute_tensor_interior(
288
			p->pole[0][3], p->pole[0][2], p->pole[1][3], p->pole[0][0],
289
			p->pole[3][3], p->pole[3][2], p->pole[1][0], p->pole[3][0]);
290
 
291
		p->pole[2][1] = pdf_compute_tensor_interior(
292
			p->pole[3][0], p->pole[3][1], p->pole[2][0], p->pole[3][3],
293
			p->pole[0][0], p->pole[0][1], p->pole[2][3], p->pole[0][3]);
294
 
295
		p->pole[2][2] = pdf_compute_tensor_interior(
296
			p->pole[3][3], p->pole[3][2], p->pole[2][3], p->pole[3][0],
297
			p->pole[0][3], p->pole[0][2], p->pole[2][0], p->pole[0][0]);
298
	}
299
	else if (type == 7)
300
	{
301
		/* see control point stream order at page 330 in pdf 1.7 */
302
 
303
		p->pole[0][0] = pt[0];
304
		p->pole[0][1] = pt[1];
305
		p->pole[0][2] = pt[2];
306
		p->pole[0][3] = pt[3];
307
		p->pole[1][3] = pt[4];
308
		p->pole[2][3] = pt[5];
309
		p->pole[3][3] = pt[6];
310
		p->pole[3][2] = pt[7];
311
		p->pole[3][1] = pt[8];
312
		p->pole[3][0] = pt[9];
313
		p->pole[2][0] = pt[10];
314
		p->pole[1][0] = pt[11];
315
		p->pole[1][1] = pt[12];
316
		p->pole[1][2] = pt[13];
317
		p->pole[2][2] = pt[14];
318
		p->pole[2][1] = pt[15];
319
	}
320
}
321
 
322
/* Sample various functions into lookup tables */
323
 
324
static void
325
pdf_sample_composite_shade_function(fz_shade *shade, pdf_function *func, float t0, float t1)
326
{
327
	int i;
328
	float t;
329
 
330
	for (i = 0; i < 256; i++)
331
	{
332
		t = t0 + (i / 255.0f) * (t1 - t0);
333
		pdf_eval_function(func, &t, 1, shade->function[i], shade->colorspace->n);
334
		shade->function[i][shade->colorspace->n] = 1;
335
	}
336
}
337
 
338
static void
339
pdf_sample_component_shade_function(fz_shade *shade, int funcs, pdf_function **func, float t0, float t1)
340
{
341
	int i, k;
342
	float t;
343
 
344
	for (i = 0; i < 256; i++)
345
	{
346
		t = t0 + (i / 255.0f) * (t1 - t0);
347
		for (k = 0; k < funcs; k++)
348
			pdf_eval_function(func[k], &t, 1, &shade->function[i][k], 1);
349
		shade->function[i][k] = 1;
350
	}
351
}
352
 
353
static void
354
pdf_sample_shade_function(fz_shade *shade, int funcs, pdf_function **func, float t0, float t1)
355
{
356
	shade->use_function = 1;
357
	if (funcs == 1)
358
		pdf_sample_composite_shade_function(shade, func[0], t0, t1);
359
	else
360
		pdf_sample_component_shade_function(shade, funcs, func, t0, t1);
361
}
362
 
363
/* Type 1-3 -- Function-based, axial and radial shadings */
364
 
365
static void
366
pdf_load_function_based_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, pdf_function *func)
367
{
368
	fz_obj *obj;
369
	float x0, y0, x1, y1;
370
	fz_matrix matrix;
371
	struct vertex v[4];
372
	int xx, yy;
373
	float x, y;
374
	float xn, yn;
375
	int i;
376
 
377
	x0 = y0 = 0;
378
	x1 = y1 = 1;
379
	obj = fz_dict_gets(dict, "Domain");
380
	if (fz_array_len(obj) == 4)
381
	{
382
		x0 = fz_to_real(fz_array_get(obj, 0));
383
		x1 = fz_to_real(fz_array_get(obj, 1));
384
		y0 = fz_to_real(fz_array_get(obj, 2));
385
		y1 = fz_to_real(fz_array_get(obj, 3));
386
	}
387
 
388
	matrix = fz_identity;
389
	obj = fz_dict_gets(dict, "Matrix");
390
	if (fz_array_len(obj) == 6)
391
		matrix = pdf_to_matrix(obj);
392
 
393
	for (yy = 0; yy < FUNSEGS; yy++)
394
	{
395
		y = y0 + (y1 - y0) * yy / FUNSEGS;
396
		yn = y0 + (y1 - y0) * (yy + 1) / FUNSEGS;
397
 
398
		for (xx = 0; xx < FUNSEGS; xx++)
399
		{
400
			x = x0 + (x1 - x0) * xx / FUNSEGS;
401
			xn = x0 + (x1 - x0) * (xx + 1) / FUNSEGS;
402
 
403
			v[0].x = x; v[0].y = y;
404
			v[1].x = xn; v[1].y = y;
405
			v[2].x = xn; v[2].y = yn;
406
			v[3].x = x; v[3].y = yn;
407
 
408
			for (i = 0; i < 4; i++)
409
			{
410
				fz_point pt;
411
				float fv[2];
412
 
413
				fv[0] = v[i].x;
414
				fv[1] = v[i].y;
415
				pdf_eval_function(func, fv, 2, v[i].c, shade->colorspace->n);
416
 
417
				pt.x = v[i].x;
418
				pt.y = v[i].y;
419
				pt = fz_transform_point(matrix, pt);
420
				v[i].x = pt.x;
421
				v[i].y = pt.y;
422
			}
423
 
424
			pdf_add_quad(shade, &v[0], &v[1], &v[2], &v[3]);
425
		}
426
	}
427
}
428
 
429
static void
430
pdf_load_axial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func)
431
{
432
	fz_obj *obj;
433
	float d0, d1;
434
	int e0, e1;
435
	float x0, y0, x1, y1;
436
	struct vertex p1, p2;
437
 
438
	obj = fz_dict_gets(dict, "Coords");
439
	x0 = fz_to_real(fz_array_get(obj, 0));
440
	y0 = fz_to_real(fz_array_get(obj, 1));
441
	x1 = fz_to_real(fz_array_get(obj, 2));
442
	y1 = fz_to_real(fz_array_get(obj, 3));
443
 
444
	d0 = 0;
445
	d1 = 1;
446
	obj = fz_dict_gets(dict, "Domain");
447
	if (fz_array_len(obj) == 2)
448
	{
449
		d0 = fz_to_real(fz_array_get(obj, 0));
450
		d1 = fz_to_real(fz_array_get(obj, 1));
451
	}
452
 
453
	e0 = e1 = 0;
454
	obj = fz_dict_gets(dict, "Extend");
455
	if (fz_array_len(obj) == 2)
456
	{
457
		e0 = fz_to_bool(fz_array_get(obj, 0));
458
		e1 = fz_to_bool(fz_array_get(obj, 1));
459
	}
460
 
461
	pdf_sample_shade_function(shade, funcs, func, d0, d1);
462
 
463
	shade->type = FZ_LINEAR;
464
 
465
	shade->extend[0] = e0;
466
	shade->extend[1] = e1;
467
 
468
	p1.x = x0;
469
	p1.y = y0;
470
	p1.c[0] = 0;
471
	pdf_add_vertex(shade, &p1);
472
 
473
	p2.x = x1;
474
	p2.y = y1;
475
	p2.c[0] = 0;
476
	pdf_add_vertex(shade, &p2);
477
}
478
 
479
static void
480
pdf_load_radial_shading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, int funcs, pdf_function **func)
481
{
482
	fz_obj *obj;
483
	float d0, d1;
484
	int e0, e1;
485
	float x0, y0, r0, x1, y1, r1;
486
	struct vertex p1, p2;
487
 
488
	obj = fz_dict_gets(dict, "Coords");
489
	x0 = fz_to_real(fz_array_get(obj, 0));
490
	y0 = fz_to_real(fz_array_get(obj, 1));
491
	r0 = fz_to_real(fz_array_get(obj, 2));
492
	x1 = fz_to_real(fz_array_get(obj, 3));
493
	y1 = fz_to_real(fz_array_get(obj, 4));
494
	r1 = fz_to_real(fz_array_get(obj, 5));
495
 
496
	d0 = 0;
497
	d1 = 1;
498
	obj = fz_dict_gets(dict, "Domain");
499
	if (fz_array_len(obj) == 2)
500
	{
501
		d0 = fz_to_real(fz_array_get(obj, 0));
502
		d1 = fz_to_real(fz_array_get(obj, 1));
503
	}
504
 
505
	e0 = e1 = 0;
506
	obj = fz_dict_gets(dict, "Extend");
507
	if (fz_array_len(obj) == 2)
508
	{
509
		e0 = fz_to_bool(fz_array_get(obj, 0));
510
		e1 = fz_to_bool(fz_array_get(obj, 1));
511
	}
512
 
513
	pdf_sample_shade_function(shade, funcs, func, d0, d1);
514
 
515
	shade->type = FZ_RADIAL;
516
 
517
	shade->extend[0] = e0;
518
	shade->extend[1] = e1;
519
 
520
	p1.x = x0;
521
	p1.y = y0;
522
	p1.c[0] = r0;
523
	pdf_add_vertex(shade, &p1);
524
 
525
	p2.x = x1;
526
	p2.y = y1;
527
	p2.c[0] = r1;
528
	pdf_add_vertex(shade, &p2);
529
}
530
 
531
/* Type 4-7 -- Triangle and patch mesh shadings */
532
 
533
static inline float read_sample(fz_stream *stream, int bits, float min, float max)
534
{
535
	/* we use pow(2,x) because (1<
536
	float bitscale = 1 / (powf(2, bits) - 1);
537
	return min + fz_read_bits(stream, bits) * (max - min) * bitscale;
538
}
539
 
540
struct mesh_params
541
{
542
	int vprow;
543
	int bpflag;
544
	int bpcoord;
545
	int bpcomp;
546
	float x0, x1;
547
	float y0, y1;
548
	float c0[FZ_MAX_COLORS];
549
	float c1[FZ_MAX_COLORS];
550
};
551
 
552
static void
553
pdf_load_mesh_params(pdf_xref *xref, fz_obj *dict, struct mesh_params *p)
554
{
555
	fz_obj *obj;
556
	int i, n;
557
 
558
	p->x0 = p->y0 = 0;
559
	p->x1 = p->y1 = 1;
560
	for (i = 0; i < FZ_MAX_COLORS; i++)
561
	{
562
		p->c0[i] = 0;
563
		p->c1[i] = 1;
564
	}
565
 
566
	p->vprow = fz_to_int(fz_dict_gets(dict, "VerticesPerRow"));
567
	p->bpflag = fz_to_int(fz_dict_gets(dict, "BitsPerFlag"));
568
	p->bpcoord = fz_to_int(fz_dict_gets(dict, "BitsPerCoordinate"));
569
	p->bpcomp = fz_to_int(fz_dict_gets(dict, "BitsPerComponent"));
570
 
571
	obj = fz_dict_gets(dict, "Decode");
572
	if (fz_array_len(obj) >= 6)
573
	{
574
		n = (fz_array_len(obj) - 4) / 2;
575
		p->x0 = fz_to_real(fz_array_get(obj, 0));
576
		p->x1 = fz_to_real(fz_array_get(obj, 1));
577
		p->y0 = fz_to_real(fz_array_get(obj, 2));
578
		p->y1 = fz_to_real(fz_array_get(obj, 3));
579
		for (i = 0; i < n; i++)
580
		{
581
			p->c0[i] = fz_to_real(fz_array_get(obj, 4 + i * 2));
582
			p->c1[i] = fz_to_real(fz_array_get(obj, 5 + i * 2));
583
		}
584
	}
585
 
586
	if (p->vprow < 2)
587
		p->vprow = 2;
588
 
589
	if (p->bpflag != 2 && p->bpflag != 4 && p->bpflag != 8)
590
		p->bpflag = 8;
591
 
592
	if (p->bpcoord != 1 && p->bpcoord != 2 && p->bpcoord != 4 &&
593
		p->bpcoord != 8 && p->bpcoord != 12 && p->bpcoord != 16 &&
594
		p->bpcoord != 24 && p->bpcoord != 32)
595
		p->bpcoord = 8;
596
 
597
	if (p->bpcomp != 1 && p->bpcomp != 2 && p->bpcomp != 4 &&
598
		p->bpcomp != 8 && p->bpcomp != 12 && p->bpcomp != 16)
599
		p->bpcomp = 8;
600
}
601
 
602
static void
603
pdf_load_type4_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict,
604
	int funcs, pdf_function **func, fz_stream *stream)
605
{
606
	struct mesh_params p;
607
	struct vertex va, vb, vc, vd;
608
	int ncomp;
609
	int flag;
610
	int i;
611
 
612
	pdf_load_mesh_params(xref, dict, &p);
613
 
614
	if (funcs > 0)
615
	{
616
		ncomp = 1;
617
		pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]);
618
	}
619
	else
620
		ncomp = shade->colorspace->n;
621
 
622
	while (!fz_is_eof_bits(stream))
623
	{
624
		flag = fz_read_bits(stream, p.bpflag);
625
		vd.x = read_sample(stream, p.bpcoord, p.x0, p.x1);
626
		vd.y = read_sample(stream, p.bpcoord, p.y0, p.y1);
627
		for (i = 0; i < ncomp; i++)
628
			vd.c[i] = read_sample(stream, p.bpcomp, p.c0[i], p.c1[i]);
629
 
630
		switch (flag)
631
		{
632
		case 0: /* start new triangle */
633
			va = vd;
634
 
635
			fz_read_bits(stream, p.bpflag);
636
			vb.x = read_sample(stream, p.bpcoord, p.x0, p.x1);
637
			vb.y = read_sample(stream, p.bpcoord, p.y0, p.y1);
638
			for (i = 0; i < ncomp; i++)
639
				vb.c[i] = read_sample(stream, p.bpcomp, p.c0[i], p.c1[i]);
640
 
641
			fz_read_bits(stream, p.bpflag);
642
			vc.x = read_sample(stream, p.bpcoord, p.x0, p.x1);
643
			vc.y = read_sample(stream, p.bpcoord, p.y0, p.y1);
644
			for (i = 0; i < ncomp; i++)
645
				vc.c[i] = read_sample(stream, p.bpcomp, p.c0[i], p.c1[i]);
646
 
647
			pdf_add_triangle(shade, &va, &vb, &vc);
648
			break;
649
 
650
		case 1: /* Vb, Vc, Vd */
651
			va = vb;
652
			vb = vc;
653
			vc = vd;
654
			pdf_add_triangle(shade, &va, &vb, &vc);
655
			break;
656
 
657
		case 2: /* Va, Vc, Vd */
658
			vb = vc;
659
			vc = vd;
660
			pdf_add_triangle(shade, &va, &vb, &vc);
661
			break;
662
		}
663
	}
664
}
665
 
666
static void
667
pdf_load_type5_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict,
668
	int funcs, pdf_function **func, fz_stream *stream)
669
{
670
	struct mesh_params p;
671
	struct vertex *buf, *ref;
672
	int first;
673
	int ncomp;
674
	int i, k;
675
 
676
	pdf_load_mesh_params(xref, dict, &p);
677
 
678
	if (funcs > 0)
679
	{
680
		ncomp = 1;
681
		pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]);
682
	}
683
	else
684
		ncomp = shade->colorspace->n;
685
 
686
	ref = fz_calloc(p.vprow, sizeof(struct vertex));
687
	buf = fz_calloc(p.vprow, sizeof(struct vertex));
688
	first = 1;
689
 
690
	while (!fz_is_eof_bits(stream))
691
	{
692
		for (i = 0; i < p.vprow; i++)
693
		{
694
			buf[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1);
695
			buf[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1);
696
			for (k = 0; k < ncomp; k++)
697
				buf[i].c[k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]);
698
		}
699
 
700
		if (!first)
701
			for (i = 0; i < p.vprow - 1; i++)
702
				pdf_add_quad(shade,
703
					&ref[i], &ref[i+1], &buf[i+1], &buf[i]);
704
 
705
		memcpy(ref, buf, p.vprow * sizeof(struct vertex));
706
		first = 0;
707
	}
708
 
709
	free(ref);
710
	free(buf);
711
}
712
 
713
/* Type 6 & 7 -- Patch mesh shadings */
714
 
715
static void
716
pdf_load_type6_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict,
717
	int funcs, pdf_function **func, fz_stream *stream)
718
{
719
	struct mesh_params p;
720
	int haspatch, hasprevpatch;
721
	float prevc[4][FZ_MAX_COLORS];
722
	fz_point prevp[12];
723
	int ncomp;
724
	int i, k;
725
 
726
	pdf_load_mesh_params(xref, dict, &p);
727
 
728
	if (funcs > 0)
729
	{
730
		ncomp = 1;
731
		pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]);
732
	}
733
	else
734
		ncomp = shade->colorspace->n;
735
 
736
	hasprevpatch = 0;
737
 
738
	while (!fz_is_eof_bits(stream))
739
	{
740
		float c[4][FZ_MAX_COLORS];
741
		fz_point v[12];
742
		int startcolor;
743
		int startpt;
744
		int flag;
745
 
746
		flag = fz_read_bits(stream, p.bpflag);
747
 
748
		if (flag == 0)
749
		{
750
			startpt = 0;
751
			startcolor = 0;
752
		}
753
		else
754
		{
755
			startpt = 4;
756
			startcolor = 2;
757
		}
758
 
759
		for (i = startpt; i < 12; i++)
760
		{
761
			v[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1);
762
			v[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1);
763
		}
764
 
765
		for (i = startcolor; i < 4; i++)
766
		{
767
			for (k = 0; k < ncomp; k++)
768
				c[i][k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]);
769
		}
770
 
771
		haspatch = 0;
772
 
773
		if (flag == 0)
774
		{
775
			haspatch = 1;
776
		}
777
		else if (flag == 1 && hasprevpatch)
778
		{
779
			v[0] = prevp[3];
780
			v[1] = prevp[4];
781
			v[2] = prevp[5];
782
			v[3] = prevp[6];
783
			memcpy(c[0], prevc[1], ncomp * sizeof(float));
784
			memcpy(c[1], prevc[2], ncomp * sizeof(float));
785
 
786
			haspatch = 1;
787
		}
788
		else if (flag == 2 && hasprevpatch)
789
		{
790
			v[0] = prevp[6];
791
			v[1] = prevp[7];
792
			v[2] = prevp[8];
793
			v[3] = prevp[9];
794
			memcpy(c[0], prevc[2], ncomp * sizeof(float));
795
			memcpy(c[1], prevc[3], ncomp * sizeof(float));
796
 
797
			haspatch = 1;
798
		}
799
		else if (flag == 3 && hasprevpatch)
800
		{
801
			v[0] = prevp[ 9];
802
			v[1] = prevp[10];
803
			v[2] = prevp[11];
804
			v[3] = prevp[ 0];
805
			memcpy(c[0], prevc[3], ncomp * sizeof(float));
806
			memcpy(c[1], prevc[0], ncomp * sizeof(float));
807
 
808
			haspatch = 1;
809
		}
810
 
811
		if (haspatch)
812
		{
813
			pdf_tensor_patch patch;
814
 
815
			pdf_make_tensor_patch(&patch, 6, v);
816
 
817
			for (i = 0; i < 4; i++)
818
				memcpy(patch.color[i], c[i], ncomp * sizeof(float));
819
 
820
			draw_patch(shade, &patch, SUBDIV, SUBDIV);
821
 
822
			for (i = 0; i < 12; i++)
823
				prevp[i] = v[i];
824
 
825
			for (i = 0; i < 4; i++)
826
				memcpy(prevc[i], c[i], ncomp * sizeof(float));
827
 
828
			hasprevpatch = 1;
829
		}
830
	}
831
}
832
 
833
static void
834
pdf_load_type7_shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict,
835
	int funcs, pdf_function **func, fz_stream *stream)
836
{
837
	struct mesh_params p;
838
	int haspatch, hasprevpatch;
839
	float prevc[4][FZ_MAX_COLORS];
840
	fz_point prevp[16];
841
	int ncomp;
842
	int i, k;
843
 
844
	pdf_load_mesh_params(xref, dict, &p);
845
 
846
	if (funcs > 0)
847
	{
848
		ncomp = 1;
849
		pdf_sample_shade_function(shade, funcs, func, p.c0[0], p.c1[0]);
850
	}
851
	else
852
		ncomp = shade->colorspace->n;
853
 
854
	hasprevpatch = 0;
855
 
856
	while (!fz_is_eof_bits(stream))
857
	{
858
		float c[4][FZ_MAX_COLORS];
859
		fz_point v[16];
860
		int startcolor;
861
		int startpt;
862
		int flag;
863
 
864
		flag = fz_read_bits(stream, p.bpflag);
865
 
866
		if (flag == 0)
867
		{
868
			startpt = 0;
869
			startcolor = 0;
870
		}
871
		else
872
		{
873
			startpt = 4;
874
			startcolor = 2;
875
		}
876
 
877
		for (i = startpt; i < 16; i++)
878
		{
879
			v[i].x = read_sample(stream, p.bpcoord, p.x0, p.x1);
880
			v[i].y = read_sample(stream, p.bpcoord, p.y0, p.y1);
881
		}
882
 
883
		for (i = startcolor; i < 4; i++)
884
		{
885
			for (k = 0; k < ncomp; k++)
886
				c[i][k] = read_sample(stream, p.bpcomp, p.c0[k], p.c1[k]);
887
		}
888
 
889
		haspatch = 0;
890
 
891
		if (flag == 0)
892
		{
893
			haspatch = 1;
894
		}
895
		else if (flag == 1 && hasprevpatch)
896
		{
897
			v[0] = prevp[3];
898
			v[1] = prevp[4];
899
			v[2] = prevp[5];
900
			v[3] = prevp[6];
901
			memcpy(c[0], prevc[1], ncomp * sizeof(float));
902
			memcpy(c[1], prevc[2], ncomp * sizeof(float));
903
 
904
			haspatch = 1;
905
		}
906
		else if (flag == 2 && hasprevpatch)
907
		{
908
			v[0] = prevp[6];
909
			v[1] = prevp[7];
910
			v[2] = prevp[8];
911
			v[3] = prevp[9];
912
			memcpy(c[0], prevc[2], ncomp * sizeof(float));
913
			memcpy(c[1], prevc[3], ncomp * sizeof(float));
914
 
915
			haspatch = 1;
916
		}
917
		else if (flag == 3 && hasprevpatch)
918
		{
919
			v[0] = prevp[ 9];
920
			v[1] = prevp[10];
921
			v[2] = prevp[11];
922
			v[3] = prevp[ 0];
923
			memcpy(c[0], prevc[3], ncomp * sizeof(float));
924
			memcpy(c[1], prevc[0], ncomp * sizeof(float));
925
 
926
			haspatch = 1;
927
		}
928
 
929
		if (haspatch)
930
		{
931
			pdf_tensor_patch patch;
932
 
933
			pdf_make_tensor_patch(&patch, 7, v);
934
 
935
			for (i = 0; i < 4; i++)
936
				memcpy(patch.color[i], c[i], ncomp * sizeof(float));
937
 
938
			draw_patch(shade, &patch, SUBDIV, SUBDIV);
939
 
940
			for (i = 0; i < 16; i++)
941
				prevp[i] = v[i];
942
 
943
			for (i = 0; i < 4; i++)
944
				memcpy(prevc[i], c[i], FZ_MAX_COLORS * sizeof(float));
945
 
946
			hasprevpatch = 1;
947
		}
948
	}
949
}
950
 
951
/* Load all of the shading dictionary parameters, then switch on the shading type. */
952
 
953
static fz_error
954
pdf_load_shading_dict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_matrix transform)
955
{
956
	fz_error error;
957
	fz_shade *shade;
958
	pdf_function *func[FZ_MAX_COLORS] = { NULL };
959
	fz_stream *stream = NULL;
960
	fz_obj *obj;
961
	int funcs;
962
	int type;
963
	int i;
964
 
965
	shade = fz_malloc(sizeof(fz_shade));
966
	shade->refs = 1;
967
	shade->type = FZ_MESH;
968
	shade->use_background = 0;
969
	shade->use_function = 0;
970
	shade->matrix = transform;
971
	shade->bbox = fz_infinite_rect;
972
	shade->extend[0] = 0;
973
	shade->extend[1] = 0;
974
 
975
	shade->mesh_len = 0;
976
	shade->mesh_cap = 0;
977
	shade->mesh = NULL;
978
 
979
	shade->colorspace = NULL;
980
 
981
	funcs = 0;
982
 
983
	obj = fz_dict_gets(dict, "ShadingType");
984
	type = fz_to_int(obj);
985
 
986
	obj = fz_dict_gets(dict, "ColorSpace");
987
	if (!obj)
988
	{
989
		fz_drop_shade(shade);
990
		return fz_throw("shading colorspace is missing");
991
	}
992
	error = pdf_load_colorspace(&shade->colorspace, xref, obj);
993
	if (error)
994
	{
995
		fz_drop_shade(shade);
996
		return fz_rethrow(error, "cannot load colorspace (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
997
	}
998
 
999
	obj = fz_dict_gets(dict, "Background");
1000
	if (obj)
1001
	{
1002
		shade->use_background = 1;
1003
		for (i = 0; i < shade->colorspace->n; i++)
1004
			shade->background[i] = fz_to_real(fz_array_get(obj, i));
1005
	}
1006
 
1007
	obj = fz_dict_gets(dict, "BBox");
1008
	if (fz_is_array(obj))
1009
	{
1010
		shade->bbox = pdf_to_rect(obj);
1011
	}
1012
 
1013
	obj = fz_dict_gets(dict, "Function");
1014
	if (fz_is_dict(obj))
1015
	{
1016
		funcs = 1;
1017
 
1018
		error = pdf_load_function(&func[0], xref, obj);
1019
		if (error)
1020
		{
1021
			error = fz_rethrow(error, "cannot load shading function (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
1022
			goto cleanup;
1023
		}
1024
	}
1025
	else if (fz_is_array(obj))
1026
	{
1027
		funcs = fz_array_len(obj);
1028
		if (funcs != 1 && funcs != shade->colorspace->n)
1029
		{
1030
			error = fz_throw("incorrect number of shading functions");
1031
			goto cleanup;
1032
		}
1033
 
1034
		for (i = 0; i < funcs; i++)
1035
		{
1036
			error = pdf_load_function(&func[i], xref, fz_array_get(obj, i));
1037
			if (error)
1038
			{
1039
				error = fz_rethrow(error, "cannot load shading function (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
1040
				goto cleanup;
1041
			}
1042
		}
1043
	}
1044
 
1045
	if (type >= 4 && type <= 7)
1046
	{
1047
		error = pdf_open_stream(&stream, xref, fz_to_num(dict), fz_to_gen(dict));
1048
		if (error)
1049
		{
1050
			error = fz_rethrow(error, "cannot open shading stream (%d %d R)", fz_to_num(dict), fz_to_gen(dict));
1051
			goto cleanup;
1052
		}
1053
	}
1054
 
1055
	switch (type)
1056
	{
1057
	case 1: pdf_load_function_based_shading(shade, xref, dict, func[0]); break;
1058
	case 2: pdf_load_axial_shading(shade, xref, dict, funcs, func); break;
1059
	case 3: pdf_load_radial_shading(shade, xref, dict, funcs, func); break;
1060
	case 4: pdf_load_type4_shade(shade, xref, dict, funcs, func, stream); break;
1061
	case 5: pdf_load_type5_shade(shade, xref, dict, funcs, func, stream); break;
1062
	case 6: pdf_load_type6_shade(shade, xref, dict, funcs, func, stream); break;
1063
	case 7: pdf_load_type7_shade(shade, xref, dict, funcs, func, stream); break;
1064
	default:
1065
		error = fz_throw("unknown shading type: %d", type);
1066
		goto cleanup;
1067
	}
1068
 
1069
	if (stream)
1070
		fz_close(stream);
1071
	for (i = 0; i < funcs; i++)
1072
		if (func[i])
1073
			pdf_drop_function(func[i]);
1074
 
1075
	*shadep = shade;
1076
	return fz_okay;
1077
 
1078
cleanup:
1079
	if (stream)
1080
		fz_close(stream);
1081
	for (i = 0; i < funcs; i++)
1082
		if (func[i])
1083
			pdf_drop_function(func[i]);
1084
	fz_drop_shade(shade);
1085
 
1086
	return fz_rethrow(error, "cannot load shading type %d (%d %d R)", type, fz_to_num(dict), fz_to_gen(dict));
1087
}
1088
 
1089
fz_error
1090
pdf_load_shading(fz_shade **shadep, pdf_xref *xref, fz_obj *dict)
1091
{
1092
	fz_error error;
1093
	fz_matrix mat;
1094
	fz_obj *obj;
1095
 
1096
	if ((*shadep = pdf_find_item(xref->store, fz_drop_shade, dict)))
1097
	{
1098
		fz_keep_shade(*shadep);
1099
		return fz_okay;
1100
	}
1101
 
1102
	/* Type 2 pattern dictionary */
1103
	if (fz_dict_gets(dict, "PatternType"))
1104
	{
1105
		obj = fz_dict_gets(dict, "Matrix");
1106
		if (obj)
1107
			mat = pdf_to_matrix(obj);
1108
		else
1109
			mat = fz_identity;
1110
 
1111
		obj = fz_dict_gets(dict, "ExtGState");
1112
		if (obj)
1113
		{
1114
			if (fz_dict_gets(obj, "CA") || fz_dict_gets(obj, "ca"))
1115
			{
1116
				fz_warn("shading with alpha not supported");
1117
			}
1118
		}
1119
 
1120
		obj = fz_dict_gets(dict, "Shading");
1121
		if (!obj)
1122
			return fz_throw("syntaxerror: missing shading dictionary");
1123
 
1124
		error = pdf_load_shading_dict(shadep, xref, obj, mat);
1125
		if (error)
1126
			return fz_rethrow(error, "cannot load shading dictionary (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
1127
	}
1128
 
1129
	/* Naked shading dictionary */
1130
	else
1131
	{
1132
		error = pdf_load_shading_dict(shadep, xref, dict, fz_identity);
1133
		if (error)
1134
			return fz_rethrow(error, "cannot load shading dictionary (%d %d R)", fz_to_num(dict), fz_to_gen(dict));
1135
	}
1136
 
1137
	pdf_store_item(xref->store, fz_keep_shade, fz_drop_shade, dict, *shadep);
1138
 
1139
	return fz_okay;
1140
}