Files
2022-08-23 15:36:13 +08:00

487 lines
12 KiB
C++

#include "display_ch.h"
//#define _ASC16_
//#define _HZK16_
DisplayCh::DisplayCh() {
// Set default highlight color
highlightcolor = RED;
highlighted = false;
// HZK16 is not used by default
hzk16Used = false;
hzk16Type = DontUsedHzk16;
// pHzk16File = nullptr;
// pAsc16File = nullptr;
textwrap = true;
_width = 320;
_height = 240;
}
/***************************************************************************************
** Function name: setTextWrap
** Description: Define if text should wrap at end of line
***************************************************************************************/
void DisplayCh::setTextWrap(boolean w) {
textwrap = w;
}
/***************************************************************************************
** Function name: setTextSize
** Description: Set the text size multiplier
***************************************************************************************/
void DisplayCh::setTextSize(uint8_t s) {
if (s > 7)
s = 7; // Limit the maximum size multiplier so byte variables can be
// used
// for rendering
textsize = (s > 0) ? s : 1; // Don't allow font size 0
// Calculate the text width and height.
// It's 8 pixels wide and 16 pixels high in for ASCII characters,
// and 16 pixels both wide and high for GBK characters in HZK16 mode.
ascCharWidth = 8 * textsize;
ascCharHeigth = 16 * textsize;
gbkCharWidth = ascCharHeigth;
gbkCharHeight = gbkCharWidth;
}
/***************************************************************************************
** Function name: setCursor
** Description: Set the text cursor x,y position
***************************************************************************************/
void DisplayCh::setCursor(int16_t x, int16_t y) {
cursor_x = x;
cursor_y = y;
}
/***************************************************************************************
** Function name: setCursor
** Description: Set the text cursor x,y position and font
***************************************************************************************/
void DisplayCh::setCursor(int16_t x, int16_t y, uint8_t font) {
textfont = font;
cursor_x = x;
cursor_y = y;
}
/***************************************************************************************
** Function name: setTextColor
** Description: Set the font foreground colour (background is
*transparent)
***************************************************************************************/
void DisplayCh::setTextColor(uint16_t c) {
// For 'transparent' background, we'll set the bg
// to the same as fg instead of using a flag
textcolor = textbgcolor = c;
}
/***************************************************************************************
** Function name: fillScreen
** Description: Clear the screen to defined colour
***************************************************************************************/
void DisplayCh::fillScreen(uint32_t color) {
M5.Lcd.fillRect(0, 0, _width, _height, color);
}
/***************************************************************************************
** Function name: setTextColor
** Description: Set the font foreground and background colour
***************************************************************************************/
void DisplayCh::setTextColor(uint16_t c, uint16_t b) {
textcolor = c;
textbgcolor = b;
}
/***************************************************************************************
** Function name: loadHzk16
** Description: loadHzk16 fonts
** Params:
** HZK16Path: HZK16 file path on TF card. e.g. /HZK16, means file on the
*root dir of TF card. * ASC16Path: ASC16 file path on TF card.
***************************************************************************************/
void DisplayCh::loadHzk16(Hzk16Types hzkTypes, const char *HZK16Path,
const char *ASC16Path) {
if (hzk16Used) return;
// Hzk16Types hzkTypes = InternalHzk16
if (hzkTypes == InternalHzk16) {
//#if defined(_ASC16_) && defined(_HZK16_)
pAscCharMatrix = (uint8_t *)&ASC16[0];
pGbkCharMatrix = (uint8_t *)&HZK16[0];
Serial.println("HZK16 path: Internal");
Serial.println("ASC16 path: Internal");
hzk16Used = initHzk16(true, nullptr, nullptr);
} else {
pAscCharMatrix = NULL;
pGbkCharMatrix = NULL;
Serial.print("HZK16 path: /SD");
Serial.println(HZK16Path);
Serial.print("ASC16 path: /SD");
Serial.println(ASC16Path);
hzk16Used = initHzk16(true, HZK16Path, ASC16Path);
}
Serial.print("HZK16 init result: ");
Serial.println(isHzk16Used());
}
/***************************************************************************************
** Function name: disableHzk16
** Description: disable Hzk16 fonts
** Params:
***************************************************************************************/
void DisplayCh::disableHzk16() {
if (hzk16Used) {
hzk16Used = initHzk16(false);
}
}
bool DisplayCh::initHzk16(boolean use, const char *HZK16Path,
const char *ASC16Path) {
bool result = false;
if (use == false) { // Do not use HZK16 and ASC16 fonts
hzk16Type = DontUsedHzk16;
Serial.println("Use default font.");
} else if (pAscCharMatrix == NULL ||
pGbkCharMatrix ==
NULL) { // Use external HZK16 and ASC16 font on TF card.
// Check if HZK16 and ASC16 files exist on TF card.
if (SD.exists(HZK16Path) && SD.exists(ASC16Path)) { // Exists
hzk16Type = ExternalHzk16;
Serial.println("Use external HZK16 and ASC16 font.");
} else { // Not exists
hzk16Type = DontUsedHzk16;
Serial.println(
"External font file HZK16/ASC16 lost, use default font.");
}
} else { // Use internal HZK16 and ASC16 fonts
hzk16Type = InternalHzk16;
Serial.println("Use internal HZK16 and ASC16 font.");
}
switch (hzk16Type) {
case ExternalHzk16: {
if (pHzk16File == NULL) {
Hzk16File = SD.open(HZK16Path);
pHzk16File = &Hzk16File;
}
if (pAsc16File == NULL) {
Asc16File = SD.open(ASC16Path);
pAsc16File = &Asc16File;
}
hzkBufCount = 0;
break;
}
case InternalHzk16: {
if (pAscCharMatrix == NULL || pGbkCharMatrix == NULL) {
hzk16Type = DontUsedHzk16;
}
if (pHzk16File != NULL) {
pHzk16File->close();
pHzk16File = NULL;
}
if (pAsc16File != NULL) {
pAsc16File->close();
pAsc16File = NULL;
}
hzkBufCount = 0;
break;
}
case DontUsedHzk16: {
if (pHzk16File != NULL) {
pHzk16File->close();
pHzk16File = NULL;
}
if (pAsc16File != NULL) {
pAsc16File->close();
pAsc16File = NULL;
}
break;
}
}
return hzk16Type != DontUsedHzk16;
}
void DisplayCh::writeHzkAsc(const char c) {
if (c == '\n') {
cursor_x = 0;
cursor_y += ascCharHeigth;
} else if (c != '\r') {
uint32_t offset;
uint8_t mask;
uint16_t posX = cursor_x, posY = cursor_y;
uint8_t charMatrix[16];
uint8_t *pCharMatrix;
offset = (uint32_t)c * 16;
if (hzk16Type == ExternalHzk16) {
pAsc16File->seek(offset, SeekSet);
pAsc16File->readBytes((char *)&charMatrix[0], 16);
pCharMatrix = &charMatrix[0];
} else {
if (pAscCharMatrix == NULL) {
return;
}
pCharMatrix = pAscCharMatrix + offset;
}
// startWrite();
if (highlighted) {
M5.Lcd.fillRect(cursor_x, cursor_y, ascCharWidth, ascCharHeigth,
highlightcolor);
} else if (istransparent == false) {
M5.Lcd.fillRect(cursor_x, cursor_y, ascCharWidth, ascCharHeigth,
textbgcolor);
}
for (uint8_t row = 0; row < 16; row++) {
mask = 0x80;
posX = cursor_x;
for (uint8_t col = 0; col < 8; col++) {
if ((*pCharMatrix & mask) != 0) {
if (textsize == 1) {
M5.Lcd.drawPixel(posX, posY, textcolor);
} else {
M5.Lcd.fillRect(posX, posY, textsize, textsize,
textcolor);
}
}
posX += textsize;
mask >>= 1;
}
posY += textsize;
pCharMatrix++;
}
// endWrite();
cursor_x += ascCharWidth;
if (textwrap && ((cursor_x + ascCharWidth) > _width)) {
cursor_x = 0;
cursor_y += ascCharHeigth;
}
}
}
void DisplayCh::writeHzk(char *c) {
char *ret = c;
if (ret == NULL) return;
while (*ret != '\0') {
while (*ret <= 0xA0) {
if (*ret == '\0') return;
writeHzkAsc(*ret);
ret++;
}
writeHzkGbk(ret);
ret++;
ret++;
}
}
void DisplayCh::writeHzkGbk(const char *c) {
uint32_t offset;
uint8_t mask;
uint16_t posX = cursor_x, posY = cursor_y;
uint8_t charMatrix[32];
uint8_t *pCharMatrix;
offset =
(uint32_t)(94 * (uint32_t)(c[0] - 0xA1) + (uint32_t)(c[1] - 0xA1)) * 32;
if (hzk16Type == ExternalHzk16) {
pHzk16File->seek(offset, SeekSet);
pHzk16File->readBytes((char *)&charMatrix[0], 32);
pCharMatrix = &charMatrix[0];
} else {
if (pGbkCharMatrix == NULL) {
return;
}
pCharMatrix = pGbkCharMatrix + offset;
}
// startWrite();
if (highlighted) {
M5.Lcd.fillRect(cursor_x, cursor_y, gbkCharWidth, gbkCharHeight,
highlightcolor);
} else if (istransparent == false) {
M5.Lcd.fillRect(cursor_x, cursor_y, gbkCharWidth, gbkCharHeight,
textbgcolor);
}
for (uint8_t row = 0; row < 16; row++) {
posX = cursor_x;
mask = 0x80;
for (uint8_t col = 0; col < 8; col++) {
if ((*pCharMatrix & mask) != 0) {
if (textsize == 1) {
M5.Lcd.drawPixel(posX, posY, textcolor);
} else {
M5.Lcd.fillRect(posX, posY, textsize, textsize, textcolor);
}
}
if ((*(pCharMatrix + 1) & mask) != 0) {
if (textsize == 1) {
M5.Lcd.drawPixel(posX + ascCharWidth, posY, textcolor);
} else {
M5.Lcd.fillRect(posX + ascCharWidth, posY, textsize,
textsize, textcolor);
}
}
mask >>= 1;
posX += textsize;
}
posY += textsize;
pCharMatrix += 2;
}
// endWrite();
cursor_x += gbkCharWidth;
if (textwrap && ((cursor_x + gbkCharWidth) > _width)) {
cursor_x = 0;
cursor_y += gbkCharHeight;
}
}