提交 a0e99e8a 编写于 作者: B bernard.xiong

add RTGUI source code

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@104 bbd45198-f89e-11dd-88c7-29a3b14d5316
上级 72adcb33
/*
* File : asc12font.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/font.h>
const rt_uint8_t asc12_font[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81,
0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff,
0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00,
0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c,
0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18,
0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3c,
0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99,
0xc3, 0xff, 0xff, 0xff, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00,
0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30,
0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67,
0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00,
0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x06, 0x0e, 0x1e, 0x3e,
0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c,
0x18, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00,
0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0xc6, 0x60, 0x38, 0x6c,
0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe,
0xfe, 0xfe, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00,
0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28,
0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe,
0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
0x10, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x28, 0x7c, 0x28, 0x7c, 0x28, 0x50, 0x50, 0x00, 0x00,
0x00, 0x10, 0x38, 0x40, 0x40, 0x38, 0x48, 0x70, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20, 0x50, 0x20,
0x0c, 0x70, 0x08, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x20, 0x20, 0x54, 0x48,
0x34, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x20, 0x20, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x10, 0x7c, 0x10, 0x28, 0x28, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0xfc, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x10, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, 0x00, 0x00,
0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10, 0x20, 0x44,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x18, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x14, 0x14, 0x24, 0x44, 0x7c, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x20, 0x20,
0x38, 0x04, 0x04, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x40, 0x78, 0x44, 0x44, 0x44,
0x38, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x44, 0x04, 0x08, 0x08, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00,
0x00, 0x38, 0x44, 0x44, 0x38, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44,
0x44, 0x3c, 0x04, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x30, 0x20, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x10, 0x60, 0x80, 0x60, 0x10, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x18, 0x04, 0x18, 0x20,
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x04, 0x08, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00,
0x38, 0x44, 0x44, 0x4c, 0x54, 0x54, 0x4c, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, 0x30, 0x10, 0x28,
0x28, 0x28, 0x7c, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x44, 0x44, 0x78, 0x44, 0x44, 0x44,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x40, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
0x00, 0xf0, 0x48, 0x44, 0x44, 0x44, 0x44, 0x48, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x44, 0x50,
0x70, 0x50, 0x40, 0x44, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x20, 0x28, 0x38, 0x28, 0x20, 0x20,
0x70, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x40, 0x40, 0x4c, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
0x00, 0xec, 0x44, 0x44, 0x7c, 0x44, 0x44, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x08, 0x08, 0x08, 0x48, 0x48, 0x48,
0x30, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x48, 0x50, 0x70, 0x48, 0x44, 0xe4, 0x00, 0x00, 0x00,
0x00, 0x70, 0x20, 0x20, 0x20, 0x20, 0x24, 0x24, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0x6c,
0x54, 0x54, 0x44, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0xec, 0x64, 0x64, 0x54, 0x54, 0x54, 0x4c,
0xec, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
0x00, 0x78, 0x24, 0x24, 0x24, 0x38, 0x20, 0x20, 0x70, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x38, 0x1c, 0x00, 0x00, 0x00, 0xf8, 0x44, 0x44, 0x44, 0x78, 0x48, 0x44,
0xe0, 0x00, 0x00, 0x00, 0x00, 0x34, 0x4c, 0x40, 0x38, 0x04, 0x04, 0x64, 0x58, 0x00, 0x00, 0x00,
0x00, 0xfc, 0x90, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44, 0x28, 0x28, 0x28, 0x10,
0x10, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44, 0x54, 0x54, 0x54, 0x54, 0x28, 0x00, 0x00, 0x00,
0x00, 0xc4, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, 0xc4, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x28,
0x28, 0x10, 0x10, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x44, 0x08, 0x10, 0x10, 0x20, 0x44,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00,
0x00, 0x40, 0x20, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x38, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x10, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
0x00, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
0x44, 0x3c, 0x44, 0x44, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x40, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x04, 0x34, 0x4c, 0x44, 0x44, 0x44, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
0x44, 0x7c, 0x40, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x7c, 0x20, 0x20, 0x20, 0x20,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x4c, 0x44, 0x44, 0x44, 0x3c, 0x04, 0x38, 0x00,
0x00, 0xc0, 0x40, 0x58, 0x64, 0x44, 0x44, 0x44, 0xec, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70,
0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x78, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x70, 0x00, 0x00, 0xc0, 0x40, 0x5c, 0x48, 0x70, 0x50, 0x48, 0xdc, 0x00, 0x00, 0x00,
0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8,
0x54, 0x54, 0x54, 0x54, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x64, 0x44, 0x44, 0x44,
0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xd8, 0x64, 0x44, 0x44, 0x44, 0x78, 0x40, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x34,
0x4c, 0x44, 0x44, 0x44, 0x3c, 0x04, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x30, 0x20, 0x20, 0x20,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x44, 0x38, 0x04, 0x44, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x7c, 0x20, 0x20, 0x20, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc,
0x44, 0x44, 0x44, 0x4c, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x44, 0x28, 0x28,
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x44, 0x54, 0x54, 0x54, 0x28, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xcc, 0x48, 0x30, 0x30, 0x48, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec,
0x44, 0x24, 0x28, 0x18, 0x10, 0x10, 0x78, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x48, 0x10, 0x20, 0x44,
0x7c, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x08, 0x00,
0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x20, 0x10, 0x10,
0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x58, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
const struct rtgui_font_bitmap asc12 =
{
asc12_font, /* bmp */
6, /* width */
12, /* height */
0, /* first char */
255 /* last char */
};
struct rtgui_font rtgui_font_asc12 =
{
"asc", /* family */
12, /* height */
1, /* refer count */
&bmp_font_engine, /* font engine */
(struct rtgui_font_bitmap *)&asc12, /* font private data */
};
/*
* File : asc16font.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/font.h>
unsigned char asc16_font[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xd6, 0xd6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0xee, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x7c, 0x38, 0x38, 0x7c, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00, 0x00,
0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
struct rtgui_font_bitmap asc16 =
{
asc16_font, /* bmp */
8, /* width */
16, /* height */
0, /* first char */
255 /* last char */
};
struct rtgui_font rtgui_font_asc16 =
{
"asc", /* family */
16, /* height */
1, /* refer count */
&bmp_font_engine, /* font engine */
&asc16, /* font private data */
};
/* size = 4096 bytes */
/*
* File : caret.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/dc.h>
#include <rtgui/caret.h>
#include <rtgui/rtgui_system.h>
#define RTGUI_CARET_WIDTH 2
#ifdef __WIN32__
#define RTGUI_CARET_BLINK 300
#else
#define RTGUI_CARET_BLINK 30
#endif
static void rtgui_caret_blink(struct rtgui_timer* timer, void* parameter)
{
struct rtgui_caret* caret;
rtgui_widget_t* widget;
caret = (struct rtgui_caret*)parameter;
RT_ASSERT(caret != RT_NULL);
if (caret->owner == RT_NULL) return;
/* caret's owner is visible? */
widget = caret->owner;
do
{
if (RTGUI_WIDGET_IS_HIDE(widget) == RT_TRUE) return;
widget = widget->parent;
} while (widget != RT_NULL);
if (caret->is_show == RT_TRUE)
{
/* set to false */
caret->is_show = RT_FALSE;
/* update owner widget */
if (caret->owner != RT_NULL)
{
rtgui_widget_update(caret->owner);
}
}
else
{
/* set to true */
caret->is_show = RT_TRUE;
/* draw caret */
rtgui_caret_draw(caret);
}
}
struct rtgui_caret* rtgui_caret_create(struct rtgui_widget* owner)
{
struct rtgui_caret* caret;
RT_ASSERT(owner != RT_NULL);
caret = (struct rtgui_caret*)rtgui_malloc(sizeof(struct rtgui_caret));
if (caret != RT_NULL)
{
caret->is_show = RT_FALSE;
caret->extent.x1 = 0;
caret->extent.y1 = 0;
caret->extent.x2 = RTGUI_CARET_WIDTH;
caret->extent.y2 = owner->gc.font->height;
caret->owner = owner;
caret->dc = (struct rtgui_dc*)rtgui_dc_buffer_create(RTGUI_CARET_WIDTH, caret->extent.y2);
if (caret->dc == RT_NULL) goto __exit;
rtgui_dc_set_color(caret->dc, black);
rtgui_dc_fill_rect(caret->dc, &(caret->extent));
caret->timer_period = RTGUI_CARET_BLINK;
caret->timer = rtgui_timer_create(caret->timer_period,
RT_TIMER_FLAG_PERIODIC,
rtgui_caret_blink, caret);
if (caret->timer == RT_NULL) goto __exit_dc;
caret->show_point.x = 0;
caret->show_point.y = 0;
}
return caret;
__exit_dc:
rtgui_dc_destory(caret->dc);
__exit:
rtgui_free(caret);
return RT_NULL;
}
void rtgui_caret_destroy(struct rtgui_caret* caret)
{
RT_ASSERT(caret != RT_NULL);
if (caret->is_show == RT_TRUE)
{
/* stop timer */
rtgui_timer_stop(caret->timer);
}
caret->owner = RT_NULL;
rtgui_dc_destory(caret->dc);
rtgui_timer_destory(caret->timer);
rtgui_free(caret);
}
/* show caret on owner widget logic position */
void rtgui_caret_show(struct rtgui_caret* caret, rt_base_t x, rt_base_t y)
{
if (caret->is_show == RT_TRUE)
{
/* set show flag and stop blink timer */
caret->is_show = RT_FALSE;
rtgui_timer_stop(caret->timer);
}
/* set show x and y */
caret->show_point.x = x;
caret->show_point.y = y;
/* set show flag and start blink timer */
caret->is_show = RT_TRUE;
/* draw caret */
rtgui_caret_draw(caret);
/* start blink timer */
rtgui_timer_start(caret->timer);
}
void rtgui_caret_hide(struct rtgui_caret* caret)
{
RT_ASSERT(caret != RT_NULL);
/* set show flag and stop blink timer */
caret->is_show = RT_FALSE;
rtgui_timer_stop(caret->timer);
/* update owner widget */
if (caret->owner != RT_NULL)
{
rtgui_widget_update(caret->owner);
}
}
void rtgui_caret_set_point(struct rtgui_caret* caret, int x, int y)
{
RT_ASSERT(caret != RT_NULL);
if (caret->is_show == RT_TRUE)
{
/* stop the old caret */
rtgui_timer_stop(caret->timer);
/* update owner widget */
if (caret->owner != RT_NULL && caret->is_show)
{
rtgui_widget_update(caret->owner);
}
}
caret->show_point.x = x;
caret->show_point.y = y;
/* draw caret */
rtgui_caret_draw(caret);
/* start blink timer */
rtgui_timer_start(caret->timer);
}
void rtgui_caret_set_box(struct rtgui_caret* caret, int w, int h)
{
RT_ASSERT(caret != RT_NULL);
caret->extent.x2 = caret->extent.x1 + w;
caret->extent.y2 = caret->extent.y1 + h;
}
void rtgui_caret_draw(struct rtgui_caret* caret)
{
RT_ASSERT(caret != RT_NULL);
if (caret->is_show == RT_TRUE && caret->owner->toplevel != RT_NULL)
{
struct rtgui_rect rect = caret->extent;
struct rtgui_point point = {0, 0};
struct rtgui_dc* hw_dc;
rtgui_rect_moveto(&rect, caret->show_point.x, caret->show_point.y);
hw_dc = rtgui_dc_begin_drawing(caret->owner);
rtgui_dc_blit(caret->dc, &point, hw_dc, &rect);
rtgui_dc_end_drawing(hw_dc);
}
}
/*
* File : color.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/color.h>
const rtgui_color_t red = RTGUI_RGB(0xff, 0x00, 0x00);
const rtgui_color_t green = RTGUI_RGB(0x00, 0xff, 0x00);
const rtgui_color_t blue = RTGUI_RGB(0x00, 0x00, 0xff);
const rtgui_color_t black = RTGUI_RGB(0x00, 0x00, 0x00);
const rtgui_color_t white = RTGUI_RGB(0xff, 0xff, 0xff);
const rtgui_color_t high_light = RTGUI_RGB(0xff, 0xff, 0xff);
const rtgui_color_t dark_grey = RTGUI_RGB(0x7f, 0x7f, 0x7f);
const rtgui_color_t light_grey = RTGUI_RGB(0xc0, 0xc0, 0xc0);
const rtgui_color_t default_foreground = RTGUI_RGB(0x00, 0x00, 0x00);
const rtgui_color_t default_background = RTGUI_RGB(0xff, 0xff, 0xff);
#define RTGUI_RGB_R(c) ((c) & 0xff)
#define RTGUI_RGB_G(c) (((c) >> 8) & 0xff)
#define RTGUI_RGB_B(c) (((c) >> 16) & 0xff)
#define RTGUI_RGB_A(c) (((c) >> 24) & 0xff)
/*
* File : dc.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/dc.h>
#include <rtgui/rtgui_system.h>
void rtgui_dc_destory(struct rtgui_dc* dc)
{
if (dc == RT_NULL) return;
dc->fini(dc);
rtgui_free(dc);
}
/*
* draw a point on dc
*/
void rtgui_dc_draw_point(struct rtgui_dc* dc, int x, int y)
{
if (dc == RT_NULL) return;
dc->draw_point(dc, x, y);
}
#if 0
void rtgui_dc_draw_point_alpha(struct rtgui_dc* dc, int x, int y, rt_uint8_t alpha)
{
if (dc == RT_NULL || alpha == 0xff) return;
if (dc->draw_point_alpha != RT_NULL)
dc->draw_point_alpha(dc, x, y, alpha);
else
{
rtgui_color_t color;
/* soft alpha bending */
color = dc->get_color(dc, int x, int y);
dc->draw_point(dc, x, y);
}
}
#endif
/*
* draw a vertical line on dc
*/
void rtgui_dc_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2)
{
if (dc == RT_NULL) return;
dc->draw_vline(dc, x, y1, y2);
}
/*
* draw a horizontal line on dc
*/
void rtgui_dc_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y)
{
if (dc == RT_NULL) return;
dc->draw_hline(dc, x1, x2, y);
}
void rtgui_dc_draw_line (struct rtgui_dc* dc, int x1, int y1, int x2, int y2)
{
if (dc == RT_NULL) return;
if (y1 == y2)
{
rtgui_dc_draw_hline(dc, x1, x2, y1);
}
else if (x1 == x2)
{
rtgui_dc_draw_vline(dc, x1, y1, y2);
}
else
{
int dx, dy, sdx, sdy, dxabs, dyabs, x, y, px, py;
register rt_base_t i;
/* rtgui_rect_t rect; */
dx = x2 - x1; /* the horizontal distance of the line */
dy = y2 - y1; /* the vertical distance of the line */
#define rtgui_sgn(x) ((x<0)?-1:((x>0)?1:0)) /* macro to return the sign of a number */
#define rtgui_abs(x) ((x)>=0? (x):-(x)) /* macro to return the absolute value */
dxabs = rtgui_abs(dx);
dyabs = rtgui_abs(dy);
sdx = rtgui_sgn(dx);
sdy = rtgui_sgn(dy);
x = dyabs >> 1;
y = dxabs >> 1;
px = x1;
py = y1;
if(dxabs >= dyabs) /* the line is more horizontal than vertical */
{
for(i = 0; i < dxabs; i++)
{
y += dyabs;
if(y >= dxabs)
{
y -= dxabs;
py += sdy;
}
px += sdx;
/* draw this point */
dc->draw_point(dc, px, py);
}
}
else /* the line is more vertical than horizontal */
{
for(i = 0; i < dyabs; i++)
{
x += dxabs;
if(x >= dyabs)
{
x -= dyabs;
px += sdx;
}
py += sdy;
/* draw this point */
dc->draw_point(dc, px, py);
}
}
}
}
#if 0
/* AA Line */
#define AAlevels 256
#define AAbits 8
int rtgui_dc_draw_line_aa(struct rtgui_dc* dc, rt_int16_t x1, rt_int16_t y1, rt_int16_t x2, rt_int16_t y2)
{
Sint32 xx0, yy0, xx1, yy1;
int result;
rt_uint32_t intshift, erracc, erradj;
rt_uint32_t erracctmp, wgt, wgtcompmask;
int dx, dy, tmp, xdir, y0p1, x0pxdir;
/*
* Keep on working with 32bit numbers
*/
xx0 = x1;
yy0 = y1;
xx1 = x2;
yy1 = y2;
/*
* Reorder points if required
*/
if (yy0 > yy1)
{
tmp = yy0;
yy0 = yy1;
yy1 = tmp;
tmp = xx0;
xx0 = xx1;
xx1 = tmp;
}
/*
* Calculate distance
*/
dx = xx1 - xx0;
dy = yy1 - yy0;
/*
* Adjust for negative dx and set xdir
*/
if (dx >= 0)
{
xdir = 1;
}
else
{
xdir = -1;
dx = (-dx);
}
/*
* Check for special cases
*/
if (dx == 0)
{
/*
* Vertical line
*/
rtgui_dc_draw_vline(dc, x1, y1, y2);
return ;
}
else if (dy == 0)
{
/*
* Horizontal line
*/
rtgui_dc_draw_hline(dc, x1, x2, y1);
return ;
}
else if (dx == dy)
{
/*
* Diagonal line
*/
rtgui_dc_draw_line(dc, x1, y1, x2, y2);
return ;
}
/*
* Zero accumulator
*/
erracc = 0;
/*
* # of bits by which to shift erracc to get intensity level
*/
intshift = 32 - AAbits;
/*
* Mask used to flip all bits in an intensity weighting
*/
wgtcompmask = AAlevels - 1;
/*
* Draw the initial pixel in the foreground color
*/
rtgui_dc_draw_point(dc, x1, y1);
/*
* x-major or y-major?
*/
if (dy > dx)
{
/*
* y-major. Calculate 16-bit fixed point fractional part of a pixel that
* X advances every time Y advances 1 pixel, truncating the result so that
* we won't overrun the endpoint along the X axis
*/
/*
* Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
*/
erradj = ((dx << 16) / dy) << 16;
/*
* draw all pixels other than the first and last
*/
x0pxdir = xx0 + xdir;
while (--dy)
{
erracctmp = erracc;
erracc += erradj;
if (erracc <= erracctmp)
{
/*
* rollover in error accumulator, x coord advances
*/
xx0 = x0pxdir;
x0pxdir += xdir;
}
yy0++; /* y-major so always advance Y */
/*
* the AAbits most significant bits of erracc give us the intensity
* weighting for this pixel, and the complement of the weighting for
* the paired pixel.
*/
wgt = (erracc >> intshift) & 255;
rtgui_dc_draw_point_alpha (dc, xx0, yy0, 255 - wgt);
rtgui_dc_draw_point_alpha (dc, x0pxdir, yy0, wgt);
}
}
else
{
/*
* x-major line. Calculate 16-bit fixed-point fractional part of a pixel
* that Y advances each time X advances 1 pixel, truncating the result so
* that we won't overrun the endpoint along the X axis.
*/
/*
* Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
*/
erradj = ((dy << 16) / dx) << 16;
/*
* draw all pixels other than the first and last
*/
y0p1 = yy0 + 1;
while (--dx)
{
erracctmp = erracc;
erracc += erradj;
if (erracc <= erracctmp)
{
/*
* Accumulator turned over, advance y
*/
yy0 = y0p1;
y0p1++;
}
xx0 += xdir; /* x-major so always advance X */
/*
* the AAbits most significant bits of erracc give us the intensity
* weighting for this pixel, and the complement of the weighting for
* the paired pixel.
*/
wgt = (erracc >> intshift) & 255;
rtgui_dc_draw_point_alpha (dc, xx0, yy0, 255 - wgt);
rtgui_dc_draw_point_alpha (dc, xx0, y0p1, wgt);
}
}
/*
* Draw final pixel, always exactly intersected by the line and doesn't
* need to be weighted.
*/
rtgui_dc_draw_point(dc, x2, y2);
}
#endif
void rtgui_dc_draw_rect (struct rtgui_dc* dc, struct rtgui_rect* rect)
{
rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y1);
rtgui_dc_draw_hline(dc, rect->x1, rect->x2, rect->y2 - 1);
rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
rtgui_dc_draw_vline(dc, rect->x2 - 1, rect->y1, rect->y2);
}
void rtgui_dc_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect)
{
if (dc == RT_NULL) return;
dc->fill_rect(dc, rect);
}
void rtgui_dc_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
{
if (dc == RT_NULL || dest == RT_NULL || rect == RT_NULL) return;
dc->blit(dc, dc_point, dest, rect);
}
void rtgui_dc_draw_text (struct rtgui_dc* dc, const rt_uint8_t* text, struct rtgui_rect* rect)
{
rt_uint32_t len;
struct rtgui_font *font;
#ifdef RTGUI_USING_FONTHZ
struct rtgui_font *gb2312_font;
#endif
struct rtgui_rect text_rect;
RT_ASSERT(dc != RT_NULL);
font = rtgui_dc_get_font(dc);
if (font == RT_NULL)
{
/* use system default font */
font = rtgui_font_default();
}
#ifdef RTGUI_USING_FONTHZ
gb2312_font = rtgui_font_refer("hz", font->height);
if (gb2312_font == RT_NULL)
{
gb2312_font = rtgui_font_refer("hz", 16);
}
#endif
/* text align */
rtgui_font_get_metrics(font, text, &text_rect);
rtgui_rect_moveto_align(rect, &text_rect, rtgui_dc_get_textalign(dc));
#ifdef RTGUI_USING_FONTHZ
while (*text)
{
len = 0;
while (*(text + len) < 0x80 && *(text + len)) len ++;
if (len > 0)
{
rtgui_font_draw(font, dc, text, len, &text_rect);
text += len;
}
len = 0;
while (*(text + len) > 0x80) len ++;
if (len > 0)
{
rtgui_font_draw(gb2312_font, dc, text, len, &text_rect);
text += len;
}
}
rtgui_font_derefer(gb2312_font);
#else
len = strlen(text);
rtgui_font_draw(font, dc, text, len, &text_rect);
#endif
}
void rtgui_dc_set_color(struct rtgui_dc* dc, rtgui_color_t color)
{
if (dc != RT_NULL)
{
dc->set_color(dc, color);
}
}
rtgui_color_t rtgui_dc_get_color(struct rtgui_dc* dc)
{
if (dc != RT_NULL)
{
return dc->get_color(dc);
}
return white;
}
void rtgui_dc_set_font(struct rtgui_dc* dc, rtgui_font_t* font)
{
if (dc != RT_NULL)
{
dc->set_font(dc, font);
}
}
rtgui_font_t* rtgui_dc_get_font(struct rtgui_dc* dc)
{
if (dc != RT_NULL)
{
return dc->get_font(dc);
}
return RT_NULL;
}
void rtgui_dc_set_textalign(struct rtgui_dc* dc, rt_int32_t align)
{
if (dc != RT_NULL)
{
dc->set_textalign(dc, align);
}
}
rt_int32_t rtgui_dc_get_textalign(struct rtgui_dc* dc)
{
if (dc != RT_NULL)
{
return dc->get_textalign(dc);
}
return RTGUI_ALIGN_NOT;
}
rt_bool_t rtgui_dc_get_visible(struct rtgui_dc* dc)
{
if (dc != RT_NULL)
{
return dc->get_visible(dc);
}
return RT_FALSE;
}
void rtgui_dc_draw_shaded_rect(struct rtgui_dc* dc, rtgui_rect_t* rect,
rtgui_color_t c1, rtgui_color_t c2)
{
RT_ASSERT(dc != RT_NULL);
rtgui_dc_set_color(dc, c1);
rtgui_dc_draw_vline(dc, rect->x1, rect->y1, rect->y2);
rtgui_dc_draw_hline(dc, rect->x1 + 1, rect->x2, rect->y1);
rtgui_dc_set_color(dc, c2);
rtgui_dc_draw_vline(dc, rect->x2, rect->y1, rect->y2);
rtgui_dc_draw_hline(dc, rect->x1, rect->x2 + 1, rect->y2);
}
void rtgui_dc_draw_border(struct rtgui_dc* dc, rtgui_rect_t* rect, int flag)
{
rtgui_rect_t r;
rtgui_color_t color;
if (dc == RT_NULL) return ;
/* save old color */
color = rtgui_dc_get_color(dc);
r = *rect;
switch (flag)
{
case RTGUI_BORDER_RAISE:
rtgui_dc_draw_shaded_rect(dc, &r, high_light, black);
rtgui_rect_inflate(&r, -1);
rtgui_dc_draw_shaded_rect(dc, &r, light_grey, dark_grey);
break;
case RTGUI_BORDER_SUNKEN:
rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
rtgui_rect_inflate(&r, -1);
rtgui_dc_draw_shaded_rect(dc, &r, black, light_grey);
break;
case RTGUI_BORDER_BOX:
rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
rtgui_rect_inflate(&r, -1);
rtgui_dc_draw_shaded_rect(dc, &r, high_light, dark_grey);
break;
case RTGUI_BORDER_STATIC:
rtgui_dc_draw_shaded_rect(dc, &r, dark_grey, high_light);
break;
case RTGUI_BORDER_EXTRA:
rtgui_dc_set_color(dc, light_grey);
rtgui_dc_draw_rect(dc, &r);
break;
case RTGUI_BORDER_SIMPLE:
rtgui_dc_set_color(dc, black);
rtgui_dc_draw_rect(dc, &r);
break;
default:
break;
}
/* restore color */
rtgui_dc_set_color(dc, color);
}
void rtgui_dc_draw_horizontal_line(struct rtgui_dc* dc, int x1, int x2, int y)
{
rtgui_color_t color;
if (dc == RT_NULL) return ;
/* save old color */
color = rtgui_dc_get_color(dc);
rtgui_dc_set_color(dc, dark_grey);
rtgui_dc_draw_hline(dc, x1, x2, y);
y ++;
rtgui_dc_set_color(dc, high_light);
rtgui_dc_draw_hline(dc, x1, x2, y);
/* restore color */
rtgui_dc_set_color(dc, color);
}
void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2)
{
rtgui_color_t color;
if (dc == RT_NULL) return ;
/* save old color */
color = rtgui_dc_get_color(dc);
rtgui_dc_set_color(dc, dark_grey);
rtgui_dc_draw_hline(dc, x, y1, y2);
x ++;
rtgui_dc_set_color(dc, high_light);
rtgui_dc_draw_hline(dc, x, y1, y2);
/* restore color */
rtgui_dc_set_color(dc, color);
}
void rtgui_dc_draw_arrow(struct rtgui_dc* dc, rtgui_rect_t* rect, int kind)
{
rt_int32_t i;
rt_int32_t x1, y1, x2, y2;
rtgui_rect_t r = {0, 0, 0, 0};
static const rt_uint8_t ARROW_WIDTH = 7;
static const rt_uint8_t ARROW_LENGTH = 4;
x1 = y1 = 0;
switch (kind)
{
case RTGUI_ARRAW_UP:
case RTGUI_ARRAW_DOWN:
r.x2 = ARROW_WIDTH;
r.y2 = ARROW_LENGTH;
break;
case RTGUI_ARRAW_LEFT:
case RTGUI_ARRAW_RIGHT:
r.x2 = ARROW_LENGTH;
r.y2 = ARROW_WIDTH;
break;
}
rtgui_rect_moveto_align(rect, &r, RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL);
switch (kind)
{
case RTGUI_ARRAW_UP:
x1 = r.x1 + (ARROW_WIDTH - 1)/2;;
y1 = r.y1;
break;
case RTGUI_ARRAW_DOWN:
x1 = r.x1 + (ARROW_WIDTH - 1)/2;
y1 = r.y1 + ARROW_LENGTH - 1;
break;
case RTGUI_ARRAW_LEFT:
x1 = r.x1;
y1 = r.y1 + (ARROW_WIDTH - 1)/2;
break;
case RTGUI_ARRAW_RIGHT:
x1 = r.x1 + ARROW_LENGTH - 1;
y1 = r.y1 + (ARROW_WIDTH - 1)/2;
break;
default:
return;
}
x2 = x1;
y2 = y1;
for (i = 0; i < ARROW_LENGTH; i++)
{
rtgui_dc_draw_line(dc, x1, y1, x2, y2);
switch (kind)
{
case RTGUI_ARRAW_UP:
x1 --;
x2 ++;
y1 ++;
y2 ++;
break;
case RTGUI_ARRAW_DOWN:
x1 --;
x2 ++;
y1 --;
y2 --;
break;
case RTGUI_ARRAW_LEFT:
y1 --;
y2 ++;
x1 ++;
x2 ++;
break;
case RTGUI_ARRAW_RIGHT:
y1 --;
y2 ++;
x1 --;
x2 --;
break;
}
}
}
void rtgui_dc_draw_polygon(struct rtgui_dc* dc, const int *vx, const int *vy, int count)
{
int i;
const int *x1, *y1, *x2, *y2;
/*
* Sanity check
*/
if (count < 3) return;
/*
* Pointer setup
*/
x1 = x2 = vx;
y1 = y2 = vy;
x2++;
y2++;
/*
* Draw
*/
for (i = 1; i < count; i++)
{
rtgui_dc_draw_line(dc, *x1, *y1, *x2, *y2);
x1 = x2;
y1 = y2;
x2++;
y2++;
}
rtgui_dc_draw_line(dc, *x1, *y1, *vx, *vy);
}
static int _int_compare(const void *a, const void *b)
{
return (*(const int *) a) - (*(const int *) b);
}
void rtgui_dc_fill_polygon(struct rtgui_dc* dc, const int* vx, const int* vy, int count)
{
int i;
int y, xa, xb;
int miny, maxy;
int x1, y1;
int x2, y2;
int ind1, ind2;
int ints;
int *poly_ints = RT_NULL;
/*
* Sanity check number of edges
*/
if (count < 3) return;
/*
* Allocate temp array, only grow array
*/
poly_ints = (int *) rt_malloc(sizeof(int) * count);
if (poly_ints == RT_NULL) return ; /* no memory, failed */
/*
* Determine Y maximal
*/
miny = vy[0];
maxy = vy[0];
for (i = 1; (i < count); i++)
{
if (vy[i] < miny) miny = vy[i];
else if (vy[i] > maxy) maxy = vy[i];
}
/*
* Draw, scanning y
*/
for (y = miny; (y <= maxy); y++) {
ints = 0;
for (i = 0; (i < count); i++) {
if (!i) {
ind1 = count - 1;
ind2 = 0;
} else {
ind1 = i - 1;
ind2 = i;
}
y1 = vy[ind1];
y2 = vy[ind2];
if (y1 < y2) {
x1 = vx[ind1];
x2 = vx[ind2];
} else if (y1 > y2) {
y2 = vy[ind1];
y1 = vy[ind2];
x2 = vx[ind1];
x1 = vx[ind2];
} else {
continue;
}
if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) )
{
poly_ints[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
}
}
qsort(poly_ints, ints, sizeof(int), _int_compare);
for (i = 0; (i < ints); i += 2)
{
xa = poly_ints[i] + 1;
xa = (xa >> 16) + ((xa & 32768) >> 15);
xb = poly_ints[i+1] - 1;
xb = (xb >> 16) + ((xb & 32768) >> 15);
rtgui_dc_draw_hline(dc, xa, xb, y);
}
}
}
void rtgui_dc_draw_circle(struct rtgui_dc* dc, int x, int y, int r)
{
rt_int16_t cx = 0;
rt_int16_t cy = r;
rt_int16_t df = 1 - r;
rt_int16_t d_e = 3;
rt_int16_t d_se = -2 * r + 5;
rt_int16_t xpcx, xmcx, xpcy, xmcy;
rt_int16_t ypcy, ymcy, ypcx, ymcx;
/*
* sanity check radius
*/
if (r < 0) return ;
/* special case for r=0 - draw a point */
if (r == 0) rtgui_dc_draw_point(dc, x, y);
/*
* draw circle
*/
do
{
ypcy = y + cy;
ymcy = y - cy;
if (cx > 0)
{
xpcx = x + cx;
xmcx = x - cx;
rtgui_dc_draw_point(dc, xmcx, ypcy);
rtgui_dc_draw_point(dc, xpcx, ypcy);
rtgui_dc_draw_point(dc, xmcx, ymcy);
rtgui_dc_draw_point(dc, xpcx, ymcy);
}
else
{
rtgui_dc_draw_point(dc, x, ymcy);
rtgui_dc_draw_point(dc, x, ypcy);
}
xpcy = x + cy;
xmcy = x - cy;
if ((cx > 0) && (cx != cy))
{
ypcx = y + cx;
ymcx = y - cx;
rtgui_dc_draw_point(dc, xmcy, ypcx);
rtgui_dc_draw_point(dc, xpcy, ypcx);
rtgui_dc_draw_point(dc, xmcy, ymcx);
rtgui_dc_draw_point(dc, xpcy, ymcx);
}
else if (cx == 0)
{
rtgui_dc_draw_point(dc, xmcy, y);
rtgui_dc_draw_point(dc, xpcy, y);
}
/*
* Update
*/
if (df < 0)
{
df += d_e;
d_e += 2;
d_se += 2;
}
else
{
df += d_se;
d_e += 2;
d_se += 4;
cy--;
}
cx++;
}while (cx <= cy);
}
void rtgui_dc_fill_circle(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t r)
{
rt_int16_t cx = 0;
rt_int16_t cy = r;
rt_int16_t ocx = (rt_int16_t) 0xffff;
rt_int16_t ocy = (rt_int16_t) 0xffff;
rt_int16_t df = 1 - r;
rt_int16_t d_e = 3;
rt_int16_t d_se = -2 * r + 5;
rt_int16_t xpcx, xmcx, xpcy, xmcy;
rt_int16_t ypcy, ymcy, ypcx, ymcx;
/*
* Sanity check radius
*/
if (r < 0) return;
/*
* Special case for r=0 - draw a point
*/
if (r == 0)
{
rtgui_dc_draw_point(dc, x, y);
return ;
}
/*
* Draw
*/
do {
xpcx = x + cx;
xmcx = x - cx;
xpcy = x + cy;
xmcy = x - cy;
if (ocy != cy) {
if (cy > 0) {
ypcy = y + cy;
ymcy = y - cy;
rtgui_dc_draw_hline(dc, xmcx, xpcx, ypcy);
rtgui_dc_draw_hline(dc, xmcx, xpcx, ymcy);
} else {
rtgui_dc_draw_hline(dc, xmcx, xpcx, y);
}
ocy = cy;
}
if (ocx != cx) {
if (cx != cy) {
if (cx > 0) {
ypcx = y + cx;
ymcx = y - cx;
rtgui_dc_draw_hline(dc, xmcy, xpcy, ymcx);
rtgui_dc_draw_hline(dc, xmcy, xpcy, ypcx);
} else {
rtgui_dc_draw_hline(dc, xmcy, xpcy, y);
}
}
ocx = cx;
}
/*
* Update
*/
if (df < 0) {
df += d_e;
d_e += 2;
d_se += 2;
} else {
df += d_se;
d_e += 2;
d_se += 4;
cy--;
}
cx++;
} while (cx <= cy);
}
void rtgui_dc_draw_ellipse(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry)
{
int ix, iy;
int h, i, j, k;
int oh, oi, oj, ok;
int xmh, xph, ypk, ymk;
int xmi, xpi, ymj, ypj;
int xmj, xpj, ymi, ypi;
int xmk, xpk, ymh, yph;
/*
* Sanity check radii
*/
if ((rx < 0) || (ry < 0)) return;
/*
* Special case for rx=0 - draw a vline
*/
if (rx == 0)
{
rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
return;
}
/*
* Special case for ry=0 - draw a hline
*/
if (ry == 0)
{
rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
return;
}
/*
* Init vars
*/
oh = oi = oj = ok = 0xFFFF;
if (rx > ry)
{
ix = 0;
iy = rx * 64;
do
{
h = (ix + 32) >> 6;
i = (iy + 32) >> 6;
j = (h * ry) / rx;
k = (i * ry) / rx;
if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j))
{
xph = x + h;
xmh = x - h;
if (k > 0)
{
ypk = y + k;
ymk = y - k;
rtgui_dc_draw_point(dc, xmh, ypk);
rtgui_dc_draw_point(dc, xph, ypk);
rtgui_dc_draw_point(dc, xmh, ymk);
rtgui_dc_draw_point(dc, xph, ymk);
}
else
{
rtgui_dc_draw_point(dc, xmh, y);
rtgui_dc_draw_point(dc, xph, y);
}
ok = k;
xpi = x + i;
xmi = x - i;
if (j > 0)
{
ypj = y + j;
ymj = y - j;
rtgui_dc_draw_point(dc, xmi, ypj);
rtgui_dc_draw_point(dc, xpi, ypj);
rtgui_dc_draw_point(dc, xmi, ymj);
rtgui_dc_draw_point(dc, xpi, ymj);
}
else
{
rtgui_dc_draw_point(dc, xmi, y);
rtgui_dc_draw_point(dc, xpi, y);
}
oj = j;
}
ix = ix + iy / rx;
iy = iy - ix / rx;
} while (i > h);
}
else
{
ix = 0;
iy = ry * 64;
do
{
h = (ix + 32) >> 6;
i = (iy + 32) >> 6;
j = (h * rx) / ry;
k = (i * rx) / ry;
if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h)))
{
xmj = x - j;
xpj = x + j;
if (i > 0)
{
ypi = y + i;
ymi = y - i;
rtgui_dc_draw_point(dc, xmj, ypi);
rtgui_dc_draw_point(dc, xpj, ypi);
rtgui_dc_draw_point(dc, xmj, ymi);
rtgui_dc_draw_point(dc, xpj, ymi);
}
else
{
rtgui_dc_draw_point(dc, xmj, y);
rtgui_dc_draw_point(dc, xpj, y);
}
oi = i;
xmk = x - k;
xpk = x + k;
if (h > 0)
{
yph = y + h;
ymh = y - h;
rtgui_dc_draw_point(dc, xmk, yph);
rtgui_dc_draw_point(dc, xpk, yph);
rtgui_dc_draw_point(dc, xmk, ymh);
rtgui_dc_draw_point(dc, xpk, ymh);
}
else
{
rtgui_dc_draw_point(dc, xmk, y);
rtgui_dc_draw_point(dc, xpk, y);
}
oh = h;
}
ix = ix + iy / ry;
iy = iy - ix / ry;
} while (i > h);
}
}
void rtgui_dc_fill_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry)
{
int ix, iy;
int h, i, j, k;
int oh, oi, oj, ok;
int xmh, xph;
int xmi, xpi;
int xmj, xpj;
int xmk, xpk;
/*
* Special case for rx=0 - draw a vline
*/
if (rx == 0)
{
rtgui_dc_draw_vline(dc, x, y - ry, y + ry);
return;
}
/* special case for ry=0 - draw a hline */
if (ry == 0) {
rtgui_dc_draw_hline(dc, x - rx, x + rx, y);
return;
}
/*
* Init vars
*/
oh = oi = oj = ok = 0xFFFF;
/*
* Draw
*/
if (rx > ry) {
ix = 0;
iy = rx * 64;
do {
h = (ix + 32) >> 6;
i = (iy + 32) >> 6;
j = (h * ry) / rx;
k = (i * ry) / rx;
if ((ok != k) && (oj != k)) {
xph = x + h;
xmh = x - h;
if (k > 0) {
rtgui_dc_draw_hline(dc, xmh, xph, y + k);
rtgui_dc_draw_hline(dc, xmh, xph, y - k);
} else {
rtgui_dc_draw_hline(dc, xmh, xph, y);
}
ok = k;
}
if ((oj != j) && (ok != j) && (k != j)) {
xmi = x - i;
xpi = x + i;
if (j > 0) {
rtgui_dc_draw_hline(dc, xmi, xpi, y + j);
rtgui_dc_draw_hline(dc, xmi, xpi, y - j);
} else {
rtgui_dc_draw_hline(dc, xmi, xpi, y);
}
oj = j;
}
ix = ix + iy / rx;
iy = iy - ix / rx;
} while (i > h);
} else {
ix = 0;
iy = ry * 64;
do {
h = (ix + 32) >> 6;
i = (iy + 32) >> 6;
j = (h * rx) / ry;
k = (i * rx) / ry;
if ((oi != i) && (oh != i)) {
xmj = x - j;
xpj = x + j;
if (i > 0) {
rtgui_dc_draw_hline(dc, xmj, xpj, y + i);
rtgui_dc_draw_hline(dc, xmj, xpj, y - i);
} else {
rtgui_dc_draw_hline(dc, xmj, xpj, y);
}
oi = i;
}
if ((oh != h) && (oi != h) && (i != h)) {
xmk = x - k;
xpk = x + k;
if (h > 0) {
rtgui_dc_draw_hline(dc, xmk, xpk, y + h);
rtgui_dc_draw_hline(dc, xmk, xpk, y - h);
} else {
rtgui_dc_draw_hline(dc, xmk, xpk, y);
}
oh = h;
}
ix = ix + iy / ry;
iy = iy - ix / ry;
} while (i > h);
}
}
void rtgui_dc_draw_focus_rect(struct rtgui_dc* dc, rtgui_rect_t* rect)
{
int i;
for (i = rect->x1; i <= rect->x2; i += 2)
{
rtgui_dc_draw_point(dc, i, rect->y1);
rtgui_dc_draw_point(dc, i, rect->y2);
}
for (i = rect->y1; i <= rect->y2; i += 2)
{
rtgui_dc_draw_point(dc, rect->x1, i);
rtgui_dc_draw_point(dc, rect->x2, i);
}
}
void rtgui_dc_get_rect(struct rtgui_dc*dc, rtgui_rect_t* rect)
{
if (dc != RT_NULL && rect != RT_NULL)
{
dc->get_rect(dc, rect);
}
}
/*
* File : dc_buffer.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/rtgui.h>
#include <rtgui/dc.h>
#include <rtgui/color.h>
#include <rtgui/rtgui_system.h>
struct rtgui_dc_buffer
{
struct rtgui_dc parent;
/* color and font */
rtgui_color_t color;
struct rtgui_font* font;
/* text align */
rt_int32_t align;
/* width and height */
rt_uint16_t width, height;
rt_uint16_t pitch;
/* blit info */
rt_uint32_t clip_sync;
rtgui_region_t clip;
/* pixel data */
rt_uint8_t* pixel;
};
static rt_bool_t rtgui_dc_buffer_fini(struct rtgui_dc* dc);
static void rtgui_dc_buffer_draw_point(struct rtgui_dc* dc, int x, int y);
static void rtgui_dc_buffer_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2);
static void rtgui_dc_buffer_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y);
static void rtgui_dc_buffer_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect);
static void rtgui_dc_buffer_blit(struct rtgui_dc* self, struct rtgui_point* dc_point,
struct rtgui_dc* dest, rtgui_rect_t* rect);
static void rtgui_dc_buffer_set_color (struct rtgui_dc* dc, rtgui_color_t color);
static rtgui_color_t rtgui_dc_buffer_get_color(struct rtgui_dc* dc);
static void rtgui_dc_buffer_set_font(struct rtgui_dc* dc, rtgui_font_t* font);
static rtgui_font_t* rtgui_dc_buffer_get_font(struct rtgui_dc* dc);
static void rtgui_dc_buffer_set_textalign(struct rtgui_dc* dc, rt_int32_t textalign);
static rt_int32_t rtgui_dc_buffer_get_textalign(struct rtgui_dc* dc);
static rt_bool_t rtgui_dc_buffer_get_visible(struct rtgui_dc* dc);
static void rtgui_dc_buffer_get_rect(struct rtgui_dc* dc, rtgui_rect_t* rect);
static void rtgui_dc_buffer_init(struct rtgui_dc_buffer* dc)
{
if (dc == RT_NULL) return;
dc->parent.type = RTGUI_DC_BUFFER;
dc->parent.draw_point = rtgui_dc_buffer_draw_point;
dc->parent.draw_hline = rtgui_dc_buffer_draw_hline;
dc->parent.draw_vline = rtgui_dc_buffer_draw_vline;
dc->parent.fill_rect = rtgui_dc_buffer_fill_rect;
dc->parent.blit = rtgui_dc_buffer_blit;
dc->parent.set_color = rtgui_dc_buffer_set_color;
dc->parent.get_color = rtgui_dc_buffer_get_color;
dc->parent.set_font = rtgui_dc_buffer_set_font;
dc->parent.get_font = rtgui_dc_buffer_get_font;
dc->parent.set_textalign = rtgui_dc_buffer_set_textalign;
dc->parent.get_textalign = rtgui_dc_buffer_get_textalign;
dc->parent.get_visible= rtgui_dc_buffer_get_visible;
dc->parent.get_rect = rtgui_dc_buffer_get_rect;
dc->parent.fini = rtgui_dc_buffer_fini;
}
struct rtgui_dc* rtgui_dc_buffer_create(int w, int h)
{
struct rtgui_dc_buffer* dc;
dc = (struct rtgui_dc_buffer*)rtgui_malloc(sizeof(struct rtgui_dc_buffer));
rtgui_dc_buffer_init(dc);
dc->color = 0;
dc->font = RT_NULL;
dc->align = 0;
dc->width = w;
dc->height = h;
dc->pitch = w * sizeof(rtgui_color_t);
dc->clip_sync = 0;
rtgui_region_init(&(dc->clip));
dc->pixel = rtgui_malloc(h * dc->pitch);
rt_memset(dc->pixel, 0, h * dc->pitch);
return &(dc->parent);
}
rt_uint8_t* rtgui_dc_buffer_get_pixel(struct rtgui_dc* dc)
{
struct rtgui_dc_buffer* dc_buffer;
dc_buffer = (struct rtgui_dc_buffer*)dc;
return dc_buffer->pixel;
}
static rt_bool_t rtgui_dc_buffer_fini(struct rtgui_dc* dc)
{
struct rtgui_dc_buffer* buffer = (struct rtgui_dc_buffer*)dc;
if (dc->type != RTGUI_DC_BUFFER) return RT_FALSE;
rtgui_free(buffer->pixel);
buffer->pixel = RT_NULL;
return RT_TRUE;
}
static void rtgui_dc_buffer_draw_point(struct rtgui_dc* self, int x, int y)
{
rtgui_color_t* ptr;
struct rtgui_dc_buffer* dc;
dc = (struct rtgui_dc_buffer*)self;
/* note: there is no parameter check in this function */
ptr = (rtgui_color_t*)(dc->pixel + y * dc->pitch + x * sizeof(rtgui_color_t));
*ptr = dc->color;
}
static void rtgui_dc_buffer_draw_vline(struct rtgui_dc* self, int x, int y1, int y2)
{
rtgui_color_t* ptr;
register rt_base_t index;
struct rtgui_dc_buffer* dc;
dc = (struct rtgui_dc_buffer*)self;
if (x >= dc->width) return;
if (y1 > dc->height) y1 = dc->height;
if (y2 > dc->height) y2 = dc->height;
ptr = (rtgui_color_t*)(dc->pixel + y1 * dc->pitch + x * sizeof(rtgui_color_t));
for (index = y1; index < y2; index ++)
{
/* draw this point */
*ptr = dc->color;
ptr += dc->width;
}
}
static void rtgui_dc_buffer_draw_hline(struct rtgui_dc* self, int x1, int x2, int y)
{
rtgui_color_t* ptr;
register rt_base_t index;
struct rtgui_dc_buffer* dc;
dc = (struct rtgui_dc_buffer*)self;
if (y >= dc->height) return;
if (x1 > dc->width) x1 = dc->width;
if (x2 > dc->width) x2 = dc->width;
ptr = (rtgui_color_t*)(dc->pixel + y * dc->pitch + x1 * sizeof(rtgui_color_t));
for (index = x1; index < x2; index ++)
{
/* draw this point */
*ptr++ = dc->color;
}
}
static void rtgui_dc_buffer_fill_rect (struct rtgui_dc* self, struct rtgui_rect* rect)
{
rtgui_rect_t r;
struct rtgui_dc_buffer* dc;
r = *rect;
dc = (struct rtgui_dc_buffer*)self;
if (r.x1 > dc->width) r.x1 = dc->width;
if (r.x2 > dc->width) r.x2 = dc->width;
if (r.y1 > dc->height) r.y1 = dc->height;
if (r.y2 > dc->height) r.y2 = dc->height;
/* fill first line */
rtgui_dc_buffer_draw_hline(&(dc->parent), r.x1, r.x2, r.y1);
/* memory copy other lines */
if (r.y2 > r.y1)
{
register rt_base_t index;
for (index = r.y1 + 1; index < r.y2; index ++)
{
rt_memcpy(dc->pixel + index * dc->pitch,
dc->pixel + r.y1 * dc->pitch,
(r.x2 - r.x1) * sizeof(rtgui_color_t));
}
}
}
/* rtgui_color to RGB323 */
rt_inline void rtgui_blit_line_1(rtgui_color_t* color, rt_uint8_t* dest, int line)
{
struct _color {rt_uint8_t r, g, b, a;} *c;
c = (struct _color*)color;
while (line-- > 0)
{
*dest = (c->r & 0xe0) | (c->g & 0xc0) >> 3 | (c->b & 0xe0) >> 5 ;
c ++;
dest ++;
}
}
/* rtgui_color to RGB565 */
rt_inline void rtgui_blit_line_2(rtgui_color_t* color, rt_uint8_t* dest, int line)
{
struct _color {rt_uint8_t r, g, b, a;} *c;
rt_uint16_t* ptr;
c = (struct _color*)color;
ptr = (rt_uint16_t*)dest;
while (line-- > 0)
{
*ptr = ((c->r & 0xf8) << 8) | ((c->g & 0xfc) << 3) | (c->b >> 3);
c ++;
ptr ++;
}
}
/* rtgui_color to RGB888 */
rt_inline void rtgui_blit_line_4(rtgui_color_t* color, rt_uint8_t* dest, int line)
{
rt_memcpy(dest, color, line * 4);
}
static void rtgui_dc_buffer_blit(struct rtgui_dc* self, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
{
struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
struct rtgui_dc_hw* hw = (struct rtgui_dc_hw*)dest;
if (dest->type == RTGUI_DC_HW)
{
register int index;
int fb_pitch;
rtgui_rect_t abs_rect;
void (*blit_line)(rtgui_color_t* color, rt_uint8_t* dest, int line);
abs_rect.x1 = hw->owner->extent.x1 + rect->x1;
abs_rect.y1 = hw->owner->extent.y1 + rect->y1;
abs_rect.x2 = abs_rect.x1 + rtgui_rect_width(*rect);
abs_rect.y2 = abs_rect.y1 + rtgui_rect_height(*rect);
/* hw fb pitch */
fb_pitch = hw->device->byte_per_pixel * hw->device->width;
/* hardware dc blit */
if (!rtgui_region_not_empty(&dc->clip) ||
dc->clip_sync != hw->owner->clip_sync)
{
/* should re-calculate clip */
rtgui_region_intersect_rect(&(dc->clip),
&(hw->owner->clip), &abs_rect);
}
switch (hw->device->byte_per_pixel)
{
case 1:
blit_line = rtgui_blit_line_1;
break;
case 2:
blit_line = rtgui_blit_line_2;
break;
case 3:
blit_line = rtgui_blit_line_4;
break;
default:
/* can not blit */
return;
}
/* blit each clip rect */
if (dc->clip.data == RT_NULL)
{
int y;
rtgui_color_t* pixel;
rt_uint8_t* fb;
pixel = (rtgui_color_t*)(dc->pixel + (dc_point->y + dc->clip.extents.y1 - abs_rect.y1) * dc->pitch +
(dc_point->x + dc->clip.extents.x1 - abs_rect.x1) * sizeof(rtgui_color_t));
fb = hw->device->get_framebuffer() + dc->clip.extents.y1 * fb_pitch +
dc->clip.extents.x1 * hw->device->byte_per_pixel;
for (y = dc->clip.extents.y1; y < dc->clip.extents.y2; y ++)
{
blit_line(pixel, fb, dc->clip.extents.x2 - dc->clip.extents.x1);
fb += fb_pitch;
pixel += dc->width;
}
}
else for (index = 0; index < rtgui_region_num_rects(&(dc->clip)); index ++)
{
int y;
rtgui_rect_t* prect;
rtgui_color_t* pixel;
rt_uint8_t* fb;
prect = ((rtgui_rect_t *)(dc->clip.data + index + 1));
pixel = (rtgui_color_t*)(dc->pixel + (dc_point->y + prect->y1 - abs_rect.y1) * dc->pitch +
(dc_point->x + prect->x1 - abs_rect.x1) * sizeof(rtgui_color_t));
fb = hw->device->get_framebuffer() + prect->y1 * fb_pitch +
prect->x1 * hw->device->byte_per_pixel;
for (y = prect->y1; y < prect->y2; y ++)
{
blit_line(pixel, fb, prect->x2 - prect->x1);
fb += fb_pitch;
pixel += dc->width;
}
}
}
}
static void rtgui_dc_buffer_set_color (struct rtgui_dc* self, rtgui_color_t color)
{
struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
dc->color = color;
}
static rtgui_color_t rtgui_dc_buffer_get_color(struct rtgui_dc* self)
{
struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
return dc->color;
}
static void rtgui_dc_buffer_set_font(struct rtgui_dc* self, rtgui_font_t* font)
{
struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
dc->font = font;
}
static rtgui_font_t* rtgui_dc_buffer_get_font(struct rtgui_dc* self)
{
struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
return dc->font;
}
static void rtgui_dc_buffer_set_textalign(struct rtgui_dc* self, rt_int32_t textalign)
{
struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
dc->align = textalign;
}
static rt_int32_t rtgui_dc_buffer_get_textalign(struct rtgui_dc* self)
{
struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
return dc->align;
}
static rt_bool_t rtgui_dc_buffer_get_visible(struct rtgui_dc* dc)
{
return RT_TRUE;
}
static void rtgui_dc_buffer_get_rect(struct rtgui_dc* self, rtgui_rect_t* rect)
{
struct rtgui_dc_buffer* dc = (struct rtgui_dc_buffer*)self;
rect->x1 = rect->y1 = 0;
rect->x2 = dc->width;
rect->y2 = dc->height;
}
/*
* File : dc_hw.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/dc.h>
#include <rtgui/driver.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/view.h>
#include <rtgui/widgets/window.h>
#include <rtgui/widgets/workbench.h>
#include <rtgui/widgets/title.h>
static void rtgui_dc_hw_draw_point(struct rtgui_dc* dc, int x, int y);
static void rtgui_dc_hw_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y);
static void rtgui_dc_hw_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2);
static void rtgui_dc_hw_fill_rect (struct rtgui_dc* dc, rtgui_rect_t* rect);
static void rtgui_dc_hw_blit (struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect);
static void rtgui_dc_hw_set_color (struct rtgui_dc* dc, rtgui_color_t color);
static rtgui_color_t rtgui_dc_hw_get_color (struct rtgui_dc* dc);
static void rtgui_dc_hw_set_font(struct rtgui_dc* dc, rtgui_font_t* font);
static rtgui_font_t* rtgui_dc_hw_get_font(struct rtgui_dc* dc);
static void rtgui_dc_hw_set_textalign(struct rtgui_dc* dc, rt_int32_t textalign);
static rt_int32_t rtgui_dc_hw_get_textalign(struct rtgui_dc* dc);
static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc* dc);
static rt_bool_t rtgui_dc_hw_get_visible(struct rtgui_dc* dc);
static void rtgui_dc_hw_get_rect(struct rtgui_dc* dc, rtgui_rect_t* rect);
struct rtgui_dc* rtgui_dc_begin_drawing(rtgui_widget_t* owner)
{
return rtgui_dc_hw_create(owner);
}
void rtgui_dc_end_drawing(struct rtgui_dc* dc)
{
if (rtgui_dc_hw_fini(dc) == RT_TRUE)
{
rtgui_free(dc);
}
}
void rtgui_dc_hw_init(struct rtgui_dc_hw* dc)
{
if (dc == RT_NULL) return;
dc->parent.type = RTGUI_DC_HW;
dc->parent.draw_point = rtgui_dc_hw_draw_point;
dc->parent.draw_hline = rtgui_dc_hw_draw_hline;
dc->parent.draw_vline = rtgui_dc_hw_draw_vline;
dc->parent.fill_rect = rtgui_dc_hw_fill_rect ;
dc->parent.blit = rtgui_dc_hw_blit;
dc->parent.set_color = rtgui_dc_hw_set_color;
dc->parent.get_color = rtgui_dc_hw_get_color;
dc->parent.set_font = rtgui_dc_hw_set_font;
dc->parent.get_font = rtgui_dc_hw_get_font;
dc->parent.set_textalign = rtgui_dc_hw_set_textalign;
dc->parent.get_textalign = rtgui_dc_hw_get_textalign;
dc->parent.get_visible= rtgui_dc_hw_get_visible;
dc->parent.get_rect = rtgui_dc_hw_get_rect;
dc->parent.fini = rtgui_dc_hw_fini;
}
extern struct rt_mutex cursor_mutex;
#define dc_set_foreground(c) dc->owner->gc.foreground = c
#define dc_set_background(c) dc->owner->gc.background = c
extern void rtgui_mouse_show_cursor(void);
extern void rtgui_mouse_hide_cursor(void);
struct rtgui_dc* rtgui_dc_hw_create(rtgui_widget_t* owner)
{
struct rtgui_dc_hw* dc;
rtgui_widget_t* widget;
/* adjudge owner */
if (owner == RT_NULL || owner->toplevel == RT_NULL) return RT_NULL;
if (!RTGUI_IS_TOPLEVEL(owner->toplevel)) return RT_NULL;
/* malloc a dc object */
dc = (struct rtgui_dc_hw*) rtgui_malloc(sizeof(struct rtgui_dc_hw));
rtgui_dc_hw_init(dc);
dc->owner = owner;
dc->visible = RT_TRUE;
dc->device = rtgui_graphic_driver_get_default();
/* set visible */
widget = owner;
while (widget != RT_NULL)
{
if (RTGUI_WIDGET_IS_HIDE(widget))
{
dc->visible = RT_FALSE;
break;
}
widget = widget->parent;
}
if (RTGUI_IS_WINTITLE(dc->owner->toplevel))
{
rtgui_toplevel_t* top = RTGUI_TOPLEVEL(dc->owner->toplevel);
top->drawing ++;
if (top->drawing == 1)
{
#ifdef RTGUI_USING_MOUSE_CURSOR
#ifdef __WIN32__
rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
rt_kprintf("hide cursor\n");
rtgui_mouse_hide_cursor();
#else
/* hide cursor */
rtgui_mouse_hide_cursor();
#endif
#endif
}
}
else if (RTGUI_IS_WORKBENCH(dc->owner->toplevel) ||
RTGUI_IS_WIN(dc->owner->toplevel))
{
rtgui_toplevel_t* top = RTGUI_TOPLEVEL(dc->owner->toplevel);
top->drawing ++;
if (top->drawing == 1)
{
#ifdef __WIN32__
#ifdef RTGUI_USING_MOUSE_CURSOR
rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
rt_kprintf("hide cursor\n");
rtgui_mouse_hide_cursor();
#endif
#else
/* send draw begin to server */
struct rtgui_event_update_begin eupdate;
RTGUI_EVENT_UPDATE_BEGIN_INIT(&(eupdate));
eupdate.rect = RTGUI_WIDGET(top)->extent;
rtgui_thread_send(top->server, (struct rtgui_event*)&eupdate, sizeof(eupdate));
#endif
}
}
return &(dc->parent);
}
static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc* dc)
{
struct rtgui_dc_hw* hw = (struct rtgui_dc_hw*)dc;
if (dc == RT_NULL || hw->parent.type != RTGUI_DC_HW) return RT_FALSE;
if (RTGUI_IS_WINTITLE(hw->owner->toplevel))
{
/* update title extent */
rtgui_toplevel_t* top = RTGUI_TOPLEVEL(hw->owner->toplevel);
top->drawing --;
if (top->drawing == 0)
{
#ifdef __WIN32__
#ifdef RTGUI_USING_MOUSE_CURSOR
rt_mutex_release(&cursor_mutex);
/* show cursor */
rtgui_mouse_show_cursor();
rt_kprintf("show cursor\n");
#endif
/* update screen */
hw->device->screen_update(&(hw->owner->extent));
#else
#ifdef RTGUI_USING_MOUSE_CURSOR
/* show cursor */
rtgui_mouse_show_cursor();
#endif
/* update screen */
hw->device->screen_update(&(hw->owner->extent));
#endif
}
}
else if (RTGUI_IS_WORKBENCH(hw->owner->toplevel) ||
RTGUI_IS_WIN(hw->owner->toplevel))
{
rtgui_toplevel_t* top = RTGUI_TOPLEVEL(hw->owner->toplevel);
top->drawing --;
if (top->drawing == 0)
{
#ifdef __WIN32__
#ifdef RTGUI_USING_MOUSE_CURSOR
rt_mutex_release(&cursor_mutex);
/* show cursor */
rtgui_mouse_show_cursor();
rt_kprintf("show cursor\n");
#endif
/* update screen */
hw->device->screen_update(&(hw->owner->extent));
#else
/* send to server to end drawing */
struct rtgui_event_update_end eupdate;
RTGUI_EVENT_UPDATE_END_INIT(&(eupdate));
eupdate.rect = RTGUI_WIDGET(top)->extent;
rtgui_thread_send(top->server, (struct rtgui_event*)&eupdate, sizeof(eupdate));
#endif
}
}
return RT_TRUE;
}
/*
* draw a logic point on device
*/
static void rtgui_dc_hw_draw_point(struct rtgui_dc* self, int x, int y)
{
struct rtgui_dc_hw* dc;
rtgui_rect_t rect;
dc = (struct rtgui_dc_hw*)self;
if (dc == RT_NULL || dc->visible != RT_TRUE) return;
x = x + dc->owner->extent.x1;
y = y + dc->owner->extent.y1;
if (rtgui_region_contains_point(&(dc->owner->clip), x, y, &rect) == RT_EOK)
{
/* draw this point */
dc->device->set_pixel(&(dc->owner->gc.foreground), x, y);
}
}
/*
* draw a logic vertical line on device
*/
static void rtgui_dc_hw_draw_vline(struct rtgui_dc* self, int x, int y1, int y2)
{
register rt_base_t index;
struct rtgui_dc_hw* dc;
dc = (struct rtgui_dc_hw*)self;
if (dc == RT_NULL || dc->visible != RT_TRUE) return;
x = x + dc->owner->extent.x1;
y1 = y1 + dc->owner->extent.y1;
y2 = y2 + dc->owner->extent.y1;
if (dc->owner->clip.data == RT_NULL)
{
rtgui_rect_t* prect;
prect = &(dc->owner->clip.extents);
/* calculate vline intersect */
if (prect->x1 > x || prect->x2 <= x) return;
if (prect->y2 <= y1 || prect->y1 > y2) return;
if (prect->y1 > y1) y1 = prect->y1;
if (prect->y2 < y2) y2 = prect->y2;
/* draw vline */
dc->device->draw_vline(&(dc->owner->gc.foreground), x, y1, y2);
}
else for (index = 0; index < rtgui_region_num_rects(&(dc->owner->clip)); index ++)
{
rtgui_rect_t* prect;
register rt_base_t draw_y1, draw_y2;
prect = ((rtgui_rect_t *)(dc->owner->clip.data + index + 1));
draw_y1 = y1;
draw_y2 = y2;
/* calculate vline clip */
if (prect->x1 > x || prect->x2 <= x) continue;
if (prect->y2 <= y1 || prect->y1 > y2) continue;
if (prect->y1 > y1) draw_y1 = prect->y1;
if (prect->y2 < y2) draw_y2 = prect->y2;
/* draw vline */
dc->device->draw_vline(&(dc->owner->gc.foreground), x, draw_y1, draw_y2);
}
}
/*
* draw a logic horizontal line on device
*/
static void rtgui_dc_hw_draw_hline(struct rtgui_dc* self, int x1, int x2, int y)
{
register rt_base_t index;
struct rtgui_dc_hw* dc;
dc = (struct rtgui_dc_hw*)self;
if (dc == RT_NULL || dc->visible != RT_TRUE) return;
/* convert logic to device */
x1 = x1 + dc->owner->extent.x1;
x2 = x2 + dc->owner->extent.x1;
y = y + dc->owner->extent.y1;
if (dc->owner->clip.data == RT_NULL)
{
rtgui_rect_t* prect;
prect = &(dc->owner->clip.extents);
/* calculate vline intersect */
if (prect->y1 > y || prect->y2 <= y ) return;
if (prect->x2 <= x1 || prect->x1 > x2) return;
if (prect->x1 > x1) x1 = prect->x1;
if (prect->x2 < x2) x2 = prect->x2;
/* draw hline */
dc->device->draw_hline(&(dc->owner->gc.foreground), x1, x2, y);
}
else for (index = 0; index < rtgui_region_num_rects(&(dc->owner->clip)); index ++)
{
rtgui_rect_t* prect;
register rt_base_t draw_x1, draw_x2;
prect = ((rtgui_rect_t *)(dc->owner->clip.data + index + 1));
draw_x1 = x1;
draw_x2 = x2;
/* calculate hline clip */
if (prect->y1 > y || prect->y2 <= y ) continue;
if (prect->x2 <= x1 || prect->x1 > x2) continue;
if (prect->x1 > x1) draw_x1 = prect->x1;
if (prect->x2 < x2) draw_x2 = prect->x2;
/* draw hline */
dc->device->draw_hline(&(dc->owner->gc.foreground), draw_x1, draw_x2, y);
}
}
static void rtgui_dc_hw_fill_rect (struct rtgui_dc* self, struct rtgui_rect* rect)
{
rtgui_color_t foreground;
register rt_base_t index;
struct rtgui_dc_hw* dc;
dc = (struct rtgui_dc_hw*)self;
if (dc == RT_NULL || dc->visible != RT_TRUE) return;
/* save foreground color */
foreground = dc->owner->gc.foreground;
/* set background color as foreground color */
dc->owner->gc.foreground = dc->owner->gc.background;
/* fill rect */
for (index = rect->y1; index < rect->y2; index ++)
{
rtgui_dc_hw_draw_hline(self, rect->x1, rect->x2, index);
}
/* restore foreground color */
dc->owner->gc.foreground = foreground;
}
static void rtgui_dc_hw_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect)
{
/* not blit in hardware dc */
return ;
}
static void rtgui_dc_hw_set_color(struct rtgui_dc* self, rtgui_color_t color)
{
struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
if (self != RT_NULL)
{
dc->owner->gc.foreground = color;
}
}
static rtgui_color_t rtgui_dc_hw_get_color(struct rtgui_dc* self)
{
struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
return self != RT_NULL? dc->owner->gc.foreground : white;
}
static void rtgui_dc_hw_set_font(struct rtgui_dc* self, rtgui_font_t* font)
{
struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
if (self != RT_NULL)
{
dc->owner->gc.font = font;
}
}
static rtgui_font_t* rtgui_dc_hw_get_font(struct rtgui_dc* self)
{
struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
return self != RT_NULL? dc->owner->gc.font : RT_NULL;
}
static void rtgui_dc_hw_set_textalign(struct rtgui_dc* self, rt_int32_t textalign)
{
struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
dc->owner->gc.textalign = textalign;
}
static rt_int32_t rtgui_dc_hw_get_textalign(struct rtgui_dc* self)
{
struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
return dc->owner->gc.textalign;
}
static rt_bool_t rtgui_dc_hw_get_visible(struct rtgui_dc* dc)
{
return RT_TRUE;
}
static void rtgui_dc_hw_get_rect(struct rtgui_dc* self, rtgui_rect_t* rect)
{
struct rtgui_dc_hw* dc = (struct rtgui_dc_hw*)self;
rtgui_widget_get_rect(dc->owner, rect);
}
/*
* File : filerw.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/filerw.h>
#include <rtgui/rtgui_system.h>
#ifdef RT_USING_STDIO_FILERW
#include <stdio.h>
/* standard file read/write */
struct rtgui_filerw_stdio
{
/* inherit from rtgui_filerw */
struct rtgui_filerw parent;
FILE* fp;
};
static int stdio_seek(struct rtgui_filerw *context, rt_off_t offset, int whence)
{
struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
int stdio_whence[3] = {SEEK_SET, SEEK_CUR, SEEK_END};
if (whence < RTGUI_FILE_SEEK_SET || whence > RTGUI_FILE_SEEK_END)
{
return -1;
}
if (fseek(stdio_filerw->fp, offset, stdio_whence[whence]) == 0)
{
return ftell(stdio_filerw->fp);
}
return -1;
}
static int stdio_read(struct rtgui_filerw *context, void *ptr, rt_size_t size, rt_size_t maxnum)
{
size_t nread;
struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
nread = fread(ptr, size, maxnum, stdio_filerw->fp);
if (nread == 0 && ferror(stdio_filerw->fp))
{
return -1;
}
return nread;
}
static int stdio_write(struct rtgui_filerw *context, const void *ptr, rt_size_t size, rt_size_t num)
{
size_t nwrote;
struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
nwrote = fwrite(ptr, size, num, stdio_filerw->fp);
if ( nwrote == 0 && ferror(stdio_filerw->fp) )
{
return -1;
}
return nwrote;
}
int stdio_tell(struct rtgui_filerw* context)
{
struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
return ftell(stdio_filerw->fp);
}
int stdio_eof(struct rtgui_filerw* context)
{
struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
return feof(stdio_filerw->fp);
}
static int stdio_close(struct rtgui_filerw *context)
{
struct rtgui_filerw_stdio* stdio_filerw = (struct rtgui_filerw_stdio *)context;
if (stdio_filerw)
{
fclose(stdio_filerw->fp);
rtgui_free(stdio_filerw);
return 0;
}
return -1;
}
#endif
/* memory file read/write */
struct rtgui_filerw_mem
{
/* inherit from rtgui_filerw */
struct rtgui_filerw parent;
rt_uint8_t *mem_base, *mem_position, *mem_end;
};
static int mem_seek(struct rtgui_filerw *context, rt_off_t offset, int whence)
{
rt_uint8_t* newpos;
struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
RT_ASSERT(mem != RT_NULL);
switch (whence) {
case RTGUI_FILE_SEEK_SET:
newpos = mem->mem_base + offset;
break;
case RTGUI_FILE_SEEK_CUR:
newpos = mem->mem_position + offset;
break;
case RTGUI_FILE_SEEK_END:
newpos = mem->mem_end + offset;
break;
default:
return -1;
}
if ( newpos < mem->mem_base )
newpos = mem->mem_base;
if ( newpos > mem->mem_end )
newpos = mem->mem_end;
mem->mem_position = newpos;
return mem->mem_position- mem->mem_base;
}
static int mem_read(struct rtgui_filerw *context, void *ptr, rt_size_t size, rt_size_t maxnum)
{
int total_bytes;
int mem_available;
struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
total_bytes = (maxnum * size);
if ( (maxnum <= 0) || (size <= 0) || ((total_bytes / maxnum) != size) )
{
return -1;
}
mem_available = mem->mem_end - mem->mem_position;
if (total_bytes > mem_available)
total_bytes = mem_available;
rt_memcpy(ptr, mem->mem_position, total_bytes);
mem->mem_position += total_bytes;
return (total_bytes / size);
}
static int mem_write(struct rtgui_filerw *context, const void *ptr, rt_size_t size, rt_size_t num)
{
struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
if ((mem->mem_position + (num * size)) > mem->mem_end)
{
num = (mem->mem_end - mem->mem_position)/size;
}
rt_memcpy(mem->mem_position, ptr, num*size);
mem->mem_position += num*size;
return num;
}
static int mem_tell(struct rtgui_filerw* context)
{
struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
return mem->mem_position - mem->mem_base;
}
static int mem_eof(struct rtgui_filerw* context)
{
struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
return mem->mem_position >= mem->mem_end;
}
static int mem_close(struct rtgui_filerw *context)
{
struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
if (mem != RT_NULL)
{
rtgui_free(mem);
return 0;
}
return -1;
}
rt_uint8_t* rtgui_filerw_mem_getdata(struct rtgui_filerw* context)
{
struct rtgui_filerw_mem* mem = (struct rtgui_filerw_mem*)context;
/* check whether it's a memory filerw */
if (mem->parent.read != mem_read) return RT_NULL;
return mem->mem_base;
}
/* file read/write public interface */
#ifdef RT_USING_STDIO_FILERW
struct rtgui_filerw* rtgui_filerw_create_file(const char* filename, const char* mode)
{
FILE *fp;
struct rtgui_filerw_stdio *rw;
RT_ASSERT(filename != RT_NULL);
rw = RT_NULL;
fp = fopen(filename, mode);
if ( fp != NULL )
{
rw = (struct rtgui_filerw_stdio*) rtgui_malloc(sizeof(struct rtgui_filerw_stdio));
if (rw != RT_NULL)
{
rw->parent.seek = stdio_seek;
rw->parent.read = stdio_read;
rw->parent.write = stdio_write;
rw->parent.tell = stdio_tell;
rw->parent.close = stdio_close;
rw->parent.eof = stdio_eof;
rw->fp = fp;
}
}
return &(rw->parent);
}
#endif
struct rtgui_filerw* rtgui_filerw_create_mem(rt_uint8_t* mem, rt_size_t size)
{
struct rtgui_filerw_mem* rw;
RT_ASSERT(mem != RT_NULL);
rw = (struct rtgui_filerw_mem*) rtgui_malloc(sizeof(struct rtgui_filerw_mem));
if (rw != RT_NULL)
{
rw->parent.seek = mem_seek;
rw->parent.read = mem_read;
rw->parent.write = mem_write;
rw->parent.tell = mem_tell;
rw->parent.eof = mem_eof;
rw->parent.close = mem_close;
rw->mem_base = mem;
rw->mem_position = mem;
rw->mem_end = mem + size;
}
return &(rw->parent);
}
int rtgui_filerw_seek(struct rtgui_filerw* context, rt_off_t offset, int whence)
{
RT_ASSERT(context != RT_NULL);
return context->seek(context, offset, whence);
}
int rtgui_filerw_read(struct rtgui_filerw* context, void* buffer, rt_size_t size, rt_size_t count)
{
RT_ASSERT(context != RT_NULL);
return context->read(context, buffer, size, count);
}
int rtgui_filerw_write(struct rtgui_filerw* context, const void* buffer, rt_size_t size, rt_size_t count)
{
RT_ASSERT(context != RT_NULL);
return context->write(context, buffer, size, count);
}
int rtgui_filerw_eof (struct rtgui_filerw* context)
{
RT_ASSERT(context != RT_NULL);
return context->eof(context);
}
int rtgui_filerw_tell(struct rtgui_filerw* context)
{
RT_ASSERT(context != RT_NULL);
return context->tell(context);
}
int rtgui_filerw_close(struct rtgui_filerw* context)
{
int result;
RT_ASSERT(context != RT_NULL);
/* close context */
result = context->close(context);
if (result != 0)
{
/* close file failed */
return -1;
}
return 0;
}
/*
* File : font.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/font.h>
#include <rtgui/dc.h>
static rtgui_list_t _rtgui_font_list;
static struct rtgui_font* rtgui_default_font;
extern struct rtgui_font rtgui_font_asc16;
extern struct rtgui_font rtgui_font_asc12;
#ifdef RTGUI_USING_FONTHZ
extern struct rtgui_font rtgui_font_hz16;
extern struct rtgui_font rtgui_font_hz12;
#endif
void rtgui_font_system_init()
{
rtgui_list_init(&(_rtgui_font_list));
/* set default font to NULL */
rtgui_default_font = RT_NULL;
#ifdef RTGUI_USING_FONT16
rtgui_font_system_add_font(&rtgui_font_asc16);
#ifdef RTGUI_USING_FONTHZ
rtgui_font_system_add_font(&rtgui_font_hz16);
#endif
#endif
rtgui_font_system_add_font(&rtgui_font_asc12);
#ifdef RTGUI_USING_FONTHZ
rtgui_font_system_add_font(&rtgui_font_hz12);
#endif
rtgui_font_set_defaut(&rtgui_font_asc12);
}
void rtgui_font_system_add_font(struct rtgui_font* font)
{
rtgui_list_init(&(font->list));
rtgui_list_append(&_rtgui_font_list, &(font->list));
}
void rtgui_font_system_remove_font(struct rtgui_font* font)
{
rtgui_list_remove(&_rtgui_font_list, &(font->list));
}
struct rtgui_font* rtgui_font_default()
{
return rtgui_default_font;
}
void rtgui_font_set_defaut(struct rtgui_font* font)
{
rtgui_default_font = font;
}
struct rtgui_font* rtgui_font_refer(const rt_uint8_t* family, rt_uint16_t height)
{
/* search font */
struct rtgui_list_node* node;
struct rtgui_font* font;
rtgui_list_foreach(node, &_rtgui_font_list)
{
font = rtgui_list_entry(node, struct rtgui_font, list);
if ((rt_strncmp((const char*)font->family, (const char*)family, RTGUI_NAME_MAX) == 0) &&
font->height == height)
{
font->refer_count ++;
return font;
}
}
return RT_NULL;
}
void rtgui_font_derefer(struct rtgui_font* font)
{
RT_ASSERT(font != RT_NULL);
font->refer_count --;
/* no refer, remove font */
if (font->refer_count == 0)
{
rtgui_font_system_remove_font(font);
}
}
/* draw a text */
void rtgui_font_draw(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect)
{
RT_ASSERT(font != RT_NULL);
if (font->engine != RT_NULL &&
font->engine->font_draw_text != RT_NULL)
{
font->engine->font_draw_text(font, dc, text, len, rect);
}
}
int rtgui_font_get_string_width(struct rtgui_font* font, const rt_uint8_t* text)
{
rtgui_rect_t rect;
/* get metrics */
rtgui_font_get_metrics(font, text, &rect);
return rect.x2 - rect.x1;
}
void rtgui_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, rtgui_rect_t* rect)
{
RT_ASSERT(font != RT_NULL);
if (font->engine != RT_NULL &&
font->engine->font_get_metrics != RT_NULL)
{
font->engine->font_get_metrics(font, text, rect);
}
else
{
/* no font engine found, set rect to zero */
rt_memset(rect, 0, sizeof(rtgui_rect_t));
}
}
static void rtgui_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect);
static void rtgui_bitmap_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, rtgui_rect_t* rect);
struct rtgui_font_engine bmp_font_engine =
{
RT_NULL,
RT_NULL,
rtgui_bitmap_font_draw_text,
rtgui_bitmap_font_get_metrics
};
void rtgui_bitmap_font_draw_char(struct rtgui_font_bitmap* font, struct rtgui_dc* dc, const char ch,
rtgui_rect_t* rect)
{
const rt_uint8_t* font_ptr = font->bmp + ch * font->height;
rt_uint16_t x, y, w, h;
register rt_base_t i, j;
x = rect->x1;
y = rect->y1;
/* check first and last char */
if (ch < font->first_char || ch > font->last_char) return;
w = (font->width + x > rect->x2)? rect->x2 - rect->x1 : font->width;
h = (font->height + y > rect->y2)? rect->y2 - rect->y1 : font->height;
for (i = 0; i < h; i ++ )
{
for (j = 0; j < w; j ++)
{
if ( ((font_ptr[i] >> (7-j)) & 0x01) != 0)
{
/* draw a pixel */
rtgui_dc_draw_point(dc, j + x, i + y);
}
}
}
}
static void rtgui_bitmap_font_draw_text(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect)
{
struct rtgui_font_bitmap* bmp_font = (struct rtgui_font_bitmap*)(font->data);
RT_ASSERT(bmp_font != RT_NULL);
while (len-- && rect->x1 < rect->x2)
{
rtgui_bitmap_font_draw_char(bmp_font, dc, *text, rect);
/* move x to next character */
rect->x1 += bmp_font->width;
text ++;
}
}
static void rtgui_bitmap_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, rtgui_rect_t* rect)
{
struct rtgui_font_bitmap* bmp_font = (struct rtgui_font_bitmap*)(font->data);
RT_ASSERT(bmp_font != RT_NULL);
/* set metrics rect */
rect->x1 = rect->y1 = 0;
rect->x2 = bmp_font->width * (rt_int16_t)rt_strlen((const char*)text);
rect->y2 = bmp_font->height;
}
/*
* File : image.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtthread.h>
#include <rtgui/image.h>
#include <rtgui/image_xpm.h>
#include <rtgui/rtgui_system.h>
#include <string.h>
#ifdef RTGUI_IMAGE_BMP
#include <rtgui/image_bmp.h>
#endif
#ifdef RTGUI_IMAGE_JPEG
#include <rtgui/image_jpeg.h>
#endif
#ifdef RTGUI_IMAGE_PNG
#include <rtgui/image_png.h>
#endif
static rtgui_list_t _rtgui_system_image_list = {RT_NULL};
/* init rtgui image system */
void rtgui_system_image_init(void)
{
/* always support XPM image */
rtgui_image_xpm_init();
#ifdef RTGUI_IMAGE_BMP
rtgui_image_bmp_init();
#endif
#ifdef RTGUI_IMAGE_JPEG
rtgui_image_jpeg_init();
#endif
#ifdef RTGUI_IMAGE_PNG
rtgui_image_png_init();
#endif
}
static struct rtgui_image_engine* rtgui_image_get_engine(const char* type)
{
struct rtgui_list_node *node;
struct rtgui_image_engine *engine;
rtgui_list_foreach(node, &_rtgui_system_image_list)
{
engine = rtgui_list_entry(node, struct rtgui_image_engine, list);
if (strncasecmp(engine->name, type, strlen(engine->name)) ==0)
return engine;
}
return RT_NULL;
}
struct rtgui_image* rtgui_image_create_from_file(const char* type, const char* filename, rt_bool_t load)
{
struct rtgui_filerw* filerw;
struct rtgui_image_engine* engine;
struct rtgui_image* image = RT_NULL;
/* create filerw context */
filerw = rtgui_filerw_create_file(filename, "rb");
if (filerw == RT_NULL) return RT_NULL;
/* get image engine */
engine = rtgui_image_get_engine(type);
if (engine == RT_NULL)
{
/* close filerw context */
rtgui_filerw_close(filerw);
return RT_NULL;
}
if (engine->image_check(filerw) == RT_TRUE)
{
image = (struct rtgui_image*) rtgui_malloc(sizeof(struct rtgui_image));
if (image == RT_NULL)
{
/* close filerw context */
rtgui_filerw_close(filerw);
return RT_NULL;
}
if (engine->image_load(image, filerw, load) != RT_TRUE)
{
/* close filerw context */
rtgui_filerw_close(filerw);
return RT_NULL;
}
/* set image engine */
image->engine = engine;
}
else
{
rtgui_filerw_close(filerw);
}
return image;
}
struct rtgui_image* rtgui_image_create_from_mem(const char* type, const rt_uint8_t* data, rt_size_t length)
{
struct rtgui_filerw* filerw;
struct rtgui_image_engine* engine;
struct rtgui_image* image = RT_NULL;
/* create filerw context */
filerw = rtgui_filerw_create_mem((rt_uint8_t*)data, length);
if (filerw == RT_NULL) return RT_NULL;
/* get image engine */
engine = rtgui_image_get_engine(type);
if (engine == RT_NULL)
{
/* close filerw context */
rtgui_filerw_close(filerw);
return RT_NULL;
}
if (engine->image_check(filerw) == RT_TRUE)
{
image = (struct rtgui_image*) rtgui_malloc(sizeof(struct rtgui_image));
if (image == RT_NULL)
{
/* close filerw context */
rtgui_filerw_close(filerw);
return RT_NULL;
}
if (engine->image_load(image, filerw, RT_TRUE) != RT_TRUE)
{
/* close filerw context */
rtgui_filerw_close(filerw);
return RT_NULL;
}
/* set image engine */
image->engine = engine;
}
else
{
rtgui_filerw_close(filerw);
}
return image;
}
void rtgui_image_destroy(struct rtgui_image* image)
{
RT_ASSERT(image != RT_NULL);
image->engine->image_unload(image);
rtgui_free(image);
}
/* register an image engine */
void rtgui_image_register_engine(struct rtgui_image_engine* engine)
{
RT_ASSERT(engine!= RT_NULL);
rtgui_list_append(&_rtgui_system_image_list, &(engine->list));
}
void rtgui_image_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect)
{
RT_ASSERT(dc != RT_NULL);
RT_ASSERT(rect != RT_NULL);
if (rtgui_dc_get_visible(dc) != RT_TRUE) return;
if (image != RT_NULL && image->engine != RT_NULL)
{
/* use image engine to blit */
image->engine->image_blit(image, dc, rect);
}
}
/*
* File : image_xpm.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <stdio.h>
#include <string.h>
#include <rtgui/filerw.h>
#include <rtgui/image_xpm.h>
#include <rtgui/rtgui_system.h>
#define XPM_MAGIC_LEN 9
static rt_bool_t rtgui_image_xpm_check(struct rtgui_filerw * file);
static rt_bool_t rtgui_image_xpm_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
static void rtgui_image_xpm_unload(struct rtgui_image* image);
static void rtgui_image_xpm_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
struct rtgui_image_engine rtgui_image_xpm_engine =
{
"xpm",
{RT_NULL},
rtgui_image_xpm_check,
rtgui_image_xpm_load,
rtgui_image_xpm_unload,
rtgui_image_xpm_blit
};
struct rgb_item
{
char *name;
int r;
int g;
int b;
};
const struct rgb_item rgbRecord[234] = {
{"AliceBlue", 240, 248, 255},
{"AntiqueWhite", 250, 235, 215},
{"Aquamarine", 50, 191, 193},
{"Azure", 240, 255, 255},
{"Beige", 245, 245, 220},
{"Bisque", 255, 228, 196},
{"Black", 0, 0, 0},
{"BlanchedAlmond", 255, 235, 205},
{"Blue", 0, 0, 255},
{"BlueViolet", 138, 43, 226},
{"Brown", 165, 42, 42},
{"burlywood", 222, 184, 135},
{"CadetBlue", 95, 146, 158},
{"chartreuse", 127, 255, 0},
{"chocolate", 210, 105, 30},
{"Coral", 255, 114, 86},
{"CornflowerBlue", 34, 34, 152},
{"cornsilk", 255, 248, 220},
{"Cyan", 0, 255, 255},
{"DarkGoldenrod", 184, 134, 11},
{"DarkGreen", 0, 86, 45},
{"DarkKhaki", 189, 183, 107},
{"DarkOliveGreen", 85, 86, 47},
{"DarkOrange", 255, 140, 0},
{"DarkOrchid", 139, 32, 139},
{"DarkSalmon", 233, 150, 122},
{"DarkSeaGreen", 143, 188, 143},
{"DarkSlateBlue", 56, 75, 102},
{"DarkSlateGray", 47, 79, 79},
{"DarkTurquoise", 0, 166, 166},
{"DarkViolet", 148, 0, 211},
{"DeepPink", 255, 20, 147},
{"DeepSkyBlue", 0, 191, 255},
{"DimGray", 84, 84, 84},
{"DodgerBlue", 30, 144, 255},
{"Firebrick", 142, 35, 35},
{"FloralWhite", 255, 250, 240},
{"ForestGreen", 80, 159, 105},
{"gainsboro", 220, 220, 220},
{"GhostWhite", 248, 248, 255},
{"Gold", 218, 170, 0},
{"Goldenrod", 239, 223, 132},
{"Gray", 126, 126, 126},
{"Gray0", 0, 0, 0},
{"Gray1", 3, 3, 3},
{"Gray10", 26, 26, 26},
{"Gray100", 255, 255, 255},
{"Gray11", 28, 28, 28},
{"Gray12", 31, 31, 31},
{"Gray13", 33, 33, 33},
{"Gray14", 36, 36, 36},
{"Gray15", 38, 38, 38},
{"Gray16", 41, 41, 41},
{"Gray17", 43, 43, 43},
{"Gray18", 46, 46, 46},
{"Gray19", 48, 48, 48},
{"Gray2", 5, 5, 5},
{"Gray20", 51, 51, 51},
{"Gray21", 54, 54, 54},
{"Gray22", 56, 56, 56},
{"Gray23", 59, 59, 59},
{"Gray24", 61, 61, 61},
{"Gray25", 64, 64, 64},
{"Gray26", 66, 66, 66},
{"Gray27", 69, 69, 69},
{"Gray28", 71, 71, 71},
{"Gray29", 74, 74, 74},
{"Gray3", 8, 8, 8},
{"Gray30", 77, 77, 77},
{"Gray31", 79, 79, 79},
{"Gray32", 82, 82, 82},
{"Gray33", 84, 84, 84},
{"Gray34", 87, 87, 87},
{"Gray35", 89, 89, 89},
{"Gray36", 92, 92, 92},
{"Gray37", 94, 94, 94},
{"Gray38", 97, 97, 97},
{"Gray39", 99, 99, 99},
{"Gray4", 10, 10, 10},
{"Gray40", 102, 102, 102},
{"Gray41", 105, 105, 105},
{"Gray42", 107, 107, 107},
{"Gray43", 110, 110, 110},
{"Gray44", 112, 112, 112},
{"Gray45", 115, 115, 115},
{"Gray46", 117, 117, 117},
{"Gray47", 120, 120, 120},
{"Gray48", 122, 122, 122},
{"Gray49", 125, 125, 125},
{"Gray5", 13, 13, 13},
{"Gray50", 127, 127, 127},
{"Gray51", 130, 130, 130},
{"Gray52", 133, 133, 133},
{"Gray53", 135, 135, 135},
{"Gray54", 138, 138, 138},
{"Gray55", 140, 140, 140},
{"Gray56", 143, 143, 143},
{"Gray57", 145, 145, 145},
{"Gray58", 148, 148, 148},
{"Gray59", 150, 150, 150},
{"Gray6", 15, 15, 15},
{"Gray60", 153, 153, 153},
{"Gray61", 156, 156, 156},
{"Gray62", 158, 158, 158},
{"Gray63", 161, 161, 161},
{"Gray64", 163, 163, 163},
{"Gray65", 166, 166, 166},
{"Gray66", 168, 168, 168},
{"Gray67", 171, 171, 171},
{"Gray68", 173, 173, 173},
{"Gray69", 176, 176, 176},
{"Gray7", 18, 18, 18},
{"Gray70", 179, 179, 179},
{"Gray71", 181, 181, 181},
{"Gray72", 184, 184, 184},
{"Gray73", 186, 186, 186},
{"Gray74", 189, 189, 189},
{"Gray75", 191, 191, 191},
{"Gray76", 194, 194, 194},
{"Gray77", 196, 196, 196},
{"Gray78", 199, 199, 199},
{"Gray79", 201, 201, 201},
{"Gray8", 20, 20, 20},
{"Gray80", 204, 204, 204},
{"Gray81", 207, 207, 207},
{"Gray82", 209, 209, 209},
{"Gray83", 212, 212, 212},
{"Gray84", 214, 214, 214},
{"Gray85", 217, 217, 217},
{"Gray86", 219, 219, 219},
{"Gray87", 222, 222, 222},
{"Gray88", 224, 224, 224},
{"Gray89", 227, 227, 227},
{"Gray9", 23, 23, 23},
{"Gray90", 229, 229, 229},
{"Gray91", 232, 232, 232},
{"Gray92", 235, 235, 235},
{"Gray93", 237, 237, 237},
{"Gray94", 240, 240, 240},
{"Gray95", 242, 242, 242},
{"Gray96", 245, 245, 245},
{"Gray97", 247, 247, 247},
{"Gray98", 250, 250, 250},
{"Gray99", 252, 252, 252},
{"Green", 0, 255, 0},
{"GreenYellow", 173, 255, 47},
{"honeydew", 240, 255, 240},
{"HotPink", 255, 105, 180},
{"IndianRed", 107, 57, 57},
{"ivory", 255, 255, 240},
{"Khaki", 179, 179, 126},
{"lavender", 230, 230, 250},
{"LavenderBlush", 255, 240, 245},
{"LawnGreen", 124, 252, 0},
{"LemonChiffon", 255, 250, 205},
{"LightBlue", 176, 226, 255},
{"LightCoral", 240, 128, 128},
{"LightCyan", 224, 255, 255},
{"LightGoldenrod", 238, 221, 130},
{"LightGoldenrodYellow", 250, 250, 210},
{"LightGray", 168, 168, 168},
{"LightPink", 255, 182, 193},
{"LightSalmon", 255, 160, 122},
{"LightSeaGreen", 32, 178, 170},
{"LightSkyBlue", 135, 206, 250},
{"LightSlateBlue", 132, 112, 255},
{"LightSlateGray", 119, 136, 153},
{"LightSteelBlue", 124, 152, 211},
{"LightYellow", 255, 255, 224},
{"LimeGreen", 0, 175, 20},
{"linen", 250, 240, 230},
{"Magenta", 255, 0, 255},
{"Maroon", 143, 0, 82},
{"MediumAquamarine", 0, 147, 143},
{"MediumBlue", 50, 50, 204},
{"MediumForestGreen", 50, 129, 75},
{"MediumGoldenrod", 209, 193, 102},
{"MediumOrchid", 189, 82, 189},
{"MediumPurple", 147, 112, 219},
{"MediumSeaGreen", 52, 119, 102},
{"MediumSlateBlue", 106, 106, 141},
{"MediumSpringGreen", 35, 142, 35},
{"MediumTurquoise", 0, 210, 210},
{"MediumVioletRed", 213, 32, 121},
{"MidnightBlue", 47, 47, 100},
{"MintCream", 245, 255, 250},
{"MistyRose", 255, 228, 225},
{"moccasin", 255, 228, 181},
{"NavajoWhite", 255, 222, 173},
{"Navy", 35, 35, 117},
{"NavyBlue", 35, 35, 117},
{"OldLace", 253, 245, 230},
{"OliveDrab", 107, 142, 35},
{"Orange", 255, 135, 0},
{"OrangeRed", 255, 69, 0},
{"Orchid", 239, 132, 239},
{"PaleGoldenrod", 238, 232, 170},
{"PaleGreen", 115, 222, 120},
{"PaleTurquoise", 175, 238, 238},
{"PaleVioletRed", 219, 112, 147},
{"PapayaWhip", 255, 239, 213},
{"PeachPuff", 255, 218, 185},
{"peru", 205, 133, 63},
{"Pink", 255, 181, 197},
{"Plum", 197, 72, 155},
{"PowderBlue", 176, 224, 230},
{"purple", 160, 32, 240},
{"Red", 255, 0, 0},
{"RosyBrown", 188, 143, 143},
{"RoyalBlue", 65, 105, 225},
{"SaddleBrown", 139, 69, 19},
{"Salmon", 233, 150, 122},
{"SandyBrown", 244, 164, 96},
{"SeaGreen", 82, 149, 132},
{"seashell", 255, 245, 238},
{"Sienna", 150, 82, 45},
{"SkyBlue", 114, 159, 255},
{"SlateBlue", 126, 136, 171},
{"SlateGray", 112, 128, 144},
{"snow", 255, 250, 250},
{"SpringGreen", 65, 172, 65},
{"SteelBlue", 84, 112, 170},
{"Tan", 222, 184, 135},
{"Thistle", 216, 191, 216},
{"tomato", 255, 99, 71},
{"Transparent", 0, 0, 1},
{"Turquoise", 25, 204, 223},
{"Violet", 156, 62, 206},
{"VioletRed", 243, 62, 150},
{"Wheat", 245, 222, 179},
{"White", 255, 255, 255},
{"WhiteSmoke", 245, 245, 245},
{"Yellow", 255, 255, 0},
{"YellowGreen", 50, 216, 56}
};
/* Hash table to look up colors from pixel strings */
#define STARTING_HASH_SIZE 256
struct hash_entry
{
char key[10];
rtgui_color_t color;
struct hash_entry *next;
};
struct color_hash
{
struct hash_entry **table;
struct hash_entry *entries; /* array of all entries */
struct hash_entry *next_free;
int size;
int maxnum;
};
static int hash_key(const char *key, int cpp, int size)
{
int hash;
hash = 0;
while ( cpp-- > 0 )
{
hash = hash * 33 + *key++;
}
return hash & (size - 1);
}
static struct color_hash *create_colorhash(int maxnum)
{
int bytes, s;
struct color_hash *hash;
/* we know how many entries we need, so we can allocate
everything here */
hash = rtgui_malloc(sizeof *hash);
if(!hash) return RT_NULL;
/* use power-of-2 sized hash table for decoding speed */
for(s = STARTING_HASH_SIZE; s < maxnum; s <<= 1) ;
hash->size = s;
hash->maxnum = maxnum;
bytes = hash->size * sizeof(struct hash_entry **);
hash->entries = RT_NULL; /* in case rt_malloc fails */
hash->table = rtgui_malloc(bytes);
if(!hash->table) return RT_NULL;
rt_memset(hash->table, 0, bytes);
hash->entries = rtgui_malloc(maxnum * sizeof(struct hash_entry));
if(!hash->entries) return RT_NULL;
hash->next_free = hash->entries;
return hash;
}
static int add_colorhash(struct color_hash *hash,
char *key, int cpp, rtgui_color_t *color)
{
int index = hash_key(key, cpp, hash->size);
struct hash_entry *e = hash->next_free++;
e->color = *color;
rt_memset(e->key, 0, sizeof(e->key));
rt_strncpy(e->key, key, cpp);
e->next = hash->table[index];
hash->table[index] = e;
return 1;
}
static void get_colorhash(struct color_hash *hash, const char *key, int cpp, rtgui_color_t* c)
{
struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
while(entry)
{
if(rt_memcmp(key, entry->key, cpp) == 0)
{
*c = entry->color;
return;
}
entry = entry->next;
}
return ; /* garbage in - garbage out */
}
static void free_colorhash(struct color_hash *hash)
{
if(hash && hash->table)
{
rtgui_free(hash->table);
rtgui_free(hash->entries);
rtgui_free(hash);
}
}
#if defined(_MSC_VER) || defined(__CC_ARM)
int strcasecmp( const char* s1, const char* s2 )
{
register unsigned int x2;
register unsigned int x1;
while (1) {
x2 = *s2 - 'A'; if (x2 < 26u) x2 += 32;
x1 = *s1 - 'A'; if (x1 < 26u) x1 += 32;
s1++; s2++;
if (x2 != x1)
break;
if (x1 == (unsigned int)-'A')
break;
}
return x1 - x2;
}
#endif
static int hex2int (char *str)
{
int i = 0;
int r = 0;
for (i = 0; i < 2; i++)
{
if (str[i] >= '0' && str[i] <= '9') r += str[i] - '0';
else if (str[i] >= 'a' && str[i] <= 'f') r += str[i] - 'a' + 10;
else if (str[i] >= 'A' && str[i] <= 'F') r += str[i] - 'A' + 10;
if (!i) r *= 16;
}
return r;
}
void rtgui_image_xpm_init()
{
/* register xpm engine */
rtgui_image_register_engine(&rtgui_image_xpm_engine);
}
static rt_bool_t rtgui_image_xpm_check(struct rtgui_filerw* file)
{
#if 0
rt_uint8_t buffer[XPM_MAGIC_LEN];
rt_size_t start;
rt_bool_t result;
result = RT_FALSE;
start = rtgui_filerw_tell(file);
/* seek to the begining of file */
if (start != 0) rtgui_filerw_seek(file, 0, SEEK_SET);
rtgui_filerw_read(file, &buffer[0], XPM_MAGIC_LEN, 1);
if (rt_memcmp(buffer, "/* XPM */", (rt_ubase_t)XPM_MAGIC_LEN) == 0)
result = RT_TRUE;
rtgui_filerw_seek(file, start, SEEK_SET);
return result;
#else
/* we can not check image type for memory file */
return RT_TRUE;
#endif
}
static rt_bool_t rtgui_image_xpm_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
{
const char **xpm;
const char *buf;
const char *buf_tmp;
int w, h;
int colors = 0;
int colors_pp = 0;
int i, j;
/* color hash table */
struct color_hash *colors_table = RT_NULL;
if (image == RT_NULL) return RT_FALSE;
xpm = (const char **)rtgui_filerw_mem_getdata(file);
if (xpm == RT_NULL) return RT_FALSE;
/* set image engine */
image->engine = &rtgui_image_xpm_engine;
/* parse xpm image */
sscanf(xpm[0], "%d %d %d %d", &w, &h, &colors, &colors_pp);
image->w = w;
image->h = h;
/* build color table */
colors_table = create_colorhash(colors);
if (!colors_table)
{
return RT_FALSE;
}
for (i = 0; i < colors; i++)
{
char color_name[10];
rtgui_color_t c = 0;
buf = xpm[i + 1];
for (j = 0; j < colors_pp; j++)
{
color_name[j] = buf[j];
}
color_name[j] = '\0';
/* build rtgui_color */
if ((buf_tmp = strstr(buf, "c #")) != RT_NULL)
{
char color_hex[10];
/* hexadecimal color value */
sscanf(buf_tmp, "c #%s", color_hex);
c = RTGUI_ARGB(0, hex2int(color_hex),
hex2int(color_hex + 2),
hex2int(color_hex + 4));
}
else if ((buf_tmp = strstr(buf, "c ")) != RT_NULL)
{
int k;
/* color name */
char rgbname[30];
sscanf(buf_tmp, "c %s", rgbname);
if (strcasecmp(rgbname, "None") == 0)
{
goto color_none;
}
for (k = 0; k < 234; k++)
{
if (strcasecmp(rgbname, rgbRecord[k].name) == 0)
{
c = RTGUI_ARGB(0, rgbRecord[k].r,
rgbRecord[k].g,
rgbRecord[k].b);
break;
}
}
}
else
{
color_none:
c = RTGUI_RGB(0, 0, 0);
}
/* add to color hash table */
add_colorhash(colors_table, color_name, colors_pp, &c);
}
/* build rgb pixel data */
image->data = (rt_uint8_t*) rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t));
memset(image->data, 0, image->w * image->h * sizeof(rtgui_color_t));
{
rtgui_color_t *ptr = (rtgui_color_t*) image->data;
for (h = 0; h < image->h; h++)
{
buf = xpm[colors + 1 + h];
for (w = 0; w < image->w; w++, buf += colors_pp)
{
get_colorhash(colors_table, buf, colors_pp, ptr);
ptr ++;
}
}
}
free_colorhash(colors_table);
return RT_TRUE;
}
static void rtgui_image_xpm_unload(struct rtgui_image* image)
{
if (image != RT_NULL)
{
/* release data */
rtgui_free(image->data);
image->data = RT_NULL;
}
}
static void rtgui_image_xpm_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect)
{
rt_uint16_t x, y;
rtgui_color_t* ptr;
rtgui_color_t foreground;
RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
RT_ASSERT(image->data != RT_NULL);
ptr = (rtgui_color_t*) image->data;
/* save foreground color */
foreground = rtgui_dc_get_color(dc);
/* draw each point within dc */
for (y = 0; y < image->h; y ++)
{
for (x = 0; x < image->w; x++)
{
/* not alpha */
if ((*ptr >> 24) != 255)
{
rtgui_dc_set_color(dc, *ptr);
rtgui_dc_draw_point(dc, x + rect->x1, y + rect->y1);
}
/* move to next color buffer */
ptr ++;
}
}
/* restore foreground */
rtgui_dc_set_color(dc, foreground);
}
/*
* File : region.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/region.h>
#include <rtgui/rtgui_system.h>
/* #define good(reg) RT_ASSERT(rtgui_region16_valid(reg)) */
#define good(reg)
#define RTGUI_MIN(a,b) ((a) < (b) ? (a) : (b))
#define RTGUI_MAX(a,b) ((a) > (b) ? (a) : (b))
#define RTGUI_SHRT_MIN (-32767-1)
#define RTGUI_SHRT_MAX 32767
#define PIXREGION_NIL(reg) ((reg)->data && !(reg)->data->numRects)
/* not a region */
#define PIXREGION_NAR(reg) ((reg)->data == &rtgui_brokendata)
#define PIXREGION_NUM_RECTS(reg) ((reg)->data ? (reg)->data->numRects : 1)
#define PIXREGION_SIZE(reg) ((reg)->data ? (reg)->data->size : 0)
#define PIXREGION_RECTS(reg) ((reg)->data ? (rtgui_rect_t *)((reg)->data + 1) \
: &(reg)->extents)
#define PIXREGION_BOXPTR(reg) ((rtgui_rect_t *)((reg)->data + 1))
#define PIXREGION_BOX(reg,i) (&PIXREGION_BOXPTR(reg)[i])
#define PIXREGION_TOP(reg) PIXREGION_BOX(reg, (reg)->data->numRects)
#define PIXREGION_END(reg) PIXREGION_BOX(reg, (reg)->data->numRects - 1)
#define PIXREGION_SZOF(n) (sizeof(rtgui_region_data_t) + ((n) * sizeof(rtgui_rect_t)))
rtgui_rect_t rtgui_empty_rect = {0, 0, 0, 0};
static rtgui_region_data_t rtgui_region_emptydata = {0, 0};
static rtgui_region_data_t rtgui_brokendata = {0, 0};
static rtgui_region_status_t rtgui_break(rtgui_region_t *pReg);
/*
* The functions in this file implement the Region abstraction used extensively
* throughout the X11 sample server. A Region is simply a set of disjoint
* (non-overlapping) rectangles, plus an "extent" rectangle which is the
* smallest single rectangle that contains all the non-overlapping rectangles.
*
* A Region is implemented as a "y-x-banded" array of rectangles. This array
* imposes two degrees of order. First, all rectangles are sorted by top side
* y coordinate first (y1), and then by left side x coordinate (x1).
*
* Furthermore, the rectangles are grouped into "bands". Each rectangle in a
* band has the same top y coordinate (y1), and each has the same bottom y
* coordinate (y2). Thus all rectangles in a band differ only in their left
* and right side (x1 and x2). Bands are implicit in the array of rectangles:
* there is no separate list of band start pointers.
*
* The y-x band representation does not RTGUI_MINimize rectangles. In particular,
* if a rectangle vertically crosses a band (the rectangle has scanlines in
* the y1 to y2 area spanned by the band), then the rectangle may be broken
* down into two or more smaller rectangles stacked one atop the other.
*
* ----------- -----------
* | | | | band 0
* | | -------- ----------- --------
* | | | | in y-x banded | | | | band 1
* | | | | form is | | | |
* ----------- | | ----------- --------
* | | | | band 2
* -------- --------
*
* An added constraint on the rectangles is that they must cover as much
* horizontal area as possible: no two rectangles within a band are allowed
* to touch.
*
* Whenever possible, bands will be merged together to cover a greater vertical
* distance (and thus reduce the number of rectangles). Two bands can be merged
* only if the bottom of one touches the top of the other and they have
* rectangles in the same places (of the same width, of course).
*
* Adam de Boor wrote most of the original region code. Joel McCormack
* substantially modified or rewrote most of the core arithmetic routines, and
* added rtgui_region_validate in order to support several speed improvements to
* rtgui_region_validateTree. Bob Scheifler changed the representation to be more
* compact when empty or a single rectangle, and did a bunch of gratuitous
* reformatting. Carl Worth did further gratuitous reformatting while re-merging
* the server and client region code into libpixregion.
*/
/* true iff two Boxes overlap */
#define EXTENTCHECK(r1,r2) \
(!( ((r1)->x2 <= (r2)->x1) || \
((r1)->x1 >= (r2)->x2) || \
((r1)->y2 <= (r2)->y1) || \
((r1)->y1 >= (r2)->y2) ) )
/* true iff (x,y) is in Box */
#define INBOX(r,x,y) \
( ((r)->x2 > (x)) && \
((r)->x1 <= (x)) && \
((r)->y2 > (y)) && \
((r)->y1 <= (y)) )
/* true iff Box r1 contains Box r2 */
#define SUBSUMES(r1,r2) \
( ((r1)->x1 <= (r2)->x1) && \
((r1)->x2 >= (r2)->x2) && \
((r1)->y1 <= (r2)->y1) && \
((r1)->y2 >= (r2)->y2) )
#define allocData(n) rtgui_malloc(PIXREGION_SZOF(n))
#define freeData(reg) if ((reg)->data && (reg)->data->size) rtgui_free((reg)->data)
#define RECTALLOC_BAIL(pReg,n,bail) \
if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
if (!rtgui_rect_alloc(pReg, n)) { goto bail; }
#define RECTALLOC(pReg,n) \
if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \
if (!rtgui_rect_alloc(pReg, n)) { return RTGUI_REGION_STATUS_FAILURE; }
#define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \
{ \
pNextRect->x1 = nx1; \
pNextRect->y1 = ny1; \
pNextRect->x2 = nx2; \
pNextRect->y2 = ny2; \
pNextRect++; \
}
#define NEWRECT(pReg,pNextRect,nx1,ny1,nx2,ny2) \
{ \
if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\
{ \
if (!rtgui_rect_alloc(pReg, 1)) \
return RTGUI_REGION_STATUS_FAILURE; \
pNextRect = PIXREGION_TOP(pReg); \
} \
ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \
pReg->data->numRects++; \
RT_ASSERT(pReg->data->numRects<=pReg->data->size); \
}
#define DOWNSIZE(reg,numRects) \
if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \
{ \
rtgui_region_data_t * NewData; \
NewData = (rtgui_region_data_t *)rt_realloc((reg)->data, PIXREGION_SZOF(numRects)); \
if (NewData) \
{ \
NewData->size = (numRects); \
(reg)->data = NewData; \
} \
}
void rtgui_region_init(rtgui_region_t *region)
{
region->extents = rtgui_empty_rect;
region->data = &rtgui_region_emptydata;
}
void rtgui_region_init_rect(rtgui_region_t *region,
int x, int y, unsigned int width, unsigned int height)
{
region->extents.x1 = x;
region->extents.y1 = y;
region->extents.x2 = x + width;
region->extents.y2 = y + height;
region->data = RT_NULL;
}
void rtgui_region_init_with_extents(rtgui_region_t *region, rtgui_rect_t *extents)
{
region->extents = *extents;
region->data = RT_NULL;
}
void rtgui_region_fini (rtgui_region_t *region)
{
good (region);
freeData (region);
}
int rtgui_region_num_rects (rtgui_region_t *region)
{
return PIXREGION_NUM_RECTS (region);
}
rtgui_rect_t *rtgui_region_rects (rtgui_region_t *region)
{
return PIXREGION_RECTS (region);
}
static rtgui_region_status_t rtgui_break (rtgui_region_t *region)
{
freeData (region);
region->extents = rtgui_empty_rect;
region->data = &rtgui_brokendata;
return RTGUI_REGION_STATUS_FAILURE;
}
static rtgui_region_status_t rtgui_rect_alloc(rtgui_region_t * region, int n)
{
rtgui_region_data_t *data;
if (!region->data)
{
n++;
region->data = allocData(n);
if (!region->data) return rtgui_break (region);
region->data->numRects = 1;
*PIXREGION_BOXPTR(region) = region->extents;
}
else if (!region->data->size)
{
region->data = allocData(n);
if (!region->data) return rtgui_break (region);
region->data->numRects = 0;
}
else
{
if (n == 1)
{
n = region->data->numRects;
if (n > 500) /* XXX pick numbers out of a hat */
n = 250;
}
n += region->data->numRects;
data = (rtgui_region_data_t *)rt_realloc(region->data, PIXREGION_SZOF(n));
if (!data) return rtgui_break (region);
region->data = data;
}
region->data->size = n;
return RTGUI_REGION_STATUS_SUCCESS;
}
rtgui_region_status_t rtgui_region_copy(rtgui_region_t *dst, rtgui_region_t *src)
{
good(dst);
good(src);
if (dst == src)
return RTGUI_REGION_STATUS_SUCCESS;
dst->extents = src->extents;
if (!src->data || !src->data->size)
{
freeData(dst);
dst->data = src->data;
return RTGUI_REGION_STATUS_SUCCESS;
}
if (!dst->data || (dst->data->size < src->data->numRects))
{
freeData(dst);
dst->data = allocData(src->data->numRects);
if (!dst->data) return rtgui_break (dst);
dst->data->size = src->data->numRects;
}
dst->data->numRects = src->data->numRects;
rt_memmove((char *)PIXREGION_BOXPTR(dst),(char *)PIXREGION_BOXPTR(src),
dst->data->numRects * sizeof(rtgui_rect_t));
return RTGUI_REGION_STATUS_SUCCESS;
}
/*======================================================================
* Generic Region Operator
*====================================================================*/
/*-
*-----------------------------------------------------------------------
* rtgui_coalesce --
* Attempt to merge the boxes in the current band with those in the
* previous one. We are guaranteed that the current band extends to
* the end of the rects array. Used only by rtgui_op.
*
* Results:
* The new index for the previous band.
*
* Side Effects:
* If coalescing takes place:
* - rectangles in the previous band will have their y2 fields
* altered.
* - region->data->numRects will be decreased.
*
*-----------------------------------------------------------------------
*/
rt_inline int
rtgui_coalesce (
rtgui_region_t *region, /* Region to coalesce */
int prevStart, /* Index of start of previous band */
int curStart) /* Index of start of current band */
{
rtgui_rect_t * pPrevBox; /* Current box in previous band */
rtgui_rect_t * pCurBox; /* Current box in current band */
int numRects; /* Number rectangles in both bands */
int y2; /* Bottom of current band */
/*
* Figure out how many rectangles are in the band.
*/
numRects = curStart - prevStart;
RT_ASSERT(numRects == region->data->numRects - curStart);
if (!numRects) return curStart;
/*
* The bands may only be coalesced if the bottom of the previous
* matches the top scanline of the current.
*/
pPrevBox = PIXREGION_BOX(region, prevStart);
pCurBox = PIXREGION_BOX(region, curStart);
if (pPrevBox->y2 != pCurBox->y1) return curStart;
/*
* Make sure the bands have boxes in the same places. This
* assumes that boxes have been added in such a way that they
* cover the most area possible. I.e. two boxes in a band must
* have some horizontal space between them.
*/
y2 = pCurBox->y2;
do
{
if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2))
{
return (curStart);
}
pPrevBox++;
pCurBox++;
numRects--;
}
while (numRects);
/*
* The bands may be merged, so set the bottom y of each box
* in the previous band to the bottom y of the current band.
*/
numRects = curStart - prevStart;
region->data->numRects -= numRects;
do
{
pPrevBox--;
pPrevBox->y2 = y2;
numRects--;
}
while (numRects);
return prevStart;
}
/* Quicky macro to avoid trivial reject procedure calls to rtgui_coalesce */
#define Coalesce(newReg, prevBand, curBand) \
if (curBand - prevBand == newReg->data->numRects - curBand) { \
prevBand = rtgui_coalesce(newReg, prevBand, curBand); \
} else { \
prevBand = curBand; \
}
/*-
*-----------------------------------------------------------------------
* rtgui_region_appendNonO --
* Handle a non-overlapping band for the union and subtract operations.
* Just adds the (top/bottom-clipped) rectangles into the region.
* Doesn't have to check for subsumption or anything.
*
* Results:
* None.
*
* Side Effects:
* region->data->numRects is incremented and the rectangles overwritten
* with the rectangles we're passed.
*
*-----------------------------------------------------------------------
*/
rt_inline rtgui_region_status_t
rtgui_region_appendNonO (
rtgui_region_t *region,
rtgui_rect_t *r,
rtgui_rect_t *rEnd,
int y1,
int y2)
{
rtgui_rect_t * pNextRect;
int newRects;
newRects = rEnd - r;
RT_ASSERT(y1 < y2);
RT_ASSERT(newRects != 0);
/* Make sure we have enough space for all rectangles to be added */
RECTALLOC(region, newRects);
pNextRect = PIXREGION_TOP(region);
region->data->numRects += newRects;
do
{
RT_ASSERT(r->x1 < r->x2);
ADDRECT(pNextRect, r->x1, y1, r->x2, y2);
r++;
}
while (r != rEnd);
return RTGUI_REGION_STATUS_SUCCESS;
}
#define FindBand(r, rBandEnd, rEnd, ry1) \
{ \
ry1 = r->y1; \
rBandEnd = r+1; \
while ((rBandEnd != rEnd) && (rBandEnd->y1 == ry1)) { \
rBandEnd++; \
} \
}
#define AppendRegions(newReg, r, rEnd) \
{ \
int newRects = rEnd - r; \
if (newRects) { \
RECTALLOC(newReg, newRects); \
rt_memmove((char *)PIXREGION_TOP(newReg),(char *)r, \
newRects * sizeof(rtgui_rect_t)); \
newReg->data->numRects += newRects; \
} \
}
/*-
*-----------------------------------------------------------------------
* rtgui_op --
* Apply an operation to two regions. Called by rtgui_region_union, rtgui_region_inverse,
* rtgui_region_subtract, rtgui_region_intersect.... Both regions MUST have at least one
* rectangle, and cannot be the same object.
*
* Results:
* RTGUI_REGION_STATUS_SUCCESS if successful.
*
* Side Effects:
* The new region is overwritten.
* pOverlap set to RTGUI_REGION_STATUS_SUCCESS if overlapFunc ever returns RTGUI_REGION_STATUS_SUCCESS.
*
* Notes:
* The idea behind this function is to view the two regions as sets.
* Together they cover a rectangle of area that this function divides
* into horizontal bands where points are covered only by one region
* or by both. For the first case, the nonOverlapFunc is called with
* each the band and the band's upper and lower extents. For the
* second, the overlapFunc is called to process the entire band. It
* is responsible for clipping the rectangles in the band, though
* this function provides the boundaries.
* At the end of each band, the new region is coalesced, if possible,
* to reduce the number of rectangles in the region.
*
*-----------------------------------------------------------------------
*/
typedef rtgui_region_status_t (*OverlapProcPtr)(
rtgui_region_t *region,
rtgui_rect_t *r1,
rtgui_rect_t *r1End,
rtgui_rect_t *r2,
rtgui_rect_t *r2End,
short y1,
short y2,
int *pOverlap);
static rtgui_region_status_t
rtgui_op(
rtgui_region_t *newReg, /* Place to store result */
rtgui_region_t *reg1, /* First region in operation */
rtgui_region_t *reg2, /* 2d region in operation */
OverlapProcPtr overlapFunc, /* Function to call for over-
* lapping bands */
int appendNon1, /* Append non-overlapping bands */
/* in region 1 ? */
int appendNon2, /* Append non-overlapping bands */
/* in region 2 ? */
int *pOverlap)
{
rtgui_rect_t * r1; /* Pointer into first region */
rtgui_rect_t * r2; /* Pointer into 2d region */
rtgui_rect_t * r1End; /* End of 1st region */
rtgui_rect_t * r2End; /* End of 2d region */
short ybot; /* Bottom of intersection */
short ytop; /* Top of intersection */
rtgui_region_data_t * oldData; /* Old data for newReg */
int prevBand; /* Index of start of
* previous band in newReg */
int curBand; /* Index of start of current
* band in newReg */
rtgui_rect_t * r1BandEnd; /* End of current band in r1 */
rtgui_rect_t * r2BandEnd; /* End of current band in r2 */
short top; /* Top of non-overlapping band */
short bot; /* Bottom of non-overlapping band*/
int r1y1; /* Temps for r1->y1 and r2->y1 */
int r2y1;
int newSize;
int numRects;
/*
* Break any region computed from a broken region
*/
if (PIXREGION_NAR (reg1) || PIXREGION_NAR(reg2))
return rtgui_break (newReg);
/*
* Initialization:
* set r1, r2, r1End and r2End appropriately, save the rectangles
* of the destination region until the end in case it's one of
* the two source regions, then mark the "new" region empty, allocating
* another array of rectangles for it to use.
*/
r1 = PIXREGION_RECTS(reg1);
newSize = PIXREGION_NUM_RECTS(reg1);
r1End = r1 + newSize;
numRects = PIXREGION_NUM_RECTS(reg2);
r2 = PIXREGION_RECTS(reg2);
r2End = r2 + numRects;
RT_ASSERT(r1 != r1End);
RT_ASSERT(r2 != r2End);
oldData = (rtgui_region_data_t *)RT_NULL;
if (((newReg == reg1) && (newSize > 1)) ||
((newReg == reg2) && (numRects > 1)))
{
oldData = newReg->data;
newReg->data = &rtgui_region_emptydata;
}
/* guess at new size */
if (numRects > newSize)
newSize = numRects;
newSize <<= 1;
if (!newReg->data)
newReg->data = &rtgui_region_emptydata;
else if (newReg->data->size)
newReg->data->numRects = 0;
if (newSize > newReg->data->size)
if (!rtgui_rect_alloc(newReg, newSize))
return RTGUI_REGION_STATUS_FAILURE;
/*
* Initialize ybot.
* In the upcoRTGUI_MINg loop, ybot and ytop serve different functions depending
* on whether the band being handled is an overlapping or non-overlapping
* band.
* In the case of a non-overlapping band (only one of the regions
* has points in the band), ybot is the bottom of the most recent
* intersection and thus clips the top of the rectangles in that band.
* ytop is the top of the next intersection between the two regions and
* serves to clip the bottom of the rectangles in the current band.
* For an overlapping band (where the two regions intersect), ytop clips
* the top of the rectangles of both regions and ybot clips the bottoms.
*/
ybot = RTGUI_MIN(r1->y1, r2->y1);
/*
* prevBand serves to mark the start of the previous band so rectangles
* can be coalesced into larger rectangles. qv. rtgui_coalesce, above.
* In the beginning, there is no previous band, so prevBand == curBand
* (curBand is set later on, of course, but the first band will always
* start at index 0). prevBand and curBand must be indices because of
* the possible expansion, and resultant moving, of the new region's
* array of rectangles.
*/
prevBand = 0;
do
{
/*
* This algorithm proceeds one source-band (as opposed to a
* destination band, which is deterRTGUI_MINed by where the two regions
* intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
* rectangle after the last one in the current band for their
* respective regions.
*/
RT_ASSERT(r1 != r1End);
RT_ASSERT(r2 != r2End);
FindBand(r1, r1BandEnd, r1End, r1y1);
FindBand(r2, r2BandEnd, r2End, r2y1);
/*
* First handle the band that doesn't intersect, if any.
*
* Note that attention is restricted to one band in the
* non-intersecting region at once, so if a region has n
* bands between the current position and the next place it overlaps
* the other, this entire loop will be passed through n times.
*/
if (r1y1 < r2y1)
{
if (appendNon1)
{
top = RTGUI_MAX(r1y1, ybot);
bot = RTGUI_MIN(r1->y2, r2y1);
if (top != bot)
{
curBand = newReg->data->numRects;
rtgui_region_appendNonO(newReg, r1, r1BandEnd, top, bot);
Coalesce(newReg, prevBand, curBand);
}
}
ytop = r2y1;
}
else if (r2y1 < r1y1)
{
if (appendNon2)
{
top = RTGUI_MAX(r2y1, ybot);
bot = RTGUI_MIN(r2->y2, r1y1);
if (top != bot)
{
curBand = newReg->data->numRects;
rtgui_region_appendNonO(newReg, r2, r2BandEnd, top, bot);
Coalesce(newReg, prevBand, curBand);
}
}
ytop = r1y1;
}
else
{
ytop = r1y1;
}
/*
* Now see if we've hit an intersecting band. The two bands only
* intersect if ybot > ytop
*/
ybot = RTGUI_MIN(r1->y2, r2->y2);
if (ybot > ytop)
{
curBand = newReg->data->numRects;
(* overlapFunc)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot,
pOverlap);
Coalesce(newReg, prevBand, curBand);
}
/*
* If we've finished with a band (y2 == ybot) we skip forward
* in the region to the next band.
*/
if (r1->y2 == ybot) r1 = r1BandEnd;
if (r2->y2 == ybot) r2 = r2BandEnd;
}
while (r1 != r1End && r2 != r2End);
/*
* Deal with whichever region (if any) still has rectangles left.
*
* We only need to worry about banding and coalescing for the very first
* band left. After that, we can just group all remaining boxes,
* regardless of how many bands, into one final append to the list.
*/
if ((r1 != r1End) && appendNon1)
{
/* Do first nonOverlap1Func call, which may be able to coalesce */
FindBand(r1, r1BandEnd, r1End, r1y1);
curBand = newReg->data->numRects;
rtgui_region_appendNonO(newReg, r1, r1BandEnd, RTGUI_MAX(r1y1, ybot), r1->y2);
Coalesce(newReg, prevBand, curBand);
/* Just append the rest of the boxes */
AppendRegions(newReg, r1BandEnd, r1End);
}
else if ((r2 != r2End) && appendNon2)
{
/* Do first nonOverlap2Func call, which may be able to coalesce */
FindBand(r2, r2BandEnd, r2End, r2y1);
curBand = newReg->data->numRects;
rtgui_region_appendNonO(newReg, r2, r2BandEnd, RTGUI_MAX(r2y1, ybot), r2->y2);
Coalesce(newReg, prevBand, curBand);
/* Append rest of boxes */
AppendRegions(newReg, r2BandEnd, r2End);
}
if (oldData)
rtgui_free(oldData);
numRects = newReg->data->numRects;
if (!numRects)
{
freeData(newReg);
newReg->data = &rtgui_region_emptydata;
}
else if (numRects == 1)
{
newReg->extents = *PIXREGION_BOXPTR(newReg);
freeData(newReg);
newReg->data = (rtgui_region_data_t *)RT_NULL;
}
else
{
DOWNSIZE(newReg, numRects);
}
return RTGUI_REGION_STATUS_SUCCESS;
}
/*-
*-----------------------------------------------------------------------
* rtgui_set_extents --
* Reset the extents of a region to what they should be. Called by
* rtgui_region_subtract and rtgui_region_intersect as they can't figure it out along the
* way or do so easily, as rtgui_region_union can.
*
* Results:
* None.
*
* Side Effects:
* The region's 'extents' structure is overwritten.
*
*-----------------------------------------------------------------------
*/
static void
rtgui_set_extents (rtgui_region_t *region)
{
rtgui_rect_t *box, *boxEnd;
if (!region->data)
return;
if (!region->data->size)
{
region->extents.x2 = region->extents.x1;
region->extents.y2 = region->extents.y1;
return;
}
box = PIXREGION_BOXPTR(region);
boxEnd = PIXREGION_END(region);
/*
* Since box is the first rectangle in the region, it must have the
* smallest y1 and since boxEnd is the last rectangle in the region,
* it must have the largest y2, because of banding. Initialize x1 and
* x2 from box and boxEnd, resp., as good things to initialize them
* to...
*/
region->extents.x1 = box->x1;
region->extents.y1 = box->y1;
region->extents.x2 = boxEnd->x2;
region->extents.y2 = boxEnd->y2;
RT_ASSERT(region->extents.y1 < region->extents.y2);
while (box <= boxEnd)
{
if (box->x1 < region->extents.x1)
region->extents.x1 = box->x1;
if (box->x2 > region->extents.x2)
region->extents.x2 = box->x2;
box++;
};
RT_ASSERT(region->extents.x1 < region->extents.x2);
}
/*======================================================================
* Region Intersection
*====================================================================*/
/*-
*-----------------------------------------------------------------------
* rtgui_region_intersectO --
* Handle an overlapping band for rtgui_region_intersect.
*
* Results:
* RTGUI_REGION_STATUS_SUCCESS if successful.
*
* Side Effects:
* Rectangles may be added to the region.
*
*-----------------------------------------------------------------------
*/
/*ARGSUSED*/
static rtgui_region_status_t
rtgui_region_intersectO (
rtgui_region_t *region,
rtgui_rect_t *r1,
rtgui_rect_t *r1End,
rtgui_rect_t *r2,
rtgui_rect_t *r2End,
short y1,
short y2,
int *pOverlap)
{
int x1;
int x2;
rtgui_rect_t * pNextRect;
pNextRect = PIXREGION_TOP(region);
RT_ASSERT(y1 < y2);
RT_ASSERT(r1 != r1End && r2 != r2End);
do
{
x1 = RTGUI_MAX(r1->x1, r2->x1);
x2 = RTGUI_MIN(r1->x2, r2->x2);
/*
* If there's any overlap between the two rectangles, add that
* overlap to the new region.
*/
if (x1 < x2)
NEWRECT(region, pNextRect, x1, y1, x2, y2);
/*
* Advance the pointer(s) with the leftmost right side, since the next
* rectangle on that list may still overlap the other region's
* current rectangle.
*/
if (r1->x2 == x2)
{
r1++;
}
if (r2->x2 == x2)
{
r2++;
}
}
while ((r1 != r1End) && (r2 != r2End));
return RTGUI_REGION_STATUS_SUCCESS;
}
rtgui_region_status_t
rtgui_region_intersect(rtgui_region_t *newReg,
rtgui_region_t *reg1,
rtgui_region_t *reg2)
{
good(reg1);
good(reg2);
good(newReg);
/* check for trivial reject */
if (PIXREGION_NIL(reg1) || PIXREGION_NIL(reg2) ||
!EXTENTCHECK(&reg1->extents, &reg2->extents))
{
/* Covers about 20% of all cases */
freeData(newReg);
newReg->extents.x2 = newReg->extents.x1;
newReg->extents.y2 = newReg->extents.y1;
if (PIXREGION_NAR(reg1) || PIXREGION_NAR(reg2))
{
newReg->data = &rtgui_brokendata;
return RTGUI_REGION_STATUS_FAILURE;
}
else
newReg->data = &rtgui_region_emptydata;
}
else if (!reg1->data && !reg2->data)
{
/* Covers about 80% of cases that aren't trivially rejected */
newReg->extents.x1 = RTGUI_MAX(reg1->extents.x1, reg2->extents.x1);
newReg->extents.y1 = RTGUI_MAX(reg1->extents.y1, reg2->extents.y1);
newReg->extents.x2 = RTGUI_MIN(reg1->extents.x2, reg2->extents.x2);
newReg->extents.y2 = RTGUI_MIN(reg1->extents.y2, reg2->extents.y2);
freeData(newReg);
newReg->data = (rtgui_region_data_t *)RT_NULL;
}
else if (!reg2->data && SUBSUMES(&reg2->extents, &reg1->extents))
{
return rtgui_region_copy(newReg, reg1);
}
else if (!reg1->data && SUBSUMES(&reg1->extents, &reg2->extents))
{
return rtgui_region_copy(newReg, reg2);
}
else if (reg1 == reg2)
{
return rtgui_region_copy(newReg, reg1);
}
else
{
/* General purpose intersection */
int overlap; /* result ignored */
if (!rtgui_op(newReg, reg1, reg2, rtgui_region_intersectO, RTGUI_REGION_STATUS_FAILURE, RTGUI_REGION_STATUS_FAILURE,
&overlap))
return RTGUI_REGION_STATUS_FAILURE;
rtgui_set_extents(newReg);
}
good(newReg);
return(RTGUI_REGION_STATUS_SUCCESS);
}
rtgui_region_status_t
rtgui_region_intersect_rect(rtgui_region_t *newReg,
rtgui_region_t *reg1,
rtgui_rect_t *rect)
{
rtgui_region_t region;
region.data = RT_NULL;
region.extents.x1 = rect->x1;
region.extents.y1 = rect->y1;
region.extents.x2 = rect->x2;
region.extents.y2 = rect->y2;
return rtgui_region_intersect(newReg, reg1, &region);
}
#define MERGERECT(r) \
{ \
if (r->x1 <= x2) { \
/* Merge with current rectangle */ \
if (r->x1 < x2) *pOverlap = RTGUI_REGION_STATUS_SUCCESS; \
if (x2 < r->x2) x2 = r->x2; \
} else { \
/* Add current rectangle, start new one */ \
NEWRECT(region, pNextRect, x1, y1, x2, y2); \
x1 = r->x1; \
x2 = r->x2; \
} \
r++; \
}
/*======================================================================
* Region Union
*====================================================================*/
/*-
*-----------------------------------------------------------------------
* rtgui_region_unionO --
* Handle an overlapping band for the union operation. Picks the
* left-most rectangle each time and merges it into the region.
*
* Results:
* RTGUI_REGION_STATUS_SUCCESS if successful.
*
* Side Effects:
* region is overwritten.
* pOverlap is set to RTGUI_REGION_STATUS_SUCCESS if any boxes overlap.
*
*-----------------------------------------------------------------------
*/
static rtgui_region_status_t
rtgui_region_unionO (
rtgui_region_t *region,
rtgui_rect_t *r1,
rtgui_rect_t *r1End,
rtgui_rect_t *r2,
rtgui_rect_t *r2End,
short y1,
short y2,
int *pOverlap)
{
rtgui_rect_t * pNextRect;
int x1; /* left and right side of current union */
int x2;
RT_ASSERT (y1 < y2);
RT_ASSERT(r1 != r1End && r2 != r2End);
pNextRect = PIXREGION_TOP(region);
/* Start off current rectangle */
if (r1->x1 < r2->x1)
{
x1 = r1->x1;
x2 = r1->x2;
r1++;
}
else
{
x1 = r2->x1;
x2 = r2->x2;
r2++;
}
while (r1 != r1End && r2 != r2End)
{
if (r1->x1 < r2->x1) MERGERECT(r1) else MERGERECT(r2);
}
/* Finish off whoever (if any) is left */
if (r1 != r1End)
{
do
{
MERGERECT(r1);
}
while (r1 != r1End);
}
else if (r2 != r2End)
{
do
{
MERGERECT(r2);
}
while (r2 != r2End);
}
/* Add current rectangle */
NEWRECT(region, pNextRect, x1, y1, x2, y2);
return RTGUI_REGION_STATUS_SUCCESS;
}
/* Convenience function for perforRTGUI_MINg union of region with a single rectangle */
rtgui_region_status_t
rtgui_region_union_rect(rtgui_region_t *dest, rtgui_region_t *source, rtgui_rect_t* rect)
{
rtgui_region_t region;
region.data = RT_NULL;
region.extents.x1 = rect->x1;
region.extents.y1 = rect->y1;
region.extents.x2 = rect->x2;
region.extents.y2 = rect->y2;
return rtgui_region_union (dest, source, &region);
}
rtgui_region_status_t
rtgui_region_union(rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_region_t *reg2)
{
int overlap; /* result ignored */
/* Return RTGUI_REGION_STATUS_SUCCESS if some overlap between reg1, reg2 */
good(reg1);
good(reg2);
good(newReg);
/* checks all the simple cases */
/*
* Region 1 and 2 are the same
*/
if (reg1 == reg2)
{
return rtgui_region_copy(newReg, reg1);
}
/*
* Region 1 is empty
*/
if (PIXREGION_NIL(reg1))
{
if (PIXREGION_NAR(reg1)) return rtgui_break (newReg);
if (newReg != reg2)
return rtgui_region_copy(newReg, reg2);
return RTGUI_REGION_STATUS_SUCCESS;
}
/*
* Region 2 is empty
*/
if (PIXREGION_NIL(reg2))
{
if (PIXREGION_NAR(reg2)) return rtgui_break (newReg);
if (newReg != reg1)
return rtgui_region_copy(newReg, reg1);
return RTGUI_REGION_STATUS_SUCCESS;
}
/*
* Region 1 completely subsumes region 2
*/
if (!reg1->data && SUBSUMES(&reg1->extents, &reg2->extents))
{
if (newReg != reg1)
return rtgui_region_copy(newReg, reg1);
return RTGUI_REGION_STATUS_SUCCESS;
}
/*
* Region 2 completely subsumes region 1
*/
if (!reg2->data && SUBSUMES(&reg2->extents, &reg1->extents))
{
if (newReg != reg2)
return rtgui_region_copy(newReg, reg2);
return RTGUI_REGION_STATUS_SUCCESS;
}
if (!rtgui_op(newReg, reg1, reg2, rtgui_region_unionO, RTGUI_REGION_STATUS_SUCCESS, RTGUI_REGION_STATUS_SUCCESS, &overlap))
return RTGUI_REGION_STATUS_FAILURE;
newReg->extents.x1 = RTGUI_MIN(reg1->extents.x1, reg2->extents.x1);
newReg->extents.y1 = RTGUI_MIN(reg1->extents.y1, reg2->extents.y1);
newReg->extents.x2 = RTGUI_MAX(reg1->extents.x2, reg2->extents.x2);
newReg->extents.y2 = RTGUI_MAX(reg1->extents.y2, reg2->extents.y2);
good(newReg);
return RTGUI_REGION_STATUS_SUCCESS;
}
/*======================================================================
* Batch Rectangle Union
*====================================================================*/
/*-
*-----------------------------------------------------------------------
* rtgui_region_append --
*
* "Append" the rgn rectangles onto the end of dstrgn, maintaining
* knowledge of YX-banding when it's easy. Otherwise, dstrgn just
* becomes a non-y-x-banded random collection of rectangles, and not
* yet a true region. After a sequence of appends, the caller must
* call rtgui_region_validate to ensure that a valid region is constructed.
*
* Results:
* RTGUI_REGION_STATUS_SUCCESS if successful.
*
* Side Effects:
* dstrgn is modified if rgn has rectangles.
*
*/
rtgui_region_status_t
rtgui_region_append(rtgui_region_t *dstrgn,
rtgui_region_t *rgn)
{
int numRects, dnumRects, size;
rtgui_rect_t *new, *old;
int prepend;
if (PIXREGION_NAR(rgn)) return rtgui_break (dstrgn);
if (!rgn->data && (dstrgn->data == &rtgui_region_emptydata))
{
dstrgn->extents = rgn->extents;
dstrgn->data = (rtgui_region_data_t *)RT_NULL;
return RTGUI_REGION_STATUS_SUCCESS;
}
numRects = PIXREGION_NUM_RECTS(rgn);
if (!numRects)
return RTGUI_REGION_STATUS_SUCCESS;
prepend = RTGUI_REGION_STATUS_FAILURE;
size = numRects;
dnumRects = PIXREGION_NUM_RECTS(dstrgn);
if (!dnumRects && (size < 200))
size = 200; /* XXX pick numbers out of a hat */
RECTALLOC(dstrgn, size);
old = PIXREGION_RECTS(rgn);
if (!dnumRects)
dstrgn->extents = rgn->extents;
else if (dstrgn->extents.x2 > dstrgn->extents.x1)
{
rtgui_rect_t *first, *last;
first = old;
last = PIXREGION_BOXPTR(dstrgn) + (dnumRects - 1);
if ((first->y1 > last->y2) ||
((first->y1 == last->y1) && (first->y2 == last->y2) &&
(first->x1 > last->x2)))
{
if (rgn->extents.x1 < dstrgn->extents.x1)
dstrgn->extents.x1 = rgn->extents.x1;
if (rgn->extents.x2 > dstrgn->extents.x2)
dstrgn->extents.x2 = rgn->extents.x2;
dstrgn->extents.y2 = rgn->extents.y2;
}
else
{
first = PIXREGION_BOXPTR(dstrgn);
last = old + (numRects - 1);
if ((first->y1 > last->y2) ||
((first->y1 == last->y1) && (first->y2 == last->y2) &&
(first->x1 > last->x2)))
{
prepend = RTGUI_REGION_STATUS_SUCCESS;
if (rgn->extents.x1 < dstrgn->extents.x1)
dstrgn->extents.x1 = rgn->extents.x1;
if (rgn->extents.x2 > dstrgn->extents.x2)
dstrgn->extents.x2 = rgn->extents.x2;
dstrgn->extents.y1 = rgn->extents.y1;
}
else
dstrgn->extents.x2 = dstrgn->extents.x1;
}
}
if (prepend)
{
new = PIXREGION_BOX(dstrgn, numRects);
if (dnumRects == 1)
*new = *PIXREGION_BOXPTR(dstrgn);
else
rt_memmove((char *)new,(char *)PIXREGION_BOXPTR(dstrgn),
dnumRects * sizeof(rtgui_rect_t));
new = PIXREGION_BOXPTR(dstrgn);
}
else
new = PIXREGION_BOXPTR(dstrgn) + dnumRects;
if (numRects == 1)
*new = *old;
else
rt_memmove((char *)new, (char *)old, numRects * sizeof(rtgui_rect_t));
dstrgn->data->numRects += numRects;
return RTGUI_REGION_STATUS_SUCCESS;
}
#define ExchangeRects(a, b) \
{ \
rtgui_rect_t t; \
t = rects[a]; \
rects[a] = rects[b]; \
rects[b] = t; \
}
static void QuickSortRects(rtgui_rect_t rects[], int numRects)
{
int y1;
int x1;
int i, j;
rtgui_rect_t *r;
/* Always called with numRects > 1 */
do
{
if (numRects == 2)
{
if (rects[0].y1 > rects[1].y1 ||
(rects[0].y1 == rects[1].y1 && rects[0].x1 > rects[1].x1))
ExchangeRects(0, 1);
return;
}
/* Choose partition element, stick in location 0 */
ExchangeRects(0, numRects >> 1);
y1 = rects[0].y1;
x1 = rects[0].x1;
/* Partition array */
i = 0;
j = numRects;
do
{
r = &(rects[i]);
do
{
r++;
i++;
}
while (i != numRects &&
(r->y1 < y1 || (r->y1 == y1 && r->x1 < x1)));
r = &(rects[j]);
do
{
r--;
j--;
}
while (y1 < r->y1 || (y1 == r->y1 && x1 < r->x1));
if (i < j)
ExchangeRects(i, j);
}
while (i < j);
/* Move partition element back to middle */
ExchangeRects(0, j);
/* Recurse */
if (numRects-j-1 > 1)
QuickSortRects(&rects[j+1], numRects-j-1);
numRects = j;
}
while (numRects > 1);
}
/*-
*-----------------------------------------------------------------------
* rtgui_region_validate --
*
* Take a ``region'' which is a non-y-x-banded random collection of
* rectangles, and compute a nice region which is the union of all the
* rectangles.
*
* Results:
* RTGUI_REGION_STATUS_SUCCESS if successful.
*
* Side Effects:
* The passed-in ``region'' may be modified.
* pOverlap set to RTGUI_REGION_STATUS_SUCCESS if any retangles overlapped, else RTGUI_REGION_STATUS_FAILURE;
*
* Strategy:
* Step 1. Sort the rectangles into ascending order with primary key y1
* and secondary key x1.
*
* Step 2. Split the rectangles into the RTGUI_MINimum number of proper y-x
* banded regions. This may require horizontally merging
* rectangles, and vertically coalescing bands. With any luck,
* this step in an identity transformation (ala the Box widget),
* or a coalescing into 1 box (ala Menus).
*
* Step 3. Merge the separate regions down to a single region by calling
* rtgui_region_union. Maximize the work each rtgui_region_union call does by using
* a binary merge.
*
*-----------------------------------------------------------------------
*/
rtgui_region_status_t rtgui_region_validate(rtgui_region_t * badreg,
int *pOverlap)
{
/* Descriptor for regions under construction in Step 2. */
typedef struct
{
rtgui_region_t reg;
int prevBand;
int curBand;
}
RegionInfo;
int numRects; /* Original numRects for badreg */
RegionInfo *ri; /* Array of current regions */
int numRI; /* Number of entries used in ri */
int sizeRI; /* Number of entries available in ri */
int i; /* Index into rects */
int j; /* Index into ri */
RegionInfo *rit; /* &ri[j] */
rtgui_region_t * reg; /* ri[j].reg */
rtgui_rect_t * box; /* Current box in rects */
rtgui_rect_t * riBox; /* Last box in ri[j].reg */
rtgui_region_t * hreg; /* ri[j_half].reg */
rtgui_region_status_t ret = RTGUI_REGION_STATUS_SUCCESS;
*pOverlap = RTGUI_REGION_STATUS_FAILURE;
if (!badreg->data)
{
good(badreg);
return RTGUI_REGION_STATUS_SUCCESS;
}
numRects = badreg->data->numRects;
if (!numRects)
{
if (PIXREGION_NAR(badreg))
return RTGUI_REGION_STATUS_FAILURE;
good(badreg);
return RTGUI_REGION_STATUS_SUCCESS;
}
if (badreg->extents.x1 < badreg->extents.x2)
{
if ((numRects) == 1)
{
freeData(badreg);
badreg->data = (rtgui_region_data_t *) RT_NULL;
}
else
{
DOWNSIZE(badreg, numRects);
}
good(badreg);
return RTGUI_REGION_STATUS_SUCCESS;
}
/* Step 1: Sort the rects array into ascending (y1, x1) order */
QuickSortRects(PIXREGION_BOXPTR(badreg), numRects);
/* Step 2: Scatter the sorted array into the RTGUI_MINimum number of regions */
/* Set up the first region to be the first rectangle in badreg */
/* Note that step 2 code will never overflow the ri[0].reg rects array */
ri = (RegionInfo *) rtgui_malloc(4 * sizeof(RegionInfo));
if (!ri) return rtgui_break (badreg);
sizeRI = 4;
numRI = 1;
ri[0].prevBand = 0;
ri[0].curBand = 0;
ri[0].reg = *badreg;
box = PIXREGION_BOXPTR(&ri[0].reg);
ri[0].reg.extents = *box;
ri[0].reg.data->numRects = 1;
/* Now scatter rectangles into the RTGUI_MINimum set of valid regions. If the
next rectangle to be added to a region would force an existing rectangle
in the region to be split up in order to maintain y-x banding, just
forget it. Try the next region. If it doesn't fit cleanly into any
region, make a new one. */
for (i = numRects; --i > 0;)
{
box++;
/* Look for a region to append box to */
for (j = numRI, rit = ri; --j >= 0; rit++)
{
reg = &rit->reg;
riBox = PIXREGION_END(reg);
if (box->y1 == riBox->y1 && box->y2 == riBox->y2)
{
/* box is in same band as riBox. Merge or append it */
if (box->x1 <= riBox->x2)
{
/* Merge it with riBox */
if (box->x1 < riBox->x2) *pOverlap = RTGUI_REGION_STATUS_SUCCESS;
if (box->x2 > riBox->x2) riBox->x2 = box->x2;
}
else
{
RECTALLOC_BAIL(reg, 1, bail);
*PIXREGION_TOP(reg) = *box;
reg->data->numRects++;
}
goto NextRect; /* So sue me */
}
else if (box->y1 >= riBox->y2)
{
/* Put box into new band */
if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1;
Coalesce(reg, rit->prevBand, rit->curBand);
rit->curBand = reg->data->numRects;
RECTALLOC_BAIL(reg, 1, bail);
*PIXREGION_TOP(reg) = *box;
reg->data->numRects++;
goto NextRect;
}
/* Well, this region was inappropriate. Try the next one. */
} /* for j */
/* Uh-oh. No regions were appropriate. Create a new one. */
if (sizeRI == numRI)
{
/* Oops, allocate space for new region information */
sizeRI <<= 1;
rit = (RegionInfo *) rt_realloc(ri, sizeRI * sizeof(RegionInfo));
if (!rit)
goto bail;
ri = rit;
rit = &ri[numRI];
}
numRI++;
rit->prevBand = 0;
rit->curBand = 0;
rit->reg.extents = *box;
rit->reg.data = (rtgui_region_data_t *)RT_NULL;
if (!rtgui_rect_alloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */
goto bail;
NextRect:
;
} /* for i */
/* Make a final pass over each region in order to Coalesce and set
extents.x2 and extents.y2 */
for (j = numRI, rit = ri; --j >= 0; rit++)
{
reg = &rit->reg;
riBox = PIXREGION_END(reg);
reg->extents.y2 = riBox->y2;
if (reg->extents.x2 < riBox->x2) reg->extents.x2 = riBox->x2;
Coalesce(reg, rit->prevBand, rit->curBand);
if (reg->data->numRects == 1) /* keep unions happy below */
{
freeData(reg);
reg->data = (rtgui_region_data_t *)RT_NULL;
}
}
/* Step 3: Union all regions into a single region */
while (numRI > 1)
{
int half = numRI/2;
for (j = numRI & 1; j < (half + (numRI & 1)); j++)
{
reg = &ri[j].reg;
hreg = &ri[j+half].reg;
if (!rtgui_op(reg, reg, hreg, rtgui_region_unionO, RTGUI_REGION_STATUS_SUCCESS, RTGUI_REGION_STATUS_SUCCESS, pOverlap))
ret = RTGUI_REGION_STATUS_FAILURE;
if (hreg->extents.x1 < reg->extents.x1)
reg->extents.x1 = hreg->extents.x1;
if (hreg->extents.y1 < reg->extents.y1)
reg->extents.y1 = hreg->extents.y1;
if (hreg->extents.x2 > reg->extents.x2)
reg->extents.x2 = hreg->extents.x2;
if (hreg->extents.y2 > reg->extents.y2)
reg->extents.y2 = hreg->extents.y2;
freeData(hreg);
}
numRI -= half;
}
*badreg = ri[0].reg;
rtgui_free(ri);
good(badreg);
return ret;
bail:
for (i = 0; i < numRI; i++)
freeData(&ri[i].reg);
rtgui_free (ri);
return rtgui_break (badreg);
}
/*======================================================================
* Region Subtraction
*====================================================================*/
/*-
*-----------------------------------------------------------------------
* rtgui_region_subtractO --
* Overlapping band subtraction. x1 is the left-most point not yet
* checked.
*
* Results:
* RTGUI_REGION_STATUS_SUCCESS if successful.
*
* Side Effects:
* region may have rectangles added to it.
*
*-----------------------------------------------------------------------
*/
/*ARGSUSED*/
static rtgui_region_status_t
rtgui_region_subtractO (
rtgui_region_t *region,
rtgui_rect_t *r1,
rtgui_rect_t *r1End,
rtgui_rect_t *r2,
rtgui_rect_t *r2End,
short y1,
short y2,
int *pOverlap)
{
rtgui_rect_t * pNextRect;
int x1;
x1 = r1->x1;
RT_ASSERT(y1<y2);
RT_ASSERT(r1 != r1End && r2 != r2End);
pNextRect = PIXREGION_TOP(region);
do
{
if (r2->x2 <= x1)
{
/*
* Subtrahend entirely to left of minuend: go to next subtrahend.
*/
r2++;
}
else if (r2->x1 <= x1)
{
/*
* Subtrahend preceeds RTGUI_MINuend: nuke left edge of minuend.
*/
x1 = r2->x2;
if (x1 >= r1->x2)
{
/*
* Minuend completely covered: advance to next minuend and
* reset left fence to edge of new RTGUI_MINuend.
*/
r1++;
if (r1 != r1End)
x1 = r1->x1;
}
else
{
/*
* Subtrahend now used up since it doesn't extend beyond
* minuend
*/
r2++;
}
}
else if (r2->x1 < r1->x2)
{
/*
* Left part of subtrahend covers part of minuend: add uncovered
* part of minuend to region and skip to next subtrahend.
*/
RT_ASSERT(x1<r2->x1);
NEWRECT(region, pNextRect, x1, y1, r2->x1, y2);
x1 = r2->x2;
if (x1 >= r1->x2)
{
/*
* Minuend used up: advance to new...
*/
r1++;
if (r1 != r1End)
x1 = r1->x1;
}
else
{
/*
* Subtrahend used up
*/
r2++;
}
}
else
{
/*
* Minuend used up: add any remaining piece before advancing.
*/
if (r1->x2 > x1)
NEWRECT(region, pNextRect, x1, y1, r1->x2, y2);
r1++;
if (r1 != r1End)
x1 = r1->x1;
}
}
while ((r1 != r1End) && (r2 != r2End));
/*
* Add remaining minuend rectangles to region.
*/
while (r1 != r1End)
{
RT_ASSERT(x1<r1->x2);
NEWRECT(region, pNextRect, x1, y1, r1->x2, y2);
r1++;
if (r1 != r1End)
x1 = r1->x1;
}
return RTGUI_REGION_STATUS_SUCCESS;
}
/*-
*-----------------------------------------------------------------------
* rtgui_region_subtract --
* Subtract regS from regM and leave the result in regD.
* S stands for subtrahend, M for minuend and D for difference.
*
* Results:
* RTGUI_REGION_STATUS_SUCCESS if successful.
*
* Side Effects:
* regD is overwritten.
*
*-----------------------------------------------------------------------
*/
rtgui_region_status_t
rtgui_region_subtract(rtgui_region_t *regD,
rtgui_region_t *regM,
rtgui_region_t *regS)
{
int overlap; /* result ignored */
good(regM);
good(regS);
good(regD);
/* check for trivial rejects */
if (PIXREGION_NIL(regM) || PIXREGION_NIL(regS) ||
!EXTENTCHECK(&regM->extents, &regS->extents))
{
if (PIXREGION_NAR (regS)) return rtgui_break (regD);
return rtgui_region_copy(regD, regM);
}
else if (regM == regS)
{
freeData(regD);
regD->extents.x2 = regD->extents.x1;
regD->extents.y2 = regD->extents.y1;
regD->data = &rtgui_region_emptydata;
return RTGUI_REGION_STATUS_SUCCESS;
}
/* Add those rectangles in region 1 that aren't in region 2,
do yucky substraction for overlaps, and
just throw away rectangles in region 2 that aren't in region 1 */
if (!rtgui_op(regD, regM, regS, rtgui_region_subtractO, RTGUI_REGION_STATUS_SUCCESS, RTGUI_REGION_STATUS_FAILURE, &overlap))
return RTGUI_REGION_STATUS_FAILURE;
/*
* Can't alter RegD's extents before we call rtgui_op because
* it might be one of the source regions and rtgui_op depends
* on the extents of those regions being unaltered. Besides, this
* way there's no checking against rectangles that will be nuked
* due to coalescing, so we have to exaRTGUI_MINe fewer rectangles.
*/
rtgui_set_extents(regD);
good(regD);
return RTGUI_REGION_STATUS_SUCCESS;
}
rtgui_region_status_t
rtgui_region_subtract_rect (rtgui_region_t *regD, rtgui_region_t *regM, rtgui_rect_t* rect)
{
rtgui_region_t region;
region.data = RT_NULL;
region.extents.x1 = rect->x1;
region.extents.y1 = rect->y1;
region.extents.x2 = rect->x2;
region.extents.y2 = rect->y2;
return rtgui_region_subtract(regD, regM, &region);
}
/*======================================================================
* Region Inversion
*====================================================================*/
/*-
*-----------------------------------------------------------------------
* rtgui_region_inverse --
* Take a region and a box and return a region that is everything
* in the box but not in the region. The careful reader will note
* that this is the same as subtracting the region from the box...
*
* Results:
* RTGUI_REGION_STATUS_SUCCESS.
*
* Side Effects:
* newReg is overwritten.
*
*-----------------------------------------------------------------------
*/
rtgui_region_status_t
rtgui_region_inverse(rtgui_region_t *newReg, /* Destination region */
rtgui_region_t *reg1, /* Region to invert */
rtgui_rect_t *invRect) /* Bounding box for inversion */
{
rtgui_region_t invReg; /* Quick and dirty region made from the
* bounding box */
int overlap; /* result ignored */
good(reg1);
good(newReg);
/* check for trivial rejects */
if (PIXREGION_NIL(reg1) || !EXTENTCHECK(invRect, &reg1->extents))
{
if (PIXREGION_NAR(reg1)) return rtgui_break (newReg);
newReg->extents = *invRect;
freeData(newReg);
newReg->data = (rtgui_region_data_t *)RT_NULL;
return RTGUI_REGION_STATUS_SUCCESS;
}
/* Add those rectangles in region 1 that aren't in region 2,
do yucky substraction for overlaps, and
just throw away rectangles in region 2 that aren't in region 1 */
invReg.extents = *invRect;
invReg.data = (rtgui_region_data_t *)RT_NULL;
if (!rtgui_op(newReg, &invReg, reg1, rtgui_region_subtractO, RTGUI_REGION_STATUS_SUCCESS, RTGUI_REGION_STATUS_FAILURE, &overlap))
return RTGUI_REGION_STATUS_FAILURE;
/*
* Can't alter newReg's extents before we call rtgui_op because
* it might be one of the source regions and rtgui_op depends
* on the extents of those regions being unaltered. Besides, this
* way there's no checking against rectangles that will be nuked
* due to coalescing, so we have to exaRTGUI_MINe fewer rectangles.
*/
rtgui_set_extents(newReg);
good(newReg);
return RTGUI_REGION_STATUS_SUCCESS;
}
/*
* RectIn(region, rect)
* This routine takes a pointer to a region and a pointer to a box
* and deterRTGUI_MINes if the box is outside/inside/partly inside the region.
*
* The idea is to travel through the list of rectangles trying to cover the
* passed box with them. Anytime a piece of the rectangle isn't covered
* by a band of rectangles, partOut is set RTGUI_REGION_STATUS_SUCCESS. Any time a rectangle in
* the region covers part of the box, partIn is set RTGUI_REGION_STATUS_SUCCESS. The process ends
* when either the box has been completely covered (we reached a band that
* doesn't overlap the box, partIn is RTGUI_REGION_STATUS_SUCCESS and partOut is false), the
* box has been partially covered (partIn == partOut == RTGUI_REGION_STATUS_SUCCESS -- because of
* the banding, the first time this is true we know the box is only
* partially in the region) or is outside the region (we reached a band
* that doesn't overlap the box at all and partIn is false)
*/
int rtgui_region_contains_rectangle(rtgui_region_t *region, rtgui_rect_t *prect)
{
int x;
int y;
rtgui_rect_t * pbox;
rtgui_rect_t * pboxEnd;
int partIn, partOut;
int numRects;
good(region);
numRects = PIXREGION_NUM_RECTS(region);
/* useful optimization */
if (!numRects || !EXTENTCHECK(&region->extents, prect))
return(RTGUI_REGION_OUT);
if (numRects == 1)
{
/* We know that it must be rgnIN or rgnPART */
if (SUBSUMES(&region->extents, prect))
return(RTGUI_REGION_IN);
else
return(RTGUI_REGION_PART);
}
partOut = RTGUI_REGION_STATUS_FAILURE;
partIn = RTGUI_REGION_STATUS_FAILURE;
/* (x,y) starts at upper left of rect, moving to the right and down */
x = prect->x1;
y = prect->y1;
/* can stop when both partOut and partIn are RTGUI_REGION_STATUS_SUCCESS, or we reach prect->y2 */
for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
pbox != pboxEnd;
pbox++)
{
if (pbox->y2 <= y)
continue; /* getting up to speed or skipping remainder of band */
if (pbox->y1 > y)
{
partOut = RTGUI_REGION_STATUS_SUCCESS; /* missed part of rectangle above */
if (partIn || (pbox->y1 >= prect->y2))
break;
y = pbox->y1; /* x guaranteed to be == prect->x1 */
}
if (pbox->x2 <= x)
continue; /* not far enough over yet */
if (pbox->x1 > x)
{
partOut = RTGUI_REGION_STATUS_SUCCESS; /* missed part of rectangle to left */
if (partIn)
break;
}
if (pbox->x1 < prect->x2)
{
partIn = RTGUI_REGION_STATUS_SUCCESS; /* definitely overlap */
if (partOut)
break;
}
if (pbox->x2 >= prect->x2)
{
y = pbox->y2; /* finished with this band */
if (y >= prect->y2)
break;
x = prect->x1; /* reset x out to left again */
}
else
{
/*
* Because boxes in a band are maximal width, if the first box
* to overlap the rectangle doesn't completely cover it in that
* band, the rectangle must be partially out, since some of it
* will be uncovered in that band. partIn will have been set true
* by now...
*/
partOut = RTGUI_REGION_STATUS_SUCCESS;
break;
}
}
return(partIn ? ((y < prect->y2) ? RTGUI_REGION_PART : RTGUI_REGION_IN) : RTGUI_REGION_OUT);
}
/* rtgui_region_translate (region, x, y)
translates in place
*/
void rtgui_region_translate (rtgui_region_t *region, int x, int y)
{
int x1, x2, y1, y2;
int nbox;
rtgui_rect_t * pbox;
good(region);
region->extents.x1 = x1 = region->extents.x1 + x;
region->extents.y1 = y1 = region->extents.y1 + y;
region->extents.x2 = x2 = region->extents.x2 + x;
region->extents.y2 = y2 = region->extents.y2 + y;
if (((x1 - RTGUI_SHRT_MIN)|(y1 - RTGUI_SHRT_MIN)|(RTGUI_SHRT_MAX - x2)|(RTGUI_SHRT_MAX - y2)) >= 0)
{
nbox = region->data->numRects;
if (region->data && nbox)
{
for (pbox = PIXREGION_BOXPTR(region); nbox--; pbox++)
{
pbox->x1 += x;
pbox->y1 += y;
pbox->x2 += x;
pbox->y2 += y;
}
}
return;
}
if (((x2 - RTGUI_SHRT_MIN)|(y2 - RTGUI_SHRT_MIN)|(RTGUI_SHRT_MAX - x1)|(RTGUI_SHRT_MAX - y1)) <= 0)
{
region->extents.x2 = region->extents.x1;
region->extents.y2 = region->extents.y1;
freeData(region);
region->data = &rtgui_region_emptydata;
return;
}
if (x1 < RTGUI_SHRT_MIN)
region->extents.x1 = RTGUI_SHRT_MIN;
else if (x2 > RTGUI_SHRT_MAX)
region->extents.x2 = RTGUI_SHRT_MAX;
if (y1 < RTGUI_SHRT_MIN)
region->extents.y1 = RTGUI_SHRT_MIN;
else if (y2 > RTGUI_SHRT_MAX)
region->extents.y2 = RTGUI_SHRT_MAX;
nbox = region->data->numRects;
if (region->data && nbox)
{
rtgui_rect_t * pboxout;
for (pboxout = pbox = PIXREGION_BOXPTR(region); nbox--; pbox++)
{
pboxout->x1 = x1 = pbox->x1 + x;
pboxout->y1 = y1 = pbox->y1 + y;
pboxout->x2 = x2 = pbox->x2 + x;
pboxout->y2 = y2 = pbox->y2 + y;
if (((x2 - RTGUI_SHRT_MIN)|(y2 - RTGUI_SHRT_MIN)|
(RTGUI_SHRT_MAX - x1)|(RTGUI_SHRT_MAX - y1)) <= 0)
{
region->data->numRects--;
continue;
}
if (x1 < RTGUI_SHRT_MIN)
pboxout->x1 = RTGUI_SHRT_MIN;
else if (x2 > RTGUI_SHRT_MAX)
pboxout->x2 = RTGUI_SHRT_MAX;
if (y1 < RTGUI_SHRT_MIN)
pboxout->y1 = RTGUI_SHRT_MIN;
else if (y2 > RTGUI_SHRT_MAX)
pboxout->y2 = RTGUI_SHRT_MAX;
pboxout++;
}
if (pboxout != pbox)
{
if (region->data->numRects == 1)
{
region->extents = *PIXREGION_BOXPTR(region);
freeData(region);
region->data = (rtgui_region_data_t *)RT_NULL;
}
else
rtgui_set_extents(region);
}
}
}
void rtgui_region_reset(rtgui_region_t *region, rtgui_rect_t* rect)
{
good(region);
freeData(region);
rtgui_region_init_with_extents(region, rect);
}
/* box is "return" value */
int rtgui_region_contains_point(rtgui_region_t * region,
int x, int y,
rtgui_rect_t * box)
{
rtgui_rect_t *pbox, *pboxEnd;
int numRects;
good(region);
numRects = PIXREGION_NUM_RECTS(region);
if (!numRects || !INBOX(&region->extents, x, y))
return -RT_ERROR;
if (numRects == 1)
{
*box = region->extents;
return RT_EOK;
}
for (pbox = PIXREGION_BOXPTR(region), pboxEnd = pbox + numRects;
pbox != pboxEnd;
pbox++)
{
if (y >= pbox->y2)
continue; /* not there yet */
if ((y < pbox->y1) || (x < pbox->x1))
break; /* missed it */
if (x >= pbox->x2)
continue; /* not there yet */
*box = *pbox;
return RT_EOK;
}
return -RT_ERROR;
}
int rtgui_region_not_empty(rtgui_region_t * region)
{
good(region);
return(!PIXREGION_NIL(region));
}
void rtgui_region_empty(rtgui_region_t * region)
{
good(region);
freeData(region);
region->extents = rtgui_empty_rect;
region->data = &rtgui_region_emptydata;
}
rtgui_rect_t *rtgui_region_extents(rtgui_region_t * region)
{
good(region);
return(&region->extents);
}
#define ExchangeSpans(a, b) \
{ \
rtgui_point_t tpt; \
int tw; \
\
tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \
tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
}
/* ||| I should apply the merge sort code to rectangle sorting above, and see
if mapping time can be improved. But right now I've been at work 12 hours,
so forget it.
*/
static void QuickSortSpans(
rtgui_point_t spans[],
int widths[],
int numSpans)
{
int y;
int i, j, m;
rtgui_point_t *r;
/* Always called with numSpans > 1 */
/* Sorts only by y, doesn't bother to sort by x */
do
{
if (numSpans < 9)
{
/* Do insertion sort */
int yprev;
yprev = spans[0].y;
i = 1;
do
{ /* while i != numSpans */
y = spans[i].y;
if (yprev > y)
{
/* spans[i] is out of order. Move into proper location. */
rtgui_point_t tpt;
int tw, k;
for (j = 0; y >= spans[j].y; j++)
{}
tpt = spans[i];
tw = widths[i];
for (k = i; k != j; k--)
{
spans[k] = spans[k-1];
widths[k] = widths[k-1];
}
spans[j] = tpt;
widths[j] = tw;
y = spans[i].y;
} /* if out of order */
yprev = y;
i++;
}
while (i != numSpans);
return;
}
/* Choose partition element, stick in location 0 */
m = numSpans / 2;
if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1);
if (spans[m].y > spans[0].y) ExchangeSpans(m, 0);
y = spans[0].y;
/* Partition array */
i = 0;
j = numSpans;
do
{
r = &(spans[i]);
do
{
r++;
i++;
}
while (i != numSpans && r->y < y);
r = &(spans[j]);
do
{
r--;
j--;
}
while (y < r->y);
if (i < j)
ExchangeSpans(i, j);
}
while (i < j);
/* Move partition element back to middle */
ExchangeSpans(0, j);
/* Recurse */
if (numSpans-j-1 > 1)
QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1);
numSpans = j;
}
while (numSpans > 1);
}
void rtgui_region_dump(rtgui_region_t* region)
{
int num;
int i;
rtgui_rect_t * rects;
num = PIXREGION_NUM_RECTS(region);
rects = PIXREGION_RECTS(region);
rt_kprintf("extents: (%d,%d) (%d,%d)\n",
region->extents.x1, region->extents.y1,
region->extents.x2, region->extents.y2);
for (i = 0; i < num; i++)
{
rt_kprintf("box[%d]: (%d,%d) (%d,%d)\n", i,
rects[i].x1, rects[i].y1,
rects[i].x2, rects[i].y2);
}
}
void rtgui_rect_moveto(rtgui_rect_t *rect, int x, int y)
{
rect->x1 += x;
rect->x2 += x;
rect->y1 += y;
rect->y2 += y;
}
void rtgui_rect_moveto_align(rtgui_rect_t *rect, rtgui_rect_t *to, int align)
{
int dw, dh;
dw = 0;
dh = 0;
/* get delta width and height */
dw = rtgui_rect_width(*rect) - rtgui_rect_width(*to);
dh = rtgui_rect_height(*rect) - rtgui_rect_height(*to);
if (dw < 0) dw = 0;
if (dh < 0) dh = 0;
/* move to insider of rect */
rtgui_rect_moveto(to, rect->x1, rect->y1);
/* limited the destination rect to source rect */
if (dw == 0) to->x2 = rect->x2;
if (dh == 0) to->y2 = rect->y2;
/* align to right */
if (align & RTGUI_ALIGN_RIGHT)
{
to->x1 += dw;
to->x2 += dw;
}
/* align to bottom */
if (align & RTGUI_ALIGN_BOTTOM)
{
to->y1 += dh;
to->y2 += dh;
}
/* align to center horizontal */
if (align & RTGUI_ALIGN_CENTER_HORIZONTAL)
{
to->x1 += dw >> 1;
to->x2 += dw >> 1;
}
/* align to center vertical */
if (align & RTGUI_ALIGN_CENTER_VERTICAL)
{
to->y1 += dh >> 1;
to->y2 += dh >> 1;
}
}
void rtgui_rect_inflate(rtgui_rect_t *rect, int d)
{
rect->x1 -= d;
rect->x2 += d;
rect->y1 -= d;
rect->y2 += d;
}
/* put the intersect of src rect and dest rect to dest */
void rtgui_rect_intersect(rtgui_rect_t *src, rtgui_rect_t *dest)
{
if (dest->x1 < src->x1) dest->x1 = src->x1;
if (dest->y1 < src->y1) dest->y1 = src->y1;
if (dest->x2 > src->x2) dest->x2 = src->x2;
if (dest->y2 > src->y2) dest->y2 = src->y2;
}
int rtgui_rect_contains_point(rtgui_rect_t *rect, int x, int y)
{
if (INBOX(rect, x, y)) return RT_EOK;
return -RT_ERROR;
}
int rtgui_rect_is_intersect(rtgui_rect_t *rect1, rtgui_rect_t *rect2)
{
if (INBOX(rect1, rect2->x1, rect2->y1) ||
INBOX(rect1, rect2->x1, rect2->y2) ||
INBOX(rect1, rect2->x2, rect2->y1) ||
INBOX(rect1, rect2->x2, rect2->y2))
{
return RT_EOK;
}
else if (INBOX(rect2, rect1->x1, rect1->y1) ||
INBOX(rect2, rect1->x1, rect1->y2) ||
INBOX(rect2, rect1->x2, rect1->y1) ||
INBOX(rect2, rect1->x2, rect1->y2))
{
return RT_EOK;
}
return -RT_ERROR;
}
......@@ -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 */
/************************************************************************/
......
......@@ -19,13 +19,14 @@
#include <rtgui/widgets/label.h>
#include <rtgui/widgets/textbox.h>
#include <rtgui/widgets/iconbox.h>
#include <rtgui/widgets/title.h>
#include <rtgui/rtgui_theme.h>
#include <rtgui/rtgui_server.h>
#define WINTITLE_CB_WIDTH 14
#define WINTITLE_CB_HEIGHT 14
static const char * close_unpressed_xpm[] = {
static const rt_uint8_t *close_unpressed_xpm[] = {
"14 14 55 1",
" c None",
". c #DCDFEA",
......@@ -97,7 +98,7 @@ static const char * close_unpressed_xpm[] = {
"#mnnnnnnnnnnm#",
"op@@@@@@@@@@po"};
static const char * close_pressed_xpm[] = {
static const rt_uint8_t *close_pressed_xpm[] = {
"14 14 66 1",
" c None",
". c #CED4EE",
......@@ -191,9 +192,11 @@ void rtgui_theme_draw_win(struct rtgui_topwin* win)
/* init close box image */
if (close_pressed == RT_NULL)
close_pressed = rtgui_image_create_from_mem("xpm", close_pressed_xpm, sizeof(close_pressed_xpm));
close_pressed = rtgui_image_create_from_mem("xpm",
(const rt_uint8_t*)close_pressed_xpm, sizeof(close_pressed_xpm));
if (close_unpressed == RT_NULL)
close_unpressed = rtgui_image_create_from_mem("xpm", close_unpressed_xpm, sizeof(close_unpressed_xpm));
close_unpressed = rtgui_image_create_from_mem("xpm",
(const rt_uint8_t*)close_unpressed_xpm, sizeof(close_unpressed_xpm));
/* begin drawing */
dc = rtgui_dc_begin_drawing(RTGUI_WIDGET(win->title));
......@@ -437,3 +440,4 @@ void rtgui_theme_draw_iconbox(rtgui_iconbox_t* iconbox)
/* end drawing */
rtgui_dc_end_drawing(dc);
}
/*
* File : caret.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_CARET_H__
#define __RTGUI_CARET_H__
#include <rtgui/dc.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/widget.h>
struct rtgui_caret
{
/* show flag */
rt_bool_t is_show;
/* the show point of caret */
struct rtgui_point show_point;
/* widget owner */
struct rtgui_widget* owner;
/* caret buffer dc */
struct rtgui_dc *dc;
/* caret extent */
struct rtgui_rect extent;
/* the blink timer */
struct rtgui_timer* timer;
rt_int32_t timer_period;
};
typedef struct rtgui_caret rtgui_caret_t;
struct rtgui_caret* rtgui_caret_create(struct rtgui_widget* owner);
void rtgui_caret_destroy(struct rtgui_caret* caret);
void rtgui_caret_show(struct rtgui_caret* caret, rt_base_t x, rt_base_t y);
void rtgui_caret_hide(struct rtgui_caret* caret);
void rtgui_caret_draw(struct rtgui_caret* caret);
void rtgui_caret_set_point(struct rtgui_caret* caret, int x, int y);
void rtgui_caret_set_box(struct rtgui_caret* caret, int w, int h);
#endif
/*
* File : color.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_COLOR_H__
#define __RTGUI_COLOR_H__
#include <rtgui/rtgui.h>
typedef unsigned long rtgui_color_t;
#define RTGUI_ARGB(a, r, g, b) \
((rtgui_color_t)(((rt_uint8_t)(r)|\
(((unsigned)(rt_uint8_t)(g))<<8))|\
(((unsigned long)(rt_uint8_t)(b))<<16)|\
(((unsigned long)(rt_uint8_t)(a))<<24)))
#define RTGUI_RGB(r, g, b) RTGUI_ARGB(255, (r), (g), (b))
#define RTGUI_RGB_R(c) ((c) & 0xff)
#define RTGUI_RGB_G(c) (((c) >> 8) & 0xff)
#define RTGUI_RGB_B(c) (((c) >> 16) & 0xff)
#define RTGUI_RGB_A(c) (((c) >> 24) & 0xff)
extern const rtgui_color_t default_foreground;
extern const rtgui_color_t default_background;
extern const rtgui_color_t red;
extern const rtgui_color_t green;
extern const rtgui_color_t blue;
extern const rtgui_color_t black;
extern const rtgui_color_t white;
extern const rtgui_color_t high_light;
extern const rtgui_color_t dark_grey;
extern const rtgui_color_t light_grey;
/*
* RTGUI default color format
* BBBB BBBB GGGG GGGG RRRR RRRR
*/
/* convert rtgui color to BBBBBGGGGGGRRRRR */
rt_inline rt_uint16_t rtgui_color_to_565(rtgui_color_t c)
{
rt_uint16_t pixel;
pixel = ((RTGUI_RGB_B(c)>> 3) << 11) | ((RTGUI_RGB_G(c) >> 2) << 5) | (RTGUI_RGB_R(c) >> 3);
return pixel;
}
rt_inline rtgui_color_t rtgui_color_from_565(rt_uint16_t pixel)
{
rt_uint16_t r, g, b;
rtgui_color_t color;
r = pixel & 0x1f;
g = (pixel >> 5) & 0x3f;
b = (pixel >> 11) & 0x1f;
color = r * 8225 / 1024 + ((g * 4047 / 1024) << 8) + ((b * 8225 / 1024) << 16);
return color;
}
/* convert rtgui color to RRRRRGGGGGGBBBBB */
rt_inline rt_uint16_t rtgui_color_to_565p(rtgui_color_t c)
{
rt_uint16_t pixel;
pixel = ((RTGUI_RGB_R(c) >> 3) << 11) | ((RTGUI_RGB_G(c) >> 2) << 5) | (RTGUI_RGB_B(c)>> 3);
return pixel;
}
rt_inline rtgui_color_t rtgui_color_from_565p(rt_uint16_t pixel)
{
rt_uint8_t r, g, b;
rtgui_color_t color;
r = (pixel >> 11) & 0x1f;
g = (pixel >> 5) & 0x3f;
b = pixel & 0x1f;
color = r * 8225 / 1024 + ((g * 4047 / 1024) << 8) + ((b * 8225 / 1024) << 16);
return color;
}
#endif
/*
* File : dc.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_DC_H__
#define __RTGUI_DC_H__
#include <rtgui/rtgui.h>
#include <rtgui/font.h>
#include <rtgui/driver.h>
#include <rtgui/widgets/widget.h>
enum rtgui_dc_type
{
RTGUI_DC_HW,
RTGUI_DC_BUFFER,
};
/* the abstract device context */
struct rtgui_dc
{
/* type of device context */
rt_uint32_t type;
/* interface */
void (*draw_point)(struct rtgui_dc* dc, int x, int y);
void (*draw_vline)(struct rtgui_dc* dc, int x, int y1, int y2);
void (*draw_hline)(struct rtgui_dc* dc, int x1, int x2, int y);
void (*fill_rect )(struct rtgui_dc* dc, rtgui_rect_t* rect);
void (*blit )(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect);
/* set and get color */
void (*set_color )(struct rtgui_dc* dc, rtgui_color_t color);
rtgui_color_t (*get_color)(struct rtgui_dc* dc);
/* set and get font */
void (*set_font )(struct rtgui_dc* dc, rtgui_font_t* font);
rtgui_font_t* (*get_font)(struct rtgui_dc* dc);
void (*set_textalign)(struct rtgui_dc* dc, rt_int32_t align);
rt_int32_t (*get_textalign)(struct rtgui_dc* dc);
/* get dc visible */
rt_bool_t (*get_visible)(struct rtgui_dc* dc);
/* get dc rect */
void (*get_rect )(struct rtgui_dc* dc, rtgui_rect_t* rect);
rt_bool_t (*fini )(struct rtgui_dc* dc);
};
/* hardware device context */
struct rtgui_dc_hw
{
struct rtgui_dc parent;
/* widget owner */
rtgui_widget_t* owner;
/* visible */
rt_bool_t visible;
/* display driver */
struct rtgui_graphic_driver* device;
};
/* create a buffer dc */
struct rtgui_dc* rtgui_dc_buffer_create(int width, int height);
rt_uint8_t* rtgui_dc_buffer_get_pixel(struct rtgui_dc* dc);
/* create a hardware dc */
struct rtgui_dc* rtgui_dc_hw_create(rtgui_widget_t* owner);
struct rtgui_dc* rtgui_dc_begin_drawing(rtgui_widget_t* owner);
void rtgui_dc_end_drawing(struct rtgui_dc* dc);
/* destroy a dc */
void rtgui_dc_destory(struct rtgui_dc* dc);
void rtgui_dc_draw_point(struct rtgui_dc* dc, int x, int y);
void rtgui_dc_draw_vline(struct rtgui_dc* dc, int x, int y1, int y2);
void rtgui_dc_draw_hline(struct rtgui_dc* dc, int x1, int x2, int y);
void rtgui_dc_fill_rect (struct rtgui_dc* dc, struct rtgui_rect* rect);
void rtgui_dc_blit(struct rtgui_dc* dc, struct rtgui_point* dc_point, struct rtgui_dc* dest, rtgui_rect_t* rect);
void rtgui_dc_set_color(struct rtgui_dc* dc, rtgui_color_t color);
rtgui_color_t rtgui_dc_get_color(struct rtgui_dc* dc);
void rtgui_dc_set_font(struct rtgui_dc* dc, rtgui_font_t* font);
rtgui_font_t* rtgui_dc_get_font(struct rtgui_dc* dc);
void rtgui_dc_set_textalign(struct rtgui_dc* dc, rt_int32_t align);
rt_int32_t rtgui_dc_get_textalign(struct rtgui_dc* dc);
rt_bool_t rtgui_dc_get_visible(struct rtgui_dc* dc);
void rtgui_dc_get_rect(struct rtgui_dc*dc, rtgui_rect_t* rect);
void rtgui_dc_draw_line (struct rtgui_dc* dc, int x1, int y1, int x2, int y2);
void rtgui_dc_draw_rect (struct rtgui_dc* dc, struct rtgui_rect* rect);
void rtgui_dc_draw_text (struct rtgui_dc* dc, const rt_uint8_t* text, struct rtgui_rect* rect);
void rtgui_dc_draw_border(struct rtgui_dc* dc, rtgui_rect_t* rect, int flag);
void rtgui_dc_draw_horizontal_line(struct rtgui_dc* dc, int x1, int x2, int y);
void rtgui_dc_draw_vertical_line(struct rtgui_dc* dc, int x, int y1, int y2);
void rtgui_dc_draw_arrow(struct rtgui_dc* dc, rtgui_rect_t* rect, int kind);
void rtgui_dc_draw_focus_rect(struct rtgui_dc* dc, rtgui_rect_t* rect);
void rtgui_dc_draw_polygon(struct rtgui_dc* dc, const int *vx, const int *vy, int count);
void rtgui_dc_fill_polygon(struct rtgui_dc* dc, const int* vx, const int* vy, int count);
void rtgui_dc_draw_circle(struct rtgui_dc* dc, int x, int y, int r);
void rtgui_dc_fill_circle(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t r);
void rtgui_dc_draw_arc(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r, rt_int16_t start, rt_int16_t end);
void rtgui_dc_draw_ellipse(struct rtgui_dc* dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry);
void rtgui_dc_fill_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry);
#endif
/*
* File : filerw.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_FILERW_H__
#define __RTGUI_FILERW_H__
#include <rtgui/rtgui.h>
#define RTGUI_FILE_SEEK_SET 0
#define RTGUI_FILE_SEEK_CUR 1
#define RTGUI_FILE_SEEK_END 2
struct rtgui_filerw
{
int (*seek) (struct rtgui_filerw *context, rt_off_t offset, int whence);
int (*read) (struct rtgui_filerw *context, void *buffer, rt_size_t size, rt_size_t count);
int (*write)(struct rtgui_filerw *context, const void *buffer, rt_size_t size, rt_size_t count);
int (*tell) (struct rtgui_filerw *context);
int (*eof) (struct rtgui_filerw *context);
int (*close)(struct rtgui_filerw *context);
};
typedef struct rtgui_filerw rtgui_filerw_t;
struct rtgui_filerw* rtgui_filerw_create_file(const char* filename, const char* mode);
struct rtgui_filerw* rtgui_filerw_create_mem(rt_uint8_t* mem, rt_size_t size);
int rtgui_filerw_seek (struct rtgui_filerw* context, rt_off_t offset, int whence);
int rtgui_filerw_read (struct rtgui_filerw* context, void* buffer, rt_size_t size, rt_size_t count);
int rtgui_filerw_write(struct rtgui_filerw* context, const void* buffer, rt_size_t size, rt_size_t count);
int rtgui_filerw_tell (struct rtgui_filerw* context);
int rtgui_filerw_eof (struct rtgui_filerw* context);
int rtgui_filerw_close(struct rtgui_filerw* context);
/* get memory data from filerw memory object */
rt_uint8_t* rtgui_filerw_mem_getdata(struct rtgui_filerw* context);
#endif
/*
* File : font.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_FONT_H__
#define __RTGUI_FONT_H__
#include <rtgui/rtgui.h>
#include <rtgui/list.h>
struct rtgui_font;
struct rtgui_dc;
struct rtgui_rect;
struct rtgui_font_engine
{
/* font engine function */
void (*font_init)(struct rtgui_font* font);
void (*font_load)(struct rtgui_font* font);
void (*font_draw_text)(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text,
rt_ubase_t len, struct rtgui_rect* rect);
void (*font_get_metrics)(struct rtgui_font* font, const rt_uint8_t* text, struct rtgui_rect* rect);
};
/*
* bitmap font engine
*/
/* bitmap font private data */
struct rtgui_font_bitmap
{
/* bitmap data */
const rt_uint8_t* bmp;
rt_uint16_t width;
rt_uint16_t height;
rt_uint8_t first_char;
rt_uint8_t last_char;
};
extern struct rtgui_font_engine bmp_font_engine;
struct rtgui_font
{
/* font name */
char* family;
/* font height */
rt_uint16_t height;
/* refer count */
rt_uint32_t refer_count;
/* font engine */
struct rtgui_font_engine* engine;
/* font private data */
void* data;
/* the font list */
rtgui_list_t list;
};
typedef struct rtgui_font rtgui_font_t;
void rtgui_font_system_init(void);
void rtgui_font_system_add_font(struct rtgui_font* font);
void rtgui_font_system_remove_font(struct rtgui_font* font);
struct rtgui_font* rtgui_font_default(void);
void rtgui_font_set_defaut(struct rtgui_font* font);
struct rtgui_font* rtgui_font_refer(const rt_uint8_t* family, rt_uint16_t height);
void rtgui_font_derefer(struct rtgui_font* font);
/* draw a text */
void rtgui_font_draw(struct rtgui_font* font, struct rtgui_dc* dc, const rt_uint8_t* text, rt_ubase_t len, struct rtgui_rect* rect);
int rtgui_font_get_string_width(struct rtgui_font* font, const rt_uint8_t* text);
void rtgui_font_get_metrics(struct rtgui_font* font, const rt_uint8_t* text, struct rtgui_rect* rect);
#endif
/*
* File : image.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_IMAGE_H__
#define __RTGUI_IMAGE_H__
#include <rtgui/dc.h>
#include <rtgui/filerw.h>
#include <rtgui/region.h>
struct rtgui_image;
struct rtgui_image_engine
{
const char* name;
struct rtgui_list_node list;
/* image engine function */
rt_bool_t (*image_check)(struct rtgui_filerw* file);
rt_bool_t (*image_load)(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load);
void (*image_unload)(struct rtgui_image* image);
void (*image_blit)(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
};
struct rtgui_image
{
/* image metrics */
rt_uint16_t w, h;
/* image engine */
struct rtgui_image_engine* engine;
/* image private data */
void* data;
};
typedef struct rtgui_image rtgui_image_t;
/* init rtgui image system */
void rtgui_system_image_init(void);
struct rtgui_image* rtgui_image_create_from_file(const char* type, const char* filename, rt_bool_t load);
struct rtgui_image* rtgui_image_create_from_mem(const char* type, const rt_uint8_t* data, rt_size_t length);
void rtgui_image_destroy(struct rtgui_image* image);
/* register an image engine */
void rtgui_image_register_engine(struct rtgui_image_engine* engine);
/* blit an image on DC */
void rtgui_image_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
#endif
/*
* File : image_png.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_IMAGE_PNG_H__
#define __RTGUI_IMAGE_PNG_H__
#include <rtgui/image.h>
#endif
/*
* File : image_xpm.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_IMAGE_XPM_H__
#define __RTGUI_IMAGE_XPM_H__
#include <rtgui/image.h>
void rtgui_image_xpm_init(void);
#endif
/*
* 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
/*
* File : list.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_LIST_H__
#define __RTGUI_LIST_H__
#include <rtgui/rtgui.h>
struct rtgui_list_node
{
struct rtgui_list_node* next;
};
typedef struct rtgui_list_node rtgui_list_t;
rt_inline void rtgui_list_init(rtgui_list_t *l)
{
l->next = (struct rtgui_list_node *)0;
}
rt_inline void rtgui_list_append(rtgui_list_t *l, rtgui_list_t *n)
{
struct rtgui_list_node* node;
node = l;
while (node->next) node = node->next;
/* append the node to the tail */
node->next = n;
n->next = (struct rtgui_list_node*) 0;
}
rt_inline void rtgui_list_insert(rtgui_list_t *l, rtgui_list_t *n)
{
n->next = l->next;
l->next = n;
}
rt_inline rtgui_list_t* rtgui_list_remove(rtgui_list_t *l, rtgui_list_t *n)
{
/* remove slist head */
struct rtgui_list_node* node = l;
while (node->next && node->next != n) node = node->next;
/* remove node */
if (node->next != (rtgui_list_t *)0) node->next = node->next->next;
return l;
}
#define rtgui_list_entry(node, type, member) \
((type *)((char*)(node)-(unsigned long)(&((type *)0)->member)))
#define rtgui_list_foreach(node, list) \
for ((node) = (list)->next; (node) != RT_NULL; (node) = (node)->next)
#endif
/*
* File : region.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_REGION_H__
#define __RTGUI_REGION_H__
#include <rtgui/rtgui.h>
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
typedef struct rtgui_region_data rtgui_region_data_t;
struct rtgui_region_data
{
rt_uint32_t size;
rt_uint32_t numRects;
/* XXX: And why, exactly, do we have this bogus struct definition? */
/* rtgui_rect_t rects[size]; in memory but not explicitly declared */
};
typedef struct rtgui_region
{
rtgui_rect_t extents;
rtgui_region_data_t *data;
}rtgui_region_t;
typedef enum
{
RTGUI_REGION_STATUS_FAILURE,
RTGUI_REGION_STATUS_SUCCESS
}rtgui_region_status_t;
/* creation/destruction */
void rtgui_region_init(rtgui_region_t *region);
void rtgui_region_init_rect(rtgui_region_t *region,
int x, int y, unsigned int width, unsigned int height);
void rtgui_region_init_with_extents(rtgui_region_t *region, rtgui_rect_t *extents);
void rtgui_region_fini (rtgui_region_t *region);
void rtgui_region_translate (rtgui_region_t *region, int x, int y);
rtgui_region_status_t rtgui_region_copy (rtgui_region_t *dest, rtgui_region_t *source);
rtgui_region_status_t rtgui_region_intersect (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_region_t *reg2);
rtgui_region_status_t rtgui_region_intersect_rect (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_rect_t *rect);
rtgui_region_status_t rtgui_region_union (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_region_t *reg2);
rtgui_region_status_t rtgui_region_union_rect(rtgui_region_t *dest, rtgui_region_t *source, rtgui_rect_t* rect);
rtgui_region_status_t rtgui_region_subtract (rtgui_region_t *regD, rtgui_region_t *regM, rtgui_region_t *regS);
rtgui_region_status_t rtgui_region_subtract_rect (rtgui_region_t *regD, rtgui_region_t *regM, rtgui_rect_t* rect);
rtgui_region_status_t rtgui_region_inverse (rtgui_region_t *newReg, rtgui_region_t *reg1, rtgui_rect_t *invRect);
int rtgui_region_num_rects (rtgui_region_t *region);
rtgui_rect_t* rtgui_region_rects (rtgui_region_t *region);
#define RTGUI_REGION_OUT 0
#define RTGUI_REGION_IN 1
#define RTGUI_REGION_PART 2
int rtgui_region_contains_point (rtgui_region_t *region, int x, int y, rtgui_rect_t *box);
int rtgui_region_contains_rectangle (rtgui_region_t *rtgui_region_t, rtgui_rect_t *prect);
int rtgui_region_not_empty (rtgui_region_t *region);
rtgui_rect_t *rtgui_region_extents (rtgui_region_t *region);
rtgui_region_status_t rtgui_region_append (rtgui_region_t *dest, rtgui_region_t *region);
rtgui_region_status_t rtgui_region_validate (rtgui_region_t *badreg, int *pOverlap);
void rtgui_region_reset(rtgui_region_t *region, rtgui_rect_t* rect);
void rtgui_region_empty (rtgui_region_t *region);
void rtgui_region_dump(rtgui_region_t* region);
/* rect functions */
extern rtgui_rect_t rtgui_empty_rect;
void rtgui_rect_moveto(rtgui_rect_t *rect, int x, int y);
void rtgui_rect_moveto_align(rtgui_rect_t *rect, rtgui_rect_t *to, int align);
void rtgui_rect_inflate(rtgui_rect_t *rect, int d);
void rtgui_rect_intersect(rtgui_rect_t *src, rtgui_rect_t *dest);
int rtgui_rect_contains_point(rtgui_rect_t *rect, int x, int y);
int rtgui_rect_is_intersect(rtgui_rect_t *rect1, rtgui_rect_t *rect2);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif /* _PIXMAN_H_ */
......@@ -16,10 +16,7 @@
#include <rtthread.h>
/* RTGUI options */
#define RTGUI_IMAGE_JPEG
#define RTGUI_NAME_MAX 32
#include <rtgui/rtgui_config.h>
#define RT_INT16_MAX 32767
#define RT_INT16_MIN (-RT_INT16_MAX-1)
......
/*
* 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
......@@ -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
......@@ -15,6 +15,7 @@
#define __RTGUI_THEME_H__
#include <rtgui/rtgui.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/widgets/label.h>
#include <rtgui/widgets/button.h>
......
/*
* File : box.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_BOX_H__
#define __RTGUI_BOX_H__
#include <rtgui/rtgui.h>
#include <rtgui/widgets/widget.h>
#include <rtgui/widgets/container.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Gets the type of a box */
#define RTGUI_BOX_TYPE (rtgui_box_type_get())
/** Casts the object to an rtgui_box */
#define RTGUI_BOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_BOX_TYPE, rtgui_box_t))
/** Checks if the object is an rtgui_box */
#define RTGUI_IS_BOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_BOX_TYPE))
struct rtgui_box
{
struct rtgui_container parent;
rt_uint16_t orientation;
rt_uint16_t border_size;
};
typedef struct rtgui_box rtgui_box_t;
rtgui_type_t *rtgui_box_type_get(void);
struct rtgui_box* rtgui_box_create(int orientation, rtgui_rect_t* rect);
void rtgui_box_destroy(struct rtgui_box* box);
rt_bool_t rtgui_box_event_handler(rtgui_widget_t* widget, rtgui_event_t* event);
void rtgui_box_append(rtgui_box_t* box, rtgui_widget_t* widget);
void rtgui_box_layout(rtgui_box_t* box);
rt_uint32_t rtgui_box_get_width(rtgui_box_t* box);
rt_uint32_t rtgui_box_get_height(rtgui_box_t* box);
#ifdef __cplusplus
}
#endif
#endif
/*
* File : button.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_BUTTON_H__
#define __RTGUI_BUTTON_H__
#include <rtgui/image.h>
#include <rtgui/widgets/widget.h>
#include <rtgui/widgets/label.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup rtgui_button
* @{
*/
/** Gets the type of a button */
#define RTGUI_BUTTON_TYPE (rtgui_button_type_get())
/** Casts the object to an rtgui_button */
#define RTGUI_BUTTON(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_BUTTON_TYPE, rtgui_button_t))
/** Checks if the object is an rtgui_button */
#define RTGUI_IS_BUTTON(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_BUTTON_TYPE))
#define RTGUI_BUTTON_FLAG_PRESS 0x01
#define RTGUI_BUTTON_FLAG_DEFAULT 0x02
#define RTGUI_BUTTON_TYPE_NORMAL 0x00
#define RTGUI_BUTTON_TYPE_PUSH 0x10
/*
* the button widget
*/
struct rtgui_button
{
/* inherit from label */
struct rtgui_label parent;
/* button flag */
rt_base_t flag;
/* pressed and unpressed image */
rtgui_image_t *pressed_image, *unpressed_image;
/* click button event handler */
void (*on_button)(struct rtgui_widget* widget, rtgui_event_t *event);
};
typedef struct rtgui_button rtgui_button_t;
rtgui_type_t *rtgui_button_type_get(void);
rtgui_button_t* rtgui_button_create(unsigned char* text);
rtgui_button_t* rtgui_pushbutton_create(unsigned char* text);
void rtgui_button_destroy(rtgui_button_t* btn);
void rtgui_button_set_pressed_image(rtgui_button_t* btn, rtgui_image_t* image);
void rtgui_button_set_unpressed_image(rtgui_button_t* btn, rtgui_image_t* image);
void rtgui_button_ondraw(rtgui_button_t* btn);
rt_bool_t rtgui_button_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
/** @} */
#ifdef __cplusplus
}
#endif
#endif
/*
* File : container.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_CONTAINER_H__
#define __RTGUI_CONTAINER_H__
#include <rtgui/widgets/widget.h>
/** Gets the type of a container */
#define RTGUI_CONTAINER_TYPE (rtgui_container_type_get())
/** Casts the object to a rtgui_container */
#define RTGUI_CONTAINER(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_CONTAINER_TYPE, rtgui_container_t))
/** Checks if the object is a rtgui_container */
#define RTGUI_IS_CONTAINER(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_CONTAINER_TYPE))
struct rtgui_container
{
/* inherit from widget */
struct rtgui_widget parent;
rtgui_list_t children;
};
typedef struct rtgui_container rtgui_container_t;
rtgui_type_t *rtgui_container_type_get(void);
void rtgui_container_add_child(rtgui_container_t *container, rtgui_widget_t* child);
void rtgui_container_remove_child(rtgui_container_t *container, rtgui_widget_t* child);
void rtgui_container_destroy_children(rtgui_container_t *container);
rtgui_widget_t* rtgui_container_get_first_child(rtgui_container_t* container);
rt_bool_t rtgui_container_event_handler(rtgui_widget_t* widget, rtgui_event_t* event);
rt_bool_t rtgui_container_dispatch_event(rtgui_container_t *container, rtgui_event_t* event);
rt_bool_t rtgui_container_dispatch_mouse_event(rtgui_container_t *container, struct rtgui_event_mouse* event);
#endif
/*
* File : iconbox.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_ICONBOX_H__
#define __RTGUI_ICONBOX_H__
#include <rtgui/rtgui.h>
#include <rtgui/image.h>
#include <rtgui/widgets/widget.h>
/** Gets the type of a iconbox */
#define RTGUI_ICONBOX_TYPE (rtgui_iconbox_type_get())
/** Casts the object to a rtgui_iconbox */
#define RTGUI_ICONBOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_ICONBOX_TYPE, rtgui_iconbox_t))
/** Checks if the object is a rtgui_iconbox */
#define RTGUI_IS_ICONBOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_ICONBOX_TYPE))
#define RTGUI_ICONBOX_NOTEXT 0x00
#define RTGUI_ICONBOX_TEXT_RIGHT 0x01
#define RTGUI_ICONBOX_TEXT_BELOW 0x02
struct rtgui_iconbox
{
/* inherit from widget */
struct rtgui_widget parent;
/* widget private data */
struct rtgui_image* image;
unsigned char *text;
rt_ubase_t text_position;
rt_bool_t selected;
};
typedef struct rtgui_iconbox rtgui_iconbox_t;
rtgui_type_t *rtgui_iconbox_type_get(void);
struct rtgui_iconbox* rtgui_iconbox_create(struct rtgui_image* image, const unsigned char* text, int position);
void rtgui_iconbox_destroy(struct rtgui_iconbox* iconbox);
rt_bool_t rtgui_iconbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
void rtgui_iconbox_set_text_position(struct rtgui_iconbox* iconbox, int position);
#endif
/*
* File : label.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_LABEL_H__
#define __RTGUI_LABEL_H__
#include <rtgui/rtgui.h>
#include <rtgui/widgets/widget.h>
/** Gets the type of a button */
#define RTGUI_LABEL_TYPE (rtgui_label_type_get())
/** Casts the object to an rtgui_button */
#define RTGUI_LABEL(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_LABEL_TYPE, rtgui_label_t))
/** Checks if the object is an rtgui_button */
#define RTGUI_IS_LABEL(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_LABEL_TYPE))
/*
* the label widget
*/
struct rtgui_label
{
struct rtgui_widget parent;
/* label */
unsigned char* text;
};
typedef struct rtgui_label rtgui_label_t;
rtgui_type_t *rtgui_label_type_get(void);
rtgui_label_t* rtgui_label_create(const unsigned char* text);
void rtgui_label_destroy(rtgui_label_t* label);
rt_bool_t rtgui_label_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
void rtgui_label_set_text(rtgui_label_t* label, const unsigned char* text);
unsigned char* rtgui_label_get_text(rtgui_label_t* label);
#endif
/*
* File : listbox.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_LISTBOX_H__
#define __RTGUI_LISTBOX_H__
#include <rtgui/widgets/item.h>
#include <rtgui/widgets/scrollview.h>
#define RTGUI_LISTBOX_WIDTH 150
#define RTGUI_LISTBOX_HEIGHT 200
/** Gets the type of a listbox */
#define RTGUI_LISTBOX_TYPE (rtgui_listbox_type_get())
/** Casts the object to a rtgui_listbox */
#define RTGUI_LISTBOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_LISTBOX_TYPE, rtgui_listbox_t))
/** Checks if the object is a rtgui_listbox */
#define RTGUI_IS_LISTBOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_LISTBOX_TYPE))
/*
* the listbox widget
*/
struct rtgui_listbox
{
struct rtgui_scrollview parent;
/* widget private data */
int flag;
/* total number of items */
rt_uint32_t count;
/* the selected item */
struct rtgui_item* selected;
/* call back */
rt_bool_t (*on_selected) (struct rtgui_widget* widget, struct rtgui_event* event);
rt_bool_t (*on_activated) (struct rtgui_widget* widget, struct rtgui_event* event);
};
typedef struct rtgui_listbox rtgui_listbox_t;
rtgui_type_t *rtgui_listbox_type_get(void);
rtgui_listbox_t* rtgui_listbox_create(void);
void rtgui_listbox_destroy(rtgui_listbox_t* listbox);
rt_bool_t rtgui_listbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
struct rtgui_item* rtgui_listbox_get_select(struct rtgui_listbox* box);
void rtgui_listbox_set_select(struct rtgui_listbox* box, rt_uint32_t index);
void rtgui_listbox_set_select_item(struct rtgui_listbox* box, struct rtgui_item* item);
struct rtgui_item* rtgui_listbox_add_item_string(struct rtgui_listbox* box, const unsigned char* text);
void rtgui_listbox_add_item(struct rtgui_listbox* list, struct rtgui_item* item);
#endif
/*
* File : textbox.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_TEXTBOX_H__
#define __RTGUI_TEXTBOX_H__
#include <rtgui/rtgui.h>
#include <rtgui/caret.h>
#include <rtgui/widgets/widget.h>
/** Gets the type of a textbox */
#define RTGUI_TEXTBOX_TYPE (rtgui_textbox_type_get())
/** Casts the object to a rtgui_textbox */
#define RTGUI_TEXTBOX(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_TEXTBOX_TYPE, rtgui_textbox_t))
/** Checks if the object is a rtgui_textbox */
#define RTGUI_IS_TEXTBOX(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_TEXTBOX_TYPE))
#define RTGUI_TEXTBOX_DEFAULT_WIDTH 80
#define RTGUI_TEXTBOX_DEFAULT_HEIGHT 20
#define RTGUI_TEXTBOX_SINGLE 0x00
#define RTGUI_TEXTBOX_MULTI 0x00
struct rtgui_textbox_line
{
rt_uint8_t* line_text;
struct rtgui_textbox_line *prev, *next;
};
struct rtgui_textbox
{
/* inherit from widget */
struct rtgui_widget parent;
/* text box type */
rt_ubase_t type;
/* current line and position */
rt_size_t line, line_begin, position, line_length;
rt_uint8_t* text;
rt_size_t font_width;
int caret_x, caret_y;
struct rtgui_caret* caret;
/* widget private data */
rt_bool_t (*on_enter) (struct rtgui_widget* widget, struct rtgui_event* event);
};
typedef struct rtgui_textbox rtgui_textbox_t;
struct rtgui_textbox* rtgui_textbox_create(const char* text);
void rtgui_textbox_destroy(struct rtgui_textbox* box);
rt_bool_t rtgui_textbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
void rtgui_textbox_set_value(struct rtgui_textbox* box, const char* text);
const char* rtgui_textbox_get_value(struct rtgui_textbox* box);
void rtgui_widget_set_line_length(struct rtgui_textbox* box, rt_size_t length);
#endif
/*
* File : title.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_TITLE__
#define __RTGUI_TITLE__
#include <rtgui/widgets/toplevel.h>
/** Gets the type of a top win */
#define RTGUI_WINTITLE_TYPE (rtgui_wintitle_type_get())
/** Casts the object to an rtgui_wintitle */
#define RTGUI_WINTITLE(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_WINTITLE_TYPE, rtgui_wintitle_t))
/** Checks if the object is an rtgui_wintitle */
#define RTGUI_IS_WINTITLE(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_WINTITLE_TYPE))
struct rtgui_wintitle
{
struct rtgui_toplevel parent;
/* title */
rt_uint8_t* title;
};
typedef struct rtgui_wintitle rtgui_wintitle_t;
rtgui_type_t* rtgui_wintitle_type_get(void);
rtgui_wintitle_t* rtgui_wintitle_create(const rt_uint8_t* title);
void rtgui_wintitle_destroy(rtgui_wintitle_t* wintitle);
rt_bool_t rtgui_wintile_event_handler(rtgui_widget_t* widget, rtgui_event_t* event);
void rtgui_wintitle_set_title(rtgui_wintitle_t* wintitle, const rt_uint8_t* title);
rt_uint8_t *rtgui_wintitle_get_title(rtgui_wintitle_t* wintitle);
#endif
/*
* File : toplevel.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_TOPLEVEL_H__
#define __RTGUI_TOPLEVEL_H__
#include <rtgui/widgets/container.h>
/** Gets the type of a toplevel */
#define RTGUI_TOPLEVEL_TYPE (rtgui_toplevel_type_get())
/** Casts the object to an rtgui_toplevel */
#define RTGUI_TOPLEVEL(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_TOPLEVEL_TYPE, rtgui_toplevel_t))
/** Checks if the object is an rtgui_toplevel */
#define RTGUI_IS_TOPLEVEL(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_TOPLEVEL_TYPE))
struct rtgui_toplevel
{
/* inherit from container */
rtgui_container_t parent;
/* drawing count */
rt_base_t drawing;
/* external clip info */
rtgui_rect_t* external_clip_rect;
rt_uint32_t external_clip_size;
/* server thread id */
rt_thread_t server;
/* current focus widget */
rtgui_widget_t* focus;
};
typedef struct rtgui_toplevel rtgui_toplevel_t;
rtgui_type_t *rtgui_toplevel_type_get(void);
rt_bool_t rtgui_toplevel_event_handler(rtgui_widget_t* widget, rtgui_event_t* event);
void rtgui_toplevel_handle_clip(struct rtgui_toplevel* top,
struct rtgui_event_clip_info* info);
void rtgui_toplevel_update_clip(rtgui_toplevel_t* top);
void rtgui_toplevel_set_focus(struct rtgui_toplevel* top, rtgui_widget_t* focus);
rtgui_widget_t* rtgui_toplevel_get_focus(struct rtgui_toplevel* top);
#endif
/*
* File : view.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_VIEW_H__
#define __RTGUI_VIEW_H__
#include <rtgui/widgets/box.h>
#include <rtgui/widgets/container.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Gets the type of a view */
#define RTGUI_VIEW_TYPE (rtgui_view_type_get())
/** Casts the object to an rtgui_view */
#define RTGUI_VIEW(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_VIEW_TYPE, rtgui_view_t))
/** Checks if the object is an rtgui_view */
#define RTGUI_IS_VIEW(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_VIEW_TYPE))
/*
* the view widget
*/
struct rtgui_view
{
/* inherit from container */
struct rtgui_container parent;
/* private field */
char* title;
};
typedef struct rtgui_view rtgui_view_t;
rtgui_view_t* rtgui_view_create(const char* title);
void rtgui_view_destroy(rtgui_view_t* view);
rt_bool_t rtgui_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event);
void rtgui_view_set_box(rtgui_view_t* view, rtgui_box_t* box);
void rtgui_view_show(rtgui_view_t* view);
void rtgui_view_hide(rtgui_view_t* view);
char* rtgui_view_get_title(rtgui_view_t* view);
void rtgui_view_set_title(rtgui_view_t* view, const char* title);
#ifdef __cplusplus
}
#endif
#endif
/*
* File : mouse.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include "mouse.h"
#include <rtgui/region.h>
#include <rtgui/driver.h>
#include <rtgui/rtgui_system.h>
struct rtgui_cursor
{
/* screen byte per pixel */
rt_uint16_t bpp;
/* screen pitch */
rt_uint16_t screen_pitch;
/* current cursor x and y */
rt_uint16_t cx, cy;
#ifdef RTGUI_USING_MOUSE_CURSOR
/* cursor pitch */
rt_uint16_t cursor_pitch;
/* show cursor and show cursor count */
rt_bool_t show_cursor;
rt_base_t show_cursor_count;
/* cursor rect info */
rtgui_rect_t rect;
/* cursor image and saved cursor */
rtgui_image_t *cursor_image;
rt_uint8_t *cursor_saved;
#endif
/* move window rect and border */
struct rtgui_topwin *topwin;
rtgui_rect_t win_rect;
rt_uint8_t *win_left, *win_right;
rt_uint8_t *win_top, *win_bottom;
rt_bool_t win_rect_show, win_rect_has_saved;
/* screen framebuffer */
rt_uint8_t* framebuffer;
};
struct rtgui_cursor* _rtgui_cursor;
#ifdef RTGUI_USING_MOUSE_CURSOR
struct rt_mutex cursor_mutex;
static const rt_uint8_t * cursor_xpm[] = {
"16 16 35 1",
" c None",
". c #A0B8D0",
"+ c #F0F0F0",
"@ c #FFFFFF",
"# c #F0F8F0",
"$ c #A0B0D0",
"% c #90A8C0",
"& c #A0B0C0",
"* c #E0E8F0",
"= c #8090B0",
"- c #D0D8E0",
"; c #7080A0",
"> c #90A0B0",
", c #FFF8FF",
"' c #F0F8FF",
") c #607090",
"! c #8098B0",
"~ c #405060",
"{ c #405070",
"] c #506070",
"^ c #607080",
"/ c #708090",
"( c #7088A0",
"_ c #D0D0E0",
": c #607890",
"< c #C0D0E0",
"[ c #C0C8D0",
"} c #506880",
"| c #5F778F",
"1 c #D0D8F0",
"2 c #506080",
"3 c #C0C8E0",
"4 c #A0A8C0",
"5 c #405870",
"6 c #5F6F8F",
" . ",
" .. ",
" .+. ",
" .@#$ ",
" $@@+% ",
" &@@@*= ",
" %@@@@-; ",
" >@@,''-) ",
" !,''+)~{] ",
" ='-^*/ ",
" (_{:<[^ ",
" ;} |:12 ",
" / )345 ",
" 6}${ ",
" 5{ ",
" "};
static void rtgui_cursor_restore (void);
static void rtgui_cursor_save (void);
static void rtgui_cursor_show (void);
#endif
static void rtgui_winrect_restore (void);
static void rtgui_winrect_save (void);
static void rtgui_winrect_show (void);
#define WIN_MOVE_BORDER 4
void rtgui_mouse_init()
{
struct rtgui_graphic_driver* gd = rtgui_graphic_driver_get_default();
_rtgui_cursor = (struct rtgui_cursor*) rtgui_malloc(sizeof(struct rtgui_cursor));
rt_memset(_rtgui_cursor, 0, sizeof(struct rtgui_cursor));
#ifdef RTGUI_USING_MOUSE_CURSOR
rt_mutex_init(&cursor_mutex, "cursor", RT_IPC_FLAG_FIFO);
#endif
/* init cursor */
_rtgui_cursor->bpp = gd->byte_per_pixel;
_rtgui_cursor->framebuffer = gd->get_framebuffer();
_rtgui_cursor->screen_pitch = _rtgui_cursor->bpp * gd->width;
#ifdef RTGUI_USING_MOUSE_CURSOR
/* init cursor image */
_rtgui_cursor->cursor_image = rtgui_image_create_from_mem("xpm", cursor_xpm, sizeof(cursor_xpm));
if (_rtgui_cursor->cursor_image == RT_NULL)
{
rtgui_free(_rtgui_cursor);
_rtgui_cursor = RT_NULL;
return;
}
/* init rect */
_rtgui_cursor->rect.x1 = _rtgui_cursor->rect.y1 = 0;
_rtgui_cursor->rect.x2 = _rtgui_cursor->cursor_image->w;
_rtgui_cursor->rect.y2 = _rtgui_cursor->cursor_image->h;
_rtgui_cursor->cursor_pitch = _rtgui_cursor->cursor_image->w * _rtgui_cursor->bpp;
_rtgui_cursor->show_cursor = RT_TRUE;
_rtgui_cursor->show_cursor_count = 0;
_rtgui_cursor->cursor_saved = rtgui_malloc(_rtgui_cursor->cursor_image->w *
_rtgui_cursor->cursor_image->h * _rtgui_cursor->bpp);
#endif
/* init window move save image */
_rtgui_cursor->win_rect_has_saved = RT_FALSE;
_rtgui_cursor->win_rect_show = RT_FALSE;
_rtgui_cursor->win_left = rtgui_malloc(_rtgui_cursor->bpp * gd->height * WIN_MOVE_BORDER);
_rtgui_cursor->win_right = rtgui_malloc(_rtgui_cursor->bpp * gd->height * WIN_MOVE_BORDER);
_rtgui_cursor->win_top = rtgui_malloc(_rtgui_cursor->bpp * gd->width * WIN_MOVE_BORDER);
_rtgui_cursor->win_bottom = rtgui_malloc(_rtgui_cursor->bpp * gd->width * WIN_MOVE_BORDER);
}
void rtgui_mouse_moveto(int x, int y)
{
#ifdef RTGUI_USING_MOUSE_CURSOR
rt_mutex_take(&cursor_mutex, RT_WAITING_FOREVER);
#endif
if (x != _rtgui_cursor->cx ||
y != _rtgui_cursor->cy)
{
if (_rtgui_cursor->win_rect_show)
{
if (_rtgui_cursor->win_rect_has_saved == RT_TRUE)
{
rtgui_winrect_restore();
}
#ifdef RTGUI_USING_MOUSE_CURSOR
rtgui_mouse_hide_cursor();
#endif
/* move winrect */
rtgui_rect_moveto(&(_rtgui_cursor->win_rect), x - _rtgui_cursor->cx,
y - _rtgui_cursor->cy);
rtgui_winrect_save();
/* move current cursor */
_rtgui_cursor->cx = x;
_rtgui_cursor->cy = y;
#ifdef RTGUI_USING_MOUSE_CURSOR
/* show cursor */
rtgui_mouse_show_cursor();
#endif
/* show winrect */
rtgui_winrect_show();
}
else
{
#ifdef RTGUI_USING_MOUSE_CURSOR
rtgui_mouse_hide_cursor();
#endif
/* move current cursor */
_rtgui_cursor->cx = x;
_rtgui_cursor->cy = y;
#ifdef RTGUI_USING_MOUSE_CURSOR
/* show cursor */
rtgui_mouse_show_cursor();
#endif
}
}
#ifdef RTGUI_USING_MOUSE_CURSOR
rt_mutex_release(&cursor_mutex);
#endif
}
#ifdef RTGUI_USING_MOUSE_CURSOR
void rtgui_mouse_set_cursor_enable(rt_bool_t enable)
{
_rtgui_cursor->show_cursor = enable;
}
/* set current cursor image */
void rtgui_mouse_set_cursor(rtgui_image_t* cursor)
{
}
void rtgui_mouse_get_cursor_rect(rtgui_rect_t* rect)
{
if (rect != RT_NULL)
{
*rect = _rtgui_cursor->rect;
}
}
void rtgui_mouse_show_cursor()
{
if (_rtgui_cursor->show_cursor == RT_FALSE)
return;
_rtgui_cursor->show_cursor_count ++;
if (_rtgui_cursor->show_cursor_count == 1)
{
/* save show mouse area */
rtgui_cursor_save();
/* show mouse cursor */
rtgui_cursor_show();
}
}
void rtgui_mouse_hide_cursor()
{
if (_rtgui_cursor->show_cursor == RT_FALSE)
return;
if (_rtgui_cursor->show_cursor_count == 1)
{
/* display the cursor coverage area */
rtgui_cursor_restore();
}
_rtgui_cursor->show_cursor_count --;
}
rt_bool_t rtgui_mouse_is_intersect(rtgui_rect_t* r)
{
return rtgui_rect_is_intersect(&(_rtgui_cursor->rect), r) == RT_EOK? RT_TRUE : RT_FALSE;
}
/* display the saved cursor area to screen */
static void rtgui_cursor_restore()
{
rt_base_t idx, height, cursor_pitch;
rt_uint8_t *cursor_ptr, *fb_ptr;
fb_ptr = _rtgui_cursor->framebuffer + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch
+ _rtgui_cursor->cx * _rtgui_cursor->bpp;
cursor_ptr = _rtgui_cursor->cursor_saved;
height = (_rtgui_cursor->cy + _rtgui_cursor->cursor_image->h <
rtgui_graphic_driver_get_default()->height)? _rtgui_cursor->cursor_image->h :
rtgui_graphic_driver_get_default()->height - _rtgui_cursor->cy;
cursor_pitch = (_rtgui_cursor->cx + _rtgui_cursor->cursor_image->w <
rtgui_graphic_driver_get_default()->width)? _rtgui_cursor->cursor_pitch :
(rtgui_graphic_driver_get_default()->width - _rtgui_cursor->cx) * _rtgui_cursor->bpp;
for (idx = 0; idx < height; idx ++)
{
rt_memcpy(fb_ptr, cursor_ptr, cursor_pitch);
fb_ptr += _rtgui_cursor->screen_pitch;
cursor_ptr += _rtgui_cursor->cursor_pitch;
}
}
/* save the cursor coverage area from screen */
static void rtgui_cursor_save()
{
rt_base_t idx, height, cursor_pitch;
rt_uint8_t *cursor_ptr, *fb_ptr;
fb_ptr = _rtgui_cursor->framebuffer + _rtgui_cursor->cy * _rtgui_cursor->screen_pitch +
_rtgui_cursor->cx * _rtgui_cursor->bpp;
cursor_ptr = _rtgui_cursor->cursor_saved;
height = (_rtgui_cursor->cy + _rtgui_cursor->cursor_image->h <
rtgui_graphic_driver_get_default()->height)? _rtgui_cursor->cursor_image->h :
rtgui_graphic_driver_get_default()->height - _rtgui_cursor->cy;
cursor_pitch = (_rtgui_cursor->cx + _rtgui_cursor->cursor_image->w <
rtgui_graphic_driver_get_default()->width)? _rtgui_cursor->cursor_pitch :
(rtgui_graphic_driver_get_default()->width - _rtgui_cursor->cx) * _rtgui_cursor->bpp;
for (idx = 0; idx < height; idx ++)
{
rt_memcpy(cursor_ptr, fb_ptr, cursor_pitch);
fb_ptr += _rtgui_cursor->screen_pitch;
cursor_ptr += _rtgui_cursor->cursor_pitch;
}
}
static void rtgui_cursor_show()
{
rt_uint16_t x, y;
rtgui_color_t* ptr;
rtgui_rect_t rect;
void (*set_pixel) (rtgui_color_t *c, rt_uint16_t x, rt_uint16_t y);
ptr = (rtgui_color_t*) _rtgui_cursor->cursor_image->data;
set_pixel = rtgui_graphic_driver_get_default()->set_pixel;
rtgui_mouse_get_cursor_rect(&rect);
rtgui_rect_moveto(&rect, _rtgui_cursor->cx, _rtgui_cursor->cy);
/* draw each point */
for (y = rect.y1; y < rect.y2; y ++)
{
for (x = rect.x1; x < rect.x2; x++)
{
/* not alpha */
if ((*ptr >> 24) != 255)
{
set_pixel(ptr, x, y);
}
/* move to next color buffer */
ptr ++;
}
}
/* update rect */
rtgui_graphic_driver_get_default()->screen_update(&rect);
}
#endif
void rtgui_winrect_set(struct rtgui_topwin* topwin)
{
/* set win rect show */
_rtgui_cursor->win_rect_show = RT_TRUE;
/* set win rect */
_rtgui_cursor->win_rect = topwin->title == RT_NULL? topwin->extent : RTGUI_WIDGET(topwin->title)->extent;
_rtgui_cursor->topwin = topwin;
}
rt_bool_t rtgui_winrect_moved_done(rtgui_rect_t* winrect, struct rtgui_topwin** topwin)
{
rt_bool_t moved = RT_FALSE;
/* no win rect */
if (winrect == RT_NULL) return RT_FALSE;
/* restore winrect */
if (_rtgui_cursor->win_rect_has_saved)
{
rtgui_winrect_restore();
moved = RT_TRUE;
}
/* clear win rect show */
_rtgui_cursor->win_rect_show = RT_FALSE;
_rtgui_cursor->win_rect_has_saved = RT_FALSE;
/* return win rect */
*winrect = _rtgui_cursor->win_rect;
*topwin = _rtgui_cursor->topwin;
return moved;
}
rt_bool_t rtgui_winrect_is_moved()
{
return _rtgui_cursor->win_rect_show;
}
/* show winrect */
static void rtgui_winrect_show()
{
rt_uint16_t x, y;
rtgui_color_t c;
rtgui_rect_t screen_rect, win_rect, win_rect_inner;
void (*set_pixel) (rtgui_color_t *c, rt_base_t x, rt_base_t y);
c = black;
set_pixel = rtgui_graphic_driver_get_default()->set_pixel;
win_rect = _rtgui_cursor->win_rect;
win_rect_inner = win_rect;
rtgui_rect_inflate(&win_rect_inner, -WIN_MOVE_BORDER);
rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(),
&screen_rect);
rtgui_rect_intersect(&screen_rect, &win_rect);
rtgui_rect_intersect(&screen_rect, &win_rect_inner);
/* draw left */
for (y = win_rect.y1; y < win_rect.y2; y ++)
{
for (x = win_rect.x1; x < win_rect_inner.x1; x++)
if ((x + y) & 0x01) set_pixel(&c, x, y);
}
/* draw right */
for (y = win_rect.y1; y < win_rect.y2; y ++)
{
for (x = win_rect_inner.x2; x < win_rect.x2; x++)
if ((x + y) & 0x01) set_pixel(&c, x, y);
}
/* draw top border */
for (y = win_rect.y1; y < win_rect_inner.y1; y ++)
{
for (x = win_rect_inner.x1; x < win_rect_inner.x2; x++)
if ((x + y) & 0x01) set_pixel(&c, x, y);
}
/* draw bottom border */
for (y = win_rect_inner.y2; y < win_rect.y2; y ++)
{
for (x = win_rect_inner.x1; x < win_rect_inner.x2; x++)
if ((x + y) & 0x01) set_pixel(&c, x, y);
}
/* update rect */
rtgui_graphic_driver_get_default()->screen_update(&win_rect);
}
#define display_direct_memcpy(src, dest, src_pitch, dest_pitch, height, len) \
for (idx = 0; idx < height; idx ++) \
{ \
rt_memcpy(dest, src, len); \
src += src_pitch; \
dest += dest_pitch; \
}
static void rtgui_winrect_restore()
{
rt_uint8_t *winrect_ptr, *fb_ptr;
int winrect_pitch, idx;
rtgui_rect_t screen_rect, win_rect;
win_rect = _rtgui_cursor->win_rect;
rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(),
&screen_rect);
rtgui_rect_intersect(&screen_rect, &win_rect);
/* restore winrect left */
fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
win_rect.x1 * _rtgui_cursor->bpp;
winrect_ptr = _rtgui_cursor->win_left;
winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch,
(win_rect.y2 - win_rect.y1), winrect_pitch);
/* restore winrect right */
fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
(win_rect.x2 - WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
winrect_ptr = _rtgui_cursor->win_right;
winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch,
(win_rect.y2 - win_rect.y1), winrect_pitch);
/* restore winrect top */
fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
(win_rect.x1 + WIN_MOVE_BORDER)* _rtgui_cursor->bpp;
winrect_ptr = _rtgui_cursor->win_top;
winrect_pitch = (win_rect.x2 - win_rect.x1 - 2 * WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch,
WIN_MOVE_BORDER, winrect_pitch);
/* restore winrect bottom */
fb_ptr = _rtgui_cursor->framebuffer + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch +
(win_rect.x1 + WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
winrect_ptr = _rtgui_cursor->win_bottom;
display_direct_memcpy(winrect_ptr, fb_ptr, winrect_pitch, _rtgui_cursor->screen_pitch,
WIN_MOVE_BORDER, winrect_pitch);
}
static void rtgui_winrect_save()
{
rt_uint8_t *winrect_ptr, *fb_ptr;
int winrect_pitch, idx;
rtgui_rect_t screen_rect, win_rect;
win_rect = _rtgui_cursor->win_rect;
rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(),
&screen_rect);
rtgui_rect_intersect(&screen_rect, &win_rect);
/* set winrect has saved */
_rtgui_cursor->win_rect_has_saved = RT_TRUE;
/* save winrect left */
fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
win_rect.x1 * _rtgui_cursor->bpp;
winrect_ptr = _rtgui_cursor->win_left;
winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch,
(win_rect.y2 - win_rect.y1), winrect_pitch);
/* save winrect right */
fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
(win_rect.x2 - WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
winrect_ptr = _rtgui_cursor->win_right;
winrect_pitch = WIN_MOVE_BORDER * _rtgui_cursor->bpp;
display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch,
(win_rect.y2 - win_rect.y1), winrect_pitch);
/* save winrect top */
fb_ptr = _rtgui_cursor->framebuffer + win_rect.y1 * _rtgui_cursor->screen_pitch +
(win_rect.x1 + WIN_MOVE_BORDER)* _rtgui_cursor->bpp;
winrect_ptr = _rtgui_cursor->win_top;
winrect_pitch = (win_rect.x2 - win_rect.x1 - 2 * WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch,
WIN_MOVE_BORDER, winrect_pitch);
/* save winrect bottom */
fb_ptr = _rtgui_cursor->framebuffer + (win_rect.y2 - WIN_MOVE_BORDER) * _rtgui_cursor->screen_pitch +
(win_rect.x1 + WIN_MOVE_BORDER) * _rtgui_cursor->bpp;
winrect_ptr = _rtgui_cursor->win_bottom;
display_direct_memcpy(fb_ptr, winrect_ptr, _rtgui_cursor->screen_pitch, winrect_pitch,
WIN_MOVE_BORDER, winrect_pitch);
}
void rtgui_mouse_monitor_append(rtgui_list_t* head, rtgui_rect_t* rect)
{
struct rtgui_mouse_monitor* mmonitor;
/* check parameters */
if (head == RT_NULL || rect == RT_NULL) return;
/* create a mouse monitor node */
mmonitor = (struct rtgui_mouse_monitor*) rtgui_malloc (sizeof(struct rtgui_mouse_monitor));
if (mmonitor == RT_NULL) return; /* no memory */
/* set mouse monitor node */
mmonitor->rect = *rect;
rtgui_list_init(&(mmonitor->list));
/* append to list */
rtgui_list_append(head, &(mmonitor->list));
}
void rtgui_mouse_monitor_remove(rtgui_list_t* head, rtgui_rect_t* rect)
{
struct rtgui_list_node* node;
struct rtgui_mouse_monitor* mmonitor;
/* check parameters */
if (head == RT_NULL || rect == RT_NULL) return;
for (node = head->next; node != RT_NULL; node = node->next)
{
mmonitor = rtgui_list_entry(node, struct rtgui_mouse_monitor, list);
if (mmonitor->rect.x1 == rect->x1 &&
mmonitor->rect.x2 == rect->x2 &&
mmonitor->rect.y1 == rect->y1 &&
mmonitor->rect.y2 == rect->y2)
{
/* found node */
rtgui_list_remove(head, node);
rtgui_free(mmonitor);
return ;
}
}
}
rt_bool_t rtgui_mouse_monitor_contains_point(rtgui_list_t* head, int x, int y)
{
struct rtgui_list_node* node;
/* check parameter */
if (head == RT_NULL) return RT_FALSE;
rtgui_list_foreach(node, head)
{
struct rtgui_mouse_monitor* monitor = rtgui_list_entry(node,
struct rtgui_mouse_monitor, list);
if (rtgui_rect_contains_point(&(monitor->rect), x, y) == RT_EOK)
{
return RT_TRUE;
}
}
return RT_FALSE;
}
/*
* File : mouse.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_MOUSE_H__
#define __RTGUI_MOUSE_H__
#include <rtgui/rtgui.h>
#include <rtgui/image.h>
#include "topwin.h"
struct rtgui_mouse_monitor
{
/* event rect */
rtgui_rect_t rect;
/* node list */
rtgui_list_t list;
};
typedef struct rtgui_mouse_monitor rtgui_mouse_monitor_t;
void rtgui_mouse_init(void);
void rtgui_mouse_moveto(int x, int y);
void rtgui_mouse_set_cursor_enable(rt_bool_t enable);
void rtgui_mouse_set_cursor(rtgui_image_t* cursor);
void rtgui_mouse_get_cursor_rect(rtgui_rect_t* rect);
void rtgui_mouse_show_cursor(void);
void rtgui_mouse_hide_cursor(void);
rt_bool_t rtgui_mouse_is_intersect(rtgui_rect_t* r);
rt_bool_t rtgui_winrect_is_moved(void);
void rtgui_winrect_set(struct rtgui_topwin* topwin);
rt_bool_t rtgui_winrect_moved_done(rtgui_rect_t* winrect, struct rtgui_topwin** topwin);
void rtgui_mouse_monitor_append(rtgui_list_t* head, rtgui_rect_t* rect);
void rtgui_mouse_monitor_remove(rtgui_list_t* head, rtgui_rect_t* rect);
rt_bool_t rtgui_mouse_monitor_contains_point(rtgui_list_t* head, int x, int y);
#endif
......@@ -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);
......
......@@ -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;
......
/*
* File : topwin.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include "panel.h"
#include "topwin.h"
#include "mouse.h"
#include <rtgui/event.h>
#include <rtgui/image.h>
#include <rtgui/rtgui_theme.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/window.h>
struct rtgui_topwin* rtgui_server_focus_topwin = RT_NULL;
static struct rtgui_list_node _rtgui_topwin_show_list;
static struct rtgui_list_node _rtgui_topwin_hide_list;
static void rtgui_topwin_update_clip(void);
static void rtgui_topwin_redraw(struct rtgui_rect* rect);
#define WINTITLE_CB_WIDTH 14
#define WINTITLE_CB_HEIGHT 14
void rtgui_topwin_init()
{
/* init window list */
rtgui_list_init(&_rtgui_topwin_show_list);
rtgui_list_init(&_rtgui_topwin_hide_list);
}
static struct rtgui_topwin*
rtgui_topwin_search_in_list(struct rtgui_win* wid, struct rtgui_list_node* list)
{
struct rtgui_list_node* node;
struct rtgui_topwin* topwin;
/* search in list */
rtgui_list_foreach(node, list)
{
topwin = rtgui_list_entry(node, struct rtgui_topwin, list);
/* is this node? */
if (topwin->wid == wid)
{
return topwin;
}
}
return RT_NULL;
}
/* add a window to window list[hide] */
rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event)
{
struct rtgui_topwin* topwin;
topwin = rtgui_malloc(sizeof(struct rtgui_topwin));
if (topwin == RT_NULL) return -RT_ERROR;
topwin->wid = event->wid;
topwin->extent = event->extent;
topwin->tid = event->parent.sender;
topwin->mask = event->mask;
topwin->flag = 0;
if (event->flag & RTGUI_WIN_STYLE_NO_TITLE) topwin->flag |= WINTITLE_NO;
if (event->flag & RTGUI_WIN_STYLE_CLOSEBOX) topwin->flag |= WINTITLE_CLOSEBOX;
if (!(event->flag & RTGUI_WIN_STYLE_NO_BORDER)) topwin->flag |= WINTITLE_BORDER;
if (event->flag & RTGUI_WIN_STYLE_NO_FOCUS) topwin->flag |= WINTITLE_NOFOCUS;
if(!(topwin->flag & WINTITLE_NO) || (topwin->flag & WINTITLE_BORDER))
{
/* get win extent */
rtgui_rect_t rect = topwin->extent;
/* add border rect */
if (topwin->flag & WINTITLE_BORDER)
{
rect.x1 -= WINTITLE_BORDER_SIZE;
rect.y1 -= WINTITLE_BORDER_SIZE;
rect.x2 += WINTITLE_BORDER_SIZE;
rect.y2 += WINTITLE_BORDER_SIZE;
}
/* add title rect */
if (!(topwin->flag & WINTITLE_NO)) rect.y1 -= WINTITLE_HEIGHT;
topwin->title = rtgui_wintitle_create(event->title);
rtgui_widget_set_rect(RTGUI_WIDGET(topwin->title), &rect);
/* update clip info */
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip),
&(RTGUI_WIDGET(topwin->title)->clip),
&(topwin->extent));
}
else topwin->title = RT_NULL;
rtgui_list_init(&topwin->list);
rtgui_list_init(&topwin->monitor_list);
/* add topwin node to the hidden window list */
rtgui_list_insert(&(_rtgui_topwin_hide_list), &(topwin->list));
return RT_EOK;
}
rt_err_t rtgui_topwin_remove(struct rtgui_win* wid)
{
struct rtgui_topwin* topwin;
/* find the topwin node */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (topwin)
{
/* remove node from list */
rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
rtgui_topwin_update_clip();
/* redraw the old rect */
rtgui_topwin_redraw(&(topwin->extent));
if (rtgui_server_focus_topwin == topwin)
{
/* activate the next window */
if (_rtgui_topwin_show_list.next != RT_NULL)
{
struct rtgui_event_win wevent;
struct rtgui_topwin* wnd;
/* get the topwin */
wnd = rtgui_list_entry(_rtgui_topwin_show_list.next,
struct rtgui_topwin, list);
/* activate the window */
RTGUI_EVENT_WIN_ACTIVATE_INIT(&wevent);
wevent.wid = wnd->wid;
rtgui_thread_send(wnd->tid, &(wevent.parent), sizeof(struct rtgui_event_win));
/* set new focus topwin */
rtgui_server_focus_topwin = wnd;
}
else
{
/* there is no shown window right now */
rtgui_server_focus_topwin = RT_NULL;
}
}
/* free the monitor rect list, topwin node and title */
while (topwin->monitor_list.next != RT_NULL)
{
struct rtgui_mouse_monitor* monitor = rtgui_list_entry(topwin->monitor_list.next,
struct rtgui_mouse_monitor, list);
topwin->monitor_list.next = topwin->monitor_list.next->next;
rtgui_free(monitor);
}
/* destroy win title */
rtgui_wintitle_destroy(topwin->title);
topwin->title = RT_NULL;
rtgui_free(topwin);
return RT_EOK;
}
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
if (topwin)
{
/* remove node from list */
rtgui_list_remove(&_rtgui_topwin_hide_list, &(topwin->list));
/* free the topwin node and title */
rtgui_wintitle_destroy(topwin->title);
topwin->title = RT_NULL;
rtgui_free(topwin);
return RT_EOK;
}
return -RT_ERROR;
}
/* activate a win
* - deactivate the old focus win
* - activate a win
* - set the focus win to activate win
* - draw win title
*/
void rtgui_topwin_activate_win(struct rtgui_topwin* win)
{
struct rtgui_event_win event;
/* activate the raised window */
RTGUI_EVENT_WIN_ACTIVATE_INIT(&event);
event.wid = win->wid;
rtgui_thread_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win));
/* redraw title */
if (win->title != RT_NULL)
{
win->flag |= WINTITLE_ACTIVATE;
rtgui_theme_draw_win(win);
}
if (rtgui_server_focus_topwin != RT_NULL)
{
/* deactivate the old focus win */
RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event);
event.wid = rtgui_server_focus_topwin->wid;
rtgui_thread_send(rtgui_server_focus_topwin->tid,
&event.parent, sizeof(struct rtgui_event_win));
/* redraw title */
if (rtgui_server_focus_topwin->title != RT_NULL)
{
rtgui_server_focus_topwin->flag &= ~WINTITLE_ACTIVATE;
rtgui_theme_draw_win(rtgui_server_focus_topwin);
}
}
rtgui_server_focus_topwin = win;
}
/*
* deactivate a win
* - deactivate the win
* - redraw win title
* - set rtgui_server_focus_topwin
*/
void rtgui_topwin_deactivate_win(struct rtgui_topwin* win)
{
/* deactivate win */
struct rtgui_event_win event;
RTGUI_EVENT_WIN_DEACTIVATE_INIT(&event);
event.wid = win->wid;
rtgui_thread_send(win->tid,
&event.parent, sizeof(struct rtgui_event_win));
win->flag &= ~WINTITLE_ACTIVATE;
rtgui_theme_draw_win(win);
if (rtgui_server_focus_topwin == win)
{
rtgui_server_focus_topwin = RT_NULL;
}
}
/* raise window to front */
void rtgui_topwin_raise(struct rtgui_win* wid, rt_thread_t sender)
{
struct rtgui_topwin* topwin;
/* find the topwin node */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (topwin)
{
rt_int32_t count;
struct rtgui_list_node* node;
struct rtgui_event_clip_info* eclip;
struct rtgui_rect* rect;
/* the window is already placed in front */
if (&(topwin->list) == _rtgui_topwin_show_list.next)
{
rtgui_server_focus_topwin = RT_NULL;
rtgui_topwin_activate_win(topwin);
return ;
}
/* update clip info */
count = 0;
node = _rtgui_topwin_show_list.next;
while (node != &(topwin->list))
{
count ++;
node = node->next;
}
eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info)
+ (count + 1)* sizeof(struct rtgui_rect));
/* reset clip info to top window */
RTGUI_EVENT_CLIP_INFO_INIT(eclip);
eclip->num_rect = 0;
eclip->wid = topwin->wid;
/* send to destination window */
rtgui_thread_send(topwin->tid, &(eclip->parent), sizeof(struct rtgui_event_clip_info));
/* reset clip info in title */
rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(topwin->title), eclip);
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip),
&(RTGUI_WIDGET(topwin->title)->clip),
&(topwin->extent));
rect = RTGUI_EVENT_GET_RECT(eclip, 0);
*rect = (topwin->title != RT_NULL)? RTGUI_WIDGET(topwin->title)->extent : topwin->extent;
count = 1;
for (node = _rtgui_topwin_show_list.next;
node != &(topwin->list);
node = node->next)
{
struct rtgui_topwin* wnd;
wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
eclip->num_rect = count;
eclip->wid = wnd->wid;
/* send to destination window */
rtgui_thread_send(wnd->tid, &(eclip->parent),
sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect));
/* reset clip info in title */
rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(wnd->title), eclip);
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip),
&(RTGUI_WIDGET(wnd->title)->clip),
&(wnd->extent));
rect = RTGUI_EVENT_GET_RECT(eclip, count++);
*rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent;
}
/* release clip info event */
rtgui_free(eclip);
/* remove node from list */
rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
/* add to front */
rtgui_list_insert(&_rtgui_topwin_show_list, &(topwin->list));
rtgui_topwin_activate_win(topwin);
}
}
/* show a window */
void rtgui_topwin_show(struct rtgui_event_win* event)
{
struct rtgui_topwin* topwin;
struct rtgui_win* wid = event->wid;
rt_thread_t sender = RTGUI_EVENT(event)->sender;
/* find in hide list */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
/* find it */
if (topwin != RT_NULL)
{
/* remove node from hidden list */
rtgui_list_remove(&_rtgui_topwin_hide_list, &(topwin->list));
/* add node to show list */
rtgui_list_insert(&_rtgui_topwin_show_list, &(topwin->list));
/* show window title */
if (topwin->title != RT_NULL)
{
RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(topwin->title));
}
/* update clip info */
rtgui_topwin_update_clip();
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
/* activate this window */
rtgui_topwin_activate_win(topwin);
}
else
{
/* the wnd is located in show list, raise wnd to front */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (topwin != RT_NULL)
{
if (_rtgui_topwin_show_list.next != &(topwin->list))
{
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
/* not the front window, raise it */
rtgui_topwin_raise(wid, sender);
}
}
else
{
/* there is no wnd in wnd list */
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
}
}
}
/* send clip info to panel */
void rtgui_topwin_update_clip_to_panel(struct rtgui_panel* panel)
{
rt_uint32_t count;
rt_thread_t tid;
struct rtgui_list_node* node;
struct rtgui_event_clip_info* eclip;
/* get topwin count */
count = 0;
node = _rtgui_topwin_show_list.next;
while (node != RT_NULL)
{
count ++;
node = node->next;
}
eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info)
+ (count + 1)* sizeof(struct rtgui_rect));
if (eclip == RT_NULL)
{
/* no memory */
return ;
}
/* reset clip info to top window */
RTGUI_EVENT_CLIP_INFO_INIT(eclip);
eclip->num_rect = count; eclip->wid = RT_NULL;
count = 0;
for (node = _rtgui_topwin_show_list.next; node != RT_NULL; node = node->next)
{
struct rtgui_topwin* wnd;
struct rtgui_rect* rect;
wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
rect = RTGUI_EVENT_GET_RECT(eclip, count++);
*rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent;
}
/* send to the activated thread of panel */
tid = rtgui_panel_get_active_thread(panel);
rtgui_thread_send(tid, (struct rtgui_event*)eclip, sizeof(struct rtgui_event_clip_info)
+ count* sizeof(struct rtgui_rect));
/* release clip info event */
rtgui_free(eclip);
}
/* hide a window */
void rtgui_topwin_hide(struct rtgui_event_win* event)
{
struct rtgui_topwin* topwin;
struct rtgui_win* wid = event->wid;
/* find in show list */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
/* found it */
if (topwin)
{
/* remove node from show list */
rtgui_list_remove(&_rtgui_topwin_show_list, &(topwin->list));
/* add node to hidden list */
rtgui_list_insert(&_rtgui_topwin_hide_list, &(topwin->list));
/* show window title */
if (topwin->title != RT_NULL)
{
RTGUI_WIDGET_HIDE(RTGUI_WIDGET(topwin->title));
}
/* update clip info */
rtgui_topwin_update_clip();
/* redraw the old rect */
rtgui_topwin_redraw(&(topwin->extent));
if (rtgui_server_focus_topwin == topwin)
{
/* activate the next window */
if (_rtgui_topwin_show_list.next != RT_NULL)
{
/* get the topwin */
topwin = rtgui_list_entry(_rtgui_topwin_show_list.next,
struct rtgui_topwin, list);
rtgui_server_focus_topwin = RT_NULL;
rtgui_topwin_activate_win(topwin);
}
else
{
/* there is no shown window right now */
rtgui_server_focus_topwin = RT_NULL;
}
}
}
else
{
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
return;
}
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
}
/* move top window */
void rtgui_topwin_move(struct rtgui_event_win_move* event)
{
struct rtgui_topwin* topwin;
/* find in show list */
topwin = rtgui_topwin_search_in_list(event->wid, &_rtgui_topwin_show_list);
if (topwin != RT_NULL)
{
int dx, dy;
rtgui_rect_t rect; /* the old topwin coverage area */
struct rtgui_list_node* node;
/* send status ok */
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_OK);
/* get the delta move x, y */
dx = event->x - topwin->extent.x1;
dy = event->y - topwin->extent.y1;
rect = topwin->extent;
/* move window rect */
rtgui_rect_moveto(&(topwin->extent), dx, dy);
/* move window title */
if (topwin->title != RT_NULL)
{
rect = RTGUI_WIDGET(topwin->title)->extent;
rtgui_widget_move_to_logic(RTGUI_WIDGET(topwin->title), dx, dy);
}
/* move the monitor rect list */
rtgui_list_foreach(node, &(topwin->monitor_list))
{
struct rtgui_mouse_monitor* monitor = rtgui_list_entry(node,
struct rtgui_mouse_monitor,
list);
rtgui_rect_moveto(&(monitor->rect), dx, dy);
}
/* update windows clip info */
rtgui_topwin_update_clip();
/* update top window title */
if (topwin->title != RT_NULL) rtgui_theme_draw_win(topwin);
if (rtgui_rect_is_intersect(&rect, &(topwin->extent)) != RT_EOK)
{
/*
* the old rect is not intersect with moved rect,
* re-paint window
*/
struct rtgui_event_paint epaint;
RTGUI_EVENT_PAINT_INIT(&epaint);
epaint.wid = topwin->wid;
rtgui_thread_send(topwin->tid, &(epaint.parent), sizeof(epaint));
}
/* update old window coverage area */
rtgui_topwin_redraw(&rect);
}
else
{
rtgui_thread_ack(RTGUI_EVENT(event), RTGUI_STATUS_ERROR);
}
}
/*
* resize a top win
* Note: currently, only support resize hidden window
*/
void rtgui_topwin_resize(struct rtgui_win* wid, rtgui_rect_t* r)
{
struct rtgui_topwin* topwin;
/* find in show list */
topwin = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
if (topwin)
{
topwin->extent = *r;
if (topwin->title != RT_NULL)
{
/* get win extent */
rtgui_rect_t rect = topwin->extent;
/* add border rect */
if (topwin->flag & WINTITLE_BORDER)
{
rect.x1 -= WINTITLE_BORDER_SIZE;
rect.y1 -= WINTITLE_BORDER_SIZE;
rect.x2 += WINTITLE_BORDER_SIZE;
rect.y2 += WINTITLE_BORDER_SIZE;
}
/* add title rect */
if (!(topwin->flag & WINTITLE_NO)) rect.y1 -= WINTITLE_HEIGHT;
RTGUI_WIDGET(topwin->title)->extent = rect;
/* update title & border clip info */
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(topwin->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(topwin->title)->clip),
&(RTGUI_WIDGET(topwin->title)->clip),
&(topwin->extent));
}
}
}
struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y)
{
struct rtgui_list_node* node;
struct rtgui_topwin* topwin;
/* search in list */
rtgui_list_foreach(node, &(_rtgui_topwin_show_list))
{
topwin = rtgui_list_entry(node, struct rtgui_topwin, list);
/* is this window? */
if ((topwin->title != RT_NULL) &&
rtgui_rect_contains_point(&(RTGUI_WIDGET(topwin->title)->extent), x, y) == RT_EOK)
{
return topwin;
}
else if (rtgui_rect_contains_point(&(topwin->extent), x, y) == RT_EOK)
{
return topwin;
}
}
return RT_NULL;
}
extern struct rtgui_list_node _rtgui_panel_list;
static void rtgui_topwin_update_clip()
{
rt_int32_t count = 0;
struct rtgui_event_clip_info* eclip;
struct rtgui_list_node* node = _rtgui_topwin_show_list.next;
/* calculate count */
while (node != RT_NULL)
{
count ++;
node = node->next;
}
eclip = (struct rtgui_event_clip_info*)rtgui_malloc(sizeof(struct rtgui_event_clip_info)
+ count * sizeof(struct rtgui_rect));
RTGUI_EVENT_CLIP_INFO_INIT(eclip);
count = 0;
rtgui_list_foreach(node, &_rtgui_topwin_show_list)
{
struct rtgui_rect* rect;
struct rtgui_topwin* wnd;
wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
eclip->num_rect = count;
eclip->wid = wnd->wid;
/* send to destination window */
rtgui_thread_send(wnd->tid, &(eclip->parent),
sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect));
/* update clip in win title */
if (wnd->title != RT_NULL)
{
/* reset clip info */
rtgui_toplevel_handle_clip(RTGUI_TOPLEVEL(wnd->title), eclip);
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(wnd->title));
rtgui_region_subtract_rect(&(RTGUI_WIDGET(wnd->title)->clip),
&(RTGUI_WIDGET(wnd->title)->clip),
&(wnd->extent));
}
rect = RTGUI_EVENT_GET_RECT(eclip, count++);
*rect = (wnd->title != RT_NULL)? RTGUI_WIDGET(wnd->title)->extent : wnd->extent;
}
/* send clip info to each panel */
eclip->wid = RT_NULL;
eclip->num_rect = count;
rtgui_list_foreach(node, &(_rtgui_panel_list))
{
struct rtgui_panel* panel;
struct rtgui_list_node* panel_node;
panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
rtgui_list_foreach(panel_node, &(panel->thread_list))
{
struct rtgui_panel_thread* thread;
thread = rtgui_list_entry(panel_node, struct rtgui_panel_thread, list);
/* send clip info to panel */
rtgui_thread_send(thread->tid, &(eclip->parent),
sizeof(struct rtgui_event_clip_info) + count * sizeof(struct rtgui_rect));
}
}
/* release clip info event */
rtgui_free(eclip);
}
static void rtgui_topwin_redraw(struct rtgui_rect* rect)
{
struct rtgui_list_node* node;
struct rtgui_event_paint epaint;
RTGUI_EVENT_PAINT_INIT(&epaint);
rtgui_list_foreach(node, &_rtgui_topwin_show_list)
{
struct rtgui_topwin* wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
if (rtgui_rect_is_intersect(rect, &(wnd->extent)) == RT_EOK)
{
/* draw window */
epaint.wid = wnd->wid;
rtgui_thread_send(wnd->tid, &(epaint.parent), sizeof(epaint));
/* draw title */
if (wnd->title != RT_NULL)
{
rtgui_theme_draw_win(wnd);
}
}
}
/* redraw the panel */
rtgui_list_foreach(node, &(_rtgui_panel_list))
{
struct rtgui_panel* panel;
panel = rtgui_list_entry(node, struct rtgui_panel, sibling);
if (rtgui_rect_is_intersect(rect, &(panel->extent)) == RT_EOK)
{
/* draw panel */
epaint.wid = RT_NULL;
rtgui_thread_send(rtgui_panel_get_active_thread(panel),
&(epaint.parent), sizeof(epaint));
}
}
}
void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mouse* event)
{
rtgui_rect_t rect;
/* let window to process this mouse event */
if (rtgui_rect_contains_point(&win->extent, event->x, event->y) == RT_EOK)
{
/* send mouse event to thread */
rtgui_thread_send(win->tid, &(event->parent), sizeof(struct rtgui_event_mouse));
return;
}
/* get close button rect (device value) */
rect.x1 = RTGUI_WIDGET(win->title)->extent.x2 - WINTITLE_BORDER_SIZE - WINTITLE_CB_WIDTH - 3;
rect.y1 = RTGUI_WIDGET(win->title)->extent.y1 + WINTITLE_BORDER_SIZE + 3;
rect.x2 = rect.x1 + WINTITLE_CB_WIDTH;
rect.y2 = rect.y1 + WINTITLE_CB_HEIGHT;
if (event->button & RTGUI_MOUSE_BUTTON_LEFT)
{
if (event->button & RTGUI_MOUSE_BUTTON_DOWN)
{
if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK)
{
win->flag |= WINTITLE_CB_PRESSED;
rtgui_theme_draw_win(win);
}
else
{
/* maybe move window */
rtgui_winrect_set(win);
}
}
else if (event->button & RTGUI_MOUSE_BUTTON_UP)
{
if (rtgui_rect_contains_point(&rect, event->x, event->y) == RT_EOK)
{
struct rtgui_event_win event;
win->flag &= ~WINTITLE_CB_PRESSED;
rtgui_theme_draw_win(win);
/* send close event to window */
RTGUI_EVENT_WIN_CLOSE_INIT(&event);
event.wid = win->wid;
rtgui_thread_send(win->tid, &(event.parent), sizeof(struct rtgui_event_win));
}
}
}
}
void rtgui_topwin_append_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect)
{
struct rtgui_topwin* win;
/* parameters check */
if (wid == RT_NULL || rect == RT_NULL) return;
/* find topwin */
win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (win == RT_NULL)
win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
if (win == RT_NULL) return;
/* append rect to top window monitor rect list */
rtgui_mouse_monitor_append(&(win->monitor_list), rect);
}
void rtgui_topwin_remove_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect)
{
struct rtgui_topwin* win;
/* parameters check */
if (wid == RT_NULL || rect == RT_NULL) return;
/* find topwin */
win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_show_list);
if (win == RT_NULL)
win = rtgui_topwin_search_in_list(wid, &_rtgui_topwin_hide_list);
if (win == RT_NULL) return;
/* remove rect from top window monitor rect list */
rtgui_mouse_monitor_remove(&(win->monitor_list), rect);
}
void rtgui_topwin_dump()
{
struct rtgui_list_node* node;
rtgui_list_foreach(node, &_rtgui_topwin_show_list)
{
struct rtgui_topwin* wnd = rtgui_list_entry(node, struct rtgui_topwin, list);
rt_kprintf("wnd at (%d, %d) - (%d, %d)\n",
wnd->extent.x1, wnd->extent.y1, wnd->extent.x2, wnd->extent.y2);
if (wnd->title != RT_NULL)
{
rt_kprintf("title[%s] border (%d, %d) - (%d, %d)\n", wnd->title->title,
RTGUI_WIDGET(wnd->title)->extent.x1, RTGUI_WIDGET(wnd->title)->extent.y1,
RTGUI_WIDGET(wnd->title)->extent.x2, RTGUI_WIDGET(wnd->title)->extent.y2);
}
}
}
/*
* File : topwin.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_TOPWIN_H__
#define __RTGUI_TOPWIN_H__
#include <rtgui/rtgui.h>
#include <rtgui/list.h>
#include <rtgui/region.h>
#include <rtgui/event.h>
#include <rtgui/widgets/title.h>
#include <rtgui/rtgui_server.h>
/* add or remove a top win */
rt_err_t rtgui_topwin_add(struct rtgui_event_win_create* event);
rt_err_t rtgui_topwin_remove(struct rtgui_win* wid);
/* raise window to front */
void rtgui_topwin_raise(struct rtgui_win* wid, rt_thread_t sender);
/* update clip info to a panel */
void rtgui_topwin_update_clip_to_panel(struct rtgui_panel* panel);
/* show a window */
void rtgui_topwin_show(struct rtgui_event_win* event);
/* hide a window */
void rtgui_topwin_hide(struct rtgui_event_win* event);
/* move a window */
void rtgui_topwin_move(struct rtgui_event_win_move* event);
/* resize a window */
void rtgui_topwin_resize(struct rtgui_win* wid, rtgui_rect_t* r);
/* get window at (x, y) */
struct rtgui_topwin* rtgui_topwin_get_wnd(int x, int y);
void rtgui_topwin_activate_win(struct rtgui_topwin* win);
void rtgui_topwin_deactivate_win(struct rtgui_topwin* win);
/* window title */
void rtgui_topwin_title_ondraw(struct rtgui_topwin* win);
void rtgui_topwin_title_onmouse(struct rtgui_topwin* win, struct rtgui_event_mouse* event);
/* monitor rect */
void rtgui_topwin_append_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect);
void rtgui_topwin_remove_monitor_rect(struct rtgui_win* wid, rtgui_rect_t* rect);
#endif
/*
* File : box.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/dc.h>
#include <rtgui/widgets/box.h>
static void _rtgui_box_constructor(rtgui_box_t *box)
{
/* init widget and set event handler */
rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_box_event_handler);
RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT;
rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_box_event_handler);
/* set proper of control */
box->orientation = RTGUI_HORIZONTAL;
box->border_size = RTGUI_BORDER_DEFAULT_WIDTH;
}
rtgui_type_t *rtgui_box_type_get(void)
{
static rtgui_type_t *box_type = RT_NULL;
if (!box_type)
{
box_type = rtgui_type_create("box", RTGUI_CONTAINER_TYPE,
sizeof(rtgui_box_t), RTGUI_CONSTRUCTOR(_rtgui_box_constructor), RT_NULL);
}
return box_type;
}
rt_bool_t rtgui_box_event_handler(rtgui_widget_t* widget, rtgui_event_t* event)
{
struct rtgui_box* box = (struct rtgui_box*)widget;
RT_ASSERT(box != RT_NULL);
switch (event->type)
{
case RTGUI_EVENT_RESIZE:
/* re-layout */
rtgui_box_layout(box);
break;
default:
return rtgui_container_event_handler(RTGUI_WIDGET(box), event);
}
return RT_FALSE;
}
struct rtgui_box* rtgui_box_create(int orientation, rtgui_rect_t* rect)
{
struct rtgui_box* box;
box = (struct rtgui_box*) rtgui_widget_create (RTGUI_BOX_TYPE);
if (box != RT_NULL)
{
/* set proper of control */
rtgui_widget_set_rect(RTGUI_WIDGET(box), rect);
box->orientation = orientation;
}
return box;
}
void rtgui_box_append(struct rtgui_box* box, rtgui_widget_t* widget)
{
/* put to box's children list */
rtgui_container_add_child(RTGUI_CONTAINER(box), widget);
}
static void rtgui_box_layout_vertical(rtgui_box_t* box)
{
rtgui_list_t *node;
rt_int32_t box_width;
rt_int32_t space_count;
rt_int32_t next_x, next_y;
rt_int32_t total_height, space_height;
struct rtgui_event_resize size_event;
/* prepare the resize event */
RTGUI_EVENT_RESIZE_INIT(&size_event);
/* find spaces */
space_count = 0;
total_height = 0;
space_height = 0;
rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
{
rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
else total_height += widget->mini_height;
}
/* calculate the height for each spaces */
if (space_count != 0)
{
space_height = (rtgui_rect_height(RTGUI_WIDGET(box)->extent) - total_height - (box->border_size << 1)) / space_count;
}
/* init (x, y) and box width */
next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
box_width = rtgui_rect_width(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
/* layout each widget */
rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
{
rtgui_rect_t *rect;
rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
/* get extent of widget */
rect = &(widget->extent);
/* reset rect */
rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
rect->x2 = widget->mini_width;
rect->y2 = widget->mini_height;
/* left in default */
rtgui_rect_moveto(rect, next_x, next_y);
if (widget->align & RTGUI_ALIGN_EXPAND)
{
/* expand on horizontal */
rect->x2 = rect->x1 + (rt_int16_t)box_width;
}
if (widget->align & RTGUI_ALIGN_CENTER_VERTICAL)
{
/* center */
rt_uint32_t mid;
mid = box_width - rtgui_rect_width(*rect);
mid = mid /2;
rect->x1 = next_x + mid;
rect->x2 = next_x + box_width - mid;
}
else if (widget->align & RTGUI_ALIGN_RIGHT)
{
/* right */
rect->x1 = next_x + box_width - rtgui_rect_width(*rect);
rect->x2 = next_x + box_width;
}
if (widget->align & RTGUI_ALIGN_STRETCH)
{
rect->y2 = rect->y1 + space_height;
}
/* process resize event */
size_event.x = rect->x1;
size_event.y = rect->y1;
size_event.w = rect->x2 - rect->x1;
size_event.h = rect->y2 - rect->y1;
widget->event_handler(widget, &size_event.parent);
/* point to next height */
next_y = rect->y2;
}
}
static void rtgui_box_layout_horizontal(rtgui_box_t* box)
{
rtgui_list_t *node;
rt_int32_t box_height;
rt_int32_t space_count;
rt_int32_t next_x, next_y;
rt_int32_t total_width, space_width;
struct rtgui_event_resize size_event;
/* prepare the resize event */
RTGUI_EVENT_RESIZE_INIT(&size_event);
/* find spaces */
space_count = 0;
total_width = 0;
space_width = 0;
rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
{
rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
if (widget->align & RTGUI_ALIGN_STRETCH) space_count ++;
else total_width += widget->mini_width;
}
if (space_count != 0)
{
/* calculate the height for each spaces */
space_width = (rtgui_rect_width(RTGUI_WIDGET(box)->extent) - total_width) / space_count;
}
/* init (x, y) and box height */
next_x = RTGUI_WIDGET(box)->extent.x1 + box->border_size;
next_y = RTGUI_WIDGET(box)->extent.y1 + box->border_size;
box_height = rtgui_rect_height(RTGUI_WIDGET(box)->extent) - (box->border_size << 1);
/* layout each widget */
rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
{
rtgui_rect_t *rect;
rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
/* get extent of widget */
rect = &(widget->extent);
/* reset rect */
rtgui_rect_moveto(rect, -rect->x1, -rect->y1);
rect->x2 = widget->mini_width;
rect->y2 = widget->mini_height;
/* top in default */
rtgui_rect_moveto(rect, next_x, next_y);
if (widget->align & RTGUI_ALIGN_EXPAND)
{
/* expand on vertical */
rect->y2 = rect->y1 + box_height;
}
if (widget->align & RTGUI_ALIGN_CENTER_HORIZONTAL)
{
/* center */
rt_uint32_t mid;
mid = box_height - rtgui_rect_height(*rect);
mid = mid /2;
rect->y1 = next_y + mid;
rect->y2 = next_y + box_height - mid;
}
else if (widget->align & RTGUI_ALIGN_RIGHT)
{
/* right */
rect->y1 = next_y + box_height - rtgui_rect_height(*rect);
rect->y2 = next_y + box_height;
}
if (widget->align & RTGUI_ALIGN_STRETCH)
{
rect->x2 = rect->x1 + space_width;
}
/* process resize event */
size_event.x = rect->x1;
size_event.y = rect->y1;
size_event.w = rect->x2 - rect->x1;
size_event.h = rect->y2 - rect->y1;
widget->event_handler(widget, &size_event.parent);
/* point to next width */
next_x = rect->x2;
}
}
void rtgui_box_layout(rtgui_box_t* box)
{
RT_ASSERT(box != RT_NULL);
if (box->orientation & RTGUI_VERTICAL)
{
rtgui_box_layout_vertical(box);
}
else
{
rtgui_box_layout_horizontal(box);
}
/* update box and its children clip */
if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box)))
{
rtgui_widget_update_clip(RTGUI_WIDGET(box));
}
}
rt_uint32_t rtgui_box_get_width(rtgui_box_t* box)
{
rtgui_list_t *node;
rt_uint32_t width;
width = 0;
rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
{
rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
rt_uint32_t widget_width;
widget_width = rtgui_rect_width(widget->extent);
if (box->orientation & RTGUI_VERTICAL)
{
/* get the max width */
if (width < widget_width) width = widget_width;
}
else
{
/* get the total width */
width += widget_width;
}
}
return width;
}
rt_uint32_t rtgui_box_get_height(rtgui_box_t* box)
{
rtgui_list_t *node;
rt_uint32_t height;
height = 0;
rtgui_list_foreach(node, &(RTGUI_CONTAINER(box)->children))
{
rtgui_widget_t* widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
rt_uint32_t widget_height;
widget_height = rtgui_rect_height(widget->extent);
if (box->orientation & RTGUI_HORIZONTAL)
{
/* get the max height */
if (height < widget_height) height = widget_height;
}
else
{
/* get the total height */
height += widget_height;
}
}
return height;
}
/*
* File : button.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/dc.h>
#include <rtgui/widgets/button.h>
#include <rtgui/rtgui_theme.h>
static void _rtgui_button_constructor(rtgui_button_t *button)
{
/* init widget and set event handler */
RTGUI_WIDGET(button)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
rtgui_widget_set_event_handler(RTGUI_WIDGET(button), rtgui_button_event_handler);
/* un-press button */
button->flag &= ~RTGUI_BUTTON_FLAG_PRESS;
/* set flag and on_button event handler */
button->pressed_image = RT_NULL;
button->unpressed_image = RT_NULL;
button->on_button = RT_NULL;
/* set gc */
RTGUI_WIDGET_FOREGROUND(RTGUI_WIDGET(button)) = default_foreground;
RTGUI_WIDGET_BACKGROUND(RTGUI_WIDGET(button)) = RTGUI_RGB(212, 208, 200);
RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(button)) = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL;
}
rtgui_type_t *rtgui_button_type_get(void)
{
static rtgui_type_t *button_type = RT_NULL;
if (!button_type)
{
button_type = rtgui_type_create("button", RTGUI_LABEL_TYPE,
sizeof(rtgui_button_t), RTGUI_CONSTRUCTOR(_rtgui_button_constructor), RT_NULL);
}
return button_type;
}
rt_bool_t rtgui_button_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
{
struct rtgui_button* btn;
RT_ASSERT(widget != RT_NULL);
btn = (struct rtgui_button*) widget;
switch (event->type)
{
case RTGUI_EVENT_PAINT:
if (widget->on_draw != RT_NULL ) widget->on_draw(widget, event);
else rtgui_theme_draw_button(btn);
break;
case RTGUI_EVENT_MOUSE_BUTTON:
{
struct rtgui_event_mouse* emouse = (struct rtgui_event_mouse*)event;
if (btn->flag & RTGUI_BUTTON_TYPE_PUSH)
{
/* it's a push button */
if (emouse->button & RTGUI_MOUSE_BUTTON_UP)
{
if (btn->flag & RTGUI_BUTTON_FLAG_PRESS)
btn->flag &= ~RTGUI_BUTTON_FLAG_PRESS;
else
btn->flag |= RTGUI_BUTTON_FLAG_PRESS;
/* draw button */
if (widget->on_draw != RT_NULL ) widget->on_draw(widget, event);
else rtgui_theme_draw_button(btn);
/* invokes call back */
if (widget->on_mouseclick != RT_NULL &&
emouse->button & RTGUI_MOUSE_BUTTON_UP)
return widget->on_mouseclick(widget, event);
}
}
else
{
if (emouse->button & RTGUI_MOUSE_BUTTON_LEFT)
{
/* it's a normal button */
if (emouse->button & RTGUI_MOUSE_BUTTON_DOWN)
{
btn->flag |= RTGUI_BUTTON_FLAG_PRESS;
}
else
{
btn->flag &= ~RTGUI_BUTTON_FLAG_PRESS;
}
/* draw button */
if (widget->on_draw != RT_NULL ) widget->on_draw(widget, event);
else rtgui_theme_draw_button(btn);
/* invokes call back */
if (widget->on_mouseclick != RT_NULL &&
emouse->button & RTGUI_MOUSE_BUTTON_UP)
return widget->on_mouseclick(widget, event);
}
}
return RT_TRUE;
}
}
return RT_FALSE;
}
rtgui_button_t* rtgui_button_create(unsigned char* text)
{
struct rtgui_button* btn;
btn = (struct rtgui_button*) rtgui_widget_create (RTGUI_BUTTON_TYPE);
if (btn != RT_NULL)
{
rtgui_rect_t rect;
/* set default rect */
rtgui_font_get_metrics(rtgui_font_default(), text, &rect);
rect.x2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1);
rect.y2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1);
rtgui_widget_set_rect(RTGUI_WIDGET(btn), &rect);
rtgui_label_set_text(RTGUI_LABEL(btn), text);
}
return btn;
}
rtgui_button_t* rtgui_pushbutton_create(unsigned char* text)
{
rtgui_button_t* btn;
btn = rtgui_button_create(text);
if (btn != RT_NULL) btn->flag |= RTGUI_BUTTON_TYPE_PUSH;
return btn;
}
void rtgui_button_destroy(rtgui_button_t* btn)
{
rtgui_widget_destroy(RTGUI_WIDGET(btn));
}
void rtgui_button_set_pressed_image(rtgui_button_t* btn, rtgui_image_t* image)
{
RT_ASSERT(btn != RT_NULL);
btn->pressed_image = image;
}
void rtgui_button_set_unpressed_image(rtgui_button_t* btn, rtgui_image_t* image)
{
RT_ASSERT(btn != RT_NULL);
btn->unpressed_image = image;
}
/*
* File : container.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/widgets/toplevel.h>
#include <rtgui/widgets/container.h>
static void _rtgui_container_constructor(rtgui_container_t *container)
{
/* set event handler and init field */
rtgui_widget_set_event_handler(RTGUI_WIDGET(container), rtgui_container_event_handler);
rtgui_list_init(&(container->children));
}
static void _rtgui_container_destructor(rtgui_container_t *container)
{
/* destroy children of container */
rtgui_container_destroy_children(container);
}
static void _rtgui_container_update_toplevel(rtgui_container_t* container)
{
struct rtgui_list_node* node;
rtgui_list_foreach(node, &(container->children))
{
rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling);
/* set child toplevel */
child->toplevel = rtgui_widget_get_toplevel(RTGUI_WIDGET(container));
if (RTGUI_IS_CONTAINER(child))
{
_rtgui_container_update_toplevel(RTGUI_CONTAINER(child));
}
}
}
rtgui_type_t *rtgui_container_type_get(void)
{
static rtgui_type_t *container_type = RT_NULL;
if (!container_type)
{
container_type = rtgui_type_create("container", RTGUI_WIDGET_TYPE,
sizeof(rtgui_container_t),
RTGUI_CONSTRUCTOR(_rtgui_container_constructor),
RTGUI_DESTRUCTOR(_rtgui_container_destructor));
}
return container_type;
}
rt_bool_t rtgui_container_dispatch_event(rtgui_container_t *container, rtgui_event_t* event)
{
/* handle in child widget */
struct rtgui_list_node* node;
rtgui_list_foreach(node, &(container->children))
{
struct rtgui_widget* w;
w = rtgui_list_entry(node, struct rtgui_widget, sibling);
if (w->event_handler(w, event) == RT_TRUE) return RT_TRUE;
}
return RT_FALSE;
}
rt_bool_t rtgui_container_dispatch_mouse_event(rtgui_container_t *container, struct rtgui_event_mouse* event)
{
/* handle in child widget */
struct rtgui_list_node* node;
rtgui_list_foreach(node, &(container->children))
{
struct rtgui_widget* w;
w = rtgui_list_entry(node, struct rtgui_widget, sibling);
if (rtgui_rect_contains_point(&(w->extent), event->x, event->y) == RT_EOK)
{
if (w->event_handler(w, (rtgui_event_t*)event) == RT_TRUE) return RT_TRUE;
}
}
return RT_FALSE;
}
rt_bool_t rtgui_container_event_handler(rtgui_widget_t* widget, rtgui_event_t* event)
{
rtgui_container_t *container = RTGUI_CONTAINER(widget);
switch (event->type)
{
case RTGUI_EVENT_PAINT:
if (widget->on_draw != RT_NULL)
{
return widget->on_draw(widget, event);
}
rtgui_container_dispatch_event(container, event);
break;
case RTGUI_EVENT_KBD:
if (widget->on_key != RT_NULL)
{
return widget->on_key(widget, event);
}
else
{
/* let parent to handle keyboard event */
if (widget->parent != RT_NULL && widget->parent != widget->toplevel)
{
return widget->parent->event_handler(widget->parent, event);
}
}
break;
case RTGUI_EVENT_MOUSE_BUTTON:
/* handle in child widget */
if (rtgui_container_dispatch_mouse_event(container,
(struct rtgui_event_mouse*)event) == RT_FALSE)
{
/* handle event in current widget */
if (widget->on_mouseclick != RT_NULL)
{
return widget->on_mouseclick(widget, event);
}
}
else return RT_TRUE;
break;
case RTGUI_EVENT_MOUSE_MOTION:
#if 0
if (rtgui_container_dispatch_mouse_event(container,
(struct rtgui_event_mouse*)event) == RT_FALSE)
{
/* handle event in current widget */
if (widget->on_mousemotion != RT_NULL)
{
return widget->on_mousemotion(widget, event);
}
}
else return RT_TRUE;
#endif
break;
case RTGUI_EVENT_COMMAND:
if (rtgui_container_dispatch_event(container, event) == RT_FALSE)
{
if (widget->on_command != RT_NULL)
{
return widget->on_command(widget, event);
}
}
else return RT_TRUE;
break;
case RTGUI_EVENT_RESIZE:
if (rtgui_container_dispatch_event(container, event) == RT_FALSE)
{
if (widget->on_size != RT_NULL)
return widget->on_size(widget, event);
}
else return RT_TRUE;
break;
default:
/* call parent widget event handler */
return rtgui_widget_event_handler(widget, event);
}
return RT_FALSE;
}
/*
* This function will add a child to a container widget
* Note: this function will not change the widget layout
* the layout is the responsibility of layout widget, such as box.
*/
void rtgui_container_add_child(rtgui_container_t *container, rtgui_widget_t* child)
{
RT_ASSERT(container != RT_NULL);
RT_ASSERT(child != RT_NULL);
/* set parent and toplevel widget */
child->parent = RTGUI_WIDGET(container);
/* put widget to parent's children list */
rtgui_list_append(&(container->children), &(child->sibling));
/* update children toplevel */
if (RTGUI_WIDGET(container)->toplevel != RT_NULL &&
RTGUI_IS_TOPLEVEL(RTGUI_WIDGET(container)->toplevel))
{
child->toplevel = rtgui_widget_get_toplevel(RTGUI_WIDGET(container));
/* update all child toplevel */
if (RTGUI_IS_CONTAINER(child))
{
_rtgui_container_update_toplevel(RTGUI_CONTAINER(child));
}
}
}
/* remove a child to widget */
void rtgui_container_remove_child(rtgui_container_t *container, rtgui_widget_t* child)
{
RT_ASSERT(container != RT_NULL);
RT_ASSERT(child != RT_NULL);
/* remove widget from parent's children list */
rtgui_list_remove(&(container->children), &(child->sibling));
/* set parent and toplevel widget */
child->parent = RT_NULL;
child->toplevel = RT_NULL;
}
/* destroy all children of container */
void rtgui_container_destroy_children(rtgui_container_t *container)
{
struct rtgui_list_node* node;
if (container == RT_NULL) return;
node = container->children.next;
while (node != RT_NULL)
{
rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling);
if (RTGUI_IS_CONTAINER(child))
{
/* destroy children of child */
rtgui_container_destroy_children(RTGUI_CONTAINER(child));
}
/* destroy object and remove from parent */
rtgui_object_destroy(RTGUI_OBJECT(child));
node = container->children.next;
}
container->children.next = RT_NULL;
/* update widget clip */
#if 0
rtgui_widget_update_clip(RTGUI_WIDGET(container));
#else
/* update toplevel widget clip */
#if 0
{
rtgui_toplevel_t* top;
top = RTGUI_TOPLEVEL(RTGUI_WIDGET(container)->toplevel);
if (RTGUI_IS_VIEW(top))
}
#endif
rtgui_toplevel_update_clip(RTGUI_TOPLEVEL(RTGUI_WIDGET(container)->toplevel));
#endif
}
rtgui_widget_t* rtgui_container_get_first_child(rtgui_container_t* container)
{
rtgui_widget_t* child = RT_NULL;
if (container->children.next != RT_NULL)
{
child = rtgui_list_entry(container->children.next, rtgui_widget_t, sibling);
}
return child;
}
/*
* File : iconbox.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/dc.h>
#include <rtgui/widgets/iconbox.h>
#include <rtgui/rtgui_theme.h>
static void _rtgui_iconbox_constructor(rtgui_iconbox_t *iconbox)
{
/* init widget and set event handler */
RTGUI_WIDGET(iconbox)->flag |= RTGUI_WIDGET_FLAG_TRANSPARENT;
rtgui_widget_set_event_handler(RTGUI_WIDGET(iconbox), rtgui_iconbox_event_handler);
/* set proper of control */
iconbox->image = RT_NULL;
iconbox->selected = RT_FALSE;
iconbox->text = RT_NULL;
iconbox->text_position = RTGUI_ICONBOX_TEXT_BELOW;
}
rtgui_type_t *rtgui_iconbox_type_get(void)
{
static rtgui_type_t *iconbox_type = RT_NULL;
if (!iconbox_type)
{
iconbox_type = rtgui_type_create("iconbox", RTGUI_WIDGET_TYPE,
sizeof(rtgui_iconbox_t), RTGUI_CONSTRUCTOR(_rtgui_iconbox_constructor), RT_NULL);
}
return iconbox_type;
}
rt_bool_t rtgui_iconbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
{
struct rtgui_iconbox* iconbox = (struct rtgui_iconbox*)widget;
switch (event->type)
{
case RTGUI_EVENT_PAINT:
if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
else
{
rtgui_theme_draw_iconbox(iconbox);
}
break;
}
return RT_FALSE;
}
struct rtgui_iconbox* rtgui_iconbox_create(struct rtgui_image* image,
const unsigned char* text,
int position)
{
struct rtgui_iconbox* iconbox;
iconbox = (struct rtgui_iconbox*)rtgui_widget_create(RTGUI_ICONBOX_TYPE);
if (iconbox != RT_NULL)
{
rtgui_rect_t rect = {0, 0, 0, 0}, text_rect;
rect.x2 = image->w;
rect.y2 = image->h;
/* get text rect */
rtgui_font_get_metrics(rtgui_font_default(), text, &text_rect);
if (position == RTGUI_ICONBOX_TEXT_BELOW)
{
rect.y2 += RTGUI_WIDGET_DEFAULT_MARGIN;
if (text_rect.x2 > rect.x2)
{
rect.x2 = text_rect.x2;
}
rect.y2 += text_rect.y2;
}
else if (position == RTGUI_ICONBOX_TEXT_RIGHT)
{
rect.x2 += RTGUI_WIDGET_DEFAULT_MARGIN;
if (text_rect.y2 > rect.y2)
{
rect.y2 = text_rect.y2;
}
rect.x2 += text_rect.x2;
}
/* set widget rect */
rtgui_widget_set_rect(RTGUI_WIDGET(iconbox), &rect);
/* set image and text position */
iconbox->image = image;
iconbox->text = (unsigned char*)rt_strdup((const char*)text);
iconbox->text_position = position;
}
return iconbox;
}
void rtgui_iconbox_destroy(struct rtgui_iconbox* iconbox)
{
rtgui_widget_destroy(RTGUI_WIDGET(iconbox));
}
void rtgui_iconbox_set_text_position(struct rtgui_iconbox* iconbox, int position)
{
rtgui_rect_t rect = {0, 0, 0, 0}, text_rect;
RT_ASSERT(iconbox != RT_NULL);
iconbox->text_position = position;
/* set mini width and height */
rect.x2 = iconbox->image->w;
rect.y2 = iconbox->image->h;
/* get text rect */
if (iconbox->text != RT_NULL)
{
rtgui_font_get_metrics(rtgui_font_default(),
iconbox->text, &text_rect);
if (position == RTGUI_ICONBOX_TEXT_BELOW)
{
rect.y2 += RTGUI_WIDGET_DEFAULT_MARGIN;
if (text_rect.x2 > rect.x2)
{
rect.x2 = text_rect.x2;
}
rect.y2 += text_rect.y2;
}
else if (position == RTGUI_ICONBOX_TEXT_RIGHT)
{
rect.x2 += RTGUI_WIDGET_DEFAULT_MARGIN;
if (text_rect.y2 > rect.y2)
{
rect.y2 = text_rect.y2;
}
rect.x2 += text_rect.x2;
}
}
rtgui_widget_set_miniwidth(RTGUI_WIDGET(iconbox), rect.x2);
rtgui_widget_set_miniheight(RTGUI_WIDGET(iconbox), rect.y2);
}
/*
* File : label.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/dc.h>
#include <rtgui/widgets/label.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/rtgui_theme.h>
static void _rtgui_label_constructor(rtgui_label_t *label)
{
/* init widget and set event handler */
rtgui_widget_set_event_handler(RTGUI_WIDGET(label), rtgui_label_event_handler);
/* set field */
label->text = RT_NULL;
}
static void _rtgui_label_destructor(rtgui_label_t *label)
{
/* release text memory */
rtgui_free(label->text);
label->text = RT_NULL;
}
rtgui_type_t *rtgui_label_type_get(void)
{
static rtgui_type_t *label_type = RT_NULL;
if (!label_type)
{
label_type = rtgui_type_create("label", RTGUI_WIDGET_TYPE,
sizeof(rtgui_label_t),
RTGUI_CONSTRUCTOR(_rtgui_label_constructor),
RTGUI_DESTRUCTOR(_rtgui_label_destructor));
}
return label_type;
}
rt_bool_t rtgui_label_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
{
struct rtgui_label* label;
RT_ASSERT(widget != RT_NULL);
label = (struct rtgui_label*) widget;
switch (event->type)
{
case RTGUI_EVENT_PAINT:
rtgui_theme_draw_label(label);
break;
}
return RT_FALSE;
}
rtgui_label_t* rtgui_label_create(const unsigned char* text)
{
struct rtgui_label* label;
label = (struct rtgui_label*) rtgui_widget_create(RTGUI_LABEL_TYPE);
if (label != RT_NULL)
{
rtgui_rect_t rect;
/* set default rect */
rtgui_font_get_metrics(rtgui_font_default(), text, &rect);
rect.x2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1);
rect.y2 += (RTGUI_BORDER_DEFAULT_WIDTH << 1);
rtgui_widget_set_rect(RTGUI_WIDGET(label), &rect);
/* set text */
label->text = (unsigned char*)rt_strdup((const char*)text);
}
return label;
}
void rtgui_label_destroy(rtgui_label_t* label)
{
rtgui_widget_destroy(RTGUI_WIDGET(label));
}
unsigned char* rtgui_label_get_text(rtgui_label_t* label)
{
RT_ASSERT(label != RT_NULL);
return label->text;
}
void rtgui_label_set_text(rtgui_label_t* label, const unsigned char* text)
{
RT_ASSERT(label != RT_NULL);
if (label->text != RT_NULL)
{
/* release old text memory */
rtgui_free(label->text);
}
if (text != RT_NULL) label->text = (unsigned char*)rt_strdup((const char*)text);
else label->text = RT_NULL;
}
/*
* File : textbox.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/dc.h>
#include <rtgui/widgets/textbox.h>
#include <rtgui/rtgui_theme.h>
#define RTGUI_TEXTBOX_LINE_MAX 64
#define RTGUI_TEXTBOX_MARGIN 3
static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kbd* event);
static rt_bool_t rtgui_textbox_onfocus(struct rtgui_widget* widget, struct rtgui_event* event);
static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_widget* widget, struct rtgui_event* event);
static void _rtgui_textbox_constructor(rtgui_textbox_t *box)
{
rtgui_rect_t rect = {0, 0, RTGUI_TEXTBOX_DEFAULT_WIDTH, RTGUI_TEXTBOX_DEFAULT_HEIGHT};
rtgui_widget_set_rect(RTGUI_WIDGET(box), &rect);
RTGUI_WIDGET(box)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
rtgui_widget_set_event_handler(RTGUI_WIDGET(box), rtgui_textbox_event_handler);
rtgui_widget_set_onfocus(RTGUI_WIDGET(box), rtgui_textbox_onfocus);
rtgui_widget_set_onunfocus(RTGUI_WIDGET(box), rtgui_textbox_onunfocus);
/* set default text align */
RTGUI_WIDGET_TEXTALIGN(RTGUI_WIDGET(box)) = RTGUI_ALIGN_CENTER_VERTICAL;
/* set proper of control */
box->caret_x = box->caret_y = 0;
box->caret = rtgui_caret_create(RTGUI_WIDGET(box));
box->line = box->line_begin = box->position = 0;
box->type = RTGUI_TEXTBOX_SINGLE;
/* allocate default line buffer */
box->text = RT_NULL;
rtgui_font_get_metrics(RTGUI_WIDGET(box)->gc.font, "h", &rect);
box->font_width = rtgui_rect_width(rect);
}
static void _rtgui_textbox_deconstructor(rtgui_textbox_t *box)
{
if (box->text != RT_NULL)
{
rtgui_free(box->text);
box->text = RT_NULL;
}
if (box->caret != RT_NULL)
{
rtgui_caret_destroy(box->caret);
box->caret = RT_NULL;
}
}
rtgui_type_t *rtgui_textbox_type_get(void)
{
static rtgui_type_t *textbox_type = RT_NULL;
if (!textbox_type)
{
textbox_type = rtgui_type_create("textbox", RTGUI_WIDGET_TYPE,
sizeof(rtgui_textbox_t),
RTGUI_CONSTRUCTOR(_rtgui_textbox_constructor),
RTGUI_DESTRUCTOR(_rtgui_textbox_deconstructor));
}
return textbox_type;
}
static void rtgui_textbox_onmouse(struct rtgui_textbox* box, struct rtgui_event_mouse* event)
{
rt_size_t length;
RT_ASSERT(box != RT_NULL);
RT_ASSERT(event != RT_NULL);
length = rt_strlen((const char*)box->text);
if (event->button & RTGUI_MOUSE_BUTTON_LEFT &&
event->button & RTGUI_MOUSE_BUTTON_DOWN)
{
rt_int32_t x;
/* set caret position */
x = event->x - RTGUI_WIDGET(box)->extent.x1;
if (x < 0)
{
box->position = 0;
}
else if (x > length * box->font_width)
{
box->position = length;
}
else
{
box->position = x / box->font_width;
}
rtgui_caret_set_point(box->caret, RTGUI_TEXTBOX_MARGIN + box->position * box->font_width, 2);
rtgui_caret_set_box(box->caret, 2, rtgui_rect_height(RTGUI_WIDGET(box)->extent) - 4);
/* set widget focus */
rtgui_widget_focus(RTGUI_WIDGET(box));
}
}
static void rtgui_textbox_onkey(struct rtgui_textbox* box, struct rtgui_event_kbd* event)
{
rt_size_t length;
RT_ASSERT(box != RT_NULL);
RT_ASSERT(event != RT_NULL);
if (event->type != RTGUI_KEYDOWN)
return ;
length = rt_strlen((const char*)box->text);
if (event->key == RTGUIK_DELETE)
{
if (box->position == length - 1)
{
box->text[box->position] = '\0';
}
else
{
unsigned char *c;
/* remove character */
for (c = &box->text[box->position]; c[1] != '\0'; c++)
*c = c[1];
*c = '\0';
}
}
else if (event->key == RTGUIK_BACKSPACE)
{
if (box->position == length - 1)
{
box->text[box->position] = '\0';
box->position --;
}
else if (box->position != 0)
{
/* remove current character */
if (box->position != 0)
{
unsigned char *c;
/* remove character */
for (c = &box->text[box->position - 1]; c[1] != '\0'; c++)
*c = c[1];
*c = '\0';
}
box->position --;
}
}
else if (event->key == RTGUIK_LEFT)
{
if (box->position > 0) box->position --;
}
else if (event->key == RTGUIK_RIGHT)
{
if (box->position < length) box->position ++;
}
else if (event->key == RTGUIK_HOME)
{
box->position = 0;
}
else if (event->key == RTGUIK_END)
{
box->position = length;
}
else if (event->key == RTGUIK_RETURN)
{
if (box->on_enter != RT_NULL)
{
box->on_enter(RTGUI_WIDGET(box), RT_NULL);
}
}
else
{
if (isprint(event->key) || isdigit(event->key))
{
/* no buffer on this line */
if (length + 1 > box->line_length) return;
if (box->position < length - 1)
{
unsigned char* c;
for (c = &box->text[length]; c != &box->text[box->position]; c--)
*c = *(c-1);
box->text[length + 1] = '\0';
}
box->text[box->position] = event->key;
box->position ++;
}
}
/* re-draw text box */
rtgui_theme_draw_textbox(box);
rtgui_caret_set_point(box->caret,
RTGUI_TEXTBOX_MARGIN + box->position * box->font_width , 2);
rtgui_caret_set_box(box->caret, 2, rtgui_rect_height(RTGUI_WIDGET(box)->extent) - 4);
}
static rt_bool_t rtgui_textbox_onfocus(struct rtgui_widget* widget, struct rtgui_event* event)
{
struct rtgui_textbox* box = (struct rtgui_textbox*)widget;
/* show caret */
rtgui_caret_show(box->caret, box->caret_x, box->caret_y);
return RT_TRUE;
}
static rt_bool_t rtgui_textbox_onunfocus(struct rtgui_widget* widget, struct rtgui_event* event)
{
struct rtgui_textbox* box = (struct rtgui_textbox*)widget;
/* hide caret */
rtgui_caret_hide(box->caret);
return RT_TRUE;
}
rt_bool_t rtgui_textbox_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
{
struct rtgui_textbox* box = (struct rtgui_textbox*)widget;
switch (event->type)
{
case RTGUI_EVENT_PAINT:
if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
else rtgui_theme_draw_textbox(box);
break;
case RTGUI_EVENT_MOUSE_BUTTON:
if (widget->on_mouseclick != RT_NULL) widget->on_mouseclick(widget, event);
else rtgui_textbox_onmouse(box, (struct rtgui_event_mouse*)event);
return RT_TRUE;
case RTGUI_EVENT_KBD:
if (widget->on_key != RT_NULL) widget->on_key(widget, event);
else rtgui_textbox_onkey(box, (struct rtgui_event_kbd*)event);
return RT_TRUE;
}
return RT_FALSE;
}
struct rtgui_textbox* rtgui_textbox_create(const char* text)
{
struct rtgui_textbox* box;
box = (struct rtgui_textbox*) rtgui_widget_create (RTGUI_TEXTBOX_TYPE);
if (box != RT_NULL)
{
rtgui_rect_t rect = {0, 0, RTGUI_TEXTBOX_DEFAULT_WIDTH, RTGUI_TEXTBOX_DEFAULT_HEIGHT};
/* allocate default line buffer */
rtgui_textbox_set_value(box, text);
rtgui_font_get_metrics(RTGUI_WIDGET(box)->gc.font, "h", &rect);
box->font_width = rtgui_rect_width(rect);
}
return box;
}
void rtgui_textbox_destroy(struct rtgui_textbox* box)
{
rtgui_widget_destroy(RTGUI_WIDGET(box));
}
void rtgui_textbox_set_value(struct rtgui_textbox* box, const char* text)
{
if (box->text != RT_NULL)
{
if (box->line_length > rt_strlen(text) + 1)
{
rt_memcpy(box->text, text, rt_strlen(text) + 1);
return;
}
else
{
/* free the old text */
rtgui_free(box->text);
box->text = RT_NULL;
}
}
box->line_length = RTGUI_TEXTBOX_LINE_MAX > rt_strlen(text) + 1 ?
RTGUI_TEXTBOX_LINE_MAX : rt_strlen(text) + 1;
/* allocate line buffer */
box->text = rtgui_malloc(box->line_length);
rt_memset(box->text, 0, box->line_length);
/* copy text */
rt_memcpy(box->text, text, rt_strlen(text) + 1);
/* set current position */
box->position = 0;
}
const char* rtgui_textbox_get_value(struct rtgui_textbox* box)
{
return (const char*)box->text;
}
void rtgui_widget_set_line_length(struct rtgui_textbox* box, rt_size_t length)
{
rt_uint8_t* new_line;
RT_ASSERT(box != RT_NULL);
/* invalid length */
if (length <= 0) return;
new_line = rtgui_malloc(length);
if (length < box->line_length)
{
rt_memcpy(new_line, box->text, length - 1);
new_line[length] = '\0';
}
else
{
rt_memcpy(new_line, (const char*)box->text, rt_strlen((const char*)box->text));
}
/* set line length */
box->line_length = length;
}
/*
* File : title.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/widgets/title.h>
#include <rtgui/rtgui_system.h>
/* there is no event handler in wintitle but handle the event on topwin of server */
static void _rtgui_wintitle_constructor(rtgui_wintitle_t* wintitle)
{
wintitle->title = RT_NULL;
RTGUI_WIDGET(wintitle)->flag = RTGUI_WIDGET_FLAG_DEFAULT;
}
rtgui_type_t* rtgui_wintitle_type_get()
{
static rtgui_type_t *wintitle_type = RT_NULL;
if (!wintitle_type)
{
wintitle_type = rtgui_type_create("wintitle", RTGUI_TOPLEVEL_TYPE,
sizeof(rtgui_wintitle_t), RTGUI_CONSTRUCTOR(_rtgui_wintitle_constructor), RT_NULL);
}
return wintitle_type;
}
rtgui_wintitle_t* rtgui_wintitle_create(const rt_uint8_t* title)
{
rtgui_wintitle_t* wintitle;
wintitle = (rtgui_wintitle_t*)rtgui_widget_create(RTGUI_WINTITLE_TYPE);
if (wintitle != RT_NULL)
{
rtgui_wintitle_set_title(wintitle, title);
}
return wintitle;
}
void rtgui_wintitle_destroy(rtgui_wintitle_t* wintitle)
{
rtgui_widget_destroy(RTGUI_WIDGET(wintitle));
}
void rtgui_wintitle_set_title(rtgui_wintitle_t* wintitle, const rt_uint8_t* title)
{
RT_ASSERT(wintitle != RT_NULL);
if (wintitle->title != RT_NULL)
{
rtgui_free(wintitle->title);
}
if (title != RT_NULL) wintitle->title = (unsigned char*)rt_strdup((const char*)title);
else wintitle->title = RT_NULL;
}
rt_uint8_t *rtgui_wintitle_get_title(rtgui_wintitle_t* wintitle)
{
RT_ASSERT(wintitle != RT_NULL);
return wintitle->title;
}
/*
* File : toplevel.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/toplevel.h>
static void _rtgui_toplevel_constructor(rtgui_toplevel_t *toplevel)
{
/* set event handler */
rtgui_widget_set_event_handler(RTGUI_WIDGET(toplevel), rtgui_toplevel_event_handler);
/* set toplevel to self */
RTGUI_WIDGET(toplevel)->toplevel = RTGUI_WIDGET(toplevel);
/* init toplevel property */
toplevel->drawing = 0;
toplevel->external_clip_rect = RT_NULL;
toplevel->external_clip_size = 0;
toplevel->focus = RT_NULL;
/* hide toplevel default */
RTGUI_WIDGET_HIDE(RTGUI_WIDGET(toplevel));
/* set server as RT_NULL (no connected) */
toplevel->server = RT_NULL;
}
static void _rtgui_toplevel_destructor(rtgui_toplevel_t* toplevel)
{
/* release external clip info */
rtgui_free(toplevel->external_clip_rect);
toplevel->drawing = 0;
toplevel->external_clip_rect = RT_NULL;
toplevel->external_clip_size = 0;
toplevel->focus = RT_NULL;
}
rtgui_type_t *rtgui_toplevel_type_get(void)
{
static rtgui_type_t *toplevel_type = RT_NULL;
if (!toplevel_type)
{
toplevel_type = rtgui_type_create("toplevel", RTGUI_CONTAINER_TYPE,
sizeof(rtgui_toplevel_t),
RTGUI_CONSTRUCTOR(_rtgui_toplevel_constructor),
RTGUI_DESTRUCTOR(_rtgui_toplevel_destructor));
}
return toplevel_type;
}
rt_bool_t rtgui_toplevel_event_handler(rtgui_widget_t* widget, rtgui_event_t* event)
{
rtgui_toplevel_t* toplevel = (rtgui_toplevel_t*)widget;
switch (event->type)
{
case RTGUI_EVENT_KBD:
if (toplevel->focus != RT_NULL)
{
toplevel->focus->event_handler(toplevel->focus, event);
}
break;
case RTGUI_EVENT_CLIP_INFO:
/* set toplevel external clip info */
rtgui_toplevel_handle_clip(toplevel, (struct rtgui_event_clip_info*)event);
/* update toplevel clip */
rtgui_toplevel_update_clip(toplevel);
break;
case RTGUI_EVENT_TIMER:
{
struct rtgui_event_timer* etimer = (struct rtgui_event_timer*) event;
if (etimer->callback != RT_NULL)
{
/* call timeout function */
etimer->callback(RT_NULL, etimer->parameter);
}
}
break;
case RTGUI_EVENT_COMMAND:
if (rtgui_container_dispatch_event(RTGUI_CONTAINER(widget), event) != RT_TRUE)
{
if (widget->on_command != RT_NULL)
{
widget->on_command(widget, event);
}
}
break;
default :
return rtgui_container_event_handler(widget, event);
}
return RT_FALSE;
}
void rtgui_toplevel_handle_clip(struct rtgui_toplevel* top,
struct rtgui_event_clip_info* info)
{
RT_ASSERT(top != RT_NULL);
RT_ASSERT(info != RT_NULL);
/* release old rect array */
if (top->external_clip_size != 0)
{
rtgui_free(top->external_clip_rect);
top->external_clip_rect = RT_NULL;
top->external_clip_size = 0;
}
/* no rect info */
if (info->num_rect == 0) return;
top->external_clip_rect = (rtgui_rect_t*) rtgui_malloc(sizeof(rtgui_rect_t) *
info->num_rect);
top->external_clip_size = info->num_rect;
/* copy rect array */
rt_memcpy(top->external_clip_rect, info->rects, sizeof(rtgui_rect_t) * info->num_rect);
}
#include <rtgui/driver.h> /* to get screen rect */
void rtgui_toplevel_update_clip(rtgui_toplevel_t* top)
{
rt_uint32_t idx;
rtgui_container_t* container;
struct rtgui_list_node* node;
rtgui_rect_t screen_rect;
if (top == RT_NULL) return;
/* reset toplevel widget clip to extent */
rtgui_region_reset(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->extent));
RTGUI_WIDGET(top)->clip_sync ++;
/* subtract the screen rect */
screen_rect.x1 = screen_rect.y1 = 0;
screen_rect.x2 = rtgui_graphic_driver_get_default()->width;
screen_rect.y2 = rtgui_graphic_driver_get_default()->height;
rtgui_region_intersect_rect(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->clip),
&screen_rect);
/* subtract the external rect */
for (idx = 0; idx < top->external_clip_size; idx ++)
{
rtgui_region_subtract_rect(&(RTGUI_WIDGET(top)->clip), &(RTGUI_WIDGET(top)->clip),
&(top->external_clip_rect[idx]));
}
/* update the clip info of each child */
container = RTGUI_CONTAINER(top);
rtgui_list_foreach(node, &(container->children))
{
rtgui_widget_t* child = rtgui_list_entry(node, rtgui_widget_t, sibling);
rtgui_widget_update_clip(child);
}
}
void rtgui_toplevel_set_focus(struct rtgui_toplevel* top, rtgui_widget_t* focus)
{
RT_ASSERT(top != RT_NULL);
top->focus = focus;
}
rtgui_widget_t* rtgui_toplevel_get_focus(struct rtgui_toplevel* top)
{
RT_ASSERT(top != RT_NULL);
return top->focus;
}
/*
* File : view.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#include <rtgui/dc.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/view.h>
#include <rtgui/widgets/workbench.h>
static void _rtgui_view_constructor(rtgui_view_t *view)
{
/* init view */
rtgui_widget_set_event_handler(RTGUI_WIDGET(view),
rtgui_view_event_handler);
view->title = RT_NULL;
}
rtgui_type_t *rtgui_view_type_get(void)
{
static rtgui_type_t *view_type = RT_NULL;
if (!view_type)
{
view_type = rtgui_type_create("view", RTGUI_CONTAINER_TYPE,
sizeof(rtgui_view_t), RTGUI_CONSTRUCTOR(_rtgui_view_constructor), RT_NULL);
}
return view_type;
}
rt_bool_t rtgui_view_event_handler(struct rtgui_widget* widget, struct rtgui_event* event)
{
struct rtgui_view* view = (struct rtgui_view*) widget;
RT_ASSERT(widget != RT_NULL);
switch (event->type)
{
case RTGUI_EVENT_PAINT:
if (widget->on_draw != RT_NULL) widget->on_draw(widget, event);
else
{
struct rtgui_dc* dc;
struct rtgui_rect rect;
dc = rtgui_dc_begin_drawing(widget);
if (dc == RT_NULL) return RT_FALSE;
rtgui_widget_get_rect(widget, &rect);
/* fill view with background */
rtgui_dc_fill_rect(dc, &rect);
/* paint on each child */
rtgui_container_dispatch_event(RTGUI_CONTAINER(view), event);
rtgui_dc_end_drawing(dc);
}
break;
default:
return rtgui_container_event_handler(widget, event);
}
return RT_FALSE;
}
rtgui_view_t* rtgui_view_create(const char* title)
{
struct rtgui_view* view;
/* allocate view */
view = (struct rtgui_view*) rtgui_widget_create (RTGUI_VIEW_TYPE);
if (view != RT_NULL)
{
if (title != RT_NULL)
view->title = rt_strdup(title);
}
return view;
}
void rtgui_view_destroy(rtgui_view_t* view)
{
rtgui_widget_destroy(RTGUI_WIDGET(view));
}
void rtgui_view_set_box(rtgui_view_t* view, rtgui_box_t* box)
{
if (view == RT_NULL ||
box == RT_NULL) return;
rtgui_container_add_child(RTGUI_CONTAINER(view), RTGUI_WIDGET(box));
rtgui_widget_set_rect(RTGUI_WIDGET(box), &(RTGUI_WIDGET(view)->extent));
}
void rtgui_view_show(rtgui_view_t* view)
{
if (view == RT_NULL) return;
if (RTGUI_WIDGET(view)->parent == RT_NULL)
{
RTGUI_WIDGET_UNHIDE(RTGUI_WIDGET(view));
return;
}
rtgui_workbench_show_view((rtgui_workbench_t*)(RTGUI_WIDGET(view)->parent), view);
}
void rtgui_view_hide(rtgui_view_t* view)
{
if (view == RT_NULL) return;
if (RTGUI_WIDGET(view)->parent == RT_NULL)
{
RTGUI_WIDGET_HIDE(RTGUI_WIDGET(view));
return;
}
rtgui_workbench_hide_view((rtgui_workbench_t*)(RTGUI_WIDGET(view)->parent), view);
}
char* rtgui_view_get_title(rtgui_view_t* view)
{
RT_ASSERT(view != RT_NULL);
return view->title;
}
void rtgui_view_set_title(rtgui_view_t* view, const char *title)
{
RT_ASSERT(view != RT_NULL);
if (view->title != RT_NULL)
{
rtgui_free(view->title);
if (title != RT_NULL) view->title = rt_strdup(title);
else view->title = RT_NULL;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册