Edit

kc3-lang/freetype/docs/design/io-frames.html

Branch :

  • Show log

    Commit

  • Author : David Turner
    Date : 2000-05-16 23:44:38
    Hash : e49ab25c
    Message : formatting - removed trailing spaces

  • docs/design/io-frames.html
  • <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
    <html>
    <head>
       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
       <meta name="Author" content="David Turner">
       <meta name="GENERATOR" content="Mozilla/4.5 [fr] (Win98; I) [Netscape]">
       <title>FreeType 2 Internals - I/O Frames</title>
    </head>
    <body>
    
    <body text="#000000"
          bgcolor="#FFFFFF"
          link="#0000EF"
          vlink="#51188E"
          alink="#FF0000">
    
    <center>
    <h1>
    FreeType 2.0 I/O Frames</h1></center>
    
    <center>
    <h3>
    &copy; 2000 David Turner (<a href="mailto:david@freetype.org">david@freetype.org</a>)<br>
    &copy; 2000 The FreeType Development Team (<a href="http://www.freetype.org">www.freetype.org</a>)</h3></center>
    
    <p><br>
    <hr WIDTH="100%">
    <br>&nbsp;
    <h2>Introduction:</h2>
    <ul>
      This document explains the concept of i/o <b>frames</b> as used in the
      FreeType 2 source code. It also enumerates the various functions and macros
      that can be used to read them.
      <p>
      It is targetted to FreeType hackers, or more simply to developers who would
      like a better understanding of the library's source code.
    </ul>
    
    <p><hr><p>
    
    <h2>I. What frames are:</h2>
    <ul>
      Simply 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.
      <p>
      But an example is certainly more meaningful than anything else.
      The following code:
      <p>
         <font color="blue"><pre>
         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 ...
         </pre></font>
      can easily be replaced with:
      <p>
         <font color="blue"><pre>
         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);
         </pre></font>
      <p>
      Here, the call to <tt>FT_Access_Frame</tt> will:<p>
      <ul>
    	  <li>Ensure that there are at least 2+4+4=10 bytes left in the stream.
    	  <li>"Preload" (for disk-based streams) 10 bytes from the current
              stream position.
    	  <li>Set the frame "cursor" to the first byte in the frame;
      </ul>
      <p>
      Each <tt>FT_Get_Short</tt> or <tt>FT_Get_ULong</tt> call will read a
      big-endian integer from the stream (2 bytes for <tt>FT_Get_Short</tt>,
      4 bytes for <tt>FT_Get_ULong</tt>) and advance the frame cursor accordingly.
      <p>
      <tt>FT_Forget_Frame</tt> "releases" the frame from memory
      <p>
      There are several advantages to using frames :<p>
      <ul>
    	  <li>single-check when loading tables
    	  <li><em>making code clearer</em> by providing simple parsing functions
                 <em>while keeping code safe</em> from file over-runs and invalid
                 offsets.
      </ul>
      <p>
    </ul>
    
    <p><hr><p>
    
    <h2>II. Accessing and reading a frame with macros:</h2>
    <ul>
    	By convention in the FreeType source code, macros are able to use two implicit
    	variables named "<tt>error</tt>" and "<tt>stream</tt>". This is useful because
    	these two variables are extremely used in the library, and doing this only
    	reduces our typing requirements and make the source code much clearer.
    	<p>
    	Note that <tt>error</tt> must be a local variable of type <tt>FT_Error</tt>,<br>
    	while <tt>stream</tt> must be a local variable or argument of type <tt>FT_Stream</tt>;
    	<p>
    	The macro used to access a frame is
        <font color="purple"><tt><b>ACCESS_Frame(_size_)</b></tt></font>, it will
    	translate to:<p>
    	<ul><font color="blue">
    		<tt>(error=FT_Access_Frame(stream,_size_)) != FT_Err_Ok</tt>.
    	</font></ul>
    	<p>
    	Similarly, the macro
        <font color="purple"><b><tt>FORGET_Frame()</tt></b></font>
        translates to:<p>
    	<ul><font color="blue">
    		<tt>FT_Forget_Frame(stream)</tt>
    	</font></ul>
    	<p>
    	Extracting integers can be performed with the <tt>GET_xxx</tt> macros, like:<p>
    	<ul>
    		<table>
    			<tr>
                    <td><b>Macro name</b>    <td>Translation  <td>Description
    
                <tr><td><font color="purple"><tt><b>
                    GET_Byte()
                    </b></tt></font><td><font color="blue"><tt>
                    (FT_Get_Byte(stream))
                    </tt></font><td>
                    reads an 8-bit unsigned byte
    
                <tr><td><font color="purple"><tt><b>
                    GET_Char()
                    </b></tt></font><td><font color="blue"><tt>
                    ((FT_Char)FT_Get_Byte(stream))
                    </tt></font><td>
                    reads an 8-bit <em>signed</em> byte
    
                <tr><td><font color="purple"><tt><b>
                    GET_Short()
                    </b></tt></font><td><font color="blue"><tt>
                    (FT_Get_Short(stream))
                    </tt></font><td>
                    reads a 16-bit signed big-endian integer
    
                <tr><td><font color="purple"><tt><b>
                    GET_UShort()
                    </b></tt></font><td><font color="blue"><tt>
                    ((FT_UShort)FT_Get_Short(stream))
                    </tt></font><td>
                    reads a 16-bit unsigned big-endian integer
    
                <tr><td><font color="purple"><tt><b>
                    GET_Offset()
                    </b></tt></font><td><font color="blue"><tt>
                    (FT_Get_Offset(stream))
                    </tt></font><td>
                    reads a 24-bit signed big-endian integer
    
                <tr><td><font color="purple"><tt><b>
                    GET_UOffset()
                    </b></tt></font><td><font color="blue"><tt>
                    ((FT_UOffset)FT_Get_Offset(stream))
                    </tt></font><td>
                    reads a 24-bit unsigned big-endian integer
    
                <tr><td><font color="purple"><tt><b>
                    GET_Long()
                    </b></tt></font><td><font color="blue"><tt>
                    (FT_Get_Long(stream))
                    </tt></font><td>
                    reads a 32-bit signed big-endian integer
    
                <tr><td><font color="purple"><tt><b>
                    GET_ULong()
                    </b></tt></font><td><font color="blue"><tt>
                    ((FT_ULong)FT_Get_Long(stream))
                    </tt></font><td>
                    reads a 32-bit unsigned big-endian integer
    
    		</table>
    	</ul>
    	<p>
    	(Note that an <b>Offset</b> is an integer stored with 3 bytes on the file).
        <p>
    	All this means that the following code:<p>
    	<font color="blue"><pre>
          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);<br>
    	</pre></font>
    	<p>
    	Can be replaced with macros by:<p>
    	<font color="blue"><pre>
          if ( ACCESS_Frame( 2+4+4 ) ) goto ...
    
          str.value1 = GET_Short();
          str.value2 = GET_ULong();
          str.value3 = GET_ULong();
    
          FORGET_Frame();
    	</pre></font>
    	<p>
    	Which is clearer. Notice that <b>error</b> and <b>stream</b> must be defined
    	locally though for this code to work.. !!
    </ul>
    
    <p><hr><p>
    
    <h2>III. Alternatives:</h2>
    <ul>
      It 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 <font color="blue"><tt>FT_Read_xxxx</tt></font>.
      <p>
      For example,
      <font color="blue"><tt>FT_Read_Short( stream, &error )</tt></font> reads and
      returns a 2-byte big-endian integer from a <tt>stream</tt>, and place an
      error code in the <tt>error</tt> variable.
      <p>
      Thus, reading a single big-endian integer is shorter than using a frame
      for it.
      <p>
      Note that there is also the macros
      <font color="purple"><tt>READ_xxx()</tt></font> which translate to:<p>
      <font color="blue"><pre>
        <tt>( FT_Read_xxx(stream,&error), error != FT_Err_Ok )
      </pre></font>
      <p>
      and can be used as in:<p>
      <font color="blue"><pre>
        if ( READ_UShort(variable1) || READ_ULong (variable2) ) goto Fail;
      </pre></font>
      <p>
      when <b>error</b> and <b>stream</b> are already defined locally..
    </ul>