babyos (七)—— 简易图形库

注:以下代码为原创,若发现bug,万望指出,若有问题,欢迎交流,转载请指明出处。若能有助于一二访客,幸甚。

与裸机做斗争真是其乐无穷啊~~

终究是能画点、线、矩形、圆、填充矩形、字符、汉字、LOGO了。且做了目前我能做到的最好的代码组织。下一步就是用这些函数实现一个简单的界面。




整理绘图功能的函数,组织成一个简易的图形库

1.绘制点直线、圆、矩形、填充矩形的函数放到graphic.c中

/*************************************************************************
	> File:		graphics.c
	> Describe:      实现基本绘图功能
	> Author:	       孤舟钓客
	> Mail:		guzhoudiaoke@126.com 
	> Time:		2013年01月02日 星期三 22时21分31秒
 ************************************************************************/

#include <graphics.h>
#include <kernel.h>
#include <math.h>

static video_info_t* p_video_info = (video_info_t*)(VIDEO_INFO_ADDR);
static u32 screen_cx = 0;
static u32 screen_cy = 0;

static color8 current_color = 0;
static u32 current_x = 0;
static u32 current_y = 0;

static u8* p_vram_base;

BOOL init_video()
{
	screen_cx = p_video_info->resolution_cx;
	screen_cy = p_video_info->resolution_cy;

	current_x = 0;
	current_y = 0;
	current_color = 0;

	p_vram_base = p_video_info->p_vram_base;

	return TRUE;
}

static BOOL set_color8(color8 color)
{
	current_color = color;
	return TRUE;
}

BOOL set_pixel(s32 x, s32 y)
{
	/* 超出屏幕范围 */
	if (x < 0 || y < 0 || (u32)x >= screen_cx || (u32)y >= screen_cy)
		return FALSE;
	
	*(p_vram_base + y*screen_cx + x) = current_color;

	return TRUE;
}

/* Bresenham line algorithm */
static BOOL bresenham_line(s32 start_x, s32 start_y, s32 end_x, s32 end_y)
{
	s32 dx, dy, x, y, p, k;

	dx = abs(end_x - start_x);
	dy = abs(end_y - start_y);
	k  = (end_x-start_x) * (end_y-start_y);

	if (dx >= dy)
	{
		p = 2*dy - dx;
		if (start_x < end_x)
		{
			x = start_x;
			y = start_y;
		}
		else
		{
			y = end_y;
			x = end_x;
			end_x = start_x;
		}

		while (x < end_x)
		{
			set_pixel(x, y);
			++x;

			if (p < 0)
				p += 2*dy;
			else
			{
				if (k > 0) ++y;
				else --y;

				p += 2*dy - 2*dx;
			}
		}
	}
	else
	{
		p = 2*dx - dy;
		if (start_y < end_y)
		{
			x = start_x;
			y = start_y;
		}
		else
		{
			y = end_y;
			x = end_x;
			end_y = start_y;
		}

		while (y < end_y)
		{
			set_pixel(x, y);
			++y;

			if (p < 0)
				p += 2*dx;
			else
			{
				if (k > 0) ++x;
				else --x;

				p += 2*dx - 2*dy;
			}
		}
	}

	return TRUE;
}

BOOL draw_line(s32 start_x, s32 start_y, s32 end_x, s32 end_y)
{
	return bresenham_line(start_x, start_y, end_x, end_y);
}

BOOL draw_circle(s32 center_x, s32 center_y, u32 radius)
{
	s32 x, y, p;
	x = 0, y = radius, p = 1-radius;

	while (x < y)
	{
		set_pixel(center_x + x, center_y + y);
		set_pixel(center_x - x, center_y + y);
		set_pixel(center_x - x, center_y - y);
		set_pixel(center_x + x, center_y - y);
		set_pixel(center_x + y, center_y + x);
		set_pixel(center_x - y, center_y + x);
		set_pixel(center_x - y, center_y - x);
		set_pixel(center_x + y, center_y - x);

		x++;
		if (p < 0) p += 2*x + 1;
		else
		{
			y--;
			p += 2*x - 2*y + 1;
		}
	}

	return TRUE;
}

BOOL draw_rectangle(s32 left, s32 top, u32 width, u32 height)
{
	u8* p_vram1;
	u8* p_vram2;
	s32 right, bottom, x, y;
	
	right = left + width;
	bottom = top + height;

	if (left < 0) left = 0;
	if (top  < 0) top  = 0;
	if ((u32)left >= screen_cx || (u32)top >= screen_cy)
		return FALSE;

	if (right < 0 || bottom < 0)
		return FALSE;

	if ((u32)right  > screen_cx) right  = screen_cx;
	if ((u32)bottom > screen_cy) bottom = screen_cy;

	p_vram1 = p_vram_base + top*screen_cx + left;
	p_vram2 = p_vram_base + top*screen_cx + right;
	for (y = top; y < bottom; y++) 
	{
		*p_vram1 = current_color;
		*p_vram2 = current_color;

		p_vram1 += screen_cx;
		p_vram2 += screen_cx;
	}

	p_vram1 = p_vram_base + top*screen_cx + left;
	p_vram2 = p_vram_base + bottom*screen_cx + left;
	for (x = left; x < right; x++)
	{
		*(p_vram1++) = current_color;
		*(p_vram2++) = current_color;
	}
	
	return TRUE;
}

