Merge branch 'master' into freertos
This commit is contained in:
commit
03914d2d2b
@ -51,5 +51,9 @@
|
||||
#define GDISP_NEED_IMAGE_JPG FALSE
|
||||
#define GDISP_NEED_IMAGE_PNG FALSE
|
||||
|
||||
#define GFX_USE_GFILE TRUE
|
||||
#define GFILE_NEED_ROMFS TRUE
|
||||
//#define GFILE_NEED_NATIVEFS TRUE
|
||||
|
||||
#endif /* _GFXCONF_H */
|
||||
|
||||
|
@ -29,15 +29,12 @@
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define USE_MEMORY_FILE TRUE // Can be true or false for Win32
|
||||
#else
|
||||
#define USE_MEMORY_FILE TRUE // Non-Win32 - use the compiled in image
|
||||
#endif
|
||||
|
||||
#if USE_MEMORY_FILE
|
||||
#include "test-pal8.h"
|
||||
#endif
|
||||
/**
|
||||
* The image file must be stored on a GFILE file-system.
|
||||
* Use either GFILE_NEED_NATIVEFS or GFILE_NEED_ROMFS (or both).
|
||||
*
|
||||
* The ROMFS uses the file "romfs_files.h" to describe the set of files in the ROMFS.
|
||||
*/
|
||||
|
||||
static gdispImage myImage;
|
||||
|
||||
@ -52,13 +49,7 @@ int main(void) {
|
||||
sheight = gdispGetHeight();
|
||||
|
||||
// Set up IO for our image
|
||||
#if USE_MEMORY_FILE
|
||||
gdispImageSetMemoryReader(&myImage, test_pal8);
|
||||
#else
|
||||
gdispImageSetSimulFileReader(&myImage, "test-pal8.bmp");
|
||||
#endif
|
||||
|
||||
gdispImageOpen(&myImage);
|
||||
gdispImageOpenFile(&myImage, "test-pal8.bmp");
|
||||
gdispImageDraw(&myImage, 0, 0, swidth, sheight, 0, 0);
|
||||
gdispImageClose(&myImage);
|
||||
|
||||
|
7
demos/modules/gdisp/images/romfs_files.h
Normal file
7
demos/modules/gdisp/images/romfs_files.h
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This file contains the list of files for the ROMFS.
|
||||
*
|
||||
* The files have been converted using...
|
||||
* file2c -dbcs infile outfile
|
||||
*/
|
||||
#include "romfs_testpal8.h"
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
* This file was generated from "test-pal8.bmp" using...
|
||||
*
|
||||
* file2c -cs test-pal8.bmp test-pal8.h
|
||||
* file2c -dcs test-pal8.bmp romfs_testpal8.h
|
||||
*
|
||||
*/
|
||||
static const unsigned char test_pal8[] = {
|
||||
static const char test_pal8[] = {
|
||||
0x42, 0x4D, 0x26, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x04, 0x00, 0x00, 0x28, 0x00,
|
||||
0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0xFC, 0x00,
|
||||
@ -585,3 +585,9 @@ static const unsigned char test_pal8[] = {
|
||||
0xC3, 0x93, 0xC4, 0x93, 0xC3, 0x93, 0xC4, 0x93, 0xC3, 0x93, 0xC4, 0x93, 0xC3, 0x93, 0xC4, 0x93,
|
||||
0xC3, 0x93, 0xC4, 0x93, 0xC3, 0x00,
|
||||
};
|
||||
|
||||
#ifdef ROMFS_DIRENTRY_HEAD
|
||||
static const ROMFS_DIRENTRY test_pal8_dir = { 0, 0, ROMFS_DIRENTRY_HEAD, "test-pal8.bmp", 9254, test_pal8 };
|
||||
#undef ROMFS_DIRENTRY_HEAD
|
||||
#define ROMFS_DIRENTRY_HEAD &test_pal8_dir
|
||||
#endif
|
@ -51,5 +51,8 @@
|
||||
#define GDISP_NEED_IMAGE_JPG FALSE
|
||||
#define GDISP_NEED_IMAGE_PNG FALSE
|
||||
|
||||
#define GFX_USE_GFILE TRUE
|
||||
#define GFILE_NEED_ROMFS TRUE
|
||||
|
||||
#endif /* _GFXCONF_H */
|
||||
|
||||
|
@ -29,23 +29,20 @@
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
/**
|
||||
* The image file must be stored on a GFILE file-system.
|
||||
* Use either GFILE_NEED_NATIVEFS or GFILE_NEED_ROMFS (or both).
|
||||
*
|
||||
* The ROMFS uses the file "romfs_files.h" to describe the set of files in the ROMFS.
|
||||
*/
|
||||
|
||||
#define USE_IMAGE_CACHE FALSE // Only if you want to get performance at the expense of RAM
|
||||
#define MY_BG_COLOR RGB2COLOR(220, 220, 255) // Pale blue so we can see the transparent parts
|
||||
|
||||
#ifdef WIN32
|
||||
#define USE_MEMORY_FILE TRUE // Can be true or false for Win32
|
||||
#else
|
||||
#define USE_MEMORY_FILE TRUE // Non-Win32 - use the compiled in image
|
||||
#endif
|
||||
static gdispImage myImage;
|
||||
|
||||
#define SHOW_ERROR(color) gdispFillArea(errx, erry, errcx, errcy, color)
|
||||
|
||||
#if USE_MEMORY_FILE
|
||||
#include "testanim.h"
|
||||
#endif
|
||||
|
||||
static gdispImage myImage;
|
||||
|
||||
/**
|
||||
* This demo display the animated gif (either directly from a file or from a
|
||||
* file encoded in flash.
|
||||
@ -75,13 +72,8 @@ int main(void) {
|
||||
errcy = sheight;
|
||||
|
||||
// Set up IO for our image
|
||||
#if USE_MEMORY_FILE
|
||||
gdispImageSetMemoryReader(&myImage, testanim);
|
||||
#else
|
||||
gdispImageSetFileReader(&myImage, "testanim.gif");
|
||||
#endif
|
||||
if (!(gdispImageOpenFile(&myImage, "testanim.gif") & GDISP_IMAGE_ERR_UNRECOVERABLE)) {
|
||||
|
||||
if (gdispImageOpen(&myImage) == GDISP_IMAGE_ERR_OK) {
|
||||
gdispImageSetBgColor(&myImage, MY_BG_COLOR);
|
||||
// Adjust the error indicator area if necessary
|
||||
if (myImage.width > errx && myImage.height < sheight) {
|
||||
|
7
demos/modules/gdisp/images_animated/romfs_files.h
Normal file
7
demos/modules/gdisp/images_animated/romfs_files.h
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This file contains the list of files for the ROMFS.
|
||||
*
|
||||
* The files have been converted using...
|
||||
* file2c -dbcs infile outfile
|
||||
*/
|
||||
#include "romfs_testanim.h"
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
* This file was generated from "testanim.gif" using...
|
||||
*
|
||||
* file2c -cs testanim.gif testanim.h
|
||||
* file2c -dcs testanim.gif romfs_testanim.h
|
||||
*
|
||||
*/
|
||||
static const unsigned char testanim[] = {
|
||||
static const char testanim[] = {
|
||||
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x99, 0x00, 0x73, 0x00, 0xE6, 0x46, 0x00, 0x04, 0x07, 0x00,
|
||||
0x10, 0x0F, 0x04, 0x1D, 0x1E, 0x29, 0x20, 0x23, 0x08, 0x2E, 0x2C, 0x18, 0x31, 0x32, 0x01, 0x2E,
|
||||
0x32, 0x2A, 0x35, 0x37, 0x3B, 0x20, 0x28, 0x42, 0x2B, 0x37, 0x53, 0x3E, 0x41, 0x03, 0x3C, 0x44,
|
||||
@ -565,3 +565,9 @@ static const unsigned char testanim[] = {
|
||||
0xD7, 0x82, 0xFC, 0x87, 0xAE, 0x20, 0x04, 0x10, 0xA0, 0x48, 0xA0, 0x86, 0xCC, 0x05, 0x0C, 0x30,
|
||||
0x87, 0x2C, 0x38, 0x88, 0xED, 0x86, 0x04, 0x02, 0x00, 0x3B,
|
||||
};
|
||||
|
||||
#ifdef ROMFS_DIRENTRY_HEAD
|
||||
static const ROMFS_DIRENTRY testanim_dir = { 0, 0, ROMFS_DIRENTRY_HEAD, "testanim.gif", 8938, testanim };
|
||||
#undef ROMFS_DIRENTRY_HEAD
|
||||
#define ROMFS_DIRENTRY_HEAD &testanim_dir
|
||||
#endif
|
@ -79,6 +79,11 @@
|
||||
#define GWIN_NEED_RADIO TRUE
|
||||
#define GWIN_NEED_LIST TRUE
|
||||
|
||||
/* Features for the GFILE subsystem. */
|
||||
#define GFX_USE_GFILE TRUE
|
||||
#define GFILE_NEED_ROMFS TRUE
|
||||
//#define GFILE_NEED_NATIVEFS TRUE
|
||||
|
||||
/* Features for the GINPUT subsystem. */
|
||||
#define GINPUT_NEED_MOUSE TRUE
|
||||
|
||||
|
@ -28,16 +28,19 @@
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
// include our chibios logo in a .gif format
|
||||
#include "image_chibios.h"
|
||||
#include "image_yesno.h"
|
||||
|
||||
/**
|
||||
* This demo demonstrates many of the GWIN widgets.
|
||||
* On the "Radio" tab try playing with the color radio buttons.
|
||||
* On the "Checkbox" tab try playing with the "Disable All" checkbox.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The image files must be stored on a GFILE file-system.
|
||||
* Use either GFILE_NEED_NATIVEFS or GFILE_NEED_ROMFS (or both).
|
||||
*
|
||||
* The ROMFS uses the file "romfs_files.h" to describe the set of files in the ROMFS.
|
||||
*/
|
||||
|
||||
/* Our custom yellow style */
|
||||
static const GWidgetStyle YellowWidgetStyle = {
|
||||
Yellow, // window background
|
||||
@ -184,15 +187,14 @@ static void createWidgets(void) {
|
||||
wi.g.x = 0+2*(LIST_WIDTH+1); wi.text = "L3"; ghList3 = gwinListCreate(0, &wi, TRUE);
|
||||
gwinListAddItem(ghList3, "Item 0", FALSE); gwinListAddItem(ghList3, "Item 1", FALSE);
|
||||
gwinListAddItem(ghList3, "Item 2", FALSE); gwinListAddItem(ghList3, "Item 3", FALSE);
|
||||
gdispImageSetMemoryReader(&imgYesNo, image_yesno);
|
||||
gdispImageOpen(&imgYesNo);
|
||||
gdispImageOpenFile(&imgYesNo, "image_yesno.gif");
|
||||
gwinListItemSetImage(ghList3, 1, &imgYesNo);
|
||||
gwinListItemSetImage(ghList3, 3, &imgYesNo);
|
||||
|
||||
// Image
|
||||
wi.g.x = ScrWidth-210; wi.g.y = TAB_HEIGHT + 10; wi.g.width = 200; wi.g.height = 200;
|
||||
ghImage1 = gwinImageCreate(0, &wi.g);
|
||||
gwinImageOpenMemory(ghImage1, image_chibios);
|
||||
gwinImageOpenFile(ghImage1, "chibios.bmp");
|
||||
gwinImageCache(ghImage1);
|
||||
|
||||
// Console - we apply some special colors before making it visible
|
||||
|
8
demos/modules/gwin/widgets/romfs_files.h
Normal file
8
demos/modules/gwin/widgets/romfs_files.h
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* This file contains the list of files for the ROMFS.
|
||||
*
|
||||
* The files have been converted using...
|
||||
* file2c -dbcs infile outfile
|
||||
*/
|
||||
#include "romfs_img_chibios.h"
|
||||
#include "romfs_img_yesno.h"
|
@ -1,4 +1,4 @@
|
||||
static const unsigned char image_chibios[] = {
|
||||
static const char image_chibios[] = {
|
||||
0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x74, 0x00, 0x74, 0x00, 0xE7, 0xFE, 0x00, 0x08, 0x07, 0x02,
|
||||
0x00, 0x0A, 0x03, 0x08, 0x07, 0x0E, 0x05, 0x0D, 0x00, 0x00, 0x11, 0x02, 0x03, 0x16, 0x01, 0x09,
|
||||
0x15, 0x00, 0x00, 0x19, 0x03, 0x14, 0x16, 0x06, 0x00, 0x1D, 0x02, 0x07, 0x1C, 0x01, 0x0F, 0x1A,
|
||||
@ -635,3 +635,9 @@ static const unsigned char image_chibios[] = {
|
||||
0xE0, 0x3F, 0x62, 0xE0, 0x07, 0x86, 0xE0, 0x08, 0x96, 0xE0, 0x09, 0xA6, 0xE0, 0x0A, 0xB6, 0xE0,
|
||||
0x0B, 0xC6, 0x60, 0xF0, 0x08, 0x08, 0x00, 0x3B,
|
||||
};
|
||||
|
||||
#ifdef ROMFS_DIRENTRY_HEAD
|
||||
static const ROMFS_DIRENTRY image_chibios_dir = { 0, 0, ROMFS_DIRENTRY_HEAD, "chibios.bmp", 634*16+8, image_chibios };
|
||||
#undef ROMFS_DIRENTRY_HEAD
|
||||
#define ROMFS_DIRENTRY_HEAD &image_chibios_dir
|
||||
#endif
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
* This file was generated from "yesno.gif" using...
|
||||
* This file was generated from "image_yesno.gif" using...
|
||||
*
|
||||
* file2c -bcs image_yesno.gif image_yesno.h
|
||||
* file2c -dcs image_yesno.gif romfs_img_yesno.h
|
||||
*
|
||||
*/
|
||||
static const unsigned char image_yesno[] = {
|
||||
static const char image_yesno[] = {
|
||||
0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x0B, 0x00, 0x2C, 0x00, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xC6, 0x00, 0xC6, 0xFF, 0xC6, 0xCE, 0xFF, 0xCE, 0xFF, 0x08, 0x18, 0xFF, 0xCE, 0xDE, 0xFF,
|
||||
0xDE, 0xDE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
@ -19,3 +19,9 @@ static const unsigned char image_yesno[] = {
|
||||
0x05, 0x35, 0x81, 0x84, 0x86, 0x83, 0x14, 0x8B, 0x07, 0x86, 0x79, 0x8F, 0x82, 0x8F, 0x8E, 0x17,
|
||||
0x8E, 0x62, 0x8B, 0x8C, 0x8A, 0x87, 0x05, 0x11, 0x00, 0x3B,
|
||||
};
|
||||
|
||||
#ifdef ROMFS_DIRENTRY_HEAD
|
||||
static const ROMFS_DIRENTRY image_yesno_dir = { 0, 0, ROMFS_DIRENTRY_HEAD, "image_yesno.gif", 202, image_yesno };
|
||||
#undef ROMFS_DIRENTRY_HEAD
|
||||
#define ROMFS_DIRENTRY_HEAD &image_yesno_dir
|
||||
#endif
|
2
gfx.mk
2
gfx.mk
@ -12,4 +12,4 @@ include $(GFXLIB)/src/gadc/gadc.mk
|
||||
include $(GFXLIB)/src/gaudin/gaudin.mk
|
||||
include $(GFXLIB)/src/gaudout/gaudout.mk
|
||||
include $(GFXLIB)/src/gmisc/gmisc.mk
|
||||
|
||||
include $(GFXLIB)/src/gfile/gfile.mk
|
||||
|
@ -9,6 +9,8 @@
|
||||
/**
|
||||
* Copy this file into your project directory and rename it as gfxconf.h
|
||||
* Edit your copy to turn on the uGFX features you want to use.
|
||||
* The values below are the defaults. You should delete anything
|
||||
* you are leaving as default.
|
||||
*
|
||||
* Please use spaces instead of tabs in this file.
|
||||
*/
|
||||
@ -27,7 +29,7 @@
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GDISP //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
#define GFX_USE_GDISP TRUE
|
||||
#define GFX_USE_GDISP FALSE
|
||||
|
||||
#define GDISP_NEED_AUTOFLUSH FALSE
|
||||
#define GDISP_NEED_TIMERFLUSH FALSE
|
||||
@ -186,6 +188,27 @@
|
||||
#define GINPUT_NEED_DIAL FALSE
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GFILE //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
#define GFX_USE_GFILE FALSE
|
||||
|
||||
#define GFILE_NEED_PRINTG FALSE
|
||||
#define GFILE_NEED_SCANG FALSE
|
||||
#define GFILE_NEED_STRINGS FALSE
|
||||
#define GFILE_NEED_STDIO FALSE
|
||||
#define GFILE_ALLOW_FLOATS FALSE
|
||||
#define GFILE_ALLOW_DEVICESPECIFIC FALSE
|
||||
#define GFILE_MAX_GFILES 3
|
||||
|
||||
#define GFILE_NEED_MEMFS FALSE
|
||||
#define GFILE_NEED_ROMFS FALSE
|
||||
#define GFILE_NEED_RAMFS FALSE
|
||||
#define GFILE_NEED_FATFS FALSE
|
||||
#define GFILE_NEED_NATIVEFS FALSE
|
||||
#define GFILE_NEED_CHBIOSFS FALSE
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GADC //
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -40,6 +40,7 @@ typedef uint16_t gdispImageError;
|
||||
#define GDISP_IMAGE_ERR_UNSUPPORTED (GDISP_IMAGE_ERR_UNRECOVERABLE+3)
|
||||
#define GDISP_IMAGE_ERR_UNSUPPORTED_OK 3
|
||||
#define GDISP_IMAGE_ERR_NOMEMORY (GDISP_IMAGE_ERR_UNRECOVERABLE+4)
|
||||
#define GDISP_IMAGE_ERR_NOSUCHFILE (GDISP_IMAGE_ERR_UNRECOVERABLE+5)
|
||||
|
||||
/**
|
||||
* @brief Image flags
|
||||
@ -103,10 +104,10 @@ typedef struct gdispImage {
|
||||
gdispImageFlags flags; /* @< The image flags */
|
||||
color_t bgcolor; /* @< The default background color */
|
||||
coord_t width, height; /* @< The image dimensions */
|
||||
gdispImageIO io; /* @< The image IO functions */
|
||||
GFILE * f; /* @< The underlying GFILE */
|
||||
#if GDISP_NEED_IMAGE_ACCOUNTING
|
||||
uint32_t memused; /* @< How much RAM is currently allocated */
|
||||
uint32_t maxmemused; /* @< How much RAM has been allocated (maximum) */
|
||||
uint32_t memused; /* @< How much RAM is currently allocated */
|
||||
uint32_t maxmemused; /* @< How much RAM has been allocated (maximum) */
|
||||
#endif
|
||||
const struct gdispImageHandlers * fns; /* @< Don't mess with this! */
|
||||
struct gdispImagePrivate * priv; /* @< Don't mess with this! */
|
||||
@ -116,59 +117,28 @@ typedef struct gdispImage {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Sets the io fields in the image structure to routines
|
||||
* that support reading from an image stored in RAM or Flash.
|
||||
*
|
||||
* @return TRUE if the IO open function succeeds
|
||||
*
|
||||
* @param[in] img The image structure
|
||||
* @param[in] memimage A pointer to the image in RAM or Flash
|
||||
*
|
||||
* @note Always returns TRUE for a Memory Reader
|
||||
/*
|
||||
* Deprecated Functions.
|
||||
*/
|
||||
bool_t gdispImageSetMemoryReader(gdispImage *img, const void *memimage);
|
||||
|
||||
#if GFX_USE_OS_CHIBIOS || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Sets the io fields in the image structure to routines
|
||||
* that support reading from an image stored on a BaseFileStream (eg SDCard).
|
||||
*
|
||||
* @return TRUE if the IO open function succeeds
|
||||
*
|
||||
* @param[in] img The image structure
|
||||
* @param[in] BaseFileStreamPtr A pointer to the (open) BaseFileStream object.
|
||||
*
|
||||
*/
|
||||
bool_t gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr);
|
||||
gdispImageError DEPRECATED("Use gdispImageOpenGFile() instead") gdispImageOpen(gdispImage *img);
|
||||
bool_t DEPRECATED("Use gdispImageOpenMemory() instead") gdispImageSetMemoryReader(gdispImage *img, const void *memimage);
|
||||
#if GFX_USE_OS_CHIBIOS
|
||||
bool_t DEPRECATED("Use gdispImageOpenBaseFileStream() instead") gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr);
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_LINUX || GFX_USE_OS_OSX || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Sets the io fields in the image structure to routines
|
||||
* that support reading from an image stored in Win32 simulators native
|
||||
* file system.
|
||||
* @pre Only available on the Win32 simulator
|
||||
*
|
||||
* @return TRUE if the IO open function succeeds
|
||||
*
|
||||
* @param[in] img The image structure
|
||||
* @param[in] filename The filename to open
|
||||
*
|
||||
*/
|
||||
bool_t gdispImageSetFileReader(gdispImage *img, const char *filename);
|
||||
/* Old definition */
|
||||
#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_LINUX || GFX_USE_OS_OSX
|
||||
bool_t DEPRECATED("Please use gdispImageOpenFile() instead") gdispImageSetFileReader(gdispImage *img, const char *filename);
|
||||
#define gdispImageSetSimulFileReader(img, fname) gdispImageSetFileReader(img, fname)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Open an image ready for drawing
|
||||
* @brief Open an image using an open GFILE and get it ready for drawing
|
||||
* @details Determine the image format and get ready to decode the first image frame
|
||||
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
|
||||
*
|
||||
* @param[in] img The image structure
|
||||
* @param[in] img The image structure
|
||||
* @param[in] f The open GFILE stream.
|
||||
*
|
||||
* @pre The io fields should be filled in before calling gdispImageOpen()
|
||||
* @pre The GFILE must be open for reading.
|
||||
*
|
||||
* @note This determines which decoder to use and then initialises all other fields
|
||||
* in the gdispImage structure.
|
||||
@ -179,17 +149,62 @@ extern "C" {
|
||||
* bit in the error code.
|
||||
* A partial success return code means an image can still be drawn but perhaps with
|
||||
* reduced functionality eg only the first page of a multi-page image.
|
||||
* @note @p gdispImageClose() can be called even after a failure to open the image to ensure
|
||||
* that the IO close routine gets called.
|
||||
* @note @p gdispImageClose() should be called when finished with the image. This will close
|
||||
* the image and its underlying GFILE file. Note that images opened with partial success
|
||||
* (eg GDISP_IMAGE_ERR_UNSUPPORTED_OK)
|
||||
* still need to be closed when you are finished with them.
|
||||
*/
|
||||
gdispImageError gdispImageOpen(gdispImage *img);
|
||||
gdispImageError gdispImageOpenGFile(gdispImage *img, GFILE *f);
|
||||
|
||||
/**
|
||||
* @brief Open an image in a file and get it ready for drawing
|
||||
* @details Determine the image format and get ready to decode the first image frame
|
||||
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
|
||||
*
|
||||
* @pre You must have included the file-system support into GFILE that you want to use.
|
||||
*
|
||||
* @param[in] img The image structure
|
||||
* @param[in] filename The filename to open
|
||||
*
|
||||
* @note This function just opens the GFILE using the filename and passes it to @p gdispImageOpenGFile().
|
||||
*/
|
||||
#define gdispImageOpenFile(img, filename) gdispImageOpenGFile((img), gfileOpen((filename), "rb"))
|
||||
|
||||
/**
|
||||
* @brief Open an image in a ChibiOS basefilestream and get it ready for drawing
|
||||
* @details Determine the image format and get ready to decode the first image frame
|
||||
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
|
||||
*
|
||||
* @pre GFILE_NEED_CHIBIOSFS and GFX_USE_OS_CHIBIOS must be TRUE. This only makes sense on the ChibiOS
|
||||
* operating system.
|
||||
*
|
||||
* @param[in] img The image structure
|
||||
* @param[in] BaseFileStreamPtr A pointer to an open BaseFileStream
|
||||
*
|
||||
* @note This function just opens the GFILE using the basefilestream and passes it to @p gdispImageOpenGFile().
|
||||
*/
|
||||
#define gdispImageOpenBaseFileStream(img, BaseFileStreamPtr) gdispImageOpenGFile((img), gfileOpenBaseFileStream((BaseFileStreamPtr), "rb"))
|
||||
|
||||
/**
|
||||
* @brief Open an image in memory and get it ready for drawing
|
||||
* @details Determine the image format and get ready to decode the first image frame
|
||||
* @return GDISP_IMAGE_ERR_OK (0) on success or an error code.
|
||||
*
|
||||
* @pre GFILE_NEED_MEMFS must be TRUE
|
||||
*
|
||||
* @param[in] img The image structure
|
||||
* @param[in] ptr A pointer to the image bytes in memory
|
||||
*
|
||||
* @note This function just opens the GFILE using the basefilestream and passes it to @p gdispImageOpenGFile().
|
||||
*/
|
||||
#define gdispImageOpenMemory(img, ptr) gdispImageOpenGFile((img), gfileOpenMemory((void *)(ptr), "rb"))
|
||||
|
||||
/**
|
||||
* @brief Close an image and release any dynamically allocated working storage.
|
||||
*
|
||||
* @param[in] img The image structure
|
||||
*
|
||||
* @pre gdispImageOpen() must have returned successfully.
|
||||
* @pre gdispImageOpenFile() must have returned successfully.
|
||||
*
|
||||
* @note Also calls the IO close function (if it hasn't already been called).
|
||||
*/
|
||||
@ -282,94 +297,6 @@ extern "C" {
|
||||
*/
|
||||
delaytime_t gdispImageNext(gdispImage *img);
|
||||
|
||||
#if GDISP_NEED_IMAGE_NATIVE
|
||||
/**
|
||||
* @brief The image drawing routines for a NATIVE format image.
|
||||
*
|
||||
* @note Only use these functions if you absolutely know the format
|
||||
* of the image you are decoding. Generally you should use the
|
||||
* generic functions and it will auto-detect the format.
|
||||
* @note A NATIVE format image is defined as an 8 byte header described below, immediately
|
||||
* followed by the bitmap data. The bitmap data is stored in the native format for
|
||||
* the display controller. If the pixel format specified in the header does not
|
||||
* match the controller native format then the image is rejected.
|
||||
* @note The 8 byte header:
|
||||
* { 'N', 'I', width.hi, width.lo, height.hi, height.lo, format.hi, format.lo }
|
||||
* The format word = GDISP_PIXELFORMAT
|
||||
* @{
|
||||
*/
|
||||
gdispImageError gdispImageOpen_NATIVE(gdispImage *img);
|
||||
void gdispImageClose_NATIVE(gdispImage *img);
|
||||
gdispImageError gdispImageCache_NATIVE(gdispImage *img);
|
||||
gdispImageError gdispGImageDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
|
||||
delaytime_t gdispImageNext_NATIVE(gdispImage *img);
|
||||
/* @} */
|
||||
#endif
|
||||
|
||||
#if GDISP_NEED_IMAGE_GIF
|
||||
/**
|
||||
* @brief The image drawing routines for a GIF image.
|
||||
* @note Only use these functions if you absolutely know the format
|
||||
* of the image you are decoding. Generally you should use the
|
||||
* generic functions and it will auto-detect the format.
|
||||
* @{
|
||||
*/
|
||||
gdispImageError gdispImageOpen_GIF(gdispImage *img);
|
||||
void gdispImageClose_GIF(gdispImage *img);
|
||||
gdispImageError gdispImageCache_GIF(gdispImage *img);
|
||||
gdispImageError gdispGImageDraw_GIF(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
|
||||
delaytime_t gdispImageNext_GIF(gdispImage *img);
|
||||
/* @} */
|
||||
#endif
|
||||
|
||||
#if GDISP_NEED_IMAGE_BMP
|
||||
/**
|
||||
* @brief The image drawing routines for a BMP image.
|
||||
* @note Only use these functions if you absolutely know the format
|
||||
* of the image you are decoding. Generally you should use the
|
||||
* generic functions and it will auto-detect the format.
|
||||
* @{
|
||||
*/
|
||||
gdispImageError gdispImageOpen_BMP(gdispImage *img);
|
||||
void gdispImageClose_BMP(gdispImage *img);
|
||||
gdispImageError gdispImageCache_BMP(gdispImage *img);
|
||||
gdispImageError gdispGImageDraw_BMP(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
|
||||
delaytime_t gdispImageNext_BMP(gdispImage *img);
|
||||
/* @} */
|
||||
#endif
|
||||
|
||||
#if GDISP_NEED_IMAGE_JPG
|
||||
/**
|
||||
* @brief The image drawing routines for a JPG image.
|
||||
* @note Only use these functions if you absolutely know the format
|
||||
* of the image you are decoding. Generally you should use the
|
||||
* generic functions and it will auto-detect the format.
|
||||
* @{
|
||||
*/
|
||||
gdispImageError gdispImageOpen_JPG(gdispImage *img);
|
||||
void gdispImageClose_JPG(gdispImage *img);
|
||||
gdispImageError gdispImageCache_JPG(gdispImage *img);
|
||||
gdispImageError gdispGImageDraw_JPG(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
|
||||
delaytime_t gdispImageNext_JPG(gdispImage *img);
|
||||
/* @} */
|
||||
#endif
|
||||
|
||||
#if GDISP_NEED_IMAGE_PNG
|
||||
/**
|
||||
* @brief The image drawing routines for a PNG image.
|
||||
* @note Only use these functions if you absolutely know the format
|
||||
* of the image you are decoding. Generally you should use the
|
||||
* generic functions and it will auto-detect the format.
|
||||
* @{
|
||||
*/
|
||||
gdispImageError gdispImageOpen_PNG(gdispImage *img);
|
||||
void gdispImageClose_PNG(gdispImage *img);
|
||||
gdispImageError gdispImageCache_PNG(gdispImage *img);
|
||||
gdispImageError gdispGImageDraw_PNG(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
|
||||
delaytime_t gdispImageNext_PNG(gdispImage *img);
|
||||
/* @} */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
169
include/gfile/gfile.h
Normal file
169
include/gfile/gfile.h
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* This file is subject to the terms of the GFX License. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://ugfx.org/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file include/gfile/gfile.h
|
||||
* @brief GFILE - File IO Routines header file.
|
||||
*
|
||||
* @addtogroup GFILE
|
||||
*
|
||||
* @brief Module which contains Operating system independent FILEIO
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GFILE_H
|
||||
#define _GFILE_H
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
#if GFX_USE_GFILE || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Type definitions */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief A file pointer
|
||||
*/
|
||||
|
||||
#ifndef GFILE_IMPLEMENTATION
|
||||
typedef void GFILE;
|
||||
#else
|
||||
typedef struct GFILE GFILE;
|
||||
#endif
|
||||
|
||||
extern GFILE *gfileStdIn;
|
||||
extern GFILE *gfileStdErr;
|
||||
extern GFILE *gfileStdOut;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool_t gfileExists(const char *fname);
|
||||
bool_t gfileDelete(const char *fname);
|
||||
long int gfileGetFilesize(const char *fname);
|
||||
bool_t gfileRename(const char *oldname, const char *newname);
|
||||
GFILE * gfileOpen(const char *fname, const char *mode);
|
||||
void gfileClose(GFILE *f);
|
||||
size_t gfileRead(GFILE *f, void *buf, size_t len);
|
||||
size_t gfileWrite(GFILE *f, const void *buf, size_t len);
|
||||
long int gfileGetPos(GFILE *f);
|
||||
bool_t gfileSetPos(GFILE *f, long int pos);
|
||||
long int gfileGetSize(GFILE *f);
|
||||
bool_t gfileEOF(GFILE *f);
|
||||
|
||||
#if GFILE_NEED_CHIBIOSFS && GFX_USE_OS_CHIBIOS
|
||||
GFILE * gfileOpenBaseFileStream(void *BaseFileStreamPtr, const char *mode);
|
||||
#endif
|
||||
#if GFILE_NEED_MEMFS
|
||||
GFILE * gfileOpenMemory(void *memptr, const char *mode);
|
||||
#endif
|
||||
|
||||
#if GFILE_NEED_PRINTG
|
||||
int vfnprintg(GFILE *f, int maxlen, const char *fmt, va_list arg);
|
||||
int fnprintg(GFILE *f, int maxlen, const char *fmt, ...);
|
||||
#define vfprintg(f,m,a) vfnprintg(f,0,m,a)
|
||||
#define fprintg(f,m,...) fnprintg(f,0,m,...)
|
||||
#define vprintg(m,a) vfnprintg(gfileStdOut,0,m,a)
|
||||
#define printg(m,...) fnprintg(gfileStdOut,0,m,...)
|
||||
|
||||
#if GFILE_NEED_STRINGS
|
||||
int vsnprintg(char *buf, int maxlen, const char *fmt, va_list arg);
|
||||
int snprintg(char *buf, int maxlen, const char *fmt, ...);
|
||||
#define vsprintg(s,m,a) vsnprintg(s,0,m,a)
|
||||
#define sprintg(s,m,...) snprintg(s,0,m,...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if GFILE_NEED_SCANG
|
||||
int vfscang(GFILE *f, const char *fmt, va_list arg);
|
||||
int fscang(GFILE *f, const char *fmt, ...);
|
||||
#define vscang(f,a) vfscang(gfileStdIn,f,a)
|
||||
#define scang(f,...) fscang(gfileStdIn,f,...)
|
||||
|
||||
#if GFILE_NEED_STRINGS
|
||||
int vsscang(const char *buf, const char *fmt, va_list arg);
|
||||
int sscang(const char *buf, const char *fmt, ...);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if GFILE_NEED_STDIO && !defined(GFILE_IMPLEMENTATION)
|
||||
#define stdin gfileStdIn
|
||||
#define stdout gfileStdOut
|
||||
#define stderr gfileStdErr
|
||||
#define FILENAME_MAX 256 // Use a relatively small number for an embedded platform
|
||||
#define L_tmpnam FILENAME_MAX
|
||||
#define FOPEN_MAX GFILE_MAX_GFILES
|
||||
#define TMP_MAX GFILE_MAX_GFILES
|
||||
#define P_tmpdir "/tmp/"
|
||||
#define FILE GFILE
|
||||
#define fopen(n,m) gfileOpen(n,m)
|
||||
#define fclose(f) gfileClose(f)
|
||||
size_t gstdioRead(void * ptr, size_t size, size_t count, FILE *f);
|
||||
size_t gstdioWrite(const void * ptr, size_t size, size_t count, FILE *f);
|
||||
#define fread(p,sz,cnt,f) gstdioRead(p,sz,cnt,f)
|
||||
#define fwrite(p,sz,cnt,f) gstdioWrite(p,sz,cnt,f)
|
||||
int gstdioSeek(FILE *f, size_t offset, int origin);
|
||||
#define fseek(f,ofs,org) gstdioSeek(f,ofs,org)
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
#define remove(n) (!gfileDelete(n))
|
||||
#define rename(o,n) (!gfileRename(o,n))
|
||||
#define fflush(f) (0)
|
||||
#define ftell(f) gfileGetPos(f)
|
||||
#define fpos_t long int
|
||||
int gstdioGetpos(FILE *f, long int *pos);
|
||||
#define fgetpos(f,pos) gstdioGetpos(f,pos)
|
||||
#define fsetpos(f, pos) (!gfileSetPos(f, *pos))
|
||||
#define rewind(f) gfileSetPos(f, 0);
|
||||
#define feof(f) gfileEOF(f)
|
||||
|
||||
#define vfprintf(f,m,a) vfnprintg(f,0,m,a)
|
||||
#define fprintf(f,m,...) fnprintg(f,0,m,...)
|
||||
#define vprintf(m,a) vfnprintg(gfileStdOut,0,m,a)
|
||||
#define printf(m,...) fnprintg(gfileStdOut,0,m,...)
|
||||
#define vsnprintf(s,n,m,a) vsnprintg(s,n,m,a)
|
||||
#define snprintf(s,n,m,...) snprintg(s,n,m,...)
|
||||
#define vsprintf(s,m,a) vsnprintg(s,0,m,a)
|
||||
#define sprintf(s,m,...) snprintg(s,0,m,...)
|
||||
//TODO
|
||||
//void clearerr ( FILE * stream );
|
||||
//int ferror ( FILE * stream );
|
||||
//FILE * tmpfile ( void ); // Auto-deleting
|
||||
//char * tmpnam ( char * str );
|
||||
//char * mktemp (char *template);
|
||||
//FILE * freopen ( const char * filename, const char * mode, FILE * stream );
|
||||
//setbuf
|
||||
//setvbuf
|
||||
//fflush
|
||||
//fgetc
|
||||
//fgets
|
||||
//fputc
|
||||
//fputs
|
||||
//getc
|
||||
//getchar
|
||||
//puts
|
||||
//ungetc
|
||||
//void perror (const char * str);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GFX_USE_GFILE */
|
||||
|
||||
#endif /* _GFILE_H */
|
||||
/** @} */
|
||||
|
158
include/gfile/options.h
Normal file
158
include/gfile/options.h
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* This file is subject to the terms of the GFX License. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://ugfx.org/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file include/gfile/options.h
|
||||
* @brief GFILE - File IO options header file.
|
||||
*
|
||||
* @addtogroup GFILE
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _GFILE_OPTIONS_H
|
||||
#define _GFILE_OPTIONS_H
|
||||
|
||||
/**
|
||||
* @name GFILE Functionality to be included
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Include printg, fprintg etc functions
|
||||
* @details Defaults to FALSE
|
||||
*/
|
||||
#ifndef GFILE_NEED_PRINTG
|
||||
#define GFILE_NEED_PRINTG FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Include scang, fscang etc functions
|
||||
* @details Defaults to FALSE
|
||||
*/
|
||||
#ifndef GFILE_NEED_SCANG
|
||||
#define GFILE_NEED_SCANG FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Include the string sprintg/sscang functions
|
||||
* @details Defaults to FALSE
|
||||
* @pre To get sprintg functions you also need to define @p GFILE_NEED_PRINTG
|
||||
* @pre To get sscang functions you also need to define @p GFILE_NEED_SCANG
|
||||
*/
|
||||
#ifndef GFILE_NEED_STRINGS
|
||||
#define GFILE_NEED_STRINGS FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Map many stdio functions to their GFILE equivalent
|
||||
* @details Defaults to FALSE
|
||||
* @note This replaces the functions in stdio.h with equivalents
|
||||
* - Do not include stdio.h as it has different conflicting definitions.
|
||||
*/
|
||||
#ifndef GFILE_NEED_STDIO
|
||||
#define GFILE_NEED_STDIO FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Include the ROM file system
|
||||
* @details Defaults to FALSE
|
||||
* @note If GFILE_ALLOW_DEVICESPECIFIC is on then you can ensure that you are
|
||||
* opening a file on the ROM file system by prefixing
|
||||
* its name with "S|" (the letter 'S', followed by a vertical bar).
|
||||
* @note This requires a file called romfs_files.h to be in the
|
||||
* users project include path. This file should include all the files
|
||||
* converted to .h files using the file2c utility (using flags "-dbcs").
|
||||
*/
|
||||
#ifndef GFILE_NEED_ROMFS
|
||||
#define GFILE_NEED_ROMFS FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Include the RAM file system
|
||||
* @details Defaults to FALSE
|
||||
* @note If GFILE_ALLOW_DEVICESPECIFIC is on then you can ensure that you are
|
||||
* opening a file on the RAM file system by prefixing
|
||||
* its name with "R|" (the letter 'R', followed by a vertical bar).
|
||||
* @note You must also define GFILE_RAMFS_SIZE with the size of the file system
|
||||
* to be allocated in RAM.
|
||||
*/
|
||||
#ifndef GFILE_NEED_RAMFS
|
||||
#define GFILE_NEED_RAMFS FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Include the FAT file system driver
|
||||
* @details Defaults to FALSE
|
||||
* @note If GFILE_ALLOW_DEVICESPECIFIC is on then you can ensure that you are
|
||||
* opening a file on the FAT file system by prefixing
|
||||
* its name with "F|" (the letter 'F', followed by a vertical bar).
|
||||
* @note You must separately include the FATFS library and code.
|
||||
*/
|
||||
#ifndef GFILE_NEED_FATFS
|
||||
#define GFILE_NEED_FATFS FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Include the operating system's native file system
|
||||
* @details Defaults to FALSE
|
||||
* @note If GFILE_ALLOW_DEVICESPECIFIC is on then you can ensure that you are
|
||||
* opening a file on the native file system by prefixing
|
||||
* its name with "N|" (the letter 'N', followed by a vertical bar).
|
||||
* @note If defined then the gfileStdOut and gfileStdErr handles
|
||||
* use the operating system equivalent stdio and stderr.
|
||||
* If it is not defined the gfileStdOut and gfileStdErr io is discarded.
|
||||
*/
|
||||
#ifndef GFILE_NEED_NATIVEFS
|
||||
#define GFILE_NEED_NATIVEFS FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Include ChibiOS BaseFileStream support
|
||||
* @details Defaults to FALSE
|
||||
* @pre This is only relevant on the ChibiOS operating system.
|
||||
* @note Use the @p gfileOpenBaseFileStream() call to open a GFILE based on a
|
||||
* BaseFileStream. The BaseFileStream must already be open.
|
||||
* @note A GFile of this type cannot be opened by filename. The BaseFileStream
|
||||
* must be pre-opened using the operating system.
|
||||
*/
|
||||
#ifndef GFILE_NEED_CHIBIOSFS
|
||||
#define GFILE_NEED_CHIBIOSFS FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief Include raw memory pointer support
|
||||
* @details Defaults to FALSE
|
||||
* @note Use the @p gfileOpenMemory() call to open a GFILE based on a
|
||||
* memory pointer. The GFILE opened appears to be of unlimited size.
|
||||
* @note A GFile of this type cannot be opened by filename.
|
||||
*/
|
||||
#ifndef GFILE_NEED_MEMFS
|
||||
#define GFILE_NEED_MEMFS FALSE
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
* @name GFILE Optional Parameters
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Add floating point support to printg/scang etc.
|
||||
*/
|
||||
#ifndef GFILE_ALLOW_FLOATS
|
||||
#define GFILE_ALLOW_FLOATS
|
||||
#endif
|
||||
/**
|
||||
* @brief Can the device be specified as part of the file name.
|
||||
* @note If this is on then a device letter and a vertical bar can be
|
||||
* prefixed on a file name to specify that it must be on a
|
||||
* specific device.
|
||||
*/
|
||||
#ifndef GFILE_ALLOW_DEVICESPECIFIC
|
||||
#define GFILE_ALLOW_DEVICESPECIFIC FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief The maximum number of open files
|
||||
* @note This count excludes gfileStdIn, gfileStdOut and gfileStdErr
|
||||
* (if open by default).
|
||||
*/
|
||||
#ifndef GFILE_MAX_GFILES
|
||||
#define GFILE_MAX_GFILES 3
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
#endif /* _GFILE_OPTIONS_H */
|
||||
/** @} */
|
@ -150,6 +150,13 @@
|
||||
#ifndef GFX_USE_GMISC
|
||||
#define GFX_USE_GMISC FALSE
|
||||
#endif
|
||||
/**
|
||||
* @brief GFX File API
|
||||
* @details Defaults to FALSE
|
||||
*/
|
||||
#ifndef GFX_USE_GFILE
|
||||
#define GFX_USE_GFILE FALSE
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@ -157,6 +164,7 @@
|
||||
*
|
||||
*/
|
||||
#include "gos/options.h"
|
||||
#include "gfile/options.h"
|
||||
#include "gmisc/options.h"
|
||||
#include "gqueue/options.h"
|
||||
#include "gevent/options.h"
|
||||
@ -169,7 +177,7 @@
|
||||
#include "gaudout/options.h"
|
||||
|
||||
/**
|
||||
* Inter-dependancy safety checks on the sub-systems.
|
||||
* Interdependency safety checks on the sub-systems.
|
||||
*
|
||||
*/
|
||||
#include "gfx_rules.h"
|
||||
@ -178,6 +186,7 @@
|
||||
* Include the sub-system header files
|
||||
*/
|
||||
#include "gos/gos.h"
|
||||
#include "gfile/gfile.h"
|
||||
#include "gmisc/gmisc.h"
|
||||
#include "gqueue/gqueue.h"
|
||||
#include "gevent/gevent.h"
|
||||
@ -208,7 +217,6 @@ extern "C" {
|
||||
* @brief The one call to end it all
|
||||
*
|
||||
* @note This will deinitialise each sub-system that has been turned on.
|
||||
* @note Do not call this without a previous @p gfxInit();
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
|
@ -187,6 +187,15 @@
|
||||
#undef GDISP_INCLUDE_FONT_UI2
|
||||
#define GDISP_INCLUDE_FONT_UI2 TRUE
|
||||
#endif
|
||||
#if GDISP_NEED_IMAGE
|
||||
#if !GFX_USE_GFILE
|
||||
#if GFX_DISPLAY_RULE_WARNINGS
|
||||
#warning "GDISP: GFX_USE_GFILE is required when GDISP_NEED_IMAGE is TRUE. It has been turned on for you."
|
||||
#endif
|
||||
#undef GFX_USE_GFILE
|
||||
#define GFX_USE_GFILE TRUE
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if GFX_USE_GAUDIN
|
||||
@ -230,5 +239,8 @@
|
||||
#if GFX_USE_GMISC
|
||||
#endif
|
||||
|
||||
#if GFX_USE_GFILE
|
||||
#endif
|
||||
|
||||
#endif /* _GFX_H */
|
||||
/** @} */
|
||||
|
@ -60,42 +60,51 @@ GHandle gwinGImageCreate(GDisplay *g, GImageObject *widget, GWindowInit *pInit);
|
||||
#define gwinImageCreate(w, pInit) gwinGImageCreate(GDISP, w, pInit)
|
||||
|
||||
/**
|
||||
* @brief Sets the input routines that support reading the image from memory
|
||||
* in RAM or flash.
|
||||
* @return TRUE if the IO open function succeeds
|
||||
* @brief Opens the image using a GFILE
|
||||
* @return TRUE if the image can be opened
|
||||
*
|
||||
* @param[in] gh The widget (must be an image widget)
|
||||
* @param[in] memory A pointer to the image in RAM or Flash
|
||||
* @param[in] f The open (for reading) GFILE to use
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
bool_t gwinImageOpenMemory(GHandle gh, const void* memory);
|
||||
bool_t gwinImageOpenGFile(GHandle gh, GFILE *f);
|
||||
|
||||
/**
|
||||
* @brief Opens the image using the specified filename
|
||||
* @return TRUE if the open succeeds
|
||||
*
|
||||
* @param[in] gh The widget (must be an image widget)
|
||||
* @param[in] filename The filename to open
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#define gwinImageOpenFile(gh, filename) gwinImageOpenGFile((gh), gfileOpen((filename), "rb"))
|
||||
|
||||
#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_LINUX || GFX_USE_OS_OSX || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Sets the input routines that support reading the image from a file
|
||||
* @brief Sets the input routines that support reading the image from memory
|
||||
* in RAM or flash.
|
||||
* @pre GFILE_NEED_MEMFS must be TRUE
|
||||
* @return TRUE if the IO open function succeeds
|
||||
*
|
||||
* @param[in] gh The widget (must be an image widget)
|
||||
* @param[in] filename The filename to open
|
||||
* @param[in] ptr A pointer to the image in RAM or Flash
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
bool_t gwinImageOpenFile(GHandle gh, const char* filename);
|
||||
#endif
|
||||
#define gwinImageOpenMemory(gh, ptr) gwinImageOpenGFile((gh), gfileOpenMemory((void *)(ptr), "rb"))
|
||||
|
||||
#if GFX_USE_OS_CHIBIOS || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Sets the input routines that support reading the image from a BaseFileStream (eg. an SD-Card).
|
||||
* @return TRUE if the IO open function succeeds
|
||||
*
|
||||
* @param[in] gh The widget (must be an image widget)
|
||||
* @param[in] streamPtr A pointer to the (open) BaseFileStream object.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
bool_t gwinImageOpenStream(GHandle gh, void *streamPtr);
|
||||
#endif
|
||||
/**
|
||||
* @brief Sets the input routines that support reading the image from a BaseFileStream (eg. an SD-Card).
|
||||
* @return TRUE if the IO open function succeeds
|
||||
* @pre GFILE_NEED_CHIBIOSFS and GFX_USE_OS_CHIBIOS must be TRUE
|
||||
*
|
||||
* @param[in] gh The widget (must be an image widget)
|
||||
* @param[in] streamPtr A pointer to the (open) BaseFileStream object.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
#define gwinImageOpenStream(gh, streamPtr) gwinImageOpenGFile((gh), gfileOpenBaseFIleStream((streamPtr), "rb"))
|
||||
|
||||
/**
|
||||
* @brief Cache the image.
|
||||
|
@ -16,7 +16,45 @@
|
||||
|
||||
#if GFX_USE_GDISP && GDISP_NEED_IMAGE
|
||||
|
||||
#include <string.h>
|
||||
#if GDISP_NEED_IMAGE_NATIVE
|
||||
extern gdispImageError gdispImageOpen_NATIVE(gdispImage *img);
|
||||
extern void gdispImageClose_NATIVE(gdispImage *img);
|
||||
extern gdispImageError gdispImageCache_NATIVE(gdispImage *img);
|
||||
extern gdispImageError gdispGImageDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
|
||||
extern delaytime_t gdispImageNext_NATIVE(gdispImage *img);
|
||||
#endif
|
||||
|
||||
#if GDISP_NEED_IMAGE_GIF
|
||||
extern gdispImageError gdispImageOpen_GIF(gdispImage *img);
|
||||
extern void gdispImageClose_GIF(gdispImage *img);
|
||||
extern gdispImageError gdispImageCache_GIF(gdispImage *img);
|
||||
extern gdispImageError gdispGImageDraw_GIF(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
|
||||
extern delaytime_t gdispImageNext_GIF(gdispImage *img);
|
||||
#endif
|
||||
|
||||
#if GDISP_NEED_IMAGE_BMP
|
||||
extern gdispImageError gdispImageOpen_BMP(gdispImage *img);
|
||||
extern void gdispImageClose_BMP(gdispImage *img);
|
||||
extern gdispImageError gdispImageCache_BMP(gdispImage *img);
|
||||
extern gdispImageError gdispGImageDraw_BMP(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
|
||||
extern delaytime_t gdispImageNext_BMP(gdispImage *img);
|
||||
#endif
|
||||
|
||||
#if GDISP_NEED_IMAGE_JPG
|
||||
extern gdispImageError gdispImageOpen_JPG(gdispImage *img);
|
||||
extern void gdispImageClose_JPG(gdispImage *img);
|
||||
extern gdispImageError gdispImageCache_JPG(gdispImage *img);
|
||||
extern gdispImageError gdispGImageDraw_JPG(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
|
||||
extern delaytime_t gdispImageNext_JPG(gdispImage *img);
|
||||
#endif
|
||||
|
||||
#if GDISP_NEED_IMAGE_PNG
|
||||
extern gdispImageError gdispImageOpen_PNG(gdispImage *img);
|
||||
extern void gdispImageClose_PNG(gdispImage *img);
|
||||
extern gdispImageError gdispImageCache_PNG(gdispImage *img);
|
||||
extern gdispImageError gdispGImageDraw_PNG(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy);
|
||||
extern delaytime_t gdispImageNext_PNG(gdispImage *img);
|
||||
#endif
|
||||
|
||||
/* The structure defining the routines for image drawing */
|
||||
typedef struct gdispImageHandlers {
|
||||
@ -59,134 +97,76 @@ static gdispImageHandlers ImageHandlers[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static size_t ImageMemoryRead(struct gdispImageIO *pio, void *buf, size_t len) {
|
||||
if (pio->fd == (void *)-1) return 0;
|
||||
memcpy(buf, ((const char *)pio->fd)+pio->pos, len);
|
||||
pio->pos += len;
|
||||
return len;
|
||||
gdispImageError
|
||||
DEPRECATED("Use gdispImageOpenGFile() instead")
|
||||
gdispImageOpen(gdispImage *img) {
|
||||
return gdispImageOpenGFile(img, img->f);
|
||||
}
|
||||
|
||||
static void ImageMemorySeek(struct gdispImageIO *pio, size_t pos) {
|
||||
if (pio->fd == (void *)-1) return;
|
||||
pio->pos = pos;
|
||||
}
|
||||
|
||||
static void ImageMemoryClose(struct gdispImageIO *pio) {
|
||||
pio->fd = (void *)-1;
|
||||
pio->pos = 0;
|
||||
}
|
||||
|
||||
static const gdispImageIOFunctions ImageMemoryFunctions =
|
||||
{ ImageMemoryRead, ImageMemorySeek, ImageMemoryClose };
|
||||
|
||||
bool_t gdispImageSetMemoryReader(gdispImage *img, const void *memimage) {
|
||||
img->io.fns = &ImageMemoryFunctions;
|
||||
img->io.pos = 0;
|
||||
img->io.fd = memimage;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if GFX_USE_OS_CHIBIOS
|
||||
static size_t ImageBaseFileStreamRead(struct gdispImageIO *pio, void *buf, size_t len) {
|
||||
if (pio->fd == (void *)-1) return 0;
|
||||
len = chSequentialStreamRead(((BaseFileStream *)pio->fd), (uint8_t *)buf, len);
|
||||
pio->pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
static void ImageBaseFileStreamSeek(struct gdispImageIO *pio, size_t pos) {
|
||||
if (pio->fd == (void *)-1) return;
|
||||
if (pio->pos != pos) {
|
||||
chFileStreamSeek(((BaseFileStream *)pio->fd), pos);
|
||||
pio->pos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
static void ImageBaseFileStreamClose(struct gdispImageIO *pio) {
|
||||
if (pio->fd == (void *)-1) return;
|
||||
chFileStreamClose(((BaseFileStream *)pio->fd));
|
||||
pio->fd = (void *)-1;
|
||||
pio->pos = 0;
|
||||
}
|
||||
|
||||
static const gdispImageIOFunctions ImageBaseFileStreamFunctions =
|
||||
{ ImageBaseFileStreamRead, ImageBaseFileStreamSeek, ImageBaseFileStreamClose };
|
||||
|
||||
bool_t gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr) {
|
||||
img->io.fns = &ImageBaseFileStreamFunctions;
|
||||
img->io.pos = 0;
|
||||
img->io.fd = BaseFileStreamPtr;
|
||||
return TRUE;
|
||||
#if GFILE_NEED_MEMFS
|
||||
bool_t
|
||||
DEPRECATED("Use gdispImageOpenMemory() instead")
|
||||
gdispImageSetMemoryReader(gdispImage *img, const void *memimage) {
|
||||
img->f = gfileOpenMemory((void *)memimage, "rb");
|
||||
return img->f != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_LINUX || GFX_USE_OS_OSX
|
||||
#include <stdio.h>
|
||||
|
||||
static size_t ImageFileRead(struct gdispImageIO *pio, void *buf, size_t len) {
|
||||
if (!pio->fd) return 0;
|
||||
len = fread(buf, 1, len, (FILE *)pio->fd);
|
||||
if ((int)len < 0) len = 0;
|
||||
pio->pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
static void ImageFileSeek(struct gdispImageIO *pio, size_t pos) {
|
||||
if (!pio->fd) return;
|
||||
if (pio->pos != pos) {
|
||||
fseek((FILE *)pio->fd, pos, SEEK_SET);
|
||||
pio->pos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
static void ImageFileClose(struct gdispImageIO *pio) {
|
||||
if (!pio->fd) return;
|
||||
fclose((FILE *)pio->fd);
|
||||
pio->fd = 0;
|
||||
pio->pos = 0;
|
||||
}
|
||||
|
||||
static const gdispImageIOFunctions ImageFileFunctions =
|
||||
{ ImageFileRead, ImageFileSeek, ImageFileClose };
|
||||
|
||||
bool_t gdispImageSetFileReader(gdispImage *img, const char *filename) {
|
||||
img->io.fns = &ImageFileFunctions;
|
||||
img->io.pos = 0;
|
||||
#if defined(WIN32) || GFX_USE_OS_WIN32
|
||||
img->io.fd = (void *)fopen(filename, "rb");
|
||||
#else
|
||||
img->io.fd = (void *)fopen(filename, "r");
|
||||
#endif
|
||||
|
||||
return img->io.fd != 0;
|
||||
bool_t
|
||||
DEPRECATED("Use gdispImageOpenFile() instead")
|
||||
gdispImageSetFileReader(gdispImage *img, const char *filename) {
|
||||
img->f = gfileOpen(filename, "rb");
|
||||
return img->f != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
gdispImageError gdispImageOpen(gdispImage *img) {
|
||||
#if GFILE_NEED_CHIBIOSFS && GFX_USE_OS_CHIBIOS
|
||||
bool_t
|
||||
DEPRECATED("Use gdispImageOpenBaseFileStream() instead")
|
||||
gdispImageSetBaseFileStreamReader(gdispImage *img, void *BaseFileStreamPtr) {
|
||||
img->f = gfileOpenBaseFileStream(BaseFileStreamPtr, "rb");
|
||||
return img->f != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
gdispImageError gdispImageOpenGFile(gdispImage *img, GFILE *f) {
|
||||
gdispImageError err;
|
||||
|
||||
if (!f)
|
||||
return GDISP_IMAGE_ERR_NOSUCHFILE;
|
||||
img->f = f;
|
||||
img->bgcolor = White;
|
||||
for(img->fns = ImageHandlers; img->fns < ImageHandlers+sizeof(ImageHandlers)/sizeof(ImageHandlers[0]); img->fns++) {
|
||||
err = img->fns->open(img);
|
||||
if (err != GDISP_IMAGE_ERR_BADFORMAT) {
|
||||
if ((err & GDISP_IMAGE_ERR_UNRECOVERABLE))
|
||||
img->fns = 0;
|
||||
goto unrecoverable;
|
||||
|
||||
// Everything is possible
|
||||
return err;
|
||||
}
|
||||
img->io.fns->seek(&img->io, 0);
|
||||
|
||||
// Try the next decoder
|
||||
gfileSetPos(img->f, 0);
|
||||
}
|
||||
|
||||
err = GDISP_IMAGE_ERR_BADFORMAT;
|
||||
img->type = GDISP_IMAGE_TYPE_UNKNOWN;
|
||||
|
||||
unrecoverable:
|
||||
gfileClose(img->f);
|
||||
img->f = 0;
|
||||
img->flags = 0;
|
||||
img->fns = 0;
|
||||
img->priv = 0;
|
||||
return GDISP_IMAGE_ERR_BADFORMAT;
|
||||
return err;
|
||||
}
|
||||
|
||||
void gdispImageClose(gdispImage *img) {
|
||||
if (img->fns)
|
||||
img->fns->close(img);
|
||||
else
|
||||
img->io.fns->close(&img->io);
|
||||
gfileClose(img->f);
|
||||
img->type = GDISP_IMAGE_TYPE_UNKNOWN;
|
||||
img->flags = 0;
|
||||
img->fns = 0;
|
||||
@ -194,7 +174,7 @@ void gdispImageClose(gdispImage *img) {
|
||||
}
|
||||
|
||||
bool_t gdispImageIsOpen(gdispImage *img) {
|
||||
return img->type != GDISP_IMAGE_TYPE_UNKNOWN && img->fns != 0;
|
||||
return img->fns != 0;
|
||||
}
|
||||
|
||||
void gdispImageSetBgColor(gdispImage *img, color_t bgcolor) {
|
||||
|
@ -118,6 +118,19 @@ typedef struct gdispImagePrivate {
|
||||
pixel_t buf[BLIT_BUFFER_SIZE];
|
||||
} gdispImagePrivate;
|
||||
|
||||
void gdispImageClose_BMP(gdispImage *img) {
|
||||
if (img->priv) {
|
||||
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
|
||||
if (img->priv->palette)
|
||||
gdispImageFree(img, (void *)img->priv->palette, img->priv->palsize*sizeof(color_t));
|
||||
#endif
|
||||
if (img->priv->frame0cache)
|
||||
gdispImageFree(img, (void *)img->priv->frame0cache, img->width*img->height*sizeof(pixel_t));
|
||||
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
|
||||
img->priv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
gdispImageError gdispImageOpen_BMP(gdispImage *img) {
|
||||
gdispImagePrivate *priv;
|
||||
uint8_t hdr[2];
|
||||
@ -126,7 +139,7 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
|
||||
uint32_t offsetColorTable;
|
||||
|
||||
/* Read the file identifier */
|
||||
if (img->io.fns->read(&img->io, hdr, 2) != 2)
|
||||
if (gfileRead(img->f, hdr, 2) != 2)
|
||||
return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us
|
||||
|
||||
/* Process the BITMAPFILEHEADER structure */
|
||||
@ -154,18 +167,18 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
|
||||
#endif
|
||||
|
||||
/* Skip the size field and the 2 reserved fields */
|
||||
if (img->io.fns->read(&img->io, priv->buf, 8) != 8)
|
||||
if (gfileRead(img->f, priv->buf, 8) != 8)
|
||||
goto baddatacleanup;
|
||||
|
||||
/* Get the offset to the bitmap data */
|
||||
if (img->io.fns->read(&img->io, &priv->frame0pos, 4) != 4)
|
||||
if (gfileRead(img->f, &priv->frame0pos, 4) != 4)
|
||||
goto baddatacleanup;
|
||||
CONVERT_FROM_DWORD_LE(priv->frame0pos);
|
||||
|
||||
/* Process the BITMAPCOREHEADER structure */
|
||||
|
||||
/* Get the offset to the colour data */
|
||||
if (img->io.fns->read(&img->io, &offsetColorTable, 4) != 4)
|
||||
if (gfileRead(img->f, &offsetColorTable, 4) != 4)
|
||||
goto baddatacleanup;
|
||||
CONVERT_FROM_DWORD_LE(offsetColorTable);
|
||||
offsetColorTable += 14; // Add the size of the BITMAPFILEHEADER
|
||||
@ -175,7 +188,7 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
|
||||
img->priv->bmpflags |= BMP_V2;
|
||||
|
||||
// Read the header
|
||||
if (img->io.fns->read(&img->io, priv->buf, 12-4) != 12-4)
|
||||
if (gfileRead(img->f, priv->buf, 12-4) != 12-4)
|
||||
goto baddatacleanup;
|
||||
// Get the width
|
||||
img->width = *(uint16_t *)(((uint8_t *)priv->buf)+0);
|
||||
@ -224,7 +237,7 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
|
||||
priv->bmpflags |= BMP_V4;
|
||||
|
||||
// Read the header
|
||||
if (img->io.fns->read(&img->io, priv->buf, 40-4) != 40-4)
|
||||
if (gfileRead(img->f, priv->buf, 40-4) != 40-4)
|
||||
goto baddatacleanup;
|
||||
// Get the width
|
||||
adword = *(uint32_t *)(((uint8_t *)priv->buf)+0);
|
||||
@ -327,18 +340,18 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
|
||||
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
|
||||
/* Load the palette tables */
|
||||
if (priv->bmpflags & BMP_PALETTE) {
|
||||
img->io.fns->seek(&img->io, offsetColorTable);
|
||||
gfileSetPos(img->f, offsetColorTable);
|
||||
|
||||
if (!(priv->palette = (color_t *)gdispImageAlloc(img, priv->palsize*sizeof(color_t))))
|
||||
return GDISP_IMAGE_ERR_NOMEMORY;
|
||||
if (priv->bmpflags & BMP_V2) {
|
||||
for(aword = 0; aword < priv->palsize; aword++) {
|
||||
if (img->io.fns->read(&img->io, &priv->buf, 3) != 3) goto baddatacleanup;
|
||||
if (gfileRead(img->f, &priv->buf, 3) != 3) goto baddatacleanup;
|
||||
priv->palette[aword] = RGB2COLOR(((uint8_t *)priv->buf)[2], ((uint8_t *)priv->buf)[1], ((uint8_t *)priv->buf)[0]);
|
||||
}
|
||||
} else {
|
||||
for(aword = 0; aword < priv->palsize; aword++) {
|
||||
if (img->io.fns->read(&img->io, &priv->buf, 4) != 4) goto baddatacleanup;
|
||||
if (gfileRead(img->f, &priv->buf, 4) != 4) goto baddatacleanup;
|
||||
priv->palette[aword] = RGB2COLOR(((uint8_t *)priv->buf)[2], ((uint8_t *)priv->buf)[1], ((uint8_t *)priv->buf)[0]);
|
||||
}
|
||||
}
|
||||
@ -349,15 +362,15 @@ gdispImageError gdispImageOpen_BMP(gdispImage *img) {
|
||||
#if GDISP_NEED_IMAGE_BMP_16 || GDISP_NEED_IMAGE_BMP_32
|
||||
/* Load the bit masks */
|
||||
if (priv->bmpflags & BMP_COMP_MASK) {
|
||||
img->io.fns->seek(&img->io, offsetColorTable);
|
||||
if (img->io.fns->read(&img->io, &priv->maskred, 4) != 4) goto baddatacleanup;
|
||||
gfileSetPos(img->f, offsetColorTable);
|
||||
if (gfileRead(img->f, &priv->maskred, 4) != 4) goto baddatacleanup;
|
||||
CONVERT_FROM_DWORD_LE(priv->maskred);
|
||||
if (img->io.fns->read(&img->io, &priv->maskgreen, 4) != 4) goto baddatacleanup;
|
||||
if (gfileRead(img->f, &priv->maskgreen, 4) != 4) goto baddatacleanup;
|
||||
CONVERT_FROM_DWORD_LE(priv->maskgreen);
|
||||
if (img->io.fns->read(&img->io, &priv->maskblue, 4) != 4) goto baddatacleanup;
|
||||
if (gfileRead(img->f, &priv->maskblue, 4) != 4) goto baddatacleanup;
|
||||
CONVERT_FROM_DWORD_LE(priv->maskblue);
|
||||
if (priv->bmpflags & BMP_V4) {
|
||||
if (img->io.fns->read(&img->io, &priv->maskalpha, 4) != 4) goto baddatacleanup;
|
||||
if (gfileRead(img->f, &priv->maskalpha, 4) != 4) goto baddatacleanup;
|
||||
CONVERT_FROM_DWORD_LE(priv->maskalpha);
|
||||
} else
|
||||
priv->maskalpha = 0;
|
||||
@ -419,20 +432,6 @@ unsupportedcleanup:
|
||||
return GDISP_IMAGE_ERR_UNSUPPORTED; // Not supported
|
||||
}
|
||||
|
||||
void gdispImageClose_BMP(gdispImage *img) {
|
||||
if (img->priv) {
|
||||
#if GDISP_NEED_IMAGE_BMP_1 || GDISP_NEED_IMAGE_BMP_4 || GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8 || GDISP_NEED_IMAGE_BMP_8_RLE
|
||||
if (img->priv->palette)
|
||||
gdispImageFree(img, (void *)img->priv->palette, img->priv->palsize*sizeof(color_t));
|
||||
#endif
|
||||
if (img->priv->frame0cache)
|
||||
gdispImageFree(img, (void *)img->priv->frame0cache, img->width*img->height*sizeof(pixel_t));
|
||||
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
|
||||
img->priv = 0;
|
||||
}
|
||||
img->io.fns->close(&img->io);
|
||||
}
|
||||
|
||||
static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
gdispImagePrivate * priv;
|
||||
color_t * pc;
|
||||
@ -454,7 +453,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
len = 0;
|
||||
|
||||
while(x < img->width && len <= BLIT_BUFFER_SIZE-32) {
|
||||
if (img->io.fns->read(&img->io, &b, 4) != 4)
|
||||
if (gfileRead(img->f, &b, 4) != 4)
|
||||
return 0;
|
||||
|
||||
for(m=0x80; m; m >>= 1, pc++)
|
||||
@ -499,7 +498,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
return len;
|
||||
} else if (priv->bmpflags & BMP_RLE_ABS) {
|
||||
while (priv->rlerun && len <= BLIT_BUFFER_SIZE-2 && x < img->width) {
|
||||
if (img->io.fns->read(&img->io, &b, 1) != 1)
|
||||
if (gfileRead(img->f, &b, 1) != 1)
|
||||
return 0;
|
||||
*pc++ = priv->palette[b[0] >> 4];
|
||||
priv->rlerun--;
|
||||
@ -514,8 +513,8 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
}
|
||||
if (priv->rlerun) // Return if we have more run to do
|
||||
return len;
|
||||
if ((img->io.pos - priv->frame0pos)&1) { // Make sure we are on a word boundary
|
||||
if (img->io.fns->read(&img->io, &b, 1) != 1)
|
||||
if ((gfileGetPos(img->f) - priv->frame0pos)&1) { // Make sure we are on a word boundary
|
||||
if (gfileRead(img->f, &b, 1) != 1)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -524,7 +523,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
priv->bmpflags &= ~(BMP_RLE_ENC|BMP_RLE_ABS);
|
||||
|
||||
// There are always at least 2 bytes in an RLE code
|
||||
if (img->io.fns->read(&img->io, &b, 2) != 2)
|
||||
if (gfileRead(img->f, &b, 2) != 2)
|
||||
return 0;
|
||||
|
||||
if (b[0]) { // Encoded mode
|
||||
@ -541,7 +540,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
return len;
|
||||
} else if (b[1] == 2) { // Delta x, y
|
||||
// There are always at least 2 bytes in an RLE code
|
||||
if (img->io.fns->read(&img->io, &b, 2) != 2)
|
||||
if (gfileRead(img->f, &b, 2) != 2)
|
||||
return 0;
|
||||
priv->rlerun = b[0] + (uint16_t)b[1] * img->width;
|
||||
priv->rlecode = 0; // Who knows what color this should really be
|
||||
@ -559,7 +558,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
uint8_t b[4];
|
||||
|
||||
while(x < img->width && len <= BLIT_BUFFER_SIZE-8) {
|
||||
if (img->io.fns->read(&img->io, &b, 4) != 4)
|
||||
if (gfileRead(img->f, &b, 4) != 4)
|
||||
return 0;
|
||||
|
||||
*pc++ = priv->palette[b[0] >> 4];
|
||||
@ -599,7 +598,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
return len;
|
||||
} else if (priv->bmpflags & BMP_RLE_ABS) {
|
||||
while (priv->rlerun && len < BLIT_BUFFER_SIZE && x < img->width) {
|
||||
if (img->io.fns->read(&img->io, &b, 1) != 1)
|
||||
if (gfileRead(img->f, &b, 1) != 1)
|
||||
return 0;
|
||||
*pc++ = priv->palette[b[0]];
|
||||
priv->rlerun--;
|
||||
@ -608,8 +607,8 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
}
|
||||
if (priv->rlerun) // Return if we have more run to do
|
||||
return len;
|
||||
if ((img->io.pos - priv->frame0pos)&1) { // Make sure we are on a word boundary
|
||||
if (img->io.fns->read(&img->io, &b, 1) != 1)
|
||||
if ((gfileGetPos(img->f) - priv->frame0pos)&1) { // Make sure we are on a word boundary
|
||||
if (gfileRead(img->f, &b, 1) != 1)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -618,7 +617,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
priv->bmpflags &= ~(BMP_RLE_ENC|BMP_RLE_ABS);
|
||||
|
||||
// There are always at least 2 bytes in an RLE code
|
||||
if (img->io.fns->read(&img->io, &b, 2) != 2)
|
||||
if (gfileRead(img->f, &b, 2) != 2)
|
||||
return 0;
|
||||
|
||||
if (b[0]) { // Encoded mode
|
||||
@ -635,7 +634,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
return len;
|
||||
} else if (b[1] == 2) { // Delta x, y
|
||||
// There are always at least 2 bytes in an RLE code
|
||||
if (img->io.fns->read(&img->io, &b, 2) != 2)
|
||||
if (gfileRead(img->f, &b, 2) != 2)
|
||||
return GDISP_IMAGE_ERR_BADDATA;
|
||||
priv->rlerun = b[0] + (uint16_t)b[1] * img->width;
|
||||
priv->rlecode = 0; // Who knows what color this should really be
|
||||
@ -653,7 +652,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
uint8_t b[4];
|
||||
|
||||
while(x < img->width && len <= BLIT_BUFFER_SIZE-4) {
|
||||
if (img->io.fns->read(&img->io, &b, 4) != 4)
|
||||
if (gfileRead(img->f, &b, 4) != 4)
|
||||
return 0;
|
||||
|
||||
*pc++ = priv->palette[b[0]];
|
||||
@ -675,7 +674,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
color_t r, g, b;
|
||||
|
||||
while(x < img->width && len <= BLIT_BUFFER_SIZE-2) {
|
||||
if (img->io.fns->read(&img->io, &w, 4) != 4)
|
||||
if (gfileRead(img->f, &w, 4) != 4)
|
||||
return 0;
|
||||
CONVERT_FROM_WORD_LE(w[0]);
|
||||
CONVERT_FROM_WORD_LE(w[1]);
|
||||
@ -720,7 +719,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
uint8_t b[3];
|
||||
|
||||
while(x < img->width && len < BLIT_BUFFER_SIZE) {
|
||||
if (img->io.fns->read(&img->io, &b, 3) != 3)
|
||||
if (gfileRead(img->f, &b, 3) != 3)
|
||||
return 0;
|
||||
*pc++ = RGB2COLOR(b[2], b[1], b[0]);
|
||||
x++;
|
||||
@ -729,7 +728,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
|
||||
if (x >= img->width) {
|
||||
// Make sure we have read a multiple of 4 bytes for the line
|
||||
if ((x & 3) && img->io.fns->read(&img->io, &b, x & 3) != (x & 3))
|
||||
if ((x & 3) && gfileRead(img->f, &b, x & 3) != (x & 3))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -743,7 +742,7 @@ static coord_t getPixels(gdispImage *img, coord_t x) {
|
||||
color_t r, g, b;
|
||||
|
||||
while(x < img->width && len < BLIT_BUFFER_SIZE) {
|
||||
if (img->io.fns->read(&img->io, &dw, 4) != 4)
|
||||
if (gfileRead(img->f, &dw, 4) != 4)
|
||||
return 0;
|
||||
CONVERT_FROM_DWORD_LE(dw);
|
||||
if (priv->shiftred < 0)
|
||||
@ -791,7 +790,7 @@ gdispImageError gdispImageCache_BMP(gdispImage *img) {
|
||||
return GDISP_IMAGE_ERR_NOMEMORY;
|
||||
|
||||
/* Read the entire bitmap into cache */
|
||||
img->io.fns->seek(&img->io, priv->frame0pos);
|
||||
gfileSetPos(img->f, priv->frame0pos);
|
||||
#if GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8_RLE
|
||||
priv->rlerun = 0;
|
||||
priv->rlecode = 0;
|
||||
@ -847,7 +846,7 @@ gdispImageError gdispGImageDraw_BMP(GDisplay *g, gdispImage *img, coord_t x, coo
|
||||
}
|
||||
|
||||
/* Start decoding from the beginning */
|
||||
img->io.fns->seek(&img->io, priv->frame0pos);
|
||||
gfileSetPos(img->f, priv->frame0pos);
|
||||
#if GDISP_NEED_IMAGE_BMP_4_RLE || GDISP_NEED_IMAGE_BMP_8_RLE
|
||||
priv->rlerun = 0;
|
||||
priv->rlecode = 0;
|
||||
|
@ -172,9 +172,9 @@ static gdispImageError startDecode(gdispImage *img) {
|
||||
// Local palette
|
||||
decode->maxpixel = priv->frame.palsize-1;
|
||||
decode->palette = (color_t *)(decode+1);
|
||||
img->io.fns->seek(&img->io, priv->frame.pospal);
|
||||
gfileSetPos(img->f, priv->frame.pospal);
|
||||
for(cnt = 0; cnt < priv->frame.palsize; cnt++) {
|
||||
if (img->io.fns->read(&img->io, &decode->buf, 3) != 3)
|
||||
if (gfileRead(img->f, &decode->buf, 3) != 3)
|
||||
goto baddatacleanup;
|
||||
decode->palette[cnt] = RGB2COLOR(decode->buf[0], decode->buf[1], decode->buf[2]);
|
||||
}
|
||||
@ -188,8 +188,8 @@ static gdispImageError startDecode(gdispImage *img) {
|
||||
}
|
||||
|
||||
// Get the initial lzw code size and values
|
||||
img->io.fns->seek(&img->io, priv->frame.posimg);
|
||||
if (img->io.fns->read(&img->io, &decode->bitsperpixel, 1) != 1 || decode->bitsperpixel >= MAX_CODE_BITS)
|
||||
gfileSetPos(img->f, priv->frame.posimg);
|
||||
if (gfileRead(img->f, &decode->bitsperpixel, 1) != 1 || decode->bitsperpixel >= MAX_CODE_BITS)
|
||||
goto baddatacleanup;
|
||||
decode->code_clear = 1 << decode->bitsperpixel;
|
||||
decode->code_eof = decode->code_clear + 1;
|
||||
@ -273,8 +273,8 @@ static uint16_t getbytes(gdispImage *img) {
|
||||
// Get another code - a code is made up of decode->bitspercode bits.
|
||||
while (decode->shiftbits < decode->bitspercode) {
|
||||
// Get a byte - we may have to start a new data block
|
||||
if ((!decode->blocksz && (img->io.fns->read(&img->io, &decode->blocksz, 1) != 1 || !decode->blocksz))
|
||||
|| img->io.fns->read(&img->io, &bdata, 1) != 1) {
|
||||
if ((!decode->blocksz && (gfileRead(img->f, &decode->blocksz, 1) != 1 || !decode->blocksz))
|
||||
|| gfileRead(img->f, &bdata, 1) != 1) {
|
||||
// Pretend we got the EOF code - some encoders seem to just end the file
|
||||
decode->code_last = decode->code_eof;
|
||||
return cnt;
|
||||
@ -302,8 +302,8 @@ static uint16_t getbytes(gdispImage *img) {
|
||||
if (code == decode->code_eof) {
|
||||
// Skip to the end of the data blocks
|
||||
do {
|
||||
img->io.fns->seek(&img->io, img->io.pos+decode->blocksz);
|
||||
} while (img->io.fns->read(&img->io, &decode->blocksz, 1) == 1 && decode->blocksz);
|
||||
gfileSetPos(img->f, gfileGetPos(img->f)+decode->blocksz);
|
||||
} while (gfileRead(img->f, &decode->blocksz, 1) == 1 && decode->blocksz);
|
||||
|
||||
// Mark the end
|
||||
decode->code_last = decode->code_eof;
|
||||
@ -398,8 +398,8 @@ static gdispImageError initFrame(gdispImage *img) {
|
||||
priv->dispose.height = priv->frame.height;
|
||||
|
||||
// Check for a cached version of this image
|
||||
for(cache=priv->cache; cache && cache->frame.posstart <= img->io.pos; cache=cache->next) {
|
||||
if (cache->frame.posstart == img->io.pos) {
|
||||
for(cache=priv->cache; cache && cache->frame.posstart <= (size_t)gfileGetPos(img->f); cache=cache->next) {
|
||||
if (cache->frame.posstart == (size_t)gfileGetPos(img->f)) {
|
||||
priv->frame = cache->frame;
|
||||
priv->curcache = cache;
|
||||
return GDISP_IMAGE_ERR_OK;
|
||||
@ -408,20 +408,20 @@ static gdispImageError initFrame(gdispImage *img) {
|
||||
|
||||
// Get ready for a new image
|
||||
priv->curcache = 0;
|
||||
priv->frame.posstart = img->io.pos;
|
||||
priv->frame.posstart = gfileGetPos(img->f);
|
||||
priv->frame.flags = 0;
|
||||
priv->frame.delay = 0;
|
||||
priv->frame.palsize = 0;
|
||||
|
||||
// Process blocks until we reach the image descriptor
|
||||
while(1) {
|
||||
if (img->io.fns->read(&img->io, &blocktype, 1) != 1)
|
||||
if (gfileRead(img->f, &blocktype, 1) != 1)
|
||||
return GDISP_IMAGE_ERR_BADDATA;
|
||||
|
||||
switch(blocktype) {
|
||||
case 0x2C: //',' - IMAGE_DESC_RECORD_TYPE;
|
||||
// Read the Image Descriptor
|
||||
if (img->io.fns->read(&img->io, priv->buf, 9) != 9)
|
||||
if (gfileRead(img->f, priv->buf, 9) != 9)
|
||||
return GDISP_IMAGE_ERR_BADDATA;
|
||||
priv->frame.x = *(uint16_t *)(((uint8_t *)priv->buf)+0);
|
||||
CONVERT_FROM_WORD_LE(priv->frame.x);
|
||||
@ -437,7 +437,7 @@ static gdispImageError initFrame(gdispImage *img) {
|
||||
priv->frame.flags |= GIFL_INTERLACE;
|
||||
|
||||
// We are ready to go for the actual palette read and image decode
|
||||
priv->frame.pospal = img->io.pos;
|
||||
priv->frame.pospal = gfileGetPos(img->f);
|
||||
priv->frame.posimg = priv->frame.pospal+priv->frame.palsize*3;
|
||||
priv->frame.posend = 0;
|
||||
|
||||
@ -448,13 +448,13 @@ static gdispImageError initFrame(gdispImage *img) {
|
||||
|
||||
case 0x21: //'!' - EXTENSION_RECORD_TYPE;
|
||||
// Read the extension type
|
||||
if (img->io.fns->read(&img->io, &blocktype, 1) != 1)
|
||||
if (gfileRead(img->f, &blocktype, 1) != 1)
|
||||
return GDISP_IMAGE_ERR_BADDATA;
|
||||
|
||||
switch(blocktype) {
|
||||
case 0xF9: // EXTENSION - Graphics Control Block
|
||||
// Read the GCB
|
||||
if (img->io.fns->read(&img->io, priv->buf, 6) != 6)
|
||||
if (gfileRead(img->f, priv->buf, 6) != 6)
|
||||
return GDISP_IMAGE_ERR_BADDATA;
|
||||
// Check we have read a 4 byte data block and a data block terminator (0)
|
||||
if (((uint8_t *)priv->buf)[0] != 4 || ((uint8_t *)priv->buf)[5] != 0)
|
||||
@ -485,7 +485,7 @@ static gdispImageError initFrame(gdispImage *img) {
|
||||
if (priv->flags & GIF_LOOP)
|
||||
goto skipdatablocks;
|
||||
// Read the Application header
|
||||
if (img->io.fns->read(&img->io, priv->buf, 16) != 16)
|
||||
if (gfileRead(img->f, priv->buf, 16) != 16)
|
||||
return GDISP_IMAGE_ERR_BADDATA;
|
||||
// Check we have read a 11 byte data block
|
||||
if (((uint8_t *)priv->buf)[0] != 11 && ((uint8_t *)priv->buf)[12] != 3)
|
||||
@ -516,11 +516,11 @@ static gdispImageError initFrame(gdispImage *img) {
|
||||
// We don't understand this extension - just skip it by skipping data blocks
|
||||
skipdatablocks:
|
||||
while(1) {
|
||||
if (img->io.fns->read(&img->io, &blocksz, 1) != 1)
|
||||
if (gfileRead(img->f, &blocksz, 1) != 1)
|
||||
return GDISP_IMAGE_ERR_BADDATA;
|
||||
if (!blocksz)
|
||||
break;
|
||||
img->io.fns->seek(&img->io, img->io.pos + blocksz);
|
||||
gfileSetPos(img->f, gfileGetPos(img->f) + blocksz);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -537,7 +537,7 @@ static gdispImageError initFrame(gdispImage *img) {
|
||||
}
|
||||
|
||||
// Seek back to frame0
|
||||
img->io.fns->seek(&img->io, priv->frame0pos);
|
||||
gfileSetPos(img->f, priv->frame0pos);
|
||||
return GDISP_IMAGE_LOOP;
|
||||
|
||||
default: // UNDEFINED_RECORD_TYPE;
|
||||
@ -546,13 +546,34 @@ static gdispImageError initFrame(gdispImage *img) {
|
||||
}
|
||||
}
|
||||
|
||||
void gdispImageClose_GIF(gdispImage *img) {
|
||||
gdispImagePrivate * priv;
|
||||
imgcache * cache;
|
||||
imgcache * ncache;
|
||||
|
||||
priv = img->priv;
|
||||
if (priv) {
|
||||
// Free any stored frames
|
||||
cache = priv->cache;
|
||||
while(cache) {
|
||||
ncache = cache->next;
|
||||
gdispImageFree(img, (void *)cache, sizeof(imgcache)+cache->frame.width*cache->frame.height+cache->frame.palsize*sizeof(color_t));
|
||||
cache = ncache;
|
||||
}
|
||||
if (priv->palette)
|
||||
gdispImageFree(img, (void *)priv->palette, priv->palsize*sizeof(color_t));
|
||||
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
|
||||
img->priv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
gdispImageError gdispImageOpen_GIF(gdispImage *img) {
|
||||
gdispImagePrivate *priv;
|
||||
uint8_t hdr[6];
|
||||
uint16_t aword;
|
||||
|
||||
/* Read the file identifier */
|
||||
if (img->io.fns->read(&img->io, hdr, 6) != 6)
|
||||
if (gfileRead(img->f, hdr, 6) != 6)
|
||||
return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us
|
||||
|
||||
/* Process the GIFFILEHEADER structure */
|
||||
@ -580,7 +601,7 @@ gdispImageError gdispImageOpen_GIF(gdispImage *img) {
|
||||
/* Process the Screen Descriptor structure */
|
||||
|
||||
// Read the screen descriptor
|
||||
if (img->io.fns->read(&img->io, priv->buf, 7) != 7)
|
||||
if (gfileRead(img->f, priv->buf, 7) != 7)
|
||||
goto baddatacleanup;
|
||||
// Get the width
|
||||
img->width = *(uint16_t *)(((uint8_t *)priv->buf)+0);
|
||||
@ -596,7 +617,7 @@ gdispImageError gdispImageOpen_GIF(gdispImage *img) {
|
||||
goto nomemcleanup;
|
||||
// Read the global palette
|
||||
for(aword = 0; aword < priv->palsize; aword++) {
|
||||
if (img->io.fns->read(&img->io, &priv->buf, 3) != 3)
|
||||
if (gfileRead(img->f, &priv->buf, 3) != 3)
|
||||
goto baddatacleanup;
|
||||
priv->palette[aword] = RGB2COLOR(((uint8_t *)priv->buf)[0], ((uint8_t *)priv->buf)[1], ((uint8_t *)priv->buf)[2]);
|
||||
}
|
||||
@ -604,7 +625,7 @@ gdispImageError gdispImageOpen_GIF(gdispImage *img) {
|
||||
priv->bgcolor = ((uint8_t *)priv->buf)[5];
|
||||
|
||||
// Save the fram0pos
|
||||
priv->frame0pos = img->io.pos;
|
||||
priv->frame0pos = gfileGetPos(img->f);
|
||||
|
||||
// Read the first frame descriptor
|
||||
switch(initFrame(img)) {
|
||||
@ -628,28 +649,6 @@ gdispImageError gdispImageOpen_GIF(gdispImage *img) {
|
||||
}
|
||||
}
|
||||
|
||||
void gdispImageClose_GIF(gdispImage *img) {
|
||||
gdispImagePrivate * priv;
|
||||
imgcache * cache;
|
||||
imgcache * ncache;
|
||||
|
||||
priv = img->priv;
|
||||
if (priv) {
|
||||
// Free any stored frames
|
||||
cache = priv->cache;
|
||||
while(cache) {
|
||||
ncache = cache->next;
|
||||
gdispImageFree(img, (void *)cache, sizeof(imgcache)+cache->frame.width*cache->frame.height+cache->frame.palsize*sizeof(color_t));
|
||||
cache = ncache;
|
||||
}
|
||||
if (priv->palette)
|
||||
gdispImageFree(img, (void *)priv->palette, priv->palsize*sizeof(color_t));
|
||||
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
|
||||
img->priv = 0;
|
||||
}
|
||||
img->io.fns->close(&img->io);
|
||||
}
|
||||
|
||||
gdispImageError gdispImageCache_GIF(gdispImage *img) {
|
||||
gdispImagePrivate * priv;
|
||||
imgcache * cache;
|
||||
@ -786,7 +785,7 @@ gdispImageError gdispImageCache_GIF(gdispImage *img) {
|
||||
}
|
||||
// We could be pedantic here but extra bytes won't hurt us
|
||||
while(getbytes(img));
|
||||
priv->frame.posend = cache->frame.posend = img->io.pos;
|
||||
priv->frame.posend = cache->frame.posend = gfileGetPos(img->f);
|
||||
|
||||
// Save everything
|
||||
priv->curcache = cache;
|
||||
@ -1150,7 +1149,7 @@ gdispImageError gdispGImageDraw_GIF(GDisplay *g, gdispImage *img, coord_t x, coo
|
||||
}
|
||||
// We could be pedantic here but extra bytes won't hurt us
|
||||
while (getbytes(img));
|
||||
priv->frame.posend = img->io.pos;
|
||||
priv->frame.posend = gfileGetPos(img->f);
|
||||
|
||||
stopDecode(img);
|
||||
return GDISP_IMAGE_ERR_OK;
|
||||
@ -1173,19 +1172,19 @@ delaytime_t gdispImageNext_GIF(gdispImage *img) {
|
||||
// We need to get to the end of this frame
|
||||
if (!priv->frame.posend) {
|
||||
// We don't know where the end of the frame is yet - find it!
|
||||
img->io.fns->seek(&img->io, priv->frame.posimg+1); // Skip the code size byte too
|
||||
gfileSetPos(img->f, priv->frame.posimg+1); // Skip the code size byte too
|
||||
while(1) {
|
||||
if (img->io.fns->read(&img->io, &blocksz, 1) != 1)
|
||||
if (gfileRead(img->f, &blocksz, 1) != 1)
|
||||
return TIME_INFINITE;
|
||||
if (!blocksz)
|
||||
break;
|
||||
img->io.fns->seek(&img->io, img->io.pos + blocksz);
|
||||
gfileSetPos(img->f, gfileGetPos(img->f) + blocksz);
|
||||
}
|
||||
priv->frame.posend = img->io.pos;
|
||||
priv->frame.posend = gfileGetPos(img->f);
|
||||
}
|
||||
|
||||
// Seek to the end of this frame
|
||||
img->io.fns->seek(&img->io, priv->frame.posend);
|
||||
gfileSetPos(img->f, priv->frame.posend);
|
||||
|
||||
// Read the next frame descriptor
|
||||
for(blocksz=0; blocksz < 2; blocksz++) { // 2 loops max to prevent cycling forever with a bad file
|
||||
|
@ -33,11 +33,20 @@ typedef struct gdispImagePrivate {
|
||||
pixel_t buf[BLIT_BUFFER_SIZE];
|
||||
} gdispImagePrivate;
|
||||
|
||||
void gdispImageClose_NATIVE(gdispImage *img) {
|
||||
if (img->priv) {
|
||||
if (img->priv->frame0cache)
|
||||
gdispImageFree(img, (void *)img->priv->frame0cache, img->width * img->height * sizeof(pixel_t));
|
||||
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
|
||||
img->priv = 0;
|
||||
}
|
||||
}
|
||||
|
||||
gdispImageError gdispImageOpen_NATIVE(gdispImage *img) {
|
||||
uint8_t hdr[HEADER_SIZE];
|
||||
|
||||
/* Read the 8 byte header */
|
||||
if (img->io.fns->read(&img->io, hdr, 8) != 8)
|
||||
if (gfileRead(img->f, hdr, 8) != 8)
|
||||
return GDISP_IMAGE_ERR_BADFORMAT; // It can't be us
|
||||
|
||||
if (hdr[0] != 'N' || hdr[1] != 'I')
|
||||
@ -60,16 +69,6 @@ gdispImageError gdispImageOpen_NATIVE(gdispImage *img) {
|
||||
return GDISP_IMAGE_ERR_OK;
|
||||
}
|
||||
|
||||
void gdispImageClose_NATIVE(gdispImage *img) {
|
||||
if (img->priv) {
|
||||
if (img->priv->frame0cache)
|
||||
gdispImageFree(img, (void *)img->priv->frame0cache, img->width * img->height * sizeof(pixel_t));
|
||||
gdispImageFree(img, (void *)img->priv, sizeof(gdispImagePrivate));
|
||||
img->priv = 0;
|
||||
}
|
||||
img->io.fns->close(&img->io);
|
||||
}
|
||||
|
||||
gdispImageError gdispImageCache_NATIVE(gdispImage *img) {
|
||||
size_t len;
|
||||
|
||||
@ -84,8 +83,8 @@ gdispImageError gdispImageCache_NATIVE(gdispImage *img) {
|
||||
return GDISP_IMAGE_ERR_NOMEMORY;
|
||||
|
||||
/* Read the entire bitmap into cache */
|
||||
img->io.fns->seek(&img->io, FRAME0POS);
|
||||
if (img->io.fns->read(&img->io, img->priv->frame0cache, len) != len)
|
||||
gfileSetPos(img->f, FRAME0POS);
|
||||
if (gfileRead(img->f, img->priv->frame0cache, len) != len)
|
||||
return GDISP_IMAGE_ERR_BADDATA;
|
||||
|
||||
return GDISP_IMAGE_ERR_OK;
|
||||
@ -112,12 +111,12 @@ gdispImageError gdispImageGDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x,
|
||||
/* Cycle through the lines */
|
||||
for(;cy;cy--, y++) {
|
||||
/* Move to the start of the line */
|
||||
img->io.fns->seek(&img->io, pos);
|
||||
gfileSetPos(img->f, pos);
|
||||
|
||||
/* Draw the line in chunks using BitBlt */
|
||||
for(mx = x, mcx = cx; mcx > 0; mcx -= len, mx += len) {
|
||||
// Read the data
|
||||
len = img->io.fns->read(&img->io,
|
||||
len = gfileRead(img->f,
|
||||
img->priv->buf,
|
||||
mcx > BLIT_BUFFER_SIZE ? (BLIT_BUFFER_SIZE*sizeof(pixel_t)) : (mcx * sizeof(pixel_t)))
|
||||
/ sizeof(pixel_t);
|
||||
|
998
src/gfile/gfile.c
Normal file
998
src/gfile/gfile.c
Normal file
@ -0,0 +1,998 @@
|
||||
/*
|
||||
* This file is subject to the terms of the GFX License. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://ugfx.org/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file src/gfile/gfile.c
|
||||
* @brief GFILE code.
|
||||
*
|
||||
*/
|
||||
|
||||
#define GFILE_IMPLEMENTATION
|
||||
|
||||
#include "gfx.h"
|
||||
|
||||
#if GFX_USE_GFILE
|
||||
|
||||
struct GFILE {
|
||||
const struct GFILEVMT * vmt;
|
||||
uint16_t flags;
|
||||
#define GFILEFLG_OPEN 0x0001 // File is open
|
||||
#define GFILEFLG_READ 0x0002 // Read the file
|
||||
#define GFILEFLG_WRITE 0x0004 // Write the file
|
||||
#define GFILEFLG_APPEND 0x0008 // Append on each write
|
||||
#define GFILEFLG_BINARY 0x0010 // Treat as a binary file
|
||||
#define GFILEFLG_DELONCLOSE 0x0020 // Delete on close
|
||||
#define GFILEFLG_CANSEEK 0x0040 // Seek operations are valid
|
||||
#define GFILEFLG_FAILONBLOCK 0x0080 // Fail on a blocking call
|
||||
#define GFILEFLG_MUSTEXIST 0x0100 // On open file must exist
|
||||
#define GFILEFLG_MUSTNOTEXIST 0x0200 // On open file must not exist
|
||||
#define GFILEFLG_TRUNC 0x0400 // On open truncate the file
|
||||
void * obj;
|
||||
long int pos;
|
||||
};
|
||||
|
||||
typedef struct GFILEVMT {
|
||||
const struct GFILEVMT * next;
|
||||
uint8_t flags;
|
||||
#define GFSFLG_WRITEABLE 0x0001
|
||||
#define GFSFLG_CASESENSITIVE 0x0002
|
||||
#define GFSFLG_SEEKABLE 0x0004
|
||||
#define GFSFLG_FAST 0x0010
|
||||
#define GFSFLG_SMALL 0x0020
|
||||
#define GFSFLG_TEXTMODES 0x0040
|
||||
char prefix;
|
||||
bool_t (*del) (const char *fname);
|
||||
bool_t (*exists) (const char *fname);
|
||||
long int (*filesize) (const char *fname);
|
||||
bool_t (*ren) (const char *oldname, const char *newname);
|
||||
bool_t (*open) (GFILE *f, const char *fname);
|
||||
void (*close) (GFILE *f);
|
||||
int (*read) (GFILE *f, void *buf, int size);
|
||||
int (*write) (GFILE *f, const void *buf, int size);
|
||||
bool_t (*setpos) (GFILE *f, long int pos);
|
||||
long int (*getsize) (GFILE *f);
|
||||
bool_t (*eof) (GFILE *f);
|
||||
} GFILEVMT;
|
||||
|
||||
// The chain of FileSystems
|
||||
#define GFILE_CHAINHEAD 0
|
||||
|
||||
// The table of GFILE's
|
||||
static GFILE gfileArr[GFILE_MAX_GFILES];
|
||||
GFILE *gfileStdIn;
|
||||
GFILE *gfileStdOut;
|
||||
GFILE *gfileStdErr;
|
||||
|
||||
/**
|
||||
* The order of the file-systems below determines the order
|
||||
* that they are searched to find a file.
|
||||
* The last defined is the first searched.
|
||||
*/
|
||||
|
||||
/********************************************************
|
||||
* The ChibiOS BaseFileStream VMT
|
||||
********************************************************/
|
||||
#if GFILE_NEED_CHIBIOSFS && GFX_USE_OS_CHIBIOS
|
||||
#include "../src/gfile/inc_chibiosfs.c"
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
* The Memory Pointer VMT
|
||||
********************************************************/
|
||||
#if GFILE_NEED_MEMFS
|
||||
#include "../src/gfile/inc_memfs.c"
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
* The RAM file-system VMT
|
||||
********************************************************/
|
||||
#if GFILE_NEED_RAMFS
|
||||
#include "../src/gfile/inc_ramfs.c"
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
* The FAT file-system VMT
|
||||
********************************************************/
|
||||
#ifndef GFILE_NEED_FATFS
|
||||
#include "../src/gfile/inc_fatfs.c"
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
* The native file-system
|
||||
********************************************************/
|
||||
#if GFILE_NEED_NATIVEFS
|
||||
#include "../src/gfile/inc_nativefs.c"
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
* The ROM file-system VMT
|
||||
********************************************************/
|
||||
#if GFILE_NEED_ROMFS
|
||||
#include "../src/gfile/inc_romfs.c"
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
* IO routines
|
||||
********************************************************/
|
||||
|
||||
/**
|
||||
* The chain of file systems.
|
||||
*/
|
||||
static const GFILEVMT const * FsChain = GFILE_CHAINHEAD;
|
||||
|
||||
/**
|
||||
* The init routine
|
||||
*/
|
||||
void _gfileInit(void) {
|
||||
#if GFILE_NEED_NATIVEFS
|
||||
NativeStdIn.flags = GFILEFLG_OPEN|GFILEFLG_READ;
|
||||
NativeStdIn.vmt = &FsNativeVMT;
|
||||
NativeStdIn.obj = (void *)stdin;
|
||||
NativeStdIn.pos = 0;
|
||||
gfileStdIn = &NativeStdIn;
|
||||
NativeStdOut.flags = GFILEFLG_OPEN|GFILEFLG_WRITE|GFILEFLG_APPEND;
|
||||
NativeStdOut.vmt = &FsNativeVMT;
|
||||
NativeStdOut.obj = (void *)stdout;
|
||||
NativeStdOut.pos = 0;
|
||||
gfileStdOut = &NativeStdOut;
|
||||
NativeStdErr.flags = GFILEFLG_OPEN|GFILEFLG_WRITE|GFILEFLG_APPEND;
|
||||
NativeStdErr.vmt = &FsNativeVMT;
|
||||
NativeStdErr.obj = (void *)stderr;
|
||||
NativeStdErr.pos = 0;
|
||||
gfileStdErr = &NativeStdErr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void _gfileDeinit(void)
|
||||
{
|
||||
/* ToDo */
|
||||
}
|
||||
|
||||
bool_t gfileExists(const char *fname) {
|
||||
const GFILEVMT *p;
|
||||
|
||||
#if GFILE_ALLOW_DEVICESPECIFIC
|
||||
if (fname[0] && fname[1] == '|') {
|
||||
for(p = FsChain; p; p = p->next) {
|
||||
if (p->prefix == fname[0])
|
||||
return p->exists && p->exists(fname+2);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(p = FsChain; p; p = p->next) {
|
||||
if (p->exists && p->exists(fname))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool_t gfileDelete(const char *fname) {
|
||||
const GFILEVMT *p;
|
||||
|
||||
#if GFILE_ALLOW_DEVICESPECIFIC
|
||||
if (fname[0] && fname[1] == '|') {
|
||||
for(p = FsChain; p; p = p->next) {
|
||||
if (p->prefix == fname[0])
|
||||
return p->del && p->del(fname+2);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(p = FsChain; p; p = p->next) {
|
||||
if (p->del && p->del(fname))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
long int gfileGetFilesize(const char *fname) {
|
||||
const GFILEVMT *p;
|
||||
long int res;
|
||||
|
||||
#if GFILE_ALLOW_DEVICESPECIFIC
|
||||
if (fname[0] && fname[1] == '|') {
|
||||
for(p = FsChain; p; p = p->next) {
|
||||
if (p->prefix == fname[0])
|
||||
return p->filesize ? p->filesize(fname+2) : -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(p = FsChain; p; p = p->next) {
|
||||
if (p->filesize && (res = p->filesize(fname)) != -1)
|
||||
return res;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool_t gfileRename(const char *oldname, const char *newname) {
|
||||
const GFILEVMT *p;
|
||||
|
||||
#if GFILE_ALLOW_DEVICESPECIFIC
|
||||
if ((oldname[0] && oldname[1] == '|') || (newname[0] && newname[1] == '|')) {
|
||||
char ch;
|
||||
|
||||
if (oldname[0] && oldname[1] == '|') {
|
||||
ch = oldname[0];
|
||||
oldname += 2;
|
||||
if (newname[0] && newname[1] == '|') {
|
||||
if (newname[0] != ch)
|
||||
// Both oldname and newname are fs specific but different ones.
|
||||
return FALSE;
|
||||
newname += 2;
|
||||
}
|
||||
} else {
|
||||
ch = newname[0];
|
||||
newname += 2;
|
||||
}
|
||||
for(p = FsChain; p; p = p->next) {
|
||||
if (p->prefix == ch)
|
||||
return p->ren && p->ren(oldname, newname);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(p = FsChain; p; p = p->next) {
|
||||
if (p->ren && p->ren(oldname,newname))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static uint16_t mode2flags(const char *mode) {
|
||||
uint16_t flags;
|
||||
|
||||
switch(mode[0]) {
|
||||
case 'r':
|
||||
flags = GFILEFLG_READ|GFILEFLG_MUSTEXIST;
|
||||
while (*++mode) {
|
||||
switch(mode[0]) {
|
||||
case '+': flags |= GFILEFLG_WRITE; break;
|
||||
case 'b': flags |= GFILEFLG_BINARY; break;
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
case 'w':
|
||||
flags = GFILEFLG_WRITE|GFILEFLG_TRUNC;
|
||||
while (*++mode) {
|
||||
switch(mode[0]) {
|
||||
case '+': flags |= GFILEFLG_READ; break;
|
||||
case 'b': flags |= GFILEFLG_BINARY; break;
|
||||
case 'x': flags |= GFILEFLG_MUSTNOTEXIST; break;
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
case 'a':
|
||||
flags = GFILEFLG_WRITE|GFILEFLG_APPEND;
|
||||
while (*++mode) {
|
||||
switch(mode[0]) {
|
||||
case '+': flags |= GFILEFLG_READ; break;
|
||||
case 'b': flags |= GFILEFLG_BINARY; break;
|
||||
case 'x': flags |= GFILEFLG_MUSTNOTEXIST; break;
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool_t testopen(const GFILEVMT *p, GFILE *f, const char *fname) {
|
||||
// If we want write but the fs doesn't allow it then return
|
||||
if ((f->flags & GFILEFLG_WRITE) && !(p->flags & GFSFLG_WRITEABLE))
|
||||
return FALSE;
|
||||
|
||||
// Try to open
|
||||
if (!p->open || !p->open(f, fname))
|
||||
return FALSE;
|
||||
|
||||
// File is open - fill in all the details
|
||||
f->vmt = p;
|
||||
f->pos = 0;
|
||||
f->flags |= GFILEFLG_OPEN;
|
||||
if (p->flags & GFSFLG_SEEKABLE)
|
||||
f->flags |= GFILEFLG_CANSEEK;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GFILE *gfileOpen(const char *fname, const char *mode) {
|
||||
uint16_t flags;
|
||||
GFILE * f;
|
||||
const GFILEVMT *p;
|
||||
|
||||
// Get the requested mode
|
||||
if (!(flags = mode2flags(mode)))
|
||||
return 0;
|
||||
|
||||
#if GFILE_ALLOW_DEVICESPECIFIC
|
||||
if (fname[0] && fname[1] == '|') {
|
||||
// First find an available GFILE slot.
|
||||
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
|
||||
if (!(f->flags & GFILEFLG_OPEN)) {
|
||||
// Try to open the file
|
||||
f->flags = flags;
|
||||
for(p = FsChain; p; p = p->next) {
|
||||
if (p->prefix == fname[0])
|
||||
return testopen(p, f, fname+2) ? f : 0;
|
||||
}
|
||||
// File not found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No available slot
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// First find an available GFILE slot.
|
||||
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
|
||||
if (!(f->flags & GFILEFLG_OPEN)) {
|
||||
|
||||
// Try to open the file
|
||||
f->flags = flags;
|
||||
for(p = FsChain; p; p = p->next) {
|
||||
if (testopen(p, f, fname))
|
||||
return f;
|
||||
}
|
||||
// File not found
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// No available slot
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if GFILE_NEED_CHIBIOSFS && GFX_USE_OS_CHIBIOS
|
||||
GFILE * gfileOpenBaseFileStream(void *BaseFileStreamPtr, const char *mode) {
|
||||
GFILE * f;
|
||||
|
||||
// First find an available GFILE slot.
|
||||
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
|
||||
if (!(f->flags & GFILEFLG_OPEN)) {
|
||||
// Get the flags
|
||||
if (!(f->flags = mode2flags(mode)))
|
||||
return 0;
|
||||
|
||||
// If we want write but the fs doesn't allow it then return
|
||||
if ((f->flags & GFILEFLG_WRITE) && !(FsCHIBIOSVMT.flags & GFSFLG_WRITEABLE))
|
||||
return 0;
|
||||
|
||||
// File is open - fill in all the details
|
||||
f->vmt = &FsCHIBIOSVMT;
|
||||
f->obj = BaseFileStreamPtr;
|
||||
f->pos = 0;
|
||||
f->flags |= GFILEFLG_OPEN|GFILEFLG_CANSEEK;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
// No available slot
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if GFILE_NEED_MEMFS
|
||||
GFILE * gfileOpenMemory(void *memptr, const char *mode) {
|
||||
GFILE * f;
|
||||
|
||||
// First find an available GFILE slot.
|
||||
for (f = gfileArr; f < &gfileArr[GFILE_MAX_GFILES]; f++) {
|
||||
if (!(f->flags & GFILEFLG_OPEN)) {
|
||||
// Get the flags
|
||||
if (!(f->flags = mode2flags(mode)))
|
||||
return 0;
|
||||
|
||||
// If we want write but the fs doesn't allow it then return
|
||||
if ((f->flags & GFILEFLG_WRITE) && !(FsMemVMT.flags & GFSFLG_WRITEABLE))
|
||||
return 0;
|
||||
|
||||
// File is open - fill in all the details
|
||||
f->vmt = &FsMemVMT;
|
||||
f->obj = memptr;
|
||||
f->pos = 0;
|
||||
f->flags |= GFILEFLG_OPEN|GFILEFLG_CANSEEK;
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
// No available slot
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void gfileClose(GFILE *f) {
|
||||
if (!f || !(f->flags & GFILEFLG_OPEN))
|
||||
return;
|
||||
if (f->vmt->close)
|
||||
f->vmt->close(f);
|
||||
f->flags = 0;
|
||||
}
|
||||
|
||||
size_t gfileRead(GFILE *f, void *buf, size_t len) {
|
||||
size_t res;
|
||||
|
||||
if (!f || (f->flags & (GFILEFLG_OPEN|GFILEFLG_READ)) != (GFILEFLG_OPEN|GFILEFLG_READ))
|
||||
return 0;
|
||||
if (!f->vmt->read)
|
||||
return 0;
|
||||
if ((res = f->vmt->read(f, buf, len)) <= 0)
|
||||
return 0;
|
||||
f->pos += res;
|
||||
return res;
|
||||
}
|
||||
|
||||
size_t gfileWrite(GFILE *f, const void *buf, size_t len) {
|
||||
size_t res;
|
||||
|
||||
if (!f || (f->flags & (GFILEFLG_OPEN|GFILEFLG_WRITE)) != (GFILEFLG_OPEN|GFILEFLG_WRITE))
|
||||
return 0;
|
||||
if (!f->vmt->write)
|
||||
return 0;
|
||||
if ((res = f->vmt->write(f, buf, len)) <= 0)
|
||||
return 0;
|
||||
f->pos += res;
|
||||
return res;
|
||||
}
|
||||
|
||||
long int gfileGetPos(GFILE *f) {
|
||||
if (!f || !(f->flags & GFILEFLG_OPEN))
|
||||
return 0;
|
||||
return f->pos;
|
||||
}
|
||||
|
||||
bool_t gfileSetPos(GFILE *f, long int pos) {
|
||||
if (!f || !(f->flags & GFILEFLG_OPEN))
|
||||
return FALSE;
|
||||
if (!f->vmt->setpos || !f->vmt->setpos(f, pos))
|
||||
return FALSE;
|
||||
f->pos = pos;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
long int gfileGetSize(GFILE *f) {
|
||||
if (!f || !(f->flags & GFILEFLG_OPEN))
|
||||
return 0;
|
||||
if (!f->vmt->getsize)
|
||||
return 0;
|
||||
return f->vmt->getsize(f);
|
||||
}
|
||||
|
||||
bool_t gfileEOF(GFILE *f) {
|
||||
if (!f || !(f->flags & GFILEFLG_OPEN))
|
||||
return TRUE;
|
||||
if (!f->vmt->eof)
|
||||
return FALSE;
|
||||
return f->vmt->eof(f);
|
||||
}
|
||||
|
||||
/********************************************************
|
||||
* String VMT routines
|
||||
********************************************************/
|
||||
#if GFILE_NEED_STRINGS && (GFILE_NEED_PRINTG || GFILE_NEED_SCANG)
|
||||
#include <string.h>
|
||||
|
||||
// Special String VMT
|
||||
static int StringRead(GFILE *f, void *buf, int size) {
|
||||
// size must be 1 for a complete read
|
||||
if (!((char *)f->obj)[f->pos])
|
||||
return 0;
|
||||
((char *)buf)[0] = ((char *)f->obj)[f->pos];
|
||||
return 1;
|
||||
}
|
||||
static int StringWrite(GFILE *f, const void *buf, int size) {
|
||||
// size must be 1 for a complete write
|
||||
((char *)f->obj)[f->pos] = ((char *)buf)[0];
|
||||
return 1;
|
||||
}
|
||||
static const GFILEVMT StringVMT = {
|
||||
0, // next
|
||||
0, // flags
|
||||
'_', // prefix
|
||||
0, 0, 0, 0,
|
||||
0, 0, StringRead, StringWrite,
|
||||
0, 0, 0,
|
||||
};
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
* printg routines
|
||||
********************************************************/
|
||||
#if GFILE_NEED_PRINTG
|
||||
#include <stdarg.h>
|
||||
|
||||
#define MAX_FILLER 11
|
||||
#define FLOAT_PRECISION 100000
|
||||
|
||||
int fnprintg(GFILE *f, int maxlen, const char *fmt, ...) {
|
||||
int res;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
res = vfnprintg(f, maxlen, fmt, ap);
|
||||
va_end(ap);
|
||||
return res;
|
||||
}
|
||||
|
||||
static char *ltoa_wd(char *p, long num, unsigned radix, long divisor) {
|
||||
int i;
|
||||
char * q;
|
||||
|
||||
if (!divisor) divisor = num;
|
||||
|
||||
q = p + MAX_FILLER;
|
||||
do {
|
||||
i = (int)(num % radix);
|
||||
i += '0';
|
||||
if (i > '9')
|
||||
i += 'A' - '0' - 10;
|
||||
*--q = i;
|
||||
num /= radix;
|
||||
} while ((divisor /= radix) != 0);
|
||||
|
||||
i = (int)(p + MAX_FILLER - q);
|
||||
do {
|
||||
*p++ = *q++;
|
||||
} while (--i);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int vfnprintg(GFILE *f, int maxlen, const char *fmt, va_list arg) {
|
||||
int ret;
|
||||
char *p, *s, c, filler;
|
||||
int i, precision, width;
|
||||
bool_t is_long, left_align;
|
||||
long l;
|
||||
#if GFILE_ALLOW_FLOATS
|
||||
float f;
|
||||
char tmpbuf[2*MAX_FILLER + 1];
|
||||
#else
|
||||
char tmpbuf[MAX_FILLER + 1];
|
||||
#endif
|
||||
|
||||
ret = 0;
|
||||
if (maxlen < 0)
|
||||
return 0;
|
||||
if (!maxlen)
|
||||
maxlen = -1;
|
||||
|
||||
while (*fmt) {
|
||||
if (*fmt != '%') {
|
||||
gfileWrite(f, fmt, 1);
|
||||
ret++; if (--maxlen) return ret;
|
||||
fmt++;
|
||||
continue;
|
||||
}
|
||||
fmt++;
|
||||
|
||||
p = s = tmpbuf;
|
||||
left_align = FALSE;
|
||||
filler = ' ';
|
||||
width = 0;
|
||||
precision = 0;
|
||||
|
||||
if (*fmt == '-') {
|
||||
fmt++;
|
||||
left_align = TRUE;
|
||||
}
|
||||
if (*fmt == '.') {
|
||||
fmt++;
|
||||
filler = '0';
|
||||
}
|
||||
|
||||
while (1) {
|
||||
c = *fmt++;
|
||||
if (c >= '0' && c <= '9')
|
||||
c -= '0';
|
||||
else if (c == '*')
|
||||
c = va_arg(ap, int);
|
||||
else
|
||||
break;
|
||||
width = width * 10 + c;
|
||||
}
|
||||
if (c == '.') {
|
||||
while (1) {
|
||||
c = *fmt++;
|
||||
if (c >= '0' && c <= '9')
|
||||
c -= '0';
|
||||
else if (c == '*')
|
||||
c = va_arg(ap, int);
|
||||
else
|
||||
break;
|
||||
precision = precision * 10 + c;
|
||||
}
|
||||
}
|
||||
/* Long modifier.*/
|
||||
if (c == 'l' || c == 'L') {
|
||||
is_long = TRUE;
|
||||
if (*fmt)
|
||||
c = *fmt++;
|
||||
}
|
||||
else
|
||||
is_long = (c >= 'A') && (c <= 'Z');
|
||||
|
||||
/* Command decoding.*/
|
||||
switch (c) {
|
||||
case 0:
|
||||
return ret;
|
||||
case 'c':
|
||||
filler = ' ';
|
||||
*p++ = va_arg(ap, int);
|
||||
break;
|
||||
case 's':
|
||||
filler = ' ';
|
||||
if ((s = va_arg(ap, char *)) == 0)
|
||||
s = "(null)";
|
||||
if (precision == 0)
|
||||
precision = 32767;
|
||||
for (p = s; *p && (--precision >= 0); p++);
|
||||
break;
|
||||
case 'D':
|
||||
case 'd':
|
||||
if (is_long)
|
||||
l = va_arg(ap, long);
|
||||
else
|
||||
l = va_arg(ap, int);
|
||||
if (l < 0) {
|
||||
*p++ = '-';
|
||||
l = -l;
|
||||
}
|
||||
p = ltoa_wd(p, l, 10, 0);
|
||||
break;
|
||||
#if GFILE_ALLOW_FLOATS
|
||||
case 'f':
|
||||
f = (float) va_arg(ap, double);
|
||||
if (f < 0) {
|
||||
*p++ = '-';
|
||||
f = -f;
|
||||
}
|
||||
l = f;
|
||||
p = ltoa_wd(p, l, 10, 0);
|
||||
*p++ = '.';
|
||||
l = (f - l) * FLOAT_PRECISION;
|
||||
p = ltoa_wd(p, l, 10, FLOAT_PRECISION / 10);
|
||||
break;
|
||||
#endif
|
||||
case 'X':
|
||||
case 'x':
|
||||
c = 16;
|
||||
goto unsigned_common;
|
||||
case 'U':
|
||||
case 'u':
|
||||
c = 10;
|
||||
goto unsigned_common;
|
||||
case 'O':
|
||||
case 'o':
|
||||
c = 8;
|
||||
unsigned_common:
|
||||
if (is_long)
|
||||
l = va_arg(ap, long);
|
||||
else
|
||||
l = va_arg(ap, int);
|
||||
p = ltoa_wd(p, l, c, 0);
|
||||
break;
|
||||
default:
|
||||
*p++ = c;
|
||||
break;
|
||||
}
|
||||
|
||||
i = (int)(p - s);
|
||||
if ((width -= i) < 0)
|
||||
width = 0;
|
||||
if (left_align == FALSE)
|
||||
width = -width;
|
||||
if (width < 0) {
|
||||
if (*s == '-' && filler == '0') {
|
||||
gfileWrite(f, s++, 1);
|
||||
ret++; if (--maxlen) return ret;
|
||||
i--;
|
||||
}
|
||||
do {
|
||||
gfileWrite(f, &filler, 1);
|
||||
ret++; if (--maxlen) return ret;
|
||||
} while (++width != 0);
|
||||
}
|
||||
while (--i >= 0) {
|
||||
gfileWrite(f, s++, 1);
|
||||
ret++; if (--maxlen) return ret;
|
||||
}
|
||||
while (width) {
|
||||
gfileWrite(f, &filler, 1);
|
||||
ret++; if (--maxlen) return ret;
|
||||
width--;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if GFILE_NEED_STRINGS
|
||||
int snprintg(char *buf, int maxlen, const char *fmt, ...) {
|
||||
int res;
|
||||
GFILE f;
|
||||
va_list ap;
|
||||
|
||||
if (maxlen <= 1) {
|
||||
if (maxlen == 1)
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
f.flags = GFILEFLG_OPEN|GFILEFLG_WRITE;
|
||||
f.vmt = &StringVMT;
|
||||
f.pos = 0;
|
||||
f.obj = buf;
|
||||
va_start(ap, fmt);
|
||||
res = vfnprintg(&f, maxlen-1, fmt, ap);
|
||||
va_end(ap);
|
||||
buf[res] = 0;
|
||||
return res;
|
||||
}
|
||||
int vsnprintg(char *buf, int maxlen, const char *fmt, va_list arg) {
|
||||
int res;
|
||||
GFILE f;
|
||||
|
||||
if (maxlen <= 1) {
|
||||
if (maxlen == 1)
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
f.flags = GFILEFLG_OPEN|GFILEFLG_WRITE;
|
||||
f.vmt = &StringVMT;
|
||||
f.pos = 0;
|
||||
f.obj = buf;
|
||||
res = vfnprintg(&f, maxlen-1, fmt, arg);
|
||||
buf[res] = 0;
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
* scang routines
|
||||
********************************************************/
|
||||
#if GFILE_NEED_SCANG
|
||||
int fscang(GFILE *f, const char *fmt, ...) {
|
||||
int res;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
res = vfscang(f, fmt, ap);
|
||||
va_end(ap);
|
||||
return res;
|
||||
}
|
||||
|
||||
int vfscang(GFILE *f, const char *fmt, va_list arg) {
|
||||
int res, width, size, base;
|
||||
char c;
|
||||
bool_t assign;
|
||||
void *p;
|
||||
|
||||
for(res = 0; *fmt; fmt++) {
|
||||
switch(*fmt) {
|
||||
case ' ': case '\t': case '\r': case '\n': case '\v': case '\f':
|
||||
break;
|
||||
|
||||
case '%':
|
||||
fmt++;
|
||||
assign = TRUE;
|
||||
width = 0;
|
||||
size = 1;
|
||||
|
||||
if (*fmt == '*') {
|
||||
fmt++;
|
||||
assign = FALSE;
|
||||
}
|
||||
while(*fmt >= '0' && *fmt <= '9')
|
||||
width = width * 10 + (*fmt++ - '0');
|
||||
if (*fmt == 'h') {
|
||||
fmt++;
|
||||
size = 0;
|
||||
} else if (*fmt == 'l') {
|
||||
fmt++;
|
||||
size = 2;
|
||||
} else if (*fmt == 'L') {
|
||||
fmt++;
|
||||
size = 3;
|
||||
}
|
||||
switch(*fmt) {
|
||||
case 0:
|
||||
return res;
|
||||
case '%':
|
||||
goto matchchar;
|
||||
case 'c':
|
||||
if (!width) {
|
||||
while(1) {
|
||||
if (!gfileRead(f, &c, 1)) return res;
|
||||
switch(c) {
|
||||
case ' ': case '\t': case '\r':
|
||||
case '\n': case '\v': case '\f': continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
width = 1;
|
||||
} else {
|
||||
if (!gfileRead(f, &c, 1)) return res;
|
||||
}
|
||||
if (assign) {
|
||||
p = va_arg(ap, char *);
|
||||
res++;
|
||||
*((char *)p)++ = c;
|
||||
}
|
||||
while(--width) {
|
||||
if (!gfileRead(f, &c, 1)) return res;
|
||||
if (assign) *((char *)p)++ = c;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
while(1) {
|
||||
if (!gfileRead(f, &c, 1)) return res;
|
||||
switch(c) {
|
||||
case ' ': case '\t': case '\r':
|
||||
case '\n': case '\v': case '\f': continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (assign) {
|
||||
p = va_arg(ap, char *);
|
||||
res++;
|
||||
*((char *)p)++ = c;
|
||||
}
|
||||
if (width) {
|
||||
while(--width) {
|
||||
if (!gfileRead(f, &c, 1)) {
|
||||
if (assign) *((char *)p) = 0;
|
||||
return res;
|
||||
}
|
||||
if (assign) *((char *)p)++ = c;
|
||||
}
|
||||
} else {
|
||||
while(1) {
|
||||
if (!gfileRead(f, &c, 1)) {
|
||||
if (assign) *((char *)p) = 0;
|
||||
return res;
|
||||
}
|
||||
switch(c) {
|
||||
case ' ': case '\t': case '\r':
|
||||
case '\n': case '\v': case '\f': break;
|
||||
default:
|
||||
if (assign) *((char *)p)++ = c;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
//ungetch(c);
|
||||
}
|
||||
if (assign) *((char *)p) = 0;
|
||||
break;
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'b':
|
||||
/*
|
||||
while (isspace (*buf))
|
||||
buf++;
|
||||
if (*s == 'd' || *s == 'u')
|
||||
base = 10;
|
||||
else if (*s == 'x')
|
||||
base = 16;
|
||||
else if (*s == 'o')
|
||||
base = 8;
|
||||
else if (*s == 'b')
|
||||
base = 2;
|
||||
if (!width) {
|
||||
if (isspace (*(s + 1)) || *(s + 1) == 0)
|
||||
width = strcspn (buf, ISSPACE);
|
||||
else
|
||||
width = strchr (buf, *(s + 1)) - buf;
|
||||
}
|
||||
strncpy (tmp, buf, width);
|
||||
tmp[width] = '\0';
|
||||
buf += width;
|
||||
if (!noassign)
|
||||
atob (va_arg (ap, u_int32_t *), tmp, base);
|
||||
}
|
||||
if (!noassign)
|
||||
count++;
|
||||
*/
|
||||
|
||||
#if GFILE_ALLOW_FLOATS
|
||||
case 'e': case 'f': case 'g':
|
||||
#endif
|
||||
default:
|
||||
return res;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
matchchar:
|
||||
while(1) {
|
||||
if (!gfileRead(f, &c, 1)) return res;
|
||||
switch(c) {
|
||||
case ' ': case '\t': case '\r':
|
||||
case '\n': case '\v': case '\f': continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (c != *fmt) return res;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#if GFILE_NEED_STRINGS
|
||||
int sscang(const char *buf, const char *fmt, ...) {
|
||||
int res;
|
||||
GFILE f;
|
||||
va_list ap;
|
||||
|
||||
f.flags = GFILEFLG_OPEN|GFILEFLG_READ;
|
||||
f.vmt = &StringVMT;
|
||||
f.pos = 0;
|
||||
f.obj = buf;
|
||||
va_start(ap, fmt);
|
||||
res = vfscang(&f, fmt, ap);
|
||||
va_end(ap);
|
||||
return res;
|
||||
}
|
||||
|
||||
int vsscang(const char *buf, const char *fmt, va_list arg) {
|
||||
int res;
|
||||
GFILE f;
|
||||
|
||||
f.flags = GFILEFLG_OPEN|GFILEFLG_READ;
|
||||
f.vmt = &StringVMT;
|
||||
f.pos = 0;
|
||||
f.obj = buf;
|
||||
res = vfscang(&f, fmt, arg);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/********************************************************
|
||||
* stdio emulation routines
|
||||
********************************************************/
|
||||
#if GFILE_NEED_STDIO
|
||||
size_t gstdioRead(void * ptr, size_t size, size_t count, FILE *f) {
|
||||
return gfileRead(f, ptr, size*count)/size;
|
||||
}
|
||||
size_t gstdioWrite(const void * ptr, size_t size, size_t count, FILE *f) {
|
||||
return gfileWrite(f, ptr, size*count)/size;
|
||||
}
|
||||
int gstdioSeek(FILE *f, size_t offset, int origin) {
|
||||
switch(origin) {
|
||||
case SEEK_SET:
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
offset += f->pos;
|
||||
break;
|
||||
case SEEK_END:
|
||||
offset += gfileGetSize(f);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return gfileSetPos(f, offset) ? 0 : -1;
|
||||
}
|
||||
int gstdioGetpos(FILE *f, long int *pos) {
|
||||
if (!(f->flags & GFILEFLG_OPEN))
|
||||
return -1;
|
||||
*pos = f->pos;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* GFX_USE_GFILE */
|
1
src/gfile/gfile.mk
Normal file
1
src/gfile/gfile.mk
Normal file
@ -0,0 +1 @@
|
||||
GFXSRC += $(GFXLIB)/src/gfile/gfile.c
|
46
src/gfile/inc_chibiosfs.c
Normal file
46
src/gfile/inc_chibiosfs.c
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is subject to the terms of the GFX License. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://ugfx.org/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is included by src/gfile/gfile.c
|
||||
*/
|
||||
|
||||
/********************************************************
|
||||
* The ChibiOS BaseFileStream file-system VMT
|
||||
********************************************************/
|
||||
|
||||
static void ChibiOSBFSClose(GFILE *f);
|
||||
static int ChibiOSBFSRead(GFILE *f, void *buf, int size);
|
||||
static int ChibiOSBFSWrite(GFILE *f, const void *buf, int size);
|
||||
static bool_t ChibiOSBFSSetpos(GFILE *f, long int pos);
|
||||
static long int ChibiOSBFSGetsize(GFILE *f);
|
||||
static bool_t ChibiOSBFSEof(GFILE *f);
|
||||
|
||||
static const GFILEVMT FsCHIBIOSVMT = {
|
||||
0, // next
|
||||
GFSFLG_SEEKABLE|GFSFLG_WRITEABLE, // flags
|
||||
0, // prefix
|
||||
0, 0, 0, 0,
|
||||
0, ChibiOSBFSClose, ChibiOSBFSRead, ChibiOSBFSWrite,
|
||||
ChibiOSBFSSetpos, ChibiOSBFSGetsize, ChibiOSBFSEof,
|
||||
};
|
||||
|
||||
static void ChibiOSBFSClose(GFILE *f) {
|
||||
chFileStreamClose(((BaseFileStream *)f->fd));
|
||||
}
|
||||
static int ChibiOSBFSRead(GFILE *f, void *buf, int size) {
|
||||
return chSequentialStreamRead(((BaseFileStream *)f->fd), (uint8_t *)buf, size);
|
||||
}
|
||||
static int ChibiOSBFSWrite(GFILE *f, const void *buf, int size) {
|
||||
return chSequentialStreamWrite(((BaseFileStream *)f->fd), (uint8_t *)buf, size);
|
||||
}
|
||||
static bool_t ChibiOSBFSSetpos(GFILE *f, long int pos) {
|
||||
chFileStreamSeek(((BaseFileStream *)f->fd), pos);
|
||||
return TRUE;
|
||||
}
|
||||
static long int ChibiOSBFSGetsize(GFILE *f) { return chFileStreamGetSize(((BaseFileStream *)f->fd)); }
|
||||
static bool_t ChibiOSBFSEof(GFILE *f) { return f->pos >= chFileStreamGetSize(((BaseFileStream *)f->fd)); }
|
15
src/gfile/inc_fatfs.c
Normal file
15
src/gfile/inc_fatfs.c
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* This file is subject to the terms of the GFX License. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://ugfx.org/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is included by src/gfile/gfile.c
|
||||
*/
|
||||
|
||||
/********************************************************
|
||||
* The FAT file-system VMT
|
||||
********************************************************/
|
||||
#error "GFILE: FATFS Not implemented yet"
|
43
src/gfile/inc_memfs.c
Normal file
43
src/gfile/inc_memfs.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is subject to the terms of the GFX License. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://ugfx.org/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is included by src/gfile/gfile.c
|
||||
*/
|
||||
|
||||
/********************************************************
|
||||
* The Memory pointer file-system VMT
|
||||
********************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static int MEMRead(GFILE *f, void *buf, int size);
|
||||
static int MEMWrite(GFILE *f, const void *buf, int size);
|
||||
static bool_t MEMSetpos(GFILE *f, long int pos);
|
||||
|
||||
static const GFILEVMT FsMemVMT = {
|
||||
0, // next
|
||||
GFSFLG_SEEKABLE|GFSFLG_WRITEABLE, // flags
|
||||
0, // prefix
|
||||
0, 0, 0, 0,
|
||||
0, 0, MEMRead, MEMWrite,
|
||||
MEMSetpos, 0, 0,
|
||||
};
|
||||
|
||||
static int MEMRead(GFILE *f, void *buf, int size) {
|
||||
memcpy(buf, ((char *)f->obj)+f->pos, size);
|
||||
return size;
|
||||
}
|
||||
static int MEMWrite(GFILE *f, const void *buf, int size) {
|
||||
memcpy(((char *)f->obj)+f->pos, buf, size);
|
||||
return size;
|
||||
}
|
||||
static bool_t MEMSetpos(GFILE *f, long int pos) {
|
||||
(void) f;
|
||||
(void) pos;
|
||||
return TRUE;
|
||||
}
|
102
src/gfile/inc_nativefs.c
Normal file
102
src/gfile/inc_nativefs.c
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is subject to the terms of the GFX License. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://ugfx.org/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is included by src/gfile/gfile.c
|
||||
*/
|
||||
|
||||
/********************************************************
|
||||
* The native file-system
|
||||
********************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
//#include <unistd.h>
|
||||
|
||||
static GFILE NativeStdIn;
|
||||
static GFILE NativeStdOut;
|
||||
static GFILE NativeStdErr;
|
||||
|
||||
static bool_t NativeDel(const char *fname);
|
||||
static bool_t NativeExists(const char *fname);
|
||||
static long int NativeFilesize(const char *fname);
|
||||
static bool_t NativeRen(const char *oldname, const char *newname);
|
||||
static bool_t NativeOpen(GFILE *f, const char *fname);
|
||||
static void NativeClose(GFILE *f);
|
||||
static int NativeRead(GFILE *f, void *buf, int size);
|
||||
static int NativeWrite(GFILE *f, const void *buf, int size);
|
||||
static bool_t NativeSetpos(GFILE *f, long int pos);
|
||||
static long int NativeGetsize(GFILE *f);
|
||||
static bool_t NativeEof(GFILE *f);
|
||||
|
||||
static const GFILEVMT FsNativeVMT = {
|
||||
GFILE_CHAINHEAD, // next
|
||||
#if defined(WIN32) || GFX_USE_OS_WIN32
|
||||
GFSFLG_TEXTMODES|
|
||||
#else
|
||||
GFSFLG_CASESENSITIVE|
|
||||
#endif
|
||||
GFSFLG_WRITEABLE|GFSFLG_SEEKABLE|GFSFLG_FAST, // flags
|
||||
'N', // prefix
|
||||
NativeDel, NativeExists, NativeFilesize, NativeRen,
|
||||
NativeOpen, NativeClose, NativeRead, NativeWrite,
|
||||
NativeSetpos, NativeGetsize, NativeEof,
|
||||
};
|
||||
#undef GFILE_CHAINHEAD
|
||||
#define GFILE_CHAINHEAD &FsNativeVMT
|
||||
|
||||
static void flags2mode(char *buf, uint16_t flags) {
|
||||
if (flags & GFILEFLG_MUSTEXIST)
|
||||
*buf = 'r';
|
||||
else if (flags & GFILEFLG_APPEND)
|
||||
*buf = 'a';
|
||||
else
|
||||
*buf = 'w';
|
||||
buf++;
|
||||
if ((flags & (GFILEFLG_READ|GFILEFLG_WRITE)) == (GFILEFLG_READ|GFILEFLG_WRITE))
|
||||
*buf++ = '+';
|
||||
if (flags & GFILEFLG_BINARY)
|
||||
*buf++ = 'b';
|
||||
if (flags & GFILEFLG_MUSTNOTEXIST)
|
||||
*buf++ = 'x';
|
||||
*buf++ = 0;
|
||||
}
|
||||
|
||||
static bool_t NativeDel(const char *fname) { return remove(fname) ? FALSE : TRUE; }
|
||||
static void NativeClose(GFILE *f) { fclose((FILE *)f->obj); }
|
||||
static int NativeRead(GFILE *f, void *buf, int size) { return fread(buf, 1, size, (FILE *)f->obj); }
|
||||
static int NativeWrite(GFILE *f, const void *buf, int size) { return fwrite(buf, 1, size, (FILE *)f->obj); }
|
||||
static bool_t NativeSetpos(GFILE *f, long int pos) { return fseek((FILE *)f->obj, pos, SEEK_SET) ? FALSE : TRUE; }
|
||||
static bool_t NativeEof(GFILE *f) { return feof((FILE *)f->obj) ? TRUE : FALSE; }
|
||||
static bool_t NativeRen(const char *oldname, const char *newname) { return rename(oldname, newname) ? FALSE : TRUE; }
|
||||
static bool_t NativeExists(const char *fname) {
|
||||
// We define access this way so we don't have to include <unistd.h> which may
|
||||
// (and does under windows) contain conflicting definitions for types such as uint16_t.
|
||||
extern int access(const char *pathname, int mode);
|
||||
return access(fname, 0) ? FALSE : TRUE;
|
||||
}
|
||||
static long int NativeFilesize(const char *fname) {
|
||||
struct stat st;
|
||||
if (stat(fname, &st)) return -1;
|
||||
return st.st_size;
|
||||
}
|
||||
static bool_t NativeOpen(GFILE *f, const char *fname) {
|
||||
FILE *fd;
|
||||
char mode[5];
|
||||
|
||||
flags2mode(mode, f->flags);
|
||||
if (!(fd = fopen(fname, mode)))
|
||||
return FALSE;
|
||||
f->obj = (void *)fd;
|
||||
return TRUE;
|
||||
}
|
||||
static long int NativeGetsize(GFILE *f) {
|
||||
struct stat st;
|
||||
if (fstat(fileno((FILE *)f->obj), &st)) return -1;
|
||||
return st.st_size;
|
||||
}
|
15
src/gfile/inc_ramfs.c
Normal file
15
src/gfile/inc_ramfs.c
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* This file is subject to the terms of the GFX License. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://ugfx.org/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is included by src/gfile/gfile.c
|
||||
*/
|
||||
|
||||
/********************************************************
|
||||
* The RAM file-system VMT
|
||||
********************************************************/
|
||||
#error "GFILE: RAMFS Not implemented yet"
|
95
src/gfile/inc_romfs.c
Normal file
95
src/gfile/inc_romfs.c
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is subject to the terms of the GFX License. If a copy of
|
||||
* the license was not distributed with this file, you can obtain one at:
|
||||
*
|
||||
* http://ugfx.org/license.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is included by src/gfile/gfile.c
|
||||
*/
|
||||
|
||||
/********************************************************
|
||||
* The ROM file-system VMT
|
||||
********************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// What directory file formats do we understand
|
||||
#define ROMFS_DIR_VER_MAX 0x0000
|
||||
|
||||
// Compression Formats
|
||||
#define ROMFS_CMP_UNCOMPRESSED 0
|
||||
|
||||
typedef struct ROMFS_DIRENTRY {
|
||||
uint16_t ver; // Directory Entry Version
|
||||
uint16_t cmp; // Compression format
|
||||
const struct ROMFS_DIRENTRY * next; // The next entry
|
||||
const char * name; // The file name
|
||||
long int size; // The file size
|
||||
const char * file; // The file data
|
||||
} ROMFS_DIRENTRY;
|
||||
|
||||
#define ROMFS_DIRENTRY_HEAD 0
|
||||
|
||||
#include "romfs_files.h"
|
||||
|
||||
static const ROMFS_DIRENTRY const *FsROMHead = ROMFS_DIRENTRY_HEAD;
|
||||
|
||||
static bool_t ROMExists(const char *fname);
|
||||
static long int ROMFilesize(const char *fname);
|
||||
static bool_t ROMOpen(GFILE *f, const char *fname);
|
||||
static void ROMClose(GFILE *f);
|
||||
static int ROMRead(GFILE *f, void *buf, int size);
|
||||
static bool_t ROMSetpos(GFILE *f, long int pos);
|
||||
static long int ROMGetsize(GFILE *f);
|
||||
static bool_t ROMEof(GFILE *f);
|
||||
|
||||
static const GFILEVMT FsROMVMT = {
|
||||
GFILE_CHAINHEAD, // next
|
||||
GFSFLG_CASESENSITIVE|GFSFLG_SEEKABLE|GFSFLG_FAST, // flags
|
||||
'S', // prefix
|
||||
0, ROMExists, ROMFilesize, 0,
|
||||
ROMOpen, ROMClose, ROMRead, 0,
|
||||
ROMSetpos, ROMGetsize, ROMEof,
|
||||
};
|
||||
#undef GFILE_CHAINHEAD
|
||||
#define GFILE_CHAINHEAD &FsROMVMT
|
||||
|
||||
static const ROMFS_DIRENTRY *ROMFindFile(const char *fname) {
|
||||
const ROMFS_DIRENTRY *p;
|
||||
|
||||
for(p = FsROMHead; p; p = p->next) {
|
||||
if (p->ver <= ROMFS_DIR_VER_MAX && p->cmp == ROMFS_CMP_UNCOMPRESSED && !strcmp(p->name, fname))
|
||||
break;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
static bool_t ROMExists(const char *fname) { return ROMFindFile(fname) != 0; }
|
||||
static long int ROMFilesize(const char *fname) {
|
||||
const ROMFS_DIRENTRY *p;
|
||||
|
||||
if (!(p = ROMFindFile(fname))) return -1;
|
||||
return p->size;
|
||||
}
|
||||
static bool_t ROMOpen(GFILE *f, const char *fname) {
|
||||
const ROMFS_DIRENTRY *p;
|
||||
|
||||
if (!(p = ROMFindFile(fname))) return FALSE;
|
||||
f->obj = (void *)p;
|
||||
return TRUE;
|
||||
}
|
||||
static void ROMClose(GFILE *f) { (void)f; }
|
||||
static int ROMRead(GFILE *f, void *buf, int size) {
|
||||
const ROMFS_DIRENTRY *p;
|
||||
|
||||
p = (const ROMFS_DIRENTRY *)f->obj;
|
||||
if (p->size - f->pos < size)
|
||||
size = p->size - f->pos;
|
||||
if (size <= 0) return 0;
|
||||
memcpy(buf, p->file+f->pos, size);
|
||||
return size;
|
||||
}
|
||||
static bool_t ROMSetpos(GFILE *f, long int pos) { return pos <= ((const ROMFS_DIRENTRY *)f->obj)->size; }
|
||||
static long int ROMGetsize(GFILE *f) { return ((const ROMFS_DIRENTRY *)f->obj)->size; }
|
||||
static bool_t ROMEof(GFILE *f) { return f->pos >= ((const ROMFS_DIRENTRY *)f->obj)->size; }
|
@ -139,14 +139,11 @@ GHandle gwinGImageCreate(GDisplay *g, GImageObject *gobj, GWindowInit *pInit) {
|
||||
return (GHandle)gobj;
|
||||
}
|
||||
|
||||
bool_t gwinImageOpenMemory(GHandle gh, const void* memory) {
|
||||
bool_t gwinImageOpenGFile(GHandle gh, GFILE *f) {
|
||||
if (gdispImageIsOpen(&widget(gh)->image))
|
||||
gdispImageClose(&widget(gh)->image);
|
||||
|
||||
if (!gdispImageSetMemoryReader(&widget(gh)->image, memory))
|
||||
return FALSE;
|
||||
|
||||
if (gdispImageOpen(&widget(gh)->image) != GDISP_IMAGE_ERR_OK)
|
||||
if ((gdispImageOpenGFile(&widget(gh)->image, f) & GDISP_IMAGE_ERR_UNRECOVERABLE))
|
||||
return FALSE;
|
||||
|
||||
if ((gh->flags & GWIN_FLG_VISIBLE)) {
|
||||
@ -161,54 +158,6 @@ bool_t gwinImageOpenMemory(GHandle gh, const void* memory) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_LINUX || GFX_USE_OS_OSX || defined(__DOXYGEN__)
|
||||
bool_t gwinImageOpenFile(GHandle gh, const char* filename) {
|
||||
if (gdispImageIsOpen(&widget(gh)->image))
|
||||
gdispImageClose(&widget(gh)->image);
|
||||
|
||||
if (!gdispImageSetFileReader(&widget(gh)->image, filename))
|
||||
return FALSE;
|
||||
|
||||
if (gdispImageOpen(&widget(gh)->image) != GDISP_IMAGE_ERR_OK)
|
||||
return FALSE;
|
||||
|
||||
if ((gh->flags & GWIN_FLG_VISIBLE)) {
|
||||
// Setting the clip here shouldn't be necessary if the redraw doesn't overdraw
|
||||
// but we put it in for safety anyway
|
||||
#if GDISP_NEED_CLIP
|
||||
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
|
||||
#endif
|
||||
_redraw(gh);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if GFX_USE_OS_CHIBIOS || defined(__DOXYGEN__)
|
||||
bool_t gwinImageOpenStream(GHandle gh, void *streamPtr) {
|
||||
if (gdispImageIsOpen(&widget(gh)->image))
|
||||
gdispImageClose(&widget(gh)->image);
|
||||
|
||||
if (!gdispImageSetBaseFileStreamReader(&widget(gh)->image, streamPtr))
|
||||
return FALSE;
|
||||
|
||||
if (gdispImageOpen(&widget(gh)->image) != GDISP_IMAGE_ERR_OK)
|
||||
return FALSE;
|
||||
|
||||
if ((gh->flags & GWIN_FLG_VISIBLE)) {
|
||||
// Setting the clip here shouldn't be necessary if the redraw doesn't overdraw
|
||||
// but we put it in for safety anyway
|
||||
#if GDISP_NEED_CLIP
|
||||
gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);
|
||||
#endif
|
||||
_redraw(gh);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
gdispImageError gwinImageCache(GHandle gh) {
|
||||
return gdispImageCache(&widget(gh)->image);
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
10
tools/file2c/src/Makefile.mingw32
Normal file
10
tools/file2c/src/Makefile.mingw32
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
CC = i686-pc-mingw32-gcc
|
||||
CFLAGS = -Wall -O2
|
||||
|
||||
all:
|
||||
$(CC) $(CFLAGS) -o file2c.exe file2c.c
|
||||
|
||||
clean:
|
||||
@rm file2c.exe
|
||||
|
@ -8,11 +8,14 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
static unsigned char buf[1024];
|
||||
static unsigned char buf[1024];
|
||||
static char tname[FILENAME_MAX];
|
||||
|
||||
static char *filenameof(char *fname) {
|
||||
char *p;
|
||||
@ -25,6 +28,13 @@ static char *filenameof(char *fname) {
|
||||
#endif
|
||||
p = strrchr(fname, '/');
|
||||
if (p) fname = p+1;
|
||||
return fname;
|
||||
}
|
||||
|
||||
static char *basenameof(char *fname) {
|
||||
char *p;
|
||||
|
||||
fname = filenameof(fname);
|
||||
p = strchr(fname, '.');
|
||||
if (p) *p = 0;
|
||||
return fname;
|
||||
@ -43,34 +53,35 @@ char * opt_progname;
|
||||
char * opt_inputfile;
|
||||
char * opt_outputfile;
|
||||
char * opt_arrayname;
|
||||
char * opt_dirname;
|
||||
int opt_breakblocks;
|
||||
int opt_romdir;
|
||||
char * opt_static;
|
||||
char * opt_const;
|
||||
FILE * f_input;
|
||||
FILE * f_output;
|
||||
unsigned blocknum;
|
||||
size_t len;
|
||||
size_t len, totallen;
|
||||
size_t i;
|
||||
|
||||
/* Default values for our parameters */
|
||||
opt_progname = filenameof(argv[0]);
|
||||
opt_inputfile = 0;
|
||||
opt_outputfile = 0;
|
||||
opt_arrayname = 0;
|
||||
opt_breakblocks = 0;
|
||||
opt_static = "";
|
||||
opt_const = "";
|
||||
opt_progname = basenameof(argv[0]);
|
||||
opt_inputfile = opt_outputfile = opt_arrayname = opt_dirname = 0;
|
||||
opt_breakblocks = opt_romdir = 0;
|
||||
opt_static = opt_const = "";
|
||||
|
||||
/* Read the arguments */
|
||||
while(*++argv) {
|
||||
if (argv[0][0] == '-') {
|
||||
while (*++(argv[0])) {
|
||||
switch(argv[0][0]) {
|
||||
case '?': case 'h': goto usage;
|
||||
case 'b': opt_breakblocks = 1; break;
|
||||
case 'c': opt_const = "const "; break;
|
||||
case 's': opt_static = "static "; break;
|
||||
case 'n': opt_arrayname = *++argv; goto nextarg;
|
||||
case '?': case 'h': goto usage;
|
||||
case 'd': opt_romdir = 1; break;
|
||||
case 'b': opt_breakblocks = 1; break;
|
||||
case 'c': opt_const = "const "; break;
|
||||
case 's': opt_static = "static "; break;
|
||||
case 'n': opt_arrayname = *++argv; goto nextarg;
|
||||
case 'f': opt_romdir = 1; opt_dirname = *++argv; goto nextarg;
|
||||
default:
|
||||
fprintf(stderr, "Unknown flag -%c\n", argv[0][0]);
|
||||
goto usage;
|
||||
@ -82,20 +93,28 @@ size_t i;
|
||||
opt_outputfile = argv[0];
|
||||
else {
|
||||
usage:
|
||||
fprintf(stderr, "Usage:\n\t%s -?\n"
|
||||
"\t%s [-bs] [-n name] [inputfile] [outputfile]\n"
|
||||
"\t\t-?\tThis help\n"
|
||||
"\t\t-h\tThis help\n"
|
||||
"\t\t-b\tBreak the arrays for compilers that won't handle large arrays\n"
|
||||
"\t\t-c\tDeclare the arrays as const (useful to ensure they end up in Flash)\n"
|
||||
"\t\t-s\tDeclare the arrays as static\n"
|
||||
"\t\t-n name\tUse \"name\" as the name of the array\n"
|
||||
fprintf(stderr, "Usage:\n\n%s -?\n"
|
||||
"%s [-dbcs] [-n name] [-f file] [inputfile] [outputfile]\n"
|
||||
"\t-?\tThis help\n"
|
||||
"\t-h\tThis help\n"
|
||||
"\t-d\tAdd a directory entry for the ROM file system\n"
|
||||
"\t-b\tBreak the arrays for compilers that won't handle large arrays\n"
|
||||
"\t-c\tDeclare as const (useful to ensure they end up in Flash)\n"
|
||||
"\t-s\tDeclare as static\n"
|
||||
"\t-n name\tUse \"name\" as the name of the array\n"
|
||||
"\t-f file\tUse \"file\" as the filename in the ROM directory entry\n"
|
||||
, opt_progname, opt_progname);
|
||||
return 1;
|
||||
}
|
||||
nextarg: ;
|
||||
}
|
||||
|
||||
/* Make sure we can generate a default directory name if required */
|
||||
if (opt_romdir && !opt_dirname && !opt_inputfile) {
|
||||
fprintf(stderr, "If using -d you must either specify an input filename or use -f to specify a directory entry filename\n");
|
||||
goto usage;
|
||||
}
|
||||
|
||||
/* Open the input file */
|
||||
if (opt_inputfile) {
|
||||
f_input = fopen(opt_inputfile,
|
||||
@ -129,43 +148,57 @@ size_t i;
|
||||
fprintf(f_output, "/**\n * This file was generated ");
|
||||
if (opt_inputfile) fprintf(f_output, "from \"%s\" ", opt_inputfile);
|
||||
fprintf(f_output, "using...\n *\n *\t%s", opt_progname);
|
||||
if (opt_arrayname || opt_static[0] || opt_const[0] || opt_breakblocks) {
|
||||
if (opt_arrayname || opt_static[0] || opt_const[0] || opt_breakblocks || opt_romdir) {
|
||||
fprintf(f_output, " -");
|
||||
if (opt_romdir) fprintf(f_output, "b");
|
||||
if (opt_breakblocks) fprintf(f_output, "b");
|
||||
if (opt_const[0]) fprintf(f_output, "c");
|
||||
if (opt_static[0]) fprintf(f_output, "s");
|
||||
if (opt_arrayname) fprintf(f_output, "n %s", opt_arrayname);
|
||||
if (opt_dirname) fprintf(f_output, (opt_arrayname ? " -f %s" : "f %s"), opt_dirname);
|
||||
}
|
||||
if (opt_inputfile) fprintf(f_output, " %s", opt_inputfile);
|
||||
if (opt_outputfile) fprintf(f_output, " %s", opt_outputfile);
|
||||
fprintf(f_output, "\n *\n */\n");
|
||||
|
||||
/*
|
||||
* Set the array name.
|
||||
* We do this after printing opt_inputfile for the last time as we
|
||||
* modify opt_inputfile in place to generate opt_arrayname.
|
||||
* Set the array name and dir name
|
||||
*/
|
||||
if (!opt_arrayname) {
|
||||
if (opt_inputfile)
|
||||
opt_arrayname = filenameof(opt_inputfile);
|
||||
if (!opt_arrayname || !opt_arrayname[0])
|
||||
opt_arrayname = "filearray";
|
||||
opt_arrayname = basenameof(strcpy(tname, opt_inputfile));
|
||||
if (!opt_arrayname || !opt_arrayname[0]) {
|
||||
srand(time(NULL));
|
||||
sprintf(tname, "filearray%u", rand());
|
||||
opt_arrayname = tname;
|
||||
}
|
||||
}
|
||||
opt_arrayname = clean4c(opt_arrayname);
|
||||
if (opt_romdir && !opt_dirname)
|
||||
opt_dirname = filenameof(opt_inputfile);
|
||||
|
||||
/* Read the file processing 1K at a time */
|
||||
blocknum = 0;
|
||||
totallen = 0;
|
||||
while((len = fread(buf, 1, sizeof(buf), f_input))) {
|
||||
if (!blocknum++)
|
||||
fprintf(f_output, "%s%sunsigned char %s[] = {", opt_static, opt_const, opt_arrayname);
|
||||
fprintf(f_output, "%s%schar %s[] = {", opt_static, opt_const, opt_arrayname);
|
||||
else if (opt_breakblocks)
|
||||
fprintf(f_output, "\n};\n%s%sunsigned char %s_p%u[] = {", opt_static, opt_const, opt_arrayname, blocknum);
|
||||
fprintf(f_output, "\n};\n%s%schar %s_p%u[] = {", opt_static, opt_const, opt_arrayname, blocknum);
|
||||
for(i = 0; i < len; i++) {
|
||||
fprintf(f_output, (i & 0x0F) ? " 0x%02X," : "\n\t0x%02X,", buf[i]);
|
||||
}
|
||||
totallen += len;
|
||||
}
|
||||
fprintf(f_output, "\n};\n");
|
||||
|
||||
/* Add the directory entry if required */
|
||||
if (opt_romdir) {
|
||||
fprintf(f_output, "\n#ifdef ROMFS_DIRENTRY_HEAD\n");
|
||||
fprintf(f_output, "\t%s%sROMFS_DIRENTRY %s_dir = { 0, 0, ROMFS_DIRENTRY_HEAD, \"%s\", %u, %s };\n", opt_static, opt_const, opt_arrayname, opt_dirname, totallen, opt_arrayname);
|
||||
fprintf(f_output, "\t#undef ROMFS_DIRENTRY_HEAD\n\t#define ROMFS_DIRENTRY_HEAD &%s_dir\n#endif\n", opt_arrayname);
|
||||
}
|
||||
|
||||
/* Clean up */
|
||||
if (ferror(f_input))
|
||||
fprintf(stderr, "Input file read error\n");
|
||||
|
Loading…
Reference in New Issue
Block a user