Browse Source

add RTGUI source code

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@104 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong 15 years ago
parent
commit
a0e99e8ad1
54 changed files with 11425 additions and 30 deletions
  1. 227 0
      rtgui/common/asc12font.c
  2. 293 0
      rtgui/common/asc16font.c
  3. 214 0
      rtgui/common/caret.c
  4. 33 0
      rtgui/common/color.c
  5. 1223 0
      rtgui/common/dc.c
  6. 392 0
      rtgui/common/dc_buffer.c
  7. 436 0
      rtgui/common/dc_hw.c
  8. 329 0
      rtgui/common/filerw.c
  9. 205 0
      rtgui/common/font.c
  10. 192 0
      rtgui/common/image.c
  11. 617 0
      rtgui/common/image_xpm.c
  12. 2228 0
      rtgui/common/region.c
  13. 0 12
      rtgui/common/rtgui_system.c
  14. 8 4
      rtgui/common/rtgui_theme.c
  15. 53 0
      rtgui/include/rtgui/caret.h
  16. 97 0
      rtgui/include/rtgui/color.h
  17. 126 0
      rtgui/include/rtgui/dc.h
  18. 47 0
      rtgui/include/rtgui/filerw.h
  19. 88 0
      rtgui/include/rtgui/font.h
  20. 63 0
      rtgui/include/rtgui/image.h
  21. 19 0
      rtgui/include/rtgui/image_png.h
  22. 21 0
      rtgui/include/rtgui/image_xpm.h
  23. 293 0
      rtgui/include/rtgui/kbddef.h
  24. 66 0
      rtgui/include/rtgui/list.h
  25. 100 0
      rtgui/include/rtgui/region.h
  26. 1 4
      rtgui/include/rtgui/rtgui.h
  27. 36 0
      rtgui/include/rtgui/rtgui_config.h
  28. 5 0
      rtgui/include/rtgui/rtgui_server.h
  29. 1 0
      rtgui/include/rtgui/rtgui_theme.h
  30. 58 0
      rtgui/include/rtgui/widgets/box.h
  31. 81 0
      rtgui/include/rtgui/widgets/button.h
  32. 47 0
      rtgui/include/rtgui/widgets/container.h
  33. 56 0
      rtgui/include/rtgui/widgets/iconbox.h
  34. 49 0
      rtgui/include/rtgui/widgets/label.h
  35. 66 0
      rtgui/include/rtgui/widgets/listbox.h
  36. 73 0
      rtgui/include/rtgui/widgets/textbox.h
  37. 45 0
      rtgui/include/rtgui/widgets/title.h
  38. 57 0
      rtgui/include/rtgui/widgets/toplevel.h
  39. 61 0
      rtgui/include/rtgui/widgets/view.h
  40. 629 0
      rtgui/server/mouse.c
  41. 51 0
      rtgui/server/mouse.h
  42. 0 4
      rtgui/server/panel.h
  43. 0 6
      rtgui/server/server.c
  44. 868 0
      rtgui/server/topwin.c
  45. 56 0
      rtgui/server/topwin.h
  46. 340 0
      rtgui/widgets/box.c
  47. 170 0
      rtgui/widgets/button.c
  48. 279 0
      rtgui/widgets/container.c
  49. 154 0
      rtgui/widgets/iconbox.c
  50. 113 0
      rtgui/widgets/label.c
  51. 346 0
      rtgui/widgets/textbox.c
  52. 73 0
      rtgui/widgets/title.c
  53. 191 0
      rtgui/widgets/toplevel.c
  54. 149 0
      rtgui/widgets/view.c

+ 227 - 0
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 */
+};

+ 293 - 0
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 */

+ 214 - 0
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);
+	}
+}
+

+ 33 - 0
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)
+

+ 1223 - 0
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);
+	}
+}

+ 392 - 0
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;
+}

+ 436 - 0
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);
+}

+ 329 - 0
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;
+}

+ 205 - 0
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;
+}

+ 192 - 0
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);
+	}
+}
+

+ 617 - 0
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);
+}
+

+ 2228 - 0
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;
+}

+ 0 - 12
rtgui/common/rtgui_system.c

@@ -40,18 +40,6 @@ void rtgui_system_server_init()
 	rtgui_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                                                 */
 /* RTGUI Thread Wrapper                                                 */
 /************************************************************************/
 /************************************************************************/

+ 8 - 4
rtgui/common/rtgui_theme.c

@@ -19,13 +19,14 @@
 #include <rtgui/widgets/label.h>
 #include <rtgui/widgets/label.h>
 #include <rtgui/widgets/textbox.h>
 #include <rtgui/widgets/textbox.h>
 #include <rtgui/widgets/iconbox.h>
 #include <rtgui/widgets/iconbox.h>
