diff --git a/README.md b/README.md index 753ead3..8413f59 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ Supported device - M5ATOMS3 - M5Dial - M5DinMeter -- M5Capsule - M5Cardputer - UnitOLED - UnitMiniOLED diff --git a/library.json b/library.json index d5617e9..e778981 100644 --- a/library.json +++ b/library.json @@ -10,7 +10,7 @@ "type": "git", "url": "https://github.com/m5stack/M5GFX.git" }, - "version": "0.1.10", + "version": "0.1.11", "frameworks": ["arduino", "espidf", "*"], "platforms": ["espressif32", "native"], "headers": "M5GFX.h" diff --git a/library.properties b/library.properties index 5752035..19a3b4c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=M5GFX -version=0.1.10 +version=0.1.11 author=M5Stack maintainer=M5Stack sentence=Library for M5Stack All Display diff --git a/src/M5GFX.cpp b/src/M5GFX.cpp index 5022212..c00bc69 100644 --- a/src/M5GFX.cpp +++ b/src/M5GFX.cpp @@ -675,7 +675,7 @@ namespace m5gfx bus_spi->config(bus_cfg); bus_spi->init(); id = _read_panel_id(bus_spi, GPIO_NUM_9, 0x70, 0); - if (id == 0x00F00000) + if ((id & 0xFFFFF0FFu) == 0x00F00000u) { // check panel (e-paper GDEW0154M09) _pin_level(GPIO_NUM_12, true); // POWER_HOLD_PIN 12 board = board_t::board_M5StackCoreInk; @@ -1432,6 +1432,9 @@ namespace m5gfx case board_M5Tough: title = "M5Tough"; break; case board_M5Station: title = "M5Station"; break; case board_M5AtomS3: title = "M5AtomS3"; break; + case board_M5Dial: title = "M5Dial"; break; + case board_M5Cardputer: title = "M5Cardputer"; break; + case board_M5DinMeter: title = "M5DinMeter"; break; default: title = "M5GFX"; break; } p->setWindowTitle(title); @@ -1462,8 +1465,16 @@ namespace m5gfx break; case board_M5Station: + case board_M5Cardputer: + w = 240; + h = 135; + pnl_cfg.offset_rotation = 3; + r = 1; + break; + case board_M5StickCPlus: case board_M5StickCPlus2: + case board_M5DinMeter: w = 135; h = 240; break; @@ -1475,6 +1486,11 @@ namespace m5gfx r = 1; break; + case board_M5Dial: + w = 240; + h = 240; + break; + default: break; } diff --git a/src/lgfx/utility/lgfx_tjpgd.c b/src/lgfx/utility/lgfx_tjpgd.c index 0b07d1d..15bd33c 100644 --- a/src/lgfx/utility/lgfx_tjpgd.c +++ b/src/lgfx/utility/lgfx_tjpgd.c @@ -130,7 +130,7 @@ static inline int32_t BYTECLIP ( /*---------------------------------------------*/ #if JD_BAYER -static const int_fast8_t Bayer[16] = { 0, 4, 1, 5,-2, 2,-1, 3, 1, 5, 0, 4,-1, 3,-2, 2}; +static const int8_t Bayer[16] = { 0, 4, 1, 5,-2, 2,-1, 3, 1, 5, 0, 4,-1, 3,-2, 2}; #endif @@ -299,7 +299,7 @@ static int32_t huffext ( /* >=0: decoded data, <0: error code */ { const uint8_t* hb_end = hb + 16 + 1; uint_fast8_t msk = jd->dbit; - uint_fast16_t w = *jd->dptr & ((1ul << msk) - 1); + uint32_t w = *jd->dptr & ((1ul << msk) - 1); for (;;) { if (!msk) { /* Next byte? */ uint8_t *dp = jd->dptr; @@ -584,7 +584,7 @@ static JRESULT mcu_output ( iy = 0; do { #if JD_BAYER - const int_fast8_t* btbl = &Bayer[(iy & 3) << 2]; + const int8_t* btbl = &Bayer[(iy & 3) << 2]; #endif py = &jd->mcubuf[((iy & 8) + iy) << 3]; pc = &jd->mcubuf[((mx << iyshift) + (iy >> iyshift)) << 3]; @@ -596,10 +596,10 @@ static JRESULT mcu_output ( ++pc; /* Convert CbCr to RGB */ - uint_fast16_t rr = ((int32_t)(1.402 * (1<> FP_SHIFT; - uint_fast16_t gg = ((int32_t)(0.34414 * (1<> FP_SHIFT; + int32_t gg = ((int32_t)(0.34414 * (1<> FP_SHIFT; - uint_fast16_t bb = ((int32_t)(1.772 * (1<> FP_SHIFT; + int32_t bb = ((int32_t)(1.772 * (1<> FP_SHIFT; do { #if JD_BAYER yy = *py + btbl[ix & 3]; /* Get Y component */ diff --git a/src/lgfx/utility/lgfx_tjpgd.h b/src/lgfx/utility/lgfx_tjpgd.h index e8ecb23..e4523b3 100644 --- a/src/lgfx/utility/lgfx_tjpgd.h +++ b/src/lgfx/utility/lgfx_tjpgd.h @@ -63,13 +63,13 @@ struct lgfxJdec { uint8_t* dptr; /* Current data read ptr */ uint8_t* dpend; /* data end ptr */ uint8_t* inbuf; /* Bit stream input buffer */ - uint_fast8_t dbit; /* Current bit in the current read byte */ - uint_fast8_t scale; /* Output scaling ratio */ - uint_fast8_t msx, msy; /* MCU size in unit of block (width, height) */ - uint_fast8_t qtid[3]; /* Quantization table ID of each component */ + uint8_t dbit; /* Current bit in the current read byte */ + uint8_t scale; /* Output scaling ratio */ + uint8_t msx, msy; /* MCU size in unit of block (width, height) */ + uint8_t qtid[3]; /* Quantization table ID of each component */ int32_t dcv[3]; /* Previous DC element of each component */ uint16_t nrst; /* Restart inverval */ - uint_fast16_t width, height;/* Size of the input image (pixel) */ + uint16_t width, height;/* Size of the input image (pixel) */ uint8_t* huffbits[2][2]; /* Huffman bit distribution tables [id][dcac] */ uint16_t* huffcode[2][2]; /* Huffman code word tables [id][dcac] */ uint8_t* huffdata[2][2]; /* Huffman decoded data tables [id][dcac] */ @@ -77,7 +77,7 @@ struct lgfxJdec { void* workbuf; /* Working buffer for IDCT and RGB output */ int16_t* mcubuf; /* Working buffer for the MCU */ uint8_t* pool; /* Pointer to available memory pool */ - uint_fast16_t sz_pool; /* Size of momory pool (bytes available) */ + uint16_t sz_pool; /* Size of momory pool (bytes available) */ uint32_t (*infunc)(void*, uint8_t*, uint32_t);/* Pointer to jpeg stream input function */ void* device; /* Pointer to I/O device identifiler for the session */ uint8_t comps_in_frame; /* 1=Y(grayscale) 3=YCrCb */ diff --git a/src/lgfx/v1/LGFXBase.cpp b/src/lgfx/v1/LGFXBase.cpp index 6e70d7c..a672cd9 100644 --- a/src/lgfx/v1/LGFXBase.cpp +++ b/src/lgfx/v1/LGFXBase.cpp @@ -2144,7 +2144,6 @@ namespace lgfx //_decoderState = utf8_decode_state_t::utf8_state0; font->getDefaultMetric(&_font_metrics); - } /// load VLW font @@ -2154,6 +2153,39 @@ namespace lgfx return load_font(&_font_data); } + bool LGFXBase::load_font_with_path(const char *path) + { + this->unloadFont(); + + if (this->_font_file.get() == nullptr) return false; + + this->prepareTmpTransaction(this->_font_file.get()); + this->_font_file->preRead(); + + bool result = this->_font_file->open(path); + if (!result) + { + size_t alloclen = strlen(path) + 8; + auto filename = (char*)alloca(alloclen); + memset(filename, 0, alloclen); + filename[0] = '/'; + + strcpy(&filename[1], &path[(path[0] == '/') ? 1 : 0]); + int len = strlen(filename); + if (memcmp(&filename[len - 4], ".vlw", 4)) + { + strcpy(&filename[len], ".vlw"); + } + result = this->_font_file->open(filename); + } + + if (result) { + result = this->load_font(this->_font_file.get()); + } + this->_font_file->postRead(); + return result; + } + bool LGFXBase::load_font(lgfx::DataWrapper* data) { this->unloadFont(); diff --git a/src/lgfx/v1/LGFXBase.hpp b/src/lgfx/v1/LGFXBase.hpp index 91a75ea..d9fbdec 100644 --- a/src/lgfx/v1/LGFXBase.hpp +++ b/src/lgfx/v1/LGFXBase.hpp @@ -742,6 +742,23 @@ namespace lgfx /// load VLW font bool loadFont(const uint8_t* array); + /// load vlw font from filesystem. + bool loadFont(const char *path) + { + this->unloadFont(); + this->_font_file.reset(_create_data_wrapper()); + return load_font_with_path(path); + } + + + template + bool loadFont(T &fs, const char *path) + { + unloadFont(); + _font_file.reset(new DataWrapperT(&fs)); + return load_font_with_path(path); + } + /// unload VLW font void unloadFont(void); @@ -754,6 +771,16 @@ namespace lgfx uint8_t getAttribute(attribute_t attr_id); uint8_t getAttribute(uint8_t attr_id) { return getAttribute((attribute_t)attr_id); } + template + void setFileStorage(T& fs) { + _data_wrapper_factory.reset(new DataWrapperTFactoryT(&fs)); + } + + template + void setFileStorage(T* fs) { _data_wrapper_factory.reset(new DataWrapperTFactoryT(fs)); } + + void clearFileStorage(void) { _data_wrapper_factory.reset(new DataWrapperTFactoryT(nullptr)); } + //---------------------------------------------------------------------------- // print & text support //---------------------------------------------------------------------------- @@ -822,9 +849,9 @@ namespace lgfx void qrcode(const char *string, int32_t x = -1, int32_t y = -1, int32_t width = -1, uint8_t version = 1); #define LGFX_FUNCTION_GENERATOR(drawImg, draw_img) \ - protected: \ + protected: \ bool draw_img(DataWrapper* data, int32_t x, int32_t y, int32_t maxWidth, int32_t maxHeight, int32_t offX, int32_t offY, float scale_x, float scale_y, datum_t datum); \ - public: \ + public: \ bool drawImg(const uint8_t *data, uint32_t len, int32_t x=0, int32_t y=0, int32_t maxWidth=0, int32_t maxHeight=0, int32_t offX=0, int32_t offY=0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ { \ PointerWrapper data_wrapper; \ @@ -835,6 +862,34 @@ namespace lgfx { \ return this->draw_img(data, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ } \ + bool drawImg##File(DataWrapper* file, const char *path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ + { \ + bool res = false; \ + this->prepareTmpTransaction(file); \ + file->preRead(); \ + if (file->open(path)) \ + { \ + res = this->draw_img(file, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ + file->close(); \ + } \ + file->postRead(); \ + return res; \ + } \ + inline bool drawImg##File(const char *path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ + { \ + auto data = _create_data_wrapper(); \ + bool res = drawImg##File(data, path, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ + delete data; \ + return res; \ + } \ + template \ + inline bool drawImg##File(T &fs, const char *path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ + { \ + DataWrapperT file ( &fs ); \ + bool res = this->drawImg##File(&file, path, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ + file.close(); \ + return res; \ + } LGFX_FUNCTION_GENERATOR(drawBmp, draw_bmp) LGFX_FUNCTION_GENERATOR(drawJpg, draw_jpg) @@ -851,6 +906,11 @@ namespace lgfx { return drawJpg(data, x, y, maxWidth, maxHeight, offX, offY, 1.0f / (1 << scale)); } + [[deprecated("use float scale")]] + inline bool drawJpgFile(const char *path, int32_t x, int32_t y, int32_t maxWidth, int32_t maxHeight, int32_t offX, int32_t offY, jpeg_div::jpeg_div_t scale) + { + return drawJpgFile(path, x, y, maxWidth, maxHeight, offX, offY, 1.0f / (1 << scale)); + } void* createPng( size_t* datalen, int32_t x = 0, int32_t y = 0, int32_t width = 0, int32_t height = 0); @@ -917,6 +977,9 @@ namespace lgfx std::shared_ptr _font_file; // run-time font file PointerWrapper _font_data; + std::shared_ptr _data_wrapper_factory; + DataWrapper* _create_data_wrapper(void) { if (nullptr == _data_wrapper_factory.get()) { clearFileStorage(); } return _data_wrapper_factory->create(); } + bool _textwrap_x = true; bool _textwrap_y = false; bool _textscroll = false; @@ -1220,6 +1283,7 @@ namespace lgfx size_t draw_string(const char *string, int32_t x, int32_t y, textdatum_t datum, const IFont* font = nullptr); int32_t text_width(const char *string, const IFont* font, FontMetrics* metrics); bool load_font(lgfx::DataWrapper* data); + bool load_font_with_path(const char *path); static void tmpBeginTransaction(LGFXBase* lgfx) { diff --git a/src/lgfx/v1/LGFX_Sprite.cpp b/src/lgfx/v1/LGFX_Sprite.cpp index 496f283..069b77b 100644 --- a/src/lgfx/v1/LGFX_Sprite.cpp +++ b/src/lgfx/v1/LGFX_Sprite.cpp @@ -680,6 +680,107 @@ namespace lgfx } } +//---------------------------------------------------------------------------- + + bool LGFX_Sprite::create_from_bmp_file(DataWrapper* data, const char *path) { + data->need_transaction = false; + bool res = false; + if (data->open(path)) { + res = createFromBmp(data); + data->close(); + } + return res; + } + + bool LGFX_Sprite::createFromBmp(DataWrapper* data) + { + bitmap_header_t bmpdata; + + if (!bmpdata.load_bmp_header(data) + || ( bmpdata.biCompression > 3)) { + return false; + } + uint32_t seekOffset = bmpdata.bfOffBits; + uint_fast16_t bpp = bmpdata.biBitCount; // 24 bcBitCount 24=RGB24bit + setColorDepth(bpp < 32 ? bpp : 24); + uint32_t w = bmpdata.biWidth; + int32_t h = bmpdata.biHeight; // bcHeight Image height (pixels) + if (!createSprite(w, h)) return false; + + //If the value of Height is positive, the image data is from bottom to top + //If the value of Height is negative, the image data is from top to bottom. + int32_t flow = (h < 0) ? 1 : -1; + int32_t y = 0; + if (h < 0) h = -h; + else y = h - 1; + + if (bpp <= 8) { + if (!_palette) createPalette(); + uint_fast16_t palettecount = 1 << bpp; + argb8888_t *palette = (argb8888_t*)alloca(sizeof(argb8888_t*) * palettecount); + data->seek(bmpdata.biSize + 14); + data->read((uint8_t*)palette, (palettecount * sizeof(argb8888_t))); // load palette + for (uint_fast16_t i = 0; i < _palette_count; ++i) + { + _palette.img24()[i].set(color_convert(palette[i].get())); + } + } + + data->seek(seekOffset); + + auto bitwidth = _panel_sprite._bitwidth; + + size_t buffersize = ((w * bpp + 31) >> 5) << 2; // readline 4Byte align. + auto lineBuffer = (uint8_t*)alloca(buffersize); + if (bpp <= 8) { + do { + if (bmpdata.biCompression == 1) { + bmpdata.load_bmp_rle8(data, lineBuffer, w); + } else + if (bmpdata.biCompression == 2) { + bmpdata.load_bmp_rle4(data, lineBuffer, w); + } else { + data->read(lineBuffer, buffersize); + } + memcpy(&_img8[y * bitwidth * bpp >> 3], lineBuffer, (w * bpp + 7) >> 3); + y += flow; + } while (--h); + } else if (bpp == 16) { + do { + data->read(lineBuffer, buffersize); + auto img = (uint16_t*)(&_img8[y * bitwidth * bpp >> 3]); + y += flow; + for (size_t i = 0; i < w; ++i) + { + img[i] = (lineBuffer[i << 1] << 8) + lineBuffer[(i << 1) + 1]; + } + } while (--h); + } else if (bpp == 24) { + do { + data->read(lineBuffer, buffersize); + auto img = &_img8[y * bitwidth * bpp >> 3]; + y += flow; + for (size_t i = 0; i < w; ++i) { + img[i * 3 ] = lineBuffer[i * 3 + 2]; + img[i * 3 + 1] = lineBuffer[i * 3 + 1]; + img[i * 3 + 2] = lineBuffer[i * 3 ]; + } + } while (--h); + } else if (bpp == 32) { + do { + data->read(lineBuffer, buffersize); + auto img = &_img8[y * bitwidth * 3]; + y += flow; + for (size_t i = 0; i < w; ++i) { + img[i * 3 ] = lineBuffer[(i << 2) + 2]; + img[i * 3 + 1] = lineBuffer[(i << 2) + 1]; + img[i * 3 + 2] = lineBuffer[(i << 2) + 0]; + } + } while (--h); + } + return true; + } + //---------------------------------------------------------------------------- } } diff --git a/src/lgfx/v1/LGFX_Sprite.hpp b/src/lgfx/v1/LGFX_Sprite.hpp index dfc7ecf..60f3892 100644 --- a/src/lgfx/v1/LGFX_Sprite.hpp +++ b/src/lgfx/v1/LGFX_Sprite.hpp @@ -194,49 +194,22 @@ namespace lgfx return _img; } -#if defined (SdFat_h) - #if SD_FAT_VERSION >= 20102 - #define LGFX_SDFAT_TYPE SdBase - #else - #define LGFX_SDFAT_TYPE SdBase - #endif - - inline void createFromBmp(LGFX_SDFAT_TYPE &fs, const char *path) { createFromBmpFile(fs, path); } - void createFromBmpFile(LGFX_SDFAT_TYPE &fs, const char *path) { - SdFatWrapper file; - file.setFS(fs); - createFromBmpFile(&file, path); - } - - #undef LGFX_SDFAT_TYPE -#endif + bool createFromBmp(DataWrapper* data); -#if defined (ARDUINO) - #if defined (FS_H) || defined (__SEEED_FS__) - - inline void createFromBmp(fs::FS &fs, const char *path) { createFromBmpFile(fs, path); } - void createFromBmpFile(fs::FS &fs, const char *path) { - FileWrapper file; - file.setFS(fs); - createFromBmpFile(&file, path); + bool createFromBmp(const uint8_t *bmp_data, uint32_t bmp_len = ~0u) { + PointerWrapper data (bmp_data, bmp_len); + return createFromBmp(&data); } - #endif - -#elif defined (ESP_PLATFORM) || defined(__SAMD51_HARMONY__) || defined(stdin) // ESP-IDF, Harmony, stdio - - void createFromBmpFile(const char *path) { - FileWrapper file; - createFromBmpFile(&file, path); + template + bool createFromBmpFile(T &fs, const char *path) + { + DataWrapperT data { fs }; + return create_from_bmp_file(&data, path); } -#endif - - void createFromBmp(const uint8_t *bmp_data, uint32_t bmp_len = ~0u) { - PointerWrapper data; - data.set(bmp_data, bmp_len); - create_from_bmp(&data); - } + template + bool createFromBmp(T &fs, const char *path) { return createFromBmpFile(fs, path); } bool createPalette(void) { @@ -437,102 +410,7 @@ namespace lgfx return true; } - void createFromBmpFile(DataWrapper* file, const char *path) { - file->need_transaction = false; - if (file->open(path)) { - create_from_bmp(file); - file->close(); - } - } - - bool create_from_bmp(DataWrapper* data) - { - bitmap_header_t bmpdata; - - if (!bmpdata.load_bmp_header(data) - || ( bmpdata.biCompression > 3)) { - return false; - } - uint32_t seekOffset = bmpdata.bfOffBits; - uint_fast16_t bpp = bmpdata.biBitCount; // 24 bcBitCount 24=RGB24bit - setColorDepth(bpp < 32 ? bpp : 24); - uint32_t w = bmpdata.biWidth; - int32_t h = bmpdata.biHeight; // bcHeight Image height (pixels) - if (!createSprite(w, h)) return false; - - //If the value of Height is positive, the image data is from bottom to top - //If the value of Height is negative, the image data is from top to bottom. - int32_t flow = (h < 0) ? 1 : -1; - int32_t y = 0; - if (h < 0) h = -h; - else y = h - 1; - - if (bpp <= 8) { - if (!_palette) createPalette(); - uint_fast16_t palettecount = 1 << bpp; - argb8888_t *palette = (argb8888_t*)alloca(sizeof(argb8888_t*) * palettecount); - data->seek(bmpdata.biSize + 14); - data->read((uint8_t*)palette, (palettecount * sizeof(argb8888_t))); // load palette - for (uint_fast16_t i = 0; i < _palette_count; ++i) - { - _palette.img24()[i].set(color_convert(palette[i].get())); - } - } - - data->seek(seekOffset); - - auto bitwidth = _panel_sprite._bitwidth; - - size_t buffersize = ((w * bpp + 31) >> 5) << 2; // readline 4Byte align. - auto lineBuffer = (uint8_t*)alloca(buffersize); - if (bpp <= 8) { - do { - if (bmpdata.biCompression == 1) { - bmpdata.load_bmp_rle8(data, lineBuffer, w); - } else - if (bmpdata.biCompression == 2) { - bmpdata.load_bmp_rle4(data, lineBuffer, w); - } else { - data->read(lineBuffer, buffersize); - } - memcpy(&_img8[y * bitwidth * bpp >> 3], lineBuffer, (w * bpp + 7) >> 3); - y += flow; - } while (--h); - } else if (bpp == 16) { - do { - data->read(lineBuffer, buffersize); - auto img = (uint16_t*)(&_img8[y * bitwidth * bpp >> 3]); - y += flow; - for (size_t i = 0; i < w; ++i) - { - img[i] = (lineBuffer[i << 1] << 8) + lineBuffer[(i << 1) + 1]; - } - } while (--h); - } else if (bpp == 24) { - do { - data->read(lineBuffer, buffersize); - auto img = &_img8[y * bitwidth * bpp >> 3]; - y += flow; - for (size_t i = 0; i < w; ++i) { - img[i * 3 ] = lineBuffer[i * 3 + 2]; - img[i * 3 + 1] = lineBuffer[i * 3 + 1]; - img[i * 3 + 2] = lineBuffer[i * 3 ]; - } - } while (--h); - } else if (bpp == 32) { - do { - data->read(lineBuffer, buffersize); - auto img = &_img8[y * bitwidth * 3]; - y += flow; - for (size_t i = 0; i < w; ++i) { - img[i * 3 ] = lineBuffer[(i << 2) + 2]; - img[i * 3 + 1] = lineBuffer[(i << 2) + 1]; - img[i * 3 + 2] = lineBuffer[(i << 2) + 0]; - } - } while (--h); - } - return true; - } + bool create_from_bmp_file(DataWrapper* data, const char *path); void push_sprite(LovyanGFX* dst, int32_t x, int32_t y, uint32_t transp = pixelcopy_t::NON_TRANSP) { @@ -561,7 +439,6 @@ namespace lgfx } RGBColor* getPalette_impl(void) const override { return _palette.img24(); } - }; //---------------------------------------------------------------------------- diff --git a/src/lgfx/v1/gitTagVersion.h b/src/lgfx/v1/gitTagVersion.h index 39764c8..820ea54 100644 --- a/src/lgfx/v1/gitTagVersion.h +++ b/src/lgfx/v1/gitTagVersion.h @@ -1,4 +1,4 @@ #define LGFX_VERSION_MAJOR 1 #define LGFX_VERSION_MINOR 1 -#define LGFX_VERSION_PATCH 10 +#define LGFX_VERSION_PATCH 11 #define LOVYANGFX_VERSION F( LGFX_VERSION_MAJOR "." LGFX_VERSION_MINOR "." LGFX_VERSION_PATCH ) diff --git a/src/lgfx/v1/lgfx_filesystem_support.hpp b/src/lgfx/v1/lgfx_filesystem_support.hpp index 4cecb41..a100737 100644 --- a/src/lgfx/v1/lgfx_filesystem_support.hpp +++ b/src/lgfx/v1/lgfx_filesystem_support.hpp @@ -57,59 +57,35 @@ namespace lgfx using Base::drawJpg; using Base::drawPng; using Base::drawQoi; + using Base::drawBmpFile; + using Base::drawJpgFile; + using Base::drawPngFile; + using Base::drawQoiFile; using Base::loadFont; #if defined (ARDUINO) - #if defined (FS_H) || defined (__SEEED_FS__) || defined (__LITTLEFS_H) || defined (_LiffleFS_H_) || defined (SDFS_H) - /// load vlw fontdata from filesystem. - bool loadFont(const char *path, fs::FS &fs -#if defined (_SD_H_) - = SD -#elif defined (_SPIFFS_H_) - = SPIFFS -#elif defined (__LITTLEFS_H) || defined (_LiffleFS_H_) - = LittleFS -#elif defined SDFS_H - = SDFS -#endif - ) - { - init_font_file(fs); - return load_font_with_path(path); - } - - bool loadFont(fs::FS &fs, const char *path) - { - init_font_file(fs); - return load_font_with_path(path); - } + #if defined (FS_H) #define LGFX_FUNCTION_GENERATOR(drawImg, draw_img) \ - inline bool drawImg##File(fs::FS &fs, const char *path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ - { FileWrapper file(fs); \ - bool res = this->drawImg##File(&file, path, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ - file.close(); \ - return res; \ - } \ - inline bool drawImg##File(fs::FS &fs, fs::File *file, int32_t x=0, int32_t y=0, int32_t maxWidth=0, int32_t maxHeight=0, int32_t offX=0, int32_t offY=0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ + template \ + inline bool drawImg##File(T &fs, fs::File *file, int32_t x=0, int32_t y=0, int32_t maxWidth=0, int32_t maxHeight=0, int32_t offX=0, int32_t offY=0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ { \ - FileWrapper data(fs, file); \ + DataWrapperT data { fs, file }; \ bool res = this->draw_img(&data, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ data.close(); \ return res; \ } \ - inline bool drawImg##File(fs::FS &fs, const String& path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ - { \ - return drawImg##File(fs, path.c_str(), x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ - } \ - inline bool drawImg(fs::File *dataSource, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ + inline bool drawImg(fs::File *file, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ { \ - StreamWrapper data; \ - data.set(dataSource); \ - data.need_transaction = true; \ + DataWrapperT data { file }; \ return this->draw_img(&data, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ } \ + template \ + inline bool drawImg##File(T &fs, const String& path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ + { \ + return drawImg##File(fs, path.c_str(), x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ + } LGFX_FUNCTION_GENERATOR(drawBmp, draw_bmp) LGFX_FUNCTION_GENERATOR(drawJpg, draw_jpg) @@ -122,7 +98,6 @@ namespace lgfx { return drawBmpFile(fs, path, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); } - [[deprecated("use float scale")]] inline bool drawJpgFile(fs::FS &fs, const char *path, int32_t x, int32_t y, int32_t maxWidth, int32_t maxHeight, int32_t offX, int32_t offY, jpeg_div::jpeg_div_t scale) { @@ -140,7 +115,7 @@ namespace lgfx } #endif - +/* #if defined (__STORAGE_H__) // for SPRESENSE /// load vlw fontdata from filesystem. @@ -211,71 +186,7 @@ namespace lgfx } #endif - - #if defined (SdFat_h) - #if SD_FAT_VERSION >= 20102 - #define LGFX_SDFAT_TYPE SdBase - #else - #define LGFX_SDFAT_TYPE SdBase - #endif - - bool loadFont(const char *path, LGFX_SDFAT_TYPE &fs) - { - init_font_file(fs); - return load_font_with_path(path); - } - - bool loadFont(LGFX_SDFAT_TYPE &fs, const char *path) - { - init_font_file(fs); - return load_font_with_path(path); - } - - #define LGFX_FUNCTION_GENERATOR(drawImg, draw_img) \ - inline bool drawImg##File(LGFX_SDFAT_TYPE &fs, const char *path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ - { \ - SdFatWrapper file(fs); \ - bool res = this->drawImg##File(&file, path, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ - file.close(); \ - return res; \ - } \ - inline bool drawImg##File(LGFX_SDFAT_TYPE &fs, FsFile *file, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ - { \ - SdFatWrapper data(fs, file); \ - bool res = this->draw_img(&data, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ - data.close(); \ - return res; \ - } \ - inline bool drawImg##File(LGFX_SDFAT_TYPE &fs, const String& path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ - { \ - return drawImg##File(fs, path.c_str(), x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ - } \ - - LGFX_FUNCTION_GENERATOR(drawBmp, draw_bmp) - LGFX_FUNCTION_GENERATOR(drawJpg, draw_jpg) - LGFX_FUNCTION_GENERATOR(drawPng, draw_png) - LGFX_FUNCTION_GENERATOR(drawQoi, draw_qoi) - - #undef LGFX_FUNCTION_GENERATOR - - inline bool drawBmp(LGFX_SDFAT_TYPE &fs, const char *path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) - { - return drawBmpFile(fs, path, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); - } - [[deprecated("use float scale")]] - inline bool drawJpgFile(LGFX_SDFAT_TYPE &fs, const char *path, int32_t x, int32_t y, int32_t maxWidth, int32_t maxHeight, int32_t offX, int32_t offY, jpeg_div::jpeg_div_t scale) - { - return drawJpgFile(fs, path, x, y, maxWidth, maxHeight, offX, offY, 1.0f / (1 << scale)); - } - [[deprecated("use float scale")]] - inline bool drawJpgFile(LGFX_SDFAT_TYPE &fs, FsFile *file, int32_t x, int32_t y, int32_t maxWidth, int32_t maxHeight, int32_t offX, int32_t offY, jpeg_div::jpeg_div_t scale) - { - return drawJpgFile(fs, file, x, y, maxWidth, maxHeight, offX, offY, 1.0f / (1 << scale)); - } - - #undef LGFX_SDFAT_TYPE - #endif - +//*/ #if defined (Stream_h) || defined ARDUINO_ARCH_RP2040 // RP2040 has no defines for builtin Stream API #define LGFX_FUNCTION_GENERATOR(drawImg, draw_img) \ @@ -351,7 +262,7 @@ namespace lgfx #endif #endif - +/* #elif defined (ESP_PLATFORM) || defined(__SAMD51_HARMONY__) || defined(stdin) // ESP-IDF, Harmony, stdio #define LGFX_FUNCTION_GENERATOR(drawImg) \ @@ -379,7 +290,7 @@ namespace lgfx init_font_file(); return load_font_with_path(path); } - +//*/ #endif #define LGFX_URL_MAXLENGTH 2083 @@ -771,28 +682,6 @@ namespace lgfx #undef LGFX_URL_MAXLENGTH - #define LGFX_FUNCTION_GENERATOR(drawImg, draw_img) \ - bool drawImg##File(DataWrapper* file, const char *path, int32_t x = 0, int32_t y = 0, int32_t maxWidth = 0, int32_t maxHeight = 0, int32_t offX = 0, int32_t offY = 0, float scale_x = 1.0f, float scale_y = 0.0f, datum_t datum = datum_t::top_left) \ - { \ - bool res = false; \ - this->prepareTmpTransaction(file); \ - file->preRead(); \ - if (file->open(path)) \ - { \ - res = this->draw_img(file, x, y, maxWidth, maxHeight, offX, offY, scale_x, scale_y, datum); \ - file->close(); \ - } \ - file->postRead(); \ - return res; \ - } \ - - LGFX_FUNCTION_GENERATOR(drawBmp, draw_bmp) - LGFX_FUNCTION_GENERATOR(drawJpg, draw_jpg) - LGFX_FUNCTION_GENERATOR(drawPng, draw_png) - LGFX_FUNCTION_GENERATOR(drawQoi, draw_qoi) - - #undef LGFX_FUNCTION_GENERATOR - private: template @@ -808,40 +697,6 @@ namespace lgfx this->unloadFont(); this->_font_file.reset(new T()); } - - bool load_font_with_path(const char *path) - { - this->unloadFont(); - - if (this->_font_file.get() == nullptr) return false; - //if (this->_font_file == nullptr) { init_font_file(SD); } - - this->prepareTmpTransaction(this->_font_file.get()); - this->_font_file->preRead(); - - bool result = this->_font_file->open(path); - if (!result) - { - size_t alloclen = strlen(path) + 8; - auto filename = (char*)alloca(alloclen); - memset(filename, 0, alloclen); - filename[0] = '/'; - - strcpy(&filename[1], &path[(path[0] == '/') ? 1 : 0]); - int len = strlen(filename); - if (memcmp(&filename[len - 4], ".vlw", 4)) - { - strcpy(&filename[len], ".vlw"); - } - result = this->_font_file->open(filename); - } - - if (result) { - result = this->load_font(this->_font_file.get()); - } - this->_font_file->postRead(); - return result; - } }; //---------------------------------------------------------------------------- diff --git a/src/lgfx/v1/misc/DataWrapper.hpp b/src/lgfx/v1/misc/DataWrapper.hpp index 376f6c7..dbe8c8a 100644 --- a/src/lgfx/v1/misc/DataWrapper.hpp +++ b/src/lgfx/v1/misc/DataWrapper.hpp @@ -22,6 +22,7 @@ Original Source: #endif #include +#include #include #include "../../utility/pgmspace.h" @@ -44,8 +45,6 @@ namespace lgfx constexpr DataWrapper(void) = default; virtual ~DataWrapper(void) = default; - bool need_transaction = false; - uint8_t read8(void) { uint8_t result; @@ -83,12 +82,80 @@ namespace lgfx LGFXBase* parent = nullptr; void (*fp_pre_read )(LGFXBase*) = nullptr; void (*fp_post_read)(LGFXBase*) = nullptr; + bool need_transaction = false; + }; + +//---------------------------------------------------------------------------- + + template + struct DataWrapperT : public DataWrapper { + DataWrapperT(void) : DataWrapper() {} + DataWrapperT(void*) : DataWrapper() {} + }; + + struct DataWrapperFactory { + virtual DataWrapper* create(void) = 0; + virtual ~DataWrapperFactory() {}; + }; + +//---------------------------------------------------------------------------- + +#if defined (__FILE_defined) || defined (_FILE_DEFINED) || defined (_FSTDIO) + template <> + struct DataWrapperT : public DataWrapper + { + DataWrapperT(FILE* fp = nullptr) : DataWrapper() , _fp { fp } + { + need_transaction = true; + } +#if defined (__STDC_WANT_SECURE_LIB__) + bool open(const char* path) override { + while (0 != fopen_s(&_fp, path, "rb") && path[0] == '/') + { ++path; } + return _fp; + } +#else + bool open(const char* path) override { + while (nullptr == (_fp = fopen(path, "rb")) && path[0] == '/') + { ++path; } + return _fp; + } +#endif + int read(uint8_t *buf, uint32_t len) override { return fread((char*)buf, 1, len, _fp); } + void skip(int32_t offset) override { seek(offset, SEEK_CUR); } + bool seek(uint32_t offset) override { return seek(offset, SEEK_SET); } + bool seek(uint32_t offset, int origin) { return fseek(_fp, offset, origin); } + void close(void) override { if (_fp) { fclose(_fp); _fp = nullptr; } } + int32_t tell(void) override { return ftell(_fp); } + protected: + FILE* _fp; + }; + + template <> + struct DataWrapperT : public DataWrapperT + { + DataWrapperT(void) : DataWrapperT() {} }; +#else + template <> + struct DataWrapperT : public DataWrapper + { + DataWrapperT(void) : DataWrapper() { } + int read(uint8_t *buf, uint32_t len) override { return false; } + void skip(int32_t offset) override { } + bool seek(uint32_t offset) override { return false; } + bool seek(uint32_t offset, int origin) { return false; } + void close(void) override { } + int32_t tell(void) override { return 0; } + }; +#endif //---------------------------------------------------------------------------- struct PointerWrapper : public DataWrapper { + PointerWrapper() : DataWrapper{} , _ptr { nullptr }, _index { 0 }, _length { 0 } {}; + PointerWrapper(const uint8_t* src, uint32_t length = ~0) : DataWrapper{}, _ptr { src }, _index { 0 }, _length { length } {} void set(const uint8_t* src, uint32_t length = ~0) { _ptr = src; _length = length; _index = 0; } int read(uint8_t *buf, uint32_t len) override { if (len > _length - _index) { len = _length - _index; } @@ -102,9 +169,9 @@ namespace lgfx int32_t tell(void) override { return _index; } protected: - const uint8_t* _ptr = nullptr; - uint32_t _index = 0; - uint32_t _length = 0; + const uint8_t* _ptr; + uint32_t _index; + uint32_t _length; }; //---------------------------------------------------------------------------- @@ -116,23 +183,52 @@ namespace lgfx #define LGFX_SDFAT_TYPE SdBase #endif - struct SdFatWrapper : public DataWrapper + template <> + struct DataWrapperT : public DataWrapper + { + DataWrapperT(FsFile* fp = nullptr) : DataWrapper{}, _fp { fp } { need_transaction = true; } + int read(uint8_t *buf, uint32_t len) override { uint32_t a = _fp->available(); return _fp->read(buf, a < len ? a : len); } + void skip(int32_t offset) override { _fp->seekCur(offset); } + bool seek(uint32_t offset) override { return _fp->seekSet(offset); } + void close(void) override { if (_fp) { _fp->close(); _fp = nullptr; } } + int32_t tell(void) override { return _fp->position(); } + protected: + FsFile *_fp; + }; + + template <> + struct DataWrapperT : public DataWrapperT { - SdFatWrapper() : DataWrapper() + DataWrapperT(LGFX_SDFAT_TYPE *fs, FsFile* fp = nullptr) : DataWrapperT{ fp }, _fs { fs } {} + bool open(const char* path) override { - need_transaction = true; - _fs = nullptr; - _fp = nullptr; + _file = _fs->open(path, O_RDONLY); + _fp = &_file; + return _file; } - + protected: LGFX_SDFAT_TYPE *_fs; - FsFile *_fp; FsFile _file; + }; + + template <> + struct DataWrapperT : public DataWrapperT { + DataWrapperT(SdFs* fs, FsFile* fp = nullptr) : DataWrapperT(fs, fp) {} + }; + + struct SdFatWrapper : public DataWrapperT + { + SdFatWrapper(LGFX_SDFAT_TYPE &fs, FsFile* fp = nullptr) : DataWrapperT ( &fs, fp ) {} + SdFatWrapper(LGFX_SDFAT_TYPE *fs, FsFile* fp = nullptr) : DataWrapperT ( fs, fp ) {} +/* + SdFatWrapper() : DataWrapperT() + { + _fs = nullptr; + _fp = nullptr; + } - SdFatWrapper(LGFX_SDFAT_TYPE &fs, FsFile* fp = nullptr) : DataWrapper(), _fs(&fs), _fp(fp) { need_transaction = true; } void setFS(LGFX_SDFAT_TYPE &fs) { _fs = &fs; - need_transaction = true; } bool open(LGFX_SDFAT_TYPE &fs, const char* path) @@ -142,25 +238,16 @@ namespace lgfx _fp = &_file; return _file; } - bool open(const char* path) override - { - _file = _fs->open(path, O_RDONLY); - _fp = &_file; - return _file; - } - int read(uint8_t *buf, uint32_t len) override { return _fp->read(buf, std::min(_fp->available(), len)); } - void skip(int32_t offset) override { _fp->seekCur(offset); } - bool seek(uint32_t offset) override { return _fp->seekSet(offset); } - void close(void) override { if (_fp) _fp->close(); } - int32_t tell(void) override { return _fp->position(); } +//*/ }; #undef LGFX_SDFAT_TYPE + #endif //---------------------------------------------------------------------------- -#if ( defined (ARDUINO) && defined (Stream_h) ) || defined ARDUINO_ARCH_RP2040 // RP2040 has no defines for builtin Stream API +#if ( defined (ARDUINO) && defined (Stream_h) ) || defined (ARDUINO_ARCH_RP2040) // RP2040 has no defines for builtin Stream API struct StreamWrapper : public DataWrapper { @@ -210,14 +297,33 @@ namespace lgfx Stream* _stream; uint32_t _index; uint32_t _length = 0; - }; #endif +//---------------------------------------------------------------------------- + + template + struct DataWrapperTFactoryT : public DataWrapperFactory { + DataWrapperTFactoryT(T* fs) : _fs { fs } {} + DataWrapperTFactoryT(T& fs) : _fs { &fs } {} + DataWrapper* create(void) override { return new DataWrapperT(_fs); } + protected: + T* _fs; + }; + + template <> + struct DataWrapperTFactoryT : public DataWrapperFactory { + DataWrapperTFactoryT(void) {} + DataWrapperTFactoryT(void*) {} + DataWrapper* create(void) override { return new DataWrapperT(); } + }; + //---------------------------------------------------------------------------- #undef LGFX_INLINE +//---------------------------------------------------------------------------- + } } diff --git a/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp b/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp index 784e203..8e798e4 100644 --- a/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp +++ b/src/lgfx/v1/platforms/esp32/Bus_SPI.cpp @@ -46,29 +46,20 @@ Original Source: #if defined (ARDUINO) // Arduino ESP32 #include #include -#else - #include - - #if defined ( CONFIG_IDF_TARGET_ESP32S3 ) - #if __has_include () - #include - #else - #include - #endif - #elif defined ( CONFIG_IDF_TARGET_ESP32S2 ) - #if __has_include () - #include - #else - #include - #endif - #else - #if __has_include () - #include - #else - #include - #endif - #endif #endif +#include + +#if defined ESP_IDF_VERSION_MAJOR && ESP_IDF_VERSION_MAJOR >= 5 + #include // dispatched by core +#elif defined ( CONFIG_IDF_TARGET_ESP32S3 ) && __has_include () + #include // dispatched by config +#elif defined ( CONFIG_IDF_TARGET_ESP32S2 ) && __has_include () + #include // dispatched by config +#elif defined ( CONFIG_IDF_TARGET_ESP32 ) && __has_include () + #include +#else + #include // dispatched by core +#endif #ifndef SPI_PIN_REG #define SPI_PIN_REG SPI_MISC_REG diff --git a/src/lgfx/v1/platforms/esp32/Light_PWM.cpp b/src/lgfx/v1/platforms/esp32/Light_PWM.cpp index cc2d879..b165784 100644 --- a/src/lgfx/v1/platforms/esp32/Light_PWM.cpp +++ b/src/lgfx/v1/platforms/esp32/Light_PWM.cpp @@ -22,6 +22,9 @@ Original Source: #if defined ( ARDUINO ) #include + #if __has_include() + #include + #endif #else #include #endif @@ -40,10 +43,20 @@ namespace lgfx #if defined ( ARDUINO ) +#if defined ESP_ARDUINO_VERSION + #if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) + #define LEDC_USE_IDF_V5 // esp32-arduino core 3.x.x uses the new ledC syntax + #endif +#endif + +#if defined LEDC_USE_IDF_V5 + ledcAttach(_cfg.pin_bl, _cfg.freq, PWM_BITS); + setBrightness(brightness); +#else ledcSetup(_cfg.pwm_channel, _cfg.freq, PWM_BITS); ledcAttachPin(_cfg.pin_bl, _cfg.pwm_channel); setBrightness(brightness); - +#endif #else static ledc_channel_config_t ledc_channel; diff --git a/src/lgfx/v1/platforms/esp32/common.hpp b/src/lgfx/v1/platforms/esp32/common.hpp index 2e7dba5..09c3531 100644 --- a/src/lgfx/v1/platforms/esp32/common.hpp +++ b/src/lgfx/v1/platforms/esp32/common.hpp @@ -133,100 +133,84 @@ namespace lgfx //---------------------------------------------------------------------------- #if defined (ARDUINO) - #if defined (FS_H) + #if defined (_SD_H_) + #define LGFX_FILESYSTEM_SD SD + #endif + #if defined (_LITTLEFS_H_) || defined (__LITTLEFS_H) || defined (_LiffleFS_H_) + #define LGFX_FILESYSTEM_LITTLEFS LittleFS + #endif + #if defined (_SPIFFS_H_) + #define LGFX_FILESYSTEM_SPIFFS SPIFFS + #endif + #if defined (_FFAT_H_) + #define LGFX_FILESYSTEM_FFAT FFat + #endif - struct FileWrapper : public DataWrapper - { -private: -#if defined (_SPIFFS_H_) - bool _check_need_transaction(void) const { return _fs != &SPIFFS; } -#else - bool _check_need_transaction(void) const { return true; } -#endif + #if defined (FS_H) \ + || defined (LGFX_FILESYSTEM_SD) \ + || defined (LGFX_FILESYSTEM_LITTLEFS) \ + || defined (LGFX_FILESYSTEM_SPIFFS) \ + || defined (LGFX_FILESYSTEM_FFAT) -public: - FileWrapper() : DataWrapper() - { -#if defined (_SD_H_) - _fs = &SD; -#elif defined (_SPIFFS_H_) - _fs = &SPIFFS; -#else - _fs = nullptr; -#endif - need_transaction = _check_need_transaction(); - _fp = nullptr; + template <> + struct DataWrapperT : public DataWrapper { + DataWrapperT(fs::File* fp = nullptr) : DataWrapper{}, _fp { fp } { + need_transaction = true; } - - fs::FS* _fs; + int read(uint8_t *buf, uint32_t len) override { return _fp->read(buf, len); } + void skip(int32_t offset) override { _fp->seek(offset, SeekCur); } + bool seek(uint32_t offset) override { return _fp->seek(offset, SeekSet); } + bool seek(uint32_t offset, SeekMode mode) { return _fp->seek(offset, mode); } + void close(void) override { if (_fp) _fp->close(); } + int32_t tell(void) override { return _fp->position(); } +protected: fs::File *_fp; - fs::File _file; - - FileWrapper(fs::FS& fs, fs::File* fp = nullptr) : DataWrapper(), _fs(&fs), _fp(fp) { need_transaction = _check_need_transaction(); } - void setFS(fs::FS& fs) { - _fs = &fs; - need_transaction = _check_need_transaction(); - } + }; - bool open(fs::FS& fs, const char* path) - { - setFS(fs); - return open(path); + template <> + struct DataWrapperT : public DataWrapperT { + DataWrapperT(fs::FS* fs, fs::File* fp = nullptr) : DataWrapperT { fp }, _fs { fs } { +#if defined (LGFX_FILESYSTEM_SD) + need_transaction = (fs == &LGFX_FILESYSTEM_SD); +#endif } bool open(const char* path) override { _file = _fs->open(path, "r"); - _fp = &_file; + DataWrapperT::_fp = &_file; return _file; } - int read(uint8_t *buf, uint32_t len) override { return _fp->read(buf, len); } - void skip(int32_t offset) override { seek(offset, SeekCur); } - bool seek(uint32_t offset) override { return seek(offset, SeekSet); } - bool seek(uint32_t offset, SeekMode mode) { return _fp->seek(offset, mode); } - void close(void) override { if (_fp) _fp->close(); } - int32_t tell(void) override { return _fp->position(); } - }; - #else - // dummy - struct FileWrapper : public DataWrapper - { - FileWrapper() : DataWrapper() - { - need_transaction = true; - } - void* _fp; - - template - void setFS(T& fs) {} - - bool open(const char* path, const char* mode) { return false; } - int read(uint8_t *buf, uint32_t len) override { return false; } - void skip(int32_t offset) override { } - bool seek(uint32_t offset) override { return false; } - bool seek(uint32_t offset, int origin) { return false; } - void close() override { } - int32_t tell(void) override { return 0; } - }; - - #endif -#else // ESP-IDF - struct FileWrapper : public DataWrapper - { - FileWrapper() : DataWrapper() - { - need_transaction = true; - } - FILE* _fp; - bool open(const char* path) override { return (_fp = fopen(path, "r")); } - int read(uint8_t *buf, uint32_t len) override { return fread((char*)buf, 1, len, _fp); } - void skip(int32_t offset) override { seek(offset, SEEK_CUR); } - bool seek(uint32_t offset) override { return seek(offset, SEEK_SET); } - bool seek(uint32_t offset, int origin) { return fseek(_fp, offset, origin); } - void close() override { if (_fp) fclose(_fp); } - int32_t tell(void) override { return ftell(_fp); } +protected: + fs::FS* _fs; + fs::File _file; }; + #if defined (LGFX_FILESYSTEM_SD) + template <> + struct DataWrapperT : public DataWrapperT { + DataWrapperT(fs::FS* fs, fs::File* fp = nullptr) : DataWrapperT(fs, fp) {} + }; + #endif + #if defined (LGFX_FILESYSTEM_SPIFFS) + template <> + struct DataWrapperT : public DataWrapperT { + DataWrapperT(fs::FS* fs, fs::File* fp = nullptr) : DataWrapperT(fs, fp) {} + }; + #endif + #if defined (LGFX_FILESYSTEM_LITTLEFS) + template <> + struct DataWrapperT : public DataWrapperT { + DataWrapperT(fs::FS* fs, fs::File* fp = nullptr) : DataWrapperT(fs, fp) {} + }; + #endif + #if defined (LGFX_FILESYSTEM_FFAT) + template <> + struct DataWrapperT : public DataWrapperT { + DataWrapperT(fs::FS* fs, fs::File* fp = nullptr) : DataWrapperT(fs, fp) {} + }; + #endif + #endif #endif //----------------------------------------------------------------------------