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