OpenGLUT Documentation
Introduction | Documentation | Examples | Proposals | Authors | Copying | Todo | Bugs | Links

OpenGLUT Text Rendering API Proposal

Note:
This is a proposal is a work-in-progress, for the purpose of discussion development. This API is not currently implemented in OpenGLUT.

There is an unreleased GLUT version 3.8 (included in the SGI Linux distribution) which apparently is a small change that provides glutStrokeWidthf and glutStrokeLengthf to return float values, and deprecates the existing integer function. The new functions are not required in OpenGLUT, as OpenGLUT has changed glutStrokeWidth() and glutStrokeLength() to return floating point values. PyOpenGL has man pages for these GLUT 3.8 functions:
    float glutStrokeWidthf (void *font, int character);
    float glutStrokeLengthf (void *font, const unsigned char *string);
    

Motivation

There are several aspects of text handling that are lacking in the GLUT API. The most important areas for improvement are font extensibility and efficient rendering of character strings. Additional area for improvement include text layout issues, texture-based font rendering, and solid (space-filling) fonts.

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.

Font Extensibility

Fonts have always been extensible in the original X11 implementation, where font data is passed as a pointer, and may represent font data generated by the user. However, this was never developed much due to the desire of avoiding data structures in the overall GLUT design concept. Win32 GLUT never supported user font data pointers.

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.

Specifying a System Font

Font specifications are passed as a single string, generally following the Postscript naming scheme.

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.

API function

When considering access to System fonts, an obvious function for the OpenGLUT API is an OS-independent version of the existing OS-dependent bitmap font functions: wglUseFontBitmaps, glXUseXFont, aglUseFont.

    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 );
    

Use of glLists to render fonts.

A question for discussion: OpenGLUT should be able to extract list-embedded fonts in order to save and include unusual fonts with an OpenGLUT application. However, it seems pointless to de-listify fonts. Furthermore, one must at least create temporary lists in order to use the well-defined OS-dependent font functions.

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.

Support for Outline Fonts.

Win32 also has a built-in function for solid space-filling fonts, wglUseFontOutlines. This could be included and emulated for X11/Mac. In addition, a Stroke font version could be included:

    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 );
    

String Rendering

Rendering a string of characters is inefficient when rendered one character at a time, primarily due to OpenGL state changes. OpenGLUT currently implements glutBitmapString, but it only supports 8-bit character sets. See the Unicode proposal for the definition of a Unicode compatible version.

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( );
    

Font Data and File Formats

Just getting started here. In general, data should be stored in a format consistent with the OpenGL functions used to render the data. It should have a human-readable header, with binary data (meaning no XML).

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.



OpenGLUT Development @ Sourceforge
Homepage | Summary | Files | CVS | Forums | Lists | Bugs | RFE

Generated on Sat Feb 5 01:47:28 2005 for OpenGLUT by doxygen 1.3.9.1
The OpenGLUT project is hosted by sourceforge.net.