diff --git a/src/bin/evas/evas_cserve2.h b/src/bin/evas/evas_cserve2.h index 3b0ec1544c..b1b6d6882e 100644 --- a/src/bin/evas/evas_cserve2.h +++ b/src/bin/evas/evas_cserve2.h @@ -5,7 +5,7 @@ #include "evas_cs2.h" #ifndef CSERVE2_LOG_LEVEL -#define CSERVE2_LOG_LEVEL 2 +#define CSERVE2_LOG_LEVEL 4 #endif #ifdef CRIT @@ -103,8 +103,17 @@ typedef enum { } Slave_Command; struct _Slave_Msg_Image_Open { - Eina_Bool has_loader_data : 1; - // Optionally followed by: + struct { + struct { + unsigned int x, y, w, h; + } region; + double dpi; + unsigned int w, h; + int scale_down_by; + Eina_Bool orientation; + } lo; + // const char path[]; + // const char key[]; // const char loader[]; }; @@ -308,7 +317,7 @@ void cserve2_cache_init(void); void cserve2_cache_shutdown(void); void cserve2_cache_client_new(Client *client); void cserve2_cache_client_del(Client *client); -int cserve2_cache_file_open(Client *client, unsigned int client_file_id, const char *path, const char *key, unsigned int rid); +int cserve2_cache_file_open(Client *client, unsigned int client_file_id, const char *path, const char *key, unsigned int rid, Evas_Image_Load_Opts *lo); void cserve2_cache_file_close(Client *client, unsigned int client_file_id); int cserve2_cache_image_entry_create(Client *client, int rid, unsigned int client_file_id, unsigned int image_id, Evas_Image_Load_Opts *opts); void cserve2_rgba_image_scale_do(void *src_data, void *dst_data, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int alpha, int smooth); diff --git a/src/bin/evas/evas_cserve2_cache.c b/src/bin/evas/evas_cserve2_cache.c index 30f4cf530f..5361c137a1 100644 --- a/src/bin/evas/evas_cserve2_cache.c +++ b/src/bin/evas/evas_cserve2_cache.c @@ -27,6 +27,22 @@ typedef struct _File_Watch File_Watch; typedef struct _Font_Source Font_Source; typedef struct _Font_Entry Font_Entry; +static const Evas_Image_Load_Opts empty_lo = { + { 0, 0, 0, 0 }, + { + 0, 0, 0, 0, + 0, 0, + 0, + 0 + }, + 0.0, + 0, 0, + 0, + 0, + + EINA_FALSE +}; + typedef enum { CSERVE2_IMAGE_FILE, CSERVE2_IMAGE_DATA, @@ -550,11 +566,12 @@ _font_loaded_send(Client *client, unsigned int rid) static void * _open_request_build(Entry *entry, int *bufsize) { + Slave_Msg_Image_Open msg = { { { 0,0,0,0}, 0,0,0,0,0, } }; const char *loader_data, *key, *path; - char *buf; - int size, pathlen, keylen, loaderlen; - Slave_Msg_Image_Open msg; + void *buf; + size_t pathlen, keylen, loaderlen; File_Data *fd; + Eina_Binbuf *bb; if (!entry || entry->type != CSERVE2_IMAGE_FILE) return NULL; @@ -568,30 +585,33 @@ _open_request_build(Entry *entry, int *bufsize) path = cserve2_shared_string_get(fd->path); key = cserve2_shared_string_get(fd->key); + loader_data = cserve2_shared_string_get(fd->loader_data); if (!path) path = ""; if (!key) key = ""; + if (!loader_data) loader_data = ""; pathlen = strlen(path) + 1; keylen = strlen(key) + 1; + loaderlen = strlen(loader_data) + 1; - memset(&msg, 0, sizeof(msg)); - loader_data = cserve2_shared_string_get(fd->loader_data); - msg.has_loader_data = !!loader_data; - loaderlen = msg.has_loader_data ? (strlen(loader_data) + 1) : 0; + msg.lo.region.x = fd->lo.region.x; + msg.lo.region.y = fd->lo.region.y; + msg.lo.region.w = fd->lo.region.w; + msg.lo.region.h = fd->lo.region.h; + msg.lo.dpi = fd->lo.dpi; + msg.lo.w = fd->lo.w; + msg.lo.h = fd->lo.h; + msg.lo.scale_down_by = fd->lo.scale_down_by; + msg.lo.orientation = fd->lo.orientation; - size = sizeof(msg) + pathlen + keylen + loaderlen; - buf = malloc(size); - if (!buf) return NULL; - - memcpy(buf, &msg, sizeof(msg)); - memcpy(buf + sizeof(msg), path, pathlen); - memcpy(buf + sizeof(msg) + pathlen, key, keylen); - if (msg.has_loader_data) - memcpy(buf + sizeof(msg) + pathlen + keylen, loader_data, loaderlen); - - *bufsize = size; - - _entry_load_start(entry); + bb = eina_binbuf_new(); + eina_binbuf_append_length(bb, (unsigned char *) &msg, sizeof(msg)); + eina_binbuf_append_length(bb, (unsigned char *) path, pathlen); + eina_binbuf_append_length(bb, (unsigned char *) key, keylen); + eina_binbuf_append_length(bb, (unsigned char *) loader_data, loaderlen); + *bufsize = eina_binbuf_length_get(bb); + buf = eina_binbuf_string_steal(bb); + eina_binbuf_free(bb); return buf; } @@ -940,17 +960,66 @@ _image_entry_size_get(Image_Entry *ientry) return size / 1024; } +static Eina_Bool +_evas_image_load_opts_empty(Evas_Image_Load_Opts *lo) +{ + if (!lo) return EINA_TRUE; + + return ((lo->scale_down_by == 0) + && (lo->dpi == 0.0) + && (lo->w == 0) && (lo->h == 0) + && (lo->region.x == 0) && (lo->region.y == 0) + && (lo->region.w == 0) && (lo->region.h == 0) + && (lo->orientation == 0)); +} + +static void +_file_hkey_get(char *buf, size_t sz, const char *path, const char *key, + Evas_Image_Load_Opts *lo) +{ + // Same as _evas_cache_image_loadopts_append() but not optimized :) + if (lo && _evas_image_load_opts_empty(lo)) + lo = NULL; + + if (!lo) + snprintf(buf, sz, "%s:%s", path, key); + else + { + if (lo->orientation) + { + snprintf(buf, sz, "%s:%s//@/%d/%f/%dx%d/%d+%d.%dx%d", + path, key, lo->scale_down_by, lo->dpi, lo->w, lo->h, + lo->region.x, lo->region.y, lo->region.w, lo->region.h); + } + else + { + snprintf(buf, sz, "%s:%s//@/%d/%f/%dx%d/%d+%d.%dx%d/o", + path, key, lo->scale_down_by, lo->dpi, lo->w, lo->h, + lo->region.x, lo->region.y, lo->region.w, lo->region.h); + } + } +} + static void _file_id_free(File_Data *fd) { + Evas_Image_Load_Opts lo = empty_lo; char buf[4096]; - DBG("Removing entry file id: %d, file: \"%s:%s\"", - fd->id, cserve2_shared_string_get(fd->path), - cserve2_shared_string_get(fd->key)); - snprintf(buf, sizeof(buf), "%s:%s", - cserve2_shared_string_get(fd->path), - cserve2_shared_string_get(fd->key)); + lo.region.x = fd->lo.region.x; + lo.region.y = fd->lo.region.y; + lo.region.w = fd->lo.region.w; + lo.region.h = fd->lo.region.h; + lo.dpi = fd->lo.dpi; + lo.w = fd->lo.w; + lo.h = fd->lo.h; + lo.scale_down_by = fd->lo.scale_down_by; + lo.orientation = fd->lo.orientation; + + _file_hkey_get(buf, sizeof(buf), cserve2_shared_string_get(fd->path), + cserve2_shared_string_get(fd->key), &lo); + + DBG("Removing entry file id: %u, file: \"%s\"", fd->id, buf); eina_hash_del_by_key(file_ids, buf); } @@ -2450,7 +2519,8 @@ _cserve2_cache_font_debug(unsigned int rid, unsigned int *size) int cserve2_cache_file_open(Client *client, unsigned int client_file_id, - const char *path, const char *key, unsigned int rid) + const char *path, const char *key, unsigned int rid, + Evas_Image_Load_Opts *lo) { unsigned int file_id; File_Data *fd; @@ -2460,6 +2530,7 @@ cserve2_cache_file_open(Client *client, unsigned int client_file_id, File_Entry *fentry; int idx; +#if 0 // look for this file on client references ref = eina_hash_find(client->files.referencing, &client_file_id); if (ref) @@ -2483,9 +2554,10 @@ cserve2_cache_file_open(Client *client, unsigned int client_file_id, _image_opened_send(client, fd, rid); return 0; } +#endif // search whether the file is already opened by another client - snprintf(buf, sizeof(buf), "%s:%s", path, key); + _file_hkey_get(buf, sizeof(buf), path, key, lo); file_id = (unsigned int)(uintptr_t)eina_hash_find(file_ids, buf); if (file_id) { @@ -2527,9 +2599,19 @@ cserve2_cache_file_open(Client *client, unsigned int client_file_id, return -1; } fd->valid = EINA_FALSE; - fd->refcount = 1; fd->path = cserve2_shared_string_add(path); fd->key = cserve2_shared_string_add(key); + if (!lo) lo = (Evas_Image_Load_Opts *) &empty_lo; + fd->lo.region.x = lo->region.x; + fd->lo.region.y = lo->region.y; + fd->lo.region.w = lo->region.w; + fd->lo.region.h = lo->region.h; + fd->lo.dpi = lo->dpi; + fd->lo.w = lo->w; + fd->lo.h = lo->h; + fd->lo.scale_down_by = lo->scale_down_by; + fd->lo.orientation = lo->orientation; + fd->refcount = 1; fd->id = file_id; fentry = calloc(1, sizeof(File_Entry)); diff --git a/src/bin/evas/evas_cserve2_main.c b/src/bin/evas/evas_cserve2_main.c index 90a811af62..bd54cbfb3d 100644 --- a/src/bin/evas/evas_cserve2_main.c +++ b/src/bin/evas/evas_cserve2_main.c @@ -136,6 +136,8 @@ _cserve2_client_open(Client *client) { Msg_Open *msg = (Msg_Open *)client->msg.buf; const char *path, *key, *end; + Evas_Image_Load_Opts *opts = NULL; + Evas_Image_Load_Opts opts_copy; path = ((const char *)msg) + sizeof(*msg) + msg->path_offset; key = ((const char *)msg) + sizeof(*msg) + msg->key_offset; @@ -146,7 +148,14 @@ _cserve2_client_open(Client *client) msg->file_id, path, key, (int) msg->has_load_opts); if (!key[0]) key = NULL; - cserve2_cache_file_open(client, msg->file_id, path, key, msg->base.rid); + if (msg->has_load_opts) + { + opts = &opts_copy; + memcpy(&opts_copy, end, sizeof(opts_copy)); + } + + cserve2_cache_file_open(client, msg->file_id, path, key, msg->base.rid, + opts); if (!msg->has_load_opts) cserve2_cache_image_entry_create(client, msg->base.rid, @@ -154,7 +163,6 @@ _cserve2_client_open(Client *client) else { // FIXME: Check message size first? - Evas_Image_Load_Opts *opts = (Evas_Image_Load_Opts *) end; DBG("Load Options:"); DBG("\tdpi: %03.1f", opts->dpi); diff --git a/src/bin/evas/evas_cserve2_shm_debug.c b/src/bin/evas/evas_cserve2_shm_debug.c index 882864618e..12ee29dd55 100644 --- a/src/bin/evas/evas_cserve2_shm_debug.c +++ b/src/bin/evas/evas_cserve2_shm_debug.c @@ -384,7 +384,7 @@ _strings_all_print(Eina_Bool full) } static void -_files_all_print(Eina_Bool full) +_files_all_print_short() { int k; @@ -401,7 +401,7 @@ _files_all_print(Eina_Bool full) fd = _shared_array_item_get(sf_files, k); if (!fd) break; - if (!fd->id || (!full && !fd->refcount)) continue; + if (!fd->id || !fd->refcount) continue; printf("%7d %7d %5dx%-6d %d %d %6.6s %6d %6d '%s':'%s'\n", k, fd->id, fd->w, fd->h, !!fd->alpha, !!fd->invalid, @@ -413,6 +413,51 @@ _files_all_print(Eina_Bool full) printf_newline(1); } +static void +_files_all_print_all(void) +{ + int k; + + if (!sf_files) return; + + printf("List of opened image files: %s\n", eina_file_filename_get(sf_files->f)); + printf_newline(0); + + for (k = 0; k < sf_files->header->count; k++) + { + File_Data *fd; + + fd = _shared_array_item_get(sf_files, k); + if (!fd) break; + if (!fd->id) continue; + + printf("File #%-8d %d\n", k, fd->id); + printf("Path:Key: '%s':'%s'\n", + _shared_string_get(fd->path), _shared_string_get(fd->key)); + printf("LoadOpts: Region: %d,%d-%dx%d\n", + fd->lo.region.x, fd->lo.region.y, fd->lo.region.w, fd->lo.region.h); + if (fd->lo.dpi != 0) + printf(" DPI: %f\n"); + else + printf(" DPI: 0\n"); + printf(" Requested: %dx%d\n", fd->lo.w, fd->lo.h); + printf(" Scale down: %d\n", fd->lo.scale_down_by); + printf(" Orientation: %s\n", fd->lo.orientation ? "YES" : "NO"); + printf("Loader: %s\n", _shared_string_get(fd->loader_data)); + printf("Geometry: %dx%d\n", fd->w, fd->h); + printf("Animation: anim: %s, frames: %d, loop: %d, hint: %d\n", + fd->animated ? "YES" : "NO", + fd->frame_count, fd->loop_count, fd->loop_hint); + printf("Alpha: %s\n", fd->alpha ? "YES" : "NO"); + printf("Invalid: %s\n", fd->invalid ? "YES" : "NO"); + + printf_newline(0); + } + + printf("\n\n"); + fflush(stdout); +} + static void _images_all_print_short(void) { @@ -752,7 +797,8 @@ main(int argc EINA_UNUSED, char **argv EINA_UNUSED) _index_tables_summary_print(); _strings_all_print(full); - _files_all_print(full); + _files_all_print_short(); + if (full) _files_all_print_all(); _images_all_print_short(); if (full) _images_all_print_full(); _fonts_all_print_short(); diff --git a/src/bin/evas/evas_cserve2_slave.c b/src/bin/evas/evas_cserve2_slave.c index da6099ba59..963a1dba76 100644 --- a/src/bin/evas/evas_cserve2_slave.c +++ b/src/bin/evas/evas_cserve2_slave.c @@ -318,7 +318,8 @@ _image_file_header(Eina_File *fd, Eina_Stringshare *key, Evas_Image_Load_Opts *l static Error_Type image_open(const char *file, const char *key, - Slave_Msg_Image_Opened *result, const char **use_loader) + Slave_Msg_Image_Opened *result, const char **use_loader, + Evas_Image_Load_Opts *load_opts) { Evas_Module *module; Eina_File *fd; @@ -327,9 +328,6 @@ image_open(const char *file, const char *key, unsigned int i; Error_Type ret = CSERVE2_NONE; Eina_Stringshare *skey = eina_stringshare_add(key); - Evas_Image_Load_Opts load_opts; - - memset(&load_opts, 0, sizeof(load_opts)); fd = eina_file_open(file, EINA_FALSE); if (!fd) @@ -344,7 +342,7 @@ image_open(const char *file, const char *key, module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader); if (module) { - if (_image_file_header(fd, skey, &load_opts, result, module)) + if (_image_file_header(fd, skey, load_opts, result, module)) goto success; } @@ -364,7 +362,7 @@ try_extension: if (loader) { module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader); - if (module && _image_file_header(fd, skey, &load_opts, result, module)) + if (module && _image_file_header(fd, skey, load_opts, result, module)) goto success; loader = NULL; module = NULL; @@ -376,7 +374,7 @@ try_extension: loader = loaders_name[i]; module = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loader); if (!module) continue; - if (_image_file_header(fd, skey, &load_opts, result, module)) + if (_image_file_header(fd, skey, load_opts, result, module)) goto success; } @@ -487,22 +485,32 @@ done: static void handle_image_open(int wfd, void *params) { - Slave_Msg_Image_Open *p; + Slave_Msg_Image_Open *msg = params; Slave_Msg_Image_Opened result; + Evas_Image_Load_Opts load_opts; Error_Type err; const char *loader = NULL, *file, *key, *ptr; char *resp; size_t resp_size; - p = params; - file = (const char *)(p + sizeof(Slave_Msg_Image_Open)); + memset(&load_opts, 0, sizeof(load_opts)); + load_opts.region.x = msg->lo.region.x; + load_opts.region.y = msg->lo.region.y; + load_opts.region.w = msg->lo.region.w; + load_opts.region.h = msg->lo.region.h; + load_opts.dpi = msg->lo.dpi; + load_opts.w = msg->lo.w; + load_opts.h = msg->lo.h; + load_opts.scale_down_by = msg->lo.scale_down_by; + load_opts.orientation = msg->lo.orientation; + + file = (const char *) (msg + 1); key = file + strlen(file) + 1; ptr = key + strlen(key) + 1; - if (p->has_loader_data) - loader = ptr; + loader = ptr; memset(&result, 0, sizeof(result)); - if ((err = image_open(file, key, &result, &loader)) + if ((err = image_open(file, key, &result, &loader, &load_opts)) != CSERVE2_NONE) { printf("OPEN failed at %s:%d\n", __FUNCTION__, __LINE__); diff --git a/src/lib/evas/cserve2/evas_cs2.h b/src/lib/evas/cserve2/evas_cs2.h index 835ed31c0b..6cc8804e29 100644 --- a/src/lib/evas/cserve2/evas_cs2.h +++ b/src/lib/evas/cserve2/evas_cs2.h @@ -324,9 +324,20 @@ struct _Index_Entry { #define FILE_DATA_ARRAY_TAG ('F' | 'I' << 8 | 'L' << 16 | 'E' << 24) struct _File_Data { SHMOBJECT; + // Hash entry elements (see Evas_Image_Load_Opts) string_t path; string_t key; - string_t loader_data; + struct { + struct { + unsigned int x, y, w, h; + } region; + double dpi; + unsigned int w, h; + int scale_down_by; + Eina_Bool orientation; + } lo; + // Properties set after opening the file + string_t loader_data; // Can also be set during open (force this loader) int w, h; int frame_count; int loop_count; diff --git a/src/lib/evas/cserve2/evas_cs2_client.c b/src/lib/evas/cserve2/evas_cs2_client.c index 566bd0655a..e6f43a73cb 100644 --- a/src/lib/evas/cserve2/evas_cs2_client.c +++ b/src/lib/evas/cserve2/evas_cs2_client.c @@ -23,6 +23,22 @@ #define HKEY_LOAD_OPTS_STR_LEN 215 typedef void (*Op_Callback)(void *data, const void *msg, int size); +static const Evas_Image_Load_Opts empty_lo = { + { 0, 0, 0, 0 }, + { + 0, 0, 0, 0, + 0, 0, + 0, + 0 + }, + 0.0, + 0, 0, + 0, + 0, + + EINA_FALSE +}; + struct _File_Entry { unsigned int file_id; unsigned int server_file_id; @@ -2053,26 +2069,45 @@ _shared_string_get(int id) do { if (!_shared_index_remap_check(&(si), sizeof(typ))) { \ CRIT("Failed to remap index"); return NULL; } } while (0) -static const char * -_shared_file_data_hkey_get(char *hkey, const char *file, const char *key, - size_t hkey_size) + +static Eina_Bool +_evas_image_load_opts_empty(Evas_Image_Load_Opts *lo) { - size_t keylen = 0, filelen; + if (!lo) return EINA_TRUE; - if (key) keylen = strlen(key) + 1; - filelen = strlen(file); + return ((lo->scale_down_by == 0) + && (lo->dpi == 0.0) + && (lo->w == 0) && (lo->h == 0) + && (lo->region.x == 0) && (lo->region.y == 0) + && (lo->region.w == 0) && (lo->region.h == 0) + && (lo->orientation == 0)); +} - if (filelen + keylen + 1 > hkey_size) - return NULL; +static void +_file_hkey_get(char *buf, size_t sz, const char *path, const char *key, + Evas_Image_Load_Opts *lo) +{ + // Same as _evas_cache_image_loadopts_append() but not optimized :) + if (lo && _evas_image_load_opts_empty(lo)) + lo = NULL; - memcpy(hkey, file, filelen); - hkey[filelen] = ':'; - if (key) - memcpy(hkey + filelen + 1, key, keylen); + if (!lo) + snprintf(buf, sz, "%s:%s", path, key); else - memcpy(hkey + filelen + 1, "(null)", 7); - - return hkey; + { + if (lo->orientation) + { + snprintf(buf, sz, "%s:%s//@/%d/%f/%dx%d/%d+%d.%dx%d", + path, key, lo->scale_down_by, lo->dpi, lo->w, lo->h, + lo->region.x, lo->region.y, lo->region.w, lo->region.h); + } + else + { + snprintf(buf, sz, "%s:%s//@/%d/%f/%dx%d/%d+%d.%dx%d/o", + path, key, lo->scale_down_by, lo->dpi, lo->w, lo->h, + lo->region.x, lo->region.y, lo->region.w, lo->region.h); + } + } } static const File_Data * @@ -2104,7 +2139,7 @@ _shared_image_entry_file_data_find(Image_Entry *ie) } // Check hash - _shared_file_data_hkey_get(hkey, ie->file, ie->key, PATH_MAX); + _file_hkey_get(hkey, sizeof(hkey), ie->file, ie->key, &ie->load_opts); fdata = eina_hash_find(_index.files.entries_by_hkey, hkey); if (fdata) return fdata; @@ -2116,6 +2151,7 @@ _shared_image_entry_file_data_find(Image_Entry *ie) const char *file, *key; const File_Data *fd; char fd_hkey[PATH_MAX]; + Evas_Image_Load_Opts lo = empty_lo; fd = &(_index.files.entries.filedata[k]); if (!fd->id) break; @@ -2136,7 +2172,17 @@ _shared_image_entry_file_data_find(Image_Entry *ie) (key > _index.strings_entries.data + _index.strings_entries.size)) key = _shared_string_get(fd->key); - _shared_file_data_hkey_get(fd_hkey, file, key, PATH_MAX); + lo.region.x = fd->lo.region.x; + lo.region.y = fd->lo.region.y; + lo.region.w = fd->lo.region.w; + lo.region.h = fd->lo.region.h; + lo.dpi = fd->lo.dpi; + lo.w = fd->lo.w; + lo.h = fd->lo.h; + lo.scale_down_by = fd->lo.scale_down_by; + lo.orientation = fd->lo.orientation; + + _file_hkey_get(fd_hkey, sizeof(fd_hkey), file, key, &lo); if (add_to_hash) {