1 #include "mupdf/fitz.h"
2 
3 #include "context-imp.h"
4 #include "image-imp.h"
5 #include "pixmap-imp.h"
6 
7 #include <string.h>
8 #include <math.h>
9 #include <assert.h>
10 
11 /* TODO: here or public? */
12 static int
fz_key_storable_needs_reaping(fz_context * ctx,const fz_key_storable * ks)13 fz_key_storable_needs_reaping(fz_context *ctx, const fz_key_storable *ks)
14 {
15 	return ks == NULL ? 0 : (ks->store_key_refs == ks->storable.refs);
16 }
17 
18 #define SANE_DPI 72.0f
19 #define INSANE_DPI 4800.0f
20 
21 #define SCALABLE_IMAGE_DPI 96
22 
23 struct fz_compressed_image
24 {
25 	fz_image super;
26 	fz_compressed_buffer *buffer;
27 };
28 
29 struct fz_pixmap_image
30 {
31 	fz_image super;
32 	fz_pixmap *tile;
33 };
34 
35 typedef struct
36 {
37 	int refs;
38 	fz_image *image;
39 	int l2factor;
40 	fz_irect rect;
41 } fz_image_key;
42 
43 fz_image *
fz_keep_image(fz_context * ctx,fz_image * image)44 fz_keep_image(fz_context *ctx, fz_image *image)
45 {
46 	return fz_keep_key_storable(ctx, &image->key_storable);
47 }
48 
49 fz_image *
fz_keep_image_store_key(fz_context * ctx,fz_image * image)50 fz_keep_image_store_key(fz_context *ctx, fz_image *image)
51 {
52 	return fz_keep_key_storable_key(ctx, &image->key_storable);
53 }
54 
55 void
fz_drop_image_store_key(fz_context * ctx,fz_image * image)56 fz_drop_image_store_key(fz_context *ctx, fz_image *image)
57 {
58 	fz_drop_key_storable_key(ctx, &image->key_storable);
59 }
60 
61 static int
fz_make_hash_image_key(fz_context * ctx,fz_store_hash * hash,void * key_)62 fz_make_hash_image_key(fz_context *ctx, fz_store_hash *hash, void *key_)
63 {
64 	fz_image_key *key = (fz_image_key *)key_;
65 	hash->u.pir.ptr = key->image;
66 	hash->u.pir.i = key->l2factor;
67 	hash->u.pir.r = key->rect;
68 	return 1;
69 }
70 
71 static void *
fz_keep_image_key(fz_context * ctx,void * key_)72 fz_keep_image_key(fz_context *ctx, void *key_)
73 {
74 	fz_image_key *key = (fz_image_key *)key_;
75 	return fz_keep_imp(ctx, key, &key->refs);
76 }
77 
78 static void
fz_drop_image_key(fz_context * ctx,void * key_)79 fz_drop_image_key(fz_context *ctx, void *key_)
80 {
81 	fz_image_key *key = (fz_image_key *)key_;
82 	if (fz_drop_imp(ctx, key, &key->refs))
83 	{
84 		fz_drop_image_store_key(ctx, key->image);
85 		fz_free(ctx, key);
86 	}
87 }
88 
89 static int
fz_cmp_image_key(fz_context * ctx,void * k0_,void * k1_)90 fz_cmp_image_key(fz_context *ctx, void *k0_, void *k1_)
91 {
92 	fz_image_key *k0 = (fz_image_key *)k0_;
93 	fz_image_key *k1 = (fz_image_key *)k1_;
94 	return k0->image == k1->image && k0->l2factor == k1->l2factor && k0->rect.x0 == k1->rect.x0 && k0->rect.y0 == k1->rect.y0 && k0->rect.x1 == k1->rect.x1 && k0->rect.y1 == k1->rect.y1;
95 }
96 
97 static void
fz_format_image_key(fz_context * ctx,char * s,size_t n,void * key_)98 fz_format_image_key(fz_context *ctx, char *s, size_t n, void *key_)
99 {
100 	fz_image_key *key = (fz_image_key *)key_;
101 	fz_snprintf(s, n, "(image %d x %d sf=%d)", key->image->w, key->image->h, key->l2factor);
102 }
103 
104 static int
fz_needs_reap_image_key(fz_context * ctx,void * key_)105 fz_needs_reap_image_key(fz_context *ctx, void *key_)
106 {
107 	fz_image_key *key = (fz_image_key *)key_;
108 
109 	return fz_key_storable_needs_reaping(ctx, &key->image->key_storable);
110 }
111 
112 static const fz_store_type fz_image_store_type =
113 {
114 	"fz_image",
115 	fz_make_hash_image_key,
116 	fz_keep_image_key,
117 	fz_drop_image_key,
118 	fz_cmp_image_key,
119 	fz_format_image_key,
120 	fz_needs_reap_image_key
121 };
122 
123 void
fz_drop_image(fz_context * ctx,fz_image * image)124 fz_drop_image(fz_context *ctx, fz_image *image)
125 {
126 	fz_drop_key_storable(ctx, &image->key_storable);
127 }
128 
129 static void
fz_mask_color_key(fz_pixmap * pix,int n,const int * colorkey)130 fz_mask_color_key(fz_pixmap *pix, int n, const int *colorkey)
131 {
132 	unsigned char *p = pix->samples;
133 	int w;
134 	int k, t;
135 	int h = pix->h;
136 	int stride = pix->stride - pix->w * pix->n;
137 	if (pix->w == 0)
138 		return;
139 	while (h--)
140 	{
141 		w = pix->w;
142 		do
143 		{
144 			t = 1;
145 			for (k = 0; k < n; k++)
146 				if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1])
147 					t = 0;
148 			if (t)
149 				for (k = 0; k < pix->n; k++)
150 					p[k] = 0;
151 			p += pix->n;
152 		}
153 		while (--w);
154 		p += stride;
155 	}
156 }
157 
158 static void
fz_unblend_masked_tile(fz_context * ctx,fz_pixmap * tile,fz_image * image,const fz_irect * isa)159 fz_unblend_masked_tile(fz_context *ctx, fz_pixmap *tile, fz_image *image, const fz_irect *isa)
160 {
161 	fz_pixmap *mask;
162 	unsigned char *s, *d = tile->samples;
163 	int n = tile->n;
164 	int k;
165 	int sstride, dstride = tile->stride - tile->w * tile->n;
166 	int h;
167 	fz_irect subarea;
168 
169 	/* We need at least as much of the mask as there was of the tile. */
170 	if (isa)
171 		subarea = *isa;
172 	else
173 	{
174 		subarea.x0 = 0;
175 		subarea.y0 = 0;
176 		subarea.x1 = tile->w;
177 		subarea.y1 = tile->h;
178 	}
179 
180 	mask = fz_get_pixmap_from_image(ctx, image->mask, &subarea, NULL, NULL, NULL);
181 	s = mask->samples;
182 	/* RJW: Urgh, bit of nastiness here. fz_pixmap_from_image will either return
183 	 * an exact match for the subarea we asked for, or the full image, and the
184 	 * normal way to know is that the matrix will be updated. That doesn't help
185 	 * us here. */
186 	if (image->mask->w == mask->w && image->mask->h == mask->h) {
187 		subarea.x0 = 0;
188 		subarea.y0 = 0;
189 	}
190 	if (isa)
191 		s += (isa->x0 - subarea.x0) * mask->n + (isa->y0 - subarea.y0) * mask->stride;
192 	sstride = mask->stride - tile->w * mask->n;
193 	h = tile->h;
194 
195 	if (tile->w != 0)
196 	{
197 		while (h--)
198 		{
199 			int w = tile->w;
200 			do
201 			{
202 				if (*s == 0)
203 					for (k = 0; k < image->n; k++)
204 						d[k] = image->colorkey[k];
205 				else
206 					for (k = 0; k < image->n; k++)
207 						d[k] = fz_clampi(image->colorkey[k] + (d[k] - image->colorkey[k]) * 255 / *s, 0, 255);
208 				s++;
209 				d += n;
210 			}
211 			while (--w);
212 			s += sstride;
213 			d += dstride;
214 		}
215 	}
216 
217 	fz_drop_pixmap(ctx, mask);
218 }
219 
fz_adjust_image_subarea(fz_context * ctx,fz_image * image,fz_irect * subarea,int l2factor)220 static void fz_adjust_image_subarea(fz_context *ctx, fz_image *image, fz_irect *subarea, int l2factor)
221 {
222 	int f = 1<<l2factor;
223 	int bpp = image->bpc * image->n;
224 	int mask;
225 
226 	switch (bpp)
227 	{
228 	case 1: mask = 8*f; break;
229 	case 2: mask = 4*f; break;
230 	case 4: mask = 2*f; break;
231 	default: mask = (bpp & 7) == 0 ? f : 0; break;
232 	}
233 
234 	if (mask != 0)
235 	{
236 		subarea->x0 &= ~(mask - 1);
237 		subarea->x1 = (subarea->x1 + mask - 1) & ~(mask - 1);
238 	}
239 	else
240 	{
241 		/* Awkward case - mask cannot be a power of 2. */
242 		mask = bpp*f;
243 		switch (bpp)
244 		{
245 		case 3:
246 		case 5:
247 		case 7:
248 		case 9:
249 		case 11:
250 		case 13:
251 		case 15:
252 		default:
253 			mask *= 8;
254 			break;
255 		case 6:
256 		case 10:
257 		case 14:
258 			mask *= 4;
259 			break;
260 		case 12:
261 			mask *= 2;
262 			break;
263 		}
264 		subarea->x0 = (subarea->x0 / mask) * mask;
265 		subarea->x1 = ((subarea->x1 + mask - 1) / mask) * mask;
266 	}
267 
268 	subarea->y0 &= ~(f - 1);
269 	if (subarea->x1 > image->w)
270 		subarea->x1 = image->w;
271 	subarea->y1 = (subarea->y1 + f - 1) & ~(f - 1);
272 	if (subarea->y1 > image->h)
273 		subarea->y1 = image->h;
274 }
275 
fz_compute_image_key(fz_context * ctx,fz_image * image,fz_matrix * ctm,fz_image_key * key,const fz_irect * subarea,int l2factor,int * w,int * h,int * dw,int * dh)276 static void fz_compute_image_key(fz_context *ctx, fz_image *image, fz_matrix *ctm,
277 	fz_image_key *key, const fz_irect *subarea, int l2factor, int *w, int *h, int *dw, int *dh)
278 {
279 	key->refs = 1;
280 	key->image = image;
281 	key->l2factor = l2factor;
282 
283 	if (subarea == NULL)
284 	{
285 		key->rect.x0 = 0;
286 		key->rect.y0 = 0;
287 		key->rect.x1 = image->w;
288 		key->rect.y1 = image->h;
289 	}
290 	else
291 	{
292 		key->rect = *subarea;
293 		ctx->tuning->image_decode(ctx->tuning->image_decode_arg, image->w, image->h, key->l2factor, &key->rect);
294 		fz_adjust_image_subarea(ctx, image, &key->rect, key->l2factor);
295 	}
296 
297 	/* Based on that subarea, recalculate the extents */
298 	if (ctm)
299 	{
300 		float frac_w = (float) (key->rect.x1 - key->rect.x0) / image->w;
301 		float frac_h = (float) (key->rect.y1 - key->rect.y0) / image->h;
302 		float a = ctm->a * frac_w;
303 		float b = ctm->b * frac_h;
304 		float c = ctm->c * frac_w;
305 		float d = ctm->d * frac_h;
306 		*w = sqrtf(a * a + b * b);
307 		*h = sqrtf(c * c + d * d);
308 	}
309 	else
310 	{
311 		*w = image->w;
312 		*h = image->h;
313 	}
314 
315 	/* Return the true sizes to the caller */
316 	if (dw)
317 		*dw = *w;
318 	if (dh)
319 		*dh = *h;
320 	if (*w > image->w)
321 		*w = image->w;
322 	if (*h > image->h)
323 		*h = image->h;
324 
325 	if (*w == 0 || *h == 0)
326 		key->l2factor = 0;
327 }
328 
329 fz_pixmap *
fz_decomp_image_from_stream(fz_context * ctx,fz_stream * stm,fz_compressed_image * cimg,fz_irect * subarea,int indexed,int l2factor)330 fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_compressed_image *cimg, fz_irect *subarea, int indexed, int l2factor)
331 {
332 	fz_image *image = &cimg->super;
333 	fz_pixmap *tile = NULL;
334 	size_t stride, len, i;
335 	unsigned char *samples = NULL;
336 	int f = 1<<l2factor;
337 	int w = image->w;
338 	int h = image->h;
339 	int matte = image->use_colorkey && image->mask;
340 
341 	if (matte)
342 	{
343 		/* Can't do l2factor decoding */
344 		if (image->w != image->mask->w || image->h != image->mask->h)
345 		{
346 			fz_warn(ctx, "mask must be of same size as image for /Matte");
347 			matte = 0;
348 		}
349 		assert(l2factor == 0);
350 	}
351 	if (subarea)
352 	{
353 		fz_adjust_image_subarea(ctx, image, subarea, l2factor);
354 		w = (subarea->x1 - subarea->x0);
355 		h = (subarea->y1 - subarea->y0);
356 	}
357 	w = (w + f - 1) >> l2factor;
358 	h = (h + f - 1) >> l2factor;
359 
360 	fz_var(tile);
361 	fz_var(samples);
362 
363 	fz_try(ctx)
364 	{
365 		int alpha = (image->colorspace == NULL);
366 		if (image->use_colorkey)
367 			alpha = 1;
368 		tile = fz_new_pixmap(ctx, image->colorspace, w, h, NULL, alpha);
369 		if (image->interpolate & FZ_PIXMAP_FLAG_INTERPOLATE)
370 			tile->flags |= FZ_PIXMAP_FLAG_INTERPOLATE;
371 		else
372 			tile->flags &= ~FZ_PIXMAP_FLAG_INTERPOLATE;
373 
374 		stride = (w * image->n * image->bpc + 7) / 8;
375 		if ((size_t)h > (size_t)(SIZE_MAX / stride))
376 			fz_throw(ctx, FZ_ERROR_MEMORY, "image too large");
377 		samples = Memento_label(fz_malloc(ctx, h * stride), "pixmap_samples");
378 
379 		if (subarea)
380 		{
381 			int hh;
382 			unsigned char *s = samples;
383 			int stream_w = (image->w + f - 1)>>l2factor;
384 			size_t stream_stride = (stream_w * image->n * image->bpc + 7) / 8;
385 			int l_margin = subarea->x0 >> l2factor;
386 			int t_margin = subarea->y0 >> l2factor;
387 			int r_margin = (image->w + f - 1 - subarea->x1) >> l2factor;
388 			int b_margin = (image->h + f - 1 - subarea->y1) >> l2factor;
389 			int l_skip = (l_margin * image->n * image->bpc)/8;
390 			int r_skip = (r_margin * image->n * image->bpc + 7)/8;
391 			size_t t_skip = t_margin * stream_stride + l_skip;
392 			size_t b_skip = b_margin * stream_stride + r_skip;
393 			size_t l = fz_skip(ctx, stm, t_skip);
394 			len = 0;
395 			if (l == t_skip)
396 			{
397 				hh = h;
398 				do
399 				{
400 					l = fz_read(ctx, stm, s, stride);
401 					s += l;
402 					len += l;
403 					if (l < stride)
404 						break;
405 					if (--hh == 0)
406 						break;
407 					l = fz_skip(ctx, stm, r_skip + l_skip);
408 					if (l < (size_t)(r_skip + l_skip))
409 						break;
410 				}
411 				while (1);
412 				(void)fz_skip(ctx, stm, r_skip + b_skip);
413 			}
414 		}
415 		else
416 		{
417 			len = fz_read(ctx, stm, samples, h * stride);
418 		}
419 
420 		/* Pad truncated images */
421 		if (len < stride * h)
422 		{
423 			fz_warn(ctx, "padding truncated image");
424 			memset(samples + len, 0, stride * h - len);
425 		}
426 
427 		/* Invert 1-bit image masks */
428 		if (image->imagemask)
429 		{
430 			/* 0=opaque and 1=transparent so we need to invert */
431 			unsigned char *p = samples;
432 			len = h * stride;
433 			for (i = 0; i < len; i++)
434 				p[i] = ~p[i];
435 		}
436 
437 		fz_unpack_tile(ctx, tile, samples, image->n, image->bpc, stride, indexed);
438 
439 		fz_free(ctx, samples);
440 		samples = NULL;
441 
442 		/* color keyed transparency */
443 		if (image->use_colorkey && !image->mask)
444 			fz_mask_color_key(tile, image->n, image->colorkey);
445 
446 		if (indexed)
447 		{
448 			fz_pixmap *conv;
449 			fz_decode_indexed_tile(ctx, tile, image->decode, (1 << image->bpc) - 1);
450 			conv = fz_convert_indexed_pixmap_to_base(ctx, tile);
451 			fz_drop_pixmap(ctx, tile);
452 			tile = conv;
453 		}
454 		else if (image->use_decode)
455 		{
456 			fz_decode_tile(ctx, tile, image->decode);
457 		}
458 
459 		/* pre-blended matte color */
460 		if (matte)
461 			fz_unblend_masked_tile(ctx, tile, image, subarea);
462 	}
463 	fz_catch(ctx)
464 	{
465 		fz_drop_pixmap(ctx, tile);
466 		fz_free(ctx, samples);
467 		fz_rethrow(ctx);
468 	}
469 
470 	return tile;
471 }
472 
473 void
fz_drop_image_base(fz_context * ctx,fz_image * image)474 fz_drop_image_base(fz_context *ctx, fz_image *image)
475 {
476 	fz_drop_colorspace(ctx, image->colorspace);
477 	fz_drop_image(ctx, image->mask);
478 	fz_free(ctx, image);
479 }
480 
481 void
fz_drop_image_imp(fz_context * ctx,fz_storable * image_)482 fz_drop_image_imp(fz_context *ctx, fz_storable *image_)
483 {
484 	fz_image *image = (fz_image *)image_;
485 
486 	image->drop_image(ctx, image);
487 	fz_drop_image_base(ctx, image);
488 }
489 
490 static void
drop_compressed_image(fz_context * ctx,fz_image * image_)491 drop_compressed_image(fz_context *ctx, fz_image *image_)
492 {
493 	fz_compressed_image *image = (fz_compressed_image *)image_;
494 
495 	fz_drop_compressed_buffer(ctx, image->buffer);
496 }
497 
498 static void
drop_pixmap_image(fz_context * ctx,fz_image * image_)499 drop_pixmap_image(fz_context *ctx, fz_image *image_)
500 {
501 	fz_pixmap_image *image = (fz_pixmap_image *)image_;
502 
503 	fz_drop_pixmap(ctx, image->tile);
504 }
505 
506 static fz_pixmap *
compressed_image_get_pixmap(fz_context * ctx,fz_image * image_,fz_irect * subarea,int w,int h,int * l2factor)507 compressed_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
508 {
509 	fz_compressed_image *image = (fz_compressed_image *)image_;
510 	int native_l2factor;
511 	fz_stream *stm;
512 	int indexed;
513 	fz_pixmap *tile;
514 	int can_sub = 0;
515 	int local_l2factor;
516 
517 	/* If we are using matte, then the decode code requires both image and tile sizes
518 	 * to match. The simplest way to ensure this is to do no native l2factor decoding.
519 	 */
520 	if (image->super.use_colorkey && image->super.mask)
521 	{
522 		local_l2factor = 0;
523 		l2factor = &local_l2factor;
524 	}
525 
526 	/* We need to make a new one. */
527 	/* First check for ones that we can't decode using streams */
528 	switch (image->buffer->params.type)
529 	{
530 	case FZ_IMAGE_PNG:
531 		tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
532 		break;
533 	case FZ_IMAGE_GIF:
534 		tile = fz_load_gif(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
535 		break;
536 	case FZ_IMAGE_BMP:
537 		tile = fz_load_bmp(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
538 		break;
539 	case FZ_IMAGE_TIFF:
540 		tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
541 		break;
542 	case FZ_IMAGE_PNM:
543 		tile = fz_load_pnm(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
544 		break;
545 	case FZ_IMAGE_JXR:
546 		tile = fz_load_jxr(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
547 		break;
548 	case FZ_IMAGE_JPX:
549 		tile = fz_load_jpx(ctx, image->buffer->buffer->data, image->buffer->buffer->len, NULL);
550 		break;
551 	case FZ_IMAGE_JPEG:
552 		/* Scan JPEG stream and patch missing height values in header */
553 		{
554 			unsigned char *s = image->buffer->buffer->data;
555 			unsigned char *e = s + image->buffer->buffer->len;
556 			unsigned char *d;
557 			for (d = s + 2; s < d && d < e - 9 && d[0] == 0xFF; d += (d[2] << 8 | d[3]) + 2)
558 			{
559 				if (d[1] < 0xC0 || (0xC3 < d[1] && d[1] < 0xC9) || 0xCB < d[1])
560 					continue;
561 				if ((d[5] == 0 && d[6] == 0) || ((d[5] << 8) | d[6]) > image->super.h)
562 				{
563 					d[5] = (image->super.h >> 8) & 0xFF;
564 					d[6] = image->super.h & 0xFF;
565 				}
566 			}
567 		}
568 		/* fall through */
569 
570 	default:
571 		native_l2factor = l2factor ? *l2factor : 0;
572 		stm = fz_open_image_decomp_stream_from_buffer(ctx, image->buffer, l2factor);
573 		fz_try(ctx)
574 		{
575 			if (l2factor)
576 				native_l2factor -= *l2factor;
577 			indexed = fz_colorspace_is_indexed(ctx, image->super.colorspace);
578 			can_sub = 1;
579 			tile = fz_decomp_image_from_stream(ctx, stm, image, subarea, indexed, native_l2factor);
580 		}
581 		fz_always(ctx)
582 			fz_drop_stream(ctx, stm);
583 		fz_catch(ctx)
584 			fz_rethrow(ctx);
585 
586 		/* CMYK JPEGs in XPS documents have to be inverted */
587 		if (image->super.invert_cmyk_jpeg &&
588 			image->buffer->params.type == FZ_IMAGE_JPEG &&
589 			fz_colorspace_is_cmyk(ctx, image->super.colorspace) &&
590 			image->buffer->params.u.jpeg.color_transform)
591 		{
592 			fz_invert_pixmap(ctx, tile);
593 		}
594 
595 		break;
596 	}
597 
598 	if (can_sub == 0 && subarea != NULL)
599 	{
600 		subarea->x0 = 0;
601 		subarea->y0 = 0;
602 		subarea->x1 = image->super.w;
603 		subarea->y1 = image->super.h;
604 	}
605 
606 	return tile;
607 }
608 
609 static fz_pixmap *
pixmap_image_get_pixmap(fz_context * ctx,fz_image * image_,fz_irect * subarea,int w,int h,int * l2factor)610 pixmap_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
611 {
612 	fz_pixmap_image *image = (fz_pixmap_image *)image_;
613 
614 	/* 'Simple' images created direct from pixmaps will have no buffer
615 	 * of compressed data. We cannot do any better than just returning
616 	 * a pointer to the original 'tile'.
617 	 */
618 	return fz_keep_pixmap(ctx, image->tile); /* That's all we can give you! */
619 }
620 
621 static void
update_ctm_for_subarea(fz_matrix * ctm,const fz_irect * subarea,int w,int h)622 update_ctm_for_subarea(fz_matrix *ctm, const fz_irect *subarea, int w, int h)
623 {
624 	fz_matrix m;
625 
626 	if (subarea->x0 == 0 && subarea->y0 == 0 && subarea->x1 == w && subarea->y1 == h)
627 		return;
628 
629 	m.a = (float) (subarea->x1 - subarea->x0) / w;
630 	m.b = 0;
631 	m.c = 0;
632 	m.d = (float) (subarea->y1 - subarea->y0) / h;
633 	m.e = (float) subarea->x0 / w;
634 	m.f = (float) subarea->y0 / h;
635 	*ctm = fz_concat(m, *ctm);
636 }
637 
fz_default_image_decode(void * arg,int w,int h,int l2factor,fz_irect * subarea)638 void fz_default_image_decode(void *arg, int w, int h, int l2factor, fz_irect *subarea)
639 {
640 	(void)arg;
641 
642 	if ((subarea->x1-subarea->x0)*(subarea->y1-subarea->y0) >= (w*h/10)*9)
643 	{
644 		/* Either no subarea specified, or a subarea 90% or more of the
645 		 * whole area specified. Use the whole image. */
646 		subarea->x0 = 0;
647 		subarea->y0 = 0;
648 		subarea->x1 = w;
649 		subarea->y1 = h;
650 	}
651 	else
652 	{
653 		/* Clip to the edges if they are within 1% */
654 		if (subarea->x0 <= w/100)
655 			subarea->x0 = 0;
656 		if (subarea->y0 <= h/100)
657 			subarea->y0 = 0;
658 		if (subarea->x1 >= w*99/100)
659 			subarea->x1 = w;
660 		if (subarea->y1 >= h*99/100)
661 			subarea->y1 = h;
662 	}
663 }
664 
665 static fz_pixmap *
fz_find_image_tile(fz_context * ctx,fz_image * image,fz_image_key * key,fz_matrix * ctm)666 fz_find_image_tile(fz_context *ctx, fz_image *image, fz_image_key *key, fz_matrix *ctm)
667 {
668 	fz_pixmap *tile;
669 	do
670 	{
671 		tile = fz_find_item(ctx, fz_drop_pixmap_imp, key, &fz_image_store_type);
672 		if (tile)
673 		{
674 			update_ctm_for_subarea(ctm, &key->rect, image->w, image->h);
675 			return tile;
676 		}
677 		key->l2factor--;
678 	}
679 	while (key->l2factor >= 0);
680 	return NULL;
681 }
682 
683 fz_pixmap *
fz_get_pixmap_from_image(fz_context * ctx,fz_image * image,const fz_irect * subarea,fz_matrix * ctm,int * dw,int * dh)684 fz_get_pixmap_from_image(fz_context *ctx, fz_image *image, const fz_irect *subarea, fz_matrix *ctm, int *dw, int *dh)
685 {
686 	fz_pixmap *tile;
687 	int l2factor, l2factor_remaining;
688 	fz_image_key key;
689 	fz_image_key *keyp = NULL;
690 	int w;
691 	int h;
692 
693 	fz_var(keyp);
694 
695 	if (!image)
696 		return NULL;
697 
698 	/* Figure out the extent. */
699 	if (ctm)
700 	{
701 		w = sqrtf(ctm->a * ctm->a + ctm->b * ctm->b);
702 		h = sqrtf(ctm->c * ctm->c + ctm->d * ctm->d);
703 	}
704 	else
705 	{
706 		w = image->w;
707 		h = image->h;
708 	}
709 
710 	if (image->scalable)
711 	{
712 		/* If the image is scalable, we always want to re-render and never cache. */
713 		fz_irect subarea_copy;
714 		if (subarea)
715 			subarea_copy = *subarea;
716 		l2factor_remaining = 0;
717 		if (dw) *dw = w;
718 		if (dh) *dh = h;
719 		return image->get_pixmap(ctx, image, subarea ? &subarea_copy : NULL, image->w, image->h, &l2factor_remaining);
720 	}
721 
722 	/* Clamp requested image size, since we never want to magnify images here. */
723 	if (w > image->w)
724 		w = image->w;
725 	if (h > image->h)
726 		h = image->h;
727 
728 	if (image->decoded)
729 	{
730 		/* If the image is already decoded, then we can't offer a subarea,
731 		 * or l2factor, and we don't want to cache. */
732 		l2factor_remaining = 0;
733 		if (dw) *dw = w;
734 		if (dh) *dh = h;
735 		return image->get_pixmap(ctx, image, NULL, image->w, image->h, &l2factor_remaining);
736 	}
737 
738 	/* What is our ideal factor? We search for the largest factor where
739 	 * we can subdivide and stay larger than the required size. We add
740 	 * a fudge factor of +2 here to allow for the possibility of
741 	 * expansion due to grid fitting. */
742 	l2factor = 0;
743 	if (w > 0 && h > 0)
744 	{
745 		while (image->w>>(l2factor+1) >= w+2 && image->h>>(l2factor+1) >= h+2 && l2factor < 6)
746 			l2factor++;
747 	}
748 
749 	/* First, look through the store for existing tiles */
750 	if (subarea)
751 	{
752 		fz_compute_image_key(ctx, image, ctm, &key, subarea, l2factor, &w, &h, dw, dh);
753 		tile = fz_find_image_tile(ctx, image, &key, ctm);
754 		if (tile)
755 			return tile;
756 	}
757 
758 	/* No subarea given, or no tile for subarea found; try entire image */
759 	fz_compute_image_key(ctx, image, ctm, &key, NULL, l2factor, &w, &h, dw, dh);
760 	tile = fz_find_image_tile(ctx, image, &key, ctm);
761 	if (tile)
762 		return tile;
763 
764 	/* Neither subarea nor full image tile found; prepare the subarea key again */
765 	if (subarea)
766 		fz_compute_image_key(ctx, image, ctm, &key, subarea, l2factor, &w, &h, dw, dh);
767 
768 	/* We'll have to decode the image; request the correct amount of downscaling. */
769 	l2factor_remaining = l2factor;
770 	tile = image->get_pixmap(ctx, image, &key.rect, w, h, &l2factor_remaining);
771 
772 	/* Update the ctm to allow for subareas. */
773 	if (ctm)
774 		update_ctm_for_subarea(ctm, &key.rect, image->w, image->h);
775 
776 	/* l2factor_remaining is updated to the amount of subscaling left to do */
777 	assert(l2factor_remaining >= 0 && l2factor_remaining <= 6);
778 	if (l2factor_remaining)
779 	{
780 		fz_try(ctx)
781 			fz_subsample_pixmap(ctx, tile, l2factor_remaining);
782 		fz_catch(ctx)
783 		{
784 			fz_drop_pixmap(ctx, tile);
785 			fz_rethrow(ctx);
786 		}
787 	}
788 
789 	fz_try(ctx)
790 	{
791 		fz_pixmap *existing_tile;
792 
793 		/* Now we try to cache the pixmap. Any failure here will just result
794 		 * in us not caching. */
795 		keyp = fz_malloc_struct(ctx, fz_image_key);
796 		keyp->refs = 1;
797 		keyp->image = fz_keep_image_store_key(ctx, image);
798 		keyp->l2factor = l2factor;
799 		keyp->rect = key.rect;
800 
801 		existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type);
802 		if (existing_tile)
803 		{
804 			/* We already have a tile. This must have been produced by a
805 			 * racing thread. We'll throw away ours and use that one. */
806 			fz_drop_pixmap(ctx, tile);
807 			tile = existing_tile;
808 		}
809 	}
810 	fz_always(ctx)
811 	{
812 		fz_drop_image_key(ctx, keyp);
813 	}
814 	fz_catch(ctx)
815 	{
816 		/* Do nothing */
817 	}
818 
819 	return tile;
820 }
821 
822 static size_t
pixmap_image_get_size(fz_context * ctx,fz_image * image)823 pixmap_image_get_size(fz_context *ctx, fz_image *image)
824 {
825 	fz_pixmap_image *im = (fz_pixmap_image *)image;
826 
827 	if (image == NULL)
828 		return 0;
829 
830 	return sizeof(fz_pixmap_image) + fz_pixmap_size(ctx, im->tile);
831 }
832 
fz_image_size(fz_context * ctx,fz_image * im)833 size_t fz_image_size(fz_context *ctx, fz_image *im)
834 {
835 	if (im == NULL)
836 		return 0;
837 
838 	return im->get_size(ctx, im);
839 }
840 
841 fz_image *
fz_new_image_from_pixmap(fz_context * ctx,fz_pixmap * pixmap,fz_image * mask)842 fz_new_image_from_pixmap(fz_context *ctx, fz_pixmap *pixmap, fz_image *mask)
843 {
844 	fz_pixmap_image *image;
845 
846 	image = fz_new_derived_image(ctx, pixmap->w, pixmap->h, 8, pixmap->colorspace,
847 				pixmap->xres, pixmap->yres, 0, 0,
848 				NULL, NULL, mask, fz_pixmap_image,
849 				pixmap_image_get_pixmap,
850 				pixmap_image_get_size,
851 				drop_pixmap_image);
852 	image->tile = fz_keep_pixmap(ctx, pixmap);
853 	image->super.decoded = 1;
854 
855 	return &image->super;
856 }
857 
858 fz_image *
fz_new_image_of_size(fz_context * ctx,int w,int h,int bpc,fz_colorspace * colorspace,int xres,int yres,int interpolate,int imagemask,float * decode,int * colorkey,fz_image * mask,size_t size,fz_image_get_pixmap_fn * get_pixmap,fz_image_get_size_fn * get_size,fz_drop_image_fn * drop)859 fz_new_image_of_size(fz_context *ctx, int w, int h, int bpc, fz_colorspace *colorspace,
860 		int xres, int yres, int interpolate, int imagemask, float *decode,
861 		int *colorkey, fz_image *mask, size_t size,
862 		fz_image_get_pixmap_fn *get_pixmap,
863 		fz_image_get_size_fn *get_size,
864 		fz_drop_image_fn *drop)
865 {
866 	fz_image *image;
867 	int i;
868 
869 	assert(mask == NULL || mask->mask == NULL);
870 	assert(size >= sizeof(fz_image));
871 
872 	image = Memento_label(fz_calloc(ctx, 1, size), "fz_image");
873 	FZ_INIT_KEY_STORABLE(image, 1, fz_drop_image_imp);
874 	image->drop_image = drop;
875 	image->get_pixmap = get_pixmap;
876 	image->get_size = get_size;
877 	image->w = w;
878 	image->h = h;
879 	image->xres = xres;
880 	image->yres = yres;
881 	image->bpc = bpc;
882 	image->n = (colorspace ? fz_colorspace_n(ctx, colorspace) : 1);
883 	image->colorspace = fz_keep_colorspace(ctx, colorspace);
884 	image->invert_cmyk_jpeg = 1;
885 	image->interpolate = interpolate;
886 	image->imagemask = imagemask;
887 	image->use_colorkey = (colorkey != NULL);
888 	if (colorkey)
889 		memcpy(image->colorkey, colorkey, sizeof(int)*image->n*2);
890 	image->use_decode = 0;
891 	if (decode)
892 	{
893 		memcpy(image->decode, decode, sizeof(float)*image->n*2);
894 	}
895 	else
896 	{
897 		float maxval = fz_colorspace_is_indexed(ctx, colorspace) ? (1 << bpc) - 1 : 1;
898 		for (i = 0; i < image->n; i++)
899 		{
900 			image->decode[2*i] = 0;
901 			image->decode[2*i+1] = maxval;
902 		}
903 	}
904 	/* ICC spaces have the default decode arrays pickled into them.
905 	 * For most spaces this is fine, because [ 0 1 0 1 0 1 ] is
906 	 * idempotent. For Lab, however, we need to adjust it. */
907 	if (fz_colorspace_is_lab_icc(ctx, colorspace))
908 	{
909 		/* Undo the default decode array of [0 100 -128 127 -128 127] */
910 		image->decode[0] = image->decode[0]/100.0f;
911 		image->decode[1] = image->decode[1]/100.0f;
912 		image->decode[2] = (image->decode[2]+128)/255.0f;
913 		image->decode[3] = (image->decode[3]+128)/255.0f;
914 		image->decode[4] = (image->decode[4]+128)/255.0f;
915 		image->decode[5] = (image->decode[5]+128)/255.0f;
916 	}
917 	for (i = 0; i < image->n; i++)
918 	{
919 		if (image->decode[i * 2] != 0 || image->decode[i * 2 + 1] != 1)
920 			break;
921 	}
922 	if (i != image->n)
923 		image->use_decode = 1;
924 	image->mask = fz_keep_image(ctx, mask);
925 
926 	return image;
927 }
928 
929 static size_t
compressed_image_get_size(fz_context * ctx,fz_image * image)930 compressed_image_get_size(fz_context *ctx, fz_image *image)
931 {
932 	fz_compressed_image *im = (fz_compressed_image *)image;
933 
934 	if (image == NULL)
935 		return 0;
936 
937 	return sizeof(fz_pixmap_image) + (im->buffer && im->buffer->buffer ? im->buffer->buffer->cap : 0);
938 }
939 
940 fz_image *
fz_new_image_from_compressed_buffer(fz_context * ctx,int w,int h,int bpc,fz_colorspace * colorspace,int xres,int yres,int interpolate,int imagemask,float * decode,int * colorkey,fz_compressed_buffer * buffer,fz_image * mask)941 fz_new_image_from_compressed_buffer(fz_context *ctx, int w, int h,
942 	int bpc, fz_colorspace *colorspace,
943 	int xres, int yres, int interpolate, int imagemask, float *decode,
944 	int *colorkey, fz_compressed_buffer *buffer, fz_image *mask)
945 {
946 	fz_compressed_image *image;
947 
948 	fz_try(ctx)
949 	{
950 		image = fz_new_derived_image(ctx, w, h, bpc,
951 					colorspace, xres, yres,
952 					interpolate, imagemask, decode,
953 					colorkey, mask, fz_compressed_image,
954 					compressed_image_get_pixmap,
955 					compressed_image_get_size,
956 					drop_compressed_image);
957 		image->buffer = buffer;
958 	}
959 	fz_catch(ctx)
960 	{
961 		fz_drop_compressed_buffer(ctx, buffer);
962 		fz_rethrow(ctx);
963 	}
964 
965 	return &image->super;
966 }
967 
fz_compressed_image_buffer(fz_context * ctx,fz_image * image)968 fz_compressed_buffer *fz_compressed_image_buffer(fz_context *ctx, fz_image *image)
969 {
970 	if (image == NULL || image->get_pixmap != compressed_image_get_pixmap)
971 		return NULL;
972 	return ((fz_compressed_image *)image)->buffer;
973 }
974 
fz_set_compressed_image_buffer(fz_context * ctx,fz_compressed_image * image,fz_compressed_buffer * buf)975 void fz_set_compressed_image_buffer(fz_context *ctx, fz_compressed_image *image, fz_compressed_buffer *buf)
976 {
977 	assert(image != NULL && image->super.get_pixmap == compressed_image_get_pixmap);
978 	((fz_compressed_image *)image)->buffer = buf; /* Note: compressed buffers are not reference counted */
979 }
980 
fz_pixmap_image_tile(fz_context * ctx,fz_pixmap_image * image)981 fz_pixmap *fz_pixmap_image_tile(fz_context *ctx, fz_pixmap_image *image)
982 {
983 	if (image == NULL || image->super.get_pixmap != pixmap_image_get_pixmap)
984 		return NULL;
985 	return ((fz_pixmap_image *)image)->tile;
986 }
987 
fz_set_pixmap_image_tile(fz_context * ctx,fz_pixmap_image * image,fz_pixmap * pix)988 void fz_set_pixmap_image_tile(fz_context *ctx, fz_pixmap_image *image, fz_pixmap *pix)
989 {
990 	assert(image != NULL && image->super.get_pixmap == pixmap_image_get_pixmap);
991 	((fz_pixmap_image *)image)->tile = pix;
992 }
993 
994 int
fz_recognize_image_format(fz_context * ctx,unsigned char p[8])995 fz_recognize_image_format(fz_context *ctx, unsigned char p[8])
996 {
997 	if (p[0] == 'P' && p[1] >= '1' && p[1] <= '7')
998 		return FZ_IMAGE_PNM;
999 	if (p[0] == 0xff && p[1] == 0x4f)
1000 		return FZ_IMAGE_JPX;
1001 	if (p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x00 && p[3] == 0x0c &&
1002 			p[4] == 0x6a && p[5] == 0x50 && p[6] == 0x20 && p[7] == 0x20)
1003 		return FZ_IMAGE_JPX;
1004 	if (p[0] == 0xff && p[1] == 0xd8)
1005 		return FZ_IMAGE_JPEG;
1006 	if (p[0] == 137 && p[1] == 80 && p[2] == 78 && p[3] == 71 &&
1007 			p[4] == 13 && p[5] == 10 && p[6] == 26 && p[7] == 10)
1008 		return FZ_IMAGE_PNG;
1009 	if (p[0] == 'I' && p[1] == 'I' && p[2] == 0xBC)
1010 		return FZ_IMAGE_JXR;
1011 	if (p[0] == 'I' && p[1] == 'I' && p[2] == 42 && p[3] == 0)
1012 		return FZ_IMAGE_TIFF;
1013 	if (p[0] == 'M' && p[1] == 'M' && p[2] == 0 && p[3] == 42)
1014 		return FZ_IMAGE_TIFF;
1015 	if (p[0] == 'G' && p[1] == 'I' && p[2] == 'F')
1016 		return FZ_IMAGE_GIF;
1017 	if (p[0] == 'B' && p[1] == 'M')
1018 		return FZ_IMAGE_BMP;
1019 	if (p[0] == 'B' && p[1] == 'A')
1020 		return FZ_IMAGE_BMP;
1021 	if (p[0] == 0x97 && p[1] == 'J' && p[2] == 'B' && p[3] == '2' &&
1022 		p[4] == '\r' && p[5] == '\n'  && p[6] == 0x1a && p[7] == '\n')
1023 		return FZ_IMAGE_JBIG2;
1024 	return FZ_IMAGE_UNKNOWN;
1025 }
1026 
1027 fz_image *
fz_new_image_from_buffer(fz_context * ctx,fz_buffer * buffer)1028 fz_new_image_from_buffer(fz_context *ctx, fz_buffer *buffer)
1029 {
1030 	fz_compressed_buffer *bc;
1031 	int w, h, xres, yres;
1032 	fz_colorspace *cspace;
1033 	size_t len = buffer->len;
1034 	unsigned char *buf = buffer->data;
1035 	fz_image *image = NULL;
1036 	int type;
1037 	int bpc;
1038 
1039 	if (len < 8)
1040 		fz_throw(ctx, FZ_ERROR_GENERIC, "unknown image file format");
1041 
1042 	type = fz_recognize_image_format(ctx, buf);
1043 	bpc = 8;
1044 	switch (type)
1045 	{
1046 	case FZ_IMAGE_PNM:
1047 		fz_load_pnm_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1048 		break;
1049 	case FZ_IMAGE_JPX:
1050 		fz_load_jpx_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1051 		break;
1052 	case FZ_IMAGE_JPEG:
1053 		fz_load_jpeg_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1054 		break;
1055 	case FZ_IMAGE_PNG:
1056 		fz_load_png_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1057 		break;
1058 	case FZ_IMAGE_JXR:
1059 		fz_load_jxr_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1060 		break;
1061 	case FZ_IMAGE_TIFF:
1062 		fz_load_tiff_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1063 		break;
1064 	case FZ_IMAGE_GIF:
1065 		fz_load_gif_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1066 		break;
1067 	case FZ_IMAGE_BMP:
1068 		fz_load_bmp_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1069 		break;
1070 	case FZ_IMAGE_JBIG2:
1071 		fz_load_jbig2_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
1072 		bpc = 1;
1073 		break;
1074 	default:
1075 		fz_throw(ctx, FZ_ERROR_GENERIC, "unknown image file format");
1076 	}
1077 
1078 	fz_try(ctx)
1079 	{
1080 		bc = fz_malloc_struct(ctx, fz_compressed_buffer);
1081 		bc->buffer = fz_keep_buffer(ctx, buffer);
1082 		bc->params.type = type;
1083 		if (type == FZ_IMAGE_JPEG)
1084 			bc->params.u.jpeg.color_transform = -1;
1085 		image = fz_new_image_from_compressed_buffer(ctx, w, h, bpc, cspace, xres, yres, 0, 0, NULL, NULL, bc, NULL);
1086 	}
1087 	fz_always(ctx)
1088 		fz_drop_colorspace(ctx, cspace);
1089 	fz_catch(ctx)
1090 		fz_rethrow(ctx);
1091 
1092 	return image;
1093 }
1094 
1095 fz_image *
fz_new_image_from_file(fz_context * ctx,const char * path)1096 fz_new_image_from_file(fz_context *ctx, const char *path)
1097 {
1098 	fz_buffer *buffer;
1099 	fz_image *image = NULL;
1100 
1101 	buffer = fz_read_file(ctx, path);
1102 	fz_try(ctx)
1103 		image = fz_new_image_from_buffer(ctx, buffer);
1104 	fz_always(ctx)
1105 		fz_drop_buffer(ctx, buffer);
1106 	fz_catch(ctx)
1107 		fz_rethrow(ctx);
1108 
1109 	return image;
1110 }
1111 
1112 void
fz_image_resolution(fz_image * image,int * xres,int * yres)1113 fz_image_resolution(fz_image *image, int *xres, int *yres)
1114 {
1115 	*xres = image->xres;
1116 	*yres = image->yres;
1117 	if (*xres < 0 || *yres < 0 || (*xres == 0 && *yres == 0))
1118 	{
1119 		/* If neither xres or yres is sane, pick a sane value */
1120 		*xres = SANE_DPI; *yres = SANE_DPI;
1121 	}
1122 	else if (*xres == 0)
1123 	{
1124 		*xres = *yres;
1125 	}
1126 	else if (*yres == 0)
1127 	{
1128 		*yres = *xres;
1129 	}
1130 
1131 	/* Scale xres and yres up until we get believable values */
1132 	if (*xres < SANE_DPI || *yres < SANE_DPI || *xres > INSANE_DPI || *yres > INSANE_DPI)
1133 	{
1134 		if (*xres < *yres)
1135 		{
1136 			*yres = *yres * SANE_DPI / *xres;
1137 			*xres = SANE_DPI;
1138 		}
1139 		else
1140 		{
1141 			*xres = *xres * SANE_DPI / *yres;
1142 			*yres = SANE_DPI;
1143 		}
1144 
1145 		if (*xres == *yres || *xres < SANE_DPI || *yres < SANE_DPI || *xres > INSANE_DPI || *yres > INSANE_DPI)
1146 		{
1147 			*xres = SANE_DPI;
1148 			*yres = SANE_DPI;
1149 		}
1150 	}
1151 }
1152 
1153 typedef struct fz_display_list_image_s
1154 {
1155 	fz_image super;
1156 	fz_matrix transform;
1157 	fz_display_list *list;
1158 } fz_display_list_image;
1159 
1160 static fz_pixmap *
display_list_image_get_pixmap(fz_context * ctx,fz_image * image_,fz_irect * subarea,int w,int h,int * l2factor)1161 display_list_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subarea, int w, int h, int *l2factor)
1162 {
1163 	fz_display_list_image *image = (fz_display_list_image *)image_;
1164 	fz_matrix ctm;
1165 	fz_device *dev;
1166 	fz_pixmap *pix;
1167 
1168 	fz_var(dev);
1169 
1170 	if (subarea)
1171 	{
1172 		/* So, the whole image should be scaled to w * h, but we only want the
1173 		 * given subarea of it. */
1174 		int l = (subarea->x0 * w) / image->super.w;
1175 		int t = (subarea->y0 * h) / image->super.h;
1176 		int r = (subarea->x1 * w + image->super.w - 1) / image->super.w;
1177 		int b = (subarea->y1 * h + image->super.h - 1) / image->super.h;
1178 
1179 		pix = fz_new_pixmap(ctx, image->super.colorspace, r-l, b-t, NULL, 0);
1180 		pix->x = l;
1181 		pix->y = t;
1182 	}
1183 	else
1184 	{
1185 		pix = fz_new_pixmap(ctx, image->super.colorspace, w, h, NULL, 0);
1186 	}
1187 
1188 	/* If we render the display list into pix with the image matrix, we'll get a unit
1189 	 * square result. Therefore scale by w, h. */
1190 	ctm = fz_pre_scale(image->transform, w, h);
1191 
1192 	fz_clear_pixmap(ctx, pix); /* clear to transparent */
1193 	fz_try(ctx)
1194 	{
1195 		dev = fz_new_draw_device(ctx, ctm, pix);
1196 		fz_run_display_list(ctx, image->list, dev, fz_identity, fz_infinite_rect, NULL);
1197 		fz_close_device(ctx, dev);
1198 	}
1199 	fz_always(ctx)
1200 		fz_drop_device(ctx, dev);
1201 	fz_catch(ctx)
1202 	{
1203 		fz_drop_pixmap(ctx, pix);
1204 		fz_rethrow(ctx);
1205 	}
1206 
1207 	/* Never do more subsampling, cos we've already given them the right size */
1208 	if (l2factor)
1209 		*l2factor = 0;
1210 
1211 	return pix;
1212 }
1213 
drop_display_list_image(fz_context * ctx,fz_image * image_)1214 static void drop_display_list_image(fz_context *ctx, fz_image *image_)
1215 {
1216 	fz_display_list_image *image = (fz_display_list_image *)image_;
1217 
1218 	if (image == NULL)
1219 		return;
1220 	fz_drop_display_list(ctx, image->list);
1221 }
1222 
1223 static size_t
display_list_image_get_size(fz_context * ctx,fz_image * image_)1224 display_list_image_get_size(fz_context *ctx, fz_image *image_)
1225 {
1226 	fz_display_list_image *image = (fz_display_list_image *)image_;
1227 
1228 	if (image == NULL)
1229 		return 0;
1230 
1231 	return sizeof(fz_display_list_image) + 4096; /* FIXME */
1232 }
1233 
fz_new_image_from_display_list(fz_context * ctx,float w,float h,fz_display_list * list)1234 fz_image *fz_new_image_from_display_list(fz_context *ctx, float w, float h, fz_display_list *list)
1235 {
1236 	fz_display_list_image *image;
1237 	int iw, ih;
1238 
1239 	iw = w * SCALABLE_IMAGE_DPI / 72;
1240 	ih = h * SCALABLE_IMAGE_DPI / 72;
1241 
1242 	image = fz_new_derived_image(ctx, iw, ih, 8, fz_device_rgb(ctx),
1243 				SCALABLE_IMAGE_DPI, SCALABLE_IMAGE_DPI, 0, 0,
1244 				NULL, NULL, NULL, fz_display_list_image,
1245 				display_list_image_get_pixmap,
1246 				display_list_image_get_size,
1247 				drop_display_list_image);
1248 	image->super.scalable = 1;
1249 	image->transform = fz_scale(1 / w, 1 / h);
1250 	image->list = fz_keep_display_list(ctx, list);
1251 
1252 	return &image->super;
1253 }
1254