426 lines
9.9 KiB
C
426 lines
9.9 KiB
C
//游戏引擎文字显示库
|
||
|
||
#include "stdio.h"
|
||
|
||
#include "sys.h"
|
||
#include "lcd.h"
|
||
#include "GameEngine.h"
|
||
|
||
#include "GE_Font.h"
|
||
|
||
/**************************************** 私有定义 ****************************************/
|
||
|
||
#define GE_Font_GetACSIIDataSize(__font_size__) ((__font_size__ / 8 + ((__font_size__ % 8) ? 1 : 0)) * (__font_size__ / 2))
|
||
#define GE_Font_GetGBKDataSize(__font_size__) ((__font_size__ / 8 + ((__font_size__ % 8) ? 1 : 0)) * (__font_size__))
|
||
|
||
/*****************************************************************************************/
|
||
|
||
/**************************************** 私有函数 ****************************************/
|
||
|
||
uint8_t GE_Font_GetACSII(uint8_t *font, uint8_t *ch, uint8_t font_size);
|
||
uint8_t GE_Font_PrintACSII(uint16_t x, uint16_t y, uint8_t *ch, uint8_t font_size, uint16_t font_color, uint16_t back_color, uint8_t is_transparent);
|
||
|
||
uint8_t GE_Font_GetGBK(uint8_t *font, uint8_t *ch, uint8_t font_size);
|
||
uint8_t GE_Font_PrintGBK(uint16_t x, uint16_t y, uint8_t *ch, uint8_t font_size, uint16_t font_color, uint16_t back_color, uint8_t is_transparent);
|
||
|
||
/*****************************************************************************************/
|
||
|
||
_ge_font_print_set ge_font_print_set;
|
||
|
||
/**
|
||
* @brief 初始化 GE_Font
|
||
*/
|
||
void GE_Font_Init(void)
|
||
{
|
||
//绘制汉字设置
|
||
ge_font_print_set.font_size = FONT_12;
|
||
ge_font_print_set.font_color = BLACK;
|
||
ge_font_print_set.back_color = WHITE;
|
||
ge_font_print_set.is_transparent = TRUE;
|
||
}
|
||
|
||
/**
|
||
* @brief 从字库读 ACSII 字符。说明略
|
||
*/
|
||
uint8_t GE_Font_GetACSII(uint8_t *font, uint8_t *ch, uint8_t font_size)
|
||
{
|
||
uint32_t addr, offset;
|
||
uint16_t data_size = GE_Font_GetACSIIDataSize(font_size);
|
||
|
||
offset = (uint32_t)data_size * (*ch);
|
||
|
||
switch (font_size)
|
||
{
|
||
case FONT_12:
|
||
addr = offset + ADDR_ASCII12;
|
||
break;
|
||
case FONT_16:
|
||
addr = offset + ADDR_ASCII16;
|
||
break;
|
||
case FONT_24:
|
||
addr = offset + ADDR_ASCII24;
|
||
break;
|
||
case FONT_32:
|
||
addr = offset + ADDR_ASCII32;
|
||
break;
|
||
case FONT_48:
|
||
addr = offset + ADDR_ASCII48;
|
||
break;
|
||
case FONT_64:
|
||
addr = offset + ADDR_ASCII64;
|
||
break;
|
||
|
||
default:
|
||
return 1;
|
||
}
|
||
|
||
LCD_Font_ReadAddr(font, addr, data_size); //从字库读取字符到 font
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 显示 ACSII 字符。说明略
|
||
*/
|
||
uint8_t GE_Font_PrintACSII(uint16_t x, uint16_t y, uint8_t *ch, uint8_t font_size, uint16_t font_color, uint16_t back_color, uint8_t is_transparent)
|
||
{
|
||
uint16_t data_size = GE_Font_GetACSIIDataSize(font_size);
|
||
|
||
//从字库获取字符
|
||
uint8_t font[256]; //使用 FONT_64 时需要 256 大小
|
||
if (GE_Font_GetACSII(font, ch, font_size) != 0)
|
||
return 1;
|
||
|
||
uint8_t temp8;
|
||
uint16_t x0 = x, y0 = y;
|
||
|
||
//循环纵向输出
|
||
for (uint16_t i = 0; i < data_size; i++)
|
||
{
|
||
temp8 = font[i];
|
||
|
||
for (uint16_t j = 0; j < 8; j++)
|
||
{
|
||
if (temp8 & 0x80)
|
||
GE_Draw_Point(x, y, font_color);
|
||
else if (is_transparent == FALSE) //不透明时使用背景色填充
|
||
GE_Draw_Point(x, y, back_color);
|
||
|
||
temp8 <<= 1;
|
||
|
||
y++;
|
||
if ((y - y0) == font_size)
|
||
{
|
||
y = y0;
|
||
x++;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 从字库读 GBK 字符。说明略
|
||
*/
|
||
uint8_t GE_Font_GetGBK(uint8_t *font, uint8_t *ch, uint8_t font_size)
|
||
{
|
||
if (font_size >= FONT_48)
|
||
return 1;
|
||
|
||
uint32_t addr, offset;
|
||
uint16_t data_size = GE_Font_GetGBKDataSize(font_size);
|
||
|
||
uint8_t qh = *ch;
|
||
uint8_t ql = *(++ch);
|
||
|
||
if (qh < 0x81 || ql < 0x40 || ql == 0xff || qh == 0xff) //非法访问
|
||
return 1;
|
||
|
||
if (ql < 0x7f)
|
||
ql -= 0x40;
|
||
else
|
||
ql -= 0x41;
|
||
|
||
qh -= 0x81;
|
||
|
||
offset = (uint32_t)data_size * (190 * (uint32_t)qh + ql);
|
||
|
||
switch (font_size)
|
||
{
|
||
case FONT_12:
|
||
addr = offset + ADDR_GBK12;
|
||
break;
|
||
case FONT_16:
|
||
addr = offset + ADDR_GBK16;
|
||
break;
|
||
case FONT_24:
|
||
addr = offset + ADDR_GBK24;
|
||
break;
|
||
case FONT_32:
|
||
addr = offset + ADDR_GBK32;
|
||
break;
|
||
|
||
default:
|
||
return 1;
|
||
}
|
||
|
||
LCD_Font_ReadAddr(font, addr, data_size); //从字库读取字符到 font
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 显示 GBK 字符。说明略
|
||
*/
|
||
uint8_t GE_Font_PrintGBK(uint16_t x, uint16_t y, uint8_t *ch, uint8_t font_size, uint16_t font_color, uint16_t back_color, uint8_t is_transparent)
|
||
{
|
||
uint16_t data_size = GE_Font_GetGBKDataSize(font_size);
|
||
|
||
//从字库获取字符
|
||
uint8_t font[128]; //使用 FONT_32 时需要 128 大小
|
||
if (GE_Font_GetGBK(font, ch, font_size) != 0)
|
||
return 1;
|
||
|
||
uint8_t temp8;
|
||
uint16_t x0 = x, y0 = y;
|
||
|
||
//循环纵向输出
|
||
for (uint16_t i = 0; i < data_size; i++)
|
||
{
|
||
temp8 = font[i];
|
||
|
||
for (uint16_t j = 0; j < 8; j++)
|
||
{
|
||
if (temp8 & 0x80)
|
||
GE_Draw_Point(x, y, font_color);
|
||
else if (is_transparent == FALSE) //不透明时使用背景色填充
|
||
GE_Draw_Point(x, y, back_color);
|
||
|
||
temp8 <<= 1;
|
||
|
||
y++;
|
||
if ((y - y0) == font_size)
|
||
{
|
||
y = y0;
|
||
x++;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 在指定区域内显示字符串。支持 ASCII、GBK 汉字
|
||
* @param x_start
|
||
* @param y_start
|
||
* @param width: 显示窗的宽
|
||
* @param height: 显示窗口的高
|
||
* @param font_size: 字体大小。注意:若含汉字,只能使用 FONT_12 16 24 32
|
||
* @param font_color: 字体颜色
|
||
* @param back_color: 背景颜色。透明时无效
|
||
* @param is_transparent: 是否透明
|
||
* @param format: 格式字符串
|
||
* @param arg: 参数表
|
||
* @retval 打印完全返回 1,未打印完全返回0
|
||
*/
|
||
uint8_t GE_Font_Print_Va(
|
||
int16_t x_start,
|
||
int16_t y_start,
|
||
uint16_t width,
|
||
uint16_t height,
|
||
uint8_t font_size,
|
||
uint16_t font_color,
|
||
uint16_t back_color,
|
||
uint8_t is_transparent,
|
||
uint8_t *format,
|
||
va_list arg)
|
||
{
|
||
int16_t x_end_plus_1;
|
||
int16_t y_end_plus_1;
|
||
int16_t x = x_start;
|
||
int16_t y = y_start;
|
||
|
||
if (width == BORDER_MAX)
|
||
x_end_plus_1 = LCD_WIDTH;
|
||
else
|
||
x_end_plus_1 = x_start + width;
|
||
|
||
if (height == BORDER_MAX)
|
||
y_end_plus_1 = LCD_HEIGHT;
|
||
else
|
||
y_end_plus_1 = y_start + height;
|
||
|
||
uint8_t is_print_all = FALSE;
|
||
|
||
uint8_t temp_str[1040];
|
||
uint8_t *str = temp_str;
|
||
|
||
vsprintf(str, format, arg);
|
||
|
||
while (1)
|
||
{
|
||
if (*(str) <= 0x80) //ASCII 字符
|
||
{
|
||
if (*str == '\0')
|
||
{
|
||
is_print_all = TRUE;
|
||
break;
|
||
}
|
||
|
||
if (*str == '\r')
|
||
{
|
||
str++;
|
||
continue;
|
||
}
|
||
|
||
if ((x + font_size / 2 > x_end_plus_1) || (*str == '\n'))
|
||
{
|
||
x = x_start;
|
||
y += font_size;
|
||
|
||
if (y + font_size > y_end_plus_1)
|
||
break;
|
||
}
|
||
|
||
if (*str != '\n')
|
||
{
|
||
GE_Font_PrintACSII(x, y, str, font_size, font_color, back_color, is_transparent);
|
||
x += font_size / 2;
|
||
}
|
||
|
||
str++;
|
||
}
|
||
else if (*(str) > 0x80) //GBK 字符
|
||
{
|
||
if (x + font_size > x_end_plus_1)
|
||
{
|
||
x = x_start;
|
||
y += font_size;
|
||
|
||
if (y + font_size > y_end_plus_1)
|
||
break;
|
||
}
|
||
|
||
GE_Font_PrintGBK(x, y, str, font_size, font_color, back_color, is_transparent);
|
||
x += font_size;
|
||
str++;
|
||
str++;
|
||
}
|
||
}
|
||
|
||
return is_print_all;
|
||
}
|
||
|
||
/**
|
||
* @brief 在指定区域内显示字符串。支持 ASCII、GBK 汉字
|
||
* @param x_start
|
||
* @param y_start
|
||
* @param width: 显示窗的宽
|
||
* @param height: 显示窗口的高
|
||
* @param font_size: 字体大小。注意:若含汉字,只能使用 FONT_12 16 24 32
|
||
* @param font_color: 字体颜色
|
||
* @param back_color: 背景颜色。透明时无效
|
||
* @param is_transparent: 是否透明
|
||
* @param format: 格式字符串。用法与 printf 相同
|
||
* @param ...
|
||
* @retval 打印完全返回 1,未打印完全返回0
|
||
*/
|
||
uint8_t GE_Font_Print(
|
||
int16_t x_start,
|
||
int16_t y_start,
|
||
uint16_t width,
|
||
uint16_t height,
|
||
uint8_t font_size,
|
||
uint16_t font_color,
|
||
uint16_t back_color,
|
||
uint8_t is_transparent,
|
||
uint8_t *format,
|
||
...)
|
||
{
|
||
va_list aptr;
|
||
va_start(aptr, format);
|
||
|
||
uint8_t ret = GE_Font_Print_Va(
|
||
x_start,
|
||
y_start,
|
||
width,
|
||
height,
|
||
font_size,
|
||
font_color,
|
||
back_color,
|
||
is_transparent,
|
||
format,
|
||
aptr);
|
||
|
||
va_end(aptr);
|
||
return ret;
|
||
}
|
||
|
||
/**
|
||
* @brief 在指定区域内显示字符串,使用设置。支持 ASCII、GBK 汉字
|
||
* @param x_start
|
||
* @param y_start
|
||
* @param width: 显示窗的宽
|
||
* @param height: 显示窗口的高
|
||
* @param format: 格式字符串
|
||
* @param arg: 参数表
|
||
* @retval 打印完全返回 1,未打印完全返回0
|
||
*/
|
||
uint8_t GE_Font_Print_WithSet_Va(
|
||
int16_t x_start,
|
||
int16_t y_start,
|
||
uint16_t width,
|
||
uint16_t height,
|
||
uint8_t *format,
|
||
va_list arg)
|
||
{
|
||
return GE_Font_Print_Va(
|
||
x_start,
|
||
y_start,
|
||
width,
|
||
height,
|
||
ge_font_print_set.font_size,
|
||
ge_font_print_set.font_color,
|
||
ge_font_print_set.back_color,
|
||
ge_font_print_set.is_transparent,
|
||
format,
|
||
arg);
|
||
}
|
||
|
||
/**
|
||
* @brief 在指定区域内显示字符串,使用设置。支持 ASCII、GBK 汉字
|
||
* @param x_start
|
||
* @param y_start
|
||
* @param width: 显示窗的宽
|
||
* @param height: 显示窗口的高
|
||
* @param format: 格式字符串。用法与 printf 相同
|
||
* @param ...
|
||
* @retval 打印完全返回 1,未打印完全返回0
|
||
*/
|
||
uint8_t GE_Font_Print_WithSet(
|
||
int16_t x_start,
|
||
int16_t y_start,
|
||
uint16_t width,
|
||
uint16_t height,
|
||
uint8_t *format,
|
||
...)
|
||
{
|
||
va_list aptr;
|
||
va_start(aptr, format);
|
||
|
||
uint8_t ret = GE_Font_Print_WithSet_Va(
|
||
x_start,
|
||
y_start,
|
||
width,
|
||
height,
|
||
format,
|
||
aptr);
|
||
|
||
va_end(aptr);
|
||
return ret;
|
||
}
|