FW_BOLD, // Font Weight
Italic, Underline and Strikeout can be either TRUE or FALSE. Basically if underline is TRUE, the font will be underlined. If it's FALSE it wont be. Pretty simple :)
FALSE, // Italic
FALSE, // Underline
FALSE, // Strikeout
Character set Identifier describes the type of Character set you wish to use. There are too many types to explain. CHINESEBIG5_CHARSET, GREEK_CHARSET, RUSSIAN_CHARSET, DEFAULT_CHARSET, etc. ANSI is the one I use, although DEFAULT would probably work just as well.
If you're interested in using a font such as Webdings or Wingdings, you need to use SYMBOL_CHARSET instead of ANSI_CHARSET.
ANSI_CHARSET, // Character Set Identifier
Output Precision is very important. It tells Windows what type of character set to use if there is more than one type available. OUT_TT_PRECIS tells Windows that if there is more than one type of font to choose from with the same name, select the TRUETYPE version of the font. Truetype fonts always look better, especially when you make them large. You can also use OUT_TT_ONLY_PRECIS, which ALWAYS trys to use a TRUETYPE Font.
OUT_TT_PRECIS, // Output Precision
Clipping Precision is the type of clipping to do on the font if it goes outside the clipping region. Not much to say about this, just leave it set to default.
CLIP_DEFAULT_PRECIS, // Clipping Precision
Output Quality is very important.you can have PROOF, DRAFT, NONANTIALIASED, DEFAULT or ANTIALIASED. We all know that ANTIALIASED fonts look good :) Antialiasing a font is the same effect you get when you turn on font smoothing in Windows. It makes everything look less jagged.
ANTIALIASED_QUALITY, // Output Quality
Next we have the Family and Pitch settings. For pitch you can have DEFAULT_PITCH, FIXED_PITCH and VARIABLE_PITCH, and for family you can have FF_DECORATIVE, FF_MODERN, FF_ROMAN, FF_SCRIPT, FF_SWISS, FF_DONTCARE. Play around with them to find out what they do. I just set them both to default.
FF_DONTCARE|DEFAULT_PITCH, // Family And Pitch
Finally… We have the actual name of the font. Boot up Microsoft Word or some other text editor. Click on the font drop down menu, and find a font you like. To use the font, replace 'Comic Sans MS' with the name of the font you'd rather use.
"Comic Sans MS"); // Font Name
Now we select the font by relating it to our DC.
SelectObject(hDC, font); // Selects The Font We Created
Now for the new code. We build our Outline font using a new command wglUseFontOutlines. We select our DC, the starting character, the number of characters to create and the 'base' display list value. All very similar to the way we built our Bitmap font.
wglUseFontOutlines(hDC, // Select The Current DC
0, // Starting Character
255, // Number Of Display Lists To Build
base, // Starting Display Lists
That's not all however. We then set the deviation level. The closer to 0.0f, the smooth the font will look. After we set the deviation, we get to set the font thickness. This describes how thick the font is on the Z axis. 0.0f will produce a flat 2D looking font and 1.0f will produce a font with some depth.
The parameter WGL_FONT_POLYGONS tells OpenGL to create a solid font using polygons. If we use WGL_FONT_LINES instead, the font will be wireframe (made of lines). It's also important to note that if you use GL_FONT_LINES, normals will not be generated so lighting will not work properly.
The last parameter gmf points to the address buffer for the display list data.
0.0f, // Deviation From The True Outlines
0.2f, // Font Thickness In The Z Direction
WGL_FONT_POLYGONS, // Use Polygons, Not Lines
gmf); // Address Of Buffer To Recieve Data
}
The following code is pretty simple. It deletes the 256 display lists from memory starting at the first list specified by base. I'm not sure if Windows would do this for you, but it's better to be safe than sorry :)
GLvoid KillFont(GLvoid) // Delete The Font
{
glDeleteLists(base, 256); // Delete All 256 Characters
}
Now for my handy dandy GL text routine. You call this section of code with the command glPrint("message goes here"). Exactly the same way you drew Bitmap fonts to the screen in lesson 13. The text is stored in the char string fmt.
GLvoid glPrint(const char *fmt, …) // Custom GL "Print" Routine
{
The first line below sets up a variable called length. We'll use this variable to find out how our string of text is. The second line creates storage space for a 256 character string. text is the string we will end up printing to the screen. The third line creates a pointer that points to the list of arguments we pass along with the string. If we send any variables along with the text, this pointer will point to them.
float length=0; // Used To Find The Length Of The Text
char text[256]; // Holds Our String
va_list ap; // Pointer To List Of Arguments
The next two lines of code check to see if there's anything to display? If there's no text, fmt will equal nothing (NULL), and nothing will be drawn to the screen.
if (fmt == NULL) // If There's No Text
return; // Do Nothing
The following three lines of code convert any symbols in the text to the actual numbers the symbols represent. The final text and any converted symbols are then stored in the character string called "text". I'll explain symbols in more detail down below.
va_start(ap, fmt); // Parses The String For Variables
vsprintf(text, fmt, ap); // And Converts Symbols To Actual Numbers
va_end(ap); // Results Are Stored In Text
Thanks to Jim Williams for suggesting the code below. I was centering the text manually. His method works alot better :)
We start off by making a loop that goes through all the text character by character. strlen(text) gives us the length of our text. After we've set up the loop, we will increase the value of length by the width of each character. When we are done the value stored in length will be the width of our entire string. So if we were printing "hello" and by some fluke each character was exactly 10 units wide, we'd increase the value of length by the width of the first letter 10. Then we'd check the width of the second letter. The width would also be 10, so length would become 10+10 (20). By the time we were done checking all 5 letters length would equal 50 (5*10).
The code that gives us the width of each character is gmf[text[loop]].gmfCellIncX. remember that gmf stores information out each display list. If loop is equal to 0 text[loop] will be the first character in our string. If loop is equal to 1 text[loop] will be the second character in our string. gmfCellIncX tells us how wide the selected character is. gmfCellIncX is actually the distance that our display moves to the right after the character has been drawn so that each character isn't drawn on top of eachother. Just so happens that distance is our width :) You can also find out the character height with the command gmfCellIncY. This might come in handy if you're drawing text vertically on the screen instead of horizontally.
for (unsigned int loop=0; loop<(strlen(text)); loop++) // Loop To Find Text Length