~noskcaj/ubuntu/trusty/gdk-pixbuf/2.30.6

1.1.1 by Sebastien Bacher
Import upstream version 2.21.6
1
/*
2
 * GdkPixbuf library - PCX image loader
3
 *
4
 * Copyright (C) 2003 Josh A. Beam
5
 *
6
 * Authors: Josh A. Beam <josh@joshbeam.com>
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Library General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Library General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Library General Public
19
 * License along with this library; if not, write to the
20
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21
 * Boston, MA 02111-1307, USA.
22
 */
23
24
#include "config.h"
25
#include <stdio.h>
26
#include <string.h>
27
#include "gdk-pixbuf-private.h"
28
29
#undef PCX_DEBUG
30
31
#define PCX_TASK_DONE 0
32
#define PCX_TASK_LOAD_HEADER 1
33
#define PCX_TASK_LOAD_DATA 2
34
#define PCX_TASK_LOAD_PALETTE 3
35
36
struct pcx_header {
37
	guint8 manufacturer;
38
	guint8 version;
39
	guint8 encoding;
40
	guint8 bitsperpixel;
41
	gint16 xmin;
42
	gint16 ymin;
43
	gint16 xmax;
44
	gint16 ymax;
45
	guint16 horizdpi;
46
	guint16 vertdpi;
47
	guint8 palette[48];
48
	guint8 reserved;
49
	guint8 colorplanes;
50
	guint16 bytesperline;
51
	guint16 palettetype;
52
	guint16 hscrsize;
53
	guint16 vscrsize;
54
	guint8 filler[54];
55
};
56
57
struct pcx_context {
58
	GdkPixbuf *pixbuf;
59
	gint rowstride;
60
61
	GdkPixbufModuleSizeFunc size_func;
62
	GdkPixbufModuleUpdatedFunc updated_func;
63
	GdkPixbufModulePreparedFunc prepared_func;
64
	gpointer user_data;
65
66
	guchar current_task;
67
68
	gboolean header_loaded;
69
	struct pcx_header *header;
70
	guint bpp;
71
	gint width, height;
72
	guint num_planes;
73
	guint bytesperline;
74
75
	guchar *buf;
76
	guint buf_size;
77
	guint buf_pos;
78
	guchar *data;
79
	guchar *line;
80
	guint current_line;
81
	guchar *p_data;
82
};
83
84
/*
85
 * set context's image information based on the header
86
 */
87
static void
88
fill_pcx_context(struct pcx_context *context)
89
{
90
	struct pcx_header *header = context->header;
91
92
	context->bpp = header->bitsperpixel;
93
	context->width = header->xmax - header->xmin + 1;
94
	context->height = header->ymax - header->ymin + 1;
95
	context->num_planes = header->colorplanes;
96
	context->bytesperline = header->bytesperline;
97
98
	if(header->version == 5 && context->bpp == 8 && context->num_planes == 3)
99
		context->bpp = 24;
100
}
101
102
static void
103
free_pcx_context(struct pcx_context *context, gboolean unref_pixbuf)
104
{
105
	g_free(context->header);
106
	g_free(context->buf);
107
	if(unref_pixbuf && context->pixbuf)
108
		g_object_unref(context->pixbuf);
109
	g_free(context->line);
110
	g_free(context->p_data);
111
112
	g_free(context);
113
}
114
115
/*
116
 * read each plane of a single scanline. store_planes is
117
 * the number of planes that can be stored in the planes array.
118
 * data is the pointer to the block of memory to read
119
 * from, size is the length of that data, and line_bytes
120
 * is where the number of bytes read will be stored.
121
 */
122
static gboolean
123
read_scanline_data(guchar *data, guint size, guchar *planes[],
124
                   guint store_planes, guint num_planes, guint bytesperline,
125
                   guint *line_bytes)
