summaryrefslogtreecommitdiff
path: root/components/rtgui/common
diff options
context:
space:
mode:
author[email protected] <[email protected]>2012-07-20 12:37:56 +0000
committer[email protected] <[email protected]>2012-07-20 12:37:56 +0000
commit92a50c838d8ca2ae4027fd77b71db12fb52d86e3 (patch)
tree08cb5a9273c78c36df97f48eea17eb2e1034a497 /components/rtgui/common
parentc2868be90d0f1f43ee13bacdb1c0f55a9fe34276 (diff)
sync with RTGUI c074ff2898b9e
Full log is in GitHub. git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2222 bbd45198-f89e-11dd-88c7-29a3b14d5316
Diffstat (limited to 'components/rtgui/common')
-rw-r--r--components/rtgui/common/blit.c66
-rw-r--r--components/rtgui/common/dc.c4
-rw-r--r--components/rtgui/common/dc_client.c6
-rw-r--r--components/rtgui/common/dc_hw.c6
-rw-r--r--components/rtgui/common/framebuffer_driver.c7
-rw-r--r--components/rtgui/common/image.c5
-rw-r--r--components/rtgui/common/image_bmp.c1195
-rw-r--r--components/rtgui/common/image_jpg.c479
-rw-r--r--components/rtgui/common/image_png.c56
-rw-r--r--components/rtgui/common/pixel_driver.c55
-rw-r--r--components/rtgui/common/rtgui_app.c380
-rw-r--r--components/rtgui/common/rtgui_system.c419
12 files changed, 2144 insertions, 534 deletions
diff --git a/components/rtgui/common/blit.c b/components/rtgui/common/blit.c
index a9b0b36749..1d84fc3a00 100644
--- a/components/rtgui/common/blit.c
+++ b/components/rtgui/common/blit.c
@@ -1,3 +1,9 @@
+/*
+ * Change Logs:
+ * Date Author Notes
+ * 2012-01-24 onelife add one more blit table which exchanges the
+ * positions of R and B color components in output
+ */
#include <rtgui/rtgui.h>
#include <rtgui/blit.h>
@@ -305,3 +311,63 @@ rtgui_blit_line_func rtgui_blit_line_get(int dst_bpp, int src_bpp)
return _blit_table[dst_bpp][src_bpp];
}
+
+
+static void rtgui_blit_line_3_2_inv(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+ rt_uint16_t* dst;
+
+ dst = (rt_uint16_t*)dst_ptr;
+ line = line / 3;
+ while (line)
+ {
+ *dst = (((*src_ptr << 8) & 0x0000F800) |
+ ((*(src_ptr + 1) << 3) & 0x000007E0) |
+ ((*(src_ptr + 2) >> 3) & 0x0000001F));
+
+ src_ptr += 3;
+ dst ++;
+ line --;
+ }
+
+ return;
+}
+
+void rtgui_blit_line_2_2_inv(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+ rt_uint16_t *dst, *src;
+
+ dst = (rt_uint16_t *)dst_ptr;
+ src = (rt_uint16_t *)src_ptr;
+ line = line / 2;
+ while (line)
+ {
+ *dst = ((*src << 11) & 0xF800) | (*src & 0x07E0) | ((*src >> 11) & 0x001F);
+ src ++;
+ dst ++;
+ line --;
+ }
+}
+
+static const rtgui_blit_line_func _blit_table_inv[5][5] =
+{
+ /* 0_0, 1_0, 2_0, 3_0, 4_0 */
+ {RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL },
+ /* 0_1, 1_1, 2_1, 3_1, 4_1 */
+ {RT_NULL, rtgui_blit_line_direct, rtgui_blit_line_2_1, rtgui_blit_line_3_1, rtgui_blit_line_4_1 },
+ /* 0_2, 1_2, 2_2, 3_2, 4_2 */
+ {RT_NULL, rtgui_blit_line_1_2, rtgui_blit_line_2_2_inv, rtgui_blit_line_3_2_inv, rtgui_blit_line_4_2 },
+ /* 0_3, 1_3, 2_3, 3_3, 4_3 */
+ {RT_NULL, rtgui_blit_line_1_3, rtgui_blit_line_2_3, rtgui_blit_line_direct, rtgui_blit_line_4_3 },
+ /* 0_4, 1_4, 2_4, 3_4, 4_4 */
+ {RT_NULL, rtgui_blit_line_1_4, rtgui_blit_line_2_4, rtgui_blit_line_3_4, rtgui_blit_line_direct },
+};
+
+rtgui_blit_line_func rtgui_blit_line_get_inv(int dst_bpp, int src_bpp)
+{
+ RT_ASSERT(dst_bpp>0 && dst_bpp < 5);
+ RT_ASSERT(src_bpp>0 && src_bpp < 5);
+
+ return _blit_table_inv[dst_bpp][src_bpp];
+}
+
diff --git a/components/rtgui/common/dc.c b/components/rtgui/common/dc.c
index fa8b85225a..97e6fcaf5c 100644
--- a/components/rtgui/common/dc.c
+++ b/components/rtgui/common/dc.c
@@ -138,12 +138,12 @@ void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2)
color = RTGUI_DC_FC(dc);
RTGUI_DC_FC(dc) = dark_grey;
- rtgui_dc_draw_hline(dc, x, y1, y2);
+ rtgui_dc_draw_vline(dc, x, y1, y2);
x ++;
RTGUI_DC_FC(dc) = high_light;
- rtgui_dc_draw_hline(dc, x, y1, y2);
+ rtgui_dc_draw_vline(dc, x, y1, y2);
/* restore color */
RTGUI_DC_FC(dc) = color;
diff --git a/components/rtgui/common/dc_client.c b/components/rtgui/common/dc_client.c
index 22d2887095..154eb359bd 100644
--- a/components/rtgui/common/dc_client.c
+++ b/components/rtgui/common/dc_client.c
@@ -21,7 +21,7 @@
#include <rtgui/driver.h>
#include <rtgui/rtgui_system.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/widgets/container.h>
#include <rtgui/widgets/window.h>
@@ -139,7 +139,7 @@ struct rtgui_dc* rtgui_dc_client_create(rtgui_widget_t* owner)
#endif
}
}
- else if (RTGUI_IS_APPLICATION(owner->toplevel))
+ else if (RTGUI_IS_APP(owner->toplevel))
{
RT_ASSERT(0);
}
@@ -207,7 +207,7 @@ static rt_bool_t rtgui_dc_client_fini(struct rtgui_dc* dc)
#endif
}
}
- else if (RTGUI_IS_APPLICATION(owner->toplevel) ||
+ else if (RTGUI_IS_APP(owner->toplevel) ||
RTGUI_IS_WIN(owner->toplevel))
{
rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
diff --git a/components/rtgui/common/dc_hw.c b/components/rtgui/common/dc_hw.c
index 2895797974..db226fd152 100644
--- a/components/rtgui/common/dc_hw.c
+++ b/components/rtgui/common/dc_hw.c
@@ -15,7 +15,7 @@
#include <rtgui/dc_hw.h>
#include <rtgui/driver.h>
#include <rtgui/rtgui_system.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/widgets/container.h>
@@ -117,7 +117,7 @@ struct rtgui_dc* rtgui_dc_hw_create(rtgui_widget_t* owner)
#endif
}
}
- else if (RTGUI_IS_APPLICATION(owner->toplevel) ||
+ else if (RTGUI_IS_APP(owner->toplevel) ||
RTGUI_IS_WIN(owner->toplevel))
{
rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
@@ -184,7 +184,7 @@ static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc* dc)
#endif
}
}
- else if (RTGUI_IS_APPLICATION(owner->toplevel) ||
+ else if (RTGUI_IS_APP(owner->toplevel) ||
RTGUI_IS_WIN(owner->toplevel))
{
rtgui_toplevel_t* top = RTGUI_TOPLEVEL(owner->toplevel);
diff --git a/components/rtgui/common/framebuffer_driver.c b/components/rtgui/common/framebuffer_driver.c
index 04c21c42a5..3d46732ebb 100644
--- a/components/rtgui/common/framebuffer_driver.c
+++ b/components/rtgui/common/framebuffer_driver.c
@@ -1,3 +1,8 @@
+/*
+ * Change Logs:
+ * Date Author Notes
+ * 2012-01-24 onelife fix a bug in framebuffer_draw_raw_hline
+ */
#include <rtgui/rtgui_system.h>
#include <rtgui/driver.h>
@@ -108,7 +113,7 @@ static void framebuffer_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y
rt_uint8_t *dst;
dst = GET_PIXEL(rtgui_graphic_get_device(), x1, y, rt_uint8_t);
- rt_memcpy(dst, pixels, (x2 - x1) * (rtgui_graphic_get_device()->bits_per_pixel/8));
+ rt_memcpy(dst, pixels, (x2 - x1 + 1) * (rtgui_graphic_get_device()->bits_per_pixel/8));
}
const struct rtgui_graphic_driver_ops _framebuffer_rgb565_ops =
diff --git a/components/rtgui/common/image.c b/components/rtgui/common/image.c
index 1ae57e0ece..358ba2bff5 100644
--- a/components/rtgui/common/image.c
+++ b/components/rtgui/common/image.c
@@ -10,6 +10,7 @@
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
+ * 2012-01-24 onelife add TJpgDec (Tiny JPEG Decompressor) support
*/
#include <rtthread.h>
#include <rtgui/image.h>
@@ -27,7 +28,7 @@
#ifdef RTGUI_IMAGE_BMP
#include <rtgui/image_bmp.h>
#endif
-#ifdef RTGUI_IMAGE_JPEG
+#if (defined(RTGUI_IMAGE_JPEG) || defined(RTGUI_IMAGE_TJPGD))
#include <rtgui/image_jpeg.h>
#endif
#ifdef RTGUI_IMAGE_PNG
@@ -50,7 +51,7 @@ void rtgui_system_image_init(void)
rtgui_image_bmp_init();
#endif
-#ifdef RTGUI_IMAGE_JPEG
+#if (defined(RTGUI_IMAGE_JPEG) || defined(RTGUI_IMAGE_TJPGD))
rtgui_image_jpeg_init();
#endif
diff --git a/components/rtgui/common/image_bmp.c b/components/rtgui/common/image_bmp.c
index 1c7c108217..2374c7537b 100644
--- a/components/rtgui/common/image_bmp.c
+++ b/components/rtgui/common/image_bmp.c
@@ -1,3 +1,10 @@
+/*
+ * Change Logs:
+ * Date Author Notes
+ * 2012-01-24 onelife Reimplement to improve efficiency and add
+ * features. The new decoder uses configurable fixed size working buffer and
+ * provides scaledown function.
+ */
#include <rtthread.h>
#include <rtgui/dc_hw.h>
#include <rtgui/image.h>
@@ -5,6 +12,10 @@
#include <rtgui/image_bmp.h>
#include <rtgui/blit.h>
+#ifdef RTGUI_USING_DFS_FILERW
+#include <dfs_posix.h>
+#endif
+
#ifdef RTGUI_IMAGE_BMP
/* Compression encodings for BMP files */
#ifndef BI_RGB
@@ -14,57 +25,32 @@
#define BI_BITFIELDS 3
#endif
-#define hw_driver (rtgui_graphic_driver_get_default())
+#define BMP_WORKING_BUFFER_SIZE (384) /* In multiple of 12 and bigger than 48 */
+#define BMP_MAX_SCALING_FACTOR (10) // TODO: find the max value!
+#define hw_driver (rtgui_graphic_driver_get_default())
struct rtgui_image_bmp
{
rt_bool_t is_loaded;
-
- rt_uint32_t Rmask;
- rt_uint32_t Gmask;
- rt_uint32_t Bmask;
-
- rt_size_t pixel_offset;
-
- rt_uint8_t byte_per_pixel;
- rt_uint8_t pad;
- rt_uint8_t ExpandBMP;
-
rt_uint8_t *pixels;
- rt_uint8_t *line_pixels;
- rt_uint32_t pitch;
-
struct rtgui_filerw* filerw;
+ rt_uint32_t w, h;
+ rt_uint32_t pixel_offset;
+ rt_uint32_t pitch; rt_uint8_t scale;
+ rt_uint8_t bit_per_pixel;
+ rt_uint8_t pad;
};
-struct rtgui_image_bmp_header
-{
- /* The Win32 BMP file header (14 bytes) */
- char magic[2];
- rt_uint32_t bfSize;
- rt_uint16_t bfReserved1;
- rt_uint16_t bfReserved2;
- rt_uint32_t bfOffBits;
-
- /* The Win32 BITMAPINFOHEADER struct (40 bytes) */
- rt_uint32_t biSize;
- rt_int32_t biWidth;
- rt_int32_t biHeight;
- rt_uint16_t biPlanes;
- rt_uint16_t biBitCount;
- rt_uint32_t biCompression;
- rt_uint32_t biSizeImage;
- rt_int32_t biXPelsPerMeter;
- rt_int32_t biYPelsPerMeter;
- rt_uint32_t biClrUsed;
- rt_uint32_t biClrImportant;
-};
-
+/* static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file,
+ rt_uint32_t *width, rt_uint32_t *height);
+static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image,
+ struct rtgui_filerw* file, rt_uint8_t scale, rt_bool_t load); */
static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file);
static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
static void rtgui_image_bmp_unload(struct rtgui_image* image);
static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
+
struct rtgui_image_engine rtgui_image_bmp_engine =
{
"bmp",
@@ -75,342 +61,429 @@ struct rtgui_image_engine rtgui_image_bmp_engine =
rtgui_image_bmp_blit
};
-rt_inline rt_uint32_t rtgui_filerw_read32(struct rtgui_filerw* src)
-{
- rt_uint32_t value;
- rtgui_filerw_read(src, &value, (sizeof value), 1);
- return value;
-}
-
-rt_inline rt_uint16_t rtgui_filerw_read16(struct rtgui_filerw* src)
-{
- rt_uint16_t value;
- rtgui_filerw_read(src, &value, (sizeof value), 1);
- return value;
-
-}
-
static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file)
+//static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file,
+// rt_uint32_t *width, rt_uint32_t *height)
{
- char magic[2];
- rt_bool_t is_bmp;
- rt_off_t start;
-
- if ( !file ) return 0;
-
- start = rtgui_filerw_tell(file);
+ rt_uint8_t buffer[18];
+ rt_bool_t is_bmp = RT_FALSE;
- /* move to the beginning of file */
- rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET);
+ do
+ {
+ if (!file )
+ {
+ break;
+ }
- is_bmp = RT_FALSE;
- if ( rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic) )
- {
- if (magic[0] == 'B' &&
- magic[1] == 'M')
+ /* Prepare to decode */
+ if (rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET) < 0)
+ {
+ break;
+ }
+ if (rtgui_filerw_read(file, (void *)buffer, 18, 1) != 18)
+ {
+ break;
+ }
+ /* Read file type */
+ if (buffer[0] != 'B' || buffer[1] != 'M')
{
- is_bmp = RT_TRUE;
+ break;
}
- }
- rtgui_filerw_seek(file, start, RTGUI_FILE_SEEK_SET);
+ /* Read BMP header size */
+ if (*(rt_uint32_t *)&buffer[14] == 12)
+ { /* Bitmap Header Version 2.x */
+ if (rtgui_filerw_read(file, (void *)buffer, 8, 1) != 8)
+ {
+ break;
+ }
+ /* Read image size */
+// *width = (rt_uint32_t)*(rt_uint16_t *)&buffer[0];
+// *height = (rt_uint32_t)*(rt_uint16_t *)&buffer[2];
+ is_bmp = RT_TRUE;
+ }
+ else
+ { /* Bitmap Header Version bigger than 2.x */
+ if (rtgui_filerw_read(file, (void *)buffer, 8, 1) != 8)
+ {
+ break;
+ }
+ /* Read image size */
+// *width = *(rt_uint32_t *)&buffer[0];
+// *height = *(rt_uint32_t *)&buffer[4];
+ is_bmp = RT_TRUE;
+ }
+ } while(0);
- return(is_bmp);
+ return is_bmp;
}
-static struct rtgui_image_palette* rtgui_image_bmp_load_palette(struct rtgui_image_bmp_header* header, struct rtgui_filerw* src)
+static struct rtgui_image_palette* rtgui_image_bmp_load_palette(
+ struct rtgui_filerw* file,
+ rt_uint32_t colorsUsed,
+ rt_bool_t alpha)
{
/* Load the palette, if any */
- rt_size_t i;
- struct rtgui_image_palette* palette;
+ rt_uint32_t i;
+ struct rtgui_image_palette *palette;
- if (header->biClrUsed == 0)
- header->biClrUsed = 1 << header->biBitCount;
+ palette = rtgui_image_palette_create(colorsUsed);
+ if (palette == RT_NULL)
+ {
+ return RT_NULL;
+ }
- palette = rtgui_image_palette_create(header->biClrUsed);
- if (palette == RT_NULL) return RT_NULL;
-
- if ( header->biSize == 12 )
- {
- rt_uint8_t r, g, b;
- for ( i = 0; i < (int)header->biClrUsed; ++i )
- {
- rtgui_filerw_read(src, &b, 1, 1);
- rtgui_filerw_read(src, &g, 1, 1);
- rtgui_filerw_read(src, &r, 1, 1);
- palette->colors[i] = RTGUI_RGB(r, g, b);
- }
- }
- else
- {
- rt_uint8_t r, g, b, a;
- for ( i = 0; i < (int)header->biClrUsed; ++i )
- {
- rtgui_filerw_read(src, &b, 1, 1);
- rtgui_filerw_read(src, &g, 1, 1);
- rtgui_filerw_read(src, &r, 1, 1);
- rtgui_filerw_read(src, &a, 1, 1);
- palette->colors[i] = RTGUI_ARGB(a, r, g, b);
- }
- }
+ if (alpha)
+ {
+ rt_uint8_t temp[4];
+ for (i = 0; i < colorsUsed; i++)
+ {
+ if (rtgui_filerw_read(file, (void *)&temp, 1, 4) != 4)
+ {
+ rtgui_free(palette);
+ return RT_NULL;
+ }
+ palette->colors[i] = RTGUI_ARGB(temp[3], temp[2], temp[1], temp[0]);
+ }
+ }
+ else
+ {
+ rt_uint8_t temp[3];
+ for (i = 0; i < colorsUsed; i++)
+ {
+ if (rtgui_filerw_read(file, (void *)&temp, 1, 3) != 3)
+ {
+ rtgui_free(palette);
+ return RT_NULL;
+ }
+ palette->colors[i] = RTGUI_RGB(temp[2], temp[1], temp[0]);
+ }
+ }
return palette;
}
-static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* src, rt_bool_t load)
+static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
+//static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image,
+// struct rtgui_filerw* file, rt_uint8_t scale, rt_bool_t load)
{
- rt_uint32_t Rmask;
- rt_uint32_t Gmask;
- rt_uint32_t Bmask;
- int ExpandBMP, bmpPitch;
+ rt_uint8_t scale = 2;
+ rt_uint8_t *wrkBuffer;
struct rtgui_image_bmp* bmp;
- struct rtgui_image_bmp_header* header;
- struct rtgui_image_palette* palette;
-
- bmp = RT_NULL;
- header = RT_NULL;
- palette = RT_NULL;
- header = (struct rtgui_image_bmp_header*) rtgui_malloc(sizeof(struct rtgui_image_bmp_header));
- if (header == RT_NULL) return RT_FALSE;
-
- if ( rtgui_filerw_read(src, header->magic, 1, sizeof(header->magic)) ==
- sizeof(sizeof(header->magic)) )
- {
- if (header->magic[0] != 'B' ||
- header->magic[1] != 'M')
- {
- goto __exit;
- }
- }
-
- header->bfSize = rtgui_filerw_read32(src);
- header->bfReserved1 = rtgui_filerw_read16(src);
- header->bfReserved2 = rtgui_filerw_read16(src);
- header->bfOffBits = rtgui_filerw_read32(src);
-
- /* Read the Win32 BITMAPINFOHEADER */
- header->biSize = rtgui_filerw_read32(src);
- if ( header->biSize == 12 )
- {
- header->biWidth = (rt_uint32_t)rtgui_filerw_read16(src);
- header->biHeight = (rt_uint32_t)rtgui_filerw_read16(src);
- header->biPlanes = rtgui_filerw_read16(src);
- header->biBitCount = rtgui_filerw_read16(src);
- header->biCompression = BI_RGB;
- header->biSizeImage = 0;
- header->biXPelsPerMeter = 0;
- header->biYPelsPerMeter = 0;
- header->biClrUsed = 0;
-
- header->biClrImportant = 0;
-
- }
- else
- {
- header->biWidth = rtgui_filerw_read32(src);
- header->biHeight = rtgui_filerw_read32(src);
- header->biPlanes = rtgui_filerw_read16(src);
- header->biBitCount = rtgui_filerw_read16(src);
- header->biCompression = rtgui_filerw_read32(src);
- header->biSizeImage = rtgui_filerw_read32(src);
- header->biXPelsPerMeter = rtgui_filerw_read32(src);
- header->biYPelsPerMeter = rtgui_filerw_read32(src);
- header->biClrUsed = rtgui_filerw_read32(src);
- header->biClrImportant = rtgui_filerw_read32(src);
-
- }
-
- /* allocate palette and expand 1 and 4 bit bitmaps to 8 bits per pixel */
- switch (header->biBitCount)
- {
- case 1:
- ExpandBMP = header->biBitCount;
- palette = rtgui_image_bmp_load_palette(header, src);
- header->biBitCount = 8;
- break;
+ rt_uint32_t bmpHeaderSize;
+ rt_uint32_t colorsUsed;
- case 4:
- ExpandBMP = header->biBitCount;
- palette = rtgui_image_bmp_load_palette(header, src);
- header->biBitCount = 8;
- break;
+ if (scale > BMP_MAX_SCALING_FACTOR)
+ {
+ return RT_FALSE;
+ }
- case 8:
- palette = rtgui_image_bmp_load_palette(header, src);
- ExpandBMP = 0;
- break;
+ do
+ {
+ wrkBuffer = (rt_uint8_t *)rt_malloc(BMP_WORKING_BUFFER_SIZE);
+ if (wrkBuffer == RT_NULL)
+ {
+ rt_kprintf("BMP err: no mem\n");
+ break;
+ }
- default:
- ExpandBMP = 0;
- break;
- }
+ bmp = (struct rtgui_image_bmp*)rtgui_malloc(sizeof(struct rtgui_image_bmp));
+ if (bmp == RT_NULL)
+ {
+ break;
+ }
- /* We don't support any BMP compression right now */
- Rmask = Gmask = Bmask = 0;
- switch (header->biCompression)
- {
- case BI_RGB:
- /* If there are no masks, use the defaults */
- if ( header->bfOffBits == (14 + header->biSize) )
+ /* Prepare to decode */
+ if (rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET) < 0)
+ {
+ break;
+ }
+ if (rtgui_filerw_read(file, (void *)wrkBuffer, 18, 1) != 18)
+ {
+ break;
+ }
+ /* Read file type */
+ if (wrkBuffer[0] != 'B' || wrkBuffer[1] != 'M')
{
- /* Default values for the BMP format */
- switch (header->biBitCount)
- {
- case 15:
- case 16:
- Rmask = 0x7C00;
- Gmask = 0x03E0;
- Bmask = 0x001F;
- break;
-
- case 24:
- case 32:
- Rmask = 0x00FF0000;
- Gmask = 0x0000FF00;
- Bmask = 0x000000FF;
- break;
-
- default:
- break;
- }
break;
}
- /* Fall through -- read the RGB masks */
+// rt_kprintf("BMP: format ok\n");
+ /* Read pixel array offset */
+ bmp->pixel_offset = *(rt_uint32_t *)&wrkBuffer[10];
+// rt_kprintf("BMP: bmp->pixel_offset %d\n", bmp->pixel_offset);
+ /* Read BMP header size */
+ bmpHeaderSize = *(rt_uint32_t *)&wrkBuffer[14];
+// rt_kprintf("BMP: bmpHeaderSize %d\n", bmpHeaderSize);
+ colorsUsed = 0;
+ if (bmpHeaderSize == 12)
+ { /* Bitmap Header Version 2.x */
+ if (rtgui_filerw_read(file, (void *)wrkBuffer, 8, 1) != 8)
+ {
+ break;
+ }
+ /* Read image size */
+ bmp->w = (rt_uint32_t)*(rt_uint16_t *)&wrkBuffer[0];
+ bmp->h = (rt_uint32_t)*(rt_uint16_t *)&wrkBuffer[2];
+ /* Read bits per pixel */
+ bmp->bit_per_pixel = (rt_uint8_t)*(rt_uint16_t *)&wrkBuffer[6];
+ }
+ else
+ { /* Bitmap Header Version bigger than 2.x */
+ rt_uint32_t compression;
- case BI_BITFIELDS:
- switch (header->biBitCount)
- {
- case 15:
- case 16:
- case 32:
- Rmask = rtgui_filerw_read32(src);
- Gmask = rtgui_filerw_read32(src);
- Bmask = rtgui_filerw_read32(src);
- break;
+ if (rtgui_filerw_read(file, (void *)wrkBuffer, 36, 1) != 36)
+ {
+ break;
+ }
+ /* Read image size */
+ bmp->w = *(rt_uint32_t *)&wrkBuffer[0];
+ bmp->h = *(rt_uint32_t *)&wrkBuffer[4];
+ /* Read bits per pixel */
+ bmp->bit_per_pixel = (rt_uint8_t)*(rt_uint16_t *)&wrkBuffer[10];
+ if (bmp->bit_per_pixel > 32)
+ {
+ rt_kprintf("BMP err: unsupported format\n");
+ break;
+ }
+ /* Read compression method */
+ compression = *(rt_uint32_t *)&wrkBuffer[12];
+ if (compression != BI_RGB && compression != BI_BITFIELDS)
+ {
+ rt_kprintf("BMP err: unsupported format\n");
+ break;
+ }
+ /* Read number of colors */
+ colorsUsed = *(rt_uint32_t *)&wrkBuffer[28];
+ }
+ if (!colorsUsed)
+ {
+ colorsUsed = 1 << bmp->bit_per_pixel;
+ }
- default:
- break;
- }
- break;
+ /* Load palette */
+ if (bmp->bit_per_pixel <= 8)
+ {
+ if (rtgui_filerw_seek(file, 14 + bmpHeaderSize, RTGUI_FILE_SEEK_SET) < 0)
+ {
+ break;
+ }
- default:
- rt_kprintf("Compressed BMP files not supported\n");
- goto __exit;
- }
+ image->palette = rtgui_image_bmp_load_palette(file, colorsUsed,
+ bmpHeaderSize > 12 ? RT_TRUE : RT_FALSE);
+ if (image->palette == RT_NULL)
+ {
+ break;
+ }
+ }
- bmp = (struct rtgui_image_bmp*) rtgui_malloc(sizeof(struct rtgui_image_bmp));
- if (bmp == RT_NULL)
- goto __exit;
+ /* Set image information */
+ bmp->is_loaded = RT_FALSE;
+ bmp->scale = scale;
+ if (bmp->bit_per_pixel == 1)
+ {
+ bmp->pitch = (bmp->w + 7) >> 3;
+ }
+ else if (bmp->bit_per_pixel == 4)
+ {
+ bmp->pitch = (bmp->w + 1) >> 1;
+ }
+ else
+ {
+ bmp->pitch = bmp->w * (bmp->bit_per_pixel >> 3);
+ }
+ bmp->pad = ((bmp->pitch % 4) ? (4 - (bmp->pitch % 4)) : 0);
+ bmp->pixels = RT_NULL;
+ bmp->filerw = file;
- /* set image information */
- image->w = header->biWidth;
- image->h = header->biHeight;
- image->engine = &rtgui_image_bmp_engine;
- image->data = bmp;
- bmp->filerw = src;
- bmp->byte_per_pixel = header->biBitCount/8;
- bmp->pitch = image->w * bmp->byte_per_pixel;
- bmp->pixel_offset = header->bfOffBits;
- bmp->Rmask = Rmask; bmp->Gmask = Gmask; bmp->Bmask = Bmask;
- bmp->ExpandBMP = ExpandBMP;
- if (palette != RT_NULL) image->palette = palette;
+ image->w = bmp->w >> bmp->scale;
+ image->h = bmp->h >> bmp->scale;
+ image->engine = &rtgui_image_bmp_engine;
+ image->data = bmp;
- /* get padding */
- switch (ExpandBMP)
- {
- case 1:
- bmpPitch = (header->biWidth + 7) >> 3;
- bmp->pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
- break;
+ /* Start to decode */
+ if (load == RT_TRUE)
+ {
+ rt_bool_t error = RT_FALSE;
+ rt_uint8_t *dst;
+ rt_uint32_t imageWidth;
+ rt_uint16_t readLength, readIndex, loadIndex;
+ rt_uint8_t skipLength;
+ rt_uint16_t y;
+ rt_uint8_t bytePerPixel;
+ rt_int8_t scale1, scale2;
- case 4:
- bmpPitch = (header->biWidth + 1) >> 1;
- bmp->pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
- break;
+ bytePerPixel = bmp->bit_per_pixel / 8;
+ if (!bytePerPixel)
+ {
+ bytePerPixel = 1;
+ }
+ imageWidth = image->w * bytePerPixel; /* Scaled width in byte */
+ bmp->pixels = rtgui_malloc(image->h * imageWidth);
+ if (bmp->pixels == RT_NULL)
+ {
+ rt_kprintf("BMP err: no mem to load (%d)\n", image->h * imageWidth);
+ break;
+ }
- default:
- bmp->pad = ((bmp->pitch%4) ? (4-(bmp->pitch%4)) : 0);
- break;
- }
+ /* Read the pixels. Note that the bmp image is upside down */
+ if (rtgui_filerw_seek(file, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
+ {
+ break;
+ }
- if (load == RT_TRUE)
- {
- rt_uint8_t *bits;
- rt_uint32_t i;
+ if (bmp->bit_per_pixel == 1)
+ {
+ if (bmp->scale > 3)
+ {
+ scale1 = bmp->scale - 3;
+ scale2 = 3;
+ }
+ else
+ {
+ scale1 = 0;
+ scale2 = bmp->scale;
+ }
+ }
+ else if (bmp->bit_per_pixel == 4)
+ {
+ if (bmp->scale > 1)
+ {
+ scale1 = bmp->scale - 1;
+ scale2 = 1;
+ }
+ else
+ {
+ scale1 = 0;
+ scale2 = bmp->scale;
+ }
+ }
- /* load all pixels */
- bmp->pixels = rtgui_malloc(image->h * bmp->pitch);
- if (bmp->pixels == RT_NULL)
- goto __exit;
+ /* Process whole image */
+ y = 0;
+ while (y < image->h)
+ {
+ dst = bmp->pixels + (image->h - y - 1) * imageWidth;
+ readIndex = 0;
+ skipLength= 0;
- /* Read the pixels. Note that the bmp image is upside down */
- if ( rtgui_filerw_seek(src, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
- goto __exit;
+ /* Process a line */
+ while (readIndex < bmp->pitch)
+ {
+ /* Put progress indicator */
+ rt_kprintf("\r%lu%%", y * 100UL / image->h);
- bits = bmp->pixels + image->h * bmp->pitch;
- while ( bits > bmp->pixels )
- {
- bits -= bmp->pitch;
- switch (ExpandBMP)
- {
- case 1:
- case 4:
- {
- rt_uint8_t pixel = 0;
- int shift = (8 - ExpandBMP);
- for ( i=0; i < image->w; ++i )
- {
- if ( i % (8/ExpandBMP) == 0 )
- {
- if ( !rtgui_filerw_read(src, &pixel, 1, 1) )
- goto __exit;
+ /* Read data to buffer */
+ readLength = (BMP_WORKING_BUFFER_SIZE > (bmp->pitch - readIndex)) ? \
+ (bmp->pitch - readIndex) : BMP_WORKING_BUFFER_SIZE;
+ if (rtgui_filerw_read(file, (void *)wrkBuffer, 1, readLength) != readLength)
+ {
+ rt_kprintf("BMP err: read failed\n");
+ error = RT_TRUE;
+ break;
+ }
+ readIndex += readLength;
- }
- *(bits+i) = (pixel>>shift);
- pixel <<= ExpandBMP;
- }
- }
- break;
+ /* Process read buffer */
+ if (bmp->bit_per_pixel == 1)
+ {
+ rt_uint8_t j;
- default:
- if ( rtgui_filerw_read(src, bits, 1, bmp->pitch) != bmp->pitch ) goto __exit;
- break;
- }
+ for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
+ {
+ for (j = 0; j < 8; j += 1 << scale2)
+ {
+ *(dst++) = (wrkBuffer[loadIndex] & (1 << (7 - j))) >> (7 - j);
+ }
+ }
+ if (scale1 && (readLength % (1 << scale1)))
+ {
+ skipLength = (1 << scale1) - readLength % (1 << scale1);
+ }
+ }
+ else if (bmp->bit_per_pixel == 4)
+ {
+ rt_uint8_t j;
- /* Skip padding bytes */
- if ( bmp->pad )
- {
- rt_uint8_t padbyte;
- for ( i=0; i < bmp->pad; ++i )
- {
- rtgui_filerw_read(src, &padbyte, 1, 1);
- }
- }
- }
+ for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
+ {
+ for (j = 0; j < 8; j += 1 << (2 + scale2))
+ {
+ *(dst++) = (wrkBuffer[loadIndex] & (0x0F << (4 - j))) >> (4 - j);
+ }
+ }
+ if (scale1 && (readLength % (1 << scale1)))
+ {
+ skipLength = (1 << scale1) - readLength % (1 << scale1);
+ }
+ }
+ else
+ {
+ if (bmp->scale == 0)
+ {
+ rt_memcpy((void *)dst, (void *)wrkBuffer, readLength);
+ dst += readLength;
+ }
+ else
+ {
+ for (loadIndex = skipLength; loadIndex < readLength; loadIndex += bytePerPixel << bmp->scale)
+ {
+ rt_memcpy((void *)dst, (void *)&wrkBuffer[loadIndex], bytePerPixel);
+ dst += bytePerPixel;
+ }
+ if (readLength % (1 << bmp->scale))
+ {
+ skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
+ }
+ }
+ }
+ }
+ if (error)
+ {
+ break;
+ }
+ y++;
- rtgui_filerw_close(bmp->filerw);
- bmp->line_pixels = RT_NULL;
- bmp->filerw = RT_NULL;
- bmp->pixel_offset = 0;
- }
- else
- {
- bmp->pixels = RT_NULL;
- bmp->line_pixels = rtgui_malloc(bmp->pitch);
- }
+ /* Skip padding bytes */
+ if (bmp->pad)
+ {
+ if ( rtgui_filerw_seek(file, bmp->pad, RTGUI_FILE_SEEK_CUR) < 0)
+ {
+ error = RT_TRUE;
+ break;
+ }
+ }
- return RT_TRUE;
+ /* Height scale down */
+ if (bmp->scale)
+ {
+ if (rtgui_filerw_seek(file, (bmp->pitch + bmp->pad) * ((1 << bmp->scale) - 1),
+ RTGUI_FILE_SEEK_CUR) < 0)
+ {
+ error = RT_TRUE;
+ break;
+ }
+ }
+ }
+ if (error)
+ {
+ break;
+ }
+ /* Close file */
+ rtgui_filerw_close(bmp->filerw);
+ bmp->filerw = RT_NULL;
+ bmp->is_loaded = RT_TRUE;
+// rt_kprintf("BMP: load to RAM\n");
+ }
-__exit:
- rtgui_free(header);
- if (palette != RT_NULL)
- {
- rtgui_free(palette);
- image->palette = RT_NULL;
- }
+ /* Release memory */
+ rt_free(wrkBuffer);
+ return RT_TRUE;
+ } while(0);
- if (bmp != RT_NULL)
- rtgui_free(bmp->pixels);
+ /* Release memory */
+ rt_free(wrkBuffer);
+ rtgui_free(image->palette);
+ rtgui_free(bmp->pixels);
rtgui_free(bmp);
return RT_FALSE;
}
@@ -421,220 +494,324 @@ static void rtgui_image_bmp_unload(struct rtgui_image* image)
if (image != RT_NULL)
{
- bmp = (struct rtgui_image_bmp*) image->data;
+ bmp = (struct rtgui_image_bmp*)image->data;
- if (bmp->pixels != RT_NULL) rtgui_free(bmp->pixels);
- if (bmp->line_pixels != RT_NULL) rtgui_free(bmp->line_pixels);
+ /* Release memory */
+ rtgui_free(bmp->pixels);
if (bmp->filerw != RT_NULL)
{
+ /* Close file */
rtgui_filerw_close(bmp->filerw);
bmp->filerw = RT_NULL;
}
-
- /* release data */
rtgui_free(bmp);
}
}
static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* dst_rect)
{
- int y;
- rt_uint16_t w, h;
+ rt_uint16_t w, h;
struct rtgui_image_bmp* bmp;
+ rt_uint8_t bytePerPixel;
+ rt_uint32_t imageWidth;
+ rt_bool_t error;
- RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL);
+ bmp = (struct rtgui_image_bmp*)image->data;
+ RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL || bmp != RT_NULL);
- /* this dc is not visible */
- if (rtgui_dc_get_visible(dc) != RT_TRUE) return;
+ bytePerPixel = bmp->bit_per_pixel / 8;
+ if (!bytePerPixel)
+ {
+ bytePerPixel = 1;
+ }
+ imageWidth = image->w * bytePerPixel; /* Scaled width in byte */
+ error = RT_FALSE;
- bmp = (struct rtgui_image_bmp*) image->data;
- RT_ASSERT(bmp != RT_NULL);
+ do
+ {
+ /* this dc is not visible */
+ if (rtgui_dc_get_visible(dc) != RT_TRUE)
+ {
+ break;
+ }
- /* the minimum rect */
- if (image->w < rtgui_rect_width(*dst_rect)) w = image->w;
- else w = rtgui_rect_width(*dst_rect);
- if (image->h < rtgui_rect_height(*dst_rect)) h = image->h;
- else h = rtgui_rect_height(*dst_rect);
+ /* the minimum rect */
+ if (image->w < rtgui_rect_width(*dst_rect))
+ {
+ w = image->w;
+ }
+ else
+ {
+ w = rtgui_rect_width(*dst_rect);
+ }
+ if (image->h < rtgui_rect_height(*dst_rect))
+ {
+ h = image->h;
+ }
+ else
+ {
+ h = rtgui_rect_height(*dst_rect);
+ }
- if (bmp->pixels != RT_NULL)
- {
- rt_uint8_t* ptr;
+ if (!bmp->is_loaded)
+ {
+ rt_uint8_t *wrkBuffer;
+ rt_uint16_t readLength, readIndex, loadIndex;
+ rt_uint8_t skipLength;
+ rt_uint16_t x, y;
+ rt_int8_t scale1, scale2;
- /* get pixel pointer */
- ptr = bmp->pixels;
- if (bmp->byte_per_pixel == hw_driver->bits_per_pixel/8)
- {
- for (y = 0; y < h; y ++)
- {
- dc->engine->blit_line(dc,
- dst_rect->x1, dst_rect->x1 + w,
- dst_rect->y1 + y,
- ptr);
- ptr += bmp->pitch;
- }
- }
- else
- {
- rt_size_t pitch;
- rt_uint8_t *line_ptr;
+ wrkBuffer = (rt_uint8_t *)rt_malloc(BMP_WORKING_BUFFER_SIZE);
+ if (wrkBuffer == RT_NULL)
+ {
+ rt_kprintf("BMP err: no mem (%d)\n", BMP_WORKING_BUFFER_SIZE);
+ break;
+ }
- if (image->palette == RT_NULL)
- {
- rtgui_blit_line_func blit_line;
- line_ptr = (rt_uint8_t*) rtgui_malloc((hw_driver->bits_per_pixel/8) * w);
- blit_line = rtgui_blit_line_get(hw_driver->bits_per_pixel/8 , bmp->byte_per_pixel);
- pitch = w * bmp->byte_per_pixel;
- if (line_ptr != RT_NULL)
- {
- for (y = 0; y < h; y ++)
- {
- blit_line(line_ptr, ptr, pitch);
- dc->engine->blit_line(dc,
- dst_rect->x1, dst_rect->x1 + w,
- dst_rect->y1 + y,
- line_ptr);
- ptr += bmp->pitch;
- }
- }
- rtgui_free(line_ptr);
- }
- else
- {
- int x;
- rtgui_color_t color;
+ /* Read the pixels. Note that the bmp image is upside down */
+ if (rtgui_filerw_seek(bmp->filerw, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
+ {
+ break;
+ }
- /* use palette */
- for (y = 0; y < h; y ++)
- {
- ptr = bmp->pixels + (y * bmp->pitch);
- for (x = 0; x < w; x ++)
- {
- color = image->palette->colors[*ptr]; ptr ++;
- rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, color);
- }
- }
- }
- }
- }
- else
- {
- int offset;
- rt_uint8_t *bits;
+ if (bmp->bit_per_pixel == 1)
+ {
+ if (bmp->scale > 3)
+ {
+ scale1 = bmp->scale - 3;
+ scale2 = 3;
+ }
+ else
+ {
+ scale1 = 0;
+ scale2 = bmp->scale;
+ }
+ }
+ else if (bmp->bit_per_pixel == 4)
+ {
+ if (bmp->scale > 1)
+ {
+ scale1 = bmp->scale - 1;
+ scale2 = 1;
+ }
+ else
+ {
+ scale1 = 0;
+ scale2 = bmp->scale;
+ }
+ }
- /* calculate offset */
- switch (bmp->ExpandBMP)
- {
- case 1:
- offset = (image->h - h) * (image->w/8) * bmp->byte_per_pixel;
- break;
+ /* Process whole image */
+ y = 0;
+ while (y < image->h)
+ {
+ x = 0;
+ readIndex = 0;
+ skipLength= 0;
- case 4:
- offset = (image->h - h) * (image->w/2) * bmp->byte_per_pixel;
- break;
+ /* Process a line */
+ while (readIndex < bmp->pitch)
+ {
+ /* Put progress indicator */
+ rt_kprintf("\r%lu%%", y * 100UL / image->h);
- default:
- offset = (image->h - h) * image->w * bmp->byte_per_pixel;
- break;
- }
- /* seek to the begin of pixel data */
- rtgui_filerw_seek(bmp->filerw, bmp->pixel_offset + offset, RTGUI_FILE_SEEK_SET);
+ /* Read data to buffer */
+ readLength = (BMP_WORKING_BUFFER_SIZE > (bmp->pitch - readIndex)) ? \
+ (bmp->pitch - readIndex) : BMP_WORKING_BUFFER_SIZE;
+ if (rtgui_filerw_read(bmp->filerw, (void *)wrkBuffer, 1, readLength) != readLength)
+ {
+ rt_kprintf("BMP err: read failed\n");
+ error = RT_TRUE;
+ break;
+ }
+ readIndex += readLength;
- if (bmp->ExpandBMP == 1 || bmp->ExpandBMP == 4)
- {
- int x;
- rtgui_color_t color;
- /* 1, 4 bit per pixels */
+ /* Process read buffer */
+ if (bmp->bit_per_pixel == 1)
+ {
+ rt_uint8_t j;
+ rtgui_color_t color;
- /* draw each line */
- for (y = h - 1; y >= 0; y --)
- {
- /* read pixel data */
- rt_uint8_t pixel = 0;
- int shift = (8 - bmp->ExpandBMP);
- int i;
+ for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
+ {
+ for (j = 0; j < 8; j += 1 << scale2)
+ {
+ color = image->palette->colors[(wrkBuffer[loadIndex] & (1 << (7 - j))) >> (7 - j)];
+ rtgui_dc_draw_color_point(dc,
+ dst_rect->x1 + x++,
+ dst_rect->y1 + image->h - y,
+ color);
+ }
+ if (scale1 && (readLength % (1 << scale1)))
+ {
+ skipLength = (1 << scale1) - readLength % (1 << scale1);
+ }
+ }
+ }
+ else if (bmp->bit_per_pixel == 4)
+ {
+ rt_uint8_t j;
+ rtgui_color_t color;
- bits = bmp->line_pixels;
- for ( i=0; i < image->w; ++i )
- {
- if ( i % (8/bmp->ExpandBMP) == 0 )
- {
- if ( !rtgui_filerw_read(bmp->filerw, &pixel, 1, 1) )
- return;
- }
- *(bits+i) = (pixel>>shift);
- pixel <<= bmp->ExpandBMP;
- }
+ for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
+ {
+ for (j = 0; j < 8; j += 1 << (2 + scale2))
+ {
+ color = image->palette->colors[(wrkBuffer[loadIndex] & (0x0F << (4 - j))) >> (4 - j)];
+ rtgui_dc_draw_color_point(dc,
+ dst_rect->x1 + x++,
+ dst_rect->y1 + image->h - y,
+ color);
+ }
+ }
+ if (scale1 && (readLength % (1 << scale1)))
+ {
+ skipLength = (1 << scale1) - readLength % (1 << scale1);
+ }
+ }
+ else if (bmp->bit_per_pixel == 8)
+ {
+ rtgui_color_t color;
- /* Skip padding bytes */
- if (bmp->pad)
- {
- int i;
- rt_uint8_t padbyte;
- for ( i=0; i < bmp->pad; ++i )
- rtgui_filerw_read(bmp->filerw, &padbyte, 1, 1);
- }
+ for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << bmp->scale)
+ {
+ color = image->palette->colors[wrkBuffer[loadIndex]];
+ rtgui_dc_draw_color_point(dc,
+ dst_rect->x1 + x++,
+ dst_rect->y1 + image->h - y,
+ color);
+ }
+ if (readLength % (1 << bmp->scale))
+ {
+ skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
+ }
+ }
+ else
+ {
+ rtgui_blit_line_func blit_line;
+ rt_uint8_t hw_bytePerPixel = hw_driver->bits_per_pixel / 8;
+ rt_uint8_t temp[4] = {0};
- /* use palette */
- bits = bmp->line_pixels;
- for (x = 0; x < w; x ++)
- {
- color = image->palette->colors[*bits]; bits ++;
- rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, color);
- }
- }
- }
- else
- {
- rt_uint8_t *line_ptr = (rt_uint8_t*) rtgui_malloc((hw_driver->bits_per_pixel/8) * w);
- if (line_ptr == RT_NULL) return;
+ if (!hw_bytePerPixel)
+ {
+ hw_bytePerPixel = 1;
+ }
- /* draw each line */
- for (y = h - 1; y >= 0; y --)
- {
- /* read line pixels */
- rtgui_filerw_read(bmp->filerw, bmp->line_pixels, 1, bmp->pitch);
+ if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
+ {
+ blit_line = rtgui_blit_line_get_inv(hw_bytePerPixel, bytePerPixel);
+ }
+ else
+ {
+ blit_line = rtgui_blit_line_get(hw_bytePerPixel, bytePerPixel);
+ }
- /* Skip padding bytes */
- if (bmp->pad)
- {
- int i;
- rt_uint8_t padbyte;
- for ( i=0; i < bmp->pad; ++i )
- rtgui_filerw_read(bmp->filerw, &padbyte, 1, 1);
- }
+ for (loadIndex = skipLength; loadIndex < readLength; loadIndex += bytePerPixel << bmp->scale)
+ {
+ blit_line(temp, &wrkBuffer[loadIndex], bytePerPixel);
+ dc->engine->blit_line(dc,
+ dst_rect->x1 + x, dst_rect->x1 + x,
+ dst_rect->y1 + image->h - y,
+ temp);
+ x++;
+ }
+ if (readLength % (1 << bmp->scale))
+ {
+ skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
+ }
+ }
+ }
+ if (error)
+ {
+ break;
+ }
+ y++;
- if (image->palette == RT_NULL)
- {
- int pitch;
- rtgui_blit_line_func blit_line;
- blit_line = rtgui_blit_line_get(hw_driver->bits_per_pixel/8 , bmp->byte_per_pixel);
- pitch = w * bmp->byte_per_pixel;
- if (line_ptr != RT_NULL)
- {
- blit_line(line_ptr, bmp->line_pixels, pitch);
- dc->engine->blit_line(dc,
- dst_rect->x1, dst_rect->x1 + w,
- dst_rect->y1 + y,
- line_ptr);
- }
- }
- else
- {
- int x;
- rtgui_color_t color;
+ /* Skip padding bytes */
+ if (bmp->pad)
+ {
+ if ( rtgui_filerw_seek(bmp->filerw, bmp->pad, RTGUI_FILE_SEEK_CUR) < 0)
+ {
+ error = RT_TRUE;
+ break;
+ }
+ }
- /* use palette */
- bits = bmp->line_pixels;
- for (x = 0; x < w; x ++)
- {
- color = image->palette->colors[*bits]; bits ++;
- rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, color);
- }
- }
- }
- if (line_ptr != RT_NULL) rtgui_free(line_ptr);
- }
- }
+ /* Height scale down */
+ if (bmp->scale)
+ {
+ if (rtgui_filerw_seek(bmp->filerw, (bmp->pitch + bmp->pad) * ((1 << bmp->scale) - 1),
+ RTGUI_FILE_SEEK_CUR) < 0)
+ {
+ error = RT_TRUE;
+ break;
+ }
+ }
+ }
+ if (error)
+ {
+ break;
+ }
+ /* Release memory */
+ rt_free(wrkBuffer);
+// rt_kprintf("BMP: load to display\n");
+ }
+ else
+ {
+ rt_uint16_t x, y;
+ rt_uint8_t* ptr;
+
+ for (y = 0; y < h; y ++)
+ {
+ ptr = bmp->pixels + (y * imageWidth);
+ if (bmp->bit_per_pixel <= 8)
+ {
+ rtgui_color_t color;
+
+ /* Using palette */
+ for (x = 0; x < w; x ++)
+ {
+ color = image->palette->colors[*(ptr++)];
+ rtgui_dc_draw_color_point(dc,
+ dst_rect->x1 + x,
+ dst_rect->y1 + y,
+ color);
+ }
+ }
+ else
+ {
+ rtgui_blit_line_func blit_line;
+ rt_uint8_t hw_bytePerPixel = hw_driver->bits_per_pixel / 8;
+ rt_uint8_t temp[4] = {0};
+
+ if (!hw_bytePerPixel)
+ {
+ hw_bytePerPixel = 1;
+ }
+
+ if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
+ {
+ blit_line = rtgui_blit_line_get_inv(hw_bytePerPixel, bytePerPixel);
+ }
+ else
+ {
+ blit_line = rtgui_blit_line_get(hw_bytePerPixel, bytePerPixel);
+ }
+
+ for (x = 0; x < w; x ++)
+ {
+ blit_line(temp, ptr, bytePerPixel);
+ ptr += bytePerPixel;
+ dc->engine->blit_line(dc,
+ dst_rect->x1 + x, dst_rect->x1 + x,
+ dst_rect->y1 + y,
+ temp);
+ }
+ }
+ }
+ }
+// rt_kprintf("BMP: blit ok\n");
+ } while(0);
}
void rtgui_image_bmp_init()
diff --git a/components/rtgui/common/image_jpg.c b/components/rtgui/common/image_jpg.c
index decf6de8c7..0980fc68d1 100644
--- a/components/rtgui/common/image_jpg.c
+++ b/components/rtgui/common/image_jpg.c
@@ -1,3 +1,8 @@
+/*
+ * Change Logs:
+ * Date Author Notes
+ * 2012-01-24 onelife add TJpgDec (Tiny JPEG Decompressor) support
+ */
#include <rtthread.h>
#include <rtgui/rtgui.h>
@@ -494,3 +499,477 @@ static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw* file)
}
#endif
+
+#if defined(RTGUI_IMAGE_TJPGD)
+/***************************************************************************//**
+ * @file image_jpg.c
+ * @brief JPEG decoder using TJpgDec module (elm-chan.org)
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ * @author onelife
+ * @version 1.0
+ *******************************************************************************
+ * @section License
+ * The license and distribution terms for this file may be found in the file
+ * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
+ *******************************************************************************
+ * @section Change Logs
+ * Date Author Notes
+ * 2012-01-24 onelife Initial creation for limited memory devices
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * @addtogroup TJpgDec
+ * @{
+ ******************************************************************************/
+
+/* Includes ------------------------------------------------------------------*/
+#include "tjpgd.h"
+
+#include <rtgui/rtgui_system.h>
+#include <rtgui/filerw.h>
+#include <rtgui/blit.h>
+#include <rtgui/image_jpeg.h>
+
+#ifdef RTGUI_USING_DFS_FILERW
+#include <dfs_posix.h>
+#endif
+
+/* Private typedef -----------------------------------------------------------*/
+struct rtgui_image_jpeg
+{
+ struct rtgui_filerw* filerw;
+ struct rtgui_dc *dc;
+ rt_uint16_t dst_x, dst_y;
+ rt_uint16_t dst_w, dst_h;
+ rt_bool_t is_loaded;
+ rt_bool_t to_buffer;
+ rt_uint8_t scale;
+ rt_uint8_t byte_per_pixel;
+ JDEC tjpgd; /* jpeg structure */
+ void *pool;
+ rt_uint8_t *pixels;
+};
+
+/* Private define ------------------------------------------------------------*/
+#define TJPGD_WORKING_BUFFER_SIZE (3100)
+#define TJPGD_MAX_MCU_WIDTH_ON_DISP (2 * 8 * 4) /* Y component: 2x2; Display: 4-byte per pixel */
+#define TJPGD_MAX_SCALING_FACTOR (3)
+#define hw_driver (rtgui_graphic_driver_get_default())
+
+/* Private macro -------------------------------------------------------------*/
+/* Private function prototypes -----------------------------------------------*/
+/* static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw* file,
+ rt_uint16_t *width, rt_uint16_t *height);
+static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image* image,
+ struct rtgui_filerw* file, rt_uint8_t scale, rt_bool_t load); */
+static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw* file);
+static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
+static void rtgui_image_jpeg_unload(struct rtgui_image* image);
+static void rtgui_image_jpeg_blit(struct rtgui_image* image,
+ struct rtgui_dc* dc, struct rtgui_rect* dst_rect);
+
+/* Private variables ---------------------------------------------------------*/
+struct rtgui_image_engine rtgui_image_jpeg_engine =
+{
+ "jpeg",
+ {RT_NULL},
+ rtgui_image_jpeg_check,
+ rtgui_image_jpeg_load,
+ rtgui_image_jpeg_unload,
+ rtgui_image_jpeg_blit
+};
+
+struct rtgui_image_engine rtgui_image_jpg_engine =
+{
+ "jpg",
+ {RT_NULL},
+ rtgui_image_jpeg_check,
+ rtgui_image_jpeg_load,
+ rtgui_image_jpeg_unload,
+ rtgui_image_jpeg_blit
+};
+
+/* Private functions ---------------------------------------------------------*/
+void rtgui_image_jpeg_init()
+{
+ /* register jpeg on image system */
+ rtgui_image_register_engine(&rtgui_image_jpeg_engine);
+ /* register jpg on image system */
+ rtgui_image_register_engine(&rtgui_image_jpg_engine);
+}
+
+static UINT tjpgd_in_func(JDEC *jdec, BYTE *buff, UINT ndata)
+{
+ struct rtgui_filerw *file = *(struct rtgui_filerw **)jdec->device;
+
+ if (buff == RT_NULL)
+ {
+ return rtgui_filerw_seek(file, ndata, RTGUI_FILE_SEEK_CUR);
+ }
+
+ return rtgui_filerw_read(file, (void *)buff, 1, ndata);
+}
+
+static UINT tjpgd_out_func(JDEC *jdec, void *bitmap, JRECT *rect)
+{
+ struct rtgui_image_jpeg *jpeg = (struct rtgui_image_jpeg *)jdec->device;
+ rt_uint16_t w, h, y;
+ rt_uint16_t rectWidth; /* Width of source rectangular (bytes) */
+ rt_uint8_t *src, *dst;
+
+ /* Put progress indicator */
+ if (rect->left == 0)
+ {
+ rt_kprintf("\r%lu%%", (rect->top << jpeg->scale) * 100UL / jdec->height);
+ }
+
+ /* Copy the decompressed RGB rectanglar to the frame buffer */
+ rectWidth = (rect->right - rect->left + 1) * jpeg->byte_per_pixel;
+ src = (rt_uint8_t *)bitmap;
+
+ if (jpeg->to_buffer)
+ {
+ rt_uint16_t imageWidth; /* Width of image (bytes) */
+
+ imageWidth = (jdec->width >> jdec->scale) * jpeg->byte_per_pixel;
+ dst = jpeg->pixels + rect->top * imageWidth + rect->left * jpeg->byte_per_pixel;
+ /* Left-top of destination rectangular */
+ for (h = rect->top; h <= rect->bottom; h++)
+ {
+ rt_memcpy(dst, src, rectWidth);
+ src += rectWidth;
+ dst += imageWidth; /* Next line */
+ }
+ }
+ else
+ {
+ rtgui_blit_line_func blit_line = RT_NULL;
+
+ w = rect->right < jpeg->dst_w ? rect->right : jpeg->dst_w;
+ w = w - rect->left + 1;
+ h = rect->bottom < jpeg->dst_h ? rect->bottom : jpeg->dst_h;
+ h = h - rect->top + 1;
+ if (jpeg->byte_per_pixel == hw_driver->bits_per_pixel / 8)
+ {
+ if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
+ {
+ blit_line = rtgui_blit_line_get_inv(hw_driver->bits_per_pixel / 8, jpeg->byte_per_pixel);
+ }
+ }
+ else
+ {
+ blit_line = rtgui_blit_line_get(hw_driver->bits_per_pixel / 8, jpeg->byte_per_pixel);
+ }
+
+ if (blit_line)
+ {
+ rt_uint8_t line_buf[TJPGD_MAX_MCU_WIDTH_ON_DISP];
+
+ for (y = 0; y < h; y++)
+ {
+ blit_line(line_buf, src, w * jpeg->byte_per_pixel);
+ jpeg->dc->engine->blit_line(jpeg->dc,
+ jpeg->dst_x + rect->left, jpeg->dst_x + rect->left + w - 1,
+ jpeg->dst_y + rect->top + y,
+ line_buf);
+ src += rectWidth;
+ }
+ }
+ else
+ {
+ for (y = 0; y < h; y++)
+ {
+ jpeg->dc->engine->blit_line(jpeg->dc,
+ jpeg->dst_x + rect->left, jpeg->dst_x + rect->left + w - 1,
+ jpeg->dst_y + rect->top + y,
+ src);
+ src += rectWidth;
+ }
+ }
+ }
+ return 1; /* Continue to decompress */
+}
+
+static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw* file)
+//static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw* file,
+// rt_uint32_t *width, rt_uint32_t *height)
+{
+ rt_bool_t is_JPG;
+ JDEC tjpgd;
+ void *pool;
+
+ is_JPG = RT_FALSE;
+ do
+ {
+ if (!file )
+ {
+ break;
+ }
+
+ pool = rt_malloc(TJPGD_WORKING_BUFFER_SIZE);
+ if (pool == RT_NULL)
+ {
+ rt_kprintf("TJPGD err: no mem\n");
+ break;
+ }
+
+ if (rtgui_filerw_seek(file, 0, SEEK_SET) == -1)
+ {
+ break;
+ }
+
+ if (jd_prepare(&tjpgd, tjpgd_in_func, pool,
+ TJPGD_WORKING_BUFFER_SIZE, (void *)&file) == JDR_OK)
+ {
+// *width = (rt_uint32_t)tjpgd.width;
+// *height = (rt_uint32_t)tjpgd.height;
+ is_JPG = RT_TRUE;
+ }
+
+ rt_kprintf("TJPGD: check OK\n");
+ } while(0);
+
+ rt_free(pool);
+
+ return is_JPG;
+}
+
+static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
+//static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image* image,
+// struct rtgui_filerw* file, rt_uint8_t scale, rt_bool_t load)
+{
+ rt_uint8_t scale = 2;
+ rt_bool_t res = RT_FALSE;
+ struct rtgui_image_jpeg *jpeg;
+ JRESULT ret;
+
+ if (scale > TJPGD_MAX_SCALING_FACTOR)
+ {
+ return RT_FALSE;
+ }
+
+ do
+ {
+ jpeg = (struct rtgui_image_jpeg *)rt_malloc(sizeof(struct rtgui_image_jpeg));
+ if (jpeg == RT_NULL)
+ {
+ break;
+ }
+ jpeg->filerw = file;
+ jpeg->is_loaded = RT_FALSE;
+ jpeg->to_buffer = load;
+ jpeg->scale = scale;
+#if (JD_FORMAT == 0)
+ jpeg->byte_per_pixel = 3;
+#elif (JD_FORMAT == 1)
+ jpeg->byte_per_pixel = 2;
+#endif
+ jpeg->pool = RT_NULL;
+ jpeg->pixels = RT_NULL;
+
+ jpeg->pool = rt_malloc(TJPGD_WORKING_BUFFER_SIZE);
+ if (jpeg->pool == RT_NULL)
+ {
+ rt_kprintf("TJPGD err: no mem (%d)\n", TJPGD_WORKING_BUFFER_SIZE);
+ break;
+ }
+
+ if (rtgui_filerw_seek(jpeg->filerw, 0, SEEK_SET) == -1)
+ {
+ break;
+ }
+
+ ret = jd_prepare(&jpeg->tjpgd, tjpgd_in_func, jpeg->pool,
+ TJPGD_WORKING_BUFFER_SIZE, (void *)jpeg);
+ if (ret != JDR_OK)
+ {
+ if (ret == JDR_FMT3)
+ {
+ rt_kprintf("TJPGD: not supported format\n");
+ }
+ break;
+ }
+ rt_kprintf("TJPGD: prepare OK\n");
+
+ image->w = (rt_uint16_t)jpeg->tjpgd.width >> jpeg->scale;
+ image->h = (rt_uint16_t)jpeg->tjpgd.height >> jpeg->scale;
+
+ /* set image private data and engine */
+ image->data = jpeg;
+ image->engine = &rtgui_image_jpeg_engine;
+
+ if (jpeg->to_buffer == RT_TRUE)
+ {
+ jpeg->pixels = (rt_uint8_t *)rtgui_malloc(
+ jpeg->byte_per_pixel * image->w * image->h);
+ if (jpeg->pixels == RT_NULL)
+ {
+ rt_kprintf("TJPGD err: no mem to load (%d)\n",
+ jpeg->byte_per_pixel * image->w * image->h);
+ break;
+ }
+
+ ret = jd_decomp(&jpeg->tjpgd, tjpgd_out_func, jpeg->scale);
+ if (ret != JDR_OK)
+ {
+ break;
+ }
+
+ rtgui_filerw_close(jpeg->filerw);
+ jpeg->is_loaded = RT_TRUE;
+
+ rt_kprintf("TJPGD: load to RAM\n");
+ }
+ res = RT_TRUE;
+ } while(0);
+
+ if (!res || jpeg->is_loaded)
+ {
+ rt_free(jpeg->pool);
+ }
+ if (!res)
+ {
+ rtgui_free(jpeg->pixels);
+ rt_free(jpeg);
+ }
+
+ /* create jpeg image successful */
+ return res;
+}
+
+
+static void rtgui_image_jpeg_unload(struct rtgui_image* image)
+{
+ if (image != RT_NULL)
+ {
+ struct rtgui_image_jpeg* jpeg;
+
+ jpeg = (struct rtgui_image_jpeg*) image->data;
+ RT_ASSERT(jpeg != RT_NULL);
+
+ if (jpeg->to_buffer == RT_TRUE)
+ {
+ if (jpeg->is_loaded == RT_TRUE)
+ {
+ rtgui_free(jpeg->pixels);
+ }
+ if (jpeg->is_loaded != RT_TRUE)
+ {
+ rtgui_filerw_close(jpeg->filerw);
+ }
+ }
+ else
+ {
+ rt_free(jpeg->pool);
+ rtgui_filerw_close(jpeg->filerw);
+ }
+ rt_free(jpeg);
+ }
+ rt_kprintf("TJPGD: unload\n");
+}
+
+static void rtgui_image_jpeg_blit(struct rtgui_image* image,
+ struct rtgui_dc* dc, struct rtgui_rect* dst_rect)
+{
+ rt_uint16_t w, h, y;
+ struct rtgui_image_jpeg *jpeg;
+
+ jpeg = (struct rtgui_image_jpeg *) image->data;
+ RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL || jpeg != RT_NULL);
+
+ do
+ {
+ /* this dc is not visible */
+ if (rtgui_dc_get_visible(dc) != RT_TRUE)
+ {
+ break;
+ }
+ jpeg->dc= dc;
+
+ /* the minimum rect */
+ if (image->w < rtgui_rect_width(*dst_rect))
+ {
+ w = image->w;
+ }
+ else
+ {
+ w = rtgui_rect_width(*dst_rect);
+ }
+ if (image->h < rtgui_rect_height(*dst_rect))
+ {
+ h = image->h;
+ }
+ else
+ {
+ h = rtgui_rect_height(*dst_rect);
+ }
+
+ if (!jpeg->is_loaded)
+ {
+ JRESULT ret;
+
+ jpeg->dst_x = dst_rect->x1;
+ jpeg->dst_y = dst_rect->y1;
+ jpeg->dst_w = w;
+ jpeg->dst_h = h;
+ ret = jd_decomp(&jpeg->tjpgd, tjpgd_out_func, jpeg->scale);
+ if (ret != JDR_OK)
+ {
+ break;
+ }
+ rt_kprintf("TJPGD: load to display\n");
+ }
+ else
+ {
+ rt_uint8_t* src = jpeg->pixels;
+ rt_uint16_t imageWidth = image->w * jpeg->byte_per_pixel;
+ rtgui_blit_line_func blit_line = RT_NULL;
+
+ if (jpeg->byte_per_pixel == hw_driver->bits_per_pixel / 8)
+ {
+ if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
+ {
+ blit_line = rtgui_blit_line_get_inv(hw_driver->bits_per_pixel / 8, jpeg->byte_per_pixel);
+ }
+ }
+ else
+ {
+ blit_line = rtgui_blit_line_get(hw_driver->bits_per_pixel / 8, jpeg->byte_per_pixel);
+ }
+
+ if (blit_line)
+ {
+ rt_uint16_t x;
+ rt_uint8_t temp[4];
+
+ for (y = 0; y < h; y++)
+ {
+ for (x = 0; x < w; x++)
+ {
+ blit_line(temp, src, jpeg->byte_per_pixel);
+ src += jpeg->byte_per_pixel;
+ dc->engine->blit_line(dc,
+ dst_rect->x1 + x, dst_rect->x1 + x,
+ dst_rect->y1 + y,
+ temp);
+ }
+ }
+ }
+ else
+ {
+ for (y = 0; y < h; y++)
+ {
+ dc->engine->blit_line(dc,
+ dst_rect->x1, dst_rect->x1 + w - 1,
+ dst_rect->y1 + y,
+ src);
+ src += imageWidth;
+ }
+ }
+ }
+ } while(0);
+}
+#endif /* defined(RTGUI_IMAGE_TJPGD) */
+/***************************************************************************//**
+ * @}
+ ******************************************************************************/
diff --git a/components/rtgui/common/image_png.c b/components/rtgui/common/image_png.c
index 9c72ef02f4..5c858bfd6e 100644
--- a/components/rtgui/common/image_png.c
+++ b/components/rtgui/common/image_png.c
@@ -242,9 +242,16 @@ 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)
{
+ struct rtgui_graphic_driver* hwdev = rtgui_graphic_get_device();
rt_uint16_t x, y, w, h;
rtgui_color_t* ptr;
struct rtgui_image_png* png;
+ int fg_maxsample;
+ int ialpha;
+ float alpha;
+ rtgui_color_t color;
+ rtgui_color_t c, bgcolor;
+ int fc[3], bc[3];
RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
RT_ASSERT(image->data != RT_NULL);
@@ -255,21 +262,56 @@ static void rtgui_image_png_blit(struct rtgui_image* image, struct rtgui_dc* dc,
else w = rtgui_rect_width(*rect);
if (image->h < rtgui_rect_height(*rect)) h = image->h;
else h = rtgui_rect_height(*rect);
+
+ fg_maxsample = (1 << png->info_ptr->bit_depth) - 1;
if (png->pixels != RT_NULL)
{
ptr = (rtgui_color_t*)png->pixels;
- /* draw each point within dc */
+ bgcolor = rtgui_color_from_565(RTGUI_DC_BC(dc));
+ bc[0] = RTGUI_RGB_R(bgcolor);
+ bc[1] = RTGUI_RGB_G(bgcolor);
+ bc[2] = RTGUI_RGB_B(bgcolor);
+ /* 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_draw_color_point(dc, x + rect->x1, y + rect->y1, *ptr);
- }
-
+ c = *ptr;
+ ialpha = RTGUI_RGB_A(c);
+ if(ialpha == 0)
+ {
+ /*
+ * Foreground image is transparent hear.
+ * If the background image is already in the frame
+ * buffer, there is nothing to do.
+ */
+ }
+ else if (ialpha == fg_maxsample)
+ {
+ /*
+ * Copy foreground pixel to frame buffer.
+ */
+ rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, c);
+ }
+ else
+ { /* output = alpha * foreground + (1-alpha) * background */
+ /*
+ * Compositing is necessary.
+ * Get floating-point alpha and its complement.
+ * Note: alpha is always linear: gamma does not
+ * affect it.
+ */
+ fc[0] = RTGUI_RGB_R(c);
+ fc[1] = RTGUI_RGB_G(c);
+ fc[2] = RTGUI_RGB_B(c);
+
+ alpha = (float) ialpha / fg_maxsample;
+ color = RTGUI_RGB( (rt_uint8_t)(fc[0]*alpha + bc[0]*(1-alpha)),
+ (rt_uint8_t)(fc[1]*alpha + bc[1]*(1-alpha)),
+ (rt_uint8_t)(fc[2]*alpha + bc[2]*(1-alpha)));
+ rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, color);
+ }
/* move to next color buffer */
ptr ++;
}
diff --git a/components/rtgui/common/pixel_driver.c b/components/rtgui/common/pixel_driver.c
index 31b22e164e..503efb76cd 100644
--- a/components/rtgui/common/pixel_driver.c
+++ b/components/rtgui/common/pixel_driver.c
@@ -1,9 +1,23 @@
+/*
+ * Change Logs:
+ * Date Author Notes
+ * 2012-01-24 onelife add mono color support
+ * 2012-01-24 onelife fix a bug in _pixel_draw_raw_hline
+ */
#include <rtgui/rtgui_system.h>
#include <rtgui/driver.h>
#define gfx_device (rtgui_graphic_get_device()->device)
#define gfx_device_ops rt_graphix_ops(gfx_device)
+static void _pixel_mono_set_pixel(rtgui_color_t *c, int x, int y)
+{
+ rt_uint8_t pixel;
+
+ pixel = rtgui_color_to_mono(*c);
+ gfx_device_ops->set_pixel((char*)&pixel, x, y);
+}
+
static void _pixel_rgb565p_set_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint16_t pixel;
@@ -28,6 +42,14 @@ static void _pixel_rgb888_set_pixel(rtgui_color_t *c, int x, int y)
gfx_device_ops->set_pixel((char*)&pixel, x, y);
}
+static void _pixel_mono_get_pixel(rtgui_color_t *c, int x, int y)
+{
+ rt_uint8_t pixel;
+
+ gfx_device_ops->get_pixel((char*)&pixel, x, y);
+ *c = rtgui_color_from_mono(pixel);
+}
+
static void _pixel_rgb565p_get_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint16_t pixel;
@@ -52,6 +74,14 @@ static void _pixel_rgb888_get_pixel(rtgui_color_t *c, int x, int y)
*c = rtgui_color_from_888(pixel);
}
+static void _pixel_mono_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
+{
+ rt_uint8_t pixel;
+
+ pixel = rtgui_color_to_mono(*c);
+ gfx_device_ops->draw_hline((char*)&pixel, x1, x2, y);
+}
+
static void _pixel_rgb565p_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
rt_uint16_t pixel;
@@ -76,6 +106,14 @@ static void _pixel_rgb888_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
gfx_device_ops->draw_hline((char*)&pixel, x1, x2, y);
}
+static void _pixel_mono_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
+{
+ rt_uint8_t pixel;
+
+ pixel = rtgui_color_to_mono(*c);
+ gfx_device_ops->draw_vline((char*)&pixel, x, y1, y2);
+}
+
static void _pixel_rgb565p_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
{
rt_uint16_t pixel;
@@ -102,13 +140,19 @@ static void _pixel_rgb888_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
static void _pixel_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y)
{
- if (x2 > x1)
- gfx_device_ops->blit_line((char*)pixels, x1, y, (x2 - x1));
- else
- gfx_device_ops->blit_line((char*)pixels, x2, y, (x1 - x2));
+ gfx_device_ops->blit_line((char*)pixels, x1, x2, y);
}
/* pixel device */
+const struct rtgui_graphic_driver_ops _pixel_mono_ops =
+{
+ _pixel_mono_set_pixel,
+ _pixel_mono_get_pixel,
+ _pixel_mono_draw_hline,
+ _pixel_mono_draw_vline,
+ _pixel_draw_raw_hline,
+};
+
const struct rtgui_graphic_driver_ops _pixel_rgb565p_ops =
{
_pixel_rgb565p_set_pixel,
@@ -140,6 +184,9 @@ const struct rtgui_graphic_driver_ops *rtgui_pixel_device_get_ops(int pixel_form
{
switch (pixel_format)
{
+ case RTGRAPHIC_PIXEL_FORMAT_MONO:
+ return &_pixel_mono_ops;
+
case RTGRAPHIC_PIXEL_FORMAT_RGB565:
return &_pixel_rgb565_ops;
diff --git a/components/rtgui/common/rtgui_app.c b/components/rtgui/common/rtgui_app.c
new file mode 100644
index 0000000000..f16a97cbf5
--- /dev/null
+++ b/components/rtgui/common/rtgui_app.c
@@ -0,0 +1,380 @@
+/*
+ * File : rtgui_application.c
+ * This file is part of RTGUI in RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date Author Notes
+ * 2012-01-13 Grissiom first version(just a prototype of application API)
+ * 2012-07-07 Bernard move the send/recv message to the rtgui_system.c
+ */
+
+#include <rtgui/rtgui_system.h>
+#include <rtgui/rtgui_app.h>
+#include <rtgui/widgets/window.h>
+
+static void _rtgui_app_constructor(struct rtgui_app *app)
+{
+ /* set event handler */
+ rtgui_object_set_event_handler(RTGUI_OBJECT(app),
+ rtgui_app_event_handler);
+
+ app->name = RT_NULL;
+ /* set EXITED so we can destroy an application that just created */
+ app->state_flag = RTGUI_APP_FLAG_EXITED;
+ app->ref_count = 0;
+ app->exit_code = 0;
+ app->tid = RT_NULL;
+ app->server = RT_NULL;
+ app->mq = RT_NULL;
+ app->modal_object = RT_NULL;
+ app->main_object = RT_NULL;
+ app->on_idle = RT_NULL;
+}
+
+static void _rtgui_app_destructor(struct rtgui_app *app)
+{
+ RT_ASSERT(app != RT_NULL);
+
+ rt_free(app->name);
+ app->name = RT_NULL;
+}
+
+DEFINE_CLASS_TYPE(application, "application",
+ RTGUI_OBJECT_TYPE,
+ _rtgui_app_constructor,
+ _rtgui_app_destructor,
+ sizeof(struct rtgui_app));
+
+struct rtgui_app* rtgui_app_create(
+ rt_thread_t tid,
+ const char *title)
+{
+ rt_thread_t srv_tid;
+ struct rtgui_app *app;
+ struct rtgui_event_application event;
+
+ RT_ASSERT(tid != RT_NULL);
+ RT_ASSERT(title != RT_NULL);
+
+ /* create application */
+ app = RTGUI_APP(rtgui_object_create(RTGUI_APP_TYPE));
+ if (app == RT_NULL)
+ return RT_NULL;
+
+ /* one thread only can create one rtgui application */
+ RT_ASSERT(tid->user_data == 0);
+ app->tid = tid;
+ /* set user thread */
+ tid->user_data = (rt_uint32_t)app;
+
+ app->mq = rt_mq_create("rtgui", sizeof(union rtgui_event_generic), 32, RT_IPC_FLAG_FIFO);
+ if (app->mq == RT_NULL)
+ {
+ rt_kprintf("create msgq failed.\n");
+ goto __mq_err;
+ }
+
+ /* set application title */
+ app->name = (unsigned char*)rt_strdup((char*)title);
+ if (app->name == RT_NULL)
+ goto __err;
+
+ /* send a message to notify rtgui server */
+ srv_tid = rtgui_get_server();
+ if (srv_tid == RT_NULL)
+ {
+ rt_kprintf("gui server is not running.\n");
+ goto __err;
+ }
+
+ /* create the rtgui server application */
+ if (srv_tid == rt_thread_self())
+ return app;
+
+ RTGUI_EVENT_APP_CREATE_INIT(&event);
+ event.app = app;
+
+ /* notify rtgui server to one application has been created */
+ if (rtgui_send_sync(srv_tid, RTGUI_EVENT(&event), sizeof(event)) == RT_EOK)
+ {
+ return app;
+ }
+
+__err:
+__mq_err:
+ rtgui_object_destroy(RTGUI_OBJECT(app));
+ tid->user_data = 0;
+ return RT_NULL;
+}
+
+#define _rtgui_application_check(app) \
+ do { \
+ RT_ASSERT(app != RT_NULL); \
+ RT_ASSERT(app->tid != RT_NULL); \
+ RT_ASSERT(app->tid->user_data != 0); \
+ RT_ASSERT(app->mq != RT_NULL); \
+ } while (0)
+
+void rtgui_app_destroy(struct rtgui_app *app)
+{
+ rt_thread_t srv_tid;
+ _rtgui_application_check(app);
+
+ if (!(app->state_flag & RTGUI_APP_FLAG_EXITED))
+ {
+ rt_kprintf("cannot destroy a running application: %s.\n",
+ app->name);
+ return;
+ }
+
+ /* send a message to notify rtgui server */
+ srv_tid = rtgui_get_server();
+ if (srv_tid != rt_thread_self()) /* must not the server thread */
+ {
+ struct rtgui_event_application event;
+ RTGUI_EVENT_APP_DESTROY_INIT(&event);
+ event.app = app;
+
+ if (rtgui_send_sync(srv_tid, RTGUI_EVENT(&event), sizeof(event)) != RT_EOK)
+ {
+ rt_kprintf("destroy an application in server failed\n");
+ return ;
+ }
+ }
+
+ app->tid->user_data = 0;
+ rt_mq_delete(app->mq);
+ rtgui_object_destroy(RTGUI_OBJECT(app));
+}
+
+struct rtgui_app* rtgui_app_self(void)
+{
+ struct rtgui_app *app;
+ rt_thread_t self;
+
+ /* get current thread */
+ self = rt_thread_self();
+ app = (struct rtgui_app*)(self->user_data);
+
+ return app;
+}
+
+void rtgui_app_set_onidle(rtgui_idle_func_t onidle)
+{
+ struct rtgui_app *app;
+
+ app = rtgui_app_self();
+ if (app != RT_NULL)
+ app->on_idle = onidle;
+}
+
+rtgui_idle_func_t rtgui_app_get_onidle(void)
+{
+ struct rtgui_app *app;
+
+ app = rtgui_app_self();
+ if (app != RT_NULL)
+ return app->on_idle;
+ else
+ return RT_NULL;
+}
+
+rt_inline rt_bool_t _rtgui_application_dest_handle(
+ struct rtgui_app *app,
+ struct rtgui_event *event)
+{
+ struct rtgui_event_win* wevent = (struct rtgui_event_win*)event;
+
+ struct rtgui_object* dest_object = RTGUI_OBJECT(wevent->wid);
+
+ if (dest_object != RT_NULL)
+ {
+ if (dest_object->event_handler != RT_NULL)
+ return dest_object->event_handler(RTGUI_OBJECT(dest_object), event);
+ else
+ return RT_FALSE;
+ }
+ else
+ {
+ rt_kprintf("RTGUI ERROR:server sent a event(%d) without wid\n", event->type);
+ return RT_FALSE;
+ }
+}
+
+rt_bool_t rtgui_app_event_handler(struct rtgui_object* object, rtgui_event_t* event)
+{
+ struct rtgui_app* app;
+
+ RT_ASSERT(object != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
+
+ app = RTGUI_APP(object);
+
+ switch (event->type)
+ {
+ case RTGUI_EVENT_PAINT:
+ case RTGUI_EVENT_CLIP_INFO:
+ case RTGUI_EVENT_WIN_ACTIVATE:
+ case RTGUI_EVENT_WIN_DEACTIVATE:
+ case RTGUI_EVENT_WIN_CLOSE:
+ case RTGUI_EVENT_WIN_MOVE:
+ case RTGUI_EVENT_KBD:
+ _rtgui_application_dest_handle(app, event);
+ break;
+
+ case RTGUI_EVENT_APP_ACTIVATE:
+ if (app->main_object != RT_NULL)
+ {
+ rtgui_win_activate(RTGUI_WIN(app->main_object));
+ if (app->modal_object != RT_NULL)
+ rtgui_win_activate(RTGUI_WIN(app->modal_object));
+ }
+ else if (app->modal_object != RT_NULL)
+ {
+ rtgui_win_activate(RTGUI_WIN(app->modal_object));
+ }
+ break;
+
+ case RTGUI_EVENT_MOUSE_BUTTON:
+ case RTGUI_EVENT_MOUSE_MOTION:
+ {
+ struct rtgui_event_win* wevent = (struct rtgui_event_win*)event;
+ struct rtgui_object* dest_object = RTGUI_OBJECT(wevent->wid);
+
+ // FIXME: let application determine the dest_wiget but not in sever
+ // so we can combine this handler with above one
+ if (app->modal_object != RT_NULL &&
+ dest_object != app->modal_object)
+ {
+// rt_kprintf("discard event %s that is not sent to modal object\n",
+// event_string[event->type]);
+ }
+ else
+ {
+ _rtgui_application_dest_handle(app, event);
+ }
+ }
+ break;
+
+ case RTGUI_EVENT_TIMER:
+ {
+ struct rtgui_timer* timer;
+ struct rtgui_event_timer* etimer = (struct rtgui_event_timer*) event;
+
+ timer = etimer->timer;
+ if (timer->timeout != RT_NULL)
+ {
+ /* call timeout function */
+ timer->timeout(timer, timer->user_data);
+ }
+ }
+ break;
+
+ case RTGUI_EVENT_COMMAND:
+ {
+ struct rtgui_event_command *ecmd = (struct rtgui_event_command*)event;
+
+ if (ecmd->wid != RT_NULL)
+ return _rtgui_application_dest_handle(app, event);
+ }
+
+ default:
+ return rtgui_object_event_handler(object, event);
+ }
+
+ return RT_TRUE;
+}
+
+rt_inline void _rtgui_application_event_loop(struct rtgui_app *app)
+{
+ rt_err_t result;
+ rt_uint16_t current_ref;
+ struct rtgui_event *event;
+
+ _rtgui_application_check(app);
+
+ /* point to event buffer */
+ event = (struct rtgui_event*)app->event_buffer;
+
+ current_ref = ++app->ref_count;
+
+ while (current_ref <= app->ref_count)
+ {
+ RT_ASSERT(current_ref == app->ref_count);
+
+ if (app->on_idle != RT_NULL)
+ {
+ result = rtgui_recv_nosuspend(event, sizeof(union rtgui_event_generic));
+ if (result == RT_EOK)
+ RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
+ else if (result == -RT_ETIMEOUT)
+ app->on_idle(RTGUI_OBJECT(app), RT_NULL);
+ }
+ else
+ {
+ result = rtgui_recv(event, sizeof(union rtgui_event_generic));
+ if (result == RT_EOK)
+ RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
+ }
+ }
+}
+
+rt_base_t rtgui_app_run(struct rtgui_app *app)
+{
+ _rtgui_application_check(app);
+
+ app->state_flag &= ~RTGUI_APP_FLAG_EXITED;
+
+ _rtgui_application_event_loop(app);
+
+ if (app->ref_count == 0)
+ app->state_flag |= RTGUI_APP_FLAG_EXITED;
+
+ return app->exit_code;
+}
+
+void rtgui_app_exit(struct rtgui_app* app, rt_uint16_t code)
+{
+ --app->ref_count;
+ app->exit_code = code;
+}
+
+/**
+ * set this application as window manager
+ */
+rt_err_t rtgui_app_set_as_wm(void)
+{
+ rt_thread_t srv_tid;
+ struct rtgui_event_set_wm event;
+ struct rtgui_app* app;
+
+ srv_tid = rtgui_get_server();
+ app = rtgui_app_self();
+ if (app != RT_NULL && srv_tid != RT_NULL)
+ {
+ /* notify rtgui server, this is a window manager */
+ RTGUI_EVENT_SET_WM_INIT(&event);
+ event.app = app;
+
+ rtgui_send_sync(srv_tid, RTGUI_EVENT(&event), sizeof(event));
+ return RT_EOK;
+ }
+
+ return RT_ERROR;
+}
+
+void rtgui_app_set_main_win(struct rtgui_win* win)
+{
+ struct rtgui_app *app;
+
+ app = rtgui_app_self();
+ if (app != RT_NULL)
+ {
+ app->main_object = RTGUI_OBJECT(win);
+ }
+}
diff --git a/components/rtgui/common/rtgui_system.c b/components/rtgui/common/rtgui_system.c
index b840893139..dce11bfaf5 100644
--- a/components/rtgui/common/rtgui_system.c
+++ b/components/rtgui/common/rtgui_system.c
@@ -16,7 +16,7 @@
#include <rtgui/image.h>
#include <rtgui/font.h>
#include <rtgui/event.h>
-#include <rtgui/rtgui_application.h>
+#include <rtgui/rtgui_app.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/window.h>
@@ -26,7 +26,7 @@
#define RTGUI_MEM_TRACE
#endif
-void rtgui_system_server_init(void)
+void rtgui_system_server_init()
{
/* init image */
rtgui_system_image_init();
@@ -59,7 +59,7 @@ static void rtgui_time_out(void* parameter)
event.timer = timer;
- rtgui_application_send(timer->tid, &(event.parent), sizeof(rtgui_event_timer_t));
+ rtgui_send(timer->tid, &(event.parent), sizeof(rtgui_event_timer_t));
}
rtgui_timer_t* rtgui_timer_create(rt_int32_t time, rt_int32_t flag, rtgui_timeout_func timeout, void* parameter)
@@ -285,3 +285,416 @@ void rtgui_free(void* ptr)
rt_free(ptr);
}
+#if defined(RTGUI_MEM_TRACE) && defined(RT_USING_FINSH)
+#include <finsh.h>
+void list_mem(void)
+{
+ rt_kprintf("Current Used: %d, Maximal Used: %d\n", mem_info.allocated_size, mem_info.max_allocated);
+}
+FINSH_FUNCTION_EXPORT(list_mem, display memory information);
+#endif
+
+/************************************************************************/
+/* RTGUI Event Dump */
+/************************************************************************/
+
+#ifdef _WIN32
+#define RTGUI_EVENT_DEBUG
+#endif
+
+#ifdef RTGUI_EVENT_DEBUG
+const char *event_string[] =
+{
+ /* application event */
+ "APP_CREATE", /* create an application */
+ "APP_DESTROY", /* destroy an application */
+ "APP_ACTIVATE", /* activate an application */
+
+ /* window event */
+ "WIN_CREATE", /* create a window */
+ "WIN_DESTROY", /* destroy a window */
+ "WIN_SHOW", /* show a window */
+ "WIN_HIDE", /* hide a window */
+ "WIN_ACTIVATE", /* activate a window */
+ "WIN_DEACTIVATE", /* deactivate a window */
+ "WIN_CLOSE", /* close a window */
+ "WIN_MOVE", /* move a window */
+ "WIN_RESIZE", /* resize a window */
+ "WIN_MODAL_ENTER", /* a window modals */
+
+ "SET_WM", /* set window manager */
+
+ "UPDATE_BEGIN", /* begin of update rect */
+ "UPDATE_END", /* end of update rect */
+ "MONITOR_ADD", /* add a monitor rect */
+ "MONITOR_REMOVE", /* remove a monitor rect*/
+ "SHOW", /* the widget is going to be shown */
+ "HIDE", /* the widget is going to be hidden */
+ "PAINT", /* paint on screen */
+ "TIMER", /* timer */
+
+ /* clip rect information */
+ "CLIP_INFO", /* clip rect info */
+
+ /* mouse and keyboard event */
+ "MOUSE_MOTION", /* mouse motion */
+ "MOUSE_BUTTON", /* mouse button info */
+ "KBD", /* keyboard info */
+
+ /* user command event */
+ "COMMAND", /* user command */
+
+ /* request's status event */
+ "STATUS", /* request result */
+ "SCROLLED", /* scroll bar scrolled */
+ "RESIZE", /* widget resize */
+};
+
+#define DBG_MSG(x) rt_kprintf x
+
+static void rtgui_event_dump(rt_thread_t tid, rtgui_event_t* event)
+{
+ char* sender = "(unknown)";
+
+ if ((event->type == RTGUI_EVENT_TIMER) ||
+ (event->type == RTGUI_EVENT_UPDATE_BEGIN) ||
+ (event->type == RTGUI_EVENT_MOUSE_MOTION) ||
+ (event->type == RTGUI_EVENT_UPDATE_END))
+ {
+ /* don't dump timer event */
+ return ;
+ }
+
+ if (event->sender != RT_NULL)
+ sender = event->sender->name;
+
+ rt_kprintf("%s -- %s --> %s ", sender, event_string[event->type], tid->name);
+ switch (event->type)
+ {
+ case RTGUI_EVENT_APP_CREATE:
+ case RTGUI_EVENT_APP_DESTROY:
+ case RTGUI_EVENT_APP_ACTIVATE:
+ {
+ struct rtgui_event_application *eapp = (struct rtgui_event_application *)event;
+
+ rt_kprintf("app: %s", eapp->app->name);
+ }
+ break;
+
+ case RTGUI_EVENT_PAINT:
+ {
+ struct rtgui_event_paint *paint = (struct rtgui_event_paint *)event;
+
+ if(paint->wid != RT_NULL)
+ rt_kprintf("win: %s", paint->wid->title);
+ }
+ break;
+
+ case RTGUI_EVENT_KBD:
+ {
+ struct rtgui_event_kbd *ekbd = (struct rtgui_event_kbd*) event;
+ if (ekbd->wid != RT_NULL)
+ rt_kprintf("win: %s", ekbd->wid->title);
+ if (RTGUI_KBD_IS_UP(ekbd)) rt_kprintf(", up");
+ else rt_kprintf(", down");
+ }
+ break;
+
+ case RTGUI_EVENT_CLIP_INFO:
+ {
+ struct rtgui_event_clip_info *info = (struct rtgui_event_clip_info *)event;
+
+ if(info->wid != RT_NULL)
+ rt_kprintf("win: %s", info->wid->title);
+ }
+ break;
+
+ case RTGUI_EVENT_WIN_CREATE:
+ {
+ struct rtgui_event_win_create *create = (struct rtgui_event_win_create*)event;
+
+ rt_kprintf(" win: %s at (x1:%d, y1:%d, x2:%d, y2:%d), addr: %p",
+#ifdef RTGUI_USING_SMALL_SIZE
+ create->wid->title,
+ RTGUI_WIDGET(create->wid)->extent.x1,
+ RTGUI_WIDGET(create->wid)->extent.y1,
+ RTGUI_WIDGET(create->wid)->extent.x2,
+ RTGUI_WIDGET(create->wid)->extent.y2,
+#else
+ create->title,
+ create->extent.x1,
+ create->extent.y1,
+ create->extent.x2,
+ create->extent.y2,
+#endif
+ create->wid
+ );
+ }
+ break;
+
+ case RTGUI_EVENT_UPDATE_END:
+ {
+ struct rtgui_event_update_end* update_end = (struct rtgui_event_update_end*)event;
+ rt_kprintf("(x:%d, y1:%d, x2:%d, y2:%d)", update_end->rect.x1,
+ update_end->rect.y1,
+ update_end->rect.x2,
+ update_end->rect.y2);
+ }
+ break;
+
+ case RTGUI_EVENT_WIN_ACTIVATE:
+ case RTGUI_EVENT_WIN_DEACTIVATE:
+ case RTGUI_EVENT_WIN_SHOW:
+ case RTGUI_EVENT_WIN_MODAL_ENTER:
+ {
+ struct rtgui_event_win *win = (struct rtgui_event_win *)event;
+
+ if(win->wid != RT_NULL)
+ rt_kprintf("win: %s", win->wid->title);
+ }
+ break;
+
+ case RTGUI_EVENT_WIN_MOVE:
+ {
+ struct rtgui_event_win_move *win = (struct rtgui_event_win_move *)event;
+
+ if(win->wid != RT_NULL)
+ {
+ rt_kprintf("win: %s", win->wid->title);
+ rt_kprintf(" to (x:%d, y:%d)", win->x, win->y);
+ }
+ }
+ break;
+
+ case RTGUI_EVENT_WIN_RESIZE:
+ {
+ struct rtgui_event_win_resize* win = (struct rtgui_event_win_resize *)event;
+
+ if (win->wid != RT_NULL)
+ {
+ rt_kprintf("win: %s, rect(x1:%d, y1:%d, x2:%d, y2:%d)", win->wid->title,
+ RTGUI_WIDGET(win->wid)->extent.x1,
+ RTGUI_WIDGET(win->wid)->extent.y1,
+ RTGUI_WIDGET(win->wid)->extent.x2,
+ RTGUI_WIDGET(win->wid)->extent.y2);
+ }
+ }
+ break;
+
+ case RTGUI_EVENT_MOUSE_BUTTON:
+ case RTGUI_EVENT_MOUSE_MOTION:
+ {
+ struct rtgui_event_mouse *mouse = (struct rtgui_event_mouse*)event;
+
+ if (mouse->button & RTGUI_MOUSE_BUTTON_LEFT) rt_kprintf("left ");
+ else rt_kprintf("right ");
+
+ if (mouse->button & RTGUI_MOUSE_BUTTON_DOWN) rt_kprintf("down ");
+ else rt_kprintf("up ");
+
+ if (mouse->wid != RT_NULL)
+ rt_kprintf("win: %s at (%d, %d)", mouse->wid->title,
+ mouse->x, mouse->y);
+ else
+ rt_kprintf("(%d, %d)", mouse->x, mouse->y);
+ }
+ break;
+
+ case RTGUI_EVENT_MONITOR_ADD:
+ {
+ struct rtgui_event_monitor *monitor = (struct rtgui_event_monitor*)event;
+ if (monitor->wid != RT_NULL)
+ {
+ rt_kprintf("win: %s, the rect is:(%d, %d) - (%d, %d)", monitor->wid->title,
+ monitor->rect.x1, monitor->rect.y1,
+ monitor->rect.x2, monitor->rect.y2);
+ }
+ }
+ break;
+ }
+
+ rt_kprintf("\n");
+}
+#else
+#define DBG_MSG(x)
+#define rtgui_event_dump(tid, event)
+#endif
+
+/************************************************************************/
+/* RTGUI IPC APIs */
+/************************************************************************/
+rt_err_t rtgui_send(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
+{
+ rt_err_t result;
+ struct rtgui_app *app;
+
+ RT_ASSERT(tid != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event_size != 0);
+
+ rtgui_event_dump(tid, event);
+
+ /* find struct rtgui_application */
+ app = (struct rtgui_app*) (tid->user_data);
+ if (app == RT_NULL)
+ return -RT_ERROR;
+
+ result = rt_mq_send(app->mq, event, event_size);
+ if (result != RT_EOK)
+ {
+ if (event->type != RTGUI_EVENT_TIMER)
+ rt_kprintf("send event to %s failed\n", app->tid->name);
+ }
+
+ return result;
+}
+
+rt_err_t rtgui_send_urgent(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
+{
+ rt_err_t result;
+ struct rtgui_app *app;
+
+ RT_ASSERT(tid != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event_size != 0);
+
+ rtgui_event_dump(tid, event);
+
+ /* find rtgui_application */
+ app = (struct rtgui_app*) (tid->user_data);
+ if (app == RT_NULL)
+ return -RT_ERROR;
+
+ result = rt_mq_urgent(app->mq, event, event_size);
+ if (result != RT_EOK)
+ rt_kprintf("send ergent event failed\n");
+
+ return result;
+}
+
+rt_err_t rtgui_send_sync(rt_thread_t tid, rtgui_event_t* event, rt_size_t event_size)
+{
+ rt_err_t r;
+ struct rtgui_app *app;
+ rt_int32_t ack_buffer, ack_status;
+ struct rt_mailbox ack_mb;
+
+ RT_ASSERT(tid != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event_size != 0);
+
+ rtgui_event_dump(tid, event);
+
+ /* init ack mailbox */
+ r = rt_mb_init(&ack_mb, "ack", &ack_buffer, 1, 0);
+ if (r!= RT_EOK)
+ goto __return;
+
+ app = (struct rtgui_app*) (tid->user_data);
+ if (app == RT_NULL)
+ {
+ r = -RT_ERROR;
+ goto __return;
+ }
+
+ event->ack = &ack_mb;
+ r = rt_mq_send(app->mq, event, event_size);
+ if (r != RT_EOK)
+ {
+ rt_kprintf("send sync event failed\n");
+ goto __return;
+ }
+
+ r = rt_mb_recv(&ack_mb, (rt_uint32_t*)&ack_status, RT_WAITING_FOREVER);
+ if (r!= RT_EOK)
+ goto __return;
+
+ if (ack_status != RTGUI_STATUS_OK)
+ r = -RT_ERROR;
+ else
+ r = RT_EOK;
+
+__return:
+ /* fini ack mailbox */
+ rt_mb_detach(&ack_mb);
+ return r;
+}
+
+rt_err_t rtgui_ack(rtgui_event_t* event, rt_int32_t status)
+{
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event->ack != RT_NULL);
+
+ rt_mb_send(event->ack, status);
+
+ return RT_EOK;
+}
+
+rt_err_t rtgui_recv(rtgui_event_t* event, rt_size_t event_size)
+{
+ struct rtgui_app* app;
+ rt_err_t r;
+
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event_size != 0);
+
+ app = (struct rtgui_app*) (rt_thread_self()->user_data);
+ if (app == RT_NULL)
+ return -RT_ERROR;
+
+ r = rt_mq_recv(app->mq, event, event_size, RT_WAITING_FOREVER);
+
+ return r;
+}
+
+rt_err_t rtgui_recv_nosuspend(rtgui_event_t* event, rt_size_t event_size)
+{
+ struct rtgui_app *app;
+ rt_err_t r;
+
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event != 0);
+
+ app = (struct rtgui_app*) (rt_thread_self()->user_data);
+ if (app == RT_NULL)
+ return -RT_ERROR;
+
+ r = rt_mq_recv(app->mq, event, event_size, 0);
+
+ return r;
+}
+
+rt_err_t rtgui_recv_filter(rt_uint32_t type, rtgui_event_t* event, rt_size_t event_size)
+{
+ struct rtgui_app *app;
+
+ RT_ASSERT(event != RT_NULL);
+ RT_ASSERT(event_size != 0);
+
+ app = (struct rtgui_app*) (rt_thread_self()->user_data);
+ if (app == RT_NULL)
+ return -RT_ERROR;
+
+ while (rt_mq_recv(app->mq, event, event_size, RT_WAITING_FOREVER) == RT_EOK)
+ {
+ if (event->type == type)
+ {
+ return RT_EOK;
+ }
+ else
+ {
+ if (RTGUI_OBJECT(app)->event_handler != RT_NULL)
+ {
+ RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
+ }
+ }
+ }
+
+ return -RT_ERROR;
+}
+
+rt_thread_t rtgui_get_server(void)
+{
+ return rt_thread_find("rtgui");
+}
+