426 lines
9.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//游戏引擎文字显示库
#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;
}