126
{
127
	guint i, j;
128
	guint p, count;
129
	guint d = 0;
130
	guint8 byte;
131
132
	for(p = 0; p < num_planes; p++) {
133
		for(i = 0; i < bytesperline;) { /* i incremented when line byte set */
134
			if(d >= size)
135
				return FALSE;
136
			byte = data[d++];
137
138
			if(byte >> 6 == 0x3) {
139
				count = byte & ~(0x3 << 6);
140
				if(count == 0)
141
					return FALSE;
142
				if(d >= size)
143
					return FALSE;
144
				byte = data[d++];
145
			} else {
146
				count = 1;
147
			}
148
149
			for(j = 0; j < count; j++) {
150
				if(p < store_planes)
151
					planes[p][i++] = byte;
152
				else
153
					i++;
154
155
				if(i >= bytesperline) {
156
					p++;
157
					if(p >= num_planes) {
158
						*line_bytes = d;
159
						return TRUE;
160
					}
161
					i = 0;
162
				}
163
			}
164
		}
165
	}
166
167
	*line_bytes = d; /* number of bytes read for scanline */
168
	return TRUE;
169
}
170
171
static gpointer
172
gdk_pixbuf__pcx_begin_load(GdkPixbufModuleSizeFunc size_func,
173
                           GdkPixbufModulePreparedFunc prepared_func,
174
                           GdkPixbufModuleUpdatedFunc updated_func,
175
                           gpointer user_data, GError **error)
176
{
177
	struct pcx_context *context;
178
179
	context = g_new0(struct pcx_context, 1);
180
	if(!context)
181
		return NULL;
182
183
	context->header = g_try_malloc(sizeof(struct pcx_header));
184
	if(!context->header) {
185
		g_free(context);
186
		g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Couldn't allocate memory for header"));
187
		return NULL;
188
	}
189
190
	context->size_func = size_func;
191
	context->updated_func = updated_func;
192
	context->prepared_func = prepared_func;
193
	context->user_data = user_data;
194
195
	context->current_task = PCX_TASK_LOAD_HEADER;
196
197
	context->buf = g_try_malloc(sizeof(guchar) * 512);
198
	if(!context->buf) {
199
		g_free(context->header);
200
		g_free(context);
201
		g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Couldn't allocate memory for context buffer"));
202
		return NULL;
203
	}
204
	context->buf_size = 512;
205
206
	context->header_loaded = FALSE;
207
208
	return context;
209
}
210
211
static gboolean
212
pcx_resize_context_buf(struct pcx_context *context, guint size)
213
{
214
	guchar *new_buf;
215
216
	new_buf = g_try_realloc(context->buf, size);
217
	if(!new_buf)
218
		return FALSE;
219
220
	context->buf = new_buf;
221
	context->buf_size = size;
222
	return TRUE;
223
}
224
225
/*
226
 * remove a number of bytes (specified by size) from the
227
 * beginning of a context's buf
228
 */
