Advertisement

Font engines

Started by March 13, 2000 03:26 AM
14 comments, last by Spiff 24 years, 7 months ago
How do you do your font engines? I''ve been working on one this weekend and what I''ve come up with this far is: 1. Load a bitmap file to a surface containing the font gfx 2. Load a .fnt file (contains a RECT for every font character to specify where the font is on the bitmap 3. Draw the font by getting the character from a character list (using 87 characters), getting the RECT for the font bitmap and drawing it on the specified destination RECT Are there any faster/better ways of doing this? I want it to be fast and flexible. ============================ Daniel Netz, Sentinel Design "I'm not stupid, I'm from Sweden" - Unknown
============================Daniel Netz, Sentinel Design"I'm not stupid, I'm from Sweden" - Unknown
That''s essentially the way I''m doing it, though I''ve combined the rect information and the bitmap data into a single file. The only other difference is that my fonts can have as many (or as few) characters as you wish (I set it up so that it can do DBCS and Unicode if necessary) to make it easier to do different character sets, or limit the amount of memory it''s taking up in the case that I''m only going to do numbers or other similar character limiting tasks.

Another way to do fonts is to use windows fonts and get a DC for a surface and draw your text to the surface (and then save the surface if you intend to use it more than once). The biggest disadvantage to this (other than possible speed issues) is that your fonts tend to look like Windows (or operating system) fonts.



Mark Fassett
Laughing Dragon Entertainment
http://www.laughing-dragon.com

Mark Fassett

Laughing Dragon Games

http://www.laughing-dragon.com

Advertisement
The way you''re doing it seems to be as fast and flexible as any other way I have seen. At least if you''re putting all of these RECTs in an array that can be indexed by character value.

As I''m sure you know it isn''t very funny create the .fnt file in a text editor though. But if you haven''t created a font editor you can use the following way of creating the font file.

I assume fixed size font because if it isn''t this way will not work.

In your font file you can specify the size of each character and then give some strings of characters that give the layout of the characters. Here''s an example of the font file

8 8 // Width and Height"abcdefghijkl""mnopqrstuvwx""yz0123456789""ABCDEFGHIJKL""MNOPQRSTUVWX""YZ+-=*/''_ "


When the file is loaded the position of each character is calculated by it''s position in the strings, for example ''a'' would be placed at (0,0) and ''J'' at (80,24).
LaughingD: One other disadvantage of using DrawText() or TextOut() besides the speed is that you have to install the font on the system, thus letting the computer owner use it as they please.

I''ve thought about merging the font descriptor file with the bitmap data, but I''m using DirectX7 for VB and I''m not that good with binary files yet.

"As I''m sure you know it isn''t very funny create the .fnt file in a text editor though" - I though of making a DirectDraw font editor to define the RECT of the font character, but I won''t be doing alot of fonts, so I created a program that saves the RECT you specify for the character. That''s easier than doing it in a text editor, also keeps your data intact and saves alot of time from doing a full featured font editor.

As it is now, I lookup every character from my character list, since it doesn''t feature the whole ASCII table (only the ones I will be needing), so it''s quite slow, but I''m thinking of doing a "transparent" function that saves the string converted to the character list values instead, saving the time it takes to look them up. Another way is to create another surface and only draw the font once, to save time.

============================
Daniel Netz, Sentinel Design
"I'm not stupid, I'm from Sweden" - Unknown
============================Daniel Netz, Sentinel Design"I'm not stupid, I'm from Sweden" - Unknown
One thing I forgot. How the heck do you scale the fonts?
When I tested my font drawing function yesterday I couldn''t scale it by one pixel without it looking skewed.
But I guess you can''t do much about that when using DirectDraw since the scaling functions are built in, right?

============================
Daniel Netz, Sentinel Design
"I'm not stupid, I'm from Sweden" - Unknown
============================Daniel Netz, Sentinel Design"I'm not stupid, I'm from Sweden" - Unknown
You say you don''t use the whole ASCII character set. That is fine and normal. You can still use the character value to index into a list though. Just build an array of 128 entries and then only fill in the characters you are using. As you''re using 87 characters you''re only wasting 41 entries, which is certainly affordable in regards to the increase of speed and ease of use, as you don''t need to make your own stringformat.

DDraw automatically scales bitmaps when the destination and source rectangles in Blt() are of different sizes. However, DDraw can only do point filtering, as opposed to bilinear filtering, which will make the font look extremely bad for scaling with fractional values.
Advertisement
Actually I''ve created my own character list, an array of 87 characters I use, but maybe it would be faster to do as you said though, since you don''t have to loop through the character list to get the character.

But I think creating a list of character list values and privately store it in the font engine class would make it faster, since you tend to display fonts every loop and draw them to the target surface, or as I said in my previous postings, drawing the font string to a new surface and blit that one to save some time.

Thanks for your help though, I was just afraid my structure would be a bad structure, but it seems like it''s what most people use.

============================
Daniel Netz, Sentinel Design
"I'm not stupid, I'm from Sweden" - Unknown
============================Daniel Netz, Sentinel Design"I'm not stupid, I'm from Sweden" - Unknown
I do not use bitmaps for my fonts. I use somewhat of a compiled font that only holds the pixels that are drawn. The problem with using the bitmap and rect is that there is a lot of data that is not needed; aka the pixels that are masked out of the font. What I do is something along these lines:

#define NUMBER_OF_FONTS 128

struct BIT_XY {
char x, y;
};

struct FONT_STRUCT {
short n_size;
BIT_XY* data;
FONT_STRUCT() : size(0), data(NULL) // c++ only???
{}
~FONT_STRUCT()
{
if (data) delete[] data;
}
};

struct FONTGROUP_STRUCT {
FONT_STRUCT font[NUMBER_OF_FONTS];
};

Each FONT_STRUCT holds a n_size (short) and a data pointer (BIT_XY*). When my program creates the FONTGROUP_STRUCT, is reads a file with NUMBER_OF_FONTS fonts in it. Then for each font it reads the n_size, allocate data (new BIT_XY[n_size] (if n_size > 0)) then reads in n_size BIT_XY structs into the data.

Then when my program wants to write a char, I call:
(psuedo)
PutChar(x_offset,y_offset)
for i = 0 to n_size
placebit(x_offset + font.data.x,y_offset +
font.data.y)<br> next i<br><br>Thus drawing the only bits needed, with no mask required, and some memory saved. It is a win - win situation.<br><br>This code is a rough sketch of the idea, but you get it. If you would like a code example in DirectDraw (640x400x8) in C++, email me (look at my profile) </i>
Spiff, I don''t scale the fonts. If I need a new size, I have to use a "different" font. So I guess they are not really fonts at all. Why do I do it this way? Because I generally don''t need more than three or four different type faces/sizes for the whole game.

I also use an array to store the characters so I can map the character code directly to the character in the array. Using a list will be much slower, especially if you do lots of text, and your average character lookup ends up in the middle. You could adjust this somewhat by putting most often used characters at the front of the list, but it still wouldn''t be as fast as using an array. Like Spellbound said, I think the speed vs size tradeoff for wasting unused character slots definitely comes out on the speed side as the winner.

Mark Fassett
Laughing Dragon Entertainment
http://www.laughing-dragon.com

Mark Fassett

Laughing Dragon Games

http://www.laughing-dragon.com

If you do need to scale the fonts, make sure the stored font bmp is the largest size you''ll use in the game. Scaling down looks much nicer than scaling up. You probably already knew that, though Of course, that would waste some memory, but that''s less memory than loading in several different bmps for the different sizes.

Good Luck!


- null_pointer

This topic is closed to new replies.

Advertisement