Go to most recent revision | Details | 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 | }>>=>>>>>>>>>>>>>>>>>>>>>>>> |