229
static gboolean
230
pcx_chop_context_buf(struct pcx_context *context, guint size)
231
{
232
	guint i, j;
233
234
	if (size > context->buf_pos)
235
		return FALSE;
236
	else if (size == 0)
237
		return TRUE;
238
239
	for (i = 0, j = size; j < context->buf_pos; i++, j++)
240
		context->buf[i] = context->buf[j];
241
242
	context->buf_pos -= size;
243
244
	return TRUE;
245
}
246
247
static guchar
248
read_pixel_1(guchar *data, guint offset)
249
{
250
	guchar retval;
251
	guint bit_offset;
252
253
	if(!(offset % 8)) {
254
		offset /= 8;
255
		retval = data[offset] >> 7;
256
	} else {
257
		bit_offset = offset % 8;
258
		offset -= bit_offset;
259
		offset /= 8;
260
		retval = (data[offset] >> (7 - bit_offset)) & 0x1;
261
	}
262
263
	return retval;
264
}
265
266
static guchar
267
read_pixel_4(guchar *data, guint offset)
268
{
269
	guchar retval;
270
271
	if(!(offset % 2)) {
272
		offset /= 2;
273
		retval = data[offset] >> 4;
274
	} else {
275
		offset--;
276
		offset /= 2;
277
		retval = data[offset] & 0xf;
278
	}
279
280
	return retval;
281
}
282
283
static gboolean
284
pcx_increment_load_data_1(struct pcx_context *context)
285
{
286
	guint i;
287
	guchar *planes[4];
288
	guint line_bytes;
289
	guint store_planes;
290
291
	if(context->num_planes == 4) {
292
		planes[0] = context->line;
293
		planes[1] = planes[0] + context->bytesperline;
294
		planes[2] = planes[1] + context->bytesperline;
295
		planes[3] = planes[2] + context->bytesperline;
296
		store_planes = 4;
297
	} else if(context->num_planes == 3) {
298
		planes[0] = context->line;
299
		planes[1] = planes[0] + context->bytesperline;
300
		planes[2] = planes[1] + context->bytesperline;
301
		store_planes = 3;
302
	} else if(context->num_planes == 2) {
303
		planes[0] = context->line;
304
		planes[1] = planes[0] + context->bytesperline;
305
		store_planes = 2;
306
	} else if(context->num_planes == 1) {
307
		planes[0] = context->line;
308
		store_planes = 1;
309
	} else {
310
		return FALSE;
311
	}
312
313
	while(read_scanline_data(context->buf, context->buf_pos, planes, store_planes, context->num_planes, context->bytesperline, &line_bytes)) {
314
		pcx_chop_context_buf(context, line_bytes);
315
316
		for(i = 0; i < context->width; i++) {
317
			guchar p;
318
319
			if(context->num_planes == 4) {
320
				p = read_pixel_1(planes[3], i);
321
				p <<= 1;
322
				p |= read_pixel_1(planes[2], i);
323
				p <<= 1;
324
				p |= read_pixel_1(planes[1], i);
325
				p <<= 1;
326
				p |= read_pixel_1(planes[0], i);
327
			} else if(context->num_planes == 3) {
328
				p = read_pixel_1(planes[2], i);
329
				p <<= 1;
330
				p |= read_pixel_1(planes[1], i);
331
				p <<= 1;
332
				p |= read_pixel_1(planes[0], i);
333
			} else if(context->num_planes == 2) {
334
				p = read_pixel_1(planes[1], i);
335
				p <<= 1;
336
				p |= read_pixel_1(planes[0], i);
337
			} else if(context->num_planes == 1) {
338
				p = read_pixel_1(planes[0], i);
339
			} else {
340
				return FALSE;
341
			}
342
			p &= 0xf;
343
			context->data[context->current_line * context->rowstride + i * 3 + 0] = context->header->palette[p * 3 + 0];
344
			context->data[context->current_line * context->rowstride + i * 3 + 1] = context->header->palette[p * 3 + 1];
345
			context->data[context->current_line * context->rowstride + i * 3 + 2] = context->header->palette[p * 3 + 2];
346
		}
347
348
		if(context->updated_func)
349
			context->updated_func(context->pixbuf, 0, context->current_line, context->width, 1, context->user_data);
350
351
		context->current_line++;
352
353
		if(context->current_line == context->height) {
354
			context->current_task = PCX_TASK_DONE;
355
			return TRUE;
356
		}
357
	}
358
359
	return TRUE;
360
}
361
362
static gboolean
363
pcx_increment_load_data_2(struct pcx_context *context)
364
{
365
	guint i;
366
	guchar *planes[1];
367
	guint line_bytes;
368
	guint shift, h;
369
370
	planes[0] = context->line;
371
372
	while(read_scanline_data(context->buf, context->buf_pos, planes, 1, context->num_planes, context->bytesperline, &line_bytes)) {
373
		pcx_chop_context_buf(context, line_bytes);
374
375
		for(i = 0; i < context->width; i++) {
376
			shift = 6 - 2 * (i % 4);
377
			h = (planes[0][i / 4] >> shift) & 0x3;
378
			context->data[context->current_line * context->rowstride + i * 3 + 0] = context->header->palette[h * 3 + 0];
379
			context->data[context->current_line * context->rowstride + i * 3 + 1] = context->header->palette[h * 3 + 1];
380
			context->data[context->current_line * context->rowstride + i * 3 + 2] = context->header->palette[h * 3 + 2];
381
		}
382
383
		if(context->updated_func)
384
			context->updated_func(context->pixbuf, 0, context->current_line, context->width, 1, context->user_data);
385
386
		context->current_line++;
387
388
		if(context->current_line == context->height) {
389
			context->current_task = PCX_TASK_DONE;
390
			return TRUE;
391
		}
392
	}
393
394
	return TRUE;
395
}
396
397
static gboolean
398
pcx_increment_load_data_4(struct pcx_context *context)
399
{
400
	guint i;
401
	guchar *planes[1];
402
	guint line_bytes;
403
404
	planes[0] = context->line;
405
406
	while(read_scanline_data(context->buf, context->buf_pos, planes, 1, context->num_planes, context->bytesperline, &line_bytes)) {
407
		pcx_chop_context_buf(context, line_bytes);
408
409
		for(i = 0; i < context->width; i++) {
410
			guchar p;
411
412
			p = read_pixel_4(planes[0], i) & 0xf;
413
			context->data[context->current_line * context->rowstride + i * 3 + 0] = context->header->palette[p * 3 + 0];
414
			context->data[context->current_line * context->rowstride + i * 3 + 1] = context->header->palette[p * 3 + 1];
415
			context->data[context->current_line * context->rowstride + i * 3 + 2] = context->header->palette[p * 3 + 2];
416
		}
417
418
		if(context->updated_func)
419
			context->updated_func(context->pixbuf, 0, context->current_line, context->width, 1, context->user_data);
420
421
		context->current_line++;
422
423
		if(context->current_line == context->height) {
424
			context->current_task = PCX_TASK_DONE;
425
			return TRUE;
426
		}
427
	}
428
429
	return TRUE;
430
}
431
432
/*
433
 * for loading 8-bit pcx images, we keep a buffer containing
434
 * each pixel's palette number; once we've loaded each scanline,
435
 * we wait for loading to stop and call pcx_load_palette_8,
436
 * which finds the palette at the end of the pcx data and sets the
437
 * RGB data.
438
 */