+#include <rtgui/widgets/title.h>
 #include <rtgui/rtgui_theme.h>
 #include <rtgui/rtgui_theme.h>
 #include <rtgui/rtgui_server.h>
 #include <rtgui/rtgui_server.h>
 
 
 #define WINTITLE_CB_WIDTH		14
 #define WINTITLE_CB_WIDTH		14
 #define WINTITLE_CB_HEIGHT		14
 #define WINTITLE_CB_HEIGHT		14
 
 
-static const char * close_unpressed_xpm[] = {
+static const rt_uint8_t *close_unpressed_xpm[] = {
 	"14 14 55 1",
 	"14 14 55 1",
 	" 	c None",
 	" 	c None",
 	".	c #DCDFEA",
 	".	c #DCDFEA",
@@ -97,7 +98,7 @@ static const char * close_unpressed_xpm[] = {
 	"#mnnnnnnnnnnm#",
 	"#mnnnnnnnnnnm#",
 	"op@@@@@@@@@@po"};
 	"op@@@@@@@@@@po"};
 
 
-static const char * close_pressed_xpm[] = {
+static const rt_uint8_t *close_pressed_xpm[] = {
 	"14 14 66 1",
 	"14 14 66 1",
 	" 	c None",
 	" 	c None",
 	".	c #CED4EE",
 	".	c #CED4EE",
@@ -191,9 +192,11 @@ void rtgui_theme_draw_win(struct rtgui_topwin* win)
 
 
 	/* init close box image */
 	/* init close box image */
 	if (close_pressed == RT_NULL)
 	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)
 	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 */
 	/* begin drawing */
 	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(win->title));
 	dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(win->title));
@@ -437,3 +440,4 @@ void rtgui_theme_draw_iconbox(rtgui_iconbox_t* iconbox)
 	/* end drawing */
 	/* end drawing */
 	rtgui_dc_end_drawing(dc);
 	rtgui_dc_end_drawing(dc);
 }
 }
+

+ 53 - 0
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

+ 97 - 0
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
+

+ 126 - 0
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

+ 47 - 0
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

+ 88 - 0
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

+ 63 - 0
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

+ 19 - 0
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

+ 21 - 0
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

+ 293 - 0
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

+ 66 - 0
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

+ 100 - 0
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_ */

+ 1 - 4
rtgui/include/rtgui/rtgui.h

@@ -16,10 +16,7 @@
 
 
 #include <rtthread.h>
 #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_MAX		32767
 #define RT_INT16_MIN		(-RT_INT16_MAX-1)
 #define RT_INT16_MIN		(-RT_INT16_MAX-1)

+ 36 - 0
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
+

+ 5 - 0
rtgui/include/rtgui/rtgui_server.h

@@ -67,4 +67,9 @@ void rtgui_server_init(void);
 /* post an event to server */
 /* post an event to server */
 void rtgui_server_post_event(struct rtgui_event* event, rt_size_t size);
 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
 #endif
+

+ 1 - 0
rtgui/include/rtgui/rtgui_theme.h

@@ -15,6 +15,7 @@
 #define __RTGUI_THEME_H__
 #define __RTGUI_THEME_H__
 
 
 #include <rtgui/rtgui.h>
 #include <rtgui/rtgui.h>
+#include <rtgui/rtgui_server.h>
 
 
 #include <rtgui/widgets/label.h>
 #include <rtgui/widgets/label.h>
 #include <rtgui/widgets/button.h>
 #include <rtgui/widgets/button.h>

+ 58 - 0
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

+ 81 - 0
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

+ 47 - 0
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

+ 56 - 0
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

+ 49 - 0
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

+ 66 - 0
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

+ 73 - 0
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

+ 45 - 0
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

+ 57 - 0
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

+ 61 - 0
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

+ 629 - 0
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;
+}

+ 51 - 0
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

+ 0 - 4
rtgui/server/panel.h

@@ -49,10 +49,6 @@ struct rtgui_panel
 	rt_thread_t wm_thread;
 	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 */
 /* find panel by name */
 struct rtgui_panel* rtgui_panel_find(char* name);
 struct rtgui_panel* rtgui_panel_find(char* name);
 
 

+ 0 - 6
rtgui/server/server.c

@@ -21,12 +21,6 @@
 #include "panel.h"
 #include "panel.h"
 #include "topwin.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 char rtgui_server_stack[2048];
 static struct rt_thread rtgui_server_thread;
 static struct rt_thread rtgui_server_thread;
 
 

+ 868 - 0
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);
+		}
+	}
+}

+ 56 - 0
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

+ 340 - 0
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;
+}

+ 170 - 0
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;
+}
+

+ 279 - 0
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;
+}

+ 154 - 0
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);
+}

+ 113 - 0
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;
+}

+ 346 - 0
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;
+}

+ 73 - 0
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;
+}

+ 191 - 0
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;
+}
+

+ 149 - 0
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;
+	}
+}