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 }