281 lines
6.2 KiB
C
281 lines
6.2 KiB
C
// Font 2 Text for MD_MAX72xx library
|
|
//
|
|
// Quick and not very robust code to create a font defintion text file
|
|
// from an existing font data table. This is considered a one-off task
|
|
// followed by some manual editing of the file.
|
|
// The file is expected to be in the similar format to the output from
|
|
// txt2font. Specifically,
|
|
// - it is expected that each character is on one data line in order to
|
|
// recognise specific parts, like comments.
|
|
// - it expects all the ascii codes to be present (ie, it does not respect
|
|
// the version information at the start of the table)
|
|
//
|
|
// The shared header file means that some elements in this
|
|
// code are reversed (eg, the IN file extension is used as the OUT file
|
|
// extension). Each font element is output as it is completed, without
|
|
// buffering the while ASCII set.
|
|
//
|
|
#include "txt2font.h"
|
|
|
|
// Global data ---------------
|
|
Global_t G;
|
|
ASCIIDef_t font = { 0 };
|
|
|
|
// Code ----------------------
|
|
void usage(void)
|
|
{
|
|
printf("\nusage: font2txt <root_name>\n");
|
|
printf("\n\ninput file <root_name>.h");
|
|
printf("\noutput file <root_name>.txt");
|
|
printf("\n");
|
|
|
|
return;
|
|
}
|
|
|
|
int cmdLine(int argc, char *argv[])
|
|
// process the command line parameter
|
|
{
|
|
if (argc != 2)
|
|
return(1);
|
|
|
|
strcpy(G.fileRoot, argv[1]);
|
|
|
|
return(0);
|
|
}
|
|
|
|
int initialise(void)
|
|
// one time initiualisation code
|
|
{
|
|
char szFile[FILE_NAME_SIZE];
|
|
|
|
// we have no font definition
|
|
font.comment[0] = NUL;
|
|
font.size = 0;
|
|
font.buf = malloc(100*sizeof(font.buf[0])); // pick a big number...
|
|
|
|
// open the file for reading
|
|
strcpy(szFile, G.fileRoot);
|
|
strcat(szFile, OUT_FILE_EXT);
|
|
if ((G.fpIn = fopen(szFile, "r")) == NULL)
|
|
{
|
|
printf("\nCannot open input ""%s\n""", szFile);
|
|
return(2);
|
|
}
|
|
|
|
// open the file for writing
|
|
strcpy(szFile, G.fileRoot);
|
|
strcat(szFile, IN_FILE_EXT);
|
|
if ((G.fpOut = fopen(szFile, "w")) == NULL)
|
|
{
|
|
printf("\nCannot open output ""%s\n""", szFile);
|
|
return(3);
|
|
}
|
|
|
|
// other stuff
|
|
G.name[0] = NUL;
|
|
G.doubleHeight = 0;
|
|
G.bufSize = SINGLE_HEIGHT;
|
|
G.fixedWidth = 0;
|
|
|
|
return(0);
|
|
}
|
|
|
|
void trimBuffer(char *buf)
|
|
// trim the buffer specified of all trailing white space
|
|
{
|
|
int i = strlen(buf)-1;
|
|
|
|
while (i > 0 && isspace(buf[i]))
|
|
buf[i--] = NUL;
|
|
|
|
return;
|
|
}
|
|
|
|
void padBuffer(char *buf, unsigned int len)
|
|
// pad the supplied buffer with spaces up to the length specified
|
|
{
|
|
if (strlen(buf) < len)
|
|
{
|
|
for (unsigned int j=strlen(buf); j<len; j++)
|
|
buf[j] = SPACE;
|
|
}
|
|
buf[len] = NUL;
|
|
|
|
return;
|
|
}
|
|
|
|
unsigned int normaliseBuffers(void)
|
|
// normalise all the input buffers to the same size
|
|
{
|
|
unsigned int max = 0;
|
|
|
|
if (G.fixedWidth == 0)
|
|
{
|
|
for (unsigned int i=0; i<G.bufSize; i++)
|
|
max = max < strlen(G.buf[i]) ? max = strlen(G.buf[i]) : max;
|
|
}
|
|
else
|
|
max = G.fixedWidth;
|
|
|
|
// now make them all the same size
|
|
for (unsigned int i=0; i<G.bufSize; i++)
|
|
{
|
|
padBuffer(G.buf[i], max);
|
|
}
|
|
|
|
return(max);
|
|
}
|
|
|
|
char *getToken(char *buf)
|
|
// isolate the first token in the buffer and return a pointer to the next non white space after the token
|
|
{
|
|
while (isspace(*buf) || ispunct(*buf))
|
|
buf++;
|
|
while (!isspace(*buf) && !ispunct(*buf))
|
|
buf++;
|
|
*buf++ = NUL;
|
|
while (isspace(*buf) || ispunct(*buf))
|
|
buf++;
|
|
|
|
return(buf);
|
|
}
|
|
|
|
void saveOutputHeader(void)
|
|
// save the current definition as a font definition header file
|
|
{
|
|
fprintf(G.fpOut, "%c%s %s\n", DOT, CMD_NAME, G.fileRoot);
|
|
fprintf(G.fpOut, "%c%s %d\n", DOT, CMD_HEIGHT, (G.doubleHeight ? 2: 1));
|
|
fprintf(G.fpOut, "%c%s %d\n", DOT, CMD_WIDTH, G.fixedWidth);
|
|
fprintf(G.fpOut, "%c%s %d %s\n", DOT, CMD_FONTHIGH, G.fontHeight, "<- THIS NEEDS EDITING");
|
|
|
|
return;
|
|
}
|
|
|
|
void saveOutputFooter(void)
|
|
// save the current definition as a font definition header file
|
|
{
|
|
fprintf(G.fpOut, "%c%s\n", DOT, CMD_END);
|
|
|
|
return;
|
|
}
|
|
|
|
void saveOutputChar(void)
|
|
// Save a single character definition
|
|
{
|
|
fprintf(G.fpOut, "%c%s %d\n", DOT, CMD_CHAR, G.curCode);
|
|
fprintf(G.fpOut, "%c%s %s\n", DOT, CMD_NOTE, font.comment);
|
|
|
|
if (G.bufSize != 0)
|
|
{
|
|
for (unsigned int i=0; i<G.bufSize; i++)
|
|
{
|
|
trimBuffer(G.buf[i]);
|
|
fprintf(G.fpOut, "%s\n", G.buf[i]);
|
|
}
|
|
}
|
|
else // need at least one line
|
|
fprintf(G.fpOut, "\n");
|
|
|
|
return;
|
|
}
|
|
|
|
void createFontData(char *cp)
|
|
// the font defintions strings are column data, so each byte will be a 'vertical'
|
|
// stripe of the input buffers. Format is the size followed by size bytes of column data,
|
|
// separated by commas. The comment is found after the data in a '//' comment and following
|
|
// the first '-'.
|
|
{
|
|
char *cpNext;
|
|
|
|
cpNext = getToken(cp);
|
|
font.size = atoi(cp);
|
|
cp = cpNext;
|
|
|
|
// get all the data from the input into the font defintion
|
|
for (unsigned int i=0; i<font.size; i++)
|
|
{
|
|
// get the data
|
|
cpNext = getToken(cp);
|
|
font.buf[i] = atoi(cp);
|
|
cp = cpNext;
|
|
}
|
|
|
|
// unpack the column data into the text strings
|
|
// create each input string [j] in turn from the column definition [i] for the char
|
|
for (unsigned int i=0; i<SINGLE_HEIGHT; i++)
|
|
{
|
|
for (unsigned int j=0; j<font.size; j++)
|
|
G.buf[i][j] = (font.buf[j] & (1<<i)) ? STAR : SPACE;
|
|
G.buf[i][font.size] = NUL; // terminate the string
|
|
}
|
|
|
|
// save the comment - first search up to after the first '-'
|
|
while ((*cp != '-') && (*cp != NUL))
|
|
cp++;
|
|
if (cp != NUL) cp++;
|
|
strcpy(font.comment, cp);
|
|
|
|
return;
|
|
}
|
|
|
|
void processInput(void)
|
|
// read the input file and process line by line
|
|
{
|
|
char c, inLine[INPUT_BUFFER_SIZE];
|
|
|
|
// skip to the opening brace then skip end of line
|
|
do
|
|
c = getc(G.fpIn);
|
|
while ((c != EOF) && (c != '{'));
|
|
do
|
|
c = getc(G.fpIn);
|
|
while ((c == '\n') || (c == '\r'));
|
|
|
|
// now read each line in turn
|
|
while (!feof(G.fpIn) && (G.curCode < ASCII_SIZE))
|
|
{
|
|
fgets(inLine, sizeof(inLine), G.fpIn);
|
|
|
|
// if we have a blank line, get another one
|
|
trimBuffer(inLine);
|
|
if (strlen(inLine) == 0) continue;
|
|
|
|
// process the buffers into a font definition and write out what we have created
|
|
createFontData(inLine);
|
|
saveOutputChar();
|
|
|
|
// reset the font and character buffers, increment current ASCII code
|
|
for (unsigned int i=0; i<G.bufSize; i++)
|
|
G.buf[i][0] = NUL;
|
|
font.size = 0;
|
|
G.curCode++;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int ret;
|
|
|
|
if (cmdLine(argc, argv))
|
|
{
|
|
usage();
|
|
return(1);
|
|
}
|
|
|
|
if ((ret = initialise()) != 0)
|
|
return(ret);
|
|
|
|
saveOutputHeader();
|
|
processInput();
|
|
saveOutputFooter();
|
|
|
|
|
|
// close files and exit
|
|
fclose(G.fpIn);
|
|
fclose(G.fpOut);
|
|
|
|
return(0);
|
|
}
|