float glutStrokeWidthf (void *font, int character);
float glutStrokeLengthf (void *font, const unsigned char *string);
Text rendering issues can become very complex, especially with international character support. It is certainly beyond the scope of OpenGLUT to provide all of these features, but it is reasonable to support text rendering in such a way that the user can manage the high-level issues within the OpenGLUT API.
There are two related issues with extensibility. First, additional fonts will normally come from through the native OS. This is important to support, particulary for access to non-ASCII fonts. How are platform-dependent fonts accessed in a platform independent way?
Second, if custom fonts are used, they need to be included with the application, which means defining a portable font file format. It would be possible to include the FreeType library, and directly support TrueType fonts, but OpenGLUT wants to minimize library dependencies. However, it is reasonable to have an external utility that generates OpenGLUT font files via TruType.
FAMILY_NAME[-ATTRIBUTES] SIZE
FAMILY_NAME is the common font name like "Courier" or "Helvetica", or may be a generic name such as "Serif" or "SansSerif". ATTRIBUTES is a concatenated collection of font specifications, from the following list (which may already be excessive): Roman, Italic, Oblique, Condensed, Narrow, Wide, DoubleWide, Light, Medium, Bold, Demi, Fixed, Proportional, Underline, StrikeOut, SmallCaps SIZE is the "Point Size" of the font. Pixel size may be more useful, but point size is far more conventional.
Selection by pixel size can be derived from the screen resolution: PointSize = 2.845 * PixelSize * glutGet(GLUT_SCREEN_HEIGHT_MM) / glutGet(GLUT_SCREEN_HEIGHT) QUESTION: Should there be a method of pixel-size selection, or is the above method sufficient? Maybe include a glutSetOption()?
It is also reasonable to simultaneously support alternate font specification formats, such as the following CSS specification example: { font: 800 14pt/16.5pt "Li Sung", serif }
Some common fonts are guaranteed to be available, provided either by built-in system fonts, or by font data compiled into the GLUT library. This is the list of standard, guaranteed fonts, and is the same as the 14 standard PDF fonts:
Courier Courier-Bold Courier-Oblique Courier-BoldOblique
Helvetica Helvetica-Bold Helvetica-Oblique Helvetica-BoldOblique
Times-Roman Times-Bold Times-Italic Times-BoldItalic
Symbol ZapfDingbats
The following standard font Point sizes (based on HTML standards) are required to be available: 8, 10, 12, 14, 18, 24 and 36.The data for all of the above fonts can fit in <400K with compression. This is small enough that compiling the entire set of standard fonts into the OpenGLUT library is not unreasonable.
GLboolean glutUseFontBitmaps(
char *name, int first, int count, int listbase
);
In addition to providing cross-platform support to exsiting functions, this can be used as the core function for extracting OpenGLUT bitmap fonts from the operating system fonts, in a manner similar to GLUT's capturexfont
and FreeGLUT's getfont
, but in an OS indepenent fashion.
The following function extracts bitmap font data from the native OS, and makes it available for use in the same manner as a regular GLUT font:
int glutCreateBitmapFont(char *name);
Parameters
Returns an integer font ID usable in glutBitmapCharacter(), etc., or zero if unsuccessful.
void glutDestroyBitmapFont(int font_id);
Parameters
Note that these functions also suggests the use of integer identifiers instead of data pointers to represent OpenGLUT fonts. This change is proposed for existing font functions in the GLUT API as well:
void glutBitmapCharacter( int font_id, int character );
int glutBitmapWidth( int font_id, int character );
void glutStrokeCharacter( int font_id, int character );
int glutStrokeWidth( int font_id, int character );
int glutBitmapLength( int font_id, const unsigned char *string );
int glutStrokeLength( int font_id, const unsigned char *string );
therefore, OpenGLUT should be able to use lists internally, initially set to start at some high value, such as PI/4 * MAXVAL. Additionally, on can redirect the OpenGLUT list base using glutSetOption(). It would also be possible for glutSetOption to disable OpenGLUT list usage. But, this would prevent access to the OS-dependet OpenGL font functions. In this case, one would be restricted to OpenGLUT built-in fonts, or be required to create OpenGLUT fonts at program initialization.
GLboolean glutUseFontOutlines(
char *name, int first, int count, int listbase
);
int glutCreateOutlineFont( char *name );
int glutDestroyOutlineFont( int font_id );
GLboolean glutUseFontStrokes(
char *name, int first, int count, int listbase
);
int glutCreateStrokeFont( char *name );
int glutDestroyStrokeFont( int font_id );
glutBitmapString attempts to handle newline characters to support rendering of multiple lines of code. This approach does not work if one intends to render text with more than one font, which includes changes in attributes such as bold or italics. Switching fonts also results in additional and unnecessary state changes. This can be alleviated by defining functions for entering and leaving a text-rendering state.
It is also useful to include an OpenGLUT API call that is used instead of glRasterPos*() functions. This has a few benefits, including the ability to support a "newline" control based on an initial text position, better handlingh of texture-based fonts which do not use the rester coordinates, and the ability to track the raster position without using glGet*().
Without proceeeding to a detailed API definition, this section ends (for now) by presenting an example of text rendering that demonstrates the general intent of String Rendering:
Times=glutCreateFont( "Times 12" );
TimesBold=glutCreateFont( "Times-Bold 12" );
TimesItalic=glutCreateFont( "Times-Italic 12" );
...
glutBeginText2i( 100, 10 );
glutBitmapString( Times, "Hey, I can draw some " );
glutBitmapString( TimesBold, "bold letters" );
glutBitmapString( Times, " with this " );
glutBitmapString( TimesItalic, "cool new" );
glutBitmapString( Times, " OpenGLUT API, and still\n" );
glutBitmapString( Times, " use a newline with mixed fonts." );
glutEndText( );
Bitmap font data will include with each character, all parameters to the glBitmap function, including both xmove and ymove. This allows for "control codes" like backspace, and allows for nonstandard font orientations (i.e. international character support).
It would be convenient if bitmap characters were set onto a 2-dimensional grid so that one could just view the image to see the font set. This would result in disjoint data for each character, so it would probably need to be shuffled during I/O. However, such a layout would not be a problem for texture-based fotns.