diff --git a/rtgui/common/asc12font.c b/rtgui/common/asc12font.c new file mode 100644 index 0000000000000000000000000000000000000000..2ea0ca049d5775edf9f396f7268e9070a203f7f0 --- /dev/null +++ b/rtgui/common/asc12font.c @@ -0,0 +1,227 @@ +/* + * File : asc12font.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include + +const rt_uint8_t asc12_font[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, +0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, +0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, +0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, +0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, +0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3c, +0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, +0xc3, 0xff, 0xff, 0xff, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, +0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, +0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, +0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, +0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x06, 0x0e, 0x1e, 0x3e, +0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, +0x18, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, +0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0xc6, 0x60, 0x38, 0x6c, +0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, +0xfe, 0xfe, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, +0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, +0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, +0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, +0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x50, 0x50, 0x00, 0x00, +0x00, 0x10, 0x38, 0x40, 0x40, 0x38, 0x48, 0x70, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20, 0x50, 0x20, +0x0c, 0x70, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x20, 0x54, 0x48, +0x34, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x20, 0x20, 0x10, +0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x10, 0x7c, 0x10, 0x28, 0x28, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0xfc, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x00, 0x00, +0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x10, +0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x20, 0x44, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x18, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00, +0x00, 0x0c, 0x14, 0x14, 0x24, 0x44, 0x7c, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x20, 0x20, +0x38, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x78, 0x44, 0x44, 0x44, +0x38, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x44, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, +0x00, 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, +0x44, 0x3c, 0x04, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, +0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x30, 0x20, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x10, 0x60, 0x80, 0x60, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x7c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x18, 0x04, 0x18, 0x20, +0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x04, 0x08, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00, +0x38, 0x44, 0x44, 0x4c, 0x54, 0x54, 0x4c, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, 0x30, 0x10, 0x28, +0x28, 0x28, 0x7c, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x44, 0x44, 0x78, 0x44, 0x44, 0x44, +0xf8, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x40, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, +0x00, 0xf0, 0x48, 0x44, 0x44, 0x44, 0x44, 0x48, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x44, 0x50, +0x70, 0x50, 0x40, 0x44, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x20, 0x28, 0x38, 0x28, 0x20, 0x20, +0x70, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x40, 0x40, 0x4c, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, +0x00, 0xec, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10, +0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x08, 0x08, 0x48, 0x48, 0x48, +0x30, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x48, 0x50, 0x70, 0x48, 0x44, 0xe4, 0x00, 0x00, 0x00, +0x00, 0x70, 0x20, 0x20, 0x20, 0x20, 0x24, 0x24, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0x6c, +0x54, 0x54, 0x44, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0xec, 0x64, 0x64, 0x54, 0x54, 0x54, 0x4c, +0xec, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, +0x00, 0x78, 0x24, 0x24, 0x24, 0x38, 0x20, 0x20, 0x70, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, +0x44, 0x44, 0x44, 0x44, 0x38, 0x1c, 0x00, 0x00, 0x00, 0xf8, 0x44, 0x44, 0x44, 0x78, 0x48, 0x44, +0xe0, 0x00, 0x00, 0x00, 0x00, 0x34, 0x4c, 0x40, 0x38, 0x04, 0x04, 0x64, 0x58, 0x00, 0x00, 0x00, +0x00, 0xfc, 0x90, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44, +0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44, 0x28, 0x28, 0x28, 0x10, +0x10, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44, 0x54, 0x54, 0x54, 0x54, 0x28, 0x00, 0x00, 0x00, +0x00, 0xc4, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x28, +0x28, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x44, 0x08, 0x10, 0x10, 0x20, 0x44, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00, +0x00, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x38, 0x08, 0x08, +0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x10, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, +0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, +0x44, 0x3c, 0x44, 0x44, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, +0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, +0x00, 0x0c, 0x04, 0x34, 0x4c, 0x44, 0x44, 0x44, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, +0x44, 0x7c, 0x40, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x7c, 0x20, 0x20, 0x20, 0x20, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x4c, 0x44, 0x44, 0x44, 0x3c, 0x04, 0x38, 0x00, +0x00, 0xc0, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70, +0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08, +0x08, 0x08, 0x70, 0x00, 0x00, 0xc0, 0x40, 0x5c, 0x48, 0x70, 0x50, 0x48, 0xdc, 0x00, 0x00, 0x00, +0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, +0x54, 0x54, 0x54, 0x54, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x64, 0x44, 0x44, 0x44, +0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xd8, 0x64, 0x44, 0x44, 0x44, 0x78, 0x40, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x34, +0x4c, 0x44, 0x44, 0x44, 0x3c, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x30, 0x20, 0x20, 0x20, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x38, 0x04, 0x44, 0x78, 0x00, 0x00, 0x00, +0x00, 0x00, 0x20, 0x7c, 0x20, 0x20, 0x20, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, +0x44, 0x44, 0x44, 0x4c, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44, 0x28, 0x28, +0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x54, 0x54, 0x54, 0x28, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xcc, 0x48, 0x30, 0x30, 0x48, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, +0x44, 0x24, 0x28, 0x18, 0x10, 0x10, 0x78, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x48, 0x10, 0x20, 0x44, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x08, 0x00, +0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10, +0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x58, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const struct rtgui_font_bitmap asc12 = +{ + asc12_font, /* bmp */ + 6, /* width */ + 12, /* height */ + 0, /* first char */ + 255 /* last char */ +}; + +struct rtgui_font rtgui_font_asc12 = +{ + "asc", /* family */ + 12, /* height */ + 1, /* refer count */ + &bmp_font_engine, /* font engine */ + (struct rtgui_font_bitmap *)&asc12, /* font private data */ +}; diff --git a/rtgui/common/asc16font.c b/rtgui/common/asc16font.c new file mode 100644 index 0000000000000000000000000000000000000000..bf69713c2f095535708b440648e4860385e750ac --- /dev/null +++ b/rtgui/common/asc16font.c @@ -0,0 +1,293 @@ +/* + * File : asc16font.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include + +unsigned char asc16_font[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00, +0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, +0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, +0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00, +0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, +0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00, +0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00, +0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, +0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, +0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +struct rtgui_font_bitmap asc16 = +{ + asc16_font, /* bmp */ + 8, /* width */ + 16, /* height */ + 0, /* first char */ + 255 /* last char */ +}; + +struct rtgui_font rtgui_font_asc16 = +{ + "asc", /* family */ + 16, /* height */ + 1, /* refer count */ + &bmp_font_engine, /* font engine */ + &asc16, /* font private data */ +}; + +/* size = 4096 bytes */ diff --git a/rtgui/common/caret.c b/rtgui/common/caret.c new file mode 100644 index 0000000000000000000000000000000000000000..dbf5d6af45e790930f37bdfc928aa03ced9d4870 --- /dev/null +++ b/rtgui/common/caret.c @@ -0,0 +1,214 @@ +/* + * File : caret.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include +#include + +#define RTGUI_CARET_WIDTH 2 + +#ifdef __WIN32__ +#define RTGUI_CARET_BLINK 300 +#else +#define RTGUI_CARET_BLINK 30 +#endif + +static void rtgui_caret_blink(struct rtgui_timer* timer, void* parameter) +{ + struct rtgui_caret* caret; + rtgui_widget_t* widget; + + caret = (struct rtgui_caret*)parameter; + + RT_ASSERT(caret != RT_NULL); + + if (caret->owner == RT_NULL) return; + + /* caret's owner is visible? */ + widget = caret->owner; + do + { + if (RTGUI_WIDGET_IS_HIDE(widget) == RT_TRUE) return; + + widget = widget->parent; + } while (widget != RT_NULL); + + if (caret->is_show == RT_TRUE) + { + /* set to false */ + caret->is_show = RT_FALSE; + + /* update owner widget */ + if (caret->owner != RT_NULL) + { + rtgui_widget_update(caret->owner); + } + } + else + { + /* set to true */ + caret->is_show = RT_TRUE; + + /* draw caret */ + rtgui_caret_draw(caret); + } +} + +struct rtgui_caret* rtgui_caret_create(struct rtgui_widget* owner) +{ + struct rtgui_caret* caret; + + RT_ASSERT(owner != RT_NULL); + + caret = (struct rtgui_caret*)rtgui_malloc(sizeof(struct rtgui_caret)); + if (caret != RT_NULL) + { + caret->is_show = RT_FALSE; + + caret->extent.x1 = 0; + caret->extent.y1 = 0; + caret->extent.x2 = RTGUI_CARET_WIDTH; + caret->extent.y2 = owner->gc.font->height; + caret->owner = owner; + + caret->dc = (struct rtgui_dc*)rtgui_dc_buffer_create(RTGUI_CARET_WIDTH, caret->extent.y2); + if (caret->dc == RT_NULL) goto __exit; + + rtgui_dc_set_color(caret->dc, black); + rtgui_dc_fill_rect(caret->dc, &(caret->extent)); + + caret->timer_period = RTGUI_CARET_BLINK; + caret->timer = rtgui_timer_create(caret->timer_period, + RT_TIMER_FLAG_PERIODIC, + rtgui_caret_blink, caret); + if (caret->timer == RT_NULL) goto __exit_dc; + + caret->show_point.x = 0; + caret->show_point.y = 0; + } + + return caret; + +__exit_dc: + rtgui_dc_destory(caret->dc); +__exit: + rtgui_free(caret); + return RT_NULL; +} + +void rtgui_caret_destroy(struct rtgui_caret* caret) +{ + RT_ASSERT(caret != RT_NULL); + + if (caret->is_show == RT_TRUE) + { + /* stop timer */ + rtgui_timer_stop(caret->timer); + } + + caret->owner = RT_NULL; + rtgui_dc_destory(caret->dc); + rtgui_timer_destory(caret->timer); + + rtgui_free(caret); +} + +/* show caret on owner widget logic position */ +void rtgui_caret_show(struct rtgui_caret* caret, rt_base_t x, rt_base_t y) +{ + if (caret->is_show == RT_TRUE) + { + /* set show flag and stop blink timer */ + caret->is_show = RT_FALSE; + rtgui_timer_stop(caret->timer); + } + + /* set show x and y */ + caret->show_point.x = x; + caret->show_point.y = y; + + /* set show flag and start blink timer */ + caret->is_show = RT_TRUE; + + /* draw caret */ + rtgui_caret_draw(caret); + + /* start blink timer */ + rtgui_timer_start(caret->timer); +} + +void rtgui_caret_hide(struct rtgui_caret* caret) +{ + RT_ASSERT(caret != RT_NULL); + + /* set show flag and stop blink timer */ + caret->is_show = RT_FALSE; + rtgui_timer_stop(caret->timer); + + /* update owner widget */ + if (caret->owner != RT_NULL) + { + rtgui_widget_update(caret->owner); + } +} + +void rtgui_caret_set_point(struct rtgui_caret* caret, int x, int y) +{ + RT_ASSERT(caret != RT_NULL); + + if (caret->is_show == RT_TRUE) + { + /* stop the old caret */ + rtgui_timer_stop(caret->timer); + /* update owner widget */ + if (caret->owner != RT_NULL && caret->is_show) + { + rtgui_widget_update(caret->owner); + } + } + + caret->show_point.x = x; + caret->show_point.y = y; + + /* draw caret */ + rtgui_caret_draw(caret); + + /* start blink timer */ + rtgui_timer_start(caret->timer); +} + +void rtgui_caret_set_box(struct rtgui_caret* caret, int w, int h) +{ + RT_ASSERT(caret != RT_NULL); + + caret->extent.x2 = caret->extent.x1 + w; + caret->extent.y2 = caret->extent.y1 + h; +} + +void rtgui_caret_draw(struct rtgui_caret* caret) +{ + RT_ASSERT(caret != RT_NULL); + + if (caret->is_show == RT_TRUE && caret->owner->toplevel != RT_NULL) + { + struct rtgui_rect rect = caret->extent; + struct rtgui_point point = {0, 0}; + struct rtgui_dc* hw_dc; + + rtgui_rect_moveto(&rect, caret->show_point.x, caret->show_point.y); + hw_dc = rtgui_dc_begin_drawing(caret->owner); + rtgui_dc_blit(caret->dc, &point, hw_dc, &rect); + rtgui_dc_end_drawing(hw_dc); + } +} + diff --git a/rtgui/common/color.c b/rtgui/common/color.c new file mode 100644 index 0000000000000000000000000000000000000000..33fc3606d642712d38a6c9a3e216a1489a2263b0 --- /dev/null +++ b/rtgui/common/color.c @@ -0,0 +1,33 @@ +/* + * File : color.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include + +const rtgui_color_t red = RTGUI_RGB(0xff, 0x00, 0x00); +const rtgui_color_t green = RTGUI_RGB(0x00, 0xff, 0x00); +const rtgui_color_t blue = RTGUI_RGB(0x00, 0x00, 0xff); +const rtgui_color_t black = RTGUI_RGB(0x00, 0x00, 0x00); +const rtgui_color_t white = RTGUI_RGB(0xff, 0xff, 0xff); + +const rtgui_color_t high_light = RTGUI_RGB(0xff, 0xff, 0xff); +const rtgui_color_t dark_grey = RTGUI_RGB(0x7f, 0x7f, 0x7f); +const rtgui_color_t light_grey = RTGUI_RGB(0xc0, 0xc0, 0xc0); + +const rtgui_color_t default_foreground = RTGUI_RGB(0x00, 0x00, 0x00); +const rtgui_color_t default_background = RTGUI_RGB(0xff, 0xff, 0xff); + +#define RTGUI_RGB_R(c) ((c) & 0xff) +#define RTGUI_RGB_G(c) (((c) >> 8) & 0xff) +#define RTGUI_RGB_B(c) (((c) >> 16) & 0xff) +#define RTGUI_RGB_A(c) (((c) >> 24) & 0xff) + diff --git a/rtgui/common/dc.c b/rtgui/common/dc.c new file mode 100644 index 0000000000000000000000000000000000000000..5701c56f4e0bf8efa8c6359e1da11b861fd96709 --- /dev/null +++ b/rtgui/common/dc.c @@ -0,0 +1,1223 @@ +/* + * File : dc.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include + +void rtgui_dc_destory(struct rtgui_dc* dc) +{ + if (dc == RT_NULL) return; + + dc->fini(dc); + rtgui_free(dc); +} + +/* + * draw a point on dc + */ +void rtgui_dc_draw_point(struct rtgui_dc* dc, int x, int y) +{ + if (dc == RT_NULL) return; + + dc->draw_point(dc, x, y); +} + +#if 0 +void rtgui_dc_draw_point_alpha(struct rtgui_dc* dc, int x, int y, rt_uint8_t alpha) +{ + if (dc == RT_NULL || alpha == 0xff) return; + + if (dc->draw_point_alpha != RT_NULL) + dc->draw_point_alpha(dc, x, y, alpha); + else + { + rtgui_color_t color; + + /* soft alpha bending */ + color = dc->get_color(dc, int x, int y); + dc->draw_point(dc, x, y); + } +} +#endif + +/* + * draw a vertical line on dc + */ +void rtgui_dc_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2) +{ + if (dc == RT_NULL) return; + + dc->draw_vline(dc, x, y1, y2); +} + +/* + * draw a horizontal line on dc + */ +void rtgui_dc_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y) +{ + if (dc == RT_NULL) return; + + dc->draw_hline(dc, x1, x2, y); +} + +void rtgui_dc_draw_line (struct rtgui_dc* dc, int x1, int y1, int x2, int y2) +{ + if (dc == RT_NULL) return; + + if (y1 == y2) + { + rtgui_dc_draw_hline(dc, x1, x2, y1); + } + else if (x1 == x2) + { + rtgui_dc_draw_vline(dc, x1, y1, y2); + } + else + { + int dx, dy, sdx, sdy, dxabs, dyabs, x, y, px, py; + register rt_base_t i; + /* rtgui_rect_t rect; */ + + dx = x2 - x1; /* the horizontal distance of the line */ + dy = y2 - y1; /* the vertical distance of the line */ + +#define rtgui_sgn(x) ((x<0)?-1:((x>0)?1:0)) /* macro to return the sign of a number */ +#define rtgui_abs(x) ((x)>=0? (x):-(x)) /* macro to return the absolute value */ + + dxabs = rtgui_abs(dx); + dyabs = rtgui_abs(dy); + sdx = rtgui_sgn(dx); + sdy = rtgui_sgn(dy); + x = dyabs >> 1; + y = dxabs >> 1; + px = x1; + py = y1; + + if(dxabs >= dyabs) /* the line is more horizontal than vertical */ + { + for(i = 0; i < dxabs; i++) + { + y += dyabs; + if(y >= dxabs) + { + y -= dxabs; + py += sdy; + } + px += sdx; + + /* draw this point */ + dc->draw_point(dc, px, py); + } + } + else /* the line is more vertical than horizontal */ + { + for(i = 0; i < dyabs; i++) + { + x += dxabs; + if(x >= dyabs) + { + x -= dyabs; + px += sdx; + } + py += sdy; + + /* draw this point */ + dc->draw_point(dc, px, py); + } + } + } +} + +#if 0 +/* AA Line */ +#define AAlevels 256 +#define AAbits 8 + +int rtgui_dc_draw_line_aa(struct rtgui_dc* dc, rt_int16_t x1, rt_int16_t y1, rt_int16_t x2, rt_int16_t y2) +{ + Sint32 xx0, yy0, xx1, yy1; + int result; + rt_uint32_t intshift, erracc, erradj; + rt_uint32_t erracctmp, wgt, wgtcompmask; + int dx, dy, tmp, xdir, y0p1, x0pxdir; + + /* + * Keep on working with 32bit numbers + */ + xx0 = x1; + yy0 = y1; + xx1 = x2; + yy1 = y2; + + /* + * Reorder points if required + */ + if (yy0 > yy1) + { + tmp = yy0; + yy0 = yy1; + yy1 = tmp; + tmp = xx0; + xx0 = xx1; + xx1 = tmp; + } + + /* + * Calculate distance + */ + dx = xx1 - xx0; + dy = yy1 - yy0; + + /* + * Adjust for negative dx and set xdir + */ + if (dx >= 0) + { + xdir = 1; + } + else + { + xdir = -1; + dx = (-dx); + } + + /* + * Check for special cases + */ + if (dx == 0) + { + /* + * Vertical line + */ + rtgui_dc_draw_vline(dc, x1, y1, y2); + return ; + } + else if (dy == 0) + { + /* + * Horizontal line + */ + rtgui_dc_draw_hline(dc, x1, x2, y1); + return ; + } + else if (dx == dy) + { + /* + * Diagonal line + */ + rtgui_dc_draw_line(dc, x1, y1, x2, y2); + return ; + } + + /* + * Zero accumulator + */ + erracc = 0; + + /* + * # of bits by which to shift erracc to get intensity level + */ + intshift = 32 - AAbits; + /* + * Mask used to flip all bits in an intensity weighting + */ + wgtcompmask = AAlevels - 1; + + /* + * Draw the initial pixel in the foreground color + */ + rtgui_dc_draw_point(dc, x1, y1); + + /* + * x-major or y-major? + */ + if (dy > dx) + { + /* + * y-major. Calculate 16-bit fixed point fractional part of a pixel that + * X advances every time Y advances 1 pixel, truncating the result so that + * we won't overrun the endpoint along the X axis + */ + /* + * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy; + */ + erradj = ((dx << 16) / dy) << 16; + + /* + * draw all pixels other than the first and last + */ + x0pxdir = xx0 + xdir; + while (--dy) + { + erracctmp = erracc; + erracc += erradj; + if (erracc <= erracctmp) + { + /* + * rollover in error accumulator, x coord advances + */ + xx0 = x0pxdir; + x0pxdir += xdir; + } + yy0++; /* y-major so always advance Y */ + + /* + * the AAbits most significant bits of erracc give us the intensity + * weighting for this pixel, and the complement of the weighting for + * the paired pixel. + */ + wgt = (erracc >> intshift) & 255; + rtgui_dc_draw_point_alpha (dc, xx0, yy0, 255 - wgt); + rtgui_dc_draw_point_alpha (dc, x0pxdir, yy0, wgt); + } + } + else + { + + /* + * x-major line. Calculate 16-bit fixed-point fractional part of a pixel + * that Y advances each time X advances 1 pixel, truncating the result so + * that we won't overrun the endpoint along the X axis. + */ + /* + * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx; + */ + erradj = ((dy << 16) / dx) << 16; + + /* + * draw all pixels other than the first and last + */ + y0p1 = yy0 + 1; + while (--dx) + { + + erracctmp = erracc; + erracc += erradj; + if (erracc <= erracctmp) + { + /* + * Accumulator turned over, advance y + */ + yy0 = y0p1; + y0p1++; + } + xx0 += xdir; /* x-major so always advance X */ + /* + * the AAbits most significant bits of erracc give us the intensity + * weighting for this pixel, and the complement of the weighting for + * the paired pixel. + */ + wgt = (erracc >> intshift) & 255; + rtgui_dc_draw_point_alpha (dc, xx0, yy0, 255 - wgt); + rtgui_dc_draw_point_alpha (dc, xx0, y0p1, wgt); + } + } + + /* + * Draw final pixel, always exactly intersected by the line and doesn't + * need to be weighted. + */ + rtgui_dc_draw_point(dc, x2, y2); +} +#endif + +void rtgui_dc_draw_rect (struct rtgui_dc* dc, struct rtgui_rect* rect) +{ + rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y1); + rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y2 - 1); + + rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2); + rtgui_dc_draw_vline(dc, rect->x2 - 1, rect->y1, rect->y2); +} + +void rtgui_dc_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect) +{ + if (dc == RT_NULL) return; + + dc->fill_rect(dc, rect); +} + +void rtgui_dc_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect) +{ + if (dc == RT_NULL || dest == RT_NULL || rect == RT_NULL) return; + + dc->blit(dc, dc_point, dest, rect); +} + +void rtgui_dc_draw_text (struct rtgui_dc* dc, const rt_uint8_t* text, struct rtgui_rect* rect) +{ + rt_uint32_t len; + struct rtgui_font *font; +#ifdef RTGUI_USING_FONTHZ + struct rtgui_font *gb2312_font; +#endif + struct rtgui_rect text_rect; + + RT_ASSERT(dc != RT_NULL); + + font = rtgui_dc_get_font(dc); + if (font == RT_NULL) + { + /* use system default font */ + font = rtgui_font_default(); + } + +#ifdef RTGUI_USING_FONTHZ + gb2312_font = rtgui_font_refer("hz", font->height); + if (gb2312_font == RT_NULL) + { + gb2312_font = rtgui_font_refer("hz", 16); + } +#endif + + /* text align */ + rtgui_font_get_metrics(font, text, &text_rect); + rtgui_rect_moveto_align(rect, &text_rect, rtgui_dc_get_textalign(dc)); + +#ifdef RTGUI_USING_FONTHZ + while (*text) + { + len = 0; + while (*(text + len) < 0x80 && *(text + len)) len ++; + if (len > 0) + { + rtgui_font_draw(font, dc, text, len, &text_rect); + + text += len; + } + + len = 0; + while (*(text + len) > 0x80) len ++; + if (len > 0) + { + rtgui_font_draw(gb2312_font, dc, text, len, &text_rect); + + text += len; + } + } + + rtgui_font_derefer(gb2312_font); +#else + len = strlen(text); + rtgui_font_draw(font, dc, text, len, &text_rect); +#endif +} + +void rtgui_dc_set_color(struct rtgui_dc* dc, rtgui_color_t color) +{ + if (dc != RT_NULL) + { + dc->set_color(dc, color); + } +} + +rtgui_color_t rtgui_dc_get_color(struct rtgui_dc* dc) +{ + if (dc != RT_NULL) + { + return dc->get_color(dc); + } + + return white; +} + +void rtgui_dc_set_font(struct rtgui_dc* dc, rtgui_font_t* font) +{ + if (dc != RT_NULL) + { + dc->set_font(dc, font); + } +} + +rtgui_font_t* rtgui_dc_get_font(struct rtgui_dc* dc) +{ + if (dc != RT_NULL) + { + return dc->get_font(dc); + } + + return RT_NULL; +} + +void rtgui_dc_set_textalign(struct rtgui_dc* dc, rt_int32_t align) +{ + if (dc != RT_NULL) + { + dc->set_textalign(dc, align); + } +} + +rt_int32_t rtgui_dc_get_textalign(struct rtgui_dc* dc) +{ + if (dc != RT_NULL) + { + return dc->get_textalign(dc); + } + + return RTGUI_ALIGN_NOT; +} + +rt_bool_t rtgui_dc_get_visible(struct rtgui_dc* dc) +{ + if (dc != RT_NULL) + { + return dc->get_visible(dc); + } + + return RT_FALSE; +} + +void rtgui_dc_draw_shaded_rect(struct rtgui_dc* dc, rtgui_rect_t* rect, + rtgui_color_t c1, rtgui_color_t c2) +{ + RT_ASSERT(dc != RT_NULL); + + rtgui_dc_set_color(dc, c1); + rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2); + rtgui_dc_draw_hline(dc, rect->x1 + 1, rect->x2, rect->y1); + + rtgui_dc_set_color(dc, c2); + rtgui_dc_draw_vline(dc, rect->x2, rect->y1, rect->y2); + rtgui_dc_draw_hline(dc, rect->x1, rect->x2 + 1, rect->y2); +} + +void rtgui_dc_draw_border(struct rtgui_dc* dc, rtgui_rect_t* rect, int flag) +{ + rtgui_rect_t r; + rtgui_color_t color; + + if (dc == RT_NULL) return ; + + /* save old color */ + color = rtgui_dc_get_color(dc); + + r = *rect; + switch (flag) + { + case RTGUI_BORDER_RAISE: + rtgui_dc_draw_shaded_rect(dc, &r, high_light, black); + rtgui_rect_inflate(&r, -1); + rtgui_dc_draw_shaded_rect(dc, &r, light_grey, dark_grey); + break; + + case RTGUI_BORDER_SUNKEN: + rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light); + rtgui_rect_inflate(&r, -1); + rtgui_dc_draw_shaded_rect(dc, &r, black, light_grey); + break; + + case RTGUI_BORDER_BOX: + rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light); + rtgui_rect_inflate(&r, -1); + rtgui_dc_draw_shaded_rect(dc, &r, high_light, dark_grey); + break; + + case RTGUI_BORDER_STATIC: + rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light); + break; + + case RTGUI_BORDER_EXTRA: + rtgui_dc_set_color(dc, light_grey); + rtgui_dc_draw_rect(dc, &r); + break; + + case RTGUI_BORDER_SIMPLE: + rtgui_dc_set_color(dc, black); + rtgui_dc_draw_rect(dc, &r); + break; + + default: + break; + } + + /* restore color */ + rtgui_dc_set_color(dc, color); +} + +void rtgui_dc_draw_horizontal_line(struct rtgui_dc* dc, int x1, int x2, int y) +{ + rtgui_color_t color; + + if (dc == RT_NULL) return ; + + /* save old color */ + color = rtgui_dc_get_color(dc); + + rtgui_dc_set_color(dc, dark_grey); + rtgui_dc_draw_hline(dc, x1, x2, y); + + y ++; + + rtgui_dc_set_color(dc, high_light); + rtgui_dc_draw_hline(dc, x1, x2, y); + + /* restore color */ + rtgui_dc_set_color(dc, color); +} + +void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2) +{ + rtgui_color_t color; + + if (dc == RT_NULL) return ; + + /* save old color */ + color = rtgui_dc_get_color(dc); + + rtgui_dc_set_color(dc, dark_grey); + rtgui_dc_draw_hline(dc, x, y1, y2); + + x ++; + + rtgui_dc_set_color(dc, high_light); + rtgui_dc_draw_hline(dc, x, y1, y2); + + /* restore color */ + rtgui_dc_set_color(dc, color); +} + +void rtgui_dc_draw_arrow(struct rtgui_dc* dc, rtgui_rect_t* rect, int kind) +{ + rt_int32_t i; + rt_int32_t x1, y1, x2, y2; + rtgui_rect_t r = {0, 0, 0, 0}; + + static const rt_uint8_t ARROW_WIDTH = 7; + static const rt_uint8_t ARROW_LENGTH = 4; + + x1 = y1 = 0; + + switch (kind) + { + case RTGUI_ARRAW_UP: + case RTGUI_ARRAW_DOWN: + r.x2 = ARROW_WIDTH; + r.y2 = ARROW_LENGTH; + break; + + case RTGUI_ARRAW_LEFT: + case RTGUI_ARRAW_RIGHT: + r.x2 = ARROW_LENGTH; + r.y2 = ARROW_WIDTH; + break; + } + rtgui_rect_moveto_align(rect, &r, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL); + + switch (kind) + { + case RTGUI_ARRAW_UP: + x1 = r.x1 + (ARROW_WIDTH - 1)/2;; + y1 = r.y1; + break; + case RTGUI_ARRAW_DOWN: + x1 = r.x1 + (ARROW_WIDTH - 1)/2; + y1 = r.y1 + ARROW_LENGTH - 1; + break; + case RTGUI_ARRAW_LEFT: + x1 = r.x1; + y1 = r.y1 + (ARROW_WIDTH - 1)/2; + break; + case RTGUI_ARRAW_RIGHT: + x1 = r.x1 + ARROW_LENGTH - 1; + y1 = r.y1 + (ARROW_WIDTH - 1)/2; + break; + default: + return; + } + x2 = x1; + y2 = y1; + + for (i = 0; i < ARROW_LENGTH; i++) + { + rtgui_dc_draw_line(dc, x1, y1, x2, y2); + + switch (kind) + { + case RTGUI_ARRAW_UP: + x1 --; + x2 ++; + y1 ++; + y2 ++; + break; + + case RTGUI_ARRAW_DOWN: + x1 --; + x2 ++; + y1 --; + y2 --; + break; + + case RTGUI_ARRAW_LEFT: + y1 --; + y2 ++; + x1 ++; + x2 ++; + break; + + case RTGUI_ARRAW_RIGHT: + y1 --; + y2 ++; + x1 --; + x2 --; + break; + } + } +} + +void rtgui_dc_draw_polygon(struct rtgui_dc* dc, const int *vx, const int *vy, int count) +{ + int i; + const int *x1, *y1, *x2, *y2; + + /* + * Sanity check + */ + if (count < 3) return; + + /* + * Pointer setup + */ + x1 = x2 = vx; + y1 = y2 = vy; + x2++; + y2++; + + /* + * Draw + */ + for (i = 1; i < count; i++) + { + rtgui_dc_draw_line(dc, *x1, *y1, *x2, *y2); + x1 = x2; + y1 = y2; + x2++; + y2++; + } + rtgui_dc_draw_line(dc, *x1, *y1, *vx, *vy); +} + +static int _int_compare(const void *a, const void *b) +{ + return (*(const int *) a) - (*(const int *) b); +} + +void rtgui_dc_fill_polygon(struct rtgui_dc* dc, const int* vx, const int* vy, int count) +{ + int i; + int y, xa, xb; + int miny, maxy; + int x1, y1; + int x2, y2; + int ind1, ind2; + int ints; + int *poly_ints = RT_NULL; + + /* + * Sanity check number of edges + */ + if (count < 3) return; + + /* + * Allocate temp array, only grow array + */ + poly_ints = (int *) rt_malloc(sizeof(int) * count); + if (poly_ints == RT_NULL) return ; /* no memory, failed */ + + /* + * Determine Y maximal + */ + miny = vy[0]; + maxy = vy[0]; + for (i = 1; (i < count); i++) + { + if (vy[i] < miny) miny = vy[i]; + else if (vy[i] > maxy) maxy = vy[i]; + } + + /* + * Draw, scanning y + */ + for (y = miny; (y <= maxy); y++) { + ints = 0; + for (i = 0; (i < count); i++) { + if (!i) { + ind1 = count - 1; + ind2 = 0; + } else { + ind1 = i - 1; + ind2 = i; + } + y1 = vy[ind1]; + y2 = vy[ind2]; + if (y1 < y2) { + x1 = vx[ind1]; + x2 = vx[ind2]; + } else if (y1 > y2) { + y2 = vy[ind1]; + y1 = vy[ind2]; + x2 = vx[ind1]; + x1 = vx[ind2]; + } else { + continue; + } + + if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) + { + poly_ints[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1); + } + } + + qsort(poly_ints, ints, sizeof(int), _int_compare); + + for (i = 0; (i < ints); i += 2) + { + xa = poly_ints[i] + 1; + xa = (xa >> 16) + ((xa & 32768) >> 15); + xb = poly_ints[i+1] - 1; + xb = (xb >> 16) + ((xb & 32768) >> 15); + rtgui_dc_draw_hline(dc, xa, xb, y); + } + } +} + +void rtgui_dc_draw_circle(struct rtgui_dc* dc, int x, int y, int r) +{ + rt_int16_t cx = 0; + rt_int16_t cy = r; + rt_int16_t df = 1 - r; + rt_int16_t d_e = 3; + rt_int16_t d_se = -2 * r + 5; + rt_int16_t xpcx, xmcx, xpcy, xmcy; + rt_int16_t ypcy, ymcy, ypcx, ymcx; + + /* + * sanity check radius + */ + if (r < 0) return ; + + /* special case for r=0 - draw a point */ + if (r == 0) rtgui_dc_draw_point(dc, x, y); + + /* + * draw circle + */ + do + { + ypcy = y + cy; + ymcy = y - cy; + if (cx > 0) + { + xpcx = x + cx; + xmcx = x - cx; + rtgui_dc_draw_point(dc, xmcx, ypcy); + rtgui_dc_draw_point(dc, xpcx, ypcy); + rtgui_dc_draw_point(dc, xmcx, ymcy); + rtgui_dc_draw_point(dc, xpcx, ymcy); + } + else + { + rtgui_dc_draw_point(dc, x, ymcy); + rtgui_dc_draw_point(dc, x, ypcy); + } + xpcy = x + cy; + xmcy = x - cy; + if ((cx > 0) && (cx != cy)) + { + ypcx = y + cx; + ymcx = y - cx; + rtgui_dc_draw_point(dc, xmcy, ypcx); + rtgui_dc_draw_point(dc, xpcy, ypcx); + rtgui_dc_draw_point(dc, xmcy, ymcx); + rtgui_dc_draw_point(dc, xpcy, ymcx); + } + else if (cx == 0) + { + rtgui_dc_draw_point(dc, xmcy, y); + rtgui_dc_draw_point(dc, xpcy, y); + } + + /* + * Update + */ + if (df < 0) + { + df += d_e; + d_e += 2; + d_se += 2; + } + else + { + df += d_se; + d_e += 2; + d_se += 4; + cy--; + } + cx++; + }while (cx <= cy); +} + +void rtgui_dc_fill_circle(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t r) +{ + rt_int16_t cx = 0; + rt_int16_t cy = r; + rt_int16_t ocx = (rt_int16_t) 0xffff; + rt_int16_t ocy = (rt_int16_t) 0xffff; + rt_int16_t df = 1 - r; + rt_int16_t d_e = 3; + rt_int16_t d_se = -2 * r + 5; + rt_int16_t xpcx, xmcx, xpcy, xmcy; + rt_int16_t ypcy, ymcy, ypcx, ymcx; + + /* + * Sanity check radius + */ + if (r < 0) return; + + /* + * Special case for r=0 - draw a point + */ + if (r == 0) + { + rtgui_dc_draw_point(dc, x, y); + return ; + } + + /* + * Draw + */ + do { + xpcx = x + cx; + xmcx = x - cx; + xpcy = x + cy; + xmcy = x - cy; + if (ocy != cy) { + if (cy > 0) { + ypcy = y + cy; + ymcy = y - cy; + rtgui_dc_draw_hline(dc, xmcx, xpcx, ypcy); + rtgui_dc_draw_hline(dc, xmcx, xpcx, ymcy); + } else { + rtgui_dc_draw_hline(dc, xmcx, xpcx, y); + } + ocy = cy; + } + if (ocx != cx) { + if (cx != cy) { + if (cx > 0) { + ypcx = y + cx; + ymcx = y - cx; + rtgui_dc_draw_hline(dc, xmcy, xpcy, ymcx); + rtgui_dc_draw_hline(dc, xmcy, xpcy, ypcx); + } else { + rtgui_dc_draw_hline(dc, xmcy, xpcy, y); + } + } + ocx = cx; + } + /* + * Update + */ + if (df < 0) { + df += d_e; + d_e += 2; + d_se += 2; + } else { + df += d_se; + d_e += 2; + d_se += 4; + cy--; + } + cx++; + } while (cx <= cy); +} + +void rtgui_dc_draw_ellipse(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry) +{ + int ix, iy; + int h, i, j, k; + int oh, oi, oj, ok; + int xmh, xph, ypk, ymk; + int xmi, xpi, ymj, ypj; + int xmj, xpj, ymi, ypi; + int xmk, xpk, ymh, yph; + + /* + * Sanity check radii + */ + if ((rx < 0) || (ry < 0)) return; + + /* + * Special case for rx=0 - draw a vline + */ + if (rx == 0) + { + rtgui_dc_draw_vline(dc, x, y - ry, y + ry); + return; + } + + /* + * Special case for ry=0 - draw a hline + */ + if (ry == 0) + { + rtgui_dc_draw_hline(dc, x - rx, x + rx, y); + return; + } + + /* + * Init vars + */ + oh = oi = oj = ok = 0xFFFF; + + if (rx > ry) + { + ix = 0; + iy = rx * 64; + + do + { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * ry) / rx; + k = (i * ry) / rx; + + if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) + { + xph = x + h; + xmh = x - h; + if (k > 0) + { + ypk = y + k; + ymk = y - k; + rtgui_dc_draw_point(dc, xmh, ypk); + rtgui_dc_draw_point(dc, xph, ypk); + rtgui_dc_draw_point(dc, xmh, ymk); + rtgui_dc_draw_point(dc, xph, ymk); + } + else + { + rtgui_dc_draw_point(dc, xmh, y); + rtgui_dc_draw_point(dc, xph, y); + } + ok = k; + xpi = x + i; + xmi = x - i; + if (j > 0) + { + ypj = y + j; + ymj = y - j; + rtgui_dc_draw_point(dc, xmi, ypj); + rtgui_dc_draw_point(dc, xpi, ypj); + rtgui_dc_draw_point(dc, xmi, ymj); + rtgui_dc_draw_point(dc, xpi, ymj); + } + else + { + rtgui_dc_draw_point(dc, xmi, y); + rtgui_dc_draw_point(dc, xpi, y); + } + oj = j; + } + + ix = ix + iy / rx; + iy = iy - ix / rx; + } while (i > h); + } + else + { + ix = 0; + iy = ry * 64; + + do + { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * rx) / ry; + k = (i * rx) / ry; + + if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) + { + xmj = x - j; + xpj = x + j; + if (i > 0) + { + ypi = y + i; + ymi = y - i; + rtgui_dc_draw_point(dc, xmj, ypi); + rtgui_dc_draw_point(dc, xpj, ypi); + rtgui_dc_draw_point(dc, xmj, ymi); + rtgui_dc_draw_point(dc, xpj, ymi); + } + else + { + rtgui_dc_draw_point(dc, xmj, y); + rtgui_dc_draw_point(dc, xpj, y); + } + oi = i; + xmk = x - k; + xpk = x + k; + if (h > 0) + { + yph = y + h; + ymh = y - h; + rtgui_dc_draw_point(dc, xmk, yph); + rtgui_dc_draw_point(dc, xpk, yph); + rtgui_dc_draw_point(dc, xmk, ymh); + rtgui_dc_draw_point(dc, xpk, ymh); + } + else + { + rtgui_dc_draw_point(dc, xmk, y); + rtgui_dc_draw_point(dc, xpk, y); + } + oh = h; + } + + ix = ix + iy / ry; + iy = iy - ix / ry; + } while (i > h); + } +} + +void rtgui_dc_fill_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry) +{ + int ix, iy; + int h, i, j, k; + int oh, oi, oj, ok; + int xmh, xph; + int xmi, xpi; + int xmj, xpj; + int xmk, xpk; + + /* + * Special case for rx=0 - draw a vline + */ + if (rx == 0) + { + rtgui_dc_draw_vline(dc, x, y - ry, y + ry); + return; + } + + /* special case for ry=0 - draw a hline */ + if (ry == 0) { + rtgui_dc_draw_hline(dc, x - rx, x + rx, y); + return; + } + + /* + * Init vars + */ + oh = oi = oj = ok = 0xFFFF; + + /* + * Draw + */ + if (rx > ry) { + ix = 0; + iy = rx * 64; + + do { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * ry) / rx; + k = (i * ry) / rx; + + if ((ok != k) && (oj != k)) { + xph = x + h; + xmh = x - h; + if (k > 0) { + rtgui_dc_draw_hline(dc, xmh, xph, y + k); + rtgui_dc_draw_hline(dc, xmh, xph, y - k); + } else { + rtgui_dc_draw_hline(dc, xmh, xph, y); + } + ok = k; + } + if ((oj != j) && (ok != j) && (k != j)) { + xmi = x - i; + xpi = x + i; + if (j > 0) { + rtgui_dc_draw_hline(dc, xmi, xpi, y + j); + rtgui_dc_draw_hline(dc, xmi, xpi, y - j); + } else { + rtgui_dc_draw_hline(dc, xmi, xpi, y); + } + oj = j; + } + + ix = ix + iy / rx; + iy = iy - ix / rx; + + } while (i > h); + } else { + ix = 0; + iy = ry * 64; + + do { + h = (ix + 32) >> 6; + i = (iy + 32) >> 6; + j = (h * rx) / ry; + k = (i * rx) / ry; + + if ((oi != i) && (oh != i)) { + xmj = x - j; + xpj = x + j; + if (i > 0) { + rtgui_dc_draw_hline(dc, xmj, xpj, y + i); + rtgui_dc_draw_hline(dc, xmj, xpj, y - i); + } else { + rtgui_dc_draw_hline(dc, xmj, xpj, y); + } + oi = i; + } + if ((oh != h) && (oi != h) && (i != h)) { + xmk = x - k; + xpk = x + k; + if (h > 0) { + rtgui_dc_draw_hline(dc, xmk, xpk, y + h); + rtgui_dc_draw_hline(dc, xmk, xpk, y - h); + } else { + rtgui_dc_draw_hline(dc, xmk, xpk, y); + } + oh = h; + } + ix = ix + iy / ry; + iy = iy - ix / ry; + } while (i > h); + } +} + +void rtgui_dc_draw_focus_rect(struct rtgui_dc* dc, rtgui_rect_t* rect) +{ + int i; + + for (i = rect->x1; i <= rect->x2; i += 2) + { + rtgui_dc_draw_point(dc, i, rect->y1); + rtgui_dc_draw_point(dc, i, rect->y2); + } + + for (i = rect->y1; i <= rect->y2; i += 2) + { + rtgui_dc_draw_point(dc, rect->x1, i); + rtgui_dc_draw_point(dc, rect->x2, i); + } +} + +void rtgui_dc_get_rect(struct rtgui_dc*dc, rtgui_rect_t* rect) +{ + if (dc != RT_NULL && rect != RT_NULL) + { + dc->get_rect(dc, rect); + } +} diff --git a/rtgui/common/dc_buffer.c b/rtgui/common/dc_buffer.c new file mode 100644 index 0000000000000000000000000000000000000000..a04fcb9c78b66f3b24e06ce76599ebcd65c3a9bd --- /dev/null +++ b/rtgui/common/dc_buffer.c @@ -0,0 +1,392 @@ +/* + * File : dc_buffer.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include +#include +#include + +struct rtgui_dc_buffer +{ + struct rtgui_dc parent; + + /* color and font */ + rtgui_color_t color; + struct rtgui_font* font; + /* text align */ + rt_int32_t align; + + /* width and height */ + rt_uint16_t width, height; + rt_uint16_t pitch; + + /* blit info */ + rt_uint32_t clip_sync; + rtgui_region_t clip; + + /* pixel data */ + rt_uint8_t* pixel; +}; + +static rt_bool_t rtgui_dc_buffer_fini(struct rtgui_dc* dc); +static void rtgui_dc_buffer_draw_point(struct rtgui_dc* dc, int x, int y); +static void rtgui_dc_buffer_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2); +static void rtgui_dc_buffer_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y); +static void rtgui_dc_buffer_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect); +static void rtgui_dc_buffer_blit(struct rtgui_dc* self, struct rtgui_point* dc_point, + struct rtgui_dc* dest, rtgui_rect_t* rect); +static void rtgui_dc_buffer_set_color (struct rtgui_dc* dc, rtgui_color_t color); +static rtgui_color_t rtgui_dc_buffer_get_color(struct rtgui_dc* dc); +static void rtgui_dc_buffer_set_font(struct rtgui_dc* dc, rtgui_font_t* font); +static rtgui_font_t* rtgui_dc_buffer_get_font(struct rtgui_dc* dc); +static void rtgui_dc_buffer_set_textalign(struct rtgui_dc* dc, rt_int32_t textalign); +static rt_int32_t rtgui_dc_buffer_get_textalign(struct rtgui_dc* dc); +static rt_bool_t rtgui_dc_buffer_get_visible(struct rtgui_dc* dc); +static void rtgui_dc_buffer_get_rect(struct rtgui_dc* dc, rtgui_rect_t* rect); + +static void rtgui_dc_buffer_init(struct rtgui_dc_buffer* dc) +{ + if (dc == RT_NULL) return; + + dc->parent.type = RTGUI_DC_BUFFER; + dc->parent.draw_point = rtgui_dc_buffer_draw_point; + dc->parent.draw_hline = rtgui_dc_buffer_draw_hline; + dc->parent.draw_vline = rtgui_dc_buffer_draw_vline; + dc->parent.fill_rect = rtgui_dc_buffer_fill_rect; + dc->parent.blit = rtgui_dc_buffer_blit; + + dc->parent.set_color = rtgui_dc_buffer_set_color; + dc->parent.get_color = rtgui_dc_buffer_get_color; + + dc->parent.set_font = rtgui_dc_buffer_set_font; + dc->parent.get_font = rtgui_dc_buffer_get_font; + dc->parent.set_textalign = rtgui_dc_buffer_set_textalign; + dc->parent.get_textalign = rtgui_dc_buffer_get_textalign; + + dc->parent.get_visible= rtgui_dc_buffer_get_visible; + dc->parent.get_rect = rtgui_dc_buffer_get_rect; + + dc->parent.fini = rtgui_dc_buffer_fini; +} + +struct rtgui_dc* rtgui_dc_buffer_create(int w, int h) +{ + struct rtgui_dc_buffer* dc; + + dc = (struct rtgui_dc_buffer*)rtgui_malloc(sizeof(struct rtgui_dc_buffer)); + rtgui_dc_buffer_init(dc); + dc->color = 0; + dc->font = RT_NULL; + dc->align = 0; + + dc->width = w; + dc->height = h; + dc->pitch = w * sizeof(rtgui_color_t); + + dc->clip_sync = 0; + rtgui_region_init(&(dc->clip)); + + dc->pixel = rtgui_malloc(h * dc->pitch); + rt_memset(dc->pixel, 0, h * dc->pitch); + + return &(dc->parent); +} + +rt_uint8_t* rtgui_dc_buffer_get_pixel(struct rtgui_dc* dc) +{ + struct rtgui_dc_buffer* dc_buffer; + + dc_buffer = (struct rtgui_dc_buffer*)dc; + + return dc_buffer->pixel; +} + +static rt_bool_t rtgui_dc_buffer_fini(struct rtgui_dc* dc) +{ + struct rtgui_dc_buffer* buffer = (struct rtgui_dc_buffer*)dc; + + if (dc->type != RTGUI_DC_BUFFER) return RT_FALSE; + + rtgui_free(buffer->pixel); + buffer->pixel = RT_NULL; + + return RT_TRUE; +} + +static void rtgui_dc_buffer_draw_point(struct rtgui_dc* self, int x, int y) +{ + rtgui_color_t* ptr; + struct rtgui_dc_buffer* dc; + + dc = (struct rtgui_dc_buffer*)self; + + /* note: there is no parameter check in this function */ + ptr = (rtgui_color_t*)(dc->pixel + y * dc->pitch + x * sizeof(rtgui_color_t)); + + *ptr = dc->color; +} + +static void rtgui_dc_buffer_draw_vline(struct rtgui_dc* self, int x, int y1, int y2) +{ + rtgui_color_t* ptr; + register rt_base_t index; + struct rtgui_dc_buffer* dc; + + dc = (struct rtgui_dc_buffer*)self; + + if (x >= dc->width) return; + if (y1 > dc->height) y1 = dc->height; + if (y2 > dc->height) y2 = dc->height; + + ptr = (rtgui_color_t*)(dc->pixel + y1 * dc->pitch + x * sizeof(rtgui_color_t)); + for (index = y1; index < y2; index ++) + { + /* draw this point */ + *ptr = dc->color; + ptr += dc->width; + } +} + +static void rtgui_dc_buffer_draw_hline(struct rtgui_dc* self, int x1, int x2, int y) +{ + rtgui_color_t* ptr; + register rt_base_t index; + struct rtgui_dc_buffer* dc; + + dc = (struct rtgui_dc_buffer*)self; + if (y >= dc->height) return; + if (x1 > dc->width) x1 = dc->width; + if (x2 > dc->width) x2 = dc->width; + + ptr = (rtgui_color_t*)(dc->pixel + y * dc->pitch + x1 * sizeof(rtgui_color_t)); + for (index = x1; index < x2; index ++) + { + /* draw this point */ + *ptr++ = dc->color; + } +} + +static void rtgui_dc_buffer_fill_rect (struct rtgui_dc* self, struct rtgui_rect* rect) +{ + rtgui_rect_t r; + struct rtgui_dc_buffer* dc; + + r = *rect; + dc = (struct rtgui_dc_buffer*)self; + if (r.x1 > dc->width) r.x1 = dc->width; + if (r.x2 > dc->width) r.x2 = dc->width; + if (r.y1 > dc->height) r.y1 = dc->height; + if (r.y2 > dc->height) r.y2 = dc->height; + + /* fill first line */ + rtgui_dc_buffer_draw_hline(&(dc->parent), r.x1, r.x2, r.y1); + + /* memory copy other lines */ + if (r.y2 > r.y1) + { + register rt_base_t index; + for (index = r.y1 + 1; index < r.y2; index ++) + { + rt_memcpy(dc->pixel + index * dc->pitch, + dc->pixel + r.y1 * dc->pitch, + (r.x2 - r.x1) * sizeof(rtgui_color_t)); + } + } +} + +/* rtgui_color to RGB323 */ +rt_inline void rtgui_blit_line_1(rtgui_color_t* color, rt_uint8_t* dest, int line) +{ + struct _color {rt_uint8_t r, g, b, a;} *c; + + c = (struct _color*)color; + while (line-- > 0) + { + *dest = (c->r & 0xe0) | (c->g & 0xc0) >> 3 | (c->b & 0xe0) >> 5 ; + + c ++; + dest ++; + } +} + +/* rtgui_color to RGB565 */ +rt_inline void rtgui_blit_line_2(rtgui_color_t* color, rt_uint8_t* dest, int line) +{ + struct _color {rt_uint8_t r, g, b, a;} *c; + rt_uint16_t* ptr; + + c = (struct _color*)color; + ptr = (rt_uint16_t*)dest; + + while (line-- > 0) + { + *ptr = ((c->r & 0xf8) << 8) | ((c->g & 0xfc) << 3) | (c->b >> 3); + + c ++; + ptr ++; + } +} + +/* rtgui_color to RGB888 */ +rt_inline void rtgui_blit_line_4(rtgui_color_t* color, rt_uint8_t* dest, int line) +{ + rt_memcpy(dest, color, line * 4); +} + +static void rtgui_dc_buffer_blit(struct rtgui_dc* self, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect) +{ + struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self; + struct rtgui_dc_hw* hw = (struct rtgui_dc_hw*)dest; + + if (dest->type == RTGUI_DC_HW) + { + register int index; + int fb_pitch; + rtgui_rect_t abs_rect; + void (*blit_line)(rtgui_color_t* color, rt_uint8_t* dest, int line); + + abs_rect.x1 = hw->owner->extent.x1 + rect->x1; + abs_rect.y1 = hw->owner->extent.y1 + rect->y1; + abs_rect.x2 = abs_rect.x1 + rtgui_rect_width(*rect); + abs_rect.y2 = abs_rect.y1 + rtgui_rect_height(*rect); + + /* hw fb pitch */ + fb_pitch = hw->device->byte_per_pixel * hw->device->width; + + /* hardware dc blit */ + if (!rtgui_region_not_empty(&dc->clip) || + dc->clip_sync != hw->owner->clip_sync) + { + /* should re-calculate clip */ + rtgui_region_intersect_rect(&(dc->clip), + &(hw->owner->clip), &abs_rect); + } + + switch (hw->device->byte_per_pixel) + { + case 1: + blit_line = rtgui_blit_line_1; + break; + case 2: + blit_line = rtgui_blit_line_2; + break; + case 3: + blit_line = rtgui_blit_line_4; + break; + + default: + /* can not blit */ + return; + } + + /* blit each clip rect */ + if (dc->clip.data == RT_NULL) + { + int y; + rtgui_color_t* pixel; + rt_uint8_t* fb; + + pixel = (rtgui_color_t*)(dc->pixel + (dc_point->y + dc->clip.extents.y1 - abs_rect.y1) * dc->pitch + + (dc_point->x + dc->clip.extents.x1 - abs_rect.x1) * sizeof(rtgui_color_t)); + fb = hw->device->get_framebuffer() + dc->clip.extents.y1 * fb_pitch + + dc->clip.extents.x1 * hw->device->byte_per_pixel; + + for (y = dc->clip.extents.y1; y < dc->clip.extents.y2; y ++) + { + blit_line(pixel, fb, dc->clip.extents.x2 - dc->clip.extents.x1); + + fb += fb_pitch; + pixel += dc->width; + } + } + else for (index = 0; index < rtgui_region_num_rects(&(dc->clip)); index ++) + { + int y; + rtgui_rect_t* prect; + rtgui_color_t* pixel; + rt_uint8_t* fb; + + prect = ((rtgui_rect_t *)(dc->clip.data + index + 1)); + + pixel = (rtgui_color_t*)(dc->pixel + (dc_point->y + prect->y1 - abs_rect.y1) * dc->pitch + + (dc_point->x + prect->x1 - abs_rect.x1) * sizeof(rtgui_color_t)); + fb = hw->device->get_framebuffer() + prect->y1 * fb_pitch + + prect->x1 * hw->device->byte_per_pixel; + + for (y = prect->y1; y < prect->y2; y ++) + { + blit_line(pixel, fb, prect->x2 - prect->x1); + + fb += fb_pitch; + pixel += dc->width; + } + } + } +} + +static void rtgui_dc_buffer_set_color (struct rtgui_dc* self, rtgui_color_t color) +{ + struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self; + + dc->color = color; +} + +static rtgui_color_t rtgui_dc_buffer_get_color(struct rtgui_dc* self) +{ + struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self; + + return dc->color; +} + +static void rtgui_dc_buffer_set_font(struct rtgui_dc* self, rtgui_font_t* font) +{ + struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self; + + dc->font = font; +} + +static rtgui_font_t* rtgui_dc_buffer_get_font(struct rtgui_dc* self) +{ + struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self; + + return dc->font; +} + +static void rtgui_dc_buffer_set_textalign(struct rtgui_dc* self, rt_int32_t textalign) +{ + struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self; + + dc->align = textalign; +} + +static rt_int32_t rtgui_dc_buffer_get_textalign(struct rtgui_dc* self) +{ + struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self; + + return dc->align; +} + +static rt_bool_t rtgui_dc_buffer_get_visible(struct rtgui_dc* dc) +{ + return RT_TRUE; +} + +static void rtgui_dc_buffer_get_rect(struct rtgui_dc* self, rtgui_rect_t* rect) +{ + struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self; + + rect->x1 = rect->y1 = 0; + + rect->x2 = dc->width; + rect->y2 = dc->height; +} diff --git a/rtgui/common/dc_hw.c b/rtgui/common/dc_hw.c new file mode 100644 index 0000000000000000000000000000000000000000..b5d8be3b6ab27e2f1e647a334fdede7627fd40b0 --- /dev/null +++ b/rtgui/common/dc_hw.c @@ -0,0 +1,436 @@ +/* + * File : dc_hw.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include +#include +#include +#include +#include +#include + +static void rtgui_dc_hw_draw_point(struct rtgui_dc* dc, int x, int y); +static void rtgui_dc_hw_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y); +static void rtgui_dc_hw_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2); +static void rtgui_dc_hw_fill_rect (struct rtgui_dc* dc, rtgui_rect_t* rect); +static void rtgui_dc_hw_blit (struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect); +static void rtgui_dc_hw_set_color (struct rtgui_dc* dc, rtgui_color_t color); +static rtgui_color_t rtgui_dc_hw_get_color (struct rtgui_dc* dc); +static void rtgui_dc_hw_set_font(struct rtgui_dc* dc, rtgui_font_t* font); +static rtgui_font_t* rtgui_dc_hw_get_font(struct rtgui_dc* dc); +static void rtgui_dc_hw_set_textalign(struct rtgui_dc* dc, rt_int32_t textalign); +static rt_int32_t rtgui_dc_hw_get_textalign(struct rtgui_dc* dc); +static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc* dc); +static rt_bool_t rtgui_dc_hw_get_visible(struct rtgui_dc* dc); +static void rtgui_dc_hw_get_rect(struct rtgui_dc* dc, rtgui_rect_t* rect); + +struct rtgui_dc* rtgui_dc_begin_drawing(rtgui_widget_t* owner) +{ + return rtgui_dc_hw_create(owner); +} + +void rtgui_dc_end_drawing(struct rtgui_dc* dc) +{ + if (rtgui_dc_hw_fini(dc) == RT_TRUE) + { + rtgui_free(dc); + } +} + +void rtgui_dc_hw_init(struct rtgui_dc_hw* dc) +{ + if (dc == RT_NULL) return; + + dc->parent.type = RTGUI_DC_HW; + dc->parent.draw_point = rtgui_dc_hw_draw_point; + dc->parent.draw_hline = rtgui_dc_hw_draw_hline; + dc->parent.draw_vline = rtgui_dc_hw_draw_vline; + dc->parent.fill_rect = rtgui_dc_hw_fill_rect ; + dc->parent.blit = rtgui_dc_hw_blit; + + dc->parent.set_color = rtgui_dc_hw_set_color; + dc->parent.get_color = rtgui_dc_hw_get_color; + + dc->parent.set_font = rtgui_dc_hw_set_font; + dc->parent.get_font = rtgui_dc_hw_get_font; + dc->parent.set_textalign = rtgui_dc_hw_set_textalign; + dc->parent.get_textalign = rtgui_dc_hw_get_textalign; + + dc->parent.get_visible= rtgui_dc_hw_get_visible; + dc->parent.get_rect = rtgui_dc_hw_get_rect; + + dc->parent.fini = rtgui_dc_hw_fini; +} + +extern struct rt_mutex cursor_mutex; +#define dc_set_foreground(c) dc->owner->gc.foreground = c +#define dc_set_background(c) dc->owner->gc.background = c +extern void rtgui_mouse_show_cursor(void); +extern void rtgui_mouse_hide_cursor(void); +struct rtgui_dc* rtgui_dc_hw_create(rtgui_widget_t* owner) +{ + struct rtgui_dc_hw* dc; + rtgui_widget_t* widget; + + /* adjudge owner */ + if (owner == RT_NULL || owner->toplevel == RT_NULL) return RT_NULL; + if (!RTGUI_IS_TOPLEVEL(owner->toplevel)) return RT_NULL; + + /* malloc a dc object */ + dc = (struct rtgui_dc_hw*) rtgui_malloc(sizeof(struct rtgui_dc_hw)); + rtgui_dc_hw_init(dc); + dc->owner = owner; + dc->visible = RT_TRUE; + dc->device = rtgui_graphic_driver_get_default(); + + /* set visible */ + widget = owner; + while (widget != RT_NULL) + { + if (RTGUI_WIDGET_IS_HIDE(widget)) + { + dc->visible = RT_FALSE; + break; + } + + widget = widget->parent; + } + + if (RTGUI_IS_WINTITLE(dc->owner->toplevel)) + { + rtgui_toplevel_t* top = RTGUI_TOPLEVEL(dc->owner->toplevel); + top->drawing ++; + + if (top->drawing == 1) + { +#ifdef RTGUI_USING_MOUSE_CURSOR +#ifdef __WIN32__ + rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER); + rt_kprintf("hide cursor\n"); + rtgui_mouse_hide_cursor(); +#else + /* hide cursor */ + rtgui_mouse_hide_cursor(); +#endif +#endif + } + } + else if (RTGUI_IS_WORKBENCH(dc->owner->toplevel) || + RTGUI_IS_WIN(dc->owner->toplevel)) + { + rtgui_toplevel_t* top = RTGUI_TOPLEVEL(dc->owner->toplevel); + top->drawing ++; + + if (top->drawing == 1) + { +#ifdef __WIN32__ +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER); + rt_kprintf("hide cursor\n"); + rtgui_mouse_hide_cursor(); +#endif +#else + /* send draw begin to server */ + struct rtgui_event_update_begin eupdate; + RTGUI_EVENT_UPDATE_BEGIN_INIT(&(eupdate)); + eupdate.rect = RTGUI_WIDGET(top)->extent; + + rtgui_thread_send(top->server, (struct rtgui_event*)&eupdate, sizeof(eupdate)); +#endif + } + } + + return &(dc->parent); +} + +static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc* dc) +{ + struct rtgui_dc_hw* hw = (struct rtgui_dc_hw*)dc; + if (dc == RT_NULL || hw->parent.type != RTGUI_DC_HW) return RT_FALSE; + + if (RTGUI_IS_WINTITLE(hw->owner->toplevel)) + { + /* update title extent */ + rtgui_toplevel_t* top = RTGUI_TOPLEVEL(hw->owner->toplevel); + + top->drawing --; + if (top->drawing == 0) + { +#ifdef __WIN32__ +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_release(&cursor_mutex); + /* show cursor */ + rtgui_mouse_show_cursor(); + rt_kprintf("show cursor\n"); +#endif + /* update screen */ + hw->device->screen_update(&(hw->owner->extent)); +#else +#ifdef RTGUI_USING_MOUSE_CURSOR + /* show cursor */ + rtgui_mouse_show_cursor(); +#endif + + /* update screen */ + hw->device->screen_update(&(hw->owner->extent)); +#endif + } + } + else if (RTGUI_IS_WORKBENCH(hw->owner->toplevel) || + RTGUI_IS_WIN(hw->owner->toplevel)) + { + rtgui_toplevel_t* top = RTGUI_TOPLEVEL(hw->owner->toplevel); + top->drawing --; + + if (top->drawing == 0) + { +#ifdef __WIN32__ +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_release(&cursor_mutex); + /* show cursor */ + rtgui_mouse_show_cursor(); + rt_kprintf("show cursor\n"); +#endif + /* update screen */ + hw->device->screen_update(&(hw->owner->extent)); +#else + /* send to server to end drawing */ + struct rtgui_event_update_end eupdate; + RTGUI_EVENT_UPDATE_END_INIT(&(eupdate)); + eupdate.rect = RTGUI_WIDGET(top)->extent; + + rtgui_thread_send(top->server, (struct rtgui_event*)&eupdate, sizeof(eupdate)); +#endif + } + } + + + return RT_TRUE; +} + +/* + * draw a logic point on device + */ +static void rtgui_dc_hw_draw_point(struct rtgui_dc* self, int x, int y) +{ + struct rtgui_dc_hw* dc; + rtgui_rect_t rect; + + dc = (struct rtgui_dc_hw*)self; + if (dc == RT_NULL || dc->visible != RT_TRUE) return; + + x = x + dc->owner->extent.x1; + y = y + dc->owner->extent.y1; + + if (rtgui_region_contains_point(&(dc->owner->clip), x, y, &rect) == RT_EOK) + { + /* draw this point */ + dc->device->set_pixel(&(dc->owner->gc.foreground), x, y); + } +} + +/* + * draw a logic vertical line on device + */ +static void rtgui_dc_hw_draw_vline(struct rtgui_dc* self, int x, int y1, int y2) +{ + register rt_base_t index; + struct rtgui_dc_hw* dc; + + dc = (struct rtgui_dc_hw*)self; + if (dc == RT_NULL || dc->visible != RT_TRUE) return; + + x = x + dc->owner->extent.x1; + y1 = y1 + dc->owner->extent.y1; + y2 = y2 + dc->owner->extent.y1; + + if (dc->owner->clip.data == RT_NULL) + { + rtgui_rect_t* prect; + + prect = &(dc->owner->clip.extents); + + /* calculate vline intersect */ + if (prect->x1 > x || prect->x2 <= x) return; + if (prect->y2 <= y1 || prect->y1 > y2) return; + + if (prect->y1 > y1) y1 = prect->y1; + if (prect->y2 < y2) y2 = prect->y2; + + /* draw vline */ + dc->device->draw_vline(&(dc->owner->gc.foreground), x, y1, y2); + } + else for (index = 0; index < rtgui_region_num_rects(&(dc->owner->clip)); index ++) + { + rtgui_rect_t* prect; + register rt_base_t draw_y1, draw_y2; + + prect = ((rtgui_rect_t *)(dc->owner->clip.data + index + 1)); + draw_y1 = y1; + draw_y2 = y2; + + /* calculate vline clip */ + if (prect->x1 > x || prect->x2 <= x) continue; + if (prect->y2 <= y1 || prect->y1 > y2) continue; + + if (prect->y1 > y1) draw_y1 = prect->y1; + if (prect->y2 < y2) draw_y2 = prect->y2; + + /* draw vline */ + dc->device->draw_vline(&(dc->owner->gc.foreground), x, draw_y1, draw_y2); + } +} + +/* + * draw a logic horizontal line on device + */ +static void rtgui_dc_hw_draw_hline(struct rtgui_dc* self, int x1, int x2, int y) +{ + register rt_base_t index; + struct rtgui_dc_hw* dc; + + dc = (struct rtgui_dc_hw*)self; + if (dc == RT_NULL || dc->visible != RT_TRUE) return; + + /* convert logic to device */ + x1 = x1 + dc->owner->extent.x1; + x2 = x2 + dc->owner->extent.x1; + y = y + dc->owner->extent.y1; + + if (dc->owner->clip.data == RT_NULL) + { + rtgui_rect_t* prect; + + prect = &(dc->owner->clip.extents); + + /* calculate vline intersect */ + if (prect->y1 > y || prect->y2 <= y ) return; + if (prect->x2 <= x1 || prect->x1 > x2) return; + + if (prect->x1 > x1) x1 = prect->x1; + if (prect->x2 < x2) x2 = prect->x2; + + /* draw hline */ + dc->device->draw_hline(&(dc->owner->gc.foreground), x1, x2, y); + } + else for (index = 0; index < rtgui_region_num_rects(&(dc->owner->clip)); index ++) + { + rtgui_rect_t* prect; + register rt_base_t draw_x1, draw_x2; + + prect = ((rtgui_rect_t *)(dc->owner->clip.data + index + 1)); + draw_x1 = x1; + draw_x2 = x2; + + /* calculate hline clip */ + if (prect->y1 > y || prect->y2 <= y ) continue; + if (prect->x2 <= x1 || prect->x1 > x2) continue; + + if (prect->x1 > x1) draw_x1 = prect->x1; + if (prect->x2 < x2) draw_x2 = prect->x2; + + /* draw hline */ + dc->device->draw_hline(&(dc->owner->gc.foreground), draw_x1, draw_x2, y); + } +} + +static void rtgui_dc_hw_fill_rect (struct rtgui_dc* self, struct rtgui_rect* rect) +{ + rtgui_color_t foreground; + register rt_base_t index; + struct rtgui_dc_hw* dc; + + dc = (struct rtgui_dc_hw*)self; + if (dc == RT_NULL || dc->visible != RT_TRUE) return; + + /* save foreground color */ + foreground = dc->owner->gc.foreground; + + /* set background color as foreground color */ + dc->owner->gc.foreground = dc->owner->gc.background; + + /* fill rect */ + for (index = rect->y1; index < rect->y2; index ++) + { + rtgui_dc_hw_draw_hline(self, rect->x1, rect->x2, index); + } + + /* restore foreground color */ + dc->owner->gc.foreground = foreground; +} + +static void rtgui_dc_hw_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect) +{ + /* not blit in hardware dc */ + return ; +} + +static void rtgui_dc_hw_set_color(struct rtgui_dc* self, rtgui_color_t color) +{ + struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self; + + if (self != RT_NULL) + { + dc->owner->gc.foreground = color; + } +} + +static rtgui_color_t rtgui_dc_hw_get_color(struct rtgui_dc* self) +{ + struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self; + + return self != RT_NULL? dc->owner->gc.foreground : white; +} + +static void rtgui_dc_hw_set_font(struct rtgui_dc* self, rtgui_font_t* font) +{ + struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self; + + if (self != RT_NULL) + { + dc->owner->gc.font = font; + } +} + +static rtgui_font_t* rtgui_dc_hw_get_font(struct rtgui_dc* self) +{ + struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self; + + return self != RT_NULL? dc->owner->gc.font : RT_NULL; +} + +static void rtgui_dc_hw_set_textalign(struct rtgui_dc* self, rt_int32_t textalign) +{ + struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self; + + dc->owner->gc.textalign = textalign; +} + +static rt_int32_t rtgui_dc_hw_get_textalign(struct rtgui_dc* self) +{ + struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self; + + return dc->owner->gc.textalign; +} + +static rt_bool_t rtgui_dc_hw_get_visible(struct rtgui_dc* dc) +{ + return RT_TRUE; +} + +static void rtgui_dc_hw_get_rect(struct rtgui_dc* self, rtgui_rect_t* rect) +{ + struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self; + + rtgui_widget_get_rect(dc->owner, rect); +} diff --git a/rtgui/common/filerw.c b/rtgui/common/filerw.c new file mode 100644 index 0000000000000000000000000000000000000000..7f390d3f1d484dac6a98653264a342a3712bdc22 --- /dev/null +++ b/rtgui/common/filerw.c @@ -0,0 +1,329 @@ +/* + * File : filerw.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ + +#include +#include + +#ifdef RT_USING_STDIO_FILERW +#include + +/* standard file read/write */ +struct rtgui_filerw_stdio +{ + /* inherit from rtgui_filerw */ + struct rtgui_filerw parent; + + FILE* fp; +}; + +static int stdio_seek(struct rtgui_filerw *context, rt_off_t offset, int whence) +{ + struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context; + int stdio_whence[3] = {SEEK_SET, SEEK_CUR, SEEK_END}; + + if (whence < RTGUI_FILE_SEEK_SET || whence > RTGUI_FILE_SEEK_END) + { + return -1; + } + + if (fseek(stdio_filerw->fp, offset, stdio_whence[whence]) == 0) + { + return ftell(stdio_filerw->fp); + } + + return -1; +} + +static int stdio_read(struct rtgui_filerw *context, void *ptr, rt_size_t size, rt_size_t maxnum) +{ + size_t nread; + struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context; + + nread = fread(ptr, size, maxnum, stdio_filerw->fp); + if (nread == 0 && ferror(stdio_filerw->fp)) + { + return -1; + } + + return nread; +} + +static int stdio_write(struct rtgui_filerw *context, const void *ptr, rt_size_t size, rt_size_t num) +{ + size_t nwrote; + struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context; + + nwrote = fwrite(ptr, size, num, stdio_filerw->fp); + + if ( nwrote == 0 && ferror(stdio_filerw->fp) ) + { + return -1; + } + + return nwrote; +} + +int stdio_tell(struct rtgui_filerw* context) +{ + struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context; + + return ftell(stdio_filerw->fp); +} + +int stdio_eof(struct rtgui_filerw* context) +{ + struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context; + + return feof(stdio_filerw->fp); +} + +static int stdio_close(struct rtgui_filerw *context) +{ + struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context; + + if (stdio_filerw) + { + fclose(stdio_filerw->fp); + rtgui_free(stdio_filerw); + + return 0; + } + + return -1; +} +#endif + +/* memory file read/write */ +struct rtgui_filerw_mem +{ + /* inherit from rtgui_filerw */ + struct rtgui_filerw parent; + + rt_uint8_t *mem_base, *mem_position, *mem_end; +}; + +static int mem_seek(struct rtgui_filerw *context, rt_off_t offset, int whence) +{ + rt_uint8_t* newpos; + struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context; + + RT_ASSERT(mem != RT_NULL); + + switch (whence) { + case RTGUI_FILE_SEEK_SET: + newpos = mem->mem_base + offset; + break; + + case RTGUI_FILE_SEEK_CUR: + newpos = mem->mem_position + offset; + break; + + case RTGUI_FILE_SEEK_END: + newpos = mem->mem_end + offset; + break; + + default: + return -1; + } + + if ( newpos < mem->mem_base ) + newpos = mem->mem_base; + + if ( newpos > mem->mem_end ) + newpos = mem->mem_end; + + mem->mem_position = newpos; + return mem->mem_position- mem->mem_base; +} + +static int mem_read(struct rtgui_filerw *context, void *ptr, rt_size_t size, rt_size_t maxnum) +{ + int total_bytes; + int mem_available; + struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context; + + total_bytes = (maxnum * size); + if ( (maxnum <= 0) || (size <= 0) || ((total_bytes / maxnum) != size) ) + { + return -1; + } + + mem_available = mem->mem_end - mem->mem_position; + if (total_bytes > mem_available) + total_bytes = mem_available; + + rt_memcpy(ptr, mem->mem_position, total_bytes); + mem->mem_position += total_bytes; + + return (total_bytes / size); +} + +static int mem_write(struct rtgui_filerw *context, const void *ptr, rt_size_t size, rt_size_t num) +{ + struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context; + + if ((mem->mem_position + (num * size)) > mem->mem_end) + { + num = (mem->mem_end - mem->mem_position)/size; + } + + rt_memcpy(mem->mem_position, ptr, num*size); + mem->mem_position += num*size; + + return num; +} + +static int mem_tell(struct rtgui_filerw* context) +{ + struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context; + + return mem->mem_position - mem->mem_base; +} + +static int mem_eof(struct rtgui_filerw* context) +{ + struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context; + + return mem->mem_position >= mem->mem_end; +} + +static int mem_close(struct rtgui_filerw *context) +{ + struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context; + + if (mem != RT_NULL) + { + rtgui_free(mem); + return 0; + } + + return -1; +} + +rt_uint8_t* rtgui_filerw_mem_getdata(struct rtgui_filerw* context) +{ + struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context; + + /* check whether it's a memory filerw */ + if (mem->parent.read != mem_read) return RT_NULL; + + return mem->mem_base; +} + +/* file read/write public interface */ +#ifdef RT_USING_STDIO_FILERW +struct rtgui_filerw* rtgui_filerw_create_file(const char* filename, const char* mode) +{ + FILE *fp; + struct rtgui_filerw_stdio *rw; + + RT_ASSERT(filename != RT_NULL); + + rw = RT_NULL; + fp = fopen(filename, mode); + + if ( fp != NULL ) + { + rw = (struct rtgui_filerw_stdio*) rtgui_malloc(sizeof(struct rtgui_filerw_stdio)); + if (rw != RT_NULL) + { + rw->parent.seek = stdio_seek; + rw->parent.read = stdio_read; + rw->parent.write = stdio_write; + rw->parent.tell = stdio_tell; + rw->parent.close = stdio_close; + rw->parent.eof = stdio_eof; + + rw->fp = fp; + } + } + + return &(rw->parent); +} +#endif + +struct rtgui_filerw* rtgui_filerw_create_mem(rt_uint8_t* mem, rt_size_t size) +{ + struct rtgui_filerw_mem* rw; + RT_ASSERT(mem != RT_NULL); + + rw = (struct rtgui_filerw_mem*) rtgui_malloc(sizeof(struct rtgui_filerw_mem)); + if (rw != RT_NULL) + { + rw->parent.seek = mem_seek; + rw->parent.read = mem_read; + rw->parent.write = mem_write; + rw->parent.tell = mem_tell; + rw->parent.eof = mem_eof; + rw->parent.close = mem_close; + + rw->mem_base = mem; + rw->mem_position = mem; + rw->mem_end = mem + size; + } + + return &(rw->parent); +} + +int rtgui_filerw_seek(struct rtgui_filerw* context, rt_off_t offset, int whence) +{ + RT_ASSERT(context != RT_NULL); + + return context->seek(context, offset, whence); +} + +int rtgui_filerw_read(struct rtgui_filerw* context, void* buffer, rt_size_t size, rt_size_t count) +{ + RT_ASSERT(context != RT_NULL); + + return context->read(context, buffer, size, count); +} + +int rtgui_filerw_write(struct rtgui_filerw* context, const void* buffer, rt_size_t size, rt_size_t count) +{ + RT_ASSERT(context != RT_NULL); + + return context->write(context, buffer, size, count); +} + +int rtgui_filerw_eof (struct rtgui_filerw* context) +{ + RT_ASSERT(context != RT_NULL); + + return context->eof(context); +} + +int rtgui_filerw_tell(struct rtgui_filerw* context) +{ + RT_ASSERT(context != RT_NULL); + + return context->tell(context); +} + +int rtgui_filerw_close(struct rtgui_filerw* context) +{ + int result; + + RT_ASSERT(context != RT_NULL); + + /* close context */ + result = context->close(context); + if (result != 0) + { + /* close file failed */ + return -1; + } + + return 0; +} diff --git a/rtgui/common/font.c b/rtgui/common/font.c new file mode 100644 index 0000000000000000000000000000000000000000..65a64705ccca095cb2a8fed1336b758816220fb3 --- /dev/null +++ b/rtgui/common/font.c @@ -0,0 +1,205 @@ +/* + * File : font.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include + +static rtgui_list_t _rtgui_font_list; +static struct rtgui_font* rtgui_default_font; + +extern struct rtgui_font rtgui_font_asc16; +extern struct rtgui_font rtgui_font_asc12; +#ifdef RTGUI_USING_FONTHZ +extern struct rtgui_font rtgui_font_hz16; +extern struct rtgui_font rtgui_font_hz12; +#endif + +void rtgui_font_system_init() +{ + rtgui_list_init(&(_rtgui_font_list)); + + /* set default font to NULL */ + rtgui_default_font = RT_NULL; + +#ifdef RTGUI_USING_FONT16 + rtgui_font_system_add_font(&rtgui_font_asc16); +#ifdef RTGUI_USING_FONTHZ + rtgui_font_system_add_font(&rtgui_font_hz16); +#endif +#endif + rtgui_font_system_add_font(&rtgui_font_asc12); +#ifdef RTGUI_USING_FONTHZ + rtgui_font_system_add_font(&rtgui_font_hz12); +#endif + + rtgui_font_set_defaut(&rtgui_font_asc12); +} + +void rtgui_font_system_add_font(struct rtgui_font* font) +{ + rtgui_list_init(&(font->list)); + rtgui_list_append(&_rtgui_font_list, &(font->list)); +} + +void rtgui_font_system_remove_font(struct rtgui_font* font) +{ + rtgui_list_remove(&_rtgui_font_list, &(font->list)); +} + +struct rtgui_font* rtgui_font_default() +{ + return rtgui_default_font; +} + +void rtgui_font_set_defaut(struct rtgui_font* font) +{ + rtgui_default_font = font; +} + +struct rtgui_font* rtgui_font_refer(const rt_uint8_t* family, rt_uint16_t height) +{ + /* search font */ + struct rtgui_list_node* node; + struct rtgui_font* font; + + rtgui_list_foreach(node, &_rtgui_font_list) + { + font = rtgui_list_entry(node, struct rtgui_font, list); + if ((rt_strncmp((const char*)font->family, (const char*)family, RTGUI_NAME_MAX) == 0) && + font->height == height) + { + font->refer_count ++; + return font; + } + } + + return RT_NULL; +} + +void rtgui_font_derefer(struct rtgui_font* font) +{ + RT_ASSERT(font != RT_NULL); + + font->refer_count --; + + /* no refer, remove font */ + if (font->refer_count == 0) + { + rtgui_font_system_remove_font(font); + } +} + +/* draw a text */ +void rtgui_font_draw(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect) +{ + RT_ASSERT(font != RT_NULL); + + if (font->engine != RT_NULL && + font->engine->font_draw_text != RT_NULL) + { + font->engine->font_draw_text(font, dc, text, len, rect); + } +} + +int rtgui_font_get_string_width(struct rtgui_font* font, const rt_uint8_t* text) +{ + rtgui_rect_t rect; + + /* get metrics */ + rtgui_font_get_metrics(font, text, &rect); + + return rect.x2 - rect.x1; +} + +void rtgui_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, rtgui_rect_t* rect) +{ + RT_ASSERT(font != RT_NULL); + + if (font->engine != RT_NULL && + font->engine->font_get_metrics != RT_NULL) + { + font->engine->font_get_metrics(font, text, rect); + } + else + { + /* no font engine found, set rect to zero */ + rt_memset(rect, 0, sizeof(rtgui_rect_t)); + } +} + +static void rtgui_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect); +static void rtgui_bitmap_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, rtgui_rect_t* rect); +struct rtgui_font_engine bmp_font_engine = +{ + RT_NULL, + RT_NULL, + rtgui_bitmap_font_draw_text, + rtgui_bitmap_font_get_metrics +}; + +void rtgui_bitmap_font_draw_char(struct rtgui_font_bitmap* font, struct rtgui_dc* dc, const char ch, + rtgui_rect_t* rect) +{ + const rt_uint8_t* font_ptr = font->bmp + ch * font->height; + rt_uint16_t x, y, w, h; + register rt_base_t i, j; + + x = rect->x1; + y = rect->y1; + + /* check first and last char */ + if (ch < font->first_char || ch > font->last_char) return; + + w = (font->width + x > rect->x2)? rect->x2 - rect->x1 : font->width; + h = (font->height + y > rect->y2)? rect->y2 - rect->y1 : font->height; + + for (i = 0; i < h; i ++ ) + { + for (j = 0; j < w; j ++) + { + if ( ((font_ptr[i] >> (7-j)) & 0x01) != 0) + { + /* draw a pixel */ + rtgui_dc_draw_point(dc, j + x, i + y); + } + } + } +} + +static void rtgui_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect) +{ + struct rtgui_font_bitmap* bmp_font = (struct rtgui_font_bitmap*)(font->data); + + RT_ASSERT(bmp_font != RT_NULL); + + while (len-- && rect->x1 < rect->x2) + { + rtgui_bitmap_font_draw_char(bmp_font, dc, *text, rect); + + /* move x to next character */ + rect->x1 += bmp_font->width; + text ++; + } +} + +static void rtgui_bitmap_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, rtgui_rect_t* rect) +{ + struct rtgui_font_bitmap* bmp_font = (struct rtgui_font_bitmap*)(font->data); + + RT_ASSERT(bmp_font != RT_NULL); + + /* set metrics rect */ + rect->x1 = rect->y1 = 0; + rect->x2 = bmp_font->width * (rt_int16_t)rt_strlen((const char*)text); + rect->y2 = bmp_font->height; +} diff --git a/rtgui/common/image.c b/rtgui/common/image.c new file mode 100644 index 0000000000000000000000000000000000000000..5fd386049eecb15eb011510d0c60d96fab013c10 --- /dev/null +++ b/rtgui/common/image.c @@ -0,0 +1,192 @@ +/* + * File : image.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include + +#include +#include + +#include + +#ifdef RTGUI_IMAGE_BMP +#include +#endif +#ifdef RTGUI_IMAGE_JPEG +#include +#endif +#ifdef RTGUI_IMAGE_PNG +#include +#endif + +static rtgui_list_t _rtgui_system_image_list = {RT_NULL}; + +/* init rtgui image system */ +void rtgui_system_image_init(void) +{ + /* always support XPM image */ + rtgui_image_xpm_init(); + +#ifdef RTGUI_IMAGE_BMP + rtgui_image_bmp_init(); +#endif + +#ifdef RTGUI_IMAGE_JPEG + rtgui_image_jpeg_init(); +#endif + +#ifdef RTGUI_IMAGE_PNG + rtgui_image_png_init(); +#endif +} + +static struct rtgui_image_engine* rtgui_image_get_engine(const char* type) +{ + struct rtgui_list_node *node; + struct rtgui_image_engine *engine; + + rtgui_list_foreach(node, &_rtgui_system_image_list) + { + engine = rtgui_list_entry(node, struct rtgui_image_engine, list); + + if (strncasecmp(engine->name, type, strlen(engine->name)) ==0) + return engine; + } + + return RT_NULL; +} + +struct rtgui_image* rtgui_image_create_from_file(const char* type, const char* filename, rt_bool_t load) +{ + struct rtgui_filerw* filerw; + struct rtgui_image_engine* engine; + struct rtgui_image* image = RT_NULL; + + /* create filerw context */ + filerw = rtgui_filerw_create_file(filename, "rb"); + if (filerw == RT_NULL) return RT_NULL; + + /* get image engine */ + engine = rtgui_image_get_engine(type); + if (engine == RT_NULL) + { + /* close filerw context */ + rtgui_filerw_close(filerw); + return RT_NULL; + } + + if (engine->image_check(filerw) == RT_TRUE) + { + image = (struct rtgui_image*) rtgui_malloc(sizeof(struct rtgui_image)); + if (image == RT_NULL) + { + /* close filerw context */ + rtgui_filerw_close(filerw); + return RT_NULL; + } + + if (engine->image_load(image, filerw, load) != RT_TRUE) + { + /* close filerw context */ + rtgui_filerw_close(filerw); + return RT_NULL; + } + + /* set image engine */ + image->engine = engine; + } + else + { + rtgui_filerw_close(filerw); + } + + return image; +} + +struct rtgui_image* rtgui_image_create_from_mem(const char* type, const rt_uint8_t* data, rt_size_t length) +{ + struct rtgui_filerw* filerw; + struct rtgui_image_engine* engine; + struct rtgui_image* image = RT_NULL; + + /* create filerw context */ + filerw = rtgui_filerw_create_mem((rt_uint8_t*)data, length); + if (filerw == RT_NULL) return RT_NULL; + + /* get image engine */ + engine = rtgui_image_get_engine(type); + if (engine == RT_NULL) + { + /* close filerw context */ + rtgui_filerw_close(filerw); + return RT_NULL; + } + + if (engine->image_check(filerw) == RT_TRUE) + { + image = (struct rtgui_image*) rtgui_malloc(sizeof(struct rtgui_image)); + if (image == RT_NULL) + { + /* close filerw context */ + rtgui_filerw_close(filerw); + return RT_NULL; + } + + if (engine->image_load(image, filerw, RT_TRUE) != RT_TRUE) + { + /* close filerw context */ + rtgui_filerw_close(filerw); + return RT_NULL; + } + + /* set image engine */ + image->engine = engine; + } + else + { + rtgui_filerw_close(filerw); + } + + return image; +} + +void rtgui_image_destroy(struct rtgui_image* image) +{ + RT_ASSERT(image != RT_NULL); + + image->engine->image_unload(image); + rtgui_free(image); +} + +/* register an image engine */ +void rtgui_image_register_engine(struct rtgui_image_engine* engine) +{ + RT_ASSERT(engine!= RT_NULL); + + rtgui_list_append(&_rtgui_system_image_list, &(engine->list)); +} + +void rtgui_image_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect) +{ + RT_ASSERT(dc != RT_NULL); + RT_ASSERT(rect != RT_NULL); + + if (rtgui_dc_get_visible(dc) != RT_TRUE) return; + + if (image != RT_NULL && image->engine != RT_NULL) + { + /* use image engine to blit */ + image->engine->image_blit(image, dc, rect); + } +} + diff --git a/rtgui/common/image_xpm.c b/rtgui/common/image_xpm.c new file mode 100644 index 0000000000000000000000000000000000000000..bb7ce057f5e106ca803bb2e824c21ede9f83572a --- /dev/null +++ b/rtgui/common/image_xpm.c @@ -0,0 +1,617 @@ +/* + * File : image_xpm.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include + +#include +#include +#include + +#define XPM_MAGIC_LEN 9 + +static rt_bool_t rtgui_image_xpm_check(struct rtgui_filerw * file); +static rt_bool_t rtgui_image_xpm_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load); +static void rtgui_image_xpm_unload(struct rtgui_image* image); +static void rtgui_image_xpm_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect); + +struct rtgui_image_engine rtgui_image_xpm_engine = +{ + "xpm", + {RT_NULL}, + rtgui_image_xpm_check, + rtgui_image_xpm_load, + rtgui_image_xpm_unload, + rtgui_image_xpm_blit +}; + +struct rgb_item +{ + char *name; + int r; + int g; + int b; +}; + +const struct rgb_item rgbRecord[234] = { + {"AliceBlue", 240, 248, 255}, + {"AntiqueWhite", 250, 235, 215}, + {"Aquamarine", 50, 191, 193}, + {"Azure", 240, 255, 255}, + {"Beige", 245, 245, 220}, + {"Bisque", 255, 228, 196}, + {"Black", 0, 0, 0}, + {"BlanchedAlmond", 255, 235, 205}, + {"Blue", 0, 0, 255}, + {"BlueViolet", 138, 43, 226}, + {"Brown", 165, 42, 42}, + {"burlywood", 222, 184, 135}, + {"CadetBlue", 95, 146, 158}, + {"chartreuse", 127, 255, 0}, + {"chocolate", 210, 105, 30}, + {"Coral", 255, 114, 86}, + {"CornflowerBlue", 34, 34, 152}, + {"cornsilk", 255, 248, 220}, + {"Cyan", 0, 255, 255}, + {"DarkGoldenrod", 184, 134, 11}, + {"DarkGreen", 0, 86, 45}, + {"DarkKhaki", 189, 183, 107}, + {"DarkOliveGreen", 85, 86, 47}, + {"DarkOrange", 255, 140, 0}, + {"DarkOrchid", 139, 32, 139}, + {"DarkSalmon", 233, 150, 122}, + {"DarkSeaGreen", 143, 188, 143}, + {"DarkSlateBlue", 56, 75, 102}, + {"DarkSlateGray", 47, 79, 79}, + {"DarkTurquoise", 0, 166, 166}, + {"DarkViolet", 148, 0, 211}, + {"DeepPink", 255, 20, 147}, + {"DeepSkyBlue", 0, 191, 255}, + {"DimGray", 84, 84, 84}, + {"DodgerBlue", 30, 144, 255}, + {"Firebrick", 142, 35, 35}, + {"FloralWhite", 255, 250, 240}, + {"ForestGreen", 80, 159, 105}, + {"gainsboro", 220, 220, 220}, + {"GhostWhite", 248, 248, 255}, + {"Gold", 218, 170, 0}, + {"Goldenrod", 239, 223, 132}, + {"Gray", 126, 126, 126}, + {"Gray0", 0, 0, 0}, + {"Gray1", 3, 3, 3}, + {"Gray10", 26, 26, 26}, + {"Gray100", 255, 255, 255}, + {"Gray11", 28, 28, 28}, + {"Gray12", 31, 31, 31}, + {"Gray13", 33, 33, 33}, + {"Gray14", 36, 36, 36}, + {"Gray15", 38, 38, 38}, + {"Gray16", 41, 41, 41}, + {"Gray17", 43, 43, 43}, + {"Gray18", 46, 46, 46}, + {"Gray19", 48, 48, 48}, + {"Gray2", 5, 5, 5}, + {"Gray20", 51, 51, 51}, + {"Gray21", 54, 54, 54}, + {"Gray22", 56, 56, 56}, + {"Gray23", 59, 59, 59}, + {"Gray24", 61, 61, 61}, + {"Gray25", 64, 64, 64}, + {"Gray26", 66, 66, 66}, + {"Gray27", 69, 69, 69}, + {"Gray28", 71, 71, 71}, + {"Gray29", 74, 74, 74}, + {"Gray3", 8, 8, 8}, + {"Gray30", 77, 77, 77}, + {"Gray31", 79, 79, 79}, + {"Gray32", 82, 82, 82}, + {"Gray33", 84, 84, 84}, + {"Gray34", 87, 87, 87}, + {"Gray35", 89, 89, 89}, + {"Gray36", 92, 92, 92}, + {"Gray37", 94, 94, 94}, + {"Gray38", 97, 97, 97}, + {"Gray39", 99, 99, 99}, + {"Gray4", 10, 10, 10}, + {"Gray40", 102, 102, 102}, + {"Gray41", 105, 105, 105}, + {"Gray42", 107, 107, 107}, + {"Gray43", 110, 110, 110}, + {"Gray44", 112, 112, 112}, + {"Gray45", 115, 115, 115}, + {"Gray46", 117, 117, 117}, + {"Gray47", 120, 120, 120}, + {"Gray48", 122, 122, 122}, + {"Gray49", 125, 125, 125}, + {"Gray5", 13, 13, 13}, + {"Gray50", 127, 127, 127}, + {"Gray51", 130, 130, 130}, + {"Gray52", 133, 133, 133}, + {"Gray53", 135, 135, 135}, + {"Gray54", 138, 138, 138}, + {"Gray55", 140, 140, 140}, + {"Gray56", 143, 143, 143}, + {"Gray57", 145, 145, 145}, + {"Gray58", 148, 148, 148}, + {"Gray59", 150, 150, 150}, + {"Gray6", 15, 15, 15}, + {"Gray60", 153, 153, 153}, + {"Gray61", 156, 156, 156}, + {"Gray62", 158, 158, 158}, + {"Gray63", 161, 161, 161}, + {"Gray64", 163, 163, 163}, + {"Gray65", 166, 166, 166}, + {"Gray66", 168, 168, 168}, + {"Gray67", 171, 171, 171}, + {"Gray68", 173, 173, 173}, + {"Gray69", 176, 176, 176}, + {"Gray7", 18, 18, 18}, + {"Gray70", 179, 179, 179}, + {"Gray71", 181, 181, 181}, + {"Gray72", 184, 184, 184}, + {"Gray73", 186, 186, 186}, + {"Gray74", 189, 189, 189}, + {"Gray75", 191, 191, 191}, + {"Gray76", 194, 194, 194}, + {"Gray77", 196, 196, 196}, + {"Gray78", 199, 199, 199}, + {"Gray79", 201, 201, 201}, + {"Gray8", 20, 20, 20}, + {"Gray80", 204, 204, 204}, + {"Gray81", 207, 207, 207}, + {"Gray82", 209, 209, 209}, + {"Gray83", 212, 212, 212}, + {"Gray84", 214, 214, 214}, + {"Gray85", 217, 217, 217}, + {"Gray86", 219, 219, 219}, + {"Gray87", 222, 222, 222}, + {"Gray88", 224, 224, 224}, + {"Gray89", 227, 227, 227}, + {"Gray9", 23, 23, 23}, + {"Gray90", 229, 229, 229}, + {"Gray91", 232, 232, 232}, + {"Gray92", 235, 235, 235}, + {"Gray93", 237, 237, 237}, + {"Gray94", 240, 240, 240}, + {"Gray95", 242, 242, 242}, + {"Gray96", 245, 245, 245}, + {"Gray97", 247, 247, 247}, + {"Gray98", 250, 250, 250}, + {"Gray99", 252, 252, 252}, + {"Green", 0, 255, 0}, + {"GreenYellow", 173, 255, 47}, + {"honeydew", 240, 255, 240}, + {"HotPink", 255, 105, 180}, + {"IndianRed", 107, 57, 57}, + {"ivory", 255, 255, 240}, + {"Khaki", 179, 179, 126}, + {"lavender", 230, 230, 250}, + {"LavenderBlush", 255, 240, 245}, + {"LawnGreen", 124, 252, 0}, + {"LemonChiffon", 255, 250, 205}, + {"LightBlue", 176, 226, 255}, + {"LightCoral", 240, 128, 128}, + {"LightCyan", 224, 255, 255}, + {"LightGoldenrod", 238, 221, 130}, + {"LightGoldenrodYellow", 250, 250, 210}, + {"LightGray", 168, 168, 168}, + {"LightPink", 255, 182, 193}, + {"LightSalmon", 255, 160, 122}, + {"LightSeaGreen", 32, 178, 170}, + {"LightSkyBlue", 135, 206, 250}, + {"LightSlateBlue", 132, 112, 255}, + {"LightSlateGray", 119, 136, 153}, + {"LightSteelBlue", 124, 152, 211}, + {"LightYellow", 255, 255, 224}, + {"LimeGreen", 0, 175, 20}, + {"linen", 250, 240, 230}, + {"Magenta", 255, 0, 255}, + {"Maroon", 143, 0, 82}, + {"MediumAquamarine", 0, 147, 143}, + {"MediumBlue", 50, 50, 204}, + {"MediumForestGreen", 50, 129, 75}, + {"MediumGoldenrod", 209, 193, 102}, + {"MediumOrchid", 189, 82, 189}, + {"MediumPurple", 147, 112, 219}, + {"MediumSeaGreen", 52, 119, 102}, + {"MediumSlateBlue", 106, 106, 141}, + {"MediumSpringGreen", 35, 142, 35}, + {"MediumTurquoise", 0, 210, 210}, + {"MediumVioletRed", 213, 32, 121}, + {"MidnightBlue", 47, 47, 100}, + {"MintCream", 245, 255, 250}, + {"MistyRose", 255, 228, 225}, + {"moccasin", 255, 228, 181}, + {"NavajoWhite", 255, 222, 173}, + {"Navy", 35, 35, 117}, + {"NavyBlue", 35, 35, 117}, + {"OldLace", 253, 245, 230}, + {"OliveDrab", 107, 142, 35}, + {"Orange", 255, 135, 0}, + {"OrangeRed", 255, 69, 0}, + {"Orchid", 239, 132, 239}, + {"PaleGoldenrod", 238, 232, 170}, + {"PaleGreen", 115, 222, 120}, + {"PaleTurquoise", 175, 238, 238}, + {"PaleVioletRed", 219, 112, 147}, + {"PapayaWhip", 255, 239, 213}, + {"PeachPuff", 255, 218, 185}, + {"peru", 205, 133, 63}, + {"Pink", 255, 181, 197}, + {"Plum", 197, 72, 155}, + {"PowderBlue", 176, 224, 230}, + {"purple", 160, 32, 240}, + {"Red", 255, 0, 0}, + {"RosyBrown", 188, 143, 143}, + {"RoyalBlue", 65, 105, 225}, + {"SaddleBrown", 139, 69, 19}, + {"Salmon", 233, 150, 122}, + {"SandyBrown", 244, 164, 96}, + {"SeaGreen", 82, 149, 132}, + {"seashell", 255, 245, 238}, + {"Sienna", 150, 82, 45}, + {"SkyBlue", 114, 159, 255}, + {"SlateBlue", 126, 136, 171}, + {"SlateGray", 112, 128, 144}, + {"snow", 255, 250, 250}, + {"SpringGreen", 65, 172, 65}, + {"SteelBlue", 84, 112, 170}, + {"Tan", 222, 184, 135}, + {"Thistle", 216, 191, 216}, + {"tomato", 255, 99, 71}, + {"Transparent", 0, 0, 1}, + {"Turquoise", 25, 204, 223}, + {"Violet", 156, 62, 206}, + {"VioletRed", 243, 62, 150}, + {"Wheat", 245, 222, 179}, + {"White", 255, 255, 255}, + {"WhiteSmoke", 245, 245, 245}, + {"Yellow", 255, 255, 0}, + {"YellowGreen", 50, 216, 56} +}; +/* Hash table to look up colors from pixel strings */ +#define STARTING_HASH_SIZE 256 + +struct hash_entry +{ + char key[10]; + rtgui_color_t color; + struct hash_entry *next; +}; + +struct color_hash +{ + struct hash_entry **table; + struct hash_entry *entries; /* array of all entries */ + struct hash_entry *next_free; + + int size; + int maxnum; +}; + +static int hash_key(const char *key, int cpp, int size) +{ + int hash; + + hash = 0; + while ( cpp-- > 0 ) + { + hash = hash * 33 + *key++; + } + return hash & (size - 1); +} + +static struct color_hash *create_colorhash(int maxnum) +{ + int bytes, s; + struct color_hash *hash; + + /* we know how many entries we need, so we can allocate + everything here */ + hash = rtgui_malloc(sizeof *hash); + if(!hash) return RT_NULL; + + /* use power-of-2 sized hash table for decoding speed */ + for(s = STARTING_HASH_SIZE; s < maxnum; s <<= 1) ; + hash->size = s; + hash->maxnum = maxnum; + bytes = hash->size * sizeof(struct hash_entry **); + hash->entries = RT_NULL; /* in case rt_malloc fails */ + hash->table = rtgui_malloc(bytes); + if(!hash->table) return RT_NULL; + + rt_memset(hash->table, 0, bytes); + hash->entries = rtgui_malloc(maxnum * sizeof(struct hash_entry)); + if(!hash->entries) return RT_NULL; + + hash->next_free = hash->entries; + return hash; +} + +static int add_colorhash(struct color_hash *hash, + char *key, int cpp, rtgui_color_t *color) +{ + int index = hash_key(key, cpp, hash->size); + struct hash_entry *e = hash->next_free++; + + e->color = *color; + rt_memset(e->key, 0, sizeof(e->key)); + rt_strncpy(e->key, key, cpp); + e->next = hash->table[index]; + hash->table[index] = e; + + return 1; +} + +static void get_colorhash(struct color_hash *hash, const char *key, int cpp, rtgui_color_t* c) +{ + struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)]; + while(entry) + { + if(rt_memcmp(key, entry->key, cpp) == 0) + { + *c = entry->color; + + return; + } + + entry = entry->next; + } + + return ; /* garbage in - garbage out */ +} + +static void free_colorhash(struct color_hash *hash) +{ + if(hash && hash->table) + { + rtgui_free(hash->table); + rtgui_free(hash->entries); + rtgui_free(hash); + } +} + +#if defined(_MSC_VER) || defined(__CC_ARM) +int strcasecmp( const char* s1, const char* s2 ) +{ + register unsigned int x2; + register unsigned int x1; + + while (1) { + x2 = *s2 - 'A'; if (x2 < 26u) x2 += 32; + x1 = *s1 - 'A'; if (x1 < 26u) x1 += 32; + s1++; s2++; + if (x2 != x1) + break; + if (x1 == (unsigned int)-'A') + break; + } + + return x1 - x2; +} +#endif + +static int hex2int (char *str) +{ + int i = 0; + int r = 0; + + for (i = 0; i < 2; i++) + { + if (str[i] >= '0' && str[i] <= '9') r += str[i] - '0'; + else if (str[i] >= 'a' && str[i] <= 'f') r += str[i] - 'a' + 10; + else if (str[i] >= 'A' && str[i] <= 'F') r += str[i] - 'A' + 10; + + if (!i) r *= 16; + } + + return r; +} + +void rtgui_image_xpm_init() +{ + /* register xpm engine */ + rtgui_image_register_engine(&rtgui_image_xpm_engine); +} + +static rt_bool_t rtgui_image_xpm_check(struct rtgui_filerw* file) +{ +#if 0 + rt_uint8_t buffer[XPM_MAGIC_LEN]; + rt_size_t start; + rt_bool_t result; + + result = RT_FALSE; + + start = rtgui_filerw_tell(file); + + /* seek to the begining of file */ + if (start != 0) rtgui_filerw_seek(file, 0, SEEK_SET); + rtgui_filerw_read(file, &buffer[0], XPM_MAGIC_LEN, 1); + + if (rt_memcmp(buffer, "/* XPM */", (rt_ubase_t)XPM_MAGIC_LEN) == 0) + result = RT_TRUE; + + rtgui_filerw_seek(file, start, SEEK_SET); + + return result; +#else + /* we can not check image type for memory file */ + return RT_TRUE; +#endif +} + +static rt_bool_t rtgui_image_xpm_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load) +{ + const char **xpm; + const char *buf; + const char *buf_tmp; + + int w, h; + int colors = 0; + int colors_pp = 0; + + int i, j; + + /* color hash table */ + struct color_hash *colors_table = RT_NULL; + + if (image == RT_NULL) return RT_FALSE; + + xpm = (const char **)rtgui_filerw_mem_getdata(file); + if (xpm == RT_NULL) return RT_FALSE; + + /* set image engine */ + image->engine = &rtgui_image_xpm_engine; + + /* parse xpm image */ + sscanf(xpm[0], "%d %d %d %d", &w, &h, &colors, &colors_pp); + image->w = w; + image->h = h; + + /* build color table */ + colors_table = create_colorhash(colors); + if (!colors_table) + { + return RT_FALSE; + } + + for (i = 0; i < colors; i++) + { + char color_name[10]; + rtgui_color_t c = 0; + + buf = xpm[i + 1]; + + for (j = 0; j < colors_pp; j++) + { + color_name[j] = buf[j]; + } + color_name[j] = '\0'; + + /* build rtgui_color */ + if ((buf_tmp = strstr(buf, "c #")) != RT_NULL) + { + char color_hex[10]; + + /* hexadecimal color value */ + sscanf(buf_tmp, "c #%s", color_hex); + + c = RTGUI_ARGB(0, hex2int(color_hex), + hex2int(color_hex + 2), + hex2int(color_hex + 4)); + } + else if ((buf_tmp = strstr(buf, "c ")) != RT_NULL) + { + int k; + + /* color name */ + char rgbname[30]; + + sscanf(buf_tmp, "c %s", rgbname); + + if (strcasecmp(rgbname, "None") == 0) + { + goto color_none; + } + + for (k = 0; k < 234; k++) + { + if (strcasecmp(rgbname, rgbRecord[k].name) == 0) + { + c = RTGUI_ARGB(0, rgbRecord[k].r, + rgbRecord[k].g, + rgbRecord[k].b); + break; + } + } + } + else + { +color_none: + c = RTGUI_RGB(0, 0, 0); + } + + /* add to color hash table */ + add_colorhash(colors_table, color_name, colors_pp, &c); + } + + /* build rgb pixel data */ + image->data = (rt_uint8_t*) rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t)); + memset(image->data, 0, image->w * image->h * sizeof(rtgui_color_t)); + + { + rtgui_color_t *ptr = (rtgui_color_t*) image->data; + + for (h = 0; h < image->h; h++) + { + buf = xpm[colors + 1 + h]; + for (w = 0; w < image->w; w++, buf += colors_pp) + { + get_colorhash(colors_table, buf, colors_pp, ptr); + + ptr ++; + } + } + } + + free_colorhash(colors_table); + + return RT_TRUE; +} + +static void rtgui_image_xpm_unload(struct rtgui_image* image) +{ + if (image != RT_NULL) + { + /* release data */ + rtgui_free(image->data); + image->data = RT_NULL; + } +} + +static void rtgui_image_xpm_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect) +{ + rt_uint16_t x, y; + rtgui_color_t* ptr; + rtgui_color_t foreground; + + RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL); + RT_ASSERT(image->data != RT_NULL); + + ptr = (rtgui_color_t*) image->data; + + /* save foreground color */ + foreground = rtgui_dc_get_color(dc); + + /* draw each point within dc */ + for (y = 0; y < image->h; y ++) + { + for (x = 0; x < image->w; x++) + { + /* not alpha */ + if ((*ptr >> 24) != 255) + { + rtgui_dc_set_color(dc, *ptr); + rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1); + } + + /* move to next color buffer */ + ptr ++; + } + } + + /* restore foreground */ + rtgui_dc_set_color(dc, foreground); +} + diff --git a/rtgui/common/region.c b/rtgui/common/region.c new file mode 100644 index 0000000000000000000000000000000000000000..e983f59ac660192f442e4551a48be6c0f0d74208 --- /dev/null +++ b/rtgui/common/region.c @@ -0,0 +1,2228 @@ +/* + * File : region.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include + +/* #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(®1->extents, ®2->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(®2->extents, ®1->extents)) + { + return rtgui_region_copy(newReg, reg1); + } + else if (!reg1->data && SUBSUMES(®1->extents, ®2->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, ®ion); +} + +#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, ®ion); +} + +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(®1->extents, ®2->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(®2->extents, ®1->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(y1x2 <= 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(x1x1); + 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(x1x2); + 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(®M->extents, ®S->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, ®ion); +} + +/*====================================================================== + * 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, ®1->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(®ion->extents, prect)) + return(RTGUI_REGION_OUT); + + if (numRects == 1) + { + /* We know that it must be rgnIN or rgnPART */ + if (SUBSUMES(®ion->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(®ion->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(®ion->extents); +} + +#define ExchangeSpans(a, b) \ +{ \ + rtgui_point_t tpt; \ + int tw; \ + \ + tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \ + tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ +} + +/* ||| I should apply the merge sort code to rectangle sorting above, and see + if mapping time can be improved. But right now I've been at work 12 hours, + so forget it. +*/ + +static void QuickSortSpans( + rtgui_point_t spans[], + int widths[], + int numSpans) +{ + int y; + int i, j, m; + rtgui_point_t *r; + + /* Always called with numSpans > 1 */ + /* Sorts only by y, doesn't bother to sort by x */ + + do + { + if (numSpans < 9) + { + /* Do insertion sort */ + int yprev; + + yprev = spans[0].y; + i = 1; + do + { /* while i != numSpans */ + y = spans[i].y; + if (yprev > y) + { + /* spans[i] is out of order. Move into proper location. */ + rtgui_point_t tpt; + int tw, k; + + for (j = 0; y >= spans[j].y; j++) + {} + tpt = spans[i]; + tw = widths[i]; + for (k = i; k != j; k--) + { + spans[k] = spans[k-1]; + widths[k] = widths[k-1]; + } + spans[j] = tpt; + widths[j] = tw; + y = spans[i].y; + } /* if out of order */ + yprev = y; + i++; + } + while (i != numSpans); + return; + } + + /* Choose partition element, stick in location 0 */ + m = numSpans / 2; + if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); + if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1); + if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); + y = spans[0].y; + + /* Partition array */ + i = 0; + j = numSpans; + do + { + r = &(spans[i]); + do + { + r++; + i++; + } + while (i != numSpans && r->y < y); + r = &(spans[j]); + do + { + r--; + j--; + } + while (y < r->y); + if (i < j) + ExchangeSpans(i, j); + } + while (i < j); + + /* Move partition element back to middle */ + ExchangeSpans(0, j); + + /* Recurse */ + if (numSpans-j-1 > 1) + QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1); + numSpans = j; + } + while (numSpans > 1); +} + +void rtgui_region_dump(rtgui_region_t* region) +{ + int num; + int i; + rtgui_rect_t * rects; + + num = PIXREGION_NUM_RECTS(region); + rects = PIXREGION_RECTS(region); + rt_kprintf("extents: (%d,%d) (%d,%d)\n", + region->extents.x1, region->extents.y1, + region->extents.x2, region->extents.y2); + + for (i = 0; i < num; i++) + { + rt_kprintf("box[%d]: (%d,%d) (%d,%d)\n", i, + rects[i].x1, rects[i].y1, + rects[i].x2, rects[i].y2); + } +} + +void rtgui_rect_moveto(rtgui_rect_t *rect, int x, int y) +{ + rect->x1 += x; + rect->x2 += x; + + rect->y1 += y; + rect->y2 += y; +} + +void rtgui_rect_moveto_align(rtgui_rect_t *rect, rtgui_rect_t *to, int align) +{ + int dw, dh; + dw = 0; + dh = 0; + + /* get delta width and height */ + dw = rtgui_rect_width(*rect) - rtgui_rect_width(*to); + dh = rtgui_rect_height(*rect) - rtgui_rect_height(*to); + if (dw < 0) dw = 0; + if (dh < 0) dh = 0; + + /* move to insider of rect */ + rtgui_rect_moveto(to, rect->x1, rect->y1); + + /* limited the destination rect to source rect */ + if (dw == 0) to->x2 = rect->x2; + if (dh == 0) to->y2 = rect->y2; + + /* align to right */ + if (align & RTGUI_ALIGN_RIGHT) + { + to->x1 += dw; + to->x2 += dw; + } + + /* align to bottom */ + if (align & RTGUI_ALIGN_BOTTOM) + { + to->y1 += dh; + to->y2 += dh; + } + + /* align to center horizontal */ + if (align & RTGUI_ALIGN_CENTER_HORIZONTAL) + { + to->x1 += dw >> 1; + to->x2 += dw >> 1; + } + + /* align to center vertical */ + if (align & RTGUI_ALIGN_CENTER_VERTICAL) + { + to->y1 += dh >> 1; + to->y2 += dh >> 1; + } +} + +void rtgui_rect_inflate(rtgui_rect_t *rect, int d) +{ + rect->x1 -= d; + rect->x2 += d; + rect->y1 -= d; + rect->y2 += d; +} + +/* put the intersect of src rect and dest rect to dest */ +void rtgui_rect_intersect(rtgui_rect_t *src, rtgui_rect_t *dest) +{ + if (dest->x1 < src->x1) dest->x1 = src->x1; + if (dest->y1 < src->y1) dest->y1 = src->y1; + if (dest->x2 > src->x2) dest->x2 = src->x2; + if (dest->y2 > src->y2) dest->y2 = src->y2; +} + +int rtgui_rect_contains_point(rtgui_rect_t *rect, int x, int y) +{ + if (INBOX(rect, x, y)) return RT_EOK; + + return -RT_ERROR; +} + +int rtgui_rect_is_intersect(rtgui_rect_t *rect1, rtgui_rect_t *rect2) +{ + if (INBOX(rect1, rect2->x1, rect2->y1) || + INBOX(rect1, rect2->x1, rect2->y2) || + INBOX(rect1, rect2->x2, rect2->y1) || + INBOX(rect1, rect2->x2, rect2->y2)) + { + return RT_EOK; + } + else if (INBOX(rect2, rect1->x1, rect1->y1) || + INBOX(rect2, rect1->x1, rect1->y2) || + INBOX(rect2, rect1->x2, rect1->y1) || + INBOX(rect2, rect1->x2, rect1->y2)) + { + return RT_EOK; + } + + return -RT_ERROR; +} diff --git a/rtgui/common/rtgui_system.c b/rtgui/common/rtgui_system.c index f1bbf2bd3742484e207ab46120baa31a97bcc33f..7288c83f55c58cc6deb72728b66d8a6b933483e8 100644 --- a/rtgui/common/rtgui_system.c +++ b/rtgui/common/rtgui_system.c @@ -40,18 +40,6 @@ void rtgui_system_server_init() rtgui_server_init(); } -void rtgui_system_app_init() -{ - /* init launcher thread */ - rtgui_launcher_init(); - - /* init pyim */ - // rtgui_pyim_init(); - - /* init term win */ - // rtgui_term_init(); -} - /************************************************************************/ /* RTGUI Thread Wrapper */ /************************************************************************/ diff --git a/rtgui/common/rtgui_theme.c b/rtgui/common/rtgui_theme.c index 7a875ae222311e8a459f2db01c77f147e4bd7e14..5b4a069c64fb1b95497dcb9af684fd5c46bb16d9 100644 --- a/rtgui/common/rtgui_theme.c +++ b/rtgui/common/rtgui_theme.c @@ -19,13 +19,14 @@ #include #include #include +#include #include #include #define WINTITLE_CB_WIDTH 14 #define WINTITLE_CB_HEIGHT 14 -static const char * close_unpressed_xpm[] = { +static const rt_uint8_t *close_unpressed_xpm[] = { "14 14 55 1", " c None", ". c #DCDFEA", @@ -97,7 +98,7 @@ static const char * close_unpressed_xpm[] = { "#mnnnnnnnnnnm#", "op@@@@@@@@@@po"}; -static const char * close_pressed_xpm[] = { +static const rt_uint8_t *close_pressed_xpm[] = { "14 14 66 1", " c None", ". c #CED4EE", @@ -191,9 +192,11 @@ void rtgui_theme_draw_win(struct rtgui_topwin* win) /* init close box image */ if (close_pressed == RT_NULL) - close_pressed = rtgui_image_create_from_mem("xpm", close_pressed_xpm, sizeof(close_pressed_xpm)); + close_pressed = rtgui_image_create_from_mem("xpm", + (const rt_uint8_t*)close_pressed_xpm, sizeof(close_pressed_xpm)); if (close_unpressed == RT_NULL) - close_unpressed = rtgui_image_create_from_mem("xpm", close_unpressed_xpm, sizeof(close_unpressed_xpm)); + close_unpressed = rtgui_image_create_from_mem("xpm", + (const rt_uint8_t*)close_unpressed_xpm, sizeof(close_unpressed_xpm)); /* begin drawing */ dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(win->title)); @@ -437,3 +440,4 @@ void rtgui_theme_draw_iconbox(rtgui_iconbox_t* iconbox) /* end drawing */ rtgui_dc_end_drawing(dc); } + diff --git a/rtgui/include/rtgui/caret.h b/rtgui/include/rtgui/caret.h new file mode 100644 index 0000000000000000000000000000000000000000..241f6cc889b37f09a4fbfc4c0f7c805a7e6a0777 --- /dev/null +++ b/rtgui/include/rtgui/caret.h @@ -0,0 +1,53 @@ +/* + * File : caret.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_CARET_H__ +#define __RTGUI_CARET_H__ + +#include +#include +#include + +struct rtgui_caret +{ + /* show flag */ + rt_bool_t is_show; + /* the show point of caret */ + struct rtgui_point show_point; + + /* widget owner */ + struct rtgui_widget* owner; + + /* caret buffer dc */ + struct rtgui_dc *dc; + + /* caret extent */ + struct rtgui_rect extent; + + /* the blink timer */ + struct rtgui_timer* timer; + rt_int32_t timer_period; +}; +typedef struct rtgui_caret rtgui_caret_t; + +struct rtgui_caret* rtgui_caret_create(struct rtgui_widget* owner); +void rtgui_caret_destroy(struct rtgui_caret* caret); + +void rtgui_caret_show(struct rtgui_caret* caret, rt_base_t x, rt_base_t y); +void rtgui_caret_hide(struct rtgui_caret* caret); +void rtgui_caret_draw(struct rtgui_caret* caret); + +void rtgui_caret_set_point(struct rtgui_caret* caret, int x, int y); +void rtgui_caret_set_box(struct rtgui_caret* caret, int w, int h); + +#endif diff --git a/rtgui/include/rtgui/color.h b/rtgui/include/rtgui/color.h new file mode 100644 index 0000000000000000000000000000000000000000..af45664a169da6fc9c646c9339012d278f5ba31e --- /dev/null +++ b/rtgui/include/rtgui/color.h @@ -0,0 +1,97 @@ +/* + * File : color.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_COLOR_H__ +#define __RTGUI_COLOR_H__ + +#include + +typedef unsigned long rtgui_color_t; +#define RTGUI_ARGB(a, r, g, b) \ + ((rtgui_color_t)(((rt_uint8_t)(r)|\ + (((unsigned)(rt_uint8_t)(g))<<8))|\ + (((unsigned long)(rt_uint8_t)(b))<<16)|\ + (((unsigned long)(rt_uint8_t)(a))<<24))) +#define RTGUI_RGB(r, g, b) RTGUI_ARGB(255, (r), (g), (b)) + +#define RTGUI_RGB_R(c) ((c) & 0xff) +#define RTGUI_RGB_G(c) (((c) >> 8) & 0xff) +#define RTGUI_RGB_B(c) (((c) >> 16) & 0xff) +#define RTGUI_RGB_A(c) (((c) >> 24) & 0xff) + +extern const rtgui_color_t default_foreground; +extern const rtgui_color_t default_background; + +extern const rtgui_color_t red; +extern const rtgui_color_t green; +extern const rtgui_color_t blue; +extern const rtgui_color_t black; +extern const rtgui_color_t white; +extern const rtgui_color_t high_light; +extern const rtgui_color_t dark_grey; +extern const rtgui_color_t light_grey; + +/* + * RTGUI default color format + * BBBB BBBB GGGG GGGG RRRR RRRR + */ + +/* convert rtgui color to BBBBBGGGGGGRRRRR */ +rt_inline rt_uint16_t rtgui_color_to_565(rtgui_color_t c) +{ + rt_uint16_t pixel; + + pixel = ((RTGUI_RGB_B(c)>> 3) << 11) | ((RTGUI_RGB_G(c) >> 2) << 5) | (RTGUI_RGB_R(c) >> 3); + + return pixel; +} + +rt_inline rtgui_color_t rtgui_color_from_565(rt_uint16_t pixel) +{ + rt_uint16_t r, g, b; + rtgui_color_t color; + + r = pixel & 0x1f; + g = (pixel >> 5) & 0x3f; + b = (pixel >> 11) & 0x1f; + + color = r * 8225 / 1024 + ((g * 4047 / 1024) << 8) + ((b * 8225 / 1024) << 16); + + return color; +} + +/* convert rtgui color to RRRRRGGGGGGBBBBB */ +rt_inline rt_uint16_t rtgui_color_to_565p(rtgui_color_t c) +{ + rt_uint16_t pixel; + + pixel = ((RTGUI_RGB_R(c) >> 3) << 11) | ((RTGUI_RGB_G(c) >> 2) << 5) | (RTGUI_RGB_B(c)>> 3); + return pixel; +} + +rt_inline rtgui_color_t rtgui_color_from_565p(rt_uint16_t pixel) +{ + rt_uint8_t r, g, b; + rtgui_color_t color; + + r = (pixel >> 11) & 0x1f; + g = (pixel >> 5) & 0x3f; + b = pixel & 0x1f; + + color = r * 8225 / 1024 + ((g * 4047 / 1024) << 8) + ((b * 8225 / 1024) << 16); + + return color; +} + +#endif + diff --git a/rtgui/include/rtgui/dc.h b/rtgui/include/rtgui/dc.h new file mode 100644 index 0000000000000000000000000000000000000000..1bf7bc1ee39b05af0bf63cf573824d18df9680e1 --- /dev/null +++ b/rtgui/include/rtgui/dc.h @@ -0,0 +1,126 @@ +/* + * File : dc.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_DC_H__ +#define __RTGUI_DC_H__ + +#include +#include +#include +#include + +enum rtgui_dc_type +{ + RTGUI_DC_HW, + RTGUI_DC_BUFFER, +}; + +/* the abstract device context */ +struct rtgui_dc +{ + /* type of device context */ + rt_uint32_t type; + + /* interface */ + void (*draw_point)(struct rtgui_dc* dc, int x, int y); + void (*draw_vline)(struct rtgui_dc* dc, int x, int y1, int y2); + void (*draw_hline)(struct rtgui_dc* dc, int x1, int x2, int y); + void (*fill_rect )(struct rtgui_dc* dc, rtgui_rect_t* rect); + void (*blit )(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect); + + /* set and get color */ + void (*set_color )(struct rtgui_dc* dc, rtgui_color_t color); + rtgui_color_t (*get_color)(struct rtgui_dc* dc); + + /* set and get font */ + void (*set_font )(struct rtgui_dc* dc, rtgui_font_t* font); + rtgui_font_t* (*get_font)(struct rtgui_dc* dc); + void (*set_textalign)(struct rtgui_dc* dc, rt_int32_t align); + rt_int32_t (*get_textalign)(struct rtgui_dc* dc); + + /* get dc visible */ + rt_bool_t (*get_visible)(struct rtgui_dc* dc); + + /* get dc rect */ + void (*get_rect )(struct rtgui_dc* dc, rtgui_rect_t* rect); + + rt_bool_t (*fini )(struct rtgui_dc* dc); +}; + +/* hardware device context */ +struct rtgui_dc_hw +{ + struct rtgui_dc parent; + + /* widget owner */ + rtgui_widget_t* owner; + + /* visible */ + rt_bool_t visible; + + /* display driver */ + struct rtgui_graphic_driver* device; +}; + +/* create a buffer dc */ +struct rtgui_dc* rtgui_dc_buffer_create(int width, int height); +rt_uint8_t* rtgui_dc_buffer_get_pixel(struct rtgui_dc* dc); + +/* create a hardware dc */ +struct rtgui_dc* rtgui_dc_hw_create(rtgui_widget_t* owner); +struct rtgui_dc* rtgui_dc_begin_drawing(rtgui_widget_t* owner); +void rtgui_dc_end_drawing(struct rtgui_dc* dc); + +/* destroy a dc */ +void rtgui_dc_destory(struct rtgui_dc* dc); + +void rtgui_dc_draw_point(struct rtgui_dc* dc, int x, int y); + +void rtgui_dc_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2); +void rtgui_dc_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y); +void rtgui_dc_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect); +void rtgui_dc_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect); + +void rtgui_dc_set_color(struct rtgui_dc* dc, rtgui_color_t color); +rtgui_color_t rtgui_dc_get_color(struct rtgui_dc* dc); + +void rtgui_dc_set_font(struct rtgui_dc* dc, rtgui_font_t* font); +rtgui_font_t* rtgui_dc_get_font(struct rtgui_dc* dc); +void rtgui_dc_set_textalign(struct rtgui_dc* dc, rt_int32_t align); +rt_int32_t rtgui_dc_get_textalign(struct rtgui_dc* dc); + +rt_bool_t rtgui_dc_get_visible(struct rtgui_dc* dc); +void rtgui_dc_get_rect(struct rtgui_dc*dc, rtgui_rect_t* rect); + +void rtgui_dc_draw_line (struct rtgui_dc* dc, int x1, int y1, int x2, int y2); +void rtgui_dc_draw_rect (struct rtgui_dc* dc, struct rtgui_rect* rect); + +void rtgui_dc_draw_text (struct rtgui_dc* dc, const rt_uint8_t* text, struct rtgui_rect* rect); + +void rtgui_dc_draw_border(struct rtgui_dc* dc, rtgui_rect_t* rect, int flag); +void rtgui_dc_draw_horizontal_line(struct rtgui_dc* dc, int x1, int x2, int y); +void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2); +void rtgui_dc_draw_arrow(struct rtgui_dc* dc, rtgui_rect_t* rect, int kind); +void rtgui_dc_draw_focus_rect(struct rtgui_dc* dc, rtgui_rect_t* rect); + +void rtgui_dc_draw_polygon(struct rtgui_dc* dc, const int *vx, const int *vy, int count); +void rtgui_dc_fill_polygon(struct rtgui_dc* dc, const int* vx, const int* vy, int count); + +void rtgui_dc_draw_circle(struct rtgui_dc* dc, int x, int y, int r); +void rtgui_dc_fill_circle(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t r); +void rtgui_dc_draw_arc(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r, rt_int16_t start, rt_int16_t end); + +void rtgui_dc_draw_ellipse(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry); +void rtgui_dc_fill_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry); + +#endif diff --git a/rtgui/include/rtgui/filerw.h b/rtgui/include/rtgui/filerw.h new file mode 100644 index 0000000000000000000000000000000000000000..0a9395fbb611ff67c3ec2e9297d7f7e25a7a36b1 --- /dev/null +++ b/rtgui/include/rtgui/filerw.h @@ -0,0 +1,47 @@ +/* + * File : filerw.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_FILERW_H__ +#define __RTGUI_FILERW_H__ + +#include + +#define RTGUI_FILE_SEEK_SET 0 +#define RTGUI_FILE_SEEK_CUR 1 +#define RTGUI_FILE_SEEK_END 2 + +struct rtgui_filerw +{ + int (*seek) (struct rtgui_filerw *context, rt_off_t offset, int whence); + int (*read) (struct rtgui_filerw *context, void *buffer, rt_size_t size, rt_size_t count); + int (*write)(struct rtgui_filerw *context, const void *buffer, rt_size_t size, rt_size_t count); + int (*tell) (struct rtgui_filerw *context); + int (*eof) (struct rtgui_filerw *context); + int (*close)(struct rtgui_filerw *context); +}; +typedef struct rtgui_filerw rtgui_filerw_t; + +struct rtgui_filerw* rtgui_filerw_create_file(const char* filename, const char* mode); +struct rtgui_filerw* rtgui_filerw_create_mem(rt_uint8_t* mem, rt_size_t size); + +int rtgui_filerw_seek (struct rtgui_filerw* context, rt_off_t offset, int whence); +int rtgui_filerw_read (struct rtgui_filerw* context, void* buffer, rt_size_t size, rt_size_t count); +int rtgui_filerw_write(struct rtgui_filerw* context, const void* buffer, rt_size_t size, rt_size_t count); +int rtgui_filerw_tell (struct rtgui_filerw* context); +int rtgui_filerw_eof (struct rtgui_filerw* context); +int rtgui_filerw_close(struct rtgui_filerw* context); + +/* get memory data from filerw memory object */ +rt_uint8_t* rtgui_filerw_mem_getdata(struct rtgui_filerw* context); + +#endif diff --git a/rtgui/include/rtgui/font.h b/rtgui/include/rtgui/font.h new file mode 100644 index 0000000000000000000000000000000000000000..db5b6857fc931e18eaebabfb155df44a4433cc8b --- /dev/null +++ b/rtgui/include/rtgui/font.h @@ -0,0 +1,88 @@ +/* + * File : font.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_FONT_H__ +#define __RTGUI_FONT_H__ + +#include +#include + +struct rtgui_font; +struct rtgui_dc; +struct rtgui_rect; + +struct rtgui_font_engine +{ + /* font engine function */ + void (*font_init)(struct rtgui_font* font); + void (*font_load)(struct rtgui_font* font); + + void (*font_draw_text)(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, + rt_ubase_t len, struct rtgui_rect* rect); + void (*font_get_metrics)(struct rtgui_font* font, const rt_uint8_t* text, struct rtgui_rect* rect); +}; + +/* + * bitmap font engine + */ +/* bitmap font private data */ +struct rtgui_font_bitmap +{ + /* bitmap data */ + const rt_uint8_t* bmp; + + rt_uint16_t width; + rt_uint16_t height; + + rt_uint8_t first_char; + rt_uint8_t last_char; +}; +extern struct rtgui_font_engine bmp_font_engine; + +struct rtgui_font +{ + /* font name */ + char* family; + + /* font height */ + rt_uint16_t height; + + /* refer count */ + rt_uint32_t refer_count; + + /* font engine */ + struct rtgui_font_engine* engine; + + /* font private data */ + void* data; + + /* the font list */ + rtgui_list_t list; +}; +typedef struct rtgui_font rtgui_font_t; + +void rtgui_font_system_init(void); +void rtgui_font_system_add_font(struct rtgui_font* font); +void rtgui_font_system_remove_font(struct rtgui_font* font); +struct rtgui_font* rtgui_font_default(void); +void rtgui_font_set_defaut(struct rtgui_font* font); + +struct rtgui_font* rtgui_font_refer(const rt_uint8_t* family, rt_uint16_t height); +void rtgui_font_derefer(struct rtgui_font* font); + +/* draw a text */ +void rtgui_font_draw(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect); +int rtgui_font_get_string_width(struct rtgui_font* font, const rt_uint8_t* text); +void rtgui_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, struct rtgui_rect* rect); + +#endif diff --git a/rtgui/include/rtgui/image.h b/rtgui/include/rtgui/image.h new file mode 100644 index 0000000000000000000000000000000000000000..68f6144ebe3b99f16c2b9fa957ade533a55de249 --- /dev/null +++ b/rtgui/include/rtgui/image.h @@ -0,0 +1,63 @@ +/* + * File : image.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_IMAGE_H__ +#define __RTGUI_IMAGE_H__ + +#include +#include +#include + +struct rtgui_image; +struct rtgui_image_engine +{ + const char* name; + struct rtgui_list_node list; + + /* image engine function */ + rt_bool_t (*image_check)(struct rtgui_filerw* file); + + rt_bool_t (*image_load)(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load); + void (*image_unload)(struct rtgui_image* image); + + void (*image_blit)(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect); +}; + +struct rtgui_image +{ + /* image metrics */ + rt_uint16_t w, h; + + /* image engine */ + struct rtgui_image_engine* engine; + + /* image private data */ + void* data; +}; +typedef struct rtgui_image rtgui_image_t; + +/* init rtgui image system */ +void rtgui_system_image_init(void); + +struct rtgui_image* rtgui_image_create_from_file(const char* type, const char* filename, rt_bool_t load); +struct rtgui_image* rtgui_image_create_from_mem(const char* type, const rt_uint8_t* data, rt_size_t length); +void rtgui_image_destroy(struct rtgui_image* image); + +/* register an image engine */ +void rtgui_image_register_engine(struct rtgui_image_engine* engine); + +/* blit an image on DC */ +void rtgui_image_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect); + + +#endif diff --git a/rtgui/include/rtgui/image_png.h b/rtgui/include/rtgui/image_png.h new file mode 100644 index 0000000000000000000000000000000000000000..13aff657f97e01502c7ec113a6790bebb29429a8 --- /dev/null +++ b/rtgui/include/rtgui/image_png.h @@ -0,0 +1,19 @@ +/* + * File : image_png.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_IMAGE_PNG_H__ +#define __RTGUI_IMAGE_PNG_H__ + +#include + +#endif diff --git a/rtgui/include/rtgui/image_xpm.h b/rtgui/include/rtgui/image_xpm.h new file mode 100644 index 0000000000000000000000000000000000000000..e580327f6d6317e80a2f0e453d196e9b7a2a6d54 --- /dev/null +++ b/rtgui/include/rtgui/image_xpm.h @@ -0,0 +1,21 @@ +/* + * File : image_xpm.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_IMAGE_XPM_H__ +#define __RTGUI_IMAGE_XPM_H__ + +#include + +void rtgui_image_xpm_init(void); + +#endif diff --git a/rtgui/include/rtgui/kbddef.h b/rtgui/include/rtgui/kbddef.h new file mode 100644 index 0000000000000000000000000000000000000000..c078404c601b3c47a613193230acd09234ee57a4 --- /dev/null +++ b/rtgui/include/rtgui/kbddef.h @@ -0,0 +1,293 @@ +/* + * File : kbddef.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __KBD_DEF_H__ +#define __KBD_DEF_H__ + +/* The keyboard key have been cleverly chosen to map to ASCII */ +typedef enum +{ + RTGUIK_UNKNOWN = 0, + RTGUIK_FIRST = 0, + RTGUIK_BACKSPACE = 8, + RTGUIK_TAB = 9, + RTGUIK_CLEAR = 12, + RTGUIK_RETURN = 13, + RTGUIK_PAUSE = 19, + RTGUIK_ESCAPE = 27, + RTGUIK_SPACE = 32, + RTGUIK_EXCLAIM = 33, + RTGUIK_QUOTEDBL = 34, + RTGUIK_HASH = 35, + RTGUIK_DOLLAR = 36, + RTGUIK_AMPERSAND = 38, + RTGUIK_QUOTE = 39, + RTGUIK_LEFTPAREN = 40, + RTGUIK_RIGHTPAREN = 41, + RTGUIK_ASTERISK = 42, + RTGUIK_PLUS = 43, + RTGUIK_COMMA = 44, + RTGUIK_MINUS = 45, + RTGUIK_PERIOD = 46, + RTGUIK_SLASH = 47, + RTGUIK_0 = 48, + RTGUIK_1 = 49, + RTGUIK_2 = 50, + RTGUIK_3 = 51, + RTGUIK_4 = 52, + RTGUIK_5 = 53, + RTGUIK_6 = 54, + RTGUIK_7 = 55, + RTGUIK_8 = 56, + RTGUIK_9 = 57, + RTGUIK_COLON = 58, + RTGUIK_SEMICOLON = 59, + RTGUIK_LESS = 60, + RTGUIK_EQUALS = 61, + RTGUIK_GREATER = 62, + RTGUIK_QUESTION = 63, + RTGUIK_AT = 64, + + /* + Skip uppercase letters + */ + RTGUIK_LEFTBRACKET = 91, + RTGUIK_BACKSLASH = 92, + RTGUIK_RIGHTBRACKET = 93, + RTGUIK_CARET = 94, + RTGUIK_UNDERSCORE = 95, + RTGUIK_BACKQUOTE = 96, + RTGUIK_a = 97, + RTGUIK_b = 98, + RTGUIK_c = 99, + RTGUIK_d = 100, + RTGUIK_e = 101, + RTGUIK_f = 102, + RTGUIK_g = 103, + RTGUIK_h = 104, + RTGUIK_i = 105, + RTGUIK_j = 106, + RTGUIK_k = 107, + RTGUIK_l = 108, + RTGUIK_m = 109, + RTGUIK_n = 110, + RTGUIK_o = 111, + RTGUIK_p = 112, + RTGUIK_q = 113, + RTGUIK_r = 114, + RTGUIK_s = 115, + RTGUIK_t = 116, + RTGUIK_u = 117, + RTGUIK_v = 118, + RTGUIK_w = 119, + RTGUIK_x = 120, + RTGUIK_y = 121, + RTGUIK_z = 122, + RTGUIK_DELETE = 127, + + /* International keyboard */ + RTGUIK_WORLD_0 = 160, /* 0xA0 */ + RTGUIK_WORLD_1 = 161, + RTGUIK_WORLD_2 = 162, + RTGUIK_WORLD_3 = 163, + RTGUIK_WORLD_4 = 164, + RTGUIK_WORLD_5 = 165, + RTGUIK_WORLD_6 = 166, + RTGUIK_WORLD_7 = 167, + RTGUIK_WORLD_8 = 168, + RTGUIK_WORLD_9 = 169, + RTGUIK_WORLD_10 = 170, + RTGUIK_WORLD_11 = 171, + RTGUIK_WORLD_12 = 172, + RTGUIK_WORLD_13 = 173, + RTGUIK_WORLD_14 = 174, + RTGUIK_WORLD_15 = 175, + RTGUIK_WORLD_16 = 176, + RTGUIK_WORLD_17 = 177, + RTGUIK_WORLD_18 = 178, + RTGUIK_WORLD_19 = 179, + RTGUIK_WORLD_20 = 180, + RTGUIK_WORLD_21 = 181, + RTGUIK_WORLD_22 = 182, + RTGUIK_WORLD_23 = 183, + RTGUIK_WORLD_24 = 184, + RTGUIK_WORLD_25 = 185, + RTGUIK_WORLD_26 = 186, + RTGUIK_WORLD_27 = 187, + RTGUIK_WORLD_28 = 188, + RTGUIK_WORLD_29 = 189, + RTGUIK_WORLD_30 = 190, + RTGUIK_WORLD_31 = 191, + RTGUIK_WORLD_32 = 192, + RTGUIK_WORLD_33 = 193, + RTGUIK_WORLD_34 = 194, + RTGUIK_WORLD_35 = 195, + RTGUIK_WORLD_36 = 196, + RTGUIK_WORLD_37 = 197, + RTGUIK_WORLD_38 = 198, + RTGUIK_WORLD_39 = 199, + RTGUIK_WORLD_40 = 200, + RTGUIK_WORLD_41 = 201, + RTGUIK_WORLD_42 = 202, + RTGUIK_WORLD_43 = 203, + RTGUIK_WORLD_44 = 204, + RTGUIK_WORLD_45 = 205, + RTGUIK_WORLD_46 = 206, + RTGUIK_WORLD_47 = 207, + RTGUIK_WORLD_48 = 208, + RTGUIK_WORLD_49 = 209, + RTGUIK_WORLD_50 = 210, + RTGUIK_WORLD_51 = 211, + RTGUIK_WORLD_52 = 212, + RTGUIK_WORLD_53 = 213, + RTGUIK_WORLD_54 = 214, + RTGUIK_WORLD_55 = 215, + RTGUIK_WORLD_56 = 216, + RTGUIK_WORLD_57 = 217, + RTGUIK_WORLD_58 = 218, + RTGUIK_WORLD_59 = 219, + RTGUIK_WORLD_60 = 220, + RTGUIK_WORLD_61 = 221, + RTGUIK_WORLD_62 = 222, + RTGUIK_WORLD_63 = 223, + RTGUIK_WORLD_64 = 224, + RTGUIK_WORLD_65 = 225, + RTGUIK_WORLD_66 = 226, + RTGUIK_WORLD_67 = 227, + RTGUIK_WORLD_68 = 228, + RTGUIK_WORLD_69 = 229, + RTGUIK_WORLD_70 = 230, + RTGUIK_WORLD_71 = 231, + RTGUIK_WORLD_72 = 232, + RTGUIK_WORLD_73 = 233, + RTGUIK_WORLD_74 = 234, + RTGUIK_WORLD_75 = 235, + RTGUIK_WORLD_76 = 236, + RTGUIK_WORLD_77 = 237, + RTGUIK_WORLD_78 = 238, + RTGUIK_WORLD_79 = 239, + RTGUIK_WORLD_80 = 240, + RTGUIK_WORLD_81 = 241, + RTGUIK_WORLD_82 = 242, + RTGUIK_WORLD_83 = 243, + RTGUIK_WORLD_84 = 244, + RTGUIK_WORLD_85 = 245, + RTGUIK_WORLD_86 = 246, + RTGUIK_WORLD_87 = 247, + RTGUIK_WORLD_88 = 248, + RTGUIK_WORLD_89 = 249, + RTGUIK_WORLD_90 = 250, + RTGUIK_WORLD_91 = 251, + RTGUIK_WORLD_92 = 252, + RTGUIK_WORLD_93 = 253, + RTGUIK_WORLD_94 = 254, + RTGUIK_WORLD_95 = 255, /* 0xFF */ + + /* Numeric keypad */ + RTGUIK_KP0 = 256, + RTGUIK_KP1 = 257, + RTGUIK_KP2 = 258, + RTGUIK_KP3 = 259, + RTGUIK_KP4 = 260, + RTGUIK_KP5 = 261, + RTGUIK_KP6 = 262, + RTGUIK_KP7 = 263, + RTGUIK_KP8 = 264, + RTGUIK_KP9 = 265, + RTGUIK_KP_PERIOD = 266, + RTGUIK_KP_DIVIDE = 267, + RTGUIK_KP_MULTIPLY = 268, + RTGUIK_KP_MINUS = 269, + RTGUIK_KP_PLUS = 270, + RTGUIK_KP_ENTER = 271, + RTGUIK_KP_EQUALS = 272, + + /* Arrows + Home/End pad */ + RTGUIK_UP = 273, + RTGUIK_DOWN = 274, + RTGUIK_RIGHT = 275, + RTGUIK_LEFT = 276, + RTGUIK_INSERT = 277, + RTGUIK_HOME = 278, + RTGUIK_END = 279, + RTGUIK_PAGEUP = 280, + RTGUIK_PAGEDOWN = 281, + + /* Function keys */ + RTGUIK_F1 = 282, + RTGUIK_F2 = 283, + RTGUIK_F3 = 284, + RTGUIK_F4 = 285, + RTGUIK_F5 = 286, + RTGUIK_F6 = 287, + RTGUIK_F7 = 288, + RTGUIK_F8 = 289, + RTGUIK_F9 = 290, + RTGUIK_F10 = 291, + RTGUIK_F11 = 292, + RTGUIK_F12 = 293, + RTGUIK_F13 = 294, + RTGUIK_F14 = 295, + RTGUIK_F15 = 296, + + /* Key state modifier keys */ + RTGUIK_NUMLOCK = 300, + RTGUIK_CAPSLOCK = 301, + RTGUIK_SCROLLOCK = 302, + RTGUIK_RSHIFT = 303, + RTGUIK_LSHIFT = 304, + RTGUIK_RCTRL = 305, + RTGUIK_LCTRL = 306, + RTGUIK_RALT = 307, + RTGUIK_LALT = 308, + RTGUIK_RMETA = 309, + RTGUIK_LMETA = 310, + RTGUIK_LSUPER = 311, /* Left "Windows" key */ + RTGUIK_RSUPER = 312, /* Right "Windows" key */ + RTGUIK_MODE = 313, /* "Alt Gr" key */ + RTGUIK_COMPOSE = 314, /* Multi-key compose key */ + + /* Miscellaneous function keys */ + RTGUIK_HELP = 315, + RTGUIK_PRINT = 316, + RTGUIK_SYSREQ = 317, + RTGUIK_BREAK = 318, + RTGUIK_MENU = 319, + RTGUIK_POWER = 320, /* Power key */ + + RTGUIK_LAST +} RTGUI_KBD_KEY; + +/* Enumeration of valid key mods (possibly OR'd together) */ +typedef enum { + RTGUI_KMOD_NONE = 0x0000, + RTGUI_KMOD_LSHIFT = 0x0001, + RTGUI_KMOD_RSHIFT = 0x0002, + RTGUI_KMOD_LCTRL = 0x0040, + RTGUI_KMOD_RCTRL = 0x0080, + RTGUI_KMOD_LALT = 0x0100, + RTGUI_KMOD_RALT = 0x0200, + RTGUI_KMOD_LMETA = 0x0400, + RTGUI_KMOD_RMETA = 0x0800, + RTGUI_KMOD_NUM = 0x1000, + RTGUI_KMOD_CAPS = 0x2000, + RTGUI_KMOD_MODE = 0x4000, + RTGUI_KMOD_RESERVED = 0x8000 +} RTGUI_KBD_MOD; + +typedef enum { + RTGUI_KEYDOWN, /* Keys pressed */ + RTGUI_KEYUP, /* Keys released */ +} RTGUI_KBD_TYPE; + +#endif diff --git a/rtgui/include/rtgui/list.h b/rtgui/include/rtgui/list.h new file mode 100644 index 0000000000000000000000000000000000000000..4b3cf951e674319032cb069c955772cd03e236a1 --- /dev/null +++ b/rtgui/include/rtgui/list.h @@ -0,0 +1,66 @@ +/* + * File : list.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_LIST_H__ +#define __RTGUI_LIST_H__ + +#include + +struct rtgui_list_node +{ + struct rtgui_list_node* next; +}; +typedef struct rtgui_list_node rtgui_list_t; + +rt_inline void rtgui_list_init(rtgui_list_t *l) +{ + l->next = (struct rtgui_list_node *)0; +} + +rt_inline void rtgui_list_append(rtgui_list_t *l, rtgui_list_t *n) +{ + struct rtgui_list_node* node; + + node = l; + while (node->next) node = node->next; + + /* append the node to the tail */ + node->next = n; + n->next = (struct rtgui_list_node*) 0; +} + +rt_inline void rtgui_list_insert(rtgui_list_t *l, rtgui_list_t *n) +{ + n->next = l->next; + l->next = n; +} + +rt_inline rtgui_list_t* rtgui_list_remove(rtgui_list_t *l, rtgui_list_t *n) +{ + /* remove slist head */ + struct rtgui_list_node* node = l; + while (node->next && node->next != n) node = node->next; + + /* remove node */ + if (node->next != (rtgui_list_t *)0) node->next = node->next->next; + + return l; +} + +#define rtgui_list_entry(node, type, member) \ + ((type *)((char*)(node)-(unsigned long)(&((type *)0)->member))) + +#define rtgui_list_foreach(node, list) \ + for ((node) = (list)->next; (node) != RT_NULL; (node) = (node)->next) + +#endif diff --git a/rtgui/include/rtgui/region.h b/rtgui/include/rtgui/region.h new file mode 100644 index 0000000000000000000000000000000000000000..72c06653e3f4a4d522000d6ba69d7da01f32fd5b --- /dev/null +++ b/rtgui/include/rtgui/region.h @@ -0,0 +1,100 @@ +/* + * File : region.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_REGION_H__ +#define __RTGUI_REGION_H__ + +#include + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +typedef struct rtgui_region_data rtgui_region_data_t; + +struct rtgui_region_data +{ + rt_uint32_t size; + rt_uint32_t numRects; + /* XXX: And why, exactly, do we have this bogus struct definition? */ + /* rtgui_rect_t rects[size]; in memory but not explicitly declared */ +}; + +typedef struct rtgui_region +{ + rtgui_rect_t extents; + rtgui_region_data_t *data; +}rtgui_region_t; + +typedef enum +{ + RTGUI_REGION_STATUS_FAILURE, + RTGUI_REGION_STATUS_SUCCESS +}rtgui_region_status_t; + +/* creation/destruction */ + +void rtgui_region_init(rtgui_region_t *region); +void rtgui_region_init_rect(rtgui_region_t *region, + int x, int y, unsigned int width, unsigned int height); +void rtgui_region_init_with_extents(rtgui_region_t *region, rtgui_rect_t *extents); +void rtgui_region_fini (rtgui_region_t *region); + +void rtgui_region_translate (rtgui_region_t *region, int x, int y); + +rtgui_region_status_t rtgui_region_copy (rtgui_region_t *dest, rtgui_region_t *source); + +rtgui_region_status_t rtgui_region_intersect (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_region_t *reg2); +rtgui_region_status_t rtgui_region_intersect_rect (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_rect_t *rect); +rtgui_region_status_t rtgui_region_union (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_region_t *reg2); +rtgui_region_status_t rtgui_region_union_rect(rtgui_region_t *dest, rtgui_region_t *source, rtgui_rect_t* rect); +rtgui_region_status_t rtgui_region_subtract (rtgui_region_t *regD, rtgui_region_t *regM, rtgui_region_t *regS); +rtgui_region_status_t rtgui_region_subtract_rect (rtgui_region_t *regD, rtgui_region_t *regM, rtgui_rect_t* rect); +rtgui_region_status_t rtgui_region_inverse (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_rect_t *invRect); + +int rtgui_region_num_rects (rtgui_region_t *region); + +rtgui_rect_t* rtgui_region_rects (rtgui_region_t *region); + +#define RTGUI_REGION_OUT 0 +#define RTGUI_REGION_IN 1 +#define RTGUI_REGION_PART 2 + +int rtgui_region_contains_point (rtgui_region_t *region, int x, int y, rtgui_rect_t *box); +int rtgui_region_contains_rectangle (rtgui_region_t *rtgui_region_t, rtgui_rect_t *prect); + +int rtgui_region_not_empty (rtgui_region_t *region); +rtgui_rect_t *rtgui_region_extents (rtgui_region_t *region); + +rtgui_region_status_t rtgui_region_append (rtgui_region_t *dest, rtgui_region_t *region); +rtgui_region_status_t rtgui_region_validate (rtgui_region_t *badreg, int *pOverlap); + +void rtgui_region_reset(rtgui_region_t *region, rtgui_rect_t* rect); +void rtgui_region_empty (rtgui_region_t *region); +void rtgui_region_dump(rtgui_region_t* region); + +/* rect functions */ +extern rtgui_rect_t rtgui_empty_rect; + +void rtgui_rect_moveto(rtgui_rect_t *rect, int x, int y); +void rtgui_rect_moveto_align(rtgui_rect_t *rect, rtgui_rect_t *to, int align); +void rtgui_rect_inflate(rtgui_rect_t *rect, int d); +void rtgui_rect_intersect(rtgui_rect_t *src, rtgui_rect_t *dest); +int rtgui_rect_contains_point(rtgui_rect_t *rect, int x, int y); +int rtgui_rect_is_intersect(rtgui_rect_t *rect1, rtgui_rect_t *rect2); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* _PIXMAN_H_ */ diff --git a/rtgui/include/rtgui/rtgui.h b/rtgui/include/rtgui/rtgui.h index bc820b76c062ac359e2d65fac498431d0edf85c8..dcc0741dba60a38466366d6fd9d7d3a5d63f8b58 100644 --- a/rtgui/include/rtgui/rtgui.h +++ b/rtgui/include/rtgui/rtgui.h @@ -16,10 +16,7 @@ #include -/* RTGUI options */ -#define RTGUI_IMAGE_JPEG - -#define RTGUI_NAME_MAX 32 +#include #define RT_INT16_MAX 32767 #define RT_INT16_MIN (-RT_INT16_MAX-1) diff --git a/rtgui/include/rtgui/rtgui_config.h b/rtgui/include/rtgui/rtgui_config.h new file mode 100644 index 0000000000000000000000000000000000000000..72667c1342f73667d1636dd609ec66abea7c51bc --- /dev/null +++ b/rtgui/include/rtgui/rtgui_config.h @@ -0,0 +1,36 @@ +/* + * File : rtgui_config.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ + +#ifndef __RTGUI_CONFIG_H__ +#define __RTGUI_CONFIG_H__ + +/* RTGUI options */ + +/* name length of RTGUI object */ +#define RTGUI_NAME_MAX 32 + +/* #define RTGUI_USING_MOUSE_CURSOR */ + +/* #define RTGUI_USING_FONT16 */ + +#define RT_USING_STDIO_FILERW + +#define RTGUI_SVR_THREAD_PRIORITY 15 +#define RTGUI_SVR_THREAD_TIMESLICE 5 + +#define RTGUI_APP_THREAD_PRIORITY 25 +#define RTGUI_APP_THREAD_TIMESLICE 8 + +#endif + diff --git a/rtgui/include/rtgui/rtgui_server.h b/rtgui/include/rtgui/rtgui_server.h index a9463ecb38a1d9133e34ab3cac6dda97bc5a1fc9..738e60100e32d2dac07a953f85ac5cedaa646b7c 100644 --- a/rtgui/include/rtgui/rtgui_server.h +++ b/rtgui/include/rtgui/rtgui_server.h @@ -67,4 +67,9 @@ void rtgui_server_init(void); /* post an event to server */ void rtgui_server_post_event(struct rtgui_event* event, rt_size_t size); +/* register or deregister panel in server */ +void rtgui_panel_register(char* name, rtgui_rect_t* extent); +void rtgui_panel_deregister(char* name); + #endif + diff --git a/rtgui/include/rtgui/rtgui_theme.h b/rtgui/include/rtgui/rtgui_theme.h index eb6738d6b51de270627c942ef7e6747eb06fc20f..60711dcaab550dfc50029e217a612a155a2f2a4d 100644 --- a/rtgui/include/rtgui/rtgui_theme.h +++ b/rtgui/include/rtgui/rtgui_theme.h @@ -15,6 +15,7 @@ #define __RTGUI_THEME_H__ #include +#include #include #include diff --git a/rtgui/include/rtgui/widgets/box.h b/rtgui/include/rtgui/widgets/box.h new file mode 100644 index 0000000000000000000000000000000000000000..69a0a01a569060bd85302c683d4443553135a9b8 --- /dev/null +++ b/rtgui/include/rtgui/widgets/box.h @@ -0,0 +1,58 @@ +/* + * File : box.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_BOX_H__ +#define __RTGUI_BOX_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Gets the type of a box */ +#define RTGUI_BOX_TYPE (rtgui_box_type_get()) +/** Casts the object to an rtgui_box */ +#define RTGUI_BOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_BOX_TYPE, rtgui_box_t)) +/** Checks if the object is an rtgui_box */ +#define RTGUI_IS_BOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_BOX_TYPE)) + +struct rtgui_box +{ + struct rtgui_container parent; + + rt_uint16_t orientation; + rt_uint16_t border_size; +}; +typedef struct rtgui_box rtgui_box_t; + +rtgui_type_t *rtgui_box_type_get(void); + +struct rtgui_box* rtgui_box_create(int orientation, rtgui_rect_t* rect); +void rtgui_box_destroy(struct rtgui_box* box); + +rt_bool_t rtgui_box_event_handler(rtgui_widget_t* widget, rtgui_event_t* event); + +void rtgui_box_append(rtgui_box_t* box, rtgui_widget_t* widget); +void rtgui_box_layout(rtgui_box_t* box); + +rt_uint32_t rtgui_box_get_width(rtgui_box_t* box); +rt_uint32_t rtgui_box_get_height(rtgui_box_t* box); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rtgui/include/rtgui/widgets/button.h b/rtgui/include/rtgui/widgets/button.h new file mode 100644 index 0000000000000000000000000000000000000000..77e7fc4e035e53e2f62ec8787d96f15ec6f1963b --- /dev/null +++ b/rtgui/include/rtgui/widgets/button.h @@ -0,0 +1,81 @@ +/* + * File : button.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_BUTTON_H__ +#define __RTGUI_BUTTON_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup rtgui_button + * @{ + */ + +/** Gets the type of a button */ +#define RTGUI_BUTTON_TYPE (rtgui_button_type_get()) +/** Casts the object to an rtgui_button */ +#define RTGUI_BUTTON(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_BUTTON_TYPE, rtgui_button_t)) +/** Checks if the object is an rtgui_button */ +#define RTGUI_IS_BUTTON(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_BUTTON_TYPE)) + +#define RTGUI_BUTTON_FLAG_PRESS 0x01 +#define RTGUI_BUTTON_FLAG_DEFAULT 0x02 + +#define RTGUI_BUTTON_TYPE_NORMAL 0x00 +#define RTGUI_BUTTON_TYPE_PUSH 0x10 + +/* + * the button widget + */ +struct rtgui_button +{ + /* inherit from label */ + struct rtgui_label parent; + + /* button flag */ + rt_base_t flag; + + /* pressed and unpressed image */ + rtgui_image_t *pressed_image, *unpressed_image; + + /* click button event handler */ + void (*on_button)(struct rtgui_widget* widget, rtgui_event_t *event); +}; +typedef struct rtgui_button rtgui_button_t; + +rtgui_type_t *rtgui_button_type_get(void); + +rtgui_button_t* rtgui_button_create(unsigned char* text); +rtgui_button_t* rtgui_pushbutton_create(unsigned char* text); +void rtgui_button_destroy(rtgui_button_t* btn); + +void rtgui_button_set_pressed_image(rtgui_button_t* btn, rtgui_image_t* image); +void rtgui_button_set_unpressed_image(rtgui_button_t* btn, rtgui_image_t* image); + +void rtgui_button_ondraw(rtgui_button_t* btn); + +rt_bool_t rtgui_button_event_handler(struct rtgui_widget* widget, struct rtgui_event* event); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rtgui/include/rtgui/widgets/container.h b/rtgui/include/rtgui/widgets/container.h new file mode 100644 index 0000000000000000000000000000000000000000..7f1af7d3d2341024bc85e98444df0a2d8713448e --- /dev/null +++ b/rtgui/include/rtgui/widgets/container.h @@ -0,0 +1,47 @@ +/* + * File : container.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_CONTAINER_H__ +#define __RTGUI_CONTAINER_H__ + +#include + +/** Gets the type of a container */ +#define RTGUI_CONTAINER_TYPE (rtgui_container_type_get()) +/** Casts the object to a rtgui_container */ +#define RTGUI_CONTAINER(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_CONTAINER_TYPE, rtgui_container_t)) +/** Checks if the object is a rtgui_container */ +#define RTGUI_IS_CONTAINER(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_CONTAINER_TYPE)) + +struct rtgui_container +{ + /* inherit from widget */ + struct rtgui_widget parent; + + rtgui_list_t children; +}; +typedef struct rtgui_container rtgui_container_t; + +rtgui_type_t *rtgui_container_type_get(void); + +void rtgui_container_add_child(rtgui_container_t *container, rtgui_widget_t* child); +void rtgui_container_remove_child(rtgui_container_t *container, rtgui_widget_t* child); +void rtgui_container_destroy_children(rtgui_container_t *container); +rtgui_widget_t* rtgui_container_get_first_child(rtgui_container_t* container); + +rt_bool_t rtgui_container_event_handler(rtgui_widget_t* widget, rtgui_event_t* event); + +rt_bool_t rtgui_container_dispatch_event(rtgui_container_t *container, rtgui_event_t* event); +rt_bool_t rtgui_container_dispatch_mouse_event(rtgui_container_t *container, struct rtgui_event_mouse* event); + +#endif diff --git a/rtgui/include/rtgui/widgets/iconbox.h b/rtgui/include/rtgui/widgets/iconbox.h new file mode 100644 index 0000000000000000000000000000000000000000..73ebd682a6669aa682124d7efbf28eeed7f85f9e --- /dev/null +++ b/rtgui/include/rtgui/widgets/iconbox.h @@ -0,0 +1,56 @@ +/* + * File : iconbox.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_ICONBOX_H__ +#define __RTGUI_ICONBOX_H__ + +#include +#include +#include + +/** Gets the type of a iconbox */ +#define RTGUI_ICONBOX_TYPE (rtgui_iconbox_type_get()) +/** Casts the object to a rtgui_iconbox */ +#define RTGUI_ICONBOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_ICONBOX_TYPE, rtgui_iconbox_t)) +/** Checks if the object is a rtgui_iconbox */ +#define RTGUI_IS_ICONBOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_ICONBOX_TYPE)) + +#define RTGUI_ICONBOX_NOTEXT 0x00 +#define RTGUI_ICONBOX_TEXT_RIGHT 0x01 +#define RTGUI_ICONBOX_TEXT_BELOW 0x02 + +struct rtgui_iconbox +{ + /* inherit from widget */ + struct rtgui_widget parent; + + /* widget private data */ + struct rtgui_image* image; + + unsigned char *text; + rt_ubase_t text_position; + + rt_bool_t selected; +}; +typedef struct rtgui_iconbox rtgui_iconbox_t; + +rtgui_type_t *rtgui_iconbox_type_get(void); + +struct rtgui_iconbox* rtgui_iconbox_create(struct rtgui_image* image, const unsigned char* text, int position); +void rtgui_iconbox_destroy(struct rtgui_iconbox* iconbox); + +rt_bool_t rtgui_iconbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event); + +void rtgui_iconbox_set_text_position(struct rtgui_iconbox* iconbox, int position); + +#endif diff --git a/rtgui/include/rtgui/widgets/label.h b/rtgui/include/rtgui/widgets/label.h new file mode 100644 index 0000000000000000000000000000000000000000..d9f87d9b88568e6f7d01f166f0fa32c939e295af --- /dev/null +++ b/rtgui/include/rtgui/widgets/label.h @@ -0,0 +1,49 @@ +/* + * File : label.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_LABEL_H__ +#define __RTGUI_LABEL_H__ + +#include +#include + +/** Gets the type of a button */ +#define RTGUI_LABEL_TYPE (rtgui_label_type_get()) +/** Casts the object to an rtgui_button */ +#define RTGUI_LABEL(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_LABEL_TYPE, rtgui_label_t)) +/** Checks if the object is an rtgui_button */ +#define RTGUI_IS_LABEL(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_LABEL_TYPE)) + +/* + * the label widget + */ +struct rtgui_label +{ + struct rtgui_widget parent; + + /* label */ + unsigned char* text; +}; +typedef struct rtgui_label rtgui_label_t; + +rtgui_type_t *rtgui_label_type_get(void); + +rtgui_label_t* rtgui_label_create(const unsigned char* text); +void rtgui_label_destroy(rtgui_label_t* label); + +rt_bool_t rtgui_label_event_handler(struct rtgui_widget* widget, struct rtgui_event* event); + +void rtgui_label_set_text(rtgui_label_t* label, const unsigned char* text); +unsigned char* rtgui_label_get_text(rtgui_label_t* label); + +#endif diff --git a/rtgui/include/rtgui/widgets/listbox.h b/rtgui/include/rtgui/widgets/listbox.h new file mode 100644 index 0000000000000000000000000000000000000000..1c201301daa7993bb6540d97dc47ee72197dfdaf --- /dev/null +++ b/rtgui/include/rtgui/widgets/listbox.h @@ -0,0 +1,66 @@ +/* + * File : listbox.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_LISTBOX_H__ +#define __RTGUI_LISTBOX_H__ + +#include +#include + +#define RTGUI_LISTBOX_WIDTH 150 +#define RTGUI_LISTBOX_HEIGHT 200 + +/** Gets the type of a listbox */ +#define RTGUI_LISTBOX_TYPE (rtgui_listbox_type_get()) +/** Casts the object to a rtgui_listbox */ +#define RTGUI_LISTBOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_LISTBOX_TYPE, rtgui_listbox_t)) +/** Checks if the object is a rtgui_listbox */ +#define RTGUI_IS_LISTBOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_LISTBOX_TYPE)) + +/* +* the listbox widget +*/ +struct rtgui_listbox +{ + struct rtgui_scrollview parent; + + /* widget private data */ + int flag; + + /* total number of items */ + rt_uint32_t count; + + /* the selected item */ + struct rtgui_item* selected; + + /* call back */ + rt_bool_t (*on_selected) (struct rtgui_widget* widget, struct rtgui_event* event); + rt_bool_t (*on_activated) (struct rtgui_widget* widget, struct rtgui_event* event); +}; +typedef struct rtgui_listbox rtgui_listbox_t; + +rtgui_type_t *rtgui_listbox_type_get(void); + +rtgui_listbox_t* rtgui_listbox_create(void); +void rtgui_listbox_destroy(rtgui_listbox_t* listbox); + +rt_bool_t rtgui_listbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event); + +struct rtgui_item* rtgui_listbox_get_select(struct rtgui_listbox* box); +void rtgui_listbox_set_select(struct rtgui_listbox* box, rt_uint32_t index); +void rtgui_listbox_set_select_item(struct rtgui_listbox* box, struct rtgui_item* item); + +struct rtgui_item* rtgui_listbox_add_item_string(struct rtgui_listbox* box, const unsigned char* text); +void rtgui_listbox_add_item(struct rtgui_listbox* list, struct rtgui_item* item); + +#endif diff --git a/rtgui/include/rtgui/widgets/textbox.h b/rtgui/include/rtgui/widgets/textbox.h new file mode 100644 index 0000000000000000000000000000000000000000..709b35f76bb897c8ad857a1742859ca10aa696ef --- /dev/null +++ b/rtgui/include/rtgui/widgets/textbox.h @@ -0,0 +1,73 @@ +/* + * File : textbox.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_TEXTBOX_H__ +#define __RTGUI_TEXTBOX_H__ + +#include +#include +#include + +/** Gets the type of a textbox */ +#define RTGUI_TEXTBOX_TYPE (rtgui_textbox_type_get()) +/** Casts the object to a rtgui_textbox */ +#define RTGUI_TEXTBOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_TEXTBOX_TYPE, rtgui_textbox_t)) +/** Checks if the object is a rtgui_textbox */ +#define RTGUI_IS_TEXTBOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_TEXTBOX_TYPE)) + +#define RTGUI_TEXTBOX_DEFAULT_WIDTH 80 +#define RTGUI_TEXTBOX_DEFAULT_HEIGHT 20 + +#define RTGUI_TEXTBOX_SINGLE 0x00 +#define RTGUI_TEXTBOX_MULTI 0x00 + +struct rtgui_textbox_line +{ + rt_uint8_t* line_text; + + struct rtgui_textbox_line *prev, *next; +}; + +struct rtgui_textbox +{ + /* inherit from widget */ + struct rtgui_widget parent; + + /* text box type */ + rt_ubase_t type; + + /* current line and position */ + rt_size_t line, line_begin, position, line_length; + + rt_uint8_t* text; + rt_size_t font_width; + + int caret_x, caret_y; + struct rtgui_caret* caret; + + /* widget private data */ + rt_bool_t (*on_enter) (struct rtgui_widget* widget, struct rtgui_event* event); +}; +typedef struct rtgui_textbox rtgui_textbox_t; + +struct rtgui_textbox* rtgui_textbox_create(const char* text); +void rtgui_textbox_destroy(struct rtgui_textbox* box); + +rt_bool_t rtgui_textbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event); + +void rtgui_textbox_set_value(struct rtgui_textbox* box, const char* text); +const char* rtgui_textbox_get_value(struct rtgui_textbox* box); + +void rtgui_widget_set_line_length(struct rtgui_textbox* box, rt_size_t length); + +#endif diff --git a/rtgui/include/rtgui/widgets/title.h b/rtgui/include/rtgui/widgets/title.h new file mode 100644 index 0000000000000000000000000000000000000000..0eda0f16a46439a0cbb393e5eafd4a288ce998bd --- /dev/null +++ b/rtgui/include/rtgui/widgets/title.h @@ -0,0 +1,45 @@ +/* + * File : title.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_TITLE__ +#define __RTGUI_TITLE__ + +#include + +/** Gets the type of a top win */ +#define RTGUI_WINTITLE_TYPE (rtgui_wintitle_type_get()) +/** Casts the object to an rtgui_wintitle */ +#define RTGUI_WINTITLE(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_WINTITLE_TYPE, rtgui_wintitle_t)) +/** Checks if the object is an rtgui_wintitle */ +#define RTGUI_IS_WINTITLE(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_WINTITLE_TYPE)) + +struct rtgui_wintitle +{ + struct rtgui_toplevel parent; + + /* title */ + rt_uint8_t* title; +}; +typedef struct rtgui_wintitle rtgui_wintitle_t; + +rtgui_type_t* rtgui_wintitle_type_get(void); + +rtgui_wintitle_t* rtgui_wintitle_create(const rt_uint8_t* title); +void rtgui_wintitle_destroy(rtgui_wintitle_t* wintitle); + +rt_bool_t rtgui_wintile_event_handler(rtgui_widget_t* widget, rtgui_event_t* event); + +void rtgui_wintitle_set_title(rtgui_wintitle_t* wintitle, const rt_uint8_t* title); +rt_uint8_t *rtgui_wintitle_get_title(rtgui_wintitle_t* wintitle); + +#endif diff --git a/rtgui/include/rtgui/widgets/toplevel.h b/rtgui/include/rtgui/widgets/toplevel.h new file mode 100644 index 0000000000000000000000000000000000000000..044edf4058cf43e92a89648ee93c20be094b5cdf --- /dev/null +++ b/rtgui/include/rtgui/widgets/toplevel.h @@ -0,0 +1,57 @@ +/* + * File : toplevel.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_TOPLEVEL_H__ +#define __RTGUI_TOPLEVEL_H__ + +#include + +/** Gets the type of a toplevel */ +#define RTGUI_TOPLEVEL_TYPE (rtgui_toplevel_type_get()) +/** Casts the object to an rtgui_toplevel */ +#define RTGUI_TOPLEVEL(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_TOPLEVEL_TYPE, rtgui_toplevel_t)) +/** Checks if the object is an rtgui_toplevel */ +#define RTGUI_IS_TOPLEVEL(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_TOPLEVEL_TYPE)) + +struct rtgui_toplevel +{ + /* inherit from container */ + rtgui_container_t parent; + + /* drawing count */ + rt_base_t drawing; + + /* external clip info */ + rtgui_rect_t* external_clip_rect; + rt_uint32_t external_clip_size; + + /* server thread id */ + rt_thread_t server; + + /* current focus widget */ + rtgui_widget_t* focus; +}; +typedef struct rtgui_toplevel rtgui_toplevel_t; + +rtgui_type_t *rtgui_toplevel_type_get(void); + +rt_bool_t rtgui_toplevel_event_handler(rtgui_widget_t* widget, rtgui_event_t* event); + +void rtgui_toplevel_handle_clip(struct rtgui_toplevel* top, + struct rtgui_event_clip_info* info); +void rtgui_toplevel_update_clip(rtgui_toplevel_t* top); + +void rtgui_toplevel_set_focus(struct rtgui_toplevel* top, rtgui_widget_t* focus); +rtgui_widget_t* rtgui_toplevel_get_focus(struct rtgui_toplevel* top); + +#endif diff --git a/rtgui/include/rtgui/widgets/view.h b/rtgui/include/rtgui/widgets/view.h new file mode 100644 index 0000000000000000000000000000000000000000..3dd6c43e639432d854ea83e126d13d4046118b7e --- /dev/null +++ b/rtgui/include/rtgui/widgets/view.h @@ -0,0 +1,61 @@ +/* + * File : view.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_VIEW_H__ +#define __RTGUI_VIEW_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Gets the type of a view */ +#define RTGUI_VIEW_TYPE (rtgui_view_type_get()) +/** Casts the object to an rtgui_view */ +#define RTGUI_VIEW(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_VIEW_TYPE, rtgui_view_t)) +/** Checks if the object is an rtgui_view */ +#define RTGUI_IS_VIEW(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_VIEW_TYPE)) + +/* + * the view widget + */ +struct rtgui_view +{ + /* inherit from container */ + struct rtgui_container parent; + + /* private field */ + char* title; +}; +typedef struct rtgui_view rtgui_view_t; + +rtgui_view_t* rtgui_view_create(const char* title); +void rtgui_view_destroy(rtgui_view_t* view); + +rt_bool_t rtgui_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event); + +void rtgui_view_set_box(rtgui_view_t* view, rtgui_box_t* box); + +void rtgui_view_show(rtgui_view_t* view); +void rtgui_view_hide(rtgui_view_t* view); + +char* rtgui_view_get_title(rtgui_view_t* view); +void rtgui_view_set_title(rtgui_view_t* view, const char* title); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rtgui/server/mouse.c b/rtgui/server/mouse.c new file mode 100644 index 0000000000000000000000000000000000000000..2432073a3ef445cd5703f1b8621fd88dc14536aa --- /dev/null +++ b/rtgui/server/mouse.c @@ -0,0 +1,629 @@ +/* + * File : mouse.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ + +#include "mouse.h" +#include +#include +#include + +struct rtgui_cursor +{ + /* screen byte per pixel */ + rt_uint16_t bpp; + + /* screen pitch */ + rt_uint16_t screen_pitch; + + /* current cursor x and y */ + rt_uint16_t cx, cy; + +#ifdef RTGUI_USING_MOUSE_CURSOR + /* cursor pitch */ + rt_uint16_t cursor_pitch; + + /* show cursor and show cursor count */ + rt_bool_t show_cursor; + rt_base_t show_cursor_count; + + /* cursor rect info */ + rtgui_rect_t rect; + + /* cursor image and saved cursor */ + rtgui_image_t *cursor_image; + rt_uint8_t *cursor_saved; +#endif + + /* move window rect and border */ + struct rtgui_topwin *topwin; + rtgui_rect_t win_rect; + rt_uint8_t *win_left, *win_right; + rt_uint8_t *win_top, *win_bottom; + rt_bool_t win_rect_show, win_rect_has_saved; + + /* screen framebuffer */ + rt_uint8_t* framebuffer; +}; + +struct rtgui_cursor* _rtgui_cursor; + +#ifdef RTGUI_USING_MOUSE_CURSOR +struct rt_mutex cursor_mutex; +static const rt_uint8_t * cursor_xpm[] = { + "16 16 35 1", + " c None", + ". c #A0B8D0", + "+ c #F0F0F0", + "@ c #FFFFFF", + "# c #F0F8F0", + "$ c #A0B0D0", + "% c #90A8C0", + "& c #A0B0C0", + "* c #E0E8F0", + "= c #8090B0", + "- c #D0D8E0", + "; c #7080A0", + "> c #90A0B0", + ", c #FFF8FF", + "' c #F0F8FF", + ") c #607090", + "! c #8098B0", + "~ c #405060", + "{ c #405070", + "] c #506070", + "^ c #607080", + "/ c #708090", + "( c #7088A0", + "_ c #D0D0E0", + ": c #607890", + "< c #C0D0E0", + "[ c #C0C8D0", + "} c #506880", + "| c #5F778F", + "1 c #D0D8F0", + "2 c #506080", + "3 c #C0C8E0", + "4 c #A0A8C0", + "5 c #405870", + "6 c #5F6F8F", + " . ", + " .. ", + " .+. ", + " .@#$ ", + " $@@+% ", + " &@@@*= ", + " %@@@@-; ", + " >@@,''-) ", + " !,''+)~{] ", + " ='-^*/ ", + " (_{:<[^ ", + " ;} |:12 ", + " / )345 ", + " 6}${ ", + " 5{ ", + " "}; + +static void rtgui_cursor_restore (void); +static void rtgui_cursor_save (void); +static void rtgui_cursor_show (void); +#endif + +static void rtgui_winrect_restore (void); +static void rtgui_winrect_save (void); +static void rtgui_winrect_show (void); + +#define WIN_MOVE_BORDER 4 +void rtgui_mouse_init() +{ + struct rtgui_graphic_driver* gd = rtgui_graphic_driver_get_default(); + + _rtgui_cursor = (struct rtgui_cursor*) rtgui_malloc(sizeof(struct rtgui_cursor)); + rt_memset(_rtgui_cursor, 0, sizeof(struct rtgui_cursor)); + +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_init(&cursor_mutex, "cursor", RT_IPC_FLAG_FIFO); +#endif + + /* init cursor */ + _rtgui_cursor->bpp = gd->byte_per_pixel; + _rtgui_cursor->framebuffer = gd->get_framebuffer(); + _rtgui_cursor->screen_pitch = _rtgui_cursor->bpp * gd->width; + +#ifdef RTGUI_USING_MOUSE_CURSOR + /* init cursor image */ + _rtgui_cursor->cursor_image = rtgui_image_create_from_mem("xpm", cursor_xpm, sizeof(cursor_xpm)); + if (_rtgui_cursor->cursor_image == RT_NULL) + { + rtgui_free(_rtgui_cursor); + _rtgui_cursor = RT_NULL; + + return; + } + + /* init rect */ + _rtgui_cursor->rect.x1 = _rtgui_cursor->rect.y1 = 0; + _rtgui_cursor->rect.x2 = _rtgui_cursor->cursor_image->w; + _rtgui_cursor->rect.y2 = _rtgui_cursor->cursor_image->h; + + _rtgui_cursor->cursor_pitch = _rtgui_cursor->cursor_image->w * _rtgui_cursor->bpp; + + _rtgui_cursor->show_cursor = RT_TRUE; + _rtgui_cursor->show_cursor_count = 0; + _rtgui_cursor->cursor_saved = rtgui_malloc(_rtgui_cursor->cursor_image->w * + _rtgui_cursor->cursor_image->h * _rtgui_cursor->bpp); +#endif + + /* init window move save image */ + _rtgui_cursor->win_rect_has_saved = RT_FALSE; + _rtgui_cursor->win_rect_show = RT_FALSE; + + _rtgui_cursor->win_left = rtgui_malloc(_rtgui_cursor->bpp * gd->height * WIN_MOVE_BORDER); + _rtgui_cursor->win_right = rtgui_malloc(_rtgui_cursor->bpp * gd->height * WIN_MOVE_BORDER); + _rtgui_cursor->win_top = rtgui_malloc(_rtgui_cursor->bpp * gd->width * WIN_MOVE_BORDER); + _rtgui_cursor->win_bottom = rtgui_malloc(_rtgui_cursor->bpp * gd->width * WIN_MOVE_BORDER); +} + +void rtgui_mouse_moveto(int x, int y) +{ +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER); +#endif + + if (x != _rtgui_cursor->cx || + y != _rtgui_cursor->cy) + { + if (_rtgui_cursor->win_rect_show) + { + if (_rtgui_cursor->win_rect_has_saved == RT_TRUE) + { + rtgui_winrect_restore(); + } + +#ifdef RTGUI_USING_MOUSE_CURSOR + rtgui_mouse_hide_cursor(); +#endif + + /* move winrect */ + rtgui_rect_moveto(&(_rtgui_cursor->win_rect), x - _rtgui_cursor->cx, + y - _rtgui_cursor->cy); + rtgui_winrect_save(); + + /* move current cursor */ + _rtgui_cursor->cx = x; + _rtgui_cursor->cy = y; + +#ifdef RTGUI_USING_MOUSE_CURSOR + /* show cursor */ + rtgui_mouse_show_cursor(); +#endif + /* show winrect */ + rtgui_winrect_show(); + } + else + { +#ifdef RTGUI_USING_MOUSE_CURSOR + rtgui_mouse_hide_cursor(); +#endif + /* move current cursor */ + _rtgui_cursor->cx = x; + _rtgui_cursor->cy = y; + +#ifdef RTGUI_USING_MOUSE_CURSOR + /* show cursor */ + rtgui_mouse_show_cursor(); +#endif + } + } + +#ifdef RTGUI_USING_MOUSE_CURSOR + rt_mutex_release(&cursor_mutex); +#endif +} + +#ifdef RTGUI_USING_MOUSE_CURSOR +void rtgui_mouse_set_cursor_enable(rt_bool_t enable) +{ + _rtgui_cursor->show_cursor = enable; +} + +/* set current cursor image */ +void rtgui_mouse_set_cursor(rtgui_image_t* cursor) +{ +} + +void rtgui_mouse_get_cursor_rect(rtgui_rect_t* rect) +{ + if (rect != RT_NULL) + { + *rect = _rtgui_cursor->rect; + } +} + +void rtgui_mouse_show_cursor() +{ + if (_rtgui_cursor->show_cursor == RT_FALSE) + return; + + _rtgui_cursor->show_cursor_count ++; + if (_rtgui_cursor->show_cursor_count == 1) + { + /* save show mouse area */ + rtgui_cursor_save(); + + /* show mouse cursor */ + rtgui_cursor_show(); + } +} + +void rtgui_mouse_hide_cursor() +{ + if (_rtgui_cursor->show_cursor == RT_FALSE) + return; + + if (_rtgui_cursor->show_cursor_count == 1) + { + /* display the cursor coverage area */ + rtgui_cursor_restore(); + } + _rtgui_cursor->show_cursor_count --; +} + +rt_bool_t rtgui_mouse_is_intersect(rtgui_rect_t* r) +{ + return rtgui_rect_is_intersect(&(_rtgui_cursor->rect), r) == RT_EOK? RT_TRUE : RT_FALSE; +} + +/* display the saved cursor area to screen */ +static void rtgui_cursor_restore() +{ + rt_base_t idx, height, cursor_pitch; + rt_uint8_t *cursor_ptr, *fb_ptr; + + fb_ptr = _rtgui_cursor->framebuffer + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch + + _rtgui_cursor->cx * _rtgui_cursor->bpp; + cursor_ptr = _rtgui_cursor->cursor_saved; + + height = (_rtgui_cursor->cy + _rtgui_cursor->cursor_image->h < + rtgui_graphic_driver_get_default()->height)? _rtgui_cursor->cursor_image->h : + rtgui_graphic_driver_get_default()->height - _rtgui_cursor->cy; + + cursor_pitch = (_rtgui_cursor->cx + _rtgui_cursor->cursor_image->w < + rtgui_graphic_driver_get_default()->width)? _rtgui_cursor->cursor_pitch : + (rtgui_graphic_driver_get_default()->width - _rtgui_cursor->cx) * _rtgui_cursor->bpp; + + for (idx = 0; idx < height; idx ++) + { + rt_memcpy(fb_ptr, cursor_ptr, cursor_pitch); + + fb_ptr += _rtgui_cursor->screen_pitch; + cursor_ptr += _rtgui_cursor->cursor_pitch; + } +} + +/* save the cursor coverage area from screen */ +static void rtgui_cursor_save() +{ + rt_base_t idx, height, cursor_pitch; + rt_uint8_t *cursor_ptr, *fb_ptr; + + fb_ptr = _rtgui_cursor->framebuffer + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch + + _rtgui_cursor->cx * _rtgui_cursor->bpp; + cursor_ptr = _rtgui_cursor->cursor_saved; + + height = (_rtgui_cursor->cy + _rtgui_cursor->cursor_image->h < + rtgui_graphic_driver_get_default()->height)? _rtgui_cursor->cursor_image->h : + rtgui_graphic_driver_get_default()->height - _rtgui_cursor->cy; + + cursor_pitch = (_rtgui_cursor->cx + _rtgui_cursor->cursor_image->w < + rtgui_graphic_driver_get_default()->width)? _rtgui_cursor->cursor_pitch : + (rtgui_graphic_driver_get_default()->width - _rtgui_cursor->cx) * _rtgui_cursor->bpp; + + for (idx = 0; idx < height; idx ++) + { + rt_memcpy(cursor_ptr, fb_ptr, cursor_pitch); + + fb_ptr += _rtgui_cursor->screen_pitch; + cursor_ptr += _rtgui_cursor->cursor_pitch; + } +} + +static void rtgui_cursor_show() +{ + rt_uint16_t x, y; + rtgui_color_t* ptr; + rtgui_rect_t rect; + void (*set_pixel) (rtgui_color_t *c, rt_uint16_t x, rt_uint16_t y); + + ptr = (rtgui_color_t*) _rtgui_cursor->cursor_image->data; + set_pixel = rtgui_graphic_driver_get_default()->set_pixel; + + rtgui_mouse_get_cursor_rect(&rect); + rtgui_rect_moveto(&rect, _rtgui_cursor->cx, _rtgui_cursor->cy); + + /* draw each point */ + for (y = rect.y1; y < rect.y2; y ++) + { + for (x = rect.x1; x < rect.x2; x++) + { + /* not alpha */ + if ((*ptr >> 24) != 255) + { + set_pixel(ptr, x, y); + } + + /* move to next color buffer */ + ptr ++; + } + } + + /* update rect */ + rtgui_graphic_driver_get_default()->screen_update(&rect); +} +#endif + +void rtgui_winrect_set(struct rtgui_topwin* topwin) +{ + /* set win rect show */ + _rtgui_cursor->win_rect_show = RT_TRUE; + + /* set win rect */ + _rtgui_cursor->win_rect = topwin->title == RT_NULL? topwin->extent : RTGUI_WIDGET(topwin->title)->extent; + _rtgui_cursor->topwin = topwin; +} + +rt_bool_t rtgui_winrect_moved_done(rtgui_rect_t* winrect, struct rtgui_topwin** topwin) +{ + rt_bool_t moved = RT_FALSE; + + /* no win rect */ + if (winrect == RT_NULL) return RT_FALSE; + + /* restore winrect */ + if (_rtgui_cursor->win_rect_has_saved) + { + rtgui_winrect_restore(); + + moved = RT_TRUE; + } + + /* clear win rect show */ + _rtgui_cursor->win_rect_show = RT_FALSE; + _rtgui_cursor->win_rect_has_saved = RT_FALSE; + + /* return win rect */ + *winrect = _rtgui_cursor->win_rect; + *topwin = _rtgui_cursor->topwin; + + return moved; +} + +rt_bool_t rtgui_winrect_is_moved() +{ + return _rtgui_cursor->win_rect_show; +} + +/* show winrect */ +static void rtgui_winrect_show() +{ + rt_uint16_t x, y; + rtgui_color_t c; + rtgui_rect_t screen_rect, win_rect, win_rect_inner; + void (*set_pixel) (rtgui_color_t *c, rt_base_t x, rt_base_t y); + + c = black; + set_pixel = rtgui_graphic_driver_get_default()->set_pixel; + + win_rect = _rtgui_cursor->win_rect; + win_rect_inner = win_rect; + rtgui_rect_inflate(&win_rect_inner, -WIN_MOVE_BORDER); + + rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), + &screen_rect); + rtgui_rect_intersect(&screen_rect, &win_rect); + rtgui_rect_intersect(&screen_rect, &win_rect_inner); + + /* draw left */ + for (y = win_rect.y1; y < win_rect.y2; y ++) + { + for (x = win_rect.x1; x < win_rect_inner.x1; x++) + if ((x + y) & 0x01) set_pixel(&c, x, y); + } + + /* draw right */ + for (y = win_rect.y1; y < win_rect.y2; y ++) + { + for (x = win_rect_inner.x2; x < win_rect.x2; x++) + if ((x + y) & 0x01) set_pixel(&c, x, y); + } + + /* draw top border */ + for (y = win_rect.y1; y < win_rect_inner.y1; y ++) + { + for (x = win_rect_inner.x1; x < win_rect_inner.x2; x++) + if ((x + y) & 0x01) set_pixel(&c, x, y); + } + + /* draw bottom border */ + for (y = win_rect_inner.y2; y < win_rect.y2; y ++) + { + for (x = win_rect_inner.x1; x < win_rect_inner.x2; x++) + if ((x + y) & 0x01) set_pixel(&c, x, y); + } + + /* update rect */ + rtgui_graphic_driver_get_default()->screen_update(&win_rect); +} + +#define display_direct_memcpy(src, dest, src_pitch, dest_pitch, height, len) \ + for (idx = 0; idx < height; idx ++) \ + { \ + rt_memcpy(dest, src, len); \ + src += src_pitch; \ + dest += dest_pitch; \ + } + +static void rtgui_winrect_restore() +{ + rt_uint8_t *winrect_ptr, *fb_ptr; + int winrect_pitch, idx; + rtgui_rect_t screen_rect, win_rect; + + win_rect = _rtgui_cursor->win_rect; + + rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), + &screen_rect); + rtgui_rect_intersect(&screen_rect, &win_rect); + + /* restore winrect left */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + win_rect.x1 * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_left; + winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp; + display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch, + (win_rect.y2 - win_rect.y1), winrect_pitch); + + /* restore winrect right */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + (win_rect.x2 - WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_right; + winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp; + display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch, + (win_rect.y2 - win_rect.y1), winrect_pitch); + + /* restore winrect top */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + (win_rect.x1 + WIN_MOVE_BORDER)* _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_top; + winrect_pitch = (win_rect.x2 - win_rect.x1 - 2 * WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch, + WIN_MOVE_BORDER, winrect_pitch); + + /* restore winrect bottom */ + fb_ptr = _rtgui_cursor->framebuffer + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch + + (win_rect.x1 + WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_bottom; + display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch, + WIN_MOVE_BORDER, winrect_pitch); +} + +static void rtgui_winrect_save() +{ + rt_uint8_t *winrect_ptr, *fb_ptr; + int winrect_pitch, idx; + rtgui_rect_t screen_rect, win_rect; + + win_rect = _rtgui_cursor->win_rect; + + rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), + &screen_rect); + rtgui_rect_intersect(&screen_rect, &win_rect); + + /* set winrect has saved */ + _rtgui_cursor->win_rect_has_saved = RT_TRUE; + + /* save winrect left */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + win_rect.x1 * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_left; + winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp; + display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch, + (win_rect.y2 - win_rect.y1), winrect_pitch); + + /* save winrect right */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + (win_rect.x2 - WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_right; + winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp; + display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch, + (win_rect.y2 - win_rect.y1), winrect_pitch); + + /* save winrect top */ + fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch + + (win_rect.x1 + WIN_MOVE_BORDER)* _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_top; + winrect_pitch = (win_rect.x2 - win_rect.x1 - 2 * WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch, + WIN_MOVE_BORDER, winrect_pitch); + + /* save winrect bottom */ + fb_ptr = _rtgui_cursor->framebuffer + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch + + (win_rect.x1 + WIN_MOVE_BORDER) * _rtgui_cursor->bpp; + winrect_ptr = _rtgui_cursor->win_bottom; + display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch, + WIN_MOVE_BORDER, winrect_pitch); +} + +void rtgui_mouse_monitor_append(rtgui_list_t* head, rtgui_rect_t* rect) +{ + struct rtgui_mouse_monitor* mmonitor; + + /* check parameters */ + if (head == RT_NULL || rect == RT_NULL) return; + + /* create a mouse monitor node */ + mmonitor = (struct rtgui_mouse_monitor*) rtgui_malloc (sizeof(struct rtgui_mouse_monitor)); + if (mmonitor == RT_NULL) return; /* no memory */ + + /* set mouse monitor node */ + mmonitor->rect = *rect; + rtgui_list_init(&(mmonitor->list)); + + /* append to list */ + rtgui_list_append(head, &(mmonitor->list)); +} + +void rtgui_mouse_monitor_remove(rtgui_list_t* head, rtgui_rect_t* rect) +{ + struct rtgui_list_node* node; + struct rtgui_mouse_monitor* mmonitor; + + /* check parameters */ + if (head == RT_NULL || rect == RT_NULL) return; + + for (node = head->next; node != RT_NULL; node = node->next) + { + mmonitor = rtgui_list_entry(node, struct rtgui_mouse_monitor, list); + if (mmonitor->rect.x1 == rect->x1 && + mmonitor->rect.x2 == rect->x2 && + mmonitor->rect.y1 == rect->y1 && + mmonitor->rect.y2 == rect->y2) + { + /* found node */ + rtgui_list_remove(head, node); + rtgui_free(mmonitor); + + return ; + } + } +} + +rt_bool_t rtgui_mouse_monitor_contains_point(rtgui_list_t* head, int x, int y) +{ + struct rtgui_list_node* node; + + /* check parameter */ + if (head == RT_NULL) return RT_FALSE; + + rtgui_list_foreach(node, head) + { + struct rtgui_mouse_monitor* monitor = rtgui_list_entry(node, + struct rtgui_mouse_monitor, list); + + if (rtgui_rect_contains_point(&(monitor->rect), x, y) == RT_EOK) + { + return RT_TRUE; + } + } + + return RT_FALSE; +} diff --git a/rtgui/server/mouse.h b/rtgui/server/mouse.h new file mode 100644 index 0000000000000000000000000000000000000000..da6c16485e0c4404433ac45d2a1de74b91188de6 --- /dev/null +++ b/rtgui/server/mouse.h @@ -0,0 +1,51 @@ +/* + * File : mouse.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_MOUSE_H__ +#define __RTGUI_MOUSE_H__ + +#include +#include +#include "topwin.h" + +struct rtgui_mouse_monitor +{ + /* event rect */ + rtgui_rect_t rect; + + /* node list */ + rtgui_list_t list; +}; +typedef struct rtgui_mouse_monitor rtgui_mouse_monitor_t; + +void rtgui_mouse_init(void); +void rtgui_mouse_moveto(int x, int y); + +void rtgui_mouse_set_cursor_enable(rt_bool_t enable); +void rtgui_mouse_set_cursor(rtgui_image_t* cursor); +void rtgui_mouse_get_cursor_rect(rtgui_rect_t* rect); + +void rtgui_mouse_show_cursor(void); +void rtgui_mouse_hide_cursor(void); + +rt_bool_t rtgui_mouse_is_intersect(rtgui_rect_t* r); + +rt_bool_t rtgui_winrect_is_moved(void); +void rtgui_winrect_set(struct rtgui_topwin* topwin); +rt_bool_t rtgui_winrect_moved_done(rtgui_rect_t* winrect, struct rtgui_topwin** topwin); + +void rtgui_mouse_monitor_append(rtgui_list_t* head, rtgui_rect_t* rect); +void rtgui_mouse_monitor_remove(rtgui_list_t* head, rtgui_rect_t* rect); +rt_bool_t rtgui_mouse_monitor_contains_point(rtgui_list_t* head, int x, int y); + +#endif diff --git a/rtgui/server/panel.h b/rtgui/server/panel.h index a524ede6a44df38f4b59ad80e908249e0c8a2b39..c40f57a5fffb4dbb0a5fcf6067edb05e5a766ea3 100644 --- a/rtgui/server/panel.h +++ b/rtgui/server/panel.h @@ -49,10 +49,6 @@ struct rtgui_panel rt_thread_t wm_thread; }; -/* register or deregister panel in server */ -void rtgui_panel_register(char* name, rtgui_rect_t* extent); -void rtgui_panel_deregister(char* name); - /* find panel by name */ struct rtgui_panel* rtgui_panel_find(char* name); diff --git a/rtgui/server/server.c b/rtgui/server/server.c index 78040ab3440dedb25b344caac19a2e30168df1e7..eb5615d8f5ffbeb543ef826ee0ea247c5d7a0dc0 100644 --- a/rtgui/server/server.c +++ b/rtgui/server/server.c @@ -21,12 +21,6 @@ #include "panel.h" #include "topwin.h" -#define RTGUI_SVR_THREAD_PRIORITY 96 -#define RTGUI_SVR_THREAD_TIMESLICE 20 - -#define RTGUI_APP_THREAD_PRIORITY 220 -#define RTGUI_APP_THREAD_TIMESLICE 20 - static char rtgui_server_stack[2048]; static struct rt_thread rtgui_server_thread; diff --git a/rtgui/server/topwin.c b/rtgui/server/topwin.c new file mode 100644 index 0000000000000000000000000000000000000000..0deadae976a6cad7c63e9e21a3591a0f6f6b0d54 --- /dev/null +++ b/rtgui/server/topwin.c @@ -0,0 +1,868 @@ +/* + * File : topwin.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include "panel.h" +#include "topwin.h" +#include "mouse.h" + +#include +#include +#include +#include +#include + +struct rtgui_topwin* rtgui_server_focus_topwin = RT_NULL; + +static struct rtgui_list_node _rtgui_topwin_show_list; +static struct rtgui_list_node _rtgui_topwin_hide_list; + +static void rtgui_topwin_update_clip(void); +static void rtgui_topwin_redraw(struct rtgui_rect* rect); + +#define WINTITLE_CB_WIDTH 14 +#define WINTITLE_CB_HEIGHT 14 + +void rtgui_topwin_init() +{ + /* init window list */ + rtgui_list_init(&_rtgui_topwin_show_list); + rtgui_list_init(&_rtgui_topwin_hide_list); +} + +static struct rtgui_topwin* +rtgui_topwin_search_in_list(struct rtgui_win* wid, struct rtgui_list_node* list) +{ + struct rtgui_list_node* node; + struct rtgui_topwin* topwin; + + /* search in list */ + rtgui_list_foreach(node, list) + { + topwin = rtgui_list_entry(node, struct rtgui_topwin, list); + + /* is this node? */ + if (topwin->wid == wid) + { + return topwin; + } + } + + return RT_NULL; +} + +/* add a window to window list[hide] */ +rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event) +{ + struct rtgui_topwin* topwin; + + topwin = rtgui_malloc(sizeof(struct rtgui_topwin)); + if (topwin == RT_NULL) return -RT_ERROR; + + topwin->wid = event->wid; + topwin->extent = event->extent; + topwin->tid = event->parent.sender; + topwin->mask = event->mask; + + topwin->flag = 0; + if (event->flag & RTGUI_WIN_STYLE_NO_TITLE) topwin->flag |= WINTITLE_NO; + if (event->flag & RTGUI_WIN_STYLE_CLOSEBOX) topwin->flag |= WINTITLE_CLOSEBOX; + if (!(event->flag & RTGUI_WIN_STYLE_NO_BORDER)) topwin->flag |= WINTITLE_BORDER; + if (event->flag & RTGUI_WIN_STYLE_NO_FOCUS) topwin->flag |= WINTITLE_NOFOCUS; + + if(!(topwin->flag & WINTITLE_NO) || (topwin->flag & WINTITLE_BORDER)) + { + /* get win extent */ + rtgui_rect_t rect = topwin->extent; + + /* add border rect */ + if (topwin->flag & WINTITLE_BORDER) + { + rect.x1 -= WINTITLE_BORDER_SIZE; + rect.y1 -= WINTITLE_BORDER_SIZE; + rect.x2 += WINTITLE_BORDER_SIZE; + rect.y2 += WINTITLE_BORDER_SIZE; + } + + /* add title rect */ + if (!(topwin->flag & WINTITLE_NO)) rect.y1 -= WINTITLE_HEIGHT; + + topwin->title = rtgui_wintitle_create(event->title); + rtgui_widget_set_rect(RTGUI_WIDGET(topwin->title), &rect); + + /* update clip info */ + rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title)); + rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip), + &(RTGUI_WIDGET(topwin->title)->clip), + &(topwin->extent)); + } + else topwin->title = RT_NULL; + + rtgui_list_init(&topwin->list); + rtgui_list_init(&topwin->monitor_list); + + /* add topwin node to the hidden window list */ + rtgui_list_insert(&(_rtgui_topwin_hide_list), &(topwin->list)); + + return RT_EOK; +} + +rt_err_t rtgui_topwin_remove(struct rtgui_win* wid) +{ + struct rtgui_topwin* topwin; + + /* find the topwin node */ + topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list); + + if (topwin) + { + /* remove node from list */ + rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list)); + + rtgui_topwin_update_clip(); + + /* redraw the old rect */ + rtgui_topwin_redraw(&(topwin->extent)); + + if (rtgui_server_focus_topwin == topwin) + { + /* activate the next window */ + if (_rtgui_topwin_show_list.next != RT_NULL) + { + struct rtgui_event_win wevent; + struct rtgui_topwin* wnd; + + /* get the topwin */ + wnd = rtgui_list_entry(_rtgui_topwin_show_list.next, + struct rtgui_topwin, list); + + /* activate the window */ + RTGUI_EVENT_WIN_ACTIVATE_INIT(&wevent); + wevent.wid = wnd->wid; + rtgui_thread_send(wnd->tid, &(wevent.parent), sizeof(struct rtgui_event_win)); + + /* set new focus topwin */ + rtgui_server_focus_topwin = wnd; + } + else + { + /* there is no shown window right now */ + rtgui_server_focus_topwin = RT_NULL; + } + } + + /* free the monitor rect list, topwin node and title */ + while (topwin->monitor_list.next != RT_NULL) + { + struct rtgui_mouse_monitor* monitor = rtgui_list_entry(topwin->monitor_list.next, + struct rtgui_mouse_monitor, list); + + topwin->monitor_list.next = topwin->monitor_list.next->next; + rtgui_free(monitor); + } + + /* destroy win title */ + rtgui_wintitle_destroy(topwin->title); + topwin->title = RT_NULL; + + rtgui_free(topwin); + + return RT_EOK; + } + + topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list); + if (topwin) + { + /* remove node from list */ + rtgui_list_remove(&_rtgui_topwin_hide_list, &(topwin->list)); + + /* free the topwin node and title */ + rtgui_wintitle_destroy(topwin->title); + topwin->title = RT_NULL; + + rtgui_free(topwin); + + return RT_EOK; + } + + return -RT_ERROR; +} + +/* activate a win + * - deactivate the old focus win + * - activate a win + * - set the focus win to activate win + * - draw win title + */ +void rtgui_topwin_activate_win(struct rtgui_topwin* win) +{ + struct rtgui_event_win event; + + /* activate the raised window */ + RTGUI_EVENT_WIN_ACTIVATE_INIT(&event); + event.wid = win->wid; + rtgui_thread_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win)); + + /* redraw title */ + if (win->title != RT_NULL) + { + win->flag |= WINTITLE_ACTIVATE; + rtgui_theme_draw_win(win); + } + + if (rtgui_server_focus_topwin != RT_NULL) + { + /* deactivate the old focus win */ + RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event); + event.wid = rtgui_server_focus_topwin->wid; + rtgui_thread_send(rtgui_server_focus_topwin->tid, + &event.parent, sizeof(struct rtgui_event_win)); + + /* redraw title */ + if (rtgui_server_focus_topwin->title != RT_NULL) + { + rtgui_server_focus_topwin->flag &= ~WINTITLE_ACTIVATE; + rtgui_theme_draw_win(rtgui_server_focus_topwin); + } + } + + rtgui_server_focus_topwin = win; +} + +/* + * deactivate a win + * - deactivate the win + * - redraw win title + * - set rtgui_server_focus_topwin + */ +void rtgui_topwin_deactivate_win(struct rtgui_topwin* win) +{ + /* deactivate win */ + struct rtgui_event_win event; + RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event); + event.wid = win->wid; + rtgui_thread_send(win->tid, + &event.parent, sizeof(struct rtgui_event_win)); + + win->flag &= ~WINTITLE_ACTIVATE; + rtgui_theme_draw_win(win); + + if (rtgui_server_focus_topwin == win) + { + rtgui_server_focus_topwin = RT_NULL; + } +} + +/* raise window to front */ +void rtgui_topwin_raise(struct rtgui_win* wid, rt_thread_t sender) +{ + struct rtgui_topwin* topwin; + + /* find the topwin node */ + topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list); + if (topwin) + { + rt_int32_t count; + struct rtgui_list_node* node; + struct rtgui_event_clip_info* eclip; + struct rtgui_rect* rect; + + /* the window is already placed in front */ + if (&(topwin->list) == _rtgui_topwin_show_list.next) + { + rtgui_server_focus_topwin = RT_NULL; + rtgui_topwin_activate_win(topwin); + return ; + } + + /* update clip info */ + count = 0; + node = _rtgui_topwin_show_list.next; + while (node != &(topwin->list)) + { + count ++; + node = node->next; + } + + eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info) + + (count + 1)* sizeof(struct rtgui_rect)); + + /* reset clip info to top window */ + RTGUI_EVENT_CLIP_INFO_INIT(eclip); + eclip->num_rect = 0; + eclip->wid = topwin->wid; + /* send to destination window */ + rtgui_thread_send(topwin->tid, &(eclip->parent), sizeof(struct rtgui_event_clip_info)); + + /* reset clip info in title */ + rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(topwin->title), eclip); + rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title)); + rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip), + &(RTGUI_WIDGET(topwin->title)->clip), + &(topwin->extent)); + + rect = RTGUI_EVENT_GET_RECT(eclip, 0); + *rect = (topwin->title != RT_NULL)? RTGUI_WIDGET(topwin->title)->extent : topwin->extent; + + count = 1; + for (node = _rtgui_topwin_show_list.next; + node != &(topwin->list); + node = node->next) + { + struct rtgui_topwin* wnd; + wnd = rtgui_list_entry(node, struct rtgui_topwin, list); + + eclip->num_rect = count; + eclip->wid = wnd->wid; + + /* send to destination window */ + rtgui_thread_send(wnd->tid, &(eclip->parent), + sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect)); + + /* reset clip info in title */ + rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(wnd->title), eclip); + rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title)); + rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip), + &(RTGUI_WIDGET(wnd->title)->clip), + &(wnd->extent)); + + rect = RTGUI_EVENT_GET_RECT(eclip, count++); + *rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent; + } + + /* release clip info event */ + rtgui_free(eclip); + + /* remove node from list */ + rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list)); + /* add to front */ + rtgui_list_insert(&_rtgui_topwin_show_list, &(topwin->list)); + + rtgui_topwin_activate_win(topwin); + } +} + +/* show a window */ +void rtgui_topwin_show(struct rtgui_event_win* event) +{ + struct rtgui_topwin* topwin; + struct rtgui_win* wid = event->wid; + rt_thread_t sender = RTGUI_EVENT(event)->sender; + + /* find in hide list */ + topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list); + + /* find it */ + if (topwin != RT_NULL) + { + /* remove node from hidden list */ + rtgui_list_remove(&_rtgui_topwin_hide_list, &(topwin->list)); + + /* add node to show list */ + rtgui_list_insert(&_rtgui_topwin_show_list, &(topwin->list)); + + /* show window title */ + if (topwin->title != RT_NULL) + { + RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(topwin->title)); + } + + /* update clip info */ + rtgui_topwin_update_clip(); + + rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK); + + /* activate this window */ + rtgui_topwin_activate_win(topwin); + } + else + { + /* the wnd is located in show list, raise wnd to front */ + topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list); + if (topwin != RT_NULL) + { + if (_rtgui_topwin_show_list.next != &(topwin->list)) + { + rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK); + + /* not the front window, raise it */ + rtgui_topwin_raise(wid, sender); + } + } + else + { + /* there is no wnd in wnd list */ + rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR); + } + } +} + +/* send clip info to panel */ +void rtgui_topwin_update_clip_to_panel(struct rtgui_panel* panel) +{ + rt_uint32_t count; + rt_thread_t tid; + struct rtgui_list_node* node; + struct rtgui_event_clip_info* eclip; + + /* get topwin count */ + count = 0; + node = _rtgui_topwin_show_list.next; + while (node != RT_NULL) + { + count ++; + node = node->next; + } + + eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info) + + (count + 1)* sizeof(struct rtgui_rect)); + if (eclip == RT_NULL) + { + /* no memory */ + return ; + } + + /* reset clip info to top window */ + RTGUI_EVENT_CLIP_INFO_INIT(eclip); + eclip->num_rect = count; eclip->wid = RT_NULL; + + count = 0; + for (node = _rtgui_topwin_show_list.next; node != RT_NULL; node = node->next) + { + struct rtgui_topwin* wnd; + struct rtgui_rect* rect; + + wnd = rtgui_list_entry(node, struct rtgui_topwin, list); + + rect = RTGUI_EVENT_GET_RECT(eclip, count++); + *rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent; + } + + /* send to the activated thread of panel */ + tid = rtgui_panel_get_active_thread(panel); + rtgui_thread_send(tid, (struct rtgui_event*)eclip, sizeof(struct rtgui_event_clip_info) + + count* sizeof(struct rtgui_rect)); + + /* release clip info event */ + rtgui_free(eclip); +} + +/* hide a window */ +void rtgui_topwin_hide(struct rtgui_event_win* event) +{ + struct rtgui_topwin* topwin; + struct rtgui_win* wid = event->wid; + + /* find in show list */ + topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list); + + /* found it */ + if (topwin) + { + /* remove node from show list */ + rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list)); + + /* add node to hidden list */ + rtgui_list_insert(&_rtgui_topwin_hide_list, &(topwin->list)); + + /* show window title */ + if (topwin->title != RT_NULL) + { + RTGUI_WIDGET_HIDE(RTGUI_WIDGET(topwin->title)); + } + + /* update clip info */ + rtgui_topwin_update_clip(); + + /* redraw the old rect */ + rtgui_topwin_redraw(&(topwin->extent)); + + if (rtgui_server_focus_topwin == topwin) + { + /* activate the next window */ + if (_rtgui_topwin_show_list.next != RT_NULL) + { + /* get the topwin */ + topwin = rtgui_list_entry(_rtgui_topwin_show_list.next, + struct rtgui_topwin, list); + + rtgui_server_focus_topwin = RT_NULL; + rtgui_topwin_activate_win(topwin); + } + else + { + /* there is no shown window right now */ + rtgui_server_focus_topwin = RT_NULL; + } + } + } + else + { + rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR); + return; + } + + rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK); +} + +/* move top window */ +void rtgui_topwin_move(struct rtgui_event_win_move* event) +{ + struct rtgui_topwin* topwin; + + /* find in show list */ + topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_show_list); + if (topwin != RT_NULL) + { + int dx, dy; + rtgui_rect_t rect; /* the old topwin coverage area */ + struct rtgui_list_node* node; + + /* send status ok */ + rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK); + + /* get the delta move x, y */ + dx = event->x - topwin->extent.x1; + dy = event->y - topwin->extent.y1; + + rect = topwin->extent; + /* move window rect */ + rtgui_rect_moveto(&(topwin->extent), dx, dy); + + /* move window title */ + if (topwin->title != RT_NULL) + { + rect = RTGUI_WIDGET(topwin->title)->extent; + rtgui_widget_move_to_logic(RTGUI_WIDGET(topwin->title), dx, dy); + } + + /* move the monitor rect list */ + rtgui_list_foreach(node, &(topwin->monitor_list)) + { + struct rtgui_mouse_monitor* monitor = rtgui_list_entry(node, + struct rtgui_mouse_monitor, + list); + rtgui_rect_moveto(&(monitor->rect), dx, dy); + } + + /* update windows clip info */ + rtgui_topwin_update_clip(); + + /* update top window title */ + if (topwin->title != RT_NULL) rtgui_theme_draw_win(topwin); + if (rtgui_rect_is_intersect(&rect, &(topwin->extent)) != RT_EOK) + { + /* + * the old rect is not intersect with moved rect, + * re-paint window + */ + struct rtgui_event_paint epaint; + RTGUI_EVENT_PAINT_INIT(&epaint); + epaint.wid = topwin->wid; + rtgui_thread_send(topwin->tid, &(epaint.parent), sizeof(epaint)); + } + + /* update old window coverage area */ + rtgui_topwin_redraw(&rect); + } + else + { + rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR); + } +} + +/* + * resize a top win + * Note: currently, only support resize hidden window + */ +void rtgui_topwin_resize(struct rtgui_win* wid, rtgui_rect_t* r) +{ + struct rtgui_topwin* topwin; + + /* find in show list */ + topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list); + if (topwin) + { + topwin->extent = *r; + + if (topwin->title != RT_NULL) + { + /* get win extent */ + rtgui_rect_t rect = topwin->extent; + + /* add border rect */ + if (topwin->flag & WINTITLE_BORDER) + { + rect.x1 -= WINTITLE_BORDER_SIZE; + rect.y1 -= WINTITLE_BORDER_SIZE; + rect.x2 += WINTITLE_BORDER_SIZE; + rect.y2 += WINTITLE_BORDER_SIZE; + } + + /* add title rect */ + if (!(topwin->flag & WINTITLE_NO)) rect.y1 -= WINTITLE_HEIGHT; + + RTGUI_WIDGET(topwin->title)->extent = rect; + + /* update title & border clip info */ + rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title)); + rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip), + &(RTGUI_WIDGET(topwin->title)->clip), + &(topwin->extent)); + } + } +} + +struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y) +{ + struct rtgui_list_node* node; + struct rtgui_topwin* topwin; + + /* search in list */ + rtgui_list_foreach(node, &(_rtgui_topwin_show_list)) + { + topwin = rtgui_list_entry(node, struct rtgui_topwin, list); + + /* is this window? */ + if ((topwin->title != RT_NULL) && + rtgui_rect_contains_point(&(RTGUI_WIDGET(topwin->title)->extent), x, y) == RT_EOK) + { + return topwin; + } + else if (rtgui_rect_contains_point(&(topwin->extent), x, y) == RT_EOK) + { + return topwin; + } + } + + return RT_NULL; +} + +extern struct rtgui_list_node _rtgui_panel_list; +static void rtgui_topwin_update_clip() +{ + rt_int32_t count = 0; + struct rtgui_event_clip_info* eclip; + struct rtgui_list_node* node = _rtgui_topwin_show_list.next; + + /* calculate count */ + while (node != RT_NULL) + { + count ++; + node = node->next; + } + + eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info) + + count * sizeof(struct rtgui_rect)); + RTGUI_EVENT_CLIP_INFO_INIT(eclip); + + count = 0; + rtgui_list_foreach(node, &_rtgui_topwin_show_list) + { + struct rtgui_rect* rect; + struct rtgui_topwin* wnd; + wnd = rtgui_list_entry(node, struct rtgui_topwin, list); + + eclip->num_rect = count; + eclip->wid = wnd->wid; + + /* send to destination window */ + rtgui_thread_send(wnd->tid, &(eclip->parent), + sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect)); + + /* update clip in win title */ + if (wnd->title != RT_NULL) + { + /* reset clip info */ + rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(wnd->title), eclip); + rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title)); + rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip), + &(RTGUI_WIDGET(wnd->title)->clip), + &(wnd->extent)); + } + + rect = RTGUI_EVENT_GET_RECT(eclip, count++); + *rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent; + } + + /* send clip info to each panel */ + eclip->wid = RT_NULL; + eclip->num_rect = count; + + rtgui_list_foreach(node, &(_rtgui_panel_list)) + { + struct rtgui_panel* panel; + struct rtgui_list_node* panel_node; + + panel = rtgui_list_entry(node, struct rtgui_panel, sibling); + + rtgui_list_foreach(panel_node, &(panel->thread_list)) + { + struct rtgui_panel_thread* thread; + thread = rtgui_list_entry(panel_node, struct rtgui_panel_thread, list); + + /* send clip info to panel */ + rtgui_thread_send(thread->tid, &(eclip->parent), + sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect)); + } + } + + /* release clip info event */ + rtgui_free(eclip); +} + +static void rtgui_topwin_redraw(struct rtgui_rect* rect) +{ + struct rtgui_list_node* node; + struct rtgui_event_paint epaint; + RTGUI_EVENT_PAINT_INIT(&epaint); + + rtgui_list_foreach(node, &_rtgui_topwin_show_list) + { + struct rtgui_topwin* wnd = rtgui_list_entry(node, struct rtgui_topwin, list); + + if (rtgui_rect_is_intersect(rect, &(wnd->extent)) == RT_EOK) + { + /* draw window */ + epaint.wid = wnd->wid; + rtgui_thread_send(wnd->tid, &(epaint.parent), sizeof(epaint)); + + /* draw title */ + if (wnd->title != RT_NULL) + { + rtgui_theme_draw_win(wnd); + } + } + } + + /* redraw the panel */ + rtgui_list_foreach(node, &(_rtgui_panel_list)) + { + struct rtgui_panel* panel; + panel = rtgui_list_entry(node, struct rtgui_panel, sibling); + + if (rtgui_rect_is_intersect(rect, &(panel->extent)) == RT_EOK) + { + /* draw panel */ + epaint.wid = RT_NULL; + rtgui_thread_send(rtgui_panel_get_active_thread(panel), + &(epaint.parent), sizeof(epaint)); + } + } +} + +void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mouse* event) +{ + rtgui_rect_t rect; + + /* let window to process this mouse event */ + if (rtgui_rect_contains_point(&win->extent, event->x, event->y) == RT_EOK) + { + /* send mouse event to thread */ + rtgui_thread_send(win->tid, &(event->parent), sizeof(struct rtgui_event_mouse)); + return; + } + + /* get close button rect (device value) */ + rect.x1 = RTGUI_WIDGET(win->title)->extent.x2 - WINTITLE_BORDER_SIZE - WINTITLE_CB_WIDTH - 3; + rect.y1 = RTGUI_WIDGET(win->title)->extent.y1 + WINTITLE_BORDER_SIZE + 3; + rect.x2 = rect.x1 + WINTITLE_CB_WIDTH; + rect.y2 = rect.y1 + WINTITLE_CB_HEIGHT; + + if (event->button & RTGUI_MOUSE_BUTTON_LEFT) + { + if (event->button & RTGUI_MOUSE_BUTTON_DOWN) + { + if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK) + { + win->flag |= WINTITLE_CB_PRESSED; + rtgui_theme_draw_win(win); + } + else + { + /* maybe move window */ + rtgui_winrect_set(win); + } + } + else if (event->button & RTGUI_MOUSE_BUTTON_UP) + { + if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK) + { + struct rtgui_event_win event; + + win->flag &= ~WINTITLE_CB_PRESSED; + rtgui_theme_draw_win(win); + + /* send close event to window */ + RTGUI_EVENT_WIN_CLOSE_INIT(&event); + event.wid = win->wid; + rtgui_thread_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win)); + } + } + } +} + +void rtgui_topwin_append_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect) +{ + struct rtgui_topwin* win; + + /* parameters check */ + if (wid == RT_NULL || rect == RT_NULL) return; + + /* find topwin */ + win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list); + if (win == RT_NULL) + win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list); + + if (win == RT_NULL) return; + + /* append rect to top window monitor rect list */ + rtgui_mouse_monitor_append(&(win->monitor_list), rect); +} + +void rtgui_topwin_remove_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect) +{ + struct rtgui_topwin* win; + + /* parameters check */ + if (wid == RT_NULL || rect == RT_NULL) return; + + /* find topwin */ + win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list); + if (win == RT_NULL) + win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list); + + if (win == RT_NULL) return; + + /* remove rect from top window monitor rect list */ + rtgui_mouse_monitor_remove(&(win->monitor_list), rect); +} + +void rtgui_topwin_dump() +{ + struct rtgui_list_node* node; + + rtgui_list_foreach(node, &_rtgui_topwin_show_list) + { + struct rtgui_topwin* wnd = rtgui_list_entry(node, struct rtgui_topwin, list); + + rt_kprintf("wnd at (%d, %d) - (%d, %d)\n", + wnd->extent.x1, wnd->extent.y1, wnd->extent.x2, wnd->extent.y2); + + if (wnd->title != RT_NULL) + { + rt_kprintf("title[%s] border (%d, %d) - (%d, %d)\n", wnd->title->title, + RTGUI_WIDGET(wnd->title)->extent.x1, RTGUI_WIDGET(wnd->title)->extent.y1, + RTGUI_WIDGET(wnd->title)->extent.x2, RTGUI_WIDGET(wnd->title)->extent.y2); + } + } +} diff --git a/rtgui/server/topwin.h b/rtgui/server/topwin.h new file mode 100644 index 0000000000000000000000000000000000000000..64d0a8a767fb86caf2c8c875151279bc66d53b47 --- /dev/null +++ b/rtgui/server/topwin.h @@ -0,0 +1,56 @@ +/* + * File : topwin.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#ifndef __RTGUI_TOPWIN_H__ +#define __RTGUI_TOPWIN_H__ + +#include +#include +#include +#include +#include +#include + +/* add or remove a top win */ +rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event); +rt_err_t rtgui_topwin_remove(struct rtgui_win* wid); + +/* raise window to front */ +void rtgui_topwin_raise(struct rtgui_win* wid, rt_thread_t sender); +/* update clip info to a panel */ +void rtgui_topwin_update_clip_to_panel(struct rtgui_panel* panel); + +/* show a window */ +void rtgui_topwin_show(struct rtgui_event_win* event); +/* hide a window */ +void rtgui_topwin_hide(struct rtgui_event_win* event); +/* move a window */ +void rtgui_topwin_move(struct rtgui_event_win_move* event); +/* resize a window */ +void rtgui_topwin_resize(struct rtgui_win* wid, rtgui_rect_t* r); + +/* get window at (x, y) */ +struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y); + +void rtgui_topwin_activate_win(struct rtgui_topwin* win); +void rtgui_topwin_deactivate_win(struct rtgui_topwin* win); + +/* window title */ +void rtgui_topwin_title_ondraw(struct rtgui_topwin* win); +void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mouse* event); + +/* monitor rect */ +void rtgui_topwin_append_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect); +void rtgui_topwin_remove_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect); + +#endif diff --git a/rtgui/widgets/box.c b/rtgui/widgets/box.c new file mode 100644 index 0000000000000000000000000000000000000000..a9d16311c84d4b7e5768d43bc95da8f54e4e8b03 --- /dev/null +++ b/rtgui/widgets/box.c @@ -0,0 +1,340 @@ +/* + * File : box.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include + +static void _rtgui_box_constructor(rtgui_box_t *box) +{ + /* init widget and set event handler */ + rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_box_event_handler); + + RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT; + rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_box_event_handler); + + /* set proper of control */ + box->orientation = RTGUI_HORIZONTAL; + box->border_size = RTGUI_BORDER_DEFAULT_WIDTH; +} + +rtgui_type_t *rtgui_box_type_get(void) +{ + static rtgui_type_t *box_type = RT_NULL; + + if (!box_type) + { + box_type = rtgui_type_create("box", RTGUI_CONTAINER_TYPE, + sizeof(rtgui_box_t), RTGUI_CONSTRUCTOR(_rtgui_box_constructor), RT_NULL); + } + + return box_type; +} + +rt_bool_t rtgui_box_event_handler(rtgui_widget_t* widget, rtgui_event_t* event) +{ + struct rtgui_box* box = (struct rtgui_box*)widget; + + RT_ASSERT(box != RT_NULL); + + switch (event->type) + { + case RTGUI_EVENT_RESIZE: + /* re-layout */ + rtgui_box_layout(box); + break; + + default: + return rtgui_container_event_handler(RTGUI_WIDGET(box), event); + } + + return RT_FALSE; +} + +struct rtgui_box* rtgui_box_create(int orientation, rtgui_rect_t* rect) +{ + struct rtgui_box* box; + + box = (struct rtgui_box*) rtgui_widget_create (RTGUI_BOX_TYPE); + if (box != RT_NULL) + { + /* set proper of control */ + rtgui_widget_set_rect(RTGUI_WIDGET(box), rect); + box->orientation = orientation; + } + + return box; +} + +void rtgui_box_append(struct rtgui_box* box, rtgui_widget_t* widget) +{ + /* put to box's children list */ + rtgui_container_add_child(RTGUI_CONTAINER(box), widget); +} + +static void rtgui_box_layout_vertical(rtgui_box_t* box) +{ + rtgui_list_t *node; + rt_int32_t box_width; + rt_int32_t space_count; + rt_int32_t next_x, next_y; + rt_int32_t total_height, space_height; + struct rtgui_event_resize size_event; + + /* prepare the resize event */ + RTGUI_EVENT_RESIZE_INIT(&size_event); + + /* find spaces */ + space_count = 0; + total_height = 0; + space_height = 0; + + rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children)) + { + rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling); + if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++; + else total_height += widget->mini_height; + } + + /* calculate the height for each spaces */ + if (space_count != 0) + { + space_height = (rtgui_rect_height(RTGUI_WIDGET(box)->extent) - total_height - (box->border_size << 1)) / space_count; + } + + /* init (x, y) and box width */ + next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size; + next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size; + box_width = rtgui_rect_width(RTGUI_WIDGET(box)->extent) - (box->border_size << 1); + + /* layout each widget */ + rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children)) + { + rtgui_rect_t *rect; + rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling); + + /* get extent of widget */ + rect = &(widget->extent); + + /* reset rect */ + rtgui_rect_moveto(rect, -rect->x1, -rect->y1); + rect->x2 = widget->mini_width; + rect->y2 = widget->mini_height; + + /* left in default */ + rtgui_rect_moveto(rect, next_x, next_y); + + if (widget->align & RTGUI_ALIGN_EXPAND) + { + /* expand on horizontal */ + rect->x2 = rect->x1 + (rt_int16_t)box_width; + } + if (widget->align & RTGUI_ALIGN_CENTER_VERTICAL) + { + /* center */ + rt_uint32_t mid; + + mid = box_width - rtgui_rect_width(*rect); + mid = mid /2; + + rect->x1 = next_x + mid; + rect->x2 = next_x + box_width - mid; + } + else if (widget->align & RTGUI_ALIGN_RIGHT) + { + /* right */ + rect->x1 = next_x + box_width - rtgui_rect_width(*rect); + rect->x2 = next_x + box_width; + } + + if (widget->align & RTGUI_ALIGN_STRETCH) + { + rect->y2 = rect->y1 + space_height; + } + + /* process resize event */ + size_event.x = rect->x1; + size_event.y = rect->y1; + size_event.w = rect->x2 - rect->x1; + size_event.h = rect->y2 - rect->y1; + widget->event_handler(widget, &size_event.parent); + + /* point to next height */ + next_y = rect->y2; + } +} + +static void rtgui_box_layout_horizontal(rtgui_box_t* box) +{ + rtgui_list_t *node; + rt_int32_t box_height; + rt_int32_t space_count; + rt_int32_t next_x, next_y; + rt_int32_t total_width, space_width; + struct rtgui_event_resize size_event; + + /* prepare the resize event */ + RTGUI_EVENT_RESIZE_INIT(&size_event); + + /* find spaces */ + space_count = 0; + total_width = 0; + space_width = 0; + + rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children)) + { + rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling); + if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++; + else total_width += widget->mini_width; + } + + if (space_count != 0) + { + /* calculate the height for each spaces */ + space_width = (rtgui_rect_width(RTGUI_WIDGET(box)->extent) - total_width) / space_count; + } + + /* init (x, y) and box height */ + next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size; + next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size; + box_height = rtgui_rect_height(RTGUI_WIDGET(box)->extent) - (box->border_size << 1); + + /* layout each widget */ + rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children)) + { + rtgui_rect_t *rect; + rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling); + + /* get extent of widget */ + rect = &(widget->extent); + + /* reset rect */ + rtgui_rect_moveto(rect, -rect->x1, -rect->y1); + rect->x2 = widget->mini_width; + rect->y2 = widget->mini_height; + + /* top in default */ + rtgui_rect_moveto(rect, next_x, next_y); + + if (widget->align & RTGUI_ALIGN_EXPAND) + { + /* expand on vertical */ + rect->y2 = rect->y1 + box_height; + } + if (widget->align & RTGUI_ALIGN_CENTER_HORIZONTAL) + { + /* center */ + rt_uint32_t mid; + + mid = box_height - rtgui_rect_height(*rect); + mid = mid /2; + + rect->y1 = next_y + mid; + rect->y2 = next_y + box_height - mid; + } + else if (widget->align & RTGUI_ALIGN_RIGHT) + { + /* right */ + rect->y1 = next_y + box_height - rtgui_rect_height(*rect); + rect->y2 = next_y + box_height; + } + + if (widget->align & RTGUI_ALIGN_STRETCH) + { + rect->x2 = rect->x1 + space_width; + } + + /* process resize event */ + size_event.x = rect->x1; + size_event.y = rect->y1; + size_event.w = rect->x2 - rect->x1; + size_event.h = rect->y2 - rect->y1; + widget->event_handler(widget, &size_event.parent); + + /* point to next width */ + next_x = rect->x2; + } +} + +void rtgui_box_layout(rtgui_box_t* box) +{ + RT_ASSERT(box != RT_NULL); + + if (box->orientation & RTGUI_VERTICAL) + { + rtgui_box_layout_vertical(box); + } + else + { + rtgui_box_layout_horizontal(box); + } + + /* update box and its children clip */ + if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box))) + { + rtgui_widget_update_clip(RTGUI_WIDGET(box)); + } +} + +rt_uint32_t rtgui_box_get_width(rtgui_box_t* box) +{ + rtgui_list_t *node; + rt_uint32_t width; + + width = 0; + rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children)) + { + rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling); + rt_uint32_t widget_width; + + widget_width = rtgui_rect_width(widget->extent); + if (box->orientation & RTGUI_VERTICAL) + { + /* get the max width */ + if (width < widget_width) width = widget_width; + } + else + { + /* get the total width */ + width += widget_width; + } + } + + return width; +} + +rt_uint32_t rtgui_box_get_height(rtgui_box_t* box) +{ + rtgui_list_t *node; + rt_uint32_t height; + + height = 0; + rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children)) + { + rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling); + rt_uint32_t widget_height; + + widget_height = rtgui_rect_height(widget->extent); + if (box->orientation & RTGUI_HORIZONTAL) + { + /* get the max height */ + if (height < widget_height) height = widget_height; + } + else + { + /* get the total height */ + height += widget_height; + } + } + + return height; +} diff --git a/rtgui/widgets/button.c b/rtgui/widgets/button.c new file mode 100644 index 0000000000000000000000000000000000000000..877f7faed5601b60b972b89a5279321d4b6bc6e2 --- /dev/null +++ b/rtgui/widgets/button.c @@ -0,0 +1,170 @@ +/* + * File : button.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include +#include + +static void _rtgui_button_constructor(rtgui_button_t *button) +{ + /* init widget and set event handler */ + RTGUI_WIDGET(button)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + rtgui_widget_set_event_handler(RTGUI_WIDGET(button), rtgui_button_event_handler); + + /* un-press button */ + button->flag &= ~RTGUI_BUTTON_FLAG_PRESS; + + /* set flag and on_button event handler */ + button->pressed_image = RT_NULL; + button->unpressed_image = RT_NULL; + button->on_button = RT_NULL; + + /* set gc */ + RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(button)) = default_foreground; + RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(button)) = RTGUI_RGB(212, 208, 200); + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(button)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL; +} + +rtgui_type_t *rtgui_button_type_get(void) +{ + static rtgui_type_t *button_type = RT_NULL; + + if (!button_type) + { + button_type = rtgui_type_create("button", RTGUI_LABEL_TYPE, + sizeof(rtgui_button_t), RTGUI_CONSTRUCTOR(_rtgui_button_constructor), RT_NULL); + } + + return button_type; +} + +rt_bool_t rtgui_button_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +{ + struct rtgui_button* btn; + + RT_ASSERT(widget != RT_NULL); + + btn = (struct rtgui_button*) widget; + switch (event->type) + { + case RTGUI_EVENT_PAINT: + if (widget->on_draw != RT_NULL ) widget->on_draw(widget, event); + else rtgui_theme_draw_button(btn); + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + { + struct rtgui_event_mouse* emouse = (struct rtgui_event_mouse*)event; + + if (btn->flag & RTGUI_BUTTON_TYPE_PUSH) + { + /* it's a push button */ + if (emouse->button & RTGUI_MOUSE_BUTTON_UP) + { + if (btn->flag & RTGUI_BUTTON_FLAG_PRESS) + btn->flag &= ~RTGUI_BUTTON_FLAG_PRESS; + else + btn->flag |= RTGUI_BUTTON_FLAG_PRESS; + + /* draw button */ + if (widget->on_draw != RT_NULL ) widget->on_draw(widget, event); + else rtgui_theme_draw_button(btn); + + /* invokes call back */ + if (widget->on_mouseclick != RT_NULL && + emouse->button & RTGUI_MOUSE_BUTTON_UP) + return widget->on_mouseclick(widget, event); + } + } + else + { + if (emouse->button & RTGUI_MOUSE_BUTTON_LEFT) + { + /* it's a normal button */ + if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN) + { + btn->flag |= RTGUI_BUTTON_FLAG_PRESS; + } + else + { + btn->flag &= ~RTGUI_BUTTON_FLAG_PRESS; + } + + /* draw button */ + if (widget->on_draw != RT_NULL ) widget->on_draw(widget, event); + else rtgui_theme_draw_button(btn); + + /* invokes call back */ + if (widget->on_mouseclick != RT_NULL && + emouse->button & RTGUI_MOUSE_BUTTON_UP) + return widget->on_mouseclick(widget, event); + } + + } + + return RT_TRUE; + } + } + + return RT_FALSE; +} + +rtgui_button_t* rtgui_button_create(unsigned char* text) +{ + struct rtgui_button* btn; + + btn = (struct rtgui_button*) rtgui_widget_create (RTGUI_BUTTON_TYPE); + if (btn != RT_NULL) + { + rtgui_rect_t rect; + + /* set default rect */ + rtgui_font_get_metrics(rtgui_font_default(), text, &rect); + rect.x2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1); + rect.y2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1); + rtgui_widget_set_rect(RTGUI_WIDGET(btn), &rect); + rtgui_label_set_text(RTGUI_LABEL(btn), text); + } + + return btn; +} + +rtgui_button_t* rtgui_pushbutton_create(unsigned char* text) +{ + rtgui_button_t* btn; + + btn = rtgui_button_create(text); + if (btn != RT_NULL) btn->flag |= RTGUI_BUTTON_TYPE_PUSH; + + return btn; +} + +void rtgui_button_destroy(rtgui_button_t* btn) +{ + rtgui_widget_destroy(RTGUI_WIDGET(btn)); +} + +void rtgui_button_set_pressed_image(rtgui_button_t* btn, rtgui_image_t* image) +{ + RT_ASSERT(btn != RT_NULL); + + btn->pressed_image = image; +} + +void rtgui_button_set_unpressed_image(rtgui_button_t* btn, rtgui_image_t* image) +{ + RT_ASSERT(btn != RT_NULL); + + btn->unpressed_image = image; +} + diff --git a/rtgui/widgets/container.c b/rtgui/widgets/container.c new file mode 100644 index 0000000000000000000000000000000000000000..1a233807c6e1ee7a0a8e10b5a9601be6e9391821 --- /dev/null +++ b/rtgui/widgets/container.c @@ -0,0 +1,279 @@ +/* + * File : container.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include + +static void _rtgui_container_constructor(rtgui_container_t *container) +{ + /* set event handler and init field */ + rtgui_widget_set_event_handler(RTGUI_WIDGET(container), rtgui_container_event_handler); + rtgui_list_init(&(container->children)); +} + +static void _rtgui_container_destructor(rtgui_container_t *container) +{ + /* destroy children of container */ + rtgui_container_destroy_children(container); +} + +static void _rtgui_container_update_toplevel(rtgui_container_t* container) +{ + struct rtgui_list_node* node; + + rtgui_list_foreach(node, &(container->children)) + { + rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling); + /* set child toplevel */ + child->toplevel = rtgui_widget_get_toplevel(RTGUI_WIDGET(container)); + + if (RTGUI_IS_CONTAINER(child)) + { + _rtgui_container_update_toplevel(RTGUI_CONTAINER(child)); + } + } +} + +rtgui_type_t *rtgui_container_type_get(void) +{ + static rtgui_type_t *container_type = RT_NULL; + + if (!container_type) + { + container_type = rtgui_type_create("container", RTGUI_WIDGET_TYPE, + sizeof(rtgui_container_t), + RTGUI_CONSTRUCTOR(_rtgui_container_constructor), + RTGUI_DESTRUCTOR(_rtgui_container_destructor)); + } + + return container_type; +} + +rt_bool_t rtgui_container_dispatch_event(rtgui_container_t *container, rtgui_event_t* event) +{ + /* handle in child widget */ + struct rtgui_list_node* node; + + rtgui_list_foreach(node, &(container->children)) + { + struct rtgui_widget* w; + w = rtgui_list_entry(node, struct rtgui_widget, sibling); + + if (w->event_handler(w, event) == RT_TRUE) return RT_TRUE; + } + + return RT_FALSE; +} + +rt_bool_t rtgui_container_dispatch_mouse_event(rtgui_container_t *container, struct rtgui_event_mouse* event) +{ + /* handle in child widget */ + struct rtgui_list_node* node; + + rtgui_list_foreach(node, &(container->children)) + { + struct rtgui_widget* w; + w = rtgui_list_entry(node, struct rtgui_widget, sibling); + if (rtgui_rect_contains_point(&(w->extent), event->x, event->y) == RT_EOK) + { + if (w->event_handler(w, (rtgui_event_t*)event) == RT_TRUE) return RT_TRUE; + } + } + + return RT_FALSE; +} + +rt_bool_t rtgui_container_event_handler(rtgui_widget_t* widget, rtgui_event_t* event) +{ + rtgui_container_t *container = RTGUI_CONTAINER(widget); + + switch (event->type) + { + case RTGUI_EVENT_PAINT: + if (widget->on_draw != RT_NULL) + { + return widget->on_draw(widget, event); + } + + rtgui_container_dispatch_event(container, event); + break; + + case RTGUI_EVENT_KBD: + if (widget->on_key != RT_NULL) + { + return widget->on_key(widget, event); + } + else + { + /* let parent to handle keyboard event */ + if (widget->parent != RT_NULL && widget->parent != widget->toplevel) + { + return widget->parent->event_handler(widget->parent, event); + } + } + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + /* handle in child widget */ + if (rtgui_container_dispatch_mouse_event(container, + (struct rtgui_event_mouse*)event) == RT_FALSE) + { + /* handle event in current widget */ + if (widget->on_mouseclick != RT_NULL) + { + return widget->on_mouseclick(widget, event); + } + } + else return RT_TRUE; + break; + + case RTGUI_EVENT_MOUSE_MOTION: +#if 0 + if (rtgui_container_dispatch_mouse_event(container, + (struct rtgui_event_mouse*)event) == RT_FALSE) + { + /* handle event in current widget */ + if (widget->on_mousemotion != RT_NULL) + { + return widget->on_mousemotion(widget, event); + } + } + else return RT_TRUE; +#endif + break; + + case RTGUI_EVENT_COMMAND: + if (rtgui_container_dispatch_event(container, event) == RT_FALSE) + { + if (widget->on_command != RT_NULL) + { + return widget->on_command(widget, event); + } + } + else return RT_TRUE; + break; + + case RTGUI_EVENT_RESIZE: + if (rtgui_container_dispatch_event(container, event) == RT_FALSE) + { + if (widget->on_size != RT_NULL) + return widget->on_size(widget, event); + } + else return RT_TRUE; + break; + + default: + /* call parent widget event handler */ + return rtgui_widget_event_handler(widget, event); + } + + return RT_FALSE; +} + +/* + * This function will add a child to a container widget + * Note: this function will not change the widget layout + * the layout is the responsibility of layout widget, such as box. + */ +void rtgui_container_add_child(rtgui_container_t *container, rtgui_widget_t* child) +{ + RT_ASSERT(container != RT_NULL); + RT_ASSERT(child != RT_NULL); + + /* set parent and toplevel widget */ + child->parent = RTGUI_WIDGET(container); + /* put widget to parent's children list */ + rtgui_list_append(&(container->children), &(child->sibling)); + + /* update children toplevel */ + if (RTGUI_WIDGET(container)->toplevel != RT_NULL && + RTGUI_IS_TOPLEVEL(RTGUI_WIDGET(container)->toplevel)) + { + child->toplevel = rtgui_widget_get_toplevel(RTGUI_WIDGET(container)); + + /* update all child toplevel */ + if (RTGUI_IS_CONTAINER(child)) + { + _rtgui_container_update_toplevel(RTGUI_CONTAINER(child)); + } + } +} + +/* remove a child to widget */ +void rtgui_container_remove_child(rtgui_container_t *container, rtgui_widget_t* child) +{ + RT_ASSERT(container != RT_NULL); + RT_ASSERT(child != RT_NULL); + + /* remove widget from parent's children list */ + rtgui_list_remove(&(container->children), &(child->sibling)); + + /* set parent and toplevel widget */ + child->parent = RT_NULL; + child->toplevel = RT_NULL; +} + +/* destroy all children of container */ +void rtgui_container_destroy_children(rtgui_container_t *container) +{ + struct rtgui_list_node* node; + + if (container == RT_NULL) return; + + node = container->children.next; + while (node != RT_NULL) + { + rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling); + + if (RTGUI_IS_CONTAINER(child)) + { + /* destroy children of child */ + rtgui_container_destroy_children(RTGUI_CONTAINER(child)); + } + + /* destroy object and remove from parent */ + rtgui_object_destroy(RTGUI_OBJECT(child)); + + node = container->children.next; + } + + container->children.next = RT_NULL; + + /* update widget clip */ +#if 0 + rtgui_widget_update_clip(RTGUI_WIDGET(container)); +#else + /* update toplevel widget clip */ +#if 0 + { + rtgui_toplevel_t* top; + + top = RTGUI_TOPLEVEL(RTGUI_WIDGET(container)->toplevel); + if (RTGUI_IS_VIEW(top)) + } +#endif + rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(RTGUI_WIDGET(container)->toplevel)); +#endif +} + +rtgui_widget_t* rtgui_container_get_first_child(rtgui_container_t* container) +{ + rtgui_widget_t* child = RT_NULL; + + if (container->children.next != RT_NULL) + { + child = rtgui_list_entry(container->children.next, rtgui_widget_t, sibling); + } + + return child; +} diff --git a/rtgui/widgets/iconbox.c b/rtgui/widgets/iconbox.c new file mode 100644 index 0000000000000000000000000000000000000000..ffb81fc4937fd644e4968bd8c96f603f3e807148 --- /dev/null +++ b/rtgui/widgets/iconbox.c @@ -0,0 +1,154 @@ +/* + * File : iconbox.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include +#include + +static void _rtgui_iconbox_constructor(rtgui_iconbox_t *iconbox) +{ + /* init widget and set event handler */ + RTGUI_WIDGET(iconbox)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT; + rtgui_widget_set_event_handler(RTGUI_WIDGET(iconbox), rtgui_iconbox_event_handler); + + /* set proper of control */ + iconbox->image = RT_NULL; + iconbox->selected = RT_FALSE; + iconbox->text = RT_NULL; + iconbox->text_position = RTGUI_ICONBOX_TEXT_BELOW; +} + +rtgui_type_t *rtgui_iconbox_type_get(void) +{ + static rtgui_type_t *iconbox_type = RT_NULL; + + if (!iconbox_type) + { + iconbox_type = rtgui_type_create("iconbox", RTGUI_WIDGET_TYPE, + sizeof(rtgui_iconbox_t), RTGUI_CONSTRUCTOR(_rtgui_iconbox_constructor), RT_NULL); + } + + return iconbox_type; +} + +rt_bool_t rtgui_iconbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +{ + struct rtgui_iconbox* iconbox = (struct rtgui_iconbox*)widget; + + switch (event->type) + { + case RTGUI_EVENT_PAINT: + if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); + else + { + rtgui_theme_draw_iconbox(iconbox); + } + + break; + } + + return RT_FALSE; +} + +struct rtgui_iconbox* rtgui_iconbox_create(struct rtgui_image* image, + const unsigned char* text, + int position) +{ + struct rtgui_iconbox* iconbox; + + iconbox = (struct rtgui_iconbox*)rtgui_widget_create(RTGUI_ICONBOX_TYPE); + if (iconbox != RT_NULL) + { + rtgui_rect_t rect = {0, 0, 0, 0}, text_rect; + + rect.x2 = image->w; + rect.y2 = image->h; + + /* get text rect */ + rtgui_font_get_metrics(rtgui_font_default(), text, &text_rect); + if (position == RTGUI_ICONBOX_TEXT_BELOW) + { + rect.y2 += RTGUI_WIDGET_DEFAULT_MARGIN; + if (text_rect.x2 > rect.x2) + { + rect.x2 = text_rect.x2; + } + rect.y2 += text_rect.y2; + } + else if (position == RTGUI_ICONBOX_TEXT_RIGHT) + { + rect.x2 += RTGUI_WIDGET_DEFAULT_MARGIN; + if (text_rect.y2 > rect.y2) + { + rect.y2 = text_rect.y2; + } + rect.x2 += text_rect.x2; + } + + /* set widget rect */ + rtgui_widget_set_rect(RTGUI_WIDGET(iconbox), &rect); + + /* set image and text position */ + iconbox->image = image; + iconbox->text = (unsigned char*)rt_strdup((const char*)text); + iconbox->text_position = position; + } + + return iconbox; +} + +void rtgui_iconbox_destroy(struct rtgui_iconbox* iconbox) +{ + rtgui_widget_destroy(RTGUI_WIDGET(iconbox)); +} + +void rtgui_iconbox_set_text_position(struct rtgui_iconbox* iconbox, int position) +{ + rtgui_rect_t rect = {0, 0, 0, 0}, text_rect; + + RT_ASSERT(iconbox != RT_NULL); + + iconbox->text_position = position; + + /* set mini width and height */ + rect.x2 = iconbox->image->w; + rect.y2 = iconbox->image->h; + + /* get text rect */ + if (iconbox->text != RT_NULL) + { + rtgui_font_get_metrics(rtgui_font_default(), + iconbox->text, &text_rect); + if (position == RTGUI_ICONBOX_TEXT_BELOW) + { + rect.y2 += RTGUI_WIDGET_DEFAULT_MARGIN; + if (text_rect.x2 > rect.x2) + { + rect.x2 = text_rect.x2; + } + rect.y2 += text_rect.y2; + } + else if (position == RTGUI_ICONBOX_TEXT_RIGHT) + { + rect.x2 += RTGUI_WIDGET_DEFAULT_MARGIN; + if (text_rect.y2 > rect.y2) + { + rect.y2 = text_rect.y2; + } + rect.x2 += text_rect.x2; + } + } + + rtgui_widget_set_miniwidth(RTGUI_WIDGET(iconbox), rect.x2); + rtgui_widget_set_miniheight(RTGUI_WIDGET(iconbox), rect.y2); +} diff --git a/rtgui/widgets/label.c b/rtgui/widgets/label.c new file mode 100644 index 0000000000000000000000000000000000000000..e326bbf0d2dcdfda4bb0acceabea5b1e2b77905b --- /dev/null +++ b/rtgui/widgets/label.c @@ -0,0 +1,113 @@ +/* + * File : label.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include +#include +#include + +static void _rtgui_label_constructor(rtgui_label_t *label) +{ + /* init widget and set event handler */ + rtgui_widget_set_event_handler(RTGUI_WIDGET(label), rtgui_label_event_handler); + + /* set field */ + label->text = RT_NULL; +} + +static void _rtgui_label_destructor(rtgui_label_t *label) +{ + /* release text memory */ + rtgui_free(label->text); + label->text = RT_NULL; +} + +rtgui_type_t *rtgui_label_type_get(void) +{ + static rtgui_type_t *label_type = RT_NULL; + + if (!label_type) + { + label_type = rtgui_type_create("label", RTGUI_WIDGET_TYPE, + sizeof(rtgui_label_t), + RTGUI_CONSTRUCTOR(_rtgui_label_constructor), + RTGUI_DESTRUCTOR(_rtgui_label_destructor)); + } + + return label_type; +} + +rt_bool_t rtgui_label_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +{ + struct rtgui_label* label; + + RT_ASSERT(widget != RT_NULL); + + label = (struct rtgui_label*) widget; + switch (event->type) + { + case RTGUI_EVENT_PAINT: + rtgui_theme_draw_label(label); + break; + } + + return RT_FALSE; +} + +rtgui_label_t* rtgui_label_create(const unsigned char* text) +{ + struct rtgui_label* label; + + label = (struct rtgui_label*) rtgui_widget_create(RTGUI_LABEL_TYPE); + if (label != RT_NULL) + { + rtgui_rect_t rect; + + /* set default rect */ + rtgui_font_get_metrics(rtgui_font_default(), text, &rect); + rect.x2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1); + rect.y2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1); + rtgui_widget_set_rect(RTGUI_WIDGET(label), &rect); + + /* set text */ + label->text = (unsigned char*)rt_strdup((const char*)text); + } + + return label; +} + +void rtgui_label_destroy(rtgui_label_t* label) +{ + rtgui_widget_destroy(RTGUI_WIDGET(label)); +} + +unsigned char* rtgui_label_get_text(rtgui_label_t* label) +{ + RT_ASSERT(label != RT_NULL); + + return label->text; +} + +void rtgui_label_set_text(rtgui_label_t* label, const unsigned char* text) +{ + RT_ASSERT(label != RT_NULL); + + if (label->text != RT_NULL) + { + /* release old text memory */ + rtgui_free(label->text); + } + + if (text != RT_NULL) label->text = (unsigned char*)rt_strdup((const char*)text); + else label->text = RT_NULL; +} diff --git a/rtgui/widgets/textbox.c b/rtgui/widgets/textbox.c new file mode 100644 index 0000000000000000000000000000000000000000..a469bd65eea879e5dedd3f4714fa4299dbb26526 --- /dev/null +++ b/rtgui/widgets/textbox.c @@ -0,0 +1,346 @@ +/* + * File : textbox.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include +#include + +#define RTGUI_TEXTBOX_LINE_MAX 64 +#define RTGUI_TEXTBOX_MARGIN 3 + +static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kbd* event); +static rt_bool_t rtgui_textbox_onfocus(struct rtgui_widget* widget, struct rtgui_event* event); +static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_widget* widget, struct rtgui_event* event); + +static void _rtgui_textbox_constructor(rtgui_textbox_t *box) +{ + rtgui_rect_t rect = {0, 0, RTGUI_TEXTBOX_DEFAULT_WIDTH, RTGUI_TEXTBOX_DEFAULT_HEIGHT}; + rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect); + + RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE; + rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_textbox_event_handler); + rtgui_widget_set_onfocus(RTGUI_WIDGET(box), rtgui_textbox_onfocus); + rtgui_widget_set_onunfocus(RTGUI_WIDGET(box), rtgui_textbox_onunfocus); + + /* set default text align */ + RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_CENTER_VERTICAL; + + /* set proper of control */ + box->caret_x = box->caret_y = 0; + box->caret = rtgui_caret_create(RTGUI_WIDGET(box)); + + box->line = box->line_begin = box->position = 0; + box->type = RTGUI_TEXTBOX_SINGLE; + + /* allocate default line buffer */ + box->text = RT_NULL; + + rtgui_font_get_metrics(RTGUI_WIDGET(box)->gc.font, "h", &rect); + box->font_width = rtgui_rect_width(rect); +} + +static void _rtgui_textbox_deconstructor(rtgui_textbox_t *box) +{ + if (box->text != RT_NULL) + { + rtgui_free(box->text); + box->text = RT_NULL; + } + + if (box->caret != RT_NULL) + { + rtgui_caret_destroy(box->caret); + box->caret = RT_NULL; + } +} + +rtgui_type_t *rtgui_textbox_type_get(void) +{ + static rtgui_type_t *textbox_type = RT_NULL; + + if (!textbox_type) + { + textbox_type = rtgui_type_create("textbox", RTGUI_WIDGET_TYPE, + sizeof(rtgui_textbox_t), + RTGUI_CONSTRUCTOR(_rtgui_textbox_constructor), + RTGUI_DESTRUCTOR(_rtgui_textbox_deconstructor)); + } + + return textbox_type; +} + +static void rtgui_textbox_onmouse(struct rtgui_textbox* box, struct rtgui_event_mouse* event) +{ + rt_size_t length; + + RT_ASSERT(box != RT_NULL); + RT_ASSERT(event != RT_NULL); + + length = rt_strlen((const char*)box->text); + + if (event->button & RTGUI_MOUSE_BUTTON_LEFT && + event->button & RTGUI_MOUSE_BUTTON_DOWN) + { + rt_int32_t x; + + /* set caret position */ + x = event->x - RTGUI_WIDGET(box)->extent.x1; + if (x < 0) + { + box->position = 0; + } + else if (x > length * box->font_width) + { + box->position = length; + } + else + { + box->position = x / box->font_width; + } + + rtgui_caret_set_point(box->caret, RTGUI_TEXTBOX_MARGIN + box->position * box->font_width, 2); + rtgui_caret_set_box(box->caret, 2, rtgui_rect_height(RTGUI_WIDGET(box)->extent) - 4); + + /* set widget focus */ + rtgui_widget_focus(RTGUI_WIDGET(box)); + } +} + +static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kbd* event) +{ + rt_size_t length; + + RT_ASSERT(box != RT_NULL); + RT_ASSERT(event != RT_NULL); + + if (event->type != RTGUI_KEYDOWN) + return ; + + length = rt_strlen((const char*)box->text); + if (event->key == RTGUIK_DELETE) + { + if (box->position == length - 1) + { + box->text[box->position] = '\0'; + } + else + { + unsigned char *c; + + /* remove character */ + for (c = &box->text[box->position]; c[1] != '\0'; c++) + *c = c[1]; + *c = '\0'; + } + } + else if (event->key == RTGUIK_BACKSPACE) + { + if (box->position == length - 1) + { + box->text[box->position] = '\0'; + box->position --; + } + else if (box->position != 0) + { + /* remove current character */ + if (box->position != 0) + { + unsigned char *c; + + /* remove character */ + for (c = &box->text[box->position - 1]; c[1] != '\0'; c++) + *c = c[1]; + *c = '\0'; + } + box->position --; + } + } + else if (event->key == RTGUIK_LEFT) + { + if (box->position > 0) box->position --; + } + else if (event->key == RTGUIK_RIGHT) + { + if (box->position < length) box->position ++; + } + else if (event->key == RTGUIK_HOME) + { + box->position = 0; + } + else if (event->key == RTGUIK_END) + { + box->position = length; + } + else if (event->key == RTGUIK_RETURN) + { + if (box->on_enter != RT_NULL) + { + box->on_enter(RTGUI_WIDGET(box), RT_NULL); + } + } + else + { + if (isprint(event->key) || isdigit(event->key)) + { + /* no buffer on this line */ + if (length + 1 > box->line_length) return; + + if (box->position < length - 1) + { + unsigned char* c; + + for (c = &box->text[length]; c != &box->text[box->position]; c--) + *c = *(c-1); + box->text[length + 1] = '\0'; + } + + box->text[box->position] = event->key; + box->position ++; + } + } + + /* re-draw text box */ + rtgui_theme_draw_textbox(box); + rtgui_caret_set_point(box->caret, + RTGUI_TEXTBOX_MARGIN + box->position * box->font_width , 2); + rtgui_caret_set_box(box->caret, 2, rtgui_rect_height(RTGUI_WIDGET(box)->extent) - 4); +} + +static rt_bool_t rtgui_textbox_onfocus(struct rtgui_widget* widget, struct rtgui_event* event) +{ + struct rtgui_textbox* box = (struct rtgui_textbox*)widget; + + /* show caret */ + rtgui_caret_show(box->caret, box->caret_x, box->caret_y); + + return RT_TRUE; +} + +static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_widget* widget, struct rtgui_event* event) +{ + struct rtgui_textbox* box = (struct rtgui_textbox*)widget; + + /* hide caret */ + rtgui_caret_hide(box->caret); + + return RT_TRUE; +} + +rt_bool_t rtgui_textbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event) +{ + struct rtgui_textbox* box = (struct rtgui_textbox*)widget; + + switch (event->type) + { + case RTGUI_EVENT_PAINT: + if (widget->on_draw != RT_NULL) widget->on_draw(widget, event); + else rtgui_theme_draw_textbox(box); + break; + + case RTGUI_EVENT_MOUSE_BUTTON: + if (widget->on_mouseclick != RT_NULL) widget->on_mouseclick(widget, event); + else rtgui_textbox_onmouse(box, (struct rtgui_event_mouse*)event); + return RT_TRUE; + + case RTGUI_EVENT_KBD: + if (widget->on_key != RT_NULL) widget->on_key(widget, event); + else rtgui_textbox_onkey(box, (struct rtgui_event_kbd*)event); + return RT_TRUE; + } + + return RT_FALSE; +} + +struct rtgui_textbox* rtgui_textbox_create(const char* text) +{ + struct rtgui_textbox* box; + + box = (struct rtgui_textbox*) rtgui_widget_create (RTGUI_TEXTBOX_TYPE); + if (box != RT_NULL) + { + rtgui_rect_t rect = {0, 0, RTGUI_TEXTBOX_DEFAULT_WIDTH, RTGUI_TEXTBOX_DEFAULT_HEIGHT}; + + /* allocate default line buffer */ + rtgui_textbox_set_value(box, text); + + rtgui_font_get_metrics(RTGUI_WIDGET(box)->gc.font, "h", &rect); + box->font_width = rtgui_rect_width(rect); + } + + return box; +} + +void rtgui_textbox_destroy(struct rtgui_textbox* box) +{ + rtgui_widget_destroy(RTGUI_WIDGET(box)); +} + +void rtgui_textbox_set_value(struct rtgui_textbox* box, const char* text) +{ + if (box->text != RT_NULL) + { + if (box->line_length > rt_strlen(text) + 1) + { + rt_memcpy(box->text, text, rt_strlen(text) + 1); + return; + } + else + { + /* free the old text */ + rtgui_free(box->text); + box->text = RT_NULL; + } + } + + box->line_length = RTGUI_TEXTBOX_LINE_MAX > rt_strlen(text) + 1 ? + RTGUI_TEXTBOX_LINE_MAX : rt_strlen(text) + 1; + + /* allocate line buffer */ + box->text = rtgui_malloc(box->line_length); + rt_memset(box->text, 0, box->line_length); + + /* copy text */ + rt_memcpy(box->text, text, rt_strlen(text) + 1); + + /* set current position */ + box->position = 0; +} + +const char* rtgui_textbox_get_value(struct rtgui_textbox* box) +{ + return (const char*)box->text; +} + +void rtgui_widget_set_line_length(struct rtgui_textbox* box, rt_size_t length) +{ + rt_uint8_t* new_line; + + RT_ASSERT(box != RT_NULL); + + /* invalid length */ + if (length <= 0) return; + + new_line = rtgui_malloc(length); + if (length < box->line_length) + { + rt_memcpy(new_line, box->text, length - 1); + new_line[length] = '\0'; + } + else + { + rt_memcpy(new_line, (const char*)box->text, rt_strlen((const char*)box->text)); + } + + /* set line length */ + box->line_length = length; +} diff --git a/rtgui/widgets/title.c b/rtgui/widgets/title.c new file mode 100644 index 0000000000000000000000000000000000000000..1e96cd34ed26434e73e62c3cf0de749ca2711297 --- /dev/null +++ b/rtgui/widgets/title.c @@ -0,0 +1,73 @@ +/* + * File : title.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include + +/* there is no event handler in wintitle but handle the event on topwin of server */ +static void _rtgui_wintitle_constructor(rtgui_wintitle_t* wintitle) +{ + wintitle->title = RT_NULL; + RTGUI_WIDGET(wintitle)->flag = RTGUI_WIDGET_FLAG_DEFAULT; +} + +rtgui_type_t* rtgui_wintitle_type_get() +{ + static rtgui_type_t *wintitle_type = RT_NULL; + + if (!wintitle_type) + { + wintitle_type = rtgui_type_create("wintitle", RTGUI_TOPLEVEL_TYPE, + sizeof(rtgui_wintitle_t), RTGUI_CONSTRUCTOR(_rtgui_wintitle_constructor), RT_NULL); + } + + return wintitle_type; +} + +rtgui_wintitle_t* rtgui_wintitle_create(const rt_uint8_t* title) +{ + rtgui_wintitle_t* wintitle; + + wintitle = (rtgui_wintitle_t*)rtgui_widget_create(RTGUI_WINTITLE_TYPE); + if (wintitle != RT_NULL) + { + rtgui_wintitle_set_title(wintitle, title); + } + + return wintitle; +} + +void rtgui_wintitle_destroy(rtgui_wintitle_t* wintitle) +{ + rtgui_widget_destroy(RTGUI_WIDGET(wintitle)); +} + +void rtgui_wintitle_set_title(rtgui_wintitle_t* wintitle, const rt_uint8_t* title) +{ + RT_ASSERT(wintitle != RT_NULL); + + if (wintitle->title != RT_NULL) + { + rtgui_free(wintitle->title); + } + + if (title != RT_NULL) wintitle->title = (unsigned char*)rt_strdup((const char*)title); + else wintitle->title = RT_NULL; +} + +rt_uint8_t *rtgui_wintitle_get_title(rtgui_wintitle_t* wintitle) +{ + RT_ASSERT(wintitle != RT_NULL); + + return wintitle->title; +} diff --git a/rtgui/widgets/toplevel.c b/rtgui/widgets/toplevel.c new file mode 100644 index 0000000000000000000000000000000000000000..6823b66799ab466b61835b8177a0e63c1169235c --- /dev/null +++ b/rtgui/widgets/toplevel.c @@ -0,0 +1,191 @@ +/* + * File : toplevel.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include + +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 /* to get screen rect */ + +void rtgui_toplevel_update_clip(rtgui_toplevel_t* top) +{ + rt_uint32_t idx; + rtgui_container_t* container; + struct rtgui_list_node* node; + rtgui_rect_t screen_rect; + + if (top == RT_NULL) return; + + /* reset toplevel widget clip to extent */ + rtgui_region_reset(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->extent)); + RTGUI_WIDGET(top)->clip_sync ++; + + /* subtract the screen rect */ + screen_rect.x1 = screen_rect.y1 = 0; + screen_rect.x2 = rtgui_graphic_driver_get_default()->width; + screen_rect.y2 = rtgui_graphic_driver_get_default()->height; + rtgui_region_intersect_rect(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->clip), + &screen_rect); + + /* subtract the external rect */ + for (idx = 0; idx < top->external_clip_size; idx ++) + { + rtgui_region_subtract_rect(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->clip), + &(top->external_clip_rect[idx])); + } + + /* update the clip info of each child */ + container = RTGUI_CONTAINER(top); + rtgui_list_foreach(node, &(container->children)) + { + rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling); + + rtgui_widget_update_clip(child); + } +} + +void rtgui_toplevel_set_focus(struct rtgui_toplevel* top, rtgui_widget_t* focus) +{ + RT_ASSERT(top != RT_NULL); + + top->focus = focus; +} + +rtgui_widget_t* rtgui_toplevel_get_focus(struct rtgui_toplevel* top) +{ + RT_ASSERT(top != RT_NULL); + + return top->focus; +} + diff --git a/rtgui/widgets/view.c b/rtgui/widgets/view.c new file mode 100644 index 0000000000000000000000000000000000000000..d016515af9632cfa33f5dd32c35e6827d3f5cee9 --- /dev/null +++ b/rtgui/widgets/view.c @@ -0,0 +1,149 @@ +/* + * File : view.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-10-16 Bernard first version + */ +#include +#include +#include +#include + +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; + } +}