[GUI Engine] Add RTGUI as a GUI Engine

This commit is contained in:
Bernard Xiong 2016-02-08 09:59:48 +08:00
parent 55bbe7290e
commit 490196b1b9
78 changed files with 63249 additions and 0 deletions

52
components/gui/SConscript Normal file
View File

@ -0,0 +1,52 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Split('''
src/asc12font.c
src/asc16font.c
src/blit.c
src/box.c
src/color.c
src/container.c
src/dc.c
src/dc_blend.c
src/dc_buffer.c
src/dc_client.c
src/dc_hw.c
src/dc_rotozoom.c
src/dc_trans.c
src/filerw.c
src/font.c
src/font_bmp.c
src/font_fnt.c
src/font_freetype.c
src/font_hz_bmp.c
src/font_hz_file.c
src/hz12font.c
src/hz16font.c
src/image.c
src/image_bmp.c
src/image_hdc.c
src/image_jpg.c
src/image_png.c
src/image_xpm.c
src/matrix.c
src/mouse.c
src/region.c
src/rtgui_app.c
src/rtgui_driver.c
src/rtgui_object.c
src/rtgui_system.c
src/server.c
src/title.c
src/topwin.c
src/widget.c
src/window.c
''')
CPPPATH = [cwd + '/include']
group = DefineGroup('GUIEngine', src, depend = ['RT_USING_GUIENGINE'], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,222 @@
/*
* File : blit.h
* This file is part of RT-Thread GUI
* COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2013-10-04 Bernard porting SDL software render to RT-Thread GUI
*/
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __RTGUI_BLIT_H__
#define __RTGUI_BLIT_H__
#include <rtgui/rtgui.h>
/* Assemble R-G-B values into a specified pixel format and store them */
#define RGB565_FROM_RGB(Pixel, r, g, b) \
{ \
Pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3); \
}
#define BGR565_FROM_RGB(Pixel, r, g, b) \
{ \
Pixel = ((b>>3)<<11)|((g>>2)<<5)|(r>>3); \
}
#define RGB555_FROM_RGB(Pixel, r, g, b) \
{ \
Pixel = ((r>>3)<<10)|((g>>3)<<5)|(b>>3); \
}
#define RGB888_FROM_RGB(Pixel, r, g, b) \
{ \
Pixel = (r<<16)|(g<<8)|b; \
}
#define ARGB8888_FROM_RGBA(Pixel, r, g, b, a) \
{ \
Pixel = (a<<24)|(r<<16)|(g<<8)|b; \
}
#define RGBA8888_FROM_RGBA(Pixel, r, g, b, a) \
{ \
Pixel = (r<<24)|(g<<16)|(b<<8)|a; \
}
#define ABGR8888_FROM_RGBA(Pixel, r, g, b, a) \
{ \
Pixel = (a<<24)|(b<<16)|(g<<8)|r; \
}
#define BGRA8888_FROM_RGBA(Pixel, r, g, b, a) \
{ \
Pixel = (b<<24)|(g<<16)|(r<<8)|a; \
}
#define ARGB2101010_FROM_RGBA(Pixel, r, g, b, a) \
{ \
r = r ? ((r << 2) | 0x3) : 0; \
g = g ? ((g << 2) | 0x3) : 0; \
b = b ? ((b << 2) | 0x3) : 0; \
a = (a * 3) / 255; \
Pixel = (a<<30)|(r<<20)|(g<<10)|b; \
}
/* Load pixel of the specified format from a buffer and get its R-G-B values */
#define RGB_FROM_RGB565(Pixel, r, g, b) \
{ \
r = rtgui_blit_expand_byte[3][((Pixel&0xF800)>>11)]; \
g = rtgui_blit_expand_byte[2][((Pixel&0x07E0)>>5)]; \
b = rtgui_blit_expand_byte[3][(Pixel&0x001F)]; \
}
#define RGB_FROM_BGR565(Pixel, r, g, b) \
{ \
b = rtgui_blit_expand_byte[3][((Pixel&0xF800)>>11)]; \
g = rtgui_blit_expand_byte[2][((Pixel&0x07E0)>>5)]; \
r = rtgui_blit_expand_byte[3][(Pixel&0x001F)]; \
}
#define RGB_FROM_RGB555(Pixel, r, g, b) \
{ \
r = rtgui_blit_expand_byte[3][((Pixel&0x7C00)>>10)]; \
g = rtgui_blit_expand_byte[3][((Pixel&0x03E0)>>5)]; \
b = rtgui_blit_expand_byte[3][(Pixel&0x001F)]; \
}
#define RGB_FROM_RGB888(Pixel, r, g, b) \
{ \
r = ((Pixel&0xFF0000)>>16); \
g = ((Pixel&0xFF00)>>8); \
b = (Pixel&0xFF); \
}
#define RGBA_FROM_RGBA8888(Pixel, r, g, b, a) \
{ \
r = (Pixel>>24); \
g = ((Pixel>>16)&0xFF); \
b = ((Pixel>>8)&0xFF); \
a = (Pixel&0xFF); \
}
#define RGBA_FROM_ARGB8888(Pixel, r, g, b, a) \
{ \
r = ((Pixel>>16)&0xFF); \
g = ((Pixel>>8)&0xFF); \
b = (Pixel&0xFF); \
a = (Pixel>>24); \
}
#define RGBA_FROM_ABGR8888(Pixel, r, g, b, a) \
{ \
r = (Pixel&0xFF); \
g = ((Pixel>>8)&0xFF); \
b = ((Pixel>>16)&0xFF); \
a = (Pixel>>24); \
}
#define RGBA_FROM_BGRA8888(Pixel, r, g, b, a) \
{ \
r = ((Pixel>>8)&0xFF); \
g = ((Pixel>>16)&0xFF); \
b = (Pixel>>24); \
a = (Pixel&0xFF); \
}
#define RGBA_FROM_ARGB2101010(Pixel, r, g, b, a) \
{ \
r = ((Pixel>>22)&0xFF); \
g = ((Pixel>>12)&0xFF); \
b = ((Pixel>>2)&0xFF); \
a = rtgui_blit_expand_byte[6][(Pixel>>30)]; \
}
/* 4-times unrolled loop */
#define DUFFS_LOOP4(pixel_copy_increment, width) \
{ int n = (width+3)/4; \
switch (width & 3) { \
case 0: do { pixel_copy_increment; \
case 3: pixel_copy_increment; \
case 2: pixel_copy_increment; \
case 1: pixel_copy_increment; \
} while (--n > 0); \
} \
}
/* 8-times unrolled loop */
#define DUFFS_LOOP8(pixel_copy_increment, width) \
{ int n = (width+7)/8; \
switch (width & 7) { \
case 0: do { pixel_copy_increment; \
case 7: pixel_copy_increment; \
case 6: pixel_copy_increment; \
case 5: pixel_copy_increment; \
case 4: pixel_copy_increment; \
case 3: pixel_copy_increment; \
case 2: pixel_copy_increment; \
case 1: pixel_copy_increment; \
} while ( --n > 0 ); \
} \
}
/* Use the 8-times version of the loop by default */
#define DUFFS_LOOP(pixel_copy_increment, width) \
DUFFS_LOOP8(pixel_copy_increment, width)
struct rtgui_blit_info
{
rt_uint8_t *src;
int src_w, src_h;
int src_pitch;
int src_skip;
rt_uint8_t *dst;
int dst_w, dst_h;
int dst_pitch;
int dst_skip;
rt_uint8_t src_fmt;
rt_uint8_t dst_fmt;
rt_uint8_t r, g, b, a;
};
struct rtgui_blit_info_src
{
rt_uint8_t *src;
int src_w, src_h;
int src_skip;
rt_uint8_t src_fmt;
};
extern const rt_uint8_t* rtgui_blit_expand_byte[9];
typedef void (*rtgui_blit_line_func)(rt_uint8_t *dst, rt_uint8_t *src, int line);
rtgui_blit_line_func rtgui_blit_line_get(int dst_bpp, int src_bpp);
rtgui_blit_line_func rtgui_blit_line_get_inv(int dst_bpp, int src_bpp);
void rtgui_blit(struct rtgui_blit_info * info);
#endif

View File

@ -0,0 +1,178 @@
/*
* 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
* 2012-01-24 onelife add mono color support
*/
#ifndef __RTGUI_COLOR_H__
#define __RTGUI_COLOR_H__
#include <rtgui/rtgui.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* The color used in the GUI:
*
* bit bit
* RGB565 15 R,G,B 0
* BGR565 15 B,G,R 0
* RGB888 23 R,G,B 0
* ARGB888 31 A,R,G,B 0
* RGBA888 31 R,G,B,A 0
* ABGR888 31 A,B,G,R 0
*
* The rtgui_color is defined as ARGB888.
* bit31 A,R,G,B bit0
*/
#define RTGUI_ARGB(a, r, g, b) \
((rtgui_color_t)(((rt_uint8_t)(b)|\
(((unsigned long)(rt_uint8_t)(g))<<8))|\
(((unsigned long)(rt_uint8_t)(r))<<16)|\
(((unsigned long)(rt_uint8_t)(a))<<24)))
#define RTGUI_RGB(r, g, b) RTGUI_ARGB(255, (r), (g), (b))
#define RTGUI_RGB_B(c) ((c) & 0xff)
#define RTGUI_RGB_G(c) (((c) >> 8) & 0xff)
#define RTGUI_RGB_R(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;
/* it's better use these color definitions */
#define RED RTGUI_RGB(0xff, 0x00, 0x00)
#define GREEN RTGUI_RGB(0x00, 0xff, 0x00)
#define BLUE RTGUI_RGB(0x00, 0x00, 0xff)
#define BLACK RTGUI_RGB(0x00, 0x00, 0x00)
#define WHITE RTGUI_RGB(0xff, 0xff, 0xff)
#define HIGH_LIGHT RTGUI_RGB(0xfc, 0xfc, 0xfc)
#define DARK_GREY RTGUI_RGB(0x7f, 0x7f, 0x7f)
#define LIGHT_GREY RTGUI_RGB(0xc0, 0xc0, 0xc0)
#define TRANSPARENT RTGUI_ARGB(0, 0, 0, 0)
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: ARGB
* AAAA AAAA RRRR RRRR GGGG GGGG BBBB BBBB
* 31 0
*/
/* convert rtgui color to mono */
rt_inline rt_uint8_t rtgui_color_to_mono(rtgui_color_t c)
{
rt_uint8_t pixel;
pixel = (RTGUI_RGB_R(c) | RTGUI_RGB_G(c) | RTGUI_RGB_B(c)) ? 0x01 : 0x00;
return pixel;
}
rt_inline rtgui_color_t rtgui_color_from_mono(rt_uint8_t pixel)
{
rtgui_color_t color;
if (pixel)
{
color = white;
}
else
{
color = black;
}
return color;
}
/* convert rtgui color to RRRRRGGGGGGBBBBB */
rt_inline rt_uint16_t rtgui_color_to_565(rtgui_color_t c)
{
rt_uint16_t pixel;
pixel = (rt_uint16_t)(((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_565(rt_uint16_t pixel)
{
rt_uint16_t r, g, b;
rtgui_color_t color;
r = (pixel >> 11) & 0x1f;
g = (pixel >> 5) & 0x3f;
b = pixel & 0x1f;
color = b * 255 / 31 + ((g * 255 / 63) << 8) + ((r * 255 / 31) << 16);
return color;
}
/* convert rtgui color to BBBBBGGGGGGRRRRR */
rt_inline rt_uint16_t rtgui_color_to_565p(rtgui_color_t c)
{
rt_uint16_t pixel;
pixel = (rt_uint16_t)(((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_565p(rt_uint16_t pixel)
{
rt_uint8_t r, g, b;
rtgui_color_t color;
r = pixel & 0x1f;
g = (pixel >> 5) & 0x3f;
b = (pixel >> 11) & 0x1f;
color = b * 255 / 31 + ((g * 255 / 63) << 8) + ((r * 255 / 31) << 16);
return color;
}
/* convert rtgui color to RGB */
rt_inline rt_uint32_t rtgui_color_to_888(rtgui_color_t c)
{
rt_uint32_t pixel;
pixel = RTGUI_RGB_R(c) << 16 | RTGUI_RGB_G(c) << 8 | RTGUI_RGB_B(c);
return pixel;
}
rt_inline rtgui_color_t rtgui_color_from_888(rt_uint32_t pixel)
{
rtgui_color_t color;
color = RTGUI_RGB(((pixel >> 16) & 0xff), ((pixel >> 8) & 0xff), pixel & 0xff);
return color;
}
/* get the bits of specified pixle format */
rt_uint8_t rtgui_color_get_bits(rt_uint8_t pixel_format) RTGUI_PURE;
/* get the bytes of specified pixle format */
rt_uint8_t rtgui_color_get_bpp(rt_uint8_t pixel_format) RTGUI_PURE;
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,267 @@
/*
* 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__
#ifdef __cplusplus
extern "C" {
#endif
#include <rtgui/rtgui.h>
#include <rtgui/font.h>
#include <rtgui/driver.h>
#include <rtgui/widgets/widget.h>
#define RTGUI_DC(dc) ((struct rtgui_dc*)(dc))
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
enum rtgui_dc_type
{
RTGUI_DC_HW,
RTGUI_DC_CLIENT,
RTGUI_DC_BUFFER,
};
struct rtgui_dc_engine
{
/* interface */
void (*draw_point)(struct rtgui_dc *dc, int x, int y);
void (*draw_color_point)(struct rtgui_dc *dc, int x, int y, rtgui_color_t color);
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_line)(struct rtgui_dc *dc, int x1, int x2, int y, rt_uint8_t *line_data);
void (*blit)(struct rtgui_dc *dc, struct rtgui_point *dc_point, struct rtgui_dc *dest, rtgui_rect_t *rect);
rt_bool_t (*fini)(struct rtgui_dc *dc);
};
/*
* The abstract device context
*
* Normally, a DC is a drawable canvas, user can draw point/line/cycle etc
* on the DC.
*
* There are several kinds of DC:
* - Hardware DC;
* - Client DC;
* - Buffer DC;
*/
struct rtgui_dc
{
/* type of device context */
rt_uint32_t type;
/* dc engine */
const struct rtgui_dc_engine *engine;
};
/*
* The hardware device context
*
* The hardware DC is a context based on hardware device, for examle the
* LCD device. The operations on the hardware DC are reflected to the real
* hardware.
*
*/
struct rtgui_dc_hw
{
struct rtgui_dc parent;
rtgui_widget_t *owner;
const struct rtgui_graphic_driver *hw_driver;
};
/**
* The buffer dc is a device context with memory buffer.
*
* All the operations on this device context is reflected to the memory buffer.
*/
struct rtgui_dc_buffer
{
struct rtgui_dc parent;
/* graphic context */
rtgui_gc_t gc;
/* pixel format */
rt_uint8_t pixel_format;
rt_uint8_t blend_mode; /* RTGUI_BLENDMODE: None/Blend/Add/Mod */
/* width and height */
rt_uint16_t width, height;
/* pitch */
rt_uint16_t pitch;
/* pixel data */
rt_uint8_t *pixel;
};
#define RTGUI_DC_FC(dc) (rtgui_dc_get_gc(RTGUI_DC(dc))->foreground)
#define RTGUI_DC_BC(dc) (rtgui_dc_get_gc(RTGUI_DC(dc))->background)
#define RTGUI_DC_FONT(dc) (rtgui_dc_get_gc(RTGUI_DC(dc))->font)
#define RTGUI_DC_TEXTALIGN(dc) (rtgui_dc_get_gc(RTGUI_DC(dc))->textalign)
/* create a buffer dc */
struct rtgui_dc *rtgui_dc_buffer_create(int width, int height);
struct rtgui_dc *rtgui_dc_buffer_create_pixformat(rt_uint8_t pixel_format, int w, int h);
struct rtgui_dc *rtgui_dc_buffer_create_from_dc(struct rtgui_dc* dc);
/* create a widget dc */
struct rtgui_dc *rtgui_dc_widget_create(struct rtgui_widget * owner);
/* begin and end a drawing */
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);
rt_uint8_t *rtgui_dc_buffer_get_pixel(struct rtgui_dc *dc);
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_fill_rect_forecolor(struct rtgui_dc *dc, struct rtgui_rect *rect);
void rtgui_dc_draw_round_rect(struct rtgui_dc *dc, struct rtgui_rect *rect, int r);
void rtgui_dc_fill_round_rect(struct rtgui_dc *dc, struct rtgui_rect *rect, int r);
/** Fill a vertical gradient rect from @c1 to @c2 */
void rtgui_dc_fill_gradient_rectv(struct rtgui_dc *dc, rtgui_rect_t *rect,
rtgui_color_t c1, rtgui_color_t c2);
void rtgui_dc_draw_annulus(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r1, rt_int16_t r2, rt_int16_t start, rt_int16_t end);
void rtgui_dc_draw_pie(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_fill_pie(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_text(struct rtgui_dc *dc, const char *text, struct rtgui_rect *rect);
void rtgui_dc_draw_text_stroke(struct rtgui_dc *dc, const char *text, struct rtgui_rect *rect,
rtgui_color_t color_stroke, rtgui_color_t color_core);
void rtgui_dc_draw_mono_bmp(struct rtgui_dc *dc, int x, int y, int w, int h, const rt_uint8_t *data);
void rtgui_dc_draw_byte(struct rtgui_dc *dc, int x, int y, int h, const rt_uint8_t *data);
void rtgui_dc_draw_word(struct rtgui_dc *dc, int x, int y, int h, const rt_uint8_t *data);
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_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);
/* alpha blending functions */
void rtgui_dc_draw_aa_line(struct rtgui_dc * dst,int x1,int y1,int x2,int y2);
void rtgui_dc_draw_aa_lines(struct rtgui_dc * dst,const struct rtgui_point * points,int count);
void rtgui_dc_blend_point(struct rtgui_dc * dst,int x,int y,enum RTGUI_BLENDMODE blendMode,rt_uint8_t r,rt_uint8_t g,rt_uint8_t b,rt_uint8_t a);
void rtgui_dc_blend_points(struct rtgui_dc * dst,const rtgui_point_t * points,int count,enum RTGUI_BLENDMODE blendMode,rt_uint8_t r,rt_uint8_t g,rt_uint8_t b,rt_uint8_t a);
void rtgui_dc_blend_line(struct rtgui_dc * dst,int x1,int y1,int x2,int y2,enum RTGUI_BLENDMODE blendMode,rtgui_color_t color);
void rtgui_dc_blend_lines(struct rtgui_dc * dst,const rtgui_point_t * points,int count,enum RTGUI_BLENDMODE blendMode,rtgui_color_t color);
void rtgui_dc_blend_fill_rect(struct rtgui_dc * dst,const rtgui_rect_t * rect,enum RTGUI_BLENDMODE blendMode,rtgui_color_t color);
void rtgui_dc_blend_fill_rects(struct rtgui_dc * dst,const rtgui_rect_t * rects,int count,enum RTGUI_BLENDMODE blendMode,rtgui_color_t color);
void rtgui_dc_draw_aa_circle(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t r);
void rtgui_dc_draw_aa_ellipse(struct rtgui_dc *dc, rt_int16_t x, rt_int16_t y, rt_int16_t rx, rt_int16_t ry);
int rtgui_dc_draw_thick_line(struct rtgui_dc * dst, rt_int16_t x1, rt_int16_t y1, rt_int16_t x2, rt_int16_t y2, rt_uint8_t width);
/*
* dc inline function
*
* Note:
* In order to improve drawing speed, put most of common function of dc to inline
*/
/*
* draw a point on dc
*/
rt_inline void rtgui_dc_draw_point(struct rtgui_dc *dc, int x, int y)
{
dc->engine->draw_point(dc, x, y);
}
/*
* draw a color point on dc
*/
rt_inline void rtgui_dc_draw_color_point(struct rtgui_dc *dc, int x, int y, rtgui_color_t color)
{
dc->engine->draw_color_point(dc, x, y, color);
}
/*
* draw a vertical line on dc
*/
rt_inline void rtgui_dc_draw_vline(struct rtgui_dc *dc, int x, int y1, int y2)
{
dc->engine->draw_vline(dc, x, y1, y2);
}
/*
* draw a horizontal line on dc
*/
rt_inline void rtgui_dc_draw_hline(struct rtgui_dc *dc, int x1, int x2, int y)
{
dc->engine->draw_hline(dc, x1, x2, y);
}
/*
* fill a rect with background color
*/
rt_inline void rtgui_dc_fill_rect(struct rtgui_dc *dc, struct rtgui_rect *rect)
{
dc->engine->fill_rect(dc, rect);
}
/*
* blit a dc (x, y) on another dc(rect)
*/
rt_inline void rtgui_dc_blit(struct rtgui_dc *dc, struct rtgui_point *dc_point, struct rtgui_dc *dest, rtgui_rect_t *rect)
{
dc->engine->blit(dc, dc_point, dest, rect);
}
/* set gc of dc */
void rtgui_dc_set_gc(struct rtgui_dc *dc, rtgui_gc_t *gc);
/* get gc of dc */
rtgui_gc_t *rtgui_dc_get_gc(struct rtgui_dc *dc);
/* get visible status of dc */
rt_bool_t rtgui_dc_get_visible(struct rtgui_dc *dc);
/* get rect of dc */
void rtgui_dc_get_rect(struct rtgui_dc *dc, rtgui_rect_t *rect);
/* get pixel format */
rt_uint8_t rtgui_dc_get_pixel_format(struct rtgui_dc *dc);
/* coordinate conversion */
void rtgui_dc_logic_to_device(struct rtgui_dc* dc, struct rtgui_point *point);
void rtgui_dc_rect_to_device(struct rtgui_dc* dc, struct rtgui_rect* rect);
/* dc rotation and zoom operations */
struct rtgui_dc *rtgui_dc_shrink(struct rtgui_dc *dc, int factorx, int factory);
struct rtgui_dc *rtgui_dc_zoom(struct rtgui_dc *dc, double zoomx, double zoomy, int smooth);
struct rtgui_dc *rtgui_dc_rotozoom(struct rtgui_dc *dc, double angle, double zoomx, double zoomy, int smooth);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,27 @@
/*
* File : dc_buffer.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2010, 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
* 2010-04-10 Bernard first version
* 2010-06-14 Bernard embedded hardware dc to each widget
* 2010-08-09 Bernard rename hardware dc to client dc
*/
#ifndef __RTGUI_DC_CLIENT_H__
#define __RTGUI_DC_CLIENT_H__
#include <rtgui/dc.h>
/* create a hardware dc */
struct rtgui_dc *rtgui_dc_client_create(rtgui_widget_t *owner);
void rtgui_dc_client_init(rtgui_widget_t *owner);
#endif

View File

@ -0,0 +1,551 @@
/*
* File : dc_blend.c
* This file is part of RT-Thread GUI
* COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2013-10-04 Bernard porting SDL software render to RT-Thread GUI
*/
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __DC_DRAW_H__
#define __DC_DRAW_H__
#include <rtgui/blit.h>
/* This code assumes that r, g, b, a are the source color,
* and in the blend and add case, the RGB values are premultiplied by a.
*/
#define DRAW_MUL(_a, _b) (((unsigned)(_a)*(_b))/256)
#define DRAW_FASTSETPIXEL(type) \
*pixel = (type) color
#define DRAW_FASTSETPIXEL1 DRAW_FASTSETPIXEL(rt_uint8_t)
#define DRAW_FASTSETPIXEL2 DRAW_FASTSETPIXEL(rt_uint16_t)
#define DRAW_FASTSETPIXEL4 DRAW_FASTSETPIXEL(rt_uint32_t)
#define DRAW_FASTSETPIXELXY(x, y, type, bpp, color) \
*(type *)(_dc_get_pixel(dst, x, y))= (type) color
#define DRAW_FASTSETPIXELXY1(x, y) DRAW_FASTSETPIXELXY(x, y, rt_uint8_t, 1, color)
#define DRAW_FASTSETPIXELXY2(x, y) DRAW_FASTSETPIXELXY(x, y, rt_uint16_t, 2, color)
#define DRAW_FASTSETPIXELXY4(x, y) DRAW_FASTSETPIXELXY(x, y, rt_uint32_t, 4, color)
#define DRAW_SETPIXEL(setpixel) \
do { \
unsigned sr = r, sg = g, sb = b, sa = a; (void) sa; \
setpixel; \
} while (0)
#define DRAW_SETPIXEL_BLEND(getpixel, setpixel) \
do { \
unsigned sr, sg, sb, sa; (void) sa; \
getpixel; \
sr = DRAW_MUL(inva, sr) + r; \
sg = DRAW_MUL(inva, sg) + g; \
sb = DRAW_MUL(inva, sb) + b; \
setpixel; \
} while (0)
#define DRAW_SETPIXEL_ADD(getpixel, setpixel) \
do { \
unsigned sr, sg, sb, sa; (void) sa; \
getpixel; \
sr += r; if (sr > 0xff) sr = 0xff; \
sg += g; if (sg > 0xff) sg = 0xff; \
sb += b; if (sb > 0xff) sb = 0xff; \
setpixel; \
} while (0)
#define DRAW_SETPIXEL_MOD(getpixel, setpixel) \
do { \
unsigned sr, sg, sb, sa; (void) sa; \
getpixel; \
sr = DRAW_MUL(sr, r); \
sg = DRAW_MUL(sg, g); \
sb = DRAW_MUL(sb, b); \
setpixel; \
} while (0)
#define DRAW_SETPIXELXY(x, y, type, bpp, op) \
do { \
type *pixel = (type *)(_dc_get_pixel(dst, x, y));\
op; \
} while (0)
/*
* Define draw operators for RGB555
*/
#define DRAW_SETPIXEL_RGB555 \
DRAW_SETPIXEL(RGB555_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_BLEND_RGB555 \
DRAW_SETPIXEL_BLEND(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
RGB555_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_ADD_RGB555 \
DRAW_SETPIXEL_ADD(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
RGB555_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_MOD_RGB555 \
DRAW_SETPIXEL_MOD(RGB_FROM_RGB555(*pixel, sr, sg, sb), \
RGB555_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXELXY_RGB555(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_RGB555)
#define DRAW_SETPIXELXY_BLEND_RGB555(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_BLEND_RGB555)
#define DRAW_SETPIXELXY_ADD_RGB555(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_ADD_RGB555)
#define DRAW_SETPIXELXY_MOD_RGB555(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_MOD_RGB555)
/*
* Define draw operators for RGB565
*/
#define DRAW_SETPIXEL_RGB565 \
DRAW_SETPIXEL(RGB565_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_BLEND_RGB565 \
DRAW_SETPIXEL_BLEND(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
RGB565_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_ADD_RGB565 \
DRAW_SETPIXEL_ADD(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
RGB565_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_MOD_RGB565 \
DRAW_SETPIXEL_MOD(RGB_FROM_RGB565(*pixel, sr, sg, sb), \
RGB565_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXELXY_RGB565(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_RGB565)
#define DRAW_SETPIXELXY_BLEND_RGB565(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_BLEND_RGB565)
#define DRAW_SETPIXELXY_ADD_RGB565(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_ADD_RGB565)
#define DRAW_SETPIXELXY_MOD_RGB565(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_MOD_RGB565)
/*
* Define draw operators for BGR565
*/
#define DRAW_SETPIXEL_BGR565 \
DRAW_SETPIXEL(BGR565_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_BLEND_BGR565 \
DRAW_SETPIXEL_BLEND(RGB_FROM_BGR565(*pixel, sr, sg, sb), \
BGR565_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_ADD_BGR565 \
DRAW_SETPIXEL_ADD(RGB_FROM_BGR565(*pixel, sr, sg, sb), \
BGR565_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_MOD_BGR565 \
DRAW_SETPIXEL_MOD(RGB_FROM_BGR565(*pixel, sr, sg, sb), \
BGR565_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXELXY_BGR565(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_BGR565)
#define DRAW_SETPIXELXY_BLEND_BGR565(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_BLEND_BGR565)
#define DRAW_SETPIXELXY_ADD_BGR565(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_ADD_BGR565)
#define DRAW_SETPIXELXY_MOD_BGR565(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint16_t, 2, DRAW_SETPIXEL_MOD_BGR565)
/*
* Define draw operators for RGB888
*/
#define DRAW_SETPIXEL_RGB888 \
DRAW_SETPIXEL(RGB888_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_BLEND_RGB888 \
DRAW_SETPIXEL_BLEND(RGB_FROM_RGB888(*pixel, sr, sg, sb), \
RGB888_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_ADD_RGB888 \
DRAW_SETPIXEL_ADD(RGB_FROM_RGB888(*pixel, sr, sg, sb), \
RGB888_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXEL_MOD_RGB888 \
DRAW_SETPIXEL_MOD(RGB_FROM_RGB888(*pixel, sr, sg, sb), \
RGB888_FROM_RGB(*pixel, sr, sg, sb))
#define DRAW_SETPIXELXY_RGB888(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint32_t, 4, DRAW_SETPIXEL_RGB888)
#define DRAW_SETPIXELXY_BLEND_RGB888(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint32_t, 4, DRAW_SETPIXEL_BLEND_RGB888)
#define DRAW_SETPIXELXY_ADD_RGB888(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint32_t, 4, DRAW_SETPIXEL_ADD_RGB888)
#define DRAW_SETPIXELXY_MOD_RGB888(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint32_t, 4, DRAW_SETPIXEL_MOD_RGB888)
/*
* Define draw operators for ARGB8888
*/
#define DRAW_SETPIXEL_ARGB8888 \
DRAW_SETPIXEL(ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
#define DRAW_SETPIXEL_BLEND_ARGB8888 \
DRAW_SETPIXEL_BLEND(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
#define DRAW_SETPIXEL_ADD_ARGB8888 \
DRAW_SETPIXEL_ADD(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
#define DRAW_SETPIXEL_MOD_ARGB8888 \
DRAW_SETPIXEL_MOD(RGBA_FROM_ARGB8888(*pixel, sr, sg, sb, sa), \
ARGB8888_FROM_RGBA(*pixel, sr, sg, sb, sa))
#define DRAW_SETPIXELXY_ARGB8888(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint32_t, 4, DRAW_SETPIXEL_ARGB8888)
#define DRAW_SETPIXELXY_BLEND_ARGB8888(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint32_t, 4, DRAW_SETPIXEL_BLEND_ARGB8888)
#define DRAW_SETPIXELXY_ADD_ARGB8888(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint32_t, 4, DRAW_SETPIXEL_ADD_ARGB8888)
#define DRAW_SETPIXELXY_MOD_ARGB8888(x, y) \
DRAW_SETPIXELXY(x, y, rt_uint32_t, 4, DRAW_SETPIXEL_MOD_ARGB8888)
/*
* Define line drawing macro
*/
#define ABS(_x) ((_x) < 0 ? -(_x) : (_x))
/* Horizontal line */
#define HLINE(type, op, draw_end) \
{ \
int length; \
type *pixel; \
if (x1 <= x2) { \
pixel = (type *)_dc_get_pixel(dst, x1, y1); \
length = draw_end ? (x2-x1+1) : (x2-x1); \
} else { \
pixel = (type *)_dc_get_pixel(dst, x2, y1); \
if (!draw_end) { \
++pixel; \
} \
length = draw_end ? (x1-x2+1) : (x1-x2); \
} \
while (length--) { \
op; \
++pixel; \
} \
}
/* Vertical line */
#define VLINE(type, op, draw_end) \
{ \
int length; \
int pitch = _dc_get_pitch(dst)/(_UI_BITBYTES(_dc_get_bits_per_pixel(dst))); \
type *pixel; \
if (y1 <= y2) { \
pixel = (type *)_dc_get_pixel(dst, x1, y1); \
length = draw_end ? (y2-y1+1) : (y2-y1); \
} else { \
pixel = (type *)_dc_get_pixel(dst, x1, y2); \
if (!draw_end) { \
pixel += pitch; \
} \
length = draw_end ? (y1-y2+1) : (y1-y2); \
} \
while (length--) { \
op; \
pixel += pitch; \
} \
}
/* Diagonal line */
#define DLINE(type, op, draw_end) \
{ \
int length; \
int pitch = _dc_get_pitch(dst)/(_UI_BITBYTES(_dc_get_bits_per_pixel(dst))); \
type *pixel; \
if (y1 <= y2) { \
pixel = (type *)_dc_get_pixel(dst, x1, y1); \
if (x1 <= x2) { \
++pitch; \
} else { \
--pitch; \
} \
length = (y2-y1); \
} else { \
pixel = (type *)_dc_get_pixel(dst, x2, y2); \
if (x2 <= x1) { \
++pitch; \
} else { \
--pitch; \
} \
if (!draw_end) { \
pixel += pitch; \
} \
length = (y1-y2); \
} \
if (draw_end) { \
++length; \
} \
while (length--) { \
op; \
pixel += pitch; \
} \
}
/* Bresenham's line algorithm */
#define BLINE(x1, y1, x2, y2, op, draw_end) \
{ \
int i, deltax, deltay, numpixels; \
int d, dinc1, dinc2; \
int x, xinc1, xinc2; \
int y, yinc1, yinc2; \
\
deltax = ABS(x2 - x1); \
deltay = ABS(y2 - y1); \
\
if (deltax >= deltay) { \
numpixels = deltax + 1; \
d = (2 * deltay) - deltax; \
dinc1 = deltay * 2; \
dinc2 = (deltay - deltax) * 2; \
xinc1 = 1; \
xinc2 = 1; \
yinc1 = 0; \
yinc2 = 1; \
} else { \
numpixels = deltay + 1; \
d = (2 * deltax) - deltay; \
dinc1 = deltax * 2; \
dinc2 = (deltax - deltay) * 2; \
xinc1 = 0; \
xinc2 = 1; \
yinc1 = 1; \
yinc2 = 1; \
} \
\
if (x1 > x2) { \
xinc1 = -xinc1; \
xinc2 = -xinc2; \
} \
if (y1 > y2) { \
yinc1 = -yinc1; \
yinc2 = -yinc2; \
} \
\
x = x1; \
y = y1; \
\
if (!draw_end) { \
--numpixels; \
} \
for (i = 0; i < numpixels; ++i) { \
op(x, y); \
if (d < 0) { \
d += dinc1; \
x += xinc1; \
y += yinc1; \
} else { \
d += dinc2; \
x += xinc2; \
y += yinc2; \
} \
} \
}
/* Xiaolin Wu's line algorithm, based on Michael Abrash's implementation */
#define WULINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
{ \
rt_uint16_t ErrorAdj, ErrorAcc; \
rt_uint16_t ErrorAccTemp, Weighting; \
int DeltaX, DeltaY, Temp, XDir; \
unsigned r, g, b, a, inva; \
\
/* remove compiling warning */ \
r = 0; g = 0; b = 0; a = 0; \
inva = 0; inva = inva; \
/* Draw the initial pixel, which is always exactly intersected by \
the line and so needs no weighting */ \
opaque_op(x1, y1); \
\
/* Draw the final pixel, which is always exactly intersected by the line \
and so needs no weighting */ \
if (draw_end) { \
opaque_op(x2, y2); \
} \
\
/* Make sure the line runs top to bottom */ \
if (y1 > y2) { \
Temp = y1; y1 = y2; y2 = Temp; \
Temp = x1; x1 = x2; x2 = Temp; \
} \
DeltaY = y2 - y1; \
\
if ((DeltaX = x2 - x1) >= 0) { \
XDir = 1; \
} else { \
XDir = -1; \
DeltaX = -DeltaX; /* make DeltaX positive */ \
} \
\
/* line is not horizontal, diagonal, or vertical */ \
ErrorAcc = 0; /* initialize the line error accumulator to 0 */ \
\
/* Is this an X-major or Y-major line? */ \
if (DeltaY > DeltaX) { \
/* Y-major line; calculate 16-bit fixed-point fractional part of a \
pixel that X advances each time Y advances 1 pixel, truncating the \
result so that we won't overrun the endpoint along the X axis */ \
ErrorAdj = ((unsigned long) DeltaX << 16) / (unsigned long) DeltaY; \
/* Draw all pixels other than the first and last */ \
while (--DeltaY) { \
ErrorAccTemp = ErrorAcc; /* remember current accumulated error */ \
ErrorAcc += ErrorAdj; /* calculate error for next pixel */ \
if (ErrorAcc <= ErrorAccTemp) { \
/* The error accumulator turned over, so advance the X coord */ \
x1 += XDir; \
} \
y1++; /* Y-major, so always advance Y */ \
/* The IntensityBits most significant bits of ErrorAcc give us the \
intensity weighting for this pixel, and the complement of the \
weighting for the paired pixel */ \
Weighting = ErrorAcc >> 8; \
{ \
a = DRAW_MUL(_a, (Weighting ^ 255)); \
r = DRAW_MUL(_r, a); \
g = DRAW_MUL(_g, a); \
b = DRAW_MUL(_b, a); \
inva = (a ^ 0xFF); \
blend_op(x1, y1); \
} \
{ \
a = DRAW_MUL(_a, Weighting); \
r = DRAW_MUL(_r, a); \
g = DRAW_MUL(_g, a); \
b = DRAW_MUL(_b, a); \
inva = (a ^ 0xFF); \
blend_op(x1 + XDir, y1); \
} \
} \
} 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 to avoid overrunning the endpoint along the X axis */ \
ErrorAdj = ((unsigned long) DeltaY << 16) / (unsigned long) DeltaX; \
/* Draw all pixels other than the first and last */ \
while (--DeltaX) { \
ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ \
ErrorAcc += ErrorAdj; /* calculate error for next pixel */ \
if (ErrorAcc <= ErrorAccTemp) { \
/* The error accumulator turned over, so advance the Y coord */ \
y1++; \
} \
x1 += XDir; /* X-major, so always advance X */ \
/* The IntensityBits most significant bits of ErrorAcc give us the \
intensity weighting for this pixel, and the complement of the \
weighting for the paired pixel */ \
Weighting = ErrorAcc >> 8; \
{ \
a = DRAW_MUL(_a, (Weighting ^ 255)); \
r = DRAW_MUL(_r, a); \
g = DRAW_MUL(_g, a); \
b = DRAW_MUL(_b, a); \
inva = (a ^ 0xFF); \
blend_op(x1, y1); \
} \
{ \
a = DRAW_MUL(_a, Weighting); \
r = DRAW_MUL(_r, a); \
g = DRAW_MUL(_g, a); \
b = DRAW_MUL(_b, a); \
inva = (a ^ 0xFF); \
blend_op(x1, y1 + 1); \
} \
} \
} \
}
#define AALINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end) \
WULINE(x1, y1, x2, y2, opaque_op, blend_op, draw_end)
/*
* Define fill rect macro
*/
#define FILLRECT(type, op) \
do { \
int width = rect->x2 - rect->x1; \
int height = rect->y2 - rect->y1; \
int pitch = _dc_get_pitch(dst)/(_UI_BITBYTES(_dc_get_bits_per_pixel(dst))); \
int skip = pitch - width; \
type *pixel = (type *)_dc_get_pixel(dst, rect->x1, rect->y1); \
while (height--) { \
{ int n = (width+3)/4; \
switch (width & 3) { \
case 0: do { op; pixel++; \
case 3: op; pixel++; \
case 2: op; pixel++; \
case 1: op; pixel++; \
} while ( --n > 0 ); \
} \
} \
pixel += skip; \
} \
} while (0)
#endif

View File

@ -0,0 +1,24 @@
/*
* File : dc_buffer.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2010, 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
* 2010-04-10 Bernard first version
* 2010-06-14 Bernard embedded hardware dc to each widget
*/
#ifndef __RTGUI_DC_HW_H__
#define __RTGUI_DC_HW_H__
#include <rtgui/dc.h>
/* create a hardware dc */
struct rtgui_dc *rtgui_dc_hw_create(rtgui_widget_t *owner);
#endif

View File

@ -0,0 +1,40 @@
#ifndef __RTGUI_DC_TRANS_H__
#define __RTGUI_DC_TRANS_H__
#include <rtgui/dc.h>
#include <rtgui/matrix.h>
struct rtgui_dc_trans;
/** Create a dc translator on the dc @owner
*
* @return RT_NULL is there is no memory.
*/
struct rtgui_dc_trans* rtgui_dc_trans_create(struct rtgui_dc *owner);
/** Rotate the dc clockwise.
*
* @param degree the degree to rotate.
*/
void rtgui_dc_trans_rotate(struct rtgui_dc_trans *dct, double degree);
void rtgui_dc_trans_set_aa(struct rtgui_dc_trans *dct, int use_aa);
void rtgui_dc_trans_scale(struct rtgui_dc_trans *dct, double sx, double sy);
/** Move the dc
*
* The unit of @dx and @dy is pixel.
*/
void rtgui_dc_trans_move(struct rtgui_dc_trans *dct, int dx, int dy);
void rtgui_dc_trans_get_new_wh(struct rtgui_dc_trans *dct, int *new_w, int *new_h);
void rtgui_dc_trans_blit(struct rtgui_dc_trans *dct,
struct rtgui_point *dc_point,
struct rtgui_dc *dest,
struct rtgui_rect *rect);
void rtgui_dc_trans_destroy(struct rtgui_dc_trans *dct);
#endif

View File

@ -0,0 +1,107 @@
/*
* File : driver.h
* This file is part of RTGUI in 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-04 Bernard first version
*/
#ifndef __RTGUI_DRIVER_H__
#define __RTGUI_DRIVER_H__
#include <rtgui/list.h>
#include <rtgui/color.h>
/* graphic driver operations */
struct rtgui_graphic_driver_ops
{
/* set and get pixel in (x, y) */
void (*set_pixel)(rtgui_color_t *c, int x, int y);
void (*get_pixel)(rtgui_color_t *c, int x, int y);
void (*draw_hline)(rtgui_color_t *c, int x1, int x2, int y);
void (*draw_vline)(rtgui_color_t *c, int x , int y1, int y2);
/* draw raw hline */
void (*draw_raw_hline)(rt_uint8_t *pixels, int x1, int x2, int y);
};
/* graphic extension operations */
struct rtgui_graphic_ext_ops
{
/* some 2D operations */
void (*draw_line)(rtgui_color_t *c, int x1, int y1, int x2, int y2);
void (*draw_rect)(rtgui_color_t *c, int x1, int y1, int x2, int y2);
void (*fill_rect)(rtgui_color_t *c, int x1, int y1, int x2, int y2);
void (*draw_circle)(rtgui_color_t *c, int x, int y, int r);
void (*fill_circle)(rtgui_color_t *c, int x, int y, int r);
void (*draw_ellipse)(rtgui_color_t *c, int x, int y, int rx, int ry);
void (*fill_ellipse)(rtgui_color_t *c, int x, int y, int rx, int ry);
};
struct rtgui_graphic_driver
{
/* pixel format and byte per pixel */
rt_uint8_t pixel_format;
rt_uint8_t bits_per_pixel;
rt_uint16_t pitch;
/* screen width and height */
rt_uint16_t width;
rt_uint16_t height;
/* framebuffer address and ops */
rt_uint8_t *framebuffer;
struct rt_device* device;
const struct rtgui_graphic_driver_ops *ops;
const struct rtgui_graphic_ext_ops *ext_ops;
};
struct rtgui_graphic_driver *rtgui_graphic_driver_get_default(void);
void rtgui_graphic_driver_get_rect(const struct rtgui_graphic_driver *driver, rtgui_rect_t *rect);
void rtgui_graphic_driver_screen_update(const struct rtgui_graphic_driver *driver, rtgui_rect_t *rect);
rt_uint8_t *rtgui_graphic_driver_get_framebuffer(const struct rtgui_graphic_driver *driver);
rt_err_t rtgui_graphic_set_device(rt_device_t device);
void rtgui_graphic_driver_set_framebuffer(void *fb);
rt_inline struct rtgui_graphic_driver *rtgui_graphic_get_device()
{
return rtgui_graphic_driver_get_default();
}
#ifdef RTGUI_USING_HW_CURSOR
/*
* hardware cursor
*/
enum rtgui_cursor_type
{
RTGUI_CURSOR_ARROW,
RTGUI_CURSOR_HAND,
};
void rtgui_cursor_set_device(const char* device_name);
void rtgui_cursor_set_position(rt_uint16_t x, rt_uint16_t y);
void rtgui_cursor_set_image(enum rtgui_cursor_type type);
#endif
#ifdef RTGUI_USING_VFRAMEBUFFER
void rtgui_graphic_driver_vmode_enter(void);
void rtgui_graphic_driver_vmode_exit(void);
struct rtgui_dc* rtgui_graphic_driver_get_rect_buffer(const struct rtgui_graphic_driver *driver, struct rtgui_rect *rect);
#endif
rt_bool_t rtgui_graphic_driver_is_vmode(void);
#endif

View File

@ -0,0 +1,554 @@
/*
* File : event.h
* This file is part of RTGUI in 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-04 Bernard first version
*/
#ifndef __RTGUI_EVENT_H__
#define __RTGUI_EVENT_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <rtdevice.h>
#include <rtgui/rtgui.h>
#include <rtgui/kbddef.h>
/* NOTE: if you create a new event type, remember to add it into the union
* rtgui_event_generic */
enum _rtgui_event_type
{
/* applications event */
RTGUI_EVENT_APP_CREATE, /* create an application */
RTGUI_EVENT_APP_DESTROY, /* destroy an application */
RTGUI_EVENT_APP_ACTIVATE, /* activate an application */
/* window event */
RTGUI_EVENT_WIN_CREATE, /* create a window */
RTGUI_EVENT_WIN_DESTROY, /* destroy a window */
RTGUI_EVENT_WIN_SHOW, /* show a window */
RTGUI_EVENT_WIN_HIDE, /* hide a window */
RTGUI_EVENT_WIN_ACTIVATE, /* activate a window */
RTGUI_EVENT_WIN_DEACTIVATE, /* deactivate a window */
RTGUI_EVENT_WIN_CLOSE, /* close a window */
RTGUI_EVENT_WIN_MOVE, /* move a window */
RTGUI_EVENT_WIN_RESIZE, /* resize a window */
RTGUI_EVENT_WIN_MODAL_ENTER, /* the window is entering modal mode.
This event should be sent after the
window got setup and before the
application got setup. */
/* WM event */
RTGUI_EVENT_SET_WM, /* set window manager */
RTGUI_EVENT_UPDATE_BEGIN, /* update a rect */
RTGUI_EVENT_UPDATE_END, /* update a rect */
RTGUI_EVENT_MONITOR_ADD, /* add a monitor rect */
RTGUI_EVENT_MONITOR_REMOVE, /* remove a monitor rect */
RTGUI_EVENT_SHOW, /* the widget is going to be shown */
RTGUI_EVENT_HIDE, /* the widget is going to be hidden */
RTGUI_EVENT_PAINT, /* paint on screen */
RTGUI_EVENT_TIMER, /* timer */
RTGUI_EVENT_UPDATE_TOPLVL, /* update the toplevel */
/* virtual paint event */
RTGUI_EVENT_VPAINT_REQ, /* virtual paint request (server -> client) */
/* clip rect information */
RTGUI_EVENT_CLIP_INFO, /* clip rect info */
/* mouse and keyboard event */
RTGUI_EVENT_MOUSE_MOTION, /* mouse motion */
RTGUI_EVENT_MOUSE_BUTTON, /* mouse button info */
RTGUI_EVENT_KBD, /* keyboard info */
RTGUI_EVENT_TOUCH, /* touch event to server */
RTGUI_EVENT_GESTURE, /* gesture event */
/* widget event */
RTGUI_EVENT_FOCUSED, /* widget focused */
RTGUI_EVENT_SCROLLED, /* scroll bar scrolled */
RTGUI_EVENT_RESIZE, /* widget resize */
RTGUI_EVENT_SELECTED, /* widget selected */
RTGUI_EVENT_UNSELECTED, /* widget un-selected */
RTGUI_EVENT_MV_MODEL, /* data of a model has been changed */
WBUS_NOTIFY_EVENT,
/* user command event. It should always be the last command type. */
RTGUI_EVENT_COMMAND = 0x0100, /* user command */
};
typedef enum _rtgui_event_type rtgui_event_type;
enum
{
RTGUI_STATUS_OK = 0, /* status ok */
RTGUI_STATUS_ERROR, /* generic error */
RTGUI_STATUS_NRC, /* no resource */
};
struct rtgui_event
{
/* the event type */
enum _rtgui_event_type type;
/* user field of event */
rt_uint16_t user;
/* the event sender */
struct rtgui_app *sender;
/* mailbox to acknowledge request */
rt_mailbox_t ack;
};
typedef struct rtgui_event rtgui_event_t;
#define RTGUI_EVENT(e) ((struct rtgui_event*)(e))
extern struct rtgui_app* rtgui_app_self(void);
#define RTGUI_EVENT_INIT(e, t) do \
{ \
(e)->type = (t); \
(e)->user = 0; \
(e)->sender = rtgui_app_self(); \
(e)->ack = RT_NULL; \
} while (0)
/*
* RTGUI Application Event
*/
struct rtgui_event_application
{
struct rtgui_event parent;
struct rtgui_app *app;
};
/* gui application init */
#define RTGUI_EVENT_APP_CREATE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_APP_CREATE)
#define RTGUI_EVENT_APP_DESTROY_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_APP_DESTROY)
#define RTGUI_EVENT_APP_ACTIVATE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_APP_ACTIVATE)
/*
* RTGUI Window Event
*/
#define _RTGUI_EVENT_WIN_ELEMENTS \
struct rtgui_event parent; \
struct rtgui_win *wid;
/*
* RTGUI Window Event
*/
struct rtgui_event_win
{
_RTGUI_EVENT_WIN_ELEMENTS
};
struct rtgui_event_win_create
{
_RTGUI_EVENT_WIN_ELEMENTS
struct rtgui_win *parent_window;
};
struct rtgui_event_win_move
{
_RTGUI_EVENT_WIN_ELEMENTS
rt_int16_t x, y;
};
struct rtgui_event_win_resize
{
_RTGUI_EVENT_WIN_ELEMENTS
rtgui_rect_t rect;
};
#define rtgui_event_win_destroy rtgui_event_win
#define rtgui_event_win_show rtgui_event_win
#define rtgui_event_win_hide rtgui_event_win
#define rtgui_event_win_activate rtgui_event_win
#define rtgui_event_win_deactivate rtgui_event_win
#define rtgui_event_win_close rtgui_event_win
#define rtgui_event_win_modal_enter rtgui_event_win
/* window event init */
#define RTGUI_EVENT_WIN_CREATE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_CREATE)
#define RTGUI_EVENT_WIN_DESTROY_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_DESTROY)
#define RTGUI_EVENT_WIN_SHOW_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_SHOW)
#define RTGUI_EVENT_WIN_HIDE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_HIDE)
#define RTGUI_EVENT_WIN_ACTIVATE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_ACTIVATE)
#define RTGUI_EVENT_WIN_DEACTIVATE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_DEACTIVATE)
#define RTGUI_EVENT_WIN_CLOSE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_CLOSE)
#define RTGUI_EVENT_WIN_MOVE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_MOVE)
#define RTGUI_EVENT_WIN_RESIZE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_RESIZE)
#define RTGUI_EVENT_WIN_MODAL_ENTER_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_WIN_MODAL_ENTER)
/*
* RTGUI set window manager
*/
struct rtgui_event_set_wm
{
struct rtgui_event parent;
struct rtgui_app *app;
};
#define RTGUI_EVENT_SET_WM_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_SET_WM);
/*
* RTGUI Other Event
*/
struct rtgui_event_update_begin
{
struct rtgui_event parent;
/* the update rect */
rtgui_rect_t rect;
};
struct rtgui_event_update_end
{
struct rtgui_event parent;
/* the update rect */
rtgui_rect_t rect;
};
struct rtgui_event_monitor
{
_RTGUI_EVENT_WIN_ELEMENTS
/* the monitor rect */
rtgui_rect_t rect;
};
struct rtgui_event_paint
{
_RTGUI_EVENT_WIN_ELEMENTS
rtgui_rect_t rect; /* rect to be updated */
};
struct rtgui_timer;
struct rtgui_event_timer
{
struct rtgui_event parent;
struct rtgui_timer *timer;
};
typedef struct rtgui_event_timer rtgui_event_timer_t;
struct rtgui_event_clip_info
{
_RTGUI_EVENT_WIN_ELEMENTS
/* the number of rects */
//rt_uint32_t num_rect;
/* rtgui_rect_t *rects */
};
#define RTGUI_EVENT_GET_RECT(e, i) &(((rtgui_rect_t*)(e + 1))[i])
#define RTGUI_EVENT_UPDATE_BEGIN_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_UPDATE_BEGIN)
#define RTGUI_EVENT_UPDATE_END_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_UPDATE_END)
#define RTGUI_EVENT_MONITOR_ADD_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_MONITOR_ADD)
#define RTGUI_EVENT_MONITOR_REMOVE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_MONITOR_REMOVE)
#define RTGUI_EVENT_CLIP_INFO_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_CLIP_INFO)
#define RTGUI_EVENT_PAINT_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_PAINT)
#define RTGUI_EVENT_TIMER_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_TIMER)
#define rtgui_event_show rtgui_event
#define rtgui_event_hide rtgui_event
#define RTGUI_EVENT_SHOW_INIT(e) RTGUI_EVENT_INIT((e), RTGUI_EVENT_SHOW)
#define RTGUI_EVENT_HIDE_INIT(e) RTGUI_EVENT_INIT((e), RTGUI_EVENT_HIDE)
struct rtgui_event_update_toplvl
{
struct rtgui_event parent;
struct rtgui_win *toplvl;
};
#define RTGUI_EVENT_UPDATE_TOPLVL_INIT(e) \
do { \
RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_UPDATE_TOPLVL); \
(e)->toplvl = RT_NULL; \
} while (0)
struct rtgui_event_vpaint_req
{
_RTGUI_EVENT_WIN_ELEMENTS
struct rtgui_event_vpaint_req *sender;
struct rt_completion *cmp;
struct rtgui_dc* buffer;
};
#define RTGUI_EVENT_VPAINT_REQ_INIT(e, win, cm) \
do { \
RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_VPAINT_REQ); \
(e)->wid = win; \
(e)->cmp = cm; \
(e)->sender = (e); \
(e)->buffer = RT_NULL; \
rt_completion_init((e)->cmp); \
} while (0)
/**
* RTGUI Gesture Event
*/
enum rtgui_gesture_type
{
RTGUI_GESTURE_NONE = 0x0000,
RTGUI_GESTURE_TAP = 0x0001,
/* Usually used to zoom in and out. */
RTGUI_GESTURE_PINCH = 0x0002,
RTGUI_GESTURE_DRAG = 0x0004,
RTGUI_GESTURE_LONGPRESS = 0x0008,
/* PINCH, DRAG finished. */
RTGUI_GESTURE_FINISH = 0x8000,
/* The corresponding gesture should be canceled. */
RTGUI_GESTURE_CANCEL = 0x4000,
RTGUI_GESTURE_TYPE_MASK = 0x0FFF,
};
struct rtgui_event_gesture
{
_RTGUI_EVENT_WIN_ELEMENTS
enum rtgui_gesture_type type;
};
/*
* RTGUI Mouse and Keyboard Event
*/
struct rtgui_event_mouse
{
_RTGUI_EVENT_WIN_ELEMENTS
rt_uint16_t x, y;
rt_uint16_t button;
/* Timestamp of this event sampled in driver. */
rt_tick_t ts;
/* id of touch session(from down to up). Different session should have
* different id. id should never be 0. */
rt_uint32_t id;
};
#define RTGUI_MOUSE_BUTTON_LEFT 0x01
#define RTGUI_MOUSE_BUTTON_RIGHT 0x02
#define RTGUI_MOUSE_BUTTON_MIDDLE 0x03
#define RTGUI_MOUSE_BUTTON_WHEELUP 0x04
#define RTGUI_MOUSE_BUTTON_WHEELDOWN 0x08
#define RTGUI_MOUSE_BUTTON_DOWN 0x10
#define RTGUI_MOUSE_BUTTON_UP 0x20
#define RTGUI_EVENT_GESTURE_INIT(e, gtype) \
do { \
RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_GESTURE); \
(e)->type = gtype; \
} while (0)
struct rtgui_event_kbd
{
_RTGUI_EVENT_WIN_ELEMENTS
rt_uint16_t type; /* key down or up */
rt_uint16_t key; /* current key */
rt_uint16_t mod; /* current key modifiers */
rt_uint16_t unicode; /* translated character */
};
#define RTGUI_KBD_IS_SET_CTRL(e) ((e)->mod & (RTGUI_KMOD_LCTRL | RTGUI_KMOD_RCTRL))
#define RTGUI_KBD_IS_SET_ALT(e) ((e)->mod & (RTGUI_KMOD_LALT | RTGUI_KMOD_RALT))
#define RTGUI_KBD_IS_SET_SHIFT(e) ((e)->mod & (RTGUI_KMOD_LSHIFT| RTGUI_KMOD_RSHIFT))
#define RTGUI_KBD_IS_UP(e) ((e)->type == RTGUI_KEYUP)
#define RTGUI_KBD_IS_DOWN(e) ((e)->type == RTGUI_KEYDOWN)
#define RTGUI_EVENT_MOUSE_MOTION_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_MOUSE_MOTION)
#define RTGUI_EVENT_MOUSE_BUTTON_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_MOUSE_BUTTON)
#define RTGUI_EVENT_KBD_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_KBD)
/**
* RTGUI Touch Event
* NOTE: There is not touch event to user applications, it's handled by server.
*/
struct rtgui_event_touch
{
struct rtgui_event parent;
rt_uint16_t x, y;
rt_uint16_t up_down;
rt_uint16_t resv;
};
#define RTGUI_TOUCH_UP 0x01
#define RTGUI_TOUCH_DOWN 0x02
#define RTGUI_TOUCH_MOTION 0x03
#define RTGUI_EVENT_TOUCH_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_TOUCH)
struct rtgui_event_command
{
_RTGUI_EVENT_WIN_ELEMENTS
/* command type */
rt_int32_t type;
/* command id */
rt_int32_t command_id;
/* command string */
char command_string[RTGUI_NAME_MAX];
};
#define RTGUI_EVENT_COMMAND_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_COMMAND)
#define RTGUI_CMD_UNKNOWN 0x00
#define RTGUI_CMD_WM_CLOSE 0x10
#define RTGUI_CMD_USER_INT 0x20
#define RTGUI_CMD_USER_STRING 0x21
/************************************************************************/
/* Widget Event */
/************************************************************************/
#define RTGUI_WIDGET_EVENT_INIT(e, t) do \
{ \
(e)->type = (t); \
(e)->sender = RT_NULL; \
(e)->ack = RT_NULL; \
} while (0)
/*
* RTGUI Scrollbar Event
*/
struct rtgui_event_scrollbar
{
struct rtgui_event parent;
rt_uint8_t event;
};
#define RTGUI_SCROLL_LINEUP 0x01
#define RTGUI_SCROLL_LINEDOWN 0x02
#define RTGUI_SCROLL_PAGEUP 0x03
#define RTGUI_SCROLL_PAGEDOWN 0x04
#define RTGUI_EVENT_SCROLLED_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_SCROLLED)
/*
* RTGUI Widget Focused Event
*/
struct rtgui_event_focused
{
struct rtgui_event parent;
struct rtgui_widget *widget;
};
#define RTGUI_EVENT_FOCUSED_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_FOCUSED)
/*
* RTGUI Widget Resize Event
*/
struct rtgui_event_resize
{
struct rtgui_event parent;
rt_int16_t x, y;
rt_int16_t w, h;
};
#define RTGUI_EVENT_RESIZE_INIT(e) RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_RESIZE)
/*
* RTGUI Model/View Event
*/
enum rtgui_event_model_mode
{
RTGUI_MV_DATA_ADDED,
RTGUI_MV_DATA_CHANGED,
RTGUI_MV_DATA_DELETED,
};
struct rtgui_event_mv_model
{
struct rtgui_event parent;
struct rtgui_mv_model *model;
struct rtgui_mv_view *view;
rt_size_t first_data_changed_idx;
rt_size_t last_data_changed_idx;
};
#define _RTGUI_EVENT_MV_INIT_TYPE(T) \
rt_inline void RTGUI_EVENT_MV_MODEL_##T##_INIT(struct rtgui_event_mv_model *e) \
{ \
RTGUI_EVENT_INIT(&((e)->parent), RTGUI_EVENT_MV_MODEL); \
(e)->parent.user = RTGUI_MV_DATA_##T; \
} \
/* useless struct to allow trailing semicolon */ \
struct dummy
_RTGUI_EVENT_MV_INIT_TYPE(ADDED);
_RTGUI_EVENT_MV_INIT_TYPE(CHANGED);
_RTGUI_EVENT_MV_INIT_TYPE(DELETED);
#undef _RTGUI_EVENT_MV_INIT_TYPE
#define _RTGUI_EVENT_MV_IS_TYPE(T) \
rt_inline rt_bool_t RTGUI_EVENT_MV_MODEL_IS_##T(struct rtgui_event_mv_model *e) \
{ \
return e->parent.user == RTGUI_MV_DATA_##T; \
} \
/* useless struct to allow trailing semicolon */ \
struct dummy
_RTGUI_EVENT_MV_IS_TYPE(ADDED);
_RTGUI_EVENT_MV_IS_TYPE(CHANGED);
_RTGUI_EVENT_MV_IS_TYPE(DELETED);
#undef _RTGUI_EVENT_MV_IS_TYPE
#undef _RTGUI_EVENT_WIN_ELEMENTS
union rtgui_event_generic
{
struct rtgui_event base;
struct rtgui_event_application app_create;
struct rtgui_event_application app_destroy;
struct rtgui_event_application app_activate;
struct rtgui_event_set_wm set_wm;
struct rtgui_event_win win_base;
struct rtgui_event_win_create win_create;
struct rtgui_event_win_move win_move;
struct rtgui_event_win_resize win_resize;
struct rtgui_event_win_destroy win_destroy;
struct rtgui_event_win_show win_show;
struct rtgui_event_win_hide win_hide;
struct rtgui_event_win_activate win_activate;
struct rtgui_event_win_deactivate win_deactivate;
struct rtgui_event_win_close win_close;
struct rtgui_event_win_modal_enter win_modal_enter;
struct rtgui_event_update_begin update_begin;
struct rtgui_event_update_end update_end;
struct rtgui_event_monitor monitor;
struct rtgui_event_paint paint;
struct rtgui_event_timer timer;
struct rtgui_event_update_toplvl update_toplvl;
struct rtgui_event_vpaint_req vpaint_req;
struct rtgui_event_clip_info clip_info;
struct rtgui_event_mouse mouse;
struct rtgui_event_kbd kbd;
struct rtgui_event_touch touch;
struct rtgui_event_gesture gesture;
struct rtgui_event_scrollbar scrollbar;
struct rtgui_event_focused focused;
struct rtgui_event_resize resize;
struct rtgui_event_mv_model model;
struct rtgui_event_command command;
};
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,68 @@
/*
* 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__
#ifdef __cplusplus
extern "C" {
#endif
#ifdef RTGUI_USING_DFS_FILERW
#ifdef _WIN32_NATIVE
#pragma warning(disable: 4996)
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#else
#include <dfs_posix.h>
#endif
#endif
#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(const 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);
int rtgui_filerw_unlink(const char *filename);
/* get memory data from filerw memory object */
const rt_uint8_t *rtgui_filerw_mem_getdata(struct rtgui_filerw *context);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,143 @@
/*
* 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>
#ifdef __cplusplus
extern "C" {
#endif
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 char *text,
rt_ubase_t len, struct rtgui_rect *rect);
void (*font_get_metrics)(struct rtgui_font *font, const char *text, struct rtgui_rect *rect);
};
/*
* bitmap font engine
*/
struct rtgui_font_bitmap
{
const rt_uint8_t *bmp; /* bitmap font data */
const rt_uint8_t *char_width; /* each character width, NULL for fixed font */
const rt_uint32_t *offset; /* offset for each character */
rt_uint16_t width; /* font width */
rt_uint16_t height; /* font height */
rt_uint8_t first_char;
rt_uint8_t last_char;
};
extern const struct rtgui_font_engine bmp_font_engine;
#include <rtgui/tree.h>
SPLAY_HEAD(cache_tree, hz_cache);
struct hz_cache
{
SPLAY_ENTRY(hz_cache) hz_node;
rt_uint16_t hz_id;
};
struct rtgui_hz_file_font
{
struct cache_tree cache_root;
rt_uint16_t cache_size;
/* font size */
rt_uint16_t font_size;
rt_uint16_t font_data_size;
/* file descriptor */
int fd;
/* font file name */
const char *font_fn;
};
extern const struct rtgui_font_engine rtgui_hz_file_font_engine;
struct rtgui_font
{
/* font name */
char *family;
/* font height */
rt_uint16_t height;
/* refer count */
rt_uint32_t refer_count;
/* font engine */
const 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 char *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 char *text, rt_ubase_t len, struct rtgui_rect *rect);
int rtgui_font_get_string_width(struct rtgui_font *font, const char *text);
void rtgui_font_get_metrics(struct rtgui_font *font, const char *text, struct rtgui_rect *rect);
/* used by stract font */
#define FONT_BMP_DATA_BEGIN
#define FONT_BMP_DATA_END
struct rtgui_char_position
{
/* Keep the size of this struct within 4 bytes so it can be passed by
* value. */
/* How long this char is. */
rt_uint16_t char_width;
/* How many bytes remaining from current pointer. At least, it will be 1. */
rt_uint16_t remain;
};
/*
* @len the length of @str.
* @offset the char offset on the string to check with.
*/
struct rtgui_char_position _string_char_width(char *str, rt_size_t len, rt_size_t offset);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,38 @@
#ifndef __FONT_FNT_H__
#define __FONT_FNT_H__
#include <rtgui/font.h>
#include <rtgui/dc.h>
/* fnt font header */
struct fnt_header
{
rt_uint8_t version[4];
rt_uint16_t max_width;
rt_uint16_t height;
rt_uint16_t ascent;
rt_uint16_t depth;
rt_uint32_t first_char;
rt_uint32_t default_char;
rt_uint32_t size;
rt_uint32_t nbits;
rt_uint32_t noffset;
rt_uint32_t nwidth;
};
typedef rt_uint8_t MWIMAGEBITS;
struct fnt_font
{
struct fnt_header header;
const MWIMAGEBITS *bits; /* nbits */
const rt_uint16_t *offset; /* noffset */
const rt_uint8_t *width; /* nwidth */
};
extern const struct rtgui_font_engine fnt_font_engine;
struct rtgui_font *fnt_font_create(const char* filename);
#endif

View File

@ -0,0 +1,18 @@
#ifndef __RTGUI_FONT_TTF_H__
#define __RTGUI_FONT_TTF_H__
#include <rtgui/dc.h>
#include <rtgui/font.h>
#ifdef __cplusplus
extern "C" {
#endif
rtgui_font_t *rtgui_freetype_font_create(const char *filename, int bold, int italic, rt_size_t size);
void rtgui_freetype_font_destroy(rtgui_font_t *font);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,90 @@
/*
* 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>
#ifdef __cplusplus
extern "C" {
#endif
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_palette
{
rtgui_color_t *colors;
rt_uint32_t ncolors;
};
typedef struct rtgui_image_palette rtgui_image_palette_t;
struct rtgui_image
{
/* image metrics */
rt_uint16_t w, h;
/* image engine */
const struct rtgui_image_engine *engine;
/* image palette */
rtgui_image_palette_t *palette;
/* image private data */
void *data;
};
typedef struct rtgui_image rtgui_image_t;
/* init rtgui image system */
void rtgui_system_image_init(void);
#if defined(RTGUI_USING_DFS_FILERW)
struct rtgui_image_engine *rtgui_image_get_engine_by_filename(const char *fn);
struct rtgui_image *rtgui_image_create_from_file(const char *type, const char *filename, rt_bool_t load);
struct rtgui_image *rtgui_image_create(const char *filename, rt_bool_t load);
#endif
struct rtgui_image *rtgui_image_create_from_mem(const char *type, const rt_uint8_t *data, rt_size_t length, rt_bool_t load);
void rtgui_image_destroy(struct rtgui_image *image);
/* get image's rect */
void rtgui_image_get_rect(struct rtgui_image *image, struct rtgui_rect *rect);
/* 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);
struct rtgui_image_palette *rtgui_image_palette_create(rt_uint32_t ncolors);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,46 @@
/*
* File : image_bmp.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
* 2010-08-10 Bernard first version
*/
#ifndef __RTGUI_IMAGE_BMP_H__
#define __RTGUI_IMAGE_BMP_H__
#pragma pack(push)
#pragma pack(2)
struct rtgui_image_bmp_header
{
/* The Win32 BMP file header (14 bytes) */
rt_uint16_t bfType;
rt_uint32_t bfSize;
rt_uint16_t bfReserved1;
rt_uint16_t bfReserved2;
rt_uint32_t bfOffBits;
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
rt_uint32_t biSize;
rt_int32_t biWidth;
rt_int32_t biHeight;
rt_uint16_t biPlanes;
rt_uint16_t biBitCount;
rt_uint32_t biCompression;
rt_uint32_t biSizeImage;
rt_int32_t biXPelsPerMeter;
rt_int32_t biYPelsPerMeter;
rt_uint32_t biClrUsed;
rt_uint32_t biClrImportant;
};
#pragma pack(pop)
void rtgui_image_bmp_init(void);
#endif

View File

@ -0,0 +1,37 @@
/*
* 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_HDC_H__
#define __RTGUI_IMAGE_HDC_H__
#include <rtgui/image.h>
struct rtgui_image_hdcmm
{
struct rtgui_image parent;
/* hdc image information */
rt_uint16_t byte_per_pixel;
rt_uint16_t pitch;
rt_uint8_t *pixels;
};
void rtgui_image_hdc_init(void);
extern const struct rtgui_image_engine rtgui_image_hdcmm_engine;
#define HDC_HEADER_SIZE (5 * 4)
#define RTGUI_IMAGE_HDC_DEF(bpp, w, h, pixels) \
{{w, h, &rtgui_image_hdcmm_engine, RT_NULL}, bpp, (bpp * w), ((rt_uint8_t*)pixels + HDC_HEADER_SIZE)}
#endif

View File

@ -0,0 +1,8 @@
#ifndef __RTGUI_IMAGE_JPEG_H__
#define __RTGUI_IMAGE_JPEG_H__
#include <rtgui/image.h>
void rtgui_image_jpeg_init(void);
#endif

View File

@ -0,0 +1,21 @@
/*
* 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>
void rtgui_image_png_init(void);
#endif

View File

@ -0,0 +1,21 @@
/*
* File : image_xpm.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_IMAGE_XPM_H__
#define __RTGUI_IMAGE_XPM_H__
#include <rtgui/image.h>
void rtgui_image_xpm_init(void);
#endif

View File

@ -0,0 +1,295 @@
/*
* 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

View File

@ -0,0 +1,66 @@
/*
* File : list.h
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2009-10-16 Bernard first version
*/
#ifndef __RTGUI_LIST_H__
#define __RTGUI_LIST_H__
#include <rtgui/rtgui.h>
struct rtgui_list_node
{
struct rtgui_list_node *next;
};
typedef struct rtgui_list_node rtgui_list_t;
rt_inline void rtgui_list_init(rtgui_list_t *l)
{
l->next = (struct rtgui_list_node *)0;
}
rt_inline void rtgui_list_append(rtgui_list_t *l, rtgui_list_t *n)
{
struct rtgui_list_node *node;
node = l;
while (node->next) node = node->next;
/* append the node to the tail */
node->next = n;
n->next = (struct rtgui_list_node *) 0;
}
rt_inline void rtgui_list_insert(rtgui_list_t *l, rtgui_list_t *n)
{
n->next = l->next;
l->next = n;
}
rt_inline rtgui_list_t *rtgui_list_remove(rtgui_list_t *l, rtgui_list_t *n)
{
/* remove slist head */
struct rtgui_list_node *node = l;
while (node->next && node->next != n) node = node->next;
/* remove node */
if (node->next != (rtgui_list_t *)0) node->next = node->next->next;
return l;
}
#define rtgui_list_entry(node, type, member) \
((type *)((char*)(node)-(unsigned long)(&((type *)0)->member)))
#define rtgui_list_foreach(node, list) \
for ((node) = (list)->next; (node) != RT_NULL; (node) = (node)->next)
#endif

View File

@ -0,0 +1,162 @@
#ifndef __MATRIX_H__
#define __MATRIX_H__
/* Port from ejoy2d: https://github.com/cloudwu/ejoy2d/blob/master/LICENSE
* Original License:
*
* The MIT License (MIT)
*
* Copyright (c) 2013 Ejoy.com Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* Port to RTGUI and modified by Grissiom */
#ifdef _MSC_VER
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#define RTGUI_MATRIX_FRAC_BITS 11
#define RTGUI_MATRIX_FRAC (1 << RTGUI_MATRIX_FRAC_BITS)
struct rtgui_matrix
{
/* The matrix format is :
*
* | m[0] m[1] 0 |
* | m[2] m[3] 0 |
* | m[4] m[5] 1 |
*
* The format of the coordinate of a point is:
*
* | x y 1 |
*
* So, if you want to transform a point p with a matrix m, do:
*
* p * m
*
* Note: m[0-3] is in fix presentation that has 10 bits decimal
* fraction(m/RTGUI_MATRIX_FRAC). While the unit of m[4-5] is pixel.
*
*/
int m[6];
};
rt_inline int32_t _rtgui_matrix_round_div32(int32_t n, int32_t d)
{
if (n == 0)
return 0;
if (d < 0)
{
d = -d;
n = -n;
}
if (n > 0)
return (n + d / 2) / d;
else
return (n - d / 2) / d;
}
rt_inline int32_t _rtgui_matrix_round_div6432(int64_t n, int32_t d)
{
if (n == 0)
return 0;
if (d < 0)
{
d = -d;
n = -n;
}
if (n > 0)
return (n + d / 2) / d;
else
return (n - d / 2) / d;
}
/* mm = mm1 * mm2 */
rt_inline void rtgui_matrix_mul(struct rtgui_matrix *mm,
const struct rtgui_matrix *mm1,
const struct rtgui_matrix *mm2)
{
int *m = mm->m;
const int *m1 = mm1->m;
const int *m2 = mm2->m;
m[0] = _rtgui_matrix_round_div32(m1[0] * m2[0] + m1[1] * m2[2], RTGUI_MATRIX_FRAC);
m[1] = _rtgui_matrix_round_div32(m1[0] * m2[1] + m1[1] * m2[3], RTGUI_MATRIX_FRAC);
m[2] = _rtgui_matrix_round_div32(m1[2] * m2[0] + m1[3] * m2[2], RTGUI_MATRIX_FRAC);
m[3] = _rtgui_matrix_round_div32(m1[2] * m2[1] + m1[3] * m2[3], RTGUI_MATRIX_FRAC);
m[4] = _rtgui_matrix_round_div32(m1[4] * m2[0] + m1[5] * m2[2], RTGUI_MATRIX_FRAC) + m2[4];
m[5] = _rtgui_matrix_round_div32(m1[4] * m2[1] + m1[5] * m2[3], RTGUI_MATRIX_FRAC) + m2[5];
}
/* Matrix multiply point[(p) = (x, y) * m], ignore the movement components. */
rt_inline void rtgui_matrix_mul_point_nomove(struct rtgui_point *p,
int x, int y,
struct rtgui_matrix *m)
{
int *mm = m->m;
p->x = _rtgui_matrix_round_div32(x * mm[0] + y * mm[2], RTGUI_MATRIX_FRAC);
p->y = _rtgui_matrix_round_div32(x * mm[1] + y * mm[3], RTGUI_MATRIX_FRAC);
}
/* Matrix multiply point[(p) = (x, y) * m]. */
rt_inline void rtgui_matrix_mul_point(struct rtgui_point *p,
int x, int y,
struct rtgui_matrix *m)
{
int *mm = m->m;
p->x = _rtgui_matrix_round_div32(x * mm[0] + y * mm[2], RTGUI_MATRIX_FRAC) + mm[4];
p->y = _rtgui_matrix_round_div32(x * mm[1] + y * mm[3], RTGUI_MATRIX_FRAC) + mm[5];
}
/** Set @mm to an identity matrix. */
rt_inline void rtgu_matrix_identity(struct rtgui_matrix *mm)
{
int *mat = mm->m;
mat[0] = RTGUI_MATRIX_FRAC;
mat[1] = 0;
mat[2] = 0;
mat[3] = RTGUI_MATRIX_FRAC;
mat[4] = 0;
mat[5] = 0;
}
/** Save the inversed matrix of @mm to @mo.
*
* @return If the matrix is not inversale, return 1. Otherwise, return 0. */
int rtgui_matrix_inverse(const struct rtgui_matrix *mm, struct rtgui_matrix *mo);
/** @degree range from 0 ~ 512. */
void rtgui_matrix_rotate(struct rtgui_matrix *m, int degree);
/** The unit is fixed point number. RTGUI_MATRIX_FRAC means 1.0. */
void rtgui_matrix_scale(struct rtgui_matrix *m, int sx, int sy);
/** The unit is pixel. Not the fixed point number. */
void rtgui_matrix_move(struct rtgui_matrix *m, int dx, int dy);
#endif /* end of include guard: __MATRIX_H__ */

View File

@ -0,0 +1,118 @@
/*
* 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_dc;
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, const 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);
void rtgui_region_draw_clip(rtgui_region_t *region, struct rtgui_dc *dc);
int rtgui_region_is_flat(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(const 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(const rtgui_rect_t *rect, int x, int y);
int rtgui_rect_is_intersect(const rtgui_rect_t *rect1, const rtgui_rect_t *rect2);
int rtgui_rect_is_equal(const rtgui_rect_t *rect1, const rtgui_rect_t *rect2);
rtgui_rect_t *rtgui_rect_set(rtgui_rect_t *rect, int x, int y, int w, int h);
rt_bool_t rtgui_rect_is_empty(const rtgui_rect_t *rect);
rt_inline void rtgui_rect_init(rtgui_rect_t* rect, int x, int y, int width, int height)
{
rect->x1 = x; rect->y1 = y;
rect->x2 = x + width; rect->y2 = y + height;
}
#define RTGUI_RECT(rect, x, y, w, h) \
do { \
rect.x1 = x; rect.y1 = y; \
rect.x2 = (x) + (w); rect.y2 = (y) + (h); \
} while (0)
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif /* _PIXMAN_H_ */

View File

@ -0,0 +1,194 @@
/*
* File : rtgui.h
* This file is part of RT-Thread GUI
* COPYRIGHT (C) 2009 - 2013, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2009-10-04 Bernard first version
*/
#ifndef __RT_GUI_H__
#define __RT_GUI_H__
#include <rtthread.h>
#include <rtgui/rtgui_config.h>
#ifdef __cplusplus
extern "C" {
#endif
#define RTGUI_VERSION 0L /**< major version number */
#define RTGUI_SUBVERSION 8L /**< minor version number */
#define RTGUI_REVISION 1L /**< revise version number */
#define RTGUI_CODENAME "Newton" /**< code name */
#define RT_INT16_MAX 32767
#define RT_INT16_MIN (-RT_INT16_MAX-1)
#define RTGUI_NOT_FOUND (-1)
#define _UI_MIN(x, y) (((x)<(y))?(x):(y))
#define _UI_MAX(x, y) (((x)>(y))?(x):(y))
#define _UI_BITBYTES(bits) ((bits + 7)/8)
#define _UI_ABS(x) ((x)>=0? (x):-(x))
/* MDK, GCC and MSVC all support __restrict keyword. */
#define RTGUI_RESTRICT __restrict
#ifdef _MSC_VER
#define RTGUI_PURE
#else
/* GCC and MDK share the same attributes.
* TODO: IAR attributes. */
#define RTGUI_PURE __attribute__((pure))
#endif
struct rtgui_event;
struct rtgui_object;
struct rtgui_widget;
struct rtgui_win;
struct rtgui_font;
typedef struct rtgui_win rtgui_win_t;
typedef rt_bool_t (*rtgui_event_handler_ptr)(struct rtgui_object *object, struct rtgui_event *event);
typedef void (*rtgui_onbutton_func_t)(struct rtgui_object *object, struct rtgui_event *event);
/**
* Coordinate point
*/
struct rtgui_point
{
rt_int16_t x, y;
};
typedef struct rtgui_point rtgui_point_t;
extern rtgui_point_t rtgui_empty_point;
/**
* Rectangle structure
*/
struct rtgui_rect
{
rt_int16_t x1, y1, x2, y2;
};
typedef struct rtgui_rect rtgui_rect_t;
#define rtgui_rect_width(r) ((r).x2 - (r).x1)
#define rtgui_rect_height(r) ((r).y2 - (r).y1)
typedef unsigned long rtgui_color_t;
/**
* Graphic context
*/
struct rtgui_gc
{
/* foreground and background color */
rtgui_color_t foreground, background;
/* text style */
rt_uint16_t textstyle;
/* text align */
rt_uint16_t textalign;
/* font */
struct rtgui_font *font;
};
typedef struct rtgui_gc rtgui_gc_t;
enum RTGUI_MARGIN_STYLE
{
RTGUI_MARGIN_LEFT = 0x01,
RTGUI_MARGIN_RIGHT = 0x02,
RTGUI_MARGIN_TOP = 0x04,
RTGUI_MARGIN_BOTTOM = 0x08,
RTGUI_MARGIN_ALL = RTGUI_MARGIN_LEFT | RTGUI_MARGIN_RIGHT | RTGUI_MARGIN_TOP | RTGUI_MARGIN_BOTTOM
};
/**
* Border style
*/
enum RTGUI_BORDER_STYLE
{
RTGUI_BORDER_NONE = 0,
RTGUI_BORDER_SIMPLE,
RTGUI_BORDER_RAISE,
RTGUI_BORDER_SUNKEN,
RTGUI_BORDER_BOX,
RTGUI_BORDER_STATIC,
RTGUI_BORDER_EXTRA,
RTGUI_BORDER_UP,
RTGUI_BORDER_DOWN
};
#define RTGUI_BORDER_DEFAULT_WIDTH 2
#define RTGUI_WIDGET_DEFAULT_MARGIN 3
/**
* Blend mode
*/
enum RTGUI_BLENDMODE
{
RTGUI_BLENDMODE_NONE = 0x00,
RTGUI_BLENDMODE_BLEND,
RTGUI_BLENDMODE_ADD,
RTGUI_BLENDMODE_MOD,
};
/**
* Orientation
*/
enum RTGUI_ORIENTATION
{
RTGUI_HORIZONTAL = 0x01,
RTGUI_VERTICAL = 0x02,
RTGUI_ORIENTATION_BOTH = RTGUI_HORIZONTAL | RTGUI_VERTICAL
};
enum RTGUI_ALIGN
{
RTGUI_ALIGN_NOT = 0x00,
RTGUI_ALIGN_CENTER_HORIZONTAL = 0x01,
RTGUI_ALIGN_LEFT = RTGUI_ALIGN_NOT,
RTGUI_ALIGN_TOP = RTGUI_ALIGN_NOT,
RTGUI_ALIGN_RIGHT = 0x02,
RTGUI_ALIGN_BOTTOM = 0x04,
RTGUI_ALIGN_CENTER_VERTICAL = 0x08,
RTGUI_ALIGN_CENTER = RTGUI_ALIGN_CENTER_HORIZONTAL | RTGUI_ALIGN_CENTER_VERTICAL,
RTGUI_ALIGN_EXPAND = 0x10,
RTGUI_ALIGN_STRETCH = 0x20,
};
enum RTGUI_TEXTSTYLE
{
RTGUI_TEXTSTYLE_NORMAL = 0x00,
RTGUI_TEXTSTYLE_DRAW_BACKGROUND = 0x01,
RTGUI_TEXTSTYLE_SHADOW = 0x02,
RTGUI_TEXTSTYLE_OUTLINE = 0x04,
};
enum RTGUI_MODAL_CODE
{
RTGUI_MODAL_OK,
RTGUI_MODAL_CANCEL
};
typedef enum RTGUI_MODAL_CODE rtgui_modal_code_t;
#include <rtgui/rtgui_object.h>
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,113 @@
/*
* File : rtgui_app.h
* This file is part of RTGUI in RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2012-01-13 Grissiom first version
*/
#ifndef __RTGUI_APP_H__
#define __RTGUI_APP_H__
#include <rtthread.h>
#include <rtgui/rtgui.h>
#include <rtgui/event.h>
#include <rtgui/rtgui_system.h>
#ifdef __cplusplus
extern "C" {
#endif
DECLARE_CLASS_TYPE(application);
/** Gets the type of a application */
#define RTGUI_APP_TYPE (RTGUI_TYPE(application))
/** Casts the object to an rtgui_workbench */
#define RTGUI_APP(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_APP_TYPE, struct rtgui_app))
/** Checks if the object is an rtgui_workbench */
#define RTGUI_IS_APP(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_APP_TYPE))
enum rtgui_app_flag
{
RTGUI_APP_FLAG_EXITED = 0x04,
RTGUI_APP_FLAG_SHOWN = 0x08,
RTGUI_APP_FLAG_KEEP = 0x80,
};
typedef void (*rtgui_idle_func_t)(struct rtgui_object *obj, struct rtgui_event *event);
struct rtgui_app
{
struct rtgui_object parent;
/* application name */
unsigned char *name;
struct rtgui_image *icon;
enum rtgui_app_flag state_flag;
rt_uint16_t ref_count;
rt_uint16_t exit_code;
/* the thread id */
rt_thread_t tid;
/* the message queue of thread */
rt_mq_t mq;
/* event buffer */
rt_uint8_t event_buffer[sizeof(union rtgui_event_generic)];
/* if not RT_NULL, the main_object is the one will be activated when the
* app recieves activate event. By default, it is the first window shown in
* the app. */
struct rtgui_object *main_object;
/* on idle event handler */
rtgui_idle_func_t on_idle;
unsigned int window_cnt;
void *user_data;
};
/**
* create an application named @myname on current thread.
*
* @param name the name of the application
*
* @return a pointer to struct rtgui_app on success. RT_NULL on failure.
*/
struct rtgui_app *rtgui_app_create(const char *name);
void rtgui_app_destroy(struct rtgui_app *app);
rt_bool_t rtgui_app_event_handler(struct rtgui_object *obj, rtgui_event_t *event);
rt_base_t rtgui_app_run(struct rtgui_app *app);
void rtgui_app_exit(struct rtgui_app *app, rt_uint16_t code);
void rtgui_app_activate(struct rtgui_app *app);
void rtgui_app_close(struct rtgui_app *app);
void rtgui_app_sleep(struct rtgui_app *app, int millisecond);
void rtgui_app_set_onidle(struct rtgui_app *app, rtgui_idle_func_t onidle);
rtgui_idle_func_t rtgui_app_get_onidle(struct rtgui_app *app);
/**
* return the rtgui_app struct on current thread
*/
struct rtgui_app *rtgui_app_self(void);
rt_err_t rtgui_app_set_as_wm(struct rtgui_app *app);
void rtgui_app_set_main_win(struct rtgui_app *app, struct rtgui_win *win);
struct rtgui_win* rtgui_app_get_main_win(struct rtgui_app *app);
#ifdef __cplusplus
}
#endif
#endif /* end of include guard: __RTGUI_APP_H__ */

View File

@ -0,0 +1,71 @@
/*
* 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
* 2010-02-08 Bernard move some RTGUI options to bsp
*/
#ifndef __RTGUI_CONFIG_H__
#define __RTGUI_CONFIG_H__
/* RTGUI options */
#ifndef RT_USING_DFS
#undef RTGUI_USING_DFS_FILERW
#undef RTGUI_USING_HZ_FILE
#endif
#ifdef RT_USING_DFS
/* if file system is used, the DFS_FILERW will be defined */
#ifndef RTGUI_USING_DFS_FILERW
#define RTGUI_USING_DFS_FILERW
#endif
#endif
#if RTGUI_DEFAULT_FONT_SIZE == 0
#define RTGUI_DEFAULT_FONT_SIZE 12
#endif
#define RTGUI_SVR_THREAD_PRIORITY 15
#define RTGUI_SVR_THREAD_TIMESLICE 5
#ifndef RTGUI_SVR_THREAD_STACK_SIZE
#ifdef RTGUI_USING_SMALL_SIZE
#define RTGUI_SVR_THREAD_STACK_SIZE 1024
#else
#define RTGUI_SVR_THREAD_STACK_SIZE 2048
#endif
#endif
#define RTGUI_APP_THREAD_PRIORITY 25
#define RTGUI_APP_THREAD_TIMESLICE 5
#ifdef RTGUI_USING_SMALL_SIZE
#define RTGUI_APP_THREAD_STACK_SIZE 1024
#else
#define RTGUI_APP_THREAD_STACK_SIZE 2048
#endif
// #define RTGUI_USING_CAST_CHECK
// #define RTGUI_USING_DESKTOP_WINDOW
// #undef RTGUI_USING_SMALL_SIZE
//#define RTGUI_USING_CALIBRATION
#define RTGUI_USING_VFRAMEBUFFER
#ifdef DEBUG_MEMLEAK
#define rtgui_malloc rt_malloc
#define rtgui_realloc rt_realloc
#define rtgui_free rt_free
#endif
#endif

View File

@ -0,0 +1,167 @@
/*
* File : rtgui_object.h
* This file is part of RTGUI in 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-04 Bernard first version
*/
#ifndef __RTGUI_OBJECT_H__
#define __RTGUI_OBJECT_H__
#include <rtthread.h>
#include <rtgui/rtgui.h>
#ifdef __cplusplus
extern "C" {
#endif
/* rtgui object type */
#define RTGUI_CONTAINER_OF(obj, type, member) \
((type *)((char *)(obj) - (unsigned long)(&((type *)0)->member)))
/** Casts the function pointer to an rtgui_constructor */
#define RTGUI_CONSTRUCTOR(constructor) ((rtgui_constructor_t)(constructor))
/** Casts the function pointer to an rtgui_constructor */
#define RTGUI_DESTRUCTOR(destructor) ((rtgui_destructor_t)(destructor))
/* pre-definition */
struct rtgui_object;
struct rtgui_app;
typedef struct rtgui_object rtgui_object_t;
typedef void (*rtgui_constructor_t)(rtgui_object_t *object);
typedef void (*rtgui_destructor_t)(rtgui_object_t *object);
/* rtgui type structure */
struct rtgui_type
{
/* type name */
char *name;
/* parent type link */
const struct rtgui_type *parent;
/* constructor and destructor */
rtgui_constructor_t constructor;
rtgui_destructor_t destructor;
/* size of type */
int size;
};
typedef struct rtgui_type rtgui_type_t;
#define RTGUI_TYPE(type) (_rtgui_##type##_get_type())
#define RTGUI_PARENT_TYPE(type) (const struct rtgui_type*)(&_rtgui_##type)
#define DECLARE_CLASS_TYPE(type) \
const rtgui_type_t *_rtgui_##type##_get_type(void); \
extern const struct rtgui_type _rtgui_##type
#define DEFINE_CLASS_TYPE(type, name, parent, constructor, destructor, size) \
const struct rtgui_type _rtgui_##type = { \
name, \
parent, \
RTGUI_CONSTRUCTOR(constructor), \
RTGUI_DESTRUCTOR(destructor), \
size }; \
const rtgui_type_t *_rtgui_##type##_get_type(void) { return &_rtgui_##type; } \
RTM_EXPORT(_rtgui_##type##_get_type)
void rtgui_type_object_construct(const rtgui_type_t *type, rtgui_object_t *object);
void rtgui_type_destructors_call(const rtgui_type_t *type, rtgui_object_t *object);
rt_bool_t rtgui_type_inherits_from(const rtgui_type_t *type, const rtgui_type_t *parent);
const rtgui_type_t *rtgui_type_parent_type_get(const rtgui_type_t *type);
const char *rtgui_type_name_get(const rtgui_type_t *type);
const rtgui_type_t *rtgui_object_object_type_get(rtgui_object_t *object);
#ifdef RTGUI_USING_CAST_CHECK
#define RTGUI_OBJECT_CAST(obj, obj_type, c_type) \
((c_type *)rtgui_object_check_cast((rtgui_object_t *)(obj), (obj_type), __FUNCTION__, __LINE__))
#else
#define RTGUI_OBJECT_CAST(obj, obj_type, c_type) ((c_type *)(obj))
#endif
#define RTGUI_OBJECT_CHECK_TYPE(_obj, _type) \
(rtgui_type_inherits_from(((rtgui_object_t *)(_obj))->type, (_type)))
DECLARE_CLASS_TYPE(object);
/** Gets the type of an object */
#define RTGUI_OBJECT_TYPE RTGUI_TYPE(object)
/** Casts the object to an rtgui_object_t */
#define RTGUI_OBJECT(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_OBJECT_TYPE, struct rtgui_object))
/** Checks if the object is an rtgui_Object */
#define RTGUI_IS_OBJECT(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_OBJECT_TYPE))
enum rtgui_object_flag
{
RTGUI_OBJECT_FLAG_NONE = 0x0000,
RTGUI_OBJECT_FLAG_STATIC = 0x0001,
RTGUI_OBJECT_FLAG_DISABLED = 0x0002,
/* When an object is created, it's flag is set to valid. When an object is
* deleted, the valid bits will be cleared. */
RTGUI_OBJECT_FLAG_VALID = 0xAB00,
};
/* rtgui base object */
struct rtgui_object
{
/* object type */
const rtgui_type_t *type;
/* the event handler */
rtgui_event_handler_ptr event_handler;
enum rtgui_object_flag flag;
rt_uint32_t id;
};
rtgui_object_t *rtgui_object_create(const rtgui_type_t *object_type);
void rtgui_object_destroy(rtgui_object_t *object);
/* set the event handler of object */
void rtgui_object_set_event_handler(struct rtgui_object *object, rtgui_event_handler_ptr handler);
/* object default event handler */
rt_bool_t rtgui_object_event_handler(struct rtgui_object *object, struct rtgui_event *event);
/* helper micro. widget event handlers could use this. */
#define RTGUI_WIDGET_EVENT_HANDLER_PREPARE \
struct rtgui_widget *widget; \
RT_ASSERT(object != RT_NULL); \
RT_ASSERT(event != RT_NULL); \
widget = RTGUI_WIDGET(object); \
/* supress compiler warning */ \
widget = widget;
/** handle @param event on @param object's own event handler
*
* If the @param object does not have an event handler, which means the object
* does not interested in any event, it will return RT_FALSE. Otherwise, the
* return code of that handler is returned.
*/
rt_inline rt_bool_t rtgui_object_handle(struct rtgui_object *object, struct rtgui_event *event)
{
if (object->event_handler)
return object->event_handler(object, event);
return RT_FALSE;
}
rtgui_object_t *rtgui_object_check_cast(rtgui_object_t *object, const rtgui_type_t *type, const char *func, int line);
const rtgui_type_t *rtgui_object_object_type_get(rtgui_object_t *object);
void rtgui_object_set_id(struct rtgui_object *obj, rt_uint32_t id);
rt_uint32_t rtgui_object_get_id(struct rtgui_object *obj);
struct rtgui_object* rtgui_get_object(struct rtgui_app *app, rt_uint32_t id);
struct rtgui_object* rtgui_get_self_object(rt_uint32_t id);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,79 @@
/*
* File : rtgui_server.h
* This file is part of RTGUI in 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-04 Bernard first version
*/
#ifndef __RTGUI_SERVER_H__
#define __RTGUI_SERVER_H__
#include <rtservice.h>
#include <rtgui/list.h>
/* RTGUI server definitions */
/* top window definitions in server */
enum rtgui_topwin_flag
{
WINTITLE_INIT = 0x00,
WINTITLE_ACTIVATE = 0x01,
WINTITLE_NOFOCUS = 0x02,
/* window is hidden by default */
WINTITLE_SHOWN = 0x04,
/* window is modaled by other window */
WINTITLE_MODALED = 0x08,
/* window is modaling other window */
WINTITLE_MODALING = 0x100,
WINTITLE_ONTOP = 0x200,
WINTITLE_ONBTM = 0x400,
};
struct rtgui_topwin
{
/* the window flag */
enum rtgui_topwin_flag flag;
/* event mask */
rt_uint32_t mask;
struct rtgui_wintitle *title;
/* the window id */
struct rtgui_win *wid;
/* which app I belong */
struct rtgui_app *app;
/* the extent information */
rtgui_rect_t extent;
struct rtgui_topwin *parent;
/* we need to iterate the topwin list with usual order(get target window)
* or reversely(painting). So it's better to use a double linked list */
rt_list_t list;
rt_list_t child_list;
/* the monitor rect list */
rtgui_list_t monitor_list;
};
/* top win manager init */
void rtgui_topwin_init(void);
void rtgui_server_init(void);
void rtgui_server_install_show_win_hook(void (*hk)(void));
void rtgui_server_install_act_win_hook(void (*hk)(void));
/* post an event to server */
void rtgui_server_post_event(struct rtgui_event *event, rt_size_t size);
rt_err_t rtgui_server_post_event_sync(struct rtgui_event *event, rt_size_t size);
#endif

View File

@ -0,0 +1,98 @@
/*
* File : rtgui_system.h
* This file is part of RTGUI in 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-04 Bernard first version
*/
#ifndef __RTGUI_SYSTEM_H__
#define __RTGUI_SYSTEM_H__
#include <rtthread.h>
#include <rtgui/rtgui.h>
#ifdef __cplusplus
extern "C" {
#endif
struct rtgui_dc;
struct rtgui_event;
struct rtgui_widget;
struct rtgui_timer;
typedef void (*rtgui_timeout_func)(struct rtgui_timer *timer, void *parameter);
enum rtgui_timer_state
{
RTGUI_TIMER_ST_INIT,
RTGUI_TIMER_ST_RUNNING,
RTGUI_TIMER_ST_DESTROY_PENDING,
};
struct rtgui_timer
{
/* the rtgui application it runs on */
struct rtgui_app* app;
/* rt timer */
struct rt_timer timer;
/* How many events are pending on the queue. */
int pending_cnt;
enum rtgui_timer_state state;
/* timeout function and user data */
rtgui_timeout_func timeout;
void *user_data;
};
typedef struct rtgui_timer rtgui_timer_t;
rtgui_timer_t *rtgui_timer_create(rt_int32_t time, rt_base_t flag, rtgui_timeout_func timeout, void *parameter);
void rtgui_timer_destory(rtgui_timer_t *timer);
void rtgui_timer_set_timeout(rtgui_timer_t *timer, rt_int32_t time);
void rtgui_timer_start(rtgui_timer_t *timer);
void rtgui_timer_stop(rtgui_timer_t *timer);
/* rtgui system initialization function */
int rtgui_system_server_init(void);
void *rtgui_malloc(rt_size_t size);
void rtgui_free(void *ptr);
void *rtgui_realloc(void *ptr, rt_size_t size);
#ifdef _WIN32_NATIVE
#define rtgui_enter_critical()
#define rtgui_exit_critical()
#else
#define rtgui_enter_critical rt_enter_critical
#define rtgui_exit_critical rt_exit_critical
#endif
struct rtgui_app* rtgui_get_server(void);
void rtgui_set_mainwin_rect(struct rtgui_rect *rect);
void rtgui_get_mainwin_rect(struct rtgui_rect *rect);
void rtgui_get_screen_rect(struct rtgui_rect *rect);
void rtgui_screen_lock(rt_int32_t timeout);
void rtgui_screen_unlock(void);
int rtgui_screen_lock_freeze(void);
void rtgui_screen_lock_thaw(int value);
struct rtgui_event;
rt_err_t rtgui_send(struct rtgui_app* app, struct rtgui_event *event, rt_size_t event_size);
rt_err_t rtgui_send_urgent(struct rtgui_app* app, struct rtgui_event *event, rt_size_t event_size);
rt_err_t rtgui_send_sync(struct rtgui_app* app, struct rtgui_event *event, rt_size_t event_size);
rt_err_t rtgui_ack(struct rtgui_event *event, rt_int32_t status);
rt_err_t rtgui_recv(struct rtgui_event *event, rt_size_t event_size, rt_int32_t timeout);
rt_err_t rtgui_recv_filter(rt_uint32_t type, struct rtgui_event *event, rt_size_t event_size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,748 @@
/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
/* $FreeBSD$ */
/*-
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SYS_TREE_H_
#define _SYS_TREE_H_
#ifndef NULL
#define NULL RT_NULL
#endif
// #include <sys/cdefs.h>
/*
* This file defines data structures for different types of trees:
* splay trees and red-black trees.
*
* A splay tree is a self-organizing data structure. Every operation
* on the tree causes a splay to happen. The splay moves the requested
* node to the root of the tree and partly rebalances it.
*
* This has the benefit that request locality causes faster lookups as
* the requested nodes move to the top of the tree. On the other hand,
* every lookup causes memory writes.
*
* The Balance Theorem bounds the total access time for m operations
* and n inserts on an initially empty tree as O((m + n)lg n). The
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
*
* A red-black tree is a binary search tree with the node color as an
* extra attribute. It fulfills a set of conditions:
* - every search path from the root to a leaf consists of the
* same number of black nodes,
* - each red node (except for the root) has a black parent,
* - each leaf node is black.
*
* Every operation on a red-black tree is bounded as O(lg n).
* The maximum height of a red-black tree is 2lg (n+1).
*/
#define SPLAY_HEAD(name, type) \
struct name { \
struct type *sph_root; /* root of the tree */ \
}
#define SPLAY_INITIALIZER(root) \
{ NULL }
#define SPLAY_INIT(root) do { \
(root)->sph_root = NULL; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ENTRY(type) \
struct { \
struct type *spe_left; /* left element */ \
struct type *spe_right; /* right element */ \
}
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
#define SPLAY_ROOT(head) (head)->sph_root
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKLEFT(head, tmp, field) do { \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
} while (/*CONSTCOND*/ 0)
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
} while (/*CONSTCOND*/ 0)
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
} while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
void name##_SPLAY(struct name *, struct type *); \
void name##_SPLAY_MINMAX(struct name *, int); \
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
\
/* Finds the node with the same key as elm */ \
rt_inline struct type * \
name##_SPLAY_FIND(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) \
return(NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) \
return (head->sph_root); \
return (NULL); \
} \
\
rt_inline struct type * \
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
{ \
name##_SPLAY(head, elm); \
if (SPLAY_RIGHT(elm, field) != NULL) { \
elm = SPLAY_RIGHT(elm, field); \
while (SPLAY_LEFT(elm, field) != NULL) { \
elm = SPLAY_LEFT(elm, field); \
} \
} else \
elm = NULL; \
return (elm); \
} \
\
rt_inline struct type * \
name##_SPLAY_MIN_MAX(struct name *head, int val) \
{ \
name##_SPLAY_MINMAX(head, val); \
return (SPLAY_ROOT(head)); \
}
/* Main splay operation.
* Moves node close to the key of elm to top
*/
#define SPLAY_GENERATE(name, type, field, cmp) \
struct type * \
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) { \
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
} else { \
int __comp; \
name##_SPLAY(head, elm); \
__comp = (cmp)(elm, (head)->sph_root); \
if(__comp < 0) { \
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
SPLAY_LEFT((head)->sph_root, field) = NULL; \
} else if (__comp > 0) { \
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT(elm, field) = (head)->sph_root; \
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
} else \
return ((head)->sph_root); \
} \
(head)->sph_root = (elm); \
return (NULL); \
} \
\
struct type * \
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *__tmp; \
if (SPLAY_EMPTY(head)) \
return (NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) { \
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
} else { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
name##_SPLAY(head, elm); \
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
} \
return (elm); \
} \
return (NULL); \
} \
\
void \
name##_SPLAY(struct name *head, struct type *elm) \
{ \
struct type __node, *__left, *__right, *__tmp; \
int __comp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) < 0){ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) > 0){ \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
} \
\
/* Splay with either the minimum or the maximum element \
* Used to find minimum or maximum element in tree. \
*/ \
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
{ \
struct type __node, *__left, *__right, *__tmp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while (1) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp < 0){ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp > 0) { \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
}
#define SPLAY_NEGINF -1
#define SPLAY_INF 1
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
#define SPLAY_FOREACH(x, name, head) \
for ((x) = SPLAY_MIN(name, head); \
(x) != NULL; \
(x) = SPLAY_NEXT(name, head, x))
/* Macros that define a red-black tree */
#define RB_HEAD(name, type) \
struct name { \
struct type *rbh_root; /* root of the tree */ \
}
#define RB_INITIALIZER(root) \
{ NULL }
#define RB_INIT(root) do { \
(root)->rbh_root = NULL; \
} while (/*CONSTCOND*/ 0)
#define RB_BLACK 0
#define RB_RED 1
#define RB_ENTRY(type) \
struct { \
struct type *rbe_left; /* left element */ \
struct type *rbe_right; /* right element */ \
struct type *rbe_parent; /* parent element */ \
int rbe_color; /* node color */ \
}
#define RB_LEFT(elm, field) (elm)->field.rbe_left
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
#define RB_COLOR(elm, field) (elm)->field.rbe_color
#define RB_ROOT(head) (head)->rbh_root
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
#define RB_SET(elm, parent, field) do { \
RB_PARENT(elm, field) = parent; \
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
RB_COLOR(elm, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
#define RB_SET_BLACKRED(black, red, field) do { \
RB_COLOR(black, field) = RB_BLACK; \
RB_COLOR(red, field) = RB_RED; \
} while (/*CONSTCOND*/ 0)
#ifndef RB_AUGMENT
#define RB_AUGMENT(x) do {} while (0)
#endif
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
(tmp) = RB_RIGHT(elm, field); \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
(head)->rbh_root = (tmp); \
RB_LEFT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (/*CONSTCOND*/ 0)
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
(tmp) = RB_LEFT(elm, field); \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
(head)->rbh_root = (tmp); \
RB_RIGHT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (/*CONSTCOND*/ 0)
/* Generates prototypes and inline functions */
#define RB_PROTOTYPE(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
attr struct type *name##_RB_FIND(struct name *, struct type *); \
attr struct type *name##_RB_NFIND(struct name *, struct type *); \
attr struct type *name##_RB_NEXT(struct type *); \
attr struct type *name##_RB_PREV(struct type *); \
attr struct type *name##_RB_MINMAX(struct name *, int); \
\
/* Main rb operation.
* Moves node close to the key of elm to top
*/
#define RB_GENERATE(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
struct type *parent, *gparent, *tmp; \
while ((parent = RB_PARENT(elm, field)) != NULL && \
RB_COLOR(parent, field) == RB_RED) { \
gparent = RB_PARENT(parent, field); \
if (parent == RB_LEFT(gparent, field)) { \
tmp = RB_RIGHT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field);\
elm = gparent; \
continue; \
} \
if (RB_RIGHT(parent, field) == elm) { \
RB_ROTATE_LEFT(head, parent, tmp, field);\
tmp = parent; \
parent = elm; \
elm = tmp; \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
} else { \
tmp = RB_LEFT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field);\
elm = gparent; \
continue; \
} \
if (RB_LEFT(parent, field) == elm) { \
RB_ROTATE_RIGHT(head, parent, tmp, field);\
tmp = parent; \
parent = elm; \
elm = tmp; \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_LEFT(head, gparent, tmp, field); \
} \
} \
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
} \
\
attr void \
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
{ \
struct type *tmp; \
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
elm != RB_ROOT(head)) { \
if (RB_LEFT(parent, field) == elm) { \
tmp = RB_RIGHT(parent, field); \
if (RB_COLOR(tmp, field) == RB_RED) { \
RB_SET_BLACKRED(tmp, parent, field); \
RB_ROTATE_LEFT(head, parent, tmp, field);\
tmp = RB_RIGHT(parent, field); \
} \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
if (RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
struct type *oleft; \
if ((oleft = RB_LEFT(tmp, field)) \
!= NULL) \
RB_COLOR(oleft, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
tmp = RB_RIGHT(parent, field); \
} \
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
RB_COLOR(parent, field) = RB_BLACK; \
if (RB_RIGHT(tmp, field)) \
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
RB_ROTATE_LEFT(head, parent, tmp, field);\
elm = RB_ROOT(head); \
break; \
} \
} else { \
tmp = RB_LEFT(parent, field); \
if (RB_COLOR(tmp, field) == RB_RED) { \
RB_SET_BLACKRED(tmp, parent, field); \
RB_ROTATE_RIGHT(head, parent, tmp, field);\
tmp = RB_LEFT(parent, field); \
} \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
if (RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
struct type *oright; \
if ((oright = RB_RIGHT(tmp, field)) \
!= NULL) \
RB_COLOR(oright, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_LEFT(head, tmp, oright, field);\
tmp = RB_LEFT(parent, field); \
} \
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
RB_COLOR(parent, field) = RB_BLACK; \
if (RB_LEFT(tmp, field)) \
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
RB_ROTATE_RIGHT(head, parent, tmp, field);\
elm = RB_ROOT(head); \
break; \
} \
} \
} \
if (elm) \
RB_COLOR(elm, field) = RB_BLACK; \
} \
\
attr struct type * \
name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *child, *parent, *old = elm; \
int color; \
if (RB_LEFT(elm, field) == NULL) \
child = RB_RIGHT(elm, field); \
else if (RB_RIGHT(elm, field) == NULL) \
child = RB_LEFT(elm, field); \
else { \
struct type *left; \
elm = RB_RIGHT(elm, field); \
while ((left = RB_LEFT(elm, field)) != NULL) \
elm = left; \
child = RB_RIGHT(elm, field); \
parent = RB_PARENT(elm, field); \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = child; \
if (RB_PARENT(elm, field) == old) \
parent = elm; \
(elm)->field = (old)->field; \
if (RB_PARENT(old, field)) { \
if (RB_LEFT(RB_PARENT(old, field), field) == old)\
RB_LEFT(RB_PARENT(old, field), field) = elm;\
else \
RB_RIGHT(RB_PARENT(old, field), field) = elm;\
RB_AUGMENT(RB_PARENT(old, field)); \
} else \
RB_ROOT(head) = elm; \
RB_PARENT(RB_LEFT(old, field), field) = elm; \
if (RB_RIGHT(old, field)) \
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
if (parent) { \
left = parent; \
do { \
RB_AUGMENT(left); \
} while ((left = RB_PARENT(left, field)) != NULL); \
} \
goto color; \
} \
parent = RB_PARENT(elm, field); \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = child; \
color: \
if (color == RB_BLACK) \
name##_RB_REMOVE_COLOR(head, parent, child); \
return (old); \
} \
\
/* Inserts a node into the RB tree */ \
attr struct type * \
name##_RB_INSERT(struct name *head, struct type *elm) \
{ \
struct type *tmp; \
struct type *parent = NULL; \
int comp = 0; \
tmp = RB_ROOT(head); \
while (tmp) { \
parent = tmp; \
comp = (cmp)(elm, parent); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
RB_SET(elm, parent, field); \
if (parent != NULL) { \
if (comp < 0) \
RB_LEFT(parent, field) = elm; \
else \
RB_RIGHT(parent, field) = elm; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = elm; \
name##_RB_INSERT_COLOR(head, elm); \
return (NULL); \
} \
\
/* Finds the node with the same key as elm */ \
attr struct type * \
name##_RB_FIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (NULL); \
} \
\
/* Finds the first node greater than or equal to the search key */ \
attr struct type * \
name##_RB_NFIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *res = NULL; \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) { \
res = tmp; \
tmp = RB_LEFT(tmp, field); \
} \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (res); \
} \
\
/* ARGSUSED */ \
attr struct type * \
name##_RB_NEXT(struct type *elm) \
{ \
if (RB_RIGHT(elm, field)) { \
elm = RB_RIGHT(elm, field); \
while (RB_LEFT(elm, field)) \
elm = RB_LEFT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
} \
\
/* ARGSUSED */ \
attr struct type * \
name##_RB_PREV(struct type *elm) \
{ \
if (RB_LEFT(elm, field)) { \
elm = RB_LEFT(elm, field); \
while (RB_RIGHT(elm, field)) \
elm = RB_RIGHT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
} \
\
attr struct type * \
name##_RB_MINMAX(struct name *head, int val) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *parent = NULL; \
while (tmp) { \
parent = tmp; \
if (val < 0) \
tmp = RB_LEFT(tmp, field); \
else \
tmp = RB_RIGHT(tmp, field); \
} \
return (parent); \
}
#define RB_NEGINF -1
#define RB_INF 1
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
#define RB_PREV(name, x, y) name##_RB_PREV(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
#define RB_FOREACH(x, name, head) \
for ((x) = RB_MIN(name, head); \
(x) != NULL; \
(x) = name##_RB_NEXT(x))
#define RB_FOREACH_REVERSE(x, name, head) \
for ((x) = RB_MAX(name, head); \
(x) != NULL; \
(x) = name##_RB_PREV(x))
#endif /* _SYS_TREE_H_ */

View File

@ -0,0 +1,55 @@
/*
* 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
DECLARE_CLASS_TYPE(box);
/** Gets the type of a box */
#define RTGUI_BOX_TYPE (RTGUI_TYPE(box))
/** 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_object parent;
rt_uint16_t orient;
rt_uint16_t border_size;
struct rtgui_container *container;
};
typedef struct rtgui_box rtgui_box_t;
struct rtgui_box *rtgui_box_create(int orientation, int border_size);
void rtgui_box_destroy(struct rtgui_box *box);
void rtgui_box_layout(rtgui_box_t *box);
void rtgui_box_layout_rect(rtgui_box_t *box, struct rtgui_rect *rect);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,70 @@
/*
* 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>
#include <rtgui/widgets/box.h>
#ifdef __cplusplus
extern "C" {
#endif
DECLARE_CLASS_TYPE(container);
/** Gets the type of a container */
#define RTGUI_CONTAINER_TYPE (RTGUI_TYPE(container))
/** Casts the object to an rtgui_container */
#define RTGUI_CONTAINER(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_CONTAINER_TYPE, rtgui_container_t))
/** Checks if the object is an rtgui_container */
#define RTGUI_IS_CONTAINER(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_CONTAINER_TYPE))
/*
* the container widget
*/
struct rtgui_container
{
struct rtgui_widget parent;
/* layout box */
struct rtgui_box *layout_box;
rtgui_list_t children;
};
typedef struct rtgui_container rtgui_container_t;
rtgui_container_t *rtgui_container_create(void);
void rtgui_container_destroy(rtgui_container_t *container);
rt_bool_t rtgui_container_event_handler(struct rtgui_object *widget, struct rtgui_event *event);
/* set layout box */
void rtgui_container_set_box(struct rtgui_container *container, struct rtgui_box *box);
void rtgui_container_layout(struct rtgui_container *container);
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(struct rtgui_object *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);
struct rtgui_object* rtgui_container_get_object(struct rtgui_container *container, rt_uint32_t id);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,38 @@
/*
* 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/widget.h>
DECLARE_CLASS_TYPE(wintitle);
/** Gets the type of a title */
#define RTGUI_WINTITLE_TYPE (RTGUI_TYPE(wintitle))
/** 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_widget parent;
};
typedef struct rtgui_wintitle rtgui_wintitle_t;
rtgui_wintitle_t *rtgui_wintitle_create(struct rtgui_win *window);
void rtgui_wintitle_destroy(rtgui_wintitle_t *wintitle);
rt_bool_t rtgui_wintile_event_handler(struct rtgui_object *object, rtgui_event_t *event);
#endif

View File

@ -0,0 +1,209 @@
/*
* File : widget.h
* This file is part of RT-Thread GUI
* COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2009-10-04 Bernard first version
*/
#ifndef __RTGUI_WIDGET_H__
#define __RTGUI_WIDGET_H__
#include <rtgui/rtgui.h>
#include <rtgui/list.h>
#include <rtgui/region.h>
#include <rtgui/event.h>
#include <rtgui/color.h>
#include <rtgui/font.h>
#ifdef __cplusplus
extern "C" {
#endif
#define RTGUI_WIDGET_FLAG_DEFAULT 0x0000
#define RTGUI_WIDGET_FLAG_SHOWN 0x0001
#define RTGUI_WIDGET_FLAG_DISABLE 0x0002
#define RTGUI_WIDGET_FLAG_FOCUS 0x0004
#define RTGUI_WIDGET_FLAG_TRANSPARENT 0x0008
#define RTGUI_WIDGET_FLAG_FOCUSABLE 0x0010
#define RTGUI_WIDGET_FLAG_DC_VISIBLE 0x0100
#define RTGUI_WIDGET_FLAG_IN_ANIM 0x0200
/* rtgui widget attribute */
#define RTGUI_WIDGET_FOREGROUND(w) (RTGUI_WIDGET(w)->gc.foreground)
#define RTGUI_WIDGET_BACKGROUND(w) (RTGUI_WIDGET(w)->gc.background)
#define RTGUI_WIDGET_TEXTALIGN(w) (RTGUI_WIDGET(w)->gc.textalign)
#define RTGUI_WIDGET_FONT(w) (RTGUI_WIDGET(w)->gc.font)
#define RTGUI_WIDGET_FLAG(w) (RTGUI_WIDGET(w)->flag)
#define RTGUI_WIDGET_ALIGN(w) (RTGUI_WIDGET(w)->align)
#define RTGUI_WIDGET_BORDER(w) (RTGUI_WIDGET(w)->border)
#define RTGUI_WIDGET_BORDER_STYLE(w) (RTGUI_WIDGET(w)->border_style)
#define RTGUI_WIDGET_UNHIDE(w) RTGUI_WIDGET_FLAG(w) |= RTGUI_WIDGET_FLAG_SHOWN
#define RTGUI_WIDGET_HIDE(w) RTGUI_WIDGET_FLAG(w) &= ~RTGUI_WIDGET_FLAG_SHOWN
#define RTGUI_WIDGET_IS_HIDE(w) (!(RTGUI_WIDGET_FLAG(w) & RTGUI_WIDGET_FLAG_SHOWN))
#define RTGUI_WIDGET_ENABLE(w) RTGUI_WIDGET_FLAG(w) &= ~RTGUI_WIDGET_FLAG_DISABLE
#define RTGUI_WIDGET_DISABLE(w) RTGUI_WIDGET_FLAG(w) |= RTGUI_WIDGET_FLAG_DISABLE
#define RTGUI_WIDGET_IS_ENABLE(w) (!((RTGUI_WIDGET_FLAG(w) & RTGUI_WIDGET_FLAG_DISABLE)))
#define RTGUI_WIDGET_UNFOCUS(w) RTGUI_WIDGET_FLAG(w) &= ~RTGUI_WIDGET_FLAG_FOCUS
#define RTGUI_WIDGET_FOCUS(w) RTGUI_WIDGET_FLAG(w) |= RTGUI_WIDGET_FLAG_FOCUS
#define RTGUI_WIDGET_IS_FOCUSED(w) (RTGUI_WIDGET_FLAG(w) & RTGUI_WIDGET_FLAG_FOCUS)
#define RTGUI_WIDGET_IS_FOCUSABLE(w) (RTGUI_WIDGET_FLAG(w) & RTGUI_WIDGET_FLAG_FOCUSABLE)
#define RTGUI_WIDGET_SET_UNFOCUSABLE(w) RTGUI_WIDGET_FLAG(w) &= ~RTGUI_WIDGET_FLAG_FOCUSABLE
#define RTGUI_WIDGET_IS_DC_VISIBLE(w) (RTGUI_WIDGET_FLAG(w) & RTGUI_WIDGET_FLAG_DC_VISIBLE)
#define RTGUI_WIDGET_DC_SET_VISIBLE(w) RTGUI_WIDGET_FLAG(w) |= RTGUI_WIDGET_FLAG_DC_VISIBLE
#define RTGUI_WIDGET_DC_SET_UNVISIBLE(w) RTGUI_WIDGET_FLAG(w) &= ~RTGUI_WIDGET_FLAG_DC_VISIBLE
#define RTGUI_WIDGET_DC(w) ((struct rtgui_dc*)&((w)->dc_type))
DECLARE_CLASS_TYPE(widget);
/** Gets the type of a widget */
#define RTGUI_WIDGET_TYPE (RTGUI_TYPE(widget))
/** Casts the object to a rtgui_widget */
#define RTGUI_WIDGET(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_WIDGET_TYPE, rtgui_widget_t))
/** Check if the object is a rtgui_widget */
#define RTGUI_IS_WIDGET(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_WIDGET_TYPE))
/*
* the base widget object
*/
struct rtgui_widget
{
/* inherit from rtgui_object */
struct rtgui_object object;
/* the widget that contains this widget */
struct rtgui_widget *parent;
/* the window that contains this widget */
struct rtgui_win *toplevel;
/* the widget children and sibling */
rtgui_list_t sibling;
/* widget flag */
rt_int32_t flag;
/* hardware device context */
rt_uint32_t dc_type;
const struct rtgui_dc_engine *dc_engine;
/* the graphic context of widget */
rtgui_gc_t gc;
/* the widget extent */
rtgui_rect_t extent;
/* minimal width and height of widget */
rt_int16_t min_width, min_height;
/* widget align */
rt_int32_t align;
rt_uint16_t border;
rt_uint16_t border_style;
/* the rect clip */
rtgui_region_t clip;
/* call back */
rt_bool_t (*on_focus_in)(struct rtgui_object *widget, struct rtgui_event *event);
rt_bool_t (*on_focus_out)(struct rtgui_object *widget, struct rtgui_event *event);
rt_bool_t (*on_paint)(struct rtgui_object *widget, struct rtgui_event *event);
/* user private data */
rt_uint32_t user_data;
};
typedef struct rtgui_widget rtgui_widget_t;
rtgui_widget_t *rtgui_widget_create(const rtgui_type_t *widget_type);
void rtgui_widget_destroy(rtgui_widget_t *widget);
rt_bool_t rtgui_widget_event_handler(struct rtgui_object *object, rtgui_event_t *event);
/* focus and unfocus */
void rtgui_widget_focus(rtgui_widget_t *widget);
void rtgui_widget_unfocus(rtgui_widget_t *widget);
/* event handler for each command */
void rtgui_widget_set_onfocus(rtgui_widget_t *widget, rtgui_event_handler_ptr handler);
void rtgui_widget_set_onunfocus(rtgui_widget_t *widget, rtgui_event_handler_ptr handler);
void rtgui_widget_set_onpaint(rtgui_widget_t *widget, rtgui_event_handler_ptr handler);
/* get and set rect of widget */
void rtgui_widget_get_rect(rtgui_widget_t *widget, rtgui_rect_t *rect);
void rtgui_widget_set_border(rtgui_widget_t *widget, rt_uint32_t style);
void rtgui_widget_set_rect(rtgui_widget_t *widget, const rtgui_rect_t *rect);
void rtgui_widget_set_rectangle(rtgui_widget_t *widget, int x, int y, int width, int height);
void rtgui_widget_get_extent(rtgui_widget_t *widget, rtgui_rect_t *rect);
void rtgui_widget_set_minsize(rtgui_widget_t *widget, int width, int height);
void rtgui_widget_set_minwidth(rtgui_widget_t *widget, int width);
void rtgui_widget_set_minheight(rtgui_widget_t *widget, int height);
void rtgui_widget_set_parent(rtgui_widget_t *widget, rtgui_widget_t *parent);
/* get the physical position of a logic point on widget */
void rtgui_widget_point_to_device(rtgui_widget_t *widget, rtgui_point_t *point);
/* get the physical position of a logic rect on widget */
void rtgui_widget_rect_to_device(rtgui_widget_t *widget, rtgui_rect_t *rect);
/* get the logic position of a physical point on widget */
void rtgui_widget_point_to_logic(rtgui_widget_t *widget, rtgui_point_t *point);
/* get the logic position of a physical rect on widget */
void rtgui_widget_rect_to_logic(rtgui_widget_t *widget, rtgui_rect_t *rect);
void rtgui_widget_clip_parent(rtgui_widget_t *widget);
void rtgui_widget_clip_return(rtgui_widget_t *widget);
/* move widget and its children to a logic point */
void rtgui_widget_move_to_logic(rtgui_widget_t *widget, int dx, int dy);
/* update the clip info of widget */
void rtgui_widget_update_clip(rtgui_widget_t *widget);
/* get the toplevel widget of widget */
struct rtgui_win *rtgui_widget_get_toplevel(rtgui_widget_t *widget);
rt_bool_t rtgui_widget_onupdate_toplvl(struct rtgui_object *object, struct rtgui_event *event);
void rtgui_widget_show(rtgui_widget_t *widget);
rt_bool_t rtgui_widget_onshow(struct rtgui_object *object, struct rtgui_event *event);
void rtgui_widget_hide(rtgui_widget_t *widget);
rt_bool_t rtgui_widget_onhide(struct rtgui_object *object, struct rtgui_event *event);
void rtgui_widget_update(rtgui_widget_t *widget);
rt_bool_t rtgui_widget_onpaint(struct rtgui_object *object, struct rtgui_event *event);
/* get parent color */
rtgui_color_t rtgui_widget_get_parent_foreground(rtgui_widget_t *widget);
rtgui_color_t rtgui_widget_get_parent_background(rtgui_widget_t *widget);
/* get the next sibling of widget */
rtgui_widget_t *rtgui_widget_get_next_sibling(rtgui_widget_t *widget);
/* get the prev sibling of widget */
rtgui_widget_t *rtgui_widget_get_prev_sibling(rtgui_widget_t *widget);
rt_bool_t rtgui_widget_is_in_animation(rtgui_widget_t *widget);
/* dump widget information */
void rtgui_widget_dump(rtgui_widget_t *widget);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,191 @@
/*
* File : window.h
* This file is part of RTGUI in 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-04 Bernard first version
* 2010-05-03 Bernard add win close function
*/
#ifndef __RTGUI_WINDOW_H__
#define __RTGUI_WINDOW_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <rtgui/rtgui.h>
#include <rtgui/list.h>
#include <rtgui/dc.h>
#include <rtgui/widgets/widget.h>
#include <rtgui/widgets/box.h>
DECLARE_CLASS_TYPE(win);
/** Gets the type of a win */
#define RTGUI_WIN_TYPE (RTGUI_TYPE(win))
/** Casts the object to an rtgui_win */
#define RTGUI_WIN(obj) (RTGUI_OBJECT_CAST((obj), RTGUI_WIN_TYPE, rtgui_win_t))
/** Checks if the object is an rtgui_win */
#define RTGUI_IS_WIN(obj) (RTGUI_OBJECT_CHECK_TYPE((obj), RTGUI_WIN_TYPE))
#define RTGUI_WIN_STYLE_NO_FOCUS 0x0001 /* non-focused window */
#define RTGUI_WIN_STYLE_NO_TITLE 0x0002 /* no title window */
#define RTGUI_WIN_STYLE_NO_BORDER 0x0004 /* no border window */
#define RTGUI_WIN_STYLE_CLOSEBOX 0x0008 /* window has the close button */
#define RTGUI_WIN_STYLE_MINIBOX 0x0010 /* window has the mini button */
#define RTGUI_WIN_STYLE_DESTROY_ON_CLOSE 0x0020 /* window is destroyed when closed */
#define RTGUI_WIN_STYLE_ONTOP 0x0040 /* window is in the top layer */
#define RTGUI_WIN_STYLE_ONBTM 0x0080 /* window is in the bottom layer */
#define RTGUI_WIN_STYLE_MAINWIN 0x0106 /* window is a main window */
#define RTGUI_WIN_STYLE_DEFAULT (RTGUI_WIN_STYLE_CLOSEBOX | RTGUI_WIN_STYLE_MINIBOX)
#define WINTITLE_HEIGHT 20
#define WINTITLE_CB_WIDTH 16
#define WINTITLE_CB_HEIGHT 16
#define WINTITLE_BORDER_SIZE 2
enum rtgui_win_flag
{
RTGUI_WIN_FLAG_INIT = 0x00, /* init state */
RTGUI_WIN_FLAG_MODAL = 0x01, /* modal mode window */
RTGUI_WIN_FLAG_CLOSED = 0x02, /* window is closed */
RTGUI_WIN_FLAG_ACTIVATE = 0x04, /* window is activated */
RTGUI_WIN_FLAG_UNDER_MODAL = 0x08, /* window is under modal
show(modaled by other) */
RTGUI_WIN_FLAG_CONNECTED = 0x10, /* connected to server */
/* window is event_key dispatcher(dispatch it to the focused widget in
* current window) _and_ a key handler(it should be able to handle keys
* such as ESC). Both of dispatching and handling are in the same
* function(rtgui_win_event_handler). So we have to distinguish between the
* two modes.
*
* If this flag is set, we are in key-handling mode.
*/
RTGUI_WIN_FLAG_HANDLE_KEY = 0x20,
RTGUI_WIN_FLAG_CB_PRESSED = 0x40,
};
struct rtgui_win
{
/* inherit from container */
rtgui_container_t parent;
/* drawing count */
rt_base_t drawing;
/* parent window. RT_NULL if the window is a top level window */
struct rtgui_win *parent_window;
struct rtgui_region outer_clip;
struct rtgui_rect outer_extent;
/* the widget that will grab the focus in current window */
struct rtgui_widget *focused_widget;
/* which app I belong */
struct rtgui_app *app;
/* window style */
rt_uint16_t style;
/* window state flag */
enum rtgui_win_flag flag;
rtgui_modal_code_t modal_code;
/* last mouse event handled widget */
rtgui_widget_t *last_mevent_widget;
/* window title */
char *title;
struct rtgui_wintitle *_title_wgt;
/* call back */
rt_bool_t (*on_activate)(struct rtgui_object *widget, struct rtgui_event *event);
rt_bool_t (*on_deactivate)(struct rtgui_object *widget, struct rtgui_event *event);
rt_bool_t (*on_close)(struct rtgui_object *widget, struct rtgui_event *event);
/* the key is sent to the focused widget by default. If the focused widget
* and all of it's parents didn't handle the key event, it will be handled
* by @func on_key
*
* If you want to handle key event on your own, it's better to overload
* this function other than handle EVENT_KBD in event_handler.
*/
rt_bool_t (*on_key)(struct rtgui_object *widget, struct rtgui_event *event);
/* reserved user data */
void *user_data;
/* Private data. */
rt_base_t (*_do_show)(struct rtgui_win *win);
};
rtgui_win_t *rtgui_win_create(struct rtgui_win *parent_window, const char *title,
rtgui_rect_t *rect, rt_uint16_t style);
rtgui_win_t *rtgui_mainwin_create(struct rtgui_win *parent_window, const char *title, rt_uint16_t style);
void rtgui_win_destroy(rtgui_win_t *win);
int rtgui_win_init(struct rtgui_win *win, struct rtgui_win *parent_window,
const char *title,
rtgui_rect_t *rect,
rt_uint16_t style);
int rtgui_win_fini(struct rtgui_win* win);
/** Close window.
*
* @param win the window you want to close
*
* @return RT_TRUE if the window is closed. RT_FALSE if not. If the onclose
* callback returns RT_FALSE, the window won't be closed.
*
* \sa rtgui_win_set_onclose .
*/
rt_bool_t rtgui_win_close(struct rtgui_win *win);
rt_base_t rtgui_win_show(struct rtgui_win *win, rt_bool_t is_modal);
rt_base_t rtgui_win_do_show(struct rtgui_win *win);
rt_base_t rtgui_win_enter_modal(struct rtgui_win *win);
void rtgui_win_hide(rtgui_win_t *win);
void rtgui_win_end_modal(rtgui_win_t *win, rtgui_modal_code_t modal_code);
rt_err_t rtgui_win_activate(struct rtgui_win *win);
rt_bool_t rtgui_win_is_activated(struct rtgui_win *win);
void rtgui_win_move(struct rtgui_win *win, int x, int y);
/* reset extent of window */
void rtgui_win_set_rect(rtgui_win_t *win, rtgui_rect_t *rect);
void rtgui_win_update_clip(struct rtgui_win *win);
void rtgui_win_set_onactivate(rtgui_win_t *win, rtgui_event_handler_ptr handler);
void rtgui_win_set_ondeactivate(rtgui_win_t *win, rtgui_event_handler_ptr handler);
void rtgui_win_set_onclose(rtgui_win_t *win, rtgui_event_handler_ptr handler);
void rtgui_win_set_onkey(rtgui_win_t *win, rtgui_event_handler_ptr handler);
rt_bool_t rtgui_win_event_handler(struct rtgui_object *win, struct rtgui_event *event);
void rtgui_win_event_loop(rtgui_win_t *wnd);
void rtgui_win_set_title(rtgui_win_t *win, const char *title);
char *rtgui_win_get_title(rtgui_win_t *win);
struct rtgui_dc *rtgui_win_get_drawing(rtgui_win_t * win);
struct rtgui_win* rtgui_win_get_topmost_shown(void);
struct rtgui_win* rtgui_win_get_next_shown(void);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,297 @@
/*
* 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>
#ifdef RTGUI_USING_FONT16
const 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 =
{
(const rt_uint8_t *)asc16_font, /* bmp */
RT_NULL, /* each character width, NULL for fixed font */
RT_NULL, /* offset for each character */
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 */
};
#endif

1123
components/gui/src/blit.c Normal file

File diff suppressed because it is too large Load Diff

300
components/gui/src/box.c Normal file
View File

@ -0,0 +1,300 @@
/*
* 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_object_set_event_handler(RTGUI_OBJECT(box), RT_NULL);
/* set proper of control */
box->orient = RTGUI_HORIZONTAL;
box->border_size = RTGUI_BORDER_DEFAULT_WIDTH;
box->container = RT_NULL;
}
DEFINE_CLASS_TYPE(box, "box",
RTGUI_PARENT_TYPE(object),
_rtgui_box_constructor,
RT_NULL,
sizeof(struct rtgui_box));
struct rtgui_box *rtgui_box_create(int orientation, int border_size)
{
struct rtgui_box *box;
box = (struct rtgui_box *) rtgui_object_create(RTGUI_BOX_TYPE);
if (box != RT_NULL)
{
box->orient = orientation;
box->border_size = border_size;
}
return box;
}
RTM_EXPORT(rtgui_box_create);
void rtgui_box_destroy(struct rtgui_box *box)
{
rtgui_object_destroy(RTGUI_OBJECT(box));
}
RTM_EXPORT(rtgui_box_destroy);
static void rtgui_box_layout_vertical(struct rtgui_box *box, struct rtgui_rect *extent)
{
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 = box->border_size;
space_height = 0;
rtgui_list_foreach(node, &(box->container->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->min_height;
}
total_height += box->border_size;
}
/* calculate the height for each spaces */
if (space_count != 0 && rtgui_rect_height(*extent) > total_height)
{
space_height = (rtgui_rect_height(*extent) - total_height) / space_count;
}
/* init (x, y) and box width */
next_x = extent->x1 + box->border_size;
next_y = extent->y1 + box->border_size;
box_width = rtgui_rect_width(*extent) - box->border_size * 2;
/* layout each widget */
rtgui_list_foreach(node, &(box->container->children))
{
struct rtgui_rect *rect;
rtgui_widget_t *widget = rtgui_list_entry(node, struct rtgui_widget, sibling);
/* get extent of widget */
rect = &(widget->extent);
/* reset rect */
rtgui_rect_init(rect, 0, 0, widget->min_width, widget->min_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;
RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget),
&size_event.parent);
/* point to next height */
next_y = rect->y2 + box->border_size;
}
}
static void rtgui_box_layout_horizontal(struct rtgui_box *box, struct rtgui_rect *extent)
{
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, &(box->container->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->min_width;
}
total_width += box->border_size;
}
if (space_count != 0)
{
/* calculate the height for each spaces */
space_width = (rtgui_rect_width(*extent) - total_width) / space_count;
}
/* init (x, y) and box height */
next_x = extent->x1 + box->border_size;
next_y = extent->y1 + box->border_size;
box_height = rtgui_rect_height(*extent) - (box->border_size << 1);
/* layout each widget */
rtgui_list_foreach(node, &(box->container->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->min_width;
rect->y2 = widget->min_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;
RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget),
&size_event.parent);
/* point to next width */
next_x = rect->x2 + box->border_size;
}
}
void rtgui_box_layout(rtgui_box_t *box)
{
struct rtgui_rect extent;
RT_ASSERT(box != RT_NULL);
if (box->container == RT_NULL) return;
rtgui_widget_get_extent(RTGUI_WIDGET(box->container), &extent);
if (box->orient & RTGUI_VERTICAL)
{
rtgui_box_layout_vertical(box, &extent);
}
else
{
rtgui_box_layout_horizontal(box, &extent);
}
/* update box and its children clip */
if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box->container)))
{
rtgui_widget_update_clip(RTGUI_WIDGET(box->container));
}
}
RTM_EXPORT(rtgui_box_layout);
void rtgui_box_layout_rect(rtgui_box_t *box, struct rtgui_rect *rect)
{
RT_ASSERT(box != RT_NULL);
if (box->container == RT_NULL) return;
if (box->orient & RTGUI_VERTICAL)
{
rtgui_box_layout_vertical(box, rect);
}
else
{
rtgui_box_layout_horizontal(box, rect);
}
/* update box and its children clip */
if (!RTGUI_WIDGET_IS_HIDE(RTGUI_WIDGET(box->container)))
{
rtgui_widget_update_clip(RTGUI_WIDGET(box->container));
}
}
RTM_EXPORT(rtgui_box_layout_rect);

View File

@ -0,0 +1,61 @@
/*
* 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(0xfc, 0xfc, 0xfc);
const rtgui_color_t dark_grey = RTGUI_RGB(0x7f, 0x7f, 0x7f);
const rtgui_color_t light_grey = RTGUI_RGB(0xc0, 0xc0, 0xc0);
const static rt_uint8_t pixel_bits_table[] =
{
1, /* mono */
2, /* 4 level for gray */
4, /* 16 level for gray */
8, /* RGB332 */
12, /* RGB444 */
16, /* RGB565 */
16, /* BGR565 */
18, /* RGB666 */
24, /* RGB888 */
32, /* ARGB888 */
};
rt_uint8_t rtgui_color_get_bits(rt_uint8_t pixel_format)
{
if (pixel_format <= RTGRAPHIC_PIXEL_FORMAT_ARGB888)
return pixel_bits_table[pixel_format];
/* use 32 as the default */
return 32;
}
RTM_EXPORT(rtgui_color_get_bits);
rt_uint8_t rtgui_color_get_bpp(rt_uint8_t pixel_format)
{
rt_uint8_t bpp = 4;
if (pixel_format <= RTGRAPHIC_PIXEL_FORMAT_ARGB888)
{
bpp = _UI_BITBYTES(pixel_bits_table[pixel_format]);
}
return bpp;
}
RTM_EXPORT(rtgui_color_get_bpp);

View File

@ -0,0 +1,368 @@
/*
* 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
* 2010-09-24 Bernard fix container destroy issue
*/
#include <rtgui/dc.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/rtgui_app.h>
#include <rtgui/widgets/container.h>
#include <rtgui/widgets/window.h>
static void _rtgui_container_constructor(rtgui_container_t *container)
{
/* init container */
rtgui_object_set_event_handler(RTGUI_OBJECT(container),
rtgui_container_event_handler);
rtgui_list_init(&(container->children));
container->layout_box = RT_NULL;
RTGUI_WIDGET(container)->flag |= RTGUI_WIDGET_FLAG_FOCUSABLE;
}
static void _rtgui_container_destructor(rtgui_container_t *container)
{
rtgui_container_destroy_children(container);
if (container->layout_box != RT_NULL)
rtgui_object_destroy(RTGUI_OBJECT(container->layout_box));
}
DEFINE_CLASS_TYPE(container, "container",
RTGUI_PARENT_TYPE(widget),
_rtgui_container_constructor,
_rtgui_container_destructor,
sizeof(struct rtgui_container));
RTM_EXPORT(_rtgui_container);
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 (RTGUI_OBJECT(w)->event_handler &&
RTGUI_OBJECT(w)->event_handler(RTGUI_OBJECT(w), event) == RT_TRUE)
return RT_TRUE;
}
return RT_FALSE;
}
RTM_EXPORT(rtgui_container_dispatch_event);
/* broadcast means that the return value of event handlers will be ignored. The
* events will always reach every child.*/
rt_bool_t rtgui_container_broadcast_event(struct rtgui_container *container, struct rtgui_event *event)
{
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_OBJECT(w)->event_handler)
RTGUI_OBJECT(w)->event_handler(RTGUI_OBJECT(w), event);
}
return RT_FALSE;
}
RTM_EXPORT(rtgui_container_broadcast_event);
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;
struct rtgui_widget *old_focus;
old_focus = RTGUI_WIDGET(container)->toplevel->focused_widget;
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 ((old_focus != w) && RTGUI_WIDGET_IS_FOCUSABLE(w))
rtgui_widget_focus(w);
if (RTGUI_OBJECT(w)->event_handler &&
RTGUI_OBJECT(w)->event_handler(RTGUI_OBJECT(w),
(rtgui_event_t *)event) == RT_TRUE)
return RT_TRUE;
}
}
return RT_FALSE;
}
RTM_EXPORT(rtgui_container_dispatch_mouse_event);
rt_bool_t rtgui_container_event_handler(struct rtgui_object *object, struct rtgui_event *event)
{
struct rtgui_container *container;
struct rtgui_widget *widget;
RT_ASSERT(object != RT_NULL);
RT_ASSERT(event != RT_NULL);
container = RTGUI_CONTAINER(object);
widget = RTGUI_WIDGET(object);
switch (event->type)
{
case RTGUI_EVENT_PAINT:
{
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 container with background */
rtgui_dc_fill_rect(dc, &rect);
/* paint on each child */
rtgui_container_dispatch_event(container, event);
rtgui_dc_end_drawing(dc);
}
break;
case RTGUI_EVENT_KBD:
break;
case RTGUI_EVENT_MOUSE_BUTTON:
case RTGUI_EVENT_MOUSE_MOTION:
/* handle in child widget */
return rtgui_container_dispatch_mouse_event(container,
(struct rtgui_event_mouse *)event);
case RTGUI_EVENT_SHOW:
rtgui_widget_onshow(RTGUI_OBJECT(container), event);
rtgui_container_dispatch_event(container, event);
break;
case RTGUI_EVENT_HIDE:
rtgui_widget_onhide(RTGUI_OBJECT(container), event);
rtgui_container_dispatch_event(container, event);
break;
case RTGUI_EVENT_COMMAND:
rtgui_container_dispatch_event(container, event);
break;
case RTGUI_EVENT_UPDATE_TOPLVL:
/* call parent handler */
rtgui_widget_onupdate_toplvl(object, event);
/* update the children */
rtgui_container_broadcast_event(container, event);
break;
case RTGUI_EVENT_RESIZE:
/* re-layout container */
rtgui_container_layout(container);
break;
default:
/* call parent widget event handler */
return rtgui_widget_event_handler(RTGUI_OBJECT(widget), event);
}
return RT_FALSE;
}
RTM_EXPORT(rtgui_container_event_handler);
rtgui_container_t *rtgui_container_create(void)
{
struct rtgui_container *container;
/* allocate container */
container = (struct rtgui_container *) rtgui_widget_create(RTGUI_CONTAINER_TYPE);
return container;
}
RTM_EXPORT(rtgui_container_create);
void rtgui_container_destroy(rtgui_container_t *container)
{
rtgui_widget_destroy(RTGUI_WIDGET(container));
}
RTM_EXPORT(rtgui_container_destroy);
/*
* 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);
if (child->parent == RTGUI_WIDGET(container))
return;
RT_ASSERT(child->parent == 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)
{
struct rtgui_win *toplevel;
struct rtgui_event_update_toplvl eup;
RTGUI_EVENT_UPDATE_TOPLVL_INIT(&eup);
eup.toplvl = RTGUI_WIDGET(container)->toplevel;
rtgui_object_handle(RTGUI_OBJECT(container), &eup.parent);
/* update window clip */
toplevel = RTGUI_WIDGET(container)->toplevel;
if ((toplevel->flag & RTGUI_WIN_FLAG_CONNECTED) &&
(RTGUI_WIDGET(toplevel)->flag & RTGUI_WIDGET_FLAG_SHOWN))
{
rtgui_win_update_clip(RTGUI_WIN(RTGUI_WIDGET(container)->toplevel));
}
}
}
RTM_EXPORT(rtgui_container_add_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);
rtgui_widget_unfocus(child);
/* 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;
/* update window clip */
if (RTGUI_WIDGET(container)->toplevel)
{
rtgui_win_update_clip(RTGUI_WIN(RTGUI_WIDGET(container)->toplevel));
}
}
RTM_EXPORT(rtgui_container_remove_child);
/* 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))
{
/* break parent firstly */
child->parent = RT_NULL;
/* destroy children of child */
rtgui_container_destroy_children(RTGUI_CONTAINER(child));
}
/* remove widget from parent's children list */
rtgui_list_remove(&(container->children), &(child->sibling));
/* set parent and toplevel widget */
child->parent = RT_NULL;
/* destroy object and remove from parent */
rtgui_object_destroy(RTGUI_OBJECT(child));
node = container->children.next;
}
container->children.next = RT_NULL;
/* update widget clip */
rtgui_win_update_clip(RTGUI_WIN(RTGUI_WIDGET(container)->toplevel));
}
RTM_EXPORT(rtgui_container_destroy_children);
rtgui_widget_t *rtgui_container_get_first_child(rtgui_container_t *container)
{
rtgui_widget_t *child = RT_NULL;
RT_ASSERT(container != RT_NULL);
if (container->children.next != RT_NULL)
{
child = rtgui_list_entry(container->children.next, rtgui_widget_t, sibling);
}
return child;
}
RTM_EXPORT(rtgui_container_get_first_child);
void rtgui_container_set_box(rtgui_container_t *container, struct rtgui_box *box)
{
if (container == RT_NULL || box == RT_NULL)
return;
container->layout_box = box;
box->container = container;
}
RTM_EXPORT(rtgui_container_set_box);
void rtgui_container_layout(struct rtgui_container *container)
{
if (container == RT_NULL || container->layout_box == RT_NULL)
return;
rtgui_box_layout(container->layout_box);
}
RTM_EXPORT(rtgui_container_layout);
struct rtgui_object* rtgui_container_get_object(struct rtgui_container *container,
rt_uint32_t id)
{
struct rtgui_list_node *node;
rtgui_list_foreach(node, &(container->children))
{
struct rtgui_object *o;
o = RTGUI_OBJECT(rtgui_list_entry(node, struct rtgui_widget, sibling));
if (o->id == id)
return o;
if (RTGUI_IS_CONTAINER(o))
{
struct rtgui_object *obj;
obj = rtgui_container_get_object(RTGUI_CONTAINER(o), id);
if (obj)
return obj;
}
}
return RT_NULL;
}
RTM_EXPORT(rtgui_container_get_object);

1923
components/gui/src/dc.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,610 @@
/*
* 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/blit.h>
#include <rtgui/dc_hw.h>
#include <rtgui/color.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/dc_draw.h>
#include <string.h>
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_color_point(struct rtgui_dc *dc, int x, int y, rtgui_color_t color);
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_line(struct rtgui_dc *self, int x1, int x2, int y, rt_uint8_t *line_data);
static void rtgui_dc_buffer_blit(struct rtgui_dc *self, struct rtgui_point *dc_point,
struct rtgui_dc *dest, rtgui_rect_t *rect);
const struct rtgui_dc_engine dc_buffer_engine =
{
rtgui_dc_buffer_draw_point,
rtgui_dc_buffer_draw_color_point,
rtgui_dc_buffer_draw_vline,
rtgui_dc_buffer_draw_hline,
rtgui_dc_buffer_fill_rect,
rtgui_dc_buffer_blit_line,
rtgui_dc_buffer_blit,
rtgui_dc_buffer_fini,
};
#define _dc_get_pitch(dc) \
(dc->pitch)
#define _dc_get_pixel(dc, x, y) \
((dc)->pixel + (y) * (dc)->pitch + (x) * rtgui_color_get_bpp((dc)->pixel_format))
#define _dc_get_bits_per_pixel(dc) \
rtgui_color_get_bits(dc->pixel_format)
#define _hw_get_pixel(dst, x, y, type) \
(type *)((rt_uint8_t*)((dst)->framebuffer) + (y) * (dst)->pitch + (x) * _UI_BITBYTES((dst)->bits_per_pixel))
struct rtgui_dc *rtgui_dc_buffer_create(int w, int h)
{
rt_uint8_t pixel_format;
pixel_format = rtgui_graphic_driver_get_default()->pixel_format;
/* create a dc_buffer with hardware driver pixel format */
return rtgui_dc_buffer_create_pixformat(pixel_format, w, h);
}
RTM_EXPORT(rtgui_dc_buffer_create);
struct rtgui_dc *rtgui_dc_buffer_create_pixformat(rt_uint8_t pixel_format, int w, int h)
{
struct rtgui_dc_buffer *dc;
dc = (struct rtgui_dc_buffer *)rtgui_malloc(sizeof(struct rtgui_dc_buffer));
if (dc)
{
dc->parent.type = RTGUI_DC_BUFFER;
dc->parent.engine = &dc_buffer_engine;
dc->gc.foreground = default_foreground;
dc->gc.background = default_background;
dc->gc.font = rtgui_font_default();
dc->gc.textalign = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_TOP;
dc->pixel_format = pixel_format;
dc->width = w;
dc->height = h;
dc->pitch = w * rtgui_color_get_bpp(pixel_format);
dc->pixel = rtgui_malloc(h * dc->pitch);
if (!dc->pixel)
{
rtgui_free(dc);
return RT_NULL;
}
rt_memset(dc->pixel, 0, h * dc->pitch);
return &(dc->parent);
}
return RT_NULL;
}
RTM_EXPORT(rtgui_dc_buffer_create_pixformat);
struct rtgui_dc *rtgui_dc_buffer_create_from_dc(struct rtgui_dc* dc)
{
struct rtgui_dc_buffer *buffer;
if (dc == RT_NULL)
return RT_NULL;
if (dc->type == RTGUI_DC_BUFFER)
{
struct rtgui_dc_buffer *d = (struct rtgui_dc_buffer*) dc;
/* buffer clone */
buffer = (struct rtgui_dc_buffer*)rtgui_dc_buffer_create_pixformat(d->pixel_format,
d->width,
d->height);
if (buffer != RT_NULL)
{
rt_memcpy(buffer->pixel, d->pixel, d->pitch * d->height);
return RTGUI_DC(buffer);
}
}
return RT_NULL;
}
RTM_EXPORT(rtgui_dc_buffer_create_from_dc);
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;
}
RTM_EXPORT(rtgui_dc_buffer_get_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)
{
struct rtgui_dc_buffer *dst;
unsigned r, g, b, a;
dst = (struct rtgui_dc_buffer *)self;
/* does not draw point out of dc */
if ((x >= dst->width) || (y >= dst->height)) return;
if (x < 0 || y < 0) return;
r = RTGUI_RGB_R(dst->gc.foreground);
g = RTGUI_RGB_G(dst->gc.foreground);
b = RTGUI_RGB_B(dst->gc.foreground);
a = RTGUI_RGB_A(dst->gc.foreground);
switch (dst->pixel_format)
{
case RTGRAPHIC_PIXEL_FORMAT_RGB565:
DRAW_SETPIXELXY_RGB565(x, y);
break;
case RTGRAPHIC_PIXEL_FORMAT_BGR565:
DRAW_SETPIXELXY_BGR565(x, y);
break;
case RTGRAPHIC_PIXEL_FORMAT_RGB888:
DRAW_SETPIXELXY_RGB888(x, y);
break;
case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
DRAW_SETPIXELXY_ARGB8888(x, y);
break;
}
}
static void rtgui_dc_buffer_draw_color_point(struct rtgui_dc *self, int x, int y, rtgui_color_t color)
{
struct rtgui_dc_buffer *dst;
unsigned r, g, b, a;
dst = (struct rtgui_dc_buffer *)self;
/* does not draw point out of dc */
if ((x >= dst->width) || (y >= dst->height)) return;
if (x < 0 || y < 0) return;
r = RTGUI_RGB_R(color);
g = RTGUI_RGB_G(color);
b = RTGUI_RGB_B(color);
a = RTGUI_RGB_A(color);
switch (dst->pixel_format)
{
case RTGRAPHIC_PIXEL_FORMAT_RGB565:
DRAW_SETPIXELXY_RGB565(x, y);
break;
case RTGRAPHIC_PIXEL_FORMAT_BGR565:
DRAW_SETPIXELXY_BGR565(x, y);
break;
case RTGRAPHIC_PIXEL_FORMAT_RGB888:
DRAW_SETPIXELXY_RGB888(x, y);
break;
case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
DRAW_SETPIXELXY_ARGB8888(x, y);
break;
}
}
static void rtgui_dc_buffer_draw_vline(struct rtgui_dc *self, int x1, int y1, int y2)
{
struct rtgui_dc_buffer *dst;
unsigned r, g, b, a;
dst = (struct rtgui_dc_buffer *)self;
if (x1 < 0 || x1 >= dst->width) return;
if (y1 >= dst->height) return;
if (y1 < 0) y1 = 0;
if (y2 > dst->height) y2 = dst->height;
r = RTGUI_RGB_R(dst->gc.foreground);
g = RTGUI_RGB_G(dst->gc.foreground);
b = RTGUI_RGB_B(dst->gc.foreground);
a = RTGUI_RGB_A(dst->gc.foreground);
switch (dst->pixel_format)
{
case RTGRAPHIC_PIXEL_FORMAT_RGB565:
VLINE(rt_uint16_t, DRAW_SETPIXEL_RGB565, 0);
break;
case RTGRAPHIC_PIXEL_FORMAT_BGR565:
VLINE(rt_uint16_t, DRAW_SETPIXEL_BGR565, 0);
break;
case RTGRAPHIC_PIXEL_FORMAT_RGB888:
VLINE(rt_uint16_t, DRAW_SETPIXEL_RGB888, 0);
break;
case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
VLINE(rt_uint32_t, DRAW_SETPIXEL_ARGB8888, 0);
break;
}
}
static void rtgui_dc_buffer_draw_hline(struct rtgui_dc *self, int x1, int x2, int y1)
{
struct rtgui_dc_buffer *dst;
unsigned r, g, b, a;
dst = (struct rtgui_dc_buffer *)self;
/* parameter checking */
if (y1 < 0 || y1 >= dst->height) return;
if (x1 >= dst->width) return;
if (x1 < 0) x1 = 0;
if (x2 > dst->width) x2 = dst->width;
r = RTGUI_RGB_R(dst->gc.foreground);
g = RTGUI_RGB_G(dst->gc.foreground);
b = RTGUI_RGB_B(dst->gc.foreground);
a = RTGUI_RGB_A(dst->gc.foreground);
switch (dst->pixel_format)
{
case RTGRAPHIC_PIXEL_FORMAT_RGB565:
HLINE(rt_uint16_t, DRAW_SETPIXEL_RGB565, 0);
break;
case RTGRAPHIC_PIXEL_FORMAT_BGR565:
HLINE(rt_uint16_t, DRAW_SETPIXEL_BGR565, 0);
break;
case RTGRAPHIC_PIXEL_FORMAT_RGB888:
HLINE(rt_uint16_t, DRAW_SETPIXEL_RGB888, 0);
break;
case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
HLINE(rt_uint32_t, DRAW_SETPIXEL_ARGB8888, 0);
break;
}
}
static void rtgui_dc_buffer_fill_rect(struct rtgui_dc *self, struct rtgui_rect *dst_rect)
{
struct rtgui_dc_buffer *dst;
unsigned r, g, b, a;
rtgui_rect_t _r, *rect;
RT_ASSERT(self);
if (dst_rect == RT_NULL) rtgui_dc_get_rect(self, &_r);
else _r = *dst_rect;
dst = (struct rtgui_dc_buffer *)self;
if (_r.x2 < 0 || _r.y2 < 0) return; /* out of rect */
/* parameter checking */
if (_r.x1 >= dst->width)
return;
else if (_r.x1 < 0)
_r.x1 = 0;
if (_r.x2 > dst->width)
_r.x2 = dst->width;
if (_r.y1 >= dst->height)
return;
else if (_r.y1 < 0)
_r.y1 = 0;
if (_r.y2 > dst->height)
_r.y2 = dst->height;
rect = &_r;
r = RTGUI_RGB_R(dst->gc.background);
g = RTGUI_RGB_G(dst->gc.background);
b = RTGUI_RGB_B(dst->gc.background);
a = RTGUI_RGB_A(dst->gc.background);
switch (dst->pixel_format)
{
case RTGRAPHIC_PIXEL_FORMAT_RGB565:
FILLRECT(rt_uint16_t, DRAW_SETPIXEL_RGB565);
break;
case RTGRAPHIC_PIXEL_FORMAT_BGR565:
FILLRECT(rt_uint16_t, DRAW_SETPIXEL_BGR565);
break;
case RTGRAPHIC_PIXEL_FORMAT_RGB888:
FILLRECT(rt_uint32_t, DRAW_SETPIXEL_RGB888);
break;
case RTGRAPHIC_PIXEL_FORMAT_ARGB888:
FILLRECT(rt_uint32_t, DRAW_SETPIXEL_ARGB8888);
break;
}
}
/* blit a dc to another dc */
static void rtgui_dc_buffer_blit(struct rtgui_dc *self,
struct rtgui_point *dc_pt,
struct rtgui_dc *dest,
rtgui_rect_t *rect)
{
int pitch;
rt_uint16_t rect_width, rect_height;
struct rtgui_rect _rect, *dest_rect;
struct rtgui_point dc_point;
struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer *)self;
if (rtgui_dc_get_visible(dest) == RT_FALSE)
return;
/* use the (0,0) origin point */
if (dc_pt == RT_NULL)
dc_point = rtgui_empty_point;
else
{
dc_point = *dc_pt;
}
rtgui_dc_get_rect(dest, &_rect);
/* use the rect of dest dc */
if (rect == RT_NULL)
{
dest_rect = &_rect;
}
else
{
dest_rect = rect;
if (dest_rect->x1 >= _rect.x2 || dest_rect->y1 >= _rect.y2)
return;
if (dest_rect->x1 < 0)
{
if (-dest_rect->x1 >= dc->width)
return;
dc_point.x += -dest_rect->x1;
dest_rect->x1 = 0;
}
if (dest_rect->y1 < 0)
{
if (-dest_rect->y1 >= dc->height)
return;
dc_point.y += -dest_rect->y1;
dest_rect->y1 = 0;
}
if (dest_rect->x2 > _rect.x2)
dest_rect->x2 = _rect.x2;
if (dest_rect->y2 > _rect.y2)
dest_rect->y2 = _rect.y2;
}
if (dest_rect->x2 < dest_rect->x1 || dest_rect->y2 < dest_rect->y1) return;
if (dc_point.x >= dc->width || dc_point.y >= dc->height) return;
/* get the minimal width and height */
rect_width = _UI_MIN(rtgui_rect_width(*dest_rect), dc->width - dc_point.x);
rect_height = _UI_MIN(rtgui_rect_height(*dest_rect), dc->height - dc_point.y);
if ((dest->type == RTGUI_DC_HW) || (dest->type == RTGUI_DC_CLIENT))
{
int index;
rt_uint8_t *line_ptr, *pixels;
rtgui_blit_line_func blit_line;
struct rtgui_graphic_driver *hw_driver;
hw_driver = rtgui_graphic_driver_get_default();
/* prepare pixel line */
pixels = _dc_get_pixel(dc, dc_point.x, dc_point.y);
if (hw_driver->bits_per_pixel == _dc_get_bits_per_pixel(dc))
{
if (dest->type == RTGUI_DC_HW && hw_driver->framebuffer != RT_NULL)
{
rt_uint8_t *hw_pixels;
struct rtgui_dc_hw *hw;
hw = (struct rtgui_dc_hw*)dest;
/* NOTES: the rect of DC is the logic coordination.
* It should be converted to client
*/
if (dest_rect != &_rect)
{
/* use local rect */
_rect = *dest_rect;
dest_rect = &_rect;
}
rtgui_rect_moveto(dest_rect, hw->owner->extent.x1, hw->owner->extent.y1);
pitch = rtgui_color_get_bpp(hw_driver->pixel_format) * rect_width;
hw_pixels = (rt_uint8_t*)(hw_driver->framebuffer + dest_rect->y1 * hw_driver->pitch +
dest_rect->x1 * rtgui_color_get_bpp(hw_driver->pixel_format));
/* do the blit with memory copy */
for (index = 0; index < rect_height; index ++)
{
rt_memcpy(hw_pixels, pixels, pitch);
pixels += dc->pitch;
hw_pixels += hw_driver->pitch;
}
}
else
{
/* it's the same bits per pixel, draw it directly */
for (index = dest_rect->y1; index < dest_rect->y1 + rect_height; index++)
{
dest->engine->blit_line(dest, dest_rect->x1, dest_rect->x1 + rect_width, index, pixels);
pixels += dc->pitch;
}
}
}
else
{
struct rtgui_graphic_driver *hw_driver;
hw_driver = rtgui_graphic_driver_get_default();
if ((dc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888) &&
(dest->type == RTGUI_DC_HW) &&
(hw_driver->framebuffer != RT_NULL) &&
(hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565))
{
/* do the fast ARGB to RGB565 blit */
struct rtgui_blit_info info;
struct rtgui_widget *owner;
/* blit source */
info.src = _dc_get_pixel(dc, dc_point.x, dc_point.y);
info.src_fmt = dc->pixel_format;
info.src_h = rect_height;
info.src_w = rect_width;
info.src_pitch = dc->pitch;
info.src_skip = info.src_pitch - info.src_w * rtgui_color_get_bpp(dc->pixel_format);
owner = ((struct rtgui_dc_hw*)dest)->owner;
/* blit destination */
info.dst = (rt_uint8_t*)hw_driver->framebuffer;
info.dst = info.dst + (owner->extent.y1 + dest_rect->y1) * hw_driver->pitch +
(owner->extent.x1 + dest_rect->x1) * rtgui_color_get_bpp(hw_driver->pixel_format);
info.dst_fmt = hw_driver->pixel_format;
info.dst_h = rect_height;
info.dst_w = rect_width;
info.dst_pitch = hw_driver->pitch;
info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(hw_driver->pixel_format);
rtgui_blit(&info);
}
else
{
/* calculate pitch */
pitch = rect_width * rtgui_color_get_bpp(dc->pixel_format);
/* get blit line function */
blit_line = rtgui_blit_line_get(_UI_BITBYTES(hw_driver->bits_per_pixel),
rtgui_color_get_bpp(dc->pixel_format));
if (hw_driver->framebuffer != RT_NULL)
{
struct rtgui_widget* owner;
if (dest->type == RTGUI_DC_HW) owner = ((struct rtgui_dc_hw*) dest)->owner;
else if (dest->type == RTGUI_DC_CLIENT) owner = RTGUI_CONTAINER_OF(dest, struct rtgui_widget, dc_type);
else RT_ASSERT(0);
/* change the logic coordinate to the device coordinate */
rtgui_rect_moveto(dest_rect, owner->extent.x1, owner->extent.y1);
for (index = dest_rect->y1; index < dest_rect->y1 + rect_height; index ++)
{
line_ptr = _hw_get_pixel(hw_driver, dest_rect->x1, index, rt_uint8_t);
blit_line(line_ptr, (rt_uint8_t*)pixels, pitch);
pixels += dc->pitch;
}
}
else
{
/* calculate pitch */
pitch = rect_width * rtgui_color_get_bpp(dc->pixel_format);
/* create line buffer */
line_ptr = (rt_uint8_t *) rtgui_malloc(rect_width * _UI_BITBYTES(hw_driver->bits_per_pixel));
/* draw each line */
for (index = dest_rect->y1; index < dest_rect->y1 + rect_height; index ++)
{
/* blit on line buffer */
blit_line(line_ptr, (rt_uint8_t *)pixels, pitch);
pixels += dc->pitch;
/* draw on hardware dc */
dest->engine->blit_line(dest, dest_rect->x1, dest_rect->x1 + rect_width,
index, line_ptr);
}
/* release line buffer */
rtgui_free(line_ptr);
}
}
}
}
else if (dest->type == RTGUI_DC_BUFFER)
{
struct rtgui_dc_buffer *dest_dc = (struct rtgui_dc_buffer*)dest;
if (dest_dc->pixel_format == dc->pixel_format && dest_dc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
{
int index;
rt_uint8_t *pixels, *dest_pixels;
/* get pitch */
pitch = rect_width * rtgui_color_get_bpp(dc->pixel_format);
pixels = _dc_get_pixel(dc, dc_point.x, dc_point.y);
dest_pixels = _dc_get_pixel(dest_dc, dest_rect->x1, dest_rect->y1);
for (index = 0; index < rect_height; index ++)
{
rt_memcpy(dest_pixels, pixels, pitch);
pixels += dc->pitch;
dest_pixels += dest_dc->pitch;
}
}
else /* use rtgui_blit to handle buffer blit */
{
/* do the fast ARGB to RGB565 blit */
struct rtgui_blit_info info;
/* blit source */
info.src = _dc_get_pixel(dc, dc_point.x, dc_point.y);
info.src_fmt = dc->pixel_format;
info.src_h = rect_height;
info.src_w = rect_width;
info.src_pitch = dc->pitch;
info.src_skip = info.src_pitch - info.src_w * rtgui_color_get_bpp(dc->pixel_format);
/* blit destination */
info.dst = _dc_get_pixel(dest_dc, dest_rect->x1, dest_rect->y1);
info.dst_fmt = dest_dc->pixel_format;
info.dst_h = rect_height;
info.dst_w = rect_width;
info.dst_pitch = dest_dc->pitch;
info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(dest_dc->pixel_format);
rtgui_blit(&info);
}
}
}
static void rtgui_dc_buffer_blit_line(struct rtgui_dc *self, int x1, int x2, int y, rt_uint8_t *line_data)
{
rt_uint8_t *pixel;
struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer *)self;
RT_ASSERT(dc != RT_NULL);
RT_ASSERT(line_data != RT_NULL);
/* out of range */
if ((x1 >= dc->width) || (y >= dc->height) || y < 0 || x1 == x2)
return;
/* check range */
if (x1 < 0)
x1 = 0;
if (x2 >= dc->width)
x2 = dc->width-1;
pixel = _dc_get_pixel(dc,x1,y);
rt_memcpy(pixel, line_data, (x2 - x1) * rtgui_color_get_bpp(dc->pixel_format));
}

View File

@ -0,0 +1,343 @@
/*
* File : dc_client.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
* 2010-08-09 Bernard rename hardware dc to client dc
* 2010-09-13 Bernard fix rtgui_dc_client_blit_line issue, which found
* by appele
* 2010-09-14 Bernard fix vline and hline coordinate issue
*/
#include <rtgui/dc.h>
#include <rtgui/dc_hw.h>
#include <rtgui/dc_client.h>
#include <rtgui/driver.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/rtgui_app.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/widgets/container.h>
#include <rtgui/widgets/window.h>
static void rtgui_dc_client_draw_point(struct rtgui_dc *dc, int x, int y);
static void rtgui_dc_client_draw_color_point(struct rtgui_dc *dc, int x, int y, rtgui_color_t color);
static void rtgui_dc_client_draw_hline(struct rtgui_dc *dc, int x1, int x2, int y);
static void rtgui_dc_client_draw_vline(struct rtgui_dc *dc, int x, int y1, int y2);
static void rtgui_dc_client_fill_rect(struct rtgui_dc *dc, rtgui_rect_t *rect);
static void rtgui_dc_client_blit_line(struct rtgui_dc *self, int x1, int x2, int y, rt_uint8_t *line_data);
static void rtgui_dc_client_blit(struct rtgui_dc *dc, struct rtgui_point *dc_point, struct rtgui_dc *dest, rtgui_rect_t *rect);
static rt_bool_t rtgui_dc_client_fini(struct rtgui_dc *dc);
#define hw_driver (rtgui_graphic_driver_get_default())
#define dc_set_foreground(c) dc->gc.foreground = c
#define dc_set_background(c) dc->gc.background = c
#define _int_swap(x, y) do {x ^= y; y ^= x; x ^= y;} while (0)
const struct rtgui_dc_engine dc_client_engine =
{
rtgui_dc_client_draw_point,
rtgui_dc_client_draw_color_point,
rtgui_dc_client_draw_vline,
rtgui_dc_client_draw_hline,
rtgui_dc_client_fill_rect,
rtgui_dc_client_blit_line,
rtgui_dc_client_blit,
rtgui_dc_client_fini,
};
void rtgui_dc_client_init(rtgui_widget_t *owner)
{
struct rtgui_dc *dc;
RT_ASSERT(owner != RT_NULL);
dc = RTGUI_WIDGET_DC(owner);
dc->type = RTGUI_DC_CLIENT;
dc->engine = &dc_client_engine;
}
struct rtgui_dc *rtgui_dc_client_create(rtgui_widget_t *owner)
{
/* adjudge owner */
if (owner == RT_NULL || owner->toplevel == RT_NULL) return RT_NULL;
return RTGUI_WIDGET_DC(owner);
}
static rt_bool_t rtgui_dc_client_fini(struct rtgui_dc *dc)
{
if (dc == RT_NULL || dc->type != RTGUI_DC_CLIENT) return RT_FALSE;
return RT_TRUE;
}
/*
* draw a logic point on device
*/
static void rtgui_dc_client_draw_point(struct rtgui_dc *self, int x, int y)
{
rtgui_rect_t rect;
rtgui_widget_t *owner;
if (self == RT_NULL) return;
if (!rtgui_dc_get_visible(self)) return;
/* get owner */
owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
x = x + owner->extent.x1;
y = y + owner->extent.y1;
if (rtgui_region_contains_point(&(owner->clip), x, y, &rect) == RT_EOK)
{
/* draw this point */
hw_driver->ops->set_pixel(&(owner->gc.foreground), x, y);
}
}
static void rtgui_dc_client_draw_color_point(struct rtgui_dc *self, int x, int y, rtgui_color_t color)
{
rtgui_rect_t rect;
rtgui_widget_t *owner;
if (self == RT_NULL) return;
if (!rtgui_dc_get_visible(self)) return;
/* get owner */
owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
x = x + owner->extent.x1;
y = y + owner->extent.y1;
if (rtgui_region_contains_point(&(owner->clip), x, y, &rect) == RT_EOK)
{
/* draw this point */
hw_driver->ops->set_pixel(&color, x, y);
}
}
/*
* draw a logic vertical line on device
*/
static void rtgui_dc_client_draw_vline(struct rtgui_dc *self, int x, int y1, int y2)
{
register rt_base_t index;
rtgui_widget_t *owner;
if (self == RT_NULL) return;
if (!rtgui_dc_get_visible(self)) return;
/* get owner */
owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
x = x + owner->extent.x1;
y1 = y1 + owner->extent.y1;
y2 = y2 + owner->extent.y1;
if (y1 > y2) _int_swap(y1, y2);
if (owner->clip.data == RT_NULL)
{
rtgui_rect_t *prect;
prect = &(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 */
hw_driver->ops->draw_vline(&(owner->gc.foreground), x, y1, y2);
}
else
{
for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
{
rtgui_rect_t *prect;
register rt_base_t draw_y1, draw_y2;
prect = ((rtgui_rect_t *)(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 */
hw_driver->ops->draw_vline(&(owner->gc.foreground), x, draw_y1, draw_y2);
}
}
}
/*
* draw a logic horizontal line on device
*/
static void rtgui_dc_client_draw_hline(struct rtgui_dc *self, int x1, int x2, int y)
{
register rt_base_t index;
rtgui_widget_t *owner;
if (self == RT_NULL) return;
if (!rtgui_dc_get_visible(self)) return;
/* get owner */
owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
/* convert logic to device */
x1 = x1 + owner->extent.x1;
x2 = x2 + owner->extent.x1;
if (x1 > x2) _int_swap(x1, x2);
y = y + owner->extent.y1;
if (owner->clip.data == RT_NULL)
{
rtgui_rect_t *prect;
prect = &(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 */
hw_driver->ops->draw_hline(&(owner->gc.foreground), x1, x2, y);
}
else
{
for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
{
rtgui_rect_t *prect;
register rt_base_t draw_x1, draw_x2;
prect = ((rtgui_rect_t *)(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 */
hw_driver->ops->draw_hline(&(owner->gc.foreground), draw_x1, draw_x2, y);
}
}
}
static void rtgui_dc_client_fill_rect(struct rtgui_dc *self, struct rtgui_rect *rect)
{
rtgui_color_t foreground;
register rt_base_t index;
rtgui_widget_t *owner;
RT_ASSERT(self);
RT_ASSERT(rect);
if (!rtgui_dc_get_visible(self)) return;
/* get owner */
owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
/* save foreground color */
foreground = owner->gc.foreground;
/* set background color as foreground color */
owner->gc.foreground = owner->gc.background;
/* fill rect */
for (index = rect->y1; index < rect->y2; index ++)
{
rtgui_dc_client_draw_hline(self, rect->x1, rect->x2, index);
}
/* restore foreground color */
owner->gc.foreground = foreground;
}
static void rtgui_dc_client_blit_line(struct rtgui_dc *self, int x1, int x2, int y, rt_uint8_t *line_data)
{
register rt_base_t index;
rtgui_widget_t *owner;
if (self == RT_NULL) return;
if (!rtgui_dc_get_visible(self)) return;
/* get owner */
owner = RTGUI_CONTAINER_OF(self, struct rtgui_widget, dc_type);
/* convert logic to device */
x1 = x1 + owner->extent.x1;
x2 = x2 + owner->extent.x1;
if (x1 > x2) _int_swap(x1, x2);
y = y + owner->extent.y1;
if (rtgui_region_is_flat(&(owner->clip)) == RT_EOK)
{
rtgui_rect_t *prect;
int offset = 0;
prect = &(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;
/* patch note:
* We need to adjust the offset when update widget clip!
* Of course at ordinary times for 0. General */
offset = owner->clip.extents.x1 - owner->extent.x1;
offset = offset * _UI_BITBYTES(hw_driver->bits_per_pixel);
/* draw hline */
hw_driver->ops->draw_raw_hline(line_data + offset, x1, x2, y);
}
else
{
for (index = 0; index < rtgui_region_num_rects(&(owner->clip)); index ++)
{
rtgui_rect_t *prect;
register rt_base_t draw_x1, draw_x2;
prect = ((rtgui_rect_t *)(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 */
hw_driver->ops->draw_raw_hline(line_data + (draw_x1 - x1) * _UI_BITBYTES(hw_driver->bits_per_pixel), draw_x1, draw_x2, y);
}
}
}
static void rtgui_dc_client_blit(struct rtgui_dc *dc, struct rtgui_point *dc_point, struct rtgui_dc *dest, rtgui_rect_t *rect)
{
/* not blit in hardware dc */
return ;
}

271
components/gui/src/dc_hw.c Normal file
View File

@ -0,0 +1,271 @@
/*
* 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/dc_hw.h>
#include <rtgui/driver.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/rtgui_app.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/widgets/container.h>
#include <rtgui/widgets/window.h>
#define _int_swap(x, y) do {x ^= y; y ^= x; x ^= y;} while (0)
static void rtgui_dc_hw_draw_point(struct rtgui_dc *dc, int x, int y);
static void rtgui_dc_hw_draw_color_point(struct rtgui_dc *dc, int x, int y, rtgui_color_t color);
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_line(struct rtgui_dc *self, int x1, int x2, int y, rt_uint8_t *line_data);
static void rtgui_dc_hw_blit(struct rtgui_dc *dc, struct rtgui_point *dc_point, struct rtgui_dc *dest, rtgui_rect_t *rect);
static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc *dc);
const struct rtgui_dc_engine dc_hw_engine =
{
rtgui_dc_hw_draw_point,
rtgui_dc_hw_draw_color_point,
rtgui_dc_hw_draw_vline,
rtgui_dc_hw_draw_hline,
rtgui_dc_hw_fill_rect,
rtgui_dc_hw_blit_line,
rtgui_dc_hw_blit,
rtgui_dc_hw_fini,
};
struct rtgui_dc *rtgui_dc_hw_create(rtgui_widget_t *owner)
{
struct rtgui_dc_hw *dc;
/* adjudge owner */
if (owner == RT_NULL || owner->toplevel == RT_NULL) return RT_NULL;
/* create DC */
dc = (struct rtgui_dc_hw *) rtgui_malloc(sizeof(struct rtgui_dc_hw));
if (dc)
{
dc->parent.type = RTGUI_DC_HW;
dc->parent.engine = &dc_hw_engine;
dc->owner = owner;
dc->hw_driver = rtgui_graphic_driver_get_default();
return &(dc->parent);
}
return RT_NULL;
}
static rt_bool_t rtgui_dc_hw_fini(struct rtgui_dc *dc)
{
if (dc == RT_NULL || dc->type != RTGUI_DC_HW) return RT_FALSE;
/* release hardware dc */
rtgui_free(dc);
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;
RT_ASSERT(self != RT_NULL);
dc = (struct rtgui_dc_hw *) self;
if (x < 0 || y < 0)
return;
x = x + dc->owner->extent.x1;
if (x >= dc->owner->extent.x2)
return;
y = y + dc->owner->extent.y1;
if (y >= dc->owner->extent.y2)
return;
/* draw this point */
dc->hw_driver->ops->set_pixel(&(dc->owner->gc.foreground), x, y);
}
static void rtgui_dc_hw_draw_color_point(struct rtgui_dc *self, int x, int y, rtgui_color_t color)
{
struct rtgui_dc_hw *dc;
RT_ASSERT(self != RT_NULL);
dc = (struct rtgui_dc_hw *) self;
if (x < 0 || y < 0)
return;
x = x + dc->owner->extent.x1;
if (x >= dc->owner->extent.x2)
return;
y = y + dc->owner->extent.y1;
if (y >= dc->owner->extent.y2)
return;
/* draw this point */
dc->hw_driver->ops->set_pixel(&color, 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)
{
struct rtgui_dc_hw *dc;
RT_ASSERT(self != RT_NULL);
dc = (struct rtgui_dc_hw *) self;
if (x < 0)
return;
x = x + dc->owner->extent.x1;
if (x >= dc->owner->extent.x2)
return;
y1 = y1 + dc->owner->extent.y1;
y2 = y2 + dc->owner->extent.y1;
if (y1 > y2)
_int_swap(y1, y2);
if (y1 > dc->owner->extent.y2 || y2 < dc->owner->extent.y1)
return;
if (y1 < dc->owner->extent.y1)
y1 = dc->owner->extent.y1;
if (y2 > dc->owner->extent.y2)
y2 = dc->owner->extent.y2;
/* draw vline */
dc->hw_driver->ops->draw_vline(&(dc->owner->gc.foreground), x, y1, 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)
{
struct rtgui_dc_hw *dc;
RT_ASSERT(self != RT_NULL);
dc = (struct rtgui_dc_hw *) self;
if (y < 0)
return;
y = y + dc->owner->extent.y1;
if (y >= dc->owner->extent.y2)
return;
/* convert logic to device */
x1 = x1 + dc->owner->extent.x1;
x2 = x2 + dc->owner->extent.x1;
if (x1 > x2)
_int_swap(x1, x2);
if (x1 > dc->owner->extent.x2 || x2 < dc->owner->extent.x1)
return;
if (x1 < dc->owner->extent.x1)
x1 = dc->owner->extent.x1;
if (x2 > dc->owner->extent.x2)
x2 = dc->owner->extent.x2;
/* draw hline */
dc->hw_driver->ops->draw_hline(&(dc->owner->gc.foreground), x1, x2, y);
}
static void rtgui_dc_hw_fill_rect(struct rtgui_dc *self, struct rtgui_rect *rect)
{
rtgui_color_t color;
register rt_base_t y1, y2, x1, x2;
struct rtgui_dc_hw *dc;
RT_ASSERT(self != RT_NULL);
RT_ASSERT(rect);
dc = (struct rtgui_dc_hw *) self;
/* get background color */
color = dc->owner->gc.background;
/* convert logic to device */
x1 = rect->x1 + dc->owner->extent.x1;
if (x1 > dc->owner->extent.x2)
return;
if (x1 < dc->owner->extent.x1)
x1 = dc->owner->extent.x1;
x2 = rect->x2 + dc->owner->extent.x1;
if (x2 < dc->owner->extent.x1)
return;
if (x2 > dc->owner->extent.x2)
x2 = dc->owner->extent.x2;
y1 = rect->y1 + dc->owner->extent.y1;
if (y1 > dc->owner->extent.y2)
return;
if (y1 < dc->owner->extent.y1)
y1 = dc->owner->extent.y1;
y2 = rect->y2 + dc->owner->extent.y1;
if (y2 < dc->owner->extent.y1)
return;
if (y2 > dc->owner->extent.y2)
y2 = dc->owner->extent.y2;
/* fill rect */
for (; y1 < y2; y1++)
{
dc->hw_driver->ops->draw_hline(&color, x1, x2, y1);
}
}
static void rtgui_dc_hw_blit_line(struct rtgui_dc *self, int x1, int x2, int y, rt_uint8_t *line_data)
{
struct rtgui_dc_hw *dc;
RT_ASSERT(self != RT_NULL);
dc = (struct rtgui_dc_hw *) self;
/* convert logic to device */
if (y < 0)
return;
y = y + dc->owner->extent.y1;
if (y > dc->owner->extent.y2)
return;
x1 = x1 + dc->owner->extent.x1;
x2 = x2 + dc->owner->extent.x1;
if (x1 > x2)
_int_swap(x1, x2);
if (x1 > dc->owner->extent.x2 || x2 < dc->owner->extent.x1)
return;
if (x1 < dc->owner->extent.x1)
x1 = dc->owner->extent.x1;
if (x2 > dc->owner->extent.x2)
x2 = dc->owner->extent.x2;
dc->hw_driver->ops->draw_raw_hline(line_data, x1, x2, y);
}
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 ;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,840 @@
#include <rtgui/rtgui.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/dc.h>
#include <rtgui/dc_trans.h>
struct rtgui_dc_trans
{
struct rtgui_matrix m;
struct rtgui_dc *owner;
int use_aa;
};
struct rtgui_dc_trans* rtgui_dc_trans_create(struct rtgui_dc *owner)
{
struct rtgui_dc_trans *dct;
dct = (struct rtgui_dc_trans*)rtgui_malloc(sizeof(*dct));
if (!dct)
return RT_NULL;
rtgu_matrix_identity(&dct->m);
dct->owner = owner;
dct->use_aa = 0;
return dct;
}
RTM_EXPORT(rtgui_dc_trans_create);
void rtgui_dc_trans_destroy(struct rtgui_dc_trans *dct)
{
rtgui_free(dct);
}
RTM_EXPORT(rtgui_dc_trans_destroy);
void rtgui_dc_trans_set_aa(struct rtgui_dc_trans *dct, int use_aa)
{
RT_ASSERT(dct);
dct->use_aa = use_aa;
}
RTM_EXPORT(rtgui_dc_trans_set_aa);
void rtgui_dc_trans_rotate(struct rtgui_dc_trans *dct, double degree)
{
RT_ASSERT(dct);
rtgui_matrix_rotate(&dct->m, degree * RTGUI_MATRIX_FRAC / 360.0);
}
RTM_EXPORT(rtgui_dc_trans_rotate);
void rtgui_dc_trans_scale(struct rtgui_dc_trans *dct,
double sx,
double sy)
{
RT_ASSERT(dct);
rtgui_matrix_scale(&dct->m, sx * RTGUI_MATRIX_FRAC, sy * RTGUI_MATRIX_FRAC);
}
RTM_EXPORT(rtgui_dc_trans_scale);
void rtgui_dc_trans_move(struct rtgui_dc_trans *dct,
int dx,
int dy)
{
RT_ASSERT(dct);
rtgui_matrix_move(&dct->m, dx, dy);
}
RTM_EXPORT(rtgui_dc_trans_move);
void rtgui_dc_trans_get_new_wh(struct rtgui_dc_trans *dct,
int *new_wp,
int *new_hp)
{
struct rtgui_rect rect;
struct rtgui_point topleft, topright, bottomright;
RT_ASSERT(dct);
if (!new_wp && !new_hp)
return;
rtgui_dc_get_rect(dct->owner, &rect);
/* We ignore the movement components in the matrix. */
/* Transform result of (0, h). */
rtgui_matrix_mul_point_nomove(&topleft, 0, rect.y2,
&dct->m);
/* Transform result of (w, h). */
rtgui_matrix_mul_point_nomove(&topright, rect.x2, rect.y2,
&dct->m);
/* Transform result of (w, 0). */
rtgui_matrix_mul_point_nomove(&bottomright,
rect.x2, 0, &dct->m);
/* Transform result of (0, 0) is always (0, 0). */
#define NORMALIZE(x) do { if (x < 0) x = 0; } while (0)
if (new_wp)
{
int neww;
/* Ignore the nagtive parts. */
NORMALIZE(topright.x);
NORMALIZE(topleft.x);
NORMALIZE(bottomright.x);
neww = _UI_MAX(topright.x, _UI_ABS(topleft.x - bottomright.x))
+ dct->m.m[4];
NORMALIZE(neww);
*new_wp = neww;
}
if (new_hp)
{
int newh;
NORMALIZE(topright.y);
NORMALIZE(topleft.y);
NORMALIZE(bottomright.y);
newh = _UI_MAX(topright.y, _UI_ABS(topleft.y - bottomright.y))
+ dct->m.m[5];
NORMALIZE(newh);
*new_hp = newh;
}
#undef NORMALIZE
}
RTM_EXPORT(rtgui_dc_trans_get_new_wh);
struct _fb_rect
{
void *fb;
/* unit: pixel */
rt_uint16_t width, height;
/* unit: pixel */
rt_uint16_t skip;
};
/* FrameRect to FrameRect, same format, 2 Bytes/pixel. */
static void _blit_rotate_FR2FR_SF2B(struct _fb_rect* RTGUI_RESTRICT src,
const struct rtgui_point *dc_point,
struct _fb_rect* RTGUI_RESTRICT dst,
const struct rtgui_matrix *invm)
{
rt_uint16_t* RTGUI_RESTRICT srcp = (rt_uint16_t*)src->fb;
rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb;
int neww = dst->width;
int newh = dst->height;
int oriw = src->width;
int orih = src->height;
int nx, ny;
int dx, dy;
/* Delta of bx/by when nx++. */
dx = invm->m[0];
dy = invm->m[1];
for (ny = dc_point->y; ny < newh; ny++)
{
/* Base x, y. */
int bx, by;
bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
for (nx = dc_point->x; nx < neww; nx++, dstp++)
{
/* The coordinate in the source frame. */
int rx, ry;
bx += dx;
by += dy;
if (bx < 0 || by < 0)
continue;
rx = bx / RTGUI_MATRIX_FRAC;
ry = by / RTGUI_MATRIX_FRAC;
if (oriw <= rx || orih <= ry)
continue;
/* We take the source as a whole and ignore the src->skip. */
*dstp = srcp[ry * oriw + rx];
}
dstp += dst->skip - neww;
}
}
/* FrameRect to FrameRect, same format, 2 Bytes/pixel, with AA. */
static void _blit_rotate_FR2FR_SF2B_AA(struct _fb_rect* RTGUI_RESTRICT src,
const struct rtgui_point *dc_point,
struct _fb_rect* RTGUI_RESTRICT dst,
const struct rtgui_matrix *invm)
{
rt_uint16_t* RTGUI_RESTRICT srcp = (rt_uint16_t*)src->fb;
rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb;
int neww = dst->width;
int newh = dst->height;
int oriw = src->width;
int orih = src->height;
int nx, ny;
int dx, dy;
dx = invm->m[0];
dy = invm->m[1];
for (ny = dc_point->y; ny < newh; ny++)
{
/* Base x, y. */
int bx, by;
bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
for (nx = dc_point->x; nx < neww; nx++, dstp++)
{
/* Color of pixels:
* c00 c01
* c10 c11 */
rt_uint32_t c00, c01, c10, c11;
int rx, ry, sx, sy;
bx += dx;
by += dy;
if (bx < 0 || by < 0)
continue;
rx = bx / RTGUI_MATRIX_FRAC;
ry = by / RTGUI_MATRIX_FRAC;
if (oriw - 1 <= rx || orih - 1 <= ry)
continue;
c00 = srcp[ry * oriw + rx];
c01 = srcp[ry * oriw + rx + 1];
c10 = srcp[(ry + 1) * oriw + rx];
c11 = srcp[(ry + 1) * oriw + rx + 1];
c00 = (c00 | c00 << 16) & 0x07e0f81f;
c01 = (c01 | c01 << 16) & 0x07e0f81f;
c10 = (c10 | c10 << 16) & 0x07e0f81f;
c11 = (c11 | c11 << 16) & 0x07e0f81f;
/* We down scale the interpolate factor to 5 bits to avoid color
* corruption. */
sx = ((unsigned int)bx % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
sy = ((unsigned int)by % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
if (sx)
c00 = ((c01 - c00) * sx / 32 + c00) & 0x07e0f81f;
if (sx && sy)
c10 = ((c11 - c10) * sx / 32 + c10) & 0x07e0f81f;
if (sy)
c00 = ((c10 - c00) * sy / 32 + c00) & 0x07e0f81f;
/* We take the source as a whole and ignore the src->skip. */
*dstp = c00 | (c00 >> 16);
}
dstp += dst->skip - neww;
}
}
union _rgba
{
rt_uint32_t blk;
struct
{
rt_uint8_t r, g, b, a;
} d;
};
/* FrameRect to FrameRect, same format, 4 Bytes/pixel. */
static void _blit_rotate_FR2FR_SF4B(struct _fb_rect* RTGUI_RESTRICT src,
const struct rtgui_point *dc_point,
struct _fb_rect* RTGUI_RESTRICT dst,
const struct rtgui_matrix *invm)
{
rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb;
rt_uint32_t* RTGUI_RESTRICT dstp = (rt_uint32_t*)dst->fb;
int neww = dst->width;
int newh = dst->height;
int oriw = src->width;
int orih = src->height;
int nx, ny;
int dx, dy;
dx = invm->m[0];
dy = invm->m[1];
for (ny = dc_point->y; ny < newh; ny++)
{
/* Base x, y. */
int bx, by;
bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
for (nx = dc_point->x; nx < neww; nx++, dstp++)
{
union _rgba spix, dpix;
int rx, ry, a;
bx += dx;
by += dy;
if (bx < 0 || by < 0)
continue;
rx = bx / RTGUI_MATRIX_FRAC;
ry = by / RTGUI_MATRIX_FRAC;
if (oriw <= rx || orih <= ry)
continue;
spix.blk = srcp[ry * oriw + rx];
/* Down scale the alpha to 5 bits. */
a = spix.d.a >> 3;
if (a == 0)
continue;
if (a == 31)
{
*dstp = spix.blk;
continue;
}
dpix.blk = *dstp;
dpix.d.r = (spix.d.r - dpix.d.r) * a / 32 + dpix.d.r;
dpix.d.g = (spix.d.g - dpix.d.g) * a / 32 + dpix.d.g;
dpix.d.b = (spix.d.b - dpix.d.b) * a / 32 + dpix.d.b;
*dstp = dpix.blk;
}
dstp += dst->skip - neww;
}
}
/* FrameRect to FrameRect, same format, 4 Bytes/pixel, with AA. */
static void _blit_rotate_FR2FR_SF4B_AA(struct _fb_rect* RTGUI_RESTRICT src,
const struct rtgui_point *dc_point,
struct _fb_rect* RTGUI_RESTRICT dst,
const struct rtgui_matrix *invm)
{
rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb;
rt_uint32_t* RTGUI_RESTRICT dstp = (rt_uint32_t*)dst->fb;
int neww = dst->width;
int newh = dst->height;
int oriw = src->width;
int orih = src->height;
int nx, ny;
int dx, dy;
dx = invm->m[0];
dy = invm->m[1];
for (ny = dc_point->y; ny < newh; ny++)
{
/* Base x, y. */
int bx, by;
bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
for (nx = dc_point->x; nx < neww; nx++, dstp++)
{
union _rgba spix00, spix01, spix10, spix11, dpix;
int rx, ry, a, sx, sy;
bx += dx;
by += dy;
if (bx < 0 || by < 0)
continue;
rx = bx / RTGUI_MATRIX_FRAC;
ry = by / RTGUI_MATRIX_FRAC;
if (oriw - 1 <= rx || orih - 1 <= ry)
continue;
spix00.blk = srcp[ry * oriw + rx];
/* Down scale the interpolate factor to 5 bits. */
sx = ((unsigned int)bx % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
sy = ((unsigned int)by % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
spix01.blk = srcp[ry * oriw + rx + 1];
spix10.blk = srcp[(ry + 1) * oriw + rx];
spix11.blk = srcp[(ry + 1) * oriw + rx + 1];
if (sx)
spix00.d.a = (spix01.d.a - spix00.d.a) * sx / 32 + spix00.d.a;
if (sx && sy)
spix10.d.a = (spix11.d.a - spix10.d.a) * sx / 32 + spix10.d.a;
if (sy)
spix00.d.a = (spix10.d.a - spix00.d.a) * sy / 32 + spix00.d.a;
a = spix00.d.a >> 3;
if (a == 0)
continue;
if (sx)
{
spix00.d.r = (spix01.d.r - spix00.d.r) * sx / 32 + spix00.d.r;
spix00.d.g = (spix01.d.g - spix00.d.g) * sx / 32 + spix00.d.g;
spix00.d.b = (spix01.d.b - spix00.d.b) * sx / 32 + spix00.d.b;
}
if (sx && sy)
{
spix10.d.r = (spix11.d.r - spix10.d.r) * sx / 32 + spix10.d.r;
spix10.d.g = (spix11.d.g - spix10.d.g) * sx / 32 + spix10.d.g;
spix10.d.b = (spix11.d.b - spix10.d.b) * sx / 32 + spix10.d.b;
}
if (sy)
{
spix00.d.r = (spix10.d.r - spix00.d.r) * sy / 32 + spix00.d.r;
spix00.d.g = (spix10.d.g - spix00.d.g) * sy / 32 + spix00.d.g;
spix00.d.b = (spix10.d.b - spix00.d.b) * sy / 32 + spix00.d.b;
}
if (a == (255 >> 3))
{
*dstp = spix00.blk;
continue;
}
dpix.blk = *dstp;
dpix.d.r = (spix00.d.r - dpix.d.r) * a / 32 + dpix.d.r;
dpix.d.g = (spix00.d.g - dpix.d.g) * a / 32 + dpix.d.g;
dpix.d.b = (spix00.d.b - dpix.d.b) * a / 32 + dpix.d.b;
*dstp = dpix.blk;
}
dstp += dst->skip - neww;
}
}
/* FrameRect to FrameRect, from ARGB8888 to RGB565. */
static void _blit_rotate_FR2FR_ARGB2RGB565(struct _fb_rect* RTGUI_RESTRICT src,
const struct rtgui_point *dc_point,
struct _fb_rect* RTGUI_RESTRICT dst,
const struct rtgui_matrix *invm)
{
rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb;
rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb;
int neww = dst->width;
int newh = dst->height;
int oriw = src->width;
int orih = src->height;
int nx, ny;
int dx, dy;
dx = invm->m[0];
dy = invm->m[1];
for (ny = dc_point->y; ny < newh; ny++)
{
/* Base x, y. */
int bx, by;
bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
for (nx = dc_point->x; nx < neww; nx++, dstp++)
{
int rx, ry;
int alpha;
rt_uint32_t op;
bx += dx;
by += dy;
if (bx < 0 || by < 0)
continue;
rx = bx / RTGUI_MATRIX_FRAC;
ry = by / RTGUI_MATRIX_FRAC;
if (oriw <= rx || orih <= ry)
continue;
/* We take the source as a whole and ignore the src->skip. */
op = srcp[ry * oriw + rx];
/* downscale alpha to 5 bits */
alpha = op >> 27;
if (alpha == (255 >> 3))
{
*dstp = (rt_uint16_t)((op >> 8 & 0xf800) +
(op >> 5 & 0x7e0) +
(op >> 3 & 0x1f));
}
else if (alpha != 0)
{
/* We take the source as a whole and ignore the src->skip. */
rt_uint32_t d = *dstp;
/*
* convert source and destination to G0RAB65565
* and blend all components at the same time
*/
op = ((op & 0xfc00) << 11) + (op >> 8 & 0xf800)
+ (op >> 3 & 0x1f);
d = (d | d << 16) & 0x07e0f81f;
d += (op - d) * alpha >> 5;
d &= 0x07e0f81f;
*dstp = (rt_uint16_t)(d | d >> 16);
}
}
dstp += dst->skip - neww;
}
}
/* FrameRect to FrameRect, from ARGB8888 to RGB565. */
static void _blit_rotate_FR2FR_ARGB2RGB565_AA(struct _fb_rect* RTGUI_RESTRICT src,
const struct rtgui_point *dc_point,
struct _fb_rect* RTGUI_RESTRICT dst,
const struct rtgui_matrix *invm)
{
rt_uint32_t* RTGUI_RESTRICT srcp = (rt_uint32_t*)src->fb;
rt_uint16_t* RTGUI_RESTRICT dstp = (rt_uint16_t*)dst->fb;
int neww = dst->width;
int newh = dst->height;
int oriw = src->width;
int orih = src->height;
int nx, ny;
int dx, dy;
dx = invm->m[0];
dy = invm->m[1];
for (ny = dc_point->y; ny < newh; ny++)
{
/* Base x, y. */
int bx, by;
bx = dc_point->x * dx + ny * invm->m[2] + RTGUI_MATRIX_FRAC * invm->m[4];
by = dc_point->x * dy + ny * invm->m[3] + RTGUI_MATRIX_FRAC * invm->m[5];
for (nx = dc_point->x; nx < neww; nx++, dstp++)
{
rt_uint32_t op00, op01, op10, op11;
rt_uint8_t a00, a01, a10, a11;
int rx, ry, sx, sy;
bx += dx;
by += dy;
if (bx < 0 || by < 0)
continue;
rx = bx / RTGUI_MATRIX_FRAC;
ry = by / RTGUI_MATRIX_FRAC;
if (oriw - 1 <= rx || orih - 1 <= ry)
continue;
op00 = srcp[ry * oriw + rx];
op01 = srcp[ry * oriw + rx + 1];
op10 = srcp[(ry + 1) * oriw + rx];
op11 = srcp[(ry + 1) * oriw + rx + 1];
/* Down scale the interpolate factor to 5 bits. */
sx = ((unsigned int)bx % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
sy = ((unsigned int)by % RTGUI_MATRIX_FRAC) >> (RTGUI_MATRIX_FRAC_BITS - 5);
a00 = op00 >> 27;
a01 = op01 >> 27;
a11 = op11 >> 27;
a10 = op10 >> 27;
if (sx)
a00 = (a01 - a00) * sx / 32 + a00;
if (sx && sy)
a10 = (a11 - a10) * sx / 32 + a10;
if (sy)
a00 = (a10 - a00) * sy / 32 + a00;
if (a00 == 0)
continue;
op00 = (((op00 >> 10) & 0x3f) << 21) | (((op00 >> 19) & 0x1f) << 11) | (op00 >> 3 & 0x1f);
op10 = (((op10 >> 10) & 0x3f) << 21) | (((op10 >> 19) & 0x1f) << 11) | (op10 >> 3 & 0x1f);
op01 = (((op01 >> 10) & 0x3f) << 21) | (((op01 >> 19) & 0x1f) << 11) | (op01 >> 3 & 0x1f);
op11 = (((op11 >> 10) & 0x3f) << 21) | (((op11 >> 19) & 0x1f) << 11) | (op11 >> 3 & 0x1f);
if (sx)
{
op00 = ((op01 - op00) * sx / 32 + op00) & 0x07e0f81f;
}
if (sx && sy)
{
op10 = ((op11 - op10) * sx / 32 + op10) & 0x07e0f81f;
}
if (sy)
{
op00 = ((op10 - op00) * sy / 32 + op00) & 0x07e0f81f;
}
if (a00 == (255 >> 3))
{
*dstp = op00 | (op00 >> 16);
}
else if (a00 != 0)
{
rt_uint32_t d = *dstp;
d = (d | d << 16) & 0x07e0f81f;
d += (op00 - d) * a00 >> 5;
d &= 0x07e0f81f;
*dstp = (rt_uint16_t)(d | d >> 16);
}
}
dstp += dst->skip - neww;
}
}
static void _blit_rotate_B2B(struct rtgui_dc_trans *dct,
const struct rtgui_point *dc_point,
struct rtgui_dc_buffer* RTGUI_RESTRICT dest,
struct rtgui_rect *rect,
const struct rtgui_matrix *invm,
int neww, int newh)
{
struct rtgui_rect srcrect;
struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer*)dct->owner;
struct _fb_rect srcfb, dstfb;
rtgui_dc_get_rect(dct->owner, &srcrect);
srcfb.fb = ((struct rtgui_dc_buffer*)dct->owner)->pixel;
srcfb.width = srcrect.x2;
srcfb.height = srcrect.y2;
srcfb.skip = 0;
dstfb.fb = dest->pixel + rtgui_color_get_bpp(dest->pixel_format) * (rect->x1 + rect->y1 * dest->width);
dstfb.width = neww;
dstfb.height = newh;
dstfb.skip = dest->width;
if (dc->pixel_format == dest->pixel_format)
{
switch (rtgui_color_get_bpp(dest->pixel_format)) {
case 2:
if (dct->use_aa)
_blit_rotate_FR2FR_SF2B_AA(&srcfb, dc_point,
&dstfb, invm);
else
_blit_rotate_FR2FR_SF2B(&srcfb, dc_point,
&dstfb, invm);
break;
case 4:
if (dct->use_aa)
_blit_rotate_FR2FR_SF4B_AA(&srcfb, dc_point,
&dstfb, invm);
else
_blit_rotate_FR2FR_SF4B(&srcfb, dc_point,
&dstfb, invm);
break;
default:
rt_kprintf("could not handle bpp: %d\n",
rtgui_color_get_bpp(dest->pixel_format));
return;
}
}
else if (dc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888 &&
dest->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
{
if (dct->use_aa)
_blit_rotate_FR2FR_ARGB2RGB565_AA(&srcfb, dc_point,
&dstfb, invm);
else
_blit_rotate_FR2FR_ARGB2RGB565(&srcfb, dc_point,
&dstfb, invm);
}
else
{
rt_kprintf("not implemented yet\n");
return;
}
}
static void _blit_rotate_B2H(struct rtgui_dc_trans *dct,
const struct rtgui_point *dc_point,
struct rtgui_dc_hw* dest,
struct rtgui_rect *rect,
const struct rtgui_matrix *invm,
int neww, int newh)
{
struct rtgui_rect srcrect;
int start_pix;
struct _fb_rect srcfb, dstfb;
struct rtgui_dc_buffer *dc = (struct rtgui_dc_buffer*)dct->owner;
if (dest->hw_driver->framebuffer == RT_NULL)
{
rt_kprintf("Only support framebuffer hw dc\n");
return;
}
rtgui_dc_get_rect(dct->owner, &srcrect);
srcfb.fb = ((struct rtgui_dc_buffer*)dct->owner)->pixel;
srcfb.width = srcrect.x2;
srcfb.height = srcrect.y2;
srcfb.skip = 0;
/* Start point of the widget. */
start_pix = dest->owner->extent.x1 + dest->owner->extent.y1 * dest->hw_driver->width;
/* Start point of the inner rect. */
start_pix += rect->x1 + rect->y1 * dest->hw_driver->width;
dstfb.fb = (void*)(dest->hw_driver->framebuffer
+ rtgui_color_get_bpp(dest->hw_driver->pixel_format) * start_pix);
dstfb.width = neww;
dstfb.height = newh;
dstfb.skip = dest->hw_driver->width;
if (dc->pixel_format == dest->hw_driver->pixel_format)
{
switch (rtgui_color_get_bpp(dest->hw_driver->pixel_format)) {
case 2:
if (dct->use_aa)
_blit_rotate_FR2FR_SF2B_AA(&srcfb, dc_point,
&dstfb, invm);
else
_blit_rotate_FR2FR_SF2B(&srcfb, dc_point,
&dstfb, invm);
break;
case 4:
if (dct->use_aa)
_blit_rotate_FR2FR_SF4B_AA(&srcfb, dc_point,
&dstfb, invm);
else
_blit_rotate_FR2FR_SF4B(&srcfb, dc_point,
&dstfb, invm);
break;
default:
rt_kprintf("could not handle bpp: %d\n",
rtgui_color_get_bpp(dest->hw_driver->pixel_format));
return;
}
}
else if (dc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888 &&
dest->hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
{
if (dct->use_aa)
_blit_rotate_FR2FR_ARGB2RGB565_AA(&srcfb, dc_point,
&dstfb, invm);
else
_blit_rotate_FR2FR_ARGB2RGB565(&srcfb, dc_point,
&dstfb, invm);
}
else
{
rt_kprintf("not implemented yet\n");
return;
}
}
void rtgui_dc_trans_blit(struct rtgui_dc_trans *dct,
struct rtgui_point *dc_point,
struct rtgui_dc *dest,
struct rtgui_rect *rect)
{
struct rtgui_rect bkrect;
struct rtgui_matrix invm;
struct rtgui_point dp;
int neww, newh;
RT_ASSERT(dct);
RT_ASSERT(dest);
if (dc_point == RT_NULL)
{
dp.x = dp.y = 0;
dc_point = &dp;
}
if (rect == RT_NULL)
{
rtgui_dc_get_rect(dest, &bkrect);
rect = &bkrect;
}
rtgui_dc_trans_get_new_wh(dct, &neww, &newh);
if (dc_point->x < 0)
{
neww -= dc_point->x;
if (neww < 0)
return;
dc_point->x = 0;
}
else if (dc_point->x > neww)
return;
if (dc_point->y < 0)
{
newh -= dc_point->y;
if (newh < 0)
return;
dc_point->y = 0;
}
else if (dc_point->y > newh)
return;
if (rtgui_matrix_inverse(&dct->m, &invm))
return;
if (rtgui_rect_width(*rect) < neww - dc_point->x)
neww = dc_point->x + rtgui_rect_width(*rect);
if (rtgui_rect_height(*rect) < newh - dc_point->y)
newh = dc_point->y + rtgui_rect_height(*rect);
/* Route to different optimized routines. */
if (dct->owner->type == RTGUI_DC_BUFFER)
{
if (dest->type == RTGUI_DC_BUFFER)
_blit_rotate_B2B(dct, dc_point,
(struct rtgui_dc_buffer*)dest,
rect, &invm, neww, newh);
else if (dest->type == RTGUI_DC_HW)
_blit_rotate_B2H(dct, dc_point,
(struct rtgui_dc_hw*)dest,
rect, &invm, neww, newh);
else if (dest->type == RTGUI_DC_CLIENT)
// TODO:
;
else
rt_kprintf("unknown dc for dc_trans\n");
}
else
rt_kprintf("not implemented yet\n");
}
RTM_EXPORT(rtgui_dc_trans_blit);

371
components/gui/src/filerw.c Normal file
View File

@ -0,0 +1,371 @@
/*
* 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/rtgui_system.h>
#include <rtgui/filerw.h>
#ifdef RTGUI_USING_DFS_FILERW
/* standard file read/write */
struct rtgui_filerw_stdio
{
/* inherit from rtgui_filerw */
struct rtgui_filerw parent;
int fd;
rt_bool_t eof;
};
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;
}
return lseek(stdio_filerw->fd, offset, stdio_whence[whence]);
}
static int stdio_read(struct rtgui_filerw *context, void *ptr, rt_size_t size, rt_size_t maxnum)
{
int result;
struct rtgui_filerw_stdio *stdio_filerw = (struct rtgui_filerw_stdio *)context;
/* end of file */
if (stdio_filerw->eof == RT_TRUE) return -1;
result = read(stdio_filerw->fd, ptr, size * maxnum);
if (result == 0) stdio_filerw->eof = RT_TRUE;
return result;
}
static int stdio_write(struct rtgui_filerw *context, const void *ptr, rt_size_t size, rt_size_t num)
{
struct rtgui_filerw_stdio *stdio_filerw = (struct rtgui_filerw_stdio *)context;
return write(stdio_filerw->fd, (char *)ptr, size * num);
}
static int stdio_tell(struct rtgui_filerw *context)
{
struct rtgui_filerw_stdio *stdio_filerw = (struct rtgui_filerw_stdio *)context;
return lseek(stdio_filerw->fd, 0, SEEK_CUR);
}
static int stdio_eof(struct rtgui_filerw *context)
{
int result;
struct rtgui_filerw_stdio *stdio_filerw = (struct rtgui_filerw_stdio *)context;
if (stdio_filerw->eof == RT_TRUE) result = 1;
else result = -1;
return result;
}
static int stdio_close(struct rtgui_filerw *context)
{
struct rtgui_filerw_stdio *stdio_filerw = (struct rtgui_filerw_stdio *)context;
if (stdio_filerw)
{
close(stdio_filerw->fd);
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;
const rt_uint8_t *mem_base, *mem_position, *mem_end;
};
static int mem_seek(struct rtgui_filerw *context, rt_off_t offset, int whence)
{
const 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)
{
return 0; /* not support memory write */
}
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;
}
const 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 RTGUI_USING_DFS_FILERW
static int parse_mode(const char *mode)
{
int f = 0;
for (;;)
{
switch (*mode)
{
case 0:
return f;
case 'b':
f |= O_BINARY;
break;
case 'r':
f = O_RDONLY;
break;
case 'w':
f = O_WRONLY | O_CREAT | O_TRUNC;
break;
case 'a':
f = O_WRONLY | O_CREAT | O_APPEND;
break;
case '+':
f = (f & (~O_WRONLY)) | O_RDWR;
break;
}
++mode;
}
}
struct rtgui_filerw *rtgui_filerw_create_file(const char *filename, const char *mode)
{
int fd;
struct rtgui_filerw_stdio *rw;
RT_ASSERT(filename != RT_NULL);
rw = RT_NULL;
#ifdef _WIN32_NATIVE
fd = _open(filename, parse_mode(mode), 0);
#else
fd = open(filename, parse_mode(mode), 0);
#endif
if (fd >= 0)
{
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->fd = fd;
rw->eof = RT_FALSE;
return &(rw->parent);
}
close(fd);
}
else
{
rt_kprintf("open:%s failed! errno=%d\n", filename, errno);
}
return RT_NULL;
}
int rtgui_filerw_unlink(const char *filename)
{
#ifdef _WIN32_NATIVE
return _unlink(filename);
#else
#ifndef RT_USING_DFS
/* no unlink function */
return -1;
#else
return unlink(filename);
#endif
#endif
}
#endif
struct rtgui_filerw *rtgui_filerw_create_mem(const 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;
}

211
components/gui/src/font.c Normal file
View File

@ -0,0 +1,211 @@
/*
* 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
* 2013-08-31 Bernard remove the default font setting.
* (which set by theme)
*/
#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_arial16;
extern struct rtgui_font rtgui_font_asc12;
extern struct rtgui_font rtgui_font_arial12;
#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
#ifdef RTGUI_USING_FONT12
rtgui_font_system_add_font(&rtgui_font_asc12);
#ifdef RTGUI_USING_FONTHZ
rtgui_font_system_add_font(&rtgui_font_hz12);
#endif
#endif
}
void rtgui_font_system_add_font(struct rtgui_font *font)
{
rtgui_list_init(&(font->list));
rtgui_list_append(&_rtgui_font_list, &(font->list));
/* init font */
if (font->engine->font_init != RT_NULL)
font->engine->font_init(font);
/* first refer, load it */
if (font->engine->font_load != RT_NULL)
font->engine->font_load(font);
}
RTM_EXPORT(rtgui_font_system_add_font);
void rtgui_font_system_remove_font(struct rtgui_font *font)
{
rtgui_list_remove(&_rtgui_font_list, &(font->list));
}
RTM_EXPORT(rtgui_font_system_remove_font);
struct rtgui_font *rtgui_font_default()
{
return rtgui_default_font;
}
void rtgui_font_set_defaut(struct rtgui_font *font)
{
// rt_kprintf("set font size to %d\n", font->height);
rtgui_default_font = font;
}
struct rtgui_font *rtgui_font_refer(const char *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(font->family, family, RTGUI_NAME_MAX) == 0) &&
font->height == height)
{
font->refer_count ++;
return font;
}
}
return RT_NULL;
}
RTM_EXPORT(rtgui_font_refer);
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);
}
}
RTM_EXPORT(rtgui_font_derefer);
/* draw a text */
void rtgui_font_draw(struct rtgui_font *font, struct rtgui_dc *dc, const char *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 char *text)
{
rtgui_rect_t rect;
/* get metrics */
rtgui_font_get_metrics(font, text, &rect);
return rect.x2 - rect.x1;
}
RTM_EXPORT(rtgui_font_get_string_width);
void rtgui_font_get_metrics(struct rtgui_font *font, const char *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));
}
}
RTM_EXPORT(rtgui_font_get_metrics);
/* GB18030 encoding:
* 1st byte 2nd byte 3rd byte 4th byte
* 1byte: 0x00~0x7F
* 2bytes: 0x81~0xFE 0x40~0xFE
* 4bytes: 0x81~0xFE 0x30~0x39 0x81~0xFE 0x30~0x39
*/
struct rtgui_char_position _string_char_width(char *str, rt_size_t len, rt_size_t offset)
{
struct rtgui_char_position pos = {0, 0};
unsigned char *pc;
RT_ASSERT(offset < len);
pc = (unsigned char*)str;
while (pc <= (unsigned char*)str + offset)
{
if (pc[0] < 0x80)
{
pos.char_width = 1;
}
else if (0x81 <= pc[0] && pc[0] <= 0xFE)
{
if (0x40 <= pc[1] && pc[1] <= 0xFE)
{
/* GBK */
pos.char_width = 2;
}
else if (0x30 <= pc[1] && pc[1] <= 0x39)
{
/* GB18030 */
pos.char_width = 4;
}
else
{
/* FIXME: unknown encoding */
RT_ASSERT(0);
pos.char_width = 1;
}
}
else
{
/* FIXME: unknown encoding */
RT_ASSERT(0);
pos.char_width = 1;
}
pc += pos.char_width;
}
pos.remain = pc - (unsigned char*)&str[offset];
return pos;
}

View File

@ -0,0 +1,193 @@
/*
* File : font.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2010, 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
* 2010-09-15 Bernard first version
*/
#include <rtgui/font.h>
#include <rtgui/dc.h>
/* bitmap font private data */
static void rtgui_bitmap_font_draw_text(struct rtgui_font *font, struct rtgui_dc *dc, const char *text, rt_ubase_t len, struct rtgui_rect *rect);
static void rtgui_bitmap_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect);
const struct rtgui_font_engine bmp_font_engine =
{
RT_NULL,
RT_NULL,
rtgui_bitmap_font_draw_text,
rtgui_bitmap_font_get_metrics
};
RTM_EXPORT(bmp_font_engine);
void rtgui_bitmap_font_draw_char(struct rtgui_font_bitmap *font, struct rtgui_dc *dc, const char ch,
rtgui_rect_t *rect)
{
rtgui_color_t bc;
const rt_uint8_t *font_ptr;
int x, y, w, h, style;
register rt_base_t i, j, /*k,*/ word_bytes;
struct rtgui_rect dc_rect;
/* check first and last char */
if (ch < font->first_char || ch > font->last_char) return;
/* get text style */
style = rtgui_dc_get_gc(dc)->textstyle;
bc = rtgui_dc_get_gc(dc)->background;
rtgui_dc_get_rect(dc, &dc_rect);
x = rect->x1;
y = rect->y1;
/* get width */
if (font->char_width == RT_NULL)
{
word_bytes = (((font->width - 1) / 8) + 1);
font_ptr = font->bmp + (ch - font->first_char) * word_bytes * font->height;
}
else
{
word_bytes = ((font->char_width[ch - font->first_char] - 1) / 8) + 1;
font_ptr = font->bmp + font->offset[ch - font->first_char];
}
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++)
{
rt_uint8_t chr = 0;
const rt_uint8_t *ptr = font_ptr + i * word_bytes;
if ((i + y) >= dc_rect.y2) continue;
if ((i + y) < 0) continue;
for (j = 0; j < w; j++)
{
if (j % 8 == 0)
chr = *ptr++;
if (chr & 0x80)
rtgui_dc_draw_point(dc, j + x, i + y);
else if (style & RTGUI_TEXTSTYLE_DRAW_BACKGROUND)
rtgui_dc_draw_color_point(dc, j + x, i + y, bc);
chr <<= 1;
}
}
}
static void rtgui_bitmap_font_draw_text(struct rtgui_font *font, struct rtgui_dc *dc,
const char *text, rt_ubase_t len, struct rtgui_rect *rect)
{
rt_uint32_t length;
struct rtgui_font_bitmap *bmp_font = (struct rtgui_font_bitmap *)(font->data);
#ifdef RTGUI_USING_FONTHZ
struct rtgui_font *hz_font;
#endif
RT_ASSERT(bmp_font != RT_NULL);
/* parameter check */
if (rect->y1 > rect->y2) return;
#ifdef RTGUI_USING_FONTHZ
hz_font = rtgui_font_refer("hz", font->height);
while ((rect->x1 < rect->x2) && len)
{
length = 0;
while ((rt_uint8_t) * (text + length) >= 0x80) length ++; /* it's not a ascii character */
if (length > 0)
{
if (hz_font != RT_NULL) rtgui_font_draw(hz_font, dc, text, length, rect);
text += length;
len -= length;
}
length = 0;
while (((rt_uint8_t) * (text + length) < 0x80) && *(text + length)) length ++;
if (length > 0)
{
len -= length;
while (length-- && rect->x1 < rect->x2)
{
rtgui_bitmap_font_draw_char(bmp_font, dc, *text, rect);
/* move x to next character */
if (bmp_font->char_width == RT_NULL)
rect->x1 += bmp_font->width;
else
rect->x1 += bmp_font->char_width[*text - bmp_font->first_char];
text ++;
}
}
}
if (hz_font != RT_NULL) rtgui_font_derefer(hz_font);
#else
while ((rect->x1 < rect->x2) && len)
{
length = 0;
while (((rt_uint8_t) * (text + length) < 0x80) && *(text + length)) length ++;
if (length > 0)
{
len -= length;
while (length-- && rect->x1 < rect->x2)
{
rtgui_bitmap_font_draw_char(bmp_font, dc, *text, rect);
/* move x to next character */
if (bmp_font->char_width == RT_NULL)
rect->x1 += bmp_font->width;
else
rect->x1 += bmp_font->char_width[*text - bmp_font->first_char];
text ++;
}
}
}
#endif
}
static void rtgui_bitmap_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect)
{
rt_uint32_t length;
struct rtgui_font_bitmap *bmp_font = (struct rtgui_font_bitmap *)(font->data);
RT_ASSERT(bmp_font != RT_NULL);
/* set init metrics rect */
rect->x1 = rect->y1 = 0;
rect->x2 = 0;
rect->y2 = bmp_font->height;
while (*text)
{
length = 0;
while ((rt_uint8_t) * (text + length) >= 0x80) length ++; /* it's not a ascii character */
rect->x2 += (font->height / 2) * length;
text += length;
length = 0;
while (((rt_uint8_t) * (text + length) < 0x80) && *(text + length)) length ++;
if (bmp_font->char_width != NULL)
{
/* get width for each character */
while (*text && ((rt_uint8_t)*text < 0x80))
{
rect->x2 += bmp_font->char_width[*text - bmp_font->first_char];
text ++;
}
}
else
{
/* set metrics rect */
rect->x2 += bmp_font->width * length;
text += length;
}
}
}

View File

@ -0,0 +1,247 @@
/*
* rockbox fnt font engine
*/
#include <rtgui/font_fnt.h>
#include <rtgui/rtgui_system.h>
static void rtgui_fnt_font_draw_text(struct rtgui_font *font, struct rtgui_dc *dc, const char *text, rt_ubase_t len, struct rtgui_rect *rect);
static void rtgui_fnt_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect);
const struct rtgui_font_engine fnt_font_engine =
{
RT_NULL,
RT_NULL,
rtgui_fnt_font_draw_text,
rtgui_fnt_font_get_metrics
};
void rtgui_fnt_font_draw_text(struct rtgui_font *font, struct rtgui_dc *dc, const char *text, rt_ubase_t len, struct rtgui_rect *rect)
{
int ch, i, j, c, width;
rt_uint32_t position;
struct fnt_font *fnt;
rt_uint8_t *data_ptr;
fnt = (struct fnt_font*)font->data;
RT_ASSERT(fnt != RT_NULL);
while (len)
{
/* get character */
ch = *text;
/* NOTE: we only support asc character right now */
if (ch > 0x80)
{
text += 1; len -= 1;
continue;
}
/* get position and width */
if (fnt->offset == RT_NULL)
{
width = fnt->header.max_width;
position = (ch - fnt->header.first_char) * width * ((fnt->header.height + 7)/8);
}
else
{
width = fnt->width[ch - fnt->header.first_char];
position = fnt->offset[ch - fnt->header.first_char];
}
/* draw a character */
data_ptr = (rt_uint8_t*)&fnt->bits[position];
for (i = 0; i < width; i ++) /* x */
{
for (j = 0; j < 8; j ++) /* y */
{
for (c = 0; c < (fnt->header.height + 7)/8; c ++)
{
/* check drawable region */
if ((rect->x1 + i > rect->x2) || (rect->y1 + c * 8 + j > rect->y2))
continue;
if (data_ptr[i + c * width] & (1 << j))
rtgui_dc_draw_point(dc, rect->x1 + i, rect->y1 + c * 8 + j);
}
}
}
rect->x1 += width;
text += 1;
len -= 1;
}
}
void rtgui_fnt_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect)
{
int ch;
struct fnt_font *fnt;
fnt = (struct fnt_font*)font->data;
RT_ASSERT(fnt != RT_NULL);
rt_memset(rect, 0x00, sizeof(rtgui_rect_t));
rect->y2 = fnt->header.height;
while (*text)
{
if (fnt->width == RT_NULL)
{
/* fixed width font */
rect->x2 += fnt->header.max_width;
}
else
{
ch = *text;
/* NOTE: we only support asc character right now */
if (ch > 0x80)
{
text += 1;
continue;
}
rect->x2 += fnt->width[ch - fnt->header.first_char];
}
text += 1;
}
}
#ifdef RTGUI_USING_FNT_FILE
#include <dfs_posix.h>
rt_inline int readbyte(int fd, unsigned char *cp)
{
unsigned char buf[1];
if (read(fd, buf, 1) != 1)
return 0;
*cp = buf[0];
return 1;
}
rt_inline int readshort(int fd, unsigned short *sp)
{
unsigned char buf[2];
if (read(fd, buf, 2) != 2)
return 0;
*sp = buf[0] | (buf[1] << 8);
return 1;
}
rt_inline int readlong(int fd, rt_uint32_t *lp)
{
unsigned char buf[4];
if (read(fd, buf, 4) != 4)
return 0;
*lp = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
return 1;
}
rt_inline int readstr(int fd, char *buf, int count)
{
return read(fd, buf, count);
}
struct rtgui_font *fnt_font_create(const char* filename, const char* font_family)
{
int fd = -1;
rt_uint32_t index;
struct rtgui_font *font = RT_NULL;
struct fnt_font *fnt = RT_NULL;
struct fnt_header *fnt_header;
fd = open(filename, O_RDONLY, 0);
if (fd < 0)
{
goto __exit;
}
font = (struct rtgui_font*) rtgui_malloc (sizeof(struct rtgui_font));
if (font == RT_NULL) goto __exit;
fnt = (struct fnt_font*) rtgui_malloc (sizeof(struct fnt_font));
if (fnt == RT_NULL) goto __exit;
rt_memset(fnt, 0x00, sizeof(struct fnt_font));
font->data = (void*)fnt;
fnt_header = &(fnt->header);
if (readstr(fd, fnt_header->version, 4) != 4) goto __exit;
if (!readshort(fd, &fnt_header->max_width)) goto __exit;
if (!readshort(fd, &fnt_header->height)) goto __exit;
if (!readshort(fd, &fnt_header->ascent)) goto __exit;
if (!readshort(fd, &fnt_header->depth)) goto __exit;
if (!readlong(fd, &fnt_header->first_char)) goto __exit;
if (!readlong(fd, &fnt_header->default_char)) goto __exit;
if (!readlong(fd, &fnt_header->size)) goto __exit;
if (!readlong(fd, &fnt_header->nbits)) goto __exit;
if (!readlong(fd, &fnt_header->noffset)) goto __exit;
if (!readlong(fd, &fnt_header->nwidth)) goto __exit;
fnt->bits = (MWIMAGEBITS*) rtgui_malloc (fnt_header->nbits * sizeof(MWIMAGEBITS));
if (fnt->bits == RT_NULL) goto __exit;
/* read data */
if (readstr(fd, &(fnt->bits[0]), fnt_header->nbits) != fnt_header->nbits) goto __exit;
/* check boundary */
if (fnt_header->nbits & 0x01)
{
rt_uint16_t pad;
readshort(fd, &pad);
pad = pad; /* skip warning */
}
if (fnt_header->noffset != 0)
{
fnt->offset = rtgui_malloc (fnt_header->noffset * sizeof(rt_uint32_t));
if (fnt->offset == RT_NULL) goto __exit;
for (index = 0; index < fnt_header->noffset; index ++)
{
if (!readshort(fd, &(fnt->offset[index]))) goto __exit;
}
}
if (fnt_header->nwidth != 0)
{
fnt->width = rtgui_malloc (fnt_header->nwidth * sizeof(rt_uint8_t));
if (fnt->width == RT_NULL) goto __exit;
for (index = 0; index < fnt_header->nwidth; index ++)
{
if (!readbyte(fd, &(fnt->width[index]))) goto __exit;
}
}
close(fd);
font->family = rt_strdup(font_family);
font->height = fnt->header.height;
font->refer_count = 0;
font->engine = &fnt_font_engine;
/* add to system */
rtgui_font_system_add_font(font);
return font;
__exit:
if (fd >= 0) close(fd);
if (fnt != RT_NULL)
{
if (fnt->bits != RT_NULL) rtgui_free(fnt->bits);
if (fnt->offset != RT_NULL) rtgui_free(fnt->offset);
if (fnt->width != RT_NULL) rtgui_free(fnt->width);
rtgui_free(fnt);
}
if (font != RT_NULL)
{
rtgui_free(font);
}
return RT_NULL;
}
#endif

View File

@ -0,0 +1,477 @@
#include <rtthread.h>
#ifdef RTGUI_USING_TTF
#include <rtgui/rtgui.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/dc.h>
#include <rtgui/font.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#define LOG_ERROR
#ifdef LOG_ERROR
#define PERROR rt_kprintf
#else
#define PERROR(...)
#endif
//#define LOG_INFO
#ifdef LOG_INFO
#define PINFO rt_kprintf
#else
#define PINFO(...)
#endif
static void ftf_draw_text(struct rtgui_font *font,
struct rtgui_dc *dc,
const char *text,
rt_ubase_t len,
struct rtgui_rect *rect);
static void ftf_get_metrics_kern(struct rtgui_font *font,
const char *text,
rtgui_rect_t *rect);
static const struct rtgui_font_engine ftf_engine =
{
RT_NULL,
RT_NULL,
ftf_draw_text,
ftf_get_metrics_kern
};
struct rtgui_freetype2_font
{
int bold;
int italic;
FT_Face face;
FT_Library library;
};
#if !defined(RT_USING_DFS) || !defined(RT_USING_DFS_ELMFAT) || (RT_DFS_ELM_CODE_PAGE != 936)
extern rt_uint32_t gb2312tounicode(const rt_uint16_t key);
#else
extern unsigned short ff_convert(unsigned short wch, int direction);
#define gb2312tounicode(code) ff_convert(code, 1)
#endif
static void gbk_to_unicode(rt_uint16_t *unicode, const char *text, int len)
{
int i;
const unsigned char *tp = (const unsigned char *)text;
unsigned short wch;
for (i = 0; i < len;)
{
if (*tp < 0x80)
{
wch = *tp;
*unicode = gb2312tounicode(wch);
tp ++;
i ++;
}
else
{
wch = *(tp + 1) | (*tp << 8);
*unicode = gb2312tounicode(wch);
tp += 2;
i += 2;
}
unicode ++;
}
*unicode = '\0';
}
static void _draw_bitmap(struct rtgui_dc *dc,
FT_GlyphSlot slot,
rt_int16_t ox, rt_int16_t btm_y,
rt_uint8_t r, rt_uint8_t g, rt_uint8_t b)
{
int rows;
rt_uint8_t *ptr;
FT_Bitmap *bitmap;
rt_int16_t xstart;
bitmap = &slot->bitmap;
ptr = (rt_uint8_t *)bitmap->buffer;
xstart = ox + slot->bitmap_left;
for (rows = 0; rows < bitmap->rows; rows++)
{
int x;
int y = btm_y + rows - slot->bitmap_top;
for (x = 0; x < bitmap->width; x++)
{
/* Use 5bit alpha. */
rt_uint8_t c = *ptr;
if (c >= 0xF8)
{
rtgui_dc_draw_point(dc, xstart + x, y);
}
else if (c >> 3)
{
rtgui_dc_blend_point(dc, xstart + x, y,
RTGUI_BLENDMODE_BLEND,
r, g, b, c);
}
ptr++;
}
}
}
static void _draw_text_nkern(struct rtgui_dc *dc,
struct rtgui_freetype2_font *fft,
rt_uint16_t *text_short,
rt_int16_t begin_x, rt_int16_t btm_y,
rt_uint8_t r, rt_uint8_t g, rt_uint8_t b)
{
rt_uint16_t *text_ptr;
FT_GlyphSlot slot;
slot = fft->face->glyph;
for (text_ptr = text_short; *text_ptr; text_ptr++)
{
FT_Error err = 0;
err = FT_Load_Char(fft->face, *text_ptr, FT_LOAD_RENDER | FT_LOAD_NO_HINTING);
if (err)
continue; /* ignore errors */
/* render font */
_draw_bitmap(dc, slot, begin_x, btm_y, r, g, b);
begin_x += slot->advance.x >> 6;
}
}
static void _draw_text_kern(struct rtgui_dc *dc,
struct rtgui_freetype2_font *fft,
rt_uint16_t *text_short,
rt_int16_t begin_x, rt_int16_t btm_y,
rt_uint8_t r, rt_uint8_t g, rt_uint8_t b)
{
rt_uint16_t *tp;
FT_GlyphSlot slot;
FT_Face face;
rt_uint32_t prev_gidx;
face = fft->face;
slot = face->glyph;
prev_gidx = 0;
for (tp = text_short; *tp; tp++)
{
FT_Error err;
rt_uint32_t cur_gidx;
cur_gidx = FT_Get_Char_Index(face, *tp);
if (prev_gidx && cur_gidx)
{
FT_Vector delta;
FT_Get_Kerning(face, prev_gidx, cur_gidx,
FT_KERNING_DEFAULT, &delta );
begin_x += delta.x >> 6;
}
prev_gidx = cur_gidx;
err = FT_Load_Glyph(face, cur_gidx, FT_LOAD_RENDER | FT_LOAD_NO_HINTING);
if (err)
continue;
/* render font */
_draw_bitmap(dc, slot, begin_x, btm_y, r, g, b);
begin_x += slot->advance.x >> 6;
}
}
static void ftf_draw_text(struct rtgui_font *font,
struct rtgui_dc *dc,
const char *text,
rt_ubase_t len,
struct rtgui_rect *rect)
{
rt_uint16_t *text_short;
struct rtgui_freetype2_font *fft;
rt_int16_t begin_x, btm_y;
rt_int16_t topy;
rt_uint8_t r, g, b;
rtgui_color_t fgc;
RT_ASSERT(font != RT_NULL);
fft = (struct rtgui_freetype2_font *) font->data;
RT_ASSERT(fft != RT_NULL);
/* allocate unicode buffer */
text_short = (rt_uint16_t *)rtgui_malloc((len + 1) * 2);
if (text_short == RT_NULL)
return; /* out of memory */
RT_ASSERT(rect);
/* convert gbk to unicode */
gbk_to_unicode(text_short, text, len);
fgc = RTGUI_DC_FC(dc);
r = RTGUI_RGB_R(fgc);
g = RTGUI_RGB_G(fgc);
b = RTGUI_RGB_B(fgc);
/* FIXME: RTGUI has no concept of "base line" right now. FreeType
* coordinate(0, 0) start from base line. So we have to adjust the rect to
* fit the glyphs within the rect. */
/* FIXME: face->size->metrics.descender is format specific actually. But it
* just works on TrueType. Varify this if you want to use with other fonts. */
topy = rect->y1 + (fft->face->size->metrics.descender >> 6);
btm_y = topy + rtgui_rect_height(*rect);
if (btm_y <= 0)
return;
begin_x = rect->x1;
if (dc->type == RTGUI_DC_BUFFER)
{
struct rtgui_dc_buffer *bdc = (struct rtgui_dc_buffer *) dc;
if (begin_x >= bdc->width || topy >= bdc->height)
{
goto _out;
}
}
else if (dc->type == RTGUI_DC_HW)
{
int x, y;
struct rtgui_dc_hw *hdc = (struct rtgui_dc_hw *) dc;
x = begin_x + hdc->owner->extent.x1;
y = topy + hdc->owner->extent.y1;
if (x >= hdc->owner->extent.x2)
goto _out;
if (y >= hdc->owner->extent.y2)
goto _out;
}
if (FT_HAS_KERNING(fft->face))
{
_draw_text_kern(dc, fft, text_short, begin_x, btm_y, r, g, b);
}
else
{
_draw_text_nkern(dc, fft, text_short, begin_x, btm_y, r, g, b);
}
_out:
/* release unicode buffer */
rtgui_free(text_short);
}
static void _get_metrics_nkern(FT_Face face, const rt_uint16_t *text_short, struct rtgui_rect *rect)
{
rt_int16_t w;
w = 0;
while (*text_short)
{
FT_Error err = 0;
rt_uint16_t index;
index = FT_Get_Char_Index(face, *text_short);
err = FT_Load_Glyph(face, index,
FT_LOAD_DEFAULT |
FT_LOAD_NO_HINTING |
FT_LOAD_IGNORE_TRANSFORM |
FT_LOAD_NO_AUTOHINT);
if (err == 0)
w += face->glyph->advance.x >> 6;
text_short ++;
}
rect->x1 = 0;
rect->y1 = 0;
rect->x2 = w;
rect->y2 = FT_MulFix(face->bbox.yMax - face->bbox.yMin,
face->size->metrics.y_scale) >> 6;
}
static void _get_metrics_kern(FT_Face face, const rt_uint16_t *text_short, struct rtgui_rect *rect)
{
rt_uint16_t prev_gidx;
rt_int16_t w;
prev_gidx = 0;
w = 0;
while (*text_short)
{
FT_Error err = 0;
rt_uint16_t index;
index = FT_Get_Char_Index(face, *text_short);
if (prev_gidx && index)
{
FT_Vector delta;
FT_Get_Kerning(face, prev_gidx, index,
FT_KERNING_DEFAULT, &delta);
w += delta.x >> 6;
}
prev_gidx = index;
err = FT_Load_Glyph(face, index,
FT_LOAD_DEFAULT |
FT_LOAD_NO_HINTING |
FT_LOAD_IGNORE_TRANSFORM |
FT_LOAD_NO_AUTOHINT);
if (err == 0)
w += face->glyph->advance.x >> 6;
text_short ++;
}
rect->x1 = 0;
rect->y1 = 0;
rect->x2 = w;
rect->y2 = FT_MulFix(face->bbox.yMax - face->bbox.yMin,
face->size->metrics.y_scale) >> 6;
}
static void ftf_get_metrics_kern(struct rtgui_font *font, const char *text, rtgui_rect_t *rect)
{
int len;
rt_uint16_t *text_short;
struct rtgui_freetype2_font *fft;
RT_ASSERT(font != RT_NULL);
RT_ASSERT(rect != RT_NULL);
fft = (struct rtgui_freetype2_font *) font->data;
RT_ASSERT(fft != RT_NULL);
len = strlen(text);
memset(rect, 0, sizeof(struct rtgui_rect));
/* allocate unicode buffer */
text_short = (rt_uint16_t *)rtgui_malloc((len + 1) * 2);
if (text_short == RT_NULL)
return; /* out of memory */
/* convert gbk to unicode */
gbk_to_unicode(text_short, text, len);
if (FT_HAS_KERNING(fft->face))
_get_metrics_kern(fft->face, text_short, rect);
else
_get_metrics_nkern(fft->face, text_short, rect);
/* release unicode buffer */
rtgui_free(text_short);
}
rtgui_font_t *rtgui_freetype_font_create(const char *filename, int bold, int italic, rt_size_t size)
{
FT_Error err = 0;
struct rtgui_font *font;
struct rtgui_freetype2_font *fft;
font = (struct rtgui_font *)rtgui_malloc(sizeof(struct rtgui_font)
+ sizeof(struct rtgui_freetype2_font));
rt_memset(font, 0, sizeof(struct rtgui_font) + sizeof(struct rtgui_freetype2_font));
if (!font)
{
PERROR("failed to allocate structs\n");
return RT_NULL;
}
fft = (struct rtgui_freetype2_font *)(font + 1);
font->data = fft;
err = FT_Init_FreeType(&fft->library);
if (err)
{
PERROR("failed to Init FreeType: %d\n", err);
goto _err_done_malloc;
}
err = FT_New_Face(fft->library, filename, 0, &fft->face);
if (err)
{
PERROR("failed to New Face: %d\n", err);
goto _err_done_init;
}
err = FT_Select_Charmap(fft->face, FT_ENCODING_UNICODE);
if (err)
{
err = FT_Select_Charmap(fft->face, FT_ENCODING_ADOBE_LATIN_1);
}
err = FT_Set_Pixel_Sizes(fft->face, 0, size);
if (err != 0)
{
PERROR("failed to set Pixel Size: %d\n", err);
goto _err_done_face;
}
fft->bold = bold;
fft->italic = italic;
PINFO("fonfile:%s\n", filename);
PINFO("font family_name:%s\n", fft->face->family_name);
PINFO("font style_name:%s\n", fft->face->style_name);
PINFO("%s kerneling\n", FT_HAS_KERNING(fft->face) ? "has" : "not has");
/* set user data */
font->family = rt_strdup(fft->face->family_name);
font->height = (rt_uint16_t)size;
font->refer_count = 1;
font->engine = &ftf_engine;
/* add to system */
rtgui_font_system_add_font(font);
return font;
_err_done_face:
FT_Done_Face(fft->face);
_err_done_init:
FT_Done_FreeType(fft->library);
_err_done_malloc:
rtgui_free(font);
return RT_NULL;
}
RTM_EXPORT(rtgui_freetype_font_create);
void rtgui_freetype_font_destroy(rtgui_font_t *font)
{
struct rtgui_freetype2_font *fft;
RT_ASSERT(font != RT_NULL);
fft = (struct rtgui_freetype2_font *) font->data;
RT_ASSERT(fft != RT_NULL);
rtgui_font_system_remove_font(font);
FT_Done_Face(fft->face);
FT_Done_FreeType(fft->library);
rt_free(font->family);
rtgui_free(font);
}
RTM_EXPORT(rtgui_freetype_font_destroy);
#ifdef RT_USING_FINSH
#include <finsh.h>
FINSH_FUNCTION_EXPORT_ALIAS(rtgui_freetype_font_create, ftc, "create freetype font: name, bold, italic, size")
FINSH_FUNCTION_EXPORT_ALIAS(rtgui_freetype_font_destroy, ftd, "destroy freetype font")
#endif
#endif

View File

@ -0,0 +1,159 @@
#include <rtgui/dc.h>
#include <rtgui/font.h>
#ifdef RTGUI_USING_HZ_BMP
static void rtgui_hz_bitmap_font_draw_text(struct rtgui_font *font, struct rtgui_dc *dc, const char *text, rt_ubase_t len, struct rtgui_rect *rect);
static void rtgui_hz_bitmap_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect);
const struct rtgui_font_engine hz_bmp_font_engine =
{
RT_NULL,
RT_NULL,
rtgui_hz_bitmap_font_draw_text,
rtgui_hz_bitmap_font_get_metrics
};
#ifdef RTGUI_USING_FONT_COMPACT
extern rt_uint32_t rtgui_font_mph12(const rt_uint16_t key);
extern rt_uint32_t rtgui_font_mph16(const rt_uint16_t key);
rt_inline const rt_uint8_t *_rtgui_hz_bitmap_get_font_ptr(struct rtgui_font_bitmap *bmp_font,
rt_uint8_t *str,
rt_base_t font_bytes)
{
rt_uint16_t cha = *(rt_uint16_t *)str;
int idx;
if (bmp_font->height == 16)
idx = rtgui_font_mph16(cha);
else // asume the height is 12
idx = rtgui_font_mph12(cha);
/* don't access beyond the data */
if (idx < 0)
idx = 0;
/* get font pixel data */
return bmp_font->bmp + idx * font_bytes;
}
#else
rt_inline const rt_uint8_t *_rtgui_hz_bitmap_get_font_ptr(struct rtgui_font_bitmap *bmp_font,
rt_uint8_t *str,
rt_base_t font_bytes)
{
rt_ubase_t sect, index;
/* calculate section and index */
sect = *str - 0xA0;
index = *(str + 1) - 0xA0;
/* get font pixel data */
return bmp_font->bmp + (94 * (sect - 1) + (index - 1)) * font_bytes;
}
#endif
static void _rtgui_hz_bitmap_font_draw_text(struct rtgui_font_bitmap *bmp_font, struct rtgui_dc *dc, const char *text, rt_ubase_t len, struct rtgui_rect *rect)
{
rtgui_color_t bc;
rt_uint16_t style;
rt_uint8_t *str;
register rt_base_t h, word_bytes, font_bytes;
RT_ASSERT(bmp_font != RT_NULL);
/* get text style */
style = rtgui_dc_get_gc(dc)->textstyle;
bc = rtgui_dc_get_gc(dc)->background;
/* drawing height */
h = (bmp_font->height + rect->y1 > rect->y2) ? rect->y2 - rect->y1 : bmp_font->height;
word_bytes = (bmp_font->width + 7) / 8;
font_bytes = word_bytes * bmp_font->height;
str = (rt_uint8_t *)text;
while (len > 0 && rect->x1 < rect->x2)
{
const rt_uint8_t *font_ptr;
register rt_base_t i, j, k;
/* get font pixel data */
font_ptr = _rtgui_hz_bitmap_get_font_ptr(bmp_font, str, font_bytes);
/* draw word */
for (i = 0; i < h; i ++)
{
for (j = 0; j < word_bytes; j++)
for (k = 0; k < 8; k++)
{
if (((font_ptr[i * word_bytes + j] >> (7 - k)) & 0x01) != 0 &&
(rect->x1 + 8 * j + k < rect->x2))
{
rtgui_dc_draw_point(dc, rect->x1 + 8 * j + k, rect->y1 + i);
}
else if (style & RTGUI_TEXTSTYLE_DRAW_BACKGROUND)
{
rtgui_dc_draw_color_point(dc, rect->x1 + 8 * j + k, rect->y1 + i, bc);
}
}
}
/* move x to next character */
rect->x1 += bmp_font->width;
str += 2;
len -= 2;
}
}
static void rtgui_hz_bitmap_font_draw_text(struct rtgui_font *font, struct rtgui_dc *dc, const char *text, rt_ubase_t length, struct rtgui_rect *rect)
{
rt_uint32_t len;
struct rtgui_font *efont;
struct rtgui_font_bitmap *bmp_font = (struct rtgui_font_bitmap *)(font->data);
RT_ASSERT(dc != RT_NULL);
/* get English font */
efont = rtgui_font_refer("asc", bmp_font->height);
if (efont == RT_NULL) efont = rtgui_font_default(); /* use system default font */
while (length > 0)
{
len = 0;
while (((rt_uint8_t) * (text + len)) < 0x80 && *(text + len) && len < length) len ++;
/* draw text with English font */
if (len > 0)
{
rtgui_font_draw(efont, dc, text, len, rect);
text += len;
length -= len;
}
len = 0;
while (((rt_uint8_t) * (text + len)) >= 0x80 && len < length) len ++;
if (len > 0)
{
_rtgui_hz_bitmap_font_draw_text(bmp_font, dc, text, len, rect);
text += len;
length -= len;
}
}
rtgui_font_derefer(efont);
}
static void rtgui_hz_bitmap_font_get_metrics(struct rtgui_font *font, const char *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;
/* Chinese font is always fixed font */
rect->x2 = (rt_int16_t)(bmp_font->width * rt_strlen((const char *)text));
rect->y2 = bmp_font->height;
}
#endif

View File

@ -0,0 +1,231 @@
/*
* Cached HZ font engine
*/
#include <rtgui/dc.h>
#include <rtgui/font.h>
#include <rtgui/tree.h>
#include <rtgui/rtgui_system.h>
#ifdef RTGUI_USING_HZ_FILE
#ifdef _WIN32_NATIVE
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#define open _open
#define close _close
#define read _read
#define write _write
#define unlink _unlink
#else
#include <dfs_posix.h>
#endif
#define HZ_CACHE_MAX 64
static int _font_cache_compare(struct hz_cache *node1, struct hz_cache *node2);
static void rtgui_hz_file_font_load(struct rtgui_font *font);
static void rtgui_hz_file_font_draw_text(struct rtgui_font *font, struct rtgui_dc *dc, const char *text, rt_ubase_t len, struct rtgui_rect *rect);
static void rtgui_hz_file_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect);
const struct rtgui_font_engine rtgui_hz_file_font_engine =
{
RT_NULL,
rtgui_hz_file_font_load,
rtgui_hz_file_font_draw_text,
rtgui_hz_file_font_get_metrics
};
SPLAY_PROTOTYPE(cache_tree, hz_cache, hz_node, _font_cache_compare);
SPLAY_GENERATE(cache_tree, hz_cache, hz_node, _font_cache_compare);
static int _font_cache_compare(struct hz_cache *cache_1, struct hz_cache *cache_2)
{
if (cache_1->hz_id > cache_2->hz_id) return 1;
if (cache_1->hz_id < cache_2->hz_id) return -1;
return 0;
}
static rt_uint8_t *_font_cache_get(struct rtgui_hz_file_font *font, rt_uint16_t hz_id)
{
rt_uint32_t seek;
struct hz_cache *cache, search;
search.hz_id = hz_id;
/* enter critical */
rtgui_enter_critical();
cache = SPLAY_FIND(cache_tree, &(font->cache_root), &search);
if (cache != RT_NULL)
{
/* exit critical */
rtgui_exit_critical();
/* found it */
return (rt_uint8_t *)(cache + 1);
}
/* exit critical */
rtgui_exit_critical();
/* can not find it, load to cache */
cache = (struct hz_cache *) rtgui_malloc(sizeof(struct hz_cache) + font->font_data_size);
if (cache == RT_NULL)
return RT_NULL; /* no memory yet */
cache->hz_id = hz_id;
seek = 94 * (((hz_id & 0xff) - 0xA0) - 1) + ((hz_id >> 8) - 0xA0) - 1;
seek *= font->font_data_size;
/* read hz font data */
if ((lseek(font->fd, seek, SEEK_SET) < 0) ||
read(font->fd, (char *)(cache + 1), font->font_data_size) !=
font->font_data_size)
{
rtgui_free(cache);
return RT_NULL;
}
/* enter critical */
rtgui_enter_critical();
if (font->cache_size >= HZ_CACHE_MAX)
{
/* remove a cache */
struct hz_cache *left;
left = font->cache_root.sph_root;
while (SPLAY_LEFT(left, hz_node) != RT_NULL) left = SPLAY_LEFT(left, hz_node);
/* remove the left node */
SPLAY_REMOVE(cache_tree, &(font->cache_root), left);
rtgui_free(left);
font->cache_size --;
}
/* insert to cache */
SPLAY_INSERT(cache_tree, &(font->cache_root), cache);
font->cache_size ++;
/* exit critical */
rtgui_exit_critical();
return (rt_uint8_t *)(cache + 1);
}
static void rtgui_hz_file_font_load(struct rtgui_font *font)
{
struct rtgui_hz_file_font *hz_file_font = (struct rtgui_hz_file_font *)font->data;
RT_ASSERT(hz_file_font != RT_NULL);
hz_file_font->fd = open(hz_file_font->font_fn, O_RDONLY, 0);
if (hz_file_font->fd < 0)
{
rt_kprintf("RTGUI: could not open the font file:%s\n", hz_file_font->font_fn);
rt_kprintf("RTGUI: please mount the fs first and make sure the file is there\n");
}
}
static void _rtgui_hz_file_font_draw_text(struct rtgui_hz_file_font *hz_file_font, struct rtgui_dc *dc, const char *text, rt_ubase_t len, struct rtgui_rect *rect)
{
rt_uint8_t *str;
rtgui_color_t bc;
rt_uint16_t style;
register rt_base_t h, word_bytes;
/* get text style */
style = rtgui_dc_get_gc(dc)->textstyle;
bc = rtgui_dc_get_gc(dc)->background;
/* drawing height */
h = (hz_file_font->font_size + rect->y1 > rect->y2) ?
rect->y2 - rect->y1 : hz_file_font->font_size;
word_bytes = (hz_file_font->font_size + 7) / 8;
str = (rt_uint8_t *)text;
while (len > 0 && rect->x1 < rect->x2)
{
const rt_uint8_t *font_ptr;
register rt_base_t i, j, k;
/* get font pixel data */
font_ptr = _font_cache_get(hz_file_font, *str | (*(str + 1) << 8));
/* draw word */
for (i = 0; i < h; i ++)
{
for (j = 0; j < word_bytes; j++)
for (k = 0; k < 8; k++)
{
if (((font_ptr[i * word_bytes + j] >> (7 - k)) & 0x01) != 0 &&
(rect->x1 + 8 * j + k < rect->x2))
{
rtgui_dc_draw_point(dc, rect->x1 + 8 * j + k, rect->y1 + i);
}
else if (style & RTGUI_TEXTSTYLE_DRAW_BACKGROUND)
{
rtgui_dc_draw_color_point(dc, rect->x1 + 8 * j + k, rect->y1 + i, bc);
}
}
}
/* move x to next character */
rect->x1 += hz_file_font->font_size;
str += 2;
len -= 2;
}
}
static void rtgui_hz_file_font_draw_text(struct rtgui_font *font, struct rtgui_dc *dc, const char *text, rt_ubase_t length, struct rtgui_rect *rect)
{
rt_uint32_t len;
struct rtgui_font *efont;
struct rtgui_hz_file_font *hz_file_font = (struct rtgui_hz_file_font *)font->data;
RT_ASSERT(dc != RT_NULL);
RT_ASSERT(hz_file_font != RT_NULL);
/* get English font */
efont = rtgui_font_refer("asc", hz_file_font->font_size);
if (efont == RT_NULL) efont = rtgui_font_default(); /* use system default font */
while (length > 0)
{
len = 0;
while (((rt_uint8_t) * (text + len)) < 0x80 && *(text + len) && len < length) len ++;
/* draw text with English font */
if (len > 0)
{
rtgui_font_draw(efont, dc, text, len, rect);
text += len;
length -= len;
}
len = 0;
while (((rt_uint8_t) * (text + len)) >= 0x80 && len < length) len ++;
if (len > 0)
{
_rtgui_hz_file_font_draw_text(hz_file_font, dc, text, len, rect);
text += len;
length -= len;
}
}
rtgui_font_derefer(efont);
}
static void rtgui_hz_file_font_get_metrics(struct rtgui_font *font, const char *text, rtgui_rect_t *rect)
{
struct rtgui_hz_file_font *hz_file_font = (struct rtgui_hz_file_font *)font->data;
RT_ASSERT(hz_file_font != RT_NULL);
/* set metrics rect */
rect->x1 = rect->y1 = 0;
rect->x2 = (rt_int16_t)(hz_file_font->font_size / 2 * rt_strlen((const char *)text));
rect->y2 = hz_file_font->font_size;
}
#endif

12323
components/gui/src/hz12font.c Normal file

File diff suppressed because it is too large Load Diff

16782
components/gui/src/hz16font.c Normal file

File diff suppressed because it is too large Load Diff

349
components/gui/src/image.c Normal file
View File

@ -0,0 +1,349 @@
/*
* 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
* 2012-01-24 onelife add TJpgDec (Tiny JPEG Decompressor) support
* 2012-08-29 amsl add Image zoom interface.
*/
#include <rtthread.h>
#include <rtgui/image.h>
#include <rtgui/image_hdc.h>
#include <rtgui/rtgui_system.h>
#include <string.h>
#ifdef _WIN32
#define strncasecmp strnicmp
#endif
#ifdef RTGUI_IMAGE_XPM
#include <rtgui/image_xpm.h>
#endif
#ifdef RTGUI_IMAGE_BMP
#include <rtgui/image_bmp.h>
#endif
#if (defined(RTGUI_IMAGE_JPEG) || defined(RTGUI_IMAGE_TJPGD))
#include <rtgui/image_jpeg.h>
#endif
#if defined(RTGUI_IMAGE_PNG) || defined(RTGUI_IMAGE_LODEPNG)
#include <rtgui/image_png.h>
#endif
static rtgui_list_t _rtgui_system_image_list = {RT_NULL};
/* initialize rtgui image system */
void rtgui_system_image_init(void)
{
/* always support HDC image */
rtgui_image_hdc_init();
#ifdef RTGUI_IMAGE_XPM
rtgui_image_xpm_init();
#endif
#ifdef RTGUI_IMAGE_BMP
rtgui_image_bmp_init();
#endif
#if (defined(RTGUI_IMAGE_JPEG) || defined(RTGUI_IMAGE_TJPGD))
rtgui_image_jpeg_init();
#endif
#if defined(RTGUI_IMAGE_PNG) || defined(RTGUI_IMAGE_LODEPNG)
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;
}
#if defined(RTGUI_USING_DFS_FILERW)
struct rtgui_image_engine *rtgui_image_get_engine_by_filename(const char *fn)
{
struct rtgui_list_node *node;
struct rtgui_image_engine *engine;
const char *ext;
ext = fn + rt_strlen(fn);
while (ext != fn)
{
if (*ext == '.')
{
ext ++;
break;
}
ext --;
}
if (ext == fn) return RT_NULL; /* no ext */
rtgui_list_foreach(node, &_rtgui_system_image_list)
{
engine = rtgui_list_entry(node, struct rtgui_image_engine, list);
if (strncasecmp(engine->name, ext, strlen(engine->name)) == 0)
return engine;
}
return RT_NULL;
}
RTM_EXPORT(rtgui_image_get_engine_by_filename);
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;
}
image->palette = 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;
}
RTM_EXPORT(rtgui_image_create_from_file);
struct rtgui_image *rtgui_image_create(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)
{
rt_kprintf("create filerw failed!\n");
return RT_NULL;
}
/* get image engine */
engine = rtgui_image_get_engine_by_filename(filename);
if (engine == RT_NULL)
{
rt_kprintf("no engine for file: %s\n", filename);
/* 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)
{
rt_kprintf("out of memory\n");
/* close filerw context */
rtgui_filerw_close(filerw);
return RT_NULL;
}
image->palette = RT_NULL;
if (engine->image_load(image, filerw, load) != RT_TRUE)
{
rt_kprintf("load image:%s failed!\n", filename);
/* close filerw context */
rtgui_filerw_close(filerw);
return RT_NULL;
}
/* set image engine */
image->engine = engine;
}
else
{
rt_kprintf("image:%s check failed!\n", filename);
rtgui_filerw_close(filerw);
}
return image;
}
RTM_EXPORT(rtgui_image_create);
#endif
struct rtgui_image *rtgui_image_create_from_mem(const char *type, const rt_uint8_t *data, rt_size_t length, 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_mem(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;
}
image->palette = 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;
}
RTM_EXPORT(rtgui_image_create_from_mem);
void rtgui_image_destroy(struct rtgui_image *image)
{
RT_ASSERT(image != RT_NULL);
image->engine->image_unload(image);
if (image->palette != RT_NULL)
rtgui_free(image->palette);
rtgui_free(image);
}
RTM_EXPORT(rtgui_image_destroy);
/* 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));
}
RTM_EXPORT(rtgui_image_register_engine);
void rtgui_image_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect)
{
struct rtgui_rect r;
RT_ASSERT(dc != RT_NULL);
if (rtgui_dc_get_visible(dc) != RT_TRUE) return;
rtgui_dc_get_rect(dc, &r);
/* use rect of DC */
if (rect == RT_NULL)
{
rect = &r;
}
else
{
/* Don't modify x1, y1, they are handled in engine->image_blit. */
if (rect->x1 > r.x2)
return;
if (rect->y1 > r.y2)
return;
if (rect->x2 > r.x2)
rect->x2 = r.x2;
if (rect->y2 > r.y2)
rect->y2 = r.y2;
}
if (image != RT_NULL && image->engine != RT_NULL)
{
/* use image engine to blit */
image->engine->image_blit(image, dc, rect);
}
}
RTM_EXPORT(rtgui_image_blit);
struct rtgui_image_palette *rtgui_image_palette_create(rt_uint32_t ncolors)
{
struct rtgui_image_palette *palette = RT_NULL;
if (ncolors > 0)
{
palette = (struct rtgui_image_palette *) rtgui_malloc(sizeof(struct rtgui_image_palette) +
sizeof(rtgui_color_t) * ncolors);
if (palette != RT_NULL) palette->colors = (rtgui_color_t *)(palette + 1);
}
return palette;
}
RTM_EXPORT(rtgui_image_palette_create);
void rtgui_image_get_rect(struct rtgui_image *image, struct rtgui_rect *rect)
{
RT_ASSERT(image != RT_NULL);
RT_ASSERT(rect != RT_NULL);
rect->x1 = 0;
rect->y1 = 0;
rect->x2 = image->w;
rect->y2 = image->h;
}
RTM_EXPORT(rtgui_image_get_rect);

View File

@ -0,0 +1,977 @@
/*
* Change Logs:
* Date Author Notes
* 2012-01-24 onelife Reimplement to improve efficiency and add
* features. The new decoder uses configurable fixed size working buffer and
* provides scaledown function.
*/
#include <rtthread.h>
#include <rtgui/dc_hw.h>
#include <rtgui/image.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/image_bmp.h>
#include <rtgui/blit.h>
#include <math.h>
#ifdef RTGUI_USING_DFS_FILERW
#include <dfs_posix.h>
#endif
#ifdef RTGUI_IMAGE_BMP
/* Compression encodings for BMP files */
#ifndef BI_RGB
#define BI_RGB 0
#define BI_RLE8 1
#define BI_RLE4 2
#define BI_BITFIELDS 3
#endif
#define BMP_WORKING_BUFFER_SIZE (384) /* In multiple of 12 and bigger than 48 */
#define BMP_MAX_SCALING_FACTOR (10) // TODO: find the max value!
#define hw_driver (rtgui_graphic_driver_get_default())
struct rtgui_image_bmp
{
rt_bool_t is_loaded;
rt_uint8_t *pixels;
struct rtgui_filerw *filerw;
rt_uint32_t w, h;
rt_uint32_t pixel_offset;
rt_uint32_t pitch;
rt_uint8_t scale;
rt_uint8_t bit_per_pixel;
rt_uint8_t pad;
};
static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw *file);
static rt_bool_t rtgui_image_bmp_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load);
static void rtgui_image_bmp_unload(struct rtgui_image *image);
static void rtgui_image_bmp_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect);
struct rtgui_image_engine rtgui_image_bmp_engine =
{
"bmp",
{ RT_NULL },
rtgui_image_bmp_check,
rtgui_image_bmp_load,
rtgui_image_bmp_unload,
rtgui_image_bmp_blit,
};
static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw *file)
{
rt_uint8_t buffer[18];
rt_bool_t is_bmp = RT_FALSE;
do
{
if (!file)
{
break;
}
/* Prepare to decode */
if (rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET) < 0)
{
break;
}
if (rtgui_filerw_read(file, (void *)buffer, 18, 1) != 18)
{
break;
}
/* Read file type */
if (buffer[0] != 'B' || buffer[1] != 'M')
{
break;
}
/* Read BMP header size */
if (*(rt_uint32_t *)&buffer[14] == 12)
{
/* Bitmap Header Version 2.x */
if (rtgui_filerw_read(file, (void *)buffer, 8, 1) != 8)
{
break;
}
/* Read image size */
is_bmp = RT_TRUE;
}
else
{
/* Bitmap Header Version bigger than 2.x */
if (rtgui_filerw_read(file, (void *)buffer, 8, 1) != 8)
{
break;
}
/* Read image size */
is_bmp = RT_TRUE;
}
} while (0);
return is_bmp;
}
static struct rtgui_image_palette *rtgui_image_bmp_load_palette(
struct rtgui_filerw *file,
rt_uint32_t colorsUsed,
rt_bool_t alpha)
{
/* Load the palette, if any */
rt_uint32_t i;
struct rtgui_image_palette *palette;
palette = rtgui_image_palette_create(colorsUsed);
if (palette == RT_NULL)
{
return RT_NULL;
}
palette->ncolors = colorsUsed;
if (alpha)
{
rt_uint8_t temp[4];
for (i = 0; i < colorsUsed; i++)
{
if (rtgui_filerw_read(file, (void *)&temp, 1, 4) != 4)
{
rtgui_free(palette);
return RT_NULL;
}
palette->colors[i] = RTGUI_ARGB(temp[3], temp[2], temp[1], temp[0]);
}
}
else
{
rt_uint8_t temp[3];
for (i = 0; i < colorsUsed; i++)
{
if (rtgui_filerw_read(file, (void *)&temp, 1, 3) != 3)
{
rtgui_free(palette);
return RT_NULL;
}
palette->colors[i] = RTGUI_RGB(temp[2], temp[1], temp[0]);
}
}
return palette;
}
static rt_bool_t rtgui_image_bmp_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
{
rt_uint8_t scale = 0;
rt_uint8_t *wrkBuffer = RT_NULL;
struct rtgui_image_bmp *bmp = RT_NULL;
rt_uint32_t bmpHeaderSize;
rt_uint32_t colorsUsed;
if (scale > BMP_MAX_SCALING_FACTOR)
{
return RT_FALSE;
}
do
{
wrkBuffer = (rt_uint8_t *)rtgui_malloc(BMP_WORKING_BUFFER_SIZE);
if (wrkBuffer == RT_NULL)
{
rt_kprintf("BMP err: no mem\n");
break;
}
bmp = (struct rtgui_image_bmp *)rtgui_malloc(sizeof(struct rtgui_image_bmp));
if (bmp == RT_NULL)
{
break;
}
bmp->pixels = RT_NULL;
/* Prepare to decode */
if (rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET) < 0)
{
break;
}
if (rtgui_filerw_read(file, (void *)wrkBuffer, 18, 1) != 18)
{
break;
}
/* Read file type */
if (wrkBuffer[0] != 'B' || wrkBuffer[1] != 'M')
{
break;
}
/* Read pixel array offset */
bmp->pixel_offset = *(rt_uint32_t *)&wrkBuffer[10];
/* Read BMP header size */
bmpHeaderSize = *(rt_uint32_t *)&wrkBuffer[14];
colorsUsed = 0;
if (bmpHeaderSize == 12)
{
/* Bitmap Header Version 2.x */
if (rtgui_filerw_read(file, (void *)wrkBuffer, 8, 1) != 8)
{
break;
}
/* Read image size */
bmp->w = (rt_uint32_t) * (rt_uint16_t *)&wrkBuffer[0];
bmp->h = (rt_uint32_t) * (rt_uint16_t *)&wrkBuffer[2];
/* Read bits per pixel */
bmp->bit_per_pixel = (rt_uint8_t) * (rt_uint16_t *)&wrkBuffer[6];
}
else
{
/* Bitmap Header Version bigger than 2.x */
rt_uint32_t compression;
if (rtgui_filerw_read(file, (void *)wrkBuffer, 36, 1) != 36)
{
break;
}
/* Read image size */
bmp->w = *(rt_uint32_t *)&wrkBuffer[0];
bmp->h = *(rt_uint32_t *)&wrkBuffer[4];
/* Read bits per pixel */
bmp->bit_per_pixel = (rt_uint8_t) * (rt_uint16_t *)&wrkBuffer[10];
if (bmp->bit_per_pixel > 32)
{
rt_kprintf("BMP err: unsupported format\n");
break;
}
/* Read compression method */
compression = *(rt_uint32_t *)&wrkBuffer[12];
if (compression != BI_RGB && compression != BI_BITFIELDS)
{
rt_kprintf("BMP err: unsupported format\n");
break;
}
/* Read number of colors */
colorsUsed = *(rt_uint32_t *)&wrkBuffer[28];
}
if (!colorsUsed)
{
colorsUsed = 1 << bmp->bit_per_pixel;
}
/* Load palette */
if (bmp->bit_per_pixel <= 8)
{
if (rtgui_filerw_seek(file, 14 + bmpHeaderSize, RTGUI_FILE_SEEK_SET) < 0)
{
break;
}
image->palette = rtgui_image_bmp_load_palette(file, colorsUsed,
bmpHeaderSize > 12 ? RT_TRUE : RT_FALSE);
if (image->palette == RT_NULL)
{
break;
}
}
/* Set image information */
bmp->is_loaded = RT_FALSE;
bmp->scale = scale;
if (bmp->bit_per_pixel == 1)
{
bmp->pitch = (bmp->w + 7) >> 3;
}
else if (bmp->bit_per_pixel == 4)
{
bmp->pitch = (bmp->w + 1) >> 1;
}
else
{
bmp->pitch = bmp->w * (bmp->bit_per_pixel >> 3);
}
bmp->pad = ((bmp->pitch % 4) ? (4 - (bmp->pitch % 4)) : 0);
bmp->filerw = file;
image->w = (rt_uint16_t)bmp->w >> bmp->scale;
image->h = (rt_uint16_t)bmp->h >> bmp->scale;
image->engine = &rtgui_image_bmp_engine;
image->data = bmp;
/* Start to decode */
if (load == RT_TRUE)
{
rt_bool_t error = RT_FALSE;
rt_uint8_t *dst;
rt_uint32_t imageWidth;
rt_uint16_t readLength, readIndex, loadIndex;
rt_uint8_t skipLength;
rt_uint16_t y;
rt_uint8_t bytePerPixel;
rt_int8_t scale1, scale2;
bytePerPixel = _UI_BITBYTES(bmp->bit_per_pixel);
imageWidth = image->w * bytePerPixel; /* Scaled width in byte */
bmp->pixels = rtgui_malloc(image->h * imageWidth);
if (bmp->pixels == RT_NULL)
{
rt_kprintf("BMP err: no mem to load (%d)\n", image->h * imageWidth);
break;
}
/* Read the pixels. Note that the bmp image is upside down */
if (rtgui_filerw_seek(file, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
{
break;
}
if (bmp->bit_per_pixel == 1)
{
if (bmp->scale > 3)
{
scale1 = bmp->scale - 3;
scale2 = 3;
}
else
{
scale1 = 0;
scale2 = bmp->scale;
}
}
else if (bmp->bit_per_pixel == 4)
{
if (bmp->scale > 1)
{
scale1 = bmp->scale - 1;
scale2 = 1;
}
else
{
scale1 = 0;
scale2 = bmp->scale;
}
}
/* Process whole image */
y = 0;
while (y < image->h)
{
dst = bmp->pixels + (image->h - y - 1) * imageWidth;
readIndex = 0;
skipLength = 0;
/* Process a line */
while (readIndex < bmp->pitch)
{
/* Read data to buffer */
readLength = (BMP_WORKING_BUFFER_SIZE > ((rt_uint16_t)bmp->pitch - readIndex)) ? \
((rt_uint16_t)bmp->pitch - readIndex) : BMP_WORKING_BUFFER_SIZE;
if (rtgui_filerw_read(file, (void *)wrkBuffer, 1, readLength) != readLength)
{
rt_kprintf("BMP err: read failed\n");
error = RT_TRUE;
break;
}
readIndex += readLength;
/* Process read buffer */
if (bmp->bit_per_pixel == 1)
{
rt_uint8_t j;
for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
{
for (j = 0; j < 8; j += 1 << scale2)
{
*(dst++) = (wrkBuffer[loadIndex] & (1 << (7 - j))) >> (7 - j);
}
}
if (scale1 && (readLength % (1 << scale1)))
{
skipLength = (1 << scale1) - readLength % (1 << scale1);
}
}
else if (bmp->bit_per_pixel == 4)
{
rt_uint8_t j;
for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
{
for (j = 0; j < 8; j += 1 << (2 + scale2))
{
*(dst++) = (wrkBuffer[loadIndex] & (0x0F << (4 - j))) >> (4 - j);
}
}
if (scale1 && (readLength % (1 << scale1)))
{
skipLength = (1 << scale1) - readLength % (1 << scale1);
}
}
else
{
if (bmp->scale == 0)
{
rt_memcpy((void *)dst, (void *)wrkBuffer, readLength);
dst += readLength;
}
else
{
for (loadIndex = skipLength; loadIndex < readLength; loadIndex += bytePerPixel << bmp->scale)
{
rt_memcpy((void *)dst, (void *)&wrkBuffer[loadIndex], bytePerPixel);
dst += bytePerPixel;
}
if (readLength % (1 << bmp->scale))
{
skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
}
}
}
}
if (error)
{
break;
}
y++;
/* Skip padding bytes */
if (bmp->pad)
{
if (rtgui_filerw_seek(file, bmp->pad, RTGUI_FILE_SEEK_CUR) < 0)
{
error = RT_TRUE;
break;
}
}
/* Height scale down */
if (bmp->scale)
{
if (rtgui_filerw_seek(file, (bmp->pitch + bmp->pad) * ((1 << bmp->scale) - 1),
RTGUI_FILE_SEEK_CUR) < 0)
{
error = RT_TRUE;
break;
}
}
}
if (error)
{
break;
}
/* Close file */
rtgui_filerw_close(bmp->filerw);
bmp->filerw = RT_NULL;
bmp->is_loaded = RT_TRUE;
}
/* Release memory */
rtgui_free(wrkBuffer);
return RT_TRUE;
} while (0);
/* Release memory */
rtgui_free(wrkBuffer);
rtgui_free(image->palette);
if (bmp)
rtgui_free(bmp->pixels);
rtgui_free(bmp);
return RT_FALSE;
}
static void rtgui_image_bmp_unload(struct rtgui_image *image)
{
struct rtgui_image_bmp *bmp;
if (image != RT_NULL)
{
bmp = (struct rtgui_image_bmp *)image->data;
/* Release memory */
rtgui_free(bmp->pixels);
if (bmp->filerw != RT_NULL)
{
/* Close file */
rtgui_filerw_close(bmp->filerw);
bmp->filerw = RT_NULL;
}
rtgui_free(bmp);
}
}
static void rtgui_image_bmp_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *dst_rect)
{
rt_uint16_t w, h;
struct rtgui_image_bmp *bmp;
rt_uint8_t bytePerPixel;
rt_uint32_t imageWidth;
rt_bool_t error;
bmp = (struct rtgui_image_bmp *)image->data;
RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL || bmp != RT_NULL);
bytePerPixel = _UI_BITBYTES(bmp->bit_per_pixel);
imageWidth = image->w * bytePerPixel; /* Scaled width in byte */
error = RT_FALSE;
do
{
/* this dc is not visible */
if (rtgui_dc_get_visible(dc) != RT_TRUE) break;
/* the minimum rect */
w = _UI_MIN(image->w, rtgui_rect_width(*dst_rect));
h = _UI_MIN(image->h, rtgui_rect_height(*dst_rect));
if (!bmp->is_loaded)
{
rt_uint8_t *wrkBuffer;
rt_uint16_t readLength, readIndex, loadIndex;
rt_uint8_t skipLength;
rt_uint16_t x, y;
rt_int8_t scale1, scale2;
rt_uint16_t y_start = dst_rect->y1 + h - 1;
/* Read the pixels. Note that the bmp image is upside down */
if (rtgui_filerw_seek(bmp->filerw, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
{
break;
}
/* the image is upside down. So we need to start from middle if the
* image is higher than the dst_rect. */
if (image->h > rtgui_rect_height(*dst_rect))
{
int hdelta = image->h - rtgui_rect_height(*dst_rect);
if (rtgui_filerw_seek(bmp->filerw, hdelta * (bmp->pitch + bmp->pad) * (1 << bmp->scale),
RTGUI_FILE_SEEK_CUR) < 0)
{
error = RT_TRUE;
break;
}
}
if (bmp->bit_per_pixel == 1)
{
if (bmp->scale > 3)
{
scale1 = bmp->scale - 3;
scale2 = 3;
}
else
{
scale1 = 0;
scale2 = bmp->scale;
}
}
else if (bmp->bit_per_pixel == 4)
{
if (bmp->scale > 1)
{
scale1 = bmp->scale - 1;
scale2 = 1;
}
else
{
scale1 = 0;
scale2 = bmp->scale;
}
}
wrkBuffer = (rt_uint8_t *)rtgui_malloc(
(BMP_WORKING_BUFFER_SIZE > bmp->pitch) ? \
bmp->pitch : BMP_WORKING_BUFFER_SIZE);
if (wrkBuffer == RT_NULL)
{
rt_kprintf("BMP err: no mem (%d)\n", BMP_WORKING_BUFFER_SIZE);
break;
}
/* Process whole image */
y = 0;
while (y < h)
{
x = 0;
readIndex = 0;
skipLength = 0;
/* Process a line */
while (readIndex < bmp->pitch)
{
/* Read data to buffer */
readLength = (BMP_WORKING_BUFFER_SIZE > ((rt_uint16_t)bmp->pitch - readIndex)) ? \
((rt_uint16_t)bmp->pitch - readIndex) : BMP_WORKING_BUFFER_SIZE;
if (rtgui_filerw_read(bmp->filerw, (void *)wrkBuffer, 1, readLength) != readLength)
{
rt_kprintf("BMP err: read failed\n");
error = RT_TRUE;
break;
}
readIndex += readLength;
/* Process read buffer */
if (bmp->bit_per_pixel == 1)
{
for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
{
rt_uint8_t j;
for (j = 0; j < 8; j += 1 << scale2)
{
rtgui_color_t color;
color = image->palette->colors[(wrkBuffer[loadIndex] & (1 << (7 - j))) >> (7 - j)];
rtgui_dc_draw_color_point(dc,
dst_rect->x1 + x++,
y_start - y,
color);
if (x >= w)
break;
}
if (scale1 && (readLength % (1 << scale1)))
{
skipLength = (1 << scale1) - readLength % (1 << scale1);
}
}
}
else if (bmp->bit_per_pixel == 4)
{
for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << scale1)
{
rt_uint8_t j;
for (j = 0; j < 8; j += 1 << (2 + scale2))
{
rtgui_color_t color;
color = image->palette->colors[(wrkBuffer[loadIndex] & (0x0F << (4 - j))) >> (4 - j)];
rtgui_dc_draw_color_point(dc,
dst_rect->x1 + x++,
y_start - y,
color);
if (x >= w)
break;
}
}
if (scale1 && (readLength % (1 << scale1)))
{
skipLength = (1 << scale1) - readLength % (1 << scale1);
}
}
else if (bmp->bit_per_pixel == 8)
{
for (loadIndex = skipLength; loadIndex < readLength; loadIndex += 1 << bmp->scale)
{
rtgui_color_t color;
color = image->palette->colors[wrkBuffer[loadIndex]];
rtgui_dc_draw_color_point(dc,
dst_rect->x1 + x++,
y_start - y,
color);
if (x >= w)
break;
}
if (readLength % (1 << bmp->scale))
{
skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
}
}
else
{
rtgui_blit_line_func blit_line;
rt_uint8_t hw_bytePerPixel = _UI_BITBYTES(hw_driver->bits_per_pixel);
rt_uint8_t temp[4] = {0};
if (!hw_bytePerPixel)
{
hw_bytePerPixel = 1;
}
if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_BGR565)
{
blit_line = rtgui_blit_line_get_inv(hw_bytePerPixel, bytePerPixel);
}
else
{
blit_line = rtgui_blit_line_get(hw_bytePerPixel, bytePerPixel);
}
for (loadIndex = skipLength;
loadIndex < readLength;
loadIndex += bytePerPixel << bmp->scale)
{
blit_line(temp, &wrkBuffer[loadIndex], bytePerPixel);
dc->engine->blit_line(dc,
dst_rect->x1 + x, dst_rect->x1 + x + 1,
y_start - y,
temp);
x++;
if (x >= w)
break;
}
if (readLength % (1 << bmp->scale))
{
skipLength = (1 << bmp->scale) - readLength % (1 << bmp->scale);
}
}
}
if (error)
{
break;
}
y++;
/* Skip padding bytes */
if (bmp->pad)
{
if (rtgui_filerw_seek(bmp->filerw, bmp->pad, RTGUI_FILE_SEEK_CUR) < 0)
{
error = RT_TRUE;
break;
}
}
/* Height scale down */
if (bmp->scale)
{
if (rtgui_filerw_seek(bmp->filerw, (bmp->pitch + bmp->pad) * ((1 << bmp->scale) - 1),
RTGUI_FILE_SEEK_CUR) < 0)
{
error = RT_TRUE;
break;
}
}
}
if (error)
{
break;
}
/* Release memory */
rtgui_free(wrkBuffer);
}
else
{
rt_uint16_t x, y;
rt_uint8_t *ptr;
if (bmp->bit_per_pixel <= 8)
{
rtgui_color_t color;
/* 1bpp, and using palette */
for (y = 0; y < h; y ++)
{
ptr = bmp->pixels + (y * imageWidth);
for (x = 0; x < w; x ++)
{
color = image->palette->colors[*(ptr++)];
rtgui_dc_draw_color_point(dc,
dst_rect->x1 + x, dst_rect->y1 + y,
color);
}
}
}
else
{
rtgui_blit_line_func blit_line;
rt_uint8_t hw_bytePerPixel = _UI_BITBYTES(hw_driver->bits_per_pixel);
rt_uint8_t *line_data;
if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_BGR565)
{
blit_line = rtgui_blit_line_get_inv(hw_bytePerPixel, bytePerPixel);
}
else
{
blit_line = rtgui_blit_line_get(hw_bytePerPixel, bytePerPixel);
}
line_data = (rt_uint8_t *)rtgui_malloc(w * rtgui_color_get_bpp(hw_driver->pixel_format));
if (line_data == RT_NULL) break; /* out of memory */
ptr = bmp->pixels;
for (y = 0; y < h; y ++)
{
blit_line(line_data, ptr, bytePerPixel * w);
ptr += imageWidth;
dc->engine->blit_line(dc, dst_rect->x1, dst_rect->x1 + w,
dst_rect->y1 + y, line_data);
}
rtgui_free(line_data);
}
}
} while (0);
}
/*
* config bitmap header.
*/
void rtgui_image_bmp_header_cfg(struct rtgui_image_bmp_header *bhr, rt_int32_t w, rt_int32_t h, rt_uint16_t bits_per_pixel)
{
int image_size = w * h * _UI_BITBYTES(bits_per_pixel);
int header_size = sizeof(struct rtgui_image_bmp_header);
bhr->bfType = 0x4d42; /* BM */
bhr->bfSize = header_size + image_size; /* data size */
bhr->bfReserved1 = 0;
bhr->bfReserved2 = 0;
bhr->bfOffBits = header_size;
bhr->biSize = 40; /* sizeof BITMAPINFOHEADER */
bhr->biWidth = w;
bhr->biHeight = h;
bhr->biPlanes = 1;
bhr->biBitCount = bits_per_pixel;
bhr->biCompression = BI_BITFIELDS;
bhr->biSizeImage = image_size;
bhr->biXPelsPerMeter = 0;
bhr->biYPelsPerMeter = 0;
bhr->biClrUsed = 0;
bhr->biClrImportant = 0;
if (bhr->biBitCount == 16 && bhr->biCompression == BI_BITFIELDS)
{
bhr->bfSize += 12;
bhr->bfOffBits += 12;
}
}
#ifdef RTGUI_USING_DFS_FILERW
#define WRITE_CLUSTER_SIZE 2048
void bmp_align_write(struct rtgui_filerw *file, char *dest, char *src, rt_int32_t len, rt_int32_t *count)
{
rt_int32_t len_bak = len;
while (len)
{
if (*count >= WRITE_CLUSTER_SIZE)
{
rtgui_filerw_write(file, dest, WRITE_CLUSTER_SIZE, 1);
*count = 0;
}
*(dest + *count) = *(src + (len_bak - len));
len --;
(*count) ++;
}
}
/*
* Grab screen and save as a BMP file
* MACRO RGB_CONVERT_TO_BGR: If the pixel of colors is BGR mode, defined it.
*/
void screenshot(const char *filename)
{
struct rtgui_filerw *file;
int w, h, i, pitch;
rt_uint16_t *src;
rt_uint32_t mask;
struct rtgui_image_bmp_header bhr;
struct rtgui_graphic_driver *grp = hw_driver;
#ifdef RGB_CONVERT_TO_BGR
int j;
rt_uint16_t *line_buf;
rt_uint16_t color, tmp;
#endif
char *pixel_buf;
rt_int32_t write_count = 0;
file = rtgui_filerw_create_file(filename, "wb");
if (file == RT_NULL)
{
rt_kprintf("create file failed\n");
return;
}
w = grp->width;
h = grp->height;
pitch = w * sizeof(rt_uint16_t);
#ifdef RGB_CONVERT_TO_BGR
line_buf = rt_malloc(pitch);
if (line_buf == RT_NULL)
{
rt_kprintf("no memory!\n");
return;
}
#endif
pixel_buf = rt_malloc(WRITE_CLUSTER_SIZE);
if (pixel_buf == RT_NULL)
{
rt_kprintf("no memory!\n");
#ifdef RGB_CONVERT_TO_BGR
rt_free(line_buf);
#endif
return;
}
rtgui_image_bmp_header_cfg(&bhr, w, h, grp->bits_per_pixel);
bmp_align_write(file, pixel_buf, (char *)&bhr,
sizeof(struct rtgui_image_bmp_header), &write_count);
if (bhr.biCompression == BI_BITFIELDS)
{
mask = 0xF800; /* Red Mask */
bmp_align_write(file, pixel_buf, (char *)&mask, 4, &write_count);
mask = 0x07E0; /* Green Mask */
bmp_align_write(file, pixel_buf, (char *)&mask, 4, &write_count);
mask = 0x001F; /* Blue Mask */
bmp_align_write(file, pixel_buf, (char *)&mask, 4, &write_count);
}
rtgui_screen_lock(RT_WAITING_FOREVER);
if (grp->framebuffer != RT_NULL)
{
src = (rt_uint16_t *)grp->framebuffer;
src += w * h;
for (i = 0; i < h; i++)
{
src -= w;
#ifdef RGB_CONVERT_TO_BGR
for (j = 0; j < w; j++)
{
tmp = *(src + j);
color = (tmp & 0x001F) << 11;
color += (tmp & 0x07E0);
color += (tmp & 0xF800) >> 11;
*(line_buf + i) = color;
}
bmp_align_write(file, pixel_buf, (char *)line_buf, pitch, &write_count);
#else
bmp_align_write(file, pixel_buf, (char *)src, pitch, &write_count);
#endif
}
}
else
{
rtgui_color_t pixel_color;
rt_uint16_t write_color;
int x;
for (i = h - 1; i >= 0; i--)
{
x = 0;
if (i % 10 == 0)rt_kprintf(">", i);
while (x < w)
{
grp->ops->get_pixel(&pixel_color, x, i);
write_color = rtgui_color_to_565p(pixel_color);
bmp_align_write(file, pixel_buf, (char *)&write_color,
sizeof(rt_uint16_t), &write_count);
x++;
}
}
}
/* write The tail of the last */
if (write_count < WRITE_CLUSTER_SIZE)
rtgui_filerw_write(file, pixel_buf, write_count, 1);
rtgui_screen_unlock();
#ifdef RGB_CONVERT_TO_BGR
rt_free(line_buf);
#endif
rt_free(pixel_buf);
rt_kprintf("bmp create succeed.\n");
rtgui_filerw_close(file);
}
#ifdef RT_USING_FINSH
#include <finsh.h>
FINSH_FUNCTION_EXPORT(screenshot, usage: screenshot(filename));
#endif
#endif
void rtgui_image_bmp_init()
{
/* register bmp on image system */
rtgui_image_register_engine(&rtgui_image_bmp_engine);
}
#endif

View File

@ -0,0 +1,449 @@
#include <rtthread.h>
#include <rtgui/dc_hw.h>
#include <rtgui/image.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/image_hdc.h>
#include <rtgui/blit.h>
#define HDC_MAGIC_LEN 4
extern int fastlz_decompress(const void *input, int length, void *output, int maxout);
struct rtgui_image_hdc
{
rt_bool_t is_loaded;
/* hdc image information */
rt_uint16_t byte_per_pixel;
rt_uint16_t pitch;
rt_uint8_t pixel_format;
rt_size_t pixel_offset;
rt_uint8_t *pixels;
struct rtgui_filerw *filerw;
};
static rt_bool_t rtgui_image_hdc_check(struct rtgui_filerw *file);
static rt_bool_t rtgui_image_hdc_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load);
static void rtgui_image_hdc_unload(struct rtgui_image *image);
static void rtgui_image_hdc_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect);
static void rtgui_image_hdcmm_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *dst_rect);
struct rtgui_image_engine rtgui_image_hdc_engine =
{
"hdc",
{ RT_NULL },
rtgui_image_hdc_check,
rtgui_image_hdc_load,
rtgui_image_hdc_unload,
rtgui_image_hdc_blit,
};
const struct rtgui_image_engine rtgui_image_hdcmm_engine =
{
"hdcmm",
{RT_NULL},
RT_NULL,
RT_NULL,
RT_NULL,
rtgui_image_hdcmm_blit,
};
static rt_bool_t rtgui_image_hdc_check(struct rtgui_filerw *file)
{
int start;
rt_bool_t is_HDC;
rt_uint8_t magic[4];
if (!file) return 0;
start = rtgui_filerw_tell(file);
/* move to the beginning of file */
rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET);
is_HDC = RT_FALSE;
if (rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic))
{
if (magic[0] == 'H' &&
magic[1] == 'D' &&
magic[2] == 'C' &&
magic[3] == '\0')
{
is_HDC = RT_TRUE;
}
}
rtgui_filerw_seek(file, start, RTGUI_FILE_SEEK_SET);
return (is_HDC);
}
static rt_bool_t rtgui_image_hdc_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
{
rt_uint32_t header[5];
struct rtgui_image_hdc *hdc;
hdc = (struct rtgui_image_hdc *) rtgui_malloc(sizeof(struct rtgui_image_hdc));
if (hdc == RT_NULL) return RT_FALSE;
rtgui_filerw_read(file, (char *)&header, 1, sizeof(header));
/* set image information */
image->w = (rt_uint16_t)header[1];
image->h = (rt_uint16_t)header[2];
image->engine = &rtgui_image_hdc_engine;
image->data = hdc;
hdc->pixel_format = header[3];
hdc->filerw = file;
if (header[3] == 0)
{
/* 0.x version */
hdc->pixel_format = rtgui_graphic_driver_get_default()->pixel_format;
}
else if (header[3] == 1)
{
/* 1.x version */
hdc->pixel_format = header[4];
}
else if (header[3] == 2)
{
/* 2.x version */
hdc->pixel_format = header[4];
}
hdc->byte_per_pixel = rtgui_color_get_bpp(hdc->pixel_format);
hdc->pitch = image->w * hdc->byte_per_pixel;
hdc->pixel_offset = rtgui_filerw_tell(file);
if (load == RT_TRUE)
{
if (header[3] == 2)
{
#if 0 /* TODO: add HDC with fastlz compressed */
int data_length, dec_length;
rt_uint8_t *data;
data_length = rtgui_filerw_seek(hdc->filerw, 0, SEEK_END) - sizeof(header);
rtgui_filerw_seek(hdc->filerw, sizeof(header), SEEK_SET);
data = (rt_uint8_t *)rtgui_malloc(data_length);
if (data == RT_NULL)
{
/* release data */
rtgui_free(hdc);
return RT_FALSE;
}
if (rtgui_filerw_read(hdc->filerw, data, 1, data_length) != data_length)
{
rtgui_filerw_close(hdc->filerw);
/* release data */
rtgui_free(hdc);
return RT_FALSE;
}
rtgui_filerw_close(hdc->filerw);
hdc->filerw = RT_NULL;
hdc->pixels = (rt_uint8_t *)rtgui_malloc(image->h * hdc->pitch);
if (hdc->pixels == RT_NULL)
{
/* release data */
rtgui_free(hdc);
rtgui_free(data);
return RT_FALSE;
}
dec_length = fastlz_decompress(data, data_length, hdc->pixels, image->h * hdc->pitch);
if (dec_length != image->h * hdc->pitch)
{
/* release data */
rtgui_free(hdc->pixels);
rtgui_free(hdc);
rtgui_free(data);
return RT_FALSE;
}
hdc->pixel_offset = 0;
rtgui_free(data);
#endif
}
else
{
/* load all pixels */
hdc->pixels = rtgui_malloc(image->h * hdc->pitch);
if (hdc->pixels == RT_NULL)
{
/* release data */
rtgui_free(hdc);
return RT_FALSE;
}
rtgui_filerw_read(hdc->filerw, hdc->pixels, 1, image->h * hdc->pitch);
rtgui_filerw_close(hdc->filerw);
hdc->filerw = RT_NULL;
hdc->pixel_offset = 0;
}
}
else
{
hdc->pixels = RT_NULL;
}
return RT_TRUE;
}
static void rtgui_image_hdc_unload(struct rtgui_image *image)
{
struct rtgui_image_hdc *hdc;
if (image != RT_NULL)
{
hdc = (struct rtgui_image_hdc *) image->data;
if (hdc->pixels != RT_NULL)
rtgui_free(hdc->pixels);
if (hdc->filerw != RT_NULL)
rtgui_filerw_close(hdc->filerw);
/* release data */
rtgui_free(hdc);
}
}
static void rtgui_image_hdc_blit(struct rtgui_image *image,
struct rtgui_dc *dc,
struct rtgui_rect *dst_rect)
{
rt_int16_t y, w, h, xoff, yoff;
struct rtgui_image_hdc *hdc;
RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL);
/* this dc is not visible */
if (rtgui_dc_get_visible(dc) != RT_TRUE)
return;
if (!image)
return;
hdc = (struct rtgui_image_hdc *) image->data;
RT_ASSERT(hdc != RT_NULL);
xoff = 0;
if (dst_rect->x1 < 0)
{
xoff = -dst_rect->x1;
dst_rect->x1 = 0;
}
yoff = 0;
if (dst_rect->y1 < 0)
{
yoff = -dst_rect->y1;
dst_rect->y1 = 0;
}
if (dst_rect->x2 <= 0 || dst_rect->y2 <= 0)
return;
if (xoff >= image->w || yoff >= image->h)
return;
/* the minimum rect */
w = _UI_MIN(image->w - xoff, rtgui_rect_width(*dst_rect));
h = _UI_MIN(image->h - yoff, rtgui_rect_height(*dst_rect));
if (w == 0 || h == 0)
return;
if (hdc->pixels != RT_NULL)
{
rt_uint8_t *ptr;
/* get pixel pointer */
ptr = hdc->pixels + hdc->pitch * yoff + hdc->byte_per_pixel * xoff;
if (hdc->pixel_format == rtgui_dc_get_pixel_format(dc) &&
hdc->pixel_format != RTGRAPHIC_PIXEL_FORMAT_ARGB888)
{
for (y = 0; y < h; y ++)
{
dc->engine->blit_line(dc,
dst_rect->x1,
dst_rect->x1 + w,
dst_rect->y1 + y,
ptr);
ptr += hdc->pitch;
}
}
else if (dc->type == RTGUI_DC_CLIENT)
{
const struct rtgui_graphic_driver *hw_driver;
struct rtgui_widget *owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
hw_driver = rtgui_graphic_driver_get_default();
if (hdc->pixel_format == RTGRAPHIC_PIXEL_FORMAT_ARGB888)
{
rt_uint8_t alpha;
for (y = 0; y < h; y ++)
{
int x;
rtgui_color_t *pixel = (rtgui_color_t *)(hdc->pixels + hdc->pitch * (yoff + y) + hdc->byte_per_pixel * xoff);
for (x = 0; x < w; x ++)
{
alpha = RTGUI_RGB_A(*pixel);
if (alpha == 0) { }
if (alpha == 0xff)
{
rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, *pixel);
}
else
{
/* draw an alpha blending point */
if (hw_driver->framebuffer != RT_NULL)
rtgui_dc_blend_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, RTGUI_BLENDMODE_BLEND,
RTGUI_RGB_R(*pixel), RTGUI_RGB_G(*pixel), RTGUI_RGB_B(*pixel), RTGUI_RGB_A(*pixel));
}
pixel ++;
}
}
}
}
else
{
struct rtgui_blit_info info;
info.a = 0;
/* initialize source blit information */
info.src = ptr;
info.src_h = h;
info.src_w = w;
info.src_fmt = hdc->pixel_format;
info.src_pitch = hdc->pitch;
info.src_skip = hdc->pitch - w * rtgui_color_get_bpp(hdc->pixel_format);
/* initialize destination blit information */
if (dc->type == RTGUI_DC_BUFFER)
{
struct rtgui_dc_buffer *buffer;
buffer = (struct rtgui_dc_buffer *)dc;
info.dst = rtgui_dc_buffer_get_pixel(RTGUI_DC(buffer)) + dst_rect->y1 * buffer->pitch +
dst_rect->x1 * rtgui_color_get_bpp(buffer->pixel_format);
info.dst_h = h;
info.dst_w = w;
info.dst_fmt = buffer->pixel_format;
info.dst_pitch = buffer->pitch;
info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(buffer->pixel_format);
}
else if (dc->type == RTGUI_DC_HW)
{
struct rtgui_widget *owner;
struct rtgui_rect r;
struct rtgui_dc_hw *ddc = (struct rtgui_dc_hw *)dc;
owner = ((struct rtgui_dc_hw *)dc)->owner;
rtgui_graphic_driver_get_rect(RT_NULL, &r);
/* blit destination */
info.dst = (rt_uint8_t *)ddc->hw_driver->framebuffer;
info.dst = info.dst + (owner->extent.y1 + dst_rect->y1) * ddc->hw_driver->pitch +
(owner->extent.x1 + dst_rect->x1) * rtgui_color_get_bpp(ddc->hw_driver->pixel_format);
info.dst_fmt = ddc->hw_driver->pixel_format;
info.dst_h = h;
info.dst_w = w;
info.dst_pitch = ddc->hw_driver->pitch;
info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(ddc->hw_driver->pixel_format);
}
rtgui_blit(&info);
}
}
else
{
rt_uint8_t *ptr;
ptr = rtgui_malloc(hdc->byte_per_pixel * w);
if (ptr == RT_NULL)
return; /* no memory */
/* seek to the begin of pixel data */
rtgui_filerw_seek(hdc->filerw,
hdc->pixel_offset + hdc->pitch * yoff + hdc->byte_per_pixel * xoff,
RTGUI_FILE_SEEK_SET);
for (y = 0; y < h; y ++)
{
/* read pixel data */
if (rtgui_filerw_read(hdc->filerw, ptr, 1,
hdc->byte_per_pixel * w) != hdc->byte_per_pixel * w)
break; /* read data failed */
dc->engine->blit_line(dc,
dst_rect->x1,
dst_rect->x1 + w,
dst_rect->y1 + y,
ptr);
rtgui_filerw_seek(hdc->filerw, hdc->byte_per_pixel * xoff, RTGUI_FILE_SEEK_CUR);
}
rtgui_free(ptr);
}
}
static void rtgui_image_hdcmm_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *dst_rect)
{
rt_uint8_t *ptr;
rt_uint16_t y, w, h, xoff, yoff;
struct rtgui_image_hdcmm *hdc;
RT_ASSERT(image != RT_NULL && dc != RT_NULL && dst_rect != RT_NULL);
/* this dc is not visible */
if (rtgui_dc_get_visible(dc) != RT_TRUE)
return;
hdc = (struct rtgui_image_hdcmm *) image;
if (!hdc->pixels)
return;
xoff = 0;
if (dst_rect->x1 < 0)
{
xoff = -dst_rect->x1;
dst_rect->x1 = 0;
}
yoff = 0;
if (dst_rect->y1 < 0)
{
yoff = -dst_rect->y1;
dst_rect->y1 = 0;
}
if (xoff >= image->w || yoff >= image->h)
return;
/* the minimum rect */
w = _UI_MIN(image->w - xoff, rtgui_rect_width(*dst_rect));
h = _UI_MIN(image->h - yoff, rtgui_rect_height(*dst_rect));
/* get pixel pointer */
ptr = hdc->pixels + hdc->pitch * yoff + hdc->byte_per_pixel * xoff;
for (y = 0; y < h; y++)
{
dc->engine->blit_line(dc, dst_rect->x1, dst_rect->x1 + w, dst_rect->y1 + y, ptr);
ptr += hdc->pitch;
}
}
void rtgui_image_hdc_init()
{
/* register hdc on image system */
rtgui_image_register_engine(&rtgui_image_hdc_engine);
}

View File

@ -0,0 +1,954 @@
/*
* Change Logs:
* Date Author Notes
* 2012-01-24 onelife add TJpgDec (Tiny JPEG Decompressor) support
*/
#include <rtthread.h>
#include <rtgui/rtgui.h>
#ifdef RTGUI_IMAGE_JPEG
#include <stdio.h>
#include <stdlib.h>
#include "jpeglib.h"
#include <rtgui/rtgui_system.h>
#include <rtgui/filerw.h>
#include <rtgui/image_jpeg.h>
#include <rtgui/blit.h>
#ifdef RTGUI_USING_DFS_FILERW
#include <dfs_posix.h>
#endif
static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw *file);
static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load);
static void rtgui_image_jpeg_unload(struct rtgui_image *image);
static void rtgui_image_jpeg_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect);
struct rtgui_jpeg_error_mgr
{
struct jpeg_error_mgr pub; /* "public" fields */
};
struct rtgui_image_jpeg
{
rt_bool_t is_loaded;
struct rtgui_filerw *filerw;
/* jpeg structure */
struct jpeg_decompress_struct cinfo;
struct rtgui_jpeg_error_mgr errmgr;
rt_uint8_t *pixels;
rt_uint8_t *line_pixels;
};
struct rtgui_image_engine rtgui_image_jpeg_engine =
{
"jpeg",
{RT_NULL},
rtgui_image_jpeg_check,
rtgui_image_jpeg_load,
rtgui_image_jpeg_unload,
rtgui_image_jpeg_blit
};
struct rtgui_image_engine rtgui_image_jpg_engine =
{
"jpg",
{RT_NULL},
rtgui_image_jpeg_check,
rtgui_image_jpeg_load,
rtgui_image_jpeg_unload,
rtgui_image_jpeg_blit
};
#define INPUT_BUFFER_SIZE 4096
typedef struct
{
struct jpeg_source_mgr pub;
struct rtgui_filerw *ctx;
rt_uint8_t buffer[INPUT_BUFFER_SIZE];
} rtgui_jpeg_source_mgr;
/*
* Initialize source --- called by jpeg_read_header
* before any data is actually read.
*/
static void init_source(j_decompress_ptr cinfo)
{
/* We don't actually need to do anything */
return;
}
/*
* Fill the input buffer --- called whenever buffer is emptied.
*/
static boolean fill_input_buffer(j_decompress_ptr cinfo)
{
rtgui_jpeg_source_mgr *src = (rtgui_jpeg_source_mgr *) cinfo->src;
int nbytes;
nbytes = rtgui_filerw_read(src->ctx, src->buffer, 1, INPUT_BUFFER_SIZE);
if (nbytes <= 0)
{
/* Insert a fake EOI marker */
src->buffer[0] = (rt_uint8_t) 0xFF;
src->buffer[1] = (rt_uint8_t) JPEG_EOI;
nbytes = 2;
}
src->pub.next_input_byte = src->buffer;
src->pub.bytes_in_buffer = nbytes;
return TRUE;
}
/*
* Skip data --- used to skip over a potentially large amount of
* uninteresting data (such as an APPn marker).
*
* Writers of suspendable-input applications must note that skip_input_data
* is not granted the right to give a suspension return. If the skip extends
* beyond the data currently in the buffer, the buffer can be marked empty so
* that the next read will cause a fill_input_buffer call that can suspend.
* Arranging for additional bytes to be discarded before reloading the input
* buffer is the application writer's problem.
*/
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
{
rtgui_jpeg_source_mgr *src = (rtgui_jpeg_source_mgr *) cinfo->src;
/* Just a dumb implementation for now. Could use fseek() except
* it doesn't work on pipes. Not clear that being smart is worth
* any trouble anyway --- large skips are infrequent.
*/
if (num_bytes > 0)
{
while (num_bytes > (long) src->pub.bytes_in_buffer)
{
num_bytes -= (long) src->pub.bytes_in_buffer;
(void) src->pub.fill_input_buffer(cinfo);
/* note we assume that fill_input_buffer will never
* return FALSE, so suspension need not be handled.
*/
}
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
/*
* Terminate source --- called by jpeg_finish_decompress
* after all data has been read.
*/
static void term_source(j_decompress_ptr cinfo)
{
/* We don't actually need to do anything */
return;
}
/*
* Prepare for input from a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing decompression.
*/
static void rtgui_jpeg_filerw_src_init(j_decompress_ptr cinfo, struct rtgui_filerw *ctx)
{
rtgui_jpeg_source_mgr *src;
/* The source object and input buffer are made permanent so that a series
* of JPEG images can be read from the same file by calling jpeg_stdio_src
* only before the first one. (If we discarded the buffer at the end of
* one image, we'd likely lose the start of the next one.)
* This makes it unsafe to use this manager and a different source
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) /* first time for this JPEG object? */
{
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT,
sizeof(rtgui_jpeg_source_mgr));
src = (rtgui_jpeg_source_mgr *) cinfo->src;
}
src = (rtgui_jpeg_source_mgr *) cinfo->src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->pub.term_source = term_source;
src->ctx = ctx;
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
src->pub.next_input_byte = NULL; /* until buffer loaded */
}
/* get line data of a jpeg image */
static rt_uint8_t *rtgui_image_get_line(struct rtgui_image *image, int h)
{
struct rtgui_image_jpeg *jpeg;
rt_uint8_t *result_ptr;
JSAMPARRAY buffer; /* Output row buffer */
int row_stride;
RT_ASSERT(image != RT_NULL);
jpeg = (struct rtgui_image_jpeg *) image->data;
RT_ASSERT(jpeg != RT_NULL);
if (h < 0 || h > image->h) return RT_NULL;
/* if the image is loaded, */
if (jpeg->is_loaded == RT_TRUE)
{
result_ptr = jpeg->pixels + (image->w * sizeof(rtgui_color_t)) * h;
return result_ptr;
}
if (jpeg->line_pixels == RT_NULL)
jpeg->line_pixels = rtgui_malloc(image->w * sizeof(rtgui_color_t));
row_stride = jpeg->cinfo.output_width * jpeg->cinfo.output_components;
buffer = (*jpeg->cinfo.mem->alloc_sarray)
((j_common_ptr) &jpeg->cinfo, JPOOL_IMAGE, row_stride, 1);
/* decompress line data */
jpeg->cinfo.output_scanline = h;
jpeg_read_scanlines(&jpeg->cinfo, buffer, (JDIMENSION) 1);
/* copy pixels memory */
{
int index;
rtgui_color_t *ptr;
ptr = (rtgui_color_t *)jpeg->line_pixels;
for (index = 0; index < image->w; index ++)
ptr[index] = RTGUI_ARGB(0, buffer[0][index * 3], buffer[0][index * 3 + 1], buffer[0][index * 3 + 2]);
}
return jpeg->line_pixels;
}
static rt_bool_t rtgui_image_jpeg_loadall(struct rtgui_image *image)
{
struct rtgui_image_jpeg *jpeg;
rt_uint8_t *line_ptr;
JSAMPARRAY buffer; /* Output row buffer */
int row_stride;
jpeg = (struct rtgui_image_jpeg *) image->data;
RT_ASSERT(jpeg != RT_NULL);
/* already load */
if (jpeg->pixels != RT_NULL) return RT_TRUE;
/* allocate all pixels */
jpeg->pixels = rtgui_malloc(image->h * image->w * sizeof(rtgui_color_t));
if (jpeg->pixels == RT_NULL) return RT_FALSE;
/* reset scan line to zero */
jpeg->cinfo.output_scanline = 0;
line_ptr = jpeg->pixels;
row_stride = jpeg->cinfo.output_width * jpeg->cinfo.output_components;
buffer = (*jpeg->cinfo.mem->alloc_sarray)
((j_common_ptr) &jpeg->cinfo, JPOOL_IMAGE, row_stride, 1);
/* decompress all pixels */
while (jpeg->cinfo.output_scanline < jpeg->cinfo.output_height)
{
/* jpeg_read_scanlines expects an array of pointers to scanlines.
* Here the array is only one element long, but you could ask for
* more than one scanline at a time if that's more convenient.
*/
(void) jpeg_read_scanlines(&jpeg->cinfo, buffer, 1);
/* copy pixels memory */
{
int index;
rtgui_color_t *ptr;
ptr = (rtgui_color_t *)line_ptr;
for (index = 0; index < image->w; index ++)
ptr[index] = RTGUI_ARGB(0, buffer[0][index * 3], buffer[0][index * 3 + 1], buffer[0][index * 3 + 2]);
}
/* move to next line */
line_ptr += image->w * sizeof(rtgui_color_t);
}
/* decompress done */
rtgui_filerw_close(jpeg->filerw);
jpeg_finish_decompress(&jpeg->cinfo);
jpeg->is_loaded = RT_TRUE;
return RT_TRUE;
}
void rtgui_image_jpeg_init()
{
/* register jpeg on image system */
rtgui_image_register_engine(&rtgui_image_jpeg_engine);
/* register jpg on image system */
rtgui_image_register_engine(&rtgui_image_jpg_engine);
}
static void my_error_exit(j_common_ptr cinfo)
{
}
static void output_no_message(j_common_ptr cinfo)
{
/* do nothing */
}
static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
{
struct rtgui_image_jpeg *jpeg;
jpeg = (struct rtgui_image_jpeg *) rtgui_malloc(sizeof(struct rtgui_image_jpeg));
if (jpeg == RT_NULL) return RT_FALSE;
jpeg->filerw = file;
/* read file header */
/* Create a decompression structure and load the JPEG header */
jpeg->cinfo.err = jpeg_std_error(&jpeg->errmgr.pub);
jpeg->errmgr.pub.error_exit = my_error_exit;
jpeg->errmgr.pub.output_message = output_no_message;
jpeg_create_decompress(&jpeg->cinfo);
rtgui_jpeg_filerw_src_init(&jpeg->cinfo, jpeg->filerw);
(void)jpeg_read_header(&jpeg->cinfo, TRUE);
image->w = jpeg->cinfo.image_width;
image->h = jpeg->cinfo.image_height;
/* set image private data and engine */
image->data = jpeg;
image->engine = &rtgui_image_jpeg_engine;
/* start decompression */
(void) jpeg_start_decompress(&jpeg->cinfo);
jpeg->cinfo.out_color_space = JCS_RGB;
jpeg->cinfo.quantize_colors = FALSE;
/* use fast jpeg */
jpeg->cinfo.scale_num = 1;
jpeg->cinfo.scale_denom = 1;
jpeg->cinfo.dct_method = JDCT_FASTEST;
jpeg->cinfo.do_fancy_upsampling = FALSE;
jpeg->pixels = RT_NULL;
jpeg->is_loaded = RT_FALSE;
/* allocate line pixels */
jpeg->line_pixels = rtgui_malloc(image->w * sizeof(rtgui_color_t));
if (jpeg->line_pixels == RT_NULL)
{
/* no memory */
jpeg_finish_decompress(&jpeg->cinfo);
jpeg_destroy_decompress(&jpeg->cinfo);
rt_free(jpeg);
return RT_FALSE;
}
if (load == RT_TRUE) rtgui_image_jpeg_loadall(image);
/* create jpeg image successful */
return RT_TRUE;
}
static void rtgui_image_jpeg_unload(struct rtgui_image *image)
{
if (image != RT_NULL)
{
struct rtgui_image_jpeg *jpeg;
jpeg = (struct rtgui_image_jpeg *) image->data;
RT_ASSERT(jpeg != RT_NULL);
if (jpeg->is_loaded == RT_TRUE)
rtgui_free(jpeg->pixels);
if (jpeg->line_pixels != RT_NULL) rtgui_free(jpeg->line_pixels);
if (jpeg->is_loaded != RT_TRUE)
{
rtgui_filerw_close(jpeg->filerw);
jpeg_finish_decompress(&jpeg->cinfo);
}
jpeg_destroy_decompress(&jpeg->cinfo);
rt_free(jpeg);
}
}
static void rtgui_image_jpeg_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect)
{
rt_uint16_t x, y;
rtgui_color_t *ptr;
struct rtgui_image_jpeg *jpeg;
RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
jpeg = (struct rtgui_image_jpeg *) image->data;
RT_ASSERT(jpeg != RT_NULL);
if (jpeg->pixels != RT_NULL)
{
ptr = (rtgui_color_t *) jpeg->pixels;
if (dc->type == RTGUI_DC_BUFFER)
{
/* blit ARGB888 to this buffered DC */
int dst_x, dst_y;
int w, h;
struct rtgui_blit_info info;
struct rtgui_dc_buffer *buffer = (struct rtgui_dc_buffer*)dc;
w = _UI_MIN(image->w, rtgui_rect_width(*rect));
h = _UI_MIN(image->h, rtgui_rect_height(*rect));
info.a = 0;
/* initialize source blit information */
info.src_fmt = RTGRAPHIC_PIXEL_FORMAT_ARGB888;;
info.src_h = h;
info.src_w = w;
info.src_pitch = image->w * rtgui_color_get_bpp(RTGRAPHIC_PIXEL_FORMAT_ARGB888);
info.src_skip = info.src_pitch - w * rtgui_color_get_bpp(RTGRAPHIC_PIXEL_FORMAT_ARGB888);
info.src = (rt_uint8_t *)image->data + y * info.src_pitch + x * rtgui_color_get_bpp(RTGRAPHIC_PIXEL_FORMAT_ARGB888);
if (rect->x1 < 0) dst_x = 0;
else dst_x = rect->x1;
if (rect->y1 < 0) dst_y = 0;
else dst_y = rect->y1;
/* initialize destination blit information */
info.dst = rtgui_dc_buffer_get_pixel(RTGUI_DC(buffer)) + dst_y * buffer->pitch +
dst_x * rtgui_color_get_bpp(buffer->pixel_format);
info.dst_h = h;
info.dst_w = w;
info.dst_fmt = buffer->pixel_format;
info.dst_pitch = buffer->pitch;
info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(buffer->pixel_format);
rtgui_blit(&info);
}
else
{
/* 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_draw_color_point(dc, x + rect->x1, y + rect->y1, *ptr);
}
/* move to next color buffer */
ptr ++;
}
}
}
}
else
{
/* seek to the begin of file */
rtgui_filerw_seek(jpeg->filerw, 0, RTGUI_FILE_SEEK_SET);
/* decompress line and line */
for (y = 0; y < image->h; y ++)
{
ptr = (rtgui_color_t *)rtgui_image_get_line(image, y);
for (x = 0; x < image->w; x++)
{
/* not alpha */
if ((*ptr >> 24) != 255)
{
rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, *ptr);
}
/* move to next color buffer */
ptr ++;
}
}
}
}
static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw *file)
{
int start;
rt_bool_t is_JPG;
int in_scan;
rt_uint8_t magic[4];
if (file == RT_NULL) return RT_FALSE; /* open file failed */
start = rtgui_filerw_tell(file);
is_JPG = RT_FALSE;
in_scan = 0;
/* seek to the begining of file */
rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET);
if (rtgui_filerw_read(file, magic, 2, 1))
{
if ((magic[0] == 0xFF) && (magic[1] == 0xD8))
{
is_JPG = RT_TRUE;
while (is_JPG == RT_TRUE)
{
if (rtgui_filerw_read(file, magic, 1, 2) != 2)
{
is_JPG = RT_FALSE;
}
else if ((magic[0] != 0xFF) && (in_scan == 0))
{
is_JPG = RT_FALSE;
}
else if ((magic[0] != 0xFF) || (magic[1] == 0xFF))
{
/* Extra padding in JPEG (legal) */
/* or this is data and we are scanning */
rtgui_filerw_seek(file, -1, RTGUI_FILE_SEEK_CUR);
}
else if (magic[1] == 0xD9)
{
/* Got to end of good JPEG */
break;
}
else if ((in_scan == 1) && (magic[1] == 0x00))
{
/* This is an encoded 0xFF within the data */
}
else if ((magic[1] >= 0xD0) && (magic[1] < 0xD9))
{
/* These have nothing else */
}
else if (rtgui_filerw_read(file, magic + 2, 1, 2) != 2)
{
is_JPG = RT_FALSE;
}
else
{
/* Yes, it's big-endian */
rt_uint32_t start;
rt_uint32_t size;
rt_uint32_t end;
start = rtgui_filerw_tell(file);
size = (magic[2] << 8) + magic[3];
end = rtgui_filerw_seek(file, size - 2, RTGUI_FILE_SEEK_CUR);
if (end != start + size - 2) is_JPG = RT_FALSE;
if (magic[1] == 0xDA)
{
/* Now comes the actual JPEG meat */
/* It is a JPEG. */
break;
}
}
}
}
}
rtgui_filerw_seek(file, start, RTGUI_FILE_SEEK_SET);
return is_JPG;
}
#endif
#if defined(RTGUI_IMAGE_TJPGD)
/***************************************************************************//**
* @file image_jpg.c
* @brief JPEG decoder using TJpgDec module (elm-chan.org)
* COPYRIGHT (C) 2012, RT-Thread Development Team
* @author onelife
* @version 1.0
*******************************************************************************
* @section License
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
*******************************************************************************
* @section Change Logs
* Date Author Notes
* 2012-01-24 onelife Initial creation for limited memory devices
******************************************************************************/
/***************************************************************************//**
* @addtogroup TJpgDec
* @{
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "tjpgd.h"
#include <rtgui/rtgui_system.h>
#include <rtgui/filerw.h>
#include <rtgui/blit.h>
#include <rtgui/image_jpeg.h>
#ifdef RTGUI_USING_DFS_FILERW
#include <dfs_posix.h>
#endif
/* Private typedef -----------------------------------------------------------*/
struct rtgui_image_jpeg
{
struct rtgui_filerw *filerw;
struct rtgui_dc *dc;
rt_uint16_t dst_x, dst_y;
rt_uint16_t dst_w, dst_h;
rt_bool_t is_loaded;
rt_uint8_t byte_per_pixel;
JDEC tjpgd; /* jpeg structure */
void *pool;
rt_uint8_t *pixels;
};
/* Private define ------------------------------------------------------------*/
#define TJPGD_WORKING_BUFFER_SIZE (32 * 1024)
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw *file);
static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load);
static void rtgui_image_jpeg_unload(struct rtgui_image *image);
static void rtgui_image_jpeg_blit(struct rtgui_image *image,
struct rtgui_dc *dc, struct rtgui_rect *dst_rect);
/* Private variables ---------------------------------------------------------*/
struct rtgui_image_engine rtgui_image_jpeg_engine =
{
"jpeg",
{RT_NULL},
rtgui_image_jpeg_check,
rtgui_image_jpeg_load,
rtgui_image_jpeg_unload,
rtgui_image_jpeg_blit
};
struct rtgui_image_engine rtgui_image_jpg_engine =
{
"jpg",
{RT_NULL},
rtgui_image_jpeg_check,
rtgui_image_jpeg_load,
rtgui_image_jpeg_unload,
rtgui_image_jpeg_blit
};
/* Private functions ---------------------------------------------------------*/
void rtgui_image_jpeg_init()
{
/* register jpeg on image system */
rtgui_image_register_engine(&rtgui_image_jpeg_engine);
/* register jpg on image system */
rtgui_image_register_engine(&rtgui_image_jpg_engine);
}
static UINT tjpgd_in_func(JDEC *jdec, BYTE *buff, UINT ndata)
{
struct rtgui_filerw *file = *(struct rtgui_filerw **)jdec->device;
if (buff == RT_NULL)
{
return rtgui_filerw_seek(file, ndata, RTGUI_FILE_SEEK_CUR);
}
return rtgui_filerw_read(file, (void *)buff, 1, ndata);
}
static UINT tjpgd_out_func(JDEC *jdec, void *bitmap, JRECT *rect)
{
struct rtgui_image_jpeg *jpeg = (struct rtgui_image_jpeg *)jdec->device;
rt_uint16_t w, h, y;
rt_uint16_t rectWidth; /* Width of source rectangular (bytes) */
rt_uint8_t *src, *dst;
/* Copy the decompressed RGB rectangular to the frame buffer */
rectWidth = (rect->right - rect->left + 1) * jpeg->byte_per_pixel;
src = (rt_uint8_t *)bitmap;
if (jpeg->is_loaded == RT_TRUE)
{
rt_uint16_t imageWidth; /* Width of image (bytes) */
imageWidth = (jdec->width >> jdec->scale) * jpeg->byte_per_pixel;
dst = jpeg->pixels + rect->top * imageWidth + rect->left * jpeg->byte_per_pixel;
/* Left-top of destination rectangular */
for (h = rect->top; h <= rect->bottom; h++)
{
rt_memcpy(dst, src, rectWidth);
src += rectWidth;
dst += imageWidth; /* Next line */
}
}
else
{
/* we decompress from top to bottom if the block is beyond the right
* boundary, just continue to next block. However, if the block is
* beyond the bottom boundary, we don't need to decompress the rest. */
if (rect->left > jpeg->dst_w) return 1;
if (rect->top > jpeg->dst_h) return 0;
w = _UI_MIN(rect->right, jpeg->dst_w);
w = w - rect->left + 1;
h = _UI_MIN(rect->bottom, jpeg->dst_h);
h = h - rect->top + 1;
for (y = 0; y < h; y++)
{
jpeg->dc->engine->blit_line(jpeg->dc,
jpeg->dst_x + rect->left, jpeg->dst_x + rect->left + w,
jpeg->dst_y + rect->top + y,
src);
src += rectWidth;
}
}
return 1; /* Continue to decompress */
}
static rt_bool_t rtgui_image_jpeg_check(struct rtgui_filerw *file)
{
rt_uint8_t soi[2];
rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET);
rtgui_filerw_read(file, &soi, 2, 1);
rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET);
/* check SOI==FFD8 */
if (soi[0] == 0xff && soi[1] == 0xd8) return RT_TRUE;
return RT_FALSE;
}
static rt_bool_t rtgui_image_jpeg_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
{
rt_bool_t res = RT_FALSE;
struct rtgui_image_jpeg *jpeg;
JRESULT ret;
struct rtgui_graphic_driver *hw_driver;
do
{
jpeg = (struct rtgui_image_jpeg *)rt_malloc(sizeof(struct rtgui_image_jpeg));
if (jpeg == RT_NULL) break;
jpeg->filerw = file;
jpeg->is_loaded = load;
jpeg->pixels = RT_NULL;
/* allocate memory pool */
jpeg->pool = rt_malloc(TJPGD_WORKING_BUFFER_SIZE);
if (jpeg->pool == RT_NULL)
{
rt_kprintf("TJPGD err: no mem (%d)\n", TJPGD_WORKING_BUFFER_SIZE);
break;
}
if (rtgui_filerw_seek(jpeg->filerw, 0, RTGUI_FILE_SEEK_SET) == -1)
{
break;
}
ret = jd_prepare(&jpeg->tjpgd, tjpgd_in_func, jpeg->pool,
TJPGD_WORKING_BUFFER_SIZE, (void *)jpeg);
if (ret != JDR_OK)
{
if (ret == JDR_FMT3)
{
rt_kprintf("TJPGD: not supported format\n");
}
break;
}
/* use RGB565 format */
hw_driver = rtgui_graphic_driver_get_default();
if (hw_driver->pixel_format == RTGRAPHIC_PIXEL_FORMAT_RGB565)
{
jpeg->tjpgd.format = 1;
jpeg->byte_per_pixel = 2;
}
/* else use RGB888 format */
else jpeg->byte_per_pixel = 3;
image->w = (rt_uint16_t)jpeg->tjpgd.width;
image->h = (rt_uint16_t)jpeg->tjpgd.height;
/* set image private data and engine */
image->data = jpeg;
image->engine = &rtgui_image_jpeg_engine;
if (jpeg->is_loaded == RT_TRUE)
{
jpeg->pixels = (rt_uint8_t *)rtgui_malloc(
jpeg->byte_per_pixel * image->w * image->h);
if (jpeg->pixels == RT_NULL)
{
rt_kprintf("TJPGD err: no mem to load (%d)\n",
jpeg->byte_per_pixel * image->w * image->h);
break;
}
ret = jd_decomp(&jpeg->tjpgd, tjpgd_out_func, 0);
if (ret != JDR_OK) break;
rtgui_filerw_close(jpeg->filerw);
jpeg->filerw = RT_NULL;
}
res = RT_TRUE;
} while (0);
if (jpeg && (!res || jpeg->is_loaded))
{
rt_free(jpeg->pool);
jpeg->pool = RT_NULL;
}
if (!res)
{
if (jpeg)
rtgui_free(jpeg->pixels);
rt_free(jpeg);
image->data = RT_NULL;
image->engine = RT_NULL;
}
/* create jpeg image successful */
return res;
}
static void rtgui_image_jpeg_unload(struct rtgui_image *image)
{
if (image != RT_NULL)
{
struct rtgui_image_jpeg *jpeg;
jpeg = (struct rtgui_image_jpeg *) image->data;
RT_ASSERT(jpeg != RT_NULL);
if (jpeg->is_loaded == RT_TRUE)
{
rtgui_free(jpeg->pixels);
}
else
{
rt_free(jpeg->pool);
rtgui_filerw_close(jpeg->filerw);
}
rt_free(jpeg);
}
}
static void rtgui_image_jpeg_blit(struct rtgui_image *image,
struct rtgui_dc *dc, struct rtgui_rect *dst_rect)
{
rt_uint16_t y, w, h, xoff, yoff;
struct rtgui_image_jpeg *jpeg;
jpeg = (struct rtgui_image_jpeg *) image->data;
RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL || jpeg != RT_NULL);
/* this dc is not visible */
if (rtgui_dc_get_visible(dc) != RT_TRUE)
return;
jpeg->dc = dc;
xoff = 0;
if (dst_rect->x1 < 0)
{
xoff = -dst_rect->x1;
dst_rect->x1 = 0;
}
yoff = 0;
if (dst_rect->y1 < 0)
{
yoff = -dst_rect->y1;
dst_rect->y1 = 0;
}
if (xoff >= image->w || yoff >= image->h)
return;
/* the minimum rect */
w = _UI_MIN(image->w - xoff, rtgui_rect_width (*dst_rect));
h = _UI_MIN(image->h - yoff, rtgui_rect_height(*dst_rect));
if (rtgui_dc_get_pixel_format(dc) == RTGRAPHIC_PIXEL_FORMAT_RGB888 &&
jpeg->tjpgd.format != 0)
{
jpeg->tjpgd.format = 0;
jpeg->byte_per_pixel = 3;
}
else if (rtgui_dc_get_pixel_format(dc) == RTGRAPHIC_PIXEL_FORMAT_RGB565 &&
jpeg->tjpgd.format != 1)
{
jpeg->tjpgd.format = 1;
jpeg->byte_per_pixel = 2;
}
if (!jpeg->is_loaded)
{
JRESULT ret;
/* TODO support xoff/yoff. */
jpeg->dst_x = dst_rect->x1;
jpeg->dst_y = dst_rect->y1;
jpeg->dst_w = w;
jpeg->dst_h = h;
ret = jd_decomp(&jpeg->tjpgd, tjpgd_out_func, 0);
if (ret != JDR_OK)
return;
}
else
{
if ((rtgui_dc_get_pixel_format(dc) == RTGRAPHIC_PIXEL_FORMAT_RGB888 && jpeg->tjpgd.format == 0) ||
(rtgui_dc_get_pixel_format(dc) == RTGRAPHIC_PIXEL_FORMAT_RGB565 && jpeg->tjpgd.format == 1))
{
rt_uint16_t imageWidth = image->w * jpeg->byte_per_pixel;
rt_uint8_t *src = jpeg->pixels + yoff * imageWidth + xoff + jpeg->byte_per_pixel;
for (y = 0; y < h; y++)
{
dc->engine->blit_line(dc,
dst_rect->x1, dst_rect->x1 + w,
dst_rect->y1 + y,
src);
src += imageWidth;
}
}
/* if the format is not match, only support DC buffer */
else if (dc->type == RTGUI_DC_BUFFER)
{
struct rtgui_blit_info info;
struct rtgui_dc_buffer *buffer;
buffer = (struct rtgui_dc_buffer*)dc;
info.src = jpeg->pixels + yoff * image->w * jpeg->byte_per_pixel + xoff + jpeg->byte_per_pixel;
info.src_h = rtgui_rect_height(*dst_rect);
info.src_w = rtgui_rect_width(*dst_rect);
info.src_fmt = (jpeg->tjpgd.format == 0? RTGRAPHIC_PIXEL_FORMAT_RGB888 : RTGRAPHIC_PIXEL_FORMAT_RGB565);
info.src_pitch = info.src_w * jpeg->byte_per_pixel;
info.src_skip = info.src_pitch - info.src_w * jpeg->byte_per_pixel;
info.dst = rtgui_dc_buffer_get_pixel(RTGUI_DC(buffer)) + dst_rect->y1 * buffer->pitch +
dst_rect->x1 * rtgui_color_get_bpp(buffer->pixel_format);
info.dst_h = rtgui_rect_height(*dst_rect);
info.dst_w = rtgui_rect_width(*dst_rect);
info.dst_fmt = buffer->pixel_format;
info.dst_pitch = buffer->pitch;
info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(buffer->pixel_format);
rtgui_blit(&info);
}
}
}
#endif /* defined(RTGUI_IMAGE_TJPGD) */

View File

@ -0,0 +1,681 @@
#include <rtthread.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/blit.h>
#include <rtgui/driver.h>
#ifdef RTGUI_IMAGE_PNG
#include "png.h"
#include <rtgui/image_png.h>
#define PNG_MAGIC_LEN 8
struct rtgui_image_png
{
rt_bool_t is_loaded;
struct rtgui_filerw *filerw;
/* png image information */
png_structp png_ptr;
png_infop info_ptr;
rt_uint8_t *pixels;
};
static rt_bool_t rtgui_image_png_check(struct rtgui_filerw *file);
static rt_bool_t rtgui_image_png_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load);
static void rtgui_image_png_unload(struct rtgui_image *image);
static void rtgui_image_png_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect);
struct rtgui_image_engine rtgui_image_png_engine =
{
"png",
{ RT_NULL },
rtgui_image_png_check,
rtgui_image_png_load,
rtgui_image_png_unload,
rtgui_image_png_blit,
};
static void rtgui_image_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
struct rtgui_filerw *filerw = (struct rtgui_filerw *)png_ptr->io_ptr;
rtgui_filerw_read(filerw, data, length, 1);
}
static rt_bool_t rtgui_image_png_process(png_structp png_ptr, png_infop info_ptr, struct rtgui_image_png *png)
{
rt_uint32_t x, y;
png_bytep row;
png_bytep data;
rtgui_color_t *ptr;
row = (png_bytep) rtgui_malloc(png_get_rowbytes(png_ptr, info_ptr));
if (row == RT_NULL) return RT_FALSE;
ptr = (rtgui_color_t *)png->pixels;
switch (info_ptr->color_type)
{
case PNG_COLOR_TYPE_RGB:
for (y = 0; y < info_ptr->height; y++)
{
png_read_row(png_ptr, row, png_bytep_NULL);
for (x = 0; x < info_ptr->width; x++)
{
data = &(row[x * 3]);
ptr[x + y * info_ptr->width] = RTGUI_RGB(data[0], data[1], data[2]);
}
}
break;
case PNG_COLOR_TYPE_RGBA:
for (y = 0; y < info_ptr->height; y++)
{
png_read_row(png_ptr, row, png_bytep_NULL);
for (x = 0; x < info_ptr->width; x++)
{
data = &(row[x * 4]);
ptr[x + y * info_ptr->width] = RTGUI_ARGB(data[3], data[0], data[1], data[2]);
}
}
break;
case PNG_COLOR_TYPE_PALETTE:
for (y = 0; y < info_ptr->height; y++)
{
png_read_row(png_ptr, row, png_bytep_NULL);
for (x = 0; x < info_ptr->width; x++)
{
data = &(row[x]);
ptr[x] = RTGUI_ARGB(0, info_ptr->palette[data[0]].red,
info_ptr->palette[data[0]].green,
info_ptr->palette[data[0]].blue);
}
}
default:
break;
};
rtgui_free(row);
return RT_TRUE;
}
static rt_bool_t rtgui_image_png_check(struct rtgui_filerw *file)
{
int start;
rt_bool_t is_PNG;
rt_uint8_t magic[4];
if (!file) return 0;
start = rtgui_filerw_tell(file);
/* move to the begining of file */
rtgui_filerw_seek(file, 0, SEEK_SET);
is_PNG = RT_FALSE;
if (rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic))
{
if (magic[0] == 0x89 &&
magic[1] == 'P' &&
magic[2] == 'N' &&
magic[3] == 'G')
{
is_PNG = RT_TRUE;
}
}
rtgui_filerw_seek(file, start, SEEK_SET);
return(is_PNG);
}
static void _image_png_error_fn(png_structp png_ptr, png_const_charp error_message)
{
rt_kprintf(error_message);
}
static rt_bool_t rtgui_image_png_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
{
png_uint_32 width;
png_uint_32 height;
int bit_depth;
int color_type;
double gamma;
struct rtgui_image_png *png;
png = (struct rtgui_image_png *) rtgui_malloc(sizeof(struct rtgui_image_png));
png->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png->png_ptr == RT_NULL)
{
rtgui_free(png);
return RT_FALSE;
}
png_set_error_fn(png->png_ptr, RT_NULL, _image_png_error_fn, _image_png_error_fn);
png->info_ptr = png_create_info_struct(png->png_ptr);
if (png->info_ptr == RT_NULL)
{
png_destroy_read_struct(&png->png_ptr, NULL, NULL);
rtgui_free(png);
return RT_FALSE;
}
png->filerw = file;
png->is_loaded = RT_FALSE;
png_set_read_fn(png->png_ptr, png->filerw, rtgui_image_png_read_data);
png_read_info(png->png_ptr, png->info_ptr);
png_get_IHDR(png->png_ptr, png->info_ptr, &width, &height, &bit_depth,
&color_type, NULL, NULL, NULL);
/* set image information */
image->w = width;
image->h = height;
image->engine = &rtgui_image_png_engine;
image->data = png;
if (bit_depth == 16)
png_set_strip_16(png->png_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png->png_ptr);
if (bit_depth < 8)
png_set_expand(png->png_ptr);
if (png_get_valid(png->png_ptr, png->info_ptr, PNG_INFO_tRNS))
png_set_expand(png->png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png->png_ptr);
/* Ignore background color */
/* set gamma conversion */
if (png_get_gAMA(png->png_ptr, png->info_ptr, &gamma))
png_set_gamma(png->png_ptr, (double)2.2, gamma);
png_read_update_info(png->png_ptr, png->info_ptr);
if (load == RT_TRUE)
{
/* load all pixels */
png->pixels = rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t));
if (png->pixels == RT_NULL)
{
png_read_end(png->png_ptr, RT_NULL);
/* destroy png struct */
png_destroy_info_struct(png->png_ptr, &png->info_ptr);
png_destroy_read_struct(&png->png_ptr, RT_NULL, RT_NULL);
/* release data */
rtgui_free(png);
return RT_FALSE;
}
rtgui_image_png_process(png->png_ptr, png->info_ptr, png);
png_read_end(png->png_ptr, RT_NULL);
png->is_loaded = RT_TRUE;
/* close file handler */
rtgui_filerw_close(png->filerw);
png->filerw = RT_NULL;
}
else
{
png->pixels = RT_NULL;
}
return RT_TRUE;
}
static void rtgui_image_png_unload(struct rtgui_image *image)
{
struct rtgui_image_png *png;
if (image != RT_NULL)
{
png = (struct rtgui_image_png *) image->data;
/* destroy png struct */
png_destroy_info_struct(png->png_ptr, &png->info_ptr);
png_destroy_read_struct(&png->png_ptr, RT_NULL, RT_NULL);
if (png->pixels != RT_NULL) rtgui_free(png->pixels);
/* release data */
rtgui_free(png);
}
}
static void rtgui_image_png_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect)
{
rt_uint16_t x, y, w, h;
rtgui_color_t *ptr;
struct rtgui_image_png *png;
int fg_maxsample;
int ialpha;
float alpha;
rtgui_color_t color;
rtgui_color_t c, bgcolor;
int fc[3], bc[3];
struct rtgui_graphic_driver *hwdev = rtgui_graphic_get_device();
RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
RT_ASSERT(image->data != RT_NULL);
png = (struct rtgui_image_png *) image->data;
w = _UI_MIN(image->w, rtgui_rect_width(*rect));
h = _UI_MIN(image->h, rtgui_rect_height(*rect));
fg_maxsample = (1 << png->info_ptr->bit_depth) - 1;
if (png->pixels != RT_NULL)
{
ptr = (rtgui_color_t *)png->pixels;
bgcolor = RTGUI_DC_BC(dc);
bc[0] = RTGUI_RGB_R(bgcolor);
bc[1] = RTGUI_RGB_G(bgcolor);
bc[2] = RTGUI_RGB_B(bgcolor);
/* draw each point within dc */
for (y = 0; y < h; y ++)
{
for (x = 0; x < w; x++)
{
c = *ptr;
ialpha = RTGUI_RGB_A(c);
if (ialpha == 0)
{
/*
* Foreground image is transparent hear.
* If the background image is already in the frame
* buffer, there is nothing to do.
*/
}
else if (ialpha == fg_maxsample)
{
/*
* Copy foreground pixel to frame buffer.
*/
rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, c);
}
else
{
/* output = alpha * foreground + (1-alpha) * background */
/*
* Compositing is necessary.
* Get floating-point alpha and its complement.
* Note: alpha is always linear: gamma does not
* affect it.
*/
fc[0] = RTGUI_RGB_R(c);
fc[1] = RTGUI_RGB_G(c);
fc[2] = RTGUI_RGB_B(c);
alpha = (float) ialpha / fg_maxsample;
color = RTGUI_RGB((rt_uint8_t)(fc[0] * alpha + bc[0] * (1 - alpha)),
(rt_uint8_t)(fc[1] * alpha + bc[1] * (1 - alpha)),
(rt_uint8_t)(fc[2] * alpha + bc[2] * (1 - alpha)));
rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, color);
}
/* move to next color buffer */
ptr ++;
}
}
}
else
{
png_bytep row;
png_bytep data;
row = (png_bytep) rtgui_malloc(png_get_rowbytes(png->png_ptr, png->info_ptr));
if (row == RT_NULL) return ;
switch (png->info_ptr->color_type)
{
case PNG_COLOR_TYPE_RGB:
for (y = 0; y < h; y++)
{
png_read_row(png->png_ptr, row, png_bytep_NULL);
for (x = 0; x < w; x++)
{
data = &(row[x * 3]);
rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1,
RTGUI_RGB(data[0], data[1], data[2]));
}
}
break;
case PNG_COLOR_TYPE_RGBA:
for (y = 0; y < h; y++)
{
png_read_row(png->png_ptr, row, png_bytep_NULL);
for (x = 0; x < w; x++)
{
data = &(row[x * 4]);
if (data[3] != 0)
{
rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1,
RTGUI_ARGB(data[3], data[0], data[1], data[2]));
}
}
}
break;
case PNG_COLOR_TYPE_PALETTE:
for (y = 0; y < h; y++)
{
png_read_row(png->png_ptr, row, png_bytep_NULL);
for (x = 0; x < w; x++)
{
data = &(row[x]);
rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1,
RTGUI_ARGB(0, png->info_ptr->palette[data[0]].red,
png->info_ptr->palette[data[0]].green,
png->info_ptr->palette[data[0]].blue));
}
}
default:
break;
};
rtgui_free(row);
}
}
void rtgui_image_png_init()
{
/* register png on image system */
rtgui_image_register_engine(&rtgui_image_png_engine);
}
#elif defined(RTGUI_IMAGE_LODEPNG)
#include "lodepng.h"
#include <rtgui/image_png.h>
static rt_bool_t rtgui_image_png_check(struct rtgui_filerw *file);
static rt_bool_t rtgui_image_png_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load);
static void rtgui_image_png_unload(struct rtgui_image *image);
static void rtgui_image_png_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect);
struct rtgui_image_engine rtgui_image_png_engine =
{
"png",
{ RT_NULL },
rtgui_image_png_check,
rtgui_image_png_load,
rtgui_image_png_unload,
rtgui_image_png_blit,
};
static rt_bool_t rtgui_image_png_check(struct rtgui_filerw *file)
{
int start;
rt_bool_t is_PNG;
rt_uint8_t magic[4];
if (!file) return 0;
start = rtgui_filerw_tell(file);
/* move to the begining of file */
rtgui_filerw_seek(file, 0, SEEK_SET);
is_PNG = RT_FALSE;
if (rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic))
{
if (magic[0] == 0x89 &&
magic[1] == 'P' &&
magic[2] == 'N' &&
magic[3] == 'G')
{
is_PNG = RT_TRUE;
}
}
rtgui_filerw_seek(file, start, SEEK_SET);
return(is_PNG);
}
static rt_bool_t rtgui_image_png_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
{
unsigned int width;
unsigned int height;
unsigned int error;
rt_uint8_t* pixel;
rt_uint8_t* in;
rt_uint32_t in_size;
RT_ASSERT(image != RT_NULL);
RT_ASSERT(file != RT_NULL);
rtgui_filerw_seek(file, 0, SEEK_END);
in_size = rtgui_filerw_tell(file);
in = rtgui_malloc(in_size);
if (in == RT_NULL) return RT_FALSE; /* out of memory */
rtgui_filerw_seek(file, 0, SEEK_SET);
rtgui_filerw_read(file, in, in_size, 1);
error = lodepng_decode32(&pixel, &width, &height, in, in_size);
if(error)
{
rt_kprintf("error %u: %s\n", error, lodepng_error_text(error));
rtgui_free(in);
return RT_FALSE;
}
rtgui_free(in);
/* set image information */
image->w = width;
image->h = height;
image->engine = &rtgui_image_png_engine;
image->data = pixel;
/* NOTE: the pixel format of PNG is ABGR888, bit0 R,G,B,A bit31 */
/* convert pixel to ARGB888, swap B/G */
{
rt_uint8_t* pixel_ptr;
rt_uint8_t* pixel_end;
pixel_ptr = (rt_uint8_t*) pixel;
pixel_end = pixel_ptr + width * height * 4;
while (pixel_ptr < pixel_end)
{
pixel_ptr[0] = pixel_ptr[0] ^ pixel_ptr[2];
pixel_ptr[2] = pixel_ptr[0] ^ pixel_ptr[2];
pixel_ptr[0] = pixel_ptr[0] ^ pixel_ptr[2];
pixel_ptr += 4;
}
}
/* close file handler */
rtgui_filerw_close(file);
return RT_TRUE;
}
static void rtgui_image_png_unload(struct rtgui_image *image)
{
rt_uint8_t *pixels;
if (image != RT_NULL)
{
pixels = (rt_uint8_t*) image->data;
/* release data */
rtgui_free(pixels);
}
}
static void rtgui_image_png_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect)
{
int x, y;
int w, h;
struct rtgui_blit_info info;
struct rtgui_graphic_driver *hw_driver = rtgui_graphic_driver_get_default();
RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
RT_ASSERT(image->data != RT_NULL);
#define blending(s, d, a) (((unsigned)(((s) - (d)) * (a)) >> 8) + (d))
/* this dc is not visible */
if (rtgui_dc_get_visible(dc) != RT_TRUE) return;
w = _UI_MIN(image->w, rtgui_rect_width(*rect));
h = _UI_MIN(image->h, rtgui_rect_height(*rect));
/* border checking */
if (rect->x1 < 0) { x = -rect->x1; w += rect->x1; }
else x = 0;
if (rect->y1 < 0) { y = -rect->y1; h += rect->y1; }
else y = 0;
if (w < 0 || h < 0) return; /* no drawing */
if ((dc->type == RTGUI_DC_CLIENT) || (dc->type == RTGUI_DC_HW && hw_driver->framebuffer == RT_NULL))
{
int dx, dy, start_x;
rtgui_rect_t r;
rtgui_color_t *pixel;
rt_uint8_t alpha;
rtgui_widget_t *owner = RT_NULL;
if (dc->type == RTGUI_DC_CLIENT)
{
/* get owner and calculate dx,dy */
owner = RTGUI_CONTAINER_OF(dc, struct rtgui_widget, dc_type);
dx = owner->extent.x1; dy = owner->extent.y1;
}
else
{
/* hardware DC */
struct rtgui_dc_hw *hw = (struct rtgui_dc_hw *) dc;
dx = hw->owner->extent.x1;
dy = hw->owner->extent.y1;
}
start_x = x;
for (; y < rect->y1 + h; ++y)
{
for (x = start_x; x < rect->x1 + w; ++x)
{
pixel = (rtgui_color_t*)((rt_uint8_t*)image->data + (y - rect->y1) * image->w * 4 +
(x - rect->x1) * 4);
alpha = RTGUI_RGB_A(*pixel);
if (alpha == 0) continue;
if (alpha == 0xff)
{
rtgui_dc_draw_color_point(dc, x, y, *pixel);
}
else
{
rtgui_color_t bc, fc;
/* draw an alpha blending point */
if (hw_driver->framebuffer != RT_NULL)
rtgui_dc_blend_point(dc, x, y, RTGUI_BLENDMODE_BLEND,
RTGUI_RGB_R(*pixel), RTGUI_RGB_G(*pixel), RTGUI_RGB_B(*pixel), RTGUI_RGB_A(*pixel));
else
{
x = x + dx;
y = y + dy;
if (dc->type == RTGUI_DC_CLIENT)
{
if (rtgui_region_contains_point(&(owner->clip), x, y, &r) != RT_EOK)
continue ;
}
/* get background pixel */
hw_driver->ops->get_pixel(&bc, x, y);
/* alpha blending */
fc = RTGUI_RGB(blending(RTGUI_RGB_R(bc), RTGUI_RGB_R(*pixel), alpha),
blending(RTGUI_RGB_G(bc), RTGUI_RGB_G(*pixel), alpha),
blending(RTGUI_RGB_B(bc), RTGUI_RGB_B(*pixel), alpha));
hw_driver->ops->set_pixel(&fc, x, y);
}
}
}
}
}
else
{
int dst_x, dst_y;
info.a = 0;
/* initialize source blit information */
info.src_fmt = RTGRAPHIC_PIXEL_FORMAT_ARGB888;;
info.src_h = h;
info.src_w = w;
info.src_pitch = image->w * rtgui_color_get_bpp(RTGRAPHIC_PIXEL_FORMAT_ARGB888);
info.src_skip = info.src_pitch - w * rtgui_color_get_bpp(RTGRAPHIC_PIXEL_FORMAT_ARGB888);
info.src = (rt_uint8_t *)image->data + y * info.src_pitch + x * rtgui_color_get_bpp(RTGRAPHIC_PIXEL_FORMAT_ARGB888);
if (rect->x1 < 0) dst_x = 0;
else dst_x = rect->x1;
if (rect->y1 < 0) dst_y = 0;
else dst_y = rect->y1;
/* initialize destination blit information */
if (dc->type == RTGUI_DC_BUFFER)
{
struct rtgui_dc_buffer *buffer;
buffer = (struct rtgui_dc_buffer*)dc;
info.dst = rtgui_dc_buffer_get_pixel(RTGUI_DC(buffer)) + dst_y * buffer->pitch +
dst_x * rtgui_color_get_bpp(buffer->pixel_format);
info.dst_h = h;
info.dst_w = w;
info.dst_fmt = buffer->pixel_format;
info.dst_pitch = buffer->pitch;
info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(buffer->pixel_format);
}
else if (dc->type == RTGUI_DC_HW)
{
struct rtgui_widget *owner;
struct rtgui_rect r;
owner = ((struct rtgui_dc_hw*)dc)->owner;
rtgui_graphic_driver_get_rect(RT_NULL, &r);
/* blit destination */
info.dst = (rt_uint8_t*)hw_driver->framebuffer;
info.dst = info.dst + (owner->extent.y1 + dst_y) * hw_driver->pitch +
(owner->extent.x1 + dst_x) * rtgui_color_get_bpp(hw_driver->pixel_format);
info.dst_fmt = hw_driver->pixel_format;
info.dst_h = h;
info.dst_w = w;
info.dst_pitch = hw_driver->pitch;
info.dst_skip = info.dst_pitch - info.dst_w * rtgui_color_get_bpp(hw_driver->pixel_format);
}
rtgui_blit(&info);
}
}
void rtgui_image_png_init()
{
/* register png on image system */
rtgui_image_register_engine(&rtgui_image_png_engine);
}
#endif

View File

@ -0,0 +1,632 @@
/*
* 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>
#ifdef RTGUI_IMAGE_XPM
#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;
rt_uint8_t r;
rt_uint8_t g;
rt_uint8_t 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(const 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 int _str2int(const char *str, int strlen, int *p)
{
int i;
*p = 0;
/* Skip the leading chars. */
for (i = 0; i < strlen; i++)
{
if ('0' <= str[i] && str[i] <= '9')
break;
}
for (; i < strlen; i++)
{
if (str[i] < '0' || '9' < str[i])
break;
*p = (*p) * 10 + str[i] - '0';
}
return i;
}
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 */
i = rt_strlen(xpm[0]);
/* Add one for the space. */
j = _str2int(xpm[0], i, &w) + 1;
j += _str2int(xpm[0] + j, i - j, &h) + 1;
j += _str2int(xpm[0] + j, i - j, &colors) + 1;
j += _str2int(xpm[0] + j, i - j, &colors_pp) + 1;
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)
{
c = RTGUI_ARGB(0, hex2int(buf_tmp + 3),
hex2int(buf_tmp + 5),
hex2int(buf_tmp + 7));
}
else if ((buf_tmp = strstr(buf, "c ")) != RT_NULL)
{
int k;
if (strcasecmp(buf_tmp + 2, "None") == 0)
{
goto color_none;
}
for (k = 0; k < 234; k++)
{
if (strcasecmp(buf_tmp + 2, 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);
rtgui_filerw_close(file);
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;
RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
RT_ASSERT(image->data != RT_NULL);
ptr = (rtgui_color_t *) image->data;
/* 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_draw_color_point(dc, x + rect->x1, y + rect->y1, *ptr);
}
/* move to next color buffer */
ptr ++;
}
}
}
#endif

221
components/gui/src/matrix.c Normal file
View File

@ -0,0 +1,221 @@
#include <rtgui/rtgui.h>
#include <rtgui/matrix.h>
/* Port from ejoy2d: https://github.com/cloudwu/ejoy2d/blob/master/LICENSE
* Original License:
*
* The MIT License (MIT)
*
* Copyright (c) 2013 Ejoy.com Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* Port to RTGUI by Grissiom */
rt_inline int _inverse_scale(const int *m , int *o)
{
if (m[0] == 0 || m[3] == 0)
return 1;
o[0] = _rtgui_matrix_round_div32(RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC, m[0]);
o[1] = 0;
o[2] = 0;
o[3] = _rtgui_matrix_round_div32(RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC, m[3]);
o[4] = _rtgui_matrix_round_div32(-m[4] * o[0], RTGUI_MATRIX_FRAC);
o[5] = _rtgui_matrix_round_div32(-m[5] * o[3], RTGUI_MATRIX_FRAC);
return 0;
}
rt_inline int _inverse_rot(const int *m, int *o)
{
if (m[1] == 0 || m[2] == 0)
return 1;
o[0] = 0;
o[1] = _rtgui_matrix_round_div32(RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC, m[2]);
o[2] = _rtgui_matrix_round_div32(RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC, m[1]);
o[3] = 0;
o[4] = _rtgui_matrix_round_div32(-m[5] * o[2], RTGUI_MATRIX_FRAC);
o[5] = _rtgui_matrix_round_div32(-m[4] * o[1], RTGUI_MATRIX_FRAC);
return 0;
}
int rtgui_matrix_inverse(const struct rtgui_matrix *mm, struct rtgui_matrix *mo)
{
const int *m = mm->m;
int *o = mo->m;
int t;
if (m[1] == 0 && m[2] == 0)
{
return _inverse_scale(m,o);
}
if (m[0] == 0 && m[3] == 0)
{
return _inverse_rot(m,o);
}
t = m[0] * m[3] - m[1] * m[2];
if (t == 0)
return 1;
o[0] = _rtgui_matrix_round_div6432((int64_t)m[3] * (RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC), t);
o[1] = _rtgui_matrix_round_div6432(-(int64_t)m[1] * (RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC), t);
o[2] = _rtgui_matrix_round_div6432(-(int64_t)m[2] * (RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC), t);
o[3] = _rtgui_matrix_round_div6432((int64_t)m[0] * (RTGUI_MATRIX_FRAC * RTGUI_MATRIX_FRAC), t);
o[4] = _rtgui_matrix_round_div6432(-((int64_t)m[4] * o[0] + (int64_t)m[5] * o[2]), RTGUI_MATRIX_FRAC);
o[5] = _rtgui_matrix_round_div6432(-((int64_t)m[4] * o[1] + (int64_t)m[5] * o[3]), RTGUI_MATRIX_FRAC);
return 0;
}
#define COS_TABLE_SZ 512
/* @dd is the degree range in 0~512 */
rt_inline int icost(int dd)
{
static const short t[COS_TABLE_SZ] = {
2048, 2048, 2047, 2047, 2046, 2044, 2042, 2040, 2038, 2036, 2033, 2029, 2026,
2022, 2018, 2013, 2009, 2004, 1998, 1993, 1987, 1980, 1974, 1967, 1960, 1952,
1945, 1937, 1928, 1920, 1911, 1902, 1892, 1882, 1872, 1862, 1851, 1840, 1829,
1818, 1806, 1794, 1782, 1769, 1757, 1744, 1730, 1717, 1703, 1689, 1674, 1660,
1645, 1630, 1615, 1599, 1583, 1567, 1551, 1534, 1517, 1500, 1483, 1466, 1448,
1430, 1412, 1394, 1375, 1357, 1338, 1319, 1299, 1280, 1260, 1240, 1220, 1200,
1179, 1159, 1138, 1117, 1096, 1074, 1053, 1031, 1009, 988, 965, 943, 921, 898,
876, 853, 830, 807, 784, 760, 737, 714, 690, 666, 642, 619, 595, 570, 546, 522,
498, 473, 449, 424, 400, 375, 350, 325, 301, 276, 251, 226, 201, 176, 151, 126,
100, 75, 50, 25, 0, -25, -50, -75, -100, -126, -151, -176, -201, -226, -251,
-276, -301, -325, -350, -375, -400, -424, -449, -473, -498, -522, -546, -570,
-595, -619, -642, -666, -690, -714, -737, -760, -784, -807, -830, -853, -876,
-898, -921, -943, -965, -988, -1009, -1031, -1053, -1074, -1096, -1117, -1138,
-1159, -1179, -1200, -1220, -1240, -1260, -1280, -1299, -1319, -1338, -1357,
-1375, -1394, -1412, -1430, -1448, -1466, -1483, -1500, -1517, -1534, -1551,
-1567, -1583, -1599, -1615, -1630, -1645, -1660, -1674, -1689, -1703, -1717,
-1730, -1744, -1757, -1769, -1782, -1794, -1806, -1818, -1829, -1840, -1851,
-1862, -1872, -1882, -1892, -1902, -1911, -1920, -1928, -1937, -1945, -1952,
-1960, -1967, -1974, -1980, -1987, -1993, -1998, -2004, -2009, -2013, -2018,
-2022, -2026, -2029, -2033, -2036, -2038, -2040, -2042, -2044, -2046, -2047,
-2047, -2048, -2048, -2048, -2047, -2047, -2046, -2044, -2042, -2040, -2038,
-2036, -2033, -2029, -2026, -2022, -2018, -2013, -2009, -2004, -1998, -1993,
-1987, -1980, -1974, -1967, -1960, -1952, -1945, -1937, -1928, -1920, -1911,
-1902, -1892, -1882, -1872, -1862, -1851, -1840, -1829, -1818, -1806, -1794,
-1782, -1769, -1757, -1744, -1730, -1717, -1703, -1689, -1674, -1660, -1645,
-1630, -1615, -1599, -1583, -1567, -1551, -1534, -1517, -1500, -1483, -1466,
-1448, -1430, -1412, -1394, -1375, -1357, -1338, -1319, -1299, -1280, -1260,
-1240, -1220, -1200, -1179, -1159, -1138, -1117, -1096, -1074, -1053, -1031,
-1009, -988, -965, -943, -921, -898, -876, -853, -830, -807, -784, -760, -737,
-714, -690, -666, -642, -619, -595, -570, -546, -522, -498, -473, -449, -424,
-400, -375, -350, -325, -301, -276, -251, -226, -201, -176, -151, -126, -100,
-75, -50, -25, 0, 25, 50, 75, 100, 126, 151, 176, 201, 226, 251, 276, 301, 325,
350, 375, 400, 424, 449, 473, 498, 522, 546, 570, 595, 619, 642, 666, 690, 714,
737, 760, 784, 807, 830, 853, 876, 898, 921, 943, 965, 988, 1009, 1031, 1053,
1074, 1096, 1117, 1138, 1159, 1179, 1200, 1220, 1240, 1260, 1280, 1299, 1319,
1338, 1357, 1375, 1394, 1412, 1430, 1448, 1466, 1483, 1500, 1517, 1534, 1551,
1567, 1583, 1599, 1615, 1630, 1645, 1660, 1674, 1689, 1703, 1717, 1730, 1744,
1757, 1769, 1782, 1794, 1806, 1818, 1829, 1840, 1851, 1862, 1872, 1882, 1892,
1902, 1911, 1920, 1928, 1937, 1945, 1952, 1960, 1967, 1974, 1980, 1987, 1993,
1998, 2004, 2009, 2013, 2018, 2022, 2026, 2029, 2033, 2036, 2038, 2040, 2042,
2044, 2046, 2047, 2047, 2048,
};
dd &= COS_TABLE_SZ - 1;
return t[dd];
}
rt_inline int icosd(int d)
{
int dd = d;
return icost(dd);
}
rt_inline int isind(int d)
{
int dd = COS_TABLE_SZ / 4 - d;
return icost(dd);
}
rt_inline void rot_mat(int *m, int d)
{
int cosd = icosd(d);
int sind = isind(d);
int m0_cosd = m[0] * cosd;
int m0_sind = m[0] * sind;
int m1_cosd = m[1] * cosd;
int m1_sind = m[1] * sind;
int m2_cosd = m[2] * cosd;
int m2_sind = m[2] * sind;
int m3_cosd = m[3] * cosd;
int m3_sind = m[3] * sind;
int m4_cosd = m[4] * cosd;
int m4_sind = m[4] * sind;
int m5_cosd = m[5] * cosd;
int m5_sind = m[5] * sind;
m[0] = _rtgui_matrix_round_div32(m0_cosd - m1_sind, RTGUI_MATRIX_FRAC);
m[1] = _rtgui_matrix_round_div32(m0_sind + m1_cosd, RTGUI_MATRIX_FRAC);
m[2] = _rtgui_matrix_round_div32(m2_cosd - m3_sind, RTGUI_MATRIX_FRAC);
m[3] = _rtgui_matrix_round_div32(m2_sind + m3_cosd, RTGUI_MATRIX_FRAC);
m[4] = _rtgui_matrix_round_div32(m4_cosd - m5_sind, RTGUI_MATRIX_FRAC);
m[5] = _rtgui_matrix_round_div32(m4_sind + m5_cosd, RTGUI_MATRIX_FRAC);
}
rt_inline void scale_mat(int *m, int sx, int sy)
{
if (sx != RTGUI_MATRIX_FRAC)
{
m[0] = _rtgui_matrix_round_div32(m[0] * sx, RTGUI_MATRIX_FRAC);
m[2] = _rtgui_matrix_round_div32(m[2] * sx, RTGUI_MATRIX_FRAC);
m[4] = _rtgui_matrix_round_div32(m[4] * sx, RTGUI_MATRIX_FRAC);
}
if (sy != RTGUI_MATRIX_FRAC)
{
m[1] = _rtgui_matrix_round_div32(m[1] * sy, RTGUI_MATRIX_FRAC);
m[3] = _rtgui_matrix_round_div32(m[3] * sy, RTGUI_MATRIX_FRAC);
m[5] = _rtgui_matrix_round_div32(m[5] * sy, RTGUI_MATRIX_FRAC);
}
}
void rtgui_matrix_rotate(struct rtgui_matrix *m, int rot)
{
if (rot)
rot_mat(m->m, rot / (RTGUI_MATRIX_FRAC / COS_TABLE_SZ));
}
RTM_EXPORT(rtgui_matrix_rotate);
void rtgui_matrix_scale(struct rtgui_matrix *m, int sx, int sy)
{
scale_mat(m->m, sx, sy);
}
void rtgui_matrix_move(struct rtgui_matrix *m, int dx, int dy)
{
m->m[4] += dx;
m->m[5] += dy;
}
void rtgui_matrix_dump(const struct rtgui_matrix *m)
{
const int *mm = m->m;
rt_kprintf("|%6d, %6d, %6d|\n", mm[0], mm[1], 0);
rt_kprintf("|%6d, %6d, %6d|\n", mm[2], mm[3], 0);
rt_kprintf("|%6d, %6d, %6d|\n", mm[4], mm[5], 1);
}

685
components/gui/src/mouse.c Normal file
View File

@ -0,0 +1,685 @@
/*
* 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
#ifdef RTGUI_USING_WINMOVE
/* move window rect and border */
struct rtgui_win *win;
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;
#endif
};
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
#ifdef RTGUI_USING_WINMOVE
static void rtgui_winrect_restore(void);
static void rtgui_winrect_save(void);
static void rtgui_winrect_show(void);
#endif
#define WIN_MOVE_BORDER 4
void rtgui_mouse_init(void)
{
const struct rtgui_graphic_driver *gd = rtgui_graphic_driver_get_default();
if (_rtgui_cursor != RT_NULL) rtgui_mouse_fini();
_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 = _UI_BITBYTES(gd->bits_per_pixel);
_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",
(rt_uint8_t *)cursor_xpm,
sizeof(cursor_xpm),
RT_TRUE);
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
#ifdef RTGUI_USING_WINMOVE
/* 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);
#endif
}
void rtgui_mouse_fini(void)
{
if (_rtgui_cursor != RT_NULL)
{
#ifdef RTGUI_USING_WINMOVE
rtgui_free(_rtgui_cursor->win_left);
rtgui_free(_rtgui_cursor->win_right);
rtgui_free(_rtgui_cursor->win_top);
rtgui_free(_rtgui_cursor->win_bottom);
#endif
#ifdef RTGUI_USING_MOUSE_CURSOR
rt_mutex_detach(&cursor_mutex);
rtgui_image_destroy(_rtgui_cursor->cursor_image);
rtgui_free(_rtgui_cursor->cursor_saved);
#endif
rtgui_free(_rtgui_cursor);
_rtgui_cursor = RT_NULL;
}
}
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)
{
#ifdef RTGUI_USING_WINMOVE
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
#endif
{
#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_HW_CURSOR
rtgui_cursor_set_position(_rtgui_cursor->cx, _rtgui_cursor->cy);
#endif
}
#ifdef RTGUI_USING_MOUSE_CURSOR
rt_mutex_release(&cursor_mutex);
#endif
}
void rtgui_mouse_set_position(int x, int y)
{
/* move current cursor */
_rtgui_cursor->cx = x;
_rtgui_cursor->cy = y;
#ifdef RTGUI_USING_HW_CURSOR
rtgui_cursor_set_position(_rtgui_cursor->cx, _rtgui_cursor->cy);
#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_graphic_driver_get_framebuffer(RT_NULL) + _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_graphic_driver_get_framebuffer(RT_NULL) + _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()
{
// FIXME: the prototype of set_pixel is using int so we have to use int
// as well. Might be uniformed with others in the future
int x, y;
rtgui_color_t *ptr;
rtgui_rect_t rect;
void (*set_pixel)(rtgui_color_t * c, int x, int y);
ptr = (rtgui_color_t *) _rtgui_cursor->cursor_image->data;
set_pixel = rtgui_graphic_driver_get_default()->ops->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_screen_update(rtgui_graphic_driver_get_default(), &rect);
}
#endif
#ifdef RTGUI_USING_WINMOVE
void rtgui_winrect_set(struct rtgui_win *win)
{
/* set win rect show */
_rtgui_cursor->win_rect_show = RT_TRUE;
/* set win rect */
_rtgui_cursor->win_rect =
win->_title_wgt == RT_NULL ?
RTGUI_WIDGET(win)->extent :
RTGUI_WIDGET(win->_title_wgt)->extent;
_rtgui_cursor->win = win;
}
rt_bool_t rtgui_winrect_moved_done(rtgui_rect_t *winrect, struct rtgui_win **win)
{
rt_bool_t moved = 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 */
if (winrect)
*winrect = _rtgui_cursor->win_rect;
if (win)
*win = _rtgui_cursor->win;
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, int x, int y);
c = black;
set_pixel = rtgui_graphic_driver_get_default()->ops->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_screen_update(rtgui_graphic_driver_get_default(), &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, *driver_fb;
int winrect_pitch, idx;
rtgui_rect_t screen_rect, win_rect;
driver_fb = rtgui_graphic_driver_get_framebuffer(RT_NULL);
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 = driver_fb + 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 = driver_fb + 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 = driver_fb + 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 = driver_fb + (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, *driver_fb;
int winrect_pitch, idx;
rtgui_rect_t screen_rect, win_rect;
driver_fb = rtgui_graphic_driver_get_framebuffer(RT_NULL);
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 = driver_fb + 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 = driver_fb + 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 = driver_fb + 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 = driver_fb + (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);
}
#endif
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;
}

View File

@ -0,0 +1,56 @@
/*
* 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 <rtgui/widgets/window.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_fini(void);
void rtgui_mouse_moveto(int x, int y);
/* set cursor position */
void rtgui_mouse_set_position(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);
#ifdef RTGUI_USING_WINMOVE
rt_bool_t rtgui_winrect_is_moved(void);
void rtgui_winrect_set(struct rtgui_win *win);
rt_bool_t rtgui_winrect_moved_done(rtgui_rect_t *winrect, struct rtgui_win **win);
#endif
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

2344
components/gui/src/region.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,473 @@
/*
* File : rtgui_app.c
* This file is part of RTGUI in RT-Thread RTOS
* COPYRIGHT (C) 2012, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2012-01-13 Grissiom first version(just a prototype of application API)
* 2012-07-07 Bernard move the send/recv message to the rtgui_system.c
*/
#include <rtgui/rtgui_system.h>
#include <rtgui/rtgui_app.h>
#include <rtgui/widgets/window.h>
static void _rtgui_app_constructor(struct rtgui_app *app)
{
/* set event handler */
rtgui_object_set_event_handler(RTGUI_OBJECT(app),
rtgui_app_event_handler);
app->name = RT_NULL;
app->icon = RT_NULL;
/* set EXITED so we can destroy an application that just created */
app->state_flag = RTGUI_APP_FLAG_EXITED;
app->ref_count = 0;
app->window_cnt = 0;
app->exit_code = 0;
app->tid = RT_NULL;
app->mq = RT_NULL;
app->main_object = RT_NULL;
app->on_idle = RT_NULL;
}
static void _rtgui_app_destructor(struct rtgui_app *app)
{
RT_ASSERT(app != RT_NULL);
rt_free(app->name);
app->name = RT_NULL;
}
DEFINE_CLASS_TYPE(application, "application",
RTGUI_PARENT_TYPE(object),
_rtgui_app_constructor,
_rtgui_app_destructor,
sizeof(struct rtgui_app));
struct rtgui_app *rtgui_app_create(const char *title)
{
rt_thread_t tid = rt_thread_self();
struct rtgui_app *app;
struct rtgui_app *srv_app;
struct rtgui_event_application event;
char mq_name[RT_NAME_MAX];
RT_ASSERT(tid != RT_NULL);
RT_ASSERT(title != RT_NULL);
/* create application */
app = RTGUI_APP(rtgui_object_create(RTGUI_APP_TYPE));
if (app == RT_NULL)
return RT_NULL;
/* one thread only can create one rtgui application */
RT_ASSERT(tid->user_data == 0);
app->tid = tid;
rt_snprintf(mq_name, RT_NAME_MAX, "g%s", title);
app->mq = rt_mq_create(mq_name,
sizeof(union rtgui_event_generic), 64,
RT_IPC_FLAG_FIFO);
if (app->mq == RT_NULL)
{
rt_kprintf("create msgq failed.\n");
goto __mq_err;
}
/* set application title */
app->name = (unsigned char *)rt_strdup((char *)title);
if (app->name == RT_NULL)
goto __err;
/* the first app should be the server */
srv_app = rtgui_get_server();
if (srv_app == RT_NULL)
{
/* set user thread */
tid->user_data = (rt_uint32_t)app;
return app;
}
RTGUI_EVENT_APP_CREATE_INIT(&event);
event.app = app;
/* notify rtgui server to one application has been created */
if (rtgui_send_sync(srv_app, RTGUI_EVENT(&event), sizeof(event)) == RT_EOK)
{
/* set user thread */
tid->user_data = (rt_uint32_t)app;
return app;
}
__err:
__mq_err:
rtgui_object_destroy(RTGUI_OBJECT(app));
return RT_NULL;
}
RTM_EXPORT(rtgui_app_create);
#define _rtgui_application_check(app) \
do { \
RT_ASSERT(app != RT_NULL); \
RT_ASSERT(app->tid != RT_NULL); \
RT_ASSERT(app->tid->user_data != 0); \
RT_ASSERT(app->mq != RT_NULL); \
} while (0)
void rtgui_app_destroy(struct rtgui_app *app)
{
struct rtgui_app *srv_app;
_rtgui_application_check(app);
if (!(app->state_flag & RTGUI_APP_FLAG_EXITED))
{
rt_kprintf("cannot destroy a running application: %s.\n",
app->name);
return;
}
/* send a message to notify rtgui server */
srv_app = rtgui_get_server();
if (srv_app != rtgui_app_self())
{
struct rtgui_event_application event;
RTGUI_EVENT_APP_DESTROY_INIT(&event);
event.app = app;
if (rtgui_send_sync(srv_app, RTGUI_EVENT(&event), sizeof(event)) != RT_EOK)
{
rt_kprintf("destroy an application in server failed\n");
return ;
}
}
app->tid->user_data = 0;
rt_mq_delete(app->mq);
rtgui_object_destroy(RTGUI_OBJECT(app));
}
RTM_EXPORT(rtgui_app_destroy);
struct rtgui_app *rtgui_app_self(void)
{
struct rtgui_app *app;
rt_thread_t self;
/* get current thread */
self = rt_thread_self();
app = (struct rtgui_app *)(self->user_data);
return app;
}
RTM_EXPORT(rtgui_app_self);
void rtgui_app_set_onidle(struct rtgui_app *app, rtgui_idle_func_t onidle)
{
_rtgui_application_check(app);
app->on_idle = onidle;
}
RTM_EXPORT(rtgui_app_set_onidle);
rtgui_idle_func_t rtgui_app_get_onidle(struct rtgui_app *app)
{
_rtgui_application_check(app);
return app->on_idle;
}
RTM_EXPORT(rtgui_app_get_onidle);
rt_inline rt_bool_t _rtgui_application_dest_handle(
struct rtgui_app *app,
struct rtgui_event *event)
{
struct rtgui_event_win *wevent = (struct rtgui_event_win *)event;
struct rtgui_object *dest_object;
if (wevent->wid == RT_NULL)
return RT_FALSE;
/* this window has been closed. */
if (wevent->wid != RT_NULL && wevent->wid->flag & RTGUI_WIN_FLAG_CLOSED)
return RT_TRUE;
/* The dest window may have been destroyed when this event arrived. Check
* against this condition. NOTE: we cannot use the RTGUI_OBJECT because it
* may be invalid already. */
dest_object = (struct rtgui_object*)wevent->wid;
if ((dest_object->flag & RTGUI_OBJECT_FLAG_VALID) !=
RTGUI_OBJECT_FLAG_VALID)
{
return RT_TRUE;
}
dest_object = RTGUI_OBJECT(wevent->wid);
if (dest_object != RT_NULL)
{
if (dest_object->event_handler != RT_NULL)
return dest_object->event_handler(dest_object, event);
else
return RT_FALSE;
}
else
{
rt_kprintf("RTGUI ERROR:server sent a event(%d) without wid\n", event->type);
return RT_FALSE;
}
}
rt_bool_t rtgui_app_event_handler(struct rtgui_object *object, rtgui_event_t *event)
{
struct rtgui_app *app;
RT_ASSERT(object != RT_NULL);
RT_ASSERT(event != RT_NULL);
app = RTGUI_APP(object);
switch (event->type)
{
case RTGUI_EVENT_PAINT:
case RTGUI_EVENT_VPAINT_REQ:
case RTGUI_EVENT_MOUSE_BUTTON:
case RTGUI_EVENT_MOUSE_MOTION:
case RTGUI_EVENT_CLIP_INFO:
case RTGUI_EVENT_WIN_ACTIVATE:
case RTGUI_EVENT_WIN_DEACTIVATE:
case RTGUI_EVENT_WIN_CLOSE:
case RTGUI_EVENT_WIN_MOVE:
case RTGUI_EVENT_WIN_SHOW:
case RTGUI_EVENT_WIN_HIDE:
case RTGUI_EVENT_KBD:
case RTGUI_EVENT_GESTURE:
_rtgui_application_dest_handle(app, event);
break;
case RTGUI_EVENT_APP_ACTIVATE:
if (app->main_object != RT_NULL)
{
/* Let the polymorphism work. */
struct rtgui_event_win_show wev;
RTGUI_EVENT_WIN_SHOW_INIT(&wev);
wev.wid = (struct rtgui_win*)app->main_object;
rtgui_object_handle(app->main_object, &wev.parent);
}
break;
case RTGUI_EVENT_APP_DESTROY:
rtgui_app_exit(app, 0);
break;
case RTGUI_EVENT_TIMER:
{
struct rtgui_timer *timer;
struct rtgui_event_timer *etimer = (struct rtgui_event_timer *) event;
timer = etimer->timer;
timer->pending_cnt--;
RT_ASSERT(timer->pending_cnt >= 0);
if (timer->state == RTGUI_TIMER_ST_DESTROY_PENDING)
{
/* Truly destroy the timer when there is no pending event. */
if (timer->pending_cnt == 0)
rtgui_timer_destory(timer);
}
else if (timer->state == RTGUI_TIMER_ST_RUNNING && timer->timeout != RT_NULL)
{
/* call timeout function */
timer->timeout(timer, timer->user_data);
}
}
break;
case RTGUI_EVENT_MV_MODEL:
{
struct rtgui_event_mv_model *emodel = (struct rtgui_event_mv_model *)event;
RT_ASSERT(emodel->view);
return rtgui_object_handle(RTGUI_OBJECT(emodel->view), event);
}
case RTGUI_EVENT_COMMAND:
{
struct rtgui_event_command *ecmd = (struct rtgui_event_command *)event;
if (ecmd->wid != RT_NULL)
return _rtgui_application_dest_handle(app, event);
}
default:
return rtgui_object_event_handler(object, event);
}
return RT_TRUE;
}
RTM_EXPORT(rtgui_app_event_handler);
rt_inline void _rtgui_application_event_loop(struct rtgui_app *app)
{
rt_err_t result;
rt_uint16_t current_ref;
struct rtgui_event *event;
_rtgui_application_check(app);
/* point to event buffer */
event = (struct rtgui_event *)app->event_buffer;
current_ref = ++app->ref_count;
while (current_ref <= app->ref_count)
{
RT_ASSERT(current_ref == app->ref_count);
if (app->on_idle != RT_NULL)
{
result = rtgui_recv(event, sizeof(union rtgui_event_generic), 0);
if (result == RT_EOK)
RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
else if (result == -RT_ETIMEOUT)
app->on_idle(RTGUI_OBJECT(app), RT_NULL);
}
else
{
result = rtgui_recv(event, sizeof(union rtgui_event_generic), RT_WAITING_FOREVER);
if (result == RT_EOK)
RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
}
}
}
rt_base_t rtgui_app_run(struct rtgui_app *app)
{
_rtgui_application_check(app);
app->state_flag &= ~RTGUI_APP_FLAG_EXITED;
_rtgui_application_event_loop(app);
if (app->ref_count == 0)
app->state_flag |= RTGUI_APP_FLAG_EXITED;
return app->exit_code;
}
RTM_EXPORT(rtgui_app_run);
void rtgui_app_exit(struct rtgui_app *app, rt_uint16_t code)
{
if (app->ref_count == 0)
return;
--app->ref_count;
app->exit_code = code;
}
RTM_EXPORT(rtgui_app_exit);
void rtgui_app_activate(struct rtgui_app *app)
{
struct rtgui_event_application event;
RTGUI_EVENT_APP_ACTIVATE_INIT(&event);
event.app = app;
rtgui_send(app, RTGUI_EVENT(&event), sizeof(struct rtgui_event_application));
}
RTM_EXPORT(rtgui_app_activate);
void rtgui_app_sleep(struct rtgui_app *app, int millisecond)
{
rt_err_t result;
rt_uint16_t current_ref;
struct rtgui_event *event;
rt_tick_t tick, sleep_tick;
int delta_tick;
tick = rt_tick_get();
millisecond = rt_tick_from_millisecond(millisecond);
if (millisecond == 0) return;
sleep_tick = tick + millisecond;
delta_tick = millisecond;
/* point to event buffer */
event = (struct rtgui_event *)app->event_buffer;
current_ref = ++app->ref_count;
while (current_ref <= app->ref_count && delta_tick)
{
RT_ASSERT(current_ref == app->ref_count);
if (app->on_idle != RT_NULL)
{
result = rtgui_recv(event, sizeof(union rtgui_event_generic), 0);
if (result == RT_EOK)
RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
else if (result == -RT_ETIMEOUT)
app->on_idle(RTGUI_OBJECT(app), RT_NULL);
}
else
{
result = rtgui_recv(event, sizeof(union rtgui_event_generic), sleep_tick - rt_tick_get());
if (result == RT_EOK)
RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), event);
}
delta_tick = sleep_tick - rt_tick_get();
}
app->ref_count --;
}
RTM_EXPORT(rtgui_app_sleep);
void rtgui_app_close(struct rtgui_app *app)
{
struct rtgui_event_application event;
RTGUI_EVENT_APP_DESTROY_INIT(&event);
event.app = app;
rtgui_send(app, RTGUI_EVENT(&event), sizeof(struct rtgui_event_application));
}
RTM_EXPORT(rtgui_app_close);
/**
* set this application as window manager
*/
rt_err_t rtgui_app_set_as_wm(struct rtgui_app *app)
{
struct rtgui_app *srv_app;
struct rtgui_event_set_wm event;
_rtgui_application_check(app);
srv_app = rtgui_get_server();
if (srv_app != RT_NULL)
{
/* notify rtgui server, this is a window manager */
RTGUI_EVENT_SET_WM_INIT(&event);
event.app = app;
rtgui_send_sync(srv_app, RTGUI_EVENT(&event), sizeof(event));
return RT_EOK;
}
return RT_ERROR;
}
RTM_EXPORT(rtgui_app_set_as_wm);
void rtgui_app_set_main_win(struct rtgui_app *app, struct rtgui_win *win)
{
_rtgui_application_check(app);
app->main_object = RTGUI_OBJECT(win);
}
RTM_EXPORT(rtgui_app_set_main_win);
struct rtgui_win *rtgui_app_get_main_win(struct rtgui_app *app)
{
return RTGUI_WIN(app->main_object);
}
RTM_EXPORT(rtgui_app_get_main_win);

View File

@ -0,0 +1,723 @@
/*
* File : driver.c
* This file is part of RTGUI in 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-04 Bernard first version
*/
#include <rtthread.h>
#include <rtgui/driver.h>
#include <rtgui/region.h>
#include <rtgui/rtgui_system.h>
#include <string.h>
extern const struct rtgui_graphic_driver_ops *rtgui_pixel_device_get_ops(int pixel_format);
extern const struct rtgui_graphic_driver_ops *rtgui_framebuffer_get_ops(int pixel_format);
static struct rtgui_graphic_driver _driver;
static struct rtgui_graphic_driver *_current_driver = &_driver;
#ifdef RTGUI_USING_VFRAMEBUFFER
#ifndef RTGUI_VFB_PIXEL_FMT
#define RTGUI_VFB_PIXEL_FMT RTGRAPHIC_PIXEL_FORMAT_RGB565
#endif
#include <rtgui/dc.h>
static struct rtgui_graphic_driver _vfb_driver = {0};
static void _graphic_driver_vmode_init(void)
{
if (_vfb_driver.width != _driver.width || _vfb_driver.height != _driver.height)
{
if (_vfb_driver.framebuffer != RT_NULL) rtgui_free((void*)_vfb_driver.framebuffer);
_vfb_driver.device = RT_NULL;
_vfb_driver.pixel_format = RTGUI_VFB_PIXEL_FMT;
_vfb_driver.bits_per_pixel = rtgui_color_get_bits(RTGUI_VFB_PIXEL_FMT);
_vfb_driver.width = _driver.width;
_vfb_driver.height = _driver.height;
_vfb_driver.pitch = _driver.width * _UI_BITBYTES(_vfb_driver.bits_per_pixel);
_vfb_driver.framebuffer = rtgui_malloc(_vfb_driver.height * _vfb_driver.pitch);
rt_memset(_vfb_driver.framebuffer, 0, _vfb_driver.height * _vfb_driver.pitch);
_vfb_driver.ext_ops = RT_NULL;
_vfb_driver.ops = rtgui_framebuffer_get_ops(_vfb_driver.pixel_format);
}
}
void rtgui_graphic_driver_vmode_enter(void)
{
rtgui_screen_lock(RT_WAITING_FOREVER);
_current_driver = &_vfb_driver;
}
RTM_EXPORT(rtgui_graphic_driver_vmode_enter);
void rtgui_graphic_driver_vmode_exit(void)
{
_current_driver = &_driver;
rtgui_screen_unlock();
}
RTM_EXPORT(rtgui_graphic_driver_vmode_exit);
rt_bool_t rtgui_graphic_driver_is_vmode(void)
{
if (_current_driver == &_vfb_driver)
return RT_TRUE;
return RT_FALSE;
}
RTM_EXPORT(rtgui_graphic_driver_is_vmode);
struct rtgui_dc*
rtgui_graphic_driver_get_rect_buffer(const struct rtgui_graphic_driver *driver,
struct rtgui_rect *r)
{
int w, h;
struct rtgui_dc_buffer *buffer;
rt_uint8_t *pixel, *dst;
struct rtgui_rect src, rect;
/* use virtual framebuffer in default */
if (driver == RT_NULL) driver = _current_driver;
if (r == RT_NULL)
{
rtgui_graphic_driver_get_rect(driver, &rect);
}
else
{
rtgui_graphic_driver_get_rect(driver, &src);
rect = *r;
rtgui_rect_intersect(&src, &rect);
}
w = rtgui_rect_width (rect);
h = rtgui_rect_height(rect);
if (!(w && h) || driver->framebuffer == RT_NULL)
return RT_NULL;
/* create buffer DC */
buffer = (struct rtgui_dc_buffer*)rtgui_dc_buffer_create_pixformat(driver->pixel_format, w, h);
if (buffer == RT_NULL)
return (struct rtgui_dc*)buffer;
/* get source pixel */
pixel = (rt_uint8_t*)driver->framebuffer
+ rect.y1 * driver->pitch
+ rect.x1 * rtgui_color_get_bpp(driver->pixel_format);
dst = buffer->pixel;
while (h--)
{
rt_memcpy(dst, pixel, buffer->pitch);
dst += buffer->pitch;
pixel += driver->pitch;
}
return (struct rtgui_dc*)buffer;
}
RTM_EXPORT(rtgui_graphic_driver_get_rect_buffer);
#else
rt_bool_t rtgui_graphic_driver_is_vmode(void)
{
return RT_FALSE;
}
RTM_EXPORT(rtgui_graphic_driver_is_vmode);
#endif
/* get default driver */
struct rtgui_graphic_driver *rtgui_graphic_driver_get_default(void)
{
return _current_driver;
}
RTM_EXPORT(rtgui_graphic_driver_get_default);
void rtgui_graphic_driver_get_rect(const struct rtgui_graphic_driver *driver, rtgui_rect_t *rect)
{
RT_ASSERT(rect != RT_NULL);
/* use default driver */
if (driver == RT_NULL)
driver = _current_driver;
rect->x1 = rect->y1 = 0;
rect->x2 = driver->width;
rect->y2 = driver->height;
}
RTM_EXPORT(rtgui_graphic_driver_get_rect);
rt_err_t rtgui_graphic_set_device(rt_device_t device)
{
rt_err_t result;
struct rt_device_graphic_info info;
struct rtgui_graphic_ext_ops *ext_ops;
/* get framebuffer address */
result = rt_device_control(device, RTGRAPHIC_CTRL_GET_INFO, &info);
if (result != RT_EOK)
{
/* get device information failed */
return -RT_ERROR;
}
/* if the first set graphic device */
if (_driver.width == 0 || _driver.height == 0)
{
rtgui_rect_t rect;
rtgui_get_mainwin_rect(&rect);
if (rect.x2 == 0 || rect.y2 == 0)
{
rtgui_rect_init(&rect, 0, 0, info.width, info.height);
/* re-set main-window */
rtgui_set_mainwin_rect(&rect);
}
}
/* initialize framebuffer driver */
_driver.device = device;
_driver.pixel_format = info.pixel_format;
_driver.bits_per_pixel = info.bits_per_pixel;
_driver.width = info.width;
_driver.height = info.height;
_driver.pitch = _driver.width * _UI_BITBYTES(_driver.bits_per_pixel);
_driver.framebuffer = info.framebuffer;
/* get graphic extension operations */
result = rt_device_control(device, RTGRAPHIC_CTRL_GET_EXT, &ext_ops);
if (result == RT_EOK)
{
_driver.ext_ops = ext_ops;
}
if (info.framebuffer != RT_NULL)
{
/* is a frame buffer device */
_driver.ops = rtgui_framebuffer_get_ops(_driver.pixel_format);
}
else
{
/* is a pixel device */
_driver.ops = rtgui_pixel_device_get_ops(_driver.pixel_format);
}
#ifdef RTGUI_USING_HW_CURSOR
/* set default cursor image */
rtgui_cursor_set_image(RTGUI_CURSOR_ARROW);
#endif
#ifdef RTGUI_USING_VFRAMEBUFFER
_graphic_driver_vmode_init();
#endif
return RT_EOK;
}
RTM_EXPORT(rtgui_graphic_set_device);
/* screen update */
void rtgui_graphic_driver_screen_update(const struct rtgui_graphic_driver *driver, rtgui_rect_t *rect)
{
if (driver->device != RT_NULL)
{
struct rt_device_rect_info rect_info;
rect_info.x = rect->x1;
rect_info.y = rect->y1;
rect_info.width = rect->x2 - rect->x1;
rect_info.height = rect->y2 - rect->y1;
rt_device_control(driver->device, RTGRAPHIC_CTRL_RECT_UPDATE, &rect_info);
}
}
RTM_EXPORT(rtgui_graphic_driver_screen_update);
void rtgui_graphic_driver_set_framebuffer(void *fb)
{
if (_current_driver)
_current_driver->framebuffer = fb;
else
_driver.framebuffer = fb;
}
/* get video frame buffer */
rt_uint8_t *rtgui_graphic_driver_get_framebuffer(const struct rtgui_graphic_driver *driver)
{
if (driver == RT_NULL) driver = _current_driver;
return (rt_uint8_t *)driver->framebuffer;
}
RTM_EXPORT(rtgui_graphic_driver_get_framebuffer);
/*
* FrameBuffer type driver
*/
#define GET_PIXEL(dst, x, y, type) \
(type *)((rt_uint8_t*)((dst)->framebuffer) + (y) * (dst)->pitch + (x) * _UI_BITBYTES((dst)->bits_per_pixel))
static void _rgb565_set_pixel(rtgui_color_t *c, int x, int y)
{
*GET_PIXEL(rtgui_graphic_get_device(), x, y, rt_uint16_t) = rtgui_color_to_565(*c);
}
static void _rgb565_get_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint16_t pixel;
pixel = *GET_PIXEL(rtgui_graphic_get_device(), x, y, rt_uint16_t);
/* get pixel from color */
*c = rtgui_color_from_565(pixel);
}
static void _rgb565_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
rt_ubase_t index;
rt_uint16_t pixel;
rt_uint16_t *pixel_ptr;
/* get pixel from color */
pixel = rtgui_color_to_565(*c);
/* get pixel pointer in framebuffer */
pixel_ptr = GET_PIXEL(rtgui_graphic_get_device(), x1, y, rt_uint16_t);
for (index = x1; index < x2; index ++)
{
*pixel_ptr = pixel;
pixel_ptr ++;
}
}
static void _rgb565_draw_vline(rtgui_color_t *c, int x , int y1, int y2)
{
struct rtgui_graphic_driver *drv;
rt_uint8_t *dst;
rt_uint16_t pixel;
rt_ubase_t index;
drv = rtgui_graphic_get_device();
pixel = rtgui_color_to_565(*c);
dst = GET_PIXEL(drv, x, y1, rt_uint8_t);
for (index = y1; index < y2; index ++)
{
*(rt_uint16_t *)dst = pixel;
dst += drv->pitch;
}
}
static void _rgb565p_set_pixel(rtgui_color_t *c, int x, int y)
{
*GET_PIXEL(rtgui_graphic_get_device(), x, y, rt_uint16_t) = rtgui_color_to_565p(*c);
}
static void _rgb565p_get_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint16_t pixel;
pixel = *GET_PIXEL(rtgui_graphic_get_device(), x, y, rt_uint16_t);
/* get pixel from color */
*c = rtgui_color_from_565p(pixel);
}
static void _rgb565p_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
rt_ubase_t index;
rt_uint16_t pixel;
rt_uint16_t *pixel_ptr;
/* get pixel from color */
pixel = rtgui_color_to_565p(*c);
/* get pixel pointer in framebuffer */
pixel_ptr = GET_PIXEL(rtgui_graphic_get_device(), x1, y, rt_uint16_t);
for (index = x1; index < x2; index ++)
{
*pixel_ptr = pixel;
pixel_ptr ++;
}
}
static void _rgb565p_draw_vline(rtgui_color_t *c, int x , int y1, int y2)
{
struct rtgui_graphic_driver *drv;
rt_uint8_t *dst;
rt_uint16_t pixel;
rt_ubase_t index;
drv = rtgui_graphic_get_device();
pixel = rtgui_color_to_565p(*c);
dst = GET_PIXEL(drv, x, y1, rt_uint8_t);
for (index = y1; index < y2; index ++)
{
*(rt_uint16_t *)dst = pixel;
dst += drv->pitch;
}
}
/* draw raw hline */
static void framebuffer_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y)
{
struct rtgui_graphic_driver *drv;
rt_uint8_t *dst;
drv = rtgui_graphic_get_device();
dst = GET_PIXEL(drv, x1, y, rt_uint8_t);
rt_memcpy(dst, pixels,
(x2 - x1) * _UI_BITBYTES(drv->bits_per_pixel));
}
const struct rtgui_graphic_driver_ops _framebuffer_rgb565_ops =
{
_rgb565_set_pixel,
_rgb565_get_pixel,
_rgb565_draw_hline,
_rgb565_draw_vline,
framebuffer_draw_raw_hline,
};
const struct rtgui_graphic_driver_ops _framebuffer_rgb565p_ops =
{
_rgb565p_set_pixel,
_rgb565p_get_pixel,
_rgb565p_draw_hline,
_rgb565p_draw_vline,
framebuffer_draw_raw_hline,
};
#define FRAMEBUFFER (drv->framebuffer)
#define MONO_PIXEL(framebuffer, x, y) \
((rt_uint8_t**)(framebuffer))[y/8][x]
static void _mono_set_pixel(rtgui_color_t *c, int x, int y)
{
struct rtgui_graphic_driver *drv = rtgui_graphic_get_device();
if (*c == white)
MONO_PIXEL(FRAMEBUFFER, x, y) &= ~(1 << (y % 8));
else
MONO_PIXEL(FRAMEBUFFER, x, y) |= (1 << (y % 8));
}
static void _mono_get_pixel(rtgui_color_t *c, int x, int y)
{
struct rtgui_graphic_driver *drv = rtgui_graphic_get_device();
if (MONO_PIXEL(FRAMEBUFFER, x, y) & (1 << (y % 8)))
*c = black;
else
*c = white;
}
static void _mono_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
struct rtgui_graphic_driver *drv = rtgui_graphic_get_device();
rt_ubase_t index;
if (*c == white)
for (index = x1; index < x2; index ++)
{
MONO_PIXEL(FRAMEBUFFER, index, y) &= ~(1 << (y % 8));
}
else
for (index = x1; index < x2; index ++)
{
MONO_PIXEL(FRAMEBUFFER, index, y) |= (1 << (y % 8));
}
}
static void _mono_draw_vline(rtgui_color_t *c, int x , int y1, int y2)
{
struct rtgui_graphic_driver *drv = rtgui_graphic_get_device();
rt_ubase_t index;
if (*c == white)
for (index = y1; index < y2; index ++)
{
MONO_PIXEL(FRAMEBUFFER, x, index) &= ~(1 << (index % 8));
}
else
for (index = y1; index < y2; index ++)
{
MONO_PIXEL(FRAMEBUFFER, x, index) |= (1 << (index % 8));
}
}
/* draw raw hline */
static void _mono_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y)
{
struct rtgui_graphic_driver *drv = rtgui_graphic_get_device();
rt_ubase_t index;
for (index = x1; index < x2; index ++)
{
if (pixels[index / 8] && (1 << (index % 8)))
MONO_PIXEL(FRAMEBUFFER, index, y) |= (1 << (y % 8));
else
MONO_PIXEL(FRAMEBUFFER, index, y) &= ~(1 << (y % 8));
}
}
const struct rtgui_graphic_driver_ops _framebuffer_mono_ops =
{
_mono_set_pixel,
_mono_get_pixel,
_mono_draw_hline,
_mono_draw_vline,
_mono_draw_raw_hline,
};
const struct rtgui_graphic_driver_ops *rtgui_framebuffer_get_ops(int pixel_format)
{
switch (pixel_format)
{
case RTGRAPHIC_PIXEL_FORMAT_MONO:
return &_framebuffer_mono_ops;
case RTGRAPHIC_PIXEL_FORMAT_GRAY4:
break;
case RTGRAPHIC_PIXEL_FORMAT_GRAY16:
break;
case RTGRAPHIC_PIXEL_FORMAT_RGB565:
return &_framebuffer_rgb565_ops;
case RTGRAPHIC_PIXEL_FORMAT_RGB565P:
return &_framebuffer_rgb565p_ops;
default:
RT_ASSERT(0);
break;
}
return RT_NULL;
}
/*
* Pixel type driver
*/
#define gfx_device (rtgui_graphic_get_device()->device)
#define gfx_device_ops rt_graphix_ops(gfx_device)
static void _pixel_mono_set_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint8_t pixel;
pixel = rtgui_color_to_mono(*c);
gfx_device_ops->set_pixel((char *)&pixel, x, y);
}
static void _pixel_rgb565p_set_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint16_t pixel;
pixel = rtgui_color_to_565p(*c);
gfx_device_ops->set_pixel((char *)&pixel, x, y);
}
static void _pixel_rgb565_set_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint16_t pixel;
pixel = rtgui_color_to_565(*c);
gfx_device_ops->set_pixel((char *)&pixel, x, y);
}
static void _pixel_rgb888_set_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint32_t pixel;
pixel = rtgui_color_to_888(*c);
gfx_device_ops->set_pixel((char *)&pixel, x, y);
}
static void _pixel_mono_get_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint8_t pixel;
gfx_device_ops->get_pixel((char *)&pixel, x, y);
*c = rtgui_color_from_mono(pixel);
}
static void _pixel_rgb565p_get_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint16_t pixel;
gfx_device_ops->get_pixel((char *)&pixel, x, y);
*c = rtgui_color_from_565p(pixel);
}
static void _pixel_rgb565_get_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint16_t pixel;
gfx_device_ops->get_pixel((char *)&pixel, x, y);
*c = rtgui_color_from_565(pixel);
}
static void _pixel_rgb888_get_pixel(rtgui_color_t *c, int x, int y)
{
rt_uint32_t pixel;
gfx_device_ops->get_pixel((char *)&pixel, x, y);
*c = rtgui_color_from_888(pixel);
}
static void _pixel_mono_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
rt_uint8_t pixel;
pixel = rtgui_color_to_mono(*c);
gfx_device_ops->draw_hline((char *)&pixel, x1, x2, y);
}
static void _pixel_rgb565p_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
rt_uint16_t pixel;
pixel = rtgui_color_to_565p(*c);
gfx_device_ops->draw_hline((char *)&pixel, x1, x2, y);
}
static void _pixel_rgb565_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
rt_uint16_t pixel;
pixel = rtgui_color_to_565(*c);
gfx_device_ops->draw_hline((char *)&pixel, x1, x2, y);
}
static void _pixel_rgb888_draw_hline(rtgui_color_t *c, int x1, int x2, int y)
{
rt_uint32_t pixel;
pixel = rtgui_color_to_888(*c);
gfx_device_ops->draw_hline((char *)&pixel, x1, x2, y);
}
static void _pixel_mono_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
{
rt_uint8_t pixel;
pixel = rtgui_color_to_mono(*c);
gfx_device_ops->draw_vline((char *)&pixel, x, y1, y2);
}
static void _pixel_rgb565p_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
{
rt_uint16_t pixel;
pixel = rtgui_color_to_565p(*c);
gfx_device_ops->draw_vline((char *)&pixel, x, y1, y2);
}
static void _pixel_rgb565_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
{
rt_uint16_t pixel;
pixel = rtgui_color_to_565(*c);
gfx_device_ops->draw_vline((char *)&pixel, x, y1, y2);
}
static void _pixel_rgb888_draw_vline(rtgui_color_t *c, int x, int y1, int y2)
{
rt_uint32_t pixel;
pixel = rtgui_color_to_888(*c);
gfx_device_ops->draw_vline((char *)&pixel, x, y1, y2);
}
static void _pixel_draw_raw_hline(rt_uint8_t *pixels, int x1, int x2, int y)
{
if (x2 > x1)
gfx_device_ops->blit_line((char *)pixels, x1, y, (x2 - x1));
else
gfx_device_ops->blit_line((char *)pixels, x2, y, (x1 - x2));
}
const struct rtgui_graphic_driver_ops _pixel_mono_ops =
{
_pixel_mono_set_pixel,
_pixel_mono_get_pixel,
_pixel_mono_draw_hline,
_pixel_mono_draw_vline,
_pixel_draw_raw_hline,
};
const struct rtgui_graphic_driver_ops _pixel_rgb565p_ops =
{
_pixel_rgb565p_set_pixel,
_pixel_rgb565p_get_pixel,
_pixel_rgb565p_draw_hline,
_pixel_rgb565p_draw_vline,
_pixel_draw_raw_hline,
};
const struct rtgui_graphic_driver_ops _pixel_rgb565_ops =
{
_pixel_rgb565_set_pixel,
_pixel_rgb565_get_pixel,
_pixel_rgb565_draw_hline,
_pixel_rgb565_draw_vline,
_pixel_draw_raw_hline,
};
const struct rtgui_graphic_driver_ops _pixel_rgb888_ops =
{
_pixel_rgb888_set_pixel,
_pixel_rgb888_get_pixel,
_pixel_rgb888_draw_hline,
_pixel_rgb888_draw_vline,
_pixel_draw_raw_hline,
};
const struct rtgui_graphic_driver_ops *rtgui_pixel_device_get_ops(int pixel_format)
{
switch (pixel_format)
{
case RTGRAPHIC_PIXEL_FORMAT_MONO:
return &_pixel_mono_ops;
case RTGRAPHIC_PIXEL_FORMAT_RGB565:
return &_pixel_rgb565_ops;
case RTGRAPHIC_PIXEL_FORMAT_RGB565P:
return &_pixel_rgb565p_ops;
case RTGRAPHIC_PIXEL_FORMAT_RGB888:
return &_pixel_rgb888_ops;
}
return RT_NULL;
}
/*
* Hardware cursor
*/
#ifdef RTGUI_USING_HW_CURSOR
void rtgui_cursor_set_position(rt_uint16_t x, rt_uint16_t y)
{
rt_uint32_t value;
if (_current_driver->device != RT_NULL)
{
value = (x << 16 | y);
rt_device_control(_driver.device, RT_DEVICE_CTRL_CURSOR_SET_POSITION, &value);
}
}
void rtgui_cursor_set_image(enum rtgui_cursor_type type)
{
rt_uint32_t value;
if (_current_driver->device != RT_NULL)
{
value = type;
rt_device_control(_driver.device, RT_DEVICE_CTRL_CURSOR_SET_TYPE, &value);
}
};
#endif

View File

@ -0,0 +1,227 @@
/*
* File : rtgui_object.c
* This file is part of RTGUI in 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-04 Bernard first version
*/
#include <rtgui/rtgui_object.h>
#include <rtgui/rtgui_system.h>
static void _rtgui_object_constructor(rtgui_object_t *object)
{
if (!object)
return;
object->flag = RTGUI_OBJECT_FLAG_VALID;
object->id = (rt_uint32_t)object;
}
/* Destroys the object */
static void _rtgui_object_destructor(rtgui_object_t *object)
{
/* Any valid objest should both have valid flag _and_ valid type. Only use
* flag is not enough because the chunk of memory may be reallocted to other
* object and thus the flag will become valid. */
object->flag = RTGUI_OBJECT_FLAG_NONE;
object->type = RT_NULL;
}
DEFINE_CLASS_TYPE(object, "object",
RT_NULL,
_rtgui_object_constructor,
_rtgui_object_destructor,
sizeof(struct rtgui_object));
RTM_EXPORT(_rtgui_object);
void rtgui_type_object_construct(const rtgui_type_t *type, rtgui_object_t *object)
{
/* construct from parent to children */
if (type->parent != RT_NULL)
rtgui_type_object_construct(type->parent, object);
if (type->constructor)
type->constructor(object);
}
void rtgui_type_destructors_call(const rtgui_type_t *type, rtgui_object_t *object)
{
/* destruct from children to parent */
if (type->destructor)
type->destructor(object);
if (type->parent)
rtgui_type_destructors_call(type->parent, object);
}
rt_bool_t rtgui_type_inherits_from(const rtgui_type_t *type, const rtgui_type_t *parent)
{
const rtgui_type_t *t;
t = type;
while (t)
{
if (t == parent) return RT_TRUE;
t = t->parent;
}
return RT_FALSE;
}
const rtgui_type_t *rtgui_type_parent_type_get(const rtgui_type_t *type)
{
return type->parent;
}
const char *rtgui_type_name_get(const rtgui_type_t *type)
{
if (!type) return RT_NULL;
return type->name;
}
#ifdef RTGUI_OBJECT_TRACE
struct rtgui_object_information
{
rt_uint32_t objs_number;
rt_uint32_t allocated_size;
rt_uint32_t max_allocated;
};
struct rtgui_object_information obj_info = {0, 0, 0};
#endif
/**
* @brief Creates a new object: it calls the corresponding constructors
* (from the constructor of the base class to the constructor of the more
* derived class) and then sets the values of the given properties
*
* @param object_type the type of object to create
* @return the created object
*/
rtgui_object_t *rtgui_object_create(const rtgui_type_t *object_type)
{
rtgui_object_t *new_object;
if (!object_type)
return RT_NULL;
new_object = rtgui_malloc(object_type->size);
if (new_object == RT_NULL) return RT_NULL;
#ifdef RTGUI_OBJECT_TRACE
obj_info.objs_number ++;
obj_info.allocated_size += object_type->size;
if (obj_info.allocated_size > obj_info.max_allocated)
obj_info.max_allocated = obj_info.allocated_size;
#endif
new_object->type = object_type;
rtgui_type_object_construct(object_type, new_object);
return new_object;
}
RTM_EXPORT(rtgui_object_create);
/**
* @brief Destroys the object.
*
* The object destructors will be called in inherited type order.
*
* @param object the object to destroy
*/
void rtgui_object_destroy(rtgui_object_t *object)
{
if (!object || object->flag & RTGUI_OBJECT_FLAG_STATIC)
return;
#ifdef RTGUI_OBJECT_TRACE
obj_info.objs_number --;
obj_info.allocated_size -= object->type->size;
#endif
/* call destructor */
RT_ASSERT(object->type != RT_NULL);
rtgui_type_destructors_call(object->type, object);
/* release object */
rtgui_free(object);
}
RTM_EXPORT(rtgui_object_destroy);
/**
* @brief Checks if the object can be cast to the specified type.
*
* If the object doesn't inherit from the specified type, a warning
* is displayed in the console but the object is returned anyway.
*
* @param object the object to cast
* @param type the type to which we cast the object
* @return Returns the object
*/
rtgui_object_t *rtgui_object_check_cast(rtgui_object_t *obj, const rtgui_type_t *obj_type, const char *func, int line)
{
if (!obj) return RT_NULL;
if (!rtgui_type_inherits_from(obj->type, obj_type))
{
rt_kprintf("%s[%d]: Invalid cast from \"%s\" to \"%s\"\n", func, line,
rtgui_type_name_get(obj->type), rtgui_type_name_get(obj_type));
}
return obj;
}
RTM_EXPORT(rtgui_object_check_cast);
/**
* @brief Gets the type of the object
*
* @param object an object
* @return the type of the object (RT_NULL on failure)
*/
const rtgui_type_t *rtgui_object_object_type_get(rtgui_object_t *object)
{
if (!object) return RT_NULL;
return object->type;
}
RTM_EXPORT(rtgui_object_object_type_get);
void rtgui_object_set_event_handler(struct rtgui_object *object, rtgui_event_handler_ptr handler)
{
RT_ASSERT(object != RT_NULL);
object->event_handler = handler;
}
RTM_EXPORT(rtgui_object_set_event_handler);
rt_bool_t rtgui_object_event_handler(struct rtgui_object *object, struct rtgui_event *event)
{
return RT_FALSE;
}
RTM_EXPORT(rtgui_object_event_handler);
void rtgui_object_set_id(struct rtgui_object *object, rt_uint32_t id)
{
#ifdef RTGUI_USING_ID_CHECK
struct rtgui_object *obj = rtgui_get_self_object(id);
RT_ASSERT(!obj);
#endif
object->id = id;
}
RTM_EXPORT(rtgui_object_set_id);
rt_uint32_t rtgui_object_get_id(struct rtgui_object *object)
{
return object->id;
}
RTM_EXPORT(rtgui_object_get_id);

View File

@ -0,0 +1,808 @@
/*
* File : rtgui_system.c
* This file is part of RTGUI in 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-04 Bernard first version
*/
#include <rtgui/rtgui.h>
#include <rtgui/image.h>
#include <rtgui/font.h>
#include <rtgui/event.h>
#include <rtgui/rtgui_app.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/widgets/window.h>
//#include <rtgui/rtgui_theme.h>
#ifdef _WIN32_NATIVE
#define RTGUI_MEM_TRACE
#endif
const rtgui_color_t default_foreground = RTGUI_RGB(0x00, 0x00, 0x00);
const rtgui_color_t default_background = RTGUI_RGB(212, 208, 200);
extern struct rtgui_font rtgui_font_asc16;
extern struct rtgui_font rtgui_font_asc12;
static rtgui_rect_t _mainwin_rect;
static struct rt_mutex _screen_lock;
int rtgui_system_server_init(void)
{
rt_mutex_init(&_screen_lock, "screen", RT_IPC_FLAG_FIFO);
#if RTGUI_DEFAULT_FONT_SIZE == 16
rtgui_font_set_defaut(&rtgui_font_asc16);
#elif RTGUI_DEFAULT_FONT_SIZE == 12
rtgui_font_set_defaut(&rtgui_font_asc12);
#else
rtgui_font_set_defaut(&rtgui_font_asc12);
#endif
/* init image */
rtgui_system_image_init();
/* init font */
rtgui_font_system_init();
/* init rtgui server */
rtgui_topwin_init();
rtgui_server_init();
/* use driver rect for main window */
rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), &_mainwin_rect);
/* init theme */
// rtgui_system_theme_init();
return 0;
}
INIT_APP_EXPORT(rtgui_system_server_init);
/************************************************************************/
/* RTGUI Timer */
/************************************************************************/
static void rtgui_time_out(void *parameter)
{
rtgui_timer_t *timer;
rtgui_event_timer_t event;
timer = (rtgui_timer_t *)parameter;
if (!(timer->state == RTGUI_TIMER_ST_RUNNING))
return;
/*
* Note: event_timer can not use RTGUI_EVENT_TIMER_INIT to init, for there is no
* thread context
*/
event.parent.type = RTGUI_EVENT_TIMER;
event.parent.sender = RT_NULL;
event.timer = timer;
timer->pending_cnt++;
rtgui_send(timer->app, &(event.parent), sizeof(rtgui_event_timer_t));
}
rtgui_timer_t *rtgui_timer_create(rt_int32_t time, rt_int32_t flag, rtgui_timeout_func timeout, void *parameter)
{
rtgui_timer_t *timer;
timer = (rtgui_timer_t *) rtgui_malloc(sizeof(rtgui_timer_t));
timer->app = rtgui_app_self();
timer->timeout = timeout;
timer->pending_cnt = 0;
timer->state = RTGUI_TIMER_ST_INIT;
timer->user_data = parameter;
/* init rt-thread timer */
rt_timer_init(&(timer->timer), "rtgui", rtgui_time_out, timer, time, (rt_uint8_t)flag);
return timer;
}
RTM_EXPORT(rtgui_timer_create);
void rtgui_timer_destory(rtgui_timer_t *timer)
{
RT_ASSERT(timer != RT_NULL);
/* stop timer firstly */
rtgui_timer_stop(timer);
if (timer->pending_cnt != 0 && timer->app->ref_count != 0)
{
timer->state = RTGUI_TIMER_ST_DESTROY_PENDING;
}
else
{
/* detach rt-thread timer */
rt_timer_detach(&(timer->timer));
rtgui_free(timer);
}
}
RTM_EXPORT(rtgui_timer_destory);
void rtgui_timer_set_timeout(rtgui_timer_t *timer, rt_int32_t time)
{
RT_ASSERT(timer != RT_NULL);
/* start rt-thread timer */
if (timer->state == RTGUI_TIMER_ST_RUNNING)
{
rtgui_timer_stop(timer);
rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_TIME, &time);
rtgui_timer_start(timer);
}
else
{
rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_TIME, &time);
}
}
RTM_EXPORT(rtgui_timer_set_timeout);
void rtgui_timer_start(rtgui_timer_t *timer)
{
RT_ASSERT(timer != RT_NULL);
/* start rt-thread timer */
timer->state = RTGUI_TIMER_ST_RUNNING;
rt_timer_start(&(timer->timer));
}
RTM_EXPORT(rtgui_timer_start);
void rtgui_timer_stop(rtgui_timer_t *timer)
{
RT_ASSERT(timer != RT_NULL);
/* stop rt-thread timer */
timer->state = RTGUI_TIMER_ST_INIT;
rt_timer_stop(&(timer->timer));
}
RTM_EXPORT(rtgui_timer_stop);
/************************************************************************/
/* RTGUI Memory Management */
/************************************************************************/
#ifdef RTGUI_MEM_TRACE
struct rtgui_mem_info
{
rt_uint32_t allocated_size;
rt_uint32_t max_allocated;
};
struct rtgui_mem_info mem_info;
#define MEMTRACE_MAX 4096
#define MEMTRACE_HASH_SIZE 256
struct rti_memtrace_item
{
void *mb_ptr; /* memory block pointer */
rt_uint32_t mb_len; /* memory block length */
struct rti_memtrace_item *next;
};
struct rti_memtrace_item trace_list[MEMTRACE_MAX];
struct rti_memtrace_item *item_hash[MEMTRACE_HASH_SIZE];
struct rti_memtrace_item *item_free;
rt_bool_t rti_memtrace_inited = 0;
void rti_memtrace_init()
{
struct rti_memtrace_item *item;
rt_uint32_t index;
rt_memset(trace_list, 0, sizeof(trace_list));
rt_memset(item_hash, 0, sizeof(item_hash));
item_free = &trace_list[0];
item = &trace_list[0];
for (index = 1; index < MEMTRACE_HASH_SIZE; index ++)
{
item->next = &trace_list[index];
item = item->next;
}
item->next = RT_NULL;
}
void rti_malloc_hook(void *ptr, rt_uint32_t len)
{
rt_uint32_t index;
struct rti_memtrace_item *item;
if (item_free == RT_NULL) return;
mem_info.allocated_size += len;
if (mem_info.max_allocated < mem_info.allocated_size)
mem_info.max_allocated = mem_info.allocated_size;
/* lock context */
item = item_free;
item_free = item->next;
item->mb_ptr = ptr;
item->mb_len = len;
item->next = RT_NULL;
/* get hash item index */
index = ((rt_uint32_t)ptr) % MEMTRACE_HASH_SIZE;
if (item_hash[index] != RT_NULL)
{
/* add to list */
item->next = item_hash[index];
item_hash[index] = item;
}
else
{
/* set list header */
item_hash[index] = item;
}
/* unlock context */
}
void rti_free_hook(void *ptr)
{
rt_uint32_t index;
struct rti_memtrace_item *item;
/* get hash item index */
index = ((rt_uint32_t)ptr) % MEMTRACE_HASH_SIZE;
if (item_hash[index] != RT_NULL)
{
item = item_hash[index];
if (item->mb_ptr == ptr)
{
/* delete item from list */
item_hash[index] = item->next;
}
else
{
/* find ptr in list */
while (item->next != RT_NULL && item->next->mb_ptr != ptr)
item = item->next;
/* delete item from list */
if (item->next != RT_NULL)
{
struct rti_memtrace_item *i;
i = item->next;
item->next = item->next->next;
item = i;
}
else
{
/* not found */
return;
}
}
/* reduce allocated size */
mem_info.allocated_size -= item->mb_len;
/* clear item */
rt_memset(item, 0, sizeof(struct rti_memtrace_item));
/* add item to the free list */
item->next = item_free;
item_free = item;
}
}
#endif
//#define DEBUG_MEMLEAK
#undef rtgui_malloc
void *rtgui_malloc(rt_size_t size)
{
void *ptr;
ptr = rt_malloc(size);
#ifdef RTGUI_MEM_TRACE
if (rti_memtrace_inited == 0)
{
rti_memtrace_init();
rti_memtrace_inited = 1;
}
if (ptr != RT_NULL)
rti_malloc_hook(ptr, size);
#endif
#ifdef DEBUG_MEMLEAK
rt_kprintf("alloc %p (%d) on %p %.*s\n",
ptr, size, __builtin_return_address(0),
RT_NAME_MAX, rt_thread_self()->name);
#endif
return ptr;
}
RTM_EXPORT(rtgui_malloc);
#undef rtgui_realloc
void *rtgui_realloc(void *ptr, rt_size_t size)
{
void *new_ptr;
#ifdef RTGUI_MEM_TRACE
new_ptr = rtgui_malloc(size);
if ((new_ptr != RT_NULL) && (ptr != RT_NULL))
{
rt_memcpy(new_ptr, ptr, size);
rtgui_free(ptr);
}
#else
new_ptr = rt_realloc(ptr, size);
#endif
#ifdef DEBUG_MEMLEAK
rt_kprintf("realloc %p to %p (%d) on %p %*.s\n",
ptr, new_ptr, size, __builtin_return_address(0),
RT_NAME_MAX, rt_thread_self()->name);
#endif
return new_ptr;
}
RTM_EXPORT(rtgui_realloc);
#undef rtgui_free
void rtgui_free(void *ptr)
{
#ifdef DEBUG_MEMLEAK
rt_kprintf("dealloc %p on %p\n",
ptr, __builtin_return_address(0));
#endif
#ifdef RTGUI_MEM_TRACE
if (ptr != RT_NULL)
rti_free_hook(ptr);
#endif
rt_free(ptr);
}
RTM_EXPORT(rtgui_free);
#if defined(RTGUI_MEM_TRACE) && defined(RT_USING_FINSH)
#include <finsh.h>
void list_guimem(void)
{
rt_kprintf("Current Used: %d, Maximal Used: %d\n", mem_info.allocated_size, mem_info.max_allocated);
}
FINSH_FUNCTION_EXPORT(list_guimem, display memory information);
#endif
/************************************************************************/
/* RTGUI Event Dump */
/************************************************************************/
// #define RTGUI_EVENT_DEBUG
#ifdef RTGUI_EVENT_DEBUG
const char *rtgui_event_string[] =
{
/* application event */
"APP_CREATE", /* create an application */
"APP_DESTROY", /* destroy an application */
"APP_ACTIVATE", /* activate an application */
/* window event */
"WIN_CREATE", /* create a window */
"WIN_DESTROY", /* destroy a window */
"WIN_SHOW", /* show a window */
"WIN_HIDE", /* hide a window */
"WIN_ACTIVATE", /* activate a window */
"WIN_DEACTIVATE", /* deactivate a window */
"WIN_CLOSE", /* close a window */
"WIN_MOVE", /* move a window */
"WIN_RESIZE", /* resize a window */
"WIN_MODAL_ENTER", /* a window modals */
"SET_WM", /* set window manager */
"UPDATE_BEGIN", /* begin of update rect */
"UPDATE_END", /* end of update rect */
"MONITOR_ADD", /* add a monitor rect */
"MONITOR_REMOVE", /* remove a monitor rect*/
"SHOW", /* the widget is going to be shown */
"HIDE", /* the widget is going to be hidden */
"PAINT", /* paint on screen */
"TIMER", /* timer */
"UPDATE_TOPLVL", /* update toplevel */
"VPAINT_REQ", /* virtual paint request */
/* clip rect information */
"CLIP_INFO", /* clip rect info */
/* mouse and keyboard event */
"MOUSE_MOTION", /* mouse motion */
"MOUSE_BUTTON", /* mouse button info */
"KBD", /* keyboard info */
"TOUCH", /* touch info */
"GESTURE", /* gesture */
"FOCUSED", /* widget got focuse */
"SCROLLED", /* scroll bar scrolled */
"RESIZE", /* widget resize */
"SELECTED", /* widget selected */
"UNSELECTED", /* widget unselected */
"MV_MODEL", /* modal chaned in MV */
"BUS_NOTIFY_EVENT",
};
#define DBG_MSG(x) rt_kprintf x
static void rtgui_event_dump(struct rtgui_app* app, rtgui_event_t *event)
{
char *sender = "(unknown)";
if ((event->type == RTGUI_EVENT_TIMER) ||
(event->type == RTGUI_EVENT_UPDATE_BEGIN) ||
(event->type == RTGUI_EVENT_MOUSE_MOTION) ||
(event->type == RTGUI_EVENT_UPDATE_END))
{
/* don't dump timer event */
return ;
}
if (event->sender != RT_NULL)
sender = (char*)event->sender->name;
if (event->type >= RTGUI_EVENT_COMMAND)
{
rt_kprintf("%s -- USER COMMAND EVENT --> %s \n", sender, app->name);
return ;
}
else
{
rt_kprintf("%s -- %s --> %s ", sender, rtgui_event_string[event->type], app->name);
}
switch (event->type)
{
case RTGUI_EVENT_APP_CREATE:
case RTGUI_EVENT_APP_DESTROY:
case RTGUI_EVENT_APP_ACTIVATE:
{
struct rtgui_event_application *eapp = (struct rtgui_event_application *)event;
rt_kprintf("app: %s", eapp->app->name);
}
break;
case RTGUI_EVENT_PAINT:
{
struct rtgui_event_paint *paint = (struct rtgui_event_paint *)event;
if (paint->wid != RT_NULL)
rt_kprintf("win: %s", paint->wid->title);
}
break;
case RTGUI_EVENT_KBD:
{
struct rtgui_event_kbd *ekbd = (struct rtgui_event_kbd *) event;
if (ekbd->wid != RT_NULL)
rt_kprintf("win: %s", ekbd->wid->title);
if (RTGUI_KBD_IS_UP(ekbd)) rt_kprintf(", up");
else rt_kprintf(", down");
}
break;
case RTGUI_EVENT_CLIP_INFO:
{
struct rtgui_event_clip_info *info = (struct rtgui_event_clip_info *)event;
if (info->wid != RT_NULL)
rt_kprintf("win: %s", info->wid->title);
}
break;
case RTGUI_EVENT_WIN_CREATE:
{
struct rtgui_event_win_create *create = (struct rtgui_event_win_create *)event;
rt_kprintf(" win: %s at (x1:%d, y1:%d, x2:%d, y2:%d), addr: %p",
create->wid->title,
RTGUI_WIDGET(create->wid)->extent.x1,
RTGUI_WIDGET(create->wid)->extent.y1,
RTGUI_WIDGET(create->wid)->extent.x2,
RTGUI_WIDGET(create->wid)->extent.y2,
create->wid
);
}
break;
case RTGUI_EVENT_UPDATE_END:
{
struct rtgui_event_update_end *update_end = (struct rtgui_event_update_end *)event;
rt_kprintf("(x:%d, y1:%d, x2:%d, y2:%d)", update_end->rect.x1,
update_end->rect.y1,
update_end->rect.x2,
update_end->rect.y2);
}
break;
case RTGUI_EVENT_WIN_ACTIVATE:
case RTGUI_EVENT_WIN_DEACTIVATE:
case RTGUI_EVENT_WIN_SHOW:
case RTGUI_EVENT_WIN_HIDE:
case RTGUI_EVENT_WIN_MODAL_ENTER:
{
struct rtgui_event_win *win = (struct rtgui_event_win *)event;
if (win->wid != RT_NULL)
rt_kprintf("win: %s", win->wid->title);
}
break;
case RTGUI_EVENT_WIN_MOVE:
{
struct rtgui_event_win_move *win = (struct rtgui_event_win_move *)event;
if (win->wid != RT_NULL)
{
rt_kprintf("win: %s", win->wid->title);
rt_kprintf(" to (x:%d, y:%d)", win->x, win->y);
}
}
break;
case RTGUI_EVENT_WIN_RESIZE:
{
struct rtgui_event_win_resize *win = (struct rtgui_event_win_resize *)event;
if (win->wid != RT_NULL)
{
rt_kprintf("win: %s, rect(x1:%d, y1:%d, x2:%d, y2:%d)", win->wid->title,
RTGUI_WIDGET(win->wid)->extent.x1,
RTGUI_WIDGET(win->wid)->extent.y1,
RTGUI_WIDGET(win->wid)->extent.x2,
RTGUI_WIDGET(win->wid)->extent.y2);
}
}
break;
case RTGUI_EVENT_MOUSE_BUTTON:
case RTGUI_EVENT_MOUSE_MOTION:
{
struct rtgui_event_mouse *mouse = (struct rtgui_event_mouse *)event;
if (mouse->button & RTGUI_MOUSE_BUTTON_LEFT) rt_kprintf("left ");
else rt_kprintf("right ");
if (mouse->button & RTGUI_MOUSE_BUTTON_DOWN) rt_kprintf("down ");
else rt_kprintf("up ");
if (mouse->wid != RT_NULL)
rt_kprintf("win: %s at (%d, %d)", mouse->wid->title,
mouse->x, mouse->y);
else
rt_kprintf("(%d, %d)", mouse->x, mouse->y);
}
break;
case RTGUI_EVENT_MONITOR_ADD:
{
struct rtgui_event_monitor *monitor = (struct rtgui_event_monitor *)event;
if (monitor->wid != RT_NULL)
{
rt_kprintf("win: %s, the rect is:(%d, %d) - (%d, %d)", monitor->wid->title,
monitor->rect.x1, monitor->rect.y1,
monitor->rect.x2, monitor->rect.y2);
}
}
break;
default:
break;
}
rt_kprintf("\n");
}
#else
#define DBG_MSG(x)
#define rtgui_event_dump(app, event)
#endif
/************************************************************************/
/* RTGUI IPC APIs */
/************************************************************************/
rt_err_t rtgui_send(struct rtgui_app* app, rtgui_event_t *event, rt_size_t event_size)
{
rt_err_t result;
RT_ASSERT(app != RT_NULL);
RT_ASSERT(event != RT_NULL);
RT_ASSERT(event_size != 0);
rtgui_event_dump(app, event);
result = rt_mq_send(app->mq, event, event_size);
if (result != RT_EOK)
{
if (event->type != RTGUI_EVENT_TIMER)
rt_kprintf("send event to %s failed\n", app->name);
}
return result;
}
RTM_EXPORT(rtgui_send);
rt_err_t rtgui_send_urgent(struct rtgui_app* app, rtgui_event_t *event, rt_size_t event_size)
{
rt_err_t result;
RT_ASSERT(app != RT_NULL);
RT_ASSERT(event != RT_NULL);
RT_ASSERT(event_size != 0);
rtgui_event_dump(app, event);
result = rt_mq_urgent(app->mq, event, event_size);
if (result != RT_EOK)
rt_kprintf("send ergent event to %s failed\n", app->name);
return result;
}
RTM_EXPORT(rtgui_send_urgent);
rt_err_t rtgui_send_sync(struct rtgui_app* app, rtgui_event_t *event, rt_size_t event_size)
{
rt_err_t r;
rt_int32_t ack_buffer, ack_status;
struct rt_mailbox ack_mb;
RT_ASSERT(app != RT_NULL);
RT_ASSERT(event != RT_NULL);
RT_ASSERT(event_size != 0);
rtgui_event_dump(app, event);
/* init ack mailbox */
r = rt_mb_init(&ack_mb, "ack", &ack_buffer, 1, 0);
if (r != RT_EOK)
goto __return;
event->ack = &ack_mb;
r = rt_mq_send(app->mq, event, event_size);
if (r != RT_EOK)
{
rt_kprintf("send sync event failed\n");
goto __return;
}
r = rt_mb_recv(&ack_mb, (rt_uint32_t *)&ack_status, RT_WAITING_FOREVER);
if (r != RT_EOK)
goto __return;
if (ack_status != RTGUI_STATUS_OK)
r = -RT_ERROR;
else
r = RT_EOK;
__return:
/* fini ack mailbox */
rt_mb_detach(&ack_mb);
return r;
}
RTM_EXPORT(rtgui_send_sync);
rt_err_t rtgui_ack(rtgui_event_t *event, rt_int32_t status)
{
RT_ASSERT(event != RT_NULL);
RT_ASSERT(event->ack != RT_NULL);
rt_mb_send(event->ack, status);
return RT_EOK;
}
RTM_EXPORT(rtgui_ack);
rt_err_t rtgui_recv(rtgui_event_t *event, rt_size_t event_size, rt_int32_t timeout)
{
struct rtgui_app *app;
rt_err_t r;
RT_ASSERT(event != RT_NULL);
RT_ASSERT(event_size != 0);
app = (struct rtgui_app *)(rt_thread_self()->user_data);
if (app == RT_NULL) return -RT_ERROR;
r = rt_mq_recv(app->mq, event, event_size, timeout);
return r;
}
RTM_EXPORT(rtgui_recv);
rt_err_t rtgui_recv_filter(rt_uint32_t type, rtgui_event_t *event, rt_size_t event_size)
{
rtgui_event_t *e;
struct rtgui_app *app;
RT_ASSERT(event != RT_NULL);
RT_ASSERT(event_size != 0);
app = (struct rtgui_app *)(rt_thread_self()->user_data);
if (app == RT_NULL)
return -RT_ERROR;
e = (rtgui_event_t*)&app->event_buffer[0];
while (rt_mq_recv(app->mq, e, sizeof(union rtgui_event_generic), RT_WAITING_FOREVER) == RT_EOK)
{
if (e->type == type)
{
rt_memcpy(event, e, event_size);
return RT_EOK;
}
else
{
if (RTGUI_OBJECT(app)->event_handler != RT_NULL)
{
RTGUI_OBJECT(app)->event_handler(RTGUI_OBJECT(app), e);
}
}
}
return -RT_ERROR;
}
RTM_EXPORT(rtgui_recv_filter);
void rtgui_set_mainwin_rect(struct rtgui_rect *rect)
{
_mainwin_rect = *rect;
}
RTM_EXPORT(rtgui_set_mainwin_rect);
void rtgui_get_mainwin_rect(struct rtgui_rect *rect)
{
*rect = _mainwin_rect;
}
RTM_EXPORT(rtgui_get_mainwin_rect);
void rtgui_get_screen_rect(struct rtgui_rect *rect)
{
rtgui_graphic_driver_get_rect(rtgui_graphic_driver_get_default(), rect);
}
RTM_EXPORT(rtgui_get_screen_rect);
void rtgui_screen_lock(rt_int32_t timeout)
{
rt_mutex_take(&_screen_lock, timeout);
}
RTM_EXPORT(rtgui_screen_lock);
void rtgui_screen_unlock(void)
{
rt_mutex_release(&_screen_lock);
}
RTM_EXPORT(rtgui_screen_unlock);
int rtgui_screen_lock_freeze(void)
{
int hold = 0;
if (_screen_lock.owner == rt_thread_self())
{
int index;
index = hold = _screen_lock.hold;
while (index --) rt_mutex_release(&_screen_lock);
}
return hold;
}
RTM_EXPORT(rtgui_screen_lock_freeze);
void rtgui_screen_lock_thaw(int value)
{
while (value--) rt_mutex_take(&_screen_lock, RT_WAITING_FOREVER);
}
RTM_EXPORT(rtgui_screen_lock_thaw);

433
components/gui/src/server.c Normal file
View File

@ -0,0 +1,433 @@
/*
* File : server.c
* This file is part of RTGUI in 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-04 Bernard first version
*/
#include <rtgui/rtgui.h>
#include <rtgui/event.h>
#include <rtgui/rtgui_system.h>
#include <rtgui/rtgui_object.h>
#include <rtgui/rtgui_app.h>
#include <rtgui/driver.h>
//#include <rtgui/touch.h>
#include <rtgui/widgets/window.h>
#include "mouse.h"
#include "topwin.h"
static struct rtgui_app *rtgui_server_app = RT_NULL;
static struct rtgui_app *rtgui_wm_application = RT_NULL;
static void (*_show_win_hook)(void);
static void (*_act_win_hook)(void);
void rtgui_server_install_show_win_hook(void (*hk)(void))
{
_show_win_hook = hk;
}
void rtgui_server_install_act_win_hook(void (*hk)(void))
{
_act_win_hook = hk;
}
void rtgui_server_handle_update(struct rtgui_event_update_end *event)
{
struct rtgui_graphic_driver *driver;
driver = rtgui_graphic_driver_get_default();
if (driver != RT_NULL)
{
rtgui_graphic_driver_screen_update(driver, &(event->rect));
}
}
void rtgui_server_handle_monitor_add(struct rtgui_event_monitor *event)
{
/* add monitor rect to top window list */
rtgui_topwin_append_monitor_rect(event->wid, &(event->rect));
}
void rtgui_server_handle_monitor_remove(struct rtgui_event_monitor *event)
{
/* add monitor rect to top window list */
rtgui_topwin_remove_monitor_rect(event->wid, &(event->rect));
}
void rtgui_server_handle_mouse_btn(struct rtgui_event_mouse *event)
{
struct rtgui_topwin *wnd;
/* re-init to server thread */
RTGUI_EVENT_MOUSE_BUTTON_INIT(event);
/* set cursor position */
rtgui_mouse_set_position(event->x, event->y);
#ifdef RTGUI_USING_WINMOVE
if (rtgui_winrect_is_moved() &&
event->button & (RTGUI_MOUSE_BUTTON_LEFT | RTGUI_MOUSE_BUTTON_UP))
{
struct rtgui_win *win;
rtgui_rect_t rect;
if (rtgui_winrect_moved_done(&rect, &win) == RT_TRUE)
{
struct rtgui_event_win_move ewin;
/* move window */
RTGUI_EVENT_WIN_MOVE_INIT(&ewin);
ewin.wid = win;
ewin.x = rect.x1;
ewin.y = rect.y1;
/* send to client thread */
rtgui_send(win->app, &(ewin.parent), sizeof(ewin));
return;
}
}
#endif
/* get the wnd which contains the mouse */
wnd = rtgui_topwin_get_wnd_no_modaled(event->x, event->y);
if (wnd == RT_NULL)
return;
event->wid = wnd->wid;
/* only raise window if the button is pressed down */
if (event->button & RTGUI_MOUSE_BUTTON_DOWN &&
rtgui_topwin_get_focus() != wnd)
{
rtgui_topwin_activate_topwin(wnd);
}
/* send mouse event to thread */
rtgui_send(wnd->app,
(struct rtgui_event *)event,
sizeof(struct rtgui_event_mouse));
}
void rtgui_server_handle_mouse_motion(struct rtgui_event_mouse *event)
{
/* the topwin contains current mouse */
struct rtgui_topwin *win = RT_NULL;
/* re-init mouse event */
RTGUI_EVENT_MOUSE_MOTION_INIT(event);
win = rtgui_topwin_get_wnd_no_modaled(event->x, event->y);
if (win != RT_NULL && win->monitor_list.next != RT_NULL)
{
// FIXME:
/* check whether the monitor exist */
if (rtgui_mouse_monitor_contains_point(&(win->monitor_list),
event->x, event->y) != RT_TRUE)
{
win = RT_NULL;
}
}
if (win)
{
event->wid = win->wid;
rtgui_send(win->wid->app, &(event->parent), sizeof(*event));
}
/* move mouse to (x, y) */
rtgui_mouse_moveto(event->x, event->y);
}
void rtgui_server_handle_kbd(struct rtgui_event_kbd *event)
{
struct rtgui_topwin *wnd;
/* re-init to server thread */
RTGUI_EVENT_KBD_INIT(event);
/* todo: handle input method and global shortcut */
wnd = rtgui_topwin_get_focus();
if (wnd != RT_NULL)
{
RT_ASSERT(wnd->flag & WINTITLE_ACTIVATE)
/* send to focus window */
event->wid = wnd->wid;
/* send keyboard event to thread */
rtgui_send(wnd->app, (struct rtgui_event *)event, sizeof(struct rtgui_event_kbd));
return;
}
}
void rtgui_server_handle_touch(struct rtgui_event_touch *event)
{
// if (rtgui_touch_do_calibration(event) == RT_TRUE)
// {
// struct rtgui_event_mouse emouse;
// /* convert it as a mouse event to rtgui */
// if (event->up_down == RTGUI_TOUCH_MOTION)
// {
// RTGUI_EVENT_MOUSE_MOTION_INIT(&emouse);
// emouse.x = event->x;
// emouse.y = event->y;
// emouse.button = 0;
// rtgui_server_handle_mouse_motion(&emouse);
// }
// else
// {
// RTGUI_EVENT_MOUSE_BUTTON_INIT(&emouse);
// emouse.x = event->x;
// emouse.y = event->y;
// emouse.button = RTGUI_MOUSE_BUTTON_LEFT;
// if (event->up_down == RTGUI_TOUCH_UP)
// emouse.button |= RTGUI_MOUSE_BUTTON_UP;
// else
// emouse.button |= RTGUI_MOUSE_BUTTON_DOWN;
// rtgui_server_handle_mouse_btn(&emouse);
// }
// }
}
#ifdef _WIN32_NATIVE
#include <windows.h>
#endif
static rt_bool_t rtgui_server_event_handler(struct rtgui_object *object,
struct rtgui_event *event)
{
RT_ASSERT(object != RT_NULL);
RT_ASSERT(event != RT_NULL);
/* dispatch event */
switch (event->type)
{
case RTGUI_EVENT_APP_CREATE:
case RTGUI_EVENT_APP_DESTROY:
if (rtgui_wm_application != RT_NULL)
{
/* forward event to wm application */
rtgui_send(rtgui_wm_application, event, sizeof(struct rtgui_event_application));
}
else
{
/* always ack with OK */
rtgui_ack(event, RTGUI_STATUS_OK);
}
break;
/* mouse and keyboard event */
case RTGUI_EVENT_MOUSE_MOTION:
/* handle mouse motion event */
rtgui_server_handle_mouse_motion((struct rtgui_event_mouse *)event);
break;
case RTGUI_EVENT_MOUSE_BUTTON:
/* handle mouse button */
rtgui_server_handle_mouse_btn((struct rtgui_event_mouse *)event);
break;
case RTGUI_EVENT_TOUCH:
/* handle touch event */
rtgui_server_handle_touch((struct rtgui_event_touch *)event);
break;
case RTGUI_EVENT_KBD:
/* handle keyboard event */
rtgui_server_handle_kbd((struct rtgui_event_kbd *)event);
break;
/* window event */
case RTGUI_EVENT_WIN_CREATE:
if (rtgui_topwin_add((struct rtgui_event_win_create *)event) == RT_EOK)
rtgui_ack(event, RTGUI_STATUS_OK);
else
rtgui_ack(event, RTGUI_STATUS_ERROR);
break;
case RTGUI_EVENT_WIN_SHOW:
if (_show_win_hook) _show_win_hook();
if (rtgui_topwin_show((struct rtgui_event_win *)event) == RT_EOK)
rtgui_ack(event, RTGUI_STATUS_OK);
else
rtgui_ack(event, RTGUI_STATUS_ERROR);
break;
case RTGUI_EVENT_WIN_HIDE:
if (rtgui_topwin_hide((struct rtgui_event_win *)event) == RT_EOK)
rtgui_ack(event, RTGUI_STATUS_OK);
else
rtgui_ack(event, RTGUI_STATUS_ERROR);
break;
case RTGUI_EVENT_WIN_MOVE:
if (rtgui_topwin_move((struct rtgui_event_win_move *)event) == RT_EOK)
rtgui_ack(event, RTGUI_STATUS_OK);
else
rtgui_ack(event, RTGUI_STATUS_ERROR);
break;
case RTGUI_EVENT_WIN_MODAL_ENTER:
if (rtgui_topwin_modal_enter((struct rtgui_event_win_modal_enter *)event) == RT_EOK)
rtgui_ack(event, RTGUI_STATUS_OK);
else
rtgui_ack(event, RTGUI_STATUS_ERROR);
break;
case RTGUI_EVENT_WIN_ACTIVATE:
if (_act_win_hook) _act_win_hook();
if (rtgui_topwin_activate((struct rtgui_event_win_activate *)event) == RT_EOK)
rtgui_ack(event, RTGUI_STATUS_OK);
else
rtgui_ack(event, RTGUI_STATUS_ERROR);
break;
case RTGUI_EVENT_WIN_DESTROY:
if (rtgui_topwin_remove(((struct rtgui_event_win *)event)->wid) == RT_EOK)
rtgui_ack(event, RTGUI_STATUS_OK);
else
rtgui_ack(event, RTGUI_STATUS_ERROR);
break;
case RTGUI_EVENT_WIN_RESIZE:
rtgui_topwin_resize(((struct rtgui_event_win_resize *)event)->wid,
&(((struct rtgui_event_win_resize *)event)->rect));
break;
case RTGUI_EVENT_SET_WM:
if (rtgui_wm_application != RT_NULL)
{
rtgui_ack(event, RTGUI_STATUS_ERROR);
}
else
{
struct rtgui_event_set_wm *set_wm;
set_wm = (struct rtgui_event_set_wm *) event;
rtgui_wm_application = set_wm->app;
rtgui_ack(event, RTGUI_STATUS_OK);
}
break;
/* other event */
case RTGUI_EVENT_COMMAND:
break;
case RTGUI_EVENT_UPDATE_BEGIN:
#ifdef RTGUI_USING_MOUSE_CURSOR
/* hide cursor */
rtgui_mouse_hide_cursor();
#endif
break;
case RTGUI_EVENT_UPDATE_END:
/* handle screen update */
rtgui_server_handle_update((struct rtgui_event_update_end *)event);
#ifdef RTGUI_USING_MOUSE_CURSOR
/* show cursor */
rtgui_mouse_show_cursor();
#endif
break;
case RTGUI_EVENT_MONITOR_ADD:
/* handle mouse monitor */
rtgui_server_handle_monitor_add((struct rtgui_event_monitor *)event);
break;
default:
rt_kprintf("RTGUI: wrong event sent to server: %d\n", event->type);
return RT_FALSE;
}
return RT_TRUE;
}
/**
* rtgui server thread's entry
*/
static void rtgui_server_entry(void *parameter)
{
#ifdef _WIN32_NATIVE
/* set the server thread to highest */
HANDLE hCurrentThread = GetCurrentThread();
SetThreadPriority(hCurrentThread, THREAD_PRIORITY_HIGHEST);
#endif
/* create rtgui server application */
rtgui_server_app = rtgui_app_create("rtgui");
if (rtgui_server_app == RT_NULL)
{
rt_kprintf("Create GUI server failed.\n");
return;
}
rtgui_object_set_event_handler(RTGUI_OBJECT(rtgui_server_app),
rtgui_server_event_handler);
/* init mouse and show */
rtgui_mouse_init();
#ifdef RTGUI_USING_MOUSE_CURSOR
rtgui_mouse_show_cursor();
#endif
rtgui_app_run(rtgui_server_app);
rtgui_app_destroy(rtgui_server_app);
rtgui_server_app = RT_NULL;
}
void rtgui_server_post_event(struct rtgui_event *event, rt_size_t size)
{
if (rtgui_server_app != RT_NULL)
rtgui_send(rtgui_server_app, event, size);
else
rt_kprintf("post when server is not running\n");
}
rt_err_t rtgui_server_post_event_sync(struct rtgui_event *event, rt_size_t size)
{
if (rtgui_server_app != RT_NULL)
return rtgui_send_sync(rtgui_server_app, event, size);
else
{
rt_kprintf("post when server is not running\n");
return -RT_ENOSYS;
}
}
struct rtgui_app* rtgui_get_server(void)
{
return rtgui_server_app;
}
RTM_EXPORT(rtgui_get_server);
void rtgui_server_init(void)
{
rt_thread_t tid;
tid = rt_thread_create("rtgui",
rtgui_server_entry, RT_NULL,
RTGUI_SVR_THREAD_STACK_SIZE,
RTGUI_SVR_THREAD_PRIORITY,
RTGUI_SVR_THREAD_TIMESLICE);
/* start rtgui server thread */
if (tid != RT_NULL)
rt_thread_startup(tid);
}

138
components/gui/src/title.c Normal file
View File

@ -0,0 +1,138 @@
/*
* 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/rtgui_system.h>
//#include <rtgui/rtgui_theme.h>
#include <rtgui/widgets/window.h>
#include <rtgui/widgets/title.h>
//#include "../server/mouse.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)
{
RTGUI_WIDGET(wintitle)->flag = RTGUI_WIDGET_FLAG_DEFAULT;
RTGUI_WIDGET_TEXTALIGN(wintitle) = RTGUI_ALIGN_CENTER_VERTICAL;
rtgui_object_set_event_handler(RTGUI_OBJECT(wintitle),
rtgui_wintile_event_handler);
}
static void _rtgui_wintitle_deconstructor(rtgui_wintitle_t *wintitle)
{
}
DEFINE_CLASS_TYPE(wintitle, "wintitle",
RTGUI_PARENT_TYPE(widget),
_rtgui_wintitle_constructor,
_rtgui_wintitle_deconstructor,
sizeof(struct rtgui_wintitle));
rtgui_wintitle_t *rtgui_wintitle_create(struct rtgui_win *window)
{
rtgui_wintitle_t *wintitle;
wintitle = (rtgui_wintitle_t *)rtgui_widget_create(RTGUI_WINTITLE_TYPE);
if (wintitle != RT_NULL)
{
RTGUI_WIDGET(wintitle)->toplevel = window;
}
return wintitle;
}
void rtgui_wintitle_destroy(rtgui_wintitle_t *wintitle)
{
rtgui_widget_destroy(RTGUI_WIDGET(wintitle));
}
rt_bool_t rtgui_wintile_event_handler(struct rtgui_object *obj, rtgui_event_t *eve)
{
struct rtgui_wintitle *wint;
struct rtgui_win *win;
RT_ASSERT(obj);
RT_ASSERT(eve);
wint = RTGUI_WINTITLE(obj);
win = RTGUI_WIDGET(wint)->toplevel;
RT_ASSERT(win);
switch (eve->type)
{
case RTGUI_EVENT_PAINT:
rtgui_theme_draw_win(wint);
return RT_FALSE;
case RTGUI_EVENT_MOUSE_BUTTON: {
struct rtgui_event_mouse *emou = (struct rtgui_event_mouse *)eve;
if (win->style & RTGUI_WIN_STYLE_CLOSEBOX)
{
rtgui_rect_t rect;
/* get close button rect (device value) */
rect.x1 = RTGUI_WIDGET(wint)->extent.x2 - WINTITLE_BORDER_SIZE - WINTITLE_CB_WIDTH - 3;
rect.y1 = RTGUI_WIDGET(wint)->extent.y1 + WINTITLE_BORDER_SIZE + 3;
rect.x2 = rect.x1 + WINTITLE_CB_WIDTH;
rect.y2 = rect.y1 + WINTITLE_CB_HEIGHT;
if (emou->button & RTGUI_MOUSE_BUTTON_LEFT)
{
if (emou->button & RTGUI_MOUSE_BUTTON_DOWN)
{
if (rtgui_rect_contains_point(&rect, emou->x, emou->y) == RT_EOK)
{
win->flag |= RTGUI_WIN_FLAG_CB_PRESSED;
rtgui_theme_draw_win(wint);
}
#ifdef RTGUI_USING_WINMOVE
else
{
rtgui_winrect_set(win);
}
#endif
}
else if (emou->button & RTGUI_MOUSE_BUTTON_UP)
{
if (win->flag & RTGUI_WIN_FLAG_CB_PRESSED &&
rtgui_rect_contains_point(&rect,
emou->x, emou->y) == RT_EOK)
{
rtgui_win_close(win);
return RT_TRUE;
}
win->flag &= ~RTGUI_WIN_FLAG_CB_PRESSED;
rtgui_theme_draw_win(wint);
#ifdef RTGUI_USING_WINMOVE
/* Reset the window movement state machine. */
rtgui_winrect_moved_done(RT_NULL, RT_NULL);
#endif
}
}
}
else if (emou->button & RTGUI_MOUSE_BUTTON_DOWN)
{
#ifdef RTGUI_USING_WINMOVE
rtgui_winrect_set(win);
#endif
}
}
return RT_TRUE;
default:
return rtgui_widget_event_handler(obj, eve);
}
}

1162
components/gui/src/topwin.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,60 @@
/*
* 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/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);
rt_err_t rtgui_topwin_activate(struct rtgui_event_win_activate *event);
rt_err_t rtgui_topwin_activate_topwin(struct rtgui_topwin *win);
/* show a window */
rt_err_t rtgui_topwin_show(struct rtgui_event_win *event);
/* hide a window */
rt_err_t rtgui_topwin_hide(struct rtgui_event_win *event);
/* move a window */
rt_err_t rtgui_topwin_move(struct rtgui_event_win_move *event);
/* resize a window */
void rtgui_topwin_resize(struct rtgui_win *wid, rtgui_rect_t *r);
/* a window is entering modal mode */
rt_err_t rtgui_topwin_modal_enter(struct rtgui_event_win_modal_enter *event);
/* get window at (x, y) */
struct rtgui_topwin *rtgui_topwin_get_wnd(int x, int y);
struct rtgui_topwin *rtgui_topwin_get_wnd_no_modaled(int x, int y);
//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);
/* get the topwin that is currently focused */
struct rtgui_topwin *rtgui_topwin_get_focus(void);
struct rtgui_topwin *rtgui_topwin_get_topmost_window_shown_all(void);
#endif

825
components/gui/src/widget.c Normal file
View File

@ -0,0 +1,825 @@
/*
* File : widget.c
* This file is part of RT-Thread GUI
* COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2009-10-04 Bernard first version
* 2010-06-26 Bernard add user_data to widget structure
* 2013-10-07 Bernard remove the win_check in update_clip.
*/
#include <rtgui/dc_client.h>
#include <rtgui/rtgui_app.h>
#include <rtgui/widgets/widget.h>
#include <rtgui/widgets/window.h>
#include <rtgui/widgets/container.h>
#ifdef RTGUI_USING_NOTEBOOK
#include <rtgui/widgets/notebook.h>
#endif
static void _rtgui_widget_constructor(rtgui_widget_t *widget)
{
if (!widget) return;
/* set widget as shown */
widget->flag = RTGUI_WIDGET_FLAG_SHOWN;
/* init list */
rtgui_list_init(&(widget->sibling));
/* init gc */
widget->gc.foreground = default_foreground;
widget->gc.background = default_background;
widget->gc.font = rtgui_font_default();
widget->gc.textstyle = RTGUI_TEXTSTYLE_NORMAL;
widget->gc.textalign = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_TOP;
widget->align = RTGUI_ALIGN_LEFT | RTGUI_ALIGN_TOP;
/* clear the garbage value of extent and clip */
widget->extent.x1 = widget->extent.y1 = 0;
widget->extent.x2 = widget->extent.y2 = 0;
widget->min_width = widget->min_height = 0;
rtgui_region_init_with_extents(&widget->clip, &widget->extent);
/* set parent and toplevel root */
widget->parent = RT_NULL;
widget->toplevel = RT_NULL;
/* some common event handler */
widget->on_focus_in = RT_NULL;
widget->on_focus_out = RT_NULL;
widget->on_paint = RT_NULL;
/* set default event handler */
rtgui_object_set_event_handler(RTGUI_OBJECT(widget), rtgui_widget_event_handler);
/* init user data private to 0 */
widget->user_data = 0;
/* init clip information */
rtgui_region_init(&(widget->clip));
/* init hardware dc */
rtgui_dc_client_init(widget);
}
/* Destroys the widget */
static void _rtgui_widget_destructor(rtgui_widget_t *widget)
{
if (widget == RT_NULL) return;
if (widget->parent != RT_NULL && RTGUI_IS_CONTAINER(widget->parent))
{
/* remove widget from parent's children list */
rtgui_list_remove(&(RTGUI_CONTAINER(widget->parent)->children), &(widget->sibling));
widget->parent = RT_NULL;
}
/* fini clip region */
rtgui_region_fini(&(widget->clip));
}
DEFINE_CLASS_TYPE(widget, "widget",
RTGUI_PARENT_TYPE(object),
_rtgui_widget_constructor,
_rtgui_widget_destructor,
sizeof(struct rtgui_widget));
RTM_EXPORT(_rtgui_widget);
rtgui_widget_t *rtgui_widget_create(const rtgui_type_t *widget_type)
{
struct rtgui_widget *widget;
widget = RTGUI_WIDGET(rtgui_object_create(widget_type));
return widget;
}
RTM_EXPORT(rtgui_widget_create);
void rtgui_widget_destroy(rtgui_widget_t *widget)
{
rtgui_object_destroy(RTGUI_OBJECT(widget));
}
RTM_EXPORT(rtgui_widget_destroy);
void rtgui_widget_set_rect(rtgui_widget_t *widget, const rtgui_rect_t *rect)
{
int delta_x, delta_y;
if (widget == RT_NULL || rect == RT_NULL) return;
/* update extent rectangle */
widget->extent = *rect;
if (RTGUI_IS_CONTAINER(widget))
{
/* re-do layout */
rtgui_container_layout(RTGUI_CONTAINER(widget));
}
/* reset min width and height */
widget->min_width = rtgui_rect_width(widget->extent);
widget->min_height = rtgui_rect_height(widget->extent);
/* it's not empty, fini it */
if (rtgui_region_not_empty(&(widget->clip)))
{
rtgui_region_fini(&(widget->clip));
}
/* reset clip info */
rtgui_region_init_with_extents(&(widget->clip), rect);
if ((widget->parent != RT_NULL) && (widget->toplevel != RT_NULL))
{
if ((void*)widget->parent == (void*)widget->toplevel)
{
rtgui_win_update_clip(widget->toplevel);
}
else
{
/* update widget clip */
rtgui_widget_update_clip(widget->parent);
}
}
/* move to a logic position if it's a container widget */
if (RTGUI_IS_CONTAINER(widget))
{
delta_x = rect->x1 - widget->extent.x1;
delta_y = rect->y1 - widget->extent.y1;
rtgui_widget_move_to_logic(widget, delta_x, delta_y);
}
}
RTM_EXPORT(rtgui_widget_set_rect);
void rtgui_widget_set_rectangle(rtgui_widget_t *widget, int x, int y, int width, int height)
{
rtgui_rect_t rect;
rect.x1 = x;
rect.y1 = y;
rect.x2 = x + width;
rect.y2 = y + height;
rtgui_widget_set_rect(widget, &rect);
}
RTM_EXPORT(rtgui_widget_set_rectangle);
void rtgui_widget_set_parent(rtgui_widget_t *widget, rtgui_widget_t *parent)
{
/* set parent and toplevel widget */
widget->parent = parent;
}
RTM_EXPORT(rtgui_widget_set_parent);
void rtgui_widget_get_extent(rtgui_widget_t *widget, rtgui_rect_t *rect)
{
RT_ASSERT(widget != RT_NULL);
RT_ASSERT(rect != RT_NULL);
*rect = widget->extent;
}
RTM_EXPORT(rtgui_widget_get_extent);
void rtgui_widget_set_minsize(rtgui_widget_t *widget, int width, int height)
{
RT_ASSERT(widget != RT_NULL);
widget->min_width = width;
widget->min_height = height;
}
RTM_EXPORT(rtgui_widget_set_minsize);
void rtgui_widget_set_minwidth(rtgui_widget_t *widget, int width)
{
RT_ASSERT(widget != RT_NULL);
widget->min_width = width;
}
RTM_EXPORT(rtgui_widget_set_minwidth);
void rtgui_widget_set_minheight(rtgui_widget_t *widget, int height)
{
RT_ASSERT(widget != RT_NULL);
widget->min_height = height;
}
RTM_EXPORT(rtgui_widget_set_minheight);
static void _widget_moveto(struct rtgui_widget* widget, int dx, int dy)
{
struct rtgui_list_node *node;
rtgui_widget_t *child;
rtgui_rect_moveto(&(widget->extent), dx, dy);
/* reset clip info */
rtgui_region_init_with_extents(&(widget->clip), &(widget->extent));
/* move each child */
if (RTGUI_IS_CONTAINER(widget))
{
rtgui_list_foreach(node, &(RTGUI_CONTAINER(widget)->children))
{
child = rtgui_list_entry(node, rtgui_widget_t, sibling);
_widget_moveto(child, dx, dy);
}
}
}
/*
* This function moves widget and its children to a logic point
*/
void rtgui_widget_move_to_logic(rtgui_widget_t *widget, int dx, int dy)
{
rtgui_rect_t rect;
rtgui_widget_t *parent;
if (widget == RT_NULL)
return;
/* give clip of this widget back to parent */
parent = widget->parent;
if (parent != RT_NULL)
{
/* get the parent rect, even if it's a transparent parent. */
rect = parent->clip.extents;
}
/* we should find out the none-transparent parent */
while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) parent = parent->parent;
if (parent != RT_NULL)
{
/* reset clip info */
rtgui_region_init_with_extents(&(widget->clip), &(widget->extent));
rtgui_region_intersect_rect(&(widget->clip), &(widget->clip), &rect);
rtgui_region_intersect_rect(&(widget->clip), &(widget->clip), &(parent->extent));
/* give back the extent */
rtgui_region_union(&(parent->clip), &(parent->clip), &(widget->clip));
}
/* move this widget (and its children if it's a container) to destination point */
_widget_moveto(widget, dx, dy);
/* update this widget */
rtgui_widget_update_clip(widget);
}
RTM_EXPORT(rtgui_widget_move_to_logic);
void rtgui_widget_get_rect(rtgui_widget_t *widget, rtgui_rect_t *rect)
{
RT_ASSERT(widget != RT_NULL);
if (rect != RT_NULL)
{
rect->x1 = rect->y1 = 0;
rect->x2 = widget->extent.x2 - widget->extent.x1;
rect->y2 = widget->extent.y2 - widget->extent.y1;
}
}
RTM_EXPORT(rtgui_widget_get_rect);
/**
* set widget draw style
*/
void rtgui_widget_set_border(rtgui_widget_t *widget, rt_uint32_t style)
{
RT_ASSERT(widget != RT_NULL);
widget->border_style = style;
switch (style)
{
case RTGUI_BORDER_NONE:
widget->border = 0;
break;
case RTGUI_BORDER_SIMPLE:
case RTGUI_BORDER_UP:
case RTGUI_BORDER_DOWN:
widget->border = 1;
break;
case RTGUI_BORDER_STATIC:
case RTGUI_BORDER_RAISE:
case RTGUI_BORDER_SUNKEN:
case RTGUI_BORDER_BOX:
case RTGUI_BORDER_EXTRA:
widget->border = 2;
break;
default:
widget->border = 2;
break;
}
}
RTM_EXPORT(rtgui_widget_set_border);
void rtgui_widget_set_onfocus(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
{
RT_ASSERT(widget != RT_NULL);
widget->on_focus_in = handler;
}
RTM_EXPORT(rtgui_widget_set_onfocus);
void rtgui_widget_set_onunfocus(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
{
RT_ASSERT(widget != RT_NULL);
widget->on_focus_out = handler;
}
RTM_EXPORT(rtgui_widget_set_onunfocus);
void rtgui_widget_set_onpaint(rtgui_widget_t *widget, rtgui_event_handler_ptr handler)
{
RT_ASSERT(widget != RT_NULL);
widget->on_paint = handler;
}
RTM_EXPORT(rtgui_widget_set_onpaint);
/**
* @brief Focuses the widget. The focused widget is the widget which can receive the keyboard events
* @param widget a widget
* @note The widget has to be attached to a toplevel widget, otherwise it will have no effect
*/
void rtgui_widget_focus(rtgui_widget_t *widget)
{
struct rtgui_widget *old_focus;
RT_ASSERT(widget != RT_NULL);
RT_ASSERT(widget->toplevel != RT_NULL);
if (!RTGUI_WIDGET_IS_FOCUSABLE(widget) || !RTGUI_WIDGET_IS_ENABLE(widget))
return;
old_focus = RTGUI_WIN(widget->toplevel)->focused_widget;
if (old_focus == widget)
return; /* it's the same focused widget */
/* unfocused the old widget */
if (old_focus != RT_NULL)
rtgui_widget_unfocus(old_focus);
/* set widget as focused */
widget->flag |= RTGUI_WIDGET_FLAG_FOCUS;
RTGUI_WIN(widget->toplevel)->focused_widget = widget;
/* invoke on focus in call back */
if (widget->on_focus_in != RT_NULL)
widget->on_focus_in(RTGUI_OBJECT(widget), RT_NULL);
}
RTM_EXPORT(rtgui_widget_focus);
/**
* @brief Unfocused the widget
* @param widget a widget
*/
void rtgui_widget_unfocus(rtgui_widget_t *widget)
{
RT_ASSERT(widget != RT_NULL);
if (!widget->toplevel || !RTGUI_WIDGET_IS_FOCUSED(widget))
return;
widget->flag &= ~RTGUI_WIDGET_FLAG_FOCUS;
if (widget->on_focus_out != RT_NULL)
widget->on_focus_out(RTGUI_OBJECT(widget), RT_NULL);
RTGUI_WIN(widget->toplevel)->focused_widget = RT_NULL;
/* Ergodic constituent widget, make child loss of focus */
if (RTGUI_IS_CONTAINER(widget))
{
rtgui_list_t *node;
rtgui_list_foreach(node, &(RTGUI_CONTAINER(widget)->children))
{
rtgui_widget_t *child = rtgui_list_entry(node, rtgui_widget_t, sibling);
if (RTGUI_WIDGET_IS_HIDE(child)) continue;
rtgui_widget_unfocus(child);
}
}
}
RTM_EXPORT(rtgui_widget_unfocus);
void rtgui_widget_point_to_device(rtgui_widget_t *widget, rtgui_point_t *point)
{
RT_ASSERT(widget != RT_NULL);
if (point != RT_NULL)
{
point->x += widget->extent.x1;
point->y += widget->extent.y1;
}
}
RTM_EXPORT(rtgui_widget_point_to_device);
void rtgui_widget_rect_to_device(rtgui_widget_t *widget, rtgui_rect_t *rect)
{
RT_ASSERT(widget != RT_NULL);
if (rect != RT_NULL)
{
rect->x1 += widget->extent.x1;
rect->x2 += widget->extent.x1;
rect->y1 += widget->extent.y1;
rect->y2 += widget->extent.y1;
}
}
RTM_EXPORT(rtgui_widget_rect_to_device);
void rtgui_widget_point_to_logic(rtgui_widget_t *widget, rtgui_point_t *point)
{
RT_ASSERT(widget != RT_NULL);
if (point != RT_NULL)
{
point->x -= widget->extent.x1;
point->y -= widget->extent.y1;
}
}
RTM_EXPORT(rtgui_widget_point_to_logic);
void rtgui_widget_rect_to_logic(rtgui_widget_t *widget, rtgui_rect_t *rect)
{
RT_ASSERT(widget != RT_NULL);
if (rect != RT_NULL)
{
rect->x1 -= widget->extent.x1;
rect->x2 -= widget->extent.x1;
rect->y1 -= widget->extent.y1;
rect->y2 -= widget->extent.y1;
}
}
RTM_EXPORT(rtgui_widget_rect_to_logic);
struct rtgui_win *rtgui_widget_get_toplevel(rtgui_widget_t *widget)
{
rtgui_widget_t *r;
RT_ASSERT(widget != RT_NULL);
if (widget->toplevel)
return widget->toplevel;
rt_kprintf("widget->toplevel not properly set\n");
r = widget;
/* get the toplevel widget */
while (r->parent != RT_NULL)
r = r->parent;
/* set toplevel */
widget->toplevel = RTGUI_WIN(r);
return RTGUI_WIN(r);
}
RTM_EXPORT(rtgui_widget_get_toplevel);
rt_bool_t rtgui_widget_onupdate_toplvl(struct rtgui_object *object, struct rtgui_event *event)
{
struct rtgui_widget *widget;
struct rtgui_event_update_toplvl *eup;
RT_ASSERT(object);
RT_ASSERT(event);
widget = RTGUI_WIDGET(object);
eup = (struct rtgui_event_update_toplvl *)event;
widget->toplevel = eup->toplvl;
return RT_FALSE;
}
RTM_EXPORT(rtgui_widget_onupdate_toplvl);
rt_bool_t rtgui_widget_onpaint(struct rtgui_object *object, struct rtgui_event *event)
{
if (RTGUI_WIDGET(object)->on_paint)
return RTGUI_WIDGET(object)->on_paint(object, event);
else
return RT_FALSE;
}
RTM_EXPORT(rtgui_widget_onpaint);
rt_bool_t rtgui_widget_event_handler(struct rtgui_object *object, rtgui_event_t *event)
{
RTGUI_WIDGET_EVENT_HANDLER_PREPARE;
switch (event->type)
{
case RTGUI_EVENT_PAINT:
return rtgui_widget_onpaint(object, event);
case RTGUI_EVENT_SHOW:
return rtgui_widget_onshow(object, event);
case RTGUI_EVENT_HIDE:
return rtgui_widget_onhide(object, event);
case RTGUI_EVENT_UPDATE_TOPLVL:
return rtgui_widget_onupdate_toplvl(object, event);
default:
break;
}
return rtgui_object_event_handler(object, event);
}
RTM_EXPORT(rtgui_widget_event_handler);
/*
* This function updates the clip info of widget
*/
void rtgui_widget_update_clip(rtgui_widget_t *widget)
{
rtgui_rect_t rect;
struct rtgui_list_node *node;
rtgui_widget_t *parent;
/* no widget or widget is hide, no update clip */
if (widget == RT_NULL || RTGUI_WIDGET_IS_HIDE(widget) || widget->parent == RT_NULL)
return;
parent = widget->parent;
rect = parent->clip.extents;
/* reset clip to extent */
rtgui_region_reset(&(widget->clip), &(widget->extent));
/* limit widget extent in parent extent */
rtgui_region_intersect_rect(&(widget->clip), &(widget->clip), &rect);
/* get the no transparent parent */
while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT)
{
parent = parent->parent;
}
if (parent != RT_NULL)
{
/* give my clip back to parent */
rtgui_region_union(&(parent->clip), &(parent->clip), &(widget->clip));
/* subtract widget clip in parent clip */
if (!(widget->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) && RTGUI_IS_CONTAINER(parent))
{
rtgui_region_subtract_rect(&(parent->clip), &(parent->clip), &(widget->extent));
}
}
/*
* note: since the layout widget introduction, the sibling widget should not intersect.
*/
/* if it's a container object, update the clip info of children */
if (RTGUI_IS_CONTAINER(widget))
{
rtgui_widget_t *child;
rtgui_list_foreach(node, &(RTGUI_CONTAINER(widget)->children))
{
child = rtgui_list_entry(node, rtgui_widget_t, sibling);
rtgui_widget_update_clip(child);
}
}
}
RTM_EXPORT(rtgui_widget_update_clip);
void rtgui_widget_show(struct rtgui_widget *widget)
{
struct rtgui_event_show eshow;
RT_ASSERT(widget != RT_NULL);
if (!RTGUI_WIDGET_IS_HIDE(widget))
return;
RTGUI_WIDGET_UNHIDE(widget);
if (widget->toplevel != RT_NULL)
{
RTGUI_EVENT_SHOW_INIT(&eshow);
if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
{
RTGUI_OBJECT(widget)->event_handler(
RTGUI_OBJECT(widget),
&eshow);
}
}
}
RTM_EXPORT(rtgui_widget_show);
void rtgui_widget_hide(struct rtgui_widget *widget)
{
struct rtgui_event_hide ehide;
RT_ASSERT(widget != RT_NULL);
if (RTGUI_WIDGET_IS_HIDE(widget))
return;
RTGUI_WIDGET_HIDE(widget);
if (widget->toplevel != RT_NULL)
{
RTGUI_EVENT_HIDE_INIT(&ehide);
if (RTGUI_OBJECT(widget)->event_handler != RT_NULL)
{
RTGUI_OBJECT(widget)->event_handler(
RTGUI_OBJECT(widget),
&ehide);
}
}
}
RTM_EXPORT(rtgui_widget_hide);
rt_bool_t rtgui_widget_onshow(struct rtgui_object *object, struct rtgui_event *event)
{
struct rtgui_widget *widget = RTGUI_WIDGET(object);
if (RTGUI_WIDGET_IS_HIDE(object)) return RT_FALSE;
if (widget->parent != RT_NULL)
{
rtgui_widget_clip_parent(widget);
}
return RT_FALSE;
}
RTM_EXPORT(rtgui_widget_onshow);
rt_bool_t rtgui_widget_onhide(struct rtgui_object *object, struct rtgui_event *event)
{
struct rtgui_widget *widget = RTGUI_WIDGET(object);
if (RTGUI_WIDGET_IS_HIDE(object))
return RT_FALSE;
if (widget->parent != RT_NULL)
{
rtgui_widget_clip_return(widget);
}
return RT_FALSE;
}
RTM_EXPORT(rtgui_widget_onhide);
rtgui_color_t rtgui_widget_get_parent_foreground(rtgui_widget_t *widget)
{
rtgui_widget_t *parent;
/* get parent widget */
parent = widget->parent;
if (parent == RT_NULL)
return RTGUI_WIDGET_FOREGROUND(widget);
while (parent->parent != RT_NULL && (RTGUI_WIDGET_FLAG(parent) & RTGUI_WIDGET_FLAG_TRANSPARENT))
parent = parent->parent;
/* get parent's color */
return RTGUI_WIDGET_FOREGROUND(parent);
}
RTM_EXPORT(rtgui_widget_get_parent_foreground);
rtgui_color_t rtgui_widget_get_parent_background(rtgui_widget_t *widget)
{
rtgui_widget_t *parent;
/* get parent widget */
parent = widget->parent;
if (parent == RT_NULL)
return RTGUI_WIDGET_BACKGROUND(widget);
while (parent->parent != RT_NULL && (RTGUI_WIDGET_FLAG(parent) & RTGUI_WIDGET_FLAG_TRANSPARENT))
parent = parent->parent;
/* get parent's color */
return RTGUI_WIDGET_BACKGROUND(parent);
}
RTM_EXPORT(rtgui_widget_get_parent_background);
void rtgui_widget_clip_parent(rtgui_widget_t *widget)
{
rtgui_widget_t *parent;
parent = widget->parent;
/* get the no transparent parent */
while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) parent = parent->parent;
/* clip the widget extern from parent */
if (parent != RT_NULL) rtgui_region_subtract(&(parent->clip), &(parent->clip), &(widget->clip));
}
RTM_EXPORT(rtgui_widget_clip_parent);
void rtgui_widget_clip_return(rtgui_widget_t *widget)
{
rtgui_widget_t *parent;
parent = widget->parent;
/* get the no transparent parent */
while (parent != RT_NULL && parent->flag & RTGUI_WIDGET_FLAG_TRANSPARENT) parent = parent->parent;
/* give clip back to parent */
if (parent != RT_NULL) rtgui_region_union(&(parent->clip), &(parent->clip), &(widget->clip));
}
RTM_EXPORT(rtgui_widget_clip_return);
void rtgui_widget_update(rtgui_widget_t *widget)
{
struct rtgui_event_paint paint;
RTGUI_EVENT_PAINT_INIT(&paint);
paint.wid = RT_NULL;
RT_ASSERT(widget != RT_NULL);
if (RTGUI_OBJECT(widget)->event_handler != RT_NULL &&
!(RTGUI_WIDGET_FLAG(widget) & RTGUI_WIDGET_FLAG_IN_ANIM))
{
RTGUI_OBJECT(widget)->event_handler(RTGUI_OBJECT(widget),
&paint.parent);
}
}
RTM_EXPORT(rtgui_widget_update);
rtgui_widget_t *rtgui_widget_get_next_sibling(rtgui_widget_t *widget)
{
rtgui_widget_t *sibling = RT_NULL;
if (widget->sibling.next != RT_NULL)
{
sibling = rtgui_list_entry(widget->sibling.next, rtgui_widget_t, sibling);
}
return sibling;
}
RTM_EXPORT(rtgui_widget_get_next_sibling);
rtgui_widget_t *rtgui_widget_get_prev_sibling(rtgui_widget_t *widget)
{
struct rtgui_list_node *node;
rtgui_widget_t *sibling, *parent;
node = RT_NULL;
sibling = RT_NULL;
parent = widget->parent;
if (parent != RT_NULL)
{
rtgui_list_foreach(node, &(RTGUI_CONTAINER(parent)->children))
{
if (node->next == &(widget->sibling))
break;
}
}
if (node != RT_NULL)
sibling = rtgui_list_entry(node, rtgui_widget_t, sibling);
return sibling;
}
RTM_EXPORT(rtgui_widget_get_prev_sibling);
rt_bool_t rtgui_widget_is_in_animation(rtgui_widget_t *widget)
{
/* check the visible of widget */
while (widget != RT_NULL)
{
if (widget->flag & RTGUI_WIDGET_FLAG_IN_ANIM)
{
return RT_TRUE;
}
widget = widget->parent;
}
return RT_FALSE;
}
RTM_EXPORT(rtgui_widget_is_in_animation);
#ifdef RTGUI_WIDGET_DEBUG
#include <rtgui/widgets/label.h>
#include <rtgui/widgets/button.h>
void rtgui_widget_dump(rtgui_widget_t *widget)
{
struct rtgui_object *obj;
obj = RTGUI_OBJECT(widget);
rt_kprintf("widget type: %s ", obj->type->name);
if (RTGUI_IS_WIN(widget) == RT_TRUE)
rt_kprintf(":%s ", RTGUI_WIN(widget)->title);
else if ((RTGUI_IS_LABEL(widget) == RT_TRUE) || (RTGUI_IS_BUTTON(widget) == RT_TRUE))
rt_kprintf(":%s ", RTGUI_LABEL(widget)->text);
rt_kprintf("extent(%d, %d) - (%d, %d)\n", widget->extent.x1,
widget->extent.y1, widget->extent.x2, widget->extent.y2);
// rtgui_region_dump(&(widget->clip));
}
#endif

1105
components/gui/src/window.c Normal file

File diff suppressed because it is too large Load Diff