439
static gboolean
440
pcx_increment_load_data_8(struct pcx_context *context)
441
{
442
	guint i;
443
	guchar *planes[1];
444
	guint line_bytes;
445
446
	planes[0] = context->line;
447
448
	while(read_scanline_data(context->buf, context->buf_pos, planes, 1, context->num_planes, context->bytesperline, &line_bytes)) {
449
		pcx_chop_context_buf(context, line_bytes);
450
451
		for(i = 0; i < context->width; i++)
452
			context->p_data[context->current_line * context->width + i + 0] = planes[0][i];
453
454
		context->current_line++;
455
456
		if(context->current_line == context->height) {
457
			context->current_task = PCX_TASK_LOAD_PALETTE;
458
			return TRUE;
459
		}
460
	}
461
462
	return TRUE;
463
}
464
465
/*
466
 * read the palette and set the RGB data
467
 */
468
static gboolean
469
pcx_load_palette_8(struct pcx_context *context)
470
{
471
	guint i, j;
472
473
	if(context->current_line < context->height)
474
		return FALSE;
475
476
	if(context->buf_pos >= 769) {
477
		guchar *palette = context->buf + (context->buf_pos - 769);
478
479
		if(palette[0] == 12) {
480
			palette++;
481
			for(i = 0; i < context->height; i++) {
482
				for(j = 0; j < context->width; j++) {
483
					context->data[i * context->rowstride + j * 3 + 0] = palette[(context->p_data[i * context->width + j]) * 3 + 0];
484
					context->data[i * context->rowstride + j * 3 + 1] = palette[(context->p_data[i * context->width + j]) * 3 + 1];
485
					context->data[i * context->rowstride + j * 3 + 2] = palette[(context->p_data[i * context->width + j]) * 3 + 2];
486
				}
487
488
				if(context->updated_func)
489
					context->updated_func(context->pixbuf, 0, i, context->width, 1, context->user_data);
490
			}
491
492
#ifdef PCX_DEBUG
493
			g_print("read palette\n");
494
#endif
495
496
			context->current_task = PCX_TASK_DONE;
497
			return TRUE;
498
		} else {
499
#ifdef PCX_DEBUG
500
			g_print("this ain't a palette\n");
501
#endif
502
			return FALSE;
503
		}
504
	}
505
506
	return FALSE;
507
}
508
509
/*
510
 * in 24-bit images, each scanline has three color planes
511
 * for red, green, and blue, respectively.
512
 */
