IntroductionThis document explains the concept of I/O frames as used in the FreeType 2 source code. It also enumerates the various functions and macros that can be used to read them. It is targeted to FreeType hackers, or more simply to developers who would like a better understanding of the library's source code. I. What frames areSimply speaking, a frame is an array of bytes in a font file that is `preloaded' into memory in order to be rapidly parsed. Frames are useful to ensure that every `load' is checked against end-of-file overruns, and provides nice functions to extract data in a variety of distinct formats. But an example is certainly more meaningful than anything else. The following code error = read_short( stream, &str.value1 ); if ( error ) goto ... error = read_ulong( stream, &str.value2 ); if ( error ) goto ... error = read_ulong( stream, &str.value3 ); if ( error ) goto ... can easily be replaced with error = FT_Access_Frame( stream, 2 + 4 + 4 ); if ( error ) goto ... str.value1 = FT_Get_Short( stream ); str.value2 = FT_Get_ULong( stream ); str.value3 = FT_Get_ULong( stream ); FT_Forget_Frame( stream ); Here, the call to
Each
There are several advantages to using frames:
II. Accessing and reading a frame with macrosBy convention in the FreeType source code, macros are able to use two implicit variables named error and stream. This is useful because these two variables are extremely often used in the library, and doing this only reduces our typing requirements and make the source code much clearer. Note that error must be a local variable of type
The macro used to access a frame is ( error = FT_Access_Frame( stream, _size_ ) ) != FT_Err_Ok Similarly, the macro FT_Forget_Frame( stream ) Extracting integers can be performed with the
(Note that an Offset is an integer stored with 3 bytes on the file.) All this means that the following code error = FT_Access_Frame( stream, 2 + 4 + 4 ); if ( error ) goto ... str.value1 = FT_Get_Short( stream ); str.value2 = FT_Get_ULong( stream ); str.value3 = FT_Get_ULong( stream ); FT_Forget_Frame( stream ); can be simplified with macros: if ( ACCESS_Frame( 2 +4 + 4 ) ) goto ... str.value1 = GET_Short(); str.value2 = GET_ULong(); str.value3 = GET_ULong(); FORGET_Frame(); Which is clearer. Notice that error and stream must be defined locally though for this code to work! III. AlternativesIt is sometimes useful to read small integers from a font file without
using a frame. Some functions have been introduced in FreeType 2 to
do just that, and they are of the form For example, Thus, reading a single big-endian integer is shorter than using a frame for it. Note that there are also macros FT_Read_xxx( stream, &error ), error != FT_Err_Ok and can be used as in if ( READ_UShort( variable1 ) || READ_ULong ( variable2 ) ) goto Fail; if error and stream are already defined locally. |