mirror of
https://github.com/m5stack/M5Stack.git
synced 2026-05-20 10:06:46 -07:00
487 lines
12 KiB
C++
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;
|
|
}
|
|
}
|