diff options
author | Gustavo Sverzut Barbieri <barbieri@gmail.com> | 2013-01-12 01:15:45 +0000 |
---|---|---|
committer | Gustavo Sverzut Barbieri <barbieri@gmail.com> | 2013-01-12 01:15:45 +0000 |
commit | 34f53151414bcdf44ec81e582b007f74da595694 (patch) | |
tree | 863058f0d94e9d39998774a375aa6d242d8714a4 /src/lib/ethumb/ethumb.c | |
parent | ae51833bac7ba5f72bd40a96beb13081c8d573f6 (diff) |
merge ethumb.
This one was a painful bitch. The edbus2 port was quite broken, mainly
leaking eina_stringshare and also not adding the '\0' to the strings
that are represented as bytearray (paths cannot be utf8 to avoid
translations).
Emotion plugin was also quite bogus and the video thumbnail as edje
(animated) is not working yet due bug in Edje_Edit api -- someone
needs to investigate this, seems strange.
Emotion plugin also had a bug that it was deleting the object from
inside object callback.
Now it seems to work. Please report if it does not.
SVN revision: 82675
Diffstat (limited to 'src/lib/ethumb/ethumb.c')
-rw-r--r-- | src/lib/ethumb/ethumb.c | 1863 |
1 files changed, 1863 insertions, 0 deletions
diff --git a/src/lib/ethumb/ethumb.c b/src/lib/ethumb/ethumb.c new file mode 100644 index 0000000000..65d3b97c84 --- /dev/null +++ b/src/lib/ethumb/ethumb.c | |||
@@ -0,0 +1,1863 @@ | |||
1 | /** | ||
2 | * @file | ||
3 | * | ||
4 | * Copyright (C) 2009 by ProFUSION embedded systems | ||
5 | * | ||
6 | * This library is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU Lesser General Public | ||
8 | * License as published by the Free Software Foundation; either | ||
9 | * version 2.1 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This library is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with this library; | ||
18 | * if not, see <http://www.gnu.org/licenses/>. | ||
19 | * | ||
20 | * @author Rafael Antognolli <antognolli@profusion.mobi> | ||
21 | */ | ||
22 | #ifdef HAVE_CONFIG_H | ||
23 | #include "config.h" | ||
24 | #endif | ||
25 | |||
26 | #ifdef STDC_HEADERS | ||
27 | # include <stdlib.h> | ||
28 | # include <stddef.h> | ||
29 | #else | ||
30 | # ifdef HAVE_STDLIB_H | ||
31 | # include <stdlib.h> | ||
32 | # endif | ||
33 | #endif | ||
34 | |||
35 | #include <stdio.h> | ||
36 | #include <stdlib.h> | ||
37 | #include <limits.h> | ||
38 | #include <string.h> | ||
39 | #include <unistd.h> | ||
40 | #include <errno.h> | ||
41 | #include <sys/types.h> | ||
42 | #include <sys/stat.h> | ||
43 | #include <dirent.h> | ||
44 | #include <dlfcn.h> | ||
45 | #include <ctype.h> | ||
46 | |||
47 | #ifdef HAVE_XATTR | ||
48 | # include <sys/xattr.h> | ||
49 | #endif | ||
50 | |||
51 | #ifndef PATH_MAX | ||
52 | # define PATH_MAX 4096 | ||
53 | #endif | ||
54 | |||
55 | #ifdef HAVE_LIBEXIF | ||
56 | #include <libexif/exif-data.h> | ||
57 | #endif | ||
58 | |||
59 | #ifdef HAVE_EVIL | ||
60 | # include <Evil.h> | ||
61 | #endif | ||
62 | |||
63 | #include <Eina.h> | ||
64 | #include <eina_safety_checks.h> | ||
65 | #include <Evas.h> | ||
66 | #include <Ecore.h> | ||
67 | #include <Ecore_Evas.h> | ||
68 | #include <Ecore_File.h> | ||
69 | #include <Edje.h> | ||
70 | |||
71 | #include "Ethumb.h" | ||
72 | #include "ethumb_private.h" | ||
73 | #include "Ethumb_Plugin.h" | ||
74 | #include "md5.h" | ||
75 | |||
76 | static Ethumb_Version _version = { VMAJ, VMIN, VMIC, VREV }; | ||
77 | EAPI Ethumb_Version *ethumb_version = &_version; | ||
78 | |||
79 | static int _log_dom = -1; | ||
80 | #define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__) | ||
81 | #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__) | ||
82 | #define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__) | ||
83 | #define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__) | ||
84 | |||
85 | static int initcount = 0; | ||
86 | static const char *_home_thumb_dir = NULL; | ||
87 | static const char *_thumb_category_normal = NULL; | ||
88 | static const char *_thumb_category_large = NULL; | ||
89 | |||
90 | static const int THUMB_SIZE_NORMAL = 128; | ||
91 | static const int THUMB_SIZE_LARGE = 256; | ||
92 | |||
93 | static Eina_Hash *_plugins_ext = NULL; | ||
94 | static Eina_Array *_plugins = NULL; | ||
95 | static Eina_Prefix *_pfx = NULL; | ||
96 | |||
97 | static Eina_Bool | ||
98 | _ethumb_plugin_list_cb(Eina_Module *m, void *data EINA_UNUSED) | ||
99 | { | ||
100 | const char *file; | ||
101 | const char **ext; | ||
102 | Ethumb_Plugin *plugin; | ||
103 | Ethumb_Plugin *(*plugin_get)(void); | ||
104 | |||
105 | file = eina_module_file_get(m); | ||
106 | if (!eina_module_load(m)) | ||
107 | { | ||
108 | ERR("could not load module \"%s\": %s", | ||
109 | file, eina_error_msg_get(eina_error_get())); | ||
110 | return EINA_FALSE; | ||
111 | } | ||
112 | |||
113 | plugin_get = eina_module_symbol_get(m, "ethumb_plugin_get"); | ||
114 | if (!plugin_get) | ||
115 | { | ||
116 | ERR("could not find ethumb_plugin_get() in module \"%s\": %s", | ||
117 | file, eina_error_msg_get(eina_error_get())); | ||
118 | eina_module_unload(m); | ||
119 | return EINA_FALSE; | ||
120 | } | ||
121 | |||
122 | plugin = plugin_get(); | ||
123 | if (!plugin) | ||
124 | { | ||
125 | ERR("plugin \"%s\" failed to init.", file); | ||
126 | eina_module_unload(m); | ||
127 | return EINA_FALSE; | ||
128 | } | ||
129 | |||
130 | DBG("loaded plugin \"%s\" (%p) with extensions:", file, plugin); | ||
131 | for (ext = plugin->extensions; *ext; ext++) | ||
132 | { | ||
133 | DBG(" extension \"%s\"", *ext); | ||
134 | eina_hash_add(_plugins_ext, *ext, plugin); | ||
135 | } | ||
136 | |||
137 | return EINA_TRUE; | ||
138 | } | ||
139 | |||
140 | static void | ||
141 | _ethumb_plugins_load(void) | ||
142 | { | ||
143 | char buf[PATH_MAX]; | ||
144 | |||
145 | _plugins_ext = eina_hash_string_small_new(NULL); | ||
146 | EINA_SAFETY_ON_NULL_RETURN(_plugins_ext); | ||
147 | |||
148 | snprintf(buf, sizeof(buf), "%s/ethumb/modules", eina_prefix_lib_get(_pfx)); | ||
149 | _plugins = eina_module_list_get(_plugins, buf, 1, | ||
150 | &_ethumb_plugin_list_cb, NULL); | ||
151 | } | ||
152 | |||
153 | static void | ||
154 | _ethumb_plugins_unload(void) | ||
155 | { | ||
156 | eina_hash_free(_plugins_ext); | ||
157 | _plugins_ext = NULL; | ||
158 | eina_module_list_unload(_plugins); | ||
159 | eina_module_list_free(_plugins); | ||
160 | eina_array_free(_plugins); | ||
161 | _plugins = NULL; | ||
162 | } | ||
163 | |||
164 | EAPI int | ||
165 | ethumb_init(void) | ||
166 | { | ||
167 | const char *home; | ||
168 | char buf[PATH_MAX]; | ||
169 | |||
170 | if (initcount) | ||
171 | return ++initcount; | ||
172 | |||
173 | if (!eina_init()) | ||
174 | { | ||
175 | fprintf(stderr, "ERROR: Could not initialize eina.\n"); | ||
176 | return 0; | ||
177 | } | ||
178 | _log_dom = eina_log_domain_register("ethumb", EINA_COLOR_GREEN); | ||
179 | if (_log_dom < 0) | ||
180 | { | ||
181 | EINA_LOG_ERR("Could not register log domain: ethumb"); | ||
182 | goto error_log; | ||
183 | } | ||
184 | |||
185 | _pfx = eina_prefix_new(NULL, ethumb_init, | ||
186 | "ETHUMB", "ethumb", "checkme", | ||
187 | PACKAGE_BIN_DIR, PACKAGE_LIB_DIR, | ||
188 | PACKAGE_DATA_DIR, PACKAGE_DATA_DIR); | ||
189 | if (!_pfx) | ||
190 | { | ||
191 | ERR("Could not get ethumb installation prefix."); | ||
192 | goto error_pfx; | ||
193 | } | ||
194 | |||
195 | evas_init(); | ||
196 | ecore_init(); | ||
197 | ecore_evas_init(); | ||
198 | edje_init(); | ||
199 | |||
200 | home = getenv("HOME"); | ||
201 | snprintf(buf, sizeof(buf), "%s/.thumbnails", home); | ||
202 | |||
203 | _home_thumb_dir = eina_stringshare_add(buf); | ||
204 | _thumb_category_normal = eina_stringshare_add("normal"); | ||
205 | _thumb_category_large = eina_stringshare_add("large"); | ||
206 | |||
207 | _ethumb_plugins_load(); | ||
208 | return ++initcount; | ||
209 | |||
210 | error_pfx: | ||
211 | eina_log_domain_unregister(_log_dom); | ||
212 | _log_dom = -1; | ||
213 | |||
214 | error_log: | ||
215 | eina_shutdown(); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | EAPI int | ||
220 | ethumb_shutdown(void) | ||
221 | { | ||
222 | if (initcount <= 0) | ||
223 | { | ||
224 | EINA_LOG_ERR("Init count not greater than 0 in shutdown."); | ||
225 | return 0; | ||
226 | } | ||
227 | initcount--; | ||
228 | if (initcount == 0) | ||
229 | { | ||
230 | _ethumb_plugins_unload(); | ||
231 | eina_stringshare_del(_home_thumb_dir); | ||
232 | eina_stringshare_del(_thumb_category_normal); | ||
233 | eina_stringshare_del(_thumb_category_large); | ||
234 | evas_shutdown(); | ||
235 | ecore_shutdown(); | ||
236 | ecore_evas_shutdown(); | ||
237 | edje_shutdown(); | ||
238 | eina_prefix_free(_pfx); | ||
239 | _pfx = NULL; | ||
240 | eina_log_domain_unregister(_log_dom); | ||
241 | _log_dom = -1; | ||
242 | eina_shutdown(); | ||
243 | } | ||
244 | |||
245 | return initcount; | ||
246 | } | ||
247 | |||
248 | EAPI Ethumb * | ||
249 | ethumb_new(void) | ||
250 | { | ||
251 | Ethumb *ethumb; | ||
252 | Ecore_Evas *ee, *sub_ee; | ||
253 | Evas *e, *sub_e; | ||
254 | Evas_Object *o, *img; | ||
255 | |||
256 | ethumb = calloc(1, sizeof(Ethumb)); | ||
257 | EINA_SAFETY_ON_NULL_RETURN_VAL(ethumb, NULL); | ||
258 | |||
259 | /* IF CHANGED, UPDATE DOCS in (Ethumb.c, Ethumb_Client.c, python...)!!! */ | ||
260 | ethumb->tw = THUMB_SIZE_NORMAL; | ||
261 | ethumb->th = THUMB_SIZE_NORMAL; | ||
262 | ethumb->orientation = ETHUMB_THUMB_ORIENT_ORIGINAL; | ||
263 | ethumb->crop_x = 0.5; | ||
264 | ethumb->crop_y = 0.5; | ||
265 | ethumb->quality = 80; | ||
266 | ethumb->compress = 9; | ||
267 | ethumb->video.start = 0.1; | ||
268 | ethumb->video.time = 3; | ||
269 | ethumb->video.interval = 0.05; | ||
270 | ethumb->video.ntimes = 3; | ||
271 | ethumb->video.fps = 10; | ||
272 | |||
273 | ee = ecore_evas_buffer_new(1, 1); | ||
274 | e = ecore_evas_get(ee); | ||
275 | if (!e) | ||
276 | { | ||
277 | ERR("could not create ecore evas buffer"); | ||
278 | free(ethumb); | ||
279 | return NULL; | ||
280 | } | ||
281 | |||
282 | evas_image_cache_set(e, 0); | ||
283 | evas_font_cache_set(e, 0); | ||
284 | |||
285 | o = ecore_evas_object_image_new(ee); | ||
286 | if (!o) | ||
287 | { | ||
288 | ERR("could not create sub ecore evas buffer"); | ||
289 | ecore_evas_free(ee); | ||
290 | free(ethumb); | ||
291 | return NULL; | ||
292 | } | ||
293 | |||
294 | sub_ee = ecore_evas_object_ecore_evas_get(o); | ||
295 | sub_e = ecore_evas_object_evas_get(o); | ||
296 | ecore_evas_alpha_set(sub_ee, EINA_TRUE); | ||
297 | |||
298 | evas_image_cache_set(sub_e, 0); | ||
299 | evas_font_cache_set(sub_e, 0); | ||
300 | |||
301 | img = evas_object_image_add(sub_e); | ||
302 | if (!img) | ||
303 | { | ||
304 | ERR("could not create source objects."); | ||
305 | ecore_evas_free(ee); | ||
306 | free(ethumb); | ||
307 | return NULL; | ||
308 | } | ||
309 | |||
310 | ethumb->ee = ee; | ||
311 | ethumb->e = e; | ||
312 | ethumb->sub_ee = sub_ee; | ||
313 | ethumb->sub_e = sub_e; | ||
314 | ethumb->o = o; | ||
315 | ethumb->img = img; | ||
316 | |||
317 | DBG("ethumb=%p", ethumb); | ||
318 | |||
319 | return ethumb; | ||
320 | } | ||
321 | |||
322 | static void | ||
323 | _ethumb_frame_free(Ethumb_Frame *frame) | ||
324 | { | ||
325 | Evas_Object *o; | ||
326 | |||
327 | if (!frame) | ||
328 | return; | ||
329 | |||
330 | if (frame->swallow && frame->edje) | ||
331 | { | ||
332 | o = edje_object_part_swallow_get(frame->edje, frame->swallow); | ||
333 | if (o) | ||
334 | edje_object_part_unswallow(frame->edje, o); | ||
335 | } | ||
336 | eina_stringshare_del(frame->file); | ||
337 | eina_stringshare_del(frame->group); | ||
338 | eina_stringshare_del(frame->swallow); | ||
339 | |||
340 | if (frame->edje) | ||
341 | evas_object_del(frame->edje); | ||
342 | |||
343 | free(frame); | ||
344 | } | ||
345 | |||
346 | EAPI void | ||
347 | ethumb_free(Ethumb *ethumb) | ||
348 | { | ||
349 | EINA_SAFETY_ON_NULL_RETURN(ethumb); | ||
350 | |||
351 | DBG("ethumb=%p", ethumb); | ||
352 | |||
353 | if (ethumb->frame) | ||
354 | _ethumb_frame_free(ethumb->frame); | ||
355 | ethumb_file_free(ethumb); | ||
356 | evas_object_del(ethumb->o); | ||
357 | ecore_evas_free(ethumb->ee); | ||
358 | eina_stringshare_del(ethumb->thumb_dir); | ||
359 | eina_stringshare_del(ethumb->category); | ||
360 | if (ethumb->finished_idler) | ||
361 | ecore_idler_del(ethumb->finished_idler); | ||
362 | free(ethumb); | ||
363 | } | ||
364 | |||
365 | EAPI void | ||
366 | ethumb_thumb_fdo_set(Ethumb *e, Ethumb_Thumb_FDO_Size s) | ||
367 | { | ||
368 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
369 | EINA_SAFETY_ON_FALSE_RETURN(s == ETHUMB_THUMB_NORMAL || | ||
370 | s == ETHUMB_THUMB_LARGE); | ||
371 | DBG("ethumb=%p, size=%d", e, s); | ||
372 | |||
373 | if (s == ETHUMB_THUMB_NORMAL) | ||
374 | { | ||
375 | e->tw = THUMB_SIZE_NORMAL; | ||
376 | e->th = THUMB_SIZE_NORMAL; | ||
377 | } | ||
378 | else | ||
379 | { | ||
380 | e->tw = THUMB_SIZE_LARGE; | ||
381 | e->th = THUMB_SIZE_LARGE; | ||
382 | } | ||
383 | |||
384 | e->format = ETHUMB_THUMB_FDO; | ||
385 | e->aspect = ETHUMB_THUMB_KEEP_ASPECT; | ||
386 | e->orientation = ETHUMB_THUMB_ORIENT_ORIGINAL; | ||
387 | _ethumb_frame_free(e->frame); | ||
388 | e->frame = NULL; | ||
389 | eina_stringshare_del(e->thumb_dir); | ||
390 | eina_stringshare_del(e->category); | ||
391 | e->thumb_dir = NULL; | ||
392 | e->category = NULL; | ||
393 | } | ||
394 | |||
395 | EAPI void | ||
396 | ethumb_thumb_size_set(Ethumb *e, int tw, int th) | ||
397 | { | ||
398 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
399 | EINA_SAFETY_ON_FALSE_RETURN(tw > 0); | ||
400 | EINA_SAFETY_ON_FALSE_RETURN(th > 0); | ||
401 | |||
402 | DBG("ethumb=%p, w=%d, h=%d", e, tw, th); | ||
403 | e->tw = tw; | ||
404 | e->th = th; | ||
405 | } | ||
406 | |||
407 | EAPI void | ||
408 | ethumb_thumb_size_get(const Ethumb *e, int *tw, int *th) | ||
409 | { | ||
410 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
411 | |||
412 | if (tw) *tw = e->tw; | ||
413 | if (th) *th = e->th; | ||
414 | } | ||
415 | |||
416 | EAPI void | ||
417 | ethumb_thumb_format_set(Ethumb *e, Ethumb_Thumb_Format f) | ||
418 | { | ||
419 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
420 | EINA_SAFETY_ON_FALSE_RETURN(f == ETHUMB_THUMB_FDO || | ||
421 | f == ETHUMB_THUMB_JPEG || | ||
422 | f == ETHUMB_THUMB_EET); | ||
423 | |||
424 | DBG("ethumb=%p, format=%d", e, f); | ||
425 | e->format = f; | ||
426 | } | ||
427 | |||
428 | EAPI Ethumb_Thumb_Format | ||
429 | ethumb_thumb_format_get(const Ethumb *e) | ||
430 | { | ||
431 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
432 | return e->format; | ||
433 | } | ||
434 | |||
435 | EAPI void | ||
436 | ethumb_thumb_aspect_set(Ethumb *e, Ethumb_Thumb_Aspect a) | ||
437 | { | ||
438 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
439 | EINA_SAFETY_ON_FALSE_RETURN(a == ETHUMB_THUMB_KEEP_ASPECT || | ||
440 | a == ETHUMB_THUMB_IGNORE_ASPECT || | ||
441 | a == ETHUMB_THUMB_CROP); | ||
442 | |||
443 | DBG("ethumb=%p, aspect=%d", e, a); | ||
444 | e->aspect = a; | ||
445 | } | ||
446 | |||
447 | EAPI Ethumb_Thumb_Aspect | ||
448 | ethumb_thumb_aspect_get(const Ethumb *e) | ||
449 | { | ||
450 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
451 | return e->aspect; | ||
452 | } | ||
453 | |||
454 | EAPI void | ||
455 | ethumb_thumb_orientation_set(Ethumb *e, Ethumb_Thumb_Orientation o) | ||
456 | { | ||
457 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
458 | EINA_SAFETY_ON_FALSE_RETURN(o == ETHUMB_THUMB_ORIENT_NONE || | ||
459 | o == ETHUMB_THUMB_ROTATE_90_CW || | ||
460 | o == ETHUMB_THUMB_ROTATE_180 || | ||
461 | o == ETHUMB_THUMB_ROTATE_90_CCW || | ||
462 | o == ETHUMB_THUMB_FLIP_HORIZONTAL || | ||
463 | o == ETHUMB_THUMB_FLIP_VERTICAL || | ||
464 | o == ETHUMB_THUMB_FLIP_TRANSPOSE || | ||
465 | o == ETHUMB_THUMB_FLIP_TRANSVERSE || | ||
466 | o == ETHUMB_THUMB_ORIENT_ORIGINAL); | ||
467 | |||
468 | DBG("ethumb=%p, orientation=%d", e, o); | ||
469 | e->orientation = o; | ||
470 | } | ||
471 | |||
472 | EAPI Ethumb_Thumb_Orientation | ||
473 | ethumb_thumb_orientation_get(const Ethumb *e) | ||
474 | { | ||
475 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
476 | return e->orientation; | ||
477 | } | ||
478 | |||
479 | EAPI void | ||
480 | ethumb_thumb_crop_align_set(Ethumb *e, float x, float y) | ||
481 | { | ||
482 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
483 | |||
484 | DBG("ethumb=%p, x=%f, y=%f", e, x, y); | ||
485 | e->crop_x = x; | ||
486 | e->crop_y = y; | ||
487 | } | ||
488 | |||
489 | EAPI void | ||
490 | ethumb_thumb_crop_align_get(const Ethumb *e, float *x, float *y) | ||
491 | { | ||
492 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
493 | |||
494 | if (x) *x = e->crop_x; | ||
495 | if (y) *y = e->crop_y; | ||
496 | } | ||
497 | |||
498 | EAPI void | ||
499 | ethumb_thumb_quality_set(Ethumb *e, int quality) | ||
500 | { | ||
501 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
502 | |||
503 | DBG("ethumb=%p, quality=%d", e, quality); | ||
504 | e->quality = quality; | ||
505 | } | ||
506 | |||
507 | EAPI int | ||
508 | ethumb_thumb_quality_get(const Ethumb *e) | ||
509 | { | ||
510 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
511 | return e->quality; | ||
512 | } | ||
513 | |||
514 | EAPI void | ||
515 | ethumb_thumb_compress_set(Ethumb *e, int compress) | ||
516 | { | ||
517 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
518 | |||
519 | DBG("ethumb=%p, compress=%d", e, compress); | ||
520 | e->compress = compress; | ||
521 | } | ||
522 | |||
523 | EAPI int | ||
524 | ethumb_thumb_compress_get(const Ethumb *e) | ||
525 | { | ||
526 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
527 | return e->compress; | ||
528 | } | ||
529 | |||
530 | EAPI Eina_Bool | ||
531 | ethumb_frame_set(Ethumb *e, const char *theme_file, const char *group, const char *swallow) | ||
532 | { | ||
533 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
534 | |||
535 | Ethumb_Frame *frame; | ||
536 | frame = e->frame; | ||
537 | |||
538 | DBG("ethumb=%p, theme_file=%s, group=%s, swallow=%s", | ||
539 | e, theme_file ? theme_file : "", group ? group : "", | ||
540 | swallow ? swallow : ""); | ||
541 | |||
542 | if (frame) | ||
543 | { | ||
544 | edje_object_part_unswallow(frame->edje, e->img); | ||
545 | if (!theme_file) | ||
546 | _ethumb_frame_free(frame); | ||
547 | } | ||
548 | |||
549 | if (!theme_file) | ||
550 | { | ||
551 | e->frame = NULL; | ||
552 | return EINA_FALSE; | ||
553 | } | ||
554 | |||
555 | if (!frame) | ||
556 | { | ||
557 | frame = calloc(1, sizeof(Ethumb_Frame)); | ||
558 | if (!frame) | ||
559 | { | ||
560 | ERR("could not allocate Ethumb_Frame structure."); | ||
561 | return EINA_FALSE; | ||
562 | } | ||
563 | |||
564 | frame->edje = edje_object_add(e->sub_e); | ||
565 | if (!frame->edje) | ||
566 | { | ||
567 | ERR("could not create edje frame object."); | ||
568 | _ethumb_frame_free(frame); | ||
569 | e->frame = NULL; | ||
570 | return EINA_FALSE; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | if (!edje_object_file_set(frame->edje, theme_file, group)) | ||
575 | { | ||
576 | ERR("could not load frame theme."); | ||
577 | _ethumb_frame_free(frame); | ||
578 | e->frame = NULL; | ||
579 | return EINA_FALSE; | ||
580 | } | ||
581 | |||
582 | edje_object_part_swallow(frame->edje, swallow, e->img); | ||
583 | if (!edje_object_part_swallow_get(frame->edje, swallow)) | ||
584 | { | ||
585 | ERR("could not swallow image to edje frame."); | ||
586 | _ethumb_frame_free(frame); | ||
587 | e->frame = NULL; | ||
588 | return EINA_FALSE; | ||
589 | } | ||
590 | |||
591 | eina_stringshare_replace(&frame->file, theme_file); | ||
592 | eina_stringshare_replace(&frame->group, group); | ||
593 | eina_stringshare_replace(&frame->swallow, swallow); | ||
594 | |||
595 | e->frame = frame; | ||
596 | |||
597 | return EINA_TRUE; | ||
598 | } | ||
599 | |||
600 | EAPI void | ||
601 | ethumb_frame_get(const Ethumb *e, const char **theme_file, const char **group, const char **swallow) | ||
602 | { | ||
603 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
604 | |||
605 | if (e->frame) | ||
606 | { | ||
607 | if (theme_file) *theme_file = e->frame->file; | ||
608 | if (group) *group = e->frame->group; | ||
609 | if (swallow) *swallow = e->frame->swallow; | ||
610 | } | ||
611 | else | ||
612 | { | ||
613 | if (theme_file) *theme_file = NULL; | ||
614 | if (group) *group = NULL; | ||
615 | if (swallow) *swallow = NULL; | ||
616 | } | ||
617 | } | ||
618 | |||
619 | static const char * | ||
620 | _ethumb_build_absolute_path(const char *path, char buf[PATH_MAX]) | ||
621 | { | ||
622 | char *p; | ||
623 | int len; | ||
624 | |||
625 | if (!path) | ||
626 | return NULL; | ||
627 | |||
628 | p = buf; | ||
629 | |||
630 | if (path[0] == '/') | ||
631 | strcpy(p, path); | ||
632 | else if (path[0] == '~') | ||
633 | { | ||
634 | const char *home = getenv("HOME"); | ||
635 | if (!home) | ||
636 | return NULL; | ||
637 | strcpy(p, home); | ||
638 | len = strlen(p); | ||
639 | p += len; | ||
640 | p[0] = '/'; | ||
641 | p++; | ||
642 | strcpy(p, path + 2); | ||
643 | } | ||
644 | else | ||
645 | { | ||
646 | if (!getcwd(p, PATH_MAX)) | ||
647 | return NULL; | ||
648 | len = strlen(p); | ||
649 | p += len; | ||
650 | p[0] = '/'; | ||
651 | p++; | ||
652 | strcpy(p, path); | ||
653 | } | ||
654 | |||
655 | return buf; | ||
656 | } | ||
657 | |||
658 | EAPI void | ||
659 | ethumb_thumb_dir_path_set(Ethumb *e, const char *path) | ||
660 | { | ||
661 | char buf[PATH_MAX]; | ||
662 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
663 | |||
664 | DBG("ethumb=%p, path=%s", e, path ? path : ""); | ||
665 | path = _ethumb_build_absolute_path(path, buf); | ||
666 | eina_stringshare_replace(&e->thumb_dir, path); | ||
667 | } | ||
668 | |||
669 | EAPI const char * | ||
670 | ethumb_thumb_dir_path_get(const Ethumb *e) | ||
671 | { | ||
672 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); | ||
673 | |||
674 | return e->thumb_dir; | ||
675 | } | ||
676 | |||
677 | EAPI void | ||
678 | ethumb_thumb_category_set(Ethumb *e, const char *category) | ||
679 | { | ||
680 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
681 | |||
682 | DBG("ethumb=%p, category=%s", e, category ? category : ""); | ||
683 | eina_stringshare_replace(&e->category, category); | ||
684 | } | ||
685 | |||
686 | EAPI const char * | ||
687 | ethumb_thumb_category_get(const Ethumb *e) | ||
688 | { | ||
689 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); | ||
690 | |||
691 | return e->category; | ||
692 | } | ||
693 | |||
694 | EAPI void | ||
695 | ethumb_video_start_set(Ethumb *e, float start) | ||
696 | { | ||
697 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
698 | EINA_SAFETY_ON_FALSE_RETURN(start >= 0.0); | ||
699 | EINA_SAFETY_ON_FALSE_RETURN(start <= 1.0); | ||
700 | |||
701 | DBG("ethumb=%p, video_start=%f", e, start); | ||
702 | e->video.start = start; | ||
703 | } | ||
704 | |||
705 | EAPI float | ||
706 | ethumb_video_start_get(const Ethumb *e) | ||
707 | { | ||
708 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
709 | |||
710 | return e->video.start; | ||
711 | } | ||
712 | |||
713 | EAPI void | ||
714 | ethumb_video_time_set(Ethumb *e, float t) | ||
715 | { | ||
716 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
717 | |||
718 | DBG("ethumb=%p, video_start=%f", e, t); | ||
719 | e->video.time = t; | ||
720 | } | ||
721 | |||
722 | EAPI float | ||
723 | ethumb_video_time_get(const Ethumb *e) | ||
724 | { | ||
725 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
726 | |||
727 | return e->video.time; | ||
728 | } | ||
729 | |||
730 | EAPI void | ||
731 | ethumb_video_interval_set(Ethumb *e, float interval) | ||
732 | { | ||
733 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
734 | |||
735 | DBG("ethumb=%p, video_interval=%f", e, interval); | ||
736 | e->video.interval = interval; | ||
737 | } | ||
738 | |||
739 | EAPI float | ||
740 | ethumb_video_interval_get(const Ethumb *e) | ||
741 | { | ||
742 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
743 | |||
744 | return e->video.interval; | ||
745 | } | ||
746 | |||
747 | EAPI void | ||
748 | ethumb_video_ntimes_set(Ethumb *e, unsigned int ntimes) | ||
749 | { | ||
750 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
751 | EINA_SAFETY_ON_FALSE_RETURN(ntimes > 0); | ||
752 | |||
753 | DBG("ethumb=%p, video_ntimes=%d", e, ntimes); | ||
754 | e->video.ntimes = ntimes; | ||
755 | } | ||
756 | |||
757 | EAPI unsigned int | ||
758 | ethumb_video_ntimes_get(const Ethumb *e) | ||
759 | { | ||
760 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
761 | |||
762 | return e->video.ntimes; | ||
763 | } | ||
764 | |||
765 | EAPI void | ||
766 | ethumb_video_fps_set(Ethumb *e, unsigned int fps) | ||
767 | { | ||
768 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
769 | EINA_SAFETY_ON_FALSE_RETURN(fps > 0); | ||
770 | |||
771 | DBG("ethumb=%p, video_fps=%d", e, fps); | ||
772 | e->video.fps = fps; | ||
773 | } | ||
774 | |||
775 | EAPI unsigned int | ||
776 | ethumb_video_fps_get(const Ethumb *e) | ||
777 | { | ||
778 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
779 | |||
780 | return e->video.fps; | ||
781 | } | ||
782 | |||
783 | EAPI void | ||
784 | ethumb_document_page_set(Ethumb *e, unsigned int page) | ||
785 | { | ||
786 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
787 | |||
788 | DBG("ethumb=%p, document_page=%d", e, page); | ||
789 | e->document.page = page; | ||
790 | } | ||
791 | |||
792 | EAPI unsigned int | ||
793 | ethumb_document_page_get(const Ethumb *e) | ||
794 | { | ||
795 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
796 | |||
797 | return e->document.page; | ||
798 | } | ||
799 | |||
800 | EAPI Eina_Bool | ||
801 | ethumb_file_set(Ethumb *e, const char *path, const char *key) | ||
802 | { | ||
803 | char buf[PATH_MAX]; | ||
804 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
805 | |||
806 | eina_stringshare_replace(&e->thumb_path, NULL); | ||
807 | eina_stringshare_replace(&e->thumb_key, NULL); | ||
808 | |||
809 | DBG("ethumb=%p, path=%s, key=%s", e, path ? path : "", key ? key : ""); | ||
810 | if (path && access(path, R_OK)) | ||
811 | { | ||
812 | ERR("couldn't access file \"%s\"", path); | ||
813 | return EINA_FALSE; | ||
814 | } | ||
815 | |||
816 | path = _ethumb_build_absolute_path(path, buf); | ||
817 | eina_stringshare_replace(&e->src_hash, NULL); | ||
818 | eina_stringshare_replace(&e->src_path, path); | ||
819 | eina_stringshare_replace(&e->src_key, key); | ||
820 | |||
821 | return EINA_TRUE; | ||
822 | } | ||
823 | |||
824 | EAPI void | ||
825 | ethumb_file_get(const Ethumb *e, const char **path, const char **key) | ||
826 | { | ||
827 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
828 | |||
829 | if (path) *path = e->src_path; | ||
830 | if (key) *key = e->src_key; | ||
831 | } | ||
832 | |||
833 | static const char ACCEPTABLE_URI_CHARS[96] = { | ||
834 | /* ! " # $ % & ' ( ) * + , - . / */ | ||
835 | 0x00,0x3F,0x20,0x20,0x28,0x00,0x2C,0x3F,0x3F,0x3F,0x3F,0x2A,0x28,0x3F,0x3F,0x1C, | ||
836 | /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ | ||
837 | 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x38,0x20,0x20,0x2C,0x20,0x20, | ||
838 | /* @ A B C D E F G H I J K L M N O */ | ||
839 | 0x38,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, | ||
840 | /* P Q R S T U V W X Y Z [ \ ] ^ _ */ | ||
841 | 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x20,0x3F, | ||
842 | /* ` a b c d e f g h i j k l m n o */ | ||
843 | 0x20,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F, | ||
844 | /* p q r s t u v w x y z { | } ~ DEL */ | ||
845 | 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x3F,0x20 | ||
846 | }; | ||
847 | |||
848 | static const char * | ||
849 | _ethumb_generate_hash(const char *file) | ||
850 | { | ||
851 | int n; | ||
852 | MD5_CTX ctx; | ||
853 | char md5out[(2 * MD5_HASHBYTES) + 1]; | ||
854 | unsigned char hash[MD5_HASHBYTES]; | ||
855 | static const char hex[] = "0123456789abcdef"; | ||
856 | |||
857 | char *uri; | ||
858 | char *t; | ||
859 | const unsigned char *c; | ||
860 | |||
861 | #ifdef HAVE_XATTR | ||
862 | ssize_t length; | ||
863 | |||
864 | length = getxattr(file, "user.e.md5", NULL, 0); | ||
865 | |||
866 | if (length > 0) | ||
867 | { | ||
868 | char *tmp; | ||
869 | |||
870 | tmp = alloca(length); | ||
871 | length = getxattr(file, "user.e.md5", tmp, length); | ||
872 | |||
873 | /* check if we have at least something that look like a md5 hash */ | ||
874 | if (length > 0 && (length == MD5_HASHBYTES * 2 + 1)) | ||
875 | { | ||
876 | tmp[length] = '\0'; | ||
877 | return eina_stringshare_add(tmp); | ||
878 | } | ||
879 | } | ||
880 | #endif | ||
881 | |||
882 | #define _check_uri_char(c) \ | ||
883 | ((c) >= 32 && (c) < 128 && (ACCEPTABLE_URI_CHARS[(c) - 32] & 0x08)) | ||
884 | |||
885 | EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL); | ||
886 | |||
887 | uri = alloca(3 * strlen(file) + 9); | ||
888 | memcpy(uri, "file://", sizeof("file://") - 1); | ||
889 | t = uri + sizeof("file://") - 1; | ||
890 | |||
891 | for (c = (const unsigned char *)file; *c != '\0'; c++) | ||
892 | { | ||
893 | if (!_check_uri_char(*c)) | ||
894 | { | ||
895 | *t++ = '%'; | ||
896 | *t++ = hex[*c >> 4]; | ||
897 | *t++ = hex[*c & 15]; | ||
898 | } | ||
899 | else | ||
900 | *t++ = *c; | ||
901 | } | ||
902 | *t = '\0'; | ||
903 | |||
904 | #undef _check_uri_char | ||
905 | |||
906 | MD5Init (&ctx); | ||
907 | MD5Update (&ctx, (unsigned char const*)uri, (unsigned)strlen (uri)); | ||
908 | MD5Final (hash, &ctx); | ||
909 | |||
910 | for (n = 0; n < MD5_HASHBYTES; n++) | ||
911 | { | ||
912 | md5out[2 * n] = hex[hash[n] >> 4]; | ||
913 | md5out[2 * n + 1] = hex[hash[n] & 0x0f]; | ||
914 | } | ||
915 | md5out[2 * n] = '\0'; | ||
916 | |||
917 | #ifdef HAVE_XATTR | ||
918 | setxattr(file, "user.e.md5", md5out, 2 * n + 1, 0); | ||
919 | #endif | ||
920 | |||
921 | DBG("md5=%s, file=%s", md5out, file); | ||
922 | return eina_stringshare_add(md5out); | ||
923 | } | ||
924 | |||
925 | static int | ||
926 | _ethumb_file_check_fdo(Ethumb *e) | ||
927 | { | ||
928 | if (!((e->tw == THUMB_SIZE_NORMAL && e->th == THUMB_SIZE_NORMAL) || | ||
929 | (e->tw == THUMB_SIZE_LARGE && e->th == THUMB_SIZE_LARGE))) | ||
930 | return 0; | ||
931 | |||
932 | if (e->format != ETHUMB_THUMB_FDO) | ||
933 | return 0; | ||
934 | |||
935 | if (e->aspect != ETHUMB_THUMB_KEEP_ASPECT) | ||
936 | return 0; | ||
937 | |||
938 | if (e->frame) | ||
939 | return 0; | ||
940 | |||
941 | return 1; | ||
942 | } | ||
943 | |||
944 | static const char * | ||
945 | _ethumb_file_generate_custom_category(Ethumb *e) | ||
946 | { | ||
947 | char buf[PATH_MAX]; | ||
948 | const char *aspect, *format; | ||
949 | const char *frame; | ||
950 | |||
951 | if (e->aspect == ETHUMB_THUMB_KEEP_ASPECT) | ||
952 | aspect = "keep_aspect"; | ||
953 | else if (e->aspect == ETHUMB_THUMB_IGNORE_ASPECT) | ||
954 | aspect = "ignore_aspect"; | ||
955 | else | ||
956 | aspect = "crop"; | ||
957 | |||
958 | if (e->format == ETHUMB_THUMB_FDO) | ||
959 | format = "png"; | ||
960 | else if (e->format == ETHUMB_THUMB_JPEG) | ||
961 | format = "jpg"; | ||
962 | else | ||
963 | format = "eet"; | ||
964 | |||
965 | if (e->frame) | ||
966 | frame = "-framed"; | ||
967 | else | ||
968 | frame = ""; | ||
969 | |||
970 | snprintf(buf, sizeof(buf), "%dx%d-%s%s-%s", | ||
971 | e->tw, e->th, aspect, frame, format); | ||
972 | |||
973 | return eina_stringshare_add(buf); | ||
974 | } | ||
975 | |||
976 | static void | ||
977 | _ethumb_file_generate_path(Ethumb *e) | ||
978 | { | ||
979 | char buf[PATH_MAX]; | ||
980 | const char *thumb_dir, *category; | ||
981 | const char *ext; | ||
982 | int fdo_format; | ||
983 | |||
984 | fdo_format = _ethumb_file_check_fdo(e); | ||
985 | |||
986 | if (e->thumb_dir) | ||
987 | thumb_dir = eina_stringshare_ref(e->thumb_dir); | ||
988 | else | ||
989 | thumb_dir = eina_stringshare_ref(_home_thumb_dir); | ||
990 | |||
991 | if (e->category) | ||
992 | category = eina_stringshare_ref(e->category); | ||
993 | else if (!fdo_format) | ||
994 | category = _ethumb_file_generate_custom_category(e); | ||
995 | else | ||
996 | { | ||
997 | if (e->tw == THUMB_SIZE_NORMAL) | ||
998 | category = eina_stringshare_ref(_thumb_category_normal); | ||
999 | else if (e->tw == THUMB_SIZE_LARGE) | ||
1000 | category = eina_stringshare_ref(_thumb_category_large); | ||
1001 | else | ||
1002 | { | ||
1003 | ERR("fdo_format but size %d is not NORMAL (%d) or LARGE (%d)?", | ||
1004 | e->tw, THUMB_SIZE_NORMAL, THUMB_SIZE_LARGE); | ||
1005 | category = "unknown"; | ||
1006 | } | ||
1007 | } | ||
1008 | |||
1009 | if (e->format == ETHUMB_THUMB_FDO) | ||
1010 | ext = "png"; | ||
1011 | else if (e->format == ETHUMB_THUMB_JPEG) | ||
1012 | ext = "jpg"; | ||
1013 | else | ||
1014 | ext = "eet"; | ||
1015 | |||
1016 | if (!e->src_hash) | ||
1017 | { | ||
1018 | char *fullname; | ||
1019 | |||
1020 | fullname = ecore_file_realpath(e->src_path); | ||
1021 | e->src_hash = _ethumb_generate_hash(fullname); | ||
1022 | free(fullname); | ||
1023 | } | ||
1024 | snprintf(buf, sizeof(buf), "%s/%s/%s.%s", thumb_dir, category, e->src_hash, ext); | ||
1025 | DBG("ethumb=%p, path=%s", e, buf); | ||
1026 | eina_stringshare_replace(&e->thumb_path, buf); | ||
1027 | if (e->format == ETHUMB_THUMB_EET) | ||
1028 | eina_stringshare_replace(&e->thumb_key, "thumbnail"); | ||
1029 | else | ||
1030 | { | ||
1031 | eina_stringshare_del(e->thumb_key); | ||
1032 | e->thumb_key = NULL; | ||
1033 | } | ||
1034 | |||
1035 | eina_stringshare_del(thumb_dir); | ||
1036 | eina_stringshare_del(category); | ||
1037 | } | ||
1038 | |||
1039 | EAPI void | ||
1040 | ethumb_file_free(Ethumb *e) | ||
1041 | { | ||
1042 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
1043 | DBG("ethumb=%p", e); | ||
1044 | |||
1045 | eina_stringshare_replace(&e->src_hash, NULL); | ||
1046 | eina_stringshare_replace(&e->src_path, NULL); | ||
1047 | eina_stringshare_replace(&e->src_key, NULL); | ||
1048 | eina_stringshare_replace(&e->thumb_path, NULL); | ||
1049 | eina_stringshare_replace(&e->thumb_key, NULL); | ||
1050 | } | ||
1051 | |||
1052 | EAPI void | ||
1053 | ethumb_thumb_path_set(Ethumb *e, const char *path, const char *key) | ||
1054 | { | ||
1055 | char buf[PATH_MAX]; | ||
1056 | |||
1057 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
1058 | DBG("ethumb=%p, path=%s, key=%s", e, path ? path : "", key ? key : ""); | ||
1059 | |||
1060 | if (!path) | ||
1061 | { | ||
1062 | eina_stringshare_replace(&e->thumb_path, NULL); | ||
1063 | eina_stringshare_replace(&e->thumb_key, NULL); | ||
1064 | } | ||
1065 | else | ||
1066 | { | ||
1067 | path = _ethumb_build_absolute_path(path, buf); | ||
1068 | eina_stringshare_replace(&e->thumb_path, path); | ||
1069 | eina_stringshare_replace(&e->thumb_key, key); | ||
1070 | } | ||
1071 | } | ||
1072 | |||
1073 | EAPI void | ||
1074 | ethumb_thumb_path_get(Ethumb *e, const char **path, const char **key) | ||
1075 | { | ||
1076 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
1077 | if (!e->thumb_path) | ||
1078 | _ethumb_file_generate_path(e); | ||
1079 | |||
1080 | if (path) *path = e->thumb_path; | ||
1081 | if (key) *key = e->thumb_key; | ||
1082 | } | ||
1083 | |||
1084 | EAPI void | ||
1085 | ethumb_thumb_hash(Ethumb *e) | ||
1086 | { | ||
1087 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
1088 | if (!e->src_hash) | ||
1089 | { | ||
1090 | char *fullname; | ||
1091 | |||
1092 | fullname = ecore_file_realpath(e->src_path); | ||
1093 | e->src_hash = _ethumb_generate_hash(fullname); | ||
1094 | free(fullname); | ||
1095 | } | ||
1096 | } | ||
1097 | |||
1098 | EAPI void | ||
1099 | ethumb_thumb_hash_copy(Ethumb *dst, const Ethumb *src) | ||
1100 | { | ||
1101 | EINA_SAFETY_ON_NULL_RETURN(dst); | ||
1102 | EINA_SAFETY_ON_NULL_RETURN(src); | ||
1103 | |||
1104 | if (src == dst) return ; | ||
1105 | |||
1106 | eina_stringshare_del(dst->src_hash); | ||
1107 | dst->src_hash = eina_stringshare_ref(src->src_hash); | ||
1108 | } | ||
1109 | |||
1110 | EAPI void | ||
1111 | ethumb_calculate_aspect_from_ratio(Ethumb *e, float ia, int *w, int *h) | ||
1112 | { | ||
1113 | float a; | ||
1114 | |||
1115 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
1116 | |||
1117 | *w = e->tw; | ||
1118 | *h = e->th; | ||
1119 | |||
1120 | if (ia == 0) | ||
1121 | return; | ||
1122 | |||
1123 | a = e->tw / (float)e->th; | ||
1124 | |||
1125 | if (e->aspect == ETHUMB_THUMB_KEEP_ASPECT) | ||
1126 | { | ||
1127 | if ((ia > a && e->tw > 0) || e->th <= 0) | ||
1128 | *h = e->tw / ia; | ||
1129 | else | ||
1130 | *w = e->th * ia; | ||
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | EAPI void | ||
1135 | ethumb_calculate_aspect(Ethumb *e, int iw, int ih, int *w, int *h) | ||
1136 | { | ||
1137 | float ia; | ||
1138 | |||
1139 | if (ih == 0) | ||
1140 | return; | ||
1141 | |||
1142 | ia = iw / (float)ih; | ||
1143 | |||
1144 | ethumb_calculate_aspect_from_ratio(e, ia, w, h); | ||
1145 | } | ||
1146 | |||
1147 | EAPI void | ||
1148 | ethumb_calculate_fill_from_ratio(Ethumb *e, float ia, int *fx, int *fy, int *fw, int *fh) | ||
1149 | { | ||
1150 | float a; | ||
1151 | |||
1152 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
1153 | |||
1154 | *fw = e->tw; | ||
1155 | *fh = e->th; | ||
1156 | *fx = 0; | ||
1157 | *fy = 0; | ||
1158 | |||
1159 | if (ia == 0) | ||
1160 | return; | ||
1161 | |||
1162 | a = e->tw / (float)e->th; | ||
1163 | |||
1164 | if (e->aspect == ETHUMB_THUMB_CROP) | ||
1165 | { | ||
1166 | if ((ia > a && e->tw > 0) || e->th <= 0) | ||
1167 | *fw = e->th * ia; | ||
1168 | else | ||
1169 | *fh = e->tw / ia; | ||
1170 | |||
1171 | *fx = - e->crop_x * (*fw - e->tw); | ||
1172 | *fy = - e->crop_y * (*fh - e->th); | ||
1173 | } | ||
1174 | else if (e->aspect == ETHUMB_THUMB_KEEP_ASPECT) | ||
1175 | { | ||
1176 | if ((ia > a && e->tw > 0) || e->th <= 0) | ||
1177 | *fh = e->tw / ia; | ||
1178 | else | ||
1179 | *fw = e->th * ia; | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | EAPI void | ||
1184 | ethumb_calculate_fill(Ethumb *e, int iw, int ih, int *fx, int *fy, int *fw, int *fh) | ||
1185 | { | ||
1186 | float ia; | ||
1187 | |||
1188 | if (ih == 0) | ||
1189 | return; | ||
1190 | |||
1191 | ia = iw / (float)ih; | ||
1192 | |||
1193 | ethumb_calculate_fill_from_ratio(e, ia, fx, fy, fw, fh); | ||
1194 | } | ||
1195 | |||
1196 | static Eina_Bool | ||
1197 | _ethumb_plugin_generate(Ethumb *e) | ||
1198 | { | ||
1199 | const char *extp; | ||
1200 | char ext[PATH_MAX]; | ||
1201 | Ethumb_Plugin *plugin; | ||
1202 | int i; | ||
1203 | |||
1204 | extp = strrchr(e->src_path, '.'); | ||
1205 | if (!extp) | ||
1206 | { | ||
1207 | ERR("could not get extension for file \"%s\"", e->src_path); | ||
1208 | return EINA_FALSE; | ||
1209 | } | ||
1210 | |||
1211 | for (i = 0; extp[i] != '\0'; i++) | ||
1212 | ext[i] = tolower(extp[i + 1]); | ||
1213 | |||
1214 | plugin = eina_hash_find(_plugins_ext, ext); | ||
1215 | if (!plugin) | ||
1216 | { | ||
1217 | DBG("no plugin for extension: \"%s\"", ext); | ||
1218 | return EINA_FALSE; | ||
1219 | } | ||
1220 | |||
1221 | if (e->frame) | ||
1222 | evas_object_hide(e->frame->edje); | ||
1223 | else | ||
1224 | evas_object_hide(e->img); | ||
1225 | |||
1226 | e->plugin = plugin; | ||
1227 | e->pdata = plugin->thumb_generate(e); | ||
1228 | |||
1229 | return EINA_TRUE; | ||
1230 | } | ||
1231 | |||
1232 | EAPI Eina_Bool | ||
1233 | ethumb_plugin_image_resize(Ethumb *e, int w, int h) | ||
1234 | { | ||
1235 | Evas_Object *img; | ||
1236 | |||
1237 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
1238 | |||
1239 | img = e->img; | ||
1240 | |||
1241 | if (e->frame) | ||
1242 | { | ||
1243 | edje_extern_object_min_size_set(img, w, h); | ||
1244 | edje_extern_object_max_size_set(img, w, h); | ||
1245 | edje_object_calc_force(e->frame->edje); | ||
1246 | evas_object_move(e->frame->edje, 0, 0); | ||
1247 | evas_object_resize(e->frame->edje, w, h); | ||
1248 | } | ||
1249 | else | ||
1250 | { | ||
1251 | evas_object_move(img, 0, 0); | ||
1252 | evas_object_resize(img, w, h); | ||
1253 | } | ||
1254 | |||
1255 | evas_object_image_size_set(e->o, w, h); | ||
1256 | ecore_evas_resize(e->sub_ee, w, h); | ||
1257 | |||
1258 | e->rw = w; | ||
1259 | e->rh = h; | ||
1260 | |||
1261 | return EINA_TRUE; | ||
1262 | } | ||
1263 | |||
1264 | EAPI Eina_Bool | ||
1265 | ethumb_image_save(Ethumb *e) | ||
1266 | { | ||
1267 | Eina_Bool r; | ||
1268 | char *dname; | ||
1269 | char flags[256]; | ||
1270 | |||
1271 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
1272 | |||
1273 | evas_damage_rectangle_add(e->sub_e, 0, 0, e->rw, e->rh); | ||
1274 | evas_render(e->sub_e); | ||
1275 | |||
1276 | if (!e->thumb_path) | ||
1277 | _ethumb_file_generate_path(e); | ||
1278 | |||
1279 | if (!e->thumb_path) | ||
1280 | { | ||
1281 | ERR("could not create file path..."); | ||
1282 | return EINA_FALSE; | ||
1283 | } | ||
1284 | |||
1285 | dname = ecore_file_dir_get(e->thumb_path); | ||
1286 | r = ecore_file_mkpath(dname); | ||
1287 | free(dname); | ||
1288 | if (!r) | ||
1289 | { | ||
1290 | ERR("could not create directory '%s'", dname); | ||
1291 | return EINA_FALSE; | ||
1292 | } | ||
1293 | |||
1294 | snprintf(flags, sizeof(flags), "quality=%d compress=%d", | ||
1295 | e->quality, e->compress); | ||
1296 | r = evas_object_image_save(e->o, e->thumb_path, e->thumb_key, flags); | ||
1297 | |||
1298 | if (!r) | ||
1299 | { | ||
1300 | ERR("could not save image: path=%s, key=%s", e->thumb_path, | ||
1301 | e->thumb_key); | ||
1302 | return EINA_FALSE; | ||
1303 | } | ||
1304 | |||
1305 | return EINA_TRUE; | ||
1306 | } | ||
1307 | |||
1308 | static void | ||
1309 | _ethumb_image_orient(Ethumb *e, int orientation) | ||
1310 | { | ||
1311 | Evas_Object *img = e->img, *tmp; | ||
1312 | unsigned int *data, *data2, *to, *from, *p1, *p2, pt; | ||
1313 | int x, y, w, hw, iw, ih, tw, th; | ||
1314 | const char *file, *key; | ||
1315 | |||
1316 | evas_object_image_size_get(img, &iw, &ih); | ||
1317 | evas_object_image_load_size_get(img, &tw, &th); | ||
1318 | evas_object_image_file_get(img, &file, &key); | ||
1319 | data = evas_object_image_data_get(img, 1); | ||
1320 | |||
1321 | switch (orientation) | ||
1322 | { | ||
1323 | case ETHUMB_THUMB_FLIP_HORIZONTAL: | ||
1324 | for (y = 0; y < ih; y++) | ||
1325 | { | ||
1326 | p1 = data + (y * iw); | ||
1327 | p2 = data + ((y + 1) * iw) - 1; | ||
1328 | for (x = 0; x < (iw >> 1); x++) | ||
1329 | { | ||
1330 | pt = *p1; | ||
1331 | *p1 = *p2; | ||
1332 | *p2 = pt; | ||
1333 | p1++; | ||
1334 | p2--; | ||
1335 | } | ||
1336 | } | ||
1337 | evas_object_image_data_set(img, data); | ||
1338 | evas_object_image_data_update_add(img, 0, 0, iw, ih); | ||
1339 | return; | ||
1340 | case ETHUMB_THUMB_FLIP_VERTICAL: | ||
1341 | for (y = 0; y < (ih >> 1); y++) | ||
1342 | { | ||
1343 | p1 = data + (y * iw); | ||
1344 | p2 = data + ((ih - 1 - y) * iw); | ||
1345 | for (x = 0; x < iw; x++) | ||
1346 | { | ||
1347 | pt = *p1; | ||
1348 | *p1 = *p2; | ||
1349 | *p2 = pt; | ||
1350 | p1++; | ||
1351 | p2++; | ||
1352 | } | ||
1353 | } | ||
1354 | evas_object_image_data_set(img, data); | ||
1355 | evas_object_image_data_update_add(img, 0, 0, iw, ih); | ||
1356 | return; | ||
1357 | case ETHUMB_THUMB_ROTATE_180: | ||
1358 | hw = iw * ih; | ||
1359 | x = (hw / 2); | ||
1360 | p1 = data; | ||
1361 | p2 = data + hw - 1; | ||
1362 | for (; --x > 0;) | ||
1363 | { | ||
1364 | pt = *p1; | ||
1365 | *p1 = *p2; | ||
1366 | *p2 = pt; | ||
1367 | p1++; | ||
1368 | p2--; | ||
1369 | } | ||
1370 | evas_object_image_data_set(img, data); | ||
1371 | evas_object_image_data_update_add(img, 0, 0, iw, ih); | ||
1372 | return; | ||
1373 | } | ||
1374 | |||
1375 | tmp = evas_object_image_add(evas_object_evas_get(img)); | ||
1376 | evas_object_image_load_size_set(tmp, tw, th); | ||
1377 | evas_object_image_file_set(tmp, file, key); | ||
1378 | data2 = evas_object_image_data_get(tmp, 0); | ||
1379 | |||
1380 | w = ih; | ||
1381 | ih = iw; | ||
1382 | iw = w; | ||
1383 | hw = w * ih; | ||
1384 | |||
1385 | evas_object_image_size_set(img, iw, ih); | ||
1386 | data = evas_object_image_data_get(img, 1); | ||
1387 | |||
1388 | switch (orientation) | ||
1389 | { | ||
1390 | case ETHUMB_THUMB_FLIP_TRANSPOSE: | ||
1391 | to = data; | ||
1392 | hw = -hw + 1; | ||
1393 | break; | ||
1394 | case ETHUMB_THUMB_FLIP_TRANSVERSE: | ||
1395 | to = data + hw - 1; | ||
1396 | w = -w; | ||
1397 | hw = hw - 1; | ||
1398 | break; | ||
1399 | case ETHUMB_THUMB_ROTATE_90_CW: | ||
1400 | to = data + w - 1; | ||
1401 | hw = -hw - 1; | ||
1402 | break; | ||
1403 | case ETHUMB_THUMB_ROTATE_90_CCW: | ||
1404 | to = data + hw - w; | ||
1405 | w = -w; | ||
1406 | hw = hw + 1; | ||
1407 | break; | ||
1408 | default: | ||
1409 | ERR("unknown orient %d", orientation); | ||
1410 | evas_object_del(tmp); | ||
1411 | evas_object_image_data_set(img, data); // give it back | ||
1412 | return; | ||
1413 | } | ||
1414 | from = data2; | ||
1415 | for (x = iw; --x >= 0;) | ||
1416 | { | ||
1417 | for (y = ih; --y >= 0;) | ||
1418 | { | ||
1419 | *to = *from; | ||
1420 | from++; | ||
1421 | to += w; | ||
1422 | } | ||
1423 | to += hw; | ||
1424 | } | ||
1425 | evas_object_del(tmp); | ||
1426 | evas_object_image_data_set(img, data); | ||
1427 | evas_object_image_data_update_add(img, 0, 0, iw, ih); | ||
1428 | } | ||
1429 | |||
1430 | static int | ||
1431 | _ethumb_image_load(Ethumb *e) | ||
1432 | { | ||
1433 | int error; | ||
1434 | Evas_Coord w, h, ww, hh, fx, fy, fw, fh; | ||
1435 | Evas_Object *img; | ||
1436 | int orientation = ETHUMB_THUMB_ORIENT_NONE; | ||
1437 | |||
1438 | img = e->img; | ||
1439 | |||
1440 | if (e->frame) | ||
1441 | evas_object_hide(e->frame->edje); | ||
1442 | else | ||
1443 | evas_object_hide(img); | ||
1444 | evas_object_image_file_set(img, NULL, NULL); | ||
1445 | evas_object_image_load_size_set(img, e->tw, e->th); | ||
1446 | evas_object_image_file_set(img, e->src_path, e->src_key); | ||
1447 | |||
1448 | if (e->frame) | ||
1449 | evas_object_show(e->frame->edje); | ||
1450 | else | ||
1451 | evas_object_show(img); | ||
1452 | |||
1453 | error = evas_object_image_load_error_get(img); | ||
1454 | if (error != EVAS_LOAD_ERROR_NONE) | ||
1455 | { | ||
1456 | ERR("could not load image '%s': %d", e->src_path, error); | ||
1457 | return 0; | ||
1458 | } | ||
1459 | |||
1460 | if (e->orientation == ETHUMB_THUMB_ORIENT_ORIGINAL) | ||
1461 | { | ||
1462 | /* TODO: rewrite to not need libexif just to get this */ | ||
1463 | #ifdef HAVE_LIBEXIF | ||
1464 | ExifData *exif = exif_data_new_from_file(e->src_path); | ||
1465 | ExifEntry *entry = NULL; | ||
1466 | ExifByteOrder bo; | ||
1467 | int o = 0; | ||
1468 | |||
1469 | if (exif) | ||
1470 | { | ||
1471 | entry = exif_data_get_entry(exif, EXIF_TAG_ORIENTATION); | ||
1472 | if (entry) | ||
1473 | { | ||
1474 | bo = exif_data_get_byte_order(exif); | ||
1475 | o = exif_get_short(entry->data, bo); | ||
1476 | } | ||
1477 | exif_data_free(exif); | ||
1478 | switch (o) | ||
1479 | { | ||
1480 | case 2: | ||
1481 | orientation = ETHUMB_THUMB_FLIP_HORIZONTAL; | ||
1482 | break; | ||
1483 | case 3: | ||
1484 | orientation = ETHUMB_THUMB_ROTATE_180; | ||
1485 | break; | ||
1486 | case 4: | ||
1487 | orientation = ETHUMB_THUMB_FLIP_VERTICAL; | ||
1488 | break; | ||
1489 | case 5: | ||
1490 | orientation = ETHUMB_THUMB_FLIP_TRANSPOSE; | ||
1491 | break; | ||
1492 | case 6: | ||
1493 | orientation = ETHUMB_THUMB_ROTATE_90_CW; | ||
1494 | break; | ||
1495 | case 7: | ||
1496 | orientation = ETHUMB_THUMB_FLIP_TRANSVERSE; | ||
1497 | break; | ||
1498 | case 8: | ||
1499 | orientation = ETHUMB_THUMB_ROTATE_90_CCW; | ||
1500 | break; | ||
1501 | } | ||
1502 | } | ||
1503 | #endif | ||
1504 | } | ||
1505 | |||
1506 | if (orientation != ETHUMB_THUMB_ORIENT_NONE) | ||
1507 | _ethumb_image_orient(e, orientation); | ||
1508 | |||
1509 | evas_object_image_size_get(img, &w, &h); | ||
1510 | if ((w <= 0) || (h <= 0)) | ||
1511 | return 0; | ||
1512 | |||
1513 | ethumb_calculate_aspect(e, w, h, &ww, &hh); | ||
1514 | |||
1515 | if (e->frame) | ||
1516 | { | ||
1517 | edje_extern_object_min_size_set(img, ww, hh); | ||
1518 | edje_extern_object_max_size_set(img, ww, hh); | ||
1519 | edje_object_calc_force(e->frame->edje); | ||
1520 | evas_object_move(e->frame->edje, 0, 0); | ||
1521 | evas_object_resize(e->frame->edje, ww, hh); | ||
1522 | } | ||
1523 | else | ||
1524 | { | ||
1525 | evas_object_move(img, 0, 0); | ||
1526 | evas_object_resize(img, ww, hh); | ||
1527 | } | ||
1528 | |||
1529 | ethumb_calculate_fill(e, w, h, &fx, &fy, &fw, &fh); | ||
1530 | evas_object_image_fill_set(img, fx, fy, fw, fh); | ||
1531 | |||
1532 | evas_object_image_size_set(e->o, ww, hh); | ||
1533 | ecore_evas_resize(e->sub_ee, ww, hh); | ||
1534 | |||
1535 | e->rw = ww; | ||
1536 | e->rh = hh; | ||
1537 | |||
1538 | return 1; | ||
1539 | } | ||
1540 | |||
1541 | static Eina_Bool | ||
1542 | _ethumb_finished_idler_cb(void *data) | ||
1543 | { | ||
1544 | Ethumb *e = data; | ||
1545 | |||
1546 | e->finished_cb(e->cb_data, e, e->cb_result); | ||
1547 | if (e->cb_data_free) | ||
1548 | e->cb_data_free(e->cb_data); | ||
1549 | e->finished_idler = NULL; | ||
1550 | e->finished_cb = NULL; | ||
1551 | e->cb_data = NULL; | ||
1552 | e->cb_data_free = NULL; | ||
1553 | |||
1554 | return EINA_FALSE; | ||
1555 | } | ||
1556 | |||
1557 | EAPI void | ||
1558 | ethumb_finished_callback_call(Ethumb *e, int result) | ||
1559 | { | ||
1560 | EINA_SAFETY_ON_NULL_RETURN(e); | ||
1561 | |||
1562 | e->cb_result = result; | ||
1563 | if (e->finished_idler) | ||
1564 | ecore_idler_del(e->finished_idler); | ||
1565 | e->finished_idler = ecore_idler_add(_ethumb_finished_idler_cb, e); | ||
1566 | e->plugin = NULL; | ||
1567 | e->pdata = NULL; | ||
1568 | } | ||
1569 | |||
1570 | EAPI Eina_Bool | ||
1571 | ethumb_generate(Ethumb *e, Ethumb_Generate_Cb finished_cb, const void *data, Eina_Free_Cb free_data) | ||
1572 | { | ||
1573 | int r; | ||
1574 | |||
1575 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
1576 | EINA_SAFETY_ON_NULL_RETURN_VAL(finished_cb, 0); | ||
1577 | DBG("ethumb=%p, finished_cb=%p, data=%p, free_data=%p, path=%s, key=%s", | ||
1578 | e, finished_cb, data, free_data, | ||
1579 | e->src_path ? e->src_path : "", e->src_key ? e->src_key : ""); | ||
1580 | |||
1581 | if (e->finished_idler) | ||
1582 | { | ||
1583 | ERR("thumbnail generation already in progress."); | ||
1584 | return EINA_FALSE; | ||
1585 | } | ||
1586 | if (e->pdata) | ||
1587 | { | ||
1588 | e->plugin->thumb_cancel(e, e->pdata); | ||
1589 | e->pdata = NULL; | ||
1590 | e->plugin = NULL; | ||
1591 | } | ||
1592 | |||
1593 | e->finished_cb = finished_cb; | ||
1594 | e->cb_data = (void *)data; | ||
1595 | e->cb_data_free = free_data; | ||
1596 | |||
1597 | if (!e->src_path) | ||
1598 | { | ||
1599 | ERR("no file set."); | ||
1600 | ethumb_finished_callback_call(e, 0); | ||
1601 | return EINA_FALSE; | ||
1602 | } | ||
1603 | |||
1604 | r = _ethumb_plugin_generate(e); | ||
1605 | DBG("ethumb plugin generate: %i: %p\n", r, e->pdata); | ||
1606 | if (r) | ||
1607 | { | ||
1608 | return EINA_TRUE; | ||
1609 | } | ||
1610 | |||
1611 | if (!_ethumb_image_load(e)) | ||
1612 | { | ||
1613 | ERR("could not load input image: file=%s, key=%s", | ||
1614 | e->src_path, e->src_key); | ||
1615 | ethumb_finished_callback_call(e, 0); | ||
1616 | return EINA_FALSE; | ||
1617 | } | ||
1618 | |||
1619 | r = ethumb_image_save(e); | ||
1620 | |||
1621 | ethumb_finished_callback_call(e, r); | ||
1622 | |||
1623 | return EINA_TRUE; | ||
1624 | } | ||
1625 | |||
1626 | EAPI Eina_Bool | ||
1627 | ethumb_exists(Ethumb *e) | ||
1628 | { | ||
1629 | struct stat thumb, src; | ||
1630 | int r_thumb, r_src; | ||
1631 | Eina_Bool r = EINA_FALSE; | ||
1632 | |||
1633 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0); | ||
1634 | EINA_SAFETY_ON_NULL_RETURN_VAL(e->src_path, 0); | ||
1635 | DBG("ethumb=%p, path=%s", e, e->src_path ? e->src_path : ""); | ||
1636 | |||
1637 | if (!e->thumb_path) | ||
1638 | _ethumb_file_generate_path(e); | ||
1639 | |||
1640 | EINA_SAFETY_ON_NULL_RETURN_VAL(e->thumb_path, 0); | ||
1641 | |||
1642 | r_thumb = stat(e->thumb_path, &thumb); | ||
1643 | r_src = stat(e->src_path, &src); | ||
1644 | |||
1645 | EINA_SAFETY_ON_TRUE_RETURN_VAL(r_src, 0); | ||
1646 | |||
1647 | if (r_thumb && errno != ENOENT) | ||
1648 | ERR("could not access file \"%s\": %s", e->thumb_path, strerror(errno)); | ||
1649 | else if (!r_thumb && thumb.st_mtime > src.st_mtime) | ||
1650 | r = EINA_TRUE; | ||
1651 | |||
1652 | return r; | ||
1653 | } | ||
1654 | |||
1655 | EAPI Evas * | ||
1656 | ethumb_evas_get(const Ethumb *e) | ||
1657 | { | ||
1658 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); | ||
1659 | |||
1660 | return e->sub_e; | ||
1661 | } | ||
1662 | |||
1663 | EAPI Ecore_Evas * | ||
1664 | ethumb_ecore_evas_get(const Ethumb *e) | ||
1665 | { | ||
1666 | EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL); | ||
1667 | |||
1668 | return e->sub_ee; | ||
1669 | } | ||
1670 | |||
1671 | EAPI Ethumb * | ||
1672 | ethumb_dup(const Ethumb *e) | ||
1673 | { | ||
1674 | Ecore_Evas *ee; | ||
1675 | Ecore_Evas *sub_ee; | ||
1676 | Evas *ev; | ||
1677 | Evas *sub_ev; | ||
1678 | Evas_Object *o; | ||
1679 | Evas_Object *img; | ||
1680 | Ethumb *r; | ||
1681 | |||
1682 | r = malloc(sizeof (Ethumb)); | ||
1683 | if (!r) return NULL; | ||
1684 | |||
1685 | memcpy(r, e, sizeof (Ethumb)); | ||
1686 | |||
1687 | r->thumb_dir = eina_stringshare_ref(e->thumb_dir); | ||
1688 | r->category = eina_stringshare_ref(e->category); | ||
1689 | r->src_hash = eina_stringshare_ref(e->src_hash); | ||
1690 | r->src_path = eina_stringshare_ref(e->src_path); | ||
1691 | r->src_key = eina_stringshare_ref(e->src_key); | ||
1692 | r->thumb_path = eina_stringshare_ref(e->thumb_path); | ||
1693 | r->thumb_key = eina_stringshare_ref(e->thumb_key); | ||
1694 | |||
1695 | ee = ecore_evas_buffer_new(1, 1); | ||
1696 | ev = ecore_evas_get(ee); | ||
1697 | if (!ev) | ||
1698 | { | ||
1699 | ERR("could not create ecore evas buffer"); | ||
1700 | free(r); | ||
1701 | return NULL; | ||
1702 | } | ||
1703 | |||
1704 | evas_image_cache_set(ev, 0); | ||
1705 | evas_font_cache_set(ev, 0); | ||
1706 | |||
1707 | o = ecore_evas_object_image_new(ee); | ||
1708 | if (!o) | ||
1709 | { | ||
1710 | ERR("could not create sub ecore evas buffer"); | ||
1711 | ecore_evas_free(ee); | ||
1712 | free(r); | ||
1713 | return NULL; | ||
1714 | } | ||
1715 | |||
1716 | sub_ee = ecore_evas_object_ecore_evas_get(o); | ||
1717 | sub_ev = ecore_evas_object_evas_get(o); | ||
1718 | ecore_evas_alpha_set(sub_ee, EINA_TRUE); | ||
1719 | |||
1720 | evas_image_cache_set(sub_ev, 0); | ||
1721 | evas_font_cache_set(sub_ev, 0); | ||
1722 | |||
1723 | img = evas_object_image_add(sub_ev); | ||
1724 | if (!img) | ||
1725 | { | ||
1726 | ERR("could not create source objects."); | ||
1727 | ecore_evas_free(ee); | ||
1728 | free(r); | ||
1729 | return NULL; | ||
1730 | } | ||
1731 | |||
1732 | r->ee = ee; | ||
1733 | r->sub_ee = sub_ee; | ||
1734 | r->e = ev; | ||
1735 | r->sub_e = sub_ev; | ||
1736 | r->o = o; | ||
1737 | r->img = img; | ||
1738 | |||
1739 | r->frame = NULL; | ||
1740 | r->finished_idler = NULL; | ||
1741 | r->finished_cb = NULL; | ||
1742 | r->cb_data = NULL; | ||
1743 | r->cb_data_free = NULL; | ||
1744 | r->cb_result = 0; | ||
1745 | r->plugin = NULL; | ||
1746 | r->pdata = NULL; | ||
1747 | |||
1748 | return r; | ||
1749 | } | ||
1750 | |||
1751 | #define CHECK_DELTA(Param) \ | ||
1752 | if (e1->Param != e2->Param) \ | ||
1753 | return EINA_TRUE; | ||
1754 | |||
1755 | EAPI Eina_Bool | ||
1756 | ethumb_cmp(const Ethumb *e1, const Ethumb *e2) | ||
1757 | { | ||
1758 | CHECK_DELTA(thumb_dir); | ||
1759 | CHECK_DELTA(category); | ||
1760 | CHECK_DELTA(tw); | ||
1761 | CHECK_DELTA(th); | ||
1762 | CHECK_DELTA(format); | ||
1763 | CHECK_DELTA(aspect); | ||
1764 | CHECK_DELTA(orientation); | ||
1765 | CHECK_DELTA(crop_x); | ||
1766 | CHECK_DELTA(crop_y); | ||
1767 | CHECK_DELTA(quality); | ||
1768 | CHECK_DELTA(compress); | ||
1769 | CHECK_DELTA(rw); | ||
1770 | CHECK_DELTA(rh); | ||
1771 | CHECK_DELTA(video.start); | ||
1772 | CHECK_DELTA(video.time); | ||
1773 | CHECK_DELTA(video.interval); | ||
1774 | CHECK_DELTA(video.ntimes); | ||
1775 | CHECK_DELTA(video.fps); | ||
1776 | CHECK_DELTA(document.page); | ||
1777 | |||
1778 | return EINA_FALSE; | ||
1779 | } | ||
1780 | |||
1781 | EAPI unsigned int | ||
1782 | ethumb_length(EINA_UNUSED const void *key) | ||
1783 | { | ||
1784 | return sizeof (Ethumb); | ||
1785 | } | ||
1786 | |||
1787 | #define CMP_PARAM(Param) \ | ||
1788 | if (e1->Param != e2->Param) \ | ||
1789 | return e1->Param - e2->Param; | ||
1790 | |||
1791 | EAPI int | ||
1792 | ethumb_key_cmp(const void *key1, EINA_UNUSED int key1_length, | ||
1793 | const void *key2, EINA_UNUSED int key2_length) | ||
1794 | { | ||
1795 | const Ethumb *e1 = key1; | ||
1796 | const Ethumb *e2 = key2; | ||
1797 | |||
1798 | CMP_PARAM(thumb_dir); | ||
1799 | CMP_PARAM(category); | ||
1800 | CMP_PARAM(tw); | ||
1801 | CMP_PARAM(th); | ||
1802 | CMP_PARAM(format); | ||
1803 | CMP_PARAM(aspect); | ||
1804 | CMP_PARAM(orientation); | ||
1805 | CMP_PARAM(crop_x); | ||
1806 | CMP_PARAM(crop_y); | ||
1807 | CMP_PARAM(quality); | ||
1808 | CMP_PARAM(compress); | ||
1809 | CMP_PARAM(rw); | ||
1810 | CMP_PARAM(rh); | ||
1811 | CMP_PARAM(video.start); | ||
1812 | CMP_PARAM(video.time); | ||
1813 | CMP_PARAM(video.interval); | ||
1814 | CMP_PARAM(video.ntimes); | ||
1815 | CMP_PARAM(video.fps); | ||
1816 | CMP_PARAM(document.page); | ||
1817 | CMP_PARAM(src_path); | ||
1818 | CMP_PARAM(src_key); | ||
1819 | |||
1820 | return 0; | ||
1821 | } | ||
1822 | |||
1823 | #undef CMP_PARAM | ||
1824 | |||
1825 | #define HASH_PARAM_I(Param) r ^= eina_hash_int32((unsigned int*) &e->Param, 0); | ||
1826 | #ifdef __LP64__ | ||
1827 | # define HASH_PARAM_P(Param) r ^= eina_hash_int64((unsigned long int*) &e->Param, 0); | ||
1828 | #else | ||
1829 | # define HASH_PARAM_P(Param) r ^= eina_hash_int32((unsigned int*) &e->Param, 0); | ||
1830 | #endif | ||
1831 | #define HASH_PARAM_D(Param) r ^= eina_hash_int64((unsigned long int*)&e->Param, 0); | ||
1832 | #define HASH_PARAM_F(Param) r ^= eina_hash_int32((unsigned int*) &e->Param, 0); | ||
1833 | |||
1834 | EAPI int | ||
1835 | ethumb_hash(const void *key, int key_length EINA_UNUSED) | ||
1836 | { | ||
1837 | const Ethumb *e = key; | ||
1838 | int r = 0; | ||
1839 | |||
1840 | HASH_PARAM_P(thumb_dir); | ||
1841 | HASH_PARAM_P(category); | ||
1842 | HASH_PARAM_I(tw); | ||
1843 | HASH_PARAM_I(th); | ||
1844 | HASH_PARAM_I(format); | ||
1845 | HASH_PARAM_I(aspect); | ||
1846 | HASH_PARAM_I(orientation); | ||
1847 | HASH_PARAM_F(crop_x); | ||
1848 | HASH_PARAM_F(crop_y); | ||
1849 | HASH_PARAM_I(quality); | ||
1850 | HASH_PARAM_I(compress); | ||
1851 | HASH_PARAM_P(src_path); | ||
1852 | HASH_PARAM_P(src_key); | ||
1853 | HASH_PARAM_I(rw); | ||
1854 | HASH_PARAM_I(rh); | ||
1855 | HASH_PARAM_D(video.start); | ||
1856 | HASH_PARAM_D(video.time); | ||
1857 | HASH_PARAM_D(video.interval); | ||
1858 | HASH_PARAM_I(video.ntimes); | ||
1859 | HASH_PARAM_I(video.fps); | ||
1860 | HASH_PARAM_I(document.page); | ||
1861 | |||
1862 | return r; | ||
1863 | } | ||