diff --git a/rtgui/common/dc.c b/rtgui/common/dc.c index d1b819d12c..1987d08bd3 100644 --- a/rtgui/common/dc.c +++ b/rtgui/common/dc.c @@ -12,8 +12,8 @@ * 2009-10-16 Bernard first version */ #include -#include - +#include + #include /* for strlen */ #include /* fir qsort */ @@ -743,8 +743,6 @@ void rtgui_dc_draw_arc(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16 { rt_int16_t cx = 0; rt_int16_t cy = r; - rt_int16_t ocx = (rt_int16_t) 0xffff; - rt_int16_t ocy = (rt_int16_t) 0xffff; rt_int16_t df = 1 - r; rt_int16_t d_e = 3; rt_int16_t d_se = -2 * r + 5; diff --git a/rtgui/common/image_hdc.c b/rtgui/common/image_hdc.c new file mode 100644 index 0000000000..f5dc561dd8 --- /dev/null +++ b/rtgui/common/image_hdc.c @@ -0,0 +1,245 @@ +#include "libpng/png.h" +#include +#include +#include + +#define HDC_MAGIC_LEN 4 + +struct rtgui_image_hdc +{ + rt_bool_t is_loaded; + + struct rtgui_filerw* filerw; + + /* hdc image information */ + rt_uint32_t width, height; + rt_uint32_t pitch; + + rt_uint8_t *pixels; +}; + +static rt_bool_t rtgui_image_hdc_check(struct rtgui_filerw* file); +static rt_bool_t rtgui_image_hdc_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load); +static void rtgui_image_hdc_unload(struct rtgui_image* image); +static void rtgui_image_hdc_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect); + +struct rtgui_image_engine rtgui_image_hdc_engine = +{ + "hdc", + { RT_NULL }, + rtgui_image_hdc_check, + rtgui_image_hdc_load, + rtgui_image_hdc_unload, + rtgui_image_hdc_blit +}; + +static rt_bool_t rtgui_image_hdc_check(struct rtgui_filerw* file) +{ + int start; + rt_bool_t is_HDC; + rt_uint8_t magic[4]; + + if ( !file ) return 0; + + start = rtgui_filerw_tell(file); + + /* move to the begining of file */ + rtgui_filerw_seek(file, 0, SEEK_SET); + + is_HDC = RT_FALSE; + if ( rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic) ) + { + if ( magic[0] == 'H' && + magic[1] == 'D' && + magic[2] == 'C' && + magic[3] == '\0' ) + { + is_HDC = RT_TRUE; + } + } + rtgui_filerw_seek(file, start, SEEK_SET); + + return(is_HDC); +} + +static rt_bool_t rtgui_image_hdc_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load) +{ + rt_uint32_t header[5]; + struct rtgui_image_hdc* hdc; + + hdc = (struct rtgui_image_hdc*) rtgui_malloc(sizeof(struct rtgui_image_hdc)); + if (hdc == RT_NULL) return RT_FALSE; + + rtgui_filerw_read(file, (char*)&header, 1, sizeof(header)); + + /* set image information */ + image->w = header[1]; image->h = header[2]; + image->engine = &rtgui_image_hdc_engine; + image->data = png; + + if (bit_depth == 16) + png_set_strip_16(png->png_ptr); + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png->png_ptr); + if (bit_depth < 8) + png_set_expand(png->png_ptr); + if (png_get_valid(png->png_ptr, png->info_ptr, PNG_INFO_tRNS)) + png_set_expand(png->png_ptr); + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png->png_ptr); + + /* Ignore background color */ + + /* set gamma conversion */ + if (png_get_gAMA(png->png_ptr, png->info_ptr, &gamma)) + png_set_gamma(png->png_ptr, (double)2.2, gamma); + + png_read_update_info(png->png_ptr, png->info_ptr); + + if (load == RT_TRUE) + { + /* load all pixels */ + png->pixels = rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t)); + if (png->pixels == RT_NULL) + { + png_read_end(png->png_ptr, RT_NULL); + + /* destroy png struct */ + png_destroy_info_struct(png->png_ptr, &png->info_ptr); + png_destroy_read_struct(&png->png_ptr, RT_NULL, RT_NULL); + + /* release data */ + rtgui_free(png); + return RT_FALSE; + } + + rtgui_image_hdc_process(png->png_ptr, png->info_ptr, png); + } + else + { + png->pixels = RT_NULL; + } + + return RT_TRUE; +} + +static void rtgui_image_hdc_unload(struct rtgui_image* image) +{ + struct rtgui_image_hdc* png; + + if (image != RT_NULL) + { + png = (struct rtgui_image_hdc*) image->data; + + png_read_end(png->png_ptr, RT_NULL); + + /* destroy png struct */ + png_destroy_info_struct(png->png_ptr, &png->info_ptr); + png_destroy_read_struct(&png->png_ptr, RT_NULL, RT_NULL); + + if (png->pixels != RT_NULL) rtgui_free(png->pixels); + + /* release data */ + rtgui_free(png); + } +} + +static void rtgui_image_hdc_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect) +{ + rt_uint16_t x, y, w, h; + rtgui_color_t* ptr; + rtgui_color_t foreground; + struct rtgui_image_hdc* png; + + RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL); + RT_ASSERT(image->data != RT_NULL); + + png = (struct rtgui_image_hdc*) image->data; + + if (image->w < rtgui_rect_width(*rect)) w = image->w; + else w = rtgui_rect_width(*rect); + if (image->h < rtgui_rect_height(*rect)) h = image->h; + else h = rtgui_rect_height(*rect); + + /* save foreground color */ + foreground = rtgui_dc_get_color(dc); + + if (png->pixels != RT_NULL) + { + ptr = (rtgui_color_t*)png->pixels; + /* draw each point within dc */ + for (y = 0; y < h; y ++) + { + for (x = 0; x < w; x++) + { + /* not alpha */ + if ((*ptr >> 24) != 255) + { + rtgui_dc_set_color(dc, *ptr); + rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1); + } + + /* move to next color buffer */ + ptr ++; + } + } + } + else + { + png_bytep row; + png_bytep data; + + row = (png_bytep) rtgui_malloc (png_get_rowbytes(png->png_ptr, png->info_ptr)); + if (row == RT_NULL) return ; + + switch (png->info_ptr->color_type) + { + case PNG_COLOR_TYPE_RGBA: + for (y = 0; y < h; y++) + { + png_read_row(png->png_ptr, row, png_bytep_NULL); + for (x = 0; x < w; x++) + { + data = &(row[x * 4]); + if (data[3] != 0) + { + rtgui_dc_set_color(dc, RTGUI_ARGB((255 - data[3]), data[0], data[1], data[2])); + rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1); + } + } + } + + break; + + case PNG_COLOR_TYPE_PALETTE: + for (y = 0; y < h; y++) + { + png_read_row(png->png_ptr, row, png_bytep_NULL); + for (x = 0; x < w; x++) + { + data = &(row[x]); + + rtgui_dc_set_color(dc, RTGUI_ARGB(0, png->info_ptr->palette[data[0]].red, + png->info_ptr->palette[data[0]].green, + png->info_ptr->palette[data[0]].blue)); + rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1); + } + } + + default: + break; + }; + + rtgui_free(row); + } + + /* restore foreground */ + rtgui_dc_set_color(dc, foreground); +} + +void rtgui_image_hdc_init() +{ + /* register png on image system */ + rtgui_image_register_engine(&rtgui_image_hdc_engine); +} diff --git a/rtgui/common/image_png.c b/rtgui/common/image_png.c index 6ea8bab52c..95dc817509 100644 --- a/rtgui/common/image_png.c +++ b/rtgui/common/image_png.c @@ -16,7 +16,6 @@ struct rtgui_image_png png_infop info_ptr; rt_uint8_t *pixels; - rt_uint8_t *line_pixels; }; static rt_bool_t rtgui_image_png_check(struct rtgui_filerw* file); @@ -182,16 +181,26 @@ static rt_bool_t rtgui_image_png_load(struct rtgui_image* image, struct rtgui_fi { /* load all pixels */ png->pixels = rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t)); - png->line_pixels = RT_NULL; + if (png->pixels == RT_NULL) + { + png_read_end(png->png_ptr, RT_NULL); + + /* destroy png struct */ + png_destroy_info_struct(png->png_ptr, &png->info_ptr); + png_destroy_read_struct(&png->png_ptr, RT_NULL, RT_NULL); + + /* release data */ + rtgui_free(png); + return RT_FALSE; + } rtgui_image_png_process(png->png_ptr, png->info_ptr, png); } else { - png->line_pixels = rtgui_malloc(image->w * sizeof(rtgui_color_t)); png->pixels = RT_NULL; } - + return RT_TRUE; } @@ -203,14 +212,13 @@ static void rtgui_image_png_unload(struct rtgui_image* image) { png = (struct rtgui_image_png*) image->data; - png_read_end(png->png_ptr, NULL); + png_read_end(png->png_ptr, RT_NULL); /* destroy png struct */ png_destroy_info_struct(png->png_ptr, &png->info_ptr); - png_destroy_read_struct(&png->png_ptr, NULL, NULL); + png_destroy_read_struct(&png->png_ptr, RT_NULL, RT_NULL); if (png->pixels != RT_NULL) rtgui_free(png->pixels); - if (png->line_pixels != RT_NULL) rtgui_free(png->line_pixels); /* release data */ rtgui_free(png); @@ -219,7 +227,7 @@ static void rtgui_image_png_unload(struct rtgui_image* image) static void rtgui_image_png_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect) { - rt_uint16_t x, y; + rt_uint16_t x, y, w, h; rtgui_color_t* ptr; rtgui_color_t foreground; struct rtgui_image_png* png; @@ -228,27 +236,83 @@ static void rtgui_image_png_blit(struct rtgui_image* image, struct rtgui_dc* dc, RT_ASSERT(image->data != RT_NULL); png = (struct rtgui_image_png*) image->data; - ptr = png->pixels; + + if (image->w < rtgui_rect_width(*rect)) w = image->w; + else w = rtgui_rect_width(*rect); + if (image->h < rtgui_rect_height(*rect)) h = image->h; + else h = rtgui_rect_height(*rect); /* save foreground color */ foreground = rtgui_dc_get_color(dc); - /* draw each point within dc */ - for (y = 0; y < image->h; y ++) - { - for (x = 0; x < image->w; x++) - { - /* not alpha */ - if ((*ptr >> 24) != 255) - { - rtgui_dc_set_color(dc, *ptr); - rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1); - } + if (png->pixels != RT_NULL) + { + ptr = (rtgui_color_t*)png->pixels; + /* draw each point within dc */ + for (y = 0; y < h; y ++) + { + for (x = 0; x < w; x++) + { + /* not alpha */ + if ((*ptr >> 24) != 255) + { + rtgui_dc_set_color(dc, *ptr); + rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1); + } - /* move to next color buffer */ - ptr ++; - } - } + /* move to next color buffer */ + ptr ++; + } + } + } + else + { + png_bytep row; + png_bytep data; + + row = (png_bytep) rtgui_malloc (png_get_rowbytes(png->png_ptr, png->info_ptr)); + if (row == RT_NULL) return ; + + switch (png->info_ptr->color_type) + { + case PNG_COLOR_TYPE_RGBA: + for (y = 0; y < h; y++) + { + png_read_row(png->png_ptr, row, png_bytep_NULL); + for (x = 0; x < w; x++) + { + data = &(row[x * 4]); + if (data[3] != 0) + { + rtgui_dc_set_color(dc, RTGUI_ARGB((255 - data[3]), data[0], data[1], data[2])); + rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1); + } + } + } + + break; + + case PNG_COLOR_TYPE_PALETTE: + for (y = 0; y < h; y++) + { + png_read_row(png->png_ptr, row, png_bytep_NULL); + for (x = 0; x < w; x++) + { + data = &(row[x]); + + rtgui_dc_set_color(dc, RTGUI_ARGB(0, png->info_ptr->palette[data[0]].red, + png->info_ptr->palette[data[0]].green, + png->info_ptr->palette[data[0]].blue)); + rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1); + } + } + + default: + break; + }; + + rtgui_free(row); + } /* restore foreground */ rtgui_dc_set_color(dc, foreground); @@ -256,6 +320,6 @@ static void rtgui_image_png_blit(struct rtgui_image* image, struct rtgui_dc* dc, void rtgui_image_png_init() { - /* register jpeg on image system */ + /* register png on image system */ rtgui_image_register_engine(&rtgui_image_png_engine); } diff --git a/rtgui/common/libpng/pngconf.h b/rtgui/common/libpng/pngconf.h index 10a6b3f0ad..611a0439bc 100644 --- a/rtgui/common/libpng/pngconf.h +++ b/rtgui/common/libpng/pngconf.h @@ -22,6 +22,7 @@ #ifdef __RT_THREAD__ #define PNG_NO_WRITE_SUPPORTED #define PNG_NO_STDIO +#define PNG_NO_SETJMP_SUPPORTED #define PNG_MAX_MALLOC_64K #define malloc rtgui_malloc #define free rtgui_free @@ -29,7 +30,7 @@ #define PNG_1_2_X -/* +/* * PNG_USER_CONFIG has to be defined on the compiler command line. This * includes the resource compiler for Windows DLL configurations. */ @@ -49,7 +50,7 @@ /* * Added at libpng-1.2.8 - * + * * If you create a private DLL you need to define in "pngusr.h" the followings: * #define PNG_USER_PRIVATEBUILD @@ -60,8 +61,8 @@ * number and must match your private DLL name> * e.g. // private DLL "libpng13gx.dll" * #define PNG_USER_DLLFNAME_POSTFIX "gx" - * - * The following macros are also at your disposal if you want to complete the + * + * The following macros are also at your disposal if you want to complete the * DLL VERSIONINFO structure. * - PNG_USER_VERSIONINFO_COMMENTS * - PNG_USER_VERSIONINFO_COMPANYNAME @@ -149,9 +150,9 @@ * 'Cygwin' defines/defaults: * PNG_BUILD_DLL -- (ignored) building the dll * (no define) -- (ignored) building an application, linking to the dll - * PNG_STATIC -- (ignored) building the static lib, or building an + * PNG_STATIC -- (ignored) building the static lib, or building an * application that links to the static lib. - * ALL_STATIC -- (ignored) building various static libs, or building an + * ALL_STATIC -- (ignored) building various static libs, or building an * application that links to the static libs. * Thus, * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and @@ -164,12 +165,12 @@ * PNG_BUILD_DLL * PNG_STATIC * (nothing) == PNG_USE_DLL - * + * * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent - * of auto-import in binutils, we no longer need to worry about + * of auto-import in binutils, we no longer need to worry about * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes - * to __declspec() stuff. However, we DO need to worry about + * to __declspec() stuff. However, we DO need to worry about * PNG_BUILD_DLL and PNG_STATIC because those change some defaults * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. */ @@ -213,8 +214,8 @@ # if !defined(PNG_DLL) # define PNG_DLL # endif -# endif -# endif +# endif +# endif # endif #endif @@ -730,7 +731,7 @@ # define PNG_EASY_ACCESS_SUPPORTED #endif -/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 +/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 * even when PNG_USE_PNGVCRD or PNG_USE_PNGGCCRD is not defined. * * PNG_NO_ASSEMBLER_CODE disables use of all assembler code and optimized C, @@ -1295,7 +1296,7 @@ typedef z_stream FAR * png_zstreamp; # define PNGAPI __cdecl # undef PNG_IMPEXP # define PNG_IMPEXP -#endif +#endif /* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", * you may get warnings regarding the linkage of png_zalloc and png_zfree. @@ -1460,7 +1461,7 @@ typedef z_stream FAR * png_zstreamp; # define PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT 128 /* >= */ #endif #ifndef PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT -# define PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT 9 /* >= */ +# define PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT 9 /* >= */ #endif /* Set this in the makefile for VC++ on Pentium, not here. */