與裸機做斗爭真是其樂無窮啊~~ 終究是能畫點、線、矩形、圓、填充矩形、字符、漢字、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; }