與裸機做斗爭真是其樂無窮啊~~
終究是能畫點、線、矩形、圓、填充矩形、字符、漢字、LOGO了。且做了目前我能做到的最好的代碼組織。下一步就是用這些函數實現一個簡單的界面。
整理繪圖功能的函數,組織成一個簡易的圖形庫
1.繪制點直線、圓、矩形、填充矩形的函數放到graphic.c中
[cpp]
/*************************************************************************
> File: graphics.c
> Describe: 實現基本繪圖功能
> Author: 孤舟釣客
> Mail: [email protected]
> 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中
[cpp]
/*************************************************************************
> File: font.c
> Author: 孤舟釣客
> Mail: [email protected]
> 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中
[cpp]
/*************************************************************************
> File: logo.c
> Describe: 顯示那個可愛的小篆字體的LOGO
> Author: 孤舟釣客
> Mail: [email protected]
> 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;
}