textui-render.c 4.7 KB

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