1 <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
4 <meta http-equiv="Content-Type"
5 content="text/html; charset=iso-8859-1">
7 content="David Turner">
8 <title>FreeType 2 Internals - I/O Frames</title>
18 FreeType 2.0 I/O Frames
22 © 2000 David Turner
23 (<a href="mailto:david@freetype.org">david@freetype.org</a>)<br>
24 © 2000 The FreeType Development Team
25 (<a href="http://www.freetype.org">www.freetype.org</a>)
38 <p>This document explains the concept of I/O <b>frames</b> as used in the
39 FreeType 2 source code. It also enumerates the various functions and
40 macros that can be used to read them.</p>
42 <p>It is targeted to FreeType hackers, or more simply to developers who
43 would like a better understanding of the library's source code.</p>
51 <p>Simply speaking, a frame is an array of bytes in a font file that is
52 `preloaded' into memory in order to be rapidly parsed. Frames are useful
53 to ensure that every `load' is checked against end-of-file overruns, and
54 provides nice functions to extract data in a variety of distinct
57 <p>But an example is certainly more meaningful than anything else. The
62 error = read_short( stream, &str.value1 );
65 error = read_ulong( stream, &str.value2 );
68 error = read_ulong( stream, &str.value3 );
69 if ( error ) goto ...</pre>
72 <p>can easily be replaced with</p>
76 error = FT_Access_Frame( stream, 2 + 4 + 4 );
79 str.value1 = FT_Get_Short( stream );
80 str.value2 = FT_Get_ULong( stream );
81 str.value3 = FT_Get_ULong( stream );
83 FT_Forget_Frame( stream );</pre>
86 <p>Here, the call to <code>FT_Access_Frame()</code> will</p>
90 <p>Ensure that there are at least 2+4+4=10 bytes left in the
94 <p>`Preload' (for disk-based streams) 10 bytes from the current
98 <p>Set the frame `cursor' to the first byte in the frame.</p>
102 <p>Each <code>FT_Get_Short()</code> or <code>FT_Get_ULong()</code> call
103 will read a big-endian integer from the stream (2 bytes for
104 <code>FT_Get_Short()</code>, 4 bytes for <code>FT_Get_ULong</code>)
105 and advance the frame cursor accordingly.</p>
107 <p><code>FT_Forget_Frame()</code> `releases' the frame from memory.</p>
109 <p>There are several advantages to using frames:</p>
113 <p>Single-check when loading tables.</p>
116 <p><em>Making code clearer</em> by providing simple parsing functions
117 <em>while keeping code safe</em> from file over-runs and invalid
125 II. Accessing and reading a frame with macros
128 <p>By convention in the FreeType source code, macros are able to use two
129 implicit variables named <var>error</var> and <var>stream</var>. This is
130 useful because these two variables are extremely often used in the
131 library, and doing this only reduces our typing requirements and make the
132 source code much clearer.</p>
134 <p>Note that <var>error</var> must be a local variable of type
135 <code>FT_Error</code>, while <var>stream</var> must be a local variable or
136 argument of type <code>FT_Stream</code>.</p>
138 <p>The macro used to access a frame is <font
139 color="purple"><code><b>ACCESS_Frame(_size_)</b></code></font>, it will
144 ( error = FT_Access_Frame( stream, _size_ ) )
148 <p>Similarly, the macro <font
149 color="purple"><b><code>FORGET_Frame()</code></b></font> translates to</p>
153 FT_Forget_Frame( stream )</pre>
156 <p>Extracting integers can be performed with the <code>GET_xxx()</code>
174 <font color="purple"><code><b>GET_Byte()</b></code></font>
177 <font color="blue"><code>FT_Get_Byte(stream)</code></font>
180 <p>Reads an 8-bit unsigned byte.</p>
185 <font color="purple"><code><b>GET_Char()</b></code></font>
188 <font color="blue"><code>(FT_Char)<br>
189 FT_Get_Byte(stream)</code></font>
192 <p>Reads an 8-bit <em>signed</em> byte.</p>
197 <font color="purple"><code><b>GET_Short()</b></code></font>
200 <font color="blue"><code>FT_Get_Short(stream)</code></font>
203 Reads a 16-bit signed big-endian integer.
208 <font color="purple"><code><b>GET_UShort()</b></code></font>
211 <font color="blue"><code>(FT_UShort)<br>
212 FT_Get_Short(stream)</code></font>
215 Reads a 16-bit unsigned big-endian integer.
220 <font color="purple"><code><b>GET_Offset()</b></code></font>
223 <font color="blue"><code>FT_Get_Offset(stream)</code></font>
226 Reads a 24-bit signed big-endian integer.
231 <font color="purple"><code><b>GET_UOffset()</b></code></font>
234 <font color="blue"><code>(FT_UOffset)<br>
235 FT_Get_Offset(stream)</code></font>
238 Reads a 24-bit unsigned big-endian integer.
243 <font color="purple"><code><b>GET_Long()</b></code></font>
246 <font color="blue"><code>FT_Get_Long(stream)</code></font>
249 Reads a 32-bit signed big-endian integer.
254 <font color="purple"><code><b>GET_ULong()</b></code></font>
257 <font color="blue"><code>(FT_ULong)<br>
258 FT_Get_Long(stream)</code></font>
261 Reads a 32-bit unsigned big-endian integer.
266 <p>(Note that an <b>Offset</b> is an integer stored with 3 bytes on
269 <p>All this means that the following code</p>
273 error = FT_Access_Frame( stream, 2 + 4 + 4 );
274 if ( error ) goto ...
276 str.value1 = FT_Get_Short( stream );
277 str.value2 = FT_Get_ULong( stream );
278 str.value3 = FT_Get_ULong( stream );
280 FT_Forget_Frame( stream );</pre>
283 <p>can be simplified with macros:</p>
287 if ( ACCESS_Frame( 2 +4 + 4 ) ) goto ...
289 str.value1 = GET_Short();
290 str.value2 = GET_ULong();
291 str.value3 = GET_ULong();
293 FORGET_Frame();</pre>
296 <p>Which is clearer. Notice that <var>error</var> and <var>stream</var>
297 must be defined locally though for this code to work!</p>
305 <p>It is sometimes useful to read small integers from a font file without
306 using a frame. Some functions have been introduced in FreeType 2 to
307 do just that, and they are of the form <font
308 color="blue"><code>FT_Read_xxxx</code></font>.</p>
310 <p>For example, <font color="blue"><code>FT_Read_Short(stream,
311 &error)</code></font> reads and returns a 2-byte big-endian integer from a
312 <var>stream</var>, and places an error code in the <var>error</var>
315 <p>Thus, reading a single big-endian integer is shorter than using a frame
318 <p>Note that there are also macros <font
319 color="purple"><code>READ_xxx()</code></font> which translate to</p>
323 FT_Read_xxx( stream, &error ), error != FT_Err_Ok</pre>
326 <p>and can be used as in</p>
330 if ( READ_UShort( variable1 ) ||
331 READ_ULong ( variable2 ) )
335 <p>if <var>error</var> and <var>stream</var> are already defined