summaryrefslogtreecommitdiff
path: root/rtgui
diff options
context:
space:
mode:
authorbernard.xiong <[email protected]>2009-10-16 00:03:50 +0000
committerbernard.xiong <[email protected]>2009-10-16 00:03:50 +0000
commita0e99e8ad1a74e10d9de6b553ce8cb1b80aae48c (patch)
treef47fc0a90b58670124c68ed77958666d3c061a51 /rtgui
parent72adcb331c43798721d9a1e3516ae8df99c73bde (diff)
add RTGUI source code
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@104 bbd45198-f89e-11dd-88c7-29a3b14d5316
Diffstat (limited to 'rtgui')
-rw-r--r--rtgui/common/asc12font.c227
-rw-r--r--rtgui/common/asc16font.c293
-rw-r--r--rtgui/common/caret.c214
-rw-r--r--rtgui/common/color.c33
-rw-r--r--rtgui/common/dc.c1223
-rw-r--r--rtgui/common/dc_buffer.c392
-rw-r--r--rtgui/common/dc_hw.c436
-rw-r--r--rtgui/common/filerw.c329
-rw-r--r--rtgui/common/font.c205
-rw-r--r--rtgui/common/image.c192
-rw-r--r--rtgui/common/image_xpm.c617
-rw-r--r--rtgui/common/region.c2228
-rw-r--r--rtgui/common/rtgui_system.c12
-rw-r--r--rtgui/common/rtgui_theme.c12
-rw-r--r--rtgui/include/rtgui/caret.h53
-rw-r--r--rtgui/include/rtgui/color.h97
-rw-r--r--rtgui/include/rtgui/dc.h126
-rw-r--r--rtgui/include/rtgui/filerw.h47
-rw-r--r--rtgui/include/rtgui/font.h88
-rw-r--r--rtgui/include/rtgui/image.h63
-rw-r--r--rtgui/include/rtgui/image_png.h19
-rw-r--r--rtgui/include/rtgui/image_xpm.h21
-rw-r--r--rtgui/include/rtgui/kbddef.h293
-rw-r--r--rtgui/include/rtgui/list.h66
-rw-r--r--rtgui/include/rtgui/region.h100
-rw-r--r--rtgui/include/rtgui/rtgui.h5
-rw-r--r--rtgui/include/rtgui/rtgui_config.h36
-rw-r--r--rtgui/include/rtgui/rtgui_server.h5
-rw-r--r--rtgui/include/rtgui/rtgui_theme.h1
-rw-r--r--rtgui/include/rtgui/widgets/box.h58
-rw-r--r--rtgui/include/rtgui/widgets/button.h81
-rw-r--r--rtgui/include/rtgui/widgets/container.h47
-rw-r--r--rtgui/include/rtgui/widgets/iconbox.h56
-rw-r--r--rtgui/include/rtgui/widgets/label.h49
-rw-r--r--rtgui/include/rtgui/widgets/listbox.h66
-rw-r--r--rtgui/include/rtgui/widgets/textbox.h73
-rw-r--r--rtgui/include/rtgui/widgets/title.h45
-rw-r--r--rtgui/include/rtgui/widgets/toplevel.h57
-rw-r--r--rtgui/include/rtgui/widgets/view.h61
-rw-r--r--rtgui/server/mouse.c629
-rw-r--r--rtgui/server/mouse.h51
-rw-r--r--rtgui/server/panel.h4
-rw-r--r--rtgui/server/server.c6
-rw-r--r--rtgui/server/topwin.c868
-rw-r--r--rtgui/server/topwin.h56
-rw-r--r--rtgui/widgets/box.c340
-rw-r--r--rtgui/widgets/button.c170
-rw-r--r--rtgui/widgets/container.c279
-rw-r--r--rtgui/widgets/iconbox.c154
-rw-r--r--rtgui/widgets/label.c113
-rw-r--r--rtgui/widgets/textbox.c346
-rw-r--r--rtgui/widgets/title.c73
-rw-r--r--rtgui/widgets/toplevel.c191
-rw-r--r--rtgui/widgets/view.c149
54 files changed, 11425 insertions, 30 deletions
diff --git a/rtgui/common/asc12font.c b/rtgui/common/asc12font.c
new file mode 100644
index 0000000000..2ea0ca049d
--- /dev/null
+++ b/rtgui/common/asc12font.c
@@ -0,0 +1,227 @@
+/*
+ * File : asc12font.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/font.h>
+
+const rt_uint8_t asc12_font[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81,
+0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff,
+0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c,
+0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18,
+0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3c,
+0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99,
+0xc3, 0xff, 0xff, 0xff, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00,
+0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30,
+0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67,
+0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00,
+0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x06, 0x0e, 0x1e, 0x3e,
+0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c,
+0x18, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00,
+0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0xc6, 0x60, 0x38, 0x6c,
+0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe,
+0xfe, 0xfe, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00,
+0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28,
+0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe,
+0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
+0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x50, 0x50, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x40, 0x40, 0x38, 0x48, 0x70, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20, 0x50, 0x20,
+0x0c, 0x70, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x20, 0x54, 0x48,
+0x34, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x20, 0x20, 0x10,
+0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x10, 0x7c, 0x10, 0x28, 0x28, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0xfc, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x00, 0x00,
+0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x10,
+0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x20, 0x44,
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x18, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
+0x00, 0x0c, 0x14, 0x14, 0x24, 0x44, 0x7c, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x20, 0x20,
+0x38, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x78, 0x44, 0x44, 0x44,
+0x38, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x44, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00,
+0x00, 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44,
+0x44, 0x3c, 0x04, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30,
+0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x30, 0x20, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x10, 0x60, 0x80, 0x60, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x7c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x18, 0x04, 0x18, 0x20,
+0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x04, 0x08, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00,
+0x38, 0x44, 0x44, 0x4c, 0x54, 0x54, 0x4c, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, 0x30, 0x10, 0x28,
+0x28, 0x28, 0x7c, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x44, 0x44, 0x78, 0x44, 0x44, 0x44,
+0xf8, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x40, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
+0x00, 0xf0, 0x48, 0x44, 0x44, 0x44, 0x44, 0x48, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x44, 0x50,
+0x70, 0x50, 0x40, 0x44, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x20, 0x28, 0x38, 0x28, 0x20, 0x20,
+0x70, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x40, 0x40, 0x4c, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
+0x00, 0xec, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10,
+0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x08, 0x08, 0x48, 0x48, 0x48,
+0x30, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x48, 0x50, 0x70, 0x48, 0x44, 0xe4, 0x00, 0x00, 0x00,
+0x00, 0x70, 0x20, 0x20, 0x20, 0x20, 0x24, 0x24, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0x6c,
+0x54, 0x54, 0x44, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0xec, 0x64, 0x64, 0x54, 0x54, 0x54, 0x4c,
+0xec, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
+0x00, 0x78, 0x24, 0x24, 0x24, 0x38, 0x20, 0x20, 0x70, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44,
+0x44, 0x44, 0x44, 0x44, 0x38, 0x1c, 0x00, 0x00, 0x00, 0xf8, 0x44, 0x44, 0x44, 0x78, 0x48, 0x44,
+0xe0, 0x00, 0x00, 0x00, 0x00, 0x34, 0x4c, 0x40, 0x38, 0x04, 0x04, 0x64, 0x58, 0x00, 0x00, 0x00,
+0x00, 0xfc, 0x90, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44,
+0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44, 0x28, 0x28, 0x28, 0x10,
+0x10, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44, 0x54, 0x54, 0x54, 0x54, 0x28, 0x00, 0x00, 0x00,
+0x00, 0xc4, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x28,
+0x28, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x44, 0x08, 0x10, 0x10, 0x20, 0x44,
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00,
+0x00, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x38, 0x08, 0x08,
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x10, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+0x44, 0x3c, 0x44, 0x44, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44,
+0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
+0x00, 0x0c, 0x04, 0x34, 0x4c, 0x44, 0x44, 0x44, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+0x44, 0x7c, 0x40, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x7c, 0x20, 0x20, 0x20, 0x20,
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x4c, 0x44, 0x44, 0x44, 0x3c, 0x04, 0x38, 0x00,
+0x00, 0xc0, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70,
+0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08,
+0x08, 0x08, 0x70, 0x00, 0x00, 0xc0, 0x40, 0x5c, 0x48, 0x70, 0x50, 0x48, 0xdc, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8,
+0x54, 0x54, 0x54, 0x54, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x64, 0x44, 0x44, 0x44,
+0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xd8, 0x64, 0x44, 0x44, 0x44, 0x78, 0x40, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x34,
+0x4c, 0x44, 0x44, 0x44, 0x3c, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x30, 0x20, 0x20, 0x20,
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x38, 0x04, 0x44, 0x78, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x20, 0x7c, 0x20, 0x20, 0x20, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc,
+0x44, 0x44, 0x44, 0x4c, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44, 0x28, 0x28,
+0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x54, 0x54, 0x54, 0x28, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xcc, 0x48, 0x30, 0x30, 0x48, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec,
+0x44, 0x24, 0x28, 0x18, 0x10, 0x10, 0x78, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x48, 0x10, 0x20, 0x44,
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x08, 0x00,
+0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10,
+0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x58, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+const struct rtgui_font_bitmap asc12 =
+{
+ asc12_font, /* bmp */
+ 6, /* width */
+ 12, /* height */
+ 0, /* first char */
+ 255 /* last char */
+};
+
+struct rtgui_font rtgui_font_asc12 =
+{
+ "asc", /* family */
+ 12, /* height */
+ 1, /* refer count */
+ &bmp_font_engine, /* font engine */
+ (struct rtgui_font_bitmap *)&asc12, /* font private data */
+};
diff --git a/rtgui/common/asc16font.c b/rtgui/common/asc16font.c
new file mode 100644
index 0000000000..bf69713c2f
--- /dev/null
+++ b/rtgui/common/asc16font.c
@@ -0,0 +1,293 @@
+/*
+ * File : asc16font.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/font.h>
+
+unsigned char asc16_font[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
+0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
+0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
+0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
+0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
+0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00,
+0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00,
+0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+struct rtgui_font_bitmap asc16 =
+{
+ asc16_font, /* bmp */
+ 8, /* width */
+ 16, /* height */
+ 0, /* first char */
+ 255 /* last char */
+};
+
+struct rtgui_font rtgui_font_asc16 =
+{
+ "asc", /* family */
+ 16, /* height */
+ 1, /* refer count */
+ &bmp_font_engine, /* font engine */
+ &asc16, /* font private data */
+};
+
+/* size = 4096 bytes */
diff --git a/rtgui/common/caret.c b/rtgui/common/caret.c
new file mode 100644
index 0000000000..dbf5d6af45
--- /dev/null
+++ b/rtgui/common/caret.c
@@ -0,0 +1,214 @@
+/*
+ * File : caret.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/caret.h>
+#include <rtgui/rtgui_system.h>
+
+#define RTGUI_CARET_WIDTH 2
+
+#ifdef __WIN32__
+#define RTGUI_CARET_BLINK 300
+#else
+#define RTGUI_CARET_BLINK 30
+#endif
+
+static void rtgui_caret_blink(struct rtgui_timer* timer, void* parameter)
+{
+ struct rtgui_caret* caret;
+ rtgui_widget_t* widget;
+
+ caret = (struct rtgui_caret*)parameter;
+
+ RT_ASSERT(caret != RT_NULL);
+
+ if (caret->owner == RT_NULL) return;
+
+ /* caret's owner is visible? */
+ widget = caret->owner;
+ do
+ {
+ if (RTGUI_WIDGET_IS_HIDE(widget) == RT_TRUE) return;
+
+ widget = widget->parent;
+ } while (widget != RT_NULL);
+
+ if (caret->is_show == RT_TRUE)
+ {
+ /* set to false */
+ caret->is_show = RT_FALSE;
+
+ /* update owner widget */
+ if (caret->owner != RT_NULL)
+ {
+ rtgui_widget_update(caret->owner);
+ }
+ }
+ else
+ {
+ /* set to true */
+ caret->is_show = RT_TRUE;
+
+ /* draw caret */
+ rtgui_caret_draw(caret);
+ }
+}
+
+struct rtgui_caret* rtgui_caret_create(struct rtgui_widget* owner)
+{
+ struct rtgui_caret* caret;
+
+ RT_ASSERT(owner != RT_NULL);
+
+ caret = (struct rtgui_caret*)rtgui_malloc(sizeof(struct rtgui_caret));
+ if (caret != RT_NULL)
+ {
+ caret->is_show = RT_FALSE;
+
+ caret->extent.x1 = 0;
+ caret->extent.y1 = 0;
+ caret->extent.x2 = RTGUI_CARET_WIDTH;
+ caret->extent.y2 = owner->gc.font->height;
+ caret->owner = owner;
+
+ caret->dc = (struct rtgui_dc*)rtgui_dc_buffer_create(RTGUI_CARET_WIDTH, caret->extent.y2);
+ if (caret->dc == RT_NULL) goto __exit;
+
+ rtgui_dc_set_color(caret->dc, black);
+ rtgui_dc_fill_rect(caret->dc, &(caret->extent));
+
+ caret->timer_period = RTGUI_CARET_BLINK;
+ caret->timer = rtgui_timer_create(caret->timer_period,
+ RT_TIMER_FLAG_PERIODIC,
+ rtgui_caret_blink, caret);
+ if (caret->timer == RT_NULL) goto __exit_dc;
+
+ caret->show_point.x = 0;
+ caret->show_point.y = 0;
+ }
+
+ return caret;
+
+__exit_dc:
+ rtgui_dc_destory(caret->dc);
+__exit:
+ rtgui_free(caret);
+ return RT_NULL;
+}
+
+void rtgui_caret_destroy(struct rtgui_caret* caret)
+{
+ RT_ASSERT(caret != RT_NULL);
+
+ if (caret->is_show == RT_TRUE)
+ {
+ /* stop timer */
+ rtgui_timer_stop(caret->timer);
+ }
+
+ caret->owner = RT_NULL;
+ rtgui_dc_destory(caret->dc);
+ rtgui_timer_destory(caret->timer);
+
+ rtgui_free(caret);
+}
+
+/* show caret on owner widget logic position */
+void rtgui_caret_show(struct rtgui_caret* caret, rt_base_t x, rt_base_t y)
+{
+ if (caret->is_show == RT_TRUE)
+ {
+ /* set show flag and stop blink timer */
+ caret->is_show = RT_FALSE;
+ rtgui_timer_stop(caret->timer);
+ }
+
+ /* set show x and y */
+ caret->show_point.x = x;
+ caret->show_point.y = y;
+
+ /* set show flag and start blink timer */
+ caret->is_show = RT_TRUE;
+
+ /* draw caret */
+ rtgui_caret_draw(caret);
+
+ /* start blink timer */
+ rtgui_timer_start(caret->timer);
+}
+
+void rtgui_caret_hide(struct rtgui_caret* caret)
+{
+ RT_ASSERT(caret != RT_NULL);
+
+ /* set show flag and stop blink timer */
+ caret->is_show = RT_FALSE;
+ rtgui_timer_stop(caret->timer);
+
+ /* update owner widget */
+ if (caret->owner != RT_NULL)
+ {
+ rtgui_widget_update(caret->owner);
+ }
+}
+
+void rtgui_caret_set_point(struct rtgui_caret* caret, int x, int y)
+{
+ RT_ASSERT(caret != RT_NULL);
+
+ if (caret->is_show == RT_TRUE)
+ {
+ /* stop the old caret */
+ rtgui_timer_stop(caret->timer);
+ /* update owner widget */
+ if (caret->owner != RT_NULL && caret->is_show)
+ {
+ rtgui_widget_update(caret->owner);
+ }
+ }
+
+ caret->show_point.x = x;
+ caret->show_point.y = y;
+
+ /* draw caret */
+ rtgui_caret_draw(caret);
+
+ /* start blink timer */
+ rtgui_timer_start(caret->timer);
+}
+
+void rtgui_caret_set_box(struct rtgui_caret* caret, int w, int h)
+{
+ RT_ASSERT(caret != RT_NULL);
+
+ caret->extent.x2 = caret->extent.x1 + w;
+ caret->extent.y2 = caret->extent.y1 + h;
+}
+
+void rtgui_caret_draw(struct rtgui_caret* caret)
+{
+ RT_ASSERT(caret != RT_NULL);
+
+ if (caret->is_show == RT_TRUE && caret->owner->toplevel != RT_NULL)
+ {
+ struct rtgui_rect rect = caret->extent;
+ struct rtgui_point point = {0, 0};
+ struct rtgui_dc* hw_dc;
+
+ rtgui_rect_moveto(&rect, caret->show_point.x, caret->show_point.y);
+ hw_dc = rtgui_dc_begin_drawing(caret->owner);
+ rtgui_dc_blit(caret->dc, &point, hw_dc, &rect);
+ rtgui_dc_end_drawing(hw_dc);
+ }
+}
+
diff --git a/rtgui/common/color.c b/rtgui/common/color.c
new file mode 100644
index 0000000000..33fc3606d6
--- /dev/null
+++ b/rtgui/common/color.c
@@ -0,0 +1,33 @@
+/*
+ * File : color.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/color.h>
+
+const rtgui_color_t red = RTGUI_RGB(0xff, 0x00, 0x00);
+const rtgui_color_t green = RTGUI_RGB(0x00, 0xff, 0x00);
+const rtgui_color_t blue = RTGUI_RGB(0x00, 0x00, 0xff);
+const rtgui_color_t black = RTGUI_RGB(0x00, 0x00, 0x00);
+const rtgui_color_t white = RTGUI_RGB(0xff, 0xff, 0xff);
+
+const rtgui_color_t high_light = RTGUI_RGB(0xff, 0xff, 0xff);
+const rtgui_color_t dark_grey = RTGUI_RGB(0x7f, 0x7f, 0x7f);
+const rtgui_color_t light_grey = RTGUI_RGB(0xc0, 0xc0, 0xc0);
+
+const rtgui_color_t default_foreground = RTGUI_RGB(0x00, 0x00, 0x00);
+const rtgui_color_t default_background = RTGUI_RGB(0xff, 0xff, 0xff);
+
+#define RTGUI_RGB_R(c) ((c) & 0xff)
+#define RTGUI_RGB_G(c) (((c) >> 8) & 0xff)
+#define RTGUI_RGB_B(c) (((c) >> 16) & 0xff)
+#define RTGUI_RGB_A(c) (((c) >> 24) & 0xff)
+
diff --git a/rtgui/common/dc.c b/rtgui/common/dc.c
new file mode 100644
index 0000000000..5701c56f4e
--- /dev/null
+++ b/rtgui/common/dc.c
@@ -0,0 +1,1223 @@
+/*
+ * File : dc.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_system.h>
+
+void rtgui_dc_destory(struct rtgui_dc* dc)
+{
+ if (dc == RT_NULL) return;
+
+ dc->fini(dc);
+ rtgui_free(dc);
+}
+
+/*
+ * draw a point on dc
+ */
+void rtgui_dc_draw_point(struct rtgui_dc* dc, int x, int y)
+{
+ if (dc == RT_NULL) return;
+
+ dc->draw_point(dc, x, y);
+}
+
+#if 0
+void rtgui_dc_draw_point_alpha(struct rtgui_dc* dc, int x, int y, rt_uint8_t alpha)
+{
+ if (dc == RT_NULL || alpha == 0xff) return;
+
+ if (dc->draw_point_alpha != RT_NULL)
+ dc->draw_point_alpha(dc, x, y, alpha);
+ else
+ {
+ rtgui_color_t color;
+
+ /* soft alpha bending */
+ color = dc->get_color(dc, int x, int y);
+ dc->draw_point(dc, x, y);
+ }
+}
+#endif
+
+/*
+ * draw a vertical line on dc
+ */
+void rtgui_dc_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2)
+{
+ if (dc == RT_NULL) return;
+
+ dc->draw_vline(dc, x, y1, y2);
+}
+
+/*
+ * draw a horizontal line on dc
+ */
+void rtgui_dc_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y)
+{
+ if (dc == RT_NULL) return;
+
+ dc->draw_hline(dc, x1, x2, y);
+}
+
+void rtgui_dc_draw_line (struct rtgui_dc* dc, int x1, int y1, int x2, int y2)
+{
+ if (dc == RT_NULL) return;
+
+ if (y1 == y2)
+ {
+ rtgui_dc_draw_hline(dc, x1, x2, y1);
+ }
+ else if (x1 == x2)
+ {
+ rtgui_dc_draw_vline(dc, x1, y1, y2);
+ }
+ else
+ {
+ int dx, dy, sdx, sdy, dxabs, dyabs, x, y, px, py;
+ register rt_base_t i;
+ /* rtgui_rect_t rect; */
+
+ dx = x2 - x1; /* the horizontal distance of the line */
+ dy = y2 - y1; /* the vertical distance of the line */
+
+#define rtgui_sgn(x) ((x<0)?-1:((x>0)?1:0)) /* macro to return the sign of a number */
+#define rtgui_abs(x) ((x)>=0? (x):-(x)) /* macro to return the absolute value */
+
+ dxabs = rtgui_abs(dx);
+ dyabs = rtgui_abs(dy);
+ sdx = rtgui_sgn(dx);
+ sdy = rtgui_sgn(dy);
+ x = dyabs >> 1;
+ y = dxabs >> 1;
+ px = x1;
+ py = y1;
+
+ if(dxabs >= dyabs) /* the line is more horizontal than vertical */
+ {
+ for(i = 0; i < dxabs; i++)
+ {
+ y += dyabs;
+ if(y >= dxabs)
+ {
+ y -= dxabs;
+ py += sdy;
+ }
+ px += sdx;
+
+ /* draw this point */
+ dc->draw_point(dc, px, py);
+ }
+ }
+ else /* the line is more vertical than horizontal */
+ {
+ for(i = 0; i < dyabs; i++)
+ {
+ x += dxabs;
+ if(x >= dyabs)
+ {
+ x -= dyabs;
+ px += sdx;
+ }
+ py += sdy;
+
+ /* draw this point */
+ dc->draw_point(dc, px, py);
+ }
+ }
+ }
+}
+
+#if 0
+/* AA Line */
+#define AAlevels 256
+#define AAbits 8
+
+int rtgui_dc_draw_line_aa(struct rtgui_dc* dc, rt_int16_t x1, rt_int16_t y1, rt_int16_t x2, rt_int16_t y2)
+{
+ Sint32 xx0, yy0, xx1, yy1;
+ int result;
+ rt_uint32_t intshift, erracc, erradj;
+ rt_uint32_t erracctmp, wgt, wgtcompmask;
+ int dx, dy, tmp, xdir, y0p1, x0pxdir;
+
+ /*
+ * Keep on working with 32bit numbers
+ */
+ xx0 = x1;
+ yy0 = y1;
+ xx1 = x2;
+ yy1 = y2;
+
+ /*
+ * Reorder points if required
+ */
+ if (yy0 > yy1)
+ {
+ tmp = yy0;
+ yy0 = yy1;
+ yy1 = tmp;
+ tmp = xx0;
+ xx0 = xx1;
+ xx1 = tmp;
+ }
+
+ /*
+ * Calculate distance
+ */
+ dx = xx1 - xx0;
+ dy = yy1 - yy0;
+
+ /*
+ * Adjust for negative dx and set xdir
+ */
+ if (dx >= 0)
+ {
+ xdir = 1;
+ }
+ else
+ {
+ xdir = -1;
+ dx = (-dx);
+ }
+
+ /*
+ * Check for special cases
+ */
+ if (dx == 0)
+ {
+ /*
+ * Vertical line
+ */
+ rtgui_dc_draw_vline(dc, x1, y1, y2);
+ return ;
+ }
+ else if (dy == 0)
+ {
+ /*
+ * Horizontal line
+ */
+ rtgui_dc_draw_hline(dc, x1, x2, y1);
+ return ;
+ }
+ else if (dx == dy)
+ {
+ /*
+ * Diagonal line
+ */
+ rtgui_dc_draw_line(dc, x1, y1, x2, y2);
+ return ;
+ }
+
+ /*
+ * Zero accumulator
+ */
+ erracc = 0;
+
+ /*
+ * # of bits by which to shift erracc to get intensity level
+ */
+ intshift = 32 - AAbits;
+ /*
+ * Mask used to flip all bits in an intensity weighting
+ */
+ wgtcompmask = AAlevels - 1;
+
+ /*
+ * Draw the initial pixel in the foreground color
+ */
+ rtgui_dc_draw_point(dc, x1, y1);
+
+ /*
+ * x-major or y-major?
+ */
+ if (dy > dx)
+ {
+ /*
+ * y-major. Calculate 16-bit fixed point fractional part of a pixel that
+ * X advances every time Y advances 1 pixel, truncating the result so that
+ * we won't overrun the endpoint along the X axis
+ */
+ /*
+ * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
+ */
+ erradj = ((dx << 16) / dy) << 16;
+
+ /*
+ * draw all pixels other than the first and last
+ */
+ x0pxdir = xx0 + xdir;
+ while (--dy)
+ {
+ erracctmp = erracc;
+ erracc += erradj;
+ if (erracc <= erracctmp)
+ {
+ /*
+ * rollover in error accumulator, x coord advances
+ */
+ xx0 = x0pxdir;
+ x0pxdir += xdir;
+ }
+ yy0++; /* y-major so always advance Y */
+
+ /*
+ * the AAbits most significant bits of erracc give us the intensity
+ * weighting for this pixel, and the complement of the weighting for
+ * the paired pixel.
+ */
+ wgt = (erracc >> intshift) & 255;
+ rtgui_dc_draw_point_alpha (dc, xx0, yy0, 255 - wgt);
+ rtgui_dc_draw_point_alpha (dc, x0pxdir, yy0, wgt);
+ }
+ }
+ else
+ {
+
+ /*
+ * x-major line. Calculate 16-bit fixed-point fractional part of a pixel
+ * that Y advances each time X advances 1 pixel, truncating the result so
+ * that we won't overrun the endpoint along the X axis.
+ */
+ /*
+ * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
+ */
+ erradj = ((dy << 16) / dx) << 16;
+
+ /*
+ * draw all pixels other than the first and last
+ */
+ y0p1 = yy0 + 1;
+ while (--dx)
+ {
+
+ erracctmp = erracc;
+ erracc += erradj;
+ if (erracc <= erracctmp)
+ {
+ /*
+ * Accumulator turned over, advance y
+ */
+ yy0 = y0p1;
+ y0p1++;
+ }
+ xx0 += xdir; /* x-major so always advance X */
+ /*
+ * the AAbits most significant bits of erracc give us the intensity
+ * weighting for this pixel, and the complement of the weighting for
+ * the paired pixel.
+ */
+ wgt = (erracc >> intshift) & 255;
+ rtgui_dc_draw_point_alpha (dc, xx0, yy0, 255 - wgt);
+ rtgui_dc_draw_point_alpha (dc, xx0, y0p1, wgt);
+ }
+ }
+
+ /*
+ * Draw final pixel, always exactly intersected by the line and doesn't
+ * need to be weighted.
+ */
+ rtgui_dc_draw_point(dc, x2, y2);
+}
+#endif
+
+void rtgui_dc_draw_rect (struct rtgui_dc* dc, struct rtgui_rect* rect)
+{
+ rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y1);
+ rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y2 - 1);
+
+ rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
+ rtgui_dc_draw_vline(dc, rect->x2 - 1, rect->y1, rect->y2);
+}
+
+void rtgui_dc_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect)
+{
+ if (dc == RT_NULL) return;
+
+ dc->fill_rect(dc, rect);
+}
+
+void rtgui_dc_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
+{
+ if (dc == RT_NULL || dest == RT_NULL || rect == RT_NULL) return;
+
+ dc->blit(dc, dc_point, dest, rect);
+}
+
+void rtgui_dc_draw_text (struct rtgui_dc* dc, const rt_uint8_t* text, struct rtgui_rect* rect)
+{
+ rt_uint32_t len;
+ struct rtgui_font *font;
+#ifdef RTGUI_USING_FONTHZ
+ struct rtgui_font *gb2312_font;
+#endif
+ struct rtgui_rect text_rect;
+
+ RT_ASSERT(dc != RT_NULL);
+
+ font = rtgui_dc_get_font(dc);
+ if (font == RT_NULL)
+ {
+ /* use system default font */
+ font = rtgui_font_default();
+ }
+
+#ifdef RTGUI_USING_FONTHZ
+ gb2312_font = rtgui_font_refer("hz", font->height);
+ if (gb2312_font == RT_NULL)
+ {
+ gb2312_font = rtgui_font_refer("hz", 16);
+ }
+#endif
+
+ /* text align */
+ rtgui_font_get_metrics(font, text, &text_rect);
+ rtgui_rect_moveto_align(rect, &text_rect, rtgui_dc_get_textalign(dc));
+
+#ifdef RTGUI_USING_FONTHZ
+ while (*text)
+ {
+ len = 0;
+ while (*(text + len) < 0x80 && *(text + len)) len ++;
+ if (len > 0)
+ {
+ rtgui_font_draw(font, dc, text, len, &text_rect);
+
+ text += len;
+ }
+
+ len = 0;
+ while (*(text + len) > 0x80) len ++;
+ if (len > 0)
+ {
+ rtgui_font_draw(gb2312_font, dc, text, len, &text_rect);
+
+ text += len;
+ }
+ }
+
+ rtgui_font_derefer(gb2312_font);
+#else
+ len = strlen(text);
+ rtgui_font_draw(font, dc, text, len, &text_rect);
+#endif
+}
+
+void rtgui_dc_set_color(struct rtgui_dc* dc, rtgui_color_t color)
+{
+ if (dc != RT_NULL)
+ {
+ dc->set_color(dc, color);
+ }
+}
+
+rtgui_color_t rtgui_dc_get_color(struct rtgui_dc* dc)
+{
+ if (dc != RT_NULL)
+ {
+ return dc->get_color(dc);
+ }
+
+ return white;
+}
+
+void rtgui_dc_set_font(struct rtgui_dc* dc, rtgui_font_t* font)
+{
+ if (dc != RT_NULL)
+ {
+ dc->set_font(dc, font);
+ }
+}
+
+rtgui_font_t* rtgui_dc_get_font(struct rtgui_dc* dc)
+{
+ if (dc != RT_NULL)
+ {
+ return dc->get_font(dc);
+ }
+
+ return RT_NULL;
+}
+
+void rtgui_dc_set_textalign(struct rtgui_dc* dc, rt_int32_t align)
+{
+ if (dc != RT_NULL)
+ {
+ dc->set_textalign(dc, align);
+ }
+}
+
+rt_int32_t rtgui_dc_get_textalign(struct rtgui_dc* dc)
+{
+ if (dc != RT_NULL)
+ {
+ return dc->get_textalign(dc);
+ }
+
+ return RTGUI_ALIGN_NOT;
+}
+
+rt_bool_t rtgui_dc_get_visible(struct rtgui_dc* dc)
+{
+ if (dc != RT_NULL)
+ {
+ return dc->get_visible(dc);
+ }
+
+ return RT_FALSE;
+}
+
+void rtgui_dc_draw_shaded_rect(struct rtgui_dc* dc, rtgui_rect_t* rect,
+ rtgui_color_t c1, rtgui_color_t c2)
+{
+ RT_ASSERT(dc != RT_NULL);
+
+ rtgui_dc_set_color(dc, c1);
+ rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
+ rtgui_dc_draw_hline(dc, rect->x1 + 1, rect->x2, rect->y1);
+
+ rtgui_dc_set_color(dc, c2);
+ rtgui_dc_draw_vline(dc, rect->x2, rect->y1, rect->y2);
+ rtgui_dc_draw_hline(dc, rect->x1, rect->x2 + 1, rect->y2);
+}
+
+void rtgui_dc_draw_border(struct rtgui_dc* dc, rtgui_rect_t* rect, int flag)
+{
+ rtgui_rect_t r;
+ rtgui_color_t color;
+
+ if (dc == RT_NULL) return ;
+
+ /* save old color */
+ color = rtgui_dc_get_color(dc);
+
+ r = *rect;
+ switch (flag)
+ {
+ case RTGUI_BORDER_RAISE:
+ rtgui_dc_draw_shaded_rect(dc, &r, high_light, black);
+ rtgui_rect_inflate(&r, -1);
+ rtgui_dc_draw_shaded_rect(dc, &r, light_grey, dark_grey);
+ break;
+
+ case RTGUI_BORDER_SUNKEN:
+ rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
+ rtgui_rect_inflate(&r, -1);
+ rtgui_dc_draw_shaded_rect(dc, &r, black, light_grey);
+ break;
+
+ case RTGUI_BORDER_BOX:
+ rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
+ rtgui_rect_inflate(&r, -1);
+ rtgui_dc_draw_shaded_rect(dc, &r, high_light, dark_grey);
+ break;
+
+ case RTGUI_BORDER_STATIC:
+ rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
+ break;
+
+ case RTGUI_BORDER_EXTRA:
+ rtgui_dc_set_color(dc, light_grey);
+ rtgui_dc_draw_rect(dc, &r);
+ break;
+
+ case RTGUI_BORDER_SIMPLE:
+ rtgui_dc_set_color(dc, black);
+ rtgui_dc_draw_rect(dc, &r);
+ break;
+
+ default:
+ break;
+ }
+
+ /* restore color */
+ rtgui_dc_set_color(dc, color);
+}
+
+void rtgui_dc_draw_horizontal_line(struct rtgui_dc* dc, int x1, int x2, int y)
+{
+ rtgui_color_t color;
+
+ if (dc == RT_NULL) return ;
+
+ /* save old color */
+ color = rtgui_dc_get_color(dc);
+
+ rtgui_dc_set_color(dc, dark_grey);
+ rtgui_dc_draw_hline(dc, x1, x2, y);
+
+ y ++;
+
+ rtgui_dc_set_color(dc, high_light);
+ rtgui_dc_draw_hline(dc, x1, x2, y);
+
+ /* restore color */
+ rtgui_dc_set_color(dc, color);
+}
+
+void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2)
+{
+ rtgui_color_t color;
+
+ if (dc == RT_NULL) return ;
+
+ /* save old color */
+ color = rtgui_dc_get_color(dc);
+
+ rtgui_dc_set_color(dc, dark_grey);
+ rtgui_dc_draw_hline(dc, x, y1, y2);
+
+ x ++;
+
+ rtgui_dc_set_color(dc, high_light);
+ rtgui_dc_draw_hline(dc, x, y1, y2);
+
+ /* restore color */
+ rtgui_dc_set_color(dc, color);
+}
+
+void rtgui_dc_draw_arrow(struct rtgui_dc* dc, rtgui_rect_t* rect, int kind)
+{
+ rt_int32_t i;
+ rt_int32_t x1, y1, x2, y2;
+ rtgui_rect_t r = {0, 0, 0, 0};
+
+ static const rt_uint8_t ARROW_WIDTH = 7;
+ static const rt_uint8_t ARROW_LENGTH = 4;
+
+ x1 = y1 = 0;
+
+ switch (kind)
+ {
+ case RTGUI_ARRAW_UP:
+ case RTGUI_ARRAW_DOWN:
+ r.x2 = ARROW_WIDTH;
+ r.y2 = ARROW_LENGTH;
+ break;
+
+ case RTGUI_ARRAW_LEFT:
+ case RTGUI_ARRAW_RIGHT:
+ r.x2 = ARROW_LENGTH;
+ r.y2 = ARROW_WIDTH;
+ break;
+ }
+ rtgui_rect_moveto_align(rect, &r, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
+
+ switch (kind)
+ {
+ case RTGUI_ARRAW_UP:
+ x1 = r.x1 + (ARROW_WIDTH - 1)/2;;
+ y1 = r.y1;
+ break;
+ case RTGUI_ARRAW_DOWN:
+ x1 = r.x1 + (ARROW_WIDTH - 1)/2;
+ y1 = r.y1 + ARROW_LENGTH - 1;
+ break;
+ case RTGUI_ARRAW_LEFT:
+ x1 = r.x1;
+ y1 = r.y1 + (ARROW_WIDTH - 1)/2;
+ break;
+ case RTGUI_ARRAW_RIGHT:
+ x1 = r.x1 + ARROW_LENGTH - 1;
+ y1 = r.y1 + (ARROW_WIDTH - 1)/2;
+ break;
+ default:
+ return;
+ }
+ x2 = x1;
+ y2 = y1;
+
+ for (i = 0; i < ARROW_LENGTH; i++)
+ {
+ rtgui_dc_draw_line(dc, x1, y1, x2, y2);
+
+ switch (kind)
+ {
+ case RTGUI_ARRAW_UP:
+ x1 --;
+ x2 ++;
+ y1 ++;
+ y2 ++;
+ break;
+
+ case RTGUI_ARRAW_DOWN:
+ x1 --;
+ x2 ++;
+ y1 --;
+ y2 --;
+ break;
+
+ case RTGUI_ARRAW_LEFT:
+ y1 --;
+ y2 ++;
+ x1 ++;
+ x2 ++;
+ break;
+
+ case RTGUI_ARRAW_RIGHT:
+ y1 --;
+ y2 ++;
+ x1 --;
+ x2 --;
+ break;
+ }
+ }
+}
+
+void rtgui_dc_draw_polygon(struct rtgui_dc* dc, const int *vx, const int *vy, int count)
+{
+ int i;
+ const int *x1, *y1, *x2, *y2;
+
+ /*
+ * Sanity check
+ */
+ if (count < 3) return;
+
+ /*
+ * Pointer setup
+ */
+ x1 = x2 = vx;
+ y1 = y2 = vy;
+ x2++;
+ y2++;
+
+ /*
+ * Draw
+ */
+ for (i = 1; i < count; i++)
+ {
+ rtgui_dc_draw_line(dc, *x1, *y1, *x2, *y2);
+ x1 = x2;
+ y1 = y2;
+ x2++;
+ y2++;
+ }
+ rtgui_dc_draw_line(dc, *x1, *y1, *vx, *vy);
+}
+
+static int _int_compare(const void *a, const void *b)
+{
+ return (*(const int *) a) - (*(const int *) b);
+}
+
+void rtgui_dc_fill_polygon(struct rtgui_dc* dc, const int* vx, const int* vy, int count)
+{
+ int i;
+ int y, xa, xb;
+ int miny, maxy;
+ int x1, y1;
+ int x2, y2;
+ int ind1, ind2;
+ int ints;
+ int *poly_ints = RT_NULL;
+
+ /*
+ * Sanity check number of edges
+ */
+ if (count < 3) return;
+
+ /*
+ * Allocate temp array, only grow array
+ */
+ poly_ints = (int *) rt_malloc(sizeof(int) * count);
+ if (poly_ints == RT_NULL) return ; /* no memory, failed */
+
+ /*
+ * Determine Y maximal
+ */
+ miny = vy[0];
+ maxy = vy[0];
+ for (i = 1; (i < count); i++)
+ {
+ if (vy[i] < miny) miny = vy[i];
+ else if (vy[i] > maxy) maxy = vy[i];
+ }
+
+ /*
+ * Draw, scanning y
+ */
+ for (y = miny; (y <= maxy); y++) {
+ ints = 0;
+ for (i = 0; (i < count); i++) {
+ if (!i) {
+ ind1 = count - 1;
+ ind2 = 0;
+ } else {
+ ind1 = i - 1;
+ ind2 = i;
+ }
+ y1 = vy[ind1];
+ y2 = vy[ind2];
+ if (y1 < y2) {
+ x1 = vx[ind1];
+ x2 = vx[ind2];
+ } else if (y1 > y2) {
+ y2 = vy[ind1];
+ y1 = vy[ind2];
+ x2 = vx[ind1];
+ x1 = vx[ind2];
+ } else {
+ continue;
+ }
+
+ if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) )
+ {
+ poly_ints[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
+ }
+ }
+
+ qsort(poly_ints, ints, sizeof(int), _int_compare);
+
+ for (i = 0; (i < ints); i += 2)
+ {
+ xa = poly_ints[i] + 1;
+ xa = (xa >> 16) + ((xa & 32768) >> 15);
+ xb = poly_ints[i+1] - 1;
+ xb = (xb >> 16) + ((xb & 32768) >> 15);
+ rtgui_dc_draw_hline(dc, xa, xb, y);
+ }
+ }
+}
+
+void rtgui_dc_draw_circle(struct rtgui_dc* dc, int x, int y, int r)
+{
+ rt_int16_t cx = 0;
+ rt_int16_t cy = r;
+ rt_int16_t df = 1 - r;
+ rt_int16_t d_e = 3;
+ rt_int16_t d_se = -2 * r + 5;
+ rt_int16_t xpcx, xmcx, xpcy, xmcy;
+ rt_int16_t ypcy, ymcy, ypcx, ymcx;
+
+ /*
+ * sanity check radius
+ */
+ if (r < 0) return ;
+
+ /* special case for r=0 - draw a point */
+ if (r == 0) rtgui_dc_draw_point(dc, x, y);
+
+ /*
+ * draw circle
+ */
+ do
+ {
+ ypcy = y + cy;
+ ymcy = y - cy;
+ if (cx > 0)
+ {
+ xpcx = x + cx;
+ xmcx = x - cx;
+ rtgui_dc_draw_point(dc, xmcx, ypcy);
+ rtgui_dc_draw_point(dc, xpcx, ypcy);
+ rtgui_dc_draw_point(dc, xmcx, ymcy);
+ rtgui_dc_draw_point(dc, xpcx, ymcy);
+ }
+ else
+ {
+ rtgui_dc_draw_point(dc, x, ymcy);
+ rtgui_dc_draw_point(dc, x, ypcy);
+ }
+ xpcy = x + cy;
+ xmcy = x - cy;
+ if ((cx > 0) && (cx != cy))
+ {
+ ypcx = y + cx;
+ ymcx = y - cx;
+ rtgui_dc_draw_point(dc, xmcy, ypcx);
+ rtgui_dc_draw_point(dc, xpcy, ypcx);
+ rtgui_dc_draw_point(dc, xmcy, ymcx);
+ rtgui_dc_draw_point(dc, xpcy, ymcx);
+ }
+ else if (cx == 0)
+ {
+ rtgui_dc_draw_point(dc, xmcy, y);
+ rtgui_dc_draw_point(dc, xpcy, y);
+ }
+
+ /*
+ * Update
+ */
+ if (df < 0)
+ {
+ df += d_e;
+ d_e += 2;
+ d_se += 2;
+ }
+ else
+ {
+ df += d_se;
+ d_e += 2;
+ d_se += 4;
+ cy--;
+ }
+ cx++;
+ }while (cx <= cy);
+}
+
+void rtgui_dc_fill_circle(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t r)
+{
+ 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;
+ rt_int16_t xpcx, xmcx, xpcy, xmcy;
+ rt_int16_t ypcy, ymcy, ypcx, ymcx;
+
+ /*
+ * Sanity check radius
+ */
+ if (r < 0) return;
+
+ /*
+ * Special case for r=0 - draw a point
+ */
+ if (r == 0)
+ {
+ rtgui_dc_draw_point(dc, x, y);
+ return ;
+ }
+
+ /*
+ * Draw
+ */
+ do {
+ xpcx = x + cx;
+ xmcx = x - cx;
+ xpcy = x + cy;
+ xmcy = x - cy;
+ if (ocy != cy) {
+ if (cy > 0) {
+ ypcy = y + cy;
+ ymcy = y - cy;
+ rtgui_dc_draw_hline(dc, xmcx, xpcx, ypcy);
+ rtgui_dc_draw_hline(dc, xmcx, xpcx, ymcy);
+ } else {
+ rtgui_dc_draw_hline(dc, xmcx, xpcx, y);
+ }
+ ocy = cy;
+ }
+ if (ocx != cx) {
+ if (cx != cy) {
+ if (cx > 0) {
+ ypcx = y + cx;
+ ymcx = y - cx;
+ rtgui_dc_draw_hline(dc, xmcy, xpcy, ymcx);
+ rtgui_dc_draw_hline(dc, xmcy, xpcy, ypcx);
+ } else {
+ rtgui_dc_draw_hline(dc, xmcy, xpcy, y);
+ }
+ }
+ ocx = cx;
+ }
+ /*
+ * Update
+ */
+ if (df < 0) {
+ df += d_e;
+ d_e += 2;
+ d_se += 2;
+ } else {
+ df += d_se;
+ d_e += 2;
+ d_se += 4;
+ cy--;
+ }
+ cx++;
+ } while (cx <= cy);
+}
+
+void rtgui_dc_draw_ellipse(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry)
+{
+ int ix, iy;
+ int h, i, j, k;
+ int oh, oi, oj, ok;
+ int xmh, xph, ypk, ymk;
+ int xmi, xpi, ymj, ypj;
+ int xmj, xpj, ymi, ypi;
+ int xmk, xpk, ymh, yph;
+
+ /*
+ * Sanity check radii
+ */
+ if ((rx < 0) || (ry < 0)) return;
+
+ /*
+ * Special case for rx=0 - draw a vline
+ */
+ if (rx == 0)
+ {
+ rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
+ return;
+ }
+
+ /*
+ * Special case for ry=0 - draw a hline
+ */
+ if (ry == 0)
+ {
+ rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
+ return;
+ }
+
+ /*
+ * Init vars
+ */
+ oh = oi = oj = ok = 0xFFFF;
+
+ if (rx > ry)
+ {
+ ix = 0;
+ iy = rx * 64;
+
+ do
+ {
+ h = (ix + 32) >> 6;
+ i = (iy + 32) >> 6;
+ j = (h * ry) / rx;
+ k = (i * ry) / rx;
+
+ if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j))
+ {
+ xph = x + h;
+ xmh = x - h;
+ if (k > 0)
+ {
+ ypk = y + k;
+ ymk = y - k;
+ rtgui_dc_draw_point(dc, xmh, ypk);
+ rtgui_dc_draw_point(dc, xph, ypk);
+ rtgui_dc_draw_point(dc, xmh, ymk);
+ rtgui_dc_draw_point(dc, xph, ymk);
+ }
+ else
+ {
+ rtgui_dc_draw_point(dc, xmh, y);
+ rtgui_dc_draw_point(dc, xph, y);
+ }
+ ok = k;
+ xpi = x + i;
+ xmi = x - i;
+ if (j > 0)
+ {
+ ypj = y + j;
+ ymj = y - j;
+ rtgui_dc_draw_point(dc, xmi, ypj);
+ rtgui_dc_draw_point(dc, xpi, ypj);
+ rtgui_dc_draw_point(dc, xmi, ymj);
+ rtgui_dc_draw_point(dc, xpi, ymj);
+ }
+ else
+ {
+ rtgui_dc_draw_point(dc, xmi, y);
+ rtgui_dc_draw_point(dc, xpi, y);
+ }
+ oj = j;
+ }
+
+ ix = ix + iy / rx;
+ iy = iy - ix / rx;
+ } while (i > h);
+ }
+ else
+ {
+ ix = 0;
+ iy = ry * 64;
+
+ do
+ {
+ h = (ix + 32) >> 6;
+ i = (iy + 32) >> 6;
+ j = (h * rx) / ry;
+ k = (i * rx) / ry;
+
+ if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h)))
+ {
+ xmj = x - j;
+ xpj = x + j;
+ if (i > 0)
+ {
+ ypi = y + i;
+ ymi = y - i;
+ rtgui_dc_draw_point(dc, xmj, ypi);
+ rtgui_dc_draw_point(dc, xpj, ypi);
+ rtgui_dc_draw_point(dc, xmj, ymi);
+ rtgui_dc_draw_point(dc, xpj, ymi);
+ }
+ else
+ {
+ rtgui_dc_draw_point(dc, xmj, y);
+ rtgui_dc_draw_point(dc, xpj, y);
+ }
+ oi = i;
+ xmk = x - k;
+ xpk = x + k;
+ if (h > 0)
+ {
+ yph = y + h;
+ ymh = y - h;
+ rtgui_dc_draw_point(dc, xmk, yph);
+ rtgui_dc_draw_point(dc, xpk, yph);
+ rtgui_dc_draw_point(dc, xmk, ymh);
+ rtgui_dc_draw_point(dc, xpk, ymh);
+ }
+ else
+ {
+ rtgui_dc_draw_point(dc, xmk, y);
+ rtgui_dc_draw_point(dc, xpk, y);
+ }
+ oh = h;
+ }
+
+ ix = ix + iy / ry;
+ iy = iy - ix / ry;
+ } while (i > h);
+ }
+}
+
+void rtgui_dc_fill_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry)
+{
+ int ix, iy;
+ int h, i, j, k;
+ int oh, oi, oj, ok;
+ int xmh, xph;
+ int xmi, xpi;
+ int xmj, xpj;
+ int xmk, xpk;
+
+ /*
+ * Special case for rx=0 - draw a vline
+ */
+ if (rx == 0)
+ {
+ rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
+ return;
+ }
+
+ /* special case for ry=0 - draw a hline */
+ if (ry == 0) {
+ rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
+ return;
+ }
+
+ /*
+ * Init vars
+ */
+ oh = oi = oj = ok = 0xFFFF;
+
+ /*
+ * Draw
+ */
+ if (rx > ry) {
+ ix = 0;
+ iy = rx * 64;
+
+ do {
+ h = (ix + 32) >> 6;
+ i = (iy + 32) >> 6;
+ j = (h * ry) / rx;
+ k = (i * ry) / rx;
+
+ if ((ok != k) && (oj != k)) {
+ xph = x + h;
+ xmh = x - h;
+ if (k > 0) {
+ rtgui_dc_draw_hline(dc, xmh, xph, y + k);
+ rtgui_dc_draw_hline(dc, xmh, xph, y - k);
+ } else {
+ rtgui_dc_draw_hline(dc, xmh, xph, y);
+ }
+ ok = k;
+ }
+ if ((oj != j) && (ok != j) && (k != j)) {
+ xmi = x - i;
+ xpi = x + i;
+ if (j > 0) {
+ rtgui_dc_draw_hline(dc, xmi, xpi, y + j);
+ rtgui_dc_draw_hline(dc, xmi, xpi, y - j);
+ } else {
+ rtgui_dc_draw_hline(dc, xmi, xpi, y);
+ }
+ oj = j;
+ }
+
+ ix = ix + iy / rx;
+ iy = iy - ix / rx;
+
+ } while (i > h);
+ } else {
+ ix = 0;
+ iy = ry * 64;
+
+ do {
+ h = (ix + 32) >> 6;
+ i = (iy + 32) >> 6;
+ j = (h * rx) / ry;
+ k = (i * rx) / ry;
+
+ if ((oi != i) && (oh != i)) {
+ xmj = x - j;
+ xpj = x + j;
+ if (i > 0) {
+ rtgui_dc_draw_hline(dc, xmj, xpj, y + i);
+ rtgui_dc_draw_hline(dc, xmj, xpj, y - i);
+ } else {
+ rtgui_dc_draw_hline(dc, xmj, xpj, y);
+ }
+ oi = i;
+ }
+ if ((oh != h) && (oi != h) && (i != h)) {
+ xmk = x - k;
+ xpk = x + k;
+ if (h > 0) {
+ rtgui_dc_draw_hline(dc, xmk, xpk, y + h);
+ rtgui_dc_draw_hline(dc, xmk, xpk, y - h);
+ } else {
+ rtgui_dc_draw_hline(dc, xmk, xpk, y);
+ }
+ oh = h;
+ }
+ ix = ix + iy / ry;
+ iy = iy - ix / ry;
+ } while (i > h);
+ }
+}
+
+void rtgui_dc_draw_focus_rect(struct rtgui_dc* dc, rtgui_rect_t* rect)
+{
+ int i;
+
+ for (i = rect->x1; i <= rect->x2; i += 2)
+ {
+ rtgui_dc_draw_point(dc, i, rect->y1);
+ rtgui_dc_draw_point(dc, i, rect->y2);
+ }
+
+ for (i = rect->y1; i <= rect->y2; i += 2)
+ {
+ rtgui_dc_draw_point(dc, rect->x1, i);
+ rtgui_dc_draw_point(dc, rect->x2, i);
+ }
+}
+
+void rtgui_dc_get_rect(struct rtgui_dc*dc, rtgui_rect_t* rect)
+{
+ if (dc != RT_NULL && rect != RT_NULL)
+ {
+ dc->get_rect(dc, rect);
+ }
+}
diff --git a/rtgui/common/dc_buffer.c b/rtgui/common/dc_buffer.c
new file mode 100644
index 0000000000..a04fcb9c78
--- /dev/null
+++ b/rtgui/common/dc_buffer.c
@@ -0,0 +1,392 @@
+/*
+ * File : dc_buffer.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/rtgui.h>
+#include <rtgui/dc.h>
+#include <rtgui/color.h>
+#include <rtgui/rtgui_system.h>
+
+struct rtgui_dc_buffer
+{
+ struct rtgui_dc parent;
+
+ /* color and font */
+ rtgui_color_t color;
+ struct rtgui_font* font;
+ /* text align */
+ rt_int32_t align;
+
+ /* width and height */
+ rt_uint16_t width, height;
+ rt_uint16_t pitch;
+
+ /* blit info */
+ rt_uint32_t clip_sync;
+ rtgui_region_t clip;
+
+ /* pixel data */
+ rt_uint8_t* pixel;
+};
+
+static rt_bool_t rtgui_dc_buffer_fini(struct rtgui_dc* dc);
+static void rtgui_dc_buffer_draw_point(struct rtgui_dc* dc, int x, int y);
+static void rtgui_dc_buffer_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2);
+static void rtgui_dc_buffer_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y);
+static void rtgui_dc_buffer_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect);
+static void rtgui_dc_buffer_blit(struct rtgui_dc* self, struct rtgui_point* dc_point,
+ struct rtgui_dc* dest, rtgui_rect_t* rect);
+static void rtgui_dc_buffer_set_color (struct rtgui_dc* dc, rtgui_color_t color);
+static rtgui_color_t rtgui_dc_buffer_get_color(struct rtgui_dc* dc);
+static void rtgui_dc_buffer_set_font(struct rtgui_dc* dc, rtgui_font_t* font);
+static rtgui_font_t* rtgui_dc_buffer_get_font(struct rtgui_dc* dc);
+static void rtgui_dc_buffer_set_textalign(struct rtgui_dc* dc, rt_int32_t textalign);
+static rt_int32_t rtgui_dc_buffer_get_textalign(struct rtgui_dc* dc);
+static rt_bool_t rtgui_dc_buffer_get_visible(struct rtgui_dc* dc);
+static void rtgui_dc_buffer_get_rect(struct rtgui_dc* dc, rtgui_rect_t* rect);
+
+static void rtgui_dc_buffer_init(struct rtgui_dc_buffer* dc)
+{
+ if (dc == RT_NULL) return;
+
+ dc->parent.type = RTGUI_DC_BUFFER;
+ dc->parent.draw_point = rtgui_dc_buffer_draw_point;
+ dc->parent.draw_hline = rtgui_dc_buffer_draw_hline;
+ dc->parent.draw_vline = rtgui_dc_buffer_draw_vline;
+ dc->parent.fill_rect = rtgui_dc_buffer_fill_rect;
+ dc->parent.blit = rtgui_dc_buffer_blit;
+
+ dc->parent.set_color = rtgui_dc_buffer_set_color;
+ dc->parent.get_color = rtgui_dc_buffer_get_color;
+
+ dc->parent.set_font = rtgui_dc_buffer_set_font;
+ dc->parent.get_font = rtgui_dc_buffer_get_font;
+ dc->parent.set_textalign = rtgui_dc_buffer_set_textalign;
+ dc->parent.get_textalign = rtgui_dc_buffer_get_textalign;
+
+ dc->parent.get_visible= rtgui_dc_buffer_get_visible;
+ dc->parent.get_rect = rtgui_dc_buffer_get_rect;
+
+ dc->parent.fini = rtgui_dc_buffer_fini;
+}
+
+struct rtgui_dc* rtgui_dc_buffer_create(int w, int h)
+{
+ struct rtgui_dc_buffer* dc;
+
+ dc = (struct rtgui_dc_buffer*)rtgui_malloc(sizeof(struct rtgui_dc_buffer));
+ rtgui_dc_buffer_init(dc);
+ dc->color = 0;
+ dc->font = RT_NULL;
+ dc->align = 0;
+
+ dc->width = w;
+ dc->height = h;
+ dc->pitch = w * sizeof(rtgui_color_t);
+
+ dc->clip_sync = 0;
+ rtgui_region_init(&(dc->clip));
+
+ dc->pixel = rtgui_malloc(h * dc->pitch);
+ rt_memset(dc->pixel, 0, h * dc->pitch);
+
+ return &(dc->parent);
+}
+
+rt_uint8_t* rtgui_dc_buffer_get_pixel(struct rtgui_dc* dc)
+{
+ struct rtgui_dc_buffer* dc_buffer;
+
+ dc_buffer = (struct rtgui_dc_buffer*)dc;
+
+ return dc_buffer->pixel;
+}
+
+static rt_bool_t rtgui_dc_buffer_fini(struct rtgui_dc* dc)
+{
+ struct rtgui_dc_buffer* buffer = (struct rtgui_dc_buffer*)dc;
+
+ if (dc->type != RTGUI_DC_BUFFER) return RT_FALSE;
+
+ rtgui_free(buffer->pixel);
+ buffer->pixel = RT_NULL;
+
+ return RT_TRUE;
+}
+
+static void rtgui_dc_buffer_draw_point(struct rtgui_dc* self, int x, int y)
+{
+ rtgui_color_t* ptr;
+ struct rtgui_dc_buffer* dc;
+
+ dc = (struct rtgui_dc_buffer*)self;
+
+ /* note: there is no parameter check in this function */
+ ptr = (rtgui_color_t*)(dc->pixel + y * dc->pitch + x * sizeof(rtgui_color_t));
+
+ *ptr = dc->color;
+}
+
+static void rtgui_dc_buffer_draw_vline(struct rtgui_dc* self, int x, int y1, int y2)
+{
+ rtgui_color_t* ptr;
+ register rt_base_t index;
+ struct rtgui_dc_buffer* dc;
+
+ dc = (struct rtgui_dc_buffer*)self;
+
+ if (x >= dc->width) return;
+ if (y1 > dc->height) y1 = dc->height;
+ if (y2 > dc->height) y2 = dc->height;
+
+ ptr = (rtgui_color_t*)(dc->pixel + y1 * dc->pitch + x * sizeof(rtgui_color_t));
+ for (index = y1; index < y2; index ++)
+ {
+ /* draw this point */
+ *ptr = dc->color;
+ ptr += dc->width;
+ }
+}
+
+static void rtgui_dc_buffer_draw_hline(struct rtgui_dc* self, int x1, int x2, int y)
+{
+ rtgui_color_t* ptr;
+ register rt_base_t index;
+ struct rtgui_dc_buffer* dc;
+
+ dc = (struct rtgui_dc_buffer*)self;
+ if (y >= dc->height) return;
+ if (x1 > dc->width) x1 = dc->width;
+ if (x2 > dc->width) x2 = dc->width;
+
+ ptr = (rtgui_color_t*)(dc->pixel + y * dc->pitch + x1 * sizeof(rtgui_color_t));
+ for (index = x1; index < x2; index ++)
+ {
+ /* draw this point */
+ *ptr++ = dc->color;
+ }
+}
+
+static void rtgui_dc_buffer_fill_rect (struct rtgui_dc* self, struct rtgui_rect* rect)
+{
+ rtgui_rect_t r;
+ struct rtgui_dc_buffer* dc;
+
+ r = *rect;
+ dc = (struct rtgui_dc_buffer*)self;
+ if (r.x1 > dc->width) r.x1 = dc->width;
+ if (r.x2 > dc->width) r.x2 = dc->width;
+ if (r.y1 > dc->height) r.y1 = dc->height;
+ if (r.y2 > dc->height) r.y2 = dc->height;
+
+ /* fill first line */
+ rtgui_dc_buffer_draw_hline(&(dc->parent), r.x1, r.x2, r.y1);
+
+ /* memory copy other lines */
+ if (r.y2 > r.y1)
+ {
+ register rt_base_t index;
+ for (index = r.y1 + 1; index < r.y2; index ++)
+ {
+ rt_memcpy(dc->pixel + index * dc->pitch,
+ dc->pixel + r.y1 * dc->pitch,
+ (r.x2 - r.x1) * sizeof(rtgui_color_t));
+ }
+ }
+}
+
+/* rtgui_color to RGB323 */
+rt_inline void rtgui_blit_line_1(rtgui_color_t* color, rt_uint8_t* dest, int line)
+{
+ struct _color {rt_uint8_t r, g, b, a;} *c;
+
+ c = (struct _color*)color;
+ while (line-- > 0)
+ {
+ *dest = (c->r & 0xe0) | (c->g & 0xc0) >> 3 | (c->b & 0xe0) >> 5 ;
+
+ c ++;
+ dest ++;
+ }
+}
+
+/* rtgui_color to RGB565 */
+rt_inline void rtgui_blit_line_2(rtgui_color_t* color, rt_uint8_t* dest, int line)
+{
+ struct _color {rt_uint8_t r, g, b, a;} *c;
+ rt_uint16_t* ptr;
+
+ c = (struct _color*)color;
+ ptr = (rt_uint16_t*)dest;
+
+ while (line-- > 0)
+ {
+ *ptr = ((c->r & 0xf8) << 8) | ((c->g & 0xfc) << 3) | (c->b >> 3);
+
+ c ++;
+ ptr ++;
+ }
+}
+
+/* rtgui_color to RGB888 */
+rt_inline void rtgui_blit_line_4(rtgui_color_t* color, rt_uint8_t* dest, int line)
+{
+ rt_memcpy(dest, color, line * 4);
+}
+
+static void rtgui_dc_buffer_blit(struct rtgui_dc* self, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
+{
+ struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
+ struct rtgui_dc_hw* hw = (struct rtgui_dc_hw*)dest;
+
+ if (dest->type == RTGUI_DC_HW)
+ {
+ register int index;
+ int fb_pitch;
+ rtgui_rect_t abs_rect;
+ void (*blit_line)(rtgui_color_t* color, rt_uint8_t* dest, int line);
+
+ abs_rect.x1 = hw->owner->extent.x1 + rect->x1;
+ abs_rect.y1 = hw->owner->extent.y1 + rect->y1;
+ abs_rect.x2 = abs_rect.x1 + rtgui_rect_width(*rect);
+ abs_rect.y2 = abs_rect.y1 + rtgui_rect_height(*rect);
+
+ /* hw fb pitch */
+ fb_pitch = hw->device->byte_per_pixel * hw->device->width;
+
+ /* hardware dc blit */
+ if (!rtgui_region_not_empty(&dc->clip) ||
+ dc->clip_sync != hw->owner->clip_sync)
+ {
+ /* should re-calculate clip */
+ rtgui_region_intersect_rect(&(dc->clip),
+ &(hw->owner->clip), &abs_rect);
+ }
+
+ switch (hw->device->byte_per_pixel)
+ {
+ case 1:
+ blit_line = rtgui_blit_line_1;
+ break;
+ case 2:
+ blit_line = rtgui_blit_line_2;
+ break;
+ case 3:
+ blit_line = rtgui_blit_line_4;
+ break;
+
+ default:
+ /* can not blit */
+ return;
+ }
+
+ /* blit each clip rect */
+ if (dc->clip.data == RT_NULL)
+ {
+ int y;
+ rtgui_color_t* pixel;
+ rt_uint8_t* fb;
+
+ pixel = (rtgui_color_t*)(dc->pixel + (dc_point->y + dc->clip.extents.y1 - abs_rect.y1) * dc->pitch +
+ (dc_point->x + dc->clip.extents.x1 - abs_rect.x1) * sizeof(rtgui_color_t));
+ fb = hw->device->get_framebuffer() + dc->clip.extents.y1 * fb_pitch +
+ dc->clip.extents.x1 * hw->device->byte_per_pixel;
+
+ for (y = dc->clip.extents.y1; y < dc->clip.extents.y2; y ++)
+ {
+ blit_line(pixel, fb, dc->clip.extents.x2 - dc->clip.extents.x1);
+
+ fb += fb_pitch;
+ pixel += dc->width;
+ }
+ }
+ else for (index = 0; index < rtgui_region_num_rects(&(dc->clip)); index ++)
+ {
+ int y;
+ rtgui_rect_t* prect;
+ rtgui_color_t* pixel;
+ rt_uint8_t* fb;
+
+ prect = ((rtgui_rect_t *)(dc->clip.data + index + 1));
+
+ pixel = (rtgui_color_t*)(dc->pixel + (dc_point->y + prect->y1 - abs_rect.y1) * dc->pitch +
+ (dc_point->x + prect->x1 - abs_rect.x1) * sizeof(rtgui_color_t));
+ fb = hw->device->get_framebuffer() + prect->y1 * fb_pitch +
+ prect->x1 * hw->device->byte_per_pixel;
+
+ for (y = prect->y1; y < prect->y2; y ++)
+ {
+ blit_line(pixel, fb, prect->x2 - prect->x1);
+
+ fb += fb_pitch;
+ pixel += dc->width;
+ }
+ }
+ }
+}
+
+static void rtgui_dc_buffer_set_color (struct rtgui_dc* self, rtgui_color_t color)
+{
+ struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
+
+ dc->color = color;
+}
+
+static rtgui_color_t rtgui_dc_buffer_get_color(struct rtgui_dc* self)
+{
+ struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
+
+ return dc->color;
+}
+
+static void rtgui_dc_buffer_set_font(struct rtgui_dc* self, rtgui_font_t* font)
+{
+ struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
+
+ dc->font = font;
+}
+
+static rtgui_font_t* rtgui_dc_buffer_get_font(struct rtgui_dc* self)
+{
+ struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
+
+ return dc->font;
+}
+
+static void rtgui_dc_buffer_set_textalign(struct rtgui_dc* self, rt_int32_t textalign)
+{
+ struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
+
+ dc->align = textalign;
+}
+
+static rt_int32_t rtgui_dc_buffer_get_textalign(struct rtgui_dc* self)
+{
+ struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
+
+ return dc->align;
+}
+
+static rt_bool_t rtgui_dc_buffer_get_visible(struct rtgui_dc* dc)
+{
+ return RT_TRUE;
+}
+
+static void rtgui_dc_buffer_get_rect(struct rtgui_dc* self, rtgui_rect_t* rect)
+{
+ struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
+
+ rect->x1 = rect->y1 = 0;
+
+ rect->x2 = dc->width;
+ rect->y2 = dc->height;
+}
diff --git a/rtgui/common/dc_hw.c b/rtgui/common/dc_hw.c
new file mode 100644
index 0000000000..b5d8be3b6a
--- /dev/null
+++ b/rtgui/common/dc_hw.c
@@ -0,0 +1,436 @@
+/*
+ * File : dc_hw.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/driver.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/widgets/view.h>
+#include <rtgui/widgets/window.h>
+#include <rtgui/widgets/workbench.h>
+#include <rtgui/widgets/title.h>
+
+static void rtgui_dc_hw_draw_point(struct rtgui_dc* dc, int x, int y);
+static void rtgui_dc_hw_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y);
+static void rtgui_dc_hw_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2);
+static void rtgui_dc_hw_fill_rect (struct rtgui_dc* dc, rtgui_rect_t* rect);
+static void rtgui_dc_hw_blit (struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect);
+static void rtgui_dc_hw_set_color (struct rtgui_dc* dc, rtgui_color_t color);
+static rtgui_color_t rtgui_dc_hw_get_color (struct rtgui_dc* dc);
+static void rtgui_dc_hw_set_font(struct rtgui_dc* dc, rtgui_font_t* font);
+static rtgui_font_t* rtgui_dc_hw_get_font(struct rtgui_dc* dc);
+static void rtgui_dc_hw_set_textalign(struct rtgui_dc* dc, rt_int32_t textalign);
+static rt_int32_t rtgui_dc_hw_get_textalign(struct rtgui_dc* dc);
+static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc* dc);
+static rt_bool_t rtgui_dc_hw_get_visible(struct rtgui_dc* dc);
+static void rtgui_dc_hw_get_rect(struct rtgui_dc* dc, rtgui_rect_t* rect);
+
+struct rtgui_dc* rtgui_dc_begin_drawing(rtgui_widget_t* owner)
+{
+ return rtgui_dc_hw_create(owner);
+}
+
+void rtgui_dc_end_drawing(struct rtgui_dc* dc)
+{
+ if (rtgui_dc_hw_fini(dc) == RT_TRUE)
+ {
+ rtgui_free(dc);
+ }
+}
+
+void rtgui_dc_hw_init(struct rtgui_dc_hw* dc)
+{
+ if (dc == RT_NULL) return;
+
+ dc->parent.type = RTGUI_DC_HW;
+ dc->parent.draw_point = rtgui_dc_hw_draw_point;
+ dc->parent.draw_hline = rtgui_dc_hw_draw_hline;
+ dc->parent.draw_vline = rtgui_dc_hw_draw_vline;
+ dc->parent.fill_rect = rtgui_dc_hw_fill_rect ;
+ dc->parent.blit = rtgui_dc_hw_blit;
+
+ dc->parent.set_color = rtgui_dc_hw_set_color;
+ dc->parent.get_color = rtgui_dc_hw_get_color;
+
+ dc->parent.set_font = rtgui_dc_hw_set_font;
+ dc->parent.get_font = rtgui_dc_hw_get_font;
+ dc->parent.set_textalign = rtgui_dc_hw_set_textalign;
+ dc->parent.get_textalign = rtgui_dc_hw_get_textalign;
+
+ dc->parent.get_visible= rtgui_dc_hw_get_visible;
+ dc->parent.get_rect = rtgui_dc_hw_get_rect;
+
+ dc->parent.fini = rtgui_dc_hw_fini;
+}
+
+extern struct rt_mutex cursor_mutex;
+#define dc_set_foreground(c) dc->owner->gc.foreground = c
+#define dc_set_background(c) dc->owner->gc.background = c
+extern void rtgui_mouse_show_cursor(void);
+extern void rtgui_mouse_hide_cursor(void);
+struct rtgui_dc* rtgui_dc_hw_create(rtgui_widget_t* owner)
+{
+ struct rtgui_dc_hw* dc;
+ rtgui_widget_t* widget;
+
+ /* adjudge owner */
+ if (owner == RT_NULL || owner->toplevel == RT_NULL) return RT_NULL;
+ if (!RTGUI_IS_TOPLEVEL(owner->toplevel)) return RT_NULL;
+
+ /* malloc a dc object */
+ dc = (struct rtgui_dc_hw*) rtgui_malloc(sizeof(struct rtgui_dc_hw));
+ rtgui_dc_hw_init(dc);
+ dc->owner = owner;
+ dc->visible = RT_TRUE;
+ dc->device = rtgui_graphic_driver_get_default();
+
+ /* set visible */
+ widget = owner;
+ while (widget != RT_NULL)
+ {
+ if (RTGUI_WIDGET_IS_HIDE(widget))
+ {
+ dc->visible = RT_FALSE;
+ break;
+ }
+
+ widget = widget->parent;
+ }
+
+ if (RTGUI_IS_WINTITLE(dc->owner->toplevel))
+ {
+ rtgui_toplevel_t* top = RTGUI_TOPLEVEL(dc->owner->toplevel);
+ top->drawing ++;
+
+ if (top->drawing == 1)
+ {
+#ifdef RTGUI_USING_MOUSE_CURSOR
+#ifdef __WIN32__
+ rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
+ rt_kprintf("hide cursor\n");
+ rtgui_mouse_hide_cursor();
+#else
+ /* hide cursor */
+ rtgui_mouse_hide_cursor();
+#endif
+#endif
+ }
+ }
+ else if (RTGUI_IS_WORKBENCH(dc->owner->toplevel) ||
+ RTGUI_IS_WIN(dc->owner->toplevel))
+ {
+ rtgui_toplevel_t* top = RTGUI_TOPLEVEL(dc->owner->toplevel);
+ top->drawing ++;
+
+ if (top->drawing == 1)
+ {
+#ifdef __WIN32__
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
+ rt_kprintf("hide cursor\n");
+ rtgui_mouse_hide_cursor();
+#endif
+#else
+ /* send draw begin to server */
+ struct rtgui_event_update_begin eupdate;
+ RTGUI_EVENT_UPDATE_BEGIN_INIT(&(eupdate));
+ eupdate.rect = RTGUI_WIDGET(top)->extent;
+
+ rtgui_thread_send(top->server, (struct rtgui_event*)&eupdate, sizeof(eupdate));
+#endif
+ }
+ }
+
+ return &(dc->parent);
+}
+
+static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc* dc)
+{
+ struct rtgui_dc_hw* hw = (struct rtgui_dc_hw*)dc;
+ if (dc == RT_NULL || hw->parent.type != RTGUI_DC_HW) return RT_FALSE;
+
+ if (RTGUI_IS_WINTITLE(hw->owner->toplevel))
+ {
+ /* update title extent */
+ rtgui_toplevel_t* top = RTGUI_TOPLEVEL(hw->owner->toplevel);
+
+ top->drawing --;
+ if (top->drawing == 0)
+ {
+#ifdef __WIN32__
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ rt_mutex_release(&cursor_mutex);
+ /* show cursor */
+ rtgui_mouse_show_cursor();
+ rt_kprintf("show cursor\n");
+#endif
+ /* update screen */
+ hw->device->screen_update(&(hw->owner->extent));
+#else
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ /* show cursor */
+ rtgui_mouse_show_cursor();
+#endif
+
+ /* update screen */
+ hw->device->screen_update(&(hw->owner->extent));
+#endif
+ }
+ }
+ else if (RTGUI_IS_WORKBENCH(hw->owner->toplevel) ||
+ RTGUI_IS_WIN(hw->owner->toplevel))
+ {
+ rtgui_toplevel_t* top = RTGUI_TOPLEVEL(hw->owner->toplevel);
+ top->drawing --;
+
+ if (top->drawing == 0)
+ {
+#ifdef __WIN32__
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ rt_mutex_release(&cursor_mutex);
+ /* show cursor */
+ rtgui_mouse_show_cursor();
+ rt_kprintf("show cursor\n");
+#endif
+ /* update screen */
+ hw->device->screen_update(&(hw->owner->extent));
+#else
+ /* send to server to end drawing */
+ struct rtgui_event_update_end eupdate;
+ RTGUI_EVENT_UPDATE_END_INIT(&(eupdate));
+ eupdate.rect = RTGUI_WIDGET(top)->extent;
+
+ rtgui_thread_send(top->server, (struct rtgui_event*)&eupdate, sizeof(eupdate));
+#endif
+ }
+ }
+
+
+ return RT_TRUE;
+}
+
+/*
+ * draw a logic point on device
+ */
+static void rtgui_dc_hw_draw_point(struct rtgui_dc* self, int x, int y)
+{
+ struct rtgui_dc_hw* dc;
+ rtgui_rect_t rect;
+
+ dc = (struct rtgui_dc_hw*)self;
+ if (dc == RT_NULL || dc->visible != RT_TRUE) return;
+
+ x = x + dc->owner->extent.x1;
+ y = y + dc->owner->extent.y1;
+
+ if (rtgui_region_contains_point(&(dc->owner->clip), x, y, &rect) == RT_EOK)
+ {
+ /* draw this point */
+ dc->device->set_pixel(&(dc->owner->gc.foreground), x, y);
+ }
+}
+
+/*
+ * draw a logic vertical line on device
+ */
+static void rtgui_dc_hw_draw_vline(struct rtgui_dc* self, int x, int y1, int y2)
+{
+ register rt_base_t index;
+ struct rtgui_dc_hw* dc;
+
+ dc = (struct rtgui_dc_hw*)self;
+ if (dc == RT_NULL || dc->visible != RT_TRUE) return;
+
+ x = x + dc->owner->extent.x1;
+ y1 = y1 + dc->owner->extent.y1;
+ y2 = y2 + dc->owner->extent.y1;
+
+ if (dc->owner->clip.data == RT_NULL)
+ {
+ rtgui_rect_t* prect;
+
+ prect = &(dc->owner->clip.extents);
+
+ /* calculate vline intersect */
+ if (prect->x1 > x || prect->x2 <= x) return;
+ if (prect->y2 <= y1 || prect->y1 > y2) return;
+
+ if (prect->y1 > y1) y1 = prect->y1;
+ if (prect->y2 < y2) y2 = prect->y2;
+
+ /* draw vline */
+ dc->device->draw_vline(&(dc->owner->gc.foreground), x, y1, y2);
+ }
+ else for (index = 0; index < rtgui_region_num_rects(&(dc->owner->clip)); index ++)
+ {
+ rtgui_rect_t* prect;
+ register rt_base_t draw_y1, draw_y2;
+
+ prect = ((rtgui_rect_t *)(dc->owner->clip.data + index + 1));
+ draw_y1 = y1;
+ draw_y2 = y2;
+
+ /* calculate vline clip */
+ if (prect->x1 > x || prect->x2 <= x) continue;
+ if (prect->y2 <= y1 || prect->y1 > y2) continue;
+
+ if (prect->y1 > y1) draw_y1 = prect->y1;
+ if (prect->y2 < y2) draw_y2 = prect->y2;
+
+ /* draw vline */
+ dc->device->draw_vline(&(dc->owner->gc.foreground), x, draw_y1, draw_y2);
+ }
+}
+
+/*
+ * draw a logic horizontal line on device
+ */
+static void rtgui_dc_hw_draw_hline(struct rtgui_dc* self, int x1, int x2, int y)
+{
+ register rt_base_t index;
+ struct rtgui_dc_hw* dc;
+
+ dc = (struct rtgui_dc_hw*)self;
+ if (dc == RT_NULL || dc->visible != RT_TRUE) return;
+
+ /* convert logic to device */
+ x1 = x1 + dc->owner->extent.x1;
+ x2 = x2 + dc->owner->extent.x1;
+ y = y + dc->owner->extent.y1;
+
+ if (dc->owner->clip.data == RT_NULL)
+ {
+ rtgui_rect_t* prect;
+
+ prect = &(dc->owner->clip.extents);
+
+ /* calculate vline intersect */
+ if (prect->y1 > y || prect->y2 <= y ) return;
+ if (prect->x2 <= x1 || prect->x1 > x2) return;
+
+ if (prect->x1 > x1) x1 = prect->x1;
+ if (prect->x2 < x2) x2 = prect->x2;
+
+ /* draw hline */
+ dc->device->draw_hline(&(dc->owner->gc.foreground), x1, x2, y);
+ }
+ else for (index = 0; index < rtgui_region_num_rects(&(dc->owner->clip)); index ++)
+ {
+ rtgui_rect_t* prect;
+ register rt_base_t draw_x1, draw_x2;
+
+ prect = ((rtgui_rect_t *)(dc->owner->clip.data + index + 1));
+ draw_x1 = x1;
+ draw_x2 = x2;
+
+ /* calculate hline clip */
+ if (prect->y1 > y || prect->y2 <= y ) continue;
+ if (prect->x2 <= x1 || prect->x1 > x2) continue;
+
+ if (prect->x1 > x1) draw_x1 = prect->x1;
+ if (prect->x2 < x2) draw_x2 = prect->x2;
+
+ /* draw hline */
+ dc->device->draw_hline(&(dc->owner->gc.foreground), draw_x1, draw_x2, y);
+ }
+}
+
+static void rtgui_dc_hw_fill_rect (struct rtgui_dc* self, struct rtgui_rect* rect)
+{
+ rtgui_color_t foreground;
+ register rt_base_t index;
+ struct rtgui_dc_hw* dc;
+
+ dc = (struct rtgui_dc_hw*)self;
+ if (dc == RT_NULL || dc->visible != RT_TRUE) return;
+
+ /* save foreground color */
+ foreground = dc->owner->gc.foreground;
+
+ /* set background color as foreground color */
+ dc->owner->gc.foreground = dc->owner->gc.background;
+
+ /* fill rect */
+ for (index = rect->y1; index < rect->y2; index ++)
+ {
+ rtgui_dc_hw_draw_hline(self, rect->x1, rect->x2, index);
+ }
+
+ /* restore foreground color */
+ dc->owner->gc.foreground = foreground;
+}
+
+static void rtgui_dc_hw_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
+{
+ /* not blit in hardware dc */
+ return ;
+}
+
+static void rtgui_dc_hw_set_color(struct rtgui_dc* self, rtgui_color_t color)
+{
+ struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
+
+ if (self != RT_NULL)
+ {
+ dc->owner->gc.foreground = color;
+ }
+}
+
+static rtgui_color_t rtgui_dc_hw_get_color(struct rtgui_dc* self)
+{
+ struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
+
+ return self != RT_NULL? dc->owner->gc.foreground : white;
+}
+
+static void rtgui_dc_hw_set_font(struct rtgui_dc* self, rtgui_font_t* font)
+{
+ struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
+
+ if (self != RT_NULL)
+ {
+ dc->owner->gc.font = font;
+ }
+}
+
+static rtgui_font_t* rtgui_dc_hw_get_font(struct rtgui_dc* self)
+{
+ struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
+
+ return self != RT_NULL? dc->owner->gc.font : RT_NULL;
+}
+
+static void rtgui_dc_hw_set_textalign(struct rtgui_dc* self, rt_int32_t textalign)
+{
+ struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
+
+ dc->owner->gc.textalign = textalign;
+}
+
+static rt_int32_t rtgui_dc_hw_get_textalign(struct rtgui_dc* self)
+{
+ struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
+
+ return dc->owner->gc.textalign;
+}
+
+static rt_bool_t rtgui_dc_hw_get_visible(struct rtgui_dc* dc)
+{
+ return RT_TRUE;
+}
+
+static void rtgui_dc_hw_get_rect(struct rtgui_dc* self, rtgui_rect_t* rect)
+{
+ struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
+
+ rtgui_widget_get_rect(dc->owner, rect);
+}
diff --git a/rtgui/common/filerw.c b/rtgui/common/filerw.c
new file mode 100644
index 0000000000..7f390d3f1d
--- /dev/null
+++ b/rtgui/common/filerw.c
@@ -0,0 +1,329 @@
+/*
+ * File : filerw.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+
+#include <rtgui/filerw.h>
+#include <rtgui/rtgui_system.h>
+
+#ifdef RT_USING_STDIO_FILERW
+#include <stdio.h>
+
+/* standard file read/write */
+struct rtgui_filerw_stdio
+{
+ /* inherit from rtgui_filerw */
+ struct rtgui_filerw parent;
+
+ FILE* fp;
+};
+
+static int stdio_seek(struct rtgui_filerw *context, rt_off_t offset, int whence)
+{
+ struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
+ int stdio_whence[3] = {SEEK_SET, SEEK_CUR, SEEK_END};
+
+ if (whence < RTGUI_FILE_SEEK_SET || whence > RTGUI_FILE_SEEK_END)
+ {
+ return -1;
+ }
+
+ if (fseek(stdio_filerw->fp, offset, stdio_whence[whence]) == 0)
+ {
+ return ftell(stdio_filerw->fp);
+ }
+
+ return -1;
+}
+
+static int stdio_read(struct rtgui_filerw *context, void *ptr, rt_size_t size, rt_size_t maxnum)
+{
+ size_t nread;
+ struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
+
+ nread = fread(ptr, size, maxnum, stdio_filerw->fp);
+ if (nread == 0 && ferror(stdio_filerw->fp))
+ {
+ return -1;
+ }
+
+ return nread;
+}
+
+static int stdio_write(struct rtgui_filerw *context, const void *ptr, rt_size_t size, rt_size_t num)
+{
+ size_t nwrote;
+ struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
+
+ nwrote = fwrite(ptr, size, num, stdio_filerw->fp);
+
+ if ( nwrote == 0 && ferror(stdio_filerw->fp) )
+ {
+ return -1;
+ }
+
+ return nwrote;
+}
+
+int stdio_tell(struct rtgui_filerw* context)
+{
+ struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
+
+ return ftell(stdio_filerw->fp);
+}
+
+int stdio_eof(struct rtgui_filerw* context)
+{
+ struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
+
+ return feof(stdio_filerw->fp);
+}
+
+static int stdio_close(struct rtgui_filerw *context)
+{
+ struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
+
+ if (stdio_filerw)
+ {
+ fclose(stdio_filerw->fp);
+ rtgui_free(stdio_filerw);
+
+ return 0;
+ }
+
+ return -1;
+}
+#endif
+
+/* memory file read/write */
+struct rtgui_filerw_mem
+{
+ /* inherit from rtgui_filerw */
+ struct rtgui_filerw parent;
+
+ rt_uint8_t *mem_base, *mem_position, *mem_end;
+};
+
+static int mem_seek(struct rtgui_filerw *context, rt_off_t offset, int whence)
+{
+ rt_uint8_t* newpos;
+ struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
+
+ RT_ASSERT(mem != RT_NULL);
+
+ switch (whence) {
+ case RTGUI_FILE_SEEK_SET:
+ newpos = mem->mem_base + offset;
+ break;
+
+ case RTGUI_FILE_SEEK_CUR:
+ newpos = mem->mem_position + offset;
+ break;
+
+ case RTGUI_FILE_SEEK_END:
+ newpos = mem->mem_end + offset;
+ break;
+
+ default:
+ return -1;
+ }
+
+ if ( newpos < mem->mem_base )
+ newpos = mem->mem_base;
+
+ if ( newpos > mem->mem_end )
+ newpos = mem->mem_end;
+
+ mem->mem_position = newpos;
+ return mem->mem_position- mem->mem_base;
+}
+
+static int mem_read(struct rtgui_filerw *context, void *ptr, rt_size_t size, rt_size_t maxnum)
+{
+ int total_bytes;
+ int mem_available;
+ struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
+
+ total_bytes = (maxnum * size);
+ if ( (maxnum <= 0) || (size <= 0) || ((total_bytes / maxnum) != size) )
+ {
+ return -1;
+ }
+
+ mem_available = mem->mem_end - mem->mem_position;
+ if (total_bytes > mem_available)
+ total_bytes = mem_available;
+
+ rt_memcpy(ptr, mem->mem_position, total_bytes);
+ mem->mem_position += total_bytes;
+
+ return (total_bytes / size);
+}
+
+static int mem_write(struct rtgui_filerw *context, const void *ptr, rt_size_t size, rt_size_t num)
+{
+ struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
+
+ if ((mem->mem_position + (num * size)) > mem->mem_end)
+ {
+ num = (mem->mem_end - mem->mem_position)/size;
+ }
+
+ rt_memcpy(mem->mem_position, ptr, num*size);
+ mem->mem_position += num*size;
+
+ return num;
+}
+
+static int mem_tell(struct rtgui_filerw* context)
+{
+ struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
+
+ return mem->mem_position - mem->mem_base;
+}
+
+static int mem_eof(struct rtgui_filerw* context)
+{
+ struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
+
+ return mem->mem_position >= mem->mem_end;
+}
+
+static int mem_close(struct rtgui_filerw *context)
+{
+ struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
+
+ if (mem != RT_NULL)
+ {
+ rtgui_free(mem);
+ return 0;
+ }
+
+ return -1;
+}
+
+rt_uint8_t* rtgui_filerw_mem_getdata(struct rtgui_filerw* context)
+{
+ struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
+
+ /* check whether it's a memory filerw */
+ if (mem->parent.read != mem_read) return RT_NULL;
+
+ return mem->mem_base;
+}
+
+/* file read/write public interface */
+#ifdef RT_USING_STDIO_FILERW
+struct rtgui_filerw* rtgui_filerw_create_file(const char* filename, const char* mode)
+{
+ FILE *fp;
+ struct rtgui_filerw_stdio *rw;
+
+ RT_ASSERT(filename != RT_NULL);
+
+ rw = RT_NULL;
+ fp = fopen(filename, mode);
+
+ if ( fp != NULL )
+ {
+ rw = (struct rtgui_filerw_stdio*) rtgui_malloc(sizeof(struct rtgui_filerw_stdio));
+ if (rw != RT_NULL)
+ {
+ rw->parent.seek = stdio_seek;
+ rw->parent.read = stdio_read;
+ rw->parent.write = stdio_write;
+ rw->parent.tell = stdio_tell;
+ rw->parent.close = stdio_close;
+ rw->parent.eof = stdio_eof;
+
+ rw->fp = fp;
+ }
+ }
+
+ return &(rw->parent);
+}
+#endif
+
+struct rtgui_filerw* rtgui_filerw_create_mem(rt_uint8_t* mem, rt_size_t size)
+{
+ struct rtgui_filerw_mem* rw;
+ RT_ASSERT(mem != RT_NULL);
+
+ rw = (struct rtgui_filerw_mem*) rtgui_malloc(sizeof(struct rtgui_filerw_mem));
+ if (rw != RT_NULL)
+ {
+ rw->parent.seek = mem_seek;
+ rw->parent.read = mem_read;
+ rw->parent.write = mem_write;
+ rw->parent.tell = mem_tell;
+ rw->parent.eof = mem_eof;
+ rw->parent.close = mem_close;
+
+ rw->mem_base = mem;
+ rw->mem_position = mem;
+ rw->mem_end = mem + size;
+ }
+
+ return &(rw->parent);
+}
+
+int rtgui_filerw_seek(struct rtgui_filerw* context, rt_off_t offset, int whence)
+{
+ RT_ASSERT(context != RT_NULL);
+
+ return context->seek(context, offset, whence);
+}
+
+int rtgui_filerw_read(struct rtgui_filerw* context, void* buffer, rt_size_t size, rt_size_t count)
+{
+ RT_ASSERT(context != RT_NULL);
+
+ return context->read(context, buffer, size, count);
+}
+
+int rtgui_filerw_write(struct rtgui_filerw* context, const void* buffer, rt_size_t size, rt_size_t count)
+{
+ RT_ASSERT(context != RT_NULL);
+
+ return context->write(context, buffer, size, count);
+}
+
+int rtgui_filerw_eof (struct rtgui_filerw* context)
+{
+ RT_ASSERT(context != RT_NULL);
+
+ return context->eof(context);
+}
+
+int rtgui_filerw_tell(struct rtgui_filerw* context)
+{
+ RT_ASSERT(context != RT_NULL);
+
+ return context->tell(context);
+}
+
+int rtgui_filerw_close(struct rtgui_filerw* context)
+{
+ int result;
+
+ RT_ASSERT(context != RT_NULL);
+
+ /* close context */
+ result = context->close(context);
+ if (result != 0)
+ {
+ /* close file failed */
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/rtgui/common/font.c b/rtgui/common/font.c
new file mode 100644
index 0000000000..65a64705cc
--- /dev/null
+++ b/rtgui/common/font.c
@@ -0,0 +1,205 @@
+/*
+ * File : font.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/font.h>
+#include <rtgui/dc.h>
+
+static rtgui_list_t _rtgui_font_list;
+static struct rtgui_font* rtgui_default_font;
+
+extern struct rtgui_font rtgui_font_asc16;
+extern struct rtgui_font rtgui_font_asc12;
+#ifdef RTGUI_USING_FONTHZ
+extern struct rtgui_font rtgui_font_hz16;
+extern struct rtgui_font rtgui_font_hz12;
+#endif
+
+void rtgui_font_system_init()
+{
+ rtgui_list_init(&(_rtgui_font_list));
+
+ /* set default font to NULL */
+ rtgui_default_font = RT_NULL;
+
+#ifdef RTGUI_USING_FONT16
+ rtgui_font_system_add_font(&rtgui_font_asc16);
+#ifdef RTGUI_USING_FONTHZ
+ rtgui_font_system_add_font(&rtgui_font_hz16);
+#endif
+#endif
+ rtgui_font_system_add_font(&rtgui_font_asc12);
+#ifdef RTGUI_USING_FONTHZ
+ rtgui_font_system_add_font(&rtgui_font_hz12);
+#endif
+
+ rtgui_font_set_defaut(&rtgui_font_asc12);
+}
+
+void rtgui_font_system_add_font(struct rtgui_font* font)
+{
+ rtgui_list_init(&(font->list));
+ rtgui_list_append(&_rtgui_font_list, &(font->list));
+}
+
+void rtgui_font_system_remove_font(struct rtgui_font* font)
+{
+ rtgui_list_remove(&_rtgui_font_list, &(font->list));
+}
+
+struct rtgui_font* rtgui_font_default()
+{
+ return rtgui_default_font;
+}
+
+void rtgui_font_set_defaut(struct rtgui_font* font)
+{
+ rtgui_default_font = font;
+}
+
+struct rtgui_font* rtgui_font_refer(const rt_uint8_t* family, rt_uint16_t height)
+{
+ /* search font */
+ struct rtgui_list_node* node;
+ struct rtgui_font* font;
+
+ rtgui_list_foreach(node, &_rtgui_font_list)
+ {
+ font = rtgui_list_entry(node, struct rtgui_font, list);
+ if ((rt_strncmp((const char*)font->family, (const char*)family, RTGUI_NAME_MAX) == 0) &&
+ font->height == height)
+ {
+ font->refer_count ++;
+ return font;
+ }
+ }
+
+ return RT_NULL;
+}
+
+void rtgui_font_derefer(struct rtgui_font* font)
+{
+ RT_ASSERT(font != RT_NULL);
+
+ font->refer_count --;
+
+ /* no refer, remove font */
+ if (font->refer_count == 0)
+ {
+ rtgui_font_system_remove_font(font);
+ }
+}
+
+/* draw a text */
+void rtgui_font_draw(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect)
+{
+ RT_ASSERT(font != RT_NULL);
+
+ if (font->engine != RT_NULL &&
+ font->engine->font_draw_text != RT_NULL)
+ {
+ font->engine->font_draw_text(font, dc, text, len, rect);
+ }
+}
+
+int rtgui_font_get_string_width(struct rtgui_font* font, const rt_uint8_t* text)
+{
+ rtgui_rect_t rect;
+
+ /* get metrics */
+ rtgui_font_get_metrics(font, text, &rect);
+
+ return rect.x2 - rect.x1;
+}
+
+void rtgui_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, rtgui_rect_t* rect)
+{
+ RT_ASSERT(font != RT_NULL);
+
+ if (font->engine != RT_NULL &&
+ font->engine->font_get_metrics != RT_NULL)
+ {
+ font->engine->font_get_metrics(font, text, rect);
+ }
+ else
+ {
+ /* no font engine found, set rect to zero */
+ rt_memset(rect, 0, sizeof(rtgui_rect_t));
+ }
+}
+
+static void rtgui_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect);
+static void rtgui_bitmap_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, rtgui_rect_t* rect);
+struct rtgui_font_engine bmp_font_engine =
+{
+ RT_NULL,
+ RT_NULL,
+ rtgui_bitmap_font_draw_text,
+ rtgui_bitmap_font_get_metrics
+};
+
+void rtgui_bitmap_font_draw_char(struct rtgui_font_bitmap* font, struct rtgui_dc* dc, const char ch,
+ rtgui_rect_t* rect)
+{
+ const rt_uint8_t* font_ptr = font->bmp + ch * font->height;
+ rt_uint16_t x, y, w, h;
+ register rt_base_t i, j;
+
+ x = rect->x1;
+ y = rect->y1;
+
+ /* check first and last char */
+ if (ch < font->first_char || ch > font->last_char) return;
+
+ w = (font->width + x > rect->x2)? rect->x2 - rect->x1 : font->width;
+ h = (font->height + y > rect->y2)? rect->y2 - rect->y1 : font->height;
+
+ for (i = 0; i < h; i ++ )
+ {
+ for (j = 0; j < w; j ++)
+ {
+ if ( ((font_ptr[i] >> (7-j)) & 0x01) != 0)
+ {
+ /* draw a pixel */
+ rtgui_dc_draw_point(dc, j + x, i + y);
+ }
+ }
+ }
+}
+
+static void rtgui_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect)
+{
+ struct rtgui_font_bitmap* bmp_font = (struct rtgui_font_bitmap*)(font->data);
+
+ RT_ASSERT(bmp_font != RT_NULL);
+
+ while (len-- && rect->x1 < rect->x2)
+ {
+ rtgui_bitmap_font_draw_char(bmp_font, dc, *text, rect);
+
+ /* move x to next character */
+ rect->x1 += bmp_font->width;
+ text ++;
+ }
+}
+
+static void rtgui_bitmap_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, rtgui_rect_t* rect)
+{
+ struct rtgui_font_bitmap* bmp_font = (struct rtgui_font_bitmap*)(font->data);
+
+ RT_ASSERT(bmp_font != RT_NULL);
+
+ /* set metrics rect */
+ rect->x1 = rect->y1 = 0;
+ rect->x2 = bmp_font->width * (rt_int16_t)rt_strlen((const char*)text);
+ rect->y2 = bmp_font->height;
+}
diff --git a/rtgui/common/image.c b/rtgui/common/image.c
new file mode 100644
index 0000000000..5fd386049e
--- /dev/null
+++ b/rtgui/common/image.c
@@ -0,0 +1,192 @@
+/*
+ * File : image.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtthread.h>
+#include <rtgui/image.h>
+
+#include <rtgui/image_xpm.h>
+#include <rtgui/rtgui_system.h>
+
+#include <string.h>
+
+#ifdef RTGUI_IMAGE_BMP
+#include <rtgui/image_bmp.h>
+#endif
+#ifdef RTGUI_IMAGE_JPEG
+#include <rtgui/image_jpeg.h>
+#endif
+#ifdef RTGUI_IMAGE_PNG
+#include <rtgui/image_png.h>
+#endif
+
+static rtgui_list_t _rtgui_system_image_list = {RT_NULL};
+
+/* init rtgui image system */
+void rtgui_system_image_init(void)
+{
+ /* always support XPM image */
+ rtgui_image_xpm_init();
+
+#ifdef RTGUI_IMAGE_BMP
+ rtgui_image_bmp_init();
+#endif
+
+#ifdef RTGUI_IMAGE_JPEG
+ rtgui_image_jpeg_init();
+#endif
+
+#ifdef RTGUI_IMAGE_PNG
+ rtgui_image_png_init();
+#endif
+}
+
+static struct rtgui_image_engine* rtgui_image_get_engine(const char* type)
+{
+ struct rtgui_list_node *node;
+ struct rtgui_image_engine *engine;
+
+ rtgui_list_foreach(node, &_rtgui_system_image_list)
+ {
+ engine = rtgui_list_entry(node, struct rtgui_image_engine, list);
+
+ if (strncasecmp(engine->name, type, strlen(engine->name)) ==0)
+ return engine;
+ }
+
+ return RT_NULL;
+}
+
+struct rtgui_image* rtgui_image_create_from_file(const char* type, const char* filename, rt_bool_t load)
+{
+ struct rtgui_filerw* filerw;
+ struct rtgui_image_engine* engine;
+ struct rtgui_image* image = RT_NULL;
+
+ /* create filerw context */
+ filerw = rtgui_filerw_create_file(filename, "rb");
+ if (filerw == RT_NULL) return RT_NULL;
+
+ /* get image engine */
+ engine = rtgui_image_get_engine(type);
+ if (engine == RT_NULL)
+ {
+ /* close filerw context */
+ rtgui_filerw_close(filerw);
+ return RT_NULL;
+ }
+
+ if (engine->image_check(filerw) == RT_TRUE)
+ {
+ image = (struct rtgui_image*) rtgui_malloc(sizeof(struct rtgui_image));
+ if (image == RT_NULL)
+ {
+ /* close filerw context */
+ rtgui_filerw_close(filerw);
+ return RT_NULL;
+ }
+
+ if (engine->image_load(image, filerw, load) != RT_TRUE)
+ {
+ /* close filerw context */
+ rtgui_filerw_close(filerw);
+ return RT_NULL;
+ }
+
+ /* set image engine */
+ image->engine = engine;
+ }
+ else
+ {
+ rtgui_filerw_close(filerw);
+ }
+
+ return image;
+}
+
+struct rtgui_image* rtgui_image_create_from_mem(const char* type, const rt_uint8_t* data, rt_size_t length)
+{
+ struct rtgui_filerw* filerw;
+ struct rtgui_image_engine* engine;
+ struct rtgui_image* image = RT_NULL;
+
+ /* create filerw context */
+ filerw = rtgui_filerw_create_mem((rt_uint8_t*)data, length);
+ if (filerw == RT_NULL) return RT_NULL;
+
+ /* get image engine */
+ engine = rtgui_image_get_engine(type);
+ if (engine == RT_NULL)
+ {
+ /* close filerw context */
+ rtgui_filerw_close(filerw);
+ return RT_NULL;
+ }
+
+ if (engine->image_check(filerw) == RT_TRUE)
+ {
+ image = (struct rtgui_image*) rtgui_malloc(sizeof(struct rtgui_image));
+ if (image == RT_NULL)
+ {
+ /* close filerw context */
+ rtgui_filerw_close(filerw);
+ return RT_NULL;
+ }
+
+ if (engine->image_load(image, filerw, RT_TRUE) != RT_TRUE)
+ {
+ /* close filerw context */
+ rtgui_filerw_close(filerw);
+ return RT_NULL;
+ }
+
+ /* set image engine */
+ image->engine = engine;
+ }
+ else
+ {
+ rtgui_filerw_close(filerw);
+ }
+
+ return image;
+}
+
+void rtgui_image_destroy(struct rtgui_image* image)
+{
+ RT_ASSERT(image != RT_NULL);
+
+ image->engine->image_unload(image);
+ rtgui_free(image);
+}
+
+/* register an image engine */
+void rtgui_image_register_engine(struct rtgui_image_engine* engine)
+{
+ RT_ASSERT(engine!= RT_NULL);
+
+ rtgui_list_append(&_rtgui_system_image_list, &(engine->list));
+}
+
+void rtgui_image_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect)
+{
+ RT_ASSERT(dc != RT_NULL);
+ RT_ASSERT(rect != RT_NULL);
+
+ if (rtgui_dc_get_visible(dc) != RT_TRUE) return;
+
+ if (image != RT_NULL && image->engine != RT_NULL)
+ {
+ /* use image engine to blit */
+ image->engine->image_blit(image, dc, rect);
+ }
+}
+
diff --git a/rtgui/common/image_xpm.c b/rtgui/common/image_xpm.c
new file mode 100644
index 0000000000..bb7ce057f5
--- /dev/null
+++ b/rtgui/common/image_xpm.c
@@ -0,0 +1,617 @@
+/*
+ * File : image_xpm.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include <rtgui/filerw.h>
+#include <rtgui/image_xpm.h>
+#include <rtgui/rtgui_system.h>
+
+#define XPM_MAGIC_LEN 9
+
+static rt_bool_t rtgui_image_xpm_check(struct rtgui_filerw * file);
+static rt_bool_t rtgui_image_xpm_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
+static void rtgui_image_xpm_unload(struct rtgui_image* image);
+static void rtgui_image_xpm_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
+
+struct rtgui_image_engine rtgui_image_xpm_engine =
+{
+ "xpm",
+ {RT_NULL},
+ rtgui_image_xpm_check,
+ rtgui_image_xpm_load,
+ rtgui_image_xpm_unload,
+ rtgui_image_xpm_blit
+};
+
+struct rgb_item
+{
+ char *name;
+ int r;
+ int g;
+ int b;
+};
+
+const struct rgb_item rgbRecord[234] = {
+ {"AliceBlue", 240, 248, 255},
+ {"AntiqueWhite", 250, 235, 215},
+ {"Aquamarine", 50, 191, 193},
+ {"Azure", 240, 255, 255},
+ {"Beige", 245, 245, 220},
+ {"Bisque", 255, 228, 196},
+ {"Black", 0, 0, 0},
+ {"BlanchedAlmond", 255, 235, 205},
+ {"Blue", 0, 0, 255},
+ {"BlueViolet", 138, 43, 226},
+ {"Brown", 165, 42, 42},
+ {"burlywood", 222, 184, 135},
+ {"CadetBlue", 95, 146, 158},
+ {"chartreuse", 127, 255, 0},
+ {"chocolate", 210, 105, 30},
+ {"Coral", 255, 114, 86},
+ {"CornflowerBlue", 34, 34, 152},
+ {"cornsilk", 255, 248, 220},
+ {"Cyan", 0, 255, 255},
+ {"DarkGoldenrod", 184, 134, 11},
+ {"DarkGreen", 0, 86, 45},
+ {"DarkKhaki", 189, 183, 107},
+ {"DarkOliveGreen", 85, 86, 47},
+ {"DarkOrange", 255, 140, 0},
+ {"DarkOrchid", 139, 32, 139},
+ {"DarkSalmon", 233, 150, 122},
+ {"DarkSeaGreen", 143, 188, 143},
+ {"DarkSlateBlue", 56, 75, 102},
+ {"DarkSlateGray", 47, 79, 79},
+ {"DarkTurquoise", 0, 166, 166},
+ {"DarkViolet", 148, 0, 211},
+ {"DeepPink", 255, 20, 147},
+ {"DeepSkyBlue", 0, 191, 255},
+ {"DimGray", 84, 84, 84},
+ {"DodgerBlue", 30, 144, 255},
+ {"Firebrick", 142, 35, 35},
+ {"FloralWhite", 255, 250, 240},
+ {"ForestGreen", 80, 159, 105},
+ {"gainsboro", 220, 220, 220},
+ {"GhostWhite", 248, 248, 255},
+ {"Gold", 218, 170, 0},
+ {"Goldenrod", 239, 223, 132},
+ {"Gray", 126, 126, 126},
+ {"Gray0", 0, 0, 0},
+ {"Gray1", 3, 3, 3},
+ {"Gray10", 26, 26, 26},
+ {"Gray100", 255, 255, 255},
+ {"Gray11", 28, 28, 28},
+ {"Gray12", 31, 31, 31},
+ {"Gray13", 33, 33, 33},
+ {"Gray14", 36, 36, 36},
+ {"Gray15", 38, 38, 38},
+ {"Gray16", 41, 41, 41},
+ {"Gray17", 43, 43, 43},
+ {"Gray18", 46, 46, 46},
+ {"Gray19", 48, 48, 48},
+ {"Gray2", 5, 5, 5},
+ {"Gray20", 51, 51, 51},
+ {"Gray21", 54, 54, 54},
+ {"Gray22", 56, 56, 56},
+ {"Gray23", 59, 59, 59},
+ {"Gray24", 61, 61, 61},
+ {"Gray25", 64, 64, 64},
+ {"Gray26", 66, 66, 66},
+ {"Gray27", 69, 69, 69},
+ {"Gray28", 71, 71, 71},
+ {"Gray29", 74, 74, 74},
+ {"Gray3", 8, 8, 8},
+ {"Gray30", 77, 77, 77},
+ {"Gray31", 79, 79, 79},
+ {"Gray32", 82, 82, 82},
+ {"Gray33", 84, 84, 84},
+ {"Gray34", 87, 87, 87},
+ {"Gray35", 89, 89, 89},
+ {"Gray36", 92, 92, 92},
+ {"Gray37", 94, 94, 94},
+ {"Gray38", 97, 97, 97},
+ {"Gray39", 99, 99, 99},
+ {"Gray4", 10, 10, 10},
+ {"Gray40", 102, 102, 102},
+ {"Gray41", 105, 105, 105},
+ {"Gray42", 107, 107, 107},
+ {"Gray43", 110, 110, 110},
+ {"Gray44", 112, 112, 112},
+ {"Gray45", 115, 115, 115},
+ {"Gray46", 117, 117, 117},
+ {"Gray47", 120, 120, 120},
+ {"Gray48", 122, 122, 122},
+ {"Gray49", 125, 125, 125},
+ {"Gray5", 13, 13, 13},
+ {"Gray50", 127, 127, 127},
+ {"Gray51", 130, 130, 130},
+ {"Gray52", 133, 133, 133},
+ {"Gray53", 135, 135, 135},
+ {"Gray54", 138, 138, 138},
+ {"Gray55", 140, 140, 140},
+ {"Gray56", 143, 143, 143},
+ {"Gray57", 145, 145, 145},
+ {"Gray58", 148, 148, 148},
+ {"Gray59", 150, 150, 150},
+ {"Gray6", 15, 15, 15},
+ {"Gray60", 153, 153, 153},
+ {"Gray61", 156, 156, 156},
+ {"Gray62", 158, 158, 158},
+ {"Gray63", 161, 161, 161},
+ {"Gray64", 163, 163, 163},
+ {"Gray65", 166, 166, 166},
+ {"Gray66", 168, 168, 168},
+ {"Gray67", 171, 171, 171},
+ {"Gray68", 173, 173, 173},
+ {"Gray69", 176, 176, 176},
+ {"Gray7", 18, 18, 18},
+ {"Gray70", 179, 179, 179},
+ {"Gray71", 181, 181, 181},
+ {"Gray72", 184, 184, 184},
+ {"Gray73", 186, 186, 186},
+ {"Gray74", 189, 189, 189},
+ {"Gray75", 191, 191, 191},
+ {"Gray76", 194, 194, 194},
+ {"Gray77", 196, 196, 196},
+ {"Gray78", 199, 199, 199},
+ {"Gray79", 201, 201, 201},
+ {"Gray8", 20, 20, 20},
+ {"Gray80", 204, 204, 204},
+ {"Gray81", 207, 207, 207},
+ {"Gray82", 209, 209, 209},
+ {"Gray83", 212, 212, 212},
+ {"Gray84", 214, 214, 214},
+ {"Gray85", 217, 217, 217},
+ {"Gray86", 219, 219, 219},
+ {"Gray87", 222, 222, 222},
+ {"Gray88", 224, 224, 224},
+ {"Gray89", 227, 227, 227},
+ {"Gray9", 23, 23, 23},
+ {"Gray90", 229, 229, 229},
+ {"Gray91", 232, 232, 232},
+ {"Gray92", 235, 235, 235},
+ {"Gray93", 237, 237, 237},
+ {"Gray94", 240, 240, 240},
+ {"Gray95", 242, 242, 242},
+ {"Gray96", 245, 245, 245},
+ {"Gray97", 247, 247, 247},
+ {"Gray98", 250, 250, 250},
+ {"Gray99", 252, 252, 252},
+ {"Green", 0, 255, 0},
+ {"GreenYellow", 173, 255, 47},
+ {"honeydew", 240, 255, 240},
+ {"HotPink", 255, 105, 180},
+ {"IndianRed", 107, 57, 57},
+ {"ivory", 255, 255, 240},
+ {"Khaki", 179, 179, 126},
+ {"lavender", 230, 230, 250},
+ {"LavenderBlush", 255, 240, 245},
+ {"LawnGreen", 124, 252, 0},
+ {"LemonChiffon", 255, 250, 205},
+ {"LightBlue", 176, 226, 255},
+ {"LightCoral", 240, 128, 128},
+ {"LightCyan", 224, 255, 255},
+ {"LightGoldenrod", 238, 221, 130},
+ {"LightGoldenrodYellow", 250, 250, 210},
+ {"LightGray", 168, 168, 168},
+ {"LightPink", 255, 182, 193},
+ {"LightSalmon", 255, 160, 122},
+ {"LightSeaGreen", 32, 178, 170},
+ {"LightSkyBlue", 135, 206, 250},
+ {"LightSlateBlue", 132, 112, 255},
+ {"LightSlateGray", 119, 136, 153},
+ {"LightSteelBlue", 124, 152, 211},
+ {"LightYellow", 255, 255, 224},
+ {"LimeGreen", 0, 175, 20},
+ {"linen", 250, 240, 230},
+ {"Magenta", 255, 0, 255},
+ {"Maroon", 143, 0, 82},
+ {"MediumAquamarine", 0, 147, 143},
+ {"MediumBlue", 50, 50, 204},
+ {"MediumForestGreen", 50, 129, 75},
+ {"MediumGoldenrod", 209, 193, 102},
+ {"MediumOrchid", 189, 82, 189},
+ {"MediumPurple", 147, 112, 219},
+ {"MediumSeaGreen", 52, 119, 102},
+ {"MediumSlateBlue", 106, 106, 141},
+ {"MediumSpringGreen", 35, 142, 35},
+ {"MediumTurquoise", 0, 210, 210},
+ {"MediumVioletRed", 213, 32, 121},
+ {"MidnightBlue", 47, 47, 100},
+ {"MintCream", 245, 255, 250},
+ {"MistyRose", 255, 228, 225},
+ {"moccasin", 255, 228, 181},
+ {"NavajoWhite", 255, 222, 173},
+ {"Navy", 35, 35, 117},
+ {"NavyBlue", 35, 35, 117},
+ {"OldLace", 253, 245, 230},
+ {"OliveDrab", 107, 142, 35},
+ {"Orange", 255, 135, 0},
+ {"OrangeRed", 255, 69, 0},
+ {"Orchid", 239, 132, 239},
+ {"PaleGoldenrod", 238, 232, 170},
+ {"PaleGreen", 115, 222, 120},
+ {"PaleTurquoise", 175, 238, 238},
+ {"PaleVioletRed", 219, 112, 147},
+ {"PapayaWhip", 255, 239, 213},
+ {"PeachPuff", 255, 218, 185},
+ {"peru", 205, 133, 63},
+ {"Pink", 255, 181, 197},
+ {"Plum", 197, 72, 155},
+ {"PowderBlue", 176, 224, 230},
+ {"purple", 160, 32, 240},
+ {"Red", 255, 0, 0},
+ {"RosyBrown", 188, 143, 143},
+ {"RoyalBlue", 65, 105, 225},
+ {"SaddleBrown", 139, 69, 19},
+ {"Salmon", 233, 150, 122},
+ {"SandyBrown", 244, 164, 96},
+ {"SeaGreen", 82, 149, 132},
+ {"seashell", 255, 245, 238},
+ {"Sienna", 150, 82, 45},
+ {"SkyBlue", 114, 159, 255},
+ {"SlateBlue", 126, 136, 171},
+ {"SlateGray", 112, 128, 144},
+ {"snow", 255, 250, 250},
+ {"SpringGreen", 65, 172, 65},
+ {"SteelBlue", 84, 112, 170},
+ {"Tan", 222, 184, 135},
+ {"Thistle", 216, 191, 216},
+ {"tomato", 255, 99, 71},
+ {"Transparent", 0, 0, 1},
+ {"Turquoise", 25, 204, 223},
+ {"Violet", 156, 62, 206},
+ {"VioletRed", 243, 62, 150},
+ {"Wheat", 245, 222, 179},
+ {"White", 255, 255, 255},
+ {"WhiteSmoke", 245, 245, 245},
+ {"Yellow", 255, 255, 0},
+ {"YellowGreen", 50, 216, 56}
+};
+/* Hash table to look up colors from pixel strings */
+#define STARTING_HASH_SIZE 256
+
+struct hash_entry
+{
+ char key[10];
+ rtgui_color_t color;
+ struct hash_entry *next;
+};
+
+struct color_hash
+{
+ struct hash_entry **table;
+ struct hash_entry *entries; /* array of all entries */
+ struct hash_entry *next_free;
+
+ int size;
+ int maxnum;
+};
+
+static int hash_key(const char *key, int cpp, int size)
+{
+ int hash;
+
+ hash = 0;
+ while ( cpp-- > 0 )
+ {
+ hash = hash * 33 + *key++;
+ }
+ return hash & (size - 1);
+}
+
+static struct color_hash *create_colorhash(int maxnum)
+{
+ int bytes, s;
+ struct color_hash *hash;
+
+ /* we know how many entries we need, so we can allocate
+ everything here */
+ hash = rtgui_malloc(sizeof *hash);
+ if(!hash) return RT_NULL;
+
+ /* use power-of-2 sized hash table for decoding speed */
+ for(s = STARTING_HASH_SIZE; s < maxnum; s <<= 1) ;
+ hash->size = s;
+ hash->maxnum = maxnum;
+ bytes = hash->size * sizeof(struct hash_entry **);
+ hash->entries = RT_NULL; /* in case rt_malloc fails */
+ hash->table = rtgui_malloc(bytes);
+ if(!hash->table) return RT_NULL;
+
+ rt_memset(hash->table, 0, bytes);
+ hash->entries = rtgui_malloc(maxnum * sizeof(struct hash_entry));
+ if(!hash->entries) return RT_NULL;
+
+ hash->next_free = hash->entries;
+ return hash;
+}
+
+static int add_colorhash(struct color_hash *hash,
+ char *key, int cpp, rtgui_color_t *color)
+{
+ int index = hash_key(key, cpp, hash->size);
+ struct hash_entry *e = hash->next_free++;
+
+ e->color = *color;
+ rt_memset(e->key, 0, sizeof(e->key));
+ rt_strncpy(e->key, key, cpp);
+ e->next = hash->table[index];
+ hash->table[index] = e;
+
+ return 1;
+}
+
+static void get_colorhash(struct color_hash *hash, const char *key, int cpp, rtgui_color_t* c)
+{
+ struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
+ while(entry)
+ {
+ if(rt_memcmp(key, entry->key, cpp) == 0)
+ {
+ *c = entry->color;
+
+ return;
+ }
+
+ entry = entry->next;
+ }
+
+ return ; /* garbage in - garbage out */
+}
+
+static void free_colorhash(struct color_hash *hash)
+{
+ if(hash && hash->table)
+ {
+ rtgui_free(hash->table);
+ rtgui_free(hash->entries);
+ rtgui_free(hash);
+ }
+}
+
+#if defined(_MSC_VER) || defined(__CC_ARM)
+int strcasecmp( const char* s1, const char* s2 )
+{
+ register unsigned int x2;
+ register unsigned int x1;
+
+ while (1) {
+ x2 = *s2 - 'A'; if (x2 < 26u) x2 += 32;
+ x1 = *s1 - 'A'; if (x1 < 26u) x1 += 32;
+ s1++; s2++;
+ if (x2 != x1)
+ break;
+ if (x1 == (unsigned int)-'A')
+ break;
+ }
+
+ return x1 - x2;
+}
+#endif
+
+static int hex2int (char *str)
+{
+ int i = 0;
+ int r = 0;
+
+ for (i = 0; i < 2; i++)
+ {
+ if (str[i] >= '0' && str[i] <= '9') r += str[i] - '0';
+ else if (str[i] >= 'a' && str[i] <= 'f') r += str[i] - 'a' + 10;
+ else if (str[i] >= 'A' && str[i] <= 'F') r += str[i] - 'A' + 10;
+
+ if (!i) r *= 16;
+ }
+
+ return r;
+}
+
+void rtgui_image_xpm_init()
+{
+ /* register xpm engine */
+ rtgui_image_register_engine(&rtgui_image_xpm_engine);
+}
+
+static rt_bool_t rtgui_image_xpm_check(struct rtgui_filerw* file)
+{
+#if 0
+ rt_uint8_t buffer[XPM_MAGIC_LEN];
+ rt_size_t start;
+ rt_bool_t result;
+
+ result = RT_FALSE;
+
+ start = rtgui_filerw_tell(file);
+
+ /* seek to the begining of file */
+ if (start != 0) rtgui_filerw_seek(file, 0, SEEK_SET);
+ rtgui_filerw_read(file, &buffer[0], XPM_MAGIC_LEN, 1);
+
+ if (rt_memcmp(buffer, "/* XPM */", (rt_ubase_t)XPM_MAGIC_LEN) == 0)
+ result = RT_TRUE;
+
+ rtgui_filerw_seek(file, start, SEEK_SET);
+
+ return result;
+#else
+ /* we can not check image type for memory file */
+ return RT_TRUE;
+#endif
+}
+
+static rt_bool_t rtgui_image_xpm_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
+{
+ const char **xpm;
+ const char *buf;
+ const char *buf_tmp;
+
+ int w, h;
+ int colors = 0;
+ int colors_pp = 0;
+
+ int i, j;
+
+ /* color hash table */
+ struct color_hash *colors_table = RT_NULL;
+
+ if (image == RT_NULL) return RT_FALSE;
+
+ xpm = (const char **)rtgui_filerw_mem_getdata(file);
+ if (xpm == RT_NULL) return RT_FALSE;
+
+ /* set image engine */
+ image->engine = &rtgui_image_xpm_engine;
+
+ /* parse xpm image */
+ sscanf(xpm[0], "%d %d %d %d", &w, &h, &colors, &colors_pp);
+ image->w = w;
+ image->h = h;
+
+ /* build color table */
+ colors_table = create_colorhash(colors);
+ if (!colors_table)
+ {
+ return RT_FALSE;
+ }
+
+ for (i = 0; i < colors; i++)
+ {
+ char color_name[10];
+ rtgui_color_t c = 0;
+
+ buf = xpm[i + 1];
+
+ for (j = 0; j < colors_pp; j++)
+ {
+ color_name[j] = buf[j];
+ }
+ color_name[j] = '\0';
+
+ /* build rtgui_color */
+ if ((buf_tmp = strstr(buf, "c #")) != RT_NULL)
+ {
+ char color_hex[10];
+
+ /* hexadecimal color value */
+ sscanf(buf_tmp, "c #%s", color_hex);
+
+ c = RTGUI_ARGB(0, hex2int(color_hex),
+ hex2int(color_hex + 2),
+ hex2int(color_hex + 4));
+ }
+ else if ((buf_tmp = strstr(buf, "c ")) != RT_NULL)
+ {
+ int k;
+
+ /* color name */
+ char rgbname[30];
+
+ sscanf(buf_tmp, "c %s", rgbname);
+
+ if (strcasecmp(rgbname, "None") == 0)
+ {
+ goto color_none;
+ }
+
+ for (k = 0; k < 234; k++)
+ {
+ if (strcasecmp(rgbname, rgbRecord[k].name) == 0)
+ {
+ c = RTGUI_ARGB(0, rgbRecord[k].r,
+ rgbRecord[k].g,
+ rgbRecord[k].b);
+ break;
+ }
+ }
+ }
+ else
+ {
+color_none:
+ c = RTGUI_RGB(0, 0, 0);
+ }
+
+ /* add to color hash table */
+ add_colorhash(colors_table, color_name, colors_pp, &c);
+ }
+
+ /* build rgb pixel data */
+ image->data = (rt_uint8_t*) rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t));
+ memset(image->data, 0, image->w * image->h * sizeof(rtgui_color_t));
+
+ {
+ rtgui_color_t *ptr = (rtgui_color_t*) image->data;
+
+ for (h = 0; h < image->h; h++)
+ {
+ buf = xpm[colors + 1 + h];
+ for (w = 0; w < image->w; w++, buf += colors_pp)
+ {
+ get_colorhash(colors_table, buf, colors_pp, ptr);
+
+ ptr ++;
+ }
+ }
+ }
+
+ free_colorhash(colors_table);
+
+ return RT_TRUE;
+}
+
+static void rtgui_image_xpm_unload(struct rtgui_image* image)
+{
+ if (image != RT_NULL)
+ {
+ /* release data */
+ rtgui_free(image->data);
+ image->data = RT_NULL;
+ }
+}
+
+static void rtgui_image_xpm_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect)
+{
+ rt_uint16_t x, y;
+ rtgui_color_t* ptr;
+ rtgui_color_t foreground;
+
+ RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
+ RT_ASSERT(image->data != RT_NULL);
+
+ ptr = (rtgui_color_t*) image->data;
+
+ /* 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);
+ }
+
+ /* move to next color buffer */
+ ptr ++;
+ }
+ }
+
+ /* restore foreground */
+ rtgui_dc_set_color(dc, foreground);
+}
+
diff --git a/rtgui/common/region.c b/rtgui/common/region.c
new file mode 100644
index 0000000000..e983f59ac6
--- /dev/null
+++ b/rtgui/common/region.c
@@ -0,0 +1,2228 @@
+/*
+ * File : region.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/region.h>
+#include <rtgui/rtgui_system.h>
+
+/* #define good(reg) RT_ASSERT(rtgui_region16_valid(reg)) */
+#define good(reg)
+
+#define RTGUI_MIN(a,b) ((a) < (b) ? (a) : (b))
+#define RTGUI_MAX(a,b) ((a) > (b) ? (a) : (b))
+
+#define RTGUI_SHRT_MIN (-32767-1)
+#define RTGUI_SHRT_MAX 32767
+
+#define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects)
+
+/* not a region */
+#define PIXREGION_NAR(reg) ((reg)->data == &rtgui_brokendata)
+#define PIXREGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1)
+#define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0)
+#define PIXREGION_RECTS(reg) ((reg)->data ? (rtgui_rect_t *)((reg)->data + 1) \
+ : &(reg)->extents)
+#define PIXREGION_BOXPTR(reg) ((rtgui_rect_t *)((reg)->data + 1))
+#define PIXREGION_BOX(reg,i) (&PIXREGION_BOXPTR(reg)[i])
+#define PIXREGION_TOP(reg) PIXREGION_BOX(reg, (reg)->data->numRects)
+#define PIXREGION_END(reg) PIXREGION_BOX(reg, (reg)->data->numRects - 1)
+#define PIXREGION_SZOF(n) (sizeof(rtgui_region_data_t) + ((n) * sizeof(rtgui_rect_t)))
+
+rtgui_rect_t rtgui_empty_rect = {0, 0, 0, 0};
+static rtgui_region_data_t rtgui_region_emptydata = {0, 0};
+static rtgui_region_data_t rtgui_brokendata = {0, 0};
+
+static rtgui_region_status_t rtgui_break(rtgui_region_t *pReg);
+
+/*
+ * The functions in this file implement the Region abstraction used extensively
+ * throughout the X11 sample server. A Region is simply a set of disjoint
+ * (non-overlapping) rectangles, plus an "extent" rectangle which is the
+ * smallest single rectangle that contains all the non-overlapping rectangles.
+ *
+ * A Region is implemented as a "y-x-banded" array of rectangles. This array
+ * imposes two degrees of order. First, all rectangles are sorted by top side
+ * y coordinate first (y1), and then by left side x coordinate (x1).
+ *
+ * Furthermore, the rectangles are grouped into "bands". Each rectangle in a
+ * band has the same top y coordinate (y1), and each has the same bottom y
+ * coordinate (y2). Thus all rectangles in a band differ only in their left
+ * and right side (x1 and x2). Bands are implicit in the array of rectangles:
+ * there is no separate list of band start pointers.
+ *
+ * The y-x band representation does not RTGUI_MINimize rectangles. In particular,
+ * if a rectangle vertically crosses a band (the rectangle has scanlines in
+ * the y1 to y2 area spanned by the band), then the rectangle may be broken
+ * down into two or more smaller rectangles stacked one atop the other.
+ *
+ * ----------- -----------
+ * | | | | band 0
+ * | | -------- ----------- --------
+ * | | | | in y-x banded | | | | band 1
+ * | | | | form is | | | |
+ * ----------- | | ----------- --------
+ * | | | | band 2
+ * -------- --------
+ *
+ * An added constraint on the rectangles is that they must cover as much
+ * horizontal area as possible: no two rectangles within a band are allowed
+ * to touch.
+ *
+ * Whenever possible, bands will be merged together to cover a greater vertical
+ * distance (and thus reduce the number of rectangles). Two bands can be merged
+ * only if the bottom of one touches the top of the other and they have
+ * rectangles in the same places (of the same width, of course).
+ *
+ * Adam de Boor wrote most of the original region code. Joel McCormack
+ * substantially modified or rewrote most of the core arithmetic routines, and
+ * added rtgui_region_validate in order to support several speed improvements to
+ * rtgui_region_validateTree. Bob Scheifler changed the representation to be more
+ * compact when empty or a single rectangle, and did a bunch of gratuitous
+ * reformatting. Carl Worth did further gratuitous reformatting while re-merging
+ * the server and client region code into libpixregion.
+ */
+
+/* true iff two Boxes overlap */
+#define EXTENTCHECK(r1,r2) \
+ (!( ((r1)->x2 <= (r2)->x1) || \
+ ((r1)->x1 >= (r2)->x2) || \
+ ((r1)->y2 <= (r2)->y1) || \
+ ((r1)->y1 >= (r2)->y2) ) )
+
+/* true iff (x,y) is in Box */
+#define INBOX(r,x,y) \
+ ( ((r)->x2 > (x)) && \
+ ((r)->x1 <= (x)) && \
+ ((r)->y2 > (y)) && \
+ ((r)->y1 <= (y)) )
+
+/* true iff Box r1 contains Box r2 */
+#define SUBSUMES(r1,r2) \
+ ( ((r1)->x1 <= (r2)->x1) && \
+ ((r1)->x2 >= (r2)->x2) && \
+ ((r1)->y1 <= (r2)->y1) && \
+ ((r1)->y2 >= (r2)->y2) )
+
+#define allocData(n) rtgui_malloc(PIXREGION_SZOF(n))
+#define freeData(reg) if ((reg)->data && (reg)->data->size) rtgui_free((reg)->data)
+
+#define RECTALLOC_BAIL(pReg,n,bail) \
+if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
+ if (!rtgui_rect_alloc(pReg, n)) { goto bail; }
+
+#define RECTALLOC(pReg,n) \
+if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
+ if (!rtgui_rect_alloc(pReg, n)) { return RTGUI_REGION_STATUS_FAILURE; }
+
+#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \
+{ \
+ pNextRect->x1 = nx1; \
+ pNextRect->y1 = ny1; \
+ pNextRect->x2 = nx2; \
+ pNextRect->y2 = ny2; \
+ pNextRect++; \
+}
+
+#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \
+{ \
+ if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\
+ { \
+ if (!rtgui_rect_alloc(pReg, 1)) \
+ return RTGUI_REGION_STATUS_FAILURE; \
+ pNextRect = PIXREGION_TOP(pReg); \
+ } \
+ ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \
+ pReg->data->numRects++; \
+ RT_ASSERT(pReg->data->numRects<=pReg->data->size); \
+}
+
+#define DOWNSIZE(reg,numRects) \
+if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
+{ \
+ rtgui_region_data_t * NewData; \
+ NewData = (rtgui_region_data_t *)rt_realloc((reg)->data, PIXREGION_SZOF(numRects)); \
+ if (NewData) \
+ { \
+ NewData->size = (numRects); \
+ (reg)->data = NewData; \
+ } \
+}
+
+void rtgui_region_init(rtgui_region_t *region)
+{
+ region->extents = rtgui_empty_rect;
+ region->data = &rtgui_region_emptydata;
+}
+
+void rtgui_region_init_rect(rtgui_region_t *region,
+ int x, int y, unsigned int width, unsigned int height)
+{
+ region->extents.x1 = x;
+ region->extents.y1 = y;
+ region->extents.x2 = x + width;
+ region->extents.y2 = y + height;
+ region->data = RT_NULL;
+}
+
+void rtgui_region_init_with_extents(rtgui_region_t *region, rtgui_rect_t *extents)
+{
+ region->extents = *extents;
+ region->data = RT_NULL;
+}
+
+void rtgui_region_fini (rtgui_region_t *region)
+{
+ good (region);
+ freeData (region);
+}
+
+int rtgui_region_num_rects (rtgui_region_t *region)
+{
+ return PIXREGION_NUM_RECTS (region);
+}
+
+rtgui_rect_t *rtgui_region_rects (rtgui_region_t *region)
+{
+ return PIXREGION_RECTS (region);
+}
+
+static rtgui_region_status_t rtgui_break (rtgui_region_t *region)
+{
+ freeData (region);
+ region->extents = rtgui_empty_rect;
+ region->data = &rtgui_brokendata;
+ return RTGUI_REGION_STATUS_FAILURE;
+}
+
+static rtgui_region_status_t rtgui_rect_alloc(rtgui_region_t * region, int n)
+{
+ rtgui_region_data_t *data;
+
+ if (!region->data)
+ {
+ n++;
+ region->data = allocData(n);
+ if (!region->data) return rtgui_break (region);
+ region->data->numRects = 1;
+ *PIXREGION_BOXPTR(region) = region->extents;
+ }
+ else if (!region->data->size)
+ {
+ region->data = allocData(n);
+ if (!region->data) return rtgui_break (region);
+ region->data->numRects = 0;
+ }
+ else
+ {
+ if (n == 1)
+ {
+ n = region->data->numRects;
+ if (n > 500) /* XXX pick numbers out of a hat */
+ n = 250;
+ }
+ n += region->data->numRects;
+ data = (rtgui_region_data_t *)rt_realloc(region->data, PIXREGION_SZOF(n));
+ if (!data) return rtgui_break (region);
+ region->data = data;
+ }
+ region->data->size = n;
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+rtgui_region_status_t rtgui_region_copy(rtgui_region_t *dst, rtgui_region_t *src)
+{
+ good(dst);
+ good(src);
+ if (dst == src)
+ return RTGUI_REGION_STATUS_SUCCESS;
+ dst->extents = src->extents;
+ if (!src->data || !src->data->size)
+ {
+ freeData(dst);
+ dst->data = src->data;
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+ if (!dst->data || (dst->data->size < src->data->numRects))
+ {
+ freeData(dst);
+ dst->data = allocData(src->data->numRects);
+ if (!dst->data) return rtgui_break (dst);
+ dst->data->size = src->data->numRects;
+ }
+ dst->data->numRects = src->data->numRects;
+ rt_memmove((char *)PIXREGION_BOXPTR(dst),(char *)PIXREGION_BOXPTR(src),
+ dst->data->numRects * sizeof(rtgui_rect_t));
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+/*======================================================================
+ * Generic Region Operator
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_coalesce --
+ * Attempt to merge the boxes in the current band with those in the
+ * previous one. We are guaranteed that the current band extends to
+ * the end of the rects array. Used only by rtgui_op.
+ *
+ * Results:
+ * The new index for the previous band.
+ *
+ * Side Effects:
+ * If coalescing takes place:
+ * - rectangles in the previous band will have their y2 fields
+ * altered.
+ * - region->data->numRects will be decreased.
+ *
+ *-----------------------------------------------------------------------
+ */
+rt_inline int
+rtgui_coalesce (
+ rtgui_region_t *region, /* Region to coalesce */
+ int prevStart, /* Index of start of previous band */
+ int curStart) /* Index of start of current band */
+{
+ rtgui_rect_t * pPrevBox; /* Current box in previous band */
+ rtgui_rect_t * pCurBox; /* Current box in current band */
+ int numRects; /* Number rectangles in both bands */
+ int y2; /* Bottom of current band */
+ /*
+ * Figure out how many rectangles are in the band.
+ */
+ numRects = curStart - prevStart;
+ RT_ASSERT(numRects == region->data->numRects - curStart);
+
+ if (!numRects) return curStart;
+
+ /*
+ * The bands may only be coalesced if the bottom of the previous
+ * matches the top scanline of the current.
+ */
+ pPrevBox = PIXREGION_BOX(region, prevStart);
+ pCurBox = PIXREGION_BOX(region, curStart);
+ if (pPrevBox->y2 != pCurBox->y1) return curStart;
+
+ /*
+ * Make sure the bands have boxes in the same places. This
+ * assumes that boxes have been added in such a way that they
+ * cover the most area possible. I.e. two boxes in a band must
+ * have some horizontal space between them.
+ */
+ y2 = pCurBox->y2;
+
+ do
+ {
+ if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2))
+ {
+ return (curStart);
+ }
+ pPrevBox++;
+ pCurBox++;
+ numRects--;
+ }
+ while (numRects);
+
+ /*
+ * The bands may be merged, so set the bottom y of each box
+ * in the previous band to the bottom y of the current band.
+ */
+ numRects = curStart - prevStart;
+ region->data->numRects -= numRects;
+ do
+ {
+ pPrevBox--;
+ pPrevBox->y2 = y2;
+ numRects--;
+ }
+ while (numRects);
+ return prevStart;
+}
+
+/* Quicky macro to avoid trivial reject procedure calls to rtgui_coalesce */
+
+#define Coalesce(newReg, prevBand, curBand) \
+ if (curBand - prevBand == newReg->data->numRects - curBand) { \
+ prevBand = rtgui_coalesce(newReg, prevBand, curBand); \
+ } else { \
+ prevBand = curBand; \
+ }
+
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_region_appendNonO --
+ * Handle a non-overlapping band for the union and subtract operations.
+ * Just adds the (top/bottom-clipped) rectangles into the region.
+ * Doesn't have to check for subsumption or anything.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * region->data->numRects is incremented and the rectangles overwritten
+ * with the rectangles we're passed.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+rt_inline rtgui_region_status_t
+rtgui_region_appendNonO (
+ rtgui_region_t *region,
+ rtgui_rect_t *r,
+ rtgui_rect_t *rEnd,
+ int y1,
+ int y2)
+{
+ rtgui_rect_t * pNextRect;
+ int newRects;
+
+ newRects = rEnd - r;
+
+ RT_ASSERT(y1 < y2);
+ RT_ASSERT(newRects != 0);
+
+ /* Make sure we have enough space for all rectangles to be added */
+ RECTALLOC(region, newRects);
+ pNextRect = PIXREGION_TOP(region);
+ region->data->numRects += newRects;
+ do
+ {
+ RT_ASSERT(r->x1 < r->x2);
+ ADDRECT(pNextRect, r->x1, y1, r->x2, y2);
+ r++;
+ }
+ while (r != rEnd);
+
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+#define FindBand(r, rBandEnd, rEnd, ry1) \
+{ \
+ ry1 = r->y1; \
+ rBandEnd = r+1; \
+ while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \
+ rBandEnd++; \
+ } \
+}
+
+#define AppendRegions(newReg, r, rEnd) \
+{ \
+ int newRects = rEnd - r; \
+ if (newRects) { \
+ RECTALLOC(newReg, newRects); \
+ rt_memmove((char *)PIXREGION_TOP(newReg),(char *)r, \
+ newRects * sizeof(rtgui_rect_t)); \
+ newReg->data->numRects += newRects; \
+ } \
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_op --
+ * Apply an operation to two regions. Called by rtgui_region_union, rtgui_region_inverse,
+ * rtgui_region_subtract, rtgui_region_intersect.... Both regions MUST have at least one
+ * rectangle, and cannot be the same object.
+ *
+ * Results:
+ * RTGUI_REGION_STATUS_SUCCESS if successful.
+ *
+ * Side Effects:
+ * The new region is overwritten.
+ * pOverlap set to RTGUI_REGION_STATUS_SUCCESS if overlapFunc ever returns RTGUI_REGION_STATUS_SUCCESS.
+ *
+ * Notes:
+ * The idea behind this function is to view the two regions as sets.
+ * Together they cover a rectangle of area that this function divides
+ * into horizontal bands where points are covered only by one region
+ * or by both. For the first case, the nonOverlapFunc is called with
+ * each the band and the band's upper and lower extents. For the
+ * second, the overlapFunc is called to process the entire band. It
+ * is responsible for clipping the rectangles in the band, though
+ * this function provides the boundaries.
+ * At the end of each band, the new region is coalesced, if possible,
+ * to reduce the number of rectangles in the region.
+ *
+ *-----------------------------------------------------------------------
+ */
+
+typedef rtgui_region_status_t (*OverlapProcPtr)(
+ rtgui_region_t *region,
+ rtgui_rect_t *r1,
+ rtgui_rect_t *r1End,
+ rtgui_rect_t *r2,
+ rtgui_rect_t *r2End,
+ short y1,
+ short y2,
+ int *pOverlap);
+
+static rtgui_region_status_t
+rtgui_op(
+ rtgui_region_t *newReg, /* Place to store result */
+ rtgui_region_t *reg1, /* First region in operation */
+ rtgui_region_t *reg2, /* 2d region in operation */
+ OverlapProcPtr overlapFunc, /* Function to call for over-
+ * lapping bands */
+ int appendNon1, /* Append non-overlapping bands */
+ /* in region 1 ? */
+ int appendNon2, /* Append non-overlapping bands */
+ /* in region 2 ? */
+ int *pOverlap)
+{
+ rtgui_rect_t * r1; /* Pointer into first region */
+ rtgui_rect_t * r2; /* Pointer into 2d region */
+ rtgui_rect_t * r1End; /* End of 1st region */
+ rtgui_rect_t * r2End; /* End of 2d region */
+ short ybot; /* Bottom of intersection */
+ short ytop; /* Top of intersection */
+ rtgui_region_data_t * oldData; /* Old data for newReg */
+ int prevBand; /* Index of start of
+ * previous band in newReg */
+ int curBand; /* Index of start of current
+ * band in newReg */
+ rtgui_rect_t * r1BandEnd; /* End of current band in r1 */
+ rtgui_rect_t * r2BandEnd; /* End of current band in r2 */
+ short top; /* Top of non-overlapping band */
+ short bot; /* Bottom of non-overlapping band*/
+ int r1y1; /* Temps for r1->y1 and r2->y1 */
+ int r2y1;
+ int newSize;
+ int numRects;
+
+ /*
+ * Break any region computed from a broken region
+ */
+ if (PIXREGION_NAR (reg1) || PIXREGION_NAR(reg2))
+ return rtgui_break (newReg);
+
+ /*
+ * Initialization:
+ * set r1, r2, r1End and r2End appropriately, save the rectangles
+ * of the destination region until the end in case it's one of
+ * the two source regions, then mark the "new" region empty, allocating
+ * another array of rectangles for it to use.
+ */
+
+ r1 = PIXREGION_RECTS(reg1);
+ newSize = PIXREGION_NUM_RECTS(reg1);
+ r1End = r1 + newSize;
+ numRects = PIXREGION_NUM_RECTS(reg2);
+ r2 = PIXREGION_RECTS(reg2);
+ r2End = r2 + numRects;
+ RT_ASSERT(r1 != r1End);
+ RT_ASSERT(r2 != r2End);
+
+ oldData = (rtgui_region_data_t *)RT_NULL;
+ if (((newReg == reg1) && (newSize > 1)) ||
+ ((newReg == reg2) && (numRects > 1)))
+ {
+ oldData = newReg->data;
+ newReg->data = &rtgui_region_emptydata;
+ }
+ /* guess at new size */
+ if (numRects > newSize)
+ newSize = numRects;
+ newSize <<= 1;
+ if (!newReg->data)
+ newReg->data = &rtgui_region_emptydata;
+ else if (newReg->data->size)
+ newReg->data->numRects = 0;
+ if (newSize > newReg->data->size)
+ if (!rtgui_rect_alloc(newReg, newSize))
+ return RTGUI_REGION_STATUS_FAILURE;
+
+ /*
+ * Initialize ybot.
+ * In the upcoRTGUI_MINg loop, ybot and ytop serve different functions depending
+ * on whether the band being handled is an overlapping or non-overlapping
+ * band.
+ * In the case of a non-overlapping band (only one of the regions
+ * has points in the band), ybot is the bottom of the most recent
+ * intersection and thus clips the top of the rectangles in that band.
+ * ytop is the top of the next intersection between the two regions and
+ * serves to clip the bottom of the rectangles in the current band.
+ * For an overlapping band (where the two regions intersect), ytop clips
+ * the top of the rectangles of both regions and ybot clips the bottoms.
+ */
+
+ ybot = RTGUI_MIN(r1->y1, r2->y1);
+
+ /*
+ * prevBand serves to mark the start of the previous band so rectangles
+ * can be coalesced into larger rectangles. qv. rtgui_coalesce, above.
+ * In the beginning, there is no previous band, so prevBand == curBand
+ * (curBand is set later on, of course, but the first band will always
+ * start at index 0). prevBand and curBand must be indices because of
+ * the possible expansion, and resultant moving, of the new region's
+ * array of rectangles.
+ */
+ prevBand = 0;
+
+ do
+ {
+ /*
+ * This algorithm proceeds one source-band (as opposed to a
+ * destination band, which is deterRTGUI_MINed by where the two regions
+ * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
+ * rectangle after the last one in the current band for their
+ * respective regions.
+ */
+ RT_ASSERT(r1 != r1End);
+ RT_ASSERT(r2 != r2End);
+
+ FindBand(r1, r1BandEnd, r1End, r1y1);
+ FindBand(r2, r2BandEnd, r2End, r2y1);
+
+ /*
+ * First handle the band that doesn't intersect, if any.
+ *
+ * Note that attention is restricted to one band in the
+ * non-intersecting region at once, so if a region has n
+ * bands between the current position and the next place it overlaps
+ * the other, this entire loop will be passed through n times.
+ */
+ if (r1y1 < r2y1)
+ {
+ if (appendNon1)
+ {
+ top = RTGUI_MAX(r1y1, ybot);
+ bot = RTGUI_MIN(r1->y2, r2y1);
+ if (top != bot)
+ {
+ curBand = newReg->data->numRects;
+ rtgui_region_appendNonO(newReg, r1, r1BandEnd, top, bot);
+ Coalesce(newReg, prevBand, curBand);
+ }
+ }
+ ytop = r2y1;
+ }
+ else if (r2y1 < r1y1)
+ {
+ if (appendNon2)
+ {
+ top = RTGUI_MAX(r2y1, ybot);
+ bot = RTGUI_MIN(r2->y2, r1y1);
+ if (top != bot)
+ {
+ curBand = newReg->data->numRects;
+ rtgui_region_appendNonO(newReg, r2, r2BandEnd, top, bot);
+ Coalesce(newReg, prevBand, curBand);
+ }
+ }
+ ytop = r1y1;
+ }
+ else
+ {
+ ytop = r1y1;
+ }
+
+ /*
+ * Now see if we've hit an intersecting band. The two bands only
+ * intersect if ybot > ytop
+ */
+ ybot = RTGUI_MIN(r1->y2, r2->y2);
+ if (ybot > ytop)
+ {
+ curBand = newReg->data->numRects;
+ (* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot,
+ pOverlap);
+ Coalesce(newReg, prevBand, curBand);
+ }
+
+ /*
+ * If we've finished with a band (y2 == ybot) we skip forward
+ * in the region to the next band.
+ */
+ if (r1->y2 == ybot) r1 = r1BandEnd;
+ if (r2->y2 == ybot) r2 = r2BandEnd;
+
+ }
+ while (r1 != r1End && r2 != r2End);
+
+ /*
+ * Deal with whichever region (if any) still has rectangles left.
+ *
+ * We only need to worry about banding and coalescing for the very first
+ * band left. After that, we can just group all remaining boxes,
+ * regardless of how many bands, into one final append to the list.
+ */
+
+ if ((r1 != r1End) && appendNon1)
+ {
+ /* Do first nonOverlap1Func call, which may be able to coalesce */
+ FindBand(r1, r1BandEnd, r1End, r1y1);
+ curBand = newReg->data->numRects;
+ rtgui_region_appendNonO(newReg, r1, r1BandEnd, RTGUI_MAX(r1y1, ybot), r1->y2);
+ Coalesce(newReg, prevBand, curBand);
+ /* Just append the rest of the boxes */
+ AppendRegions(newReg, r1BandEnd, r1End);
+ }
+ else if ((r2 != r2End) && appendNon2)
+ {
+ /* Do first nonOverlap2Func call, which may be able to coalesce */
+ FindBand(r2, r2BandEnd, r2End, r2y1);
+ curBand = newReg->data->numRects;
+ rtgui_region_appendNonO(newReg, r2, r2BandEnd, RTGUI_MAX(r2y1, ybot), r2->y2);
+ Coalesce(newReg, prevBand, curBand);
+ /* Append rest of boxes */
+ AppendRegions(newReg, r2BandEnd, r2End);
+ }
+
+ if (oldData)
+ rtgui_free(oldData);
+
+ numRects = newReg->data->numRects;
+ if (!numRects)
+ {
+ freeData(newReg);
+ newReg->data = &rtgui_region_emptydata;
+ }
+ else if (numRects == 1)
+ {
+ newReg->extents = *PIXREGION_BOXPTR(newReg);
+ freeData(newReg);
+ newReg->data = (rtgui_region_data_t *)RT_NULL;
+ }
+ else
+ {
+ DOWNSIZE(newReg, numRects);
+ }
+
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_set_extents --
+ * Reset the extents of a region to what they should be. Called by
+ * rtgui_region_subtract and rtgui_region_intersect as they can't figure it out along the
+ * way or do so easily, as rtgui_region_union can.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The region's 'extents' structure is overwritten.
+ *
+ *-----------------------------------------------------------------------
+ */
+static void
+rtgui_set_extents (rtgui_region_t *region)
+{
+ rtgui_rect_t *box, *boxEnd;
+
+ if (!region->data)
+ return;
+ if (!region->data->size)
+ {
+ region->extents.x2 = region->extents.x1;
+ region->extents.y2 = region->extents.y1;
+ return;
+ }
+
+ box = PIXREGION_BOXPTR(region);
+ boxEnd = PIXREGION_END(region);
+
+ /*
+ * Since box is the first rectangle in the region, it must have the
+ * smallest y1 and since boxEnd is the last rectangle in the region,
+ * it must have the largest y2, because of banding. Initialize x1 and
+ * x2 from box and boxEnd, resp., as good things to initialize them
+ * to...
+ */
+ region->extents.x1 = box->x1;
+ region->extents.y1 = box->y1;
+ region->extents.x2 = boxEnd->x2;
+ region->extents.y2 = boxEnd->y2;
+
+ RT_ASSERT(region->extents.y1 < region->extents.y2);
+ while (box <= boxEnd)
+ {
+ if (box->x1 < region->extents.x1)
+ region->extents.x1 = box->x1;
+ if (box->x2 > region->extents.x2)
+ region->extents.x2 = box->x2;
+ box++;
+ };
+
+ RT_ASSERT(region->extents.x1 < region->extents.x2);
+}
+
+/*======================================================================
+ * Region Intersection
+ *====================================================================*/
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_region_intersectO --
+ * Handle an overlapping band for rtgui_region_intersect.
+ *
+ * Results:
+ * RTGUI_REGION_STATUS_SUCCESS if successful.
+ *
+ * Side Effects:
+ * Rectangles may be added to the region.
+ *
+ *-----------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static rtgui_region_status_t
+rtgui_region_intersectO (
+ rtgui_region_t *region,
+ rtgui_rect_t *r1,
+ rtgui_rect_t *r1End,
+ rtgui_rect_t *r2,
+ rtgui_rect_t *r2End,
+ short y1,
+ short y2,
+ int *pOverlap)
+{
+ int x1;
+ int x2;
+ rtgui_rect_t * pNextRect;
+
+ pNextRect = PIXREGION_TOP(region);
+
+ RT_ASSERT(y1 < y2);
+ RT_ASSERT(r1 != r1End && r2 != r2End);
+
+ do
+ {
+ x1 = RTGUI_MAX(r1->x1, r2->x1);
+ x2 = RTGUI_MIN(r1->x2, r2->x2);
+
+ /*
+ * If there's any overlap between the two rectangles, add that
+ * overlap to the new region.
+ */
+ if (x1 < x2)
+ NEWRECT(region, pNextRect, x1, y1, x2, y2);
+
+ /*
+ * Advance the pointer(s) with the leftmost right side, since the next
+ * rectangle on that list may still overlap the other region's
+ * current rectangle.
+ */
+ if (r1->x2 == x2)
+ {
+ r1++;
+ }
+ if (r2->x2 == x2)
+ {
+ r2++;
+ }
+ }
+ while ((r1 != r1End) && (r2 != r2End));
+
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+rtgui_region_status_t
+rtgui_region_intersect(rtgui_region_t *newReg,
+ rtgui_region_t *reg1,
+ rtgui_region_t *reg2)
+{
+ good(reg1);
+ good(reg2);
+ good(newReg);
+ /* check for trivial reject */
+ if (PIXREGION_NIL(reg1) || PIXREGION_NIL(reg2) ||
+ !EXTENTCHECK(&reg1->extents, &reg2->extents))
+ {
+ /* Covers about 20% of all cases */
+ freeData(newReg);
+ newReg->extents.x2 = newReg->extents.x1;
+ newReg->extents.y2 = newReg->extents.y1;
+ if (PIXREGION_NAR(reg1) || PIXREGION_NAR(reg2))
+ {
+ newReg->data = &rtgui_brokendata;
+ return RTGUI_REGION_STATUS_FAILURE;
+ }
+ else
+ newReg->data = &rtgui_region_emptydata;
+ }
+ else if (!reg1->data && !reg2->data)
+ {
+ /* Covers about 80% of cases that aren't trivially rejected */
+ newReg->extents.x1 = RTGUI_MAX(reg1->extents.x1, reg2->extents.x1);
+ newReg->extents.y1 = RTGUI_MAX(reg1->extents.y1, reg2->extents.y1);
+ newReg->extents.x2 = RTGUI_MIN(reg1->extents.x2, reg2->extents.x2);
+ newReg->extents.y2 = RTGUI_MIN(reg1->extents.y2, reg2->extents.y2);
+ freeData(newReg);
+ newReg->data = (rtgui_region_data_t *)RT_NULL;
+ }
+ else if (!reg2->data && SUBSUMES(&reg2->extents, &reg1->extents))
+ {
+ return rtgui_region_copy(newReg, reg1);
+ }
+ else if (!reg1->data && SUBSUMES(&reg1->extents, &reg2->extents))
+ {
+ return rtgui_region_copy(newReg, reg2);
+ }
+ else if (reg1 == reg2)
+ {
+ return rtgui_region_copy(newReg, reg1);
+ }
+ else
+ {
+ /* General purpose intersection */
+ int overlap; /* result ignored */
+ if (!rtgui_op(newReg, reg1, reg2, rtgui_region_intersectO, RTGUI_REGION_STATUS_FAILURE, RTGUI_REGION_STATUS_FAILURE,
+ &overlap))
+ return RTGUI_REGION_STATUS_FAILURE;
+ rtgui_set_extents(newReg);
+ }
+
+ good(newReg);
+ return(RTGUI_REGION_STATUS_SUCCESS);
+}
+
+rtgui_region_status_t
+rtgui_region_intersect_rect(rtgui_region_t *newReg,
+ rtgui_region_t *reg1,
+ rtgui_rect_t *rect)
+{
+ rtgui_region_t region;
+
+ region.data = RT_NULL;
+ region.extents.x1 = rect->x1;
+ region.extents.y1 = rect->y1;
+ region.extents.x2 = rect->x2;
+ region.extents.y2 = rect->y2;
+
+ return rtgui_region_intersect(newReg, reg1, &region);
+}
+
+#define MERGERECT(r) \
+{ \
+ if (r->x1 <= x2) { \
+ /* Merge with current rectangle */ \
+ if (r->x1 < x2) *pOverlap = RTGUI_REGION_STATUS_SUCCESS; \
+ if (x2 < r->x2) x2 = r->x2; \
+ } else { \
+ /* Add current rectangle, start new one */ \
+ NEWRECT(region, pNextRect, x1, y1, x2, y2); \
+ x1 = r->x1; \
+ x2 = r->x2; \
+ } \
+ r++; \
+}
+
+/*======================================================================
+ * Region Union
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_region_unionO --
+ * Handle an overlapping band for the union operation. Picks the
+ * left-most rectangle each time and merges it into the region.
+ *
+ * Results:
+ * RTGUI_REGION_STATUS_SUCCESS if successful.
+ *
+ * Side Effects:
+ * region is overwritten.
+ * pOverlap is set to RTGUI_REGION_STATUS_SUCCESS if any boxes overlap.
+ *
+ *-----------------------------------------------------------------------
+ */
+static rtgui_region_status_t
+rtgui_region_unionO (
+ rtgui_region_t *region,
+ rtgui_rect_t *r1,
+ rtgui_rect_t *r1End,
+ rtgui_rect_t *r2,
+ rtgui_rect_t *r2End,
+ short y1,
+ short y2,
+ int *pOverlap)
+{
+ rtgui_rect_t * pNextRect;
+ int x1; /* left and right side of current union */
+ int x2;
+
+ RT_ASSERT (y1 < y2);
+ RT_ASSERT(r1 != r1End && r2 != r2End);
+
+ pNextRect = PIXREGION_TOP(region);
+
+ /* Start off current rectangle */
+ if (r1->x1 < r2->x1)
+ {
+ x1 = r1->x1;
+ x2 = r1->x2;
+ r1++;
+ }
+ else
+ {
+ x1 = r2->x1;
+ x2 = r2->x2;
+ r2++;
+ }
+ while (r1 != r1End && r2 != r2End)
+ {
+ if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2);
+ }
+
+ /* Finish off whoever (if any) is left */
+ if (r1 != r1End)
+ {
+ do
+ {
+ MERGERECT(r1);
+ }
+ while (r1 != r1End);
+ }
+ else if (r2 != r2End)
+ {
+ do
+ {
+ MERGERECT(r2);
+ }
+ while (r2 != r2End);
+ }
+
+ /* Add current rectangle */
+ NEWRECT(region, pNextRect, x1, y1, x2, y2);
+
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+/* Convenience function for perforRTGUI_MINg union of region with a single rectangle */
+rtgui_region_status_t
+rtgui_region_union_rect(rtgui_region_t *dest, rtgui_region_t *source, rtgui_rect_t* rect)
+{
+ rtgui_region_t region;
+
+ region.data = RT_NULL;
+ region.extents.x1 = rect->x1;
+ region.extents.y1 = rect->y1;
+ region.extents.x2 = rect->x2;
+ region.extents.y2 = rect->y2;
+
+ return rtgui_region_union (dest, source, &region);
+}
+
+rtgui_region_status_t
+rtgui_region_union(rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_region_t *reg2)
+{
+ int overlap; /* result ignored */
+
+ /* Return RTGUI_REGION_STATUS_SUCCESS if some overlap between reg1, reg2 */
+ good(reg1);
+ good(reg2);
+ good(newReg);
+ /* checks all the simple cases */
+
+ /*
+ * Region 1 and 2 are the same
+ */
+ if (reg1 == reg2)
+ {
+ return rtgui_region_copy(newReg, reg1);
+ }
+
+ /*
+ * Region 1 is empty
+ */
+ if (PIXREGION_NIL(reg1))
+ {
+ if (PIXREGION_NAR(reg1)) return rtgui_break (newReg);
+ if (newReg != reg2)
+ return rtgui_region_copy(newReg, reg2);
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+
+ /*
+ * Region 2 is empty
+ */
+ if (PIXREGION_NIL(reg2))
+ {
+ if (PIXREGION_NAR(reg2)) return rtgui_break (newReg);
+ if (newReg != reg1)
+ return rtgui_region_copy(newReg, reg1);
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+
+ /*
+ * Region 1 completely subsumes region 2
+ */
+ if (!reg1->data && SUBSUMES(&reg1->extents, &reg2->extents))
+ {
+ if (newReg != reg1)
+ return rtgui_region_copy(newReg, reg1);
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+
+ /*
+ * Region 2 completely subsumes region 1
+ */
+ if (!reg2->data && SUBSUMES(&reg2->extents, &reg1->extents))
+ {
+ if (newReg != reg2)
+ return rtgui_region_copy(newReg, reg2);
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+
+ if (!rtgui_op(newReg, reg1, reg2, rtgui_region_unionO, RTGUI_REGION_STATUS_SUCCESS, RTGUI_REGION_STATUS_SUCCESS, &overlap))
+ return RTGUI_REGION_STATUS_FAILURE;
+
+ newReg->extents.x1 = RTGUI_MIN(reg1->extents.x1, reg2->extents.x1);
+ newReg->extents.y1 = RTGUI_MIN(reg1->extents.y1, reg2->extents.y1);
+ newReg->extents.x2 = RTGUI_MAX(reg1->extents.x2, reg2->extents.x2);
+ newReg->extents.y2 = RTGUI_MAX(reg1->extents.y2, reg2->extents.y2);
+ good(newReg);
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+/*======================================================================
+ * Batch Rectangle Union
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_region_append --
+ *
+ * "Append" the rgn rectangles onto the end of dstrgn, maintaining
+ * knowledge of YX-banding when it's easy. Otherwise, dstrgn just
+ * becomes a non-y-x-banded random collection of rectangles, and not
+ * yet a true region. After a sequence of appends, the caller must
+ * call rtgui_region_validate to ensure that a valid region is constructed.
+ *
+ * Results:
+ * RTGUI_REGION_STATUS_SUCCESS if successful.
+ *
+ * Side Effects:
+ * dstrgn is modified if rgn has rectangles.
+ *
+ */
+rtgui_region_status_t
+rtgui_region_append(rtgui_region_t *dstrgn,
+ rtgui_region_t *rgn)
+{
+ int numRects, dnumRects, size;
+ rtgui_rect_t *new, *old;
+ int prepend;
+
+ if (PIXREGION_NAR(rgn)) return rtgui_break (dstrgn);
+
+ if (!rgn->data && (dstrgn->data == &rtgui_region_emptydata))
+ {
+ dstrgn->extents = rgn->extents;
+ dstrgn->data = (rtgui_region_data_t *)RT_NULL;
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+
+ numRects = PIXREGION_NUM_RECTS(rgn);
+ if (!numRects)
+ return RTGUI_REGION_STATUS_SUCCESS;
+ prepend = RTGUI_REGION_STATUS_FAILURE;
+ size = numRects;
+ dnumRects = PIXREGION_NUM_RECTS(dstrgn);
+ if (!dnumRects && (size < 200))
+ size = 200; /* XXX pick numbers out of a hat */
+ RECTALLOC(dstrgn, size);
+ old = PIXREGION_RECTS(rgn);
+ if (!dnumRects)
+ dstrgn->extents = rgn->extents;
+ else if (dstrgn->extents.x2 > dstrgn->extents.x1)
+ {
+ rtgui_rect_t *first, *last;
+
+ first = old;
+ last = PIXREGION_BOXPTR(dstrgn) + (dnumRects - 1);
+ if ((first->y1 > last->y2) ||
+ ((first->y1 == last->y1) && (first->y2 == last->y2) &&
+ (first->x1 > last->x2)))
+ {
+ if (rgn->extents.x1 < dstrgn->extents.x1)
+ dstrgn->extents.x1 = rgn->extents.x1;
+ if (rgn->extents.x2 > dstrgn->extents.x2)
+ dstrgn->extents.x2 = rgn->extents.x2;
+ dstrgn->extents.y2 = rgn->extents.y2;
+ }
+ else
+ {
+ first = PIXREGION_BOXPTR(dstrgn);
+ last = old + (numRects - 1);
+ if ((first->y1 > last->y2) ||
+ ((first->y1 == last->y1) && (first->y2 == last->y2) &&
+ (first->x1 > last->x2)))
+ {
+ prepend = RTGUI_REGION_STATUS_SUCCESS;
+ if (rgn->extents.x1 < dstrgn->extents.x1)
+ dstrgn->extents.x1 = rgn->extents.x1;
+ if (rgn->extents.x2 > dstrgn->extents.x2)
+ dstrgn->extents.x2 = rgn->extents.x2;
+ dstrgn->extents.y1 = rgn->extents.y1;
+ }
+ else
+ dstrgn->extents.x2 = dstrgn->extents.x1;
+ }
+ }
+ if (prepend)
+ {
+ new = PIXREGION_BOX(dstrgn, numRects);
+ if (dnumRects == 1)
+ *new = *PIXREGION_BOXPTR(dstrgn);
+ else
+ rt_memmove((char *)new,(char *)PIXREGION_BOXPTR(dstrgn),
+ dnumRects * sizeof(rtgui_rect_t));
+ new = PIXREGION_BOXPTR(dstrgn);
+ }
+ else
+ new = PIXREGION_BOXPTR(dstrgn) + dnumRects;
+ if (numRects == 1)
+ *new = *old;
+ else
+ rt_memmove((char *)new, (char *)old, numRects * sizeof(rtgui_rect_t));
+ dstrgn->data->numRects += numRects;
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+#define ExchangeRects(a, b) \
+{ \
+ rtgui_rect_t t; \
+ t = rects[a]; \
+ rects[a] = rects[b]; \
+ rects[b] = t; \
+}
+
+static void QuickSortRects(rtgui_rect_t rects[], int numRects)
+{
+ int y1;
+ int x1;
+ int i, j;
+ rtgui_rect_t *r;
+
+ /* Always called with numRects > 1 */
+
+ do
+ {
+ if (numRects == 2)
+ {
+ if (rects[0].y1 > rects[1].y1 ||
+ (rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
+ ExchangeRects(0, 1);
+ return;
+ }
+
+ /* Choose partition element, stick in location 0 */
+ ExchangeRects(0, numRects >> 1);
+ y1 = rects[0].y1;
+ x1 = rects[0].x1;
+
+ /* Partition array */
+ i = 0;
+ j = numRects;
+ do
+ {
+ r = &(rects[i]);
+ do
+ {
+ r++;
+ i++;
+ }
+ while (i != numRects &&
+ (r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
+ r = &(rects[j]);
+ do
+ {
+ r--;
+ j--;
+ }
+ while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
+ if (i < j)
+ ExchangeRects(i, j);
+ }
+ while (i < j);
+
+ /* Move partition element back to middle */
+ ExchangeRects(0, j);
+
+ /* Recurse */
+ if (numRects-j-1 > 1)
+ QuickSortRects(&rects[j+1], numRects-j-1);
+ numRects = j;
+ }
+ while (numRects > 1);
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_region_validate --
+ *
+ * Take a ``region'' which is a non-y-x-banded random collection of
+ * rectangles, and compute a nice region which is the union of all the
+ * rectangles.
+ *
+ * Results:
+ * RTGUI_REGION_STATUS_SUCCESS if successful.
+ *
+ * Side Effects:
+ * The passed-in ``region'' may be modified.
+ * pOverlap set to RTGUI_REGION_STATUS_SUCCESS if any retangles overlapped, else RTGUI_REGION_STATUS_FAILURE;
+ *
+ * Strategy:
+ * Step 1. Sort the rectangles into ascending order with primary key y1
+ * and secondary key x1.
+ *
+ * Step 2. Split the rectangles into the RTGUI_MINimum number of proper y-x
+ * banded regions. This may require horizontally merging
+ * rectangles, and vertically coalescing bands. With any luck,
+ * this step in an identity transformation (ala the Box widget),
+ * or a coalescing into 1 box (ala Menus).
+ *
+ * Step 3. Merge the separate regions down to a single region by calling
+ * rtgui_region_union. Maximize the work each rtgui_region_union call does by using
+ * a binary merge.
+ *
+ *-----------------------------------------------------------------------
+ */
+rtgui_region_status_t rtgui_region_validate(rtgui_region_t * badreg,
+ int *pOverlap)
+{
+ /* Descriptor for regions under construction in Step 2. */
+ typedef struct
+ {
+ rtgui_region_t reg;
+ int prevBand;
+ int curBand;
+ }
+ RegionInfo;
+
+ int numRects; /* Original numRects for badreg */
+ RegionInfo *ri; /* Array of current regions */
+ int numRI; /* Number of entries used in ri */
+ int sizeRI; /* Number of entries available in ri */
+ int i; /* Index into rects */
+ int j; /* Index into ri */
+ RegionInfo *rit; /* &ri[j] */
+ rtgui_region_t * reg; /* ri[j].reg */
+ rtgui_rect_t * box; /* Current box in rects */
+ rtgui_rect_t * riBox; /* Last box in ri[j].reg */
+ rtgui_region_t * hreg; /* ri[j_half].reg */
+ rtgui_region_status_t ret = RTGUI_REGION_STATUS_SUCCESS;
+
+ *pOverlap = RTGUI_REGION_STATUS_FAILURE;
+ if (!badreg->data)
+ {
+ good(badreg);
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+ numRects = badreg->data->numRects;
+ if (!numRects)
+ {
+ if (PIXREGION_NAR(badreg))
+ return RTGUI_REGION_STATUS_FAILURE;
+ good(badreg);
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+ if (badreg->extents.x1 < badreg->extents.x2)
+ {
+ if ((numRects) == 1)
+ {
+ freeData(badreg);
+ badreg->data = (rtgui_region_data_t *) RT_NULL;
+ }
+ else
+ {
+ DOWNSIZE(badreg, numRects);
+ }
+ good(badreg);
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+
+ /* Step 1: Sort the rects array into ascending (y1, x1) order */
+ QuickSortRects(PIXREGION_BOXPTR(badreg), numRects);
+
+ /* Step 2: Scatter the sorted array into the RTGUI_MINimum number of regions */
+
+ /* Set up the first region to be the first rectangle in badreg */
+ /* Note that step 2 code will never overflow the ri[0].reg rects array */
+ ri = (RegionInfo *) rtgui_malloc(4 * sizeof(RegionInfo));
+ if (!ri) return rtgui_break (badreg);
+ sizeRI = 4;
+ numRI = 1;
+ ri[0].prevBand = 0;
+ ri[0].curBand = 0;
+ ri[0].reg = *badreg;
+ box = PIXREGION_BOXPTR(&ri[0].reg);
+ ri[0].reg.extents = *box;
+ ri[0].reg.data->numRects = 1;
+
+ /* Now scatter rectangles into the RTGUI_MINimum set of valid regions. If the
+ next rectangle to be added to a region would force an existing rectangle
+ in the region to be split up in order to maintain y-x banding, just
+ forget it. Try the next region. If it doesn't fit cleanly into any
+ region, make a new one. */
+
+ for (i = numRects; --i > 0;)
+ {
+ box++;
+ /* Look for a region to append box to */
+ for (j = numRI, rit = ri; --j >= 0; rit++)
+ {
+ reg = &rit->reg;
+ riBox = PIXREGION_END(reg);
+
+ if (box->y1 == riBox->y1 && box->y2 == riBox->y2)
+ {
+ /* box is in same band as riBox. Merge or append it */
+ if (box->x1 <= riBox->x2)
+ {
+ /* Merge it with riBox */
+ if (box->x1 < riBox->x2) *pOverlap = RTGUI_REGION_STATUS_SUCCESS;
+ if (box->x2 > riBox->x2) riBox->x2 = box->x2;
+ }
+ else
+ {
+ RECTALLOC_BAIL(reg, 1, bail);
+ *PIXREGION_TOP(reg) = *box;
+ reg->data->numRects++;
+ }
+ goto NextRect; /* So sue me */
+ }
+ else if (box->y1 >= riBox->y2)
+ {
+ /* Put box into new band */
+ if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
+ if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1;
+ Coalesce(reg, rit->prevBand, rit->curBand);
+ rit->curBand = reg->data->numRects;
+ RECTALLOC_BAIL(reg, 1, bail);
+ *PIXREGION_TOP(reg) = *box;
+ reg->data->numRects++;
+ goto NextRect;
+ }
+ /* Well, this region was inappropriate. Try the next one. */
+ } /* for j */
+
+ /* Uh-oh. No regions were appropriate. Create a new one. */
+ if (sizeRI == numRI)
+ {
+ /* Oops, allocate space for new region information */
+ sizeRI <<= 1;
+ rit = (RegionInfo *) rt_realloc(ri, sizeRI * sizeof(RegionInfo));
+ if (!rit)
+ goto bail;
+ ri = rit;
+ rit = &ri[numRI];
+ }
+ numRI++;
+ rit->prevBand = 0;
+ rit->curBand = 0;
+ rit->reg.extents = *box;
+ rit->reg.data = (rtgui_region_data_t *)RT_NULL;
+ if (!rtgui_rect_alloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */
+ goto bail;
+NextRect:
+ ;
+ } /* for i */
+
+ /* Make a final pass over each region in order to Coalesce and set
+ extents.x2 and extents.y2 */
+
+ for (j = numRI, rit = ri; --j >= 0; rit++)
+ {
+ reg = &rit->reg;
+ riBox = PIXREGION_END(reg);
+ reg->extents.y2 = riBox->y2;
+ if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
+ Coalesce(reg, rit->prevBand, rit->curBand);
+ if (reg->data->numRects == 1) /* keep unions happy below */
+ {
+ freeData(reg);
+ reg->data = (rtgui_region_data_t *)RT_NULL;
+ }
+ }
+
+ /* Step 3: Union all regions into a single region */
+ while (numRI > 1)
+ {
+ int half = numRI/2;
+ for (j = numRI & 1; j < (half + (numRI & 1)); j++)
+ {
+ reg = &ri[j].reg;
+ hreg = &ri[j+half].reg;
+ if (!rtgui_op(reg, reg, hreg, rtgui_region_unionO, RTGUI_REGION_STATUS_SUCCESS, RTGUI_REGION_STATUS_SUCCESS, pOverlap))
+ ret = RTGUI_REGION_STATUS_FAILURE;
+ if (hreg->extents.x1 < reg->extents.x1)
+ reg->extents.x1 = hreg->extents.x1;
+ if (hreg->extents.y1 < reg->extents.y1)
+ reg->extents.y1 = hreg->extents.y1;
+ if (hreg->extents.x2 > reg->extents.x2)
+ reg->extents.x2 = hreg->extents.x2;
+ if (hreg->extents.y2 > reg->extents.y2)
+ reg->extents.y2 = hreg->extents.y2;
+ freeData(hreg);
+ }
+ numRI -= half;
+ }
+ *badreg = ri[0].reg;
+ rtgui_free(ri);
+ good(badreg);
+ return ret;
+
+bail:
+ for (i = 0; i < numRI; i++)
+ freeData(&ri[i].reg);
+ rtgui_free (ri);
+
+ return rtgui_break (badreg);
+}
+
+/*======================================================================
+ * Region Subtraction
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_region_subtractO --
+ * Overlapping band subtraction. x1 is the left-most point not yet
+ * checked.
+ *
+ * Results:
+ * RTGUI_REGION_STATUS_SUCCESS if successful.
+ *
+ * Side Effects:
+ * region may have rectangles added to it.
+ *
+ *-----------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static rtgui_region_status_t
+rtgui_region_subtractO (
+ rtgui_region_t *region,
+ rtgui_rect_t *r1,
+ rtgui_rect_t *r1End,
+ rtgui_rect_t *r2,
+ rtgui_rect_t *r2End,
+ short y1,
+ short y2,
+ int *pOverlap)
+{
+ rtgui_rect_t * pNextRect;
+ int x1;
+
+ x1 = r1->x1;
+
+ RT_ASSERT(y1<y2);
+ RT_ASSERT(r1 != r1End && r2 != r2End);
+
+ pNextRect = PIXREGION_TOP(region);
+
+ do
+ {
+ if (r2->x2 <= x1)
+ {
+ /*
+ * Subtrahend entirely to left of minuend: go to next subtrahend.
+ */
+ r2++;
+ }
+ else if (r2->x1 <= x1)
+ {
+ /*
+ * Subtrahend preceeds RTGUI_MINuend: nuke left edge of minuend.
+ */
+ x1 = r2->x2;
+ if (x1 >= r1->x2)
+ {
+ /*
+ * Minuend completely covered: advance to next minuend and
+ * reset left fence to edge of new RTGUI_MINuend.
+ */
+ r1++;
+ if (r1 != r1End)
+ x1 = r1->x1;
+ }
+ else
+ {
+ /*
+ * Subtrahend now used up since it doesn't extend beyond
+ * minuend
+ */
+ r2++;
+ }
+ }
+ else if (r2->x1 < r1->x2)
+ {
+ /*
+ * Left part of subtrahend covers part of minuend: add uncovered
+ * part of minuend to region and skip to next subtrahend.
+ */
+ RT_ASSERT(x1<r2->x1);
+ NEWRECT(region, pNextRect, x1, y1, r2->x1, y2);
+
+ x1 = r2->x2;
+ if (x1 >= r1->x2)
+ {
+ /*
+ * Minuend used up: advance to new...
+ */
+ r1++;
+ if (r1 != r1End)
+ x1 = r1->x1;
+ }
+ else
+ {
+ /*
+ * Subtrahend used up
+ */
+ r2++;
+ }
+ }
+ else
+ {
+ /*
+ * Minuend used up: add any remaining piece before advancing.
+ */
+ if (r1->x2 > x1)
+ NEWRECT(region, pNextRect, x1, y1, r1->x2, y2);
+ r1++;
+ if (r1 != r1End)
+ x1 = r1->x1;
+ }
+ }
+ while ((r1 != r1End) && (r2 != r2End));
+
+ /*
+ * Add remaining minuend rectangles to region.
+ */
+ while (r1 != r1End)
+ {
+ RT_ASSERT(x1<r1->x2);
+ NEWRECT(region, pNextRect, x1, y1, r1->x2, y2);
+ r1++;
+ if (r1 != r1End)
+ x1 = r1->x1;
+ }
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_region_subtract --
+ * Subtract regS from regM and leave the result in regD.
+ * S stands for subtrahend, M for minuend and D for difference.
+ *
+ * Results:
+ * RTGUI_REGION_STATUS_SUCCESS if successful.
+ *
+ * Side Effects:
+ * regD is overwritten.
+ *
+ *-----------------------------------------------------------------------
+ */
+rtgui_region_status_t
+rtgui_region_subtract(rtgui_region_t *regD,
+ rtgui_region_t *regM,
+ rtgui_region_t *regS)
+{
+ int overlap; /* result ignored */
+
+ good(regM);
+ good(regS);
+ good(regD);
+ /* check for trivial rejects */
+ if (PIXREGION_NIL(regM) || PIXREGION_NIL(regS) ||
+ !EXTENTCHECK(&regM->extents, &regS->extents))
+ {
+ if (PIXREGION_NAR (regS)) return rtgui_break (regD);
+ return rtgui_region_copy(regD, regM);
+ }
+ else if (regM == regS)
+ {
+ freeData(regD);
+ regD->extents.x2 = regD->extents.x1;
+ regD->extents.y2 = regD->extents.y1;
+ regD->data = &rtgui_region_emptydata;
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+
+ /* Add those rectangles in region 1 that aren't in region 2,
+ do yucky substraction for overlaps, and
+ just throw away rectangles in region 2 that aren't in region 1 */
+ if (!rtgui_op(regD, regM, regS, rtgui_region_subtractO, RTGUI_REGION_STATUS_SUCCESS, RTGUI_REGION_STATUS_FAILURE, &overlap))
+ return RTGUI_REGION_STATUS_FAILURE;
+
+ /*
+ * Can't alter RegD's extents before we call rtgui_op because
+ * it might be one of the source regions and rtgui_op depends
+ * on the extents of those regions being unaltered. Besides, this
+ * way there's no checking against rectangles that will be nuked
+ * due to coalescing, so we have to exaRTGUI_MINe fewer rectangles.
+ */
+ rtgui_set_extents(regD);
+ good(regD);
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+rtgui_region_status_t
+rtgui_region_subtract_rect (rtgui_region_t *regD, rtgui_region_t *regM, rtgui_rect_t* rect)
+{
+ rtgui_region_t region;
+
+ region.data = RT_NULL;
+ region.extents.x1 = rect->x1;
+ region.extents.y1 = rect->y1;
+ region.extents.x2 = rect->x2;
+ region.extents.y2 = rect->y2;
+
+ return rtgui_region_subtract(regD, regM, &region);
+}
+
+/*======================================================================
+ * Region Inversion
+ *====================================================================*/
+
+/*-
+ *-----------------------------------------------------------------------
+ * rtgui_region_inverse --
+ * Take a region and a box and return a region that is everything
+ * in the box but not in the region. The careful reader will note
+ * that this is the same as subtracting the region from the box...
+ *
+ * Results:
+ * RTGUI_REGION_STATUS_SUCCESS.
+ *
+ * Side Effects:
+ * newReg is overwritten.
+ *
+ *-----------------------------------------------------------------------
+ */
+rtgui_region_status_t
+rtgui_region_inverse(rtgui_region_t *newReg, /* Destination region */
+ rtgui_region_t *reg1, /* Region to invert */
+ rtgui_rect_t *invRect) /* Bounding box for inversion */
+{
+ rtgui_region_t invReg; /* Quick and dirty region made from the
+ * bounding box */
+ int overlap; /* result ignored */
+
+ good(reg1);
+ good(newReg);
+ /* check for trivial rejects */
+ if (PIXREGION_NIL(reg1) || !EXTENTCHECK(invRect, &reg1->extents))
+ {
+ if (PIXREGION_NAR(reg1)) return rtgui_break (newReg);
+ newReg->extents = *invRect;
+ freeData(newReg);
+ newReg->data = (rtgui_region_data_t *)RT_NULL;
+ return RTGUI_REGION_STATUS_SUCCESS;
+ }
+
+ /* Add those rectangles in region 1 that aren't in region 2,
+ do yucky substraction for overlaps, and
+ just throw away rectangles in region 2 that aren't in region 1 */
+ invReg.extents = *invRect;
+ invReg.data = (rtgui_region_data_t *)RT_NULL;
+ if (!rtgui_op(newReg, &invReg, reg1, rtgui_region_subtractO, RTGUI_REGION_STATUS_SUCCESS, RTGUI_REGION_STATUS_FAILURE, &overlap))
+ return RTGUI_REGION_STATUS_FAILURE;
+
+ /*
+ * Can't alter newReg's extents before we call rtgui_op because
+ * it might be one of the source regions and rtgui_op depends
+ * on the extents of those regions being unaltered. Besides, this
+ * way there's no checking against rectangles that will be nuked
+ * due to coalescing, so we have to exaRTGUI_MINe fewer rectangles.
+ */
+ rtgui_set_extents(newReg);
+ good(newReg);
+ return RTGUI_REGION_STATUS_SUCCESS;
+}
+
+/*
+ * RectIn(region, rect)
+ * This routine takes a pointer to a region and a pointer to a box
+ * and deterRTGUI_MINes if the box is outside/inside/partly inside the region.
+ *
+ * The idea is to travel through the list of rectangles trying to cover the
+ * passed box with them. Anytime a piece of the rectangle isn't covered
+ * by a band of rectangles, partOut is set RTGUI_REGION_STATUS_SUCCESS. Any time a rectangle in
+ * the region covers part of the box, partIn is set RTGUI_REGION_STATUS_SUCCESS. The process ends
+ * when either the box has been completely covered (we reached a band that
+ * doesn't overlap the box, partIn is RTGUI_REGION_STATUS_SUCCESS and partOut is false), the
+ * box has been partially covered (partIn == partOut == RTGUI_REGION_STATUS_SUCCESS -- because of
+ * the banding, the first time this is true we know the box is only
+ * partially in the region) or is outside the region (we reached a band
+ * that doesn't overlap the box at all and partIn is false)
+ */
+
+int rtgui_region_contains_rectangle(rtgui_region_t *region, rtgui_rect_t *prect)
+{
+ int x;
+ int y;
+ rtgui_rect_t * pbox;
+ rtgui_rect_t * pboxEnd;
+ int partIn, partOut;
+ int numRects;
+
+ good(region);
+ numRects = PIXREGION_NUM_RECTS(region);
+ /* useful optimization */
+ if (!numRects || !EXTENTCHECK(&region->extents, prect))
+ return(RTGUI_REGION_OUT);
+
+ if (numRects == 1)
+ {
+ /* We know that it must be rgnIN or rgnPART */
+ if (SUBSUMES(&region->extents, prect))
+ return(RTGUI_REGION_IN);
+ else
+ return(RTGUI_REGION_PART);
+ }
+
+ partOut = RTGUI_REGION_STATUS_FAILURE;
+ partIn = RTGUI_REGION_STATUS_FAILURE;
+
+ /* (x,y) starts at upper left of rect, moving to the right and down */
+ x = prect->x1;
+ y = prect->y1;
+
+ /* can stop when both partOut and partIn are RTGUI_REGION_STATUS_SUCCESS, or we reach prect->y2 */
+ for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
+ pbox != pboxEnd;
+ pbox++)
+ {
+
+ if (pbox->y2 <= y)
+ continue; /* getting up to speed or skipping remainder of band */
+
+ if (pbox->y1 > y)
+ {
+ partOut = RTGUI_REGION_STATUS_SUCCESS; /* missed part of rectangle above */
+ if (partIn || (pbox->y1 >= prect->y2))
+ break;
+ y = pbox->y1; /* x guaranteed to be == prect->x1 */
+ }
+
+ if (pbox->x2 <= x)
+ continue; /* not far enough over yet */
+
+ if (pbox->x1 > x)
+ {
+ partOut = RTGUI_REGION_STATUS_SUCCESS; /* missed part of rectangle to left */
+ if (partIn)
+ break;
+ }
+
+ if (pbox->x1 < prect->x2)
+ {
+ partIn = RTGUI_REGION_STATUS_SUCCESS; /* definitely overlap */
+ if (partOut)
+ break;
+ }
+
+ if (pbox->x2 >= prect->x2)
+ {
+ y = pbox->y2; /* finished with this band */
+ if (y >= prect->y2)
+ break;
+ x = prect->x1; /* reset x out to left again */
+ }
+ else
+ {
+ /*
+ * Because boxes in a band are maximal width, if the first box
+ * to overlap the rectangle doesn't completely cover it in that
+ * band, the rectangle must be partially out, since some of it
+ * will be uncovered in that band. partIn will have been set true
+ * by now...
+ */
+ partOut = RTGUI_REGION_STATUS_SUCCESS;
+ break;
+ }
+ }
+
+ return(partIn ? ((y < prect->y2) ? RTGUI_REGION_PART : RTGUI_REGION_IN) : RTGUI_REGION_OUT);
+}
+
+/* rtgui_region_translate (region, x, y)
+ translates in place
+*/
+void rtgui_region_translate (rtgui_region_t *region, int x, int y)
+{
+ int x1, x2, y1, y2;
+ int nbox;
+ rtgui_rect_t * pbox;
+
+ good(region);
+ region->extents.x1 = x1 = region->extents.x1 + x;
+ region->extents.y1 = y1 = region->extents.y1 + y;
+ region->extents.x2 = x2 = region->extents.x2 + x;
+ region->extents.y2 = y2 = region->extents.y2 + y;
+ if (((x1 - RTGUI_SHRT_MIN)|(y1 - RTGUI_SHRT_MIN)|(RTGUI_SHRT_MAX - x2)|(RTGUI_SHRT_MAX - y2)) >= 0)
+ {
+ nbox = region->data->numRects;
+ if (region->data && nbox)
+ {
+ for (pbox = PIXREGION_BOXPTR(region); nbox--; pbox++)
+ {
+ pbox->x1 += x;
+ pbox->y1 += y;
+ pbox->x2 += x;
+ pbox->y2 += y;
+ }
+ }
+ return;
+ }
+ if (((x2 - RTGUI_SHRT_MIN)|(y2 - RTGUI_SHRT_MIN)|(RTGUI_SHRT_MAX - x1)|(RTGUI_SHRT_MAX - y1)) <= 0)
+ {
+ region->extents.x2 = region->extents.x1;
+ region->extents.y2 = region->extents.y1;
+ freeData(region);
+ region->data = &rtgui_region_emptydata;
+ return;
+ }
+ if (x1 < RTGUI_SHRT_MIN)
+ region->extents.x1 = RTGUI_SHRT_MIN;
+ else if (x2 > RTGUI_SHRT_MAX)
+ region->extents.x2 = RTGUI_SHRT_MAX;
+ if (y1 < RTGUI_SHRT_MIN)
+ region->extents.y1 = RTGUI_SHRT_MIN;
+ else if (y2 > RTGUI_SHRT_MAX)
+ region->extents.y2 = RTGUI_SHRT_MAX;
+
+ nbox = region->data->numRects;
+ if (region->data && nbox)
+ {
+ rtgui_rect_t * pboxout;
+
+ for (pboxout = pbox = PIXREGION_BOXPTR(region); nbox--; pbox++)
+ {
+ pboxout->x1 = x1 = pbox->x1 + x;
+ pboxout->y1 = y1 = pbox->y1 + y;
+ pboxout->x2 = x2 = pbox->x2 + x;
+ pboxout->y2 = y2 = pbox->y2 + y;
+ if (((x2 - RTGUI_SHRT_MIN)|(y2 - RTGUI_SHRT_MIN)|
+ (RTGUI_SHRT_MAX - x1)|(RTGUI_SHRT_MAX - y1)) <= 0)
+ {
+ region->data->numRects--;
+ continue;
+ }
+ if (x1 < RTGUI_SHRT_MIN)
+ pboxout->x1 = RTGUI_SHRT_MIN;
+ else if (x2 > RTGUI_SHRT_MAX)
+ pboxout->x2 = RTGUI_SHRT_MAX;
+ if (y1 < RTGUI_SHRT_MIN)
+ pboxout->y1 = RTGUI_SHRT_MIN;
+ else if (y2 > RTGUI_SHRT_MAX)
+ pboxout->y2 = RTGUI_SHRT_MAX;
+ pboxout++;
+ }
+ if (pboxout != pbox)
+ {
+ if (region->data->numRects == 1)
+ {
+ region->extents = *PIXREGION_BOXPTR(region);
+ freeData(region);
+ region->data = (rtgui_region_data_t *)RT_NULL;
+ }
+ else
+ rtgui_set_extents(region);
+ }
+ }
+}
+
+void rtgui_region_reset(rtgui_region_t *region, rtgui_rect_t* rect)
+{
+ good(region);
+ freeData(region);
+
+ rtgui_region_init_with_extents(region, rect);
+}
+
+/* box is "return" value */
+int rtgui_region_contains_point(rtgui_region_t * region,
+ int x, int y,
+ rtgui_rect_t * box)
+{
+ rtgui_rect_t *pbox, *pboxEnd;
+ int numRects;
+
+ good(region);
+ numRects = PIXREGION_NUM_RECTS(region);
+ if (!numRects || !INBOX(&region->extents, x, y))
+ return -RT_ERROR;
+
+ if (numRects == 1)
+ {
+ *box = region->extents;
+ return RT_EOK;
+ }
+
+ for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
+ pbox != pboxEnd;
+ pbox++)
+ {
+ if (y >= pbox->y2)
+ continue; /* not there yet */
+ if ((y < pbox->y1) || (x < pbox->x1))
+ break; /* missed it */
+ if (x >= pbox->x2)
+ continue; /* not there yet */
+ *box = *pbox;
+ return RT_EOK;
+ }
+
+ return -RT_ERROR;
+}
+
+int rtgui_region_not_empty(rtgui_region_t * region)
+{
+ good(region);
+
+ return(!PIXREGION_NIL(region));
+}
+
+void rtgui_region_empty(rtgui_region_t * region)
+{
+ good(region);
+ freeData(region);
+
+ region->extents = rtgui_empty_rect;
+ region->data = &rtgui_region_emptydata;
+}
+
+rtgui_rect_t *rtgui_region_extents(rtgui_region_t * region)
+{
+ good(region);
+ return(&region->extents);
+}
+
+#define ExchangeSpans(a, b) \
+{ \
+ rtgui_point_t tpt; \
+ int tw; \
+ \
+ tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \
+ tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
+}
+
+/* ||| I should apply the merge sort code to rectangle sorting above, and see
+ if mapping time can be improved. But right now I've been at work 12 hours,
+ so forget it.
+*/
+
+static void QuickSortSpans(
+ rtgui_point_t spans[],
+ int widths[],
+ int numSpans)
+{
+ int y;
+ int i, j, m;
+ rtgui_point_t *r;
+
+ /* Always called with numSpans > 1 */
+ /* Sorts only by y, doesn't bother to sort by x */
+
+ do
+ {
+ if (numSpans < 9)
+ {
+ /* Do insertion sort */
+ int yprev;
+
+ yprev = spans[0].y;
+ i = 1;
+ do
+ { /* while i != numSpans */
+ y = spans[i].y;
+ if (yprev > y)
+ {
+ /* spans[i] is out of order. Move into proper location. */
+ rtgui_point_t tpt;
+ int tw, k;
+
+ for (j = 0; y >= spans[j].y; j++)
+ {}
+ tpt = spans[i];
+ tw = widths[i];
+ for (k = i; k != j; k--)
+ {
+ spans[k] = spans[k-1];
+ widths[k] = widths[k-1];
+ }
+ spans[j] = tpt;
+ widths[j] = tw;
+ y = spans[i].y;
+ } /* if out of order */
+ yprev = y;
+ i++;
+ }
+ while (i != numSpans);
+ return;
+ }
+
+ /* Choose partition element, stick in location 0 */
+ m = numSpans / 2;
+ if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
+ if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1);
+ if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
+ y = spans[0].y;
+
+ /* Partition array */
+ i = 0;
+ j = numSpans;
+ do
+ {
+ r = &(spans[i]);
+ do
+ {
+ r++;
+ i++;
+ }
+ while (i != numSpans && r->y < y);
+ r = &(spans[j]);
+ do
+ {
+ r--;
+ j--;
+ }
+ while (y < r->y);
+ if (i < j)
+ ExchangeSpans(i, j);
+ }
+ while (i < j);
+
+ /* Move partition element back to middle */
+ ExchangeSpans(0, j);
+
+ /* Recurse */
+ if (numSpans-j-1 > 1)
+ QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1);
+ numSpans = j;
+ }
+ while (numSpans > 1);
+}
+
+void rtgui_region_dump(rtgui_region_t* region)
+{
+ int num;
+ int i;
+ rtgui_rect_t * rects;
+
+ num = PIXREGION_NUM_RECTS(region);
+ rects = PIXREGION_RECTS(region);
+ rt_kprintf("extents: (%d,%d) (%d,%d)\n",
+ region->extents.x1, region->extents.y1,
+ region->extents.x2, region->extents.y2);
+
+ for (i = 0; i < num; i++)
+ {
+ rt_kprintf("box[%d]: (%d,%d) (%d,%d)\n", i,
+ rects[i].x1, rects[i].y1,
+ rects[i].x2, rects[i].y2);
+ }
+}
+
+void rtgui_rect_moveto(rtgui_rect_t *rect, int x, int y)
+{
+ rect->x1 += x;
+ rect->x2 += x;
+
+ rect->y1 += y;
+ rect->y2 += y;
+}
+
+void rtgui_rect_moveto_align(rtgui_rect_t *rect, rtgui_rect_t *to, int align)
+{
+ int dw, dh;
+ dw = 0;
+ dh = 0;
+
+ /* get delta width and height */
+ dw = rtgui_rect_width(*rect) - rtgui_rect_width(*to);
+ dh = rtgui_rect_height(*rect) - rtgui_rect_height(*to);
+ if (dw < 0) dw = 0;
+ if (dh < 0) dh = 0;
+
+ /* move to insider of rect */
+ rtgui_rect_moveto(to, rect->x1, rect->y1);
+
+ /* limited the destination rect to source rect */
+ if (dw == 0) to->x2 = rect->x2;
+ if (dh == 0) to->y2 = rect->y2;
+
+ /* align to right */
+ if (align & RTGUI_ALIGN_RIGHT)
+ {
+ to->x1 += dw;
+ to->x2 += dw;
+ }
+
+ /* align to bottom */
+ if (align & RTGUI_ALIGN_BOTTOM)
+ {
+ to->y1 += dh;
+ to->y2 += dh;
+ }
+
+ /* align to center horizontal */
+ if (align & RTGUI_ALIGN_CENTER_HORIZONTAL)
+ {
+ to->x1 += dw >> 1;
+ to->x2 += dw >> 1;
+ }
+
+ /* align to center vertical */
+ if (align & RTGUI_ALIGN_CENTER_VERTICAL)
+ {
+ to->y1 += dh >> 1;
+ to->y2 += dh >> 1;
+ }
+}
+
+void rtgui_rect_inflate(rtgui_rect_t *rect, int d)
+{
+ rect->x1 -= d;
+ rect->x2 += d;
+ rect->y1 -= d;
+ rect->y2 += d;
+}
+
+/* put the intersect of src rect and dest rect to dest */
+void rtgui_rect_intersect(rtgui_rect_t *src, rtgui_rect_t *dest)
+{
+ if (dest->x1 < src->x1) dest->x1 = src->x1;
+ if (dest->y1 < src->y1) dest->y1 = src->y1;
+ if (dest->x2 > src->x2) dest->x2 = src->x2;
+ if (dest->y2 > src->y2) dest->y2 = src->y2;
+}
+
+int rtgui_rect_contains_point(rtgui_rect_t *rect, int x, int y)
+{
+ if (INBOX(rect, x, y)) return RT_EOK;
+
+ return -RT_ERROR;
+}
+
+int rtgui_rect_is_intersect(rtgui_rect_t *rect1, rtgui_rect_t *rect2)
+{
+ if (INBOX(rect1, rect2->x1, rect2->y1) ||
+ INBOX(rect1, rect2->x1, rect2->y2) ||
+ INBOX(rect1, rect2->x2, rect2->y1) ||
+ INBOX(rect1, rect2->x2, rect2->y2))
+ {
+ return RT_EOK;
+ }
+ else if (INBOX(rect2, rect1->x1, rect1->y1) ||
+ INBOX(rect2, rect1->x1, rect1->y2) ||
+ INBOX(rect2, rect1->x2, rect1->y1) ||
+ INBOX(rect2, rect1->x2, rect1->y2))
+ {
+ return RT_EOK;
+ }
+
+ return -RT_ERROR;
+}
diff --git a/rtgui/common/rtgui_system.c b/rtgui/common/rtgui_system.c
index f1bbf2bd37..7288c83f55 100644
--- a/rtgui/common/rtgui_system.c
+++ b/rtgui/common/rtgui_system.c
@@ -40,18 +40,6 @@ void rtgui_system_server_init()
rtgui_server_init();
}
-void rtgui_system_app_init()
-{
- /* init launcher thread */
- rtgui_launcher_init();
-
- /* init pyim */
- // rtgui_pyim_init();
-
- /* init term win */
- // rtgui_term_init();
-}
-
/************************************************************************/
/* RTGUI Thread Wrapper */
/************************************************************************/
diff --git a/rtgui/common/rtgui_theme.c b/rtgui/common/rtgui_theme.c
index 7a875ae222..5b4a069c64 100644
--- a/rtgui/common/rtgui_theme.c
+++ b/rtgui/common/rtgui_theme.c
@@ -19,13 +19,14 @@
#include <rtgui/widgets/label.h>
#include <rtgui/widgets/textbox.h>
#include <rtgui/widgets/iconbox.h>
+#include <rtgui/widgets/title.h>
#include <rtgui/rtgui_theme.h>
#include <rtgui/rtgui_server.h>
#define WINTITLE_CB_WIDTH 14
#define WINTITLE_CB_HEIGHT 14
-static const char * close_unpressed_xpm[] = {
+static const rt_uint8_t *close_unpressed_xpm[] = {
"14 14 55 1",
" c None",
". c #DCDFEA",
@@ -97,7 +98,7 @@ static const char * close_unpressed_xpm[] = {
"#mnnnnnnnnnnm#",
"op@@@@@@@@@@po"};
-static const char * close_pressed_xpm[] = {
+static const rt_uint8_t *close_pressed_xpm[] = {
"14 14 66 1",
" c None",
". c #CED4EE",
@@ -191,9 +192,11 @@ void rtgui_theme_draw_win(struct rtgui_topwin* win)
/* init close box image */
if (close_pressed == RT_NULL)
- close_pressed = rtgui_image_create_from_mem("xpm", close_pressed_xpm, sizeof(close_pressed_xpm));
+ close_pressed = rtgui_image_create_from_mem("xpm",
+ (const rt_uint8_t*)close_pressed_xpm, sizeof(close_pressed_xpm));
if (close_unpressed == RT_NULL)
- close_unpressed = rtgui_image_create_from_mem("xpm", close_unpressed_xpm, sizeof(close_unpressed_xpm));
+ close_unpressed = rtgui_image_create_from_mem("xpm",
+ (const rt_uint8_t*)close_unpressed_xpm, sizeof(close_unpressed_xpm));
/* begin drawing */
dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(win->title));
@@ -437,3 +440,4 @@ void rtgui_theme_draw_iconbox(rtgui_iconbox_t* iconbox)
/* end drawing */
rtgui_dc_end_drawing(dc);
}
+
diff --git a/rtgui/include/rtgui/caret.h b/rtgui/include/rtgui/caret.h
new file mode 100644
index 0000000000..241f6cc889
--- /dev/null
+++ b/rtgui/include/rtgui/caret.h
@@ -0,0 +1,53 @@
+/*
+ * File : caret.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_CARET_H__
+#define __RTGUI_CARET_H__
+
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/widgets/widget.h>
+
+struct rtgui_caret
+{
+ /* show flag */
+ rt_bool_t is_show;
+ /* the show point of caret */
+ struct rtgui_point show_point;
+
+ /* widget owner */
+ struct rtgui_widget* owner;
+
+ /* caret buffer dc */
+ struct rtgui_dc *dc;
+
+ /* caret extent */
+ struct rtgui_rect extent;
+
+ /* the blink timer */
+ struct rtgui_timer* timer;
+ rt_int32_t timer_period;
+};
+typedef struct rtgui_caret rtgui_caret_t;
+
+struct rtgui_caret* rtgui_caret_create(struct rtgui_widget* owner);
+void rtgui_caret_destroy(struct rtgui_caret* caret);
+
+void rtgui_caret_show(struct rtgui_caret* caret, rt_base_t x, rt_base_t y);
+void rtgui_caret_hide(struct rtgui_caret* caret);
+void rtgui_caret_draw(struct rtgui_caret* caret);
+
+void rtgui_caret_set_point(struct rtgui_caret* caret, int x, int y);
+void rtgui_caret_set_box(struct rtgui_caret* caret, int w, int h);
+
+#endif
diff --git a/rtgui/include/rtgui/color.h b/rtgui/include/rtgui/color.h
new file mode 100644
index 0000000000..af45664a16
--- /dev/null
+++ b/rtgui/include/rtgui/color.h
@@ -0,0 +1,97 @@
+/*
+ * File : color.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_COLOR_H__
+#define __RTGUI_COLOR_H__
+
+#include <rtgui/rtgui.h>
+
+typedef unsigned long rtgui_color_t;
+#define RTGUI_ARGB(a, r, g, b) \
+ ((rtgui_color_t)(((rt_uint8_t)(r)|\
+ (((unsigned)(rt_uint8_t)(g))<<8))|\
+ (((unsigned long)(rt_uint8_t)(b))<<16)|\
+ (((unsigned long)(rt_uint8_t)(a))<<24)))
+#define RTGUI_RGB(r, g, b) RTGUI_ARGB(255, (r), (g), (b))
+
+#define RTGUI_RGB_R(c) ((c) & 0xff)
+#define RTGUI_RGB_G(c) (((c) >> 8) & 0xff)
+#define RTGUI_RGB_B(c) (((c) >> 16) & 0xff)
+#define RTGUI_RGB_A(c) (((c) >> 24) & 0xff)
+
+extern const rtgui_color_t default_foreground;
+extern const rtgui_color_t default_background;
+
+extern const rtgui_color_t red;
+extern const rtgui_color_t green;
+extern const rtgui_color_t blue;
+extern const rtgui_color_t black;
+extern const rtgui_color_t white;
+extern const rtgui_color_t high_light;
+extern const rtgui_color_t dark_grey;
+extern const rtgui_color_t light_grey;
+
+/*
+ * RTGUI default color format
+ * BBBB BBBB GGGG GGGG RRRR RRRR
+ */
+
+/* convert rtgui color to BBBBBGGGGGGRRRRR */
+rt_inline rt_uint16_t rtgui_color_to_565(rtgui_color_t c)
+{
+ rt_uint16_t pixel;
+
+ pixel = ((RTGUI_RGB_B(c)>> 3) << 11) | ((RTGUI_RGB_G(c) >> 2) << 5) | (RTGUI_RGB_R(c) >> 3);
+
+ return pixel;
+}
+
+rt_inline rtgui_color_t rtgui_color_from_565(rt_uint16_t pixel)
+{
+ rt_uint16_t r, g, b;
+ rtgui_color_t color;
+
+ r = pixel & 0x1f;
+ g = (pixel >> 5) & 0x3f;
+ b = (pixel >> 11) & 0x1f;
+
+ color = r * 8225 / 1024 + ((g * 4047 / 1024) << 8) + ((b * 8225 / 1024) << 16);
+
+ return color;
+}
+
+/* convert rtgui color to RRRRRGGGGGGBBBBB */
+rt_inline rt_uint16_t rtgui_color_to_565p(rtgui_color_t c)
+{
+ rt_uint16_t pixel;
+
+ pixel = ((RTGUI_RGB_R(c) >> 3) << 11) | ((RTGUI_RGB_G(c) >> 2) << 5) | (RTGUI_RGB_B(c)>> 3);
+ return pixel;
+}
+
+rt_inline rtgui_color_t rtgui_color_from_565p(rt_uint16_t pixel)
+{
+ rt_uint8_t r, g, b;
+ rtgui_color_t color;
+
+ r = (pixel >> 11) & 0x1f;
+ g = (pixel >> 5) & 0x3f;
+ b = pixel & 0x1f;
+
+ color = r * 8225 / 1024 + ((g * 4047 / 1024) << 8) + ((b * 8225 / 1024) << 16);
+
+ return color;
+}
+
+#endif
+
diff --git a/rtgui/include/rtgui/dc.h b/rtgui/include/rtgui/dc.h
new file mode 100644
index 0000000000..1bf7bc1ee3
--- /dev/null
+++ b/rtgui/include/rtgui/dc.h
@@ -0,0 +1,126 @@
+/*
+ * File : dc.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_DC_H__
+#define __RTGUI_DC_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/font.h>
+#include <rtgui/driver.h>
+#include <rtgui/widgets/widget.h>
+
+enum rtgui_dc_type
+{
+ RTGUI_DC_HW,
+ RTGUI_DC_BUFFER,
+};
+
+/* the abstract device context */
+struct rtgui_dc
+{
+ /* type of device context */
+ rt_uint32_t type;
+
+ /* interface */
+ void (*draw_point)(struct rtgui_dc* dc, int x, int y);
+ void (*draw_vline)(struct rtgui_dc* dc, int x, int y1, int y2);
+ void (*draw_hline)(struct rtgui_dc* dc, int x1, int x2, int y);
+ void (*fill_rect )(struct rtgui_dc* dc, rtgui_rect_t* rect);
+ void (*blit )(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect);
+
+ /* set and get color */
+ void (*set_color )(struct rtgui_dc* dc, rtgui_color_t color);
+ rtgui_color_t (*get_color)(struct rtgui_dc* dc);
+
+ /* set and get font */
+ void (*set_font )(struct rtgui_dc* dc, rtgui_font_t* font);
+ rtgui_font_t* (*get_font)(struct rtgui_dc* dc);
+ void (*set_textalign)(struct rtgui_dc* dc, rt_int32_t align);
+ rt_int32_t (*get_textalign)(struct rtgui_dc* dc);
+
+ /* get dc visible */
+ rt_bool_t (*get_visible)(struct rtgui_dc* dc);
+
+ /* get dc rect */
+ void (*get_rect )(struct rtgui_dc* dc, rtgui_rect_t* rect);
+
+ rt_bool_t (*fini )(struct rtgui_dc* dc);
+};
+
+/* hardware device context */
+struct rtgui_dc_hw
+{
+ struct rtgui_dc parent;
+
+ /* widget owner */
+ rtgui_widget_t* owner;
+
+ /* visible */
+ rt_bool_t visible;
+
+ /* display driver */
+ struct rtgui_graphic_driver* device;
+};
+
+/* create a buffer dc */
+struct rtgui_dc* rtgui_dc_buffer_create(int width, int height);
+rt_uint8_t* rtgui_dc_buffer_get_pixel(struct rtgui_dc* dc);
+
+/* create a hardware dc */
+struct rtgui_dc* rtgui_dc_hw_create(rtgui_widget_t* owner);
+struct rtgui_dc* rtgui_dc_begin_drawing(rtgui_widget_t* owner);
+void rtgui_dc_end_drawing(struct rtgui_dc* dc);
+
+/* destroy a dc */
+void rtgui_dc_destory(struct rtgui_dc* dc);
+
+void rtgui_dc_draw_point(struct rtgui_dc* dc, int x, int y);
+
+void rtgui_dc_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2);
+void rtgui_dc_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y);
+void rtgui_dc_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect);
+void rtgui_dc_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect);
+
+void rtgui_dc_set_color(struct rtgui_dc* dc, rtgui_color_t color);
+rtgui_color_t rtgui_dc_get_color(struct rtgui_dc* dc);
+
+void rtgui_dc_set_font(struct rtgui_dc* dc, rtgui_font_t* font);
+rtgui_font_t* rtgui_dc_get_font(struct rtgui_dc* dc);
+void rtgui_dc_set_textalign(struct rtgui_dc* dc, rt_int32_t align);
+rt_int32_t rtgui_dc_get_textalign(struct rtgui_dc* dc);
+
+rt_bool_t rtgui_dc_get_visible(struct rtgui_dc* dc);
+void rtgui_dc_get_rect(struct rtgui_dc*dc, rtgui_rect_t* rect);
+
+void rtgui_dc_draw_line (struct rtgui_dc* dc, int x1, int y1, int x2, int y2);
+void rtgui_dc_draw_rect (struct rtgui_dc* dc, struct rtgui_rect* rect);
+
+void rtgui_dc_draw_text (struct rtgui_dc* dc, const rt_uint8_t* text, struct rtgui_rect* rect);
+
+void rtgui_dc_draw_border(struct rtgui_dc* dc, rtgui_rect_t* rect, int flag);
+void rtgui_dc_draw_horizontal_line(struct rtgui_dc* dc, int x1, int x2, int y);
+void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2);
+void rtgui_dc_draw_arrow(struct rtgui_dc* dc, rtgui_rect_t* rect, int kind);
+void rtgui_dc_draw_focus_rect(struct rtgui_dc* dc, rtgui_rect_t* rect);
+
+void rtgui_dc_draw_polygon(struct rtgui_dc* dc, const int *vx, const int *vy, int count);
+void rtgui_dc_fill_polygon(struct rtgui_dc* dc, const int* vx, const int* vy, int count);
+
+void rtgui_dc_draw_circle(struct rtgui_dc* dc, int x, int y, int r);
+void rtgui_dc_fill_circle(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t r);
+void rtgui_dc_draw_arc(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r, rt_int16_t start, rt_int16_t end);
+
+void rtgui_dc_draw_ellipse(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry);
+void rtgui_dc_fill_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry);
+
+#endif
diff --git a/rtgui/include/rtgui/filerw.h b/rtgui/include/rtgui/filerw.h
new file mode 100644
index 0000000000..0a9395fbb6
--- /dev/null
+++ b/rtgui/include/rtgui/filerw.h
@@ -0,0 +1,47 @@
+/*
+ * File : filerw.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_FILERW_H__
+#define __RTGUI_FILERW_H__
+
+#include <rtgui/rtgui.h>
+
+#define RTGUI_FILE_SEEK_SET 0
+#define RTGUI_FILE_SEEK_CUR 1
+#define RTGUI_FILE_SEEK_END 2
+
+struct rtgui_filerw
+{
+ int (*seek) (struct rtgui_filerw *context, rt_off_t offset, int whence);
+ int (*read) (struct rtgui_filerw *context, void *buffer, rt_size_t size, rt_size_t count);
+ int (*write)(struct rtgui_filerw *context, const void *buffer, rt_size_t size, rt_size_t count);
+ int (*tell) (struct rtgui_filerw *context);
+ int (*eof) (struct rtgui_filerw *context);
+ int (*close)(struct rtgui_filerw *context);
+};
+typedef struct rtgui_filerw rtgui_filerw_t;
+
+struct rtgui_filerw* rtgui_filerw_create_file(const char* filename, const char* mode);
+struct rtgui_filerw* rtgui_filerw_create_mem(rt_uint8_t* mem, rt_size_t size);
+
+int rtgui_filerw_seek (struct rtgui_filerw* context, rt_off_t offset, int whence);
+int rtgui_filerw_read (struct rtgui_filerw* context, void* buffer, rt_size_t size, rt_size_t count);
+int rtgui_filerw_write(struct rtgui_filerw* context, const void* buffer, rt_size_t size, rt_size_t count);
+int rtgui_filerw_tell (struct rtgui_filerw* context);
+int rtgui_filerw_eof (struct rtgui_filerw* context);
+int rtgui_filerw_close(struct rtgui_filerw* context);
+
+/* get memory data from filerw memory object */
+rt_uint8_t* rtgui_filerw_mem_getdata(struct rtgui_filerw* context);
+
+#endif
diff --git a/rtgui/include/rtgui/font.h b/rtgui/include/rtgui/font.h
new file mode 100644
index 0000000000..db5b6857fc
--- /dev/null
+++ b/rtgui/include/rtgui/font.h
@@ -0,0 +1,88 @@
+/*
+ * File : font.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_FONT_H__
+#define __RTGUI_FONT_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/list.h>
+
+struct rtgui_font;
+struct rtgui_dc;
+struct rtgui_rect;
+
+struct rtgui_font_engine
+{
+ /* font engine function */
+ void (*font_init)(struct rtgui_font* font);
+ void (*font_load)(struct rtgui_font* font);
+
+ void (*font_draw_text)(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text,
+ rt_ubase_t len, struct rtgui_rect* rect);
+ void (*font_get_metrics)(struct rtgui_font* font, const rt_uint8_t* text, struct rtgui_rect* rect);
+};
+
+/*
+ * bitmap font engine
+ */
+/* bitmap font private data */
+struct rtgui_font_bitmap
+{
+ /* bitmap data */
+ const rt_uint8_t* bmp;
+
+ rt_uint16_t width;
+ rt_uint16_t height;
+
+ rt_uint8_t first_char;
+ rt_uint8_t last_char;
+};
+extern struct rtgui_font_engine bmp_font_engine;
+
+struct rtgui_font
+{
+ /* font name */
+ char* family;
+
+ /* font height */
+ rt_uint16_t height;
+
+ /* refer count */
+ rt_uint32_t refer_count;
+
+ /* font engine */
+ struct rtgui_font_engine* engine;
+
+ /* font private data */
+ void* data;
+
+ /* the font list */
+ rtgui_list_t list;
+};
+typedef struct rtgui_font rtgui_font_t;
+
+void rtgui_font_system_init(void);
+void rtgui_font_system_add_font(struct rtgui_font* font);
+void rtgui_font_system_remove_font(struct rtgui_font* font);
+struct rtgui_font* rtgui_font_default(void);
+void rtgui_font_set_defaut(struct rtgui_font* font);
+
+struct rtgui_font* rtgui_font_refer(const rt_uint8_t* family, rt_uint16_t height);
+void rtgui_font_derefer(struct rtgui_font* font);
+
+/* draw a text */
+void rtgui_font_draw(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect);
+int rtgui_font_get_string_width(struct rtgui_font* font, const rt_uint8_t* text);
+void rtgui_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, struct rtgui_rect* rect);
+
+#endif
diff --git a/rtgui/include/rtgui/image.h b/rtgui/include/rtgui/image.h
new file mode 100644
index 0000000000..68f6144ebe
--- /dev/null
+++ b/rtgui/include/rtgui/image.h
@@ -0,0 +1,63 @@
+/*
+ * File : image.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_IMAGE_H__
+#define __RTGUI_IMAGE_H__
+
+#include <rtgui/dc.h>
+#include <rtgui/filerw.h>
+#include <rtgui/region.h>
+
+struct rtgui_image;
+struct rtgui_image_engine
+{
+ const char* name;
+ struct rtgui_list_node list;
+
+ /* image engine function */
+ rt_bool_t (*image_check)(struct rtgui_filerw* file);
+
+ rt_bool_t (*image_load)(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
+ void (*image_unload)(struct rtgui_image* image);
+
+ void (*image_blit)(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
+};
+
+struct rtgui_image
+{
+ /* image metrics */
+ rt_uint16_t w, h;
+
+ /* image engine */
+ struct rtgui_image_engine* engine;
+
+ /* image private data */
+ void* data;
+};
+typedef struct rtgui_image rtgui_image_t;
+
+/* init rtgui image system */
+void rtgui_system_image_init(void);
+
+struct rtgui_image* rtgui_image_create_from_file(const char* type, const char* filename, rt_bool_t load);
+struct rtgui_image* rtgui_image_create_from_mem(const char* type, const rt_uint8_t* data, rt_size_t length);
+void rtgui_image_destroy(struct rtgui_image* image);
+
+/* register an image engine */
+void rtgui_image_register_engine(struct rtgui_image_engine* engine);
+
+/* blit an image on DC */
+void rtgui_image_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
+
+
+#endif
diff --git a/rtgui/include/rtgui/image_png.h b/rtgui/include/rtgui/image_png.h
new file mode 100644
index 0000000000..13aff657f9
--- /dev/null
+++ b/rtgui/include/rtgui/image_png.h
@@ -0,0 +1,19 @@
+/*
+ * File : image_png.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_IMAGE_PNG_H__
+#define __RTGUI_IMAGE_PNG_H__
+
+#include <rtgui/image.h>
+
+#endif
diff --git a/rtgui/include/rtgui/image_xpm.h b/rtgui/include/rtgui/image_xpm.h
new file mode 100644
index 0000000000..e580327f6d
--- /dev/null
+++ b/rtgui/include/rtgui/image_xpm.h
@@ -0,0 +1,21 @@
+/*
+ * File : image_xpm.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_IMAGE_XPM_H__
+#define __RTGUI_IMAGE_XPM_H__
+
+#include <rtgui/image.h>
+
+void rtgui_image_xpm_init(void);
+
+#endif
diff --git a/rtgui/include/rtgui/kbddef.h b/rtgui/include/rtgui/kbddef.h
new file mode 100644
index 0000000000..c078404c60
--- /dev/null
+++ b/rtgui/include/rtgui/kbddef.h
@@ -0,0 +1,293 @@
+/*
+ * File : kbddef.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __KBD_DEF_H__
+#define __KBD_DEF_H__
+
+/* The keyboard key have been cleverly chosen to map to ASCII */
+typedef enum
+{
+ RTGUIK_UNKNOWN = 0,
+ RTGUIK_FIRST = 0,
+ RTGUIK_BACKSPACE = 8,
+ RTGUIK_TAB = 9,
+ RTGUIK_CLEAR = 12,
+ RTGUIK_RETURN = 13,
+ RTGUIK_PAUSE = 19,
+ RTGUIK_ESCAPE = 27,
+ RTGUIK_SPACE = 32,
+ RTGUIK_EXCLAIM = 33,
+ RTGUIK_QUOTEDBL = 34,
+ RTGUIK_HASH = 35,
+ RTGUIK_DOLLAR = 36,
+ RTGUIK_AMPERSAND = 38,
+ RTGUIK_QUOTE = 39,
+ RTGUIK_LEFTPAREN = 40,
+ RTGUIK_RIGHTPAREN = 41,
+ RTGUIK_ASTERISK = 42,
+ RTGUIK_PLUS = 43,
+ RTGUIK_COMMA = 44,
+ RTGUIK_MINUS = 45,
+ RTGUIK_PERIOD = 46,
+ RTGUIK_SLASH = 47,
+ RTGUIK_0 = 48,
+ RTGUIK_1 = 49,
+ RTGUIK_2 = 50,
+ RTGUIK_3 = 51,
+ RTGUIK_4 = 52,
+ RTGUIK_5 = 53,
+ RTGUIK_6 = 54,
+ RTGUIK_7 = 55,
+ RTGUIK_8 = 56,
+ RTGUIK_9 = 57,
+ RTGUIK_COLON = 58,
+ RTGUIK_SEMICOLON = 59,
+ RTGUIK_LESS = 60,
+ RTGUIK_EQUALS = 61,
+ RTGUIK_GREATER = 62,
+ RTGUIK_QUESTION = 63,
+ RTGUIK_AT = 64,
+
+ /*
+ Skip uppercase letters
+ */
+ RTGUIK_LEFTBRACKET = 91,
+ RTGUIK_BACKSLASH = 92,
+ RTGUIK_RIGHTBRACKET = 93,
+ RTGUIK_CARET = 94,
+ RTGUIK_UNDERSCORE = 95,
+ RTGUIK_BACKQUOTE = 96,
+ RTGUIK_a = 97,
+ RTGUIK_b = 98,
+ RTGUIK_c = 99,
+ RTGUIK_d = 100,
+ RTGUIK_e = 101,
+ RTGUIK_f = 102,
+ RTGUIK_g = 103,
+ RTGUIK_h = 104,
+ RTGUIK_i = 105,
+ RTGUIK_j = 106,
+ RTGUIK_k = 107,
+ RTGUIK_l = 108,
+ RTGUIK_m = 109,
+ RTGUIK_n = 110,
+ RTGUIK_o = 111,
+ RTGUIK_p = 112,
+ RTGUIK_q = 113,
+ RTGUIK_r = 114,
+ RTGUIK_s = 115,
+ RTGUIK_t = 116,
+ RTGUIK_u = 117,
+ RTGUIK_v = 118,
+ RTGUIK_w = 119,
+ RTGUIK_x = 120,
+ RTGUIK_y = 121,
+ RTGUIK_z = 122,
+ RTGUIK_DELETE = 127,
+
+ /* International keyboard */
+ RTGUIK_WORLD_0 = 160, /* 0xA0 */
+ RTGUIK_WORLD_1 = 161,
+ RTGUIK_WORLD_2 = 162,
+ RTGUIK_WORLD_3 = 163,
+ RTGUIK_WORLD_4 = 164,
+ RTGUIK_WORLD_5 = 165,
+ RTGUIK_WORLD_6 = 166,
+ RTGUIK_WORLD_7 = 167,
+ RTGUIK_WORLD_8 = 168,
+ RTGUIK_WORLD_9 = 169,
+ RTGUIK_WORLD_10 = 170,
+ RTGUIK_WORLD_11 = 171,
+ RTGUIK_WORLD_12 = 172,
+ RTGUIK_WORLD_13 = 173,
+ RTGUIK_WORLD_14 = 174,
+ RTGUIK_WORLD_15 = 175,
+ RTGUIK_WORLD_16 = 176,
+ RTGUIK_WORLD_17 = 177,
+ RTGUIK_WORLD_18 = 178,
+ RTGUIK_WORLD_19 = 179,
+ RTGUIK_WORLD_20 = 180,
+ RTGUIK_WORLD_21 = 181,
+ RTGUIK_WORLD_22 = 182,
+ RTGUIK_WORLD_23 = 183,
+ RTGUIK_WORLD_24 = 184,
+ RTGUIK_WORLD_25 = 185,
+ RTGUIK_WORLD_26 = 186,
+ RTGUIK_WORLD_27 = 187,
+ RTGUIK_WORLD_28 = 188,
+ RTGUIK_WORLD_29 = 189,
+ RTGUIK_WORLD_30 = 190,
+ RTGUIK_WORLD_31 = 191,
+ RTGUIK_WORLD_32 = 192,
+ RTGUIK_WORLD_33 = 193,
+ RTGUIK_WORLD_34 = 194,
+ RTGUIK_WORLD_35 = 195,
+ RTGUIK_WORLD_36 = 196,
+ RTGUIK_WORLD_37 = 197,
+ RTGUIK_WORLD_38 = 198,
+ RTGUIK_WORLD_39 = 199,
+ RTGUIK_WORLD_40 = 200,
+ RTGUIK_WORLD_41 = 201,
+ RTGUIK_WORLD_42 = 202,
+ RTGUIK_WORLD_43 = 203,
+ RTGUIK_WORLD_44 = 204,
+ RTGUIK_WORLD_45 = 205,
+ RTGUIK_WORLD_46 = 206,
+ RTGUIK_WORLD_47 = 207,
+ RTGUIK_WORLD_48 = 208,
+ RTGUIK_WORLD_49 = 209,
+ RTGUIK_WORLD_50 = 210,
+ RTGUIK_WORLD_51 = 211,
+ RTGUIK_WORLD_52 = 212,
+ RTGUIK_WORLD_53 = 213,
+ RTGUIK_WORLD_54 = 214,
+ RTGUIK_WORLD_55 = 215,
+ RTGUIK_WORLD_56 = 216,
+ RTGUIK_WORLD_57 = 217,
+ RTGUIK_WORLD_58 = 218,
+ RTGUIK_WORLD_59 = 219,
+ RTGUIK_WORLD_60 = 220,
+ RTGUIK_WORLD_61 = 221,
+ RTGUIK_WORLD_62 = 222,
+ RTGUIK_WORLD_63 = 223,
+ RTGUIK_WORLD_64 = 224,
+ RTGUIK_WORLD_65 = 225,
+ RTGUIK_WORLD_66 = 226,
+ RTGUIK_WORLD_67 = 227,
+ RTGUIK_WORLD_68 = 228,
+ RTGUIK_WORLD_69 = 229,
+ RTGUIK_WORLD_70 = 230,
+ RTGUIK_WORLD_71 = 231,
+ RTGUIK_WORLD_72 = 232,
+ RTGUIK_WORLD_73 = 233,
+ RTGUIK_WORLD_74 = 234,
+ RTGUIK_WORLD_75 = 235,
+ RTGUIK_WORLD_76 = 236,
+ RTGUIK_WORLD_77 = 237,
+ RTGUIK_WORLD_78 = 238,
+ RTGUIK_WORLD_79 = 239,
+ RTGUIK_WORLD_80 = 240,
+ RTGUIK_WORLD_81 = 241,
+ RTGUIK_WORLD_82 = 242,
+ RTGUIK_WORLD_83 = 243,
+ RTGUIK_WORLD_84 = 244,
+ RTGUIK_WORLD_85 = 245,
+ RTGUIK_WORLD_86 = 246,
+ RTGUIK_WORLD_87 = 247,
+ RTGUIK_WORLD_88 = 248,
+ RTGUIK_WORLD_89 = 249,
+ RTGUIK_WORLD_90 = 250,
+ RTGUIK_WORLD_91 = 251,
+ RTGUIK_WORLD_92 = 252,
+ RTGUIK_WORLD_93 = 253,
+ RTGUIK_WORLD_94 = 254,
+ RTGUIK_WORLD_95 = 255, /* 0xFF */
+
+ /* Numeric keypad */
+ RTGUIK_KP0 = 256,
+ RTGUIK_KP1 = 257,
+ RTGUIK_KP2 = 258,
+ RTGUIK_KP3 = 259,
+ RTGUIK_KP4 = 260,
+ RTGUIK_KP5 = 261,
+ RTGUIK_KP6 = 262,
+ RTGUIK_KP7 = 263,
+ RTGUIK_KP8 = 264,
+ RTGUIK_KP9 = 265,
+ RTGUIK_KP_PERIOD = 266,
+ RTGUIK_KP_DIVIDE = 267,
+ RTGUIK_KP_MULTIPLY = 268,
+ RTGUIK_KP_MINUS = 269,
+ RTGUIK_KP_PLUS = 270,
+ RTGUIK_KP_ENTER = 271,
+ RTGUIK_KP_EQUALS = 272,
+
+ /* Arrows + Home/End pad */
+ RTGUIK_UP = 273,
+ RTGUIK_DOWN = 274,
+ RTGUIK_RIGHT = 275,
+ RTGUIK_LEFT = 276,
+ RTGUIK_INSERT = 277,
+ RTGUIK_HOME = 278,
+ RTGUIK_END = 279,
+ RTGUIK_PAGEUP = 280,
+ RTGUIK_PAGEDOWN = 281,
+
+ /* Function keys */
+ RTGUIK_F1 = 282,
+ RTGUIK_F2 = 283,
+ RTGUIK_F3 = 284,
+ RTGUIK_F4 = 285,
+ RTGUIK_F5 = 286,
+ RTGUIK_F6 = 287,
+ RTGUIK_F7 = 288,
+ RTGUIK_F8 = 289,
+ RTGUIK_F9 = 290,
+ RTGUIK_F10 = 291,
+ RTGUIK_F11 = 292,
+ RTGUIK_F12 = 293,
+ RTGUIK_F13 = 294,
+ RTGUIK_F14 = 295,
+ RTGUIK_F15 = 296,
+
+ /* Key state modifier keys */
+ RTGUIK_NUMLOCK = 300,
+ RTGUIK_CAPSLOCK = 301,
+ RTGUIK_SCROLLOCK = 302,
+ RTGUIK_RSHIFT = 303,
+ RTGUIK_LSHIFT = 304,
+ RTGUIK_RCTRL = 305,
+ RTGUIK_LCTRL = 306,
+ RTGUIK_RALT = 307,
+ RTGUIK_LALT = 308,
+ RTGUIK_RMETA = 309,
+ RTGUIK_LMETA = 310,
+ RTGUIK_LSUPER = 311, /* Left "Windows" key */
+ RTGUIK_RSUPER = 312, /* Right "Windows" key */
+ RTGUIK_MODE = 313, /* "Alt Gr" key */
+ RTGUIK_COMPOSE = 314, /* Multi-key compose key */
+
+ /* Miscellaneous function keys */
+ RTGUIK_HELP = 315,
+ RTGUIK_PRINT = 316,
+ RTGUIK_SYSREQ = 317,
+ RTGUIK_BREAK = 318,
+ RTGUIK_MENU = 319,
+ RTGUIK_POWER = 320, /* Power key */
+
+ RTGUIK_LAST
+} RTGUI_KBD_KEY;
+
+/* Enumeration of valid key mods (possibly OR'd together) */
+typedef enum {
+ RTGUI_KMOD_NONE = 0x0000,
+ RTGUI_KMOD_LSHIFT = 0x0001,
+ RTGUI_KMOD_RSHIFT = 0x0002,
+ RTGUI_KMOD_LCTRL = 0x0040,
+ RTGUI_KMOD_RCTRL = 0x0080,
+ RTGUI_KMOD_LALT = 0x0100,
+ RTGUI_KMOD_RALT = 0x0200,
+ RTGUI_KMOD_LMETA = 0x0400,
+ RTGUI_KMOD_RMETA = 0x0800,
+ RTGUI_KMOD_NUM = 0x1000,
+ RTGUI_KMOD_CAPS = 0x2000,
+ RTGUI_KMOD_MODE = 0x4000,
+ RTGUI_KMOD_RESERVED = 0x8000
+} RTGUI_KBD_MOD;
+
+typedef enum {
+ RTGUI_KEYDOWN, /* Keys pressed */
+ RTGUI_KEYUP, /* Keys released */
+} RTGUI_KBD_TYPE;
+
+#endif
diff --git a/rtgui/include/rtgui/list.h b/rtgui/include/rtgui/list.h
new file mode 100644
index 0000000000..4b3cf951e6
--- /dev/null
+++ b/rtgui/include/rtgui/list.h
@@ -0,0 +1,66 @@
+/*
+ * File : list.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_LIST_H__
+#define __RTGUI_LIST_H__
+
+#include <rtgui/rtgui.h>
+
+struct rtgui_list_node
+{
+ struct rtgui_list_node* next;
+};
+typedef struct rtgui_list_node rtgui_list_t;
+
+rt_inline void rtgui_list_init(rtgui_list_t *l)
+{
+ l->next = (struct rtgui_list_node *)0;
+}
+
+rt_inline void rtgui_list_append(rtgui_list_t *l, rtgui_list_t *n)
+{
+ struct rtgui_list_node* node;
+
+ node = l;
+ while (node->next) node = node->next;
+
+ /* append the node to the tail */
+ node->next = n;
+ n->next = (struct rtgui_list_node*) 0;
+}
+
+rt_inline void rtgui_list_insert(rtgui_list_t *l, rtgui_list_t *n)
+{
+ n->next = l->next;
+ l->next = n;
+}
+
+rt_inline rtgui_list_t* rtgui_list_remove(rtgui_list_t *l, rtgui_list_t *n)
+{
+ /* remove slist head */
+ struct rtgui_list_node* node = l;
+ while (node->next && node->next != n) node = node->next;
+
+ /* remove node */
+ if (node->next != (rtgui_list_t *)0) node->next = node->next->next;
+
+ return l;
+}
+
+#define rtgui_list_entry(node, type, member) \
+ ((type *)((char*)(node)-(unsigned long)(&((type *)0)->member)))
+
+#define rtgui_list_foreach(node, list) \
+ for ((node) = (list)->next; (node) != RT_NULL; (node) = (node)->next)
+
+#endif
diff --git a/rtgui/include/rtgui/region.h b/rtgui/include/rtgui/region.h
new file mode 100644
index 0000000000..72c06653e3
--- /dev/null
+++ b/rtgui/include/rtgui/region.h
@@ -0,0 +1,100 @@
+/*
+ * File : region.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_REGION_H__
+#define __RTGUI_REGION_H__
+
+#include <rtgui/rtgui.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+typedef struct rtgui_region_data rtgui_region_data_t;
+
+struct rtgui_region_data
+{
+ rt_uint32_t size;
+ rt_uint32_t numRects;
+ /* XXX: And why, exactly, do we have this bogus struct definition? */
+ /* rtgui_rect_t rects[size]; in memory but not explicitly declared */
+};
+
+typedef struct rtgui_region
+{
+ rtgui_rect_t extents;
+ rtgui_region_data_t *data;
+}rtgui_region_t;
+
+typedef enum
+{
+ RTGUI_REGION_STATUS_FAILURE,
+ RTGUI_REGION_STATUS_SUCCESS
+}rtgui_region_status_t;
+
+/* creation/destruction */
+
+void rtgui_region_init(rtgui_region_t *region);
+void rtgui_region_init_rect(rtgui_region_t *region,
+ int x, int y, unsigned int width, unsigned int height);
+void rtgui_region_init_with_extents(rtgui_region_t *region, rtgui_rect_t *extents);
+void rtgui_region_fini (rtgui_region_t *region);
+
+void rtgui_region_translate (rtgui_region_t *region, int x, int y);
+
+rtgui_region_status_t rtgui_region_copy (rtgui_region_t *dest, rtgui_region_t *source);
+
+rtgui_region_status_t rtgui_region_intersect (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_region_t *reg2);
+rtgui_region_status_t rtgui_region_intersect_rect (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_rect_t *rect);
+rtgui_region_status_t rtgui_region_union (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_region_t *reg2);
+rtgui_region_status_t rtgui_region_union_rect(rtgui_region_t *dest, rtgui_region_t *source, rtgui_rect_t* rect);
+rtgui_region_status_t rtgui_region_subtract (rtgui_region_t *regD, rtgui_region_t *regM, rtgui_region_t *regS);
+rtgui_region_status_t rtgui_region_subtract_rect (rtgui_region_t *regD, rtgui_region_t *regM, rtgui_rect_t* rect);
+rtgui_region_status_t rtgui_region_inverse (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_rect_t *invRect);
+
+int rtgui_region_num_rects (rtgui_region_t *region);
+
+rtgui_rect_t* rtgui_region_rects (rtgui_region_t *region);
+
+#define RTGUI_REGION_OUT 0
+#define RTGUI_REGION_IN 1
+#define RTGUI_REGION_PART 2
+
+int rtgui_region_contains_point (rtgui_region_t *region, int x, int y, rtgui_rect_t *box);
+int rtgui_region_contains_rectangle (rtgui_region_t *rtgui_region_t, rtgui_rect_t *prect);
+
+int rtgui_region_not_empty (rtgui_region_t *region);
+rtgui_rect_t *rtgui_region_extents (rtgui_region_t *region);
+
+rtgui_region_status_t rtgui_region_append (rtgui_region_t *dest, rtgui_region_t *region);
+rtgui_region_status_t rtgui_region_validate (rtgui_region_t *badreg, int *pOverlap);
+
+void rtgui_region_reset(rtgui_region_t *region, rtgui_rect_t* rect);
+void rtgui_region_empty (rtgui_region_t *region);
+void rtgui_region_dump(rtgui_region_t* region);
+
+/* rect functions */
+extern rtgui_rect_t rtgui_empty_rect;
+
+void rtgui_rect_moveto(rtgui_rect_t *rect, int x, int y);
+void rtgui_rect_moveto_align(rtgui_rect_t *rect, rtgui_rect_t *to, int align);
+void rtgui_rect_inflate(rtgui_rect_t *rect, int d);
+void rtgui_rect_intersect(rtgui_rect_t *src, rtgui_rect_t *dest);
+int rtgui_rect_contains_point(rtgui_rect_t *rect, int x, int y);
+int rtgui_rect_is_intersect(rtgui_rect_t *rect1, rtgui_rect_t *rect2);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* _PIXMAN_H_ */
diff --git a/rtgui/include/rtgui/rtgui.h b/rtgui/include/rtgui/rtgui.h
index bc820b76c0..dcc0741dba 100644
--- a/rtgui/include/rtgui/rtgui.h
+++ b/rtgui/include/rtgui/rtgui.h
@@ -16,10 +16,7 @@
#include <rtthread.h>
-/* RTGUI options */
-#define RTGUI_IMAGE_JPEG
-
-#define RTGUI_NAME_MAX 32
+#include <rtgui/rtgui_config.h>
#define RT_INT16_MAX 32767
#define RT_INT16_MIN (-RT_INT16_MAX-1)
diff --git a/rtgui/include/rtgui/rtgui_config.h b/rtgui/include/rtgui/rtgui_config.h
new file mode 100644
index 0000000000..72667c1342
--- /dev/null
+++ b/rtgui/include/rtgui/rtgui_config.h
@@ -0,0 +1,36 @@
+/*
+ * File : rtgui_config.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+
+#ifndef __RTGUI_CONFIG_H__
+#define __RTGUI_CONFIG_H__
+
+/* RTGUI options */
+
+/* name length of RTGUI object */
+#define RTGUI_NAME_MAX 32
+
+/* #define RTGUI_USING_MOUSE_CURSOR */
+
+/* #define RTGUI_USING_FONT16 */
+
+#define RT_USING_STDIO_FILERW
+
+#define RTGUI_SVR_THREAD_PRIORITY 15
+#define RTGUI_SVR_THREAD_TIMESLICE 5
+
+#define RTGUI_APP_THREAD_PRIORITY 25
+#define RTGUI_APP_THREAD_TIMESLICE 8
+
+#endif
+
diff --git a/rtgui/include/rtgui/rtgui_server.h b/rtgui/include/rtgui/rtgui_server.h
index a9463ecb38..738e60100e 100644
--- a/rtgui/include/rtgui/rtgui_server.h
+++ b/rtgui/include/rtgui/rtgui_server.h
@@ -67,4 +67,9 @@ void rtgui_server_init(void);
/* post an event to server */
void rtgui_server_post_event(struct rtgui_event* event, rt_size_t size);
+/* register or deregister panel in server */
+void rtgui_panel_register(char* name, rtgui_rect_t* extent);
+void rtgui_panel_deregister(char* name);
+
#endif
+
diff --git a/rtgui/include/rtgui/rtgui_theme.h b/rtgui/include/rtgui/rtgui_theme.h
index eb6738d6b5..60711dcaab 100644
--- a/rtgui/include/rtgui/rtgui_theme.h
+++ b/rtgui/include/rtgui/rtgui_theme.h
@@ -15,6 +15,7 @@
#define __RTGUI_THEME_H__
#include <rtgui/rtgui.h>
+#include <rtgui/rtgui_server.h>
#include <rtgui/widgets/label.h>
#include <rtgui/widgets/button.h>
diff --git a/rtgui/include/rtgui/widgets/box.h b/rtgui/include/rtgui/widgets/box.h
new file mode 100644
index 0000000000..69a0a01a56
--- /dev/null
+++ b/rtgui/include/rtgui/widgets/box.h
@@ -0,0 +1,58 @@
+/*
+ * File : box.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_BOX_H__
+#define __RTGUI_BOX_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/widgets/widget.h>
+#include <rtgui/widgets/container.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Gets the type of a box */
+#define RTGUI_BOX_TYPE (rtgui_box_type_get())
+/** Casts the object to an rtgui_box */
+#define RTGUI_BOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_BOX_TYPE, rtgui_box_t))
+/** Checks if the object is an rtgui_box */
+#define RTGUI_IS_BOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_BOX_TYPE))
+
+struct rtgui_box
+{
+ struct rtgui_container parent;
+
+ rt_uint16_t orientation;
+ rt_uint16_t border_size;
+};
+typedef struct rtgui_box rtgui_box_t;
+
+rtgui_type_t *rtgui_box_type_get(void);
+
+struct rtgui_box* rtgui_box_create(int orientation, rtgui_rect_t* rect);
+void rtgui_box_destroy(struct rtgui_box* box);
+
+rt_bool_t rtgui_box_event_handler(rtgui_widget_t* widget, rtgui_event_t* event);
+
+void rtgui_box_append(rtgui_box_t* box, rtgui_widget_t* widget);
+void rtgui_box_layout(rtgui_box_t* box);
+
+rt_uint32_t rtgui_box_get_width(rtgui_box_t* box);
+rt_uint32_t rtgui_box_get_height(rtgui_box_t* box);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rtgui/include/rtgui/widgets/button.h b/rtgui/include/rtgui/widgets/button.h
new file mode 100644
index 0000000000..77e7fc4e03
--- /dev/null
+++ b/rtgui/include/rtgui/widgets/button.h
@@ -0,0 +1,81 @@
+/*
+ * File : button.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_BUTTON_H__
+#define __RTGUI_BUTTON_H__
+
+#include <rtgui/image.h>
+#include <rtgui/widgets/widget.h>
+#include <rtgui/widgets/label.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup rtgui_button
+ * @{
+ */
+
+/** Gets the type of a button */
+#define RTGUI_BUTTON_TYPE (rtgui_button_type_get())
+/** Casts the object to an rtgui_button */
+#define RTGUI_BUTTON(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_BUTTON_TYPE, rtgui_button_t))
+/** Checks if the object is an rtgui_button */
+#define RTGUI_IS_BUTTON(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_BUTTON_TYPE))
+
+#define RTGUI_BUTTON_FLAG_PRESS 0x01
+#define RTGUI_BUTTON_FLAG_DEFAULT 0x02
+
+#define RTGUI_BUTTON_TYPE_NORMAL 0x00
+#define RTGUI_BUTTON_TYPE_PUSH 0x10
+
+/*
+ * the button widget
+ */
+struct rtgui_button
+{
+ /* inherit from label */
+ struct rtgui_label parent;
+
+ /* button flag */
+ rt_base_t flag;
+
+ /* pressed and unpressed image */
+ rtgui_image_t *pressed_image, *unpressed_image;
+
+ /* click button event handler */
+ void (*on_button)(struct rtgui_widget* widget, rtgui_event_t *event);
+};
+typedef struct rtgui_button rtgui_button_t;
+
+rtgui_type_t *rtgui_button_type_get(void);
+
+rtgui_button_t* rtgui_button_create(unsigned char* text);
+rtgui_button_t* rtgui_pushbutton_create(unsigned char* text);
+void rtgui_button_destroy(rtgui_button_t* btn);
+
+void rtgui_button_set_pressed_image(rtgui_button_t* btn, rtgui_image_t* image);
+void rtgui_button_set_unpressed_image(rtgui_button_t* btn, rtgui_image_t* image);
+
+void rtgui_button_ondraw(rtgui_button_t* btn);
+
+rt_bool_t rtgui_button_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rtgui/include/rtgui/widgets/container.h b/rtgui/include/rtgui/widgets/container.h
new file mode 100644
index 0000000000..7f1af7d3d2
--- /dev/null
+++ b/rtgui/include/rtgui/widgets/container.h
@@ -0,0 +1,47 @@
+/*
+ * File : container.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_CONTAINER_H__
+#define __RTGUI_CONTAINER_H__
+
+#include <rtgui/widgets/widget.h>
+
+/** Gets the type of a container */
+#define RTGUI_CONTAINER_TYPE (rtgui_container_type_get())
+/** Casts the object to a rtgui_container */
+#define RTGUI_CONTAINER(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_CONTAINER_TYPE, rtgui_container_t))
+/** Checks if the object is a rtgui_container */
+#define RTGUI_IS_CONTAINER(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_CONTAINER_TYPE))
+
+struct rtgui_container
+{
+ /* inherit from widget */
+ struct rtgui_widget parent;
+
+ rtgui_list_t children;
+};
+typedef struct rtgui_container rtgui_container_t;
+
+rtgui_type_t *rtgui_container_type_get(void);
+
+void rtgui_container_add_child(rtgui_container_t *container, rtgui_widget_t* child);
+void rtgui_container_remove_child(rtgui_container_t *container, rtgui_widget_t* child);
+void rtgui_container_destroy_children(rtgui_container_t *container);
+rtgui_widget_t* rtgui_container_get_first_child(rtgui_container_t* container);
+
+rt_bool_t rtgui_container_event_handler(rtgui_widget_t* widget, rtgui_event_t* event);
+
+rt_bool_t rtgui_container_dispatch_event(rtgui_container_t *container, rtgui_event_t* event);
+rt_bool_t rtgui_container_dispatch_mouse_event(rtgui_container_t *container, struct rtgui_event_mouse* event);
+
+#endif
diff --git a/rtgui/include/rtgui/widgets/iconbox.h b/rtgui/include/rtgui/widgets/iconbox.h
new file mode 100644
index 0000000000..73ebd682a6
--- /dev/null
+++ b/rtgui/include/rtgui/widgets/iconbox.h
@@ -0,0 +1,56 @@
+/*
+ * File : iconbox.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_ICONBOX_H__
+#define __RTGUI_ICONBOX_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/image.h>
+#include <rtgui/widgets/widget.h>
+
+/** Gets the type of a iconbox */
+#define RTGUI_ICONBOX_TYPE (rtgui_iconbox_type_get())
+/** Casts the object to a rtgui_iconbox */
+#define RTGUI_ICONBOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_ICONBOX_TYPE, rtgui_iconbox_t))
+/** Checks if the object is a rtgui_iconbox */
+#define RTGUI_IS_ICONBOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_ICONBOX_TYPE))
+
+#define RTGUI_ICONBOX_NOTEXT 0x00
+#define RTGUI_ICONBOX_TEXT_RIGHT 0x01
+#define RTGUI_ICONBOX_TEXT_BELOW 0x02
+
+struct rtgui_iconbox
+{
+ /* inherit from widget */
+ struct rtgui_widget parent;
+
+ /* widget private data */
+ struct rtgui_image* image;
+
+ unsigned char *text;
+ rt_ubase_t text_position;
+
+ rt_bool_t selected;
+};
+typedef struct rtgui_iconbox rtgui_iconbox_t;
+
+rtgui_type_t *rtgui_iconbox_type_get(void);
+
+struct rtgui_iconbox* rtgui_iconbox_create(struct rtgui_image* image, const unsigned char* text, int position);
+void rtgui_iconbox_destroy(struct rtgui_iconbox* iconbox);
+
+rt_bool_t rtgui_iconbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+
+void rtgui_iconbox_set_text_position(struct rtgui_iconbox* iconbox, int position);
+
+#endif
diff --git a/rtgui/include/rtgui/widgets/label.h b/rtgui/include/rtgui/widgets/label.h
new file mode 100644
index 0000000000..d9f87d9b88
--- /dev/null
+++ b/rtgui/include/rtgui/widgets/label.h
@@ -0,0 +1,49 @@
+/*
+ * File : label.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_LABEL_H__
+#define __RTGUI_LABEL_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/widgets/widget.h>
+
+/** Gets the type of a button */
+#define RTGUI_LABEL_TYPE (rtgui_label_type_get())
+/** Casts the object to an rtgui_button */
+#define RTGUI_LABEL(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_LABEL_TYPE, rtgui_label_t))
+/** Checks if the object is an rtgui_button */
+#define RTGUI_IS_LABEL(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_LABEL_TYPE))
+
+/*
+ * the label widget
+ */
+struct rtgui_label
+{
+ struct rtgui_widget parent;
+
+ /* label */
+ unsigned char* text;
+};
+typedef struct rtgui_label rtgui_label_t;
+
+rtgui_type_t *rtgui_label_type_get(void);
+
+rtgui_label_t* rtgui_label_create(const unsigned char* text);
+void rtgui_label_destroy(rtgui_label_t* label);
+
+rt_bool_t rtgui_label_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+
+void rtgui_label_set_text(rtgui_label_t* label, const unsigned char* text);
+unsigned char* rtgui_label_get_text(rtgui_label_t* label);
+
+#endif
diff --git a/rtgui/include/rtgui/widgets/listbox.h b/rtgui/include/rtgui/widgets/listbox.h
new file mode 100644
index 0000000000..1c201301da
--- /dev/null
+++ b/rtgui/include/rtgui/widgets/listbox.h
@@ -0,0 +1,66 @@
+/*
+ * File : listbox.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_LISTBOX_H__
+#define __RTGUI_LISTBOX_H__
+
+#include <rtgui/widgets/item.h>
+#include <rtgui/widgets/scrollview.h>
+
+#define RTGUI_LISTBOX_WIDTH 150
+#define RTGUI_LISTBOX_HEIGHT 200
+
+/** Gets the type of a listbox */
+#define RTGUI_LISTBOX_TYPE (rtgui_listbox_type_get())
+/** Casts the object to a rtgui_listbox */
+#define RTGUI_LISTBOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_LISTBOX_TYPE, rtgui_listbox_t))
+/** Checks if the object is a rtgui_listbox */
+#define RTGUI_IS_LISTBOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_LISTBOX_TYPE))
+
+/*
+* the listbox widget
+*/
+struct rtgui_listbox
+{
+ struct rtgui_scrollview parent;
+
+ /* widget private data */
+ int flag;
+
+ /* total number of items */
+ rt_uint32_t count;
+
+ /* the selected item */
+ struct rtgui_item* selected;
+
+ /* call back */
+ rt_bool_t (*on_selected) (struct rtgui_widget* widget, struct rtgui_event* event);
+ rt_bool_t (*on_activated) (struct rtgui_widget* widget, struct rtgui_event* event);
+};
+typedef struct rtgui_listbox rtgui_listbox_t;
+
+rtgui_type_t *rtgui_listbox_type_get(void);
+
+rtgui_listbox_t* rtgui_listbox_create(void);
+void rtgui_listbox_destroy(rtgui_listbox_t* listbox);
+
+rt_bool_t rtgui_listbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+
+struct rtgui_item* rtgui_listbox_get_select(struct rtgui_listbox* box);
+void rtgui_listbox_set_select(struct rtgui_listbox* box, rt_uint32_t index);
+void rtgui_listbox_set_select_item(struct rtgui_listbox* box, struct rtgui_item* item);
+
+struct rtgui_item* rtgui_listbox_add_item_string(struct rtgui_listbox* box, const unsigned char* text);
+void rtgui_listbox_add_item(struct rtgui_listbox* list, struct rtgui_item* item);
+
+#endif
diff --git a/rtgui/include/rtgui/widgets/textbox.h b/rtgui/include/rtgui/widgets/textbox.h
new file mode 100644
index 0000000000..709b35f76b
--- /dev/null
+++ b/rtgui/include/rtgui/widgets/textbox.h
@@ -0,0 +1,73 @@
+/*
+ * File : textbox.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_TEXTBOX_H__
+#define __RTGUI_TEXTBOX_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/caret.h>
+#include <rtgui/widgets/widget.h>
+
+/** Gets the type of a textbox */
+#define RTGUI_TEXTBOX_TYPE (rtgui_textbox_type_get())
+/** Casts the object to a rtgui_textbox */
+#define RTGUI_TEXTBOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_TEXTBOX_TYPE, rtgui_textbox_t))
+/** Checks if the object is a rtgui_textbox */
+#define RTGUI_IS_TEXTBOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_TEXTBOX_TYPE))
+
+#define RTGUI_TEXTBOX_DEFAULT_WIDTH 80
+#define RTGUI_TEXTBOX_DEFAULT_HEIGHT 20
+
+#define RTGUI_TEXTBOX_SINGLE 0x00
+#define RTGUI_TEXTBOX_MULTI 0x00
+
+struct rtgui_textbox_line
+{
+ rt_uint8_t* line_text;
+
+ struct rtgui_textbox_line *prev, *next;
+};
+
+struct rtgui_textbox
+{
+ /* inherit from widget */
+ struct rtgui_widget parent;
+
+ /* text box type */
+ rt_ubase_t type;
+
+ /* current line and position */
+ rt_size_t line, line_begin, position, line_length;
+
+ rt_uint8_t* text;
+ rt_size_t font_width;
+
+ int caret_x, caret_y;
+ struct rtgui_caret* caret;
+
+ /* widget private data */
+ rt_bool_t (*on_enter) (struct rtgui_widget* widget, struct rtgui_event* event);
+};
+typedef struct rtgui_textbox rtgui_textbox_t;
+
+struct rtgui_textbox* rtgui_textbox_create(const char* text);
+void rtgui_textbox_destroy(struct rtgui_textbox* box);
+
+rt_bool_t rtgui_textbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+
+void rtgui_textbox_set_value(struct rtgui_textbox* box, const char* text);
+const char* rtgui_textbox_get_value(struct rtgui_textbox* box);
+
+void rtgui_widget_set_line_length(struct rtgui_textbox* box, rt_size_t length);
+
+#endif
diff --git a/rtgui/include/rtgui/widgets/title.h b/rtgui/include/rtgui/widgets/title.h
new file mode 100644
index 0000000000..0eda0f16a4
--- /dev/null
+++ b/rtgui/include/rtgui/widgets/title.h
@@ -0,0 +1,45 @@
+/*
+ * File : title.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_TITLE__
+#define __RTGUI_TITLE__
+
+#include <rtgui/widgets/toplevel.h>
+
+/** Gets the type of a top win */
+#define RTGUI_WINTITLE_TYPE (rtgui_wintitle_type_get())
+/** Casts the object to an rtgui_wintitle */
+#define RTGUI_WINTITLE(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_WINTITLE_TYPE, rtgui_wintitle_t))
+/** Checks if the object is an rtgui_wintitle */
+#define RTGUI_IS_WINTITLE(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_WINTITLE_TYPE))
+
+struct rtgui_wintitle
+{
+ struct rtgui_toplevel parent;
+
+ /* title */
+ rt_uint8_t* title;
+};
+typedef struct rtgui_wintitle rtgui_wintitle_t;
+
+rtgui_type_t* rtgui_wintitle_type_get(void);
+
+rtgui_wintitle_t* rtgui_wintitle_create(const rt_uint8_t* title);
+void rtgui_wintitle_destroy(rtgui_wintitle_t* wintitle);
+
+rt_bool_t rtgui_wintile_event_handler(rtgui_widget_t* widget, rtgui_event_t* event);
+
+void rtgui_wintitle_set_title(rtgui_wintitle_t* wintitle, const rt_uint8_t* title);
+rt_uint8_t *rtgui_wintitle_get_title(rtgui_wintitle_t* wintitle);
+
+#endif
diff --git a/rtgui/include/rtgui/widgets/toplevel.h b/rtgui/include/rtgui/widgets/toplevel.h
new file mode 100644
index 0000000000..044edf4058
--- /dev/null
+++ b/rtgui/include/rtgui/widgets/toplevel.h
@@ -0,0 +1,57 @@
+/*
+ * File : toplevel.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_TOPLEVEL_H__
+#define __RTGUI_TOPLEVEL_H__
+
+#include <rtgui/widgets/container.h>
+
+/** Gets the type of a toplevel */
+#define RTGUI_TOPLEVEL_TYPE (rtgui_toplevel_type_get())
+/** Casts the object to an rtgui_toplevel */
+#define RTGUI_TOPLEVEL(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_TOPLEVEL_TYPE, rtgui_toplevel_t))
+/** Checks if the object is an rtgui_toplevel */
+#define RTGUI_IS_TOPLEVEL(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_TOPLEVEL_TYPE))
+
+struct rtgui_toplevel
+{
+ /* inherit from container */
+ rtgui_container_t parent;
+
+ /* drawing count */
+ rt_base_t drawing;
+
+ /* external clip info */
+ rtgui_rect_t* external_clip_rect;
+ rt_uint32_t external_clip_size;
+
+ /* server thread id */
+ rt_thread_t server;
+
+ /* current focus widget */
+ rtgui_widget_t* focus;
+};
+typedef struct rtgui_toplevel rtgui_toplevel_t;
+
+rtgui_type_t *rtgui_toplevel_type_get(void);
+
+rt_bool_t rtgui_toplevel_event_handler(rtgui_widget_t* widget, rtgui_event_t* event);
+
+void rtgui_toplevel_handle_clip(struct rtgui_toplevel* top,
+ struct rtgui_event_clip_info* info);
+void rtgui_toplevel_update_clip(rtgui_toplevel_t* top);
+
+void rtgui_toplevel_set_focus(struct rtgui_toplevel* top, rtgui_widget_t* focus);
+rtgui_widget_t* rtgui_toplevel_get_focus(struct rtgui_toplevel* top);
+
+#endif
diff --git a/rtgui/include/rtgui/widgets/view.h b/rtgui/include/rtgui/widgets/view.h
new file mode 100644
index 0000000000..3dd6c43e63
--- /dev/null
+++ b/rtgui/include/rtgui/widgets/view.h
@@ -0,0 +1,61 @@
+/*
+ * File : view.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_VIEW_H__
+#define __RTGUI_VIEW_H__
+
+#include <rtgui/widgets/box.h>
+#include <rtgui/widgets/container.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Gets the type of a view */
+#define RTGUI_VIEW_TYPE (rtgui_view_type_get())
+/** Casts the object to an rtgui_view */
+#define RTGUI_VIEW(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_VIEW_TYPE, rtgui_view_t))
+/** Checks if the object is an rtgui_view */
+#define RTGUI_IS_VIEW(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_VIEW_TYPE))
+
+/*
+ * the view widget
+ */
+struct rtgui_view
+{
+ /* inherit from container */
+ struct rtgui_container parent;
+
+ /* private field */
+ char* title;
+};
+typedef struct rtgui_view rtgui_view_t;
+
+rtgui_view_t* rtgui_view_create(const char* title);
+void rtgui_view_destroy(rtgui_view_t* view);
+
+rt_bool_t rtgui_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
+
+void rtgui_view_set_box(rtgui_view_t* view, rtgui_box_t* box);
+
+void rtgui_view_show(rtgui_view_t* view);
+void rtgui_view_hide(rtgui_view_t* view);
+
+char* rtgui_view_get_title(rtgui_view_t* view);
+void rtgui_view_set_title(rtgui_view_t* view, const char* title);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/rtgui/server/mouse.c b/rtgui/server/mouse.c
new file mode 100644
index 0000000000..2432073a3e
--- /dev/null
+++ b/rtgui/server/mouse.c
@@ -0,0 +1,629 @@
+/*
+ * File : mouse.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+
+#include "mouse.h"
+#include <rtgui/region.h>
+#include <rtgui/driver.h>
+#include <rtgui/rtgui_system.h>
+
+struct rtgui_cursor
+{
+ /* screen byte per pixel */
+ rt_uint16_t bpp;
+
+ /* screen pitch */
+ rt_uint16_t screen_pitch;
+
+ /* current cursor x and y */
+ rt_uint16_t cx, cy;
+
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ /* cursor pitch */
+ rt_uint16_t cursor_pitch;
+
+ /* show cursor and show cursor count */
+ rt_bool_t show_cursor;
+ rt_base_t show_cursor_count;
+
+ /* cursor rect info */
+ rtgui_rect_t rect;
+
+ /* cursor image and saved cursor */
+ rtgui_image_t *cursor_image;
+ rt_uint8_t *cursor_saved;
+#endif
+
+ /* move window rect and border */
+ struct rtgui_topwin *topwin;
+ rtgui_rect_t win_rect;
+ rt_uint8_t *win_left, *win_right;
+ rt_uint8_t *win_top, *win_bottom;
+ rt_bool_t win_rect_show, win_rect_has_saved;
+
+ /* screen framebuffer */
+ rt_uint8_t* framebuffer;
+};
+
+struct rtgui_cursor* _rtgui_cursor;
+
+#ifdef RTGUI_USING_MOUSE_CURSOR
+struct rt_mutex cursor_mutex;
+static const rt_uint8_t * cursor_xpm[] = {
+ "16 16 35 1",
+ " c None",
+ ". c #A0B8D0",
+ "+ c #F0F0F0",
+ "@ c #FFFFFF",
+ "# c #F0F8F0",
+ "$ c #A0B0D0",
+ "% c #90A8C0",
+ "& c #A0B0C0",
+ "* c #E0E8F0",
+ "= c #8090B0",
+ "- c #D0D8E0",
+ "; c #7080A0",
+ "> c #90A0B0",
+ ", c #FFF8FF",
+ "' c #F0F8FF",
+ ") c #607090",
+ "! c #8098B0",
+ "~ c #405060",
+ "{ c #405070",
+ "] c #506070",
+ "^ c #607080",
+ "/ c #708090",
+ "( c #7088A0",
+ "_ c #D0D0E0",
+ ": c #607890",
+ "< c #C0D0E0",
+ "[ c #C0C8D0",
+ "} c #506880",
+ "| c #5F778F",
+ "1 c #D0D8F0",
+ "2 c #506080",
+ "3 c #C0C8E0",
+ "4 c #A0A8C0",
+ "5 c #405870",
+ "6 c #5F6F8F",
+ " . ",
+ " .. ",
+ " .+. ",
+ " .@#$ ",
+ " $@@+% ",
+ " &@@@*= ",
+ " %@@@@-; ",
+ " >@@,''-) ",
+ " !,''+)~{] ",
+ " ='-^*/ ",
+ " (_{:<[^ ",
+ " ;} |:12 ",
+ " / )345 ",
+ " 6}${ ",
+ " 5{ ",
+ " "};
+
+static void rtgui_cursor_restore (void);
+static void rtgui_cursor_save (void);
+static void rtgui_cursor_show (void);
+#endif
+
+static void rtgui_winrect_restore (void);
+static void rtgui_winrect_save (void);
+static void rtgui_winrect_show (void);
+
+#define WIN_MOVE_BORDER 4
+void rtgui_mouse_init()
+{
+ struct rtgui_graphic_driver* gd = rtgui_graphic_driver_get_default();
+
+ _rtgui_cursor = (struct rtgui_cursor*) rtgui_malloc(sizeof(struct rtgui_cursor));
+ rt_memset(_rtgui_cursor, 0, sizeof(struct rtgui_cursor));
+
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ rt_mutex_init(&cursor_mutex, "cursor", RT_IPC_FLAG_FIFO);
+#endif
+
+ /* init cursor */
+ _rtgui_cursor->bpp = gd->byte_per_pixel;
+ _rtgui_cursor->framebuffer = gd->get_framebuffer();
+ _rtgui_cursor->screen_pitch = _rtgui_cursor->bpp * gd->width;
+
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ /* init cursor image */
+ _rtgui_cursor->cursor_image = rtgui_image_create_from_mem("xpm", cursor_xpm, sizeof(cursor_xpm));
+ if (_rtgui_cursor->cursor_image == RT_NULL)
+ {
+ rtgui_free(_rtgui_cursor);
+ _rtgui_cursor = RT_NULL;
+
+ return;
+ }
+
+ /* init rect */
+ _rtgui_cursor->rect.x1 = _rtgui_cursor->rect.y1 = 0;
+ _rtgui_cursor->rect.x2 = _rtgui_cursor->cursor_image->w;
+ _rtgui_cursor->rect.y2 = _rtgui_cursor->cursor_image->h;
+
+ _rtgui_cursor->cursor_pitch = _rtgui_cursor->cursor_image->w * _rtgui_cursor->bpp;
+
+ _rtgui_cursor->show_cursor = RT_TRUE;
+ _rtgui_cursor->show_cursor_count = 0;
+ _rtgui_cursor->cursor_saved = rtgui_malloc(_rtgui_cursor->cursor_image->w *
+ _rtgui_cursor->cursor_image->h * _rtgui_cursor->bpp);
+#endif
+
+ /* init window move save image */
+ _rtgui_cursor->win_rect_has_saved = RT_FALSE;
+ _rtgui_cursor->win_rect_show = RT_FALSE;
+
+ _rtgui_cursor->win_left = rtgui_malloc(_rtgui_cursor->bpp * gd->height * WIN_MOVE_BORDER);
+ _rtgui_cursor->win_right = rtgui_malloc(_rtgui_cursor->bpp * gd->height * WIN_MOVE_BORDER);
+ _rtgui_cursor->win_top = rtgui_malloc(_rtgui_cursor->bpp * gd->width * WIN_MOVE_BORDER);
+ _rtgui_cursor->win_bottom = rtgui_malloc(_rtgui_cursor->bpp * gd->width * WIN_MOVE_BORDER);
+}
+
+void rtgui_mouse_moveto(int x, int y)
+{
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
+#endif
+
+ if (x != _rtgui_cursor->cx ||
+ y != _rtgui_cursor->cy)
+ {
+ if (_rtgui_cursor->win_rect_show)
+ {
+ if (_rtgui_cursor->win_rect_has_saved == RT_TRUE)
+ {
+ rtgui_winrect_restore();
+ }
+
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ rtgui_mouse_hide_cursor();
+#endif
+
+ /* move winrect */
+ rtgui_rect_moveto(&(_rtgui_cursor->win_rect), x - _rtgui_cursor->cx,
+ y - _rtgui_cursor->cy);
+ rtgui_winrect_save();
+
+ /* move current cursor */
+ _rtgui_cursor->cx = x;
+ _rtgui_cursor->cy = y;
+
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ /* show cursor */
+ rtgui_mouse_show_cursor();
+#endif
+ /* show winrect */
+ rtgui_winrect_show();
+ }
+ else
+ {
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ rtgui_mouse_hide_cursor();
+#endif
+ /* move current cursor */
+ _rtgui_cursor->cx = x;
+ _rtgui_cursor->cy = y;
+
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ /* show cursor */
+ rtgui_mouse_show_cursor();
+#endif
+ }
+ }
+
+#ifdef RTGUI_USING_MOUSE_CURSOR
+ rt_mutex_release(&cursor_mutex);
+#endif
+}
+
+#ifdef RTGUI_USING_MOUSE_CURSOR
+void rtgui_mouse_set_cursor_enable(rt_bool_t enable)
+{
+ _rtgui_cursor->show_cursor = enable;
+}
+
+/* set current cursor image */
+void rtgui_mouse_set_cursor(rtgui_image_t* cursor)
+{
+}
+
+void rtgui_mouse_get_cursor_rect(rtgui_rect_t* rect)
+{
+ if (rect != RT_NULL)
+ {
+ *rect = _rtgui_cursor->rect;
+ }
+}
+
+void rtgui_mouse_show_cursor()
+{
+ if (_rtgui_cursor->show_cursor == RT_FALSE)
+ return;
+
+ _rtgui_cursor->show_cursor_count ++;
+ if (_rtgui_cursor->show_cursor_count == 1)
+ {
+ /* save show mouse area */
+ rtgui_cursor_save();
+
+ /* show mouse cursor */
+ rtgui_cursor_show();
+ }
+}
+
+void rtgui_mouse_hide_cursor()
+{
+ if (_rtgui_cursor->show_cursor == RT_FALSE)
+ return;
+
+ if (_rtgui_cursor->show_cursor_count == 1)
+ {
+ /* display the cursor coverage area */
+ rtgui_cursor_restore();
+ }
+ _rtgui_cursor->show_cursor_count --;
+}
+
+rt_bool_t rtgui_mouse_is_intersect(rtgui_rect_t* r)
+{
+ return rtgui_rect_is_intersect(&(_rtgui_cursor->rect), r) == RT_EOK? RT_TRUE : RT_FALSE;
+}
+
+/* display the saved cursor area to screen */
+static void rtgui_cursor_restore()
+{
+ rt_base_t idx, height, cursor_pitch;
+ rt_uint8_t *cursor_ptr, *fb_ptr;
+
+ fb_ptr = _rtgui_cursor->framebuffer + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch
+ + _rtgui_cursor->cx * _rtgui_cursor->bpp;
+ cursor_ptr = _rtgui_cursor->cursor_saved;
+
+ height = (_rtgui_cursor->cy + _rtgui_cursor->cursor_image->h <
+ rtgui_graphic_driver_get_default()->height)? _rtgui_cursor->cursor_image->h :
+ rtgui_graphic_driver_get_default()->height - _rtgui_cursor->cy;
+
+ cursor_pitch = (_rtgui_cursor->cx + _rtgui_cursor->cursor_image->w <
+ rtgui_graphic_driver_get_default()->width)? _rtgui_cursor->cursor_pitch :
+ (rtgui_graphic_driver_get_default()->width - _rtgui_cursor->cx) * _rtgui_cursor->bpp;
+
+ for (idx = 0; idx < height; idx ++)
+ {
+ rt_memcpy(fb_ptr, cursor_ptr, cursor_pitch);
+
+ fb_ptr += _rtgui_cursor->screen_pitch;
+ cursor_ptr += _rtgui_cursor->cursor_pitch;
+ }
+}
+
+/* save the cursor coverage area from screen */
+static void rtgui_cursor_save()
+{
+ rt_base_t idx, height, cursor_pitch;
+ rt_uint8_t *cursor_ptr, *fb_ptr;
+
+ fb_ptr = _rtgui_cursor->framebuffer + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch +
+ _rtgui_cursor->cx * _rtgui_cursor->bpp;
+ cursor_ptr = _rtgui_cursor->cursor_saved;
+
+ height = (_rtgui_cursor->cy + _rtgui_cursor->cursor_image->h <
+ rtgui_graphic_driver_get_default()->height)? _rtgui_cursor->cursor_image->h :
+ rtgui_graphic_driver_get_default()->height - _rtgui_cursor->cy;
+
+ cursor_pitch = (_rtgui_cursor->cx + _rtgui_cursor->cursor_image->w <
+ rtgui_graphic_driver_get_default()->width)? _rtgui_cursor->cursor_pitch :
+ (rtgui_graphic_driver_get_default()->width - _rtgui_cursor->cx) * _rtgui_cursor->bpp;
+
+ for (idx = 0; idx < height; idx ++)
+ {
+ rt_memcpy(cursor_ptr, fb_ptr, cursor_pitch);
+
+ fb_ptr += _rtgui_cursor->screen_pitch;
+ cursor_ptr += _rtgui_cursor->cursor_pitch;
+ }
+}
+
+static void rtgui_cursor_show()
+{
+ rt_uint16_t x, y;
+ rtgui_color_t* ptr;
+ rtgui_rect_t rect;
+ void (*set_pixel) (rtgui_color_t *c, rt_uint16_t x, rt_uint16_t y);
+
+ ptr = (rtgui_color_t*) _rtgui_cursor->cursor_image->data;
+ set_pixel = rtgui_graphic_driver_get_default()->set_pixel;
+
+ rtgui_mouse_get_cursor_rect(&rect);
+ rtgui_rect_moveto(&rect, _rtgui_cursor->cx, _rtgui_cursor->cy);
+
+ /* draw each point */
+ for (y = rect.y1; y < rect.y2; y ++)
+ {
+ for (x = rect.x1; x < rect.x2; x++)
+ {
+ /* not alpha */
+ if ((*ptr >> 24) != 255)
+ {
+ set_pixel(ptr, x, y);
+ }
+
+ /* move to next color buffer */
+ ptr ++;
+ }
+ }
+
+ /* update rect */
+ rtgui_graphic_driver_get_default()->screen_update(&rect);
+}
+#endif
+
+void rtgui_winrect_set(struct rtgui_topwin* topwin)
+{
+ /* set win rect show */
+ _rtgui_cursor->win_rect_show = RT_TRUE;
+
+ /* set win rect */
+ _rtgui_cursor->win_rect = topwin->title == RT_NULL? topwin->extent : RTGUI_WIDGET(topwin->title)->extent;
+ _rtgui_cursor->topwin = topwin;
+}
+
+rt_bool_t rtgui_winrect_moved_done(rtgui_rect_t* winrect, struct rtgui_topwin** topwin)
+{
+ rt_bool_t moved = RT_FALSE;
+
+ /* no win rect */
+ if (winrect == RT_NULL) return RT_FALSE;
+
+ /* restore winrect */
+ if (_rtgui_cursor->win_rect_has_saved)
+ {
+ rtgui_winrect_restore();
+
+ moved = RT_TRUE;
+ }
+
+ /* clear win rect show */
+ _rtgui_cursor->win_rect_show = RT_FALSE;
+ _rtgui_cursor->win_rect_has_saved = RT_FALSE;
+
+ /* return win rect */
+ *winrect = _rtgui_cursor->win_rect;
+ *topwin = _rtgui_cursor->topwin;
+
+ return moved;
+}
+
+rt_bool_t rtgui_winrect_is_moved()
+{
+ return _rtgui_cursor->win_rect_show;
+}
+
+/* show winrect */
+static void rtgui_winrect_show()
+{
+ rt_uint16_t x, y;
+ rtgui_color_t c;
+ rtgui_rect_t screen_rect, win_rect, win_rect_inner;
+ void (*set_pixel) (rtgui_color_t *c, rt_base_t x, rt_base_t y);
+
+ c = black;
+ set_pixel = rtgui_graphic_driver_get_default()->set_pixel;
+
+ win_rect = _rtgui_cursor->win_rect;
+ win_rect_inner = win_rect;
+ rtgui_rect_inflate(&win_rect_inner, -WIN_MOVE_BORDER);
+
+ rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(),
+ &screen_rect);
+ rtgui_rect_intersect(&screen_rect, &win_rect);
+ rtgui_rect_intersect(&screen_rect, &win_rect_inner);
+
+ /* draw left */
+ for (y = win_rect.y1; y < win_rect.y2; y ++)
+ {
+ for (x = win_rect.x1; x < win_rect_inner.x1; x++)
+ if ((x + y) & 0x01) set_pixel(&c, x, y);
+ }
+
+ /* draw right */
+ for (y = win_rect.y1; y < win_rect.y2; y ++)
+ {
+ for (x = win_rect_inner.x2; x < win_rect.x2; x++)
+ if ((x + y) & 0x01) set_pixel(&c, x, y);
+ }
+
+ /* draw top border */
+ for (y = win_rect.y1; y < win_rect_inner.y1; y ++)
+ {
+ for (x = win_rect_inner.x1; x < win_rect_inner.x2; x++)
+ if ((x + y) & 0x01) set_pixel(&c, x, y);
+ }
+
+ /* draw bottom border */
+ for (y = win_rect_inner.y2; y < win_rect.y2; y ++)
+ {
+ for (x = win_rect_inner.x1; x < win_rect_inner.x2; x++)
+ if ((x + y) & 0x01) set_pixel(&c, x, y);
+ }
+
+ /* update rect */
+ rtgui_graphic_driver_get_default()->screen_update(&win_rect);
+}
+
+#define display_direct_memcpy(src, dest, src_pitch, dest_pitch, height, len) \
+ for (idx = 0; idx < height; idx ++) \
+ { \
+ rt_memcpy(dest, src, len); \
+ src += src_pitch; \
+ dest += dest_pitch; \
+ }
+
+static void rtgui_winrect_restore()
+{
+ rt_uint8_t *winrect_ptr, *fb_ptr;
+ int winrect_pitch, idx;
+ rtgui_rect_t screen_rect, win_rect;
+
+ win_rect = _rtgui_cursor->win_rect;
+
+ rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(),
+ &screen_rect);
+ rtgui_rect_intersect(&screen_rect, &win_rect);
+
+ /* restore winrect left */
+ fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+ win_rect.x1 * _rtgui_cursor->bpp;
+ winrect_ptr = _rtgui_cursor->win_left;
+ winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
+ display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch,
+ (win_rect.y2 - win_rect.y1), winrect_pitch);
+
+ /* restore winrect right */
+ fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+ (win_rect.x2 - WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
+ winrect_ptr = _rtgui_cursor->win_right;
+ winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
+ display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch,
+ (win_rect.y2 - win_rect.y1), winrect_pitch);
+
+ /* restore winrect top */
+ fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+ (win_rect.x1 + WIN_MOVE_BORDER)* _rtgui_cursor->bpp;
+ winrect_ptr = _rtgui_cursor->win_top;
+ winrect_pitch = (win_rect.x2 - win_rect.x1 - 2 * WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
+ display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch,
+ WIN_MOVE_BORDER, winrect_pitch);
+
+ /* restore winrect bottom */
+ fb_ptr = _rtgui_cursor->framebuffer + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch +
+ (win_rect.x1 + WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
+ winrect_ptr = _rtgui_cursor->win_bottom;
+ display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch,
+ WIN_MOVE_BORDER, winrect_pitch);
+}
+
+static void rtgui_winrect_save()
+{
+ rt_uint8_t *winrect_ptr, *fb_ptr;
+ int winrect_pitch, idx;
+ rtgui_rect_t screen_rect, win_rect;
+
+ win_rect = _rtgui_cursor->win_rect;
+
+ rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(),
+ &screen_rect);
+ rtgui_rect_intersect(&screen_rect, &win_rect);
+
+ /* set winrect has saved */
+ _rtgui_cursor->win_rect_has_saved = RT_TRUE;
+
+ /* save winrect left */
+ fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+ win_rect.x1 * _rtgui_cursor->bpp;
+ winrect_ptr = _rtgui_cursor->win_left;
+ winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
+ display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch,
+ (win_rect.y2 - win_rect.y1), winrect_pitch);
+
+ /* save winrect right */
+ fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+ (win_rect.x2 - WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
+ winrect_ptr = _rtgui_cursor->win_right;
+ winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
+ display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch,
+ (win_rect.y2 - win_rect.y1), winrect_pitch);
+
+ /* save winrect top */
+ fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
+ (win_rect.x1 + WIN_MOVE_BORDER)* _rtgui_cursor->bpp;
+ winrect_ptr = _rtgui_cursor->win_top;
+ winrect_pitch = (win_rect.x2 - win_rect.x1 - 2 * WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
+ display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch,
+ WIN_MOVE_BORDER, winrect_pitch);
+
+ /* save winrect bottom */
+ fb_ptr = _rtgui_cursor->framebuffer + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch +
+ (win_rect.x1 + WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
+ winrect_ptr = _rtgui_cursor->win_bottom;
+ display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch,
+ WIN_MOVE_BORDER, winrect_pitch);
+}
+
+void rtgui_mouse_monitor_append(rtgui_list_t* head, rtgui_rect_t* rect)
+{
+ struct rtgui_mouse_monitor* mmonitor;
+
+ /* check parameters */
+ if (head == RT_NULL || rect == RT_NULL) return;
+
+ /* create a mouse monitor node */
+ mmonitor = (struct rtgui_mouse_monitor*) rtgui_malloc (sizeof(struct rtgui_mouse_monitor));
+ if (mmonitor == RT_NULL) return; /* no memory */
+
+ /* set mouse monitor node */
+ mmonitor->rect = *rect;
+ rtgui_list_init(&(mmonitor->list));
+
+ /* append to list */
+ rtgui_list_append(head, &(mmonitor->list));
+}
+
+void rtgui_mouse_monitor_remove(rtgui_list_t* head, rtgui_rect_t* rect)
+{
+ struct rtgui_list_node* node;
+ struct rtgui_mouse_monitor* mmonitor;
+
+ /* check parameters */
+ if (head == RT_NULL || rect == RT_NULL) return;
+
+ for (node = head->next; node != RT_NULL; node = node->next)
+ {
+ mmonitor = rtgui_list_entry(node, struct rtgui_mouse_monitor, list);
+ if (mmonitor->rect.x1 == rect->x1 &&
+ mmonitor->rect.x2 == rect->x2 &&
+ mmonitor->rect.y1 == rect->y1 &&
+ mmonitor->rect.y2 == rect->y2)
+ {
+ /* found node */
+ rtgui_list_remove(head, node);
+ rtgui_free(mmonitor);
+
+ return ;
+ }
+ }
+}
+
+rt_bool_t rtgui_mouse_monitor_contains_point(rtgui_list_t* head, int x, int y)
+{
+ struct rtgui_list_node* node;
+
+ /* check parameter */
+ if (head == RT_NULL) return RT_FALSE;
+
+ rtgui_list_foreach(node, head)
+ {
+ struct rtgui_mouse_monitor* monitor = rtgui_list_entry(node,
+ struct rtgui_mouse_monitor, list);
+
+ if (rtgui_rect_contains_point(&(monitor->rect), x, y) == RT_EOK)
+ {
+ return RT_TRUE;
+ }
+ }
+
+ return RT_FALSE;
+}
diff --git a/rtgui/server/mouse.h b/rtgui/server/mouse.h
new file mode 100644
index 0000000000..da6c16485e
--- /dev/null
+++ b/rtgui/server/mouse.h
@@ -0,0 +1,51 @@
+/*
+ * File : mouse.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_MOUSE_H__
+#define __RTGUI_MOUSE_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/image.h>
+#include "topwin.h"
+
+struct rtgui_mouse_monitor
+{
+ /* event rect */
+ rtgui_rect_t rect;
+
+ /* node list */
+ rtgui_list_t list;
+};
+typedef struct rtgui_mouse_monitor rtgui_mouse_monitor_t;
+
+void rtgui_mouse_init(void);
+void rtgui_mouse_moveto(int x, int y);
+
+void rtgui_mouse_set_cursor_enable(rt_bool_t enable);
+void rtgui_mouse_set_cursor(rtgui_image_t* cursor);
+void rtgui_mouse_get_cursor_rect(rtgui_rect_t* rect);
+
+void rtgui_mouse_show_cursor(void);
+void rtgui_mouse_hide_cursor(void);
+
+rt_bool_t rtgui_mouse_is_intersect(rtgui_rect_t* r);
+
+rt_bool_t rtgui_winrect_is_moved(void);
+void rtgui_winrect_set(struct rtgui_topwin* topwin);
+rt_bool_t rtgui_winrect_moved_done(rtgui_rect_t* winrect, struct rtgui_topwin** topwin);
+
+void rtgui_mouse_monitor_append(rtgui_list_t* head, rtgui_rect_t* rect);
+void rtgui_mouse_monitor_remove(rtgui_list_t* head, rtgui_rect_t* rect);
+rt_bool_t rtgui_mouse_monitor_contains_point(rtgui_list_t* head, int x, int y);
+
+#endif
diff --git a/rtgui/server/panel.h b/rtgui/server/panel.h
index a524ede6a4..c40f57a5ff 100644
--- a/rtgui/server/panel.h
+++ b/rtgui/server/panel.h
@@ -49,10 +49,6 @@ struct rtgui_panel
rt_thread_t wm_thread;
};
-/* register or deregister panel in server */
-void rtgui_panel_register(char* name, rtgui_rect_t* extent);
-void rtgui_panel_deregister(char* name);
-
/* find panel by name */
struct rtgui_panel* rtgui_panel_find(char* name);
diff --git a/rtgui/server/server.c b/rtgui/server/server.c
index 78040ab344..eb5615d8f5 100644
--- a/rtgui/server/server.c
+++ b/rtgui/server/server.c
@@ -21,12 +21,6 @@
#include "panel.h"
#include "topwin.h"
-#define RTGUI_SVR_THREAD_PRIORITY 96
-#define RTGUI_SVR_THREAD_TIMESLICE 20
-
-#define RTGUI_APP_THREAD_PRIORITY 220
-#define RTGUI_APP_THREAD_TIMESLICE 20
-
static char rtgui_server_stack[2048];
static struct rt_thread rtgui_server_thread;
diff --git a/rtgui/server/topwin.c b/rtgui/server/topwin.c
new file mode 100644
index 0000000000..0deadae976
--- /dev/null
+++ b/rtgui/server/topwin.c
@@ -0,0 +1,868 @@
+/*
+ * File : topwin.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include "panel.h"
+#include "topwin.h"
+#include "mouse.h"
+
+#include <rtgui/event.h>
+#include <rtgui/image.h>
+#include <rtgui/rtgui_theme.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/widgets/window.h>
+
+struct rtgui_topwin* rtgui_server_focus_topwin = RT_NULL;
+
+static struct rtgui_list_node _rtgui_topwin_show_list;
+static struct rtgui_list_node _rtgui_topwin_hide_list;
+
+static void rtgui_topwin_update_clip(void);
+static void rtgui_topwin_redraw(struct rtgui_rect* rect);
+
+#define WINTITLE_CB_WIDTH 14
+#define WINTITLE_CB_HEIGHT 14
+
+void rtgui_topwin_init()
+{
+ /* init window list */
+ rtgui_list_init(&_rtgui_topwin_show_list);
+ rtgui_list_init(&_rtgui_topwin_hide_list);
+}
+
+static struct rtgui_topwin*
+rtgui_topwin_search_in_list(struct rtgui_win* wid, struct rtgui_list_node* list)
+{
+ struct rtgui_list_node* node;
+ struct rtgui_topwin* topwin;
+
+ /* search in list */
+ rtgui_list_foreach(node, list)
+ {
+ topwin = rtgui_list_entry(node, struct rtgui_topwin, list);
+
+ /* is this node? */
+ if (topwin->wid == wid)
+ {
+ return topwin;
+ }
+ }
+
+ return RT_NULL;
+}
+
+/* add a window to window list[hide] */
+rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event)
+{
+ struct rtgui_topwin* topwin;
+
+ topwin = rtgui_malloc(sizeof(struct rtgui_topwin));
+ if (topwin == RT_NULL) return -RT_ERROR;
+
+ topwin->wid = event->wid;
+ topwin->extent = event->extent;
+ topwin->tid = event->parent.sender;
+ topwin->mask = event->mask;
+
+ topwin->flag = 0;
+ if (event->flag & RTGUI_WIN_STYLE_NO_TITLE) topwin->flag |= WINTITLE_NO;
+ if (event->flag & RTGUI_WIN_STYLE_CLOSEBOX) topwin->flag |= WINTITLE_CLOSEBOX;
+ if (!(event->flag & RTGUI_WIN_STYLE_NO_BORDER)) topwin->flag |= WINTITLE_BORDER;
+ if (event->flag & RTGUI_WIN_STYLE_NO_FOCUS) topwin->flag |= WINTITLE_NOFOCUS;
+
+ if(!(topwin->flag & WINTITLE_NO) || (topwin->flag & WINTITLE_BORDER))
+ {
+ /* get win extent */
+ rtgui_rect_t rect = topwin->extent;
+
+ /* add border rect */
+ if (topwin->flag & WINTITLE_BORDER)
+ {
+ rect.x1 -= WINTITLE_BORDER_SIZE;
+ rect.y1 -= WINTITLE_BORDER_SIZE;
+ rect.x2 += WINTITLE_BORDER_SIZE;
+ rect.y2 += WINTITLE_BORDER_SIZE;
+ }
+
+ /* add title rect */
+ if (!(topwin->flag & WINTITLE_NO)) rect.y1 -= WINTITLE_HEIGHT;
+
+ topwin->title = rtgui_wintitle_create(event->title);
+ rtgui_widget_set_rect(RTGUI_WIDGET(topwin->title), &rect);
+
+ /* update clip info */
+ rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title));
+ rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip),
+ &(RTGUI_WIDGET(topwin->title)->clip),
+ &(topwin->extent));
+ }
+ else topwin->title = RT_NULL;
+
+ rtgui_list_init(&topwin->list);
+ rtgui_list_init(&topwin->monitor_list);
+
+ /* add topwin node to the hidden window list */
+ rtgui_list_insert(&(_rtgui_topwin_hide_list), &(topwin->list));
+
+ return RT_EOK;
+}
+
+rt_err_t rtgui_topwin_remove(struct rtgui_win* wid)
+{
+ struct rtgui_topwin* topwin;
+
+ /* find the topwin node */
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
+
+ if (topwin)
+ {
+ /* remove node from list */
+ rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
+
+ rtgui_topwin_update_clip();
+
+ /* redraw the old rect */
+ rtgui_topwin_redraw(&(topwin->extent));
+
+ if (rtgui_server_focus_topwin == topwin)
+ {
+ /* activate the next window */
+ if (_rtgui_topwin_show_list.next != RT_NULL)
+ {
+ struct rtgui_event_win wevent;
+ struct rtgui_topwin* wnd;
+
+ /* get the topwin */
+ wnd = rtgui_list_entry(_rtgui_topwin_show_list.next,
+ struct rtgui_topwin, list);
+
+ /* activate the window */
+ RTGUI_EVENT_WIN_ACTIVATE_INIT(&wevent);
+ wevent.wid = wnd->wid;
+ rtgui_thread_send(wnd->tid, &(wevent.parent), sizeof(struct rtgui_event_win));
+
+ /* set new focus topwin */
+ rtgui_server_focus_topwin = wnd;
+ }
+ else
+ {
+ /* there is no shown window right now */
+ rtgui_server_focus_topwin = RT_NULL;
+ }
+ }
+
+ /* free the monitor rect list, topwin node and title */
+ while (topwin->monitor_list.next != RT_NULL)
+ {
+ struct rtgui_mouse_monitor* monitor = rtgui_list_entry(topwin->monitor_list.next,
+ struct rtgui_mouse_monitor, list);
+
+ topwin->monitor_list.next = topwin->monitor_list.next->next;
+ rtgui_free(monitor);
+ }
+
+ /* destroy win title */
+ rtgui_wintitle_destroy(topwin->title);
+ topwin->title = RT_NULL;
+
+ rtgui_free(topwin);
+
+ return RT_EOK;
+ }
+
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
+ if (topwin)
+ {
+ /* remove node from list */
+ rtgui_list_remove(&_rtgui_topwin_hide_list, &(topwin->list));
+
+ /* free the topwin node and title */
+ rtgui_wintitle_destroy(topwin->title);
+ topwin->title = RT_NULL;
+
+ rtgui_free(topwin);
+
+ return RT_EOK;
+ }
+
+ return -RT_ERROR;
+}
+
+/* activate a win
+ * - deactivate the old focus win
+ * - activate a win
+ * - set the focus win to activate win
+ * - draw win title
+ */
+void rtgui_topwin_activate_win(struct rtgui_topwin* win)
+{
+ struct rtgui_event_win event;
+
+ /* activate the raised window */
+ RTGUI_EVENT_WIN_ACTIVATE_INIT(&event);
+ event.wid = win->wid;
+ rtgui_thread_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win));
+
+ /* redraw title */
+ if (win->title != RT_NULL)
+ {
+ win->flag |= WINTITLE_ACTIVATE;
+ rtgui_theme_draw_win(win);
+ }
+
+ if (rtgui_server_focus_topwin != RT_NULL)
+ {
+ /* deactivate the old focus win */
+ RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event);
+ event.wid = rtgui_server_focus_topwin->wid;
+ rtgui_thread_send(rtgui_server_focus_topwin->tid,
+ &event.parent, sizeof(struct rtgui_event_win));
+
+ /* redraw title */
+ if (rtgui_server_focus_topwin->title != RT_NULL)
+ {
+ rtgui_server_focus_topwin->flag &= ~WINTITLE_ACTIVATE;
+ rtgui_theme_draw_win(rtgui_server_focus_topwin);
+ }
+ }
+
+ rtgui_server_focus_topwin = win;
+}
+
+/*
+ * deactivate a win
+ * - deactivate the win
+ * - redraw win title
+ * - set rtgui_server_focus_topwin
+ */
+void rtgui_topwin_deactivate_win(struct rtgui_topwin* win)
+{
+ /* deactivate win */
+ struct rtgui_event_win event;
+ RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event);
+ event.wid = win->wid;
+ rtgui_thread_send(win->tid,
+ &event.parent, sizeof(struct rtgui_event_win));
+
+ win->flag &= ~WINTITLE_ACTIVATE;
+ rtgui_theme_draw_win(win);
+
+ if (rtgui_server_focus_topwin == win)
+ {
+ rtgui_server_focus_topwin = RT_NULL;
+ }
+}
+
+/* raise window to front */
+void rtgui_topwin_raise(struct rtgui_win* wid, rt_thread_t sender)
+{
+ struct rtgui_topwin* topwin;
+
+ /* find the topwin node */
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
+ if (topwin)
+ {
+ rt_int32_t count;
+ struct rtgui_list_node* node;
+ struct rtgui_event_clip_info* eclip;
+ struct rtgui_rect* rect;
+
+ /* the window is already placed in front */
+ if (&(topwin->list) == _rtgui_topwin_show_list.next)
+ {
+ rtgui_server_focus_topwin = RT_NULL;
+ rtgui_topwin_activate_win(topwin);
+ return ;
+ }
+
+ /* update clip info */
+ count = 0;
+ node = _rtgui_topwin_show_list.next;
+ while (node != &(topwin->list))
+ {
+ count ++;
+ node = node->next;
+ }
+
+ eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info)
+ + (count + 1)* sizeof(struct rtgui_rect));
+
+ /* reset clip info to top window */
+ RTGUI_EVENT_CLIP_INFO_INIT(eclip);
+ eclip->num_rect = 0;
+ eclip->wid = topwin->wid;
+ /* send to destination window */
+ rtgui_thread_send(topwin->tid, &(eclip->parent), sizeof(struct rtgui_event_clip_info));
+
+ /* reset clip info in title */
+ rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(topwin->title), eclip);
+ rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title));
+ rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip),
+ &(RTGUI_WIDGET(topwin->title)->clip),
+ &(topwin->extent));
+
+ rect = RTGUI_EVENT_GET_RECT(eclip, 0);
+ *rect = (topwin->title != RT_NULL)? RTGUI_WIDGET(topwin->title)->extent : topwin->extent;
+
+ count = 1;
+ for (node = _rtgui_topwin_show_list.next;
+ node != &(topwin->list);
+ node = node->next)
+ {
+ struct rtgui_topwin* wnd;
+ wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
+
+ eclip->num_rect = count;
+ eclip->wid = wnd->wid;
+
+ /* send to destination window */
+ rtgui_thread_send(wnd->tid, &(eclip->parent),
+ sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect));
+
+ /* reset clip info in title */
+ rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(wnd->title), eclip);
+ rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title));
+ rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip),
+ &(RTGUI_WIDGET(wnd->title)->clip),
+ &(wnd->extent));
+
+ rect = RTGUI_EVENT_GET_RECT(eclip, count++);
+ *rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent;
+ }
+
+ /* release clip info event */
+ rtgui_free(eclip);
+
+ /* remove node from list */
+ rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
+ /* add to front */
+ rtgui_list_insert(&_rtgui_topwin_show_list, &(topwin->list));
+
+ rtgui_topwin_activate_win(topwin);
+ }
+}
+
+/* show a window */
+void rtgui_topwin_show(struct rtgui_event_win* event)
+{
+ struct rtgui_topwin* topwin;
+ struct rtgui_win* wid = event->wid;
+ rt_thread_t sender = RTGUI_EVENT(event)->sender;
+
+ /* find in hide list */
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
+
+ /* find it */
+ if (topwin != RT_NULL)
+ {
+ /* remove node from hidden list */
+ rtgui_list_remove(&_rtgui_topwin_hide_list, &(topwin->list));
+
+ /* add node to show list */
+ rtgui_list_insert(&_rtgui_topwin_show_list, &(topwin->list));
+
+ /* show window title */
+ if (topwin->title != RT_NULL)
+ {
+ RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(topwin->title));
+ }
+
+ /* update clip info */
+ rtgui_topwin_update_clip();
+
+ rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
+
+ /* activate this window */
+ rtgui_topwin_activate_win(topwin);
+ }
+ else
+ {
+ /* the wnd is located in show list, raise wnd to front */
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
+ if (topwin != RT_NULL)
+ {
+ if (_rtgui_topwin_show_list.next != &(topwin->list))
+ {
+ rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
+
+ /* not the front window, raise it */
+ rtgui_topwin_raise(wid, sender);
+ }
+ }
+ else
+ {
+ /* there is no wnd in wnd list */
+ rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
+ }
+ }
+}
+
+/* send clip info to panel */
+void rtgui_topwin_update_clip_to_panel(struct rtgui_panel* panel)
+{
+ rt_uint32_t count;
+ rt_thread_t tid;
+ struct rtgui_list_node* node;
+ struct rtgui_event_clip_info* eclip;
+
+ /* get topwin count */
+ count = 0;
+ node = _rtgui_topwin_show_list.next;
+ while (node != RT_NULL)
+ {
+ count ++;
+ node = node->next;
+ }
+
+ eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info)
+ + (count + 1)* sizeof(struct rtgui_rect));
+ if (eclip == RT_NULL)
+ {
+ /* no memory */
+ return ;
+ }
+
+ /* reset clip info to top window */
+ RTGUI_EVENT_CLIP_INFO_INIT(eclip);
+ eclip->num_rect = count; eclip->wid = RT_NULL;
+
+ count = 0;
+ for (node = _rtgui_topwin_show_list.next; node != RT_NULL; node = node->next)
+ {
+ struct rtgui_topwin* wnd;
+ struct rtgui_rect* rect;
+
+ wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
+
+ rect = RTGUI_EVENT_GET_RECT(eclip, count++);
+ *rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent;
+ }
+
+ /* send to the activated thread of panel */
+ tid = rtgui_panel_get_active_thread(panel);
+ rtgui_thread_send(tid, (struct rtgui_event*)eclip, sizeof(struct rtgui_event_clip_info)
+ + count* sizeof(struct rtgui_rect));
+
+ /* release clip info event */
+ rtgui_free(eclip);
+}
+
+/* hide a window */
+void rtgui_topwin_hide(struct rtgui_event_win* event)
+{
+ struct rtgui_topwin* topwin;
+ struct rtgui_win* wid = event->wid;
+
+ /* find in show list */
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
+
+ /* found it */
+ if (topwin)
+ {
+ /* remove node from show list */
+ rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
+
+ /* add node to hidden list */
+ rtgui_list_insert(&_rtgui_topwin_hide_list, &(topwin->list));
+
+ /* show window title */
+ if (topwin->title != RT_NULL)
+ {
+ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(topwin->title));
+ }
+
+ /* update clip info */
+ rtgui_topwin_update_clip();
+
+ /* redraw the old rect */
+ rtgui_topwin_redraw(&(topwin->extent));
+
+ if (rtgui_server_focus_topwin == topwin)
+ {
+ /* activate the next window */
+ if (_rtgui_topwin_show_list.next != RT_NULL)
+ {
+ /* get the topwin */
+ topwin = rtgui_list_entry(_rtgui_topwin_show_list.next,
+ struct rtgui_topwin, list);
+
+ rtgui_server_focus_topwin = RT_NULL;
+ rtgui_topwin_activate_win(topwin);
+ }
+ else
+ {
+ /* there is no shown window right now */
+ rtgui_server_focus_topwin = RT_NULL;
+ }
+ }
+ }
+ else
+ {
+ rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
+ return;
+ }
+
+ rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
+}
+
+/* move top window */
+void rtgui_topwin_move(struct rtgui_event_win_move* event)
+{
+ struct rtgui_topwin* topwin;
+
+ /* find in show list */
+ topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_show_list);
+ if (topwin != RT_NULL)
+ {
+ int dx, dy;
+ rtgui_rect_t rect; /* the old topwin coverage area */
+ struct rtgui_list_node* node;
+
+ /* send status ok */
+ rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
+
+ /* get the delta move x, y */
+ dx = event->x - topwin->extent.x1;
+ dy = event->y - topwin->extent.y1;
+
+ rect = topwin->extent;
+ /* move window rect */
+ rtgui_rect_moveto(&(topwin->extent), dx, dy);
+
+ /* move window title */
+ if (topwin->title != RT_NULL)
+ {
+ rect = RTGUI_WIDGET(topwin->title)->extent;
+ rtgui_widget_move_to_logic(RTGUI_WIDGET(topwin->title), dx, dy);
+ }
+
+ /* move the monitor rect list */
+ rtgui_list_foreach(node, &(topwin->monitor_list))
+ {
+ struct rtgui_mouse_monitor* monitor = rtgui_list_entry(node,
+ struct rtgui_mouse_monitor,
+ list);
+ rtgui_rect_moveto(&(monitor->rect), dx, dy);
+ }
+
+ /* update windows clip info */
+ rtgui_topwin_update_clip();
+
+ /* update top window title */
+ if (topwin->title != RT_NULL) rtgui_theme_draw_win(topwin);
+ if (rtgui_rect_is_intersect(&rect, &(topwin->extent)) != RT_EOK)
+ {
+ /*
+ * the old rect is not intersect with moved rect,
+ * re-paint window
+ */
+ struct rtgui_event_paint epaint;
+ RTGUI_EVENT_PAINT_INIT(&epaint);
+ epaint.wid = topwin->wid;
+ rtgui_thread_send(topwin->tid, &(epaint.parent), sizeof(epaint));
+ }
+
+ /* update old window coverage area */
+ rtgui_topwin_redraw(&rect);
+ }
+ else
+ {
+ rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
+ }
+}
+
+/*
+ * resize a top win
+ * Note: currently, only support resize hidden window
+ */
+void rtgui_topwin_resize(struct rtgui_win* wid, rtgui_rect_t* r)
+{
+ struct rtgui_topwin* topwin;
+
+ /* find in show list */
+ topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
+ if (topwin)
+ {
+ topwin->extent = *r;
+
+ if (topwin->title != RT_NULL)
+ {
+ /* get win extent */
+ rtgui_rect_t rect = topwin->extent;
+
+ /* add border rect */
+ if (topwin->flag & WINTITLE_BORDER)
+ {
+ rect.x1 -= WINTITLE_BORDER_SIZE;
+ rect.y1 -= WINTITLE_BORDER_SIZE;
+ rect.x2 += WINTITLE_BORDER_SIZE;
+ rect.y2 += WINTITLE_BORDER_SIZE;
+ }
+
+ /* add title rect */
+ if (!(topwin->flag & WINTITLE_NO)) rect.y1 -= WINTITLE_HEIGHT;
+
+ RTGUI_WIDGET(topwin->title)->extent = rect;
+
+ /* update title & border clip info */
+ rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title));
+ rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip),
+ &(RTGUI_WIDGET(topwin->title)->clip),
+ &(topwin->extent));
+ }
+ }
+}
+
+struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y)
+{
+ struct rtgui_list_node* node;
+ struct rtgui_topwin* topwin;
+
+ /* search in list */
+ rtgui_list_foreach(node, &(_rtgui_topwin_show_list))
+ {
+ topwin = rtgui_list_entry(node, struct rtgui_topwin, list);
+
+ /* is this window? */
+ if ((topwin->title != RT_NULL) &&
+ rtgui_rect_contains_point(&(RTGUI_WIDGET(topwin->title)->extent), x, y) == RT_EOK)
+ {
+ return topwin;
+ }
+ else if (rtgui_rect_contains_point(&(topwin->extent), x, y) == RT_EOK)
+ {
+ return topwin;
+ }
+ }
+
+ return RT_NULL;
+}
+
+extern struct rtgui_list_node _rtgui_panel_list;
+static void rtgui_topwin_update_clip()
+{
+ rt_int32_t count = 0;
+ struct rtgui_event_clip_info* eclip;
+ struct rtgui_list_node* node = _rtgui_topwin_show_list.next;
+
+ /* calculate count */
+ while (node != RT_NULL)
+ {
+ count ++;
+ node = node->next;
+ }
+
+ eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info)
+ + count * sizeof(struct rtgui_rect));
+ RTGUI_EVENT_CLIP_INFO_INIT(eclip);
+
+ count = 0;
+ rtgui_list_foreach(node, &_rtgui_topwin_show_list)
+ {
+ struct rtgui_rect* rect;
+ struct rtgui_topwin* wnd;
+ wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
+
+ eclip->num_rect = count;
+ eclip->wid = wnd->wid;
+
+ /* send to destination window */
+ rtgui_thread_send(wnd->tid, &(eclip->parent),
+ sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect));
+
+ /* update clip in win title */
+ if (wnd->title != RT_NULL)
+ {
+ /* reset clip info */
+ rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(wnd->title), eclip);
+ rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title));
+ rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip),
+ &(RTGUI_WIDGET(wnd->title)->clip),
+ &(wnd->extent));
+ }
+
+ rect = RTGUI_EVENT_GET_RECT(eclip, count++);
+ *rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent;
+ }
+
+ /* send clip info to each panel */
+ eclip->wid = RT_NULL;
+ eclip->num_rect = count;
+
+ rtgui_list_foreach(node, &(_rtgui_panel_list))
+ {
+ struct rtgui_panel* panel;
+ struct rtgui_list_node* panel_node;
+
+ panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
+
+ rtgui_list_foreach(panel_node, &(panel->thread_list))
+ {
+ struct rtgui_panel_thread* thread;
+ thread = rtgui_list_entry(panel_node, struct rtgui_panel_thread, list);
+
+ /* send clip info to panel */
+ rtgui_thread_send(thread->tid, &(eclip->parent),
+ sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect));
+ }
+ }
+
+ /* release clip info event */
+ rtgui_free(eclip);
+}
+
+static void rtgui_topwin_redraw(struct rtgui_rect* rect)
+{
+ struct rtgui_list_node* node;
+ struct rtgui_event_paint epaint;
+ RTGUI_EVENT_PAINT_INIT(&epaint);
+
+ rtgui_list_foreach(node, &_rtgui_topwin_show_list)
+ {
+ struct rtgui_topwin* wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
+
+ if (rtgui_rect_is_intersect(rect, &(wnd->extent)) == RT_EOK)
+ {
+ /* draw window */
+ epaint.wid = wnd->wid;
+ rtgui_thread_send(wnd->tid, &(epaint.parent), sizeof(epaint));
+
+ /* draw title */
+ if (wnd->title != RT_NULL)
+ {
+ rtgui_theme_draw_win(wnd);
+ }
+ }
+ }
+
+ /* redraw the panel */
+ rtgui_list_foreach(node, &(_rtgui_panel_list))
+ {
+ struct rtgui_panel* panel;
+ panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
+
+ if (rtgui_rect_is_intersect(rect, &(panel->extent)) == RT_EOK)
+ {
+ /* draw panel */
+ epaint.wid = RT_NULL;
+ rtgui_thread_send(rtgui_panel_get_active_thread(panel),
+ &(epaint.parent), sizeof(epaint));
+ }
+ }
+}
+
+void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mouse* event)
+{
+ rtgui_rect_t rect;
+
+ /* let window to process this mouse event */
+ if (rtgui_rect_contains_point(&win->extent, event->x, event->y) == RT_EOK)
+ {
+ /* send mouse event to thread */
+ rtgui_thread_send(win->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
+ return;
+ }
+
+ /* get close button rect (device value) */
+ rect.x1 = RTGUI_WIDGET(win->title)->extent.x2 - WINTITLE_BORDER_SIZE - WINTITLE_CB_WIDTH - 3;
+ rect.y1 = RTGUI_WIDGET(win->title)->extent.y1 + WINTITLE_BORDER_SIZE + 3;
+ rect.x2 = rect.x1 + WINTITLE_CB_WIDTH;
+ rect.y2 = rect.y1 + WINTITLE_CB_HEIGHT;
+
+ if (event->button & RTGUI_MOUSE_BUTTON_LEFT)
+ {
+ if (event->button & RTGUI_MOUSE_BUTTON_DOWN)
+ {
+ if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK)
+ {
+ win->flag |= WINTITLE_CB_PRESSED;
+ rtgui_theme_draw_win(win);
+ }
+ else
+ {
+ /* maybe move window */
+ rtgui_winrect_set(win);
+ }
+ }
+ else if (event->button & RTGUI_MOUSE_BUTTON_UP)
+ {
+ if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK)
+ {
+ struct rtgui_event_win event;
+
+ win->flag &= ~WINTITLE_CB_PRESSED;
+ rtgui_theme_draw_win(win);
+
+ /* send close event to window */
+ RTGUI_EVENT_WIN_CLOSE_INIT(&event);
+ event.wid = win->wid;
+ rtgui_thread_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win));
+ }
+ }
+ }
+}
+
+void rtgui_topwin_append_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect)
+{
+ struct rtgui_topwin* win;
+
+ /* parameters check */
+ if (wid == RT_NULL || rect == RT_NULL) return;
+
+ /* find topwin */
+ win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
+ if (win == RT_NULL)
+ win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
+
+ if (win == RT_NULL) return;
+
+ /* append rect to top window monitor rect list */
+ rtgui_mouse_monitor_append(&(win->monitor_list), rect);
+}
+
+void rtgui_topwin_remove_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect)
+{
+ struct rtgui_topwin* win;
+
+ /* parameters check */
+ if (wid == RT_NULL || rect == RT_NULL) return;
+
+ /* find topwin */
+ win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
+ if (win == RT_NULL)
+ win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
+
+ if (win == RT_NULL) return;
+
+ /* remove rect from top window monitor rect list */
+ rtgui_mouse_monitor_remove(&(win->monitor_list), rect);
+}
+
+void rtgui_topwin_dump()
+{
+ struct rtgui_list_node* node;
+
+ rtgui_list_foreach(node, &_rtgui_topwin_show_list)
+ {
+ struct rtgui_topwin* wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
+
+ rt_kprintf("wnd at (%d, %d) - (%d, %d)\n",
+ wnd->extent.x1, wnd->extent.y1, wnd->extent.x2, wnd->extent.y2);
+
+ if (wnd->title != RT_NULL)
+ {
+ rt_kprintf("title[%s] border (%d, %d) - (%d, %d)\n", wnd->title->title,
+ RTGUI_WIDGET(wnd->title)->extent.x1, RTGUI_WIDGET(wnd->title)->extent.y1,
+ RTGUI_WIDGET(wnd->title)->extent.x2, RTGUI_WIDGET(wnd->title)->extent.y2);
+ }
+ }
+}
diff --git a/rtgui/server/topwin.h b/rtgui/server/topwin.h
new file mode 100644
index 0000000000..64d0a8a767
--- /dev/null
+++ b/rtgui/server/topwin.h
@@ -0,0 +1,56 @@
+/*
+ * File : topwin.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#ifndef __RTGUI_TOPWIN_H__
+#define __RTGUI_TOPWIN_H__
+
+#include <rtgui/rtgui.h>
+#include <rtgui/list.h>
+#include <rtgui/region.h>
+#include <rtgui/event.h>
+#include <rtgui/widgets/title.h>
+#include <rtgui/rtgui_server.h>
+
+/* add or remove a top win */
+rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event);
+rt_err_t rtgui_topwin_remove(struct rtgui_win* wid);
+
+/* raise window to front */
+void rtgui_topwin_raise(struct rtgui_win* wid, rt_thread_t sender);
+/* update clip info to a panel */
+void rtgui_topwin_update_clip_to_panel(struct rtgui_panel* panel);
+
+/* show a window */
+void rtgui_topwin_show(struct rtgui_event_win* event);
+/* hide a window */
+void rtgui_topwin_hide(struct rtgui_event_win* event);
+/* move a window */
+void rtgui_topwin_move(struct rtgui_event_win_move* event);
+/* resize a window */
+void rtgui_topwin_resize(struct rtgui_win* wid, rtgui_rect_t* r);
+
+/* get window at (x, y) */
+struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y);
+
+void rtgui_topwin_activate_win(struct rtgui_topwin* win);
+void rtgui_topwin_deactivate_win(struct rtgui_topwin* win);
+
+/* window title */
+void rtgui_topwin_title_ondraw(struct rtgui_topwin* win);
+void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mouse* event);
+
+/* monitor rect */
+void rtgui_topwin_append_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect);
+void rtgui_topwin_remove_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect);
+
+#endif
diff --git a/rtgui/widgets/box.c b/rtgui/widgets/box.c
new file mode 100644
index 0000000000..a9d16311c8
--- /dev/null
+++ b/rtgui/widgets/box.c
@@ -0,0 +1,340 @@
+/*
+ * File : box.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/widgets/box.h>
+
+static void _rtgui_box_constructor(rtgui_box_t *box)
+{
+ /* init widget and set event handler */
+ rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_box_event_handler);
+
+ RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT;
+ rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_box_event_handler);
+
+ /* set proper of control */
+ box->orientation = RTGUI_HORIZONTAL;
+ box->border_size = RTGUI_BORDER_DEFAULT_WIDTH;
+}
+
+rtgui_type_t *rtgui_box_type_get(void)
+{
+ static rtgui_type_t *box_type = RT_NULL;
+
+ if (!box_type)
+ {
+ box_type = rtgui_type_create("box", RTGUI_CONTAINER_TYPE,
+ sizeof(rtgui_box_t), RTGUI_CONSTRUCTOR(_rtgui_box_constructor), RT_NULL);
+ }
+
+ return box_type;
+}
+
+rt_bool_t rtgui_box_event_handler(rtgui_widget_t* widget, rtgui_event_t* event)
+{
+ struct rtgui_box* box = (struct rtgui_box*)widget;
+
+ RT_ASSERT(box != RT_NULL);
+
+ switch (event->type)
+ {
+ case RTGUI_EVENT_RESIZE:
+ /* re-layout */
+ rtgui_box_layout(box);
+ break;
+
+ default:
+ return rtgui_container_event_handler(RTGUI_WIDGET(box), event);
+ }
+
+ return RT_FALSE;
+}
+
+struct rtgui_box* rtgui_box_create(int orientation, rtgui_rect_t* rect)
+{
+ struct rtgui_box* box;
+
+ box = (struct rtgui_box*) rtgui_widget_create (RTGUI_BOX_TYPE);
+ if (box != RT_NULL)
+ {
+ /* set proper of control */
+ rtgui_widget_set_rect(RTGUI_WIDGET(box), rect);
+ box->orientation = orientation;
+ }
+
+ return box;
+}
+
+void rtgui_box_append(struct rtgui_box* box, rtgui_widget_t* widget)
+{
+ /* put to box's children list */
+ rtgui_container_add_child(RTGUI_CONTAINER(box), widget);
+}
+
+static void rtgui_box_layout_vertical(rtgui_box_t* box)
+{
+ rtgui_list_t *node;
+ rt_int32_t box_width;
+ rt_int32_t space_count;
+ rt_int32_t next_x, next_y;
+ rt_int32_t total_height, space_height;
+ struct rtgui_event_resize size_event;
+
+ /* prepare the resize event */
+ RTGUI_EVENT_RESIZE_INIT(&size_event);
+
+ /* find spaces */
+ space_count = 0;
+ total_height = 0;
+ space_height = 0;
+
+ rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+ {
+ rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
+ if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
+ else total_height += widget->mini_height;
+ }
+
+ /* calculate the height for each spaces */
+ if (space_count != 0)
+ {
+ space_height = (rtgui_rect_height(RTGUI_WIDGET(box)->extent) - total_height - (box->border_size << 1)) / space_count;
+ }
+
+ /* init (x, y) and box width */
+ next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
+ next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
+ box_width = rtgui_rect_width(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
+
+ /* layout each widget */
+ rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+ {
+ rtgui_rect_t *rect;
+ rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
+
+ /* get extent of widget */
+ rect = &(widget->extent);
+
+ /* reset rect */
+ rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
+ rect->x2 = widget->mini_width;
+ rect->y2 = widget->mini_height;
+
+ /* left in default */
+ rtgui_rect_moveto(rect, next_x, next_y);
+
+ if (widget->align & RTGUI_ALIGN_EXPAND)
+ {
+ /* expand on horizontal */
+ rect->x2 = rect->x1 + (rt_int16_t)box_width;
+ }
+ if (widget->align & RTGUI_ALIGN_CENTER_VERTICAL)
+ {
+ /* center */
+ rt_uint32_t mid;
+
+ mid = box_width - rtgui_rect_width(*rect);
+ mid = mid /2;
+
+ rect->x1 = next_x + mid;
+ rect->x2 = next_x + box_width - mid;
+ }
+ else if (widget->align & RTGUI_ALIGN_RIGHT)
+ {
+ /* right */
+ rect->x1 = next_x + box_width - rtgui_rect_width(*rect);
+ rect->x2 = next_x + box_width;
+ }
+
+ if (widget->align & RTGUI_ALIGN_STRETCH)
+ {
+ rect->y2 = rect->y1 + space_height;
+ }
+
+ /* process resize event */
+ size_event.x = rect->x1;
+ size_event.y = rect->y1;
+ size_event.w = rect->x2 - rect->x1;
+ size_event.h = rect->y2 - rect->y1;
+ widget->event_handler(widget, &size_event.parent);
+
+ /* point to next height */
+ next_y = rect->y2;
+ }
+}
+
+static void rtgui_box_layout_horizontal(rtgui_box_t* box)
+{
+ rtgui_list_t *node;
+ rt_int32_t box_height;
+ rt_int32_t space_count;
+ rt_int32_t next_x, next_y;
+ rt_int32_t total_width, space_width;
+ struct rtgui_event_resize size_event;
+
+ /* prepare the resize event */
+ RTGUI_EVENT_RESIZE_INIT(&size_event);
+
+ /* find spaces */
+ space_count = 0;
+ total_width = 0;
+ space_width = 0;
+
+ rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+ {
+ rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
+ if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
+ else total_width += widget->mini_width;
+ }
+
+ if (space_count != 0)
+ {
+ /* calculate the height for each spaces */
+ space_width = (rtgui_rect_width(RTGUI_WIDGET(box)->extent) - total_width) / space_count;
+ }
+
+ /* init (x, y) and box height */
+ next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
+ next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
+ box_height = rtgui_rect_height(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
+
+ /* layout each widget */
+ rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+ {
+ rtgui_rect_t *rect;
+ rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
+
+ /* get extent of widget */
+ rect = &(widget->extent);
+
+ /* reset rect */
+ rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
+ rect->x2 = widget->mini_width;
+ rect->y2 = widget->mini_height;
+
+ /* top in default */
+ rtgui_rect_moveto(rect, next_x, next_y);
+
+ if (widget->align & RTGUI_ALIGN_EXPAND)
+ {
+ /* expand on vertical */
+ rect->y2 = rect->y1 + box_height;
+ }
+ if (widget->align & RTGUI_ALIGN_CENTER_HORIZONTAL)
+ {
+ /* center */
+ rt_uint32_t mid;
+
+ mid = box_height - rtgui_rect_height(*rect);
+ mid = mid /2;
+
+ rect->y1 = next_y + mid;
+ rect->y2 = next_y + box_height - mid;
+ }
+ else if (widget->align & RTGUI_ALIGN_RIGHT)
+ {
+ /* right */
+ rect->y1 = next_y + box_height - rtgui_rect_height(*rect);
+ rect->y2 = next_y + box_height;
+ }
+
+ if (widget->align & RTGUI_ALIGN_STRETCH)
+ {
+ rect->x2 = rect->x1 + space_width;
+ }
+
+ /* process resize event */
+ size_event.x = rect->x1;
+ size_event.y = rect->y1;
+ size_event.w = rect->x2 - rect->x1;
+ size_event.h = rect->y2 - rect->y1;
+ widget->event_handler(widget, &size_event.parent);
+
+ /* point to next width */
+ next_x = rect->x2;
+ }
+}
+
+void rtgui_box_layout(rtgui_box_t* box)
+{
+ RT_ASSERT(box != RT_NULL);
+
+ if (box->orientation & RTGUI_VERTICAL)
+ {
+ rtgui_box_layout_vertical(box);
+ }
+ else
+ {
+ rtgui_box_layout_horizontal(box);
+ }
+
+ /* update box and its children clip */
+ if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box)))
+ {
+ rtgui_widget_update_clip(RTGUI_WIDGET(box));
+ }
+}
+
+rt_uint32_t rtgui_box_get_width(rtgui_box_t* box)
+{
+ rtgui_list_t *node;
+ rt_uint32_t width;
+
+ width = 0;
+ rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+ {
+ rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
+ rt_uint32_t widget_width;
+
+ widget_width = rtgui_rect_width(widget->extent);
+ if (box->orientation & RTGUI_VERTICAL)
+ {
+ /* get the max width */
+ if (width < widget_width) width = widget_width;
+ }
+ else
+ {
+ /* get the total width */
+ width += widget_width;
+ }
+ }
+
+ return width;
+}
+
+rt_uint32_t rtgui_box_get_height(rtgui_box_t* box)
+{
+ rtgui_list_t *node;
+ rt_uint32_t height;
+
+ height = 0;
+ rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
+ {
+ rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
+ rt_uint32_t widget_height;
+
+ widget_height = rtgui_rect_height(widget->extent);
+ if (box->orientation & RTGUI_HORIZONTAL)
+ {
+ /* get the max height */
+ if (height < widget_height) height = widget_height;
+ }
+ else
+ {
+ /* get the total height */
+ height += widget_height;
+ }
+ }
+
+ return height;
+}
diff --git a/rtgui/widgets/button.c b/rtgui/widgets/button.c
new file mode 100644
index 0000000000..877f7faed5
--- /dev/null
+++ b/rtgui/widgets/button.c
@@ -0,0 +1,170 @@
+/*
+ * File : button.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/widgets/button.h>
+#include <rtgui/rtgui_theme.h>
+
+static void _rtgui_button_constructor(rtgui_button_t *button)
+{
+ /* init widget and set event handler */
+ RTGUI_WIDGET(button)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
+ rtgui_widget_set_event_handler(RTGUI_WIDGET(button), rtgui_button_event_handler);
+
+ /* un-press button */
+ button->flag &= ~RTGUI_BUTTON_FLAG_PRESS;
+
+ /* set flag and on_button event handler */
+ button->pressed_image = RT_NULL;
+ button->unpressed_image = RT_NULL;
+ button->on_button = RT_NULL;
+
+ /* set gc */
+ RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(button)) = default_foreground;
+ RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(button)) = RTGUI_RGB(212, 208, 200);
+ RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(button)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
+}
+
+rtgui_type_t *rtgui_button_type_get(void)
+{
+ static rtgui_type_t *button_type = RT_NULL;
+
+ if (!button_type)
+ {
+ button_type = rtgui_type_create("button", RTGUI_LABEL_TYPE,
+ sizeof(rtgui_button_t), RTGUI_CONSTRUCTOR(_rtgui_button_constructor), RT_NULL);
+ }
+
+ return button_type;
+}
+
+rt_bool_t rtgui_button_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+ struct rtgui_button* btn;
+
+ RT_ASSERT(widget != RT_NULL);
+
+ btn = (struct rtgui_button*) widget;
+ switch (event->type)
+ {
+ case RTGUI_EVENT_PAINT:
+ if (widget->on_draw != RT_NULL ) widget->on_draw(widget, event);
+ else rtgui_theme_draw_button(btn);
+ break;
+
+ case RTGUI_EVENT_MOUSE_BUTTON:
+ {
+ struct rtgui_event_mouse* emouse = (struct rtgui_event_mouse*)event;
+
+ if (btn->flag & RTGUI_BUTTON_TYPE_PUSH)
+ {
+ /* it's a push button */
+ if (emouse->button & RTGUI_MOUSE_BUTTON_UP)
+ {
+ if (btn->flag & RTGUI_BUTTON_FLAG_PRESS)
+ btn->flag &= ~RTGUI_BUTTON_FLAG_PRESS;
+ else
+ btn->flag |= RTGUI_BUTTON_FLAG_PRESS;
+
+ /* draw button */
+ if (widget->on_draw != RT_NULL ) widget->on_draw(widget, event);
+ else rtgui_theme_draw_button(btn);
+
+ /* invokes call back */
+ if (widget->on_mouseclick != RT_NULL &&
+ emouse->button & RTGUI_MOUSE_BUTTON_UP)
+ return widget->on_mouseclick(widget, event);
+ }
+ }
+ else
+ {
+ if (emouse->button & RTGUI_MOUSE_BUTTON_LEFT)
+ {
+ /* it's a normal button */
+ if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
+ {
+ btn->flag |= RTGUI_BUTTON_FLAG_PRESS;
+ }
+ else
+ {
+ btn->flag &= ~RTGUI_BUTTON_FLAG_PRESS;
+ }
+
+ /* draw button */
+ if (widget->on_draw != RT_NULL ) widget->on_draw(widget, event);
+ else rtgui_theme_draw_button(btn);
+
+ /* invokes call back */
+ if (widget->on_mouseclick != RT_NULL &&
+ emouse->button & RTGUI_MOUSE_BUTTON_UP)
+ return widget->on_mouseclick(widget, event);
+ }
+
+ }
+
+ return RT_TRUE;
+ }
+ }
+
+ return RT_FALSE;
+}
+
+rtgui_button_t* rtgui_button_create(unsigned char* text)
+{
+ struct rtgui_button* btn;
+
+ btn = (struct rtgui_button*) rtgui_widget_create (RTGUI_BUTTON_TYPE);
+ if (btn != RT_NULL)
+ {
+ rtgui_rect_t rect;
+
+ /* set default rect */
+ rtgui_font_get_metrics(rtgui_font_default(), text, &rect);
+ rect.x2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1);
+ rect.y2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1);
+ rtgui_widget_set_rect(RTGUI_WIDGET(btn), &rect);
+ rtgui_label_set_text(RTGUI_LABEL(btn), text);
+ }
+
+ return btn;
+}
+
+rtgui_button_t* rtgui_pushbutton_create(unsigned char* text)
+{
+ rtgui_button_t* btn;
+
+ btn = rtgui_button_create(text);
+ if (btn != RT_NULL) btn->flag |= RTGUI_BUTTON_TYPE_PUSH;
+
+ return btn;
+}
+
+void rtgui_button_destroy(rtgui_button_t* btn)
+{
+ rtgui_widget_destroy(RTGUI_WIDGET(btn));
+}
+
+void rtgui_button_set_pressed_image(rtgui_button_t* btn, rtgui_image_t* image)
+{
+ RT_ASSERT(btn != RT_NULL);
+
+ btn->pressed_image = image;
+}
+
+void rtgui_button_set_unpressed_image(rtgui_button_t* btn, rtgui_image_t* image)
+{
+ RT_ASSERT(btn != RT_NULL);
+
+ btn->unpressed_image = image;
+}
+
diff --git a/rtgui/widgets/container.c b/rtgui/widgets/container.c
new file mode 100644
index 0000000000..1a233807c6
--- /dev/null
+++ b/rtgui/widgets/container.c
@@ -0,0 +1,279 @@
+/*
+ * File : container.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/widgets/toplevel.h>
+#include <rtgui/widgets/container.h>
+
+static void _rtgui_container_constructor(rtgui_container_t *container)
+{
+ /* set event handler and init field */
+ rtgui_widget_set_event_handler(RTGUI_WIDGET(container), rtgui_container_event_handler);
+ rtgui_list_init(&(container->children));
+}
+
+static void _rtgui_container_destructor(rtgui_container_t *container)
+{
+ /* destroy children of container */
+ rtgui_container_destroy_children(container);
+}
+
+static void _rtgui_container_update_toplevel(rtgui_container_t* container)
+{
+ struct rtgui_list_node* node;
+
+ rtgui_list_foreach(node, &(container->children))
+ {
+ rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling);
+ /* set child toplevel */
+ child->toplevel = rtgui_widget_get_toplevel(RTGUI_WIDGET(container));
+
+ if (RTGUI_IS_CONTAINER(child))
+ {
+ _rtgui_container_update_toplevel(RTGUI_CONTAINER(child));
+ }
+ }
+}
+
+rtgui_type_t *rtgui_container_type_get(void)
+{
+ static rtgui_type_t *container_type = RT_NULL;
+
+ if (!container_type)
+ {
+ container_type = rtgui_type_create("container", RTGUI_WIDGET_TYPE,
+ sizeof(rtgui_container_t),
+ RTGUI_CONSTRUCTOR(_rtgui_container_constructor),
+ RTGUI_DESTRUCTOR(_rtgui_container_destructor));
+ }
+
+ return container_type;
+}
+
+rt_bool_t rtgui_container_dispatch_event(rtgui_container_t *container, rtgui_event_t* event)
+{
+ /* handle in child widget */
+ struct rtgui_list_node* node;
+
+ rtgui_list_foreach(node, &(container->children))
+ {
+ struct rtgui_widget* w;
+ w = rtgui_list_entry(node, struct rtgui_widget, sibling);
+
+ if (w->event_handler(w, event) == RT_TRUE) return RT_TRUE;
+ }
+
+ return RT_FALSE;
+}
+
+rt_bool_t rtgui_container_dispatch_mouse_event(rtgui_container_t *container, struct rtgui_event_mouse* event)
+{
+ /* handle in child widget */
+ struct rtgui_list_node* node;
+
+ rtgui_list_foreach(node, &(container->children))
+ {
+ struct rtgui_widget* w;
+ w = rtgui_list_entry(node, struct rtgui_widget, sibling);
+ if (rtgui_rect_contains_point(&(w->extent), event->x, event->y) == RT_EOK)
+ {
+ if (w->event_handler(w, (rtgui_event_t*)event) == RT_TRUE) return RT_TRUE;
+ }
+ }
+
+ return RT_FALSE;
+}
+
+rt_bool_t rtgui_container_event_handler(rtgui_widget_t* widget, rtgui_event_t* event)
+{
+ rtgui_container_t *container = RTGUI_CONTAINER(widget);
+
+ switch (event->type)
+ {
+ case RTGUI_EVENT_PAINT:
+ if (widget->on_draw != RT_NULL)
+ {
+ return widget->on_draw(widget, event);
+ }
+
+ rtgui_container_dispatch_event(container, event);
+ break;
+
+ case RTGUI_EVENT_KBD:
+ if (widget->on_key != RT_NULL)
+ {
+ return widget->on_key(widget, event);
+ }
+ else
+ {
+ /* let parent to handle keyboard event */
+ if (widget->parent != RT_NULL && widget->parent != widget->toplevel)
+ {
+ return widget->parent->event_handler(widget->parent, event);
+ }
+ }
+ break;
+
+ case RTGUI_EVENT_MOUSE_BUTTON:
+ /* handle in child widget */
+ if (rtgui_container_dispatch_mouse_event(container,
+ (struct rtgui_event_mouse*)event) == RT_FALSE)
+ {
+ /* handle event in current widget */
+ if (widget->on_mouseclick != RT_NULL)
+ {
+ return widget->on_mouseclick(widget, event);
+ }
+ }
+ else return RT_TRUE;
+ break;
+
+ case RTGUI_EVENT_MOUSE_MOTION:
+#if 0
+ if (rtgui_container_dispatch_mouse_event(container,
+ (struct rtgui_event_mouse*)event) == RT_FALSE)
+ {
+ /* handle event in current widget */
+ if (widget->on_mousemotion != RT_NULL)
+ {
+ return widget->on_mousemotion(widget, event);
+ }
+ }
+ else return RT_TRUE;
+#endif
+ break;
+
+ case RTGUI_EVENT_COMMAND:
+ if (rtgui_container_dispatch_event(container, event) == RT_FALSE)
+ {
+ if (widget->on_command != RT_NULL)
+ {
+ return widget->on_command(widget, event);
+ }
+ }
+ else return RT_TRUE;
+ break;
+
+ case RTGUI_EVENT_RESIZE:
+ if (rtgui_container_dispatch_event(container, event) == RT_FALSE)
+ {
+ if (widget->on_size != RT_NULL)
+ return widget->on_size(widget, event);
+ }
+ else return RT_TRUE;
+ break;
+
+ default:
+ /* call parent widget event handler */
+ return rtgui_widget_event_handler(widget, event);
+ }
+
+ return RT_FALSE;
+}
+
+/*
+ * This function will add a child to a container widget
+ * Note: this function will not change the widget layout
+ * the layout is the responsibility of layout widget, such as box.
+ */
+void rtgui_container_add_child(rtgui_container_t *container, rtgui_widget_t* child)
+{
+ RT_ASSERT(container != RT_NULL);
+ RT_ASSERT(child != RT_NULL);
+
+ /* set parent and toplevel widget */
+ child->parent = RTGUI_WIDGET(container);
+ /* put widget to parent's children list */
+ rtgui_list_append(&(container->children), &(child->sibling));
+
+ /* update children toplevel */
+ if (RTGUI_WIDGET(container)->toplevel != RT_NULL &&
+ RTGUI_IS_TOPLEVEL(RTGUI_WIDGET(container)->toplevel))
+ {
+ child->toplevel = rtgui_widget_get_toplevel(RTGUI_WIDGET(container));
+
+ /* update all child toplevel */
+ if (RTGUI_IS_CONTAINER(child))
+ {
+ _rtgui_container_update_toplevel(RTGUI_CONTAINER(child));
+ }
+ }
+}
+
+/* remove a child to widget */
+void rtgui_container_remove_child(rtgui_container_t *container, rtgui_widget_t* child)
+{
+ RT_ASSERT(container != RT_NULL);
+ RT_ASSERT(child != RT_NULL);
+
+ /* remove widget from parent's children list */
+ rtgui_list_remove(&(container->children), &(child->sibling));
+
+ /* set parent and toplevel widget */
+ child->parent = RT_NULL;
+ child->toplevel = RT_NULL;
+}
+
+/* destroy all children of container */
+void rtgui_container_destroy_children(rtgui_container_t *container)
+{
+ struct rtgui_list_node* node;
+
+ if (container == RT_NULL) return;
+
+ node = container->children.next;
+ while (node != RT_NULL)
+ {
+ rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling);
+
+ if (RTGUI_IS_CONTAINER(child))
+ {
+ /* destroy children of child */
+ rtgui_container_destroy_children(RTGUI_CONTAINER(child));
+ }
+
+ /* destroy object and remove from parent */
+ rtgui_object_destroy(RTGUI_OBJECT(child));
+
+ node = container->children.next;
+ }
+
+ container->children.next = RT_NULL;
+
+ /* update widget clip */
+#if 0
+ rtgui_widget_update_clip(RTGUI_WIDGET(container));
+#else
+ /* update toplevel widget clip */
+#if 0
+ {
+ rtgui_toplevel_t* top;
+
+ top = RTGUI_TOPLEVEL(RTGUI_WIDGET(container)->toplevel);
+ if (RTGUI_IS_VIEW(top))
+ }
+#endif
+ rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(RTGUI_WIDGET(container)->toplevel));
+#endif
+}
+
+rtgui_widget_t* rtgui_container_get_first_child(rtgui_container_t* container)
+{
+ rtgui_widget_t* child = RT_NULL;
+
+ if (container->children.next != RT_NULL)
+ {
+ child = rtgui_list_entry(container->children.next, rtgui_widget_t, sibling);
+ }
+
+ return child;
+}
diff --git a/rtgui/widgets/iconbox.c b/rtgui/widgets/iconbox.c
new file mode 100644
index 0000000000..ffb81fc493
--- /dev/null
+++ b/rtgui/widgets/iconbox.c
@@ -0,0 +1,154 @@
+/*
+ * File : iconbox.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/widgets/iconbox.h>
+#include <rtgui/rtgui_theme.h>
+
+static void _rtgui_iconbox_constructor(rtgui_iconbox_t *iconbox)
+{
+ /* init widget and set event handler */
+ RTGUI_WIDGET(iconbox)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT;
+ rtgui_widget_set_event_handler(RTGUI_WIDGET(iconbox), rtgui_iconbox_event_handler);
+
+ /* set proper of control */
+ iconbox->image = RT_NULL;
+ iconbox->selected = RT_FALSE;
+ iconbox->text = RT_NULL;
+ iconbox->text_position = RTGUI_ICONBOX_TEXT_BELOW;
+}
+
+rtgui_type_t *rtgui_iconbox_type_get(void)
+{
+ static rtgui_type_t *iconbox_type = RT_NULL;
+
+ if (!iconbox_type)
+ {
+ iconbox_type = rtgui_type_create("iconbox", RTGUI_WIDGET_TYPE,
+ sizeof(rtgui_iconbox_t), RTGUI_CONSTRUCTOR(_rtgui_iconbox_constructor), RT_NULL);
+ }
+
+ return iconbox_type;
+}
+
+rt_bool_t rtgui_iconbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+ struct rtgui_iconbox* iconbox = (struct rtgui_iconbox*)widget;
+
+ switch (event->type)
+ {
+ case RTGUI_EVENT_PAINT:
+ if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
+ else
+ {
+ rtgui_theme_draw_iconbox(iconbox);
+ }
+
+ break;
+ }
+
+ return RT_FALSE;
+}
+
+struct rtgui_iconbox* rtgui_iconbox_create(struct rtgui_image* image,
+ const unsigned char* text,
+ int position)
+{
+ struct rtgui_iconbox* iconbox;
+
+ iconbox = (struct rtgui_iconbox*)rtgui_widget_create(RTGUI_ICONBOX_TYPE);
+ if (iconbox != RT_NULL)
+ {
+ rtgui_rect_t rect = {0, 0, 0, 0}, text_rect;
+
+ rect.x2 = image->w;
+ rect.y2 = image->h;
+
+ /* get text rect */
+ rtgui_font_get_metrics(rtgui_font_default(), text, &text_rect);
+ if (position == RTGUI_ICONBOX_TEXT_BELOW)
+ {
+ rect.y2 += RTGUI_WIDGET_DEFAULT_MARGIN;
+ if (text_rect.x2 > rect.x2)
+ {
+ rect.x2 = text_rect.x2;
+ }
+ rect.y2 += text_rect.y2;
+ }
+ else if (position == RTGUI_ICONBOX_TEXT_RIGHT)
+ {
+ rect.x2 += RTGUI_WIDGET_DEFAULT_MARGIN;
+ if (text_rect.y2 > rect.y2)
+ {
+ rect.y2 = text_rect.y2;
+ }
+ rect.x2 += text_rect.x2;
+ }
+
+ /* set widget rect */
+ rtgui_widget_set_rect(RTGUI_WIDGET(iconbox), &rect);
+
+ /* set image and text position */
+ iconbox->image = image;
+ iconbox->text = (unsigned char*)rt_strdup((const char*)text);
+ iconbox->text_position = position;
+ }
+
+ return iconbox;
+}
+
+void rtgui_iconbox_destroy(struct rtgui_iconbox* iconbox)
+{
+ rtgui_widget_destroy(RTGUI_WIDGET(iconbox));
+}
+
+void rtgui_iconbox_set_text_position(struct rtgui_iconbox* iconbox, int position)
+{
+ rtgui_rect_t rect = {0, 0, 0, 0}, text_rect;
+
+ RT_ASSERT(iconbox != RT_NULL);
+
+ iconbox->text_position = position;
+
+ /* set mini width and height */
+ rect.x2 = iconbox->image->w;
+ rect.y2 = iconbox->image->h;
+
+ /* get text rect */
+ if (iconbox->text != RT_NULL)
+ {
+ rtgui_font_get_metrics(rtgui_font_default(),
+ iconbox->text, &text_rect);
+ if (position == RTGUI_ICONBOX_TEXT_BELOW)
+ {
+ rect.y2 += RTGUI_WIDGET_DEFAULT_MARGIN;
+ if (text_rect.x2 > rect.x2)
+ {
+ rect.x2 = text_rect.x2;
+ }
+ rect.y2 += text_rect.y2;
+ }
+ else if (position == RTGUI_ICONBOX_TEXT_RIGHT)
+ {
+ rect.x2 += RTGUI_WIDGET_DEFAULT_MARGIN;
+ if (text_rect.y2 > rect.y2)
+ {
+ rect.y2 = text_rect.y2;
+ }
+ rect.x2 += text_rect.x2;
+ }
+ }
+
+ rtgui_widget_set_miniwidth(RTGUI_WIDGET(iconbox), rect.x2);
+ rtgui_widget_set_miniheight(RTGUI_WIDGET(iconbox), rect.y2);
+}
diff --git a/rtgui/widgets/label.c b/rtgui/widgets/label.c
new file mode 100644
index 0000000000..e326bbf0d2
--- /dev/null
+++ b/rtgui/widgets/label.c
@@ -0,0 +1,113 @@
+/*
+ * File : label.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/widgets/label.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/rtgui_theme.h>
+
+static void _rtgui_label_constructor(rtgui_label_t *label)
+{
+ /* init widget and set event handler */
+ rtgui_widget_set_event_handler(RTGUI_WIDGET(label), rtgui_label_event_handler);
+
+ /* set field */
+ label->text = RT_NULL;
+}
+
+static void _rtgui_label_destructor(rtgui_label_t *label)
+{
+ /* release text memory */
+ rtgui_free(label->text);
+ label->text = RT_NULL;
+}
+
+rtgui_type_t *rtgui_label_type_get(void)
+{
+ static rtgui_type_t *label_type = RT_NULL;
+
+ if (!label_type)
+ {
+ label_type = rtgui_type_create("label", RTGUI_WIDGET_TYPE,
+ sizeof(rtgui_label_t),
+ RTGUI_CONSTRUCTOR(_rtgui_label_constructor),
+ RTGUI_DESTRUCTOR(_rtgui_label_destructor));
+ }
+
+ return label_type;
+}
+
+rt_bool_t rtgui_label_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+ struct rtgui_label* label;
+
+ RT_ASSERT(widget != RT_NULL);
+
+ label = (struct rtgui_label*) widget;
+ switch (event->type)
+ {
+ case RTGUI_EVENT_PAINT:
+ rtgui_theme_draw_label(label);
+ break;
+ }
+
+ return RT_FALSE;
+}
+
+rtgui_label_t* rtgui_label_create(const unsigned char* text)
+{
+ struct rtgui_label* label;
+
+ label = (struct rtgui_label*) rtgui_widget_create(RTGUI_LABEL_TYPE);
+ if (label != RT_NULL)
+ {
+ rtgui_rect_t rect;
+
+ /* set default rect */
+ rtgui_font_get_metrics(rtgui_font_default(), text, &rect);
+ rect.x2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1);
+ rect.y2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1);
+ rtgui_widget_set_rect(RTGUI_WIDGET(label), &rect);
+
+ /* set text */
+ label->text = (unsigned char*)rt_strdup((const char*)text);
+ }
+
+ return label;
+}
+
+void rtgui_label_destroy(rtgui_label_t* label)
+{
+ rtgui_widget_destroy(RTGUI_WIDGET(label));
+}
+
+unsigned char* rtgui_label_get_text(rtgui_label_t* label)
+{
+ RT_ASSERT(label != RT_NULL);
+
+ return label->text;
+}
+
+void rtgui_label_set_text(rtgui_label_t* label, const unsigned char* text)
+{
+ RT_ASSERT(label != RT_NULL);
+
+ if (label->text != RT_NULL)
+ {
+ /* release old text memory */
+ rtgui_free(label->text);
+ }
+
+ if (text != RT_NULL) label->text = (unsigned char*)rt_strdup((const char*)text);
+ else label->text = RT_NULL;
+}
diff --git a/rtgui/widgets/textbox.c b/rtgui/widgets/textbox.c
new file mode 100644
index 0000000000..a469bd65ee
--- /dev/null
+++ b/rtgui/widgets/textbox.c
@@ -0,0 +1,346 @@
+/*
+ * File : textbox.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/widgets/textbox.h>
+#include <rtgui/rtgui_theme.h>
+
+#define RTGUI_TEXTBOX_LINE_MAX 64
+#define RTGUI_TEXTBOX_MARGIN 3
+
+static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kbd* event);
+static rt_bool_t rtgui_textbox_onfocus(struct rtgui_widget* widget, struct rtgui_event* event);
+static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_widget* widget, struct rtgui_event* event);
+
+static void _rtgui_textbox_constructor(rtgui_textbox_t *box)
+{
+ rtgui_rect_t rect = {0, 0, RTGUI_TEXTBOX_DEFAULT_WIDTH, RTGUI_TEXTBOX_DEFAULT_HEIGHT};
+ rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect);
+
+ RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
+ rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_textbox_event_handler);
+ rtgui_widget_set_onfocus(RTGUI_WIDGET(box), rtgui_textbox_onfocus);
+ rtgui_widget_set_onunfocus(RTGUI_WIDGET(box), rtgui_textbox_onunfocus);
+
+ /* set default text align */
+ RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_CENTER_VERTICAL;
+
+ /* set proper of control */
+ box->caret_x = box->caret_y = 0;
+ box->caret = rtgui_caret_create(RTGUI_WIDGET(box));
+
+ box->line = box->line_begin = box->position = 0;
+ box->type = RTGUI_TEXTBOX_SINGLE;
+
+ /* allocate default line buffer */
+ box->text = RT_NULL;
+
+ rtgui_font_get_metrics(RTGUI_WIDGET(box)->gc.font, "h", &rect);
+ box->font_width = rtgui_rect_width(rect);
+}
+
+static void _rtgui_textbox_deconstructor(rtgui_textbox_t *box)
+{
+ if (box->text != RT_NULL)
+ {
+ rtgui_free(box->text);
+ box->text = RT_NULL;
+ }
+
+ if (box->caret != RT_NULL)
+ {
+ rtgui_caret_destroy(box->caret);
+ box->caret = RT_NULL;
+ }
+}
+
+rtgui_type_t *rtgui_textbox_type_get(void)
+{
+ static rtgui_type_t *textbox_type = RT_NULL;
+
+ if (!textbox_type)
+ {
+ textbox_type = rtgui_type_create("textbox", RTGUI_WIDGET_TYPE,
+ sizeof(rtgui_textbox_t),
+ RTGUI_CONSTRUCTOR(_rtgui_textbox_constructor),
+ RTGUI_DESTRUCTOR(_rtgui_textbox_deconstructor));
+ }
+
+ return textbox_type;
+}
+
+static void rtgui_textbox_onmouse(struct rtgui_textbox* box, struct rtgui_event_mouse* event)
+{
+ rt_size_t length;
+
+ RT_ASSERT(box != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
+
+ length = rt_strlen((const char*)box->text);
+
+ if (event->button & RTGUI_MOUSE_BUTTON_LEFT &&
+ event->button & RTGUI_MOUSE_BUTTON_DOWN)
+ {
+ rt_int32_t x;
+
+ /* set caret position */
+ x = event->x - RTGUI_WIDGET(box)->extent.x1;
+ if (x < 0)
+ {
+ box->position = 0;
+ }
+ else if (x > length * box->font_width)
+ {
+ box->position = length;
+ }
+ else
+ {
+ box->position = x / box->font_width;
+ }
+
+ rtgui_caret_set_point(box->caret, RTGUI_TEXTBOX_MARGIN + box->position * box->font_width, 2);
+ rtgui_caret_set_box(box->caret, 2, rtgui_rect_height(RTGUI_WIDGET(box)->extent) - 4);
+
+ /* set widget focus */
+ rtgui_widget_focus(RTGUI_WIDGET(box));
+ }
+}
+
+static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kbd* event)
+{
+ rt_size_t length;
+
+ RT_ASSERT(box != RT_NULL);
+ RT_ASSERT(event != RT_NULL);
+
+ if (event->type != RTGUI_KEYDOWN)
+ return ;
+
+ length = rt_strlen((const char*)box->text);
+ if (event->key == RTGUIK_DELETE)
+ {
+ if (box->position == length - 1)
+ {
+ box->text[box->position] = '\0';
+ }
+ else
+ {
+ unsigned char *c;
+
+ /* remove character */
+ for (c = &box->text[box->position]; c[1] != '\0'; c++)
+ *c = c[1];
+ *c = '\0';
+ }
+ }
+ else if (event->key == RTGUIK_BACKSPACE)
+ {
+ if (box->position == length - 1)
+ {
+ box->text[box->position] = '\0';
+ box->position --;
+ }
+ else if (box->position != 0)
+ {
+ /* remove current character */
+ if (box->position != 0)
+ {
+ unsigned char *c;
+
+ /* remove character */
+ for (c = &box->text[box->position - 1]; c[1] != '\0'; c++)
+ *c = c[1];
+ *c = '\0';
+ }
+ box->position --;
+ }
+ }
+ else if (event->key == RTGUIK_LEFT)
+ {
+ if (box->position > 0) box->position --;
+ }
+ else if (event->key == RTGUIK_RIGHT)
+ {
+ if (box->position < length) box->position ++;
+ }
+ else if (event->key == RTGUIK_HOME)
+ {
+ box->position = 0;
+ }
+ else if (event->key == RTGUIK_END)
+ {
+ box->position = length;
+ }
+ else if (event->key == RTGUIK_RETURN)
+ {
+ if (box->on_enter != RT_NULL)
+ {
+ box->on_enter(RTGUI_WIDGET(box), RT_NULL);
+ }
+ }
+ else
+ {
+ if (isprint(event->key) || isdigit(event->key))
+ {
+ /* no buffer on this line */
+ if (length + 1 > box->line_length) return;
+
+ if (box->position < length - 1)
+ {
+ unsigned char* c;
+
+ for (c = &box->text[length]; c != &box->text[box->position]; c--)
+ *c = *(c-1);
+ box->text[length + 1] = '\0';
+ }
+
+ box->text[box->position] = event->key;
+ box->position ++;
+ }
+ }
+
+ /* re-draw text box */
+ rtgui_theme_draw_textbox(box);
+ rtgui_caret_set_point(box->caret,
+ RTGUI_TEXTBOX_MARGIN + box->position * box->font_width , 2);
+ rtgui_caret_set_box(box->caret, 2, rtgui_rect_height(RTGUI_WIDGET(box)->extent) - 4);
+}
+
+static rt_bool_t rtgui_textbox_onfocus(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+ struct rtgui_textbox* box = (struct rtgui_textbox*)widget;
+
+ /* show caret */
+ rtgui_caret_show(box->caret, box->caret_x, box->caret_y);
+
+ return RT_TRUE;
+}
+
+static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+ struct rtgui_textbox* box = (struct rtgui_textbox*)widget;
+
+ /* hide caret */
+ rtgui_caret_hide(box->caret);
+
+ return RT_TRUE;
+}
+
+rt_bool_t rtgui_textbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+ struct rtgui_textbox* box = (struct rtgui_textbox*)widget;
+
+ switch (event->type)
+ {
+ case RTGUI_EVENT_PAINT:
+ if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
+ else rtgui_theme_draw_textbox(box);
+ break;
+
+ case RTGUI_EVENT_MOUSE_BUTTON:
+ if (widget->on_mouseclick != RT_NULL) widget->on_mouseclick(widget, event);
+ else rtgui_textbox_onmouse(box, (struct rtgui_event_mouse*)event);
+ return RT_TRUE;
+
+ case RTGUI_EVENT_KBD:
+ if (widget->on_key != RT_NULL) widget->on_key(widget, event);
+ else rtgui_textbox_onkey(box, (struct rtgui_event_kbd*)event);
+ return RT_TRUE;
+ }
+
+ return RT_FALSE;
+}
+
+struct rtgui_textbox* rtgui_textbox_create(const char* text)
+{
+ struct rtgui_textbox* box;
+
+ box = (struct rtgui_textbox*) rtgui_widget_create (RTGUI_TEXTBOX_TYPE);
+ if (box != RT_NULL)
+ {
+ rtgui_rect_t rect = {0, 0, RTGUI_TEXTBOX_DEFAULT_WIDTH, RTGUI_TEXTBOX_DEFAULT_HEIGHT};
+
+ /* allocate default line buffer */
+ rtgui_textbox_set_value(box, text);
+
+ rtgui_font_get_metrics(RTGUI_WIDGET(box)->gc.font, "h", &rect);
+ box->font_width = rtgui_rect_width(rect);
+ }
+
+ return box;
+}
+
+void rtgui_textbox_destroy(struct rtgui_textbox* box)
+{
+ rtgui_widget_destroy(RTGUI_WIDGET(box));
+}
+
+void rtgui_textbox_set_value(struct rtgui_textbox* box, const char* text)
+{
+ if (box->text != RT_NULL)
+ {
+ if (box->line_length > rt_strlen(text) + 1)
+ {
+ rt_memcpy(box->text, text, rt_strlen(text) + 1);
+ return;
+ }
+ else
+ {
+ /* free the old text */
+ rtgui_free(box->text);
+ box->text = RT_NULL;
+ }
+ }
+
+ box->line_length = RTGUI_TEXTBOX_LINE_MAX > rt_strlen(text) + 1 ?
+ RTGUI_TEXTBOX_LINE_MAX : rt_strlen(text) + 1;
+
+ /* allocate line buffer */
+ box->text = rtgui_malloc(box->line_length);
+ rt_memset(box->text, 0, box->line_length);
+
+ /* copy text */
+ rt_memcpy(box->text, text, rt_strlen(text) + 1);
+
+ /* set current position */
+ box->position = 0;
+}
+
+const char* rtgui_textbox_get_value(struct rtgui_textbox* box)
+{
+ return (const char*)box->text;
+}
+
+void rtgui_widget_set_line_length(struct rtgui_textbox* box, rt_size_t length)
+{
+ rt_uint8_t* new_line;
+
+ RT_ASSERT(box != RT_NULL);
+
+ /* invalid length */
+ if (length <= 0) return;
+
+ new_line = rtgui_malloc(length);
+ if (length < box->line_length)
+ {
+ rt_memcpy(new_line, box->text, length - 1);
+ new_line[length] = '\0';
+ }
+ else
+ {
+ rt_memcpy(new_line, (const char*)box->text, rt_strlen((const char*)box->text));
+ }
+
+ /* set line length */
+ box->line_length = length;
+}
diff --git a/rtgui/widgets/title.c b/rtgui/widgets/title.c
new file mode 100644
index 0000000000..1e96cd34ed
--- /dev/null
+++ b/rtgui/widgets/title.c
@@ -0,0 +1,73 @@
+/*
+ * File : title.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/widgets/title.h>
+#include <rtgui/rtgui_system.h>
+
+/* there is no event handler in wintitle but handle the event on topwin of server */
+static void _rtgui_wintitle_constructor(rtgui_wintitle_t* wintitle)
+{
+ wintitle->title = RT_NULL;
+ RTGUI_WIDGET(wintitle)->flag = RTGUI_WIDGET_FLAG_DEFAULT;
+}
+
+rtgui_type_t* rtgui_wintitle_type_get()
+{
+ static rtgui_type_t *wintitle_type = RT_NULL;
+
+ if (!wintitle_type)
+ {
+ wintitle_type = rtgui_type_create("wintitle", RTGUI_TOPLEVEL_TYPE,
+ sizeof(rtgui_wintitle_t), RTGUI_CONSTRUCTOR(_rtgui_wintitle_constructor), RT_NULL);
+ }
+
+ return wintitle_type;
+}
+
+rtgui_wintitle_t* rtgui_wintitle_create(const rt_uint8_t* title)
+{
+ rtgui_wintitle_t* wintitle;
+
+ wintitle = (rtgui_wintitle_t*)rtgui_widget_create(RTGUI_WINTITLE_TYPE);
+ if (wintitle != RT_NULL)
+ {
+ rtgui_wintitle_set_title(wintitle, title);
+ }
+
+ return wintitle;
+}
+
+void rtgui_wintitle_destroy(rtgui_wintitle_t* wintitle)
+{
+ rtgui_widget_destroy(RTGUI_WIDGET(wintitle));
+}
+
+void rtgui_wintitle_set_title(rtgui_wintitle_t* wintitle, const rt_uint8_t* title)
+{
+ RT_ASSERT(wintitle != RT_NULL);
+
+ if (wintitle->title != RT_NULL)
+ {
+ rtgui_free(wintitle->title);
+ }
+
+ if (title != RT_NULL) wintitle->title = (unsigned char*)rt_strdup((const char*)title);
+ else wintitle->title = RT_NULL;
+}
+
+rt_uint8_t *rtgui_wintitle_get_title(rtgui_wintitle_t* wintitle)
+{
+ RT_ASSERT(wintitle != RT_NULL);
+
+ return wintitle->title;
+}
diff --git a/rtgui/widgets/toplevel.c b/rtgui/widgets/toplevel.c
new file mode 100644
index 0000000000..6823b66799
--- /dev/null
+++ b/rtgui/widgets/toplevel.c
@@ -0,0 +1,191 @@
+/*
+ * File : toplevel.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/rtgui_system.h>
+#include <rtgui/widgets/toplevel.h>
+
+static void _rtgui_toplevel_constructor(rtgui_toplevel_t *toplevel)
+{
+ /* set event handler */
+ rtgui_widget_set_event_handler(RTGUI_WIDGET(toplevel), rtgui_toplevel_event_handler);
+
+ /* set toplevel to self */
+ RTGUI_WIDGET(toplevel)->toplevel = RTGUI_WIDGET(toplevel);
+
+ /* init toplevel property */
+ toplevel->drawing = 0;
+ toplevel->external_clip_rect = RT_NULL;
+ toplevel->external_clip_size = 0;
+ toplevel->focus = RT_NULL;
+
+ /* hide toplevel default */
+ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(toplevel));
+
+ /* set server as RT_NULL (no connected) */
+ toplevel->server = RT_NULL;
+}
+
+static void _rtgui_toplevel_destructor(rtgui_toplevel_t* toplevel)
+{
+ /* release external clip info */
+ rtgui_free(toplevel->external_clip_rect);
+
+ toplevel->drawing = 0;
+ toplevel->external_clip_rect = RT_NULL;
+ toplevel->external_clip_size = 0;
+ toplevel->focus = RT_NULL;
+}
+
+rtgui_type_t *rtgui_toplevel_type_get(void)
+{
+ static rtgui_type_t *toplevel_type = RT_NULL;
+
+ if (!toplevel_type)
+ {
+ toplevel_type = rtgui_type_create("toplevel", RTGUI_CONTAINER_TYPE,
+ sizeof(rtgui_toplevel_t),
+ RTGUI_CONSTRUCTOR(_rtgui_toplevel_constructor),
+ RTGUI_DESTRUCTOR(_rtgui_toplevel_destructor));
+ }
+
+ return toplevel_type;
+}
+
+rt_bool_t rtgui_toplevel_event_handler(rtgui_widget_t* widget, rtgui_event_t* event)
+{
+ rtgui_toplevel_t* toplevel = (rtgui_toplevel_t*)widget;
+
+ switch (event->type)
+ {
+ case RTGUI_EVENT_KBD:
+ if (toplevel->focus != RT_NULL)
+ {
+ toplevel->focus->event_handler(toplevel->focus, event);
+ }
+ break;
+
+ case RTGUI_EVENT_CLIP_INFO:
+ /* set toplevel external clip info */
+ rtgui_toplevel_handle_clip(toplevel, (struct rtgui_event_clip_info*)event);
+
+ /* update toplevel clip */
+ rtgui_toplevel_update_clip(toplevel);
+ break;
+
+ case RTGUI_EVENT_TIMER:
+ {
+ struct rtgui_event_timer* etimer = (struct rtgui_event_timer*) event;
+
+ if (etimer->callback != RT_NULL)
+ {
+ /* call timeout function */
+ etimer->callback(RT_NULL, etimer->parameter);
+ }
+ }
+ break;
+
+ case RTGUI_EVENT_COMMAND:
+ if (rtgui_container_dispatch_event(RTGUI_CONTAINER(widget), event) != RT_TRUE)
+ {
+ if (widget->on_command != RT_NULL)
+ {
+ widget->on_command(widget, event);
+ }
+ }
+ break;
+
+ default :
+ return rtgui_container_event_handler(widget, event);
+ }
+
+ return RT_FALSE;
+}
+
+void rtgui_toplevel_handle_clip(struct rtgui_toplevel* top,
+ struct rtgui_event_clip_info* info)
+{
+ RT_ASSERT(top != RT_NULL);
+ RT_ASSERT(info != RT_NULL);
+
+ /* release old rect array */
+ if (top->external_clip_size != 0)
+ {
+ rtgui_free(top->external_clip_rect);
+ top->external_clip_rect = RT_NULL;
+ top->external_clip_size = 0;
+ }
+
+ /* no rect info */
+ if (info->num_rect == 0) return;
+
+ top->external_clip_rect = (rtgui_rect_t*) rtgui_malloc(sizeof(rtgui_rect_t) *
+ info->num_rect);
+ top->external_clip_size = info->num_rect;
+
+ /* copy rect array */
+ rt_memcpy(top->external_clip_rect, info->rects, sizeof(rtgui_rect_t) * info->num_rect);
+}
+
+#include <rtgui/driver.h> /* to get screen rect */
+
+void rtgui_toplevel_update_clip(rtgui_toplevel_t* top)
+{
+ rt_uint32_t idx;
+ rtgui_container_t* container;
+ struct rtgui_list_node* node;
+ rtgui_rect_t screen_rect;
+
+ if (top == RT_NULL) return;
+
+ /* reset toplevel widget clip to extent */
+ rtgui_region_reset(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->extent));
+ RTGUI_WIDGET(top)->clip_sync ++;
+
+ /* subtract the screen rect */
+ screen_rect.x1 = screen_rect.y1 = 0;
+ screen_rect.x2 = rtgui_graphic_driver_get_default()->width;
+ screen_rect.y2 = rtgui_graphic_driver_get_default()->height;
+ rtgui_region_intersect_rect(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->clip),
+ &screen_rect);
+
+ /* subtract the external rect */
+ for (idx = 0; idx < top->external_clip_size; idx ++)
+ {
+ rtgui_region_subtract_rect(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->clip),
+ &(top->external_clip_rect[idx]));
+ }
+
+ /* update the clip info of each child */
+ container = RTGUI_CONTAINER(top);
+ rtgui_list_foreach(node, &(container->children))
+ {
+ rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling);
+
+ rtgui_widget_update_clip(child);
+ }
+}
+
+void rtgui_toplevel_set_focus(struct rtgui_toplevel* top, rtgui_widget_t* focus)
+{
+ RT_ASSERT(top != RT_NULL);
+
+ top->focus = focus;
+}
+
+rtgui_widget_t* rtgui_toplevel_get_focus(struct rtgui_toplevel* top)
+{
+ RT_ASSERT(top != RT_NULL);
+
+ return top->focus;
+}
+
diff --git a/rtgui/widgets/view.c b/rtgui/widgets/view.c
new file mode 100644
index 0000000000..d016515af9
--- /dev/null
+++ b/rtgui/widgets/view.c
@@ -0,0 +1,149 @@
+/*
+ * File : view.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2009, 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
+ * 2009-10-16 Bernard first version
+ */
+#include <rtgui/dc.h>
+#include <rtgui/rtgui_system.h>
+#include <rtgui/widgets/view.h>
+#include <rtgui/widgets/workbench.h>
+
+static void _rtgui_view_constructor(rtgui_view_t *view)
+{
+ /* init view */
+ rtgui_widget_set_event_handler(RTGUI_WIDGET(view),
+ rtgui_view_event_handler);
+
+ view->title = RT_NULL;
+}
+
+rtgui_type_t *rtgui_view_type_get(void)
+{
+ static rtgui_type_t *view_type = RT_NULL;
+
+ if (!view_type)
+ {
+ view_type = rtgui_type_create("view", RTGUI_CONTAINER_TYPE,
+ sizeof(rtgui_view_t), RTGUI_CONSTRUCTOR(_rtgui_view_constructor), RT_NULL);
+ }
+
+ return view_type;
+}
+
+rt_bool_t rtgui_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
+{
+ struct rtgui_view* view = (struct rtgui_view*) widget;
+ RT_ASSERT(widget != RT_NULL);
+
+ switch (event->type)
+ {
+ case RTGUI_EVENT_PAINT:
+ if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
+ else
+ {
+ struct rtgui_dc* dc;
+ struct rtgui_rect rect;
+
+ dc = rtgui_dc_begin_drawing(widget);
+ if (dc == RT_NULL) return RT_FALSE;
+ rtgui_widget_get_rect(widget, &rect);
+
+ /* fill view with background */
+ rtgui_dc_fill_rect(dc, &rect);
+
+ /* paint on each child */
+ rtgui_container_dispatch_event(RTGUI_CONTAINER(view), event);
+
+ rtgui_dc_end_drawing(dc);
+ }
+ break;
+
+ default:
+ return rtgui_container_event_handler(widget, event);
+ }
+
+ return RT_FALSE;
+}
+
+rtgui_view_t* rtgui_view_create(const char* title)
+{
+ struct rtgui_view* view;
+
+ /* allocate view */
+ view = (struct rtgui_view*) rtgui_widget_create (RTGUI_VIEW_TYPE);
+ if (view != RT_NULL)
+ {
+ if (title != RT_NULL)
+ view->title = rt_strdup(title);
+ }
+
+ return view;
+}
+
+void rtgui_view_destroy(rtgui_view_t* view)
+{
+ rtgui_widget_destroy(RTGUI_WIDGET(view));
+}
+
+void rtgui_view_set_box(rtgui_view_t* view, rtgui_box_t* box)
+{
+ if (view == RT_NULL ||
+ box == RT_NULL) return;
+
+ rtgui_container_add_child(RTGUI_CONTAINER(view), RTGUI_WIDGET(box));
+ rtgui_widget_set_rect(RTGUI_WIDGET(box), &(RTGUI_WIDGET(view)->extent));
+}
+
+void rtgui_view_show(rtgui_view_t* view)
+{
+ if (view == RT_NULL) return;
+
+ if (RTGUI_WIDGET(view)->parent == RT_NULL)
+ {
+ RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(view));
+ return;
+ }
+
+ rtgui_workbench_show_view((rtgui_workbench_t*)(RTGUI_WIDGET(view)->parent), view);
+}
+
+void rtgui_view_hide(rtgui_view_t* view)
+{
+ if (view == RT_NULL) return;
+
+ if (RTGUI_WIDGET(view)->parent == RT_NULL)
+ {
+ RTGUI_WIDGET_HIDE(RTGUI_WIDGET(view));
+ return;
+ }
+
+ rtgui_workbench_hide_view((rtgui_workbench_t*)(RTGUI_WIDGET(view)->parent), view);
+}
+
+char* rtgui_view_get_title(rtgui_view_t* view)
+{
+ RT_ASSERT(view != RT_NULL);
+
+ return view->title;
+}
+
+void rtgui_view_set_title(rtgui_view_t* view, const char *title)
+{
+ RT_ASSERT(view != RT_NULL);
+
+ if (view->title != RT_NULL)
+ {
+ rtgui_free(view->title);
+
+ if (title != RT_NULL) view->title = rt_strdup(title);
+ else view->title = RT_NULL;
+ }
+}