Open Font Render 1.2
Loading...
Searching...
No Matches
How to load font files from file system

Control of file systems such as SD/TF cards and SPIFFS is strongly hardware-dependent.
OpenFontRender supports the following reads as presets.

How to use preset

If you only use a preset, simply include a header in your code.
However, the file system initialization code must be written in the user code.

See example for complete code.

// (omitted)
#include "OpenFontRender.h"
#include "ofrfs/M5Stack_SD_Preset.h" // Use preset
void setup()
{
// put your setup code here, to run once:
auto cfg = M5.config();
M5.begin(cfg);
M5.Display.fillScreen(TFT_BLACK);
// File system initialization code
SD.begin(GPIO_NUM_4, SPI, 40000000);
render.setSerial(Serial); // Need to print render library message
render.showFreeTypeVersion(); // print FreeType version
render.showCredit(); // print FTL credit
if (render.loadFont("/JKG-M_3_Tiny.ttf"))
{
Serial.println("Render initialize error");
return;
}
render.setDrawer(M5.Display); // Set drawer object
// (omitted)
Definition: OpenFontRender.h:183
void setDrawer(T &drawer)
Collectively set up screen control functions.
Definition: OpenFontRender.h:296
FT_Error loadFont(const unsigned char *data, size_t size, uint8_t target_face_index=0)
Load font from memory.
Definition: OpenFontRender.cpp:424
void showCredit()
Show FreeType credit.
Definition: OpenFontRender.cpp:1226
void showFreeTypeVersion()
Show using FreeType version.
Definition: OpenFontRender.cpp:1213
static void setSerial(T &output)
Set up serial output control functions.
Definition: OpenFontRender.h:319

How to read from a file system without presets

If you want to use a microcomputer or file system for which no presets are provided, you have to write a custom code.
There are five global functions you have to write.

  • OFR_fclose (fclose)
  • OFR_fopen (fopen)
  • OFR_fread (fread)
  • OFR_fseek (fseek)
  • OFR_ftell (ftell)

The processing performed by these is the same as the C language functions inside the parentheses.
A step-by-step implementation flow is shown below.
In this explain, the hardware will use M5Stack and assume reading from an SD card.

1. Declare file object

First, declare the file object in global scope.
Since the file object will continue to be used for the entire time the file is open, we declare it in global scope, not local scope.

File myFile;

2. Implement the OFR_fopen

Next, implement the OFR_fopen function, which handles file opening.
The arguments and return values are as follows.

type variable mean
argument filename The path to the file to be opened.
argument mode File access mode.
return Pointer to the file object.

The details of the arguments filename and mode are the same as for the C language fopen function.

The reference implementation below opens a file with SD.open and returns a pointer to the file object.

FT_FILE *OFR_fopen(const char *filename, const char *mode)
{
myFile = SD.open(filename, mode);
return &myFile;
}
FT_FILE * OFR_fopen(const char *filename, const char *mode)
Open file and get file pointer.
Definition: FileSupport.cpp:93
#define FT_FILE
Definition: FileSupport.h:16

3. Implement the OFR_fclose

Next, implement the OFR_close function, which handles file closing.

The arguments and return values are as follows.

type variable mean
argument stream Pointer to the file object.
In this example, it is a pointer to myFile.
return None
Note
File object pointer that given as argument must ALWAYS be cast before use in a function.

The reference implementation below.
Also ((File *)stream)->close() has the same meaning as myFile.close().

void OFR_fclose(FT_FILE *stream)
{
((File *)stream)->close();
}
void OFR_fclose(FT_FILE *stream)
Close file.
Definition: FileSupport.cpp:82

4. Implement the OFR_fread

Next, implement the OFR_fread function, which handles file reading.
The arguments and return values are as follows.

type variable mean
argument ptr Pointer to the array where the read objects are stored.
argument size Size of each object in bytes.
argument nmemb The number of the objects to be read.
argument stream Pointer to the file object.
return Number of objects read successfully.

The details of the arguments are the same as for the C language fread function.

Note
File object pointer that given as argument must ALWAYS be cast before use in a function.

The reference implementation below.

size_t OFR_fread(void *ptr, size_t size, size_t nmemb, FT_FILE *stream)
{
return ((File *)stream)->read((uint8_t *)ptr, size * nmemb);
}
size_t OFR_fread(void *ptr, size_t size, size_t nmemb, FT_FILE *stream)
Read data from a file and store it in a buffer.
Definition: FileSupport.cpp:107

5. Implement the OFR_fseek

Next, implement the OFR_fseek function, which handles moving file pointer.
The arguments and return values are as follows.

type variable mean
argument stream Pointer to the file object.
argument offset Number of characters to shift the position relative to origin.
argument whence Position to which offset is added.
return 0​ upon success, nonzero value otherwise.

The details of the arguments are the same as for the C language fseek function.

Note
File object pointer that given as argument must ALWAYS be cast before use in a function.

The reference implementation below.

int OFR_fseek(FT_FILE *stream, long int offset, int whence)
{
return ((File *)stream)->seek(offset, (SeekMode)whence);
}
int OFR_fseek(FT_FILE *stream, long int offset, int whence)
Moves the cursor to the specified position.
Definition: FileSupport.cpp:120

6. Implement the OFR_ftell

Finally, implement the OFR_ftell function, which get current position of the file pointer within a file.
The arguments and return values are as follows.

type variable mean
argument stream Pointer to the file object.
return File position indicator on success or -1L if failure occurs.

The details of the arguments are the same as for the C language ftell function.

Note
File object pointer that given as argument must ALWAYS be cast before use in a function.

The reference implementation below.

long int OFR_ftell(FT_FILE *stream)
{
return ((File *)stream)->position();
}
long int OFR_ftell(FT_FILE *stream)
Get file cursor position.
Definition: FileSupport.cpp:131

Conclusion

All implementation is now complete. The entire sample program is shown. However, unnecessary parts before and after are omitted (...).
See example for complete code.

// (omitted)
#include "OpenFontRender.h" // Include after M5Unified.h
/*=== Overwrite SD (File) operation methods BEGIN ===*/
File myFile;
FT_FILE *OFR_fopen(const char *filename, const char *mode)
{
myFile = SD.open(filename, mode);
return &myFile;
}
void OFR_fclose(FT_FILE *stream)
{
// myFile.close()
((File *)stream)->close();
}
size_t OFR_fread(void *ptr, size_t size, size_t nmemb, FT_FILE *stream)
{
// myFile.read()
return ((File *)stream)->read((uint8_t *)ptr, size * nmemb);
}
int OFR_fseek(FT_FILE *stream, long int offset, int whence)
{
// myFile.seek()
return ((File *)stream)->seek(offset, (SeekMode)whence);
}
long int OFR_ftell(FT_FILE *stream)
{
// myFile.position()
return ((File *)stream)->position();
}
/*=== Overwrite SD (File) operation methods END ===*/
void setup()
{
// (omitted)