aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/loaders/pmaps/evas_image_load_pmaps.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/loaders/pmaps/evas_image_load_pmaps.c')
-rw-r--r--libraries/evas/src/modules/loaders/pmaps/evas_image_load_pmaps.c558
1 files changed, 558 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/loaders/pmaps/evas_image_load_pmaps.c b/libraries/evas/src/modules/loaders/pmaps/evas_image_load_pmaps.c
new file mode 100644
index 0000000..9ba8f81
--- /dev/null
+++ b/libraries/evas/src/modules/loaders/pmaps/evas_image_load_pmaps.c
@@ -0,0 +1,558 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#ifdef HAVE_EVIL
6# include <Evil.h>
7#endif
8
9#include "evas_common.h"
10#include "evas_private.h"
11
12#define FILE_BUFFER_SIZE 1024 * 32
13#define FILE_BUFFER_UNREAD_SIZE 16
14
15static Eina_Bool evas_image_load_file_head_pmaps(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
16static Eina_Bool evas_image_load_file_data_pmaps(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
17
18Evas_Image_Load_Func evas_image_load_pmaps_func = {
19 EINA_TRUE,
20 evas_image_load_file_head_pmaps,
21 evas_image_load_file_data_pmaps,
22 NULL
23};
24
25/* The buffer to load pmaps images */
26typedef struct Pmaps_Buffer Pmaps_Buffer;
27
28struct Pmaps_Buffer
29{
30 FILE *file;
31
32 /* the buffer */
33 DATA8 buffer[FILE_BUFFER_SIZE];
34 DATA8 unread[FILE_BUFFER_UNREAD_SIZE];
35 DATA8 *current;
36 DATA8 *end;
37 char type[3];
38 unsigned char unread_len:7;
39 unsigned char last_buffer:1;
40
41 /* image properties */
42 int w;
43 int h;
44 int max;
45
46 /* interface */
47 int (*int_get) (Pmaps_Buffer *b, int *val);
48 int (*color_get) (Pmaps_Buffer *b, DATA32 *color);
49};
50
51/* internal used functions */
52static Eina_Bool pmaps_buffer_open(Pmaps_Buffer *b, const char *filename, int *error);
53static void pmaps_buffer_close(Pmaps_Buffer *b);
54static Eina_Bool pmaps_buffer_header_parse(Pmaps_Buffer *b, int *error);
55static int pmaps_buffer_plain_int_get(Pmaps_Buffer *b, int *val);
56static int pmaps_buffer_1byte_int_get(Pmaps_Buffer *b, int *val);
57static int pmaps_buffer_2byte_int_get(Pmaps_Buffer *b, int *val);
58static int pmaps_buffer_gray_get(Pmaps_Buffer *b, DATA32 *color);
59static int pmaps_buffer_rgb_get(Pmaps_Buffer *b, DATA32 *color);
60static int pmaps_buffer_plain_bw_get(Pmaps_Buffer *b, DATA32 *color);
61
62static size_t pmaps_buffer_plain_update(Pmaps_Buffer *b);
63static size_t pmaps_buffer_raw_update(Pmaps_Buffer *b);
64static int pmaps_buffer_comment_skip(Pmaps_Buffer *b);
65
66static Eina_Bool
67evas_image_load_file_head_pmaps(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
68{
69 Pmaps_Buffer b;
70
71 if (!pmaps_buffer_open(&b, file, error))
72 {
73 pmaps_buffer_close(&b);
74 return EINA_FALSE;
75 }
76
77 if (!pmaps_buffer_header_parse(&b, error))
78 {
79 pmaps_buffer_close(&b);
80 return EINA_FALSE;
81 }
82
83 ie->w = b.w;
84 ie->h = b.h;
85
86 pmaps_buffer_close(&b);
87 *error = EVAS_LOAD_ERROR_NONE;
88 return EINA_TRUE;
89}
90
91static Eina_Bool
92evas_image_load_file_data_pmaps(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
93{
94 Pmaps_Buffer b;
95 int pixels;
96 DATA32 *ptr;
97
98 if (!pmaps_buffer_open(&b, file, error))
99 {
100 pmaps_buffer_close(&b);
101 return EINA_FALSE;
102 }
103
104 if (!pmaps_buffer_header_parse(&b, error))
105 {
106 pmaps_buffer_close(&b);
107 return EINA_FALSE;
108 }
109
110 pixels = b.w * b.h;
111
112 evas_cache_image_surface_alloc(ie, b.w, b.h);
113 ptr = evas_cache_image_pixels(ie);
114 if (!ptr)
115 {
116 pmaps_buffer_close(&b);
117 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
118 return EINA_FALSE;
119 }
120
121 if (b.type[1] != '4')
122 {
123 while (pixels > 0 && b.color_get(&b, ptr))
124 {
125 pixels--;
126 ptr++;
127 }
128 }
129 else
130 {
131 while (pixels > 0
132 && (b.current != b.end || pmaps_buffer_raw_update(&b)))
133 {
134 int i;
135
136 for (i = 7; i >= 0 && pixels > 0; i--)
137 {
138 if (*b.current & (1 << i))
139 *ptr = 0xff000000;
140 else
141 *ptr = 0xffffffff;
142 ptr++;
143 pixels--;
144 }
145 b.current++;
146 }
147 }
148
149 /* if there are some pix missing, give them a proper default */
150 memset(ptr, 0xff, 4 * pixels);
151 pmaps_buffer_close(&b);
152
153 *error = EVAS_LOAD_ERROR_NONE;
154 return EINA_TRUE;
155}
156
157/* internal used functions */
158static Eina_Bool
159pmaps_buffer_open(Pmaps_Buffer *b, const char *filename, int *error)
160{
161 size_t len;
162
163 b->file = fopen(filename, "rb");
164 if (!b->file)
165 {
166 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
167 return EINA_FALSE;
168 }
169
170 *b->buffer = 0;
171 *b->unread = 0;
172 b->last_buffer = 0;
173 b->unread_len = 0;
174
175 len = pmaps_buffer_plain_update(b);
176
177 if (len < 3)
178 {
179 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
180 fclose(b->file);
181 b->file = NULL;
182 return EINA_FALSE;
183 }
184
185 /* copy the type */
186 b->type[0] = b->buffer[0];
187 b->type[1] = b->buffer[1];
188 b->type[2] = 0;
189 /* skip the PX */
190 b->current = b->buffer + 2;
191
192 *error = EVAS_LOAD_ERROR_NONE;
193 return EINA_TRUE;
194}
195
196static void
197pmaps_buffer_close(Pmaps_Buffer *b)
198{
199 if (b->file)
200 fclose(b->file);
201}
202
203static Eina_Bool
204pmaps_buffer_header_parse(Pmaps_Buffer *b, int *error)
205{
206 /* if there is no P at the beginning it is not a file we can parse */
207 if (b->type[0] != 'P')
208 {
209 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
210 return EINA_FALSE;
211 }
212
213 /* get the width */
214 if (!pmaps_buffer_plain_int_get(b, &(b->w)) || b->w < 1)
215 {
216 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
217 return EINA_FALSE;
218 }
219
220 /* get the height */
221 if (!pmaps_buffer_plain_int_get(b, &(b->h)) || b->h < 1)
222 {
223 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
224 return EINA_FALSE;
225 }
226
227 /* get the maximum value. P1 and P4 don't have a maximum value. */
228 if (!(b->type[1] == '1' || b->type[1] == '4')
229 && (!pmaps_buffer_plain_int_get(b, &(b->max)) || b->max < 1))
230 {
231 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
232 return EINA_FALSE;
233 }
234
235 /* set up the color get callback */
236 switch (b->type[1])
237 {
238 /* Black and White */
239 case '1':
240 b->color_get = pmaps_buffer_plain_bw_get;
241 break;
242 case '4':
243 /* Binary black and white use another format */
244 b->color_get = NULL;
245 break;
246 case '2':
247 case '5':
248 b->color_get = pmaps_buffer_gray_get;
249 break;
250 case '3':
251 case '6':
252 b->color_get = pmaps_buffer_rgb_get;
253 break;
254 case '7':
255 /* XXX write me */
256 return 0;
257 break;
258 default:
259 return 0;
260 }
261 /* set up the int get callback */
262 switch (b->type[1])
263 {
264 /* RAW */
265 case '5':
266 case '6':
267 if (b->max < 256)
268 b->int_get = pmaps_buffer_1byte_int_get;
269 else
270 b->int_get = pmaps_buffer_2byte_int_get;
271
272 if (b->current == b->end && !pmaps_buffer_raw_update(b))
273 return 0;
274
275 b->current++;
276 break;
277 /* Plain */
278 case '2':
279 case '3':
280 b->int_get = pmaps_buffer_plain_int_get;
281 break;
282 /* Black and White Bitmaps don't use that callback */
283 case '1':
284 case '4':
285 b->int_get = NULL;
286 /* we need to skip the next character fpr P4 it
287 * doesn't hurt if we do it for the P1 as well */
288 b->current++;
289 break;
290 }
291 return 1;
292}
293
294static size_t
295pmaps_buffer_plain_update(Pmaps_Buffer *b)
296{
297 size_t r;
298
299 /* if we already are in the last buffer we can not update it */
300 if (b->last_buffer)
301 return 0;
302
303 /* if we have unread bytes we need to put them before the new read
304 * stuff */
305 if (b->unread_len)
306 memcpy(b->buffer, b->unread, b->unread_len);
307
308 r = fread(&b->buffer[b->unread_len], 1,
309 FILE_BUFFER_SIZE - b->unread_len - 1, b->file) + b->unread_len;
310
311 /* we haven't read anything nor have we bytes in the unread buffer */
312 if (r == 0)
313 {
314 b->buffer[0] = '\0';
315 b->end = b->buffer;
316 b->last_buffer = 1;
317 return 0;
318 }
319
320 if (r < FILE_BUFFER_SIZE - 1)
321 {
322 /*we reached eof */ ;
323 b->last_buffer = 1;
324 }
325
326 b->buffer[r] = 0;
327
328 b->unread[0] = '\0';
329 b->unread_len = 0;
330
331 b->buffer[r] = '\0';
332 b->current = b->buffer;
333 b->end = b->buffer + r;
334
335 return r;
336}
337
338static size_t
339pmaps_buffer_raw_update(Pmaps_Buffer *b)
340{
341 size_t r;
342
343 if (b->last_buffer)
344 return 0;
345
346 if (b->unread_len)
347 memcpy(b->buffer, b->unread, b->unread_len);
348
349 r = fread(&b->buffer[b->unread_len], 1, FILE_BUFFER_SIZE - b->unread_len,
350 b->file) + b->unread_len;
351
352 if (r < FILE_BUFFER_SIZE)
353 {
354 /*we reached eof */
355 b->last_buffer = 1;
356 }
357
358 b->end = b->buffer + r;
359 b->current = b->buffer;
360
361 if (b->unread_len)
362 {
363 /* the buffer is now read */
364 *b->unread = 0;
365 b->unread_len = 0;
366 }
367
368 return r;
369}
370
371static int
372pmaps_buffer_plain_int_get(Pmaps_Buffer *b, int *val)
373{
374 char *start;
375 DATA8 lastc;
376
377 /* first skip all white space
378 * Note: we are skipping here actually every character than is not
379 * a digit */
380 while (!isdigit(*b->current))
381 {
382 if (*b->current == '\0')
383 {
384 if (!pmaps_buffer_plain_update(b))
385 return 0;
386
387 continue;
388 }
389 if (*b->current == '#' && !pmaps_buffer_comment_skip(b))
390 return 0;
391 b->current++;
392 }
393
394 start = (char *)b->current;
395 /* now find the end of the number */
396 while (isdigit(*b->current))
397 b->current++;
398
399 lastc = *b->current;
400 *b->current = '\0';
401 *val = atoi(start);
402 *b->current = lastc;
403
404 return 1;
405}
406
407static int
408pmaps_buffer_1byte_int_get(Pmaps_Buffer *b, int *val)
409{
410 /* are we at the end of the buffer? */
411 if (b->current == b->end && !pmaps_buffer_raw_update(b))
412 return 0;
413
414 *val = *b->current;
415 b->current++;
416
417 return 1;
418}
419static int
420pmaps_buffer_2byte_int_get(Pmaps_Buffer *b, int *val)
421{
422 /* are we at the end of the buffer? */
423 if (b->current == b->end && !pmaps_buffer_raw_update(b))
424 return 0;
425
426 *val = (int)(*b->current << 8);
427 b->current++;
428
429 /* are we at the end of the buffer? */
430 if (b->current == b->end && !pmaps_buffer_raw_update(b))
431 return 0;
432
433 *val |= *b->current;
434 b->current++;
435
436 return 1;
437}
438
439static int
440pmaps_buffer_comment_skip(Pmaps_Buffer *b)
441{
442 while (*b->current != '\n')
443 {
444 if (*b->current == '\0')
445 {
446 if (!pmaps_buffer_plain_update(b))
447 return 0;
448
449 continue;
450 }
451 b->current++;
452 }
453 return 1;
454}
455
456static int
457pmaps_buffer_rgb_get(Pmaps_Buffer *b, DATA32 *color)
458{
459 int vr, vg, vb;
460
461 if (!b->int_get(b, &vr) || !b->int_get(b, &vg) || !b->int_get(b, &vb))
462 return 0;
463
464 if (b->max != 255)
465 {
466 vr = (vr * 255) / b->max;
467 vg = (vg * 255) / b->max;
468 vb = (vb * 255) / b->max;
469 }
470 if (vr > 255)
471 vr = 255;
472 if (vg > 255)
473 vg = 255;
474 if (vb > 255)
475 vb = 255;
476
477 *color = ARGB_JOIN(0xff, vr, vg, vb);
478
479 return 1;
480}
481
482static int
483pmaps_buffer_gray_get(Pmaps_Buffer *b, DATA32 *color)
484{
485 int val;
486
487 if (!b->int_get(b, &val))
488 return 0;
489
490 if (b->max != 255)
491 val = (val * 255) / b->max;
492 if (val > 255)
493 val = 255;
494 *color = ARGB_JOIN(0xff, val, val, val);
495
496 return 1;
497}
498
499static int
500pmaps_buffer_plain_bw_get(Pmaps_Buffer *b, DATA32 *val)
501{
502 /* first skip all white space
503 * Note: we are skipping here actually every character than is not
504 * a digit */
505 while (!isdigit(*b->current))
506 {
507 if (*b->current == '\0')
508 {
509 if (!pmaps_buffer_raw_update(b))
510 return 0;
511
512 continue;
513 }
514 if (*b->current == '#' && !pmaps_buffer_comment_skip(b))
515 return 0;
516 b->current++;
517 }
518
519 if (*b->current == '0')
520 *val = 0xffffffff;
521 else
522 *val = 0xff000000;
523
524 b->current++;
525
526 return 1;
527}
528
529/* external functions */
530static int
531module_open(Evas_Module *em)
532{
533 if (!em)
534 return 0;
535 em->functions = (void *)(&evas_image_load_pmaps_func);
536 return 1;
537}
538
539static void
540module_close(Evas_Module *em __UNUSED__)
541{
542}
543
544static Evas_Module_Api evas_modapi = {
545 EVAS_MODULE_API_VERSION,
546 "pmaps",
547 "none",
548 {
549 module_open,
550 module_close
551 }
552};
553
554EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, pmaps);
555
556#ifndef EVAS_STATIC_BUILD_PMAPS
557EVAS_EINA_MODULE_DEFINE(image_loader, pmaps);
558#endif