Enlightenment CVS committal Author : moom Project : e17 Module : proto
Dir : e17/proto/etk/src/lib Modified Files: etk_image.c etk_image.h Log Message: * [Etk_Image] Rewrite Etk_Image and add etk_image_set_from_data() =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_image.c,v retrieving revision 1.26 retrieving revision 1.27 diff -u -3 -r1.26 -r1.27 --- etk_image.c 25 Dec 2006 14:04:53 -0000 1.26 +++ etk_image.c 29 Dec 2006 21:50:46 -0000 1.27 @@ -16,14 +16,14 @@ enum Etk_Image_Property_Id { + ETK_IMAGE_SOURCE_PROPERTY, ETK_IMAGE_FILE_PROPERTY, - ETK_IMAGE_EDJE_FILE_PROPERTY, - ETK_IMAGE_EDJE_GROUP_PROPERTY, - ETK_IMAGE_EVAS_OBJECT_PROPERTY, - ETK_IMAGE_KEEP_ASPECT_PROPERTY, - ETK_IMAGE_USE_EDJE_PROPERTY, + ETK_IMAGE_KEY_PROPERTY, ETK_IMAGE_STOCK_ID_PROPERTY, - ETK_IMAGE_STOCK_SIZE_PROPERTY + ETK_IMAGE_STOCK_SIZE_PROPERTY, + ETK_IMAGE_EVAS_OBJECT_PROPERTY, + ETK_IMAGE_KEEP_ASPECT_PROPERTY, + ETK_IMAGE_ASPECT_RATIO_PROPERTY }; static void _etk_image_constructor(Etk_Image *image); @@ -31,9 +31,9 @@ static void _etk_image_property_set(Etk_Object *object, int property_id, Etk_Property_Value *value); static void _etk_image_property_get(Etk_Object *object, int property_id, Etk_Property_Value *value); static void _etk_image_realize_cb(Etk_Object *object, void *data); -static void _etk_image_unrealize_cb(Etk_Object *object, void *data); static void _etk_image_size_request(Etk_Widget *widget, Etk_Size *size); static void _etk_image_size_allocate(Etk_Widget *widget, Etk_Geometry geometry); +static void _etk_image_source_set(Etk_Image *image, Etk_Image_Source source); static void _etk_image_load(Etk_Image *image); /************************** @@ -47,7 +47,7 @@ * @brief Gets the type of an Etk_Image * @return Returns the type of an Etk_Image */ -Etk_Type *etk_image_type_get() +Etk_Type *etk_image_type_get(void) { static Etk_Type *image_type = NULL; @@ -56,22 +56,22 @@ image_type = etk_type_new("Etk_Image", ETK_WIDGET_TYPE, sizeof(Etk_Image), ETK_CONSTRUCTOR(_etk_image_constructor), ETK_DESTRUCTOR(_etk_image_destructor)); - etk_type_property_add(image_type, "image_file", ETK_IMAGE_FILE_PROPERTY, - ETK_PROPERTY_STRING, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_string(NULL)); - etk_type_property_add(image_type, "edje_file", ETK_IMAGE_EDJE_FILE_PROPERTY, + etk_type_property_add(image_type, "source", ETK_IMAGE_SOURCE_PROPERTY, + ETK_PROPERTY_INT, ETK_PROPERTY_READABLE, etk_property_value_int(ETK_IMAGE_FILE)); + etk_type_property_add(image_type, "file", ETK_IMAGE_FILE_PROPERTY, ETK_PROPERTY_STRING, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_string(NULL)); - etk_type_property_add(image_type, "edje_group", ETK_IMAGE_EDJE_GROUP_PROPERTY, + etk_type_property_add(image_type, "key", ETK_IMAGE_KEY_PROPERTY, ETK_PROPERTY_STRING, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_string(NULL)); - etk_type_property_add(image_type, "evas_object", ETK_IMAGE_EVAS_OBJECT_PROPERTY, - ETK_PROPERTY_POINTER, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_pointer(NULL)); - etk_type_property_add(image_type, "keep_aspect", ETK_IMAGE_KEEP_ASPECT_PROPERTY, - ETK_PROPERTY_BOOL, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_bool(ETK_TRUE)); - etk_type_property_add(image_type, "use_edje", ETK_IMAGE_USE_EDJE_PROPERTY, - ETK_PROPERTY_BOOL, ETK_PROPERTY_READABLE, NULL); etk_type_property_add(image_type, "stock_id", ETK_IMAGE_STOCK_ID_PROPERTY, ETK_PROPERTY_INT, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_int(ETK_STOCK_NO_STOCK)); etk_type_property_add(image_type, "stock_size", ETK_IMAGE_STOCK_SIZE_PROPERTY, ETK_PROPERTY_INT, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_int(ETK_STOCK_SMALL)); + etk_type_property_add(image_type, "evas_object", ETK_IMAGE_EVAS_OBJECT_PROPERTY, + ETK_PROPERTY_POINTER, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_pointer(NULL)); + etk_type_property_add(image_type, "keep_aspect", ETK_IMAGE_KEEP_ASPECT_PROPERTY, + ETK_PROPERTY_BOOL, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_bool(ETK_TRUE)); + etk_type_property_add(image_type, "aspect_ratio", ETK_IMAGE_ASPECT_RATIO_PROPERTY, + ETK_PROPERTY_DOUBLE, ETK_PROPERTY_READABLE_WRITABLE, etk_property_value_double(0.0)); image_type->property_set = _etk_image_property_set; image_type->property_get = _etk_image_property_get; @@ -81,33 +81,56 @@ } /** - * @brief Creates a new image + * @brief Creates a new empty image * @return Returns the new image widget */ -Etk_Widget *etk_image_new() +Etk_Widget *etk_image_new(void) { return etk_widget_new(ETK_IMAGE_TYPE, NULL); } /** * @brief Creates a new image and loads the image from an image file - * @param filename the name of the file to load + * @param filename the path of the file to load * @return Returns the new image widget */ Etk_Widget *etk_image_new_from_file(const char *filename) { - return etk_widget_new(ETK_IMAGE_TYPE, "image_file", filename, NULL); + Etk_Widget *image; + + image = etk_image_new(); + etk_image_set_from_file(ETK_IMAGE(image), filename); + return image; +} + +/** + * @brief Creates a new image and loads the image from an edje-file + * @param filename the name of the edje-file to load + * @param group the name of the edje-group to load + * @return Returns the new image widget + */ +Etk_Widget *etk_image_new_from_edje(const char *filename, const char *group) +{ + Etk_Widget *image; + + image = etk_image_new(); + etk_image_set_from_edje(ETK_IMAGE(image), filename, group); + return image; } /** - * @brief Creates a new image and loads the image from an edje file - * @param edje_filename the name of the edje file to load - * @param edje_group the name of the edje group to load + * @brief Creates a new image and loads the image corresponding to the stock id + * @param stock_id the stock id corresponding to the image + * @param stock_size the size of the image to load * @return Returns the new image widget */ -Etk_Widget *etk_image_new_from_edje(const char *edje_filename, const char *edje_group) +Etk_Widget *etk_image_new_from_stock(Etk_Stock_Id stock_id, Etk_Stock_Size stock_size) { - return etk_widget_new(ETK_IMAGE_TYPE, "edje_file", edje_filename, "edje_group", edje_group, NULL); + Etk_Widget *image; + + image = etk_image_new(); + etk_image_set_from_stock(ETK_IMAGE(image), stock_id, stock_size); + return image; } /** @@ -117,294 +140,389 @@ */ Etk_Widget *etk_image_new_from_evas_object(Evas_Object *evas_object) { - return etk_widget_new(ETK_IMAGE_TYPE, "evas_object", evas_object, NULL); + Etk_Widget *image; + + image = etk_image_new(); + etk_image_set_from_evas_object(ETK_IMAGE(image), evas_object); + return image; } /** - * @brief Creates a new image and loads the image corresponding to the stock id - * @param stock_id the stock id corresponding to the image - * @param stock_size the size of the image to load + * @brief Creates a new image from the given pixel data + * @param width the width of the image + * @param height the height of the image + * @param data a pointer to the pixels: the pixels have to be stored in the premul'ed ARGB format + * @param copy whether the pixels should be copied or not. If you decide not to copy the pixels, you have to make sure + * the memory area where the pixels are stored is valid during all the lifetime of the image * @return Returns the new image widget */ -Etk_Widget *etk_image_new_from_stock(Etk_Stock_Id stock_id, Etk_Stock_Size stock_size) +Etk_Widget *etk_image_new_from_data(int width, int height, void *data, Etk_Bool copy) { - Etk_Widget *new_image; + Etk_Widget *image; - new_image = etk_image_new(); - etk_image_set_from_stock(ETK_IMAGE(new_image), stock_id, stock_size); - return new_image; + image = etk_image_new(); + etk_image_set_from_data(ETK_IMAGE(image), width, height, data, copy); + return image; } /** * @brief Loads the image from a file * @param image an image - * @param filename the name of the file to load + * @param filename the path to the file to load */ void etk_image_set_from_file(Etk_Image *image, const char *filename) { - Etk_Widget *widget; - - if (!(widget = ETK_WIDGET(image)) || (image->filename == filename)) + if (!image) return; - - free(image->filename); - image->filename = filename ? strdup(filename) : NULL; - etk_object_notify(ETK_OBJECT(image), "image_file"); - - if (image->edje_group) - { - free(image->edje_group); - image->edje_group = NULL; - etk_object_notify(ETK_OBJECT(image), "edje_group"); - } - if (image->edje_filename) - { - free(image->edje_filename); - image->edje_filename = NULL; - etk_object_notify(ETK_OBJECT(image), "edje_file"); - } - if (image->use_edje) + + _etk_image_source_set(image, ETK_IMAGE_FILE); + if (image->info.file.filename != filename) { - image->use_edje = ETK_FALSE; - image->object_type_changed = ETK_TRUE; - etk_object_notify(ETK_OBJECT(image), "use_edje"); - } - if (image->stock_id != ETK_STOCK_NO_STOCK) - { - image->stock_id = ETK_STOCK_NO_STOCK; - etk_object_notify(ETK_OBJECT(image), "stock_id"); + free(image->info.file.filename); + image->info.file.filename = filename ? strdup(filename) : NULL; + etk_object_notify(ETK_OBJECT(image), "file"); } _etk_image_load(image); } /** - * @brief Gets the name of the file used for the image + * @brief Gets the path to the file used by the image * @param image an image - * @return Returns the name of the file used by the image (NULL on failure) + * @return Returns the path to the file used by the image (NULL on failure) */ const char *etk_image_file_get(Etk_Image *image) { - if (!image || image->use_edje) + if (!image || image->source != ETK_IMAGE_FILE) return NULL; - return image->filename; + return image->info.file.filename; } /** * @brief Loads the image from an edje file * @param image an image - * @param edje_filename the name of the edje file to load - * @param edje_group the name of the edje group to load + * @param filename the path to the edje-file to load + * @param group the name of the edje-group to load */ -void etk_image_set_from_edje(Etk_Image *image, const char *edje_filename, const char *edje_group) +void etk_image_set_from_edje(Etk_Image *image, const char *filename, const char *group) { - Etk_Widget *widget; - - if (!(widget = ETK_WIDGET(image))) + if (!image) return; - - if (image->edje_filename != edje_filename) - { - free(image->edje_filename); - image->edje_filename = edje_filename ? strdup(edje_filename) : NULL; - etk_object_notify(ETK_OBJECT(image), "edje_file"); - } - if (image->edje_group != edje_group) - { - free(image->edje_group); - image->edje_group = edje_group ? strdup(edje_group) : NULL; - etk_object_notify(ETK_OBJECT(image), "edje_group"); - } - - if (image->filename) - { - free(image->filename); - image->filename = NULL; - etk_object_notify(ETK_OBJECT(image), "image_file"); - } - if (!image->use_edje) + + _etk_image_source_set(image, ETK_IMAGE_EDJE); + if (image->info.edje.filename != filename) { - image->use_edje = ETK_TRUE; - image->object_type_changed = ETK_TRUE; - etk_object_notify(ETK_OBJECT(image), "use_edje"); - } - if (image->stock_id != ETK_STOCK_NO_STOCK) - { - image->stock_id = ETK_STOCK_NO_STOCK; - etk_object_notify(ETK_OBJECT(image), "stock_id"); + free(image->info.edje.filename); + image->info.edje.filename = filename ? strdup(filename) : NULL; + etk_object_notify(ETK_OBJECT(image), "file"); + } + if (image->info.edje.group != group) + { + free(image->info.edje.group); + image->info.edje.group = group ? strdup(group) : NULL; + etk_object_notify(ETK_OBJECT(image), "key"); } _etk_image_load(image); } /** - * @brief Gets the filename and the group of the edje object used for the image + * @brief Gets the filename and the group of the edje-object used for the image * @param image an image - * @param edje_filename the location to store the filename of the edje object - * @param edje_group the location to store the filename of the edje group + * @param filename the location to store the path to the edje-file used + * @param group the location to store the name of the edje-group used */ -void etk_image_edje_get(Etk_Image *image, char **edje_filename, char **edje_group) +void etk_image_edje_get(Etk_Image *image, char **filename, char **group) { - if (!image || !image->use_edje) + if (!image || image->source != ETK_IMAGE_EDJE) { - if (edje_filename) - *edje_filename = NULL; - if (edje_group) - *edje_group = NULL; + if (filename) + *filename = NULL; + if (group) + *group = NULL; return; } - if (edje_filename) - *edje_filename = image->edje_filename; - if (edje_group) - *edje_group = image->edje_group; + if (filename) + *filename = image->info.edje.filename; + if (group) + *group = image->info.edje.group; } /** - * @brief Loads the image from an evas object + * @brief Loads the image corresponding to the given stock-id * @param image an image - * @param evas_object the evas object to use + * @param stock_id the stock-id corresponding to the icon to load + * @param stock_size the size of the stock-icon */ -void etk_image_set_from_evas_object(Etk_Image *image, Evas_Object *evas_object) +void etk_image_set_from_stock(Etk_Image *image, Etk_Stock_Id stock_id, Etk_Stock_Size stock_size) { - Etk_Widget *widget; - - if (!(widget = ETK_WIDGET(image)) || !evas_object) + if (!image) return; - - if (image->image_object != evas_object) + if (image->source == ETK_IMAGE_STOCK && image->info.stock.id == stock_id && image->info.stock.size == stock_size) + return; + + _etk_image_source_set(image, ETK_IMAGE_STOCK); + if (image->info.stock.id != stock_id) { - if (image->image_object && (image->filename || image->use_edje)) - evas_object_del(image->image_object); - image->image_object = evas_object; - etk_object_notify(ETK_OBJECT(image), "evas_object"); + image->info.stock.id = stock_id; + etk_object_notify(ETK_OBJECT(image), "stock_id"); } - - if (image->edje_group) + if (image->info.stock.size != stock_size) { - free(image->edje_group); - image->edje_group = NULL; - etk_object_notify(ETK_OBJECT(image), "edje_group"); + image->info.stock.size = stock_size; + etk_object_notify(ETK_OBJECT(image), "stock_size"); } - if (image->edje_filename) + + _etk_image_load(image); +} + +/** + * @brief Gets the stock-id and the stock-size used by the image + * @param image an image + * @param stock_id the location where to store the stock id used by the image + * @param stock_size the location where to store the stock size used by the image + */ +void etk_image_stock_get(Etk_Image *image, Etk_Stock_Id *stock_id, Etk_Stock_Size *stock_size) +{ + if (!image || image->source != ETK_IMAGE_STOCK) { - free(image->edje_filename); - image->edje_filename = NULL; - etk_object_notify(ETK_OBJECT(image), "edje_file"); + if (stock_id) + *stock_id = ETK_STOCK_NO_STOCK; + if (stock_size) + *stock_size = ETK_STOCK_SMALL; } - if (image->use_edje) - { - image->use_edje = ETK_FALSE; - image->object_type_changed = ETK_TRUE; - etk_object_notify(ETK_OBJECT(image), "use_edje"); - } - if (image->filename) + else { - free(image->filename); - image->filename = NULL; - etk_object_notify(ETK_OBJECT(image), "image_file"); + if (stock_id) + *stock_id = image->info.stock.id; + if (stock_size) + *stock_size = image->info.stock.size; } +} + +/** + * @brief Loads the image from an Evas object + * @param image an image + * @param evas_object the Evas object to use. The object can be anything (image, edje object, emotion object, ...) + */ +void etk_image_set_from_evas_object(Etk_Image *image, Evas_Object *evas_object) +{ + if (!image) + return; - if (!image->use_object) - { - image->use_object = ETK_TRUE; - image->object_type_changed = ETK_TRUE; - etk_object_notify(ETK_OBJECT(image), "use_object"); - } - if (image->stock_id != ETK_STOCK_NO_STOCK) + _etk_image_source_set(image, ETK_IMAGE_EVAS_OBJECT); + if (image->object != evas_object) { - image->stock_id = ETK_STOCK_NO_STOCK; - etk_object_notify(ETK_OBJECT(image), "stock_id"); + image->object = evas_object; + etk_object_notify(ETK_OBJECT(image), "evas_object"); } _etk_image_load(image); } /** - * @brief Gets the evas object of the image + * @brief Gets the Evas object used by the image. You can call this function even if you have not explicitly set the + * Evas object used by this image. For example, if you have loaded the image from a file, this function will return the + * corresponding Evas image object. You should just be careful by manipulating it (don't use Edje functions on an image + * object for example). * @param image an image - * @return Returns the evas object of the image + * @return Returns the Evas object of the image */ Evas_Object *etk_image_evas_object_get(Etk_Image *image) { if (!image) return NULL; - return image->image_object; + return image->object; } /** - * @brief Loads the image corresponding to the stock id + * @brief Sets the pixels of the image * @param image an image - * @param stock_id the stock id corresponding to the image - * @param stock_size the size of the stock icon + * @param width the width of the image + * @param height the height of the image + * @param data a pointer to the pixels: the pixels have to be stored in the premul'ed ARGB format + * @param copy whether the pixels should be copied or not. If you decide not to copy the pixels, you have to make sure + * the memory area where the pixels are stored is valid during all the lifetime of the image + * @return Returns the new image widget */ -void etk_image_set_from_stock(Etk_Image *image, Etk_Stock_Id stock_id, Etk_Stock_Size stock_size) +void etk_image_set_from_data(Etk_Image *image, int width, int height, void *data, Etk_Bool copy) { - char *key; - - if (!image || ((image->stock_id == stock_id) && (image->stock_size == stock_size))) + if (!image) return; - if ((key = etk_stock_key_get(stock_id, stock_size))) - etk_image_set_from_edje(image, etk_theme_icon_get(), key); - image->stock_id = stock_id; - image->stock_size = stock_size; + _etk_image_source_set(image, ETK_IMAGE_DATA); - etk_object_notify(ETK_OBJECT(image), "stock_id"); - etk_object_notify(ETK_OBJECT(image), "stock_size"); + if (data && width > 0 && height > 0) + { + image->info.data.size.w = width; + image->info.data.size.h = height; + image->info.data.copied = copy; + if (copy) + { + image->info.data.pixels = malloc(sizeof(width * height * 4)); + memcpy(image->info.data.pixels, data, width * height * 4); + } + else + image->info.data.pixels = data; + } + + _etk_image_load(image); } /** - * @brief Gets the stock id used by the image + * @brief Gets a pointer to the image pixels. This function only works if the image has been loaded from a file or if + * you have explicitely set its pixels with etk_image_set_from_data(). * @param image an image - * @param stock_id the location where to store the stock id used by the image - * @param stock_size the location where to store the stock size used by the image + * @param for_writing whether or not you want to be able to modify the pixels of the image. If so, call + * etk_image_update() once you have finished. + * @return Returns a pointer to the location of the pixels (stored in premul'ed ARGB format) + * @note If the image is loaded from a file, it has to be realized. Otherwise it will return NULL */ -void etk_image_stock_get(Etk_Image *image, Etk_Stock_Id *stock_id, Etk_Stock_Size *stock_size) +void *etk_image_data_get(Etk_Image *image, Etk_Bool for_writing) +{ + if (!image) + return NULL; + + if (image->source == ETK_IMAGE_FILE) + { + if (image->object) + return evas_object_image_data_get(image->object, for_writing); + } + else if (image->source == ETK_IMAGE_DATA) + { + if (image->object) + return evas_object_image_data_get(image->object, for_writing); + else + return image->info.data.pixels; + } + + return NULL; +} + +/** + * @brief Gets the source of the image (file, edje-file, stock, Evas object or pixel data) + * @param image an image + * @return Returns the source of the image + */ +Etk_Image_Source etk_image_source_get(Etk_Image *image) +{ + if (!image) + return ETK_IMAGE_FILE; + return image->source; +} + +/** + * @brief Updates all the pixels of the image (to be called after you have modified the pixel buffer for example). + * Same as etk_image_update_rect(image, 0, 0, image_width, image_height) + * @param image an image + */ +void etk_image_update(Etk_Image *image) { - if (stock_id) - *stock_id = image ? image->stock_id : ETK_STOCK_NO_STOCK; - if (stock_size) - *stock_size = image ? image->stock_size : ETK_STOCK_SMALL; + int w, h; + + if (!image) + return; + + etk_image_size_get(image, &w, &h); + etk_image_update_rect(image, 0, 0, w, h); } /** - * @brief Gets the native size of the image + * @brief Updates a rectangle of the pixels of the image (to be called after you have modified the pixel buffer + * for example). It only has effect on image loaded from a pixel buffer + * @param image an image + * @param x the x position of the top-left corner of the rectangle to update + * @param y the y position of the top-left corner of the rectangle to update + * @param w the width of the rectangle to update + * @param h the height of the rectangle to update + */ +void etk_image_update_rect(Etk_Image *image, int x, int y, int w, int h) +{ + if (!image || image->source != ETK_IMAGE_DATA || !image->object) + return; + evas_object_image_data_update_add(image->object, x, y, w, h); +} + +/** + * @brief Copies the image @a src_image to @a dest_image + * @param dest_image the destination image + * @param src_image the image to copy + * @note If @a src_image is an edje image, the current state of the edje animation won't be copied + */ +void etk_image_copy(Etk_Image *dest_image, Etk_Image *src_image) +{ + if (!dest_image || !src_image || dest_image == src_image) + return; + + switch (src_image->source) + { + case ETK_IMAGE_FILE: + /* TODO: copy the key too.. */ + etk_image_set_from_file(dest_image, src_image->info.file.filename); + break; + case ETK_IMAGE_EDJE: + etk_image_set_from_edje(dest_image, src_image->info.edje.filename, src_image->info.edje.group); + break; + case ETK_IMAGE_STOCK: + etk_image_set_from_stock(dest_image, src_image->info.stock.id, src_image->info.stock.size); + break; + case ETK_IMAGE_EVAS_OBJECT: + ETK_WARNING("You can't copy an image that is set from an Evas Object"); + break; + case ETK_IMAGE_DATA: + etk_image_set_from_data(dest_image, src_image->info.data.size.w, src_image->info.data.size.h, + src_image->info.data.pixels, ETK_TRUE); + break; + default: + break; + } + + etk_image_aspect_ratio_set(dest_image, src_image->aspect_ratio); + etk_image_keep_aspect_set(dest_image, src_image->keep_aspect); +} + +/** + * @brief Gets the native size of the image. If the image is loaded from a file or from given pixels, it returns the + * native size of the image. If the image is loaded from an Edje file or a stock-id, it returns the minimum size of the + * Edje object (a stock image is an Edje object). Otherwise, the returned size is 0x0 * @param image an image * @param width the location where to set the native width of the image * @param height the location where to set the native height of the image */ void etk_image_size_get(Etk_Image *image, int *width, int *height) { - if (!image) + if (width) + *width = 0; + if (height) + *height = 0; + + if (!image || !image->object) return; - if (!image) + if (image->source == ETK_IMAGE_FILE || image->source == ETK_IMAGE_DATA) + evas_object_image_size_get(image->object, width, height); + else if (image->source == ETK_IMAGE_EDJE || image->source == ETK_IMAGE_STOCK) { + Evas_Coord min_x, min_y, calc_x, calc_y; + + edje_object_size_min_get(image->object, &min_x, &min_y); + edje_object_size_min_calc(image->object, &calc_x, &calc_y); if (width) - *width = 0; + *width = ETK_MAX(min_x, calc_x); if (height) - *height = 0; - } - else - { - if (image->use_object) - evas_object_geometry_get(image->image_object, NULL, NULL, width, height); - else if (image->use_edje) - edje_object_size_min_get(image->image_object, width, height); - else - evas_object_image_size_get(image->image_object, width, height); + *height = ETK_MAX(min_y, calc_y); } } /** * @brief Sets if the image should keep its aspect ratio when it is resized * @param image an image - * @param keep_aspect if keep_aspect == ETK_TRUE, the image will keep its aspect ratio when itis resized + * @param keep_aspect if @a keep_aspect is ETK_TRUE, the image will keep its aspect ratio when it is resized */ void etk_image_keep_aspect_set(Etk_Image *image, Etk_Bool keep_aspect) { - if (!image) + if (!image || image->keep_aspect == keep_aspect) return; image->keep_aspect = keep_aspect; @@ -413,7 +531,7 @@ } /** - * @brief Get whether the image keeps its aspect ratio when it is resized + * @brief Gets whether the image keeps its aspect ratio when it is resized * @param image an image * @return Returns ETK_TRUE if the image keeps its aspect ratio when it is resized */ @@ -425,30 +543,33 @@ } /** - * @brief Copies the image @a src_image to @a dest_image - * @param dest_image the destination image - * @param src_image the image to copy - * @note If @a src_image is an edje image, the state of the edje animation won't be copied + * @brief Sets (forces) the aspect ratio of the image. You can use this function for example to set the aspect-ratio + * when you set the image from an Evas object with etk_image_set_from_evas_object(). + * @param image an image + * @param aspect_ratio the aspect ratio to set, or 0.0 to make Etk calculates automatically the aspect ratio */ -void etk_image_copy(Etk_Image *dest_image, Etk_Image *src_image) +void etk_image_aspect_ratio_set(Etk_Image *image, double aspect_ratio) { - if (!dest_image || !src_image || dest_image == src_image) + if (!image || image->aspect_ratio) return; - free(dest_image->filename); - free(dest_image->edje_filename); - free(dest_image->edje_group); - - dest_image->filename = src_image->filename ? strdup(src_image->filename) : NULL; - dest_image->edje_group = src_image->edje_group ? strdup(src_image->edje_group) : NULL; - dest_image->edje_filename = src_image->edje_group ? strdup(src_image->edje_filename) : NULL; - dest_image->stock_id = src_image->stock_id; - dest_image->stock_size = src_image->stock_size; - dest_image->keep_aspect = src_image->keep_aspect; - dest_image->object_type_changed = (dest_image->use_edje != src_image->use_edje); - dest_image->use_edje = src_image->use_edje; - - _etk_image_load(dest_image); + image->aspect_ratio = aspect_ratio; + etk_widget_size_recalc_queue(ETK_WIDGET(image)); + etk_object_notify(ETK_OBJECT(image), "aspect_ratio"); +} + +/** + * @brief Gets the aspect ratio you set to the image. If no aspect ratio has been set, it will return 0.0. + * To know the native aspect ratio, call etk_image_size_get() to get the native size of the image and calculate the + * aspect ratio from these values. + * @param image an image + * @return Returns the aspect ratio you set to the image, or 0.0 if no aspect ratio has been set + */ +double etk_image_aspect_ratio_get(Etk_Image *image) +{ + if (!image) + return 0.0; + return image->aspect_ratio; } /************************** @@ -465,22 +586,18 @@ if (!(widget = ETK_WIDGET(image))) return; - image->image_object = NULL; - image->filename = NULL; - image->edje_filename = NULL; - image->edje_group = NULL; - image->stock_id = ETK_STOCK_NO_STOCK; - image->stock_size = ETK_STOCK_SMALL; + image->object = NULL; + image->source = ETK_IMAGE_FILE; + image->info.file.filename = NULL; + image->info.file.key = NULL; image->keep_aspect = ETK_TRUE; - image->use_edje = ETK_FALSE; - image->use_object = ETK_FALSE; - image->object_type_changed = ETK_FALSE; + image->aspect_ratio = 0.0; widget->size_request = _etk_image_size_request; widget->size_allocate = _etk_image_size_allocate; etk_signal_connect("realize", ETK_OBJECT(image), ETK_CALLBACK(_etk_image_realize_cb), NULL); - etk_signal_connect("unrealize", ETK_OBJECT(image), ETK_CALLBACK(_etk_image_unrealize_cb), NULL); + etk_signal_connect_swapped("unrealize", ETK_OBJECT(image), ETK_CALLBACK(etk_callback_set_null), &image->object); } /* Destroys the image */ @@ -489,9 +606,21 @@ if (!image) return; - free(image->filename); - free(image->edje_filename); - free(image->edje_group); + if (image->source == ETK_IMAGE_FILE) + { + free(image->info.file.filename); + free(image->info.file.key); + } + else if (image->source == ETK_IMAGE_EDJE) + { + free(image->info.edje.filename); + free(image->info.edje.group); + } + else if (image->source == ETK_IMAGE_DATA) + { + if (image->info.data.copied) + free(image->info.data.pixels); + } } /* Sets the property whose id is "property_id" to the value "value" */ @@ -505,25 +634,39 @@ switch (property_id) { case ETK_IMAGE_FILE_PROPERTY: - etk_image_set_from_file(image, etk_property_value_string_get(value)); + if (image->source == ETK_IMAGE_EDJE) + etk_image_set_from_edje(image, etk_property_value_string_get(value), image->info.edje.group); + else + { + /* TODO: set the key! */ + etk_image_set_from_file(image, etk_property_value_string_get(value)); + } + break; + case ETK_IMAGE_KEY_PROPERTY: + if (image->source == ETK_IMAGE_FILE) + { + /* TODO: set the key! */ + //etk_image_set_from_file(image, image->info.file.filename, etk_property_value_string_get(value)); + } + else if (image->source == ETK_IMAGE_EDJE) + etk_image_set_from_edje(image, image->info.edje.filename, etk_property_value_string_get(value)); break; - case ETK_IMAGE_EDJE_FILE_PROPERTY: - etk_image_set_from_edje(image, etk_property_value_string_get(value), image->edje_group); + case ETK_IMAGE_STOCK_ID_PROPERTY: + if (image->source == ETK_IMAGE_STOCK) + etk_image_set_from_stock(image, etk_property_value_int_get(value), image->info.stock.size); break; - case ETK_IMAGE_EDJE_GROUP_PROPERTY: - etk_image_set_from_edje(image, image->edje_filename, etk_property_value_string_get(value)); + case ETK_IMAGE_STOCK_SIZE_PROPERTY: + if (image->source == ETK_IMAGE_STOCK) + etk_image_set_from_stock(image, image->info.stock.id, etk_property_value_int_get(value)); break; case ETK_IMAGE_EVAS_OBJECT_PROPERTY: etk_image_set_from_evas_object(image, etk_property_value_pointer_get(value)); - break; + break; case ETK_IMAGE_KEEP_ASPECT_PROPERTY: etk_image_keep_aspect_set(image, etk_property_value_bool_get(value)); break; - case ETK_IMAGE_STOCK_ID_PROPERTY: - etk_image_set_from_stock(image, etk_property_value_int_get(value), image->stock_size); - break; - case ETK_IMAGE_STOCK_SIZE_PROPERTY: - etk_image_set_from_stock(image, image->stock_id, etk_property_value_int_get(value)); + case ETK_IMAGE_ASPECT_RATIO_PROPERTY: + etk_image_aspect_ratio_set(image, etk_property_value_double_get(value)); break; default: break; @@ -540,29 +683,39 @@ switch (property_id) { + case ETK_IMAGE_SOURCE_PROPERTY: + etk_property_value_int_set(value, image->source); + break; case ETK_IMAGE_FILE_PROPERTY: - etk_property_value_string_set(value, image->filename); + if (image->source == ETK_IMAGE_FILE) + etk_property_value_string_set(value, image->info.file.filename); + else if (image->source == ETK_IMAGE_EDJE) + etk_property_value_string_set(value, image->info.edje.filename); + else + etk_property_value_string_set(value, NULL); + break; + case ETK_IMAGE_KEY_PROPERTY: + if (image->source == ETK_IMAGE_FILE) + etk_property_value_string_set(value, image->info.file.key); + else if (image->source == ETK_IMAGE_EDJE) + etk_property_value_string_set(value, image->info.edje.group); + else + etk_property_value_string_set(value, NULL); break; - case ETK_IMAGE_EDJE_FILE_PROPERTY: - etk_property_value_string_set(value, image->edje_filename); + case ETK_IMAGE_STOCK_ID_PROPERTY: + etk_property_value_int_set(value, image->info.stock.id); break; - case ETK_IMAGE_EDJE_GROUP_PROPERTY: - etk_property_value_string_set(value, image->edje_group); + case ETK_IMAGE_STOCK_SIZE_PROPERTY: + etk_property_value_int_set(value, image->info.stock.size); break; case ETK_IMAGE_EVAS_OBJECT_PROPERTY: - etk_property_value_pointer_set(value, image->image_object); - break; + etk_property_value_pointer_set(value, image->object); + break; case ETK_IMAGE_KEEP_ASPECT_PROPERTY: etk_property_value_bool_set(value, image->keep_aspect); break; - case ETK_IMAGE_USE_EDJE_PROPERTY: - etk_property_value_bool_set(value, image->use_edje); - break; - case ETK_IMAGE_STOCK_ID_PROPERTY: - etk_property_value_int_set(value, image->stock_id); - break; - case ETK_IMAGE_STOCK_SIZE_PROPERTY: - etk_property_value_int_set(value, image->stock_size); + case ETK_IMAGE_ASPECT_RATIO_PROPERTY: + etk_property_value_double_set(value, image->aspect_ratio); break; default: break; @@ -576,28 +729,7 @@ if (!(image = ETK_IMAGE(widget)) || !size) return; - - if (image->image_object) - { - if (image->use_object) - evas_object_geometry_get(image->image_object, NULL, NULL, &size->w, &size->h); - else if (image->use_edje) - { - Evas_Coord min_x, min_y, calc_x, calc_y; - - edje_object_size_min_get(image->image_object, &min_x, &min_y); - edje_object_size_min_calc(image->image_object, &calc_x, &calc_y); - size->w = ETK_MAX(min_x, calc_x); - size->h = ETK_MAX(min_y, calc_y); - } - else - evas_object_image_size_get(image->image_object, &size->w, &size->h); - } - else - { - size->w = 0; - size->h = 0; - } + etk_image_size_get(image, &size->w, &size->h); } /* Resizes the image to the allocated size */ @@ -607,8 +739,7 @@ if (!(image = ETK_IMAGE(widget))) return; - - if (!image->image_object) + if (!image->object) return; if (image->keep_aspect) @@ -616,20 +747,20 @@ double aspect_ratio; int image_w, image_h; int new_size; - - if (image->use_object) - evas_object_geometry_get(image->image_object, NULL, NULL, &image_w, &image_h); - else if (image->use_edje) - edje_object_size_min_get(image->image_object, &image_w, &image_h); + + if (image->aspect_ratio > 0.0) + aspect_ratio = image->aspect_ratio; else - evas_object_image_size_get(image->image_object, &image_w, &image_h); - if (image_w <= 0 || image_h <= 0) { - image_w = 1; - image_h = 1; + etk_image_size_get(image, &image_w, &image_h); + if (image_w <= 0 || image_h <= 0) + { + image_w = 1; + image_h = 1; + } + aspect_ratio = (double)image_w / (double)image_h; } - aspect_ratio = (double)image_w / (double)image_h; if (geometry.h * aspect_ratio > geometry.w) { new_size = geometry.w / aspect_ratio; @@ -644,11 +775,11 @@ } } - if (!image->use_edje && !image->use_object) - evas_object_image_fill_set(image->image_object, 0, 0, geometry.w, geometry.h); + if (image->source == ETK_IMAGE_FILE || image->source == ETK_IMAGE_DATA) + evas_object_image_fill_set(image->object, 0, 0, geometry.w, geometry.h); - evas_object_move(image->image_object, geometry.x, geometry.y); - evas_object_resize(image->image_object, geometry.w, geometry.h); + evas_object_move(image->object, geometry.x, geometry.y); + evas_object_resize(image->object, geometry.w, geometry.h); } /************************** @@ -667,104 +798,147 @@ _etk_image_load(image); } -/* Called when the image is unrealized */ -static void _etk_image_unrealize_cb(Etk_Object *object, void *data) -{ - Etk_Image *image; - - if (!(image = ETK_IMAGE(object))) - return; - image->image_object = NULL; -} - /************************** * * Private functions * **************************/ +/* Sets the source of the image */ +static void _etk_image_source_set(Etk_Image *image, Etk_Image_Source source) +{ + if (!image || image->source == source) + return; + + switch (image->source) + { + case ETK_IMAGE_FILE: + free(image->info.file.filename); + free(image->info.file.key); + break; + case ETK_IMAGE_EDJE: + free(image->info.edje.filename); + free(image->info.edje.group); + break; + case ETK_IMAGE_DATA: + if (image->info.data.copied) + free(image->info.data.pixels); + break; + default: + break; + } + + switch (source) + { + case ETK_IMAGE_FILE: + image->info.file.filename = NULL; + image->info.file.key = NULL; + break; + case ETK_IMAGE_EDJE: + image->info.edje.filename = NULL; + image->info.edje.group = NULL; + break; + case ETK_IMAGE_STOCK: + image->info.stock.id = ETK_STOCK_NO_STOCK; + image->info.stock.size = ETK_STOCK_SMALL; + break; + case ETK_IMAGE_DATA: + image->info.data.size.w = 0; + image->info.data.size.h = 0; + image->info.data.copied = ETK_FALSE; + image->info.data.pixels = NULL; + break; + default: + break; + } + + if (image->object && image->source != ETK_IMAGE_EVAS_OBJECT) + evas_object_del(image->object); + image->object = NULL; + + image->source = source; + etk_object_notify(ETK_OBJECT(image), "source"); +} + /* Load the image from the image or the edje file */ static void _etk_image_load(Etk_Image *image) { - Etk_Widget *widget; - - if (!(widget = ETK_WIDGET(image))) + Evas *evas; + + if (!image || !(evas = etk_widget_toplevel_evas_get(ETK_WIDGET(image)))) return; - - if (image->image_object && image->object_type_changed) + + /* Create the Evas object */ + if (!image->object) { - if (!image->use_object) + switch (image->source) { - etk_widget_member_object_del(widget, image->image_object); - evas_object_del(image->image_object); - image->image_object = NULL; + case ETK_IMAGE_FILE: + case ETK_IMAGE_DATA: + image->object = evas_object_image_add(evas); + break; + case ETK_IMAGE_EDJE: + case ETK_IMAGE_STOCK: + image->object = edje_object_add(evas); + break; + default: + break; } - image->object_type_changed = ETK_FALSE; } - if (image->filename) + + if (!image->object) + return; + etk_widget_member_object_add(ETK_WIDGET(image), image->object); + + /* Load the image */ + switch (image->source) { - int error_code; - Evas *evas; - - if (!image->image_object && (evas = etk_widget_toplevel_evas_get(widget))) - { - /* TODO: FIXME: the image might not be realized here... */ - image->image_object = evas_object_image_add(evas); - etk_widget_member_object_add(widget, image->image_object); - } - if (image->image_object) + case ETK_IMAGE_FILE: { const char *image_file; + int error_code; - evas_object_image_file_get(image->image_object, &image_file, NULL); - if (!image_file || strcmp(image_file, image->filename) != 0) + evas_object_image_file_get(image->object, &image_file, NULL); + if (!image_file || !image->info.file.filename || strcmp(image_file, image->info.file.filename) != 0) { - evas_object_image_file_set(image->image_object, image->filename, NULL); - if ((error_code = evas_object_image_load_error_get(image->image_object))) - { - ETK_WARNING("Unable to load image from file \"%s\", error %d", image->filename, error_code); - evas_object_hide(image->image_object); - } - else - evas_object_show(image->image_object); + evas_object_image_file_set(image->object, image->info.file.filename, image->info.file.key); + if ((error_code = evas_object_image_load_error_get(image->object))) + ETK_WARNING("Unable to load image from file \"%s\", error %d", image->info.file.filename, error_code); } + break; } - } - else if (image->edje_filename && image->edje_group) - { - int error_code; - Evas *evas; - - if (!image->image_object && (evas = etk_widget_toplevel_evas_get(widget))) - { - image->image_object = edje_object_add(evas); - etk_widget_member_object_add(widget, image->image_object); - } - if (image->image_object) + case ETK_IMAGE_EDJE: + case ETK_IMAGE_STOCK: { - const char *edje_file, *edje_group; + const char *file, *key; + int error_code; - edje_object_file_get(image->image_object, &edje_file, &edje_group); - if (!edje_file || !edje_group || strcmp(edje_file, image->edje_filename) != 0 || strcmp(edje_group, image->edje_group) != 0) + if (image->source == ETK_IMAGE_STOCK) { - edje_object_file_set(image->image_object, image->edje_filename, image->edje_group); - if ((error_code = edje_object_load_error_get(image->image_object))) - { - ETK_WARNING("Unable to load image from edje file \"%s\"/\"%s\", error %d", image->edje_filename, image->edje_group, error_code); - evas_object_hide(image->image_object); - } - else - evas_object_show(image->image_object); + file = etk_theme_icon_get(); + key = etk_stock_key_get(image->info.stock.id, image->info.stock.size); } - } - } - else if (image->image_object && image->use_object) - { - etk_widget_member_object_add(widget, image->image_object); - evas_object_show(image->image_object); + else + { + file = image->info.edje.filename; + key = image->info.edje.group; + } + + edje_object_file_set(image->object, file, key); + if ((error_code = edje_object_load_error_get(image->object))) + ETK_WARNING("Unable to load image from edje-file \"%s\"/\"%s\", error %d", file, key, error_code); + break; + } + case ETK_IMAGE_DATA: + evas_object_image_size_set(image->object, image->info.data.size.w, image->info.data.size.h); + evas_object_image_data_set(image->object, image->info.data.pixels); + break; + default: + break; } - - etk_widget_size_recalc_queue(widget); + + evas_object_show(image->object); + etk_widget_size_recalc_queue(ETK_WIDGET(image)); } /** @} */ @@ -780,7 +954,7 @@ * * @image html widgets/image.png * The image can be loaded from several sources: image files (png, jpg, and the other formats supported by evas), edje - * files (edj), or from stock IDs. + * files (edj), stock-icons, data pixels or given Evas objects. * * \par Object Hierarchy: * - Etk_Object =================================================================== RCS file: /cvs/e/e17/proto/etk/src/lib/etk_image.h,v retrieving revision 1.11 retrieving revision 1.12 diff -u -3 -r1.11 -r1.12 --- etk_image.h 25 Dec 2006 14:04:53 -0000 1.11 +++ etk_image.h 29 Dec 2006 21:50:46 -0000 1.12 @@ -6,10 +6,6 @@ #include "etk_widget.h" #include "etk_stock.h" -/* TODO/FIXME list: - * - Add new/set_from_data() - */ - /** * @defgroup Etk_Image Etk_Image * @brief An Etk_Image is a widget that can load and display an image from various sources @@ -23,6 +19,16 @@ /** Check if the object is an Etk_Image */ #define ETK_IS_IMAGE(obj) (ETK_OBJECT_CHECK_TYPE((obj), ETK_IMAGE_TYPE)) +/** @brief The different sources that an Etk_Image can use */ +typedef enum Etk_Image_Source +{ + ETK_IMAGE_FILE, /**< The image is loaded from an image file */ + ETK_IMAGE_EDJE, /**< The image is loaded from an Edje file */ + ETK_IMAGE_STOCK, /**< The image is loaded from a stock id */ + ETK_IMAGE_EVAS_OBJECT, /**< The image shows an existing Evas Object */ + ETK_IMAGE_DATA /**< The image uses pixel data given by the user */ +} Etk_Image_Source; + /** * @brief @widget A widget that can load and display an image * @structinfo @@ -33,44 +39,72 @@ /* Inherit from Etk_Widget */ Etk_Widget widget; - Evas_Object *image_object; - char *filename; - char *edje_group; - char *edje_filename; + Evas_Object *object; - Etk_Stock_Id stock_id; - Etk_Stock_Size stock_size; + Etk_Image_Source source; + union + { + struct + { + char *filename; + char *key; + } file; + + struct + { + char *filename; + char *group; + } edje; + + struct + { + Etk_Stock_Id id; + Etk_Stock_Size size; + } stock; + + struct + { + void *pixels; + Etk_Size size; + Etk_Bool copied; + } data; + } info; + double aspect_ratio; Etk_Bool keep_aspect; - Etk_Bool use_edje; - Etk_Bool use_object; - Etk_Bool object_type_changed; }; -Etk_Type *etk_image_type_get(); -Etk_Widget *etk_image_new(); +Etk_Type *etk_image_type_get(void); + +Etk_Widget *etk_image_new(void); Etk_Widget *etk_image_new_from_file(const char *filename); -Etk_Widget *etk_image_new_from_edje(const char *edje_filename, const char *edje_group); -Etk_Widget *etk_image_new_from_evas_object(Evas_Object *evas_object); +Etk_Widget *etk_image_new_from_edje(const char *filename, const char *group); Etk_Widget *etk_image_new_from_stock(Etk_Stock_Id stock_id, Etk_Stock_Size stock_size); +Etk_Widget *etk_image_new_from_evas_object(Evas_Object *evas_object); +Etk_Widget *etk_image_new_from_data(int width, int height, void *data, Etk_Bool copy); -void etk_image_set_from_file(Etk_Image *image, const char *filename); -const char *etk_image_file_get(Etk_Image *image); - -void etk_image_set_from_edje(Etk_Image *image, const char *edje_filename, const char *edje_group); -void etk_image_edje_get(Etk_Image *image, char **edje_filename, char **edje_group); - +void etk_image_set_from_file(Etk_Image *image, const char *filename); +const char *etk_image_file_get(Etk_Image *image); +void etk_image_set_from_edje(Etk_Image *image, const char *filename, const char *group); +void etk_image_edje_get(Etk_Image *image, char **filename, char **group); +void etk_image_set_from_stock(Etk_Image *image, Etk_Stock_Id stock_id, Etk_Stock_Size stock_size); +void etk_image_stock_get(Etk_Image *image, Etk_Stock_Id *stock_id, Etk_Stock_Size *stock_size); void etk_image_set_from_evas_object(Etk_Image *image, Evas_Object *evas_object); Evas_Object *etk_image_evas_object_get(Etk_Image *image); +void etk_image_set_from_data(Etk_Image *image, int width, int height, void *data, Etk_Bool copy); +void *etk_image_data_get(Etk_Image *image, Etk_Bool for_writing); -void etk_image_set_from_stock(Etk_Image *image, Etk_Stock_Id stock_id, Etk_Stock_Size stock_size); -void etk_image_stock_get(Etk_Image *image, Etk_Stock_Id *stock_id, Etk_Stock_Size *stock_size); +Etk_Image_Source etk_image_source_get(Etk_Image *image); +void etk_image_update(Etk_Image *image); +void etk_image_update_rect(Etk_Image *image, int x, int y, int w, int h); void etk_image_copy(Etk_Image *dest_image, Etk_Image *src_image); void etk_image_size_get(Etk_Image *image, int *width, int *height); void etk_image_keep_aspect_set(Etk_Image *image, Etk_Bool keep_aspect); Etk_Bool etk_image_keep_aspect_get(Etk_Image *image); +void etk_image_aspect_ratio_set(Etk_Image *image, double aspect_ratio); +double etk_image_aspect_ratio_get(Etk_Image *image); /** @} */ ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys - and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ enlightenment-cvs mailing list enlightenment-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-cvs