513
static gboolean
514
pcx_increment_load_data_24(struct pcx_context *context)
515
{
516
	guint i;
517
	guchar *planes[3];
518
	guint line_bytes;
519
520
	planes[0] = context->line;
521
	planes[1] = planes[0] + context->bytesperline;
522
	planes[2] = planes[1] + context->bytesperline;
523
524
	while(read_scanline_data(context->buf, context->buf_pos, planes, 3, context->num_planes, context->bytesperline, &line_bytes)) {
525
		pcx_chop_context_buf(context, line_bytes);
526
527
		for(i = 0; i < context->width; i++) {
528
			context->data[context->current_line * context->rowstride + i * 3 + 0] = planes[0][i];
529
			context->data[context->current_line * context->rowstride + i * 3 + 1] = planes[1][i];
530
			context->data[context->current_line * context->rowstride + i * 3 + 2] = planes[2][i];
531
		}
532
533
		if(context->updated_func)
534
			context->updated_func(context->pixbuf, 0, context->current_line, context->width, 1, context->user_data);
535
536
		context->current_line++;
537
538
		if(context->current_line == context->height) {
539
			context->current_task = PCX_TASK_DONE;
540
			return TRUE;
541
		}
542
	}
543
544
	return TRUE;
545
}
546
547
static gboolean
548
gdk_pixbuf__pcx_load_increment(gpointer data, const guchar *buf, guint size,
549
                               GError **error)
550
{
551
	struct pcx_context *context = (struct pcx_context *)data;
552
	struct pcx_header *header;
553
	guint i;
554
	gboolean retval = TRUE;
555
556
	/* if context's buf isn't large enough to hold its current data plus the passed buf, increase its size */
557
	if(context->buf_pos + size > context->buf_size) {
558
		if(!pcx_resize_context_buf(context, sizeof(guchar) * (context->buf_pos + size))) {
559
			g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Couldn't allocate memory for context buffer"));
560
			return FALSE;
561
		}
562
	}
563
564
	for(i = 0; i < size; i++)
565
		context->buf[context->buf_pos++] = buf[i];
566
567
	if(context->current_task == PCX_TASK_LOAD_HEADER) {
568
		if(!context->header_loaded && context->buf_pos > sizeof(struct pcx_header)) { /* set header */
569
			gint width, height;
570
571
			memcpy(context->header, context->buf, sizeof(struct pcx_header));
572
			pcx_chop_context_buf(context, sizeof(struct pcx_header));
573
			header = context->header;
574
575
			/* convert the multi-byte header variables that will be used */
576
			header->xmin = GINT16_FROM_LE(header->xmin);
577
			header->ymin = GINT16_FROM_LE(header->ymin);
578
			header->xmax = GINT16_FROM_LE(header->xmax);
579
			header->ymax = GINT16_FROM_LE(header->ymax);
580
			header->bytesperline = GUINT16_FROM_LE(header->bytesperline);
581
582
#ifdef PCX_DEBUG
583
			g_print ("Manufacturer %d\n"
584
			         "Version %d\n"
585
			         "Encoding %d\n"
586
				 "Bits/Pixel %d\n"
587
				 "Planes %d\n"
588
				 "Palette %d\n", 
589
				 header->manufacturer, header->version, 
590
				 header->encoding, header->bitsperpixel,
591
				 header->colorplanes, header->palettetype);
592
#endif
593
594
			context->header_loaded = TRUE;
595
			fill_pcx_context(context);
596
597
			width = context->width;
598
			height = context->height;
599
			if(width <= 0 || height <= 0) {
600
				g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Image has invalid width and/or height"));
601
				return FALSE;
602
			}
603
			if (context->size_func)
604
			  {
605
			    (*context->size_func) (&width, &height, context->user_data);
606
			    if (width == 0 || height == 0)
607
			      return TRUE;
608
			  }
609
610
			switch(context->bpp) {
611
				default:
612
					g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_UNKNOWN_TYPE, _("Image has unsupported bpp"));
613
					return FALSE;
614
					break;
615
				case 1:
616
					if(context->num_planes < 1 || context->num_planes > 4) {
617
						g_set_error(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_UNKNOWN_TYPE, _("Image has unsupported number of %d-bit planes"), 1);
618
						return FALSE;
619
					}
620
					break;
621
				case 2:
622
				case 4:
623
				case 8:
624
					if(context->num_planes != 1) {
625
					  g_set_error(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_UNKNOWN_TYPE, _("Image has unsupported number of %d-bit planes"), (gint)context->bpp);
626
						return FALSE;
627
					}
628
					break;
629
				case 24:
630
					break; /* context's bpp is set to 24 if there are three 8-bit planes */
631
			}
632
633
#ifdef PCX_DEBUG
634
			g_print("io-pcx: header loaded\n");
635
			g_print("bpp: %u\n", context->bpp);
636
			g_print("dimensions: %ux%u\n", context->width, context->height);
637
#endif
638
639
			context->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, context->width, context->height);
640
			if(!context->pixbuf) {
641
				g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Couldn't create new pixbuf"));
642
				return FALSE;
643
			}
644
			context->data = gdk_pixbuf_get_pixels(context->pixbuf);
645
			context->rowstride = gdk_pixbuf_get_rowstride(context->pixbuf);
646
647
			context->line = g_try_malloc(sizeof(guchar) * context->bytesperline * context->num_planes);
648
			if(!context->line) {
649
				g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Couldn't allocate memory for line data"));
650
				return FALSE;
651
			}
652
653
			if(context->bpp == 8) {
654
				context->p_data = g_try_malloc(sizeof(guchar) * context->width * context->height);
655
				if(!context->p_data) {
1.1.4 by Sebastien Bacher
Import upstream version 2.22.1
656
					g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Couldn't allocate memory for PCX image"));
1.1.1 by Sebastien Bacher
Import upstream version 2.21.6
657
					return FALSE;
658
				}
659
			}
660
661
			if(context->prepared_func)
662
			        context->prepared_func(context->pixbuf, NULL, context->user_data);
663
664
			context->current_task = PCX_TASK_LOAD_DATA;
665
		}
