1 #include "textui.h"
2 #include <driver/uart/uart.h>
3 #include <common/errno.h>
4 #include "screen_manager.h"
5
6 #define WHITE 0x00ffffff //白
7 #define BLACK 0x00000000 //黑
8 #define RED 0x00ff0000 //红
9 #define ORANGE 0x00ff8000 //橙
10 #define YELLOW 0x00ffff00 //黄
11 #define GREEN 0x0000ff00 //绿
12 #define BLUE 0x000000ff //蓝
13 #define INDIGO 0x0000ffff //靛
14 #define PURPLE 0x008000ff //紫
15
16 // 根据rgb计算出最终的颜色值
17 #define calculate_color(r, g, b) ((((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff)) & 0x00ffffff)
18
19 extern struct scm_ui_framework_t textui_framework;
20
21 extern unsigned char font_ascii[256][16]; //导出ascii字体的bitmap(8*16大小) ps:位于font.h中
22 static void __textui_render_chromatic(uint16_t actual_line, uint16_t index, struct textui_char_chromatic_t *character);
23
24 /**
25 * @brief 重新渲染整个虚拟行
26 *
27 * @param window 窗口结构体
28 * @param vline_id 虚拟行号
29 * @return int 错误码
30 */
textui_refresh_vline(struct textui_window_t * window,uint16_t vline_id)31 int textui_refresh_vline(struct textui_window_t *window, uint16_t vline_id)
32 {
33 if (textui_is_chromatic(window->flags))
34 return textui_refresh_characters(window, vline_id, 0, window->chars_per_line);
35 else
36 return textui_refresh_characters(window, vline_id, 0, window->chars_per_line);
37 }
38
textui_refresh_vlines(struct textui_window_t * window,uint16_t start,uint16_t count)39 int textui_refresh_vlines(struct textui_window_t *window, uint16_t start, uint16_t count)
40 {
41 char bufff[16] = {0};
42 // uart_send_str(COM1, " BEGIN ");
43 for (int i = start; i < window->vlines_num && count > 0; ++i, --count)
44 {
45 // sprintk(bufff, "[ 1fresh: %d ] ", i);
46 // uart_send_str(COM1, bufff);
47 textui_refresh_vline(window, i);
48 }
49 start = 0;
50 while (count > 0)
51 {
52 // sprintk(bufff, "[ 2fresh: %d ] ", start);
53 // uart_send_str(COM1, bufff);
54 // sprintk(bufff, " index=%d ", (window->vlines.chromatic)[start].index);
55 // uart_send_str(COM1, bufff);
56 textui_refresh_vline(window, start);
57 ++start;
58 --count;
59 }
60 // uart_send_str(COM1, " END ");
61 return 0;
62 }
63
64 /**
65 * @brief 刷新某个虚拟行的连续n个字符对象
66 *
67 * @param window 窗口结构体
68 * @param vline_id 虚拟行号
69 * @param start 起始字符号
70 * @param count 要刷新的字符数量
71 * @return int 错误码
72 */
textui_refresh_characters(struct textui_window_t * window,uint16_t vline_id,uint16_t start,uint16_t count)73 int textui_refresh_characters(struct textui_window_t *window, uint16_t vline_id, uint16_t start, uint16_t count)
74 {
75 if (window->id != __textui_get_current_window_id())
76 return 0;
77 // 判断虚拟行参数是否合法
78 if (unlikely(vline_id >= window->vlines_num && (start + count) > window->chars_per_line))
79 return -EINVAL;
80
81 // 计算虚拟行对应的真实行
82 int actual_line_id = (int)vline_id - window->top_vline;
83 if (actual_line_id < 0)
84 actual_line_id += __textui_get_actual_lines();
85 // 判断真实行id是否合理
86 if (unlikely(actual_line_id < 0 || actual_line_id >= __textui_get_actual_lines()))
87 return 0;
88
89 // 若是彩色像素模式
90 if (textui_is_chromatic(window->flags))
91 {
92 struct textui_vline_chromatic_t *vline = &(window->vlines.chromatic)[vline_id];
93 for (int i = 0; i < count; ++i)
94 {
95
96 __textui_render_chromatic(actual_line_id, start + i, &vline->chars[start + i]);
97 }
98 }
99
100 return 0;
101 }
102
103 /**
104 * @brief 渲染彩色字符
105 *
106 * @param actual_line 真实行的行号
107 * @param index 列号
108 * @param character 要渲染的字符
109 */
__textui_render_chromatic(uint16_t actual_line,uint16_t index,struct textui_char_chromatic_t * character)110 static void __textui_render_chromatic(uint16_t actual_line, uint16_t index, struct textui_char_chromatic_t *character)
111 {
112 /**
113 * @brief 在屏幕上指定位置打印字符
114 *
115 * @param x 左上角列像素点位置
116 * @param y 左上角行像素点位置
117 * @param FRcolor 字体颜色
118 * @param BKcolor 背景颜色
119 * @param font 字符的bitmap
120 */
121
122 unsigned char *font_ptr = font_ascii[(uint8_t)character->c];
123 unsigned int *addr;
124 uint32_t *fb = (uint32_t *)textui_framework.buf->vaddr;
125
126 uint32_t FRcolor = character->FRcolor & 0x00ffffff;
127
128 uint32_t BKcolor = character->BKcolor & 0x00ffffff;
129
130 uint32_t x = index * TEXTUI_CHAR_WIDTH;
131 uint32_t y = actual_line * TEXTUI_CHAR_HEIGHT;
132
133 int testbit; // 用来测试某位是背景还是字体本身
134
135 for (int i = 0; i < TEXTUI_CHAR_HEIGHT; ++i)
136 {
137 // 计算出帧缓冲区的地址
138 addr = (uint32_t *)(fb + textui_framework.buf->width * (y + i) + x);
139
140 testbit = (1 << (TEXTUI_CHAR_WIDTH + 1));
141 for (int j = 0; j < TEXTUI_CHAR_WIDTH; ++j)
142 {
143 // 从左往右逐个测试相应位
144 testbit >>= 1;
145 if (*font_ptr & testbit)
146 *addr = FRcolor; // 字,显示前景色
147 else
148 *addr = BKcolor; // 背景色
149
150 ++addr;
151 }
152 ++font_ptr;
153 }
154 }