# Function for rendering custom fonts

I have a function that converts any normal true-type font to my own font file .bff That function works correct and am not going to post that function for that matter (the function is also only compatible with a specific engine you may not hear about).

If I post the .bff file and you have an environment in which you could use putpixel(x, y) to put a pixel (for e.g a red one) on the x and y spot, then you can also test my rendering function.

Let me first explain my custom compression method:

I call "Arlo compression" vername "Arlo1" with compression level over 60%. You have to understand the compression before take a look at the rendering function.

• Standart characters (dec 48+) to represent whitespaces. 5 will represent 5 spaces and so forth
• After each space a pixel is placed. So if there is 00 it puts two pixels right next to each other if there is 20 it puts 1 pixel after 2 spaces and one pixel as a next.
• Important: to prevent a vertical line after each character the rendering function is made to not put pixel after the last space-representing character of the line determined (that is what causes problems - some characters needs a pixel at the end and it renders them cropped (without these last pixels) thanks to the vertical-line prevention condition.
• # character found in the bff means new line of the character
• & character found in the bff means offset for next character
• Characters are with ascii sequence, dec32-126

The function:

typedef unsigned char BYTE;

void
bitfox_render_text
(char *FONTNEX, char *STRING, int X_OFFSET, int Y_OFFSET)
{
FILE* fp = fopen(FONTNEX, "r");
char *buffer = STRING, *font;
int fontsize, buffsize = strlen(buffer), strl;
int line = 0, linep = 0, colp = 0;

fseek(fp, EOF, SEEK_END);
fontsize = ftell(fp);
font = malloc(fontsize);
rewind(fp);
fclose(fp);

for(strl=0; strl<buffsize; strl++)
{
int chrOffset, chr = 32;

// In-line code for finding the current index of characters
for(chrOffset=0; chr != buffer[strl]; chrOffset++) { if(font[chrOffset] == '&') { chr++; }} // <--

do
{   linep++;
if
(font[chrOffset+linep] == '#') { colp++; line = 0; }
else if
(font[chrOffset+(linep+1)] != '#')  // if not NL and w/o ending supplement:
{
// there is a function that describes size and color of the brush here
putpixel(X_OFFSET+(line+=(font[chrOffset+linep]-48)+1), Y_OFFSET+colp);
}
} while(font[chrOffset+(linep+1)] != '&');
}
free(font);
}


The function currently reads successfully only one character passed as a string. Don't mind the arguments currently not used. Despite the fact that this function is not fully functional.. the only problem is the condition: (font[chrOffset+(linep+1)] != '#') // if not NL and w/o ending supplement It prevents for putting pixels at the end of each line. If i remove that condition.. there will be a vertical line at the end of each character.. if it remains, some characters that need these pixels will be rendered cropped.

I will be doing constant edits to improve the level of clarification. Here is the download link of the .bff that response for the .ttf file "arial.ttf size 11 Normal".

Summary: The .bff file or "Bitfox Font File" is a custom font file, with custom compression method impiled ("Arlo1"). Each character from the ascii in the range of 32 to 126 in sequence is represented in raster-type where # determines there is a new line and & determines next character. To indicate where is a pixel placed, the current character's data consists of ascii characters (dec48-126) that represent whitespaces. The pixel is placed after the sapce is determined with chr-48. For the sake of the unrequired pixels prevention, the rendering function won't place pixels when the last character of the line is readed. That causes some characters to be cropped with 1 pixel at their end.

• I've noticed you've edited the original code snippet. Take a look at this: meta.codereview.stackexchange.com/questions/1763/… Oct 18, 2014 at 3:18
• Yes, okay. I'm not going to do that anymore. It was effort for good though and i hope someone can assist me in this after all. Oct 18, 2014 at 3:37

I'm not going to comment on the algorithm or functionality, however, there are several aspects in this code that make it very hard to read and understand.

Strange variable naming:

Most programmers associate names in ALL_CAPS with macros and constants (Windows programmers might also like that notation for typedefs), which makes them very unsuited for variable and parameter names. X_OFFSET, STRING, and the others would be much better as x_offset, string, and so on.

Unused parameter:

BYTE CLRSPACE[][3] is not used by the function. Should be removed or at least referenced with a (void) to suppress compiler warnings:

{
(void)CLRSPACE;
...


Too many things in a line:

You have no idea how these lines combining several statements can hurt readability. A few instances:

char *buffer = STRING, *font; int xo = X_OFFSET, yo = Y_OFFSET;
...
fseek(fp, EOF, SEEK_END); fontsize = ftell(fp); font = malloc(fontsize); rewind(fp);


A much clearer layout:

char *buffer = STRING, *font;
int xo = X_OFFSET, yo = Y_OFFSET;
...
fseek(fp, EOF, SEEK_END);
fontsize = ftell(fp);
font = malloc(fontsize);
rewind(fp);


Inconsistent statement layout:

You have different ways of indenting and positioning your control statements. This one in particular is very awkward:

if
(font[chrOffset+linep] == '#') { colp++; line = 0; }
else if
(font[chrOffset+(linep+1)] != '#')  // if not NL and w/o ending supplement:
{
...
}


Re-arrange that to a more natural way an be consistent with all your code:

if (font[chrOffset+linep] == '#')
{
colp++;
line = 0;
}
else if (font[chrOffset+(linep+1)] != '#')  // if not NL and w/o ending supplement:
{
...
}


Here, at the end of the function, another strange arrangement:

    } free(font);
return;
}


free(font) should be in its own line. The return is not necessary, as this is a void function.

Mysterious statement:

It seems that in here:

int chrOffset, chr = 32; _ = chrOffset;


You have declared (or re-assigned) a variable named _. I have no idea what that is supposed to mean, as there are no further references to _. A variable named _ is already pretty bad by itself. This code here, I'm not even sure if it would compile...

There are probably more aspects to consider, but that's all I can tell you for now. Hope the advices are useful.

• For reading the code - yes (I'll edit tomorrow) But the code isn't supposed to be readable anyway. Only functional. Oct 18, 2014 at 0:50
• @Edenia, Why would you not want the code to be readable? Hight-level languages, such as C, are meant first and foremost to be human readable. If readability wasn't a concern, we would still be doing everything in assembly. Oct 18, 2014 at 1:16
• (C is Low level Programming Language) Oct 18, 2014 at 1:18
• Not according to wikipedia "Examples of popular high-level programming languages today may include C++, C, Java, Python ..." Oct 18, 2014 at 1:22
• I wouldn't go as far putting C in the same stance of Python, VB, JS and other scripting languages as in that statement from wikipedia, but it is certainly very hight level. Oct 18, 2014 at 1:26