666
667
		retval = TRUE;
668
	}
669
670
	if(context->current_task == PCX_TASK_LOAD_DATA) {
671
		switch(context->bpp) {
672
			default:
673
				g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_UNKNOWN_TYPE, _("Image has unsupported bpp"));
674
				retval = FALSE;
675
				break;
676
			case 1:
677
				retval = pcx_increment_load_data_1(context);
678
				break;
679
			case 2:
680
				retval = pcx_increment_load_data_2(context);
681
				break;
682
			case 4:
683
				retval = pcx_increment_load_data_4(context);
684
				break;
685
			case 8:
686
				retval = pcx_increment_load_data_8(context);
687
				break;
688
			case 24:
689
				retval = pcx_increment_load_data_24(context);
690
				break;
691
		}
692
	}
693
694
	return retval;
695
}
696
697
static gboolean
698
gdk_pixbuf__pcx_stop_load(gpointer data, GError **error)
699
{
700
	struct pcx_context *context = (struct pcx_context *)data;
701
702
	if(context->current_line != context->height) {
703
		g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, _("Didn't get all lines of PCX image"));
704
		free_pcx_context(context, FALSE);
705
		return FALSE;
706
	}
707
708
	if(context->current_task == PCX_TASK_LOAD_PALETTE) {
709
		if(!pcx_load_palette_8(context)) {
710
			g_set_error_literal(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, _("No palette found at end of PCX data"));
711
			free_pcx_context(context, FALSE);
712
			return FALSE;
713
		}
714
	}
715
716
	free_pcx_context(context, FALSE);
717
718
	return TRUE;
719
}
720
721
#ifndef INCLUDE_pcx
722
#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
723
#else
724
#define MODULE_ENTRY(function) void _gdk_pixbuf__pcx_ ## function
725
#endif
726
727
MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
728
{
729
	module->begin_load = gdk_pixbuf__pcx_begin_load;
730
	module->stop_load = gdk_pixbuf__pcx_stop_load;
731
	module->load_increment = gdk_pixbuf__pcx_load_increment;
732
}
733
734
MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
735
{
736
	static GdkPixbufModulePattern signature[] = {
737
		{ "\x0a \x01", NULL, 100 },
738
		{ "\x0a\x02\x01", NULL, 100 },
739
		{ "\x0a\x03\x01", NULL, 100 },
740
		{ "\x0a\x04\x01", NULL, 100 },
741
		{ "\x0a\x05\x01", NULL, 100 },
742
		{ NULL, NULL, 0 }
743
	};
744
	static gchar *mime_types[] = {
745
		"image/x-pcx",
746
		NULL,
747
	};
748
	static gchar *extensions[] = {
749
		"pcx",
750
		NULL,
751
	};
752
753
	info->name = "pcx";
754
	info->signature = signature;
755
	info->description = N_("The PCX image format");
756
	info->mime_types = mime_types;
757
	info->extensions = extensions;
758
	info->flags = GDK_PIXBUF_FORMAT_THREADSAFE;
759
	info->license = "LGPL";
760
}