BOOL fill_rectangle(s32 left, s32 top, u32 width, u32 height)
{
	u8* p_vram;
	s32 right, bottom, x, y;
	
	right	= left + width;
	bottom	= top  + height;

	/* 超出边界,截取在屏幕中的部分 */
	if (left < 0) left = 0;
	if (top  < 0)  top = 0;

	/* 完全在屏幕外 */
	if ((u32)left >= screen_cx || (u32)top >= screen_cy)
		return FALSE;

	/* 完全在屏幕外 */
	if (right < 0 || bottom < 0)
		return FALSE;

	/* 超出边界,截取在屏幕中的部分 */
	if ((u32)right  > screen_cx)  right = screen_cx;
	if ((u32)bottom > screen_cy) bottom = screen_cy;

	p_vram = p_vram_base + top*screen_cx;

	for (y = top; y < bottom; y++) 
	{
		for (x = left; x < right; x++)
			p_vram[x] = current_color;
		
		p_vram += screen_cx;
	}

	return TRUE;
}


BOOL set_color(color8 color)
{
	return set_color8(color);
}

2.绘制字符和汉字的函数放到font.c中

/*************************************************************************
	> File:		font.c
	> Author:	孤舟钓客
	> Mail:		guzhoudiaoke@126.com 
	> Time:		2013年01月03日 星期四 16时40分52秒
 ************************************************************************/

#include <font.h>
#include <kernel.h>
#include <graphics.h>

static u8* p_font_asc16_base = (u8*)(FONT_ASC_ADDR);
static u8* p_font_hzk16_base = (u8*)(FONT_HZK_ADDR);

static BOOL draw_asc16(char ch, s32 left, s32 top)
{
	u8* p_asc;
	s32 x, y;

	p_asc = p_font_asc16_base + ch * FONT_ASC16_SIZE;
	for (y = 0; y < FONT_ASC16_HEIGHT; y++)
	{
		u8 test_bit = 1 << 7;
		
		for (x = 0; x < FONT_ASC16_WIDTH; x++)
		{
			if (*p_asc & test_bit)
				set_pixel(left+x, top+y);

			test_bit >>= 1;
		}
		
		p_asc++;
	}

	return TRUE;
}

static BOOL draw_hzk16(char ch[3], s32 left, s32 top)
{
	u8 qu_no, wei_no;
	u32 offset;
	s32 y, x;
	u8* p_hzk;

	qu_no  = (u8)ch[0] - 0xa0;
	wei_no = (u8)ch[1] - 0xa0;
	offset= (94*(qu_no-1) + (wei_no-1)) * FONT_HZK16_SIZE;
	p_hzk = p_font_hzk16_base + offset;

	for (y = 0; y < FONT_HZK16_HEIGHT; y++)
	{
		u8 test_bit = 1 << 7;
		
		for (x = 0; x < FONT_HZK16_WIDTH; x++)
		{
			if (*(p_hzk + (x & 8 ? 1 : 0)) & test_bit)
				set_pixel(left+x, top+y);	

			if ((test_bit >>= 1) == 0)
				test_bit = 1 << 7;
		}
		p_hzk += 2;
	}

	return TRUE;
}

/* 实现一个简陋的打印字符串程序 */
static BOOL draw_string16(char* str, s32 left, s32 top)
{
	char* p = str;
	char hzk[3];
	s32 cur_x, cur_y;

	hzk[2] = '\0';
	cur_x = left;
	cur_y = top;

	while (*p != '\0')
	{
		if ((*p & 0x80) == 0)
		{
			draw_asc16(*p, cur_x, cur_y);
			cur_x += 8;
			p++;
		}
		else
		{
			hzk[0] = *p++;
			hzk[1] = *p++;
			draw_hzk16(hzk, cur_x, cur_y);
			cur_x += 16;
		}
	}

	return TRUE;
}

BOOL draw_asc(char ch, int left, int top)
{
	return draw_asc16(ch, left, top);
}

BOOL draw_hzk(char ch[3], int left, int top)
{
	return draw_hzk16(ch, left, top);
}

BOOL draw_string(char *str, int left, int top)
{
	return draw_string16(str, left, top);
}

3.绘制logo的函数放到logo.c中

/*************************************************************************
	> File:		logo.c
	> Describe: 显示那个可爱的小篆字体的LOGO	
	> Author:	孤舟钓客
	> Mail:		guzhoudiaoke@126.com 
	> Time:		2013年01月03日 星期四 17时05分11秒
 ************************************************************************/

#include <logo.h>
#include <kernel.h>
#include <graphics.h>


static u8* p_logo_base = (u8*)(LOGO_ADDR);
static u32 logo_cx = (u32)(LOGO_CX);
static u32 logo_cy = (u32)(LOGO_CY);


BOOL draw_logo(s32 left, s32 top)
{
	u32 y, x;
	u8* p_logo = p_logo_base;

	for (y = 0; y < logo_cy; y++)
	{
		for (x = 0; x < logo_cx; x++)
		{
			if (p_logo[x] != 0xff)
				set_pixel(left+x, top+y);
		}
		p_logo += logo_cx;
	}

	return TRUE;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值