1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdio.h>
6
7 #include "evas_common_private.h"
8 #include "evas_private.h"
9
10 static int
read_mb(unsigned int * data,void * map,size_t length,size_t * position)11 read_mb(unsigned int *data, void *map, size_t length, size_t *position)
12 {
13 int ac = 0, ct;
14 unsigned char buf;
15
16 for (ct = 0;;)
17 {
18 if ((ct++) == 5) return -1;
19 if (*position > length) return -1;
20 buf = ((unsigned char *) map)[(*position)++];
21 ac = (ac << 7) | (buf & 0x7f);
22 if ((buf & 0x80) == 0) break;
23 }
24 *data = ac;
25 return 0;
26 }
27
28 static void *
evas_image_load_file_open_wbmp(Eina_File * f,Eina_Stringshare * key EINA_UNUSED,Evas_Image_Load_Opts * opts EINA_UNUSED,Evas_Image_Animated * animated EINA_UNUSED,int * error EINA_UNUSED)29 evas_image_load_file_open_wbmp(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
30 Evas_Image_Load_Opts *opts EINA_UNUSED,
31 Evas_Image_Animated *animated EINA_UNUSED,
32 int *error EINA_UNUSED)
33 {
34 return f;
35 }
36
37 static void
evas_image_load_file_close_wbmp(void * loader_data EINA_UNUSED)38 evas_image_load_file_close_wbmp(void *loader_data EINA_UNUSED)
39 {
40 }
41
42 static Eina_Bool
evas_image_load_file_head_wbmp(void * loader_data,Emile_Image_Property * prop,int * error)43 evas_image_load_file_head_wbmp(void *loader_data,
44 Emile_Image_Property *prop,
45 int *error)
46 {
47 Eina_File *f = loader_data;
48 void *map = NULL;
49 size_t position = 0;
50 size_t length;
51 unsigned int type, w, h;
52 Eina_Bool r = EINA_FALSE;
53
54 *error = EVAS_LOAD_ERROR_GENERIC;
55 length = eina_file_size_get(f);
56 if (length <= 4) goto bail;
57
58 map = eina_file_map_all(f, EINA_FILE_RANDOM);
59 if (!map) goto bail;
60
61 if (read_mb(&type, map, length, &position) < 0) goto bail;
62
63 if (type != 0)
64 {
65 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
66 goto bail;
67 }
68
69 position++; /* skipping one byte */
70 if (read_mb(&w, map, length, &position) < 0) goto bail;
71 if (read_mb(&h, map, length, &position) < 0) goto bail;
72
73 /* Wbmp header identifier is too weak....
74 Here checks size validation whether it's acutal wbmp or not. */
75 if ((((w + 7) >> 3) * h) + position != length)
76 {
77 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
78 goto bail;
79 }
80
81 if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
82 IMG_TOO_BIG(w, h))
83 {
84 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
85 goto bail;
86 }
87
88 prop->w = w;
89 prop->h = h;
90
91 *error = EVAS_LOAD_ERROR_NONE;
92 r = EINA_TRUE;
93
94 bail:
95 if (map) eina_file_map_free(f, map);
96 return r;
97 }
98
99 static Eina_Bool
evas_image_load_file_data_wbmp(void * loader_data,Emile_Image_Property * prop,void * pixels,int * error)100 evas_image_load_file_data_wbmp(void *loader_data,
101 Emile_Image_Property *prop,
102 void *pixels,
103 int *error)
104 {
105 Eina_File *f = loader_data;
106 void *map = NULL;
107 size_t position = 0;
108 size_t length;
109 unsigned int type, w, h;
110 unsigned int line_length;
111 unsigned char *line = NULL;
112 int cur = 0, x, y;
113 DATA32 *dst_data;
114 Eina_Bool r = EINA_FALSE;
115
116 *error = EVAS_LOAD_ERROR_GENERIC;
117 length = eina_file_size_get(f);
118 if (length <= 4) goto bail;
119
120 map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
121 if (!map) goto bail;
122
123 if (read_mb(&type, map, length, &position) < 0) goto bail;
124
125 if (type != 0)
126 {
127 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
128 goto bail;
129 }
130
131 position++; /* skipping one byte */
132 if (read_mb(&w, map, length, &position) < 0) goto bail;
133 if (read_mb(&h, map, length, &position) < 0) goto bail;
134
135 /* Wbmp header identifier is too weak....
136 Here checks size validation whether it's acutal wbmp or not. */
137 if ((((w + 7) >> 3) * h) + position != length)
138 {
139 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
140 goto bail;
141 }
142
143 if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
144 IMG_TOO_BIG(w, h))
145 {
146 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
147 goto bail;
148 }
149
150 if (prop->w != w || prop->h != h)
151 {
152 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
153 goto bail;
154 }
155
156 dst_data = pixels;
157
158 line_length = (prop->w + 7) >> 3;
159
160 for (y = 0; y < (int)prop->h; y++)
161 {
162 line = ((unsigned char*) map) + position;
163 position += line_length;
164 for (x = 0; x < (int)prop->w; x++)
165 {
166 int idx = x >> 3;
167 int offset = 1 << (0x07 - (x & 0x07));
168 if (line[idx] & offset) dst_data[cur] = 0xffffffff;
169 else dst_data[cur] = 0xff000000;
170 cur++;
171 }
172 }
173
174 *error = EVAS_LOAD_ERROR_NONE;
175 r = EINA_TRUE;
176
177 bail:
178 if (map) eina_file_map_free(f, map);
179 return r;
180 }
181
182 static Evas_Image_Load_Func evas_image_load_wbmp_func =
183 {
184 EVAS_IMAGE_LOAD_VERSION,
185 evas_image_load_file_open_wbmp,
186 evas_image_load_file_close_wbmp,
187 (void*) evas_image_load_file_head_wbmp,
188 NULL,
189 (void*) evas_image_load_file_data_wbmp,
190 NULL,
191 EINA_TRUE,
192 EINA_FALSE
193 };
194
195 static int
module_open(Evas_Module * em)196 module_open(Evas_Module *em)
197 {
198 if (!em) return 0;
199 em->functions = (void *)(&evas_image_load_wbmp_func);
200 return 1;
201 }
202
203 static void
module_close(Evas_Module * em EINA_UNUSED)204 module_close(Evas_Module *em EINA_UNUSED)
205 {
206 }
207
208 static Evas_Module_Api evas_modapi =
209 {
210 EVAS_MODULE_API_VERSION,
211 "wbmp",
212 "none",
213 {
214 module_open,
215 module_close
216 }
217 };
218
219 EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, wbmp);
220
221 #ifndef EVAS_STATIC_BUILD_WBMP
222 EVAS_EINA_MODULE_DEFINE(image_loader, wbmp);
223 #endif
224