display_ch.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. #include "display_ch.h"
  2. //#define _ASC16_
  3. //#define _HZK16_
  4. DisplayCh::DisplayCh(){
  5. // Set default highlight color
  6. highlightcolor = RED;
  7. highlighted = false;
  8. // HZK16 is not used by default
  9. hzk16Used = false;
  10. hzk16Type = DontUsedHzk16;
  11. //pHzk16File = nullptr;
  12. //pAsc16File = nullptr;
  13. textwrap = true;
  14. _width = 320;
  15. _height = 240;
  16. }
  17. /***************************************************************************************
  18. ** Function name: setTextWrap
  19. ** Description: Define if text should wrap at end of line
  20. ***************************************************************************************/
  21. void DisplayCh::setTextWrap(boolean w) { textwrap = w; }
  22. /***************************************************************************************
  23. ** Function name: setTextSize
  24. ** Description: Set the text size multiplier
  25. ***************************************************************************************/
  26. void DisplayCh::setTextSize(uint8_t s) {
  27. if (s > 7)
  28. s = 7; // Limit the maximum size multiplier so byte variables can be used
  29. // for rendering
  30. textsize = (s > 0) ? s : 1; // Don't allow font size 0
  31. // Calculate the text width and height.
  32. // It's 8 pixels wide and 16 pixels high in for ASCII characters,
  33. // and 16 pixels both wide and high for GBK characters in HZK16 mode.
  34. ascCharWidth = 8 * textsize;
  35. ascCharHeigth = 16 * textsize;
  36. gbkCharWidth = ascCharHeigth;
  37. gbkCharHeight = gbkCharWidth;
  38. }
  39. /***************************************************************************************
  40. ** Function name: setCursor
  41. ** Description: Set the text cursor x,y position
  42. ***************************************************************************************/
  43. void DisplayCh::setCursor(int16_t x, int16_t y) {
  44. cursor_x = x;
  45. cursor_y = y;
  46. }
  47. /***************************************************************************************
  48. ** Function name: setCursor
  49. ** Description: Set the text cursor x,y position and font
  50. ***************************************************************************************/
  51. void DisplayCh::setCursor(int16_t x, int16_t y, uint8_t font) {
  52. textfont = font;
  53. cursor_x = x;
  54. cursor_y = y;
  55. }
  56. /***************************************************************************************
  57. ** Function name: setTextColor
  58. ** Description: Set the font foreground colour (background is
  59. *transparent)
  60. ***************************************************************************************/
  61. void DisplayCh::setTextColor(uint16_t c) {
  62. // For 'transparent' background, we'll set the bg
  63. // to the same as fg instead of using a flag
  64. textcolor = textbgcolor = c;
  65. }
  66. /***************************************************************************************
  67. ** Function name: fillScreen
  68. ** Description: Clear the screen to defined colour
  69. ***************************************************************************************/
  70. void DisplayCh::fillScreen(uint32_t color) {
  71. M5.Lcd.fillRect(0, 0, _width, _height, color);
  72. }
  73. /***************************************************************************************
  74. ** Function name: setTextColor
  75. ** Description: Set the font foreground and background colour
  76. ***************************************************************************************/
  77. void DisplayCh::setTextColor(uint16_t c, uint16_t b) {
  78. textcolor = c;
  79. textbgcolor = b;
  80. }
  81. /***************************************************************************************
  82. ** Function name: loadHzk16
  83. ** Description: loadHzk16 fonts
  84. ** Params:
  85. ** HZK16Path: HZK16 file path on TF card. e.g. /HZK16, means file on the
  86. *root dir of TF card. * ASC16Path: ASC16 file path on TF card.
  87. ***************************************************************************************/
  88. void DisplayCh::loadHzk16(Hzk16Types hzkTypes,const char *HZK16Path, const char *ASC16Path) {
  89. if (hzk16Used)
  90. return;
  91. //Hzk16Types hzkTypes = InternalHzk16
  92. if(hzkTypes == InternalHzk16){
  93. //#if defined(_ASC16_) && defined(_HZK16_)
  94. pAscCharMatrix = (uint8_t *)&ASC16[0];
  95. pGbkCharMatrix = (uint8_t *)&HZK16[0];
  96. Serial.println("HZK16 path: Internal");
  97. Serial.println("ASC16 path: Internal");
  98. hzk16Used = initHzk16(true, nullptr, nullptr);
  99. }
  100. else
  101. {
  102. pAscCharMatrix = NULL;
  103. pGbkCharMatrix = NULL;
  104. Serial.print("HZK16 path: /SD");
  105. Serial.println(HZK16Path);
  106. Serial.print("ASC16 path: /SD");
  107. Serial.println(ASC16Path);
  108. hzk16Used = initHzk16(true, HZK16Path, ASC16Path);
  109. }
  110. Serial.print("HZK16 init result: ");
  111. Serial.println(isHzk16Used());
  112. }
  113. /***************************************************************************************
  114. ** Function name: disableHzk16
  115. ** Description: disable Hzk16 fonts
  116. ** Params:
  117. ***************************************************************************************/
  118. void DisplayCh::disableHzk16() {
  119. if (hzk16Used) {
  120. hzk16Used = initHzk16(false);
  121. }
  122. }
  123. bool DisplayCh::initHzk16(boolean use, const char *HZK16Path,
  124. const char *ASC16Path) {
  125. bool result = false;
  126. if (use == false) { // Do not use HZK16 and ASC16 fonts
  127. hzk16Type = DontUsedHzk16;
  128. Serial.println("Use default font.");
  129. } else if (pAscCharMatrix == NULL ||
  130. pGbkCharMatrix ==
  131. NULL) { // Use external HZK16 and ASC16 font on TF card.
  132. // Check if HZK16 and ASC16 files exist on TF card.
  133. if (SD.exists(HZK16Path) && SD.exists(ASC16Path)) { // Exists
  134. hzk16Type = ExternalHzk16;
  135. Serial.println("Use external HZK16 and ASC16 font.");
  136. } else { // Not exists
  137. hzk16Type = DontUsedHzk16;
  138. Serial.println("External font file HZK16/ASC16 lost, use default font.");
  139. }
  140. } else { // Use internal HZK16 and ASC16 fonts
  141. hzk16Type = InternalHzk16;
  142. Serial.println("Use internal HZK16 and ASC16 font.");
  143. }
  144. switch (hzk16Type) {
  145. case ExternalHzk16: {
  146. if (pHzk16File == NULL) {
  147. Hzk16File = SD.open(HZK16Path);
  148. pHzk16File = &Hzk16File;
  149. }
  150. if (pAsc16File == NULL) {
  151. Asc16File = SD.open(ASC16Path);
  152. pAsc16File = &Asc16File;
  153. }
  154. hzkBufCount = 0;
  155. break;
  156. }
  157. case InternalHzk16: {
  158. if (pAscCharMatrix == NULL || pGbkCharMatrix == NULL) {
  159. hzk16Type = DontUsedHzk16;
  160. }
  161. if (pHzk16File != NULL) {
  162. pHzk16File->close();
  163. pHzk16File = NULL;
  164. }
  165. if (pAsc16File != NULL) {
  166. pAsc16File->close();
  167. pAsc16File = NULL;
  168. }
  169. hzkBufCount = 0;
  170. break;
  171. }
  172. case DontUsedHzk16: {
  173. if (pHzk16File != NULL) {
  174. pHzk16File->close();
  175. pHzk16File = NULL;
  176. }
  177. if (pAsc16File != NULL) {
  178. pAsc16File->close();
  179. pAsc16File = NULL;
  180. }
  181. break;
  182. }
  183. }
  184. return hzk16Type != DontUsedHzk16;
  185. }
  186. void DisplayCh::writeHzkAsc(const char c) {
  187. if (c == '\n') {
  188. cursor_x = 0;
  189. cursor_y += ascCharHeigth;
  190. } else if (c != '\r') {
  191. uint32_t offset;
  192. uint8_t mask;
  193. uint16_t posX = cursor_x, posY = cursor_y;
  194. uint8_t charMatrix[16];
  195. uint8_t *pCharMatrix;
  196. offset = (uint32_t)c * 16;
  197. if (hzk16Type == ExternalHzk16) {
  198. pAsc16File->seek(offset, SeekSet);
  199. pAsc16File->readBytes((char *)&charMatrix[0], 16);
  200. pCharMatrix = &charMatrix[0];
  201. } else {
  202. if (pAscCharMatrix == NULL) {
  203. return;
  204. }
  205. pCharMatrix = pAscCharMatrix + offset;
  206. }
  207. // startWrite();
  208. if (highlighted) {
  209. M5.Lcd.fillRect(cursor_x, cursor_y, ascCharWidth, ascCharHeigth, highlightcolor);
  210. } else if (istransparent == false) {
  211. M5.Lcd.fillRect(cursor_x, cursor_y, ascCharWidth, ascCharHeigth, textbgcolor);
  212. }
  213. for (uint8_t row = 0; row < 16; row++) {
  214. mask = 0x80;
  215. posX = cursor_x;
  216. for (uint8_t col = 0; col < 8; col++) {
  217. if ((*pCharMatrix & mask) != 0) {
  218. if (textsize == 1) {
  219. M5.Lcd.drawPixel(posX, posY, textcolor);
  220. } else {
  221. M5.Lcd.fillRect(posX, posY, textsize, textsize, textcolor);
  222. }
  223. }
  224. posX += textsize;
  225. mask >>= 1;
  226. }
  227. posY += textsize;
  228. pCharMatrix++;
  229. }
  230. // endWrite();
  231. cursor_x += ascCharWidth;
  232. if (textwrap && ((cursor_x + ascCharWidth) > _width)) {
  233. cursor_x = 0;
  234. cursor_y += ascCharHeigth;
  235. }
  236. }
  237. }
  238. void DisplayCh::writeHzk(char* c){
  239. char *ret = c;
  240. if(ret == NULL) return;
  241. while(*ret != '\0'){
  242. while(*ret <= 0xA0){
  243. if(*ret == '\0') return;
  244. writeHzkAsc(*ret);
  245. ret++;
  246. }
  247. writeHzkGbk(ret);
  248. ret++;
  249. ret++;
  250. }
  251. }
  252. void DisplayCh::writeHzkGbk(const char *c) {
  253. uint32_t offset;
  254. uint8_t mask;
  255. uint16_t posX = cursor_x, posY = cursor_y;
  256. uint8_t charMatrix[32];
  257. uint8_t *pCharMatrix;
  258. offset = (uint32_t)(94 * (uint32_t)(c[0] - 0xA1) + (uint32_t)(c[1] - 0xA1)) * 32;
  259. if (hzk16Type == ExternalHzk16) {
  260. pHzk16File->seek(offset, SeekSet);
  261. pHzk16File->readBytes((char *)&charMatrix[0], 32);
  262. pCharMatrix = &charMatrix[0];
  263. } else {
  264. if (pGbkCharMatrix == NULL) {
  265. return;
  266. }
  267. pCharMatrix = pGbkCharMatrix + offset;
  268. }
  269. // startWrite();
  270. if (highlighted) {
  271. M5.Lcd.fillRect(cursor_x, cursor_y, gbkCharWidth, gbkCharHeight, highlightcolor);
  272. } else if (istransparent == false) {
  273. M5.Lcd.fillRect(cursor_x, cursor_y, gbkCharWidth, gbkCharHeight, textbgcolor);
  274. }
  275. for (uint8_t row = 0; row < 16; row++) {
  276. posX = cursor_x;
  277. mask = 0x80;
  278. for (uint8_t col = 0; col < 8; col++) {
  279. if ((*pCharMatrix & mask) != 0) {
  280. if (textsize == 1) {
  281. M5.Lcd.drawPixel(posX, posY, textcolor);
  282. } else {
  283. M5.Lcd.fillRect(posX, posY, textsize, textsize, textcolor);
  284. }
  285. }
  286. if ((*(pCharMatrix + 1) & mask) != 0) {
  287. if (textsize == 1) {
  288. M5.Lcd.drawPixel(posX + ascCharWidth, posY, textcolor);
  289. } else {
  290. M5.Lcd.fillRect(posX + ascCharWidth, posY, textsize, textsize, textcolor);
  291. }
  292. }
  293. mask >>= 1;
  294. posX += textsize;
  295. }
  296. posY += textsize;
  297. pCharMatrix += 2;
  298. }
  299. // endWrite();
  300. cursor_x += gbkCharWidth;
  301. if (textwrap && ((cursor_x + gbkCharWidth) > _width)) {
  302. cursor_x = 0;
  303. cursor_y += gbkCharHeight;
  304. }
  305. }