font.c 5.5 KB
Newer Older
B
bernard.xiong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * File      : font.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2009-10-16     Bernard      first version
 */
#include <rtgui/font.h>
#include <rtgui/dc.h>

static rtgui_list_t _rtgui_font_list;
static struct rtgui_font* rtgui_default_font;

extern struct rtgui_font rtgui_font_asc16;
B
bernard.xiong 已提交
21
extern struct rtgui_font rtgui_font_arial16;
B
bernard.xiong 已提交
22
extern struct rtgui_font rtgui_font_asc12;
B
bernard.xiong 已提交
23
extern struct rtgui_font rtgui_font_arial12;
B
bernard.xiong 已提交
24 25 26 27 28 29 30 31 32 33
#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 */
34
	rtgui_default_font = RT_NULL;
B
bernard.xiong 已提交
35 36 37 38 39 40

#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
41 42 43
#endif

#ifdef RTGUI_USING_FONT12
B
bernard.xiong 已提交
44 45 46 47
	rtgui_font_system_add_font(&rtgui_font_asc12);
#ifdef RTGUI_USING_FONTHZ
	rtgui_font_system_add_font(&rtgui_font_hz12);
#endif
48
#endif
B
bernard.xiong 已提交
49

50
#ifdef RTGUI_USING_FONT12
B
bernard.xiong 已提交
51 52
	if (rtgui_default_font == RT_NULL)
		rtgui_font_set_defaut(&rtgui_font_asc12);
53 54
#endif
#ifdef RTGUI_USING_FONT16
B
bernard.xiong 已提交
55 56
	if (rtgui_default_font == RT_NULL)
		rtgui_font_set_defaut(&rtgui_font_asc16);
57
#endif
B
bernard.xiong 已提交
58 59 60 61 62 63
}

void rtgui_font_system_add_font(struct rtgui_font* font)
{
	rtgui_list_init(&(font->list));
	rtgui_list_append(&_rtgui_font_list, &(font->list));
64 65 66 67 68 69 70 71

	/* 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);
B
bernard.xiong 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
}

void rtgui_font_system_remove_font(struct rtgui_font* font)
{
	rtgui_list_remove(&_rtgui_font_list, &(font->list));
}

struct rtgui_font* rtgui_font_default()
{
	return rtgui_default_font;
}

void rtgui_font_set_defaut(struct rtgui_font* font)
{
	rtgui_default_font = font;
}

struct rtgui_font* rtgui_font_refer(const rt_uint8_t* family, rt_uint16_t height)
{
	/* search font */
	struct rtgui_list_node* node;
	struct rtgui_font* font;

	rtgui_list_foreach(node, &_rtgui_font_list)
	{
		font = rtgui_list_entry(node, struct rtgui_font, list);
		if ((rt_strncmp((const char*)font->family, (const char*)family, RTGUI_NAME_MAX) == 0) &&
			font->height == height)
		{
			font->refer_count ++;
			return font;
		}
	}

	return RT_NULL;
}

void rtgui_font_derefer(struct rtgui_font* font)
{
	RT_ASSERT(font != RT_NULL);

	font->refer_count --;

	/* no refer, remove font */
	if (font->refer_count == 0)
	{
		rtgui_font_system_remove_font(font);
	}
}

/* draw a text */
123
void rtgui_font_draw(struct rtgui_font* font, struct rtgui_dc* dc, const char* text, rt_ubase_t len, struct rtgui_rect* rect)
B
bernard.xiong 已提交
124 125 126 127 128 129 130 131 132 133
{
	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);
	}
}

134
int rtgui_font_get_string_width(struct rtgui_font* font, const char* text)
B
bernard.xiong 已提交
135 136 137 138 139 140 141 142 143
{
	rtgui_rect_t rect;

	/* get metrics */
	rtgui_font_get_metrics(font, text, &rect);

	return rect.x2 - rect.x1;
}

144
void rtgui_font_get_metrics(struct rtgui_font* font, const char* text, rtgui_rect_t* rect)
B
bernard.xiong 已提交
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
{
	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));
	}
}

160 161
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);
B
bernard.xiong 已提交
162 163 164 165 166 167 168 169 170 171 172
struct rtgui_font_engine bmp_font_engine =
{
	RT_NULL,
	RT_NULL,
	rtgui_bitmap_font_draw_text,
	rtgui_bitmap_font_get_metrics
};

void rtgui_bitmap_font_draw_char(struct rtgui_font_bitmap* font, struct rtgui_dc* dc, const char ch,
	rtgui_rect_t* rect)
{
B
bernard.xiong 已提交
173
	const rt_uint8_t* font_ptr;
K
kyle.hu.gz 已提交
174 175 176 177 178
	rt_uint16_t x, y, h;
	register rt_base_t i, j, k, word_bytes;

	/* check first and last char */
	if (ch < font->first_char || ch > font->last_char) return;
B
bernard.xiong 已提交
179 180 181

	x = rect->x1;
	y = rect->y1;
K
kyle.hu.gz 已提交
182
	word_bytes = (((font->width - 1) / 8) + 1);
B
bernard.xiong 已提交
183

K
kyle.hu.gz 已提交
184
	font_ptr = font->bmp + (ch - font->first_char) * word_bytes * font->height;
B
bernard.xiong 已提交
185

K
kyle.hu.gz 已提交
186
	h = (font->height + y > rect->y2) ? rect->y2 - rect->y1 : font->height;
B
bernard.xiong 已提交
187

K
kyle.hu.gz 已提交
188
	for (i = 0; i < h; i++)
B
bernard.xiong 已提交
189
	{
K
kyle.hu.gz 已提交
190
		for (j = 0; j < word_bytes; j++)
B
bernard.xiong 已提交
191
		{
K
kyle.hu.gz 已提交
192
			for (k = 0; k < 8; k++)
B
bernard.xiong 已提交
193
			{
K
kyle.hu.gz 已提交
194 195 196 197 198
				if (((font_ptr[i * word_bytes + j] >> (7 - k)) & 0x01) != 0)
				{
					/* draw a pixel */
					rtgui_dc_draw_point(dc, k + 8 * j + x, i + y);
				}
B
bernard.xiong 已提交
199 200 201 202 203
			}
		}
	}
}

204
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)
B
bernard.xiong 已提交
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
{
	struct rtgui_font_bitmap* bmp_font = (struct rtgui_font_bitmap*)(font->data);

	RT_ASSERT(bmp_font != RT_NULL);

	while (len-- && rect->x1 < rect->x2)
	{
		rtgui_bitmap_font_draw_char(bmp_font, dc, *text, rect);

		/* move x to next character */
		rect->x1 += bmp_font->width;
		text ++;
	}
}

220
static void rtgui_bitmap_font_get_metrics(struct rtgui_font* font, const char* text, rtgui_rect_t* rect)
B
bernard.xiong 已提交
221 222 223 224 225 226 227 228 229 230
{
	struct rtgui_font_bitmap* bmp_font = (struct rtgui_font_bitmap*)(font->data);

	RT_ASSERT(bmp_font != RT_NULL);

	/* set metrics rect */
	rect->x1 = rect->y1 = 0;
	rect->x2 = bmp_font->width * (rt_int16_t)rt_strlen((const char*)text);
	rect->y2 = bmp_font->height;
}